Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions packages/react-native/React/Base/RCTBridgeModule.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
@class RCTModuleRegistry;
@class RCTViewRegistry;
@class RCTCallableJSModules;
@class RCTBundleProvider;

/**
* The type of a block that is capable of sending a response to a bridged
Expand Down Expand Up @@ -142,6 +143,16 @@ RCT_EXTERN_C_END
*/
@property (nonatomic, weak, readwrite) RCTBundleManager *bundleManager;

/**
* A reference to the RCTBundleProvider. Useful for modules that need to use
the app's JavaScript bundle and sourceURL.
*
* To implement this in your module, just add `@synthesize bundleProvider =
* _bundleProvider;`. If using Swift, add `@objc var bundleProvider:
* RCTBundleProvider!` to your module.
*/
@property (nonatomic, weak, readwrite) RCTBundleProvider *bundleProvider;

/**
* A reference to an RCTCallableJSModules. Useful for modules that need to
* call into methods on JavaScript modules registered as callable with
Expand Down
2 changes: 2 additions & 0 deletions packages/react-native/React/Base/RCTBridgeModuleDecorator.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,13 @@
@property (nonatomic, strong, readonly) RCTViewRegistry *viewRegistry_DEPRECATED;
@property (nonatomic, strong, readonly) RCTModuleRegistry *moduleRegistry;
@property (nonatomic, strong, readonly) RCTBundleManager *bundleManager;
@property (nonatomic, strong, readonly) RCTBundleProvider *bundleProvider;
@property (nonatomic, strong, readonly) RCTCallableJSModules *callableJSModules;

- (instancetype)initWithViewRegistry:(RCTViewRegistry *)viewRegistry
moduleRegistry:(RCTModuleRegistry *)moduleRegistry
bundleManager:(RCTBundleManager *)bundleManager
bundleProvider:(RCTBundleProvider *)bundleProvider
callableJSModules:(RCTCallableJSModules *)callableJSModules;

- (void)attachInteropAPIsToModule:(id<RCTBridgeModule>)bridgeModule;
Expand Down
13 changes: 13 additions & 0 deletions packages/react-native/React/Base/RCTBridgeModuleDecorator.m
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,14 @@ @implementation RCTBridgeModuleDecorator
- (instancetype)initWithViewRegistry:(RCTViewRegistry *)viewRegistry
moduleRegistry:(RCTModuleRegistry *)moduleRegistry
bundleManager:(RCTBundleManager *)bundleManager
bundleProvider:(RCTBundleProvider *)bundleProvider
callableJSModules:(RCTCallableJSModules *)callableJSModules
{
if (self = [super init]) {
_viewRegistry_DEPRECATED = viewRegistry;
_moduleRegistry = moduleRegistry;
_bundleManager = bundleManager;
_bundleProvider = bundleProvider;
_callableJSModules = callableJSModules;
}
return self;
Expand Down Expand Up @@ -47,6 +49,17 @@ - (void)attachInteropAPIsToModule:(id<RCTBridgeModule>)bridgeModule
bridgeModule.bundleManager = _bundleManager;
}

/**
* Attach the RCTBundleProvider to this TurboModule, which allows this TurboModule to
* read from the app's bundle and sourceURL.
*
* Usage: In the TurboModule @implementation, include:
* `@synthesize bundleProvider = _bundleProvider`
*/
if([bridgeModule respondsToSelector:@selector(setBundleProvider:)]) {
bridgeModule.bundleProvider = _bundleProvider;
}

/**
* Attach the RCTCallableJSModules to this TurboModule, which allows this TurboModule
* to call JS Module methods.
Expand Down
28 changes: 28 additions & 0 deletions packages/react-native/React/Base/RCTBundleProvider.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/*
* 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>

#ifdef __cplusplus
#import <jsireact/JSIExecutor.h>
#endif // __cplusplus

@class NSBundleWrapper;

/**
* Provides the interface needed to register a Bundle Provider module.
*/
@interface RCTBundleProvider : NSObject

#ifdef __cplusplus

- (std::shared_ptr<const facebook::react::JSBigString>)getBundle;
- (NSString *)getSourceURL;

