Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Flag default imports with named imports as needing importStar #23795

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 18 additions & 10 deletions src/compiler/transformers/utilities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,6 @@ namespace ts {
hasExportStarsToExportValues: boolean; // whether this module contains export*
}

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;
Expand All @@ -34,11 +26,27 @@ namespace ts {
}

export function getImportNeedsImportStarHelper(node: ImportDeclaration) {
return !!getNamespaceDeclarationNode(node) || (getNamedImportCount(node) > 1 && containsDefaultReference(node.importClause.namedBindings));
if (!!getNamespaceDeclarationNode(node)) {
return true;
}
const bindings = node.importClause && node.importClause.namedBindings;
if (!bindings) {
return false;
}
if (!isNamedImports(bindings)) return false;
let defaultRefCount = 0;
for (const binding of bindings.elements) {
if (isNamedDefaultReference(binding)) {
defaultRefCount++;
}
}
// Import star is required if there's default named refs mixed with non-default refs, or if theres non-default refs and it has a default import
return (defaultRefCount > 0 && defaultRefCount !== bindings.elements.length) || (!!(bindings.elements.length - defaultRefCount) && isDefaultImport(node));
}

export function getImportNeedsImportDefaultHelper(node: ImportDeclaration) {
return isDefaultImport(node) || (getNamedImportCount(node) === 1 && containsDefaultReference(node.importClause.namedBindings));
// Import default is needed if there's a default import or a default ref and no other refs (meaning an import star helper wasn't requested)
return !getImportNeedsImportStarHelper(node) && (isDefaultImport(node) || (node.importClause && isNamedImports(node.importClause.namedBindings) && containsDefaultReference(node.importClause.namedBindings)));
}

export function collectExternalModuleInfo(sourceFile: SourceFile, resolver: EmitResolver, compilerOptions: CompilerOptions): ExternalModuleInfo {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
tests/cases/compiler/esModuleInteropImportDefaultWhenAllNamedAreDefaultAlias.ts(1,42): error TS2307: Cannot find module 'm'.


==== tests/cases/compiler/esModuleInteropImportDefaultWhenAllNamedAreDefaultAlias.ts (1 errors) ====
import {default as a, default as b} from "m";
~~~
!!! error TS2307: Cannot find module 'm'.
void a;
void b;
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
//// [esModuleInteropImportDefaultWhenAllNamedAreDefaultAlias.ts]
import {default as a, default as b} from "m";
void a;
void b;

//// [esModuleInteropImportDefaultWhenAllNamedAreDefaultAlias.js]
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
exports.__esModule = true;
var m_1 = __importDefault(require("m"));
void m_1["default"];
void m_1["default"];
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
=== tests/cases/compiler/esModuleInteropImportDefaultWhenAllNamedAreDefaultAlias.ts ===
import {default as a, default as b} from "m";
>default : Symbol(a, Decl(esModuleInteropImportDefaultWhenAllNamedAreDefaultAlias.ts, 0, 8))
>a : Symbol(a, Decl(esModuleInteropImportDefaultWhenAllNamedAreDefaultAlias.ts, 0, 8))
>default : Symbol(b, Decl(esModuleInteropImportDefaultWhenAllNamedAreDefaultAlias.ts, 0, 21))
>b : Symbol(b, Decl(esModuleInteropImportDefaultWhenAllNamedAreDefaultAlias.ts, 0, 21))

void a;
>a : Symbol(a, Decl(esModuleInteropImportDefaultWhenAllNamedAreDefaultAlias.ts, 0, 8))

void b;
>b : Symbol(b, Decl(esModuleInteropImportDefaultWhenAllNamedAreDefaultAlias.ts, 0, 21))

Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
=== tests/cases/compiler/esModuleInteropImportDefaultWhenAllNamedAreDefaultAlias.ts ===
import {default as a, default as b} from "m";
>default : any
>a : any
>default : any
>b : any

void a;
>void a : undefined
>a : any

void b;
>void b : undefined
>b : any

Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
tests/cases/compiler/esModuleInteropUsesExportStarWhenDefaultPlusNames.ts(1,28): error TS2307: Cannot find module './dep'.


==== tests/cases/compiler/esModuleInteropUsesExportStarWhenDefaultPlusNames.ts (1 errors) ====
import Deps, { var2 } from './dep';
~~~~~~~
!!! error TS2307: Cannot find module './dep'.
void Deps;
void var2;
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
//// [esModuleInteropUsesExportStarWhenDefaultPlusNames.ts]
import Deps, { var2 } from './dep';
void Deps;
void var2;

//// [esModuleInteropUsesExportStarWhenDefaultPlusNames.js]
"use strict";
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 dep_1 = __importStar(require("./dep"));
void dep_1["default"];
void dep_1.var2;
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
=== tests/cases/compiler/esModuleInteropUsesExportStarWhenDefaultPlusNames.ts ===
import Deps, { var2 } from './dep';
>Deps : Symbol(Deps, Decl(esModuleInteropUsesExportStarWhenDefaultPlusNames.ts, 0, 6))
>var2 : Symbol(var2, Decl(esModuleInteropUsesExportStarWhenDefaultPlusNames.ts, 0, 14))

void Deps;
>Deps : Symbol(Deps, Decl(esModuleInteropUsesExportStarWhenDefaultPlusNames.ts, 0, 6))

void var2;
>var2 : Symbol(var2, Decl(esModuleInteropUsesExportStarWhenDefaultPlusNames.ts, 0, 14))

Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
=== tests/cases/compiler/esModuleInteropUsesExportStarWhenDefaultPlusNames.ts ===
import Deps, { var2 } from './dep';
>Deps : any
>var2 : any

void Deps;
>void Deps : undefined
>Deps : any

void var2;
>void var2 : undefined
>var2 : any

Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
// @esModuleInterop: true
import {default as a, default as b} from "m";
void a;
void b;
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
// @esModuleInterop: true
import Deps, { var2 } from './dep';
void Deps;
void var2;