From 185bc248e434a3fdb0e617a594ced2e5194b7115 Mon Sep 17 00:00:00 2001 From: Ramanpreet Nara Date: Tue, 28 Mar 2023 09:11:56 -0700 Subject: [PATCH] Finish the Java-facing side of the TurboModule interop layer (#36627) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/36627 ## Changes Now, when you call TurboModuleManager.getModule(interopModuleName), the TurboModuleManager will create and return that interop module to you. Changes in this diff: 1. Forward interop NativeModules from app's ReactPackages to the TurboModuleManager 2. Extend TurboModule system's module creation algorithm to create interop NativeModules. ## Details TurboModuleManagerDelegate's capabilities: ||API| Without Interop | With Interop | |same|getModule()|Java [NativeModule](https://www.internalfb.com/code/fbsource/[e5db2a0dc412f0656f7eeec1db9d2da4aab61f40]/xplat/js/react-native-github/ReactAndroid/src/main/java/com/facebook/react/bridge/NativeModule.java?lines=21) that also implements [TurboModule](https://www.internalfb.com/code/fbsource/[c7089c1408eda109f342a1f33252533e743614ed]/xplat/js/react-native-github/ReactAndroid/src/main/java/com/facebook/react/turbomodule/core/interfaces/TurboModule.java?lines=11) |Java [NativeModule](https://www.internalfb.com/code/fbsource/[e5db2a0dc412f0656f7eeec1db9d2da4aab61f40]/xplat/js/react-native-github/ReactAndroid/src/main/java/com/facebook/react/bridge/NativeModule.java?lines=21) that also implements [TurboModule](https://www.internalfb.com/code/fbsource/[c7089c1408eda109f342a1f33252533e743614ed]/xplat/js/react-native-github/ReactAndroid/src/main/java/com/facebook/react/turbomodule/core/interfaces/TurboModule.java?lines=11) | |new|getLegacyModule()| |Java [NativeModule](https://www.internalfb.com/code/fbsource/[e5db2a0dc412f0656f7eeec1db9d2da4aab61f40]/xplat/js/react-native-github/ReactAndroid/src/main/java/com/facebook/react/bridge/NativeModule.java?lines=21) that **doesn't** implement [TurboModule](https://www.internalfb.com/code/fbsource/[c7089c1408eda109f342a1f33252533e743614ed]/xplat/js/react-native-github/ReactAndroid/src/main/java/com/facebook/react/turbomodule/core/interfaces/TurboModule.java?lines=11)| Changelog: [Internal] Reviewed By: cortinico Differential Revision: D43751055 fbshipit-source-id: 75afb6f836b8ec270bb916525ff2fc9030d34012 --- ...eactPackageTurboModuleManagerDelegate.java | 53 +++++++++++++++++-- .../turbomodule/core/TurboModuleManager.java | 31 +++++++++++ .../core/TurboModuleManagerDelegate.java | 10 ++++ 3 files changed, 91 insertions(+), 3 deletions(-) diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactPackageTurboModuleManagerDelegate.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactPackageTurboModuleManagerDelegate.java index a8a197a11fb..a7a23911199 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactPackageTurboModuleManagerDelegate.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactPackageTurboModuleManagerDelegate.java @@ -39,6 +39,11 @@ public abstract class ReactPackageTurboModuleManagerDelegate extends TurboModule && ReactFeatureFlags.unstable_useTurboModuleInterop; } + private static boolean shouldCreateLegacyModules() { + return ReactFeatureFlags.enableBridgelessArchitecture + && ReactFeatureFlags.unstable_useTurboModuleInterop; + } + protected ReactPackageTurboModuleManagerDelegate( ReactApplicationContext reactApplicationContext, List packages) { super(); @@ -147,6 +152,7 @@ public abstract class ReactPackageTurboModuleManagerDelegate extends TurboModule try { final ReactModuleInfo moduleInfo = mPackageModuleInfos.get(moduleProvider).get(moduleName); if (moduleInfo == null + // Skip TurboModule-incompatible modules || !moduleInfo.isTurboModule() || resolvedModule != null && !moduleInfo.canOverrideExistingModule()) { continue; @@ -165,11 +171,52 @@ public abstract class ReactPackageTurboModuleManagerDelegate extends TurboModule } } - if (resolvedModule instanceof TurboModule) { - return (TurboModule) resolvedModule; + // Skip TurboModule-incompatible modules + if (!(resolvedModule instanceof TurboModule)) { + return null; } - return null; + return (TurboModule) resolvedModule; + } + + @Nullable + @Override + public NativeModule getLegacyModule(String moduleName) { + if (!shouldCreateLegacyModules()) { + return null; + } + + NativeModule resolvedModule = null; + + for (final ModuleProvider moduleProvider : mModuleProviders) { + try { + final ReactModuleInfo moduleInfo = mPackageModuleInfos.get(moduleProvider).get(moduleName); + if (moduleInfo == null + // Skip TurboModule-compatible modules + || moduleInfo.isTurboModule() + || resolvedModule != null && !moduleInfo.canOverrideExistingModule()) { + continue; + } + + final NativeModule module = moduleProvider.getModule(moduleName); + if (module != null) { + resolvedModule = module; + } + } catch (IllegalArgumentException ex) { + /** + * TurboReactPackages can throw an IllegalArgumentException when a module isn't found. If + * this happens, it's safe to ignore the exception because a later TurboReactPackage could + * provide the module. + */ + } + } + + // Skip TurboModule-compatible modules + if (resolvedModule instanceof TurboModule) { + return null; + } + + return resolvedModule; } @Deprecated diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/turbomodule/core/TurboModuleManager.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/turbomodule/core/TurboModuleManager.java index e385f26e579..262835b0255 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/turbomodule/core/TurboModuleManager.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/turbomodule/core/TurboModuleManager.java @@ -17,6 +17,7 @@ import com.facebook.react.bridge.CxxModuleWrapper; import com.facebook.react.bridge.JSIModule; import com.facebook.react.bridge.NativeModule; import com.facebook.react.bridge.RuntimeExecutor; +import com.facebook.react.config.ReactFeatureFlags; import com.facebook.react.turbomodule.core.interfaces.CallInvokerHolder; import com.facebook.react.turbomodule.core.interfaces.TurboModule; import com.facebook.react.turbomodule.core.interfaces.TurboModuleRegistry; @@ -32,6 +33,7 @@ public class TurboModuleManager implements JSIModule, TurboModuleRegistry { private static volatile boolean sIsSoLibraryLoaded; private final List mEagerInitModuleNames; private final ModuleProvider mModuleProvider; + private final ModuleProvider mLegacyModuleProvider; // Prevents the creation of new TurboModules once cleanup as been initiated. private final Object mModuleCleanupLock = new Object(); @@ -87,6 +89,31 @@ public class TurboModuleManager implements JSIModule, TurboModuleRegistry { return module; } }; + + mLegacyModuleProvider = + new ModuleProvider() { + @Nullable + public NativeModule getModule(String moduleName) { + if (delegate == null || !shouldCreateLegacyModules()) { + return null; + } + + NativeModule nativeModule = delegate.getLegacyModule(moduleName); + if (nativeModule != null) { + // TurboModuleManagerDelegate.getLegacyModule must never return a TurboModule + Assertions.assertCondition( + !(nativeModule instanceof TurboModule), + "NativeModule \"" + moduleName + "\" is a TurboModule"); + return nativeModule; + } + return nativeModule; + } + }; + } + + private static boolean shouldCreateLegacyModules() { + return ReactFeatureFlags.enableBridgelessArchitecture + && ReactFeatureFlags.unstable_useTurboModuleInterop; } public List getEagerInitModuleNames() { @@ -187,6 +214,10 @@ public class TurboModuleManager implements JSIModule, TurboModuleRegistry { TurboModulePerfLogger.moduleCreateConstructStart(moduleName, moduleHolder.getModuleId()); NativeModule nativeModule = (NativeModule) mModuleProvider.getModule(moduleName); + if (nativeModule == null) { + nativeModule = mLegacyModuleProvider.getModule(moduleName); + } + TurboModulePerfLogger.moduleCreateConstructEnd(moduleName, moduleHolder.getModuleId()); TurboModulePerfLogger.moduleCreateSetUpStart(moduleName, moduleHolder.getModuleId()); diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/turbomodule/core/TurboModuleManagerDelegate.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/turbomodule/core/TurboModuleManagerDelegate.java index deef3b9206a..0a55f1faf9e 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/turbomodule/core/TurboModuleManagerDelegate.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/turbomodule/core/TurboModuleManagerDelegate.java @@ -11,6 +11,7 @@ import androidx.annotation.Nullable; import com.facebook.jni.HybridData; import com.facebook.proguard.annotations.DoNotStrip; import com.facebook.react.bridge.CxxModuleWrapper; +import com.facebook.react.bridge.NativeModule; import com.facebook.react.turbomodule.core.interfaces.TurboModule; import com.facebook.soloader.SoLoader; import java.util.ArrayList; @@ -48,6 +49,15 @@ public abstract class TurboModuleManagerDelegate { @Nullable public abstract CxxModuleWrapper getLegacyCxxModule(String moduleName); + /** + * Create an return a legacy NativeModule with name `moduleName`. If `moduleName` is a + * TurboModule, return null. + */ + @Nullable + public NativeModule getLegacyModule(String moduleName) { + return null; + } + public List getEagerInitModuleNames() { return new ArrayList<>(); }