1
1
/*@internal */
2
2
namespace ts {
3
3
4
- const enum ImportOrExportBindingReferenceKind {
5
- None ,
6
- ImportedHelper ,
7
- TopLevelExportBinding ,
8
- ImportClause ,
9
- ImportSpecifier ,
10
- }
11
-
12
- type ImportOrExportBindingReferenceResult =
13
- | { kind : ImportOrExportBindingReferenceKind . None , node : undefined }
14
- | { kind : ImportOrExportBindingReferenceKind . ImportedHelper , node : Identifier }
15
- | { kind : ImportOrExportBindingReferenceKind . TopLevelExportBinding , node : undefined }
16
- | { kind : ImportOrExportBindingReferenceKind . ImportClause , node : ImportClause }
17
- | { kind : ImportOrExportBindingReferenceKind . ImportSpecifier , node : ImportSpecifier } ;
18
-
19
- const noReferenceResult : ImportOrExportBindingReferenceResult = { kind : ImportOrExportBindingReferenceKind . None , node : undefined } ;
20
- const topLevelExportReferenceResult : ImportOrExportBindingReferenceResult = { kind : ImportOrExportBindingReferenceKind . TopLevelExportBinding , node : undefined } ;
21
-
22
4
export function transformModule ( context : TransformationContext ) {
23
5
interface AsynchronousDependencies {
24
6
aliasedModuleNames : Expression [ ] ;
@@ -67,7 +49,7 @@ namespace ts {
67
49
let currentModuleInfo : ExternalModuleInfo ; // The ExternalModuleInfo for the current file.
68
50
let noSubstitution : boolean [ ] ; // Set of nodes for which substitution rules should be ignored.
69
51
let needUMDDynamicImportHelper : boolean ;
70
- let bindingReferenceCache : ESMap < Node , ImportOrExportBindingReferenceResult > | undefined ;
52
+ let bindingReferenceCache : ESMap < Node , Identifier | SourceFile | ImportClause | ImportSpecifier | undefined > | undefined ;
71
53
72
54
return chainBundle ( context , transformSourceFile ) ;
73
55
@@ -1776,49 +1758,61 @@ namespace ts {
1776
1758
return node ;
1777
1759
}
1778
1760
1779
- function getImportOrExportBindingReferenceWorker ( node : Identifier ) : ImportOrExportBindingReferenceResult {
1761
+ /**
1762
+ * For an Identifier, gets the import or export binding that it references.
1763
+ * @returns One of the following:
1764
+ * - An `Identifier` if node references an external helpers module (i.e., `tslib`).
1765
+ * - A `SourceFile` if the node references an export in the file.
1766
+ * - An `ImportClause` or `ImportSpecifier` if the node references an import binding.
1767
+ * - Otherwise, `undefined`.
1768
+ */
1769
+ function getImportOrExportBindingReferenceWorker ( node : Identifier ) : Identifier | SourceFile | ImportClause | ImportSpecifier | undefined {
1780
1770
if ( getEmitFlags ( node ) & EmitFlags . HelperName ) {
1781
1771
const externalHelpersModuleName = getExternalHelpersModuleName ( currentSourceFile ) ;
1782
1772
if ( externalHelpersModuleName ) {
1783
- return { kind : ImportOrExportBindingReferenceKind . ImportedHelper , node : externalHelpersModuleName } ;
1773
+ return externalHelpersModuleName ;
1784
1774
}
1785
1775
}
1786
1776
else if ( ! ( isGeneratedIdentifier ( node ) && ! ( node . autoGenerateFlags & GeneratedIdentifierFlags . AllowNameSubstitution ) ) && ! isLocalName ( node ) ) {
1787
1777
const exportContainer = resolver . getReferencedExportContainer ( node , isExportName ( node ) ) ;
1788
1778
if ( exportContainer ?. kind === SyntaxKind . SourceFile ) {
1789
- return topLevelExportReferenceResult ;
1779
+ return exportContainer ;
1790
1780
}
1791
1781
const importDeclaration = resolver . getReferencedImportDeclaration ( node ) ;
1792
- if ( importDeclaration ) {
1793
- if ( isImportClause ( importDeclaration ) ) return { kind : ImportOrExportBindingReferenceKind . ImportClause , node : importDeclaration } ;
1794
- if ( isImportSpecifier ( importDeclaration ) ) return { kind : ImportOrExportBindingReferenceKind . ImportSpecifier , node : importDeclaration } ;
1782
+ if ( importDeclaration && ( isImportClause ( importDeclaration ) || isImportSpecifier ( importDeclaration ) ) ) {
1783
+ return importDeclaration ;
1795
1784
}
1796
1785
}
1797
- return noReferenceResult ;
1786
+ return undefined ;
1798
1787
}
1799
1788
1800
- function getImportOrExportBindingReference ( node : Identifier , removeEntry : boolean ) : ImportOrExportBindingReferenceResult {
1801
- bindingReferenceCache ||= new Map ( ) ;
1802
- let result = bindingReferenceCache . get ( node ) ;
1803
- if ( ! result ) {
1789
+ /**
1790
+ * For an Identifier, gets the import or export binding that it references.
1791
+ * @param removeEntry When `false`, the result is cached to avoid recomputing the result in a later substitution.
1792
+ * When `true`, any cached result for the node is removed.
1793
+ * @returns One of the following:
1794
+ * - An `Identifier` if node references an external helpers module (i.e., `tslib`).
1795
+ * - A `SourceFile` if the node references an export in the file.
1796
+ * - An `ImportClause` or `ImportSpecifier` if the node references an import binding.
1797
+ * - Otherwise, `undefined`.
1798
+ */
1799
+ function getImportOrExportBindingReference ( node : Identifier , removeEntry : boolean ) : Identifier | SourceFile | ImportClause | ImportSpecifier | undefined {
1800
+ let result = bindingReferenceCache ?. get ( node ) ;
1801
+ if ( ! result && ! bindingReferenceCache ?. has ( node ) ) {
1804
1802
result = getImportOrExportBindingReferenceWorker ( node ) ;
1805
1803
if ( ! removeEntry ) {
1806
- switch ( result . kind ) {
1807
- case ImportOrExportBindingReferenceKind . ImportedHelper :
1808
- case ImportOrExportBindingReferenceKind . ImportClause :
1809
- case ImportOrExportBindingReferenceKind . ImportSpecifier :
1810
- bindingReferenceCache . set ( node , result ) ;
1811
- }
1804
+ bindingReferenceCache ||= new Map ( ) ;
1805
+ bindingReferenceCache . set ( node , result ) ;
1812
1806
}
1813
1807
}
1814
1808
else if ( removeEntry ) {
1815
- bindingReferenceCache . delete ( node ) ;
1809
+ bindingReferenceCache ? .delete ( node ) ;
1816
1810
}
1817
1811
return result ;
1818
1812
}
1819
1813
1820
1814
function substituteCallExpression ( node : CallExpression ) {
1821
- if ( isIdentifier ( node . expression ) && getImportOrExportBindingReference ( node . expression , /*removeEntry*/ false ) . kind !== ImportOrExportBindingReferenceKind . None ) {
1815
+ if ( isIdentifier ( node . expression ) && getImportOrExportBindingReference ( node . expression , /*removeEntry*/ false ) ) {
1822
1816
return isCallChain ( node ) ?
1823
1817
factory . updateCallChain ( node ,
1824
1818
setTextRange ( factory . createComma ( factory . createNumericLiteral ( 0 ) , node . expression ) , node . expression ) ,
@@ -1834,7 +1828,7 @@ namespace ts {
1834
1828
}
1835
1829
1836
1830
function substituteTaggedTemplateExpression ( node : TaggedTemplateExpression ) {
1837
- if ( isIdentifier ( node . tag ) && getImportOrExportBindingReference ( node . tag , /*removeEntry*/ false ) . kind !== ImportOrExportBindingReferenceKind . None ) {
1831
+ if ( isIdentifier ( node . tag ) && getImportOrExportBindingReference ( node . tag , /*removeEntry*/ false ) ) {
1838
1832
return factory . updateTaggedTemplateExpression (
1839
1833
node ,
1840
1834
setTextRange ( factory . createComma ( factory . createNumericLiteral ( 0 ) , node . tag ) , node . tag ) ,
@@ -1852,30 +1846,30 @@ namespace ts {
1852
1846
*/
1853
1847
function substituteExpressionIdentifier ( node : Identifier ) : Expression {
1854
1848
const result = getImportOrExportBindingReference ( node , /*removeEntry*/ true ) ;
1855
- switch ( result . kind ) {
1856
- case ImportOrExportBindingReferenceKind . ImportedHelper :
1857
- return factory . createPropertyAccessExpression ( result . node , node ) ;
1858
- case ImportOrExportBindingReferenceKind . TopLevelExportBinding :
1849
+ switch ( result ? .kind ) {
1850
+ case SyntaxKind . Identifier : // tslib import
1851
+ return factory . createPropertyAccessExpression ( result , node ) ;
1852
+ case SyntaxKind . SourceFile : // top-level export
1859
1853
return setTextRange (
1860
1854
factory . createPropertyAccessExpression (
1861
1855
factory . createIdentifier ( "exports" ) ,
1862
1856
factory . cloneNode ( node )
1863
1857
) ,
1864
1858
/*location*/ node
1865
1859
) ;
1866
- case ImportOrExportBindingReferenceKind . ImportClause :
1860
+ case SyntaxKind . ImportClause :
1867
1861
return setTextRange (
1868
1862
factory . createPropertyAccessExpression (
1869
- factory . getGeneratedNameForNode ( result . node . parent ) ,
1863
+ factory . getGeneratedNameForNode ( result . parent ) ,
1870
1864
factory . createIdentifier ( "default" )
1871
1865
) ,
1872
1866
/*location*/ node
1873
1867
) ;
1874
- case ImportOrExportBindingReferenceKind . ImportSpecifier :
1875
- const name = result . node . propertyName || result . node . name ;
1868
+ case SyntaxKind . ImportSpecifier :
1869
+ const name = result . propertyName || result . name ;
1876
1870
return setTextRange (
1877
1871
factory . createPropertyAccessExpression (
1878
- factory . getGeneratedNameForNode ( result . node . parent ?. parent ?. parent || result . node ) ,
1872
+ factory . getGeneratedNameForNode ( result . parent ?. parent ?. parent || result ) ,
1879
1873
factory . cloneNode ( name )
1880
1874
) ,
1881
1875
/*location*/ node
0 commit comments