Allow ModuleRegistry initialization to complete lazily

Reviewed By: mhorowitz

Differential Revision: D4794794

fbshipit-source-id: f3b7a5d02587b4cd4e214aa6b0368a0d214fb63f
This commit is contained in:
Pieter De Baets 2017-04-07 09:27:05 -07:00 committed by Facebook Github Bot
parent 568fb403bf
commit b2647ea335
6 changed files with 28 additions and 14 deletions

View File

@ -398,7 +398,7 @@ struct RCTInstanceCallback : public InstanceCallback {
[_performanceLogger markStartForTag:RCTPLNativeModulePrepareConfig]; [_performanceLogger markStartForTag:RCTPLNativeModulePrepareConfig];
RCT_PROFILE_BEGIN_EVENT(RCTProfileTagAlways, @"-[RCTCxxBridge buildModuleRegistry]", nil); RCT_PROFILE_BEGIN_EVENT(RCTProfileTagAlways, @"-[RCTCxxBridge buildModuleRegistry]", nil);
auto registry = buildModuleRegistry(_moduleDataByID, self, _reactInstance); auto registry = std::make_shared<ModuleRegistry>(createNativeModules(_moduleDataByID, self, _reactInstance));
[_performanceLogger markStopForTag:RCTPLNativeModulePrepareConfig]; [_performanceLogger markStopForTag:RCTPLNativeModulePrepareConfig];
RCT_PROFILE_END_EVENT(RCTProfileTagAlways, @""); RCT_PROFILE_END_EVENT(RCTProfileTagAlways, @"");

View File

@ -12,7 +12,6 @@
#import <React/RCTConvert.h> #import <React/RCTConvert.h>
#include <JavaScriptCore/JavaScriptCore.h> #include <JavaScriptCore/JavaScriptCore.h>
#include <cxxreact/JSCExecutor.h> #include <cxxreact/JSCExecutor.h>
#include <cxxreact/ModuleRegistry.h>
#include <folly/dynamic.h> #include <folly/dynamic.h>
#include <jschelpers/JavaScriptCore.h> #include <jschelpers/JavaScriptCore.h>
@ -30,7 +29,7 @@ namespace react {
class Instance; class Instance;
std::shared_ptr<ModuleRegistry> buildModuleRegistry(NSArray<RCTModuleData *> *modules, RCTBridge *bridge, const std::shared_ptr<Instance> &instance); std::vector<std::unique_ptr<NativeModule>> createNativeModules(NSArray<RCTModuleData *> *modules, RCTBridge *bridge, const std::shared_ptr<Instance> &instance);
JSContext *contextForGlobalContextRef(JSGlobalContextRef contextRef); JSContext *contextForGlobalContextRef(JSGlobalContextRef contextRef);

View File

@ -41,7 +41,7 @@ using namespace facebook::react;
namespace facebook { namespace facebook {
namespace react { namespace react {
std::shared_ptr<ModuleRegistry> buildModuleRegistry(NSArray<RCTModuleData *> *modules, RCTBridge *bridge, const std::shared_ptr<Instance> &instance) std::vector<std::unique_ptr<NativeModule>> createNativeModules(NSArray<RCTModuleData *> *modules, RCTBridge *bridge, const std::shared_ptr<Instance> &instance)
{ {
std::vector<std::unique_ptr<NativeModule>> nativeModules; std::vector<std::unique_ptr<NativeModule>> nativeModules;
for (RCTModuleData *moduleData in modules) { for (RCTModuleData *moduleData in modules) {
@ -61,8 +61,7 @@ std::shared_ptr<ModuleRegistry> buildModuleRegistry(NSArray<RCTModuleData *> *mo
nativeModules.emplace_back(std::make_unique<RCTNativeModule>(bridge, moduleData)); nativeModules.emplace_back(std::make_unique<RCTNativeModule>(bridge, moduleData));
} }
} }
return nativeModules;
return std::make_shared<ModuleRegistry>(std::move(nativeModules));
} }
JSContext *contextForGlobalContextRef(JSGlobalContextRef contextRef) JSContext *contextForGlobalContextRef(JSGlobalContextRef contextRef)

View File

@ -45,10 +45,6 @@ folly::Optional<Object> JSCNativeModules::createModule(const std::string& name,
auto global = Object::getGlobalObject(context); auto global = Object::getGlobalObject(context);
m_genNativeModuleJS = global.getProperty("__fbGenNativeModule").asObject(); m_genNativeModuleJS = global.getProperty("__fbGenNativeModule").asObject();
m_genNativeModuleJS->makeProtected(); m_genNativeModuleJS->makeProtected();
// Initialize the module name list, otherwise getModuleConfig won't work
// TODO (pieterdb): fix this in ModuleRegistry
m_moduleRegistry->moduleNames();
} }
auto result = m_moduleRegistry->getConfig(name); auto result = m_moduleRegistry->getConfig(name);

View File

@ -2,6 +2,8 @@
#include "ModuleRegistry.h" #include "ModuleRegistry.h"
#include <glog/logging.h>
#include "NativeModule.h" #include "NativeModule.h"
#include "SystraceSection.h" #include "SystraceSection.h"
@ -28,6 +30,18 @@ std::string normalizeName(std::string name) {
ModuleRegistry::ModuleRegistry(std::vector<std::unique_ptr<NativeModule>> modules) ModuleRegistry::ModuleRegistry(std::vector<std::unique_ptr<NativeModule>> modules)
: modules_(std::move(modules)) {} : modules_(std::move(modules)) {}
void ModuleRegistry::registerModules(std::vector<std::unique_ptr<NativeModule>> modules) {
// TODO: consider relaxing this restriction
CHECK(modulesByName_.empty()) << "Can only register additional modules before NativeModules have been accessed";
if (modules_.empty()) {
modules_ = std::move(modules);
} else {
modules_.reserve(modules_.size() + modules.size());
std::move(modules.begin(), modules.end(), std::back_inserter(modules_));
}
}
std::vector<std::string> ModuleRegistry::moduleNames() { std::vector<std::string> ModuleRegistry::moduleNames() {
std::vector<std::string> names; std::vector<std::string> names;
for (size_t i = 0; i < modules_.size(); i++) { for (size_t i = 0; i < modules_.size(); i++) {
@ -40,6 +54,12 @@ std::vector<std::string> ModuleRegistry::moduleNames() {
folly::Optional<ModuleConfig> ModuleRegistry::getConfig(const std::string& name) { folly::Optional<ModuleConfig> ModuleRegistry::getConfig(const std::string& name) {
SystraceSection s("getConfig", "module", name); SystraceSection s("getConfig", "module", name);
// Initialize modulesByName_
if (modulesByName_.empty() && !modules_.empty()) {
moduleNames();
}
auto it = modulesByName_.find(name); auto it = modulesByName_.find(name);
if (it == modulesByName_.end()) { if (it == modulesByName_.end()) {
return nullptr; return nullptr;
@ -97,8 +117,7 @@ void ModuleRegistry::callNativeMethod(ExecutorToken token, unsigned int moduleId
folly::dynamic&& params, int callId) { folly::dynamic&& params, int callId) {
if (moduleId >= modules_.size()) { if (moduleId >= modules_.size()) {
throw std::runtime_error( throw std::runtime_error(
folly::to<std::string>("moduleId ", moduleId, folly::to<std::string>("moduleId ", moduleId, " out of range [0..", modules_.size(), ")"));
" out of range [0..", modules_.size(), ")"));
} }
#ifdef WITH_FBSYSTRACE #ifdef WITH_FBSYSTRACE
@ -113,8 +132,7 @@ void ModuleRegistry::callNativeMethod(ExecutorToken token, unsigned int moduleId
MethodCallResult ModuleRegistry::callSerializableNativeHook(ExecutorToken token, unsigned int moduleId, unsigned int methodId, folly::dynamic&& params) { MethodCallResult ModuleRegistry::callSerializableNativeHook(ExecutorToken token, unsigned int moduleId, unsigned int methodId, folly::dynamic&& params) {
if (moduleId >= modules_.size()) { if (moduleId >= modules_.size()) {
throw std::runtime_error( throw std::runtime_error(
folly::to<std::string>("moduleId ", moduleId, folly::to<std::string>("moduleId ", moduleId, "out of range [0..", modules_.size(), ")"));
" out of range [0..", modules_.size(), ")"));
} }
return modules_[moduleId]->callSerializableNativeHook(token, methodId, std::move(params)); return modules_[moduleId]->callSerializableNativeHook(token, methodId, std::move(params));
} }

View File

@ -30,6 +30,8 @@ class ModuleRegistry {
// notifyCatalystInstanceDestroy: use RAII instead // notifyCatalystInstanceDestroy: use RAII instead
ModuleRegistry(std::vector<std::unique_ptr<NativeModule>> modules); ModuleRegistry(std::vector<std::unique_ptr<NativeModule>> modules);
void registerModules(std::vector<std::unique_ptr<NativeModule>> modules);
std::vector<std::string> moduleNames(); std::vector<std::string> moduleNames();
folly::Optional<ModuleConfig> getConfig(const std::string& name); folly::Optional<ModuleConfig> getConfig(const std::string& name);