Make the choice of bridge based on an optional delegate method

Reviewed By: javache

Differential Revision: D4679644

fbshipit-source-id: f53e554e283fdb0b59c41623e690fd1a21e03a57
This commit is contained in:
Marc Horowitz 2017-03-21 18:24:58 -07:00 committed by Facebook Github Bot
parent c41b29d6de
commit d9ac00735c
4 changed files with 42 additions and 64 deletions

View File

@ -302,7 +302,31 @@ RCT_NOT_IMPLEMENTED(- (instancetype)init)
- (void)createBatchedBridge - (void)createBatchedBridge
{ {
self.batchedBridge = [[RCTBatchedBridge alloc] initWithParentBridge:self]; // In order to facilitate switching between bridges with only build
// file changes, this uses reflection to check which bridges are
// available. This is a short-term hack until RCTBatchedBridge is
// removed.
Class batchedBridgeClass = objc_lookUpClass("RCTBatchedBridge");
Class cxxBridgeClass = objc_lookUpClass("RCTCxxBridge");
Class implClass = nil;
if ([self.delegate respondsToSelector:@selector(shouldBridgeUseCxxBridge:)]) {
if ([self.delegate shouldBridgeUseCxxBridge:self]) {
implClass = cxxBridgeClass;
} else {
implClass = batchedBridgeClass;
}
} else if (batchedBridgeClass != nil) {
implClass = batchedBridgeClass;
} else if (cxxBridgeClass != nil) {
implClass = cxxBridgeClass;
}
RCTAssert(implClass != nil, @"No bridge implementation is available, giving up.");
self.batchedBridge = [[implClass alloc] initWithParentBridge:self];
} }
- (BOOL)isLoading - (BOOL)isLoading

View File

@ -91,6 +91,20 @@
*/ */
- (BOOL)shouldBridgeUseCustomJSC:(RCTBridge *)bridge; - (BOOL)shouldBridgeUseCustomJSC:(RCTBridge *)bridge;
/**
* Configure whether the legacy RCTBatchedBridge or new RCTCxxBridge
* should be used. If this method is implemented and the specified
* bridge is not linked in, startup will fail. If this method is not
* implemented, the implementation will default to RCTBatchedBridge,
* but if it is not linked in, will try RCTCxxBridge instead. If
* neither bridge is linked in, startup will fail. This order will be
* reversed in the near future, as the legacy bridge is closer to
* being removed.
*
* @experimental
*/
- (BOOL)shouldBridgeUseCxxBridge:(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
* location specified by the `sourceURLForBridge:` method, however, if you want * location specified by the `sourceURLForBridge:` method, however, if you want

View File

@ -1,17 +0,0 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
#import <React/RCTBridge.h>
@interface RCTCxxBridge : RCTBridge
+ (void)enable;
+ (void)disable;
@end

View File

@ -9,8 +9,6 @@
* 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.
*/ */
#include "RCTCxxBridge.h"
#include <atomic> #include <atomic>
#include <future> #include <future>
#include <libkern/OSAtomic.h> #include <libkern/OSAtomic.h>
@ -48,6 +46,9 @@
#import <React/RCTFBSystrace.h> #import <React/RCTFBSystrace.h>
#endif #endif
@interface RCTCxxBridge : RCTBridge
@end
#define RCTAssertJSThread() \ #define RCTAssertJSThread() \
RCTAssert(self.executorClass || self->_jsThread == [NSThread currentThread], \ RCTAssert(self.executorClass || self->_jsThread == [NSThread currentThread], \
@"This method must be called on JS thread") @"This method must be called on JS thread")
@ -92,8 +93,6 @@ static bool isRAMBundle(NSData *script) {
return parseTypeFromHeader(header) == ScriptTag::RAMBundle; return parseTypeFromHeader(header) == ScriptTag::RAMBundle;
} }
static std::atomic_bool cxxBridgeEnabled(false);
@interface RCTCxxBridge () @interface RCTCxxBridge ()
@property (nonatomic, weak, readonly) RCTBridge *parentBridge; @property (nonatomic, weak, readonly) RCTBridge *parentBridge;
@ -121,19 +120,6 @@ struct RCTInstanceCallback : public InstanceCallback {
void onExecutorStopped(ExecutorToken) override {} void onExecutorStopped(ExecutorToken) override {}
}; };
@implementation RCTBridge (CxxBridge)
- (void)CXX_createBatchedBridge
{
if (cxxBridgeEnabled) {
self.batchedBridge = [[RCTCxxBridge alloc] initWithParentBridge:self];
} else {
self.batchedBridge = [[RCTBatchedBridge alloc] initWithParentBridge:self];
}
}
@end
@implementation RCTCxxBridge @implementation RCTCxxBridge
{ {
BOOL _wasBatchActive; BOOL _wasBatchActive;
@ -172,35 +158,6 @@ struct RCTInstanceCallback : public InstanceCallback {
} }
} }
+ (void)swizzleBridge
{
// Swizzle RCTBridge to use this, instead of RCTBatchedBridge
static dispatch_once_t once;
dispatch_once(&once, ^{
RCTSwapInstanceMethods([RCTBridge class],
NSSelectorFromString(@"createBatchedBridge"),
@selector(CXX_createBatchedBridge));
});
}
+ (void)enable
{
[RCTCxxBridge swizzleBridge];
#ifdef WITH_FBSYSTRACE
[RCTFBSystrace registerCallbacks];
#endif
cxxBridgeEnabled = true;
}
+ (void)disable
{
[RCTCxxBridge swizzleBridge];
#ifdef WITH_FBSYSTRACE
[RCTFBSystrace unregisterCallbacks];
#endif
cxxBridgeEnabled = false;
}
- (JSContext *)jsContext - (JSContext *)jsContext
{ {
return contextForGlobalContextRef((JSGlobalContextRef) self->_reactInstance->getJavaScriptContext()); return contextForGlobalContextRef((JSGlobalContextRef) self->_reactInstance->getJavaScriptContext());