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,
|
filename: ?string,
|
||||||
force?: boolean,
|
force?: boolean,
|
||||||
): void {
|
): 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._buf.push(str);
|
||||||
this._last = str[str.length - 1];
|
this._last = str[str.length - 1];
|
||||||
|
|
||||||
for (let i = 0; i < str.length; i++) {
|
// Search for newline chars. We search only for `\n`, since both `\r` and
|
||||||
if (str[i] === "\n") {
|
// `\r\n` are normalized to `\n` during parse. We exclude `\u2028` and
|
||||||
this._position.line++;
|
// `\u2029` for performance reasons, they're so uncommon that it's probably
|
||||||
this._position.column = 0;
|
// ok. It's also unclear how other sourcemap utilities handle them...
|
||||||
} else {
|
let i = str.indexOf("\n");
|
||||||
this._position.column++;
|
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 {
|
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 fs from "fs";
|
||||||
import path from "path";
|
import path from "path";
|
||||||
import fixtures from "@babel/helper-fixtures";
|
import fixtures from "@babel/helper-fixtures";
|
||||||
|
import sourcemap from "source-map";
|
||||||
|
|
||||||
describe("generation", function () {
|
describe("generation", function () {
|
||||||
it("completeness", function () {
|
it("completeness", function () {
|
||||||
@ -277,6 +278,48 @@ describe("generation", function () {
|
|||||||
expect(generated.code).toBe("function foo2() {\n bar2;\n}");
|
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 () {
|
it("lazy source map generation", function () {
|
||||||
const code = "function hi (msg) { console.log(msg); }\n";
|
const code = "function hi (msg) { console.log(msg); }\n";
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user