Skip to content

Cleanup and ownership

Every listener, timer, observer, state subscription, overlay entry, focus scope, and scroll lock has one owner. createDisposableScope() releases resources in reverse order exactly once. Open-only resources are recreated for each transition and released immediately on close.

Controller destruction releases external subscriptions before references can leak. Registration cleanup uses tokens so a stale cleanup cannot remove replacement metadata. Async Combobox work uses AbortController and request generations so destruction or a newer query invalidates the older result.

createTimeoutManager() owns one replaceable timeout and clears its handle before invoking the callback, which makes re-entrant scheduling deterministic. Menu typeahead, Tooltip delay, Listbox/Tree typeahead, and Navigation Menu intent all use this primitive. Commands, registrations, subscriptions, and delayed callbacks created after destroy() are inert; the final frozen snapshot remains readable.

Headless behavior; consumer-owned rendering and styling.