@@ -960,6 +960,7 @@ namespace ts {
960
960
const potentialThisCollisions: Node[] = [];
961
961
const potentialNewTargetCollisions: Node[] = [];
962
962
const potentialWeakMapSetCollisions: Node[] = [];
963
+ const potentialReflectCollisions: Node[] = [];
963
964
const awaitedTypeStack: number[] = [];
964
965
965
966
const diagnostics = createDiagnosticCollection();
@@ -24888,6 +24889,18 @@ namespace ts {
24888
24889
24889
24890
if (isStatic(container) || isCallExpression) {
24890
24891
nodeCheckFlag = NodeCheckFlags.SuperStatic;
24892
+ if (!isCallExpression &&
24893
+ languageVersion >= ScriptTarget.ES2015 && languageVersion <= ScriptTarget.ES2021 &&
24894
+ (isPropertyDeclaration(container) || isClassStaticBlockDeclaration(container))) {
24895
+ // for `super.x` or `super[x]` in a static initializer, mark all enclosing
24896
+ // block scope containers so that we can report potential collisions with
24897
+ // `Reflect`.
24898
+ forEachEnclosingBlockScopeContainer(node.parent, current => {
24899
+ if (!isSourceFile(current) || isExternalOrCommonJsModule(current)) {
24900
+ getNodeLinks(current).flags |= NodeCheckFlags.ContainsSuperPropertyInStaticInitializer;
24901
+ }
24902
+ });
24903
+ }
24891
24904
}
24892
24905
else {
24893
24906
nodeCheckFlag = NodeCheckFlags.SuperInstance;
@@ -31174,6 +31187,10 @@ namespace ts {
31174
31187
Debug.assert(node.kind !== SyntaxKind.MethodDeclaration || isObjectLiteralMethod(node));
31175
31188
checkNodeDeferred(node);
31176
31189
31190
+ if (isFunctionExpression(node)) {
31191
+ checkCollisionsForDeclarationName(node, node.name);
31192
+ }
31193
+
31177
31194
// The identityMapper object is used to indicate that function expressions are wildcards
31178
31195
if (checkMode && checkMode & CheckMode.SkipContextSensitive && isContextSensitive(node)) {
31179
31196
// Skip parameters, return signature with return type that retains noncontextual parts so inferences can still be drawn in an early stage
@@ -34961,8 +34978,7 @@ namespace ts {
34961
34978
if (produceDiagnostics) {
34962
34979
checkFunctionOrMethodDeclaration(node);
34963
34980
checkGrammarForGenerator(node);
34964
- checkCollisionWithRequireExportsInGeneratedCode(node, node.name!);
34965
- checkCollisionWithGlobalPromiseInGeneratedCode(node, node.name!);
34981
+ checkCollisionsForDeclarationName(node, node.name);
34966
34982
}
34967
34983
}
34968
34984
@@ -35485,8 +35501,13 @@ namespace ts {
35485
35501
});
35486
35502
}
35487
35503
35504
+ /**
35505
+ * Checks whether an {@link Identifier}, in the context of another {@link Node}, would collide with a runtime value
35506
+ * of {@link name} in an outer scope. This is used to check for collisions for downlevel transformations that
35507
+ * require names like `Object`, `Promise`, `Reflect`, `require`, `exports`, etc.
35508
+ */
35488
35509
function needCollisionCheckForIdentifier(node: Node, identifier: Identifier | undefined, name: string): boolean {
35489
- if (!( identifier && identifier .escapedText === name) ) {
35510
+ if (identifier? .escapedText !== name) {
35490
35511
return false;
35491
35512
}
35492
35513
@@ -35495,8 +35516,9 @@ namespace ts {
35495
35516
node.kind === SyntaxKind.MethodDeclaration ||
35496
35517
node.kind === SyntaxKind.MethodSignature ||
35497
35518
node.kind === SyntaxKind.GetAccessor ||
35498
- node.kind === SyntaxKind.SetAccessor) {
35499
- // it is ok to have member named '_super' or '_this' - member access is always qualified
35519
+ node.kind === SyntaxKind.SetAccessor ||
35520
+ node.kind === SyntaxKind.PropertyAssignment) {
35521
+ // it is ok to have member named '_super', '_this', `Promise`, etc. - member access is always qualified
35500
35522
return false;
35501
35523
}
35502
35524
@@ -35505,8 +35527,15 @@ namespace ts {
35505
35527
return false;
35506
35528
}
35507
35529
35530
+ if (isImportClause(node) || isImportEqualsDeclaration(node) || isImportSpecifier(node)) {
35531
+ // type-only imports do not require collision checks against runtime values.
35532
+ if (isTypeOnlyImportOrExportDeclaration(node)) {
35533
+ return false;
35534
+ }
35535
+ }
35536
+
35508
35537
const root = getRootDeclaration(node);
35509
- if (root.kind === SyntaxKind.Parameter && nodeIsMissing((root.parent as FunctionLikeDeclaration).body)) {
35538
+ if (isParameter( root) && nodeIsMissing((root.parent as FunctionLikeDeclaration).body)) {
35510
35539
// just an overload - no codegen impact
35511
35540
return false;
35512
35541
}
@@ -35547,21 +35576,13 @@ namespace ts {
35547
35576
});
35548
35577
}
35549
35578
35550
- function checkWeakMapSetCollision(node: Node) {
35551
- const enclosingBlockScope = getEnclosingBlockScopeContainer(node);
35552
- if (getNodeCheckFlags(enclosingBlockScope) & NodeCheckFlags.ContainsClassWithPrivateIdentifiers) {
35553
- Debug.assert(isNamedDeclaration(node) && isIdentifier(node.name) && typeof node.name.escapedText === "string", "The target of a WeakMap/WeakSet collision check should be an identifier");
35554
- errorSkippedOn("noEmit", node, Diagnostics.Compiler_reserves_name_0_when_emitting_private_identifier_downlevel, node.name.escapedText);
35555
- }
35556
- }
35557
-
35558
- function checkCollisionWithRequireExportsInGeneratedCode(node: Node, name: Identifier) {
35579
+ function checkCollisionWithRequireExportsInGeneratedCode(node: Node, name: Identifier | undefined) {
35559
35580
// No need to check for require or exports for ES6 modules and later
35560
35581
if (moduleKind >= ModuleKind.ES2015) {
35561
35582
return;
35562
35583
}
35563
35584
35564
- if (!needCollisionCheckForIdentifier(node, name, "require") && !needCollisionCheckForIdentifier(node, name, "exports")) {
35585
+ if (!name || ! needCollisionCheckForIdentifier(node, name, "require") && !needCollisionCheckForIdentifier(node, name, "exports")) {
35565
35586
return;
35566
35587
}
35567
35588
@@ -35579,8 +35600,8 @@ namespace ts {
35579
35600
}
35580
35601
}
35581
35602
35582
- function checkCollisionWithGlobalPromiseInGeneratedCode(node: Node, name: Identifier): void {
35583
- if (languageVersion >= ScriptTarget.ES2017 || !needCollisionCheckForIdentifier(node, name, "Promise")) {
35603
+ function checkCollisionWithGlobalPromiseInGeneratedCode(node: Node, name: Identifier | undefined ): void {
35604
+ if (!name || languageVersion >= ScriptTarget.ES2017 || !needCollisionCheckForIdentifier(node, name, "Promise")) {
35584
35605
return;
35585
35606
}
35586
35607
@@ -35598,6 +35619,76 @@ namespace ts {
35598
35619
}
35599
35620
}
35600
35621
35622
+ function recordPotentialCollisionWithWeakMapSetInGeneratedCode(node: Node, name: Identifier): void {
35623
+ if (languageVersion <= ScriptTarget.ES2021
35624
+ && (needCollisionCheckForIdentifier(node, name, "WeakMap") || needCollisionCheckForIdentifier(node, name, "WeakSet"))) {
35625
+ potentialWeakMapSetCollisions.push(node);
35626
+ }
35627
+ }
35628
+
35629
+ function checkWeakMapSetCollision(node: Node) {
35630
+ const enclosingBlockScope = getEnclosingBlockScopeContainer(node);
35631
+ if (getNodeCheckFlags(enclosingBlockScope) & NodeCheckFlags.ContainsClassWithPrivateIdentifiers) {
35632
+ Debug.assert(isNamedDeclaration(node) && isIdentifier(node.name) && typeof node.name.escapedText === "string", "The target of a WeakMap/WeakSet collision check should be an identifier");
35633
+ errorSkippedOn("noEmit", node, Diagnostics.Compiler_reserves_name_0_when_emitting_private_identifier_downlevel, node.name.escapedText);
35634
+ }
35635
+ }
35636
+
35637
+ function recordPotentialCollisionWithReflectInGeneratedCode(node: Node, name: Identifier | undefined): void {
35638
+ if (name && languageVersion >= ScriptTarget.ES2015 && languageVersion <= ScriptTarget.ES2021
35639
+ && needCollisionCheckForIdentifier(node, name, "Reflect")) {
35640
+ potentialReflectCollisions.push(node);
35641
+ }
35642
+ }
35643
+
35644
+ function checkReflectCollision(node: Node) {
35645
+ let hasCollision = false;
35646
+ if (isClassExpression(node)) {
35647
+ // ClassExpression names don't contribute to their containers, but do matter for any of their block-scoped members.
35648
+ for (const member of node.members) {
35649
+ if (getNodeCheckFlags(member) & NodeCheckFlags.ContainsSuperPropertyInStaticInitializer) {
35650
+ hasCollision = true;
35651
+ break;
35652
+ }
35653
+ }
35654
+ }
35655
+ else if (isFunctionExpression(node)) {
35656
+ // FunctionExpression names don't contribute to their containers, but do matter for their contents
35657
+ if (getNodeCheckFlags(node) & NodeCheckFlags.ContainsSuperPropertyInStaticInitializer) {
35658
+ hasCollision = true;
35659
+ }
35660
+ }
35661
+ else {
35662
+ const container = getEnclosingBlockScopeContainer(node);
35663
+ if (container && getNodeCheckFlags(container) & NodeCheckFlags.ContainsSuperPropertyInStaticInitializer) {
35664
+ hasCollision = true;
35665
+ }
35666
+ }
35667
+ if (hasCollision) {
35668
+ Debug.assert(isNamedDeclaration(node) && isIdentifier(node.name), "The target of a Reflect collision check should be an identifier");
35669
+ errorSkippedOn("noEmit", node, Diagnostics.Duplicate_identifier_0_Compiler_reserves_name_1_when_emitting_super_references_in_static_initializers,
35670
+ declarationNameToString(node.name),
35671
+ "Reflect");
35672
+ }
35673
+ }
35674
+
35675
+ function checkCollisionsForDeclarationName(node: Node, name: Identifier | undefined) {
35676
+ if (!name) return;
35677
+ checkCollisionWithRequireExportsInGeneratedCode(node, name);
35678
+ checkCollisionWithGlobalPromiseInGeneratedCode(node, name);
35679
+ recordPotentialCollisionWithWeakMapSetInGeneratedCode(node, name);
35680
+ recordPotentialCollisionWithReflectInGeneratedCode(node, name);
35681
+ if (isClassLike(node)) {
35682
+ checkTypeNameIsReserved(name, Diagnostics.Class_name_cannot_be_0);
35683
+ if (!(node.flags & NodeFlags.Ambient)) {
35684
+ checkClassNameCollisionWithObject(name);
35685
+ }
35686
+ }
35687
+ else if (isEnumDeclaration(node)) {
35688
+ checkTypeNameIsReserved(name, Diagnostics.Enum_name_cannot_be_0);
35689
+ }
35690
+ }
35691
+
35601
35692
function checkVarDeclaredNamesNotShadowed(node: VariableDeclaration | BindingElement) {
35602
35693
// - ScriptBody : StatementList
35603
35694
// It is a Syntax Error if any element of the LexicallyDeclaredNames of StatementList
@@ -35816,12 +35907,7 @@ namespace ts {
35816
35907
if (node.kind === SyntaxKind.VariableDeclaration || node.kind === SyntaxKind.BindingElement) {
35817
35908
checkVarDeclaredNamesNotShadowed(node);
35818
35909
}
35819
- checkCollisionWithRequireExportsInGeneratedCode(node, node.name);
35820
- checkCollisionWithGlobalPromiseInGeneratedCode(node, node.name);
35821
- if (languageVersion < ScriptTarget.ESNext
35822
- && (needCollisionCheckForIdentifier(node, node.name, "WeakMap") || needCollisionCheckForIdentifier(node, node.name, "WeakSet"))) {
35823
- potentialWeakMapSetCollisions.push(node);
35824
- }
35910
+ checkCollisionsForDeclarationName(node, node.name);
35825
35911
}
35826
35912
}
35827
35913
@@ -37380,14 +37466,7 @@ namespace ts {
37380
37466
function checkClassLikeDeclaration(node: ClassLikeDeclaration) {
37381
37467
checkGrammarClassLikeDeclaration(node);
37382
37468
checkDecorators(node);
37383
- if (node.name) {
37384
- checkTypeNameIsReserved(node.name, Diagnostics.Class_name_cannot_be_0);
37385
- checkCollisionWithRequireExportsInGeneratedCode(node, node.name);
37386
- checkCollisionWithGlobalPromiseInGeneratedCode(node, node.name);
37387
- if (!(node.flags & NodeFlags.Ambient)) {
37388
- checkClassNameCollisionWithObject(node.name);
37389
- }
37390
- }
37469
+ checkCollisionsForDeclarationName(node, node.name);
37391
37470
checkTypeParameters(getEffectiveTypeParameterDeclarations(node));
37392
37471
checkExportsOnMergedDeclarations(node);
37393
37472
const symbol = getSymbolOfNode(node);
@@ -38114,9 +38193,7 @@ namespace ts {
38114
38193
// Grammar checking
38115
38194
checkGrammarDecoratorsAndModifiers(node);
38116
38195
38117
- checkTypeNameIsReserved(node.name, Diagnostics.Enum_name_cannot_be_0);
38118
- checkCollisionWithRequireExportsInGeneratedCode(node, node.name);
38119
- checkCollisionWithGlobalPromiseInGeneratedCode(node, node.name);
38196
+ checkCollisionsForDeclarationName(node, node.name);
38120
38197
checkExportsOnMergedDeclarations(node);
38121
38198
node.members.forEach(checkEnumMember);
38122
38199
@@ -38225,8 +38302,7 @@ namespace ts {
38225
38302
}
38226
38303
38227
38304
if (isIdentifier(node.name)) {
38228
- checkCollisionWithRequireExportsInGeneratedCode(node, node.name);
38229
- checkCollisionWithGlobalPromiseInGeneratedCode(node, node.name);
38305
+ checkCollisionsForDeclarationName(node, node.name);
38230
38306
}
38231
38307
38232
38308
checkExportsOnMergedDeclarations(node);
@@ -38443,8 +38519,7 @@ namespace ts {
38443
38519
}
38444
38520
38445
38521
function checkImportBinding(node: ImportEqualsDeclaration | ImportClause | NamespaceImport | ImportSpecifier) {
38446
- checkCollisionWithRequireExportsInGeneratedCode(node, node.name!);
38447
- checkCollisionWithGlobalPromiseInGeneratedCode(node, node.name!);
38522
+ checkCollisionsForDeclarationName(node, node.name);
38448
38523
checkAliasSymbol(node);
38449
38524
if (node.kind === SyntaxKind.ImportSpecifier &&
38450
38525
idText(node.propertyName || node.name) === "default" &&
@@ -39162,6 +39237,7 @@ namespace ts {
39162
39237
clear(potentialThisCollisions);
39163
39238
clear(potentialNewTargetCollisions);
39164
39239
clear(potentialWeakMapSetCollisions);
39240
+ clear(potentialReflectCollisions);
39165
39241
39166
39242
forEach(node.statements, checkSourceElement);
39167
39243
checkSourceElement(node.endOfFileToken);
@@ -39206,6 +39282,11 @@ namespace ts {
39206
39282
clear(potentialWeakMapSetCollisions);
39207
39283
}
39208
39284
39285
+ if (potentialReflectCollisions.length) {
39286
+ forEach(potentialReflectCollisions, checkReflectCollision);
39287
+ clear(potentialReflectCollisions);
39288
+ }
39289
+
39209
39290
links.flags |= NodeCheckFlags.TypeChecked;
39210
39291
}
39211
39292
}
@@ -40318,7 +40399,9 @@ namespace ts {
40318
40399
}
40319
40400
40320
40401
function getNodeCheckFlags(node: Node): NodeCheckFlags {
40321
- return getNodeLinks(node).flags || 0;
40402
+ const nodeId = node.id || 0;
40403
+ if (nodeId < 0 || nodeId >= nodeLinks.length) return 0;
40404
+ return nodeLinks[nodeId]?.flags || 0;
40322
40405
}
40323
40406
40324
40407
function getEnumMemberValue(node: EnumMember): string | number | undefined {
0 commit comments