Skip to content

Commit 7ce364c

Browse files
Report CommonJS top-level Object value collisions in checker (#3870)
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: RyanCavanaugh <6685088+RyanCavanaugh@users.noreply.github.com>
1 parent ed52070 commit 7ce364c

9 files changed

Lines changed: 93 additions & 0 deletions

internal/checker/checker.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10402,6 +10402,7 @@ func (c *Checker) checkCollisionsForDeclarationName(node *ast.Node, name *ast.No
1040210402
return
1040310403
}
1040410404
c.checkCollisionWithRequireExportsInGeneratedCode(node, name)
10405+
c.checkCollisionWithGlobalObjectInGeneratedCode(node, name)
1040510406
c.checkCollisionWithGlobalPromiseInGeneratedCode(node, name)
1040610407
c.recordPotentialCollisionWithWeakMapSetInGeneratedCode(node, name)
1040710408
c.recordPotentialCollisionWithReflectInGeneratedCode(node, name)
@@ -10435,6 +10436,22 @@ func (c *Checker) checkCollisionWithRequireExportsInGeneratedCode(node *ast.Node
1043510436
}
1043610437
}
1043710438

10439+
func (c *Checker) checkCollisionWithGlobalObjectInGeneratedCode(node *ast.Node, name *ast.Node) {
10440+
if name == nil || ast.IsClassLike(node) || !c.needCollisionCheckForIdentifier(node, name, "Object") {
10441+
return
10442+
}
10443+
// Uninstantiated modules shouldn't do this check
10444+
if ast.IsModuleDeclaration(node) && ast.GetModuleInstanceState(node) != ast.ModuleInstanceStateInstantiated {
10445+
return
10446+
}
10447+
// In case of variable declaration, node.parent is variable statement so look at the variable statement's parent
10448+
parent := ast.GetDeclarationContainer(node)
10449+
if ast.IsSourceFile(parent) && ast.IsExternalOrCommonJSModule(parent.AsSourceFile()) && c.program.GetEmitModuleFormatOfFile(parent.AsSourceFile()) == core.ModuleKindCommonJS {
10450+
// If the declaration happens to be in external module, report error that Object is a reserved identifier.
10451+
c.errorSkippedOnNoEmit(name, diagnostics.Duplicate_identifier_0_Compiler_reserves_name_1_in_top_level_scope_of_a_module, scanner.DeclarationNameToString(name), scanner.DeclarationNameToString(name))
10452+
}
10453+
}
10454+
1043810455
func (c *Checker) needCollisionCheckForIdentifier(node *ast.Node, identifier *ast.Node, name string) bool {
1043910456
if identifier != nil && identifier.Text() != name {
1044010457
return false
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
objectNameCollisionCommonJS.ts(1,5): error TS2441: Duplicate identifier 'Object'. Compiler reserves name 'Object' in top level scope of a module.
2+
3+
4+
==== objectNameCollisionCommonJS.ts (1 errors) ====
5+
let Object = 0;
6+
~~~~~~
7+
!!! error TS2441: Duplicate identifier 'Object'. Compiler reserves name 'Object' in top level scope of a module.
8+
export const x = 1;
9+
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
//// [tests/cases/compiler/objectNameCollisionCommonJS.ts] ////
2+
3+
//// [objectNameCollisionCommonJS.ts]
4+
let Object = 0;
5+
export const x = 1;
6+
7+
8+
//// [objectNameCollisionCommonJS.js]
9+
"use strict";
10+
Object.defineProperty(exports, "__esModule", { value: true });
11+
exports.x = void 0;
12+
let Object = 0;
13+
exports.x = 1;
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
//// [tests/cases/compiler/objectNameCollisionCommonJS.ts] ////
2+
3+
=== objectNameCollisionCommonJS.ts ===
4+
let Object = 0;
5+
>Object : Symbol(Object, Decl(objectNameCollisionCommonJS.ts, 0, 3))
6+
7+
export const x = 1;
8+
>x : Symbol(x, Decl(objectNameCollisionCommonJS.ts, 1, 12))
9+
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
//// [tests/cases/compiler/objectNameCollisionCommonJS.ts] ////
2+
3+
=== objectNameCollisionCommonJS.ts ===
4+
let Object = 0;
5+
>Object : number
6+
>0 : 0
7+
8+
export const x = 1;
9+
>x : 1
10+
>1 : 1
11+
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
//// [tests/cases/compiler/objectNameCollisionCommonJS.ts] ////
2+
3+
//// [objectNameCollisionCommonJS.ts]
4+
let Object = 0;
5+
export const x = 1;
6+
7+
8+
//// [objectNameCollisionCommonJS.js]
9+
let Object = 0;
10+
export const x = 1;
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
//// [tests/cases/compiler/objectNameCollisionCommonJS.ts] ////
2+
3+
=== objectNameCollisionCommonJS.ts ===
4+
let Object = 0;
5+
>Object : Symbol(Object, Decl(objectNameCollisionCommonJS.ts, 0, 3))
6+
7+
export const x = 1;
8+
>x : Symbol(x, Decl(objectNameCollisionCommonJS.ts, 1, 12))
9+
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
//// [tests/cases/compiler/objectNameCollisionCommonJS.ts] ////
2+
3+
=== objectNameCollisionCommonJS.ts ===
4+
let Object = 0;
5+
>Object : number
6+
>0 : 0
7+
8+
export const x = 1;
9+
>x : 1
10+
>1 : 1
11+
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
// @module: commonjs,esnext
2+
3+
let Object = 0;
4+
export const x = 1;

0 commit comments

Comments
 (0)