Skip to content

Commit d7dce97

Browse files
philIipfacebook-github-bot
authored andcommitted
introduce native api to access RuntimeExecutor (#42882)
Summary: Pull Request resolved: #42882 Changelog: [Android][Added] - introduce native api to access RuntimeExecutor This is the android equivalent of [PR#42758](#42758). From [PR#42758](#42758) > The goal of this API is to provide a safe way to access the jsi::runtime in bridgeless mode. The decision to limit access to the runtime in bridgeless was a conscious one - the runtime pointer is not thread-safe and its lifecycle must be managed correctly by owners. > However, interacting with the runtime is an advanced use case we would want to support. Our recommended ways to access the runtime in bridgeless mode is either 1) via the RuntimeExecutor, or 2) via a C++ TurboModule. This diff introduces the API that would allow for 1). because react context can be non-null before react instance is ready, this can still return null. however, the callsite should be cognizant of when this will happen. in the case of expomodules, the runtime should be ready when the module is init, unless it is a eager initialized module Reviewed By: RSNara Differential Revision: D53461821 fbshipit-source-id: 69555d0593a59f8655e4dcd2f0ef1f78f4cfff7d
1 parent 40bb425 commit d7dce97

4 files changed

Lines changed: 49 additions & 3 deletions

File tree

packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/ReactContext.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@
2727
import com.facebook.react.common.LifecycleState;
2828
import com.facebook.react.common.ReactConstants;
2929
import com.facebook.react.common.annotations.DeprecatedInNewArchitecture;
30+
import com.facebook.react.common.annotations.FrameworkAPI;
31+
import com.facebook.react.common.annotations.UnstableReactNativeAPI;
3032
import java.lang.ref.WeakReference;
3133
import java.util.Collection;
3234
import java.util.concurrent.CopyOnWriteArraySet;
@@ -36,6 +38,7 @@
3638
* CatalystInstance}
3739
*/
3840
public class ReactContext extends ContextWrapper {
41+
3942
@DoNotStrip
4043
public interface RCTDeviceEventEmitter extends JavaScriptModule {
4144
void emit(@NonNull String eventName, @Nullable Object data);
@@ -206,6 +209,20 @@ public <T extends NativeModule> T getNativeModule(Class<T> nativeModuleInterface
206209
return mCatalystInstance.getNativeModule(nativeModuleInterface);
207210
}
208211

212+
/**
213+
* @return the RuntimeExecutor, a thread-safe handler for accessing the runtime.
214+
* @experimental
215+
*/
216+
@Nullable
217+
@FrameworkAPI
218+
@UnstableReactNativeAPI
219+
public RuntimeExecutor getRuntimeExecutor() {
220+
if (mCatalystInstance == null) {
221+
raiseCatalystInstanceMissingException();
222+
}
223+
return mCatalystInstance.getRuntimeExecutor();
224+
}
225+
209226
/**
210227
* Calls RCTDeviceEventEmitter.emit to JavaScript, with given event name and an optional list of
211228
* arguments.

packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/BridgelessReactContext.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,11 @@
1919
import com.facebook.react.bridge.ReactApplicationContext;
2020
import com.facebook.react.bridge.ReactNoCrashBridgeNotAllowedSoftException;
2121
import com.facebook.react.bridge.ReactSoftExceptionLogger;
22+
import com.facebook.react.bridge.RuntimeExecutor;
2223
import com.facebook.react.bridge.UIManager;
2324
import com.facebook.react.bridge.WritableNativeArray;
25+
import com.facebook.react.common.annotations.FrameworkAPI;
26+
import com.facebook.react.common.annotations.UnstableReactNativeAPI;
2427
import com.facebook.react.config.ReactFeatureFlags;
2528
import com.facebook.react.devsupport.interfaces.DevSupportManager;
2629
import com.facebook.react.modules.core.DefaultHardwareBackBtnHandler;
@@ -149,6 +152,16 @@ public Collection<NativeModule> getNativeModules() {
149152
public @Nullable <T extends NativeModule> T getNativeModule(Class<T> nativeModuleInterface) {
150153
return mReactHost.getNativeModule(nativeModuleInterface);
151154
}
155+
/**
156+
* @return the RuntimeExecutor, a thread-safe handler for accessing the runtime. If the runtime is
157+
* not initialized yet, it will return null.
158+
*/
159+
@Override
160+
@FrameworkAPI
161+
@UnstableReactNativeAPI
162+
public @Nullable RuntimeExecutor getRuntimeExecutor() {
163+
return mReactHost.getRuntimeExecutor();
164+
}
152165

153166
@Override
154167
public void handleException(Exception e) {

packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/ReactHostImpl.java

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
import com.facebook.react.bridge.ReactNoCrashBridgeNotAllowedSoftException;
3939
import com.facebook.react.bridge.ReactNoCrashSoftException;
4040
import com.facebook.react.bridge.ReactSoftExceptionLogger;
41+
import com.facebook.react.bridge.RuntimeExecutor;
4142
import com.facebook.react.bridge.UiThreadUtil;
4243
import com.facebook.react.bridge.queue.QueueThreadExceptionHandler;
4344
import com.facebook.react.bridge.queue.ReactQueueConfiguration;
@@ -542,7 +543,8 @@ private void setCurrentActivity(@Nullable Activity activity) {
542543
return reactInstance.getEventDispatcher();
543544
}
544545

545-
/* package */ @Nullable
546+
/* package */
547+
@Nullable
546548
FabricUIManager getUIManager() {
547549
final ReactInstance reactInstance = mReactInstanceTaskRef.get().getResult();
548550
if (reactInstance == null) {
@@ -567,7 +569,8 @@ FabricUIManager getUIManager() {
567569
return new ArrayList<>();
568570
}
569571

570-
/* package */ @Nullable
572+
/* package */
573+
@Nullable
571574
<T extends NativeModule> T getNativeModule(Class<T> nativeModuleInterface) {
572575
if (nativeModuleInterface == UIManagerModule.class) {
573576
ReactSoftExceptionLogger.logSoftExceptionVerbose(
@@ -583,6 +586,19 @@ <T extends NativeModule> T getNativeModule(Class<T> nativeModuleInterface) {
583586
return null;
584587
}
585588

589+
/* package */
590+
@Nullable
591+
RuntimeExecutor getRuntimeExecutor() {
592+
final ReactInstance reactInstance = mReactInstanceTaskRef.get().getResult();
593+
if (reactInstance != null) {
594+
return reactInstance.getBufferedRuntimeExecutor();
595+
}
596+
ReactSoftExceptionLogger.logSoftException(
597+
TAG,
598+
new ReactNoCrashSoftException("Tried to get runtime executor while instance is not ready"));
599+
return null;
600+
}
601+
586602
/* package */
587603
DefaultHardwareBackBtnHandler getDefaultBackButtonHandler() {
588604
return () -> {

packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/ReactInstance.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -471,7 +471,7 @@ private native HybridData initHybrid(
471471

472472
private native RuntimeExecutor getUnbufferedRuntimeExecutor();
473473

474-
private native RuntimeExecutor getBufferedRuntimeExecutor();
474+
/* package */ native RuntimeExecutor getBufferedRuntimeExecutor();
475475

476476
private native RuntimeScheduler getRuntimeScheduler();
477477

0 commit comments

Comments
 (0)