diff --git a/packages/ast-spec/src/declaration/ExportNamedDeclaration/spec.ts b/packages/ast-spec/src/declaration/ExportNamedDeclaration/spec.ts index bf4d9ea86d2..a8f476477a7 100644 --- a/packages/ast-spec/src/declaration/ExportNamedDeclaration/spec.ts +++ b/packages/ast-spec/src/declaration/ExportNamedDeclaration/spec.ts @@ -2,13 +2,13 @@ import type { AST_NODE_TYPES } from '../../ast-node-types'; import type { BaseNode } from '../../base/BaseNode'; import type { ExportSpecifier } from '../../special/ExportSpecifier/spec'; import type { ExportDeclaration } from '../../unions/ExportDeclaration'; -import type { Expression } from '../../unions/Expression'; +import type { Literal } from '../../unions/Literal'; import type { ExportKind } from '../ExportAndImportKind'; export interface ExportNamedDeclaration extends BaseNode { type: AST_NODE_TYPES.ExportNamedDeclaration; declaration: ExportDeclaration | null; specifiers: ExportSpecifier[]; - source: Expression | null; + source: Literal | null; exportKind: ExportKind; } diff --git a/packages/shared-fixtures/fixtures/javascript/modules/invalid-export-module-specifier.src.js b/packages/shared-fixtures/fixtures/javascript/modules/invalid-export-module-specifier.src.js new file mode 100644 index 00000000000..29faf851822 --- /dev/null +++ b/packages/shared-fixtures/fixtures/javascript/modules/invalid-export-module-specifier.src.js @@ -0,0 +1 @@ +export { foo } from bar; diff --git a/packages/typescript-estree/src/convert.ts b/packages/typescript-estree/src/convert.ts index 7f8514d8bc0..ffacd1d8a8f 100644 --- a/packages/typescript-estree/src/convert.ts +++ b/packages/typescript-estree/src/convert.ts @@ -724,6 +724,21 @@ export class Converter { } } + private assertModuleSpecifier( + node: ts.ExportDeclaration | ts.ImportDeclaration, + ): void { + if ( + node.moduleSpecifier && + node.moduleSpecifier.kind !== SyntaxKind.StringLiteral + ) { + throw createError( + this.ast, + node.moduleSpecifier.pos, + 'Module specifier must be a string literal.', + ); + } + } + /** * Converts a TypeScript node into an ESTree node. * The core of the conversion logic: @@ -1690,6 +1705,8 @@ export class Converter { }); case SyntaxKind.ImportDeclaration: { + this.assertModuleSpecifier(node); + const result = this.createNode(node, { type: AST_NODE_TYPES.ImportDeclaration, source: this.convertChild(node.moduleSpecifier), @@ -1748,7 +1765,8 @@ export class Converter { }); } - case SyntaxKind.ExportDeclaration: + case SyntaxKind.ExportDeclaration: { + this.assertModuleSpecifier(node); if (node.exportClause?.kind === SyntaxKind.NamedExports) { return this.createNode(node, { type: AST_NODE_TYPES.ExportNamedDeclaration, @@ -1775,6 +1793,7 @@ export class Converter { : null, }); } + } case SyntaxKind.ExportSpecifier: return this.createNode(node, { diff --git a/packages/typescript-estree/tests/lib/__snapshots__/semantic-diagnostics-enabled.test.ts.snap b/packages/typescript-estree/tests/lib/__snapshots__/semantic-diagnostics-enabled.test.ts.snap index 7a972315f31..4d07cbc4128 100644 --- a/packages/typescript-estree/tests/lib/__snapshots__/semantic-diagnostics-enabled.test.ts.snap +++ b/packages/typescript-estree/tests/lib/__snapshots__/semantic-diagnostics-enabled.test.ts.snap @@ -908,6 +908,15 @@ TSError { } `; +exports[`Parse all fixtures with "errorOnTypeScriptSyntacticAndSemanticIssues" enabled fixtures/javascript/modules/invalid-export-module-specifier.src 1`] = ` +TSError { + "column": 19, + "index": 19, + "lineNumber": 1, + "message": "Module specifier must be a string literal.", +} +`; + exports[`Parse all fixtures with "errorOnTypeScriptSyntacticAndSemanticIssues" enabled fixtures/javascript/modules/invalid-export-named-default.src 1`] = `"TEST OUTPUT: No semantic or syntactic issues found"`; exports[`Parse all fixtures with "errorOnTypeScriptSyntacticAndSemanticIssues" enabled fixtures/javascript/modules/invalid-export-named-extra-comma.src 1`] = ` @@ -966,10 +975,10 @@ TSError { exports[`Parse all fixtures with "errorOnTypeScriptSyntacticAndSemanticIssues" enabled fixtures/javascript/modules/invalid-import-default-module-specifier.src 1`] = ` TSError { - "column": 16, - "index": 16, + "column": 15, + "index": 15, "lineNumber": 1, - "message": "String literal expected.", + "message": "Module specifier must be a string literal.", } `; @@ -984,10 +993,10 @@ TSError { exports[`Parse all fixtures with "errorOnTypeScriptSyntacticAndSemanticIssues" enabled fixtures/javascript/modules/invalid-import-module-specifier.src 1`] = ` TSError { - "column": 18, - "index": 18, + "column": 17, + "index": 17, "lineNumber": 1, - "message": "String literal expected.", + "message": "Module specifier must be a string literal.", } `; diff --git a/packages/typescript-estree/tests/snapshots/javascript/modules/invalid-export-module-specifier.src.js.shot b/packages/typescript-estree/tests/snapshots/javascript/modules/invalid-export-module-specifier.src.js.shot new file mode 100644 index 00000000000..5467f678c18 --- /dev/null +++ b/packages/typescript-estree/tests/snapshots/javascript/modules/invalid-export-module-specifier.src.js.shot @@ -0,0 +1,10 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`javascript modules invalid-export-module-specifier.src 1`] = ` +TSError { + "column": 19, + "index": 19, + "lineNumber": 1, + "message": "Module specifier must be a string literal.", +} +`; diff --git a/packages/typescript-estree/tests/snapshots/javascript/modules/invalid-import-default-module-specifier.src.js.shot b/packages/typescript-estree/tests/snapshots/javascript/modules/invalid-import-default-module-specifier.src.js.shot index 11bb8f0abb0..0754b716ae5 100644 --- a/packages/typescript-estree/tests/snapshots/javascript/modules/invalid-import-default-module-specifier.src.js.shot +++ b/packages/typescript-estree/tests/snapshots/javascript/modules/invalid-import-default-module-specifier.src.js.shot @@ -1,190 +1,10 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`javascript modules invalid-import-default-module-specifier.src 1`] = ` -Object { - "body": Array [ - Object { - "importKind": "value", - "loc": Object { - "end": Object { - "column": 20, - "line": 1, - }, - "start": Object { - "column": 0, - "line": 1, - }, - }, - "range": Array [ - 0, - 20, - ], - "source": Object { - "loc": Object { - "end": Object { - "column": 19, - "line": 1, - }, - "start": Object { - "column": 16, - "line": 1, - }, - }, - "name": "bar", - "range": Array [ - 16, - 19, - ], - "type": "Identifier", - }, - "specifiers": Array [ - Object { - "loc": Object { - "end": Object { - "column": 10, - "line": 1, - }, - "start": Object { - "column": 7, - "line": 1, - }, - }, - "local": Object { - "loc": Object { - "end": Object { - "column": 10, - "line": 1, - }, - "start": Object { - "column": 7, - "line": 1, - }, - }, - "name": "foo", - "range": Array [ - 7, - 10, - ], - "type": "Identifier", - }, - "range": Array [ - 7, - 10, - ], - "type": "ImportDefaultSpecifier", - }, - ], - "type": "ImportDeclaration", - }, - ], - "comments": Array [], - "loc": Object { - "end": Object { - "column": 0, - "line": 2, - }, - "start": Object { - "column": 0, - "line": 1, - }, - }, - "range": Array [ - 0, - 21, - ], - "sourceType": "module", - "tokens": Array [ - Object { - "loc": Object { - "end": Object { - "column": 6, - "line": 1, - }, - "start": Object { - "column": 0, - "line": 1, - }, - }, - "range": Array [ - 0, - 6, - ], - "type": "Keyword", - "value": "import", - }, - Object { - "loc": Object { - "end": Object { - "column": 10, - "line": 1, - }, - "start": Object { - "column": 7, - "line": 1, - }, - }, - "range": Array [ - 7, - 10, - ], - "type": "Identifier", - "value": "foo", - }, - Object { - "loc": Object { - "end": Object { - "column": 15, - "line": 1, - }, - "start": Object { - "column": 11, - "line": 1, - }, - }, - "range": Array [ - 11, - 15, - ], - "type": "Identifier", - "value": "from", - }, - Object { - "loc": Object { - "end": Object { - "column": 19, - "line": 1, - }, - "start": Object { - "column": 16, - "line": 1, - }, - }, - "range": Array [ - 16, - 19, - ], - "type": "Identifier", - "value": "bar", - }, - Object { - "loc": Object { - "end": Object { - "column": 20, - "line": 1, - }, - "start": Object { - "column": 19, - "line": 1, - }, - }, - "range": Array [ - 19, - 20, - ], - "type": "Punctuator", - "value": ";", - }, - ], - "type": "Program", +TSError { + "column": 15, + "index": 15, + "lineNumber": 1, + "message": "Module specifier must be a string literal.", } `; diff --git a/packages/typescript-estree/tests/snapshots/javascript/modules/invalid-import-module-specifier.src.js.shot b/packages/typescript-estree/tests/snapshots/javascript/modules/invalid-import-module-specifier.src.js.shot index f810bb25d0c..d456d2e4679 100644 --- a/packages/typescript-estree/tests/snapshots/javascript/modules/invalid-import-module-specifier.src.js.shot +++ b/packages/typescript-estree/tests/snapshots/javascript/modules/invalid-import-module-specifier.src.js.shot @@ -1,227 +1,10 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`javascript modules invalid-import-module-specifier.src 1`] = ` -Object { - "body": Array [ - Object { - "declaration": null, - "exportKind": "value", - "loc": Object { - "end": Object { - "column": 21, - "line": 1, - }, - "start": Object { - "column": 0, - "line": 1, - }, - }, - "range": Array [ - 0, - 21, - ], - "source": Object { - "loc": Object { - "end": Object { - "column": 21, - "line": 1, - }, - "start": Object { - "column": 18, - "line": 1, - }, - }, - "name": "bar", - "range": Array [ - 18, - 21, - ], - "type": "Identifier", - }, - "specifiers": Array [ - Object { - "exported": Object { - "loc": Object { - "end": Object { - "column": 11, - "line": 1, - }, - "start": Object { - "column": 8, - "line": 1, - }, - }, - "name": "foo", - "range": Array [ - 8, - 11, - ], - "type": "Identifier", - }, - "loc": Object { - "end": Object { - "column": 11, - "line": 1, - }, - "start": Object { - "column": 8, - "line": 1, - }, - }, - "local": Object { - "loc": Object { - "end": Object { - "column": 11, - "line": 1, - }, - "start": Object { - "column": 8, - "line": 1, - }, - }, - "name": "foo", - "range": Array [ - 8, - 11, - ], - "type": "Identifier", - }, - "range": Array [ - 8, - 11, - ], - "type": "ExportSpecifier", - }, - ], - "type": "ExportNamedDeclaration", - }, - ], - "comments": Array [], - "loc": Object { - "end": Object { - "column": 0, - "line": 2, - }, - "start": Object { - "column": 0, - "line": 1, - }, - }, - "range": Array [ - 0, - 22, - ], - "sourceType": "module", - "tokens": Array [ - Object { - "loc": Object { - "end": Object { - "column": 6, - "line": 1, - }, - "start": Object { - "column": 0, - "line": 1, - }, - }, - "range": Array [ - 0, - 6, - ], - "type": "Keyword", - "value": "export", - }, - Object { - "loc": Object { - "end": Object { - "column": 8, - "line": 1, - }, - "start": Object { - "column": 7, - "line": 1, - }, - }, - "range": Array [ - 7, - 8, - ], - "type": "Punctuator", - "value": "{", - }, - Object { - "loc": Object { - "end": Object { - "column": 11, - "line": 1, - }, - "start": Object { - "column": 8, - "line": 1, - }, - }, - "range": Array [ - 8, - 11, - ], - "type": "Identifier", - "value": "foo", - }, - Object { - "loc": Object { - "end": Object { - "column": 12, - "line": 1, - }, - "start": Object { - "column": 11, - "line": 1, - }, - }, - "range": Array [ - 11, - 12, - ], - "type": "Punctuator", - "value": "}", - }, - Object { - "loc": Object { - "end": Object { - "column": 17, - "line": 1, - }, - "start": Object { - "column": 13, - "line": 1, - }, - }, - "range": Array [ - 13, - 17, - ], - "type": "Identifier", - "value": "from", - }, - Object { - "loc": Object { - "end": Object { - "column": 21, - "line": 1, - }, - "start": Object { - "column": 18, - "line": 1, - }, - }, - "range": Array [ - 18, - 21, - ], - "type": "Identifier", - "value": "bar", - }, - ], - "type": "Program", +TSError { + "column": 17, + "index": 17, + "lineNumber": 1, + "message": "Module specifier must be a string literal.", } `;