mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-21 23:20:20 +00:00
LibWeb: Implement WebDriver element references according to the spec
Our currently ad-hoc method of tracking element references is basically a process-wide map, rather than grouping elements according to their browsing context groups. This prevents us from recognizing when an element reference is invalid due to its browsing context having been closed. This implements the WebDriver spec concept of element references grouped according to their browsing context groups. This patch is a bit noisy because we now need to plumb the current BC through to the element reference AOs.
This commit is contained in:
parent
ede6924db8
commit
a9c858fc78
Notes:
github-actions[bot]
2024-10-24 23:01:12 +00:00
Author: https://github.com/trflynn89 Commit: https://github.com/LadybirdBrowser/ladybird/commit/a9c858fc78d Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/1949 Reviewed-by: https://github.com/awesomekling ✅
8 changed files with 155 additions and 67 deletions
|
@ -397,6 +397,11 @@ BrowsingContextGroup* BrowsingContext::group()
|
|||
return m_group;
|
||||
}
|
||||
|
||||
BrowsingContextGroup const* BrowsingContext::group() const
|
||||
{
|
||||
return m_group;
|
||||
}
|
||||
|
||||
void BrowsingContext::set_group(BrowsingContextGroup* group)
|
||||
{
|
||||
m_group = group;
|
||||
|
|
|
@ -117,6 +117,7 @@ public:
|
|||
JS::GCPtr<BrowsingContext> top_level_browsing_context() const;
|
||||
|
||||
BrowsingContextGroup* group();
|
||||
BrowsingContextGroup const* group() const;
|
||||
void set_group(BrowsingContextGroup*);
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/browsers.html#bcg-remove
|
||||
|
|
|
@ -200,7 +200,7 @@ static ErrorOr<CSSPixelPoint, WebDriver::Error> get_coordinates_relative_to_orig
|
|||
// 1. Let element be the result of trying to run actions options' get element origin steps with origin and
|
||||
// browsing context.
|
||||
// 2. If element is null, return error with error code no such element.
|
||||
auto element = TRY(actions_options.get_element_origin(origin));
|
||||
auto element = TRY(actions_options.get_element_origin(browsing_context, origin));
|
||||
|
||||
// 3. Let x element and y element be the result of calculating the in-view center point of element.
|
||||
auto position = in_view_center_point(element, viewport);
|
||||
|
|
|
@ -119,7 +119,7 @@ struct ActionObject {
|
|||
// https://w3c.github.io/webdriver/#dfn-actions-options
|
||||
struct ActionsOptions {
|
||||
Function<bool(JsonObject const&)> is_element_origin;
|
||||
Function<ErrorOr<JS::NonnullGCPtr<DOM::Element>, WebDriver::Error>(StringView)> get_element_origin;
|
||||
Function<ErrorOr<JS::NonnullGCPtr<DOM::Element>, WebDriver::Error>(HTML::BrowsingContext const&, StringView)> get_element_origin;
|
||||
};
|
||||
|
||||
using OnActionsComplete = JS::NonnullGCPtr<JS::HeapFunction<void(Web::WebDriver::Response)>>;
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <AK/HashMap.h>
|
||||
#include <LibWeb/DOM/Document.h>
|
||||
#include <LibWeb/DOM/Element.h>
|
||||
#include <LibWeb/DOM/Node.h>
|
||||
|
@ -11,6 +12,7 @@
|
|||
#include <LibWeb/Geometry/DOMRect.h>
|
||||
#include <LibWeb/Geometry/DOMRectList.h>
|
||||
#include <LibWeb/HTML/BrowsingContext.h>
|
||||
#include <LibWeb/HTML/BrowsingContextGroup.h>
|
||||
#include <LibWeb/HTML/HTMLBodyElement.h>
|
||||
#include <LibWeb/HTML/HTMLInputElement.h>
|
||||
#include <LibWeb/HTML/HTMLTextAreaElement.h>
|
||||
|
@ -27,25 +29,105 @@ static ByteString const web_element_identifier = "element-6066-11e4-a52e-4f73546
|
|||
// https://w3c.github.io/webdriver/#dfn-shadow-root-identifier
|
||||
static ByteString const shadow_root_identifier = "shadow-6066-11e4-a52e-4f735466cecf"sv;
|
||||
|
||||
// https://w3c.github.io/webdriver/#dfn-get-or-create-a-web-element-reference
|
||||
ByteString get_or_create_a_web_element_reference(Web::DOM::Node const& element)
|
||||
{
|
||||
// FIXME: 1. For each known element of the current browsing context’s list of known elements:
|
||||
// FIXME: 1. If known element equals element, return success with known element’s web element reference.
|
||||
// FIXME: 2. Add element to the list of known elements of the current browsing context.
|
||||
// FIXME: 3. Return success with the element’s web element reference.
|
||||
// https://w3c.github.io/webdriver/#dfn-browsing-context-group-node-map
|
||||
static HashMap<JS::RawGCPtr<HTML::BrowsingContextGroup const>, HashTable<ByteString>> browsing_context_group_node_map;
|
||||
|
||||
return ByteString::number(element.unique_id().value());
|
||||
// https://w3c.github.io/webdriver/#dfn-navigable-seen-nodes-map
|
||||
static HashMap<JS::RawGCPtr<HTML::Navigable>, HashTable<ByteString>> navigable_seen_nodes_map;
|
||||
|
||||
// https://w3c.github.io/webdriver/#dfn-get-a-node
|
||||
JS::GCPtr<Web::DOM::Node> get_node(HTML::BrowsingContext const& browsing_context, StringView reference)
|
||||
{
|
||||
// 1. Let browsing context group node map be session's browsing context group node map.
|
||||
// 2. Let browsing context group be browsing context's browsing context group.
|
||||
auto const* browsing_context_group = browsing_context.group();
|
||||
|
||||
// 3. If browsing context group node map does not contain browsing context group, return null.
|
||||
// 4. Let node id map be browsing context group node map[browsing context group].
|
||||
auto node_id_map = browsing_context_group_node_map.get(browsing_context_group);
|
||||
if (!node_id_map.has_value())
|
||||
return nullptr;
|
||||
|
||||
// 5. Let node be the entry in node id map whose value is reference, if such an entry exists, or null otherwise.
|
||||
JS::GCPtr<Web::DOM::Node> node;
|
||||
|
||||
if (node_id_map->contains(reference)) {
|
||||
auto node_id = reference.to_number<i64>().value();
|
||||
node = Web::DOM::Node::from_unique_id(UniqueNodeID(node_id));
|
||||
}
|
||||
|
||||
// 6. Return node.
|
||||
return node;
|
||||
}
|
||||
|
||||
// https://w3c.github.io/webdriver/#dfn-get-or-create-a-node-reference
|
||||
ByteString get_or_create_a_node_reference(HTML::BrowsingContext const& browsing_context, Web::DOM::Node const& node)
|
||||
{
|
||||
// 1. Let browsing context group node map be session's browsing context group node map.
|
||||
// 2. Let browsing context group be browsing context's browsing context group.
|
||||
auto const* browsing_context_group = browsing_context.group();
|
||||
|
||||
// 3. If browsing context group node map does not contain browsing context group, set browsing context group node
|
||||
// map[browsing context group] to a new weak map.
|
||||
// 4. Let node id map be browsing context group node map[browsing context group].
|
||||
auto& node_id_map = browsing_context_group_node_map.ensure(browsing_context_group);
|
||||
|
||||
auto node_id = ByteString::number(node.unique_id().value());
|
||||
|
||||
// 5. If node id map does not contain node:
|
||||
if (!node_id_map.contains(node_id)) {
|
||||
// 1. Let node id be a new globally unique string.
|
||||
// 2. Set node id map[node] to node id.
|
||||
node_id_map.set(node_id);
|
||||
|
||||
// 3. Let navigable be browsing context's active document's node navigable.
|
||||
auto navigable = browsing_context.active_document()->navigable();
|
||||
|
||||
// 4. Let navigable seen nodes map be session's navigable seen nodes map.
|
||||
// 5. If navigable seen nodes map does not contain navigable, set navigable seen nodes map[navigable] to an empty set.
|
||||
// 6. Append node id to navigable seen nodes map[navigable].
|
||||
navigable_seen_nodes_map.ensure(navigable).set(node_id);
|
||||
}
|
||||
|
||||
// 6. Return node id map[node].
|
||||
return node_id;
|
||||
}
|
||||
|
||||
// https://w3c.github.io/webdriver/#dfn-node-reference-is-known
|
||||
bool node_reference_is_known(HTML::BrowsingContext const& browsing_context, StringView reference)
|
||||
{
|
||||
// 1. Let navigable be browsing context's active document's node navigable.
|
||||
auto navigable = browsing_context.active_document()->navigable();
|
||||
if (!navigable)
|
||||
return false;
|
||||
|
||||
// 2. Let navigable seen nodes map be session's navigable seen nodes map.
|
||||
// 3. If navigable seen nodes map contains navigable and navigable seen nodes map[navigable] contains reference,
|
||||
// return true, otherwise return false.
|
||||
if (auto map = navigable_seen_nodes_map.get(navigable); map.has_value())
|
||||
return map->contains(reference);
|
||||
return false;
|
||||
}
|
||||
|
||||
// https://w3c.github.io/webdriver/#dfn-get-or-create-a-web-element-reference
|
||||
ByteString get_or_create_a_web_element_reference(HTML::BrowsingContext const& browsing_context, Web::DOM::Node const& element)
|
||||
{
|
||||
// 1. Assert: element implements Element.
|
||||
VERIFY(element.is_element());
|
||||
|
||||
// 2. Return the result of trying to get or create a node reference given session, session's current browsing
|
||||
// context, and element.
|
||||
return get_or_create_a_node_reference(browsing_context, element);
|
||||
}
|
||||
|
||||
// https://w3c.github.io/webdriver/#dfn-web-element-reference-object
|
||||
JsonObject web_element_reference_object(Web::DOM::Node const& element)
|
||||
JsonObject web_element_reference_object(HTML::BrowsingContext const& browsing_context, Web::DOM::Node const& element)
|
||||
{
|
||||
// 1. Let identifier be the web element identifier.
|
||||
auto identifier = web_element_identifier;
|
||||
|
||||
// 2. Let reference be the result of get or create a web element reference given element.
|
||||
auto reference = get_or_create_a_web_element_reference(element);
|
||||
auto reference = get_or_create_a_web_element_reference(browsing_context, element);
|
||||
|
||||
// 3. Return a JSON Object initialized with a property with name identifier and value reference.
|
||||
JsonObject object;
|
||||
|
@ -54,7 +136,7 @@ JsonObject web_element_reference_object(Web::DOM::Node const& element)
|
|||
}
|
||||
|
||||
// https://w3c.github.io/webdriver/#dfn-deserialize-a-web-element
|
||||
ErrorOr<JS::NonnullGCPtr<Web::DOM::Element>, WebDriver::Error> deserialize_web_element(JsonObject const& object)
|
||||
ErrorOr<JS::NonnullGCPtr<Web::DOM::Element>, WebDriver::Error> deserialize_web_element(Web::HTML::BrowsingContext const& browsing_context, 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))
|
||||
|
@ -64,10 +146,10 @@ ErrorOr<JS::NonnullGCPtr<Web::DOM::Element>, WebDriver::Error> deserialize_web_e
|
|||
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_element(reference));
|
||||
auto element = TRY(get_known_element(browsing_context, reference));
|
||||
|
||||
// 4. Return success with data element.
|
||||
return *element;
|
||||
return element;
|
||||
}
|
||||
|
||||
ByteString extract_web_element_reference(JsonObject const& object)
|
||||
|
@ -85,39 +167,35 @@ bool represents_a_web_element(JsonValue const& value)
|
|||
}
|
||||
|
||||
// https://w3c.github.io/webdriver/#dfn-get-a-webelement-origin
|
||||
ErrorOr<JS::NonnullGCPtr<Web::DOM::Element>, Web::WebDriver::Error> get_web_element_origin(StringView origin)
|
||||
ErrorOr<JS::NonnullGCPtr<Web::DOM::Element>, Web::WebDriver::Error> get_web_element_origin(Web::HTML::BrowsingContext const& browsing_context, StringView origin)
|
||||
{
|
||||
// 1. Assert: browsing context is the current browsing context.
|
||||
|
||||
// 2. Let element be equal to the result of trying to get a known element with session and origin.
|
||||
auto element = TRY(get_known_element(origin));
|
||||
auto element = TRY(get_known_element(browsing_context, origin));
|
||||
|
||||
// 3. Return success with data element.
|
||||
return element;
|
||||
}
|
||||
|
||||
// https://w3c.github.io/webdriver/#dfn-get-a-known-element
|
||||
ErrorOr<JS::NonnullGCPtr<Web::DOM::Element>, Web::WebDriver::Error> get_known_element(StringView element_id)
|
||||
ErrorOr<JS::NonnullGCPtr<Web::DOM::Element>, Web::WebDriver::Error> get_known_element(Web::HTML::BrowsingContext const& browsing_context, StringView reference)
|
||||
{
|
||||
// NOTE: The whole concept of "connected elements" is not implemented yet. See get_or_create_a_web_element_reference().
|
||||
// For now the element is only represented by its ID.
|
||||
|
||||
// 1. If not node reference is known with session, session's current browsing context, and reference return error
|
||||
// with error code no such element.
|
||||
auto element = element_id.to_number<i64>();
|
||||
if (!element.has_value())
|
||||
if (!node_reference_is_known(browsing_context, reference))
|
||||
return Web::WebDriver::Error::from_code(Web::WebDriver::ErrorCode::NoSuchElement, "Element ID is not an integer");
|
||||
|
||||
// 2. Let node be the result of get a node with session, session's current browsing context, and reference.
|
||||
auto* node = Web::DOM::Node::from_unique_id(UniqueNodeID(*element));
|
||||
auto node = get_node(browsing_context, reference);
|
||||
|
||||
// 3. If node is not null and node does not implement Element return error with error code no such element.
|
||||
if (node && !node->is_element())
|
||||
return Web::WebDriver::Error::from_code(Web::WebDriver::ErrorCode::NoSuchElement, ByteString::formatted("Could not find element with ID: {}", element_id));
|
||||
return Web::WebDriver::Error::from_code(Web::WebDriver::ErrorCode::NoSuchElement, ByteString::formatted("Could not find element with node reference: {}", reference));
|
||||
|
||||
// 4. If node is null or node is stale return error with error code stale element reference.
|
||||
if (!node || is_element_stale(*node))
|
||||
return Web::WebDriver::Error::from_code(Web::WebDriver::ErrorCode::StaleElementReference, ByteString::formatted("Element with ID: {} is stale", element_id));
|
||||
return Web::WebDriver::Error::from_code(Web::WebDriver::ErrorCode::StaleElementReference, ByteString::formatted("Element reference {} is stale", reference));
|
||||
|
||||
// 5. Return success with data node.
|
||||
return static_cast<Web::DOM::Element&>(*node);
|
||||
|
|
|
@ -16,13 +16,17 @@
|
|||
|
||||
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&);
|
||||
JS::GCPtr<Web::DOM::Node> get_node(HTML::BrowsingContext const&, StringView reference);
|
||||
ByteString get_or_create_a_node_reference(HTML::BrowsingContext const&, Web::DOM::Node const&);
|
||||
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);
|
||||
ErrorOr<JS::NonnullGCPtr<Web::DOM::Element>, WebDriver::Error> deserialize_web_element(Web::HTML::BrowsingContext const&, JsonObject const&);
|
||||
ByteString extract_web_element_reference(JsonObject const&);
|
||||
bool represents_a_web_element(JsonValue const& value);
|
||||
ErrorOr<JS::NonnullGCPtr<Web::DOM::Element>, Web::WebDriver::Error> get_web_element_origin(StringView origin);
|
||||
ErrorOr<JS::NonnullGCPtr<Web::DOM::Element>, Web::WebDriver::Error> get_known_element(StringView element_id);
|
||||
ErrorOr<JS::NonnullGCPtr<Web::DOM::Element>, Web::WebDriver::Error> get_web_element_origin(Web::HTML::BrowsingContext const&, StringView origin);
|
||||
ErrorOr<JS::NonnullGCPtr<Web::DOM::Element>, Web::WebDriver::Error> get_known_element(Web::HTML::BrowsingContext const&, StringView reference);
|
||||
|
||||
bool is_element_stale(Web::DOM::Node const& element);
|
||||
bool is_element_interactable(Web::HTML::BrowsingContext const&, Web::DOM::Element const&);
|
||||
|
|
|
@ -46,8 +46,8 @@ namespace Web::WebDriver {
|
|||
_temporary_result.release_value(); \
|
||||
})
|
||||
|
||||
static ErrorOr<JsonValue, ExecuteScriptResultType> internal_json_clone_algorithm(JS::Realm&, JS::Value, HashTable<JS::Object*>& seen);
|
||||
static ErrorOr<JsonValue, ExecuteScriptResultType> clone_an_object(JS::Realm&, JS::Object&, HashTable<JS::Object*>& seen, auto const& clone_algorithm);
|
||||
static ErrorOr<JsonValue, ExecuteScriptResultType> internal_json_clone_algorithm(JS::Realm&, HTML::BrowsingContext const&, JS::Value, HashTable<JS::Object*>& seen);
|
||||
static ErrorOr<JsonValue, ExecuteScriptResultType> clone_an_object(JS::Realm&, HTML::BrowsingContext const&, JS::Object&, HashTable<JS::Object*>& seen, auto const& clone_algorithm);
|
||||
|
||||
// https://w3c.github.io/webdriver/#dfn-collection
|
||||
static bool is_collection(JS::Object const& value)
|
||||
|
@ -73,15 +73,15 @@ static bool is_collection(JS::Object const& value)
|
|||
}
|
||||
|
||||
// https://w3c.github.io/webdriver/#dfn-json-clone
|
||||
static ErrorOr<JsonValue, ExecuteScriptResultType> json_clone(JS::Realm& realm, JS::Value value)
|
||||
static ErrorOr<JsonValue, ExecuteScriptResultType> json_clone(JS::Realm& realm, HTML::BrowsingContext const& browsing_context, JS::Value value)
|
||||
{
|
||||
// To perform a JSON clone return the result of calling the internal JSON clone algorithm with arguments value and an empty List.
|
||||
auto seen = HashTable<JS::Object*> {};
|
||||
return internal_json_clone_algorithm(realm, value, seen);
|
||||
return internal_json_clone_algorithm(realm, browsing_context, value, seen);
|
||||
}
|
||||
|
||||
// https://w3c.github.io/webdriver/#dfn-internal-json-clone-algorithm
|
||||
static ErrorOr<JsonValue, ExecuteScriptResultType> internal_json_clone_algorithm(JS::Realm& realm, JS::Value value, HashTable<JS::Object*>& seen)
|
||||
static ErrorOr<JsonValue, ExecuteScriptResultType> internal_json_clone_algorithm(JS::Realm& realm, HTML::BrowsingContext const& browsing_context, JS::Value value, HashTable<JS::Object*>& seen)
|
||||
{
|
||||
auto& vm = realm.vm();
|
||||
|
||||
|
@ -122,7 +122,7 @@ static ErrorOr<JsonValue, ExecuteScriptResultType> internal_json_clone_algorithm
|
|||
// Otherwise:
|
||||
else {
|
||||
// 1. Let reference be the web element reference object for session and value.
|
||||
auto reference = web_element_reference_object(element);
|
||||
auto reference = web_element_reference_object(browsing_context, element);
|
||||
|
||||
// 2. Return success with data reference.
|
||||
return reference;
|
||||
|
@ -168,14 +168,14 @@ static ErrorOr<JsonValue, ExecuteScriptResultType> internal_json_clone_algorithm
|
|||
} };
|
||||
|
||||
// 3. Let result be the value of running the clone an object algorithm with arguments value and seen, and the internal JSON clone algorithm as the clone algorithm.
|
||||
auto result = TRY(clone_an_object(realm, value.as_object(), seen, internal_json_clone_algorithm));
|
||||
auto result = TRY(clone_an_object(realm, browsing_context, value.as_object(), seen, internal_json_clone_algorithm));
|
||||
|
||||
// 5. Return result.
|
||||
return result;
|
||||
}
|
||||
|
||||
// https://w3c.github.io/webdriver/#dfn-clone-an-object
|
||||
static ErrorOr<JsonValue, ExecuteScriptResultType> clone_an_object(JS::Realm& realm, JS::Object& value, HashTable<JS::Object*>& seen, auto const& clone_algorithm)
|
||||
static ErrorOr<JsonValue, ExecuteScriptResultType> clone_an_object(JS::Realm& realm, HTML::BrowsingContext const& browsing_context, JS::Object& value, HashTable<JS::Object*>& seen, auto const& clone_algorithm)
|
||||
{
|
||||
auto& vm = realm.vm();
|
||||
|
||||
|
@ -217,7 +217,7 @@ static ErrorOr<JsonValue, ExecuteScriptResultType> clone_an_object(JS::Realm& re
|
|||
continue;
|
||||
|
||||
// 3. Let cloned property result be the result of calling the clone algorithm with arguments source property value and seen.
|
||||
auto cloned_property_result = clone_algorithm(realm, *source_property_value->value, seen);
|
||||
auto cloned_property_result = clone_algorithm(realm, browsing_context, *source_property_value->value, seen);
|
||||
|
||||
// 4. If cloned property result is a success, set a property of result with name name and value equal to cloned property result’s data.
|
||||
if (!cloned_property_result.is_error()) {
|
||||
|
@ -398,12 +398,12 @@ void execute_script(HTML::BrowsingContext const& browsing_context, ByteString bo
|
|||
});
|
||||
|
||||
// 9. Wait until promise is resolved, or timer's timeout fired flag is set, whichever occurs first.
|
||||
auto reaction_steps = JS::create_heap_function(vm.heap(), [&realm, promise, timer, on_complete](JS::Value) -> WebIDL::ExceptionOr<JS::Value> {
|
||||
auto reaction_steps = JS::create_heap_function(vm.heap(), [&realm, &browsing_context, promise, timer, on_complete](JS::Value) -> WebIDL::ExceptionOr<JS::Value> {
|
||||
if (timer->is_timed_out())
|
||||
return JS::js_undefined();
|
||||
timer->stop();
|
||||
|
||||
auto json_value_or_error = json_clone(realm, promise->result());
|
||||
auto json_value_or_error = json_clone(realm, browsing_context, promise->result());
|
||||
if (json_value_or_error.is_error()) {
|
||||
auto error_object = JsonObject {};
|
||||
error_object.set("name", "Error");
|
||||
|
@ -513,12 +513,12 @@ void execute_async_script(HTML::BrowsingContext const& browsing_context, ByteStr
|
|||
});
|
||||
|
||||
// 9. Wait until promise is resolved, or timer's timeout fired flag is set, whichever occurs first.
|
||||
auto reaction_steps = JS::create_heap_function(vm.heap(), [&realm, promise, timer, on_complete](JS::Value) -> WebIDL::ExceptionOr<JS::Value> {
|
||||
auto reaction_steps = JS::create_heap_function(vm.heap(), [&realm, &browsing_context, promise, timer, on_complete](JS::Value) -> WebIDL::ExceptionOr<JS::Value> {
|
||||
if (timer->is_timed_out())
|
||||
return JS::js_undefined();
|
||||
timer->stop();
|
||||
|
||||
auto json_value_or_error = json_clone(realm, promise->result());
|
||||
auto json_value_or_error = json_clone(realm, browsing_context, promise->result());
|
||||
if (json_value_or_error.is_error()) {
|
||||
auto error_object = JsonObject {};
|
||||
error_object.set("name", "Error");
|
||||
|
|
|
@ -565,7 +565,7 @@ Messages::WebDriverClient::SwitchToFrameResponse WebDriverConnection::switch_to_
|
|||
TRY(handle_any_user_prompts());
|
||||
|
||||
// 3. Let element be the result of trying to get a known element with session and id.
|
||||
auto element = TRY(Web::WebDriver::get_known_element(element_id));
|
||||
auto element = TRY(Web::WebDriver::get_known_element(current_browsing_context(), element_id));
|
||||
|
||||
// 4. If element is not a frame or iframe element, return error with error code no such frame.
|
||||
bool is_frame = is<Web::HTML::HTMLFrameElement>(*element);
|
||||
|
@ -902,7 +902,7 @@ Messages::WebDriverClient::FindElementFromElementResponse WebDriverConnection::f
|
|||
|
||||
auto start_node_getter = [&]() -> StartNodeGetter::ReturnType {
|
||||
// 7. Let start node be the result of trying to get a known connected element with url variable element id.
|
||||
return TRY(Web::WebDriver::get_known_element(element_id));
|
||||
return TRY(Web::WebDriver::get_known_element(current_browsing_context(), element_id));
|
||||
};
|
||||
|
||||
// 8. Let result be the value of trying to Find with start node, location strategy, and selector.
|
||||
|
@ -938,7 +938,7 @@ Messages::WebDriverClient::FindElementsFromElementResponse WebDriverConnection::
|
|||
|
||||
auto start_node_getter = [&]() -> StartNodeGetter::ReturnType {
|
||||
// 7. Let start node be the result of trying to get a known connected element with url variable element id.
|
||||
return TRY(Web::WebDriver::get_known_element(element_id));
|
||||
return TRY(Web::WebDriver::get_known_element(current_browsing_context(), element_id));
|
||||
};
|
||||
|
||||
// 8. Return the result of trying to Find with start node, location strategy, and selector.
|
||||
|
@ -1041,7 +1041,7 @@ Messages::WebDriverClient::GetElementShadowRootResponse WebDriverConnection::get
|
|||
TRY(handle_any_user_prompts());
|
||||
|
||||
// 3. Let element be the result of trying to get a known connected element with url variable element id.
|
||||
auto element = TRY(Web::WebDriver::get_known_element(element_id));
|
||||
auto element = TRY(Web::WebDriver::get_known_element(current_browsing_context(), element_id));
|
||||
|
||||
// 4. Let shadow root be element's shadow root.
|
||||
auto shadow_root = element->shadow_root();
|
||||
|
@ -1067,7 +1067,7 @@ Messages::WebDriverClient::IsElementSelectedResponse WebDriverConnection::is_ele
|
|||
TRY(handle_any_user_prompts());
|
||||
|
||||
// 3. Let element be the result of trying to get a known connected element with url variable element id.
|
||||
auto element = TRY(Web::WebDriver::get_known_element(element_id));
|
||||
auto element = TRY(Web::WebDriver::get_known_element(current_browsing_context(), element_id));
|
||||
|
||||
// 4. Let selected be the value corresponding to the first matching statement:
|
||||
bool selected = false;
|
||||
|
@ -1103,7 +1103,7 @@ Messages::WebDriverClient::GetElementAttributeResponse WebDriverConnection::get_
|
|||
TRY(handle_any_user_prompts());
|
||||
|
||||
// 3. Let element be the result of trying to get a known connected element with url variable element id.
|
||||
auto element = TRY(Web::WebDriver::get_known_element(element_id));
|
||||
auto element = TRY(Web::WebDriver::get_known_element(current_browsing_context(), element_id));
|
||||
|
||||
// 4. Let result be the result of the first matching condition:
|
||||
Optional<ByteString> result;
|
||||
|
@ -1137,7 +1137,7 @@ Messages::WebDriverClient::GetElementPropertyResponse WebDriverConnection::get_e
|
|||
TRY(handle_any_user_prompts());
|
||||
|
||||
// 3. Let element be the result of trying to get a known connected element with url variable element id.
|
||||
auto element = TRY(Web::WebDriver::get_known_element(element_id));
|
||||
auto element = TRY(Web::WebDriver::get_known_element(current_browsing_context(), element_id));
|
||||
|
||||
Optional<ByteString> result;
|
||||
|
||||
|
@ -1170,7 +1170,7 @@ Messages::WebDriverClient::GetElementCssValueResponse WebDriverConnection::get_e
|
|||
TRY(handle_any_user_prompts());
|
||||
|
||||
// 3. Let element be the result of trying to get a known connected element with url variable element id.
|
||||
auto element = TRY(Web::WebDriver::get_known_element(element_id));
|
||||
auto element = TRY(Web::WebDriver::get_known_element(current_browsing_context(), element_id));
|
||||
|
||||
// 4. Let computed value be the result of the first matching condition:
|
||||
ByteString computed_value;
|
||||
|
@ -1203,7 +1203,7 @@ Messages::WebDriverClient::GetElementTextResponse WebDriverConnection::get_eleme
|
|||
TRY(handle_any_user_prompts());
|
||||
|
||||
// 3. Let element be the result of trying to get a known connected element with url variable element id.
|
||||
auto element = TRY(Web::WebDriver::get_known_element(element_id));
|
||||
auto element = TRY(Web::WebDriver::get_known_element(current_browsing_context(), element_id));
|
||||
|
||||
// 4. Let rendered text be the result of performing implementation-specific steps whose result is exactly the same as the result of a Function.[[Call]](null, element) with bot.dom.getVisibleText as the this value.
|
||||
auto rendered_text = element->text_content();
|
||||
|
@ -1222,7 +1222,7 @@ Messages::WebDriverClient::GetElementTagNameResponse WebDriverConnection::get_el
|
|||
TRY(handle_any_user_prompts());
|
||||
|
||||
// 3. Let element be the result of trying to get a known connected element with url variable element id.
|
||||
auto element = TRY(Web::WebDriver::get_known_element(element_id));
|
||||
auto element = TRY(Web::WebDriver::get_known_element(current_browsing_context(), element_id));
|
||||
|
||||
// 4. Let qualified name be the result of getting element’s tagName IDL attribute.
|
||||
auto qualified_name = element->tag_name();
|
||||
|
@ -1241,7 +1241,7 @@ Messages::WebDriverClient::GetElementRectResponse WebDriverConnection::get_eleme
|
|||
TRY(handle_any_user_prompts());
|
||||
|
||||
// 3. Let element be the result of trying to get a known connected element with url variable element id.
|
||||
auto element = TRY(Web::WebDriver::get_known_element(element_id));
|
||||
auto element = TRY(Web::WebDriver::get_known_element(current_browsing_context(), element_id));
|
||||
|
||||
// 4. Calculate the absolute position of element and let it be coordinates.
|
||||
// 5. Let rect be element’s bounding rectangle.
|
||||
|
@ -1272,7 +1272,7 @@ Messages::WebDriverClient::IsElementEnabledResponse WebDriverConnection::is_elem
|
|||
TRY(handle_any_user_prompts());
|
||||
|
||||
// 3. Let element be the result of trying to get a known connected element with url variable element id.
|
||||
auto element = TRY(Web::WebDriver::get_known_element(element_id));
|
||||
auto element = TRY(Web::WebDriver::get_known_element(current_browsing_context(), element_id));
|
||||
|
||||
// 4. Let enabled be a boolean initially set to true if the current browsing context’s active document’s type is not "xml".
|
||||
// 5. Otherwise, let enabled to false and jump to the last step of this algorithm.
|
||||
|
@ -1298,7 +1298,7 @@ Messages::WebDriverClient::GetComputedRoleResponse WebDriverConnection::get_comp
|
|||
TRY(handle_any_user_prompts());
|
||||
|
||||
// 3. Let element be the result of trying to get a known connected element with url variable element id.
|
||||
auto element = TRY(Web::WebDriver::get_known_element(element_id));
|
||||
auto element = TRY(Web::WebDriver::get_known_element(current_browsing_context(), element_id));
|
||||
|
||||
// 4. Let role be the result of computing the WAI-ARIA role of element.
|
||||
auto role = element->role_or_default();
|
||||
|
@ -1319,7 +1319,7 @@ Messages::WebDriverClient::GetComputedLabelResponse WebDriverConnection::get_com
|
|||
TRY(handle_any_user_prompts());
|
||||
|
||||
// 3. Let element be the result of trying to get a known element with url variable element id.
|
||||
auto element = TRY(Web::WebDriver::get_known_element(element_id));
|
||||
auto element = TRY(Web::WebDriver::get_known_element(current_browsing_context(), element_id));
|
||||
|
||||
// 4. Let label be the result of a Accessible Name and Description Computation for the Accessible Name of the element.
|
||||
auto label = element->accessible_name(element->document()).release_value_but_fixme_should_propagate_errors();
|
||||
|
@ -1338,7 +1338,7 @@ Messages::WebDriverClient::ElementClickResponse WebDriverConnection::element_cli
|
|||
TRY(handle_any_user_prompts());
|
||||
|
||||
// 3. Let element be the result of trying to get a known element with element id.
|
||||
auto element = TRY(Web::WebDriver::get_known_element(element_id));
|
||||
auto element = TRY(Web::WebDriver::get_known_element(current_browsing_context(), element_id));
|
||||
|
||||
// 4. If the element is an input element in the file upload state return error with error code invalid argument.
|
||||
if (is<Web::HTML::HTMLInputElement>(*element)) {
|
||||
|
@ -1467,7 +1467,7 @@ Messages::WebDriverClient::ElementClickResponse WebDriverConnection::element_cli
|
|||
pointer_move_action.pointer_move_fields().position = { 0, 0 };
|
||||
|
||||
// 10. Set a property origin to element on pointer move action.
|
||||
auto origin = Web::WebDriver::get_or_create_a_web_element_reference(*element);
|
||||
auto origin = Web::WebDriver::get_or_create_a_web_element_reference(current_browsing_context(), *element);
|
||||
pointer_move_action.pointer_move_fields().origin = MUST(String::from_byte_string(origin));
|
||||
|
||||
// 11. Let pointer down action be an action object constructed with arguments input id, "pointer", and "pointerDown".
|
||||
|
@ -1561,7 +1561,7 @@ Messages::WebDriverClient::ElementClearResponse WebDriverConnection::element_cle
|
|||
TRY(handle_any_user_prompts());
|
||||
|
||||
// 3. Let element be the result of trying to get a known element with session and element id.
|
||||
auto element = TRY(Web::WebDriver::get_known_element(element_id));
|
||||
auto element = TRY(Web::WebDriver::get_known_element(current_browsing_context(), element_id));
|
||||
|
||||
// 4. If element is not editable, return an error with error code invalid element state.
|
||||
if (!Web::WebDriver::is_element_editable(*element))
|
||||
|
@ -1617,7 +1617,7 @@ Messages::WebDriverClient::ElementSendKeysResponse WebDriverConnection::element_
|
|||
TRY(handle_any_user_prompts());
|
||||
|
||||
// 5. Let element be the result of trying to get a known element with session and URL variables[element id].
|
||||
auto element = TRY(Web::WebDriver::get_known_element(element_id));
|
||||
auto element = TRY(Web::WebDriver::get_known_element(current_browsing_context(), element_id));
|
||||
|
||||
// 6. Let file be true if element is input element in the file upload state, or false otherwise.
|
||||
auto file = is<Web::HTML::HTMLInputElement>(*element) && static_cast<Web::HTML::HTMLInputElement&>(*element).type_state() == Web::HTML::HTMLInputElement::TypeAttributeState::FileUpload;
|
||||
|
@ -2273,7 +2273,7 @@ Messages::WebDriverClient::TakeElementScreenshotResponse WebDriverConnection::ta
|
|||
TRY(handle_any_user_prompts());
|
||||
|
||||
// 3. Let element be the result of trying to get a known connected element with url variable element id.
|
||||
auto element = TRY(Web::WebDriver::get_known_element(element_id));
|
||||
auto element = TRY(Web::WebDriver::get_known_element(current_browsing_context(), element_id));
|
||||
|
||||
// 4. Scroll into view the element.
|
||||
(void)scroll_element_into_view(*element);
|
||||
|
@ -2545,14 +2545,14 @@ ErrorOr<JsonArray, Web::WebDriver::Error> WebDriverConnection::find(StartNodeGet
|
|||
|
||||
// 8. For each element in elements returned, append the web element reference object for element, to result.
|
||||
for (size_t i = 0; i < elements->length(); ++i)
|
||||
TRY(result.append(Web::WebDriver::web_element_reference_object(*elements->item(i))));
|
||||
TRY(result.append(Web::WebDriver::web_element_reference_object(current_browsing_context(), *elements->item(i))));
|
||||
|
||||
// 9. Return success with data result.
|
||||
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)
|
||||
static ErrorOr<JS::Value, Web::WebDriver::Error> json_deserialize(JS::VM& vm, Web::HTML::BrowsingContext const& browsing_context, JsonValue const& value)
|
||||
{
|
||||
// 1. If seen is not provided, let seen be an empty List.
|
||||
// 2. Jump to the first appropriate step below:
|
||||
|
@ -2570,7 +2570,7 @@ static ErrorOr<JS::Value, Web::WebDriver::Error> json_deserialize(JS::VM& vm, Js
|
|||
// -> 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());
|
||||
return Web::WebDriver::deserialize_web_element(browsing_context, value.as_object());
|
||||
}
|
||||
|
||||
// FIXME: -> Object that represents a shadow root
|
||||
|
@ -2604,7 +2604,7 @@ ErrorOr<WebDriverConnection::ScriptArguments, Web::WebDriver::Error> WebDriverCo
|
|||
auto arguments = JS::MarkedVector<JS::Value> { vm.heap() };
|
||||
|
||||
TRY(args.try_for_each([&](auto const& arg) -> ErrorOr<void, Web::WebDriver::Error> {
|
||||
arguments.append(TRY(json_deserialize(vm, arg)));
|
||||
arguments.append(TRY(json_deserialize(vm, current_browsing_context(), arg)));
|
||||
return {};
|
||||
}));
|
||||
|
||||
|
|
Loading…
Reference in a new issue