LibWeb+WebContent: Partially implement WebDriver's JSON deserialize AO

In particular, we need to convert web element references to the actual
element. The AO isn't fully implemented because we will need to work out
mixing JsonValue types with JS value types, which currently isn't very
straight forward with our JSON clone algorithm.
This commit is contained in:
Timothy Flynn 2024-09-29 11:44:17 -04:00 committed by Andreas Kling
parent 434663b1c6
commit 94c243acd6
Notes: github-actions[bot] 2024-10-01 09:03:42 +00:00
3 changed files with 60 additions and 5 deletions
Userland
Libraries/LibWeb/WebDriver
Services/WebContent

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2024, Tim Flynn <trflynn89@serenityos.org>
* Copyright (c) 2024, Tim Flynn <trflynn89@ladybird.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
@ -44,6 +44,23 @@ JsonObject web_element_reference_object(Web::DOM::Node const& element)
return object;
}
// https://w3c.github.io/webdriver/#dfn-deserialize-a-web-element
ErrorOr<JS::NonnullGCPtr<Web::DOM::Element>, WebDriver::Error> deserialize_web_element(JsonObject const& object)
{
// 1. If object has no own property web element identifier, return error with error code invalid argument.
if (!object.has_string(web_element_identifier))
return WebDriver::Error::from_code(WebDriver::ErrorCode::InvalidArgument, "Object is not a web element");
// 2. Let reference be the result of getting the web element identifier property from object.
auto reference = extract_web_element_reference(object);
// 3. Let element be the result of trying to get a known element with session and reference.
auto* element = TRY(get_known_connected_element(reference));
// 4. Return success with data element.
return *element;
}
ByteString extract_web_element_reference(JsonObject const& object)
{
return object.get_byte_string(web_element_identifier).release_value();

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2024, Tim Flynn <trflynn89@serenityos.org>
* Copyright (c) 2024, Tim Flynn <trflynn89@ladybird.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
@ -9,6 +9,7 @@
#include <AK/ByteString.h>
#include <AK/Error.h>
#include <AK/JsonObject.h>
#include <LibJS/Heap/GCPtr.h>
#include <LibWeb/Forward.h>
#include <LibWeb/WebDriver/Error.h>
@ -16,6 +17,7 @@ namespace Web::WebDriver {
ByteString get_or_create_a_web_element_reference(Web::DOM::Node const& element);
JsonObject web_element_reference_object(Web::DOM::Node const& element);
ErrorOr<JS::NonnullGCPtr<Web::DOM::Element>, WebDriver::Error> deserialize_web_element(JsonObject const&);
ByteString extract_web_element_reference(JsonObject const&);
bool represents_a_web_element(JsonValue const& value);
ErrorOr<Web::DOM::Element*, Web::WebDriver::Error> get_known_connected_element(StringView element_id);

View file

@ -2312,6 +2312,41 @@ ErrorOr<JsonArray, Web::WebDriver::Error> WebDriverConnection::find(StartNodeGet
return result;
}
// https://w3c.github.io/webdriver/#dfn-json-deserialize
static ErrorOr<JS::Value, Web::WebDriver::Error> json_deserialize(JS::VM& vm, JsonValue const& value)
{
// 1. If seen is not provided, let seen be an empty List.
// 2. Jump to the first appropriate step below:
// 3. Matching on value:
// -> undefined
// -> null
// -> type Boolean
// -> type Number
// -> type String
if (value.is_null() || value.is_bool() || value.is_number() || value.is_string()) {
// Return success with data value.
return JS::JSONObject::parse_json_value(vm, value);
}
// -> Object that represents a web element
if (Web::WebDriver::represents_a_web_element(value)) {
// Return the deserialized web element of value.
return Web::WebDriver::deserialize_web_element(value.as_object());
}
// FIXME: -> Object that represents a shadow root
// Return the deserialized shadow root of value.
// FIXME: -> Object that represents a web frame
// Return the deserialized web frame of value.
// FIXME: -> Object that represents a web window
// Return the deserialized web window of value.
// FIXME: -> instance of Array
// FIXME: -> instance of Object
// Return clone an object algorithm with session, value and seen, and the JSON deserialize algorithm as the clone algorithm.
dbgln("FIXME: Implement JSON deserialize for: {}", value);
return JS::JSONObject::parse_json_value(vm, value);
}
// https://w3c.github.io/webdriver/#dfn-extract-the-script-arguments-from-a-request
ErrorOr<WebDriverConnection::ScriptArguments, Web::WebDriver::Error> WebDriverConnection::extract_the_script_arguments_from_a_request(JS::VM& vm, JsonValue const& payload)
{
@ -2329,9 +2364,10 @@ ErrorOr<WebDriverConnection::ScriptArguments, Web::WebDriver::Error> WebDriverCo
// 5. Let arguments be the result of calling the JSON deserialize algorithm with arguments args.
auto arguments = JS::MarkedVector<JS::Value> { vm.heap() };
args.for_each([&](auto const& arg) {
arguments.append(JS::JSONObject::parse_json_value(vm, arg));
});
TRY(args.try_for_each([&](auto const& arg) -> ErrorOr<void, Web::WebDriver::Error> {
arguments.append(TRY(json_deserialize(vm, arg)));
return {};
}));
// 6. Return success with data script and arguments.
return ScriptArguments { move(script), move(arguments) };