@@ -20722,6 +20722,10 @@ namespace ts {
20722
20722
return findAncestor(node, n => n === container ? "quit" : n === container.initializer || n === container.condition || n === container.incrementor || n === container.statement);
20723
20723
}
20724
20724
20725
+ function getEnclosingIterationStatement(node: Node): Node | undefined {
20726
+ return findAncestor(node, n => (!n || nodeStartsNewLexicalEnvironment(n)) ? "quit" : isIterationStatement(n, /*lookInLabeledStatements*/ false));
20727
+ }
20728
+
20725
20729
function checkNestedBlockScopedBinding(node: Identifier, symbol: Symbol): void {
20726
20730
if (languageVersion >= ScriptTarget.ES2015 ||
20727
20731
(symbol.flags & (SymbolFlags.BlockScopedVariable | SymbolFlags.Class)) === 0 ||
@@ -20737,18 +20741,9 @@ namespace ts {
20737
20741
20738
20742
const container = getEnclosingBlockScopeContainer(symbol.valueDeclaration);
20739
20743
const usedInFunction = isInsideFunction(node.parent, container);
20740
- let current = container;
20741
-
20742
- let containedInIterationStatement = false;
20743
- while (current && !nodeStartsNewLexicalEnvironment(current)) {
20744
- if (isIterationStatement(current, /*lookInLabeledStatements*/ false)) {
20745
- containedInIterationStatement = true;
20746
- break;
20747
- }
20748
- current = current.parent;
20749
- }
20750
20744
20751
- if (containedInIterationStatement) {
20745
+ const enclosingIterationStatement = getEnclosingIterationStatement(container);
20746
+ if (enclosingIterationStatement) {
20752
20747
if (usedInFunction) {
20753
20748
// mark iteration statement as containing block-scoped binding captured in some function
20754
20749
let capturesBlockScopeBindingInLoopBody = true;
@@ -20770,7 +20765,7 @@ namespace ts {
20770
20765
}
20771
20766
}
20772
20767
if (capturesBlockScopeBindingInLoopBody) {
20773
- getNodeLinks(current ).flags |= NodeCheckFlags.LoopWithCapturedBlockScopedBinding;
20768
+ getNodeLinks(enclosingIterationStatement ).flags |= NodeCheckFlags.LoopWithCapturedBlockScopedBinding;
20774
20769
}
20775
20770
}
20776
20771
@@ -22369,6 +22364,20 @@ namespace ts {
22369
22364
const links = getNodeLinks(node.expression);
22370
22365
if (!links.resolvedType) {
22371
22366
links.resolvedType = checkExpression(node.expression);
22367
+ // The computed property name of a non-static class field within a loop must be stored in a block-scoped binding.
22368
+ // (It needs to be bound at class evaluation time.)
22369
+ if (isPropertyDeclaration(node.parent) && !hasStaticModifier(node.parent) && isClassExpression(node.parent.parent)) {
22370
+ const container = getEnclosingBlockScopeContainer(node.parent.parent);
22371
+ const enclosingIterationStatement = getEnclosingIterationStatement(container);
22372
+ if (enclosingIterationStatement) {
22373
+ // The computed field name will use a block scoped binding which can be unique for each iteration of the loop.
22374
+ getNodeLinks(enclosingIterationStatement).flags |= NodeCheckFlags.LoopWithCapturedBlockScopedBinding;
22375
+ // The generated variable which stores the computed field name must be block-scoped.
22376
+ getNodeLinks(node).flags |= NodeCheckFlags.BlockScopedBindingInLoop;
22377
+ // The generated variable which stores the class must be block-scoped.
22378
+ getNodeLinks(node.parent.parent).flags |= NodeCheckFlags.BlockScopedBindingInLoop;
22379
+ }
22380
+ }
22372
22381
// This will allow types number, string, symbol or any. It will also allow enums, the unknown
22373
22382
// type, and any union of these types (like string | number).
22374
22383
if (links.resolvedType.flags & TypeFlags.Nullable ||
@@ -28916,6 +28925,16 @@ namespace ts {
28916
28925
for (let lexicalScope = getEnclosingBlockScopeContainer(node); !!lexicalScope; lexicalScope = getEnclosingBlockScopeContainer(lexicalScope)) {
28917
28926
getNodeLinks(lexicalScope).flags |= NodeCheckFlags.ContainsClassWithPrivateIdentifiers;
28918
28927
}
28928
+
28929
+ // If this is a private field in a class expression inside the body of a loop,
28930
+ // then we must use a block-scoped binding to store the WeakMap.
28931
+ if (isClassExpression(node.parent)) {
28932
+ const enclosingIterationStatement = getEnclosingIterationStatement(node.parent);
28933
+ if (enclosingIterationStatement) {
28934
+ getNodeLinks(node.name).flags |= NodeCheckFlags.BlockScopedBindingInLoop;
28935
+ getNodeLinks(enclosingIterationStatement).flags |= NodeCheckFlags.LoopWithCapturedBlockScopedBinding;
28936
+ }
28937
+ }
28919
28938
}
28920
28939
}
28921
28940
0 commit comments