From 3c676087158a98efc365e0c434b80242716f40f7 Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Tue, 16 Apr 2019 12:36:07 -0700 Subject: [PATCH] When interfaces are merged, always ensure that the parent symbol of the late bound member symbol is declared symbol containing the node. Ensure that resolvedMembers adds the late bound symbol even when its resolved sunce lateBoundMember may or may not be added to resolved members depending on when its checked Fixes #30891 --- src/compiler/checker.ts | 15 ++- ...s-merged-and-contains-late-bound-member.js | 100 ++++++++++++++++++ 2 files changed, 112 insertions(+), 3 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 0cb40d8541a..5c2745ab3e7 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -6607,12 +6607,11 @@ namespace ts { * unique symbol type which we can then use as the name of the member. This allows users * to define custom symbols that can be used in the members of an object type. * - * @param parent The containing symbol for the member. * @param earlySymbols The early-bound symbols of the parent. * @param lateSymbols The late-bound symbols of the parent. * @param decl The member to bind. */ - function lateBindMember(parent: Symbol, earlySymbols: SymbolTable | undefined, lateSymbols: SymbolTable, decl: LateBoundDeclaration) { + function lateBindMember(earlySymbols: SymbolTable | undefined, lateSymbols: SymbolTable, decl: LateBoundDeclaration) { Debug.assert(!!decl.symbol, "The member is expected to have a symbol."); const links = getNodeLinks(decl); if (!links.resolvedSymbol) { @@ -6643,6 +6642,7 @@ namespace ts { } lateSymbol.nameType = type; addDeclarationToLateBoundSymbol(lateSymbol, decl, symbolFlags); + const parent = getSymbolOfNode(decl.parent); if (lateSymbol.parent) { Debug.assert(lateSymbol.parent === parent, "Existing symbol parent should match new one"); } @@ -6652,6 +6652,15 @@ namespace ts { return links.resolvedSymbol = lateSymbol; } } + else { + const type = checkComputedPropertyName(decl.name); + if (isTypeUsableAsPropertyName(type)) { + const memberName = getPropertyNameFromType(type); + if (!lateSymbols.has(memberName)) { + lateSymbols.set(memberName, links.resolvedSymbol); + } + } + } return links.resolvedSymbol; } @@ -6675,7 +6684,7 @@ namespace ts { if (members) { for (const member of members) { if (isStatic === hasStaticModifier(member) && hasLateBindableName(member)) { - lateBindMember(symbol, earlySymbols, lateSymbols, member); + lateBindMember(earlySymbols, lateSymbols, member); } } } diff --git a/tests/baselines/reference/tsbuild/lateBoundSymbol/incremental-declaration-doesnt-change/interface-is-merged-and-contains-late-bound-member.js b/tests/baselines/reference/tsbuild/lateBoundSymbol/incremental-declaration-doesnt-change/interface-is-merged-and-contains-late-bound-member.js index 3e5da585c7c..89748694bbc 100644 --- a/tests/baselines/reference/tsbuild/lateBoundSymbol/incremental-declaration-doesnt-change/interface-is-merged-and-contains-late-bound-member.js +++ b/tests/baselines/reference/tsbuild/lateBoundSymbol/incremental-declaration-doesnt-change/interface-is-merged-and-contains-late-bound-member.js @@ -1,3 +1,9 @@ +//// [/src/src/main.js] +"use strict"; +exports.__esModule = true; +var sym = Symbol(); + + //// [/src/src/main.ts] import { HKT } from "./hkt"; @@ -11,3 +17,97 @@ declare module "./hkt" { type A = HKT[typeof sym]; +//// [/src/tsconfig.tsbuildinfo] +{ + "program": { + "fileInfos": { + "/lib/lib.es5.d.ts": { + "version": "/lib/lib.es5.d.ts", + "signature": "/lib/lib.es5.d.ts" + }, + "/lib/lib.es2015.d.ts": { + "version": "/lib/lib.es2015.d.ts", + "signature": "/lib/lib.es2015.d.ts" + }, + "/lib/lib.es2015.core.d.ts": { + "version": "/lib/lib.es2015.core.d.ts", + "signature": "/lib/lib.es2015.core.d.ts" + }, + "/lib/lib.es2015.collection.d.ts": { + "version": "/lib/lib.es2015.collection.d.ts", + "signature": "/lib/lib.es2015.collection.d.ts" + }, + "/lib/lib.es2015.generator.d.ts": { + "version": "/lib/lib.es2015.generator.d.ts", + "signature": "/lib/lib.es2015.generator.d.ts" + }, + "/lib/lib.es2015.iterable.d.ts": { + "version": "/lib/lib.es2015.iterable.d.ts", + "signature": "/lib/lib.es2015.iterable.d.ts" + }, + "/lib/lib.es2015.promise.d.ts": { + "version": "/lib/lib.es2015.promise.d.ts", + "signature": "/lib/lib.es2015.promise.d.ts" + }, + "/lib/lib.es2015.proxy.d.ts": { + "version": "/lib/lib.es2015.proxy.d.ts", + "signature": "/lib/lib.es2015.proxy.d.ts" + }, + "/lib/lib.es2015.reflect.d.ts": { + "version": "/lib/lib.es2015.reflect.d.ts", + "signature": "/lib/lib.es2015.reflect.d.ts" + }, + "/lib/lib.es2015.symbol.d.ts": { + "version": "/lib/lib.es2015.symbol.d.ts", + "signature": "/lib/lib.es2015.symbol.d.ts" + }, + "/lib/lib.es2015.symbol.wellknown.d.ts": { + "version": "/lib/lib.es2015.symbol.wellknown.d.ts", + "signature": "/lib/lib.es2015.symbol.wellknown.d.ts" + }, + "/src/src/hkt.ts": { + "version": "675797797", + "signature": "2373810515" + }, + "/src/src/main.ts": { + "version": "-27494779858", + "signature": "-7779857705" + } + }, + "options": { + "rootDir": "/src/src", + "lib": [ + "lib.es2015.d.ts" + ], + "incremental": true, + "configFilePath": "/src/tsconfig.json" + }, + "referencedMap": { + "/src/src/main.ts": [ + "/src/src/hkt.ts" + ] + }, + "exportedModulesMap": { + "/src/src/main.ts": [ + "/src/src/hkt.ts" + ] + }, + "semanticDiagnosticsPerFile": [ + "/lib/lib.es2015.collection.d.ts", + "/lib/lib.es2015.core.d.ts", + "/lib/lib.es2015.d.ts", + "/lib/lib.es2015.generator.d.ts", + "/lib/lib.es2015.iterable.d.ts", + "/lib/lib.es2015.promise.d.ts", + "/lib/lib.es2015.proxy.d.ts", + "/lib/lib.es2015.reflect.d.ts", + "/lib/lib.es2015.symbol.d.ts", + "/lib/lib.es2015.symbol.wellknown.d.ts", + "/lib/lib.es5.d.ts", + "/src/src/hkt.ts", + "/src/src/main.ts" + ] + }, + "version": "FakeTSVersion" +} +