1// Copyright 2015-present 650 Industries. All rights reserved. 2 3#import <EXDevMenu/DevMenuRCTBridge.h> 4 5// The search path for the Swift generated headers are different 6// between use_frameworks and non_use_frameworks mode. 7#if __has_include(<EXDevMenuInterface/EXDevMenuInterface-Swift.h>) 8#import <EXDevMenuInterface/EXDevMenuInterface-Swift.h> 9#else 10#import <EXDevMenuInterface-Swift.h> 11#endif 12#if __has_include(<ExpoModulesCore/ExpoModulesCore-Swift.h>) 13#import <ExpoModulesCore/ExpoModulesCore-Swift.h> 14#else 15#import <ExpoModulesCore-Swift.h> 16#endif 17#if __has_include(<EXDevMenu/EXDevMenu-Swift.h>) 18#import <EXDevMenu/EXDevMenu-Swift.h> 19#else 20#import <EXDevMenu-Swift.h> 21#endif 22#import <RCTCxxBridge+Private.h> 23 24#import <React/RCTPerformanceLogger.h> 25#import <React/RCTDevSettings.h> 26#import <React/RCTBridge+Private.h> 27#import <React/RCTDevMenu.h> 28#import <React/RCTCxxBridgeDelegate.h> 29#import <React/RCTJSIExecutorRuntimeInstaller.h> 30#import <React/RCTRuntimeExecutorFromBridge.h> 31#if __has_include(<React_RCTAppDelegate/RCTAppSetupUtils.h>) 32// for importing the header from framework, the dash will be transformed to underscore 33#import <React_RCTAppDelegate/RCTAppSetupUtils.h> 34#else 35#import <React-RCTAppDelegate/RCTAppSetupUtils.h> 36#endif 37#import <react/renderer/runtimescheduler/RuntimeScheduler.h> 38#if __has_include(<reacthermes/HermesExecutorFactory.h>) 39#import <reacthermes/HermesExecutorFactory.h> 40#endif 41 42 43 44@implementation DevMenuRCTCxxBridge 45 46- (instancetype)initWithParentBridge:(RCTBridge *)bridge 47{ 48 if ((self = [super initWithParentBridge:bridge])) { 49 RCTBridge *appBridge = DevMenuManager.shared.currentBridge; 50 // reset the singleton `RCTBridge.currentBridge` to app bridge instance 51 RCTBridge.currentBridge = appBridge != nil ? appBridge.batchedBridge : nil; 52 } 53 return self; 54} 55 56/** 57 * Theoretically, we could overwrite the `RCTDevSettings` module by exporting our version through the bridge. 58 * However, this won't work with the js remote debugging. For some reason, the RN needs to initialized remote tools very early. So it always uses the default module to do it. 59 * When we export our module, it won't be used in the initialized phase. So the dev-menu will start with remote debug support. 60 */ 61- (RCTDevSettings *)devSettings 62{ 63 // uncomment below to enable fast refresh for development builds of DevMenu 64 // return super.devSettings; 65 return nil; 66} 67 68- (RCTDevMenu *)devMenu 69{ 70 return nil; 71} 72 73- (NSArray<Class> *)filterModuleList:(NSArray<Class> *)modules 74{ 75 NSArray<NSString *> *allowedModules = @[@"RCT", @"ExpoBridgeModule", @"EXNativeModulesProxy", @"EXReactNativeEventEmitter"]; 76 NSArray<Class> *filteredModuleList = [modules filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(id _Nullable clazz, NSDictionary<NSString *,id> * _Nullable bindings) { 77 NSString* clazzName = NSStringFromClass(clazz); 78 79 if ([clazz conformsToProtocol:@protocol(EXDevExtensionProtocol)]) { 80 return true; 81 } 82 83 for (NSString *allowedModule in allowedModules) { 84 if ([clazzName hasPrefix:allowedModule]) { 85 return true; 86 } 87 } 88 return false; 89 }]]; 90 91 return filteredModuleList; 92} 93 94- (NSArray<RCTModuleData *> *)_initializeModules:(NSArray<Class> *)modules 95 withDispatchGroup:(dispatch_group_t)dispatchGroup 96 lazilyDiscovered:(BOOL)lazilyDiscovered 97{ 98 NSArray<Class> *filteredModuleList = [self filterModuleList: modules]; 99 return [super _initializeModules:filteredModuleList withDispatchGroup:dispatchGroup lazilyDiscovered:lazilyDiscovered]; 100} 101 102@end 103 104@implementation DevMenuRCTBridge 105 106- (Class)bridgeClass 107{ 108 return [DevMenuRCTCxxBridge class]; 109} 110 111#pragma clang diagnostic push 112#pragma clang diagnostic ignored "-Wdeprecated-implementations" 113// This method is still used so we need to override it even if it's deprecated 114- (void)reloadWithReason:(NSString *)reason {} 115#pragma clang diagnostic pop 116 117@end 118 119@interface DevClientAppDelegate (DevMenuRCTAppDelegate) 120 121#ifdef __cplusplus 122- (std::unique_ptr<facebook::react::JSExecutorFactory>)jsExecutorFactoryForBridge:(RCTBridge *)bridge; 123#endif 124@end 125 126@implementation DevMenuRCTAppDelegate 127 128 129- (RCTBridge *)createBridgeWithDelegate:(id<RCTBridgeDelegate>)delegate launchOptions:(NSDictionary *)launchOptions 130{ 131 return [[DevMenuRCTBridge alloc] initWithDelegate:delegate launchOptions:launchOptions]; 132} 133 134#pragma mark - RCTCxxBridgeDelegate 135- (std::unique_ptr<facebook::react::JSExecutorFactory>)jsExecutorFactoryForBridge:(RCTBridge *)bridge 136{ 137 std::unique_ptr<facebook::react::JSExecutorFactory> executorFactory = [super jsExecutorFactoryForBridge:bridge]; 138 139 #if __has_include(<reacthermes/HermesExecutorFactory.h>) 140 auto rawExecutorFactory = executorFactory.get(); 141 auto hermesExecFactory = dynamic_cast<facebook::react::HermesExecutorFactory*>(rawExecutorFactory); 142 if (hermesExecFactory != nullptr) { 143 hermesExecFactory->setEnableDebugger(false); 144 } 145 #endif 146 147 return executorFactory; 148} 149 150@end 151