SP slotplate
Concept

Disposables

One cancellation primitive for everything.

Every allocation — a ticker handle, a MobX reaction, an event listener, a Pixi resource — implements Disposable and is owned by a parent that tears it down.

export interface Disposable {
  dispose(): void;
}

Phases dispose their tickers on exit. Scenes dispose their presenters on teardown. DisposableBag collects children so the parent doesn't have to remember handles individually.

Rule of thumb

If you write const x = something.on(...) or const x = ticker.schedule(...), the return value has a dispose and the parent is responsible for calling it.

Why

A slot runs for hours. Tiny leaks — a callback here, a listener there — compound. Resource-leak bugs are usually invisible for the first week and lethal by the second. A consistent disposal contract turns "did anyone clean this up?" into "yes, its parent did, in dispose()."

Idempotence

dispose is safe to call twice. Implementations no-op after the first call. This lets parents dispose aggressively without tracking "already disposed" flags.