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

@babel-core: parse should parse only #10914

Merged
merged 2 commits into from Dec 24, 2019
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
13 changes: 5 additions & 8 deletions packages/babel-core/src/parse.js
@@ -1,14 +1,11 @@
// @flow

import loadConfig, { type InputOptions } from "./config";
import normalizeFile from "./transformation/normalize-file";
import parser from "./parser";
import type { ParseResult } from "./parser";
import normalizeOptions from "./transformation/normalize-opts";

type AstRoot = BabelNodeFile | BabelNodeProgram;

export type ParseResult = AstRoot;

export type FileParseCallback = {
type FileParseCallback = {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(Note for reviewers)
This wasn't already imported anywhere.

(Error, null): any,
(null, ParseResult | null): any,
};
Expand Down Expand Up @@ -49,7 +46,7 @@ export const parse: Parse = (function parse(code, opts, callback) {
const cfg = loadConfig(opts);
if (cfg === null) return cb(null, null);

ast = normalizeFile(cfg.passes, normalizeOptions(cfg), code).ast;
ast = parser(cfg.passes, normalizeOptions(cfg), code);
} catch (err) {
return cb(err);
}
Expand All @@ -68,7 +65,7 @@ export function parseSync(
return null;
}

return normalizeFile(config.passes, normalizeOptions(config), code).ast;
return parser(config.passes, normalizeOptions(config), code);
}

export function parseAsync(
Expand Down
74 changes: 74 additions & 0 deletions packages/babel-core/src/parser/index.js
@@ -0,0 +1,74 @@
import { parse } from "@babel/parser";
import { codeFrameColumns } from "@babel/code-frame";
import generateMissingPluginMessage from "./util/missing-plugin-helper";

type AstRoot = BabelNodeFile | BabelNodeProgram;

export type ParseResult = AstRoot;

export default function parser(
pluginPasses: PluginPasses,
{ parserOpts, highlightCode = true, filename = "unknown" }: Object,
code: string,
): ParseResult {
try {
const results = [];
for (const plugins of pluginPasses) {
for (const plugin of plugins) {
const { parserOverride } = plugin;
if (parserOverride) {
const ast = parserOverride(code, parserOpts, parse);

if (ast !== undefined) results.push(ast);
}
}
}

if (results.length === 0) {
return parse(code, parserOpts);
} else if (results.length === 1) {
if (typeof results[0].then === "function") {
throw new Error(
`You appear to be using an async parser plugin, ` +
`which your current version of Babel does not support. ` +
`If you're using a published plugin, you may need to upgrade ` +
`your @babel/core version.`,
);
}
return results[0];
}
throw new Error("More than one plugin attempted to override parsing.");
} catch (err) {
if (err.code === "BABEL_PARSER_SOURCETYPE_MODULE_REQUIRED") {
err.message +=
"\nConsider renaming the file to '.mjs', or setting sourceType:module " +
"or sourceType:unambiguous in your Babel config for this file.";
// err.code will be changed to BABEL_PARSE_ERROR later.
}

const { loc, missingPlugin } = err;
if (loc) {
const codeFrame = codeFrameColumns(
code,
{
start: {
line: loc.line,
column: loc.column + 1,
},
},
{
highlightCode,
},
);
if (missingPlugin) {
err.message =
`${filename}: ` +
generateMissingPluginMessage(missingPlugin[0], loc, codeFrame);
} else {
err.message = `${filename}: ${err.message}\n\n` + codeFrame;
}
err.code = "BABEL_PARSE_ERROR";
}
throw err;
}
}
74 changes: 1 addition & 73 deletions packages/babel-core/src/transformation/normalize-file.js
Expand Up @@ -7,10 +7,8 @@ import cloneDeep from "lodash/cloneDeep";
import * as t from "@babel/types";
import type { PluginPasses } from "../config";
import convertSourceMap, { typeof Converter } from "convert-source-map";
import { parse } from "@babel/parser";
import { codeFrameColumns } from "@babel/code-frame";
import File from "./file/file";
import generateMissingPluginMessage from "./util/missing-plugin-helper";
import parser from "../parser";

const debug = buildDebug("babel:transform:file");
const LARGE_INPUT_SOURCEMAP_THRESHOLD = 1_000_000;
Expand All @@ -37,9 +35,6 @@ export default function normalizeFile(
}
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);
}

Expand Down Expand Up @@ -94,73 +89,6 @@ export default function normalizeFile(
});
}

function parser(
pluginPasses: PluginPasses,
{ parserOpts, highlightCode = true, filename = "unknown" }: Object,
code: string,
) {
try {
const results = [];
for (const plugins of pluginPasses) {
for (const plugin of plugins) {
const { parserOverride } = plugin;
if (parserOverride) {
const ast = parserOverride(code, parserOpts, parse);

if (ast !== undefined) results.push(ast);
}
}
}

if (results.length === 0) {
return parse(code, parserOpts);
} else if (results.length === 1) {
if (typeof results[0].then === "function") {
throw new Error(
`You appear to be using an async parser plugin, ` +
`which your current version of Babel does not support. ` +
`If you're using a published plugin, you may need to upgrade ` +
`your @babel/core version.`,
);
}
return results[0];
}
throw new Error("More than one plugin attempted to override parsing.");
} catch (err) {
if (err.code === "BABEL_PARSER_SOURCETYPE_MODULE_REQUIRED") {
err.message +=
"\nConsider renaming the file to '.mjs', or setting sourceType:module " +
"or sourceType:unambiguous in your Babel config for this file.";
// err.code will be changed to BABEL_PARSE_ERROR later.
}

const { loc, missingPlugin } = err;
if (loc) {
const codeFrame = codeFrameColumns(
code,
{
start: {
line: loc.line,
column: loc.column + 1,
},
},
{
highlightCode,
},
);
if (missingPlugin) {
err.message =
`${filename}: ` +
generateMissingPluginMessage(missingPlugin[0], loc, codeFrame);
} else {
err.message = `${filename}: ${err.message}\n\n` + codeFrame;
}
err.code = "BABEL_PARSE_ERROR";
}
throw err;
}
}

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

Expand Down