@@ -22262,6 +22262,10 @@ namespace ts {
22262
22262
return findAncestor(node, n => n === container ? "quit" : n === container.initializer || n === container.condition || n === container.incrementor || n === container.statement);
22263
22263
}
22264
22264
22265
+ function getEnclosingIterationStatement(node: Node): Node | undefined {
22266
+ return findAncestor(node, n => (!n || nodeStartsNewLexicalEnvironment(n)) ? "quit" : isIterationStatement(n, /*lookInLabeledStatements*/ false));
22267
+ }
22268
+
22265
22269
function checkNestedBlockScopedBinding(node: Identifier, symbol: Symbol): void {
22266
22270
if (languageVersion >= ScriptTarget.ES2015 ||
22267
22271
(symbol.flags & (SymbolFlags.BlockScopedVariable | SymbolFlags.Class)) === 0 ||
@@ -22277,18 +22281,9 @@ namespace ts {
22277
22281
22278
22282
const container = getEnclosingBlockScopeContainer(symbol.valueDeclaration);
22279
22283
const usedInFunction = isInsideFunction(node.parent, container);
22280
- let current = container;
22281
-
22282
- let containedInIterationStatement = false;
22283
- while (current && !nodeStartsNewLexicalEnvironment(current)) {
22284
- if (isIterationStatement(current, /*lookInLabeledStatements*/ false)) {
22285
- containedInIterationStatement = true;
22286
- break;
22287
- }
22288
- current = current.parent;
22289
- }
22290
22284
22291
- if (containedInIterationStatement) {
22285
+ const enclosingIterationStatement = getEnclosingIterationStatement(container);
22286
+ if (enclosingIterationStatement) {
22292
22287
if (usedInFunction) {
22293
22288
// mark iteration statement as containing block-scoped binding captured in some function
22294
22289
let capturesBlockScopeBindingInLoopBody = true;
@@ -22310,7 +22305,7 @@ namespace ts {
22310
22305
}
22311
22306
}
22312
22307
if (capturesBlockScopeBindingInLoopBody) {
22313
- getNodeLinks(current ).flags |= NodeCheckFlags.LoopWithCapturedBlockScopedBinding;
22308
+ getNodeLinks(enclosingIterationStatement ).flags |= NodeCheckFlags.LoopWithCapturedBlockScopedBinding;
22314
22309
}
22315
22310
}
22316
22311
@@ -23882,6 +23877,20 @@ namespace ts {
23882
23877
const links = getNodeLinks(node.expression);
23883
23878
if (!links.resolvedType) {
23884
23879
links.resolvedType = checkExpression(node.expression);
23880
+ // The computed property name of a non-static class field within a loop must be stored in a block-scoped binding.
23881
+ // (It needs to be bound at class evaluation time.)
23882
+ if (isPropertyDeclaration(node.parent) && !hasStaticModifier(node.parent) && isClassExpression(node.parent.parent)) {
23883
+ const container = getEnclosingBlockScopeContainer(node.parent.parent);
23884
+ const enclosingIterationStatement = getEnclosingIterationStatement(container);
23885
+ if (enclosingIterationStatement) {
23886
+ // The computed field name will use a block scoped binding which can be unique for each iteration of the loop.
23887
+ getNodeLinks(enclosingIterationStatement).flags |= NodeCheckFlags.LoopWithCapturedBlockScopedBinding;
23888
+ // The generated variable which stores the computed field name must be block-scoped.
23889
+ getNodeLinks(node).flags |= NodeCheckFlags.BlockScopedBindingInLoop;
23890
+ // The generated variable which stores the class must be block-scoped.
23891
+ getNodeLinks(node.parent.parent).flags |= NodeCheckFlags.BlockScopedBindingInLoop;
23892
+ }
23893
+ }
23885
23894
// This will allow types number, string, symbol or any. It will also allow enums, the unknown
23886
23895
// type, and any union of these types (like string | number).
23887
23896
if (links.resolvedType.flags & TypeFlags.Nullable ||
@@ -30714,6 +30723,16 @@ namespace ts {
30714
30723
for (let lexicalScope = getEnclosingBlockScopeContainer(node); !!lexicalScope; lexicalScope = getEnclosingBlockScopeContainer(lexicalScope)) {
30715
30724
getNodeLinks(lexicalScope).flags |= NodeCheckFlags.ContainsClassWithPrivateIdentifiers;
30716
30725
}
30726
+
30727
+ // If this is a private field in a class expression inside the body of a loop,
30728
+ // then we must use a block-scoped binding to store the WeakMap.
30729
+ if (isClassExpression(node.parent)) {
30730
+ const enclosingIterationStatement = getEnclosingIterationStatement(node.parent);
30731
+ if (enclosingIterationStatement) {
30732
+ getNodeLinks(node.name).flags |= NodeCheckFlags.BlockScopedBindingInLoop;
30733
+ getNodeLinks(enclosingIterationStatement).flags |= NodeCheckFlags.LoopWithCapturedBlockScopedBinding;
30734
+ }
30735
+ }
30717
30736
}
30718
30737
}
30719
30738
0 commit comments