diff --git a/ReactAndroid/src/main/jni/react/jni/CatalystInstanceImpl.cpp b/ReactAndroid/src/main/jni/react/jni/CatalystInstanceImpl.cpp index db4e0aa4984..3c2fa6f5fb2 100644 --- a/ReactAndroid/src/main/jni/react/jni/CatalystInstanceImpl.cpp +++ b/ReactAndroid/src/main/jni/react/jni/CatalystInstanceImpl.cpp @@ -197,6 +197,8 @@ void CatalystInstanceImpl::jniLoadScriptFromAssets( sourceURL, loadSynchronously); return; + } else if (Instance::isIndexedRAMBundle(&script)) { + instance_->loadRAMBundleFromString(std::move(script), sourceURL); } else { instance_->loadScriptFromString(std::move(script), sourceURL, loadSynchronously); } diff --git a/ReactCommon/cxxreact/Instance.cpp b/ReactCommon/cxxreact/Instance.cpp index a9b6bd5623a..8849be8aed8 100644 --- a/ReactCommon/cxxreact/Instance.cpp +++ b/ReactCommon/cxxreact/Instance.cpp @@ -108,6 +108,24 @@ bool Instance::isIndexedRAMBundle(const char *sourcePath) { return parseTypeFromHeader(header) == ScriptTag::RAMBundle; } +bool Instance::isIndexedRAMBundle(std::unique_ptr* script) { + BundleHeader header; + strncpy(reinterpret_cast(&header), script->get()->c_str(), sizeof(header)); + + return parseTypeFromHeader(header) == ScriptTag::RAMBundle; +} + +void Instance::loadRAMBundleFromString(std::unique_ptr script, const std::string& sourceURL) { + auto bundle = folly::make_unique(std::move(script)); + auto startupScript = bundle->getStartupCode(); + auto registry = RAMBundleRegistry::singleBundleRegistry(std::move(bundle)); + loadRAMBundle( + std::move(registry), + std::move(startupScript), + sourceURL, + true); +} + void Instance::loadRAMBundleFromFile(const std::string& sourcePath, const std::string& sourceURL, bool loadSynchronously) { diff --git a/ReactCommon/cxxreact/Instance.h b/ReactCommon/cxxreact/Instance.h index 72a5a7ee836..b63119f5ac2 100644 --- a/ReactCommon/cxxreact/Instance.h +++ b/ReactCommon/cxxreact/Instance.h @@ -47,6 +47,8 @@ public: void loadScriptFromString(std::unique_ptr string, std::string sourceURL, bool loadSynchronously); static bool isIndexedRAMBundle(const char *sourcePath); + static bool isIndexedRAMBundle(std::unique_ptr* string); + void loadRAMBundleFromString(std::unique_ptr script, const std::string& sourceURL); void loadRAMBundleFromFile(const std::string& sourcePath, const std::string& sourceURL, bool loadSynchronously); diff --git a/ReactCommon/cxxreact/JSIndexedRAMBundle.cpp b/ReactCommon/cxxreact/JSIndexedRAMBundle.cpp index 237b9550f08..5b1bc5c4b14 100644 --- a/ReactCommon/cxxreact/JSIndexedRAMBundle.cpp +++ b/ReactCommon/cxxreact/JSIndexedRAMBundle.cpp @@ -6,29 +6,50 @@ #include "JSIndexedRAMBundle.h" #include +#include +#include +#include namespace facebook { namespace react { -std::function(std::string)> JSIndexedRAMBundle::buildFactory() { - return [](const std::string& bundlePath){ +std::function(std::string)> +JSIndexedRAMBundle::buildFactory() { + return [](const std::string &bundlePath) { return folly::make_unique(bundlePath.c_str()); }; } -JSIndexedRAMBundle::JSIndexedRAMBundle(const char *sourcePath) : - m_bundle (sourcePath, std::ios_base::in) { +JSIndexedRAMBundle::JSIndexedRAMBundle(const char *sourcePath) { + m_bundle = std::make_unique(sourcePath, std::ifstream::binary); if (!m_bundle) { - throw std::ios_base::failure( - folly::to("Bundle ", sourcePath, - "cannot be opened: ", m_bundle.rdstate())); + throw std::ios_base::failure(folly::to( + "Bundle ", sourcePath, "cannot be opened: ", m_bundle->rdstate())); } + init(); +} +JSIndexedRAMBundle::JSIndexedRAMBundle( + std::unique_ptr script) { + // tmpStream is needed because m_bundle is std::istream type + // which has no member 'write' + std::unique_ptr tmpStream = + std::make_unique(); + tmpStream->write(script->c_str(), script->size()); + m_bundle = std::move(tmpStream); + if (!m_bundle) { + throw std::ios_base::failure(folly::to( + "Bundle from string cannot be opened: ", m_bundle->rdstate())); + } + init(); +} + +void JSIndexedRAMBundle::init() { // read in magic header, number of entries, and length of the startup section uint32_t header[3]; static_assert( - sizeof(header) == 12, - "header size must exactly match the input file format"); + sizeof(header) == 12, + "header size must exactly match the input file format"); readBundle(reinterpret_cast(header), sizeof(header)); const size_t numTableEntries = folly::Endian::little(header[1]); @@ -40,15 +61,17 @@ JSIndexedRAMBundle::JSIndexedRAMBundle(const char *sourcePath) : // read the lookup table from the file readBundle( - reinterpret_cast(m_table.data.get()), m_table.byteLength()); + reinterpret_cast(m_table.data.get()), m_table.byteLength()); // read the startup code - m_startupCode = std::unique_ptr(new JSBigBufferString{startupCodeSize - 1}); + m_startupCode = std::unique_ptr( + new JSBigBufferString{startupCodeSize - 1}); readBundle(m_startupCode->data(), startupCodeSize - 1); } -JSIndexedRAMBundle::Module JSIndexedRAMBundle::getModule(uint32_t moduleId) const { +JSIndexedRAMBundle::Module JSIndexedRAMBundle::getModule( + uint32_t moduleId) const { Module ret; ret.name = folly::to(moduleId, ".js"); ret.code = getModuleCode(moduleId); @@ -56,7 +79,8 @@ JSIndexedRAMBundle::Module JSIndexedRAMBundle::getModule(uint32_t moduleId) cons } std::unique_ptr JSIndexedRAMBundle::getStartupCode() { - CHECK(m_startupCode) << "startup code for a RAM Bundle can only be retrieved once"; + CHECK(m_startupCode) + << "startup code for a RAM Bundle can only be retrieved once"; return std::move(m_startupCode); } @@ -64,24 +88,29 @@ std::string JSIndexedRAMBundle::getModuleCode(const uint32_t id) const { const auto moduleData = id < m_table.numEntries ? &m_table.data[id] : nullptr; // entries without associated code have offset = 0 and length = 0 - const uint32_t length = moduleData ? folly::Endian::little(moduleData->length) : 0; + const uint32_t length = + moduleData ? folly::Endian::little(moduleData->length) : 0; if (length == 0) { throw std::ios_base::failure( - folly::to("Error loading module", id, "from RAM Bundle")); + folly::to("Error loading module", id, "from RAM Bundle")); } std::string ret(length - 1, '\0'); - readBundle(&ret.front(), length - 1, m_baseOffset + folly::Endian::little(moduleData->offset)); + readBundle( + &ret.front(), + length - 1, + m_baseOffset + folly::Endian::little(moduleData->offset)); return ret; } -void JSIndexedRAMBundle::readBundle(char *buffer, const std::streamsize bytes) const { - if (!m_bundle.read(buffer, bytes)) { - if (m_bundle.rdstate() & std::ios::eofbit) { +void JSIndexedRAMBundle::readBundle(char *buffer, const std::streamsize bytes) + const { + if (!m_bundle->read(buffer, bytes)) { + if (m_bundle->rdstate() & std::ios::eofbit) { throw std::ios_base::failure("Unexpected end of RAM Bundle file"); } - throw std::ios_base::failure( - folly::to("Error reading RAM Bundle: ", m_bundle.rdstate())); + throw std::ios_base::failure(folly::to( + "Error reading RAM Bundle: ", m_bundle->rdstate())); } } @@ -89,13 +118,12 @@ void JSIndexedRAMBundle::readBundle( char *buffer, const std::streamsize bytes, const std::ifstream::pos_type position) const { - - if (!m_bundle.seekg(position)) { - throw std::ios_base::failure( - folly::to("Error reading RAM Bundle: ", m_bundle.rdstate())); + if (!m_bundle->seekg(position)) { + throw std::ios_base::failure(folly::to( + "Error reading RAM Bundle: ", m_bundle->rdstate())); } readBundle(buffer, bytes); } -} // namespace react -} // namespace facebook +} // namespace react +} // namespace facebook diff --git a/ReactCommon/cxxreact/JSIndexedRAMBundle.h b/ReactCommon/cxxreact/JSIndexedRAMBundle.h index be6b27f7a84..2f2db3b708f 100644 --- a/ReactCommon/cxxreact/JSIndexedRAMBundle.h +++ b/ReactCommon/cxxreact/JSIndexedRAMBundle.h @@ -5,7 +5,7 @@ #pragma once -#include +#include #include #include @@ -24,6 +24,7 @@ public: // Throws std::runtime_error on failure. JSIndexedRAMBundle(const char *sourceURL); + JSIndexedRAMBundle(std::unique_ptr script); // Throws std::runtime_error on failure. std::unique_ptr getStartupCode(); @@ -51,14 +52,15 @@ private: } }; + void init(); std::string getModuleCode(const uint32_t id) const; void readBundle(char *buffer, const std::streamsize bytes) const; void readBundle( char *buffer, const std::streamsize bytes, - const std::ifstream::pos_type position) const; + const std::istream::pos_type position) const; - mutable std::ifstream m_bundle; + mutable std::unique_ptr m_bundle; ModuleTable m_table; size_t m_baseOffset; std::unique_ptr m_startupCode;