Some string in codebase causing candidatePermutations to stack overflow
calebmer opened this issue · 4 comments
What version of @tailwindcss/jit are you using?
v0.1.13
What version of Node.js are you using?
v14.15.0
What browser are you using?
n/a
What operating system are you using?
macOS
Reproduction repository
n/a
I have the following line of code in my codebase: [^${char}\\s][^${char}]*[^${char}\\s] (it’s used to build a regular expression). When I remove it from my codebase, @tailwindcss/jit works fine. When I add it back Tailwind CSS fails to build with:
RangeError: Maximum call stack size exceeded
at candidatePermutations.next (<anonymous>)
at candidatePermutations.next (<anonymous>)
at candidatePermutations.next (<anonymous>)
at candidatePermutations.next (<anonymous>)
at candidatePermutations.next (<anonymous>)
at candidatePermutations.next (<anonymous>)
at candidatePermutations.next (<anonymous>)
I reproduced this issue by taking the implementation of candidatePermutations() in my node_modules folder and running it standalone:
function* candidatePermutations(candidate, lastIndex = Infinity) {
if (lastIndex < 0) {
return
}
let dashIdx
if (candidate.endsWith(']', lastIndex + 1)) {
dashIdx = candidate.lastIndexOf('[') - 1
} else {
dashIdx = candidate.lastIndexOf('-', lastIndex)
}
if (dashIdx < 0) {
return
}
let prefix = candidate.slice(0, dashIdx)
let modifier = candidate.slice(dashIdx + 1)
yield [prefix, modifier]
yield* candidatePermutations(candidate, dashIdx - 1)
}
for (const result of candidatePermutations('[^${char}\\\\s][^${char}]*[^${char}\\\\s]')) {
console.log(result);
}Simplest string that reproduces the infinite iteration: ]-[].
Simplest string that reproduces the infinite iteration:
]-[].
Now this is a maintainer's dream in terms of minimal reproduction 🙏 Looking into it now, thanks.
I think it might be a typo here:
tailwindcss-jit/src/lib/generateRules.js
Lines 26 to 30 in a54c6fd
This code works for me locally:
if (candidate.endsWith("]", lastIndex + 1)) {
dashIdx = candidate.lastIndexOf("[", lastIndex) - 1;
} else {
dashIdx = candidate.lastIndexOf("-", lastIndex);
}Line 28 is missing lastIndex.
Should be fixed in v0.1.14! Used a slightly different solution, basically only worry about the square bracket stuff on the first pass when looking at the full string, since we don't support arbitrary values in the middle of class candidates anyways (like bg-[#126546]-foo-bar isn't valid) 👍