diff --git a/React/CxxBridge/RCTCxxBridge.mm b/React/CxxBridge/RCTCxxBridge.mm index 871bc46071c255..b5ce3026b2553a 100644 --- a/React/CxxBridge/RCTCxxBridge.mm +++ b/React/CxxBridge/RCTCxxBridge.mm @@ -1152,7 +1152,7 @@ - (void)executeApplicationScript:(NSData *)script ? [[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 53c32368d5b15e..476bcff9b40709 100644 --- a/React/CxxBridge/RCTObjcExecutor.mm +++ b/React/CxxBridge/RCTObjcExecutor.mm @@ -95,6 +95,10 @@ void setBundleRegistry(std::unique_ptr) override { 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 3bcc53aa8318e9..4ca32b7b9c44b5 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 d79f4f96d6e30c..1b9395ceae4c9f 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 30758073a79eef..b77d35f63745cd 100644 --- a/ReactAndroid/src/main/jni/react/jni/ProxyExecutor.h +++ b/ReactAndroid/src/main/jni/react/jni/ProxyExecutor.h @@ -37,6 +37,8 @@ class ProxyExecutor : public JSExecutor { 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 271dc85815d291..bdf1fce1eee280 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 6999fb60de1edc..d04bcb3563721c 100644 --- a/ReactCommon/cxxreact/Instance.h +++ b/ReactCommon/cxxreact/Instance.h @@ -59,6 +59,9 @@ class RN_EXPORT Instance { 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 3dfe2db47257d4..0b66c8c3c6da8f 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 f2dc8c61ed571d..c646677d6022c4 100644 --- a/ReactCommon/cxxreact/JSCExecutor.h +++ b/ReactCommon/cxxreact/JSCExecutor.h @@ -66,6 +66,7 @@ class RN_EXPORT JSCExecutor : public JSExecutor, public PrivateDataBase { 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 b8cc3d3f13709d..83f9e15344fbd7 100644 --- a/ReactCommon/cxxreact/JSExecutor.h +++ b/ReactCommon/cxxreact/JSExecutor.h @@ -53,6 +53,11 @@ class JSExecutor { */ 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 51672048570e99..b5db5203fa74ad 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 3d4341b4a40a1b..6467977279fa53 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 3f1f78c8336637..51bad86f746f92 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 dee12b6e3273b3..093707f2e8215a 100644 --- a/ReactCommon/cxxreact/NativeToJsBridge.h +++ b/ReactCommon/cxxreact/NativeToJsBridge.h @@ -98,6 +98,7 @@ class NativeToJsBridge { 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 896eeb5f649c15..635875b3b79cbe 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 cb845a4751e29f..2d628f22c35d7c 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; };