mirror of
https://github.com/anomalyco/opencode.git
synced 2026-05-29 11:14:23 +00:00
fix: batch server switch to avoid cleanNode crash
The status popover and select-server dialog used to call navigate('/') then
defer server.setActive to the next microtask. With multiple sidecars in v2,
that split triggered two separate disposal cascades - one for the route
change and a second for the ServerKey Show re-key - and the sidebar project
bucket also swaps (local -> wsl:Debian), tearing down every solid-dnd
sortable in the middle. Wrapping both calls in batch() lands them in a
single Solid update so disposal runs once.
Also raise Error.stackTraceLimit to 200 so future disposal crashes capture
the originating frame instead of truncating at the tenth cleanNode.
This commit is contained in:
parent
3360480a2a
commit
cfcc6f1353
3 changed files with 19 additions and 6 deletions
|
|
@ -8,7 +8,7 @@ import { List } from "@opencode-ai/ui/list"
|
|||
import { TextField } from "@opencode-ai/ui/text-field"
|
||||
import { useMutation } from "@tanstack/solid-query"
|
||||
import { showToast } from "@opencode-ai/ui/toast"
|
||||
import { createEffect, createMemo, createResource, onCleanup, Show } from "solid-js"
|
||||
import { batch, createEffect, createMemo, createResource, onCleanup, Show } from "solid-js"
|
||||
import { createStore, reconcile } from "solid-js/store"
|
||||
import { DialogWslServer } from "@/components/dialog-wsl-server"
|
||||
import { ServerHealthIndicator, ServerRow } from "@/components/server/server-row"
|
||||
|
|
@ -364,8 +364,10 @@ export function DialogSelectServer(props: DialogSelectServerProps = {}) {
|
|||
props.onNavigateHome?.()
|
||||
return
|
||||
}
|
||||
props.onNavigateHome?.()
|
||||
queueMicrotask(() => server.setActive(ServerConnection.key(conn)))
|
||||
batch(() => {
|
||||
props.onNavigateHome?.()
|
||||
server.setActive(ServerConnection.key(conn))
|
||||
})
|
||||
}
|
||||
|
||||
const handleAddChange = (value: string) => {
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import { Tabs } from "@opencode-ai/ui/tabs"
|
|||
import { useMutation } from "@tanstack/solid-query"
|
||||
import { showToast } from "@opencode-ai/ui/toast"
|
||||
import { useNavigate } from "@solidjs/router"
|
||||
import { type Accessor, createEffect, createMemo, For, type JSXElement, onCleanup, Show } from "solid-js"
|
||||
import { type Accessor, batch, createEffect, createMemo, For, type JSXElement, onCleanup, Show } from "solid-js"
|
||||
import { createStore, reconcile } from "solid-js/store"
|
||||
import { ServerHealthIndicator, ServerRow } from "@/components/server/server-row"
|
||||
import { useLanguage } from "@/context/language"
|
||||
|
|
@ -292,8 +292,13 @@ export function StatusPopoverBody(props: { shown: Accessor<boolean> }) {
|
|||
aria-disabled={blocked()}
|
||||
onClick={() => {
|
||||
if (blocked()) return
|
||||
navigate("/")
|
||||
queueMicrotask(() => server.setActive(key))
|
||||
// Run navigate + setActive in the same tick so Solid
|
||||
// disposes the old subtree once instead of cascading
|
||||
// the route change disposal into the ServerKey remount.
|
||||
batch(() => {
|
||||
navigate("/")
|
||||
server.setActive(key)
|
||||
})
|
||||
}}
|
||||
>
|
||||
<ServerHealthIndicator health={health[key]} />
|
||||
|
|
|
|||
|
|
@ -1,5 +1,11 @@
|
|||
// @refresh reload
|
||||
|
||||
// V8's default Error.stackTraceLimit truncates at 10 frames, which is exactly
|
||||
// the depth of the recursive cleanNode crash — the real trigger (our code
|
||||
// calling dispose, or a store update racing disposal) is beyond that. Raise
|
||||
// it so stacks contain the origin frame.
|
||||
Error.stackTraceLimit = 200
|
||||
|
||||
// Install global error listeners before any other module runs so that
|
||||
// uncaught errors and rejected promises reach the main process with their
|
||||
// full stacks intact. Electron's `console-message` event only forwards the
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue