Channge interface to getNativeModule to use strings instead of classes

Summary: Now that NativeModules are stored based on String keys instead of classnames, the old innterface to getNativeModules(Class moduleInterface) is deprecated. This interface is also incorrect since a native module with the same name may be overridden, causing issues. Getting native modules by name is also similar to what JavaScript does

Reviewed By: achen1

Differential Revision: D9697827

fbshipit-source-id: ff832bd2ea5e1c7cfe7d8c0c3a66f0d755b2c354
This commit is contained in:
Ram N 2018-09-19 18:44:05 -07:00 committed by Facebook Github Bot
parent 5f31a1082b
commit 0cd3994f1a
3 changed files with 57 additions and 34 deletions

View File

@ -63,6 +63,7 @@ public interface CatalystInstance
<T extends JavaScriptModule> T getJSModule(Class<T> jsInterface);
<T extends NativeModule> boolean hasNativeModule(Class<T> nativeModuleInterface);
<T extends NativeModule> T getNativeModule(Class<T> nativeModuleInterface);
NativeModule getNativeModule(String moduleName);
<T extends JSIModule> T getJSIModule(Class<T> jsiModuleInterface);
Collection<NativeModule> getNativeModules();

View File

@ -23,8 +23,11 @@ import com.facebook.react.bridge.queue.ReactQueueConfigurationImpl;
import com.facebook.react.bridge.queue.ReactQueueConfigurationSpec;
import com.facebook.react.common.ReactConstants;
import com.facebook.react.common.annotations.VisibleForTesting;
import com.facebook.react.module.annotations.ReactModule;
import com.facebook.systrace.Systrace;
import com.facebook.systrace.TraceListener;
import java.lang.annotation.Annotation;
import java.lang.annotation.Native;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Collection;
@ -422,13 +425,25 @@ public class CatalystInstanceImpl implements CatalystInstance {
@Override
public <T extends NativeModule> boolean hasNativeModule(Class<T> nativeModuleInterface) {
return mNativeModuleRegistry.hasModule(nativeModuleInterface);
return mNativeModuleRegistry.hasModule(getNameFromAnnotation(nativeModuleInterface));
}
// This is only ever called with UIManagerModule or CurrentViewerModule.
@Override
public <T extends NativeModule> T getNativeModule(Class<T> nativeModuleInterface) {
return mNativeModuleRegistry.getModule(nativeModuleInterface);
return (T) mNativeModuleRegistry.getModule(getNameFromAnnotation(nativeModuleInterface));
}
@Override
public NativeModule getNativeModule(String moduleName) {
return mNativeModuleRegistry.getModule(moduleName);
}
private <T extends NativeModule> String getNameFromAnnotation(Class<T> nativeModuleInterface){
ReactModule annotation = nativeModuleInterface.getAnnotation(ReactModule.class);
if (annotation == null) {
throw new IllegalArgumentException("Could not find @ReactModule annotation in " + nativeModuleInterface.getCanonicalName());
}
return annotation.name();
}
// This is only used by com.facebook.react.modules.common.ModuleDataCleaner

View File

@ -1,39 +1,32 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
* <p>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.bridge;
import com.facebook.infer.annotation.Assertions;
import com.facebook.react.module.annotations.ReactModule;
import com.facebook.systrace.Systrace;
import java.lang.annotation.Annotation;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
/**
* A set of Java APIs to expose to a particular JavaScript instance.
*/
/** A set of Java APIs to expose to a particular JavaScript instance. */
public class NativeModuleRegistry {
private final ReactApplicationContext mReactApplicationContext;
private final Map<String, ModuleHolder> mModules;
public NativeModuleRegistry(
ReactApplicationContext reactApplicationContext,
Map<String, ModuleHolder> modules) {
ReactApplicationContext reactApplicationContext, Map<String, ModuleHolder> modules) {
mReactApplicationContext = reactApplicationContext;
mModules = modules;
}
/**
* Private getters for combining NativeModuleRegistrys
*/
/** Private getters for combining NativeModuleRegistrys */
private Map<String, ModuleHolder> getModuleMap() {
return mModules;
}
@ -42,12 +35,10 @@ public class NativeModuleRegistry {
return mReactApplicationContext;
}
/* package */ Collection<JavaModuleWrapper> getJavaModules(
JSInstance jsInstance) {
/* package */ Collection<JavaModuleWrapper> getJavaModules(JSInstance jsInstance) {
ArrayList<JavaModuleWrapper> javaModules = new ArrayList<>();
for (Map.Entry<String, ModuleHolder> entry : mModules.entrySet()) {
if (!entry.getValue().isCxxModule()) {
//if (!CxxModuleWrapperBase.class.isAssignableFrom(entry.getValue().getModule().getClass())) {
javaModules.add(new JavaModuleWrapper(jsInstance, entry.getValue()));
}
}
@ -65,12 +56,13 @@ public class NativeModuleRegistry {
}
/*
* Adds any new modules to the current module registry
*/
* Adds any new modules to the current module registry
*/
/* package */ void registerModules(NativeModuleRegistry newRegister) {
Assertions.assertCondition(mReactApplicationContext.equals(newRegister.getReactApplicationContext()),
"Extending native modules with non-matching application contexts.");
Assertions.assertCondition(
mReactApplicationContext.equals(newRegister.getReactApplicationContext()),
"Extending native modules with non-matching application contexts.");
Map<String, ModuleHolder> newModules = newRegister.getModuleMap();
@ -86,8 +78,7 @@ public class NativeModuleRegistry {
/* package */ void notifyJSInstanceDestroy() {
mReactApplicationContext.assertOnNativeModulesQueueThread();
Systrace.beginSection(
Systrace.TRACE_TAG_REACT_JAVA_BRIDGE,
"NativeModuleRegistry_notifyJSInstanceDestroy");
Systrace.TRACE_TAG_REACT_JAVA_BRIDGE, "NativeModuleRegistry_notifyJSInstanceDestroy");
try {
for (ModuleHolder module : mModules.values()) {
module.destroy();
@ -98,14 +89,14 @@ public class NativeModuleRegistry {
}
/* package */ void notifyJSInstanceInitialized() {
mReactApplicationContext.assertOnNativeModulesQueueThread("From version React Native v0.44, " +
"native modules are explicitly not initialized on the UI thread. See " +
"https://github.com/facebook/react-native/wiki/Breaking-Changes#d4611211-reactnativeandroidbreaking-move-nativemodule-initialization-off-ui-thread---aaachiuuu " +
" for more details.");
mReactApplicationContext.assertOnNativeModulesQueueThread(
"From version React Native v0.44, "
+ "native modules are explicitly not initialized on the UI thread. See "
+ "https://github.com/facebook/react-native/wiki/Breaking-Changes#d4611211-reactnativeandroidbreaking-move-nativemodule-initialization-off-ui-thread---aaachiuuu "
+ " for more details.");
ReactMarker.logMarker(ReactMarkerConstants.NATIVE_MODULE_INITIALIZE_START);
Systrace.beginSection(
Systrace.TRACE_TAG_REACT_JAVA_BRIDGE,
"NativeModuleRegistry_notifyJSInstanceInitialized");
Systrace.TRACE_TAG_REACT_JAVA_BRIDGE, "NativeModuleRegistry_notifyJSInstanceInitialized");
try {
for (ModuleHolder module : mModules.values()) {
module.markInitializable();
@ -118,7 +109,8 @@ public class NativeModuleRegistry {
public void onBatchComplete() {
// The only native module that uses the onBatchComplete is the UI Manager. Hence, instead of
// iterating over all the modules for find this one instance, and then calling it, we short-circuit
// iterating over all the modules for find this one instance, and then calling it, we
// short-circuit
// the search, and simply call OnBatchComplete on the UI Manager.
// With Fabric, UIManager would no longer be a NativeModule, so this call would simply go away
ModuleHolder moduleHolder = mModules.get("UIManager");
@ -135,10 +127,25 @@ public class NativeModuleRegistry {
public <T extends NativeModule> T getModule(Class<T> moduleInterface) {
ReactModule annotation = moduleInterface.getAnnotation(ReactModule.class);
if (annotation == null) {
throw new IllegalArgumentException("Could not find @ReactModule annotation in class " + moduleInterface.getName());
throw new IllegalArgumentException(
"Could not find @ReactModule annotation in class " + moduleInterface.getName());
}
return (T) Assertions.assertNotNull(
mModules.get(annotation.name()), annotation.name() + " could not be found. Is it defined in " + moduleInterface.getName()).getModule();
return (T)
Assertions.assertNotNull(
mModules.get(annotation.name()),
annotation.name()
+ " could not be found. Is it defined in "
+ moduleInterface.getName())
.getModule();
}
public boolean hasModule(String name) {
return mModules.containsKey(name);
}
public NativeModule getModule(String name) {
return Assertions.assertNotNull(
mModules.get(name), "Could not find module with name " + name).getModule();
}
public List<NativeModule> getAllModules() {