Skip to content

fix(devtools-bundler-core): make stateful-regex ignore patterns deterministic - #5

Open
detail-app[bot] wants to merge 1 commit into
mainfrom
detail/bug-fix/fix-devtools-bundler-core-make-stateful-regex-igno-4033de
Open

detail-app[bot] wants to merge 1 commit into
mainfrom
detail/bug-fix/fix-devtools-bundler-core-make-stateful-regex-igno-4033de

Conversation

@detail-app

@detail-app detail-app Bot commented Oct 23, 2026

Copy link
Copy Markdown

Detail bug report: View on Detail

🎯 Changes

The matcher used by the injectSource.ignore.files / ignore.components config called pattern.test(s) directly on user-supplied RegExp objects. When a regex has the g (global) or y (sticky) flag, .test() is stateful and advances lastIndex on a successful match. Because the same regex object from the user's config is reused across every module transform (Vite transform hook and rspack loader) and every JSX-element check for the lifetime of a dev server/build, identical inputs produced alternating match/no-match results — so files/components the user asked to ignore were intermittently injected with data-tsd-source depending on module processing order.

Fix: matcher now clones any g/y-flagged regex without those stateful flags (preserving all other flags like i/m/s/u) so each .test() is stateless and deterministic. Flagless regexes pass through by identity, so the common documented cases are unchanged. The user's original config regex is never mutated (lastIndex stays 0).

✅ Checklist

  • I have followed the steps in the Contributing guide.
  • I have tested code changes locally with pnpm test:pr, or these tests do not apply to this pull request.
  • I fully understand the code in this pull request, including any code generated with AI assistance.

🚀 Release Impact

  • This change affects published code, and I have generated a changeset.
  • This change is docs/CI/dev-only (no release).

Testing

  • Unit tests, typecheck (tsc --noEmit), lint (eslint ./src), and build (vite build + publint --strict) for @tanstack/devtools-bundler-core all pass. Downstream consumers @tanstack/devtools-vite and @tanstack/devtools-rspack typecheck cleanly against the updated package. The full devtools-bundler-core suite (13 files / 204 tests) is green, including the existing inject-source ignore-pattern tests (53 tests, no regression).
  • Added regression tests in matcher.test.ts asserting that g- and y-flagged regexes stay deterministic across repeated calls with a shared regex object, and that the user's regex lastIndex is not mutated.
  • End-to-end verification of the reported public-API symptom: a temporary (unversioned) test drove repeated addSourceToJsx(code, 'src/Foo.test.tsx', { files: [/\.test\.tsx$/g] }) calls sharing one config object — the exact code path the Vite plugin and rspack loader use per module. With the fix, the file is ignored on every call; with the fix reverted the suite reproduces the reported nondeterminism (call chore: remove unused a11y panel style keys #1 injects instead of ignoring, lastIndex advances to 16, and a file with multiple <Button/> elements intermittently gets data-tsd-source on a later element). The fix was restored before commit.
  • A live Vite dev-server repro was not run: no existing example app uses injectSource, and the headless public-API test exercises the identical shared-config-reuse code path, with the revert control confirming the exact reported symptom.

Automatic Fixes PRs can be configured here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

0 participants