Status: accepted (Phase 1)
Context resolution, disposal, error ownership and portal semantics all need a notion of “parent”. The physical DOM parent is the wrong answer for portals, and walking the DOM is the wrong answer for performance.
composedPath/parentNode walk used by
many web-component libraries, or a context-request event). Portals break it
by construction, shadow boundaries complicate it, and every lookup is O(depth)
of the DOM.context-request DOM event protocol. Good for interop with foreign
components, but allocates an event per lookup, is bound to the physical tree,
and cannot express “resolve once, then subscribe”.Option 3. An Owner is a plain object with a parent pointer, an intrusive child
list, a lazily created disposal array and a lazily created, prototype-chained
context record.
provide writes into the owner’s context record, which is
Object.create(parentRecord). useContext resolves once at setup time via a
single prototype-chain property lookup and then holds the provider’s cell
directly; subsequent reads cost exactly one signal read. Nested providers cost
nothing extra at read time.Option 2 remains available as an interop adapter for consuming third-party
context-request providers; it is not the internal mechanism.
One owner per scope, with arrays allocated only when something is actually registered. A disposed subtree drops its owners, its context records and its links in one pass.
The rule “ownership is where you wrote it, not where the DOM ended up” is simple
and matches intuition. The one sharp edge: creating reactive scopes outside any
owner (e.g. at module top level) leaves them un-owned; createRoot makes that
explicit and returns a dispose.
DOM traversal (breaks portals, O(depth), shadow complications), event-based context (allocation per lookup, physical-tree bound).