Skip to content

Commit

Permalink
RuntimeTarget refactor - Store weak refs to agents in RuntimeTarget
Browse files Browse the repository at this point in the history
Summary:
Changelog: [Internal]

Applies to RuntimeTarget → RuntimeAgent the same pattern we use for InstanceTarget → InstanceAgent (D53266708) and PageTarget → PageTargetSession: the target has `weak_ptr`s to its agents/sessions so it can (1) dispatch events to them and (2) assert that they are destroyed before the target itself is destroyed.

In RuntimeTarget this will primarily serve as an event dispatching mechanism from JS (single target) to CDP (multiple sessions), with the addition of threading abstractions in upcoming diffs.

Reviewed By: hoxyq

Differential Revision: D53266706

fbshipit-source-id: 64d7226a1aebf00e0ad178f28101a568e9bc6c53
  • Loading branch information
motiz88 authored and facebook-github-bot committed Feb 14, 2024
1 parent 04eadf6 commit 48f1f2d
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ class InstanceAgent final {
private:
FrontendChannel frontendChannel_;
InstanceTarget& target_;
std::unique_ptr<RuntimeAgent> runtimeAgent_;
std::shared_ptr<RuntimeAgent> runtimeAgent_;
SessionState& sessionState_;
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,31 @@ namespace facebook::react::jsinspector_modern {
RuntimeTarget::RuntimeTarget(RuntimeTargetDelegate& delegate)
: delegate_(delegate) {}

std::unique_ptr<RuntimeAgent> RuntimeTarget::createAgent(
std::shared_ptr<RuntimeAgent> RuntimeTarget::createAgent(
FrontendChannel channel,
SessionState& sessionState) {
return std::make_unique<RuntimeAgent>(
auto runtimeAgent = std::make_shared<RuntimeAgent>(
channel,
*this,
sessionState,
delegate_.createAgentDelegate(channel, sessionState));
agents_.push_back(runtimeAgent);
return runtimeAgent;
}

void RuntimeTarget::removeExpiredAgents() {
// Remove all expired agents.
forEachAgent([](auto&) {});
}

RuntimeTarget::~RuntimeTarget() {
removeExpiredAgents();

// Agents are owned by the session, not by RuntimeTarget, but
// they hold a RuntimeTarget& that we must guarantee is valid.
assert(
agents_.empty() &&
"RuntimeAgent objects must be destroyed before their RuntimeTarget. Did you call InstanceTarget::unregisterRuntime()?");
}

} // namespace facebook::react::jsinspector_modern
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include "RuntimeAgent.h"
#include "SessionState.h"

#include <list>
#include <memory>

#ifndef JSINSPECTOR_EXPORT
Expand Down Expand Up @@ -59,6 +60,7 @@ class JSINSPECTOR_EXPORT RuntimeTarget final {
RuntimeTarget(RuntimeTarget&&) = delete;
RuntimeTarget& operator=(const RuntimeTarget&) = delete;
RuntimeTarget& operator=(RuntimeTarget&&) = delete;
~RuntimeTarget();

/**
* Create a new RuntimeAgent that can be used to debug the underlying JS VM.
Expand All @@ -69,12 +71,31 @@ class JSINSPECTOR_EXPORT RuntimeTarget final {
* frontend.
* \returns The new agent, or nullptr if the runtime is not debuggable.
*/
std::unique_ptr<RuntimeAgent> createAgent(
std::shared_ptr<RuntimeAgent> createAgent(
FrontendChannel channel,
SessionState& sessionState);

private:
RuntimeTargetDelegate& delegate_;
std::list<std::weak_ptr<RuntimeAgent>> agents_;

/**
* Call the given function for every active agent, and clean up any
* references to inactive agents.
*/
template <typename Fn>
void forEachAgent(Fn&& fn) {
for (auto it = agents_.begin(); it != agents_.end();) {
if (auto agent = it->lock()) {
fn(*agent);
++it;
} else {
it = agents_.erase(it);
}
}
}

void removeExpiredAgents();
};

} // namespace facebook::react::jsinspector_modern

0 comments on commit 48f1f2d

Please sign in to comment.