Convert com.facebook.react.BaseReactPackage to Kotlin (#47679)

Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/47679

Changelog: [Internal]

Reviewed By: mdvacca

Differential Revision: D66119659

fbshipit-source-id: d7917aa09edac6d5a8c07635d294de229723f0c9
This commit is contained in:
Pieter De Baets 2024-11-20 04:05:26 -08:00 committed by Facebook GitHub Bot
parent ba1bc639b8
commit 09b08aa4e0
3 changed files with 132 additions and 160 deletions

View File

@ -28,7 +28,7 @@ public class PopupMenuPackage() : BaseReactPackage(), ViewManagerOnDemandReactPa
return null
}
protected override fun getViewManagers(context: ReactApplicationContext): List<ModuleSpec> {
protected override fun getViewManagers(reactContext: ReactApplicationContext): List<ModuleSpec> {
return viewManagersMap.values.toList()
}

View File

@ -1,159 +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;
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.internal.featureflags.ReactNativeFeatureFlags;
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<NativeModule> 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<ModuleHolder> getNativeModuleIterator(final ReactApplicationContext reactContext) {
final Set<Map.Entry<String, ReactModuleInfo>> entrySet =
getReactModuleInfoProvider().getReactModuleInfos().entrySet();
final Iterator<Map.Entry<String, ReactModuleInfo>> entrySetIterator = entrySet.iterator();
// This should ideally be an IteratorConvertor, but we don't have any internal library for it
return () ->
new Iterator<ModuleHolder>() {
@Nullable Map.Entry<String, ReactModuleInfo> nextEntry = null;
private void findNext() {
while (entrySetIterator.hasNext()) {
Map.Entry<String, ReactModuleInfo> 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 (ReactNativeFeatureFlags.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<String, ReactModuleInfo> 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<ModuleSpec> getViewManagers(ReactApplicationContext reactContext) {
return Collections.emptyList();
}
@Override
public List<ViewManager> createViewManagers(@NonNull ReactApplicationContext reactContext) {
List<ModuleSpec> viewManagerModuleSpecs = getViewManagers(reactContext);
if (viewManagerModuleSpecs == null || viewManagerModuleSpecs.isEmpty()) {
return Collections.emptyList();
}
List<ViewManager> viewManagers = new ArrayList<>();
for (ModuleSpec moduleSpec : viewManagerModuleSpecs) {
viewManagers.add((ViewManager) moduleSpec.getProvider().get());
}
return viewManagers;
}
public abstract ReactModuleInfoProvider getReactModuleInfoProvider();
private class ModuleHolderProvider implements Provider<NativeModule> {
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);
}
}
}

View File

@ -0,0 +1,131 @@
/*
* 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 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.internal.featureflags.ReactNativeFeatureFlags
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.NoSuchElementException
import javax.inject.Provider
/** Abstract class that supports lazy loading of NativeModules by default. */
public abstract class BaseReactPackage : ReactPackage {
override fun createNativeModules(reactContext: ReactApplicationContext): List<NativeModule> {
throw UnsupportedOperationException(
"createNativeModules method is not supported. Use getModule() method instead.")
}
/**
* The API needed for TurboModules. Given a module name, it returns an instance of [NativeModule]
* for the name
*
* @param name name of the Native Module
* @param reactContext [ReactApplicationContext] context for this
*/
abstract override fun getModule(
name: String,
reactContext: ReactApplicationContext
): NativeModule?
/**
* This is a temporary method till we implement TurboModules. Once we implement TurboModules, we
* will be able to directly call [BaseReactPackage#getModule(String, ReactApplicationContext)]
* This method will be removed when TurboModule implementation is complete
*
* @param reactContext [ReactApplicationContext]
* @return
*/
internal fun getNativeModuleIterator(
reactContext: ReactApplicationContext
): Iterable<ModuleHolder> {
val entrySet = getReactModuleInfoProvider().getReactModuleInfos().entries
val entrySetIterator = entrySet.iterator()
// This should ideally be an IteratorConvertor, but we don't have any internal library for it
return Iterable {
object : Iterator<ModuleHolder> {
var nextEntry: Map.Entry<String, ReactModuleInfo>? = null
private fun findNext() {
while (entrySetIterator.hasNext()) {
val entry = entrySetIterator.next()
val reactModuleInfo = entry.value
// 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 (ReactNativeFeatureFlags.useTurboModules() && reactModuleInfo.isTurboModule) {
continue
}
nextEntry = entry
return
}
nextEntry = null
}
override fun hasNext(): Boolean {
if (nextEntry == null) {
findNext()
}
return nextEntry != null
}
override fun next(): ModuleHolder {
if (nextEntry == null) {
findNext()
}
val entry = nextEntry ?: throw NoSuchElementException("ModuleHolder not found")
// Advance iterator
findNext()
return ModuleHolder(entry.value, ModuleHolderProvider(entry.key, reactContext))
}
}
}
}
/**
* @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 open fun getViewManagers(reactContext: ReactApplicationContext): List<ModuleSpec> =
emptyList()
override fun createViewManagers(
reactContext: ReactApplicationContext
): List<ViewManager<in Nothing, in Nothing>> {
val viewManagerModuleSpecs = getViewManagers(reactContext)
if (viewManagerModuleSpecs.isNullOrEmpty()) {
return emptyList()
}
val viewManagers: MutableList<ViewManager<*, *>> = ArrayList()
for (moduleSpec in viewManagerModuleSpecs) {
viewManagers.add((moduleSpec.provider.get() as ViewManager<*, *>))
}
return viewManagers
}
public abstract fun getReactModuleInfoProvider(): ReactModuleInfoProvider
private inner class ModuleHolderProvider(
private val name: String,
private val reactContext: ReactApplicationContext
) : Provider<NativeModule?> {
override fun get(): NativeModule? = getModule(name, reactContext)
}
}