test: document webpack source map behaviour for column=0 lookups - #299
Conversation
Add tests for SourceMapper.mappingInfo with a synthetic webpack-style single-line bundle to document the known limitation introduced by #248. Background ---------- PR #81 changed originalPositionFor to always try LEAST_UPPER_BOUND first (then fall back to GREATEST_LOWER_BOUND). This was reverted in #106 because it broke webpack source maps: for real non-zero columns LEAST_UPPER_BOUND finds the *next* mapping (≥ column) rather than the one at the column, returning wrong function names. PR #248 fixed that regression by using LEAST_UPPER_BOUND only when column === 0, and GREATEST_LOWER_BOUND otherwise. This correctly handles Node.js ≥ 25 where V8's LineTick struct carries real column numbers. Residual limitation (Node.js < 25) ----------------------------------- On Node.js < 25, the LineTick struct has no column field. The C++ layer therefore always emits column=0 for every LineTick sample. With column=0, the sourcemapper uses LEAST_UPPER_BOUND, which finds the *first* mapping on the line. In a webpack bundle (all output on one line) every function maps to the same first source function in the map. This is not a regression vs. the pre-#248 state: before #248, those functions were simply unmapped (column=0 + GREATEST_LOWER_BOUND → nothing ≤ 0 → null → falls back to generated name/file). Both outcomes are imperfect; #248 trades "unmapped" for "mapped to first function", which may or may not be preferable depending on the use case. The two new tests pin both behaviours explicitly so any future change to this logic is immediately visible. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Overall package sizeSelf size: 2.43 MB Dependency sizes| name | version | self size | total size | |------|---------|-----------|------------| | pprof-format | 2.2.3 | 500.55 kB | 500.55 kB | | source-map | 0.8.0 | 185.66 kB | 185.66 kB | | node-gyp-build | 4.8.4 | 13.86 kB | 13.86 kB |🤖 This report was automatically generated by heaviest-objects-in-the-universe |
BenchmarksBenchmark execution time: 2026-03-13 12:45:12 Comparing candidate commit d6f79f2 in PR branch Found 0 performance improvements and 0 performance regressions! Performance is the same for 91 metrics, 29 unstable metrics. |
When lineNumbers is enabled, the column is always zero. If only one occurence of a call occurs on one line then that is correctly selected. However, in cases where the same function is called multiple times in the same line it will be unable to differentiate them and would use the unmapped value. This now makes it select the first call in the line as a best-guess for the match, and in Node.js v25 will use the new column field in LineTick to select the correct column where possible.
This comment has been minimized.
This comment has been minimized.
|
The code paths modified by this PR ( |
|
@nsavoire You're right, I was a bit too trigger happy with Claude's suggestions. For our current usage, this is indeed dead code as we don't use |
73c192a to
d6f79f2
Compare
* test: document webpack source map behaviour for column=0 lookups (#248) Add tests for SourceMapper.mappingInfo with a synthetic webpack-style single-line bundle to document the known limitation introduced by #248. Background ---------- PR #81 changed originalPositionFor to always try LEAST_UPPER_BOUND first (then fall back to GREATEST_LOWER_BOUND). This was reverted in #106 because it broke webpack source maps: for real non-zero columns LEAST_UPPER_BOUND finds the *next* mapping (≥ column) rather than the one at the column, returning wrong function names. PR #248 fixed that regression by using LEAST_UPPER_BOUND only when column === 0, and GREATEST_LOWER_BOUND otherwise. This correctly handles Node.js ≥ 25 where V8's LineTick struct carries real column numbers. Residual limitation (Node.js < 25) ----------------------------------- On Node.js < 25, the LineTick struct has no column field. The C++ layer therefore always emits column=0 for every LineTick sample. With column=0, the sourcemapper uses LEAST_UPPER_BOUND, which finds the *first* mapping on the line. In a webpack bundle (all output on one line) every function maps to the same first source function in the map. This is not a regression vs. the pre-#248 state: before #248, those functions were simply unmapped (column=0 + GREATEST_LOWER_BOUND → nothing ≤ 0 → null → falls back to generated name/file). Both outcomes are imperfect; #248 trades "unmapped" for "mapped to first function", which may or may not be preferable depending on the use case. The two new tests pin both behaviours explicitly so any future change to this logic is immediately visible. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix: apply prettier formatting to test-sourcemapper.ts * Fix source mapping of zero-column locations (#248) When lineNumbers is enabled, the column is always zero. If only one occurence of a call occurs on one line then that is correctly selected. However, in cases where the same function is called multiple times in the same line it will be unable to differentiate them and would use the unmapped value. This now makes it select the first call in the line as a best-guess for the match, and in Node.js v25 will use the new column field in LineTick to select the correct column where possible. * fix: use path.resolve/join for platform-portable bundle path in test --------- Co-authored-by: Stephen Belanger <admin@stephenbelanger.com>
What
Adds regression tests documenting how the source-mapper resolves single-line (webpack / Next.js) bundles, where multiple functions share generated line 1 and are distinguished only by column. The tests cover both paths:
GREATEST_LOWER_BOUNDresolves each function to its own source;column === 0(no column info) →LEAST_UPPER_BOUNDfalls back to the first mapping on the line.This locks in the behaviour of the #248 source-mapper fix so a regression would be immediately visible.
Scope
Tests only — the #248 source-mapper fix itself is already on
main.Also removes two stale
eslint-disablecomments (oom.ts,test-worker-threads.ts) for rules the current gts config no longer enables.Testing
test-sourcemapper— 29 passing.