Skip to content

Commit 4ccef9f

Browse files
authored
Defer binding of expando assignments and give them lower priority (#2715)
1 parent 4e5c49d commit 4ccef9f

13 files changed

Lines changed: 452 additions & 340 deletions

internal/binder/binder.go

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,12 @@ const (
4141
ContainerFlagsIsThisContainer ContainerFlags = 1 << 8
4242
)
4343

44+
type ExpandoAssignmentInfo struct {
45+
node *ast.Node
46+
container *ast.Node
47+
blockScopeContainer *ast.Node
48+
}
49+
4450
type Binder struct {
4551
file *ast.SourceFile
4652
bindFunc func(*ast.Node) bool
@@ -73,6 +79,7 @@ type Binder struct {
7379
flowNodePool core.Pool[ast.FlowNode]
7480
flowListPool core.Pool[ast.FlowList]
7581
singleDeclarationsPool core.Pool[*ast.Node]
82+
expandoAssignments []ExpandoAssignmentInfo
7683
}
7784

7885
func (b *Binder) options() core.SourceFileAffectingCompilerOptions {
@@ -123,6 +130,7 @@ func bindSourceFile(file *ast.SourceFile) {
123130
b.inStrictMode = b.options().BindInStrictMode && !file.IsDeclarationFile || ast.IsExternalModule(file)
124131
b.unreachableFlow = b.newFlowNode(ast.FlowFlagsUnreachable)
125132
b.bind(file.AsNode())
133+
b.bindDeferredExpandoAssignments()
126134
file.SymbolCount = b.symbolCount
127135
file.ClassifiableNames = b.classifiableNames
128136
})
@@ -1011,6 +1019,22 @@ func addLateBoundAssignmentDeclarationToSymbol(node *ast.Node, symbol *ast.Symbo
10111019
}
10121020

10131021
func (b *Binder) bindExpandoPropertyAssignment(node *ast.Node) {
1022+
b.expandoAssignments = append(b.expandoAssignments, ExpandoAssignmentInfo{
1023+
node: node,
1024+
container: b.container,
1025+
blockScopeContainer: b.blockScopeContainer,
1026+
})
1027+
}
1028+
1029+
func (b *Binder) bindDeferredExpandoAssignments() {
1030+
for _, info := range b.expandoAssignments {
1031+
b.container = info.container
1032+
b.blockScopeContainer = info.blockScopeContainer
1033+
b.bindDeferredExpandoAssignment(info.node)
1034+
}
1035+
}
1036+
1037+
func (b *Binder) bindDeferredExpandoAssignment(node *ast.Node) {
10141038
parent := getParentOfPropertyAssignment(node)
10151039
symbol := b.lookupEntity(parent, b.blockScopeContainer)
10161040
if symbol == nil {
@@ -1021,7 +1045,11 @@ func (b *Binder) bindExpandoPropertyAssignment(node *ast.Node) {
10211045
b.bindAnonymousDeclaration(node, ast.SymbolFlagsProperty|ast.SymbolFlagsAssignment, ast.InternalSymbolNameComputed)
10221046
addLateBoundAssignmentDeclarationToSymbol(node, symbol)
10231047
} else {
1024-
b.declareSymbol(ast.GetExports(symbol), symbol, node, ast.SymbolFlagsProperty|ast.SymbolFlagsAssignment, ast.SymbolFlagsPropertyExcludes)
1048+
// We declare expandos only when there are no non-expando declarations for that name.
1049+
exports := ast.GetExports(symbol)
1050+
if existing := exports[b.getDeclarationName(node)]; existing == nil || existing.Flags&ast.SymbolFlagsAssignment != 0 {
1051+
b.declareSymbol(exports, symbol, node, ast.SymbolFlagsProperty|ast.SymbolFlagsAssignment, ast.SymbolFlagsPropertyExcludes)
1052+
}
10251053
}
10261054
}
10271055
}

testdata/baselines/reference/submodule/compiler/expandoFunctionNestedAssigmentsDeclared.symbols

Lines changed: 66 additions & 66 deletions
Large diffs are not rendered by default.

testdata/baselines/reference/submodule/compiler/expandoFunctionNestedAssigmentsDeclared.symbols.diff

Lines changed: 192 additions & 55 deletions
Large diffs are not rendered by default.

testdata/baselines/reference/submodule/compiler/targetTypeTest1.symbols

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ declare class Point
2121
>Point : Symbol(Point, Decl(targetTypeTest1.ts, 8, 1), Decl(targetTypeTest1.ts, 0, 0))
2222

2323
static origin: Point;
24-
>origin : Symbol(Point.origin, Decl(targetTypeTest1.ts, 5, 48), Decl(targetTypeTest1.ts, 22, 17))
24+
>origin : Symbol(Point.origin, Decl(targetTypeTest1.ts, 5, 48))
2525
>Point : Symbol(Point, Decl(targetTypeTest1.ts, 8, 1), Decl(targetTypeTest1.ts, 0, 0))
2626

2727
}
@@ -59,19 +59,19 @@ var x = EF1(1,2);
5959

6060
// Point.origin declared as type Point
6161
Point.origin = new Point(0, 0);
62-
>Point.origin : Symbol(Point.origin, Decl(targetTypeTest1.ts, 5, 48), Decl(targetTypeTest1.ts, 22, 17))
62+
>Point.origin : Symbol(Point.origin, Decl(targetTypeTest1.ts, 5, 48))
6363
>Point : Symbol(Point, Decl(targetTypeTest1.ts, 8, 1), Decl(targetTypeTest1.ts, 0, 0))
64-
>origin : Symbol(Point.origin, Decl(targetTypeTest1.ts, 5, 48), Decl(targetTypeTest1.ts, 22, 17))
64+
>origin : Symbol(Point.origin, Decl(targetTypeTest1.ts, 5, 48))
6565
>Point : Symbol(Point, Decl(targetTypeTest1.ts, 8, 1), Decl(targetTypeTest1.ts, 0, 0))
6666

6767
// Point.prototype declared as type Point
6868
// this inferred as Point because of obj.prop assignment
6969
// dx, dy, and return type inferred using target typing
7070
Point.prototype.add = function(dx, dy) {
7171
>Point.prototype.add : Symbol(Point.add, Decl(targetTypeTest1.ts, 4, 23))
72-
>Point.prototype : Symbol(Point.prototype, Decl(targetTypeTest1.ts, 34, 19))
72+
>Point.prototype : Symbol(Point.prototype)
7373
>Point : Symbol(Point, Decl(targetTypeTest1.ts, 8, 1), Decl(targetTypeTest1.ts, 0, 0))
74-
>prototype : Symbol(Point.prototype, Decl(targetTypeTest1.ts, 34, 19))
74+
>prototype : Symbol(Point.prototype)
7575
>add : Symbol(Point.add, Decl(targetTypeTest1.ts, 4, 23))
7676
>dx : Symbol(dx, Decl(targetTypeTest1.ts, 30, 31))
7777
>dy : Symbol(dy, Decl(targetTypeTest1.ts, 30, 34))
@@ -90,9 +90,9 @@ var f : number = 5;
9090
// this in function add inferred to be type of object literal (i.e. Point)
9191
// dx, dy, and return type of add inferred using target typing
9292
Point.prototype = {
93-
>Point.prototype : Symbol(Point.prototype, Decl(targetTypeTest1.ts, 34, 19))
93+
>Point.prototype : Symbol(Point.prototype)
9494
>Point : Symbol(Point, Decl(targetTypeTest1.ts, 8, 1), Decl(targetTypeTest1.ts, 0, 0))
95-
>prototype : Symbol(Point.prototype, Decl(targetTypeTest1.ts, 34, 19))
95+
>prototype : Symbol(Point.prototype)
9696

9797
x: 0,
9898
>x : Symbol(x, Decl(targetTypeTest1.ts, 39, 19))
@@ -155,9 +155,9 @@ function C(a,b) {
155155
}
156156

157157
C.prototype =
158-
>C.prototype : Symbol(C.prototype, Decl(targetTypeTest1.ts, 62, 1))
158+
>C.prototype : Symbol(C.prototype)
159159
>C : Symbol(C, Decl(targetTypeTest1.ts, 57, 1), Decl(targetTypeTest1.ts, 50, 1))
160-
>prototype : Symbol(C.prototype, Decl(targetTypeTest1.ts, 62, 1))
160+
>prototype : Symbol(C.prototype)
161161

162162
{ a:0,
163163
>a : Symbol(a, Decl(targetTypeTest1.ts, 65, 2))

testdata/baselines/reference/submodule/compiler/targetTypeTest1.symbols.diff

Lines changed: 17 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,9 @@
1717
+>Point : Symbol(Point, Decl(targetTypeTest1.ts, 8, 1), Decl(targetTypeTest1.ts, 0, 0))
1818

1919
static origin: Point;
20-
>origin : Symbol(Point.origin, Decl(targetTypeTest1.ts, 5, 48), Decl(targetTypeTest1.ts, 22, 17))
20+
->origin : Symbol(Point.origin, Decl(targetTypeTest1.ts, 5, 48), Decl(targetTypeTest1.ts, 22, 17))
2121
->Point : Symbol(Point, Decl(targetTypeTest1.ts, 8, 1), Decl(targetTypeTest1.ts, 0, 0), Decl(targetTypeTest1.ts, 22, 17))
22+
+>origin : Symbol(Point.origin, Decl(targetTypeTest1.ts, 5, 48))
2223
+>Point : Symbol(Point, Decl(targetTypeTest1.ts, 8, 1), Decl(targetTypeTest1.ts, 0, 0))
2324

2425
}
@@ -32,27 +33,28 @@
3233
>x : Symbol(x, Decl(targetTypeTest1.ts, 13, 15))
3334
>y : Symbol(y, Decl(targetTypeTest1.ts, 13, 17))
3435

35-
@@= skipped -30, +30 lines =@@
36+
@@= skipped -29, +29 lines =@@
37+
3638
// Point.origin declared as type Point
3739
Point.origin = new Point(0, 0);
38-
>Point.origin : Symbol(Point.origin, Decl(targetTypeTest1.ts, 5, 48), Decl(targetTypeTest1.ts, 22, 17))
40+
->Point.origin : Symbol(Point.origin, Decl(targetTypeTest1.ts, 5, 48), Decl(targetTypeTest1.ts, 22, 17))
3941
->Point : Symbol(Point, Decl(targetTypeTest1.ts, 8, 1), Decl(targetTypeTest1.ts, 0, 0), Decl(targetTypeTest1.ts, 22, 17))
40-
+>Point : Symbol(Point, Decl(targetTypeTest1.ts, 8, 1), Decl(targetTypeTest1.ts, 0, 0))
41-
>origin : Symbol(Point.origin, Decl(targetTypeTest1.ts, 5, 48), Decl(targetTypeTest1.ts, 22, 17))
42+
->origin : Symbol(Point.origin, Decl(targetTypeTest1.ts, 5, 48), Decl(targetTypeTest1.ts, 22, 17))
4243
->Point : Symbol(Point, Decl(targetTypeTest1.ts, 8, 1), Decl(targetTypeTest1.ts, 0, 0), Decl(targetTypeTest1.ts, 22, 17))
44+
+>Point.origin : Symbol(Point.origin, Decl(targetTypeTest1.ts, 5, 48))
45+
+>Point : Symbol(Point, Decl(targetTypeTest1.ts, 8, 1), Decl(targetTypeTest1.ts, 0, 0))
46+
+>origin : Symbol(Point.origin, Decl(targetTypeTest1.ts, 5, 48))
4347
+>Point : Symbol(Point, Decl(targetTypeTest1.ts, 8, 1), Decl(targetTypeTest1.ts, 0, 0))
4448

4549
// Point.prototype declared as type Point
4650
// this inferred as Point because of obj.prop assignment
47-
// dx, dy, and return type inferred using target typing
51+
@@= skipped -11, +11 lines =@@
4852
Point.prototype.add = function(dx, dy) {
4953
>Point.prototype.add : Symbol(Point.add, Decl(targetTypeTest1.ts, 4, 23))
50-
->Point.prototype : Symbol(Point.prototype)
54+
>Point.prototype : Symbol(Point.prototype)
5155
->Point : Symbol(Point, Decl(targetTypeTest1.ts, 8, 1), Decl(targetTypeTest1.ts, 0, 0), Decl(targetTypeTest1.ts, 22, 17))
52-
->prototype : Symbol(Point.prototype)
53-
+>Point.prototype : Symbol(Point.prototype, Decl(targetTypeTest1.ts, 34, 19))
5456
+>Point : Symbol(Point, Decl(targetTypeTest1.ts, 8, 1), Decl(targetTypeTest1.ts, 0, 0))
55-
+>prototype : Symbol(Point.prototype, Decl(targetTypeTest1.ts, 34, 19))
57+
>prototype : Symbol(Point.prototype)
5658
>add : Symbol(Point.add, Decl(targetTypeTest1.ts, 4, 23))
5759
>dx : Symbol(dx, Decl(targetTypeTest1.ts, 30, 31))
5860
>dy : Symbol(dy, Decl(targetTypeTest1.ts, 30, 34))
@@ -63,37 +65,21 @@
6365
>dx : Symbol(dx, Decl(targetTypeTest1.ts, 30, 31))
6466
>dy : Symbol(dy, Decl(targetTypeTest1.ts, 30, 34))
6567

66-
@@= skipped -30, +30 lines =@@
67-
// this in function add inferred to be type of object literal (i.e. Point)
68+
@@= skipped -21, +21 lines =@@
6869
// dx, dy, and return type of add inferred using target typing
6970
Point.prototype = {
70-
->Point.prototype : Symbol(Point.prototype)
71+
>Point.prototype : Symbol(Point.prototype)
7172
->Point : Symbol(Point, Decl(targetTypeTest1.ts, 8, 1), Decl(targetTypeTest1.ts, 0, 0), Decl(targetTypeTest1.ts, 22, 17))
72-
->prototype : Symbol(Point.prototype)
73-
+>Point.prototype : Symbol(Point.prototype, Decl(targetTypeTest1.ts, 34, 19))
7473
+>Point : Symbol(Point, Decl(targetTypeTest1.ts, 8, 1), Decl(targetTypeTest1.ts, 0, 0))
75-
+>prototype : Symbol(Point.prototype, Decl(targetTypeTest1.ts, 34, 19))
74+
>prototype : Symbol(Point.prototype)
7675

7776
x: 0,
78-
>x : Symbol(x, Decl(targetTypeTest1.ts, 39, 19))
79-
@@= skipped -16, +16 lines =@@
77+
@@= skipped -15, +15 lines =@@
8078
>dy : Symbol(dy, Decl(targetTypeTest1.ts, 42, 21))
8179

8280
return new Point(this.x + dx, this.y + dy);
8381
->Point : Symbol(Point, Decl(targetTypeTest1.ts, 8, 1), Decl(targetTypeTest1.ts, 0, 0), Decl(targetTypeTest1.ts, 22, 17))
8482
+>Point : Symbol(Point, Decl(targetTypeTest1.ts, 8, 1), Decl(targetTypeTest1.ts, 0, 0))
8583
>dx : Symbol(dx, Decl(targetTypeTest1.ts, 42, 18))
8684
>dy : Symbol(dy, Decl(targetTypeTest1.ts, 42, 21))
87-
}
88-
@@= skipped -49, +49 lines =@@
89-
}
90-
91-
C.prototype =
92-
->C.prototype : Symbol(C.prototype)
93-
+>C.prototype : Symbol(C.prototype, Decl(targetTypeTest1.ts, 62, 1))
94-
>C : Symbol(C, Decl(targetTypeTest1.ts, 57, 1), Decl(targetTypeTest1.ts, 50, 1))
95-
->prototype : Symbol(C.prototype)
96-
+>prototype : Symbol(C.prototype, Decl(targetTypeTest1.ts, 62, 1))
97-
98-
{ a:0,
99-
>a : Symbol(a, Decl(targetTypeTest1.ts, 65, 2))
85+
}

testdata/baselines/reference/submodule/compiler/targetTypeTest1.types

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -116,11 +116,11 @@ var f : number = 5;
116116
// this in function add inferred to be type of object literal (i.e. Point)
117117
// dx, dy, and return type of add inferred using target typing
118118
Point.prototype = {
119-
>Point.prototype = { x: 0, y: 0, add: function(dx, dy) { return new Point(this.x + dx, this.y + dy); }} : { x: number; y: number; add: (dx: any, dy: any) => Point; }
119+
>Point.prototype = { x: 0, y: 0, add: function(dx, dy) { return new Point(this.x + dx, this.y + dy); }} : { x: number; y: number; add: (dx: number, dy: number) => Point; }
120120
>Point.prototype : Point
121121
>Point : typeof Point
122122
>prototype : Point
123-
>{ x: 0, y: 0, add: function(dx, dy) { return new Point(this.x + dx, this.y + dy); }} : { x: number; y: number; add: (dx: any, dy: any) => Point; }
123+
>{ x: 0, y: 0, add: function(dx, dy) { return new Point(this.x + dx, this.y + dy); }} : { x: number; y: number; add: (dx: number, dy: number) => Point; }
124124

125125
x: 0,
126126
>x : number
@@ -131,10 +131,10 @@ Point.prototype = {
131131
>0 : 0
132132

133133
add: function(dx, dy) {
134-
>add : (dx: any, dy: any) => Point
135-
>function(dx, dy) { return new Point(this.x + dx, this.y + dy); } : (dx: any, dy: any) => Point
136-
>dx : any
137-
>dy : any
134+
>add : (dx: number, dy: number) => Point
135+
>function(dx, dy) { return new Point(this.x + dx, this.y + dy); } : (dx: number, dy: number) => Point
136+
>dx : number
137+
>dy : number
138138

139139
return new Point(this.x + dx, this.y + dy);
140140
>new Point(this.x + dx, this.y + dy) : Point
@@ -143,12 +143,12 @@ Point.prototype = {
143143
>this.x : any
144144
>this : any
145145
>x : any
146-
>dx : any
146+
>dx : number
147147
>this.y + dy : any
148148
>this.y : any
149149
>this : any
150150
>y : any
151-
>dy : any
151+
>dy : number
152152
}
153153
};
154154

@@ -205,13 +205,13 @@ function C(a,b) {
205205
}
206206

207207
C.prototype =
208-
>C.prototype = { a:0, b:0, C1M1: function(c,d) { return (this.a + c) + (this.b + d); } } : { a: number; b: number; C1M1: (c: any, d: any) => any; }
208+
>C.prototype = { a:0, b:0, C1M1: function(c,d) { return (this.a + c) + (this.b + d); } } : { a: number; b: number; C1M1: (c: number, d: number) => any; }
209209
>C.prototype : C
210210
>C : typeof C
211211
>prototype : C
212212

213213
{ a:0,
214-
>{ a:0, b:0, C1M1: function(c,d) { return (this.a + c) + (this.b + d); } } : { a: number; b: number; C1M1: (c: any, d: any) => any; }
214+
>{ a:0, b:0, C1M1: function(c,d) { return (this.a + c) + (this.b + d); } } : { a: number; b: number; C1M1: (c: number, d: number) => any; }
215215
>a : number
216216
>0 : 0
217217

@@ -220,10 +220,10 @@ C.prototype =
220220
>0 : 0
221221

222222
C1M1: function(c,d) {
223-
>C1M1 : (c: any, d: any) => any
224-
>function(c,d) { return (this.a + c) + (this.b + d); } : (c: any, d: any) => any
225-
>c : any
226-
>d : any
223+
>C1M1 : (c: number, d: number) => any
224+
>function(c,d) { return (this.a + c) + (this.b + d); } : (c: number, d: number) => any
225+
>c : number
226+
>d : number
227227

228228
return (this.a + c) + (this.b + d);
229229
>(this.a + c) + (this.b + d) : any
@@ -232,13 +232,13 @@ C.prototype =
232232
>this.a : any
233233
>this : any
234234
>a : any
235-
>c : any
235+
>c : number
236236
>(this.b + d) : any
237237
>this.b + d : any
238238
>this.b : any
239239
>this : any
240240
>b : any
241-
>d : any
241+
>d : number
242242
}
243243
};
244244

testdata/baselines/reference/submodule/compiler/targetTypeTest1.types.diff

Lines changed: 0 additions & 92 deletions
This file was deleted.

0 commit comments

Comments
 (0)