mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
Introduce ReactPackageTurboModuleManagerDelegate
Summary: ## Summary People use `ReactPackage` instances to create NativeModules. To make the migration from NativeModule to TurboModule easy, I'm introducing a `TurboModuleManagerDelegate` that understands `ReactPackage`s, and uses them to lookup and create the Java TurboModule objects. This way, we don't have to change the way we declare NativeModules for the migration. ## TurboModule registration Each application should have its own subclass of `ReactPackageTurboModuleManagerDelegate`. This subclass is a hybrid class with a C++ and a Java part. The Java part can (and probably should) do nothing (for now). The C++ part has to implement the `moduleName -> jni::HostObject` and `moduleName, javaInstance -> jni::HostObject` functions for all TurboModules in the application. **Use Case: Migrating a NativeModule to TurboModule system** 1. Make the Java NativeModule extend `TurboModule`. (The reason why this doesn't happen automatically is probably because we haven't changed the Java codegen yet). 2. Modify the `moduleName -> jni::HostObject` or `moduleName, javaInstance -> jni::HostObject` functions to return the `TurboModule`. **Use Case: Adding a new TurboModule** 1. Add the TurboModule to a `ReactPackage` in the application. 2. Modify the `moduleName -> jni::HostObject` or `moduleName, javaInstance -> jni::HostObject` functions to return the TurboModule `jsi::HostObject`. **Note:** It's also possible to declare TurboModules by overriding the `getModule(String moduleName)` function of `ReactPackageTurboModuleManagerDelegate`. It's not a good idea, because it'll make switching between the NativeModule/TurboModule system difficult. Reviewed By: mdvacca Differential Revision: D15209129 fbshipit-source-id: 4b0a303595145be9b19d6f4934f956b91990f859
This commit is contained in:
committed by
Facebook Github Bot
parent
12c0ec85f7
commit
08d87cdacc
@@ -76,8 +76,7 @@ public abstract class LazyReactPackage implements ReactPackage {
|
||||
* @param reactContext
|
||||
* @return
|
||||
*/
|
||||
/* package */
|
||||
Iterable<ModuleHolder> getNativeModuleIterator(final ReactApplicationContext reactContext) {
|
||||
public Iterable<ModuleHolder> getNativeModuleIterator(final ReactApplicationContext reactContext) {
|
||||
final Map<String, ReactModuleInfo> reactModuleInfoMap =
|
||||
getReactModuleInfoProvider().getReactModuleInfos();
|
||||
final List<ModuleSpec> nativeModules = getNativeModules(reactContext);
|
||||
|
||||
@@ -307,6 +307,10 @@ public class ReactInstanceManager {
|
||||
return mMemoryPressureRouter;
|
||||
}
|
||||
|
||||
public List<ReactPackage> getPackages() {
|
||||
return new ArrayList<>(mPackages);
|
||||
}
|
||||
|
||||
private static void initializeSoLoaderIfNecessary(Context applicationContext) {
|
||||
// Call SoLoader.initialize here, this is required for apps that does not use exopackage and
|
||||
// does not use SoLoader for loading other native code except from the one used by React Native
|
||||
|
||||
@@ -21,6 +21,8 @@ rn_android_library(
|
||||
react_native_target("java/com/facebook/debug/holder:holder"),
|
||||
react_native_target("java/com/facebook/react/bridge:interfaces"),
|
||||
react_native_target("java/com/facebook/react/bridge:bridge"),
|
||||
react_native_target("java/com/facebook/react/config:config"),
|
||||
react_native_target("java/com/facebook/react:react"),
|
||||
":jscallinvokerholder",
|
||||
],
|
||||
exported_deps = [
|
||||
|
||||
+104
@@ -0,0 +1,104 @@
|
||||
// Copyright 2004-present Facebook. All Rights Reserved.
|
||||
|
||||
package com.facebook.react.turbomodule.core;
|
||||
|
||||
import com.facebook.react.ReactPackage;
|
||||
import com.facebook.react.TurboReactPackage;
|
||||
import com.facebook.react.bridge.CxxModuleWrapper;
|
||||
import com.facebook.react.bridge.NativeModule;
|
||||
import com.facebook.react.bridge.ReactApplicationContext;
|
||||
import com.facebook.react.turbomodule.core.interfaces.TurboModule;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.List;
|
||||
|
||||
public abstract class ReactPackageTurboModuleManagerDelegate extends TurboModuleManagerDelegate {
|
||||
private final List<TurboReactPackage> mPackages = new ArrayList<>();
|
||||
private final Map<String, TurboModule> mModules = new HashMap<>();
|
||||
private final ReactApplicationContext mReactApplicationContext;
|
||||
|
||||
public ReactPackageTurboModuleManagerDelegate(ReactApplicationContext reactApplicationContext, List<ReactPackage> packages) {
|
||||
super(reactApplicationContext);
|
||||
mReactApplicationContext = reactApplicationContext;
|
||||
for (ReactPackage reactPackage : packages) {
|
||||
if (reactPackage instanceof TurboReactPackage) {
|
||||
mPackages.add((TurboReactPackage)reactPackage);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public TurboModule getModule(String moduleName) {
|
||||
TurboModule module = resolveModule(moduleName);
|
||||
if (module == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (module instanceof CxxModuleWrapper) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
return module;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public CxxModuleWrapper getLegacyCxxModule(String moduleName) {
|
||||
TurboModule module = resolveModule(moduleName);
|
||||
if (module == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!(module instanceof CxxModuleWrapper)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
return (CxxModuleWrapper)module;
|
||||
}
|
||||
|
||||
private TurboModule resolveModule(String moduleName) {
|
||||
if (mModules.containsKey(moduleName)) {
|
||||
return mModules.get(moduleName);
|
||||
}
|
||||
|
||||
NativeModule resolvedModule = null;
|
||||
|
||||
for (final TurboReactPackage pkg : mPackages) {
|
||||
try {
|
||||
NativeModule module = pkg.getModule(moduleName, mReactApplicationContext);
|
||||
if (resolvedModule == null || module != null && module.canOverrideExistingModule()) {
|
||||
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.
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
if (resolvedModule instanceof TurboModule) {
|
||||
mModules.put(moduleName, (TurboModule)resolvedModule);
|
||||
} else {
|
||||
/**
|
||||
* 1. The list of TurboReactPackages doesn't change.
|
||||
* 2. TurboReactPackage.getModule is deterministic. Therefore, any two
|
||||
* invocations of TurboReactPackage.getModule will return the same result
|
||||
* given that they're provided the same arguments.
|
||||
*
|
||||
* Hence, if module lookup fails once, we know it'll fail every time.
|
||||
* Therefore, we can write null to the mModules Map and avoid doing this
|
||||
* extra work.
|
||||
*/
|
||||
mModules.put(moduleName, null);
|
||||
}
|
||||
|
||||
return mModules.get(moduleName);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user