Reviewed By: mhorowitz

Differential Revision: D3580025

fbshipit-source-id: 4422b6b97ef844158e369e022d62d6f0ae641222
This commit is contained in:
Pieter De Baets 2016-08-02 14:09:30 -07:00 коммит произвёл Facebook Github Bot 3
Родитель ed89d5ba0d
Коммит b83ccb5749
6 изменённых файлов: 40 добавлений и 150 удалений

Просмотреть файл

@ -16,9 +16,8 @@ const NativeModules = require('NativeModules');
const { UIManager } = NativeModules; const { UIManager } = NativeModules;
const findNodeHandle = require('react/lib/findNodeHandle'); const findNodeHandle = require('react/lib/findNodeHandle');
const invariant = require('fbjs/lib/invariant');
invariant(UIManager, 'UIManager is undefined. The native module config is probably incorrect.'); const _takeSnapshot = UIManager.takeSnapshot;
/** /**
* Capture an image of the screen, window or an individual view. The image * Capture an image of the screen, window or an individual view. The image
@ -40,13 +39,12 @@ invariant(UIManager, 'UIManager is undefined. The native module config is probab
UIManager.takeSnapshot = async function( UIManager.takeSnapshot = async function(
view ?: 'window' | ReactElement<any> | number, view ?: 'window' | ReactElement<any> | number,
options ?: { options ?: {
width ?: number, width ?: number;
height ?: number, height ?: number;
format ?: 'png' | 'jpeg', format ?: 'png' | 'jpeg';
quality ?: number, quality ?: number;
}, },
) { ) {
const _takeSnapshot = UIManager.takeSnapshot;
if (!_takeSnapshot) { if (!_takeSnapshot) {
console.warn('UIManager.takeSnapshot is not available on this platform'); console.warn('UIManager.takeSnapshot is not available on this platform');
return; return;

Просмотреть файл

@ -46,10 +46,9 @@ RCT_EXTERN NSArray<Class> *RCTGetModuleClasses(void);
{ {
BOOL _wasBatchActive; BOOL _wasBatchActive;
NSMutableArray<dispatch_block_t> *_pendingCalls; NSMutableArray<dispatch_block_t> *_pendingCalls;
NSDictionary<NSString *, RCTModuleData *> *_moduleDataByName; NSMutableDictionary<NSString *, RCTModuleData *> *_moduleDataByName;
NSArray<RCTModuleData *> *_moduleDataByID; NSArray<RCTModuleData *> *_moduleDataByID;
NSArray<Class> *_moduleClassesByID; NSArray<Class> *_moduleClassesByID;
NSUInteger _modulesInitializedOnMainQueue;
RCTDisplayLink *_displayLink; RCTDisplayLink *_displayLink;
} }
@ -100,8 +99,6 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithDelegate:(id<RCTBridgeDelegate>)dele
- (void)start - (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_queue_t bridgeQueue = dispatch_queue_create("com.facebook.react.RCTBridgeQueue", DISPATCH_QUEUE_CONCURRENT);
dispatch_group_t initModulesAndLoadSource = dispatch_group_create(); dispatch_group_t initModulesAndLoadSource = dispatch_group_create();
@ -140,11 +137,9 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithDelegate:(id<RCTBridgeDelegate>)dele
// Asynchronously gather the module config // Asynchronously gather the module config
dispatch_group_async(setupJSExecutorAndModuleConfig, bridgeQueue, ^{ dispatch_group_async(setupJSExecutorAndModuleConfig, bridgeQueue, ^{
if (weakSelf.valid) { if (weakSelf.valid) {
RCT_PROFILE_BEGIN_EVENT(0, @"-[RCTBatchedBridge moduleConfig", nil);
[performanceLogger markStartForTag:RCTPLNativeModulePrepareConfig]; [performanceLogger markStartForTag:RCTPLNativeModulePrepareConfig];
config = [weakSelf moduleConfig]; config = [weakSelf moduleConfig];
[performanceLogger markStopForTag:RCTPLNativeModulePrepareConfig]; [performanceLogger markStopForTag:RCTPLNativeModulePrepareConfig];
RCT_PROFILE_END_EVENT(0, @"", nil);
} }
}); });
@ -171,8 +166,6 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithDelegate:(id<RCTBridgeDelegate>)dele
[strongSelf executeSourceCode:sourceCode]; [strongSelf executeSourceCode:sourceCode];
} }
}); });
RCT_PROFILE_END_EVENT(0, @"", nil);
} }
- (void)loadSource:(RCTSourceLoadBlock)_onSourceLoad - (void)loadSource:(RCTSourceLoadBlock)_onSourceLoad
@ -240,13 +233,6 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithDelegate:(id<RCTBridgeDelegate>)dele
moduleData = _moduleDataByName[[@"RCT" stringByAppendingString:moduleName]]; moduleData = _moduleDataByName[[@"RCT" stringByAppendingString:moduleName]];
} }
if (moduleData) { 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 moduleData.config;
} }
return (id)kCFNull; return (id)kCFNull;
@ -254,7 +240,6 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithDelegate:(id<RCTBridgeDelegate>)dele
- (void)initModulesWithDispatchGroup:(dispatch_group_t)dispatchGroup - (void)initModulesWithDispatchGroup:(dispatch_group_t)dispatchGroup
{ {
RCT_PROFILE_BEGIN_EVENT(0, @"-[RCTBatchedBridge initModules]", nil);
[_performanceLogger markStartForTag:RCTPLNativeModuleInit]; [_performanceLogger markStartForTag:RCTPLNativeModuleInit];
NSArray<id<RCTBridgeModule>> *extraModules = nil; NSArray<id<RCTBridgeModule>> *extraModules = nil;
@ -267,6 +252,7 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithDelegate:(id<RCTBridgeDelegate>)dele
} }
if (RCT_DEBUG && !RCTRunningInTestEnvironment()) { if (RCT_DEBUG && !RCTRunningInTestEnvironment()) {
// Check for unexported modules // Check for unexported modules
static Class *classes; static Class *classes;
static unsigned int classCount; static unsigned int classCount;
@ -304,7 +290,6 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithDelegate:(id<RCTBridgeDelegate>)dele
NSMutableDictionary<NSString *, RCTModuleData *> *moduleDataByName = [NSMutableDictionary new]; NSMutableDictionary<NSString *, RCTModuleData *> *moduleDataByName = [NSMutableDictionary new];
// Set up moduleData for pre-initialized module instances // Set up moduleData for pre-initialized module instances
RCT_PROFILE_BEGIN_EVENT(0, @"extraModules", nil);
for (id<RCTBridgeModule> module in extraModules) { for (id<RCTBridgeModule> module in extraModules) {
Class moduleClass = [module class]; Class moduleClass = [module class];
NSString *moduleName = RCTBridgeModuleNameForClass(moduleClass); NSString *moduleName = RCTBridgeModuleNameForClass(moduleClass);
@ -332,13 +317,11 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithDelegate:(id<RCTBridgeDelegate>)dele
_javaScriptExecutor = (id<RCTJavaScriptExecutor>)module; _javaScriptExecutor = (id<RCTJavaScriptExecutor>)module;
} }
} }
RCT_PROFILE_END_EVENT(0, @"", nil);
// The executor is a bridge module, but we want it to be instantiated before // 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. // 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 // TODO: once we have more fine-grained control of init (t11106126) we can
// probably just replace this with [self moduleForClass:self.executorClass] // probably just replace this with [self moduleForClass:self.executorClass]
RCT_PROFILE_BEGIN_EVENT(0, @"JavaScriptExecutor", nil);
if (!_javaScriptExecutor) { if (!_javaScriptExecutor) {
id<RCTJavaScriptExecutor> executorModule = [self.executorClass new]; id<RCTJavaScriptExecutor> executorModule = [self.executorClass new];
RCTModuleData *moduleData = [[RCTModuleData alloc] initWithModuleInstance:executorModule RCTModuleData *moduleData = [[RCTModuleData alloc] initWithModuleInstance:executorModule
@ -350,10 +333,8 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithDelegate:(id<RCTBridgeDelegate>)dele
// NOTE: _javaScriptExecutor is a weak reference // NOTE: _javaScriptExecutor is a weak reference
_javaScriptExecutor = executorModule; _javaScriptExecutor = executorModule;
} }
RCT_PROFILE_END_EVENT(0, @"", nil);
// Set up moduleData for automatically-exported modules // Set up moduleData for automatically-exported modules
RCT_PROFILE_BEGIN_EVENT(0, @"ModuleData", nil);
for (Class moduleClass in RCTGetModuleClasses()) { for (Class moduleClass in RCTGetModuleClasses()) {
NSString *moduleName = RCTBridgeModuleNameForClass(moduleClass); NSString *moduleName = RCTBridgeModuleNameForClass(moduleClass);
@ -386,10 +367,8 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithDelegate:(id<RCTBridgeDelegate>)dele
_moduleDataByID = [moduleDataByID copy]; _moduleDataByID = [moduleDataByID copy];
_moduleDataByName = [moduleDataByName copy]; _moduleDataByName = [moduleDataByName copy];
_moduleClassesByID = [moduleClassesByID copy]; _moduleClassesByID = [moduleClassesByID copy];
RCT_PROFILE_END_EVENT(0, @"", nil);
// Synchronously set up the pre-initialized modules // Synchronously set up the pre-initialized modules
RCT_PROFILE_BEGIN_EVENT(0, @"extraModules", nil);
for (RCTModuleData *moduleData in _moduleDataByID) { for (RCTModuleData *moduleData in _moduleDataByID) {
if (moduleData.hasInstance && if (moduleData.hasInstance &&
(!moduleData.requiresMainQueueSetup || RCTIsMainQueue())) { (!moduleData.requiresMainQueueSetup || RCTIsMainQueue())) {
@ -402,79 +381,39 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithDelegate:(id<RCTBridgeDelegate>)dele
(void)[moduleData instance]; (void)[moduleData instance];
} }
} }
RCT_PROFILE_END_EVENT(0, @"", nil);
// From this point on, RCTDidInitializeModuleNotification notifications will // From this point on, RCTDidInitializeModuleNotification notifications will
// be sent the first time a module is accessed. // be sent the first time a module is accessed.
_moduleSetupComplete = YES; _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(shouldBridgeInitializeNativeModulesOnCurrentThread:)]) {
initializeImmediately = [self.delegate shouldBridgeInitializeNativeModulesOnCurrentThread:self];
}
// Set up modules that require main thread init or constants export // Set up modules that require main thread init or constants export
[_performanceLogger setValue:0 forTag:RCTPLNativeModuleMainThread]; [_performanceLogger setValue:0 forTag:RCTPLNativeModuleMainThread];
NSUInteger modulesOnMainQueueCount = 0;
for (RCTModuleData *moduleData in _moduleDataByID) { for (RCTModuleData *moduleData in _moduleDataByID) {
if (whitelistedModules && ![whitelistedModules containsObject:[moduleData moduleClass]]) { __weak RCTBatchedBridge *weakSelf = self;
continue;
}
if (moduleData.requiresMainQueueSetup || moduleData.hasConstantsToExport) { if (moduleData.requiresMainQueueSetup || moduleData.hasConstantsToExport) {
// Modules that need to be set up on the main thread cannot be initialized // 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, // 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 // 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 // modules on the main thread in parallel with loading the JS code, so
// they will already be available before they are ever required. // they will already be available before they are ever required.
dispatch_block_t block = ^{ dispatch_group_async(dispatchGroup, dispatch_get_main_queue(), ^{
if (self.valid) { RCTBatchedBridge *strongSelf = weakSelf;
[self->_performanceLogger appendStartForTag:RCTPLNativeModuleMainThread]; if (!strongSelf.valid) {
(void)[moduleData instance]; return;
[moduleData gatherConstants];
[self->_performanceLogger appendStopForTag:RCTPLNativeModuleMainThread];
} }
};
if (initializeImmediately && RCTIsMainQueue()) { [strongSelf->_performanceLogger appendStartForTag:RCTPLNativeModuleMainThread];
block(); (void)[moduleData instance];
} else { [moduleData gatherConstants];
// We've already checked that dispatchGroup is non-null, but this satisifies the [strongSelf->_performanceLogger appendStopForTag:RCTPLNativeModuleMainThread];
// Xcode analyzer });
if (dispatchGroup) { modulesOnMainQueueCount++;
dispatch_group_async(dispatchGroup, dispatch_get_main_queue(), block);
}
}
_modulesInitializedOnMainQueue++;
} }
} }
[_performanceLogger setValue:_modulesInitializedOnMainQueue forTag:RCTPLNativeModuleMainThreadUsesCount]; [_performanceLogger markStopForTag:RCTPLNativeModuleInit];
RCT_PROFILE_END_EVENT(0, @"", nil); [_performanceLogger setValue:modulesOnMainQueueCount forTag:RCTPLNativeModuleMainThreadUsesCount];
}
- (void)whitelistedModulesDidChange
{
[self prepareModulesWithDispatchGroup:NULL];
} }
- (void)setUpExecutor - (void)setUpExecutor
@ -658,22 +597,23 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithBundleURL:(__unused NSURL *)bundleUR
queue:(dispatch_queue_t)queue queue:(dispatch_queue_t)queue
{ {
if (queue == RCTJSThread) { if (queue == RCTJSThread) {
__weak __typeof(self) weakSelf = self;
RCTProfileBeginFlowEvent(); RCTProfileBeginFlowEvent();
RCTAssert(_javaScriptExecutor != nil, @"Need JS executor to schedule JS work"); RCTAssert(_javaScriptExecutor != nil, @"Need JS executor to schedule JS work");
[_javaScriptExecutor executeBlockOnJavaScriptQueue:^{ [_javaScriptExecutor executeBlockOnJavaScriptQueue:^{
RCTProfileEndFlowEvent(); RCTProfileEndFlowEvent();
RCT_PROFILE_BEGIN_EVENT(0, @"-[RCTBatchedBridge dispatchBlock", @{ @"loading": @(self.loading) }); RCTBatchedBridge *strongSelf = weakSelf;
if (!strongSelf) {
return;
}
if (self.loading) { if (strongSelf.loading) {
RCTAssert(self->_pendingCalls != nil, @"Can't add pending call, bridge is no longer loading"); [strongSelf->_pendingCalls addObject:block];
[self->_pendingCalls addObject:block];
} else { } else {
block(); block();
} }
RCT_PROFILE_END_EVENT(0, @"", nil);
}]; }];
} else if (queue) { } else if (queue) {
dispatch_async(queue, block); dispatch_async(queue, block);
@ -765,11 +705,11 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithBundleURL:(__unused NSURL *)bundleUR
/** /**
* AnyThread * AnyThread
*/ */
RCT_PROFILE_BEGIN_EVENT(RCTProfileTagAlways, @"-[RCTBatchedBridge enqueueJSCall:]", nil);
if (!_valid) { if (!_valid) {
return; return;
} }
RCT_PROFILE_BEGIN_EVENT(RCTProfileTagAlways, @"-[RCTBatchedBridge enqueueJSCall:]", nil);
__weak __typeof(self) weakSelf = self; __weak __typeof(self) weakSelf = self;
[self dispatchBlock:^{ [self dispatchBlock:^{
[weakSelf _actuallyInvokeAndProcessModule:module method:method arguments:args ?: @[]]; [weakSelf _actuallyInvokeAndProcessModule:module method:method arguments:args ?: @[]];
@ -777,6 +717,7 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithBundleURL:(__unused NSURL *)bundleUR
completion(); completion();
} }
} queue:RCTJSThread]; } queue:RCTJSThread];
RCT_PROFILE_END_EVENT(RCTProfileTagAlways, @"", nil); RCT_PROFILE_END_EVENT(RCTProfileTagAlways, @"", nil);
} }
@ -850,7 +791,7 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithBundleURL:(__unused NSURL *)bundleUR
{ {
RCTAssertJSThread(); RCTAssertJSThread();
__weak __typeof(self) weakSelf = self; __weak typeof(self) weakSelf = self;
[_javaScriptExecutor callFunctionOnModule:module [_javaScriptExecutor callFunctionOnModule:module
method:method method:method
arguments:args arguments:args
@ -864,7 +805,7 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithBundleURL:(__unused NSURL *)bundleUR
{ {
RCTAssertJSThread(); RCTAssertJSThread();
__weak __typeof(self) weakSelf = self; __weak typeof(self) weakSelf = self;
[_javaScriptExecutor invokeCallbackID:cbID [_javaScriptExecutor invokeCallbackID:cbID
arguments:args arguments:args
callback:^(id json, NSError *error) { callback:^(id json, NSError *error) {
@ -990,7 +931,7 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithBundleURL:(__unused NSURL *)bundleUR
- (void)partialBatchDidFlush - (void)partialBatchDidFlush
{ {
for (RCTModuleData *moduleData in _moduleDataByID) { for (RCTModuleData *moduleData in _moduleDataByID) {
if (moduleData.hasInstance && moduleData.implementsPartialBatchDidFlush) { if (moduleData.implementsPartialBatchDidFlush) {
[self dispatchBlock:^{ [self dispatchBlock:^{
[moduleData.instance partialBatchDidFlush]; [moduleData.instance partialBatchDidFlush];
} queue:moduleData.methodQueue]; } queue:moduleData.methodQueue];
@ -1002,7 +943,7 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithBundleURL:(__unused NSURL *)bundleUR
{ {
// TODO: batchDidComplete is only used by RCTUIManager - can we eliminate this special case? // TODO: batchDidComplete is only used by RCTUIManager - can we eliminate this special case?
for (RCTModuleData *moduleData in _moduleDataByID) { for (RCTModuleData *moduleData in _moduleDataByID) {
if (moduleData.hasInstance && moduleData.implementsBatchDidComplete) { if (moduleData.implementsBatchDidComplete) {
[self dispatchBlock:^{ [self dispatchBlock:^{
[moduleData.instance batchDidComplete]; [moduleData.instance batchDidComplete];
} queue:moduleData.methodQueue]; } queue:moduleData.methodQueue];

Просмотреть файл

@ -126,17 +126,6 @@ RCT_EXTERN NSString *RCTBridgeModuleNameForClass(Class bridgeModuleClass);
*/ */
- (BOOL)moduleIsInitialized:(Class)moduleClass; - (BOOL)moduleIsInitialized:(Class)moduleClass;
/**
* Call when your delegate's `whitelistedModulesForBridge:` value has changed.
* In response to this, the bridge will instantiate any (whitelisted) native modules
* that require main thread initialization, so we don't depend on dispatch_sync
* later on.
*
* 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. * All registered bridge module classes.
*/ */

Просмотреть файл

@ -17,7 +17,6 @@
#import "RCTLog.h" #import "RCTLog.h"
#import "RCTModuleData.h" #import "RCTModuleData.h"
#import "RCTPerformanceLogger.h" #import "RCTPerformanceLogger.h"
#import "RCTProfile.h"
#import "RCTUtils.h" #import "RCTUtils.h"
NSString *const RCTReloadNotification = @"RCTReloadNotification"; NSString *const RCTReloadNotification = @"RCTReloadNotification";
@ -177,6 +176,7 @@ RCT_NOT_IMPLEMENTED(- (instancetype)init)
object:nil object:nil
userInfo:nil]; userInfo:nil];
}]; }];
#endif #endif
} }
@ -219,11 +219,6 @@ RCT_NOT_IMPLEMENTED(- (instancetype)init)
return [self.batchedBridge moduleIsInitialized:moduleClass]; return [self.batchedBridge moduleIsInitialized:moduleClass];
} }
- (void)whitelistedModulesDidChange
{
[self.batchedBridge whitelistedModulesDidChange];
}
- (void)reload - (void)reload
{ {
/** /**
@ -237,8 +232,6 @@ RCT_NOT_IMPLEMENTED(- (instancetype)init)
- (void)setUp - (void)setUp
{ {
RCT_PROFILE_BEGIN_EVENT(0, @"-[RCTBridge setUp]", nil);
// Only update bundleURL from delegate if delegate bundleURL has changed // Only update bundleURL from delegate if delegate bundleURL has changed
NSURL *previousDelegateURL = _delegateBundleURL; NSURL *previousDelegateURL = _delegateBundleURL;
_delegateBundleURL = [self.delegate sourceURLForBridge:self]; _delegateBundleURL = [self.delegate sourceURLForBridge:self];
@ -250,8 +243,6 @@ RCT_NOT_IMPLEMENTED(- (instancetype)init)
_bundleURL = [RCTConvert NSURL:_bundleURL.absoluteString]; _bundleURL = [RCTConvert NSURL:_bundleURL.absoluteString];
[self createBatchedBridge]; [self createBatchedBridge];
RCT_PROFILE_END_EVENT(0, @"", nil);
} }
- (void)createBatchedBridge - (void)createBatchedBridge

Просмотреть файл

@ -7,10 +7,9 @@
* of patent rights can be found in the PATENTS file in the same directory. * of patent rights can be found in the PATENTS file in the same directory.
*/ */
#import "RCTJavaScriptLoader.h"
@class RCTBridge; @class RCTBridge;
@protocol RCTBridgeModule;
#import "RCTJavaScriptLoader.h"
@protocol RCTBridgeDelegate <NSObject> @protocol RCTBridgeDelegate <NSObject>
@ -47,28 +46,7 @@
* not recommended in most cases - if the module methods and behavior do not * not recommended in most cases - if the module methods and behavior do not
* match exactly, it may lead to bugs or crashes. * match exactly, it may lead to bugs or crashes.
*/ */
- (NSArray<id<RCTBridgeModule>> *)extraModulesForBridge:(RCTBridge *)bridge; - (NSArray *)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 subset 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 main-thread-only native modules, the bridge will be default
* 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.
*
* @experimental
*/
- (BOOL)shouldBridgeInitializeNativeModulesOnCurrentThread:(RCTBridge *)bridge;
/** /**
* The bridge will automatically attempt to load the JS source code from the * The bridge will automatically attempt to load the JS source code from the

Просмотреть файл

@ -83,14 +83,14 @@ RCT_NOT_IMPLEMENTED(- (instancetype)init);
- (void)setUpInstanceAndBridge - (void)setUpInstanceAndBridge
{ {
RCT_PROFILE_BEGIN_EVENT(RCTProfileTagAlways, @"[RCTModuleData setUpInstanceAndBridge] [_instanceLock lock]", @{ @"moduleClass": _moduleClass }); RCT_PROFILE_BEGIN_EVENT(RCTProfileTagAlways, @"[RCTModuleData setUpInstanceAndBridge] [_instanceLock lock]", nil);
[_instanceLock lock]; [_instanceLock lock];
if (!_setupComplete && _bridge.valid) { if (!_setupComplete && _bridge.valid) {
if (!_instance) { if (!_instance) {
if (RCT_DEBUG && _requiresMainQueueSetup) { if (RCT_DEBUG && _requiresMainQueueSetup) {
RCTAssertMainQueue(); RCTAssertMainQueue();
} }
RCT_PROFILE_BEGIN_EVENT(RCTProfileTagAlways, @"[RCTModuleData setUpInstanceAndBridge] [_moduleClass new]", @{ @"moduleClass": _moduleClass }); RCT_PROFILE_BEGIN_EVENT(RCTProfileTagAlways, @"[RCTModuleData setUpInstanceAndBridge] [_moduleClass new]", nil);
_instance = [_moduleClass new]; _instance = [_moduleClass new];
RCT_PROFILE_END_EVENT(RCTProfileTagAlways, @"", nil); RCT_PROFILE_END_EVENT(RCTProfileTagAlways, @"", nil);
if (!_instance) { if (!_instance) {
@ -216,10 +216,6 @@ RCT_NOT_IMPLEMENTED(- (instancetype)init);
// get accessed by client code during bridge setup, and a very low risk of // 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. // deadlock is better than a fairly high risk of an assertion being thrown.
RCT_PROFILE_BEGIN_EVENT(RCTProfileTagAlways, @"[RCTModuleData instance] main thread setup", nil); RCT_PROFILE_BEGIN_EVENT(RCTProfileTagAlways, @"[RCTModuleData instance] main thread setup", nil);
if (!RCTIsMainQueue()) {
RCTLogError(@"RCTBridge required dispatch_sync to load %@. This may lead to deadlocks", _moduleClass);
}
RCTExecuteOnMainThread(^{ RCTExecuteOnMainThread(^{
[self setUpInstanceAndBridge]; [self setUpInstanceAndBridge];
}, YES); }, YES);
@ -282,9 +278,6 @@ RCT_NOT_IMPLEMENTED(- (instancetype)init);
if (_hasConstantsToExport && !_constantsToExport) { if (_hasConstantsToExport && !_constantsToExport) {
RCT_PROFILE_BEGIN_EVENT(RCTProfileTagAlways, [NSString stringWithFormat:@"[RCTModuleData gatherConstants] %@", _moduleClass], nil); RCT_PROFILE_BEGIN_EVENT(RCTProfileTagAlways, [NSString stringWithFormat:@"[RCTModuleData gatherConstants] %@", _moduleClass], nil);
(void)[self instance]; (void)[self instance];
if (!RCTIsMainQueue()) {
RCTLogError(@"Required dispatch_sync to load constants for %@. This may lead to deadlocks", _moduleClass);
}
RCTExecuteOnMainThread(^{ RCTExecuteOnMainThread(^{
self->_constantsToExport = [self->_instance constantsToExport] ?: @{}; self->_constantsToExport = [self->_instance constantsToExport] ?: @{};
}, YES); }, YES);