2019-10-16 20:03:47 +03:00
|
|
|
/*
|
2018-09-12 01:27:47 +03:00
|
|
|
* Copyright (c) Facebook, Inc. and its affiliates.
|
2015-03-23 23:28:42 +03:00
|
|
|
*
|
2018-02-17 05:24:55 +03:00
|
|
|
* This source code is licensed under the MIT license found in the
|
|
|
|
* LICENSE file in the root directory of this source tree.
|
2015-03-23 23:28:42 +03:00
|
|
|
*/
|
2015-02-20 07:10:52 +03:00
|
|
|
|
2015-04-02 17:33:21 +03:00
|
|
|
#import <UIKit/UIKit.h>
|
|
|
|
|
2016-11-23 18:47:52 +03:00
|
|
|
#import <React/RCTBridgeDelegate.h>
|
|
|
|
#import <React/RCTBridgeModule.h>
|
|
|
|
#import <React/RCTDefines.h>
|
|
|
|
#import <React/RCTFrameUpdate.h>
|
|
|
|
#import <React/RCTInvalidating.h>
|
2015-02-20 07:10:52 +03:00
|
|
|
|
2016-09-29 00:00:16 +03:00
|
|
|
@class JSValue;
|
2015-02-24 20:06:57 +03:00
|
|
|
@class RCTBridge;
|
2016-07-07 17:20:03 +03:00
|
|
|
@class RCTPerformanceLogger;
|
2015-02-20 07:10:52 +03:00
|
|
|
|
2015-07-28 21:07:45 +03:00
|
|
|
/**
|
2018-03-06 22:01:34 +03:00
|
|
|
* This notification fires when the bridge initializes.
|
2015-07-28 21:07:45 +03:00
|
|
|
*/
|
|
|
|
RCT_EXTERN NSString *const RCTJavaScriptWillStartLoadingNotification;
|
|
|
|
|
2018-03-06 22:01:34 +03:00
|
|
|
/**
|
|
|
|
* This notification fires when the bridge starts executing the JS bundle.
|
|
|
|
*/
|
|
|
|
RCT_EXTERN NSString *const RCTJavaScriptWillStartExecutingNotification;
|
|
|
|
|
2015-04-12 01:08:00 +03:00
|
|
|
/**
|
2015-12-15 16:42:45 +03:00
|
|
|
* This notification fires when the bridge has finished loading the JS bundle.
|
2015-04-12 01:08:00 +03:00
|
|
|
*/
|
2015-06-10 13:43:55 +03:00
|
|
|
RCT_EXTERN NSString *const RCTJavaScriptDidLoadNotification;
|
2015-04-12 01:08:00 +03:00
|
|
|
|
2015-05-07 14:29:31 +03:00
|
|
|
/**
|
2015-12-15 16:42:45 +03:00
|
|
|
* This notification fires when the bridge failed to load the JS bundle. The
|
2018-01-13 09:03:51 +03:00
|
|
|
* `error` key can be used to determine the error that occurred.
|
2015-05-07 14:29:31 +03:00
|
|
|
*/
|
2015-06-10 13:43:55 +03:00
|
|
|
RCT_EXTERN NSString *const RCTJavaScriptDidFailToLoadNotification;
|
2015-05-07 14:29:31 +03:00
|
|
|
|
2015-07-01 03:08:28 +03:00
|
|
|
/**
|
2015-12-15 16:42:45 +03:00
|
|
|
* This notification fires each time a native module is instantiated. The
|
|
|
|
* `module` key will contain a reference to the newly-created module instance.
|
|
|
|
* Note that this notification may be fired before the module is available via
|
|
|
|
* the `[bridge moduleForClass:]` method.
|
2015-07-01 03:08:28 +03:00
|
|
|
*/
|
2015-12-15 16:42:45 +03:00
|
|
|
RCT_EXTERN NSString *const RCTDidInitializeModuleNotification;
|
2015-07-01 03:08:28 +03:00
|
|
|
|
2019-03-22 20:39:38 +03:00
|
|
|
/**
|
2019-05-16 01:24:53 +03:00
|
|
|
* This notification fires each time a module is setup after it is initialized. The
|
2019-03-22 20:39:38 +03:00
|
|
|
* `RCTDidSetupModuleNotificationModuleNameKey` key will contain a reference to the module name and
|
|
|
|
* `RCTDidSetupModuleNotificationSetupTimeKey` will contain the setup time in ms.
|
|
|
|
*/
|
|
|
|
RCT_EXTERN NSString *const RCTDidSetupModuleNotification;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Key for the module name (NSString) in the
|
|
|
|
* RCTDidSetupModuleNotification userInfo dictionary.
|
|
|
|
*/
|
|
|
|
RCT_EXTERN NSString *const RCTDidSetupModuleNotificationModuleNameKey;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Key for the setup time (NSNumber) in the
|
|
|
|
* RCTDidSetupModuleNotification userInfo dictionary.
|
|
|
|
*/
|
|
|
|
RCT_EXTERN NSString *const RCTDidSetupModuleNotificationSetupTimeKey;
|
|
|
|
|
2017-08-18 03:09:59 +03:00
|
|
|
/**
|
2019-10-30 22:20:29 +03:00
|
|
|
* DEPRECATED - Use RCTReloadCommand instead. This notification fires just before the bridge starts
|
|
|
|
* processing a request to reload.
|
2017-08-18 03:09:59 +03:00
|
|
|
*/
|
|
|
|
RCT_EXTERN NSString *const RCTBridgeWillReloadNotification;
|
|
|
|
|
2019-09-30 17:01:15 +03:00
|
|
|
/**
|
|
|
|
* This notification fires whenever a fast refresh happens.
|
|
|
|
*/
|
|
|
|
RCT_EXTERN NSString *const RCTBridgeFastRefreshNotification;
|
|
|
|
|
2017-08-18 03:09:59 +03:00
|
|
|
/**
|
|
|
|
* This notification fires just before the bridge begins downloading a script
|
|
|
|
* from the packager.
|
|
|
|
*/
|
|
|
|
RCT_EXTERN NSString *const RCTBridgeWillDownloadScriptNotification;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* This notification fires just after the bridge finishes downloading a script
|
|
|
|
* from the packager.
|
|
|
|
*/
|
|
|
|
RCT_EXTERN NSString *const RCTBridgeDidDownloadScriptNotification;
|
|
|
|
|
2019-06-22 01:50:10 +03:00
|
|
|
/**
|
|
|
|
* This notification fires right after the bridge is about to invalidate NativeModule
|
|
|
|
* instances during teardown. Handle this notification to perform additional invalidation.
|
|
|
|
*/
|
|
|
|
RCT_EXTERN NSString *const RCTBridgeWillInvalidateModulesNotification;
|
|
|
|
|
2019-05-16 03:32:42 +03:00
|
|
|
/**
|
|
|
|
* This notification fires right after the bridge finishes invalidating NativeModule
|
|
|
|
* instances during teardown. Handle this notification to perform additional invalidation.
|
|
|
|
*/
|
|
|
|
RCT_EXTERN NSString *const RCTBridgeDidInvalidateModulesNotification;
|
|
|
|
|
2019-10-25 03:43:08 +03:00
|
|
|
/**
|
|
|
|
* This notification fires right before the bridge starting invalidation process.
|
|
|
|
* Handle this notification to perform additional invalidation.
|
|
|
|
* The notification can be issued on any thread.
|
|
|
|
*/
|
|
|
|
RCT_EXTERN NSString *const RCTBridgeWillBeInvalidatedNotification;
|
|
|
|
|
2017-08-31 15:25:19 +03:00
|
|
|
/**
|
|
|
|
* Key for the RCTSource object in the RCTBridgeDidDownloadScriptNotification
|
|
|
|
* userInfo dictionary.
|
|
|
|
*/
|
|
|
|
RCT_EXTERN NSString *const RCTBridgeDidDownloadScriptNotificationSourceKey;
|
|
|
|
|
2019-09-30 17:01:15 +03:00
|
|
|
/**
|
|
|
|
* Key for the reload reason in the RCTBridgeWillReloadNotification userInfo dictionary.
|
|
|
|
*/
|
|
|
|
RCT_EXTERN NSString *const RCTBridgeDidDownloadScriptNotificationReasonKey;
|
|
|
|
|
2018-04-11 05:23:07 +03:00
|
|
|
/**
|
|
|
|
* Key for the bridge description (NSString_ in the
|
|
|
|
* RCTBridgeDidDownloadScriptNotification userInfo dictionary.
|
|
|
|
*/
|
|
|
|
RCT_EXTERN NSString *const RCTBridgeDidDownloadScriptNotificationBridgeDescriptionKey;
|
|
|
|
|
2015-02-24 20:06:57 +03:00
|
|
|
/**
|
|
|
|
* This block can be used to instantiate modules that require additional
|
|
|
|
* init parameters, or additional configuration prior to being used.
|
2019-07-23 13:19:41 +03:00
|
|
|
* The bridge will call this block to instantiate the modules, and will
|
2015-03-02 02:33:55 +03:00
|
|
|
* 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.
|
2015-02-24 20:06:57 +03:00
|
|
|
*/
|
2020-03-09 08:58:01 +03:00
|
|
|
typedef NSArray<id<RCTBridgeModule>> * (^RCTBridgeModuleListProvider)(void);
|
2015-02-24 20:06:57 +03:00
|
|
|
|
2020-06-08 19:04:56 +03:00
|
|
|
/**
|
|
|
|
* These blocks are used to report whether an additional bundle
|
|
|
|
* fails or succeeds loading.
|
|
|
|
*/
|
|
|
|
typedef void (^RCTLoadAndExecuteErrorBlock)(NSError *error);
|
|
|
|
|
2015-04-07 17:36:26 +03:00
|
|
|
/**
|
|
|
|
* This function returns the module name for a given class.
|
|
|
|
*/
|
2015-04-21 15:26:51 +03:00
|
|
|
RCT_EXTERN NSString *RCTBridgeModuleNameForClass(Class bridgeModuleClass);
|
2015-04-07 17:36:26 +03:00
|
|
|
|
2018-08-30 01:36:24 +03:00
|
|
|
/**
|
|
|
|
* Experimental.
|
|
|
|
* Check/set if JSI-bound NativeModule is enabled. By default it's off.
|
|
|
|
*/
|
2018-11-14 21:27:32 +03:00
|
|
|
RCT_EXTERN BOOL RCTTurboModuleEnabled(void);
|
2018-11-20 12:14:35 +03:00
|
|
|
RCT_EXTERN void RCTEnableTurboModule(BOOL enabled);
|
2018-08-30 01:36:24 +03:00
|
|
|
|
2020-07-10 02:22:44 +03:00
|
|
|
// Turn on TurboModule eager initialization
|
|
|
|
RCT_EXTERN BOOL RCTTurboModuleEagerInitEnabled(void);
|
|
|
|
RCT_EXTERN void RCTEnableTurboModuleEagerInit(BOOL enabled);
|
|
|
|
|
2020-09-09 19:28:37 +03:00
|
|
|
// Turn on TurboModule shared mutex initialization
|
|
|
|
RCT_EXTERN BOOL RCTTurboModuleSharedMutexInitEnabled(void);
|
|
|
|
RCT_EXTERN void RCTEnableTurboModuleSharedMutexInit(BOOL enabled);
|
|
|
|
|
2021-09-08 22:49:15 +03:00
|
|
|
// Turn off TurboModule delegate locking
|
|
|
|
RCT_EXTERN BOOL RCTTurboModuleManagerDelegateLockingDisabled(void);
|
|
|
|
RCT_EXTERN void RCTDisableTurboModuleManagerDelegateLocking(BOOL enabled);
|
|
|
|
|
Stop sharing LongLivedObjectCollection with the bridge
Summary:
## Context
Previously, when you'd call TurboModule methods with JavaScript callbacks, we'd [store the callbacks](https://www.internalfb.com/code/fbsource/[c503ff1b38621aebca87b2bbebeae088b01886c4]/xplat/js/react-native-github/ReactCommon/react/nativemodule/core/platform/ios/RCTTurboModule.mm?lines=173%2C248-249) into [this global LongLivedObjectCollection collection](https://www.internalfb.com/code/fbsource/[c503ff1b38621aebca87b2bbebeae088b01886c4]/xplat/js/react-native-github/ReactCommon/react/nativemodule/core/ReactCommon/TurboModuleUtils.h?lines=65). Then, when React Native's JavaScript VM got torn down, we'd [clear the global collection](https://www.internalfb.com/code/fbsource/[e26f476ce208c578f05b1edb7639d1dad5612c7d]/xplat/js/react-native-github/ReactCommon/react/nativemodule/core/ReactCommon/TurboModuleBinding.cpp?lines=49), which would ensure that we deleted all held jsi::Functions, before deleting the jsi::Runtime.
## Problem
With bridgeless mode enabled, there can be two TurboModule systems. Further, it is possible to tear down bridgeless mode, or the bridge, without tearing down the other initialization infra. In this scenario, the jsi::Function for the other initialization infra would also get deleted, which could lead to mysterious problems.
## Fix
In this diff, I refactored the jsi::Function cleanup in the TurboModule system. Now, there are 3 modes:
- kGlobalScope: Everything works as it did before
- kRCTGlobalScopeUsingRetainJSCallback: We still use the global LongLivedObjectCollection, but we do it through invoking a block passed to every ObjCTurboModule by the TurboModuleManager. This group exists to assess the impact of having each TurboModule retain/use the block. I suspect this will be negligible, but it'd be good to have actual data to back this claim.
- kRCTTurboModuleManagerScope: Every TurboModule uses a LongLivedObjectCollection that is owned by its TurboModuleManager. This should effectively fix the problem I outlined above.
Changelog: [Internal]
Reviewed By: p-sun
Differential Revision: D30019833
fbshipit-source-id: da50d884c7e37190107f570d8ed70eeda7d9ae83
2021-08-02 21:19:47 +03:00
|
|
|
typedef enum {
|
|
|
|
kRCTGlobalScope,
|
|
|
|
kRCTGlobalScopeUsingRetainJSCallback,
|
|
|
|
kRCTTurboModuleManagerScope,
|
|
|
|
} RCTTurboModuleCleanupMode;
|
|
|
|
|
|
|
|
RCT_EXTERN RCTTurboModuleCleanupMode RCTGetTurboModuleCleanupMode(void);
|
|
|
|
RCT_EXTERN void RCTSetTurboModuleCleanupMode(RCTTurboModuleCleanupMode mode);
|
|
|
|
|
2015-02-20 07:10:52 +03:00
|
|
|
/**
|
|
|
|
* Async batched bridge used to communicate with the JavaScript application.
|
|
|
|
*/
|
|
|
|
@interface RCTBridge : NSObject <RCTInvalidating>
|
|
|
|
|
2015-07-29 01:48:46 +03:00
|
|
|
/**
|
|
|
|
* Creates a new bridge with a custom RCTBridgeDelegate.
|
|
|
|
*
|
|
|
|
* All the interaction with the JavaScript context should be done using the bridge
|
|
|
|
* instance of the RCTBridgeModules. Modules will be automatically instantiated
|
|
|
|
* using the default contructor, but you can optionally pass in an array of
|
|
|
|
* pre-initialized module instances if they require additional init parameters
|
|
|
|
* or configuration.
|
|
|
|
*/
|
2020-03-09 08:58:01 +03:00
|
|
|
- (instancetype)initWithDelegate:(id<RCTBridgeDelegate>)delegate launchOptions:(NSDictionary *)launchOptions;
|
2015-07-29 01:48:46 +03:00
|
|
|
|
2015-02-20 07:10:52 +03:00
|
|
|
/**
|
2015-07-29 01:48:46 +03:00
|
|
|
* DEPRECATED: Use initWithDelegate:launchOptions: instead
|
|
|
|
*
|
2015-02-20 07:10:52 +03:00
|
|
|
* The designated initializer. This creates a new bridge on top of the specified
|
|
|
|
* executor. The bridge should then be used for all subsequent communication
|
2015-02-24 20:06:57 +03:00
|
|
|
* with the JavaScript code running in the executor. Modules will be automatically
|
2015-03-02 02:33:55 +03:00
|
|
|
* instantiated using the default contructor, but you can optionally pass in an
|
|
|
|
* array of pre-initialized module instances if they require additional init
|
|
|
|
* parameters or configuration.
|
2015-02-20 07:10:52 +03:00
|
|
|
*/
|
2015-04-12 01:08:00 +03:00
|
|
|
- (instancetype)initWithBundleURL:(NSURL *)bundleURL
|
2017-04-07 21:11:03 +03:00
|
|
|
moduleProvider:(RCTBridgeModuleListProvider)block
|
2016-07-12 15:51:56 +03:00
|
|
|
launchOptions:(NSDictionary *)launchOptions;
|
2015-02-20 07:10:52 +03:00
|
|
|
|
|
|
|
/**
|
|
|
|
* This method is used to call functions in the JavaScript application context.
|
|
|
|
* It is primarily intended for use by modules that require two-way communication
|
2015-06-15 23:01:39 +03:00
|
|
|
* with the JavaScript code. Safe to call from any thread.
|
2015-02-20 07:10:52 +03:00
|
|
|
*/
|
|
|
|
- (void)enqueueJSCall:(NSString *)moduleDotMethod args:(NSArray *)args;
|
2020-03-09 08:58:01 +03:00
|
|
|
- (void)enqueueJSCall:(NSString *)module
|
|
|
|
method:(NSString *)method
|
|
|
|
args:(NSArray *)args
|
|
|
|
completion:(dispatch_block_t)completion;
|
2016-07-18 17:12:22 +03:00
|
|
|
|
2017-11-09 22:55:39 +03:00
|
|
|
/**
|
|
|
|
* This method registers the file path of an additional JS segment by its ID.
|
|
|
|
*
|
|
|
|
* @experimental
|
|
|
|
*/
|
|
|
|
- (void)registerSegmentWithId:(NSUInteger)segmentId path:(NSString *)path;
|
|
|
|
|
2015-04-08 15:42:43 +03:00
|
|
|
/**
|
2015-11-25 14:09:00 +03:00
|
|
|
* Retrieve a bridge module instance by name or class. Note that modules are
|
|
|
|
* lazily instantiated, so calling these methods for the first time with a given
|
2019-07-23 13:19:41 +03:00
|
|
|
* module name/class may cause the class to be synchronously instantiated,
|
2016-03-03 13:20:20 +03:00
|
|
|
* potentially blocking both the calling thread and main thread for a short time.
|
2018-11-14 07:09:21 +03:00
|
|
|
*
|
|
|
|
* Note: This method does NOT lazily load the particular module if it's not yet loaded.
|
2015-11-25 14:09:00 +03:00
|
|
|
*/
|
|
|
|
- (id)moduleForName:(NSString *)moduleName;
|
2018-11-14 07:09:21 +03:00
|
|
|
- (id)moduleForName:(NSString *)moduleName lazilyLoadIfNecessary:(BOOL)lazilyLoad;
|
|
|
|
// Note: This method lazily load the module as necessary.
|
2015-11-25 14:09:00 +03:00
|
|
|
- (id)moduleForClass:(Class)moduleClass;
|
|
|
|
|
Enable module lookup in TurboModules
Summary:
NativeModules are instantiated by the bridge. If they choose, they can capture the bridge instance that instantiated them. From within the NativeModule, the bridge can then be used to lookup other NativeModules. TurboModules have no way to do such a lookup.
Both NativeModules and TurboModules need to be able to query for one another. Therefore, we have four cases:
1. NativeModule accesses NativeModule.
2. NativeModule accesses TurboModule.
3. TurboModule accesses NativeModule.
4. TurboModule accesses TurboModule.
In summary, this solution extends the bridge to support querying TurboModules. It also introduces a `RCTTurboModuleLookupDelegate` protocol, which, implemented by `RCTTurboModuleManager`, supports querying TurboModules:
```
protocol RCTTurboModuleLookupDelegate <NSObject>
- (id)moduleForName:(NSString *)moduleName;
- (id)moduleForName:(NSString *)moduleName warnOnLookupFailure:(BOOL)warnOnLookupFailure;
- (BOOL)moduleIsInitialized:(NSString *)moduleName
end
```
If TurboModules want to query other TurboModules, then they need to implement this protocol and synthesize `turboModuleLookupDelegate`:
```
protocol RCTTurboModuleWithLookupCapabilities
property (nonatomic, weak) id<RCTTurboModuleLookupDelegate> turboModuleLookupDelegate;
end
```
NativeModules will continue to use `RCTBridge` to access other NativeModules. Nothing needs to change.
When we attach the bridge to `RCTTurboModuleManager`, we also attach `RCTTurboModuleManager` to the bridge as a `RCTTurboModuleLookupDelegate`. This allows the bridge to query TurboModules, which enables our NativeModules to transparently (i.e: without any NativeModule code modification) query TurboModules.
In an ideal world, all modules would be TurboModules. Until then, we're going to require that TurboModules use the bridge to query for NativeModules or TurboModules.
`RCTTurboModuleManager` keeps a map of all TurboModules that we instantiated. We simply search in this map and return the TurboModule.
This setup allows us to switch NativeModules to TurboModules without compromising their ability to use the bridge to search for other NativeModules (and TurboModules). When we write new TurboModules, we can have them use `RCTTurboModuleLookupDelegate` to do access other TurboModules. Eventually, after we migrate all NativeModules to TurboModules, we can migrate all old callsites to use `RCTTurboModuleLookupDelegate`.
Reviewed By: fkgozali
Differential Revision: D13553186
fbshipit-source-id: 4d0488eef081332c8b70782e1337eccf10717dae
2019-01-31 22:04:45 +03:00
|
|
|
/**
|
|
|
|
* When a NativeModule performs a lookup for a TurboModule, we need to query
|
2020-07-08 02:22:59 +03:00
|
|
|
* the TurboModuleRegistry.
|
Enable module lookup in TurboModules
Summary:
NativeModules are instantiated by the bridge. If they choose, they can capture the bridge instance that instantiated them. From within the NativeModule, the bridge can then be used to lookup other NativeModules. TurboModules have no way to do such a lookup.
Both NativeModules and TurboModules need to be able to query for one another. Therefore, we have four cases:
1. NativeModule accesses NativeModule.
2. NativeModule accesses TurboModule.
3. TurboModule accesses NativeModule.
4. TurboModule accesses TurboModule.
In summary, this solution extends the bridge to support querying TurboModules. It also introduces a `RCTTurboModuleLookupDelegate` protocol, which, implemented by `RCTTurboModuleManager`, supports querying TurboModules:
```
protocol RCTTurboModuleLookupDelegate <NSObject>
- (id)moduleForName:(NSString *)moduleName;
- (id)moduleForName:(NSString *)moduleName warnOnLookupFailure:(BOOL)warnOnLookupFailure;
- (BOOL)moduleIsInitialized:(NSString *)moduleName
end
```
If TurboModules want to query other TurboModules, then they need to implement this protocol and synthesize `turboModuleLookupDelegate`:
```
protocol RCTTurboModuleWithLookupCapabilities
property (nonatomic, weak) id<RCTTurboModuleLookupDelegate> turboModuleLookupDelegate;
end
```
NativeModules will continue to use `RCTBridge` to access other NativeModules. Nothing needs to change.
When we attach the bridge to `RCTTurboModuleManager`, we also attach `RCTTurboModuleManager` to the bridge as a `RCTTurboModuleLookupDelegate`. This allows the bridge to query TurboModules, which enables our NativeModules to transparently (i.e: without any NativeModule code modification) query TurboModules.
In an ideal world, all modules would be TurboModules. Until then, we're going to require that TurboModules use the bridge to query for NativeModules or TurboModules.
`RCTTurboModuleManager` keeps a map of all TurboModules that we instantiated. We simply search in this map and return the TurboModule.
This setup allows us to switch NativeModules to TurboModules without compromising their ability to use the bridge to search for other NativeModules (and TurboModules). When we write new TurboModules, we can have them use `RCTTurboModuleLookupDelegate` to do access other TurboModules. Eventually, after we migrate all NativeModules to TurboModules, we can migrate all old callsites to use `RCTTurboModuleLookupDelegate`.
Reviewed By: fkgozali
Differential Revision: D13553186
fbshipit-source-id: 4d0488eef081332c8b70782e1337eccf10717dae
2019-01-31 22:04:45 +03:00
|
|
|
*/
|
2020-07-08 02:22:59 +03:00
|
|
|
- (void)setRCTTurboModuleRegistry:(id<RCTTurboModuleRegistry>)turboModuleRegistry;
|
Enable module lookup in TurboModules
Summary:
NativeModules are instantiated by the bridge. If they choose, they can capture the bridge instance that instantiated them. From within the NativeModule, the bridge can then be used to lookup other NativeModules. TurboModules have no way to do such a lookup.
Both NativeModules and TurboModules need to be able to query for one another. Therefore, we have four cases:
1. NativeModule accesses NativeModule.
2. NativeModule accesses TurboModule.
3. TurboModule accesses NativeModule.
4. TurboModule accesses TurboModule.
In summary, this solution extends the bridge to support querying TurboModules. It also introduces a `RCTTurboModuleLookupDelegate` protocol, which, implemented by `RCTTurboModuleManager`, supports querying TurboModules:
```
protocol RCTTurboModuleLookupDelegate <NSObject>
- (id)moduleForName:(NSString *)moduleName;
- (id)moduleForName:(NSString *)moduleName warnOnLookupFailure:(BOOL)warnOnLookupFailure;
- (BOOL)moduleIsInitialized:(NSString *)moduleName
end
```
If TurboModules want to query other TurboModules, then they need to implement this protocol and synthesize `turboModuleLookupDelegate`:
```
protocol RCTTurboModuleWithLookupCapabilities
property (nonatomic, weak) id<RCTTurboModuleLookupDelegate> turboModuleLookupDelegate;
end
```
NativeModules will continue to use `RCTBridge` to access other NativeModules. Nothing needs to change.
When we attach the bridge to `RCTTurboModuleManager`, we also attach `RCTTurboModuleManager` to the bridge as a `RCTTurboModuleLookupDelegate`. This allows the bridge to query TurboModules, which enables our NativeModules to transparently (i.e: without any NativeModule code modification) query TurboModules.
In an ideal world, all modules would be TurboModules. Until then, we're going to require that TurboModules use the bridge to query for NativeModules or TurboModules.
`RCTTurboModuleManager` keeps a map of all TurboModules that we instantiated. We simply search in this map and return the TurboModule.
This setup allows us to switch NativeModules to TurboModules without compromising their ability to use the bridge to search for other NativeModules (and TurboModules). When we write new TurboModules, we can have them use `RCTTurboModuleLookupDelegate` to do access other TurboModules. Eventually, after we migrate all NativeModules to TurboModules, we can migrate all old callsites to use `RCTTurboModuleLookupDelegate`.
Reviewed By: fkgozali
Differential Revision: D13553186
fbshipit-source-id: 4d0488eef081332c8b70782e1337eccf10717dae
2019-01-31 22:04:45 +03:00
|
|
|
|
2021-05-01 02:38:30 +03:00
|
|
|
/**
|
|
|
|
* This hook is called by the TurboModule infra with every TurboModule that's created.
|
|
|
|
* It allows the bridge to attach properties to TurboModules that give TurboModules
|
|
|
|
* access to Bridge APIs.
|
|
|
|
*/
|
|
|
|
- (void)attachBridgeAPIsToTurboModule:(id<RCTTurboModule>)module;
|
|
|
|
|
2016-03-03 13:20:20 +03:00
|
|
|
/**
|
|
|
|
* Convenience method for retrieving all modules conforming to a given protocol.
|
2019-07-23 13:19:41 +03:00
|
|
|
* Modules will be synchronously instantiated if they haven't already been,
|
2016-03-03 13:20:20 +03:00
|
|
|
* potentially blocking both the calling thread and main thread for a short time.
|
|
|
|
*/
|
|
|
|
- (NSArray *)modulesConformingToProtocol:(Protocol *)protocol;
|
|
|
|
|
2016-03-07 20:30:20 +03:00
|
|
|
/**
|
|
|
|
* Test if a module has been initialized. Use this prior to calling
|
2016-03-24 03:22:16 +03:00
|
|
|
* `moduleForClass:` or `moduleForName:` if you do not want to cause the module
|
2016-03-07 20:30:20 +03:00
|
|
|
* to be instantiated if it hasn't been already.
|
|
|
|
*/
|
|
|
|
- (BOOL)moduleIsInitialized:(Class)moduleClass;
|
|
|
|
|
2015-11-25 14:09:00 +03:00
|
|
|
/**
|
|
|
|
* All registered bridge module classes.
|
2015-04-08 15:42:43 +03:00
|
|
|
*/
|
2015-11-25 14:09:00 +03:00
|
|
|
@property (nonatomic, copy, readonly) NSArray<Class> *moduleClasses;
|
2015-04-08 15:42:43 +03:00
|
|
|
|
2015-04-21 00:04:53 +03:00
|
|
|
/**
|
|
|
|
* URL of the script that was loaded into the bridge.
|
|
|
|
*/
|
2016-01-04 21:39:07 +03:00
|
|
|
@property (nonatomic, strong, readonly) NSURL *bundleURL;
|
2015-04-21 00:04:53 +03:00
|
|
|
|
2015-07-29 01:48:46 +03:00
|
|
|
/**
|
2016-01-04 21:39:07 +03:00
|
|
|
* The class of the executor currently being used. Changes to this value will
|
|
|
|
* take effect after the bridge is reloaded.
|
2015-07-29 01:48:46 +03:00
|
|
|
*/
|
2015-04-02 17:33:21 +03:00
|
|
|
@property (nonatomic, strong) Class executorClass;
|
|
|
|
|
2015-07-29 01:48:46 +03:00
|
|
|
/**
|
|
|
|
* The delegate provided during the bridge initialization
|
|
|
|
*/
|
|
|
|
@property (nonatomic, weak, readonly) id<RCTBridgeDelegate> delegate;
|
|
|
|
|
2015-04-08 15:42:43 +03:00
|
|
|
/**
|
|
|
|
* The launch options that were used to initialize the bridge.
|
|
|
|
*/
|
2015-03-26 04:59:42 +03:00
|
|
|
@property (nonatomic, copy, readonly) NSDictionary *launchOptions;
|
|
|
|
|
2015-02-20 07:10:52 +03:00
|
|
|
/**
|
2015-04-08 15:42:43 +03:00
|
|
|
* Use this to check if the bridge is currently loading.
|
2015-02-20 07:10:52 +03:00
|
|
|
*/
|
2015-04-12 01:08:00 +03:00
|
|
|
@property (nonatomic, readonly, getter=isLoading) BOOL loading;
|
2015-02-20 07:10:52 +03:00
|
|
|
|
2015-08-14 11:59:42 +03:00
|
|
|
/**
|
|
|
|
* Use this to check if the bridge has been invalidated.
|
|
|
|
*/
|
|
|
|
@property (nonatomic, readonly, getter=isValid) BOOL valid;
|
|
|
|
|
2016-07-07 17:20:03 +03:00
|
|
|
/**
|
|
|
|
* Link to the Performance Logger that logs React Native perf events.
|
|
|
|
*/
|
|
|
|
@property (nonatomic, readonly, strong) RCTPerformanceLogger *performanceLogger;
|
|
|
|
|
[ReactNative] Move module info from bridge to RCTModuleData
Summary:
@public
The info about bridge modules (such as id, name, queue, methods...) was spread
across arrays & dictionaries on the bridge, move it into a specific class.
It also removes a lot of information that was statically cached, and now have
the same lifecycle of the bridge.
Also moved RCTModuleMethod, RCTFrameUpdate and RCTBatchedBridge into it's own
files, for organization sake.
NOTE: This diff seems huge, but most of it was just moving code :)
Test Plan:
Tested UIExplorer & UIExplorer tests, Catalyst, MAdMan and Groups. Everything
looks fine.
2015-06-25 02:34:56 +03:00
|
|
|
/**
|
2015-11-25 14:09:00 +03:00
|
|
|
* Reload the bundle and reset executor & modules. Safe to call from any thread.
|
[ReactNative] Move module info from bridge to RCTModuleData
Summary:
@public
The info about bridge modules (such as id, name, queue, methods...) was spread
across arrays & dictionaries on the bridge, move it into a specific class.
It also removes a lot of information that was statically cached, and now have
the same lifecycle of the bridge.
Also moved RCTModuleMethod, RCTFrameUpdate and RCTBatchedBridge into it's own
files, for organization sake.
NOTE: This diff seems huge, but most of it was just moving code :)
Test Plan:
Tested UIExplorer & UIExplorer tests, Catalyst, MAdMan and Groups. Everything
looks fine.
2015-06-25 02:34:56 +03:00
|
|
|
*/
|
2019-10-30 22:20:29 +03:00
|
|
|
- (void)reload __deprecated_msg("Use RCTReloadCommand instead");
|
2019-09-30 17:01:15 +03:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Reload the bundle and reset executor & modules. Safe to call from any thread.
|
|
|
|
*/
|
2019-10-30 22:20:29 +03:00
|
|
|
- (void)reloadWithReason:(NSString *)reason __deprecated_msg("Use RCTReloadCommand instead");
|
2015-11-25 14:09:00 +03:00
|
|
|
|
2019-09-30 17:01:15 +03:00
|
|
|
/**
|
|
|
|
* Handle notifications for a fast refresh. Safe to call from any thread.
|
|
|
|
*/
|
|
|
|
- (void)onFastRefresh;
|
|
|
|
|
2016-09-08 03:24:23 +03:00
|
|
|
/**
|
|
|
|
* Inform the bridge, and anything subscribing to it, that it should reload.
|
|
|
|
*/
|
2019-10-30 22:20:29 +03:00
|
|
|
- (void)requestReload __deprecated_msg("Use RCTReloadCommand instead");
|
2016-09-08 03:24:23 +03:00
|
|
|
|
2015-12-11 17:54:56 +03:00
|
|
|
/**
|
2020-06-08 19:04:56 +03:00
|
|
|
* Says whether bridge has started receiving calls from JavaScript.
|
2015-12-11 17:54:56 +03:00
|
|
|
*/
|
|
|
|
- (BOOL)isBatchActive;
|
|
|
|
|
2020-06-08 19:04:56 +03:00
|
|
|
/**
|
|
|
|
* Loads and executes additional bundles in the VM for development.
|
|
|
|
*/
|
|
|
|
- (void)loadAndExecuteSplitBundleURL:(NSURL *)bundleURL
|
|
|
|
onError:(RCTLoadAndExecuteErrorBlock)onError
|
|
|
|
onComplete:(dispatch_block_t)onComplete;
|
|
|
|
|
2015-11-25 14:09:00 +03:00
|
|
|
@end
|