fix: only compute selector specificity once per selector

This commit is contained in:
Mikael Sand
2019-10-22 00:12:02 +03:00
parent 168ee25ee4
commit 9f53e31b24
+21 -9
View File
@@ -405,20 +405,31 @@ function compareSpecificity(
return 0; return 0;
} }
type specificityAndSelector = {
selector: FlatSelector;
specificity: Specificity;
};
function specificityAndSelector(
selector: FlatSelector,
): specificityAndSelector {
return {
selector,
specificity: specificity(selector.item.data as Selector),
};
}
/** /**
* Compare two simple selectors. * Compare two simple selectors.
* *
* @param {Object} selectorA Simple selector A * @param {Object} a Simple selector A
* @param {Object} selectorB Simple selector B * @param {Object} b Simple selector B
* @return {Number} Score of selector A compared to selector B * @return {Number} Score of selector A compared to selector B
*/ */
function bySelectorSpecificity( function bySelectorSpecificity(
selectorA: FlatSelector, a: specificityAndSelector,
selectorB: FlatSelector, b: specificityAndSelector,
): number { ): number {
const aSpecificity = specificity(selectorA.item.data as Selector), return compareSpecificity(a.specificity, b.specificity);
bSpecificity = specificity(selectorB.item.data as Selector);
return compareSpecificity(aSpecificity, bSpecificity);
} }
// Run a single pass with the given chunk size. // Run a single pass with the given chunk size.
@@ -478,7 +489,7 @@ function pass<T>(
// Execute the sort using the input array and a second buffer as work space. // Execute the sort using the input array and a second buffer as work space.
// Returns one of those two, containing the final result. // Returns one of those two, containing the final result.
function exec<T>(arr: T[], len: number, comp: (a: T, b: T) => number) { function exec<T>(arr: T[], len: number, comp: (a: T, b: T) => number): T[] {
// Rather than dividing input, simply iterate chunks of 1, 2, 4, 8, etc. // Rather than dividing input, simply iterate chunks of 1, 2, 4, 8, etc.
// Chunks are the size of the left or right hand in merge sort. // Chunks are the size of the left or right hand in merge sort.
// Stop when the left-hand covers all of the array. // Stop when the left-hand covers all of the array.
@@ -505,7 +516,8 @@ function sortSelectors(selectors: FlatSelectorList) {
if (len <= 1) { if (len <= 1) {
return selectors; return selectors;
} }
return exec(selectors.slice(), len, bySelectorSpecificity); const withSpecificity = selectors.map(specificityAndSelector);
return exec(withSpecificity, len, bySelectorSpecificity).map(s => s.selector);
} }
const declarationParseProps = { const declarationParseProps = {