LibWebView+WebContent: Begin supporting the DevTools JavaScript console

This supports evaluating the script and replying with the result. We
currently serialize JS objects to a string, but we will need to support
dynamic interaction with the objects over IPC. This does not yet support
sending console messages to DevTools.
This commit is contained in:
Timothy Flynn
2025-02-24 11:57:33 -05:00
committed by Andreas Kling
parent 6d33b70e61
commit 32bc2dc7b6
10 changed files with 101 additions and 2 deletions

View File

@@ -30,7 +30,7 @@ target_include_directories(webcontentservice PUBLIC $<BUILD_INTERFACE:${CMAKE_CU
target_include_directories(webcontentservice PUBLIC $<BUILD_INTERFACE:${LADYBIRD_SOURCE_DIR}>)
target_include_directories(webcontentservice PUBLIC $<BUILD_INTERFACE:${LADYBIRD_SOURCE_DIR}/Services/>)
target_link_libraries(webcontentservice PUBLIC LibCore LibFileSystem LibGfx LibIPC LibJS LibMain LibMedia LibWeb LibWebSocket LibRequests LibWebView LibImageDecoderClient LibGC)
target_link_libraries(webcontentservice PUBLIC LibCore LibCrypto LibFileSystem LibGfx LibIPC LibJS LibMain LibMedia LibWeb LibWebSocket LibRequests LibWebView LibImageDecoderClient LibGC)
target_link_libraries(webcontentservice PRIVATE OpenSSL::Crypto OpenSSL::SSL)
if (ENABLE_QT)

View File

@@ -4,7 +4,13 @@
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <AK/JsonObject.h>
#include <AK/JsonValue.h>
#include <AK/MemoryStream.h>
#include <LibJS/Print.h>
#include <LibJS/Runtime/BigInt.h>
#include <LibJS/Runtime/Realm.h>
#include <LibWeb/HTML/Scripting/TemporaryExecutionContext.h>
#include <LibWeb/HTML/Window.h>
#include <WebContent/ConsoleGlobalEnvironmentExtensions.h>
#include <WebContent/DevToolsConsoleClient.h>
@@ -29,9 +35,67 @@ DevToolsConsoleClient::DevToolsConsoleClient(JS::Realm& realm, JS::Console& cons
DevToolsConsoleClient::~DevToolsConsoleClient() = default;
// https://firefox-source-docs.mozilla.org/devtools/backend/protocol.html#grips
static JsonValue serialize_js_value(JS::Realm& realm, JS::Value value)
{
auto& vm = realm.vm();
auto serialize_type = [](StringView type) {
JsonObject serialized;
serialized.set("type"sv, type);
return serialized;
};
if (value.is_undefined())
return serialize_type("undefined"sv);
if (value.is_null())
return serialize_type("null"sv);
if (value.is_boolean())
return value.as_bool();
if (value.is_string())
return value.as_string().utf8_string();
if (value.is_number()) {
if (value.is_nan())
return serialize_type("NaN"sv);
if (value.is_positive_infinity())
return serialize_type("Infinity"sv);
if (value.is_negative_infinity())
return serialize_type("-Infinity"sv);
if (value.is_negative_zero())
return serialize_type("-0"sv);
return value.as_double();
}
if (value.is_bigint()) {
auto serialized = serialize_type("BigInt"sv);
serialized.set("text"sv, MUST(value.as_bigint().big_integer().to_base(10)));
return serialized;
}
if (value.is_symbol())
return MUST(value.as_symbol().descriptive_string());
// FIXME: Handle serialization of object grips. For now, we stringify the object.
if (value.is_object()) {
Web::HTML::TemporaryExecutionContext execution_context { realm };
AllocatingMemoryStream stream;
JS::PrintContext context { vm, stream, true };
MUST(JS::print(value, context));
return MUST(String::from_stream(stream, stream.used_buffer_size()));
}
return {};
}
void DevToolsConsoleClient::handle_result(JS::Value result)
{
(void)result;
m_client->did_execute_js_console_input(serialize_js_value(m_realm, result));
}
void DevToolsConsoleClient::report_exception(JS::Error const& exception, bool in_promise)

View File

@@ -7,6 +7,7 @@
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <AK/JsonValue.h>
#include <LibGfx/ShareableBitmap.h>
#include <LibJS/Console.h>
#include <LibJS/Runtime/ConsoleObject.h>
@@ -750,6 +751,11 @@ void PageClient::initialize_js_console(Web::DOM::Document& document)
document.set_console_client(console_client);
}
void PageClient::did_execute_js_console_input(JsonValue result)
{
client().async_did_execute_js_console_input(m_id, move(result));
}
void PageClient::js_console_input(StringView js_source)
{
if (m_top_level_document_console_client)

View File

@@ -85,6 +85,7 @@ public:
void initialize_js_console(Web::DOM::Document& document);
void js_console_input(StringView js_source);
void did_execute_js_console_input(JsonValue);
void run_javascript(StringView js_source);
void js_console_request_messages(i32 start_index);
void did_output_js_console_message(i32 message_index);

View File

@@ -91,6 +91,7 @@ endpoint WebContentClient
did_change_audio_play_state(u64 page_id, Web::HTML::AudioPlayState play_state) =|
did_execute_js_console_input(u64 page_id, JsonValue result) =|
did_output_js_console_message(u64 page_id, i32 message_index) =|
did_get_js_console_messages(u64 page_id, i32 start_index, Vector<String> message_types, Vector<String> messages) =|