Repository navigation
Fix #9: emit source maps for transformed output - #14
Conversation
Collect removal ranges in original coordinates, apply them with magic-string, and compose maps when the functions pass normalizes line endings. Add tests that assert map presence and trace generated positions back to the source.
| }); | ||
| expect(transformed?.code).toBe(["let x = 0;", "let z = 0;", "console.log('kept');"].join("\n")); | ||
| const raw = parseSourceMapJson(transformed!.map as { toString(): string }); | ||
| expect((raw.mappings as string).length).toBeGreaterThan(0); |
There was a problem hiding this comment.
is there a deep assertion that can be made here and other places where toBeGreaterThan is used
There was a problem hiding this comment.
Addressed in latest push: added expectSourceMapHasTraceableSegments using eachMapping so we assert decoded segments exist, not only non-empty VLQ.
| ms.remove(start, end); | ||
| } | ||
|
|
||
| const mid = ms.toString(); |
There was a problem hiding this comment.
can we find a more descriptive name for this?
There was a problem hiding this comment.
Renamed to codeAfterRemovals (and the same name in buildNormalizeMagicString) so it reads as the module text after all removal passes, before optional LF normalization.
| const allRemovalRanges = mergeRanges([...dbgRanges, ...fnRangesOrig, ...labelRangesOrig]); | ||
|
|
||
| const ms = new MagicString(code); | ||
| const sortedRemovals = [...allRemovalRanges].sort((a, b) => b[0] - a[0]); |
There was a problem hiding this comment.
because it is not obvious from the code, in a single line comment explain how you are sorting the array
There was a problem hiding this comment.
Added a one-line comment: ranges are sorted by descending start offset so we apply deletes from the end of the file toward the start (common batch-delete convention; all indices stay in original-file space).
| function computeLineStarts(code: string, lines: string[]): number[] { | ||
| const starts: number[] = new Array(lines.length); | ||
| starts[0] = 0; | ||
| let pos = 0; |
There was a problem hiding this comment.
more descriptive name
There was a problem hiding this comment.
Renamed the loop cursor to offsetInOriginalFile — it is the index walking code while aligning split(/\\r?\\n/) line boundaries to absolute positions for removal ranges.
| chainedCalls?: ChainedCallsPolicy; | ||
| } | ||
|
|
||
| const STRIP_INTERMEDIATE = "\0rolldown-plugin-strip/intermediate"; |
There was a problem hiding this comment.
what is this doing and why is it necessary?
There was a problem hiding this comment.
Documented above the const: it is a virtual sources/file bridge name so remapping can chain the removal-stage map (output = synthetic intermediate) with the LF-normalization map (input = that same intermediate, output = real module id).
Rename removal-stage string and scanning offset for clarity, document virtual map filename and removal sort order, and assert source maps contain traceable segments via eachMapping.
|
Pushed 148e40d addressing the inline review threads:
Replies are threaded under each original comment. |
Summary
transformchanges module source, usingmagic-stringremovals keyed by original indices.@jridgewell/remappingwhen thefunctionspass also normalizes line endings (split(/\r?\n/).join("\n")).join("\n")output (no stray newline after the sole kept line).originalPositionFortrace.Issues
How to test
Notes
magic-string,@jridgewell/remapping(map composition only when LF normalization runs).@jridgewell/trace-mapping(tests only).Learning notes
Source map composition across sequential transforms
What it is
When two transforms run in sequence (here: delete ranges, then normalize newlines), each can emit its own map. A composed map traces generated positions through both steps back to the original file.
Where it appears in this PR
src/index.ts— aftermagic-stringremovals, optional LF normalization uses a secondMagicStringon the intermediate string;remapping([normalizeMap, removalMap], () => null)folds those maps so consumers only see one map rooted at the Rolldown module id.Why it was the right call here
Returning only the first-stage map would mis-attribute columns whenever
\r\ncollapses to\n. Composing keeps the contract “map matches emitted code” without teaching the removal pass about newline normalization edge cases.If you want to go deeper
@jridgewell/remappingREADME — “Multiple transformations of a file” (array order: most recent map first).