Skip to content

Commit 9717772

Browse files
authored
Allow assignments to readonly class properties within IIFEs contained in constructors (#60416)
1 parent b263cc4 commit 9717772

File tree

6 files changed

+166
-79
lines changed

6 files changed

+166
-79
lines changed

src/compiler/checker.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39082,7 +39082,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
3908239082
expr.expression.kind === SyntaxKind.ThisKeyword
3908339083
) {
3908439084
// Look for if this is the constructor for the class that `symbol` is a property of.
39085-
const ctor = getContainingFunction(expr);
39085+
const ctor = getControlFlowContainer(expr);
3908639086
if (!(ctor && (ctor.kind === SyntaxKind.Constructor || isJSConstructor(ctor)))) {
3908739087
return true;
3908839088
}

tests/baselines/reference/readonlyMembers.errors.txt

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,19 @@ readonlyMembers.ts(16,14): error TS2540: Cannot assign to 'c' because it is a re
44
readonlyMembers.ts(18,18): error TS2540: Cannot assign to 'a' because it is a read-only property.
55
readonlyMembers.ts(19,18): error TS2540: Cannot assign to 'b' because it is a read-only property.
66
readonlyMembers.ts(20,18): error TS2540: Cannot assign to 'c' because it is a read-only property.
7-
readonlyMembers.ts(24,14): error TS2540: Cannot assign to 'a' because it is a read-only property.
8-
readonlyMembers.ts(25,14): error TS2540: Cannot assign to 'b' because it is a read-only property.
9-
readonlyMembers.ts(26,14): error TS2540: Cannot assign to 'c' because it is a read-only property.
10-
readonlyMembers.ts(35,3): error TS2540: Cannot assign to 'a' because it is a read-only property.
11-
readonlyMembers.ts(39,3): error TS2540: Cannot assign to 'a' because it is a read-only property.
12-
readonlyMembers.ts(48,3): error TS2540: Cannot assign to 'A' because it is a read-only property.
13-
readonlyMembers.ts(55,3): error TS2540: Cannot assign to 'a' because it is a read-only property.
14-
readonlyMembers.ts(61,1): error TS2542: Index signature in type '{ readonly [x: string]: string; }' only permits reading.
15-
readonlyMembers.ts(64,1): error TS2542: Index signature in type '{ readonly [x: number]: string; [x: string]: string; }' only permits reading.
7+
readonlyMembers.ts(25,18): error TS2540: Cannot assign to 'c' because it is a read-only property.
8+
readonlyMembers.ts(29,14): error TS2540: Cannot assign to 'a' because it is a read-only property.
9+
readonlyMembers.ts(30,14): error TS2540: Cannot assign to 'b' because it is a read-only property.
10+
readonlyMembers.ts(31,14): error TS2540: Cannot assign to 'c' because it is a read-only property.
11+
readonlyMembers.ts(40,3): error TS2540: Cannot assign to 'a' because it is a read-only property.
12+
readonlyMembers.ts(44,3): error TS2540: Cannot assign to 'a' because it is a read-only property.
13+
readonlyMembers.ts(53,3): error TS2540: Cannot assign to 'A' because it is a read-only property.
14+
readonlyMembers.ts(60,3): error TS2540: Cannot assign to 'a' because it is a read-only property.
15+
readonlyMembers.ts(66,1): error TS2542: Index signature in type '{ readonly [x: string]: string; }' only permits reading.
16+
readonlyMembers.ts(69,1): error TS2542: Index signature in type '{ readonly [x: number]: string; [x: string]: string; }' only permits reading.
1617

1718

18-
==== readonlyMembers.ts (15 errors) ====
19+
==== readonlyMembers.ts (16 errors) ====
1920
interface X {
2021
readonly a: number;
2122
readonly b?: number;
@@ -48,7 +49,14 @@ readonlyMembers.ts(64,1): error TS2542: Index signature in type '{ readonly [x:
4849
this.c = 1; // Error
4950
~
5051
!!! error TS2540: Cannot assign to 'c' because it is a read-only property.
51-
}
52+
};
53+
(() => {
54+
this.a = 1; // Ok
55+
this.b = 1; // Ok
56+
this.c = 1; // Error
57+
~
58+
!!! error TS2540: Cannot assign to 'c' because it is a read-only property.
59+
})();
5260
}
5361
foo() {
5462
this.a = 1; // Error

tests/baselines/reference/readonlyMembers.js

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,12 @@ class C {
2121
this.a = 1; // Error
2222
this.b = 1; // Error
2323
this.c = 1; // Error
24-
}
24+
};
25+
(() => {
26+
this.a = 1; // Ok
27+
this.b = 1; // Ok
28+
this.c = 1; // Error
29+
})();
2530
}
2631
foo() {
2732
this.a = 1; // Error
@@ -83,6 +88,11 @@ var C = /** @class */ (function () {
8388
_this.b = 1; // Error
8489
_this.c = 1; // Error
8590
};
91+
(function () {
92+
_this.a = 1; // Ok
93+
_this.b = 1; // Ok
94+
_this.c = 1; // Error
95+
})();
8696
}
8797
Object.defineProperty(C.prototype, "c", {
8898
get: function () { return 1; },

tests/baselines/reference/readonlyMembers.symbols

Lines changed: 82 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -70,10 +70,28 @@ class C {
7070
>this.c : Symbol(C.c, Decl(readonlyMembers.ts, 10, 19))
7171
>this : Symbol(C, Decl(readonlyMembers.ts, 6, 8))
7272
>c : Symbol(C.c, Decl(readonlyMembers.ts, 10, 19))
73-
}
73+
74+
};
75+
(() => {
76+
this.a = 1; // Ok
77+
>this.a : Symbol(C.a, Decl(readonlyMembers.ts, 8, 9))
78+
>this : Symbol(C, Decl(readonlyMembers.ts, 6, 8))
79+
>a : Symbol(C.a, Decl(readonlyMembers.ts, 8, 9))
80+
81+
this.b = 1; // Ok
82+
>this.b : Symbol(C.b, Decl(readonlyMembers.ts, 9, 23))
83+
>this : Symbol(C, Decl(readonlyMembers.ts, 6, 8))
84+
>b : Symbol(C.b, Decl(readonlyMembers.ts, 9, 23))
85+
86+
this.c = 1; // Error
87+
>this.c : Symbol(C.c, Decl(readonlyMembers.ts, 10, 19))
88+
>this : Symbol(C, Decl(readonlyMembers.ts, 6, 8))
89+
>c : Symbol(C.c, Decl(readonlyMembers.ts, 10, 19))
90+
91+
})();
7492
}
7593
foo() {
76-
>foo : Symbol(C.foo, Decl(readonlyMembers.ts, 21, 5))
94+
>foo : Symbol(C.foo, Decl(readonlyMembers.ts, 26, 5))
7795

7896
this.a = 1; // Error
7997
>this.a : Symbol(C.a, Decl(readonlyMembers.ts, 8, 9))
@@ -93,121 +111,121 @@ class C {
93111
}
94112

95113
var o = {
96-
>o : Symbol(o, Decl(readonlyMembers.ts, 29, 3))
114+
>o : Symbol(o, Decl(readonlyMembers.ts, 34, 3))
97115

98116
get a() { return 1 },
99-
>a : Symbol(a, Decl(readonlyMembers.ts, 29, 9))
117+
>a : Symbol(a, Decl(readonlyMembers.ts, 34, 9))
100118

101119
get b() { return 1 },
102-
>b : Symbol(b, Decl(readonlyMembers.ts, 30, 25), Decl(readonlyMembers.ts, 31, 25))
120+
>b : Symbol(b, Decl(readonlyMembers.ts, 35, 25), Decl(readonlyMembers.ts, 36, 25))
103121

104122
set b(value) { }
105-
>b : Symbol(b, Decl(readonlyMembers.ts, 30, 25), Decl(readonlyMembers.ts, 31, 25))
106-
>value : Symbol(value, Decl(readonlyMembers.ts, 32, 10))
123+
>b : Symbol(b, Decl(readonlyMembers.ts, 35, 25), Decl(readonlyMembers.ts, 36, 25))
124+
>value : Symbol(value, Decl(readonlyMembers.ts, 37, 10))
107125

108126
};
109127
o.a = 1; // Error
110-
>o.a : Symbol(a, Decl(readonlyMembers.ts, 29, 9))
111-
>o : Symbol(o, Decl(readonlyMembers.ts, 29, 3))
112-
>a : Symbol(a, Decl(readonlyMembers.ts, 29, 9))
128+
>o.a : Symbol(a, Decl(readonlyMembers.ts, 34, 9))
129+
>o : Symbol(o, Decl(readonlyMembers.ts, 34, 3))
130+
>a : Symbol(a, Decl(readonlyMembers.ts, 34, 9))
113131

114132
o.b = 1;
115-
>o.b : Symbol(b, Decl(readonlyMembers.ts, 30, 25), Decl(readonlyMembers.ts, 31, 25))
116-
>o : Symbol(o, Decl(readonlyMembers.ts, 29, 3))
117-
>b : Symbol(b, Decl(readonlyMembers.ts, 30, 25), Decl(readonlyMembers.ts, 31, 25))
133+
>o.b : Symbol(b, Decl(readonlyMembers.ts, 35, 25), Decl(readonlyMembers.ts, 36, 25))
134+
>o : Symbol(o, Decl(readonlyMembers.ts, 34, 3))
135+
>b : Symbol(b, Decl(readonlyMembers.ts, 35, 25), Decl(readonlyMembers.ts, 36, 25))
118136

119137
var p: { readonly a: number, b: number } = { a: 1, b: 1 };
120-
>p : Symbol(p, Decl(readonlyMembers.ts, 37, 3))
121-
>a : Symbol(a, Decl(readonlyMembers.ts, 37, 8))
122-
>b : Symbol(b, Decl(readonlyMembers.ts, 37, 28))
123-
>a : Symbol(a, Decl(readonlyMembers.ts, 37, 44))
124-
>b : Symbol(b, Decl(readonlyMembers.ts, 37, 50))
138+
>p : Symbol(p, Decl(readonlyMembers.ts, 42, 3))
139+
>a : Symbol(a, Decl(readonlyMembers.ts, 42, 8))
140+
>b : Symbol(b, Decl(readonlyMembers.ts, 42, 28))
141+
>a : Symbol(a, Decl(readonlyMembers.ts, 42, 44))
142+
>b : Symbol(b, Decl(readonlyMembers.ts, 42, 50))
125143

126144
p.a = 1; // Error
127-
>p.a : Symbol(a, Decl(readonlyMembers.ts, 37, 8))
128-
>p : Symbol(p, Decl(readonlyMembers.ts, 37, 3))
129-
>a : Symbol(a, Decl(readonlyMembers.ts, 37, 8))
145+
>p.a : Symbol(a, Decl(readonlyMembers.ts, 42, 8))
146+
>p : Symbol(p, Decl(readonlyMembers.ts, 42, 3))
147+
>a : Symbol(a, Decl(readonlyMembers.ts, 42, 8))
130148

131149
p.b = 1;
132-
>p.b : Symbol(b, Decl(readonlyMembers.ts, 37, 28))
133-
>p : Symbol(p, Decl(readonlyMembers.ts, 37, 3))
134-
>b : Symbol(b, Decl(readonlyMembers.ts, 37, 28))
150+
>p.b : Symbol(b, Decl(readonlyMembers.ts, 42, 28))
151+
>p : Symbol(p, Decl(readonlyMembers.ts, 42, 3))
152+
>b : Symbol(b, Decl(readonlyMembers.ts, 42, 28))
135153

136154
var q: { a: number, b: number } = p;
137-
>q : Symbol(q, Decl(readonlyMembers.ts, 40, 3))
138-
>a : Symbol(a, Decl(readonlyMembers.ts, 40, 8))
139-
>b : Symbol(b, Decl(readonlyMembers.ts, 40, 19))
140-
>p : Symbol(p, Decl(readonlyMembers.ts, 37, 3))
155+
>q : Symbol(q, Decl(readonlyMembers.ts, 45, 3))
156+
>a : Symbol(a, Decl(readonlyMembers.ts, 45, 8))
157+
>b : Symbol(b, Decl(readonlyMembers.ts, 45, 19))
158+
>p : Symbol(p, Decl(readonlyMembers.ts, 42, 3))
141159

142160
q.a = 1;
143-
>q.a : Symbol(a, Decl(readonlyMembers.ts, 40, 8))
144-
>q : Symbol(q, Decl(readonlyMembers.ts, 40, 3))
145-
>a : Symbol(a, Decl(readonlyMembers.ts, 40, 8))
161+
>q.a : Symbol(a, Decl(readonlyMembers.ts, 45, 8))
162+
>q : Symbol(q, Decl(readonlyMembers.ts, 45, 3))
163+
>a : Symbol(a, Decl(readonlyMembers.ts, 45, 8))
146164

147165
q.b = 1;
148-
>q.b : Symbol(b, Decl(readonlyMembers.ts, 40, 19))
149-
>q : Symbol(q, Decl(readonlyMembers.ts, 40, 3))
150-
>b : Symbol(b, Decl(readonlyMembers.ts, 40, 19))
166+
>q.b : Symbol(b, Decl(readonlyMembers.ts, 45, 19))
167+
>q : Symbol(q, Decl(readonlyMembers.ts, 45, 3))
168+
>b : Symbol(b, Decl(readonlyMembers.ts, 45, 19))
151169

152170
enum E {
153-
>E : Symbol(E, Decl(readonlyMembers.ts, 42, 8))
171+
>E : Symbol(E, Decl(readonlyMembers.ts, 47, 8))
154172

155173
A, B, C
156-
>A : Symbol(E.A, Decl(readonlyMembers.ts, 44, 8))
157-
>B : Symbol(E.B, Decl(readonlyMembers.ts, 45, 6))
158-
>C : Symbol(E.C, Decl(readonlyMembers.ts, 45, 9))
174+
>A : Symbol(E.A, Decl(readonlyMembers.ts, 49, 8))
175+
>B : Symbol(E.B, Decl(readonlyMembers.ts, 50, 6))
176+
>C : Symbol(E.C, Decl(readonlyMembers.ts, 50, 9))
159177
}
160178
E.A = 1; // Error
161-
>E.A : Symbol(E.A, Decl(readonlyMembers.ts, 44, 8))
162-
>E : Symbol(E, Decl(readonlyMembers.ts, 42, 8))
163-
>A : Symbol(E.A, Decl(readonlyMembers.ts, 44, 8))
179+
>E.A : Symbol(E.A, Decl(readonlyMembers.ts, 49, 8))
180+
>E : Symbol(E, Decl(readonlyMembers.ts, 47, 8))
181+
>A : Symbol(E.A, Decl(readonlyMembers.ts, 49, 8))
164182

165183
namespace N {
166-
>N : Symbol(N, Decl(readonlyMembers.ts, 47, 8))
184+
>N : Symbol(N, Decl(readonlyMembers.ts, 52, 8))
167185

168186
export const a = 1;
169-
>a : Symbol(a, Decl(readonlyMembers.ts, 50, 16))
187+
>a : Symbol(a, Decl(readonlyMembers.ts, 55, 16))
170188

171189
export let b = 1;
172-
>b : Symbol(b, Decl(readonlyMembers.ts, 51, 14))
190+
>b : Symbol(b, Decl(readonlyMembers.ts, 56, 14))
173191

174192
export var c = 1;
175-
>c : Symbol(c, Decl(readonlyMembers.ts, 52, 14))
193+
>c : Symbol(c, Decl(readonlyMembers.ts, 57, 14))
176194
}
177195
N.a = 1; // Error
178-
>N.a : Symbol(N.a, Decl(readonlyMembers.ts, 50, 16))
179-
>N : Symbol(N, Decl(readonlyMembers.ts, 47, 8))
180-
>a : Symbol(N.a, Decl(readonlyMembers.ts, 50, 16))
196+
>N.a : Symbol(N.a, Decl(readonlyMembers.ts, 55, 16))
197+
>N : Symbol(N, Decl(readonlyMembers.ts, 52, 8))
198+
>a : Symbol(N.a, Decl(readonlyMembers.ts, 55, 16))
181199

182200
N.b = 1;
183-
>N.b : Symbol(N.b, Decl(readonlyMembers.ts, 51, 14))
184-
>N : Symbol(N, Decl(readonlyMembers.ts, 47, 8))
185-
>b : Symbol(N.b, Decl(readonlyMembers.ts, 51, 14))
201+
>N.b : Symbol(N.b, Decl(readonlyMembers.ts, 56, 14))
202+
>N : Symbol(N, Decl(readonlyMembers.ts, 52, 8))
203+
>b : Symbol(N.b, Decl(readonlyMembers.ts, 56, 14))
186204

187205
N.c = 1;
188-
>N.c : Symbol(N.c, Decl(readonlyMembers.ts, 52, 14))
189-
>N : Symbol(N, Decl(readonlyMembers.ts, 47, 8))
190-
>c : Symbol(N.c, Decl(readonlyMembers.ts, 52, 14))
206+
>N.c : Symbol(N.c, Decl(readonlyMembers.ts, 57, 14))
207+
>N : Symbol(N, Decl(readonlyMembers.ts, 52, 8))
208+
>c : Symbol(N.c, Decl(readonlyMembers.ts, 57, 14))
191209

192210
let xx: { readonly [x: string]: string };
193-
>xx : Symbol(xx, Decl(readonlyMembers.ts, 58, 3))
194-
>x : Symbol(x, Decl(readonlyMembers.ts, 58, 20))
211+
>xx : Symbol(xx, Decl(readonlyMembers.ts, 63, 3))
212+
>x : Symbol(x, Decl(readonlyMembers.ts, 63, 20))
195213

196214
let s = xx["foo"];
197-
>s : Symbol(s, Decl(readonlyMembers.ts, 59, 3))
198-
>xx : Symbol(xx, Decl(readonlyMembers.ts, 58, 3))
215+
>s : Symbol(s, Decl(readonlyMembers.ts, 64, 3))
216+
>xx : Symbol(xx, Decl(readonlyMembers.ts, 63, 3))
199217

200218
xx["foo"] = "abc"; // Error
201-
>xx : Symbol(xx, Decl(readonlyMembers.ts, 58, 3))
219+
>xx : Symbol(xx, Decl(readonlyMembers.ts, 63, 3))
202220

203221
let yy: { readonly [x: number]: string, [x: string]: string };
204-
>yy : Symbol(yy, Decl(readonlyMembers.ts, 62, 3))
205-
>x : Symbol(x, Decl(readonlyMembers.ts, 62, 20))
206-
>x : Symbol(x, Decl(readonlyMembers.ts, 62, 41))
222+
>yy : Symbol(yy, Decl(readonlyMembers.ts, 67, 3))
223+
>x : Symbol(x, Decl(readonlyMembers.ts, 67, 20))
224+
>x : Symbol(x, Decl(readonlyMembers.ts, 67, 41))
207225

208226
yy[1] = "abc"; // Error
209-
>yy : Symbol(yy, Decl(readonlyMembers.ts, 62, 3))
227+
>yy : Symbol(yy, Decl(readonlyMembers.ts, 67, 3))
210228

211229
yy["foo"] = "abc";
212-
>yy : Symbol(yy, Decl(readonlyMembers.ts, 62, 3))
230+
>yy : Symbol(yy, Decl(readonlyMembers.ts, 67, 3))
213231

tests/baselines/reference/readonlyMembers.types

Lines changed: 47 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,53 @@ class C {
142142
> : ^^^
143143
>1 : 1
144144
> : ^
145-
}
145+
146+
};
147+
(() => {
148+
>(() => { this.a = 1; // Ok this.b = 1; // Ok this.c = 1; // Error })() : void
149+
> : ^^^^
150+
>(() => { this.a = 1; // Ok this.b = 1; // Ok this.c = 1; // Error }) : () => void
151+
> : ^^^^^^^^^^
152+
>() => { this.a = 1; // Ok this.b = 1; // Ok this.c = 1; // Error } : () => void
153+
> : ^^^^^^^^^^
154+
155+
this.a = 1; // Ok
156+
>this.a = 1 : 1
157+
> : ^
158+
>this.a : number
159+
> : ^^^^^^
160+
>this : this
161+
> : ^^^^
162+
>a : number
163+
> : ^^^^^^
164+
>1 : 1
165+
> : ^
166+
167+
this.b = 1; // Ok
168+
>this.b = 1 : 1
169+
> : ^
170+
>this.b : 1
171+
> : ^
172+
>this : this
173+
> : ^^^^
174+
>b : 1
175+
> : ^
176+
>1 : 1
177+
> : ^
178+
179+
this.c = 1; // Error
180+
>this.c = 1 : 1
181+
> : ^
182+
>this.c : any
183+
> : ^^^
184+
>this : this
185+
> : ^^^^
186+
>c : any
187+
> : ^^^
188+
>1 : 1
189+
> : ^
190+
191+
})();
146192
}
147193
foo() {
148194
>foo : () => void

tests/cases/compiler/readonlyMembers.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,12 @@ class C {
2020
this.a = 1; // Error
2121
this.b = 1; // Error
2222
this.c = 1; // Error
23-
}
23+
};
24+
(() => {
25+
this.a = 1; // Ok
26+
this.b = 1; // Ok
27+
this.c = 1; // Error
28+
})();
2429
}
2530
foo() {
2631
this.a = 1; // Error

0 commit comments

Comments
 (0)