diff --git a/packages/babel-generator/src/generators/expressions.js b/packages/babel-generator/src/generators/expressions.js index 884d9acd077f..e85eec65380d 100644 --- a/packages/babel-generator/src/generators/expressions.js +++ b/packages/babel-generator/src/generators/expressions.js @@ -95,7 +95,34 @@ export function Decorator(node: Object) { this.newline(); } -export function CallExpression(node: Object) { +export function OptionalMemberExpression(node: Object) { + this.print(node.object, node); + + if (!node.computed && t.isMemberExpression(node.property)) { + throw new TypeError("Got a MemberExpression for MemberExpression property"); + } + + let computed = node.computed; + if (t.isLiteral(node.property) && typeof node.property.value === "number") { + computed = true; + } + if (node.optional) { + this.token("?."); + } + + if (computed) { + this.token("["); + this.print(node.property, node); + this.token("]"); + } else { + if (!node.optional) { + this.token("."); + } + this.print(node.property, node); + } +} + +export function OptionalCallExpression(node: Object) { this.print(node.callee, node); this.print(node.typeParameters, node); // TS @@ -108,6 +135,15 @@ export function CallExpression(node: Object) { this.token(")"); } +export function CallExpression(node: Object) { + this.print(node.callee, node); + + this.print(node.typeParameters, node); // TS + this.token("("); + this.printList(node.arguments, node); + this.token(")"); +} + export function Import() { this.word("import"); } @@ -203,17 +239,12 @@ export function MemberExpression(node: Object) { computed = true; } - if (node.optional) { - this.token("?."); - } if (computed) { this.token("["); this.print(node.property, node); this.token("]"); } else { - if (!node.optional) { - this.token("."); - } + this.token("."); this.print(node.property, node); } } diff --git a/packages/babel-generator/test/fixtures/types/Optional-NewExpression/input.js b/packages/babel-generator/test/fixtures/types/Optional-NewExpression/input.js deleted file mode 100644 index fe994af68f65..000000000000 --- a/packages/babel-generator/test/fixtures/types/Optional-NewExpression/input.js +++ /dev/null @@ -1,39 +0,0 @@ -new foo?.(); -new foo?.("foo"); -new foo?.("foo", "bar"); -new foo?.(bar()); -new foo?.(bar("test")); -foo(new bar?.()); -foo(new bar?.("test")); - -new a.foo?.(); -new a.foo?.("foo"); -new a.foo?.("foo", "bar"); -new a.foo?.(bar()); -new a.foo?.(bar("test")); -a.foo(new bar?.()); -a.foo(new bar?.("test")); - -new a?.foo?.(); -new a?.foo?.("foo"); -new a?.foo?.("foo", "bar"); -new a?.foo?.(bar()); -new a?.foo?.(bar("test")); -a?.foo(new bar?.()); -a?.foo(new bar?.("test")); - -new a.foo?.().baz; -new a.foo?.("foo").baz; -new a.foo?.("foo", "bar").baz; -new a.foo?.(bar()).baz; -new a.foo?.(bar("test")).baz; -a.foo(new bar?.()).baz; -a.foo(new bar?.("test")).baz; - -new a.foo?.()?.baz; -new a.foo?.("foo")?.baz; -new a.foo?.("foo", "bar")?.baz; -new a.foo?.(bar())?.baz; -new a.foo?.(bar("test"))?.baz; -a.foo(new bar?.())?.baz; -a.foo(new bar?.("test"))?.baz; diff --git a/packages/babel-generator/test/fixtures/types/Optional-NewExpression/options.json b/packages/babel-generator/test/fixtures/types/Optional-NewExpression/options.json deleted file mode 100644 index b4da7fc0667c..000000000000 --- a/packages/babel-generator/test/fixtures/types/Optional-NewExpression/options.json +++ /dev/null @@ -1 +0,0 @@ -{ "plugins": ["optionalChaining"] } \ No newline at end of file diff --git a/packages/babel-generator/test/fixtures/types/Optional-NewExpression/output.js b/packages/babel-generator/test/fixtures/types/Optional-NewExpression/output.js deleted file mode 100644 index 22e72fe05b5b..000000000000 --- a/packages/babel-generator/test/fixtures/types/Optional-NewExpression/output.js +++ /dev/null @@ -1,35 +0,0 @@ -new foo?.(); -new foo?.("foo"); -new foo?.("foo", "bar"); -new foo?.(bar()); -new foo?.(bar("test")); -foo(new bar?.()); -foo(new bar?.("test")); -new a.foo?.(); -new a.foo?.("foo"); -new a.foo?.("foo", "bar"); -new a.foo?.(bar()); -new a.foo?.(bar("test")); -a.foo(new bar?.()); -a.foo(new bar?.("test")); -new a?.foo?.(); -new a?.foo?.("foo"); -new a?.foo?.("foo", "bar"); -new a?.foo?.(bar()); -new a?.foo?.(bar("test")); -a?.foo(new bar?.()); -a?.foo(new bar?.("test")); -new a.foo?.().baz; -new a.foo?.("foo").baz; -new a.foo?.("foo", "bar").baz; -new a.foo?.(bar()).baz; -new a.foo?.(bar("test")).baz; -a.foo(new bar?.()).baz; -a.foo(new bar?.("test")).baz; -new a.foo?.()?.baz; -new a.foo?.("foo")?.baz; -new a.foo?.("foo", "bar")?.baz; -new a.foo?.(bar())?.baz; -new a.foo?.(bar("test"))?.baz; -a.foo(new bar?.())?.baz; -a.foo(new bar?.("test"))?.baz; \ No newline at end of file diff --git a/packages/babel-plugin-proposal-optional-chaining/src/index.js b/packages/babel-plugin-proposal-optional-chaining/src/index.js index 80228f69dd8b..1a854c082bdb 100644 --- a/packages/babel-plugin-proposal-optional-chaining/src/index.js +++ b/packages/babel-plugin-proposal-optional-chaining/src/index.js @@ -9,15 +9,20 @@ export default function(api, options) { const optionals = []; let objectPath = path; - while (objectPath.isMemberExpression() || objectPath.isCallExpression()) { + while ( + objectPath.isOptionalMemberExpression() || + objectPath.isOptionalCallExpression() + ) { const { node } = objectPath; if (node.optional) { optionals.push(node); } - if (objectPath.isMemberExpression()) { + if (objectPath.isOptionalMemberExpression()) { + objectPath.node.type = "MemberExpression"; objectPath = objectPath.get("object"); } else { + objectPath.node.type = "CallExpression"; objectPath = objectPath.get("callee"); } } @@ -101,21 +106,10 @@ export default function(api, options) { return path.find(path => { const { parentPath } = path; - if (path.key == "left" && parentPath.isAssignmentExpression()) { - throw path.buildCodeFrameError( - "Illegal optional chain in assignment expression", - ); - } - if (path.key == "argument" && parentPath.isUpdateExpression()) { - throw path.buildCodeFrameError( - "Illegal optional chain in update expression", - ); - } - - if (path.key == "object" && parentPath.isMemberExpression()) { + if (path.key == "object" && parentPath.isOptionalMemberExpression()) { return false; } - if (path.key == "callee" && parentPath.isCallExpression()) { + if (path.key == "callee" && parentPath.isOptionalCallExpression()) { return false; } if ( @@ -133,7 +127,7 @@ export default function(api, options) { inherits: syntaxOptionalChaining, visitor: { - "MemberExpression|CallExpression"(path) { + "OptionalCallExpression|OptionalMemberExpression"(path) { if (!path.node.optional) { return; } diff --git a/packages/babel-plugin-proposal-optional-chaining/test/fixtures/general/lhs-assignment-read-and-update/options.json b/packages/babel-plugin-proposal-optional-chaining/test/fixtures/general/lhs-assignment-read-and-update/options.json index 5ef1ad8077e7..ea37454d9b87 100644 --- a/packages/babel-plugin-proposal-optional-chaining/test/fixtures/general/lhs-assignment-read-and-update/options.json +++ b/packages/babel-plugin-proposal-optional-chaining/test/fixtures/general/lhs-assignment-read-and-update/options.json @@ -1,3 +1,3 @@ { - "throws": "Illegal optional chain in assignment expression" + "throws": "Invalid left-hand side in assignment expression" } diff --git a/packages/babel-plugin-proposal-optional-chaining/test/fixtures/general/lhs-assignment/options.json b/packages/babel-plugin-proposal-optional-chaining/test/fixtures/general/lhs-assignment/options.json index 5ef1ad8077e7..ea37454d9b87 100644 --- a/packages/babel-plugin-proposal-optional-chaining/test/fixtures/general/lhs-assignment/options.json +++ b/packages/babel-plugin-proposal-optional-chaining/test/fixtures/general/lhs-assignment/options.json @@ -1,3 +1,3 @@ { - "throws": "Illegal optional chain in assignment expression" + "throws": "Invalid left-hand side in assignment expression" } diff --git a/packages/babel-plugin-proposal-optional-chaining/test/fixtures/general/lhs-update/options.json b/packages/babel-plugin-proposal-optional-chaining/test/fixtures/general/lhs-update/options.json index 3bea483d4781..0153e85a5e1c 100644 --- a/packages/babel-plugin-proposal-optional-chaining/test/fixtures/general/lhs-update/options.json +++ b/packages/babel-plugin-proposal-optional-chaining/test/fixtures/general/lhs-update/options.json @@ -1,3 +1,3 @@ { - "throws": "Illegal optional chain in update expression" + "throws": "Invalid left-hand side in postfix operation" } diff --git a/packages/babel-types/README.md b/packages/babel-types/README.md index 1e1106b6e566..b465146f791c 100644 --- a/packages/babel-types/README.md +++ b/packages/babel-types/README.md @@ -1590,6 +1590,38 @@ Aliases: `Flow`, `FlowDeclaration`, `Statement`, `Declaration` --- +### optionalCallExpression +```javascript +t.optionalCallExpression(callee, arguments, optional) +``` + +See also `t.isOptionalCallExpression(node, opts)` and `t.assertOptionalCallExpression(node, opts)`. + +Aliases: `Expression` + + - `callee`: `Expression` (required) + - `arguments`: `Array` (required) + - `optional`: `boolean` (required) + - `typeParameters`: `TypeParameterInstantiation | TSTypeParameterInstantiation` (default: `null`) + +--- + +### optionalMemberExpression +```javascript +t.optionalMemberExpression(object, property, computed, optional) +``` + +See also `t.isOptionalMemberExpression(node, opts)` and `t.assertOptionalMemberExpression(node, opts)`. + +Aliases: `Expression` + + - `object`: `Expression` (required) + - `property`: `any` (required) + - `computed`: `boolean` (default: `false`) + - `optional`: `boolean` (required) + +--- + ### parenthesizedExpression ```javascript t.parenthesizedExpression(expression) diff --git a/packages/babel-types/src/asserts/generated/index.js b/packages/babel-types/src/asserts/generated/index.js index a4cdccdd1a63..093d1e7701b0 100644 --- a/packages/babel-types/src/asserts/generated/index.js +++ b/packages/babel-types/src/asserts/generated/index.js @@ -651,6 +651,18 @@ export function assertBindExpression(node: Object, opts?: Object = {}): void { export function assertClassProperty(node: Object, opts?: Object = {}): void { assert("ClassProperty", node, opts); } +export function assertOptionalMemberExpression( + node: Object, + opts?: Object = {}, +): void { + assert("OptionalMemberExpression", node, opts); +} +export function assertOptionalCallExpression( + node: Object, + opts?: Object = {}, +): void { + assert("OptionalCallExpression", node, opts); +} export function assertImport(node: Object, opts?: Object = {}): void { assert("Import", node, opts); } diff --git a/packages/babel-types/src/builders/generated/index.js b/packages/babel-types/src/builders/generated/index.js index ba2b95e61d67..ee003c27e812 100644 --- a/packages/babel-types/src/builders/generated/index.js +++ b/packages/babel-types/src/builders/generated/index.js @@ -596,6 +596,14 @@ export function ClassProperty(...args: Array): Object { return builder("ClassProperty", ...args); } export { ClassProperty as classProperty }; +export function OptionalMemberExpression(...args: Array): Object { + return builder("OptionalMemberExpression", ...args); +} +export { OptionalMemberExpression as optionalMemberExpression }; +export function OptionalCallExpression(...args: Array): Object { + return builder("OptionalCallExpression", ...args); +} +export { OptionalCallExpression as optionalCallExpression }; export function Import(...args: Array): Object { return builder("Import", ...args); } diff --git a/packages/babel-types/src/definitions/experimental.js b/packages/babel-types/src/definitions/experimental.js index 2859f099c2d7..d10d2c47c0fc 100644 --- a/packages/babel-types/src/definitions/experimental.js +++ b/packages/babel-types/src/definitions/experimental.js @@ -54,6 +54,63 @@ defineType("ClassProperty", { }, }); +defineType("OptionalMemberExpression", { + builder: ["object", "property", "computed", "optional"], + visitor: ["object", "property"], + aliases: ["Expression"], + fields: { + object: { + validate: assertNodeType("Expression"), + }, + property: { + validate: (function() { + const normal = assertNodeType("Identifier"); + const computed = assertNodeType("Expression"); + + return function(node, key, val) { + const validator = node.computed ? computed : normal; + validator(node, key, val); + }; + })(), + }, + computed: { + default: false, + }, + optional: { + validate: assertValueType("boolean"), + }, + }, +}); + +defineType("OptionalCallExpression", { + visitor: ["callee", "arguments", "typeParameters"], + builder: ["callee", "arguments", "optional"], + aliases: ["Expression"], + fields: { + callee: { + validate: assertNodeType("Expression"), + }, + arguments: { + validate: chain( + assertValueType("array"), + assertEach( + assertNodeType("Expression", "SpreadElement", "JSXNamespacedName"), + ), + ), + }, + optional: { + validate: assertValueType("boolean"), + }, + typeParameters: { + validate: assertNodeType( + "TypeParameterInstantiation", + "TSTypeParameterInstantiation", + ), + optional: true, + }, + }, +}); + defineType("Import", { aliases: ["Expression"], }); diff --git a/packages/babel-types/src/validators/generated/index.js b/packages/babel-types/src/validators/generated/index.js index 9f3a5f66c8df..4a2215a50b11 100644 --- a/packages/babel-types/src/validators/generated/index.js +++ b/packages/babel-types/src/validators/generated/index.js @@ -485,6 +485,15 @@ export function isBindExpression(node: Object, opts?: Object): boolean { export function isClassProperty(node: Object, opts?: Object): boolean { return is("ClassProperty", node, opts); } +export function isOptionalMemberExpression( + node: Object, + opts?: Object, +): boolean { + return is("OptionalMemberExpression", node, opts); +} +export function isOptionalCallExpression(node: Object, opts?: Object): boolean { + return is("OptionalCallExpression", node, opts); +} export function isImport(node: Object, opts?: Object): boolean { return is("Import", node, opts); } diff --git a/packages/babylon/src/parser/expression.js b/packages/babylon/src/parser/expression.js index 40b53d321fc3..83508c035a46 100644 --- a/packages/babylon/src/parser/expression.js +++ b/packages/babylon/src/parser/expression.js @@ -433,13 +433,13 @@ export default class ExpressionParser extends LValParser { return base; } - /** @param state Set 'state.stop = true' to indicate that we should stop parsing subscripts. */ + /** @param state Set 'state.stop = true' to indicate that we should stop parsing subscripts. 'state.optionalChainMember to indicate that the member is currently in OptionalChain'*/ parseSubscript( base: N.Expression, startPos: number, startLoc: Position, noCalls: ?boolean, - state: { stop: boolean }, + state: { stop: boolean, optionalChainMember?: boolean }, ): N.Expression { if (!noCalls && this.eat(tt.doubleColon)) { const node = this.startNodeAt(startPos, startLoc); @@ -454,7 +454,7 @@ export default class ExpressionParser extends LValParser { ); } else if (this.match(tt.questionDot)) { this.expectPlugin("optionalChaining"); - + state.optionalChainMember = true; if (noCalls && this.lookahead().type == tt.parenL) { state.stop = true; return base; @@ -469,7 +469,7 @@ export default class ExpressionParser extends LValParser { node.computed = true; node.optional = true; this.expect(tt.bracketR); - return this.finishNode(node, "MemberExpression"); + return this.finishNode(node, "OptionalMemberExpression"); } else if (this.eat(tt.parenL)) { const possibleAsync = this.atPossibleAsync(base); @@ -480,19 +480,23 @@ export default class ExpressionParser extends LValParser { ); node.optional = true; - return this.finishNode(node, "CallExpression"); + return this.finishNode(node, "OptionalCallExpression"); } else { node.object = base; node.property = this.parseIdentifier(true); node.computed = false; node.optional = true; - return this.finishNode(node, "MemberExpression"); + return this.finishNode(node, "OptionalMemberExpression"); } } else if (this.eat(tt.dot)) { const node = this.startNodeAt(startPos, startLoc); node.object = base; node.property = this.parseMaybePrivateName(); node.computed = false; + if (state.optionalChainMember) { + node.optional = false; + return this.finishNode(node, "OptionalMemberExpression"); + } return this.finishNode(node, "MemberExpression"); } else if (this.eat(tt.bracketL)) { const node = this.startNodeAt(startPos, startLoc); @@ -500,6 +504,10 @@ export default class ExpressionParser extends LValParser { node.property = this.parseExpression(); node.computed = true; this.expect(tt.bracketR); + if (state.optionalChainMember) { + node.optional = false; + return this.finishNode(node, "OptionalMemberExpression"); + } return this.finishNode(node, "MemberExpression"); } else if (!noCalls && this.match(tt.parenL)) { const possibleAsync = this.atPossibleAsync(base); @@ -518,7 +526,11 @@ export default class ExpressionParser extends LValParser { possibleAsync, refTrailingCommaPos, ); - this.finishCallExpression(node); + if (!state.optionalChainMember) { + this.finishCallExpression(node); + } else { + this.finishOptionalCallExpression(node); + } if (possibleAsync && this.shouldParseAsyncArrow()) { state.stop = true; @@ -542,7 +554,14 @@ export default class ExpressionParser extends LValParser { const node = this.startNodeAt(startPos, startLoc); node.tag = base; node.quasi = this.parseTemplate(true); - return this.finishNode(node, "TaggedTemplateExpression"); + if (!state.optionalChainMember) { + return this.finishNode(node, "TaggedTemplateExpression"); + } else { + this.raise( + startPos, + "Tagged Template Literals are not allowed in optionalChain", + ); + } } else { state.stop = true; return base; @@ -572,6 +591,20 @@ export default class ExpressionParser extends LValParser { return this.finishNode(node, "CallExpression"); } + finishOptionalCallExpression(node: N.CallExpression): N.CallExpression { + if (node.callee.type === "Import") { + if (node.arguments.length !== 1) { + this.raise(node.start, "import() requires exactly one argument"); + } + + const importArg = node.arguments[0]; + if (importArg && importArg.type === "SpreadElement") { + this.raise(importArg.start, "... is not allowed in import()"); + } + } + return this.finishNode(node, "OptionalCallExpression"); + } + parseCallExpressionArguments( close: TokenType, possibleAsyncArrow: boolean, @@ -1103,7 +1136,21 @@ export default class ExpressionParser extends LValParser { } node.callee = this.parseNoCallExpr(); - if (this.eat(tt.questionDot)) node.optional = true; + if ( + node.callee.type === "OptionalMemberExpression" || + node.callee.type === "OptionalCallExpression" + ) { + this.raise( + this.state.lastTokEnd, + "constructors in/after an Optional Chain are not allowed", + ); + } + if (this.eat(tt.questionDot)) { + this.raise( + this.state.start, + "constructors in/after an Optional Chain are not allowed", + ); + } this.parseNewArguments(node); return this.finishNode(node, "NewExpression"); } diff --git a/packages/babylon/src/types.js b/packages/babylon/src/types.js index a777716dd589..201c4f35c718 100644 --- a/packages/babylon/src/types.js +++ b/packages/babylon/src/types.js @@ -509,6 +509,18 @@ export type MemberExpression = NodeBase & { computed: boolean, }; +export type OptionalMemberExpression = NodeBase & { + type: "OptionalMemberExpression", + object: Expression | Super, + property: Expression, + computed: boolean, + optional: boolean, +}; + +export type OptionalCallExpression = CallOrNewBase & { + type: "OptionalCallExpression", + optional: boolean, +}; export type BindExpression = NodeBase & { type: "BindExpression", object: $ReadOnlyArray, diff --git a/packages/babylon/test/fixtures/experimental/optional-chaining/class-contructor-call/input.js b/packages/babylon/test/fixtures/experimental/optional-chaining/class-contructor-call/input.js index 8cefe8182151..1cd62a965ecf 100644 --- a/packages/babylon/test/fixtures/experimental/optional-chaining/class-contructor-call/input.js +++ b/packages/babylon/test/fixtures/experimental/optional-chaining/class-contructor-call/input.js @@ -1,9 +1 @@ -new C?.() - -new C?.(a, b) - -new B?.C?.() - -new B?.C?.(a, b) - -new B?.C +new C?.b.d() \ No newline at end of file diff --git a/packages/babylon/test/fixtures/experimental/optional-chaining/class-contructor-call/options.json b/packages/babylon/test/fixtures/experimental/optional-chaining/class-contructor-call/options.json index fd201c1bdb02..ed5e3c16bf68 100644 --- a/packages/babylon/test/fixtures/experimental/optional-chaining/class-contructor-call/options.json +++ b/packages/babylon/test/fixtures/experimental/optional-chaining/class-contructor-call/options.json @@ -1,3 +1,4 @@ { - "plugins": ["optionalChaining"] + "plugins": ["optionalChaining"], + "throws": "constructors in/after an Optional Chain are not allowed (1:10)" } diff --git a/packages/babylon/test/fixtures/experimental/optional-chaining/class-contructor-call/output.json b/packages/babylon/test/fixtures/experimental/optional-chaining/class-contructor-call/output.json deleted file mode 100644 index 49911ff155e3..000000000000 --- a/packages/babylon/test/fixtures/experimental/optional-chaining/class-contructor-call/output.json +++ /dev/null @@ -1,450 +0,0 @@ -{ - "type": "File", - "start": 0, - "end": 66, - "loc": { - "start": { - "line": 1, - "column": 0 - }, - "end": { - "line": 9, - "column": 8 - } - }, - "program": { - "type": "Program", - "start": 0, - "end": 66, - "loc": { - "start": { - "line": 1, - "column": 0 - }, - "end": { - "line": 9, - "column": 8 - } - }, - "sourceType": "script", - "body": [ - { - "type": "ExpressionStatement", - "start": 0, - "end": 9, - "loc": { - "start": { - "line": 1, - "column": 0 - }, - "end": { - "line": 1, - "column": 9 - } - }, - "expression": { - "type": "NewExpression", - "start": 0, - "end": 9, - "loc": { - "start": { - "line": 1, - "column": 0 - }, - "end": { - "line": 1, - "column": 9 - } - }, - "callee": { - "type": "Identifier", - "start": 4, - "end": 5, - "loc": { - "start": { - "line": 1, - "column": 4 - }, - "end": { - "line": 1, - "column": 5 - }, - "identifierName": "C" - }, - "name": "C" - }, - "optional": true, - "arguments": [] - } - }, - { - "type": "ExpressionStatement", - "start": 11, - "end": 24, - "loc": { - "start": { - "line": 3, - "column": 0 - }, - "end": { - "line": 3, - "column": 13 - } - }, - "expression": { - "type": "NewExpression", - "start": 11, - "end": 24, - "loc": { - "start": { - "line": 3, - "column": 0 - }, - "end": { - "line": 3, - "column": 13 - } - }, - "callee": { - "type": "Identifier", - "start": 15, - "end": 16, - "loc": { - "start": { - "line": 3, - "column": 4 - }, - "end": { - "line": 3, - "column": 5 - }, - "identifierName": "C" - }, - "name": "C" - }, - "optional": true, - "arguments": [ - { - "type": "Identifier", - "start": 19, - "end": 20, - "loc": { - "start": { - "line": 3, - "column": 8 - }, - "end": { - "line": 3, - "column": 9 - }, - "identifierName": "a" - }, - "name": "a" - }, - { - "type": "Identifier", - "start": 22, - "end": 23, - "loc": { - "start": { - "line": 3, - "column": 11 - }, - "end": { - "line": 3, - "column": 12 - }, - "identifierName": "b" - }, - "name": "b" - } - ] - } - }, - { - "type": "ExpressionStatement", - "start": 26, - "end": 38, - "loc": { - "start": { - "line": 5, - "column": 0 - }, - "end": { - "line": 5, - "column": 12 - } - }, - "expression": { - "type": "NewExpression", - "start": 26, - "end": 38, - "loc": { - "start": { - "line": 5, - "column": 0 - }, - "end": { - "line": 5, - "column": 12 - } - }, - "callee": { - "type": "MemberExpression", - "start": 30, - "end": 34, - "loc": { - "start": { - "line": 5, - "column": 4 - }, - "end": { - "line": 5, - "column": 8 - } - }, - "object": { - "type": "Identifier", - "start": 30, - "end": 31, - "loc": { - "start": { - "line": 5, - "column": 4 - }, - "end": { - "line": 5, - "column": 5 - }, - "identifierName": "B" - }, - "name": "B" - }, - "property": { - "type": "Identifier", - "start": 33, - "end": 34, - "loc": { - "start": { - "line": 5, - "column": 7 - }, - "end": { - "line": 5, - "column": 8 - }, - "identifierName": "C" - }, - "name": "C" - }, - "computed": false, - "optional": true - }, - "optional": true, - "arguments": [] - } - }, - { - "type": "ExpressionStatement", - "start": 40, - "end": 56, - "loc": { - "start": { - "line": 7, - "column": 0 - }, - "end": { - "line": 7, - "column": 16 - } - }, - "expression": { - "type": "NewExpression", - "start": 40, - "end": 56, - "loc": { - "start": { - "line": 7, - "column": 0 - }, - "end": { - "line": 7, - "column": 16 - } - }, - "callee": { - "type": "MemberExpression", - "start": 44, - "end": 48, - "loc": { - "start": { - "line": 7, - "column": 4 - }, - "end": { - "line": 7, - "column": 8 - } - }, - "object": { - "type": "Identifier", - "start": 44, - "end": 45, - "loc": { - "start": { - "line": 7, - "column": 4 - }, - "end": { - "line": 7, - "column": 5 - }, - "identifierName": "B" - }, - "name": "B" - }, - "property": { - "type": "Identifier", - "start": 47, - "end": 48, - "loc": { - "start": { - "line": 7, - "column": 7 - }, - "end": { - "line": 7, - "column": 8 - }, - "identifierName": "C" - }, - "name": "C" - }, - "computed": false, - "optional": true - }, - "optional": true, - "arguments": [ - { - "type": "Identifier", - "start": 51, - "end": 52, - "loc": { - "start": { - "line": 7, - "column": 11 - }, - "end": { - "line": 7, - "column": 12 - }, - "identifierName": "a" - }, - "name": "a" - }, - { - "type": "Identifier", - "start": 54, - "end": 55, - "loc": { - "start": { - "line": 7, - "column": 14 - }, - "end": { - "line": 7, - "column": 15 - }, - "identifierName": "b" - }, - "name": "b" - } - ] - } - }, - { - "type": "ExpressionStatement", - "start": 58, - "end": 66, - "loc": { - "start": { - "line": 9, - "column": 0 - }, - "end": { - "line": 9, - "column": 8 - } - }, - "expression": { - "type": "NewExpression", - "start": 58, - "end": 66, - "loc": { - "start": { - "line": 9, - "column": 0 - }, - "end": { - "line": 9, - "column": 8 - } - }, - "callee": { - "type": "MemberExpression", - "start": 62, - "end": 66, - "loc": { - "start": { - "line": 9, - "column": 4 - }, - "end": { - "line": 9, - "column": 8 - } - }, - "object": { - "type": "Identifier", - "start": 62, - "end": 63, - "loc": { - "start": { - "line": 9, - "column": 4 - }, - "end": { - "line": 9, - "column": 5 - }, - "identifierName": "B" - }, - "name": "B" - }, - "property": { - "type": "Identifier", - "start": 65, - "end": 66, - "loc": { - "start": { - "line": 9, - "column": 7 - }, - "end": { - "line": 9, - "column": 8 - }, - "identifierName": "C" - }, - "name": "C" - }, - "computed": false, - "optional": true - }, - "arguments": [] - } - } - ], - "directives": [] - } -} \ No newline at end of file diff --git a/packages/babylon/test/fixtures/experimental/optional-chaining/function-call/input.js b/packages/babylon/test/fixtures/experimental/optional-chaining/function-call/input.js index ccf7cad6ee45..9963372b6f7d 100644 --- a/packages/babylon/test/fixtures/experimental/optional-chaining/function-call/input.js +++ b/packages/babylon/test/fixtures/experimental/optional-chaining/function-call/input.js @@ -5,3 +5,5 @@ func?.(a, b) a?.func?.() a?.func?.(a, b) + +a.func?.() \ No newline at end of file diff --git a/packages/babylon/test/fixtures/experimental/optional-chaining/function-call/output.json b/packages/babylon/test/fixtures/experimental/optional-chaining/function-call/output.json index 92e841058e98..20946ed07edc 100644 --- a/packages/babylon/test/fixtures/experimental/optional-chaining/function-call/output.json +++ b/packages/babylon/test/fixtures/experimental/optional-chaining/function-call/output.json @@ -1,29 +1,29 @@ { "type": "File", "start": 0, - "end": 52, + "end": 64, "loc": { "start": { "line": 1, "column": 0 }, "end": { - "line": 7, - "column": 15 + "line": 9, + "column": 10 } }, "program": { "type": "Program", "start": 0, - "end": 52, + "end": 64, "loc": { "start": { "line": 1, "column": 0 }, "end": { - "line": 7, - "column": 15 + "line": 9, + "column": 10 } }, "sourceType": "script", @@ -43,7 +43,7 @@ } }, "expression": { - "type": "CallExpression", + "type": "OptionalCallExpression", "start": 0, "end": 8, "loc": { @@ -92,7 +92,7 @@ } }, "expression": { - "type": "CallExpression", + "type": "OptionalCallExpression", "start": 10, "end": 22, "loc": { @@ -176,7 +176,7 @@ } }, "expression": { - "type": "CallExpression", + "type": "OptionalCallExpression", "start": 24, "end": 35, "loc": { @@ -190,7 +190,7 @@ } }, "callee": { - "type": "MemberExpression", + "type": "OptionalMemberExpression", "start": 24, "end": 31, "loc": { @@ -259,7 +259,7 @@ } }, "expression": { - "type": "CallExpression", + "type": "OptionalCallExpression", "start": 37, "end": 52, "loc": { @@ -273,7 +273,7 @@ } }, "callee": { - "type": "MemberExpression", + "type": "OptionalMemberExpression", "start": 37, "end": 44, "loc": { @@ -361,6 +361,88 @@ ], "optional": true } + }, + { + "type": "ExpressionStatement", + "start": 54, + "end": 64, + "loc": { + "start": { + "line": 9, + "column": 0 + }, + "end": { + "line": 9, + "column": 10 + } + }, + "expression": { + "type": "OptionalCallExpression", + "start": 54, + "end": 64, + "loc": { + "start": { + "line": 9, + "column": 0 + }, + "end": { + "line": 9, + "column": 10 + } + }, + "callee": { + "type": "MemberExpression", + "start": 54, + "end": 60, + "loc": { + "start": { + "line": 9, + "column": 0 + }, + "end": { + "line": 9, + "column": 6 + } + }, + "object": { + "type": "Identifier", + "start": 54, + "end": 55, + "loc": { + "start": { + "line": 9, + "column": 0 + }, + "end": { + "line": 9, + "column": 1 + }, + "identifierName": "a" + }, + "name": "a" + }, + "property": { + "type": "Identifier", + "start": 56, + "end": 60, + "loc": { + "start": { + "line": 9, + "column": 2 + }, + "end": { + "line": 9, + "column": 6 + }, + "identifierName": "func" + }, + "name": "func" + }, + "computed": false + }, + "arguments": [], + "optional": true + } } ], "directives": [] diff --git a/packages/babylon/test/fixtures/experimental/optional-chaining/member-access-bracket/input.js b/packages/babylon/test/fixtures/experimental/optional-chaining/member-access-bracket/input.js index ee45bfdb9e98..4866719475ce 100644 --- a/packages/babylon/test/fixtures/experimental/optional-chaining/member-access-bracket/input.js +++ b/packages/babylon/test/fixtures/experimental/optional-chaining/member-access-bracket/input.js @@ -5,3 +5,7 @@ obj?.[expr]?.[other] obj?.[true] obj?.[true]?.[true] + +obj.a?.[expr] + +obj.a?.[true] \ No newline at end of file diff --git a/packages/babylon/test/fixtures/experimental/optional-chaining/member-access-bracket/output.json b/packages/babylon/test/fixtures/experimental/optional-chaining/member-access-bracket/output.json index aa2588dde0cc..c59ce8a3816d 100644 --- a/packages/babylon/test/fixtures/experimental/optional-chaining/member-access-bracket/output.json +++ b/packages/babylon/test/fixtures/experimental/optional-chaining/member-access-bracket/output.json @@ -1,29 +1,29 @@ { "type": "File", "start": 0, - "end": 67, + "end": 97, "loc": { "start": { "line": 1, "column": 0 }, "end": { - "line": 7, - "column": 19 + "line": 11, + "column": 13 } }, "program": { "type": "Program", "start": 0, - "end": 67, + "end": 97, "loc": { "start": { "line": 1, "column": 0 }, "end": { - "line": 7, - "column": 19 + "line": 11, + "column": 13 } }, "sourceType": "script", @@ -43,7 +43,7 @@ } }, "expression": { - "type": "MemberExpression", + "type": "OptionalMemberExpression", "start": 0, "end": 11, "loc": { @@ -109,7 +109,7 @@ } }, "expression": { - "type": "MemberExpression", + "type": "OptionalMemberExpression", "start": 13, "end": 33, "loc": { @@ -123,7 +123,7 @@ } }, "object": { - "type": "MemberExpression", + "type": "OptionalMemberExpression", "start": 13, "end": 24, "loc": { @@ -209,7 +209,7 @@ } }, "expression": { - "type": "MemberExpression", + "type": "OptionalMemberExpression", "start": 35, "end": 46, "loc": { @@ -274,7 +274,7 @@ } }, "expression": { - "type": "MemberExpression", + "type": "OptionalMemberExpression", "start": 48, "end": 67, "loc": { @@ -288,7 +288,7 @@ } }, "object": { - "type": "MemberExpression", + "type": "OptionalMemberExpression", "start": 48, "end": 59, "loc": { @@ -356,6 +356,203 @@ "computed": true, "optional": true } + }, + { + "type": "ExpressionStatement", + "start": 69, + "end": 82, + "loc": { + "start": { + "line": 9, + "column": 0 + }, + "end": { + "line": 9, + "column": 13 + } + }, + "expression": { + "type": "OptionalMemberExpression", + "start": 69, + "end": 82, + "loc": { + "start": { + "line": 9, + "column": 0 + }, + "end": { + "line": 9, + "column": 13 + } + }, + "object": { + "type": "MemberExpression", + "start": 69, + "end": 74, + "loc": { + "start": { + "line": 9, + "column": 0 + }, + "end": { + "line": 9, + "column": 5 + } + }, + "object": { + "type": "Identifier", + "start": 69, + "end": 72, + "loc": { + "start": { + "line": 9, + "column": 0 + }, + "end": { + "line": 9, + "column": 3 + }, + "identifierName": "obj" + }, + "name": "obj" + }, + "property": { + "type": "Identifier", + "start": 73, + "end": 74, + "loc": { + "start": { + "line": 9, + "column": 4 + }, + "end": { + "line": 9, + "column": 5 + }, + "identifierName": "a" + }, + "name": "a" + }, + "computed": false + }, + "property": { + "type": "Identifier", + "start": 77, + "end": 81, + "loc": { + "start": { + "line": 9, + "column": 8 + }, + "end": { + "line": 9, + "column": 12 + }, + "identifierName": "expr" + }, + "name": "expr" + }, + "computed": true, + "optional": true + } + }, + { + "type": "ExpressionStatement", + "start": 84, + "end": 97, + "loc": { + "start": { + "line": 11, + "column": 0 + }, + "end": { + "line": 11, + "column": 13 + } + }, + "expression": { + "type": "OptionalMemberExpression", + "start": 84, + "end": 97, + "loc": { + "start": { + "line": 11, + "column": 0 + }, + "end": { + "line": 11, + "column": 13 + } + }, + "object": { + "type": "MemberExpression", + "start": 84, + "end": 89, + "loc": { + "start": { + "line": 11, + "column": 0 + }, + "end": { + "line": 11, + "column": 5 + } + }, + "object": { + "type": "Identifier", + "start": 84, + "end": 87, + "loc": { + "start": { + "line": 11, + "column": 0 + }, + "end": { + "line": 11, + "column": 3 + }, + "identifierName": "obj" + }, + "name": "obj" + }, + "property": { + "type": "Identifier", + "start": 88, + "end": 89, + "loc": { + "start": { + "line": 11, + "column": 4 + }, + "end": { + "line": 11, + "column": 5 + }, + "identifierName": "a" + }, + "name": "a" + }, + "computed": false + }, + "property": { + "type": "BooleanLiteral", + "start": 92, + "end": 96, + "loc": { + "start": { + "line": 11, + "column": 8 + }, + "end": { + "line": 11, + "column": 12 + } + }, + "value": true + }, + "computed": true, + "optional": true + } } ], "directives": [] diff --git a/packages/babylon/test/fixtures/experimental/optional-chaining/member-access/input.js b/packages/babylon/test/fixtures/experimental/optional-chaining/member-access/input.js index 8e44f5741534..20630c3ef06a 100644 --- a/packages/babylon/test/fixtures/experimental/optional-chaining/member-access/input.js +++ b/packages/babylon/test/fixtures/experimental/optional-chaining/member-access/input.js @@ -1,3 +1,5 @@ foo?.bar foo?.bar?.baz + +foo.bar?.baz \ No newline at end of file diff --git a/packages/babylon/test/fixtures/experimental/optional-chaining/member-access/output.json b/packages/babylon/test/fixtures/experimental/optional-chaining/member-access/output.json index db9bb6bc0d18..ec7d0d5737e7 100644 --- a/packages/babylon/test/fixtures/experimental/optional-chaining/member-access/output.json +++ b/packages/babylon/test/fixtures/experimental/optional-chaining/member-access/output.json @@ -1,29 +1,29 @@ { "type": "File", "start": 0, - "end": 23, + "end": 37, "loc": { "start": { "line": 1, "column": 0 }, "end": { - "line": 3, - "column": 13 + "line": 5, + "column": 12 } }, "program": { "type": "Program", "start": 0, - "end": 23, + "end": 37, "loc": { "start": { "line": 1, "column": 0 }, "end": { - "line": 3, - "column": 13 + "line": 5, + "column": 12 } }, "sourceType": "script", @@ -43,7 +43,7 @@ } }, "expression": { - "type": "MemberExpression", + "type": "OptionalMemberExpression", "start": 0, "end": 8, "loc": { @@ -109,7 +109,7 @@ } }, "expression": { - "type": "MemberExpression", + "type": "OptionalMemberExpression", "start": 10, "end": 23, "loc": { @@ -123,7 +123,7 @@ } }, "object": { - "type": "MemberExpression", + "type": "OptionalMemberExpression", "start": 10, "end": 18, "loc": { @@ -193,6 +193,105 @@ "computed": false, "optional": true } + }, + { + "type": "ExpressionStatement", + "start": 25, + "end": 37, + "loc": { + "start": { + "line": 5, + "column": 0 + }, + "end": { + "line": 5, + "column": 12 + } + }, + "expression": { + "type": "OptionalMemberExpression", + "start": 25, + "end": 37, + "loc": { + "start": { + "line": 5, + "column": 0 + }, + "end": { + "line": 5, + "column": 12 + } + }, + "object": { + "type": "MemberExpression", + "start": 25, + "end": 32, + "loc": { + "start": { + "line": 5, + "column": 0 + }, + "end": { + "line": 5, + "column": 7 + } + }, + "object": { + "type": "Identifier", + "start": 25, + "end": 28, + "loc": { + "start": { + "line": 5, + "column": 0 + }, + "end": { + "line": 5, + "column": 3 + }, + "identifierName": "foo" + }, + "name": "foo" + }, + "property": { + "type": "Identifier", + "start": 29, + "end": 32, + "loc": { + "start": { + "line": 5, + "column": 4 + }, + "end": { + "line": 5, + "column": 7 + }, + "identifierName": "bar" + }, + "name": "bar" + }, + "computed": false + }, + "property": { + "type": "Identifier", + "start": 34, + "end": 37, + "loc": { + "start": { + "line": 5, + "column": 9 + }, + "end": { + "line": 5, + "column": 12 + }, + "identifierName": "baz" + }, + "name": "baz" + }, + "computed": false, + "optional": true + } } ], "directives": [] diff --git a/packages/babylon/test/fixtures/experimental/optional-chaining/optioanl-chain-expression/input.js b/packages/babylon/test/fixtures/experimental/optional-chaining/optioanl-chain-expression/input.js new file mode 100644 index 000000000000..dde9a725f234 --- /dev/null +++ b/packages/babylon/test/fixtures/experimental/optional-chaining/optioanl-chain-expression/input.js @@ -0,0 +1 @@ +a.b?.c() \ No newline at end of file diff --git a/packages/babylon/test/fixtures/experimental/optional-chaining/optioanl-chain-expression/options.json b/packages/babylon/test/fixtures/experimental/optional-chaining/optioanl-chain-expression/options.json new file mode 100644 index 000000000000..ec2042c93230 --- /dev/null +++ b/packages/babylon/test/fixtures/experimental/optional-chaining/optioanl-chain-expression/options.json @@ -0,0 +1,3 @@ +{ + "plugins": ["optionalChaining"] +} \ No newline at end of file diff --git a/packages/babylon/test/fixtures/experimental/optional-chaining/optioanl-chain-expression/output.json b/packages/babylon/test/fixtures/experimental/optional-chaining/optioanl-chain-expression/output.json new file mode 100644 index 000000000000..3eb34c498b6e --- /dev/null +++ b/packages/babylon/test/fixtures/experimental/optional-chaining/optioanl-chain-expression/output.json @@ -0,0 +1,149 @@ +{ + "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", + "body": [ + { + "type": "ExpressionStatement", + "start": 0, + "end": 8, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 8 + } + }, + "expression": { + "type": "OptionalCallExpression", + "start": 0, + "end": 8, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 8 + } + }, + "callee": { + "type": "OptionalMemberExpression", + "start": 0, + "end": 6, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 6 + } + }, + "object": { + "type": "MemberExpression", + "start": 0, + "end": 3, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 3 + } + }, + "object": { + "type": "Identifier", + "start": 0, + "end": 1, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 1 + }, + "identifierName": "a" + }, + "name": "a" + }, + "property": { + "type": "Identifier", + "start": 2, + "end": 3, + "loc": { + "start": { + "line": 1, + "column": 2 + }, + "end": { + "line": 1, + "column": 3 + }, + "identifierName": "b" + }, + "name": "b" + }, + "computed": false + }, + "property": { + "type": "Identifier", + "start": 5, + "end": 6, + "loc": { + "start": { + "line": 1, + "column": 5 + }, + "end": { + "line": 1, + "column": 6 + }, + "identifierName": "c" + }, + "name": "c" + }, + "computed": false, + "optional": true + }, + "arguments": [] + } + } + ], + "directives": [] + } +} \ No newline at end of file diff --git a/packages/babylon/test/fixtures/experimental/optional-chaining/optional-constructor/input.js b/packages/babylon/test/fixtures/experimental/optional-chaining/optional-constructor/input.js new file mode 100644 index 000000000000..3a5a910b4fe9 --- /dev/null +++ b/packages/babylon/test/fixtures/experimental/optional-chaining/optional-constructor/input.js @@ -0,0 +1 @@ +new a?.(); \ No newline at end of file diff --git a/packages/babylon/test/fixtures/experimental/optional-chaining/optional-constructor/options.json b/packages/babylon/test/fixtures/experimental/optional-chaining/optional-constructor/options.json new file mode 100644 index 000000000000..ada2df9c6460 --- /dev/null +++ b/packages/babylon/test/fixtures/experimental/optional-chaining/optional-constructor/options.json @@ -0,0 +1,4 @@ +{ + "plugins": ["optionalChaining"], + "throws": "constructors in/after an Optional Chain are not allowed (1:7)" + } diff --git a/packages/babylon/test/fixtures/experimental/optional-chaining/optional-tagged-template-literals/input.js b/packages/babylon/test/fixtures/experimental/optional-chaining/optional-tagged-template-literals/input.js new file mode 100644 index 000000000000..7a70f3cdcb72 --- /dev/null +++ b/packages/babylon/test/fixtures/experimental/optional-chaining/optional-tagged-template-literals/input.js @@ -0,0 +1 @@ +a?.b`foo` \ No newline at end of file diff --git a/packages/babylon/test/fixtures/experimental/optional-chaining/optional-tagged-template-literals/options.json b/packages/babylon/test/fixtures/experimental/optional-chaining/optional-tagged-template-literals/options.json new file mode 100644 index 000000000000..fb1568dfd199 --- /dev/null +++ b/packages/babylon/test/fixtures/experimental/optional-chaining/optional-tagged-template-literals/options.json @@ -0,0 +1,4 @@ +{ + "plugins" : ["optionalChaining"], + "throws" : "Tagged Template Literals are not allowed in optionalChain (1:0)" +} \ No newline at end of file diff --git a/packages/babylon/test/fixtures/experimental/optional-chaining/parenthised-chain/input.js b/packages/babylon/test/fixtures/experimental/optional-chaining/parenthised-chain/input.js new file mode 100644 index 000000000000..bea5fb1bebb9 --- /dev/null +++ b/packages/babylon/test/fixtures/experimental/optional-chaining/parenthised-chain/input.js @@ -0,0 +1,5 @@ +(a?.b).c; + +(a?.b).c(); + +(a?.b)?.c.d?.e; \ No newline at end of file diff --git a/packages/babylon/test/fixtures/experimental/optional-chaining/parenthised-chain/options.json b/packages/babylon/test/fixtures/experimental/optional-chaining/parenthised-chain/options.json new file mode 100644 index 000000000000..f19632ef9d4a --- /dev/null +++ b/packages/babylon/test/fixtures/experimental/optional-chaining/parenthised-chain/options.json @@ -0,0 +1,3 @@ +{ + "plugins": ["optionalChaining"] +} diff --git a/packages/babylon/test/fixtures/experimental/optional-chaining/parenthised-chain/output.json b/packages/babylon/test/fixtures/experimental/optional-chaining/parenthised-chain/output.json new file mode 100644 index 000000000000..d099840c7b97 --- /dev/null +++ b/packages/babylon/test/fixtures/experimental/optional-chaining/parenthised-chain/output.json @@ -0,0 +1,428 @@ +{ + "type": "File", + "start": 0, + "end": 39, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 5, + "column": 15 + } + }, + "program": { + "type": "Program", + "start": 0, + "end": 39, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 5, + "column": 15 + } + }, + "sourceType": "script", + "body": [ + { + "type": "ExpressionStatement", + "start": 0, + "end": 9, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 9 + } + }, + "expression": { + "type": "MemberExpression", + "start": 0, + "end": 8, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 8 + } + }, + "object": { + "type": "OptionalMemberExpression", + "start": 1, + "end": 5, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 5 + } + }, + "object": { + "type": "Identifier", + "start": 1, + "end": 2, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 2 + }, + "identifierName": "a" + }, + "name": "a" + }, + "property": { + "type": "Identifier", + "start": 4, + "end": 5, + "loc": { + "start": { + "line": 1, + "column": 4 + }, + "end": { + "line": 1, + "column": 5 + }, + "identifierName": "b" + }, + "name": "b" + }, + "computed": false, + "optional": true, + "extra": { + "parenthesized": true, + "parenStart": 0 + } + }, + "property": { + "type": "Identifier", + "start": 7, + "end": 8, + "loc": { + "start": { + "line": 1, + "column": 7 + }, + "end": { + "line": 1, + "column": 8 + }, + "identifierName": "c" + }, + "name": "c" + }, + "computed": false + } + }, + { + "type": "ExpressionStatement", + "start": 11, + "end": 22, + "loc": { + "start": { + "line": 3, + "column": 0 + }, + "end": { + "line": 3, + "column": 11 + } + }, + "expression": { + "type": "CallExpression", + "start": 11, + "end": 21, + "loc": { + "start": { + "line": 3, + "column": 0 + }, + "end": { + "line": 3, + "column": 10 + } + }, + "callee": { + "type": "MemberExpression", + "start": 11, + "end": 19, + "loc": { + "start": { + "line": 3, + "column": 0 + }, + "end": { + "line": 3, + "column": 8 + } + }, + "object": { + "type": "OptionalMemberExpression", + "start": 12, + "end": 16, + "loc": { + "start": { + "line": 3, + "column": 1 + }, + "end": { + "line": 3, + "column": 5 + } + }, + "object": { + "type": "Identifier", + "start": 12, + "end": 13, + "loc": { + "start": { + "line": 3, + "column": 1 + }, + "end": { + "line": 3, + "column": 2 + }, + "identifierName": "a" + }, + "name": "a" + }, + "property": { + "type": "Identifier", + "start": 15, + "end": 16, + "loc": { + "start": { + "line": 3, + "column": 4 + }, + "end": { + "line": 3, + "column": 5 + }, + "identifierName": "b" + }, + "name": "b" + }, + "computed": false, + "optional": true, + "extra": { + "parenthesized": true, + "parenStart": 11 + } + }, + "property": { + "type": "Identifier", + "start": 18, + "end": 19, + "loc": { + "start": { + "line": 3, + "column": 7 + }, + "end": { + "line": 3, + "column": 8 + }, + "identifierName": "c" + }, + "name": "c" + }, + "computed": false + }, + "arguments": [] + } + }, + { + "type": "ExpressionStatement", + "start": 24, + "end": 39, + "loc": { + "start": { + "line": 5, + "column": 0 + }, + "end": { + "line": 5, + "column": 15 + } + }, + "expression": { + "type": "OptionalMemberExpression", + "start": 24, + "end": 38, + "loc": { + "start": { + "line": 5, + "column": 0 + }, + "end": { + "line": 5, + "column": 14 + } + }, + "object": { + "type": "OptionalMemberExpression", + "start": 24, + "end": 35, + "loc": { + "start": { + "line": 5, + "column": 0 + }, + "end": { + "line": 5, + "column": 11 + } + }, + "object": { + "type": "OptionalMemberExpression", + "start": 24, + "end": 33, + "loc": { + "start": { + "line": 5, + "column": 0 + }, + "end": { + "line": 5, + "column": 9 + } + }, + "object": { + "type": "OptionalMemberExpression", + "start": 25, + "end": 29, + "loc": { + "start": { + "line": 5, + "column": 1 + }, + "end": { + "line": 5, + "column": 5 + } + }, + "object": { + "type": "Identifier", + "start": 25, + "end": 26, + "loc": { + "start": { + "line": 5, + "column": 1 + }, + "end": { + "line": 5, + "column": 2 + }, + "identifierName": "a" + }, + "name": "a" + }, + "property": { + "type": "Identifier", + "start": 28, + "end": 29, + "loc": { + "start": { + "line": 5, + "column": 4 + }, + "end": { + "line": 5, + "column": 5 + }, + "identifierName": "b" + }, + "name": "b" + }, + "computed": false, + "optional": true, + "extra": { + "parenthesized": true, + "parenStart": 24 + } + }, + "property": { + "type": "Identifier", + "start": 32, + "end": 33, + "loc": { + "start": { + "line": 5, + "column": 8 + }, + "end": { + "line": 5, + "column": 9 + }, + "identifierName": "c" + }, + "name": "c" + }, + "computed": false, + "optional": true + }, + "property": { + "type": "Identifier", + "start": 34, + "end": 35, + "loc": { + "start": { + "line": 5, + "column": 10 + }, + "end": { + "line": 5, + "column": 11 + }, + "identifierName": "d" + }, + "name": "d" + }, + "computed": false, + "optional": false + }, + "property": { + "type": "Identifier", + "start": 37, + "end": 38, + "loc": { + "start": { + "line": 5, + "column": 13 + }, + "end": { + "line": 5, + "column": 14 + }, + "identifierName": "e" + }, + "name": "e" + }, + "computed": false, + "optional": true + } + } + ], + "directives": [] + } +} \ No newline at end of file diff --git a/packages/babylon/test/fixtures/experimental/optional-chaining/separated-chaining/output.json b/packages/babylon/test/fixtures/experimental/optional-chaining/separated-chaining/output.json index 49d8792a94da..8886e6bce842 100644 --- a/packages/babylon/test/fixtures/experimental/optional-chaining/separated-chaining/output.json +++ b/packages/babylon/test/fixtures/experimental/optional-chaining/separated-chaining/output.json @@ -43,7 +43,7 @@ } }, "expression": { - "type": "MemberExpression", + "type": "OptionalMemberExpression", "start": 0, "end": 13, "loc": { @@ -57,7 +57,7 @@ } }, "object": { - "type": "MemberExpression", + "type": "OptionalMemberExpression", "start": 0, "end": 10, "loc": { @@ -71,7 +71,7 @@ } }, "object": { - "type": "MemberExpression", + "type": "OptionalMemberExpression", "start": 0, "end": 8, "loc": { @@ -85,7 +85,7 @@ } }, "object": { - "type": "MemberExpression", + "type": "OptionalMemberExpression", "start": 0, "end": 6, "loc": { @@ -99,7 +99,7 @@ } }, "object": { - "type": "MemberExpression", + "type": "OptionalMemberExpression", "start": 0, "end": 4, "loc": { @@ -166,7 +166,8 @@ }, "name": "c" }, - "computed": false + "computed": false, + "optional": false }, "property": { "type": "Identifier", @@ -185,7 +186,8 @@ }, "name": "d" }, - "computed": false + "computed": false, + "optional": false }, "property": { "type": "Identifier", @@ -204,7 +206,8 @@ }, "name": "e" }, - "computed": false + "computed": false, + "optional": false }, "property": { "type": "Identifier", @@ -242,7 +245,7 @@ } }, "expression": { - "type": "MemberExpression", + "type": "OptionalMemberExpression", "start": 15, "end": 27, "loc": { @@ -256,7 +259,7 @@ } }, "object": { - "type": "MemberExpression", + "type": "OptionalMemberExpression", "start": 15, "end": 25, "loc": { @@ -270,7 +273,7 @@ } }, "object": { - "type": "MemberExpression", + "type": "OptionalMemberExpression", "start": 15, "end": 23, "loc": { @@ -403,7 +406,8 @@ }, "name": "e" }, - "computed": false + "computed": false, + "optional": false }, "property": { "type": "Identifier", @@ -422,7 +426,8 @@ }, "name": "f" }, - "computed": false + "computed": false, + "optional": false } } ],