Skip to content

Commit 8ef4750

Browse files
committed
Support tree-shakable imports for --target es2015
1 parent cc3db8f commit 8ef4750

13 files changed

Lines changed: 95 additions & 23 deletions

File tree

src/compiler/emitter.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1609,7 +1609,7 @@ namespace ts {
16091609
for (let i = 0; i < numNodes; i++) {
16101610
const currentNode = bundle ? i < numPrepends ? bundle.prepends[i] : bundle.sourceFiles[i - numPrepends] : node;
16111611
const sourceFile = isSourceFile(currentNode) ? currentNode : isUnparsedSource(currentNode) ? undefined : currentSourceFile!;
1612-
const shouldSkip = printerOptions.noEmitHelpers || (!!sourceFile && getExternalHelpersModuleName(sourceFile) !== undefined);
1612+
const shouldSkip = printerOptions.noEmitHelpers || (!!sourceFile && hasRecordedExternalHelpers(sourceFile));
16131613
const shouldBundle = (isSourceFile(currentNode) || isUnparsedSource(currentNode)) && !isOwnFileEmit;
16141614
const helpers = isUnparsedSource(currentNode) ? currentNode.helpers : getSortedEmitHelpers(currentNode);
16151615
if (helpers) {

src/compiler/factory.ts

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3634,6 +3634,7 @@ namespace ts {
36343634

36353635
export const valuesHelper: UnscopedEmitHelper = {
36363636
name: "typescript:values",
3637+
importName: "__values",
36373638
scoped: false,
36383639
text: `
36393640
var __values = (this && this.__values) || function(o) {
@@ -3663,6 +3664,7 @@ namespace ts {
36633664

36643665
export const readHelper: UnscopedEmitHelper = {
36653666
name: "typescript:read",
3667+
importName: "__read",
36663668
scoped: false,
36673669
text: `
36683670
var __read = (this && this.__read) || function (o, n) {
@@ -3699,6 +3701,7 @@ namespace ts {
36993701

37003702
export const spreadHelper: UnscopedEmitHelper = {
37013703
name: "typescript:spread",
3704+
importName: "__spread",
37023705
scoped: false,
37033706
text: `
37043707
var __spread = (this && this.__spread) || function () {
@@ -3722,6 +3725,7 @@ namespace ts {
37223725

37233726
export const spreadArraysHelper: UnscopedEmitHelper = {
37243727
name: "typescript:spreadArrays",
3728+
importName: "__spreadArrays",
37253729
scoped: false,
37263730
text: `
37273731
var __spreadArrays = (this && this.__spreadArrays) || function () {
@@ -4863,6 +4867,60 @@ namespace ts {
48634867
return emitNode && emitNode.externalHelpersModuleName;
48644868
}
48654869

4870+
export function hasRecordedExternalHelpers(sourceFile: SourceFile) {
4871+
const parseNode = getOriginalNode(sourceFile, isSourceFile);
4872+
const emitNode = parseNode && parseNode.emitNode;
4873+
return !!emitNode && (!!emitNode.externalHelpersModuleName || !!emitNode.externalHelpers);
4874+
}
4875+
4876+
export function createExternalHelpersImportDeclarationIfNeeded(sourceFile: SourceFile, compilerOptions: CompilerOptions, hasExportStarsToExportValues?: boolean, hasImportStar?: boolean, hasImportDefault?: boolean) {
4877+
if (compilerOptions.importHelpers && isEffectiveExternalModule(sourceFile, compilerOptions)) {
4878+
let namedBindings: NamedImportBindings | undefined;
4879+
const moduleKind = getEmitModuleKind(compilerOptions);
4880+
if (moduleKind >= ModuleKind.ES2015 && moduleKind <= ModuleKind.ESNext) {
4881+
// use named imports
4882+
const helpers = getEmitHelpers(sourceFile);
4883+
if (helpers) {
4884+
const helperNames: string[] = [];
4885+
for (const helper of helpers) {
4886+
if (!helper.scoped) {
4887+
const importName = (helper as UnscopedEmitHelper).importName;
4888+
if (importName) {
4889+
pushIfUnique(helperNames, importName);
4890+
}
4891+
}
4892+
}
4893+
if (some(helperNames)) {
4894+
helperNames.sort(compareStringsCaseSensitive);
4895+
namedBindings = createNamedImports(
4896+
map(helperNames, name => createImportSpecifier(/*propertyName*/ undefined, createIdentifier(name)))
4897+
);
4898+
const parseNode = getOriginalNode(sourceFile, isSourceFile);
4899+
const emitNode = getOrCreateEmitNode(parseNode);
4900+
emitNode.externalHelpers = true;
4901+
}
4902+
}
4903+
}
4904+
else {
4905+
// use a namespace import
4906+
const externalHelpersModuleName = getOrCreateExternalHelpersModuleNameIfNeeded(sourceFile, compilerOptions, hasExportStarsToExportValues, hasImportStar || hasImportDefault);
4907+
if (externalHelpersModuleName) {
4908+
namedBindings = createNamespaceImport(externalHelpersModuleName);
4909+
}
4910+
}
4911+
if (namedBindings) {
4912+
const externalHelpersImportDeclaration = createImportDeclaration(
4913+
/*decorators*/ undefined,
4914+
/*modifiers*/ undefined,
4915+
createImportClause(/*name*/ undefined, namedBindings),
4916+
createLiteral(externalHelpersModuleNameText)
4917+
);
4918+
addEmitFlags(externalHelpersImportDeclaration, EmitFlags.NeverApplyImportHelper);
4919+
return externalHelpersImportDeclaration;
4920+
}
4921+
}
4922+
}
4923+
48664924
export function getOrCreateExternalHelpersModuleNameIfNeeded(node: SourceFile, compilerOptions: CompilerOptions, hasExportStarsToExportValues?: boolean, hasImportStarOrImportDefault?: boolean) {
48674925
if (compilerOptions.importHelpers && isEffectiveExternalModule(node, compilerOptions)) {
48684926
const externalHelpersModuleName = getExternalHelpersModuleName(node);

src/compiler/transformers/destructuring.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -514,6 +514,7 @@ namespace ts {
514514

515515
export const restHelper: UnscopedEmitHelper = {
516516
name: "typescript:rest",
517+
importName: "__rest",
517518
scoped: false,
518519
text: `
519520
var __rest = (this && this.__rest) || function (s, e) {

src/compiler/transformers/es2015.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4362,6 +4362,7 @@ namespace ts {
43624362

43634363
export const extendsHelper: UnscopedEmitHelper = {
43644364
name: "typescript:extends",
4365+
importName: "__extends",
43654366
scoped: false,
43664367
priority: 0,
43674368
text: `
@@ -4383,6 +4384,7 @@ namespace ts {
43834384

43844385
export const templateObjectHelper: UnscopedEmitHelper = {
43854386
name: "typescript:makeTemplateObject",
4387+
importName: "__makeTemplateObject",
43864388
scoped: false,
43874389
priority: 0,
43884390
text: `

src/compiler/transformers/es2017.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -771,6 +771,7 @@ namespace ts {
771771

772772
export const awaiterHelper: UnscopedEmitHelper = {
773773
name: "typescript:awaiter",
774+
importName: "__awaiter",
774775
scoped: false,
775776
priority: 5,
776777
text: `

src/compiler/transformers/es2018.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -995,6 +995,7 @@ namespace ts {
995995

996996
export const assignHelper: UnscopedEmitHelper = {
997997
name: "typescript:assign",
998+
importName: "__assign",
998999
scoped: false,
9991000
priority: 1,
10001001
text: `
@@ -1027,6 +1028,7 @@ namespace ts {
10271028

10281029
export const awaitHelper: UnscopedEmitHelper = {
10291030
name: "typescript:await",
1031+
importName: "__await",
10301032
scoped: false,
10311033
text: `
10321034
var __await = (this && this.__await) || function (v) { return this instanceof __await ? (this.v = v, this) : new __await(v); }`
@@ -1039,6 +1041,7 @@ namespace ts {
10391041

10401042
export const asyncGeneratorHelper: UnscopedEmitHelper = {
10411043
name: "typescript:asyncGenerator",
1044+
importName: "__asyncGenerator",
10421045
scoped: false,
10431046
text: `
10441047
var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _arguments, generator) {
@@ -1074,6 +1077,7 @@ namespace ts {
10741077

10751078
export const asyncDelegator: UnscopedEmitHelper = {
10761079
name: "typescript:asyncDelegator",
1080+
importName: "__asyncDelegator",
10771081
scoped: false,
10781082
text: `
10791083
var __asyncDelegator = (this && this.__asyncDelegator) || function (o) {
@@ -1098,6 +1102,7 @@ namespace ts {
10981102

10991103
export const asyncValues: UnscopedEmitHelper = {
11001104
name: "typescript:asyncValues",
1105+
importName: "__asyncValues",
11011106
scoped: false,
11021107
text: `
11031108
var __asyncValues = (this && this.__asyncValues) || function (o) {

src/compiler/transformers/generators.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3242,6 +3242,7 @@ namespace ts {
32423242
// For examples of how these are used, see the comments in ./transformers/generators.ts
32433243
export const generatorHelper: UnscopedEmitHelper = {
32443244
name: "typescript:generator",
3245+
importName: "__generator",
32453246
scoped: false,
32463247
priority: 6,
32473248
text: `

src/compiler/transformers/module/es2015.ts

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -18,18 +18,11 @@ namespace ts {
1818
}
1919

2020
if (isExternalModule(node) || compilerOptions.isolatedModules) {
21-
const externalHelpersModuleName = getOrCreateExternalHelpersModuleNameIfNeeded(node, compilerOptions);
22-
if (externalHelpersModuleName) {
21+
const externalHelpersImportDeclaration = createExternalHelpersImportDeclarationIfNeeded(node, compilerOptions);
22+
if (externalHelpersImportDeclaration) {
2323
const statements: Statement[] = [];
2424
const statementOffset = addPrologue(statements, node.statements);
25-
const tslibImport = createImportDeclaration(
26-
/*decorators*/ undefined,
27-
/*modifiers*/ undefined,
28-
createImportClause(/*name*/ undefined, createNamespaceImport(externalHelpersModuleName)),
29-
createLiteral(externalHelpersModuleNameText)
30-
);
31-
addEmitFlags(tslibImport, EmitFlags.NeverApplyImportHelper);
32-
append(statements, tslibImport);
25+
append(statements, externalHelpersImportDeclaration);
3326

3427
addRange(statements, visitNodes(node.statements, visitor, isStatement, statementOffset));
3528
return updateSourceFileNode(

src/compiler/transformers/module/module.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1808,6 +1808,7 @@ namespace ts {
18081808
// emit helper for `import * as Name from "foo"`
18091809
export const importStarHelper: UnscopedEmitHelper = {
18101810
name: "typescript:commonjsimportstar",
1811+
importName: "__importStar",
18111812
scoped: false,
18121813
text: `
18131814
var __importStar = (this && this.__importStar) || function (mod) {
@@ -1822,6 +1823,7 @@ var __importStar = (this && this.__importStar) || function (mod) {
18221823
// emit helper for `import Name from "foo"`
18231824
export const importDefaultHelper: UnscopedEmitHelper = {
18241825
name: "typescript:commonjsimportdefault",
1826+
importName: "__importDefault",
18251827
scoped: false,
18261828
text: `
18271829
var __importDefault = (this && this.__importDefault) || function (mod) {

src/compiler/transformers/ts.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3292,6 +3292,7 @@ namespace ts {
32923292

32933293
export const decorateHelper: UnscopedEmitHelper = {
32943294
name: "typescript:decorate",
3295+
importName: "__decorate",
32953296
scoped: false,
32963297
priority: 2,
32973298
text: `
@@ -3317,6 +3318,7 @@ namespace ts {
33173318

33183319
export const metadataHelper: UnscopedEmitHelper = {
33193320
name: "typescript:metadata",
3321+
importName: "__metadata",
33203322
scoped: false,
33213323
priority: 3,
33223324
text: `
@@ -3342,6 +3344,7 @@ namespace ts {
33423344

33433345
export const paramHelper: UnscopedEmitHelper = {
33443346
name: "typescript:param",
3347+
importName: "__param",
33453348
scoped: false,
33463349
priority: 4,
33473350
text: `

0 commit comments

Comments
 (0)