Skip to content

Commit 245c757

Browse files
authored
Speed up segmentation
1 parent 4aefd26 commit 245c757

File tree

1 file changed

+32
-20
lines changed

1 file changed

+32
-20
lines changed

packages/tailwindcss/src/utils/segment.ts

Lines changed: 32 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -10,44 +10,56 @@
1010
* x x x ╰──────── Split because top-level
1111
* ╰──────────────┴──┴───────────── Ignored b/c inside >= 1 levels of parens
1212
*/
13+
const closingBracketStack = new Uint8Array(256)
14+
const OPEN_PAREN = '('.charCodeAt(0)
15+
const OPEN_BRACKET = '['.charCodeAt(0)
16+
const OPEN_BRACE = '{'.charCodeAt(0)
17+
const CLOSE_PAREN = ')'.charCodeAt(0)
18+
const CLOSE_BRACKET = ']'.charCodeAt(0)
19+
const CLOSE_BRACE = '}'.charCodeAt(0)
20+
const BACKSLASH = '\\'.charCodeAt(0)
21+
1322
export function segment(input: string, separator: string) {
14-
// Stack of characters to close open brackets. Appending to a string because
15-
// it's faster than an array of strings.
16-
let closingBracketStack = ''
23+
// Since JavaScript is single-threaded, using a shared buffer
24+
// is more efficient and should still be safe.
25+
let stackPointer = 0
1726
let parts: string[] = []
1827
let lastPos = 0
1928

29+
let separatorCode = separator.charCodeAt(0)
30+
2031
for (let idx = 0; idx < input.length; idx++) {
21-
let char = input[idx]
32+
let char = input.charCodeAt(idx)
2233

23-
if (closingBracketStack.length === 0 && char === separator) {
34+
if (stackPointer === 0 && char === separatorCode) {
2435
parts.push(input.slice(lastPos, idx))
2536
lastPos = idx + 1
2637
continue
2738
}
2839

2940
switch (char) {
30-
case '\\':
41+
case BACKSLASH:
3142
// The next character is escaped, so we skip it.
3243
idx += 1
3344
break
34-
case '(':
35-
closingBracketStack += ')'
45+
case OPEN_PAREN:
46+
closingBracketStack[stackPointer] = CLOSE_PAREN
47+
stackPointer++
3648
break
37-
case '[':
38-
closingBracketStack += ']'
49+
case OPEN_BRACKET:
50+
closingBracketStack[stackPointer] = CLOSE_BRACKET
51+
stackPointer++
3952
break
40-
case '{':
41-
closingBracketStack += '}'
53+
case OPEN_BRACE:
54+
closingBracketStack[stackPointer] = CLOSE_BRACE
55+
stackPointer++
4256
break
43-
case ')':
44-
case ']':
45-
case '}':
46-
if (
47-
closingBracketStack.length > 0 &&
48-
char === closingBracketStack[closingBracketStack.length - 1]
49-
) {
50-
closingBracketStack = closingBracketStack.slice(0, closingBracketStack.length - 1)
57+
case CLOSE_BRACKET:
58+
case CLOSE_BRACE:
59+
case CLOSE_PAREN:
60+
if (stackPointer > 0 && char === closingBracketStack[stackPointer - 1]) {
61+
// No need to mutate the buffer here, as it can stay dirty for the next use
62+
stackPointer--
5163
}
5264
break
5365
}

0 commit comments

Comments
 (0)