Skip to content

Commit 10e3b73

Browse files
authored
Debug assert on parent rebind, mitigate circularity in symbol access checking (microsoft#22282)
* Assert that symbol parents are never rebound to different parents * mitigate circularities in symbol accessibility checking
1 parent f6418c0 commit 10e3b73

2 files changed

Lines changed: 22 additions & 5 deletions

File tree

src/compiler/binder.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -427,7 +427,12 @@ namespace ts {
427427
}
428428

429429
addDeclarationToSymbol(symbol, node, includes);
430-
symbol.parent = parent;
430+
if (symbol.parent) {
431+
Debug.assert(symbol.parent === parent, "Existing symbol parent should match new one");
432+
}
433+
else {
434+
symbol.parent = parent;
435+
}
431436

432437
return symbol;
433438
}

src/compiler/checker.ts

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2470,12 +2470,19 @@ namespace ts {
24702470
return rightMeaning === SymbolFlags.Value ? SymbolFlags.Value : SymbolFlags.Namespace;
24712471
}
24722472

2473-
function getAccessibleSymbolChain(symbol: Symbol, enclosingDeclaration: Node | undefined, meaning: SymbolFlags, useOnlyExternalAliasing: boolean): Symbol[] | undefined {
2473+
function getAccessibleSymbolChain(symbol: Symbol, enclosingDeclaration: Node | undefined, meaning: SymbolFlags, useOnlyExternalAliasing: boolean, visitedSymbolTablesMap: Map<SymbolTable[]> = createMap()): Symbol[] | undefined {
24742474
if (!(symbol && !isPropertyOrMethodDeclarationSymbol(symbol))) {
24752475
return undefined;
24762476
}
24772477

2478-
const visitedSymbolTables: SymbolTable[] = [];
2478+
const id = "" + getSymbolId(symbol);
2479+
let visitedSymbolTables: SymbolTable[];
2480+
if (visitedSymbolTablesMap.has(id)) {
2481+
visitedSymbolTables = visitedSymbolTablesMap.get(id);
2482+
}
2483+
else {
2484+
visitedSymbolTablesMap.set(id, visitedSymbolTables = []);
2485+
}
24792486
return forEachSymbolTableInScope(enclosingDeclaration, getAccessibleSymbolChainFromSymbolTable);
24802487

24812488
/**
@@ -2495,7 +2502,7 @@ namespace ts {
24952502
// If the symbol is equivalent and doesn't need further qualification, this symbol is accessible
24962503
return !needsQualification(symbolFromSymbolTable, enclosingDeclaration, meaning) ||
24972504
// If symbol needs qualification, make sure that parent is accessible, if it is then this symbol is accessible too
2498-
!!getAccessibleSymbolChain(symbolFromSymbolTable.parent, enclosingDeclaration, getQualifiedLeftMeaning(meaning), useOnlyExternalAliasing);
2505+
!!getAccessibleSymbolChain(symbolFromSymbolTable.parent, enclosingDeclaration, getQualifiedLeftMeaning(meaning), useOnlyExternalAliasing, visitedSymbolTablesMap);
24992506
}
25002507

25012508
function isAccessible(symbolFromSymbolTable: Symbol, resolvedAliasSymbol?: Symbol, ignoreQualification?: boolean) {
@@ -5445,7 +5452,12 @@ namespace ts {
54455452
}
54465453

54475454
addDeclarationToLateBoundSymbol(lateSymbol, decl, symbolFlags);
5448-
lateSymbol.parent = parent;
5455+
if (lateSymbol.parent) {
5456+
Debug.assert(lateSymbol.parent === parent, "Existing symbol parent should match new one");
5457+
}
5458+
else {
5459+
lateSymbol.parent = parent;
5460+
}
54495461
return links.resolvedSymbol = lateSymbol;
54505462
}
54515463
}

0 commit comments

Comments
 (0)