From 0371097e2c5e8b694696d1f83f4c3d3f46a1dedb Mon Sep 17 00:00:00 2001 From: Timothy Flynn Date: Sun, 3 Nov 2024 07:11:06 -0500 Subject: [PATCH] LibWeb: Add overloads of some element reference AOs for JS objects We currently only use these methods with AK JSON objects, but they're actually spec'd for JS objects, as the WebDriver spec sort of assumes we are sending encoded JS objects over the wire. When we fully implement JSON deserialization for executing scripts, we will need to invoke these AOs with JS objects. --- .../LibWeb/WebDriver/ElementReference.cpp | 105 ++++++++++++++++-- .../LibWeb/WebDriver/ElementReference.h | 10 +- 2 files changed, 105 insertions(+), 10 deletions(-) diff --git a/Userland/Libraries/LibWeb/WebDriver/ElementReference.cpp b/Userland/Libraries/LibWeb/WebDriver/ElementReference.cpp index d5c1a56f294..c8dec6ef5a2 100644 --- a/Userland/Libraries/LibWeb/WebDriver/ElementReference.cpp +++ b/Userland/Libraries/LibWeb/WebDriver/ElementReference.cpp @@ -5,6 +5,7 @@ */ #include +#include #include #include #include @@ -135,6 +136,27 @@ JsonObject web_element_reference_object(HTML::BrowsingContext const& browsing_co return object; } +// https://w3c.github.io/webdriver/#dfn-represents-a-web-element +bool represents_a_web_element(JsonValue const& value) +{ + // An ECMAScript Object represents a web element if it has a web element identifier own property. + if (!value.is_object()) + return false; + + return value.as_object().has(web_element_identifier); +} + +// https://w3c.github.io/webdriver/#dfn-represents-a-web-element +bool represents_a_web_element(JS::Value value) +{ + // An ECMAScript Object represents a web element if it has a web element identifier own property. + if (!value.is_object()) + return false; + + auto result = value.as_object().has_own_property(web_element_identifier); + return !result.is_error() && result.value(); +} + // https://w3c.github.io/webdriver/#dfn-deserialize-a-web-element ErrorOr, WebDriver::Error> deserialize_web_element(Web::HTML::BrowsingContext const& browsing_context, JsonObject const& object) { @@ -152,20 +174,29 @@ ErrorOr, WebDriver::Error> deserialize_web_e return element; } +// https://w3c.github.io/webdriver/#dfn-deserialize-a-web-element +ErrorOr, WebDriver::Error> deserialize_web_element(Web::HTML::BrowsingContext const& browsing_context, JS::Object const& object) +{ + // 1. If object has no own property web element identifier, return error with error code invalid argument. + auto property = object.get(web_element_identifier); + if (property.is_error() || !property.value().is_string()) + 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 = property.value().as_string().utf8_string(); + + // 3. Let element be the result of trying to get a known element with session and reference. + auto element = TRY(get_known_element(browsing_context, 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(); } -// https://w3c.github.io/webdriver/#dfn-represents-a-web-element -bool represents_a_web_element(JsonValue const& value) -{ - // An ECMAScript Object represents a web element if it has a web element identifier own property. - if (!value.is_object()) - return false; - return value.as_object().has_string(web_element_identifier); -} - // https://w3c.github.io/webdriver/#dfn-get-a-webelement-origin ErrorOr, Web::WebDriver::Error> get_web_element_origin(Web::HTML::BrowsingContext const& browsing_context, StringView origin) { @@ -399,6 +430,62 @@ JsonObject shadow_root_reference_object(HTML::BrowsingContext const& browsing_co return object; } +// https://w3c.github.io/webdriver/#dfn-represents-a-shadow-root +bool represents_a_shadow_root(JsonValue const& value) +{ + // An ECMAScript Object represents a shadow root if it has a shadow root identifier own property. + if (!value.is_object()) + return false; + + return value.as_object().has(shadow_root_identifier); +} + +// https://w3c.github.io/webdriver/#dfn-represents-a-shadow-root +bool represents_a_shadow_root(JS::Value value) +{ + // An ECMAScript Object represents a shadow root if it has a shadow root identifier own property. + if (!value.is_object()) + return false; + + auto result = value.as_object().has_own_property(shadow_root_identifier); + return !result.is_error() && result.value(); +} + +// https://w3c.github.io/webdriver/#dfn-deserialize-a-shadow-root +ErrorOr, WebDriver::Error> deserialize_shadow_root(Web::HTML::BrowsingContext const& browsing_context, JsonObject const& object) +{ + // 1. If object has no own property shadow root identifier, return error with error code invalid argument. + if (!object.has_string(shadow_root_identifier)) + return WebDriver::Error::from_code(WebDriver::ErrorCode::InvalidArgument, "Object is not a Shadow Root"); + + // 2. Let reference be the result of getting the shadow root identifier property from object. + auto reference = object.get_byte_string(shadow_root_identifier).release_value(); + + // 3. Let shadow be the result of trying to get a known shadow root with session and reference. + auto shadow = TRY(get_known_shadow_root(browsing_context, reference)); + + // 4. Return success with data shadow. + return shadow; +} + +// https://w3c.github.io/webdriver/#dfn-deserialize-a-shadow-root +ErrorOr, WebDriver::Error> deserialize_shadow_root(Web::HTML::BrowsingContext const& browsing_context, JS::Object const& object) +{ + // 1. If object has no own property shadow root identifier, return error with error code invalid argument. + auto property = object.get(shadow_root_identifier); + if (property.is_error() || !property.value().is_string()) + return WebDriver::Error::from_code(WebDriver::ErrorCode::InvalidArgument, "Object is not a Shadow Root"); + + // 2. Let reference be the result of getting the shadow root identifier property from object. + auto reference = property.value().as_string().utf8_string(); + + // 3. Let shadow be the result of trying to get a known shadow root with session and reference. + auto shadow = TRY(get_known_shadow_root(browsing_context, reference)); + + // 4. Return success with data shadow. + return shadow; +} + // https://w3c.github.io/webdriver/#dfn-get-a-known-shadow-root ErrorOr, Web::WebDriver::Error> get_known_shadow_root(HTML::BrowsingContext const& browsing_context, StringView reference) { diff --git a/Userland/Libraries/LibWeb/WebDriver/ElementReference.h b/Userland/Libraries/LibWeb/WebDriver/ElementReference.h index 301bd975024..b9d3e0b86a6 100644 --- a/Userland/Libraries/LibWeb/WebDriver/ElementReference.h +++ b/Userland/Libraries/LibWeb/WebDriver/ElementReference.h @@ -9,7 +9,9 @@ #include #include #include +#include #include +#include #include #include #include @@ -22,9 +24,11 @@ bool node_reference_is_known(HTML::BrowsingContext const&, StringView reference) ByteString get_or_create_a_web_element_reference(HTML::BrowsingContext const&, Web::DOM::Node const& element); JsonObject web_element_reference_object(HTML::BrowsingContext const&, Web::DOM::Node const& element); +bool represents_a_web_element(JsonValue const&); +bool represents_a_web_element(JS::Value); ErrorOr, WebDriver::Error> deserialize_web_element(Web::HTML::BrowsingContext const&, JsonObject const&); +ErrorOr, WebDriver::Error> deserialize_web_element(Web::HTML::BrowsingContext const&, JS::Object const&); ByteString extract_web_element_reference(JsonObject const&); -bool represents_a_web_element(JsonValue const& value); ErrorOr, Web::WebDriver::Error> get_web_element_origin(Web::HTML::BrowsingContext const&, StringView origin); ErrorOr, Web::WebDriver::Error> get_known_element(Web::HTML::BrowsingContext const&, StringView reference); @@ -44,6 +48,10 @@ JS::MarkedVector> pointer_interactable_tree( ByteString get_or_create_a_shadow_root_reference(HTML::BrowsingContext const&, Web::DOM::ShadowRoot const&); JsonObject shadow_root_reference_object(HTML::BrowsingContext const&, Web::DOM::ShadowRoot const&); +bool represents_a_shadow_root(JsonValue const&); +bool represents_a_shadow_root(JS::Value); +ErrorOr, WebDriver::Error> deserialize_shadow_root(Web::HTML::BrowsingContext const&, JsonObject const&); +ErrorOr, WebDriver::Error> deserialize_shadow_root(Web::HTML::BrowsingContext const&, JS::Object const&); ErrorOr, Web::WebDriver::Error> get_known_shadow_root(HTML::BrowsingContext const&, StringView reference); bool is_shadow_root_detached(Web::DOM::ShadowRoot const&);