diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index 86c9c97bdd5..a3a2be8bca3 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -427,7 +427,12 @@ namespace ts { } addDeclarationToSymbol(symbol, node, includes); - symbol.parent = parent; + if (symbol.parent) { + Debug.assert(symbol.parent === parent, "Existing symbol parent should match new one"); + } + else { + symbol.parent = parent; + } return symbol; } diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 1931661bf5f..515789a3fd7 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -2470,12 +2470,19 @@ namespace ts { return rightMeaning === SymbolFlags.Value ? SymbolFlags.Value : SymbolFlags.Namespace; } - function getAccessibleSymbolChain(symbol: Symbol, enclosingDeclaration: Node | undefined, meaning: SymbolFlags, useOnlyExternalAliasing: boolean): Symbol[] | undefined { + function getAccessibleSymbolChain(symbol: Symbol, enclosingDeclaration: Node | undefined, meaning: SymbolFlags, useOnlyExternalAliasing: boolean, visitedSymbolTablesMap: Map = createMap()): Symbol[] | undefined { if (!(symbol && !isPropertyOrMethodDeclarationSymbol(symbol))) { return undefined; } - const visitedSymbolTables: SymbolTable[] = []; + const id = "" + getSymbolId(symbol); + let visitedSymbolTables: SymbolTable[]; + if (visitedSymbolTablesMap.has(id)) { + visitedSymbolTables = visitedSymbolTablesMap.get(id); + } + else { + visitedSymbolTablesMap.set(id, visitedSymbolTables = []); + } return forEachSymbolTableInScope(enclosingDeclaration, getAccessibleSymbolChainFromSymbolTable); /** @@ -2495,7 +2502,7 @@ namespace ts { // If the symbol is equivalent and doesn't need further qualification, this symbol is accessible return !needsQualification(symbolFromSymbolTable, enclosingDeclaration, meaning) || // If symbol needs qualification, make sure that parent is accessible, if it is then this symbol is accessible too - !!getAccessibleSymbolChain(symbolFromSymbolTable.parent, enclosingDeclaration, getQualifiedLeftMeaning(meaning), useOnlyExternalAliasing); + !!getAccessibleSymbolChain(symbolFromSymbolTable.parent, enclosingDeclaration, getQualifiedLeftMeaning(meaning), useOnlyExternalAliasing, visitedSymbolTablesMap); } function isAccessible(symbolFromSymbolTable: Symbol, resolvedAliasSymbol?: Symbol, ignoreQualification?: boolean) { @@ -5445,7 +5452,12 @@ namespace ts { } addDeclarationToLateBoundSymbol(lateSymbol, decl, symbolFlags); - lateSymbol.parent = parent; + if (lateSymbol.parent) { + Debug.assert(lateSymbol.parent === parent, "Existing symbol parent should match new one"); + } + else { + lateSymbol.parent = parent; + } return links.resolvedSymbol = lateSymbol; } }