Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 647421f

Browse files
committedSep 24, 2020
Cache property name widening contexts
When creating a new `WideningContext` for a given property, check whether there's an existing `WideningContext` with the same `parent` and `propertyName`. Otherwise, we won't adequately leverage the cache of computed `siblings` stored on the `WideningContext`.
1 parent 5305e4a commit 647421f

File tree

2 files changed

+21
-8
lines changed

2 files changed

+21
-8
lines changed
 

‎src/compiler/checker.ts

+16-4
Original file line numberDiff line numberDiff line change
@@ -19212,8 +19212,20 @@ namespace ts {
1921219212
return regularNew;
1921319213
}
1921419214

19215-
function createWideningContext(parent: WideningContext | undefined, propertyName: __String | undefined, siblings: Type[] | undefined): WideningContext {
19216-
return { parent, propertyName, siblings, resolvedProperties: undefined };
19215+
function createSiblingWideningContext(siblings: Type[]): WideningContext {
19216+
return { siblings };
19217+
}
19218+
19219+
function createPropertyWideningContext(parent: WideningContext, propertyName: __String): WideningContext {
19220+
const cache = (parent.childContexts ??= new Map<__String, WideningContext>());
19221+
const existing = cache.get(propertyName);
19222+
if (existing) {
19223+
return existing;
19224+
}
19225+
19226+
const context: WideningContext = { parent, propertyName };
19227+
cache.set(propertyName, context);
19228+
return context;
1921719229
}
1921819230

1921919231
function getSiblingsOfContext(context: WideningContext): Type[] {
@@ -19256,7 +19268,7 @@ namespace ts {
1925619268
return prop;
1925719269
}
1925819270
const original = getTypeOfSymbol(prop);
19259-
const propContext = context && createWideningContext(context, prop.escapedName, /*siblings*/ undefined);
19271+
const propContext = context && createPropertyWideningContext(context, prop.escapedName);
1926019272
const widened = getWidenedTypeWithContext(original, propContext);
1926119273
return widened === original ? prop : createSymbolWithType(prop, widened);
1926219274
}
@@ -19310,7 +19322,7 @@ namespace ts {
1931019322
result = getWidenedTypeOfObjectLiteral(type, context);
1931119323
}
1931219324
else if (type.flags & TypeFlags.Union) {
19313-
const unionContext = context || createWideningContext(/*parent*/ undefined, /*propertyName*/ undefined, (<UnionType>type).types);
19325+
const unionContext = context || createSiblingWideningContext((<UnionType>type).types);
1931419326
const widenedTypes = sameMap((<UnionType>type).types, t => t.flags & TypeFlags.Nullable ? t : getWidenedTypeWithContext(t, unionContext));
1931519327
// Widening an empty object literal transitions from a highly restrictive type to
1931619328
// a highly inclusive one. For that reason we perform subtype reduction here if the

‎src/compiler/types.ts

+5-4
Original file line numberDiff line numberDiff line change
@@ -5550,10 +5550,11 @@ namespace ts {
55505550

55515551
/* @internal */
55525552
export interface WideningContext {
5553-
parent?: WideningContext; // Parent context
5554-
propertyName?: __String; // Name of property in parent
5555-
siblings?: Type[]; // Types of siblings
5556-
resolvedProperties?: Symbol[]; // Properties occurring in sibling object literals
5553+
parent?: WideningContext; // Parent context
5554+
propertyName?: __String; // Name of property in parent
5555+
siblings?: Type[]; // Types of siblings
5556+
resolvedProperties?: Symbol[]; // Properties occurring in sibling object literals
5557+
childContexts?: ESMap<__String, WideningContext>; // WideningContexts with parent === this and propertyName as the key
55575558
}
55585559

55595560
/* @internal */

0 commit comments

Comments
 (0)
Please sign in to comment.