From adec8d303b33d354946b17fc3dc4c8d22d8a9531 Mon Sep 17 00:00:00 2001 From: Moti Zilberman Date: Thu, 1 Feb 2024 11:03:41 -0800 Subject: [PATCH] Create RuntimeAgent interface to handle messages for VM (#42635) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/42635 Changelog: [Internal] Adds a RuntimeAgent interface to the modern CDP backend, plus an `InstanceTargetDelegate::createRuntimeAgent()` method. This allows the RN integration to provide an engine-specific CDP implementation. This diff includes all the plumbing in Bridge and Bridgeless to route `createRuntimeAgent()` calls to the right place - ending up at `JSExecutor::createRuntimeAgent()` and `JSIRuntimeHolder::createInspectorAgent` respectively - at which point we currently return `nullptr` to signify that JS debugging isn't supported. ## Next steps In upcoming diffs we'll add concrete implementations of `RuntimeAgent`, and teach both Bridge and Bridgeless to create them as appropriate: * `HermesRuntimeAgent` for Hermes * `FallbackRuntimeAgent` for all other JS engines (JSI or not) We'll also (likely) add assertions to ensure that any JSI runtime that reports itself as "inspectable" (a flag used to control some of the in-app debugging UI) comes with a non-default `createRuntimeAgent()` implementation. We avoid this for now to prevent crashing the modern backend on Hermes. NOTE: Like the rest of the modern CDP backend, the `RuntimeAgent` API is 100% experimental and subject to change without notice. A *future* version of this API will allow out-of-tree JSI engines to integrate with the modern CDP backend. Either way, it is intended strictly for the use case of integrating with a JS engine, not for adding any other framework-level CDP functionality. Reviewed By: huntie Differential Revision: D51231326 fbshipit-source-id: 81e87c5134df73cc4aac0f9d5793a5236b5720d6 --- .../Libraries/Blob/React-RCTBlob.podspec | 5 + .../CoreModules/React-CoreModules.podspec | 5 + .../ReactCommon/cxxreact/Instance.cpp | 5 + .../ReactCommon/cxxreact/Instance.h | 4 + .../ReactCommon/cxxreact/JSExecutor.cpp | 7 + .../ReactCommon/cxxreact/JSExecutor.h | 11 +- .../ReactCommon/cxxreact/NativeToJsBridge.cpp | 7 + .../ReactCommon/cxxreact/NativeToJsBridge.h | 8 + .../jsiexecutor/React-jsiexecutor.podspec | 1 + .../jsinspector-modern/InstanceAgent.cpp | 17 +- .../jsinspector-modern/InstanceAgent.h | 14 +- .../jsinspector-modern/InstanceTarget.cpp | 5 +- .../jsinspector-modern/InstanceTarget.h | 13 + .../jsinspector-modern/PageAgent.cpp | 52 ++-- .../ReactCommon/jsinspector-modern/Parsing.h | 7 + .../ReactCommon/jsinspector-modern/ReactCdp.h | 1 + .../jsinspector-modern/RuntimeAgent.cpp | 14 ++ .../jsinspector-modern/RuntimeAgent.h | 35 +++ .../jsinspector-modern/tests/InspectorMocks.h | 25 +- .../tests/PageTargetTest.cpp | 225 ++++++++++++------ .../react/runtime/JSRuntimeFactory.cpp | 9 + .../react/runtime/JSRuntimeFactory.h | 11 + .../react/runtime/React-RuntimeHermes.podspec | 2 +- .../react/runtime/ReactInstance.cpp | 6 + .../ReactCommon/react/runtime/ReactInstance.h | 4 + packages/rn-tester/Podfile.lock | 92 ++++--- .../RNTesterPods.xcodeproj/project.pbxproj | 32 +-- 27 files changed, 443 insertions(+), 174 deletions(-) create mode 100644 packages/react-native/ReactCommon/jsinspector-modern/RuntimeAgent.cpp create mode 100644 packages/react-native/ReactCommon/jsinspector-modern/RuntimeAgent.h diff --git a/packages/react-native/Libraries/Blob/React-RCTBlob.podspec b/packages/react-native/Libraries/Blob/React-RCTBlob.podspec index 6d1c24ea00f..8b48d45e7f4 100644 --- a/packages/react-native/Libraries/Blob/React-RCTBlob.podspec +++ b/packages/react-native/Libraries/Blob/React-RCTBlob.podspec @@ -22,6 +22,9 @@ folly_version = folly_config[:version] header_search_paths = [ "\"$(PODS_ROOT)/RCT-Folly\"", + "\"$(PODS_ROOT)/boost\"", + "\"$(PODS_ROOT)/DoubleConversion\"", + "\"$(PODS_ROOT)/fmt/include\"", "\"${PODS_ROOT}/Headers/Public/React-Codegen/react/renderer/components\"", ] @@ -44,6 +47,8 @@ Pod::Spec.new do |s| "HEADER_SEARCH_PATHS" => header_search_paths.join(' ') } + s.dependency "DoubleConversion" + s.dependency "fmt", "9.1.0" s.dependency "RCT-Folly", folly_version s.dependency "React-jsi" s.dependency "React-Core/RCTBlobHeaders" diff --git a/packages/react-native/React/CoreModules/React-CoreModules.podspec b/packages/react-native/React/CoreModules/React-CoreModules.podspec index 9a0938f25fc..b6f2cfb1e23 100644 --- a/packages/react-native/React/CoreModules/React-CoreModules.podspec +++ b/packages/react-native/React/CoreModules/React-CoreModules.podspec @@ -22,8 +22,11 @@ folly_version = folly_config[:version] socket_rocket_version = '0.7.0' header_search_paths = [ + "\"$(PODS_ROOT)/boost\"", "\"$(PODS_TARGET_SRCROOT)/React/CoreModules\"", "\"$(PODS_ROOT)/RCT-Folly\"", + "\"$(PODS_ROOT)/DoubleConversion\"", + "\"$(PODS_ROOT)/fmt/include\"", "\"${PODS_ROOT}/Headers/Public/React-Codegen/react/renderer/components\"", ] @@ -45,6 +48,8 @@ Pod::Spec.new do |s| "HEADER_SEARCH_PATHS" => header_search_paths.join(" ") } s.framework = "UIKit" + s.dependency "DoubleConversion" + s.dependency "fmt", "9.1.0" s.dependency "RCT-Folly", folly_version s.dependency "RCTTypeSafety", version s.dependency "React-Core/CoreModulesHeaders", version diff --git a/packages/react-native/ReactCommon/cxxreact/Instance.cpp b/packages/react-native/ReactCommon/cxxreact/Instance.cpp index e7a8eba6252..f6120eb76bd 100644 --- a/packages/react-native/ReactCommon/cxxreact/Instance.cpp +++ b/packages/react-native/ReactCommon/cxxreact/Instance.cpp @@ -316,4 +316,9 @@ void Instance::JSCallInvoker::scheduleAsync( } } +std::unique_ptr Instance::createRuntimeAgent( + jsinspector_modern::FrontendChannel frontendChannel) { + return nativeToJsBridge_->createRuntimeAgent(frontendChannel); +} + } // namespace facebook::react diff --git a/packages/react-native/ReactCommon/cxxreact/Instance.h b/packages/react-native/ReactCommon/cxxreact/Instance.h index 1cc3750be10..747ed4524e2 100644 --- a/packages/react-native/ReactCommon/cxxreact/Instance.h +++ b/packages/react-native/ReactCommon/cxxreact/Instance.h @@ -151,6 +151,10 @@ class RN_EXPORT Instance : private jsinspector_modern::InstanceTargetDelegate { std::unique_ptr startupScript, std::string startupScriptSourceURL); + // From InstanceTargetDelegate + std::unique_ptr createRuntimeAgent( + jsinspector_modern::FrontendChannel frontendChannel) override; + std::shared_ptr callback_; std::shared_ptr nativeToJsBridge_; std::shared_ptr moduleRegistry_; diff --git a/packages/react-native/ReactCommon/cxxreact/JSExecutor.cpp b/packages/react-native/ReactCommon/cxxreact/JSExecutor.cpp index fa0cb3f1944..1989bb951f6 100644 --- a/packages/react-native/ReactCommon/cxxreact/JSExecutor.cpp +++ b/packages/react-native/ReactCommon/cxxreact/JSExecutor.cpp @@ -34,4 +34,11 @@ double JSExecutor::performanceNow() { return duration / NANOSECONDS_IN_MILLISECOND; } +std::unique_ptr +JSExecutor::createRuntimeAgent( + jsinspector_modern::FrontendChannel frontendChannel) { + (void)frontendChannel; + return nullptr; +} + } // namespace facebook::react diff --git a/packages/react-native/ReactCommon/cxxreact/JSExecutor.h b/packages/react-native/ReactCommon/cxxreact/JSExecutor.h index 09a1ac67296..3fdb5f495c3 100644 --- a/packages/react-native/ReactCommon/cxxreact/JSExecutor.h +++ b/packages/react-native/ReactCommon/cxxreact/JSExecutor.h @@ -12,6 +12,8 @@ #include #include +#include +#include #ifndef RN_EXPORT #define RN_EXPORT __attribute__((visibility("default"))) @@ -111,7 +113,8 @@ class RN_EXPORT JSExecutor { /** * Returns whether or not the underlying executor supports debugging via the - * Chrome remote debugging protocol. + * Chrome remote debugging protocol. If true, the executor should also + * override the \c createRuntimeAgent method. */ virtual bool isInspectable() { return false; @@ -136,6 +139,12 @@ class RN_EXPORT JSExecutor { const std::string& bundlePath); static double performanceNow(); + + /** + * Create a RuntimeAgent that can be used to debug the JS VM instance. + */ + virtual std::unique_ptr createRuntimeAgent( + jsinspector_modern::FrontendChannel frontendChannel); }; } // namespace facebook::react diff --git a/packages/react-native/ReactCommon/cxxreact/NativeToJsBridge.cpp b/packages/react-native/ReactCommon/cxxreact/NativeToJsBridge.cpp index 5b48900d789..c9f7b17063a 100644 --- a/packages/react-native/ReactCommon/cxxreact/NativeToJsBridge.cpp +++ b/packages/react-native/ReactCommon/cxxreact/NativeToJsBridge.cpp @@ -343,4 +343,11 @@ NativeToJsBridge::getDecoratedNativeMethodCallInvoker( m_delegate, std::move(nativeMethodCallInvoker)); } +std::unique_ptr +NativeToJsBridge::createRuntimeAgent( + jsinspector_modern::FrontendChannel frontendChannel) { + auto agent = m_executor->createRuntimeAgent(std::move(frontendChannel)); + return agent; +} + } // namespace facebook::react diff --git a/packages/react-native/ReactCommon/cxxreact/NativeToJsBridge.h b/packages/react-native/ReactCommon/cxxreact/NativeToJsBridge.h index f8f59f596e4..d7d949b5f67 100644 --- a/packages/react-native/ReactCommon/cxxreact/NativeToJsBridge.h +++ b/packages/react-native/ReactCommon/cxxreact/NativeToJsBridge.h @@ -15,6 +15,7 @@ #include #include #include +#include namespace folly { struct dynamic; @@ -106,6 +107,13 @@ class NativeToJsBridge { std::shared_ptr getDecoratedNativeMethodCallInvoker( std::shared_ptr nativeInvoker) const; + /** + * Create a RuntimeAgent that can be used to debug the underlying JS VM + * instance. + */ + virtual std::unique_ptr createRuntimeAgent( + jsinspector_modern::FrontendChannel frontendChannel); + private: // This is used to avoid a race condition where a proxyCallback gets queued // after ~NativeToJsBridge(), on the same thread. In that case, the callback diff --git a/packages/react-native/ReactCommon/jsiexecutor/React-jsiexecutor.podspec b/packages/react-native/ReactCommon/jsiexecutor/React-jsiexecutor.podspec index b0edfc93d04..894f6614f44 100644 --- a/packages/react-native/ReactCommon/jsiexecutor/React-jsiexecutor.podspec +++ b/packages/react-native/ReactCommon/jsiexecutor/React-jsiexecutor.podspec @@ -43,6 +43,7 @@ Pod::Spec.new do |s| s.dependency "DoubleConversion" s.dependency "fmt", "9.1.0" s.dependency "glog" + add_dependency(s, "React-jsinspector", :framework_name => 'jsinspector_modern') if ENV['USE_HERMES'] == nil || ENV['USE_HERMES'] == "1" s.dependency 'hermes-engine' diff --git a/packages/react-native/ReactCommon/jsinspector-modern/InstanceAgent.cpp b/packages/react-native/ReactCommon/jsinspector-modern/InstanceAgent.cpp index c5020edde20..386f62109d7 100644 --- a/packages/react-native/ReactCommon/jsinspector-modern/InstanceAgent.cpp +++ b/packages/react-native/ReactCommon/jsinspector-modern/InstanceAgent.cpp @@ -11,24 +11,19 @@ namespace facebook::react::jsinspector_modern { InstanceAgent::InstanceAgent( FrontendChannel frontendChannel, - InstanceTarget& target) - : frontendChannel_(frontendChannel), target_(target) { + InstanceTarget& target, + std::unique_ptr runtimeAgent) + : frontendChannel_(frontendChannel), + target_(target), + runtimeAgent_(std::move(runtimeAgent)) { (void)target_; } bool InstanceAgent::handleRequest(const cdp::PreparsedRequest& req) { - // NOTE: Our implementation of @cdp Runtime.getHeapUsage is a stub. - if (req.method == "Runtime.getHeapUsage") { - folly::dynamic res = folly::dynamic::object("id", req.id)( - "result", folly::dynamic::object("usedSize", 0)("totalSize", 0)); - frontendChannel_(folly::toJson(res)); + if (runtimeAgent_ && runtimeAgent_->handleRequest(req)) { return true; } return false; } -int InstanceAgent::getExecutionContextId() const { - return 1; -} - } // namespace facebook::react::jsinspector_modern diff --git a/packages/react-native/ReactCommon/jsinspector-modern/InstanceAgent.h b/packages/react-native/ReactCommon/jsinspector-modern/InstanceAgent.h index 24759fe5744..52538786495 100644 --- a/packages/react-native/ReactCommon/jsinspector-modern/InstanceAgent.h +++ b/packages/react-native/ReactCommon/jsinspector-modern/InstanceAgent.h @@ -9,6 +9,7 @@ #include #include +#include #include namespace facebook::react::jsinspector_modern { @@ -27,10 +28,13 @@ class InstanceAgent { * \param target The InstanceTarget that this agent is attached to. The * caller is responsible for ensuring that the InstanceTarget outlives this * object. + * \param runtimeAgent The RuntimeAgent that this agent will use to + * communicate with the JS runtime. */ explicit InstanceAgent( FrontendChannel frontendChannel, - InstanceTarget& target); + InstanceTarget& target, + std::unique_ptr runtimeAgent); /** * Handle a CDP request. The response will be sent over the provided @@ -39,16 +43,10 @@ class InstanceAgent { */ bool handleRequest(const cdp::PreparsedRequest& req); - /** - * Get the ID of the execution context that this agent is associated with. - * \see - * https://chromedevtools.github.io/devtools-protocol/tot/Runtime/#type-ExecutionContextId - */ - int getExecutionContextId() const; - private: FrontendChannel frontendChannel_; InstanceTarget& target_; + std::unique_ptr runtimeAgent_; }; } // namespace facebook::react::jsinspector_modern diff --git a/packages/react-native/ReactCommon/jsinspector-modern/InstanceTarget.cpp b/packages/react-native/ReactCommon/jsinspector-modern/InstanceTarget.cpp index c31c37cf38f..246baaf346f 100644 --- a/packages/react-native/ReactCommon/jsinspector-modern/InstanceTarget.cpp +++ b/packages/react-native/ReactCommon/jsinspector-modern/InstanceTarget.cpp @@ -20,6 +20,9 @@ InstanceTargetDelegate::~InstanceTargetDelegate() {} std::unique_ptr InstanceTarget::createAgent( FrontendChannel channel) { - return std::make_unique(channel, *this); + auto runtimeAgent = delegate_.createRuntimeAgent(channel); + return std::make_unique( + channel, *this, std::move(runtimeAgent)); } + } // namespace facebook::react::jsinspector_modern diff --git a/packages/react-native/ReactCommon/jsinspector-modern/InstanceTarget.h b/packages/react-native/ReactCommon/jsinspector-modern/InstanceTarget.h index 75fec740892..3f50756e70a 100644 --- a/packages/react-native/ReactCommon/jsinspector-modern/InstanceTarget.h +++ b/packages/react-native/ReactCommon/jsinspector-modern/InstanceTarget.h @@ -8,8 +8,10 @@ #pragma once #include +#include #include +#include #include namespace facebook::react::jsinspector_modern { @@ -29,6 +31,17 @@ class InstanceTargetDelegate { InstanceTargetDelegate& operator=(const InstanceTargetDelegate&) = delete; InstanceTargetDelegate& operator=(InstanceTargetDelegate&&) = default; + /** + * Create a new RuntimeAgent that can be used to debug the underlying JS VM. + * The agent will be destroyed when the session ends or the InstanceTarget is + * unregistered from its PageTarget (whichever happens first). + * \param channel A thread-safe channel for sending CDP messages to the + * frontend. + * \returns The new agent, or nullptr if the target does not support JS + * debugging. + */ + virtual std::unique_ptr createRuntimeAgent( + FrontendChannel channel) = 0; virtual ~InstanceTargetDelegate(); }; diff --git a/packages/react-native/ReactCommon/jsinspector-modern/PageAgent.cpp b/packages/react-native/ReactCommon/jsinspector-modern/PageAgent.cpp index 0d7831b4bc4..5223ee719c4 100644 --- a/packages/react-native/ReactCommon/jsinspector-modern/PageAgent.cpp +++ b/packages/react-native/ReactCommon/jsinspector-modern/PageAgent.cpp @@ -71,24 +71,15 @@ void PageAgent::handleRequest(const cdp::PreparsedRequest& req) { return; } + bool shouldSendOKResponse = false; + if (req.method == "Runtime.enable") { runtimeEnabled_ = true; - folly::dynamic res = folly::dynamic::object("id", req.id)( - "result", folly::dynamic::object()); - std::string json = folly::toJson(res); - frontendChannel_(json); - - if (instanceAgent_) { - folly::dynamic params = folly::dynamic::object( - "context", - folly::dynamic::object("id", instanceAgent_->getExecutionContextId())( - "origin", "")("name", "React Native")); - folly::dynamic contextCreated = folly::dynamic::object( - "method", "Runtime.executionContextCreated")("params", params); - frontendChannel_(folly::toJson(contextCreated)); - } - return; + // Fall through to letting the instance handle this request and send a + // response, but remember that we need to send a response in case the + // instance doesn't handle the request. + shouldSendOKResponse = true; } if (req.method == "Runtime.disable") { runtimeEnabled_ = false; @@ -96,13 +87,25 @@ void PageAgent::handleRequest(const cdp::PreparsedRequest& req) { "result", folly::dynamic::object()); std::string json = folly::toJson(res); frontendChannel_(json); - return; + + // Fall through to letting the instance handle this request and send a + // response, but remember that we need to send a response in case the + // instance doesn't handle the request. + shouldSendOKResponse = true; } if (instanceAgent_ && instanceAgent_->handleRequest(req)) { return; } + if (shouldSendOKResponse) { + folly::dynamic res = folly::dynamic::object("id", req.id)( + "result", folly::dynamic::object()); + std::string json = folly::toJson(res); + frontendChannel_(json); + return; + } + folly::dynamic res = folly::dynamic::object("id", req.id)( "error", folly::dynamic::object("code", -32601)( @@ -133,12 +136,8 @@ void PageAgent::setCurrentInstanceAgent( return; } if (previousInstanceAgent != nullptr) { - auto executionContextId = previousInstanceAgent->getExecutionContextId(); - folly::dynamic contextDestroyed = - folly::dynamic::object("method", "Runtime.executionContextDestroyed")( - "params", - folly::dynamic::object("executionContextId", executionContextId)); - frontendChannel_(folly::toJson(contextDestroyed)); + // TODO: Send Runtime.executionContextDestroyed here - at the moment we + // expect the runtime to do it for us. // Because we can only have a single instance, we can report all contexts // as cleared. @@ -147,13 +146,8 @@ void PageAgent::setCurrentInstanceAgent( frontendChannel_(folly::toJson(contextsCleared)); } if (instanceAgent_) { - folly::dynamic params = folly::dynamic::object( - "context", - folly::dynamic::object("id", instanceAgent_->getExecutionContextId())( - "origin", "")("name", "React Native")); - folly::dynamic contextCreated = folly::dynamic::object( - "method", "Runtime.executionContextCreated")("params", params); - frontendChannel_(folly::toJson(contextCreated)); + // TODO: Send Runtime.executionContextCreated here - at the moment we expect + // the runtime to do it for us. } } diff --git a/packages/react-native/ReactCommon/jsinspector-modern/Parsing.h b/packages/react-native/ReactCommon/jsinspector-modern/Parsing.h index 94d6401b6a1..4db24fcb2a3 100644 --- a/packages/react-native/ReactCommon/jsinspector-modern/Parsing.h +++ b/packages/react-native/ReactCommon/jsinspector-modern/Parsing.h @@ -36,6 +36,13 @@ struct PreparsedRequest { * The parameters passed to the method, if any. */ folly::dynamic params; + + /** + * Equality operator, useful for unit tests + */ + inline bool operator==(const PreparsedRequest& rhs) const { + return id == rhs.id && method == rhs.method && params == rhs.params; + } }; /** diff --git a/packages/react-native/ReactCommon/jsinspector-modern/ReactCdp.h b/packages/react-native/ReactCommon/jsinspector-modern/ReactCdp.h index edbba4ecece..da28a4ae8bc 100644 --- a/packages/react-native/ReactCommon/jsinspector-modern/ReactCdp.h +++ b/packages/react-native/ReactCommon/jsinspector-modern/ReactCdp.h @@ -9,3 +9,4 @@ #include #include +#include diff --git a/packages/react-native/ReactCommon/jsinspector-modern/RuntimeAgent.cpp b/packages/react-native/ReactCommon/jsinspector-modern/RuntimeAgent.cpp new file mode 100644 index 00000000000..084d8891a38 --- /dev/null +++ b/packages/react-native/ReactCommon/jsinspector-modern/RuntimeAgent.cpp @@ -0,0 +1,14 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#include + +namespace facebook::react::jsinspector_modern { + +RuntimeAgent::~RuntimeAgent() {} + +} // namespace facebook::react::jsinspector_modern diff --git a/packages/react-native/ReactCommon/jsinspector-modern/RuntimeAgent.h b/packages/react-native/ReactCommon/jsinspector-modern/RuntimeAgent.h new file mode 100644 index 00000000000..7beba2f653f --- /dev/null +++ b/packages/react-native/ReactCommon/jsinspector-modern/RuntimeAgent.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#pragma once + +#include + +namespace facebook::react::jsinspector_modern { + +/** + * An Agent interface that handles requests from the Chrome DevTools Protocol + * for a particular JS runtime instance. The exact mechanism of sending + * responses/events to the frontend is left up to the implementation, but + * implementations SHOULD use FrontendChannel or a similar abstraction. + */ +class RuntimeAgent { + public: + virtual ~RuntimeAgent(); + + /** + * Handle a CDP request. This implementation must perform any synchronization + * required between the thread on which this method is called and the thread + * where the JS runtime is executing. + * \returns true if this agent has responded, or will respond asynchronously, + * to the request (with either a success or error message). False if the + * agent expects another agent to respond to the request instead. + */ + virtual bool handleRequest(const cdp::PreparsedRequest& req) = 0; +}; + +} // namespace facebook::react::jsinspector_modern diff --git a/packages/react-native/ReactCommon/jsinspector-modern/tests/InspectorMocks.h b/packages/react-native/ReactCommon/jsinspector-modern/tests/InspectorMocks.h index aaafc57c18b..b77b63efd0f 100644 --- a/packages/react-native/ReactCommon/jsinspector-modern/tests/InspectorMocks.h +++ b/packages/react-native/ReactCommon/jsinspector-modern/tests/InspectorMocks.h @@ -121,6 +121,29 @@ class MockPageTargetDelegate : public PageTargetDelegate { MOCK_METHOD(void, onReload, (const PageReloadRequest& request), (override)); }; -class MockInstanceTargetDelegate : public InstanceTargetDelegate {}; +class MockInstanceTargetDelegate : public InstanceTargetDelegate { + public: + // InstanceTargetDelegate methods + MOCK_METHOD( + std::unique_ptr, + createRuntimeAgent, + (FrontendChannel channel), + (override)); +}; + +class MockRuntimeAgent : public RuntimeAgent { + public: + inline MockRuntimeAgent(FrontendChannel frontendChannel) + : frontendChannel(std::move(frontendChannel)) {} + + // RuntimeAgent methods + MOCK_METHOD( + bool, + handleRequest, + (const cdp::PreparsedRequest& req), + (override)); + + const FrontendChannel frontendChannel; +}; } // namespace facebook::react::jsinspector_modern diff --git a/packages/react-native/ReactCommon/jsinspector-modern/tests/PageTargetTest.cpp b/packages/react-native/ReactCommon/jsinspector-modern/tests/PageTargetTest.cpp index ae1c1062f17..3f7b1bc6fcf 100644 --- a/packages/react-native/ReactCommon/jsinspector-modern/tests/PageTargetTest.cpp +++ b/packages/react-native/ReactCommon/jsinspector-modern/tests/PageTargetTest.cpp @@ -27,6 +27,11 @@ namespace { class PageTargetTest : public Test { protected: + PageTargetTest() { + EXPECT_CALL(instanceTargetDelegate_, createRuntimeAgent(_)) + .WillRepeatedly(runtimeAgents_.lazily_make_unique()); + } + void connect() { ASSERT_FALSE(toPage_) << "Can only connect once in a PageTargetTest."; toPage_ = page_.connect( @@ -47,6 +52,10 @@ class PageTargetTest : public Test { PageTarget page_{pageTargetDelegate_}; + MockInstanceTargetDelegate instanceTargetDelegate_; + + UniquePtrFactory> runtimeAgents_; + private: UniquePtrFactory> remoteConnections_; @@ -183,17 +192,13 @@ TEST_F(PageTargetProtocolTest, PageReloadMethod) { } TEST_F(PageTargetProtocolTest, RegisterUnregisterInstanceWithoutEvents) { - MockInstanceTargetDelegate instanceTargetDelegate; - - auto& instanceTarget = page_.registerInstance(instanceTargetDelegate); + auto& instanceTarget = page_.registerInstance(instanceTargetDelegate_); page_.unregisterInstance(instanceTarget); } TEST_F(PageTargetTest, ConnectToAlreadyRegisteredInstanceWithoutEvents) { - MockInstanceTargetDelegate instanceTargetDelegate; - - auto& instanceTarget = page_.registerInstance(instanceTargetDelegate); + auto& instanceTarget = page_.registerInstance(instanceTargetDelegate_); connect(); @@ -212,26 +217,8 @@ TEST_F(PageTargetProtocolTest, RegisterUnregisterInstanceWithEvents) { "method": "Runtime.enable" })"); - MockInstanceTargetDelegate instanceTargetDelegate; + auto& instanceTarget = page_.registerInstance(instanceTargetDelegate_); - EXPECT_CALL(fromPage(), onMessage(JsonEq(R"({ - "method": "Runtime.executionContextCreated", - "params": { - "context": { - "id": 1, - "origin": "", - "name": "React Native" - } - } - })"))); - auto& instanceTarget = page_.registerInstance(instanceTargetDelegate); - - EXPECT_CALL(fromPage(), onMessage(JsonEq(R"({ - "method": "Runtime.executionContextDestroyed", - "params": { - "executionContextId": 1 - } - })"))); EXPECT_CALL(fromPage(), onMessage(JsonEq(R"({ "method": "Runtime.executionContextsCleared" })"))); @@ -239,88 +226,184 @@ TEST_F(PageTargetProtocolTest, RegisterUnregisterInstanceWithEvents) { } TEST_F(PageTargetTest, ConnectToAlreadyRegisteredInstanceWithEvents) { - MockInstanceTargetDelegate instanceTargetDelegate; - auto& instanceTarget = page_.registerInstance(instanceTargetDelegate); + auto& instanceTarget = page_.registerInstance(instanceTargetDelegate_); connect(); InSequence s; + EXPECT_CALL(*runtimeAgents_[0], handleRequest(Eq(cdp::preparse(R"({ + "id": 1, + "method": "Runtime.enable" + })")))) + .RetiresOnSaturation(); EXPECT_CALL(fromPage(), onMessage(JsonEq(R"({ "id": 1, "result": {} })"))); - EXPECT_CALL(fromPage(), onMessage(JsonEq(R"({ - "method": "Runtime.executionContextCreated", - "params": { - "context": { - "id": 1, - "origin": "", - "name": "React Native" - } - } - })"))); toPage_->sendMessage(R"({ "id": 1, "method": "Runtime.enable" })"); - EXPECT_CALL(fromPage(), onMessage(JsonEq(R"({ - "method": "Runtime.executionContextDestroyed", - "params": { - "executionContextId": 1 - } - })"))); EXPECT_CALL(fromPage(), onMessage(JsonEq(R"({ "method": "Runtime.executionContextsCleared" })"))); page_.unregisterInstance(instanceTarget); } -TEST_F(PageTargetProtocolTest, RespondToHeapUsageMethodWhileInstanceExists) { - // NOTE: This test will be deleted once we add some real CDP method - // implementations to InstanceAgent. +TEST_F(PageTargetProtocolTest, RuntimeAgentLifecycle) { + { + auto& instanceTarget = page_.registerInstance(instanceTargetDelegate_); + EXPECT_TRUE(runtimeAgents_[0]); + + page_.unregisterInstance(instanceTarget); + } + + EXPECT_FALSE(runtimeAgents_[0]); + + { + auto& instanceTarget = page_.registerInstance(instanceTargetDelegate_); + + EXPECT_TRUE(runtimeAgents_[1]); + + page_.unregisterInstance(instanceTarget); + } + + EXPECT_FALSE(runtimeAgents_[1]); +} + +TEST_F(PageTargetProtocolTest, MethodNotHandledByRuntimeAgent) { + InSequence s; + + auto& instanceTarget = page_.registerInstance(instanceTargetDelegate_); + + ASSERT_TRUE(runtimeAgents_[0]); + EXPECT_CALL(*runtimeAgents_[0], handleRequest(_)) + .WillOnce(Return(false)) + .RetiresOnSaturation(); EXPECT_CALL( - fromPage(), - onMessage(JsonParsed(AllOf( - AtJsonPtr("/error/code", Eq(-32601)), AtJsonPtr("/id", Eq(1)))))) + fromPage(), onMessage(JsonParsed(AtJsonPtr("/error/code", Eq(-32601))))) .RetiresOnSaturation(); - toPage_->sendMessage(R"({ "id": 1, - "method": "Runtime.getHeapUsage" - })"); - - MockInstanceTargetDelegate instanceTargetDelegate; - auto& instanceTarget = page_.registerInstance(instanceTargetDelegate); - - EXPECT_CALL(fromPage(), onMessage(JsonEq(R"({ - "id": 2, - "result": { - "usedSize": 0, - "totalSize": 0 - } - })"))); - - toPage_->sendMessage(R"({ - "id": 2, - "method": "Runtime.getHeapUsage" + "method": "CustomRuntimeDomain.Foo", + "params": { + "expression": "42" + } })"); page_.unregisterInstance(instanceTarget); +} + +TEST_F(PageTargetProtocolTest, MethodHandledByRuntimeAgent) { + InSequence s; + + auto& instanceTarget = page_.registerInstance(instanceTargetDelegate_); + + ASSERT_TRUE(runtimeAgents_[0]); + EXPECT_CALL(*runtimeAgents_[0], handleRequest(_)) + .WillOnce(Return(true)) + .RetiresOnSaturation(); + toPage_->sendMessage(R"({ + "id": 1, + "method": "CustomRuntimeDomain.Foo", + "params": { + "expression": "42" + } + })"); + + static constexpr auto kFooResponse = R"({ + "id": 1, + "result": { + "fooValue": 42 + } + })"; + EXPECT_CALL(fromPage(), onMessage(JsonEq(kFooResponse))) + .RetiresOnSaturation(); + runtimeAgents_[0]->frontendChannel(kFooResponse); + + page_.unregisterInstance(instanceTarget); +} + +TEST_F(PageTargetProtocolTest, MessageRoutingWhileNoRuntimeAgent) { + InSequence s; EXPECT_CALL( - fromPage(), - onMessage(JsonParsed(AllOf( - AtJsonPtr("/error/code", Eq(-32601)), AtJsonPtr("/id", Eq(3)))))) + fromPage(), onMessage(JsonParsed(AtJsonPtr("/error/code", Eq(-32601))))) .RetiresOnSaturation(); + toPage_->sendMessage(R"({ + "id": 1, + "method": "CustomRuntimeDomain.Foo", + "params": { + "expression": "42" + } + })"); + auto& instanceTarget = page_.registerInstance(instanceTargetDelegate_); + + ASSERT_TRUE(runtimeAgents_[0]); + EXPECT_CALL(*runtimeAgents_[0], handleRequest(_)) + .WillOnce(Return(true)) + .RetiresOnSaturation(); + toPage_->sendMessage(R"({ + "id": 2, + "method": "CustomRuntimeDomain.Foo", + "params": { + "expression": "42" + } + })"); + + static constexpr auto kFooResponse = R"({ + "id": 2, + "result": { + "fooValue": 42 + } + })"; + EXPECT_CALL(fromPage(), onMessage(JsonEq(kFooResponse))) + .RetiresOnSaturation(); + runtimeAgents_[0]->frontendChannel(kFooResponse); + + page_.unregisterInstance(instanceTarget); + + EXPECT_FALSE(runtimeAgents_[0]); + + EXPECT_CALL( + fromPage(), onMessage(JsonParsed(AtJsonPtr("/error/code", Eq(-32601))))) + .RetiresOnSaturation(); toPage_->sendMessage(R"({ "id": 3, - "method": "Runtime.getHeapUsage" + "method": "CustomRuntimeDomain.Foo", + "params": { + "expression": "42" + } })"); } +TEST_F(PageTargetProtocolTest, InstanceWithNullRuntimeAgent) { + InSequence s; + + EXPECT_CALL(instanceTargetDelegate_, createRuntimeAgent(_)) + .WillRepeatedly(ReturnNull()); + + auto& instanceTarget = page_.registerInstance(instanceTargetDelegate_); + + EXPECT_FALSE(runtimeAgents_[0]); + + EXPECT_CALL( + fromPage(), onMessage(JsonParsed(AtJsonPtr("/error/code", Eq(-32601))))) + .RetiresOnSaturation(); + toPage_->sendMessage(R"({ + "id": 1, + "method": "CustomRuntimeDomain.Foo", + "params": { + "expression": "42" + } + })"); + + page_.unregisterInstance(instanceTarget); +} + } // namespace facebook::react::jsinspector_modern diff --git a/packages/react-native/ReactCommon/react/runtime/JSRuntimeFactory.cpp b/packages/react-native/ReactCommon/react/runtime/JSRuntimeFactory.cpp index a0b11fe6686..e9e338b539a 100644 --- a/packages/react-native/ReactCommon/react/runtime/JSRuntimeFactory.cpp +++ b/packages/react-native/ReactCommon/react/runtime/JSRuntimeFactory.cpp @@ -8,6 +8,7 @@ #include "JSRuntimeFactory.h" namespace facebook::react { + jsi::Runtime& JSIRuntimeHolder::getRuntime() noexcept { return *runtime_; } @@ -16,4 +17,12 @@ JSIRuntimeHolder::JSIRuntimeHolder(std::unique_ptr runtime) : runtime_(std::move(runtime)) { assert(runtime_ != nullptr); } + +std::unique_ptr +JSIRuntimeHolder::createInspectorAgent( + jsinspector_modern::FrontendChannel frontendChannel) { + (void)frontendChannel; + return nullptr; +} + } // namespace facebook::react diff --git a/packages/react-native/ReactCommon/react/runtime/JSRuntimeFactory.h b/packages/react-native/ReactCommon/react/runtime/JSRuntimeFactory.h index 110c1f26590..0ffdb7896d7 100644 --- a/packages/react-native/ReactCommon/react/runtime/JSRuntimeFactory.h +++ b/packages/react-native/ReactCommon/react/runtime/JSRuntimeFactory.h @@ -10,6 +10,7 @@ #include #include #include +#include namespace facebook::react { @@ -20,6 +21,14 @@ class JSRuntime { public: virtual jsi::Runtime& getRuntime() noexcept = 0; + /** + * Creates a new inspector agent for this runtime, if the runtime is + * inspectable. Returns nullptr otherwise. + * \see InspectorTargetDelegate::createRuntimeAgent + */ + virtual std::unique_ptr + createInspectorAgent(jsinspector_modern::FrontendChannel frontendChannel) = 0; + virtual ~JSRuntime() = default; }; @@ -40,6 +49,8 @@ class JSRuntimeFactory { class JSIRuntimeHolder : public JSRuntime { public: jsi::Runtime& getRuntime() noexcept override; + std::unique_ptr createInspectorAgent( + jsinspector_modern::FrontendChannel frontendChannel) override; explicit JSIRuntimeHolder(std::unique_ptr runtime); diff --git a/packages/react-native/ReactCommon/react/runtime/React-RuntimeHermes.podspec b/packages/react-native/ReactCommon/react/runtime/React-RuntimeHermes.podspec index 15ba2bde3ea..eeb27776bf6 100644 --- a/packages/react-native/ReactCommon/react/runtime/React-RuntimeHermes.podspec +++ b/packages/react-native/ReactCommon/react/runtime/React-RuntimeHermes.podspec @@ -33,7 +33,7 @@ Pod::Spec.new do |s| s.source = source s.source_files = "hermes/*.{cpp,h}" s.header_dir = "react/runtime/hermes" - s.pod_target_xcconfig = { "HEADER_SEARCH_PATHS" => "\"${PODS_TARGET_SRCROOT}/../..\" \"${PODS_TARGET_SRCROOT}/../../hermes/executor\"", + s.pod_target_xcconfig = { "HEADER_SEARCH_PATHS" => "\"${PODS_TARGET_SRCROOT}/../..\" \"${PODS_TARGET_SRCROOT}/../../hermes/executor\" \"$(PODS_ROOT)/boost\"", "USE_HEADERMAP" => "YES", "CLANG_CXX_LANGUAGE_STANDARD" => "c++20", "GCC_WARN_PEDANTIC" => "YES" } diff --git a/packages/react-native/ReactCommon/react/runtime/ReactInstance.cpp b/packages/react-native/ReactCommon/react/runtime/ReactInstance.cpp index cea0bfd0cd4..988fd15242c 100644 --- a/packages/react-native/ReactCommon/react/runtime/ReactInstance.cpp +++ b/packages/react-native/ReactCommon/react/runtime/ReactInstance.cpp @@ -460,4 +460,10 @@ void ReactInstance::handleMemoryPressureJs(int pressureLevel) { } } +std::unique_ptr +ReactInstance::createRuntimeAgent(jsinspector_modern::FrontendChannel channel) { + auto agent = runtime_->createInspectorAgent(std::move(channel)); + return agent; +} + } // namespace facebook::react diff --git a/packages/react-native/ReactCommon/react/runtime/ReactInstance.h b/packages/react-native/ReactCommon/react/runtime/ReactInstance.h index e4fa651ae39..c52b916defe 100644 --- a/packages/react-native/ReactCommon/react/runtime/ReactInstance.h +++ b/packages/react-native/ReactCommon/react/runtime/ReactInstance.h @@ -72,6 +72,10 @@ class ReactInstance final : private jsinspector_modern::InstanceTargetDelegate { void unregisterFromInspector(); private: + // From InstanceTargetDelegate + std::unique_ptr createRuntimeAgent( + jsinspector_modern::FrontendChannel channel) override; + std::shared_ptr runtime_; std::shared_ptr jsMessageQueueThread_; std::shared_ptr bufferedRuntimeExecutor_; diff --git a/packages/rn-tester/Podfile.lock b/packages/rn-tester/Podfile.lock index 8a9a12708d9..55a146f89ec 100644 --- a/packages/rn-tester/Podfile.lock +++ b/packages/rn-tester/Podfile.lock @@ -123,6 +123,7 @@ PODS: - React-hermes - React-jsi - React-jsiexecutor + - React-jsinspector - React-perflogger - React-runtimescheduler - React-utils @@ -139,6 +140,7 @@ PODS: - React-hermes - React-jsi - React-jsiexecutor + - React-jsinspector - React-perflogger - React-runtimescheduler - React-utils @@ -154,7 +156,7 @@ PODS: - React-hermes - React-jsi - React-jsiexecutor - - React-jsinspector (= 1000.0.0) + - React-jsinspector - React-perflogger - React-runtimescheduler - React-utils @@ -172,7 +174,7 @@ PODS: - React-hermes - React-jsi - React-jsiexecutor - - React-jsinspector (= 1000.0.0) + - React-jsinspector - React-perflogger - React-runtimescheduler - React-utils @@ -189,6 +191,7 @@ PODS: - React-hermes - React-jsi - React-jsiexecutor + - React-jsinspector - React-perflogger - React-runtimescheduler - React-utils @@ -205,6 +208,7 @@ PODS: - React-hermes - React-jsi - React-jsiexecutor + - React-jsinspector - React-perflogger - React-runtimescheduler - React-utils @@ -221,6 +225,7 @@ PODS: - React-hermes - React-jsi - React-jsiexecutor + - React-jsinspector - React-perflogger - React-runtimescheduler - React-utils @@ -237,6 +242,7 @@ PODS: - React-hermes - React-jsi - React-jsiexecutor + - React-jsinspector - React-perflogger - React-runtimescheduler - React-utils @@ -253,6 +259,7 @@ PODS: - React-hermes - React-jsi - React-jsiexecutor + - React-jsinspector - React-perflogger - React-runtimescheduler - React-utils @@ -269,6 +276,7 @@ PODS: - React-hermes - React-jsi - React-jsiexecutor + - React-jsinspector - React-perflogger - React-runtimescheduler - React-utils @@ -285,6 +293,7 @@ PODS: - React-hermes - React-jsi - React-jsiexecutor + - React-jsinspector - React-perflogger - React-runtimescheduler - React-utils @@ -301,6 +310,7 @@ PODS: - React-hermes - React-jsi - React-jsiexecutor + - React-jsinspector - React-perflogger - React-runtimescheduler - React-utils @@ -317,6 +327,7 @@ PODS: - React-hermes - React-jsi - React-jsiexecutor + - React-jsinspector - React-perflogger - React-runtimescheduler - React-utils @@ -333,6 +344,7 @@ PODS: - React-hermes - React-jsi - React-jsiexecutor + - React-jsinspector - React-perflogger - React-runtimescheduler - React-utils @@ -349,17 +361,21 @@ PODS: - React-hermes - React-jsi - React-jsiexecutor + - React-jsinspector - React-perflogger - React-runtimescheduler - React-utils - SocketRocket (= 0.7.0) - Yoga - React-CoreModules (1000.0.0): + - DoubleConversion + - fmt (= 9.1.0) - RCT-Folly (= 2024.01.01.00) - RCTTypeSafety (= 1000.0.0) - React-Codegen - React-Core/CoreModulesHeaders (= 1000.0.0) - React-jsi (= 1000.0.0) + - React-jsinspector - React-NativeModulesApple - React-RCTBlob - React-RCTImage (= 1000.0.0) @@ -375,7 +391,7 @@ PODS: - React-callinvoker (= 1000.0.0) - React-debug (= 1000.0.0) - React-jsi (= 1000.0.0) - - React-jsinspector (= 1000.0.0) + - React-jsinspector - React-logger (= 1000.0.0) - React-perflogger (= 1000.0.0) - React-runtimeexecutor (= 1000.0.0) @@ -967,6 +983,7 @@ PODS: - RCT-Folly (= 2024.01.01.00) - React-cxxreact (= 1000.0.0) - React-jsi (= 1000.0.0) + - React-jsinspector - React-perflogger (= 1000.0.0) - React-jsinspector (1000.0.0): - DoubleConversion @@ -988,6 +1005,7 @@ PODS: - React-Core - React-cxxreact - React-jsi + - React-jsinspector - React-runtimeexecutor - ReactCommon/turbomodule/bridging - ReactCommon/turbomodule/core @@ -1026,12 +1044,15 @@ PODS: - React-utils - ReactCommon - React-RCTBlob (1000.0.0): + - DoubleConversion + - fmt (= 9.1.0) - hermes-engine - RCT-Folly (= 2024.01.01.00) - React-Codegen - React-Core/RCTBlobHeaders - React-Core/RCTWebSocket - React-jsi + - React-jsinspector - React-NativeModulesApple - React-RCTNetwork - ReactCommon @@ -1046,6 +1067,7 @@ PODS: - React-graphics - React-ImageManager - React-jsi + - React-jsinspector - React-nativeconfig - React-RCTImage - React-RCTText @@ -1445,9 +1467,9 @@ SPEC CHECKSUMS: FBLazyVector: f4492a543c5a8fa1502d3a5867e3f7252497cfe8 fmt: 4c2741a687cc09f0634a2e2c72a838b99f1ff120 glog: c5d68082e772fa1c511173d6b30a9de2c05a69a2 - hermes-engine: 555b5d9c3dd704cf1d6af043928ea8d6936f5945 - MyNativeView: dd2b0ad0ea90d05a1776b18c7d3470aa8b69f9d1 - NativeCxxModuleExample: 31e3c8426cf9ca356c76d253e6fc7e98921a7f4d + hermes-engine: b6ed6780e02b97c31d4d84407f579e3523177780 + MyNativeView: 08e59984e995c857953374e22082d058be3cb945 + NativeCxxModuleExample: 51569707f2da9a460d1ebf74a29d02f0a86c549e OCMock: 9491e4bec59e0b267d52a9184ff5605995e74be8 RCT-Folly: 045d6ecaa59d826c5736dfba0b2f4083ff8d79df RCTDeprecation: 3808e36294137f9ee5668f4df2e73dc079cd1dcf @@ -1455,32 +1477,32 @@ SPEC CHECKSUMS: RCTTypeSafety: 5f57d4ae5dfafc85a0f575d756c909b584722c52 React: cb6dc75e09f32aeddb4d8fb58a394a67219a92fe React-callinvoker: bae59cbd6affd712bbfc703839dad868ff35069d - React-Codegen: 25f5198c8c8158ec8ba01ee189d3a1d6b63379d5 - React-Core: f36333c59576ea93c31573bc71fe29893fbc4484 - React-CoreModules: 04058009e696161fd7a9f55b43e04819c41f12e3 - React-cxxreact: d7e2b4279e31dee6ec2af7fd8fdd42b1fd0e655c - React-debug: 296b501a90c41f83961f58c6d96a01330d499da5 - React-Fabric: 2a9b753ed7595c5357f3043fb57fa0055d2f4301 - React-FabricImage: da62cc5089fe6bdaa6ec0ab6ccca75c7d679065d - React-featureflags: 23f83a12963770bf3cff300e8990678192436b36 - React-graphics: 7e646eb47b666d2cb4e148ec4afcecc4253f1736 + React-Codegen: b66fa3765bc7a786e88e56ff92459a41dec00b0f + React-Core: 738c8db837b21aae813479f2eb284d5507a5c256 + React-CoreModules: 0b94c427e958c1b7ce268d03aa39a1f424d76901 + React-cxxreact: dadc89738f0089c3e2b85f36de940a088759b20d + React-debug: 4097205dd5ff0ada516e7df5b6721a9464a6f20b + React-Fabric: a3214cc064ca25e029aff0a42e2beb8c87b71861 + React-FabricImage: 6daf9bcd047ac1c424cfd7cae298089f8d495761 + React-featureflags: 36f601a77af59dca45877a298c804883dd04f8d0 + React-graphics: 8d54d923bef33e9f423d06c4fd51431f917a4b2f React-hermes: 14e7007ebbfcc9f674c9c4f3ac768aa587b6da79 - React-ImageManager: 716592dcbe11a4960e1eb3d82adb264ee15b5f6d - React-jserrorhandler: 13a0cce4e1e445d2ace089dc6122fb85411a11b3 + React-ImageManager: 44304168f3ec4733a0191dadee7b1711291272f4 + React-jserrorhandler: 2809ae4d87fb880d2c18be72bcaed114e79f3993 React-jsi: b7645527d3f77afdea4365488e47dbc5b293177f - React-jsiexecutor: 6baaff1e509ce9269b0457d3a9e442e3ae895c33 - React-jsinspector: 7f94cd18b2d33a9c1fab31fd11949f2e0f777120 - React-jsitracing: dd08057dd5b74119cb406beb42028da85ed5b8a5 + React-jsiexecutor: 42eeb6b4e73e1b50caa3940ad0189171723c6b29 + React-jsinspector: 363ee50f69cb39cc2ee4eef0705f2fc4a33f83f3 + React-jsitracing: 46474207a88a3978c08e191d9cf33a6457722d65 React-logger: 8486d7a1d32b972414b1d34a93470ee2562c6ee2 - React-Mapbuffer: fd0d0306c1c4326be5f18a61e978d32a66b20a85 - React-nativeconfig: 40a2c848083ef4065c163c854e1c82b5f9e9db84 - React-NativeModulesApple: 67ee4e22f916aceaa8ccfc9c849d3e7de5d55b0b + React-Mapbuffer: 9d18546228182de42aae8cb047baa5e14886a922 + React-nativeconfig: a5a38eee09c6a57824489bf9005d46d2e3fbb78b + React-NativeModulesApple: ff03b94214a1628f920b43bb64964860fc227f9f React-perflogger: 70d009f755dd10002183454cdf5ad9b22de4a1d7 React-RCTActionSheet: 943bd5f540f3af1e5a149c13c4de81858edf718a React-RCTAnimation: 07583f0ebfa7154f0e696a75c32a8f8b180fc8c5 React-RCTAppDelegate: 60cfe221df61de818f6e6b200ff55b4346e6ea7c - React-RCTBlob: da87f794f188db6539a05b8e13cbc5a198c94848 - React-RCTFabric: d28cb914dbf28c6316d5863d8e6e11ab66704d8f + React-RCTBlob: 2dbf6931deac47ff5d3910e4c81cdd856ea239d6 + React-RCTFabric: e613b7e4aec23114ee6999295ca97b3f0508ee0f React-RCTImage: 8f46d82257827c2332bc4108fddef1a840f440a7 React-RCTLinking: efa67827466e50e07c5471447c12e474cbc5e336 React-RCTNetwork: a80529d2d90f79caa5e31d49e840735a10d6d91a @@ -1489,17 +1511,17 @@ SPEC CHECKSUMS: React-RCTTest: 3b9f62c66c3814ccace402441597160aefc9e812 React-RCTText: d9925903524a7b179cf7803162a98038e0bfb4fd React-RCTVibration: 33bef249bc4a637ed91bf1cf0d94d9329381dc7b - React-rendererdebug: 0abbd75e947eeae23542f3bf7491b048ae063141 - React-rncore: e903b3d2819a25674403c548ec103f34bf02ba2b - React-RuntimeApple: b43ad6a5d60157f37ff3139e4dfb0cd6340e9be6 - React-RuntimeCore: 7cfdac312222d7260d8ba9604686fbb4aa4f8a13 + React-rendererdebug: bc0f2a1816a4607e85ed603170a413c44c1d2635 + React-rncore: 79f594bc32c96203ab607bd9868ec76caa2f290c + React-RuntimeApple: 504b50d20ddf82de9c2c527c6b5a09119e03b737 + React-RuntimeCore: 9dc8d98bc09b0797c2dca7a30be5e8f84ecf5746 React-runtimeexecutor: e1c32bc249dd3cf3919cb4664fd8dc84ef70cff7 - React-RuntimeHermes: e1d75303b20b761391be4b9443a0181d0ffe4d97 - React-runtimescheduler: d5fecf52a345c1e557499ee86c864089c2a01fb8 - React-utils: d468de964db1cfd301b450755ba00518777704c4 - ReactCommon: 9e0640c274b0b7d1d46fd9e4b0d2e518be4898d5 - ReactCommon-Samples: ca3ac1e08ee7f73d2b3b4a77946cfb44204d09ca - ScreenshotManager: 5cdc3d3097325172021474d2741a0852ba712e05 + React-RuntimeHermes: b1f60690c9ed90d448f1325355f72c662c02e49a + React-runtimescheduler: 0df238ee8e88e1b8874d332856ee7d36870be4ad + React-utils: 00c57742056c9c90e58b1a8cd06ca50d30528d6f + ReactCommon: 4148a8bfb8bbfdbea8f517f98cadeeb0f30c8de8 + ReactCommon-Samples: 5d703e2b5e1c8ddb812e7b7cace5a8effbcc6438 + ScreenshotManager: 823189e19d4e6f7d4792fe1db6b037df7efc2fab SocketRocket: abac6f5de4d4d62d24e11868d7a2f427e0ef940d Yoga: 53e99e2a727b8498ea9e8aed8d917b808c9ff2ea diff --git a/packages/rn-tester/RNTesterPods.xcodeproj/project.pbxproj b/packages/rn-tester/RNTesterPods.xcodeproj/project.pbxproj index 393fa1e581e..edfdf6aa584 100644 --- a/packages/rn-tester/RNTesterPods.xcodeproj/project.pbxproj +++ b/packages/rn-tester/RNTesterPods.xcodeproj/project.pbxproj @@ -7,7 +7,7 @@ objects = { /* Begin PBXBuildFile section */ - 111FD3845C7358250C2702B6 /* libPods-RNTesterIntegrationTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 63C6B5E1C2465D85E9BDB6E5 /* libPods-RNTesterIntegrationTests.a */; }; + 00915AE8006CF5DB156153DD /* Pods_RNTester.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F9DA138FE541ED31A6C589D7 /* Pods_RNTester.framework */; }; 13B07FC11A68108700A75B9A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB71A68108700A75B9A /* main.m */; }; 2DDEF0101F84BF7B00DBDF73 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 2DDEF00F1F84BF7B00DBDF73 /* Images.xcassets */; }; 383889DA23A7398900D06C3E /* RCTConvert_UIColorTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 383889D923A7398900D06C3E /* RCTConvert_UIColorTests.m */; }; @@ -15,8 +15,8 @@ 5C60EB1C226440DB0018C04F /* AppDelegate.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5C60EB1B226440DB0018C04F /* AppDelegate.mm */; }; 8145AE06241172D900A3F8DA /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 8145AE05241172D900A3F8DA /* LaunchScreen.storyboard */; }; 832F45BB2A8A6E1F0097B4E6 /* SwiftTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 832F45BA2A8A6E1F0097B4E6 /* SwiftTest.swift */; }; + 836E54623F6567BB812F3F6A /* Pods_RNTesterUnitTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3B5084412F9118F6F7FA99DA /* Pods_RNTesterUnitTests.framework */; }; CD10C7A5290BD4EB0033E1ED /* RCTEventEmitterTests.m in Sources */ = {isa = PBXBuildFile; fileRef = CD10C7A4290BD4EB0033E1ED /* RCTEventEmitterTests.m */; }; - DD6FAB12C0152128DD2DA1BE /* libPods-RNTester.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 175067970892CD30B8B0A8E0 /* libPods-RNTester.a */; }; E62F11832A5C6580000BF1C8 /* FlexibleSizeExampleView.mm in Sources */ = {isa = PBXBuildFile; fileRef = 27F441E81BEBE5030039B79C /* FlexibleSizeExampleView.mm */; }; E62F11842A5C6584000BF1C8 /* UpdatePropertiesExampleView.mm in Sources */ = {isa = PBXBuildFile; fileRef = 272E6B3C1BEA849E001FCF37 /* UpdatePropertiesExampleView.mm */; }; E7C1241A22BEC44B00DA25C0 /* RNTesterIntegrationTests.m in Sources */ = {isa = PBXBuildFile; fileRef = E7C1241922BEC44B00DA25C0 /* RNTesterIntegrationTests.m */; }; @@ -55,7 +55,7 @@ E7DB216422B2F3EC005AC45F /* RCTUIManagerScenarioTests.m in Sources */ = {isa = PBXBuildFile; fileRef = E7DB215F22B2F3EC005AC45F /* RCTUIManagerScenarioTests.m */; }; E7DB216722B2F69F005AC45F /* JavaScriptCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E7DB213022B2C649005AC45F /* JavaScriptCore.framework */; }; E7DB218C22B41FCD005AC45F /* XCTest.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E7DB218B22B41FCD005AC45F /* XCTest.framework */; }; - F37EF1CF1FC0B3DD56375DC7 /* libPods-RNTesterUnitTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D6942D0981036096211E5BDC /* libPods-RNTesterUnitTests.a */; }; + FA45ED19FFAECF4CFEFE0DC7 /* Pods_RNTesterIntegrationTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 87E71F82CA94BF2D3CA3110A /* Pods_RNTesterIntegrationTests.framework */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -80,7 +80,6 @@ 13B07FAF1A68108700A75B9A /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AppDelegate.h; path = RNTester/AppDelegate.h; sourceTree = ""; }; 13B07FB61A68108700A75B9A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = RNTester/Info.plist; sourceTree = ""; }; 13B07FB71A68108700A75B9A /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = RNTester/main.m; sourceTree = ""; }; - 175067970892CD30B8B0A8E0 /* libPods-RNTester.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-RNTester.a"; sourceTree = BUILT_PRODUCTS_DIR; }; 272E6B3B1BEA849E001FCF37 /* UpdatePropertiesExampleView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = UpdatePropertiesExampleView.h; path = RNTester/NativeExampleViews/UpdatePropertiesExampleView.h; sourceTree = ""; }; 272E6B3C1BEA849E001FCF37 /* UpdatePropertiesExampleView.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = UpdatePropertiesExampleView.mm; path = RNTester/NativeExampleViews/UpdatePropertiesExampleView.mm; sourceTree = ""; }; 2734C5E31C1D7A09BF872585 /* Pods-RNTester.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RNTester.debug.xcconfig"; path = "Target Support Files/Pods-RNTester/Pods-RNTester.debug.xcconfig"; sourceTree = ""; }; @@ -89,18 +88,18 @@ 2DDEF00F1F84BF7B00DBDF73 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Images.xcassets; path = RNTester/Images.xcassets; sourceTree = ""; }; 359825B9A5AE4A3F4AA612DD /* Pods-RNTesterUnitTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RNTesterUnitTests.debug.xcconfig"; path = "Target Support Files/Pods-RNTesterUnitTests/Pods-RNTesterUnitTests.debug.xcconfig"; sourceTree = ""; }; 383889D923A7398900D06C3E /* RCTConvert_UIColorTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTConvert_UIColorTests.m; sourceTree = ""; }; + 3B5084412F9118F6F7FA99DA /* Pods_RNTesterUnitTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RNTesterUnitTests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 3D2AFAF41D646CF80089D1A3 /* legacy_image@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "legacy_image@2x.png"; path = "RNTester/legacy_image@2x.png"; sourceTree = ""; }; 5C60EB1B226440DB0018C04F /* AppDelegate.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = AppDelegate.mm; path = RNTester/AppDelegate.mm; sourceTree = ""; }; - 63C6B5E1C2465D85E9BDB6E5 /* libPods-RNTesterIntegrationTests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-RNTesterIntegrationTests.a"; sourceTree = BUILT_PRODUCTS_DIR; }; 66C3087F2D5BF762FE9E6422 /* Pods-RNTesterIntegrationTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RNTesterIntegrationTests.debug.xcconfig"; path = "Target Support Files/Pods-RNTesterIntegrationTests/Pods-RNTesterIntegrationTests.debug.xcconfig"; sourceTree = ""; }; 7CDA7A212644C6BB8C0D00D8 /* Pods-RNTesterIntegrationTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RNTesterIntegrationTests.release.xcconfig"; path = "Target Support Files/Pods-RNTesterIntegrationTests/Pods-RNTesterIntegrationTests.release.xcconfig"; sourceTree = ""; }; 8145AE05241172D900A3F8DA /* LaunchScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; name = LaunchScreen.storyboard; path = RNTester/LaunchScreen.storyboard; sourceTree = ""; }; 832F45BA2A8A6E1F0097B4E6 /* SwiftTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = SwiftTest.swift; path = RNTester/SwiftTest.swift; sourceTree = ""; }; + 87E71F82CA94BF2D3CA3110A /* Pods_RNTesterIntegrationTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RNTesterIntegrationTests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 8BFB9C61D7BDE894E24BF24F /* Pods-RNTesterUnitTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RNTesterUnitTests.release.xcconfig"; path = "Target Support Files/Pods-RNTesterUnitTests/Pods-RNTesterUnitTests.release.xcconfig"; sourceTree = ""; }; 9B8542B8C590B51BD0588751 /* Pods-RNTester.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RNTester.release.xcconfig"; path = "Target Support Files/Pods-RNTester/Pods-RNTester.release.xcconfig"; sourceTree = ""; }; AC474BFB29BBD4A1002BDAED /* RNTester.xctestplan */ = {isa = PBXFileReference; lastKnownFileType = text; name = RNTester.xctestplan; path = RNTester/RNTester.xctestplan; sourceTree = ""; }; CD10C7A4290BD4EB0033E1ED /* RCTEventEmitterTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTEventEmitterTests.m; sourceTree = ""; }; - D6942D0981036096211E5BDC /* libPods-RNTesterUnitTests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-RNTesterUnitTests.a"; sourceTree = BUILT_PRODUCTS_DIR; }; E771AEEA22B44E3100EA1189 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = RNTester/Info.plist; sourceTree = ""; }; E7C1241922BEC44B00DA25C0 /* RNTesterIntegrationTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RNTesterIntegrationTests.m; sourceTree = ""; }; E7DB209F22B2BA84005AC45F /* RNTesterUnitTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RNTesterUnitTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -162,6 +161,7 @@ E7DB215E22B2F3EC005AC45F /* RCTLoggingTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTLoggingTests.m; sourceTree = ""; }; E7DB215F22B2F3EC005AC45F /* RCTUIManagerScenarioTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTUIManagerScenarioTests.m; sourceTree = ""; }; E7DB218B22B41FCD005AC45F /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = XCTest.framework; sourceTree = DEVELOPER_DIR; }; + F9DA138FE541ED31A6C589D7 /* Pods_RNTester.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RNTester.framework; sourceTree = BUILT_PRODUCTS_DIR; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -169,7 +169,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - DD6FAB12C0152128DD2DA1BE /* libPods-RNTester.a in Frameworks */, + 00915AE8006CF5DB156153DD /* Pods_RNTester.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -178,7 +178,7 @@ buildActionMask = 2147483647; files = ( E7DB213122B2C649005AC45F /* JavaScriptCore.framework in Frameworks */, - F37EF1CF1FC0B3DD56375DC7 /* libPods-RNTesterUnitTests.a in Frameworks */, + 836E54623F6567BB812F3F6A /* Pods_RNTesterUnitTests.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -188,7 +188,7 @@ files = ( E7DB218C22B41FCD005AC45F /* XCTest.framework in Frameworks */, E7DB216722B2F69F005AC45F /* JavaScriptCore.framework in Frameworks */, - 111FD3845C7358250C2702B6 /* libPods-RNTesterIntegrationTests.a in Frameworks */, + FA45ED19FFAECF4CFEFE0DC7 /* Pods_RNTesterIntegrationTests.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -258,9 +258,9 @@ E7DB211822B2BD53005AC45F /* libReact-RCTText.a */, E7DB211A22B2BD53005AC45F /* libReact-RCTVibration.a */, E7DB212222B2BD53005AC45F /* libyoga.a */, - 175067970892CD30B8B0A8E0 /* libPods-RNTester.a */, - 63C6B5E1C2465D85E9BDB6E5 /* libPods-RNTesterIntegrationTests.a */, - D6942D0981036096211E5BDC /* libPods-RNTesterUnitTests.a */, + F9DA138FE541ED31A6C589D7 /* Pods_RNTester.framework */, + 87E71F82CA94BF2D3CA3110A /* Pods_RNTesterIntegrationTests.framework */, + 3B5084412F9118F6F7FA99DA /* Pods_RNTesterUnitTests.framework */, ); name = Frameworks; sourceTree = ""; @@ -925,6 +925,8 @@ "${PODS_CONFIGURATION_BUILD_DIR}/React-Fabric/React_Fabric.framework/Headers/react/renderer/components/view/platform/cxx", "${PODS_CONFIGURATION_BUILD_DIR}/React-NativeModulesApple/React_NativeModulesApple.framework/Headers", "${PODS_CONFIGURATION_BUILD_DIR}/React-graphics/React_graphics.framework/Headers/react/renderer/graphics/platform/ios", + " ${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon/ReactCommon.framework/Headers", + " ${PODS_CONFIGURATION_BUILD_DIR}/React-graphics/React_graphics.framework/Headers", ); IPHONEOS_DEPLOYMENT_TARGET = 13.4; MTL_ENABLE_DEBUG_INFO = YES; @@ -941,8 +943,6 @@ OTHER_LDFLAGS = ( "-ObjC", "-lc++", - "-Wl", - "-ld_classic", ); REACT_NATIVE_PATH = "${PODS_ROOT}/../../react-native"; SDKROOT = iphoneos; @@ -1018,6 +1018,8 @@ "${PODS_CONFIGURATION_BUILD_DIR}/React-Fabric/React_Fabric.framework/Headers/react/renderer/components/view/platform/cxx", "${PODS_CONFIGURATION_BUILD_DIR}/React-NativeModulesApple/React_NativeModulesApple.framework/Headers", "${PODS_CONFIGURATION_BUILD_DIR}/React-graphics/React_graphics.framework/Headers/react/renderer/graphics/platform/ios", + " ${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon/ReactCommon.framework/Headers", + " ${PODS_CONFIGURATION_BUILD_DIR}/React-graphics/React_graphics.framework/Headers", ); IPHONEOS_DEPLOYMENT_TARGET = 13.4; MTL_ENABLE_DEBUG_INFO = NO; @@ -1033,8 +1035,6 @@ OTHER_LDFLAGS = ( "-ObjC", "-lc++", - "-Wl", - "-ld_classic", ); REACT_NATIVE_PATH = "${PODS_ROOT}/../../react-native"; SDKROOT = iphoneos;