add reconciler architecture docs and update existing docs with cross-references
Phase 2: transitioning reconciler research into architecture documents. New docs: - reconciler.md: fiber tree, reconciliation algorithm (signal-driven props + key-based children), update scheduling, commit order, TypeBox optimization layer, file structure, consumer impact - lifecycle.md: mount/update/dispose phases, fiber tree disposal, partial tree removal, ReactiveRoot.dispose(), finalizeInstance, idempotent disposal, computed vs effect cleanup - ADR-004: key as first-class field on UElement (not a prop) - ADR-005: signal-driven updates for props, reconciliation for structure (hybrid approach, not full tree diffing) Updated docs: - README.md: add reconciler.md, lifecycle.md, ADRs 004/005 to index; update reconciler roadmap with architecture doc links - schema.md: add key?: string to UElement type with TODO comment; update known gaps to reference ADR-004 and reconciler.md; rephrase key constraint as temporary - element-factory.md: update key extraction gap to reference ADR-004 and reconciler.md - host-config.md: reference reconciler.md and lifecycle.md for the reconciler bridge and disposal gaps - reactive-layer.md: reference reconciler.md and lifecycle.md for the signal-host bridge and disposal gaps - events.md: reference lifecycle.md for unmount/dispose gap
This commit is contained in:
@@ -125,11 +125,11 @@ Calling `render()` a second time replaces `this.renderDisposer` without disposin
|
||||
|
||||
### No connection to HostConfig reconciler
|
||||
|
||||
`ReactiveRoot.render()` emits events, but nothing consumes those events to call `HostConfig.prepareUpdate`/`commitUpdate`. The signal layer and the host layer are two separate islands. The reconciler research ([01-reactive-host-bridge.md](../../research/reconciler/01-reactive-host-bridge.md)) proposes a fiber-based bridge: `ReactiveRoot` signal changes trigger a reconciliation pass that diffs props and calls `HostConfig` update methods.
|
||||
`ReactiveRoot.render()` emits events, but nothing consumes those events to call `HostConfig.prepareUpdate`/`commitUpdate`. The signal layer and the host layer are two separate islands. The reconciler architecture ([reconciler.md](reconciler.md)) proposes a fiber-based bridge: `ReactiveRoot` signal changes trigger a reconciliation pass that diffs props and calls `HostConfig` update methods.
|
||||
|
||||
### No auto-dispose on unmount
|
||||
|
||||
`ReactiveRoot` has no `unmount()` or `destroy()` method. Effects created by `subscribe()` and `render()` are never automatically torn down. The reconciler research ([03-unmount-dispose-support.md](../../research/reconciler/03-unmount-dispose-support.md)) addresses this.
|
||||
`ReactiveRoot` has no `unmount()` or `destroy()` method. Effects created by `subscribe()` and `render()` are never automatically torn down. The lifecycle management architecture ([lifecycle.md](lifecycle.md)) addresses this, with `ReactiveRoot.dispose()` tracking and cleaning up all subscriber and render effect disposers.
|
||||
|
||||
## Constraints
|
||||
|
||||
@@ -143,13 +143,15 @@ Calling `render()` a second time replaces `this.renderDisposer` without disposin
|
||||
|
||||
1. **Should `ReactiveNode.dispose` be implemented using `effect` cleanup or stored-disposer patterns?** The current `computed` signals have no public dispose API in `@preact/signals-core`. Disposal requires either switching to an effect-based approach (where each `computed` is tracked by an `effect` that can be disposed) or maintaining an explicit disposer list.
|
||||
2. **Should `ReactiveRoot` track all subscription disposers?** Adding an internal `Set<() => void>` for active subscribers would allow `ReactiveRoot` to clean up on unmount. This creates a lifecycle coupling — `ReactiveRoot` would need a `destroy()` method.
|
||||
3. **How should `ReactiveRoot` connect to the reconciler?** Options: (a) `ReactiveRoot` emits events that a reconciler subscribes to, (b) `createReactiveRoot(host, container)` bridges both layers, (c) consumer code wires them manually. See [01-reactive-host-bridge.md](../../research/reconciler/01-reactive-host-bridge.md) for analysis.
|
||||
3. **How should `ReactiveRoot` connect to the reconciler?** Options: (a) `ReactiveRoot` emits events that a reconciler subscribes to, (b) `createReactiveRoot(host, container)` bridges both layers, (c) consumer code wires them manually. See [reconciler.md](reconciler.md) for the fiber-based bridge approach.
|
||||
4. **Should `render()` support multiple concurrent subscribers?** The current overwriting design suggests single-subscriber usage. If multiple hosts need to render the same reactive tree, they should each call `subscribe()` directly rather than `render()`.
|
||||
|
||||
## References
|
||||
|
||||
- Source: `src/core/reactive.ts`
|
||||
- ADR-003: `docs/architecture/decisions/003-preact-signals-for-reactivity.md`
|
||||
- Reconciler architecture: [reconciler.md](reconciler.md)
|
||||
- Lifecycle management: [lifecycle.md](lifecycle.md)
|
||||
- Reactive → Host bridge research: `docs/research/reconciler/01-reactive-host-bridge.md`
|
||||
- Unmount & dispose research: `docs/research/reconciler/03-unmount-dispose-support.md`
|
||||
- Preact signals-core: `@preact/signals-core`
|
||||
Reference in New Issue
Block a user