Skip to content

fix(adyen): destroy Drop-in on unmount to stop iframe/listener leak - #813

Closed
acasazza wants to merge 1 commit into
mainfrom
fix/adyen-dropin-memory-leak-811
Closed

fix(adyen): destroy Drop-in on unmount to stop iframe/listener leak#813
acasazza wants to merge 1 commit into
mainfrom
fix/adyen-dropin-memory-leak-811

Conversation

@acasazza

Copy link
Copy Markdown
Member

Summary

  • AdyenPayment mounted an Adyen Web Drop-in but never called its remove() teardown on unmount, leaking Secured-Field iframes, wallet SDK injections, 3DS challenge frames, and global message/resize listeners on every payment-method switch away from and back to Adyen (AdyenGateway unmounts the component on selection change).
  • The destroy call lives in a separate unmount-only effect (empty deps), not the existing mount effect's cleanup — that cleanup also fires on every status change (e.g. a declined-payment retry flips standby -> placing -> standby while the component stays mounted), and destroying the live Drop-in there would rebuild it mid-flow.
  • No other call sites needed changes: the component.mount("#adyen-dropin") calls elsewhere reuse the SDK-handed-back live instance, not new ones.

Fixes #811. A related but distinct latent race (unmount during an in-flight AdyenCheckout() call) is filed separately as #812.

Test plan

  • Added specs/payment_source/adyen-payment.spec.tsx: mocks Dropin/AdyenCheckout, asserts remove() is called exactly once on real unmount and not called across a status-only re-render.
  • Verified this test fails against the unfixed code and against a naive fix that merges remove() into the shared cleanup (which fires on the status flip and rebuilds the Drop-in mid-retry).
  • pnpm lint / tsc --noEmit clean on changed files.
  • Manual DevTools confirmation of detached-iframe/heap behavior (jsdom has no real GC/detached-node instrumentation to assert on in CI).

AdyenPayment mounted an Adyen Web Drop-in but never called its remove()
teardown, so every payment-method switch away from and back to Adyen
(AdyenGateway unmounts the component on selection change) orphaned the
previous instance's Secured-Field iframes, wallet SDK injections, 3DS
frames, and global message/resize listeners.

The destroy call is added in a separate unmount-only effect (empty deps)
rather than the existing mount effect's cleanup, because that cleanup
also fires on every status change (e.g. a declined-payment retry flips
standby -> placing -> standby while the component stays mounted), and
tearing down the live Drop-in there would rebuild it mid-flow.

Fixes #811
@netlify

netlify Bot commented Aug 10, 2026

Copy link
Copy Markdown

Deploy Preview for commercelayer-react-components failed.

Name Link
🔨 Latest commit e738022
🔍 Latest deploy log https://app.netlify.com/projects/commercelayer-react-components/deploys/6a7a49c50d89ee0008dda35a

@acasazza

Copy link
Copy Markdown
Member Author

Closing: v5 has landed on main (#619), so this fix will be redone against the new codebase rather than rebased onto it. The commits stay reachable at refs/pull/813/head.

@acasazza acasazza closed this Aug 24, 2026
@acasazza
acasazza deleted the fix/adyen-dropin-memory-leak-811 branch August 24, 2026 14:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

AdyenPayment never destroys the Adyen Web Drop-in on unmount (memory leak)

1 participant