1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-31 08:08:12 +00:00

LibWeb: Port URL and URLSearchParams to new String

This commit is contained in:
Kenneth Myhra 2023-03-01 20:10:01 +01:00 committed by Linus Groh
parent 843c9d6cd7
commit 9da09e4fd3
12 changed files with 229 additions and 157 deletions

View file

@ -90,7 +90,8 @@ WebIDL::ExceptionOr<Infrastructure::BodyWithType> extract_body(JS::Realm& realm,
}, },
[&](JS::Handle<URL::URLSearchParams> const& url_search_params) -> WebIDL::ExceptionOr<void> { [&](JS::Handle<URL::URLSearchParams> const& url_search_params) -> WebIDL::ExceptionOr<void> {
// Set source to the result of running the application/x-www-form-urlencoded serializer with objects list. // Set source to the result of running the application/x-www-form-urlencoded serializer with objects list.
source = url_search_params->to_deprecated_string().to_byte_buffer(); auto search_params_bytes = TRY(url_search_params->to_string()).bytes();
source = TRY_OR_THROW_OOM(vm, ByteBuffer::copy(search_params_bytes));
// Set type to `application/x-www-form-urlencoded;charset=UTF-8`. // Set type to `application/x-www-form-urlencoded;charset=UTF-8`.
type = TRY_OR_THROW_OOM(vm, ByteBuffer::copy("application/x-www-form-urlencoded;charset=UTF-8"sv.bytes())); type = TRY_OR_THROW_OOM(vm, ByteBuffer::copy("application/x-www-form-urlencoded;charset=UTF-8"sv.bytes()));
return {}; return {};

View file

@ -32,7 +32,7 @@ HTMLButtonElement::HTMLButtonElement(DOM::Document& document, DOM::QualifiedName
case TypeAttributeState::Submit: case TypeAttributeState::Submit:
// Submit Button // Submit Button
// Submit element's form owner from element. // Submit element's form owner from element.
form()->submit_form(this); form()->submit_form(this).release_value_but_fixme_should_propagate_errors();
break; break;
case TypeAttributeState::Reset: case TypeAttributeState::Reset:
// Reset Button // Reset Button

View file

@ -47,21 +47,21 @@ void HTMLFormElement::visit_edges(Cell::Visitor& visitor)
visitor.visit(element.ptr()); visitor.visit(element.ptr());
} }
void HTMLFormElement::submit_form(JS::GCPtr<HTMLElement> submitter, bool from_submit_binding) ErrorOr<void> HTMLFormElement::submit_form(JS::GCPtr<HTMLElement> submitter, bool from_submit_binding)
{ {
if (cannot_navigate()) if (cannot_navigate())
return; return {};
if (action().is_null()) { if (action().is_null()) {
dbgln("Unsupported form action ''"); dbgln("Unsupported form action ''");
return; return {};
} }
auto effective_method = method().to_lowercase(); auto effective_method = method().to_lowercase();
if (effective_method == "dialog") { if (effective_method == "dialog") {
dbgln("Failed to submit form: Unsupported form method '{}'", method()); dbgln("Failed to submit form: Unsupported form method '{}'", method());
return; return {};
} }
if (effective_method != "get" && effective_method != "post") { if (effective_method != "get" && effective_method != "post") {
@ -70,7 +70,7 @@ void HTMLFormElement::submit_form(JS::GCPtr<HTMLElement> submitter, bool from_su
if (!from_submit_binding) { if (!from_submit_binding) {
if (m_firing_submission_events) if (m_firing_submission_events)
return; return {};
m_firing_submission_events = true; m_firing_submission_events = true;
@ -91,51 +91,56 @@ void HTMLFormElement::submit_form(JS::GCPtr<HTMLElement> submitter, bool from_su
m_firing_submission_events = false; m_firing_submission_events = false;
if (!continue_) if (!continue_)
return; return {};
// This is checked again because arbitrary JS may have run when handling submit, // This is checked again because arbitrary JS may have run when handling submit,
// which may have changed the result. // which may have changed the result.
if (cannot_navigate()) if (cannot_navigate())
return; return {};
} }
AK::URL url(document().parse_url(action())); AK::URL url(document().parse_url(action()));
if (!url.is_valid()) { if (!url.is_valid()) {
dbgln("Failed to submit form: Invalid URL: {}", action()); dbgln("Failed to submit form: Invalid URL: {}", action());
return; return {};
} }
if (url.scheme() == "file") { if (url.scheme() == "file") {
if (document().url().scheme() != "file") { if (document().url().scheme() != "file") {
dbgln("Failed to submit form: Security violation: {} may not submit to {}", document().url(), url); dbgln("Failed to submit form: Security violation: {} may not submit to {}", document().url(), url);
return; return {};
} }
if (effective_method != "get") { if (effective_method != "get") {
dbgln("Failed to submit form: Unsupported form method '{}' for URL: {}", method(), url); dbgln("Failed to submit form: Unsupported form method '{}' for URL: {}", method(), url);
return; return {};
} }
} else if (url.scheme() != "http" && url.scheme() != "https") { } else if (url.scheme() != "http" && url.scheme() != "https") {
dbgln("Failed to submit form: Unsupported protocol for URL: {}", url); dbgln("Failed to submit form: Unsupported protocol for URL: {}", url);
return; return {};
} }
Vector<URL::QueryParam> parameters; Vector<URL::QueryParam> parameters;
for_each_in_inclusive_subtree_of_type<HTMLInputElement>([&](auto& input) { for_each_in_inclusive_subtree_of_type<HTMLInputElement>([&](auto& input) {
if (!input.name().is_null() && (input.type() != "submit" || &input == submitter)) if (!input.name().is_null() && (input.type() != "submit" || &input == submitter)) {
parameters.append({ input.name(), input.value() }); auto name = String::from_deprecated_string(input.name()).release_value_but_fixme_should_propagate_errors();
auto value = String::from_deprecated_string(input.value()).release_value_but_fixme_should_propagate_errors();
parameters.append({ move(name), move(value) });
}
return IterationDecision::Continue; return IterationDecision::Continue;
}); });
if (effective_method == "get") { if (effective_method == "get") {
url.set_query(url_encode(parameters, AK::URL::PercentEncodeSet::ApplicationXWWWFormUrlencoded)); auto url_encoded_parameters = TRY(url_encode(parameters, AK::URL::PercentEncodeSet::ApplicationXWWWFormUrlencoded)).to_deprecated_string();
url.set_query(move(url_encoded_parameters));
} }
LoadRequest request = LoadRequest::create_for_url_on_page(url, document().page()); LoadRequest request = LoadRequest::create_for_url_on_page(url, document().page());
if (effective_method == "post") { if (effective_method == "post") {
auto body = url_encode(parameters, AK::URL::PercentEncodeSet::ApplicationXWWWFormUrlencoded).to_byte_buffer(); auto url_encoded_parameters_as_bytes = TRY(url_encode(parameters, AK::URL::PercentEncodeSet::ApplicationXWWWFormUrlencoded)).bytes();
auto body = TRY(ByteBuffer::copy(url_encoded_parameters_as_bytes));
request.set_method("POST"); request.set_method("POST");
request.set_header("Content-Type", "application/x-www-form-urlencoded"); request.set_header("Content-Type", "application/x-www-form-urlencoded");
request.set_body(move(body)); request.set_body(move(body));
@ -143,6 +148,8 @@ void HTMLFormElement::submit_form(JS::GCPtr<HTMLElement> submitter, bool from_su
if (auto* page = document().page()) if (auto* page = document().page())
page->load(request); page->load(request);
return {};
} }
// https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#resetting-a-form // https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#resetting-a-form
@ -166,9 +173,12 @@ void HTMLFormElement::reset_form()
} }
} }
void HTMLFormElement::submit() WebIDL::ExceptionOr<void> HTMLFormElement::submit()
{ {
submit_form(this, true); auto& vm = realm().vm();
TRY_OR_THROW_OOM(vm, submit_form(this, true));
return {};
} }
// https://html.spec.whatwg.org/multipage/forms.html#dom-form-reset // https://html.spec.whatwg.org/multipage/forms.html#dom-form-reset

View file

@ -22,12 +22,12 @@ public:
DeprecatedString action() const; DeprecatedString action() const;
DeprecatedString method() const { return attribute(HTML::AttributeNames::method); } DeprecatedString method() const { return attribute(HTML::AttributeNames::method); }
void submit_form(JS::GCPtr<HTMLElement> submitter, bool from_submit_binding = false); ErrorOr<void> submit_form(JS::GCPtr<HTMLElement> submitter, bool from_submit_binding = false);
void reset_form(); void reset_form();
// NOTE: This is for the JS bindings. Use submit_form instead. // NOTE: This is for the JS bindings. Use submit_form instead.
void submit(); WebIDL::ExceptionOr<void> submit();
// NOTE: This is for the JS bindings. Use submit_form instead. // NOTE: This is for the JS bindings. Use submit_form instead.
void reset(); void reset();

View file

@ -35,7 +35,7 @@ HTMLInputElement::HTMLInputElement(DOM::Document& document, DOM::QualifiedName q
// FIXME: 1. If this element is not mutable and is not in the Checkbox state and is not in the Radio state, then return. // FIXME: 1. If this element is not mutable and is not in the Checkbox state and is not in the Radio state, then return.
// 2. Run this element's input activation behavior, if any, and do nothing otherwise. // 2. Run this element's input activation behavior, if any, and do nothing otherwise.
run_input_activation_behavior(); run_input_activation_behavior().release_value_but_fixme_should_propagate_errors();
}; };
} }
@ -217,12 +217,12 @@ WebIDL::ExceptionOr<void> HTMLInputElement::show_picker()
} }
// https://html.spec.whatwg.org/multipage/input.html#input-activation-behavior // https://html.spec.whatwg.org/multipage/input.html#input-activation-behavior
void HTMLInputElement::run_input_activation_behavior() ErrorOr<void> HTMLInputElement::run_input_activation_behavior()
{ {
if (type_state() == TypeAttributeState::Checkbox || type_state() == TypeAttributeState::RadioButton) { if (type_state() == TypeAttributeState::Checkbox || type_state() == TypeAttributeState::RadioButton) {
// 1. If the element is not connected, then return. // 1. If the element is not connected, then return.
if (!is_connected()) if (!is_connected())
return; return {};
// 2. Fire an event named input at the element with the bubbles and composed attributes initialized to true. // 2. Fire an event named input at the element with the bubbles and composed attributes initialized to true.
auto input_event = DOM::Event::create(realm(), HTML::EventNames::input).release_value_but_fixme_should_propagate_errors(); auto input_event = DOM::Event::create(realm(), HTML::EventNames::input).release_value_but_fixme_should_propagate_errors();
@ -238,19 +238,21 @@ void HTMLInputElement::run_input_activation_behavior()
JS::GCPtr<HTMLFormElement> form; JS::GCPtr<HTMLFormElement> form;
// 1. If the element does not have a form owner, then return. // 1. If the element does not have a form owner, then return.
if (!(form = this->form())) if (!(form = this->form()))
return; return {};
// 2. If the element's node document is not fully active, then return. // 2. If the element's node document is not fully active, then return.
if (!document().is_fully_active()) if (!document().is_fully_active())
return; return {};
// 3. Submit the form owner from the element. // 3. Submit the form owner from the element.
form->submit_form(this); TRY(form->submit_form(this));
} else if (type_state() == TypeAttributeState::FileUpload) { } else if (type_state() == TypeAttributeState::FileUpload) {
show_the_picker_if_applicable(*this); show_the_picker_if_applicable(*this);
} else { } else {
dispatch_event(DOM::Event::create(realm(), EventNames::change).release_value_but_fixme_should_propagate_errors()); dispatch_event(DOM::Event::create(realm(), EventNames::change).release_value_but_fixme_should_propagate_errors());
} }
return {};
} }
void HTMLInputElement::did_edit_text_node(Badge<BrowsingContext>) void HTMLInputElement::did_edit_text_node(Badge<BrowsingContext>)

