@@ -145,7 +145,7 @@ namespace ts {
145
145
loopOutParameters : LoopOutParameter [ ] ;
146
146
}
147
147
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 ;
149
149
150
150
// Facts we track as we traverse the tree
151
151
const enum HierarchyFacts {
@@ -163,11 +163,12 @@ namespace ts {
163
163
ExportedVariableStatement = 1 << 5 , // Enclosed in an exported variable statement in the current scope
164
164
TopLevel = 1 << 6 , // Enclosing block-scoped container is a top-level container
165
165
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
167
167
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'
171
172
// NOTE: do not add more ancestor flags without also updating AncestorFactsMask below.
172
173
// NOTE: when adding a new ancestor flag, be sure to update the subtree flags below.
173
174
@@ -184,11 +185,11 @@ namespace ts {
184
185
185
186
// A source file is a top-level block scope.
186
187
SourceFileIncludes = TopLevel ,
187
- SourceFileExcludes = BlockScopeExcludes & ~ TopLevel ,
188
+ SourceFileExcludes = BlockScopeExcludes & ~ TopLevel | IterationContainer ,
188
189
189
190
// Functions, methods, and accessors are both new lexical scopes and new block scopes.
190
191
FunctionIncludes = Function | TopLevel ,
191
- FunctionExcludes = BlockScopeExcludes & ~ TopLevel | ArrowFunction | AsyncFunctionBody | CapturesThis | NonStaticClassElement | ConstructorWithCapturedSuper ,
192
+ FunctionExcludes = BlockScopeExcludes & ~ TopLevel | ArrowFunction | AsyncFunctionBody | CapturesThis | NonStaticClassElement | ConstructorWithCapturedSuper | IterationContainer ,
192
193
193
194
AsyncFunctionBodyIncludes = FunctionIncludes | AsyncFunctionBody ,
194
195
AsyncFunctionBodyExcludes = FunctionExcludes & ~ NonStaticClassElement ,
@@ -205,16 +206,16 @@ namespace ts {
205
206
// 'do' and 'while' statements are not block scopes. We track that the subtree is contained
206
207
// within an IterationStatement to indicate whether the embedded statement is an
207
208
// IterationStatementBlock.
208
- DoOrWhileStatementIncludes = IterationStatement ,
209
+ DoOrWhileStatementIncludes = IterationStatement | IterationContainer ,
209
210
DoOrWhileStatementExcludes = None ,
210
211
211
212
// 'for' statements are new block scopes and have special handling for 'let' declarations.
212
- ForStatementIncludes = IterationStatement | ForStatement ,
213
+ ForStatementIncludes = IterationStatement | ForStatement | IterationContainer ,
213
214
ForStatementExcludes = BlockScopeExcludes & ~ ForStatement ,
214
215
215
216
// 'for-in' and 'for-of' statements are new block scopes and have special handling for
216
217
// 'let' declarations.
217
- ForInOrForOfStatementIncludes = IterationStatement | ForInOrForOfStatement ,
218
+ ForInOrForOfStatementIncludes = IterationStatement | ForInOrForOfStatement | IterationContainer ,
218
219
ForInOrForOfStatementExcludes = BlockScopeExcludes & ~ ForInOrForOfStatement ,
219
220
220
221
// Blocks (other than function bodies) are new block scopes.
@@ -228,8 +229,8 @@ namespace ts {
228
229
// Subtree facts
229
230
//
230
231
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.
233
234
234
235
//
235
236
// Subtree masks
@@ -2227,7 +2228,7 @@ namespace ts {
2227
2228
2228
2229
function visitIterationStatementWithFacts ( excludeFacts : HierarchyFacts , includeFacts : HierarchyFacts , node : IterationStatement , outermostLabeledStatement : LabeledStatement | undefined , convert ?: LoopConverter ) {
2229
2230
const ancestorFacts = enterSubtree ( excludeFacts , includeFacts ) ;
2230
- const updated = convertIterationStatementBodyIfNecessary ( node , outermostLabeledStatement , convert ) ;
2231
+ const updated = convertIterationStatementBodyIfNecessary ( node , outermostLabeledStatement , ancestorFacts , convert ) ;
2231
2232
exitSubtree ( ancestorFacts , HierarchyFacts . None , HierarchyFacts . None ) ;
2232
2233
return updated ;
2233
2234
}
@@ -2434,7 +2435,7 @@ namespace ts {
2434
2435
return restoreEnclosingLabel ( forStatement , outermostLabeledStatement , convertedLoopState && resetLabel ) ;
2435
2436
}
2436
2437
2437
- function convertForOfStatementForIterable ( node : ForOfStatement , outermostLabeledStatement : LabeledStatement , convertedLoopBodyStatements : Statement [ ] ) : Statement {
2438
+ function convertForOfStatementForIterable ( node : ForOfStatement , outermostLabeledStatement : LabeledStatement , convertedLoopBodyStatements : Statement [ ] , ancestorFacts : HierarchyFacts ) : Statement {
2438
2439
const expression = visitNode ( node . expression , visitor , isExpression ) ;
2439
2440
const iterator = isIdentifier ( expression ) ? getGeneratedNameForNode ( expression ) : createTempVariable ( /*recordTempVariable*/ undefined ) ;
2440
2441
const result = isIdentifier ( expression ) ? getGeneratedNameForNode ( iterator ) : createTempVariable ( /*recordTempVariable*/ undefined ) ;
@@ -2447,13 +2448,18 @@ namespace ts {
2447
2448
hoistVariableDeclaration ( errorRecord ) ;
2448
2449
hoistVariableDeclaration ( returnMethod ) ;
2449
2450
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
+
2450
2456
const forStatement = setEmitFlags (
2451
2457
setTextRange (
2452
2458
createFor (
2453
2459
/*initializer*/ setEmitFlags (
2454
2460
setTextRange (
2455
2461
createVariableDeclarationList ( [
2456
- setTextRange ( createVariableDeclaration ( iterator , /*type*/ undefined , values ) , node . expression ) ,
2462
+ setTextRange ( createVariableDeclaration ( iterator , /*type*/ undefined , initializer ) , node . expression ) ,
2457
2463
createVariableDeclaration ( result , /*type*/ undefined , next )
2458
2464
] ) ,
2459
2465
node . expression
@@ -2665,7 +2671,7 @@ namespace ts {
2665
2671
}
2666
2672
}
2667
2673
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 > {
2669
2675
if ( ! shouldConvertIterationStatement ( node ) ) {
2670
2676
let saveAllowedNonLabeledJumps : Jump | undefined ;
2671
2677
if ( convertedLoopState ) {
@@ -2676,7 +2682,7 @@ namespace ts {
2676
2682
}
2677
2683
2678
2684
const result = convert
2679
- ? convert ( node , outermostLabeledStatement , /*convertedLoopBodyStatements*/ undefined )
2685
+ ? convert ( node , outermostLabeledStatement , /*convertedLoopBodyStatements*/ undefined , ancestorFacts )
2680
2686
: restoreEnclosingLabel ( visitEachChild ( node , visitor , context ) , outermostLabeledStatement , convertedLoopState && resetLabel ) ;
2681
2687
2682
2688
if ( convertedLoopState ) {
@@ -2708,7 +2714,7 @@ namespace ts {
2708
2714
let loop : Statement ;
2709
2715
if ( bodyFunction ) {
2710
2716
if ( convert ) {
2711
- loop = convert ( node , outermostLabeledStatement , bodyFunction . part ) ;
2717
+ loop = convert ( node , outermostLabeledStatement , bodyFunction . part , ancestorFacts ) ;
2712
2718
}
2713
2719
else {
2714
2720
const clone = convertIterationStatementCore ( node , initializerFunction , createBlock ( bodyFunction . part , /*multiLine*/ true ) ) ;
0 commit comments