From a6661e850c9d3cfc350443d8cac27e1ee954a7a4 Mon Sep 17 00:00:00 2001 From: fisker Cheung Date: Wed, 10 Aug 2022 19:32:44 +0800 Subject: [PATCH] Use `import()` in parsers (#13261) --- .eslintrc.cjs | 1 - scripts/build/config.mjs | 11 +++++++++++ src/language-graphql/parser-graphql.js | 13 ++++--------- src/language-handlebars/parser-glimmer.js | 15 ++++++++++----- src/language-js/parse/angular.js | 7 ++----- src/language-js/parse/babel.js | 19 ++++++++++--------- src/language-js/parse/flow.js | 13 ++++++------- src/language-js/parse/json.js | 7 ++----- src/language-js/parse/meriyah.js | 15 ++++++--------- src/language-js/parse/typescript.js | 9 ++++----- src/language-yaml/parser-yaml.js | 7 ++----- 11 files changed, 57 insertions(+), 60 deletions(-) diff --git a/.eslintrc.cjs b/.eslintrc.cjs index 5c7ac1d94..8972b2871 100644 --- a/.eslintrc.cjs +++ b/.eslintrc.cjs @@ -12,7 +12,6 @@ module.exports = { ecmaVersion: "latest", sourceType: "module", }, - reportUnusedDisableDirectives: true, extends: ["eslint:recommended", "prettier"], plugins: [ "prettier-internal-rules", diff --git a/scripts/build/config.mjs b/scripts/build/config.mjs index 6b7aa91e8..e519face4 100644 --- a/scripts/build/config.mjs +++ b/scripts/build/config.mjs @@ -247,6 +247,17 @@ const parsers = [ }, { input: "src/language-handlebars/parser-glimmer.js", + replaceModule: [ + // See comment in `src/language-handlebars/parser-glimmer.js` file + { + module: require.resolve( + "@glimmer/syntax/dist/commonjs/es2017/lib/parser/tokenizer-event-handlers.js" + ), + path: require.resolve( + "@glimmer/syntax/dist/modules/es2017/lib/parser/tokenizer-event-handlers.js" + ), + }, + ], }, { input: "src/language-html/parser-html.js", diff --git a/src/language-graphql/parser-graphql.js b/src/language-graphql/parser-graphql.js index 380210824..abc7a2107 100644 --- a/src/language-graphql/parser-graphql.js +++ b/src/language-graphql/parser-graphql.js @@ -1,10 +1,7 @@ -import { createRequire } from "node:module"; import createError from "../common/parser-create-error.js"; import { hasPragma } from "./pragma.js"; import { locStart, locEnd } from "./loc.js"; -const require = createRequire(import.meta.url); - function parseComments(ast) { const comments = []; const { startToken } = ast.loc; @@ -42,9 +39,7 @@ const parseOptions = { }; function createParseError(error) { - const { GraphQLError } = require("graphql/error/GraphQLError"); - - if (error instanceof GraphQLError) { + if (error?.name === "GraphQLError") { const { message, locations: [start], @@ -56,9 +51,9 @@ function createParseError(error) { return error; } -function parse(text /*, parsers, opts*/) { - // Inline the require to avoid loading all the JS if we don't use it - const { parse } = require("graphql/language/parser"); +async function parse(text /*, parsers, opts*/) { + // Inline `import()` to avoid loading all the JS if we don't use it + const { parse } = await import("graphql/language/parser.mjs"); /** @type {any} */ let ast; diff --git a/src/language-handlebars/parser-glimmer.js b/src/language-handlebars/parser-glimmer.js index 4432c391d..350bde6bb 100644 --- a/src/language-handlebars/parser-glimmer.js +++ b/src/language-handlebars/parser-glimmer.js @@ -1,10 +1,7 @@ -import { createRequire } from "node:module"; import { LinesAndColumns } from "lines-and-columns"; import createError from "../common/parser-create-error.js"; import { locStart, locEnd } from "./loc.js"; -const require = createRequire(import.meta.url); - /* from the following template: `non-escaped mustache \\{{helper}}` * glimmer parser will produce an AST missing a backslash * so here we add it back @@ -50,8 +47,16 @@ function addOffset(text) { }); } -function parse(text) { - const { preprocess: glimmer } = require("@glimmer/syntax"); +async function parse(text) { + // Inline `import()` to avoid loading all the JS if we don't use it + /* + The module version `@glimmer/syntax/dist/modules/es2017/lib/parser/tokenizer-event-handlers.js` + can't be be imported since it use `.js` extension, and don't have `type: module` in `package.json` + We'll replace it during build + */ + const { preprocess: glimmer } = await import( + "@glimmer/syntax/dist/commonjs/es2017/lib/parser/tokenizer-event-handlers.js" + ); let ast; try { ast = glimmer(text, { diff --git a/src/language-js/parse/angular.js b/src/language-js/parse/angular.js index d702d11fc..e141be508 100644 --- a/src/language-js/parse/angular.js +++ b/src/language-js/parse/angular.js @@ -1,11 +1,8 @@ -import { createRequire } from "node:module"; import { locStart, locEnd } from "../loc.js"; -const require = createRequire(import.meta.url); - function createParser(_parse) { - const parse = (text, parsers, options) => { - const ngEstreeParser = require("angular-estree-parser"); + const parse = async (text, parsers, options) => { + const ngEstreeParser = await import("angular-estree-parser"); const node = _parse(text, ngEstreeParser); return { type: "NGRoot", diff --git a/src/language-js/parse/babel.js b/src/language-js/parse/babel.js index c8915cb07..5b9d08cba 100644 --- a/src/language-js/parse/babel.js +++ b/src/language-js/parse/babel.js @@ -1,4 +1,3 @@ -import { createRequire } from "node:module"; import tryCombinations from "../../utils/try-combinations.js"; import getShebang from "../utils/get-shebang.js"; import getNextNonSpaceNonCommentCharacterIndexWithStartIndex from "../../utils/text/get-next-non-space-non-comment-character-index-with-start-index.js"; @@ -7,8 +6,6 @@ import createBabelParseError from "./utils/create-babel-parse-error.js"; import postprocess from "./postprocess/index.js"; import jsonParsers from "./json.js"; -const require = createRequire(import.meta.url); - /** * @typedef {import("@babel/parser").parse | import("@babel/parser").parseExpression} Parse * @typedef {import("@babel/parser").ParserOptions} ParserOptions @@ -86,10 +83,7 @@ function isFlowFile(text, options) { return FLOW_PRAGMA_REGEX.test(text); } -function parseWithOptions(parseMethod, text, options) { - // Inline the require to avoid loading all the JS if we don't use it - /** @type {Parse} */ - const parse = require("@babel/parser")[parseMethod]; +function parseWithOptions(parse, text, options) { const ast = parse(text, options); const error = ast.errors.find( (error) => !allowedMessageCodes.has(error.reasonCode) @@ -101,7 +95,7 @@ function parseWithOptions(parseMethod, text, options) { } function createParse(parseMethod, ...optionsCombinations) { - return (text, parsers, opts = {}) => { + return async (text, parsers, opts = {}) => { if ( (opts.parser === "babel" || opts.parser === "__babel_estree") && isFlowFile(text, opts) @@ -140,9 +134,16 @@ function createParse(parseMethod, ...optionsCombinations) { ); } + // Inline `import()` to avoid loading all the JS if we don't use it + const { parse: babelParse, parseExpression } = await import( + "@babel/parser" + ); + /** @type {Parse} */ + const parseFunction = + parseMethod === "parseExpression" ? parseExpression : babelParse; const { result: ast, error } = tryCombinations( ...combinations.map( - (options) => () => parseWithOptions(parseMethod, text, options) + (options) => () => parseWithOptions(parseFunction, text, options) ) ); diff --git a/src/language-js/parse/flow.js b/src/language-js/parse/flow.js index 8cab6102d..12e84c5d6 100644 --- a/src/language-js/parse/flow.js +++ b/src/language-js/parse/flow.js @@ -1,11 +1,8 @@ -import { createRequire } from "node:module"; import createError from "../../common/parser-create-error.js"; import createParser from "./utils/create-parser.js"; import replaceHashbang from "./utils/replace-hashbang.js"; import postprocess from "./postprocess/index.js"; -const require = createRequire(import.meta.url); - // https://github.com/facebook/flow/tree/main/packages/flow-parser#options // Keep this sync with `/scripts/sync-flow-test.js` const parseOptions = { @@ -39,10 +36,12 @@ function createParseError(error) { }); } -function parse(text, parsers, options = {}) { - // Inline the require to avoid loading all the JS if we don't use it - const flow = require("flow-parser"); - const ast = flow.parse(replaceHashbang(text), parseOptions); +async function parse(text, parsers, options = {}) { + // Inline `import()` to avoid loading all the JS if we don't use it + const { + default: { parse }, + } = await import("flow-parser"); + const ast = parse(replaceHashbang(text), parseOptions); const [error] = ast.errors; if (error) { throw createParseError(error); diff --git a/src/language-js/parse/json.js b/src/language-js/parse/json.js index 773d6bcc4..3e1f8b48d 100644 --- a/src/language-js/parse/json.js +++ b/src/language-js/parse/json.js @@ -1,16 +1,13 @@ -import { createRequire } from "node:module"; import isNonEmptyArray from "../../utils/is-non-empty-array.js"; import createError from "../../common/parser-create-error.js"; import createParser from "./utils/create-parser.js"; import createBabelParseError from "./utils/create-babel-parse-error.js"; -const require = createRequire(import.meta.url); - function createJsonParse(options = {}) { const { allowComments = true } = options; - return function parse(text /*, parsers, options*/) { - const { parseExpression } = require("@babel/parser"); + return async function parse(text /*, parsers, options*/) { + const { parseExpression } = await import("@babel/parser"); let ast; try { ast = parseExpression(text, { diff --git a/src/language-js/parse/meriyah.js b/src/language-js/parse/meriyah.js index e98e72335..b5b2dfa14 100644 --- a/src/language-js/parse/meriyah.js +++ b/src/language-js/parse/meriyah.js @@ -1,11 +1,8 @@ -import { createRequire } from "node:module"; import createError from "../../common/parser-create-error.js"; import tryCombinations from "../../utils/try-combinations.js"; import createParser from "./utils/create-parser.js"; import postprocess from "./postprocess/index.js"; -const require = createRequire(import.meta.url); - // https://github.com/meriyah/meriyah/blob/4676f60b6c149d7082bde2c9147f9ae2359c8075/src/parser.ts#L185 const parseOptions = { // Allow module code @@ -42,13 +39,12 @@ const parseOptions = { uniqueKeyInPattern: false, }; -function parseWithOptions(text, module) { - const { parse: meriyahParse } = require("meriyah"); +function parseWithOptions(parse, text, module) { const comments = []; const tokens = []; /** @type {any} */ - const ast = meriyahParse(text, { + const ast = parse(text, { ...parseOptions, module, onComment: comments, @@ -85,10 +81,11 @@ function createParseError(error) { return createError(message, { start: { line, column } }); } -function parse(text, parsers, options = {}) { +async function parse(text, parsers, options = {}) { + const { parse } = await import("meriyah"); const { result: ast, error: moduleParseError } = tryCombinations( - () => parseWithOptions(text, /* module */ true), - () => parseWithOptions(text, /* module */ false) + () => parseWithOptions(parse, text, /* module */ true), + () => parseWithOptions(parse, text, /* module */ false) ); if (!ast) { diff --git a/src/language-js/parse/typescript.js b/src/language-js/parse/typescript.js index f9ad969b0..d8359ba86 100644 --- a/src/language-js/parse/typescript.js +++ b/src/language-js/parse/typescript.js @@ -1,12 +1,9 @@ -import { createRequire } from "node:module"; import createError from "../../common/parser-create-error.js"; import tryCombinations from "../../utils/try-combinations.js"; import createParser from "./utils/create-parser.js"; import replaceHashbang from "./utils/replace-hashbang.js"; import postprocess from "./postprocess/index.js"; -const require = createRequire(import.meta.url); - /** @type {import("@typescript-eslint/typescript-estree").TSESTreeOptions} */ const parseOptions = { // `jest@<=26.4.2` rely on `loc` @@ -33,11 +30,13 @@ function createParseError(error) { }); } -function parse(text, parsers, options = {}) { +async function parse(text, parsers, options = {}) { const textToParse = replaceHashbang(text); const jsx = isProbablyJsx(text); - const { parseWithNodeMaps } = require("@typescript-eslint/typescript-estree"); + const { parseWithNodeMaps } = await import( + "@typescript-eslint/typescript-estree/dist/parser.js" + ); const { result, error: firstError } = tryCombinations( // Try passing with our best guess first. () => parseWithNodeMaps(textToParse, { ...parseOptions, jsx }), diff --git a/src/language-yaml/parser-yaml.js b/src/language-yaml/parser-yaml.js index 245d92160..1ee1b94cd 100644 --- a/src/language-yaml/parser-yaml.js +++ b/src/language-yaml/parser-yaml.js @@ -1,12 +1,9 @@ -import { createRequire } from "node:module"; import createError from "../common/parser-create-error.js"; import { hasPragma } from "./pragma.js"; import { locStart, locEnd } from "./loc.js"; -const require = createRequire(import.meta.url); - -function parse(text) { - const { parse: parseYaml } = require("yaml-unist-parser"); +async function parse(text) { + const { parse: parseYaml } = await import("yaml-unist-parser/lib/parse.js"); try { const root = parseYaml(text);