Skip to content

Commit 1e7d089

Browse files
authored
Merge pull request #39490 from microsoft/fix37113
Fix namespace import/export helper usage under '--esModuleInterop'
2 parents 2c08aff + 5ad8532 commit 1e7d089

File tree

114 files changed

+2407
-43
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

114 files changed

+2407
-43
lines changed

src/compiler/checker.ts

+34-1
Original file line numberDiff line numberDiff line change
@@ -35258,6 +35258,12 @@ namespace ts {
3525835258
checkCollisionWithRequireExportsInGeneratedCode(node, node.name!);
3525935259
checkCollisionWithGlobalPromiseInGeneratedCode(node, node.name!);
3526035260
checkAliasSymbol(node);
35261+
if (node.kind === SyntaxKind.ImportSpecifier &&
35262+
idText(node.propertyName || node.name) === "default" &&
35263+
compilerOptions.esModuleInterop &&
35264+
moduleKind !== ModuleKind.System && moduleKind < ModuleKind.ES2015) {
35265+
checkExternalEmitHelpers(node, ExternalEmitHelpers.ImportDefault);
35266+
}
3526135267
}
3526235268

3526335269
function checkImportDeclaration(node: ImportDeclaration) {
@@ -35277,6 +35283,10 @@ namespace ts {
3527735283
if (importClause.namedBindings) {
3527835284
if (importClause.namedBindings.kind === SyntaxKind.NamespaceImport) {
3527935285
checkImportBinding(importClause.namedBindings);
35286+
if (moduleKind !== ModuleKind.System && moduleKind < ModuleKind.ES2015 && compilerOptions.esModuleInterop) {
35287+
// import * as ns from "foo";
35288+
checkExternalEmitHelpers(node, ExternalEmitHelpers.ImportStar);
35289+
}
3528035290
}
3528135291
else {
3528235292
const moduleExisted = resolveExternalModuleName(node, node.moduleSpecifier);
@@ -35287,6 +35297,7 @@ namespace ts {
3528735297
}
3528835298
}
3528935299
}
35300+
3529035301
}
3529135302

3529235303
function checkImportEqualsDeclaration(node: ImportEqualsDeclaration) {
@@ -35354,6 +35365,7 @@ namespace ts {
3535435365
}
3535535366
else {
3535635367
// export * from "foo"
35368+
// export * as ns from "foo";
3535735369
const moduleSymbol = resolveExternalModuleName(node, node.moduleSpecifier!);
3535835370
if (moduleSymbol && hasExportAssignmentSymbol(moduleSymbol)) {
3535935371
error(node.moduleSpecifier, Diagnostics.Module_0_uses_export_and_cannot_be_used_with_export_Asterisk, symbolToString(moduleSymbol));
@@ -35362,7 +35374,18 @@ namespace ts {
3536235374
checkAliasSymbol(node.exportClause);
3536335375
}
3536435376
if (moduleKind !== ModuleKind.System && moduleKind < ModuleKind.ES2015) {
35365-
checkExternalEmitHelpers(node, ExternalEmitHelpers.ExportStar);
35377+
if (node.exportClause) {
35378+
// export * as ns from "foo";
35379+
// For ES2015 modules, we emit it as a pair of `import * as a_1 ...; export { a_1 as ns }` and don't need the helper.
35380+
// We only use the helper here when in esModuleInterop
35381+
if (compilerOptions.esModuleInterop) {
35382+
checkExternalEmitHelpers(node, ExternalEmitHelpers.ImportStar);
35383+
}
35384+
}
35385+
else {
35386+
// export * from "foo"
35387+
checkExternalEmitHelpers(node, ExternalEmitHelpers.ExportStar);
35388+
}
3536635389
}
3536735390
}
3536835391
}
@@ -35434,6 +35457,14 @@ namespace ts {
3543435457
}
3543535458
}
3543635459
}
35460+
else {
35461+
if (compilerOptions.esModuleInterop &&
35462+
moduleKind !== ModuleKind.System &&
35463+
moduleKind < ModuleKind.ES2015 &&
35464+
idText(node.propertyName || node.name) === "default") {
35465+
checkExternalEmitHelpers(node, ExternalEmitHelpers.ImportDefault);
35466+
}
35467+
}
3543735468
}
3543835469

