Skip to content

Commit 301ee4a

Browse files
Copilotjakebailey
andcommitted
Port WeakMap/WeakSet collision detection from TypeScript checker
Add potentialWeakMapSetCollisions array and collision checking functions Co-authored-by: jakebailey <[email protected]>
1 parent 5c22781 commit 301ee4a

File tree

1 file changed

+41
-0
lines changed

1 file changed

+41
-0
lines changed

internal/checker/checker.go

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -774,6 +774,7 @@ type Checker struct {
774774
lastFlowNodeReachable bool
775775
flowNodeReachable map[*ast.FlowNode]bool
776776
flowNodePostSuper map[*ast.FlowNode]bool
777+
potentialWeakMapSetCollisions []*ast.Node
777778
renamedBindingElementsInTypes []*ast.Node
778779
contextualInfos []ContextualInfo
779780
inferenceContextInfos []InferenceContextInfo
@@ -2126,6 +2127,7 @@ func (c *Checker) checkSourceFile(ctx context.Context, sourceFile *ast.SourceFil
21262127
// Grammar checking
21272128
c.checkGrammarSourceFile(sourceFile)
21282129
c.renamedBindingElementsInTypes = nil
2130+
c.potentialWeakMapSetCollisions = nil
21292131
c.checkSourceElements(sourceFile.Statements.Nodes)
21302132
c.checkDeferredNodes(sourceFile)
21312133
if ast.IsExternalOrCommonJSModule(sourceFile) {
@@ -2143,6 +2145,12 @@ func (c *Checker) checkSourceFile(ctx context.Context, sourceFile *ast.SourceFil
21432145
} else {
21442146
c.wasCanceled = true
21452147
}
2148+
if len(c.potentialWeakMapSetCollisions) > 0 {
2149+
for _, node := range c.potentialWeakMapSetCollisions {
2150+
c.checkWeakMapSetCollision(node)
2151+
}
2152+
c.potentialWeakMapSetCollisions = nil
2153+
}
21462154
c.ctx = nil
21472155
links.typeChecked = true
21482156
}
@@ -2536,6 +2544,7 @@ func (c *Checker) checkPropertyDeclaration(node *ast.Node) {
25362544
c.checkGrammarComputedPropertyName(node.Name())
25372545
}
25382546
c.checkVariableLikeDeclaration(node)
2547+
c.setNodeLinksForPrivateIdentifierScope(node)
25392548
// property signatures already report "initializer not allowed in ambient context" elsewhere
25402549
if ast.HasSyntacticModifier(node, ast.ModifierFlagsAbstract) && ast.IsPropertyDeclaration(node) {
25412550
if node.Initializer() != nil {
@@ -2633,6 +2642,7 @@ func (c *Checker) checkMethodDeclaration(node *ast.Node) {
26332642
if ast.IsPrivateIdentifier(node.Name()) && ast.GetContainingClass(node) == nil {
26342643
c.error(node, diagnostics.Private_identifiers_are_not_allowed_outside_class_bodies)
26352644
}
2645+
c.setNodeLinksForPrivateIdentifierScope(node)
26362646
}
26372647

26382648
func (c *Checker) checkClassStaticBlockDeclaration(node *ast.Node) {
@@ -2800,6 +2810,7 @@ func (c *Checker) checkAccessorDeclaration(node *ast.Node) {
28002810
c.checkAllCodePathsInNonVoidFunctionReturnOrThrow(node, returnType)
28012811
}
28022812
c.checkSourceElement(node.Body())
2813+
c.setNodeLinksForPrivateIdentifierScope(node)
28032814
}
28042815

28052816
func (c *Checker) checkTypeReferenceNode(node *ast.Node) {
@@ -10148,6 +10159,7 @@ func (c *Checker) assignBindingElementTypes(pattern *ast.Node, parentType *Type)
1014810159

1014910160
func (c *Checker) checkCollisionsForDeclarationName(node *ast.Node, name *ast.Node) {
1015010161
c.checkCollisionWithRequireExportsInGeneratedCode(node, name)
10162+
c.recordPotentialCollisionWithWeakMapSetInGeneratedCode(node, name)
1015110163
switch {
1015210164
case name == nil:
1015310165
return
@@ -10206,6 +10218,35 @@ func (c *Checker) needCollisionCheckForIdentifier(node *ast.Node, identifier *as
1020610218
return true
1020710219
}
1020810220

10221+
func (c *Checker) setNodeLinksForPrivateIdentifierScope(node *ast.Node) {
10222+
if name := node.Name(); ast.IsPrivateIdentifier(name) {
10223+
// Check if we need to mark containers with the ContainsClassWithPrivateIdentifiers flag
10224+
// This happens for older language versions or when useDefineForClassFields is false
10225+
// PrivateNamesAndClassStaticBlocks is ES2022, ClassAndClassElementDecorators is ESNext
10226+
if c.languageVersion < core.ScriptTargetES2022 || c.languageVersion < core.ScriptTargetESNext || !c.emitStandardClassFields {
10227+
for lexicalScope := ast.GetEnclosingBlockScopeContainer(node); lexicalScope != nil; lexicalScope = ast.GetEnclosingBlockScopeContainer(lexicalScope) {
10228+
c.nodeLinks.Get(lexicalScope).flags |= NodeCheckFlagsContainsClassWithPrivateIdentifiers
10229+
}
10230+
}
10231+
}
10232+
}
10233+
10234+
func (c *Checker) recordPotentialCollisionWithWeakMapSetInGeneratedCode(node *ast.Node, name *ast.Node) {
10235+
if c.languageVersion <= core.ScriptTargetES2021 &&
10236+
(c.needCollisionCheckForIdentifier(node, name, "WeakMap") || c.needCollisionCheckForIdentifier(node, name, "WeakSet")) {
10237+
c.potentialWeakMapSetCollisions = append(c.potentialWeakMapSetCollisions, node)
10238+
}
10239+
}
10240+
10241+
func (c *Checker) checkWeakMapSetCollision(node *ast.Node) {
10242+
enclosingBlockScope := ast.GetEnclosingBlockScopeContainer(node)
10243+
if c.nodeLinks.Get(enclosingBlockScope).flags&NodeCheckFlagsContainsClassWithPrivateIdentifiers != 0 {
10244+
if name := node.Name(); ast.IsIdentifier(name) {
10245+
c.errorSkippedOnNoEmit(node, diagnostics.Compiler_reserves_name_0_when_emitting_private_identifier_downlevel, name.Text())
10246+
}
10247+
}
10248+
}
10249+
1020910250
func (c *Checker) checkTypeOfExpression(node *ast.Node) *Type {
1021010251
c.checkExpression(node.Expression())
1021110252
return c.typeofType

0 commit comments

Comments
 (0)