Skip to content

Commit a766005

Browse files
authored
Merge pull request #9097 from Microsoft/transforms-importHelpers
[Transforms] Import external helpers module
2 parents 03d273e + f3d0b86 commit a766005

Some content is hidden

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

45 files changed

+2031
-121
lines changed

src/compiler/binder.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1765,7 +1765,7 @@ namespace ts {
17651765
return bindPropertyOrMethodOrAccessor(<Declaration>node, SymbolFlags.EnumMember, SymbolFlags.EnumMemberExcludes);
17661766

17671767
case SyntaxKind.JsxSpreadAttribute:
1768-
emitFlags |= NodeFlags.HasJsxSpreadAttribute;
1768+
emitFlags |= NodeFlags.HasJsxSpreadAttributes;
17691769
return;
17701770

17711771
case SyntaxKind.CallSignature:

src/compiler/checker.ts

+70-10
Original file line numberDiff line numberDiff line change
@@ -1264,10 +1264,13 @@ namespace ts {
12641264
}
12651265

12661266
const moduleReferenceLiteral = <LiteralExpression>moduleReferenceExpression;
1267+
return resolveExternalModule(location, moduleReferenceLiteral.text, moduleNotFoundError, moduleReferenceLiteral);
1268+
}
12671269

1270+
function resolveExternalModule(location: Node, moduleReference: string, moduleNotFoundError: DiagnosticMessage, errorNode: Node): Symbol {
12681271
// Module names are escaped in our symbol table. However, string literal values aren't.
12691272
// Escape the name in the "require(...)" clause to ensure we find the right symbol.
1270-
const moduleName = escapeIdentifier(moduleReferenceLiteral.text);
1273+
const moduleName = escapeIdentifier(moduleReference);
12711274

12721275
if (moduleName === undefined) {
12731276
return;
@@ -1282,7 +1285,7 @@ namespace ts {
12821285
}
12831286
}
12841287

1285-
const resolvedModule = getResolvedModule(getSourceFileOfNode(location), moduleReferenceLiteral.text);
1288+
const resolvedModule = getResolvedModule(getSourceFileOfNode(location), moduleReference);
12861289
const sourceFile = resolvedModule && host.getSourceFile(resolvedModule.resolvedFileName);
12871290
if (sourceFile) {
12881291
if (sourceFile.symbol) {
@@ -1291,7 +1294,7 @@ namespace ts {
12911294
}
12921295
if (moduleNotFoundError) {
12931296
// report errors only if it was requested
1294-
error(moduleReferenceLiteral, Diagnostics.File_0_is_not_a_module, sourceFile.fileName);
1297+
error(errorNode, Diagnostics.File_0_is_not_a_module, sourceFile.fileName);
12951298
}
12961299
return undefined;
12971300
}
@@ -1305,7 +1308,7 @@ namespace ts {
13051308

13061309
if (moduleNotFoundError) {
13071310
// report errors only if it was requested
1308-
error(moduleReferenceLiteral, moduleNotFoundError, moduleName);
1311+
error(errorNode, moduleNotFoundError, moduleName);
13091312
}
13101313
return undefined;
13111314
}
@@ -17445,6 +17448,11 @@ namespace ts {
1744517448

1744617449
function isReferencedAliasDeclaration(node: Node, checkChildren?: boolean): boolean {
1744717450
node = getParseTreeNode(node);
17451+
// Purely synthesized nodes are always emitted.
17452+
if (node === undefined) {
17453+
return true;
17454+
}
17455+
1744817456
if (isAliasSymbolDeclaration(node)) {
1744917457
const symbol = getSymbolOfNode(node);
1745017458
if (symbol && getSymbolLinks(symbol).referenced) {
@@ -17759,27 +17767,37 @@ namespace ts {
1775917767

1776017768
function initializeTypeChecker() {
1776117769
// Bind all source files and propagate errors
17762-
forEach(host.getSourceFiles(), file => {
17770+
for (const file of host.getSourceFiles()) {
1776317771
bindSourceFile(file, compilerOptions);
17764-
});
17772+
}
1776517773

17766-
let augmentations: LiteralExpression[][];
1776717774
// Initialize global symbol table
17768-
forEach(host.getSourceFiles(), file => {
17775+
let augmentations: LiteralExpression[][];
17776+
let requestedExternalEmitHelpers: NodeFlags = 0;
17777+
let firstFileRequestingExternalHelpers: SourceFile;
17778+
for (const file of host.getSourceFiles()) {
1776917779
if (!isExternalOrCommonJsModule(file)) {
1777017780
mergeSymbolTable(globals, file.locals);
1777117781
}
1777217782
if (file.patternAmbientModules && file.patternAmbientModules.length) {
1777317783
patternAmbientModules = concatenate(patternAmbientModules, file.patternAmbientModules);
1777417784
}
17775-
1777617785
if (file.moduleAugmentations.length) {
1777717786
(augmentations || (augmentations = [])).push(file.moduleAugmentations);
1777817787
}
1777917788
if (file.symbol && file.symbol.globalExports) {
1778017789
mergeSymbolTable(globals, file.symbol.globalExports);
1778117790
}
17782-
});
17791+
if ((compilerOptions.isolatedModules || isExternalModule(file)) && !file.isDeclarationFile) {
17792+
const fileRequestedExternalEmitHelpers = file.flags & NodeFlags.EmitHelperFlags;
17793+
if (fileRequestedExternalEmitHelpers) {
17794+
requestedExternalEmitHelpers |= fileRequestedExternalEmitHelpers;
17795+
if (firstFileRequestingExternalHelpers === undefined) {
17796+
firstFileRequestingExternalHelpers = file;
17797+
}
17798+
}
17799+
}
17800+
}
1778317801

1778417802
if (augmentations) {
1778517803
// merge module augmentations.
@@ -17842,6 +17860,48 @@ namespace ts {
1784217860
const symbol = getGlobalSymbol("ReadonlyArray", SymbolFlags.Type, /*diagnostic*/ undefined);
1784317861
globalReadonlyArrayType = symbol && <GenericType>getTypeOfGlobalSymbol(symbol, /*arity*/ 1);
1784417862
anyReadonlyArrayType = globalReadonlyArrayType ? createTypeFromGenericGlobalType(globalReadonlyArrayType, [anyType]) : anyArrayType;
17863+
17864+
// If we have specified that we are importing helpers, we should report global
17865+
// errors if we cannot resolve the helpers external module, or if it does not have
17866+
// the necessary helpers exported.
17867+
if (compilerOptions.importHelpers && firstFileRequestingExternalHelpers) {
17868+
// Find the first reference to the helpers module.
17869+
const helpersModule = resolveExternalModule(
17870+
firstFileRequestingExternalHelpers,
17871+
externalHelpersModuleNameText,
17872+
Diagnostics.Cannot_find_module_0,
17873+
/*errorNode*/ undefined);
17874+
17875+
// If we found the module, report errors if it does not have the necessary exports.
17876+
if (helpersModule) {
17877+
const exports = helpersModule.exports;
17878+
if (requestedExternalEmitHelpers & NodeFlags.HasClassExtends && languageVersion < ScriptTarget.ES6) {
17879+
verifyHelperSymbol(exports, "__extends", SymbolFlags.Value);
17880+
}
17881+
if (requestedExternalEmitHelpers & NodeFlags.HasJsxSpreadAttributes && compilerOptions.jsx !== JsxEmit.Preserve) {
17882+
verifyHelperSymbol(exports, "__assign", SymbolFlags.Value);
17883+
}
17884+
if (requestedExternalEmitHelpers & NodeFlags.HasDecorators) {
17885+
verifyHelperSymbol(exports, "__decorate", SymbolFlags.Value);
17886+
if (compilerOptions.emitDecoratorMetadata) {
17887+
verifyHelperSymbol(exports, "__metadata", SymbolFlags.Value);
17888+
}
17889+
}
17890+
if (requestedExternalEmitHelpers & NodeFlags.HasParamDecorators) {
17891+
verifyHelperSymbol(exports, "__param", SymbolFlags.Value);
17892+
}
17893+
if (requestedExternalEmitHelpers & NodeFlags.HasAsyncFunctions) {
17894+
verifyHelperSymbol(exports, "__awaiter", SymbolFlags.Value);
17895+
}
17896+
}
17897+
}
17898+
}
17899+
17900+
function verifyHelperSymbol(symbols: SymbolTable, name: string, meaning: SymbolFlags) {
17901+
const symbol = getSymbol(symbols, escapeIdentifier(name), meaning);
17902+
if (!symbol) {
17903+
error(/*location*/ undefined, Diagnostics.Module_0_has_no_exported_member_1, externalHelpersModuleNameText, name);
17904+
}
1784517905
}
1784617906

1784717907
function createInstantiatedPromiseLikeType(): ObjectType {

src/compiler/commandLineParser.ts

+5
Original file line numberDiff line numberDiff line change
@@ -421,6 +421,11 @@ namespace ts {
421421
name: "strictNullChecks",
422422
type: "boolean",
423423
description: Diagnostics.Enable_strict_null_checks
424+
},
425+
{
426+
name: "importHelpers",
427+
type: "boolean",
428+
description: Diagnostics.Import_emit_helpers_from_tslib
424429
}
425430
];
426431

src/compiler/diagnosticMessages.json

+4
Original file line numberDiff line numberDiff line change
@@ -2776,6 +2776,10 @@
27762776
"category": "Message",
27772777
"code": 6132
27782778
},
2779+
"Import emit helpers from 'tslib'.": {
2780+
"category": "Message",
2781+
"code": 6133
2782+
},
27792783

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

src/compiler/emitter.ts

+42-34
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.HasJsxSpreadAttributes)) {
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;

0 commit comments

Comments
 (0)