Fixed race condition in RCTUIManager's mounting process

Summary:
See the comment in code.
This picture also illustrates the problem: https://cl.ly/250z0D1B0c17.
https://pxl.cl/ckBq

Reviewed By: fkgozali

Differential Revision: D7343566

fbshipit-source-id: e45a691add5e43434dea8708be4b76ff18e52131
This commit is contained in:
Valentin Shergin 2018-03-21 10:18:59 -07:00 committed by Facebook Github Bot
parent 0594a109d1
commit 909861ff05

View File

@ -69,6 +69,9 @@ NSString *const RCTUIManagerWillUpdateViewsDueToContentSizeMultiplierChangeNotif
// Keyed by viewName
NSDictionary *_componentDataByName;
BOOL _isMountingInProgress;
BOOL _isRemountingNeeded;
}
@synthesize bridge = _bridge;
@ -1046,6 +1049,19 @@ RCT_EXPORT_METHOD(dispatchViewManagerCommand:(nonnull NSNumber *)reactTag
*/
- (void)_layoutAndMount
{
// Mounting is (usually, not always) an asynchronous process.
// So, we have to ensure that there is no any case of self-interleaving
// (when another mourning process is initiated before the previous
// one finishes) here.
if (_isMountingInProgress) {
// In a case when another mounting process hasn't completed yet,
// we have to run another pass right after it finishes.
_isRemountingNeeded = YES;
return;
}
_isMountingInProgress = YES;
[self _dispatchPropsDidChangeEvents];
[self _dispatchChildrenDidChangeEvents];
@ -1063,6 +1079,13 @@ RCT_EXPORT_METHOD(dispatchViewManagerCommand:(nonnull NSNumber *)reactTag
[self flushUIBlocksWithCompletion:^{
[self->_observerCoordinator uiManagerDidPerformMounting:self];
self->_isMountingInProgress = NO;
if (self->_isRemountingNeeded) {
self->_isRemountingNeeded = NO;
[self _layoutAndMount];
}
}];
}