Skip to content

Commit

Permalink
[Init] Add executor providers to RCTBridge's init method
Browse files Browse the repository at this point in the history
If you construct an RCTBridge you may want to configure the executor. However the constructor synchronously calls `setUp` and sets up the executor. Instead, let the code that constructs the bridge specify the executor and a debug executor up front. This allows for customizing the web view executor with a UIWebView of your choice, or configuring the URL of the debugger proxy that the web socket executor connects to.

Now that RCTRootView takes a bridge in one of its initializers, it is possible to create a bridge with a custom executor and then use that to set up a root view.

Fixes #288
  • Loading branch information
ide committed Apr 7, 2015
1 parent 1dba7e0 commit 73ce367
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 14 deletions.
16 changes: 14 additions & 2 deletions React/Base/RCTBridge.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,19 @@
/**
* This block can be used to instantiate modules that require additional
* init parameters, or additional configuration prior to being used.
* The bridge will call this block to instatiate the modules, and will
* The bridge will call this block to instantiate the modules, and will
* be responsible for invalidating/releasing them when the bridge is destroyed.
* For this reason, the block should always return new module instances, and
* module instances should not be shared between bridges.
*/
typedef NSArray *(^RCTBridgeModuleProviderBlock)(void);

/**
* A block that provides a new instance of an RCTJavaScript executor. The bridge
* will call this block to define the executor it uses.
*/
typedef id<RCTJavaScriptExecutor>(^RCTJavaScriptExecutorProviderBlock)(void);

extern NSString *const RCTReloadBridge;

/**
Expand All @@ -45,7 +51,13 @@ extern NSString *const RCTReloadBridge;
*/
- (instancetype)initWithBundlePath:(NSString *)bundlepath
moduleProvider:(RCTBridgeModuleProviderBlock)block
launchOptions:(NSDictionary *)launchOptions NS_DESIGNATED_INITIALIZER;
launchOptions:(NSDictionary *)launchOptions
executorBlock:(RCTJavaScriptExecutorProviderBlock)executorBlock
debugExecutorBlock:(RCTJavaScriptExecutorProviderBlock)debugExecutorBlock NS_DESIGNATED_INITIALIZER;

- (instancetype)initWithBundlePath:(NSString *)bundlepath
moduleProvider:(RCTBridgeModuleProviderBlock)block
launchOptions:(NSDictionary *)launchOptions;

/**
* This method is used to call functions in the JavaScript application context.
Expand Down
49 changes: 37 additions & 12 deletions React/Base/RCTBridge.m
Original file line number Diff line number Diff line change
Expand Up @@ -132,8 +132,6 @@ @implementation RCTModuleMethod
NSString *_methodName;
}

static Class _globalExecutorClass;

- (instancetype)initWithMethodName:(NSString *)methodName
JSMethodName:(NSString *)JSMethodName
{
Expand Down Expand Up @@ -506,7 +504,9 @@ @implementation RCTBridge
RCTSparseArray *_modulesByID;
NSDictionary *_modulesByName;
id<RCTJavaScriptExecutor> _javaScriptExecutor;
Class _executorClass;
RCTJavaScriptExecutorProviderBlock _executorBlock;
RCTJavaScriptExecutorProviderBlock _debugExecutorBlock;
BOOL _usingDebugExecutor;
NSString *_bundlePath;
NSDictionary *_launchOptions;
RCTBridgeModuleProviderBlock _moduleProvider;
Expand All @@ -518,25 +518,53 @@ @implementation RCTBridge
- (instancetype)initWithBundlePath:(NSString *)bundlePath
moduleProvider:(RCTBridgeModuleProviderBlock)block
launchOptions:(NSDictionary *)launchOptions
executorBlock:(RCTJavaScriptExecutorProviderBlock)executorBlock
debugExecutorBlock:(RCTJavaScriptExecutorProviderBlock)debugExecutorBlock
{
if ((self = [super init])) {
_bundlePath = bundlePath;
_moduleProvider = block;
_launchOptions = launchOptions;
_executorBlock = executorBlock;
_debugExecutorBlock = debugExecutorBlock;
[self setUp];
[self bindKeys];
}

return self;
}

- (instancetype)initWithBundlePath:(NSString *)bundlePath
moduleProvider:(RCTBridgeModuleProviderBlock)block
launchOptions:(NSDictionary *)launchOptions
{
return [self initWithBundlePath:bundlePath
moduleProvider:block
launchOptions:launchOptions
executorBlock:^{ return [[RCTContextExecutor alloc] init]; }
debugExecutorBlock:^{
Class executorClass = NSClassFromString(@"RCTWebSocketExecutor");
if (!executorClass) {
RCTLogError(@"WebSocket debugger is not available. Did you forget to include RCTWebSocketExecutor?");
executorClass = [RCTContextExecutor class];
}
return [[executorClass alloc] init];
}];
}

- (void)setUp
{
Class executorClass = _executorClass ?: _globalExecutorClass ?: [RCTContextExecutor class];
if ([NSStringFromClass(executorClass) isEqualToString:@"RCTWebViewExecutor"]) {
_javaScriptExecutor = [[RCTWebViewExecutor alloc] initWithWebView:[[UIWebView alloc] init]];
if (_usingDebugExecutor) {
if (_debugExecutorBlock) {
_javaScriptExecutor = _debugExecutorBlock();
} else {
RCTLogError(@"Attempting to debug without providing a debug executor; falling back to the default executor");
_javaScriptExecutor = _executorBlock();
}
} else {
_javaScriptExecutor = [[executorClass alloc] init];
_javaScriptExecutor = _executorBlock();
}

_latestJSExecutor = _javaScriptExecutor;
_eventDispatcher = [[RCTEventDispatcher alloc] initWithBridge:self];
_shadowQueue = dispatch_queue_create("com.facebook.ReactKit.ShadowQueue", DISPATCH_QUEUE_SERIAL);
Expand Down Expand Up @@ -643,17 +671,14 @@ - (void)bindKeys
[[RCTKeyCommands sharedInstance] registerKeyCommandWithInput:@"n"
modifierFlags:UIKeyModifierCommand
action:^(UIKeyCommand *command) {
_executorClass = Nil;
_usingDebugExecutor = NO;
[self reload];
}];

[[RCTKeyCommands sharedInstance] registerKeyCommandWithInput:@"d"
modifierFlags:UIKeyModifierCommand
action:^(UIKeyCommand *command) {
_executorClass = NSClassFromString(@"RCTWebSocketExecutor");
if (!_executorClass) {
RCTLogError(@"WebSocket debugger is not available. Did you forget to include RCTWebSocketExecutor?");
}
_usingDebugExecutor = YES;
[self reload];
}];
#endif
Expand Down

0 comments on commit 73ce367

Please sign in to comment.