Cleanup bridge init, measure native module init time
This commit is contained in:
parent
8d07df4a22
commit
eab390aecb
|
@ -113,27 +113,26 @@ RCT_EXTERN NSArray *RCTGetModuleClasses(void);
|
|||
|
||||
- (void)start
|
||||
{
|
||||
__weak RCTBatchedBridge *weakSelf = self;
|
||||
|
||||
__block NSString *sourceCode;
|
||||
__block NSString *config;
|
||||
|
||||
dispatch_queue_t bridgeQueue = dispatch_queue_create("com.facebook.react.RCTBridgeQueue", DISPATCH_QUEUE_CONCURRENT);
|
||||
|
||||
dispatch_group_t initModulesAndLoadSource = dispatch_group_create();
|
||||
|
||||
dispatch_group_enter(initModulesAndLoadSource);
|
||||
[weakSelf loadSource:^(NSError *error, NSString *source) {
|
||||
if (error) {
|
||||
RCTLogError(@"%@", error);
|
||||
} else {
|
||||
sourceCode = source;
|
||||
}
|
||||
|
||||
__block NSString *sourceCode;
|
||||
[self loadSource:^(NSError *error, NSString *source) {
|
||||
sourceCode = source;
|
||||
dispatch_group_leave(initModulesAndLoadSource);
|
||||
}];
|
||||
|
||||
// Synchronously initialize all native modules
|
||||
[self initModules];
|
||||
|
||||
if (RCTProfileIsProfiling()) {
|
||||
// Depends on moduleDataByID being loaded
|
||||
RCTProfileHookModules(self);
|
||||
}
|
||||
|
||||
__weak RCTBatchedBridge *weakSelf = self;
|
||||
__block NSString *config;
|
||||
dispatch_group_enter(initModulesAndLoadSource);
|
||||
dispatch_async(bridgeQueue, ^{
|
||||
dispatch_group_t setupJSExecutorAndModuleConfig = dispatch_group_create();
|
||||
|
@ -144,16 +143,16 @@ RCT_EXTERN NSArray *RCTGetModuleClasses(void);
|
|||
dispatch_group_async(setupJSExecutorAndModuleConfig, bridgeQueue, ^{
|
||||
if (weakSelf.isValid) {
|
||||
config = [weakSelf moduleConfig];
|
||||
|
||||
if (RCTProfileIsProfiling()) {
|
||||
RCTProfileHookModules(weakSelf);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
dispatch_group_notify(setupJSExecutorAndModuleConfig, bridgeQueue, ^{
|
||||
[weakSelf injectJSONConfiguration:config onComplete:^(__unused NSError *error) {}];
|
||||
|
||||
// We're not waiting for this complete to leave the dispatch group, since
|
||||
// injectJSONConfiguration and executeSourceCode will schedule operations on the
|
||||
// same queue anyway.
|
||||
[weakSelf injectJSONConfiguration:config onComplete:^(__unused NSError *error) {
|
||||
RCTPerformanceLoggerEnd(RCTPLNativeModuleInit);
|
||||
}];
|
||||
dispatch_group_leave(initModulesAndLoadSource);
|
||||
});
|
||||
});
|
||||
|
@ -167,51 +166,52 @@ RCT_EXTERN NSArray *RCTGetModuleClasses(void);
|
|||
|
||||
- (void)loadSource:(RCTSourceLoadBlock)_onSourceLoad
|
||||
{
|
||||
RCTPerformanceLoggerStart(RCTPLScriptDownload);
|
||||
int cookie = RCTProfileBeginAsyncEvent(0, @"JavaScript download", nil);
|
||||
RCTPerformanceLoggerStart(RCTPLScriptDownload);
|
||||
int cookie = RCTProfileBeginAsyncEvent(0, @"JavaScript download", nil);
|
||||
|
||||
RCTSourceLoadBlock onSourceLoad = ^(NSError *error, NSString *source) {
|
||||
RCTPerformanceLoggerEnd(RCTPLScriptDownload);
|
||||
RCTProfileEndAsyncEvent(0, @"init,download", cookie, @"JavaScript download", nil);
|
||||
RCTSourceLoadBlock onSourceLoad = ^(NSError *error, NSString *source) {
|
||||
RCTProfileEndAsyncEvent(0, @"init,download", cookie, @"JavaScript download", nil);
|
||||
RCTPerformanceLoggerEnd(RCTPLScriptDownload);
|
||||
|
||||
if (error) {
|
||||
NSArray *stack = [error userInfo][@"stack"];
|
||||
if (stack) {
|
||||
[self.redBox showErrorMessage:error.localizedDescription
|
||||
withStack:stack];
|
||||
} else {
|
||||
[self.redBox showErrorMessage:error.localizedDescription
|
||||
withDetails:error.localizedFailureReason];
|
||||
}
|
||||
|
||||
NSDictionary *userInfo = @{@"bridge": self, @"error": error};
|
||||
[[NSNotificationCenter defaultCenter] postNotificationName:RCTJavaScriptDidFailToLoadNotification
|
||||
object:_parentBridge
|
||||
userInfo:userInfo];
|
||||
if (error) {
|
||||
NSArray *stack = [error userInfo][@"stack"];
|
||||
if (stack) {
|
||||
[self.redBox showErrorMessage:error.localizedDescription
|
||||
withStack:stack];
|
||||
} else {
|
||||
[self.redBox showErrorMessage:error.localizedDescription
|
||||
withDetails:error.localizedFailureReason];
|
||||
}
|
||||
|
||||
_onSourceLoad(error, source);
|
||||
};
|
||||
|
||||
if ([self.delegate respondsToSelector:@selector(loadSourceForBridge:withBlock:)]) {
|
||||
[self.delegate loadSourceForBridge:_parentBridge withBlock:onSourceLoad];
|
||||
} else if (self.bundleURL) {
|
||||
[RCTJavaScriptLoader loadBundleAtURL:self.bundleURL onComplete:onSourceLoad];
|
||||
} else {
|
||||
// Allow testing without a script
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
_loading = NO;
|
||||
[[NSNotificationCenter defaultCenter] postNotificationName:RCTJavaScriptDidLoadNotification
|
||||
object:_parentBridge
|
||||
userInfo:@{ @"bridge": self }];
|
||||
});
|
||||
onSourceLoad(nil, nil);
|
||||
NSDictionary *userInfo = @{@"bridge": self, @"error": error};
|
||||
[[NSNotificationCenter defaultCenter] postNotificationName:RCTJavaScriptDidFailToLoadNotification
|
||||
object:_parentBridge
|
||||
userInfo:userInfo];
|
||||
}
|
||||
|
||||
_onSourceLoad(error, source);
|
||||
};
|
||||
|
||||
if ([self.delegate respondsToSelector:@selector(loadSourceForBridge:withBlock:)]) {
|
||||
[self.delegate loadSourceForBridge:_parentBridge withBlock:onSourceLoad];
|
||||
} else if (self.bundleURL) {
|
||||
[RCTJavaScriptLoader loadBundleAtURL:self.bundleURL onComplete:onSourceLoad];
|
||||
} else {
|
||||
// Allow testing without a script
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
_loading = NO;
|
||||
[[NSNotificationCenter defaultCenter] postNotificationName:RCTJavaScriptDidLoadNotification
|
||||
object:_parentBridge
|
||||
userInfo:@{ @"bridge": self }];
|
||||
});
|
||||
onSourceLoad(nil, nil);
|
||||
}
|
||||
}
|
||||
|
||||
- (void)initModules
|
||||
{
|
||||
RCTAssertMainThread();
|
||||
RCTPerformanceLoggerStart(RCTPLNativeModuleInit);
|
||||
|
||||
// Register passed-in module instances
|
||||
NSMutableDictionary *preregisteredModules = [NSMutableDictionary new];
|
||||
|
@ -266,7 +266,6 @@ RCT_EXTERN NSArray *RCTGetModuleClasses(void);
|
|||
_javaScriptExecutor = _modulesByName[RCTBridgeModuleNameForClass(self.executorClass)];
|
||||
|
||||
for (id<RCTBridgeModule> module in _modulesByName.allValues) {
|
||||
|
||||
// Bridge must be set before moduleData is set up, as methodQueue
|
||||
// initialization requires it (View Managers get their queue by calling
|
||||
// self.bridge.uiManager.methodQueue)
|
||||
|
@ -288,7 +287,6 @@ RCT_EXTERN NSArray *RCTGetModuleClasses(void);
|
|||
- (void)setupExecutor
|
||||
{
|
||||
[_javaScriptExecutor setUp];
|
||||
|
||||
}
|
||||
|
||||
- (NSString *)moduleConfig
|
||||
|
@ -309,7 +307,7 @@ RCT_EXTERN NSArray *RCTGetModuleClasses(void);
|
|||
- (void)injectJSONConfiguration:(NSString *)configJSON
|
||||
onComplete:(void (^)(NSError *))onComplete
|
||||
{
|
||||
if (!self.isValid) {
|
||||
if (!self.valid) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -325,9 +323,7 @@ RCT_EXTERN NSArray *RCTGetModuleClasses(void);
|
|||
|
||||
- (void)executeSourceCode:(NSString *)sourceCode
|
||||
{
|
||||
_loading = NO;
|
||||
|
||||
if (!self.isValid || !_javaScriptExecutor) {
|
||||
if (!self.valid || !_javaScriptExecutor) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -336,22 +332,23 @@ RCT_EXTERN NSArray *RCTGetModuleClasses(void);
|
|||
sourceCodeModule.scriptText = sourceCode;
|
||||
|
||||
[self enqueueApplicationScript:sourceCode url:self.bundleURL onComplete:^(NSError *loadError) {
|
||||
|
||||
if (loadError) {
|
||||
[self.redBox showError:loadError];
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the display link to start sending js calls after everything
|
||||
* is setup
|
||||
*/
|
||||
// Register the display link to start sending js calls after everything is setup
|
||||
NSRunLoop *targetRunLoop = [_javaScriptExecutor isKindOfClass:[RCTContextExecutor class]] ? [NSRunLoop currentRunLoop] : [NSRunLoop mainRunLoop];
|
||||
[_jsDisplayLink addToRunLoop:targetRunLoop forMode:NSRunLoopCommonModes];
|
||||
|
||||
[[NSNotificationCenter defaultCenter] postNotificationName:RCTJavaScriptDidLoadNotification
|
||||
object:_parentBridge
|
||||
userInfo:@{ @"bridge": self }];
|
||||
// Perform the state update and notification on the main thread, so we can't run into
|
||||
// timing issues with RCTRootView
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
_loading = NO;
|
||||
[[NSNotificationCenter defaultCenter] postNotificationName:RCTJavaScriptDidLoadNotification
|
||||
object:_parentBridge
|
||||
userInfo:@{ @"bridge": self }];
|
||||
});
|
||||
}];
|
||||
}
|
||||
|
||||
|
@ -420,12 +417,13 @@ RCT_NOT_IMPLEMENTED(-initWithBundleURL:(__unused NSURL *)bundleURL
|
|||
|
||||
- (void)invalidate
|
||||
{
|
||||
if (!self.isValid) {
|
||||
if (!self.valid) {
|
||||
return;
|
||||
}
|
||||
|
||||
RCTAssertMainThread();
|
||||
|
||||
_loading = NO;
|
||||
_valid = NO;
|
||||
if ([RCTBridge currentBridge] == self) {
|
||||
[RCTBridge setCurrentBridge:nil];
|
||||
|
|
|
@ -186,8 +186,8 @@ static RCTBridge *RCTCurrentBridgeInstance = nil;
|
|||
_bundleURL = bundleURL;
|
||||
_moduleProvider = block;
|
||||
_launchOptions = [launchOptions copy];
|
||||
[self bindKeys];
|
||||
[self setUp];
|
||||
[self bindKeys];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
@ -214,21 +214,18 @@ RCT_NOT_IMPLEMENTED(-init)
|
|||
object:nil];
|
||||
|
||||
#if TARGET_IPHONE_SIMULATOR
|
||||
|
||||
RCTKeyCommands *commands = [RCTKeyCommands sharedInstance];
|
||||
|
||||
// reload in current mode
|
||||
[commands registerKeyCommandWithInput:@"r"
|
||||
modifierFlags:UIKeyModifierCommand
|
||||
action:^(__unused UIKeyCommand *command)
|
||||
{
|
||||
action:^(__unused UIKeyCommand *command) {
|
||||
[[NSNotificationCenter defaultCenter] postNotificationName:RCTReloadNotification
|
||||
object:nil
|
||||
userInfo:nil];
|
||||
}];
|
||||
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
- (RCTEventDispatcher *)eventDispatcher
|
||||
|
@ -260,6 +257,11 @@ RCT_NOT_IMPLEMENTED(-init)
|
|||
return _batchedBridge.loading;
|
||||
}
|
||||
|
||||
- (BOOL)isValid
|
||||
{
|
||||
return _batchedBridge.valid;
|
||||
}
|
||||
|
||||
- (void)invalidate
|
||||
{
|
||||
RCTAssertMainThread();
|
||||
|
|
|
@ -10,11 +10,11 @@
|
|||
#import <Foundation/Foundation.h>
|
||||
|
||||
#import "RCTDefines.h"
|
||||
#import "RCTBridgeModule.h"
|
||||
|
||||
typedef NS_ENUM(NSUInteger, RCTPLTag) {
|
||||
RCTPLScriptDownload = 0,
|
||||
RCTPLAppScriptExecution,
|
||||
RCTPLScriptExecution,
|
||||
RCTPLNativeModuleInit,
|
||||
RCTPLTTI,
|
||||
RCTPLSize
|
||||
};
|
||||
|
|
|
@ -27,12 +27,14 @@ void RCTPerformanceLoggerEnd(RCTPLTag tag)
|
|||
NSArray *RCTPerformanceLoggerOutput(void)
|
||||
{
|
||||
return @[
|
||||
@(RCTPLData[0][0]),
|
||||
@(RCTPLData[0][1]),
|
||||
@(RCTPLData[1][0]),
|
||||
@(RCTPLData[1][1]),
|
||||
@(RCTPLData[2][0]),
|
||||
@(RCTPLData[2][1]),
|
||||
@(RCTPLData[RCTPLScriptDownload][0]),
|
||||
@(RCTPLData[RCTPLScriptDownload][1]),
|
||||
@(RCTPLData[RCTPLScriptExecution][0]),
|
||||
@(RCTPLData[RCTPLScriptExecution][1]),
|
||||
@(RCTPLData[RCTPLNativeModuleInit][0]),
|
||||
@(RCTPLData[RCTPLNativeModuleInit][1]),
|
||||
@(RCTPLData[RCTPLTTI][0]),
|
||||
@(RCTPLData[RCTPLTTI][1]),
|
||||
];
|
||||
}
|
||||
|
||||
|
@ -71,6 +73,7 @@ RCT_EXPORT_MODULE()
|
|||
@[
|
||||
@"ScriptDownload",
|
||||
@"ScriptExecution",
|
||||
@"NativeModuleInit",
|
||||
@"TTI",
|
||||
],
|
||||
]];
|
||||
|
|
|
@ -160,10 +160,9 @@ RCT_NOT_IMPLEMENTED(-initWithCoder:(NSCoder *)aDecoder)
|
|||
|
||||
- (void)javaScriptDidLoad:(NSNotification *)notification
|
||||
{
|
||||
RCTAssertMainThread();
|
||||
RCTBridge *bridge = notification.userInfo[@"bridge"];
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
[self bundleFinishedLoading:bridge];
|
||||
});
|
||||
[self bundleFinishedLoading:bridge];
|
||||
}
|
||||
|
||||
- (void)bundleFinishedLoading:(RCTBridge *)bridge
|
||||
|
|
|
@ -458,14 +458,15 @@ static NSError *RCTNSErrorFromJSError(JSContextRef context, JSValueRef jsError)
|
|||
if (!strongSelf || !strongSelf.isValid) {
|
||||
return;
|
||||
}
|
||||
RCTPerformanceLoggerStart(RCTPLAppScriptExecution);
|
||||
|
||||
RCTPerformanceLoggerStart(RCTPLScriptExecution);
|
||||
JSValueRef jsError = NULL;
|
||||
JSStringRef execJSString = JSStringCreateWithCFString((__bridge CFStringRef)script);
|
||||
JSStringRef jsURL = JSStringCreateWithCFString((__bridge CFStringRef)sourceURL.absoluteString);
|
||||
JSValueRef result = JSEvaluateScript(strongSelf->_context.ctx, execJSString, NULL, jsURL, 0, &jsError);
|
||||
JSStringRelease(jsURL);
|
||||
JSStringRelease(execJSString);
|
||||
RCTPerformanceLoggerEnd(RCTPLAppScriptExecution);
|
||||
RCTPerformanceLoggerEnd(RCTPLScriptExecution);
|
||||
|
||||
if (onComplete) {
|
||||
NSError *error;
|
||||
|
|
Loading…
Reference in New Issue