Skip to content

sourcemaps: don't map a trailing generated-only segment - #66264

Open
jackyzha0 wants to merge 2 commits into
nodejs:mainfrom
jackyzha0:sourcemap-trailing-segment
Open

jackyzha0 wants to merge 2 commits into
nodejs:mainfrom
jackyzha0:sourcemap-trailing-segment

Conversation

@jackyzha0

@jackyzha0 jackyzha0 commented Sep 24, 2026 •

Copy link
Copy Markdown
Contributor

Why

The mappings parser detects a segment that has only a generated column by peeking at the next character.

At the end of the mappings string the peek returns an empty string, which is not a separator, so a final generated-only segment is decoded with phantom zero deltas and inherits the source, line, and column of the segment before it.

With --enable-source-maps, stack frames in code after the last mapped segment are then attributed to the last mapped source.

repro.js:

vendor();
function vendor() { throw new Error('boom'); }
//# sourceMappingURL=repro.js.map

repro.js.map:

{"version":3,"sources":["app.ts"],"names":[],"mappings":"AAAA;A"}
$ node --enable-source-maps repro.js
Error: boom
    at vendor (app.ts:1:1)

With this change:

$ node --enable-source-maps repro.js
Error: boom
    at vendor (repro.js:2:27)

What Changed

Check for the end of the string before reading source fields.

Disclaimer: this PR was written with the help of Opus 5.5 but I have personally read, reviewed, and validated the changes.

The mappings parser detects a segment that has only a generated column
by peeking at the next character. At the end of the mappings string the
peek returns an empty string, which is not a separator, so a final
generated-only segment is decoded with phantom zero deltas and inherits
the source, line, and column of the segment before it. With
--enable-source-maps, stack frames in code after the last mapped
segment are then attributed to the last mapped source.

Check for the end of the string before reading source fields.

Signed-off-by: Jacky Zhao <j.zhao2k19@gmail.com>
@nodejs-github-bot nodejs-github-bot added needs-ci PRs that need a full CI run. source maps Issues and PRs related to source map support. labels Sep 24, 2026
@codecov

codecov Bot commented Sep 24, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 90.43%. Comparing base (e7d8ab5) to head (9d71a74).
⚠️ Report is 361 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main   #66264      +/-   ##
==========================================
+ Coverage   90.30%   90.43%   +0.12%     
==========================================
  Files         789      791       +2     
  Lines      272880   276595    +3715     
  Branches    52110    53119    +1009     
==========================================
+ Hits       246418   250125    +3707     
+ Misses      16912    16864      -48     
- Partials     9550     9606      +56     
Files with missing lines Coverage Δ
lib/internal/source_map/source_map.js 99.49% <100.00%> (+<0.01%) ⬆️

... and 197 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Comment thread lib/internal/source_map/source_map.js Outdated

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Would you mind adding the hasNext check here as well? This could be verified with a test like:

{
  const sm = new SourceMap({
    version: 3,
    sources: ['a.js'],
    names: ['should-not-be-used'],
    mappings: 'AAAA', // No name field.
  });

  assert.deepStrictEqual(sm.findEntry(0, 0), {
    generatedLine: 0,
    generatedColumn: 0,
    originalSource: 'a.js',
    originalLine: 0,
    originalColumn: 0,
    name: undefined, // No name field.
  });
}

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

done!

Check hasNext() before reading the optional name field, and add a test
for a segment that has no name.

Signed-off-by: Jacky Zhao <j.zhao2k19@gmail.com>
Assisted-by: Claude Code
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

needs-ci PRs that need a full CI run. source maps Issues and PRs related to source map support.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants