From 7826e551df2f0f16c872fc766fb0faa76222f6fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Ribaudo?= Date: Thu, 6 May 2021 21:51:14 +0200 Subject: [PATCH 1/4] [eslint] Don't crash on multiple `@babel/parser` copies --- .../src/convert/convertTokens.js | 128 +++++++++--------- eslint/babel-eslint-tests/package.json | 3 +- .../duplicated-babel-parser/.eslintrc.js | 13 ++ .../fixtures/duplicated-babel-parser/a.js | 5 + .../duplicated-babel-parser/babel.config.js | 7 + .../integration/duplicated-babel-parser.js | 17 +++ yarn.lock | 3 +- 7 files changed, 112 insertions(+), 64 deletions(-) create mode 100644 eslint/babel-eslint-tests/test/fixtures/duplicated-babel-parser/.eslintrc.js create mode 100644 eslint/babel-eslint-tests/test/fixtures/duplicated-babel-parser/a.js create mode 100644 eslint/babel-eslint-tests/test/fixtures/duplicated-babel-parser/babel.config.js create mode 100644 eslint/babel-eslint-tests/test/integration/duplicated-babel-parser.js diff --git a/eslint/babel-eslint-parser/src/convert/convertTokens.js b/eslint/babel-eslint-parser/src/convert/convertTokens.js index cab96602bffc..b9b49df659cd 100644 --- a/eslint/babel-eslint-parser/src/convert/convertTokens.js +++ b/eslint/babel-eslint-parser/src/convert/convertTokens.js @@ -1,4 +1,8 @@ -import { tokTypes as tt } from "@babel/core"; +import { tokTypes } from "@babel/core"; + +const tl = Object.fromEntries( + Object.keys(tokTypes).map(key => [key, tokTypes[key].label]), +); function convertTemplateType(tokens) { let curlyBrace = null; @@ -12,7 +16,7 @@ function convertTemplateType(tokens) { const value = templateTokens.reduce((result, token) => { if (token.value) { result += token.value; - } else if (token.type !== tt.template) { + } else if (token.type.label !== tl.template) { result += token.type.label; } @@ -34,8 +38,8 @@ function convertTemplateType(tokens) { } tokens.forEach(token => { - switch (token.type) { - case tt.backQuote: + switch (token.type.label) { + case tl.backQuote: if (curlyBrace) { result.push(curlyBrace); curlyBrace = null; @@ -49,12 +53,12 @@ function convertTemplateType(tokens) { break; - case tt.dollarBraceL: + case tl.dollarBraceL: templateTokens.push(token); addTemplateType(); break; - case tt.braceR: + case tl.braceR: if (curlyBrace) { result.push(curlyBrace); } @@ -62,7 +66,7 @@ function convertTemplateType(tokens) { curlyBrace = token; break; - case tt.template: + case tl.template: if (curlyBrace) { templateTokens.push(curlyBrace); curlyBrace = null; @@ -71,7 +75,7 @@ function convertTemplateType(tokens) { templateTokens.push(token); break; - case tt.eof: + case tl.eof: if (curlyBrace) { result.push(curlyBrace); } @@ -92,63 +96,64 @@ function convertTemplateType(tokens) { } function convertToken(token, source) { - const type = token.type; + const { type } = token; + const { label } = type; token.range = [token.start, token.end]; - if (type === tt.name) { + if (label === tl.name) { token.type = "Identifier"; } else if ( - type === tt.semi || - type === tt.comma || - type === tt.parenL || - type === tt.parenR || - type === tt.braceL || - type === tt.braceR || - type === tt.slash || - type === tt.dot || - type === tt.bracketL || - type === tt.bracketR || - type === tt.ellipsis || - type === tt.arrow || - type === tt.pipeline || - type === tt.star || - type === tt.incDec || - type === tt.colon || - type === tt.question || - type === tt.template || - type === tt.backQuote || - type === tt.dollarBraceL || - type === tt.at || - type === tt.logicalOR || - type === tt.logicalAND || - type === tt.nullishCoalescing || - type === tt.bitwiseOR || - type === tt.bitwiseXOR || - type === tt.bitwiseAND || - type === tt.equality || - type === tt.relational || - type === tt.bitShift || - type === tt.plusMin || - type === tt.modulo || - type === tt.exponent || - type === tt.bang || - type === tt.tilde || - type === tt.doubleColon || - type === tt.hash || - type === tt.questionDot || + label === tl.semi || + label === tl.comma || + label === tl.parenL || + label === tl.parenR || + label === tl.braceL || + label === tl.braceR || + label === tl.slash || + label === tl.dot || + label === tl.bracketL || + label === tl.bracketR || + label === tl.ellipsis || + label === tl.arrow || + label === tl.pipeline || + label === tl.star || + label === tl.incDec || + label === tl.colon || + label === tl.question || + label === tl.template || + label === tl.backQuote || + label === tl.dollarBraceL || + label === tl.at || + label === tl.logicalOR || + label === tl.logicalAND || + label === tl.nullishCoalescing || + label === tl.bitwiseOR || + label === tl.bitwiseXOR || + label === tl.bitwiseAND || + label === tl.equality || + label === tl.relational || + label === tl.bitShift || + label === tl.plusMin || + label === tl.modulo || + label === tl.exponent || + label === tl.bang || + label === tl.tilde || + label === tl.doubleColon || + label === tl.hash || + label === tl.questionDot || type.isAssign ) { token.type = "Punctuator"; - if (!token.value) token.value = type.label; - } else if (type === tt.jsxTagStart) { + token.value ??= label; + } else if (label === tl.jsxTagStart) { token.type = "Punctuator"; token.value = "<"; - } else if (type === tt.jsxTagEnd) { + } else if (label === tl.jsxTagEnd) { token.type = "Punctuator"; token.value = ">"; - } else if (type === tt.jsxName) { + } else if (label === tl.jsxName) { token.type = "JSXIdentifier"; - } else if (type === tt.jsxText) { + } else if (label === tl.jsxText) { token.type = "JSXText"; } else if (type.keyword === "null") { token.type = "Null"; @@ -156,13 +161,13 @@ function convertToken(token, source) { token.type = "Boolean"; } else if (type.keyword) { token.type = "Keyword"; - } else if (type === tt.num) { + } else if (label === tl.num) { token.type = "Numeric"; token.value = source.slice(token.start, token.end); - } else if (type === tt.string) { + } else if (label === tl.string) { token.type = "String"; token.value = source.slice(token.start, token.end); - } else if (type === tt.regexp) { + } else if (label === tl.regexp) { token.type = "RegularExpression"; const value = token.value; token.regex = { @@ -170,16 +175,15 @@ function convertToken(token, source) { flags: value.flags, }; token.value = `/${value.pattern}/${value.flags}`; - } else if (type === tt.bigint) { + } else if (label === tl.bigint) { token.type = "Numeric"; token.value = `${token.value}n`; - } else if (type === tt.privateName) { + } else if (type === tl.privateName) { token.type = "PrivateIdentifier"; } - if (typeof token.type !== "string") { - // Acorn does not have rightAssociative - delete token.type.rightAssociative; - } + + // Acorn does not have rightAssociative + delete token.type.rightAssociative; return token; } diff --git a/eslint/babel-eslint-tests/package.json b/eslint/babel-eslint-tests/package.json index 00def8741a8a..27095e2bcefe 100644 --- a/eslint/babel-eslint-tests/package.json +++ b/eslint/babel-eslint-tests/package.json @@ -8,6 +8,7 @@ "@babel/eslint-parser": "workspace:^7.12.1", "dedent": "^0.7.0", "eslint": "^7.5.0", - "eslint-plugin-import": "^2.22.0" + "eslint-plugin-import": "^2.22.0", + "npm-babel-parser": "npm:@babel/parser@^7.14.0" } } diff --git a/eslint/babel-eslint-tests/test/fixtures/duplicated-babel-parser/.eslintrc.js b/eslint/babel-eslint-tests/test/fixtures/duplicated-babel-parser/.eslintrc.js new file mode 100644 index 000000000000..b832402fc576 --- /dev/null +++ b/eslint/babel-eslint-tests/test/fixtures/duplicated-babel-parser/.eslintrc.js @@ -0,0 +1,13 @@ +module.exports = { + root: true, + parser: "@babel/eslint-parser", + parserOptions: { + babelOptions: { + configFile: __dirname + "/babel.config.js", + sourceType: "module", + }, + }, + rules: { + "template-curly-spacing": "error", + }, +}; diff --git a/eslint/babel-eslint-tests/test/fixtures/duplicated-babel-parser/a.js b/eslint/babel-eslint-tests/test/fixtures/duplicated-babel-parser/a.js new file mode 100644 index 000000000000..202d32b870c5 --- /dev/null +++ b/eslint/babel-eslint-tests/test/fixtures/duplicated-babel-parser/a.js @@ -0,0 +1,5 @@ +import { func1 } from "./iodex.js"; + +export function five() { + return { five: `number(${5})` }; +} diff --git a/eslint/babel-eslint-tests/test/fixtures/duplicated-babel-parser/babel.config.js b/eslint/babel-eslint-tests/test/fixtures/duplicated-babel-parser/babel.config.js new file mode 100644 index 000000000000..884409cc0705 --- /dev/null +++ b/eslint/babel-eslint-tests/test/fixtures/duplicated-babel-parser/babel.config.js @@ -0,0 +1,7 @@ +module.exports = { + plugins: [ + () => ({ + parserOverride: require("npm-babel-parser").parse, + }), + ], +}; diff --git a/eslint/babel-eslint-tests/test/integration/duplicated-babel-parser.js b/eslint/babel-eslint-tests/test/integration/duplicated-babel-parser.js new file mode 100644 index 000000000000..b15c5ecbe357 --- /dev/null +++ b/eslint/babel-eslint-tests/test/integration/duplicated-babel-parser.js @@ -0,0 +1,17 @@ +import eslint from "eslint"; +import path from "path"; +import { fileURLToPath } from "url"; + +describe("https://github.com/babel/babel/issues/12985", () => { + it("works with different copies of @babel/parser", () => { + const engine = new eslint.CLIEngine({ ignore: false }); + expect(() => + engine.executeOnFiles([ + path.resolve( + path.dirname(fileURLToPath(import.meta.url)), + `../fixtures/duplicated-babel-parser/a.js`, + ), + ]), + ).not.toThrow(); + }); +}); diff --git a/yarn.lock b/yarn.lock index 7af75fc0af81..68d830169d3f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5,7 +5,7 @@ __metadata: version: 4 cacheKey: 7 -"@babel-baseline/parser@npm:@babel/parser@^7.14.0, @babel/parser@npm:^7.0.0, @babel/parser@npm:^7.12.13, @babel/parser@npm:^7.12.7, @babel/parser@npm:^7.14.0": +"@babel-baseline/parser@npm:@babel/parser@^7.14.0, @babel/parser@npm:^7.0.0, @babel/parser@npm:^7.12.13, @babel/parser@npm:^7.12.7, @babel/parser@npm:^7.14.0, npm-babel-parser@npm:@babel/parser@^7.14.0": version: 7.14.0 resolution: "@babel/parser@npm:7.14.0" bin: @@ -314,6 +314,7 @@ __metadata: dedent: ^0.7.0 eslint: ^7.5.0 eslint-plugin-import: ^2.22.0 + npm-babel-parser: "npm:@babel/parser@^7.14.0" languageName: unknown linkType: soft From 177c430fce9fd9bffca6e8101f330a8ccb88eef0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Ribaudo?= Date: Thu, 6 May 2021 22:07:52 +0200 Subject: [PATCH 2/4] Fix --- eslint/babel-eslint-parser/src/convert/convertTokens.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/eslint/babel-eslint-parser/src/convert/convertTokens.js b/eslint/babel-eslint-parser/src/convert/convertTokens.js index b9b49df659cd..33d3f682aeb9 100644 --- a/eslint/babel-eslint-parser/src/convert/convertTokens.js +++ b/eslint/babel-eslint-parser/src/convert/convertTokens.js @@ -178,7 +178,7 @@ function convertToken(token, source) { } else if (label === tl.bigint) { token.type = "Numeric"; token.value = `${token.value}n`; - } else if (type === tl.privateName) { + } else if (label === tl.privateName) { token.type = "PrivateIdentifier"; } From 2e85d14bee05174478d05d0a320b24581fc48292 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Ribaudo?= Date: Thu, 6 May 2021 22:10:46 +0200 Subject: [PATCH 3/4] Polyfill `Object.fromEntries` --- eslint/babel-eslint-parser/src/convert/convertTokens.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/eslint/babel-eslint-parser/src/convert/convertTokens.js b/eslint/babel-eslint-parser/src/convert/convertTokens.js index 33d3f682aeb9..f3d771944475 100644 --- a/eslint/babel-eslint-parser/src/convert/convertTokens.js +++ b/eslint/babel-eslint-parser/src/convert/convertTokens.js @@ -1,6 +1,8 @@ import { tokTypes } from "@babel/core"; -const tl = Object.fromEntries( +const tl = (process.env.BABEL_8_BREAKING + ? Object.fromEntries + : p => p.reduce((o, [k, v]) => ({ ...o, [k]: v }), {}))( Object.keys(tokTypes).map(key => [key, tokTypes[key].label]), ); From 5601f3233f015898dc61aba148c3ec373ad27369 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Ribaudo?= Date: Thu, 6 May 2021 22:47:32 +0200 Subject: [PATCH 4/4] Bring back if check --- eslint/babel-eslint-parser/src/convert/convertTokens.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/eslint/babel-eslint-parser/src/convert/convertTokens.js b/eslint/babel-eslint-parser/src/convert/convertTokens.js index f3d771944475..9c93990f2cd7 100644 --- a/eslint/babel-eslint-parser/src/convert/convertTokens.js +++ b/eslint/babel-eslint-parser/src/convert/convertTokens.js @@ -184,8 +184,10 @@ function convertToken(token, source) { token.type = "PrivateIdentifier"; } - // Acorn does not have rightAssociative - delete token.type.rightAssociative; + if (typeof token.type !== "string") { + // Acorn does not have rightAssociative + delete token.type.rightAssociative; + } return token; }