Skip to content

Commit 5f0435f

Browse files
sherginfacebook-github-bot
authored andcommitted
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
1 parent 9349ee2 commit 5f0435f

1 file changed

Lines changed: 25 additions & 5 deletions

File tree

React/Fabric/Mounting/RCTMountingManager.mm

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,8 @@ static void RNPerformMountInstructions(
207207

208208
@implementation RCTMountingManager {
209209
RCTMountingTransactionObserverCoordinator _observerCoordinator;
210+
BOOL _transactionInFlight;
211+
BOOL _followUpTransactionRequired;
210212
}
211213

212214
- (instancetype)init
@@ -225,14 +227,14 @@ - (void)scheduleTransaction:(MountingCoordinator::Shared const &)mountingCoordin
225227
// * No need to do a thread jump;
226228
// * No need to do expensive copy of all mutations;
227229
// * No need to allocate a block.
228-
[self mountMutations:mountingCoordinator];
230+
[self initiateTransaction:mountingCoordinator];
229231
return;
230232
}
231233

232234
auto mountingCoordinatorCopy = mountingCoordinator;
233235
RCTExecuteOnMainQueue(^{
234236
RCTAssertMainQueue();
235-
[self mountMutations:mountingCoordinatorCopy];
237+
[self initiateTransaction:mountingCoordinatorCopy];
236238
});
237239
}
238240

@@ -252,9 +254,28 @@ - (void)dispatchCommand:(ReactTag)reactTag commandName:(NSString *)commandName a
252254
});
253255
}
254256

255-
- (void)mountMutations:(MountingCoordinator::Shared const &)mountingCoordinator
257+
- (void)initiateTransaction:(MountingCoordinator::Shared const &)mountingCoordinator
256258
{
257-
SystraceSection s("-[RCTMountingManager mountMutations:]");
259+
SystraceSection s("-[RCTMountingManager initiateTransaction:]");
260+
RCTAssertMainQueue();
261+
262+
if (_transactionInFlight) {
263+
_followUpTransactionRequired = YES;
264+
return;
265+
}
266+
267+
do {
268+
_followUpTransactionRequired = NO;
269+
_transactionInFlight = YES;
270+
[self performTransaction:mountingCoordinator];
271+
_transactionInFlight = NO;
272+
} while (_followUpTransactionRequired);
273+
}
274+
275+
- (void)performTransaction:(MountingCoordinator::Shared const &)mountingCoordinator
276+
{
277+
SystraceSection s("-[RCTMountingManager performTransaction:]");
278+
RCTAssertMainQueue();
258279

259280
auto transaction = mountingCoordinator->pullTransaction();
260281
if (!transaction.has_value()) {
@@ -268,7 +289,6 @@ - (void)mountMutations:(MountingCoordinator::Shared const &)mountingCoordinator
268289
return;
269290
}
270291

271-
RCTAssertMainQueue();
272292
auto telemetry = transaction->getTelemetry();
273293
auto number = transaction->getNumber();
274294

0 commit comments

Comments
 (0)