Skip to content

Commit 1a9240c

Browse files
bartvenemanBart Veneman
andauthored
tiny perf bits (#386)
``` # before 19097 analyzer.cjs 90945 analyzer.cjs.map 17440 analyzer.modern.js 90485 analyzer.modern.js.map 18871 analyzer.module.js 90985 analyzer.module.js.map 19071 analyzer.umd.js 91146 analyzer.umd.js.map 27391 index.d.ts # after 19021 analyzer.cjs 90418 analyzer.cjs.map 17338 analyzer.modern.js 89870 analyzer.modern.js.map 18795 analyzer.module.js 90458 analyzer.module.js.map 18975 analyzer.umd.js 90628 analyzer.umd.js.map 27391 index.d.ts ``` --------- Co-authored-by: Bart Veneman <bart.veneman@drukwerkdeal.nl>
1 parent 5384f6f commit 1a9240c

File tree

9 files changed

+96
-118
lines changed

9 files changed

+96
-118
lines changed

src/atrules/atrules.js

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -68,27 +68,26 @@ export function isMediaBrowserhack(prelude) {
6868
returnValue = true
6969
return this.break
7070
}
71-
}
72-
if (node.type === MediaFeature) {
71+
} else if (node.type === MediaFeature) {
7372
if (value !== null && value.unit === '\\0') {
7473
returnValue = true
7574
return this.break
7675
}
77-
if (strEquals('-moz-images-in-menus', name)
76+
else if (strEquals('-moz-images-in-menus', name)
7877
|| strEquals('min--moz-device-pixel-ratio', name)
7978
|| strEquals('-ms-high-contrast', name)
8079
) {
8180
returnValue = true
8281
return this.break
8382
}
84-
if (strEquals('min-resolution', name)
83+
else if (strEquals('min-resolution', name)
8584
&& strEquals('.001', value.value)
8685
&& strEquals('dpcm', value.unit)
8786
) {
8887
returnValue = true
8988
return this.break
9089
}
91-
if (strEquals('-webkit-min-device-pixel-ratio', name)) {
90+
else if (strEquals('-webkit-min-device-pixel-ratio', name)) {
9291
let val = value.value
9392
if ((strEquals('0', val) || strEquals('10000', val))) {
9493
returnValue = true

src/collection.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ export class Collection {
7878

7979
items.forEach((list, key) => {
8080
if (useLocations) {
81-
let nodes = list.map(index => {
81+
let nodes = list.map(function (index) {
8282
let position = index * 4
8383
/** @type {CssLocation} */
8484
return {
@@ -89,8 +89,9 @@ export class Collection {
8989
}
9090
})
9191
uniqueWithLocations.set(key, nodes)
92+
} else {
93+
unique[key] = list.length
9294
}
93-
unique[key] = list.length
9495
})
9596

9697
let total = this._total

src/index.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ export function analyze(css, options = {}) {
7373
// Stylesheet
7474
let totalComments = 0
7575
let commentsSize = 0
76-
let embeds = new Collection(useLocations)
76+
let embeds = new Collection(false)
7777
let embedSize = 0
7878
let embedTypes = {
7979
total: 0,

src/properties/property-utils.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,9 @@ export function isHack(property) {
1111
let code = property.charCodeAt(0)
1212

1313
return code === 47 // /
14+
|| code === 42 // *
1415
|| code === 95 // _
1516
|| code === 43 // +
16-
|| code === 42 // *
1717
|| code === 38 // &
1818
|| code === 36 // $
1919
|| code === 35 // #

src/selectors/utils.js

Lines changed: 35 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
import walk from 'css-tree/walker'
33
import { startsWith, strEquals } from '../string-utils.js'
44
import { hasVendorPrefix } from '../vendor-prefix.js'
5+
import { KeywordSet } from '../keyword-set.js'
56
import {
67
PseudoClassSelector,
78
PseudoElementSelector,
@@ -29,20 +30,17 @@ function analyzeList(selectorListAst, cb) {
2930
return childSelectors
3031
}
3132

32-
/** @param {string} name */
33-
function isPseudoFunction(name) {
34-
return (
35-
strEquals(name, 'not')
36-
|| strEquals(name, 'nth-child')
37-
|| strEquals(name, 'nth-last-child')
38-
|| strEquals(name, 'where')
39-
|| strEquals(name, 'is')
40-
|| strEquals(name, 'has')
41-
|| strEquals(name, 'matches')
42-
|| strEquals(name, '-webkit-any')
43-
|| strEquals(name, '-moz-any')
44-
)
45-
}
33+
const PSEUDO_FUNCTIONS = new KeywordSet([
34+
'nth-child',
35+
'where',
36+
'not',
37+
'is',
38+
'has',
39+
'nth-last-child',
40+
'matches',
41+
'-webkit-any',
42+
'-moz-any',
43+
])
4644

4745
/** @param {import('css-tree').Selector} selector */
4846
export function isAccessibility(selector) {
@@ -57,17 +55,17 @@ export function isAccessibility(selector) {
5755
}
5856
}
5957
// Test for [aria-] or [role] inside :is()/:where() and friends
60-
else if (node.type === PseudoClassSelector) {
61-
if (isPseudoFunction(node.name)) {
62-
let list = analyzeList(node, isAccessibility)
58+
else if (node.type === PseudoClassSelector && PSEUDO_FUNCTIONS.has(node.name)) {
59+
let list = analyzeList(node, isAccessibility)
6360

64-
if (list.some(b => b === true)) {
61+
for (let c of list) {
62+
if (c === true) {
6563
isA11y = true
66-
return this.skip
64+
break
6765
}
68-
69-
return this.skip
7066
}
67+
68+
return this.skip
7169
}
7270
})
7371

@@ -82,15 +80,17 @@ export function isPrefixed(selector) {
8280
let isPrefixed = false
8381

8482
walk(selector, function (node) {
85-
if (node.type === PseudoElementSelector
86-
|| node.type === TypeSelector
87-
|| node.type === PseudoClassSelector
83+
let type = node.type
84+
85+
if (type === PseudoElementSelector
86+
|| type === TypeSelector
87+
|| type === PseudoClassSelector
8888
) {
8989
if (hasVendorPrefix(node.name)) {
9090
isPrefixed = true
9191
return this.break
9292
}
93-
} else if (node.type === AttributeSelector) {
93+
} else if (type === AttributeSelector) {
9494
if (hasVendorPrefix(node.name.name)) {
9595
isPrefixed = true
9696
return this.break
@@ -110,20 +110,21 @@ export function getComplexity(selector) {
110110
let complexity = 0
111111

112112
walk(selector, function (node) {
113-
if (node.type === Selector || node.type === Nth) return
113+
let type = node.type
114+
if (type === Selector || type === Nth) return
114115

115116
complexity++
116117

117-
if (node.type === PseudoElementSelector
118-
|| node.type === TypeSelector
119-
|| node.type === PseudoClassSelector
118+
if (type === PseudoElementSelector
119+
|| type === TypeSelector
120+
|| type === PseudoClassSelector
120121
) {
121122
if (hasVendorPrefix(node.name)) {
122123
complexity++
123124
}
124125
}
125126

126-
if (node.type === AttributeSelector) {
127+
if (type === AttributeSelector) {
127128
if (node.value) {
128129
complexity++
129130
}
@@ -133,16 +134,16 @@ export function getComplexity(selector) {
133134
return this.skip
134135
}
135136

136-
if (node.type === PseudoClassSelector) {
137-
if (isPseudoFunction(node.name)) {
137+
if (type === PseudoClassSelector) {
138+
if (PSEUDO_FUNCTIONS.has(node.name)) {
138139
let list = analyzeList(node, getComplexity)
139140

140141
// Bail out for empty/non-existent :nth-child() params
141142
if (list.length === 0) return
142143

143-
list.forEach((c) => {
144+
for (let c of list) {
144145
complexity += c
145-
})
146+
}
146147
return this.skip
147148
}
148149
}

src/string-utils.js

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,3 @@
1-
/**
2-
* @param {string} str
3-
* @param {number} at
4-
*/
5-
function charCodeAt(str, at) {
6-
return str.charCodeAt(at)
7-
}
8-
91
/**
102
* Case-insensitive compare two character codes
113
* @param {string} referenceCode
@@ -38,7 +30,7 @@ export function strEquals(base, maybe) {
3830
if (len !== maybe.length) return false
3931

4032
for (let i = 0; i < len; i++) {
41-
if (compareChar(charCodeAt(base, i), charCodeAt(maybe, i)) === false) {
33+
if (compareChar(base.charCodeAt(i), maybe.charCodeAt(i)) === false) {
4234
return false
4335
}
4436
}
@@ -66,7 +58,7 @@ export function endsWith(base, maybe) {
6658
}
6759

6860
for (let i = len - 1; i >= offset; i--) {
69-
if (compareChar(charCodeAt(base, i - offset), charCodeAt(maybe, i)) === false) {
61+
if (compareChar(base.charCodeAt(i - offset), maybe.charCodeAt(i)) === false) {
7062
return false
7163
}
7264
}
@@ -76,16 +68,22 @@ export function endsWith(base, maybe) {
7668

7769
/**
7870
* Case-insensitive testing whether a string starts with a given substring
71+
*
72+
* @example
73+
* startsWith('test', 'my-test') // false
74+
* startsWith('test', 'tes') // true
75+
* startsWith('test', 'test-me') // true
76+
*
7977
* @param {string} base
8078
* @param {string} maybe
81-
* @returns {boolean} true if `test` starts with `base`, false otherwise
79+
* @returns {boolean} true if `base` starts with `maybe`, false otherwise
8280
*/
8381
export function startsWith(base, maybe) {
8482
let len = base.length
8583
if (maybe.length < len) return false
8684

8785
for (let i = 0; i < len; i++) {
88-
if (compareChar(charCodeAt(base, i), charCodeAt(maybe, i)) === false) {
86+
if (compareChar(base.charCodeAt(i), maybe.charCodeAt(i)) === false) {
8987
return false
9088
}
9189
}

src/stylesheet/stylesheet.js

Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,3 @@
1-
/**
2-
* @param {string} str
3-
* @param {number} start
4-
* @param {number} end
5-
*/
6-
function substring(str, start, end) {
7-
return str.substring(start, end)
8-
}
9-
101
/** @param {string} embed */
112
export function getEmbedType(embed) {
123
// data:image/gif;base64,R0lG
@@ -15,12 +6,12 @@ export function getEmbedType(embed) {
156
let comma = embed.indexOf(',')
167

178
if (semicolon === -1) {
18-
return substring(embed, start, comma)
9+
return embed.substring(start, comma)
1910
}
2011

2112
if (comma !== -1 && comma < semicolon) {
22-
return substring(embed, start, comma);
13+
return embed.substring(start, comma);
2314
}
2415

25-
return substring(embed, start, semicolon)
16+
return embed.substring(start, semicolon)
2617
}

src/values/animations.js

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -24,32 +24,30 @@ const TIMING_FUNCTION_VALUES = new KeywordSet([
2424
export function analyzeAnimation(children, cb) {
2525
let durationFound = false
2626

27-
children.forEach(child => {
27+
for (let child of children) {
2828
let type = child.type
2929
let name = child.name
3030

3131
// Right after a ',' we start over again
3232
if (type === Operator) {
33-
return durationFound = false
34-
}
35-
if (type === Dimension && durationFound === false) {
33+
durationFound = false
34+
} else if (type === Dimension && durationFound === false) {
35+
// The first Dimension is the duration, the second is the delay
3636
durationFound = true
37-
return cb({
37+
cb({
3838
type: 'duration',
3939
value: child,
4040
})
41-
}
42-
if (type === Identifier && TIMING_KEYWORDS.has(name)) {
43-
return cb({
41+
} else if (type === Identifier && TIMING_KEYWORDS.has(name)) {
42+
cb({
4443
type: 'fn',
4544
value: child,
4645
})
47-
}
48-
if (type === Func && TIMING_FUNCTION_VALUES.has(name)) {
49-
return cb({
46+
} else if (type === Func && TIMING_FUNCTION_VALUES.has(name)) {
47+
cb({
5048
type: 'fn',
5149
value: child,
5250
})
5351
}
54-
})
52+
}
5553
}

0 commit comments

Comments
 (0)