fix(vscode): blank preview panel on VSCode 1.116 (#2361)#2372
Merged
markscott-ms merged 7 commits intofinos:mainfrom Apr 28, 2026
Merged
Conversation
Calling panel.reveal() on a webview panel that createWebviewPanel just created causes a blank first paint on VSCode 1.116+. createWebviewPanel already shows the panel, so the extra reveal() is redundant and races with the compositor. Adds a revealPanel option to CalmPreviewPanel.reveal() so the brand-new panel path skips the extra call; the reuse path is unchanged. Regression guards: - Unit test asserts panel.reveal() is not called on brand-new panels and is called on reuse. - Integration test harness (@vscode/test-electron + Xvfb on CI) runs a matrix across 1.115.0, 1.116.0, and stable, using a rAF-based paint probe that catches compositor stalls. - Self-validation test creates a standalone webview with the original buggy pattern and asserts the probe returns rendered=false on 1.116 and rendered=true on 1.115 — proves the probe works remotely and isn't silently passing or false-positiving.
tsup fails to resolve @finos/calm-shared / @finos/calm-models in CI because the integration-test job skipped `build:shared`. Mirrors the pattern used by test:vscode and package:vscode.
Contributor
There was a problem hiding this comment.
Pull request overview
Fixes a VS Code 1.116+ regression where the CALM Preview webview can appear blank on first open due to an extra panel.reveal() call racing the compositor, and adds layered regression tests (unit + real VS Code integration) to prevent recurrence.
Changes:
- Avoid calling
WebviewPanel.reveal()when creating a brand-new CALM preview panel; keep reveal behavior for panel reuse. - Add a webview “paint probe” (
ready+ rAF-gatedrendered) and expose a small test-only API fromactivate()for integration tests. - Introduce
@vscode/test-electronintegration test harness + CI matrix across multiple VS Code versions.
Reviewed changes
Copilot reviewed 17 out of 18 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
calm-plugins/vscode/src/features/preview/preview-panel.ts |
Skips panel.reveal() on newly created panels; wires new rendered message handling. |
calm-plugins/vscode/src/features/preview/commands.ts |
Adds rendered webview message type + command. |
calm-plugins/vscode/src/features/preview/webview/panel.view-model.ts |
Posts ready and rAF-based rendered signals from the webview. |
calm-plugins/vscode/src/features/preview/preview.view-model.ts |
Tracks rendered state and emits onRenderedStateChanged for tests. |
calm-plugins/vscode/src/test-api.ts |
Adds test-only API used by integration tests to await ready/rendered. |
calm-plugins/vscode/src/extension.ts |
Makes activate() async and returns the test API for integration tests. |
calm-plugins/vscode/src/calm-extension-controller.ts |
Stores PreviewPanelFactory and provides getTestApi() for integration tests. |
calm-plugins/vscode/src/features/preview/preview-panel.spec.ts |
Adds unit regression tests ensuring reveal() is not called on first create, but is on reuse. |
calm-plugins/vscode/test/integration/* |
Adds Mocha-based @vscode/test-electron harness + regression/self-validation suites. |
calm-plugins/vscode/vitest.config.mts |
Excludes test/integration/** from vitest runs. |
calm-plugins/vscode/package.json |
Adds integration test scripts + dev dependencies (@vscode/test-electron, mocha, glob, types). |
.github/workflows/build-vscode-extension.yml |
Splits workflow into build/test, integration matrix, then package/publish. |
package-lock.json |
Lockfile updates for new dev dependencies. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
- Use vscode.version (runtime) instead of VSCODE_VERSION env var for paint-probe self-validation assertions. The env var holds the matrix label (e.g. "stable") and doesn't reflect the actual version under test. - Reset isRendered to false when the preview panel is disposed. The PreviewViewModel outlives individual CalmPreviewPanel instances; without this reset a stale rendered=true from a prior panel would mask a new blank-paint regression on reopen.
- Retry runTests() once in runTest.ts to survive transient CDN timeouts when @vscode/test-electron resolves the 'stable' version tag. - Mark the 'stable' matrix entry as continue-on-error: it's an early warning for upcoming VSCode releases, not a hard gate. Pinned versions (1.115.0, 1.116.0) remain required.
markscott-ms
requested changes
Apr 23, 2026
Contributor
markscott-ms
left a comment
There was a problem hiding this comment.
Tested on VSCode 1.117.0 / Windows.
Contributor
|
Also, @LeighFinegold notes in #2361 that VSCode 1.117 does not need this fix, i.e. it was a compatibility issue with 1.116 only. |
markscott-ms
approved these changes
Apr 28, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Fixes #2361.
On VSCode 1.116+, opening the CALM Preview shows a blank pane until the user covers/uncovers it or otherwise forces a relayout. Root cause:
CalmPreviewPanel.createOrShowcallspanel.reveal()on a webview panel thatvscode.window.createWebviewPaneljust created.createWebviewPanelalready shows the panel; the extrareveal()races with the compositor and stalls the first paint.CalmPreviewPanel.reveal()gains an optionalrevealPanelflag; brand-new panels are initialized withrevealPanel: false, the reuse path is unchanged.Regression guards (triple-layered):
panel.reveal()is NOT called on brand-new panels and IS called on reuse. Fails on the pre-fix code, passes on the fix. This is the structural guard.@vscode/test-electron) — newtest/integration/harness launches a real VSCode instance (Xvfb on Linux CI), opens the preview against a fixture, and probes the webview with arequestAnimationFrame-gatedrenderedmessage. A stalled compositor means rAF never fires → probe returnsfalse→ test fails. Matrix runs across1.115.0,1.116.0, andstable.test/integration/suite/paint-probe-validation.test.tscreates a standalone webview inside the test (not the CALM extension) that deliberately reproduces the pre-fix buggy pattern. Assertsrendered=falseon 1.116 (proves probe catches the stall) andrendered=trueon 1.115 (proves probe doesn't silently false-positive under Xvfb). This verifies the probe itself is trustworthy on the remote runner — without this, a passing main test could hide a broken probe.Type of Change
Affected Components
Commit Message Format ✅
Testing
Local 2×2 matrix (rerun with and without the fix, against both VSCode versions):
Unit test suite: 375 passing (including 2 new regression tests in `preview-panel.spec.ts`).
Checklist
Notes for reviewers
vscode.window.createWebviewPanelcall.activate()now returns a small test-only API (src/test-api.ts) exposingwaitForPreviewReady/waitForPreviewRenderedfor integration tests. Not intended for runtime use by other extensions.