Skip to content
This repository has been archived by the owner on Apr 6, 2021. It is now read-only.

Some string in codebase causing candidatePermutations to stack overflow #172

Closed
calebmer opened this issue Mar 27, 2021 · 4 comments
Closed

Comments

@calebmer
Copy link

calebmer commented Mar 27, 2021

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);
}

(Babel playground)

@calebmer
Copy link
Author

Simplest string that reproduces the infinite iteration: ]-[].

@adamwathan
Copy link
Member

Simplest string that reproduces the infinite iteration: ]-[].

Now this is a maintainer's dream in terms of minimal reproduction 🙏 Looking into it now, thanks.

@calebmer
Copy link
Author

calebmer commented Mar 27, 2021

I think it might be a typo here:

if (candidate.endsWith(']', lastIndex + 1)) {
dashIdx = candidate.lastIndexOf('[') - 1
} else {
dashIdx = candidate.lastIndexOf('-', lastIndex)
}

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.

@adamwathan
Copy link
Member

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) 👍

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants