diff --git a/packages/babel-parser/src/parser/statement.js b/packages/babel-parser/src/parser/statement.js index 81e310debd7b..d926d51c1ef0 100644 --- a/packages/babel-parser/src/parser/statement.js +++ b/packages/babel-parser/src/parser/statement.js @@ -1348,6 +1348,7 @@ export default class StatementParser extends ExpressionParser { const isPrivate = key.type === "PrivateName"; // Check the key is not a computed expression or string literal. const isSimple = key.type === "Identifier"; + const maybeQuestionTokenStart = this.state.start; this.parsePostMemberNameModifiers(publicMember); @@ -1403,6 +1404,10 @@ export default class StatementParser extends ExpressionParser { // an async method const isGenerator = this.eat(tt.star); + if (publicMember.optional) { + this.unexpected(maybeQuestionTokenStart); + } + method.kind = "method"; // The so-called parsed name would have been "async": get the real name. this.parseClassPropertyName(method); diff --git a/packages/babel-parser/test/fixtures/typescript/class/async-named-properties/input.ts b/packages/babel-parser/test/fixtures/typescript/class/async-named-properties/input.ts new file mode 100644 index 000000000000..1e0af756a626 --- /dev/null +++ b/packages/babel-parser/test/fixtures/typescript/class/async-named-properties/input.ts @@ -0,0 +1,4 @@ +class A { + async?(): void + async?: boolean +} \ No newline at end of file diff --git a/packages/babel-parser/test/fixtures/typescript/class/async-named-properties/output.json b/packages/babel-parser/test/fixtures/typescript/class/async-named-properties/output.json new file mode 100644 index 000000000000..e0ac8a5907fa --- /dev/null +++ b/packages/babel-parser/test/fixtures/typescript/class/async-named-properties/output.json @@ -0,0 +1,221 @@ +{ + "type": "File", + "start": 0, + "end": 46, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 4, + "column": 1 + } + }, + "program": { + "type": "Program", + "start": 0, + "end": 46, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 4, + "column": 1 + } + }, + "sourceType": "module", + "interpreter": null, + "body": [ + { + "type": "ClassDeclaration", + "start": 0, + "end": 46, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 4, + "column": 1 + } + }, + "id": { + "type": "Identifier", + "start": 6, + "end": 7, + "loc": { + "start": { + "line": 1, + "column": 6 + }, + "end": { + "line": 1, + "column": 7 + }, + "identifierName": "A" + }, + "name": "A" + }, + "superClass": null, + "body": { + "type": "ClassBody", + "start": 8, + "end": 46, + "loc": { + "start": { + "line": 1, + "column": 8 + }, + "end": { + "line": 4, + "column": 1 + } + }, + "body": [ + { + "type": "TSDeclareMethod", + "start": 12, + "end": 26, + "loc": { + "start": { + "line": 2, + "column": 2 + }, + "end": { + "line": 2, + "column": 16 + } + }, + "static": false, + "key": { + "type": "Identifier", + "start": 12, + "end": 17, + "loc": { + "start": { + "line": 2, + "column": 2 + }, + "end": { + "line": 2, + "column": 7 + }, + "identifierName": "async" + }, + "name": "async" + }, + "computed": false, + "optional": true, + "kind": "method", + "id": null, + "generator": false, + "async": false, + "params": [], + "returnType": { + "type": "TSTypeAnnotation", + "start": 20, + "end": 26, + "loc": { + "start": { + "line": 2, + "column": 10 + }, + "end": { + "line": 2, + "column": 16 + } + }, + "typeAnnotation": { + "type": "TSVoidKeyword", + "start": 22, + "end": 26, + "loc": { + "start": { + "line": 2, + "column": 12 + }, + "end": { + "line": 2, + "column": 16 + } + } + } + } + }, + { + "type": "ClassProperty", + "start": 29, + "end": 44, + "loc": { + "start": { + "line": 3, + "column": 2 + }, + "end": { + "line": 3, + "column": 17 + } + }, + "static": false, + "key": { + "type": "Identifier", + "start": 29, + "end": 34, + "loc": { + "start": { + "line": 3, + "column": 2 + }, + "end": { + "line": 3, + "column": 7 + }, + "identifierName": "async" + }, + "name": "async" + }, + "computed": false, + "optional": true, + "typeAnnotation": { + "type": "TSTypeAnnotation", + "start": 35, + "end": 44, + "loc": { + "start": { + "line": 3, + "column": 8 + }, + "end": { + "line": 3, + "column": 17 + } + }, + "typeAnnotation": { + "type": "TSBooleanKeyword", + "start": 37, + "end": 44, + "loc": { + "start": { + "line": 3, + "column": 10 + }, + "end": { + "line": 3, + "column": 17 + } + } + } + }, + "value": null + } + ] + } + } + ], + "directives": [] + } +} \ No newline at end of file diff --git a/packages/babel-parser/test/fixtures/typescript/class/optional-async-error/input.js b/packages/babel-parser/test/fixtures/typescript/class/optional-async-error/input.js new file mode 100644 index 000000000000..01d6018a50d2 --- /dev/null +++ b/packages/babel-parser/test/fixtures/typescript/class/optional-async-error/input.js @@ -0,0 +1,4 @@ +class B { } +class A extends B { + async? method(val: string): Promise; +} \ No newline at end of file diff --git a/packages/babel-parser/test/fixtures/typescript/class/optional-async-error/options.json b/packages/babel-parser/test/fixtures/typescript/class/optional-async-error/options.json new file mode 100644 index 000000000000..8dde42aa3f55 --- /dev/null +++ b/packages/babel-parser/test/fixtures/typescript/class/optional-async-error/options.json @@ -0,0 +1,3 @@ +{ + "throws": "Unexpected token (3:9)" +} \ No newline at end of file