From 03d93f1c415a175f8e13ab63647107801e0a3b37 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Ribaudo?= Date: Wed, 15 Mar 2023 10:26:52 +0100 Subject: [PATCH 1/3] [ts] Parse `import ... =` and `export =` in scripts --- .../src/plugins/typescript/index.ts | 12 ++++++ .../export/equals-in-script/input.ts | 1 + .../export/equals-in-script/options.json | 3 ++ .../export/equals-in-script/output.json | 22 +++++++++++ .../export/equals-in-unambiguous/input.ts | 1 + .../export/equals-in-unambiguous/options.json | 3 ++ .../export/equals-in-unambiguous/output.json | 22 +++++++++++ .../import/equals-in-script/input.ts | 1 + .../import/equals-in-script/options.json | 3 ++ .../import/equals-in-script/output.json | 38 +++++++++++++++++++ .../import/equals-in-unambiguous/input.ts | 1 + .../import/equals-in-unambiguous/options.json | 3 ++ .../import/equals-in-unambiguous/output.json | 38 +++++++++++++++++++ .../import/equals-require-in-script/input.ts | 1 + .../equals-require-in-script/options.json | 3 ++ .../equals-require-in-script/output.json | 37 ++++++++++++++++++ .../equals-require-in-unambiguous/input.ts | 1 + .../options.json | 3 ++ .../equals-require-in-unambiguous/output.json | 37 ++++++++++++++++++ 19 files changed, 230 insertions(+) create mode 100644 packages/babel-parser/test/fixtures/typescript/export/equals-in-script/input.ts create mode 100644 packages/babel-parser/test/fixtures/typescript/export/equals-in-script/options.json create mode 100644 packages/babel-parser/test/fixtures/typescript/export/equals-in-script/output.json create mode 100644 packages/babel-parser/test/fixtures/typescript/export/equals-in-unambiguous/input.ts create mode 100644 packages/babel-parser/test/fixtures/typescript/export/equals-in-unambiguous/options.json create mode 100644 packages/babel-parser/test/fixtures/typescript/export/equals-in-unambiguous/output.json create mode 100644 packages/babel-parser/test/fixtures/typescript/import/equals-in-script/input.ts create mode 100644 packages/babel-parser/test/fixtures/typescript/import/equals-in-script/options.json create mode 100644 packages/babel-parser/test/fixtures/typescript/import/equals-in-script/output.json create mode 100644 packages/babel-parser/test/fixtures/typescript/import/equals-in-unambiguous/input.ts create mode 100644 packages/babel-parser/test/fixtures/typescript/import/equals-in-unambiguous/options.json create mode 100644 packages/babel-parser/test/fixtures/typescript/import/equals-in-unambiguous/output.json create mode 100644 packages/babel-parser/test/fixtures/typescript/import/equals-require-in-script/input.ts create mode 100644 packages/babel-parser/test/fixtures/typescript/import/equals-require-in-script/options.json create mode 100644 packages/babel-parser/test/fixtures/typescript/import/equals-require-in-script/output.json create mode 100644 packages/babel-parser/test/fixtures/typescript/import/equals-require-in-unambiguous/input.ts create mode 100644 packages/babel-parser/test/fixtures/typescript/import/equals-require-in-unambiguous/options.json create mode 100644 packages/babel-parser/test/fixtures/typescript/import/equals-require-in-unambiguous/output.json diff --git a/packages/babel-parser/src/plugins/typescript/index.ts b/packages/babel-parser/src/plugins/typescript/index.ts index ac93e996870b..df97882b7729 100644 --- a/packages/babel-parser/src/plugins/typescript/index.ts +++ b/packages/babel-parser/src/plugins/typescript/index.ts @@ -2711,6 +2711,18 @@ export default (superClass: ClassWithMixin) => */ checkDuplicateExports() {} + assertModuleNodeAllowed(node: N.Node): void { + if ( + node.type === "TSImportEqualsDeclaration" || + node.type === "TSExportAssignment" + ) { + // `import ... =` and `export =` are allowed in scripts, + // since they are used for CommonJS. + return; + } + super.assertModuleNodeAllowed(node); + } + parseImport( node: Undone, ): N.AnyImport { diff --git a/packages/babel-parser/test/fixtures/typescript/export/equals-in-script/input.ts b/packages/babel-parser/test/fixtures/typescript/export/equals-in-script/input.ts new file mode 100644 index 000000000000..af251c676fd9 --- /dev/null +++ b/packages/babel-parser/test/fixtures/typescript/export/equals-in-script/input.ts @@ -0,0 +1 @@ +export = f; diff --git a/packages/babel-parser/test/fixtures/typescript/export/equals-in-script/options.json b/packages/babel-parser/test/fixtures/typescript/export/equals-in-script/options.json new file mode 100644 index 000000000000..53135cabff8f --- /dev/null +++ b/packages/babel-parser/test/fixtures/typescript/export/equals-in-script/options.json @@ -0,0 +1,3 @@ +{ + "sourceType": "script" +} \ No newline at end of file diff --git a/packages/babel-parser/test/fixtures/typescript/export/equals-in-script/output.json b/packages/babel-parser/test/fixtures/typescript/export/equals-in-script/output.json new file mode 100644 index 000000000000..4435b69c7622 --- /dev/null +++ b/packages/babel-parser/test/fixtures/typescript/export/equals-in-script/output.json @@ -0,0 +1,22 @@ +{ + "type": "File", + "start":0,"end":11,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":1,"column":11,"index":11}}, + "program": { + "type": "Program", + "start":0,"end":11,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":1,"column":11,"index":11}}, + "sourceType": "script", + "interpreter": null, + "body": [ + { + "type": "TSExportAssignment", + "start":0,"end":11,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":1,"column":11,"index":11}}, + "expression": { + "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" + } + } + ], + "directives": [] + } +} diff --git a/packages/babel-parser/test/fixtures/typescript/export/equals-in-unambiguous/input.ts b/packages/babel-parser/test/fixtures/typescript/export/equals-in-unambiguous/input.ts new file mode 100644 index 000000000000..af251c676fd9 --- /dev/null +++ b/packages/babel-parser/test/fixtures/typescript/export/equals-in-unambiguous/input.ts @@ -0,0 +1 @@ +export = f; diff --git a/packages/babel-parser/test/fixtures/typescript/export/equals-in-unambiguous/options.json b/packages/babel-parser/test/fixtures/typescript/export/equals-in-unambiguous/options.json new file mode 100644 index 000000000000..196eb8690cea --- /dev/null +++ b/packages/babel-parser/test/fixtures/typescript/export/equals-in-unambiguous/options.json @@ -0,0 +1,3 @@ +{ + "sourceType": "unambiguous" +} \ No newline at end of file diff --git a/packages/babel-parser/test/fixtures/typescript/export/equals-in-unambiguous/output.json b/packages/babel-parser/test/fixtures/typescript/export/equals-in-unambiguous/output.json new file mode 100644 index 000000000000..4435b69c7622 --- /dev/null +++ b/packages/babel-parser/test/fixtures/typescript/export/equals-in-unambiguous/output.json @@ -0,0 +1,22 @@ +{ + "type": "File", + "start":0,"end":11,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":1,"column":11,"index":11}}, + "program": { + "type": "Program", + "start":0,"end":11,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":1,"column":11,"index":11}}, + "sourceType": "script", + "interpreter": null, + "body": [ + { + "type": "TSExportAssignment", + "start":0,"end":11,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":1,"column":11,"index":11}}, + "expression": { + "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" + } + } + ], + "directives": [] + } +} diff --git a/packages/babel-parser/test/fixtures/typescript/import/equals-in-script/input.ts b/packages/babel-parser/test/fixtures/typescript/import/equals-in-script/input.ts new file mode 100644 index 000000000000..4e414cfa827e --- /dev/null +++ b/packages/babel-parser/test/fixtures/typescript/import/equals-in-script/input.ts @@ -0,0 +1 @@ +import A = B.C; diff --git a/packages/babel-parser/test/fixtures/typescript/import/equals-in-script/options.json b/packages/babel-parser/test/fixtures/typescript/import/equals-in-script/options.json new file mode 100644 index 000000000000..514f1ad398bf --- /dev/null +++ b/packages/babel-parser/test/fixtures/typescript/import/equals-in-script/options.json @@ -0,0 +1,3 @@ +{ + "sourceType": "script" +} diff --git a/packages/babel-parser/test/fixtures/typescript/import/equals-in-script/output.json b/packages/babel-parser/test/fixtures/typescript/import/equals-in-script/output.json new file mode 100644 index 000000000000..f89c0c3c37b3 --- /dev/null +++ b/packages/babel-parser/test/fixtures/typescript/import/equals-in-script/output.json @@ -0,0 +1,38 @@ +{ + "type": "File", + "start":0,"end":15,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":1,"column":15,"index":15}}, + "program": { + "type": "Program", + "start":0,"end":15,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":1,"column":15,"index":15}}, + "sourceType": "script", + "interpreter": null, + "body": [ + { + "type": "TSImportEqualsDeclaration", + "start":0,"end":15,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":1,"column":15,"index":15}}, + "importKind": "value", + "isExport": false, + "id": { + "type": "Identifier", + "start":7,"end":8,"loc":{"start":{"line":1,"column":7,"index":7},"end":{"line":1,"column":8,"index":8},"identifierName":"A"}, + "name": "A" + }, + "moduleReference": { + "type": "TSQualifiedName", + "start":11,"end":14,"loc":{"start":{"line":1,"column":11,"index":11},"end":{"line":1,"column":14,"index":14}}, + "left": { + "type": "Identifier", + "start":11,"end":12,"loc":{"start":{"line":1,"column":11,"index":11},"end":{"line":1,"column":12,"index":12},"identifierName":"B"}, + "name": "B" + }, + "right": { + "type": "Identifier", + "start":13,"end":14,"loc":{"start":{"line":1,"column":13,"index":13},"end":{"line":1,"column":14,"index":14},"identifierName":"C"}, + "name": "C" + } + } + } + ], + "directives": [] + } +} diff --git a/packages/babel-parser/test/fixtures/typescript/import/equals-in-unambiguous/input.ts b/packages/babel-parser/test/fixtures/typescript/import/equals-in-unambiguous/input.ts new file mode 100644 index 000000000000..4e414cfa827e --- /dev/null +++ b/packages/babel-parser/test/fixtures/typescript/import/equals-in-unambiguous/input.ts @@ -0,0 +1 @@ +import A = B.C; diff --git a/packages/babel-parser/test/fixtures/typescript/import/equals-in-unambiguous/options.json b/packages/babel-parser/test/fixtures/typescript/import/equals-in-unambiguous/options.json new file mode 100644 index 000000000000..db909ceb87b3 --- /dev/null +++ b/packages/babel-parser/test/fixtures/typescript/import/equals-in-unambiguous/options.json @@ -0,0 +1,3 @@ +{ + "sourceType": "unambiguous" +} diff --git a/packages/babel-parser/test/fixtures/typescript/import/equals-in-unambiguous/output.json b/packages/babel-parser/test/fixtures/typescript/import/equals-in-unambiguous/output.json new file mode 100644 index 000000000000..f89c0c3c37b3 --- /dev/null +++ b/packages/babel-parser/test/fixtures/typescript/import/equals-in-unambiguous/output.json @@ -0,0 +1,38 @@ +{ + "type": "File", + "start":0,"end":15,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":1,"column":15,"index":15}}, + "program": { + "type": "Program", + "start":0,"end":15,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":1,"column":15,"index":15}}, + "sourceType": "script", + "interpreter": null, + "body": [ + { + "type": "TSImportEqualsDeclaration", + "start":0,"end":15,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":1,"column":15,"index":15}}, + "importKind": "value", + "isExport": false, + "id": { + "type": "Identifier", + "start":7,"end":8,"loc":{"start":{"line":1,"column":7,"index":7},"end":{"line":1,"column":8,"index":8},"identifierName":"A"}, + "name": "A" + }, + "moduleReference": { + "type": "TSQualifiedName", + "start":11,"end":14,"loc":{"start":{"line":1,"column":11,"index":11},"end":{"line":1,"column":14,"index":14}}, + "left": { + "type": "Identifier", + "start":11,"end":12,"loc":{"start":{"line":1,"column":11,"index":11},"end":{"line":1,"column":12,"index":12},"identifierName":"B"}, + "name": "B" + }, + "right": { + "type": "Identifier", + "start":13,"end":14,"loc":{"start":{"line":1,"column":13,"index":13},"end":{"line":1,"column":14,"index":14},"identifierName":"C"}, + "name": "C" + } + } + } + ], + "directives": [] + } +} diff --git a/packages/babel-parser/test/fixtures/typescript/import/equals-require-in-script/input.ts b/packages/babel-parser/test/fixtures/typescript/import/equals-require-in-script/input.ts new file mode 100644 index 000000000000..2c82fffdd91a --- /dev/null +++ b/packages/babel-parser/test/fixtures/typescript/import/equals-require-in-script/input.ts @@ -0,0 +1 @@ +import a = require("a"); diff --git a/packages/babel-parser/test/fixtures/typescript/import/equals-require-in-script/options.json b/packages/babel-parser/test/fixtures/typescript/import/equals-require-in-script/options.json new file mode 100644 index 000000000000..514f1ad398bf --- /dev/null +++ b/packages/babel-parser/test/fixtures/typescript/import/equals-require-in-script/options.json @@ -0,0 +1,3 @@ +{ + "sourceType": "script" +} diff --git a/packages/babel-parser/test/fixtures/typescript/import/equals-require-in-script/output.json b/packages/babel-parser/test/fixtures/typescript/import/equals-require-in-script/output.json new file mode 100644 index 000000000000..8a8fdd743052 --- /dev/null +++ b/packages/babel-parser/test/fixtures/typescript/import/equals-require-in-script/output.json @@ -0,0 +1,37 @@ +{ + "type": "File", + "start":0,"end":24,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":1,"column":24,"index":24}}, + "program": { + "type": "Program", + "start":0,"end":24,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":1,"column":24,"index":24}}, + "sourceType": "script", + "interpreter": null, + "body": [ + { + "type": "TSImportEqualsDeclaration", + "start":0,"end":24,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":1,"column":24,"index":24}}, + "importKind": "value", + "isExport": false, + "id": { + "type": "Identifier", + "start":7,"end":8,"loc":{"start":{"line":1,"column":7,"index":7},"end":{"line":1,"column":8,"index":8},"identifierName":"a"}, + "name": "a" + }, + "moduleReference": { + "type": "TSExternalModuleReference", + "start":11,"end":23,"loc":{"start":{"line":1,"column":11,"index":11},"end":{"line":1,"column":23,"index":23}}, + "expression": { + "type": "StringLiteral", + "start":19,"end":22,"loc":{"start":{"line":1,"column":19,"index":19},"end":{"line":1,"column":22,"index":22}}, + "extra": { + "rawValue": "a", + "raw": "\"a\"" + }, + "value": "a" + } + } + } + ], + "directives": [] + } +} diff --git a/packages/babel-parser/test/fixtures/typescript/import/equals-require-in-unambiguous/input.ts b/packages/babel-parser/test/fixtures/typescript/import/equals-require-in-unambiguous/input.ts new file mode 100644 index 000000000000..2c82fffdd91a --- /dev/null +++ b/packages/babel-parser/test/fixtures/typescript/import/equals-require-in-unambiguous/input.ts @@ -0,0 +1 @@ +import a = require("a"); diff --git a/packages/babel-parser/test/fixtures/typescript/import/equals-require-in-unambiguous/options.json b/packages/babel-parser/test/fixtures/typescript/import/equals-require-in-unambiguous/options.json new file mode 100644 index 000000000000..db909ceb87b3 --- /dev/null +++ b/packages/babel-parser/test/fixtures/typescript/import/equals-require-in-unambiguous/options.json @@ -0,0 +1,3 @@ +{ + "sourceType": "unambiguous" +} diff --git a/packages/babel-parser/test/fixtures/typescript/import/equals-require-in-unambiguous/output.json b/packages/babel-parser/test/fixtures/typescript/import/equals-require-in-unambiguous/output.json new file mode 100644 index 000000000000..8a8fdd743052 --- /dev/null +++ b/packages/babel-parser/test/fixtures/typescript/import/equals-require-in-unambiguous/output.json @@ -0,0 +1,37 @@ +{ + "type": "File", + "start":0,"end":24,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":1,"column":24,"index":24}}, + "program": { + "type": "Program", + "start":0,"end":24,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":1,"column":24,"index":24}}, + "sourceType": "script", + "interpreter": null, + "body": [ + { + "type": "TSImportEqualsDeclaration", + "start":0,"end":24,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":1,"column":24,"index":24}}, + "importKind": "value", + "isExport": false, + "id": { + "type": "Identifier", + "start":7,"end":8,"loc":{"start":{"line":1,"column":7,"index":7},"end":{"line":1,"column":8,"index":8},"identifierName":"a"}, + "name": "a" + }, + "moduleReference": { + "type": "TSExternalModuleReference", + "start":11,"end":23,"loc":{"start":{"line":1,"column":11,"index":11},"end":{"line":1,"column":23,"index":23}}, + "expression": { + "type": "StringLiteral", + "start":19,"end":22,"loc":{"start":{"line":1,"column":19,"index":19},"end":{"line":1,"column":22,"index":22}}, + "extra": { + "rawValue": "a", + "raw": "\"a\"" + }, + "value": "a" + } + } + } + ], + "directives": [] + } +} From fb30f90c11cef61c5f4cb8efece78170af427a1a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Ribaudo?= Date: Wed, 15 Mar 2023 10:43:42 +0100 Subject: [PATCH 2/3] [ts] Support `import ... =` and `export =` in scripts --- .../src/index.ts | 58 +++++++++++++------ .../fixtures/exports/export=-script/input.ts | 1 + .../exports/export=-script/options.json | 3 + .../fixtures/exports/export=-script/output.js | 1 + .../fixtures/exports/export=/options.json | 2 +- .../{import= => import=-module}/input.ts | 0 .../imports/import=-module/options.json | 4 ++ .../fixtures/imports/import=-script/input.ts | 2 + .../imports/import=-script/options.json | 3 + .../fixtures/imports/import=-script/output.js | 2 + .../fixtures/imports/import=/options.json | 3 - 11 files changed, 58 insertions(+), 21 deletions(-) create mode 100644 packages/babel-plugin-transform-typescript/test/fixtures/exports/export=-script/input.ts create mode 100644 packages/babel-plugin-transform-typescript/test/fixtures/exports/export=-script/options.json create mode 100644 packages/babel-plugin-transform-typescript/test/fixtures/exports/export=-script/output.js rename packages/babel-plugin-transform-typescript/test/fixtures/imports/{import= => import=-module}/input.ts (100%) create mode 100644 packages/babel-plugin-transform-typescript/test/fixtures/imports/import=-module/options.json create mode 100644 packages/babel-plugin-transform-typescript/test/fixtures/imports/import=-script/input.ts create mode 100644 packages/babel-plugin-transform-typescript/test/fixtures/imports/import=-script/options.json create mode 100644 packages/babel-plugin-transform-typescript/test/fixtures/imports/import=-script/output.js delete mode 100644 packages/babel-plugin-transform-typescript/test/fixtures/imports/import=/options.json diff --git a/packages/babel-plugin-transform-typescript/src/index.ts b/packages/babel-plugin-transform-typescript/src/index.ts index 7913e0b78f9d..bcb9f6c7ff20 100644 --- a/packages/babel-plugin-transform-typescript/src/index.ts +++ b/packages/babel-plugin-transform-typescript/src/index.ts @@ -78,6 +78,21 @@ function safeRemove(path: NodePath) { path.opts.noScope = false; } +function assertCjsModuleIsScript( + path: NodePath, + wrong: string, + suggestion: string, + extra: string = "", +): void { + const programParent = path.find(p => p.isProgram()) as NodePath; + if (programParent.node.sourceType !== "script") { + throw path.buildCodeFrameError( + `\`${wrong}\` is only supported when "sourceType" is "script".\n` + + `Please consider using \`${suggestion}\`${extra}.`, + ); + } +} + export interface Options extends SyntaxOptions { /** @default true */ allowNamespaces?: boolean; @@ -575,33 +590,42 @@ export default declare((api, opts: Options) => { }, TSImportEqualsDeclaration(path: NodePath) { - if (t.isTSExternalModuleReference(path.node.moduleReference)) { + const { id, moduleReference } = path.node; + + let init: t.Expression; + let varKind: "var" | "const"; + if (t.isTSExternalModuleReference(moduleReference)) { // import alias = require('foo'); - throw path.buildCodeFrameError( - `\`import ${path.node.id.name} = require('${path.node.moduleReference.expression.value}')\` ` + - "is not supported by @babel/plugin-transform-typescript\n" + - "Please consider using " + - `\`import ${path.node.id.name} from '${path.node.moduleReference.expression.value}';\` alongside ` + - "Typescript's --allowSyntheticDefaultImports option.", + assertCjsModuleIsScript( + path, + `import ${id.name} = require(...);`, + `import ${id.name} from '...';`, + " alongside Typescript's --allowSyntheticDefaultImports option", ); + init = t.callExpression(t.identifier("require"), [ + moduleReference.expression, + ]); + varKind = "const"; + } else { + // import alias = Namespace; + init = entityNameToExpr(moduleReference); + varKind = "var"; } - // import alias = Namespace; path.replaceWith( - t.variableDeclaration("var", [ - t.variableDeclarator( - path.node.id, - entityNameToExpr(path.node.moduleReference), - ), - ]), + t.variableDeclaration(varKind, [t.variableDeclarator(id, init)]), ); path.scope.registerDeclaration(path); }, TSExportAssignment(path) { - throw path.buildCodeFrameError( - "`export =` is not supported by @babel/plugin-transform-typescript\n" + - "Please consider using `export ;`.", + assertCjsModuleIsScript( + path, + `export = ;`, + `export default ;`, + ); + path.replaceWith( + template.statement.ast`module.exports = ${path.node.expression}`, ); }, diff --git a/packages/babel-plugin-transform-typescript/test/fixtures/exports/export=-script/input.ts b/packages/babel-plugin-transform-typescript/test/fixtures/exports/export=-script/input.ts new file mode 100644 index 000000000000..fbedae645eb3 --- /dev/null +++ b/packages/babel-plugin-transform-typescript/test/fixtures/exports/export=-script/input.ts @@ -0,0 +1 @@ +export = 0; \ No newline at end of file diff --git a/packages/babel-plugin-transform-typescript/test/fixtures/exports/export=-script/options.json b/packages/babel-plugin-transform-typescript/test/fixtures/exports/export=-script/options.json new file mode 100644 index 000000000000..b412ffe6712f --- /dev/null +++ b/packages/babel-plugin-transform-typescript/test/fixtures/exports/export=-script/options.json @@ -0,0 +1,3 @@ +{ + "sourceType": "script" +} diff --git a/packages/babel-plugin-transform-typescript/test/fixtures/exports/export=-script/output.js b/packages/babel-plugin-transform-typescript/test/fixtures/exports/export=-script/output.js new file mode 100644 index 000000000000..d5b2e8bb3efb --- /dev/null +++ b/packages/babel-plugin-transform-typescript/test/fixtures/exports/export=-script/output.js @@ -0,0 +1 @@ +module.exports = 0; diff --git a/packages/babel-plugin-transform-typescript/test/fixtures/exports/export=/options.json b/packages/babel-plugin-transform-typescript/test/fixtures/exports/export=/options.json index 9ba7cc5c5f3a..e2376e518413 100644 --- a/packages/babel-plugin-transform-typescript/test/fixtures/exports/export=/options.json +++ b/packages/babel-plugin-transform-typescript/test/fixtures/exports/export=/options.json @@ -1,3 +1,3 @@ { - "throws": "`export =` is not supported by @babel/plugin-transform-typescript\nPlease consider using `export ;`." + "throws": "`export = ;` is only supported when \"sourceType\" is \"script\".\nPlease consider using `export default ;`" } diff --git a/packages/babel-plugin-transform-typescript/test/fixtures/imports/import=/input.ts b/packages/babel-plugin-transform-typescript/test/fixtures/imports/import=-module/input.ts similarity index 100% rename from packages/babel-plugin-transform-typescript/test/fixtures/imports/import=/input.ts rename to packages/babel-plugin-transform-typescript/test/fixtures/imports/import=-module/input.ts diff --git a/packages/babel-plugin-transform-typescript/test/fixtures/imports/import=-module/options.json b/packages/babel-plugin-transform-typescript/test/fixtures/imports/import=-module/options.json new file mode 100644 index 000000000000..8f13c717fc76 --- /dev/null +++ b/packages/babel-plugin-transform-typescript/test/fixtures/imports/import=-module/options.json @@ -0,0 +1,4 @@ +{ + "sourceType": "module", + "throws": "`import lib = require(...);` is only supported when \"sourceType\" is \"script\".\nPlease consider using `import lib from '...';` alongside Typescript's --allowSyntheticDefaultImports option." +} diff --git a/packages/babel-plugin-transform-typescript/test/fixtures/imports/import=-script/input.ts b/packages/babel-plugin-transform-typescript/test/fixtures/imports/import=-script/input.ts new file mode 100644 index 000000000000..dc8b049669b3 --- /dev/null +++ b/packages/babel-plugin-transform-typescript/test/fixtures/imports/import=-script/input.ts @@ -0,0 +1,2 @@ +import lib = require("lib"); +lib(); diff --git a/packages/babel-plugin-transform-typescript/test/fixtures/imports/import=-script/options.json b/packages/babel-plugin-transform-typescript/test/fixtures/imports/import=-script/options.json new file mode 100644 index 000000000000..b412ffe6712f --- /dev/null +++ b/packages/babel-plugin-transform-typescript/test/fixtures/imports/import=-script/options.json @@ -0,0 +1,3 @@ +{ + "sourceType": "script" +} diff --git a/packages/babel-plugin-transform-typescript/test/fixtures/imports/import=-script/output.js b/packages/babel-plugin-transform-typescript/test/fixtures/imports/import=-script/output.js new file mode 100644 index 000000000000..2ddbce589436 --- /dev/null +++ b/packages/babel-plugin-transform-typescript/test/fixtures/imports/import=-script/output.js @@ -0,0 +1,2 @@ +const lib = require("lib"); +lib(); diff --git a/packages/babel-plugin-transform-typescript/test/fixtures/imports/import=/options.json b/packages/babel-plugin-transform-typescript/test/fixtures/imports/import=/options.json deleted file mode 100644 index fc8cd41e40a3..000000000000 --- a/packages/babel-plugin-transform-typescript/test/fixtures/imports/import=/options.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "throws": "`import lib = require('lib')` is not supported by @babel/plugin-transform-typescript\nPlease consider using `import lib from 'lib';` alongside Typescript's --allowSyntheticDefaultImports option." -} From 1f1e9db04069ed933f80e67f611b59523244c4dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Ribaudo?= Date: Thu, 30 Mar 2023 19:06:39 +0200 Subject: [PATCH 3/3] Align behavior with TS --- .../src/plugins/typescript/index.ts | 14 ++-------- .../export/equals-in-script/output.json | 3 +++ .../export/equals-in-unambiguous/output.json | 2 +- .../import/equals-in-script/output.json | 3 +++ .../equals-require-in-script/output.json | 3 +++ .../equals-require-in-unambiguous/output.json | 2 +- .../src/index.ts | 26 ++++++++++++------- .../exports/export=-script/options.json | 3 --- .../input.ts | 0 .../exports/export=-to-cjs/options.json | 4 +++ .../output.js | 2 ++ .../fixtures/exports/export=/options.json | 2 +- .../input.ts | 0 .../import=-module-to-cjs/options.json | 4 +++ .../output.js | 2 ++ .../imports/import=-module/options.json | 2 +- .../imports/import=-script/options.json | 3 --- 17 files changed, 43 insertions(+), 32 deletions(-) delete mode 100644 packages/babel-plugin-transform-typescript/test/fixtures/exports/export=-script/options.json rename packages/babel-plugin-transform-typescript/test/fixtures/exports/{export=-script => export=-to-cjs}/input.ts (100%) create mode 100644 packages/babel-plugin-transform-typescript/test/fixtures/exports/export=-to-cjs/options.json rename packages/babel-plugin-transform-typescript/test/fixtures/exports/{export=-script => export=-to-cjs}/output.js (57%) rename packages/babel-plugin-transform-typescript/test/fixtures/imports/{import=-script => import=-module-to-cjs}/input.ts (100%) create mode 100644 packages/babel-plugin-transform-typescript/test/fixtures/imports/import=-module-to-cjs/options.json rename packages/babel-plugin-transform-typescript/test/fixtures/imports/{import=-script => import=-module-to-cjs}/output.js (70%) delete mode 100644 packages/babel-plugin-transform-typescript/test/fixtures/imports/import=-script/options.json diff --git a/packages/babel-parser/src/plugins/typescript/index.ts b/packages/babel-parser/src/plugins/typescript/index.ts index df97882b7729..665df7ab23f3 100644 --- a/packages/babel-parser/src/plugins/typescript/index.ts +++ b/packages/babel-parser/src/plugins/typescript/index.ts @@ -2017,6 +2017,7 @@ export default (superClass: ClassWithMixin) => // For compatibility to estree we cannot call parseLiteral directly here node.expression = super.parseExprAtom() as N.StringLiteral; this.expect(tt.parenR); + this.sawUnambiguousESM = true; return this.finishNode(node, "TSExternalModuleReference"); } @@ -2711,18 +2712,6 @@ export default (superClass: ClassWithMixin) => */ checkDuplicateExports() {} - assertModuleNodeAllowed(node: N.Node): void { - if ( - node.type === "TSImportEqualsDeclaration" || - node.type === "TSExportAssignment" - ) { - // `import ... =` and `export =` are allowed in scripts, - // since they are used for CommonJS. - return; - } - super.assertModuleNodeAllowed(node); - } - parseImport( node: Undone, ): N.AnyImport { @@ -2800,6 +2789,7 @@ export default (superClass: ClassWithMixin) => const assign = node as Undone; assign.expression = super.parseExpression(); this.semicolon(); + this.sawUnambiguousESM = true; return this.finishNode(assign, "TSExportAssignment"); } else if (this.eatContextual(tt._as)) { // `export as namespace A;` diff --git a/packages/babel-parser/test/fixtures/typescript/export/equals-in-script/output.json b/packages/babel-parser/test/fixtures/typescript/export/equals-in-script/output.json index 4435b69c7622..a49b3540c5dd 100644 --- a/packages/babel-parser/test/fixtures/typescript/export/equals-in-script/output.json +++ b/packages/babel-parser/test/fixtures/typescript/export/equals-in-script/output.json @@ -1,6 +1,9 @@ { "type": "File", "start":0,"end":11,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":1,"column":11,"index":11}}, + "errors": [ + "SyntaxError: 'import' and 'export' may appear only with 'sourceType: \"module\"' (1:0)" + ], "program": { "type": "Program", "start":0,"end":11,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":1,"column":11,"index":11}}, diff --git a/packages/babel-parser/test/fixtures/typescript/export/equals-in-unambiguous/output.json b/packages/babel-parser/test/fixtures/typescript/export/equals-in-unambiguous/output.json index 4435b69c7622..9f13e9e0bae5 100644 --- a/packages/babel-parser/test/fixtures/typescript/export/equals-in-unambiguous/output.json +++ b/packages/babel-parser/test/fixtures/typescript/export/equals-in-unambiguous/output.json @@ -4,7 +4,7 @@ "program": { "type": "Program", "start":0,"end":11,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":1,"column":11,"index":11}}, - "sourceType": "script", + "sourceType": "module", "interpreter": null, "body": [ { diff --git a/packages/babel-parser/test/fixtures/typescript/import/equals-in-script/output.json b/packages/babel-parser/test/fixtures/typescript/import/equals-in-script/output.json index f89c0c3c37b3..6d116ee43624 100644 --- a/packages/babel-parser/test/fixtures/typescript/import/equals-in-script/output.json +++ b/packages/babel-parser/test/fixtures/typescript/import/equals-in-script/output.json @@ -1,6 +1,9 @@ { "type": "File", "start":0,"end":15,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":1,"column":15,"index":15}}, + "errors": [ + "SyntaxError: 'import' and 'export' may appear only with 'sourceType: \"module\"' (1:0)" + ], "program": { "type": "Program", "start":0,"end":15,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":1,"column":15,"index":15}}, diff --git a/packages/babel-parser/test/fixtures/typescript/import/equals-require-in-script/output.json b/packages/babel-parser/test/fixtures/typescript/import/equals-require-in-script/output.json index 8a8fdd743052..1d87684dbe32 100644 --- a/packages/babel-parser/test/fixtures/typescript/import/equals-require-in-script/output.json +++ b/packages/babel-parser/test/fixtures/typescript/import/equals-require-in-script/output.json @@ -1,6 +1,9 @@ { "type": "File", "start":0,"end":24,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":1,"column":24,"index":24}}, + "errors": [ + "SyntaxError: 'import' and 'export' may appear only with 'sourceType: \"module\"' (1:0)" + ], "program": { "type": "Program", "start":0,"end":24,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":1,"column":24,"index":24}}, diff --git a/packages/babel-parser/test/fixtures/typescript/import/equals-require-in-unambiguous/output.json b/packages/babel-parser/test/fixtures/typescript/import/equals-require-in-unambiguous/output.json index 8a8fdd743052..19b29f5d027f 100644 --- a/packages/babel-parser/test/fixtures/typescript/import/equals-require-in-unambiguous/output.json +++ b/packages/babel-parser/test/fixtures/typescript/import/equals-require-in-unambiguous/output.json @@ -4,7 +4,7 @@ "program": { "type": "Program", "start":0,"end":24,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":1,"column":24,"index":24}}, - "sourceType": "script", + "sourceType": "module", "interpreter": null, "body": [ { diff --git a/packages/babel-plugin-transform-typescript/src/index.ts b/packages/babel-plugin-transform-typescript/src/index.ts index bcb9f6c7ff20..ee1262a9eb43 100644 --- a/packages/babel-plugin-transform-typescript/src/index.ts +++ b/packages/babel-plugin-transform-typescript/src/index.ts @@ -1,6 +1,6 @@ import { declare } from "@babel/helper-plugin-utils"; import syntaxTypeScript from "@babel/plugin-syntax-typescript"; -import type { types as t } from "@babel/core"; +import type { PluginPass, types as t } from "@babel/core"; import { injectInitialization } from "@babel/helper-create-class-features-plugin"; import type { Binding, NodePath, Scope } from "@babel/traverse"; import type { Options as SyntaxOptions } from "@babel/plugin-syntax-typescript"; @@ -78,17 +78,18 @@ function safeRemove(path: NodePath) { path.opts.noScope = false; } -function assertCjsModuleIsScript( +function assertCjsTransformEnabled( path: NodePath, + pass: PluginPass, wrong: string, suggestion: string, extra: string = "", ): void { - const programParent = path.find(p => p.isProgram()) as NodePath; - if (programParent.node.sourceType !== "script") { + if (pass.file.get("@babel/plugin-transform-modules-*") !== "commonjs") { throw path.buildCodeFrameError( - `\`${wrong}\` is only supported when "sourceType" is "script".\n` + - `Please consider using \`${suggestion}\`${extra}.`, + `\`${wrong}\` is only supported when compiling modules to CommonJS.\n` + + `Please consider using \`${suggestion}\`${extra}, or add ` + + `@babel/plugin-transform-modules-commonjs to your Babel config.`, ); } } @@ -589,15 +590,19 @@ export default declare((api, opts: Options) => { } }, - TSImportEqualsDeclaration(path: NodePath) { + TSImportEqualsDeclaration( + path: NodePath, + pass, + ) { const { id, moduleReference } = path.node; let init: t.Expression; let varKind: "var" | "const"; if (t.isTSExternalModuleReference(moduleReference)) { // import alias = require('foo'); - assertCjsModuleIsScript( + assertCjsTransformEnabled( path, + pass, `import ${id.name} = require(...);`, `import ${id.name} from '...';`, " alongside Typescript's --allowSyntheticDefaultImports option", @@ -618,9 +623,10 @@ export default declare((api, opts: Options) => { path.scope.registerDeclaration(path); }, - TSExportAssignment(path) { - assertCjsModuleIsScript( + TSExportAssignment(path, pass) { + assertCjsTransformEnabled( path, + pass, `export = ;`, `export default ;`, ); diff --git a/packages/babel-plugin-transform-typescript/test/fixtures/exports/export=-script/options.json b/packages/babel-plugin-transform-typescript/test/fixtures/exports/export=-script/options.json deleted file mode 100644 index b412ffe6712f..000000000000 --- a/packages/babel-plugin-transform-typescript/test/fixtures/exports/export=-script/options.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "sourceType": "script" -} diff --git a/packages/babel-plugin-transform-typescript/test/fixtures/exports/export=-script/input.ts b/packages/babel-plugin-transform-typescript/test/fixtures/exports/export=-to-cjs/input.ts similarity index 100% rename from packages/babel-plugin-transform-typescript/test/fixtures/exports/export=-script/input.ts rename to packages/babel-plugin-transform-typescript/test/fixtures/exports/export=-to-cjs/input.ts diff --git a/packages/babel-plugin-transform-typescript/test/fixtures/exports/export=-to-cjs/options.json b/packages/babel-plugin-transform-typescript/test/fixtures/exports/export=-to-cjs/options.json new file mode 100644 index 000000000000..63658e075fb1 --- /dev/null +++ b/packages/babel-plugin-transform-typescript/test/fixtures/exports/export=-to-cjs/options.json @@ -0,0 +1,4 @@ +{ + "plugins": ["transform-typescript", "transform-modules-commonjs"], + "sourceType": "module" +} diff --git a/packages/babel-plugin-transform-typescript/test/fixtures/exports/export=-script/output.js b/packages/babel-plugin-transform-typescript/test/fixtures/exports/export=-to-cjs/output.js similarity index 57% rename from packages/babel-plugin-transform-typescript/test/fixtures/exports/export=-script/output.js rename to packages/babel-plugin-transform-typescript/test/fixtures/exports/export=-to-cjs/output.js index d5b2e8bb3efb..92ffe35d3a39 100644 --- a/packages/babel-plugin-transform-typescript/test/fixtures/exports/export=-script/output.js +++ b/packages/babel-plugin-transform-typescript/test/fixtures/exports/export=-to-cjs/output.js @@ -1 +1,3 @@ +"use strict"; + module.exports = 0; diff --git a/packages/babel-plugin-transform-typescript/test/fixtures/exports/export=/options.json b/packages/babel-plugin-transform-typescript/test/fixtures/exports/export=/options.json index e2376e518413..a4af08a4d481 100644 --- a/packages/babel-plugin-transform-typescript/test/fixtures/exports/export=/options.json +++ b/packages/babel-plugin-transform-typescript/test/fixtures/exports/export=/options.json @@ -1,3 +1,3 @@ { - "throws": "`export = ;` is only supported when \"sourceType\" is \"script\".\nPlease consider using `export default ;`" + "throws": "`export = ;` is only supported when compiling modules to CommonJS.\nPlease consider using `export default ;`, or add @babel/plugin-transform-modules-commonjs to your Babel config." } diff --git a/packages/babel-plugin-transform-typescript/test/fixtures/imports/import=-script/input.ts b/packages/babel-plugin-transform-typescript/test/fixtures/imports/import=-module-to-cjs/input.ts similarity index 100% rename from packages/babel-plugin-transform-typescript/test/fixtures/imports/import=-script/input.ts rename to packages/babel-plugin-transform-typescript/test/fixtures/imports/import=-module-to-cjs/input.ts diff --git a/packages/babel-plugin-transform-typescript/test/fixtures/imports/import=-module-to-cjs/options.json b/packages/babel-plugin-transform-typescript/test/fixtures/imports/import=-module-to-cjs/options.json new file mode 100644 index 000000000000..63658e075fb1 --- /dev/null +++ b/packages/babel-plugin-transform-typescript/test/fixtures/imports/import=-module-to-cjs/options.json @@ -0,0 +1,4 @@ +{ + "plugins": ["transform-typescript", "transform-modules-commonjs"], + "sourceType": "module" +} diff --git a/packages/babel-plugin-transform-typescript/test/fixtures/imports/import=-script/output.js b/packages/babel-plugin-transform-typescript/test/fixtures/imports/import=-module-to-cjs/output.js similarity index 70% rename from packages/babel-plugin-transform-typescript/test/fixtures/imports/import=-script/output.js rename to packages/babel-plugin-transform-typescript/test/fixtures/imports/import=-module-to-cjs/output.js index 2ddbce589436..c1220e59684f 100644 --- a/packages/babel-plugin-transform-typescript/test/fixtures/imports/import=-script/output.js +++ b/packages/babel-plugin-transform-typescript/test/fixtures/imports/import=-module-to-cjs/output.js @@ -1,2 +1,4 @@ +"use strict"; + const lib = require("lib"); lib(); diff --git a/packages/babel-plugin-transform-typescript/test/fixtures/imports/import=-module/options.json b/packages/babel-plugin-transform-typescript/test/fixtures/imports/import=-module/options.json index 8f13c717fc76..eb23daa9d797 100644 --- a/packages/babel-plugin-transform-typescript/test/fixtures/imports/import=-module/options.json +++ b/packages/babel-plugin-transform-typescript/test/fixtures/imports/import=-module/options.json @@ -1,4 +1,4 @@ { "sourceType": "module", - "throws": "`import lib = require(...);` is only supported when \"sourceType\" is \"script\".\nPlease consider using `import lib from '...';` alongside Typescript's --allowSyntheticDefaultImports option." + "throws": "`import lib = require(...);` is only supported when compiling modules to CommonJS.\nPlease consider using `import lib from '...';` alongside Typescript's --allowSyntheticDefaultImports option, or add @babel/plugin-transform-modules-commonjs to your Babel config." } diff --git a/packages/babel-plugin-transform-typescript/test/fixtures/imports/import=-script/options.json b/packages/babel-plugin-transform-typescript/test/fixtures/imports/import=-script/options.json deleted file mode 100644 index b412ffe6712f..000000000000 --- a/packages/babel-plugin-transform-typescript/test/fixtures/imports/import=-script/options.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "sourceType": "script" -}