diff --git a/React/Base/RCTBridge.m b/React/Base/RCTBridge.m index 5fa260caf..0fe05ca8b 100644 --- a/React/Base/RCTBridge.m +++ b/React/Base/RCTBridge.m @@ -302,7 +302,31 @@ RCT_NOT_IMPLEMENTED(- (instancetype)init) - (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 diff --git a/React/Base/RCTBridgeDelegate.h b/React/Base/RCTBridgeDelegate.h index 343a2275d..763933985 100644 --- a/React/Base/RCTBridgeDelegate.h +++ b/React/Base/RCTBridgeDelegate.h @@ -91,6 +91,20 @@ */ - (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 * location specified by the `sourceURLForBridge:` method, however, if you want diff --git a/React/CxxBridge/RCTCxxBridge.h b/React/CxxBridge/RCTCxxBridge.h deleted file mode 100644 index 89ac4d01e..000000000 --- a/React/CxxBridge/RCTCxxBridge.h +++ /dev/null @@ -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 - -@interface RCTCxxBridge : RCTBridge - -+ (void)enable; -+ (void)disable; - -@end diff --git a/React/CxxBridge/RCTCxxBridge.mm b/React/CxxBridge/RCTCxxBridge.mm index e48906af7..ee84db6be 100644 --- a/React/CxxBridge/RCTCxxBridge.mm +++ b/React/CxxBridge/RCTCxxBridge.mm @@ -9,8 +9,6 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -#include "RCTCxxBridge.h" - #include #include #include @@ -48,6 +46,9 @@ #import #endif +@interface RCTCxxBridge : RCTBridge +@end + #define RCTAssertJSThread() \ RCTAssert(self.executorClass || self->_jsThread == [NSThread currentThread], \ @"This method must be called on JS thread") @@ -92,8 +93,6 @@ static bool isRAMBundle(NSData *script) { return parseTypeFromHeader(header) == ScriptTag::RAMBundle; } -static std::atomic_bool cxxBridgeEnabled(false); - @interface RCTCxxBridge () @property (nonatomic, weak, readonly) RCTBridge *parentBridge; @@ -121,19 +120,6 @@ struct RCTInstanceCallback : public InstanceCallback { 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 { 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 { return contextForGlobalContextRef((JSGlobalContextRef) self->_reactInstance->getJavaScriptContext());