1
0
Fork 0
mirror of https://github.com/LadybirdBrowser/ladybird.git synced 2025-06-09 09:34:57 +09:00

LibWeb: Remove exception handling from safely extracting response bodies

The entire purpose of this AO is to avoid handling exceptions, which we
can do now that the underlying AOs do not throw exceptions on OOM.
This commit is contained in:
Timothy Flynn 2024-11-04 16:06:01 +01:00 committed by Andrew Kaster
parent 49ff5eb4d8
commit 953fe75271
Notes: github-actions[bot] 2024-12-10 03:04:18 +00:00
8 changed files with 33 additions and 34 deletions

View file

@ -23,7 +23,7 @@
namespace Web::Fetch {
// https://fetch.spec.whatwg.org/#bodyinit-safely-extract
WebIDL::ExceptionOr<Infrastructure::BodyWithType> safely_extract_body(JS::Realm& realm, BodyInitOrReadableBytes const& object)
Infrastructure::BodyWithType safely_extract_body(JS::Realm& realm, BodyInitOrReadableBytes const& object)
{
// 1. If object is a ReadableStream object, then:
if (auto const* stream = object.get_pointer<GC::Root<Streams::ReadableStream>>()) {
@ -32,7 +32,7 @@ WebIDL::ExceptionOr<Infrastructure::BodyWithType> safely_extract_body(JS::Realm&
}
// 2. Return the result of extracting object.
return extract_body(realm, object);
return MUST(extract_body(realm, object));
}
// https://fetch.spec.whatwg.org/#concept-bodyinit-extract

View file

@ -17,7 +17,7 @@ namespace Web::Fetch {
using BodyInit = Variant<GC::Root<Streams::ReadableStream>, GC::Root<FileAPI::Blob>, GC::Root<WebIDL::BufferSource>, GC::Root<XHR::FormData>, GC::Root<DOMURL::URLSearchParams>, String>;
using BodyInitOrReadableBytes = Variant<GC::Root<Streams::ReadableStream>, GC::Root<FileAPI::Blob>, GC::Root<WebIDL::BufferSource>, GC::Root<XHR::FormData>, GC::Root<DOMURL::URLSearchParams>, String, ReadonlyBytes>;
WebIDL::ExceptionOr<Infrastructure::BodyWithType> safely_extract_body(JS::Realm&, BodyInitOrReadableBytes const&);
Infrastructure::BodyWithType safely_extract_body(JS::Realm&, BodyInitOrReadableBytes const&);
WebIDL::ExceptionOr<Infrastructure::BodyWithType> extract_body(JS::Realm&, BodyInitOrReadableBytes const&, bool keepalive = false);
}

View file

@ -122,7 +122,7 @@ WebIDL::ExceptionOr<GC::Ref<Infrastructure::FetchController>> fetch(JS::Realm& r
// 8. If requests body is a byte sequence, then set requests body to requests body as a body.
if (auto const* buffer = request.body().get_pointer<ByteBuffer>())
request.set_body(TRY(Infrastructure::byte_sequence_as_body(realm, buffer->bytes())));
request.set_body(Infrastructure::byte_sequence_as_body(realm, buffer->bytes()));
// 9. If requests window is "client", then set requests window to requests client, if requests clients global
// object is a Window object; otherwise "no-window".
@ -576,7 +576,7 @@ WebIDL::ExceptionOr<GC::Ptr<PendingResponse>> main_fetch(JS::Realm& realm, Infra
}
// 2. Set responses body to bytes as a body.
response->set_body(TRY_OR_IGNORE(Infrastructure::byte_sequence_as_body(realm, bytes)));
response->set_body(Infrastructure::byte_sequence_as_body(realm, bytes));
// 3. Run fetch response handover given fetchParams and response.
fetch_response_handover(realm, fetch_params, *response);
@ -807,7 +807,7 @@ WebIDL::ExceptionOr<GC::Ref<PendingResponse>> scheme_fetch(JS::Realm& realm, Inf
auto header = Infrastructure::Header::from_string_pair("Content-Type"sv, "text/html;charset=utf-8"sv);
response->header_list()->append(move(header));
response->set_body(MUST(Infrastructure::byte_sequence_as_body(realm, ""sv.bytes())));
response->set_body(Infrastructure::byte_sequence_as_body(realm, ""sv.bytes()));
return PendingResponse::create(vm, request, response);
}
@ -845,13 +845,13 @@ WebIDL::ExceptionOr<GC::Ref<PendingResponse>> scheme_fetch(JS::Realm& realm, Inf
// 8. If requests header list does not contain `Range`:
if (!request->header_list()->contains("Range"sv.bytes())) {
// 1. Let bodyWithType be the result of safely extracting blob.
auto body_with_type = TRY(safely_extract_body(realm, blob->raw_bytes()));
auto body_with_type = safely_extract_body(realm, blob->raw_bytes());
// 2. Set responses status message to `OK`.
response->set_status_message(MUST(ByteBuffer::copy("OK"sv.bytes())));
// 3. Set responses body to bodyWithTypes body.
response->set_body(move(body_with_type.body));
response->set_body(body_with_type.body);
// 4. Set responses header list to « (`Content-Length`, serializedFullLength), (`Content-Type`, type) ».
auto content_length_header = Infrastructure::Header::from_string_pair("Content-Length"sv, serialized_full_length);
@ -903,7 +903,7 @@ WebIDL::ExceptionOr<GC::Ref<PendingResponse>> scheme_fetch(JS::Realm& realm, Inf
auto sliced_blob = TRY(blob->slice(*range_start, *range_end + 1, type));
// 9. Let slicedBodyWithType be the result of safely extracting slicedBlob.
auto sliced_body_with_type = TRY(safely_extract_body(realm, sliced_blob->raw_bytes()));
auto sliced_body_with_type = safely_extract_body(realm, sliced_blob->raw_bytes());
// 10. Set responses body to slicedBodyWithTypes body.
response->set_body(sliced_body_with_type.body);
@ -958,7 +958,7 @@ WebIDL::ExceptionOr<GC::Ref<PendingResponse>> scheme_fetch(JS::Realm& realm, Inf
auto header = Infrastructure::Header::from_string_pair("Content-Type"sv, mime_type);
response->header_list()->append(move(header));
response->set_body(TRY(Infrastructure::byte_sequence_as_body(realm, data_url_struct.value().body)));
response->set_body(Infrastructure::byte_sequence_as_body(realm, data_url_struct.value().body));
return PendingResponse::create(vm, request, response);
}
// -> "file"
@ -1308,8 +1308,8 @@ WebIDL::ExceptionOr<GC::Ptr<PendingResponse>> http_redirect_fetch(JS::Realm& rea
auto converted_source = source.has<ByteBuffer>()
? BodyInitOrReadableBytes { source.get<ByteBuffer>() }
: BodyInitOrReadableBytes { source.get<GC::Root<FileAPI::Blob>>() };
auto [body, _] = TRY(safely_extract_body(realm, converted_source));
request->set_body(move(body));
auto [body, _] = safely_extract_body(realm, converted_source);
request->set_body(body);
}
// 15. Let timingInfo be fetchParamss timing info.
@ -2107,8 +2107,8 @@ WebIDL::ExceptionOr<GC::Ref<PendingResponse>> http_network_or_cache_fetch(JS::Re
auto converted_source = source.has<ByteBuffer>()
? BodyInitOrReadableBytes { source.get<ByteBuffer>() }
: BodyInitOrReadableBytes { source.get<GC::Root<FileAPI::Blob>>() };
auto [body, _] = TRY_OR_IGNORE(safely_extract_body(realm, converted_source));
request->set_body(move(body));
auto [body, _] = safely_extract_body(realm, converted_source);
request->set_body(body);
}
// 3. If requests use-URL-credentials flag is unset or isAuthenticationFetch is true, then:

View file

@ -134,10 +134,10 @@ void Body::incrementally_read_loop(Streams::ReadableStreamDefaultReader& reader,
}
// https://fetch.spec.whatwg.org/#byte-sequence-as-a-body
WebIDL::ExceptionOr<GC::Ref<Body>> byte_sequence_as_body(JS::Realm& realm, ReadonlyBytes bytes)
GC::Ref<Body> byte_sequence_as_body(JS::Realm& realm, ReadonlyBytes bytes)
{
// To get a byte sequence bytes as a body, return the body of the result of safely extracting bytes.
auto [body, _] = TRY(safely_extract_body(realm, bytes));
auto [body, _] = safely_extract_body(realm, bytes);
return body;
}

View file

@ -76,6 +76,6 @@ struct BodyWithType {
Optional<ByteBuffer> type;
};
WebIDL::ExceptionOr<GC::Ref<Body>> byte_sequence_as_body(JS::Realm&, ReadonlyBytes);
GC::Ref<Body> byte_sequence_as_body(JS::Realm&, ReadonlyBytes);
}

View file

@ -618,7 +618,8 @@ static GC::Ptr<DOM::Document> attempt_to_create_a_non_fetch_scheme_document(NonF
}
// https://html.spec.whatwg.org/multipage/browsing-the-web.html#create-navigation-params-from-a-srcdoc-resource
static WebIDL::ExceptionOr<GC::Ref<NavigationParams>> create_navigation_params_from_a_srcdoc_resource(GC::Ptr<SessionHistoryEntry> entry, GC::Ptr<Navigable> navigable, TargetSnapshotParams const& target_snapshot_params, Optional<String> navigation_id)
static GC::Ref<NavigationParams> create_navigation_params_from_a_srcdoc_resource(GC::Ptr<SessionHistoryEntry> entry, GC::Ptr<Navigable> navigable, TargetSnapshotParams const& target_snapshot_params, Optional<String> navigation_id)
{
auto& vm = navigable->vm();
VERIFY(navigable->active_window());
@ -638,7 +639,7 @@ static WebIDL::ExceptionOr<GC::Ref<NavigationParams>> create_navigation_params_f
auto header = Fetch::Infrastructure::Header::from_string_pair("Content-Type"sv, "text/html"sv);
response->header_list()->append(move(header));
response->set_body(TRY(Fetch::Infrastructure::byte_sequence_as_body(realm, document_resource.get<String>().bytes())));
response->set_body(Fetch::Infrastructure::byte_sequence_as_body(realm, document_resource.get<String>().bytes()));
// 3. Let responseOrigin be the result of determining the origin given response's URL, targetSnapshotParams's sandboxing flags, and entry's document state's origin.
auto response_origin = determine_the_origin(response->url(), target_snapshot_params.sandboxing_flags, entry->document_state()->origin());
@ -1100,7 +1101,7 @@ WebIDL::ExceptionOr<void> Navigable::populate_session_history_entry_document(
// of creating navigation params from a srcdoc resource given entry, navigable,
// targetSnapshotParams, navigationId, and navTimingType.
if (document_resource.has<String>()) {
navigation_params = TRY(create_navigation_params_from_a_srcdoc_resource(entry, this, target_snapshot_params, navigation_id));
navigation_params = create_navigation_params_from_a_srcdoc_resource(entry, this, target_snapshot_params, navigation_id);
}
// 2. Otherwise, if all of the following are true:
// - entry's URL's scheme is a fetch scheme; and
@ -1377,7 +1378,7 @@ WebIDL::ExceptionOr<void> Navigable::navigate(NavigateParams params)
// 1. Queue a global task on the navigation and traversal task source given navigable's active window to navigate to a javascript: URL given navigable, url, historyHandling, initiatorOriginSnapshot, and cspNavigationType.
VERIFY(active_window());
queue_global_task(Task::Source::NavigationAndTraversal, *active_window(), GC::create_function(heap(), [this, url, history_handling, initiator_origin_snapshot, csp_navigation_type, navigation_id] {
(void)navigate_to_a_javascript_url(url, to_history_handling_behavior(history_handling), initiator_origin_snapshot, csp_navigation_type, navigation_id);
navigate_to_a_javascript_url(url, to_history_handling_behavior(history_handling), initiator_origin_snapshot, csp_navigation_type, navigation_id);
}));
// 2. Return.
@ -1604,7 +1605,7 @@ WebIDL::ExceptionOr<void> Navigable::navigate_to_a_fragment(URL::URL const& url,
// https://html.spec.whatwg.org/multipage/browsing-the-web.html#evaluate-a-javascript:-url
// https://whatpr.org/html/9893/browsing-the-web.html#evaluate-a-javascript:-url
WebIDL::ExceptionOr<GC::Ptr<DOM::Document>> Navigable::evaluate_javascript_url(URL::URL const& url, URL::Origin const& new_document_origin, String navigation_id)
GC::Ptr<DOM::Document> Navigable::evaluate_javascript_url(URL::URL const& url, URL::Origin const& new_document_origin, String navigation_id)
{
auto& vm = this->vm();
VERIFY(active_window());
@ -1652,7 +1653,7 @@ WebIDL::ExceptionOr<GC::Ptr<DOM::Document>> Navigable::evaluate_javascript_url(U
auto header = Fetch::Infrastructure::Header::from_string_pair("Content-Type"sv, "text/html"sv);
response->header_list()->append(move(header));
response->set_body(TRY(Fetch::Infrastructure::byte_sequence_as_body(realm, result.bytes())));
response->set_body(Fetch::Infrastructure::byte_sequence_as_body(realm, result.bytes()));
// 12. Let policyContainer be targetNavigable's active document's policy container.
auto const& policy_container = active_document()->policy_container();
@ -1708,7 +1709,7 @@ WebIDL::ExceptionOr<GC::Ptr<DOM::Document>> Navigable::evaluate_javascript_url(U
}
// https://html.spec.whatwg.org/multipage/browsing-the-web.html#navigate-to-a-javascript:-url
WebIDL::ExceptionOr<void> Navigable::navigate_to_a_javascript_url(URL::URL const& url, HistoryHandlingBehavior history_handling, URL::Origin const& initiator_origin, CSPNavigationType csp_navigation_type, String navigation_id)
void Navigable::navigate_to_a_javascript_url(URL::URL const& url, HistoryHandlingBehavior history_handling, URL::Origin const& initiator_origin, CSPNavigationType csp_navigation_type, String navigation_id)
{
// 1. Assert: historyHandling is "replace".
VERIFY(history_handling == HistoryHandlingBehavior::Replace);
@ -1718,7 +1719,7 @@ WebIDL::ExceptionOr<void> Navigable::navigate_to_a_javascript_url(URL::URL const
// 3. If initiatorOrigin is not same origin-domain with targetNavigable's active document's origin, then return.
if (!initiator_origin.is_same_origin_domain(active_document()->origin()))
return {};
return;
// FIXME: 4. Let request be a new request whose URL is url.
@ -1726,12 +1727,12 @@ WebIDL::ExceptionOr<void> Navigable::navigate_to_a_javascript_url(URL::URL const
(void)csp_navigation_type;
// 6. Let newDocument be the result of evaluating a javascript: URL given targetNavigable, url, and initiatorOrigin.
auto new_document = TRY(evaluate_javascript_url(url, initiator_origin, navigation_id));
auto new_document = evaluate_javascript_url(url, initiator_origin, navigation_id);
// 7. If newDocument is null, then return.
if (!new_document) {
// NOTE: In this case, some JavaScript code was executed, but no new Document was created, so we will not perform a navigation.
return {};
return;
}
// 8. Assert: initiatorOrigin is newDocument's origin.
@ -1776,8 +1777,6 @@ WebIDL::ExceptionOr<void> Navigable::navigate_to_a_javascript_url(URL::URL const
traversable_navigable()->append_session_history_traversal_steps(GC::create_function(heap(), [this, history_entry, history_handling, navigation_id] {
finalize_a_cross_document_navigation(*this, history_handling, history_entry);
}));
return {};
}
// https://html.spec.whatwg.org/multipage/browsing-the-web.html#reload

View file

@ -156,8 +156,8 @@ public:
WebIDL::ExceptionOr<void> navigate_to_a_fragment(URL::URL const&, HistoryHandlingBehavior, UserNavigationInvolvement, Optional<SerializationRecord> navigation_api_state, String navigation_id);
WebIDL::ExceptionOr<GC::Ptr<DOM::Document>> evaluate_javascript_url(URL::URL const&, URL::Origin const& new_document_origin, String navigation_id);
WebIDL::ExceptionOr<void> navigate_to_a_javascript_url(URL::URL const&, HistoryHandlingBehavior, URL::Origin const& initiator_origin, CSPNavigationType csp_navigation_type, String navigation_id);
GC::Ptr<DOM::Document> evaluate_javascript_url(URL::URL const&, URL::Origin const& new_document_origin, String navigation_id);
void navigate_to_a_javascript_url(URL::URL const&, HistoryHandlingBehavior, URL::Origin const& initiator_origin, CSPNavigationType csp_navigation_type, String navigation_id);
bool allowed_by_sandboxing_to_navigate(Navigable const& target, SourceSnapshotParams const&);

View file

@ -574,15 +574,15 @@ WebIDL::ExceptionOr<void> XMLHttpRequest::send(Optional<DocumentOrXMLHttpRequest
// 2. If body is a Document, then set thiss request body to body, serialized, converted, and UTF-8 encoded.
if (body->has<GC::Root<DOM::Document>>()) {
auto string_serialized_document = TRY(body->get<GC::Root<DOM::Document>>().cell()->serialize_fragment(DOMParsing::RequireWellFormed::No));
m_request_body = TRY(Fetch::Infrastructure::byte_sequence_as_body(realm, string_serialized_document.bytes()));
m_request_body = Fetch::Infrastructure::byte_sequence_as_body(realm, string_serialized_document.bytes());
}
// 3. Otherwise:
else {
// 1. Let bodyWithType be the result of safely extracting body.
auto body_with_type = TRY(Fetch::safely_extract_body(realm, body->downcast<Fetch::BodyInitOrReadableBytes>()));
auto body_with_type = Fetch::safely_extract_body(realm, body->downcast<Fetch::BodyInitOrReadableBytes>());
// 2. Set thiss request body to bodyWithTypes body.
m_request_body = move(body_with_type.body);
m_request_body = body_with_type.body;
// 3. Set extractedContentType to bodyWithTypes type.
extracted_content_type = move(body_with_type.type);