@@ -959,6 +959,7 @@ namespace ts {
959
959
const potentialThisCollisions: Node[] = [];
960
960
const potentialNewTargetCollisions: Node[] = [];
961
961
const potentialWeakMapSetCollisions: Node[] = [];
962
+ const potentialReflectCollisions: Node[] = [];
962
963
const awaitedTypeStack: number[] = [];
963
964
964
965
const diagnostics = createDiagnosticCollection();
@@ -24873,6 +24874,18 @@ namespace ts {
24873
24874
24874
24875
if (isStatic(container) || isCallExpression) {
24875
24876
nodeCheckFlag = NodeCheckFlags.SuperStatic;
24877
+ if (!isCallExpression &&
24878
+ languageVersion >= ScriptTarget.ES2015 && languageVersion <= ScriptTarget.ES2021 &&
24879
+ (isPropertyDeclaration(container) || isClassStaticBlockDeclaration(container))) {
24880
+ // for `super.x` or `super[x]` in a static initializer, mark all enclosing
24881
+ // block scope containers so that we can report potential collisions with
24882
+ // `Reflect`.
24883
+ forEachEnclosingBlockScopeContainer(node.parent, current => {
24884
+ if (!isSourceFile(current) || isExternalOrCommonJsModule(current)) {
24885
+ getNodeLinks(current).flags |= NodeCheckFlags.ContainsSuperPropertyInStaticInitializer;
24886
+ }
24887
+ });
24888
+ }
24876
24889
}
24877
24890
else {
24878
24891
nodeCheckFlag = NodeCheckFlags.SuperInstance;
@@ -31159,6 +31172,10 @@ namespace ts {
31159
31172
Debug.assert(node.kind !== SyntaxKind.MethodDeclaration || isObjectLiteralMethod(node));
31160
31173
checkNodeDeferred(node);
31161
31174
31175
+ if (isFunctionExpression(node)) {
31176
+ checkCollisionsForDeclarationName(node, node.name);
31177
+ }
31178
+
31162
31179
// The identityMapper object is used to indicate that function expressions are wildcards
31163
31180
if (checkMode && checkMode & CheckMode.SkipContextSensitive && isContextSensitive(node)) {
31164
31181
// Skip parameters, return signature with return type that retains noncontextual parts so inferences can still be drawn in an early stage
@@ -34946,8 +34963,7 @@ namespace ts {
34946
34963
if (produceDiagnostics) {
34947
34964
checkFunctionOrMethodDeclaration(node);
34948
34965
checkGrammarForGenerator(node);
34949
- checkCollisionWithRequireExportsInGeneratedCode(node, node.name!);
34950
- checkCollisionWithGlobalPromiseInGeneratedCode(node, node.name!);
34966
+ checkCollisionsForDeclarationName(node, node.name);
34951
34967
}
34952
34968
}
34953
34969
@@ -35470,8 +35486,13 @@ namespace ts {
35470
35486
});
35471
35487
}
35472
35488
35489
+ /**
35490
+ * Checks whether an {@link Identifier}, in the context of another {@link Node}, would collide with a runtime value
35491
+ * of {@link name} in an outer scope. This is used to check for collisions for downlevel transformations that
35492
+ * require names like `Object`, `Promise`, `Reflect`, `require`, `exports`, etc.
35493
+ */
35473
35494
function needCollisionCheckForIdentifier(node: Node, identifier: Identifier | undefined, name: string): boolean {
35474
- if (!( identifier && identifier .escapedText === name) ) {
35495
+ if (identifier? .escapedText !== name) {
35475
35496
return false;
35476
35497
}
35477
35498
@@ -35480,8 +35501,9 @@ namespace ts {
35480
35501
node.kind === SyntaxKind.MethodDeclaration ||
35481
35502
node.kind === SyntaxKind.MethodSignature ||
35482
35503
node.kind === SyntaxKind.GetAccessor ||
35483
- node.kind === SyntaxKind.SetAccessor) {
35484
- // it is ok to have member named '_super' or '_this' - member access is always qualified
35504
+ node.kind === SyntaxKind.SetAccessor ||
35505
+ node.kind === SyntaxKind.PropertyAssignment) {
35506
+ // it is ok to have member named '_super', '_this', `Promise`, etc. - member access is always qualified
35485
35507
return false;
35486
35508
}
35487
35509
@@ -35490,8 +35512,15 @@ namespace ts {
35490
35512
return false;
35491
35513
}
35492
35514
35515
+ if (isImportClause(node) || isImportEqualsDeclaration(node) || isImportSpecifier(node)) {
35516
+ // type-only imports do not require collision checks against runtime values.
35517
+ if (isTypeOnlyImportOrExportDeclaration(node)) {
35518
+ return false;
35519
+ }
35520
+ }
35521
+
35493
35522
const root = getRootDeclaration(node);
35494
- if (root.kind === SyntaxKind.Parameter && nodeIsMissing((root.parent as FunctionLikeDeclaration).body)) {
35523
+ if (isParameter( root) && nodeIsMissing((root.parent as FunctionLikeDeclaration).body)) {
35495
35524
// just an overload - no codegen impact
35496
35525
return false;
35497
35526
}
@@ -35532,21 +35561,13 @@ namespace ts {
35532
35561
});
35533
35562
}
35534
35563
35535
- function checkWeakMapSetCollision(node: Node) {
35536
- const enclosingBlockScope = getEnclosingBlockScopeContainer(node);
35537
- if (getNodeCheckFlags(enclosingBlockScope) & NodeCheckFlags.ContainsClassWithPrivateIdentifiers) {
35538
- Debug.assert(isNamedDeclaration(node) && isIdentifier(node.name) && typeof node.name.escapedText === "string", "The target of a WeakMap/WeakSet collision check should be an identifier");
35539
- errorSkippedOn("noEmit", node, Diagnostics.Compiler_reserves_name_0_when_emitting_private_identifier_downlevel, node.name.escapedText);
35540
- }
35541
- }
35542
-
35543
- function checkCollisionWithRequireExportsInGeneratedCode(node: Node, name: Identifier) {
35564
+ function checkCollisionWithRequireExportsInGeneratedCode(node: Node, name: Identifier | undefined) {
35544
35565
// No need to check for require or exports for ES6 modules and later
35545
35566
if (moduleKind >= ModuleKind.ES2015) {
35546
35567
return;
35547
35568
}
35548
35569
35549
- if (!needCollisionCheckForIdentifier(node, name, "require") && !needCollisionCheckForIdentifier(node, name, "exports")) {
35570
+ if (!name || ! needCollisionCheckForIdentifier(node, name, "require") && !needCollisionCheckForIdentifier(node, name, "exports")) {
35550
35571
return;
35551
35572
}
35552
35573
@@ -35564,8 +35585,8 @@ namespace ts {
35564
35585
}
35565
35586
}
35566
35587
35567
- function checkCollisionWithGlobalPromiseInGeneratedCode(node: Node, name: Identifier): void {
35568
- if (languageVersion >= ScriptTarget.ES2017 || !needCollisionCheckForIdentifier(node, name, "Promise")) {
35588
+ function checkCollisionWithGlobalPromiseInGeneratedCode(node: Node, name: Identifier | undefined ): void {
35589
+ if (!name || languageVersion >= ScriptTarget.ES2017 || !needCollisionCheckForIdentifier(node, name, "Promise")) {
35569
35590
return;
35570
35591
}
35571
35592
@@ -35583,6 +35604,76 @@ namespace ts {
35583
35604
}
35584
35605
}
35585
35606
35607
+ function recordPotentialCollisionWithWeakMapSetInGeneratedCode(node: Node, name: Identifier): void {
35608
+ if (languageVersion <= ScriptTarget.ES2021
35609
+ && (needCollisionCheckForIdentifier(node, name, "WeakMap") || needCollisionCheckForIdentifier(node, name, "WeakSet"))) {
35610
+ potentialWeakMapSetCollisions.push(node);
35611
+ }
35612
+ }
35613
+
35614
+ function checkWeakMapSetCollision(node: Node) {
35615
+ const enclosingBlockScope = getEnclosingBlockScopeContainer(node);
35616
+ if (getNodeCheckFlags(enclosingBlockScope) & NodeCheckFlags.ContainsClassWithPrivateIdentifiers) {
35617
+ Debug.assert(isNamedDeclaration(node) && isIdentifier(node.name) && typeof node.name.escapedText === "string", "The target of a WeakMap/WeakSet collision check should be an identifier");
35618
+ errorSkippedOn("noEmit", node, Diagnostics.Compiler_reserves_name_0_when_emitting_private_identifier_downlevel, node.name.escapedText);
35619
+ }
35620
+ }
35621
+
35622
+ function recordPotentialCollisionWithReflectInGeneratedCode(node: Node, name: Identifier | undefined): void {
35623
+ if (name && languageVersion >= ScriptTarget.ES2015 && languageVersion <= ScriptTarget.ES2021
35624
+ && needCollisionCheckForIdentifier(node, name, "Reflect")) {
35625
+ potentialReflectCollisions.push(node);
35626
+ }
35627
+ }
35628
+
35629
+ function checkReflectCollision(node: Node) {
35630
+ let hasCollision = false;
35631
+ if (isClassExpression(node)) {
35632
+ // ClassExpression names don't contribute to their containers, but do matter for any of their block-scoped members.
35633
+ for (const member of node.members) {
35634
+ if (getNodeCheckFlags(member) & NodeCheckFlags.ContainsSuperPropertyInStaticInitializer) {
35635
+ hasCollision = true;
35636
+ break;
35637
+ }
35638
+ }
35639
+ }
35640
+ else if (isFunctionExpression(node)) {
35641
+ // FunctionExpression names don't contribute to their containers, but do matter for their contents
35642
+ if (getNodeCheckFlags(node) & NodeCheckFlags.ContainsSuperPropertyInStaticInitializer) {
35643
+ hasCollision = true;
35644
+ }
35645
+ }
35646
+ else {
35647
+ const container = getEnclosingBlockScopeContainer(node);
35648
+ if (container && getNodeCheckFlags(container) & NodeCheckFlags.ContainsSuperPropertyInStaticInitializer) {
35649
+ hasCollision = true;
35650
+ }
35651
+ }
35652
+ if (hasCollision) {
35653
+ Debug.assert(isNamedDeclaration(node) && isIdentifier(node.name), "The target of a Reflect collision check should be an identifier");
35654
+ errorSkippedOn("noEmit", node, Diagnostics.Duplicate_identifier_0_Compiler_reserves_name_1_when_emitting_super_references_in_static_initializers,
35655
+ declarationNameToString(node.name),
35656
+ "Reflect");
35657
+ }
35658
+ }
35659
+
35660
+ function checkCollisionsForDeclarationName(node: Node, name: Identifier | undefined) {
35661
+ if (!name) return;
35662
+ checkCollisionWithRequireExportsInGeneratedCode(node, name);
35663
+ checkCollisionWithGlobalPromiseInGeneratedCode(node, name);
35664
+ recordPotentialCollisionWithWeakMapSetInGeneratedCode(node, name);
35665
+ recordPotentialCollisionWithReflectInGeneratedCode(node, name);
35666
+ if (isClassLike(node)) {
35667
+ checkTypeNameIsReserved(name, Diagnostics.Class_name_cannot_be_0);
35668
+ if (!(node.flags & NodeFlags.Ambient)) {
35669
+ checkClassNameCollisionWithObject(name);
35670
+ }
35671
+ }
35672
+ else if (isEnumDeclaration(node)) {
35673
+ checkTypeNameIsReserved(name, Diagnostics.Enum_name_cannot_be_0);
35674
+ }
35675
+ }
35676
+
35586
35677
function checkVarDeclaredNamesNotShadowed(node: VariableDeclaration | BindingElement) {
35587
35678
// - ScriptBody : StatementList
35588
35679
// It is a Syntax Error if any element of the LexicallyDeclaredNames of StatementList
@@ -35801,12 +35892,7 @@ namespace ts {
35801
35892
if (node.kind === SyntaxKind.VariableDeclaration || node.kind === SyntaxKind.BindingElement) {
35802
35893
checkVarDeclaredNamesNotShadowed(node);
35803
35894
}
35804
- checkCollisionWithRequireExportsInGeneratedCode(node, node.name);
35805
- checkCollisionWithGlobalPromiseInGeneratedCode(node, node.name);
35806
- if (languageVersion < ScriptTarget.ESNext
35807
- && (needCollisionCheckForIdentifier(node, node.name, "WeakMap") || needCollisionCheckForIdentifier(node, node.name, "WeakSet"))) {
35808
- potentialWeakMapSetCollisions.push(node);
35809
- }
35895
+ checkCollisionsForDeclarationName(node, node.name);
35810
35896
}
35811
35897
}
35812
35898
@@ -37365,14 +37451,7 @@ namespace ts {
37365
37451
function checkClassLikeDeclaration(node: ClassLikeDeclaration) {
37366
37452
checkGrammarClassLikeDeclaration(node);
37367
37453
checkDecorators(node);
37368
- if (node.name) {
37369
- checkTypeNameIsReserved(node.name, Diagnostics.Class_name_cannot_be_0);
37370
- checkCollisionWithRequireExportsInGeneratedCode(node, node.name);
37371
- checkCollisionWithGlobalPromiseInGeneratedCode(node, node.name);
37372
- if (!(node.flags & NodeFlags.Ambient)) {
37373
- checkClassNameCollisionWithObject(node.name);
37374
- }
37375
- }
37454
+ checkCollisionsForDeclarationName(node, node.name);
37376
37455
checkTypeParameters(getEffectiveTypeParameterDeclarations(node));
37377
37456
checkExportsOnMergedDeclarations(node);
37378
37457
const symbol = getSymbolOfNode(node);
@@ -38099,9 +38178,7 @@ namespace ts {
38099
38178
// Grammar checking
38100
38179
checkGrammarDecoratorsAndModifiers(node);
38101
38180
38102
- checkTypeNameIsReserved(node.name, Diagnostics.Enum_name_cannot_be_0);
38103
- checkCollisionWithRequireExportsInGeneratedCode(node, node.name);
38104
- checkCollisionWithGlobalPromiseInGeneratedCode(node, node.name);
38181
+ checkCollisionsForDeclarationName(node, node.name);
38105
38182
checkExportsOnMergedDeclarations(node);
38106
38183
node.members.forEach(checkEnumMember);
38107
38184
@@ -38210,8 +38287,7 @@ namespace ts {
38210
38287
}
38211
38288
38212
38289
if (isIdentifier(node.name)) {
38213
- checkCollisionWithRequireExportsInGeneratedCode(node, node.name);
38214
- checkCollisionWithGlobalPromiseInGeneratedCode(node, node.name);
38290
+ checkCollisionsForDeclarationName(node, node.name);
38215
38291
}
38216
38292
38217
38293
checkExportsOnMergedDeclarations(node);
@@ -38428,8 +38504,7 @@ namespace ts {
38428
38504
}
38429
38505
38430
38506
function checkImportBinding(node: ImportEqualsDeclaration | ImportClause | NamespaceImport | ImportSpecifier) {
38431
- checkCollisionWithRequireExportsInGeneratedCode(node, node.name!);
38432
- checkCollisionWithGlobalPromiseInGeneratedCode(node, node.name!);
38507
+ checkCollisionsForDeclarationName(node, node.name);
38433
38508
checkAliasSymbol(node);
38434
38509
if (node.kind === SyntaxKind.ImportSpecifier &&
38435
38510
idText(node.propertyName || node.name) === "default" &&
@@ -39147,6 +39222,7 @@ namespace ts {
39147
39222
clear(potentialThisCollisions);
39148
39223
clear(potentialNewTargetCollisions);
39149
39224
clear(potentialWeakMapSetCollisions);
39225
+ clear(potentialReflectCollisions);
39150
39226
39151
39227
forEach(node.statements, checkSourceElement);
39152
39228
checkSourceElement(node.endOfFileToken);
@@ -39191,6 +39267,11 @@ namespace ts {
39191
39267
clear(potentialWeakMapSetCollisions);
39192
39268
}
39193
39269
39270
+ if (potentialReflectCollisions.length) {
39271
+ forEach(potentialReflectCollisions, checkReflectCollision);
39272
+ clear(potentialReflectCollisions);
39273
+ }
39274
+
39194
39275
links.flags |= NodeCheckFlags.TypeChecked;
39195
39276
}
39196
39277
}
@@ -40303,7 +40384,9 @@ namespace ts {
40303
40384
}
40304
40385
40305
40386
function getNodeCheckFlags(node: Node): NodeCheckFlags {
40306
- return getNodeLinks(node).flags || 0;
40387
+ const nodeId = node.id || 0;
40388
+ if (nodeId < 0 || nodeId >= nodeLinks.length) return 0;
40389
+ return nodeLinks[nodeId]?.flags || 0;
40307
40390
}
40308
40391
40309
40392
function getEnumMemberValue(node: EnumMember): string | number | undefined {
0 commit comments