LibDevTools: Re-implement how we handle ordered responses

We must reply to requests received from the client in the order they are
received. The wrench in this requirement is handling requests that must
be performed asynchronously, such as fetching the serialized DOM tree
from the WebContent process.

We currently handle this with a "block token". Async request handlers
hold a token that blocks any subsequent responses from being sent. When
that token is removed (i.e. the async request now has a response to be
sent), the async response is then sent followed by the blocked responses
in-order.

This strategy had a limitation that we could not handle an actor trying
to take 2 block tokens, meaning only one async request could be handled
at a time. This has been fine so far, but an upcoming feature (style
sheet sources) will break this limitation. The client will request N
sources at a time, which would try to take N block tokens.

The new strategy is to assign all requests an ID, and store a list of
request IDs that are awaiting a response. When the server wants to send
a reply, we match the ID of the replied-to message to this list of IDs.
If it is not the first in this list, then we are blocked waiting for an
earlier reply, and just store the response. When the earlier request(s)
receive their response, we can then send out all blocked replies (up to
the next request that has not yet received a response).
This commit is contained in:
Timothy Flynn 2025-03-12 12:26:58 -04:00 committed by Tim Flynn
commit f9e83af475
Notes: github-actions[bot] 2025-03-13 20:57:51 +00:00
20 changed files with 165 additions and 168 deletions

View file

@ -4,6 +4,7 @@
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <AK/Enumerate.h>
#include <LibDevTools/Actor.h>
#include <LibDevTools/Connection.h>
#include <LibDevTools/DevToolsServer.h>
@ -20,29 +21,70 @@ Actor::~Actor() = default;
void Actor::message_received(StringView type, JsonObject message)
{
handle_message({ type, move(message) });
auto message_id = m_next_message_id++;
m_pending_responses.empend(message_id, OptionalNone {});
handle_message({ type, move(message), message_id });
}
void Actor::send_message(JsonObject message, Optional<BlockToken> block_token)
void Actor::send_response(Message const& message, JsonObject response)
{
if (m_block_responses && !block_token.has_value()) {
m_blocked_responses.append(move(message));
auto& connection = devtools().connection();
if (!connection)
return;
response.set("from"sv, name());
for (auto const& [i, pending_response] : enumerate(m_pending_responses)) {
if (pending_response.id != message.id)
continue;
pending_response.response = move(response);
if (i != 0)
return;
}
size_t number_of_sent_messages = 0;
for (auto const& pending_response : m_pending_responses) {
if (!pending_response.response.has_value())
break;
connection->send_message(*pending_response.response);
++number_of_sent_messages;
}
m_pending_responses.remove(0, number_of_sent_messages);
}
void Actor::send_message(JsonObject message)
{
auto& connection = devtools().connection();
if (!connection)
return;
message.set("from"sv, name());
if (auto& connection = devtools().connection())
connection->send_message(move(message));
if (m_pending_responses.is_empty()) {
connection->send_message(message);
return;
}
m_pending_responses.empend(OptionalNone {}, move(message));
}
// https://firefox-source-docs.mozilla.org/devtools/backend/protocol.html#error-packets
void Actor::send_missing_parameter_error(StringView parameter)
void Actor::send_missing_parameter_error(Optional<Message const&> message, StringView parameter)
{
JsonObject error;
error.set("error"sv, "missingParameter"sv);
error.set("message"sv, MUST(String::formatted("Missing parameter: '{}'", parameter)));
send_message(move(error));
if (message.has_value())
send_response(*message, move(error));
else
send_message(move(error));
}
// https://firefox-source-docs.mozilla.org/devtools/backend/protocol.html#error-packets
@ -51,64 +93,21 @@ void Actor::send_unrecognized_packet_type_error(Message const& message)
JsonObject error;
error.set("error"sv, "unrecognizedPacketType"sv);
error.set("message"sv, MUST(String::formatted("Unrecognized packet type: '{}'", message.type)));
send_message(move(error));
send_response(message, move(error));
}
// https://github.com/mozilla/gecko-dev/blob/master/devtools/server/actors/object.js
// This error is not documented, but is used by Firefox nonetheless.
void Actor::send_unknown_actor_error(StringView actor)
void Actor::send_unknown_actor_error(Optional<Message const&> message, StringView actor)
{
JsonObject error;
error.set("error"sv, "unknownActor"sv);
error.set("message"sv, MUST(String::formatted("Unknown actor: '{}'", actor)));
send_message(move(error));
}
Actor::BlockToken Actor::block_responses()
{
// https://firefox-source-docs.mozilla.org/devtools/backend/protocol.html#the-request-reply-pattern
// The actor processes packets in the order they are received, and the client can trust that the ith reply
// corresponds to the ith request.
// The above requirement gets tricky for actors which require an async implementation. For example, the "getWalker"
// message sent to the InspectorActor results in the server fetching the DOM tree as JSON from the WebContent process.
// We cannot reply to the message until that is received. However, we will likely receive more messages from the
// client in that time. We cannot reply to those messages until we've replied to the "getWalker" message. Thus, we
// use this token to queue responses from the actor until that reply can be sent.
return { {}, *this };
}
Actor::BlockToken::BlockToken(Badge<Actor>, Actor& actor)
: m_actor(actor)
{
// If we end up in a situtation where an actor has multiple async handlers at once, we will need to come up with a
// more sophisticated blocking mechanism.
VERIFY(!actor.m_block_responses);
actor.m_block_responses = true;
}
Actor::BlockToken::BlockToken(BlockToken&& other)
: m_actor(move(other.m_actor))
{
}
Actor::BlockToken& Actor::BlockToken::operator=(BlockToken&& other)
{
m_actor = move(other.m_actor);
return *this;
}
Actor::BlockToken::~BlockToken()
{
auto actor = m_actor.strong_ref();
if (!actor)
return;
auto blocked_responses = move(actor->m_blocked_responses);
actor->m_block_responses = false;
for (auto& message : blocked_responses)
actor->send_message(move(message));
if (message.has_value())
send_response(*message, move(error));
else
send_message(move(error));
}
}

