Skip to content

Commit f6f1a0d

Browse files
committed
Adds support for importing external helpers.
1 parent d147eed commit f6f1a0d

37 files changed

+928
-87
lines changed

src/compiler/checker.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17385,6 +17385,11 @@ namespace ts {
1738517385

1738617386
function isReferencedAliasDeclaration(node: Node, checkChildren?: boolean): boolean {
1738717387
node = getParseTreeNode(node);
17388+
// Purely synthesized nodes are always emitted.
17389+
if (node === undefined) {
17390+
return true;
17391+
}
17392+
1738817393
if (isAliasSymbolDeclaration(node)) {
1738917394
const symbol = getSymbolOfNode(node);
1739017395
if (symbol && getSymbolLinks(symbol).referenced) {

src/compiler/commandLineParser.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -415,6 +415,11 @@ namespace ts {
415415
name: "strictNullChecks",
416416
type: "boolean",
417417
description: Diagnostics.Enable_strict_null_checks
418+
},
419+
{
420+
name: "importHelpers",
421+
type: "boolean",
422+
description: Diagnostics.Import_emit_helpers_from_tslib
418423
}
419424
];
420425

src/compiler/diagnosticMessages.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2772,6 +2772,10 @@
27722772
"category": "Error",
27732773
"code": 6131
27742774
},
2775+
"Import emit helpers from 'tslib'.": {
2776+
"category": "Message",
2777+
"code": 6132
2778+
},
27752779

27762780
"Variable '{0}' implicitly has an '{1}' type.": {
27772781
"category": "Error",

src/compiler/emitter.ts

Lines changed: 42 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -2106,48 +2106,56 @@ const _super = (function (geti, seti) {
21062106
}
21072107

21082108
function emitEmitHelpers(node: SourceFile) {
2109-
let helpersEmitted = false;
2110-
21112109
// Only emit helpers if the user did not say otherwise.
2112-
if (!compilerOptions.noEmitHelpers) {
2113-
// Only Emit __extends function when target ES5.
2114-
// For target ES6 and above, we can emit classDeclaration as is.
2115-
if ((languageVersion < ScriptTarget.ES6) && (!extendsEmitted && node.flags & NodeFlags.HasClassExtends)) {
2116-
writeLines(extendsHelper);
2117-
extendsEmitted = true;
2118-
helpersEmitted = true;
2119-
}
2110+
if (compilerOptions.noEmitHelpers) {
2111+
return false;
2112+
}
21202113

2121-
if (compilerOptions.jsx !== JsxEmit.Preserve && !assignEmitted && (node.flags & NodeFlags.HasJsxSpreadAttribute)) {
2122-
writeLines(assignHelper);
2123-
assignEmitted = true;
2124-
}
2114+
// Don't emit helpers if we can import them.
2115+
if (compilerOptions.importHelpers
2116+
&& (isExternalModule(node) || compilerOptions.isolatedModules)) {
2117+
return false;
2118+
}
21252119

2126-
if (!decorateEmitted && node.flags & NodeFlags.HasDecorators) {
2127-
writeLines(decorateHelper);
2128-
if (compilerOptions.emitDecoratorMetadata) {
2129-
writeLines(metadataHelper);
2130-
}
2120+
let helpersEmitted = false;
21312121

2132-
decorateEmitted = true;
2133-
helpersEmitted = true;
2134-
}
2122+
// Only Emit __extends function when target ES5.
2123+
// For target ES6 and above, we can emit classDeclaration as is.
2124+
if ((languageVersion < ScriptTarget.ES6) && (!extendsEmitted && node.flags & NodeFlags.HasClassExtends)) {
2125+
writeLines(extendsHelper);
2126+
extendsEmitted = true;
2127+
helpersEmitted = true;
2128+
}
21352129

2136-
if (!paramEmitted && node.flags & NodeFlags.HasParamDecorators) {
2137-
writeLines(paramHelper);
2138-
paramEmitted = true;
2139-
helpersEmitted = true;
2140-
}
2130+
if (compilerOptions.jsx !== JsxEmit.Preserve && !assignEmitted && (node.flags & NodeFlags.HasJsxSpreadAttribute)) {
2131+
writeLines(assignHelper);
2132+
assignEmitted = true;
2133+
}
21412134

2142-
if (!awaiterEmitted && node.flags & NodeFlags.HasAsyncFunctions) {
2143-
writeLines(awaiterHelper);
2144-
awaiterEmitted = true;
2145-
helpersEmitted = true;
2135+
if (!decorateEmitted && node.flags & NodeFlags.HasDecorators) {
2136+
writeLines(decorateHelper);
2137+
if (compilerOptions.emitDecoratorMetadata) {
2138+
writeLines(metadataHelper);
21462139
}
21472140

2148-
if (helpersEmitted) {
2149-
writeLine();
2150-
}
2141+
decorateEmitted = true;
2142+
helpersEmitted = true;
2143+
}
2144+
2145+
if (!paramEmitted && node.flags & NodeFlags.HasParamDecorators) {
2146+
writeLines(paramHelper);
2147+
paramEmitted = true;
2148+
helpersEmitted = true;
2149+
}
2150+
2151+
if (!awaiterEmitted && node.flags & NodeFlags.HasAsyncFunctions) {
2152+
writeLines(awaiterHelper);
2153+
awaiterEmitted = true;
2154+
helpersEmitted = true;
2155+
}
2156+
2157+
if (helpersEmitted) {
2158+
writeLine();
21512159
}
21522160

21532161
return helpersEmitted;

src/compiler/factory.ts

Lines changed: 51 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -800,30 +800,31 @@ namespace ts {
800800
updated.fileName = node.fileName;
801801
updated.path = node.path;
802802
updated.text = node.text;
803-
updated.amdDependencies = node.amdDependencies;
804-
updated.moduleName = node.moduleName;
805-
updated.referencedFiles = node.referencedFiles;
806-
updated.typeReferenceDirectives = node.typeReferenceDirectives;
807-
updated.languageVariant = node.languageVariant;
808-
updated.isDeclarationFile = node.isDeclarationFile;
809-
updated.renamedDependencies = node.renamedDependencies;
810-
updated.hasNoDefaultLib = node.hasNoDefaultLib;
811-
updated.languageVersion = node.languageVersion;
812-
updated.scriptKind = node.scriptKind;
813-
updated.externalModuleIndicator = node.externalModuleIndicator;
814-
updated.commonJsModuleIndicator = node.commonJsModuleIndicator;
815-
updated.identifiers = node.identifiers;
816-
updated.nodeCount = node.nodeCount;
817-
updated.identifierCount = node.identifierCount;
818-
updated.symbolCount = node.symbolCount;
819-
updated.parseDiagnostics = node.parseDiagnostics;
820-
updated.bindDiagnostics = node.bindDiagnostics;
821-
updated.lineMap = node.lineMap;
822-
updated.classifiableNames = node.classifiableNames;
823-
updated.resolvedModules = node.resolvedModules;
824-
updated.resolvedTypeReferenceDirectiveNames = node.resolvedTypeReferenceDirectiveNames;
825-
updated.imports = node.imports;
826-
updated.moduleAugmentations = node.moduleAugmentations;
803+
if (node.amdDependencies !== undefined) updated.amdDependencies = node.amdDependencies;
804+
if (node.moduleName !== undefined) updated.moduleName = node.moduleName;
805+
if (node.referencedFiles !== undefined) updated.referencedFiles = node.referencedFiles;
806+
if (node.typeReferenceDirectives !== undefined) updated.typeReferenceDirectives = node.typeReferenceDirectives;
807+
if (node.languageVariant !== undefined) updated.languageVariant = node.languageVariant;
808+
if (node.isDeclarationFile !== undefined) updated.isDeclarationFile = node.isDeclarationFile;
809+
if (node.renamedDependencies !== undefined) updated.renamedDependencies = node.renamedDependencies;
810+
if (node.hasNoDefaultLib !== undefined) updated.hasNoDefaultLib = node.hasNoDefaultLib;
811+
if (node.languageVersion !== undefined) updated.languageVersion = node.languageVersion;
812+
if (node.scriptKind !== undefined) updated.scriptKind = node.scriptKind;
813+
if (node.externalModuleIndicator !== undefined) updated.externalModuleIndicator = node.externalModuleIndicator;
814+
if (node.commonJsModuleIndicator !== undefined) updated.commonJsModuleIndicator = node.commonJsModuleIndicator;
815+
if (node.identifiers !== undefined) updated.identifiers = node.identifiers;
816+
if (node.nodeCount !== undefined) updated.nodeCount = node.nodeCount;
817+
if (node.identifierCount !== undefined) updated.identifierCount = node.identifierCount;
818+
if (node.symbolCount !== undefined) updated.symbolCount = node.symbolCount;
819+
if (node.parseDiagnostics !== undefined) updated.parseDiagnostics = node.parseDiagnostics;
820+
if (node.bindDiagnostics !== undefined) updated.bindDiagnostics = node.bindDiagnostics;
821+
if (node.lineMap !== undefined) updated.lineMap = node.lineMap;
822+
if (node.classifiableNames !== undefined) updated.classifiableNames = node.classifiableNames;
823+
if (node.resolvedModules !== undefined) updated.resolvedModules = node.resolvedModules;
824+
if (node.resolvedTypeReferenceDirectiveNames !== undefined) updated.resolvedTypeReferenceDirectiveNames = node.resolvedTypeReferenceDirectiveNames;
825+
if (node.imports !== undefined) updated.imports = node.imports;
826+
if (node.moduleAugmentations !== undefined) updated.moduleAugmentations = node.moduleAugmentations;
827+
if (node.tslib !== undefined) updated.tslib = node.tslib;
827828
return updateNode(updated, node);
828829
}
829830

@@ -923,6 +924,12 @@ namespace ts {
923924
return node;
924925
}
925926

927+
export function createNamespaceImport(name: Identifier): NamespaceImport {
928+
const node = <NamespaceImport>createNode(SyntaxKind.NamespaceImport);
929+
node.name = name;
930+
return node;
931+
}
932+
926933
export function createNamedImports(elements: NodeArray<ImportSpecifier>, location?: TextRange): NamedImports {
927934
const node = <NamedImports>createNode(SyntaxKind.NamedImports, location);
928935
node.elements = elements;
@@ -1058,9 +1065,15 @@ namespace ts {
10581065

10591066
// Helpers
10601067

1061-
export function createExtendsHelper(name: Identifier) {
1068+
export function createHelperName(tslib: Identifier, name: string) {
1069+
return tslib
1070+
? createPropertyAccess(tslib, name)
1071+
: createIdentifier(name);
1072+
}
1073+
1074+
export function createExtendsHelper(tslib: Identifier, name: Identifier) {
10621075
return createCall(
1063-
createIdentifier("__extends"),
1076+
createHelperName(tslib, "__extends"),
10641077
/*typeArguments*/ undefined,
10651078
[
10661079
name,
@@ -1069,17 +1082,17 @@ namespace ts {
10691082
);
10701083
}
10711084

1072-
export function createAssignHelper(attributesSegments: Expression[]) {
1085+
export function createAssignHelper(tslib: Identifier, attributesSegments: Expression[]) {
10731086
return createCall(
1074-
createIdentifier("__assign"),
1087+
createHelperName(tslib, "__assign"),
10751088
/*typeArguments*/ undefined,
10761089
attributesSegments
10771090
);
10781091
}
10791092

1080-
export function createParamHelper(expression: Expression, parameterOffset: number, location?: TextRange) {
1093+
export function createParamHelper(tslib: Identifier, expression: Expression, parameterOffset: number, location?: TextRange) {
10811094
return createCall(
1082-
createIdentifier("__param"),
1095+
createHelperName(tslib, "__param"),
10831096
/*typeArguments*/ undefined,
10841097
[
10851098
createLiteral(parameterOffset),
@@ -1089,9 +1102,9 @@ namespace ts {
10891102
);
10901103
}
10911104

1092-
export function createMetadataHelper(metadataKey: string, metadataValue: Expression) {
1105+
export function createMetadataHelper(tslib: Identifier, metadataKey: string, metadataValue: Expression) {
10931106
return createCall(
1094-
createIdentifier("__metadata"),
1107+
createHelperName(tslib, "__metadata"),
10951108
/*typeArguments*/ undefined,
10961109
[
10971110
createLiteral(metadataKey),
@@ -1100,7 +1113,7 @@ namespace ts {
11001113
);
11011114
}
11021115

1103-
export function createDecorateHelper(decoratorExpressions: Expression[], target: Expression, memberName?: Expression, descriptor?: Expression, location?: TextRange) {
1116+
export function createDecorateHelper(tslib: Identifier, decoratorExpressions: Expression[], target: Expression, memberName?: Expression, descriptor?: Expression, location?: TextRange) {
11041117
const argumentsArray: Expression[] = [];
11051118
argumentsArray.push(createArrayLiteral(decoratorExpressions, /*location*/ undefined, /*multiLine*/ true));
11061119
argumentsArray.push(target);
@@ -1111,12 +1124,12 @@ namespace ts {
11111124
}
11121125
}
11131126

1114-
return createCall(createIdentifier("__decorate"), /*typeArguments*/ undefined, argumentsArray, location);
1127+
return createCall(createHelperName(tslib, "__decorate"), /*typeArguments*/ undefined, argumentsArray, location);
11151128
}
11161129

1117-
export function createAwaiterHelper(hasLexicalArguments: boolean, promiseConstructor: EntityName | Expression, body: Block) {
1130+
export function createAwaiterHelper(tslib: Identifier, hasLexicalArguments: boolean, promiseConstructor: EntityName | Expression, body: Block) {
11181131
return createCall(
1119-
createIdentifier("__awaiter"),
1132+
createHelperName(tslib, "__awaiter"),
11201133
/*typeArguments*/ undefined,
11211134
[
11221135
createThis(),
@@ -1920,7 +1933,8 @@ namespace ts {
19201933
export function getLocalNameForExternalImport(node: ImportDeclaration | ExportDeclaration | ImportEqualsDeclaration, sourceFile: SourceFile): Identifier {
19211934
const namespaceDeclaration = getNamespaceDeclarationNode(node);
19221935
if (namespaceDeclaration && !isDefaultImport(node)) {
1923-
return createIdentifier(getSourceTextOfNodeFromSourceFile(sourceFile, namespaceDeclaration.name));
1936+
const name = namespaceDeclaration.name;
1937+
return isGeneratedIdentifier(name) ? name : createIdentifier(getSourceTextOfNodeFromSourceFile(sourceFile, namespaceDeclaration.name));
19241938
}
19251939
if (node.kind === SyntaxKind.ImportDeclaration && (<ImportDeclaration>node).importClause) {
19261940
return getGeneratedNameForNode(node);

src/compiler/transformers/es6.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -702,7 +702,7 @@ namespace ts {
702702
if (extendsClauseElement) {
703703
statements.push(
704704
createStatement(
705-
createExtendsHelper(getDeclarationName(node)),
705+
createExtendsHelper(currentSourceFile.tslib, getDeclarationName(node)),
706706
/*location*/ extendsClauseElement
707707
)
708708
);

src/compiler/transformers/jsx.ts

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

88
export function transformJsx(context: TransformationContext) {
99
const compilerOptions = context.getCompilerOptions();
10+
let currentSourceFile: SourceFile;
1011
return transformSourceFile;
1112

1213
/**
@@ -15,7 +16,10 @@ namespace ts {
1516
* @param node A SourceFile node.
1617
*/
1718
function transformSourceFile(node: SourceFile) {
18-
return visitEachChild(node, visitor, context);
19+
currentSourceFile = node;
20+
node = visitEachChild(node, visitor, context);
21+
currentSourceFile = undefined;
22+
return node;
1923
}
2024

2125
function visitor(node: Node): VisitResult<Node> {
@@ -102,7 +106,7 @@ namespace ts {
102106
// Either emit one big object literal (no spread attribs), or
103107
// a call to the __assign helper.
104108
objectProperties = singleOrUndefined(segments)
105-
|| createAssignHelper(segments);
109+
|| createAssignHelper(currentSourceFile.tslib, segments);
106110
}
107111

108112
const element = createReactCreateElement(

0 commit comments

Comments
 (0)