Trim per-release overhead in the scene
Only re-measure the viewport at begin() when a container is mounted, and only allocate waiting machinery when an interrupted finish() actually needs to wait for a later release. Interrupted releases now resolve with the final decided outcome in every case. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Faarh2Ts6StJPcz2mRiHiR
This commit is contained in:
@@ -285,9 +285,12 @@ class Scene implements OriginScene {
|
||||
*/
|
||||
/** The latest release (finish call) of each operation. */
|
||||
private readonly releases = new WeakMap<MutableOriginOperation, object>();
|
||||
private readonly outcomes = new WeakMap<
|
||||
/** Final outcome of each operation, once a release has decided it. */
|
||||
private readonly outcomes = new WeakMap<MutableOriginOperation, boolean>();
|
||||
/** Interrupted releases waiting for a later release to decide. */
|
||||
private readonly waiters = new WeakMap<
|
||||
MutableOriginOperation,
|
||||
{ promise: Promise<boolean>; resolve(committed: boolean): void }
|
||||
Array<(committed: boolean) => void>
|
||||
>();
|
||||
private readonly effectSets = new WeakMap<
|
||||
MutableOriginOperation,
|
||||
@@ -322,7 +325,7 @@ class Scene implements OriginScene {
|
||||
originKey: string,
|
||||
action: OriginAction,
|
||||
): Promise<OriginOperationHandle> {
|
||||
this.refreshViewport();
|
||||
if (this.container) this.refreshViewport();
|
||||
const operation = this.graph.begin(
|
||||
originKey,
|
||||
action,
|
||||
@@ -383,36 +386,40 @@ class Scene implements OriginScene {
|
||||
current,
|
||||
);
|
||||
|
||||
const outcome = this.outcomeOf(operation);
|
||||
// Another release already decided this operation.
|
||||
const decided = this.outcomes.get(operation);
|
||||
if (decided !== undefined) return decided;
|
||||
// A later operation may already have finalized this edge.
|
||||
const finished = (operation.phase as OriginOperationPhase) === "finished";
|
||||
if (!this.graph.operation(operation.id) || finished) {
|
||||
const committed = this.graph.operation(operation.id)
|
||||
? operation.intent === "commit"
|
||||
: commit;
|
||||
outcome.resolve(committed);
|
||||
return committed;
|
||||
}
|
||||
// Caught by update() or superseded by a later finish().
|
||||
if (!current()) return outcome.promise;
|
||||
if (!this.graph.operation(operation.id) || finished)
|
||||
return this.decide(
|
||||
operation,
|
||||
finished ? operation.intent === "commit" : commit,
|
||||
);
|
||||
// Caught by update() or superseded by a later finish(): wait for the
|
||||
// release that decides.
|
||||
if (!current())
|
||||
return new Promise<boolean>((resolve) =>
|
||||
this.waiters.set(operation, [
|
||||
...(this.waiters.get(operation) ?? []),
|
||||
resolve,
|
||||
]),
|
||||
);
|
||||
|
||||
const committed = commit
|
||||
return this.decide(
|
||||
operation,
|
||||
commit
|
||||
? this.graph.commit(operation.id)
|
||||
: (this.graph.cancel(operation.id), false);
|
||||
outcome.resolve(committed);
|
||||
return committed;
|
||||
: (this.graph.cancel(operation.id), false),
|
||||
);
|
||||
}
|
||||
|
||||
/** Resolves with an operation's final outcome, whichever release decides. */
|
||||
private outcomeOf(operation: MutableOriginOperation) {
|
||||
let outcome = this.outcomes.get(operation);
|
||||
if (!outcome) {
|
||||
let resolve!: (committed: boolean) => void;
|
||||
const promise = new Promise<boolean>((done) => (resolve = done));
|
||||
outcome = { promise, resolve };
|
||||
this.outcomes.set(operation, outcome);
|
||||
}
|
||||
return outcome;
|
||||
/** Record an operation's final outcome and settle interrupted releases. */
|
||||
private decide(operation: MutableOriginOperation, committed: boolean) {
|
||||
this.outcomes.set(operation, committed);
|
||||
for (const resolve of this.waiters.get(operation) ?? []) resolve(committed);
|
||||
this.waiters.delete(operation);
|
||||
return committed;
|
||||
}
|
||||
|
||||
registerElement(nodeKey: string, element: HTMLElement | null): void {
|
||||
|
||||
Reference in New Issue
Block a user