@@ -145,7 +145,7 @@ namespace ts {
145145 loopOutParameters : LoopOutParameter [ ] ;
146146 }
147147
148- type LoopConverter = ( node : IterationStatement , outermostLabeledStatement : LabeledStatement | undefined , convertedLoopBodyStatements : Statement [ ] | undefined ) => Statement ;
148+ type LoopConverter = ( node : IterationStatement , outermostLabeledStatement : LabeledStatement | undefined , convertedLoopBodyStatements : Statement [ ] | undefined , ancestorFacts : HierarchyFacts ) => Statement ;
149149
150150 // Facts we track as we traverse the tree
151151 const enum HierarchyFacts {
@@ -163,11 +163,12 @@ namespace ts {
163163 ExportedVariableStatement = 1 << 5 , // Enclosed in an exported variable statement in the current scope
164164 TopLevel = 1 << 6 , // Enclosing block-scoped container is a top-level container
165165 Block = 1 << 7 , // Enclosing block-scoped container is a Block
166- IterationStatement = 1 << 8 , // Enclosed in an IterationStatement
166+ IterationStatement = 1 << 8 , // Immediately enclosed in an IterationStatement
167167 IterationStatementBlock = 1 << 9 , // Enclosing Block is enclosed in an IterationStatement
168- ForStatement = 1 << 10 , // Enclosing block-scoped container is a ForStatement
169- ForInOrForOfStatement = 1 << 11 , // Enclosing block-scoped container is a ForInStatement or ForOfStatement
170- ConstructorWithCapturedSuper = 1 << 12 , // Enclosed in a constructor that captures 'this' for use with 'super'
168+ IterationContainer = 1 << 10 , // Enclosed in an outer IterationStatement
169+ ForStatement = 1 << 11 , // Enclosing block-scoped container is a ForStatement
170+ ForInOrForOfStatement = 1 << 12 , // Enclosing block-scoped container is a ForInStatement or ForOfStatement
171+ ConstructorWithCapturedSuper = 1 << 13 , // Enclosed in a constructor that captures 'this' for use with 'super'
171172 // NOTE: do not add more ancestor flags without also updating AncestorFactsMask below.
172173 // NOTE: when adding a new ancestor flag, be sure to update the subtree flags below.
173174
@@ -184,11 +185,11 @@ namespace ts {
184185
185186 // A source file is a top-level block scope.
186187 SourceFileIncludes = TopLevel ,
187- SourceFileExcludes = BlockScopeExcludes & ~ TopLevel ,
188+ SourceFileExcludes = BlockScopeExcludes & ~ TopLevel | IterationContainer ,
188189
189190 // Functions, methods, and accessors are both new lexical scopes and new block scopes.
190191 FunctionIncludes = Function | TopLevel ,
191- FunctionExcludes = BlockScopeExcludes & ~ TopLevel | ArrowFunction | AsyncFunctionBody | CapturesThis | NonStaticClassElement | ConstructorWithCapturedSuper ,
192+ FunctionExcludes = BlockScopeExcludes & ~ TopLevel | ArrowFunction | AsyncFunctionBody | CapturesThis | NonStaticClassElement | ConstructorWithCapturedSuper | IterationContainer ,
192193
193194 AsyncFunctionBodyIncludes = FunctionIncludes | AsyncFunctionBody ,
194195 AsyncFunctionBodyExcludes = FunctionExcludes & ~ NonStaticClassElement ,
@@ -205,16 +206,16 @@ namespace ts {
205206 // 'do' and 'while' statements are not block scopes. We track that the subtree is contained
206207 // within an IterationStatement to indicate whether the embedded statement is an
207208 // IterationStatementBlock.
208- DoOrWhileStatementIncludes = IterationStatement ,
209+ DoOrWhileStatementIncludes = IterationStatement | IterationContainer ,
209210 DoOrWhileStatementExcludes = None ,
210211
211212 // 'for' statements are new block scopes and have special handling for 'let' declarations.
212- ForStatementIncludes = IterationStatement | ForStatement ,
213+ ForStatementIncludes = IterationStatement | ForStatement | IterationContainer ,
213214 ForStatementExcludes = BlockScopeExcludes & ~ ForStatement ,
214215
215216 // 'for-in' and 'for-of' statements are new block scopes and have special handling for
216217 // 'let' declarations.
217- ForInOrForOfStatementIncludes = IterationStatement | ForInOrForOfStatement ,
218+ ForInOrForOfStatementIncludes = IterationStatement | ForInOrForOfStatement | IterationContainer ,
218219 ForInOrForOfStatementExcludes = BlockScopeExcludes & ~ ForInOrForOfStatement ,
219220
220221 // Blocks (other than function bodies) are new block scopes.
@@ -228,8 +229,8 @@ namespace ts {
228229 // Subtree facts
229230 //
230231
231- NewTarget = 1 << 13 , // Contains a 'new.target' meta-property
232- CapturedLexicalThis = 1 << 14 , // Contains a lexical `this` reference captured by an arrow function.
232+ NewTarget = 1 << 14 , // Contains a 'new.target' meta-property
233+ CapturedLexicalThis = 1 << 15 , // Contains a lexical `this` reference captured by an arrow function.
233234
234235 //
235236 // Subtree masks
@@ -2227,7 +2228,7 @@ namespace ts {
22272228
22282229 function visitIterationStatementWithFacts ( excludeFacts : HierarchyFacts , includeFacts : HierarchyFacts , node : IterationStatement , outermostLabeledStatement : LabeledStatement | undefined , convert ?: LoopConverter ) {
22292230 const ancestorFacts = enterSubtree ( excludeFacts , includeFacts ) ;
2230- const updated = convertIterationStatementBodyIfNecessary ( node , outermostLabeledStatement , convert ) ;
2231+ const updated = convertIterationStatementBodyIfNecessary ( node , outermostLabeledStatement , ancestorFacts , convert ) ;
22312232 exitSubtree ( ancestorFacts , HierarchyFacts . None , HierarchyFacts . None ) ;
22322233 return updated ;
22332234 }
@@ -2434,7 +2435,7 @@ namespace ts {
24342435 return restoreEnclosingLabel ( forStatement , outermostLabeledStatement , convertedLoopState && resetLabel ) ;
24352436 }
24362437
2437- function convertForOfStatementForIterable ( node : ForOfStatement , outermostLabeledStatement : LabeledStatement , convertedLoopBodyStatements : Statement [ ] ) : Statement {
2438+ function convertForOfStatementForIterable ( node : ForOfStatement , outermostLabeledStatement : LabeledStatement , convertedLoopBodyStatements : Statement [ ] , ancestorFacts : HierarchyFacts ) : Statement {
24382439 const expression = visitNode ( node . expression , visitor , isExpression ) ;
24392440 const iterator = isIdentifier ( expression ) ? getGeneratedNameForNode ( expression ) : createTempVariable ( /*recordTempVariable*/ undefined ) ;
24402441 const result = isIdentifier ( expression ) ? getGeneratedNameForNode ( iterator ) : createTempVariable ( /*recordTempVariable*/ undefined ) ;
@@ -2447,13 +2448,18 @@ namespace ts {
24472448 hoistVariableDeclaration ( errorRecord ) ;
24482449 hoistVariableDeclaration ( returnMethod ) ;
24492450
2451+ // if we are enclosed in an outer loop ensure we reset 'errorRecord' per each iteration
2452+ const initializer = ancestorFacts & HierarchyFacts . IterationContainer
2453+ ? inlineExpressions ( [ createAssignment ( errorRecord , createVoidZero ( ) ) , values ] )
2454+ : values ;
2455+
24502456 const forStatement = setEmitFlags (
24512457 setTextRange (
24522458 createFor (
24532459 /*initializer*/ setEmitFlags (
24542460 setTextRange (
24552461 createVariableDeclarationList ( [
2456- setTextRange ( createVariableDeclaration ( iterator , /*type*/ undefined , values ) , node . expression ) ,
2462+ setTextRange ( createVariableDeclaration ( iterator , /*type*/ undefined , initializer ) , node . expression ) ,
24572463 createVariableDeclaration ( result , /*type*/ undefined , next )
24582464 ] ) ,
24592465 node . expression
@@ -2665,7 +2671,7 @@ namespace ts {
26652671 }
26662672 }
26672673
2668- function convertIterationStatementBodyIfNecessary ( node : IterationStatement , outermostLabeledStatement : LabeledStatement | undefined , convert ?: LoopConverter ) : VisitResult < Statement > {
2674+ function convertIterationStatementBodyIfNecessary ( node : IterationStatement , outermostLabeledStatement : LabeledStatement | undefined , ancestorFacts : HierarchyFacts , convert ?: LoopConverter ) : VisitResult < Statement > {
26692675 if ( ! shouldConvertIterationStatement ( node ) ) {
26702676 let saveAllowedNonLabeledJumps : Jump | undefined ;
26712677 if ( convertedLoopState ) {
@@ -2676,7 +2682,7 @@ namespace ts {
26762682 }
26772683
26782684 const result = convert
2679- ? convert ( node , outermostLabeledStatement , /*convertedLoopBodyStatements*/ undefined )
2685+ ? convert ( node , outermostLabeledStatement , /*convertedLoopBodyStatements*/ undefined , ancestorFacts )
26802686 : restoreEnclosingLabel ( visitEachChild ( node , visitor , context ) , outermostLabeledStatement , convertedLoopState && resetLabel ) ;
26812687
26822688 if ( convertedLoopState ) {
@@ -2708,7 +2714,7 @@ namespace ts {
27082714 let loop : Statement ;
27092715 if ( bodyFunction ) {
27102716 if ( convert ) {
2711- loop = convert ( node , outermostLabeledStatement , bodyFunction . part ) ;
2717+ loop = convert ( node , outermostLabeledStatement , bodyFunction . part , ancestorFacts ) ;
27122718 }
27132719 else {
27142720 const clone = convertIterationStatementCore ( node , initializerFunction , createBlock ( bodyFunction . part , /*multiLine*/ true ) ) ;
0 commit comments