@@ -222,8 +222,21 @@ namespace ts {
222
222
case SyntaxKind . ExportAssignment :
223
223
return ( < ExportAssignment > node ) . isExportEquals ? "export=" : "default" ;
224
224
case SyntaxKind . BinaryExpression :
225
- // Binary expression case is for JS module 'module.exports = expr'
226
- return "export=" ;
225
+ switch ( getSpecialPropertyAssignmentKind ( node ) ) {
226
+ case SpecialPropertyAssignmentKind . ModuleExports :
227
+ // module.exports = ...
228
+ return "export=" ;
229
+ case SpecialPropertyAssignmentKind . ExportsProperty :
230
+ case SpecialPropertyAssignmentKind . ThisProperty :
231
+ // exports.x = ... or this.y = ...
232
+ return ( ( node as BinaryExpression ) . left as PropertyAccessExpression ) . name . text ;
233
+ case SpecialPropertyAssignmentKind . PrototypeProperty :
234
+ // className.prototype.methodName = ...
235
+ return ( ( ( node as BinaryExpression ) . left as PropertyAccessExpression ) . expression as PropertyAccessExpression ) . name . text ;
236
+ }
237
+ Debug . fail ( "Unknown binary declaration kind" ) ;
238
+ break ;
239
+
227
240
case SyntaxKind . FunctionDeclaration :
228
241
case SyntaxKind . ClassDeclaration :
229
242
return node . flags & NodeFlags . Default ? "default" : undefined ;
@@ -1166,11 +1179,25 @@ namespace ts {
1166
1179
return checkStrictModeIdentifier ( < Identifier > node ) ;
1167
1180
case SyntaxKind . BinaryExpression :
1168
1181
if ( isInJavaScriptFile ( node ) ) {
1169
- if ( isExportsPropertyAssignment ( node ) ) {
1170
- bindExportsPropertyAssignment ( < BinaryExpression > node ) ;
1171
- }
1172
- else if ( isModuleExportsAssignment ( node ) ) {
1173
- bindModuleExportsAssignment ( < BinaryExpression > node ) ;
1182
+ const specialKind = getSpecialPropertyAssignmentKind ( node ) ;
1183
+ switch ( specialKind ) {
1184
+ case SpecialPropertyAssignmentKind . ExportsProperty :
1185
+ bindExportsPropertyAssignment ( < BinaryExpression > node ) ;
1186
+ break ;
1187
+ case SpecialPropertyAssignmentKind . ModuleExports :
1188
+ bindModuleExportsAssignment ( < BinaryExpression > node ) ;
1189
+ break ;
1190
+ case SpecialPropertyAssignmentKind . PrototypeProperty :
1191
+ bindPrototypePropertyAssignment ( < BinaryExpression > node ) ;
1192
+ break ;
1193
+ case SpecialPropertyAssignmentKind . ThisProperty :
1194
+ bindThisPropertyAssignment ( < BinaryExpression > node ) ;
1195
+ break ;
1196
+ case SpecialPropertyAssignmentKind . None :
1197
+ // Nothing to do
1198
+ break ;
1199
+ default :
1200
+ Debug . fail ( "Unknown special property assignment kind" ) ;
1174
1201
}
1175
1202
}
1176
1203
return checkStrictModeBinaryExpression ( < BinaryExpression > node ) ;
@@ -1351,6 +1378,34 @@ namespace ts {
1351
1378
bindExportAssignment ( node ) ;
1352
1379
}
1353
1380
1381
+ function bindThisPropertyAssignment ( node : BinaryExpression ) {
1382
+ // Declare a 'member' in case it turns out the container was an ES5 class
1383
+ if ( container . kind === SyntaxKind . FunctionExpression || container . kind === SyntaxKind . FunctionDeclaration ) {
1384
+ container . symbol . members = container . symbol . members || { } ;
1385
+ declareSymbol ( container . symbol . members , container . symbol , node , SymbolFlags . Property , SymbolFlags . PropertyExcludes ) ;
1386
+ }
1387
+ }
1388
+
1389
+ function bindPrototypePropertyAssignment ( node : BinaryExpression ) {
1390
+ // We saw a node of the form 'x.prototype.y = z'. Declare a 'member' y on x if x was a function.
1391
+
1392
+ // Look up the function in the local scope, since prototype assignments should
1393
+ // follow the function declaration
1394
+ const classId = < Identifier > ( < PropertyAccessExpression > ( < PropertyAccessExpression > node . left ) . expression ) . expression ;
1395
+ const funcSymbol = container . locals [ classId . text ] ;
1396
+ if ( ! funcSymbol || ! ( funcSymbol . flags & SymbolFlags . Function ) ) {
1397
+ return ;
1398
+ }
1399
+
1400
+ // Set up the members collection if it doesn't exist already
1401
+ if ( ! funcSymbol . members ) {
1402
+ funcSymbol . members = { } ;
1403
+ }
1404
+
1405
+ // Declare the method/property
1406
+ declareSymbol ( funcSymbol . members , funcSymbol , < PropertyAccessExpression > node . left , SymbolFlags . Property , SymbolFlags . PropertyExcludes ) ;
1407
+ }
1408
+
1354
1409
function bindCallExpression ( node : CallExpression ) {
1355
1410
// We're only inspecting call expressions to detect CommonJS modules, so we can skip
1356
1411
// this check if we've already seen the module indicator
0 commit comments