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

56 lines
2.4 KiB
Markdown

---
id: fiber-disposal
name: Implement fiber tree disposal
status: pending
depends_on: [review-reconciler]
created: 2026-05-18T16:22:57.277429897Z
modified: 2026-05-18T16:22:57.277430341Z
scope: moderate
risk: high
impact: phase
level: 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