react-native/ReactCommon/bridge/ModuleRegistry.cpp

115 lines
3.6 KiB
C++

// Copyright 2004-present Facebook. All Rights Reserved.
#include "ModuleRegistry.h"
#include "NativeModule.h"
#ifdef WITH_FBSYSTRACE
#include <fbsystrace.h>
using fbsystrace::FbSystraceSection;
#endif
namespace facebook {
namespace react {
ModuleRegistry::ModuleRegistry(std::vector<std::unique_ptr<NativeModule>> modules)
: modules_(std::move(modules)) {}
folly::dynamic ModuleRegistry::moduleDescriptions() {
folly::dynamic modDescs = folly::dynamic::object;
for (size_t moduleId = 0; moduleId < modules_.size(); ++moduleId) {
const auto& module = modules_[moduleId];
folly::dynamic methodDescs = folly::dynamic::object;
std::vector<MethodDescriptor> methods;
{
#ifdef WITH_FBSYSTRACE
FbSystraceSection s(TRACE_TAG_REACT_CXX_BRIDGE, "getMethods", "module", module->getName());
#endif
methods = module->getMethods();
}
for (size_t methodId = 0; methodId < methods.size(); ++methodId) {
methodDescs.insert(std::move(methods[methodId].name),
folly::dynamic::object
("methodID", methodId)
("type", std::move(methods[methodId].type)));
}
folly::dynamic constants = folly::dynamic::array();
{
#ifdef WITH_FBSYSTRACE
FbSystraceSection s(TRACE_TAG_REACT_CXX_BRIDGE, "getConstants", "module", module->getName());
#endif
constants = module->getConstants();
}
modDescs.insert(module->getName(),
folly::dynamic::object
("supportsWebWorkers", module->supportsWebWorkers())
("moduleID", moduleId)
("methods", std::move(methodDescs))
("constants", std::move(constants)));
}
return modDescs;
}
void ModuleRegistry::callNativeMethod(ExecutorToken token, unsigned int moduleId, unsigned int methodId,
folly::dynamic&& params, int callId) {
if (moduleId >= modules_.size()) {
throw std::runtime_error(
folly::to<std::string>("moduleId ", moduleId,
" out of range [0..", modules_.size(), ")"));
}
#ifdef WITH_FBSYSTRACE
if (callId != -1) {
fbsystrace_end_async_flow(TRACE_TAG_REACT_APPS, "native", callId);
}
#endif
// TODO mhorowitz: systrace
std::string what;
try {
modules_[moduleId]->invoke(token, methodId, std::move(params));
return;
} catch (const std::exception& e) {
what = e.what();
// fall through;
} catch (...) {
// fall through;
}
std::string moduleName = modules_[moduleId]->getName();
auto descs = modules_[moduleId]->getMethods();
std::string methodName;
if (methodId < descs.size()) {
methodName = descs[methodId].name;
} else {
methodName = folly::to<std::string>("id ", methodId, " (out of range [0..",
descs.size(), "))");
}
if (what.empty()) {
throw std::runtime_error(
folly::to<std::string>("Unknown native exception in module '", moduleName,
"' method '", methodName, "'"));
} else {
throw std::runtime_error(
folly::to<std::string>("Native exception in module '", moduleName,
"' method '", methodName, "': ", what));
}
}
MethodCallResult ModuleRegistry::callSerializableNativeHook(ExecutorToken token, unsigned int moduleId, unsigned int methodId, folly::dynamic&& params) {
if (moduleId >= modules_.size()) {
throw std::runtime_error(
folly::to<std::string>("moduleId ", moduleId,
" out of range [0..", modules_.size(), ")"));
}
return modules_[moduleId]->callSerializableNativeHook(token, methodId, std::move(params));
}
}}