Description
This breaks glimmer
, and thereby our RWC (once sufficiently fixed in other ways)
Code
Isolated repro (needs dom
lib for ElementTagNameMap
and associated types):
export function assertIsElement(node: Node | null): node is Element {
let nodeType = node === null ? null : node.nodeType;
return nodeType === 1;
}
export function assertNodeTagName<
T extends keyof ElementTagNameMap,
U extends ElementTagNameMap[T]>(node: Node | null, tagName: T): node is U {
if (assertIsElement(node)) {
const nodeTagName = node.tagName.toLowerCase();
return nodeTagName === tagName;
}
return false;
}
export function assertNodeProperty<
T extends keyof ElementTagNameMap,
P extends keyof ElementTagNameMap[T],
V extends HTMLElementTagNameMap[T][P]>(node: Node | null, tagName: T, prop: P, value: V) {
if (assertNodeTagName(node, tagName)) {
node[prop];
}
}
Expected behavior:
No crash.
Actual behavior:
OOM crash after a very long delay.
Preliminary investigation shows the OOM occurs when we try to get the distributed form of keyof <Large Union>
- namely the process is defined recursively, so when the union has ~170 members, we create 170 intermediate types (flattening one member at a time, while also wasting time recalculating type flags and other bits we will never need) before getting the final, distributed result. Now, picture doing this on every relation comparison operation for P
(this distribution is uncached), and multiplying it for V
in assertNodeProperty
- the complexity is huge.
cc @DanielRosenwasser since I think you care about when we break glimmer.