diff --git a/React/CxxBridge/RCTCxxBridge.mm b/React/CxxBridge/RCTCxxBridge.mm index 48eb02b537..2b25e227f9 100644 --- a/React/CxxBridge/RCTCxxBridge.mm +++ b/React/CxxBridge/RCTCxxBridge.mm @@ -1345,7 +1345,7 @@ RCT_NOT_IMPLEMENTED(-(instancetype)initWithBundleURL } else if (reactInstance) { reactInstance->loadScriptFromString(std::make_unique(script), sourceUrlStr.UTF8String, !async); } else { - std::string methodName = async ? "loadApplicationScript" : "loadApplicationScriptSync"; + std::string methodName = async ? "loadBundle" : "loadBundleSync"; throw std::logic_error("Attempt to call " + methodName + ": on uninitialized bridge"); } }]; diff --git a/React/CxxBridge/RCTObjcExecutor.mm b/React/CxxBridge/RCTObjcExecutor.mm index 47d5787aa1..7eebcfcdde 100644 --- a/React/CxxBridge/RCTObjcExecutor.mm +++ b/React/CxxBridge/RCTObjcExecutor.mm @@ -67,7 +67,12 @@ class RCTObjcExecutor : public JSExecutor { setGlobalVariable("__fbBatchedBridgeConfig", std::make_unique(folly::toJson(config))); } - void loadApplicationScript(std::unique_ptr script, std::string sourceURL) override + void initializeRuntime() override + { + // We do nothing here since initialization is done in the constructor + } + + void loadBundle(std::unique_ptr script, std::string sourceURL) override { RCTProfileBeginFlowEvent(); [m_jse executeApplicationScript:[NSData dataWithBytes:script->c_str() length:script->size()] diff --git a/ReactAndroid/src/main/java/com/facebook/react/bridge/JavaJSExecutor.java b/ReactAndroid/src/main/java/com/facebook/react/bridge/JavaJSExecutor.java index b9572f64ce..db9f29b130 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/bridge/JavaJSExecutor.java +++ b/ReactAndroid/src/main/java/com/facebook/react/bridge/JavaJSExecutor.java @@ -38,7 +38,7 @@ public interface JavaJSExecutor { * @param sourceURL url or file location from which script content was loaded */ @DoNotStrip - void loadApplicationScript(String sourceURL) throws ProxyExecutorException; + void loadBundle(String sourceURL) throws ProxyExecutorException; /** * Execute javascript method within js context diff --git a/ReactAndroid/src/main/java/com/facebook/react/devsupport/JSDebuggerWebSocketClient.java b/ReactAndroid/src/main/java/com/facebook/react/devsupport/JSDebuggerWebSocketClient.java index 103f22868f..83772aecf5 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/devsupport/JSDebuggerWebSocketClient.java +++ b/ReactAndroid/src/main/java/com/facebook/react/devsupport/JSDebuggerWebSocketClient.java @@ -81,7 +81,7 @@ public class JSDebuggerWebSocketClient extends WebSocketListener { } } - public void loadApplicationScript( + public void loadBundle( String sourceURL, HashMap injectedObjects, JSDebuggerCallback callback) { int requestID = mRequestID.getAndIncrement(); mCallbacks.put(requestID, callback); diff --git a/ReactAndroid/src/main/java/com/facebook/react/devsupport/WebsocketJavaScriptExecutor.java b/ReactAndroid/src/main/java/com/facebook/react/devsupport/WebsocketJavaScriptExecutor.java index b045cf69f4..e993205ee7 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/devsupport/WebsocketJavaScriptExecutor.java +++ b/ReactAndroid/src/main/java/com/facebook/react/devsupport/WebsocketJavaScriptExecutor.java @@ -153,10 +153,9 @@ public class WebsocketJavaScriptExecutor implements JavaJSExecutor { } @Override - public void loadApplicationScript(String sourceURL) throws JavaJSExecutor.ProxyExecutorException { + public void loadBundle(String sourceURL) throws JavaJSExecutor.ProxyExecutorException { JSExecutorCallbackFuture callback = new JSExecutorCallbackFuture(); - Assertions.assertNotNull(mWebSocketClient) - .loadApplicationScript(sourceURL, mInjectedObjects, callback); + Assertions.assertNotNull(mWebSocketClient).loadBundle(sourceURL, mInjectedObjects, callback); try { callback.get(); } catch (Throwable cause) { @@ -178,7 +177,7 @@ public class WebsocketJavaScriptExecutor implements JavaJSExecutor { @Override public void setGlobalVariable(String propertyName, String jsonEncodedValue) { - // Store and use in the next loadApplicationScript() call. + // Store and use in the next loadBundle() call. mInjectedObjects.put(propertyName, jsonEncodedValue); } } diff --git a/ReactAndroid/src/main/jni/react/jni/ProxyExecutor.cpp b/ReactAndroid/src/main/jni/react/jni/ProxyExecutor.cpp index 43914cadd2..17e324d115 100644 --- a/ReactAndroid/src/main/jni/react/jni/ProxyExecutor.cpp +++ b/ReactAndroid/src/main/jni/react/jni/ProxyExecutor.cpp @@ -53,9 +53,7 @@ ProxyExecutor::~ProxyExecutor() { m_executor.reset(); } -void ProxyExecutor::loadApplicationScript( - std::unique_ptr, - std::string sourceURL) { +void ProxyExecutor::initializeRuntime() { folly::dynamic nativeModuleConfig = folly::dynamic::array; { @@ -76,14 +74,17 @@ void ProxyExecutor::loadApplicationScript( "__fbBatchedBridgeConfig", std::make_unique(folly::toJson(config))); } +} - static auto loadApplicationScript = - jni::findClassStatic(EXECUTOR_BASECLASS) - ->getMethod("loadApplicationScript"); +void ProxyExecutor::loadBundle( + std::unique_ptr, + std::string sourceURL) { + static auto loadBundle = jni::findClassStatic(EXECUTOR_BASECLASS) + ->getMethod("loadBundle"); // The proxy ignores the script data passed in. - loadApplicationScript(m_executor.get(), jni::make_jstring(sourceURL).get()); + loadBundle(m_executor.get(), jni::make_jstring(sourceURL).get()); // We can get pending calls here to native but the queue will be drained when // we launch the application. } diff --git a/ReactAndroid/src/main/jni/react/jni/ProxyExecutor.h b/ReactAndroid/src/main/jni/react/jni/ProxyExecutor.h index fa1c12634f..c9eab4170d 100644 --- a/ReactAndroid/src/main/jni/react/jni/ProxyExecutor.h +++ b/ReactAndroid/src/main/jni/react/jni/ProxyExecutor.h @@ -37,7 +37,8 @@ class ProxyExecutor : public JSExecutor { jni::global_ref &&executorInstance, std::shared_ptr delegate); virtual ~ProxyExecutor() override; - virtual void loadApplicationScript( + virtual void initializeRuntime() override; + virtual void loadBundle( std::unique_ptr script, std::string sourceURL) override; virtual void setBundleRegistry( diff --git a/ReactAndroid/src/test/java/com/facebook/react/devsupport/JSDebuggerWebSocketClientTest.java b/ReactAndroid/src/test/java/com/facebook/react/devsupport/JSDebuggerWebSocketClientTest.java index 3a341c7136..0c6bbde0e8 100644 --- a/ReactAndroid/src/test/java/com/facebook/react/devsupport/JSDebuggerWebSocketClientTest.java +++ b/ReactAndroid/src/test/java/com/facebook/react/devsupport/JSDebuggerWebSocketClientTest.java @@ -40,7 +40,7 @@ public class JSDebuggerWebSocketClientTest { } @Test - public void test_loadApplicationScript_ShouldSendCorrectMessage() throws Exception { + public void test_loadBundle_ShouldSendCorrectMessage() throws Exception { final JSDebuggerWebSocketClient.JSDebuggerCallback cb = PowerMockito.mock(JSDebuggerWebSocketClient.JSDebuggerCallback.class); @@ -49,7 +49,7 @@ public class JSDebuggerWebSocketClientTest { injectedObjects.put("key1", "value1"); injectedObjects.put("key2", "value2"); - client.loadApplicationScript("http://localhost:8080/index.js", injectedObjects, cb); + client.loadBundle("http://localhost:8080/index.js", injectedObjects, cb); PowerMockito.verifyPrivate(client) .invoke( "sendMessage", diff --git a/ReactCommon/cxxreact/Instance.cpp b/ReactCommon/cxxreact/Instance.cpp index 5144921f17..7c87c26f5a 100644 --- a/ReactCommon/cxxreact/Instance.cpp +++ b/ReactCommon/cxxreact/Instance.cpp @@ -49,6 +49,8 @@ void Instance::initializeBridge( nativeToJsBridge_ = std::make_shared( jsef.get(), moduleRegistry_, jsQueue, callback_); + nativeToJsBridge_->initializeRuntime(); + /** * After NativeToJsBridge is created, the jsi::Runtime should exist. * Also, the JS message queue thread exists. So, it's safe to @@ -64,25 +66,25 @@ void Instance::initializeBridge( CHECK(nativeToJsBridge_); } -void Instance::loadApplication( +void Instance::loadBundle( std::unique_ptr bundleRegistry, std::unique_ptr string, std::string sourceURL) { callback_->incrementPendingJSCalls(); - SystraceSection s("Instance::loadApplication", "sourceURL", sourceURL); - nativeToJsBridge_->loadApplication( + SystraceSection s("Instance::loadBundle", "sourceURL", sourceURL); + nativeToJsBridge_->loadBundle( std::move(bundleRegistry), std::move(string), std::move(sourceURL)); } -void Instance::loadApplicationSync( +void Instance::loadBundleSync( std::unique_ptr bundleRegistry, std::unique_ptr string, std::string sourceURL) { std::unique_lock lock(m_syncMutex); m_syncCV.wait(lock, [this] { return m_syncReady; }); - SystraceSection s("Instance::loadApplicationSync", "sourceURL", sourceURL); - nativeToJsBridge_->loadApplicationSync( + SystraceSection s("Instance::loadBundleSync", "sourceURL", sourceURL); + nativeToJsBridge_->loadBundleSync( std::move(bundleRegistry), std::move(string), std::move(sourceURL)); } @@ -90,7 +92,7 @@ void Instance::setSourceURL(std::string sourceURL) { callback_->incrementPendingJSCalls(); SystraceSection s("Instance::setSourceURL", "sourceURL", sourceURL); - nativeToJsBridge_->loadApplication(nullptr, nullptr, std::move(sourceURL)); + nativeToJsBridge_->loadBundle(nullptr, nullptr, std::move(sourceURL)); } void Instance::loadScriptFromString( @@ -99,9 +101,9 @@ void Instance::loadScriptFromString( bool loadSynchronously) { SystraceSection s("Instance::loadScriptFromString", "sourceURL", sourceURL); if (loadSynchronously) { - loadApplicationSync(nullptr, std::move(string), std::move(sourceURL)); + loadBundleSync(nullptr, std::move(string), std::move(sourceURL)); } else { - loadApplication(nullptr, std::move(string), std::move(sourceURL)); + loadBundle(nullptr, std::move(string), std::move(sourceURL)); } } @@ -157,12 +159,12 @@ void Instance::loadRAMBundle( std::string startupScriptSourceURL, bool loadSynchronously) { if (loadSynchronously) { - loadApplicationSync( + loadBundleSync( std::move(bundleRegistry), std::move(startupScript), std::move(startupScriptSourceURL)); } else { - loadApplication( + loadBundle( std::move(bundleRegistry), std::move(startupScript), std::move(startupScriptSourceURL)); diff --git a/ReactCommon/cxxreact/Instance.h b/ReactCommon/cxxreact/Instance.h index 7aabee19ab..4a76d5e9d6 100644 --- a/ReactCommon/cxxreact/Instance.h +++ b/ReactCommon/cxxreact/Instance.h @@ -47,6 +47,8 @@ class RN_EXPORT Instance { std::shared_ptr jsQueue, std::shared_ptr moduleRegistry); + void initializeRuntime(); + void setSourceURL(std::string sourceURL); void loadScriptFromString( @@ -130,11 +132,11 @@ class RN_EXPORT Instance { private: void callNativeModules(folly::dynamic &&calls, bool isEndOfBatch); - void loadApplication( + void loadBundle( std::unique_ptr bundleRegistry, std::unique_ptr startupScript, std::string startupScriptSourceURL); - void loadApplicationSync( + void loadBundleSync( std::unique_ptr bundleRegistry, std::unique_ptr startupScript, std::string startupScriptSourceURL); diff --git a/ReactCommon/cxxreact/JSExecutor.h b/ReactCommon/cxxreact/JSExecutor.h index ab54642d99..b3b29d1b32 100644 --- a/ReactCommon/cxxreact/JSExecutor.h +++ b/ReactCommon/cxxreact/JSExecutor.h @@ -59,10 +59,15 @@ class JSExecutorFactory { class RN_EXPORT JSExecutor { public: + /** + * Prepares the JS runtime for React Native by installing global variables. + * Called once before any JS is evaluated. + */ + virtual void initializeRuntime() = 0; /** * Execute an application script bundle in the JS context. */ - virtual void loadApplicationScript( + virtual void loadBundle( std::unique_ptr script, std::string sourceURL) = 0; diff --git a/ReactCommon/cxxreact/NativeToJsBridge.cpp b/ReactCommon/cxxreact/NativeToJsBridge.cpp index a34041e5a1..83ceb0c1a7 100644 --- a/ReactCommon/cxxreact/NativeToJsBridge.cpp +++ b/ReactCommon/cxxreact/NativeToJsBridge.cpp @@ -114,7 +114,12 @@ NativeToJsBridge::~NativeToJsBridge() { << "NativeToJsBridge::destroy() must be called before deallocating the NativeToJsBridge!"; } -void NativeToJsBridge::loadApplication( +void NativeToJsBridge::initializeRuntime() { + runOnExecutorQueue( + [](JSExecutor *executor) mutable { executor->initializeRuntime(); }); +} + +void NativeToJsBridge::loadBundle( std::unique_ptr bundleRegistry, std::unique_ptr startupScript, std::string startupScriptSourceURL) { @@ -129,7 +134,7 @@ void NativeToJsBridge::loadApplication( executor->setBundleRegistry(std::move(bundleRegistry)); } try { - executor->loadApplicationScript( + executor->loadBundle( std::move(*startupScript), std::move(startupScriptSourceURL)); } catch (...) { m_applicationScriptHasFailure = true; @@ -138,7 +143,7 @@ void NativeToJsBridge::loadApplication( }); } -void NativeToJsBridge::loadApplicationSync( +void NativeToJsBridge::loadBundleSync( std::unique_ptr bundleRegistry, std::unique_ptr startupScript, std::string startupScriptSourceURL) { @@ -146,7 +151,7 @@ void NativeToJsBridge::loadApplicationSync( m_executor->setBundleRegistry(std::move(bundleRegistry)); } try { - m_executor->loadApplicationScript( + m_executor->loadBundle( std::move(startupScript), std::move(startupScriptSourceURL)); } catch (...) { m_applicationScriptHasFailure = true; diff --git a/ReactCommon/cxxreact/NativeToJsBridge.h b/ReactCommon/cxxreact/NativeToJsBridge.h index 0a4f6d400a..e6d6dc643c 100644 --- a/ReactCommon/cxxreact/NativeToJsBridge.h +++ b/ReactCommon/cxxreact/NativeToJsBridge.h @@ -32,7 +32,7 @@ class RAMBundleRegistry; // executors and their threads. All functions here can be called from // any thread. // -// Except for loadApplicationScriptSync(), all void methods will queue +// Except for loadBundleSync(), all void methods will queue // work to run on the jsQueue passed to the ctor, and return // immediately. class NativeToJsBridge { @@ -63,16 +63,21 @@ class NativeToJsBridge { */ void invokeCallback(double callbackId, folly::dynamic &&args); + /** + * Sets global variables in the JS Context. + */ + void initializeRuntime(); + /** * Starts the JS application. If bundleRegistry is non-null, then it is * used to fetch JavaScript modules as individual scripts. * Otherwise, the script is assumed to include all the modules. */ - void loadApplication( + void loadBundle( std::unique_ptr bundleRegistry, std::unique_ptr startupCode, std::string sourceURL); - void loadApplicationSync( + void loadBundleSync( std::unique_ptr bundleRegistry, std::unique_ptr startupCode, std::string sourceURL); diff --git a/ReactCommon/jsiexecutor/jsireact/JSIExecutor.cpp b/ReactCommon/jsiexecutor/jsireact/JSIExecutor.cpp index 3fb689543d..360918d672 100644 --- a/ReactCommon/jsiexecutor/jsireact/JSIExecutor.cpp +++ b/ReactCommon/jsiexecutor/jsireact/JSIExecutor.cpp @@ -70,13 +70,8 @@ JSIExecutor::JSIExecutor( *runtime, "__jsiExecutorDescription", runtime->description()); } -void JSIExecutor::loadApplicationScript( - std::unique_ptr script, - std::string sourceURL) { - SystraceSection s("JSIExecutor::loadApplicationScript"); - - // TODO: check for and use precompiled HBC - +void JSIExecutor::initializeRuntime() { + SystraceSection s("JSIExecutor::initializeRuntime"); runtime_->global().setProperty( *runtime_, "nativeModuleProxy", @@ -134,6 +129,18 @@ void JSIExecutor::loadApplicationScript( if (runtimeInstaller_) { runtimeInstaller_(*runtime_); } + bool hasLogger(ReactMarker::logTaggedMarker); + if (hasLogger) { + ReactMarker::logMarker(ReactMarker::CREATE_REACT_CONTEXT_STOP); + } +} + +void JSIExecutor::loadBundle( + std::unique_ptr script, + std::string sourceURL) { + SystraceSection s("JSIExecutor::loadBundle"); + + // TODO: check for and use precompiled HBC bool hasLogger(ReactMarker::logTaggedMarker); std::string scriptName = simpleBasename(sourceURL); @@ -145,7 +152,6 @@ void JSIExecutor::loadApplicationScript( std::make_unique(std::move(script)), sourceURL); flush(); if (hasLogger) { - ReactMarker::logMarker(ReactMarker::CREATE_REACT_CONTEXT_STOP); ReactMarker::logTaggedMarker( ReactMarker::RUN_JS_BUNDLE_STOP, scriptName.c_str()); } diff --git a/ReactCommon/jsiexecutor/jsireact/JSIExecutor.h b/ReactCommon/jsiexecutor/jsireact/JSIExecutor.h index 8245e3fd3f..a8a1042ab8 100644 --- a/ReactCommon/jsiexecutor/jsireact/JSIExecutor.h +++ b/ReactCommon/jsiexecutor/jsireact/JSIExecutor.h @@ -77,7 +77,8 @@ class JSIExecutor : public JSExecutor { std::shared_ptr delegate, const JSIScopedTimeoutInvoker &timeoutInvoker, RuntimeInstaller runtimeInstaller); - void loadApplicationScript( + void initializeRuntime() override; + void loadBundle( std::unique_ptr script, std::string sourceURL) override; void setBundleRegistry(std::unique_ptr) override;