LibWeb: Propagate OOM in Body::fully_read() through its error callback

Fetched bodies can be on the order of gigabytes, so rather than crashing
when we hit OOM here, we can simply invoke the error callback with a DOM
exception. We use "UnknownError" here as the spec directly supports this
for OOM errors:

    UnknownError: The operation failed for an unknown transient reason
                  (e.g. out of memory).

This is still an ad-hoc implementation. We should be using streams, and
we do have the AOs available to do so. But they need to be massaged to
be compatible with callers of Body::fully_read. And once we do use
streams, this function will become infallible - so making it infallible
here is at least a step in the right direction.
This commit is contained in:
Timothy Flynn 2024-04-26 14:57:40 -04:00 committed by Andreas Kling
commit 1ffda6a805
Notes: sideshowbarker 2024-07-16 18:03:21 +09:00
10 changed files with 39 additions and 42 deletions

View file

@ -98,11 +98,10 @@ static WebIDL::ExceptionOr<JS::NonnullGCPtr<DOM::Document>> load_markdown_docume
});
navigation_params.response->body()->fully_read(
realm,
process_body,
process_body_error,
JS::NonnullGCPtr { realm.global_object() })
.release_value_but_fixme_should_propagate_errors();
realm,
process_body,
process_body_error,
JS::NonnullGCPtr { realm.global_object() });
});
}
@ -174,7 +173,7 @@ static WebIDL::ExceptionOr<JS::NonnullGCPtr<DOM::Document>> load_html_document(H
});
auto& realm = document->realm();
TRY(navigation_params.response->body()->fully_read(realm, process_body, process_body_error, JS::NonnullGCPtr { realm.global_object() }));
navigation_params.response->body()->fully_read(realm, process_body, process_body_error, JS::NonnullGCPtr { realm.global_object() });
}
// 4. Return document.
@ -265,7 +264,7 @@ static WebIDL::ExceptionOr<JS::NonnullGCPtr<DOM::Document>> load_xml_document(HT
});
auto& realm = document->realm();
TRY(navigation_params.response->body()->fully_read(realm, process_body, process_body_error, JS::NonnullGCPtr { realm.global_object() }));
navigation_params.response->body()->fully_read(realm, process_body, process_body_error, JS::NonnullGCPtr { realm.global_object() });
return document;
}
@ -328,7 +327,7 @@ static WebIDL::ExceptionOr<JS::NonnullGCPtr<DOM::Document>> load_text_document(H
});
auto& realm = document->realm();
TRY(navigation_params.response->body()->fully_read(realm, process_body, process_body_error, JS::NonnullGCPtr { realm.global_object() }));
navigation_params.response->body()->fully_read(realm, process_body, process_body_error, JS::NonnullGCPtr { realm.global_object() });
// 6. Return document.
return document;
@ -416,11 +415,11 @@ static WebIDL::ExceptionOr<JS::NonnullGCPtr<DOM::Document>> load_media_document(
// However, if we don't, then we get stuck in HTMLParser::the_end() waiting for the media file to load, which
// never happens.
auto& realm = document->realm();
TRY(navigation_params.response->body()->fully_read(
navigation_params.response->body()->fully_read(
realm,
JS::create_heap_function(document->heap(), [document](ByteBuffer) { HTML::HTMLParser::the_end(document); }),
JS::create_heap_function(document->heap(), [](JS::GCPtr<WebIDL::DOMException>) {}),
JS::NonnullGCPtr { realm.global_object() }));
JS::NonnullGCPtr { realm.global_object() });
// 9. Return document.
return document;