Nozbe / WatermelonDB

🍉 Reactive & asynchronous database for powerful React and React Native apps ⚡️
https://watermelondb.dev
MIT License
10.46k stars 587 forks source link

Bridgeless Mode support (New Architecture) [0.74] #1769

Open angelo-hub opened 5 months ago

angelo-hub commented 5 months ago

Bridgeless Mode is going to be default in 0.74 can offer some bandwidth to migrate to bridgeless mode as this is a super cool project

enahum commented 4 months ago

Have you been able to make it work even with the bridge on 74? On Android there is no longer getJSIModulePackage I cannot seem to find a solution to this yet.

enahum commented 4 months ago

@radex do you think you can take a look at this to solve the breaking change introduced by RN 74 ?

karengharibyan commented 3 months ago

+

hawadlu commented 3 months ago

@angelo-hub Any progress on this one?

yuyongmao commented 3 months ago

Have you been able to make it work even with the bridge on 74? On Android there is no longer getJSIModulePackage I cannot seem to find a solution to this yet.

@enahum Is there any progress on this issue? I have the same problem.

suman379 commented 2 months ago

@radex any plan for new arch?

LukasMod commented 1 month ago

@radex Can we get an answer in this thread? Are there any plans to restore the compatibility of the library with the latest version of react native (current 0.74.3)?

radex commented 1 month ago

Yes, sorry for staying quiet about it. Yes, I'm planning to work on this likely in August.

3210jr commented 1 month ago

Hey @radex - I am happy to help with chores and low hanging fruit re new architecture support. Not my area of expertise but if there is a pull request I will contribute

lucaswitch commented 1 month ago

Hey @radex - I am happy to help with chores and low hanging fruit re new architecture support. Not my area of expertise but if there is a pull request I will contribute

I'm happy to help too

juliesaia-vendora commented 2 weeks ago

I got it working on 0.74.5 (with bridge) with this patch, it reverts the deprecation and removes BridgelessCatalystInstance.kt.

It might be possible to do the same with 0.75, but it will be more difficult because there they actually removed the JSIModule stuff. I might try it later though

Be sure to enable building from source on Android (android/settings.gradle):

includeBuild('../node_modules/react-native') {
    dependencySubstitution {
        substitute(module("com.facebook.react:react-android")).using(project(":packages:react-native:ReactAndroid"))
        substitute(module("com.facebook.react:react-native")).using(project(":packages:react-native:ReactAndroid"))
        substitute(module("com.facebook.react:hermes-android")).using(project(":packages:react-native:ReactAndroid:hermes-engine"))
        substitute(module("com.facebook.react:hermes-engine")).using(project(":packages:react-native:ReactAndroid:hermes-engine"))
    }
}

The patch:

diff --git a/node_modules/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManager.java b/node_modules/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManager.java
index 7258ab9..6df97c6 100644
--- a/node_modules/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManager.java
+++ b/node_modules/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManager.java
@@ -55,6 +55,8 @@ import com.facebook.react.bridge.CatalystInstance;
 import com.facebook.react.bridge.CatalystInstanceImpl;
 import com.facebook.react.bridge.JSBundleLoader;
 import com.facebook.react.bridge.JSExceptionHandler;
+import com.facebook.react.bridge.JSIModulePackage;
+import com.facebook.react.bridge.JSIModuleType;
 import com.facebook.react.bridge.JavaJSExecutor;
 import com.facebook.react.bridge.JavaScriptExecutor;
 import com.facebook.react.bridge.JavaScriptExecutorFactory;
@@ -184,6 +186,7 @@ public class ReactInstanceManager {
   private volatile Boolean mHasStartedDestroying = false;
   private final MemoryPressureRouter mMemoryPressureRouter;
   private final @Nullable JSExceptionHandler mJSExceptionHandler;
+    private final @Nullable JSIModulePackage mJSIModulePackage;
   private final @Nullable UIManagerProvider mUIManagerProvider;
   private final @Nullable ReactPackageTurboModuleManagerDelegate.Builder mTMMDelegateBuilder;
   private List<ViewManager> mViewManagers;
@@ -232,6 +235,7 @@ public class ReactInstanceManager {
       @Nullable DevBundleDownloadListener devBundleDownloadListener,
       int minNumShakes,
       int minTimeLeftInFrameForNonBatchedOperationMs,
+      @Nullable JSIModulePackage jsiModulePackage,
       @Nullable UIManagerProvider uIManagerProvider,
       @Nullable Map<String, RequestHandler> customPackagerCommandHandlers,
       @Nullable ReactPackageTurboModuleManagerDelegate.Builder tmmDelegateBuilder,
@@ -292,6 +296,7 @@ public class ReactInstanceManager {
       }
       mPackages.addAll(packages);
     }
+    mJSIModulePackage = jsiModulePackage;
     mUIManagerProvider = uIManagerProvider;

     // Instantiate ReactChoreographer in UI thread.
@@ -1399,15 +1404,20 @@ public class ReactInstanceManager {
       }
     }

