diff --git a/ReactCommon/cxxreact/BundleRegistry.cpp b/ReactCommon/cxxreact/BundleRegistry.cpp index 24cb490653a3..d217614e8fe3 100644 --- a/ReactCommon/cxxreact/BundleRegistry.cpp +++ b/ReactCommon/cxxreact/BundleRegistry.cpp @@ -14,26 +14,39 @@ BundleRegistry::BundleRegistry(JSExecutorFactory* jsExecutorFactory, } BundleRegistry::~BundleRegistry() { - bundleExecutionEnvironments_.clear(); + bundleEnvironments_.clear(); bundles_.clear(); } -void BundleRegistry::runNewExecutionEnvironment(std::unique_ptr initialBundle, - std::function callback) { +void BundleRegistry::preloadEnvironment(std::string environmentId, std::function callback) { + if (hasEnvironment(environmentId)) { + throw std::runtime_error( + folly::to("Environment with id = ", environmentId, " already exists") + ); + } std::shared_ptr execEnv = std::make_shared(); execEnv->valid = false; execEnv->jsQueue = jsQueueFactory_(); - bundles_.push_back(std::move(initialBundle)); - execEnv->initialBundle = std::weak_ptr(bundles_.back()); - bundleExecutionEnvironments_.push_back(std::move(execEnv)); + execEnv->initialBundle = std::weak_ptr(); + bundleEnvironments_[environmentId] = std::move(execEnv); - execEnv = bundleExecutionEnvironments_.back(); + execEnv = bundleEnvironments_[environmentId]; execEnv->jsQueue->runOnQueueSync([this, execEnv, callback]() mutable { execEnv->nativeToJsBridge = std::make_unique(jsExecutorFactory_, moduleRegistry_, execEnv->jsQueue, callback_); + callback(); + }); +} +void BundleRegistry::runInPreloadedEnvironment(std::string environmentId, + std::unique_ptr initialBundle) { + std::shared_ptr execEnv = getEnvironment(environmentId).lock(); + bundles_.push_back(std::move(initialBundle)); + execEnv->initialBundle = std::weak_ptr(bundles_.back()); + + execEnv->jsQueue->runOnQueueSync([this, execEnv]() mutable { auto bundle = execEnv->initialBundle.lock(); if (bundle->getBundleType() == BundleType::FileRAMBundle || bundle->getBundleType() == BundleType::IndexedRAMBundle) { @@ -67,7 +80,6 @@ void BundleRegistry::runNewExecutionEnvironment(std::unique_ptr in } execEnv->valid = true; - callback(); }); } @@ -88,22 +100,24 @@ BundleRegistry::LoadBundleLambda BundleRegistry::makeLoadBundleLambda() { }; } -void BundleRegistry::disposeExecutionEnvironments() { - for (auto execEnv : bundleExecutionEnvironments_) { - execEnv->nativeToJsBridge->destroy(); +void BundleRegistry::disposeEnvironments() { + for (auto environment : bundleEnvironments_) { + environment.second->nativeToJsBridge->destroy(); } } -std::weak_ptr BundleRegistry::getFirstExecutionEnvironment() { - if (bundleExecutionEnvironments_.size() == 0) { - throw std::runtime_error("Cannot get first BundleExecutionEnvironment"); +std::weak_ptr BundleRegistry::getEnvironment(std::string environmentId) { + if (!hasEnvironment(environmentId)) { + throw std::runtime_error( + folly::to("Cannot get environment with id = ", environmentId) + ); } - return std::weak_ptr(bundleExecutionEnvironments_[0]); + return std::weak_ptr(bundleEnvironments_[environmentId]); } -bool BundleRegistry::hasExecutionEnvironment() { - return bundleExecutionEnvironments_.size() > 0; +bool BundleRegistry::hasEnvironment(std::string environmentId) { + return bundleEnvironments_.find(environmentId) != bundleEnvironments_.end(); } } // react diff --git a/ReactCommon/cxxreact/BundleRegistry.h b/ReactCommon/cxxreact/BundleRegistry.h index cd24e31f51ca..7d67c67b245c 100644 --- a/ReactCommon/cxxreact/BundleRegistry.h +++ b/ReactCommon/cxxreact/BundleRegistry.h @@ -32,16 +32,15 @@ class BundleRegistry { BundleRegistry& operator=(const BundleRegistry&) = delete; ~BundleRegistry(); - void runNewExecutionEnvironment(std::unique_ptr initialBundle, - std::function callback); - void disposeExecutionEnvironments(); - // TODO: get rid of this - std::weak_ptr getFirstExecutionEnvironment(); - bool hasExecutionEnvironment(); + void preloadEnvironment(std::string environmentId, std::function callback); + void runInPreloadedEnvironment(std::string environmentId, std::unique_ptr initialBundle); + void disposeEnvironments(); + std::weak_ptr getEnvironment(std::string environmentId); + bool hasEnvironment(std::string environmentId); private: - std::vector> bundleExecutionEnvironments_; + std::map> bundleEnvironments_; std::vector> bundles_; JSExecutorFactory* jsExecutorFactory_; std::shared_ptr moduleRegistry_; @@ -50,7 +49,7 @@ class BundleRegistry { /** * Setup environment and load initial bundle. Should be called only once - * per BundleExecutionEnvironemnt. + * per BundleEnvironemnt. */ void evalInitialBundle(std::shared_ptr execEnv, std::unique_ptr startupScript, diff --git a/ReactCommon/cxxreact/Instance.cpp b/ReactCommon/cxxreact/Instance.cpp index 0fd1fb3b384f..db9a0c75235d 100644 --- a/ReactCommon/cxxreact/Instance.cpp +++ b/ReactCommon/cxxreact/Instance.cpp @@ -28,7 +28,7 @@ namespace react { Instance::~Instance() { if (bundleRegistry_) { - bundleRegistry_->disposeExecutionEnvironments(); + bundleRegistry_->disposeEnvironments(); } } @@ -45,16 +45,17 @@ void Instance::initializeBridge( callback_, [jsQueue]() { return jsQueue; } // TODO: use a factory ); + bundleRegistry_->preloadEnvironment(defaultEnvironmentId_,[this]() { + std::lock_guard lock(m_syncMutex); + m_syncReady = true; + m_syncCV.notify_all(); + }); } void Instance::loadBundleAsync(std::unique_ptr bundle) { callback_->incrementPendingJSCalls(); SystraceSection s("Instance::loadBundleAsync", "sourceURL", bundle->getSourceURL()); - bundleRegistry_->runNewExecutionEnvironment(std::move(bundle), [this]() { - std::lock_guard lock(m_syncMutex); - m_syncReady = true; - m_syncCV.notify_all(); - }); + bundleRegistry_->runInPreloadedEnvironment(defaultEnvironmentId_, std::move(bundle)); } void Instance::loadBundleSync(std::unique_ptr bundle) { @@ -62,12 +63,7 @@ void Instance::loadBundleSync(std::unique_ptr bundle) { m_syncCV.wait(lock, [this] { return m_syncReady; }); SystraceSection s("Instance::loadBundleSync", "sourceURL", bundle->getSourceURL()); - bundleRegistry_->runNewExecutionEnvironment(std::move(bundle), [this]() { - // TODO: check if this is needed at all - std::lock_guard lock(m_syncMutex); - m_syncReady = true; - m_syncCV.notify_all(); - }); + bundleRegistry_->runInPreloadedEnvironment(defaultEnvironmentId_, std::move(bundle)); } void Instance::loadBundle(std::unique_ptr bundle, bool loadSynchronously) { @@ -81,17 +77,17 @@ void Instance::loadBundle(std::unique_ptr bundle, bool loadSynchro void Instance::setGlobalVariable(std::string propName, std::unique_ptr jsonValue) { - if (auto execEnv = bundleRegistry_->getFirstExecutionEnvironment().lock()) { + if (auto execEnv = bundleRegistry_->getEnvironment(defaultEnvironmentId_).lock()) { execEnv->nativeToJsBridge->setGlobalVariable(std::move(propName), std::move(jsonValue)); } else { - throw std::runtime_error("BundleExecutionEnvironment pointer is invalid"); + throw std::runtime_error("BundleEnvironment pointer is invalid"); } } void* Instance::getJavaScriptContext() { - if (bundleRegistry_->hasExecutionEnvironment()) { - if (auto execEnv = bundleRegistry_->getFirstExecutionEnvironment().lock()) { + if (bundleRegistry_->hasEnvironment(defaultEnvironmentId_)) { + if (auto execEnv = bundleRegistry_->getEnvironment(defaultEnvironmentId_).lock()) { return execEnv->nativeToJsBridge ? execEnv->nativeToJsBridge->getJavaScriptContext() : nullptr; } } @@ -100,8 +96,8 @@ void* Instance::getJavaScriptContext() { } bool Instance::isInspectable() { - if (bundleRegistry_->hasExecutionEnvironment()) { - if (auto execEnv = bundleRegistry_->getFirstExecutionEnvironment().lock()) { + if (bundleRegistry_->hasEnvironment(defaultEnvironmentId_)) { + if (auto execEnv = bundleRegistry_->getEnvironment(defaultEnvironmentId_).lock()) { return execEnv->nativeToJsBridge ? execEnv->nativeToJsBridge->isInspectable() : false; } } @@ -110,8 +106,8 @@ bool Instance::isInspectable() { } bool Instance::isBatchActive() { - if (bundleRegistry_->hasExecutionEnvironment()) { - if (auto execEnv = bundleRegistry_->getFirstExecutionEnvironment().lock()) { + if (bundleRegistry_->hasEnvironment(defaultEnvironmentId_)) { + if (auto execEnv = bundleRegistry_->getEnvironment(defaultEnvironmentId_).lock()) { return execEnv->nativeToJsBridge ? execEnv->nativeToJsBridge->isBatchActive() : false; } } @@ -119,25 +115,26 @@ bool Instance::isBatchActive() { return false; } -void Instance::callJSFunction(std::string &&module, std::string &&method, +void Instance::callJSFunction(std::string &&module, + std::string &&method, folly::dynamic &¶ms) { callback_->incrementPendingJSCalls(); - if (auto execEnv = bundleRegistry_->getFirstExecutionEnvironment().lock()) { + if (auto execEnv = bundleRegistry_->getEnvironment(defaultEnvironmentId_).lock()) { execEnv->nativeToJsBridge->callFunction(std::move(module), std::move(method), std::move(params)); } else { - throw std::runtime_error("BundleExecutionEnvironment pointer is invalid"); + throw std::runtime_error("BundleEnvironment pointer is invalid"); } } void Instance::callJSCallback(uint64_t callbackId, folly::dynamic &¶ms) { SystraceSection s("Instance::callJSCallback"); callback_->incrementPendingJSCalls(); - if (auto execEnv = bundleRegistry_->getFirstExecutionEnvironment().lock()) { + if (auto execEnv = bundleRegistry_->getEnvironment(defaultEnvironmentId_).lock()) { execEnv->nativeToJsBridge->invokeCallback((double)callbackId, std::move(params)); } else { - throw std::runtime_error("BundleExecutionEnvironment pointer is invalid"); + throw std::runtime_error("BundleEnvironment pointer is invalid"); } } @@ -148,10 +145,10 @@ const ModuleRegistry &Instance::getModuleRegistry() const { ModuleRegistry &Instance::getModuleRegistry() { return *moduleRegistry_; } void Instance::handleMemoryPressure(int pressureLevel) { - if (auto execEnv = bundleRegistry_->getFirstExecutionEnvironment().lock()) { + if (auto execEnv = bundleRegistry_->getEnvironment(defaultEnvironmentId_).lock()) { execEnv->nativeToJsBridge->handleMemoryPressure(pressureLevel); } else { - throw std::runtime_error("BundleExecutionEnvironment pointer is invalid"); + throw std::runtime_error("BundleEnvironment pointer is invalid"); } } diff --git a/ReactCommon/cxxreact/Instance.h b/ReactCommon/cxxreact/Instance.h index f03f45e6a834..50474a0f8228 100644 --- a/ReactCommon/cxxreact/Instance.h +++ b/ReactCommon/cxxreact/Instance.h @@ -68,6 +68,8 @@ class RN_EXPORT Instance { std::shared_ptr moduleRegistry_; std::unique_ptr bundleRegistry_; + std::string defaultEnvironmentId_ = "default"; + std::mutex m_syncMutex; std::condition_variable m_syncCV; bool m_syncReady = false;