From cff0d8e0e599d1ab21b36779b41fbb26512874aa Mon Sep 17 00:00:00 2001 From: Alex Dvornikov Date: Thu, 9 Nov 2017 11:55:37 -0800 Subject: [PATCH] Register split segment paths with RAMBundleRegistry Differential Revision: D6284466 fbshipit-source-id: c80cf929af38f92f06cca5b366c58785ae992d83 --- React/CxxBridge/RCTCxxBridge.mm | 2 +- React/CxxBridge/RCTObjcExecutor.mm | 4 ++++ .../main/jni/react/jni/CatalystInstanceImpl.cpp | 2 +- .../src/main/jni/react/jni/ProxyExecutor.cpp | 6 ++++++ .../src/main/jni/react/jni/ProxyExecutor.h | 2 ++ ReactCommon/cxxreact/Instance.cpp | 4 ++++ ReactCommon/cxxreact/Instance.h | 3 +++ ReactCommon/cxxreact/JSCExecutor.cpp | 6 ++++++ ReactCommon/cxxreact/JSCExecutor.h | 1 + ReactCommon/cxxreact/JSExecutor.h | 5 +++++ ReactCommon/cxxreact/JSIndexedRAMBundle.cpp | 7 +++---- ReactCommon/cxxreact/JSIndexedRAMBundle.h | 2 +- ReactCommon/cxxreact/NativeToJsBridge.cpp | 6 ++++++ ReactCommon/cxxreact/NativeToJsBridge.h | 1 + ReactCommon/cxxreact/RAMBundleRegistry.cpp | 15 ++++++++++++--- ReactCommon/cxxreact/RAMBundleRegistry.h | 9 ++++++--- 16 files changed, 62 insertions(+), 13 deletions(-) diff --git a/React/CxxBridge/RCTCxxBridge.mm b/React/CxxBridge/RCTCxxBridge.mm index 871bc4607..b5ce3026b 100644 --- a/React/CxxBridge/RCTCxxBridge.mm +++ b/React/CxxBridge/RCTCxxBridge.mm @@ -1152,7 +1152,7 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithBundleURL:(__unused NSURL *)bundleUR ? [[self.delegate jsSegmentsDirectory].path stringByAppendingString:@"/"] : nil; auto registry = jsSegmentsDirectory != nil - ? RAMBundleRegistry::multipleBundlesRegistry(std::move(ramBundle), JSIndexedRAMBundle::buildFactory(jsSegmentsDirectory.UTF8String)) + ? RAMBundleRegistry::multipleBundlesRegistry(std::move(ramBundle), JSIndexedRAMBundle::buildFactory()) : RAMBundleRegistry::singleBundleRegistry(std::move(ramBundle)); self->_reactInstance->loadRAMBundle(std::move(registry), std::move(scriptStr), sourceUrlStr.UTF8String, !async); diff --git a/React/CxxBridge/RCTObjcExecutor.mm b/React/CxxBridge/RCTObjcExecutor.mm index 53c32368d..476bcff9b 100644 --- a/React/CxxBridge/RCTObjcExecutor.mm +++ b/React/CxxBridge/RCTObjcExecutor.mm @@ -95,6 +95,10 @@ public: RCTAssert(NO, @"RAM bundles are not supported in RCTObjcExecutor"); } + void registerBundle(uint32_t bundleId, const std::string &bundlePath) override { + RCTAssert(NO, @"RAM bundles are not supported in RCTObjcExecutor"); + } + void callFunction(const std::string &module, const std::string &method, const folly::dynamic &arguments) override { [m_jse callFunctionOnModule:@(module.c_str()) diff --git a/ReactAndroid/src/main/jni/react/jni/CatalystInstanceImpl.cpp b/ReactAndroid/src/main/jni/react/jni/CatalystInstanceImpl.cpp index 3bcc53aa8..4ca32b7b9 100644 --- a/ReactAndroid/src/main/jni/react/jni/CatalystInstanceImpl.cpp +++ b/ReactAndroid/src/main/jni/react/jni/CatalystInstanceImpl.cpp @@ -212,7 +212,7 @@ void CatalystInstanceImpl::jniLoadScriptFromFile(const std::string& fileName, auto script = bundle->getStartupCode(); auto registry = jsSegmentsDirectory_.empty() ? RAMBundleRegistry::singleBundleRegistry(std::move(bundle)) - : RAMBundleRegistry::multipleBundlesRegistry(std::move(bundle), JSIndexedRAMBundle::buildFactory(jsSegmentsDirectory_)); + : RAMBundleRegistry::multipleBundlesRegistry(std::move(bundle), JSIndexedRAMBundle::buildFactory()); instance_->loadRAMBundle( std::move(registry), std::move(script), diff --git a/ReactAndroid/src/main/jni/react/jni/ProxyExecutor.cpp b/ReactAndroid/src/main/jni/react/jni/ProxyExecutor.cpp index d79f4f96d..1b9395cea 100644 --- a/ReactAndroid/src/main/jni/react/jni/ProxyExecutor.cpp +++ b/ReactAndroid/src/main/jni/react/jni/ProxyExecutor.cpp @@ -90,6 +90,12 @@ void ProxyExecutor::setBundleRegistry(std::unique_ptr) { "Loading application RAM bundles is not supported for proxy executors"); } +void ProxyExecutor::registerBundle(uint32_t bundleId, const std::string& bundlePath) { + jni::throwNewJavaException( + "java/lang/UnsupportedOperationException", + "Loading application RAM bundles is not supported for proxy executors"); +} + void ProxyExecutor::callFunction(const std::string& moduleId, const std::string& methodId, const folly::dynamic& arguments) { auto call = folly::dynamic::array(moduleId, methodId, std::move(arguments)); diff --git a/ReactAndroid/src/main/jni/react/jni/ProxyExecutor.h b/ReactAndroid/src/main/jni/react/jni/ProxyExecutor.h index 30758073a..b77d35f63 100644 --- a/ReactAndroid/src/main/jni/react/jni/ProxyExecutor.h +++ b/ReactAndroid/src/main/jni/react/jni/ProxyExecutor.h @@ -37,6 +37,8 @@ public: std::string sourceURL) override; virtual void setBundleRegistry( std::unique_ptr bundle) override; + virtual void registerBundle( + uint32_t bundleId, const std::string& bundlePath) override; virtual void callFunction( const std::string& moduleId, const std::string& methodId, diff --git a/ReactCommon/cxxreact/Instance.cpp b/ReactCommon/cxxreact/Instance.cpp index 271dc8581..bdf1fce1e 100644 --- a/ReactCommon/cxxreact/Instance.cpp +++ b/ReactCommon/cxxreact/Instance.cpp @@ -156,6 +156,10 @@ void Instance::callJSCallback(uint64_t callbackId, folly::dynamic &¶ms) { 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_; } diff --git a/ReactCommon/cxxreact/Instance.h b/ReactCommon/cxxreact/Instance.h index 6999fb60d..d04bcb356 100644 --- a/ReactCommon/cxxreact/Instance.h +++ b/ReactCommon/cxxreact/Instance.h @@ -59,6 +59,9 @@ public: folly::dynamic &¶ms); void callJSCallback(uint64_t callbackId, folly::dynamic &¶ms); + // This method is experimental, and may be modified or removed. + void registerBundle(uint32_t bundleId, const std::string& bundlePath); + // This method is experimental, and may be modified or removed. template Value callFunctionSync(const std::string &module, const std::string &method, diff --git a/ReactCommon/cxxreact/JSCExecutor.cpp b/ReactCommon/cxxreact/JSCExecutor.cpp index 3dfe2db47..0b66c8c3c 100644 --- a/ReactCommon/cxxreact/JSCExecutor.cpp +++ b/ReactCommon/cxxreact/JSCExecutor.cpp @@ -458,6 +458,12 @@ namespace facebook { m_bundleRegistry = std::move(bundleRegistry); } + void JSCExecutor::registerBundle(uint32_t bundleId, const std::string& bundlePath) { + if (m_bundleRegistry) { + m_bundleRegistry->registerBundle(bundleId, bundlePath); + } + } + void JSCExecutor::bindBridge() throw(JSException) { SystraceSection s("JSCExecutor::bindBridge"); std::call_once(m_bindFlag, [this] { diff --git a/ReactCommon/cxxreact/JSCExecutor.h b/ReactCommon/cxxreact/JSCExecutor.h index f2dc8c61e..c646677d6 100644 --- a/ReactCommon/cxxreact/JSCExecutor.h +++ b/ReactCommon/cxxreact/JSCExecutor.h @@ -66,6 +66,7 @@ public: std::string sourceURL) override; virtual void setBundleRegistry(std::unique_ptr bundleRegistry) override; + virtual void registerBundle(uint32_t bundleId, const std::string& bundlePath) override; virtual void callFunction( const std::string& moduleId, diff --git a/ReactCommon/cxxreact/JSExecutor.h b/ReactCommon/cxxreact/JSExecutor.h index b8cc3d3f1..83f9e1534 100644 --- a/ReactCommon/cxxreact/JSExecutor.h +++ b/ReactCommon/cxxreact/JSExecutor.h @@ -53,6 +53,11 @@ public: */ virtual void setBundleRegistry(std::unique_ptr bundleRegistry) = 0; + /** + * Register a file path for an additional "RAM" bundle + */ + virtual void registerBundle(uint32_t bundleId, const std::string& bundlePath) = 0; + /** * Executes BatchedBridge.callFunctionReturnFlushedQueue with the module ID, * method ID and optional additional arguments in JS. The executor is responsible diff --git a/ReactCommon/cxxreact/JSIndexedRAMBundle.cpp b/ReactCommon/cxxreact/JSIndexedRAMBundle.cpp index 516720485..b5db5203f 100644 --- a/ReactCommon/cxxreact/JSIndexedRAMBundle.cpp +++ b/ReactCommon/cxxreact/JSIndexedRAMBundle.cpp @@ -9,10 +9,9 @@ namespace facebook { namespace react { -std::function(uint32_t)> JSIndexedRAMBundle::buildFactory(const std::string& baseDirectoryPath) { - return [baseDirectoryPath](uint32_t index){ - std::string bundlePathById = baseDirectoryPath + toString(index) + ".jsbundle"; - return folly::make_unique(bundlePathById.c_str()); +std::function(std::string)> JSIndexedRAMBundle::buildFactory() { + return [](const std::string& bundlePath){ + return folly::make_unique(bundlePath.c_str()); }; } diff --git a/ReactCommon/cxxreact/JSIndexedRAMBundle.h b/ReactCommon/cxxreact/JSIndexedRAMBundle.h index 3d4341b4a..646797727 100644 --- a/ReactCommon/cxxreact/JSIndexedRAMBundle.h +++ b/ReactCommon/cxxreact/JSIndexedRAMBundle.h @@ -17,7 +17,7 @@ namespace react { class RN_EXPORT JSIndexedRAMBundle : public JSModulesUnbundle { public: - static std::function(uint32_t)> buildFactory(const std::string& baseDirectoryPath); + static std::function(std::string)> buildFactory(); // Throws std::runtime_error on failure. JSIndexedRAMBundle(const char *sourceURL); diff --git a/ReactCommon/cxxreact/NativeToJsBridge.cpp b/ReactCommon/cxxreact/NativeToJsBridge.cpp index 3f1f78c83..51bad86f7 100644 --- a/ReactCommon/cxxreact/NativeToJsBridge.cpp +++ b/ReactCommon/cxxreact/NativeToJsBridge.cpp @@ -171,6 +171,12 @@ void NativeToJsBridge::invokeCallback(double callbackId, folly::dynamic&& argume }); } +void NativeToJsBridge::registerBundle(uint32_t bundleId, const std::string& bundlePath) { + runOnExecutorQueue([bundleId, bundlePath] (JSExecutor* executor) { + executor->registerBundle(bundleId, bundlePath); + }); +} + void NativeToJsBridge::setGlobalVariable(std::string propName, std::unique_ptr jsonValue) { runOnExecutorQueue([propName=std::move(propName), jsonValue=folly::makeMoveWrapper(std::move(jsonValue))] diff --git a/ReactCommon/cxxreact/NativeToJsBridge.h b/ReactCommon/cxxreact/NativeToJsBridge.h index dee12b6e3..093707f2e 100644 --- a/ReactCommon/cxxreact/NativeToJsBridge.h +++ b/ReactCommon/cxxreact/NativeToJsBridge.h @@ -98,6 +98,7 @@ public: std::unique_ptr startupCode, std::string sourceURL); + void registerBundle(uint32_t bundleId, const std::string& bundlePath); void setGlobalVariable(std::string propName, std::unique_ptr jsonValue); void* getJavaScriptContext(); diff --git a/ReactCommon/cxxreact/RAMBundleRegistry.cpp b/ReactCommon/cxxreact/RAMBundleRegistry.cpp index 896eeb5f6..635875b3b 100644 --- a/ReactCommon/cxxreact/RAMBundleRegistry.cpp +++ b/ReactCommon/cxxreact/RAMBundleRegistry.cpp @@ -16,21 +16,30 @@ std::unique_ptr RAMBundleRegistry::singleBundleRegistry(std:: return std::unique_ptr(registry); } -std::unique_ptr RAMBundleRegistry::multipleBundlesRegistry(std::unique_ptr mainBundle, std::function(uint32_t)> factory) { +std::unique_ptr RAMBundleRegistry::multipleBundlesRegistry(std::unique_ptr mainBundle, std::function(std::string)> factory) { RAMBundleRegistry *registry = new RAMBundleRegistry(std::move(mainBundle), std::move(factory)); return std::unique_ptr(registry); } -RAMBundleRegistry::RAMBundleRegistry(std::unique_ptr mainBundle, std::function(uint32_t)> factory): m_factory(factory) { +RAMBundleRegistry::RAMBundleRegistry(std::unique_ptr mainBundle, std::function(std::string)> factory): m_factory(factory) { m_bundles.emplace(MAIN_BUNDLE_ID, std::move(mainBundle)); } +void RAMBundleRegistry::registerBundle(uint32_t bundleId, std::string bundlePath) { + m_bundlePaths.emplace(bundleId, bundlePath); +} + JSModulesUnbundle::Module RAMBundleRegistry::getModule(uint32_t bundleId, uint32_t moduleId) { if (m_bundles.find(bundleId) == m_bundles.end()) { if (!m_factory) { throw std::runtime_error("You need to register factory function in order to support multiple RAM bundles."); } - m_bundles.emplace(bundleId, m_factory(bundleId)); + + auto bundlePath = m_bundlePaths.find(bundleId); + if (bundlePath == m_bundlePaths.end()) { + throw std::runtime_error("In order to fetch RAM bundle from the registry, its file path needs to be registered first."); + } + m_bundles.emplace(bundleId, m_factory(bundlePath->second)); } return getBundle(bundleId)->getModule(moduleId); diff --git a/ReactCommon/cxxreact/RAMBundleRegistry.h b/ReactCommon/cxxreact/RAMBundleRegistry.h index cb845a475..2d628f22c 100644 --- a/ReactCommon/cxxreact/RAMBundleRegistry.h +++ b/ReactCommon/cxxreact/RAMBundleRegistry.h @@ -21,21 +21,24 @@ namespace react { class RN_EXPORT RAMBundleRegistry : noncopyable { public: using unique_ram_bundle = std::unique_ptr; + using bundle_path = std::string; constexpr static uint32_t MAIN_BUNDLE_ID = 0; static std::unique_ptr singleBundleRegistry(unique_ram_bundle mainBundle); - static std::unique_ptr multipleBundlesRegistry(unique_ram_bundle mainBundle, std::function factory); + static std::unique_ptr multipleBundlesRegistry(unique_ram_bundle mainBundle, std::function factory); RAMBundleRegistry(RAMBundleRegistry&&) = default; RAMBundleRegistry& operator=(RAMBundleRegistry&&) = default; + void registerBundle(uint32_t bundleId, bundle_path bundlePath); JSModulesUnbundle::Module getModule(uint32_t bundleId, uint32_t moduleId); virtual ~RAMBundleRegistry() {}; private: - explicit RAMBundleRegistry(unique_ram_bundle mainBundle, std::function factory = {}); + explicit RAMBundleRegistry(unique_ram_bundle mainBundle, std::function factory = {}); JSModulesUnbundle *getBundle(uint32_t bundleId) const; - std::function m_factory; + std::function m_factory; + std::unordered_map m_bundlePaths; std::unordered_map m_bundles; };