Skip to content

Platforms

Host adapters

Differential patches, attachment ownership and custom hosts.

packages/toned-core/hosts/README.md ↗Rendered from the package’s Markdown

This directory is internal architecture; it is not a public package entry point. Native integrations supply a NativeHostAdapter (exported from @toned/core/stylesheet); see NATIVE-HOSTS.md.

The controller treats attached targets as opaque identities. HostIntegration supplies committed parent/state reads, topology and viewport subscriptions, liveness, attachment, and post-attachment validation. It never returns CSS selectors or renderer nodes to the evaluator.

dom.ts owns DOM parent traversal, state selectors, shared document observers, shared media emitters, and grid registration. native.ts validates the explicit native adapter's topology/state/viewport capabilities and delegates to that integration. Constructing either adapter is pure; subscriptions begin only when a controller commits and are released during disposal. Writer ownership remains in the shared stylesheet/applyStyles.ts registry, which selects the registered native patch adapter or the DOM writer behind its target-based API.

Attachment may receive an invalidate(target) callback for local ownership dependencies. The DOM grid adapter calls it for retained area children when their owner detaches: a forwarded parent ref can move while those child refs remain unchanged. Controllers queue attached or invalidated targets and expose validatePendingHosts() to flush them after all commit refs have attached. The first pending entry advances a monotonic revision and notifies committed subscribers. React's createElements mounts one hostless validation observer per scope: it subscribes with useSyncExternalStore and drains the queue in an effect. This also catches a custom host moving its own forwarded ref through internal state, even when no provider or part renders. Only the observer rerenders, and validation errors reach the React error boundary above the scope. Full provider validation also drains the entries it checks. Flushing does not advance the revision or notify again. Detached ref cleanup removes only its own pending generation; detached grid children have no binding and validate as a no-op.

Relations keep their portable registered-part semantics in PartRelations. Host topology supplies the facts; it does not alter source-order resolution, instance boundaries, or event-state ownership. Hover, active, and focus facts come from committed events rather than a selector reread.

Native contract fixtures prove this boundary with opaque targets whose DOM accessors throw. They do not certify a concrete React Native renderer; that integration owns the native commit/reset conformance evidence documented in NATIVE-HOSTS.md.