Fixed symbol lookup for binding expando properties in blocks (#56552)

This commit is contained in:
Mateusz Burzyński
2023-11-29 22:06:34 +01:00
committed by GitHub
parent 697025d0c0
commit e5513254a3
5 changed files with 202 additions and 2 deletions

View File

@@ -3309,7 +3309,7 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void {
function bindSpecialPropertyAssignment(node: BindablePropertyAssignmentExpression) {
// Class declarations in Typescript do not allow property declarations
const parentSymbol = lookupSymbolForPropertyAccess(node.left.expression, container) || lookupSymbolForPropertyAccess(node.left.expression, blockScopeContainer);
const parentSymbol = lookupSymbolForPropertyAccess(node.left.expression, blockScopeContainer) || lookupSymbolForPropertyAccess(node.left.expression, container);
if (!isInJSFile(node) && !isFunctionSymbol(parentSymbol)) {
return;
}
@@ -3428,7 +3428,7 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void {
}
function bindPropertyAssignment(name: BindableStaticNameExpression, propertyAccess: BindableStaticAccessExpression, isPrototypeProperty: boolean, containerIsClass: boolean) {
let namespaceSymbol = lookupSymbolForPropertyAccess(name, container) || lookupSymbolForPropertyAccess(name, blockScopeContainer);
let namespaceSymbol = lookupSymbolForPropertyAccess(name, blockScopeContainer) || lookupSymbolForPropertyAccess(name, container);
const isToplevel = isTopLevelNamespaceAssignment(propertyAccess);
namespaceSymbol = bindPotentiallyMissingNamespaces(namespaceSymbol, propertyAccess.expression, isToplevel, isPrototypeProperty, containerIsClass);
bindPotentiallyNewExpandoMemberToNamespace(propertyAccess, namespaceSymbol, isPrototypeProperty);

View File

@@ -0,0 +1,51 @@
//// [tests/cases/compiler/expandoFunctionBlockShadowing.ts] ////
//// [expandoFunctionBlockShadowing.ts]
// https://github.com/microsoft/TypeScript/issues/56538
export function X() {}
if (Math.random()) {
const X: { test?: any } = {};
X.test = 1;
}
export function Y() {}
Y.test = "foo";
const aliasTopY = Y;
if (Math.random()) {
const Y = function Y() {}
Y.test = 42;
const topYcheck: { (): void; test: string } = aliasTopY;
const blockYcheck: { (): void; test: number } = Y;
}
//// [expandoFunctionBlockShadowing.js]
"use strict";
// https://github.com/microsoft/TypeScript/issues/56538
Object.defineProperty(exports, "__esModule", { value: true });
exports.Y = exports.X = void 0;
function X() { }
exports.X = X;
if (Math.random()) {
var X_1 = {};
X_1.test = 1;
}
function Y() { }
exports.Y = Y;
Y.test = "foo";
var aliasTopY = Y;
if (Math.random()) {
var Y_1 = function Y() { };
Y_1.test = 42;
var topYcheck = aliasTopY;
var blockYcheck = Y_1;
}
//// [expandoFunctionBlockShadowing.d.ts]
export declare function X(): void;
export declare function Y(): void;
export declare namespace Y {
var test: string;
}

View File

@@ -0,0 +1,59 @@
//// [tests/cases/compiler/expandoFunctionBlockShadowing.ts] ////
=== expandoFunctionBlockShadowing.ts ===
// https://github.com/microsoft/TypeScript/issues/56538
export function X() {}
>X : Symbol(X, Decl(expandoFunctionBlockShadowing.ts, 0, 0))
if (Math.random()) {
>Math.random : Symbol(Math.random, Decl(lib.es5.d.ts, --, --))
>Math : Symbol(Math, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
>random : Symbol(Math.random, Decl(lib.es5.d.ts, --, --))
const X: { test?: any } = {};
>X : Symbol(X, Decl(expandoFunctionBlockShadowing.ts, 4, 7))
>test : Symbol(test, Decl(expandoFunctionBlockShadowing.ts, 4, 12))
X.test = 1;
>X.test : Symbol(test, Decl(expandoFunctionBlockShadowing.ts, 4, 12))
>X : Symbol(X, Decl(expandoFunctionBlockShadowing.ts, 4, 7))
>test : Symbol(test, Decl(expandoFunctionBlockShadowing.ts, 4, 12))
}
export function Y() {}
>Y : Symbol(Y, Decl(expandoFunctionBlockShadowing.ts, 6, 1), Decl(expandoFunctionBlockShadowing.ts, 8, 22))
Y.test = "foo";
>Y.test : Symbol(Y.test, Decl(expandoFunctionBlockShadowing.ts, 8, 22))
>Y : Symbol(Y, Decl(expandoFunctionBlockShadowing.ts, 6, 1), Decl(expandoFunctionBlockShadowing.ts, 8, 22))
>test : Symbol(Y.test, Decl(expandoFunctionBlockShadowing.ts, 8, 22))
const aliasTopY = Y;
>aliasTopY : Symbol(aliasTopY, Decl(expandoFunctionBlockShadowing.ts, 10, 5))
>Y : Symbol(Y, Decl(expandoFunctionBlockShadowing.ts, 6, 1), Decl(expandoFunctionBlockShadowing.ts, 8, 22))
if (Math.random()) {
>Math.random : Symbol(Math.random, Decl(lib.es5.d.ts, --, --))
>Math : Symbol(Math, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
>random : Symbol(Math.random, Decl(lib.es5.d.ts, --, --))
const Y = function Y() {}
>Y : Symbol(Y, Decl(expandoFunctionBlockShadowing.ts, 12, 7))
>Y : Symbol(Y, Decl(expandoFunctionBlockShadowing.ts, 12, 11))
Y.test = 42;
>Y.test : Symbol(Y.test, Decl(expandoFunctionBlockShadowing.ts, 12, 27))
>Y : Symbol(Y, Decl(expandoFunctionBlockShadowing.ts, 12, 7))
>test : Symbol(Y.test, Decl(expandoFunctionBlockShadowing.ts, 12, 27))
const topYcheck: { (): void; test: string } = aliasTopY;
>topYcheck : Symbol(topYcheck, Decl(expandoFunctionBlockShadowing.ts, 15, 7))
>test : Symbol(test, Decl(expandoFunctionBlockShadowing.ts, 15, 30))
>aliasTopY : Symbol(aliasTopY, Decl(expandoFunctionBlockShadowing.ts, 10, 5))
const blockYcheck: { (): void; test: number } = Y;
>blockYcheck : Symbol(blockYcheck, Decl(expandoFunctionBlockShadowing.ts, 16, 7))
>test : Symbol(test, Decl(expandoFunctionBlockShadowing.ts, 16, 32))
>Y : Symbol(Y, Decl(expandoFunctionBlockShadowing.ts, 12, 7))
}

View File

@@ -0,0 +1,69 @@
//// [tests/cases/compiler/expandoFunctionBlockShadowing.ts] ////
=== expandoFunctionBlockShadowing.ts ===
// https://github.com/microsoft/TypeScript/issues/56538
export function X() {}
>X : () => void
if (Math.random()) {
>Math.random() : number
>Math.random : () => number
>Math : Math
>random : () => number
const X: { test?: any } = {};
>X : { test?: any; }
>test : any
>{} : {}
X.test = 1;
>X.test = 1 : 1
>X.test : any
>X : { test?: any; }
>test : any
>1 : 1
}
export function Y() {}
>Y : typeof Y
Y.test = "foo";
>Y.test = "foo" : "foo"
>Y.test : string
>Y : typeof Y
>test : string
>"foo" : "foo"
const aliasTopY = Y;
>aliasTopY : typeof Y
>Y : typeof Y
if (Math.random()) {
>Math.random() : number
>Math.random : () => number
>Math : Math
>random : () => number
const Y = function Y() {}
>Y : { (): void; test: number; }
>function Y() {} : { (): void; test: number; }
>Y : { (): void; test: number; }
Y.test = 42;
>Y.test = 42 : 42
>Y.test : number
>Y : { (): void; test: number; }
>test : number
>42 : 42
const topYcheck: { (): void; test: string } = aliasTopY;
>topYcheck : { (): void; test: string; }
>test : string
>aliasTopY : typeof import("expandoFunctionBlockShadowing").Y
const blockYcheck: { (): void; test: number } = Y;
>blockYcheck : { (): void; test: number; }
>test : number
>Y : { (): void; test: number; }
}

View File

@@ -0,0 +1,21 @@
// @strict: true
// @declaration: true
// https://github.com/microsoft/TypeScript/issues/56538
export function X() {}
if (Math.random()) {
const X: { test?: any } = {};
X.test = 1;
}
export function Y() {}
Y.test = "foo";
const aliasTopY = Y;
if (Math.random()) {
const Y = function Y() {}
Y.test = 42;
const topYcheck: { (): void; test: string } = aliasTopY;
const blockYcheck: { (): void; test: number } = Y;
}