Gildas преди 7 години
родител
ревизия
dcc8469bad
променени са 1 файла, в които са добавени 15 реда и са изтрити 7 реда
  1. 15 7
      lib/single-file/css-rules-matcher.js

+ 15 - 7
lib/single-file/css-rules-matcher.js

@@ -30,14 +30,15 @@ this.RulesMatcher = this.RulesMatcher || (() => {
 			this.doc = doc;
 			this.mediaAllInfo = createMediaInfo(MEDIA_ALL);
 			const matchedElementsCache = new Map();
+			const unmatchedSelectorsCache = new Set();
 			doc.querySelectorAll("style").forEach((styleElement, styleIndex) => {
 				if (styleElement.sheet) {
 					if (styleElement.media && styleElement.media != MEDIA_ALL) {
 						const mediaInfo = createMediaInfo(styleElement.media);
 						this.mediaAllInfo.medias.set(styleElement.media, mediaInfo);
-						getMatchedElementsRules(doc, styleElement.sheet.cssRules, mediaInfo, styleIndex, matchedElementsCache);
+						getMatchedElementsRules(doc, styleElement.sheet.cssRules, mediaInfo, styleIndex, matchedElementsCache, unmatchedSelectorsCache);
 					} else {
-						getMatchedElementsRules(doc, styleElement.sheet.cssRules, this.mediaAllInfo, styleIndex, matchedElementsCache);
+						getMatchedElementsRules(doc, styleElement.sheet.cssRules, this.mediaAllInfo, styleIndex, matchedElementsCache, unmatchedSelectorsCache);
 					}
 				}
 			});
@@ -60,18 +61,18 @@ this.RulesMatcher = this.RulesMatcher || (() => {
 		}
 	};
 
-	function getMatchedElementsRules(doc, cssRules, mediaInfo, sheetIndex, matchedElementsCache) {
+	function getMatchedElementsRules(doc, cssRules, mediaInfo, sheetIndex, matchedElementsCache, unmatchedSelectorsCache) {
 		Array.from(cssRules).forEach((cssRule, ruleIndex) => {
 			if (cssRule.type == CSSRule.MEDIA_RULE) {
 				const ruleMediaInfo = createMediaInfo(cssRule.media);
 				mediaInfo.medias.set(cssRule.media, ruleMediaInfo);
-				getMatchedElementsRules(doc, cssRule.cssRules, ruleMediaInfo, sheetIndex, matchedElementsCache);
+				getMatchedElementsRules(doc, cssRule.cssRules, ruleMediaInfo, sheetIndex, matchedElementsCache, unmatchedSelectorsCache);
 			} else if (cssRule.type == CSSRule.STYLE_RULE) {
 				if (cssRule.selectorText) {
 					try {
 						let selectors = cssWhat.parse(cssRule.selectorText);
 						const selectorsText = selectors.map(selector => cssWhat.stringify([selector]));
-						selectors.forEach(selector => getMatchedElementsSelector(doc, cssRule, selector, selectorsText, mediaInfo, ruleIndex, sheetIndex, matchedElementsCache));
+						selectors.forEach(selector => getMatchedElementsSelector(doc, cssRule, selector, selectorsText, mediaInfo, ruleIndex, sheetIndex, matchedElementsCache, unmatchedSelectorsCache));
 					} catch (error) {
 						/* ignored */
 					}
@@ -80,11 +81,18 @@ this.RulesMatcher = this.RulesMatcher || (() => {
 		});
 	}
 
-	function getMatchedElementsSelector(doc, cssRule, selector, selectorsText, mediaInfo, ruleIndex, sheetIndex, matchedElementsCache) {
+	function getMatchedElementsSelector(doc, cssRule, selector, selectorsText, mediaInfo, ruleIndex, sheetIndex, matchedElementsCache, unmatchedSelectorsCache) {
 		const selectorText = cssWhat.stringify([selector]);
 		let matchedElements = matchedElementsCache.get(selectorText);
 		if (!matchedElements) {
-			matchedElements = doc.querySelectorAll(selectorText);
+			if (unmatchedSelectorsCache.has(selectorText)) {
+				matchedElements = [];
+			} else {
+				matchedElements = doc.querySelectorAll(selectorText);
+				if (!matchedElements.length) {
+					unmatchedSelectorsCache.add(selectorText);
+				}
+			}
 			matchedElementsCache.set(selectorText, matchedElements);
 		}
 		if (matchedElements.length) {