mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
Interop: Introduce Bridge proxy
Summary: The TurboModule interop layer on iOS will ship with a Bridge proxy. The Bridge proxy is an object that will try to simulate the Bridge's APIs, whenever possible, by delegating to Bridgeless abstractions. ## Changes This diff introduces the Bridge proxy. This diff starts attaching the Bridge proxy on legacy native module objects. ## How did we polyfill the APIs The polyfills can be classified into these categories: - implemented - custom warning - custom error - default error - deleted When there was a sane implementation (e.g: the API belonged to [RCTCallableJSModules](https://www.internalfb.com/code/fbsource/[534223aa13d33b595edcb777189618efe20dd167]/xplat/js/react-native-github/React/Base/RCTCallableJSModules.m?lines=11), [RCTModuleRegistry](https://www.internalfb.com/code/fbsource/[9a3ba2b3176b6d1a1f161e33cec51bf892815311]/xplat/js/react-native-github/React/Base/RCTModuleRegistry.m?lines=13), [RCTBundleManager](https://www.internalfb.com/code/fbsource/[91fa1f7f49731a16aedbcd5a6740647dc21ff727]/xplat/js/react-native-github/React/Base/RCTBundleManager.m?lines=13), or [RCTBundleManager](https://www.internalfb.com/code/fbsource/[91fa1f7f49731a16aedbcd5a6740647dc21ff727]/xplat/js/react-native-github/React/Base/RCTBundleManager.m?lines=13)), it was implemented. When it was safe to no-op the API (e.g: loading), it emit a custom warning. When it was unsafe to call (i.e: we didn't want people calling the API) (e.g: RCTCxxBridge start), it emit a custom error. All other APIs emit default errors. Some APIs cannot emit errors because doing so makes the app not render: I put warnings and nooped those APIs. I think we will have to tune these polyfills based off production crashes/results. Reviewed By: mdvacca Differential Revision: D46084318 fbshipit-source-id: c02535073956597a4bf91c14b1980f653cb6d3df
This commit is contained in:
committed by
Facebook GitHub Bot
parent
3e3032636d
commit
7bc2b730a8
@@ -8,6 +8,7 @@
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
#import <React/RCTBridge.h>
|
||||
#import <React/RCTBridgeProxy.h>
|
||||
#import <React/RCTDefines.h>
|
||||
#import <React/RCTImageCache.h>
|
||||
#import <React/RCTImageDataDecoder.h>
|
||||
@@ -34,3 +35,9 @@
|
||||
@property (nonatomic, readonly) RCTImageLoader *imageLoader;
|
||||
|
||||
@end
|
||||
|
||||
@interface RCTBridgeProxy (RCTImageLoader)
|
||||
|
||||
@property (nonatomic, readonly) RCTImageLoader *imageLoader;
|
||||
|
||||
@end
|
||||
|
||||
@@ -1293,6 +1293,15 @@ RCT_EXPORT_METHOD(queryCache
|
||||
|
||||
@end
|
||||
|
||||
@implementation RCTBridgeProxy (RCTImageLoader)
|
||||
|
||||
- (RCTImageLoader *)imageLoader
|
||||
{
|
||||
return [self moduleForClass:[RCTImageLoader class]];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
Class RCTImageLoaderCls(void)
|
||||
{
|
||||
return RCTImageLoader.class;
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
#import <React/RCTBridge.h>
|
||||
#import <React/RCTBridgeProxy.h>
|
||||
#import <React/RCTURLRequestHandler.h>
|
||||
|
||||
@interface RCTImageStoreManager : NSObject <RCTURLRequestHandler>
|
||||
@@ -44,3 +45,9 @@
|
||||
@property (nonatomic, readonly) RCTImageStoreManager *imageStoreManager;
|
||||
|
||||
@end
|
||||
|
||||
@interface RCTBridgeProxy (RCTImageStoreManager)
|
||||
|
||||
@property (nonatomic, readonly) RCTImageStoreManager *imageStoreManager;
|
||||
|
||||
@end
|
||||
|
||||
@@ -254,6 +254,15 @@ RCT_EXPORT_METHOD(addImageFromBase64
|
||||
|
||||
@end
|
||||
|
||||
@implementation RCTBridgeProxy (RCTImageStoreManager)
|
||||
|
||||
- (RCTImageStoreManager *)imageStoreManager
|
||||
{
|
||||
return [self moduleForClass:[RCTImageStoreManager class]];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
Class RCTImageStoreManagerCls(void)
|
||||
{
|
||||
return RCTImageStoreManager.class;
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#import <React/RCTBridgeProxy.h>
|
||||
#import <React/RCTEventEmitter.h>
|
||||
#import <React/RCTNetworkTask.h>
|
||||
#import <React/RCTURLRequestHandler.h>
|
||||
@@ -61,6 +62,12 @@
|
||||
|
||||
@end
|
||||
|
||||
@interface RCTBridgeProxy (RCTNetworking)
|
||||
|
||||
@property (nonatomic, readonly) RCTNetworking *networking;
|
||||
|
||||
@end
|
||||
|
||||
// HACK: When uploading images/video from PHAssetLibrary, we change the URL scheme to be
|
||||
// ph-upload://. This is to ensure that we upload a full video when given a ph-upload:// URL,
|
||||
// instead of just the thumbnail. Consider the following problem:
|
||||
|
||||
@@ -762,6 +762,15 @@ RCT_EXPORT_METHOD(clearCookies : (RCTResponseSenderBlock)responseSender)
|
||||
|
||||
@end
|
||||
|
||||
@implementation RCTBridgeProxy (RCTNetworking)
|
||||
|
||||
- (RCTNetworking *)networking
|
||||
{
|
||||
return [self moduleForClass:[RCTNetworking class]];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
Class RCTNetworkingCls(void)
|
||||
{
|
||||
return RCTNetworking.class;
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#import "RCTBridgeModule.h"
|
||||
|
||||
@class RCTBundleManager;
|
||||
@class RCTCallableJSModules;
|
||||
@class RCTModuleRegistry;
|
||||
@class RCTViewRegistry;
|
||||
|
||||
@interface RCTBridgeProxy : NSProxy
|
||||
- (instancetype)initWithViewRegistry:(RCTViewRegistry *)viewRegistry
|
||||
moduleRegistry:(RCTModuleRegistry *)moduleRegistry
|
||||
bundleManager:(RCTBundleManager *)bundleManager
|
||||
callableJSModules:(RCTCallableJSModules *)callableJSModules
|
||||
dispatchToJSThread:(void (^)(dispatch_block_t))dispatchToJSThread NS_DESIGNATED_INITIALIZER;
|
||||
|
||||
- (NSMethodSignature *)methodSignatureForSelector:(SEL)sel;
|
||||
- (void)forwardInvocation:(NSInvocation *)invocation;
|
||||
|
||||
- (void)logWarning:(NSString *)message cmd:(SEL)cmd;
|
||||
- (void)logError:(NSString *)message cmd:(SEL)cmd;
|
||||
|
||||
/**
|
||||
* Methods required for RCTBridge class extensions
|
||||
*/
|
||||
- (id)moduleForClass:(Class)moduleClass;
|
||||
- (id)moduleForName:(NSString *)moduleName lazilyLoadIfNecessary:(BOOL)lazilyLoad;
|
||||
@end
|
||||
@@ -0,0 +1,447 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#import "RCTBridgeProxy.h"
|
||||
#import <React/RCTBridge+Private.h>
|
||||
#import <React/RCTBridge.h>
|
||||
#import <React/RCTLog.h>
|
||||
#import <React/RCTUIManager.h>
|
||||
#import <jsi/jsi.h>
|
||||
|
||||
using namespace facebook;
|
||||
|
||||
@interface RCTUIManagerProxy : NSProxy
|
||||
- (instancetype)initWithViewRegistry:(RCTViewRegistry *)viewRegistry NS_DESIGNATED_INITIALIZER;
|
||||
|
||||
- (NSMethodSignature *)methodSignatureForSelector:(SEL)sel;
|
||||
- (void)forwardInvocation:(NSInvocation *)invocation;
|
||||
@end
|
||||
|
||||
@implementation RCTBridgeProxy {
|
||||
RCTUIManagerProxy *_uiManagerProxy;
|
||||
RCTModuleRegistry *_moduleRegistry;
|
||||
RCTBundleManager *_bundleManager;
|
||||
RCTCallableJSModules *_callableJSModules;
|
||||
void (^_dispatchToJSThread)(dispatch_block_t);
|
||||
}
|
||||
|
||||
- (instancetype)initWithViewRegistry:(RCTViewRegistry *)viewRegistry
|
||||
moduleRegistry:(RCTModuleRegistry *)moduleRegistry
|
||||
bundleManager:(RCTBundleManager *)bundleManager
|
||||
callableJSModules:(RCTCallableJSModules *)callableJSModules
|
||||
dispatchToJSThread:(void (^)(dispatch_block_t))dispatchToJSThread
|
||||
{
|
||||
self = [super self];
|
||||
if (self) {
|
||||
self->_uiManagerProxy = [[RCTUIManagerProxy alloc] initWithViewRegistry:viewRegistry];
|
||||
self->_moduleRegistry = moduleRegistry;
|
||||
self->_bundleManager = bundleManager;
|
||||
self->_callableJSModules = callableJSModules;
|
||||
self->_dispatchToJSThread = dispatchToJSThread;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)dispatchBlock:(dispatch_block_t)block queue:(dispatch_queue_t)queue
|
||||
{
|
||||
[self logWarning:@"Please migrate to dispatchToJSThread: @synthesize dispatchToJSThread = _dispatchToJSThread"
|
||||
cmd:_cmd];
|
||||
|
||||
if (queue == RCTJSThread) {
|
||||
_dispatchToJSThread(block);
|
||||
} else if (queue) {
|
||||
dispatch_async(queue, block);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Used By:
|
||||
* - RCTDevSettings
|
||||
*/
|
||||
- (Class)executorClass
|
||||
{
|
||||
[self logWarning:@"This method is unsupported. Returning nil." cmd:_cmd];
|
||||
return nil;
|
||||
}
|
||||
|
||||
/**
|
||||
* Used By:
|
||||
* - RCTBlobCollector
|
||||
*/
|
||||
- (jsi::Runtime *)runtime
|
||||
{
|
||||
[self logWarning:@"This method is unsupported. Returning nullptr." cmd:_cmd];
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* RCTModuleRegistry
|
||||
*/
|
||||
- (id)moduleForName:(NSString *)moduleName
|
||||
{
|
||||
[self logWarning:@"Please migrate to RCTModuleRegistry: @synthesize moduleRegistry = _moduleRegistry." cmd:_cmd];
|
||||
return [_moduleRegistry moduleForName:[moduleName UTF8String]];
|
||||
}
|
||||
|
||||
- (id)moduleForName:(NSString *)moduleName lazilyLoadIfNecessary:(BOOL)lazilyLoad
|
||||
{
|
||||
[self logWarning:@"Please migrate to RCTModuleRegistry: @synthesize moduleRegistry = _moduleRegistry." cmd:_cmd];
|
||||
return [_moduleRegistry moduleForName:[moduleName UTF8String] lazilyLoadIfNecessary:lazilyLoad];
|
||||
}
|
||||
|
||||
- (id)moduleForClass:(Class)moduleClass
|
||||
{
|
||||
[self logWarning:@"Please migrate to RCTModuleRegistry: @synthesize moduleRegistry = _moduleRegistry." cmd:_cmd];
|
||||
NSString *moduleName = RCTBridgeModuleNameForClass(moduleClass);
|
||||
return [_moduleRegistry moduleForName:[moduleName UTF8String] lazilyLoadIfNecessary:YES];
|
||||
}
|
||||
|
||||
- (NSArray *)modulesConformingToProtocol:(Protocol *)protocol
|
||||
{
|
||||
[self logError:@"The TurboModule system cannot load modules by protocol. Returning an empty NSArray*." cmd:_cmd];
|
||||
return @[];
|
||||
}
|
||||
|
||||
- (BOOL)moduleIsInitialized:(Class)moduleClass
|
||||
{
|
||||
[self logWarning:@"Please migrate to RCTModuleRegistry: @synthesize moduleRegistry = _moduleRegistry." cmd:_cmd];
|
||||
return [_moduleRegistry moduleIsInitialized:moduleClass];
|
||||
}
|
||||
|
||||
- (NSArray<Class> *)moduleClasses
|
||||
{
|
||||
[self logError:@"The TurboModuleManager does not implement this method. Returning an empty NSArray*." cmd:_cmd];
|
||||
return @[];
|
||||
}
|
||||
|
||||
/**
|
||||
* RCTBundleManager
|
||||
*/
|
||||
- (void)setBundleURL:(NSURL *)bundleURL
|
||||
{
|
||||
[self logWarning:@"Please migrate to RCTBundleManager: @synthesize bundleManager = _bundleManager." cmd:_cmd];
|
||||
[_bundleManager setBundleURL:bundleURL];
|
||||
}
|
||||
|
||||
- (NSURL *)bundleURL
|
||||
{
|
||||
[self logWarning:@"Please migrate to RCTBundleManager: @synthesize bundleManager = _bundleManager." cmd:_cmd];
|
||||
return [_bundleManager bundleURL];
|
||||
}
|
||||
|
||||
/**
|
||||
* RCTCallableJSModules
|
||||
*/
|
||||
- (void)enqueueJSCall:(NSString *)moduleDotMethod args:(NSArray *)args
|
||||
{
|
||||
[self logWarning:@"Please migrate to RCTCallableJSModules: @synthesize callableJSModules = _callableJSModules."
|
||||
cmd:_cmd];
|
||||
|
||||
NSArray<NSString *> *ids = [moduleDotMethod componentsSeparatedByString:@"."];
|
||||
NSString *module = ids[0];
|
||||
NSString *method = ids[1];
|
||||
[_callableJSModules invokeModule:module method:method withArgs:args];
|
||||
}
|
||||
|
||||
- (void)enqueueJSCall:(NSString *)module
|
||||
method:(NSString *)method
|
||||
args:(NSArray *)args
|
||||
completion:(dispatch_block_t)completion
|
||||
{
|
||||
[self logWarning:@"Please migrate to RCTCallableJSModules: @synthesize callableJSModules = _callableJSModules."
|
||||
cmd:_cmd];
|
||||
[_callableJSModules invokeModule:module method:method withArgs:args onComplete:completion];
|
||||
}
|
||||
|
||||
- (void)registerSegmentWithId:(NSUInteger)segmentId path:(NSString *)path
|
||||
{
|
||||
[self logError:@"Please migrate to RCTHost registerSegmentWithId. Nooping" cmd:_cmd];
|
||||
}
|
||||
|
||||
- (id<RCTBridgeDelegate>)delegate
|
||||
{
|
||||
[self logError:@"This method is unsupported. Returning nil." cmd:_cmd];
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (NSDictionary *)launchOptions
|
||||
{
|
||||
[self logError:@"Bridgeless mode doesn't support launchOptions. Returning nil." cmd:_cmd];
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (BOOL)loading
|
||||
{
|
||||
[self logWarning:@"This method is not implemented. Returning NO." cmd:_cmd];
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (BOOL)valid
|
||||
{
|
||||
[self logWarning:@"This method is not implemented. Returning NO." cmd:_cmd];
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (RCTPerformanceLogger *)performanceLogger
|
||||
{
|
||||
[self logWarning:@"Bridgeless mode does not support RCTPerformanceLogger. Returning nil." cmd:_cmd];
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (void)reload
|
||||
{
|
||||
[self logError:@"Please use RCTReloadCommand instead. Nooping." cmd:_cmd];
|
||||
}
|
||||
|
||||
- (void)reloadWithReason:(NSString *)reason
|
||||
{
|
||||
[self logError:@"Please use RCTReloadCommand instead. Nooping." cmd:_cmd];
|
||||
}
|
||||
|
||||
- (void)onFastRefresh
|
||||
{
|
||||
[[NSNotificationCenter defaultCenter] postNotificationName:RCTBridgeFastRefreshNotification object:self];
|
||||
}
|
||||
|
||||
- (void)requestReload __deprecated_msg("Use RCTReloadCommand instead")
|
||||
{
|
||||
[self logError:@"Please use RCTReloadCommand instead. Nooping." cmd:_cmd];
|
||||
}
|
||||
|
||||
- (BOOL)isBatchActive
|
||||
{
|
||||
[self logWarning:@"Bridgeless mode does not support batching. Returning NO." cmd:_cmd];
|
||||
return NO;
|
||||
}
|
||||
|
||||
/**
|
||||
* RCTBridge ()
|
||||
*/
|
||||
|
||||
- (NSString *)bridgeDescription
|
||||
{
|
||||
[self logWarning:@"Bridgeless mode does not support bridgeDescription. Returning \"BridgeProxy\"." cmd:_cmd];
|
||||
return @"BridgeProxy";
|
||||
}
|
||||
|
||||
- (void)enqueueCallback:(NSNumber *)cbID args:(NSArray *)args
|
||||
{
|
||||
[self logError:@"Bridgeless mode does not queuing callbacks by ids. No-oping." cmd:_cmd];
|
||||
}
|
||||
|
||||
- (RCTBridge *)batchedBridge
|
||||
{
|
||||
[self logWarning:@"Bridgeless mode does not support batchedBridge. Returning bridge proxy." cmd:_cmd];
|
||||
return (RCTBridge *)self;
|
||||
}
|
||||
|
||||
- (void)setBatchedBridge
|
||||
{
|
||||
[self logError:@"Bridgeless mode does not support setBatchedBridge. No-oping." cmd:_cmd];
|
||||
}
|
||||
|
||||
- (RCTBridgeModuleListProvider)moduleProvider
|
||||
{
|
||||
[self logWarning:@"Bridgeless mode does not support RCTBridgeModuleListProvider. Returning empty block" cmd:_cmd];
|
||||
return ^{
|
||||
return @[];
|
||||
};
|
||||
}
|
||||
|
||||
- (RCTModuleRegistry *)moduleRegistry
|
||||
{
|
||||
return _moduleRegistry;
|
||||
}
|
||||
|
||||
/**
|
||||
* RCTBridge (RCTCxxBridge)
|
||||
*/
|
||||
|
||||
- (RCTBridge *)parentBridge
|
||||
{
|
||||
[self logWarning:@"Bridgeless mode does not support parentBridge. Returning bridge proxy." cmd:_cmd];
|
||||
return (RCTBridge *)self;
|
||||
}
|
||||
|
||||
- (BOOL)moduleSetupComplete
|
||||
{
|
||||
[self logWarning:@"Bridgeless mode does not implement moduleSetupComplete. Returning YES." cmd:_cmd];
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (void)start
|
||||
{
|
||||
[self
|
||||
logError:
|
||||
@"Starting the bridge proxy does nothing. If you want to start React Native, please use RCTHost start. Nooping"
|
||||
cmd:_cmd];
|
||||
}
|
||||
|
||||
- (void)registerModuleForFrameUpdates:(id<RCTBridgeModule>)module withModuleData:(RCTModuleData *)moduleData
|
||||
{
|
||||
[self logError:@"Bridgeless mode does not allow custom modules to register themselves for frame updates. Nooping"
|
||||
cmd:_cmd];
|
||||
}
|
||||
|
||||
- (RCTModuleData *)moduleDataForName:(NSString *)moduleName
|
||||
{
|
||||
[self logError:@"Bridgeless mode does not use RCTModuleData. Returning nil." cmd:_cmd];
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (void)registerAdditionalModuleClasses:(NSArray<Class> *)newModules
|
||||
{
|
||||
[self
|
||||
logError:
|
||||
@"This API is unsupported. Please return all module classes from your app's RCTTurboModuleManagerDelegate getModuleClassFromName:. Nooping."
|
||||
cmd:_cmd];
|
||||
}
|
||||
|
||||
- (void)updateModuleWithInstance:(id<RCTBridgeModule>)instance
|
||||
{
|
||||
[self logError:@"Bridgeless mode does not support module replacement. Nooping." cmd:_cmd];
|
||||
}
|
||||
|
||||
- (void)startProfiling
|
||||
{
|
||||
[self logWarning:@"Bridgeless mode does not support this method. Nooping." cmd:_cmd];
|
||||
}
|
||||
|
||||
- (void)stopProfiling:(void (^)(NSData *))callback
|
||||
{
|
||||
[self logWarning:@"Bridgeless mode does not support this method. Nooping." cmd:_cmd];
|
||||
}
|
||||
|
||||
- (id)callNativeModule:(NSUInteger)moduleID method:(NSUInteger)methodID params:(NSArray *)params
|
||||
{
|
||||
[self logError:@"Bridgeless mode does not support this method. Nooping and returning nil." cmd:_cmd];
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (void)logMessage:(NSString *)message level:(NSString *)level
|
||||
{
|
||||
[self logWarning:@"Bridgeless mode does not support this method. Nooping." cmd:_cmd];
|
||||
}
|
||||
|
||||
- (void)_immediatelyCallTimer:(NSNumber *)timer
|
||||
{
|
||||
[self logWarning:@"Bridgeless mode does not support this method. Nooping." cmd:_cmd];
|
||||
}
|
||||
|
||||
/**
|
||||
* RCTBridge (Inspector)
|
||||
*/
|
||||
- (BOOL)inspectable
|
||||
{
|
||||
[self logWarning:@"Bridgeless mode does not support this method. Returning NO." cmd:_cmd];
|
||||
return NO;
|
||||
}
|
||||
|
||||
/**
|
||||
* RCTBridge (RCTUIManager)
|
||||
*/
|
||||
- (RCTUIManager *)uiManager
|
||||
{
|
||||
return (RCTUIManager *)_uiManagerProxy;
|
||||
}
|
||||
|
||||
/**
|
||||
* NSProxy setup
|
||||
*/
|
||||
- (NSMethodSignature *)methodSignatureForSelector:(SEL)sel;
|
||||
{
|
||||
return [RCTCxxBridge instanceMethodSignatureForSelector:sel];
|
||||
}
|
||||
|
||||
- (void)forwardInvocation:(NSInvocation *)invocation
|
||||
{
|
||||
[self logError:@"This method is unsupported." cmd:invocation.selector];
|
||||
}
|
||||
|
||||
/**
|
||||
* Logging
|
||||
* TODO(155977839): Add a means to configure/disable these logs, so people do not ignore all LogBoxes
|
||||
*/
|
||||
- (void)logWarning:(NSString *)message cmd:(SEL)cmd
|
||||
{
|
||||
RCTLogWarn(@"RCTBridgeProxy: Calling [bridge %@]. %@", NSStringFromSelector(cmd), message);
|
||||
}
|
||||
|
||||
- (void)logError:(NSString *)message cmd:(SEL)cmd
|
||||
{
|
||||
RCTLogError(@"RCTBridgeProxy: Calling [bridge %@]. %@", NSStringFromSelector(cmd), message);
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation RCTUIManagerProxy {
|
||||
RCTViewRegistry *_viewRegistry;
|
||||
}
|
||||
- (instancetype)initWithViewRegistry:(RCTViewRegistry *)viewRegistry
|
||||
{
|
||||
self = [super self];
|
||||
if (self) {
|
||||
_viewRegistry = viewRegistry;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
/**
|
||||
* RCTViewRegistry
|
||||
*/
|
||||
- (UIView *)viewForReactTag:(NSNumber *)reactTag
|
||||
{
|
||||
[self logWarning:@"Please migrate to RCTViewRegistry: @synthesize viewRegistry_DEPRECATED = _viewRegistry_DEPRECATED."
|
||||
cmd:_cmd];
|
||||
return [_viewRegistry viewForReactTag:reactTag];
|
||||
}
|
||||
|
||||
- (void)addUIBlock:(RCTViewManagerUIBlock)block
|
||||
{
|
||||
[self
|
||||
logWarning:
|
||||
@"This method isn't implemented faithfully: the viewRegistry passed to RCTViewManagerUIBlock is nil. Please migrate to RCTViewRegistry: @synthesize viewRegistry_DEPRECATED = _viewRegistry_DEPRECATED."
|
||||
cmd:_cmd];
|
||||
__weak __typeof(self) weakSelf = self;
|
||||
RCTExecuteOnMainQueue(^{
|
||||
__typeof(self) strongSelf = weakSelf;
|
||||
if (strongSelf) {
|
||||
block((RCTUIManager *)strongSelf, nil);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* NSProxy setup
|
||||
*/
|
||||
- (NSMethodSignature *)methodSignatureForSelector:(SEL)sel
|
||||
{
|
||||
return [RCTUIManager instanceMethodSignatureForSelector:sel];
|
||||
}
|
||||
|
||||
- (void)forwardInvocation:(NSInvocation *)invocation
|
||||
{
|
||||
[self logError:@"This methid is unsupported." cmd:invocation.selector];
|
||||
}
|
||||
|
||||
/**
|
||||
* Logging
|
||||
* TODO(155977839): Add a means to configure/disable these logs, so people do not ignore all LogBoxes
|
||||
*/
|
||||
- (void)logWarning:(NSString *)message cmd:(SEL)cmd
|
||||
{
|
||||
RCTLogWarn(
|
||||
@"RCTBridgeProxy (RCTUIManagerProxy): Calling [bridge.uiManager %@]. %@", NSStringFromSelector(cmd), message);
|
||||
}
|
||||
|
||||
- (void)logError:(NSString *)message cmd:(SEL)cmd
|
||||
{
|
||||
RCTLogError(
|
||||
@"RCTBridgeProxy (RCTUIManagerProxy): Calling [bridge.uiManager %@]. %@", NSStringFromSelector(cmd), message);
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -28,3 +28,12 @@ NSString *RCTNormalizeInputEventName(NSString *eventName)
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation RCTBridgeProxy (RCTEventDispatcher)
|
||||
|
||||
- (id<RCTEventDispatcherProtocol>)eventDispatcher
|
||||
{
|
||||
return [self moduleForName:@"EventDispatcher" lazilyLoadIfNecessary:YES];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
#import <React/RCTBridge.h>
|
||||
#import <React/RCTBridgeProxy.h>
|
||||
|
||||
/**
|
||||
* The threshold at which text inputs will start warning that the JS thread
|
||||
@@ -132,3 +133,9 @@ typedef NS_ENUM(NSInteger, RCTTextEventType) {
|
||||
- (id<RCTEventDispatcherProtocol>)eventDispatcher;
|
||||
|
||||
@end
|
||||
|
||||
@interface RCTBridgeProxy (RCTEventDispatcher)
|
||||
|
||||
- (id<RCTEventDispatcherProtocol>)eventDispatcher;
|
||||
|
||||
@end
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
|
||||
#import <React/RCTBridge.h>
|
||||
#import <React/RCTBridgeModule.h>
|
||||
#import <React/RCTBridgeProxy.h>
|
||||
|
||||
extern NSString *const RCTAccessibilityManagerDidUpdateMultiplierNotification; // posted when multiplier is changed
|
||||
|
||||
@@ -34,3 +35,9 @@ extern NSString *const RCTAccessibilityManagerDidUpdateMultiplierNotification; /
|
||||
@property (nonatomic, readonly) RCTAccessibilityManager *accessibilityManager;
|
||||
|
||||
@end
|
||||
|
||||
@interface RCTBridgeProxy (RCTAccessibilityManager)
|
||||
|
||||
@property (nonatomic, readonly) RCTAccessibilityManager *accessibilityManager;
|
||||
|
||||
@end
|
||||
|
||||
@@ -405,6 +405,15 @@ void RCTAccessibilityManagerSetIsVoiceOverEnabled(
|
||||
|
||||
@end
|
||||
|
||||
@implementation RCTBridgeProxy (RCTAccessibilityManager)
|
||||
|
||||
- (RCTAccessibilityManager *)accessibilityManager
|
||||
{
|
||||
return [self moduleForClass:[RCTAccessibilityManager class]];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
Class RCTAccessibilityManagerCls(void)
|
||||
{
|
||||
return RCTAccessibilityManager.class;
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
|
||||
#import <React/RCTBridge.h>
|
||||
#import <React/RCTBridgeModule.h>
|
||||
#import <React/RCTBridgeProxy.h>
|
||||
#import <React/RCTDefines.h>
|
||||
|
||||
#if RCT_DEV_MENU
|
||||
@@ -108,3 +109,9 @@ typedef NSString * (^RCTDevMenuItemTitleBlock)(void);
|
||||
@property (nonatomic, readonly) RCTDevMenu *devMenu;
|
||||
|
||||
@end
|
||||
|
||||
@interface RCTBridgeProxy (RCTDevMenu)
|
||||
|
||||
@property (nonatomic, readonly) RCTDevMenu *devMenu;
|
||||
|
||||
@end
|
||||
|
||||
@@ -563,6 +563,19 @@ RCT_EXPORT_METHOD(setHotLoadingEnabled : (BOOL)enabled)
|
||||
|
||||
@end
|
||||
|
||||
@implementation RCTBridgeProxy (RCTDevMenu)
|
||||
|
||||
- (RCTDevMenu *)devMenu
|
||||
{
|
||||
#if RCT_DEV_MENU
|
||||
return [self moduleForClass:[RCTDevMenu class]];
|
||||
#else
|
||||
return nil;
|
||||
#endif
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
Class RCTDevMenuCls(void)
|
||||
{
|
||||
return RCTDevMenu.class;
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
*/
|
||||
|
||||
#import <React/RCTBridge.h>
|
||||
#import <React/RCTBridgeProxy.h>
|
||||
#import <React/RCTDefines.h>
|
||||
#import <React/RCTEventEmitter.h>
|
||||
#import <React/RCTInitializing.h>
|
||||
@@ -114,6 +115,12 @@
|
||||
|
||||
@end
|
||||
|
||||
@interface RCTBridgeProxy (RCTDevSettings)
|
||||
|
||||
@property (nonatomic, readonly) RCTDevSettings *devSettings;
|
||||
|
||||
@end
|
||||
|
||||
// In debug builds, the dev menu is enabled by default but it is further customizable using this method.
|
||||
// However, this method only has an effect in builds where the dev menu is actually compiled in.
|
||||
// (i.e. RCT_DEV or RCT_DEV_MENU is set)
|
||||
|
||||
@@ -633,6 +633,21 @@ RCT_EXPORT_METHOD(addMenuItem : (NSString *)title)
|
||||
|
||||
@end
|
||||
|
||||
@implementation RCTBridgeProxy (RCTDevSettings)
|
||||
|
||||
- (RCTDevSettings *)devSettings
|
||||
{
|
||||
#if RCT_REMOTE_PROFILE
|
||||
return [self moduleForClass:[RCTDevSettings class]];
|
||||
#elif RCT_DEV_MENU
|
||||
return devSettingsMenuEnabled ? [self moduleForClass:[RCTDevSettings class]] : nil;
|
||||
#else
|
||||
return nil;
|
||||
#endif
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
Class RCTDevSettingsCls(void)
|
||||
{
|
||||
return RCTDevSettings.class;
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
|
||||
#import <React/RCTBridge.h>
|
||||
#import <React/RCTBridgeModule.h>
|
||||
#import <React/RCTBridgeProxy.h>
|
||||
#import <React/RCTErrorCustomizer.h>
|
||||
|
||||
@class RCTJSStackFrame;
|
||||
@@ -57,3 +58,9 @@ typedef void (^RCTRedBoxButtonPressHandler)(void);
|
||||
@property (nonatomic, readonly) RCTRedBox *redBox;
|
||||
|
||||
@end
|
||||
|
||||
@interface RCTBridgeProxy (RCTRedBox)
|
||||
|
||||
@property (nonatomic, readonly) RCTRedBox *redBox;
|
||||
|
||||
@end
|
||||
|
||||
@@ -702,6 +702,15 @@ RCT_EXPORT_METHOD(dismiss)
|
||||
|
||||
@end
|
||||
|
||||
@implementation RCTBridgeProxy (RCTRedBox)
|
||||
|
||||
- (RCTRedBox *)redBox
|
||||
{
|
||||
return RCTRedBoxGetEnabled() ? [self moduleForClass:[RCTRedBox class]] : nil;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#else // Disabled
|
||||
|
||||
@interface RCTRedBox () <NativeRedBoxSpec>
|
||||
@@ -787,6 +796,15 @@ RCT_EXPORT_METHOD(dismiss)
|
||||
|
||||
@end
|
||||
|
||||
@implementation RCTBridgeProxy (RCTRedBox)
|
||||
|
||||
- (RCTRedBox *)redBox
|
||||
{
|
||||
return nil;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#endif
|
||||
|
||||
Class RCTRedBoxCls(void)
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#import <React/RCTBridgeProxy.h>
|
||||
#import <React/RCTEventEmitter.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
@@ -32,4 +33,10 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@end
|
||||
|
||||
@interface RCTBridgeProxy (RCTWebSocketModule)
|
||||
|
||||
- (RCTWebSocketModule *)webSocketModule;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
@@ -207,6 +207,15 @@ RCT_EXPORT_METHOD(close : (double)code reason : (NSString *)reason socketID : (d
|
||||
|
||||
@end
|
||||
|
||||
@implementation RCTBridgeProxy (RCTWebSocketModule)
|
||||
|
||||
- (RCTWebSocketModule *)webSocketModule
|
||||
{
|
||||
return [self moduleForClass:[RCTWebSocketModule class]];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
Class RCTWebSocketModuleCls(void)
|
||||
{
|
||||
return RCTWebSocketModule.class;
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#import <objc/runtime.h>
|
||||
|
||||
#import <React/RCTBridge.h>
|
||||
#import <React/RCTBridgeProxy.h>
|
||||
|
||||
@protocol RCTSurfaceProtocol;
|
||||
|
||||
@@ -44,4 +45,11 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@end
|
||||
|
||||
@interface RCTBridgeProxy (RCTSurfacePresenterStub)
|
||||
|
||||
- (id<RCTSurfacePresenterStub>)surfacePresenter;
|
||||
- (void)setSurfacePresenter:(id<RCTSurfacePresenterStub>)presenter;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
@@ -20,3 +20,17 @@
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation RCTBridgeProxy (RCTSurfacePresenterStub)
|
||||
|
||||
- (id<RCTSurfacePresenterStub>)surfacePresenter
|
||||
{
|
||||
return objc_getAssociatedObject(self, @selector(surfacePresenter));
|
||||
}
|
||||
|
||||
- (void)setSurfacePresenter:(id<RCTSurfacePresenterStub>)surfacePresenter
|
||||
{
|
||||
objc_setAssociatedObject(self, @selector(surfacePresenter), surfacePresenter, OBJC_ASSOCIATION_RETAIN);
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -6,11 +6,13 @@
|
||||
*/
|
||||
|
||||
#import "RCTInstance.h"
|
||||
#import <React/RCTBridgeProxy.h>
|
||||
|
||||
#import <memory>
|
||||
|
||||
#import <React/NSDataBigString.h>
|
||||
#import <React/RCTAssert.h>
|
||||
#import <React/RCTBridge.h>
|
||||
#import <React/RCTBridgeModule.h>
|
||||
#import <React/RCTBridgeModuleDecorator.h>
|
||||
#import <React/RCTComponentViewFactory.h>
|
||||
@@ -229,6 +231,21 @@ void RCTInstanceSetRuntimeDiagnosticFlags(NSString *flags)
|
||||
delegate:self
|
||||
jsInvoker:std::make_shared<BridgelessJSCallInvoker>(bufferedRuntimeExecutor)];
|
||||
|
||||
if (RCTTurboModuleInteropEnabled() && RCTTurboModuleInteropBridgeProxyEnabled()) {
|
||||
RCTBridgeProxy *bridgeProxy = [[RCTBridgeProxy alloc]
|
||||
initWithViewRegistry:_bridgeModuleDecorator.viewRegistry_DEPRECATED
|
||||
moduleRegistry:_bridgeModuleDecorator.moduleRegistry
|
||||
bundleManager:_bridgeModuleDecorator.bundleManager
|
||||
callableJSModules:_bridgeModuleDecorator.callableJSModules
|
||||
dispatchToJSThread:^(dispatch_block_t block) {
|
||||
__strong __typeof(self) strongSelf = weakSelf;
|
||||
if (strongSelf && strongSelf->_valid) {
|
||||
strongSelf->_reactInstance->getBufferedRuntimeExecutor()([=](jsi::Runtime &runtime) { block(); });
|
||||
}
|
||||
}];
|
||||
[_turboModuleManager setBridgeProxy:bridgeProxy];
|
||||
}
|
||||
|
||||
// Initialize RCTModuleRegistry so that TurboModules can require other TurboModules.
|
||||
[_bridgeModuleDecorator.moduleRegistry setTurboModuleRegistry:_turboModuleManager];
|
||||
|
||||
|
||||
+4
@@ -9,6 +9,7 @@
|
||||
|
||||
#import <memory>
|
||||
|
||||
#import <React/RCTBridgeProxy.h>
|
||||
#import <React/RCTDefines.h>
|
||||
#import <React/RCTTurboModuleRegistry.h>
|
||||
#import <ReactCommon/RuntimeExecutor.h>
|
||||
@@ -65,6 +66,9 @@ RCT_EXTERN void RCTTurboModuleSetBindingMode(facebook::react::TurboModuleBinding
|
||||
*/
|
||||
- (void)installJSBindingWithRuntimeExecutor:(facebook::react::RuntimeExecutor &)runtimeExecutor;
|
||||
|
||||
// TODO: Should we move this into the initializer?
|
||||
- (void)setBridgeProxy:(RCTBridgeProxy *)bridgeProxy;
|
||||
|
||||
- (void)invalidate;
|
||||
|
||||
@end
|
||||
|
||||
+23
-2
@@ -17,6 +17,7 @@
|
||||
|
||||
#import <React/RCTBridge+Private.h>
|
||||
#import <React/RCTBridgeModule.h>
|
||||
#import <React/RCTBridgeProxy.h>
|
||||
#import <React/RCTConstants.h>
|
||||
#import <React/RCTCxxModule.h>
|
||||
#import <React/RCTInitializing.h>
|
||||
@@ -198,6 +199,8 @@ static Class getFallbackClassFromName(const char *name)
|
||||
|
||||
NSDictionary<NSString *, id<RCTBridgeModule>> *_legacyEagerlyInitializedModules;
|
||||
NSDictionary<NSString *, Class> *_legacyEagerlyRegisteredModuleClasses;
|
||||
|
||||
RCTBridgeProxy *_bridgeProxy;
|
||||
}
|
||||
|
||||
- (instancetype)initWithBridge:(RCTBridge *)bridge
|
||||
@@ -243,6 +246,11 @@ static Class getFallbackClassFromName(const char *name)
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)setBridgeProxy:(RCTBridgeProxy *)bridgeProxy
|
||||
{
|
||||
_bridgeProxy = bridgeProxy;
|
||||
}
|
||||
|
||||
- (void)notifyAboutTurboModuleSetup:(const char *)name
|
||||
{
|
||||
NSString *moduleName = [[NSString alloc] initWithUTF8String:name];
|
||||
@@ -441,6 +449,15 @@ static Class getFallbackClassFromName(const char *name)
|
||||
}
|
||||
|
||||
Class moduleClass = [self _getModuleClassFromName:moduleName];
|
||||
return [self _isLegacyModuleClass:moduleClass];
|
||||
}
|
||||
|
||||
- (BOOL)_isLegacyModuleClass:(Class)moduleClass
|
||||
{
|
||||
if (RCTTurboModuleInteropForAllTurboModulesEnabled()) {
|
||||
return YES;
|
||||
}
|
||||
|
||||
return moduleClass != nil &&
|
||||
(!RCT_IS_TURBO_MODULE_CLASS(moduleClass) || [moduleClass isSubclassOfClass:RCTCxxModule.class]);
|
||||
}
|
||||
@@ -617,7 +634,7 @@ static Class getFallbackClassFromName(const char *name)
|
||||
* this method exists to know if we can safely set the bridge to the
|
||||
* NativeModule.
|
||||
*/
|
||||
if ([module respondsToSelector:@selector(bridge)] && _bridge) {
|
||||
if ([module respondsToSelector:@selector(bridge)] && (_bridge || _bridgeProxy)) {
|
||||
/**
|
||||
* Just because a NativeModule has the `bridge` method, it doesn't mean
|
||||
* that it has synthesized the bridge in its implementation. Therefore,
|
||||
@@ -634,7 +651,11 @@ static Class getFallbackClassFromName(const char *name)
|
||||
* generated, so we have have to rely on the KVC API of ObjC to set
|
||||
* the bridge property of these NativeModules.
|
||||
*/
|
||||
[(id)module setValue:_bridge forKey:@"bridge"];
|
||||
if (_bridge) {
|
||||
[(id)module setValue:_bridge forKey:@"bridge"];
|
||||
} else if (_bridgeProxy && [self _isLegacyModuleClass:[module class]]) {
|
||||
[(id)module setValue:_bridgeProxy forKey:@"bridge"];
|
||||
}
|
||||
} @catch (NSException *exception) {
|
||||
RCTLogError(
|
||||
@"%@ has no setter or ivar for its bridge, which is not "
|
||||
|
||||
Reference in New Issue
Block a user