#endif // __cplusplus

@end
32 changes: 32 additions & 0 deletions packages/react-native/React/Base/RCTBundleProvider.mm
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/*
* 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 "RCTBundleProvider.h"

using namespace facebook::react;

@implementation RCTBundleProvider{
std::shared_ptr<const JSBigString> _bundle;
NSString *_sourceURL;
}

- (std::shared_ptr<const JSBigString>)getBundle {
return _bundle;
}

- (void)setBundle:(std::shared_ptr<const JSBigString>)bundle {
_bundle = bundle;
}

- (NSString *)getSourceURL {
return _sourceURL;
}

- (void)setSourceURL:(NSString *)sourceURL {
_sourceURL = sourceURL;
}
@end
3 changes: 3 additions & 0 deletions packages/react-native/React/Base/RCTModuleData.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
@class RCTBundleManager;
@class RCTCallableJSModules;
@class RCTCallInvoker;
@class RCTBundleProvider;

typedef id<RCTBridgeModule> (^RCTBridgeModuleProvider)(void);

Expand All @@ -34,6 +35,7 @@ typedef id<RCTBridgeModule> (^RCTBridgeModuleProvider)(void);
moduleRegistry:(RCTModuleRegistry *)moduleRegistry
viewRegistry_DEPRECATED:(RCTViewRegistry *)viewRegistry_DEPRECATED
bundleManager:(RCTBundleManager *)bundleManager
bundleProvider:(RCTBundleProvider *)bundleProvider
callableJSModules:(RCTCallableJSModules *)callableJSModules NS_DESIGNATED_INITIALIZER
__deprecated_msg("This API will be removed along with the legacy architecture.");

Expand All @@ -42,6 +44,7 @@ typedef id<RCTBridgeModule> (^RCTBridgeModuleProvider)(void);
moduleRegistry:(RCTModuleRegistry *)moduleRegistry
viewRegistry_DEPRECATED:(RCTViewRegistry *)viewRegistry_DEPRECATED
bundleManager:(RCTBundleManager *)bundleManager
bundleProvider:(RCTBundleProvider *)bundleProvider
callableJSModules:(RCTCallableJSModules *)callableJSModules NS_DESIGNATED_INITIALIZER
__deprecated_msg("This API will be removed along with the legacy architecture.");

Expand Down
4 changes: 4 additions & 0 deletions packages/react-native/React/Base/RCTModuleData.mm
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ @implementation RCTModuleData {
RCTModuleRegistry *_moduleRegistry;
RCTViewRegistry *_viewRegistry_DEPRECATED;
RCTBundleManager *_bundleManager;
RCTBundleProvider *_bundleProvider;
RCTCallableJSModules *_callableJSModules;
BOOL _isInitialized;
}
Expand Down Expand Up @@ -100,6 +101,7 @@ - (instancetype)initWithModuleClass:(Class)moduleClass
moduleRegistry:(RCTModuleRegistry *)moduleRegistry
viewRegistry_DEPRECATED:(RCTViewRegistry *)viewRegistry_DEPRECATED
bundleManager:(RCTBundleManager *)bundleManager
bundleProvider:(RCTBundleProvider *)bundleProvider
callableJSModules:(RCTCallableJSModules *)callableJSModules
{
if (self = [super init]) {
Expand All @@ -121,6 +123,7 @@ - (instancetype)initWithModuleInstance:(id<RCTBridgeModule>)instance
moduleRegistry:(RCTModuleRegistry *)moduleRegistry
viewRegistry_DEPRECATED:(RCTViewRegistry *)viewRegistry_DEPRECATED
bundleManager:(RCTBundleManager *)bundleManager
bundleProvider:(RCTBundleProvider *)bundleProvider
callableJSModules:(RCTCallableJSModules *)callableJSModules
{
if (self = [super init]) {
Expand Down Expand Up @@ -195,6 +198,7 @@ - (void)setUpInstanceAndBridge:(int32_t)requestId
[[RCTBridgeModuleDecorator alloc] initWithViewRegistry:_viewRegistry_DEPRECATED
moduleRegistry:_moduleRegistry
bundleManager:_bundleManager
bundleProvider:_bundleProvider
callableJSModules:_callableJSModules];
[moduleDecorator attachInteropAPIsToModule:_instance];

Expand Down
4 changes: 4 additions & 0 deletions packages/react-native/React/CxxBridge/RCTCxxBridge.mm
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,7 @@ @implementation RCTCxxBridge {
RCTModuleRegistry *_objCModuleRegistry;
RCTViewRegistry *_viewRegistry_DEPRECATED;
RCTBundleManager *_bundleManager;
RCTBundleProvider *_bundleProvider;
RCTCallableJSModules *_callableJSModules;
std::atomic<BOOL> _loading;
std::atomic<BOOL> _valid;
Expand Down Expand Up @@ -288,6 +289,7 @@ - (RCTBridgeModuleDecorator *)bridgeModuleDecorator
return [[RCTBridgeModuleDecorator alloc] initWithViewRegistry:_viewRegistry_DEPRECATED
moduleRegistry:_objCModuleRegistry
bundleManager:_bundleManager
bundleProvider:_bundleProvider
callableJSModules:_callableJSModules];
}

Expand Down Expand Up @@ -810,6 +812,7 @@ - (void)updateModuleWithInstance:(id<RCTBridgeModule>)instance
moduleRegistry:_objCModuleRegistry
viewRegistry_DEPRECATED:_viewRegistry_DEPRECATED
bundleManager:_bundleManager
bundleProvider:_bundleProvider
callableJSModules:_callableJSModules];
moduleData.callInvokerProvider = self;
BridgeNativeModulePerfLogger::moduleDataCreateEnd([moduleName UTF8String], moduleDataId);
Expand Down Expand Up @@ -888,6 +891,7 @@ - (void)registerExtraModules
moduleRegistry:_objCModuleRegistry
viewRegistry_DEPRECATED:_viewRegistry_DEPRECATED
bundleManager:_bundleManager
bundleProvider:_bundleProvider
callableJSModules:_callableJSModules];
BridgeNativeModulePerfLogger::moduleDataCreateEnd([moduleName UTF8String], moduleDataId);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import com.facebook.react.common.annotations.internal.LegacyArchitecture;
import com.facebook.react.common.annotations.internal.LegacyArchitectureLogLevel;
import com.facebook.react.common.annotations.internal.LegacyArchitectureLogger;
import com.facebook.react.fabric.BundleWrapper;;
import com.facebook.react.turbomodule.core.interfaces.CallInvokerHolder;
import java.util.Collection;
import java.util.Objects;
Expand Down Expand Up @@ -292,6 +293,16 @@ public CallInvokerHolder getJSCallInvokerHolder() {
return Objects.requireNonNull(mCatalystInstance).getFabricUIManager();
}

/**
* Get the JS bundle.
*
* @return The JS bundle set when the bundle was loaded
*/
@Override
public @Nullable BundleWrapper getBundle() {
return mCatalystInstance == null ? null : mCatalystInstance.getBundle();
}

