Skip to content

Instantly share code, notes, and snippets.

@jridgewell
Last active February 12, 2024 05:15
Show Gist options
  • Save jridgewell/ef8a674291f8f7419a2bea0448c3b0eb to your computer and use it in GitHub Desktop.
Save jridgewell/ef8a674291f8f7419a2bea0448c3b0eb to your computer and use it in GitHub Desktop.
Flatten unobservable AsyncContext.Variable values from all living snapshot chains
/**
* Flattens all "snapshots", removing unobservable nodes so they may free their
* values.
*
* "snapshots" here is all Snapshot instances, every created
* Generator/AsyncGenerator, every stored Job, etc.
*/
function flatten(snapshots: Snapshot[]) {
const current = new Map<Variable>();
const maybe = new Map<LinkNode, LinkNode>();
const seen = new Set<LinkNode>();
for (const snapshot of snapshots) {
let c = snapshot.[[AsyncContextLinkNode]];
let parent;
while (c) {
// If we've already seen this variable in this linked-list chain, then it's an unobservable
const variable = c.[[AsyncContextVariable]];
if (current.has(variable)) {
if (!seen.has(c)) {
maybe.set(c, parent);
}
} else {
maybe.delete(c);
}
seen.add(c);
current.add(variable);
parent = c;
c = c.[[AsyncContextLinkNode]];
}
current.clear();
}
// Anything still in maybe is unreachable across all snapshots.
for (const [node, parent] of maybe) {
parent.[[AsyncContextLinkNode]] = node.[[AsyncContextLinkNode]];
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment