// 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. #include "JSCNativeModules.h" #include #include "ModuleRegistry.h" #include "ReactMarker.h" namespace facebook { namespace react { JSCNativeModules::JSCNativeModules(std::shared_ptr moduleRegistry) : m_moduleRegistry(std::move(moduleRegistry)) {} JSValueRef JSCNativeModules::getModule(JSContextRef context, JSStringRef jsName) { if (!m_moduleRegistry) { return nullptr; } std::string moduleName = String::ref(context, jsName).str(); const auto it = m_objects.find(moduleName); if (it != m_objects.end()) { return static_cast(it->second); } auto module = createModule(moduleName, context); if (!module.hasValue()) { // Allow lookup to continue in the objects own properties, which allows for overrides of NativeModules return nullptr; } // Protect since we'll be holding on to this value, even though JS may not module->makeProtected(); auto result = m_objects.emplace(std::move(moduleName), std::move(*module)).first; return static_cast(result->second); } void JSCNativeModules::reset() { m_genNativeModuleJS = nullptr; m_objects.clear(); } folly::Optional JSCNativeModules::createModule(const std::string& name, JSContextRef context) { ReactMarker::logTaggedMarker(ReactMarker::NATIVE_MODULE_SETUP_START, name.c_str()); if (!m_genNativeModuleJS) { auto global = Object::getGlobalObject(context); m_genNativeModuleJS = global.getProperty("__fbGenNativeModule").asObject(); m_genNativeModuleJS->makeProtected(); } auto result = m_moduleRegistry->getConfig(name); if (!result.hasValue()) { return nullptr; } Value moduleInfo = m_genNativeModuleJS->callAsFunction({ Value::fromDynamic(context, result->config), Value::makeNumber(context, result->index) }); CHECK(!moduleInfo.isNull()) << "Module returned from genNativeModule is null"; folly::Optional module(moduleInfo.asObject().getProperty("module").asObject()); ReactMarker::logTaggedMarker(ReactMarker::NATIVE_MODULE_SETUP_STOP, name.c_str()); return module; } } }