View file

@ -139,7 +139,7 @@ private:
static TypeAttributeState parse_type_attribute(StringView); static TypeAttributeState parse_type_attribute(StringView);
void create_shadow_tree_if_needed(); void create_shadow_tree_if_needed();
void run_input_activation_behavior(); ErrorOr<void> run_input_activation_behavior();
void set_checked_within_group(); void set_checked_within_group();
// https://html.spec.whatwg.org/multipage/input.html#value-sanitization-algorithm // https://html.spec.whatwg.org/multipage/input.html#value-sanitization-algorithm

View file

@ -18,14 +18,16 @@ WebIDL::ExceptionOr<JS::NonnullGCPtr<URL>> URL::create(JS::Realm& realm, AK::URL
return MUST_OR_THROW_OOM(realm.heap().allocate<URL>(realm, realm, move(url), move(query))); return MUST_OR_THROW_OOM(realm.heap().allocate<URL>(realm, realm, move(url), move(query)));
} }
WebIDL::ExceptionOr<JS::NonnullGCPtr<URL>> URL::construct_impl(JS::Realm& realm, DeprecatedString const& url, DeprecatedString const& base) WebIDL::ExceptionOr<JS::NonnullGCPtr<URL>> URL::construct_impl(JS::Realm& realm, String const& url, Optional<String> const& base)
{ {
auto& vm = realm.vm();
// 1. Let parsedBase be null. // 1. Let parsedBase be null.
Optional<AK::URL> parsed_base; Optional<AK::URL> parsed_base;
// 2. If base is given, then: // 2. If base is given, then:
if (!base.is_null()) { if (base.has_value()) {
// 1. Let parsedBase be the result of running the basic URL parser on base. // 1. Let parsedBase be the result of running the basic URL parser on base.
parsed_base = base; parsed_base = base.value();
// 2. If parsedBase is failure, then throw a TypeError. // 2. If parsedBase is failure, then throw a TypeError.
if (!parsed_base->is_valid()) if (!parsed_base->is_valid())
return WebIDL::SimpleException { WebIDL::SimpleExceptionType::TypeError, "Invalid base URL"sv }; return WebIDL::SimpleException { WebIDL::SimpleExceptionType::TypeError, "Invalid base URL"sv };
@ -40,7 +42,7 @@ WebIDL::ExceptionOr<JS::NonnullGCPtr<URL>> URL::construct_impl(JS::Realm& realm,
if (!parsed_url.is_valid()) if (!parsed_url.is_valid())
return WebIDL::SimpleException { WebIDL::SimpleExceptionType::TypeError, "Invalid URL"sv }; return WebIDL::SimpleException { WebIDL::SimpleExceptionType::TypeError, "Invalid URL"sv };
// 5. Let query be parsedURLs query, if that is non-null, and the empty string otherwise. // 5. Let query be parsedURLs query, if that is non-null, and the empty string otherwise.
auto& query = parsed_url.query().is_null() ? DeprecatedString::empty() : parsed_url.query(); auto query = parsed_url.query().is_null() ? String {} : TRY_OR_THROW_OOM(vm, String::from_deprecated_string(parsed_url.query()));
// 6. Set thiss URL to parsedURL. // 6. Set thiss URL to parsedURL.
// 7. Set thiss query object to a new URLSearchParams object. // 7. Set thiss query object to a new URLSearchParams object.
auto query_object = MUST(URLSearchParams::construct_impl(realm, query)); auto query_object = MUST(URLSearchParams::construct_impl(realm, query));
@ -75,20 +77,26 @@ void URL::visit_edges(Cell::Visitor& visitor)
visitor.visit(m_query.ptr()); visitor.visit(m_query.ptr());
} }
DeprecatedString URL::href() const WebIDL::ExceptionOr<String> URL::href() const
{ {
auto& vm = realm().vm();
// return the serialization of thiss URL. // return the serialization of thiss URL.
return m_url.serialize(); return TRY_OR_THROW_OOM(vm, String::from_deprecated_string(m_url.serialize()));
} }
DeprecatedString URL::to_json() const WebIDL::ExceptionOr<String> URL::to_json() const
{ {
auto& vm = realm().vm();
// return the serialization of thiss URL. // return the serialization of thiss URL.
return m_url.serialize(); return TRY_OR_THROW_OOM(vm, String::from_deprecated_string(m_url.serialize()));
} }
WebIDL::ExceptionOr<void> URL::set_href(DeprecatedString const& href) WebIDL::ExceptionOr<void> URL::set_href(String const& href)
{ {
auto& vm = realm().vm();
// 1. Let parsedURL be the result of running the basic URL parser on the given value. // 1. Let parsedURL be the result of running the basic URL parser on the given value.
AK::URL parsed_url = href; AK::URL parsed_url = href;
// 2. If parsedURL is failure, then throw a TypeError. // 2. If parsedURL is failure, then throw a TypeError.
@ -102,37 +110,46 @@ WebIDL::ExceptionOr<void> URL::set_href(DeprecatedString const& href)
auto& query = m_url.query(); auto& query = m_url.query();
// 6. If query is non-null, then set thiss query objects list to the result of parsing query. // 6. If query is non-null, then set thiss query objects list to the result of parsing query.
if (!query.is_null()) if (!query.is_null())
m_query->m_list = url_decode(query); m_query->m_list = TRY_OR_THROW_OOM(vm, url_decode(query));
return {}; return {};
} }
DeprecatedString URL::origin() const WebIDL::ExceptionOr<String> URL::origin() const
{ {
auto& vm = realm().vm();
// return the serialization of thiss URLs origin. // return the serialization of thiss URLs origin.
return m_url.serialize_origin(); return TRY_OR_THROW_OOM(vm, String::from_deprecated_string(m_url.serialize_origin()));
} }
DeprecatedString URL::protocol() const WebIDL::ExceptionOr<String> URL::protocol() const
{ {
auto& vm = realm().vm();
// return thiss URLs scheme, followed by U+003A (:). // return thiss URLs scheme, followed by U+003A (:).
return DeprecatedString::formatted("{}:", m_url.scheme()); return TRY_OR_THROW_OOM(vm, String::formatted("{}:", m_url.scheme()));
} }
void URL::set_protocol(DeprecatedString const& protocol) WebIDL::ExceptionOr<void> URL::set_protocol(String const& protocol)
{ {
auto& vm = realm().vm();
// basic URL parse the given value, followed by U+003A (:), with thiss URL as url and scheme start state as state override. // basic URL parse the given value, followed by U+003A (:), with thiss URL as url and scheme start state as state override.
auto result_url = URLParser::parse(DeprecatedString::formatted("{}:", protocol), nullptr, m_url, URLParser::State::SchemeStart); auto result_url = URLParser::parse(TRY_OR_THROW_OOM(vm, String::formatted("{}:", protocol)), nullptr, m_url, URLParser::State::SchemeStart);
if (result_url.is_valid()) if (result_url.is_valid())
m_url = move(result_url); m_url = move(result_url);
return {};
} }
DeprecatedString URL::username() const WebIDL::ExceptionOr<String> URL::username() const
{ {
auto& vm = realm().vm();
// return thiss URLs username. // return thiss URLs username.
return m_url.username(); return TRY_OR_THROW_OOM(vm, String::from_deprecated_string(m_url.username()));
} }
void URL::set_username(DeprecatedString const& username) void URL::set_username(String const& username)
{ {
// 1. If thiss URL cannot have a username/password/port, then return. // 1. If thiss URL cannot have a username/password/port, then return.
if (m_url.cannot_have_a_username_or_password_or_port()) if (m_url.cannot_have_a_username_or_password_or_port())
@ -141,13 +158,15 @@ void URL::set_username(DeprecatedString const& username)
m_url.set_username(AK::URL::percent_encode(username, AK::URL::PercentEncodeSet::Userinfo)); m_url.set_username(AK::URL::percent_encode(username, AK::URL::PercentEncodeSet::Userinfo));
} }
DeprecatedString URL::password() const WebIDL::ExceptionOr<String> URL::password() const
{ {
auto& vm = realm().vm();
// return thiss URLs password. // return thiss URLs password.
return m_url.password(); return TRY_OR_THROW_OOM(vm, String::from_deprecated_string(m_url.password()));
} }
void URL::set_password(DeprecatedString const& password) void URL::set_password(String const& password)
{ {
// 1. If thiss URL cannot have a username/password/port, then return. // 1. If thiss URL cannot have a username/password/port, then return.
if (m_url.cannot_have_a_username_or_password_or_port()) if (m_url.cannot_have_a_username_or_password_or_port())
@ -156,21 +175,23 @@ void URL::set_password(DeprecatedString const& password)
m_url.set_password(AK::URL::percent_encode(password, AK::URL::PercentEncodeSet::Userinfo)); m_url.set_password(AK::URL::percent_encode(password, AK::URL::PercentEncodeSet::Userinfo));
} }
DeprecatedString URL::host() const WebIDL::ExceptionOr<String> URL::host() const
{ {
auto& vm = realm().vm();
// 1. Let url be thiss URL. // 1. Let url be thiss URL.
auto& url = m_url; auto& url = m_url;
// 2. If urls host is null, then return the empty string. // 2. If urls host is null, then return the empty string.
if (url.host().is_null()) if (url.host().is_null())
return DeprecatedString::empty(); return String {};
// 3. If urls port is null, return urls host, serialized. // 3. If urls port is null, return urls host, serialized.
if (!url.port().has_value()) if (!url.port().has_value())
return url.host(); return TRY_OR_THROW_OOM(vm, String::from_deprecated_string(url.host()));
// 4. Return urls host, serialized, followed by U+003A (:) and urls port, serialized. // 4. Return urls host, serialized, followed by U+003A (:) and urls port, serialized.
return DeprecatedString::formatted("{}:{}", url.host(), *url.port()); return TRY_OR_THROW_OOM(vm, String::formatted("{}:{}", url.host(), *url.port()));
} }
void URL::set_host(DeprecatedString const& host) void URL::set_host(String const& host)
{ {
// 1. If thiss URLs cannot-be-a-base-URL is true, then return. // 1. If thiss URLs cannot-be-a-base-URL is true, then return.
if (m_url.cannot_be_a_base_url()) if (m_url.cannot_be_a_base_url())
@ -181,16 +202,18 @@ void URL::set_host(DeprecatedString const& host)
m_url = move(result_url); m_url = move(result_url);
} }
DeprecatedString URL::hostname() const WebIDL::ExceptionOr<String> URL::hostname() const
{ {
auto& vm = realm().vm();
// 1. If thiss URLs host is null, then return the empty string. // 1. If thiss URLs host is null, then return the empty string.
if (m_url.host().is_null()) if (m_url.host().is_null())
return DeprecatedString::empty(); return String {};
// 2. Return thiss URLs host, serialized. // 2. Return thiss URLs host, serialized.
return m_url.host(); return TRY_OR_THROW_OOM(vm, String::from_deprecated_string(m_url.host()));
} }
void URL::set_hostname(DeprecatedString const& hostname) void URL::set_hostname(String const& hostname)
{ {
// 1. If thiss URLs cannot-be-a-base-URL is true, then return. // 1. If thiss URLs cannot-be-a-base-URL is true, then return.
if (m_url.cannot_be_a_base_url()) if (m_url.cannot_be_a_base_url())
@ -201,17 +224,19 @@ void URL::set_hostname(DeprecatedString const& hostname)
m_url = move(result_url); m_url = move(result_url);
} }
DeprecatedString URL::port() const WebIDL::ExceptionOr<String> URL::port() const
{ {
auto& vm = realm().vm();
// 1. If thiss URLs port is null, then return the empty string. // 1. If thiss URLs port is null, then return the empty string.
if (!m_url.port().has_value()) if (!m_url.port().has_value())
return {}; return String {};
// 2. Return thiss URLs port, serialized. // 2. Return thiss URLs port, serialized.
return DeprecatedString::formatted("{}", *m_url.port()); return TRY_OR_THROW_OOM(vm, String::formatted("{}", *m_url.port()));
} }
void URL::set_port(DeprecatedString const& port) void URL::set_port(String const& port)
{ {
// 1. If thiss URL cannot have a username/password/port, then return. // 1. If thiss URL cannot have a username/password/port, then return.
if (m_url.cannot_have_a_username_or_password_or_port()) if (m_url.cannot_have_a_username_or_password_or_port())
@ -229,15 +254,17 @@ void URL::set_port(DeprecatedString const& port)
m_url = move(result_url); m_url = move(result_url);
} }
DeprecatedString URL::pathname() const WebIDL::ExceptionOr<String> URL::pathname() const
{ {
auto& vm = realm().vm();
// 1. If thiss URLs cannot-be-a-base-URL is true, then return thiss URLs path[0]. // 1. If thiss URLs cannot-be-a-base-URL is true, then return thiss URLs path[0].
// 2. If thiss URLs path is empty, then return the empty string. // 2. If thiss URLs path is empty, then return the empty string.
// 3. Return U+002F (/), followed by the strings in thiss URLs path (including empty strings), if any, separated from each other by U+002F (/). // 3. Return U+002F (/), followed by the strings in thiss URLs path (including empty strings), if any, separated from each other by U+002F (/).
return m_url.path(); return TRY_OR_THROW_OOM(vm, String::from_deprecated_string(m_url.path()));
} }
void URL::set_pathname(DeprecatedString const& pathname) void URL::set_pathname(String const& pathname)
{ {
// 1. If thiss URLs cannot-be-a-base-URL is true, then return. // 1. If thiss URLs cannot-be-a-base-URL is true, then return.
if (m_url.cannot_be_a_base_url()) if (m_url.cannot_be_a_base_url())
@ -251,27 +278,32 @@ void URL::set_pathname(DeprecatedString const& pathname)
m_url = move(result_url); m_url = move(result_url);
} }
DeprecatedString URL::search() const WebIDL::ExceptionOr<String> URL::search() const
{ {
auto& vm = realm().vm();
// 1. If thiss URLs query is either null or the empty string, then return the empty string. // 1. If thiss URLs query is either null or the empty string, then return the empty string.
if (m_url.query().is_null() || m_url.query().is_empty()) if (m_url.query().is_null() || m_url.query().is_empty())
return DeprecatedString::empty(); return String {};
// 2. Return U+003F (?), followed by thiss URLs query. // 2. Return U+003F (?), followed by thiss URLs query.
return DeprecatedString::formatted("?{}", m_url.query()); return TRY_OR_THROW_OOM(vm, String::formatted("?{}", m_url.query()));
} }
void URL::set_search(DeprecatedString const& search) WebIDL::ExceptionOr<void> URL::set_search(String const& search)
{ {
auto& vm = realm().vm();
// 1. Let url be thiss URL. // 1. Let url be thiss URL.
auto& url = m_url; auto& url = m_url;
// If the given value is the empty string, set urls query to null, empty thiss query objects list, and then return. // If the given value is the empty string, set urls query to null, empty thiss query objects list, and then return.
if (search.is_empty()) { if (search.is_empty()) {
url.set_query({}); url.set_query({});
m_query->m_list.clear(); m_query->m_list.clear();
return; return {};
} }
// 2. Let input be the given value with a single leading U+003F (?) removed, if any. // 2. Let input be the given value with a single leading U+003F (?) removed, if any.
auto input = search.substring_view(search.starts_with('?')); auto search_as_string_view = search.bytes_as_string_view();
auto input = search_as_string_view.substring_view(search_as_string_view.starts_with('?'));
// 3. Set urls query to the empty string. // 3. Set urls query to the empty string.
auto url_copy = url; // We copy the URL here to follow other browser's behaviour of reverting the search change if the parse failed. auto url_copy = url; // We copy the URL here to follow other browser's behaviour of reverting the search change if the parse failed.
url_copy.set_query(DeprecatedString::empty()); url_copy.set_query(DeprecatedString::empty());
@ -280,8 +312,10 @@ void URL::set_search(DeprecatedString const& search)
if (result_url.is_valid()) { if (result_url.is_valid()) {
m_url = move(result_url); m_url = move(result_url);
// 5. Set thiss query objects list to the result of parsing input. // 5. Set thiss query objects list to the result of parsing input.
m_query->m_list = url_decode(input); m_query->m_list = TRY_OR_THROW_OOM(vm, url_decode(input));
} }
return {};
} }
URLSearchParams const* URL::search_params() const URLSearchParams const* URL::search_params() const
@ -289,16 +323,18 @@ URLSearchParams const* URL::search_params() const
return m_query; return m_query;
} }
DeprecatedString URL::hash() const WebIDL::ExceptionOr<String> URL::hash() const
{ {
auto& vm = realm().vm();
// 1. If thiss URLs fragment is either null or the empty string, then return the empty string. // 1. If thiss URLs fragment is either null or the empty string, then return the empty string.
if (m_url.fragment().is_null() || m_url.fragment().is_empty()) if (m_url.fragment().is_null() || m_url.fragment().is_empty())
return DeprecatedString::empty(); return String {};
// 2. Return U+0023 (#), followed by thiss URLs fragment. // 2. Return U+0023 (#), followed by thiss URLs fragment.
return DeprecatedString::formatted("#{}", m_url.fragment()); return TRY_OR_THROW_OOM(vm, String::formatted("#{}", m_url.fragment()));
} }
void URL::set_hash(DeprecatedString const& hash) void URL::set_hash(String const& hash)
{ {
// 1. If the given value is the empty string, then set thiss URLs fragment to null and return. // 1. If the given value is the empty string, then set thiss URLs fragment to null and return.
if (hash.is_empty()) { if (hash.is_empty()) {
@ -306,7 +342,8 @@ void URL::set_hash(DeprecatedString const& hash)
return; return;
} }
// 2. Let input be the given value with a single leading U+0023 (#) removed, if any. // 2. Let input be the given value with a single leading U+0023 (#) removed, if any.
auto input = hash.substring_view(hash.starts_with('#')); auto hash_as_string_view = hash.bytes_as_string_view();
auto input = hash_as_string_view.substring_view(hash_as_string_view.starts_with('#'));
// 3. Set thiss URLs fragment to the empty string. // 3. Set thiss URLs fragment to the empty string.
auto url = m_url; // We copy the URL here to follow other browser's behaviour of reverting the hash change if the parse failed. auto url = m_url; // We copy the URL here to follow other browser's behaviour of reverting the hash change if the parse failed.
url.set_fragment(DeprecatedString::empty()); url.set_fragment(DeprecatedString::empty());

View file

@ -20,47 +20,47 @@ class URL : public Bindings::PlatformObject {
public: public:
static WebIDL::ExceptionOr<JS::NonnullGCPtr<URL>> create(JS::Realm&, AK::URL url, JS::NonnullGCPtr<URLSearchParams> query); static WebIDL::ExceptionOr<JS::NonnullGCPtr<URL>> create(JS::Realm&, AK::URL url, JS::NonnullGCPtr<URLSearchParams> query);
static WebIDL::ExceptionOr<JS::NonnullGCPtr<URL>> construct_impl(JS::Realm&, DeprecatedString const& url, DeprecatedString const& base); static WebIDL::ExceptionOr<JS::NonnullGCPtr<URL>> construct_impl(JS::Realm&, String const& url, Optional<String> const& base = {});
virtual ~URL() override; virtual ~URL() override;
DeprecatedString href() const; WebIDL::ExceptionOr<String> href() const;
WebIDL::ExceptionOr<void> set_href(DeprecatedString const&); WebIDL::ExceptionOr<void> set_href(String const&);
DeprecatedString origin() const; WebIDL::ExceptionOr<String> origin() const;
DeprecatedString protocol() const; WebIDL::ExceptionOr<String> protocol() const;
void set_protocol(DeprecatedString const&); WebIDL::ExceptionOr<void> set_protocol(String const&);
DeprecatedString username() const; WebIDL::ExceptionOr<String> username() const;
void set_username(DeprecatedString const&); void set_username(String const&);
DeprecatedString password() const; WebIDL::ExceptionOr<String> password() const;
void set_password(DeprecatedString const&); void set_password(String const&);
DeprecatedString host() const; WebIDL::ExceptionOr<String> host() const;
void set_host(DeprecatedString const&); void set_host(String const&);
DeprecatedString hostname() const; WebIDL::ExceptionOr<String> hostname() const;
void set_hostname(DeprecatedString const&); void set_hostname(String const&);
DeprecatedString port() const; WebIDL::ExceptionOr<String> port() const;
void set_port(DeprecatedString const&); void set_port(String const&);
DeprecatedString pathname() const; WebIDL::ExceptionOr<String> pathname() const;
void set_pathname(DeprecatedString const&); void set_pathname(String const&);
DeprecatedString search() const; WebIDL::ExceptionOr<String> search() const;
void set_search(DeprecatedString const&); WebIDL::ExceptionOr<void> set_search(String const&);
URLSearchParams const* search_params() const; URLSearchParams const* search_params() const;
DeprecatedString hash() const; WebIDL::ExceptionOr<String> hash() const;
void set_hash(DeprecatedString const&); void set_hash(String const&);
DeprecatedString to_json() const; WebIDL::ExceptionOr<String> to_json() const;
void set_query(Badge<URLSearchParams>, DeprecatedString query) { m_url.set_query(move(query)); } void set_query(Badge<URLSearchParams>, String query) { m_url.set_query(query.to_deprecated_string()); }
private: private:
URL(JS::Realm&, AK::URL, JS::NonnullGCPtr<URLSearchParams> query); URL(JS::Realm&, AK::URL, JS::NonnullGCPtr<URLSearchParams> query);

View file

@ -1,7 +1,7 @@
#import <URL/URLSearchParams.idl> #import <URL/URLSearchParams.idl>
// https://url.spec.whatwg.org/#url // https://url.spec.whatwg.org/#url
[Exposed=*, LegacyWindowAlias=webkitURL] [Exposed=*, LegacyWindowAlias=webkitURL, UseNewAKString]
interface URL { interface URL {
constructor(USVString url, optional USVString base); constructor(USVString url, optional USVString base);

View file

@ -7,6 +7,7 @@
#include <AK/QuickSort.h> #include <AK/QuickSort.h>
#include <AK/StringBuilder.h> #include <AK/StringBuilder.h>
#include <AK/Utf8View.h> #include <AK/Utf8View.h>
#include <LibWeb/Bindings/ExceptionOrUtils.h>
#include <LibWeb/Bindings/Intrinsics.h> #include <LibWeb/Bindings/Intrinsics.h>
#include <LibWeb/URL/URL.h> #include <LibWeb/URL/URL.h>
#include <LibWeb/URL/URLSearchParams.h> #include <LibWeb/URL/URLSearchParams.h>
@ -35,20 +36,20 @@ void URLSearchParams::visit_edges(Cell::Visitor& visitor)
visitor.visit(m_url); visitor.visit(m_url);
} }
DeprecatedString url_encode(Vector<QueryParam> const& pairs, AK::URL::PercentEncodeSet percent_encode_set) ErrorOr<String> url_encode(Vector<QueryParam> const& pairs, AK::URL::PercentEncodeSet percent_encode_set)
{ {
StringBuilder builder; StringBuilder builder;
for (size_t i = 0; i < pairs.size(); ++i) { for (size_t i = 0; i < pairs.size(); ++i) {
builder.append(AK::URL::percent_encode(pairs[i].name, percent_encode_set, AK::URL::SpaceAsPlus::Yes)); TRY(builder.try_append(AK::URL::percent_encode(pairs[i].name, percent_encode_set, AK::URL::SpaceAsPlus::Yes)));
builder.append('='); TRY(builder.try_append('='));
builder.append(AK::URL::percent_encode(pairs[i].value, percent_encode_set, AK::URL::SpaceAsPlus::Yes)); TRY(builder.try_append(AK::URL::percent_encode(pairs[i].value, percent_encode_set, AK::URL::SpaceAsPlus::Yes)));
if (i != pairs.size() - 1) if (i != pairs.size() - 1)
builder.append('&'); TRY(builder.try_append('&'));
} }
return builder.to_deprecated_string(); return builder.to_string();
} }
Vector<QueryParam> url_decode(StringView input) ErrorOr<Vector<QueryParam>> url_decode(StringView input)
{ {
// 1. Let sequences be the result of splitting input on 0x26 (&). // 1. Let sequences be the result of splitting input on 0x26 (&).
auto sequences = input.split_view('&'); auto sequences = input.split_view('&');
@ -80,10 +81,10 @@ Vector<QueryParam> url_decode(StringView input)
auto space_decoded_name = name.replace("+"sv, " "sv, ReplaceMode::All); auto space_decoded_name = name.replace("+"sv, " "sv, ReplaceMode::All);
// 5. Let nameString and valueString be the result of running UTF-8 decode without BOM on the percent-decoding of name and value, respectively. // 5. Let nameString and valueString be the result of running UTF-8 decode without BOM on the percent-decoding of name and value, respectively.
auto name_string = AK::URL::percent_decode(space_decoded_name); auto name_string = TRY(String::from_deprecated_string(AK::URL::percent_decode(space_decoded_name)));
auto value_string = AK::URL::percent_decode(value); auto value_string = TRY(String::from_deprecated_string(AK::URL::percent_decode(value)));
output.empend(move(name_string), move(value_string)); TRY(output.try_empend(move(name_string), move(value_string)));
} }
return output; return output;
@ -96,8 +97,10 @@ WebIDL::ExceptionOr<JS::NonnullGCPtr<URLSearchParams>> URLSearchParams::create(J
// https://url.spec.whatwg.org/#dom-urlsearchparams-urlsearchparams // https://url.spec.whatwg.org/#dom-urlsearchparams-urlsearchparams
// https://url.spec.whatwg.org/#urlsearchparams-initialize // https://url.spec.whatwg.org/#urlsearchparams-initialize
WebIDL::ExceptionOr<JS::NonnullGCPtr<URLSearchParams>> URLSearchParams::construct_impl(JS::Realm& realm, Variant<Vector<Vector<DeprecatedString>>, OrderedHashMap<DeprecatedString, DeprecatedString>, DeprecatedString> const& init) WebIDL::ExceptionOr<JS::NonnullGCPtr<URLSearchParams>> URLSearchParams::construct_impl(JS::Realm& realm, Variant<Vector<Vector<String>>, OrderedHashMap<String, String>, String> const& init)
{ {
auto& vm = realm.vm();
// 1. If init is a string and starts with U+003F (?), then remove the first code point from init. // 1. If init is a string and starts with U+003F (?), then remove the first code point from init.
// NOTE: We do this when we know that it's a string on step 3 of initialization. // NOTE: We do this when we know that it's a string on step 3 of initialization.
@ -106,8 +109,8 @@ WebIDL::ExceptionOr<JS::NonnullGCPtr<URLSearchParams>> URLSearchParams::construc
// URLSearchParams init from this point forward // URLSearchParams init from this point forward
// 1. If init is a sequence, then for each pair in init: // 1. If init is a sequence, then for each pair in init:
if (init.has<Vector<Vector<DeprecatedString>>>()) { if (init.has<Vector<Vector<String>>>()) {
auto const& init_sequence = init.get<Vector<Vector<DeprecatedString>>>(); auto const& init_sequence = init.get<Vector<Vector<String>>>();
Vector<QueryParam> list; Vector<QueryParam> list;
list.ensure_capacity(init_sequence.size()); list.ensure_capacity(init_sequence.size());
@ -125,8 +128,8 @@ WebIDL::ExceptionOr<JS::NonnullGCPtr<URLSearchParams>> URLSearchParams::construc
} }
// 2. Otherwise, if init is a record, then for each name → value of init, append a new name-value pair whose name is name and value is value, to querys list. // 2. Otherwise, if init is a record, then for each name → value of init, append a new name-value pair whose name is name and value is value, to querys list.
if (init.has<OrderedHashMap<DeprecatedString, DeprecatedString>>()) { if (init.has<OrderedHashMap<String, String>>()) {
auto const& init_record = init.get<OrderedHashMap<DeprecatedString, DeprecatedString>>(); auto const& init_record = init.get<OrderedHashMap<String, String>>();
Vector<QueryParam> list; Vector<QueryParam> list;
list.ensure_capacity(init_record.size()); list.ensure_capacity(init_record.size());
@ -140,13 +143,14 @@ WebIDL::ExceptionOr<JS::NonnullGCPtr<URLSearchParams>> URLSearchParams::construc
// 3. Otherwise: // 3. Otherwise:
// a. Assert: init is a string. // a. Assert: init is a string.
// NOTE: `get` performs `VERIFY(has<T>())` // NOTE: `get` performs `VERIFY(has<T>())`
auto const& init_string = init.get<DeprecatedString>(); auto const& init_string = init.get<String>();
// See NOTE at the start of this function. // See NOTE at the start of this function.
StringView stripped_init = init_string.substring_view(init_string.starts_with('?')); auto init_string_view = init_string.bytes_as_string_view();
auto stripped_init = init_string_view.substring_view(init_string_view.starts_with('?'));
// b. Set querys list to the result of parsing init. // b. Set querys list to the result of parsing init.
return URLSearchParams::create(realm, url_decode(stripped_init)); return URLSearchParams::create(realm, TRY_OR_THROW_OOM(vm, url_decode(stripped_init)));
} }
// https://url.spec.whatwg.org/#dom-urlsearchparams-size // https://url.spec.whatwg.org/#dom-urlsearchparams-size
@ -156,39 +160,47 @@ size_t URLSearchParams::size() const
return m_list.size(); return m_list.size();
} }
void URLSearchParams::append(DeprecatedString const& name, DeprecatedString const& value) WebIDL::ExceptionOr<void> URLSearchParams::append(String const& name, String const& value)
{ {
auto& vm = realm().vm();
// 1. Append a new name-value pair whose name is name and value is value, to list. // 1. Append a new name-value pair whose name is name and value is value, to list.
m_list.empend(name, value); TRY_OR_THROW_OOM(vm, m_list.try_empend(name, value));
// 2. Update this. // 2. Update this.
update(); TRY(update());
return {};
} }
void URLSearchParams::update() WebIDL::ExceptionOr<void> URLSearchParams::update()
{ {
// 1. If querys URL object is null, then return. // 1. If querys URL object is null, then return.
if (!m_url) if (!m_url)
return; return {};
// 2. Let serializedQuery be the serialization of querys list. // 2. Let serializedQuery be the serialization of querys list.
auto serialized_query = to_deprecated_string(); auto serialized_query = TRY(to_string());
// 3. If serializedQuery is the empty string, then set serializedQuery to null. // 3. If serializedQuery is the empty string, then set serializedQuery to null.
if (serialized_query.is_empty()) if (serialized_query.is_empty())
serialized_query = {}; serialized_query = {};
// 4. Set querys URL objects URLs query to serializedQuery. // 4. Set querys URL objects URLs query to serializedQuery.
m_url->set_query({}, move(serialized_query)); m_url->set_query({}, move(serialized_query));
return {};
} }
void URLSearchParams::delete_(DeprecatedString const& name) WebIDL::ExceptionOr<void> URLSearchParams::delete_(String const& name)
{ {
// 1. Remove all name-value pairs whose name is name from list. // 1. Remove all name-value pairs whose name is name from list.
m_list.remove_all_matching([&name](auto& entry) { m_list.remove_all_matching([&name](auto& entry) {
return entry.name == name; return entry.name == name;
}); });
// 2. Update this. // 2. Update this.
update(); TRY(update());
return {};
} }
DeprecatedString URLSearchParams::get(DeprecatedString const& name) Optional<String> URLSearchParams::get(String const& name)
{ {
// return the value of the first name-value pair whose name is name in thiss list, if there is such a pair, and null otherwise. // return the value of the first name-value pair whose name is name in thiss list, if there is such a pair, and null otherwise.
auto result = m_list.find_if([&name](auto& entry) { auto result = m_list.find_if([&name](auto& entry) {
@ -200,18 +212,20 @@ DeprecatedString URLSearchParams::get(DeprecatedString const& name)
} }
// https://url.spec.whatwg.org/#dom-urlsearchparams-getall // https://url.spec.whatwg.org/#dom-urlsearchparams-getall
Vector<DeprecatedString> URLSearchParams::get_all(DeprecatedString const& name) WebIDL::ExceptionOr<Vector<String>> URLSearchParams::get_all(String const& name)
{ {
auto& vm = realm().vm();
// return the values of all name-value pairs whose name is name, in thiss list, in list order, and the empty sequence otherwise. // return the values of all name-value pairs whose name is name, in thiss list, in list order, and the empty sequence otherwise.
Vector<DeprecatedString> values; Vector<String> values;
for (auto& entry : m_list) { for (auto& entry : m_list) {
if (entry.name == name) if (entry.name == name)
values.append(entry.value); TRY_OR_THROW_OOM(vm, values.try_append(entry.value));
} }
return values; return values;
} }
bool URLSearchParams::has(DeprecatedString const& name) bool URLSearchParams::has(String const& name)
{ {
// return true if there is a name-value pair whose name is name in thiss list, and false otherwise. // return true if there is a name-value pair whose name is name in thiss list, and false otherwise.
return !m_list.find_if([&name](auto& entry) { return !m_list.find_if([&name](auto& entry) {
@ -220,8 +234,10 @@ bool URLSearchParams::has(DeprecatedString const& name)
.is_end(); .is_end();
} }
void URLSearchParams::set(DeprecatedString const& name, DeprecatedString const& value) WebIDL::ExceptionOr<void> URLSearchParams::set(String const& name, String const& value)
{ {
auto& vm = realm().vm();
// 1. If thiss list contains any name-value pairs whose name is name, then set the value of the first such name-value pair to value and remove the others. // 1. If thiss list contains any name-value pairs whose name is name, then set the value of the first such name-value pair to value and remove the others.
auto existing = m_list.find_if([&name](auto& entry) { auto existing = m_list.find_if([&name](auto& entry) {
return entry.name == name; return entry.name == name;
@ -234,13 +250,15 @@ void URLSearchParams::set(DeprecatedString const& name, DeprecatedString const&
} }
// 2. Otherwise, append a new name-value pair whose name is name and value is value, to thiss list. // 2. Otherwise, append a new name-value pair whose name is name and value is value, to thiss list.
else { else {
m_list.empend(name, value); TRY_OR_THROW_OOM(vm, m_list.try_empend(name, value));
} }
// 3. Update this. // 3. Update this.
update(); TRY(update());
return {};
} }
void URLSearchParams::sort() WebIDL::ExceptionOr<void> URLSearchParams::sort()
{ {
// 1. Sort all name-value pairs, if any, by their names. Sorting must be done by comparison of code units. The relative order between name-value pairs with equal names must be preserved. // 1. Sort all name-value pairs, if any, by their names. Sorting must be done by comparison of code units. The relative order between name-value pairs with equal names must be preserved.
quick_sort(m_list.begin(), m_list.end(), [](auto& a, auto& b) { quick_sort(m_list.begin(), m_list.end(), [](auto& a, auto& b) {
@ -266,13 +284,17 @@ void URLSearchParams::sort()
VERIFY_NOT_REACHED(); VERIFY_NOT_REACHED();
}); });
// 2. Update this. // 2. Update this.
update(); TRY(update());
return {};
} }
DeprecatedString URLSearchParams::to_deprecated_string() const WebIDL::ExceptionOr<String> URLSearchParams::to_string() const
{ {
auto& vm = realm().vm();
// return the serialization of thiss list. // return the serialization of thiss list.
return url_encode(m_list, AK::URL::PercentEncodeSet::ApplicationXWWWFormUrlencoded); return TRY_OR_THROW_OOM(vm, url_encode(m_list, AK::URL::PercentEncodeSet::ApplicationXWWWFormUrlencoded));
} }
JS::ThrowCompletionOr<void> URLSearchParams::for_each(ForEachCallback callback) JS::ThrowCompletionOr<void> URLSearchParams::for_each(ForEachCallback callback)

View file

@ -13,34 +13,34 @@
namespace Web::URL { namespace Web::URL {
struct QueryParam { struct QueryParam {
DeprecatedString name; String name;
DeprecatedString value; String value;
}; };
DeprecatedString url_encode(Vector<QueryParam> const&, AK::URL::PercentEncodeSet); ErrorOr<String> url_encode(Vector<QueryParam> const&, AK::URL::PercentEncodeSet);
Vector<QueryParam> url_decode(StringView); ErrorOr<Vector<QueryParam>> url_decode(StringView);
class URLSearchParams : public Bindings::PlatformObject { class URLSearchParams : public Bindings::PlatformObject {
WEB_PLATFORM_OBJECT(URLSearchParams, Bindings::PlatformObject); WEB_PLATFORM_OBJECT(URLSearchParams, Bindings::PlatformObject);
public: public:
static WebIDL::ExceptionOr<JS::NonnullGCPtr<URLSearchParams>> create(JS::Realm&, Vector<QueryParam> list); static WebIDL::ExceptionOr<JS::NonnullGCPtr<URLSearchParams>> create(JS::Realm&, Vector<QueryParam> list);
static WebIDL::ExceptionOr<JS::NonnullGCPtr<URLSearchParams>> construct_impl(JS::Realm&, Variant<Vector<Vector<DeprecatedString>>, OrderedHashMap<DeprecatedString, DeprecatedString>, DeprecatedString> const& init); static WebIDL::ExceptionOr<JS::NonnullGCPtr<URLSearchParams>> construct_impl(JS::Realm&, Variant<Vector<Vector<String>>, OrderedHashMap<String, String>, String> const& init);
virtual ~URLSearchParams() override; virtual ~URLSearchParams() override;
size_t size() const; size_t size() const;
void append(DeprecatedString const& name, DeprecatedString const& value); WebIDL::ExceptionOr<void> append(String const& name, String const& value);
void delete_(DeprecatedString const& name); WebIDL::ExceptionOr<void> delete_(String const& name);
DeprecatedString get(DeprecatedString const& name); Optional<String> get(String const& name);
Vector<DeprecatedString> get_all(DeprecatedString const& name); WebIDL::ExceptionOr<Vector<String>> get_all(String const& name);
bool has(DeprecatedString const& name); bool has(String const& name);
void set(DeprecatedString const& name, DeprecatedString const& value); WebIDL::ExceptionOr<void> set(String const& name, String const& value);
void sort(); WebIDL::ExceptionOr<void> sort();
DeprecatedString to_deprecated_string() const; WebIDL::ExceptionOr<String> to_string() const;
using ForEachCallback = Function<JS::ThrowCompletionOr<void>(DeprecatedString const&, DeprecatedString const&)>; using ForEachCallback = Function<JS::ThrowCompletionOr<void>(String const&, String const&)>;
JS::ThrowCompletionOr<void> for_each(ForEachCallback); JS::ThrowCompletionOr<void> for_each(ForEachCallback);
private: private:
@ -52,7 +52,7 @@ private:
virtual JS::ThrowCompletionOr<void> initialize(JS::Realm&) override; virtual JS::ThrowCompletionOr<void> initialize(JS::Realm&) override;
virtual void visit_edges(Cell::Visitor&) override; virtual void visit_edges(Cell::Visitor&) override;
void update(); WebIDL::ExceptionOr<void> update();
Vector<QueryParam> m_list; Vector<QueryParam> m_list;
JS::GCPtr<URL> m_url; JS::GCPtr<URL> m_url;

View file

@ -1,5 +1,5 @@
// https://url.spec.whatwg.org/#urlsearchparams // https://url.spec.whatwg.org/#urlsearchparams
[Exposed=*] [Exposed=*, UseNewAKString]
interface URLSearchParams { interface URLSearchParams {
constructor(optional (sequence<sequence<USVString>> or record<USVString, USVString> or USVString) init = ""); constructor(optional (sequence<sequence<USVString>> or record<USVString, USVString> or USVString) init = "");