refactor: redesign webview package as @microsoft/vscode-ext-webview#766
refactor: redesign webview package as @microsoft/vscode-ext-webview#766tnaum-ms wants to merge 62 commits into
Conversation
…Sink, BaseRouterContext)
…ain openAppWebview
…red, testing, and webview directories
…tions in README and migration manual
… [R766-N06] Adds an ADVANCED.md section showing the consumer-side Map<key, controller> + revealToForeground() + onDisposed() eviction pattern for single-instance panels, instead of building a panel registry into the transport package.
|
[R766-N06] — documented the create-or-reveal pattern ( Per the review, this stays consumer scope (a panel registry is consumer state, not transport state). Added a "Create-or-reveal (single-instance panels)" section to ADVANCED.md showing the few-line pattern using the returned controller handle: a |
…-operation listener [R766-S04] attachTrpc stamps each dispatch log entry with 'concurrent' (in-flight ops at completion) via a logProcedure wrapper; ProcedureLogEntry gains an optional concurrent field. DocumentDB rpcConcurrencyLogger forwards it into callWithAccumulatingTelemetry as a concurrentRpcOps distribution + dispatch counter (batched), wired via openAppWebview. Turns S04's 'revisit on evidence' into a real signal. Tests on both sides.
|
[R766-S04] — the per-operation listener is now measured, not guessed ( The design is unchanged (still one
Tests on both sides (package: |
Iteration 2 — summarySix review items shipped as individual commits (each pushed + commented above); one is deferred to Iteration 3.
Deferred to Iteration 3 — [R766-N05] (observer exceptions → telemetry): per the standing "options only" decision, not implemented. Two things are bundled and wait on one design decision — (1) the cheap correctness fix (isolate a throwing event-channel observer so it can't break the tRPC call it only observes), and (2) the telemetry-visibility hook (leaning: an opt-in Validation (all green): Motivation and rationale for every change are recorded inline in the PR review doc ( |
…erverError sink [R766-N05] createEventChannel always isolates a throwing onSuccess/onError/onAborted handler so it cannot break the tRPC call it observes, routing it to an onObserverError sink (default console.error). Threaded through connectTrpc + WithWebviewContext/hooks. Off by default in the happy path; DocumentDB opts in via reportObserverError (structured console.error + reportError() global elevation, no channel re-entry). README + ADVANCED document it; tests cover isolation, sink routing, default, and the DocumentDB sink.
|
[R766-N05] — event-channel observers are now isolated + an opt-in Implements option 1 from the review discussion. Previously a throwing
Validation: |
…observer-error sink [R766-N05]
reportError is declared in lib.dom (the webview tsconfig includes 'dom'), so the '(globalThis as { reportError?: ... })' cast was unnecessary. Call globalThis.reportError directly behind the same typeof guard. No behavior change; the DOM reportError() global is unrelated to the app router's reportError tRPC mutation.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 92 out of 99 changed files in this pull request and generated 3 comments.
Comments suppressed due to low confidence (1)
src/webviews/_integration/useTrpcClient.ts:20
useTrpcClientis a shared helper used across the webview codebase; giving it an explicit return type makes the public surface clearer and avoids accidental type widening if the framework hook signature changes.
…back as Iteration 4 Iteration 3: R766-N05 (event-observer isolation) was implemented after the iter-2 batch but recorded inconsistently (folded into iter-2, while the options section still said 'deferred to iter-3'). Give it its own chapter: what shipped (option 1 always-on isolation + opt-in onObserverError sink; DocumentDB opts in via reportObserverError), the change protocol (7622703 / 559a9af / f7c9656, jest 2661/159), the reportError DOM-global-vs-tRPC-mutation naming clarification, and the deferred host-telemetry route. Reconcile the iter-2 'Still open' table, protocol table, wrap-up, and N05 options blockquote to point at Iteration 3. Iteration 4: triage the GitHub Copilot reviewer's 2026-07-05 pass (review 4630986353) as R766-C01..C04 with detailed options and recommendations (analysis only, not yet implemented): C01 telemetry middleware stamps error fields on aborted calls; C02 the DocumentDB runner re-stamps them (pairs with C01); C03 tighten the webview onReceive guard to an own string id (refines R766-N01); C04 explicit return type on useTrpcClient (suppressed). Also brings the doc into prettier compliance (the committed version was failing prettier; tables are now column-aligned).
…PC calls [R766-C01][R766-C02] R766-C01 (package): telemetryMiddlewareBody gated the 'Failed' result on !aborted but still stamped error/errorMessage for an aborted call that surfaced as a rejected result, so a cancellation looked like a failure on the error dimension. Gate the whole error-recording block on !aborted (option A): an aborted call is now recorded only as 'Canceled' (aborted='true') with no error* fields. Also export getInvocationSignal from ./host so consumers can share the abort check. Adds a regression test (aborted invocation that also throws -> no error* fields). R766-C02 (documentdb): documentDbTelemetryRunner ran its parseError enrichment (error/errorMessage/errorStack/errorCause) for any !result.ok, on the same telemetry bag, after the body -- so it re-stamped error fields and silently undid C01 for canceled ops. It now reads getInvocationSignal(invocation.ctx)?.aborted and skips enrichment when aborted (option B). Shipped with C01 so both telemetry layers agree. Also marks R766-C01/C02 implemented in the review doc.
…onse guard [R766-C03] The webview onReceive guard added in R766-N01 forwarded any object with an `id` property, including an inherited (prototype) `id` and a non-string `id` -- looser than the host-side isTransportRequestMessage guard (which already checks typeof id === 'string'). Add a shared isTransportResponseMessage type guard to shared/wireProtocol.ts (non-null object with its OWN string `id`, via Object.hasOwn + typeof) and use it in connectTrpc's onReceive, restoring host/webview symmetry and a single source of truth for the response shape (option C). Extend the R766-N01 test with a numeric-id case and an inherited-id case (whose id equals the pending request id, so the old guard would have resolved the query with undefined before the real response arrived). Also marks R766-C03 implemented in the review doc.
…n type [R766-C04] The DocumentDB useTrpcClient wrapper had an inferred return type. Declare it explicitly as TrpcClient<AppRouter> (imported from @microsoft/vscode-ext-webview/react), which locks the public surface, guards against accidental type widening if the framework hook signature changes, and matches the repo TypeScript guideline of always specifying return types. This was the Copilot reviewer's low-confidence (self-suppressed) comment. Also marks R766-C04 implemented in the review doc.
All four Copilot findings are implemented; add the Iteration 4 change-protocol table (C01/C02 -> 553bf4e, C03 -> 3301a70, C04 -> 19b99cb) and flip the chapter intro from "nothing implemented yet" to implemented. Records the green validation run (l10n no drift, prettier, eslint, jest 2662/159, tsc build).
Iteration 4 — Copilot feedback addressedAll four findings from the 2026-07-05 Copilot review are implemented on
The three inline threads (C01 / C02 / C03) have been replied to and resolved. C04 was self-suppressed and had no thread, hence this summary note. C01 and C02 shipped in one commit because C02's enrichment would otherwise undo C01. Validation (all green): |
The Iteration 4 chapter ended on the "Suggested batching" recommendations. Add a closing "Iteration 4 — done" section that lists the steps performed (triage, Batch 1 C01+C02 553bf4e, Batch 2 C03 3301a70, Batch 3 C04 19b99cb, doc finalize cb9cd3b, green validation) and a clear completion message, and reword the batching close to past tense.
…mics and onboarding
…ot extension mode The redesign chose the bundled-vs-dev source layout from extensionMode === Production, but the dev server (webpack serve) emits the bundled asset name (views.js). A webpack-bundled extension running in Development (the normal F5 dev flow, IS_BUNDLE=true, DEVSERVER=true) therefore requested the tsc dev file (index.js) from the dev server and got a 404, leaving the webview blank. Restore the pre-redesign contract: a required isBundled option drives the layout; extensionMode stays CSP-only. The DocumentDB consumer passes isBundled: git commit -q -F /tmp/done-msg.txt && git push -q origin HEAD && echo pushed && git --no-pager log -1 --format='%h %s'ext.isBundle. Adds regression tests.
…ubfolder Move rpcConcurrencyLogger (host) and reportObserverError (webview), plus their tests, into src/webviews/_integration/observability/ so the reference integration folder separates the router/transport wiring from the cross-cutting observability adapters. Update imports, the two external importers, the folder README, and add observability/README.md. No runtime behavior change.
…tion 7 (_integration observability regrouping)
✅ Code Quality Checks
This comment is updated automatically on each push. |
📦 Build Size Report
Download artifact · updated automatically on each push. |
Summary
Redesigns the webview RPC package: replaces
@microsoft/vscode-ext-react-webviewwith a new@microsoft/vscode-ext-webview(0.9.0-preview) built around four side-aware subpaths and composable primitives, migrates the extension onto it, and removes the old package.What changed
@microsoft/vscode-ext-webviewwith four subpaths:.(shared, novscode/react),./host,./webview,./reactopenWebviewfactory + options-bagWebviewController,attachTrpc(bring-your-own-panel),connectTrpc,initWebviewTrpc, and telemetry middleware bodies (telemetryMiddlewareBody/loggingMiddlewareBody) wired through a consumer-suppliedTelemetryRunneradapter.useTrpcClient()returns the client directly;useRpcEvents()exposes the event channel.createMiddleware,TelemetryContext, the olduseTrpcClienttuple return,UseTrpcClientOptions._integrationlayer and panel controllers moved onto the new package; construction-only panels now use anopenAppWebviewfactory preset (the oldWebviewControllerBaseis gone).@microsoft/vscode-ext-react-webviewpackage and all references.README.md+ADVANCED.md, plus an internal migration manual.Validation
Whole-repo lint clean, full Jest suite green (2571 tests / 146 suites), and
npm run buildgreen.Draft for review.