Skip to content

Fixed expando functions with symbol-only properties #54726

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Jul 20, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 9 additions & 12 deletions src/compiler/checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13065,19 +13065,16 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
return;
}
// Combinations of function, class, enum and module
let members = emptySymbols;
let members = getExportsOfSymbol(symbol);
let indexInfos: IndexInfo[] | undefined;
if (symbol.exports) {
members = getExportsOfSymbol(symbol);
if (symbol === globalThisSymbol) {
const varsOnly = new Map<__String, Symbol>();
members.forEach(p => {
if (!(p.flags & SymbolFlags.BlockScoped) && !(p.flags & SymbolFlags.ValueModule && p.declarations?.length && every(p.declarations, isAmbientModule))) {
varsOnly.set(p.escapedName, p);
}
});
members = varsOnly;
}
if (symbol === globalThisSymbol) {
const varsOnly = new Map<__String, Symbol>();
members.forEach(p => {
if (!(p.flags & SymbolFlags.BlockScoped) && !(p.flags & SymbolFlags.ValueModule && p.declarations?.length && every(p.declarations, isAmbientModule))) {
varsOnly.set(p.escapedName, p);
}
});
members = varsOnly;
}
let baseConstructorIndexInfo: IndexInfo | undefined;
setStructuredTypeMembers(type, members, emptyArray, emptyArray, emptyArray);
Expand Down
37 changes: 37 additions & 0 deletions tests/baselines/reference/expandoFunctionSymbolProperty.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
//// [tests/cases/compiler/expandoFunctionSymbolProperty.ts] ////

//// [expandoFunctionSymbolProperty.ts]
// repro from https://github.com/microsoft/TypeScript/issues/54220

const symb = Symbol();

interface TestSymb {
(): void;
readonly [symb]: boolean;
}

export function test(): TestSymb {
function inner() {}
inner[symb] = true;
return inner;
}


//// [expandoFunctionSymbolProperty.js]
// repro from https://github.com/microsoft/TypeScript/issues/54220
const symb = Symbol();
export function test() {
function inner() { }
inner[symb] = true;
return inner;
}


//// [expandoFunctionSymbolProperty.d.ts]
declare const symb: unique symbol;
interface TestSymb {
(): void;
readonly [symb]: boolean;
}
export declare function test(): TestSymb;
export {};
33 changes: 33 additions & 0 deletions tests/baselines/reference/expandoFunctionSymbolProperty.symbols
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
//// [tests/cases/compiler/expandoFunctionSymbolProperty.ts] ////

=== expandoFunctionSymbolProperty.ts ===
// repro from https://github.com/microsoft/TypeScript/issues/54220

const symb = Symbol();
>symb : Symbol(symb, Decl(expandoFunctionSymbolProperty.ts, 2, 5))
>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, --, --))

interface TestSymb {
>TestSymb : Symbol(TestSymb, Decl(expandoFunctionSymbolProperty.ts, 2, 22))

(): void;
readonly [symb]: boolean;
>[symb] : Symbol(TestSymb[symb], Decl(expandoFunctionSymbolProperty.ts, 5, 11))
>symb : Symbol(symb, Decl(expandoFunctionSymbolProperty.ts, 2, 5))
}

export function test(): TestSymb {
>test : Symbol(test, Decl(expandoFunctionSymbolProperty.ts, 7, 1))
>TestSymb : Symbol(TestSymb, Decl(expandoFunctionSymbolProperty.ts, 2, 22))

function inner() {}
>inner : Symbol(inner, Decl(expandoFunctionSymbolProperty.ts, 9, 34))

inner[symb] = true;
>inner : Symbol(inner, Decl(expandoFunctionSymbolProperty.ts, 9, 34))
>symb : Symbol(symb, Decl(expandoFunctionSymbolProperty.ts, 2, 5))

return inner;
>inner : Symbol(inner, Decl(expandoFunctionSymbolProperty.ts, 9, 34))
}

34 changes: 34 additions & 0 deletions tests/baselines/reference/expandoFunctionSymbolProperty.types
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
//// [tests/cases/compiler/expandoFunctionSymbolProperty.ts] ////

=== expandoFunctionSymbolProperty.ts ===
// repro from https://github.com/microsoft/TypeScript/issues/54220

const symb = Symbol();
>symb : unique symbol
>Symbol() : unique symbol
>Symbol : SymbolConstructor

interface TestSymb {
(): void;
readonly [symb]: boolean;
>[symb] : boolean
>symb : unique symbol
}

