RN若要调用js,先通过
(mReactContext.getJSModule(NativeToJsBridge.class)得到Js模块。
这一步最后调用的是com.facebook.react.bridge.JavaScriptModuleRegistry#getJavaScriptModule
实际上,这个函数里面是new了一个代理对象
JavaScriptModule interfaceProxy = (JavaScriptModule) Proxy.newProxyInstance(
moduleInterface.getClassLoader(),
new Class[]{moduleInterface},
new JavaScriptModuleInvocationHandler(instance, moduleInterface));
当调用代理对象对应js方法的时候,走到
com.facebook.react.bridge.JavaScriptModuleRegistry.JavaScriptModuleInvocationHandler#invoke:(这个过程是java 动态代理的原理。)
@Override
public @Nullable Object invoke(Object proxy, Method method, @Nullable Object[] args) throws Throwable {
NativeArray jsArgs = args != null
? Arguments.fromJavaArgs(args)
: new WritableNativeArray();
mCatalystInstance.callFunction(getJSModuleName(), method.getName(), jsArgs);
return null;
}
mCatalystInstance.callFunction(getJSModuleName(), method.getName(), jsArgs);这一句调用的是:
com.facebook.react.bridge.CatalystInstanceImpl#callFunction(com.facebook.react.bridge.CatalystInstanceImpl.PendingJSCall)
public void callFunction(PendingJSCall function) {
if (mDestroyed) {
final String call = function.toString();
FLog.w(ReactConstants.TAG, "Calling JS function after bridge has been destroyed: " + call);
return;
}
if (!mAcceptCalls) {
// Most of the time the instance is initialized and we don't need to acquire the lock
synchronized (mJSCallsPendingInitLock) {
if (!mAcceptCalls) {
mJSCallsPendingInit.add(function);
return;
}
}
}
function.call(this);
}
function.call(this);也就是:
com.facebook.react.bridge.CatalystInstanceImpl.PendingJSCall#call
void call(CatalystInstanceImpl catalystInstance) {
NativeArray arguments = mArguments != null ? mArguments : new WritableNativeArray();
catalystInstance.jniCallJSFunction(mModule, mMethod, arguments);
}
最后调用到了jni:catalystInstance.jniCallJSFunction(mModule, mMethod, arguments);
该jni函数在:
ReactAndroid/src/main/jni/react/jni/CatalystInstanceImpl.cpp:
void CatalystInstanceImpl::jniCallJSFunction(std::string module, std::string method, NativeArray* arguments) {
// We want to share the C++ code, and on iOS, modules pass module/method
// names as strings all the way through to JS, and there's no way to do
// string -> id mapping on the objc side. So on Android, we convert the
// number to a string, here which gets passed as-is to JS. There, they they
// used as ids if isFinite(), which handles this case, and looked up as
// strings otherwise. Eventually, we'll probably want to modify the stack
// from the JS proxy through here to use strings, too.
instance_->callJSFunction(std::move(module),
std::move(method),
arguments->consume());
}
instance_->callJSFunctio 这一句调用的是:
ReactCommon/cxxreact/Instance.cpp:
void Instance::callJSFunction(std::string &&module, std::string &&method,
folly::dynamic &¶ms) {
callback_->incrementPendingJSCalls();
nativeToJsBridge_->callFunction(std::move(module), std::move(method),
std::move(params));
}
nativeToJsBridge_->callFunction 这一句是:
ReactCommon/cxxreact/NativeToJsBridge.cpp:
void NativeToJsBridge::callFunction(
std::string&& module,
std::string&& method,
folly::dynamic&& arguments) {
int systraceCookie = -1;
#ifdef WITH_FBSYSTRACE
systraceCookie = m_systraceCookie++;
FbSystraceAsyncFlow::begin(
TRACE_TAG_REACT_CXX_BRIDGE,
"JSCall",
systraceCookie);
#endif
runOnExecutorQueue([this, module = std::move(module), method = std::move(method), arguments = std::move(arguments), systraceCookie]
(JSExecutor* executor) {
if (m_applicationScriptHasFailure) {
LOG(ERROR) << "Attempting to call JS function on a bad application bundle: " << module.c_str() << "." << method.c_str() << "()";
throw std::runtime_error("Attempting to call JS function on a bad application bundle: " + module + "." + method + "()");
}
#ifdef WITH_FBSYSTRACE
FbSystraceAsyncFlow::end(
TRACE_TAG_REACT_CXX_BRIDGE,
"JSCall",
systraceCookie);
SystraceSection s("NativeToJsBridge::callFunction", "module", module, "method", method);
#endif
// This is safe because we are running on the executor's thread: it won't
// destruct until after it's been unregistered (which we check above) and
// that will happen on this thread
executor->callFunction(module, method, arguments);
});
}
executor->callFunction 实际上调用的是:
ReactCommon/cxxreact/JSCExecutor.cpp
void JSCExecutor::callFunction(
const std::string& moduleId,
const std::string& methodId,
const folly::dynamic& arguments) {
SystraceSection s("JSCExecutor::callFunction");
// This weird pattern is because Value is not default constructible.
// The lambda is inlined, so there's no overhead.
auto result = [&] {
JSContextLock lock(m_context);
try {
if (!m_callFunctionReturnResultAndFlushedQueueJS) {
bindBridge();
}
return m_callFunctionReturnFlushedQueueJS->callAsFunction(
{Value(m_context, String::createExpectingAscii(m_context, moduleId)),
Value(m_context, String::createExpectingAscii(m_context, methodId)),
Value::fromDynamic(m_context, std::move(arguments))});
} catch (...) {
std::throw_with_nested(
std::runtime_error("Error calling " + moduleId + "." + methodId));
}
}();
callNativeModules(std::move(result));
}
到这里基本就结束了,通过m_callFunctionReturnFlushedQueueJS->callAsFunction来执行js函数。
我们顺便跟一下m_callFunctionReturnFlushedQueueJS是怎么来的
m_callFunctionReturnFlushedQueueJS->callAsFunction(
{Value(m_context, String::createExpectingAscii(m_context, moduleId)),
Value(m_context, String::createExpectingAscii(m_context, methodId)),
Value::fromDynamic(m_context, std::move(arguments))});
这一句的m_callFunctionReturnFlushedQueueJS是:
m_callFunctionReturnFlushedQueueJS =
batchedBridge.getProperty("callFunctionReturnFlushedQueue").asObject();
这个就是操作Js对象了。
上面的batchedBridge来自batchedBridgeValue:
auto batchedBridge = batchedBridgeValue.asObject();
而batchedBridgeValue是:
auto batchedBridgeValue = global.getProperty("__fbBatchedBridge");
if (batchedBridgeValue.isUndefined()) {
auto requireBatchedBridge =
global.getProperty("__fbRequireBatchedBridge");
if (!requireBatchedBridge.isUndefined()) {
batchedBridgeValue = requireBatchedBridge.asObject().callAsFunction({});
}
if (batchedBridgeValue.isUndefined()) {
throw JSException(
"Could not get BatchedBridge, make sure your bundle is packaged correctly");
}
这里的global是:
auto global = Object::getGlobalObject(m_context);
而m_context是:
m_context =
JSC_JSGlobalContextCreateInGroup(useCustomJSC, nullptr, globalClass);
JSC_JSGlobalContextCreateInGroup这个是:
#define JSC_JSGlobalContextCreateInGroup(...) __jsc_bool_wrapper(JSGlobalContextCreateInGroup, __VA_ARGS__)
从这里就可以看到m_context是通过jscore的api:JSGlobalContextCreateInGroup获取的对象了。