Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 31 additions & 17 deletions ReactCommon/cxxreact/BundleRegistry.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,26 +14,39 @@ BundleRegistry::BundleRegistry(JSExecutorFactory* jsExecutorFactory,
}

BundleRegistry::~BundleRegistry() {
bundleExecutionEnvironments_.clear();
bundleEnvironments_.clear();
bundles_.clear();
}

void BundleRegistry::runNewExecutionEnvironment(std::unique_ptr<const Bundle> initialBundle,
std::function<void()> callback) {
void BundleRegistry::preloadEnvironment(std::string environmentId, std::function<void()> callback) {
if (hasEnvironment(environmentId)) {
throw std::runtime_error(
folly::to<std::string>("Environment with id = ", environmentId, " already exists")
);
}
std::shared_ptr<BundleExecutionEnvironment> execEnv = std::make_shared<BundleExecutionEnvironment>();
execEnv->valid = false;
execEnv->jsQueue = jsQueueFactory_();
bundles_.push_back(std::move(initialBundle));
execEnv->initialBundle = std::weak_ptr<const Bundle>(bundles_.back());
bundleExecutionEnvironments_.push_back(std::move(execEnv));
execEnv->initialBundle = std::weak_ptr<const Bundle>();
bundleEnvironments_[environmentId] = std::move(execEnv);

execEnv = bundleExecutionEnvironments_.back();
execEnv = bundleEnvironments_[environmentId];
execEnv->jsQueue->runOnQueueSync([this, execEnv, callback]() mutable {
execEnv->nativeToJsBridge = std::make_unique<NativeToJsBridge>(jsExecutorFactory_,
moduleRegistry_,
execEnv->jsQueue,
callback_);
callback();
});
}

void BundleRegistry::runInPreloadedEnvironment(std::string environmentId,
std::unique_ptr<const Bundle> initialBundle) {
std::shared_ptr<BundleExecutionEnvironment> execEnv = getEnvironment(environmentId).lock();
bundles_.push_back(std::move(initialBundle));
execEnv->initialBundle = std::weak_ptr<const Bundle>(bundles_.back());

execEnv->jsQueue->runOnQueueSync([this, execEnv]() mutable {
auto bundle = execEnv->initialBundle.lock();
if (bundle->getBundleType() == BundleType::FileRAMBundle ||
bundle->getBundleType() == BundleType::IndexedRAMBundle) {
Expand Down Expand Up @@ -67,7 +80,6 @@ void BundleRegistry::runNewExecutionEnvironment(std::unique_ptr<const Bundle> in
}

execEnv->valid = true;
callback();
});
}

Expand All @@ -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::BundleExecutionEnvironment> BundleRegistry::getFirstExecutionEnvironment() {
if (bundleExecutionEnvironments_.size() == 0) {
throw std::runtime_error("Cannot get first BundleExecutionEnvironment");
std::weak_ptr<BundleRegistry::BundleExecutionEnvironment> BundleRegistry::getEnvironment(std::string environmentId) {
if (!hasEnvironment(environmentId)) {
throw std::runtime_error(
folly::to<std::string>("Cannot get environment with id = ", environmentId)
);
}

return std::weak_ptr<BundleExecutionEnvironment>(bundleExecutionEnvironments_[0]);
return std::weak_ptr<BundleExecutionEnvironment>(bundleEnvironments_[environmentId]);
}

bool BundleRegistry::hasExecutionEnvironment() {
return bundleExecutionEnvironments_.size() > 0;
bool BundleRegistry::hasEnvironment(std::string environmentId) {
return bundleEnvironments_.find(environmentId) != bundleEnvironments_.end();
}

} // react
Expand Down
15 changes: 7 additions & 8 deletions ReactCommon/cxxreact/BundleRegistry.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,16 +32,15 @@ class BundleRegistry {
BundleRegistry& operator=(const BundleRegistry&) = delete;
~BundleRegistry();

void runNewExecutionEnvironment(std::unique_ptr<const Bundle> initialBundle,
std::function<void()> callback);
void disposeExecutionEnvironments();
// TODO: get rid of this
std::weak_ptr<BundleExecutionEnvironment> getFirstExecutionEnvironment();
bool hasExecutionEnvironment();
void preloadEnvironment(std::string environmentId, std::function<void()> callback);
void runInPreloadedEnvironment(std::string environmentId, std::unique_ptr<const Bundle> initialBundle);
void disposeEnvironments();

std::weak_ptr<BundleExecutionEnvironment> getEnvironment(std::string environmentId);
bool hasEnvironment(std::string environmentId);

private:
std::vector<std::shared_ptr<BundleExecutionEnvironment>> bundleExecutionEnvironments_;
std::map<std::string, std::shared_ptr<BundleExecutionEnvironment>> bundleEnvironments_;
std::vector<std::shared_ptr<const Bundle>> bundles_;
JSExecutorFactory* jsExecutorFactory_;
std::shared_ptr<ModuleRegistry> moduleRegistry_;
Expand All @@ -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<BundleExecutionEnvironment> execEnv,
std::unique_ptr<const JSBigString> startupScript,
Expand Down
51 changes: 24 additions & 27 deletions ReactCommon/cxxreact/Instance.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ namespace react {

Instance::~Instance() {
if (bundleRegistry_) {
bundleRegistry_->disposeExecutionEnvironments();
bundleRegistry_->disposeEnvironments();
}
}

Expand All @@ -45,29 +45,25 @@ void Instance::initializeBridge(
callback_,
[jsQueue]() { return jsQueue; } // TODO: use a factory
);
bundleRegistry_->preloadEnvironment(defaultEnvironmentId_,[this]() {
std::lock_guard<std::mutex> lock(m_syncMutex);
m_syncReady = true;
m_syncCV.notify_all();
});
}

void Instance::loadBundleAsync(std::unique_ptr<const Bundle> bundle) {
callback_->incrementPendingJSCalls();
SystraceSection s("Instance::loadBundleAsync", "sourceURL", bundle->getSourceURL());
bundleRegistry_->runNewExecutionEnvironment(std::move(bundle), [this]() {
std::lock_guard<std::mutex> lock(m_syncMutex);
m_syncReady = true;
m_syncCV.notify_all();
});
bundleRegistry_->runInPreloadedEnvironment(defaultEnvironmentId_, std::move(bundle));
}

void Instance::loadBundleSync(std::unique_ptr<const Bundle> bundle) {
std::unique_lock<std::mutex> lock(m_syncMutex);
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<std::mutex> lock(m_syncMutex);
m_syncReady = true;
m_syncCV.notify_all();
});
bundleRegistry_->runInPreloadedEnvironment(defaultEnvironmentId_, std::move(bundle));
}

void Instance::loadBundle(std::unique_ptr<const Bundle> bundle, bool loadSynchronously) {
Expand All @@ -81,17 +77,17 @@ void Instance::loadBundle(std::unique_ptr<const Bundle> bundle, bool loadSynchro

void Instance::setGlobalVariable(std::string propName,
std::unique_ptr<const JSBigString> 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;
}
}
Expand All @@ -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;
}
}
Expand All @@ -110,34 +106,35 @@ 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;
}
}

return false;
}

void Instance::callJSFunction(std::string &&module, std::string &&method,
void Instance::callJSFunction(std::string &&module,
std::string &&method,
folly::dynamic &&params) {
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 &&params) {
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");
}
}

Expand All @@ -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");
}
}

Expand Down
2 changes: 2 additions & 0 deletions ReactCommon/cxxreact/Instance.h
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,8 @@ class RN_EXPORT Instance {
std::shared_ptr<ModuleRegistry> moduleRegistry_;
std::unique_ptr<BundleRegistry> bundleRegistry_;

std::string defaultEnvironmentId_ = "default";

std::mutex m_syncMutex;
std::condition_variable m_syncCV;
bool m_syncReady = false;
Expand Down