From 6ec23b53df27cb71e546d3ccf5027088c94b8cae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BB=98=E6=99=A8=E6=98=B1?= Date: Sat, 18 Jul 2026 17:03:30 +0800 Subject: [PATCH 1/5] fix(desktop): refresh legacy session panel on session switch --- packages/app/src/pages/session.tsx | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/packages/app/src/pages/session.tsx b/packages/app/src/pages/session.tsx index 3ce28416760f..7686c82221f6 100644 --- a/packages/app/src/pages/session.tsx +++ b/packages/app/src/pages/session.tsx @@ -2313,9 +2313,13 @@ export default function Page() { )} ) : ( - - {sessionPanelContent()} - + + {(_) => ( + + {sessionPanelContent()} + + )} + )} From da04124947dd967ff189d9aa00cd54f8a6fa2f36 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BB=98=E6=99=A8=E6=98=B1?= Date: Mon, 20 Jul 2026 11:26:20 +0800 Subject: [PATCH 2/5] fix(desktop): remount legacy workspace sessions --- .SRCINFO | 20 ++++++++ PKGBUILD | 74 ++++++++++++++++++++++++++++++ packages/app/src/app.tsx | 4 +- packages/app/src/pages/session.tsx | 7 +-- 4 files changed, 100 insertions(+), 5 deletions(-) create mode 100644 .SRCINFO create mode 100644 PKGBUILD diff --git a/.SRCINFO b/.SRCINFO new file mode 100644 index 000000000000..d3f2bd2d4ab7 --- /dev/null +++ b/.SRCINFO @@ -0,0 +1,20 @@ +pkgbase = opencode-desktop-bin + pkgdesc = OpenCode desktop client (local build with workspace refresh and Linux titlebar fixes) + pkgver = 1.18.3 + pkgrel = 6 + url = https://opencode.ai + arch = x86_64 + license = MIT + depends = gtk3 + depends = nss + depends = libxss + depends = libxtst + depends = alsa-lib + depends = libsecret + depends = libnotify + depends = xdg-utils + depends = ripgrep + provides = opencode-desktop + conflicts = opencode-desktop + +pkgname = opencode-desktop-bin diff --git a/PKGBUILD b/PKGBUILD new file mode 100644 index 000000000000..e187dbdefd41 --- /dev/null +++ b/PKGBUILD @@ -0,0 +1,74 @@ +# PKGBUILD: 用本地构建产物安装 OpenCode desktop(覆盖 AUR opencode-desktop-bin) +# 包含 legacy workspace/session 切换刷新和 Linux 自定义标题栏修复。 +# +# 前置:在 packages/desktop 完成 prod 构建 +# OPENCODE_CHANNEL=prod bun run prebuild +# OPENCODE_CHANNEL=prod bun run build +# OPENCODE_CHANNEL=prod bun run package:linux -- --dir +# +# 安装:在此文件所在目录运行 +# paru -U . +# 或 +# makepkg -si + +pkgname=opencode-desktop-bin +pkgver=1.18.3 +pkgrel=6 +pkgdesc="OpenCode desktop client (local build with workspace refresh and Linux titlebar fixes)" +arch=('x86_64') +url="https://opencode.ai" +license=('MIT') +depends=('gtk3' 'nss' 'libxss' 'libxtst' 'alsa-lib' 'libsecret' 'libnotify' 'xdg-utils' 'ripgrep') +provides=('opencode-desktop') +conflicts=('opencode-desktop') + +_local_build="$startdir/packages/desktop/dist/linux-unpacked" +_icons="$startdir/packages/desktop/resources/icons" + +package() { + # Electron app -> /opt/OpenCode + mkdir -p "$pkgdir/opt" + cp -a --no-preserve=ownership "$_local_build" "$pkgdir/opt/OpenCode" + + # /usr/bin launcher (matches AUR helper script) + install -Dm755 /dev/stdin "$pkgdir/usr/bin/opencode-desktop" <<'EOF' +#!/bin/bash +XDG_CONFIG_HOME="${XDG_CONFIG_HOME:-$HOME/.config}" +if [[ -f "$XDG_CONFIG_HOME/opencode-desktop-flags.conf" ]]; then + OPENCODE_USER_FLAGS="$(grep -v '^#' "$XDG_CONFIG_HOME/opencode-desktop-flags.conf")" +fi +exec /opt/OpenCode/ai.opencode.desktop $OPENCODE_USER_FLAGS "$@" +EOF + + # Primary .desktop entry + install -Dm644 /dev/stdin "$pkgdir/usr/share/applications/ai.opencode.desktop.desktop" <<'EOF' +[Desktop Entry] +Name=OpenCode +Exec=opencode-desktop %U +Terminal=false +Type=Application +Icon=ai.opencode.desktop +StartupWMClass=ai.opencode.desktop +MimeType=x-scheme-handler/opencode; +Categories=Development; +EOF + + # Legacy .desktop entry (keeps old GNOME/KDE pins resolving) + install -Dm644 /dev/stdin "$pkgdir/usr/share/applications/opencode-desktop.desktop" <<'EOF' +[Desktop Entry] +Name=OpenCode +Exec=/opt/OpenCode/ai.opencode.desktop %U +Terminal=false +Type=Application +Icon=ai.opencode.desktop +StartupWMClass=ai.opencode.desktop +NoDisplay=true +Comment=Open source AI coding agent +Categories=Development; +EOF + + # hicolor icons + install -Dm644 "$_icons/32x32.png" "$pkgdir/usr/share/icons/hicolor/32x32/apps/ai.opencode.desktop.png" + install -Dm644 "$_icons/64x64.png" "$pkgdir/usr/share/icons/hicolor/64x64/apps/ai.opencode.desktop.png" + install -Dm644 "$_icons/128x128.png" "$pkgdir/usr/share/icons/hicolor/128x128/apps/ai.opencode.desktop.png" +} diff --git a/packages/app/src/app.tsx b/packages/app/src/app.tsx index b4496ba7de1f..bc623f3406ce 100644 --- a/packages/app/src/app.tsx +++ b/packages/app/src/app.tsx @@ -66,7 +66,7 @@ import { useCheckServerHealth } from "./utils/server-health" import { legacySessionHref, legacySessionServer, requireServerKey, sessionHref } from "./utils/session-route" import { createSessionLineage } from "@/pages/session/session-lineage" -import { SessionPage, SessionRouteErrorBoundary, TargetSessionRouteContent } from "@/pages/session" +import { SessionRouteErrorBoundary, TargetSessionRouteContent, WorkspaceSessionPage } from "@/pages/session" import { NewHome, LegacyHome } from "@/pages/home" const NewSession = lazy(() => import("@/pages/new-session")) @@ -102,7 +102,7 @@ const SessionRoute = () => { return ( - + ) } diff --git a/packages/app/src/pages/session.tsx b/packages/app/src/pages/session.tsx index 7686c82221f6..e69fe1108575 100644 --- a/packages/app/src/pages/session.tsx +++ b/packages/app/src/pages/session.tsx @@ -99,6 +99,7 @@ import { Persist, persisted } from "@/utils/persist" import { extractPromptFromParts } from "@/utils/prompt" import { formatServerError, isLocalSessionNotFoundError, isSessionNotFoundError } from "@/utils/server-errors" import { legacySessionHref, requireServerKey, sessionHref } from "@/utils/session-route" +import { ScopedKey } from "@/utils/server-scope" import { useUsageExceededDialogs } from "./session/usage-exceeded-dialogs" import { createSessionOwnership } from "./session/session-ownership" import { createSessionLineage } from "./session/session-lineage" @@ -271,7 +272,7 @@ function ResolvedTargetSessionRoute() { - + @@ -281,11 +282,11 @@ function ResolvedTargetSessionRoute() { // Owns the workspace-identity remount. Must not include the session ID in the // key: SessionPage handles session changes reactively, and remounting here // destroys workspace-scoped state (terminal PTYs, file/prompt providers). -function TargetSessionPage() { +export function WorkspaceSessionPage() { const sdk = useSDK() const serverSDK = useServerSDK() return ( - + ) From 4c6f1a47955b9816cea01e774e4a281183d178f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BB=98=E6=99=A8=E6=98=B1?= Date: Mon, 20 Jul 2026 12:34:03 +0800 Subject: [PATCH 3/5] fix(app): stabilize session switch remount --- .SRCINFO | 2 +- PKGBUILD | 2 +- .../app/src/components/prompt-input/editor-dom.test.ts | 10 ++++++++++ packages/app/src/components/prompt-input/editor-dom.ts | 3 +++ packages/app/src/pages/session.tsx | 5 ++++- 5 files changed, 19 insertions(+), 3 deletions(-) diff --git a/.SRCINFO b/.SRCINFO index d3f2bd2d4ab7..84a10ac3dcdb 100644 --- a/.SRCINFO +++ b/.SRCINFO @@ -1,7 +1,7 @@ pkgbase = opencode-desktop-bin pkgdesc = OpenCode desktop client (local build with workspace refresh and Linux titlebar fixes) pkgver = 1.18.3 - pkgrel = 6 + pkgrel = 7 url = https://opencode.ai arch = x86_64 license = MIT diff --git a/PKGBUILD b/PKGBUILD index e187dbdefd41..1b6832367c6e 100644 --- a/PKGBUILD +++ b/PKGBUILD @@ -13,7 +13,7 @@ pkgname=opencode-desktop-bin pkgver=1.18.3 -pkgrel=6 +pkgrel=7 pkgdesc="OpenCode desktop client (local build with workspace refresh and Linux titlebar fixes)" arch=('x86_64') url="https://opencode.ai" diff --git a/packages/app/src/components/prompt-input/editor-dom.test.ts b/packages/app/src/components/prompt-input/editor-dom.test.ts index 3088522a59f6..52e5d98796ca 100644 --- a/packages/app/src/components/prompt-input/editor-dom.test.ts +++ b/packages/app/src/components/prompt-input/editor-dom.test.ts @@ -96,4 +96,14 @@ describe("prompt-input editor dom", () => { container.remove() }) + + test("setCursorPosition ignores editors detached during session remount", () => { + const container = document.createElement("div") + container.textContent = "old session" + window.getSelection()?.removeAllRanges() + + setCursorPosition(container, 3) + + expect(window.getSelection()?.rangeCount).toBe(0) + }) }) diff --git a/packages/app/src/components/prompt-input/editor-dom.ts b/packages/app/src/components/prompt-input/editor-dom.ts index 8575140d7d54..e771f10f428b 100644 --- a/packages/app/src/components/prompt-input/editor-dom.ts +++ b/packages/app/src/components/prompt-input/editor-dom.ts @@ -54,6 +54,9 @@ export function getCursorPosition(parent: HTMLElement): number { } export function setCursorPosition(parent: HTMLElement, position: number) { + // Focus restoration can outlive a session panel remount. Do not install a + // selection range backed by the detached editor from the previous session. + if (!parent.isConnected) return let remaining = position let node = parent.firstChild while (node) { diff --git a/packages/app/src/pages/session.tsx b/packages/app/src/pages/session.tsx index e69fe1108575..045d1b3569ce 100644 --- a/packages/app/src/pages/session.tsx +++ b/packages/app/src/pages/session.tsx @@ -2115,7 +2115,10 @@ export default function Page() { - + {/* SessionPanelFrame already remounts on sessionPanelKey. Keying this + descendant on the same navigation double-disposes its owner tree + when Solid commits the route transition. */} + {(_id) => ( Date: Mon, 20 Jul 2026 15:24:28 +0800 Subject: [PATCH 4/5] fix(app): drop session-id keyed remount to prevent Solid double disposal 1.18.3-8 moved the session-id keyed remount from the session panel up to the whole Page owner. Switching sessions still triggered Solid's cleanNode on the same owner twice, crashing at node.cleanups[i]() when an inner cleanup had already nulled cleanups. Remove every session-id keyed remount inside Page: keep SessionPage stable, keep WorkspaceSessionPage keyed only on scope+directory so TerminalProvider survives, and let MessageTimeline/SessionPanelFrame react to params.id without disposing. Session switches already reset view state (on(sessionKey)), autoScroll + scroll-to-bottom (on(params.id)), editor draft (restorePromptModel), and focus (on(params.id)); timeline messages, file tabs and review diffs are reactive on params.id/sessionKey. Also stop tracking the local AUR packaging files (.SRCINFO, PKGBUILD); they are build artifacts moved under tmp/aur (gitignored). --- .SRCINFO | 20 -------- PKGBUILD | 74 ------------------------------ packages/app/src/pages/session.tsx | 31 ++++--------- 3 files changed, 10 insertions(+), 115 deletions(-) delete mode 100644 .SRCINFO delete mode 100644 PKGBUILD diff --git a/.SRCINFO b/.SRCINFO deleted file mode 100644 index 84a10ac3dcdb..000000000000 --- a/.SRCINFO +++ /dev/null @@ -1,20 +0,0 @@ -pkgbase = opencode-desktop-bin - pkgdesc = OpenCode desktop client (local build with workspace refresh and Linux titlebar fixes) - pkgver = 1.18.3 - pkgrel = 7 - url = https://opencode.ai - arch = x86_64 - license = MIT - depends = gtk3 - depends = nss - depends = libxss - depends = libxtst - depends = alsa-lib - depends = libsecret - depends = libnotify - depends = xdg-utils - depends = ripgrep - provides = opencode-desktop - conflicts = opencode-desktop - -pkgname = opencode-desktop-bin diff --git a/PKGBUILD b/PKGBUILD deleted file mode 100644 index 1b6832367c6e..000000000000 --- a/PKGBUILD +++ /dev/null @@ -1,74 +0,0 @@ -# PKGBUILD: 用本地构建产物安装 OpenCode desktop(覆盖 AUR opencode-desktop-bin) -# 包含 legacy workspace/session 切换刷新和 Linux 自定义标题栏修复。 -# -# 前置:在 packages/desktop 完成 prod 构建 -# OPENCODE_CHANNEL=prod bun run prebuild -# OPENCODE_CHANNEL=prod bun run build -# OPENCODE_CHANNEL=prod bun run package:linux -- --dir -# -# 安装:在此文件所在目录运行 -# paru -U . -# 或 -# makepkg -si - -pkgname=opencode-desktop-bin -pkgver=1.18.3 -pkgrel=7 -pkgdesc="OpenCode desktop client (local build with workspace refresh and Linux titlebar fixes)" -arch=('x86_64') -url="https://opencode.ai" -license=('MIT') -depends=('gtk3' 'nss' 'libxss' 'libxtst' 'alsa-lib' 'libsecret' 'libnotify' 'xdg-utils' 'ripgrep') -provides=('opencode-desktop') -conflicts=('opencode-desktop') - -_local_build="$startdir/packages/desktop/dist/linux-unpacked" -_icons="$startdir/packages/desktop/resources/icons" - -package() { - # Electron app -> /opt/OpenCode - mkdir -p "$pkgdir/opt" - cp -a --no-preserve=ownership "$_local_build" "$pkgdir/opt/OpenCode" - - # /usr/bin launcher (matches AUR helper script) - install -Dm755 /dev/stdin "$pkgdir/usr/bin/opencode-desktop" <<'EOF' -#!/bin/bash -XDG_CONFIG_HOME="${XDG_CONFIG_HOME:-$HOME/.config}" -if [[ -f "$XDG_CONFIG_HOME/opencode-desktop-flags.conf" ]]; then - OPENCODE_USER_FLAGS="$(grep -v '^#' "$XDG_CONFIG_HOME/opencode-desktop-flags.conf")" -fi -exec /opt/OpenCode/ai.opencode.desktop $OPENCODE_USER_FLAGS "$@" -EOF - - # Primary .desktop entry - install -Dm644 /dev/stdin "$pkgdir/usr/share/applications/ai.opencode.desktop.desktop" <<'EOF' -[Desktop Entry] -Name=OpenCode -Exec=opencode-desktop %U -Terminal=false -Type=Application -Icon=ai.opencode.desktop -StartupWMClass=ai.opencode.desktop -MimeType=x-scheme-handler/opencode; -Categories=Development; -EOF - - # Legacy .desktop entry (keeps old GNOME/KDE pins resolving) - install -Dm644 /dev/stdin "$pkgdir/usr/share/applications/opencode-desktop.desktop" <<'EOF' -[Desktop Entry] -Name=OpenCode -Exec=/opt/OpenCode/ai.opencode.desktop %U -Terminal=false -Type=Application -Icon=ai.opencode.desktop -StartupWMClass=ai.opencode.desktop -NoDisplay=true -Comment=Open source AI coding agent -Categories=Development; -EOF - - # hicolor icons - install -Dm644 "$_icons/32x32.png" "$pkgdir/usr/share/icons/hicolor/32x32/apps/ai.opencode.desktop.png" - install -Dm644 "$_icons/64x64.png" "$pkgdir/usr/share/icons/hicolor/64x64/apps/ai.opencode.desktop.png" - install -Dm644 "$_icons/128x128.png" "$pkgdir/usr/share/icons/hicolor/128x128/apps/ai.opencode.desktop.png" -} diff --git a/packages/app/src/pages/session.tsx b/packages/app/src/pages/session.tsx index 045d1b3569ce..b66545e69b73 100644 --- a/packages/app/src/pages/session.tsx +++ b/packages/app/src/pages/session.tsx @@ -153,9 +153,10 @@ export function SessionPage() { } // Rendered under app.tsx's TargetSessionRoute, which owns the per-server keyed -// remount around the server-scoped providers. Nothing here may key on the -// session ID: session tabs on the same server share this route instance, and -// workspace-scoped state (terminal, directory providers) lives below. +// remount around the server-scoped providers. Session changes are handled +// reactively inside Page: nothing here keys on the session ID, so session +// tabs on the same server share this route instance and workspace-scoped +// state (terminal, directory providers) stays alive across switches. export function TargetSessionRouteContent() { const params = useParams<{ serverKey: string; id: string }>() const serverSync = useServerSync() @@ -406,7 +407,6 @@ export default function Page() { }) const workspaceTabs = createMemo(() => layout.tabs(workspaceKey)) - const sessionPanelKey = createMemo(() => (params.id ? `${serverSDK().scope}\0${params.id}` : undefined)) createEffect( on( @@ -2115,9 +2115,6 @@ export default function Page() { - {/* SessionPanelFrame already remounts on sessionPanelKey. Keying this - descendant on the same navigation double-disposes its owner tree - when Solid commits the route transition. */} {(_id) => ( {settings.general.newLayoutDesigns() ? ( - - {(_) => ( - - {sessionPanelContent()} - - )} - + + {sessionPanelContent()} + ) : ( - - {(_) => ( - - {sessionPanelContent()} - - )} - + + {sessionPanelContent()} + )} From 13e731bdebcddb600180c09e9a4ef1cc878d3c9b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BB=98=E6=99=A8=E6=98=B1?= Date: Tue, 21 Jul 2026 10:30:49 +0800 Subject: [PATCH 5/5] fix(app): guard Solid cleanNode against reentrant disposal Add reentrant-disposal guards to cleanNode in solid-js 1.9.10: capture owned/tOwned/cleanups to a local, null the node field, then iterate. A cleanup or owned-child disposal can re-enter cleanNode on the same owner during a router transition, nulling the field mid-loop and crashing on the next index read. --- patches/solid-js@1.9.10.patch | 114 +++++++++++++++++++++++++++++++--- 1 file changed, 104 insertions(+), 10 deletions(-) diff --git a/patches/solid-js@1.9.10.patch b/patches/solid-js@1.9.10.patch index e4e38c2e6840..b1ef007025a7 100644 --- a/patches/solid-js@1.9.10.patch +++ b/patches/solid-js@1.9.10.patch @@ -1,11 +1,5 @@ -diff --git a/Users/brendonovich/github.com/anomalyco/opencode/node_modules/solid-js/.bun-tag-6fcb6b48d6947d2c b/.bun-tag-6fcb6b48d6947d2c -new file mode 100644 -index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 -diff --git a/Users/brendonovich/github.com/anomalyco/opencode/node_modules/solid-js/.bun-tag-b272f631c12927b0 b/.bun-tag-b272f631c12927b0 -new file mode 100644 -index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/dist/dev.cjs b/dist/dev.cjs -index 7104749486e4361e8c4ee7836a8046582cec7aa1..0501eb1ec5d13b81ecb13a5ac1a82db42502b976 100644 +index 7104749..dc3eac9 100644 --- a/dist/dev.cjs +++ b/dist/dev.cjs @@ -764,6 +764,8 @@ function runComputation(node, value, time) { @@ -17,8 +11,33 @@ index 7104749486e4361e8c4ee7836a8046582cec7aa1..0501eb1ec5d13b81ecb13a5ac1a82db4 Transition.sources.add(node); node.tValue = nextValue; } else node.value = nextValue; +@@ -987,18 +989,21 @@ function cleanNode(node) { + } + } + if (node.tOwned) { +- for (i = node.tOwned.length - 1; i >= 0; i--) cleanNode(node.tOwned[i]); ++ const tOwned = node.tOwned; + delete node.tOwned; ++ for (i = tOwned.length - 1; i >= 0; i--) cleanNode(tOwned[i]); + } + if (Transition && Transition.running && node.pure) { + reset(node, true); + } else if (node.owned) { +- for (i = node.owned.length - 1; i >= 0; i--) cleanNode(node.owned[i]); ++ const owned = node.owned; + node.owned = null; ++ for (i = owned.length - 1; i >= 0; i--) cleanNode(owned[i]); + } + if (node.cleanups) { +- for (i = node.cleanups.length - 1; i >= 0; i--) node.cleanups[i](); ++ const cleanups = node.cleanups; + node.cleanups = null; ++ for (i = cleanups.length - 1; i >= 0; i--) cleanups[i](); + } + if (Transition && Transition.running) node.tState = 0;else node.state = 0; + delete node.sourceMap; diff --git a/dist/dev.js b/dist/dev.js -index ea5e4bc2fd4f0b3922a73d9134439529dc81339f..4b3ec07e624d20fdd23d6941a4fdde6d3a78cca3 100644 +index ea5e4bc..a2e2d59 100644 --- a/dist/dev.js +++ b/dist/dev.js @@ -762,6 +762,8 @@ function runComputation(node, value, time) { @@ -30,8 +49,33 @@ index ea5e4bc2fd4f0b3922a73d9134439529dc81339f..4b3ec07e624d20fdd23d6941a4fdde6d Transition.sources.add(node); node.tValue = nextValue; } else node.value = nextValue; +@@ -985,18 +987,21 @@ function cleanNode(node) { + } + } + if (node.tOwned) { +- for (i = node.tOwned.length - 1; i >= 0; i--) cleanNode(node.tOwned[i]); ++ const tOwned = node.tOwned; + delete node.tOwned; ++ for (i = tOwned.length - 1; i >= 0; i--) cleanNode(tOwned[i]); + } + if (Transition && Transition.running && node.pure) { + reset(node, true); + } else if (node.owned) { +- for (i = node.owned.length - 1; i >= 0; i--) cleanNode(node.owned[i]); ++ const owned = node.owned; + node.owned = null; ++ for (i = owned.length - 1; i >= 0; i--) cleanNode(owned[i]); + } + if (node.cleanups) { +- for (i = node.cleanups.length - 1; i >= 0; i--) node.cleanups[i](); ++ const cleanups = node.cleanups; + node.cleanups = null; ++ for (i = cleanups.length - 1; i >= 0; i--) cleanups[i](); + } + if (Transition && Transition.running) node.tState = 0;else node.state = 0; + delete node.sourceMap; diff --git a/dist/solid.cjs b/dist/solid.cjs -index 7c133a2b254678a84fd61d719fbeffad766e1331..2f68c99f2698210cc0bac62f074cc8cd3beb2881 100644 +index 7c133a2..5ef1501 100644 --- a/dist/solid.cjs +++ b/dist/solid.cjs @@ -717,6 +717,8 @@ function runComputation(node, value, time) { @@ -43,8 +87,33 @@ index 7c133a2b254678a84fd61d719fbeffad766e1331..2f68c99f2698210cc0bac62f074cc8cd Transition.sources.add(node); node.tValue = nextValue; } else node.value = nextValue; +@@ -938,18 +940,21 @@ function cleanNode(node) { + } + } + if (node.tOwned) { +- for (i = node.tOwned.length - 1; i >= 0; i--) cleanNode(node.tOwned[i]); ++ const tOwned = node.tOwned; + delete node.tOwned; ++ for (i = tOwned.length - 1; i >= 0; i--) cleanNode(tOwned[i]); + } + if (Transition && Transition.running && node.pure) { + reset(node, true); + } else if (node.owned) { +- for (i = node.owned.length - 1; i >= 0; i--) cleanNode(node.owned[i]); ++ const owned = node.owned; + node.owned = null; ++ for (i = owned.length - 1; i >= 0; i--) cleanNode(owned[i]); + } + if (node.cleanups) { +- for (i = node.cleanups.length - 1; i >= 0; i--) node.cleanups[i](); ++ const cleanups = node.cleanups; + node.cleanups = null; ++ for (i = cleanups.length - 1; i >= 0; i--) cleanups[i](); + } + if (Transition && Transition.running) node.tState = 0;else node.state = 0; + } diff --git a/dist/solid.js b/dist/solid.js -index 656fd26e7e5c794aa22df19c2377ff5c0591fc29..f08e9f5a7157c3506e5b6922fe2ef991335a80be 100644 +index 656fd26..6e0038c 100644 --- a/dist/solid.js +++ b/dist/solid.js @@ -715,6 +715,8 @@ function runComputation(node, value, time) { @@ -56,3 +125,28 @@ index 656fd26e7e5c794aa22df19c2377ff5c0591fc29..f08e9f5a7157c3506e5b6922fe2ef991 Transition.sources.add(node); node.tValue = nextValue; } else node.value = nextValue; +@@ -936,18 +938,21 @@ function cleanNode(node) { + } + } + if (node.tOwned) { +- for (i = node.tOwned.length - 1; i >= 0; i--) cleanNode(node.tOwned[i]); ++ const tOwned = node.tOwned; + delete node.tOwned; ++ for (i = tOwned.length - 1; i >= 0; i--) cleanNode(tOwned[i]); + } + if (Transition && Transition.running && node.pure) { + reset(node, true); + } else if (node.owned) { +- for (i = node.owned.length - 1; i >= 0; i--) cleanNode(node.owned[i]); ++ const owned = node.owned; + node.owned = null; ++ for (i = owned.length - 1; i >= 0; i--) cleanNode(owned[i]); + } + if (node.cleanups) { +- for (i = node.cleanups.length - 1; i >= 0; i--) node.cleanups[i](); ++ const cleanups = node.cleanups; + node.cleanups = null; ++ for (i = cleanups.length - 1; i >= 0; i--) cleanups[i](); + } + if (Transition && Transition.running) node.tState = 0;else node.state = 0; + }