View file

@ -6,7 +6,6 @@
#pragma once
#include <AK/Badge.h>
#include <AK/Debug.h>
#include <AK/JsonObject.h>
#include <AK/Optional.h>
@ -25,8 +24,9 @@ class Actor
, public Weakable<Actor> {
public:
struct Message {
StringView type;
JsonObject data;
StringView type {};
JsonObject data {};
u64 id { 0 };
};
virtual ~Actor();
@ -35,25 +35,15 @@ public:
void message_received(StringView type, JsonObject);
class [[nodiscard]] BlockToken {
public:
BlockToken(Badge<Actor>, Actor&);
~BlockToken();
// Use send_response when replying directly to a request received from the client.
void send_response(Message const&, JsonObject);
BlockToken(BlockToken const&) = delete;
BlockToken& operator=(BlockToken const&) = delete;
// Use send_message when sending an unprompted message to the client.
void send_message(JsonObject);
BlockToken(BlockToken&&);
BlockToken& operator=(BlockToken&&);
private:
WeakPtr<Actor> m_actor;
};
void send_message(JsonObject, Optional<BlockToken> block_token = {});
void send_missing_parameter_error(StringView parameter);
void send_missing_parameter_error(Optional<Message const&>, StringView parameter);
void send_unrecognized_packet_type_error(Message const&);
void send_unknown_actor_error(StringView actor);
void send_unknown_actor_error(Optional<Message const&>, StringView actor);
protected:
explicit Actor(DevToolsServer&, String name);
@ -63,8 +53,6 @@ protected:
DevToolsServer& devtools() { return m_devtools; }
DevToolsServer const& devtools() const { return m_devtools; }
BlockToken block_responses();
template<typename ParameterType>
auto get_required_parameter(Message const& message, StringView parameter)
{
@ -84,15 +72,17 @@ protected:
}();
if (!result.has_value())
send_missing_parameter_error(parameter);
send_missing_parameter_error(message, parameter);
return result;
}
template<typename ActorType = Actor, typename Handler>
auto async_handler(Handler&& handler)
auto async_handler(Optional<Message const&> message, Handler&& handler)
{
return [weak_self = make_weak_ptr<ActorType>(), handler = forward<Handler>(handler), block_token = block_responses()](auto result) mutable {
auto message_id = message.map([](auto const& message) { return message.id; });
return [weak_self = make_weak_ptr<ActorType>(), message_id, handler = forward<Handler>(handler)](auto result) mutable {
if (result.is_error()) {
dbgln_if(DEVTOOLS_DEBUG, "Error performing async action: {}", result.error());
return;
@ -101,22 +91,30 @@ protected:
if (auto self = weak_self.strong_ref()) {
JsonObject response;
handler(*self, result.release_value(), response);
self->send_message(move(response), move(block_token));
if (message_id.has_value())
self->send_response({ .id = *message_id }, move(response));
else
self->send_message(move(response));
}
};
}
auto default_async_handler()
auto default_async_handler(Message const& message)
{
return async_handler([](auto&, auto, auto) { });
return async_handler(message, [](auto&, auto, auto) { });
}
private:
DevToolsServer& m_devtools;
String m_name;
Vector<JsonObject> m_blocked_responses;
bool m_block_responses { false };
struct PendingResponse {
Optional<u64> id;
Optional<JsonObject> response;
};
Vector<PendingResponse, 1> m_pending_responses;
u64 m_next_message_id { 0 };
};
}

