Skip to content

Harden webview panel lifecycle and restore panels across window reloads - #886

Open
chrisdp wants to merge 1 commit into
masterfrom
webview-panel-hardening
Open

Harden webview panel lifecycle and restore panels across window reloads#886
chrisdp wants to merge 1 commit into
masterfrom
webview-panel-hardening

Conversation

@chrisdp

@chrisdp chrisdp commented Aug 29, 2026

Copy link
Copy Markdown
Collaborator

What

Hardens the shared webview base class's popped-out-panel lifecycle and lets panels survive a window reload.

  • Fixes a crash posting to a closed panel. vscode.WebviewPanel.webview throws synchronously ("Webview is disposed") once the panel is disposed. postMessage previously resolved the webview outside its try/catch, so a device event arriving after the user closed a popped-out panel (e.g. the SceneGraph Inspector's) threw instead of queueing the message.
  • Clears the stored panel on dispose. this.panel was never cleared when the user closed the tab, so the provider kept posting at (and trying to reveal) a dead panel forever.
  • Panel restore across window reloads. New opt-in enablePanelRestore() registers a WebviewPanelSerializer so a popped-out panel comes back after a reload, paired with an onWebviewPanel:<id> activation event (same pattern as the existing onWebviewPanel:rceVideoView). The SceneGraph Inspector adopts it.
  • retainPanelContextWhenHidden — providers can opt their panel flavor into retainContextWhenHidden when re-rendering from scratch on tab switch is too costly.
  • Dev-watcher fix: the html live-reload watcher targeted this.view.webview unconditionally and NPE'd when only a panel was open; it now targets (view ?? panel).
  • webviewContext: the index.html template now exposes window.webviewContext ('sidebar' | 'panel') so a view can persist state or behave differently per surface. Defaults to 'sidebar', so existing views are byte-for-byte unaffected.

Why now

The SceneGraph Inspector already ships an "open in panel" command, so the disposed-panel crash and the missing restore are user-visible today. The rest is groundwork any future panel-capable view gets for free.

Testing

  • tsc --noEmit, eslint: clean.
  • Full unit suite: 1304 passing, 0 failing (registerWebviewPanelSerializer added to the vscode mock).
  • To verify manually: pop out the SceneGraph Inspector, close the tab while device events stream (previously threw "Webview is disposed"; now the messages queue), and reload the window with the panel open (it now restores).

🤖 Generated with Claude Code

- postMessage resolves the webview inside try/catch: touching .webview
  on a disposed panel throws synchronously, so a device event arriving
  after the user closes a popped-out panel (e.g. the SceneGraph
  Inspector) crashed instead of queueing.
- attachPanel() extracted from createOrRevealWebviewPanel; the panel's
  onDidDispose now clears the stored reference so a closed panel can't
  be posted to or revealed again.
- enablePanelRestore(): providers can opt into a WebviewPanelSerializer
  so their popped-out panel survives a window reload (paired with an
  onWebviewPanel activation event). SceneGraph Inspector adopts it.
- retainPanelContextWhenHidden: opt-in retainContextWhenHidden for the
  panel flavor of a view.
- The dev-mode html reload watcher targets (view ?? panel) instead of
  assuming the sidebar view exists.
- The index.html template exposes webviewContext ('sidebar' | 'panel')
  so a view can persist/behave differently per surface; defaults to
  'sidebar' so existing views are unaffected.
@chrisdp chrisdp added the bug label Aug 29, 2026
@chrisdp
chrisdp requested a review from TwitchBronBron August 29, 2026 18:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant