Просмотр исходного кода

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.
Tim Ledbetter 1 год назад
Родитель
Сommit
17e64cf08b

+ 2 - 2
Userland/Libraries/LibWeb/DOM/AbortSignal.h

@@ -49,14 +49,14 @@ public:
     static WebIDL::ExceptionOr<JS::NonnullGCPtr<AbortSignal>> timeout(JS::VM&, Web::WebIDL::UnsignedLongLong milliseconds);
     static WebIDL::ExceptionOr<JS::NonnullGCPtr<AbortSignal>> any(JS::VM&, JS::Value signals);
 
+    static WebIDL::ExceptionOr<JS::NonnullGCPtr<AbortSignal>> create_dependent_abort_signal(JS::Realm&, Vector<JS::Handle<AbortSignal>> const&);
+
 private:
     explicit AbortSignal(JS::Realm&);
 
     virtual void initialize(JS::Realm&) override;
     virtual void visit_edges(JS::Cell::Visitor&) override;
 
-    static WebIDL::ExceptionOr<JS::NonnullGCPtr<AbortSignal>> create_dependent_abort_signal(JS::Realm&, Vector<JS::Handle<AbortSignal>> const&);
-
     bool dependent() const { return m_dependent; }
     void set_dependent(bool dependent) { m_dependent = dependent; }
 

+ 33 - 26
Userland/Libraries/LibWeb/Fetch/Request.cpp

@@ -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 requestObject’s 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 requestObject’s signal to a new AbortSignal object with realm.
-    request_object->m_signal = realm.heap().allocate<DOM::AbortSignal>(realm, realm);
+    // 4. Set requestObject’s 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 this’s request to request.
+    // FIXME: 27. If init["priority"] exists, then:
+
+    // 28. Set this’s 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 this’s signal to a new AbortSignal object with this’s 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 this’s 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 this’s headers to a new Headers object with this’s relevant Realm, whose header list is request’s header list and guard is "request".
+    // 30. Set this’s signal to the result of creating a dependent abort signal from signals, using AbortSignal and this’s relevant realm.
+    request_object->m_signal = TRY(DOM::AbortSignal::create_dependent_abort_signal(this_relevant_realm, signals));
+
+    // 31. Set this’s headers to a new Headers object with this’s relevant Realm, whose header list is request’s 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 this’s request’s mode is "no-cors", then:
+    // 32. If this’s request’s mode is "no-cors", then:
     if (request_object->request()->mode() == Infrastructure::Request::Mode::NoCORS) {
         // 1. If this’s request’s 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 this’s 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 input’s request’s body if input is a Request object; otherwise null.
+    // 34. Let inputBody be input’s request’s 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 request’s 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 request’s 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 request’s 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 inputOrInitBody’s source is null, then:
+    // 39. If inputOrInitBody is non-null and inputOrInitBody’s 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 this’s request’s body to finalBody.
+    // 42. Set this’s request’s 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 this’s request.
     auto cloned_request = m_request->clone(realm);
 
-    // 3. Let clonedRequestObject be the result of creating a Request object, given clonedRequest, this’s headers’s guard, and this’s relevant Realm.
-    auto cloned_request_object = Request::create(HTML::relevant_realm(*this), cloned_request, m_headers->guard());
+    // 3. Assert: this’s signal is non-null.
+    VERIFY(m_signal);
+
+    // 4. Let clonedSignal be the result of creating a dependent abort signal from « this’s signal », using AbortSignal and this’s relevant realm.
+    auto& relevant_realm = HTML::relevant_realm(*this);
+    auto cloned_signal = TRY(DOM::AbortSignal::create_dependent_abort_signal(relevant_realm, { m_signal }));
 
-    // 4. Make clonedRequestObject’s signal follow this’s signal.
-    cloned_request_object->m_signal->follow(*m_signal);
+    // 5. Let clonedRequestObject be the result of creating a Request object, given clonedRequest, this’s headers’s guard, clonedSignal and this’s relevant realm.
+    auto cloned_request_object = Request::create(relevant_realm, cloned_request, m_headers->guard(), cloned_signal);
 
-    // 5. Return clonedRequestObject.
+    // 6. Return clonedRequestObject.
     return cloned_request_object;
 }
 

+ 1 - 1
Userland/Libraries/LibWeb/Fetch/Request.h

@@ -67,7 +67,7 @@ class Request final
     JS_DECLARE_ALLOCATOR(Request);
 
 public:
-    [[nodiscard]] static JS::NonnullGCPtr<Request> create(JS::Realm&, JS::NonnullGCPtr<Infrastructure::Request>, Headers::Guard);
+    [[nodiscard]] static JS::NonnullGCPtr<Request> create(JS::Realm&, JS::NonnullGCPtr<Infrastructure::Request>, Headers::Guard, JS::NonnullGCPtr<DOM::AbortSignal>);
     static WebIDL::ExceptionOr<JS::NonnullGCPtr<Request>> construct_impl(JS::Realm&, RequestInfo const& input, RequestInit const& init = {});
 
     virtual ~Request() override;