Skip to content

Superseded by #1012 - #1009

Closed
claude[bot] wants to merge 2 commits into
masterfrom
claude/applepay-availability-two-instance-fix
Closed

Superseded by #1012#1009
claude[bot] wants to merge 2 commits into
masterfrom
claude/applepay-availability-two-instance-fix

Conversation

@claude

@claude claude Bot commented Sep 7, 2026

Copy link
Copy Markdown

Requested by oisín, Alexander Reyes-Wainwright · Slack thread

Why

Before: A page that constructs two ui.applePay() instances gets "unsupported" from the second one, permanently. Each instance loaded the Apple Pay SDK itself, and an instance that found a <script> tag already in the DOM marked the script loaded without checking whether it had run — so the second instance sailed past the load wait while Apple's script was still in flight, found no ApplePaySession, and returned "unsupported". availability() cached that answer for the life of the instance and cleared it only on a thrown probe, so no later call and no remount recovered. The express-checkout button never appeared. This only shows up where ApplePaySession comes from Apple's injected SDK rather than the browser: Chrome and Edge on macOS and iOS, in-app browsers, older Safari. Native Safari 17+ defines applePayCapabilities itself, so it never reproduced.

After: Every ApplePayButton on the page shares one SDK load, and the second instance waits for the same script the first one injected, so both resolve "available" and the express-checkout button mounts. A "unsupported" result is no longer cached, so a call made before the SDK is ready no longer poisons every call after it. A tag the merchant injected themselves — the workaround the reporting customer is running — is now handled whether or not it finished loading before the SDK was constructed. Browsers that genuinely have no Apple Pay still get "unsupported", not an error.

How

Script loading moves from per-instance #injectScript() to a single module-level loadApplePaySDK() promise: it resolves immediately when a tag exists and ApplePaySession.applePayCapabilities is already a function, otherwise listens for load on the one tag and applies the existing 10s timeout — rejecting for a tag we injected, resolving for one we did not, since a tag that already ran will never fire load again. availability() keeps memoizing "available" and "unavailable" and drops "unsupported" so the next call re-probes.

Where it came from

Introduced by e6891313a42fee08ebf86894b257d4190989a334; shipped in @evervault/browser@2.62.1 (Aug 10) but only reached prod when 2.63.0 deployed 2026-09-02, which is why it surfaced in September.

Two calls worth a reviewer's attention

The resolve-immediately fast path is gated on a <script> tag existing rather than on applePayCapabilities alone, because the script-loading suite's beforeEach stubs a ready ApplePaySession with no tag in the DOM and an unconditional fast path breaks the existing onload and timeout tests.

For a tag we did not inject, the 10s timeout resolves rather than rejects, so a merchant-self-injected tag on a browser without Apple Pay waits up to 10s before answering "unsupported".

Testing

The new regression test fails on master with expected 'unsupported' to be 'available' and passes with this change. applePay.test.ts is 75/75; tsc --noEmit and eslint are clean. resetApplePaySDKLoader() exists for test isolation and must be called from the top-level beforeEach.

A second ApplePayButton on the same page found the first instance's script
tag before Apple's SDK had executed, resolved its script wait immediately,
and cached the resulting "unsupported" for the life of the instance, so the
button never mounted.

Move script loading to a single module-level promise and stop memoizing an
"unsupported" availability result.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014HHDw5Q6brV8iTrctYMJJr
@claude
claude Bot requested a review from a team as a code owner September 7, 2026 15:37
@changeset-bot

changeset-bot Bot commented Sep 7, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 9e56bbb

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 7 packages
Name Type
@evervault/browser Patch
@evervault/inputs Patch
example-apple-pay Patch
example-react-google-wallet Patch
@evervault/browser-e2e-tests Patch
e2e-tests-ui-components-vanilla-server Patch
@evervault/inputs-e2e-tests Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

Comment thread packages/browser/lib/ui/ApplePay/index.ts Outdated
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014HHDw5Q6brV8iTrctYMJJr
@alexander-rw
Alexander (alexander-rw) deleted the claude/applepay-availability-two-instance-fix branch September 8, 2026 09:40
@alexander-rw Alexander (alexander-rw) changed the title fix(browser): share Apple Pay SDK load across instances Superseded by #1012 Sep 8, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

2 participants