@@ -6,8 +6,8 @@ namespace ts {
6
6
7
7
export const enum ModuleInstanceState {
8
8
NonInstantiated = 0 ,
9
- Instantiated = 1 ,
10
- ConstEnumOnly = 2
9
+ Instantiated = 1 ,
10
+ ConstEnumOnly = 2
11
11
}
12
12
13
13
export function getModuleInstanceState ( node : Node ) : ModuleInstanceState {
@@ -90,6 +90,8 @@ namespace ts {
90
90
let lastContainer : Node ;
91
91
let seenThisKeyword : boolean ;
92
92
93
+ let isJavaScriptFile = isSourceFileJavaScript ( file ) ;
94
+
93
95
// If this file is an external module, then it is automatically in strict-mode according to
94
96
// ES6. If it is not an external module, then we'll determine if it is in strict mode or
95
97
// not depending on if we see "use strict" in certain places (or if we hit a class/namespace).
@@ -167,6 +169,10 @@ namespace ts {
167
169
case SyntaxKind . FunctionDeclaration :
168
170
case SyntaxKind . ClassDeclaration :
169
171
return node . flags & NodeFlags . Default ? "default" : undefined ;
172
+
173
+ case SyntaxKind . BinaryExpression :
174
+ Debug . assert ( isModuleExportsAssignment ( node ) ) ;
175
+ return "__jsExports" ;
170
176
}
171
177
}
172
178
@@ -779,7 +785,7 @@ namespace ts {
779
785
return "__" + indexOf ( ( < SignatureDeclaration > node . parent ) . parameters , node ) ;
780
786
}
781
787
782
- function bind ( node : Node ) {
788
+ function bind ( node : Node ) : void {
783
789
node . parent = parent ;
784
790
785
791
let savedInStrictMode = inStrictMode ;
@@ -851,9 +857,18 @@ namespace ts {
851
857
852
858
function bindWorker ( node : Node ) {
853
859
switch ( node . kind ) {
860
+ /* Strict mode checks */
854
861
case SyntaxKind . Identifier :
855
862
return checkStrictModeIdentifier ( < Identifier > node ) ;
856
863
case SyntaxKind . BinaryExpression :
864
+ if ( isJavaScriptFile ) {
865
+ if ( isExportsPropertyAssignment ( node ) ) {
866
+ bindExportsPropertyAssignment ( < BinaryExpression > node ) ;
867
+ }
868
+ else if ( isModuleExportsAssignment ( node ) ) {
869
+ bindModuleExportsAssignment ( < BinaryExpression > node ) ;
870
+ }
871
+ }
857
872
return checkStrictModeBinaryExpression ( < BinaryExpression > node ) ;
858
873
case SyntaxKind . CatchClause :
859
874
return checkStrictModeCatchClause ( < CatchClause > node ) ;
@@ -919,6 +934,16 @@ namespace ts {
919
934
checkStrictModeFunctionName ( < FunctionExpression > node ) ;
920
935
let bindingName = ( < FunctionExpression > node ) . name ? ( < FunctionExpression > node ) . name . text : "__function" ;
921
936
return bindAnonymousDeclaration ( < FunctionExpression > node , SymbolFlags . Function , bindingName ) ;
937
+
938
+ case SyntaxKind . CallExpression :
939
+ // We're only inspecting call expressions to detect CommonJS modules, so we can skip
940
+ // this check if we've already seen the module indicator
941
+ if ( isJavaScriptFile && ! file . commonJsModuleIndicator ) {
942
+ bindCallExpression ( < CallExpression > node ) ;
943
+ }
944
+ break ;
945
+
946
+ // Members of classes, interfaces, and modules
922
947
case SyntaxKind . ClassExpression :
923
948
case SyntaxKind . ClassDeclaration :
924
949
return bindClassLikeDeclaration ( < ClassLikeDeclaration > node ) ;
@@ -930,6 +955,8 @@ namespace ts {
930
955
return bindEnumDeclaration ( < EnumDeclaration > node ) ;
931
956
case SyntaxKind . ModuleDeclaration :
932
957
return bindModuleDeclaration ( < ModuleDeclaration > node ) ;
958
+
959
+ // Imports and exports
933
960
case SyntaxKind . ImportEqualsDeclaration :
934
961
case SyntaxKind . NamespaceImport :
935
962
case SyntaxKind . ImportSpecifier :
@@ -949,10 +976,14 @@ namespace ts {
949
976
function bindSourceFileIfExternalModule ( ) {
950
977
setExportContextFlag ( file ) ;
951
978
if ( isExternalModule ( file ) ) {
952
- bindAnonymousDeclaration ( file , SymbolFlags . ValueModule , `" ${ removeFileExtension ( file . fileName ) } "` ) ;
979
+ bindSourceFileAsExternalModule ( ) ;
953
980
}
954
981
}
955
982
983
+ function bindSourceFileAsExternalModule ( ) {
984
+ bindAnonymousDeclaration ( file , SymbolFlags . ValueModule , `"${ removeFileExtension ( file . fileName ) } "` ) ;
985
+ }
986
+
956
987
function bindExportAssignment ( node : ExportAssignment ) {
957
988
if ( ! container . symbol || ! container . symbol . exports ) {
958
989
// Export assignment in some sort of block construct
@@ -985,6 +1016,32 @@ namespace ts {
985
1016
}
986
1017
}
987
1018
1019
+ function setCommonJsModuleIndicator ( node : Node ) {
1020
+ if ( ! file . commonJsModuleIndicator ) {
1021
+ file . commonJsModuleIndicator = node ;
1022
+ bindSourceFileAsExternalModule ( ) ;
1023
+ }
1024
+ }
1025
+
1026
+ function bindExportsPropertyAssignment ( node : BinaryExpression ) {
1027
+ // When we create a property via 'exports.foo = bar', the 'exports.foo' property access
1028
+ // expression is the declaration
1029
+ setCommonJsModuleIndicator ( node ) ;
1030
+ declareSymbol ( file . symbol . exports , file . symbol , < PropertyAccessExpression > node . left , SymbolFlags . Property | SymbolFlags . Export , SymbolFlags . None ) ;
1031
+ }
1032
+
1033
+ function bindModuleExportsAssignment ( node : BinaryExpression ) {
1034
+ // 'module.exports = expr' assignment
1035
+ setCommonJsModuleIndicator ( node ) ;
1036
+ declareSymbol ( file . symbol . exports , file . symbol , node , SymbolFlags . None , SymbolFlags . None ) ;
1037
+ }
1038
+
1039
+ function bindCallExpression ( node : CallExpression ) {
1040
+ if ( isRequireCall ( node ) ) {
1041
+ setCommonJsModuleIndicator ( node ) ;
1042
+ }
1043
+ }
1044
+
988
1045
function bindClassLikeDeclaration ( node : ClassLikeDeclaration ) {
989
1046
if ( node . kind === SyntaxKind . ClassDeclaration ) {
990
1047
bindBlockScopedDeclaration ( node , SymbolFlags . Class , SymbolFlags . ClassExcludes ) ;
0 commit comments