fix: defer reactive root disposal in cache cleanups
Same nested-dispose-in-onCleanup bug as 7f36ac2481 but in three more places: TerminalProvider.disposeAll, PromptProvider.disposeAll, and scoped-cache.clear() (covers viewCache.clear and comments cache.clear). All of them synchronously call createRoot dispose() on cached entries inside onCleanup, which during a server switch nests into the outer cleanNode cascade and throws TypeError at chunk-*.js:992. Snapshot the pending disposers, clear the cache synchronously, and fire the disposers on a microtask so the outer cleanup finishes first.
This commit is contained in:
@@ -232,10 +232,13 @@ export const { use: usePrompt, provider: PromptProvider } = createSimpleContext(
|
||||
const cache = new Map<string, PromptCacheEntry>()
|
||||
|
||||
const disposeAll = () => {
|
||||
for (const entry of cache.values()) {
|
||||
entry.dispose()
|
||||
}
|
||||
// Defer the dispose calls to a microtask; synchronous nested dispose
|
||||
// inside a parent onCleanup corrupts solid-js's in-flight cleanNode
|
||||
// traversal during mass remounts (see context/terminal.tsx for the
|
||||
// same pattern).
|
||||
const pending = Array.from(cache.values(), (entry) => entry.dispose)
|
||||
cache.clear()
|
||||
if (pending.length) queueMicrotask(() => pending.forEach((d) => d()))
|
||||
}
|
||||
|
||||
onCleanup(disposeAll)
|
||||
|
||||
@@ -364,10 +364,15 @@ export const { use: useTerminal, provider: TerminalProvider } = createSimpleCont
|
||||
onCleanup(() => caches.delete(cache))
|
||||
|
||||
const disposeAll = () => {
|
||||
for (const entry of cache.values()) {
|
||||
entry.dispose()
|
||||
}
|
||||
// Snapshot disposers, then defer them to a microtask. When this runs
|
||||
// from onCleanup during a parent remount (e.g. switching servers),
|
||||
// calling dispose() synchronously starts a nested cleanNode cascade on
|
||||
// a sibling root while the outer cascade is mid-traversal, corrupting
|
||||
// solid-js's graph walk state and throwing `Cannot read properties of
|
||||
// null (reading '1')` at chunk-*.js:992.
|
||||
const pending = Array.from(cache.values(), (entry) => entry.dispose)
|
||||
cache.clear()
|
||||
if (pending.length) queueMicrotask(() => pending.forEach((d) => d()))
|
||||
}
|
||||
|
||||
onCleanup(disposeAll)
|
||||
|
||||
Reference in New Issue
Block a user