From 7a31ecd6653f673edca2e9bfd01b9059bfe3d869 Mon Sep 17 00:00:00 2001 From: David Vacca Date: Tue, 10 Oct 2023 15:43:48 -0700 Subject: [PATCH] Introduce BaseReactPackage class (#40775) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/40775 In this diff I'm introducing the BaseReactPackage class to the public API of React Native Android. the goal is for this class to replace TurboReactPackage, which will be Deprecated in the New Architecture changelog: [internal] internal Reviewed By: christophpurrer Differential Revision: D50128456 fbshipit-source-id: a65e1eb0d81b94e442799226784f73f489eabb73 --- .../com/facebook/react/BaseReactPackage.java | 159 ++++++++++++++++++ .../com/facebook/react/TurboReactPackage.java | 151 +---------------- 2 files changed, 162 insertions(+), 148 deletions(-) create mode 100644 packages/react-native/ReactAndroid/src/main/java/com/facebook/react/BaseReactPackage.java diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/BaseReactPackage.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/BaseReactPackage.java new file mode 100644 index 00000000000..0a606e0c65f --- /dev/null +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/BaseReactPackage.java @@ -0,0 +1,159 @@ +/* + * 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; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import com.facebook.react.bridge.ModuleHolder; +import com.facebook.react.bridge.ModuleSpec; +import com.facebook.react.bridge.NativeModule; +import com.facebook.react.bridge.ReactApplicationContext; +import com.facebook.react.config.ReactFeatureFlags; +import com.facebook.react.module.model.ReactModuleInfo; +import com.facebook.react.module.model.ReactModuleInfoProvider; +import com.facebook.react.uimanager.ViewManager; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.NoSuchElementException; +import java.util.Set; +import javax.inject.Provider; + +/** Abstract class that supports lazy loading of NativeModules by default. */ +public abstract class BaseReactPackage implements ReactPackage { + + @Override + public List createNativeModules(@NonNull ReactApplicationContext reactContext) { + throw new UnsupportedOperationException( + "createNativeModules method is not supported. Use getModule() method instead."); + } + + /** + * The API needed for TurboModules. Given a module name, it returns an instance of {@link + * NativeModule} for the name + * + * @param name name of the Native Module + * @param reactContext {@link ReactApplicationContext} context for this + */ + @Override + public abstract @Nullable NativeModule getModule( + @NonNull String name, @NonNull ReactApplicationContext reactContext); + + /** + * This is a temporary method till we implement TurboModules. Once we implement TurboModules, we + * will be able to directly call {@link BaseReactPackage#getModule(String, + * ReactApplicationContext)} This method will be removed when TurboModule implementation is + * complete + * + * @param reactContext + * @return + */ + /** package */ + Iterable getNativeModuleIterator(final ReactApplicationContext reactContext) { + final Set> entrySet = + getReactModuleInfoProvider().getReactModuleInfos().entrySet(); + final Iterator> entrySetIterator = entrySet.iterator(); + // This should ideally be an IteratorConvertor, but we don't have any internal library for it + return () -> + new Iterator() { + @Nullable Map.Entry nextEntry = null; + + private void findNext() { + while (entrySetIterator.hasNext()) { + Map.Entry entry = entrySetIterator.next(); + ReactModuleInfo reactModuleInfo = entry.getValue(); + + // This Iterator is used to create the NativeModule registry. The NativeModule + // registry must not have TurboModules. Therefore, if TurboModules are enabled, and + // the current NativeModule is a TurboModule, we need to skip iterating over it. + if (ReactFeatureFlags.useTurboModules && reactModuleInfo.isTurboModule()) { + continue; + } + + nextEntry = entry; + return; + } + nextEntry = null; + } + + @Override + public boolean hasNext() { + if (nextEntry == null) { + findNext(); + } + return nextEntry != null; + } + + @Override + public ModuleHolder next() { + if (nextEntry == null) { + findNext(); + } + + if (nextEntry == null) { + throw new NoSuchElementException("ModuleHolder not found"); + } + + Map.Entry entry = nextEntry; + + // Advance iterator + findNext(); + String name = entry.getKey(); + ReactModuleInfo reactModuleInfo = entry.getValue(); + return new ModuleHolder(reactModuleInfo, new ModuleHolderProvider(name, reactContext)); + } + + @Override + public void remove() { + throw new UnsupportedOperationException("Cannot remove native modules from the list"); + } + }; + } + + /** + * @param reactContext react application context that can be used to create View Managers. + * @return list of module specs that can create the View Managers. + */ + protected List getViewManagers(ReactApplicationContext reactContext) { + return Collections.emptyList(); + } + + @Override + public List createViewManagers(@NonNull ReactApplicationContext reactContext) { + List viewManagerModuleSpecs = getViewManagers(reactContext); + if (viewManagerModuleSpecs == null || viewManagerModuleSpecs.isEmpty()) { + return Collections.emptyList(); + } + + List viewManagers = new ArrayList<>(); + for (ModuleSpec moduleSpec : viewManagerModuleSpecs) { + viewManagers.add((ViewManager) moduleSpec.getProvider().get()); + } + return viewManagers; + } + + public abstract ReactModuleInfoProvider getReactModuleInfoProvider(); + + private class ModuleHolderProvider implements Provider { + + private final String mName; + private final ReactApplicationContext mReactContext; + + public ModuleHolderProvider(String name, ReactApplicationContext reactContext) { + mName = name; + mReactContext = reactContext; + } + + @Override + public @Nullable NativeModule get() { + return getModule(mName, mReactContext); + } + } +} diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/TurboReactPackage.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/TurboReactPackage.java index 8d09923ddd2..c8f5ea9d24d 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/TurboReactPackage.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/TurboReactPackage.java @@ -7,153 +7,8 @@ package com.facebook.react; -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import com.facebook.react.bridge.ModuleHolder; -import com.facebook.react.bridge.ModuleSpec; -import com.facebook.react.bridge.NativeModule; -import com.facebook.react.bridge.ReactApplicationContext; -import com.facebook.react.config.ReactFeatureFlags; -import com.facebook.react.module.model.ReactModuleInfo; -import com.facebook.react.module.model.ReactModuleInfoProvider; -import com.facebook.react.uimanager.ViewManager; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.NoSuchElementException; -import java.util.Set; -import javax.inject.Provider; +import com.facebook.react.common.annotations.DeprecatedInNewArchitecture; /** This will eventually replace {@link LazyReactPackage} when TurboModules are finally done. */ -public abstract class TurboReactPackage implements ReactPackage { - - @Override - public List createNativeModules(ReactApplicationContext reactContext) { - throw new UnsupportedOperationException( - "createNativeModules method is not supported. Use getModule() method instead."); - } - - /** - * The API needed for TurboModules. Given a module name, it returns an instance of {@link - * NativeModule} for the name - * - * @param name name of the Native Module - * @param reactContext {@link ReactApplicationContext} context for this - */ - @Override - public abstract @Nullable NativeModule getModule( - @NonNull String name, @NonNull ReactApplicationContext reactContext); - - /** - * This is a temporary method till we implement TurboModules. Once we implement TurboModules, we - * will be able to directly call {@link TurboReactPackage#getModule(String, - * ReactApplicationContext)} This method will be removed when TurboModule implementation is - * complete - * - * @param reactContext - * @return - */ - /** package */ - Iterable getNativeModuleIterator(final ReactApplicationContext reactContext) { - final Set> entrySet = - getReactModuleInfoProvider().getReactModuleInfos().entrySet(); - final Iterator> entrySetIterator = entrySet.iterator(); - // This should ideally be an IteratorConvertor, but we don't have any internal library for it - return () -> - new Iterator() { - @Nullable Map.Entry nextEntry = null; - - private void findNext() { - while (entrySetIterator.hasNext()) { - Map.Entry entry = entrySetIterator.next(); - ReactModuleInfo reactModuleInfo = entry.getValue(); - - // This Iterator is used to create the NativeModule registry. The NativeModule - // registry must not have TurboModules. Therefore, if TurboModules are enabled, and - // the current NativeModule is a TurboModule, we need to skip iterating over it. - if (ReactFeatureFlags.useTurboModules && reactModuleInfo.isTurboModule()) { - continue; - } - - nextEntry = entry; - return; - } - nextEntry = null; - } - - @Override - public boolean hasNext() { - if (nextEntry == null) { - findNext(); - } - return nextEntry != null; - } - - @Override - public ModuleHolder next() { - if (nextEntry == null) { - findNext(); - } - - if (nextEntry == null) { - throw new NoSuchElementException("ModuleHolder not found"); - } - - Map.Entry entry = nextEntry; - - // Advance iterator - findNext(); - String name = entry.getKey(); - ReactModuleInfo reactModuleInfo = entry.getValue(); - return new ModuleHolder(reactModuleInfo, new ModuleHolderProvider(name, reactContext)); - } - - @Override - public void remove() { - throw new UnsupportedOperationException("Cannot remove native modules from the list"); - } - }; - } - - /** - * @param reactContext react application context that can be used to create View Managers. - * @return list of module specs that can create the View Managers. - */ - protected List getViewManagers(ReactApplicationContext reactContext) { - return Collections.emptyList(); - } - - @Override - public List createViewManagers(ReactApplicationContext reactContext) { - List viewManagerModuleSpecs = getViewManagers(reactContext); - if (viewManagerModuleSpecs == null || viewManagerModuleSpecs.isEmpty()) { - return Collections.emptyList(); - } - - List viewManagers = new ArrayList<>(); - for (ModuleSpec moduleSpec : viewManagerModuleSpecs) { - viewManagers.add((ViewManager) moduleSpec.getProvider().get()); - } - return viewManagers; - } - - public abstract ReactModuleInfoProvider getReactModuleInfoProvider(); - - private class ModuleHolderProvider implements Provider { - - private final String mName; - private final ReactApplicationContext mReactContext; - - public ModuleHolderProvider(String name, ReactApplicationContext reactContext) { - mName = name; - mReactContext = reactContext; - } - - @Override - public NativeModule get() { - return getModule(mName, mReactContext); - } - } -} +@DeprecatedInNewArchitecture(message = "Use BaseReactPackage instead") +public abstract class TurboReactPackage extends BaseReactPackage {}