+    if (mJSIModulePackage != null) {
+      catalystInstance.addJSIModules(
+          mJSIModulePackage.getJSIModules(
+              reactContext, catalystInstance.getJavaScriptContextHolder()));
+    }
+
     if (mUIManagerProvider != null) {
       UIManager uiManager = mUIManagerProvider.createUIManager(reactContext);
       if (uiManager != null) {
-        catalystInstance.setFabricUIManager(uiManager);
-
-        // Initialize the UIManager
         uiManager.initialize();
         catalystInstance.setFabricUIManager(uiManager);
       }
+    } else if (ReactFeatureFlags.enableFabricRenderer) {
+    catalystInstance.getJSIModule(JSIModuleType.UIManager);
     }
     if (mBridgeIdleDebugListener != null) {
       catalystInstance.addBridgeIdleDebugListener(mBridgeIdleDebugListener);
diff --git a/node_modules/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManagerBuilder.java b/node_modules/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManagerBuilder.java
index d467ab9..3ae051f 100644
--- a/node_modules/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManagerBuilder.java
+++ b/node_modules/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManagerBuilder.java
@@ -20,6 +20,7 @@ import com.facebook.hermes.reactexecutor.HermesExecutorFactory;
 import com.facebook.infer.annotation.Assertions;
 import com.facebook.react.bridge.JSBundleLoader;
 import com.facebook.react.bridge.JSExceptionHandler;
+import com.facebook.react.bridge.JSIModulePackage;
 import com.facebook.react.bridge.JavaScriptExecutorFactory;
 import com.facebook.react.bridge.NotThreadSafeBridgeIdleDebugListener;
 import com.facebook.react.bridge.UIManagerProvider;
@@ -67,6 +68,7 @@ public class ReactInstanceManagerBuilder {
   private @Nullable JavaScriptExecutorFactory mJavaScriptExecutorFactory;
   private int mMinNumShakes = 1;
   private int mMinTimeLeftInFrameForNonBatchedOperationMs = -1;
+  private @Nullable JSIModulePackage mJSIModulesPackage;
   private @Nullable UIManagerProvider mUIManagerProvider;
   private @Nullable Map<String, RequestHandler> mCustomPackagerCommandHandlers;
   private @Nullable ReactPackageTurboModuleManagerDelegate.Builder mTMMDelegateBuilder;
@@ -77,6 +79,12 @@ public class ReactInstanceManagerBuilder {

   /* package protected */ ReactInstanceManagerBuilder() {}

+  public ReactInstanceManagerBuilder setJSIModulesPackage(
+      @Nullable JSIModulePackage jsiModulePackage) {
+    mJSIModulesPackage = jsiModulePackage;
+    return this;
+  }
+
   /** Factory for desired implementation of JavaScriptExecutor. */
   public ReactInstanceManagerBuilder setJavaScriptExecutorFactory(
       @Nullable JavaScriptExecutorFactory javaScriptExecutorFactory) {
@@ -353,6 +361,7 @@ public class ReactInstanceManagerBuilder {
         mDevBundleDownloadListener,
         mMinNumShakes,
         mMinTimeLeftInFrameForNonBatchedOperationMs,
+        mJSIModulesPackage,
         mUIManagerProvider,
         mCustomPackagerCommandHandlers,
         mTMMDelegateBuilder,
diff --git a/node_modules/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactNativeHost.java b/node_modules/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactNativeHost.java
index 6551937..3f1fb6f 100644
--- a/node_modules/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactNativeHost.java
+++ b/node_modules/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactNativeHost.java
@@ -10,6 +10,7 @@ package com.facebook.react;
 import android.app.Application;
 import androidx.annotation.Nullable;
 import com.facebook.infer.annotation.Assertions;
+import com.facebook.react.bridge.JSIModulePackage;
 import com.facebook.react.bridge.JavaScriptExecutorFactory;
 import com.facebook.react.bridge.ReactMarker;
 import com.facebook.react.bridge.ReactMarkerConstants;
@@ -84,6 +85,7 @@ public abstract class ReactNativeHost {
             .setLazyViewManagersEnabled(getLazyViewManagersEnabled())
             .setRedBoxHandler(getRedBoxHandler())
             .setJavaScriptExecutorFactory(getJavaScriptExecutorFactory())
+            .setJSIModulesPackage(getJSIModulePackage())
             .setUIManagerProvider(getUIManagerProvider())
             .setInitialLifecycleState(LifecycleState.BEFORE_CREATE)
             .setReactPackageTurboModuleManagerDelegateBuilder(
@@ -125,6 +127,10 @@ public abstract class ReactNativeHost {
     return mApplication;
   }

+  protected @Nullable JSIModulePackage getJSIModulePackage() {
+    return null;
+  }
+
   protected @Nullable UIManagerProvider getUIManagerProvider() {
     return reactApplicationContext -> null;
   }
diff --git a/node_modules/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/CatalystInstance.java b/node_modules/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/CatalystInstance.java
index b2e2d7c..0ee0dd6 100644
--- a/node_modules/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/CatalystInstance.java
+++ b/node_modules/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/CatalystInstance.java
@@ -120,7 +120,7 @@ public interface CatalystInstance
   RuntimeScheduler getRuntimeScheduler();

   @Deprecated
-  <T extends JSIModule> void addJSIModules(List<JSIModuleSpec<T>> jsiModules);
+  void addJSIModules(List<JSIModuleSpec> jsiModules);

   /**
    * Returns a hybrid object that contains a pointer to a JS CallInvoker, which is used to schedule
diff --git a/node_modules/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/CatalystInstanceImpl.java b/node_modules/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/CatalystInstanceImpl.java
index f86dffb..67e5e35 100644
--- a/node_modules/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/CatalystInstanceImpl.java
+++ b/node_modules/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/CatalystInstanceImpl.java
@@ -537,8 +537,7 @@ public class CatalystInstanceImpl implements CatalystInstance {
   public native RuntimeScheduler getRuntimeScheduler();

   @Override
-  @Deprecated
-  public <T extends JSIModule> void addJSIModules(List<JSIModuleSpec<T>> jsiModules) {
+  public void addJSIModules(List<JSIModuleSpec> jsiModules) {
     mJSIModuleRegistry.registerModules(jsiModules);
   }

diff --git a/node_modules/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/JSIModuleRegistry.java b/node_modules/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/JSIModuleRegistry.java
index 90d5cde..e81b361 100644
--- a/node_modules/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/JSIModuleRegistry.java
+++ b/node_modules/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/JSIModuleRegistry.java
@@ -26,8 +26,8 @@ class JSIModuleRegistry {
     return Assertions.assertNotNull(jsiModuleHolder.getJSIModule());
   }

-  public <T extends JSIModule> void registerModules(List<JSIModuleSpec<T>> jsiModules) {
-    for (JSIModuleSpec<T> spec : jsiModules) {
+  public void registerModules(List<JSIModuleSpec> jsiModules) {
+    for (JSIModuleSpec spec : jsiModules) {
       mModules.put(spec.getJSIModuleType(), new JSIModuleHolder(spec));
     }
   }
diff --git a/node_modules/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/BridgelessCatalystInstance.kt b/node_modules/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/BridgelessCatalystInstance.kt
deleted file mode 100644
index 03a18c6..0000000
--- a/node_modules/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/BridgelessCatalystInstance.kt
+++ /dev/null
@@ -1,194 +0,0 @@
-/*
- * 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.runtime
-
-import android.content.res.AssetManager
-import com.facebook.proguard.annotations.DoNotStrip
-import com.facebook.react.bridge.CatalystInstance
-import com.facebook.react.bridge.JSIModule
-import com.facebook.react.bridge.JSIModuleSpec
-import com.facebook.react.bridge.JSIModuleType
-import com.facebook.react.bridge.JavaScriptContextHolder
-import com.facebook.react.bridge.JavaScriptModule
-import com.facebook.react.bridge.NativeArray
-import com.facebook.react.bridge.NativeArrayInterface
-import com.facebook.react.bridge.NativeModule
-import com.facebook.react.bridge.NativeModuleRegistry
-import com.facebook.react.bridge.NotThreadSafeBridgeIdleDebugListener
-import com.facebook.react.bridge.RuntimeExecutor
-import com.facebook.react.bridge.RuntimeScheduler
-import com.facebook.react.bridge.UIManager
-import com.facebook.react.bridge.queue.ReactQueueConfiguration
-import com.facebook.react.common.annotations.DeprecatedInNewArchitecture
-import com.facebook.react.common.annotations.VisibleForTesting
-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
-
-@DoNotStrip
-@DeprecatedInNewArchitecture
-public class BridgelessCatalystInstance(private val reactHost: ReactHostImpl) : CatalystInstance {
-
-  override fun handleMemoryPressure(level: Int) {
-    throw UnsupportedOperationException("Unimplemented method 'handleMemoryPressure'")
-  }
-
-  override fun loadScriptFromAssets(
-      assetManager: AssetManager,
-      assetURL: String,
-      loadSynchronously: Boolean
-  ) {
-    throw UnsupportedOperationException("Unimplemented method 'loadScriptFromAssets'")
-  }
-
-  override fun loadScriptFromFile(fileName: String, sourceURL: String, loadSynchronously: Boolean) {
-    throw UnsupportedOperationException("Unimplemented method 'loadScriptFromFile'")
-  }
-
-  override fun loadSplitBundleFromFile(fileName: String, sourceURL: String) {
-    throw UnsupportedOperationException("Unimplemented method 'loadSplitBundleFromFile'")
-  }
-
-  override fun setSourceURLs(deviceURL: String, remoteURL: String) {
-    throw UnsupportedOperationException("Unimplemented method 'setSourceURLs'")
-  }
-
-  override fun runJSBundle() {
-    throw UnsupportedOperationException("Unimplemented method 'runJSBundle'")
-  }
-
-  override fun hasRunJSBundle(): Boolean {
-    throw UnsupportedOperationException("Unimplemented method 'hasRunJSBundle'")
-  }
-
-  override fun getSourceURL(): String? {
-    throw UnsupportedOperationException("Unimplemented method 'getSourceURL'")
-  }
-
-  @DoNotStrip
-  override fun invokeCallback(callbackID: Int, arguments: NativeArrayInterface) {
-    throw UnsupportedOperationException("Unimplemented method 'invokeCallback'")
-  }
-
-  override fun callFunction(module: String, method: String, arguments: NativeArray) {
-    throw UnsupportedOperationException("Unimplemented method 'callFunction'")
-  }
-
-  override fun destroy() {
-    throw UnsupportedOperationException("Unimplemented method 'destroy'")
-  }
-
-  override fun isDestroyed(): Boolean {
-    throw UnsupportedOperationException("Unimplemented method 'isDestroyed'")
-  }
-
-  @VisibleForTesting
-  override fun initialize() {
-    throw UnsupportedOperationException("Unimplemented method 'initialize'")
-  }
-
-  override fun getReactQueueConfiguration(): ReactQueueConfiguration =
-      reactHost.reactQueueConfiguration!!
-
-  override fun <T : JavaScriptModule> getJSModule(jsInterface: Class<T>): T =
-      reactHost.currentReactContext?.getJSModule(jsInterface)!!
-
-  override fun <T : NativeModule> hasNativeModule(nativeModuleInterface: Class<T>): Boolean =
-      reactHost.hasNativeModule(nativeModuleInterface)
-
-  override fun <T : NativeModule> getNativeModule(nativeModuleInterface: Class<T>): T? =
-      reactHost.getNativeModule(nativeModuleInterface)
-
-  override fun getNativeModule(moduleName: String): NativeModule? =
-      reactHost.getNativeModule(moduleName)
-
-  @Deprecated(
-      message =
-          "getJSIModule(JSIModuleType moduleType) is deprecated and will be deleted in the future. Please use ReactInstanceEventListener to subscribe for react instance events instead.")
-  override fun getJSIModule(moduleType: JSIModuleType): JSIModule {
-    throw UnsupportedOperationException("Unimplemented method 'getJSIModule'")
-  }
-
-  override fun getNativeModules(): Collection<NativeModule> = reactHost.getNativeModules()
-
-  override fun extendNativeModules(modules: NativeModuleRegistry) {
-    throw UnsupportedOperationException("Unimplemented method 'extendNativeModules'")
-  }
-
-  override fun addBridgeIdleDebugListener(listener: NotThreadSafeBridgeIdleDebugListener) {
-    throw UnsupportedOperationException("Unimplemented method 'addBridgeIdleDebugListener'")
-  }
-
-  override fun removeBridgeIdleDebugListener(listener: NotThreadSafeBridgeIdleDebugListener) {
-    throw UnsupportedOperationException("Unimplemented method 'removeBridgeIdleDebugListener'")
-  }
-
-  override fun registerSegment(segmentId: Int, path: String) {
-    throw UnsupportedOperationException("Unimplemented method 'registerSegment'")
-  }
-
-  @VisibleForTesting
-  override fun setGlobalVariable(propName: String, jsonValue: String) {
-    throw UnsupportedOperationException("Unimplemented method 'setGlobalVariable'")
-  }
-
-  @Deprecated(message = "This API is unsupported in the New Architecture.")
-  override fun getJavaScriptContextHolder(): JavaScriptContextHolder? {
-    return reactHost.getJavaScriptContextHolder()
-  }
-
-  override fun getRuntimeExecutor(): RuntimeExecutor? {
-    return reactHost.getRuntimeExecutor()
-  }
-
-  override fun getRuntimeScheduler(): RuntimeScheduler {
-    throw UnsupportedOperationException("Unimplemented method 'getRuntimeScheduler'")
-  }
-
-  @Deprecated(message = "This API is unsupported in the New Architecture.")
-  override fun <T : JSIModule> addJSIModules(jsiModules: List<JSIModuleSpec<T>>) {
-    throw UnsupportedOperationException("Unimplemented method 'addJSIModules'")
-  }
-
-  override fun getJSCallInvokerHolder(): CallInvokerHolder? {
-    return reactHost.getJSCallInvokerHolder()
-  }
-
-  override fun getNativeMethodCallInvokerHolder(): NativeMethodCallInvokerHolder {
-    throw UnsupportedOperationException("Unimplemented method 'getNativeMethodCallInvokerHolder'")
-  }
-
-  @Deprecated(
-      message =
-          "setTurboModuleManager(JSIModule getter) is deprecated and will be deleted in the future. Please use setTurboModuleRegistry(TurboModuleRegistry turboModuleRegistry) instead.",
-      replaceWith = ReplaceWith("setTurboModuleRegistry(turboModuleRegistry)"))
-  override fun setTurboModuleManager(getter: JSIModule) {
-    throw UnsupportedOperationException("Unimplemented method 'setTurboModuleManager'")
-  }
-
-  @DeprecatedInNewArchitecture(
-      message =
-          "This method will be deprecated later as part of Stable APIs with bridge removal and not encouraged usage.")
-  override fun setTurboModuleRegistry(turboModuleRegistry: TurboModuleRegistry) {
-    throw UnsupportedOperationException("Unimplemented method 'setTurboModuleRegistry'")
-  }
-
-  @DeprecatedInNewArchitecture(
-      message =
-          "This method will be deprecated later as part of Stable APIs with bridge removal and not encouraged usage.")
-  override fun setFabricUIManager(fabricUIManager: UIManager) {
-    throw UnsupportedOperationException("Unimplemented method 'setFabricUIManager'")
-  }
-
-  @DeprecatedInNewArchitecture(
-      message =
-          "This method will be deprecated later as part of Stable APIs with bridge removal and not encouraged usage.")
-  override fun getFabricUIManager(): UIManager {
-    throw UnsupportedOperationException("Unimplemented method 'getFabricUIManager'")
-  }
-}
diff --git a/node_modules/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/BridgelessReactContext.java b/node_modules/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/BridgelessReactContext.java
index d1cdaa9..24cc18a 100644
--- a/node_modules/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/BridgelessReactContext.java
+++ b/node_modules/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/BridgelessReactContext.java
@@ -81,14 +81,6 @@ class BridgelessReactContext extends ReactApplicationContext implements EventDis
     return mReactHost.getUIManager();
   }

-  @Override
-  public CatalystInstance getCatalystInstance() {
-    Log.w(
-        TAG,
-        "[WARNING] Bridgeless doesn't support CatalystInstance. Accessing an API that's not part of the new architecture is not encouraged usage.");
-    return new BridgelessCatalystInstance(mReactHost);
-  }
-
   @Override
   public boolean hasActiveReactInstance() {
     return mReactHost.isInstanceInitialized();

Really frustrating that the RN changelog mentions that this was unused in open source, idk how they missed this huge repo