diff --git a/ReactAndroid/src/main/java/com/facebook/react/cxxbridge/CatalystInstanceImpl.java b/ReactAndroid/src/main/java/com/facebook/react/cxxbridge/CatalystInstanceImpl.java index 569ae980e..7bef0a38b 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/cxxbridge/CatalystInstanceImpl.java +++ b/ReactAndroid/src/main/java/com/facebook/react/cxxbridge/CatalystInstanceImpl.java @@ -161,8 +161,9 @@ public class CatalystInstanceImpl implements CatalystInstance { MessageQueueThread moduleQueue, ModuleRegistryHolder registryHolder); - /* package */ native void loadScriptFromAssets(AssetManager assetManager, String assetURL, boolean useLazyBundle); + /* package */ native void loadScriptFromAssets(AssetManager assetManager, String assetURL); /* package */ native void loadScriptFromFile(String fileName, String sourceURL); + /* package */ native void loadScriptFromOptimizedBundle(String path, String sourceURL, int flags); @Override public void runJSBundle() { diff --git a/ReactAndroid/src/main/java/com/facebook/react/cxxbridge/JSBundleLoader.java b/ReactAndroid/src/main/java/com/facebook/react/cxxbridge/JSBundleLoader.java index 6615c75c8..311b4fa41 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/cxxbridge/JSBundleLoader.java +++ b/ReactAndroid/src/main/java/com/facebook/react/cxxbridge/JSBundleLoader.java @@ -30,18 +30,11 @@ public abstract class JSBundleLoader { public static JSBundleLoader createFileLoader( final Context context, final String fileName) { - return createFileLoader(context, fileName, false); - } - - public static JSBundleLoader createFileLoader( - final Context context, - final String fileName, - final boolean useLazyBundle) { return new JSBundleLoader() { @Override public void loadScript(CatalystInstanceImpl instance) { if (fileName.startsWith("assets://")) { - instance.loadScriptFromAssets(context.getAssets(), fileName, useLazyBundle); + instance.loadScriptFromAssets(context.getAssets(), fileName); } else { instance.loadScriptFromFile(fileName, fileName); } diff --git a/ReactAndroid/src/main/java/com/facebook/react/cxxbridge/UnpackingJSBundleLoader.java b/ReactAndroid/src/main/java/com/facebook/react/cxxbridge/UnpackingJSBundleLoader.java index ed65860ff..722b3c596 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/cxxbridge/UnpackingJSBundleLoader.java +++ b/ReactAndroid/src/main/java/com/facebook/react/cxxbridge/UnpackingJSBundleLoader.java @@ -38,6 +38,12 @@ import static com.facebook.systrace.Systrace.TRACE_TAG_REACT_JAVA_BRIDGE; */ public class UnpackingJSBundleLoader extends JSBundleLoader { + /** + * Flag passed to loadScriptFromOptimizedBundle to let the bridge know that + * the unpacked unpacked js source file. + */ + static final int UNPACKED_JS_SOURCE = (1 << 0); + /** * Name of the lock files. Multiple processes can be spawned off the same app * and we need to guarantee that at most one unpacks files at any time. To @@ -141,10 +147,10 @@ public class UnpackingJSBundleLoader extends JSBundleLoader { @Override public void loadScript(CatalystInstanceImpl instance) { prepare(); - // TODO(12128379): add instance method that would take bundle directory - instance.loadScriptFromFile( - new File(mDirectoryPath, "bundle.js").getPath(), - mSourceURL); + instance.loadScriptFromOptimizedBundle( + mDirectoryPath.getPath(), + mSourceURL, + UNPACKED_JS_SOURCE); } @Override diff --git a/ReactAndroid/src/main/jni/xreact/jni/CatalystInstanceImpl.cpp b/ReactAndroid/src/main/jni/xreact/jni/CatalystInstanceImpl.cpp index 612107b7c..196e333a5 100644 --- a/ReactAndroid/src/main/jni/xreact/jni/CatalystInstanceImpl.cpp +++ b/ReactAndroid/src/main/jni/xreact/jni/CatalystInstanceImpl.cpp @@ -13,8 +13,6 @@ #include #include -#include - #include #include #include @@ -25,7 +23,6 @@ #include "ModuleRegistryHolder.h" #include "NativeArray.h" #include "JNativeRunnable.h" -#include "OnLoad.h" using namespace facebook::jni; @@ -101,9 +98,11 @@ void CatalystInstanceImpl::registerNatives() { makeNativeMethod("initHybrid", CatalystInstanceImpl::initHybrid), makeNativeMethod("initializeBridge", CatalystInstanceImpl::initializeBridge), makeNativeMethod("loadScriptFromAssets", - "(Landroid/content/res/AssetManager;Ljava/lang/String;Z)V", + "(Landroid/content/res/AssetManager;Ljava/lang/String;)V", CatalystInstanceImpl::loadScriptFromAssets), makeNativeMethod("loadScriptFromFile", CatalystInstanceImpl::loadScriptFromFile), + makeNativeMethod("loadScriptFromOptimizedBundle", + CatalystInstanceImpl::loadScriptFromOptimizedBundle), makeNativeMethod("callJSFunction", CatalystInstanceImpl::callJSFunction), makeNativeMethod("callJSCallback", CatalystInstanceImpl::callJSCallback), makeNativeMethod("getMainExecutorToken", CatalystInstanceImpl::getMainExecutorToken), @@ -152,131 +151,20 @@ void CatalystInstanceImpl::initializeBridge( mrh->getModuleRegistry()); } -#ifdef WITH_FBJSCEXTENSIONS -static std::unique_ptr loadScriptFromCache( - AAssetManager* manager, - std::string& sourceURL) { - - // 20-byte sha1 as hex - static const size_t HASH_STR_SIZE = 40; - - // load bundle hash from the metadata file in the APK - auto hash = react::loadScriptFromAssets(manager, sourceURL + ".meta"); - auto cacheDir = getApplicationCacheDir() + "/rn-bundle"; - auto encoding = static_cast(hash->c_str()[20]); - - if (mkdir(cacheDir.c_str(), 0755) == -1 && errno != EEXIST) { - throw std::runtime_error("Can't create cache directory"); - } - - if (encoding != JSBigMmapString::Encoding::Ascii) { - throw std::runtime_error("Can't use mmap fastpath for non-ascii bundles"); - } - - // convert hash to string - char hashStr[HASH_STR_SIZE + 1]; - for (size_t i = 0; i < HASH_STR_SIZE; i += 2) { - snprintf(hashStr + i, 3, "%02hhx", hash->c_str()[i / 2] & 0xFF); - } - - // the name of the cached bundle file should be the hash - std::string cachePath = cacheDir + "/" + hashStr; - FILE *cache = fopen(cachePath.c_str(), "r"); - SCOPE_EXIT { if (cache) fclose(cache); }; - - size_t size = 0; - if (cache == NULL) { - // delete old bundle, if there was one. - std::string metaPath = cacheDir + "/meta"; - if (auto meta = fopen(metaPath.c_str(), "r")) { - char oldBundleHash[HASH_STR_SIZE + 1]; - if (fread(oldBundleHash, HASH_STR_SIZE, 1, meta) == HASH_STR_SIZE) { - remove((cacheDir + "/" + oldBundleHash).c_str()); - remove(metaPath.c_str()); - } - fclose(meta); - } - - // load script from the APK and write to temporary file - auto script = react::loadScriptFromAssets(manager, sourceURL); - auto tmpPath = cachePath + "_"; - cache = fopen(tmpPath.c_str(), "w"); - if (!cache) { - throw std::runtime_error("Can't open cache, errno: " + errno); - } - if (fwrite(script->c_str(), 1, script->size(), cache) != size) { - remove(tmpPath.c_str()); - throw std::runtime_error("Failed to unpack bundle"); - } - - // force data to be written to disk - fsync(fileno(cache)); - fclose(cache); - - // move script to final path - atomic operation - if (rename(tmpPath.c_str(), cachePath.c_str())) { - throw std::runtime_error("Failed to update cache, errno: " + errno); - } - - // store the bundle hash in a metadata file - auto meta = fopen(metaPath.c_str(), "w"); - if (!meta) { - throw std::runtime_error("Failed to open metadata file to store bundle hash"); - } - if (fwrite(hashStr, HASH_STR_SIZE, 1, meta) != HASH_STR_SIZE) { - throw std::runtime_error("Failed to write bundle hash to metadata file"); - } - fsync(fileno(meta)); - fclose(meta); - - // return the final written cache - cache = fopen(cachePath.c_str(), "r"); - if (!cache) { - throw std::runtime_error("Cache has been cleared"); - } - } else { - struct stat fileInfo = {0}; - if (fstat(fileno(cache), &fileInfo)) { - throw std::runtime_error("Failed to get cache stats, errno: " + errno); - } - size = fileInfo.st_size; - } - - return folly::make_unique( - dup(fileno(cache)), - size, - reinterpret_cast(hash->c_str()), - encoding); -} -#endif - void CatalystInstanceImpl::loadScriptFromAssets(jobject assetManager, - const std::string& assetURL, - bool useLazyBundle) { + const std::string& assetURL) { const int kAssetsLength = 9; // strlen("assets://"); auto sourceURL = assetURL.substr(kAssetsLength); - auto manager = react::extractAssetManager(assetManager); + auto manager = react::extractAssetManager(assetManager); + auto script = react::loadScriptFromAssets(manager, sourceURL); if (JniJSModulesUnbundle::isUnbundle(manager, sourceURL)) { - auto script = react::loadScriptFromAssets(manager, sourceURL); instance_->loadUnbundle( folly::make_unique(manager, sourceURL), std::move(script), sourceURL); return; } else { -#ifdef WITH_FBJSCEXTENSIONS - if (useLazyBundle) { - try { - auto script = loadScriptFromCache(manager, sourceURL); - instance_->loadScriptFromString(std::move(script), sourceURL); - return; - } catch (...) { - LOG(WARNING) << "Failed to load bundle as Source Code"; - } - } -#endif - auto script = react::loadScriptFromAssets(manager, sourceURL); instance_->loadScriptFromString(std::move(script), sourceURL); } } @@ -287,6 +175,14 @@ void CatalystInstanceImpl::loadScriptFromFile(jni::alias_ref fileName, sourceURL); } +void CatalystInstanceImpl::loadScriptFromOptimizedBundle(const std::string& bundlePath, + const std::string& sourceURL, + jint flags) { + return instance_->loadScriptFromOptimizedBundle(std::move(bundlePath), + std::move(sourceURL), + flags); +} + void CatalystInstanceImpl::callJSFunction( JExecutorToken* token, std::string module, std::string method, NativeArray* arguments) { // We want to share the C++ code, and on iOS, modules pass module/method diff --git a/ReactAndroid/src/main/jni/xreact/jni/CatalystInstanceImpl.h b/ReactAndroid/src/main/jni/xreact/jni/CatalystInstanceImpl.h index 64835e6b4..d0221af97 100644 --- a/ReactAndroid/src/main/jni/xreact/jni/CatalystInstanceImpl.h +++ b/ReactAndroid/src/main/jni/xreact/jni/CatalystInstanceImpl.h @@ -47,8 +47,9 @@ class CatalystInstanceImpl : public jni::HybridClass { jni::alias_ref jsQueue, jni::alias_ref moduleQueue, ModuleRegistryHolder* mrh); - void loadScriptFromAssets(jobject assetManager, const std::string& assetURL, bool useLazyBundle); + void loadScriptFromAssets(jobject assetManager, const std::string& assetURL); void loadScriptFromFile(jni::alias_ref fileName, const std::string& sourceURL); + void loadScriptFromOptimizedBundle(const std::string& bundlePath, const std::string& sourceURL, jint flags); void callJSFunction(JExecutorToken* token, std::string module, std::string method, NativeArray* arguments); void callJSCallback(JExecutorToken* token, jint callbackId, NativeArray* arguments); local_ref getMainExecutorToken(); diff --git a/ReactAndroid/src/main/jni/xreact/jni/OnLoad.cpp b/ReactAndroid/src/main/jni/xreact/jni/OnLoad.cpp index 67e167b4e..952a6b46c 100644 --- a/ReactAndroid/src/main/jni/xreact/jni/OnLoad.cpp +++ b/ReactAndroid/src/main/jni/xreact/jni/OnLoad.cpp @@ -51,6 +51,10 @@ static std::string getApplicationDir(const char* methodName) { return getAbsolutePathMethod(dirObj)->toStdString(); } +static std::string getApplicationCacheDir() { + return getApplicationDir("getCacheDir"); +} + static std::string getApplicationPersistentDir() { return getApplicationDir("getFilesDir"); } @@ -158,10 +162,6 @@ class JReactMarker : public JavaClass { } -std::string getApplicationCacheDir() { - return getApplicationDir("getCacheDir"); -} - extern "C" JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved) { return initialize(vm, [] { // Inject some behavior into react/ diff --git a/ReactAndroid/src/main/jni/xreact/jni/OnLoad.h b/ReactAndroid/src/main/jni/xreact/jni/OnLoad.h index 713d8b582..5cd3c1749 100644 --- a/ReactAndroid/src/main/jni/xreact/jni/OnLoad.h +++ b/ReactAndroid/src/main/jni/xreact/jni/OnLoad.h @@ -10,6 +10,5 @@ namespace facebook { namespace react { jmethodID getLogMarkerMethod(); -std::string getApplicationCacheDir(); } // namespace react } // namespace facebook diff --git a/ReactAndroid/src/test/java/com/facebook/react/cxxbridge/UnpackingJSBundleLoaderTest.java b/ReactAndroid/src/test/java/com/facebook/react/cxxbridge/UnpackingJSBundleLoaderTest.java index d6a2b9c66..016ecb201 100644 --- a/ReactAndroid/src/test/java/com/facebook/react/cxxbridge/UnpackingJSBundleLoaderTest.java +++ b/ReactAndroid/src/test/java/com/facebook/react/cxxbridge/UnpackingJSBundleLoaderTest.java @@ -102,9 +102,10 @@ public class UnpackingJSBundleLoaderTest { @Test public void testCallsAppropriateInstanceMethod() throws IOException { mBuilder.build().loadScript(mCatalystInstanceImpl); - verify(mCatalystInstanceImpl).loadScriptFromFile( - eq(new File(mDestinationPath, "bundle.js").getPath()), - eq(URL)); + verify(mCatalystInstanceImpl).loadScriptFromOptimizedBundle( + eq(mDestinationPath.getPath()), + eq(URL), + eq(UnpackingJSBundleLoader.UNPACKED_JS_SOURCE)); verifyNoMoreInteractions(mCatalystInstanceImpl); } diff --git a/ReactCommon/cxxreact/Android.mk b/ReactCommon/cxxreact/Android.mk index 985cc0357..30cd232db 100644 --- a/ReactCommon/cxxreact/Android.mk +++ b/ReactCommon/cxxreact/Android.mk @@ -5,6 +5,7 @@ include $(CLEAR_VARS) LOCAL_MODULE := libreactnativefb LOCAL_SRC_FILES := \ + Executor.cpp \ Instance.cpp \ JSCExecutor.cpp \ JSCHelpers.cpp \ diff --git a/ReactCommon/cxxreact/BUCK b/ReactCommon/cxxreact/BUCK index 14a5b1e77..46b19ea4e 100644 --- a/ReactCommon/cxxreact/BUCK +++ b/ReactCommon/cxxreact/BUCK @@ -109,6 +109,7 @@ react_library( force_static = True, srcs = [ 'CxxMessageQueue.cpp', + 'Executor.cpp', 'Instance.cpp', 'JSCExecutor.cpp', 'JSCHelpers.cpp', diff --git a/ReactCommon/cxxreact/Executor.cpp b/ReactCommon/cxxreact/Executor.cpp new file mode 100644 index 000000000..15f7730b4 --- /dev/null +++ b/ReactCommon/cxxreact/Executor.cpp @@ -0,0 +1,77 @@ +// Copyright 2004-present Facebook. All Rights Reserved. + +#include "Executor.h" + +#include +#include +#include +#include +#include + +#include + +namespace facebook { +namespace react { + +void JSExecutor::loadApplicationScript(std::string bundlePath, std::string sourceURL, int flags) { + if ((flags & UNPACKED_JS_SOURCE) == 0) { + throw std::runtime_error("No unpacked js source file"); + } + return loadApplicationScript( + JSBigMmapString::fromOptimizedBundle(bundlePath), + std::move(sourceURL)); +} + +static JSBigMmapString::Encoding encodingFromByte(uint8_t byte) { + switch (byte) { + case 0: + return JSBigMmapString::Encoding::Unknown; + case 1: + return JSBigMmapString::Encoding::Ascii; + case 2: + return JSBigMmapString::Encoding::Utf8; + case 3: + return JSBigMmapString::Encoding::Utf16; + default: + throw std::invalid_argument("Unknown bundle encoding"); + } +} + +std::unique_ptr JSBigMmapString::fromOptimizedBundle( + const std::string& bundlePath) { + uint8_t sha1[20]; + uint8_t encoding; + struct stat fileInfo; + int fd = -1; + SCOPE_FAIL { CHECK(fd == -1 || ::close(fd) == 0); }; + + { + auto metaPath = bundlePath + UNPACKED_META_PATH_SUFFIX; + std::ifstream metaFile; + metaFile.exceptions(std::ifstream::eofbit | std::ifstream::failbit | std::ifstream::badbit); + metaFile.open(metaPath, std::ifstream::in | std::ifstream::binary); + metaFile.read(reinterpret_cast(sha1), sizeof(sha1)); + metaFile.read(reinterpret_cast(&encoding), sizeof(encoding)); + } + + { + auto sourcePath = bundlePath + UNPACKED_JS_SOURCE_PATH_SUFFIX; + fd = ::open(sourcePath.c_str(), O_RDONLY); + if (fd == -1) { + throw std::runtime_error(std::string("could not open js bundle file: ") + ::strerror(errno)); + } + } + + if (::fstat(fd, &fileInfo)) { + throw std::runtime_error(std::string("fstat on js bundle failed: ") + strerror(errno)); + } + + return folly::make_unique( + fd, + fileInfo.st_size, + sha1, + encodingFromByte(encoding)); +} + +} // namespace react +} // namespace facebook diff --git a/ReactCommon/cxxreact/Executor.h b/ReactCommon/cxxreact/Executor.h index 6b99df0b2..62b2004c5 100644 --- a/ReactCommon/cxxreact/Executor.h +++ b/ReactCommon/cxxreact/Executor.h @@ -16,6 +16,13 @@ namespace facebook { namespace react { +#define UNPACKED_JS_SOURCE_PATH_SUFFIX "/bundle.js" +#define UNPACKED_META_PATH_SUFFIX "/bundle.meta" + +enum { + UNPACKED_JS_SOURCE = (1 << 0), +}; + class JSExecutor; class MessageQueueThread; @@ -190,6 +197,8 @@ public: return m_encoding; } + static std::unique_ptr fromOptimizedBundle(const std::string& bundlePath); + private: int m_fd; size_t m_size; @@ -206,6 +215,11 @@ public: virtual void loadApplicationScript(std::unique_ptr script, std::string sourceURL) = 0; + /** + * Execute an application script optimized bundle in the JS context. + */ + virtual void loadApplicationScript(std::string bundlePath, std::string source, int flags); + /** * Add an application "unbundle" file */ @@ -245,4 +259,6 @@ public: virtual ~JSExecutor() {} }; +std::unique_ptr readJSBundle(const std::string& path); + } } diff --git a/ReactCommon/cxxreact/Instance.cpp b/ReactCommon/cxxreact/Instance.cpp index cbc8e656b..eb5e31d94 100644 --- a/ReactCommon/cxxreact/Instance.cpp +++ b/ReactCommon/cxxreact/Instance.cpp @@ -75,6 +75,16 @@ void Instance::loadScriptFromFile(const std::string& filename, loadScriptFromString(std::move(buf), sourceURL); } +void Instance::loadScriptFromOptimizedBundle(std::string bundlePath, + std::string sourceURL, + int flags) { + SystraceSection s("reactbridge_xplat_loadScriptFromOptimizedBundle", + "bundlePath", bundlePath); + nativeToJsBridge_->loadOptimizedApplicationScript(std::move(bundlePath), + std::move(sourceURL), + flags); +} + void Instance::loadUnbundle(std::unique_ptr unbundle, std::unique_ptr startupScript, std::string startupScriptSourceURL) { diff --git a/ReactCommon/cxxreact/Instance.h b/ReactCommon/cxxreact/Instance.h index fada0a7cf..1e53c81f2 100644 --- a/ReactCommon/cxxreact/Instance.h +++ b/ReactCommon/cxxreact/Instance.h @@ -36,6 +36,7 @@ class Instance { std::shared_ptr moduleRegistry); void loadScriptFromString(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, diff --git a/ReactCommon/cxxreact/JSCExecutor.cpp b/ReactCommon/cxxreact/JSCExecutor.cpp index d26409c2e..67b17a666 100644 --- a/ReactCommon/cxxreact/JSCExecutor.cpp +++ b/ReactCommon/cxxreact/JSCExecutor.cpp @@ -254,15 +254,37 @@ void JSCExecutor::terminateOnJSVMThread() { } #ifdef WITH_FBJSCEXTENSIONS -static void loadApplicationSource( - const JSGlobalContextRef context, - const JSBigMmapString* script, - const std::string& sourceURL) { +void JSCExecutor::loadApplicationScript( + std::string bundlePath, + std::string sourceURL, + int flags) { + SystraceSection s("JSCExecutor::loadApplicationScript", + "sourceURL", sourceURL); + + if ((flags & UNPACKED_JS_SOURCE) == 0) { + throw std::runtime_error("Optimized bundle with no unpacked js source"); + } + + auto jsScriptBigString = JSBigMmapString::fromOptimizedBundle(bundlePath); + if (jsScriptBigString->encoding() != JSBigMmapString::Encoding::Ascii) { + throw std::runtime_error("Optimized bundle needs to be ascii encoded"); + } + String jsSourceURL(sourceURL.c_str()); - bool is8bit = script->encoding() == JSBigMmapString::Encoding::Ascii || script->encoding() == JSBigMmapString::Encoding::Utf8; - JSSourceCodeRef sourceCode = JSCreateSourceCode(script->fd(), script->size(), jsSourceURL, script->hash(), is8bit); - evaluateSourceCode(context, sourceCode, jsSourceURL); - JSReleaseSourceCode(sourceCode); + JSSourceCodeRef sourceCode = JSCreateSourceCode( + jsScriptBigString->fd(), + jsScriptBigString->size(), + jsSourceURL, + jsScriptBigString->hash(), + true); + SCOPE_EXIT { JSReleaseSourceCode(sourceCode); }; + + evaluateSourceCode(m_context, sourceCode, jsSourceURL); + + bindBridge(); + + flush(); + ReactMarker::logMarker("CREATE_REACT_CONTEXT_END"); } #endif @@ -270,16 +292,6 @@ void JSCExecutor::loadApplicationScript(std::unique_ptr scrip SystraceSection s("JSCExecutor::loadApplicationScript", "sourceURL", sourceURL); - #ifdef WITH_FBJSCEXTENSIONS - if (auto source = dynamic_cast(script.get())) { - loadApplicationSource(m_context, source, sourceURL); - bindBridge(); - flush(); - ReactMarker::logMarker("CREATE_REACT_CONTEXT_END"); - return; - } - #endif - #ifdef WITH_FBSYSTRACE fbsystrace_begin_section( TRACE_TAG_REACT_CXX_BRIDGE, diff --git a/ReactCommon/cxxreact/JSCExecutor.h b/ReactCommon/cxxreact/JSCExecutor.h index b1dfcdb56..b02c7e5b6 100644 --- a/ReactCommon/cxxreact/JSCExecutor.h +++ b/ReactCommon/cxxreact/JSCExecutor.h @@ -59,6 +59,12 @@ public: virtual void loadApplicationScript( std::unique_ptr script, std::string sourceURL) throw(JSException) override; +#ifdef WITH_FBJSCEXTENSIONS + virtual void loadApplicationScript( + std::string bundlePath, + std::string sourceURL, + int flags) override; +#endif virtual void setJSModulesUnbundle( std::unique_ptr unbundle) override; virtual void callFunction( diff --git a/ReactCommon/cxxreact/NativeToJsBridge.cpp b/ReactCommon/cxxreact/NativeToJsBridge.cpp index 8da6bb0fc..ecddf32e2 100644 --- a/ReactCommon/cxxreact/NativeToJsBridge.cpp +++ b/ReactCommon/cxxreact/NativeToJsBridge.cpp @@ -124,6 +124,20 @@ void NativeToJsBridge::loadApplicationScript(std::unique_ptr m_mainExecutor->loadApplicationScript(std::move(script), std::move(sourceURL)); } +void NativeToJsBridge::loadOptimizedApplicationScript( + std::string bundlePath, + std::string sourceURL, + int flags) { + runOnExecutorQueue( + m_mainExecutorToken, + [bundlePath=std::move(bundlePath), + sourceURL=std::move(sourceURL), + flags=flags] + (JSExecutor* executor) { + executor->loadApplicationScript(std::move(bundlePath), std::move(sourceURL), flags); + }); +} + void NativeToJsBridge::loadApplicationUnbundle( std::unique_ptr unbundle, std::unique_ptr startupScript, diff --git a/ReactCommon/cxxreact/NativeToJsBridge.h b/ReactCommon/cxxreact/NativeToJsBridge.h index 786c26867..e95367378 100644 --- a/ReactCommon/cxxreact/NativeToJsBridge.h +++ b/ReactCommon/cxxreact/NativeToJsBridge.h @@ -84,6 +84,12 @@ public: */ void loadApplicationScript(std::unique_ptr script, std::string sourceURL); + /** + * Similar to loading a "bundle", but instead of passing js source this method accepts + * path to a directory containing files prepared for particular JSExecutor. + */ + void loadOptimizedApplicationScript(std::string bundlePath, std::string sourceURL, int flags); + /** * An "unbundle" is a backend that stores and injects JavaScript modules as * individual scripts, rather than bundling all of them into a single scrupt.