feat: enhance source map handling in NLS and private field conversion#296957
feat: enhance source map handling in NLS and private field conversion#296957
Conversation
- Implemented inline source maps in the NLS plugin to ensure accurate mapping from transformed source back to original. - Modified `transformToPlaceholders` to return edits for source map adjustments. - Added `adjustSourceMap` function to update source maps based on text edits in `convertPrivateFields`. - Introduced tests for source map accuracy in both NLS and private field conversion scenarios. - Updated documentation to reflect changes in source map handling and the rationale behind accepting column imprecision.
There was a problem hiding this comment.
Pull request overview
Improves source map correctness in the build/next esbuild-based pipeline, specifically around NLS placeholder transformation and post-bundle private-field mangling so that debugging/crash reporting points back to original sources more reliably.
Changes:
- Add inline input source maps in the NLS esbuild plugin so esbuild can compose NLS transforms into final bundle source maps.
- Return detailed text edits from
convertPrivateFieldsand introduceadjustSourceMapto rewrite.mapfiles accordingly during post-processing. - Add targeted tests for NLS and private-field conversion source map behavior, plus documentation updates describing remaining column-imprecision tradeoffs.
Reviewed changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| build/next/working.md | Documents source map corruption root causes, fixes applied, and remaining known limitations. |
| build/next/nls-plugin.ts | Tracks NLS edits and appends an inline source map to transformed TS so esbuild can compose maps correctly. |
| build/next/private-to-property.ts | Exposes applied edits and adds adjustSourceMap to shift generated columns based on those edits. |
| build/next/index.ts | Integrates source map adjustment during bundling output post-processing. |
| build/next/test/nls-sourcemap.test.ts | New tests validating NLS plugin source map composition and sourcesContent correctness. |
| build/next/test/private-to-property.test.ts | New tests validating convertPrivateFields edit reporting and adjustSourceMap behavior. |
Comments suppressed due to low confidence (1)
build/next/private-to-property.ts:287
- Rebuilding the map via
new SourceMapGenerator({ file: sourceMapJson.file })drops other top-level sourcemap fields (e.g.sourceRootand any vendor extensions likex_google_ignoreList) if they exist on the input map. If those are present in esbuild’s output for this repo, they should be preserved on the adjusted map as well.
// Use source-map library to read, adjust, and write
const consumer = new SourceMapConsumer(sourceMapJson);
const generator = new SourceMapGenerator({ file: sourceMapJson.file });
// Copy sourcesContent
for (let i = 0; i < sourceMapJson.sources.length; i++) {
const content = sourceMapJson.sourcesContent?.[i];
if (content !== null && content !== undefined) {
generator.setSourceContent(sourceMapJson.sources[i], content);
}
}
// Walk every mapping, adjust the generated column, and add to the new generator
consumer.eachMapping(mapping => {
const lineEdits = editsByLine.get(mapping.generatedLine - 1); // 0-based for our data
const adjustedCol = adjustColumn(mapping.generatedColumn, lineEdits);
const newMapping: Mapping = {
generated: { line: mapping.generatedLine, column: adjustedCol },
original: { line: mapping.originalLine, column: mapping.originalColumn },
source: mapping.source,
};
if (mapping.name !== null) {
newMapping.name = mapping.name;
}
generator.addMapping(newMapping);
});
return JSON.parse(generator.toString());
}
| if (mangleResult.editCount > 0) { | ||
| mangleStats.push({ file: path.relative(path.join(REPO_ROOT, outDir), file.path), result: mangleResult }); | ||
| mangleEdits.set(file.path, { preMangleCode, edits: mangleResult.edits }); | ||
| } |
There was a problem hiding this comment.
The private-field edits are computed after postProcessNLS (see preMangleCode = content after NLS replacement), but the .map file being adjusted is still the original esbuild map for the pre-postProcess output. That means the edit offsets/columns do not line up with the map’s generated positions when NLS is enabled, so adjustSourceMap will shift the wrong columns (potentially making maps worse). To keep coordinate systems consistent, either run convertPrivateFields before postProcessNLS, or adjust the source map for NLS edits first / translate the private-field edit offsets back to the pre-NLS code.
…, reorder mangle before NLS
transformToPlaceholdersto return edits for source map adjustments.adjustSourceMapfunction to update source maps based on text edits inconvertPrivateFields.