Skip to content

Blank out backticks/dollars in placeholder JS instead of escaping - #69

Merged
NullVoxPopuli merged 1 commit into
NullVoxPopuli:mainfrom
NullVoxPopuli-ai-agent:fix-placeholder-backtick-overflow-pr
Jul 3, 2026
Merged

Blank out backticks/dollars in placeholder JS instead of escaping#69
NullVoxPopuli merged 1 commit into
NullVoxPopuli:mainfrom
NullVoxPopuli-ai-agent:fix-placeholder-backtick-overflow-pr

Conversation

@NullVoxPopuli-ai-agent

@NullVoxPopuli-ai-agent NullVoxPopuli-ai-agent commented Jul 3, 2026

Copy link
Copy Markdown

Fixes the root cause of ember-tooling/ember-eslint-parser#230.

The bug

toPlaceholderJS backslash-escapes ` and $ in template content, growing the placeholder by one character per occurrence. The padding slack is fixed: <template></template> is 21 chars, the static{`...`} wrapper is 10, so class-member templates have 11 chars of slack (expression templates have 19). Math.max(0, spaces) silently clamps once the escapes exceed that, so the placeholder ends up longer than the original region:

  • matchPlaceholder's end-range check fails, and the raw StaticBlock / TemplateLiteral placeholder leaks into the final AST — downstream, no-unused-expressions fires on it (that's exactly the #230 report: its two comments contain 12 backticks, one over the limit; 11 lints clean).
  • Every offset after the template shifts, so locations for the rest of the file are wrong too.

$ alone triggers it as well (e.g. {{! $$$$$$$$$$$$ }}), not just backticks.

The fix

Replace each ` and $ with a space instead of escaping. The placeholder content is discarded once the real Glimmer AST is spliced in — the placeholder node itself is only used as a WeakMap key for the TS node map in ember-eslint-parser, and its type (string / void) doesn't depend on the quasi content — so only the placeholder's length and line structure matter. Blanking keeps it the exact same length as the source region in all cases.

Verification

  • New regression tests cover the #230 snippet verbatim, the $ variant, the expression-template form, and offset accuracy for code after a hostile template (that last one failed with expected '' to be 'const after = 1;' before the fix).
  • Full suite passes (220 tests).
  • Verified end-to-end in ember-eslint-parser: with this patch in node_modules, the #230 file lints clean and ember-eslint-parser's own 86 tests still pass.

Note: now rebased onto current main.

🤖 Generated with Claude Code

Backslash-escaping ` and $ in template content grew the placeholder by
one character per occurrence. Once the growth exceeded the padding slack
(11 chars for class-member templates, 19 for expression templates), the
placeholder no longer lined up with the original <template> region:
matchPlaceholder's end-range check failed, the raw StaticBlock /
TemplateLiteral leaked into the AST, and every offset after the template
shifted. Downstream this surfaced as a false no-unused-expressions error
on gts files with backtick-heavy template comments
(ember-tooling/ember-eslint-parser#230).

Placeholder content is discarded when the Glimmer AST is spliced in, so
only its length and line structure matter — replace each ` and $ with a
space to keep the placeholder the exact same length as the source region.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@NullVoxPopuli-ai-agent
NullVoxPopuli-ai-agent force-pushed the fix-placeholder-backtick-overflow-pr branch from ca7ece8 to 3fc9513 Compare July 3, 2026 15:27
@NullVoxPopuli NullVoxPopuli added bug Something isn't working and removed internal labels Jul 3, 2026
@NullVoxPopuli
NullVoxPopuli merged commit 3feb166 into NullVoxPopuli:main Jul 3, 2026
6 of 8 checks passed
@NullVoxPopuli
NullVoxPopuli deleted the fix-placeholder-backtick-overflow-pr branch July 3, 2026 15:29
@github-actions github-actions Bot mentioned this pull request Jul 3, 2026
NullVoxPopuli added a commit to ember-tooling/ember-eslint-parser that referenced this pull request Jul 3, 2026
ember-estree < 0.6.10 backslash-escaped backticks and dollar signs when
building its same-length placeholder JS. Each escape grew the placeholder
by one character, and once the growth exceeded the padding slack (11
chars for class-member templates) the placeholder no longer matched the
original <template> region: the raw static block leaked into the AST and
no-unused-expressions fired on it, with all offsets after the template
shifted. Fixed upstream in NullVoxPopuli/ember-estree#69 by blanking the
characters instead of escaping.

Adds an end-to-end regression test with the exact snippet from #230.

The refreshed lockfile pulls newer oxc-parser/content-tag within
ember-estree's ranges, which rewords one syntax-error diagnostic; the
inline snapshot is updated to match.

Fixes #230

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants