diff --git a/ReactAndroid/src/main/java/com/facebook/react/BUCK b/ReactAndroid/src/main/java/com/facebook/react/BUCK index 8f2c72e8c..bab7db08b 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/BUCK @@ -37,6 +37,7 @@ rn_android_library( react_native_target("java/com/facebook/react/uimanager:uimanager"), react_native_target("java/com/facebook/react/module/annotations:annotations"), react_native_target("java/com/facebook/react/views/imagehelper:imagehelper"), + react_native_target("java/com/facebook/react/config:config"), ], exported_deps = [ react_native_target("java/com/facebook/react/packagerconnection:packagerconnection"), diff --git a/ReactAndroid/src/main/java/com/facebook/react/NativeModuleRegistryBuilder.java b/ReactAndroid/src/main/java/com/facebook/react/NativeModuleRegistryBuilder.java index 3bb541bf8..62f3f0c59 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/NativeModuleRegistryBuilder.java +++ b/ReactAndroid/src/main/java/com/facebook/react/NativeModuleRegistryBuilder.java @@ -8,6 +8,7 @@ package com.facebook.react; import com.facebook.react.bridge.ModuleHolder; import com.facebook.react.bridge.NativeModuleRegistry; import com.facebook.react.bridge.ReactApplicationContext; +import com.facebook.react.config.ReactFeatureFlags; import java.util.HashMap; import java.util.Map; @@ -55,6 +56,17 @@ public class NativeModuleRegistryBuilder { } mModules.remove(existingNativeModule); } + if (ReactFeatureFlags.useTurboModules && moduleHolder.isTurboModule()) { + // If this module is a TurboModule, and if TurboModules are enabled, don't add this module + + // This condition is after checking for overrides, since if there is already a module, + // and we want to override it with a turbo module, we would need to remove the modules thats + // already in the list, and then NOT add the new module, since that will be directly exposed + + // Note that is someone uses {@link NativeModuleRegistry#registerModules}, we will NOT check + // for TurboModules - assuming that people wanted to explicitly register native modules there + continue; + } mModules.put(name, moduleHolder); } } diff --git a/ReactAndroid/src/main/java/com/facebook/react/bridge/BUCK b/ReactAndroid/src/main/java/com/facebook/react/bridge/BUCK index af47db17a..2920a204e 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/bridge/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/bridge/BUCK @@ -43,6 +43,7 @@ rn_android_library( react_native_target("java/com/facebook/react/module/model:model"), react_native_target("java/com/facebook/react/uimanager/common:common"), react_native_target("java/com/facebook/react/module/annotations:annotations"), + react_native_target("java/com/facebook/react/turbomodule/core/interfaces:interfaces"), ] + ([react_native_target("jni/react/jni:jni")] if not IS_OSS_BUILD else []), exported_deps = [ react_native_dep("java/com/facebook/jni:jni"), diff --git a/ReactAndroid/src/main/java/com/facebook/react/bridge/ModuleHolder.java b/ReactAndroid/src/main/java/com/facebook/react/bridge/ModuleHolder.java index 175943530..e1299d525 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/bridge/ModuleHolder.java +++ b/ReactAndroid/src/main/java/com/facebook/react/bridge/ModuleHolder.java @@ -15,6 +15,7 @@ import com.facebook.debug.tags.ReactDebugOverlayTags; import com.facebook.infer.annotation.Assertions; import com.facebook.proguard.annotations.DoNotStrip; import com.facebook.react.module.model.ReactModuleInfo; +import com.facebook.react.turbomodule.core.interfaces.TurboModule; import com.facebook.systrace.SystraceMessage; import java.util.concurrent.atomic.AtomicInteger; import javax.annotation.Nullable; @@ -68,7 +69,9 @@ public class ModuleHolder { nativeModule.canOverrideExistingModule(), true, true, - CxxModuleWrapper.class.isAssignableFrom(nativeModule.getClass())); + CxxModuleWrapper.class.isAssignableFrom(nativeModule.getClass()), + TurboModule.class.isAssignableFrom(nativeModule.getClass()) + ); mModule = nativeModule; PrinterHolder.getPrinter() @@ -119,6 +122,10 @@ public class ModuleHolder { return mReactModuleInfo.hasConstants(); } + public boolean isTurboModule() { + return mReactModuleInfo.isTurboModule(); + } + public boolean isCxxModule() { return mReactModuleInfo.isCxxModule(); } diff --git a/ReactAndroid/src/main/java/com/facebook/react/config/ReactFeatureFlags.java b/ReactAndroid/src/main/java/com/facebook/react/config/ReactFeatureFlags.java index be48e96bc..1171fa909 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/config/ReactFeatureFlags.java +++ b/ReactAndroid/src/main/java/com/facebook/react/config/ReactFeatureFlags.java @@ -30,4 +30,11 @@ public class ReactFeatureFlags { * Reduce the number of Java-JS interops while accessing native maps */ public static boolean useMapNativeAccessor = false; + + /** + * Should this application use TurboModules. If yes, then any module that inherits + * {@link com.facebook.react.turbomodule.core.interfaces.TurboModule} will NOT be passed in to + * C++ CatalystInstanceImpl + */ + public static boolean useTurboModules = false; } diff --git a/ReactAndroid/src/main/java/com/facebook/react/module/model/ReactModuleInfo.java b/ReactAndroid/src/main/java/com/facebook/react/module/model/ReactModuleInfo.java index 198a6c589..9e2f1cd73 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/module/model/ReactModuleInfo.java +++ b/ReactAndroid/src/main/java/com/facebook/react/module/model/ReactModuleInfo.java @@ -17,6 +17,7 @@ public class ReactModuleInfo { private final boolean mHasConstants; private final boolean mIsCxxModule; private String mClassName; + private final boolean mIsTurboModule; public ReactModuleInfo( String name, @@ -24,13 +25,15 @@ public class ReactModuleInfo { boolean canOverrideExistingModule, boolean needsEagerInit, boolean hasConstants, - boolean isCxxModule) { + boolean isCxxModule, + boolean isTurboModule) { mName = name; mClassName = className; mCanOverrideExistingModule = canOverrideExistingModule; mNeedsEagerInit = needsEagerInit; mHasConstants = hasConstants; mIsCxxModule = isCxxModule; + mIsTurboModule = isTurboModule; } public String name() { @@ -53,4 +56,6 @@ public class ReactModuleInfo { public boolean isCxxModule() {return mIsCxxModule; } + public boolean isTurboModule() {return mIsTurboModule; } + } diff --git a/ReactAndroid/src/main/java/com/facebook/react/module/processing/BUCK b/ReactAndroid/src/main/java/com/facebook/react/module/processing/BUCK index 01c0dc0f7..663c17003 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/module/processing/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/module/processing/BUCK @@ -23,5 +23,6 @@ rn_java_library( react_native_dep("third-party/java/jsr-305:jsr-305"), react_native_target("java/com/facebook/react/module/annotations:annotations"), react_native_target("java/com/facebook/react/module/model:model"), + react_native_target("java/com/facebook/react/turbomodule/core/interfaces:interfaces"), ], ) diff --git a/ReactAndroid/src/main/java/com/facebook/react/module/processing/ReactModuleSpecProcessor.java b/ReactAndroid/src/main/java/com/facebook/react/module/processing/ReactModuleSpecProcessor.java index 65bcb3d09..cf0c30b11 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/module/processing/ReactModuleSpecProcessor.java +++ b/ReactAndroid/src/main/java/com/facebook/react/module/processing/ReactModuleSpecProcessor.java @@ -13,6 +13,7 @@ import com.facebook.react.module.annotations.ReactModule; import com.facebook.react.module.annotations.ReactModuleList; import com.facebook.react.module.model.ReactModuleInfo; import com.facebook.react.module.model.ReactModuleInfoProvider; +import com.facebook.react.turbomodule.core.interfaces.TurboModule; import com.squareup.javapoet.ClassName; import com.squareup.javapoet.CodeBlock; import com.squareup.javapoet.JavaFile; @@ -26,6 +27,7 @@ import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Optional; import java.util.Set; import javax.annotation.processing.AbstractProcessor; import javax.annotation.processing.Filer; @@ -147,7 +149,7 @@ public class ReactModuleSpecProcessor extends AbstractProcessor { private CodeBlock getCodeBlockForReactModuleInfos(List nativeModules) throws ReactModuleSpecException { - CodeBlock.Builder builder = CodeBlock.builder(); + final CodeBlock.Builder builder = CodeBlock.builder(); if (nativeModules == null || nativeModules.isEmpty()) { builder.addStatement("return $T.emptyMap()", COLLECTIONS_TYPE); } else { @@ -170,6 +172,12 @@ public class ReactModuleSpecProcessor extends AbstractProcessor { "Did you forget to add the @ReactModule annotation to the native module?"); } + boolean isTurboModule = isTurboModuleTypeElement(typeElement); + if (!isTurboModule) { + TypeMirror nativeModuleSpecTypeMirror = typeElement.getSuperclass(); + isTurboModule = isTurboModuleTypeElement(mElements.getTypeElement(nativeModuleSpecTypeMirror.toString())); + } + List elements = typeElement.getEnclosedElements(); boolean hasConstants = false; if (elements != null) { @@ -189,7 +197,8 @@ public class ReactModuleSpecProcessor extends AbstractProcessor { .append(reactModule.canOverrideExistingModule()).append(", ") .append(reactModule.needsEagerInit()).append(", ") .append(hasConstants).append(", ") - .append(reactModule.isCxxModule()) + .append(reactModule.isCxxModule()).append(", ") + .append(isTurboModule) .append(")") .toString(); @@ -200,6 +209,17 @@ public class ReactModuleSpecProcessor extends AbstractProcessor { return builder.build(); } + /** + * A Module is a Turbo Module if it either implements TurboModule or its super class, + * typically NativeModuleSpec implements TurboMobile + */ + private boolean isTurboModuleTypeElement(TypeElement typeElement) { + if (typeElement == null) { + return false; + } + return typeElement.getInterfaces().stream().anyMatch(el -> el.toString().equals(TurboModule.class.getName())); + } + private static class ReactModuleSpecException extends Exception { public final String mMessage;