Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -385,8 +385,7 @@ class HostAgent::Impl final {
return fuseboxClientType_ == FuseboxClientType::Fusebox;
}

void emitExternalTracingProfile(
tracing::HostTracingProfile tracingProfile) const {
void emitExternalTracingProfile(tracing::HostTracingProfile tracingProfile) {
assert(
hasFuseboxClientConnected() &&
"Attempted to emit a trace recording to a non-Fusebox client");
Expand Down Expand Up @@ -543,11 +542,11 @@ bool HostAgent::hasFuseboxClientConnected() const {
}

void HostAgent::emitExternalTracingProfile(
tracing::HostTracingProfile tracingProfile) const {
tracing::HostTracingProfile tracingProfile) {
impl_->emitExternalTracingProfile(std::move(tracingProfile));
}

void HostAgent::emitSystemStateChanged(bool isSingleHost) const {
void HostAgent::emitSystemStateChanged(bool isSingleHost) {
impl_->emitSystemStateChanged(isSingleHost);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,13 +77,13 @@ class HostAgent final {
* Emits the HostTracingProfile that was captured externally, not via the
* CDP-initiated request.
*/
void emitExternalTracingProfile(tracing::HostTracingProfile tracingProfile) const;
void emitExternalTracingProfile(tracing::HostTracingProfile tracingProfile);

/**
* Emits a system state changed event when the number of ReactHost instances
* changes.
*/
void emitSystemStateChanged(bool isSingleHost) const;
void emitSystemStateChanged(bool isSingleHost);

private:
// We use the private implementation idiom to ensure this class has the same
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,8 +111,7 @@ class HostTargetSession {
return hostAgent_.hasFuseboxClientConnected();
}

void emitHostTracingProfile(
tracing::HostTracingProfile tracingProfile) const {
void emitHostTracingProfile(tracing::HostTracingProfile tracingProfile) {
hostAgent_.emitExternalTracingProfile(std::move(tracingProfile));
}

Expand Down Expand Up @@ -377,16 +376,16 @@ folly::dynamic createHostMetadataPayload(const HostTargetMetadata& metadata) {

bool HostTarget::hasActiveSessionWithFuseboxClient() const {
bool hasActiveFuseboxSession = false;
sessions_.forEach([&](HostTargetSession& session) {
sessions_.forEach([&](auto& session) {
hasActiveFuseboxSession |= session.hasFuseboxClient();
});
return hasActiveFuseboxSession;
}

void HostTarget::emitTracingProfileForFirstFuseboxClient(
tracing::HostTracingProfile tracingProfile) const {
tracing::HostTracingProfile tracingProfile) {
bool emitted = false;
sessions_.forEach([&](HostTargetSession& session) {
sessions_.forEach([&](auto& session) {
if (emitted) {
/**
* HostTracingProfile object is not copiable for performance reasons,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -363,7 +363,7 @@ class JSINSPECTOR_EXPORT HostTarget : public EnableExecutorFromThis<HostTarget>
*
* @see \c hasActiveFrontendSession
*/
void emitTracingProfileForFirstFuseboxClient(tracing::HostTracingProfile tracingProfile) const;
void emitTracingProfileForFirstFuseboxClient(tracing::HostTracingProfile tracingProfile);

/**
* An endpoint for the Host to report frame timings that will be recorded if and only if there is currently an active
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,13 @@ class Stream : public NetworkRequestListener,
};
} // namespace

NetworkIOAgent::~NetworkIOAgent() {
if (networkAgentId_) {
NetworkHandler::getInstance().disableAgent(*networkAgentId_);
networkAgentId_ = std::nullopt;
}
}

bool NetworkIOAgent::handleRequest(
const cdp::PreparsedRequest& req,
LoadNetworkResourceDelegate& delegate) {
Expand All @@ -278,15 +285,17 @@ bool NetworkIOAgent::handleRequest(

// @cdp Network.enable support is experimental.
if (req.method == "Network.enable") {
networkHandler.setFrontendChannel(frontendChannel_);
networkHandler.enable();
networkAgentId_ = networkHandler.enableAgent(frontendChannel_);
// NOTE: Domain enable/disable responses are sent by HostAgent.
return false;
}

// @cdp Network.disable support is experimental.
if (req.method == "Network.disable") {
networkHandler.disable();
if (networkAgentId_) {
networkHandler.disableAgent(*networkAgentId_);
networkAgentId_ = std::nullopt;
}
// NOTE: Domain enable/disable responses are sent by HostAgent.
return false;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,13 @@ class NetworkIOAgent {
{
}

~NetworkIOAgent();

NetworkIOAgent(const NetworkIOAgent &) = delete;
NetworkIOAgent &operator=(const NetworkIOAgent &) = delete;
NetworkIOAgent(NetworkIOAgent &&) = delete;
NetworkIOAgent &operator=(NetworkIOAgent &&) = delete;

/**
* Handle a CDP request. The response will be sent over the provided
* \c FrontendChannel synchronously or asynchronously.
Expand Down Expand Up @@ -247,6 +254,12 @@ class NetworkIOAgent {
*/
unsigned long nextStreamId_{0};

/**
* If non-nullopt, indicates that this agent has enabled the Network domain
* via NetworkHandler, storing the agent ID for cleanup.
*/
std::optional<size_t> networkAgentId_;

/**
* Begin loading an HTTP resource, delegating platform-specific
* implementation, responding to the frontend on headers received or on error.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,8 @@ bool TracingAgent::handleRequest(const cdp::PreparsedRequest& req) {
bool didNotHaveAlreadyRunningRecording = hostTargetController_.startTracing(
tracing::Mode::CDP, std::move(enabledCategories));
if (!didNotHaveAlreadyRunningRecording) {
// @cdp Tracing.start fails if there is a tracing session already running
// in the current target. This matches Chrome's behavior.
frontendChannel_(
cdp::jsonError(
req.id,
Expand Down Expand Up @@ -118,14 +120,14 @@ bool TracingAgent::handleRequest(const cdp::PreparsedRequest& req) {
}

void TracingAgent::emitExternalHostTracingProfile(
tracing::HostTracingProfile tracingProfile) const {
tracing::HostTracingProfile tracingProfile) {
frontendChannel_(
cdp::jsonNotification("ReactNativeApplication.traceRequested"));
emitHostTracingProfile(std::move(tracingProfile));
}

void TracingAgent::emitHostTracingProfile(
tracing::HostTracingProfile tracingProfile) const {
tracing::HostTracingProfile tracingProfile) {
auto dataCollectedCallback = [this](folly::dynamic&& eventsChunk) {
frontendChannel_(
cdp::jsonNotification(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ class TracingAgent {
/**
* Emits the HostTracingProfile that was stashed externally by the HostTarget.
*/
void emitExternalHostTracingProfile(tracing::HostTracingProfile tracingProfile) const;
void emitExternalHostTracingProfile(tracing::HostTracingProfile tracingProfile);

private:
/**
Expand All @@ -60,7 +60,7 @@ class TracingAgent {
* Emits captured HostTracingProfile in a series of
* Tracing.dataCollected events, followed by a Tracing.tracingComplete event.
*/
void emitHostTracingProfile(tracing::HostTracingProfile tracingProfile) const;
void emitHostTracingProfile(tracing::HostTracingProfile tracingProfile);
};

} // namespace facebook::react::jsinspector_modern
61 changes: 60 additions & 1 deletion packages/react-native/ReactCommon/jsinspector-modern/WeakList.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ class WeakList {
* to destroyed elements) will be removed during iteration.
*/
template <typename Fn>
void forEach(Fn &&fn) const
void forEach(Fn &&fn)
{
for (auto it = ptrs_.begin(); it != ptrs_.end();) {
if (auto ptr = it->lock()) {
Expand All @@ -42,6 +42,65 @@ class WeakList {
}
}

/**
* Call the given function for every element in the list, ensuring the element
* is not destroyed for the duration of the call. Elements are visited in the
* order they were inserted.
*
* As a side effect, any null pointers in the underlying list (corresponding
* to destroyed elements) will be removed during iteration.
*/
template <typename Fn>
void forEach(Fn &&fn) const
{
for (auto it = ptrs_.cbegin(); it != ptrs_.cend();) {
if (auto ptr = it->lock()) {
fn(*ptr);
++it;
} else {
it = ptrs_.erase(it);
}
}
}

/**
* Returns true if the given function returns true for any element in the
* list, ensuring the element is not destroyed for the duration of the call.
*
* As a side effect, any null pointers in the underlying list (corresponding
* to destroyed elements) will be removed during iteration.
*/
template <typename Fn>
bool anyOf(Fn &&fn)
{
bool found = false;
forEach([&](auto &element) {
if (!found && fn(element)) {
found = true;
}
});
return found;
}

/**
* Returns true if the given function returns true for any element in the
* list, ensuring the element is not destroyed for the duration of the call.
*
* As a side effect, any null pointers in the underlying list (corresponding
* to destroyed elements) will be removed during iteration.
*/
template <typename Fn>
bool anyOf(Fn &&fn) const
{
bool found = false;
forEach([&](const auto &element) {
if (!found && fn(element)) {
found = true;
}
});
return found;
}

/**
* Returns the number of (non-null) elements in the list. The count will only
* remain accurate as long as the list is not modified and elements are
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,27 +37,31 @@ NetworkHandler& NetworkHandler::getInstance() {
return instance;
}

void NetworkHandler::setFrontendChannel(FrontendChannel frontendChannel) {
frontendChannel_ = std::move(frontendChannel);
size_t NetworkHandler::enableAgent(FrontendChannel frontendChannel) {
std::lock_guard<std::mutex> lock(agentsMutex_);
size_t id = nextAgentId_++;
agents_.push_back({id, std::move(frontendChannel)});
enabled_.store(true, std::memory_order_release);
return id;
}

bool NetworkHandler::enable() {
if (enabled_.load(std::memory_order_acquire)) {
return false;
}
void NetworkHandler::disableAgent(size_t agentId) {
std::lock_guard<std::mutex> lock(agentsMutex_);
agents_.remove_if(
[agentId](const AgentRecord& r) { return r.id == agentId; });
if (agents_.empty()) {
enabled_.store(false, std::memory_order_release);

enabled_.store(true, std::memory_order_release);
return true;
std::lock_guard<std::mutex> lock2(requestBodyMutex_);
responseBodyBuffer_.clear();
}
}

bool NetworkHandler::disable() {
if (!enabled_.load(std::memory_order_acquire)) {
return false;
void NetworkHandler::sendToAllAgents(std::string_view message) {
std::lock_guard<std::mutex> lock(agentsMutex_);
for (auto& agent : agents_) {
agent.channel(message);
}

enabled_.store(false, std::memory_order_release);
responseBodyBuffer_.clear();
return true;
}

void NetworkHandler::onRequestWillBeSent(
Expand Down Expand Up @@ -88,7 +92,7 @@ void NetworkHandler::onRequestWillBeSent(
.redirectResponse = redirectResponse,
};

frontendChannel_(
sendToAllAgents(
cdp::jsonNotification("Network.requestWillBeSent", params.toDynamic()));
}

Expand All @@ -105,7 +109,7 @@ void NetworkHandler::onRequestWillBeSentExtraInfo(
.connectTiming = {.requestTime = getCurrentUnixTimestampSeconds()},
};

frontendChannel_(
sendToAllAgents(
cdp::jsonNotification(
"Network.requestWillBeSentExtraInfo", params.toDynamic()));
}
Expand All @@ -132,7 +136,7 @@ void NetworkHandler::onResponseReceived(
.hasExtraInfo = false,
};

frontendChannel_(
sendToAllAgents(
cdp::jsonNotification("Network.responseReceived", params.toDynamic()));
}

Expand All @@ -151,7 +155,7 @@ void NetworkHandler::onDataReceived(
.encodedDataLength = encodedDataLength,
};

frontendChannel_(
sendToAllAgents(
cdp::jsonNotification("Network.dataReceived", params.toDynamic()));
}

Expand All @@ -168,7 +172,7 @@ void NetworkHandler::onLoadingFinished(
.encodedDataLength = encodedDataLength,
};

frontendChannel_(
sendToAllAgents(
cdp::jsonNotification("Network.loadingFinished", params.toDynamic()));
}

Expand All @@ -191,7 +195,7 @@ void NetworkHandler::onLoadingFailed(
.canceled = cancelled,
};

frontendChannel_(
sendToAllAgents(
cdp::jsonNotification("Network.loadingFailed", params.toDynamic()));
}
}
Expand Down
Loading
Loading