mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-09-02 15:46:33 +00:00
LibWeb+WebContent+WebDriver: Port WebDriver to String
This commit is contained in:
parent
bc54c0cdfb
commit
9879ac0893
Notes:
github-actions[bot]
2025-02-21 00:29:12 +00:00
Author: https://github.com/trflynn89
Commit: 9879ac0893
Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/3631
Reviewed-by: https://github.com/awesomekling ✅
21 changed files with 194 additions and 190 deletions
|
@ -106,7 +106,7 @@ static Optional<ActionObject::Origin> determine_origin(ActionsOptions const& act
|
|||
|
||||
if (origin->is_object()) {
|
||||
if (actions_options.is_element_origin(origin->as_object()))
|
||||
return MUST(String::from_byte_string(extract_web_element_reference(origin->as_object())));
|
||||
return extract_web_element_reference(origin->as_object());
|
||||
}
|
||||
|
||||
return {};
|
||||
|
@ -229,7 +229,7 @@ static ErrorOr<PointerParameters, WebDriver::Error> process_pointer_parameters(O
|
|||
|
||||
// 3. If parameters data is not an Object, return error with error code invalid argument.
|
||||
if (!parameters_data->is_object())
|
||||
return WebDriver::Error::from_code(WebDriver::ErrorCode::InvalidArgument, "Property 'parameters' is not an Object");
|
||||
return WebDriver::Error::from_code(WebDriver::ErrorCode::InvalidArgument, "Property 'parameters' is not an Object"sv);
|
||||
|
||||
// 4. Let pointer type be the result of getting a property named "pointerType" from parameters data.
|
||||
auto pointer_type = TRY(get_optional_property(parameters_data->as_object(), "pointerType"sv));
|
||||
|
@ -241,7 +241,7 @@ static ErrorOr<PointerParameters, WebDriver::Error> process_pointer_parameters(O
|
|||
auto parsed_pointer_type = pointer_input_source_subtype_from_string(*pointer_type);
|
||||
|
||||
if (!parsed_pointer_type.has_value())
|
||||
return WebDriver::Error::from_code(WebDriver::ErrorCode::InvalidArgument, "Property 'pointerType' must be one of 'mouse', 'pen', or 'touch'");
|
||||
return WebDriver::Error::from_code(WebDriver::ErrorCode::InvalidArgument, "Property 'pointerType' must be one of 'mouse', 'pen', or 'touch'"sv);
|
||||
|
||||
// 2. Set the pointerType property of parameters to pointer type.
|
||||
parameters.pointer_type = *parsed_pointer_type;
|
||||
|
@ -272,7 +272,7 @@ static ErrorOr<ActionObject, WebDriver::Error> process_null_action(String id, Js
|
|||
|
||||
// 2. If subtype is not "pause", return error with error code invalid argument.
|
||||
if (subtype != ActionObject::Subtype::Pause)
|
||||
return WebDriver::Error::from_code(WebDriver::ErrorCode::InvalidArgument, "Property 'type' must be 'pause'");
|
||||
return WebDriver::Error::from_code(WebDriver::ErrorCode::InvalidArgument, "Property 'type' must be 'pause'"sv);
|
||||
|
||||
// 3. Let action be an action object constructed with arguments id, "none", and subtype.
|
||||
ActionObject action { move(id), InputSourceType::None, *subtype };
|
||||
|
@ -294,7 +294,7 @@ static ErrorOr<ActionObject, WebDriver::Error> process_key_action(String id, Jso
|
|||
|
||||
// 2. If subtype is not one of the values "keyUp", "keyDown", or "pause", return an error with error code invalid argument.
|
||||
if (!first_is_one_of(subtype, KeyUp, KeyDown, Pause))
|
||||
return WebDriver::Error::from_code(WebDriver::ErrorCode::InvalidArgument, "Property 'type' must be one of 'keyUp', 'keyDown', or 'pause'");
|
||||
return WebDriver::Error::from_code(WebDriver::ErrorCode::InvalidArgument, "Property 'type' must be one of 'keyUp', 'keyDown', or 'pause'"sv);
|
||||
|
||||
// 3. Let action be an action object constructed with arguments id, "key", and subtype.
|
||||
ActionObject action { move(id), InputSourceType::Key, *subtype };
|
||||
|
@ -317,7 +317,7 @@ static ErrorOr<ActionObject, WebDriver::Error> process_key_action(String id, Jso
|
|||
// FIXME: The spec seems undecided on whether grapheme clusters should be supported. Update this step to check
|
||||
// for graphemes if we end up needing to support them. We would also need to update Page's key event
|
||||
// handlers to support multi-code point events.
|
||||
return WebDriver::Error::from_code(WebDriver::ErrorCode::InvalidArgument, "Property 'value' must be a single code point");
|
||||
return WebDriver::Error::from_code(WebDriver::ErrorCode::InvalidArgument, "Property 'value' must be a single code point"sv);
|
||||
}
|
||||
|
||||
// 7. Set the value property on action to key.
|
||||
|
@ -412,7 +412,7 @@ static ErrorOr<void, WebDriver::Error> process_pointer_move_action(JsonObject co
|
|||
// 6. If origin is not equal to "viewport" or "pointer", and actions options is element origin steps given origin
|
||||
// return false, return error with error code invalid argument.
|
||||
if (!origin.has_value())
|
||||
return WebDriver::Error::from_code(WebDriver::ErrorCode::InvalidArgument, "Property 'origin' must be 'viewport', 'pointer', or an element origin");
|
||||
return WebDriver::Error::from_code(WebDriver::ErrorCode::InvalidArgument, "Property 'origin' must be 'viewport', 'pointer', or an element origin"sv);
|
||||
|
||||
// 7. Set the origin property of action to origin.
|
||||
fields.origin = origin.release_value();
|
||||
|
@ -440,7 +440,7 @@ static ErrorOr<ActionObject, WebDriver::Error> process_pointer_action(String id,
|
|||
|
||||
// 2. If subtype is not one of the values "pause", "pointerUp", "pointerDown", "pointerMove", or "pointerCancel", return an error with error code invalid argument.
|
||||
if (!first_is_one_of(subtype, Pause, PointerUp, PointerDown, PointerMove, PointerCancel))
|
||||
return WebDriver::Error::from_code(WebDriver::ErrorCode::InvalidArgument, "Property 'type' must be one of 'pause', 'pointerUp', 'pointerDown', 'pointerMove', or 'pointerCancel'");
|
||||
return WebDriver::Error::from_code(WebDriver::ErrorCode::InvalidArgument, "Property 'type' must be one of 'pause', 'pointerUp', 'pointerDown', 'pointerMove', or 'pointerCancel'"sv);
|
||||
|
||||
// 3. Let action be an action object constructed with arguments id, "pointer", and subtype.
|
||||
ActionObject action { move(id), InputSourceType::Pointer, *subtype };
|
||||
|
@ -487,7 +487,7 @@ static ErrorOr<ActionObject, WebDriver::Error> process_wheel_action(String id, J
|
|||
|
||||
// 2. If subtype is not the value "pause", or "scroll", return an error with error code invalid argument.
|
||||
if (!first_is_one_of(subtype, Pause, Scroll))
|
||||
return WebDriver::Error::from_code(WebDriver::ErrorCode::InvalidArgument, "Property 'type' must be one of 'pause' or 'scroll'");
|
||||
return WebDriver::Error::from_code(WebDriver::ErrorCode::InvalidArgument, "Property 'type' must be one of 'pause' or 'scroll'"sv);
|
||||
|
||||
// 3. Let action be an action object constructed with arguments id, "wheel", and subtype.
|
||||
ActionObject action { move(id), InputSourceType::Wheel, *subtype };
|
||||
|
@ -514,7 +514,7 @@ static ErrorOr<ActionObject, WebDriver::Error> process_wheel_action(String id, J
|
|||
// 10. If origin is not equal to "viewport", or actions options' is element origin steps given origin return false,
|
||||
// return error with error code invalid argument.
|
||||
if (!origin.has_value() || origin == ActionObject::OriginType::Pointer)
|
||||
return WebDriver::Error::from_code(WebDriver::ErrorCode::InvalidArgument, "Property 'origin' must be 'viewport' or an element origin");
|
||||
return WebDriver::Error::from_code(WebDriver::ErrorCode::InvalidArgument, "Property 'origin' must be 'viewport' or an element origin"sv);
|
||||
|
||||
// 11. Set the origin property of action to origin.
|
||||
fields.origin = origin.release_value();
|
||||
|
@ -551,11 +551,11 @@ static ErrorOr<Vector<ActionObject>, WebDriver::Error> process_input_source_acti
|
|||
|
||||
// 2. If type is not "key", "pointer", "wheel", or "none", return an error with error code invalid argument.
|
||||
if (!type.has_value())
|
||||
return WebDriver::Error::from_code(WebDriver::ErrorCode::InvalidArgument, "Property 'type' must be one of 'key', 'pointer', 'wheel', or 'none'");
|
||||
return WebDriver::Error::from_code(WebDriver::ErrorCode::InvalidArgument, "Property 'type' must be one of 'key', 'pointer', 'wheel', or 'none'"sv);
|
||||
|
||||
// 3. Let id be the result of getting the property "id" from action sequence.
|
||||
// 4. If id is undefined or is not a String, return error with error code invalid argument.
|
||||
auto const id = MUST(String::from_byte_string(TRY(get_property(action_sequence, "id"sv))));
|
||||
auto const id = TRY(get_property(action_sequence, "id"sv));
|
||||
|
||||
// 5. If type is equal to "pointer", let parameters data be the result of getting the property "parameters" from
|
||||
// action sequence. Then let parameters be the result of trying to process pointer parameters with argument
|
||||
|
@ -575,7 +575,7 @@ static ErrorOr<Vector<ActionObject>, WebDriver::Error> process_input_source_acti
|
|||
// return an error with error code invalid argument.
|
||||
if (auto const* pointer_input_source = source.get_pointer<PointerInputSource>(); pointer_input_source && parameters.has_value()) {
|
||||
if (parameters->pointer_type != pointer_input_source->subtype)
|
||||
return WebDriver::Error::from_code(WebDriver::ErrorCode::InvalidArgument, "Invalid 'pointerType' property");
|
||||
return WebDriver::Error::from_code(WebDriver::ErrorCode::InvalidArgument, "Invalid 'pointerType' property"sv);
|
||||
}
|
||||
|
||||
// 8. Let action items be the result of getting a property named "actions" from action sequence.
|
||||
|
@ -589,7 +589,7 @@ static ErrorOr<Vector<ActionObject>, WebDriver::Error> process_input_source_acti
|
|||
TRY(action_items.try_for_each([&](auto const& action_item) -> ErrorOr<void, WebDriver::Error> {
|
||||
// 1. If action item is not an Object return error with error code invalid argument.
|
||||
if (!action_item.is_object())
|
||||
return WebDriver::Error::from_code(WebDriver::ErrorCode::InvalidArgument, "Property 'actions' item is not an Object");
|
||||
return WebDriver::Error::from_code(WebDriver::ErrorCode::InvalidArgument, "Property 'actions' item is not an Object"sv);
|
||||
|
||||
auto action = TRY([&]() {
|
||||
switch (*type) {
|
||||
|
@ -1240,11 +1240,11 @@ static ErrorOr<void, WebDriver::Error> dispatch_pointer_move_action(ActionObject
|
|||
|
||||
// 5. If x is less than 0 or greater than the width of the viewport in CSS pixels, then return error with error code move target out of bounds.
|
||||
if (coordinates.x() < 0 || coordinates.x() > viewport.width())
|
||||
return WebDriver::Error::from_code(WebDriver::ErrorCode::MoveTargetOutOfBounds, ByteString::formatted("Coordinates {} are out of bounds", coordinates));
|
||||
return WebDriver::Error::from_code(WebDriver::ErrorCode::MoveTargetOutOfBounds, MUST(String::formatted("Coordinates {} are out of bounds", coordinates)));
|
||||
|
||||
// 6. If y is less than 0 or greater than the height of the viewport in CSS pixels, then return error with error code move target out of bounds.
|
||||
if (coordinates.y() < 0 || coordinates.y() > viewport.height())
|
||||
return WebDriver::Error::from_code(WebDriver::ErrorCode::MoveTargetOutOfBounds, ByteString::formatted("Coordinates {} are out of bounds", coordinates));
|
||||
return WebDriver::Error::from_code(WebDriver::ErrorCode::MoveTargetOutOfBounds, MUST(String::formatted("Coordinates {} are out of bounds", coordinates)));
|
||||
|
||||
// 7. Let duration be equal to action object's duration property if it is not undefined, or tick duration otherwise.
|
||||
[[maybe_unused]] auto duration = action_object.duration.value_or(tick_duration);
|
||||
|
|
|
@ -91,7 +91,7 @@ static ErrorOr<JsonObject, Error> validate_capabilities(JsonValue const& capabil
|
|||
else if (name.is_one_of("browserName"sv, "browserVersion"sv, "platformName"sv)) {
|
||||
// If value is not a string return an error with error code invalid argument. Otherwise, let deserialized be set to value.
|
||||
if (!value.is_string())
|
||||
return Error::from_code(ErrorCode::InvalidArgument, ByteString::formatted("Capability {} must be a string", name));
|
||||
return Error::from_code(ErrorCode::InvalidArgument, MUST(String::formatted("Capability {} must be a string", name)));
|
||||
deserialized = value;
|
||||
}
|
||||
|
||||
|
@ -152,7 +152,7 @@ static ErrorOr<JsonObject, Error> validate_capabilities(JsonValue const& capabil
|
|||
// -> The remote end is an endpoint node
|
||||
else {
|
||||
// Return an error with error code invalid argument.
|
||||
return Error::from_code(ErrorCode::InvalidArgument, ByteString::formatted("Unrecognized capability: {}", name));
|
||||
return Error::from_code(ErrorCode::InvalidArgument, MUST(String::formatted("Unrecognized capability: {}", name)));
|
||||
}
|
||||
|
||||
// d. If deserialized is not null, set a property on result with name name and value deserialized.
|
||||
|
@ -195,7 +195,7 @@ static ErrorOr<JsonObject, Error> merge_capabilities(JsonObject const& primary,
|
|||
|
||||
// d. If primary value is not undefined, return an error with error code invalid argument.
|
||||
if (primary_value.has_value())
|
||||
return Error::from_code(ErrorCode::InvalidArgument, ByteString::formatted("Unable to merge capability {}", name));
|
||||
return Error::from_code(ErrorCode::InvalidArgument, MUST(String::formatted("Unable to merge capability {}", name)));
|
||||
|
||||
// e. Set a property on result with name name and value value.
|
||||
result.set(name, value);
|
||||
|
@ -290,13 +290,13 @@ static JsonValue match_capabilities(JsonObject const& capabilities, SessionFlags
|
|||
else if (name == "browserVersion"sv) {
|
||||
// Compare value to the "browserVersion" entry in matched capabilities using an implementation-defined comparison algorithm. The comparison is to accept a value that places constraints on the version using the "<", "<=", ">", and ">=" operators.
|
||||
// If the two values do not match, return success with data null.
|
||||
if (!matches_browser_version(value.as_string(), matched_capabilities.get_byte_string(name).value()))
|
||||
if (!matches_browser_version(value.as_string(), matched_capabilities.get_string(name).value()))
|
||||
return AK::Error::from_string_literal("browserVersion");
|
||||
}
|
||||
// -> "platformName"
|
||||
else if (name == "platformName"sv) {
|
||||
// If value is not a string equal to the "platformName" entry in matched capabilities, return success with data null.
|
||||
if (!matches_platform_name(value.as_string(), matched_capabilities.get_byte_string(name).value()))
|
||||
if (!matches_platform_name(value.as_string(), matched_capabilities.get_string(name).value()))
|
||||
return AK::Error::from_string_literal("platformName");
|
||||
}
|
||||
// -> "acceptInsecureCerts"
|
||||
|
|
|
@ -167,7 +167,7 @@ static ErrorOr<MatchedRoute, Error> match_route(HTTP::HttpRequest const& request
|
|||
}
|
||||
}
|
||||
|
||||
return Error::from_code(ErrorCode::UnknownCommand, "The command was not recognized.");
|
||||
return Error::from_code(ErrorCode::UnknownCommand, "The command was not recognized."sv);
|
||||
}
|
||||
|
||||
static JsonValue make_success_response(JsonValue value)
|
||||
|
@ -329,8 +329,8 @@ ErrorOr<void, Client::WrappedError> Client::send_error_response(HTTP::HttpReques
|
|||
auto reason = HTTP::HttpResponse::reason_phrase_for_code(error.http_status);
|
||||
|
||||
JsonObject error_response;
|
||||
error_response.set("error"sv, MUST(String::from_byte_string(error.error)));
|
||||
error_response.set("message"sv, MUST(String::from_byte_string(error.message)));
|
||||
error_response.set("error"sv, error.error);
|
||||
error_response.set("message"sv, error.message);
|
||||
error_response.set("stacktrace"sv, ""sv);
|
||||
if (error.data.has_value())
|
||||
error_response.set("data"sv, *error.data);
|
||||
|
|
|
@ -14,10 +14,10 @@
|
|||
namespace Web::WebDriver {
|
||||
|
||||
// https://w3c.github.io/webdriver/#dfn-web-window-identifier
|
||||
static ByteString const WEB_WINDOW_IDENTIFIER = "window-fcc6-11e5-b4f8-330a88ab9d7f"sv;
|
||||
static JS::PropertyKey const WEB_WINDOW_IDENTIFIER { "window-fcc6-11e5-b4f8-330a88ab9d7f" };
|
||||
|
||||
// https://w3c.github.io/webdriver/#dfn-web-frame-identifier
|
||||
static ByteString const WEB_FRAME_IDENTIFIER = "frame-075b-4da1-b6ba-e579c2d3230a"sv;
|
||||
static JS::PropertyKey const WEB_FRAME_IDENTIFIER { "frame-075b-4da1-b6ba-e579c2d3230a" };
|
||||
|
||||
// https://w3c.github.io/webdriver/#dfn-windowproxy-reference-object
|
||||
JsonObject window_proxy_reference_object(HTML::WindowProxy const& window)
|
||||
|
@ -30,7 +30,7 @@ JsonObject window_proxy_reference_object(HTML::WindowProxy const& window)
|
|||
// Ref: https://html.spec.whatwg.org/multipage/document-sequences.html#bc-traversable
|
||||
auto navigable = window.associated_browsing_context()->active_document()->navigable();
|
||||
|
||||
auto identifier = navigable->is_top_level_traversable()
|
||||
auto const& identifier = navigable->is_top_level_traversable()
|
||||
? WEB_WINDOW_IDENTIFIER
|
||||
: WEB_FRAME_IDENTIFIER;
|
||||
|
||||
|
@ -39,7 +39,7 @@ JsonObject window_proxy_reference_object(HTML::WindowProxy const& window)
|
|||
|
||||
// identifier
|
||||
// Associated window handle of the window’s browsing context.
|
||||
object.set(identifier, navigable->traversable_navigable()->window_handle());
|
||||
object.set(identifier.as_string(), navigable->traversable_navigable()->window_handle());
|
||||
|
||||
return object;
|
||||
}
|
||||
|
@ -64,7 +64,7 @@ bool represents_a_web_frame(JS::Value value)
|
|||
if (!value.is_object())
|
||||
return false;
|
||||
|
||||
auto result = value.as_object().has_own_property(WEB_FRAME_IDENTIFIER);
|
||||
auto result = value.as_object().has_own_property(WEB_WINDOW_IDENTIFIER);
|
||||
return !result.is_error() && result.value();
|
||||
}
|
||||
|
||||
|
|
|
@ -25,16 +25,18 @@
|
|||
namespace Web::WebDriver {
|
||||
|
||||
// https://w3c.github.io/webdriver/#dfn-web-element-identifier
|
||||
static ByteString const web_element_identifier = "element-6066-11e4-a52e-4f735466cecf"sv;
|
||||
static String const web_element_identifier = "element-6066-11e4-a52e-4f735466cecf"_string;
|
||||
static JS::PropertyKey web_element_identifier_key { web_element_identifier.to_byte_string() };
|
||||
|
||||
// https://w3c.github.io/webdriver/#dfn-shadow-root-identifier
|
||||
static ByteString const shadow_root_identifier = "shadow-6066-11e4-a52e-4f735466cecf"sv;
|
||||
static String const shadow_root_identifier = "shadow-6066-11e4-a52e-4f735466cecf"_string;
|
||||
static JS::PropertyKey shadow_root_identifier_key { shadow_root_identifier.to_byte_string() };
|
||||
|
||||
// https://w3c.github.io/webdriver/#dfn-browsing-context-group-node-map
|
||||
static HashMap<GC::RawPtr<HTML::BrowsingContextGroup const>, HashTable<ByteString>> browsing_context_group_node_map;
|
||||
static HashMap<GC::RawPtr<HTML::BrowsingContextGroup const>, HashTable<String>> browsing_context_group_node_map;
|
||||
|
||||
// https://w3c.github.io/webdriver/#dfn-navigable-seen-nodes-map
|
||||
static HashMap<GC::RawPtr<HTML::Navigable>, HashTable<ByteString>> navigable_seen_nodes_map;
|
||||
static HashMap<GC::RawPtr<HTML::Navigable>, HashTable<String>> navigable_seen_nodes_map;
|
||||
|
||||
// https://w3c.github.io/webdriver/#dfn-get-a-node
|
||||
GC::Ptr<Web::DOM::Node> get_node(HTML::BrowsingContext const& browsing_context, StringView reference)
|
||||
|
@ -62,7 +64,7 @@ GC::Ptr<Web::DOM::Node> get_node(HTML::BrowsingContext const& browsing_context,
|
|||
}
|
||||
|
||||
// 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)
|
||||
String 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.
|
||||
|
@ -73,7 +75,7 @@ ByteString get_or_create_a_node_reference(HTML::BrowsingContext const& browsing_
|
|||
// 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());
|
||||
auto node_id = String::number(node.unique_id().value());
|
||||
|
||||
// 5. If node id map does not contain node:
|
||||
if (!node_id_map.contains(node_id)) {
|
||||
|
@ -111,7 +113,7 @@ bool node_reference_is_known(HTML::BrowsingContext const& browsing_context, Stri
|
|||
}
|
||||
|
||||
// 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)
|
||||
String 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());
|
||||
|
@ -132,7 +134,7 @@ JsonObject web_element_reference_object(HTML::BrowsingContext const& browsing_co
|
|||
|
||||
// 3. Return a JSON Object initialized with a property with name identifier and value reference.
|
||||
JsonObject object;
|
||||
object.set(identifier, MUST(String::from_byte_string(reference)));
|
||||
object.set(identifier, move(reference));
|
||||
return object;
|
||||
}
|
||||
|
||||
|
@ -153,7 +155,7 @@ bool represents_a_web_element(JS::Value value)
|
|||
if (!value.is_object())
|
||||
return false;
|
||||
|
||||
auto result = value.as_object().has_own_property(web_element_identifier);
|
||||
auto result = value.as_object().has_own_property(web_element_identifier_key);
|
||||
return !result.is_error() && result.value();
|
||||
}
|
||||
|
||||
|
@ -162,7 +164,7 @@ ErrorOr<GC::Ref<Web::DOM::Element>, WebDriver::Error> deserialize_web_element(We
|
|||
{
|
||||
// 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");
|
||||
return WebDriver::Error::from_code(WebDriver::ErrorCode::InvalidArgument, "Object is not a web element"sv);
|
||||
|
||||
// 2. Let reference be the result of getting the web element identifier property from object.
|
||||
auto reference = extract_web_element_reference(object);
|
||||
|
@ -178,9 +180,9 @@ ErrorOr<GC::Ref<Web::DOM::Element>, WebDriver::Error> deserialize_web_element(We
|
|||
ErrorOr<GC::Ref<Web::DOM::Element>, 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);
|
||||
auto property = object.get(web_element_identifier_key);
|
||||
if (property.is_error() || !property.value().is_string())
|
||||
return WebDriver::Error::from_code(WebDriver::ErrorCode::InvalidArgument, "Object is not a web element");
|
||||
return WebDriver::Error::from_code(WebDriver::ErrorCode::InvalidArgument, "Object is not a web element"sv);
|
||||
|
||||
// 2. Let reference be the result of getting the web element identifier property from object.
|
||||
auto reference = property.value().as_string().utf8_string();
|
||||
|
@ -192,9 +194,9 @@ ErrorOr<GC::Ref<Web::DOM::Element>, WebDriver::Error> deserialize_web_element(We
|
|||
return element;
|
||||
}
|
||||
|
||||
ByteString extract_web_element_reference(JsonObject const& object)
|
||||
String extract_web_element_reference(JsonObject const& object)
|
||||
{
|
||||
return object.get_byte_string(web_element_identifier).release_value();
|
||||
return object.get_string(web_element_identifier).release_value();
|
||||
}
|
||||
|
||||
// https://w3c.github.io/webdriver/#dfn-get-a-webelement-origin
|
||||
|
@ -215,18 +217,18 @@ ErrorOr<GC::Ref<Web::DOM::Element>, Web::WebDriver::Error> get_known_element(Web
|
|||
// 1. If not node reference is known with session, session's current browsing context, and reference return error
|
||||
// with error code no such element.
|
||||
if (!node_reference_is_known(browsing_context, reference))
|
||||
return Web::WebDriver::Error::from_code(Web::WebDriver::ErrorCode::NoSuchElement, ByteString::formatted("Element reference '{}' is not known", reference));
|
||||
return Web::WebDriver::Error::from_code(Web::WebDriver::ErrorCode::NoSuchElement, MUST(String::formatted("Element reference '{}' is not known", reference)));
|
||||
|
||||
// 2. Let node be the result of get a node with session, session's current browsing context, and reference.
|
||||
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 reference '{}'", reference));
|
||||
return Web::WebDriver::Error::from_code(Web::WebDriver::ErrorCode::NoSuchElement, MUST(String::formatted("Could not find element with 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 reference '{}' is stale", reference));
|
||||
return Web::WebDriver::Error::from_code(Web::WebDriver::ErrorCode::StaleElementReference, MUST(String::formatted("Element reference '{}' is stale", reference)));
|
||||
|
||||
// 5. Return success with data node.
|
||||
return static_cast<Web::DOM::Element&>(*node);
|
||||
|
@ -403,7 +405,7 @@ GC::RootVector<GC::Ref<Web::DOM::Element>> pointer_interactable_tree(Web::HTML::
|
|||
}
|
||||
|
||||
// https://w3c.github.io/webdriver/#dfn-get-or-create-a-shadow-root-reference
|
||||
ByteString get_or_create_a_shadow_root_reference(HTML::BrowsingContext const& browsing_context, Web::DOM::ShadowRoot const& shadow_root)
|
||||
String get_or_create_a_shadow_root_reference(HTML::BrowsingContext const& browsing_context, Web::DOM::ShadowRoot const& shadow_root)
|
||||
{
|
||||
// 1. Assert: element implements ShadowRoot.
|
||||
// 2. Return the result of trying to get or create a node reference with session, session's current browsing context,
|
||||
|
@ -422,7 +424,7 @@ JsonObject shadow_root_reference_object(HTML::BrowsingContext const& browsing_co
|
|||
|
||||
// 3. Return a JSON Object initialized with a property with name identifier and value reference.
|
||||
JsonObject object;
|
||||
object.set(identifier, MUST(String::from_byte_string(reference)));
|
||||
object.set(identifier, move(reference));
|
||||
return object;
|
||||
}
|
||||
|
||||
|
@ -443,7 +445,7 @@ bool represents_a_shadow_root(JS::Value value)
|
|||
if (!value.is_object())
|
||||
return false;
|
||||
|
||||
auto result = value.as_object().has_own_property(shadow_root_identifier);
|
||||
auto result = value.as_object().has_own_property(shadow_root_identifier_key);
|
||||
return !result.is_error() && result.value();
|
||||
}
|
||||
|
||||
|
@ -452,10 +454,10 @@ ErrorOr<GC::Ref<Web::DOM::ShadowRoot>, WebDriver::Error> deserialize_shadow_root
|
|||
{
|
||||
// 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");
|
||||
return WebDriver::Error::from_code(WebDriver::ErrorCode::InvalidArgument, "Object is not a Shadow Root"sv);
|
||||
|
||||
// 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();
|
||||
auto const& reference = object.get_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));
|
||||
|
@ -468,9 +470,9 @@ ErrorOr<GC::Ref<Web::DOM::ShadowRoot>, WebDriver::Error> deserialize_shadow_root
|
|||
ErrorOr<GC::Ref<Web::DOM::ShadowRoot>, 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);
|
||||
auto property = object.get(shadow_root_identifier_key);
|
||||
if (property.is_error() || !property.value().is_string())
|
||||
return WebDriver::Error::from_code(WebDriver::ErrorCode::InvalidArgument, "Object is not a Shadow Root");
|
||||
return WebDriver::Error::from_code(WebDriver::ErrorCode::InvalidArgument, "Object is not a Shadow Root"sv);
|
||||
|
||||
// 2. Let reference be the result of getting the shadow root identifier property from object.
|
||||
auto reference = property.value().as_string().utf8_string();
|
||||
|
@ -487,18 +489,18 @@ ErrorOr<GC::Ref<Web::DOM::ShadowRoot>, Web::WebDriver::Error> get_known_shadow_r
|
|||
{
|
||||
// 1. If not node reference is known with session, session's current browsing context, and reference return error with error code no such shadow root.
|
||||
if (!node_reference_is_known(browsing_context, reference))
|
||||
return Web::WebDriver::Error::from_code(Web::WebDriver::ErrorCode::NoSuchShadowRoot, ByteString::formatted("Shadow root reference '{}' is not known", reference));
|
||||
return Web::WebDriver::Error::from_code(Web::WebDriver::ErrorCode::NoSuchShadowRoot, MUST(String::formatted("Shadow root reference '{}' is not known", reference)));
|
||||
|
||||
// 2. Let node be the result of get a node with session, session's current browsing context, and reference.
|
||||
auto node = get_node(browsing_context, reference);
|
||||
|
||||
// 3. If node is not null and node does not implement ShadowRoot return error with error code no such shadow root.
|
||||
if (node && !node->is_shadow_root())
|
||||
return Web::WebDriver::Error::from_code(Web::WebDriver::ErrorCode::NoSuchShadowRoot, ByteString::formatted("Could not find shadow root with reference '{}'", reference));
|
||||
return Web::WebDriver::Error::from_code(Web::WebDriver::ErrorCode::NoSuchShadowRoot, MUST(String::formatted("Could not find shadow root with reference '{}'", reference)));
|
||||
|
||||
// 4. If node is null or node is detached return error with error code detached shadow root.
|
||||
if (!node || is_shadow_root_detached(static_cast<Web::DOM::ShadowRoot&>(*node)))
|
||||
return Web::WebDriver::Error::from_code(Web::WebDriver::ErrorCode::DetachedShadowRoot, ByteString::formatted("Element reference '{}' is stale", reference));
|
||||
return Web::WebDriver::Error::from_code(Web::WebDriver::ErrorCode::DetachedShadowRoot, MUST(String::formatted("Element reference '{}' is stale", reference)));
|
||||
|
||||
// 5. Return success with data node.
|
||||
return static_cast<Web::DOM::ShadowRoot&>(*node);
|
||||
|
|
|
@ -6,9 +6,9 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <AK/ByteString.h>
|
||||
#include <AK/Error.h>
|
||||
#include <AK/JsonObject.h>
|
||||
#include <AK/String.h>
|
||||
#include <LibGC/Ptr.h>
|
||||
#include <LibJS/Forward.h>
|
||||
#include <LibJS/Runtime/Value.h>
|
||||
|
@ -19,16 +19,16 @@
|
|||
namespace Web::WebDriver {
|
||||
|
||||
GC::Ptr<Web::DOM::Node> get_node(HTML::BrowsingContext const&, StringView reference);
|
||||
ByteString get_or_create_a_node_reference(HTML::BrowsingContext const&, Web::DOM::Node const&);
|
||||
String 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);
|
||||
String 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<GC::Ref<Web::DOM::Element>, WebDriver::Error> deserialize_web_element(Web::HTML::BrowsingContext const&, JsonObject const&);
|
||||
ErrorOr<GC::Ref<Web::DOM::Element>, WebDriver::Error> deserialize_web_element(Web::HTML::BrowsingContext const&, JS::Object const&);
|
||||
ByteString extract_web_element_reference(JsonObject const&);
|
||||
String extract_web_element_reference(JsonObject const&);
|
||||
ErrorOr<GC::Ref<Web::DOM::Element>, Web::WebDriver::Error> get_web_element_origin(Web::HTML::BrowsingContext const&, StringView origin);
|
||||
ErrorOr<GC::Ref<Web::DOM::Element>, Web::WebDriver::Error> get_known_element(Web::HTML::BrowsingContext const&, StringView reference);
|
||||
|
||||
|
@ -46,7 +46,7 @@ bool is_element_in_view(ReadonlySpan<GC::Ref<Web::DOM::Element>> paint_tree, Web
|
|||
bool is_element_obscured(ReadonlySpan<GC::Ref<Web::DOM::Element>> paint_tree, Web::DOM::Element&);
|
||||
GC::RootVector<GC::Ref<Web::DOM::Element>> pointer_interactable_tree(Web::HTML::BrowsingContext&, Web::DOM::Element&);
|
||||
|
||||
ByteString get_or_create_a_shadow_root_reference(HTML::BrowsingContext const&, Web::DOM::ShadowRoot const&);
|
||||
String 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);
|
||||
|
|
|
@ -13,43 +13,43 @@ namespace Web::WebDriver {
|
|||
struct ErrorCodeData {
|
||||
ErrorCode error_code;
|
||||
unsigned http_status;
|
||||
ByteString json_error_code;
|
||||
String json_error_code;
|
||||
};
|
||||
|
||||
// https://w3c.github.io/webdriver/#dfn-error-code
|
||||
static Vector<ErrorCodeData> const s_error_code_data = {
|
||||
{ ErrorCode::ElementClickIntercepted, 400, "element click intercepted" },
|
||||
{ ErrorCode::ElementNotInteractable, 400, "element not interactable" },
|
||||
{ ErrorCode::InsecureCertificate, 400, "insecure certificate" },
|
||||
{ ErrorCode::InvalidArgument, 400, "invalid argument" },
|
||||
{ ErrorCode::InvalidCookieDomain, 400, "invalid cookie domain" },
|
||||
{ ErrorCode::InvalidElementState, 400, "invalid element state" },
|
||||
{ ErrorCode::InvalidSelector, 400, "invalid selector" },
|
||||
{ ErrorCode::InvalidSessionId, 404, "invalid session id" },
|
||||
{ ErrorCode::JavascriptError, 500, "javascript error" },
|
||||
{ ErrorCode::MoveTargetOutOfBounds, 500, "move target out of bounds" },
|
||||
{ ErrorCode::NoSuchAlert, 404, "no such alert" },
|
||||
{ ErrorCode::NoSuchCookie, 404, "no such cookie" },
|
||||
{ ErrorCode::NoSuchElement, 404, "no such element" },
|
||||
{ ErrorCode::NoSuchFrame, 404, "no such frame" },
|
||||
{ ErrorCode::NoSuchWindow, 404, "no such window" },
|
||||
{ ErrorCode::NoSuchShadowRoot, 404, "no such shadow root" },
|
||||
{ ErrorCode::ScriptTimeoutError, 500, "script timeout" },
|
||||
{ ErrorCode::SessionNotCreated, 500, "session not created" },
|
||||
{ ErrorCode::StaleElementReference, 404, "stale element reference" },
|
||||
{ ErrorCode::DetachedShadowRoot, 404, "detached shadow root" },
|
||||
{ ErrorCode::Timeout, 500, "timeout" },
|
||||
{ ErrorCode::UnableToSetCookie, 500, "unable to set cookie" },
|
||||
{ ErrorCode::UnableToCaptureScreen, 500, "unable to capture screen" },
|
||||
{ ErrorCode::UnexpectedAlertOpen, 500, "unexpected alert open" },
|
||||
{ ErrorCode::UnknownCommand, 404, "unknown command" },
|
||||
{ ErrorCode::UnknownError, 500, "unknown error" },
|
||||
{ ErrorCode::UnknownMethod, 405, "unknown method" },
|
||||
{ ErrorCode::UnsupportedOperation, 500, "unsupported operation" },
|
||||
{ ErrorCode::OutOfMemory, 500, "out of memory" },
|
||||
{ ErrorCode::ElementClickIntercepted, 400, "element click intercepted"_string },
|
||||
{ ErrorCode::ElementNotInteractable, 400, "element not interactable"_string },
|
||||
{ ErrorCode::InsecureCertificate, 400, "insecure certificate"_string },
|
||||
{ ErrorCode::InvalidArgument, 400, "invalid argument"_string },
|
||||
{ ErrorCode::InvalidCookieDomain, 400, "invalid cookie domain"_string },
|
||||
{ ErrorCode::InvalidElementState, 400, "invalid element state"_string },
|
||||
{ ErrorCode::InvalidSelector, 400, "invalid selector"_string },
|
||||
{ ErrorCode::InvalidSessionId, 404, "invalid session id"_string },
|
||||
{ ErrorCode::JavascriptError, 500, "javascript error"_string },
|
||||
{ ErrorCode::MoveTargetOutOfBounds, 500, "move target out of bounds"_string },
|
||||
{ ErrorCode::NoSuchAlert, 404, "no such alert"_string },
|
||||
{ ErrorCode::NoSuchCookie, 404, "no such cookie"_string },
|
||||
{ ErrorCode::NoSuchElement, 404, "no such element"_string },
|
||||
{ ErrorCode::NoSuchFrame, 404, "no such frame"_string },
|
||||
{ ErrorCode::NoSuchWindow, 404, "no such window"_string },
|
||||
{ ErrorCode::NoSuchShadowRoot, 404, "no such shadow root"_string },
|
||||
{ ErrorCode::ScriptTimeoutError, 500, "script timeout"_string },
|
||||
{ ErrorCode::SessionNotCreated, 500, "session not created"_string },
|
||||
{ ErrorCode::StaleElementReference, 404, "stale element reference"_string },
|
||||
{ ErrorCode::DetachedShadowRoot, 404, "detached shadow root"_string },
|
||||
{ ErrorCode::Timeout, 500, "timeout"_string },
|
||||
{ ErrorCode::UnableToSetCookie, 500, "unable to set cookie"_string },
|
||||
{ ErrorCode::UnableToCaptureScreen, 500, "unable to capture screen"_string },
|
||||
{ ErrorCode::UnexpectedAlertOpen, 500, "unexpected alert open"_string },
|
||||
{ ErrorCode::UnknownCommand, 404, "unknown command"_string },
|
||||
{ ErrorCode::UnknownError, 500, "unknown error"_string },
|
||||
{ ErrorCode::UnknownMethod, 405, "unknown method"_string },
|
||||
{ ErrorCode::UnsupportedOperation, 500, "unsupported operation"_string },
|
||||
{ ErrorCode::OutOfMemory, 500, "out of memory"_string },
|
||||
};
|
||||
|
||||
Error Error::from_code(ErrorCode code, ByteString message, Optional<JsonValue> data)
|
||||
Error Error::from_code(ErrorCode code, String message, Optional<JsonValue> data)
|
||||
{
|
||||
auto const& error_code_data = s_error_code_data[to_underlying(code)];
|
||||
|
||||
|
@ -61,13 +61,18 @@ Error Error::from_code(ErrorCode code, ByteString message, Optional<JsonValue> d
|
|||
};
|
||||
}
|
||||
|
||||
Error Error::from_code(ErrorCode code, StringView message, Optional<JsonValue> data)
|
||||
{
|
||||
return from_code(code, String::from_utf8_without_validation(message.bytes()), move(data));
|
||||
}
|
||||
|
||||
Error::Error(AK::Error const& error)
|
||||
{
|
||||
VERIFY(error.code() == ENOMEM);
|
||||
*this = from_code(ErrorCode::OutOfMemory, {}, {});
|
||||
*this = from_code(ErrorCode::OutOfMemory, String {}, {});
|
||||
}
|
||||
|
||||
Error::Error(unsigned http_status_, ByteString error_, ByteString message_, Optional<JsonValue> data_)
|
||||
Error::Error(unsigned http_status_, String error_, String message_, Optional<JsonValue> data_)
|
||||
: http_status(http_status_)
|
||||
, error(move(error_))
|
||||
, message(move(message_))
|
||||
|
|
|
@ -7,8 +7,8 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <AK/ByteString.h>
|
||||
#include <AK/JsonValue.h>
|
||||
#include <AK/String.h>
|
||||
|
||||
namespace Web::WebDriver {
|
||||
|
||||
|
@ -50,13 +50,14 @@ enum class ErrorCode {
|
|||
// https://w3c.github.io/webdriver/#errors
|
||||
struct Error {
|
||||
unsigned http_status;
|
||||
ByteString error;
|
||||
ByteString message;
|
||||
String error;
|
||||
String message;
|
||||
Optional<JsonValue> data;
|
||||
|
||||
static Error from_code(ErrorCode, ByteString message, Optional<JsonValue> data = {});
|
||||
static Error from_code(ErrorCode, String message, Optional<JsonValue> data = {});
|
||||
static Error from_code(ErrorCode, StringView message, Optional<JsonValue> data = {});
|
||||
|
||||
Error(unsigned http_status, ByteString error, ByteString message, Optional<JsonValue> data);
|
||||
Error(unsigned http_status, String error, String message, Optional<JsonValue> data);
|
||||
Error(AK::Error const&);
|
||||
};
|
||||
|
||||
|
@ -66,6 +67,6 @@ template<>
|
|||
struct AK::Formatter<Web::WebDriver::Error> : Formatter<StringView> {
|
||||
ErrorOr<void> format(FormatBuilder& builder, Web::WebDriver::Error const& error)
|
||||
{
|
||||
return Formatter<StringView>::format(builder, ByteString::formatted("Error {}, {}: {}", error.http_status, error.error, error.message));
|
||||
return Formatter<StringView>::format(builder, MUST(String::formatted("Error {}, {}: {}", error.http_status, error.error, error.message)));
|
||||
}
|
||||
};
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
namespace Web::WebDriver {
|
||||
|
||||
// https://w3c.github.io/webdriver/#dfn-execute-a-function-body
|
||||
static JS::ThrowCompletionOr<JS::Value> execute_a_function_body(HTML::BrowsingContext const& browsing_context, ByteString const& body, ReadonlySpan<JS::Value> parameters)
|
||||
static JS::ThrowCompletionOr<JS::Value> execute_a_function_body(HTML::BrowsingContext const& browsing_context, StringView body, ReadonlySpan<JS::Value> parameters)
|
||||
{
|
||||
// 1. Let window be the associated window of the current browsing context’s active document.
|
||||
auto window = browsing_context.active_document()->window();
|
||||
|
@ -84,7 +84,7 @@ static JS::ThrowCompletionOr<JS::Value> execute_a_function_body(HTML::BrowsingCo
|
|||
return completion;
|
||||
}
|
||||
|
||||
void execute_script(HTML::BrowsingContext const& browsing_context, ByteString body, GC::RootVector<JS::Value> arguments, Optional<u64> const& timeout_ms, GC::Ref<OnScriptComplete> on_complete)
|
||||
void execute_script(HTML::BrowsingContext const& browsing_context, String body, GC::RootVector<JS::Value> arguments, Optional<u64> const& timeout_ms, GC::Ref<OnScriptComplete> on_complete)
|
||||
{
|
||||
auto const* document = browsing_context.active_document();
|
||||
auto& realm = document->realm();
|
||||
|
@ -142,7 +142,7 @@ void execute_script(HTML::BrowsingContext const& browsing_context, ByteString bo
|
|||
}
|
||||
|
||||
// https://w3c.github.io/webdriver/#execute-async-script
|
||||
void execute_async_script(HTML::BrowsingContext const& browsing_context, ByteString body, GC::RootVector<JS::Value> arguments, Optional<u64> const& timeout_ms, GC::Ref<OnScriptComplete> on_complete)
|
||||
void execute_async_script(HTML::BrowsingContext const& browsing_context, String body, GC::RootVector<JS::Value> arguments, Optional<u64> const& timeout_ms, GC::Ref<OnScriptComplete> on_complete)
|
||||
{
|
||||
auto const* document = browsing_context.active_document();
|
||||
auto& realm = document->realm();
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#pragma once
|
||||
|
||||
#include <AK/Forward.h>
|
||||
#include <AK/String.h>
|
||||
#include <LibGC/Function.h>
|
||||
#include <LibJS/Forward.h>
|
||||
#include <LibJS/Runtime/Promise.h>
|
||||
|
@ -23,7 +24,7 @@ struct ExecutionResult {
|
|||
|
||||
using OnScriptComplete = GC::Function<void(ExecutionResult)>;
|
||||
|
||||
void execute_script(HTML::BrowsingContext const&, ByteString body, GC::RootVector<JS::Value> arguments, Optional<u64> const& timeout_ms, GC::Ref<OnScriptComplete> on_complete);
|
||||
void execute_async_script(HTML::BrowsingContext const&, ByteString body, GC::RootVector<JS::Value> arguments, Optional<u64> const& timeout_ms, GC::Ref<OnScriptComplete> on_complete);
|
||||
void execute_script(HTML::BrowsingContext const&, String body, GC::RootVector<JS::Value> arguments, Optional<u64> const& timeout_ms, GC::Ref<OnScriptComplete> on_complete);
|
||||
void execute_async_script(HTML::BrowsingContext const&, String body, GC::RootVector<JS::Value> arguments, Optional<u64> const& timeout_ms, GC::Ref<OnScriptComplete> on_complete);
|
||||
|
||||
}
|
||||
|
|
|
@ -176,7 +176,7 @@ ErrorOr<InputSource*, WebDriver::Error> get_or_create_input_source(InputState& i
|
|||
// FIXME: Spec issue: It does not make sense to check if "source is a pointer input source". This would errantly
|
||||
// prevent the ability to perform two pointer actions in a row.
|
||||
// https://github.com/w3c/webdriver/issues/1810
|
||||
return WebDriver::Error::from_code(WebDriver::ErrorCode::InvalidArgument, "Property 'type' does not match existing input source type");
|
||||
return WebDriver::Error::from_code(WebDriver::ErrorCode::InvalidArgument, "Property 'type' does not match existing input source type"sv);
|
||||
}
|
||||
|
||||
// 3. If source is undefined, set source to the result of trying to create an input source with input state and type.
|
||||
|
|
|
@ -30,14 +30,14 @@
|
|||
|
||||
namespace Web::WebDriver {
|
||||
|
||||
#define TRY_OR_JS_ERROR(expression) \
|
||||
({ \
|
||||
auto&& _temporary_result = (expression); \
|
||||
if (_temporary_result.is_error()) [[unlikely]] \
|
||||
return WebDriver::Error::from_code(ErrorCode::JavascriptError, "Script returned an error"); \
|
||||
static_assert(!::AK::Detail::IsLvalueReference<decltype(_temporary_result.release_value())>, \
|
||||
"Do not return a reference from a fallible expression"); \
|
||||
_temporary_result.release_value(); \
|
||||
#define TRY_OR_JS_ERROR(expression) \
|
||||
({ \
|
||||
auto&& _temporary_result = (expression); \
|
||||
if (_temporary_result.is_error()) [[unlikely]] \
|
||||
return WebDriver::Error::from_code(ErrorCode::JavascriptError, "Script returned an error"sv); \
|
||||
static_assert(!::AK::Detail::IsLvalueReference<decltype(_temporary_result.release_value())>, \
|
||||
"Do not return a reference from a fallible expression"); \
|
||||
_temporary_result.release_value(); \
|
||||
})
|
||||
|
||||
using SeenMap = HashTable<GC::RawPtr<JS::Object const>>;
|
||||
|
@ -120,7 +120,7 @@ static ErrorOr<ResultType, WebDriver::Error> clone_an_object(HTML::BrowsingConte
|
|||
// script to be run and that script throws an error, return error with error code javascript error.
|
||||
auto source_property_value = value.get(name);
|
||||
if (source_property_value.is_error()) {
|
||||
error = WebDriver::Error::from_code(ErrorCode::JavascriptError, "Script returned an error");
|
||||
error = WebDriver::Error::from_code(ErrorCode::JavascriptError, "Script returned an error"sv);
|
||||
return JS::normal_completion({});
|
||||
}
|
||||
|
||||
|
@ -183,7 +183,7 @@ static Response internal_json_clone(HTML::BrowsingContext const& browsing_contex
|
|||
if (value.is_number())
|
||||
return JsonValue { value.as_double() };
|
||||
if (value.is_string())
|
||||
return JsonValue { value.as_string().byte_string() };
|
||||
return JsonValue { value.as_string().utf8_string() };
|
||||
|
||||
// AD-HOC: BigInt and Symbol not mentioned anywhere in the WebDriver spec, as it references ES5.
|
||||
// It assumes that all primitives are handled above, and the value is an object for the remaining steps.
|
||||
|
@ -257,7 +257,7 @@ static Response internal_json_clone(HTML::BrowsingContext const& browsing_contex
|
|||
if (!to_json_result.is_string())
|
||||
return WebDriver::Error::from_code(ErrorCode::JavascriptError, "toJSON did not return a String"sv);
|
||||
|
||||
return JsonValue { to_json_result.as_string().byte_string() };
|
||||
return JsonValue { to_json_result.as_string().utf8_string() };
|
||||
}
|
||||
|
||||
// -> Otherwise
|
||||
|
|
|
@ -6,22 +6,22 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <AK/ByteString.h>
|
||||
#include <AK/JsonArray.h>
|
||||
#include <AK/JsonObject.h>
|
||||
#include <AK/JsonValue.h>
|
||||
#include <AK/String.h>
|
||||
#include <LibJS/Runtime/Value.h>
|
||||
#include <LibWeb/WebDriver/Error.h>
|
||||
|
||||
namespace Web::WebDriver {
|
||||
|
||||
template<typename PropertyType = ByteString>
|
||||
template<typename PropertyType = String>
|
||||
static ErrorOr<PropertyType, WebDriver::Error> get_property(JsonObject const& payload, StringView key)
|
||||
{
|
||||
auto property = payload.get(key);
|
||||
|
||||
if (!property.has_value())
|
||||
return WebDriver::Error::from_code(ErrorCode::InvalidArgument, ByteString::formatted("No property called '{}' present", key));
|
||||
return WebDriver::Error::from_code(ErrorCode::InvalidArgument, MUST(String::formatted("No property called '{}' present", key)));
|
||||
|
||||
auto is_safe_number = []<typename T>(T value) {
|
||||
if constexpr (sizeof(T) >= 8) {
|
||||
|
@ -37,29 +37,29 @@ static ErrorOr<PropertyType, WebDriver::Error> get_property(JsonObject const& pa
|
|||
return true;
|
||||
};
|
||||
|
||||
if constexpr (IsSame<PropertyType, ByteString>) {
|
||||
if constexpr (IsSame<PropertyType, String>) {
|
||||
if (!property->is_string())
|
||||
return WebDriver::Error::from_code(ErrorCode::InvalidArgument, ByteString::formatted("Property '{}' is not a String", key));
|
||||
return property->as_string().to_byte_string();
|
||||
return WebDriver::Error::from_code(ErrorCode::InvalidArgument, MUST(String::formatted("Property '{}' is not a String", key)));
|
||||
return property->as_string();
|
||||
} else if constexpr (IsSame<PropertyType, bool>) {
|
||||
if (!property->is_bool())
|
||||
return WebDriver::Error::from_code(ErrorCode::InvalidArgument, ByteString::formatted("Property '{}' is not a Boolean", key));
|
||||
return WebDriver::Error::from_code(ErrorCode::InvalidArgument, MUST(String::formatted("Property '{}' is not a Boolean", key)));
|
||||
return property->as_bool();
|
||||
} else if constexpr (IsIntegral<PropertyType>) {
|
||||
if (auto maybe_number = property->get_integer<PropertyType>(); maybe_number.has_value() && is_safe_number(*maybe_number))
|
||||
return *maybe_number;
|
||||
return WebDriver::Error::from_code(ErrorCode::InvalidArgument, ByteString::formatted("Property '{}' is not an Integer", key));
|
||||
return WebDriver::Error::from_code(ErrorCode::InvalidArgument, MUST(String::formatted("Property '{}' is not an Integer", key)));
|
||||
} else if constexpr (IsSame<PropertyType, double>) {
|
||||
if (auto maybe_number = property->get_double_with_precision_loss(); maybe_number.has_value() && is_safe_number(*maybe_number))
|
||||
return *maybe_number;
|
||||
return WebDriver::Error::from_code(ErrorCode::InvalidArgument, ByteString::formatted("Property '{}' is not a Number", key));
|
||||
return WebDriver::Error::from_code(ErrorCode::InvalidArgument, MUST(String::formatted("Property '{}' is not a Number", key)));
|
||||
} else if constexpr (IsSame<PropertyType, JsonArray const*>) {
|
||||
if (!property->is_array())
|
||||
return WebDriver::Error::from_code(ErrorCode::InvalidArgument, ByteString::formatted("Property '{}' is not an Array", key));
|
||||
return WebDriver::Error::from_code(ErrorCode::InvalidArgument, MUST(String::formatted("Property '{}' is not an Array", key)));
|
||||
return &property->as_array();
|
||||
} else if constexpr (IsSame<PropertyType, JsonObject const*>) {
|
||||
if (!property->is_object())
|
||||
return WebDriver::Error::from_code(ErrorCode::InvalidArgument, ByteString::formatted("Property '{}' is not an Object", key));
|
||||
return WebDriver::Error::from_code(ErrorCode::InvalidArgument, MUST(String::formatted("Property '{}' is not an Object", key)));
|
||||
return &property->as_object();
|
||||
} else {
|
||||
static_assert(DependentFalse<PropertyType>, "get_property invoked with unknown property type");
|
||||
|
@ -67,15 +67,15 @@ static ErrorOr<PropertyType, WebDriver::Error> get_property(JsonObject const& pa
|
|||
}
|
||||
}
|
||||
|
||||
template<typename PropertyType = ByteString>
|
||||
template<typename PropertyType = String>
|
||||
static ErrorOr<PropertyType, WebDriver::Error> get_property(JsonValue const& payload, StringView key)
|
||||
{
|
||||
if (!payload.is_object())
|
||||
return WebDriver::Error::from_code(ErrorCode::InvalidArgument, "Payload is not a JSON object");
|
||||
return WebDriver::Error::from_code(ErrorCode::InvalidArgument, "Payload is not a JSON object"sv);
|
||||
return get_property<PropertyType>(payload.as_object(), key);
|
||||
}
|
||||
|
||||
template<typename PropertyType = ByteString>
|
||||
template<typename PropertyType = String>
|
||||
static ErrorOr<Optional<PropertyType>, WebDriver::Error> get_optional_property(JsonObject const& object, StringView key)
|
||||
{
|
||||
if (!object.has(key))
|
||||
|
@ -89,9 +89,9 @@ static ErrorOr<PropertyType, WebDriver::Error> get_property_with_limits(JsonObje
|
|||
auto value = TRY(get_property<PropertyType>(object, key));
|
||||
|
||||
if (min.has_value() && value < *min)
|
||||
return WebDriver::Error::from_code(WebDriver::ErrorCode::InvalidArgument, ByteString::formatted("Property '{}' must not be less than {}", key, *min));
|
||||
return WebDriver::Error::from_code(WebDriver::ErrorCode::InvalidArgument, MUST(String::formatted("Property '{}' must not be less than {}", key, *min)));
|
||||
if (max.has_value() && value > *max)
|
||||
return WebDriver::Error::from_code(WebDriver::ErrorCode::InvalidArgument, ByteString::formatted("Property '{}' must not be greater than {}", key, *max));
|
||||
return WebDriver::Error::from_code(WebDriver::ErrorCode::InvalidArgument, MUST(String::formatted("Property '{}' must not be greater than {}", key, *max)));
|
||||
|
||||
return value;
|
||||
}
|
||||
|
|
|
@ -58,8 +58,8 @@ ErrorOr<Web::WebDriver::Response> IPC::decode(Decoder& decoder)
|
|||
|
||||
case ResponseType::Error: {
|
||||
auto http_status = TRY(decoder.decode<unsigned>());
|
||||
auto error = TRY(decoder.decode<ByteString>());
|
||||
auto message = TRY(decoder.decode<ByteString>());
|
||||
auto error = TRY(decoder.decode<String>());
|
||||
auto message = TRY(decoder.decode<String>());
|
||||
auto data = TRY(decoder.decode<Optional<JsonValue>>());
|
||||
|
||||
return Web::WebDriver::Error { http_status, move(error), move(message), move(data) };
|
||||
|
|
|
@ -85,7 +85,7 @@ Response encode_canvas_element(HTML::HTMLCanvasElement& canvas)
|
|||
auto encoded_string = MUST(data_url.substring_from_byte_offset(*index + 1));
|
||||
|
||||
// 7. Return success with data encoded string.
|
||||
return JsonValue { encoded_string.to_byte_string() };
|
||||
return JsonValue { move(encoded_string) };
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -46,7 +46,7 @@ ErrorOr<void, Error> json_deserialize_as_a_timeouts_configuration_into(JsonValue
|
|||
{
|
||||
// 1. Set timeouts to the result of converting a JSON-derived JavaScript value to an Infra value with timeouts.
|
||||
if (!timeouts.is_object())
|
||||
return Error::from_code(ErrorCode::InvalidArgument, "Payload is not a JSON object");
|
||||
return Error::from_code(ErrorCode::InvalidArgument, "Payload is not a JSON object"sv);
|
||||
|
||||
// 3. For each key → value in timeouts:
|
||||
TRY(timeouts.as_object().try_for_each_member([&](auto const& key, JsonValue const& value) -> ErrorOr<void, Error> {
|
||||
|
@ -62,7 +62,7 @@ ErrorOr<void, Error> json_deserialize_as_a_timeouts_configuration_into(JsonValue
|
|||
auto duration = value.get_integer<u64>();
|
||||
|
||||
if (!duration.has_value() || *duration > JS::MAX_ARRAY_LIKE_INDEX)
|
||||
return Error::from_code(ErrorCode::InvalidArgument, "Invalid timeout value");
|
||||
return Error::from_code(ErrorCode::InvalidArgument, "Invalid timeout value"sv);
|
||||
|
||||
parsed_value = static_cast<u64>(*duration);
|
||||
}
|
||||
|
|
|
@ -71,7 +71,7 @@ static constexpr PromptType prompt_type_from_string(StringView prompt_type)
|
|||
|
||||
PromptHandlerConfiguration PromptHandlerConfiguration::deserialize(JsonValue const& configuration)
|
||||
{
|
||||
auto handler = prompt_handler_from_string(*configuration.as_object().get_byte_string("handler"sv));
|
||||
auto handler = prompt_handler_from_string(*configuration.as_object().get_string("handler"sv));
|
||||
|
||||
auto notify = *configuration.as_object().get_bool("notify"sv)
|
||||
? PromptHandlerConfiguration::Notify::Yes
|
||||
|
@ -138,7 +138,7 @@ Response deserialize_as_an_unhandled_prompt_behavior(JsonValue value)
|
|||
TRY(value.as_object().try_for_each_member([&](String const& prompt_type, JsonValue const& handler_value) -> ErrorOr<void, WebDriver::Error> {
|
||||
// 1. If is string value is false and valid prompt types does not contain prompt type return error with error code invalid argument.
|
||||
if (!is_string_value && !valid_prompt_types.contains_slow(prompt_type))
|
||||
return WebDriver::Error::from_code(ErrorCode::InvalidArgument, ByteString::formatted("'{}' is not a valid prompt type", prompt_type));
|
||||
return WebDriver::Error::from_code(ErrorCode::InvalidArgument, MUST(String::formatted("'{}' is not a valid prompt type", prompt_type)));
|
||||
|
||||
// 2. If known prompt handlers does not contain an entry with handler key handler return error with error code invalid argument.
|
||||
if (!handler_value.is_string())
|
||||
|
@ -147,7 +147,7 @@ Response deserialize_as_an_unhandled_prompt_behavior(JsonValue value)
|
|||
StringView handler = handler_value.as_string();
|
||||
|
||||
if (!known_prompt_handlers.contains_slow(handler))
|
||||
return WebDriver::Error::from_code(ErrorCode::InvalidArgument, ByteString::formatted("'{}' is not a known prompt handler", handler));
|
||||
return WebDriver::Error::from_code(ErrorCode::InvalidArgument, MUST(String::formatted("'{}' is not a known prompt handler", handler)));
|
||||
|
||||
// 3. Let notify be false.
|
||||
bool notify = false;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue