Skip to content

fix(core): ignore source map directives in JavaScript strings - #15969

Merged
LingyuCoder merged 2 commits into
web-infra-dev:mainfrom
Tiancheng-Xu:fix/source-map-template-literal
Oct 9, 2026
Merged

LingyuCoder merged 2 commits into
web-infra-dev:mainfrom
Tiancheng-Xu:fix/source-map-template-literal

Conversation

@Tiancheng-Xu

@Tiancheng-Xu Tiancheng-Xu commented Oct 6, 2026 •

Copy link
Copy Markdown
Contributor

Motivation

Closes #15950

With extractSourceMap enabled, source-map text in Angular-style template literals can trigger a missing-file lookup. Extraction must also leave identical directive text inside a string intact.

Changes

Replace full-program parsing and comment-position collection with a borrowed reverse scan of the trailing comment suffix, following ECMA-426 extraction without parsing. There is no AST, collected line vector, comment-position set, or new dependency.

Keep the existing URL/whitespace compatibility and JavaScript/CSS block directives, with guards against earlier block terminators, literal delimiters and ambiguous opening markers. Remove only the selected byte range; the public Rust result and function signature remain unchanged.

The config/runtime regression covers original template, nested/quoted/escaped string and regex cases, exact literal preservation, real JS/CSS maps with independently asserted sources, BOM whitespace, all five JavaScript line terminators, and nested block-marker/terminal-regex boundaries. Line-terminator resources use the existing VirtualModulesPlugin so Git normalization cannot change their bytes. Mapped functions prevent constant optimization from hiding map assertions.

Compatibility limit: quoted/backtick candidate comments and ambiguous block tails stop extraction. A quoted malformed directive no longer yields a truncated URL. An otherwise-valid directive followed by a quoted ordinary block, or after unmatched raw /* text in an earlier literal, can remain unextracted. A quoted ordinary block before a final unambiguous directive is accepted. Original source stays intact rather than risking removal across literal or executable text.

Validation

  • Rebuilt the native binding with the repository build script and pinned nightly toolchain.
  • rs test --project base -t extract-source-map-template-literal: 2 passed, 4.71s (the explicit filter skips the other cases).
  • rs test --project base: 43 files passed; 9,048 tests passed, 4 skipped; 1m 29s.
  • cargo test -p rspack_core utils::extract_source_map::tests -- --nocapture: 3 passed, 275 filtered.
  • cargo check --workspace --all-targets --locked and repository cargo lint: passed with two build jobs, run separately from JS tests.
  • cargo fmt --all --check, scoped config formatting/check and staged git diff --check: passed. Ordinary fixture ignores apply; the scoped JS check is not fixture-JS lint coverage.

Cargo emitted the existing build-script rustc-cdylib-link-arg warnings also present before this follow-up. No warning suppression or test-timeout/assertion changes were made. These are local results for bc93abe21e2d; upstream CI/review remain pending.

The old implementation failed the actual config/runtime no-warning regression. Review-added cases also reproduced native parsing corruption and changed template-literal contents before repair. Fixture/tool errors and the optimized-constant BOM observation are not counted as production RED evidence.

Copilot AI balanced review requested due to automatic review settings October 6, 2026 05:44

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🔵 Needs a closer look

It changes core source-map extraction semantics by integrating full SWC parsing and altering directive-removal logic, which warrants human verification of the parser-interaction edge cases and performance impact on large vendor bundles.

Review effort: Balanced
Findings: None

What changed in this PR

This PR fixes issue #15950, where extractSourceMap incorrectly treated a sourceMappingURL substring inside a JavaScript template literal (Angular's dom_renderer.ts) as a real source-map directive, causing Rspack to try to open a literal ${resolvedSourceMapUrl} path and emit a missing-file warning. The fix cross-checks regex matches against real comment positions obtained from the SWC parser, so directives embedded in strings, template literals, and regex literals are ignored, while genuine comment directives are still extracted. It lives in the core extract_source_map utility, which is the loader-side path that resolves and inlines external source maps.

Changes:

  • For JavaScript, gate the extraction regex by parsing with SWC and keeping only matches whose start offset coincides with an actual comment start; non-JS inputs and parse failures fall back to the existing regex-only behavior.
  • Switch comment removal from a first-occurrence string replace (cow_replace) to removing the exact matched byte range (replace_range), so an identical directive inside a string is preserved.
  • Add a configCases fixture covering Angular-style interpolation, multiline/nested/quoted/escaped string text, a regex literal, a real external map, and an identical directive preserved inside a string.
File Description
crates/​rspack_core/​src/​utils/​extract_source_map.rs Adds javascript_comment_starts + range-aware extraction, filters regex matches to real comment positions, and removes directives by exact byte range.
tests/​rspack-test/​configCases/​source-map/​extract-source-map-template-literal/​rspack.config.ts New config enabling extractSourceMap for the fixture (target node, source-map devtool).
tests/​rspack-test/​configCases/​source-map/​extract-source-map-template-literal/​strings.js Fixture strings with in-string/regex/template-literal directives that must stay unchanged.
tests/​rspack-test/​configCases/​source-map/​extract-source-map-template-literal/​mapped.js Fixture with an in-string directive plus a real trailing directive to be extracted.
tests/​rspack-test/​configCases/​source-map/​extract-source-map-template-literal/​mapped.js.map External source map referencing original.js, used to assert real extraction.
tests/​rspack-test/​configCases/​source-map/​extract-source-map-template-literal/​index.js Test entry asserting in-string directives are preserved and the real comment is extracted.
Files not reviewed (1)
  • tests/rspack-test/configCases/source-map/extract-source-map-template-literal/mapped.js: Generated file

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread crates/rspack_core/src/utils/extract_source_map.rs Outdated
@codspeed

codspeed Bot commented Oct 9, 2026

Copy link
Copy Markdown
Contributor

Merging this PR will not alter performance

✅ 54 untouched benchmarks
⏩ 47 skipped benchmarks1


Comparing Tiancheng-Xu:fix/source-map-template-literal (bc93abe) with main (c68c264)

Open in CodSpeed

Footnotes

  1. 47 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports. ↩

@LingyuCoder LingyuCoder left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, thanks

@LingyuCoder
LingyuCoder merged commit 3350006 into web-infra-dev:main Oct 9, 2026
69 of 71 checks passed
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.

[Bug]: extractSourceMap falsely matches on sourceMappingURL inside template literal

3 participants