Skip to content

fix: run embedded CardView native lifecycle on main thread#1161

Merged
descorp merged 3 commits into
developfrom
fix/embedded-view-main-thread
Jul 9, 2026
Merged

fix: run embedded CardView native lifecycle on main thread#1161
descorp merged 3 commits into
developfrom
fix/embedded-view-main-thread

Conversation

@descorp

@descorp descorp commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

Summary

Fixes a residual iOS crash: C++ Exception: AdyenComponentBus.unsubscribe raised an exception: Call must be made on main thread, still occurring on 2.11.1 despite the earlier fix in c143c27.

Root cause

The 2.11.1 fix hardened only the AdyenComponentBus module's JS-facing entry points (subscribe/unsubscribe/handleetc.) with ensureMainThread. It did not cover the native Fabric view path: CardComponentViewProxy (backing ADYCardView) still called Adyen SDK APIs directly from dispose() (cancelIfNeeded(), EmbeddedComponentBusModule.unregister) and initializeComponentIfNeeded() (CardComponent/AdyenActionComponent construction) with no main-thread guarantee. When Fabric drives view teardown/mount off the main thread, the Adyen SDK's main-thread assertion fires.

Fix

Wrap dispose() and initializeComponentIfNeeded() in CardComponentViewProxy with the existing ensureMainThread(_:) helper, matching the pattern already used in EmbeddedComponentBusModule.

Tests

Added two regression tests to ThreadingSafetyTests.swift:

  • test_cardComponentViewProxyDispose_fromBackgroundThread_doesNotCrash
  • test_cardComponentViewProxyInitialize_fromBackgroundThread_reportsErrorOnMainThread

Ticket

COSDK-1355

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces thread-safety improvements to CardComponentViewProxy by ensuring that both dispose() and initializeComponentIfNeeded() are executed on the main thread, and adds corresponding unit tests to verify these behaviors. The feedback recommends capturing self strongly in the dispose() thread-safety block to prevent silent cleanup failures if the proxy is deallocated prematurely. Additionally, it suggests refactoring the new unit tests to use an onSend callback on the mock emitter instead of a hardcoded delay, making the tests deterministic and faster.

Comment thread ios/Views/CardView/CardComponentViewProxy.swift Outdated
Comment thread example/ios/AdyenExampleTests/Modules/ThreadingSafetyTests.swift
Comment thread example/ios/AdyenExampleTests/Modules/ThreadingSafetyTests.swift Outdated
@sonarqubecloud

sonarqubecloud Bot commented Jul 9, 2026

Copy link
Copy Markdown

Comment thread ios/Views/CardView/CardComponentViewProxy.swift
Comment thread ios/Views/CardView/CardComponentViewProxy.swift
@descorp
descorp merged commit a8dde39 into develop Jul 9, 2026
16 of 17 checks passed
@descorp
descorp deleted the fix/embedded-view-main-thread branch July 9, 2026 14:25
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.

4 participants