Skip to content

Commit 5128e06

Browse files
authored
Fixed expando functions with symbol-only properties (#54726)
1 parent 2623fe7 commit 5128e06

9 files changed

+285
-12
lines changed

src/compiler/checker.ts

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -13072,19 +13072,16 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
1307213072
return;
1307313073
}
1307413074
// Combinations of function, class, enum and module
13075-
let members = emptySymbols;
13075+
let members = getExportsOfSymbol(symbol);
1307613076
let indexInfos: IndexInfo[] | undefined;
13077-
if (symbol.exports) {
13078-
members = getExportsOfSymbol(symbol);
13079-
if (symbol === globalThisSymbol) {
13080-
const varsOnly = new Map<__String, Symbol>();
13081-
members.forEach(p => {
13082-
if (!(p.flags & SymbolFlags.BlockScoped) && !(p.flags & SymbolFlags.ValueModule && p.declarations?.length && every(p.declarations, isAmbientModule))) {
13083-
varsOnly.set(p.escapedName, p);
13084-
}
13085-
});
13086-
members = varsOnly;
13087-
}
13077+
if (symbol === globalThisSymbol) {
13078+
const varsOnly = new Map<__String, Symbol>();
13079+
members.forEach(p => {
13080+
if (!(p.flags & SymbolFlags.BlockScoped) && !(p.flags & SymbolFlags.ValueModule && p.declarations?.length && every(p.declarations, isAmbientModule))) {
13081+
varsOnly.set(p.escapedName, p);
13082+
}
13083+
});
13084+
members = varsOnly;
1308813085
}
1308913086
let baseConstructorIndexInfo: IndexInfo | undefined;
1309013087
setStructuredTypeMembers(type, members, emptyArray, emptyArray, emptyArray);
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
//// [tests/cases/compiler/expandoFunctionSymbolProperty.ts] ////
2+
3+
//// [expandoFunctionSymbolProperty.ts]
4+
// repro from https://github.com/microsoft/TypeScript/issues/54220
5+
6+
const symb = Symbol();
7+
8+
interface TestSymb {
9+
(): void;
10+
readonly [symb]: boolean;
11+
}
12+
13+
export function test(): TestSymb {
14+
function inner() {}
15+
inner[symb] = true;
16+
return inner;
17+
}
18+
19+
20+
//// [expandoFunctionSymbolProperty.js]
21+
// repro from https://github.com/microsoft/TypeScript/issues/54220
22+
const symb = Symbol();
23+
export function test() {
24+
function inner() { }
25+
inner[symb] = true;
26+
return inner;
27+
}
28+
29+
30+
//// [expandoFunctionSymbolProperty.d.ts]
31+
declare const symb: unique symbol;
32+
interface TestSymb {
33+
(): void;
34+
readonly [symb]: boolean;
35+
}
36+
export declare function test(): TestSymb;
37+
export {};
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
//// [tests/cases/compiler/expandoFunctionSymbolProperty.ts] ////
2+
3+
=== expandoFunctionSymbolProperty.ts ===
4+
// repro from https://github.com/microsoft/TypeScript/issues/54220
5+
6+
const symb = Symbol();
7+
>symb : Symbol(symb, Decl(expandoFunctionSymbolProperty.ts, 2, 5))
8+
>Symbol : Symbol(Symbol, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2019.symbol.d.ts, --, --))
9+
10+
interface TestSymb {
11+
>TestSymb : Symbol(TestSymb, Decl(expandoFunctionSymbolProperty.ts, 2, 22))
12+
13+
(): void;
14+
readonly [symb]: boolean;
15+
>[symb] : Symbol(TestSymb[symb], Decl(expandoFunctionSymbolProperty.ts, 5, 11))
16+
>symb : Symbol(symb, Decl(expandoFunctionSymbolProperty.ts, 2, 5))
17+
}
18+
19+
export function test(): TestSymb {
20+
>test : Symbol(test, Decl(expandoFunctionSymbolProperty.ts, 7, 1))
21+
>TestSymb : Symbol(TestSymb, Decl(expandoFunctionSymbolProperty.ts, 2, 22))
22+
23+
function inner() {}
24+
>inner : Symbol(inner, Decl(expandoFunctionSymbolProperty.ts, 9, 34))
25+
26+
inner[symb] = true;
27+
>inner : Symbol(inner, Decl(expandoFunctionSymbolProperty.ts, 9, 34))
28+
>symb : Symbol(symb, Decl(expandoFunctionSymbolProperty.ts, 2, 5))
29+
30+
return inner;
31+
>inner : Symbol(inner, Decl(expandoFunctionSymbolProperty.ts, 9, 34))
32+
}
33+
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
//// [tests/cases/compiler/expandoFunctionSymbolProperty.ts] ////
2+
3+
=== expandoFunctionSymbolProperty.ts ===
4+
// repro from https://github.com/microsoft/TypeScript/issues/54220
5+
6+
const symb = Symbol();
7+
>symb : unique symbol
8+
>Symbol() : unique symbol
9+
>Symbol : SymbolConstructor
10+
11+
interface TestSymb {
12+
(): void;
13+
readonly [symb]: boolean;
14+
>[symb] : boolean
15+
>symb : unique symbol
16+
}
17+
18+
export function test(): TestSymb {
19+
>test : () => TestSymb
20+
21+
function inner() {}
22+
>inner : { (): void; [symb]: boolean; }
23+
24+
inner[symb] = true;
25+
>inner[symb] = true : true
26+
>inner[symb] : boolean
27+
>inner : { (): void; [symb]: boolean; }
28+
>symb : unique symbol
29+
>true : true
30+
31+
return inner;
32+
>inner : { (): void; [symb]: boolean; }
33+
}
34+
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
//// [tests/cases/compiler/expandoFunctionSymbolPropertyJs.ts] ////
2+
3+
//// [types.ts]
4+
export const symb = Symbol();
5+
6+
export interface TestSymb {
7+
(): void;
8+
readonly [symb]: boolean;
9+
}
10+
11+
//// [a.js]
12+
import { symb } from "./types";
13+
14+
/**
15+
* @returns {import("./types").TestSymb}
16+
*/
17+
export function test() {
18+
function inner() {}
19+
inner[symb] = true;
20+
return inner;
21+
}
22+
23+
//// [types.js]
24+
"use strict";
25+
Object.defineProperty(exports, "__esModule", { value: true });
26+
exports.symb = void 0;
27+
exports.symb = Symbol();
28+
//// [a.js]
29+
"use strict";
30+
Object.defineProperty(exports, "__esModule", { value: true });
31+
exports.test = void 0;
32+
var types_1 = require("./types");
33+
/**
34+
* @returns {import("./types").TestSymb}
35+
*/
36+
function test() {
37+
function inner() { }
38+
inner[types_1.symb] = true;
39+
return inner;
40+
}
41+
exports.test = test;
42+
43+
44+
//// [types.d.ts]
45+
export declare const symb: unique symbol;
46+
export interface TestSymb {
47+
(): void;
48+
readonly [symb]: boolean;
49+
}
50+
//// [a.d.ts]
51+
/**
52+
* @returns {import("./types").TestSymb}
53+
*/
54+
export function test(): import("./types").TestSymb;
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
//// [tests/cases/compiler/expandoFunctionSymbolPropertyJs.ts] ////
2+
3+
=== /types.ts ===
4+
export const symb = Symbol();
5+
>symb : Symbol(symb, Decl(types.ts, 0, 12))
6+
>Symbol : Symbol(Symbol, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2019.symbol.d.ts, --, --))
7+
8+
export interface TestSymb {
9+
>TestSymb : Symbol(TestSymb, Decl(types.ts, 0, 29))
10+
11+
(): void;
12+
readonly [symb]: boolean;
13+
>[symb] : Symbol(TestSymb[symb], Decl(types.ts, 3, 11))
14+
>symb : Symbol(symb, Decl(types.ts, 0, 12))
15+
}
16+
17+
=== /a.js ===
18+
import { symb } from "./types";
19+
>symb : Symbol(symb, Decl(a.js, 0, 8))
20+
21+
/**
22+
* @returns {import("./types").TestSymb}
23+
*/
24+
export function test() {
25+
>test : Symbol(test, Decl(a.js, 0, 31))
26+
27+
function inner() {}
28+
>inner : Symbol(inner, Decl(a.js, 5, 24))
29+
30+
inner[symb] = true;
31+
>inner : Symbol(inner, Decl(a.js, 5, 24))
32+
>symb : Symbol(symb, Decl(a.js, 0, 8))
33+
34+
return inner;
35+
>inner : Symbol(inner, Decl(a.js, 5, 24))
36+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
//// [tests/cases/compiler/expandoFunctionSymbolPropertyJs.ts] ////
2+
3+
=== /types.ts ===
4+
export const symb = Symbol();
5+
>symb : unique symbol
6+
>Symbol() : unique symbol
7+
>Symbol : SymbolConstructor
8+
9+
export interface TestSymb {
10+
(): void;
11+
readonly [symb]: boolean;
12+
>[symb] : boolean
13+
>symb : unique symbol
14+
}
15+
16+
=== /a.js ===
17+
import { symb } from "./types";
18+
>symb : unique symbol
19+
20+
/**
21+
* @returns {import("./types").TestSymb}
22+
*/
23+
export function test() {
24+
>test : () => import("./types").TestSymb
25+
26+
function inner() {}
27+
>inner : { (): void; [symb]: boolean; }
28+
29+
inner[symb] = true;
30+
>inner[symb] = true : true
31+
>inner[symb] : boolean
32+
>inner : { (): void; [symb]: boolean; }
33+
>symb : unique symbol
34+
>true : true
35+
36+
return inner;
37+
>inner : { (): void; [symb]: boolean; }
38+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// @strict: true
2+
// @target: esnext
3+
// @declaration: true
4+
5+
// repro from https://github.com/microsoft/TypeScript/issues/54220
6+
7+
const symb = Symbol();
8+
9+
interface TestSymb {
10+
(): void;
11+
readonly [symb]: boolean;
12+
}
13+
14+
export function test(): TestSymb {
15+
function inner() {}
16+
inner[symb] = true;
17+
return inner;
18+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// @strict: true
2+
// @lib: esnext
3+
// @allowJs: true
4+
// @checkJs: true
5+
// @declaration: true
6+
// @outDir: dist
7+
8+
// @filename: /types.ts
9+
export const symb = Symbol();
10+
11+
export interface TestSymb {
12+
(): void;
13+
readonly [symb]: boolean;
14+
}
15+
16+
// @filename: /a.js
17+
import { symb } from "./types";
18+
19+
/**
20+
* @returns {import("./types").TestSymb}
21+
*/
22+
export function test() {
23+
function inner() {}
24+
inner[symb] = true;
25+
return inner;
26+
}

0 commit comments

Comments
 (0)