1
+ /// <reference path="utilities.ts"/>
1
2
/// <reference path="parser.ts"/>
2
3
3
4
/* @internal */
@@ -6,8 +7,8 @@ namespace ts {
6
7
7
8
export const enum ModuleInstanceState {
8
9
NonInstantiated = 0 ,
9
- Instantiated = 1 ,
10
- ConstEnumOnly = 2
10
+ Instantiated = 1 ,
11
+ ConstEnumOnly = 2
11
12
}
12
13
13
14
const enum Reachability {
@@ -188,6 +189,11 @@ namespace ts {
188
189
}
189
190
if ( node . name . kind === SyntaxKind . ComputedPropertyName ) {
190
191
const nameExpression = ( < ComputedPropertyName > node . name ) . expression ;
192
+ // treat computed property names where expression is string/numeric literal as just string/numeric literal
193
+ if ( isStringOrNumericLiteral ( nameExpression . kind ) ) {
194
+ return ( < LiteralExpression > nameExpression ) . text ;
195
+ }
196
+
191
197
Debug . assert ( isWellKnownSymbolSyntactically ( nameExpression ) ) ;
192
198
return getPropertyNameForKnownSymbolName ( ( < PropertyAccessExpression > nameExpression ) . name . text ) ;
193
199
}
@@ -208,6 +214,9 @@ namespace ts {
208
214
return "__export" ;
209
215
case SyntaxKind . ExportAssignment :
210
216
return ( < ExportAssignment > node ) . isExportEquals ? "export=" : "default" ;
217
+ case SyntaxKind . BinaryExpression :
218
+ // Binary expression case is for JS module 'module.exports = expr'
219
+ return "export=" ;
211
220
case SyntaxKind . FunctionDeclaration :
212
221
case SyntaxKind . ClassDeclaration :
213
222
return node . flags & NodeFlags . Default ? "default" : undefined ;
@@ -1069,7 +1078,7 @@ namespace ts {
1069
1078
return "__" + indexOf ( ( < SignatureDeclaration > node . parent ) . parameters , node ) ;
1070
1079
}
1071
1080
1072
- function bind ( node : Node ) {
1081
+ function bind ( node : Node ) : void {
1073
1082
if ( ! node ) {
1074
1083
return ;
1075
1084
}
@@ -1145,9 +1154,18 @@ namespace ts {
1145
1154
1146
1155
function bindWorker ( node : Node ) {
1147
1156
switch ( node . kind ) {
1157
+ /* Strict mode checks */
1148
1158
case SyntaxKind . Identifier :
1149
1159
return checkStrictModeIdentifier ( < Identifier > node ) ;
1150
1160
case SyntaxKind . BinaryExpression :
1161
+ if ( isInJavaScriptFile ( node ) ) {
1162
+ if ( isExportsPropertyAssignment ( node ) ) {
1163
+ bindExportsPropertyAssignment ( < BinaryExpression > node ) ;
1164
+ }
1165
+ else if ( isModuleExportsAssignment ( node ) ) {
1166
+ bindModuleExportsAssignment ( < BinaryExpression > node ) ;
1167
+ }
1168
+ }
1151
1169
return checkStrictModeBinaryExpression ( < BinaryExpression > node ) ;
1152
1170
case SyntaxKind . CatchClause :
1153
1171
return checkStrictModeCatchClause ( < CatchClause > node ) ;
@@ -1213,6 +1231,14 @@ namespace ts {
1213
1231
checkStrictModeFunctionName ( < FunctionExpression > node ) ;
1214
1232
const bindingName = ( < FunctionExpression > node ) . name ? ( < FunctionExpression > node ) . name . text : "__function" ;
1215
1233
return bindAnonymousDeclaration ( < FunctionExpression > node , SymbolFlags . Function , bindingName ) ;
1234
+
1235
+ case SyntaxKind . CallExpression :
1236
+ if ( isInJavaScriptFile ( node ) ) {
1237
+ bindCallExpression ( < CallExpression > node ) ;
1238
+ }
1239
+ break ;
1240
+
1241
+ // Members of classes, interfaces, and modules
1216
1242
case SyntaxKind . ClassExpression :
1217
1243
case SyntaxKind . ClassDeclaration :
1218
1244
return bindClassLikeDeclaration ( < ClassLikeDeclaration > node ) ;
@@ -1224,6 +1250,8 @@ namespace ts {
1224
1250
return bindEnumDeclaration ( < EnumDeclaration > node ) ;
1225
1251
case SyntaxKind . ModuleDeclaration :
1226
1252
return bindModuleDeclaration ( < ModuleDeclaration > node ) ;
1253
+
1254
+ // Imports and exports
1227
1255
case SyntaxKind . ImportEqualsDeclaration :
1228
1256
case SyntaxKind . NamespaceImport :
1229
1257
case SyntaxKind . ImportSpecifier :
@@ -1243,16 +1271,21 @@ namespace ts {
1243
1271
function bindSourceFileIfExternalModule ( ) {
1244
1272
setExportContextFlag ( file ) ;
1245
1273
if ( isExternalModule ( file ) ) {
1246
- bindAnonymousDeclaration ( file , SymbolFlags . ValueModule , `" ${ removeFileExtension ( file . fileName ) } "` ) ;
1274
+ bindSourceFileAsExternalModule ( ) ;
1247
1275
}
1248
1276
}
1249
1277
1250
- function bindExportAssignment ( node : ExportAssignment ) {
1278
+ function bindSourceFileAsExternalModule ( ) {
1279
+ bindAnonymousDeclaration ( file , SymbolFlags . ValueModule , `"${ removeFileExtension ( file . fileName ) } "` ) ;
1280
+ }
1281
+
1282
+ function bindExportAssignment ( node : ExportAssignment | BinaryExpression ) {
1283
+ const boundExpression = node . kind === SyntaxKind . ExportAssignment ? ( < ExportAssignment > node ) . expression : ( < BinaryExpression > node ) . right ;
1251
1284
if ( ! container . symbol || ! container . symbol . exports ) {
1252
1285
// Export assignment in some sort of block construct
1253
1286
bindAnonymousDeclaration ( node , SymbolFlags . Alias , getDeclarationName ( node ) ) ;
1254
1287
}
1255
- else if ( node . expression . kind === SyntaxKind . Identifier ) {
1288
+ else if ( boundExpression . kind === SyntaxKind . Identifier ) {
1256
1289
// An export default clause with an identifier exports all meanings of that identifier
1257
1290
declareSymbol ( container . symbol . exports , container . symbol , node , SymbolFlags . Alias , SymbolFlags . PropertyExcludes | SymbolFlags . AliasExcludes ) ;
1258
1291
}
@@ -1279,6 +1312,34 @@ namespace ts {
1279
1312
}
1280
1313
}
1281
1314
1315
+ function setCommonJsModuleIndicator ( node : Node ) {
1316
+ if ( ! file . commonJsModuleIndicator ) {
1317
+ file . commonJsModuleIndicator = node ;
1318
+ bindSourceFileAsExternalModule ( ) ;
1319
+ }
1320
+ }
1321
+
1322
+ function bindExportsPropertyAssignment ( node : BinaryExpression ) {
1323
+ // When we create a property via 'exports.foo = bar', the 'exports.foo' property access
1324
+ // expression is the declaration
1325
+ setCommonJsModuleIndicator ( node ) ;
1326
+ declareSymbol ( file . symbol . exports , file . symbol , < PropertyAccessExpression > node . left , SymbolFlags . Property | SymbolFlags . Export , SymbolFlags . None ) ;
1327
+ }
1328
+
1329
+ function bindModuleExportsAssignment ( node : BinaryExpression ) {
1330
+ // 'module.exports = expr' assignment
1331
+ setCommonJsModuleIndicator ( node ) ;
1332
+ bindExportAssignment ( node ) ;
1333
+ }
1334
+
1335
+ function bindCallExpression ( node : CallExpression ) {
1336
+ // We're only inspecting call expressions to detect CommonJS modules, so we can skip
1337
+ // this check if we've already seen the module indicator
1338
+ if ( ! file . commonJsModuleIndicator && isRequireCall ( node ) ) {
1339
+ setCommonJsModuleIndicator ( node ) ;
1340
+ }
1341
+ }
1342
+
1282
1343
function bindClassLikeDeclaration ( node : ClassLikeDeclaration ) {
1283
1344
if ( node . kind === SyntaxKind . ClassDeclaration ) {
1284
1345
bindBlockScopedDeclaration ( node , SymbolFlags . Class , SymbolFlags . ClassExcludes ) ;
0 commit comments