@@ -3628,12 +3628,16 @@ namespace ts {
36283628
36293629 // Helpers
36303630
3631- export function getHelperName ( name : string ) {
3631+ /**
3632+ * Gets an identifier for the name of an *unscoped* emit helper.
3633+ */
3634+ export function getUnscopedHelperName ( name : string ) {
36323635 return setEmitFlags ( createIdentifier ( name ) , EmitFlags . HelperName | EmitFlags . AdviseOnEmitNode ) ;
36333636 }
36343637
36353638 export const valuesHelper : UnscopedEmitHelper = {
36363639 name : "typescript:values" ,
3640+ importName : "__values" ,
36373641 scoped : false ,
36383642 text : `
36393643 var __values = (this && this.__values) || function(o) {
@@ -3653,7 +3657,7 @@ namespace ts {
36533657 context . requestEmitHelper ( valuesHelper ) ;
36543658 return setTextRange (
36553659 createCall (
3656- getHelperName ( "__values" ) ,
3660+ getUnscopedHelperName ( "__values" ) ,
36573661 /*typeArguments*/ undefined ,
36583662 [ expression ]
36593663 ) ,
@@ -3663,6 +3667,7 @@ namespace ts {
36633667
36643668 export const readHelper : UnscopedEmitHelper = {
36653669 name : "typescript:read" ,
3670+ importName : "__read" ,
36663671 scoped : false ,
36673672 text : `
36683673 var __read = (this && this.__read) || function (o, n) {
@@ -3687,7 +3692,7 @@ namespace ts {
36873692 context . requestEmitHelper ( readHelper ) ;
36883693 return setTextRange (
36893694 createCall (
3690- getHelperName ( "__read" ) ,
3695+ getUnscopedHelperName ( "__read" ) ,
36913696 /*typeArguments*/ undefined ,
36923697 count !== undefined
36933698 ? [ iteratorRecord , createLiteral ( count ) ]
@@ -3699,6 +3704,7 @@ namespace ts {
36993704
37003705 export const spreadHelper : UnscopedEmitHelper = {
37013706 name : "typescript:spread" ,
3707+ importName : "__spread" ,
37023708 scoped : false ,
37033709 text : `
37043710 var __spread = (this && this.__spread) || function () {
@@ -3712,7 +3718,7 @@ namespace ts {
37123718 context . requestEmitHelper ( spreadHelper ) ;
37133719 return setTextRange (
37143720 createCall (
3715- getHelperName ( "__spread" ) ,
3721+ getUnscopedHelperName ( "__spread" ) ,
37163722 /*typeArguments*/ undefined ,
37173723 argumentList
37183724 ) ,
@@ -3722,6 +3728,7 @@ namespace ts {
37223728
37233729 export const spreadArraysHelper : UnscopedEmitHelper = {
37243730 name : "typescript:spreadArrays" ,
3731+ importName : "__spreadArrays" ,
37253732 scoped : false ,
37263733 text : `
37273734 var __spreadArrays = (this && this.__spreadArrays) || function () {
@@ -3737,7 +3744,7 @@ namespace ts {
37373744 context . requestEmitHelper ( spreadArraysHelper ) ;
37383745 return setTextRange (
37393746 createCall (
3740- getHelperName ( "__spreadArrays" ) ,
3747+ getUnscopedHelperName ( "__spreadArrays" ) ,
37413748 /*typeArguments*/ undefined ,
37423749 argumentList
37433750 ) ,
@@ -4863,6 +4870,65 @@ namespace ts {
48634870 return emitNode && emitNode . externalHelpersModuleName ;
48644871 }
48654872
4873+ export function hasRecordedExternalHelpers ( sourceFile : SourceFile ) {
4874+ const parseNode = getOriginalNode ( sourceFile , isSourceFile ) ;
4875+ const emitNode = parseNode && parseNode . emitNode ;
4876+ return ! ! emitNode && ( ! ! emitNode . externalHelpersModuleName || ! ! emitNode . externalHelpers ) ;
4877+ }
4878+
4879+ export function createExternalHelpersImportDeclarationIfNeeded ( sourceFile : SourceFile , compilerOptions : CompilerOptions , hasExportStarsToExportValues ?: boolean , hasImportStar ?: boolean , hasImportDefault ?: boolean ) {
4880+ if ( compilerOptions . importHelpers && isEffectiveExternalModule ( sourceFile , compilerOptions ) ) {
4881+ let namedBindings : NamedImportBindings | undefined ;
4882+ const moduleKind = getEmitModuleKind ( compilerOptions ) ;
4883+ if ( moduleKind >= ModuleKind . ES2015 && moduleKind <= ModuleKind . ESNext ) {
4884+ // use named imports
4885+ const helpers = getEmitHelpers ( sourceFile ) ;
4886+ if ( helpers ) {
4887+ const helperNames : string [ ] = [ ] ;
4888+ for ( const helper of helpers ) {
4889+ if ( ! helper . scoped ) {
4890+ const importName = ( helper as UnscopedEmitHelper ) . importName ;
4891+ if ( importName ) {
4892+ pushIfUnique ( helperNames , importName ) ;
4893+ }
4894+ }
4895+ }
4896+ if ( some ( helperNames ) ) {
4897+ helperNames . sort ( compareStringsCaseSensitive ) ;
4898+ // Alias the imports if the names are used somewhere in the file.
4899+ // NOTE: We don't need to care about global import collisions as this is a module.
4900+ namedBindings = createNamedImports (
4901+ map ( helperNames , name => isFileLevelUniqueName ( sourceFile , name )
4902+ ? createImportSpecifier ( /*propertyName*/ undefined , createIdentifier ( name ) )
4903+ : createImportSpecifier ( createIdentifier ( name ) , getUnscopedHelperName ( name ) )
4904+ )
4905+ ) ;
4906+ const parseNode = getOriginalNode ( sourceFile , isSourceFile ) ;
4907+ const emitNode = getOrCreateEmitNode ( parseNode ) ;
4908+ emitNode . externalHelpers = true ;
4909+ }
4910+ }
4911+ }
4912+ else {
4913+ // use a namespace import
4914+ const externalHelpersModuleName = getOrCreateExternalHelpersModuleNameIfNeeded ( sourceFile , compilerOptions , hasExportStarsToExportValues , hasImportStar || hasImportDefault ) ;
4915+ if ( externalHelpersModuleName ) {
4916+ namedBindings = createNamespaceImport ( externalHelpersModuleName ) ;
4917+ }
4918+ }
4919+ if ( namedBindings ) {
4920+ const externalHelpersImportDeclaration = createImportDeclaration (
4921+ /*decorators*/ undefined ,
4922+ /*modifiers*/ undefined ,
4923+ createImportClause ( /*name*/ undefined , namedBindings ) ,
4924+ createLiteral ( externalHelpersModuleNameText )
4925+ ) ;
4926+ addEmitFlags ( externalHelpersImportDeclaration , EmitFlags . NeverApplyImportHelper ) ;
4927+ return externalHelpersImportDeclaration ;
4928+ }
4929+ }
4930+ }
4931+
48664932 export function getOrCreateExternalHelpersModuleNameIfNeeded ( node : SourceFile , compilerOptions : CompilerOptions , hasExportStarsToExportValues ?: boolean , hasImportStarOrImportDefault ?: boolean ) {
48674933 if ( compilerOptions . importHelpers && isEffectiveExternalModule ( node , compilerOptions ) ) {
48684934 const externalHelpersModuleName = getExternalHelpersModuleName ( node ) ;
0 commit comments