diff --git a/React/Base/RCTBridgeModule.h b/React/Base/RCTBridgeModule.h index c7a1888b0dd1e6..8c96f4b9023a66 100644 --- a/React/Base/RCTBridgeModule.h +++ b/React/Base/RCTBridgeModule.h @@ -14,6 +14,7 @@ @protocol RCTBridgeMethod; @class RCTModuleRegistry; @class RCTViewRegistry; +@class RCTBundleManager; /** * The type of a block that is capable of sending a response to a bridged @@ -135,6 +136,16 @@ RCT_EXTERN_C_END */ @property (nonatomic, weak, readwrite) RCTViewRegistry *viewRegistry_DEPRECATED; +/** + * A reference to the RCTBundleManager. Useful for modules that need to read + * or write to the app's bundle URL. + * + * To implement this in your module, just add `@synthesize bundleManager = + * _bundleManager;`. If using Swift, add `@objc var bundleManager: + * RCTBundleManager!` to your module. + */ +@property (nonatomic, weak, readwrite) RCTBundleManager *bundleManager; + /** * A reference to the RCTBridge. Useful for modules that require access * to bridge features, such as sending events or making JS calls. This @@ -406,6 +417,19 @@ RCT_EXTERN_C_END - (id)moduleForName:(const char *)moduleName lazilyLoadIfNecessary:(BOOL)lazilyLoad; @end +typedef void (^RCTBridgelessBundleURLSetter)(NSURL *bundleURL); +typedef NSURL * (^RCTBridgelessBundleURLGetter)(); + +/** + * A class that allows NativeModules/TurboModules to read/write the bundleURL, with or without the bridge. + */ +@interface RCTBundleManager : NSObject +- (void)setBridge:(RCTBridge *)bridge; +- (void)setBridgelessBundleURLGetter:(RCTBridgelessBundleURLGetter)getter + andSetter:(RCTBridgelessBundleURLSetter)setter; +@property NSURL *bundleURL; +@end + typedef UIView * (^RCTBridgelessComponentViewProvider)(NSNumber *); /** diff --git a/React/Base/RCTBundleManager.m b/React/Base/RCTBundleManager.m new file mode 100644 index 00000000000000..b6423e9c55941b --- /dev/null +++ b/React/Base/RCTBundleManager.m @@ -0,0 +1,56 @@ +/* + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#import "RCTAssert.h" +#import "RCTBridge+Private.h" +#import "RCTBridge.h" +#import "RCTBridgeModule.h" + +@implementation RCTBundleManager { + __weak RCTBridge *_bridge; + RCTBridgelessBundleURLGetter _bridgelessBundleURLGetter; + RCTBridgelessBundleURLSetter _bridgelessBundleURLSetter; +} + +- (void)setBridge:(RCTBridge *)bridge +{ + _bridge = bridge; +} + +- (void)setBridgelessBundleURLGetter:(RCTBridgelessBundleURLGetter)getter andSetter:(RCTBridgelessBundleURLSetter)setter +{ + _bridgelessBundleURLGetter = getter; + _bridgelessBundleURLSetter = setter; +} + +- (void)setBundleURL:(NSURL *)bundleURL +{ + if (_bridge) { + _bridge.bundleURL = bundleURL; + return; + } + + RCTAssert( + _bridgelessBundleURLSetter != nil, + @"RCTBundleManager: In bridgeless mode, RCTBridgelessBundleURLSetter must not be nil."); + _bridgelessBundleURLSetter(bundleURL); +} + +- (NSURL *)bundleURL +{ + if (_bridge) { + return _bridge.bundleURL; + } + + RCTAssert( + _bridgelessBundleURLGetter != nil, + @"RCTBundleManager: In bridgeless mode, RCTBridgelessBundleURLGetter must not be nil."); + + return _bridgelessBundleURLGetter(); +} + +@end