mirror of
https://github.com/status-im/react-native.git
synced 2025-01-26 17:30:25 +00:00
Customize main thread initialization of native modules (2nd try)
Reviewed By: majak Differential Revision: D3671197 fbshipit-source-id: e8df7669be79303d335f2c881e97310b5fed47f9
This commit is contained in:
parent
68b9a36858
commit
0222107170
@ -16,8 +16,9 @@ const NativeModules = require('NativeModules');
|
||||
const { UIManager } = NativeModules;
|
||||
|
||||
const findNodeHandle = require('react/lib/findNodeHandle');
|
||||
const invariant = require('fbjs/lib/invariant');
|
||||
|
||||
const _takeSnapshot = UIManager.takeSnapshot;
|
||||
invariant(UIManager, 'UIManager is undefined. The native module config is probably incorrect.');
|
||||
|
||||
/**
|
||||
* Capture an image of the screen, window or an individual view. The image
|
||||
@ -39,12 +40,13 @@ const _takeSnapshot = UIManager.takeSnapshot;
|
||||
UIManager.takeSnapshot = async function(
|
||||
view ?: 'window' | ReactElement<any> | number,
|
||||
options ?: {
|
||||
width ?: number;
|
||||
height ?: number;
|
||||
format ?: 'png' | 'jpeg';
|
||||
quality ?: number;
|
||||
width ?: number,
|
||||
height ?: number,
|
||||
format ?: 'png' | 'jpeg',
|
||||
quality ?: number,
|
||||
},
|
||||
) {
|
||||
const _takeSnapshot = UIManager.takeSnapshot;
|
||||
if (!_takeSnapshot) {
|
||||
console.warn('UIManager.takeSnapshot is not available on this platform');
|
||||
return;
|
||||
|
@ -46,9 +46,10 @@ RCT_EXTERN NSArray<Class> *RCTGetModuleClasses(void);
|
||||
{
|
||||
BOOL _wasBatchActive;
|
||||
NSMutableArray<dispatch_block_t> *_pendingCalls;
|
||||
NSMutableDictionary<NSString *, RCTModuleData *> *_moduleDataByName;
|
||||
NSDictionary<NSString *, RCTModuleData *> *_moduleDataByName;
|
||||
NSArray<RCTModuleData *> *_moduleDataByID;
|
||||
NSArray<Class> *_moduleClassesByID;
|
||||
NSUInteger _modulesInitializedOnMainQueue;
|
||||
RCTDisplayLink *_displayLink;
|
||||
}
|
||||
|
||||
@ -99,6 +100,8 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithDelegate:(id<RCTBridgeDelegate>)dele
|
||||
|
||||
- (void)start
|
||||
{
|
||||
RCT_PROFILE_BEGIN_EVENT(0, @"-[RCTBatchedBridge setUp]", nil);
|
||||
|
||||
dispatch_queue_t bridgeQueue = dispatch_queue_create("com.facebook.react.RCTBridgeQueue", DISPATCH_QUEUE_CONCURRENT);
|
||||
|
||||
dispatch_group_t initModulesAndLoadSource = dispatch_group_create();
|
||||
@ -137,9 +140,11 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithDelegate:(id<RCTBridgeDelegate>)dele
|
||||
// Asynchronously gather the module config
|
||||
dispatch_group_async(setupJSExecutorAndModuleConfig, bridgeQueue, ^{
|
||||
if (weakSelf.valid) {
|
||||
RCT_PROFILE_BEGIN_EVENT(0, @"-[RCTBatchedBridge moduleConfig", nil);
|
||||
[performanceLogger markStartForTag:RCTPLNativeModulePrepareConfig];
|
||||
config = [weakSelf moduleConfig];
|
||||
[performanceLogger markStopForTag:RCTPLNativeModulePrepareConfig];
|
||||
RCT_PROFILE_END_EVENT(0, @"", nil);
|
||||
}
|
||||
});
|
||||
|
||||
@ -166,6 +171,8 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithDelegate:(id<RCTBridgeDelegate>)dele
|
||||
[strongSelf executeSourceCode:sourceCode];
|
||||
}
|
||||
});
|
||||
|
||||
RCT_PROFILE_END_EVENT(0, @"", nil);
|
||||
}
|
||||
|
||||
- (void)loadSource:(RCTSourceLoadBlock)_onSourceLoad
|
||||
@ -233,6 +240,13 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithDelegate:(id<RCTBridgeDelegate>)dele
|
||||
moduleData = _moduleDataByName[[@"RCT" stringByAppendingString:moduleName]];
|
||||
}
|
||||
if (moduleData) {
|
||||
#if RCT_DEV
|
||||
if ([self.delegate respondsToSelector:@selector(whitelistedModulesForBridge:)]) {
|
||||
NSArray *whitelisted = [self.delegate whitelistedModulesForBridge:self];
|
||||
RCTAssert(!whitelisted || [whitelisted containsObject:[moduleData moduleClass]],
|
||||
@"Required config for %@, which was not whitelisted", moduleName);
|
||||
}
|
||||
#endif
|
||||
return moduleData.config;
|
||||
}
|
||||
return (id)kCFNull;
|
||||
@ -240,6 +254,7 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithDelegate:(id<RCTBridgeDelegate>)dele
|
||||
|
||||
- (void)initModulesWithDispatchGroup:(dispatch_group_t)dispatchGroup
|
||||
{
|
||||
RCT_PROFILE_BEGIN_EVENT(0, @"-[RCTBatchedBridge initModules]", nil);
|
||||
[_performanceLogger markStartForTag:RCTPLNativeModuleInit];
|
||||
|
||||
NSArray<id<RCTBridgeModule>> *extraModules = nil;
|
||||
@ -252,7 +267,6 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithDelegate:(id<RCTBridgeDelegate>)dele
|
||||
}
|
||||
|
||||
if (RCT_DEBUG && !RCTRunningInTestEnvironment()) {
|
||||
|
||||
// Check for unexported modules
|
||||
static Class *classes;
|
||||
static unsigned int classCount;
|
||||
@ -290,6 +304,7 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithDelegate:(id<RCTBridgeDelegate>)dele
|
||||
NSMutableDictionary<NSString *, RCTModuleData *> *moduleDataByName = [NSMutableDictionary new];
|
||||
|
||||
// Set up moduleData for pre-initialized module instances
|
||||
RCT_PROFILE_BEGIN_EVENT(0, @"extraModules", nil);
|
||||
for (id<RCTBridgeModule> module in extraModules) {
|
||||
Class moduleClass = [module class];
|
||||
NSString *moduleName = RCTBridgeModuleNameForClass(moduleClass);
|
||||
@ -317,11 +332,13 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithDelegate:(id<RCTBridgeDelegate>)dele
|
||||
_javaScriptExecutor = (id<RCTJavaScriptExecutor>)module;
|
||||
}
|
||||
}
|
||||
RCT_PROFILE_END_EVENT(0, @"", nil);
|
||||
|
||||
// The executor is a bridge module, but we want it to be instantiated before
|
||||
// any other module has access to the bridge, in case they need the JS thread.
|
||||
// TODO: once we have more fine-grained control of init (t11106126) we can
|
||||
// probably just replace this with [self moduleForClass:self.executorClass]
|
||||
RCT_PROFILE_BEGIN_EVENT(0, @"JavaScriptExecutor", nil);
|
||||
if (!_javaScriptExecutor) {
|
||||
id<RCTJavaScriptExecutor> executorModule = [self.executorClass new];
|
||||
RCTModuleData *moduleData = [[RCTModuleData alloc] initWithModuleInstance:executorModule
|
||||
@ -333,8 +350,10 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithDelegate:(id<RCTBridgeDelegate>)dele
|
||||
// NOTE: _javaScriptExecutor is a weak reference
|
||||
_javaScriptExecutor = executorModule;
|
||||
}
|
||||
RCT_PROFILE_END_EVENT(0, @"", nil);
|
||||
|
||||
// Set up moduleData for automatically-exported modules
|
||||
RCT_PROFILE_BEGIN_EVENT(0, @"ModuleData", nil);
|
||||
for (Class moduleClass in RCTGetModuleClasses()) {
|
||||
NSString *moduleName = RCTBridgeModuleNameForClass(moduleClass);
|
||||
|
||||
@ -367,8 +386,10 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithDelegate:(id<RCTBridgeDelegate>)dele
|
||||
_moduleDataByID = [moduleDataByID copy];
|
||||
_moduleDataByName = [moduleDataByName copy];
|
||||
_moduleClassesByID = [moduleClassesByID copy];
|
||||
RCT_PROFILE_END_EVENT(0, @"", nil);
|
||||
|
||||
// Synchronously set up the pre-initialized modules
|
||||
RCT_PROFILE_BEGIN_EVENT(0, @"extraModules", nil);
|
||||
for (RCTModuleData *moduleData in _moduleDataByID) {
|
||||
if (moduleData.hasInstance &&
|
||||
(!moduleData.requiresMainQueueSetup || RCTIsMainQueue())) {
|
||||
@ -381,39 +402,80 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithDelegate:(id<RCTBridgeDelegate>)dele
|
||||
(void)[moduleData instance];
|
||||
}
|
||||
}
|
||||
RCT_PROFILE_END_EVENT(0, @"", nil);
|
||||
|
||||
// From this point on, RCTDidInitializeModuleNotification notifications will
|
||||
// be sent the first time a module is accessed.
|
||||
_moduleSetupComplete = YES;
|
||||
|
||||
[self prepareModulesWithDispatchGroup:dispatchGroup];
|
||||
|
||||
[_performanceLogger markStopForTag:RCTPLNativeModuleInit];
|
||||
RCT_PROFILE_END_EVENT(0, @"", nil);
|
||||
}
|
||||
|
||||
- (void)prepareModulesWithDispatchGroup:(dispatch_group_t)dispatchGroup
|
||||
{
|
||||
RCT_PROFILE_BEGIN_EVENT(0, @"-[RCTBatchedBridge prepareModulesWithDispatch]", nil);
|
||||
|
||||
NSArray<Class> *whitelistedModules = nil;
|
||||
if ([self.delegate respondsToSelector:@selector(whitelistedModulesForBridge:)]) {
|
||||
whitelistedModules = [self.delegate whitelistedModulesForBridge:self];
|
||||
}
|
||||
|
||||
BOOL initializeImmediately = NO;
|
||||
if (dispatchGroup == NULL) {
|
||||
// If no dispatchGroup is passed in, we must prepare everything immediately.
|
||||
// We better be on the right thread too.
|
||||
RCTAssertMainQueue();
|
||||
initializeImmediately = YES;
|
||||
} else if ([self.delegate respondsToSelector:@selector(shouldBridgeInitializeNativeModulesSynchronously:)]) {
|
||||
initializeImmediately = [self.delegate shouldBridgeInitializeNativeModulesSynchronously:self];
|
||||
}
|
||||
|
||||
// Set up modules that require main thread init or constants export
|
||||
[_performanceLogger setValue:0 forTag:RCTPLNativeModuleMainThread];
|
||||
NSUInteger modulesOnMainQueueCount = 0;
|
||||
for (RCTModuleData *moduleData in _moduleDataByID) {
|
||||
__weak RCTBatchedBridge *weakSelf = self;
|
||||
if (whitelistedModules && ![whitelistedModules containsObject:[moduleData moduleClass]]) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (moduleData.requiresMainQueueSetup || moduleData.hasConstantsToExport) {
|
||||
// Modules that need to be set up on the main thread cannot be initialized
|
||||
// lazily when required without doing a dispatch_sync to the main thread,
|
||||
// which can result in deadlock. To avoid this, we initialize all of these
|
||||
// modules on the main thread in parallel with loading the JS code, so
|
||||
// they will already be available before they are ever required.
|
||||
dispatch_group_async(dispatchGroup, dispatch_get_main_queue(), ^{
|
||||
RCTBatchedBridge *strongSelf = weakSelf;
|
||||
if (!strongSelf.valid) {
|
||||
return;
|
||||
dispatch_block_t block = ^{
|
||||
if (self.valid) {
|
||||
[self->_performanceLogger appendStartForTag:RCTPLNativeModuleMainThread];
|
||||
(void)[moduleData instance];
|
||||
[moduleData gatherConstants];
|
||||
[self->_performanceLogger appendStopForTag:RCTPLNativeModuleMainThread];
|
||||
}
|
||||
};
|
||||
|
||||
[strongSelf->_performanceLogger appendStartForTag:RCTPLNativeModuleMainThread];
|
||||
(void)[moduleData instance];
|
||||
[moduleData gatherConstants];
|
||||
[strongSelf->_performanceLogger appendStopForTag:RCTPLNativeModuleMainThread];
|
||||
});
|
||||
modulesOnMainQueueCount++;
|
||||
if (initializeImmediately && RCTIsMainQueue()) {
|
||||
block();
|
||||
} else {
|
||||
// We've already checked that dispatchGroup is non-null, but this satisifies the
|
||||
// Xcode analyzer
|
||||
if (dispatchGroup) {
|
||||
dispatch_group_async(dispatchGroup, dispatch_get_main_queue(), block);
|
||||
}
|
||||
}
|
||||
_modulesInitializedOnMainQueue++;
|
||||
}
|
||||
}
|
||||
|
||||
[_performanceLogger markStopForTag:RCTPLNativeModuleInit];
|
||||
[_performanceLogger setValue:modulesOnMainQueueCount forTag:RCTPLNativeModuleMainThreadUsesCount];
|
||||
[_performanceLogger setValue:_modulesInitializedOnMainQueue forTag:RCTPLNativeModuleMainThreadUsesCount];
|
||||
RCT_PROFILE_END_EVENT(0, @"", nil);
|
||||
}
|
||||
|
||||
- (void)whitelistedModulesDidChange
|
||||
{
|
||||
RCTAssertMainQueue();
|
||||
[self prepareModulesWithDispatchGroup:NULL];
|
||||
}
|
||||
|
||||
- (void)setUpExecutor
|
||||
@ -597,23 +659,22 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithBundleURL:(__unused NSURL *)bundleUR
|
||||
queue:(dispatch_queue_t)queue
|
||||
{
|
||||
if (queue == RCTJSThread) {
|
||||
__weak __typeof(self) weakSelf = self;
|
||||
RCTProfileBeginFlowEvent();
|
||||
RCTAssert(_javaScriptExecutor != nil, @"Need JS executor to schedule JS work");
|
||||
|
||||
[_javaScriptExecutor executeBlockOnJavaScriptQueue:^{
|
||||
RCTProfileEndFlowEvent();
|
||||
|
||||
RCTBatchedBridge *strongSelf = weakSelf;
|
||||
if (!strongSelf) {
|
||||
return;
|
||||
}
|
||||
RCT_PROFILE_BEGIN_EVENT(0, @"-[RCTBatchedBridge dispatchBlock", @{ @"loading": @(self.loading) });
|
||||
|
||||
if (strongSelf.loading) {
|
||||
[strongSelf->_pendingCalls addObject:block];
|
||||
if (self.loading) {
|
||||
RCTAssert(self->_pendingCalls != nil, @"Can't add pending call, bridge is no longer loading");
|
||||
[self->_pendingCalls addObject:block];
|
||||
} else {
|
||||
block();
|
||||
}
|
||||
|
||||
RCT_PROFILE_END_EVENT(0, @"", nil);
|
||||
}];
|
||||
} else if (queue) {
|
||||
dispatch_async(queue, block);
|
||||
@ -705,11 +766,11 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithBundleURL:(__unused NSURL *)bundleUR
|
||||
/**
|
||||
* AnyThread
|
||||
*/
|
||||
RCT_PROFILE_BEGIN_EVENT(RCTProfileTagAlways, @"-[RCTBatchedBridge enqueueJSCall:]", nil);
|
||||
if (!_valid) {
|
||||
return;
|
||||
}
|
||||
|
||||
RCT_PROFILE_BEGIN_EVENT(RCTProfileTagAlways, @"-[RCTBatchedBridge enqueueJSCall:]", nil);
|
||||
__weak __typeof(self) weakSelf = self;
|
||||
[self dispatchBlock:^{
|
||||
[weakSelf _actuallyInvokeAndProcessModule:module method:method arguments:args ?: @[]];
|
||||
@ -717,7 +778,6 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithBundleURL:(__unused NSURL *)bundleUR
|
||||
completion();
|
||||
}
|
||||
} queue:RCTJSThread];
|
||||
|
||||
RCT_PROFILE_END_EVENT(RCTProfileTagAlways, @"", nil);
|
||||
}
|
||||
|
||||
@ -791,7 +851,7 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithBundleURL:(__unused NSURL *)bundleUR
|
||||
{
|
||||
RCTAssertJSThread();
|
||||
|
||||
__weak typeof(self) weakSelf = self;
|
||||
__weak __typeof(self) weakSelf = self;
|
||||
[_javaScriptExecutor callFunctionOnModule:module
|
||||
method:method
|
||||
arguments:args
|
||||
@ -805,7 +865,7 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithBundleURL:(__unused NSURL *)bundleUR
|
||||
{
|
||||
RCTAssertJSThread();
|
||||
|
||||
__weak typeof(self) weakSelf = self;
|
||||
__weak __typeof(self) weakSelf = self;
|
||||
[_javaScriptExecutor invokeCallbackID:cbID
|
||||
arguments:args
|
||||
callback:^(id json, NSError *error) {
|
||||
@ -931,7 +991,7 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithBundleURL:(__unused NSURL *)bundleUR
|
||||
- (void)partialBatchDidFlush
|
||||
{
|
||||
for (RCTModuleData *moduleData in _moduleDataByID) {
|
||||
if (moduleData.implementsPartialBatchDidFlush) {
|
||||
if (moduleData.hasInstance && moduleData.implementsPartialBatchDidFlush) {
|
||||
[self dispatchBlock:^{
|
||||
[moduleData.instance partialBatchDidFlush];
|
||||
} queue:moduleData.methodQueue];
|
||||
@ -943,7 +1003,7 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithBundleURL:(__unused NSURL *)bundleUR
|
||||
{
|
||||
// TODO: batchDidComplete is only used by RCTUIManager - can we eliminate this special case?
|
||||
for (RCTModuleData *moduleData in _moduleDataByID) {
|
||||
if (moduleData.implementsBatchDidComplete) {
|
||||
if (moduleData.hasInstance && moduleData.implementsBatchDidComplete) {
|
||||
[self dispatchBlock:^{
|
||||
[moduleData.instance batchDidComplete];
|
||||
} queue:moduleData.methodQueue];
|
||||
|
@ -126,6 +126,17 @@ RCT_EXTERN NSString *RCTBridgeModuleNameForClass(Class bridgeModuleClass);
|
||||
*/
|
||||
- (BOOL)moduleIsInitialized:(Class)moduleClass;
|
||||
|
||||
/**
|
||||
* Call when your delegate's `whitelistedModulesForBridge:` value has changed.
|
||||
* In response to this, the bridge will immediately instantiate any (whitelisted)
|
||||
* native modules that require main thread initialization. Modules that do not require
|
||||
* main thread initialization will still be created lazily.
|
||||
*
|
||||
* This method must be called on the main thread, as any pending native modules
|
||||
* will be initialized immediately.
|
||||
*/
|
||||
- (void)whitelistedModulesDidChange;
|
||||
|
||||
/**
|
||||
* All registered bridge module classes.
|
||||
*/
|
||||
|
@ -17,6 +17,7 @@
|
||||
#import "RCTLog.h"
|
||||
#import "RCTModuleData.h"
|
||||
#import "RCTPerformanceLogger.h"
|
||||
#import "RCTProfile.h"
|
||||
#import "RCTUtils.h"
|
||||
|
||||
NSString *const RCTReloadNotification = @"RCTReloadNotification";
|
||||
@ -176,7 +177,6 @@ RCT_NOT_IMPLEMENTED(- (instancetype)init)
|
||||
object:nil
|
||||
userInfo:nil];
|
||||
}];
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -219,6 +219,11 @@ RCT_NOT_IMPLEMENTED(- (instancetype)init)
|
||||
return [self.batchedBridge moduleIsInitialized:moduleClass];
|
||||
}
|
||||
|
||||
- (void)whitelistedModulesDidChange
|
||||
{
|
||||
[self.batchedBridge whitelistedModulesDidChange];
|
||||
}
|
||||
|
||||
- (void)reload
|
||||
{
|
||||
/**
|
||||
@ -232,6 +237,8 @@ RCT_NOT_IMPLEMENTED(- (instancetype)init)
|
||||
|
||||
- (void)setUp
|
||||
{
|
||||
RCT_PROFILE_BEGIN_EVENT(0, @"-[RCTBridge setUp]", nil);
|
||||
|
||||
// Only update bundleURL from delegate if delegate bundleURL has changed
|
||||
NSURL *previousDelegateURL = _delegateBundleURL;
|
||||
_delegateBundleURL = [self.delegate sourceURLForBridge:self];
|
||||
@ -243,6 +250,8 @@ RCT_NOT_IMPLEMENTED(- (instancetype)init)
|
||||
_bundleURL = [RCTConvert NSURL:_bundleURL.absoluteString];
|
||||
|
||||
[self createBatchedBridge];
|
||||
|
||||
RCT_PROFILE_END_EVENT(0, @"", nil);
|
||||
}
|
||||
|
||||
- (void)createBatchedBridge
|
||||
|
@ -7,10 +7,11 @@
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*/
|
||||
|
||||
@class RCTBridge;
|
||||
|
||||
#import "RCTJavaScriptLoader.h"
|
||||
|
||||
@class RCTBridge;
|
||||
@protocol RCTBridgeModule;
|
||||
|
||||
@protocol RCTBridgeDelegate <NSObject>
|
||||
|
||||
/**
|
||||
@ -46,7 +47,31 @@
|
||||
* not recommended in most cases - if the module methods and behavior do not
|
||||
* match exactly, it may lead to bugs or crashes.
|
||||
*/
|
||||
- (NSArray *)extraModulesForBridge:(RCTBridge *)bridge;
|
||||
- (NSArray<id<RCTBridgeModule>> *)extraModulesForBridge:(RCTBridge *)bridge;
|
||||
|
||||
/**
|
||||
* Customize how bridge native modules are initialized.
|
||||
*
|
||||
* By default all modules are created lazily except those that have constants to export
|
||||
* or require main thread initialization. If you want to limit the set of native
|
||||
* modules that this should be considered for, implement this method.
|
||||
*
|
||||
* Return nil to whitelist all modules found. Modules passed in extraModulesForBridge:
|
||||
* are automatically whitelisted.
|
||||
*
|
||||
* @experimental
|
||||
*/
|
||||
- (NSArray<Class> *)whitelistedModulesForBridge:(RCTBridge *)bridge;
|
||||
|
||||
/**
|
||||
* When initializing native modules that require main thread initialization, the bridge
|
||||
* will default to dispatch module creation blocks asynchrously. If we're blockingly
|
||||
* waiting on the main thread to finish bridge creation on the main thread, this will
|
||||
* deadlock. Override this method to initialize modules synchronously instead.
|
||||
*
|
||||
* @experimental
|
||||
*/
|
||||
- (BOOL)shouldBridgeInitializeNativeModulesSynchronously:(RCTBridge *)bridge;
|
||||
|
||||
/**
|
||||
* The bridge will automatically attempt to load the JS source code from the
|
||||
|
@ -83,14 +83,14 @@ RCT_NOT_IMPLEMENTED(- (instancetype)init);
|
||||
|
||||
- (void)setUpInstanceAndBridge
|
||||
{
|
||||
RCT_PROFILE_BEGIN_EVENT(RCTProfileTagAlways, @"[RCTModuleData setUpInstanceAndBridge] [_instanceLock lock]", nil);
|
||||
RCT_PROFILE_BEGIN_EVENT(RCTProfileTagAlways, @"[RCTModuleData setUpInstanceAndBridge] [_instanceLock lock]", @{ @"moduleClass": _moduleClass });
|
||||
[_instanceLock lock];
|
||||
if (!_setupComplete && _bridge.valid) {
|
||||
if (!_instance) {
|
||||
if (RCT_DEBUG && _requiresMainQueueSetup) {
|
||||
RCTAssertMainQueue();
|
||||
}
|
||||
RCT_PROFILE_BEGIN_EVENT(RCTProfileTagAlways, @"[RCTModuleData setUpInstanceAndBridge] [_moduleClass new]", nil);
|
||||
RCT_PROFILE_BEGIN_EVENT(RCTProfileTagAlways, @"[RCTModuleData setUpInstanceAndBridge] [_moduleClass new]", @{ @"moduleClass": _moduleClass });
|
||||
_instance = [_moduleClass new];
|
||||
RCT_PROFILE_END_EVENT(RCTProfileTagAlways, @"", nil);
|
||||
if (!_instance) {
|
||||
@ -216,6 +216,10 @@ RCT_NOT_IMPLEMENTED(- (instancetype)init);
|
||||
// get accessed by client code during bridge setup, and a very low risk of
|
||||
// deadlock is better than a fairly high risk of an assertion being thrown.
|
||||
RCT_PROFILE_BEGIN_EVENT(RCTProfileTagAlways, @"[RCTModuleData instance] main thread setup", nil);
|
||||
|
||||
if (!RCTIsMainQueue()) {
|
||||
RCTLogWarn(@"RCTBridge required dispatch_sync to load %@. This may lead to deadlocks", _moduleClass);
|
||||
}
|
||||
RCTExecuteOnMainThread(^{
|
||||
[self setUpInstanceAndBridge];
|
||||
}, YES);
|
||||
@ -278,6 +282,9 @@ RCT_NOT_IMPLEMENTED(- (instancetype)init);
|
||||
if (_hasConstantsToExport && !_constantsToExport) {
|
||||
RCT_PROFILE_BEGIN_EVENT(RCTProfileTagAlways, [NSString stringWithFormat:@"[RCTModuleData gatherConstants] %@", _moduleClass], nil);
|
||||
(void)[self instance];
|
||||
if (!RCTIsMainQueue()) {
|
||||
RCTLogWarn(@"Required dispatch_sync to load constants for %@. This may lead to deadlocks", _moduleClass);
|
||||
}
|
||||
RCTExecuteOnMainThread(^{
|
||||
self->_constantsToExport = [self->_instance constantsToExport] ?: @{};
|
||||
}, YES);
|
||||
|
Loading…
x
Reference in New Issue
Block a user