@@ -265,6 +265,7 @@ namespace ts {
265265 return "export=" ;
266266 case SpecialPropertyAssignmentKind . ExportsProperty :
267267 case SpecialPropertyAssignmentKind . ThisProperty :
268+ case SpecialPropertyAssignmentKind . Property :
268269 // exports.x = ... or this.y = ...
269270 return ( ( node as BinaryExpression ) . left as PropertyAccessExpression ) . name . text ;
270271 case SpecialPropertyAssignmentKind . PrototypeProperty :
@@ -1051,8 +1052,8 @@ namespace ts {
10511052 // second -> edge that represents post-finally flow.
10521053 // these edges are used in following scenario:
10531054 // let a; (1)
1054- // try { a = someOperation(); (2)}
1055- // finally { (3) console.log(a) } (4)
1055+ // try { a = someOperation(); (2)}
1056+ // finally { (3) console.log(a) } (4)
10561057 // (5) a
10571058
10581059 // flow graph for this case looks roughly like this (arrows show ):
@@ -1064,11 +1065,11 @@ namespace ts {
10641065 // In case when we walk the flow starting from inside the finally block we want to take edge '*****' into account
10651066 // since it ensures that finally is always reachable. However when we start outside the finally block and go through label (5)
10661067 // then edge '*****' should be discarded because label 4 is only reachable if post-finally label-4 is reachable
1067- // Simply speaking code inside finally block is treated as reachable as pre-try-flow
1068+ // Simply speaking code inside finally block is treated as reachable as pre-try-flow
10681069 // since we conservatively assume that any line in try block can throw or return in which case we'll enter finally.
10691070 // However code after finally is reachable only if control flow was not abrupted in try/catch or finally blocks - it should be composed from
10701071 // final flows of these blocks without taking pre-try flow into account.
1071- //
1072+ //
10721073 // extra edges that we inject allows to control this behavior
10731074 // if when walking the flow we step on post-finally edge - we can mark matching pre-finally edge as locked so it will be skipped.
10741075 const preFinallyFlow : PreFinallyFlow = { flags : FlowFlags . PreFinally , antecedent : preTryFlow , lock : { } } ;
@@ -1969,6 +1970,9 @@ namespace ts {
19691970 case SpecialPropertyAssignmentKind . ThisProperty :
19701971 bindThisPropertyAssignment ( < BinaryExpression > node ) ;
19711972 break ;
1973+ case SpecialPropertyAssignmentKind . Property :
1974+ bindStaticPropertyAssignment ( < BinaryExpression > node ) ;
1975+ break ;
19721976 case SpecialPropertyAssignmentKind . None :
19731977 // Nothing to do
19741978 break ;
@@ -2265,18 +2269,41 @@ namespace ts {
22652269 constructorFunction . parent = classPrototype ;
22662270 classPrototype . parent = leftSideOfAssignment ;
22672271
2268- const funcSymbol = container . locals . get ( constructorFunction . text ) ;
2269- if ( ! funcSymbol || ! ( funcSymbol . flags & SymbolFlags . Function || isDeclarationOfFunctionExpression ( funcSymbol ) ) ) {
2272+ bindPropertyAssignment ( constructorFunction . text , leftSideOfAssignment , /*isPrototypeProperty*/ true ) ;
2273+ }
2274+
2275+ function bindStaticPropertyAssignment ( node : BinaryExpression ) {
2276+ // We saw a node of the form 'x.y = z'. Declare a 'member' y on x if x was a function.
2277+
2278+ // Look up the function in the local scope, since prototype assignments should
2279+ // follow the function declaration
2280+ const leftSideOfAssignment = node . left as PropertyAccessExpression ;
2281+ const target = leftSideOfAssignment . expression as Identifier ;
2282+
2283+ // Fix up parent pointers since we're going to use these nodes before we bind into them
2284+ leftSideOfAssignment . parent = node ;
2285+ target . parent = leftSideOfAssignment ;
2286+
2287+ bindPropertyAssignment ( target . text , leftSideOfAssignment , /*isPrototypeProperty*/ false ) ;
2288+ }
2289+
2290+ function bindPropertyAssignment ( functionName : string , propertyAccessExpression : PropertyAccessExpression , isPrototypeProperty : boolean ) {
2291+ let targetSymbol = container . locals . get ( functionName ) ;
2292+ if ( targetSymbol && isDeclarationOfFunctionOrClassExpression ( targetSymbol ) ) {
2293+ targetSymbol = ( targetSymbol . valueDeclaration as VariableDeclaration ) . initializer . symbol ;
2294+ }
2295+
2296+ if ( ! targetSymbol || ! ( targetSymbol . flags & ( SymbolFlags . Function | SymbolFlags . Class ) ) ) {
22702297 return ;
22712298 }
22722299
22732300 // Set up the members collection if it doesn't exist already
2274- if ( ! funcSymbol . members ) {
2275- funcSymbol . members = createMap < Symbol > ( ) ;
2276- }
2301+ const symbolTable = isPrototypeProperty ?
2302+ ( targetSymbol . members || ( targetSymbol . members = createMap < Symbol > ( ) ) ) :
2303+ ( targetSymbol . exports || ( targetSymbol . exports = createMap < Symbol > ( ) ) ) ;
22772304
22782305 // Declare the method/property
2279- declareSymbol ( funcSymbol . members , funcSymbol , leftSideOfAssignment , SymbolFlags . Property , SymbolFlags . PropertyExcludes ) ;
2306+ declareSymbol ( symbolTable , targetSymbol , propertyAccessExpression , SymbolFlags . Property , SymbolFlags . PropertyExcludes ) ;
22802307 }
22812308
22822309 function bindCallExpression ( node : CallExpression ) {
0 commit comments