LibWeb/Fetch: Replace usages of AbortSignal::follow() in Fetch::Request

Since the introduction of `AbortSignal::any()`, the specification says
`AbortSignal::create_dependent_abort_signal()` should be used where
`AbortSignal::follow` was previously.
This commit is contained in:
Tim Ledbetter 2024-03-26 07:45:11 +00:00 committed by Andreas Kling
parent 3d78f86a2f
commit 17e64cf08b
Notes: sideshowbarker 2024-07-17 05:21:12 +09:00
3 changed files with 36 additions and 29 deletions

View file

@ -81,7 +81,7 @@ JS::GCPtr<Infrastructure::Body> Request::body_impl()
}
// https://fetch.spec.whatwg.org/#request-create
JS::NonnullGCPtr<Request> Request::create(JS::Realm& realm, JS::NonnullGCPtr<Infrastructure::Request> request, Headers::Guard guard)
JS::NonnullGCPtr<Request> Request::create(JS::Realm& realm, JS::NonnullGCPtr<Infrastructure::Request> request, Headers::Guard guard, JS::NonnullGCPtr<DOM::AbortSignal> signal)
{
// 1. Let requestObject be a new Request object with realm.
// 2. Set requestObjects request to request.
@ -91,8 +91,8 @@ JS::NonnullGCPtr<Request> Request::create(JS::Realm& realm, JS::NonnullGCPtr<Inf
request_object->m_headers = realm.heap().allocate<Headers>(realm, realm, request->header_list());
request_object->m_headers->set_guard(guard);
// 4. Set requestObjects signal to a new AbortSignal object with realm.
request_object->m_signal = realm.heap().allocate<DOM::AbortSignal>(realm, realm);
// 4. Set requestObjects signal to signal.
request_object->m_signal = signal;
// 5. Return requestObject.
return request_object;
@ -383,23 +383,26 @@ WebIDL::ExceptionOr<JS::NonnullGCPtr<Request>> Request::construct_impl(JS::Realm
if (init.signal.has_value())
input_signal = *init.signal;
// 27. Set thiss request to request.
// FIXME: 27. If init["priority"] exists, then:
// 28. Set thiss request to request.
// NOTE: This is done at the beginning as the 'this' value Request object
// cannot exist with a null Infrastructure::Request.
// 28. Set thiss signal to a new AbortSignal object with thiss relevant Realm.
// 29. Let signals be « signal » if signal is non-null; otherwise « ».
auto& this_relevant_realm = HTML::relevant_realm(*request_object);
request_object->m_signal = realm.heap().allocate<DOM::AbortSignal>(this_relevant_realm, this_relevant_realm);
// 29. If signal is not null, then make thiss signal follow signal.
Vector<JS::Handle<DOM::AbortSignal>> signals;
if (input_signal != nullptr)
request_object->m_signal->follow(*input_signal);
signals.append(*input_signal);
// 30. Set thiss headers to a new Headers object with thiss relevant Realm, whose header list is requests header list and guard is "request".
// 30. Set thiss signal to the result of creating a dependent abort signal from signals, using AbortSignal and thiss relevant realm.
request_object->m_signal = TRY(DOM::AbortSignal::create_dependent_abort_signal(this_relevant_realm, signals));
// 31. Set thiss headers to a new Headers object with thiss relevant Realm, whose header list is requests header list and guard is "request".
request_object->m_headers = realm.heap().allocate<Headers>(realm, realm, request->header_list());
request_object->m_headers->set_guard(Headers::Guard::Request);
// 31. If thiss requests mode is "no-cors", then:
// 32. If thiss requests mode is "no-cors", then:
if (request_object->request()->mode() == Infrastructure::Request::Mode::NoCORS) {
// 1. If thiss requests method is not a CORS-safelisted method, then throw a TypeError.
if (!Infrastructure::is_cors_safelisted_method(request_object->request()->method()))
@ -409,7 +412,7 @@ WebIDL::ExceptionOr<JS::NonnullGCPtr<Request>> Request::construct_impl(JS::Realm
request_object->headers()->set_guard(Headers::Guard::RequestNoCORS);
}
// 32. If init is not empty, then:
// 33. If init is not empty, then:
if (!init.is_empty()) {
// 1. Let headers be a copy of thiss headers and its associated header list.
auto headers = Variant<HeadersInit, JS::NonnullGCPtr<Infrastructure::HeaderList>> { request_object->headers()->header_list() };
@ -432,19 +435,19 @@ WebIDL::ExceptionOr<JS::NonnullGCPtr<Request>> Request::construct_impl(JS::Realm
}
}
// 33. Let inputBody be inputs requests body if input is a Request object; otherwise null.
// 34. Let inputBody be inputs requests body if input is a Request object; otherwise null.
Optional<Infrastructure::Request::BodyType const&> input_body;
if (input.has<JS::Handle<Request>>())
input_body = input.get<JS::Handle<Request>>()->request()->body();
// 34. If either init["body"] exists and is non-null or inputBody is non-null, and requests method is `GET` or `HEAD`, then throw a TypeError.
// 35. If either init["body"] exists and is non-null or inputBody is non-null, and requests method is `GET` or `HEAD`, then throw a TypeError.
if (((init.body.has_value() && (*init.body).has_value()) || (input_body.has_value() && !input_body.value().has<Empty>())) && StringView { request->method() }.is_one_of("GET"sv, "HEAD"sv))
return WebIDL::SimpleException { WebIDL::SimpleExceptionType::TypeError, "Method must not be GET or HEAD when body is provided"sv };
// 35. Let initBody be null.
// 36. Let initBody be null.
JS::GCPtr<Infrastructure::Body> init_body;
// 36. If init["body"] exists and is non-null, then:
// 37. If init["body"] exists and is non-null, then:
if (init.body.has_value() && (*init.body).has_value()) {
// 1. Let bodyWithType be the result of extracting init["body"], with keepalive set to requests keepalive.
auto body_with_type = TRY(extract_body(realm, (*init.body).value(), request->keepalive()));
@ -460,12 +463,12 @@ WebIDL::ExceptionOr<JS::NonnullGCPtr<Request>> Request::construct_impl(JS::Realm
TRY(request_object->headers()->append(TRY_OR_THROW_OOM(vm, Infrastructure::Header::from_string_pair("Content-Type"sv, type->span()))));
}
// 37. Let inputOrInitBody be initBody if it is non-null; otherwise inputBody.
// 38. Let inputOrInitBody be initBody if it is non-null; otherwise inputBody.
Optional<Infrastructure::Request::BodyType> input_or_init_body = init_body
? Infrastructure::Request::BodyType { *init_body }
: input_body;
// 38. If inputOrInitBody is non-null and inputOrInitBodys source is null, then:
// 39. If inputOrInitBody is non-null and inputOrInitBodys source is null, then:
// FIXME: The spec doesn't check if inputOrInitBody is a body before accessing source.
if (input_or_init_body.has_value() && input_or_init_body->has<JS::NonnullGCPtr<Infrastructure::Body>>() && input_or_init_body->get<JS::NonnullGCPtr<Infrastructure::Body>>()->source().has<Empty>()) {
// 1. If initBody is non-null and init["duplex"] does not exist, then throw a TypeError.
@ -480,10 +483,10 @@ WebIDL::ExceptionOr<JS::NonnullGCPtr<Request>> Request::construct_impl(JS::Realm
request_object->request()->set_use_cors_preflight(true);
}
// 39. Let finalBody be inputOrInitBody.
// 40. Let finalBody be inputOrInitBody.
auto const& final_body = input_or_init_body;
// 40. If initBody is null and inputBody is non-null, then:
// 41. If initBody is null and inputBody is non-null, then:
if (!init_body && input_body.has_value()) {
// 2. If input is unusable, then throw a TypeError.
if (input.has<JS::Handle<Request>>() && input.get<JS::Handle<Request>>()->is_unusable())
@ -492,7 +495,7 @@ WebIDL::ExceptionOr<JS::NonnullGCPtr<Request>> Request::construct_impl(JS::Realm
// FIXME: 2. Set finalBody to the result of creating a proxy for inputBody.
}
// 41. Set thiss requests body to finalBody.
// 42. Set thiss requests body to finalBody.
if (final_body.has_value())
request_object->request()->set_body(*final_body);
@ -643,13 +646,17 @@ WebIDL::ExceptionOr<JS::NonnullGCPtr<Request>> Request::clone() const
// 2. Let clonedRequest be the result of cloning thiss request.
auto cloned_request = m_request->clone(realm);
// 3. Let clonedRequestObject be the result of creating a Request object, given clonedRequest, thiss headerss guard, and thiss relevant Realm.
auto cloned_request_object = Request::create(HTML::relevant_realm(*this), cloned_request, m_headers->guard());
// 3. Assert: thiss signal is non-null.
VERIFY(m_signal);
// 4. Make clonedRequestObjects signal follow thiss signal.
cloned_request_object->m_signal->follow(*m_signal);
// 4. Let clonedSignal be the result of creating a dependent abort signal from « thiss signal », using AbortSignal and thiss relevant realm.
auto& relevant_realm = HTML::relevant_realm(*this);
auto cloned_signal = TRY(DOM::AbortSignal::create_dependent_abort_signal(relevant_realm, { m_signal }));
// 5. Return clonedRequestObject.
// 5. Let clonedRequestObject be the result of creating a Request object, given clonedRequest, thiss headerss guard, clonedSignal and thiss relevant realm.
auto cloned_request_object = Request::create(relevant_realm, cloned_request, m_headers->guard(), cloned_signal);
// 6. Return clonedRequestObject.
return cloned_request_object;
}