From c292e683f16880237e950847ceeed291be207f5d Mon Sep 17 00:00:00 2001 From: liuxingbaoyu <30521560+liuxingbaoyu@users.noreply.github.com> Date: Sun, 19 Feb 2023 01:36:03 +0800 Subject: [PATCH] feat: Generate sourcemaps of friendly call frames (#15022) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Justin Ridgewell Co-authored-by: Nicolò Ribaudo --- packages/babel-cli/package.json | 2 +- .../out-files/script2.js | 2 +- packages/babel-core/package.json | 4 +- .../src/transformation/file/generate.ts | 34 ++- .../src/transformation/normalize-file.ts | 11 +- .../arrow-function/source-map.json | 2 +- .../source-maps/class/source-map.json | 7 +- .../input-source-map-complex/source-map.json | 7 +- .../input-source-map-external/source-map.json | 8 +- .../source-map.json | 8 +- .../source-map.json | 14 +- .../source-map.json | 8 +- .../source-map.json | 8 +- .../input-source-map/source-map.json | 8 +- packages/babel-generator/package.json | 2 +- packages/babel-generator/src/buffer.ts | 81 ++++-- .../babel-generator/src/generators/methods.ts | 95 +++++- .../babel-generator/src/generators/types.ts | 4 + .../src/generators/typescript.ts | 9 +- packages/babel-generator/src/index.ts | 2 + packages/babel-generator/src/printer.ts | 14 +- packages/babel-generator/src/source-map.ts | 88 +++++- .../sourcemaps/call-identifiers/output.js | 2 +- .../function-identifier-name/input.js | 61 ++++ .../function-identifier-name/options.json | 4 + .../function-identifier-name/output.js | 53 ++++ .../function-identifier-name/source-map.json | 21 ++ .../real-world-babel-file1/source-map.json | 2 +- .../real-world-babel-file2/source-map.json | 2 +- packages/babel-generator/test/index.js | 272 ++++++++++++++---- .../sourcemap/declaration-loc/source-map.json | 5 +- .../misc/reference-source-map/source-map.json | 13 +- .../fixtures/strict/import/source-map.json | 6 +- .../sourcemaps/JSXText/source-map.json | 6 +- .../arguments-source-maps/source-map.json | 7 +- .../this-source-maps/source-map.json | 3 +- scripts/integration-tests/e2e-jest.sh | 6 + yarn.lock | 33 ++- 38 files changed, 737 insertions(+), 177 deletions(-) create mode 100644 packages/babel-generator/test/fixtures/sourcemaps/function-identifier-name/input.js create mode 100644 packages/babel-generator/test/fixtures/sourcemaps/function-identifier-name/options.json create mode 100644 packages/babel-generator/test/fixtures/sourcemaps/function-identifier-name/output.js create mode 100644 packages/babel-generator/test/fixtures/sourcemaps/function-identifier-name/source-map.json diff --git a/packages/babel-cli/package.json b/packages/babel-cli/package.json index 56dd45c0ee92..1a6fe5a739b7 100644 --- a/packages/babel-cli/package.json +++ b/packages/babel-cli/package.json @@ -24,7 +24,7 @@ "compiler" ], "dependencies": { - "@jridgewell/trace-mapping": "^0.3.8", + "@jridgewell/trace-mapping": "^0.3.17", "commander": "^4.0.1", "convert-source-map": "^1.1.0", "fs-readdir-recursive": "^1.1.0", diff --git a/packages/babel-cli/test/fixtures/babel/filename-sourcemap --out-file --source-maps inline/out-files/script2.js b/packages/babel-cli/test/fixtures/babel/filename-sourcemap --out-file --source-maps inline/out-files/script2.js index c25911f046e9..6c90cf21568f 100644 --- a/packages/babel-cli/test/fixtures/babel/filename-sourcemap --out-file --source-maps inline/out-files/script2.js +++ b/packages/babel-cli/test/fixtures/babel/filename-sourcemap --out-file --source-maps inline/out-files/script2.js @@ -4,4 +4,4 @@ arr.map(function (x) { return x * MULTIPLIER; }); -//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2NyaXB0Mi5qcyIsIm5hbWVzIjpbImFyciIsIngiXSwic291cmNlcyI6WyJvcmlnaW5hbC5qcyJdLCJzb3VyY2VzQ29udGVudCI6WyJ2YXIgZm9vID0gKCkgPT4gNDsiXSwibWFwcGluZ3MiOiI7O0FBQUFBO0VBQUEsT0FBVUMsYyJ9 \ No newline at end of file +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2NyaXB0Mi5qcyIsIm5hbWVzIjpbImFyciIsIm1hcCIsIngiLCJNVUxUSVBMSUVSIl0sInNvdXJjZXMiOlsib3JpZ2luYWwuanMiXSwic291cmNlc0NvbnRlbnQiOlsidmFyIGZvbyA9ICgpID0+IDQ7Il0sIm1hcHBpbmdzIjoiOztBQUFBQSxHQUFBLENBQUFDLEdBQUEsV0FBQUMsQ0FBQTtFQUFBLE9BQVVBLENBQUEsR0FBQUMsVSJ9 \ No newline at end of file diff --git a/packages/babel-core/package.json b/packages/babel-core/package.json index 060d58b0906a..e692ef4e8d5c 100644 --- a/packages/babel-core/package.json +++ b/packages/babel-core/package.json @@ -46,7 +46,7 @@ "./src/transform-file.ts": "./src/transform-file-browser.ts" }, "dependencies": { - "@ampproject/remapping": "^2.1.0", + "@ampproject/remapping": "^2.2.0", "@babel/code-frame": "workspace:^", "@babel/generator": "workspace:^", "@babel/helper-compilation-targets": "workspace:^", @@ -68,7 +68,7 @@ "@babel/plugin-transform-flow-strip-types": "workspace:^", "@babel/plugin-transform-modules-commonjs": "workspace:^", "@babel/preset-env": "workspace:^", - "@jridgewell/trace-mapping": "^0.3.8", + "@jridgewell/trace-mapping": "^0.3.17", "@types/convert-source-map": "^1.5.1", "@types/debug": "^4.1.0", "@types/gensync": "^1.0.0", diff --git a/packages/babel-core/src/transformation/file/generate.ts b/packages/babel-core/src/transformation/file/generate.ts index 6be562b1d54a..a0ef5fd06a5e 100644 --- a/packages/babel-core/src/transformation/file/generate.ts +++ b/packages/babel-core/src/transformation/file/generate.ts @@ -16,6 +16,8 @@ export default function generateCode( const { opts, ast, code, inputMap } = file; const { generatorOpts } = opts; + generatorOpts.inputSourceMap = inputMap?.toObject(); + const results = []; for (const plugins of pluginPasses) { for (const plugin of plugins) { @@ -51,18 +53,26 @@ export default function generateCode( // back to the encoded map. let { code: outputCode, decodedMap: outputMap = result.map } = result; - if (outputMap) { - if (inputMap) { - // mergeSourceMap returns an encoded map - outputMap = mergeSourceMap( - inputMap.toObject(), - outputMap, - generatorOpts.sourceFileName, - ); - } else { - // We cannot output a decoded map, so retrieve the encoded form. Because - // the decoded form is free, it's fine to prioritize decoded first. - outputMap = result.map; + // For backwards compat. + if (result.__mergedMap) { + /** + * @see mergeSourceMap + */ + outputMap = { ...result.map }; + } else { + if (outputMap) { + if (inputMap) { + // mergeSourceMap returns an encoded map + outputMap = mergeSourceMap( + inputMap.toObject(), + outputMap, + generatorOpts.sourceFileName, + ); + } else { + // We cannot output a decoded map, so retrieve the encoded form. Because + // the decoded form is free, it's fine to prioritize decoded first. + outputMap = result.map; + } } } diff --git a/packages/babel-core/src/transformation/normalize-file.ts b/packages/babel-core/src/transformation/normalize-file.ts index 0f3f238ee006..979ebded6136 100644 --- a/packages/babel-core/src/transformation/normalize-file.ts +++ b/packages/babel-core/src/transformation/normalize-file.ts @@ -12,7 +12,6 @@ import parser from "../parser"; import cloneDeep from "./util/clone-deep"; const debug = buildDebug("babel:transform:file"); -const LARGE_INPUT_SOURCEMAP_THRESHOLD = 3_000_000; // These regexps are copied from the convert-source-map package, // but without // or /* at the beginning of the comment. @@ -81,15 +80,9 @@ export default function* normalizeFile( ) as any; const inputMapContent = fs.readFileSync( path.resolve(path.dirname(options.filename), match[1]), + "utf8", ); - if (inputMapContent.length > LARGE_INPUT_SOURCEMAP_THRESHOLD) { - debug("skip merging input map > 1 MB"); - } else { - inputMap = convertSourceMap.fromJSON( - // todo: - inputMapContent as unknown as string, - ); - } + inputMap = convertSourceMap.fromJSON(inputMapContent); } catch (err) { debug("discarding unknown file input sourcemap", err); } diff --git a/packages/babel-core/test/fixtures/transformation/source-maps/arrow-function/source-map.json b/packages/babel-core/test/fixtures/transformation/source-maps/arrow-function/source-map.json index e4e51810ff8a..aa7b3e90b2b5 100644 --- a/packages/babel-core/test/fixtures/transformation/source-maps/arrow-function/source-map.json +++ b/packages/babel-core/test/fixtures/transformation/source-maps/arrow-function/source-map.json @@ -10,5 +10,5 @@ "sourcesContent": [ "var t = x => x * x;" ], - "mappings": "AAAA,IAAIA,CAAC,GAAG,SAAJA,CAAC,CAAGC,CAAC;EAAA,OAAIA,CAAC,GAAGA,CAAC;AAAA" + "mappings": "AAAA,IAAIA,CAAC,GAAG,SAAJA,CAACA,CAAGC,CAAC;EAAA,OAAIA,CAAC,GAAGA,CAAC;AAAA" } \ No newline at end of file diff --git a/packages/babel-core/test/fixtures/transformation/source-maps/class/source-map.json b/packages/babel-core/test/fixtures/transformation/source-maps/class/source-map.json index 66ef4d8bac33..7bcd3e9de1d7 100644 --- a/packages/babel-core/test/fixtures/transformation/source-maps/class/source-map.json +++ b/packages/babel-core/test/fixtures/transformation/source-maps/class/source-map.json @@ -2,6 +2,11 @@ "version": 3, "names": [ "Test", + "babelHelpers", + "classCallCheck", + "createClass", + "key", + "get", "Error", "test", "bar" @@ -12,5 +17,5 @@ "sourcesContent": [ "class Test {\n get bar() {\n throw new Error(\"wow\");\n }\n}\n\nvar test = new Test;\ntest.bar;" ], - "mappings": "IAAMA,IAAI;EAAA;;EAAA;IAAA;EAAA;EAAA;IAAA;IAAA,KACR,YAAU;MACR,MAAM,IAAIC,KAAK,CAAC,KAAK,CAAC;IACxB;EAAC;EAAA;AAAA;AAGH,IAAIC,IAAI,GAAG,IAAIF,IAAI;AACnBE,IAAI,CAACC,GAAG" + "mappings": "IAAMA,IAAI;EAAA;;EAAA,SAAAA,KAAA;IAAAC,YAAA,CAAAC,cAAA,OAAAF,IAAA;EAAA;EAAAC,YAAA,CAAAE,WAAA,CAAAH,IAAA;IAAAI,GAAA;IAAAC,GAAA,EACR,SAAAA,CAAA,EAAU;MACR,MAAM,IAAIC,KAAK,CAAC,KAAK,CAAC;IACxB;EAAC;EAAA,OAAAN,IAAA;AAAA;AAGH,IAAIO,IAAI,GAAG,IAAIP,IAAI;AACnBO,IAAI,CAACC,GAAG" } \ No newline at end of file diff --git a/packages/babel-core/test/fixtures/transformation/source-maps/input-source-map-complex/source-map.json b/packages/babel-core/test/fixtures/transformation/source-maps/input-source-map-complex/source-map.json index 2aab281b3b1b..56dfd768ed08 100644 --- a/packages/babel-core/test/fixtures/transformation/source-maps/input-source-map-complex/source-map.json +++ b/packages/babel-core/test/fixtures/transformation/source-maps/input-source-map-complex/source-map.json @@ -1,16 +1,15 @@ { "version": 3, - "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;eAsFA;EACAA;EACAC;IACA;MACAC;IACA;EACA;AACA", "names": [ "name", "data", "msg" ], - "sourceRoot": "src/components", "sources": [ - "HelloWorld.vue" + "src/components/HelloWorld.vue" ], "sourcesContent": [ "\n\n\n\n\n\n" - ] + ], + "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;eAsFA;EACAA,IAAA;EACAC,KAAA;IACA;MACAC,GAAA;IACA;EACA;AACA,G" } \ No newline at end of file diff --git a/packages/babel-core/test/fixtures/transformation/source-maps/input-source-map-external/source-map.json b/packages/babel-core/test/fixtures/transformation/source-maps/input-source-map-external/source-map.json index 1b9392bc5377..aa80cf5ef409 100644 --- a/packages/babel-core/test/fixtures/transformation/source-maps/input-source-map-external/source-map.json +++ b/packages/babel-core/test/fixtures/transformation/source-maps/input-source-map-external/source-map.json @@ -1,11 +1,13 @@ { "version": 3, - "mappings": "AAAA,UAAU,Y;SAAM,C;CAAC", - "names": [], + "names": [ + "foo" + ], "sources": [ "original.js" ], "sourcesContent": [ "var foo = () => 4;" - ] + ], + "mappings": "AAAA,IAAAA,GAAA,GAAU,SAAAA,CAAA,E;SAAM,C;CAAC" } \ No newline at end of file diff --git a/packages/babel-core/test/fixtures/transformation/source-maps/input-source-map-multiple-output-sources-complete-replace/source-map.json b/packages/babel-core/test/fixtures/transformation/source-maps/input-source-map-multiple-output-sources-complete-replace/source-map.json index 050799fd70f9..a5f1938f9f60 100644 --- a/packages/babel-core/test/fixtures/transformation/source-maps/input-source-map-multiple-output-sources-complete-replace/source-map.json +++ b/packages/babel-core/test/fixtures/transformation/source-maps/input-source-map-multiple-output-sources-complete-replace/source-map.json @@ -1,13 +1,17 @@ { "version": 3, - "mappings": "AAAC,KAAG;ACAJ,KAAG", "names": [], "sources": [ + "input.tsx", + "source-maps/input-source-map-multiple-output-sources-complete-replace/input.js", "bar.js", "baz.js" ], "sourcesContent": [ + "foo(1);\nfunction foo(bar: number): never {\n throw new Error('Intentional.');\n}", + "foo(1);\nfunction foo(bar) {\n throw new Error('Intentional.');\n}\n//# sourceMappingURL=input.js.map", "", "baz();" - ] + ], + "mappings": "AAAA,KAAI;AAAJ,KAAG" } \ No newline at end of file diff --git a/packages/babel-core/test/fixtures/transformation/source-maps/input-source-map-multiple-output-sources/source-map.json b/packages/babel-core/test/fixtures/transformation/source-maps/input-source-map-multiple-output-sources/source-map.json index fd627dac5f6b..2a794dfd9964 100644 --- a/packages/babel-core/test/fixtures/transformation/source-maps/input-source-map-multiple-output-sources/source-map.json +++ b/packages/babel-core/test/fixtures/transformation/source-maps/input-source-map-multiple-output-sources/source-map.json @@ -1,17 +1,19 @@ { "version": 3, - "mappings": "AAAC,KAAG;ACCJ,SAASA,GAAG,CAACC,GAAW;EACpB,MAAM,IAAIC,KAAK,CAAC,cAAc,CAAC;AACnC", "names": [ "foo", "bar", "Error" ], "sources": [ - "test.js", - "input.tsx" + "input.tsx", + "source-maps/input-source-map-multiple-output-sources/input.js", + "test.js" ], "sourcesContent": [ - "", - "foo(1);\nfunction foo(bar: number): never {\n throw new Error('Intentional.');\n}" - ] + "foo(1);\nfunction foo(bar: number): never {\n throw new Error('Intentional.');\n}", + "foo(1);\nfunction foo(bar) {\n throw new Error('Intentional.');\n}\n//# sourceMappingURL=input.js.map", + "" + ], + "mappings": "AAAA,KAAI;AACJ,SAASA,GAAGA,CAACC,GAAW;EACpB,MAAM,IAAIC,KAAK,CAAC,cAAc,CAAC;AACnC" } \ No newline at end of file diff --git a/packages/babel-core/test/fixtures/transformation/source-maps/input-source-map-same-location/source-map.json b/packages/babel-core/test/fixtures/transformation/source-maps/input-source-map-same-location/source-map.json index 0dde70b60b7c..c90ac92dd77c 100644 --- a/packages/babel-core/test/fixtures/transformation/source-maps/input-source-map-same-location/source-map.json +++ b/packages/babel-core/test/fixtures/transformation/source-maps/input-source-map-same-location/source-map.json @@ -1,11 +1,13 @@ { "version": 3, - "mappings": "AAAA,UAAU,Y;SAAM,C;CAAC", - "names": [], + "names": [ + "foo" + ], "sources": [ "source-maps/input-source-map-same-location/input.js" ], "sourcesContent": [ "var foo = () => 4;" - ] + ], + "mappings": "AAAA,IAAAA,GAAA,GAAU,SAAAA,CAAA,E;SAAM,C;CAAC" } \ No newline at end of file diff --git a/packages/babel-core/test/fixtures/transformation/source-maps/input-source-map-sources-complete-replace/source-map.json b/packages/babel-core/test/fixtures/transformation/source-maps/input-source-map-sources-complete-replace/source-map.json index 4a26e2136a38..eb6d4a8e5c3e 100644 --- a/packages/babel-core/test/fixtures/transformation/source-maps/input-source-map-sources-complete-replace/source-map.json +++ b/packages/babel-core/test/fixtures/transformation/source-maps/input-source-map-sources-complete-replace/source-map.json @@ -1,11 +1,15 @@ { "version": 3, - "mappings": "AAAC,KAAG", "names": [], "sources": [ + "input.tsx", + "source-maps/input-source-map-sources-complete-replace/input.js", "test.js" ], "sourcesContent": [ + "foo(1);\nfunction foo(bar: number): never {\n throw new Error('Intentional.');\n}", + "foo(1);\nfunction foo(bar) {\n throw new Error('Intentional.');\n}\n//# sourceMappingURL=input.js.map", "" - ] + ], + "mappings": "AAAA,KAAI" } \ No newline at end of file diff --git a/packages/babel-core/test/fixtures/transformation/source-maps/input-source-map/source-map.json b/packages/babel-core/test/fixtures/transformation/source-maps/input-source-map/source-map.json index 1b9392bc5377..aa80cf5ef409 100644 --- a/packages/babel-core/test/fixtures/transformation/source-maps/input-source-map/source-map.json +++ b/packages/babel-core/test/fixtures/transformation/source-maps/input-source-map/source-map.json @@ -1,11 +1,13 @@ { "version": 3, - "mappings": "AAAA,UAAU,Y;SAAM,C;CAAC", - "names": [], + "names": [ + "foo" + ], "sources": [ "original.js" ], "sourcesContent": [ "var foo = () => 4;" - ] + ], + "mappings": "AAAA,IAAAA,GAAA,GAAU,SAAAA,CAAA,E;SAAM,C;CAAC" } \ No newline at end of file diff --git a/packages/babel-generator/package.json b/packages/babel-generator/package.json index e251cdf3032b..149cf41ffd74 100644 --- a/packages/babel-generator/package.json +++ b/packages/babel-generator/package.json @@ -21,12 +21,12 @@ "dependencies": { "@babel/types": "workspace:^", "@jridgewell/gen-mapping": "^0.3.2", + "@jridgewell/trace-mapping": "^0.3.17", "jsesc": "condition: BABEL_8_BREAKING ? ^3.0.2 : ^2.5.1" }, "devDependencies": { "@babel/helper-fixtures": "workspace:^", "@babel/parser": "workspace:^", - "@jridgewell/trace-mapping": "^0.3.8", "@types/jsesc": "^2.5.0", "charcodes": "^0.2.0" }, diff --git a/packages/babel-generator/src/buffer.ts b/packages/babel-generator/src/buffer.ts index ab83d2ba408b..6a9d61dfd4ec 100644 --- a/packages/babel-generator/src/buffer.ts +++ b/packages/babel-generator/src/buffer.ts @@ -8,22 +8,23 @@ export type Pos = { export type Loc = { start?: Pos; end?: Pos; - identifierName?: string; filename?: string; }; type SourcePos = { - identifierName: string | undefined; line: number | undefined; column: number | undefined; + identifierName: string | undefined; filename: string | undefined; }; +type InternalSourcePos = SourcePos & { identifierNamePos: Pos }; type QueueItem = { char: number; repeat: number; line: number | undefined; column: number | undefined; - identifierName: string | undefined; + identifierName: undefined; // Not used, it always undefined. + identifierNamePos: undefined; // Not used, it always undefined. filename: string | undefined; }; @@ -41,13 +42,15 @@ export default class Buffer { _last = 0; _queue: QueueItem[] = []; _queueCursor = 0; + _canMarkIdName = true; _position = { line: 1, column: 0, }; - _sourcePosition: SourcePos = { + _sourcePosition: InternalSourcePos = { identifierName: undefined, + identifierNamePos: undefined, line: undefined, column: undefined, filename: undefined, @@ -63,6 +66,7 @@ export default class Buffer { line: undefined, column: undefined, identifierName: undefined, + identifierNamePos: undefined, filename: "", }); } @@ -73,7 +77,6 @@ export default class Buffer { repeat: number, line: number | undefined, column: number | undefined, - identifierName: string | undefined, filename: string | undefined, ) { const cursor = this._queueCursor; @@ -85,7 +88,6 @@ export default class Buffer { item.repeat = repeat; item.line = line; item.column = column; - item.identifierName = identifierName; item.filename = filename; this._queueCursor++; @@ -112,7 +114,12 @@ export default class Buffer { code: (this._buf + this._str).trimRight(), // Decoded sourcemap is free to generate. decodedMap: map?.getDecoded(), - + // Used as a marker for backwards compatibility. We moved input map merging + // into the generator. We cannot merge the input map a second time, so the + // presence of this field tells us we've already done the work. + get __mergedMap() { + return this.map; + }, // Encoding the sourcemap is moderately CPU expensive. get map() { const resultMap = map ? map.get() : null; @@ -173,7 +180,6 @@ export default class Buffer { 1, sourcePosition.line, sourcePosition.column, - sourcePosition.identifierName, sourcePosition.filename, ); } @@ -182,7 +188,7 @@ export default class Buffer { * Same as queue, but this indentation will never have a sourcemap marker. */ queueIndentation(char: number, repeat: number): void { - this._pushQueue(char, repeat, undefined, undefined, undefined, undefined); + this._pushQueue(char, repeat, undefined, undefined, undefined); } _flush(): void { @@ -195,7 +201,11 @@ export default class Buffer { this._queueCursor = 0; } - _appendChar(char: number, repeat: number, sourcePos: SourcePos): void { + _appendChar( + char: number, + repeat: number, + sourcePos: InternalSourcePos, + ): void { this._last = char; this._str += @@ -208,6 +218,7 @@ export default class Buffer { sourcePos.line, sourcePos.column, sourcePos.identifierName, + sourcePos.identifierNamePos, sourcePos.filename, ); this._position.column += repeat; @@ -215,9 +226,18 @@ export default class Buffer { this._position.line++; this._position.column = 0; } + + if (this._canMarkIdName) { + sourcePos.identifierName = undefined; + sourcePos.identifierNamePos = undefined; + } } - _append(str: string, sourcePos: SourcePos, maybeNewline: boolean): void { + _append( + str: string, + sourcePos: InternalSourcePos, + maybeNewline: boolean, + ): void { const len = str.length; const position = this._position; @@ -237,9 +257,17 @@ export default class Buffer { return; } - const { column, identifierName, filename } = sourcePos; + const { column, identifierName, identifierNamePos, filename } = sourcePos; let line = sourcePos.line; + if ( + (identifierName != null || identifierNamePos != null) && + this._canMarkIdName + ) { + sourcePos.identifierName = undefined; + sourcePos.identifierNamePos = undefined; + } + // Search for newline chars. We search only for `\n`, since both `\r` and // `\r\n` are normalized to `\n` during parse. We exclude `\u2028` and // `\u2029` for performance reasons, they're so uncommon that it's probably @@ -250,7 +278,7 @@ export default class Buffer { // If the string starts with a newline char, then adding a mark is redundant. // This catches both "no newlines" and "newline after several chars". if (i !== 0) { - this._mark(line, column, identifierName, filename); + this._mark(line, column, identifierName, identifierNamePos, filename); } // Now, find each remaining newline char in the string. @@ -263,7 +291,7 @@ export default class Buffer { // unless this is the last char. // When manually adding multi-line content (such as a comment), `line` will be `undefined`. if (last < len && line !== undefined) { - this._mark(++line, 0, identifierName, filename); + this._mark(++line, 0, null, null, filename); } i = str.indexOf("\n", last); } @@ -274,9 +302,17 @@ export default class Buffer { line: number | undefined, column: number | undefined, identifierName: string | undefined, + identifierNamePos: Pos | undefined, filename: string | undefined, ): void { - this._map?.mark(this._position, line, column, identifierName, filename); + this._map?.mark( + this._position, + line, + column, + identifierName, + identifierNamePos, + filename, + ); } removeTrailingNewline(): void { @@ -377,9 +413,20 @@ export default class Buffer { if (!this._map) return cb(); this.source("start", loc); - + // @ts-expect-error identifierName is not defined + const identifierName = loc.identifierName; + const sourcePos = this._sourcePosition; + if (identifierName) { + this._canMarkIdName = false; + sourcePos.identifierName = identifierName; + } cb(); + if (identifierName) { + this._canMarkIdName = true; + sourcePos.identifierName = undefined; + sourcePos.identifierNamePos = undefined; + } this.source("end", loc); } @@ -428,8 +475,6 @@ export default class Buffer { const pos = loc[prop]; const target = this._sourcePosition; - target.identifierName = - (prop === "start" && loc.identifierName) || undefined; if (pos) { target.line = pos.line + lineOffset; target.column = pos.column + columnOffset; diff --git a/packages/babel-generator/src/generators/methods.ts b/packages/babel-generator/src/generators/methods.ts index e8a94da32898..e6beb1770440 100644 --- a/packages/babel-generator/src/generators/methods.ts +++ b/packages/babel-generator/src/generators/methods.ts @@ -1,12 +1,23 @@ import type Printer from "../printer"; -import { isIdentifier } from "@babel/types"; import type * as t from "@babel/types"; +import { isIdentifier } from "@babel/types"; +import type { NodePath } from "@babel/traverse"; export function _params( this: Printer, node: t.Function | t.TSDeclareMethod | t.TSDeclareFunction, + idNode: t.Expression | t.PrivateName, + parentNode: NodePath< + t.Function | t.TSDeclareMethod | t.TSDeclareFunction + >["parent"], ) { this.print(node.typeParameters, node); + + const nameInfo = _getFuncIdName.call(this, idNode, parentNode); + if (nameInfo) { + this.sourceIdentifierName(nameInfo.name, nameInfo.pos); + } + this.token("("); this._parameters(node.params, node); this.token(")"); @@ -106,7 +117,11 @@ export function _methodHead(this: Printer, node: t.Method | t.TSDeclareMethod) { this.token("?"); } - this._params(node); + this._params( + node, + node.computed && node.key.type !== "StringLiteral" ? undefined : node.key, + undefined, + ); } export function _predicate( @@ -129,6 +144,9 @@ export function _predicate( export function _functionHead( this: Printer, node: t.FunctionDeclaration | t.FunctionExpression | t.TSDeclareFunction, + parent: NodePath< + t.FunctionDeclaration | t.FunctionExpression | t.TSDeclareFunction + >["parent"], ) { if (node.async) { this.word("async"); @@ -152,14 +170,18 @@ export function _functionHead( this.print(node.id, node); } - this._params(node); + this._params(node, node.id, parent); if (node.type !== "TSDeclareFunction") { this._predicate(node); } } -export function FunctionExpression(this: Printer, node: t.FunctionExpression) { - this._functionHead(node); +export function FunctionExpression( + this: Printer, + node: t.FunctionExpression, + parent: NodePath["parent"], +) { + this._functionHead(node, parent); this.space(); this.print(node.body, node); } @@ -169,6 +191,7 @@ export { FunctionExpression as FunctionDeclaration }; export function ArrowFunctionExpression( this: Printer, node: t.ArrowFunctionExpression, + parent: NodePath["parent"], ) { if (node.async) { this.word("async", true); @@ -186,7 +209,7 @@ export function ArrowFunctionExpression( ) { this.print(firstParam, node, true); } else { - this._params(node); + this._params(node, undefined, parent); } this._predicate(node, true); @@ -217,3 +240,63 @@ function hasTypesOrComments( param.trailingComments?.length ); } + +function _getFuncIdName( + this: Printer, + idNode: t.Expression | t.PrivateName, + parent: NodePath< + t.Function | t.TSDeclareMethod | t.TSDeclareFunction + >["parent"], +) { + let id: t.Expression | t.PrivateName | t.LVal = idNode; + + if (!id && parent) { + const parentType = parent.type; + + if (parentType === "VariableDeclarator") { + id = parent.id; + } else if ( + parentType === "AssignmentExpression" || + parentType === "AssignmentPattern" + ) { + id = parent.left; + } else if ( + parentType === "ObjectProperty" || + parentType === "ClassProperty" + ) { + if (!parent.computed || parent.key.type === "StringLiteral") { + id = parent.key; + } + } else if ( + parentType === "ClassPrivateProperty" || + parentType === "ClassAccessorProperty" + ) { + id = parent.key; + } + } + + if (!id) return; + + let nameInfo; + + if (id.type === "Identifier") { + nameInfo = { + pos: id.loc?.start, + name: + // @ts-expect-error Undocumented property identifierName + id.loc?.identifierName || id.name, + }; + } else if (id.type === "PrivateName") { + nameInfo = { + pos: id.loc?.start, + name: "#" + id.id.name, + }; + } else if (id.type === "StringLiteral") { + nameInfo = { + pos: id.loc?.start, + name: id.value, + }; + } + + return nameInfo; +} diff --git a/packages/babel-generator/src/generators/types.ts b/packages/babel-generator/src/generators/types.ts index ce9addd525f0..30d98f99a2f9 100644 --- a/packages/babel-generator/src/generators/types.ts +++ b/packages/babel-generator/src/generators/types.ts @@ -4,6 +4,10 @@ import type * as t from "@babel/types"; import jsesc from "jsesc"; export function Identifier(this: Printer, node: t.Identifier) { + this.sourceIdentifierName( + // @ts-expect-error Undocumented property identifierName + node.loc?.identifierName || node.name, + ); this.word(node.name); } diff --git a/packages/babel-generator/src/generators/typescript.ts b/packages/babel-generator/src/generators/typescript.ts index 54da4a4e0f67..c5585c555bd0 100644 --- a/packages/babel-generator/src/generators/typescript.ts +++ b/packages/babel-generator/src/generators/typescript.ts @@ -1,5 +1,6 @@ import type Printer from "../printer"; import type * as t from "@babel/types"; +import type { NodePath } from "@babel/traverse"; export function TSTypeAnnotation(this: Printer, node: t.TSTypeAnnotation) { this.token(":"); @@ -73,12 +74,16 @@ export function TSParameterProperty( this._param(node.parameter); } -export function TSDeclareFunction(this: Printer, node: t.TSDeclareFunction) { +export function TSDeclareFunction( + this: Printer, + node: t.TSDeclareFunction, + parent: NodePath["parent"], +) { if (node.declare) { this.word("declare"); this.space(); } - this._functionHead(node); + this._functionHead(node, parent); this.token(";"); } diff --git a/packages/babel-generator/src/index.ts b/packages/babel-generator/src/index.ts index f0ba5bd74855..d56db075a50b 100644 --- a/packages/babel-generator/src/index.ts +++ b/packages/babel-generator/src/index.ts @@ -182,6 +182,8 @@ export interface GeneratorOptions { */ sourceMaps?: boolean; + inputSourceMap?: any; + /** * A root for all relative URLs in the source map. */ diff --git a/packages/babel-generator/src/printer.ts b/packages/babel-generator/src/printer.ts index 73386493da1f..95f237bd6612 100644 --- a/packages/babel-generator/src/printer.ts +++ b/packages/babel-generator/src/printer.ts @@ -1,4 +1,4 @@ -import Buffer from "./buffer"; +import Buffer, { type Pos } from "./buffer"; import type { Loc } from "./buffer"; import * as n from "./node"; import type * as t from "@babel/types"; @@ -18,6 +18,7 @@ import type { Opts as jsescOptions } from "jsesc"; import * as generatorFunctions from "./generators"; import type SourceMap from "./source-map"; import * as charCodes from "charcodes"; +import { type TraceMap } from "@jridgewell/trace-mapping"; const SCIENTIFIC_NOTATION = /e/i; const ZERO_DECIMAL_INTEGER = /\.0+$/; @@ -101,7 +102,10 @@ class Printer { this._indentChar = format.indent.style.charCodeAt(0); this._indentRepeat = format.indent.style.length; + + this._inputMap = map?._inputMap; } + declare _inputMap: TraceMap; declare format: Format; inForStatementInitCounter: number = 0; @@ -364,6 +368,14 @@ class Printer { this._buf.withSource(prop, loc, cb); } + sourceIdentifierName(identifierName: string, pos?: Pos): void { + if (!this._buf._canMarkIdName) return; + + const sourcePosition = this._buf._sourcePosition; + sourcePosition.identifierNamePos = pos; + sourcePosition.identifierName = identifierName; + } + _space(): void { this._queue(charCodes.space); } diff --git a/packages/babel-generator/src/source-map.ts b/packages/babel-generator/src/source-map.ts index 421bccf9d422..634b41fb60e0 100644 --- a/packages/babel-generator/src/source-map.ts +++ b/packages/babel-generator/src/source-map.ts @@ -13,6 +13,12 @@ import type { Mapping, } from "@jridgewell/gen-mapping"; +import { + type SourceMapInput, + originalPositionFor, + TraceMap, +} from "@jridgewell/trace-mapping"; + /** * Build a sourcemap. */ @@ -30,24 +36,44 @@ export default class SourceMap { // inits to an impossible value. So init to 0 is fine. private _lastSourceColumn = 0; + public _inputMap: TraceMap; + constructor( - opts: { sourceFileName?: string; sourceRoot?: string }, + opts: { + sourceFileName?: string; + sourceRoot?: string; + inputSourceMap?: SourceMapInput; + }, code: string | { [sourceFileName: string]: string }, ) { const map = (this._map = new GenMapping({ sourceRoot: opts.sourceRoot })); this._sourceFileName = opts.sourceFileName?.replace(/\\/g, "/"); this._rawMappings = undefined; - if (typeof code === "string") { + if (opts.inputSourceMap) { + this._inputMap = new TraceMap(opts.inputSourceMap); + const resolvedSources = this._inputMap.resolvedSources; + if (resolvedSources.length) { + for (let i = 0; i < resolvedSources.length; i++) { + setSourceContent( + map, + resolvedSources[i], + this._inputMap.sourcesContent[i], + ); + } + } + } + + if (typeof code === "string" && !opts.inputSourceMap) { setSourceContent(map, this._sourceFileName, code); } else if (typeof code === "object") { - Object.keys(code).forEach(sourceFileName => { + for (const sourceFileName of Object.keys(code)) { setSourceContent( map, sourceFileName.replace(/\\/g, "/"), code[sourceFileName], ); - }); + } } } @@ -76,24 +102,56 @@ export default class SourceMap { line: number, column: number, identifierName?: string | null, + identifierNamePos?: { line: number; column: number }, filename?: string | null, ) { this._rawMappings = undefined; + let originalMapping: { + source: string | null; + name?: string | null; + line: number | null; + column: number | null; + }; + + if (line != null) { + if (this._inputMap) { + // This is the lookup for this mark + originalMapping = originalPositionFor(this._inputMap, { + line, + column, + }); + + // If the we found a name, nothing else needs to be done + // Maybe we're marking a `(` and the input map already had a name attached there, + // or we're marking a `(` and the sourcemap spanned a `foo(`, + // or we're marking an identifier, etc. + if (!originalMapping.name && identifierNamePos) { + // We're trying to mark a `(` (as that's the only thing that provides + // an identifierNamePos currently), and we the AST had an identifier attached. + // Lookup it's original name. + const originalIdentifierMapping = originalPositionFor( + this._inputMap, + identifierNamePos, + ); + if (originalIdentifierMapping.name) { + identifierName = originalIdentifierMapping.name; + } + } + } else { + originalMapping = { + source: filename?.replace(/\\/g, "/") || this._sourceFileName, + line: line, + column: column, + }; + } + } + maybeAddMapping(this._map, { name: identifierName, generated, - source: - line == null - ? undefined - : filename?.replace(/\\/g, "/") || this._sourceFileName, - original: - line == null - ? undefined - : { - line: line, - column: column, - }, + source: originalMapping?.source, + original: originalMapping, }); } } diff --git a/packages/babel-generator/test/fixtures/sourcemaps/call-identifiers/output.js b/packages/babel-generator/test/fixtures/sourcemaps/call-identifiers/output.js index 2aa2d3b2b022..f913bd9810df 100644 --- a/packages/babel-generator/test/fixtures/sourcemaps/call-identifiers/output.js +++ b/packages/babel-generator/test/fixtures/sourcemaps/call-identifiers/output.js @@ -13,4 +13,4 @@ obj.foo().bar; obj.foo(); obj.foo.bar; obj.foo().bar; -} +} \ No newline at end of file diff --git a/packages/babel-generator/test/fixtures/sourcemaps/function-identifier-name/input.js b/packages/babel-generator/test/fixtures/sourcemaps/function-identifier-name/input.js new file mode 100644 index 000000000000..5df8f3f4b966 --- /dev/null +++ b/packages/babel-generator/test/fixtures/sourcemaps/function-identifier-name/input.js @@ -0,0 +1,61 @@ +function fn() {} + +export default function () {} + +var a = { + fn() {}, + fn:function() {}, + [fn]:function() {}, + ["fn"]:function() {}, + [function() {}]:function() {}, + [()=> {}]:function() {}, + [fn]() { }, + ["fn"]() { }, + [function() {}]() { }, + [()=> {}]() { } +} + +class b { + fn() {}; + fn=function() {}; + [fn]=function() {}; + ["fn"]=function() {}; + [function() {}]=function() {}; + [()=> {}]=function() {}; + [fn]() { }; + ["fn"]() { }; + [function() {}]() { }; + [()=> {}]() { }; + #x = function() {}; + accessor y = function() {} +} + +var aa = { + fn:function a() {}, + [fn]:function a() {}, + ["fn"]:function a() {}, + [function() {}]:function a() {}, + [()=> {}]:function a() {}, +} + +class bb { + fn=function a() {}; + [fn]=function a() {}; + ["fn"]=function a() {}; + [function() {}]=function a() {}; + [()=> {}]=function a() {}; +} + +var x = function fn() {}; +var x = function () {}; + +(function fn() {}); + +var z = () => {}; +var z = x => {}; +var z = (x) => {}; +var z = (x, y, z) => {}; + +x = function() {}; + +( { x = function() {} } = {}); diff --git a/packages/babel-generator/test/fixtures/sourcemaps/function-identifier-name/options.json b/packages/babel-generator/test/fixtures/sourcemaps/function-identifier-name/options.json new file mode 100644 index 000000000000..5a346a8a5cf6 --- /dev/null +++ b/packages/babel-generator/test/fixtures/sourcemaps/function-identifier-name/options.json @@ -0,0 +1,4 @@ +{ + "sourceMaps": true, + "plugins": ["decoratorAutoAccessors"] +} diff --git a/packages/babel-generator/test/fixtures/sourcemaps/function-identifier-name/output.js b/packages/babel-generator/test/fixtures/sourcemaps/function-identifier-name/output.js new file mode 100644 index 000000000000..5d815fb69740 --- /dev/null +++ b/packages/babel-generator/test/fixtures/sourcemaps/function-identifier-name/output.js @@ -0,0 +1,53 @@ +function fn() {} +export default function () {} +var a = { + fn() {}, + fn: function () {}, + [fn]: function () {}, + ["fn"]: function () {}, + [function () {}]: function () {}, + [() => {}]: function () {}, + [fn]() {}, + ["fn"]() {}, + [function () {}]() {}, + [() => {}]() {} +}; +class b { + fn() {} + fn = function () {}; + [fn] = function () {}; + ["fn"] = function () {}; + [function () {}] = function () {}; + [() => {}] = function () {}; + [fn]() {} + ["fn"]() {} + [function () {}]() {} + [() => {}]() {} + #x = function () {}; + accessor y = function () {}; +} +var aa = { + fn: function a() {}, + [fn]: function a() {}, + ["fn"]: function a() {}, + [function () {}]: function a() {}, + [() => {}]: function a() {} +}; +class bb { + fn = function a() {}; + [fn] = function a() {}; + ["fn"] = function a() {}; + [function () {}] = function a() {}; + [() => {}] = function a() {}; +} +var x = function fn() {}; +var x = function () {}; +(function fn() {}); +var z = () => {}; +var z = x => {}; +var z = x => {}; +var z = (x, y, z) => {}; +x = function () {}; +({ + x = function () {} +} = {}); \ No newline at end of file diff --git a/packages/babel-generator/test/fixtures/sourcemaps/function-identifier-name/source-map.json b/packages/babel-generator/test/fixtures/sourcemaps/function-identifier-name/source-map.json new file mode 100644 index 000000000000..e32aa61af2c3 --- /dev/null +++ b/packages/babel-generator/test/fixtures/sourcemaps/function-identifier-name/source-map.json @@ -0,0 +1,21 @@ +{ + "version": 3, + "names": [ + "fn", + "a", + "b", + "x", + "#x", + "y", + "aa", + "bb", + "z" + ], + "sources": [ + "fixtures/sourcemaps/function-identifier-name/input.js" + ], + "sourcesContent": [ + "function fn() {}\n\nexport default function () {}\n\nvar a = {\n fn() {},\n fn:function() {},\n [fn]:function() {},\n [\"fn\"]:function() {},\n [function() {}]:function() {},\n [()=> {}]:function() {},\n [fn]() { },\n [\"fn\"]() { },\n [function() {}]() { },\n [()=> {}]() { }\n}\n\nclass b {\n fn() {};\n fn=function() {};\n [fn]=function() {};\n [\"fn\"]=function() {};\n [function() {}]=function() {};\n [()=> {}]=function() {};\n [fn]() { };\n [\"fn\"]() { };\n [function() {}]() { };\n [()=> {}]() { };\n #x = function() {};\n accessor y = function() {}\n}\n\nvar aa = {\n fn:function a() {},\n [fn]:function a() {},\n [\"fn\"]:function a() {},\n [function() {}]:function a() {},\n [()=> {}]:function a() {},\n}\n\nclass bb {\n fn=function a() {};\n [fn]=function a() {};\n [\"fn\"]=function a() {};\n [function() {}]=function a() {};\n [()=> {}]=function a() {};\n}\n\nvar x = function fn() {};\nvar x = function () {};\n\n(function fn() {});\n\nvar z = () => {};\nvar z = x => {};\nvar z = (x) => {};\nvar z = (x, y, z) => {};\n\nx = function() {};\n\n( { x = function() {} } = {});" + ], + "mappings": "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" +} \ No newline at end of file diff --git a/packages/babel-generator/test/fixtures/sourcemaps/real-world-babel-file1/source-map.json b/packages/babel-generator/test/fixtures/sourcemaps/real-world-babel-file1/source-map.json index 7b69685247d6..090a46e57302 100644 --- a/packages/babel-generator/test/fixtures/sourcemaps/real-world-babel-file1/source-map.json +++ b/packages/babel-generator/test/fixtures/sourcemaps/real-world-babel-file1/source-map.json @@ -74,5 +74,5 @@ "sourcesContent": [ "// From packages\\babel-cli\\src\\babel\\watcher.ts\n\nimport { createRequire } from \"module\";\nimport path from \"path\";\nimport type { WatchOptions, FSWatcher } from \"chokidar\";\n\nconst fileToDeps = new Map>();\nconst depToFiles = new Map>();\n\nlet isWatchMode = false;\nlet watcher: FSWatcher;\nconst watchQueue = new Set();\nlet hasStarted = false;\n\nexport function enable({ enableGlobbing }: { enableGlobbing: boolean }) {\n isWatchMode = true;\n\n const { FSWatcher } = requireChokidar();\n\n const options: WatchOptions = {\n disableGlobbing: !enableGlobbing,\n persistent: true,\n ignoreInitial: true,\n awaitWriteFinish: {\n stabilityThreshold: 50,\n pollInterval: 10,\n },\n };\n watcher = new FSWatcher(options);\n\n watcher.on(\"unlink\", unwatchFile);\n}\n\nexport function startWatcher() {\n hasStarted = true;\n\n for (const dep of watchQueue) {\n watcher.add(dep);\n }\n watchQueue.clear();\n\n watcher.on(\"ready\", () => {\n console.log(\"The watcher is ready.\");\n });\n}\n\nexport function watch(filename: string): void {\n if (!isWatchMode) {\n throw new Error(\n \"Internal Babel error: .watch called when not in watch mode.\",\n );\n }\n\n if (!hasStarted) {\n watchQueue.add(path.resolve(filename));\n } else {\n watcher.add(path.resolve(filename));\n }\n}\n\n/**\n * Call @param callback whenever a dependency (source file)/\n * external dependency (non-source file) changes.\n *\n * Handles mapping external dependencies to their corresponding\n * dependencies.\n */\nexport function onFilesChange(\n callback: (filenames: string[], event: string, cause: string) => void,\n): void {\n if (!isWatchMode) {\n throw new Error(\n \"Internal Babel error: .onFilesChange called when not in watch mode.\",\n );\n }\n\n watcher.on(\"all\", (event, filename) => {\n if (event !== \"change\" && event !== \"add\") return;\n\n const absoluteFile = path.resolve(filename);\n callback(\n [absoluteFile, ...(depToFiles.get(absoluteFile) ?? [])],\n event,\n absoluteFile,\n );\n });\n}\n\nexport function updateExternalDependencies(\n filename: string,\n dependencies: Set,\n) {\n if (!isWatchMode) return;\n\n // Use absolute paths\n const absFilename = path.resolve(filename);\n const absDependencies = new Set(\n Array.from(dependencies, dep => path.resolve(dep)),\n );\n\n const deps = fileToDeps.get(absFilename);\n if (deps) {\n for (const dep of deps) {\n if (!absDependencies.has(dep)) {\n removeFileDependency(absFilename, dep);\n }\n }\n }\n for (const dep of absDependencies) {\n let deps = depToFiles.get(dep);\n if (!deps) {\n depToFiles.set(dep, (deps = new Set()));\n\n if (!hasStarted) {\n watchQueue.add(dep);\n } else {\n watcher.add(dep);\n }\n }\n\n deps.add(absFilename);\n }\n\n fileToDeps.set(absFilename, absDependencies);\n}\n\nfunction removeFileDependency(filename: string, dep: string) {\n const deps = depToFiles.get(dep) as Set;\n deps.delete(filename);\n\n if (deps.size === 0) {\n depToFiles.delete(dep);\n\n if (!hasStarted) {\n watchQueue.delete(dep);\n } else {\n watcher.unwatch(dep);\n }\n }\n}\n\nfunction unwatchFile(filename: string) {\n const deps = fileToDeps.get(filename);\n if (!deps) return;\n\n for (const dep of deps) {\n removeFileDependency(filename, dep);\n }\n fileToDeps.delete(filename);\n}\n\nfunction requireChokidar(): any {\n const require = createRequire(import.meta.url);\n\n try {\n return process.env.BABEL_8_BREAKING\n ? require(\"chokidar\")\n : parseInt(process.versions.node) >= 8\n ? require(\"chokidar\")\n : require(\"@nicolo-ribaudo/chokidar-2\");\n } catch (err) {\n console.error(\n \"The optional dependency chokidar failed to install and is required for \" +\n \"--watch. Chokidar is likely not supported on your platform.\",\n );\n throw err;\n }\n}" ], - "mappings": "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" + "mappings": "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" } \ No newline at end of file diff --git a/packages/babel-generator/test/fixtures/sourcemaps/real-world-babel-file2/source-map.json b/packages/babel-generator/test/fixtures/sourcemaps/real-world-babel-file2/source-map.json index 9785528535d9..9f3b1707a207 100644 --- a/packages/babel-generator/test/fixtures/sourcemaps/real-world-babel-file2/source-map.json +++ b/packages/babel-generator/test/fixtures/sourcemaps/real-world-babel-file2/source-map.json @@ -253,5 +253,5 @@ "sourcesContent": [ "// From packages\\babel-generator\\src\\printer.ts\n\nimport Buffer from \"./buffer\";\nimport type { Loc } from \"./buffer\";\nimport * as n from \"./node\";\nimport type * as t from \"@babel/types\";\nimport type {\n RecordAndTuplePluginOptions,\n PipelineOperatorPluginOptions,\n} from \"@babel/parser\";\nimport type { Opts as jsescOptions } from \"jsesc\";\n\nimport * as generatorFunctions from \"./generators\";\nimport type SourceMap from \"./source-map\";\nimport * as charCodes from \"charcodes\";\n\nconst SCIENTIFIC_NOTATION = /e/i;\nconst ZERO_DECIMAL_INTEGER = /\\.0+$/;\nconst NON_DECIMAL_LITERAL = /^0[box]/;\nconst PURE_ANNOTATION_RE = /^\\s*[@#]__PURE__\\s*$/;\n\nconst { needsParens, needsWhitespaceAfter, needsWhitespaceBefore } = n;\n\nexport type Format = {\n shouldPrintComment: (comment: string) => boolean;\n retainLines: boolean;\n retainFunctionParens: boolean;\n comments: boolean;\n auxiliaryCommentBefore: string;\n auxiliaryCommentAfter: string;\n compact: boolean | \"auto\";\n minified: boolean;\n concise: boolean;\n indent: {\n adjustMultilineComment: boolean;\n style: string;\n };\n recordAndTupleSyntaxType: RecordAndTuplePluginOptions[\"syntaxType\"];\n jsescOption: jsescOptions;\n jsonCompatibleStrings?: boolean;\n /**\n * For use with the Hack-style pipe operator.\n * Changes what token is used for pipe bodies’ topic references.\n */\n topicToken?: PipelineOperatorPluginOptions[\"topicToken\"];\n /**\n * @deprecated Removed in Babel 8\n */\n decoratorsBeforeExport?: boolean;\n};\n\ninterface AddNewlinesOptions {\n addNewlines(leading: boolean, node: t.Node): number;\n}\n\ninterface PrintSequenceOptions extends Partial {\n statement?: boolean;\n indent?: boolean;\n}\n\ninterface PrintListOptions {\n separator?: (this: Printer) => void;\n statement?: boolean;\n indent?: boolean;\n}\n\ntype PrintJoinOptions = PrintListOptions &\n PrintSequenceOptions & {\n iterator?: (node: t.Node, index: number) => void;\n };\nclass Printer {\n constructor(format: Format, map: SourceMap) {\n this.format = format;\n this._buf = new Buffer(map);\n\n this._indentChar = format.indent.style.charCodeAt(0);\n this._indentRepeat = format.indent.style.length;\n }\n\n declare format: Format;\n inForStatementInitCounter: number = 0;\n\n declare _buf: Buffer;\n _printStack: Array = [];\n _indent: number = 0;\n _indentChar: number = 0;\n _indentRepeat: number = 0;\n _insideAux: boolean = false;\n _parenPushNewlineState: { printed: boolean } | null = null;\n _noLineTerminator: boolean = false;\n _printAuxAfterOnNextUserNode: boolean = false;\n _printedComments = new Set();\n _endsWithInteger = false;\n _endsWithWord = false;\n\n generate(ast: t.Node) {\n this.print(ast);\n this._maybeAddAuxComment();\n\n return this._buf.get();\n }\n\n /**\n * Increment indent size.\n */\n\n indent(): void {\n if (this.format.compact || this.format.concise) return;\n\n this._indent++;\n }\n\n /**\n * Decrement indent size.\n */\n\n dedent(): void {\n if (this.format.compact || this.format.concise) return;\n\n this._indent--;\n }\n\n /**\n * Add a semicolon to the buffer.\n */\n\n semicolon(force: boolean = false): void {\n this._maybeAddAuxComment();\n if (force) {\n this._appendChar(charCodes.semicolon);\n } else {\n this._queue(charCodes.semicolon);\n }\n }\n\n /**\n * Add a right brace to the buffer.\n */\n\n rightBrace(): void {\n if (this.format.minified) {\n this._buf.removeLastSemicolon();\n }\n this.token(\"}\");\n }\n\n /**\n * Add a space to the buffer unless it is compact.\n */\n\n space(force: boolean = false): void {\n if (this.format.compact) return;\n\n if (force) {\n this._space();\n } else if (this._buf.hasContent()) {\n const lastCp = this.getLastChar();\n if (lastCp !== charCodes.space && lastCp !== charCodes.lineFeed) {\n this._space();\n }\n }\n }\n\n /**\n * Writes a token that can't be safely parsed without taking whitespace into account.\n */\n\n word(str: string): void {\n // prevent concatenating words and creating // comment out of division and regex\n if (\n this._endsWithWord ||\n (str.charCodeAt(0) === charCodes.slash && this.endsWith(charCodes.slash))\n ) {\n this._space();\n }\n\n this._maybeAddAuxComment();\n this._append(str, false);\n\n this._endsWithWord = true;\n }\n\n /**\n * Writes a number token so that we can validate if it is an integer.\n */\n\n number(str: string): void {\n this.word(str);\n\n // Integer tokens need special handling because they cannot have '.'s inserted\n // immediately after them.\n this._endsWithInteger =\n Number.isInteger(+str) &&\n !NON_DECIMAL_LITERAL.test(str) &&\n !SCIENTIFIC_NOTATION.test(str) &&\n !ZERO_DECIMAL_INTEGER.test(str) &&\n str.charCodeAt(str.length - 1) !== charCodes.dot;\n }\n\n /**\n * Writes a simple token.\n */\n\n token(str: string, maybeNewline = false): void {\n // space is mandatory to avoid outputting