From fbfd1b2aa665679f1d9e4d8b2f6db9557830f35b Mon Sep 17 00:00:00 2001 From: Federico Ciardi Date: Wed, 27 Jan 2021 05:51:12 +0100 Subject: [PATCH] fix(parser): throw error with wrong typescript 'export declare' (#12684) --- .../src/plugins/typescript/index.js | 12 ++++ .../export/declare-invalid/input.ts | 1 + .../export/declare-invalid/options.json | 7 +++ .../typescript/export/declare/input.ts | 2 + .../typescript/export/declare/output.json | 62 ++++++++++++++++++- .../typescript/export/double-declare/input.ts | 1 + .../export/double-declare/options.json | 7 +++ 7 files changed, 90 insertions(+), 2 deletions(-) create mode 100644 packages/babel-parser/test/fixtures/typescript/export/declare-invalid/input.ts create mode 100644 packages/babel-parser/test/fixtures/typescript/export/declare-invalid/options.json create mode 100644 packages/babel-parser/test/fixtures/typescript/export/double-declare/input.ts create mode 100644 packages/babel-parser/test/fixtures/typescript/export/double-declare/options.json diff --git a/packages/babel-parser/src/plugins/typescript/index.js b/packages/babel-parser/src/plugins/typescript/index.js index 3a88f8d673..a890a7136e 100644 --- a/packages/babel-parser/src/plugins/typescript/index.js +++ b/packages/babel-parser/src/plugins/typescript/index.js @@ -74,6 +74,8 @@ const TSErrors = Object.freeze({ EmptyHeritageClauseType: "'%0' list cannot be empty.", EmptyTypeArguments: "Type argument list cannot be empty.", EmptyTypeParameters: "Type parameter list cannot be empty.", + ExpectedAmbientAfterExportDeclare: + "'export declare' must be followed by an ambient declaration.", IndexSignatureHasAbstract: "Index signatures cannot have the 'abstract' modifier", IndexSignatureHasAccessibility: @@ -2281,6 +2283,16 @@ export default (superClass: Class): Class => // "export declare" is equivalent to just "export". const isDeclare = this.eatContextual("declare"); + if ( + isDeclare && + (this.isContextual("declare") || !this.shouldParseExportDeclaration()) + ) { + throw this.raise( + this.state.start, + TSErrors.ExpectedAmbientAfterExportDeclare, + ); + } + let declaration: ?N.Declaration; if (this.match(tt.name)) { diff --git a/packages/babel-parser/test/fixtures/typescript/export/declare-invalid/input.ts b/packages/babel-parser/test/fixtures/typescript/export/declare-invalid/input.ts new file mode 100644 index 0000000000..a4cb16b163 --- /dev/null +++ b/packages/babel-parser/test/fixtures/typescript/export/declare-invalid/input.ts @@ -0,0 +1 @@ +export declare foo; diff --git a/packages/babel-parser/test/fixtures/typescript/export/declare-invalid/options.json b/packages/babel-parser/test/fixtures/typescript/export/declare-invalid/options.json new file mode 100644 index 0000000000..72369bfd51 --- /dev/null +++ b/packages/babel-parser/test/fixtures/typescript/export/declare-invalid/options.json @@ -0,0 +1,7 @@ +{ + "sourceType": "module", + "plugins": [ + "typescript" + ], + "throws": "'export declare' must be followed by an ambient declaration. (1:15)" +} \ No newline at end of file diff --git a/packages/babel-parser/test/fixtures/typescript/export/declare/input.ts b/packages/babel-parser/test/fixtures/typescript/export/declare/input.ts index e269282a91..d272d27444 100644 --- a/packages/babel-parser/test/fixtures/typescript/export/declare/input.ts +++ b/packages/babel-parser/test/fixtures/typescript/export/declare/input.ts @@ -6,3 +6,5 @@ export declare type T = number; export declare module M {} export declare namespace N {} export declare enum foo {} +export declare var bar: string; +export declare var _bar; diff --git a/packages/babel-parser/test/fixtures/typescript/export/declare/output.json b/packages/babel-parser/test/fixtures/typescript/export/declare/output.json index bba4bdacb9..7d11b6f3e0 100644 --- a/packages/babel-parser/test/fixtures/typescript/export/declare/output.json +++ b/packages/babel-parser/test/fixtures/typescript/export/declare/output.json @@ -1,9 +1,9 @@ { "type": "File", - "start":0,"end":238,"loc":{"start":{"line":1,"column":0},"end":{"line":8,"column":26}}, + "start":0,"end":295,"loc":{"start":{"line":1,"column":0},"end":{"line":10,"column":24}}, "program": { "type": "Program", - "start":0,"end":238,"loc":{"start":{"line":1,"column":0},"end":{"line":8,"column":26}}, + "start":0,"end":295,"loc":{"start":{"line":1,"column":0},"end":{"line":10,"column":24}}, "sourceType": "module", "interpreter": null, "body": [ @@ -195,6 +195,64 @@ "members": [], "declare": true } + }, + { + "type": "ExportNamedDeclaration", + "start":239,"end":270,"loc":{"start":{"line":9,"column":0},"end":{"line":9,"column":31}}, + "exportKind": "type", + "specifiers": [], + "source": null, + "declaration": { + "type": "VariableDeclaration", + "start":246,"end":270,"loc":{"start":{"line":9,"column":7},"end":{"line":9,"column":31}}, + "declarations": [ + { + "type": "VariableDeclarator", + "start":258,"end":269,"loc":{"start":{"line":9,"column":19},"end":{"line":9,"column":30}}, + "id": { + "type": "Identifier", + "start":258,"end":269,"loc":{"start":{"line":9,"column":19},"end":{"line":9,"column":30},"identifierName":"bar"}, + "name": "bar", + "typeAnnotation": { + "type": "TSTypeAnnotation", + "start":261,"end":269,"loc":{"start":{"line":9,"column":22},"end":{"line":9,"column":30}}, + "typeAnnotation": { + "type": "TSStringKeyword", + "start":263,"end":269,"loc":{"start":{"line":9,"column":24},"end":{"line":9,"column":30}} + } + } + }, + "init": null + } + ], + "kind": "var", + "declare": true + } + }, + { + "type": "ExportNamedDeclaration", + "start":271,"end":295,"loc":{"start":{"line":10,"column":0},"end":{"line":10,"column":24}}, + "exportKind": "type", + "specifiers": [], + "source": null, + "declaration": { + "type": "VariableDeclaration", + "start":278,"end":295,"loc":{"start":{"line":10,"column":7},"end":{"line":10,"column":24}}, + "declarations": [ + { + "type": "VariableDeclarator", + "start":290,"end":294,"loc":{"start":{"line":10,"column":19},"end":{"line":10,"column":23}}, + "id": { + "type": "Identifier", + "start":290,"end":294,"loc":{"start":{"line":10,"column":19},"end":{"line":10,"column":23},"identifierName":"_bar"}, + "name": "_bar" + }, + "init": null + } + ], + "kind": "var", + "declare": true + } } ], "directives": [] diff --git a/packages/babel-parser/test/fixtures/typescript/export/double-declare/input.ts b/packages/babel-parser/test/fixtures/typescript/export/double-declare/input.ts new file mode 100644 index 0000000000..9e7187f0a1 --- /dev/null +++ b/packages/babel-parser/test/fixtures/typescript/export/double-declare/input.ts @@ -0,0 +1 @@ +export declare declare var name; diff --git a/packages/babel-parser/test/fixtures/typescript/export/double-declare/options.json b/packages/babel-parser/test/fixtures/typescript/export/double-declare/options.json new file mode 100644 index 0000000000..72369bfd51 --- /dev/null +++ b/packages/babel-parser/test/fixtures/typescript/export/double-declare/options.json @@ -0,0 +1,7 @@ +{ + "sourceType": "module", + "plugins": [ + "typescript" + ], + "throws": "'export declare' must be followed by an ambient declaration. (1:15)" +} \ No newline at end of file