diff --git a/packages/babel-parser/src/parser/expression.js b/packages/babel-parser/src/parser/expression.js index 1b58a874696e..25be2e49b701 100644 --- a/packages/babel-parser/src/parser/expression.js +++ b/packages/babel-parser/src/parser/expression.js @@ -303,7 +303,8 @@ export default class ExpressionParser extends LValParser { node.operator = operator; if (this.match(tt.eq)) { - node.left = this.toAssignable(left, /* isLHS */ true); + this.toAssignable(left, /* isLHS */ true); + node.left = left; if ( refExpressionErrors.doubleProtoLoc != null && @@ -2425,7 +2426,8 @@ export default class ExpressionParser extends LValParser { params: N.Expression[], trailingCommaLoc: ?Position, ): void { - node.params = this.toAssignableList(params, trailingCommaLoc, false); + this.toAssignableList(params, trailingCommaLoc, false); + node.params = params; } parseFunctionBodyAndFinish( diff --git a/packages/babel-parser/src/parser/lval.js b/packages/babel-parser/src/parser/lval.js index aeecc15515a1..20f883246882 100644 --- a/packages/babel-parser/src/parser/lval.js +++ b/packages/babel-parser/src/parser/lval.js @@ -90,13 +90,12 @@ export default class LValParser extends NodeUtils { When this one is updated, please check if also that one needs to be updated. * @param {Node} node The expression atom - * @param {boolean} [isLHS=false] Whether we are parsing a LeftHandSideExpression. If isLHS is `true`, the following cases are allowed: - `[(a)] = [0]`, `[(a.b)] = [0]` - - * @returns {Node} The converted assignable pattern + * @param {boolean} [isLHS=false] Whether we are parsing a LeftHandSideExpression. + * If isLHS is `true`, the following cases are allowed: `[(a)] = [0]`, `[(a.b)] = [0]` + * If isLHS is `false`, we are in an arrow function parameters list. * @memberof LValParser */ - toAssignable(node: Node, isLHS: boolean = false): Node { + toAssignable(node: Node, isLHS: boolean = false): void { let parenthesized = undefined; if (node.type === "ParenthesizedExpression" || node.extra?.parenthesized) { parenthesized = unwrapParenthesizedExpression(node); @@ -104,9 +103,12 @@ export default class LValParser extends NodeUtils { // an LHS can be reinterpreted to a binding pattern but not vice versa. // therefore a parenthesized identifier is ambiguous until we are sure it is an assignment expression // i.e. `([(a) = []] = []) => {}` - // see also `recordParenthesizedIdentifierError` signature in packages/babel-parser/src/util/expression-scope.js + // see also `recordArrowParemeterBindingError` signature in packages/babel-parser/src/util/expression-scope.js if (parenthesized.type === "Identifier") { - this.expressionScope.recordParenthesizedIdentifierError({ at: node }); + this.expressionScope.recordArrowParemeterBindingError( + Errors.InvalidParenthesizedAssignment, + { at: node }, + ); } else if (parenthesized.type !== "MemberExpression") { // A parenthesized member expression can be in LHS but not in pattern. // If the LHS is later interpreted as a pattern, `checkLVal` will throw for member expression binding @@ -162,12 +164,10 @@ export default class LValParser extends NodeUtils { } case "SpreadElement": { - this.checkToRestConversion(node); - - node.type = "RestElement"; - const arg = node.argument; - this.toAssignable(arg, isLHS); - break; + throw new Error( + "Internal @babel/parser error (this is a bug, please report it)." + + " SpreadElement should be converted by .toAssignable's caller.", + ); } case "ArrayExpression": @@ -198,7 +198,6 @@ export default class LValParser extends NodeUtils { // We don't know how to deal with this node. It will // be reported by a later call to checkLVal } - return node; } toAssignableObjectExpressionProp( @@ -213,8 +212,15 @@ export default class LValParser extends NodeUtils { : Errors.PatternHasMethod, { at: prop.key }, ); - } else if (prop.type === "SpreadElement" && !isLast) { - this.raise(Errors.RestTrailingComma, { at: prop }); + } else if (prop.type === "SpreadElement") { + prop.type = "RestElement"; + const arg = prop.argument; + this.checkToRestConversion(arg, /* allowPattern */ false); + this.toAssignable(arg, isLHS); + + if (!isLast) { + this.raise(Errors.RestTrailingComma, { at: prop }); + } } else { this.toAssignable(prop, isLHS); } @@ -226,43 +232,30 @@ export default class LValParser extends NodeUtils { exprList: Expression[], trailingCommaLoc?: ?Position, isLHS: boolean, - ): $ReadOnlyArray { - let end = exprList.length; - if (end) { - const last = exprList[end - 1]; - if (last?.type === "RestElement") { - --end; - } else if (last?.type === "SpreadElement") { - last.type = "RestElement"; - let arg = last.argument; - this.toAssignable(arg, isLHS); - arg = unwrapParenthesizedExpression(arg); - if ( - arg.type !== "Identifier" && - arg.type !== "MemberExpression" && - arg.type !== "ArrayPattern" && - arg.type !== "ObjectPattern" - ) { - this.unexpected(arg.start); - } - - if (trailingCommaLoc) { - this.raise(Errors.RestTrailingComma, { at: trailingCommaLoc }); - } + ): void { + const end = exprList.length - 1; - --end; - } - } - for (let i = 0; i < end; i++) { + for (let i = 0; i <= end; i++) { const elt = exprList[i]; - if (elt) { + if (!elt) continue; + + if (elt.type === "SpreadElement") { + elt.type = "RestElement"; + const arg = elt.argument; + this.checkToRestConversion(arg, /* allowPattern */ true); + this.toAssignable(arg, isLHS); + } else { this.toAssignable(elt, isLHS); - if (elt.type === "RestElement") { + } + + if (elt.type === "RestElement") { + if (i < end) { this.raise(Errors.RestTrailingComma, { at: elt }); + } else if (trailingCommaLoc) { + this.raise(Errors.RestTrailingComma, { at: trailingCommaLoc }); } } } - return exprList; } isAssignable(node: Node, isBinding?: boolean): boolean { @@ -513,8 +506,9 @@ export default class LValParser extends NodeUtils { * `[key: string, parenthesized: false]`. * * @param {NodeType} type A Node `type` string - * @param {boolean} isParenthesized - * Whether the node in question is parenthesized. + * @param {boolean} isUnparenthesizedInAssign + * Whether the node in question is unparenthesized and its parent + * is either an assignment pattern or an assignment expression. * @param {BindingTypes} binding * The binding operation that is being considered for this potential * LVal. @@ -525,8 +519,13 @@ export default class LValParser extends NodeUtils { * A `[string, boolean]` tuple if we need to check this child and * treat is as parenthesized. */ - // eslint-disable-next-line no-unused-vars - isValidLVal(type: string, isParenthesized: boolean, binding: BindingTypes) { + isValidLVal( + type: string, + // eslint-disable-next-line no-unused-vars + isUnparenthesizedInAssign: boolean, + // eslint-disable-next-line no-unused-vars + binding: BindingTypes, + ) { return getOwn( { AssignmentPattern: "left", @@ -625,7 +624,8 @@ export default class LValParser extends NodeUtils { const validity = this.isValidLVal( expression.type, - hasParenthesizedAncestor || expression.extra?.parenthesized, + !(hasParenthesizedAncestor || expression.extra?.parenthesized) && + ancestor.type === "AssignmentExpression", binding, ); @@ -707,14 +707,20 @@ export default class LValParser extends NodeUtils { this.scope.declareName(identifier.name, binding, identifier.loc.start); } - checkToRestConversion(node: SpreadElement): void { - if ( - node.argument.type !== "Identifier" && - node.argument.type !== "MemberExpression" - ) { - this.raise(Errors.InvalidRestAssignmentPattern, { - at: node.argument, - }); + checkToRestConversion(node: Node, allowPattern: boolean): void { + switch (node.type) { + case "ParenthesizedExpression": + this.checkToRestConversion(node.expression, allowPattern); + break; + case "Identifier": + case "MemberExpression": + break; + case "ArrayExpression": + case "ObjectExpression": + if (allowPattern) break; + /* falls through */ + default: + this.raise(Errors.InvalidRestAssignmentPattern, { at: node }); } } diff --git a/packages/babel-parser/src/plugins/estree.js b/packages/babel-parser/src/plugins/estree.js index c09187f99d82..b4863fcba0ec 100644 --- a/packages/babel-parser/src/plugins/estree.js +++ b/packages/babel-parser/src/plugins/estree.js @@ -354,7 +354,7 @@ export default (superClass: Class): Class => return super.isAssignable(node, isBinding); } - toAssignable(node: N.Node, isLHS: boolean = false): N.Node { + toAssignable(node: N.Node, isLHS: boolean = false): void { if (node != null && this.isObjectProperty(node)) { const { key, value } = node; if (this.isPrivateName(key)) { @@ -364,19 +364,18 @@ export default (superClass: Class): Class => ); } this.toAssignable(value, isLHS); - return node; + } else { + super.toAssignable(node, isLHS); } - - return super.toAssignable(node, isLHS); } - toAssignableObjectExpressionProp(prop: N.Node, ...args) { + toAssignableObjectExpressionProp(prop: N.Node) { if (prop.kind === "get" || prop.kind === "set") { this.raise(Errors.PatternHasAccessor, { at: prop.key }); } else if (prop.method) { this.raise(Errors.PatternHasMethod, { at: prop.key }); } else { - super.toAssignableObjectExpressionProp(prop, ...args); + super.toAssignableObjectExpressionProp(...arguments); } } diff --git a/packages/babel-parser/src/plugins/flow/index.js b/packages/babel-parser/src/plugins/flow/index.js index c335fc58a702..0f85780f59d6 100644 --- a/packages/babel-parser/src/plugins/flow/index.js +++ b/packages/babel-parser/src/plugins/flow/index.js @@ -2362,12 +2362,15 @@ export default (superClass: Class): Class => } } - toAssignable(node: N.Node, isLHS: boolean = false): N.Node { - if (node.type === "TypeCastExpression") { - return super.toAssignable(this.typeCastToParameter(node), isLHS); - } else { - return super.toAssignable(node, isLHS); + toAssignable(node: N.Node, isLHS: boolean = false): void { + if ( + !isLHS && + node.type === "AssignmentExpression" && + node.left.type === "TypeCastExpression" + ) { + node.left = this.typeCastToParameter(node.left); } + super.toAssignable(...arguments); } // turn type casts that we found in function parameter head into type annotated params @@ -2375,14 +2378,14 @@ export default (superClass: Class): Class => exprList: N.Expression[], trailingCommaLoc?: ?Position, isLHS: boolean, - ): $ReadOnlyArray { + ): void { for (let i = 0; i < exprList.length; i++) { const expr = exprList[i]; if (expr?.type === "TypeCastExpression") { exprList[i] = this.typeCastToParameter(expr); } } - return super.toAssignableList(exprList, trailingCommaLoc, isLHS); + super.toAssignableList(exprList, trailingCommaLoc, isLHS); } // this is a list of nodes, from something like a call expression, we need to filter the diff --git a/packages/babel-parser/src/plugins/placeholders.js b/packages/babel-parser/src/plugins/placeholders.js index 3b28fc968b65..805ff84b48be 100644 --- a/packages/babel-parser/src/plugins/placeholders.js +++ b/packages/babel-parser/src/plugins/placeholders.js @@ -140,16 +140,16 @@ export default (superClass: Class): Class => return type === "Placeholder" || super.isValidLVal(type, ...rest); } - toAssignable(node: N.Node): N.Node { + toAssignable(node: N.Node): void { if ( node && node.type === "Placeholder" && node.expectedNode === "Expression" ) { node.expectedNode = "Pattern"; - return node; + } else { + super.toAssignable(...arguments); } - return super.toAssignable(...arguments); } /* ============================================================ * diff --git a/packages/babel-parser/src/plugins/typescript/index.js b/packages/babel-parser/src/plugins/typescript/index.js index daf6ab18a68b..05525510791c 100644 --- a/packages/babel-parser/src/plugins/typescript/index.js +++ b/packages/babel-parser/src/plugins/typescript/index.js @@ -3250,38 +3250,64 @@ export default (superClass: Class): Class => } } - toAssignable(node: N.Node, isLHS: boolean = false): N.Node { + toAssignable(node: N.Node, isLHS: boolean = false): void { switch (node.type) { - case "TSTypeCastExpression": - return super.toAssignable(this.typeCastToParameter(node), isLHS); - case "TSParameterProperty": - return super.toAssignable(node, isLHS); case "ParenthesizedExpression": - return this.toAssignableParenthesizedExpression(node, isLHS); + this.toAssignableParenthesizedExpression(node, isLHS); + break; case "TSAsExpression": case "TSNonNullExpression": case "TSTypeAssertion": - node.expression = this.toAssignable(node.expression, isLHS); - return node; + if (isLHS) { + this.expressionScope.recordArrowParemeterBindingError( + TSErrors.UnexpectedTypeCastInParameter, + { at: node }, + ); + } else { + this.raise(TSErrors.UnexpectedTypeCastInParameter, { at: node }); + } + this.toAssignable(node.expression, isLHS); + break; + case "AssignmentExpression": + if (!isLHS && node.left.type === "TSTypeCastExpression") { + node.left = this.typeCastToParameter(node.left); + } + /* fall through */ default: - return super.toAssignable(node, isLHS); + super.toAssignable(node, isLHS); } } - toAssignableParenthesizedExpression(node: N.Node, isLHS: boolean) { + toAssignableParenthesizedExpression(node: N.Node, isLHS: boolean): void { switch (node.expression.type) { case "TSAsExpression": case "TSNonNullExpression": case "TSTypeAssertion": case "ParenthesizedExpression": - node.expression = this.toAssignable(node.expression, isLHS); - return node; + this.toAssignable(node.expression, isLHS); + break; + default: + super.toAssignable(node, isLHS); + } + } + + checkToRestConversion(node: N.Node, allowPattern: boolean): void { + switch (node.type) { + case "TSAsExpression": + case "TSTypeAssertion": + case "TSNonNullExpression": + this.checkToRestConversion(node.expression, false); + break; default: - return super.toAssignable(node, isLHS); + super.checkToRestConversion(node, allowPattern); } } - isValidLVal(type: string, isParenthesized: boolean, binding: BindingTypes) { + isValidLVal( + type: string, + isUnparenthesizedInAssign: boolean, + binding: BindingTypes, + ) { return ( getOwn( { @@ -3291,17 +3317,13 @@ export default (superClass: Class): Class => TSTypeCastExpression: true, TSParameterProperty: "parameter", TSNonNullExpression: "expression", - TSAsExpression: (binding !== BIND_NONE || isParenthesized) && [ - "expression", - true, - ], - TSTypeAssertion: (binding !== BIND_NONE || isParenthesized) && [ - "expression", - true, - ], + TSAsExpression: (binding !== BIND_NONE || + !isUnparenthesizedInAssign) && ["expression", true], + TSTypeAssertion: (binding !== BIND_NONE || + !isUnparenthesizedInAssign) && ["expression", true], }, type, - ) || super.isValidLVal(type, isParenthesized, binding) + ) || super.isValidLVal(type, isUnparenthesizedInAssign, binding) ); } @@ -3411,27 +3433,14 @@ export default (superClass: Class): Class => return type; } - toAssignableList(exprList: N.Expression[]): $ReadOnlyArray { + toAssignableList(exprList: N.Expression[]): void { for (let i = 0; i < exprList.length; i++) { const expr = exprList[i]; - if (!expr) continue; - switch (expr.type) { - case "TSTypeCastExpression": - exprList[i] = this.typeCastToParameter(expr); - break; - case "TSAsExpression": - case "TSTypeAssertion": - if (!this.state.maybeInArrowParameters) { - exprList[i] = this.typeCastToParameter(expr); - } else { - this.raise(TSErrors.UnexpectedTypeCastInParameter, { - at: expr, - }); - } - break; + if (expr?.type === "TSTypeCastExpression") { + exprList[i] = this.typeCastToParameter(expr); } } - return super.toAssignableList(...arguments); + super.toAssignableList(...arguments); } typeCastToParameter(node: N.TsTypeCastExpression): N.Node { diff --git a/packages/babel-parser/src/util/expression-scope.js b/packages/babel-parser/src/util/expression-scope.js index f3fb1019a28e..fee099aa74db 100644 --- a/packages/babel-parser/src/util/expression-scope.js +++ b/packages/babel-parser/src/util/expression-scope.js @@ -1,6 +1,6 @@ // @flow -import { Errors } from "../parse-error"; +import { Errors, type ParseErrorConstructor } from "../parse-error"; import { Position } from "./location"; import type { Node } from "../types"; import Tokenizer from "../tokenizer"; @@ -86,13 +86,13 @@ type ArrowHeadParsingDeclarationError = | typeof Errors.AwaitBindingIdentifier; class ArrowHeadParsingScope extends ExpressionScope { - declarationErrors: Map = + declarationErrors: Map, Position]> = new Map(); constructor(type: 1 | 2) { super(type); } - recordDeclarationError( - ParsingErrorClass: T, + recordDeclarationError( + ParsingErrorClass: ParseErrorConstructor<{||}>, { at }: { at: Position }, ) { const index = at.index; @@ -157,9 +157,11 @@ export default class ExpressionScopeHandler { } /** - * Record parenthesized identifier errors + * Record errors that must be thrown if the current pattern ends up being an arrow + * function parameter. This is used to record parenthesized identifiers, and to record + * "a as T" and " a" type assertions when parsing typescript. * - * A parenthesized identifier in LHS can be ambiguous because the assignment + * A parenthesized identifier (or type assertion) in LHS can be ambiguous because the assignment * can be transformed to an assignable later, but not vice versa: * For example, in `([(a) = []] = []) => {}`, we think `(a) = []` is an LHS in `[(a) = []]`, * an LHS within `[(a) = []] = []`. However the LHS chain is then transformed by toAssignable, @@ -172,23 +174,23 @@ export default class ExpressionScopeHandler { * For example, in `( x = ( [(a) = []] = [] ) ) => {}`, we should not record `(a)` in `( x = ... ) =>` * arrow scope because when we finish parsing `( [(a) = []] = [] )`, it is an unambiguous assignment * expression and can not be cast to pattern - * @param {number} pos - * @param {ErrorTemplate} template + * @param {ParseErrorConstructor<{||}>} error + * @param {Node} payload.at * @returns {void} * @memberof ExpressionScopeHandler */ - recordParenthesizedIdentifierError({ at: node }: { at: Node }): void { + recordArrowParemeterBindingError( + error: ParseErrorConstructor<{||}>, + { at: node }: { at: Node }, + ): void { const { stack } = this; const scope: ExpressionScope = stack[stack.length - 1]; const origin = { at: node.loc.start }; if (scope.isCertainlyParameterDeclaration()) { - this.parser.raise(Errors.InvalidParenthesizedAssignment, origin); + this.parser.raise(error, origin); } else if (scope.canBeArrowParameterDeclaration()) { /*:: invariant(scope instanceof ArrowHeadParsingScope) */ - scope.recordDeclarationError( - Errors.InvalidParenthesizedAssignment, - origin, - ); + scope.recordDeclarationError(error, origin); } else { return; } diff --git a/packages/babel-parser/test/fixtures/core/create-parenthesized-expressions/valid-pattern-in-rest-lhs/input.js b/packages/babel-parser/test/fixtures/core/create-parenthesized-expressions/valid-pattern-in-array-rest-lhs/input.js similarity index 100% rename from packages/babel-parser/test/fixtures/core/create-parenthesized-expressions/valid-pattern-in-rest-lhs/input.js rename to packages/babel-parser/test/fixtures/core/create-parenthesized-expressions/valid-pattern-in-array-rest-lhs/input.js diff --git a/packages/babel-parser/test/fixtures/core/create-parenthesized-expressions/valid-pattern-in-rest-lhs/output.json b/packages/babel-parser/test/fixtures/core/create-parenthesized-expressions/valid-pattern-in-array-rest-lhs/output.json similarity index 100% rename from packages/babel-parser/test/fixtures/core/create-parenthesized-expressions/valid-pattern-in-rest-lhs/output.json rename to packages/babel-parser/test/fixtures/core/create-parenthesized-expressions/valid-pattern-in-array-rest-lhs/output.json diff --git a/packages/babel-parser/test/fixtures/core/create-parenthesized-expressions/valid-pattern-in-rest-member-lhs/input.js b/packages/babel-parser/test/fixtures/core/create-parenthesized-expressions/valid-pattern-in-array-rest-member-lhs/input.js similarity index 100% rename from packages/babel-parser/test/fixtures/core/create-parenthesized-expressions/valid-pattern-in-rest-member-lhs/input.js rename to packages/babel-parser/test/fixtures/core/create-parenthesized-expressions/valid-pattern-in-array-rest-member-lhs/input.js diff --git a/packages/babel-parser/test/fixtures/core/create-parenthesized-expressions/valid-pattern-in-rest-member-lhs/output.json b/packages/babel-parser/test/fixtures/core/create-parenthesized-expressions/valid-pattern-in-array-rest-member-lhs/output.json similarity index 100% rename from packages/babel-parser/test/fixtures/core/create-parenthesized-expressions/valid-pattern-in-rest-member-lhs/output.json rename to packages/babel-parser/test/fixtures/core/create-parenthesized-expressions/valid-pattern-in-array-rest-member-lhs/output.json diff --git a/packages/babel-parser/test/fixtures/core/create-parenthesized-expressions/valid-pattern-in-object-rest-lhs/input.js b/packages/babel-parser/test/fixtures/core/create-parenthesized-expressions/valid-pattern-in-object-rest-lhs/input.js new file mode 100644 index 000000000000..6265e21c18dd --- /dev/null +++ b/packages/babel-parser/test/fixtures/core/create-parenthesized-expressions/valid-pattern-in-object-rest-lhs/input.js @@ -0,0 +1 @@ +0, {...(a)} = {}; diff --git a/packages/babel-parser/test/fixtures/core/create-parenthesized-expressions/valid-pattern-in-object-rest-lhs/output.json b/packages/babel-parser/test/fixtures/core/create-parenthesized-expressions/valid-pattern-in-object-rest-lhs/output.json new file mode 100644 index 000000000000..b71bb3cb75c3 --- /dev/null +++ b/packages/babel-parser/test/fixtures/core/create-parenthesized-expressions/valid-pattern-in-object-rest-lhs/output.json @@ -0,0 +1,61 @@ +{ + "type": "File", + "start":0,"end":17,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":1,"column":17,"index":17}}, + "program": { + "type": "Program", + "start":0,"end":17,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":1,"column":17,"index":17}}, + "sourceType": "script", + "interpreter": null, + "body": [ + { + "type": "ExpressionStatement", + "start":0,"end":17,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":1,"column":17,"index":17}}, + "expression": { + "type": "SequenceExpression", + "start":0,"end":16,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":1,"column":16,"index":16}}, + "expressions": [ + { + "type": "NumericLiteral", + "start":0,"end":1,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":1,"column":1,"index":1}}, + "extra": { + "rawValue": 0, + "raw": "0" + }, + "value": 0 + }, + { + "type": "AssignmentExpression", + "start":3,"end":16,"loc":{"start":{"line":1,"column":3,"index":3},"end":{"line":1,"column":16,"index":16}}, + "operator": "=", + "left": { + "type": "ObjectPattern", + "start":3,"end":11,"loc":{"start":{"line":1,"column":3,"index":3},"end":{"line":1,"column":11,"index":11}}, + "properties": [ + { + "type": "RestElement", + "start":4,"end":10,"loc":{"start":{"line":1,"column":4,"index":4},"end":{"line":1,"column":10,"index":10}}, + "argument": { + "type": "ParenthesizedExpression", + "start":7,"end":10,"loc":{"start":{"line":1,"column":7,"index":7},"end":{"line":1,"column":10,"index":10}}, + "expression": { + "type": "Identifier", + "start":8,"end":9,"loc":{"start":{"line":1,"column":8,"index":8},"end":{"line":1,"column":9,"index":9},"identifierName":"a"}, + "name": "a" + } + } + } + ] + }, + "right": { + "type": "ObjectExpression", + "start":14,"end":16,"loc":{"start":{"line":1,"column":14,"index":14},"end":{"line":1,"column":16,"index":16}}, + "properties": [] + } + } + ] + } + } + ], + "directives": [] + } +} diff --git a/packages/babel-parser/test/fixtures/core/create-parenthesized-expressions/valid-pattern-in-object-rest-member-lhs/input.js b/packages/babel-parser/test/fixtures/core/create-parenthesized-expressions/valid-pattern-in-object-rest-member-lhs/input.js new file mode 100644 index 000000000000..e9771dc6f6f9 --- /dev/null +++ b/packages/babel-parser/test/fixtures/core/create-parenthesized-expressions/valid-pattern-in-object-rest-member-lhs/input.js @@ -0,0 +1 @@ +0, {...(a.b)} = {}; diff --git a/packages/babel-parser/test/fixtures/core/create-parenthesized-expressions/valid-pattern-in-object-rest-member-lhs/output.json b/packages/babel-parser/test/fixtures/core/create-parenthesized-expressions/valid-pattern-in-object-rest-member-lhs/output.json new file mode 100644 index 000000000000..721c6211d4eb --- /dev/null +++ b/packages/babel-parser/test/fixtures/core/create-parenthesized-expressions/valid-pattern-in-object-rest-member-lhs/output.json @@ -0,0 +1,71 @@ +{ + "type": "File", + "start":0,"end":19,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":1,"column":19,"index":19}}, + "program": { + "type": "Program", + "start":0,"end":19,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":1,"column":19,"index":19}}, + "sourceType": "script", + "interpreter": null, + "body": [ + { + "type": "ExpressionStatement", + "start":0,"end":19,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":1,"column":19,"index":19}}, + "expression": { + "type": "SequenceExpression", + "start":0,"end":18,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":1,"column":18,"index":18}}, + "expressions": [ + { + "type": "NumericLiteral", + "start":0,"end":1,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":1,"column":1,"index":1}}, + "extra": { + "rawValue": 0, + "raw": "0" + }, + "value": 0 + }, + { + "type": "AssignmentExpression", + "start":3,"end":18,"loc":{"start":{"line":1,"column":3,"index":3},"end":{"line":1,"column":18,"index":18}}, + "operator": "=", + "left": { + "type": "ObjectPattern", + "start":3,"end":13,"loc":{"start":{"line":1,"column":3,"index":3},"end":{"line":1,"column":13,"index":13}}, + "properties": [ + { + "type": "RestElement", + "start":4,"end":12,"loc":{"start":{"line":1,"column":4,"index":4},"end":{"line":1,"column":12,"index":12}}, + "argument": { + "type": "ParenthesizedExpression", + "start":7,"end":12,"loc":{"start":{"line":1,"column":7,"index":7},"end":{"line":1,"column":12,"index":12}}, + "expression": { + "type": "MemberExpression", + "start":8,"end":11,"loc":{"start":{"line":1,"column":8,"index":8},"end":{"line":1,"column":11,"index":11}}, + "object": { + "type": "Identifier", + "start":8,"end":9,"loc":{"start":{"line":1,"column":8,"index":8},"end":{"line":1,"column":9,"index":9},"identifierName":"a"}, + "name": "a" + }, + "computed": false, + "property": { + "type": "Identifier", + "start":10,"end":11,"loc":{"start":{"line":1,"column":10,"index":10},"end":{"line":1,"column":11,"index":11},"identifierName":"b"}, + "name": "b" + } + } + } + } + ] + }, + "right": { + "type": "ObjectExpression", + "start":16,"end":18,"loc":{"start":{"line":1,"column":16,"index":16},"end":{"line":1,"column":18,"index":18}}, + "properties": [] + } + } + ] + } + } + ], + "directives": [] + } +} diff --git a/packages/babel-parser/test/fixtures/es2018/object-rest-spread/expression-rest-not-last-invalid/output.json b/packages/babel-parser/test/fixtures/es2018/object-rest-spread/expression-rest-not-last-invalid/output.json index 6ab32e02056b..a988993ba48c 100644 --- a/packages/babel-parser/test/fixtures/es2018/object-rest-spread/expression-rest-not-last-invalid/output.json +++ b/packages/babel-parser/test/fixtures/es2018/object-rest-spread/expression-rest-not-last-invalid/output.json @@ -2,8 +2,7 @@ "type": "File", "start":0,"end":19,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":1,"column":19,"index":19}}, "errors": [ - "SyntaxError: Unexpected trailing comma after rest element. (1:2)", - "SyntaxError: Invalid left-hand side in object destructuring pattern. (1:2)" + "SyntaxError: Unexpected trailing comma after rest element. (1:2)" ], "program": { "type": "Program", @@ -23,7 +22,7 @@ "start":1,"end":13,"loc":{"start":{"line":1,"column":1,"index":1},"end":{"line":1,"column":13,"index":13}}, "properties": [ { - "type": "SpreadElement", + "type": "RestElement", "start":2,"end":9,"loc":{"start":{"line":1,"column":2,"index":2},"end":{"line":1,"column":9,"index":9}}, "argument": { "type": "Identifier", diff --git a/packages/babel-parser/test/fixtures/es2018/object-rest-spread/18/input.js b/packages/babel-parser/test/fixtures/es2018/object-rest-spread/no-pattern-in-rest-with-flow/input.js similarity index 100% rename from packages/babel-parser/test/fixtures/es2018/object-rest-spread/18/input.js rename to packages/babel-parser/test/fixtures/es2018/object-rest-spread/no-pattern-in-rest-with-flow/input.js diff --git a/packages/babel-parser/test/fixtures/es2018/object-rest-spread/no-pattern-in-rest-with-flow/options.json b/packages/babel-parser/test/fixtures/es2018/object-rest-spread/no-pattern-in-rest-with-flow/options.json new file mode 100644 index 000000000000..66dd3748d6ea --- /dev/null +++ b/packages/babel-parser/test/fixtures/es2018/object-rest-spread/no-pattern-in-rest-with-flow/options.json @@ -0,0 +1,3 @@ +{ + "plugins": ["flow"] +} diff --git a/packages/babel-parser/test/fixtures/es2018/object-rest-spread/18/output.json b/packages/babel-parser/test/fixtures/es2018/object-rest-spread/no-pattern-in-rest-with-flow/output.json similarity index 100% rename from packages/babel-parser/test/fixtures/es2018/object-rest-spread/18/output.json rename to packages/babel-parser/test/fixtures/es2018/object-rest-spread/no-pattern-in-rest-with-flow/output.json diff --git a/packages/babel-parser/test/fixtures/es2018/object-rest-spread/no-pattern-in-rest-with-ts/input.js b/packages/babel-parser/test/fixtures/es2018/object-rest-spread/no-pattern-in-rest-with-ts/input.js new file mode 100644 index 000000000000..78c283fdd7fa --- /dev/null +++ b/packages/babel-parser/test/fixtures/es2018/object-rest-spread/no-pattern-in-rest-with-ts/input.js @@ -0,0 +1 @@ +({...{}} = {}) diff --git a/packages/babel-parser/test/fixtures/es2018/object-rest-spread/no-pattern-in-rest-with-ts/options.json b/packages/babel-parser/test/fixtures/es2018/object-rest-spread/no-pattern-in-rest-with-ts/options.json new file mode 100644 index 000000000000..5047d6993fe8 --- /dev/null +++ b/packages/babel-parser/test/fixtures/es2018/object-rest-spread/no-pattern-in-rest-with-ts/options.json @@ -0,0 +1,3 @@ +{ + "plugins": ["typescript"] +} diff --git a/packages/babel-parser/test/fixtures/es2018/object-rest-spread/no-pattern-in-rest-with-ts/output.json b/packages/babel-parser/test/fixtures/es2018/object-rest-spread/no-pattern-in-rest-with-ts/output.json new file mode 100644 index 000000000000..93d12f3462d4 --- /dev/null +++ b/packages/babel-parser/test/fixtures/es2018/object-rest-spread/no-pattern-in-rest-with-ts/output.json @@ -0,0 +1,49 @@ +{ + "type": "File", + "start":0,"end":14,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":1,"column":14,"index":14}}, + "errors": [ + "SyntaxError: Invalid rest operator's argument. (1:5)" + ], + "program": { + "type": "Program", + "start":0,"end":14,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":1,"column":14,"index":14}}, + "sourceType": "script", + "interpreter": null, + "body": [ + { + "type": "ExpressionStatement", + "start":0,"end":14,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":1,"column":14,"index":14}}, + "expression": { + "type": "AssignmentExpression", + "start":1,"end":13,"loc":{"start":{"line":1,"column":1,"index":1},"end":{"line":1,"column":13,"index":13}}, + "operator": "=", + "left": { + "type": "ObjectPattern", + "start":1,"end":8,"loc":{"start":{"line":1,"column":1,"index":1},"end":{"line":1,"column":8,"index":8}}, + "properties": [ + { + "type": "RestElement", + "start":2,"end":7,"loc":{"start":{"line":1,"column":2,"index":2},"end":{"line":1,"column":7,"index":7}}, + "argument": { + "type": "ObjectPattern", + "start":5,"end":7,"loc":{"start":{"line":1,"column":5,"index":5},"end":{"line":1,"column":7,"index":7}}, + "properties": [] + } + } + ] + }, + "right": { + "type": "ObjectExpression", + "start":11,"end":13,"loc":{"start":{"line":1,"column":11,"index":11},"end":{"line":1,"column":13,"index":13}}, + "properties": [] + }, + "extra": { + "parenthesized": true, + "parenStart": 0 + } + } + } + ], + "directives": [] + } +} diff --git a/packages/babel-parser/test/fixtures/es2018/object-rest-spread/no-pattern-in-rest/input.js b/packages/babel-parser/test/fixtures/es2018/object-rest-spread/no-pattern-in-rest/input.js new file mode 100644 index 000000000000..78c283fdd7fa --- /dev/null +++ b/packages/babel-parser/test/fixtures/es2018/object-rest-spread/no-pattern-in-rest/input.js @@ -0,0 +1 @@ +({...{}} = {}) diff --git a/packages/babel-parser/test/fixtures/es2018/object-rest-spread/no-pattern-in-rest/output.json b/packages/babel-parser/test/fixtures/es2018/object-rest-spread/no-pattern-in-rest/output.json new file mode 100644 index 000000000000..93d12f3462d4 --- /dev/null +++ b/packages/babel-parser/test/fixtures/es2018/object-rest-spread/no-pattern-in-rest/output.json @@ -0,0 +1,49 @@ +{ + "type": "File", + "start":0,"end":14,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":1,"column":14,"index":14}}, + "errors": [ + "SyntaxError: Invalid rest operator's argument. (1:5)" + ], + "program": { + "type": "Program", + "start":0,"end":14,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":1,"column":14,"index":14}}, + "sourceType": "script", + "interpreter": null, + "body": [ + { + "type": "ExpressionStatement", + "start":0,"end":14,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":1,"column":14,"index":14}}, + "expression": { + "type": "AssignmentExpression", + "start":1,"end":13,"loc":{"start":{"line":1,"column":1,"index":1},"end":{"line":1,"column":13,"index":13}}, + "operator": "=", + "left": { + "type": "ObjectPattern", + "start":1,"end":8,"loc":{"start":{"line":1,"column":1,"index":1},"end":{"line":1,"column":8,"index":8}}, + "properties": [ + { + "type": "RestElement", + "start":2,"end":7,"loc":{"start":{"line":1,"column":2,"index":2},"end":{"line":1,"column":7,"index":7}}, + "argument": { + "type": "ObjectPattern", + "start":5,"end":7,"loc":{"start":{"line":1,"column":5,"index":5},"end":{"line":1,"column":7,"index":7}}, + "properties": [] + } + } + ] + }, + "right": { + "type": "ObjectExpression", + "start":11,"end":13,"loc":{"start":{"line":1,"column":11,"index":11},"end":{"line":1,"column":13,"index":13}}, + "properties": [] + }, + "extra": { + "parenthesized": true, + "parenStart": 0 + } + } + } + ], + "directives": [] + } +} diff --git a/packages/babel-parser/test/fixtures/typescript/cast/destructure-and-assign/output.json b/packages/babel-parser/test/fixtures/typescript/cast/destructure-and-assign/output.json index c75f512e3956..353c94add393 100644 --- a/packages/babel-parser/test/fixtures/typescript/cast/destructure-and-assign/output.json +++ b/packages/babel-parser/test/fixtures/typescript/cast/destructure-and-assign/output.json @@ -19,9 +19,13 @@ "start":0,"end":13,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":1,"column":13,"index":13}}, "elements": [ { - "type": "Identifier", - "start":1,"end":12,"loc":{"start":{"line":1,"column":1,"index":1},"end":{"line":1,"column":12,"index":12},"identifierName":"a"}, - "name": "a", + "type": "TSAsExpression", + "start":1,"end":12,"loc":{"start":{"line":1,"column":1,"index":1},"end":{"line":1,"column":12,"index":12}}, + "expression": { + "type": "Identifier", + "start":1,"end":2,"loc":{"start":{"line":1,"column":1,"index":1},"end":{"line":1,"column":2,"index":2},"identifierName":"a"}, + "name": "a" + }, "typeAnnotation": { "type": "TSNumberKeyword", "start":6,"end":12,"loc":{"start":{"line":1,"column":6,"index":6},"end":{"line":1,"column":12,"index":12}} @@ -58,12 +62,16 @@ "start":22,"end":33,"loc":{"start":{"line":2,"column":0,"index":22},"end":{"line":2,"column":11,"index":33}}, "elements": [ { - "type": "Identifier", - "start":31,"end":30,"loc":{"start":{"line":2,"column":9,"index":31},"end":{"line":2,"column":8,"index":30},"identifierName":"a"}, - "name": "a", + "type": "TSTypeAssertion", + "start":23,"end":32,"loc":{"start":{"line":2,"column":1,"index":23},"end":{"line":2,"column":10,"index":32}}, "typeAnnotation": { "type": "TSNumberKeyword", "start":24,"end":30,"loc":{"start":{"line":2,"column":2,"index":24},"end":{"line":2,"column":8,"index":30}} + }, + "expression": { + "type": "Identifier", + "start":31,"end":32,"loc":{"start":{"line":2,"column":9,"index":31},"end":{"line":2,"column":10,"index":32},"identifierName":"a"}, + "name": "a" } } ] diff --git a/packages/babel-parser/test/fixtures/typescript/cast/destructuring-assignent-rest-invalid/input.ts b/packages/babel-parser/test/fixtures/typescript/cast/destructuring-assignent-rest-invalid/input.ts new file mode 100644 index 000000000000..3946f7f08e3c --- /dev/null +++ b/packages/babel-parser/test/fixtures/typescript/cast/destructuring-assignent-rest-invalid/input.ts @@ -0,0 +1,5 @@ +0, { ...{} as T} = b; +[...[] as T] = b; + +0, { ...({} as T)} = b; +[...([] as T)] = b; diff --git a/packages/babel-parser/test/fixtures/typescript/cast/destructuring-assignent-rest-invalid/output.json b/packages/babel-parser/test/fixtures/typescript/cast/destructuring-assignent-rest-invalid/output.json new file mode 100644 index 000000000000..a93d662061a6 --- /dev/null +++ b/packages/babel-parser/test/fixtures/typescript/cast/destructuring-assignent-rest-invalid/output.json @@ -0,0 +1,225 @@ +{ + "type": "File", + "start":0,"end":84,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":5,"column":19,"index":84}}, + "errors": [ + "SyntaxError: Invalid rest operator's argument. (1:8)", + "SyntaxError: Invalid rest operator's argument. (2:4)", + "SyntaxError: Invalid rest operator's argument. (4:9)", + "SyntaxError: Invalid rest operator's argument. (5:5)" + ], + "program": { + "type": "Program", + "start":0,"end":84,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":5,"column":19,"index":84}}, + "sourceType": "module", + "interpreter": null, + "body": [ + { + "type": "ExpressionStatement", + "start":0,"end":21,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":1,"column":21,"index":21}}, + "expression": { + "type": "SequenceExpression", + "start":0,"end":20,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":1,"column":20,"index":20}}, + "expressions": [ + { + "type": "NumericLiteral", + "start":0,"end":1,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":1,"column":1,"index":1}}, + "extra": { + "rawValue": 0, + "raw": "0" + }, + "value": 0 + }, + { + "type": "AssignmentExpression", + "start":3,"end":20,"loc":{"start":{"line":1,"column":3,"index":3},"end":{"line":1,"column":20,"index":20}}, + "operator": "=", + "left": { + "type": "ObjectPattern", + "start":3,"end":16,"loc":{"start":{"line":1,"column":3,"index":3},"end":{"line":1,"column":16,"index":16}}, + "properties": [ + { + "type": "RestElement", + "start":5,"end":15,"loc":{"start":{"line":1,"column":5,"index":5},"end":{"line":1,"column":15,"index":15}}, + "argument": { + "type": "TSAsExpression", + "start":8,"end":15,"loc":{"start":{"line":1,"column":8,"index":8},"end":{"line":1,"column":15,"index":15}}, + "expression": { + "type": "ObjectPattern", + "start":8,"end":10,"loc":{"start":{"line":1,"column":8,"index":8},"end":{"line":1,"column":10,"index":10}}, + "properties": [] + }, + "typeAnnotation": { + "type": "TSTypeReference", + "start":14,"end":15,"loc":{"start":{"line":1,"column":14,"index":14},"end":{"line":1,"column":15,"index":15}}, + "typeName": { + "type": "Identifier", + "start":14,"end":15,"loc":{"start":{"line":1,"column":14,"index":14},"end":{"line":1,"column":15,"index":15},"identifierName":"T"}, + "name": "T" + } + } + } + } + ] + }, + "right": { + "type": "Identifier", + "start":19,"end":20,"loc":{"start":{"line":1,"column":19,"index":19},"end":{"line":1,"column":20,"index":20},"identifierName":"b"}, + "name": "b" + } + } + ] + } + }, + { + "type": "ExpressionStatement", + "start":22,"end":39,"loc":{"start":{"line":2,"column":0,"index":22},"end":{"line":2,"column":17,"index":39}}, + "expression": { + "type": "AssignmentExpression", + "start":22,"end":38,"loc":{"start":{"line":2,"column":0,"index":22},"end":{"line":2,"column":16,"index":38}}, + "operator": "=", + "left": { + "type": "ArrayPattern", + "start":22,"end":34,"loc":{"start":{"line":2,"column":0,"index":22},"end":{"line":2,"column":12,"index":34}}, + "elements": [ + { + "type": "RestElement", + "start":23,"end":33,"loc":{"start":{"line":2,"column":1,"index":23},"end":{"line":2,"column":11,"index":33}}, + "argument": { + "type": "TSAsExpression", + "start":26,"end":33,"loc":{"start":{"line":2,"column":4,"index":26},"end":{"line":2,"column":11,"index":33}}, + "expression": { + "type": "ArrayPattern", + "start":26,"end":28,"loc":{"start":{"line":2,"column":4,"index":26},"end":{"line":2,"column":6,"index":28}}, + "elements": [] + }, + "typeAnnotation": { + "type": "TSTypeReference", + "start":32,"end":33,"loc":{"start":{"line":2,"column":10,"index":32},"end":{"line":2,"column":11,"index":33}}, + "typeName": { + "type": "Identifier", + "start":32,"end":33,"loc":{"start":{"line":2,"column":10,"index":32},"end":{"line":2,"column":11,"index":33},"identifierName":"T"}, + "name": "T" + } + } + } + } + ] + }, + "right": { + "type": "Identifier", + "start":37,"end":38,"loc":{"start":{"line":2,"column":15,"index":37},"end":{"line":2,"column":16,"index":38},"identifierName":"b"}, + "name": "b" + } + } + }, + { + "type": "ExpressionStatement", + "start":41,"end":64,"loc":{"start":{"line":4,"column":0,"index":41},"end":{"line":4,"column":23,"index":64}}, + "expression": { + "type": "SequenceExpression", + "start":41,"end":63,"loc":{"start":{"line":4,"column":0,"index":41},"end":{"line":4,"column":22,"index":63}}, + "expressions": [ + { + "type": "NumericLiteral", + "start":41,"end":42,"loc":{"start":{"line":4,"column":0,"index":41},"end":{"line":4,"column":1,"index":42}}, + "extra": { + "rawValue": 0, + "raw": "0" + }, + "value": 0 + }, + { + "type": "AssignmentExpression", + "start":44,"end":63,"loc":{"start":{"line":4,"column":3,"index":44},"end":{"line":4,"column":22,"index":63}}, + "operator": "=", + "left": { + "type": "ObjectPattern", + "start":44,"end":59,"loc":{"start":{"line":4,"column":3,"index":44},"end":{"line":4,"column":18,"index":59}}, + "properties": [ + { + "type": "RestElement", + "start":46,"end":58,"loc":{"start":{"line":4,"column":5,"index":46},"end":{"line":4,"column":17,"index":58}}, + "argument": { + "type": "TSAsExpression", + "start":50,"end":57,"loc":{"start":{"line":4,"column":9,"index":50},"end":{"line":4,"column":16,"index":57}}, + "expression": { + "type": "ObjectPattern", + "start":50,"end":52,"loc":{"start":{"line":4,"column":9,"index":50},"end":{"line":4,"column":11,"index":52}}, + "properties": [] + }, + "typeAnnotation": { + "type": "TSTypeReference", + "start":56,"end":57,"loc":{"start":{"line":4,"column":15,"index":56},"end":{"line":4,"column":16,"index":57}}, + "typeName": { + "type": "Identifier", + "start":56,"end":57,"loc":{"start":{"line":4,"column":15,"index":56},"end":{"line":4,"column":16,"index":57},"identifierName":"T"}, + "name": "T" + } + }, + "extra": { + "parenthesized": true, + "parenStart": 49 + } + } + } + ] + }, + "right": { + "type": "Identifier", + "start":62,"end":63,"loc":{"start":{"line":4,"column":21,"index":62},"end":{"line":4,"column":22,"index":63},"identifierName":"b"}, + "name": "b" + } + } + ] + } + }, + { + "type": "ExpressionStatement", + "start":65,"end":84,"loc":{"start":{"line":5,"column":0,"index":65},"end":{"line":5,"column":19,"index":84}}, + "expression": { + "type": "AssignmentExpression", + "start":65,"end":83,"loc":{"start":{"line":5,"column":0,"index":65},"end":{"line":5,"column":18,"index":83}}, + "operator": "=", + "left": { + "type": "ArrayPattern", + "start":65,"end":79,"loc":{"start":{"line":5,"column":0,"index":65},"end":{"line":5,"column":14,"index":79}}, + "elements": [ + { + "type": "RestElement", + "start":66,"end":78,"loc":{"start":{"line":5,"column":1,"index":66},"end":{"line":5,"column":13,"index":78}}, + "argument": { + "type": "TSAsExpression", + "start":70,"end":77,"loc":{"start":{"line":5,"column":5,"index":70},"end":{"line":5,"column":12,"index":77}}, + "expression": { + "type": "ArrayPattern", + "start":70,"end":72,"loc":{"start":{"line":5,"column":5,"index":70},"end":{"line":5,"column":7,"index":72}}, + "elements": [] + }, + "typeAnnotation": { + "type": "TSTypeReference", + "start":76,"end":77,"loc":{"start":{"line":5,"column":11,"index":76},"end":{"line":5,"column":12,"index":77}}, + "typeName": { + "type": "Identifier", + "start":76,"end":77,"loc":{"start":{"line":5,"column":11,"index":76},"end":{"line":5,"column":12,"index":77},"identifierName":"T"}, + "name": "T" + } + }, + "extra": { + "parenthesized": true, + "parenStart": 69 + } + } + } + ] + }, + "right": { + "type": "Identifier", + "start":82,"end":83,"loc":{"start":{"line":5,"column":17,"index":82},"end":{"line":5,"column":18,"index":83},"identifierName":"b"}, + "name": "b" + } + } + } + ], + "directives": [] + } +} diff --git a/packages/babel-parser/test/fixtures/typescript/cast/destructuring-assignment-in-parens/input.ts b/packages/babel-parser/test/fixtures/typescript/cast/destructuring-assignment-in-parens/input.ts new file mode 100644 index 000000000000..bd87610286b3 --- /dev/null +++ b/packages/babel-parser/test/fixtures/typescript/cast/destructuring-assignment-in-parens/input.ts @@ -0,0 +1,7 @@ +({a: x as T} = b); +([a as T] = b); +({a: (x as T) = c} = b); +([(a as T) = c] = b); +({ ...a as T} = b); +([...a as T] = b); +({...x!} = y); diff --git a/packages/babel-parser/test/fixtures/typescript/cast/destructuring-assignment-in-parens/output.json b/packages/babel-parser/test/fixtures/typescript/cast/destructuring-assignment-in-parens/output.json new file mode 100644 index 000000000000..f9dadd8a6fa6 --- /dev/null +++ b/packages/babel-parser/test/fixtures/typescript/cast/destructuring-assignment-in-parens/output.json @@ -0,0 +1,360 @@ +{ + "type": "File", + "start":0,"end":135,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":7,"column":14,"index":135}}, + "program": { + "type": "Program", + "start":0,"end":135,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":7,"column":14,"index":135}}, + "sourceType": "module", + "interpreter": null, + "body": [ + { + "type": "ExpressionStatement", + "start":0,"end":18,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":1,"column":18,"index":18}}, + "expression": { + "type": "AssignmentExpression", + "start":1,"end":16,"loc":{"start":{"line":1,"column":1,"index":1},"end":{"line":1,"column":16,"index":16}}, + "operator": "=", + "left": { + "type": "ObjectPattern", + "start":1,"end":12,"loc":{"start":{"line":1,"column":1,"index":1},"end":{"line":1,"column":12,"index":12}}, + "properties": [ + { + "type": "ObjectProperty", + "start":2,"end":11,"loc":{"start":{"line":1,"column":2,"index":2},"end":{"line":1,"column":11,"index":11}}, + "method": false, + "key": { + "type": "Identifier", + "start":2,"end":3,"loc":{"start":{"line":1,"column":2,"index":2},"end":{"line":1,"column":3,"index":3},"identifierName":"a"}, + "name": "a" + }, + "computed": false, + "shorthand": false, + "value": { + "type": "TSAsExpression", + "start":5,"end":11,"loc":{"start":{"line":1,"column":5,"index":5},"end":{"line":1,"column":11,"index":11}}, + "expression": { + "type": "Identifier", + "start":5,"end":6,"loc":{"start":{"line":1,"column":5,"index":5},"end":{"line":1,"column":6,"index":6},"identifierName":"x"}, + "name": "x" + }, + "typeAnnotation": { + "type": "TSTypeReference", + "start":10,"end":11,"loc":{"start":{"line":1,"column":10,"index":10},"end":{"line":1,"column":11,"index":11}}, + "typeName": { + "type": "Identifier", + "start":10,"end":11,"loc":{"start":{"line":1,"column":10,"index":10},"end":{"line":1,"column":11,"index":11},"identifierName":"T"}, + "name": "T" + } + } + } + } + ] + }, + "right": { + "type": "Identifier", + "start":15,"end":16,"loc":{"start":{"line":1,"column":15,"index":15},"end":{"line":1,"column":16,"index":16},"identifierName":"b"}, + "name": "b" + }, + "extra": { + "parenthesized": true, + "parenStart": 0 + } + } + }, + { + "type": "ExpressionStatement", + "start":19,"end":34,"loc":{"start":{"line":2,"column":0,"index":19},"end":{"line":2,"column":15,"index":34}}, + "expression": { + "type": "AssignmentExpression", + "start":20,"end":32,"loc":{"start":{"line":2,"column":1,"index":20},"end":{"line":2,"column":13,"index":32}}, + "operator": "=", + "left": { + "type": "ArrayPattern", + "start":20,"end":28,"loc":{"start":{"line":2,"column":1,"index":20},"end":{"line":2,"column":9,"index":28}}, + "elements": [ + { + "type": "TSAsExpression", + "start":21,"end":27,"loc":{"start":{"line":2,"column":2,"index":21},"end":{"line":2,"column":8,"index":27}}, + "expression": { + "type": "Identifier", + "start":21,"end":22,"loc":{"start":{"line":2,"column":2,"index":21},"end":{"line":2,"column":3,"index":22},"identifierName":"a"}, + "name": "a" + }, + "typeAnnotation": { + "type": "TSTypeReference", + "start":26,"end":27,"loc":{"start":{"line":2,"column":7,"index":26},"end":{"line":2,"column":8,"index":27}}, + "typeName": { + "type": "Identifier", + "start":26,"end":27,"loc":{"start":{"line":2,"column":7,"index":26},"end":{"line":2,"column":8,"index":27},"identifierName":"T"}, + "name": "T" + } + } + } + ] + }, + "right": { + "type": "Identifier", + "start":31,"end":32,"loc":{"start":{"line":2,"column":12,"index":31},"end":{"line":2,"column":13,"index":32},"identifierName":"b"}, + "name": "b" + }, + "extra": { + "parenthesized": true, + "parenStart": 19 + } + } + }, + { + "type": "ExpressionStatement", + "start":35,"end":59,"loc":{"start":{"line":3,"column":0,"index":35},"end":{"line":3,"column":24,"index":59}}, + "expression": { + "type": "AssignmentExpression", + "start":36,"end":57,"loc":{"start":{"line":3,"column":1,"index":36},"end":{"line":3,"column":22,"index":57}}, + "operator": "=", + "left": { + "type": "ObjectPattern", + "start":36,"end":53,"loc":{"start":{"line":3,"column":1,"index":36},"end":{"line":3,"column":18,"index":53}}, + "properties": [ + { + "type": "ObjectProperty", + "start":37,"end":52,"loc":{"start":{"line":3,"column":2,"index":37},"end":{"line":3,"column":17,"index":52}}, + "method": false, + "key": { + "type": "Identifier", + "start":37,"end":38,"loc":{"start":{"line":3,"column":2,"index":37},"end":{"line":3,"column":3,"index":38},"identifierName":"a"}, + "name": "a" + }, + "computed": false, + "shorthand": false, + "value": { + "type": "AssignmentPattern", + "start":40,"end":52,"loc":{"start":{"line":3,"column":5,"index":40},"end":{"line":3,"column":17,"index":52}}, + "left": { + "type": "TSAsExpression", + "start":41,"end":47,"loc":{"start":{"line":3,"column":6,"index":41},"end":{"line":3,"column":12,"index":47}}, + "expression": { + "type": "Identifier", + "start":41,"end":42,"loc":{"start":{"line":3,"column":6,"index":41},"end":{"line":3,"column":7,"index":42},"identifierName":"x"}, + "name": "x" + }, + "typeAnnotation": { + "type": "TSTypeReference", + "start":46,"end":47,"loc":{"start":{"line":3,"column":11,"index":46},"end":{"line":3,"column":12,"index":47}}, + "typeName": { + "type": "Identifier", + "start":46,"end":47,"loc":{"start":{"line":3,"column":11,"index":46},"end":{"line":3,"column":12,"index":47},"identifierName":"T"}, + "name": "T" + } + }, + "extra": { + "parenthesized": true, + "parenStart": 40 + } + }, + "right": { + "type": "Identifier", + "start":51,"end":52,"loc":{"start":{"line":3,"column":16,"index":51},"end":{"line":3,"column":17,"index":52},"identifierName":"c"}, + "name": "c" + } + } + } + ] + }, + "right": { + "type": "Identifier", + "start":56,"end":57,"loc":{"start":{"line":3,"column":21,"index":56},"end":{"line":3,"column":22,"index":57},"identifierName":"b"}, + "name": "b" + }, + "extra": { + "parenthesized": true, + "parenStart": 35 + } + } + }, + { + "type": "ExpressionStatement", + "start":60,"end":81,"loc":{"start":{"line":4,"column":0,"index":60},"end":{"line":4,"column":21,"index":81}}, + "expression": { + "type": "AssignmentExpression", + "start":61,"end":79,"loc":{"start":{"line":4,"column":1,"index":61},"end":{"line":4,"column":19,"index":79}}, + "operator": "=", + "left": { + "type": "ArrayPattern", + "start":61,"end":75,"loc":{"start":{"line":4,"column":1,"index":61},"end":{"line":4,"column":15,"index":75}}, + "elements": [ + { + "type": "AssignmentPattern", + "start":62,"end":74,"loc":{"start":{"line":4,"column":2,"index":62},"end":{"line":4,"column":14,"index":74}}, + "left": { + "type": "TSAsExpression", + "start":63,"end":69,"loc":{"start":{"line":4,"column":3,"index":63},"end":{"line":4,"column":9,"index":69}}, + "expression": { + "type": "Identifier", + "start":63,"end":64,"loc":{"start":{"line":4,"column":3,"index":63},"end":{"line":4,"column":4,"index":64},"identifierName":"a"}, + "name": "a" + }, + "typeAnnotation": { + "type": "TSTypeReference", + "start":68,"end":69,"loc":{"start":{"line":4,"column":8,"index":68},"end":{"line":4,"column":9,"index":69}}, + "typeName": { + "type": "Identifier", + "start":68,"end":69,"loc":{"start":{"line":4,"column":8,"index":68},"end":{"line":4,"column":9,"index":69},"identifierName":"T"}, + "name": "T" + } + }, + "extra": { + "parenthesized": true, + "parenStart": 62 + } + }, + "right": { + "type": "Identifier", + "start":73,"end":74,"loc":{"start":{"line":4,"column":13,"index":73},"end":{"line":4,"column":14,"index":74},"identifierName":"c"}, + "name": "c" + } + } + ] + }, + "right": { + "type": "Identifier", + "start":78,"end":79,"loc":{"start":{"line":4,"column":18,"index":78},"end":{"line":4,"column":19,"index":79},"identifierName":"b"}, + "name": "b" + }, + "extra": { + "parenthesized": true, + "parenStart": 60 + } + } + }, + { + "type": "ExpressionStatement", + "start":82,"end":101,"loc":{"start":{"line":5,"column":0,"index":82},"end":{"line":5,"column":19,"index":101}}, + "expression": { + "type": "AssignmentExpression", + "start":83,"end":99,"loc":{"start":{"line":5,"column":1,"index":83},"end":{"line":5,"column":17,"index":99}}, + "operator": "=", + "left": { + "type": "ObjectPattern", + "start":83,"end":95,"loc":{"start":{"line":5,"column":1,"index":83},"end":{"line":5,"column":13,"index":95}}, + "properties": [ + { + "type": "RestElement", + "start":85,"end":94,"loc":{"start":{"line":5,"column":3,"index":85},"end":{"line":5,"column":12,"index":94}}, + "argument": { + "type": "TSAsExpression", + "start":88,"end":94,"loc":{"start":{"line":5,"column":6,"index":88},"end":{"line":5,"column":12,"index":94}}, + "expression": { + "type": "Identifier", + "start":88,"end":89,"loc":{"start":{"line":5,"column":6,"index":88},"end":{"line":5,"column":7,"index":89},"identifierName":"a"}, + "name": "a" + }, + "typeAnnotation": { + "type": "TSTypeReference", + "start":93,"end":94,"loc":{"start":{"line":5,"column":11,"index":93},"end":{"line":5,"column":12,"index":94}}, + "typeName": { + "type": "Identifier", + "start":93,"end":94,"loc":{"start":{"line":5,"column":11,"index":93},"end":{"line":5,"column":12,"index":94},"identifierName":"T"}, + "name": "T" + } + } + } + } + ] + }, + "right": { + "type": "Identifier", + "start":98,"end":99,"loc":{"start":{"line":5,"column":16,"index":98},"end":{"line":5,"column":17,"index":99},"identifierName":"b"}, + "name": "b" + }, + "extra": { + "parenthesized": true, + "parenStart": 82 + } + } + }, + { + "type": "ExpressionStatement", + "start":102,"end":120,"loc":{"start":{"line":6,"column":0,"index":102},"end":{"line":6,"column":18,"index":120}}, + "expression": { + "type": "AssignmentExpression", + "start":103,"end":118,"loc":{"start":{"line":6,"column":1,"index":103},"end":{"line":6,"column":16,"index":118}}, + "operator": "=", + "left": { + "type": "ArrayPattern", + "start":103,"end":114,"loc":{"start":{"line":6,"column":1,"index":103},"end":{"line":6,"column":12,"index":114}}, + "elements": [ + { + "type": "RestElement", + "start":104,"end":113,"loc":{"start":{"line":6,"column":2,"index":104},"end":{"line":6,"column":11,"index":113}}, + "argument": { + "type": "TSAsExpression", + "start":107,"end":113,"loc":{"start":{"line":6,"column":5,"index":107},"end":{"line":6,"column":11,"index":113}}, + "expression": { + "type": "Identifier", + "start":107,"end":108,"loc":{"start":{"line":6,"column":5,"index":107},"end":{"line":6,"column":6,"index":108},"identifierName":"a"}, + "name": "a" + }, + "typeAnnotation": { + "type": "TSTypeReference", + "start":112,"end":113,"loc":{"start":{"line":6,"column":10,"index":112},"end":{"line":6,"column":11,"index":113}}, + "typeName": { + "type": "Identifier", + "start":112,"end":113,"loc":{"start":{"line":6,"column":10,"index":112},"end":{"line":6,"column":11,"index":113},"identifierName":"T"}, + "name": "T" + } + } + } + } + ] + }, + "right": { + "type": "Identifier", + "start":117,"end":118,"loc":{"start":{"line":6,"column":15,"index":117},"end":{"line":6,"column":16,"index":118},"identifierName":"b"}, + "name": "b" + }, + "extra": { + "parenthesized": true, + "parenStart": 102 + } + } + }, + { + "type": "ExpressionStatement", + "start":121,"end":135,"loc":{"start":{"line":7,"column":0,"index":121},"end":{"line":7,"column":14,"index":135}}, + "expression": { + "type": "AssignmentExpression", + "start":122,"end":133,"loc":{"start":{"line":7,"column":1,"index":122},"end":{"line":7,"column":12,"index":133}}, + "operator": "=", + "left": { + "type": "ObjectPattern", + "start":122,"end":129,"loc":{"start":{"line":7,"column":1,"index":122},"end":{"line":7,"column":8,"index":129}}, + "properties": [ + { + "type": "RestElement", + "start":123,"end":128,"loc":{"start":{"line":7,"column":2,"index":123},"end":{"line":7,"column":7,"index":128}}, + "argument": { + "type": "TSNonNullExpression", + "start":126,"end":128,"loc":{"start":{"line":7,"column":5,"index":126},"end":{"line":7,"column":7,"index":128}}, + "expression": { + "type": "Identifier", + "start":126,"end":127,"loc":{"start":{"line":7,"column":5,"index":126},"end":{"line":7,"column":6,"index":127},"identifierName":"x"}, + "name": "x" + } + } + } + ] + }, + "right": { + "type": "Identifier", + "start":132,"end":133,"loc":{"start":{"line":7,"column":11,"index":132},"end":{"line":7,"column":12,"index":133},"identifierName":"y"}, + "name": "y" + }, + "extra": { + "parenthesized": true, + "parenStart": 121 + } + } + } + ], + "directives": [] + } +} diff --git a/packages/babel-parser/test/fixtures/typescript/cast/for-of-lhs/input.ts b/packages/babel-parser/test/fixtures/typescript/cast/for-of-lhs/input.ts new file mode 100644 index 000000000000..63549667801a --- /dev/null +++ b/packages/babel-parser/test/fixtures/typescript/cast/for-of-lhs/input.ts @@ -0,0 +1,2 @@ +for (a as T of []); +for ( a of []); diff --git a/packages/babel-parser/test/fixtures/typescript/cast/for-of-lhs/output.json b/packages/babel-parser/test/fixtures/typescript/cast/for-of-lhs/output.json new file mode 100644 index 000000000000..53ca699d54c9 --- /dev/null +++ b/packages/babel-parser/test/fixtures/typescript/cast/for-of-lhs/output.json @@ -0,0 +1,77 @@ +{ + "type": "File", + "start":0,"end":38,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":2,"column":18,"index":38}}, + "program": { + "type": "Program", + "start":0,"end":38,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":2,"column":18,"index":38}}, + "sourceType": "module", + "interpreter": null, + "body": [ + { + "type": "ForOfStatement", + "start":0,"end":19,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":1,"column":19,"index":19}}, + "await": false, + "left": { + "type": "TSAsExpression", + "start":5,"end":11,"loc":{"start":{"line":1,"column":5,"index":5},"end":{"line":1,"column":11,"index":11}}, + "expression": { + "type": "Identifier", + "start":5,"end":6,"loc":{"start":{"line":1,"column":5,"index":5},"end":{"line":1,"column":6,"index":6},"identifierName":"a"}, + "name": "a" + }, + "typeAnnotation": { + "type": "TSTypeReference", + "start":10,"end":11,"loc":{"start":{"line":1,"column":10,"index":10},"end":{"line":1,"column":11,"index":11}}, + "typeName": { + "type": "Identifier", + "start":10,"end":11,"loc":{"start":{"line":1,"column":10,"index":10},"end":{"line":1,"column":11,"index":11},"identifierName":"T"}, + "name": "T" + } + } + }, + "right": { + "type": "ArrayExpression", + "start":15,"end":17,"loc":{"start":{"line":1,"column":15,"index":15},"end":{"line":1,"column":17,"index":17}}, + "elements": [] + }, + "body": { + "type": "EmptyStatement", + "start":18,"end":19,"loc":{"start":{"line":1,"column":18,"index":18},"end":{"line":1,"column":19,"index":19}} + } + }, + { + "type": "ForOfStatement", + "start":20,"end":38,"loc":{"start":{"line":2,"column":0,"index":20},"end":{"line":2,"column":18,"index":38}}, + "await": false, + "left": { + "type": "TSTypeAssertion", + "start":25,"end":30,"loc":{"start":{"line":2,"column":5,"index":25},"end":{"line":2,"column":10,"index":30}}, + "typeAnnotation": { + "type": "TSTypeReference", + "start":26,"end":27,"loc":{"start":{"line":2,"column":6,"index":26},"end":{"line":2,"column":7,"index":27}}, + "typeName": { + "type": "Identifier", + "start":26,"end":27,"loc":{"start":{"line":2,"column":6,"index":26},"end":{"line":2,"column":7,"index":27},"identifierName":"T"}, + "name": "T" + } + }, + "expression": { + "type": "Identifier", + "start":29,"end":30,"loc":{"start":{"line":2,"column":9,"index":29},"end":{"line":2,"column":10,"index":30},"identifierName":"a"}, + "name": "a" + } + }, + "right": { + "type": "ArrayExpression", + "start":34,"end":36,"loc":{"start":{"line":2,"column":14,"index":34},"end":{"line":2,"column":16,"index":36}}, + "elements": [] + }, + "body": { + "type": "EmptyStatement", + "start":37,"end":38,"loc":{"start":{"line":2,"column":17,"index":37},"end":{"line":2,"column":18,"index":38}} + } + } + ], + "directives": [] + } +} diff --git a/packages/babel-parser/test/fixtures/typescript/cast/null-assertion-invalid-arrow-param/input.ts b/packages/babel-parser/test/fixtures/typescript/cast/null-assertion-invalid-arrow-param/input.ts new file mode 100644 index 000000000000..eeeabeef2584 --- /dev/null +++ b/packages/babel-parser/test/fixtures/typescript/cast/null-assertion-invalid-arrow-param/input.ts @@ -0,0 +1,6 @@ +(a!) => b; +(a! = b) => c; +([a!]) => c; +({a: a!}) => c; +([...a!]) => c; +({...a!}) => c; diff --git a/packages/babel-parser/test/fixtures/typescript/cast/null-assertion-invalid-arrow-param/output.json b/packages/babel-parser/test/fixtures/typescript/cast/null-assertion-invalid-arrow-param/output.json new file mode 100644 index 000000000000..6dd54a2f1816 --- /dev/null +++ b/packages/babel-parser/test/fixtures/typescript/cast/null-assertion-invalid-arrow-param/output.json @@ -0,0 +1,237 @@ +{ + "type": "File", + "start":0,"end":86,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":6,"column":15,"index":86}}, + "errors": [ + "SyntaxError: Unexpected type cast in parameter position. (1:1)", + "SyntaxError: Unexpected type cast in parameter position. (2:1)", + "SyntaxError: Unexpected type cast in parameter position. (2:1)", + "SyntaxError: Unexpected type cast in parameter position. (3:2)", + "SyntaxError: Unexpected type cast in parameter position. (4:5)", + "SyntaxError: Unexpected type cast in parameter position. (5:5)", + "SyntaxError: Unexpected type cast in parameter position. (6:5)" + ], + "program": { + "type": "Program", + "start":0,"end":86,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":6,"column":15,"index":86}}, + "sourceType": "module", + "interpreter": null, + "body": [ + { + "type": "ExpressionStatement", + "start":0,"end":10,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":1,"column":10,"index":10}}, + "expression": { + "type": "ArrowFunctionExpression", + "start":0,"end":9,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":1,"column":9,"index":9}}, + "id": null, + "generator": false, + "async": false, + "params": [ + { + "type": "TSNonNullExpression", + "start":1,"end":3,"loc":{"start":{"line":1,"column":1,"index":1},"end":{"line":1,"column":3,"index":3}}, + "expression": { + "type": "Identifier", + "start":1,"end":2,"loc":{"start":{"line":1,"column":1,"index":1},"end":{"line":1,"column":2,"index":2},"identifierName":"a"}, + "name": "a" + } + } + ], + "body": { + "type": "Identifier", + "start":8,"end":9,"loc":{"start":{"line":1,"column":8,"index":8},"end":{"line":1,"column":9,"index":9},"identifierName":"b"}, + "name": "b" + } + } + }, + { + "type": "ExpressionStatement", + "start":11,"end":25,"loc":{"start":{"line":2,"column":0,"index":11},"end":{"line":2,"column":14,"index":25}}, + "expression": { + "type": "ArrowFunctionExpression", + "start":11,"end":24,"loc":{"start":{"line":2,"column":0,"index":11},"end":{"line":2,"column":13,"index":24}}, + "id": null, + "generator": false, + "async": false, + "params": [ + { + "type": "AssignmentPattern", + "start":12,"end":18,"loc":{"start":{"line":2,"column":1,"index":12},"end":{"line":2,"column":7,"index":18}}, + "left": { + "type": "TSNonNullExpression", + "start":12,"end":14,"loc":{"start":{"line":2,"column":1,"index":12},"end":{"line":2,"column":3,"index":14}}, + "expression": { + "type": "Identifier", + "start":12,"end":13,"loc":{"start":{"line":2,"column":1,"index":12},"end":{"line":2,"column":2,"index":13},"identifierName":"a"}, + "name": "a" + } + }, + "right": { + "type": "Identifier", + "start":17,"end":18,"loc":{"start":{"line":2,"column":6,"index":17},"end":{"line":2,"column":7,"index":18},"identifierName":"b"}, + "name": "b" + } + } + ], + "body": { + "type": "Identifier", + "start":23,"end":24,"loc":{"start":{"line":2,"column":12,"index":23},"end":{"line":2,"column":13,"index":24},"identifierName":"c"}, + "name": "c" + } + } + }, + { + "type": "ExpressionStatement", + "start":26,"end":38,"loc":{"start":{"line":3,"column":0,"index":26},"end":{"line":3,"column":12,"index":38}}, + "expression": { + "type": "ArrowFunctionExpression", + "start":26,"end":37,"loc":{"start":{"line":3,"column":0,"index":26},"end":{"line":3,"column":11,"index":37}}, + "id": null, + "generator": false, + "async": false, + "params": [ + { + "type": "ArrayPattern", + "start":27,"end":31,"loc":{"start":{"line":3,"column":1,"index":27},"end":{"line":3,"column":5,"index":31}}, + "elements": [ + { + "type": "TSNonNullExpression", + "start":28,"end":30,"loc":{"start":{"line":3,"column":2,"index":28},"end":{"line":3,"column":4,"index":30}}, + "expression": { + "type": "Identifier", + "start":28,"end":29,"loc":{"start":{"line":3,"column":2,"index":28},"end":{"line":3,"column":3,"index":29},"identifierName":"a"}, + "name": "a" + } + } + ] + } + ], + "body": { + "type": "Identifier", + "start":36,"end":37,"loc":{"start":{"line":3,"column":10,"index":36},"end":{"line":3,"column":11,"index":37},"identifierName":"c"}, + "name": "c" + } + } + }, + { + "type": "ExpressionStatement", + "start":39,"end":54,"loc":{"start":{"line":4,"column":0,"index":39},"end":{"line":4,"column":15,"index":54}}, + "expression": { + "type": "ArrowFunctionExpression", + "start":39,"end":53,"loc":{"start":{"line":4,"column":0,"index":39},"end":{"line":4,"column":14,"index":53}}, + "id": null, + "generator": false, + "async": false, + "params": [ + { + "type": "ObjectPattern", + "start":40,"end":47,"loc":{"start":{"line":4,"column":1,"index":40},"end":{"line":4,"column":8,"index":47}}, + "properties": [ + { + "type": "ObjectProperty", + "start":41,"end":46,"loc":{"start":{"line":4,"column":2,"index":41},"end":{"line":4,"column":7,"index":46}}, + "method": false, + "key": { + "type": "Identifier", + "start":41,"end":42,"loc":{"start":{"line":4,"column":2,"index":41},"end":{"line":4,"column":3,"index":42},"identifierName":"a"}, + "name": "a" + }, + "computed": false, + "shorthand": false, + "value": { + "type": "TSNonNullExpression", + "start":44,"end":46,"loc":{"start":{"line":4,"column":5,"index":44},"end":{"line":4,"column":7,"index":46}}, + "expression": { + "type": "Identifier", + "start":44,"end":45,"loc":{"start":{"line":4,"column":5,"index":44},"end":{"line":4,"column":6,"index":45},"identifierName":"a"}, + "name": "a" + } + } + } + ] + } + ], + "body": { + "type": "Identifier", + "start":52,"end":53,"loc":{"start":{"line":4,"column":13,"index":52},"end":{"line":4,"column":14,"index":53},"identifierName":"c"}, + "name": "c" + } + } + }, + { + "type": "ExpressionStatement", + "start":55,"end":70,"loc":{"start":{"line":5,"column":0,"index":55},"end":{"line":5,"column":15,"index":70}}, + "expression": { + "type": "ArrowFunctionExpression", + "start":55,"end":69,"loc":{"start":{"line":5,"column":0,"index":55},"end":{"line":5,"column":14,"index":69}}, + "id": null, + "generator": false, + "async": false, + "params": [ + { + "type": "ArrayPattern", + "start":56,"end":63,"loc":{"start":{"line":5,"column":1,"index":56},"end":{"line":5,"column":8,"index":63}}, + "elements": [ + { + "type": "RestElement", + "start":57,"end":62,"loc":{"start":{"line":5,"column":2,"index":57},"end":{"line":5,"column":7,"index":62}}, + "argument": { + "type": "TSNonNullExpression", + "start":60,"end":62,"loc":{"start":{"line":5,"column":5,"index":60},"end":{"line":5,"column":7,"index":62}}, + "expression": { + "type": "Identifier", + "start":60,"end":61,"loc":{"start":{"line":5,"column":5,"index":60},"end":{"line":5,"column":6,"index":61},"identifierName":"a"}, + "name": "a" + } + } + } + ] + } + ], + "body": { + "type": "Identifier", + "start":68,"end":69,"loc":{"start":{"line":5,"column":13,"index":68},"end":{"line":5,"column":14,"index":69},"identifierName":"c"}, + "name": "c" + } + } + }, + { + "type": "ExpressionStatement", + "start":71,"end":86,"loc":{"start":{"line":6,"column":0,"index":71},"end":{"line":6,"column":15,"index":86}}, + "expression": { + "type": "ArrowFunctionExpression", + "start":71,"end":85,"loc":{"start":{"line":6,"column":0,"index":71},"end":{"line":6,"column":14,"index":85}}, + "id": null, + "generator": false, + "async": false, + "params": [ + { + "type": "ObjectPattern", + "start":72,"end":79,"loc":{"start":{"line":6,"column":1,"index":72},"end":{"line":6,"column":8,"index":79}}, + "properties": [ + { + "type": "RestElement", + "start":73,"end":78,"loc":{"start":{"line":6,"column":2,"index":73},"end":{"line":6,"column":7,"index":78}}, + "argument": { + "type": "TSNonNullExpression", + "start":76,"end":78,"loc":{"start":{"line":6,"column":5,"index":76},"end":{"line":6,"column":7,"index":78}}, + "expression": { + "type": "Identifier", + "start":76,"end":77,"loc":{"start":{"line":6,"column":5,"index":76},"end":{"line":6,"column":6,"index":77},"identifierName":"a"}, + "name": "a" + } + } + } + ] + } + ], + "body": { + "type": "Identifier", + "start":84,"end":85,"loc":{"start":{"line":6,"column":13,"index":84},"end":{"line":6,"column":14,"index":85},"identifierName":"c"}, + "name": "c" + } + } + } + ], + "directives": [] + } +} diff --git a/packages/babel-parser/test/fixtures/typescript/cast/unparenthesized-assert-and-assign/output.json b/packages/babel-parser/test/fixtures/typescript/cast/unparenthesized-assert-and-assign/output.json index 55b9929fc45c..27f637009e37 100644 --- a/packages/babel-parser/test/fixtures/typescript/cast/unparenthesized-assert-and-assign/output.json +++ b/packages/babel-parser/test/fixtures/typescript/cast/unparenthesized-assert-and-assign/output.json @@ -3,8 +3,7 @@ "start":0,"end":46,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":2,"column":29,"index":46}}, "errors": [ "SyntaxError: Invalid left-hand side in assignment expression. (1:0)", - "SyntaxError: Invalid left-hand side in assignment expression. (2:6)", - "SyntaxError: Invalid left-hand side in object destructuring pattern. (2:6)" + "SyntaxError: Invalid left-hand side in assignment expression. (2:6)" ], "program": { "type": "Program", diff --git a/packages/babel-plugin-transform-destructuring/src/util.ts b/packages/babel-plugin-transform-destructuring/src/util.ts index 93e31e887493..a3fc29f1f041 100644 --- a/packages/babel-plugin-transform-destructuring/src/util.ts +++ b/packages/babel-plugin-transform-destructuring/src/util.ts @@ -101,11 +101,7 @@ export class DestructuringTransformer { } buildVariableAssignment( - id: - | t.Identifier - | t.MemberExpression - | t.RestElement - | t.TSParameterProperty, + id: t.AssignmentExpression["left"], init: t.Expression, ) { let op = this.operator; @@ -238,7 +234,6 @@ export class DestructuringTransformer { this.objectRestNoSymbols, this.useBuiltIns, ); - // @ts-expect-error: The argument of a RestElement in ObjectPattern must not be an ArrayPattern this.nodes.push(this.buildVariableAssignment(spreadProp.argument, value)); } diff --git a/packages/babel-types/src/ast-types/generated/index.ts b/packages/babel-types/src/ast-types/generated/index.ts index 919a581737ff..c29254a26672 100644 --- a/packages/babel-types/src/ast-types/generated/index.ts +++ b/packages/babel-types/src/ast-types/generated/index.ts @@ -703,7 +703,14 @@ export interface WithStatement extends BaseNode { export interface AssignmentPattern extends BaseNode { type: "AssignmentPattern"; - left: Identifier | ObjectPattern | ArrayPattern | MemberExpression; + left: + | Identifier + | ObjectPattern + | ArrayPattern + | MemberExpression + | TSAsExpression + | TSTypeAssertion + | TSNonNullExpression; right: Expression; decorators?: Array | null; typeAnnotation?: TypeAnnotation | TSTypeAnnotation | Noop | null; @@ -2346,7 +2353,10 @@ export type PatternLike = | RestElement | AssignmentPattern | ArrayPattern - | ObjectPattern; + | ObjectPattern + | TSAsExpression + | TSTypeAssertion + | TSNonNullExpression; export type LVal = | Identifier | MemberExpression @@ -2354,7 +2364,10 @@ export type LVal = | AssignmentPattern | ArrayPattern | ObjectPattern - | TSParameterProperty; + | TSParameterProperty + | TSAsExpression + | TSTypeAssertion + | TSNonNullExpression; export type TSEntityName = Identifier | TSQualifiedName; export type Literal = | StringLiteral diff --git a/packages/babel-types/src/builders/generated/index.ts b/packages/babel-types/src/builders/generated/index.ts index ae8a309fb83d..e0573e9d6bf2 100644 --- a/packages/babel-types/src/builders/generated/index.ts +++ b/packages/babel-types/src/builders/generated/index.ts @@ -322,7 +322,14 @@ export function withStatement( return builder.apply("WithStatement", arguments); } export function assignmentPattern( - left: t.Identifier | t.ObjectPattern | t.ArrayPattern | t.MemberExpression, + left: + | t.Identifier + | t.ObjectPattern + | t.ArrayPattern + | t.MemberExpression + | t.TSAsExpression + | t.TSTypeAssertion + | t.TSNonNullExpression, right: t.Expression, ): t.AssignmentPattern { return builder.apply("AssignmentPattern", arguments); diff --git a/packages/babel-types/src/definitions/core.ts b/packages/babel-types/src/definitions/core.ts index 49e1768571a2..a660422bd172 100644 --- a/packages/babel-types/src/definitions/core.ts +++ b/packages/babel-types/src/definitions/core.ts @@ -66,6 +66,9 @@ defineType("AssignmentExpression", { "MemberExpression", "ArrayPattern", "ObjectPattern", + "TSAsExpression", + "TSTypeAssertion", + "TSNonNullExpression", ), }, right: { @@ -319,6 +322,9 @@ defineType("ForInStatement", { "MemberExpression", "ArrayPattern", "ObjectPattern", + "TSAsExpression", + "TSTypeAssertion", + "TSNonNullExpression", ), }, right: { @@ -887,7 +893,13 @@ defineType("ObjectProperty", { visitor: ["key", "value", "decorators"], aliases: ["UserWhitespacable", "Property", "ObjectMember"], validate: (function () { - const pattern = assertNodeType("Identifier", "Pattern"); + const pattern = assertNodeType( + "Identifier", + "Pattern", + "TSAsExpression", + "TSNonNullExpression", + "TSTypeAssertion", + ); const expression = assertNodeType("Expression"); return function (parent, key, node) { @@ -914,6 +926,9 @@ defineType("RestElement", { "ArrayPattern", "ObjectPattern", "MemberExpression", + "TSAsExpression", + "TSTypeAssertion", + "TSNonNullExpression", ), }, // For Flow @@ -1191,6 +1206,9 @@ defineType("AssignmentPattern", { "ObjectPattern", "ArrayPattern", "MemberExpression", + "TSAsExpression", + "TSTypeAssertion", + "TSNonNullExpression", ), }, right: { @@ -1595,6 +1613,9 @@ defineType("ForOfStatement", { "MemberExpression", "ArrayPattern", "ObjectPattern", + "TSAsExpression", + "TSTypeAssertion", + "TSNonNullExpression", ); return function (node, key, val) { diff --git a/packages/babel-types/src/definitions/typescript.ts b/packages/babel-types/src/definitions/typescript.ts index 42dcf6accd24..f060162f6de5 100644 --- a/packages/babel-types/src/definitions/typescript.ts +++ b/packages/babel-types/src/definitions/typescript.ts @@ -450,7 +450,7 @@ defineType("TSTypeAliasDeclaration", { }); defineType("TSAsExpression", { - aliases: ["Expression"], + aliases: ["Expression", "LVal", "PatternLike"], visitor: ["expression", "typeAnnotation"], fields: { expression: validateType("Expression"), @@ -459,7 +459,7 @@ defineType("TSAsExpression", { }); defineType("TSTypeAssertion", { - aliases: ["Expression"], + aliases: ["Expression", "LVal", "PatternLike"], visitor: ["typeAnnotation", "expression"], fields: { typeAnnotation: validateType("TSType"), @@ -542,7 +542,7 @@ defineType("TSExternalModuleReference", { }); defineType("TSNonNullExpression", { - aliases: ["Expression"], + aliases: ["Expression", "LVal", "PatternLike"], visitor: ["expression"], fields: { expression: validateType("Expression"), diff --git a/packages/babel-types/src/validators/generated/index.ts b/packages/babel-types/src/validators/generated/index.ts index c9ad115da496..4a0ca65165dc 100644 --- a/packages/babel-types/src/validators/generated/index.ts +++ b/packages/babel-types/src/validators/generated/index.ts @@ -4870,6 +4870,9 @@ export function isPatternLike( "AssignmentPattern" === nodeType || "ArrayPattern" === nodeType || "ObjectPattern" === nodeType || + "TSAsExpression" === nodeType || + "TSTypeAssertion" === nodeType || + "TSNonNullExpression" === nodeType || (nodeType === "Placeholder" && ("Pattern" === (node as t.Placeholder).expectedNode || "Identifier" === (node as t.Placeholder).expectedNode)) @@ -4898,6 +4901,9 @@ export function isLVal( "ArrayPattern" === nodeType || "ObjectPattern" === nodeType || "TSParameterProperty" === nodeType || + "TSAsExpression" === nodeType || + "TSTypeAssertion" === nodeType || + "TSNonNullExpression" === nodeType || (nodeType === "Placeholder" && ("Pattern" === (node as t.Placeholder).expectedNode || "Identifier" === (node as t.Placeholder).expectedNode)) diff --git a/packages/babel-types/test/validate.js b/packages/babel-types/test/validate.js new file mode 100644 index 000000000000..1786f487f560 --- /dev/null +++ b/packages/babel-types/test/validate.js @@ -0,0 +1,30 @@ +import * as t from "../lib/index.js"; + +describe("validate", () => { + describe("TS", () => { + const id1 = t.identifier("foo"); + const id2 = t.identifier("bar"); + const lhs = [ + t.tsAsExpression(id1, t.tsAnyKeyword()), + t.tsTypeAssertion(t.tsAnyKeyword(), id1), + t.tsNonNullExpression(id1), + ]; + const validNodes = { + "AssignmentExpression(=)": lhs => t.assignmentExpression("=", lhs, id2), + "AssignmentExpression(+=)": lhs => t.assignmentExpression("+=", lhs, id2), + ForOfStatement: lhs => t.forOfStatement(lhs, id2, t.emptyStatement()), + ForInStatement: lhs => t.forInStatement(lhs, id2, t.emptyStatement()), + "ObjectPattern > ObjectProperty": lhs => + t.objectPattern([t.objectProperty(t.stringLiteral("x"), lhs)]), + ArrayPattern: lhs => t.arrayPattern([lhs]), + AssignmentPattern: lhs => t.assignmentPattern(lhs, id2), + }; + Object.keys(validNodes).forEach(name => { + lhs.forEach(lhs => { + it(`${lhs.type} is allowed in ${name}`, () => { + expect(() => t.validate(validNodes[name](lhs))).not.toThrow(); + }); + }); + }); + }); +});