diff --git a/eslint/babel-eslint-parser/package.json b/eslint/babel-eslint-parser/package.json index 4874f4a06289..81bcaf965c6f 100644 --- a/eslint/babel-eslint-parser/package.json +++ b/eslint/babel-eslint-parser/package.json @@ -23,8 +23,8 @@ "eslint": ">=6.0.0" }, "dependencies": { - "eslint-scope": "5.0.0", - "eslint-visitor-keys": "^1.1.0", + "eslint-scope": "5.1.0", + "eslint-visitor-keys": "^1.3.0", "semver": "^6.3.0" }, "devDependencies": { diff --git a/eslint/babel-eslint-parser/src/convert/convertAST.js b/eslint/babel-eslint-parser/src/convert/convertAST.js index 4cee65d0f6f7..d44cce84b203 100644 --- a/eslint/babel-eslint-parser/src/convert/convertAST.js +++ b/eslint/babel-eslint-parser/src/convert/convertAST.js @@ -1,4 +1,5 @@ import { types as t, traverse } from "@babel/core"; +import VISITOR_KEYS from "../visitor-keys"; function convertNodes(ast, code) { const astTransformVisitor = { @@ -81,21 +82,28 @@ function convertNodes(ast, code) { }; const state = { source: code }; - // Monkey patch visitor keys in order to be able to traverse the estree nodes - t.VISITOR_KEYS.Property = t.VISITOR_KEYS.ObjectProperty; - t.VISITOR_KEYS.MethodDefinition = [ - "key", - "value", - "decorators", - "returnType", - "typeParameters", - ]; - - traverse(ast, astTransformVisitor, null, state); - - // These can be safely deleted because they are not defined in the original visitor keys. - delete t.VISITOR_KEYS.Property; - delete t.VISITOR_KEYS.MethodDefinition; + const oldExportAllDeclarationKeys = t.VISITOR_KEYS.ExportAllDeclaration; + + try { + // Monkey patch visitor keys in order to be able to traverse the estree nodes + t.VISITOR_KEYS.ChainExpression = VISITOR_KEYS.ChainExpression; + t.VISITOR_KEYS.Property = VISITOR_KEYS.Property; + t.VISITOR_KEYS.MethodDefinition = VISITOR_KEYS.MethodDefinition; + + // Make sure we visit `exported` key to remove `identifierName` from loc node + t.VISITOR_KEYS.ExportAllDeclaration = t.VISITOR_KEYS.ExportAllDeclaration.concat( + "exported", + ); + + traverse(ast, astTransformVisitor, null, state); + } finally { + // These can be safely deleted because they are not defined in the original visitor keys. + delete t.VISITOR_KEYS.ChainExpression; + delete t.VISITOR_KEYS.MethodDefinition; + delete t.VISITOR_KEYS.Property; + + t.VISITOR_KEYS.ExportAllDeclaration = oldExportAllDeclarationKeys; + } } function convertProgramNode(ast) { diff --git a/eslint/babel-eslint-parser/src/convert/convertTokens.js b/eslint/babel-eslint-parser/src/convert/convertTokens.js index 402f02ebe6c6..0f5f43fb2386 100644 --- a/eslint/babel-eslint-parser/src/convert/convertTokens.js +++ b/eslint/babel-eslint-parser/src/convert/convertTokens.js @@ -115,7 +115,6 @@ function convertToken(token, source) { type === tt.incDec || type === tt.colon || type === tt.question || - type === tt.questionDot || type === tt.template || type === tt.backQuote || type === tt.dollarBraceL || @@ -173,6 +172,12 @@ function convertToken(token, source) { } else if (type === tt.bigint) { token.type = "Numeric"; token.value = `${token.value}n`; + } else if (type === tt.questionDot) { + token.value = type.label; + } + if (typeof token.type !== "string") { + // Acorn does not have rightAssociative + delete token.type.rightAssociative; } return token; diff --git a/eslint/babel-eslint-parser/src/visitor-keys.js b/eslint/babel-eslint-parser/src/visitor-keys.js index 6676a86602e3..9908664dced8 100644 --- a/eslint/babel-eslint-parser/src/visitor-keys.js +++ b/eslint/babel-eslint-parser/src/visitor-keys.js @@ -1,10 +1,13 @@ import { types as t } from "@babel/core"; import { KEYS as ESLINT_VISITOR_KEYS } from "eslint-visitor-keys"; -const { VISITOR_KEYS: BABEL_VISITOR_KEYS } = t; +/*eslint no-unused-vars: ["error", { "ignoreRestSiblings": true }]*/ +const { ExportAllDeclaration, ...BABEL_VISITOR_KEYS } = t.VISITOR_KEYS; export default Object.assign( { + ChainExpression: ESLINT_VISITOR_KEYS.ChainExpression, + ExportAllDeclaration: ESLINT_VISITOR_KEYS.ExportAllDeclaration, Literal: ESLINT_VISITOR_KEYS.Literal, MethodDefinition: ["decorators"].concat( ESLINT_VISITOR_KEYS.MethodDefinition, diff --git a/eslint/babel-eslint-parser/test/index.js b/eslint/babel-eslint-parser/test/index.js index bea8b50ef894..e662efa3aa71 100644 --- a/eslint/babel-eslint-parser/test/index.js +++ b/eslint/babel-eslint-parser/test/index.js @@ -253,6 +253,10 @@ describe("Babel and Espree", () => { parseAndAssertSame('import "foo";'); }); + it("import meta", () => { + parseAndAssertSame("const url = import.meta.url"); + }); + it("export default class declaration", () => { parseAndAssertSame("export default class Foo {}"); }); @@ -273,15 +277,8 @@ describe("Babel and Espree", () => { parseAndAssertSame('export * from "foo";'); }); - // Espree doesn't support `export * as ns` yet it("export * as ns", () => { - const code = 'export * as Foo from "foo";'; - const babylonAST = parseForESLint(code, { - eslintVisitorKeys: true, - eslintScopeManager: true, - babelOptions: BABEL_OPTIONS, - }).ast; - expect(babylonAST.tokens[1].type).toEqual("Punctuator"); + parseAndAssertSame('export * as Foo from "foo";'); }); it("export named", () => { @@ -292,26 +289,12 @@ describe("Babel and Espree", () => { parseAndAssertSame("var foo = 1;export { foo as bar };"); }); - // Espree doesn't support the optional chaining operator yet - it("optional chaining operator (token)", () => { - const code = "foo?.bar"; - const babylonAST = parseForESLint(code, { - eslintVisitorKeys: true, - eslintScopeManager: true, - babelOptions: BABEL_OPTIONS, - }).ast; - expect(babylonAST.tokens[1].type).toEqual("Punctuator"); + it("optional chaining operator", () => { + parseAndAssertSame("foo?.bar?.().qux()"); }); - // Espree doesn't support the nullish coalescing operator yet - it("nullish coalescing operator (token)", () => { - const code = "foo ?? bar"; - const babylonAST = parseForESLint(code, { - eslintVisitorKeys: true, - eslintScopeManager: true, - babelOptions: BABEL_OPTIONS, - }).ast; - expect(babylonAST.tokens[1].type).toEqual("Punctuator"); + it("nullish coalescing operator", () => { + parseAndAssertSame("foo ?? bar"); }); // Espree doesn't support the pipeline operator yet diff --git a/eslint/babel-eslint-plugin/src/rules/no-unused-expressions.js b/eslint/babel-eslint-plugin/src/rules/no-unused-expressions.js index a313b0743245..455153474668 100644 --- a/eslint/babel-eslint-plugin/src/rules/no-unused-expressions.js +++ b/eslint/babel-eslint-plugin/src/rules/no-unused-expressions.js @@ -53,7 +53,8 @@ function isOptionalCallExpression(node) { return ( !!node && node.type === "ExpressionStatement" && - node.expression.type === "OptionalCallExpression" + node.expression.type === "ChainExpression" && + node.expression.expression.type === "CallExpression" ); } diff --git a/packages/babel-parser/src/plugins/estree.js b/packages/babel-parser/src/plugins/estree.js index 6c5f90780ea0..b4ab6e9b0110 100644 --- a/packages/babel-parser/src/plugins/estree.js +++ b/packages/babel-parser/src/plugins/estree.js @@ -374,8 +374,6 @@ export default (superClass: Class): Class => delete node.arguments; // $FlowIgnore - callee isn't optional in the type definition delete node.callee; - } else if (node.type === "CallExpression") { - (node: N.Node).optional = false; } return node; @@ -417,10 +415,38 @@ export default (superClass: Class): Class => return node; } - parseSubscript(...args) { - const node = super.parseSubscript(...args); + parseSubscript( + base: N.Expression, + startPos: number, + startLoc: Position, + noCalls: ?boolean, + state: N.ParseSubscriptState, + ) { + const node = super.parseSubscript( + base, + startPos, + startLoc, + noCalls, + state, + ); - if (node.type === "MemberExpression") { + if (state.optionalChainMember) { + // https://github.com/estree/estree/blob/master/es2020.md#chainexpression + if ( + node.type === "OptionalMemberExpression" || + node.type === "OptionalCallExpression" + ) { + node.type = node.type.substring(8); // strip Optional prefix + } + if (state.stop) { + const chain = this.startNodeAtNode(node); + chain.expression = node; + return this.finishNode(chain, "ChainExpression"); + } + } else if ( + node.type === "MemberExpression" || + node.type === "CallExpression" + ) { node.optional = false; } diff --git a/packages/babel-parser/test/fixtures/estree/optional-chaining/optional-call-call/input.js b/packages/babel-parser/test/fixtures/estree/optional-chaining/optional-call-call/input.js new file mode 100644 index 000000000000..b3d7b711391b --- /dev/null +++ b/packages/babel-parser/test/fixtures/estree/optional-chaining/optional-call-call/input.js @@ -0,0 +1 @@ +(foo?.())() diff --git a/packages/babel-parser/test/fixtures/estree/optional-chaining/optional-call-call/output.json b/packages/babel-parser/test/fixtures/estree/optional-chaining/optional-call-call/output.json new file mode 100644 index 000000000000..5c349122bede --- /dev/null +++ b/packages/babel-parser/test/fixtures/estree/optional-chaining/optional-call-call/output.json @@ -0,0 +1,41 @@ +{ + "type": "File", + "start":0,"end":11,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":11}}, + "program": { + "type": "Program", + "start":0,"end":11,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":11}}, + "sourceType": "script", + "interpreter": null, + "body": [ + { + "type": "ExpressionStatement", + "start":0,"end":11,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":11}}, + "expression": { + "type": "CallExpression", + "start":0,"end":11,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":11}}, + "callee": { + "type": "ChainExpression", + "start":1,"end":8,"loc":{"start":{"line":1,"column":1},"end":{"line":1,"column":8}}, + "expression": { + "type": "CallExpression", + "start":1,"end":8,"loc":{"start":{"line":1,"column":1},"end":{"line":1,"column":8}}, + "callee": { + "type": "Identifier", + "start":1,"end":4,"loc":{"start":{"line":1,"column":1},"end":{"line":1,"column":4},"identifierName":"foo"}, + "name": "foo" + }, + "optional": true, + "arguments": [] + }, + "extra": { + "parenthesized": true, + "parenStart": 0 + } + }, + "arguments": [], + "optional": false + } + } + ] + } +} \ No newline at end of file diff --git a/packages/babel-parser/test/fixtures/estree/optional-chaining/optional-call-chained-call/input.js b/packages/babel-parser/test/fixtures/estree/optional-chaining/optional-call-chained-call/input.js new file mode 100644 index 000000000000..2b31720258c8 --- /dev/null +++ b/packages/babel-parser/test/fixtures/estree/optional-chaining/optional-call-chained-call/input.js @@ -0,0 +1 @@ +foo?.()() diff --git a/packages/babel-parser/test/fixtures/estree/optional-chaining/optional-call-chained-call/output.json b/packages/babel-parser/test/fixtures/estree/optional-chaining/optional-call-chained-call/output.json new file mode 100644 index 000000000000..c09278489170 --- /dev/null +++ b/packages/babel-parser/test/fixtures/estree/optional-chaining/optional-call-chained-call/output.json @@ -0,0 +1,37 @@ +{ + "type": "File", + "start":0,"end":9,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":9}}, + "program": { + "type": "Program", + "start":0,"end":9,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":9}}, + "sourceType": "script", + "interpreter": null, + "body": [ + { + "type": "ExpressionStatement", + "start":0,"end":9,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":9}}, + "expression": { + "type": "ChainExpression", + "start":0,"end":9,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":9}}, + "expression": { + "type": "CallExpression", + "start":0,"end":9,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":9}}, + "callee": { + "type": "CallExpression", + "start":0,"end":7,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":7}}, + "callee": { + "type": "Identifier", + "start":0,"end":3,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":3},"identifierName":"foo"}, + "name": "foo" + }, + "optional": true, + "arguments": [] + }, + "optional": false, + "arguments": [] + } + } + } + ] + } +} \ No newline at end of file diff --git a/packages/babel-parser/test/fixtures/estree/optional-chaining/optional-call-chained-member/input.js b/packages/babel-parser/test/fixtures/estree/optional-chaining/optional-call-chained-member/input.js new file mode 100644 index 000000000000..807074cdb89a --- /dev/null +++ b/packages/babel-parser/test/fixtures/estree/optional-chaining/optional-call-chained-member/input.js @@ -0,0 +1 @@ +foo?.().bar diff --git a/packages/babel-parser/test/fixtures/estree/optional-chaining/optional-call-chained-member/output.json b/packages/babel-parser/test/fixtures/estree/optional-chaining/optional-call-chained-member/output.json new file mode 100644 index 000000000000..9369e8f489a2 --- /dev/null +++ b/packages/babel-parser/test/fixtures/estree/optional-chaining/optional-call-chained-member/output.json @@ -0,0 +1,42 @@ +{ + "type": "File", + "start":0,"end":11,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":11}}, + "program": { + "type": "Program", + "start":0,"end":11,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":11}}, + "sourceType": "script", + "interpreter": null, + "body": [ + { + "type": "ExpressionStatement", + "start":0,"end":11,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":11}}, + "expression": { + "type": "ChainExpression", + "start":0,"end":11,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":11}}, + "expression": { + "type": "MemberExpression", + "start":0,"end":11,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":11}}, + "object": { + "type": "CallExpression", + "start":0,"end":7,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":7}}, + "callee": { + "type": "Identifier", + "start":0,"end":3,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":3},"identifierName":"foo"}, + "name": "foo" + }, + "optional": true, + "arguments": [] + }, + "property": { + "type": "Identifier", + "start":8,"end":11,"loc":{"start":{"line":1,"column":8},"end":{"line":1,"column":11},"identifierName":"bar"}, + "name": "bar" + }, + "computed": false, + "optional": false + } + } + } + ] + } +} \ No newline at end of file diff --git a/packages/babel-parser/test/fixtures/estree/optional-chaining/optional-call-member/input.js b/packages/babel-parser/test/fixtures/estree/optional-chaining/optional-call-member/input.js new file mode 100644 index 000000000000..1d1d847e00d2 --- /dev/null +++ b/packages/babel-parser/test/fixtures/estree/optional-chaining/optional-call-member/input.js @@ -0,0 +1 @@ +(foo?.()).bar diff --git a/packages/babel-parser/test/fixtures/estree/optional-chaining/optional-call-member/output.json b/packages/babel-parser/test/fixtures/estree/optional-chaining/optional-call-member/output.json new file mode 100644 index 000000000000..0fe7f00909fd --- /dev/null +++ b/packages/babel-parser/test/fixtures/estree/optional-chaining/optional-call-member/output.json @@ -0,0 +1,46 @@ +{ + "type": "File", + "start":0,"end":13,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":13}}, + "program": { + "type": "Program", + "start":0,"end":13,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":13}}, + "sourceType": "script", + "interpreter": null, + "body": [ + { + "type": "ExpressionStatement", + "start":0,"end":13,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":13}}, + "expression": { + "type": "MemberExpression", + "start":0,"end":13,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":13}}, + "object": { + "type": "ChainExpression", + "start":1,"end":8,"loc":{"start":{"line":1,"column":1},"end":{"line":1,"column":8}}, + "expression": { + "type": "CallExpression", + "start":1,"end":8,"loc":{"start":{"line":1,"column":1},"end":{"line":1,"column":8}}, + "callee": { + "type": "Identifier", + "start":1,"end":4,"loc":{"start":{"line":1,"column":1},"end":{"line":1,"column":4},"identifierName":"foo"}, + "name": "foo" + }, + "optional": true, + "arguments": [] + }, + "extra": { + "parenthesized": true, + "parenStart": 0 + } + }, + "property": { + "type": "Identifier", + "start":10,"end":13,"loc":{"start":{"line":1,"column":10},"end":{"line":1,"column":13},"identifierName":"bar"}, + "name": "bar" + }, + "computed": false, + "optional": false + } + } + ] + } +} \ No newline at end of file diff --git a/packages/babel-parser/test/fixtures/estree/optional-chaining/optional-call-optional-call/input.js b/packages/babel-parser/test/fixtures/estree/optional-chaining/optional-call-optional-call/input.js new file mode 100644 index 000000000000..37fc6ab1c9ea --- /dev/null +++ b/packages/babel-parser/test/fixtures/estree/optional-chaining/optional-call-optional-call/input.js @@ -0,0 +1 @@ +foo?.()?.() diff --git a/packages/babel-parser/test/fixtures/estree/optional-chaining/optional-call-optional-call/output.json b/packages/babel-parser/test/fixtures/estree/optional-chaining/optional-call-optional-call/output.json new file mode 100644 index 000000000000..5f3a6de4284b --- /dev/null +++ b/packages/babel-parser/test/fixtures/estree/optional-chaining/optional-call-optional-call/output.json @@ -0,0 +1,37 @@ +{ + "type": "File", + "start":0,"end":11,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":11}}, + "program": { + "type": "Program", + "start":0,"end":11,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":11}}, + "sourceType": "script", + "interpreter": null, + "body": [ + { + "type": "ExpressionStatement", + "start":0,"end":11,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":11}}, + "expression": { + "type": "ChainExpression", + "start":0,"end":11,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":11}}, + "expression": { + "type": "CallExpression", + "start":0,"end":11,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":11}}, + "callee": { + "type": "CallExpression", + "start":0,"end":7,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":7}}, + "callee": { + "type": "Identifier", + "start":0,"end":3,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":3},"identifierName":"foo"}, + "name": "foo" + }, + "optional": true, + "arguments": [] + }, + "optional": true, + "arguments": [] + } + } + } + ] + } +} \ No newline at end of file diff --git a/packages/babel-parser/test/fixtures/estree/optional-chaining/optional-call-optional-member/input.js b/packages/babel-parser/test/fixtures/estree/optional-chaining/optional-call-optional-member/input.js new file mode 100644 index 000000000000..224bf8cbcf4a --- /dev/null +++ b/packages/babel-parser/test/fixtures/estree/optional-chaining/optional-call-optional-member/input.js @@ -0,0 +1 @@ +foo?.()?.bar diff --git a/packages/babel-parser/test/fixtures/estree/optional-chaining/optional-call-optional-member/output.json b/packages/babel-parser/test/fixtures/estree/optional-chaining/optional-call-optional-member/output.json new file mode 100644 index 000000000000..e80ce5e918cd --- /dev/null +++ b/packages/babel-parser/test/fixtures/estree/optional-chaining/optional-call-optional-member/output.json @@ -0,0 +1,42 @@ +{ + "type": "File", + "start":0,"end":12,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":12}}, + "program": { + "type": "Program", + "start":0,"end":12,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":12}}, + "sourceType": "script", + "interpreter": null, + "body": [ + { + "type": "ExpressionStatement", + "start":0,"end":12,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":12}}, + "expression": { + "type": "ChainExpression", + "start":0,"end":12,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":12}}, + "expression": { + "type": "MemberExpression", + "start":0,"end":12,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":12}}, + "object": { + "type": "CallExpression", + "start":0,"end":7,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":7}}, + "callee": { + "type": "Identifier", + "start":0,"end":3,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":3},"identifierName":"foo"}, + "name": "foo" + }, + "optional": true, + "arguments": [] + }, + "property": { + "type": "Identifier", + "start":9,"end":12,"loc":{"start":{"line":1,"column":9},"end":{"line":1,"column":12},"identifierName":"bar"}, + "name": "bar" + }, + "computed": false, + "optional": true + } + } + } + ] + } +} \ No newline at end of file diff --git a/packages/babel-parser/test/fixtures/estree/optional-chaining/optional-call/input.js b/packages/babel-parser/test/fixtures/estree/optional-chaining/optional-call/input.js new file mode 100644 index 000000000000..58728f9a32ee --- /dev/null +++ b/packages/babel-parser/test/fixtures/estree/optional-chaining/optional-call/input.js @@ -0,0 +1 @@ +foo?.() diff --git a/packages/babel-parser/test/fixtures/estree/optional-chaining/optional-call/output.json b/packages/babel-parser/test/fixtures/estree/optional-chaining/optional-call/output.json new file mode 100644 index 000000000000..fa463157eecd --- /dev/null +++ b/packages/babel-parser/test/fixtures/estree/optional-chaining/optional-call/output.json @@ -0,0 +1,31 @@ +{ + "type": "File", + "start":0,"end":7,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":7}}, + "program": { + "type": "Program", + "start":0,"end":7,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":7}}, + "sourceType": "script", + "interpreter": null, + "body": [ + { + "type": "ExpressionStatement", + "start":0,"end":7,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":7}}, + "expression": { + "type": "ChainExpression", + "start":0,"end":7,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":7}}, + "expression": { + "type": "CallExpression", + "start":0,"end":7,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":7}}, + "callee": { + "type": "Identifier", + "start":0,"end":3,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":3},"identifierName":"foo"}, + "name": "foo" + }, + "optional": true, + "arguments": [] + } + } + } + ] + } +} \ No newline at end of file diff --git a/packages/babel-parser/test/fixtures/estree/optional-chaining/optional-member-call/input.js b/packages/babel-parser/test/fixtures/estree/optional-chaining/optional-member-call/input.js new file mode 100644 index 000000000000..36546dc139c4 --- /dev/null +++ b/packages/babel-parser/test/fixtures/estree/optional-chaining/optional-member-call/input.js @@ -0,0 +1 @@ +(foo?.bar)() diff --git a/packages/babel-parser/test/fixtures/estree/optional-chaining/optional-member-call/output.json b/packages/babel-parser/test/fixtures/estree/optional-chaining/optional-member-call/output.json new file mode 100644 index 000000000000..71ea0bec2f4d --- /dev/null +++ b/packages/babel-parser/test/fixtures/estree/optional-chaining/optional-member-call/output.json @@ -0,0 +1,46 @@ +{ + "type": "File", + "start":0,"end":12,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":12}}, + "program": { + "type": "Program", + "start":0,"end":12,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":12}}, + "sourceType": "script", + "interpreter": null, + "body": [ + { + "type": "ExpressionStatement", + "start":0,"end":12,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":12}}, + "expression": { + "type": "CallExpression", + "start":0,"end":12,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":12}}, + "callee": { + "type": "ChainExpression", + "start":1,"end":9,"loc":{"start":{"line":1,"column":1},"end":{"line":1,"column":9}}, + "expression": { + "type": "MemberExpression", + "start":1,"end":9,"loc":{"start":{"line":1,"column":1},"end":{"line":1,"column":9}}, + "object": { + "type": "Identifier", + "start":1,"end":4,"loc":{"start":{"line":1,"column":1},"end":{"line":1,"column":4},"identifierName":"foo"}, + "name": "foo" + }, + "property": { + "type": "Identifier", + "start":6,"end":9,"loc":{"start":{"line":1,"column":6},"end":{"line":1,"column":9},"identifierName":"bar"}, + "name": "bar" + }, + "computed": false, + "optional": true + }, + "extra": { + "parenthesized": true, + "parenStart": 0 + } + }, + "arguments": [], + "optional": false + } + } + ] + } +} \ No newline at end of file diff --git a/packages/babel-parser/test/fixtures/estree/optional-chaining/optional-member-chained-call/input.js b/packages/babel-parser/test/fixtures/estree/optional-chaining/optional-member-chained-call/input.js new file mode 100644 index 000000000000..62587bbd256a --- /dev/null +++ b/packages/babel-parser/test/fixtures/estree/optional-chaining/optional-member-chained-call/input.js @@ -0,0 +1 @@ +foo?.bar() diff --git a/packages/babel-parser/test/fixtures/estree/optional-chaining/optional-member-chained-call/output.json b/packages/babel-parser/test/fixtures/estree/optional-chaining/optional-member-chained-call/output.json new file mode 100644 index 000000000000..b09b5792ae77 --- /dev/null +++ b/packages/babel-parser/test/fixtures/estree/optional-chaining/optional-member-chained-call/output.json @@ -0,0 +1,42 @@ +{ + "type": "File", + "start":0,"end":10,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":10}}, + "program": { + "type": "Program", + "start":0,"end":10,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":10}}, + "sourceType": "script", + "interpreter": null, + "body": [ + { + "type": "ExpressionStatement", + "start":0,"end":10,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":10}}, + "expression": { + "type": "ChainExpression", + "start":0,"end":10,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":10}}, + "expression": { + "type": "CallExpression", + "start":0,"end":10,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":10}}, + "callee": { + "type": "MemberExpression", + "start":0,"end":8,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":8}}, + "object": { + "type": "Identifier", + "start":0,"end":3,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":3},"identifierName":"foo"}, + "name": "foo" + }, + "property": { + "type": "Identifier", + "start":5,"end":8,"loc":{"start":{"line":1,"column":5},"end":{"line":1,"column":8},"identifierName":"bar"}, + "name": "bar" + }, + "computed": false, + "optional": true + }, + "optional": false, + "arguments": [] + } + } + } + ] + } +} \ No newline at end of file diff --git a/packages/babel-parser/test/fixtures/estree/optional-chaining/optional-member-chained-member/input.js b/packages/babel-parser/test/fixtures/estree/optional-chaining/optional-member-chained-member/input.js new file mode 100644 index 000000000000..bb1224f5f2d2 --- /dev/null +++ b/packages/babel-parser/test/fixtures/estree/optional-chaining/optional-member-chained-member/input.js @@ -0,0 +1 @@ +foo?.bar.qux diff --git a/packages/babel-parser/test/fixtures/estree/optional-chaining/optional-member-chained-member/output.json b/packages/babel-parser/test/fixtures/estree/optional-chaining/optional-member-chained-member/output.json new file mode 100644 index 000000000000..ad36a4f6b33d --- /dev/null +++ b/packages/babel-parser/test/fixtures/estree/optional-chaining/optional-member-chained-member/output.json @@ -0,0 +1,47 @@ +{ + "type": "File", + "start":0,"end":12,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":12}}, + "program": { + "type": "Program", + "start":0,"end":12,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":12}}, + "sourceType": "script", + "interpreter": null, + "body": [ + { + "type": "ExpressionStatement", + "start":0,"end":12,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":12}}, + "expression": { + "type": "ChainExpression", + "start":0,"end":12,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":12}}, + "expression": { + "type": "MemberExpression", + "start":0,"end":12,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":12}}, + "object": { + "type": "MemberExpression", + "start":0,"end":8,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":8}}, + "object": { + "type": "Identifier", + "start":0,"end":3,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":3},"identifierName":"foo"}, + "name": "foo" + }, + "property": { + "type": "Identifier", + "start":5,"end":8,"loc":{"start":{"line":1,"column":5},"end":{"line":1,"column":8},"identifierName":"bar"}, + "name": "bar" + }, + "computed": false, + "optional": true + }, + "property": { + "type": "Identifier", + "start":9,"end":12,"loc":{"start":{"line":1,"column":9},"end":{"line":1,"column":12},"identifierName":"qux"}, + "name": "qux" + }, + "computed": false, + "optional": false + } + } + } + ] + } +} \ No newline at end of file diff --git a/packages/babel-parser/test/fixtures/estree/optional-chaining/optional-member-member/input.js b/packages/babel-parser/test/fixtures/estree/optional-chaining/optional-member-member/input.js new file mode 100644 index 000000000000..92d4b9c2e976 --- /dev/null +++ b/packages/babel-parser/test/fixtures/estree/optional-chaining/optional-member-member/input.js @@ -0,0 +1 @@ +(foo?.bar).qux diff --git a/packages/babel-parser/test/fixtures/estree/optional-chaining/optional-member-member/output.json b/packages/babel-parser/test/fixtures/estree/optional-chaining/optional-member-member/output.json new file mode 100644 index 000000000000..0e9d26ac4e78 --- /dev/null +++ b/packages/babel-parser/test/fixtures/estree/optional-chaining/optional-member-member/output.json @@ -0,0 +1,51 @@ +{ + "type": "File", + "start":0,"end":14,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":14}}, + "program": { + "type": "Program", + "start":0,"end":14,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":14}}, + "sourceType": "script", + "interpreter": null, + "body": [ + { + "type": "ExpressionStatement", + "start":0,"end":14,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":14}}, + "expression": { + "type": "MemberExpression", + "start":0,"end":14,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":14}}, + "object": { + "type": "ChainExpression", + "start":1,"end":9,"loc":{"start":{"line":1,"column":1},"end":{"line":1,"column":9}}, + "expression": { + "type": "MemberExpression", + "start":1,"end":9,"loc":{"start":{"line":1,"column":1},"end":{"line":1,"column":9}}, + "object": { + "type": "Identifier", + "start":1,"end":4,"loc":{"start":{"line":1,"column":1},"end":{"line":1,"column":4},"identifierName":"foo"}, + "name": "foo" + }, + "property": { + "type": "Identifier", + "start":6,"end":9,"loc":{"start":{"line":1,"column":6},"end":{"line":1,"column":9},"identifierName":"bar"}, + "name": "bar" + }, + "computed": false, + "optional": true + }, + "extra": { + "parenthesized": true, + "parenStart": 0 + } + }, + "property": { + "type": "Identifier", + "start":11,"end":14,"loc":{"start":{"line":1,"column":11},"end":{"line":1,"column":14},"identifierName":"qux"}, + "name": "qux" + }, + "computed": false, + "optional": false + } + } + ] + } +} \ No newline at end of file diff --git a/packages/babel-parser/test/fixtures/estree/optional-chaining/optional-member-optional-call/input.js b/packages/babel-parser/test/fixtures/estree/optional-chaining/optional-member-optional-call/input.js new file mode 100644 index 000000000000..5585979981d2 --- /dev/null +++ b/packages/babel-parser/test/fixtures/estree/optional-chaining/optional-member-optional-call/input.js @@ -0,0 +1 @@ +foo?.bar?.() diff --git a/packages/babel-parser/test/fixtures/estree/optional-chaining/optional-member-optional-call/output.json b/packages/babel-parser/test/fixtures/estree/optional-chaining/optional-member-optional-call/output.json new file mode 100644 index 000000000000..c6d55b054ad1 --- /dev/null +++ b/packages/babel-parser/test/fixtures/estree/optional-chaining/optional-member-optional-call/output.json @@ -0,0 +1,42 @@ +{ + "type": "File", + "start":0,"end":12,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":12}}, + "program": { + "type": "Program", + "start":0,"end":12,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":12}}, + "sourceType": "script", + "interpreter": null, + "body": [ + { + "type": "ExpressionStatement", + "start":0,"end":12,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":12}}, + "expression": { + "type": "ChainExpression", + "start":0,"end":12,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":12}}, + "expression": { + "type": "CallExpression", + "start":0,"end":12,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":12}}, + "callee": { + "type": "MemberExpression", + "start":0,"end":8,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":8}}, + "object": { + "type": "Identifier", + "start":0,"end":3,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":3},"identifierName":"foo"}, + "name": "foo" + }, + "property": { + "type": "Identifier", + "start":5,"end":8,"loc":{"start":{"line":1,"column":5},"end":{"line":1,"column":8},"identifierName":"bar"}, + "name": "bar" + }, + "computed": false, + "optional": true + }, + "optional": true, + "arguments": [] + } + } + } + ] + } +} \ No newline at end of file diff --git a/packages/babel-parser/test/fixtures/estree/optional-chaining/optional-member-optional-member/input.js b/packages/babel-parser/test/fixtures/estree/optional-chaining/optional-member-optional-member/input.js new file mode 100644 index 000000000000..732b09bd4eed --- /dev/null +++ b/packages/babel-parser/test/fixtures/estree/optional-chaining/optional-member-optional-member/input.js @@ -0,0 +1 @@ +foo?.bar?.qux diff --git a/packages/babel-parser/test/fixtures/estree/optional-chaining/optional-member-optional-member/output.json b/packages/babel-parser/test/fixtures/estree/optional-chaining/optional-member-optional-member/output.json new file mode 100644 index 000000000000..0bbc05854982 --- /dev/null +++ b/packages/babel-parser/test/fixtures/estree/optional-chaining/optional-member-optional-member/output.json @@ -0,0 +1,47 @@ +{ + "type": "File", + "start":0,"end":13,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":13}}, + "program": { + "type": "Program", + "start":0,"end":13,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":13}}, + "sourceType": "script", + "interpreter": null, + "body": [ + { + "type": "ExpressionStatement", + "start":0,"end":13,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":13}}, + "expression": { + "type": "ChainExpression", + "start":0,"end":13,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":13}}, + "expression": { + "type": "MemberExpression", + "start":0,"end":13,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":13}}, + "object": { + "type": "MemberExpression", + "start":0,"end":8,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":8}}, + "object": { + "type": "Identifier", + "start":0,"end":3,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":3},"identifierName":"foo"}, + "name": "foo" + }, + "property": { + "type": "Identifier", + "start":5,"end":8,"loc":{"start":{"line":1,"column":5},"end":{"line":1,"column":8},"identifierName":"bar"}, + "name": "bar" + }, + "computed": false, + "optional": true + }, + "property": { + "type": "Identifier", + "start":10,"end":13,"loc":{"start":{"line":1,"column":10},"end":{"line":1,"column":13},"identifierName":"qux"}, + "name": "qux" + }, + "computed": false, + "optional": true + } + } + } + ] + } +} \ No newline at end of file diff --git a/packages/babel-parser/test/fixtures/estree/optional-chaining/optional-member/input.js b/packages/babel-parser/test/fixtures/estree/optional-chaining/optional-member/input.js new file mode 100644 index 000000000000..6ed5c83b9389 --- /dev/null +++ b/packages/babel-parser/test/fixtures/estree/optional-chaining/optional-member/input.js @@ -0,0 +1 @@ +foo?.bar diff --git a/packages/babel-parser/test/fixtures/estree/optional-chaining/optional-member/output.json b/packages/babel-parser/test/fixtures/estree/optional-chaining/optional-member/output.json new file mode 100644 index 000000000000..2429cf521f27 --- /dev/null +++ b/packages/babel-parser/test/fixtures/estree/optional-chaining/optional-member/output.json @@ -0,0 +1,36 @@ +{ + "type": "File", + "start":0,"end":8,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":8}}, + "program": { + "type": "Program", + "start":0,"end":8,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":8}}, + "sourceType": "script", + "interpreter": null, + "body": [ + { + "type": "ExpressionStatement", + "start":0,"end":8,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":8}}, + "expression": { + "type": "ChainExpression", + "start":0,"end":8,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":8}}, + "expression": { + "type": "MemberExpression", + "start":0,"end":8,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":8}}, + "object": { + "type": "Identifier", + "start":0,"end":3,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":3},"identifierName":"foo"}, + "name": "foo" + }, + "property": { + "type": "Identifier", + "start":5,"end":8,"loc":{"start":{"line":1,"column":5},"end":{"line":1,"column":8},"identifierName":"bar"}, + "name": "bar" + }, + "computed": false, + "optional": true + } + } + } + ] + } +} \ No newline at end of file diff --git a/yarn.lock b/yarn.lock index be37146a7a73..f9a88e060136 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2120,12 +2120,7 @@ acorn@^6.0.1: resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.4.1.tgz#531e58ba3f51b9dacb9a6646ca4debf5b14ca474" integrity sha512-ZVA9k326Nwrj3Cj9jlh3wGFutC2ZornPNARZwsNYqQYgN0EsV2d53w5RN/co65Ohn4sUAUtb1rSUAOD6XN9idA== -acorn@^7.0.0, acorn@^7.1.0: - version "7.1.1" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.1.1.tgz#e35668de0b402f359de515c5482a1ab9f89a69bf" - integrity sha512-add7dgA5ppRPxCFJoAGfMDi7PIBXq1RtGo7BhbLaxwrXPOmw8gq48Y9ozT01hUKy9byMjlR20EJhu5zlkErEkg== - -acorn@^7.1.1: +acorn@^7.0.0, acorn@^7.1.0, acorn@^7.1.1: version "7.3.1" resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.3.1.tgz#85010754db53c3fbaf3b9ea3e083aa5c5d147ffd" integrity sha512-tLc0wSnatxAQHVHUapaHdz72pi9KUyHjq5KyHjGg9Y8Ifdc79pTh2XvI6I1/chZbnM7QtNKzh66ooDogPZSleA== @@ -4365,7 +4360,7 @@ eslint-plugin-prettier@^3.1.2: dependencies: prettier-linter-helpers "^1.0.0" -eslint-scope@5.0.0, eslint-scope@^5.0.0: +eslint-scope@5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.0.0.tgz#e87c8887c73e8d1ec84f1ca591645c358bfc8fb9" integrity sha512-oYrhJW7S0bxAFDvWqzvMPRm6pcgcnWc4QnofCAqRTRfQC0JcwenzGglTtsLyIuuWFfkqDG9vz67cnttSd53djw== @@ -4373,6 +4368,14 @@ eslint-scope@5.0.0, eslint-scope@^5.0.0: esrecurse "^4.1.0" estraverse "^4.1.1" +eslint-scope@5.1.0, eslint-scope@^5.0.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.0.tgz#d0f971dfe59c69e0cada684b23d49dbf82600ce5" + integrity sha512-iiGRvtxWqgtx5m8EyQUJihBloE4EnYeGE/bz1wSPwJE6tZuJUtHlhqDM4Xj2ukE8Dyy1+HCZ4hE0fzIVMzb58w== + dependencies: + esrecurse "^4.1.0" + estraverse "^4.1.1" + eslint-utils@^1.4.3: version "1.4.3" resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-1.4.3.tgz#74fec7c54d0776b6f67e0251040b5806564e981f" @@ -4380,10 +4383,10 @@ eslint-utils@^1.4.3: dependencies: eslint-visitor-keys "^1.1.0" -eslint-visitor-keys@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.1.0.tgz#e2a82cea84ff246ad6fb57f9bde5b46621459ec2" - integrity sha512-8y9YjtM1JBJU/A9Kc+SbaOV4y29sSWckBwMHa+FGtVj5gN/sbnKDf6xJUl+8g7FAij9LVaP8C24DUiH/f/2Z9A== +eslint-visitor-keys@^1.1.0, eslint-visitor-keys@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz#30ebd1ef7c2fdff01c3a4f151044af25fab0523e" + integrity sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ== eslint@^6.8.0: version "6.8.0"