Reviewed By: javache

Differential Revision: D4762575

fbshipit-source-id: fc3be786640b8c42664d7b357ab0fe197006b28b
This commit is contained in:
Kathy Gray 2017-03-29 02:32:35 -07:00 коммит произвёл Facebook Github Bot
Родитель a85a86bd8d
Коммит f804af27c2
3 изменённых файлов: 44 добавлений и 21 удалений

Просмотреть файл

@ -168,31 +168,45 @@ public abstract class BaseJavaModule implements NativeModule {
public class JavaMethod implements NativeMethod { public class JavaMethod implements NativeMethod {
private Method mMethod; private final Method mMethod;
private final ArgumentExtractor[] mArgumentExtractors; private final Class[] mParameterTypes;
private final String mSignature; private final int mParamLength;
private final Object[] mArguments; private boolean mArgumentsProcessed = false;
private @Nullable ArgumentExtractor[] mArgumentExtractors;
private @Nullable String mSignature;
private @Nullable Object[] mArguments;
private String mType = METHOD_TYPE_ASYNC; private String mType = METHOD_TYPE_ASYNC;
private final int mJSArgumentsNeeded; private @Nullable int mJSArgumentsNeeded;
private final String mTraceName; private String mTraceName;
public JavaMethod(Method method, boolean isSync) { public JavaMethod(Method method, boolean isSync) {
mMethod = method; mMethod = method;
mMethod.setAccessible(true); mMethod.setAccessible(true);
Systrace.beginSection(TRACE_TAG_REACT_JAVA_BRIDGE, "callGetParameterTypes");
mParameterTypes = mMethod.getParameterTypes();
Systrace.endSection(TRACE_TAG_REACT_JAVA_BRIDGE);
mParamLength = mParameterTypes.length;
if (isSync) { if (isSync) {
mType = METHOD_TYPE_SYNC; mType = METHOD_TYPE_SYNC;
} else if (mParamLength > 0 && (mParameterTypes[mParamLength - 1] == Promise.class)) {
mType = METHOD_TYPE_PROMISE;
} }
// TODO: create these lazily
Class[] parameterTypes = method.getParameterTypes();
mArgumentExtractors = buildArgumentExtractors(parameterTypes);
mSignature = buildSignature(mMethod, parameterTypes, isSync);
// Since native methods are invoked from a message queue executed on a single thread, it is
// save to allocate only one arguments object per method that can be reused across calls
mArguments = new Object[parameterTypes.length];
mJSArgumentsNeeded = calculateJSArgumentsNeeded();
mTraceName = BaseJavaModule.this.getName() + "." + mMethod.getName(); mTraceName = BaseJavaModule.this.getName() + "." + mMethod.getName();
}
private void processArguments() {
if (mArgumentsProcessed) {
return;
}
mArgumentsProcessed = true;
mArgumentExtractors = buildArgumentExtractors(mParameterTypes);
mSignature = buildSignature(mMethod, mParameterTypes, (mType.equals(METHOD_TYPE_SYNC)));
// Since native methods are invoked from a message queue executed on a single thread, it is
// safe to allocate only one arguments object per method that can be reused across calls
mArguments = new Object[mParameterTypes.length];
mJSArgumentsNeeded = calculateJSArgumentsNeeded();
} }
public Method getMethod() { public Method getMethod() {
@ -200,7 +214,10 @@ public abstract class BaseJavaModule implements NativeModule {
} }
public String getSignature() { public String getSignature() {
return mSignature; if (!mArgumentsProcessed) {
processArguments();
}
return assertNotNull(mSignature);
} }
private String buildSignature(Method method, Class[] paramTypes, boolean isSync) { private String buildSignature(Method method, Class[] paramTypes, boolean isSync) {
@ -312,6 +329,12 @@ public abstract class BaseJavaModule implements NativeModule {
.arg("method", mTraceName) .arg("method", mTraceName)
.flush(); .flush();
try { try {
if (!mArgumentsProcessed) {
processArguments();
}
if (mArguments == null || mArgumentExtractors == null) {
throw new Error("processArguments failed");
}
if (mJSArgumentsNeeded != parameters.size()) { if (mJSArgumentsNeeded != parameters.size()) {
throw new NativeArgumentsParseException( throw new NativeArgumentsParseException(
BaseJavaModule.this.getName() + "." + mMethod.getName() + " got " + BaseJavaModule.this.getName() + "." + mMethod.getName() + " got " +

Просмотреть файл

@ -155,12 +155,12 @@ std::size_t countJsArgs(const std::string& signature) {
MethodInvoker::MethodInvoker(jni::alias_ref<JReflectMethod::javaobject> method, std::string signature, std::string traceName, bool isSync) MethodInvoker::MethodInvoker(jni::alias_ref<JReflectMethod::javaobject> method, std::string signature, std::string traceName, bool isSync)
: method_(method->getMethodID()), : method_(method->getMethodID()),
jsArgCount_(countJsArgs(signature) - 2), signature_(signature),
signature_(std::move(signature)), jsArgCount_(countJsArgs(signature) -2),
traceName_(std::move(traceName)), traceName_(std::move(traceName)),
isSync_(isSync) { isSync_(isSync) {
CHECK(signature_.at(1) == '.') << "Improper module method signature"; CHECK(signature_.at(1) == '.') << "Improper module method signature";
CHECK(isSync || signature_.at(0) == 'v') << "Non-sync hooks cannot have a non-void return type"; CHECK(isSync_ || signature_.at(0) == 'v') << "Non-sync hooks cannot have a non-void return type";
} }
MethodCallResult MethodInvoker::invoke(std::weak_ptr<Instance>& instance, jni::alias_ref<JBaseJavaModule::javaobject> module, ExecutorToken token, const folly::dynamic& params) { MethodCallResult MethodInvoker::invoke(std::weak_ptr<Instance>& instance, jni::alias_ref<JBaseJavaModule::javaobject> module, ExecutorToken token, const folly::dynamic& params) {

Просмотреть файл

@ -38,8 +38,8 @@ public:
} }
private: private:
jmethodID method_; jmethodID method_;
std::size_t jsArgCount_;
std::string signature_; std::string signature_;
std::size_t jsArgCount_;
std::string traceName_; std::string traceName_;
bool isSync_; bool isSync_;
}; };