Skip to content

Commit e551325

Browse files
authored
Fixed symbol lookup for binding expando properties in blocks (#56552)
1 parent 697025d commit e551325

File tree

5 files changed

+202
-2
lines changed

5 files changed

+202
-2
lines changed

src/compiler/binder.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3309,7 +3309,7 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void {
33093309

33103310
function bindSpecialPropertyAssignment(node: BindablePropertyAssignmentExpression) {
33113311
// Class declarations in Typescript do not allow property declarations
3312-
const parentSymbol = lookupSymbolForPropertyAccess(node.left.expression, container) || lookupSymbolForPropertyAccess(node.left.expression, blockScopeContainer);
3312+
const parentSymbol = lookupSymbolForPropertyAccess(node.left.expression, blockScopeContainer) || lookupSymbolForPropertyAccess(node.left.expression, container);
33133313
if (!isInJSFile(node) && !isFunctionSymbol(parentSymbol)) {
33143314
return;
33153315
}
@@ -3428,7 +3428,7 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void {
34283428
}
34293429

34303430
function bindPropertyAssignment(name: BindableStaticNameExpression, propertyAccess: BindableStaticAccessExpression, isPrototypeProperty: boolean, containerIsClass: boolean) {
3431-
let namespaceSymbol = lookupSymbolForPropertyAccess(name, container) || lookupSymbolForPropertyAccess(name, blockScopeContainer);
3431+
let namespaceSymbol = lookupSymbolForPropertyAccess(name, blockScopeContainer) || lookupSymbolForPropertyAccess(name, container);
34323432
const isToplevel = isTopLevelNamespaceAssignment(propertyAccess);
34333433
namespaceSymbol = bindPotentiallyMissingNamespaces(namespaceSymbol, propertyAccess.expression, isToplevel, isPrototypeProperty, containerIsClass);
34343434
bindPotentiallyNewExpandoMemberToNamespace(propertyAccess, namespaceSymbol, isPrototypeProperty);
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
//// [tests/cases/compiler/expandoFunctionBlockShadowing.ts] ////
2+
3+
//// [expandoFunctionBlockShadowing.ts]
4+
// https://github.com/microsoft/TypeScript/issues/56538
5+
6+
export function X() {}
7+
if (Math.random()) {
8+
const X: { test?: any } = {};
9+
X.test = 1;
10+
}
11+
12+
export function Y() {}
13+
Y.test = "foo";
14+
const aliasTopY = Y;
15+
if (Math.random()) {
16+
const Y = function Y() {}
17+
Y.test = 42;
18+
19+
const topYcheck: { (): void; test: string } = aliasTopY;
20+
const blockYcheck: { (): void; test: number } = Y;
21+
}
22+
23+
//// [expandoFunctionBlockShadowing.js]
24+
"use strict";
25+
// https://github.com/microsoft/TypeScript/issues/56538
26+
Object.defineProperty(exports, "__esModule", { value: true });
27+
exports.Y = exports.X = void 0;
28+
function X() { }
29+
exports.X = X;
30+
if (Math.random()) {
31+
var X_1 = {};
32+
X_1.test = 1;
33+
}
34+
function Y() { }
35+
exports.Y = Y;
36+
Y.test = "foo";
37+
var aliasTopY = Y;
38+
if (Math.random()) {
39+
var Y_1 = function Y() { };
40+
Y_1.test = 42;
41+
var topYcheck = aliasTopY;
42+
var blockYcheck = Y_1;
43+
}
44+
45+
46+
//// [expandoFunctionBlockShadowing.d.ts]
47+
export declare function X(): void;
48+
export declare function Y(): void;
49+
export declare namespace Y {
50+
var test: string;
51+
}
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
//// [tests/cases/compiler/expandoFunctionBlockShadowing.ts] ////
2+
3+
=== expandoFunctionBlockShadowing.ts ===
4+
// https://github.com/microsoft/TypeScript/issues/56538
5+
6+
export function X() {}
7+
>X : Symbol(X, Decl(expandoFunctionBlockShadowing.ts, 0, 0))
8+
9+
if (Math.random()) {
10+
>Math.random : Symbol(Math.random, Decl(lib.es5.d.ts, --, --))
11+
>Math : Symbol(Math, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
12+
>random : Symbol(Math.random, Decl(lib.es5.d.ts, --, --))
13+
14+
const X: { test?: any } = {};
15+
>X : Symbol(X, Decl(expandoFunctionBlockShadowing.ts, 4, 7))
16+
>test : Symbol(test, Decl(expandoFunctionBlockShadowing.ts, 4, 12))
17+
18+
X.test = 1;
19+
>X.test : Symbol(test, Decl(expandoFunctionBlockShadowing.ts, 4, 12))
20+
>X : Symbol(X, Decl(expandoFunctionBlockShadowing.ts, 4, 7))
21+
>test : Symbol(test, Decl(expandoFunctionBlockShadowing.ts, 4, 12))
22+
}
23+
24+
export function Y() {}
25+
>Y : Symbol(Y, Decl(expandoFunctionBlockShadowing.ts, 6, 1), Decl(expandoFunctionBlockShadowing.ts, 8, 22))
26+
27+
Y.test = "foo";
28+
>Y.test : Symbol(Y.test, Decl(expandoFunctionBlockShadowing.ts, 8, 22))
29+
>Y : Symbol(Y, Decl(expandoFunctionBlockShadowing.ts, 6, 1), Decl(expandoFunctionBlockShadowing.ts, 8, 22))
30+
>test : Symbol(Y.test, Decl(expandoFunctionBlockShadowing.ts, 8, 22))
31+
32+
const aliasTopY = Y;
33+
>aliasTopY : Symbol(aliasTopY, Decl(expandoFunctionBlockShadowing.ts, 10, 5))
34+
>Y : Symbol(Y, Decl(expandoFunctionBlockShadowing.ts, 6, 1), Decl(expandoFunctionBlockShadowing.ts, 8, 22))
35+
36+
if (Math.random()) {
37+
>Math.random : Symbol(Math.random, Decl(lib.es5.d.ts, --, --))
38+
>Math : Symbol(Math, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
39+
>random : Symbol(Math.random, Decl(lib.es5.d.ts, --, --))
40+
41+
const Y = function Y() {}
42+
>Y : Symbol(Y, Decl(expandoFunctionBlockShadowing.ts, 12, 7))
43+
>Y : Symbol(Y, Decl(expandoFunctionBlockShadowing.ts, 12, 11))
44+
45+
Y.test = 42;
46+
>Y.test : Symbol(Y.test, Decl(expandoFunctionBlockShadowing.ts, 12, 27))
47+
>Y : Symbol(Y, Decl(expandoFunctionBlockShadowing.ts, 12, 7))
48+
>test : Symbol(Y.test, Decl(expandoFunctionBlockShadowing.ts, 12, 27))
49+
50+
const topYcheck: { (): void; test: string } = aliasTopY;
51+
>topYcheck : Symbol(topYcheck, Decl(expandoFunctionBlockShadowing.ts, 15, 7))
52+
>test : Symbol(test, Decl(expandoFunctionBlockShadowing.ts, 15, 30))
53+
>aliasTopY : Symbol(aliasTopY, Decl(expandoFunctionBlockShadowing.ts, 10, 5))
54+
55+
const blockYcheck: { (): void; test: number } = Y;
56+
>blockYcheck : Symbol(blockYcheck, Decl(expandoFunctionBlockShadowing.ts, 16, 7))
57+
>test : Symbol(test, Decl(expandoFunctionBlockShadowing.ts, 16, 32))
58+
>Y : Symbol(Y, Decl(expandoFunctionBlockShadowing.ts, 12, 7))
59+
}
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
//// [tests/cases/compiler/expandoFunctionBlockShadowing.ts] ////
2+
3+
=== expandoFunctionBlockShadowing.ts ===
4+
// https://github.com/microsoft/TypeScript/issues/56538
5+
6+
export function X() {}
7+
>X : () => void
8+
9+
if (Math.random()) {
10+
>Math.random() : number
11+
>Math.random : () => number
12+
>Math : Math
13+
>random : () => number
14+
15+
const X: { test?: any } = {};
16+
>X : { test?: any; }
17+
>test : any
18+
>{} : {}
19+
20+
X.test = 1;
21+
>X.test = 1 : 1
22+
>X.test : any
23+
>X : { test?: any; }
24+
>test : any
25+
>1 : 1
26+
}
27+
28+
export function Y() {}
29+
>Y : typeof Y
30+
31+
Y.test = "foo";
32+
>Y.test = "foo" : "foo"
33+
>Y.test : string
34+
>Y : typeof Y
35+
>test : string
36+
>"foo" : "foo"
37+
38+
const aliasTopY = Y;
39+
>aliasTopY : typeof Y
40+
>Y : typeof Y
41+
42+
if (Math.random()) {
43+
>Math.random() : number
44+
>Math.random : () => number
45+
>Math : Math
46+
>random : () => number
47+
48+
const Y = function Y() {}
49+
>Y : { (): void; test: number; }
50+
>function Y() {} : { (): void; test: number; }
51+
>Y : { (): void; test: number; }
52+
53+
Y.test = 42;
54+
>Y.test = 42 : 42
55+
>Y.test : number
56+
>Y : { (): void; test: number; }
57+
>test : number
58+
>42 : 42
59+
60+
const topYcheck: { (): void; test: string } = aliasTopY;
61+
>topYcheck : { (): void; test: string; }
62+
>test : string
63+
>aliasTopY : typeof import("expandoFunctionBlockShadowing").Y
64+
65+
const blockYcheck: { (): void; test: number } = Y;
66+
>blockYcheck : { (): void; test: number; }
67+
>test : number
68+
>Y : { (): void; test: number; }
69+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// @strict: true
2+
// @declaration: true
3+
4+
// https://github.com/microsoft/TypeScript/issues/56538
5+
6+
export function X() {}
7+
if (Math.random()) {
8+
const X: { test?: any } = {};
9+
X.test = 1;
10+
}
11+
12+
export function Y() {}
13+
Y.test = "foo";
14+
const aliasTopY = Y;
15+
if (Math.random()) {
16+
const Y = function Y() {}
17+
Y.test = 42;
18+
19+
const topYcheck: { (): void; test: string } = aliasTopY;
20+
const blockYcheck: { (): void; test: number } = Y;
21+
}

0 commit comments

Comments
 (0)