diff --git a/packages/react-native/ReactCommon/cxxreact/Instance.cpp b/packages/react-native/ReactCommon/cxxreact/Instance.cpp index 702ed3a88c8..01c03ee9785 100644 --- a/packages/react-native/ReactCommon/cxxreact/Instance.cpp +++ b/packages/react-native/ReactCommon/cxxreact/Instance.cpp @@ -67,8 +67,10 @@ void Instance::initializeBridge( if (parentInspectorTarget) { inspectorTarget_ = &parentInspectorTarget->registerInstance(*this); + RuntimeExecutor runtimeExecutorIfJsi = getRuntimeExecutor(); runtimeInspectorTarget_ = &inspectorTarget_->registerRuntime( - nativeToJsBridge_->getInspectorTargetDelegate()); + nativeToJsBridge_->getInspectorTargetDelegate(), + runtimeExecutorIfJsi ? runtimeExecutorIfJsi : [](auto) {}); } /** diff --git a/packages/react-native/ReactCommon/jsinspector-modern/CMakeLists.txt b/packages/react-native/ReactCommon/jsinspector-modern/CMakeLists.txt index ee8290b0743..cbbc44f6dd0 100644 --- a/packages/react-native/ReactCommon/jsinspector-modern/CMakeLists.txt +++ b/packages/react-native/ReactCommon/jsinspector-modern/CMakeLists.txt @@ -22,4 +22,5 @@ target_link_libraries(jsinspector folly_runtime glog react_featureflags + runtimeexecutor ) diff --git a/packages/react-native/ReactCommon/jsinspector-modern/InstanceTarget.cpp b/packages/react-native/ReactCommon/jsinspector-modern/InstanceTarget.cpp index 920973fa027..7736862fb4c 100644 --- a/packages/react-native/ReactCommon/jsinspector-modern/InstanceTarget.cpp +++ b/packages/react-native/ReactCommon/jsinspector-modern/InstanceTarget.cpp @@ -46,9 +46,10 @@ InstanceTarget::~InstanceTarget() { } RuntimeTarget& InstanceTarget::registerRuntime( - RuntimeTargetDelegate& delegate) { + RuntimeTargetDelegate& delegate, + RuntimeExecutor executor) { assert(!currentRuntime_ && "Only one Runtime allowed"); - currentRuntime_.emplace(delegate); + currentRuntime_.emplace(delegate, executor); forEachAgent([currentRuntime = &*currentRuntime_](InstanceAgent& agent) { agent.setCurrentRuntime(currentRuntime); }); diff --git a/packages/react-native/ReactCommon/jsinspector-modern/InstanceTarget.h b/packages/react-native/ReactCommon/jsinspector-modern/InstanceTarget.h index 5be5e97b7c5..87fca391e38 100644 --- a/packages/react-native/ReactCommon/jsinspector-modern/InstanceTarget.h +++ b/packages/react-native/ReactCommon/jsinspector-modern/InstanceTarget.h @@ -59,7 +59,9 @@ class InstanceTarget final { FrontendChannel channel, SessionState& sessionState); - RuntimeTarget& registerRuntime(RuntimeTargetDelegate& delegate); + RuntimeTarget& registerRuntime( + RuntimeTargetDelegate& delegate, + RuntimeExecutor executor); void unregisterRuntime(RuntimeTarget& runtime); private: diff --git a/packages/react-native/ReactCommon/jsinspector-modern/React-jsinspector.podspec b/packages/react-native/ReactCommon/jsinspector-modern/React-jsinspector.podspec index 53089c6ca95..12c619ccd9e 100644 --- a/packages/react-native/ReactCommon/jsinspector-modern/React-jsinspector.podspec +++ b/packages/react-native/ReactCommon/jsinspector-modern/React-jsinspector.podspec @@ -51,4 +51,5 @@ Pod::Spec.new do |s| s.dependency "RCT-Folly", folly_version s.dependency "React-featureflags" s.dependency "DoubleConversion" + s.dependency "React-runtimeexecutor", version end diff --git a/packages/react-native/ReactCommon/jsinspector-modern/RuntimeTarget.cpp b/packages/react-native/ReactCommon/jsinspector-modern/RuntimeTarget.cpp index c56003dc958..ea260acec02 100644 --- a/packages/react-native/ReactCommon/jsinspector-modern/RuntimeTarget.cpp +++ b/packages/react-native/ReactCommon/jsinspector-modern/RuntimeTarget.cpp @@ -8,8 +8,11 @@ #include namespace facebook::react::jsinspector_modern { -RuntimeTarget::RuntimeTarget(RuntimeTargetDelegate& delegate) - : delegate_(delegate) {} + +RuntimeTarget::RuntimeTarget( + RuntimeTargetDelegate& delegate, + RuntimeExecutor executor) + : delegate_(delegate), executor_(executor) {} std::shared_ptr RuntimeTarget::createAgent( FrontendChannel channel, diff --git a/packages/react-native/ReactCommon/jsinspector-modern/RuntimeTarget.h b/packages/react-native/ReactCommon/jsinspector-modern/RuntimeTarget.h index a067ed10e70..f83f3a66b68 100644 --- a/packages/react-native/ReactCommon/jsinspector-modern/RuntimeTarget.h +++ b/packages/react-native/ReactCommon/jsinspector-modern/RuntimeTarget.h @@ -7,6 +7,7 @@ #pragma once +#include #include "InspectorInterfaces.h" #include "RuntimeAgent.h" #include "SessionState.h" @@ -53,8 +54,12 @@ class JSINSPECTOR_EXPORT RuntimeTarget final { * \param delegate The object that will receive events from this target. * The caller is responsible for ensuring that the delegate outlives this * object. + * \param executor A RuntimeExecutor that can be used to schedule work on + * the JS runtime's thread. The executor's queue should be empty when + * RuntimeTarget is constructed (i.e. anything scheduled during the + * constructor should be executed before any user code is run). */ - explicit RuntimeTarget(RuntimeTargetDelegate& delegate); + RuntimeTarget(RuntimeTargetDelegate& delegate, RuntimeExecutor executor); RuntimeTarget(const RuntimeTarget&) = delete; RuntimeTarget(RuntimeTarget&&) = delete; @@ -77,6 +82,7 @@ class JSINSPECTOR_EXPORT RuntimeTarget final { private: RuntimeTargetDelegate& delegate_; + RuntimeExecutor executor_; std::list> agents_; /** diff --git a/packages/react-native/ReactCommon/jsinspector-modern/tests/PageTargetTest.cpp b/packages/react-native/ReactCommon/jsinspector-modern/tests/PageTargetTest.cpp index 9f68661833e..205b8bc6b3f 100644 --- a/packages/react-native/ReactCommon/jsinspector-modern/tests/PageTargetTest.cpp +++ b/packages/react-native/ReactCommon/jsinspector-modern/tests/PageTargetTest.cpp @@ -56,6 +56,9 @@ class PageTargetTest : public Test { MockInstanceTargetDelegate instanceTargetDelegate_; MockRuntimeTargetDelegate runtimeTargetDelegate_; + // We don't have access to a jsi::Runtime in these tests, so just use an + // executor that never runs the scheduled callbacks. + RuntimeExecutor runtimeExecutor_ = [](auto) {}; UniquePtrFactory> runtimeAgentDelegates_; @@ -252,7 +255,8 @@ TEST_F(PageTargetTest, ConnectToAlreadyRegisteredInstanceWithEvents) { TEST_F(PageTargetTest, ConnectToAlreadyRegisteredRuntimeWithEvents) { auto& instanceTarget = page_.registerInstance(instanceTargetDelegate_); - auto& runtimeTarget = instanceTarget.registerRuntime(runtimeTargetDelegate_); + auto& runtimeTarget = + instanceTarget.registerRuntime(runtimeTargetDelegate_, runtimeExecutor_); connect(); @@ -287,8 +291,8 @@ TEST_F(PageTargetTest, ConnectToAlreadyRegisteredRuntimeWithEvents) { TEST_F(PageTargetProtocolTest, RuntimeAgentDelegateLifecycle) { { auto& instanceTarget = page_.registerInstance(instanceTargetDelegate_); - auto& runtimeTarget = - instanceTarget.registerRuntime(runtimeTargetDelegate_); + auto& runtimeTarget = instanceTarget.registerRuntime( + runtimeTargetDelegate_, runtimeExecutor_); EXPECT_TRUE(runtimeAgentDelegates_[0]); @@ -300,8 +304,8 @@ TEST_F(PageTargetProtocolTest, RuntimeAgentDelegateLifecycle) { { auto& instanceTarget = page_.registerInstance(instanceTargetDelegate_); - auto& runtimeTarget = - instanceTarget.registerRuntime(runtimeTargetDelegate_); + auto& runtimeTarget = instanceTarget.registerRuntime( + runtimeTargetDelegate_, runtimeExecutor_); EXPECT_TRUE(runtimeAgentDelegates_[1]); @@ -316,7 +320,8 @@ TEST_F(PageTargetProtocolTest, MethodNotHandledByRuntimeAgentDelegate) { InSequence s; auto& instanceTarget = page_.registerInstance(instanceTargetDelegate_); - auto& runtimeTarget = instanceTarget.registerRuntime(runtimeTargetDelegate_); + auto& runtimeTarget = + instanceTarget.registerRuntime(runtimeTargetDelegate_, runtimeExecutor_); ASSERT_TRUE(runtimeAgentDelegates_[0]); EXPECT_CALL(*runtimeAgentDelegates_[0], handleRequest(_)) @@ -341,7 +346,8 @@ TEST_F(PageTargetProtocolTest, MethodHandledByRuntimeAgentDelegate) { InSequence s; auto& instanceTarget = page_.registerInstance(instanceTargetDelegate_); - auto& runtimeTarget = instanceTarget.registerRuntime(runtimeTargetDelegate_); + auto& runtimeTarget = + instanceTarget.registerRuntime(runtimeTargetDelegate_, runtimeExecutor_); ASSERT_TRUE(runtimeAgentDelegates_[0]); EXPECT_CALL(*runtimeAgentDelegates_[0], handleRequest(_)) @@ -384,7 +390,8 @@ TEST_F(PageTargetProtocolTest, MessageRoutingWhileNoRuntimeAgentDelegate) { })"); auto& instanceTarget = page_.registerInstance(instanceTargetDelegate_); - auto& runtimeTarget = instanceTarget.registerRuntime(runtimeTargetDelegate_); + auto& runtimeTarget = + instanceTarget.registerRuntime(runtimeTargetDelegate_, runtimeExecutor_); ASSERT_TRUE(runtimeAgentDelegates_[0]); EXPECT_CALL(*runtimeAgentDelegates_[0], handleRequest(_)) @@ -432,7 +439,8 @@ TEST_F(PageTargetProtocolTest, InstanceWithNullRuntimeAgentDelegate) { .WillRepeatedly(ReturnNull()); auto& instanceTarget = page_.registerInstance(instanceTargetDelegate_); - auto& runtimeTarget = instanceTarget.registerRuntime(runtimeTargetDelegate_); + auto& runtimeTarget = + instanceTarget.registerRuntime(runtimeTargetDelegate_, runtimeExecutor_); EXPECT_FALSE(runtimeAgentDelegates_[0]); @@ -466,7 +474,7 @@ TEST_F(PageTargetProtocolTest, RuntimeAgentDelegateHasAccessToSessionState) { })"); auto& instanceTarget = page_.registerInstance(instanceTargetDelegate_); - instanceTarget.registerRuntime(runtimeTargetDelegate_); + instanceTarget.registerRuntime(runtimeTargetDelegate_, runtimeExecutor_); ASSERT_TRUE(runtimeAgentDelegates_[0]); EXPECT_TRUE(runtimeAgentDelegates_[0]->sessionState.isRuntimeDomainEnabled); diff --git a/packages/react-native/ReactCommon/react/runtime/ReactInstance.cpp b/packages/react-native/ReactCommon/react/runtime/ReactInstance.cpp index 0f5fca84bab..afefd87605c 100644 --- a/packages/react-native/ReactCommon/react/runtime/ReactInstance.cpp +++ b/packages/react-native/ReactCommon/react/runtime/ReactInstance.cpp @@ -37,10 +37,6 @@ ReactInstance::ReactInstance( jsErrorHandler_(jsErrorHandlingFunc), hasFatalJsError_(std::make_shared(false)), parentInspectorTarget_(parentInspectorTarget) { - if (parentInspectorTarget_) { - inspectorTarget_ = &parentInspectorTarget_->registerInstance(*this); - runtimeInspectorTarget_ = &inspectorTarget_->registerRuntime(*runtime_); - } auto runtimeExecutor = [weakRuntime = std::weak_ptr(runtime_), weakTimerManager = std::weak_ptr(timerManager_), @@ -88,6 +84,12 @@ ReactInstance::ReactInstance( } }; + if (parentInspectorTarget_) { + inspectorTarget_ = &parentInspectorTarget_->registerInstance(*this); + runtimeInspectorTarget_ = + &inspectorTarget_->registerRuntime(*runtime_, runtimeExecutor); + } + runtimeScheduler_ = std::make_shared(std::move(runtimeExecutor));