fix: unbreak the login webview shipped in 2.5.0 - #179
Open
ashishrp-aws wants to merge 1 commit into
Open
Conversation
Two defects compound into the black login view with "Error: Webview error" that customers hit on IdC sign-in in 2.5.0. Diagnosed from the extension log of a live repro: the logged failure is `Webview backend command failed: "setUiReady()" -> TypeError: Cannot read properties of undefined (reading 'start')`. 1. The login Vue bundle ships wrapped in a CommonJS helper. esbuild-loader 4.5.0 (from the 2.5.0 dependency remediation) infers `format: 'iife'` when the compile target is 'web' and the minifier target is not 'esnext', wrapping the whole bundle in a lazy CJS factory and rewriting top-level `this`, which also breaks `output.libraryTarget: 'this'`. Of the four Vue bundles in the shipped 2.5.0 VSIX, login/webview/vue/amazonq/index.js is the ONLY one wrapped -- feedback, codewhisperer and securityIssue shipped clean. Pinning the minimizer to target 'esnext' keeps esbuild as a pure minifier; the loader has already transpiled to es2021 and these bundles only run in the IDE's Chromium webview. This exact upgrade was reverted once before for the same breakage (91a54b0, "broke loading mynah-ui"). 2. setDidLoad dereferences `loadMetadata!.start`. The webview's 10-second load timeout clears loadMetadata on the assumption the load failed, so a page that reports readiness late -- 44 seconds after activation in the captured log -- crashes the setUiReady command instead of recording a slow-but-successful load, and VS Code surfaces that as the webview error banner. Emit without a duration and return instead. The rebuilt login bundle is verified free of the CJS wrapper.
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.
Customer-reported: black login view with "Webview error" on IdC sign-in in 2.5.0
Diagnosed from the extension log of a live repro. The logged failure:
This PR contains two fixes. One is the demonstrated cause of the reported failure; the other is a real packaging regression in the shipped 2.5.0 artifact that is fixed here as prevention, but is most likely not what customers are hitting. An earlier revision of this description claimed the two compound; tracing
root.vue's load sequence disproved that, so the claim is corrected rather than left to stand.The demonstrated cause:
setDidLoadcrashes on any late loadThe captured timeline:
setup()arms a 10-second load timeout; on expiry it clearsloadMetadata, assuming the load failedroot.vue'screated()awaitsclient.refreshAuthState()before reporting readiness, and that call sits onAuthUtil.getChatAuthState()— ~44 seconds on this busy startup. The view renders nothing while it waits: this wait is the black screensetUiReady→setDidLoaddereferencesloadMetadata!.start, but the timeout consumed it 30+ seconds earlier → TypeError → VS Code shows the webview error bannerA second, deterministic trigger — no slowness required
Found while investigating why local testing (repeated IdC logout/login) also produced the error. The login webview is
retainContextWhenHidden: true, so one webview instance lives across auth cycles.root.vuereports readiness once per page kind (auth,selectProfile) per webview lifetime, but the backend has a singleloadMetadataslot: armed atsetup(), re-armed only byenterProfileSelection(), and consumed (= undefined) by any successfulsetDidLoad.So: webview resolves while in
PENDING_PROFILE_SELECTION(every IdC sign-in passes through it) → the profile page reports first and consumes the metadata → user signs out → the LOGIN page renders for its first time in this webview's lifetime and reports readiness →loadMetadataisundefined→ same TypeError. Repeated IdC logout/login cycles reliably produce this ordering. It also explains why field reports cluster on IdC: Builder ID skips profile selection, so it can only hit the timeout variant.The error path (
setLoadFailure) already optional-chains; only the success path could throw. Fix (covers both triggers): when the metadata has already been consumed — by the timeout or by the other page kind — emittoolkit_didLoadModulewithreason: 'LoadReportedAfterMetadataCleared'and no duration, and return. A late or re-ordered successful load is a success, not a crash.Suggested regression test for the checklist, deterministic and environment-free: IdC sign-in → do not select a profile → sign out → confirm no webview error banner.
The prevented regression: the login Vue bundle shipped mis-packaged
esbuild-loader4.5.0 (from the 2.5.0 dependency remediation) infersformat: 'iife'when webpack's compile target isweband the minifier target is notesnext, wrapping the whole bundle in a CommonJS helper and rewriting top-levelthis, which defeatsoutput.libraryTarget: 'this'. In the shipped 2.5.0 VSIX the login bundle is the only wrapped one:feedback/vue/index.jscodewhisperer/vue/index.jscodewhisperer/views/securityIssue/vue/index.jslogin/webview/vue/amazonq/index.jsWhy it is probably not the customer failure: the wrapper's factory self-invokes at the end of the bundle (
po();), so the login app still executes and mounts, and unlike the chat webview nothing on the login page consumes the global export the wrapper destroys. Verified against the installed artifact.Why it is fixed anyway: the identical wrapper does break consumers that resolve exports off the global — it broke the chat webview in pre-release testing (
HybridChatAdapter is not defined, blank panel) and the same loader upgrade was reverted once before for breaking mynah-ui (91a54b0c1). Which bundle gets wrapped is an artifact of minification internals, so leaving the inference in place makes every Vue bundle a future coin flip. Fix: pin the Vue config's minimizer toEsbuildPlugin({ target: 'esnext' }), keeping esbuild as a pure minifier. The loader has already transpiled to es2021 and these bundles only run in the IDE's Chromium webview — packaging shape changes, language level does not.What this PR does not fix
The ~44-second blank login view on a slow startup. That is
root.vueblocking first paint onrefreshAuthState()with no loading state, and it deserves its own change (render a spinner/skeleton before auth state resolves, or lengthen/re-arm the 10s assumption). With this PR the slow path stops producing an error banner, but it is still slow. Follow-up recommended.Verification
npm run compile -w packages/core: 0 TS errorslogin/webview/vue/amazonq/index.jsverified free of the CJS helperRelease note
This should go out as 2.5.1. The marketplace cannot roll back, and any 2.5.0 user whose startup exceeds the 10-second load window gets the error banner on the login view. Suggested addition to the release MCM preflight: verify the login view renders, not only chat — the two are built by different webpack configs, so a chat check does not cover this.