Add sourcemap markings for each line of a string (#12086)
* Add sourcemap markings for each line of a string Fixes https://github.com/babel/babel/issues/12083 * Fix for multiple newlines * Optimize with indexOf * Comment explaining newline search
This commit is contained in:
parent
a4a14caee7
commit
f49234aa69
@ -116,30 +116,54 @@ export default class Buffer {
|
||||
filename: ?string,
|
||||
force?: boolean,
|
||||
): void {
|
||||
// If there the line is ending, adding a new mapping marker is redundant
|
||||
if (this._map && str[0] !== "\n") {
|
||||
this._map.mark(
|
||||
this._position.line,
|
||||
this._position.column,
|
||||
line,
|
||||
column,
|
||||
identifierName,
|
||||
filename,
|
||||
force,
|
||||
);
|
||||
}
|
||||
|
||||
this._buf.push(str);
|
||||
this._last = str[str.length - 1];
|
||||
|
||||
for (let i = 0; i < str.length; i++) {
|
||||
if (str[i] === "\n") {
|
||||
this._position.line++;
|
||||
this._position.column = 0;
|
||||
} else {
|
||||
this._position.column++;
|
||||
}
|
||||
// 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
|
||||
// ok. It's also unclear how other sourcemap utilities handle them...
|
||||
let i = str.indexOf("\n");
|
||||
let last = 0;
|
||||
|
||||
// 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, force);
|
||||
}
|
||||
|
||||
// Now, find each reamining newline char in the string.
|
||||
while (i !== -1) {
|
||||
this._position.line++;
|
||||
this._position.column = 0;
|
||||
last = i + 1;
|
||||
|
||||
// We mark the start of each line, which happens directly after this newline char
|
||||
// unless this is the last char.
|
||||
if (last < str.length) {
|
||||
this._mark(++line, 0, identifierName, filename, force);
|
||||
}
|
||||
i = str.indexOf("\n", last);
|
||||
}
|
||||
this._position.column += str.length - last;
|
||||
}
|
||||
|
||||
_mark(
|
||||
line: number,
|
||||
column: number,
|
||||
identifierName: ?string,
|
||||
filename: ?string,
|
||||
force?: boolean,
|
||||
): void {
|
||||
this._map?.mark(
|
||||
this._position.line,
|
||||
this._position.column,
|
||||
line,
|
||||
column,
|
||||
identifierName,
|
||||
filename,
|
||||
force,
|
||||
);
|
||||
}
|
||||
|
||||
removeTrailingNewline(): void {
|
||||
|
||||
6
packages/babel-generator/test/fixtures/sourcemaps/string-literal-newline/input.js
vendored
Normal file
6
packages/babel-generator/test/fixtures/sourcemaps/string-literal-newline/input.js
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
"before\
|
||||
after";
|
||||
|
||||
"before\
|
||||
\
|
||||
after";
|
||||
5
packages/babel-generator/test/fixtures/sourcemaps/string-literal-newline/output.js
vendored
Normal file
5
packages/babel-generator/test/fixtures/sourcemaps/string-literal-newline/output.js
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
"before\
|
||||
after";
|
||||
"before\
|
||||
\
|
||||
after";
|
||||
9
packages/babel-generator/test/fixtures/sourcemaps/string-literal-newline/source-map.json
vendored
Normal file
9
packages/babel-generator/test/fixtures/sourcemaps/string-literal-newline/source-map.json
vendored
Normal file
@ -0,0 +1,9 @@
|
||||
{
|
||||
"mappings": "AAAA;AACA,MADA;AAGA;AACA;AACA,MAFA",
|
||||
"names": [],
|
||||
"sources": ["fixtures/sourcemaps/string-literal-newline/input.js"],
|
||||
"sourcesContent": [
|
||||
"\"before\\\nafter\";\n\n\"before\\\n\\\nafter\";"
|
||||
],
|
||||
"version": 3
|
||||
}
|
||||
27
packages/babel-generator/test/fixtures/sourcemaps/template-literal-newline/input.js
vendored
Normal file
27
packages/babel-generator/test/fixtures/sourcemaps/template-literal-newline/input.js
vendored
Normal file
@ -0,0 +1,27 @@
|
||||
// Newline
|
||||
`before
|
||||
after`;
|
||||
|
||||
// Newline newline
|
||||
`before
|
||||
|
||||
after`;
|
||||
|
||||
// Newline LineContinuation
|
||||
`before
|
||||
\
|
||||
after`;
|
||||
|
||||
// LineContinuation
|
||||
`before\
|
||||
after`;
|
||||
|
||||
// LineContinuation newline
|
||||
`before\
|
||||
|
||||
after`;
|
||||
|
||||
// LineContinuation LineContinuation
|
||||
`before\
|
||||
\
|
||||
after`;
|
||||
22
packages/babel-generator/test/fixtures/sourcemaps/template-literal-newline/output.js
vendored
Normal file
22
packages/babel-generator/test/fixtures/sourcemaps/template-literal-newline/output.js
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
// Newline
|
||||
`before
|
||||
after`; // Newline newline
|
||||
|
||||
`before
|
||||
|
||||
after`; // Newline LineContinuation
|
||||
|
||||
`before
|
||||
\
|
||||
after`; // LineContinuation
|
||||
|
||||
`before\
|
||||
after`; // LineContinuation newline
|
||||
|
||||
`before\
|
||||
|
||||
after`; // LineContinuation LineContinuation
|
||||
|
||||
`before\
|
||||
\
|
||||
after`;
|
||||
9
packages/babel-generator/test/fixtures/sourcemaps/template-literal-newline/source-map.json
vendored
Normal file
9
packages/babel-generator/test/fixtures/sourcemaps/template-literal-newline/source-map.json
vendored
Normal file
@ -0,0 +1,9 @@
|
||||
{
|
||||
"mappings": "AAAA;AACC;AACD,MADA,C,CAGA;;AACC;AACD;AACA,MAFA,C,CAIA;;AACC;AACD;AACA,MAFA,C,CAIA;;AACC;AACD,MADA,C,CAGA;;AACC;AACD;AACA,MAFA,C,CAIA;;AACC;AACD;AACA,MAFA",
|
||||
"names": [],
|
||||
"sources": ["fixtures/sourcemaps/template-literal-newline/input.js"],
|
||||
"sourcesContent": [
|
||||
"// Newline\n`before\nafter`;\n\n// Newline newline\n`before\n\nafter`;\n\n// Newline LineContinuation\n`before\n\\\nafter`;\n\n// LineContinuation\n`before\\\nafter`;\n\n// LineContinuation newline\n`before\\\n\nafter`;\n\n// LineContinuation LineContinuation\n`before\\\n\\\nafter`;"
|
||||
],
|
||||
"version": 3
|
||||
}
|
||||
@ -5,6 +5,7 @@ import * as t from "@babel/types";
|
||||
import fs from "fs";
|
||||
import path from "path";
|
||||
import fixtures from "@babel/helper-fixtures";
|
||||
import sourcemap from "source-map";
|
||||
|
||||
describe("generation", function () {
|
||||
it("completeness", function () {
|
||||
@ -277,6 +278,48 @@ describe("generation", function () {
|
||||
expect(generated.code).toBe("function foo2() {\n bar2;\n}");
|
||||
});
|
||||
|
||||
it("newline in template literal", () => {
|
||||
const code = "`before\n\nafter`;";
|
||||
const ast = parse(code, { filename: "inline" }).program;
|
||||
const generated = generate(
|
||||
ast,
|
||||
{
|
||||
filename: "inline",
|
||||
sourceFileName: "inline",
|
||||
sourceMaps: true,
|
||||
},
|
||||
code,
|
||||
);
|
||||
|
||||
const consumer = new sourcemap.SourceMapConsumer(generated.map);
|
||||
const loc = consumer.originalPositionFor({ line: 2, column: 1 });
|
||||
expect(loc).toMatchObject({
|
||||
column: 0,
|
||||
line: 2,
|
||||
});
|
||||
});
|
||||
|
||||
it("newline in string literal", () => {
|
||||
const code = "'before\\\n\\\nafter';";
|
||||
const ast = parse(code, { filename: "inline" }).program;
|
||||
const generated = generate(
|
||||
ast,
|
||||
{
|
||||
filename: "inline",
|
||||
sourceFileName: "inline",
|
||||
sourceMaps: true,
|
||||
},
|
||||
code,
|
||||
);
|
||||
|
||||
const consumer = new sourcemap.SourceMapConsumer(generated.map);
|
||||
const loc = consumer.originalPositionFor({ line: 2, column: 1 });
|
||||
expect(loc).toMatchObject({
|
||||
column: 0,
|
||||
line: 2,
|
||||
});
|
||||
});
|
||||
|
||||
it("lazy source map generation", function () {
|
||||
const code = "function hi (msg) { console.log(msg); }\n";
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user