mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
Fabric: Support for interleaving/followup transactions in RCTMountingManager (iOS)
Summary: Imagine a case where we initiate a synchronous state update right in the middle of the mount transaction. With the current implementation, the mount transaction caused by the change will be mounted right inside the in-flight transaction, which will probably cause a crash or incorrect mounting side-effects (which will cause a crash later). Instead of executing all mounting instructions cased by the state change, we actually need to execute them right after the end of the current transaction (synchronously, inside the same main run loop tick). This diff implements exactly this. Changelog: [Internal] Fabric-specific internal change. Reviewed By: mdvacca Differential Revision: D18444730 fbshipit-source-id: 3e777a7aa70ff28205d40588970c7478869b6899
This commit is contained in:
committed by
Facebook Github Bot
parent
9349ee26e7
commit
5f0435fb85
@@ -207,6 +207,8 @@ static void RNPerformMountInstructions(
|
||||
|
||||
@implementation RCTMountingManager {
|
||||
RCTMountingTransactionObserverCoordinator _observerCoordinator;
|
||||
BOOL _transactionInFlight;
|
||||
BOOL _followUpTransactionRequired;
|
||||
}
|
||||
|
||||
- (instancetype)init
|
||||
@@ -225,14 +227,14 @@ static void RNPerformMountInstructions(
|
||||
// * No need to do a thread jump;
|
||||
// * No need to do expensive copy of all mutations;
|
||||
// * No need to allocate a block.
|
||||
[self mountMutations:mountingCoordinator];
|
||||
[self initiateTransaction:mountingCoordinator];
|
||||
return;
|
||||
}
|
||||
|
||||
auto mountingCoordinatorCopy = mountingCoordinator;
|
||||
RCTExecuteOnMainQueue(^{
|
||||
RCTAssertMainQueue();
|
||||
[self mountMutations:mountingCoordinatorCopy];
|
||||
[self initiateTransaction:mountingCoordinatorCopy];
|
||||
});
|
||||
}
|
||||
|
||||
@@ -252,9 +254,28 @@ static void RNPerformMountInstructions(
|
||||
});
|
||||
}
|
||||
|
||||
- (void)mountMutations:(MountingCoordinator::Shared const &)mountingCoordinator
|
||||
- (void)initiateTransaction:(MountingCoordinator::Shared const &)mountingCoordinator
|
||||
{
|
||||
SystraceSection s("-[RCTMountingManager mountMutations:]");
|
||||
SystraceSection s("-[RCTMountingManager initiateTransaction:]");
|
||||
RCTAssertMainQueue();
|
||||
|
||||
if (_transactionInFlight) {
|
||||
_followUpTransactionRequired = YES;
|
||||
return;
|
||||
}
|
||||
|
||||
do {
|
||||
_followUpTransactionRequired = NO;
|
||||
_transactionInFlight = YES;
|
||||
[self performTransaction:mountingCoordinator];
|
||||
_transactionInFlight = NO;
|
||||
} while (_followUpTransactionRequired);
|
||||
}
|
||||
|
||||
- (void)performTransaction:(MountingCoordinator::Shared const &)mountingCoordinator
|
||||
{
|
||||
SystraceSection s("-[RCTMountingManager performTransaction:]");
|
||||
RCTAssertMainQueue();
|
||||
|
||||
auto transaction = mountingCoordinator->pullTransaction();
|
||||
if (!transaction.has_value()) {
|
||||
@@ -268,7 +289,6 @@ static void RNPerformMountInstructions(
|
||||
return;
|
||||
}
|
||||
|
||||
RCTAssertMainQueue();
|
||||
auto telemetry = transaction->getTelemetry();
|
||||
auto number = transaction->getNumber();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user