From: Jakub Pawlowicz Date: Fri, 30 Dec 2016 21:50:09 +0000 (+0100) Subject: See #829 - some performance tweaks. X-Git-Url: https://git.ndcode.org/public/gitweb.cgi?a=commitdiff_plain;h=19162d72769222f23fb2178ec4a2e6c1a532990b;p=clean-css.git See #829 - some performance tweaks. Why: * Uses flat loops instead of callbacks; * Checks for number of matches before invoking costly calculations. --- diff --git a/lib/optimizer/is-mergeable.js b/lib/optimizer/is-mergeable.js index ba46e236..df9ddd59 100644 --- a/lib/optimizer/is-mergeable.js +++ b/lib/optimizer/is-mergeable.js @@ -22,11 +22,21 @@ var Level = { }; function isMergeable(selector, mergeablePseudoClasses, mergeablePseudoElements) { - return split(selector, Marker.COMMA).every(function (singleSelector) { - return singleSelector.length > 0 && - !isDeepSelector(singleSelector) && - areMergable(singleSelector, extractPseudoFrom(singleSelector), mergeablePseudoClasses, mergeablePseudoElements); - }); + var singleSelectors = split(selector, Marker.COMMA); + var singleSelector; + var i, l; + + for (i = 0, l = singleSelectors.length; i < l; i++) { + singleSelector = singleSelectors[i]; + + if (singleSelector.length === 0 || + isDeepSelector(singleSelector) || + !areMergable(singleSelector, extractPseudoFrom(singleSelector), mergeablePseudoClasses, mergeablePseudoElements)) { + return false; + } + } + + return true; } function isDeepSelector(selector) { @@ -115,47 +125,74 @@ function extractPseudoFrom(selector) { function areMergable(selector, matches, mergeablePseudoClasses, mergeablePseudoElements) { return areAllowed(matches, mergeablePseudoClasses, mergeablePseudoElements) && needArguments(matches) && - !someIncorrectlyChained(selector, matches) && - !someMixed(matches); + (matches.length < 2 || !someIncorrectlyChained(selector, matches)) && + (matches.length < 2 || !someMixed(matches)); } function areAllowed(matches, mergeablePseudoClasses, mergeablePseudoElements) { - return matches.every(function (match) { - var name = match.indexOf(Marker.OPEN_ROUND_BRACKET) > -1 ? + var match; + var name; + var i, l; + + for (i = 0, l = matches.length; i < l; i++) { + match = matches[i]; + name = match.indexOf(Marker.OPEN_ROUND_BRACKET) > -1 ? match.substring(0, match.indexOf(Marker.OPEN_ROUND_BRACKET)) : match; - return mergeablePseudoClasses.indexOf(name) > -1 || mergeablePseudoElements.indexOf(name) > -1; - }); + if (mergeablePseudoClasses.indexOf(name) === -1 && mergeablePseudoElements.indexOf(name) === -1) { + return false; + } + } + + return true; } function needArguments(matches) { - return matches.every(function (match) { - var bracketOpensAt = match.indexOf(Marker.OPEN_ROUND_BRACKET); - var hasArguments = bracketOpensAt > -1; - var name = hasArguments ? + var match; + var name; + var bracketOpensAt; + var hasArguments; + var i, l; + + for (i = 0, l = matches.length; i < l; i++) { + match = matches[i]; + + bracketOpensAt = match.indexOf(Marker.OPEN_ROUND_BRACKET); + hasArguments = bracketOpensAt > -1; + name = hasArguments ? match.substring(0, bracketOpensAt) : match; - return hasArguments ? - PSEUDO_CLASSES_WITH_ARGUMENTS.indexOf(name) > -1 : - PSEUDO_CLASSES_WITH_ARGUMENTS.indexOf(name) == -1; - }); + if (hasArguments && PSEUDO_CLASSES_WITH_ARGUMENTS.indexOf(name) == -1) { + return false; + } + + if (!hasArguments && PSEUDO_CLASSES_WITH_ARGUMENTS.indexOf(name) > -1) { + return false; + } + } + + return true; } function someIncorrectlyChained(selector, matches) { var positionInSelector = 0; - - return matches.some(function (match, index) { - var matchAt; - var nextMatch = matches[index + 1]; - var nextMatchAt; - var name; - var nextName; - var areChained; + var match; + var matchAt; + var nextMatch; + var nextMatchAt; + var name; + var nextName; + var areChained; + var i, l; + + for (i = 0, l = matches.length; i < l; i++) { + match = matches[i]; + nextMatch = matches[i + 1]; if (!nextMatch) { - return false; + break; } matchAt = selector.indexOf(match, positionInSelector); @@ -171,19 +208,29 @@ function someIncorrectlyChained(selector, matches) { nextMatch.substring(0, nextMatch.indexOf(Marker.OPEN_ROUND_BRACKET)) : nextMatch; - return name != NOT_PSEUDO || nextName != NOT_PSEUDO; - } else { - return false; + if (name != NOT_PSEUDO || nextName != NOT_PSEUDO) { + return true; + } } - }); + } + + return false; } function someMixed(matches) { var firstIsPseudoElement = DOUBLE_COLON_PATTERN.test(matches[0]); + var match; + var i, l; + + for (i = 0, l = matches.length; i < l; i++) { + match = matches[i]; + + if (DOUBLE_COLON_PATTERN.test(match) != firstIsPseudoElement) { + return true; + } + } - return matches.some(function (match) { - return DOUBLE_COLON_PATTERN.test(match) != firstIsPseudoElement; - }); + return false; } module.exports = isMergeable;