export function test(): TestSymb {
>test : () => TestSymb

function inner() {}
>inner : { (): void; [symb]: boolean; }

inner[symb] = true;
>inner[symb] = true : true
>inner[symb] : boolean
>inner : { (): void; [symb]: boolean; }
>symb : unique symbol
>true : true

return inner;
>inner : { (): void; [symb]: boolean; }
}

54 changes: 54 additions & 0 deletions tests/baselines/reference/expandoFunctionSymbolPropertyJs.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
//// [tests/cases/compiler/expandoFunctionSymbolPropertyJs.ts] ////

//// [types.ts]
export const symb = Symbol();

export interface TestSymb {
(): void;
readonly [symb]: boolean;
}

//// [a.js]
import { symb } from "./types";

/**
* @returns {import("./types").TestSymb}
*/
export function test() {
function inner() {}
inner[symb] = true;
return inner;
}

//// [types.js]
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.symb = void 0;
exports.symb = Symbol();
//// [a.js]
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.test = void 0;
var types_1 = require("./types");
/**
* @returns {import("./types").TestSymb}
*/
function test() {
function inner() { }
inner[types_1.symb] = true;
return inner;
}
exports.test = test;


//// [types.d.ts]
export declare const symb: unique symbol;
export interface TestSymb {
(): void;
readonly [symb]: boolean;
}
//// [a.d.ts]
/**
* @returns {import("./types").TestSymb}
*/
export function test(): import("./types").TestSymb;
36 changes: 36 additions & 0 deletions tests/baselines/reference/expandoFunctionSymbolPropertyJs.symbols
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
//// [tests/cases/compiler/expandoFunctionSymbolPropertyJs.ts] ////

=== /types.ts ===
export const symb = Symbol();
>symb : Symbol(symb, Decl(types.ts, 0, 12))
>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, --, --))

export interface TestSymb {
>TestSymb : Symbol(TestSymb, Decl(types.ts, 0, 29))

(): void;
readonly [symb]: boolean;
>[symb] : Symbol(TestSymb[symb], Decl(types.ts, 3, 11))
>symb : Symbol(symb, Decl(types.ts, 0, 12))
}

=== /a.js ===
import { symb } from "./types";
>symb : Symbol(symb, Decl(a.js, 0, 8))

/**
* @returns {import("./types").TestSymb}
*/
export function test() {
>test : Symbol(test, Decl(a.js, 0, 31))

function inner() {}
>inner : Symbol(inner, Decl(a.js, 5, 24))

inner[symb] = true;
>inner : Symbol(inner, Decl(a.js, 5, 24))
>symb : Symbol(symb, Decl(a.js, 0, 8))

return inner;
>inner : Symbol(inner, Decl(a.js, 5, 24))
}
38 changes: 38 additions & 0 deletions tests/baselines/reference/expandoFunctionSymbolPropertyJs.types
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
//// [tests/cases/compiler/expandoFunctionSymbolPropertyJs.ts] ////

=== /types.ts ===
export const symb = Symbol();
>symb : unique symbol
>Symbol() : unique symbol
>Symbol : SymbolConstructor

export interface TestSymb {
(): void;
readonly [symb]: boolean;
>[symb] : boolean
>symb : unique symbol
}

=== /a.js ===
import { symb } from "./types";
>symb : unique symbol

/**
* @returns {import("./types").TestSymb}
*/
export function test() {
>test : () => import("./types").TestSymb

function inner() {}
>inner : { (): void; [symb]: boolean; }

inner[symb] = true;
>inner[symb] = true : true
>inner[symb] : boolean
>inner : { (): void; [symb]: boolean; }
>symb : unique symbol
>true : true

return inner;
>inner : { (): void; [symb]: boolean; }
}
18 changes: 18 additions & 0 deletions tests/cases/compiler/expandoFunctionSymbolProperty.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// @strict: true
// @target: esnext
// @declaration: true

// repro from https://github.com/microsoft/TypeScript/issues/54220

const symb = Symbol();

interface TestSymb {
(): void;
readonly [symb]: boolean;
}

export function test(): TestSymb {
function inner() {}
inner[symb] = true;
return inner;
}
26 changes: 26 additions & 0 deletions tests/cases/compiler/expandoFunctionSymbolPropertyJs.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// @strict: true
// @lib: esnext
// @allowJs: true
// @checkJs: true
// @declaration: true
// @outDir: dist

// @filename: /types.ts
export const symb = Symbol();

export interface TestSymb {
(): void;
readonly [symb]: boolean;
}

// @filename: /a.js
import { symb } from "./types";

/**
* @returns {import("./types").TestSymb}
*/
export function test() {
function inner() {}
inner[symb] = true;
return inner;
}