LibWeb: Implement HTMLImageElement::decode with a few FIXMEs
Implements enough of HTMLImageElement::decode for it to not break websites and actually load an image :)
This commit is contained in:
parent
7b67fa706f
commit
862fc91b2c
Notes:
sideshowbarker
2024-07-17 10:39:39 +09:00
Author: https://github.com/Enverbalalic Commit: https://github.com/LadybirdBrowser/ladybird/commit/862fc91b2c Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/66
3 changed files with 86 additions and 1 deletions
|
@ -26,9 +26,11 @@
|
|||
#include <LibWeb/HTML/ListOfAvailableImages.h>
|
||||
#include <LibWeb/HTML/Parser/HTMLParser.h>
|
||||
#include <LibWeb/HTML/PotentialCORSRequest.h>
|
||||
#include <LibWeb/HTML/Scripting/TemporaryExecutionContext.h>
|
||||
#include <LibWeb/Layout/ImageBox.h>
|
||||
#include <LibWeb/Loader/ResourceLoader.h>
|
||||
#include <LibWeb/Painting/PaintableBox.h>
|
||||
#include <LibWeb/Platform/EventLoopPlugin.h>
|
||||
#include <LibWeb/Platform/ImageCodecPlugin.h>
|
||||
#include <LibWeb/SVG/SVGDecodedImageData.h>
|
||||
|
||||
|
@ -276,6 +278,86 @@ String HTMLImageElement::current_src() const
|
|||
return MUST(m_current_request->current_url().to_string());
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/embedded-content.html#dom-img-decode
|
||||
WebIDL::ExceptionOr<JS::NonnullGCPtr<JS::Promise>> HTMLImageElement::decode() const
|
||||
{
|
||||
auto& realm = this->realm();
|
||||
|
||||
// 1. Let promise be a new promise.
|
||||
auto promise = WebIDL::create_promise(realm);
|
||||
|
||||
// 2. Queue a microtask to perform the following steps:
|
||||
queue_a_microtask(&document(), JS::create_heap_function(realm.heap(), [this, promise, &realm]() mutable {
|
||||
auto reject_if_document_not_fully_active = [this, promise, &realm]() -> bool {
|
||||
if (this->document().is_fully_active())
|
||||
return false;
|
||||
|
||||
auto exception = WebIDL::EncodingError::create(realm, "Node document not fully active"_fly_string);
|
||||
WebIDL::reject_promise(realm, promise, exception);
|
||||
return true;
|
||||
};
|
||||
|
||||
auto reject_if_current_request_state_broken = [this, promise, &realm]() {
|
||||
if (this->current_request().state() != ImageRequest::State::Broken)
|
||||
return false;
|
||||
|
||||
auto exception = WebIDL::EncodingError::create(realm, "Current request state is broken"_fly_string);
|
||||
WebIDL::reject_promise(realm, promise, exception);
|
||||
return true;
|
||||
};
|
||||
|
||||
// 2.1 If any of the following are true:
|
||||
// 2.1.1 this's node document is not fully active;
|
||||
// 2.1.1 then reject promise with an "EncodingError" DOMException.
|
||||
if (reject_if_document_not_fully_active())
|
||||
return;
|
||||
|
||||
// 2.1.2 or this's current request's state is broken,
|
||||
// 2.1.2 then reject promise with an "EncodingError" DOMException.
|
||||
if (reject_if_current_request_state_broken())
|
||||
return;
|
||||
|
||||
// 2.2 Otherwise, in parallel wait for one of the following cases to occur, and perform the corresponding actions:
|
||||
Platform::EventLoopPlugin::the().deferred_invoke([this, promise, &realm, reject_if_document_not_fully_active, reject_if_current_request_state_broken] {
|
||||
Platform::EventLoopPlugin::the().spin_until([&] {
|
||||
auto state = this->current_request().state();
|
||||
|
||||
return !this->document().is_fully_active() || state == ImageRequest::State::Broken || state == ImageRequest::State::CompletelyAvailable;
|
||||
});
|
||||
|
||||
// 2.2.1 This img element's node document stops being fully active
|
||||
// 2.2.1 Reject promise with an "EncodingError" DOMException.
|
||||
if (reject_if_document_not_fully_active())
|
||||
return;
|
||||
|
||||
// FIXME: 2.2.2 This img element's current request changes or is mutated
|
||||
// FIXME: 2.2.2 Reject promise with an "EncodingError" DOMException.
|
||||
|
||||
// 2.2.3 This img element's current request's state becomes broken
|
||||
// 2.2.3 Reject promise with an "EncodingError" DOMException.
|
||||
if (reject_if_current_request_state_broken())
|
||||
return;
|
||||
|
||||
// 2.2.4 This img element's current request's state becomes completely available
|
||||
if (this->current_request().state() == ImageRequest::State::CompletelyAvailable) {
|
||||
// 2.2.4.1 FIXME: Decode the image.
|
||||
// 2.2.4.2 FIXME: If decoding does not need to be performed for this image (for example because it is a vector graphic), resolve promise with undefined.
|
||||
// 2.2.4.3 FIXME: If decoding fails (for example due to invalid image data), reject promise with an "EncodingError" DOMException.
|
||||
// 2.2.4.4 FIXME: If the decoding process completes successfully, resolve promise with undefined.
|
||||
// 2.2.4.5 FIXME: User agents should ensure that the decoded media data stays readily available until at least the end of the next successful update
|
||||
// the rendering step in the event loop. This is an important part of the API contract, and should not be broken if at all possible.
|
||||
// (Typically, this would only be violated in low-memory situations that require evicting decoded image data, or when the image is too large
|
||||
// to keep in decoded form for this period of time.)
|
||||
|
||||
HTML::TemporaryExecutionContext execution_context { Bindings::host_defined_environment_settings_object(realm) };
|
||||
WebIDL::resolve_promise(realm, promise, JS::js_undefined());
|
||||
}
|
||||
});
|
||||
}));
|
||||
|
||||
return JS::NonnullGCPtr { verify_cast<JS::Promise>(*promise->promise()) };
|
||||
}
|
||||
|
||||
Optional<ARIA::Role> HTMLImageElement::default_role() const
|
||||
{
|
||||
// https://www.w3.org/TR/html-aria/#el-img
|
||||
|
|
|
@ -60,6 +60,9 @@ public:
|
|||
// https://html.spec.whatwg.org/multipage/embedded-content.html#dom-img-currentsrc
|
||||
String current_src() const;
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/embedded-content.html#dom-img-decode
|
||||
[[nodiscard]] WebIDL::ExceptionOr<JS::NonnullGCPtr<JS::Promise>> decode() const;
|
||||
|
||||
virtual Optional<ARIA::Role> default_role() const override;
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/images.html#img-environment-changes
|
||||
|
|
|
@ -25,7 +25,7 @@ interface HTMLImageElement : HTMLElement {
|
|||
[CEReactions, Enumerated=LazyLoadingAttribute, Reflect] attribute DOMString loading;
|
||||
[CEReactions, Enumerated=FetchPriorityAttribute, Reflect=fetchpriority] attribute DOMString fetchPriority;
|
||||
|
||||
[FIXME] Promise<undefined> decode();
|
||||
Promise<undefined> decode();
|
||||
|
||||
// Obsolete
|
||||
[CEReactions, Reflect] attribute DOMString name;
|
||||
|
|
Loading…
Add table
Reference in a new issue