mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-04-21 03:55:24 +00:00
LibDevTools: Associate node actors with a DOM node identifier
This is a prepatory commit to be able to handle DOM mutations. Once a node actor is created, the DOM node it is created for must continue to be associated with the same actor even after DOM mutations. This change stores an identifier on the node actor, and only creates new actors when an actor for a node does not exist.
This commit is contained in:
parent
ee88edc750
commit
ddea67034f
Notes:
github-actions[bot]
2025-03-08 00:28:03 +00:00
Author: https://github.com/trflynn89 Commit: https://github.com/LadybirdBrowser/ladybird/commit/ddea67034f8 Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/3850
6 changed files with 80 additions and 28 deletions
|
@ -42,7 +42,7 @@ void HighlighterActor::handle_message(StringView type, JsonObject const& message
|
|||
response.set("value"sv, false);
|
||||
|
||||
if (auto dom_node = WalkerActor::dom_node_for(InspectorActor::walker_for(m_inspector), *node); dom_node.has_value()) {
|
||||
devtools().delegate().highlight_dom_node(dom_node->tab->description(), dom_node->id, dom_node->pseudo_element);
|
||||
devtools().delegate().highlight_dom_node(dom_node->tab->description(), dom_node->identifier.id, dom_node->identifier.pseudo_element);
|
||||
response.set("value"sv, true);
|
||||
}
|
||||
|
||||
|
|
|
@ -11,13 +11,31 @@
|
|||
|
||||
namespace DevTools {
|
||||
|
||||
NonnullRefPtr<NodeActor> NodeActor::create(DevToolsServer& devtools, String name, WeakPtr<WalkerActor> walker)
|
||||
NodeIdentifier NodeIdentifier::for_node(JsonObject const& node)
|
||||
{
|
||||
return adopt_ref(*new NodeActor(devtools, move(name), move(walker)));
|
||||
NodeIdentifier identifier;
|
||||
|
||||
identifier.pseudo_element = node.get_integer<UnderlyingType<Web::CSS::Selector::PseudoElement::Type>>("pseudo-element"sv).map([](auto value) {
|
||||
VERIFY(value < to_underlying(Web::CSS::Selector::PseudoElement::Type::KnownPseudoElementCount));
|
||||
return static_cast<Web::CSS::Selector::PseudoElement::Type>(value);
|
||||
});
|
||||
|
||||
if (identifier.pseudo_element.has_value())
|
||||
identifier.id = node.get_integer<Web::UniqueNodeID::Type>("parent-id"sv).value();
|
||||
else
|
||||
identifier.id = node.get_integer<Web::UniqueNodeID::Type>("id"sv).value();
|
||||
|
||||
return identifier;
|
||||
}
|
||||
|
||||
NodeActor::NodeActor(DevToolsServer& devtools, String name, WeakPtr<WalkerActor> walker)
|
||||
NonnullRefPtr<NodeActor> NodeActor::create(DevToolsServer& devtools, String name, NodeIdentifier node_identifier, WeakPtr<WalkerActor> walker)
|
||||
{
|
||||
return adopt_ref(*new NodeActor(devtools, move(name), move(node_identifier), move(walker)));
|
||||
}
|
||||
|
||||
NodeActor::NodeActor(DevToolsServer& devtools, String name, NodeIdentifier node_identifier, WeakPtr<WalkerActor> walker)
|
||||
: Actor(devtools, move(name))
|
||||
, m_node_identifier(move(node_identifier))
|
||||
, m_walker(move(walker))
|
||||
{
|
||||
}
|
||||
|
|
|
@ -8,20 +8,35 @@
|
|||
|
||||
#include <AK/NonnullRefPtr.h>
|
||||
#include <LibDevTools/Actor.h>
|
||||
#include <LibWeb/CSS/Selector.h>
|
||||
#include <LibWeb/Forward.h>
|
||||
|
||||
namespace DevTools {
|
||||
|
||||
struct NodeIdentifier {
|
||||
static NodeIdentifier for_node(JsonObject const& node);
|
||||
|
||||
bool operator==(NodeIdentifier const&) const = default;
|
||||
|
||||
Web::UniqueNodeID id { 0 };
|
||||
Optional<Web::CSS::Selector::PseudoElement::Type> pseudo_element;
|
||||
};
|
||||
|
||||
class NodeActor final : public Actor {
|
||||
public:
|
||||
static constexpr auto base_name = "node"sv;
|
||||
|
||||
static NonnullRefPtr<NodeActor> create(DevToolsServer&, String name, WeakPtr<WalkerActor>);
|
||||
static NonnullRefPtr<NodeActor> create(DevToolsServer&, String name, NodeIdentifier, WeakPtr<WalkerActor>);
|
||||
virtual ~NodeActor() override;
|
||||
|
||||
virtual void handle_message(StringView type, JsonObject const&) override;
|
||||
|
||||
NodeIdentifier const& node_identifier() const { return m_node_identifier; }
|
||||
|
||||
private:
|
||||
NodeActor(DevToolsServer&, String name, WeakPtr<WalkerActor>);
|
||||
NodeActor(DevToolsServer&, String name, NodeIdentifier, WeakPtr<WalkerActor>);
|
||||
|
||||
NodeIdentifier m_node_identifier;
|
||||
|
||||
WeakPtr<WalkerActor> m_walker;
|
||||
};
|
||||
|
|
|
@ -102,7 +102,7 @@ void PageStyleActor::inspect_dom_node(StringView node_actor, Callback&& callback
|
|||
auto block_token = block_responses();
|
||||
|
||||
devtools().delegate().inspect_dom_node(
|
||||
dom_node->tab->description(), dom_node->id, dom_node->pseudo_element,
|
||||
dom_node->tab->description(), dom_node->identifier.id, dom_node->identifier.pseudo_element,
|
||||
[weak_self = make_weak_ptr<PageStyleActor>(), block_token = move(block_token), callback = forward<Callback>(callback)](ErrorOr<DOMNodeProperties> properties) mutable {
|
||||
if (properties.is_error()) {
|
||||
dbgln_if(DEVTOOLS_DEBUG, "Unable to inspect DOM node: {}", properties.error());
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
#include <AK/JsonArray.h>
|
||||
#include <AK/StringUtils.h>
|
||||
#include <LibDevTools/Actors/LayoutInspectorActor.h>
|
||||
#include <LibDevTools/Actors/NodeActor.h>
|
||||
#include <LibDevTools/Actors/TabActor.h>
|
||||
#include <LibDevTools/Actors/WalkerActor.h>
|
||||
#include <LibDevTools/DevToolsServer.h>
|
||||
|
@ -25,7 +24,7 @@ WalkerActor::WalkerActor(DevToolsServer& devtools, String name, WeakPtr<TabActor
|
|||
, m_tab(move(tab))
|
||||
, m_dom_tree(move(dom_tree))
|
||||
{
|
||||
populate_dom_tree_cache(m_dom_tree);
|
||||
populate_dom_tree_cache();
|
||||
}
|
||||
|
||||
WalkerActor::~WalkerActor() = default;
|
||||
|
@ -267,19 +266,9 @@ Optional<WalkerActor::DOMNode> WalkerActor::dom_node(StringView actor)
|
|||
return {};
|
||||
|
||||
auto const& dom_node = *maybe_dom_node.value();
|
||||
auto identifier = NodeIdentifier::for_node(dom_node);
|
||||
|
||||
auto pseudo_element = dom_node.get_integer<UnderlyingType<Web::CSS::Selector::PseudoElement::Type>>("pseudo-element"sv).map([](auto value) {
|
||||
VERIFY(value < to_underlying(Web::CSS::Selector::PseudoElement::Type::KnownPseudoElementCount));
|
||||
return static_cast<Web::CSS::Selector::PseudoElement::Type>(value);
|
||||
});
|
||||
|
||||
Web::UniqueNodeID node_id { 0 };
|
||||
if (pseudo_element.has_value())
|
||||
node_id = dom_node.get_integer<Web::UniqueNodeID::Type>("parent-id"sv).value();
|
||||
else
|
||||
node_id = dom_node.get_integer<Web::UniqueNodeID::Type>("id"sv).value();
|
||||
|
||||
return DOMNode { .node = dom_node, .id = node_id, .pseudo_element = pseudo_element, .tab = tab.release_nonnull() };
|
||||
return DOMNode { .node = dom_node, .identifier = move(identifier), .tab = tab.release_nonnull() };
|
||||
}
|
||||
|
||||
Optional<JsonObject const&> WalkerActor::find_node_by_selector(JsonObject const& node, StringView selector)
|
||||
|
@ -306,14 +295,25 @@ Optional<JsonObject const&> WalkerActor::find_node_by_selector(JsonObject const&
|
|||
return {};
|
||||
}
|
||||
|
||||
void WalkerActor::populate_dom_tree_cache()
|
||||
{
|
||||
m_dom_node_to_parent_map.clear();
|
||||
m_actor_to_dom_node_map.clear();
|
||||
m_dom_node_id_to_actor_map.clear();
|
||||
|
||||
populate_dom_tree_cache(m_dom_tree, nullptr);
|
||||
}
|
||||
|
||||
void WalkerActor::populate_dom_tree_cache(JsonObject& node, JsonObject const* parent)
|
||||
{
|
||||
auto& node_actor = devtools().register_actor<NodeActor>(*this);
|
||||
auto const& node_actor = actor_for_node(node);
|
||||
node.set("actor"sv, node_actor.name());
|
||||
|
||||
m_dom_node_to_parent_map.set(&node, parent);
|
||||
|
||||
m_actor_to_dom_node_map.set(node_actor.name(), &node);
|
||||
node.set("actor"sv, node_actor.name());
|
||||
|
||||
if (!node_actor.node_identifier().pseudo_element.has_value())
|
||||
m_dom_node_id_to_actor_map.set(node_actor.node_identifier().id, node_actor.name());
|
||||
|
||||
auto children = node.get_array("children"sv);
|
||||
if (!children.has_value())
|
||||
|
@ -328,4 +328,20 @@ void WalkerActor::populate_dom_tree_cache(JsonObject& node, JsonObject const* pa
|
|||
});
|
||||
}
|
||||
|
||||
NodeActor const& WalkerActor::actor_for_node(JsonObject const& node)
|
||||
{
|
||||
auto identifier = NodeIdentifier::for_node(node);
|
||||
|
||||
for (auto const& actor : devtools().actor_registry()) {
|
||||
auto const* node_actor = as_if<NodeActor>(*actor.value);
|
||||
if (!node_actor)
|
||||
continue;
|
||||
|
||||
if (node_actor->node_identifier() == identifier)
|
||||
return *node_actor;
|
||||
}
|
||||
|
||||
return devtools().register_actor<NodeActor>(move(identifier), *this);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
#include <AK/NonnullRefPtr.h>
|
||||
#include <AK/Optional.h>
|
||||
#include <LibDevTools/Actor.h>
|
||||
#include <LibWeb/CSS/Selector.h>
|
||||
#include <LibDevTools/Actors/NodeActor.h>
|
||||
#include <LibWeb/Forward.h>
|
||||
|
||||
namespace DevTools {
|
||||
|
@ -30,8 +30,7 @@ public:
|
|||
|
||||
struct DOMNode {
|
||||
JsonObject const& node;
|
||||
Web::UniqueNodeID id { 0 };
|
||||
Optional<Web::CSS::Selector::PseudoElement::Type> pseudo_element;
|
||||
NodeIdentifier identifier;
|
||||
NonnullRefPtr<TabActor> tab;
|
||||
};
|
||||
static Optional<DOMNode> dom_node_for(WeakPtr<WalkerActor> const&, StringView actor);
|
||||
|
@ -43,7 +42,10 @@ private:
|
|||
JsonValue serialize_node(JsonObject const&) const;
|
||||
Optional<JsonObject const&> find_node_by_selector(JsonObject const& node, StringView selector);
|
||||
|
||||
void populate_dom_tree_cache(JsonObject& node, JsonObject const* parent = nullptr);
|
||||
void populate_dom_tree_cache();
|
||||
void populate_dom_tree_cache(JsonObject& node, JsonObject const* parent);
|
||||
|
||||
NodeActor const& actor_for_node(JsonObject const& node);
|
||||
|
||||
WeakPtr<TabActor> m_tab;
|
||||
WeakPtr<LayoutInspectorActor> m_layout_inspector;
|
||||
|
@ -52,6 +54,7 @@ private:
|
|||
|
||||
HashMap<JsonObject const*, JsonObject const*> m_dom_node_to_parent_map;
|
||||
HashMap<String, JsonObject const*> m_actor_to_dom_node_map;
|
||||
HashMap<Web::UniqueNodeID, String> m_dom_node_id_to_actor_map;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue