Enable Bridgeless (#38002)

Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/38002

Enable Bridgeless in RNTester Android by adding the initialization logic

Changelog: [Internal]

Reviewed By: fkgozali

Differential Revision: D46375362

fbshipit-source-id: 4c62cba5920d4c90d83a43afed4c4f91e52ec469
This commit is contained in:
Lulu Wu
2023-06-24 08:06:55 -07:00
committed by Facebook GitHub Bot
parent 72fab3c39a
commit 0876170681
14 changed files with 409 additions and 70 deletions
@@ -19,6 +19,8 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.facebook.infer.annotation.Assertions;
import com.facebook.react.bridge.Callback;
import com.facebook.react.config.ReactFeatureFlags;
import com.facebook.react.interfaces.ReactHostInterface;
import com.facebook.react.modules.core.PermissionListener;
/**
@@ -86,6 +88,10 @@ public class ReactActivityDelegate {
return ((ReactApplication) getPlainActivity().getApplication()).getReactNativeHost();
}
public ReactHostInterface getReactHost() {
return ((ReactApplication) getPlainActivity().getApplication()).getReactHostInterface();
}
public ReactInstanceManager getReactInstanceManager() {
return mReactDelegate.getReactInstanceManager();
}
@@ -97,14 +103,19 @@ public class ReactActivityDelegate {
protected void onCreate(Bundle savedInstanceState) {
String mainComponentName = getMainComponentName();
final Bundle launchOptions = composeLaunchOptions();
mReactDelegate =
new ReactDelegate(
getPlainActivity(), getReactNativeHost(), mainComponentName, launchOptions) {
@Override
protected ReactRootView createRootView() {
return ReactActivityDelegate.this.createRootView(launchOptions);
}
};
if (ReactFeatureFlags.enableBridgelessArchitecture) {
mReactDelegate =
new ReactDelegate(getPlainActivity(), getReactHost(), mainComponentName, launchOptions);
} else {
mReactDelegate =
new ReactDelegate(
getPlainActivity(), getReactNativeHost(), mainComponentName, launchOptions) {
@Override
protected ReactRootView createRootView() {
return ReactActivityDelegate.this.createRootView(launchOptions);
}
};
}
if (mainComponentName != null) {
loadApp(mainComponentName);
}
@@ -137,11 +148,13 @@ public class ReactActivityDelegate {
}
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (getReactNativeHost().hasInstance()
&& getReactNativeHost().getUseDeveloperSupport()
&& keyCode == KeyEvent.KEYCODE_MEDIA_FAST_FORWARD) {
event.startTracking();
return true;
if (!ReactFeatureFlags.enableBridgelessArchitecture) {
if (getReactNativeHost().hasInstance()
&& getReactNativeHost().getUseDeveloperSupport()
&& keyCode == KeyEvent.KEYCODE_MEDIA_FAST_FORWARD) {
event.startTracking();
return true;
}
}
return false;
}
@@ -151,11 +164,13 @@ public class ReactActivityDelegate {
}
public boolean onKeyLongPress(int keyCode, KeyEvent event) {
if (getReactNativeHost().hasInstance()
&& getReactNativeHost().getUseDeveloperSupport()
&& keyCode == KeyEvent.KEYCODE_MEDIA_FAST_FORWARD) {
getReactNativeHost().getReactInstanceManager().showDevOptionsDialog();
return true;
if (!ReactFeatureFlags.enableBridgelessArchitecture) {
if (getReactNativeHost().hasInstance()
&& getReactNativeHost().getUseDeveloperSupport()
&& keyCode == KeyEvent.KEYCODE_MEDIA_FAST_FORWARD) {
getReactNativeHost().getReactInstanceManager().showDevOptionsDialog();
return true;
}
}
return false;
}
@@ -165,22 +180,28 @@ public class ReactActivityDelegate {
}
public boolean onNewIntent(Intent intent) {
if (getReactNativeHost().hasInstance()) {
getReactNativeHost().getReactInstanceManager().onNewIntent(intent);
return true;
if (!ReactFeatureFlags.enableBridgelessArchitecture) {
if (getReactNativeHost().hasInstance()) {
getReactNativeHost().getReactInstanceManager().onNewIntent(intent);
return true;
}
}
return false;
}
public void onWindowFocusChanged(boolean hasFocus) {
if (getReactNativeHost().hasInstance()) {
getReactNativeHost().getReactInstanceManager().onWindowFocusChange(hasFocus);
if (!ReactFeatureFlags.enableBridgelessArchitecture) {
if (getReactNativeHost().hasInstance()) {
getReactNativeHost().getReactInstanceManager().onWindowFocusChange(hasFocus);
}
}
}
public void onConfigurationChanged(Configuration newConfig) {
if (getReactNativeHost().hasInstance()) {
getReactInstanceManager().onConfigurationChanged(getContext(), newConfig);
if (!ReactFeatureFlags.enableBridgelessArchitecture) {
if (getReactNativeHost().hasInstance()) {
getReactInstanceManager().onConfigurationChanged(getContext(), newConfig);
}
}
}
@@ -14,7 +14,10 @@ import android.view.KeyEvent;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.facebook.infer.annotation.Assertions;
import com.facebook.react.config.ReactFeatureFlags;
import com.facebook.react.devsupport.DoubleTapReloadRecognizer;
import com.facebook.react.interfaces.ReactHostInterface;
import com.facebook.react.interfaces.ReactSurfaceInterface;
import com.facebook.react.modules.core.DefaultHardwareBackBtnHandler;
/**
@@ -32,7 +35,9 @@ public class ReactDelegate {
@Nullable private DoubleTapReloadRecognizer mDoubleTapReloadRecognizer;
private ReactNativeHost mReactNativeHost;
@Nullable private ReactNativeHost mReactNativeHost;
@Nullable private ReactHostInterface mReactHost;
@Nullable private ReactSurfaceInterface mReactSurface;
private boolean mFabricEnabled = false;
@@ -48,6 +53,18 @@ public class ReactDelegate {
mReactNativeHost = reactNativeHost;
}
public ReactDelegate(
Activity activity,
ReactHostInterface reactHost,
@Nullable String appKey,
@Nullable Bundle launchOptions) {
mActivity = activity;
mMainComponentName = appKey;
mLaunchOptions = launchOptions;
mDoubleTapReloadRecognizer = new DoubleTapReloadRecognizer();
mReactHost = reactHost;
}
public ReactDelegate(
Activity activity,
ReactNativeHost reactNativeHost,
@@ -63,48 +80,72 @@ public class ReactDelegate {
}
public void onHostResume() {
if (getReactNativeHost().hasInstance()) {
if (ReactFeatureFlags.enableBridgelessArchitecture) {
if (mActivity instanceof DefaultHardwareBackBtnHandler) {
getReactNativeHost()
.getReactInstanceManager()
.onHostResume(mActivity, (DefaultHardwareBackBtnHandler) mActivity);
} else {
throw new ClassCastException(
"Host Activity does not implement DefaultHardwareBackBtnHandler");
mReactHost.onHostResume(mActivity, (DefaultHardwareBackBtnHandler) mActivity);
}
} else {
if (getReactNativeHost().hasInstance()) {
if (mActivity instanceof DefaultHardwareBackBtnHandler) {
getReactNativeHost()
.getReactInstanceManager()
.onHostResume(mActivity, (DefaultHardwareBackBtnHandler) mActivity);
} else {
throw new ClassCastException(
"Host Activity does not implement DefaultHardwareBackBtnHandler");
}
}
}
}
public void onHostPause() {
if (getReactNativeHost().hasInstance()) {
getReactNativeHost().getReactInstanceManager().onHostPause(mActivity);
if (ReactFeatureFlags.enableBridgelessArchitecture) {
mReactHost.onHostPause(mActivity);
} else {
if (getReactNativeHost().hasInstance()) {
getReactNativeHost().getReactInstanceManager().onHostPause(mActivity);
}
}
}
public void onHostDestroy() {
if (mReactRootView != null) {
mReactRootView.unmountReactApplication();
mReactRootView = null;
}
if (getReactNativeHost().hasInstance()) {
getReactNativeHost().getReactInstanceManager().onHostDestroy(mActivity);
if (ReactFeatureFlags.enableBridgelessArchitecture) {
mReactHost.onHostDestroy(mActivity);
} else {
if (mReactRootView != null) {
mReactRootView.unmountReactApplication();
mReactRootView = null;
}
if (getReactNativeHost().hasInstance()) {
getReactNativeHost().getReactInstanceManager().onHostDestroy(mActivity);
}
}
}
public boolean onBackPressed() {
if (getReactNativeHost().hasInstance()) {
getReactNativeHost().getReactInstanceManager().onBackPressed();
if (ReactFeatureFlags.enableBridgelessArchitecture) {
mReactHost.onBackPressed();
return true;
} else {
if (getReactNativeHost().hasInstance()) {
getReactNativeHost().getReactInstanceManager().onBackPressed();
return true;
}
}
return false;
}
public void onActivityResult(
int requestCode, int resultCode, Intent data, boolean shouldForwardToReactInstance) {
if (getReactNativeHost().hasInstance() && shouldForwardToReactInstance) {
getReactNativeHost()
.getReactInstanceManager()
.onActivityResult(mActivity, requestCode, resultCode, data);
if (ReactFeatureFlags.enableBridgelessArchitecture) {
// TODO T156475655: Implement onActivityResult for Bridgeless
return;
} else {
if (getReactNativeHost().hasInstance() && shouldForwardToReactInstance) {
getReactNativeHost()
.getReactInstanceManager()
.onActivityResult(mActivity, requestCode, resultCode, data);
}
}
}
@@ -113,16 +154,31 @@ public class ReactDelegate {
}
public void loadApp(String appKey) {
if (mReactRootView != null) {
throw new IllegalStateException("Cannot loadApp while app is already running.");
// With Bridgeless enabled, create and start the surface
if (ReactFeatureFlags.enableBridgelessArchitecture) {
if (mReactSurface == null) {
// Create a ReactSurface
mReactSurface = mReactHost.createSurface(mActivity, appKey, mLaunchOptions);
// Set main Activity's content view
mActivity.setContentView(mReactSurface.getView());
}
mReactSurface.start();
} else {
if (mReactRootView != null) {
throw new IllegalStateException("Cannot loadApp while app is already running.");
}
mReactRootView = createRootView();
mReactRootView.startReactApplication(
getReactNativeHost().getReactInstanceManager(), appKey, mLaunchOptions);
}
mReactRootView = createRootView();
mReactRootView.startReactApplication(
getReactNativeHost().getReactInstanceManager(), appKey, mLaunchOptions);
}
public ReactRootView getReactRootView() {
return mReactRootView;
if (ReactFeatureFlags.enableBridgelessArchitecture) {
return (ReactRootView) mReactSurface.getView();
} else {
return mReactRootView;
}
}
protected ReactRootView createRootView() {
@@ -139,7 +195,11 @@ public class ReactDelegate {
* application.
*/
public boolean shouldShowDevMenuOrReload(int keyCode, KeyEvent event) {
if (getReactNativeHost().hasInstance() && getReactNativeHost().getUseDeveloperSupport()) {
if (ReactFeatureFlags.enableBridgelessArchitecture) {
// TODO T156475655: Implement shouldShowDevMenuOrReload for Bridgeless
return false;
} else if (getReactNativeHost().hasInstance()
&& getReactNativeHost().getUseDeveloperSupport()) {
if (keyCode == KeyEvent.KEYCODE_MENU) {
getReactNativeHost().getReactInstanceManager().showDevOptionsDialog();
return true;
@@ -15,6 +15,7 @@ import static java.lang.Boolean.TRUE;
import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import androidx.annotation.Nullable;
import com.facebook.common.logging.FLog;
import com.facebook.infer.annotation.Assertions;
@@ -44,11 +45,13 @@ import com.facebook.react.bridgeless.internal.bolts.TaskCompletionSource;
import com.facebook.react.common.LifecycleState;
import com.facebook.react.common.build.ReactBuildConfig;
import com.facebook.react.config.ReactFeatureFlags;
import com.facebook.react.devsupport.DevSupportManagerBase;
import com.facebook.react.devsupport.DisabledDevSupportManager;
import com.facebook.react.devsupport.interfaces.DevSupportManager;
import com.facebook.react.fabric.ComponentFactory;
import com.facebook.react.fabric.FabricUIManager;
import com.facebook.react.interfaces.ReactHostInterface;
import com.facebook.react.interfaces.ReactSurfaceInterface;
import com.facebook.react.modules.core.DefaultHardwareBackBtnHandler;
import com.facebook.react.modules.core.DeviceEventManagerModule;
import com.facebook.react.uimanager.UIManagerModule;
@@ -432,6 +435,15 @@ public class ReactHost implements ReactHostInterface {
return assertNotNull(mDevSupportManager);
}
@Override
public ReactSurfaceInterface createSurface(
Context context, String moduleName, @Nullable Bundle initialProps) {
ReactSurface surface = new ReactSurface(context, moduleName, initialProps);
surface.attachView(new ReactSurfaceView(context, surface));
surface.attach(this);
return surface;
}
@Nullable
/* package */ Activity getCurrentActivity() {
return mActivity.get();
@@ -495,7 +507,7 @@ public class ReactHost implements ReactHostInterface {
return null;
}
/* package */ DefaultHardwareBackBtnHandler getDefaultBackButtonHandler() {
public DefaultHardwareBackBtnHandler getDefaultBackButtonHandler() {
return () -> {
UiThreadUtil.assertOnUiThread();
if (mDefaultHardwareBackBtnHandler != null) {
@@ -1002,16 +1014,21 @@ public class ReactHost implements ReactHostInterface {
log(method);
final TaskCompletionSource<JSBundleLoader> taskCompletionSource = new TaskCompletionSource<>();
final DevSupportManager asyncDevSupportManager = getDevSupportManager();
final String sourceUrl = asyncDevSupportManager.getSourceUrl();
final DevSupportManagerBase asyncDevSupportManager =
((DevSupportManagerBase) getDevSupportManager());
String bundleURL =
asyncDevSupportManager
.getDevServerHelper()
.getDevServerBundleURL(
Assertions.assertNotNull(asyncDevSupportManager.getJSAppBundleName()));
asyncDevSupportManager.reloadJSFromServer(
sourceUrl,
bundleURL,
() -> {
log(method, "Creating BundleLoader");
JSBundleLoader bundleLoader =
JSBundleLoader.createCachedBundleFromNetworkLoader(
sourceUrl, asyncDevSupportManager.getDownloadedJSBundleFile());
bundleURL, asyncDevSupportManager.getDownloadedJSBundleFile());
taskCompletionSource.setResult(bundleLoader);
});
@@ -12,6 +12,7 @@ import android.os.Bundle;
import android.util.DisplayMetrics;
import android.view.View;
import android.view.View.MeasureSpec;
import android.view.ViewGroup;
import androidx.annotation.UiThread;
import com.facebook.infer.annotation.Nullsafe;
import com.facebook.infer.annotation.ThreadSafe;
@@ -24,6 +25,7 @@ import com.facebook.react.common.annotations.VisibleForTesting;
import com.facebook.react.fabric.SurfaceHandler;
import com.facebook.react.fabric.SurfaceHandlerBinding;
import com.facebook.react.interfaces.ReactSurfaceInterface;
import com.facebook.react.interfaces.TaskInterface;
import com.facebook.react.modules.i18nmanager.I18nUtil;
import com.facebook.react.uimanager.events.EventDispatcher;
import java.util.concurrent.atomic.AtomicReference;
@@ -130,7 +132,8 @@ public class ReactSurface implements ReactSurfaceInterface {
return mSurfaceHandler;
}
public @Nullable ReactSurfaceView getView() {
@Override
public @Nullable ViewGroup getView() {
return mSurfaceView.get();
}
@@ -144,7 +147,8 @@ public class ReactSurface implements ReactSurfaceInterface {
return host.prerenderSurface(this);
}
public Task<Void> start() {
@Override
public TaskInterface start() {
if (mSurfaceView.get() == null) {
return Task.forError(
new IllegalStateException(
@@ -181,7 +185,7 @@ public class ReactSurface implements ReactSurfaceInterface {
public void clear() {
UiThreadUtil.runOnUiThread(
() -> {
ReactSurfaceView view = getView();
ReactSurfaceView view = (ReactSurfaceView) getView();
if (view != null) {
view.removeAllViews();
view.setId(View.NO_ID);
@@ -7,6 +7,7 @@
package com.facebook.react.bridgeless.internal.bolts;
import com.facebook.react.interfaces.TaskInterface;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
@@ -26,7 +27,7 @@ import java.util.concurrent.atomic.AtomicInteger;
*
* @param <TResult> The type of the result of the task.
*/
public class Task<TResult> {
public class Task<TResult> implements TaskInterface {
/** An {@link java.util.concurrent.Executor} that executes tasks in parallel. */
public static final ExecutorService BACKGROUND_EXECUTOR = BoltsExecutors.background();
@@ -27,15 +27,18 @@ object DefaultNewArchitectureEntryPoint {
fun load(
turboModulesEnabled: Boolean = true,
fabricEnabled: Boolean = true,
bridgelessEnaled: Boolean = false,
dynamicLibraryName: String = "appmodules",
) {
ReactFeatureFlags.useTurboModules = turboModulesEnabled
ReactFeatureFlags.enableFabricRenderer = fabricEnabled
ReactFeatureFlags.unstable_useFabricInterop = fabricEnabled
ReactFeatureFlags.enableBridgelessArchitecture = bridgelessEnaled
this.privateFabricEnabled = fabricEnabled
this.privateTurboModulesEnabled = turboModulesEnabled
this.privateConcurrentReactEnabled = fabricEnabled
this.privateBridgelessEnabled = bridgelessEnaled
SoLoader.loadLibrary("react_newarchdefaults")
SoLoader.loadLibrary(dynamicLibraryName)
@@ -49,10 +52,11 @@ object DefaultNewArchitectureEntryPoint {
fun load(
turboModulesEnabled: Boolean = true,
fabricEnabled: Boolean = true,
bridgelessEnaled: Boolean = false,
@Suppress("UNUSED_PARAMETER") concurrentReactEnabled: Boolean = true,
dynamicLibraryName: String = "appmodules",
) {
load(turboModulesEnabled, fabricEnabled, dynamicLibraryName)
load(turboModulesEnabled, fabricEnabled, bridgelessEnaled, dynamicLibraryName)
}
private var privateFabricEnabled: Boolean = false
@@ -69,4 +73,9 @@ object DefaultNewArchitectureEntryPoint {
@JvmStatic
val concurrentReactEnabled: Boolean
get() = privateConcurrentReactEnabled
private var privateBridgelessEnabled: Boolean = false
@JvmStatic
val bridgelessEnaled: Boolean
get() = privateBridgelessEnabled
}
@@ -27,7 +27,7 @@ private constructor(context: ReactApplicationContext, packages: List<ReactPackag
@DoNotStrip external override fun initHybrid(): HybridData?
class Builder : ReactPackageTurboModuleManagerDelegate.Builder() {
override fun build(context: ReactApplicationContext, packages: List<ReactPackage>) =
public override fun build(context: ReactApplicationContext, packages: List<ReactPackage>) =
DefaultTurboModuleManagerDelegate(context, packages)
}
}
@@ -687,7 +687,7 @@ public abstract class DevSupportManagerBase implements DevSupportManager {
return mCurrentContext;
}
protected @Nullable String getJSAppBundleName() {
public @Nullable String getJSAppBundleName() {
return mJSAppBundleName;
}
@@ -695,7 +695,7 @@ public abstract class DevSupportManagerBase implements DevSupportManager {
return mApplicationContext;
}
protected DevServerHelper getDevServerHelper() {
public DevServerHelper getDevServerHelper() {
return mDevServerHelper;
}
@@ -8,6 +8,8 @@
package com.facebook.react.interfaces
import android.app.Activity
import android.content.Context
import android.os.Bundle
import com.facebook.react.bridge.ReactContext
import com.facebook.react.bridge.queue.ReactQueueConfiguration
import com.facebook.react.common.LifecycleState
@@ -63,4 +65,11 @@ interface ReactHostInterface {
/** To be called when the host activity is destroyed. */
fun onHostDestroy(activity: Activity?)
/** To be called to create and setup an ReactSurface. */
fun createSurface(
context: Context,
moduleName: String,
initialProps: Bundle?
): ReactSurfaceInterface?
}
@@ -7,8 +7,16 @@
package com.facebook.react.interfaces
import android.view.ViewGroup
/** Represents a Surface in React Native. */
interface ReactSurfaceInterface {
// the API of this interface will be completed as we analyze and refactor API of ReactSurface,
// ReactRootView, etc.
// Start running this surface
fun start(): TaskInterface
// Get React root view of this surface
fun getView(): ViewGroup?
}
@@ -0,0 +1,13 @@
/*
* 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.interfaces
/**
* This is the public interface for Task which represents the result of an asynchronous computation.
*/
interface TaskInterface {}
@@ -88,7 +88,7 @@ public class ReactSurfaceTest {
public void testStart() throws InterruptedException {
mReactSurface.attach(mReactHost);
assertThat(mReactHost.isSurfaceAttached(mReactSurface)).isFalse();
Task<Void> task = mReactSurface.start();
Task<Void> task = (Task<Void>) mReactSurface.start();
task.waitForCompletion();
verify(mReactHost).startSurface(mReactSurface);
@@ -99,7 +99,7 @@ public class ReactSurfaceTest {
public void testStop() throws InterruptedException {
mReactSurface.attach(mReactHost);
Task<Void> task = mReactSurface.start();
Task<Void> task = (Task<Void>) mReactSurface.start();
task.waitForCompletion();
task = mReactSurface.stop();
@@ -147,7 +147,8 @@ public class ReactSurfaceTest {
assertThat(mReactSurface.isRunning()).isFalse();
mReactSurface.start().waitForCompletion();
Task<Void> task = (Task<Void>) mReactSurface.start();
task.waitForCompletion();
assertThat(mReactSurface.isRunning()).isTrue();
@@ -16,9 +16,16 @@ import com.facebook.react.ReactPackage;
import com.facebook.react.TurboReactPackage;
import com.facebook.react.bridge.NativeModule;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridgeless.ReactHost;
import com.facebook.react.bridgeless.exceptionmanager.ReactJsExceptionHandler;
import com.facebook.react.common.annotations.UnstableReactNativeAPI;
import com.facebook.react.common.mapbuffer.ReadableMapBuffer;
import com.facebook.react.config.ReactFeatureFlags;
import com.facebook.react.defaults.DefaultComponentsRegistry;
import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint;
import com.facebook.react.defaults.DefaultReactNativeHost;
import com.facebook.react.fabric.ComponentFactory;
import com.facebook.react.interfaces.ReactHostInterface;
import com.facebook.react.module.model.ReactModuleInfo;
import com.facebook.react.module.model.ReactModuleInfoProvider;
import com.facebook.react.shell.MainReactPackage;
@@ -36,6 +43,8 @@ import java.util.Map;
public class RNTesterApplication extends Application implements ReactApplication {
private ReactHost mReactHost;
private final ReactNativeHost mReactNativeHost =
new DefaultReactNativeHost(this) {
@Override
@@ -142,4 +151,34 @@ public class RNTesterApplication extends Application implements ReactApplication
public ReactNativeHost getReactNativeHost() {
return mReactNativeHost;
}
@Override
@UnstableReactNativeAPI
public ReactHostInterface getReactHostInterface() {
if (mReactHost == null) {
// Create an instance of ReactHost to manager the instance of ReactInstance,
// which is similar to how we use ReactNativeHost to manager instance of ReactInstanceManager
RNTesterReactHostDelegate reactHostDelegate =
new RNTesterReactHostDelegate(getApplicationContext());
RNTesterReactJsExceptionHandler reactJsExceptionHandler =
new RNTesterReactJsExceptionHandler();
ComponentFactory componentFactory = new ComponentFactory();
DefaultComponentsRegistry.register(componentFactory);
mReactHost =
new ReactHost(
this.getApplicationContext(),
reactHostDelegate,
componentFactory,
true,
reactJsExceptionHandler,
true);
reactHostDelegate.setReactHost(mReactHost);
}
return mReactHost;
}
public static class RNTesterReactJsExceptionHandler implements ReactJsExceptionHandler {
public void reportJsException(ReadableMapBuffer errorMap) {}
}
};
@@ -0,0 +1,157 @@
/*
* 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.uiapp;
import android.content.Context;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.facebook.fbreact.specs.SampleTurboModule;
import com.facebook.react.ReactPackage;
import com.facebook.react.ReactPackageTurboModuleManagerDelegate;
import com.facebook.react.TurboReactPackage;
import com.facebook.react.bridge.JSBundleLoader;
import com.facebook.react.bridge.NativeModule;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridgeless.BindingsInstaller;
import com.facebook.react.bridgeless.JSEngineInstance;
import com.facebook.react.bridgeless.ReactHost;
import com.facebook.react.bridgeless.ReactHostDelegate;
import com.facebook.react.bridgeless.hermes.HermesInstance;
import com.facebook.react.common.annotations.UnstableReactNativeAPI;
import com.facebook.react.config.ReactFeatureFlags;
import com.facebook.react.defaults.DefaultTurboModuleManagerDelegate;
import com.facebook.react.fabric.ReactNativeConfig;
import com.facebook.react.module.model.ReactModuleInfo;
import com.facebook.react.module.model.ReactModuleInfoProvider;
import com.facebook.react.shell.MainReactPackage;
import com.facebook.react.turbomodule.core.TurboModuleManager;
import com.facebook.react.uiapp.component.MyLegacyViewManager;
import com.facebook.react.uiapp.component.MyNativeViewManager;
import com.facebook.react.uimanager.ViewManager;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@UnstableReactNativeAPI
public class RNTesterReactHostDelegate implements ReactHostDelegate {
private final Context mContext;
private @Nullable ReactHost mReactHost;
private @Nullable List<ReactPackage> mReactPackages;
RNTesterReactHostDelegate(Context context) {
this.mContext = context;
}
public void setReactHost(ReactHost reactHost) {
mReactHost = reactHost;
}
@Override
public String getJSMainModulePath() {
return "js/RNTesterApp.android";
}
@Override
public JSBundleLoader getJSBundleLoader() {
return JSBundleLoader.createAssetLoader(mContext, "assets://RNTesterApp.android.bundle", true);
}
@Override
public synchronized BindingsInstaller getBindingsInstaller() {
return null;
}
@NonNull
@Override
public ReactPackageTurboModuleManagerDelegate.Builder getTurboModuleManagerDelegateBuilder() {
return new DefaultTurboModuleManagerDelegate.Builder();
}
@Override
public JSEngineInstance getJSEngineInstance() {
return new HermesInstance();
}
@Override
public void handleInstanceException(Exception e) {}
@Override
public ReactNativeConfig getReactNativeConfig(TurboModuleManager turboModuleManager) {
return ReactNativeConfig.DEFAULT_CONFIG;
}
@Override
public List<ReactPackage> getReactPackages() {
if (mReactPackages == null) {
mReactPackages =
Arrays.<ReactPackage>asList(
new MainReactPackage(),
new TurboReactPackage() {
public NativeModule getModule(
final String name, final ReactApplicationContext reactContext) {
if (!ReactFeatureFlags.useTurboModules) {
return null;
}
if (SampleTurboModule.NAME.equals(name)) {
return new SampleTurboModule(reactContext);
}
return null;
}
// Note: Specialized annotation processor for @ReactModule isn't configured in OSS
// yet. For now, hardcode this information, though it's not necessary for most
// modules.
public ReactModuleInfoProvider getReactModuleInfoProvider() {
return new ReactModuleInfoProvider() {
public Map<String, ReactModuleInfo> getReactModuleInfos() {
final Map<String, ReactModuleInfo> moduleInfos = new HashMap<>();
if (ReactFeatureFlags.useTurboModules) {
moduleInfos.put(
SampleTurboModule.NAME,
new ReactModuleInfo(
SampleTurboModule.NAME,
"SampleTurboModule",
false, // canOverrideExistingModule
false, // needsEagerInit
true, // hasConstants
false, // isCxxModule
true // isTurboModule
));
}
return moduleInfos;
}
};
}
},
new ReactPackage() {
@NonNull
@Override
public List<NativeModule> createNativeModules(
@NonNull ReactApplicationContext reactContext) {
return Collections.emptyList();
}
@NonNull
@Override
public List<ViewManager> createViewManagers(
@NonNull ReactApplicationContext reactContext) {
List<ViewManager> viewManagers = new ArrayList<>();
viewManagers.add(new MyNativeViewManager());
viewManagers.add(new MyLegacyViewManager(reactContext));
return viewManagers;
}
});
}
return mReactPackages;
}
}