From 6071e8ca2c3e9c8fa54289a55f269b529272e036 Mon Sep 17 00:00:00 2001 From: Marc Horowitz Date: Mon, 26 Sep 2016 16:01:42 -0700 Subject: [PATCH] Support sync loading of the initial bundle/source Reviewed By: javache Differential Revision: D3897521 fbshipit-source-id: a4f234c7003a5f4be952d315eb62f382836e24dc --- ReactCommon/cxxreact/Instance.cpp | 24 ++++++++++++++++++++++- ReactCommon/cxxreact/Instance.h | 10 ++++++++++ ReactCommon/cxxreact/NativeToJsBridge.cpp | 11 +++++++++++ ReactCommon/cxxreact/NativeToJsBridge.h | 13 +++++++++--- 4 files changed, 54 insertions(+), 4 deletions(-) diff --git a/ReactCommon/cxxreact/Instance.cpp b/ReactCommon/cxxreact/Instance.cpp index 42ddd74ee..34311d130 100644 --- a/ReactCommon/cxxreact/Instance.cpp +++ b/ReactCommon/cxxreact/Instance.cpp @@ -39,6 +39,10 @@ void Instance::initializeBridge( nativeQueue=folly::makeMoveWrapper(std::move(nativeQueue))] () mutable { nativeToJsBridge_ = folly::make_unique( jsef.get(), moduleRegistry, jsQueue, nativeQueue.move(), callback_); + + std::lock_guard lock(m_syncMutex); + m_syncReady = true; + m_syncCV.notify_all(); }); CHECK(nativeToJsBridge_); @@ -52,6 +56,14 @@ void Instance::loadScriptFromString(std::unique_ptr string, nativeToJsBridge_->loadApplication(nullptr, std::move(string), std::move(sourceURL)); } +void Instance::loadScriptFromStringSync(std::unique_ptr string, + std::string sourceURL) { + std::unique_lock lock(m_syncMutex); + m_syncCV.wait(lock, [this] { return m_syncReady; }); + + nativeToJsBridge_->loadApplicationSync(nullptr, std::move(string), std::move(sourceURL)); +} + void Instance::loadScriptFromFile(const std::string& filename, const std::string& sourceURL) { // TODO mhorowitz: ReactMarker around file read @@ -88,11 +100,21 @@ void Instance::loadUnbundle(std::unique_ptr unbundle, std::unique_ptr startupScript, std::string startupScriptSourceURL) { callback_->incrementPendingJSCalls(); - SystraceSection s("reactbridge_xplat_setJSModulesUnbundle"); nativeToJsBridge_->loadApplication(std::move(unbundle), std::move(startupScript), std::move(startupScriptSourceURL)); } +void Instance::loadUnbundleSync(std::unique_ptr unbundle, + std::unique_ptr startupScript, + std::string startupScriptSourceURL) { + std::unique_lock lock(m_syncMutex); + m_syncCV.wait(lock, [this] { return m_syncReady; }); + + SystraceSection s("reactbridge_xplat_loadApplicationSync"); + nativeToJsBridge_->loadApplicationSync(std::move(unbundle), std::move(startupScript), + std::move(startupScriptSourceURL)); +} + bool Instance::supportsProfiling() { return nativeToJsBridge_->supportsProfiling(); } diff --git a/ReactCommon/cxxreact/Instance.h b/ReactCommon/cxxreact/Instance.h index efc1a3a36..2a6035659 100644 --- a/ReactCommon/cxxreact/Instance.h +++ b/ReactCommon/cxxreact/Instance.h @@ -35,12 +35,17 @@ class Instance { std::unique_ptr nativeQueue, std::shared_ptr moduleRegistry); void loadScriptFromString(std::unique_ptr string, std::string sourceURL); + void loadScriptFromStringSync(std::unique_ptr string, std::string sourceURL); void loadScriptFromFile(const std::string& filename, const std::string& sourceURL); void loadScriptFromOptimizedBundle(std::string bundlePath, std::string sourceURL, int flags); void loadUnbundle( std::unique_ptr unbundle, std::unique_ptr startupScript, std::string startupScriptSourceURL); + void loadUnbundleSync( + std::unique_ptr unbundle, + std::unique_ptr startupScript, + std::string startupScriptSourceURL); bool supportsProfiling(); void startProfiler(const std::string& title); void stopProfiler(const std::string& title, const std::string& filename); @@ -50,6 +55,7 @@ class Instance { void callJSCallback(ExecutorToken token, uint64_t callbackId, folly::dynamic&& params); MethodCallResult callSerializableNativeHook(ExecutorToken token, unsigned int moduleId, unsigned int methodId, folly::dynamic&& args); + ExecutorToken getMainExecutorToken(); void handleMemoryPressureUiHidden(); void handleMemoryPressureModerate(); @@ -60,6 +66,10 @@ class Instance { std::shared_ptr callback_; std::unique_ptr nativeToJsBridge_; + + std::mutex m_syncMutex; + std::condition_variable m_syncCV; + bool m_syncReady = false; }; } diff --git a/ReactCommon/cxxreact/NativeToJsBridge.cpp b/ReactCommon/cxxreact/NativeToJsBridge.cpp index 00fa82829..ad7ce7b28 100644 --- a/ReactCommon/cxxreact/NativeToJsBridge.cpp +++ b/ReactCommon/cxxreact/NativeToJsBridge.cpp @@ -152,6 +152,17 @@ void NativeToJsBridge::loadApplication( }); } +void NativeToJsBridge::loadApplicationSync( + std::unique_ptr unbundle, + std::unique_ptr startupScript, + std::string startupScriptSourceURL) { + if (unbundle) { + m_mainExecutor->setJSModulesUnbundle(std::move(unbundle)); + } + m_mainExecutor->loadApplicationScript(std::move(startupScript), + std::move(startupScriptSourceURL)); +} + void NativeToJsBridge::callFunction( ExecutorToken executorToken, std::string&& module, diff --git a/ReactCommon/cxxreact/NativeToJsBridge.h b/ReactCommon/cxxreact/NativeToJsBridge.h index 429291375..6deb038e5 100644 --- a/ReactCommon/cxxreact/NativeToJsBridge.h +++ b/ReactCommon/cxxreact/NativeToJsBridge.h @@ -44,9 +44,12 @@ public: class JsToNativeBridge; // This class manages calls from native code to JS. It also manages -// executors and their threads. This part is used by both bridges for -// now, but further refactorings should separate the bridges more -// fully #11247981. +// executors and their threads. All functions here can be called from +// any thread. +// +// Except for loadApplicationScriptSync(), all void methods will queue +// work to run on the jsQueue passed to the ctor, and return +// immediately. class NativeToJsBridge { public: friend class JsToNativeBridge; @@ -86,6 +89,10 @@ public: std::unique_ptr unbundle, std::unique_ptr startupCode, std::string sourceURL); + void loadApplicationSync( + std::unique_ptr unbundle, + std::unique_ptr startupCode, + std::string sourceURL); /** * Similar to loading a "bundle", but instead of passing js source this method accepts