Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Do not delete "fake" source map comments from strings #9960

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion lib/third-party-libs.js.flow
Expand Up @@ -181,7 +181,7 @@ declare module "convert-source-map" {
fromJSON(str: string): Converter,
fromBase64(str: string): Converter,
fromComment(str: string): Converter,
fromMapFileComment(str: string): Converter,
fromMapFileComment(str: string, dir: string): Converter,
fromSource(str: string): Converter,
fromMapFileSource(str: string, dir: string): Converter,
removeComments(str: string): string,
Expand Down
102 changes: 70 additions & 32 deletions packages/babel-core/src/transformation/normalize-file.js
Expand Up @@ -27,6 +27,20 @@ export default function normalizeFile(
): File {
code = `${code || ""}`;

if (ast) {
if (ast.type === "Program") {
ast = t.file(ast, [], []);
} else if (ast.type !== "File") {
throw new Error("AST root must be a Program or File node");
}
ast = cloneDeep(ast);
} else {
// The parser's AST types aren't fully compatible with the types generated
// by the logic in babel-types.
// $FlowFixMe
ast = parser(pluginPasses, options, code);
}

let inputMap = null;
if (options.inputSourceMap !== false) {
// If an explicit object is passed in, it overrides the processing of
Expand All @@ -36,54 +50,33 @@ export default function normalizeFile(
}

if (!inputMap) {
try {
inputMap = convertSourceMap.fromSource(code);

if (inputMap) {
code = convertSourceMap.removeComments(code);
const lastComment = extractComments(INLINE_SOURCEMAP_REGEX, ast);
if (lastComment) {
try {
inputMap = convertSourceMap.fromComment(lastComment);
} catch (err) {
debug("discarding unknown inline input sourcemap", err);
}
} catch (err) {
debug("discarding unknown inline input sourcemap", err);
code = convertSourceMap.removeComments(code);
}
}

if (!inputMap) {
if (typeof options.filename === "string") {
const lastComment = extractComments(EXTERNAL_SOURCEMAP_REGEX, ast);
if (typeof options.filename === "string" && lastComment) {
try {
inputMap = convertSourceMap.fromMapFileSource(
code,
inputMap = convertSourceMap.fromMapFileComment(
lastComment,
path.dirname(options.filename),
);

if (inputMap) {
code = convertSourceMap.removeMapFileComments(code);
}
} catch (err) {
debug("discarding unknown file input sourcemap", err);
code = convertSourceMap.removeMapFileComments(code);
}
} else {
} else if (lastComment) {
debug("discarding un-loadable file input sourcemap");
code = convertSourceMap.removeMapFileComments(code);
}
}
}

if (ast) {
if (ast.type === "Program") {
ast = t.file(ast, [], []);
} else if (ast.type !== "File") {
throw new Error("AST root must be a Program or File node");
}
ast = cloneDeep(ast);
} else {
// The parser's AST types aren't fully compatible with the types generated
// by the logic in babel-types.
// $FlowFixMe
ast = parser(pluginPasses, options, code);
}

return new File(options, {
code,
ast,
Expand Down Expand Up @@ -156,3 +149,48 @@ function parser(
throw err;
}
}

// These regexps are copied from the convert-source-map package,
// but without // or /* at the beginning of the comment.

// eslint-disable-next-line max-len
const INLINE_SOURCEMAP_REGEX = /^[@#]\s+sourceMappingURL=data:(?:application|text)\/json;(?:charset[:=]\S+?;)?base64,(?:.*)$/;
const EXTERNAL_SOURCEMAP_REGEX = /^[@#][ \t]+sourceMappingURL=([^\s'"`]+?)[ \t]*$/;

function extractCommentsFromList(regex, comments, lastComment) {
if (comments) {
comments = comments.filter(({ value }) => {
if (regex.test(value)) {
lastComment = value;
return false;
}
return true;
});
}
return [comments, lastComment];
}

function extractComments(regex, ast) {
let lastComment = null;
t.traverseFast(ast, node => {
// $FlowIgnore destructuring with expressions is not supported
[node.leadingComments, lastComment] = extractCommentsFromList(
regex,
node.leadingComments,
lastComment,
);
// $FlowIgnore destructuring with expressions is not supported
[node.innerComments, lastComment] = extractCommentsFromList(
regex,
node.innerComments,
lastComment,
);
// $FlowIgnore destructuring with expressions is not supported
[node.trailingComments, lastComment] = extractCommentsFromList(
regex,
node.trailingComments,
lastComment,
);
});
return lastComment;
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

@@ -0,0 +1,3 @@
{
"inputSourceMap": true
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion packages/babel-types/src/traverse/traverseFast.js
Expand Up @@ -7,7 +7,7 @@ import { VISITOR_KEYS } from "../definitions";
*/
export default function traverseFast(
node: Object,
enter: (node: Node, opts?: Object) => void,
enter: (node: BabelNode, opts?: Object) => void,
opts?: Object,
): void {
if (!node) return;
Expand Down