Skip to content

Reanimated is not supporting multiple surfaces #8344

@gosha212

Description

@gosha212

Description

TLDR
LayoutAnimationsProxy is not RN Surface aware (and probably other components too)
Reproduction Repo
The crash happens only on iOS for some reason

Full Description
Background: In Wix React Native Navigation we are using multiple surfaces. For example, each modal is a new native modal / dialog and hosts a new surface. When we close the surface with animation and switch to another surface with animation the applications crashes. For some reason it happens only on iOS but not on Android.

Here is the stacktrace:

*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'RCTComponentViewRegistry: Attempt to query unregistered component.'
*** First throw call stack:
(
	0   CoreFoundation                      0x00000001804c9690 __exceptionPreprocess + 172
	1   libobjc.A.dylib                     0x00000001800937cc objc_exception_throw + 72
	2   Foundation                          0x0000000180e54f4c -[NSMutableDictionary(NSMutableDictionary) classForCoder] + 0
	3   rn773navigation.debug.dylib         0x0000000104f4b840 -[RCTComponentViewRegistry componentViewDescriptorWithTag:] + 524
	4   rn773navigation.debug.dylib         0x0000000104f8df98 _ZL27RCTPerformMountInstructionsRKNSt3__16vectorIN8facebook5react18ShadowViewMutationENS_9allocatorIS3_EEEEP24RCTComponentViewRegistryR41RCTMountingTransactionObserverCoordinatori + 1428
	5   rn773navigation.debug.dylib         0x0000000104f8d9f8 _ZZ41-[RCTMountingManager performTransaction:]ENK3$_1clERKN8facebook5react19MountingTransactionERKNS1_16SurfaceTelemetryE + 80
	6   rn773navigation.debug.dylib         0x0000000104f8d99c _ZNSt3__18__invokeB8de190102IRZ41-[RCTMountingManager performTransaction:]E3$_1JRKN8facebook5react19MountingTransactionERKNS4_16SurfaceTelemetryEEEEDTclclsr3stdE7declvalIT_EEspclsr3stdE7declvalIT	7   rn773navigation.debug.dylib         0x0000000104f8d944 _ZNSt3__128__invoke_void_return_wrapperIvLb1EE6__callB8de190102IJRZ41-[RCTMountingManager performTransaction:]E3$_1RKN8facebook5react19MountingTransactionERKNS6_16SurfaceTelemetryEEEEvDpOT_ + 40
	8   rn773navigation.debug.dylib         0x0000000104f8d910 _ZNSt3__110__function12__alloc_funcIZ41-[RCTMountingManager performTransaction:]E3$_1NS_9allocatorIS2_EEFvRKN8facebook5react19MountingTransactionERKNS6_16SurfaceTelemetryEEEclB8de190102ES9_SC_ + 	9   rn773navigation.debug.dylib         0x0000000104f8c798 _ZNSt3__110__function6__funcIZ41-[RCTMountingManager performTransaction:]E3$_1NS_9allocatorIS2_EEFvRKN8facebook5react19MountingTransactionERKNS6_16SurfaceTelemetryEEEclES9_SC_ + 44
	10  rn773navigation.debug.dylib         0x0000000104d19904 _ZNKSt3__110__function12__value_funcIFvRKN8facebook5react19MountingTransactionERKNS3_16SurfaceTelemetryEEEclB8de190102ES6_S9_ + 76
	11  rn773navigation.debug.dylib         0x0000000104d18b84 _ZNKSt3__18functionIFvRKN8facebook5react19MountingTransactionERKNS2_16SurfaceTelemetryEEEclES5_S8_ + 40
	12  rn773navigation.debug.dylib         0x0000000104d189b8 _ZNK8facebook5react19TelemetryController15pullTransactionERKNSt3__18functionIFvRKNS0_19MountingTransactionERKNS0_16SurfaceTelemetryEEEESD_SD_ + 300
	13  rn773navigation.debug.dylib         0x0000000104f87afc -[RCTMountingManager performTransaction:] + 588
	14  rn773navigation.debug.dylib         0x0000000104f8782c -[RCTMountingManager initiateTransaction:] + 496
	15  rn773navigation.debug.dylib         0x0000000104f8719c __42-[RCTMountingManager scheduleTransaction:]_block_invoke + 348
	16  rn773navigation.debug.dylib         0x0000000104b3b714 __RCTExecuteOnMainQueue_block_invoke + 40
	17  libdispatch.dylib                   0x00000001009cbec8 _dispatch_call_block_and_release + 24
	18  libdispatch.dylib                   0x00000001009e5798 _dispatch_client_callout + 12
	19  libdispatch.dylib                   0x00000001009db408 _dispatch_main_queue_drain + 1220
	20  libdispatch.dylib                   0x00000001009daf34 _dispatch_main_queue_callback_4CF + 40
	21  CoreFoundation                      0x0000000180428d48 __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ + 12
	22  CoreFoundation                      0x0000000180423754 __CFRunLoopRun + 1920
	23  CoreFoundation                      0x0000000180422b98 CFRunLoopRunSpecific + 536
	24  GraphicsServices                    0x000000019101fd00 GSEventRunModal + 164
	25  UIKitCore                           0x0000000185c5ebb8 -[UIApplication _run] + 796
	26  UIKitCore                           0x0000000185c62f84 UIApplicationMain + 124
	27  UIKitCore                           0x0000000185028f88 block_destroy_helper.14 + 9560
	28  rn773navigation.debug.dylib         0x0000000104826d3c $sSo21UIApplicationDelegateP5UIKitE4mainyyFZ + 128
	29  rn773navigation.debug.dylib         0x0000000104826cac $s15rn773navigation11AppDelegateC5$mainyyFZ + 44
	30  rn773navigation.debug.dylib         0x0000000104826db8 __debug_main_executable_dylib_entry_point + 28
	31  dyld                                0x0000000100ac93d4 start_sim + 20
	32  ???                                 0x0000000100bdeb98 0x0 + 4307413912
)
libc++abi: terminating due to uncaught exception of type NSException

