Implement ReactContext.getNativeModule support

Summary: `ReactContext.getNativeModule` can be used to access NativeModules. With these changes, it can also be used to instantiate (if necessary) and retrieve a TurboModule.

Reviewed By: mdvacca

Differential Revision: D15167631

fbshipit-source-id: 3cb0d9a4be16cbadebbf6648c3f1481ba26513c3
This commit is contained in:
Ramanpreet Nara
2019-05-22 13:11:53 -07:00
committed by Facebook Github Bot
parent db0ec66341
commit 12c0ec85f7
6 changed files with 110 additions and 16 deletions
@@ -11,6 +11,7 @@ import com.facebook.proguard.annotations.DoNotStrip;
import com.facebook.react.bridge.queue.ReactQueueConfiguration;
import com.facebook.react.common.annotations.VisibleForTesting;
import com.facebook.react.turbomodule.core.interfaces.JSCallInvokerHolder;
import com.facebook.react.turbomodule.core.interfaces.TurboModuleRegistry;
import java.util.Collection;
import java.util.List;
import javax.annotation.Nullable;
@@ -110,4 +111,12 @@ public interface CatalystInstance
* Required for TurboModuleManager initialization.
*/
JSCallInvokerHolder getJSCallInvokerHolder();
/**
* For the time being, we want code relying on the old infra to also
* work with TurboModules. Hence, we must provide the TurboModuleRegistry
* to CatalystInstance so that getNativeModule, hasNativeModule, and
* getNativeModules can also return TurboModules.
*/
void setTurboModuleRegistry(TurboModuleRegistry getter);
}
@@ -25,10 +25,10 @@ import com.facebook.react.common.ReactConstants;
import com.facebook.react.common.annotations.VisibleForTesting;
import com.facebook.react.module.annotations.ReactModule;
import com.facebook.react.turbomodule.core.JSCallInvokerHolderImpl;
import com.facebook.react.turbomodule.core.interfaces.TurboModule;
import com.facebook.react.turbomodule.core.interfaces.TurboModuleRegistry;
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;
@@ -96,6 +96,7 @@ public class CatalystInstanceImpl implements CatalystInstance {
private @Nullable String mSourceURL;
private JavaScriptContextHolder mJavaScriptContextHolder;
private @Nullable TurboModuleRegistry mTurboModuleRegistry = null;
// C++ parts
private final HybridData mHybridData;
@@ -421,16 +422,25 @@ public class CatalystInstanceImpl implements CatalystInstance {
@Override
public <T extends NativeModule> boolean hasNativeModule(Class<T> nativeModuleInterface) {
return mNativeModuleRegistry.hasModule(getNameFromAnnotation(nativeModuleInterface));
String moduleName = getNameFromAnnotation(nativeModuleInterface);
return mTurboModuleRegistry != null && mTurboModuleRegistry.hasModule(moduleName) ? true : mNativeModuleRegistry.hasModule(moduleName);
}
@Override
public <T extends NativeModule> T getNativeModule(Class<T> nativeModuleInterface) {
return (T) mNativeModuleRegistry.getModule(getNameFromAnnotation(nativeModuleInterface));
return (T) getNativeModule(getNameFromAnnotation(nativeModuleInterface));
}
@Override
public NativeModule getNativeModule(String moduleName) {
if (mTurboModuleRegistry != null) {
TurboModule turboModule = mTurboModuleRegistry.getModule(moduleName);
if (turboModule != null) {
return (NativeModule)turboModule;
}
}
return mNativeModuleRegistry.getModule(moduleName);
}
@@ -445,7 +455,16 @@ public class CatalystInstanceImpl implements CatalystInstance {
// This is only used by com.facebook.react.modules.common.ModuleDataCleaner
@Override
public Collection<NativeModule> getNativeModules() {
return mNativeModuleRegistry.getAllModules();
Collection<NativeModule> nativeModules = new ArrayList<>();
nativeModules.addAll(mNativeModuleRegistry.getAllModules());
if (mTurboModuleRegistry != null) {
for (TurboModule turboModule : mTurboModuleRegistry.getModules()) {
nativeModules.add((NativeModule) turboModule);
}
}
return nativeModules;
}
private native void jniHandleMemoryPressure(int level);
@@ -517,6 +536,10 @@ public class CatalystInstanceImpl implements CatalystInstance {
}
}
public void setTurboModuleRegistry(TurboModuleRegistry getter) {
mTurboModuleRegistry = getter;
}
private void decrementPendingJSCalls() {
int newPendingCalls = mPendingJSCalls.decrementAndGet();
// TODO(9604406): handle case of web workers injecting messages to main thread
@@ -13,7 +13,6 @@ rn_android_library(
"PUBLIC",
],
deps = [
react_native_target("java/com/facebook/react/turbomodule/core/interfaces:interfaces"),
react_native_dep("java/com/facebook/systrace:systrace"),
react_native_dep("libraries/soloader/java/com/facebook/soloader:soloader"),
react_native_dep("third-party/java/infer-annotations:infer-annotations"),
@@ -24,6 +23,9 @@ rn_android_library(
react_native_target("java/com/facebook/react/bridge:bridge"),
":jscallinvokerholder",
],
exported_deps = [
react_native_target("java/com/facebook/react/turbomodule/core/interfaces:interfaces"),
],
)
rn_android_library(
@@ -9,20 +9,24 @@ package com.facebook.react.turbomodule.core;
import com.facebook.jni.HybridData;
import com.facebook.proguard.annotations.DoNotStrip;
import com.facebook.react.bridge.CatalystInstance;
import com.facebook.react.bridge.JSIModule;
import com.facebook.react.bridge.JavaScriptContextHolder;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.queue.MessageQueueThread;
import com.facebook.react.turbomodule.core.interfaces.JSCallInvokerHolder;
import com.facebook.react.turbomodule.core.interfaces.TurboModule;
import com.facebook.react.turbomodule.core.interfaces.TurboModuleRegistry;
import com.facebook.soloader.SoLoader;
import java.util.*;
import javax.annotation.Nullable;
/**
* This is the main class and entry point for TurboModules.
* Note that this is a hybrid class, and has a C++ counterpart
* This class installs the JSI bindings. It also implements the method to get a Java module, that the C++ counterpart calls.
*/
public class TurboModuleManager implements JSIModule {
public class TurboModuleManager implements JSIModule, TurboModuleRegistry {
static {
SoLoader.loadLibrary("turbomodulejsijni");
}
@@ -30,6 +34,8 @@ public class TurboModuleManager implements JSIModule {
private final ReactApplicationContext mReactApplicationContext;
private final TurboModuleManagerDelegate mTurbomoduleManagerDelegate;
private final Map<String, TurboModule> mTurboModules = new HashMap<>();
@DoNotStrip
@SuppressWarnings("unused")
private final HybridData mHybridData;
@@ -41,9 +47,30 @@ public class TurboModuleManager implements JSIModule {
mTurbomoduleManagerDelegate = tmmDelegate;
}
@DoNotStrip
@SuppressWarnings("unused")
private TurboModule getJavaModule(String name) {
return mTurbomoduleManagerDelegate.getModule(name);
@Nullable
protected TurboModule getJavaModule(String name) {
if (!mTurboModules.containsKey(name)) {
final TurboModule turboModule = mTurbomoduleManagerDelegate.getModule(name);
if (turboModule != null) {
mTurboModules.put(name, turboModule);
}
}
return mTurboModules.get(name);
}
@Nullable
public TurboModule getModule(String name) {
return getJavaModule(name);
}
public Collection<TurboModule> getModules() {
return mTurboModules.values();
}
public boolean hasModule(String name) {
return mTurboModules.containsKey(name);
}
private native HybridData initHybrid(long jsContext, JSCallInvokerHolderImpl jsQueue, TurboModuleManagerDelegate tmmDelegate);
@@ -59,9 +86,4 @@ public class TurboModuleManager implements JSIModule {
@Override
public void onCatalystInstanceDestroy() {}
/** All applications must implement this interface, and provide the Java TurboModule class */
public interface ModuleProvider {
TurboModule getModule(String name, ReactApplicationContext reactApplicationContext);
}
}
@@ -1,4 +1,4 @@
load("//tools/build_defs/oss:rn_defs.bzl", "rn_android_library")
load("//tools/build_defs/oss:rn_defs.bzl", "react_native_dep", "rn_android_library")
rn_android_library(
name = "interfaces",
@@ -9,4 +9,7 @@ rn_android_library(
visibility = [
"PUBLIC",
],
deps = [
react_native_dep("third-party/java/jsr-305:jsr-305"),
],
)
@@ -0,0 +1,35 @@
/**
* 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.
*/
package com.facebook.react.turbomodule.core.interfaces;
import java.util.Collection;
import javax.annotation.Nullable;
/**
* Interface to allow for creating and retrieving TurboModuels.
*/
public interface TurboModuleRegistry {
/**
* Return the TurboModule instance that has that name `moduleName`.
* If the `moduleName` TurboModule hasn't been instantiated, instantiate it.
* If no TurboModule is registered under `moduleName`, return null.
*/
@Nullable
TurboModule getModule(String moduleName);
/**
* Get all instantiated TurboModules.
*/
Collection<TurboModule> getModules();
/**
* Has the TurboModule with name `moduleName` been instantiated?
*/
boolean hasModule(String moduleName);
}