View file

@ -47,7 +47,7 @@ void CSSPropertiesActor::handle_message(Message const& message)
}
response.set("properties"sv, move(properties));
send_message(move(response));
send_response(message, move(response));
return;
}

View file

@ -46,7 +46,7 @@ void ConsoleActor::handle_message(Message const& message)
if (message.type == "autocomplete"sv) {
response.set("matches"sv, JsonArray {});
response.set("matchProp"sv, String {});
send_message(move(response));
send_response(message, move(response));
return;
}
@ -58,7 +58,7 @@ void ConsoleActor::handle_message(Message const& message)
auto result_id = MUST(String::formatted("{}-{}", name(), m_execution_id++));
response.set("resultID"sv, result_id);
send_message(move(response));
send_response(message, move(response));
// FIXME: We do not support eager evaluation of scripts. Just bail for now.
if (message.data.get_bool("eager"sv).value_or(false)) {
@ -67,7 +67,7 @@ void ConsoleActor::handle_message(Message const& message)
if (auto tab = m_tab.strong_ref()) {
devtools().delegate().evaluate_javascript(tab->description(), *text,
async_handler([result_id, input = *text](auto&, auto result, auto& response) {
async_handler({}, [result_id, input = *text](auto&, auto result, auto& response) {
received_console_result(response, move(result_id), move(input), move(result));
}));
}

View file

@ -49,7 +49,7 @@ void DeviceActor::handle_message(Message const& message)
JsonObject response;
response.set("value"sv, move(value));
send_message(move(response));
send_response(message, move(response));
return;
}

View file

@ -62,12 +62,12 @@ void FrameActor::handle_message(Message const& message)
tab->reset_selected_node();
}
send_message(move(response));
send_response(message, move(response));
return;
}
if (message.type == "listFrames"sv) {
send_message(move(response));
send_response(message, move(response));
return;
}

View file

@ -43,7 +43,7 @@ void HighlighterActor::handle_message(Message const& message)
response.set("value"sv, true);
}
send_message(move(response));
send_response(message, move(response));
return;
}
@ -51,7 +51,7 @@ void HighlighterActor::handle_message(Message const& message)
if (auto tab = InspectorActor::tab_for(m_inspector))
devtools().delegate().clear_highlighted_dom_node(tab->description());
send_message(move(response));
send_response(message, move(response));
return;
}