3543935470
function checkExportAssignment(node: ExportAssignment) {
@@ -37624,6 +37655,8 @@ namespace ts {
3762437655
case ExternalEmitHelpers.AsyncDelegator: return "__asyncDelegator";
3762537656
case ExternalEmitHelpers.AsyncValues: return "__asyncValues";
3762637657
case ExternalEmitHelpers.ExportStar: return "__exportStar";
37658+
case ExternalEmitHelpers.ImportStar: return "__importStar";
37659+
case ExternalEmitHelpers.ImportDefault: return "__importDefault";
3762737660
case ExternalEmitHelpers.MakeTemplateObject: return "__makeTemplateObject";
3762837661
case ExternalEmitHelpers.ClassPrivateFieldGet: return "__classPrivateFieldGet";
3762937662
case ExternalEmitHelpers.ClassPrivateFieldSet: return "__classPrivateFieldSet";

src/compiler/factory/emitHelpers.ts

+26
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ namespace ts {
3131
createImportStarHelper(expression: Expression): Expression;
3232
createImportStarCallbackHelper(): Expression;
3333
createImportDefaultHelper(expression: Expression): Expression;
34+
createExportStarHelper(moduleExpression: Expression, exportsExpression?: Expression): Expression;
3435
// Class Fields Helpers
3536
createClassPrivateFieldGetHelper(receiver: Expression, privateField: Identifier): Expression;
3637
createClassPrivateFieldSetHelper(receiver: Expression, privateField: Identifier, value: Expression): Expression;
@@ -69,6 +70,7 @@ namespace ts {
6970
createImportStarHelper,
7071
createImportStarCallbackHelper,
7172
createImportDefaultHelper,
73+
createExportStarHelper,
7274
// Class Fields Helpers
7375
createClassPrivateFieldGetHelper,
7476
createClassPrivateFieldSetHelper,
@@ -366,6 +368,16 @@ namespace ts {
366368
);
367369
}
368370

371+
function createExportStarHelper(moduleExpression: Expression, exportsExpression: Expression = factory.createIdentifier("exports")) {
372+
context.requestEmitHelper(exportStarHelper);
373+
context.requestEmitHelper(createBindingHelper);
374+
return factory.createCallExpression(
375+
getUnscopedHelperName("__exportStar"),
376+
/*typeArguments*/ undefined,
377+
[moduleExpression, exportsExpression]
378+
);
379+
}
380+
369381
// Class Fields Helpers
370382

371383
function createClassPrivateFieldGetHelper(receiver: Expression, privateField: Identifier) {
@@ -815,6 +827,19 @@ namespace ts {
815827
};`
816828
};
817829

830+
// emit output for the __export helper function
831+
export const exportStarHelper: UnscopedEmitHelper = {
832+
name: "typescript:export-star",
833+
importName: "__exportStar",
834+
scoped: false,
835+
dependencies: [createBindingHelper],
836+
priority: 2,
837+
text: `
838+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
839+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
840+
};`
841+
};
842+
818843
// Class fields helpers
819844
export const classPrivateFieldGetHelper: UnscopedEmitHelper = {
820845
name: "typescript:classPrivateFieldGet",
@@ -864,6 +889,7 @@ namespace ts {
864889
generatorHelper,
865890
importStarHelper,
866891
importDefaultHelper,
892+
exportStarHelper,
867893
classPrivateFieldGetHelper,
868894
classPrivateFieldSetHelper,
869895
createBindingHelper,

src/compiler/transformers/module/module.ts

+12-32
Original file line numberDiff line numberDiff line change
@@ -700,7 +700,6 @@ namespace ts {
700700

701701
const promise = factory.createNewExpression(factory.createIdentifier("Promise"), /*typeArguments*/ undefined, [func]);
702702
if (compilerOptions.esModuleInterop) {
703-
context.requestEmitHelper(importStarHelper);
704703
return factory.createCallExpression(factory.createPropertyAccessExpression(promise, factory.createIdentifier("then")), /*typeArguments*/ undefined, [emitHelpers().createImportStarCallbackHelper()]);
705704
}
706705
return promise;
@@ -715,7 +714,6 @@ namespace ts {
715714
const promiseResolveCall = factory.createCallExpression(factory.createPropertyAccessExpression(factory.createIdentifier("Promise"), "resolve"), /*typeArguments*/ undefined, /*argumentsArray*/ []);
716715
let requireCall: Expression = factory.createCallExpression(factory.createIdentifier("require"), /*typeArguments*/ undefined, arg ? [arg] : []);
717716
if (compilerOptions.esModuleInterop) {
718-
context.requestEmitHelper(importStarHelper);
719717
requireCall = emitHelpers().createImportStarHelper(requireCall);
720718
}
721719

@@ -755,8 +753,7 @@ namespace ts {
755753
return innerExpr;
756754
}
757755
if (getExportNeedsImportStarHelper(node)) {
758-
context.requestEmitHelper(importStarHelper);
759-
return factory.createCallExpression(context.getEmitHelperFactory().getUnscopedHelperName("__importStar"), /*typeArguments*/ undefined, [innerExpr]);
756+
return emitHelpers().createImportStarHelper(innerExpr);
760757
}
761758
return innerExpr;
762759
}
@@ -766,11 +763,9 @@ namespace ts {
766763
return innerExpr;
767764
}
768765
if (getImportNeedsImportStarHelper(node)) {
769-
context.requestEmitHelper(importStarHelper);
770766
return emitHelpers().createImportStarHelper(innerExpr);
771767
}
772768
if (getImportNeedsImportDefaultHelper(node)) {
773-
context.requestEmitHelper(importDefaultHelper);
774769
return emitHelpers().createImportDefaultHelper(innerExpr);
775770
}
776771
return innerExpr;
@@ -1015,18 +1010,21 @@ namespace ts {
10151010
setOriginalNode(
10161011
setTextRange(
10171012
factory.createExpressionStatement(
1018-
context.getEmitHelperFactory().createCreateBindingHelper(generatedName, factory.createStringLiteralFromNode(specifier.propertyName || specifier.name), specifier.propertyName ? factory.createStringLiteralFromNode(specifier.name) : undefined)
1013+
emitHelpers().createCreateBindingHelper(generatedName, factory.createStringLiteralFromNode(specifier.propertyName || specifier.name), specifier.propertyName ? factory.createStringLiteralFromNode(specifier.name) : undefined)
10191014
),
10201015
specifier),
10211016
specifier
10221017
)
10231018
);
10241019
}
10251020
else {
1021+
const exportNeedsImportDefault =
1022+
!!compilerOptions.esModuleInterop &&
1023+
!(getEmitFlags(node) & EmitFlags.NeverApplyImportHelper) &&
1024+
idText(specifier.propertyName || specifier.name) === "default";
10261025
const exportedValue = factory.createPropertyAccessExpression(
1027-
generatedName,
1028-
specifier.propertyName || specifier.name
1029-
);
1026+
exportNeedsImportDefault ? emitHelpers().createImportDefaultHelper(generatedName) : generatedName,
1027+
specifier.propertyName || specifier.name);
10301028
statements.push(
10311029
setOriginalNode(
10321030
setTextRange(
@@ -1051,9 +1049,9 @@ namespace ts {
10511049
factory.createExpressionStatement(
10521050
createExportExpression(
10531051
factory.cloneNode(node.exportClause.name),
1054-
moduleKind !== ModuleKind.AMD ?
1055-
getHelperExpressionForExport(node, createRequireCall(node)) :
1056-
factory.createIdentifier(idText(node.exportClause.name))
1052+
getHelperExpressionForExport(node, moduleKind !== ModuleKind.AMD ?
1053+
createRequireCall(node) :
1054+
factory.createIdentifier(idText(node.exportClause.name)))
10571055
)
10581056
),
10591057
node
@@ -1069,7 +1067,7 @@ namespace ts {
10691067
return setOriginalNode(
10701068
setTextRange(
10711069
factory.createExpressionStatement(
1072-
createExportStarHelper(context, moduleKind !== ModuleKind.AMD ? createRequireCall(node) : generatedName)
1070+
emitHelpers().createExportStarHelper(moduleKind !== ModuleKind.AMD ? createRequireCall(node) : generatedName)
10731071
),
10741072
node),
10751073
node
@@ -1857,24 +1855,6 @@ namespace ts {
18571855
}
18581856
}
18591857

1860-
// emit output for the __export helper function
1861-
const exportStarHelper: UnscopedEmitHelper = {
1862-
name: "typescript:export-star",
1863-
importName: "__exportStar",
1864-
scoped: false,
1865-
dependencies: [createBindingHelper],
1866-
priority: 2,
1867-
text: `
1868-
var __exportStar = (this && this.__exportStar) || function(m, exports) {
1869-
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
1870-
};`
1871-
};
1872-
1873-
function createExportStarHelper(context: TransformationContext, module: Expression) {
1874-
context.requestEmitHelper(exportStarHelper);
1875-
return context.factory.createCallExpression(context.getEmitHelperFactory().getUnscopedHelperName("__exportStar"), /*typeArguments*/ undefined, [module, context.factory.createIdentifier("exports")]);
1876-
}
1877-
18781858
// emit helper for dynamic import
18791859
const dynamicImportUMDHelper: EmitHelper = {
18801860
name: "typescript:dynamicimport-sync-require",

src/compiler/transformers/utilities.ts

+2
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,8 @@ namespace ts {
122122
uniqueExports.set(idText(name), true);
123123
exportedNames = append(exportedNames, name);
124124
}
125+
// we use the same helpers for `export * as ns` as we do for `import * as ns`
126+
hasImportStar = true;
125127
}
126128
}
127129
}

src/compiler/types.ts

+6-4
Original file line numberDiff line numberDiff line change
@@ -6436,10 +6436,12 @@ namespace ts {
64366436
AsyncDelegator = 1 << 14, // __asyncDelegator (used by ES2017 async generator yield* transformation)
64376437
AsyncValues = 1 << 15, // __asyncValues (used by ES2017 for..await..of transformation)
64386438
ExportStar = 1 << 16, // __exportStar (used by CommonJS/AMD/UMD module transformation)
6439-
MakeTemplateObject = 1 << 17, // __makeTemplateObject (used for constructing template string array objects)
6440-
ClassPrivateFieldGet = 1 << 18, // __classPrivateFieldGet (used by the class private field transformation)
6441-
ClassPrivateFieldSet = 1 << 19, // __classPrivateFieldSet (used by the class private field transformation)
6442-
CreateBinding = 1 << 20, // __createBinding (use by the module transform for (re)exports and namespace imports)
6439+
ImportStar = 1 << 17, // __importStar (used by CommonJS/AMD/UMD module transformation)
6440+
ImportDefault = 1 << 18, // __importStar (used by CommonJS/AMD/UMD module transformation)
6441+
MakeTemplateObject = 1 << 19, // __makeTemplateObject (used for constructing template string array objects)
6442+
ClassPrivateFieldGet = 1 << 20, // __classPrivateFieldGet (used by the class private field transformation)
6443+
ClassPrivateFieldSet = 1 << 21, // __classPrivateFieldSet (used by the class private field transformation)
6444+
CreateBinding = 1 << 22, // __createBinding (use by the module transform for (re)exports and namespace imports)
64436445
FirstEmitHelper = Extends,
64446446
LastEmitHelper = CreateBinding,
64456447

src/testRunner/compilerRunner.ts

+1-2
Original file line numberDiff line numberDiff line change
@@ -159,13 +159,12 @@ namespace Harness {
159159
let configuredName = "";
160160
const keys = Object
161161
.keys(configurationOverrides)
162-
.map(k => k.toLowerCase())
163162
.sort();
164163
for (const key of keys) {
165164
if (configuredName) {
166165
configuredName += ",";
167166
}
168-
configuredName += `${key}=${configurationOverrides[key].toLowerCase()}`;
167+
configuredName += `${key.toLowerCase()}=${configurationOverrides[key].toLowerCase()}`;
169168
}
170169
if (configuredName) {
171170
const extname = vpath.extname(this.justName);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
tests/cases/compiler/file2.ts(1,1): error TS2354: This syntax requires an imported helper but module 'tslib' cannot be found.
2+
3+
4+
==== tests/cases/compiler/refs.d.ts (0 errors) ====
5+
declare module "path";
6+
==== tests/cases/compiler/file.ts (0 errors) ====
7+
import path from "path";
8+
path.resolve("", "../");
9+
export class Foo { }
10+
==== tests/cases/compiler/file2.ts (1 errors) ====
11+
import * as path from "path";
12+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
13+
!!! error TS2354: This syntax requires an imported helper but module 'tslib' cannot be found.
14+
path.resolve("", "../");
15+
export class Foo2 { }
16+
==== tests/cases/compiler/file3.ts (0 errors) ====
17+
import {default as resolve} from "path";
18+
resolve("", "../");
19+
export class Foo3 { }
20+
==== tests/cases/compiler/file4.ts (0 errors) ====
21+
import {Bar, default as resolve} from "path";
22+
resolve("", "../");
23+
export { Bar }

tests/baselines/reference/exportAsNamespace2(module=amd).js

+20-1
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,30 @@ define(["require", "exports"], function (require, exports) {
2424
exports.b = 2;
2525
});
2626
//// [1.js]
27+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
28+
if (k2 === undefined) k2 = k;
29+
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
30+
}) : (function(o, m, k, k2) {
31+
if (k2 === undefined) k2 = k;
32+
o[k2] = m[k];
33+
}));
34+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
35+
Object.defineProperty(o, "default", { enumerable: true, value: v });
36+
}) : function(o, v) {
37+
o["default"] = v;
38+
});
39+
var __importStar = (this && this.__importStar) || function (mod) {
40+
if (mod && mod.__esModule) return mod;
41+
var result = {};
42+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
43+
__setModuleDefault(result, mod);
44+
return result;
45+
};
2746
define(["require", "exports", "./0"], function (require, exports, ns) {
2847
"use strict";
2948
exports.__esModule = true;
3049
exports.ns = void 0;
31-
exports.ns = ns;
50+
exports.ns = __importStar(ns);
3251
ns.a;
3352
ns.b;
3453
});

tests/baselines/reference/exportAsNamespace3(module=amd).js

+20-1
Original file line numberDiff line numberDiff line change
@@ -27,11 +27,30 @@ define(["require", "exports"], function (require, exports) {
2727
exports.b = 2;
2828
});
2929
//// [1.js]
30+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
31+
if (k2 === undefined) k2 = k;
32+
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
33+
}) : (function(o, m, k, k2) {
34+
if (k2 === undefined) k2 = k;
35+
o[k2] = m[k];
36+
}));
37+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
38+
Object.defineProperty(o, "default", { enumerable: true, value: v });
39+
}) : function(o, v) {
40+
o["default"] = v;
41+
});
42+
var __importStar = (this && this.__importStar) || function (mod) {
43+
if (mod && mod.__esModule) return mod;
44+
var result = {};
45+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
46+
__setModuleDefault(result, mod);
47+
return result;
48+
};
3049
define(["require", "exports", "./0"], function (require, exports, ns) {
3150
"use strict";
3251
exports.__esModule = true;
3352
exports.ns = void 0;
34-
exports.ns = ns;
53+
exports.ns = __importStar(ns);
3554
ns.a;
3655
ns.b;
3756
var ns = { a: 1, b: 2 };

0 commit comments

Comments
 (0)