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
This commit is contained in:
Moti Zilberman
2024-02-01 11:03:41 -08:00
committed by Facebook GitHub Bot
parent 3b6c522942
commit adec8d303b
27 changed files with 443 additions and 174 deletions
@@ -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"
@@ -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
@@ -316,4 +316,9 @@ void Instance::JSCallInvoker::scheduleAsync(
}
}
std::unique_ptr<jsinspector_modern::RuntimeAgent> Instance::createRuntimeAgent(
jsinspector_modern::FrontendChannel frontendChannel) {
return nativeToJsBridge_->createRuntimeAgent(frontendChannel);
}
} // namespace facebook::react
@@ -151,6 +151,10 @@ class RN_EXPORT Instance : private jsinspector_modern::InstanceTargetDelegate {
std::unique_ptr<const JSBigString> startupScript,
std::string startupScriptSourceURL);
// From InstanceTargetDelegate
std::unique_ptr<jsinspector_modern::RuntimeAgent> createRuntimeAgent(
jsinspector_modern::FrontendChannel frontendChannel) override;
std::shared_ptr<InstanceCallback> callback_;
std::shared_ptr<NativeToJsBridge> nativeToJsBridge_;
std::shared_ptr<ModuleRegistry> moduleRegistry_;
@@ -34,4 +34,11 @@ double JSExecutor::performanceNow() {
return duration / NANOSECONDS_IN_MILLISECOND;
}
std::unique_ptr<jsinspector_modern::RuntimeAgent>
JSExecutor::createRuntimeAgent(
jsinspector_modern::FrontendChannel frontendChannel) {
(void)frontendChannel;
return nullptr;
}
} // namespace facebook::react
@@ -12,6 +12,8 @@
#include <cxxreact/NativeModule.h>
#include <folly/dynamic.h>
#include <jsinspector-modern/InspectorInterfaces.h>
#include <jsinspector-modern/RuntimeAgent.h>
#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<jsinspector_modern::RuntimeAgent> createRuntimeAgent(
jsinspector_modern::FrontendChannel frontendChannel);
};
} // namespace facebook::react
@@ -343,4 +343,11 @@ NativeToJsBridge::getDecoratedNativeMethodCallInvoker(
m_delegate, std::move(nativeMethodCallInvoker));
}
std::unique_ptr<jsinspector_modern::RuntimeAgent>
NativeToJsBridge::createRuntimeAgent(
jsinspector_modern::FrontendChannel frontendChannel) {
auto agent = m_executor->createRuntimeAgent(std::move(frontendChannel));
return agent;
}
} // namespace facebook::react
@@ -15,6 +15,7 @@
#include <ReactCommon/CallInvoker.h>
#include <ReactCommon/RuntimeExecutor.h>
#include <cxxreact/JSExecutor.h>
#include <jsinspector-modern/RuntimeAgent.h>
namespace folly {
struct dynamic;
@@ -106,6 +107,13 @@ class NativeToJsBridge {
std::shared_ptr<NativeMethodCallInvoker> getDecoratedNativeMethodCallInvoker(
std::shared_ptr<NativeMethodCallInvoker> nativeInvoker) const;
/**
* Create a RuntimeAgent that can be used to debug the underlying JS VM
* instance.
*/
virtual std::unique_ptr<jsinspector_modern::RuntimeAgent> 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
@@ -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'
@@ -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> 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
@@ -9,6 +9,7 @@
#include <jsinspector-modern/InspectorInterfaces.h>
#include <jsinspector-modern/Parsing.h>
#include <jsinspector-modern/RuntimeAgent.h>
#include <functional>
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> 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> runtimeAgent_;
};
} // namespace facebook::react::jsinspector_modern
@@ -20,6 +20,9 @@ InstanceTargetDelegate::~InstanceTargetDelegate() {}
std::unique_ptr<InstanceAgent> InstanceTarget::createAgent(
FrontendChannel channel) {
return std::make_unique<InstanceAgent>(channel, *this);
auto runtimeAgent = delegate_.createRuntimeAgent(channel);
return std::make_unique<InstanceAgent>(
channel, *this, std::move(runtimeAgent));
}
} // namespace facebook::react::jsinspector_modern
@@ -8,8 +8,10 @@
#pragma once
#include <jsinspector-modern/InspectorInterfaces.h>
#include <jsinspector-modern/RuntimeAgent.h>
#include <list>
#include <memory>
#include <optional>
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<RuntimeAgent> createRuntimeAgent(
FrontendChannel channel) = 0;
virtual ~InstanceTargetDelegate();
};
@@ -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.
}
}
@@ -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;
}
};
/**
@@ -9,3 +9,4 @@
#include <jsinspector-modern/InstanceTarget.h>
#include <jsinspector-modern/PageTarget.h>
#include <jsinspector-modern/RuntimeAgent.h>
@@ -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 <jsinspector-modern/RuntimeAgent.h>
namespace facebook::react::jsinspector_modern {
RuntimeAgent::~RuntimeAgent() {}
} // namespace facebook::react::jsinspector_modern
@@ -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 <jsinspector-modern/Parsing.h>
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
@@ -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<RuntimeAgent>,
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
@@ -27,6 +27,11 @@ namespace {
class PageTargetTest : public Test {
protected:
PageTargetTest() {
EXPECT_CALL(instanceTargetDelegate_, createRuntimeAgent(_))
.WillRepeatedly(runtimeAgents_.lazily_make_unique<FrontendChannel>());
}
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<StrictMock<MockRuntimeAgent>> runtimeAgents_;
private:
UniquePtrFactory<StrictMock<MockRemoteConnection>> 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
@@ -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<jsi::Runtime> runtime)
: runtime_(std::move(runtime)) {
assert(runtime_ != nullptr);
}
std::unique_ptr<jsinspector_modern::RuntimeAgent>
JSIRuntimeHolder::createInspectorAgent(
jsinspector_modern::FrontendChannel frontendChannel) {
(void)frontendChannel;
return nullptr;
}
} // namespace facebook::react
@@ -10,6 +10,7 @@
#include <ReactCommon/RuntimeExecutor.h>
#include <cxxreact/MessageQueueThread.h>
#include <jsi/jsi.h>
#include <jsinspector-modern/ReactCdp.h>
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<jsinspector_modern::RuntimeAgent>
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<jsinspector_modern::RuntimeAgent> createInspectorAgent(
jsinspector_modern::FrontendChannel frontendChannel) override;
explicit JSIRuntimeHolder(std::unique_ptr<jsi::Runtime> runtime);
@@ -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" }
@@ -460,4 +460,10 @@ void ReactInstance::handleMemoryPressureJs(int pressureLevel) {
}
}
std::unique_ptr<jsinspector_modern::RuntimeAgent>
ReactInstance::createRuntimeAgent(jsinspector_modern::FrontendChannel channel) {
auto agent = runtime_->createInspectorAgent(std::move(channel));
return agent;
}
} // namespace facebook::react
@@ -72,6 +72,10 @@ class ReactInstance final : private jsinspector_modern::InstanceTargetDelegate {
void unregisterFromInspector();
private:
// From InstanceTargetDelegate
std::unique_ptr<jsinspector_modern::RuntimeAgent> createRuntimeAgent(
jsinspector_modern::FrontendChannel channel) override;
std::shared_ptr<JSRuntime> runtime_;
std::shared_ptr<MessageQueueThread> jsMessageQueueThread_;
std::shared_ptr<BufferedRuntimeExecutor> bufferedRuntimeExecutor_;
+57 -35
View File
@@ -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
@@ -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 = "<group>"; };
13B07FB61A68108700A75B9A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = RNTester/Info.plist; sourceTree = "<group>"; };
13B07FB71A68108700A75B9A /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = RNTester/main.m; sourceTree = "<group>"; };
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 = "<group>"; };
272E6B3C1BEA849E001FCF37 /* UpdatePropertiesExampleView.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = UpdatePropertiesExampleView.mm; path = RNTester/NativeExampleViews/UpdatePropertiesExampleView.mm; sourceTree = "<group>"; };
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 = "<group>"; };
@@ -89,18 +88,18 @@
2DDEF00F1F84BF7B00DBDF73 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Images.xcassets; path = RNTester/Images.xcassets; sourceTree = "<group>"; };
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 = "<group>"; };
383889D923A7398900D06C3E /* RCTConvert_UIColorTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTConvert_UIColorTests.m; sourceTree = "<group>"; };
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 = "<group>"; };
5C60EB1B226440DB0018C04F /* AppDelegate.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = AppDelegate.mm; path = RNTester/AppDelegate.mm; sourceTree = "<group>"; };
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 = "<group>"; };
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 = "<group>"; };
8145AE05241172D900A3F8DA /* LaunchScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; name = LaunchScreen.storyboard; path = RNTester/LaunchScreen.storyboard; sourceTree = "<group>"; };
832F45BA2A8A6E1F0097B4E6 /* SwiftTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = SwiftTest.swift; path = RNTester/SwiftTest.swift; sourceTree = "<group>"; };
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 = "<group>"; };
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 = "<group>"; };
AC474BFB29BBD4A1002BDAED /* RNTester.xctestplan */ = {isa = PBXFileReference; lastKnownFileType = text; name = RNTester.xctestplan; path = RNTester/RNTester.xctestplan; sourceTree = "<group>"; };
CD10C7A4290BD4EB0033E1ED /* RCTEventEmitterTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTEventEmitterTests.m; sourceTree = "<group>"; };
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 = "<group>"; };
E7C1241922BEC44B00DA25C0 /* RNTesterIntegrationTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RNTesterIntegrationTests.m; sourceTree = "<group>"; };
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 = "<group>"; };
E7DB215F22B2F3EC005AC45F /* RCTUIManagerScenarioTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTUIManagerScenarioTests.m; sourceTree = "<group>"; };
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 = "<group>";
@@ -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;