@@ -63,6 +63,8 @@ export function updateSourceFile(
63
63
sourceFile : ts . SourceFile , module : PartialModule ,
64
64
context : ts . TransformationContext ) : [ ts . SourceFile , Map < ts . Node , Node > ] {
65
65
const converter = new _NodeEmitterVisitor ( ) ;
66
+ converter . loadExportedVariableIdentifiers ( sourceFile ) ;
67
+
66
68
const prefixStatements = module . statements . filter ( statement => ! ( statement instanceof ClassStmt ) ) ;
67
69
const classes =
68
70
module . statements . filter ( statement => statement instanceof ClassStmt ) as ClassStmt [ ] ;
@@ -158,6 +160,11 @@ function createLiteral(value: any) {
158
160
}
159
161
}
160
162
163
+ function isExportTypeStatement ( statement : ts . Statement ) : boolean {
164
+ return ! ! statement . modifiers &&
165
+ statement . modifiers . some ( mod => mod . kind === ts . SyntaxKind . ExportKeyword ) ;
166
+ }
167
+
161
168
/**
162
169
* Visits an output ast and produces the corresponding TypeScript synthetic nodes.
163
170
*/
@@ -166,6 +173,26 @@ class _NodeEmitterVisitor implements StatementVisitor, ExpressionVisitor {
166
173
private _importsWithPrefixes = new Map < string , string > ( ) ;
167
174
private _reexports = new Map < string , { name : string , as : string } [ ] > ( ) ;
168
175
private _templateSources = new Map < ParseSourceFile , ts . SourceMapSource > ( ) ;
176
+ private _exportedVariableIdentifiers = new Map < string , ts . Identifier > ( ) ;
177
+
178
+ /**
179
+ * Process the source file and collect exported identifiers that refer to variables.
180
+ *
181
+ * Only variables are collected because exported classes still exist in the module scope in
182
+ * CommonJS, whereas variables have their declarations moved onto the `exports` object, and all
183
+ * references are updated accordingly.
184
+ */
185
+ loadExportedVariableIdentifiers ( sourceFile : ts . SourceFile ) : void {
186
+ sourceFile . statements . forEach ( statement => {
187
+ if ( ts . isVariableStatement ( statement ) && isExportTypeStatement ( statement ) ) {
188
+ statement . declarationList . declarations . forEach ( declaration => {
189
+ if ( ts . isIdentifier ( declaration . name ) ) {
190
+ this . _exportedVariableIdentifiers . set ( declaration . name . text , declaration . name ) ;
191
+ }
192
+ } ) ;
193
+ }
194
+ } ) ;
195
+ }
169
196
170
197
getReexports ( ) : ts . Statement [ ] {
171
198
return Array . from ( this . _reexports . entries ( ) )
@@ -612,7 +639,8 @@ class _NodeEmitterVisitor implements StatementVisitor, ExpressionVisitor {
612
639
}
613
640
614
641
private _visitIdentifier ( value : ExternalReference ) : ts . Expression {
615
- const { name, moduleName} = value ;
642
+ // name can only be null during JIT which never executes this code.
643
+ const moduleName = value . moduleName , name = value . name ! ;
616
644
let prefixIdent : ts . Identifier | null = null ;
617
645
if ( moduleName ) {
618
646
let prefix = this . _importsWithPrefixes . get ( moduleName ) ;
@@ -622,10 +650,17 @@ class _NodeEmitterVisitor implements StatementVisitor, ExpressionVisitor {
622
650
}
623
651
prefixIdent = ts . createIdentifier ( prefix ) ;
624
652
}
625
- // name can only be null during JIT which never executes this code.
626
- let result : ts . Expression =
627
- prefixIdent ? ts . createPropertyAccess ( prefixIdent , name ! ) : ts . createIdentifier ( name ! ) ;
628
- return result ;
653
+ if ( prefixIdent ) {
654
+ return ts . createPropertyAccess ( prefixIdent , name ) ;
655
+ } else {
656
+ const id = ts . createIdentifier ( name ) ;
657
+ if ( this . _exportedVariableIdentifiers . has ( name ) ) {
658
+ // In order for this new identifier node to be properly rewritten in CommonJS output,
659
+ // it must have its original node set to a parsed instance of the same identifier.
660
+ ts . setOriginalNode ( id , this . _exportedVariableIdentifiers . get ( name ) ) ;
661
+ }
662
+ return id ;
663
+ }
629
664
}
630
665
}
631
666
0 commit comments