Repository navigation
Feat/session aware plot viewer - #1932
Conversation
- Bind standard plot viewers to their originating R sessions - Add JGD session selection and isolate resize requests by device - Restore httpgd connections and request standard plots from live sessions - Persist JGD frames and selection for reload restoration - Add session isolation and restoration tests
Give each JGD session its own viewer and remove the session dropdown. Keep history, navigation, resize, and text measurement scoped to each session, and restore separate viewers after VS Code reload. Avoid redundant plot requests and toolbar updates, and prevent httpgd restoration from overwriting newer connection credentials.
Reuse the list/data viewer indicator in standard, httpgd, and JGD viewers, showing R <version>: <PID> on hover or keyboard focus. Preserve session identity across reloads, handle late attachments, and update indicators when the owning R process exits.
- Persist restoration state during normal operation - Preserve live R plot state and reconnect JGD devices with stable identities - Limit Show Viewer to the active session and prevent duplicate or empty tabs - Keep closed viewers closed during reattachment across all plot engines - Bump sess to 3.4.0.9001 - Add session isolation and live reconnection regression tests
… session disconnects, without showing shutdown-related error popups.
This reverts commit 053acbd.
- Preserve saved httpgd credentials when loading fails and report the error - Stop selecting an arbitrary restored JGD device - Always send JGD session identity metadata - Remove the unbound standard viewer and unused history/resize code - Bump sess to 3.4.0.9005 Validated all three plot backends across repeated VS Code reloads.
- Refresh open standard plot viewers after sess reconnect without reopening closed panels - Fetch the latest standard plot when showing an existing viewer - Retain httpgd viewport changes during disconnects and ignore stale render dimensions - Preserve httpgd divider height when reopening in a resized editor group - Restore JGD devices using captured dimensions and DPI without hardcoded defaults - Add regression coverage for reconnects, device settings, and both httpgd layouts
- Share plot ownership, viewer reuse, and exit cleanup across engines - Delete in-memory history and saved state on permanent R exit while leaving rendered plots and viewer tabs untouched - Preserve restoration across VS Code reloads and live R reconnects - Combine httpgd devices into one viewer with collision-safe plot IDs and device-specific rendering, export, and deletion - Coalesce httpgd refreshes, discard stale responses, and avoid rerendering inactive devices at new sizes - Discover explicit httpgd devices without taking lifecycle ownership - Prevent commands from ended viewers from targeting another session - Add regression coverage for cleanup, device reuse, and restoration - Remove legacy html/httpgd files replaced by src/plotViewer/webview - Remove unused getNewestViewer method and MaybePromise type - Remove write-only plotWidth and plotHeight viewer fields - Update the shared webview message types comment Validation: 152 VS Code tests and 20 Node tests passed; build, type checking, lint, and formatting passed.
Remove incorrect viewer identification derived from resource URLs. Route toolbar actions to the focused live viewer without falling back to another session when an ended session's tab remains open. Add regression coverage for consecutive httpgd plots and toolbar command routing. Validation: real toolbar clicks and 152 regression tests passed.
…ation - Refresh changed inactive plots while reusing unchanged cached content - Isolate failed plot fetches and avoid redundant retries - Defer httpgd restoration notifications until runtime setup completes - Add regression coverage for stale plots, fetch failures, and cleanup
- Restore interleaved plot history using saved ordering metadata - Switch to the next available server when the selected device closes - Avoid resize errors after the last device closes - Fix divider jumps caused by the session header - Add live R and VS Code regression coverage
- Persist httpgd SVGs, plot order, selection, and hidden plots - Preserve navigation and SVG export after devices close - Refresh annotations on previous and hidden plots - Keep restored thumbnails in session timeline order - Align JGD and httpgd viewer reopening behavior - Consolidate received SVGs into one authoritative collection - Clean up retained content and credentials on confirmed R exit - Add lifecycle regression tests and dedicated cross-platform CI - Require live R test dependencies and enable CI for master Validated with 198 extension tests, 38 Node tests, compilation, lint, formatting, and manual httpgd/JGD lifecycle checks.
- Update JGD fixtures for device tracking and session metadata - Use Windows-compatible interactive R flags in plot tests - Handle connection resets and cleanup in HTTP recovery tests - Install libtiffxx6 on Linux and expose dependency load errors
There was a problem hiding this comment.
Reviewed with ChatGPT.
I found several issues and would like to request changes before merging.
-
Unbounded plot history storage
- JGD drawing operations and httpgd SVG data are persisted in
workspaceState, but there appears to be no limit on the serialized data size. - Complex plots or long sessions could result in excessive storage usage. Please consider a storage size limit or a separate cache mechanism, and add tests for large plot histories.
- JGD drawing operations and httpgd SVG data are persisted in
-
Plot commands may target another session
CommonPlotManager.activeViewerfalls back to the most recently used JGD or httpgd viewer without checking whether it belongs to the active R session.- Commands invoked without an explicit viewer target could therefore operate on another session's plot history. Please ensure the fallback respects session ownership.
-
CI and test configuration changes
.github/workflows/main.yml: Addingmasterto the workflow triggers seems unrelated to this PR. Please revert it.- Installing
libtiffxx6on Linux appears justified by theunigddependency. But using r-lib action seems better than this. - Verifying R package availability and setting
VSCR_REQUIRE_PLOT_TESTS=1are reasonable ways to ensure the live plot tests are actually executed. .vscode-test.mjs: Separating plot lifecycle tests into their own VS Code test profile is reasonable because these tests manipulate global extension state. However, manually maintaining theplotSuitesfilename list could lead to newly added tests being omitted. Please consider a more maintainable way to group these tests.
-
Overly broad error handling in
R/tests/attach_sess.R- The modified
readLines()handler suppresses all errors rather than only handling files that have disappeared. - Please revert this change unless it is necessary. If Windows file locking requires retries, please handle only the expected transient errors and explain why this change belongs in this PR.
- The modified
-
Questionable synchronization in
sessionTerminalLifecycle.test.ts- Calling
fsp.readFile()while advancing fake timers does not guarantee completion of the original asynchronous operation. - Please check whether limiting the fake timers to
setTimeout,clearTimeout, andDateis sufficient. If additional synchronization is needed, please use an explicit mechanism rather than relying on unrelated filesystem activity.
- Calling
-
Implementation-dependent test in
sessionTerminalIntegration.test.ts- Spying on
fsp.rename()couples the test to the file publication implementation rather than its observable behavior. - Please consider retaining the original behavior-based assertion, with narrowly scoped handling for transient Windows file access errors if necessary.
- Spying on
The new plot-specific tests provide useful coverage, and I am not suggesting removing them. My concern is primarily with unrelated changes to existing tests and CI configuration that may be working around timing issues without addressing their underlying causes.
Please address the first two issues and reconsider the unrelated CI and test modifications. If any of those modifications are necessary, please explain the underlying failures and why the proposed changes are appropriate.
renkun-ken
left a comment
There was a problem hiding this comment.
Reviewed commit 9eb31681e877f271a5ddd7f9592882afae270349. I found two additional reproducible device-lifetime regressions in the reload/reconnect path; details are inline.
- JGD restoration can process a stale closed-device registration after a live device is reopened into its number, overwriting the closed device's retained plot and redirecting subsequent plots to its logical identity.
- Standard restoration retains a numeric null-device ID and ownership registration across disconnection, allowing a caller-created PDF that reuses that number to be captured and later closed by sess.
Validation: compilation and TypeScript checks passed; all 28 focused Node/live-R tests and all 199 plot-lifecycle extension tests passed locally on macOS (VS Code 1.145.2). I also reproduced the two uncovered cases with live R; the standard case was compared with the base revision. All six hosted checks are green on this head.
Please add regression coverage for these device-reuse cases and fix the restoration ownership checks before merging.
Move JGD frames and httpgd SVGs out of workspaceState into a shared 256 MiB persistent cache. Retain restoration metadata in workspaceState, migrate existing histories, and evict older cached plots. Add coverage for size limits, eviction, migration, missing files, and restoration.
Match untargeted plot commands by session ID, host, and PID. Do nothing when no matching viewer exists, while preserving focused viewer and explicit-target routing. Add regression tests for cross-session routing and session identity reuse.
- Replace manual R and Linux plot dependency installation - Move plot suites into a dedicated directory for discovery - Remove unrelated master triggers - Preserve mandatory live plot dependency checks
Replace filesystem pacing with a controlled startup-file stub and deferred synchronization. Preserve restricted fake timers and real readiness and IPC behavior.
… assertions. Avoid Windows read/replacement races while preserving pending-PID coverage.
Filter live JGD registrations before reopening devices. Use lifetime markers to prevent capture or closure of replacement PDFs. Add regressions for reconnect identity and device-number reuse.
renkun-ken
left a comment
There was a problem hiding this comment.
Reviewed the changes through 3ec8a47636baa8e98ee2ad63eac53a78fa1de7ec.
Both of my earlier device-reuse findings are fixed. I reran the original live-R reproductions: JGD retains the survivor's logical key, and the caller-owned standard PDF is neither captured nor closed. The active-session command fallback now checks session ID, host and PID. The CI/test grouping and synchronization changes also address the earlier review requests.
I found one remaining P2 in the new disk cache: replacing a plot can evict unchanged history even when the final checkpoint fits the byte budget. I also reproduced a smaller P3 startup race that misses checkpoint cleanup when R exits during asynchronous history loading. Details are inline.
Validation: compilation/typechecking passed; 39 focused Node/live-R/cache tests, 208 plot-lifecycle extension tests, 88 session/terminal extension tests and 62 focused R assertions passed locally. All six hosted checks are green on this head. The two new cases are not covered by those tests.
Please fix the cache replacement eviction before merging and add regression coverage for both cases.
…eanup Reclaim superseded payloads before evicting retained plots. Observe JGD history changes before asynchronous httpgd initialization. Add regression coverage for full-quota replacement and R exit during startup.
renkun-ken
left a comment
There was a problem hiding this comment.
Reviewed 7fba664714773dfc0afa952e9ce307b76d7caf38. Both remaining findings are resolved, and I reran their original reproductions successfully.
The cache now computes the complete retained-reference set before writing replacement payloads, reclaims superseded content first, and preserves references belonging to the other backend. Equal-sized replacement at a full quota retains both current plots. JGD checkpoint observation is now installed before httpgd initialization yields, so an R exit during startup removes both saved metadata and payloads.
I found no additional actionable issues in the follow-up diff. Compilation/typechecking, all 41 focused Node/live-R/cache tests, and all 209 plot-lifecycle extension tests passed locally on macOS. All six hosted checks are green on this head.
eitsupi
left a comment
There was a problem hiding this comment.
Reviewed the latest changes with ChatGPT (7fba664).
Most of my previous concerns appear to have been addressed. The plot history now uses a size-limited disk cache, command fallback respects session ownership, and the unrelated workflow trigger and overly broad error handling have been reverted. Moving the plot tests into a dedicated directory also resolves the test grouping concern.
I have two remaining observations:
-
CI dependency installation
The switch to
r-lib/actions/setup-r-dependenciesis reasonable, especially because it handles Linux system dependencies automatically.However, with
working-directory: sess, the action installs all dependencies fromsess/DESCRIPTION, includingSuggests, plus the six explicitly listedextra-packages. The subsequentpnpm run buildstill callsremotes::install_local(..., dependencies=TRUE, force=TRUE).This seems somewhat redundant. Could we review whether all six extra packages are still needed, particularly
renv, and whether dependency installation can be simplified without losing test coverage?I would not suggest switching directly to
dependencies: "hard", since the plot tests require packages listed underSuggests. -
Test synchronization
The changes to
sessionTerminalLifecycle.test.tsare an improvement, particularly the explicit control over startup-file reads.However,
waitForTimerDelay()and several other tests still callfsp.readFile()while waiting for fake timers and asynchronous operations to settle. These reads do not directly synchronize with the operations being tested.It would be preferable to use explicit synchronization or controlled filesystem mocks consistently, rather than relying on additional filesystem activity to advance the event loop.
These are primarily maintainability concerns rather than confirmed functional regressions. I am leaving them as comments rather than requesting changes.
|
Thanks for all the reviews and suggestions. The Now the installation split the existing build into two steps.
|
Requested changes were addressed. Reviewer confirmed in their subsequent comment.
|
Why did you merge it before I reviewed it? @renkun-ken Is it possible to restrict the merge method to squash merge only? (I don't have permission to change the settings.) |
I thought the final comments cleared the past commits, and further changes just small CI improvements and passed all the tests. That was my mistake. |
I've done the following changes:
|
|
Thanks! |

Closes #1780
Summary
This PR makes standalone R plot viewers session-aware across the JGD, httpgd, and standard backends. Plots remain associated with their originating R process, multiple devices share their session’s history, and retained plots can be reopened after VS Code reloads while R remains running.
New features
What changed
Fixes
Testing