Skip to content

Commit c867aba

Browse files
cortinicofacebook-github-bot
authored andcommitted
Move BridgelessDevSupportManager to .devsupport package (#46914)
Summary: Pull Request resolved: #46914 The `BridgelessDevSupportManager` should have lived inside the `.devsupport` package alongside all the other devsupport related tooling. It was instead created inside `.runtime` causing a tight coupling with `ReactHostImpl`. This made it impossible for Frameworks to customize it (i.e. in Expo GO) also because there was a circular dependency between ReactHostImpl and BridgelessDevSupportManager In this diff I'm: 1. Breaking the circular dependency by using `ReactHostDevHelper` 2. Updating all the parameters to reference `ReactHost` rather than `ReactHostImpl` 3. Moving BridgelessDevSupportManager to the `.devsupport` package. This is breaking for users that are manually composing a `BridgelessDevSupportManager` or that are extending the `ReactInstanceDevHelper`. - `ReactInstanceDevHelper` has 3 new method which will have to be implemented. - `BridgelessDevSupportManager` is now living in a different package. Changelog: [Android] [Breaking] - Add 3 methods to ReactInstanceDevHelper Reviewed By: rshest Differential Revision: D64105790 fbshipit-source-id: 13478fe1a035adb5b0dc83ebb1daad6cfb243881
1 parent ad6a2fa commit c867aba

File tree

12 files changed

+354
-192
lines changed

12 files changed

+354
-192
lines changed

packages/react-native/ReactAndroid/api/ReactAndroid.api

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2134,6 +2134,7 @@ public final class com/facebook/react/devsupport/DefaultDevLoadingViewImplementa
21342134
public final class com/facebook/react/devsupport/DefaultDevSupportManagerFactory : com/facebook/react/devsupport/DevSupportManagerFactory {
21352135
public fun <init> ()V
21362136
public fun create (Landroid/content/Context;Lcom/facebook/react/devsupport/ReactInstanceDevHelper;Ljava/lang/String;ZLcom/facebook/react/devsupport/interfaces/RedBoxHandler;Lcom/facebook/react/devsupport/interfaces/DevBundleDownloadListener;ILjava/util/Map;Lcom/facebook/react/common/SurfaceDelegateFactory;Lcom/facebook/react/devsupport/interfaces/DevLoadingViewManager;Lcom/facebook/react/devsupport/interfaces/PausedInDebuggerOverlayManager;)Lcom/facebook/react/devsupport/interfaces/DevSupportManager;
2137+
public fun create (Landroid/content/Context;Lcom/facebook/react/devsupport/ReactInstanceDevHelper;Ljava/lang/String;ZLcom/facebook/react/devsupport/interfaces/RedBoxHandler;Lcom/facebook/react/devsupport/interfaces/DevBundleDownloadListener;ILjava/util/Map;Lcom/facebook/react/common/SurfaceDelegateFactory;Lcom/facebook/react/devsupport/interfaces/DevLoadingViewManager;Lcom/facebook/react/devsupport/interfaces/PausedInDebuggerOverlayManager;Z)Lcom/facebook/react/devsupport/interfaces/DevSupportManager;
21372138
}
21382139

21392140
public class com/facebook/react/devsupport/DevServerHelper {
@@ -2173,6 +2174,7 @@ public final class com/facebook/react/devsupport/DevSettingsActivity : android/p
21732174
}
21742175

21752176
public abstract class com/facebook/react/devsupport/DevSupportManagerBase : com/facebook/react/devsupport/interfaces/DevSupportManager {
2177+
protected final field mReactInstanceDevHelper Lcom/facebook/react/devsupport/ReactInstanceDevHelper;
21762178
public fun <init> (Landroid/content/Context;Lcom/facebook/react/devsupport/ReactInstanceDevHelper;Ljava/lang/String;ZLcom/facebook/react/devsupport/interfaces/RedBoxHandler;Lcom/facebook/react/devsupport/interfaces/DevBundleDownloadListener;ILjava/util/Map;Lcom/facebook/react/common/SurfaceDelegateFactory;Lcom/facebook/react/devsupport/interfaces/DevLoadingViewManager;Lcom/facebook/react/devsupport/interfaces/PausedInDebuggerOverlayManager;)V
21772179
public fun addCustomDevOption (Ljava/lang/String;Lcom/facebook/react/devsupport/interfaces/DevOptionHandler;)V
21782180
public fun createRootView (Ljava/lang/String;)Landroid/view/View;
@@ -2236,6 +2238,7 @@ public abstract interface class com/facebook/react/devsupport/DevSupportManagerB
22362238

22372239
public abstract interface class com/facebook/react/devsupport/DevSupportManagerFactory {
22382240
public abstract fun create (Landroid/content/Context;Lcom/facebook/react/devsupport/ReactInstanceDevHelper;Ljava/lang/String;ZLcom/facebook/react/devsupport/interfaces/RedBoxHandler;Lcom/facebook/react/devsupport/interfaces/DevBundleDownloadListener;ILjava/util/Map;Lcom/facebook/react/common/SurfaceDelegateFactory;Lcom/facebook/react/devsupport/interfaces/DevLoadingViewManager;Lcom/facebook/react/devsupport/interfaces/PausedInDebuggerOverlayManager;)Lcom/facebook/react/devsupport/interfaces/DevSupportManager;
2241+
public abstract fun create (Landroid/content/Context;Lcom/facebook/react/devsupport/ReactInstanceDevHelper;Ljava/lang/String;ZLcom/facebook/react/devsupport/interfaces/RedBoxHandler;Lcom/facebook/react/devsupport/interfaces/DevBundleDownloadListener;ILjava/util/Map;Lcom/facebook/react/common/SurfaceDelegateFactory;Lcom/facebook/react/devsupport/interfaces/DevLoadingViewManager;Lcom/facebook/react/devsupport/interfaces/PausedInDebuggerOverlayManager;Z)Lcom/facebook/react/devsupport/interfaces/DevSupportManager;
22392242
}
22402243

22412244
public final class com/facebook/react/devsupport/DoubleTapReloadRecognizer {
@@ -2327,9 +2330,12 @@ public abstract interface class com/facebook/react/devsupport/ReactInstanceDevHe
23272330
public abstract fun createRootView (Ljava/lang/String;)Landroid/view/View;
23282331
public abstract fun destroyRootView (Landroid/view/View;)V
23292332
public abstract fun getCurrentActivity ()Landroid/app/Activity;
2333+
public abstract fun getCurrentReactContext ()Lcom/facebook/react/bridge/ReactContext;
23302334
public abstract fun getJavaScriptExecutorFactory ()Lcom/facebook/react/bridge/JavaScriptExecutorFactory;
2335+
public abstract fun loadBundle (Lcom/facebook/react/bridge/JSBundleLoader;)Lcom/facebook/react/interfaces/TaskInterface;
23312336
public abstract fun onJSBundleLoadedFromServer ()V
23322337
public abstract fun onReloadWithJSDebugger (Lcom/facebook/react/bridge/JavaJSExecutor$Factory;)V
2338+
public abstract fun reload (Ljava/lang/String;)V
23332339
public abstract fun toggleElementInspector ()V
23342340
}
23352341

@@ -3887,6 +3893,7 @@ public abstract class com/facebook/react/runtime/JSRuntimeFactory {
38873893

38883894
public class com/facebook/react/runtime/ReactHostImpl : com/facebook/react/ReactHost {
38893895
public fun <init> (Landroid/content/Context;Lcom/facebook/react/runtime/ReactHostDelegate;Lcom/facebook/react/fabric/ComponentFactory;Ljava/util/concurrent/Executor;Ljava/util/concurrent/Executor;ZZ)V
3896+
public fun <init> (Landroid/content/Context;Lcom/facebook/react/runtime/ReactHostDelegate;Lcom/facebook/react/fabric/ComponentFactory;Ljava/util/concurrent/Executor;Ljava/util/concurrent/Executor;ZZLcom/facebook/react/devsupport/DevSupportManagerFactory;)V
38903897
public fun <init> (Landroid/content/Context;Lcom/facebook/react/runtime/ReactHostDelegate;Lcom/facebook/react/fabric/ComponentFactory;ZZ)V
38913898
public fun addBeforeDestroyListener (Lkotlin/jvm/functions/Function0;)V
38923899
public fun addReactInstanceEventListener (Lcom/facebook/react/ReactInstanceEventListener;)V
@@ -3918,7 +3925,7 @@ public class com/facebook/react/runtime/ReactHostImpl : com/facebook/react/React
39183925

39193926
public class com/facebook/react/runtime/ReactSurfaceImpl : com/facebook/react/interfaces/fabric/ReactSurface {
39203927
public fun <init> (Landroid/content/Context;Ljava/lang/String;Landroid/os/Bundle;)V
3921-
public fun attach (Lcom/facebook/react/runtime/ReactHostImpl;)V
3928+
public fun attach (Lcom/facebook/react/ReactHost;)V
39223929
public fun attachView (Lcom/facebook/react/runtime/ReactSurfaceView;)V
39233930
public fun clear ()V
39243931
public static fun createWithView (Landroid/content/Context;Ljava/lang/String;Landroid/os/Bundle;)Lcom/facebook/react/runtime/ReactSurfaceImpl;

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

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@
9292
import com.facebook.react.devsupport.interfaces.PackagerStatusCallback;
9393
import com.facebook.react.devsupport.interfaces.PausedInDebuggerOverlayManager;
9494
import com.facebook.react.devsupport.interfaces.RedBoxHandler;
95+
import com.facebook.react.interfaces.TaskInterface;
9596
import com.facebook.react.internal.AndroidChoreographerProvider;
9697
import com.facebook.react.internal.ChoreographerProvider;
9798
import com.facebook.react.internal.featureflags.ReactNativeFeatureFlags;
@@ -369,6 +370,23 @@ public void destroyRootView(View rootView) {
369370
((ReactRootView) rootView).unmountReactApplication();
370371
}
371372
}
373+
374+
@Override
375+
public void reload(String s) {
376+
// no-op not implemented for Bridge Mode
377+
}
378+
379+
@Override
380+
public TaskInterface<Boolean> loadBundle(JSBundleLoader bundleLoader) {
381+
// no-op not implemented for Bridge Mode
382+
return null;
383+
}
384+
385+
@Override
386+
public ReactContext getCurrentReactContext() {
387+
// no-op not implemented for Bridge Mode
388+
return null;
389+
}
372390
};
373391
}
374392

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
/*
2+
* Copyright (c) Meta Platforms, Inc. and affiliates.
3+
*
4+
* This source code is licensed under the MIT license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*/
7+
8+
package com.facebook.react.devsupport;
9+
10+
import android.content.Context;
11+
import androidx.annotation.Nullable;
12+
import com.facebook.infer.annotation.Nullsafe;
13+
import com.facebook.react.bridge.JSBundleLoader;
14+
import com.facebook.react.bridge.ReactContext;
15+
import com.facebook.react.bridge.UiThreadUtil;
16+
import com.facebook.react.common.SurfaceDelegateFactory;
17+
import com.facebook.react.devsupport.interfaces.DevBundleDownloadListener;
18+
import com.facebook.react.devsupport.interfaces.DevLoadingViewManager;
19+
import com.facebook.react.devsupport.interfaces.DevSplitBundleCallback;
20+
import com.facebook.react.devsupport.interfaces.PausedInDebuggerOverlayManager;
21+
import com.facebook.react.devsupport.interfaces.RedBoxHandler;
22+
import com.facebook.react.packagerconnection.RequestHandler;
23+
import java.util.Map;
24+
25+
/**
26+
* An implementation of {@link com.facebook.react.devsupport.interfaces.DevSupportManager} that
27+
* extends the functionality in {@link DevSupportManagerBase} with some additional, more flexible
28+
* APIs for asynchronously loading the JS bundle.
29+
*/
30+
@Nullsafe(Nullsafe.Mode.LOCAL)
31+
class BridgelessDevSupportManager extends DevSupportManagerBase {
32+
33+
public BridgelessDevSupportManager(
34+
Context context,
35+
ReactInstanceDevHelper reactInstanceManagerHelper,
36+
@Nullable String packagerPathForJSBundleName) {
37+
this(
38+
context.getApplicationContext(),
39+
reactInstanceManagerHelper,
40+
packagerPathForJSBundleName,
41+
true /* enableOnCreate */,
42+
null /* redBoxHandler */,
43+
null /* devBundleDownloadListener */,
44+
2 /* minNumShakes */,
45+
null /* customPackagerCommandHandlers */,
46+
null /* surfaceDelegateFactory */,
47+
null /* devLoadingViewManager */,
48+
null /* pausedInDebuggerOverlayManager */);
49+
}
50+
51+
/**
52+
* This constructor mirrors the same constructor we have for {@link BridgeDevSupportManager} and
53+
* is kept for backward compatibility.
54+
*/
55+
public BridgelessDevSupportManager(
56+
Context applicationContext,
57+
ReactInstanceDevHelper reactInstanceManagerHelper,
58+
@Nullable String packagerPathForJSBundleName,
59+
boolean enableOnCreate,
60+
@Nullable RedBoxHandler redBoxHandler,
61+
@Nullable DevBundleDownloadListener devBundleDownloadListener,
62+
int minNumShakes,
63+
@Nullable Map<String, RequestHandler> customPackagerCommandHandlers,
64+
@Nullable SurfaceDelegateFactory surfaceDelegateFactory,
65+
@Nullable DevLoadingViewManager devLoadingViewManager,
66+
@Nullable PausedInDebuggerOverlayManager pausedInDebuggerOverlayManager) {
67+
super(
68+
applicationContext,
69+
reactInstanceManagerHelper,
70+
packagerPathForJSBundleName,
71+
enableOnCreate,
72+
redBoxHandler,
73+
devBundleDownloadListener,
74+
minNumShakes,
75+
customPackagerCommandHandlers,
76+
surfaceDelegateFactory,
77+
devLoadingViewManager,
78+
pausedInDebuggerOverlayManager);
79+
}
80+
81+
@Override
82+
protected String getUniqueTag() {
83+
return "Bridgeless";
84+
}
85+
86+
@Override
87+
public void loadSplitBundleFromServer(
88+
final String bundlePath, final DevSplitBundleCallback callback) {
89+
fetchSplitBundleAndCreateBundleLoader(
90+
bundlePath,
91+
new CallbackWithBundleLoader() {
92+
@Override
93+
public void onSuccess(final JSBundleLoader bundleLoader) {
94+
try {
95+
mReactInstanceDevHelper.loadBundle(bundleLoader).waitForCompletion();
96+
String bundleURL = getDevServerHelper().getDevServerSplitBundleURL(bundlePath);
97+
ReactContext reactContext = mReactInstanceDevHelper.getCurrentReactContext();
98+
if (reactContext != null) {
99+
reactContext.getJSModule(HMRClient.class).registerBundle(bundleURL);
100+
}
101+
callback.onSuccess();
102+
} catch (InterruptedException e) {
103+
throw new RuntimeException(
104+
"[BridgelessDevSupportManager]: Got interrupted while loading bundle", e);
105+
}
106+
}
107+
108+
@Override
109+
public void onError(String url, Throwable cause) {
110+
callback.onError(url, cause);
111+
}
112+
});
113+
}
114+
115+
@Override
116+
public void handleReloadJS() {
117+
UiThreadUtil.assertOnUiThread();
118+
119+
// dismiss redbox if exists
120+
hideRedboxDialog();
121+
mReactInstanceDevHelper.reload("BridgelessDevSupportManager.handleReloadJS()");
122+
}
123+
}

packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/DefaultDevSupportManagerFactory.kt

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,8 @@ import com.facebook.react.packagerconnection.RequestHandler
1919
/**
2020
* A simple factory that creates instances of [DevSupportManager] implementations. Uses reflection
2121
* to create BridgeDevSupportManager if it exists. This allows ProGuard to strip that class and its
22-
* dependencies in release builds. If the class isn't found, [ ] is returned instead.
22+
* dependencies in release builds. If the class isn't found, [PerftestDevSupportManager] is returned
23+
* instead.
2324
*/
2425
public class DefaultDevSupportManagerFactory : DevSupportManagerFactory {
2526

@@ -85,6 +86,37 @@ public class DefaultDevSupportManagerFactory : DevSupportManagerFactory {
8586
}
8687
}
8788

89+
override fun create(
90+
applicationContext: Context,
91+
reactInstanceManagerHelper: ReactInstanceDevHelper,
92+
packagerPathForJSBundleName: String?,
93+
enableOnCreate: Boolean,
94+
redBoxHandler: RedBoxHandler?,
95+
devBundleDownloadListener: DevBundleDownloadListener?,
96+
minNumShakes: Int,
97+
customPackagerCommandHandlers: MutableMap<String, RequestHandler>?,
98+
surfaceDelegateFactory: SurfaceDelegateFactory?,
99+
devLoadingViewManager: DevLoadingViewManager?,
100+
pausedInDebuggerOverlayManager: PausedInDebuggerOverlayManager?,
101+
useDevSupport: Boolean
102+
): DevSupportManager =
103+
if (!useDevSupport) {
104+
ReleaseDevSupportManager()
105+
} else {
106+
BridgelessDevSupportManager(
107+
applicationContext,
108+
reactInstanceManagerHelper,
109+
packagerPathForJSBundleName,
110+
enableOnCreate,
111+
redBoxHandler,
112+
devBundleDownloadListener,
113+
minNumShakes,
114+
customPackagerCommandHandlers,
115+
surfaceDelegateFactory,
116+
devLoadingViewManager,
117+
pausedInDebuggerOverlayManager)
118+
}
119+
88120
private companion object {
89121
private const val DEVSUPPORT_IMPL_PACKAGE = "com.facebook.react.devsupport"
90122
private const val DEVSUPPORT_IMPL_CLASS = "BridgeDevSupportManager"

packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/DevSupportManagerBase.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ public interface CallbackWithBundleLoader {
9494
private final BroadcastReceiver mReloadAppBroadcastReceiver;
9595
private final DevServerHelper mDevServerHelper;
9696
private final LinkedHashMap<String, DevOptionHandler> mCustomDevOptions = new LinkedHashMap<>();
97-
private final ReactInstanceDevHelper mReactInstanceDevHelper;
97+
protected final ReactInstanceDevHelper mReactInstanceDevHelper;
9898
private final @Nullable String mJSAppBundleName;
9999
private final File mJSBundleDownloadedFile;
100100
private final File mJSSplitBundlesDir;

packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/DevSupportManagerFactory.java

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,10 @@
1919
import java.util.Map;
2020

2121
public interface DevSupportManagerFactory {
22+
/**
23+
* Factory used by the Old Architecture flow to create a {@link DevSupportManager} and a {@link
24+
* com.facebook.react.runtime.BridgeDevSupportManager}
25+
*/
2226
DevSupportManager create(
2327
Context applicationContext,
2428
ReactInstanceDevHelper reactInstanceManagerHelper,
@@ -31,4 +35,22 @@ DevSupportManager create(
3135
@Nullable SurfaceDelegateFactory surfaceDelegateFactory,
3236
@Nullable DevLoadingViewManager devLoadingViewManager,
3337
@Nullable PausedInDebuggerOverlayManager pausedInDebuggerOverlayManager);
38+
39+
/**
40+
* Factory used by the New Architecture/Bridgeless flow to create a {@link DevSupportManager} and
41+
* a {@link BridgelessDevSupportManager}
42+
*/
43+
DevSupportManager create(
44+
Context applicationContext,
45+
ReactInstanceDevHelper reactInstanceManagerHelper,
46+
@Nullable String packagerPathForJSBundleName,
47+
boolean enableOnCreate,
48+
@Nullable RedBoxHandler redBoxHandler,
49+
@Nullable DevBundleDownloadListener devBundleDownloadListener,
50+
int minNumShakes,
51+
@Nullable Map<String, RequestHandler> customPackagerCommandHandlers,
52+
@Nullable SurfaceDelegateFactory surfaceDelegateFactory,
53+
@Nullable DevLoadingViewManager devLoadingViewManager,
54+
@Nullable PausedInDebuggerOverlayManager pausedInDebuggerOverlayManager,
55+
boolean useDevSupport);
3456
}

packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/ReactInstanceDevHelper.java

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,16 @@
1010
import android.app.Activity;
1111
import android.view.View;
1212
import androidx.annotation.Nullable;
13+
import com.facebook.react.bridge.JSBundleLoader;
1314
import com.facebook.react.bridge.JavaJSExecutor;
1415
import com.facebook.react.bridge.JavaScriptExecutorFactory;
16+
import com.facebook.react.bridge.ReactContext;
17+
import com.facebook.react.interfaces.TaskInterface;
1518

1619
/**
1720
* Interface used by {@link DevSupportManager} for accessing some fields and methods of {@link
18-
* ReactInstanceManager} or {@link ReactHostImpl} for the purpose of displaying and handling
19-
* developer menu options.
21+
* ReactInstanceManager} or {@link ReactHost} for the purpose of displaying and handling developer
22+
* menu options.
2023
*/
2124
public interface ReactInstanceDevHelper {
2225

@@ -39,4 +42,11 @@ public interface ReactInstanceDevHelper {
3942
View createRootView(String appKey);
4043

4144
void destroyRootView(View rootView);
45+
46+
void reload(String s);
47+
48+
TaskInterface<Boolean> loadBundle(JSBundleLoader bundleLoader);
49+
50+
@Nullable
51+
ReactContext getCurrentReactContext();
4252
}

0 commit comments

Comments
 (0)