This crash happens only if you have components that implement mountingTransactionWillMount:withSurfaceTelemetry: Like ScrollView because RN have a special logic only for this components:

void RCTMountingTransactionObserverCoordinator::unregisterViewComponentDescriptor(
    const RCTComponentViewDescriptor &componentViewDescriptor,
    SurfaceId surfaceId)
{
  if (!componentViewDescriptor.observesMountingTransactionWillMount &&
      !componentViewDescriptor.observesMountingTransactionDidMount) {
    return;
  }

  auto &surfaceRegistry = registry_[surfaceId];
  assert(surfaceRegistry.count(componentViewDescriptor) == 1);
  surfaceRegistry.erase(componentViewDescriptor);
}

Deeper investigation

  1. Main screen is surface 1
  2. Open a New modal with ScrollView and exit animation. It becomes surface 11
  3. When you close the modal the LayoutAnimationsProxy::pullTransaction will make some changes to the transaction and will not remove all the nodes immediately in the same commit.
  4. Some of the nodes will complete the animation and will be added to deadNodes list in LayoutAnimationsProxy
  5. Once you open another surface or make another commit (State), the next LayoutAnimationsProxy::pullTransaction will add the deadNodes from shadow tree of surface 11 to the transaction of any other surface but not 11. In case of ScrollView it's going to crash because of special handling in RCTMountingTransactionObserverCoordinator

Steps to reproduce

  1. Checkout https://github.com/gosha212/rnn-reanimated-crash-077-078
  2. npm i
  3. cd pod && pod install && cd ..
  4. npx react-native run-ios
  5. Click on 'Show Modal'
  6. Click on 'Close'
  7. Click on 'Show Modal` once again.

Result-> iOS app will crash.

Snack or a link to a repository

https://github.com/gosha212/rnn-reanimated-crash-077-078

Reanimated version

3.18

Worklets version

?

React Native version

0.77.3

Platforms

iOS

JavaScript runtime

Hermes

Workflow

React Native CLI

Architecture

New Architecture (Fabric renderer)

Build type

Debug app & dev bundle

Device

iOS simulator

Host machine

macOS

Device model

iPhone 16

Acknowledgements

Yes

Metadata

Metadata

Assignees

No one assigned

    Labels

    Platform: iOSThis issue is specific to iOSRepro providedA reproduction with a snippet of code, snack or repo is provided

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions