diff --git a/packages/babel-parser/src/parser/expression.ts b/packages/babel-parser/src/parser/expression.ts index ff10ce7374fc..49f3eb5aa98a 100644 --- a/packages/babel-parser/src/parser/expression.ts +++ b/packages/babel-parser/src/parser/expression.ts @@ -95,10 +95,7 @@ export default abstract class ExpressionParser extends LValParser { allowExpressionBody?: boolean, isAsync?: boolean, ): T; - abstract parseFunctionParams( - node: N.Function, - allowModifiers?: boolean, - ): void; + abstract parseFunctionParams(node: N.Function, isConstructor?: boolean): void; abstract parseBlockOrModuleBlockBody( body: N.Statement[], directives: N.Directive[] | null | undefined, @@ -2427,7 +2424,6 @@ export default abstract class ExpressionParser extends LValParser { ): T { this.initFunction(node, isAsync); node.generator = isGenerator; - const allowModifiers = isConstructor; // For TypeScript parameter properties this.scope.enter( SCOPE_FUNCTION | SCOPE_SUPER | @@ -2435,7 +2431,7 @@ export default abstract class ExpressionParser extends LValParser { (allowDirectSuper ? SCOPE_DIRECT_SUPER : 0), ); this.prodParam.enter(functionFlags(isAsync, node.generator)); - this.parseFunctionParams(node, allowModifiers); + this.parseFunctionParams(node, isConstructor); const finishedNode = this.parseFunctionBodyAndFinish(node, type, true); this.prodParam.exit(); this.scope.exit(); diff --git a/packages/babel-parser/src/parser/lval.ts b/packages/babel-parser/src/parser/lval.ts index d1df5f9daa88..e7e293d66d91 100644 --- a/packages/babel-parser/src/parser/lval.ts +++ b/packages/babel-parser/src/parser/lval.ts @@ -44,6 +44,12 @@ const unwrapParenthesizedExpression = (node: Node): Node => { : node; }; +export const enum ParseBindingListFlags { + ALLOW_EMPTY = 1 << 0, + IS_FUNCTION_PARAMS = 1 << 1, + IS_CONSTRUCTOR_PARAMS = 1 << 2, +} + export default abstract class LValParser extends NodeUtils { // Forward-declaration: defined in expression.js abstract parseIdentifier(liberal?: boolean): Identifier; @@ -366,7 +372,7 @@ export default abstract class LValParser extends NodeUtils { node.elements = this.parseBindingList( tt.bracketR, charCodes.rightSquareBracket, - true, + ParseBindingListFlags.ALLOW_EMPTY, ); return this.finishNode(node, "ArrayPattern"); } @@ -384,9 +390,10 @@ export default abstract class LValParser extends NodeUtils { this: Parser, close: TokenType, closeCharCode: typeof charCodes[keyof typeof charCodes], - allowEmpty?: boolean, - allowModifiers?: boolean, + flags: ParseBindingListFlags, ): Array { + const allowEmpty = flags & ParseBindingListFlags.ALLOW_EMPTY; + const elts: Array = []; let first = true; while (!this.eat(close)) { @@ -400,7 +407,9 @@ export default abstract class LValParser extends NodeUtils { } else if (this.eat(close)) { break; } else if (this.match(tt.ellipsis)) { - elts.push(this.parseAssignableListItemTypes(this.parseRestBinding())); + elts.push( + this.parseAssignableListItemTypes(this.parseRestBinding(), flags), + ); if (!this.checkCommaAfterRest(closeCharCode)) { this.expect(close); break; @@ -416,7 +425,7 @@ export default abstract class LValParser extends NodeUtils { while (this.match(tt.at)) { decorators.push(this.parseDecorator()); } - elts.push(this.parseAssignableListItem(allowModifiers, decorators)); + elts.push(this.parseAssignableListItem(flags, decorators)); } } return elts; @@ -460,11 +469,11 @@ export default abstract class LValParser extends NodeUtils { parseAssignableListItem( this: Parser, - allowModifiers: boolean | undefined | null, + flags: ParseBindingListFlags, decorators: Decorator[], ): Pattern | TSParameterProperty { const left = this.parseMaybeDefault(); - this.parseAssignableListItemTypes(left); + this.parseAssignableListItemTypes(left, flags); const elt = this.parseMaybeDefault(left.loc.start, left); if (decorators.length) { left.decorators = decorators; @@ -473,7 +482,11 @@ export default abstract class LValParser extends NodeUtils { } // Used by flow/typescript plugin to add type annotations to binding elements - parseAssignableListItemTypes(param: Pattern): Pattern { + parseAssignableListItemTypes( + param: Pattern, + // eslint-disable-next-line @typescript-eslint/no-unused-vars + flags: ParseBindingListFlags, + ): Pattern { return param; } diff --git a/packages/babel-parser/src/parser/statement.ts b/packages/babel-parser/src/parser/statement.ts index d0bbefc4c372..5a8d1a39194b 100644 --- a/packages/babel-parser/src/parser/statement.ts +++ b/packages/babel-parser/src/parser/statement.ts @@ -43,6 +43,7 @@ import type { Position } from "../util/location"; import { createPositionWithColumnOffset } from "../util/location"; import { cloneStringLiteral, cloneIdentifier, type Undone } from "./node"; import type Parser from "./index"; +import { ParseBindingListFlags } from "./lval"; const loopLabel = { kind: "loop" } as const, switchLabel = { kind: "switch" } as const; @@ -1566,7 +1567,7 @@ export default abstract class StatementParser extends ExpressionParser { node.id = this.parseFunctionId(); } - this.parseFunctionParams(node, /* allowModifiers */ false); + this.parseFunctionParams(node, /* isConstructor */ false); // For the smartPipelines plugin: Disable topic references from outer // contexts within the function body. They are permitted in function @@ -1602,15 +1603,15 @@ export default abstract class StatementParser extends ExpressionParser { parseFunctionParams( this: Parser, node: Undone, - allowModifiers?: boolean, + isConstructor?: boolean, ): void { this.expect(tt.parenL); this.expressionScope.enter(newParameterDeclarationScope()); node.params = this.parseBindingList( tt.parenR, charCodes.rightParenthesis, - /* allowEmpty */ false, - allowModifiers, + ParseBindingListFlags.IS_FUNCTION_PARAMS | + (isConstructor ? ParseBindingListFlags.IS_CONSTRUCTOR_PARAMS : 0), ); this.expressionScope.exit(); diff --git a/packages/babel-parser/src/plugins/flow/index.ts b/packages/babel-parser/src/plugins/flow/index.ts index 175629c84139..013f94d6d54c 100644 --- a/packages/babel-parser/src/plugins/flow/index.ts +++ b/packages/babel-parser/src/plugins/flow/index.ts @@ -2887,14 +2887,14 @@ export default (superClass: typeof Parser) => // parse function type parameters - function foo() {} parseFunctionParams( node: Undone, - allowModifiers?: boolean, + isConstructor: boolean, ): void { // @ts-expect-error kind may not index node const kind = node.kind; if (kind !== "get" && kind !== "set" && this.match(tt.lt)) { node.typeParameters = this.flowParseTypeParameterDeclaration(); } - super.parseFunctionParams(node, allowModifiers); + super.parseFunctionParams(node, isConstructor); } // parse flow type annotations on variable declarator heads - let foo: string = bar @@ -3291,7 +3291,7 @@ export default (superClass: typeof Parser) => startLoc: Position, ): N.ArrowFunctionExpression | undefined | null { const node = this.startNodeAt(startLoc); - this.parseFunctionParams(node); + this.parseFunctionParams(node, false); if (!this.parseArrow(node)) return; return super.parseArrowExpression( node, diff --git a/packages/babel-parser/src/plugins/typescript/index.ts b/packages/babel-parser/src/plugins/typescript/index.ts index e781b07987be..9a2eb6b0e9dc 100644 --- a/packages/babel-parser/src/plugins/typescript/index.ts +++ b/packages/babel-parser/src/plugins/typescript/index.ts @@ -42,6 +42,7 @@ import { cloneIdentifier, type Undone } from "../../parser/node"; import type { Pattern } from "../../types"; import type { Expression } from "../../types"; import type { IJSXParserMixin } from "../jsx"; +import { ParseBindingListFlags } from "../../parser/lval"; const getOwn = (object: T, key: keyof T) => Object.hasOwnProperty.call(object, key) && object[key]; @@ -755,7 +756,11 @@ export default (superClass: ClassWithMixin) => N.Identifier | N.RestElement | N.ObjectPattern | N.ArrayPattern > { return super - .parseBindingList(tt.parenR, charCodes.rightParenthesis) + .parseBindingList( + tt.parenR, + charCodes.rightParenthesis, + ParseBindingListFlags.IS_FUNCTION_PARAMS, + ) .map(pattern => { if ( pattern.type !== "Identifier" && @@ -1422,7 +1427,7 @@ export default (superClass: ClassWithMixin) => super.parseBindingList( tt.bracketR, charCodes.rightSquareBracket, - true, + ParseBindingListFlags.ALLOW_EMPTY, ); return errors.length === previousErrorCount; } catch { @@ -2249,40 +2254,35 @@ export default (superClass: ClassWithMixin) => } parseAssignableListItem( - allowModifiers: boolean | undefined | null, + flags: ParseBindingListFlags, decorators: N.Decorator[], ): N.Pattern | N.TSParameterProperty { // Store original location to include modifiers in range const startLoc = this.state.startLoc; - let accessibility: N.Accessibility | undefined | null; - let readonly = false; - let override = false; - if (allowModifiers !== undefined) { - const modified: ModifierBase = {}; - this.tsParseModifiers({ - modified, - allowedModifiers: [ - "public", - "private", - "protected", - "override", - "readonly", - ], - }); - accessibility = modified.accessibility; - override = modified.override; - readonly = modified.readonly; - if ( - allowModifiers === false && - (accessibility || readonly || override) - ) { - this.raise(TSErrors.UnexpectedParameterModifier, { at: startLoc }); - } + const modified: ModifierBase = {}; + this.tsParseModifiers({ + modified, + allowedModifiers: [ + "public", + "private", + "protected", + "override", + "readonly", + ], + }); + const accessibility = modified.accessibility; + const override = modified.override; + const readonly = modified.readonly; + if ( + !(flags & ParseBindingListFlags.IS_CONSTRUCTOR_PARAMS) && + (accessibility || readonly || override) + ) { + this.raise(TSErrors.UnexpectedParameterModifier, { at: startLoc }); } const left = this.parseMaybeDefault(); - this.parseAssignableListItemTypes(left); + this.parseAssignableListItemTypes(left, flags); const elt = this.parseMaybeDefault(left.loc.start, left); if (accessibility || readonly || override) { const pp = this.startNodeAt(startLoc); @@ -2314,6 +2314,27 @@ export default (superClass: ClassWithMixin) => ); } + tsDisallowOptionalPattern(node: Undone) { + for (const param of node.params) { + if ( + param.type !== "Identifier" && + (param as any).optional && + !this.state.isAmbientContext + ) { + this.raise(TSErrors.PatternIsOptional, { at: param }); + } + } + } + + setArrowFunctionParameters( + node: Undone, + params: N.Expression[], + trailingCommaLoc?: Position | null, + ): void { + super.setArrowFunctionParameters(node, params, trailingCommaLoc); + this.tsDisallowOptionalPattern(node); + } + parseFunctionBodyAndFinish< T extends | N.Function @@ -2340,6 +2361,7 @@ export default (superClass: ClassWithMixin) => return super.parseFunctionBodyAndFinish(node, bodilessType, isMethod); } } + this.tsDisallowOptionalPattern(node); return super.parseFunctionBodyAndFinish(node, type, isMethod); } @@ -3271,10 +3293,10 @@ export default (superClass: ClassWithMixin) => ); } - parseFunctionParams(node: N.Function, allowModifiers?: boolean): void { + parseFunctionParams(node: N.Function, isConstructor: boolean): void { const typeParameters = this.tsTryParseTypeParameters(); if (typeParameters) node.typeParameters = typeParameters; - super.parseFunctionParams(node, allowModifiers); + super.parseFunctionParams(node, isConstructor); } // `let x: number;` @@ -3504,16 +3526,13 @@ export default (superClass: ClassWithMixin) => } // Allow type annotations inside of a parameter list. - parseAssignableListItemTypes(param: N.Pattern) { - if (this.eat(tt.question)) { - if ( - param.type !== "Identifier" && - !this.state.isAmbientContext && - !this.state.inType - ) { - this.raise(TSErrors.PatternIsOptional, { at: param }); - } + parseAssignableListItemTypes( + param: N.Pattern, + flags: ParseBindingListFlags, + ) { + if (!(flags & ParseBindingListFlags.IS_FUNCTION_PARAMS)) return param; + if (this.eat(tt.question)) { (param as any as N.Identifier).optional = true; } const type = this.tsTryParseTypeAnnotation(); diff --git a/packages/babel-parser/test/fixtures/typescript/arrow-function/async-rest-optional-parameter/output.json b/packages/babel-parser/test/fixtures/typescript/arrow-function/async-rest-optional-parameter/output.json index 7c0ab134d135..31026da03f9d 100644 --- a/packages/babel-parser/test/fixtures/typescript/arrow-function/async-rest-optional-parameter/output.json +++ b/packages/babel-parser/test/fixtures/typescript/arrow-function/async-rest-optional-parameter/output.json @@ -1,6 +1,9 @@ { "type": "File", "start":0,"end":34,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":1,"column":34,"index":34}}, + "errors": [ + "SyntaxError: A binding pattern parameter cannot be optional in an implementation signature. (1:6)" + ], "program": { "type": "Program", "start":0,"end":34,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":1,"column":34,"index":34}}, diff --git a/packages/babel-parser/test/fixtures/typescript/function/pattern-optional-parameters-arrow/input.ts b/packages/babel-parser/test/fixtures/typescript/function/pattern-optional-parameters-arrow/input.ts new file mode 100644 index 000000000000..355c4ac0c1f1 --- /dev/null +++ b/packages/babel-parser/test/fixtures/typescript/function/pattern-optional-parameters-arrow/input.ts @@ -0,0 +1 @@ +([]?, {}) => {} diff --git a/packages/babel-parser/test/fixtures/typescript/function/pattern-optional-parameters-arrow/output.json b/packages/babel-parser/test/fixtures/typescript/function/pattern-optional-parameters-arrow/output.json new file mode 100644 index 000000000000..491fe4f5c70c --- /dev/null +++ b/packages/babel-parser/test/fixtures/typescript/function/pattern-optional-parameters-arrow/output.json @@ -0,0 +1,46 @@ +{ + "type": "File", + "start":0,"end":15,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":1,"column":15,"index":15}}, + "errors": [ + "SyntaxError: A binding pattern parameter cannot be optional in an implementation signature. (1:1)" + ], + "program": { + "type": "Program", + "start":0,"end":15,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":1,"column":15,"index":15}}, + "sourceType": "module", + "interpreter": null, + "body": [ + { + "type": "ExpressionStatement", + "start":0,"end":15,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":1,"column":15,"index":15}}, + "expression": { + "type": "ArrowFunctionExpression", + "start":0,"end":15,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":1,"column":15,"index":15}}, + "id": null, + "generator": false, + "async": false, + "params": [ + { + "type": "ArrayPattern", + "start":1,"end":4,"loc":{"start":{"line":1,"column":1,"index":1},"end":{"line":1,"column":4,"index":4}}, + "elements": [], + "optional": true + }, + { + "type": "ObjectPattern", + "start":6,"end":8,"loc":{"start":{"line":1,"column":6,"index":6},"end":{"line":1,"column":8,"index":8}}, + "properties": [] + } + ], + "body": { + "type": "BlockStatement", + "start":13,"end":15,"loc":{"start":{"line":1,"column":13,"index":13},"end":{"line":1,"column":15,"index":15}}, + "body": [], + "directives": [] + } + } + } + ], + "directives": [] + } +} diff --git a/packages/babel-parser/test/fixtures/typescript/function/pattern-parameters/input.ts b/packages/babel-parser/test/fixtures/typescript/function/pattern-optional-parameters/input.ts similarity index 100% rename from packages/babel-parser/test/fixtures/typescript/function/pattern-parameters/input.ts rename to packages/babel-parser/test/fixtures/typescript/function/pattern-optional-parameters/input.ts diff --git a/packages/babel-parser/test/fixtures/typescript/function/pattern-parameters/output.json b/packages/babel-parser/test/fixtures/typescript/function/pattern-optional-parameters/output.json similarity index 100% rename from packages/babel-parser/test/fixtures/typescript/function/pattern-parameters/output.json rename to packages/babel-parser/test/fixtures/typescript/function/pattern-optional-parameters/output.json diff --git a/packages/babel-parser/test/fixtures/typescript/scope/function-type-before-declaration-optional-pattern/input.ts b/packages/babel-parser/test/fixtures/typescript/scope/function-type-before-declaration-optional-pattern/input.ts new file mode 100644 index 000000000000..4c4a780fe057 --- /dev/null +++ b/packages/babel-parser/test/fixtures/typescript/scope/function-type-before-declaration-optional-pattern/input.ts @@ -0,0 +1,4 @@ +function f({}?): void; +function f() {} + +export { f }; \ No newline at end of file diff --git a/packages/babel-parser/test/fixtures/typescript/scope/function-type-before-declaration-optional-pattern/output.json b/packages/babel-parser/test/fixtures/typescript/scope/function-type-before-declaration-optional-pattern/output.json new file mode 100644 index 000000000000..60d5f159e94e --- /dev/null +++ b/packages/babel-parser/test/fixtures/typescript/scope/function-type-before-declaration-optional-pattern/output.json @@ -0,0 +1,82 @@ +{ + "type": "File", + "start":0,"end":53,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":4,"column":13,"index":53}}, + "program": { + "type": "Program", + "start":0,"end":53,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":4,"column":13,"index":53}}, + "sourceType": "module", + "interpreter": null, + "body": [ + { + "type": "TSDeclareFunction", + "start":0,"end":22,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":1,"column":22,"index":22}}, + "id": { + "type": "Identifier", + "start":9,"end":10,"loc":{"start":{"line":1,"column":9,"index":9},"end":{"line":1,"column":10,"index":10},"identifierName":"f"}, + "name": "f" + }, + "generator": false, + "async": false, + "params": [ + { + "type": "ObjectPattern", + "start":11,"end":14,"loc":{"start":{"line":1,"column":11,"index":11},"end":{"line":1,"column":14,"index":14}}, + "properties": [], + "optional": true + } + ], + "returnType": { + "type": "TSTypeAnnotation", + "start":15,"end":21,"loc":{"start":{"line":1,"column":15,"index":15},"end":{"line":1,"column":21,"index":21}}, + "typeAnnotation": { + "type": "TSVoidKeyword", + "start":17,"end":21,"loc":{"start":{"line":1,"column":17,"index":17},"end":{"line":1,"column":21,"index":21}} + } + } + }, + { + "type": "FunctionDeclaration", + "start":23,"end":38,"loc":{"start":{"line":2,"column":0,"index":23},"end":{"line":2,"column":15,"index":38}}, + "id": { + "type": "Identifier", + "start":32,"end":33,"loc":{"start":{"line":2,"column":9,"index":32},"end":{"line":2,"column":10,"index":33},"identifierName":"f"}, + "name": "f" + }, + "generator": false, + "async": false, + "params": [], + "body": { + "type": "BlockStatement", + "start":36,"end":38,"loc":{"start":{"line":2,"column":13,"index":36},"end":{"line":2,"column":15,"index":38}}, + "body": [], + "directives": [] + } + }, + { + "type": "ExportNamedDeclaration", + "start":40,"end":53,"loc":{"start":{"line":4,"column":0,"index":40},"end":{"line":4,"column":13,"index":53}}, + "exportKind": "value", + "specifiers": [ + { + "type": "ExportSpecifier", + "start":49,"end":50,"loc":{"start":{"line":4,"column":9,"index":49},"end":{"line":4,"column":10,"index":50}}, + "local": { + "type": "Identifier", + "start":49,"end":50,"loc":{"start":{"line":4,"column":9,"index":49},"end":{"line":4,"column":10,"index":50},"identifierName":"f"}, + "name": "f" + }, + "exportKind": "value", + "exported": { + "type": "Identifier", + "start":49,"end":50,"loc":{"start":{"line":4,"column":9,"index":49},"end":{"line":4,"column":10,"index":50},"identifierName":"f"}, + "name": "f" + } + } + ], + "source": null, + "declaration": null + } + ], + "directives": [] + } +} diff --git a/packages/babel-parser/test/fixtures/typescript/types/no-annotation-in-destructuring/input.ts b/packages/babel-parser/test/fixtures/typescript/types/no-annotation-in-destructuring/input.ts new file mode 100644 index 000000000000..1254a85e3364 --- /dev/null +++ b/packages/babel-parser/test/fixtures/typescript/types/no-annotation-in-destructuring/input.ts @@ -0,0 +1 @@ +let [a: number] = b; \ No newline at end of file diff --git a/packages/babel-parser/test/fixtures/typescript/types/no-annotation-in-destructuring/options.json b/packages/babel-parser/test/fixtures/typescript/types/no-annotation-in-destructuring/options.json new file mode 100644 index 000000000000..c11cb6fdfbdf --- /dev/null +++ b/packages/babel-parser/test/fixtures/typescript/types/no-annotation-in-destructuring/options.json @@ -0,0 +1,3 @@ +{ + "throws": "Unexpected token, expected \",\" (1:6)" +} diff --git a/packages/babel-parser/test/fixtures/typescript/types/no-optional-in-destructuring-in-params/input.ts b/packages/babel-parser/test/fixtures/typescript/types/no-optional-in-destructuring-in-params/input.ts new file mode 100644 index 000000000000..5ddddb679cd2 --- /dev/null +++ b/packages/babel-parser/test/fixtures/typescript/types/no-optional-in-destructuring-in-params/input.ts @@ -0,0 +1 @@ +function f([a: number]) {} diff --git a/packages/babel-parser/test/fixtures/typescript/types/no-optional-in-destructuring-in-params/options.json b/packages/babel-parser/test/fixtures/typescript/types/no-optional-in-destructuring-in-params/options.json new file mode 100644 index 000000000000..c5749f7ae776 --- /dev/null +++ b/packages/babel-parser/test/fixtures/typescript/types/no-optional-in-destructuring-in-params/options.json @@ -0,0 +1,3 @@ +{ + "throws": "Unexpected token, expected \",\" (1:13)" +} diff --git a/packages/babel-parser/test/fixtures/typescript/types/no-optional-in-destructuring/input.ts b/packages/babel-parser/test/fixtures/typescript/types/no-optional-in-destructuring/input.ts new file mode 100644 index 000000000000..1254a85e3364 --- /dev/null +++ b/packages/babel-parser/test/fixtures/typescript/types/no-optional-in-destructuring/input.ts @@ -0,0 +1 @@ +let [a: number] = b; \ No newline at end of file diff --git a/packages/babel-parser/test/fixtures/typescript/types/no-optional-in-destructuring/options.json b/packages/babel-parser/test/fixtures/typescript/types/no-optional-in-destructuring/options.json new file mode 100644 index 000000000000..c11cb6fdfbdf --- /dev/null +++ b/packages/babel-parser/test/fixtures/typescript/types/no-optional-in-destructuring/options.json @@ -0,0 +1,3 @@ +{ + "throws": "Unexpected token, expected \",\" (1:6)" +} diff --git a/packages/babel-plugin-transform-flow-comments/src/index.ts b/packages/babel-plugin-transform-flow-comments/src/index.ts index 524479c91654..d851f07f6faa 100644 --- a/packages/babel-plugin-transform-flow-comments/src/index.ts +++ b/packages/babel-plugin-transform-flow-comments/src/index.ts @@ -143,9 +143,9 @@ export default declare(api => { AssignmentPattern: { exit({ node }) { const { left } = node; - // @ts-expect-error optional is not in ObjectPattern + // @ts-expect-error optional is not in TSAsExpression if (left.optional) { - // @ts-expect-error optional is not in ObjectPattern + // @ts-expect-error optional is not in TSAsExpression left.optional = false; } }, @@ -238,7 +238,6 @@ export default declare(api => { ofPath: path.get("typeAnnotation"), toPath: path, optional: - // @ts-expect-error optional is not in ObjectPattern node.optional || // @ts-expect-error Fixme: optional is not in t.TypeAnnotation node.typeAnnotation.optional, diff --git a/packages/babel-plugin-transform-flow-strip-types/src/index.ts b/packages/babel-plugin-transform-flow-strip-types/src/index.ts index d633741f21f6..db6060e1d726 100644 --- a/packages/babel-plugin-transform-flow-strip-types/src/index.ts +++ b/packages/babel-plugin-transform-flow-strip-types/src/index.ts @@ -136,9 +136,9 @@ export default declare((api, opts: Options) => { AssignmentPattern({ node }) { if (skipStrip) return; - // @ts-expect-error optional is not in ObjectPattern + // @ts-expect-error optional is not in TSAsExpression if (node.left.optional) { - // @ts-expect-error optional is not in ObjectPattern + // @ts-expect-error optional is not in TSAsExpression node.left.optional = false; } }, @@ -159,9 +159,9 @@ export default declare((api, opts: Options) => { // must not be a MemberExpression param = param.left; } - // @ts-expect-error optional is not in ObjectPattern + // @ts-expect-error optional is not in TSAsExpression if (param.optional) { - // @ts-expect-error optional is not in ObjectPattern + // @ts-expect-error optional is not in TSAsExpression param.optional = false; } } diff --git a/packages/babel-types/src/ast-types/generated/index.ts b/packages/babel-types/src/ast-types/generated/index.ts index d09439230eac..f3eb2cf0dae8 100644 --- a/packages/babel-types/src/ast-types/generated/index.ts +++ b/packages/babel-types/src/ast-types/generated/index.ts @@ -725,6 +725,7 @@ export interface AssignmentPattern extends BaseNode { | TSNonNullExpression; right: Expression; decorators?: Array | null; + optional?: boolean | null; typeAnnotation?: TypeAnnotation | TSTypeAnnotation | Noop | null; } @@ -911,6 +912,7 @@ export interface ObjectPattern extends BaseNode { type: "ObjectPattern"; properties: Array; decorators?: Array | null; + optional?: boolean | null; typeAnnotation?: TypeAnnotation | TSTypeAnnotation | Noop | null; } diff --git a/packages/babel-types/src/definitions/core.ts b/packages/babel-types/src/definitions/core.ts index 522cf74b04a7..c2ca202879e1 100644 --- a/packages/babel-types/src/definitions/core.ts +++ b/packages/babel-types/src/definitions/core.ts @@ -492,6 +492,10 @@ export const patternLikeCommon = () => ({ ), optional: true, }, + optional: { + validate: assertValueType("boolean"), + optional: true, + }, decorators: { validate: chain( assertValueType("array"), @@ -522,10 +526,6 @@ defineType("Identifier", { ), ), }, - optional: { - validate: assertValueType("boolean"), - optional: true, - }, }, validate(parent, key, node) { if (!process.env.BABEL_TYPES_8_BREAKING) return; @@ -968,11 +968,6 @@ defineType("RestElement", { "TSNonNullExpression", ), }, - // For Flow - optional: { - validate: assertValueType("boolean"), - optional: true, - }, }, validate(parent: t.ArrayPattern | t.ObjectPattern, key) { if (!process.env.BABEL_TYPES_8_BREAKING) return; @@ -1285,18 +1280,6 @@ defineType("ArrayPattern", { assertEach(assertNodeOrValueType("null", "PatternLike", "LVal")), ), }, - // For TypeScript - decorators: { - validate: chain( - assertValueType("array"), - assertEach(assertNodeType("Decorator")), - ), - optional: true, - }, - optional: { - validate: assertValueType("boolean"), - optional: true, - }, }, }); diff --git a/scripts/parser-tests/typescript/allowlist.txt b/scripts/parser-tests/typescript/allowlist.txt index d4404a932f64..17b027afe5dc 100644 --- a/scripts/parser-tests/typescript/allowlist.txt +++ b/scripts/parser-tests/typescript/allowlist.txt @@ -40,7 +40,6 @@ constDeclarations-invalidContexts.ts constDeclarations-scopes.ts constDeclarations-validContexts.ts declarationEmitDestructuring2.ts -declarationEmitDestructuringOptionalBindingParametersInOverloads.ts declarationEmitDestructuringParameterProperties.ts declarationEmitDestructuringWithOptionalBindingParameters.ts declarationEmitInterfaceWithNonEntityNameExpressionHeritage.ts