diff --git a/src/compiler/transformers/module/module.ts b/src/compiler/transformers/module/module.ts index 0d4e5b6864acf..aabc2bc45c18f 100644 --- a/src/compiler/transformers/module/module.ts +++ b/src/compiler/transformers/module/module.ts @@ -690,16 +690,36 @@ namespace ts { return createCall(createPropertyAccess(promiseResolveCall, "then"), /*typeArguments*/ undefined, [func]); } + function getNamedImportCount(node: ImportDeclaration) { + if (!(node.importClause && node.importClause.namedBindings)) return 0; + const names = node.importClause.namedBindings; + if (!names) return 0; + if (!isNamedImports(names)) return 0; + return names.elements.length; + } + + function containsDefaultReference(node: NamedImportBindings) { + if (!node) return false; + if (!isNamedImports(node)) return false; + return some(node.elements, isNamedDefaultReference); + } + + function isNamedDefaultReference(e: ImportSpecifier) { + return e.propertyName && e.propertyName.escapedText === InternalSymbolName.Default; + } function getHelperExpressionForImport(node: ImportDeclaration, innerExpr: Expression) { if (!compilerOptions.esModuleInterop || getEmitFlags(node) & EmitFlags.NeverApplyImportHelper) { return innerExpr; } - if (getNamespaceDeclarationNode(node)) { + const nameCount = getNamedImportCount(node); + const hasDefault = nameCount > 0 ? containsDefaultReference(node.importClause.namedBindings) : undefined; + + if (getNamespaceDeclarationNode(node) || (nameCount > 1 && hasDefault)) { context.requestEmitHelper(importStarHelper); return createCall(getHelperName("__importStar"), /*typeArguments*/ undefined, [innerExpr]); } - if (isDefaultImport(node)) { + if (isDefaultImport(node) || (nameCount === 1 && hasDefault)) { context.requestEmitHelper(importDefaultHelper); return createCall(getHelperName("__importDefault"), /*typeArguments*/ undefined, [innerExpr]); } diff --git a/tests/baselines/reference/esModuleInteropNamedDefaultImports.js b/tests/baselines/reference/esModuleInteropNamedDefaultImports.js new file mode 100644 index 0000000000000..d3a804b5e4ca7 --- /dev/null +++ b/tests/baselines/reference/esModuleInteropNamedDefaultImports.js @@ -0,0 +1,49 @@ +//// [tests/cases/compiler/esModuleInteropNamedDefaultImports.ts] //// + +//// [mod.ts] +export default class Foo {} +export class Bar {} +//// [idx.ts] +import Foo from "./mod"; +import { default as Foo2 } from "./mod"; +import { Bar, default as Foo3 } from "./mod"; +new Foo(); +new Foo2(); +new Bar(); +new Foo3(); + +//// [mod.js] +"use strict"; +exports.__esModule = true; +var Foo = /** @class */ (function () { + function Foo() { + } + return Foo; +}()); +exports["default"] = Foo; +var Bar = /** @class */ (function () { + function Bar() { + } + return Bar; +}()); +exports.Bar = Bar; +//// [idx.js] +"use strict"; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +} +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k]; + result["default"] = mod; + return result; +} +exports.__esModule = true; +var mod_1 = __importDefault(require("./mod")); +var mod_2 = __importDefault(require("./mod")); +var mod_3 = __importStar(require("./mod")); +new mod_1["default"](); +new mod_2["default"](); +new mod_3.Bar(); +new mod_3["default"](); diff --git a/tests/baselines/reference/esModuleInteropNamedDefaultImports.symbols b/tests/baselines/reference/esModuleInteropNamedDefaultImports.symbols new file mode 100644 index 0000000000000..5b84c591feafc --- /dev/null +++ b/tests/baselines/reference/esModuleInteropNamedDefaultImports.symbols @@ -0,0 +1,32 @@ +=== tests/cases/compiler/mod.ts === +export default class Foo {} +>Foo : Symbol(Foo, Decl(mod.ts, 0, 0)) + +export class Bar {} +>Bar : Symbol(Bar, Decl(mod.ts, 0, 27)) + +=== tests/cases/compiler/idx.ts === +import Foo from "./mod"; +>Foo : Symbol(Foo, Decl(idx.ts, 0, 6)) + +import { default as Foo2 } from "./mod"; +>default : Symbol(Foo2, Decl(idx.ts, 1, 8)) +>Foo2 : Symbol(Foo2, Decl(idx.ts, 1, 8)) + +import { Bar, default as Foo3 } from "./mod"; +>Bar : Symbol(Bar, Decl(idx.ts, 2, 8)) +>default : Symbol(Foo3, Decl(idx.ts, 2, 13)) +>Foo3 : Symbol(Foo3, Decl(idx.ts, 2, 13)) + +new Foo(); +>Foo : Symbol(Foo, Decl(idx.ts, 0, 6)) + +new Foo2(); +>Foo2 : Symbol(Foo2, Decl(idx.ts, 1, 8)) + +new Bar(); +>Bar : Symbol(Bar, Decl(idx.ts, 2, 8)) + +new Foo3(); +>Foo3 : Symbol(Foo3, Decl(idx.ts, 2, 13)) + diff --git a/tests/baselines/reference/esModuleInteropNamedDefaultImports.types b/tests/baselines/reference/esModuleInteropNamedDefaultImports.types new file mode 100644 index 0000000000000..3cc78be737d35 --- /dev/null +++ b/tests/baselines/reference/esModuleInteropNamedDefaultImports.types @@ -0,0 +1,36 @@ +=== tests/cases/compiler/mod.ts === +export default class Foo {} +>Foo : Foo + +export class Bar {} +>Bar : Bar + +=== tests/cases/compiler/idx.ts === +import Foo from "./mod"; +>Foo : typeof Foo + +import { default as Foo2 } from "./mod"; +>default : typeof Foo +>Foo2 : typeof Foo + +import { Bar, default as Foo3 } from "./mod"; +>Bar : typeof Bar +>default : typeof Foo +>Foo3 : typeof Foo + +new Foo(); +>new Foo() : Foo +>Foo : typeof Foo + +new Foo2(); +>new Foo2() : Foo +>Foo2 : typeof Foo + +new Bar(); +>new Bar() : Bar +>Bar : typeof Bar + +new Foo3(); +>new Foo3() : Foo +>Foo3 : typeof Foo + diff --git a/tests/cases/compiler/esModuleInteropNamedDefaultImports.ts b/tests/cases/compiler/esModuleInteropNamedDefaultImports.ts new file mode 100644 index 0000000000000..4f4a4922c33f2 --- /dev/null +++ b/tests/cases/compiler/esModuleInteropNamedDefaultImports.ts @@ -0,0 +1,13 @@ +// @module: commonjs +// @esModuleInterop: true +// @filename: mod.ts +export default class Foo {} +export class Bar {} +// @filename: idx.ts +import Foo from "./mod"; +import { default as Foo2 } from "./mod"; +import { Bar, default as Foo3 } from "./mod"; +new Foo(); +new Foo2(); +new Bar(); +new Foo3(); \ No newline at end of file