/**
* Get the sourceURL for the JS bundle from the CatalystInstance. This method is needed for
* compatibility with bridgeless mode, which has no CatalystInstance.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ package com.facebook.react.bridge
import com.facebook.proguard.annotations.DoNotStrip
import com.facebook.react.bridge.queue.ReactQueueConfiguration
import com.facebook.react.common.annotations.internal.LegacyArchitecture
import com.facebook.react.fabric.BundleWrapper
import com.facebook.react.internal.turbomodule.core.interfaces.TurboModuleRegistry
import com.facebook.react.turbomodule.core.interfaces.CallInvokerHolder
import com.facebook.react.turbomodule.core.interfaces.NativeMethodCallInvokerHolder
Expand Down Expand Up @@ -39,6 +40,11 @@ public interface CatalystInstance : MemoryPressureListener, JSInstance, JSBundle
*/
public val sourceURL: String?

/**
* Get the JS bundle that was run or `null` if no JS bundle has been run yet.
*/
public val bundle: BundleWrapper?

// This is called from java code, so it won't be stripped anyway, but proguard will rename it,
// which this prevents.
@DoNotStrip public override fun invokeCallback(callbackID: Int, arguments: NativeArrayInterface)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import com.facebook.react.common.annotations.internal.LegacyArchitecture;
import com.facebook.react.common.annotations.internal.LegacyArchitectureLogLevel;
import com.facebook.react.common.annotations.internal.LegacyArchitectureLogger;
import com.facebook.react.fabric.BundleWrapper;
import com.facebook.react.internal.featureflags.ReactNativeNewArchitectureFeatureFlags;
import com.facebook.react.internal.turbomodule.core.interfaces.TurboModuleRegistry;
import com.facebook.react.module.annotations.ReactModule;
Expand Down Expand Up @@ -104,6 +105,7 @@ public String toString() {

private boolean mJSBundleHasLoaded;
private @Nullable String mSourceURL;
private @Nullable BundleWrapper mBundle;

private JavaScriptContextHolder mJavaScriptContextHolder;
private @Nullable TurboModuleRegistry mTurboModuleRegistry;
Expand Down Expand Up @@ -276,6 +278,11 @@ public boolean hasRunJSBundle() {
}
}

