/* * 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 "Instance.h" #include "JSBigString.h" #include "JSBundleType.h" #include "JSExecutor.h" #include "MessageQueueThread.h" #include "MethodCall.h" #include "NativeToJsBridge.h" #include "RAMBundleRegistry.h" #include "RecoverableError.h" #include "SystraceSection.h" #include #include #include #include #include #include #include #include #include namespace facebook { namespace react { Instance::~Instance() { if (nativeToJsBridge_) { nativeToJsBridge_->destroy(); } } void Instance::initializeBridge( std::unique_ptr callback, std::shared_ptr jsef, std::shared_ptr jsQueue, std::shared_ptr moduleRegistry) { callback_ = std::move(callback); moduleRegistry_ = std::move(moduleRegistry); jsQueue->runOnQueueSync([this, &jsef, jsQueue]() mutable { nativeToJsBridge_ = std::make_unique( jsef.get(), moduleRegistry_, jsQueue, callback_); std::lock_guard lock(m_syncMutex); m_syncReady = true; m_syncCV.notify_all(); }); CHECK(nativeToJsBridge_); } void Instance::loadApplication( std::unique_ptr bundleRegistry, std::unique_ptr string, std::string sourceURL) { callback_->incrementPendingJSCalls(); SystraceSection s("Instance::loadApplication", "sourceURL", sourceURL); nativeToJsBridge_->loadApplication( std::move(bundleRegistry), std::move(string), std::move(sourceURL)); } void Instance::loadApplicationSync( std::unique_ptr bundleRegistry, std::unique_ptr string, std::string sourceURL) { std::unique_lock lock(m_syncMutex); m_syncCV.wait(lock, [this] { return m_syncReady; }); SystraceSection s("Instance::loadApplicationSync", "sourceURL", sourceURL); nativeToJsBridge_->loadApplicationSync( std::move(bundleRegistry), std::move(string), std::move(sourceURL)); } void Instance::setSourceURL(std::string sourceURL) { callback_->incrementPendingJSCalls(); SystraceSection s("Instance::setSourceURL", "sourceURL", sourceURL); nativeToJsBridge_->loadApplication(nullptr, nullptr, std::move(sourceURL)); } void Instance::loadScriptFromString( std::unique_ptr string, std::string sourceURL, bool loadSynchronously) { SystraceSection s("Instance::loadScriptFromString", "sourceURL", sourceURL); if (loadSynchronously) { loadApplicationSync(nullptr, std::move(string), std::move(sourceURL)); } else { loadApplication(nullptr, std::move(string), std::move(sourceURL)); } } bool Instance::isIndexedRAMBundle(const char *sourcePath) { std::ifstream bundle_stream(sourcePath, std::ios_base::in); BundleHeader header; if (!bundle_stream || !bundle_stream.read(reinterpret_cast(&header), sizeof(header))) { return false; } return parseTypeFromHeader(header) == ScriptTag::RAMBundle; } bool Instance::isIndexedRAMBundle(std::unique_ptr *script) { BundleHeader header; strncpy( reinterpret_cast(&header), script->get()->c_str(), sizeof(header)); return parseTypeFromHeader(header) == ScriptTag::RAMBundle; } void Instance::loadRAMBundleFromString( std::unique_ptr script, const std::string &sourceURL) { auto bundle = std::make_unique(std::move(script)); auto startupScript = bundle->getStartupCode(); auto registry = RAMBundleRegistry::singleBundleRegistry(std::move(bundle)); loadRAMBundle(std::move(registry), std::move(startupScript), sourceURL, true); } void Instance::loadRAMBundleFromFile( const std::string &sourcePath, const std::string &sourceURL, bool loadSynchronously) { auto bundle = std::make_unique(sourcePath.c_str()); auto startupScript = bundle->getStartupCode(); auto registry = RAMBundleRegistry::multipleBundlesRegistry( std::move(bundle), JSIndexedRAMBundle::buildFactory()); loadRAMBundle( std::move(registry), std::move(startupScript), sourceURL, loadSynchronously); } void Instance::loadRAMBundle( std::unique_ptr bundleRegistry, std::unique_ptr startupScript, std::string startupScriptSourceURL, bool loadSynchronously) { if (loadSynchronously) { loadApplicationSync( std::move(bundleRegistry), std::move(startupScript), std::move(startupScriptSourceURL)); } else { loadApplication( std::move(bundleRegistry), std::move(startupScript), std::move(startupScriptSourceURL)); } } void Instance::setGlobalVariable( std::string propName, std::unique_ptr jsonValue) { nativeToJsBridge_->setGlobalVariable( std::move(propName), std::move(jsonValue)); } void *Instance::getJavaScriptContext() { return nativeToJsBridge_ ? nativeToJsBridge_->getJavaScriptContext() : nullptr; } bool Instance::isInspectable() { return nativeToJsBridge_ ? nativeToJsBridge_->isInspectable() : false; } bool Instance::isBatchActive() { return nativeToJsBridge_ ? nativeToJsBridge_->isBatchActive() : false; } 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)); } void Instance::callJSCallback(uint64_t callbackId, folly::dynamic &¶ms) { SystraceSection s("Instance::callJSCallback"); callback_->incrementPendingJSCalls(); nativeToJsBridge_->invokeCallback((double)callbackId, std::move(params)); } void Instance::registerBundle( uint32_t bundleId, const std::string &bundlePath) { nativeToJsBridge_->registerBundle(bundleId, bundlePath); } const ModuleRegistry &Instance::getModuleRegistry() const { return *moduleRegistry_; } ModuleRegistry &Instance::getModuleRegistry() { return *moduleRegistry_; } void Instance::handleMemoryPressure(int pressureLevel) { nativeToJsBridge_->handleMemoryPressure(pressureLevel); } void Instance::invokeAsync(std::function &&func) { nativeToJsBridge_->runOnExecutorQueue( [func = std::move(func)](JSExecutor *executor) { func(); executor->flush(); }); } } // namespace react } // namespace facebook