LibWeb/Fetch: Deserialize abort reason

Deserialize the fetch controllers abort reason according to the spec.
Currently fetch does not support a scenario where this actually happens.
This commit is contained in:
Glenn Skrzypczak 2024-11-24 20:37:13 +01:00 committed by Jelle Raaijmakers
commit b263cd11f7
Notes: github-actions[bot] 2024-12-16 11:44:20 +00:00
3 changed files with 66 additions and 12 deletions

View file

@ -96,7 +96,27 @@ void FetchController::abort(JS::Realm& realm, Optional<JS::Value> error)
m_serialized_abort_reason = structured_serialize(realm.vm(), error.value(), fallback_error);
}
// FIXME: https://fetch.spec.whatwg.org/#deserialize-a-serialized-abort-reason
// https://fetch.spec.whatwg.org/#deserialize-a-serialized-abort-reason
JS::Value FetchController::deserialize_a_serialized_abort_reason(JS::Realm& realm)
{
// 1. Let fallbackError be an "AbortError" DOMException.
auto fallback_error = WebIDL::AbortError::create(realm, "Fetch was aborted"_string);
// 2. Let deserializedError be fallbackError.
JS::Value deserialized_error = fallback_error;
// 3. If abortReason is non-null, then set deserializedError to StructuredDeserialize(abortReason, realm).
// If that threw an exception or returned undefined, then set deserializedError to fallbackError.
if (m_serialized_abort_reason.has_value()) {
auto deserialized_error_or_exception = HTML::structured_deserialize(realm.vm(), m_serialized_abort_reason.value(), realm, {});
if (!deserialized_error_or_exception.is_exception() && !deserialized_error_or_exception.value().is_undefined()) {
deserialized_error = deserialized_error_or_exception.value();
}
}
// 4. Return deserializedError.
return deserialized_error;
}
// https://fetch.spec.whatwg.org/#fetch-controller-terminate
void FetchController::terminate()
@ -137,4 +157,19 @@ void FetchController::fetch_task_complete(u64 fetch_task_id)
m_ongoing_fetch_tasks.remove(fetch_task_id);
}
GC_DEFINE_ALLOCATOR(FetchControllerHolder);
FetchControllerHolder::FetchControllerHolder() = default;
GC::Ref<FetchControllerHolder> FetchControllerHolder::create(JS::VM& vm)
{
return vm.heap().allocate<FetchControllerHolder>();
}
void FetchControllerHolder::visit_edges(JS::Cell::Visitor& visitor)
{
Base::visit_edges(visitor);
visitor.visit(m_controller);
}
}

View file

@ -44,6 +44,7 @@ public:
void process_next_manual_redirect() const;
[[nodiscard]] GC::Ref<FetchTimingInfo> extract_full_timing_info() const;
void abort(JS::Realm&, Optional<JS::Value>);
JS::Value deserialize_a_serialized_abort_reason(JS::Realm&);
void terminate();
void set_fetch_params(Badge<FetchParams>, GC::Ref<FetchParams> fetch_params) { m_fetch_params = fetch_params; }
@ -77,7 +78,7 @@ private:
// https://fetch.spec.whatwg.org/#fetch-controller-report-timing-steps
// serialized abort reason (default null)
// Null or a Record (result of StructuredSerialize).
HTML::SerializationRecord m_serialized_abort_reason;
Optional<HTML::SerializationRecord> m_serialized_abort_reason;
// https://fetch.spec.whatwg.org/#fetch-controller-next-manual-redirect-steps
// next manual redirect steps (default null)
@ -90,4 +91,22 @@ private:
u64 m_next_fetch_task_id { 0 };
};
class FetchControllerHolder : public JS::Cell {
GC_CELL(FetchControllerHolder, JS::Cell);
GC_DECLARE_ALLOCATOR(FetchControllerHolder);
public:
static GC::Ref<FetchControllerHolder> create(JS::VM&);
[[nodiscard]] GC::Ptr<FetchController> const& controller() const { return m_controller; }
void set_controller(GC::Ref<FetchController> controller) { m_controller = controller; }
private:
FetchControllerHolder();
virtual void visit_edges(Cell::Visitor&) override;
GC::Ptr<FetchController> m_controller;
};
}