View file

@ -38,7 +38,7 @@ void InspectorActor::handle_message(Message const& message)
m_page_style = devtools().register_actor<PageStyleActor>(*this);
response.set("pageStyle"sv, m_page_style->serialize_style());
send_message(move(response));
send_response(message, move(response));
return;
}
@ -52,14 +52,14 @@ void InspectorActor::handle_message(Message const& message)
});
response.set("highlighter"sv, highlighter->serialize_highlighter());
send_message(move(response));
send_response(message, move(response));
return;
}
if (message.type == "getWalker"sv) {
if (auto tab = m_tab.strong_ref()) {
devtools().delegate().inspect_tab(tab->description(),
async_handler<InspectorActor>([](auto& self, auto dom_tree, auto& response) {
async_handler<InspectorActor>(message, [](auto& self, auto dom_tree, auto& response) {
if (!WalkerActor::is_suitable_for_dom_inspection(dom_tree)) {
dbgln_if(DEVTOOLS_DEBUG, "Did not receive a suitable DOM tree: {}", dom_tree);
return;
@ -74,7 +74,7 @@ void InspectorActor::handle_message(Message const& message)
if (message.type == "supportsHighlighters"sv) {
response.set("value"sv, true);
send_message(move(response));
send_response(message, move(response));
return;
}

View file

@ -28,13 +28,13 @@ void LayoutInspectorActor::handle_message(Message const& message)
if (message.type == "getCurrentFlexbox"sv) {
response.set("flexbox"sv, JsonValue {});
send_message(move(response));
send_response(message, move(response));
return;
}
if (message.type == "getGrids"sv) {
response.set("grids"sv, JsonArray {});
send_message(move(response));
send_response(message, move(response));
return;
}

View file

@ -100,12 +100,12 @@ void NodeActor::handle_message(Message const& message)
if (message.type == "getUniqueSelector"sv) {
auto dom_node = WalkerActor::dom_node_for(m_walker, name());
if (!dom_node.has_value()) {
send_unknown_actor_error(name());
send_unknown_actor_error(message, name());
return;
}
response.set("value"sv, dom_node->node.get_string("name"sv)->to_ascii_lowercase());
send_message(move(response));
send_response(message, move(response));
return;
}
@ -120,14 +120,14 @@ void NodeActor::handle_message(Message const& message)
auto dom_node = WalkerActor::dom_node_for(m_walker, name());
if (!dom_node.has_value()) {
send_unknown_actor_error(name());
send_unknown_actor_error(message, name());
return;
}
if (attribute_to_replace.has_value())
devtools().delegate().replace_dom_node_attribute(dom_node->tab->description(), dom_node->identifier.id, *attribute_to_replace, move(replacement_attributes), default_async_handler());
devtools().delegate().replace_dom_node_attribute(dom_node->tab->description(), dom_node->identifier.id, *attribute_to_replace, move(replacement_attributes), default_async_handler(message));
else
devtools().delegate().add_dom_node_attributes(dom_node->tab->description(), dom_node->identifier.id, move(replacement_attributes), default_async_handler());
devtools().delegate().add_dom_node_attributes(dom_node->tab->description(), dom_node->identifier.id, move(replacement_attributes), default_async_handler(message));
return;
}
@ -139,11 +139,11 @@ void NodeActor::handle_message(Message const& message)
auto dom_node = WalkerActor::dom_node_for(m_walker, name());
if (!dom_node.has_value()) {
send_unknown_actor_error(name());
send_unknown_actor_error(message, name());
return;
}
devtools().delegate().set_dom_node_text(dom_node->tab->description(), dom_node->identifier.id, *value, default_async_handler());
devtools().delegate().set_dom_node_text(dom_node->tab->description(), dom_node->identifier.id, *value, default_async_handler(message));
return;
}

View file

@ -93,7 +93,7 @@ void PageStyleActor::handle_message(Message const& message)
// FIXME: This provides information to the "styles" pane in the inspector tab, which allows toggling and editing
// styles live. We do not yet support figuring out the list of styles that apply to a specific node.
response.set("entries"sv, JsonArray {});
send_message(move(response));
send_response(message, move(response));
return;
}
@ -102,7 +102,7 @@ void PageStyleActor::handle_message(Message const& message)
if (!node.has_value())
return;
inspect_dom_node(*node, [](auto& response, auto const& properties) {
inspect_dom_node(message, *node, [](auto& response, auto const& properties) {
received_computed_style(response, properties.computed_style);
});
@ -114,7 +114,7 @@ void PageStyleActor::handle_message(Message const& message)
if (!node.has_value())
return;
inspect_dom_node(*node, [](auto& response, auto const& properties) {
inspect_dom_node(message, *node, [](auto& response, auto const& properties) {
received_layout(response, properties.computed_style, properties.node_box_sizing);
});
@ -123,7 +123,7 @@ void PageStyleActor::handle_message(Message const& message)
if (message.type == "isPositionEditable") {
response.set("value"sv, false);
send_message(move(response));
send_response(message, move(response));
return;
}
@ -145,16 +145,16 @@ JsonValue PageStyleActor::serialize_style() const
}
template<typename Callback>
void PageStyleActor::inspect_dom_node(StringView node_actor, Callback&& callback)
void PageStyleActor::inspect_dom_node(Message const& message, StringView node_actor, Callback&& callback)
{
auto dom_node = WalkerActor::dom_node_for(InspectorActor::walker_for(m_inspector), node_actor);
if (!dom_node.has_value()) {
send_unknown_actor_error(node_actor);
send_unknown_actor_error(message, node_actor);
return;
}
devtools().delegate().inspect_dom_node(dom_node->tab->description(), dom_node->identifier.id, dom_node->identifier.pseudo_element,
async_handler([callback = forward<Callback>(callback)](auto&, auto properties, auto& response) {
async_handler(message, [callback = forward<Callback>(callback)](auto&, auto properties, auto& response) {
callback(response, properties);
}));
}

View file

@ -32,7 +32,7 @@ private:
virtual void handle_message(Message const&) override;
template<typename Callback>
void inspect_dom_node(StringView node_actor, Callback&&);
void inspect_dom_node(Message const&, StringView node_actor, Callback&&);
WeakPtr<InspectorActor> m_inspector;
};

View file

@ -31,7 +31,7 @@ void PreferenceActor::handle_message(Message const& message)
if (message.type == "getBoolPref"sv) {
JsonObject response;
response.set("value"sv, false);
send_message(move(response));
send_response(message, move(response));
return;
}

View file

@ -46,7 +46,7 @@ void RootActor::handle_message(Message const& message)
JsonObject response;
if (message.type == "connect") {
send_message(move(response));
send_response(message, move(response));
return;
}
@ -60,7 +60,7 @@ void RootActor::handle_message(Message const& message)
response.set("preferenceActor"sv, actor.key);
}
send_message(move(response));
send_response(message, move(response));
return;
}
@ -80,7 +80,7 @@ void RootActor::handle_message(Message const& message)
break;
}
send_message(move(response));
send_response(message, move(response));
return;
}
@ -100,13 +100,13 @@ void RootActor::handle_message(Message const& message)
break;
}
send_message(move(response));
send_response(message, move(response));
return;
}
if (message.type == "listAddons"sv) {
response.set("addons"sv, JsonArray {});
send_message(move(response));
send_response(message, move(response));
return;
}
@ -119,13 +119,13 @@ void RootActor::handle_message(Message const& message)
}
response.set("processes"sv, move(processes));
send_message(move(response));
send_response(message, move(response));
return;
}
if (message.type == "listServiceWorkerRegistrations"sv) {
response.set("registrations"sv, JsonArray {});
send_message(move(response));
send_response(message, move(response));
return;
}
@ -140,13 +140,13 @@ void RootActor::handle_message(Message const& message)
}
response.set("tabs"sv, move(tabs));
send_message(move(response));
send_response(message, move(response));
return;
}
if (message.type == "listWorkers"sv) {
response.set("workers"sv, JsonArray {});
send_message(move(response));
send_response(message, move(response));
return;
}

View file

@ -36,7 +36,7 @@ void TabActor::handle_message(Message const& message)
// FIXME: Firefox DevTools wants a favicon URL here, but supplying a URL seems to prevent this tab from being
// listed on the about:debugging page. Both Servo and Firefox itself supply `null` here.
response.set("favicon"sv, JsonValue {});
send_message(move(response));
send_response(message, move(response));
return;
}
@ -46,7 +46,7 @@ void TabActor::handle_message(Message const& message)
response.set("actor"sv, m_watcher->name());
response.set("traits"sv, m_watcher->serialize_description());
send_message(move(response));
send_response(message, move(response));
return;
}

View file

@ -31,7 +31,7 @@ void TargetConfigurationActor::handle_message(Message const& message)
if (!configuration.has_value())
return;
send_message(move(response));
send_response(message, move(response));
return;
}

View file

@ -31,7 +31,7 @@ void ThreadConfigurationActor::handle_message(Message const& message)
if (!configuration.has_value())
return;
send_message(move(response));
send_response(message, move(response));
return;
}

View file

@ -54,7 +54,7 @@ void WalkerActor::handle_message(Message const& message)
auto ancestor_node = WalkerActor::dom_node_for(*this, *node);
if (!ancestor_node.has_value()) {
send_unknown_actor_error(*node);
send_unknown_actor_error(message, *node);
return;
}
@ -69,7 +69,7 @@ void WalkerActor::handle_message(Message const& message)
response.set("hasFirst"sv, !nodes.is_empty());
response.set("hasLast"sv, !nodes.is_empty());
response.set("nodes"sv, move(nodes));
send_message(move(response));
send_response(message, move(response));
return;
}
@ -80,11 +80,11 @@ void WalkerActor::handle_message(Message const& message)
auto dom_node = WalkerActor::dom_node_for(*this, *node);
if (!dom_node.has_value()) {
send_unknown_actor_error(*node);
send_unknown_actor_error(message, *node);
return;
}
devtools().delegate().clone_dom_node(dom_node->tab->description(), dom_node->identifier.id, default_async_handler());
devtools().delegate().clone_dom_node(dom_node->tab->description(), dom_node->identifier.id, default_async_handler(message));
return;
}
@ -99,11 +99,11 @@ void WalkerActor::handle_message(Message const& message)
auto dom_node = WalkerActor::dom_node_for(*this, *node);
if (!dom_node.has_value()) {
send_unknown_actor_error(*node);
send_unknown_actor_error(message, *node);
return;
}
devtools().delegate().set_dom_node_tag(dom_node->tab->description(), dom_node->identifier.id, *tag_name, default_async_handler());
devtools().delegate().set_dom_node_tag(dom_node->tab->description(), dom_node->identifier.id, *tag_name, default_async_handler(message));
return;
}
@ -115,13 +115,13 @@ void WalkerActor::handle_message(Message const& message)
actor.set("actor"sv, m_layout_inspector->name());
response.set("actor"sv, move(actor));
send_message(move(response));
send_response(message, move(response));
return;
}
if (message.type == "getMutations"sv) {
response.set("mutations"sv, serialize_mutations());
send_message(move(response));
send_response(message, move(response));
m_has_new_mutations_since_last_mutations_request = false;
return;
@ -129,7 +129,7 @@ void WalkerActor::handle_message(Message const& message)
if (message.type == "getOffsetParent"sv) {
response.set("node"sv, JsonValue {});
send_message(move(response));
send_response(message, move(response));
return;
}
@ -140,12 +140,12 @@ void WalkerActor::handle_message(Message const& message)
auto dom_node = WalkerActor::dom_node_for(*this, *node);
if (!dom_node.has_value()) {
send_unknown_actor_error(*node);
send_unknown_actor_error(message, *node);
return;
}
devtools().delegate().get_dom_node_inner_html(dom_node->tab->description(), dom_node->identifier.id,
async_handler([](auto&, auto html, auto& response) {
async_handler(message, [](auto&, auto html, auto& response) {
response.set("value"sv, move(html));
}));
@ -162,12 +162,12 @@ void WalkerActor::handle_message(Message const& message)
auto dom_node = WalkerActor::dom_node_for(*this, *node);
if (!dom_node.has_value()) {
send_unknown_actor_error(*node);
send_unknown_actor_error(message, *node);
return;
}
devtools().delegate().create_child_element(dom_node->tab->description(), dom_node->identifier.id,
async_handler<WalkerActor>([](auto& self, auto node_id, auto& response) {
async_handler<WalkerActor>(message, [](auto& self, auto node_id, auto& response) {
JsonArray nodes;
if (auto actor = self.m_dom_node_id_to_actor_map.get(node_id); actor.has_value()) {
@ -193,13 +193,13 @@ void WalkerActor::handle_message(Message const& message)
auto dom_node = WalkerActor::dom_node_for(*this, *node);
if (!dom_node.has_value()) {
send_unknown_actor_error(*node);
send_unknown_actor_error(message, *node);
return;
}
auto parent_dom_node = WalkerActor::dom_node_for(*this, *parent);
if (!parent_dom_node.has_value()) {
send_unknown_actor_error(*parent);
send_unknown_actor_error(message, *parent);
return;
}
@ -207,14 +207,14 @@ void WalkerActor::handle_message(Message const& message)
if (auto sibling = message.data.get_string("sibling"sv); sibling.has_value()) {
auto sibling_dom_node = WalkerActor::dom_node_for(*this, *sibling);
if (!sibling_dom_node.has_value()) {
send_unknown_actor_error(*sibling);
send_unknown_actor_error(message, *sibling);
return;
}
sibling_node_id = sibling_dom_node->identifier.id;
}
devtools().delegate().insert_dom_node_before(dom_node->tab->description(), dom_node->identifier.id, parent_dom_node->identifier.id, sibling_node_id, default_async_handler());
devtools().delegate().insert_dom_node_before(dom_node->tab->description(), dom_node->identifier.id, parent_dom_node->identifier.id, sibling_node_id, default_async_handler(message));
return;
}
@ -224,7 +224,7 @@ void WalkerActor::handle_message(Message const& message)
return;
response.set("attached"sv, m_actor_to_dom_node_map.contains(*node));
send_message(move(response));
send_response(message, move(response));
return;
}
@ -235,12 +235,12 @@ void WalkerActor::handle_message(Message const& message)
auto dom_node = WalkerActor::dom_node_for(*this, *node);
if (!dom_node.has_value()) {
send_unknown_actor_error(*node);
send_unknown_actor_error(message, *node);
return;
}
devtools().delegate().get_dom_node_outer_html(dom_node->tab->description(), dom_node->identifier.id,
async_handler([](auto&, auto html, auto& response) {
async_handler(message, [](auto&, auto html, auto& response) {
response.set("value"sv, move(html));
}));
@ -254,7 +254,7 @@ void WalkerActor::handle_message(Message const& message)
auto dom_node = WalkerActor::dom_node_for(*this, *node);
if (!dom_node.has_value()) {
send_unknown_actor_error(*node);
send_unknown_actor_error(message, *node);
return;
}
@ -263,7 +263,7 @@ void WalkerActor::handle_message(Message const& message)
previous_sibling = serialize_node(*previous_sibling_node);
response.set("node"sv, move(previous_sibling));
send_message(move(response));
send_response(message, move(response));
return;
}
@ -278,7 +278,7 @@ void WalkerActor::handle_message(Message const& message)
auto ancestor_node = WalkerActor::dom_node_for(*this, *node);
if (!ancestor_node.has_value()) {
send_unknown_actor_error(*node);
send_unknown_actor_error(message, *node);
return;
}
@ -294,7 +294,7 @@ void WalkerActor::handle_message(Message const& message)
}
}
send_message(move(response));
send_response(message, move(response));
return;
}
@ -305,7 +305,7 @@ void WalkerActor::handle_message(Message const& message)
auto dom_node = WalkerActor::dom_node_for(*this, *node);
if (!dom_node.has_value()) {
send_unknown_actor_error(*node);
send_unknown_actor_error(message, *node);
return;
}
@ -318,7 +318,7 @@ void WalkerActor::handle_message(Message const& message)
return;
devtools().delegate().remove_dom_node(dom_node->tab->description(), dom_node->identifier.id,
async_handler([next_sibling = move(next_sibling)](auto&, auto, auto& response) mutable {
async_handler(message, [next_sibling = move(next_sibling)](auto&, auto, auto& response) mutable {
response.set("nextSibling"sv, move(next_sibling));
}));
@ -326,7 +326,7 @@ void WalkerActor::handle_message(Message const& message)
}
if (message.type == "retainNode"sv) {
send_message(move(response));
send_response(message, move(response));
return;
}
@ -341,18 +341,18 @@ void WalkerActor::handle_message(Message const& message)
auto dom_node = WalkerActor::dom_node_for(*this, *node);
if (!dom_node.has_value()) {
send_unknown_actor_error(*node);
send_unknown_actor_error(message, *node);
return;
}
devtools().delegate().set_dom_node_outer_html(dom_node->tab->description(), dom_node->identifier.id, value.release_value(), default_async_handler());
devtools().delegate().set_dom_node_outer_html(dom_node->tab->description(), dom_node->identifier.id, value.release_value(), default_async_handler(message));
return;
}
if (message.type == "watchRootNode"sv) {
response.set("type"sv, "root-available"sv);
response.set("node"sv, serialize_root());
send_message(move(response));
send_response(message, move(response));
send_message({});
return;

View file

@ -43,7 +43,7 @@ void WatcherActor::handle_message(Message const& message)
return;
response.set("browsingContextID"sv, *browsing_context_id);
send_message(move(response));
send_response(message, move(response));
return;
}
@ -52,7 +52,7 @@ void WatcherActor::handle_message(Message const& message)
m_target_configuration = devtools().register_actor<TargetConfigurationActor>();
response.set("configuration"sv, m_target_configuration->serialize_configuration());
send_message(move(response));
send_response(message, move(response));
return;
}
@ -61,7 +61,7 @@ void WatcherActor::handle_message(Message const& message)
m_thread_configuration = devtools().register_actor<ThreadConfigurationActor>();
response.set("configuration"sv, m_thread_configuration->serialize_configuration());
send_message(move(response));
send_response(message, move(response));
return;
}
@ -79,7 +79,7 @@ void WatcherActor::handle_message(Message const& message)
}
}
send_message(move(response));
send_response(message, move(response));
return;
}
@ -99,7 +99,7 @@ void WatcherActor::handle_message(Message const& message)
response.set("type"sv, "target-available-form"sv);
response.set("target"sv, target.serialize_target());
send_message(move(response));
send_response(message, move(response));
target.send_frame_update_message();

View file

@ -87,19 +87,19 @@ void DevToolsServer::on_message_received(JsonObject message)
{
auto to = message.get_string("to"sv);
if (!to.has_value()) {
m_root_actor->send_missing_parameter_error("to"sv);
m_root_actor->send_missing_parameter_error({}, "to"sv);
return;
}
auto actor = m_actor_registry.find(*to);
if (actor == m_actor_registry.end()) {
m_root_actor->send_unknown_actor_error(*to);
m_root_actor->send_unknown_actor_error({}, *to);
return;
}
auto type = message.get_string("type"sv);
if (!type.has_value()) {
actor->value->send_missing_parameter_error("type"sv);
actor->value->send_missing_parameter_error({}, "type"sv);
return;
}