ソースを参照

web: fix log window dying after close (onClosed compared win objects)

Repro: open log window → close → reopen: nothing appears. 'Refresh'
(page reload) worked because the orphaned server stream was still
alive and the fresh attach reused it.

Root cause: the log window's onClosed looked the entry up in logWins
with 'x.win === win' — but 'win' there is makeWin's return object
{win, body}, while logWins stores the section element (win.win).
The compare was always false, so close never called detachLog:
- the logWins entry stayed behind → the re-open click hit openLog's
  'window already open' guard, 'fronted' the detached element
  (invisible) and returned — no new window;
- the server-side stream was never deleted → orphaned SSH streams
  (MAX_ATTACHES=8 eventually refused new opens).
Same bug in the container-select onchange closure. Both now compare
win.win.

Playwright +2 regression checks (close removes / re-open shows a
fresh window). Live-verified on dgx1: 203 lines → close → reopen
201 lines, clean note.
Alexander Korolev 2 ヶ月 前
親
コミット
0949d63f47
2 ファイル変更、12 行追加、2 行削除
  1. 2 2
      src/web/ui.html
  2. 10 0
      src/web/ui.playwright.mjs

+ 2 - 2
src/web/ui.html

@@ -842,7 +842,7 @@ async function openLog(cluster, node, recipe) {
     extraCls: "logwin",
     removeOnClose: true,
     onClosed: () => {
-      const w = [...logWins.entries()].find(([, x]) => x.node === node && x.cluster === cluster && x.win === win);
+      const w = [...logWins.entries()].find(([, x]) => x.node === node && x.cluster === cluster && x.win === win.win);
       if (w) detachLog(w[0]);
     },
   });
@@ -866,7 +866,7 @@ async function openLog(cluster, node, recipe) {
   if (n.containers.length) sel.value = recipe;
   sel.onchange = async () => {
     if (!sel.value) return;
-    const cur = [...logWins.entries()].find(([, x]) => x.win === win);
+    const cur = [...logWins.entries()].find(([, x]) => x.win === win.win);
     if (cur) detachLog(cur[0], false); // drop the old stream, keep this window
     await attachLog(w, sel.value);
   };

+ 10 - 0
src/web/ui.playwright.mjs

@@ -237,6 +237,16 @@ ok(
   "logs button on an already-open node fronts, not duplicates",
   (await page.locator(".logwin").count()) === 1,
 );
+// Regression (win-vs-object compare in onClosed): close used to leave the
+// logWins entry behind, so the re-open click just 'fronted' the detached
+// window and nothing appeared.
+await page.click(".logwin .wbtn[data-act=close]");
+ok("closing a log window removes it", (await page.locator(".logwin").count()) === 0);
+await page.click("#clusters .node .logsbtn");
+ok(
+  "re-open after close shows a fresh window",
+  (await page.locator(".logwin").count()) === 1,
+);
 
 // --- 13. raw window (via the dock + new-window menu) -------------------------------
 await page.click("#dock .plus");