diff --git a/packages/react-native/React/Base/RCTBridgeProxy.h b/packages/react-native/React/Base/RCTBridgeProxy.h index f8639c418e0d..79c75c3b491a 100644 --- a/packages/react-native/React/Base/RCTBridgeProxy.h +++ b/packages/react-native/React/Base/RCTBridgeProxy.h @@ -20,7 +20,8 @@ bundleManager:(RCTBundleManager *)bundleManager callableJSModules:(RCTCallableJSModules *)callableJSModules dispatchToJSThread:(void (^)(dispatch_block_t))dispatchToJSThread - registerSegmentWithId:(void (^)(NSNumber *, NSString *))registerSegmentWithId NS_DESIGNATED_INITIALIZER; + registerSegmentWithId:(void (^)(NSNumber *, NSString *))registerSegmentWithId + runtime:(void *)runtime NS_DESIGNATED_INITIALIZER; - (NSMethodSignature *)methodSignatureForSelector:(SEL)sel; - (void)forwardInvocation:(NSInvocation *)invocation; diff --git a/packages/react-native/React/Base/RCTBridgeProxy.mm b/packages/react-native/React/Base/RCTBridgeProxy.mm index e4ece263b12b..af6b7afb687a 100644 --- a/packages/react-native/React/Base/RCTBridgeProxy.mm +++ b/packages/react-native/React/Base/RCTBridgeProxy.mm @@ -28,6 +28,7 @@ @implementation RCTBridgeProxy { RCTCallableJSModules *_callableJSModules; void (^_dispatchToJSThread)(dispatch_block_t); void (^_registerSegmentWithId)(NSNumber *, NSString *); + void *_runtime; } - (instancetype)initWithViewRegistry:(RCTViewRegistry *)viewRegistry @@ -36,15 +37,17 @@ - (instancetype)initWithViewRegistry:(RCTViewRegistry *)viewRegistry callableJSModules:(RCTCallableJSModules *)callableJSModules dispatchToJSThread:(void (^)(dispatch_block_t))dispatchToJSThread registerSegmentWithId:(void (^)(NSNumber *, NSString *))registerSegmentWithId + runtime:(void *)runtime { self = [super self]; if (self) { - self->_uiManagerProxy = [[RCTUIManagerProxy alloc] initWithViewRegistry:viewRegistry]; - self->_moduleRegistry = moduleRegistry; - self->_bundleManager = bundleManager; - self->_callableJSModules = callableJSModules; - self->_dispatchToJSThread = dispatchToJSThread; - self->_registerSegmentWithId = registerSegmentWithId; + _uiManagerProxy = [[RCTUIManagerProxy alloc] initWithViewRegistry:viewRegistry]; + _moduleRegistry = moduleRegistry; + _bundleManager = bundleManager; + _callableJSModules = callableJSModules; + _dispatchToJSThread = dispatchToJSThread; + _registerSegmentWithId = registerSegmentWithId; + _runtime = runtime; } return self; } @@ -75,10 +78,10 @@ - (Class)executorClass * Used By: * - RCTBlobCollector */ -- (jsi::Runtime *)runtime +- (void *)runtime { - [self logWarning:@"This method is unsupported. Returning nullptr." cmd:_cmd]; - return nullptr; + [self logWarning:@"Please migrate to C++ TurboModule or RuntimeExecutor." cmd:_cmd]; + return _runtime; } /** @@ -162,7 +165,7 @@ - (void)enqueueJSCall:(NSString *)module - (void)registerSegmentWithId:(NSUInteger)segmentId path:(NSString *)path { - self->_registerSegmentWithId(@(segmentId), path); + _registerSegmentWithId(@(segmentId), path); } - (id)delegate diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/BridgelessReactContext.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/BridgelessReactContext.java index 742775ea32bd..5fa394795910 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/BridgelessReactContext.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/BridgelessReactContext.java @@ -12,6 +12,7 @@ import com.facebook.react.bridge.Arguments; import com.facebook.react.bridge.Callback; import com.facebook.react.bridge.CatalystInstance; +import com.facebook.react.bridge.JavaScriptContextHolder; import com.facebook.react.bridge.JavaScriptModule; import com.facebook.react.bridge.JavaScriptModuleRegistry; import com.facebook.react.bridge.NativeArray; @@ -163,6 +164,13 @@ public Collection getNativeModules() { return mReactHost.getRuntimeExecutor(); } + @Override + @FrameworkAPI + @UnstableReactNativeAPI + public @Nullable JavaScriptContextHolder getJavaScriptContextHolder() { + return mReactHost.getJavaScriptContextHolder(); + } + @Override public void handleException(Exception e) { mReactHost.handleHostException(e); diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/ReactHostImpl.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/ReactHostImpl.java index 08dca74feed5..674aeb42f9f7 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/ReactHostImpl.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/ReactHostImpl.java @@ -29,6 +29,7 @@ import com.facebook.react.ReactInstanceEventListener; import com.facebook.react.bridge.Callback; import com.facebook.react.bridge.JSBundleLoader; +import com.facebook.react.bridge.JavaScriptContextHolder; import com.facebook.react.bridge.MemoryPressureListener; import com.facebook.react.bridge.NativeArray; import com.facebook.react.bridge.NativeModule; @@ -599,6 +600,15 @@ RuntimeExecutor getRuntimeExecutor() { return null; } + @Nullable + JavaScriptContextHolder getJavaScriptContextHolder() { + final ReactInstance reactInstance = mReactInstanceTaskRef.get().getResult(); + if (reactInstance != null) { + return reactInstance.getJavaScriptContextHolder(); + } + return null; + } + /* package */ DefaultHardwareBackBtnHandler getDefaultBackButtonHandler() { return () -> { diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/ReactInstance.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/ReactInstance.java index d0d42462bf80..37d8d44d830a 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/ReactInstance.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/ReactInstance.java @@ -20,6 +20,7 @@ import com.facebook.react.bridge.Arguments; import com.facebook.react.bridge.JSBundleLoader; import com.facebook.react.bridge.JSBundleLoaderDelegate; +import com.facebook.react.bridge.JavaScriptContextHolder; import com.facebook.react.bridge.LifecycleEventListener; import com.facebook.react.bridge.NativeArray; import com.facebook.react.bridge.NativeMap; @@ -95,6 +96,8 @@ final class ReactInstance { private final JavaTimerManager mJavaTimerManager; private final BridgelessViewManagerResolver mViewManagerResolver; + private JavaScriptContextHolder mJavaScriptContextHolder; + @DoNotStrip @Nullable private ComponentNameResolverManager mComponentNameResolverManager; @DoNotStrip @Nullable private UIConstantsProviderManager mUIConstantsProviderManager; @@ -181,6 +184,8 @@ public void onHostDestroy() { bindingsInstaller, isProfiling); + mJavaScriptContextHolder = new JavaScriptContextHolder(getJavaScriptContext()); + // Set up TurboModules Systrace.beginSection( Systrace.TRACE_TAG_REACT_JAVA_BRIDGE, "ReactInstance.initialize#initTurboModules"); @@ -430,6 +435,10 @@ public Collection getNativeModules() { mFabricUIManager.stopSurface(surface.getSurfaceHandler()); } + /* package */ JavaScriptContextHolder getJavaScriptContextHolder() { + return mJavaScriptContextHolder; + } + /* --- Lifecycle methods --- */ @ThreadConfined("ReactHost") /* package */ void destroy() { @@ -440,6 +449,7 @@ public Collection getNativeModules() { mHybridData.resetNative(); mComponentNameResolverManager = null; mUIConstantsProviderManager = null; + mJavaScriptContextHolder.clear(); } /* --- Native methods --- */ @@ -475,6 +485,8 @@ private native HybridData initHybrid( private native RuntimeScheduler getRuntimeScheduler(); + private native long getJavaScriptContext(); + /* package */ native void callFunctionOnModule( String moduleName, String methodName, NativeArray args); diff --git a/packages/react-native/ReactAndroid/src/main/jni/react/runtime/jni/JReactInstance.cpp b/packages/react-native/ReactAndroid/src/main/jni/react/runtime/jni/JReactInstance.cpp index 0adccf64d7f1..ce3bc7b613e0 100644 --- a/packages/react-native/ReactAndroid/src/main/jni/react/runtime/jni/JReactInstance.cpp +++ b/packages/react-native/ReactAndroid/src/main/jni/react/runtime/jni/JReactInstance.cpp @@ -201,6 +201,10 @@ void JReactInstance::handleMemoryPressureJs(jint level) { instance_->handleMemoryPressureJs(level); } +jlong JReactInstance::getJavaScriptContext() { + return (jlong)(intptr_t)instance_->getJavaScriptContext(); +} + void JReactInstance::registerNatives() { registerHybrid({ makeNativeMethod("initHybrid", JReactInstance::initHybrid), @@ -230,6 +234,8 @@ void JReactInstance::registerNatives() { "registerSegmentNative", JReactInstance::registerSegment), makeNativeMethod( "handleMemoryPressureJs", JReactInstance::handleMemoryPressureJs), + makeNativeMethod( + "getJavaScriptContext", JReactInstance::getJavaScriptContext), }); } diff --git a/packages/react-native/ReactAndroid/src/main/jni/react/runtime/jni/JReactInstance.h b/packages/react-native/ReactAndroid/src/main/jni/react/runtime/jni/JReactInstance.h index b07ed7377fdf..6a28ea50c737 100644 --- a/packages/react-native/ReactAndroid/src/main/jni/react/runtime/jni/JReactInstance.h +++ b/packages/react-native/ReactAndroid/src/main/jni/react/runtime/jni/JReactInstance.h @@ -105,6 +105,8 @@ class JReactInstance : public jni::HybridClass { nativeMethodCallInvokerHolder_; jni::global_ref jReactExceptionManager_; jni::global_ref jBindingsInstaller_; + + jlong getJavaScriptContext(); }; } // namespace facebook::react diff --git a/packages/react-native/ReactCommon/react/runtime/ReactInstance.cpp b/packages/react-native/ReactCommon/react/runtime/ReactInstance.cpp index afefd87605c4..b4d34b28fd4c 100644 --- a/packages/react-native/ReactCommon/react/runtime/ReactInstance.cpp +++ b/packages/react-native/ReactCommon/react/runtime/ReactInstance.cpp @@ -465,4 +465,8 @@ void ReactInstance::handleMemoryPressureJs(int pressureLevel) { } } +void* ReactInstance::getJavaScriptContext() { + return &runtime_->getRuntime(); +} + } // namespace facebook::react diff --git a/packages/react-native/ReactCommon/react/runtime/ReactInstance.h b/packages/react-native/ReactCommon/react/runtime/ReactInstance.h index 50a4f17a1ed7..c82656c77679 100644 --- a/packages/react-native/ReactCommon/react/runtime/ReactInstance.h +++ b/packages/react-native/ReactCommon/react/runtime/ReactInstance.h @@ -71,6 +71,8 @@ class ReactInstance final : private jsinspector_modern::InstanceTargetDelegate { */ void unregisterFromInspector(); + void* getJavaScriptContext(); + private: std::shared_ptr runtime_; std::shared_ptr jsMessageQueueThread_; diff --git a/packages/react-native/ReactCommon/react/runtime/platform/ios/ReactCommon/RCTInstance.mm b/packages/react-native/ReactCommon/react/runtime/platform/ios/ReactCommon/RCTInstance.mm index 5bcec41c63da..a123105a672c 100644 --- a/packages/react-native/ReactCommon/react/runtime/platform/ios/ReactCommon/RCTInstance.mm +++ b/packages/react-native/ReactCommon/react/runtime/platform/ios/ReactCommon/RCTInstance.mm @@ -263,7 +263,8 @@ - (void)_start if (strongSelf && strongSelf->_valid) { [strongSelf registerSegmentWithId:segmentId path:path]; } - }]; + } + runtime:_reactInstance->getJavaScriptContext()]; [RCTBridge setCurrentBridge:(RCTBridge *)bridgeProxy]; // Set up TurboModules