@Override
public @Nullable BundleWrapper getBundle() {
return mBundle;
}

@Override
public @Nullable String getSourceURL() {
return mSourceURL;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import com.facebook.react.bridge.queue.ReactQueueConfiguration;
import com.facebook.react.common.LifecycleState;
import com.facebook.react.turbomodule.core.interfaces.CallInvokerHolder;
import com.facebook.react.fabric.BundleWrapper;
import java.lang.ref.WeakReference;
import java.util.Collection;
import java.util.concurrent.CopyOnWriteArraySet;
Expand Down Expand Up @@ -505,6 +506,13 @@ public boolean startActivityForResult(Intent intent, int code, Bundle bundle) {
*/
public abstract @Nullable UIManager getFabricUIManager();

/**
* Get the BundleWrapper for the JS bundle.
*
* @return The BundleWrapper containing the JS bundle.
*/
public abstract @Nullable BundleWrapper getBundle();

/**
* Get the sourceURL for the JS bundle from the CatalystInstance. This method is needed for
* compatibility with bridgeless mode, which has no CatalystInstance.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/*
* 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.
*/

package com.facebook.react.fabric

import android.annotation.SuppressLint
import android.content.res.AssetManager
import com.facebook.jni.HybridData
import com.facebook.proguard.annotations.DoNotStripAny

/**
* A wrapper around a JavaScript bundle that is backed by a native C++ object.
*/
@SuppressLint("MissingNativeLoadLibrary")
@DoNotStripAny
public class BundleWrapper {

private val mHybridData: HybridData

public constructor(fileName: String) {
mHybridData = initHybridFromFile(fileName)
}

public constructor(assetManager: AssetManager, assetURL: String) {
mHybridData = initHybridFromAssets(assetManager, assetURL)
}

private external fun initHybridFromFile(fileName: String): HybridData

private external fun initHybridFromAssets(
assetManager: AssetManager,
assetURL: String
): HybridData
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import com.facebook.react.common.annotations.VisibleForTesting
import com.facebook.react.common.annotations.internal.LegacyArchitecture
import com.facebook.react.common.annotations.internal.LegacyArchitectureLogLevel
import com.facebook.react.common.annotations.internal.LegacyArchitectureLogger
import com.facebook.react.fabric.BundleWrapper
import com.facebook.react.internal.turbomodule.core.interfaces.TurboModuleRegistry
import com.facebook.react.turbomodule.core.interfaces.CallInvokerHolder
import com.facebook.react.turbomodule.core.interfaces.NativeMethodCallInvokerHolder
Expand Down Expand Up @@ -136,6 +137,9 @@ internal class BridgelessCatalystInstance(private val reactHost: ReactHostImpl)
throw UnsupportedOperationException("Unimplemented method 'extendNativeModules'")
}

override val bundle: BundleWrapper?
get() = throw UnsupportedOperationException("Unimplemented method 'getBundle'")

override val sourceURL: String
get() = throw UnsupportedOperationException("Unimplemented method 'getSourceURL'")

Expand Down
Loading
Loading