From 5d720a979a627ed1f2e43c6d2e974f592f9d595c Mon Sep 17 00:00:00 2001 From: Ferdinand Prantl Date: Sat, 7 May 2022 17:07:18 +0200 Subject: [PATCH 1/3] Add support for the Meriyah parser Meriyah is a fast and modern implementation of ECMAScript parser --- .github/workflows/main.yml | 26 +++++++++++++------------- README.md | 2 +- lib/parser.ts | 4 ++-- package-lock.json | 16 ++++++++++++++++ package.json | 1 + parsers/meriyah.ts | 36 ++++++++++++++++++++++++++++++++++++ test/comments.ts | 2 ++ test/parser.ts | 2 ++ test/printer.ts | 1 + tsconfig.json | 5 +---- 10 files changed, 75 insertions(+), 20 deletions(-) create mode 100644 parsers/meriyah.ts diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 336d4c56..caefff28 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -2,9 +2,9 @@ name: CI on: push: - branches: [ master ] + branches: [master] pull_request: - branches: [ master ] + branches: [master] jobs: test: @@ -12,18 +12,18 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - node_version: ['10.x', '12.x', '14.x', '15.x', '16.x'] + node_version: ["10.x", "12.x", "14.x", "15.x", "16.x"] os: [ubuntu-latest] steps: - - uses: actions/checkout@v2 - - name: Use Node.js ${{ matrix.node_version }} - uses: actions/setup-node@v1 - with: - node-version: ${{ matrix.node_version }} + - uses: actions/checkout@v2 + - name: Use Node.js ${{ matrix.node_version }} + uses: actions/setup-node@v1 + with: + node-version: ${{ matrix.node_version }} - - name: npm install, build and test - run: | - npm install - npm run build --if-present - npm test + - name: npm install, build and test + run: | + npm install + npm run build --if-present + npm test diff --git a/README.md b/README.md index d55db99f..5c812445 100644 --- a/README.md +++ b/README.md @@ -168,7 +168,7 @@ const tsAst = recast.parse(source, { }); ``` -**Note:** Some of these parsers import npm packages that Recast does not directly depend upon, so please be aware you may have to run `npm install babylon@next` to use the `typescript`, `flow`, or `babylon` parsers, or `npm install acorn` to use the `acorn` parser. Only Esprima is installed by default when Recast is installed. +**Note:** Some of these parsers import npm packages that Recast does not directly depend upon, so please be aware you may have to run `npm install babylon@next` to use the `typescript`, `flow`, or `babylon` parsers, or `npm install acorn` to use the `acorn` parser, or `npm install meriyah` to use the `meriyah` parser. Only Esprima is installed by default when Recast is installed. After calling `recast.parse`, if you're going to transform the AST, make sure that the `.original` property is preserved. With Babel, for instance, if you call `transformFromAST`, you must pass `cloneInputAst: false` in its options. ([More detail](https://github.com/babel/babel/issues/12882). diff --git a/lib/parser.ts b/lib/parser.ts index ca48b56b..b7ab65ef 100644 --- a/lib/parser.ts +++ b/lib/parser.ts @@ -78,8 +78,8 @@ export function parse(source: string, options?: Partial) { program = ast; // In order to ensure we reprint leading and trailing program // comments, wrap the original Program node with a File node. Only - // ESTree parsers (Acorn and Esprima) return a Program as the root AST - // node. Most other (Babylon-like) parsers return a File. + // ESTree parsers (Acorn, Esprima, Meriyah) return a Program as the root + // AST node. Most other (Babylon-like) parsers return a File. file = b.file(ast, options.sourceFileName || null); file.loc = { start: lines.firstPos(), diff --git a/package-lock.json b/package-lock.json index f72bf2d6..08e8b666 100644 --- a/package-lock.json +++ b/package-lock.json @@ -28,6 +28,7 @@ "flow-parser": "0.156.0", "glob": "7.2.0", "lint-staged": "^12.4.1", + "meriyah": "^4.2.1", "mocha": "9.0.2", "prettier": "^2.6.2", "reify": "0.20.12", @@ -4074,6 +4075,15 @@ "node": ">= 8" } }, + "node_modules/meriyah": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/meriyah/-/meriyah-4.2.1.tgz", + "integrity": "sha512-Uv5sWsmjFNC6IszEmHo5bzJLL+kqjQ/VrEj9Agqsqtx7B6dcxHnHLew1ioJD19HNXrxrRZltPi+NVh12I8RLXA==", + "dev": true, + "engines": { + "node": ">=10.4.0" + } + }, "node_modules/micromatch": { "version": "4.0.5", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", @@ -8506,6 +8516,12 @@ "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", "dev": true }, + "meriyah": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/meriyah/-/meriyah-4.2.1.tgz", + "integrity": "sha512-Uv5sWsmjFNC6IszEmHo5bzJLL+kqjQ/VrEj9Agqsqtx7B6dcxHnHLew1ioJD19HNXrxrRZltPi+NVh12I8RLXA==", + "dev": true + }, "micromatch": { "version": "4.0.5", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", diff --git a/package.json b/package.json index 94e9134d..00c2745d 100644 --- a/package.json +++ b/package.json @@ -61,6 +61,7 @@ "flow-parser": "0.156.0", "glob": "7.2.0", "lint-staged": "^12.4.1", + "meriyah": "^4.2.1", "mocha": "9.0.2", "prettier": "^2.6.2", "reify": "0.20.12", diff --git a/parsers/meriyah.ts b/parsers/meriyah.ts new file mode 100644 index 00000000..310abc19 --- /dev/null +++ b/parsers/meriyah.ts @@ -0,0 +1,36 @@ +// This module is suitable for passing as options.parser when calling +// recast.parse to process JavaScript code with Meriyah: +// +// const ast = recast.parse(source, { +// parser: require("recast/parsers/meriyah") +// }); +// +import { getOption } from "../lib/util"; + +function convertComment(comment: any): any { + let { type } = comment; + type = type[0] === "S" ? "Line" : "Block"; // SingleLine/MultiLine + return { ...comment, type }; +} + +export function parse(source: string, options?: any) { + const comments: any[] = []; + const tokens: any[] = []; + const ast = require("meriyah").parse(source, { + module: getOption(options, "sourceType", "module") === "module", + specDeviation: getOption(options, "tolerant", true), + jsx: getOption(options, "jsx", false), + ranges: getOption(options, "range", false), + loc: true, + raw: true, + next: true, + globalReturn: true, + onComment: comments, + onToken: tokens, + }); + + ast.comments = comments.map(convertComment); + ast.tokens = tokens; + + return ast; +} diff --git a/test/comments.ts b/test/comments.ts index 4029c036..ff9aecdd 100644 --- a/test/comments.ts +++ b/test/comments.ts @@ -23,6 +23,7 @@ const nodeMajorVersion = parseInt(process.versions.node, 10); describe("comments", function () { [ "../parsers/acorn", + "../parsers/meriyah", "../parsers/babel", "../parsers/esprima", "../parsers/flow", @@ -180,6 +181,7 @@ function runTestsForParser(parserId: any) { const info = ( { acorn: esprimaInfo, + meriyah: esprimaInfo, babel: babelInfo, esprima: esprimaInfo, flow: babelInfo, diff --git a/test/parser.ts b/test/parser.ts index c044146d..0e5b9799 100644 --- a/test/parser.ts +++ b/test/parser.ts @@ -15,6 +15,7 @@ const nodeMajorVersion = parseInt(process.versions.node, 10); describe("parser", function () { [ "../parsers/acorn", + "../parsers/meriyah", "../parsers/babel", "../parsers/esprima", "../parsers/flow", @@ -84,6 +85,7 @@ function runTestsForParser(parserId: string) { const lineCommentTypes: { [name: string]: string } = { acorn: "Line", + meriyah: "Line", babel: "CommentLine", esprima: "Line", flow: "CommentLine", diff --git a/test/printer.ts b/test/printer.ts index a2934dde..f7898391 100644 --- a/test/printer.ts +++ b/test/printer.ts @@ -1692,6 +1692,7 @@ describe("printer", function () { checkWith(require("../parsers/esprima")); checkWith(require("../parsers/acorn")); + checkWith(require("../parsers/meriyah")); if (nodeMajorVersion >= 6) { checkWith(require("../parsers/babel")); diff --git a/tsconfig.json b/tsconfig.json index b11175ee..b148a05c 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -14,8 +14,5 @@ "importHelpers": true, "stripInternal": true }, - "exclude": [ - "node_modules", - "test/data" - ] + "exclude": ["node_modules", "test/data"] } From 767a44fb773f4f0413a24aa4619e157b62be432b Mon Sep 17 00:00:00 2001 From: Ferdinand Prantl Date: Sat, 7 May 2022 23:40:39 +0200 Subject: [PATCH 2/3] Revert changes in config files Caused `npm run format`. --- .github/workflows/main.yml | 26 +++++++++++++------------- tsconfig.json | 5 ++++- 2 files changed, 17 insertions(+), 14 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index caefff28..336d4c56 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -2,9 +2,9 @@ name: CI on: push: - branches: [master] + branches: [ master ] pull_request: - branches: [master] + branches: [ master ] jobs: test: @@ -12,18 +12,18 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - node_version: ["10.x", "12.x", "14.x", "15.x", "16.x"] + node_version: ['10.x', '12.x', '14.x', '15.x', '16.x'] os: [ubuntu-latest] steps: - - uses: actions/checkout@v2 - - name: Use Node.js ${{ matrix.node_version }} - uses: actions/setup-node@v1 - with: - node-version: ${{ matrix.node_version }} + - uses: actions/checkout@v2 + - name: Use Node.js ${{ matrix.node_version }} + uses: actions/setup-node@v1 + with: + node-version: ${{ matrix.node_version }} - - name: npm install, build and test - run: | - npm install - npm run build --if-present - npm test + - name: npm install, build and test + run: | + npm install + npm run build --if-present + npm test diff --git a/tsconfig.json b/tsconfig.json index b148a05c..b11175ee 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -14,5 +14,8 @@ "importHelpers": true, "stripInternal": true }, - "exclude": ["node_modules", "test/data"] + "exclude": [ + "node_modules", + "test/data" + ] } From 0cc1683c1af1af1f1450ae9fc23fffed408a3a27 Mon Sep 17 00:00:00 2001 From: Ferdinand Prantl Date: Sat, 7 May 2022 23:51:19 +0200 Subject: [PATCH 3/3] Compare the full comment type, not just the first letter --- parsers/meriyah.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/parsers/meriyah.ts b/parsers/meriyah.ts index 310abc19..432a8d95 100644 --- a/parsers/meriyah.ts +++ b/parsers/meriyah.ts @@ -9,7 +9,7 @@ import { getOption } from "../lib/util"; function convertComment(comment: any): any { let { type } = comment; - type = type[0] === "S" ? "Line" : "Block"; // SingleLine/MultiLine + type = type === "SingleLine" ? "Line" : "Block"; return { ...comment, type }; }