Skip to content

test(xterm): pre-#617 kolu + observer-nullify on latest xterm master#668

Draft
srid wants to merge 1 commit intomasterfrom
test/pre617-nullify
Draft

test(xterm): pre-#617 kolu + observer-nullify on latest xterm master#668
srid wants to merge 1 commit intomasterfrom
test/pre617-nullify

Conversation

@srid
Copy link
Copy Markdown
Member

@srid srid commented Apr 23, 2026

Why this branch exists

The original #617 repro — 30× Focus↔Canvas sidebar mode toggle with 7 terminals, producing +367 MB / 30 toggles on pureintent — isn't reproducible on kolu master anymore because #622 made the workspace mode-less (no sidebar toggle, unified infinite canvas).

So to answer jerch's question on xtermjs/xterm.js#5821does the observer-nullify variant defuse the retention as effectively as WeakRef? — I need the exact same kolu state that #617 was measured against, only with the observer-nullify fork spliced in instead.

This branch does that:

No WeakRef anywhere in the IntersectionObserver callback lineage.

Three-arm result

All three arms share the same kolu UI (pre-#622, sidebar toggle alive). The MCP Chrome measurement used fresh just dev runs, clean .kolu-dev where needed, 7 terminals created/restored through the UI, and 30 Focus↔Canvas round trips via the visible header toggle.

Arm kolu ref xterm override xterm buffer retention Δ / 30 toggles
A — unpatched baseline 1b18af1^ juspay/xterm.js#fix/dispose-leaks-built (pre-#5821) Uint32Array +339, JSArrayBufferData +339
B — WeakRef (merged fix) 1b18af1 juspay/xterm.js#fix/kolu-xterm-fixes-built (dispose-leaks + WeakRef) Uint32Array +0, JSArrayBufferData +0
C — observer-nullify (this PR) this branch juspay/xterm.js#test/kolu-nullify-on-latest-master-built (upstream master + nullify) Uint32Array +0, JSArrayBufferData +0

Heap snapshot self-size deltas were noisy because DevTools itself retained other frontend objects during the run, but the xterm buffer signature is the important signal here:

Arm Heap snapshot self Δ JSArrayBufferData bytes Δ Uint32Array count Δ
A — unpatched baseline +34.2 MB +0.8 MB +339
B — WeakRef +40.8 MB +0.0 MB +0
C — observer-nullify +40.7 MB +0.0 MB +0

Caveat: this MCP run reproduced the leak signature on A, but not the original +367 MB magnitude because the clean UI-created/restored terminals only had ~118 rows of scrollback rather than the large restored buffers from the pureintent measurement.

Answering jerch

Observer-nullify defuses the same xterm buffer retention leak as the merged WeakRef fix. In the same Chrome DevTools MCP methodology, the unpatched baseline retained new xterm buffer arrays after 30 toggles, while both WeakRef and observer-nullify retained zero additional xterm buffer arrays.

That means the upstream PR can be simplified to the observer-nullify variant without relying on WeakRef in the IntersectionObserver callback lineage.

Rollback

Not for merge. Close after data is collected. The real outcome lands as a change on #5821.

Refs xtermjs/xterm.js#5821, #617, #620, #652, #653

The original #617 repro — 30× Focus↔Canvas sidebar mode toggle with
7 terminals — no longer exists in current kolu master because #622
made the workspace mode-less. To re-run that exact repro with the
observer-nullify variant instead of WeakRef, this branch rewinds
kolu to the parent of #617's merge commit (where the sidebar toggle
still exists) and bumps the xterm override to latest upstream master
stacked with just the nullify patch:

    juspay/xterm.js#test/kolu-nullify-on-latest-master-built
      = xtermjs/xterm.js@32553b41 + observer-nullify

The branch does NOT carry the WeakRef fix that landed in #5821 /
#617. The IntersectionObserver callback uses a strong `this` capture;
the observer is stored on `this._observer` and nulled on dispose.

Test plan (on your real Chrome, not chrome-devtools MCP):

  1. Check out this branch, `just dev`
  2. Restore 7 terminals
  3. Toggle 30× between Focus and Canvas sidebar mode (Ctrl+Shift+C
     or the sidebar icon)
  4. Chrome Task Manager: note Memory Footprint Δ

Arm cross-reference:
  - Arm A (unpatched baseline):   git checkout 1b18af1^
  - Arm B (WeakRef, #617 merged): git checkout 1b18af1
  - Arm C (observer-nullify):     this branch

Expected per #617: Arm A +367 MB / 30 toggles, Arm B ~0 MB. The open
question Arm C answers: does observer-nullify defuse the retention
as effectively as WeakRef?

Not for merge. Data collection only.

Refs xtermjs/xterm.js#5821, #617, #652, #653
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant