mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-08-01 05:39:11 +00:00
LibDevTools+LibWebView: Implement basic support for console logging
This implements support for basic usage of console.log and friends. It does not implement console.assert, console.trace, console.group, etc.
This commit is contained in:
parent
848ac11495
commit
c5a22a1a97
Notes:
github-actions[bot]
2025-03-04 20:34:51 +00:00
Author: https://github.com/trflynn89
Commit: c5a22a1a97
Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/3801
Reviewed-by: https://github.com/AtkinsSJ
5 changed files with 155 additions and 2 deletions
|
@ -12,6 +12,9 @@
|
||||||
#include <LibDevTools/Actors/InspectorActor.h>
|
#include <LibDevTools/Actors/InspectorActor.h>
|
||||||
#include <LibDevTools/Actors/TabActor.h>
|
#include <LibDevTools/Actors/TabActor.h>
|
||||||
#include <LibDevTools/Actors/ThreadActor.h>
|
#include <LibDevTools/Actors/ThreadActor.h>
|
||||||
|
#include <LibDevTools/DevToolsDelegate.h>
|
||||||
|
#include <LibDevTools/DevToolsServer.h>
|
||||||
|
#include <LibWebView/ConsoleOutput.h>
|
||||||
|
|
||||||
namespace DevTools {
|
namespace DevTools {
|
||||||
|
|
||||||
|
@ -28,9 +31,25 @@ FrameActor::FrameActor(DevToolsServer& devtools, String name, WeakPtr<TabActor>
|
||||||
, m_inspector(move(inspector))
|
, m_inspector(move(inspector))
|
||||||
, m_thread(move(thread))
|
, m_thread(move(thread))
|
||||||
{
|
{
|
||||||
|
if (auto tab = m_tab.strong_ref()) {
|
||||||
|
devtools.delegate().listen_for_console_messages(
|
||||||
|
tab->description(),
|
||||||
|
[weak_self = make_weak_ptr<FrameActor>()](i32 message_index) {
|
||||||
|
if (auto self = weak_self.strong_ref())
|
||||||
|
self->console_message_available(message_index);
|
||||||
|
},
|
||||||
|
[weak_self = make_weak_ptr<FrameActor>()](i32 start_index, Vector<WebView::ConsoleOutput> console_output) {
|
||||||
|
if (auto self = weak_self.strong_ref())
|
||||||
|
self->console_messages_received(start_index, move(console_output));
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
FrameActor::~FrameActor() = default;
|
FrameActor::~FrameActor()
|
||||||
|
{
|
||||||
|
if (auto tab = m_tab.strong_ref())
|
||||||
|
devtools().delegate().stop_listening_for_console_messages(tab->description());
|
||||||
|
}
|
||||||
|
|
||||||
void FrameActor::handle_message(StringView type, JsonObject const&)
|
void FrameActor::handle_message(StringView type, JsonObject const&)
|
||||||
{
|
{
|
||||||
|
@ -38,8 +57,10 @@ void FrameActor::handle_message(StringView type, JsonObject const&)
|
||||||
response.set("from"sv, name());
|
response.set("from"sv, name());
|
||||||
|
|
||||||
if (type == "detach"sv) {
|
if (type == "detach"sv) {
|
||||||
if (auto tab = m_tab.strong_ref())
|
if (auto tab = m_tab.strong_ref()) {
|
||||||
|
devtools().delegate().stop_listening_for_console_messages(tab->description());
|
||||||
tab->reset_selected_node();
|
tab->reset_selected_node();
|
||||||
|
}
|
||||||
|
|
||||||
send_message(move(response));
|
send_message(move(response));
|
||||||
return;
|
return;
|
||||||
|
@ -107,4 +128,95 @@ JsonObject FrameActor::serialize_target() const
|
||||||
return target;
|
return target;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FrameActor::console_message_available(i32 message_index)
|
||||||
|
{
|
||||||
|
if (message_index <= m_highest_received_message_index) {
|
||||||
|
dbgln("Notified about console message we already have");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (message_index <= m_highest_notified_message_index) {
|
||||||
|
dbgln("Notified about console message we're already aware of");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_highest_notified_message_index = message_index;
|
||||||
|
|
||||||
|
if (!m_waiting_for_messages)
|
||||||
|
request_console_messages();
|
||||||
|
}
|
||||||
|
|
||||||
|
void FrameActor::console_messages_received(i32 start_index, Vector<WebView::ConsoleOutput> console_output)
|
||||||
|
{
|
||||||
|
auto end_index = start_index + static_cast<i32>(console_output.size()) - 1;
|
||||||
|
if (end_index <= m_highest_received_message_index) {
|
||||||
|
dbgln("Received old console messages");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
JsonArray messages;
|
||||||
|
messages.ensure_capacity(console_output.size());
|
||||||
|
|
||||||
|
for (auto& output : console_output) {
|
||||||
|
JsonObject message;
|
||||||
|
|
||||||
|
switch (output.level) {
|
||||||
|
case JS::Console::LogLevel::Debug:
|
||||||
|
message.set("level"sv, "debug"sv);
|
||||||
|
break;
|
||||||
|
case JS::Console::LogLevel::Error:
|
||||||
|
message.set("level"sv, "error"sv);
|
||||||
|
break;
|
||||||
|
case JS::Console::LogLevel::Info:
|
||||||
|
message.set("level"sv, "info"sv);
|
||||||
|
break;
|
||||||
|
case JS::Console::LogLevel::Log:
|
||||||
|
message.set("level"sv, "log"sv);
|
||||||
|
break;
|
||||||
|
case JS::Console::LogLevel::Warn:
|
||||||
|
message.set("level"sv, "warn"sv);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
// FIXME: Implement remaining console levels.
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
message.set("filename"sv, "<eval>"sv);
|
||||||
|
message.set("line_number"sv, 1);
|
||||||
|
message.set("column_number"sv, 1);
|
||||||
|
message.set("time_stamp"sv, output.timestamp.milliseconds_since_epoch());
|
||||||
|
message.set("arguments"sv, JsonArray { move(output.arguments) });
|
||||||
|
|
||||||
|
messages.must_append(move(message));
|
||||||
|
}
|
||||||
|
|
||||||
|
JsonArray console_message;
|
||||||
|
console_message.must_append("console-message"sv);
|
||||||
|
console_message.must_append(move(messages));
|
||||||
|
|
||||||
|
JsonArray array;
|
||||||
|
array.must_append(move(console_message));
|
||||||
|
|
||||||
|
JsonObject message;
|
||||||
|
message.set("from"sv, name());
|
||||||
|
message.set("type"sv, "resources-available-array"sv);
|
||||||
|
message.set("array"sv, move(array));
|
||||||
|
send_message(move(message));
|
||||||
|
|
||||||
|
m_highest_received_message_index = end_index;
|
||||||
|
m_waiting_for_messages = false;
|
||||||
|
|
||||||
|
if (m_highest_received_message_index < m_highest_notified_message_index)
|
||||||
|
request_console_messages();
|
||||||
|
}
|
||||||
|
|
||||||
|
void FrameActor::request_console_messages()
|
||||||
|
{
|
||||||
|
VERIFY(!m_waiting_for_messages);
|
||||||
|
|
||||||
|
if (auto tab = m_tab.strong_ref()) {
|
||||||
|
devtools().delegate().request_console_messages(m_tab->description(), m_highest_received_message_index + 1);
|
||||||
|
m_waiting_for_messages = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,10 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <AK/NonnullRefPtr.h>
|
#include <AK/NonnullRefPtr.h>
|
||||||
|
#include <AK/Types.h>
|
||||||
|
#include <AK/Vector.h>
|
||||||
#include <LibDevTools/Actor.h>
|
#include <LibDevTools/Actor.h>
|
||||||
|
#include <LibWebView/Forward.h>
|
||||||
|
|
||||||
namespace DevTools {
|
namespace DevTools {
|
||||||
|
|
||||||
|
@ -26,12 +29,20 @@ public:
|
||||||
private:
|
private:
|
||||||
FrameActor(DevToolsServer&, String name, WeakPtr<TabActor>, WeakPtr<CSSPropertiesActor>, WeakPtr<ConsoleActor>, WeakPtr<InspectorActor>, WeakPtr<ThreadActor>);
|
FrameActor(DevToolsServer&, String name, WeakPtr<TabActor>, WeakPtr<CSSPropertiesActor>, WeakPtr<ConsoleActor>, WeakPtr<InspectorActor>, WeakPtr<ThreadActor>);
|
||||||
|
|
||||||
|
void console_message_available(i32 message_index);
|
||||||
|
void console_messages_received(i32 start_index, Vector<WebView::ConsoleOutput>);
|
||||||
|
void request_console_messages();
|
||||||
|
|
||||||
WeakPtr<TabActor> m_tab;
|
WeakPtr<TabActor> m_tab;
|
||||||
|
|
||||||
WeakPtr<CSSPropertiesActor> m_css_properties;
|
WeakPtr<CSSPropertiesActor> m_css_properties;
|
||||||
WeakPtr<ConsoleActor> m_console;
|
WeakPtr<ConsoleActor> m_console;
|
||||||
WeakPtr<InspectorActor> m_inspector;
|
WeakPtr<InspectorActor> m_inspector;
|
||||||
WeakPtr<ThreadActor> m_thread;
|
WeakPtr<ThreadActor> m_thread;
|
||||||
|
|
||||||
|
i32 m_highest_notified_message_index { -1 };
|
||||||
|
i32 m_highest_received_message_index { -1 };
|
||||||
|
bool m_waiting_for_messages { false };
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
#include <LibDevTools/Forward.h>
|
#include <LibDevTools/Forward.h>
|
||||||
#include <LibWeb/CSS/Selector.h>
|
#include <LibWeb/CSS/Selector.h>
|
||||||
#include <LibWeb/Forward.h>
|
#include <LibWeb/Forward.h>
|
||||||
|
#include <LibWebView/Forward.h>
|
||||||
|
|
||||||
namespace DevTools {
|
namespace DevTools {
|
||||||
|
|
||||||
|
@ -38,6 +39,12 @@ public:
|
||||||
|
|
||||||
using OnScriptEvaluationComplete = Function<void(ErrorOr<JsonValue>)>;
|
using OnScriptEvaluationComplete = Function<void(ErrorOr<JsonValue>)>;
|
||||||
virtual void evaluate_javascript(TabDescription const&, String, OnScriptEvaluationComplete) const { }
|
virtual void evaluate_javascript(TabDescription const&, String, OnScriptEvaluationComplete) const { }
|
||||||
|
|
||||||
|
using OnConsoleMessageAvailable = Function<void(i32 message_id)>;
|
||||||
|
using OnReceivedConsoleMessages = Function<void(i32 start_index, Vector<WebView::ConsoleOutput>)>;
|
||||||
|
virtual void listen_for_console_messages(TabDescription const&, OnConsoleMessageAvailable, OnReceivedConsoleMessages) const { }
|
||||||
|
virtual void stop_listening_for_console_messages(TabDescription const&) const { }
|
||||||
|
virtual void request_console_messages(TabDescription const&, i32) const { }
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
22
Libraries/LibWebView/ConsoleOutput.h
Normal file
22
Libraries/LibWebView/ConsoleOutput.h
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2025, Tim Flynn <trflynn89@ladybird.org>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <AK/JsonValue.h>
|
||||||
|
#include <AK/Time.h>
|
||||||
|
#include <AK/Vector.h>
|
||||||
|
#include <LibJS/Console.h>
|
||||||
|
|
||||||
|
namespace WebView {
|
||||||
|
|
||||||
|
struct ConsoleOutput {
|
||||||
|
JS::Console::LogLevel level;
|
||||||
|
UnixDateTime timestamp;
|
||||||
|
Vector<JsonValue> arguments;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
|
@ -19,6 +19,7 @@ class ViewImplementation;
|
||||||
class WebContentClient;
|
class WebContentClient;
|
||||||
|
|
||||||
struct Attribute;
|
struct Attribute;
|
||||||
|
struct ConsoleOutput;
|
||||||
struct CookieStorageKey;
|
struct CookieStorageKey;
|
||||||
struct ProcessHandle;
|
struct ProcessHandle;
|
||||||
struct SearchEngine;
|
struct SearchEngine;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue