Skip to content

Commit 20a0ac5

Browse files
committed
Merge pull request #2476 from Microsoft/immutableBindings
Disallow assignments to imported exports
2 parents e5e5ad8 + 3a8df41 commit 20a0ac5

File tree

4 files changed

+347
-1
lines changed

4 files changed

+347
-1
lines changed

src/compiler/checker.ts

+23-1
Original file line numberDiff line numberDiff line change
@@ -7254,7 +7254,6 @@ module ts {
72547254
case SyntaxKind.ElementAccessExpression: {
72557255
let index = (<ElementAccessExpression>n).argumentExpression;
72567256
let symbol = findSymbol((<ElementAccessExpression>n).expression);
7257-
72587257
if (symbol && index && index.kind === SyntaxKind.StringLiteral) {
72597258
let name = (<LiteralExpression>index).text;
72607259
let prop = getPropertyOfType(getTypeOfSymbol(symbol), name);
@@ -7269,14 +7268,37 @@ module ts {
72697268
}
72707269
}
72717270

7271+
function isImportedNameFromExternalModule(n: Node): boolean {
7272+
switch (n.kind) {
7273+
case SyntaxKind.ElementAccessExpression:
7274+
case SyntaxKind.PropertyAccessExpression: {
7275+
// all bindings for external module should be immutable
7276+
// so attempt to use a.b or a[b] as lhs will always fail
7277+
// no matter what b is
7278+
let symbol = findSymbol((<PropertyAccessExpression | ElementAccessExpression>n).expression);
7279+
return symbol && symbol.flags & SymbolFlags.Alias && isExternalModuleSymbol(resolveAlias(symbol));
7280+
}
7281+
case SyntaxKind.ParenthesizedExpression:
7282+
return isImportedNameFromExternalModule((<ParenthesizedExpression>n).expression);
7283+
default:
7284+
return false;
7285+
}
7286+
}
7287+
72727288
if (!isReferenceOrErrorExpression(n)) {
72737289
error(n, invalidReferenceMessage);
72747290
return false;
72757291
}
7292+
72767293
if (isConstVariableReference(n)) {
72777294
error(n, constantVariableMessage);
72787295
return false;
72797296
}
7297+
7298+
if (isImportedNameFromExternalModule(n)) {
7299+
error(n, invalidReferenceMessage);
7300+
}
7301+
72807302
return true;
72817303
}
72827304

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
tests/cases/compiler/f2.ts(5,1): error TS2364: Invalid left-hand side of assignment expression.
2+
tests/cases/compiler/f2.ts(6,1): error TS2364: Invalid left-hand side of assignment expression.
3+
tests/cases/compiler/f2.ts(7,1): error TS2364: Invalid left-hand side of assignment expression.
4+
tests/cases/compiler/f2.ts(7,7): error TS2339: Property 'blah' does not exist on type 'typeof "tests/cases/compiler/f1"'.
5+
tests/cases/compiler/f2.ts(8,1): error TS2364: Invalid left-hand side of assignment expression.
6+
tests/cases/compiler/f2.ts(10,1): error TS2357: The operand of an increment or decrement operator must be a variable, property or indexer.
7+
tests/cases/compiler/f2.ts(11,1): error TS2357: The operand of an increment or decrement operator must be a variable, property or indexer.
8+
tests/cases/compiler/f2.ts(12,1): error TS2357: The operand of an increment or decrement operator must be a variable, property or indexer.
9+
tests/cases/compiler/f2.ts(13,1): error TS2357: The operand of an increment or decrement operator must be a variable, property or indexer.
10+
tests/cases/compiler/f2.ts(15,1): error TS2364: Invalid left-hand side of assignment expression.
11+
tests/cases/compiler/f2.ts(16,1): error TS2364: Invalid left-hand side of assignment expression.
12+
tests/cases/compiler/f2.ts(17,1): error TS2364: Invalid left-hand side of assignment expression.
13+
tests/cases/compiler/f2.ts(17,8): error TS2339: Property 'blah' does not exist on type 'typeof "tests/cases/compiler/f1"'.
14+
tests/cases/compiler/f2.ts(18,1): error TS2364: Invalid left-hand side of assignment expression.
15+
tests/cases/compiler/f2.ts(20,1): error TS2357: The operand of an increment or decrement operator must be a variable, property or indexer.
16+
tests/cases/compiler/f2.ts(21,1): error TS2357: The operand of an increment or decrement operator must be a variable, property or indexer.
17+
tests/cases/compiler/f2.ts(22,1): error TS2357: The operand of an increment or decrement operator must be a variable, property or indexer.
18+
tests/cases/compiler/f2.ts(23,1): error TS2357: The operand of an increment or decrement operator must be a variable, property or indexer.
19+
tests/cases/compiler/f2.ts(25,6): error TS2405: The left-hand side of a 'for...in' statement must be of type 'string' or 'any'.
20+
tests/cases/compiler/f2.ts(26,6): error TS2487: Invalid left-hand side in 'for...of' statement.
21+
tests/cases/compiler/f2.ts(27,6): error TS2405: The left-hand side of a 'for...in' statement must be of type 'string' or 'any'.
22+
tests/cases/compiler/f2.ts(28,6): error TS2487: Invalid left-hand side in 'for...of' statement.
23+
tests/cases/compiler/f2.ts(29,6): error TS2406: Invalid left-hand side in 'for...in' statement.
24+
tests/cases/compiler/f2.ts(29,12): error TS2339: Property 'blah' does not exist on type 'typeof "tests/cases/compiler/f1"'.
25+
tests/cases/compiler/f2.ts(30,6): error TS2487: Invalid left-hand side in 'for...of' statement.
26+
tests/cases/compiler/f2.ts(30,12): error TS2339: Property 'blah' does not exist on type 'typeof "tests/cases/compiler/f1"'.
27+
tests/cases/compiler/f2.ts(31,6): error TS2406: Invalid left-hand side in 'for...in' statement.
28+
tests/cases/compiler/f2.ts(32,6): error TS2487: Invalid left-hand side in 'for...of' statement.
29+
tests/cases/compiler/f2.ts(34,6): error TS2405: The left-hand side of a 'for...in' statement must be of type 'string' or 'any'.
30+
tests/cases/compiler/f2.ts(35,6): error TS2487: Invalid left-hand side in 'for...of' statement.
31+
tests/cases/compiler/f2.ts(36,6): error TS2405: The left-hand side of a 'for...in' statement must be of type 'string' or 'any'.
32+
tests/cases/compiler/f2.ts(37,6): error TS2487: Invalid left-hand side in 'for...of' statement.
33+
tests/cases/compiler/f2.ts(38,6): error TS2406: Invalid left-hand side in 'for...in' statement.
34+
tests/cases/compiler/f2.ts(38,13): error TS2339: Property 'blah' does not exist on type 'typeof "tests/cases/compiler/f1"'.
35+
tests/cases/compiler/f2.ts(39,6): error TS2487: Invalid left-hand side in 'for...of' statement.
36+
tests/cases/compiler/f2.ts(39,13): error TS2339: Property 'blah' does not exist on type 'typeof "tests/cases/compiler/f1"'.
37+
tests/cases/compiler/f2.ts(40,6): error TS2406: Invalid left-hand side in 'for...in' statement.
38+
tests/cases/compiler/f2.ts(41,6): error TS2487: Invalid left-hand side in 'for...of' statement.
39+
40+
41+
==== tests/cases/compiler/f1.ts (0 errors) ====
42+
export var x = 1;
43+
44+
==== tests/cases/compiler/f2.ts (38 errors) ====
45+
import * as stuff from 'f1';
46+
47+
var n = 'baz';
48+
49+
stuff.x = 0;
50+
~~~~~~~
51+
!!! error TS2364: Invalid left-hand side of assignment expression.
52+
stuff['x'] = 1;
53+
~~~~~~~~~~
54+
!!! error TS2364: Invalid left-hand side of assignment expression.
55+
stuff.blah = 2;
56+
~~~~~~~~~~
57+
!!! error TS2364: Invalid left-hand side of assignment expression.
58+
~~~~
59+
!!! error TS2339: Property 'blah' does not exist on type 'typeof "tests/cases/compiler/f1"'.
60+
stuff[n] = 3;
61+
~~~~~~~~
62+
!!! error TS2364: Invalid left-hand side of assignment expression.
63+
64+
stuff.x++;
65+
~~~~~~~
66+
!!! error TS2357: The operand of an increment or decrement operator must be a variable, property or indexer.
67+
stuff['x']++;
68+
~~~~~~~~~~
69+
!!! error TS2357: The operand of an increment or decrement operator must be a variable, property or indexer.
70+
stuff['blah']++;
71+
~~~~~~~~~~~~~
72+
!!! error TS2357: The operand of an increment or decrement operator must be a variable, property or indexer.
73+
stuff[n]++;
74+
~~~~~~~~
75+
!!! error TS2357: The operand of an increment or decrement operator must be a variable, property or indexer.
76+
77+
(stuff.x) = 0;
78+
~~~~~~~~~
79+
!!! error TS2364: Invalid left-hand side of assignment expression.
80+
(stuff['x']) = 1;
81+
~~~~~~~~~~~~
82+
!!! error TS2364: Invalid left-hand side of assignment expression.
83+
(stuff.blah) = 2;
84+
~~~~~~~~~~~~
85+
!!! error TS2364: Invalid left-hand side of assignment expression.
86+
~~~~
87+
!!! error TS2339: Property 'blah' does not exist on type 'typeof "tests/cases/compiler/f1"'.
88+
(stuff[n]) = 3;
89+
~~~~~~~~~~
90+
!!! error TS2364: Invalid left-hand side of assignment expression.
91+
92+
(stuff.x)++;
93+
~~~~~~~~~
94+
!!! error TS2357: The operand of an increment or decrement operator must be a variable, property or indexer.
95+
(stuff['x'])++;
96+
~~~~~~~~~~~~
97+
!!! error TS2357: The operand of an increment or decrement operator must be a variable, property or indexer.
98+
(stuff['blah'])++;
99+
~~~~~~~~~~~~~~~
100+
!!! error TS2357: The operand of an increment or decrement operator must be a variable, property or indexer.
101+
(stuff[n])++;
102+
~~~~~~~~~~
103+
!!! error TS2357: The operand of an increment or decrement operator must be a variable, property or indexer.
104+
105+
for (stuff.x in []) {}
106+
~~~~~~~
107+
!!! error TS2405: The left-hand side of a 'for...in' statement must be of type 'string' or 'any'.
108+
for (stuff.x of []) {}
109+
~~~~~~~
110+
!!! error TS2487: Invalid left-hand side in 'for...of' statement.
111+
for (stuff['x'] in []) {}
112+
~~~~~~~~~~
113+
!!! error TS2405: The left-hand side of a 'for...in' statement must be of type 'string' or 'any'.
114+
for (stuff['x'] of []) {}
115+
~~~~~~~~~~
116+
!!! error TS2487: Invalid left-hand side in 'for...of' statement.
117+
for (stuff.blah in []) {}
118+
~~~~~~~~~~
119+
!!! error TS2406: Invalid left-hand side in 'for...in' statement.
120+
~~~~
121+
!!! error TS2339: Property 'blah' does not exist on type 'typeof "tests/cases/compiler/f1"'.
122+
for (stuff.blah of []) {}
123+
~~~~~~~~~~
124+
!!! error TS2487: Invalid left-hand side in 'for...of' statement.
125+
~~~~
126+
!!! error TS2339: Property 'blah' does not exist on type 'typeof "tests/cases/compiler/f1"'.
127+
for (stuff[n] in []) {}
128+
~~~~~~~~
129+
!!! error TS2406: Invalid left-hand side in 'for...in' statement.
130+
for (stuff[n] of []) {}
131+
~~~~~~~~
132+
!!! error TS2487: Invalid left-hand side in 'for...of' statement.
133+
134+
for ((stuff.x) in []) {}
135+
~~~~~~~~~
136+
!!! error TS2405: The left-hand side of a 'for...in' statement must be of type 'string' or 'any'.
137+
for ((stuff.x) of []) {}
138+
~~~~~~~~~
139+
!!! error TS2487: Invalid left-hand side in 'for...of' statement.
140+
for ((stuff['x']) in []) {}
141+
~~~~~~~~~~~~
142+
!!! error TS2405: The left-hand side of a 'for...in' statement must be of type 'string' or 'any'.
143+
for ((stuff['x']) of []) {}
144+
~~~~~~~~~~~~
145+
!!! error TS2487: Invalid left-hand side in 'for...of' statement.
146+
for ((stuff.blah) in []) {}
147+
~~~~~~~~~~~~
148+
!!! error TS2406: Invalid left-hand side in 'for...in' statement.
149+
~~~~
150+
!!! error TS2339: Property 'blah' does not exist on type 'typeof "tests/cases/compiler/f1"'.
151+
for ((stuff.blah) of []) {}
152+
~~~~~~~~~~~~
153+
!!! error TS2487: Invalid left-hand side in 'for...of' statement.
154+
~~~~
155+
!!! error TS2339: Property 'blah' does not exist on type 'typeof "tests/cases/compiler/f1"'.
156+
for ((stuff[n]) in []) {}
157+
~~~~~~~~~~
158+
!!! error TS2406: Invalid left-hand side in 'for...in' statement.
159+
for ((stuff[n]) of []) {}
160+
~~~~~~~~~~
161+
!!! error TS2487: Invalid left-hand side in 'for...of' statement.
162+
163+
164+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
//// [tests/cases/compiler/externalModuleImmutableBindings.ts] ////
2+
3+
//// [f1.ts]
4+
export var x = 1;
5+
6+
//// [f2.ts]
7+
import * as stuff from 'f1';
8+
9+
var n = 'baz';
10+
11+
stuff.x = 0;
12+
stuff['x'] = 1;
13+
stuff.blah = 2;
14+
stuff[n] = 3;
15+
16+
stuff.x++;
17+
stuff['x']++;
18+
stuff['blah']++;
19+
stuff[n]++;
20+
21+
(stuff.x) = 0;
22+
(stuff['x']) = 1;
23+
(stuff.blah) = 2;
24+
(stuff[n]) = 3;
25+
26+
(stuff.x)++;
27+
(stuff['x'])++;
28+
(stuff['blah'])++;
29+
(stuff[n])++;
30+
31+
for (stuff.x in []) {}
32+
for (stuff.x of []) {}
33+
for (stuff['x'] in []) {}
34+
for (stuff['x'] of []) {}
35+
for (stuff.blah in []) {}
36+
for (stuff.blah of []) {}
37+
for (stuff[n] in []) {}
38+
for (stuff[n] of []) {}
39+
40+
for ((stuff.x) in []) {}
41+
for ((stuff.x) of []) {}
42+
for ((stuff['x']) in []) {}
43+
for ((stuff['x']) of []) {}
44+
for ((stuff.blah) in []) {}
45+
for ((stuff.blah) of []) {}
46+
for ((stuff[n]) in []) {}
47+
for ((stuff[n]) of []) {}
48+
49+
50+
51+
52+
//// [f1.js]
53+
exports.x = 1;
54+
//// [f2.js]
55+
var stuff = require('f1');
56+
var n = 'baz';
57+
stuff.x = 0;
58+
stuff['x'] = 1;
59+
stuff.blah = 2;
60+
stuff[n] = 3;
61+
stuff.x++;
62+
stuff['x']++;
63+
stuff['blah']++;
64+
stuff[n]++;
65+
(stuff.x) = 0;
66+
(stuff['x']) = 1;
67+
(stuff.blah) = 2;
68+
(stuff[n]) = 3;
69+
(stuff.x)++;
70+
(stuff['x'])++;
71+
(stuff['blah'])++;
72+
(stuff[n])++;
73+
for (stuff.x in []) {
74+
}
75+
for (var _i = 0, _a = []; _i < _a.length; _i++) {
76+
stuff.x = _a[_i];
77+
}
78+
for (stuff['x'] in []) {
79+
}
80+
for (var _b = 0, _c = []; _b < _c.length; _b++) {
81+
stuff['x'] = _c[_b];
82+
}
83+
for (stuff.blah in []) {
84+
}
85+
for (var _d = 0, _e = []; _d < _e.length; _d++) {
86+
stuff.blah = _e[_d];
87+
}
88+
for (stuff[n] in []) {
89+
}
90+
for (var _f = 0, _g = []; _f < _g.length; _f++) {
91+
stuff[n] = _g[_f];
92+
}
93+
for ((stuff.x) in []) {
94+
}
95+
for (var _h = 0, _j = []; _h < _j.length; _h++) {
96+
(stuff.x) = _j[_h];
97+
}
98+
for ((stuff['x']) in []) {
99+
}
100+
for (var _k = 0, _l = []; _k < _l.length; _k++) {
101+
(stuff['x']) = _l[_k];
102+
}
103+
for ((stuff.blah) in []) {
104+
}
105+
for (var _m = 0, _o = []; _m < _o.length; _m++) {
106+
(stuff.blah) = _o[_m];
107+
}
108+
for ((stuff[n]) in []) {
109+
}
110+
for (var _p = 0, _q = []; _p < _q.length; _p++) {
111+
(stuff[n]) = _q[_p];
112+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
// @module: commonjs
2+
// @Filename: f1.ts
3+
export var x = 1;
4+
5+
// @Filename: f2.ts
6+
import * as stuff from 'f1';
7+
8+
var n = 'baz';
9+
10+
stuff.x = 0;
11+
stuff['x'] = 1;
12+
stuff.blah = 2;
13+
stuff[n] = 3;
14+
15+
stuff.x++;
16+
stuff['x']++;
17+
stuff['blah']++;
18+
stuff[n]++;
19+
20+
(stuff.x) = 0;
21+
(stuff['x']) = 1;
22+
(stuff.blah) = 2;
23+
(stuff[n]) = 3;
24+
25+
(stuff.x)++;
26+
(stuff['x'])++;
27+
(stuff['blah'])++;
28+
(stuff[n])++;
29+
30+
for (stuff.x in []) {}
31+
for (stuff.x of []) {}
32+
for (stuff['x'] in []) {}
33+
for (stuff['x'] of []) {}
34+
for (stuff.blah in []) {}
35+
for (stuff.blah of []) {}
36+
for (stuff[n] in []) {}
37+
for (stuff[n] of []) {}
38+
39+
for ((stuff.x) in []) {}
40+
for ((stuff.x) of []) {}
41+
for ((stuff['x']) in []) {}
42+
for ((stuff['x']) of []) {}
43+
for ((stuff.blah) in []) {}
44+
for ((stuff.blah) of []) {}
45+
for ((stuff[n]) in []) {}
46+
for ((stuff[n]) of []) {}
47+
48+

0 commit comments

Comments
 (0)