Files
ujsx/tasks/fiber-disposal.md
glm-5.1 c9c32a6aa6 decompose reconciler roadmap into 20 implementation tasks across 5 phases
Tasks follow the architecture spec phases:
- Phase 0: key field on UElement (2 tasks + review)
- Phase 1: reactive-host bridge / fiber tree (4 tasks + review)
- Phase 2: key-based children reconciliation (3 tasks + review)
- Phase 3: unmount & dispose support (4 tasks)
- Phase 4: TypeBox value optimizations (4 tasks)

Validated with taskgraph CLI: no cycles, 15 parallel generations,
3 high-risk tasks identified (signal-driven-updates, commit-mutations,
fiber-disposal).
2026-05-18 16:26:52 +00:00

2.4 KiB

id, name, status, depends_on, created, modified, scope, risk, impact, level
id name status depends_on created modified scope risk impact level
fiber-disposal Implement fiber tree disposal pending
review-reconciler
2026-05-18T16:22:57.277429897Z 2026-05-18T16:22:57.277430341Z moderate high phase implementation

Description

Implement disposeFiber() for full teardown of a fiber subtree. This is the foundation for both root unmount and partial tree removal during reconciliation.

Disposal is bottom-up (children before parents) and covers:

  1. Recursively dispose all child fibers
  2. Call host.finalizeInstance?(instance, ctx) for per-instance cleanup
  3. Call each disposer in fiber.signalDisposers to clean up signal subscriptions
  4. Clear fiber state (children = [], parent = null, effect = null, signalDisposers = [])

Important constraint: disposeFiber disposes resources but does NOT call host.removeChild(). Instance removal happens during the commit phase, in a specific order, as part of the reconciliation algorithm. This separation ensures correct mutation ordering when batching removes.

All disposal operations are idempotent — calling dispose() twice is safe.

Acceptance Criteria

  • disposeFiber(fiber, ctx) function implemented in src/host/fiber.ts
  • Bottom-up disposal: children disposed before their parent
  • Calls host.finalizeInstance?(instance, ctx) for each fiber after children are disposed
  • Calls every disposer in fiber.signalDisposers
  • Clears fiber.signalDisposers = [] after calling (prevents double-call)
  • Clears fiber.parent = null after disposal
  • Clears fiber.effect = null
  • Idempotent: calling disposeFiber twice is safe (no double-dispose, no errors)
  • Does NOT call host.removeChild() — that's the commit phase's job
  • computed signals are NOT explicitly disposed (they're garbage collected when references clear)
  • Only effect() return values need explicit disposal
  • New test: diposeFiber on a tree with 3 levels calls disposers and finalizeInstance bottom-up
  • New test: idempotent double-dispose does not error
  • New test: signal subscriptions are cleaned up (effect no longer fires after dispose)

References

  • docs/architecture/lifecycle.md — Fiber Tree Disposal, Root Unmount Flow, Disposal Idempotency, computed vs effect Cleanup
  • docs/architecture/reconciler.md — Effect type "remove"

Notes

To be filled by implementation agent

Summary

To be filled on completion