mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-24 05:11:16 +00:00
Bug 1501794 - Implement img decode API. r=bzbarsky,tnikkel
The img decode API allows a web author to request that an image be decoded at its intrinsic size and be notified when it has been completed. This is useful to ensure an image is ready to display before adding it to the DOM tree -- this will help reduce flickering. Differential Revision: https://phabricator.services.mozilla.com/D11362
This commit is contained in:
parent
1a0c72f193
commit
dbfad894d9
@ -4301,6 +4301,13 @@ static void NotifyActivityChanged(nsISupports* aSupports, void* aUnused) {
|
||||
do_QueryInterface(aSupports));
|
||||
if (objectDocumentActivity) {
|
||||
objectDocumentActivity->NotifyOwnerDocumentActivityChanged();
|
||||
} else {
|
||||
nsCOMPtr<nsIImageLoadingContent> imageLoadingContent(
|
||||
do_QueryInterface(aSupports));
|
||||
if (imageLoadingContent) {
|
||||
auto ilc = static_cast<nsImageLoadingContent*>(imageLoadingContent.get());
|
||||
ilc->NotifyOwnerDocumentActivityChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -164,3 +164,8 @@ DOM4_MSG_DEF(InvalidStateError, "responseXML is only available if responseType i
|
||||
DOM4_MSG_DEF(InvalidStateError, "responseText is only available if responseType is '' or 'text'.", NS_ERROR_DOM_INVALID_STATE_XHR_HAS_WRONG_RESPONSETYPE_FOR_RESPONSETEXT)
|
||||
DOM4_MSG_DEF(InvalidStateError, "synchronous XMLHttpRequests do not support 'moz-chunked-arraybuffer' responseType.", NS_ERROR_DOM_INVALID_STATE_XHR_CHUNKED_RESPONSETYPES_UNSUPPORTED_FOR_SYNC)
|
||||
DOM4_MSG_DEF(InvalidAccessError, "synchronous XMLHttpRequests do not support timeout and responseType.", NS_ERROR_DOM_INVALID_ACCESS_XHR_TIMEOUT_AND_RESPONSETYPE_UNSUPPORTED_FOR_SYNC)
|
||||
|
||||
/* Image decode errors. */
|
||||
DOM4_MSG_DEF(EncodingError, "Node bound to inactive document.", NS_ERROR_DOM_IMAGE_INACTIVE_DOCUMENT)
|
||||
DOM4_MSG_DEF(EncodingError, "Invalid image request.", NS_ERROR_DOM_IMAGE_INVALID_REQUEST)
|
||||
DOM4_MSG_DEF(EncodingError, "Invalid encoded image data.", NS_ERROR_DOM_IMAGE_BROKEN)
|
||||
|
@ -95,6 +95,8 @@ nsImageLoadingContent::nsImageLoadingContent()
|
||||
: mCurrentRequestFlags(0),
|
||||
mPendingRequestFlags(0),
|
||||
mObserverList(nullptr),
|
||||
mOutstandingDecodePromises(0),
|
||||
mRequestGeneration(0),
|
||||
mImageBlockingStatus(nsIContentPolicy::ACCEPT),
|
||||
mLoadingEnabled(true),
|
||||
mIsImageStateForced(false),
|
||||
@ -120,17 +122,21 @@ nsImageLoadingContent::nsImageLoadingContent()
|
||||
void nsImageLoadingContent::DestroyImageLoadingContent() {
|
||||
// Cancel our requests so they won't hold stale refs to us
|
||||
// NB: Don't ask to discard the images here.
|
||||
RejectDecodePromises(NS_ERROR_DOM_IMAGE_INVALID_REQUEST);
|
||||
ClearCurrentRequest(NS_BINDING_ABORTED);
|
||||
ClearPendingRequest(NS_BINDING_ABORTED);
|
||||
}
|
||||
|
||||
nsImageLoadingContent::~nsImageLoadingContent() {
|
||||
NS_ASSERTION(!mCurrentRequest && !mPendingRequest,
|
||||
"DestroyImageLoadingContent not called");
|
||||
NS_ASSERTION(!mObserverList.mObserver && !mObserverList.mNext,
|
||||
"Observers still registered?");
|
||||
NS_ASSERTION(mScriptedObservers.IsEmpty(),
|
||||
"Scripted observers still registered?");
|
||||
MOZ_ASSERT(!mCurrentRequest && !mPendingRequest,
|
||||
"DestroyImageLoadingContent not called");
|
||||
MOZ_ASSERT(!mObserverList.mObserver && !mObserverList.mNext,
|
||||
"Observers still registered?");
|
||||
MOZ_ASSERT(mScriptedObservers.IsEmpty(),
|
||||
"Scripted observers still registered?");
|
||||
MOZ_ASSERT(mOutstandingDecodePromises == 0,
|
||||
"Decode promises still unfulfilled?");
|
||||
MOZ_ASSERT(mDecodePromises.IsEmpty(), "Decode promises still unfulfilled?");
|
||||
}
|
||||
|
||||
/*
|
||||
@ -204,6 +210,11 @@ nsImageLoadingContent::Notify(imgIRequest* aRequest, int32_t aType,
|
||||
return OnLoadComplete(aRequest, status);
|
||||
}
|
||||
|
||||
if (aType == imgINotificationObserver::FRAME_COMPLETE &&
|
||||
mCurrentRequest == aRequest) {
|
||||
MaybeResolveDecodePromises();
|
||||
}
|
||||
|
||||
if (aType == imgINotificationObserver::DECODE_COMPLETE) {
|
||||
nsCOMPtr<imgIContainer> container;
|
||||
aRequest->GetImage(getter_AddRefs(container));
|
||||
@ -260,6 +271,7 @@ nsresult nsImageLoadingContent::OnLoadComplete(imgIRequest* aRequest,
|
||||
nsCOMPtr<nsINode> thisNode =
|
||||
do_QueryInterface(static_cast<nsIImageLoadingContent*>(this));
|
||||
SVGObserverUtils::InvalidateDirectRenderingObservers(thisNode->AsElement());
|
||||
MaybeResolveDecodePromises();
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
@ -334,6 +346,166 @@ void nsImageLoadingContent::SetLoadingEnabled(bool aLoadingEnabled) {
|
||||
}
|
||||
}
|
||||
|
||||
already_AddRefed<Promise> nsImageLoadingContent::QueueDecodeAsync(
|
||||
ErrorResult& aRv) {
|
||||
Document* doc = GetOurOwnerDoc();
|
||||
RefPtr<Promise> promise = Promise::Create(doc->GetScopeObject(), aRv);
|
||||
if (aRv.Failed()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
class QueueDecodeTask final : public Runnable {
|
||||
public:
|
||||
QueueDecodeTask(nsImageLoadingContent* aOwner, Promise* aPromise,
|
||||
uint32_t aRequestGeneration)
|
||||
: Runnable("nsImageLoadingContent::QueueDecodeTask"),
|
||||
mOwner(aOwner),
|
||||
mPromise(aPromise),
|
||||
mRequestGeneration(aRequestGeneration) {}
|
||||
|
||||
NS_IMETHOD Run() override {
|
||||
mOwner->DecodeAsync(std::move(mPromise), mRequestGeneration);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
private:
|
||||
RefPtr<nsImageLoadingContent> mOwner;
|
||||
RefPtr<Promise> mPromise;
|
||||
uint32_t mRequestGeneration;
|
||||
};
|
||||
|
||||
if (++mOutstandingDecodePromises == 1) {
|
||||
MOZ_ASSERT(mDecodePromises.IsEmpty());
|
||||
doc->RegisterActivityObserver(this);
|
||||
}
|
||||
|
||||
auto task = MakeRefPtr<QueueDecodeTask>(this, promise, mRequestGeneration);
|
||||
nsContentUtils::RunInStableState(task.forget());
|
||||
return promise.forget();
|
||||
}
|
||||
|
||||
void nsImageLoadingContent::DecodeAsync(RefPtr<Promise>&& aPromise,
|
||||
uint32_t aRequestGeneration) {
|
||||
MOZ_ASSERT(nsContentUtils::IsInStableOrMetaStableState());
|
||||
MOZ_ASSERT(aPromise);
|
||||
MOZ_ASSERT(mOutstandingDecodePromises > mDecodePromises.Length());
|
||||
|
||||
// The request may have gotten updated since the decode call was issued.
|
||||
if (aRequestGeneration != mRequestGeneration) {
|
||||
aPromise->MaybeReject(NS_ERROR_DOM_IMAGE_INVALID_REQUEST);
|
||||
// We never got placed in mDecodePromises, so we must ensure we decrement
|
||||
// the counter explicitly.
|
||||
--mOutstandingDecodePromises;
|
||||
MaybeDeregisterActivityObserver();
|
||||
return;
|
||||
}
|
||||
|
||||
bool wasEmpty = mDecodePromises.IsEmpty();
|
||||
mDecodePromises.AppendElement(std::move(aPromise));
|
||||
if (wasEmpty) {
|
||||
MaybeResolveDecodePromises();
|
||||
}
|
||||
}
|
||||
|
||||
void nsImageLoadingContent::MaybeResolveDecodePromises() {
|
||||
if (mDecodePromises.IsEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!mCurrentRequest) {
|
||||
RejectDecodePromises(NS_ERROR_DOM_IMAGE_INVALID_REQUEST);
|
||||
return;
|
||||
}
|
||||
|
||||
// Only can resolve if our document is the active document. If not we are
|
||||
// supposed to reject the promise, even if it was fulfilled successfully.
|
||||
if (!GetOurOwnerDoc()->IsCurrentActiveDocument()) {
|
||||
RejectDecodePromises(NS_ERROR_DOM_IMAGE_INACTIVE_DOCUMENT);
|
||||
return;
|
||||
}
|
||||
|
||||
// If any error occurred while decoding, we need to reject first.
|
||||
uint32_t status = imgIRequest::STATUS_NONE;
|
||||
mCurrentRequest->GetImageStatus(&status);
|
||||
if (status & imgIRequest::STATUS_ERROR) {
|
||||
RejectDecodePromises(NS_ERROR_DOM_IMAGE_BROKEN);
|
||||
return;
|
||||
}
|
||||
|
||||
// We need the size to bother with requesting a decode, as we are either
|
||||
// blocked on validation or metadata decoding.
|
||||
if (!(status & imgIRequest::STATUS_SIZE_AVAILABLE)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Check the surface cache status and/or request decoding begin. We do this
|
||||
// before LOAD_COMPLETE because we want to start as soon as possible.
|
||||
uint32_t flags = imgIContainer::FLAG_HIGH_QUALITY_SCALING |
|
||||
imgIContainer::FLAG_AVOID_REDECODE_FOR_SIZE;
|
||||
if (!mCurrentRequest->RequestDecodeWithResult(flags)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// We can only fulfill the promises once we have all the data.
|
||||
if (!(status & imgIRequest::STATUS_LOAD_COMPLETE)) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (auto& promise : mDecodePromises) {
|
||||
promise->MaybeResolveWithUndefined();
|
||||
}
|
||||
|
||||
MOZ_ASSERT(mOutstandingDecodePromises >= mDecodePromises.Length());
|
||||
mOutstandingDecodePromises -= mDecodePromises.Length();
|
||||
mDecodePromises.Clear();
|
||||
MaybeDeregisterActivityObserver();
|
||||
}
|
||||
|
||||
void nsImageLoadingContent::RejectDecodePromises(nsresult aStatus) {
|
||||
if (mDecodePromises.IsEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (auto& promise : mDecodePromises) {
|
||||
promise->MaybeReject(aStatus);
|
||||
}
|
||||
|
||||
MOZ_ASSERT(mOutstandingDecodePromises >= mDecodePromises.Length());
|
||||
mOutstandingDecodePromises -= mDecodePromises.Length();
|
||||
mDecodePromises.Clear();
|
||||
MaybeDeregisterActivityObserver();
|
||||
}
|
||||
|
||||
void nsImageLoadingContent::MaybeAgeRequestGeneration(nsIURI* aNewURI) {
|
||||
MOZ_ASSERT(mCurrentRequest);
|
||||
|
||||
// If the current request is about to change, we need to verify if the new
|
||||
// URI matches the existing current request's URI. If it doesn't, we need to
|
||||
// reject any outstanding promises due to the current request mutating as per
|
||||
// step 2.2 of the decode API requirements.
|
||||
//
|
||||
// https://html.spec.whatwg.org/multipage/embedded-content.html#dom-img-decode
|
||||
if (aNewURI) {
|
||||
nsCOMPtr<nsIURI> currentURI;
|
||||
mCurrentRequest->GetURI(getter_AddRefs(currentURI));
|
||||
|
||||
bool equal = false;
|
||||
if (NS_SUCCEEDED(aNewURI->Equals(currentURI, &equal)) && equal) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
++mRequestGeneration;
|
||||
RejectDecodePromises(NS_ERROR_DOM_IMAGE_INVALID_REQUEST);
|
||||
}
|
||||
|
||||
void nsImageLoadingContent::MaybeDeregisterActivityObserver() {
|
||||
if (mOutstandingDecodePromises == 0) {
|
||||
MOZ_ASSERT(mDecodePromises.IsEmpty());
|
||||
GetOurOwnerDoc()->UnregisterActivityObserver(this);
|
||||
}
|
||||
}
|
||||
|
||||
void nsImageLoadingContent::SetSyncDecodingHint(bool aHint) {
|
||||
if (mSyncDecodingHint == aHint) {
|
||||
return;
|
||||
@ -786,6 +958,15 @@ nsImageLoadingContent::LoadImageWithChannel(nsIChannel* aChannel,
|
||||
// Shouldn't that be done before the start of the load?
|
||||
// XXX what about shouldProcess?
|
||||
|
||||
// If we have a current request without a size, we know we will replace it
|
||||
// with the PrepareNextRequest below. If the new current request is for a
|
||||
// different URI, then we need to reject any outstanding promises.
|
||||
if (mCurrentRequest && !HaveSize(mCurrentRequest)) {
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
aChannel->GetOriginalURI(getter_AddRefs(uri));
|
||||
MaybeAgeRequestGeneration(uri);
|
||||
}
|
||||
|
||||
// Our state might change. Watch it.
|
||||
AutoStateChanger changer(this, true);
|
||||
|
||||
@ -944,6 +1125,13 @@ nsresult nsImageLoadingContent::LoadImage(nsIURI* aNewURI, bool aForce,
|
||||
}
|
||||
}
|
||||
|
||||
// If we have a current request without a size, we know we will replace it
|
||||
// with the PrepareNextRequest below. If the new current request is for a
|
||||
// different URI, then we need to reject any outstanding promises.
|
||||
if (mCurrentRequest && !HaveSize(mCurrentRequest)) {
|
||||
MaybeAgeRequestGeneration(aNewURI);
|
||||
}
|
||||
|
||||
// From this point on, our image state could change. Watch it.
|
||||
AutoStateChanger changer(this, aNotify);
|
||||
|
||||
@ -1120,11 +1308,13 @@ void nsImageLoadingContent::UpdateImageState(bool aNotify) {
|
||||
} else if (!mCurrentRequest) {
|
||||
// No current request means error, since we weren't disabled or suppressed
|
||||
mBroken = true;
|
||||
RejectDecodePromises(NS_ERROR_DOM_IMAGE_BROKEN);
|
||||
} else {
|
||||
uint32_t currentLoadStatus;
|
||||
nsresult rv = mCurrentRequest->GetImageStatus(¤tLoadStatus);
|
||||
if (NS_FAILED(rv) || (currentLoadStatus & imgIRequest::STATUS_ERROR)) {
|
||||
mBroken = true;
|
||||
RejectDecodePromises(NS_ERROR_DOM_IMAGE_BROKEN);
|
||||
} else if (!(currentLoadStatus & imgIRequest::STATUS_SIZE_AVAILABLE)) {
|
||||
mLoading = true;
|
||||
}
|
||||
@ -1135,6 +1325,7 @@ void nsImageLoadingContent::UpdateImageState(bool aNotify) {
|
||||
}
|
||||
|
||||
void nsImageLoadingContent::CancelImageRequests(bool aNotify) {
|
||||
RejectDecodePromises(NS_ERROR_DOM_IMAGE_INVALID_REQUEST);
|
||||
AutoStateChanger changer(this, aNotify);
|
||||
ClearPendingRequest(NS_BINDING_ABORTED, Some(OnNonvisible::DISCARD_IMAGES));
|
||||
ClearCurrentRequest(NS_BINDING_ABORTED, Some(OnNonvisible::DISCARD_IMAGES));
|
||||
@ -1183,6 +1374,7 @@ nsresult nsImageLoadingContent::FireEvent(const nsAString& aEventType,
|
||||
bool aIsCancelable) {
|
||||
if (nsContentUtils::DocumentInactiveForImageLoads(GetOurOwnerDoc())) {
|
||||
// Don't bother to fire any events, especially error events.
|
||||
RejectDecodePromises(NS_ERROR_DOM_IMAGE_INACTIVE_DOCUMENT);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -1315,6 +1507,13 @@ class ImageRequestAutoLock {
|
||||
void nsImageLoadingContent::MakePendingRequestCurrent() {
|
||||
MOZ_ASSERT(mPendingRequest);
|
||||
|
||||
// If we have a pending request, we know that there is an existing current
|
||||
// request with size information. If the pending request is for a different
|
||||
// URI, then we need to reject any outstanding promises.
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
mPendingRequest->GetURI(getter_AddRefs(uri));
|
||||
MaybeAgeRequestGeneration(uri);
|
||||
|
||||
// Lock mCurrentRequest for the duration of this method. We do this because
|
||||
// PrepareCurrentRequest() might unlock mCurrentRequest. If mCurrentRequest
|
||||
// and mPendingRequest are both requests for the same image, unlocking
|
||||
@ -1408,6 +1607,12 @@ bool nsImageLoadingContent::HaveSize(imgIRequest* aImage) {
|
||||
return (NS_SUCCEEDED(rv) && (status & imgIRequest::STATUS_SIZE_AVAILABLE));
|
||||
}
|
||||
|
||||
void nsImageLoadingContent::NotifyOwnerDocumentActivityChanged() {
|
||||
if (!GetOurOwnerDoc()->IsCurrentActiveDocument()) {
|
||||
RejectDecodePromises(NS_ERROR_DOM_IMAGE_INACTIVE_DOCUMENT);
|
||||
}
|
||||
}
|
||||
|
||||
void nsImageLoadingContent::BindToTree(Document* aDocument, nsIContent* aParent,
|
||||
nsIContent* aBindingParent) {
|
||||
// We may be getting connected, if so our image should be tracked,
|
||||
|
@ -23,6 +23,7 @@
|
||||
#include "mozilla/ErrorResult.h"
|
||||
#include "nsIContentPolicy.h"
|
||||
#include "mozilla/dom/BindingDeclarations.h"
|
||||
#include "mozilla/dom/Promise.h"
|
||||
#include "mozilla/net/ReferrerPolicy.h"
|
||||
#include "nsAttrValue.h"
|
||||
|
||||
@ -82,6 +83,12 @@ class nsImageLoadingContent : public nsIImageLoadingContent {
|
||||
*/
|
||||
void SetSyncDecodingHint(bool aHint);
|
||||
|
||||
/**
|
||||
* Notify us that the document state has changed. Called by nsDocument so that
|
||||
* we may reject any promises which require the document to be active.
|
||||
*/
|
||||
void NotifyOwnerDocumentActivityChanged();
|
||||
|
||||
protected:
|
||||
enum ImageLoadType {
|
||||
// Most normal image loads
|
||||
@ -230,6 +237,18 @@ class nsImageLoadingContent : public nsIImageLoadingContent {
|
||||
uint32_t NaturalWidth();
|
||||
uint32_t NaturalHeight();
|
||||
|
||||
/**
|
||||
* Create a promise and queue a microtask which will ensure the current
|
||||
* request (after any pending loads are applied) has requested a full decode.
|
||||
* The promise is fulfilled once the request has a fully decoded surface that
|
||||
* is available for drawing, or an error condition occurrs (e.g. broken image,
|
||||
* current request is updated, etc).
|
||||
*
|
||||
* https://html.spec.whatwg.org/multipage/embedded-content.html#dom-img-decode
|
||||
*/
|
||||
already_AddRefed<mozilla::dom::Promise> QueueDecodeAsync(
|
||||
mozilla::ErrorResult& aRv);
|
||||
|
||||
enum class ImageDecodingType : uint8_t {
|
||||
Auto,
|
||||
Async,
|
||||
@ -240,6 +259,38 @@ class nsImageLoadingContent : public nsIImageLoadingContent {
|
||||
static const nsAttrValue::EnumTable* kDecodingTableDefault;
|
||||
|
||||
private:
|
||||
/**
|
||||
* Enqueue and/or fulfill a promise created by QueueDecodeAsync.
|
||||
*/
|
||||
void DecodeAsync(RefPtr<mozilla::dom::Promise>&& aPromise,
|
||||
uint32_t aRequestGeneration);
|
||||
|
||||
/**
|
||||
* Attempt to resolve all queued promises based on the state of the current
|
||||
* request. If the current request does not yet have all of the encoded data,
|
||||
* or the decoding has not yet completed, it will return without changing the
|
||||
* promise states.
|
||||
*/
|
||||
void MaybeResolveDecodePromises();
|
||||
|
||||
/**
|
||||
* Reject all queued promises with the given status.
|
||||
*/
|
||||
void RejectDecodePromises(nsresult aStatus);
|
||||
|
||||
/**
|
||||
* Age the generation counter if we have a new current request with a
|
||||
* different URI. If the generation counter is aged, then all queued promises
|
||||
* will also be rejected.
|
||||
*/
|
||||
void MaybeAgeRequestGeneration(nsIURI* aNewURI);
|
||||
|
||||
/**
|
||||
* Deregister as an observer for the owner document's activity notifications
|
||||
* if we have no outstanding decode promises.
|
||||
*/
|
||||
void MaybeDeregisterActivityObserver();
|
||||
|
||||
/**
|
||||
* Struct used to manage the native image observers.
|
||||
*/
|
||||
@ -483,6 +534,12 @@ class nsImageLoadingContent : public nsIImageLoadingContent {
|
||||
*/
|
||||
nsTArray<RefPtr<ScriptedImageObserver>> mScriptedObservers;
|
||||
|
||||
/**
|
||||
* Promises created by QueueDecodeAsync that are still waiting to be
|
||||
* fulfilled by the image being fully decoded.
|
||||
*/
|
||||
nsTArray<RefPtr<mozilla::dom::Promise>> mDecodePromises;
|
||||
|
||||
/**
|
||||
* When mIsImageStateForced is true, this holds the ImageState that we'll
|
||||
* return in ImageState().
|
||||
@ -491,6 +548,23 @@ class nsImageLoadingContent : public nsIImageLoadingContent {
|
||||
|
||||
mozilla::TimeStamp mMostRecentRequestChange;
|
||||
|
||||
/**
|
||||
* Total number of outstanding decode promises, including those stored in
|
||||
* mDecodePromises and those embedded in runnables waiting to be enqueued.
|
||||
* This is used to determine whether we need to register as an observer for
|
||||
* document activity notifications.
|
||||
*/
|
||||
size_t mOutstandingDecodePromises;
|
||||
|
||||
/**
|
||||
* An incrementing counter representing the current request generation;
|
||||
* Each time mCurrentRequest is modified with a different URI, this will
|
||||
* be incremented. Each QueueDecodeAsync call will cache the generation
|
||||
* of the current request so that when it is processed, it knows if it
|
||||
* should have rejected because the request changed.
|
||||
*/
|
||||
uint32_t mRequestGeneration;
|
||||
|
||||
int16_t mImageBlockingStatus;
|
||||
bool mLoadingEnabled : 1;
|
||||
|
||||
|
@ -499,6 +499,16 @@ already_AddRefed<nsINode> nsNodeUtils::CloneAndAdopt(
|
||||
nsObjectLoadingContent* olc =
|
||||
static_cast<nsObjectLoadingContent*>(objectLoadingContent.get());
|
||||
olc->NotifyOwnerDocumentActivityChanged();
|
||||
} else {
|
||||
// HTMLImageElement::FromNode is insufficient since we need this for
|
||||
// <svg:image> as well.
|
||||
nsCOMPtr<nsIImageLoadingContent> imageLoadingContent(
|
||||
do_QueryInterface(aNode));
|
||||
if (imageLoadingContent) {
|
||||
auto ilc =
|
||||
static_cast<nsImageLoadingContent*>(imageLoadingContent.get());
|
||||
ilc->NotifyOwnerDocumentActivityChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -927,6 +927,7 @@ void nsObjectLoadingContent::NotifyOwnerDocumentActivityChanged() {
|
||||
if (mInstanceOwner || mInstantiating) {
|
||||
QueueCheckPluginStopEvent();
|
||||
}
|
||||
nsImageLoadingContent::NotifyOwnerDocumentActivityChanged();
|
||||
}
|
||||
|
||||
// nsIRequestObserver
|
||||
|
@ -191,6 +191,10 @@ void HTMLImageElement::GetDecoding(nsAString& aValue) {
|
||||
GetEnumAttr(nsGkAtoms::decoding, kDecodingTableDefault->tag, aValue);
|
||||
}
|
||||
|
||||
already_AddRefed<Promise> HTMLImageElement::Decode(ErrorResult& aRv) {
|
||||
return nsImageLoadingContent::QueueDecodeAsync(aRv);
|
||||
}
|
||||
|
||||
bool HTMLImageElement::ParseAttribute(int32_t aNamespaceID, nsAtom* aAttribute,
|
||||
const nsAString& aValue,
|
||||
nsIPrincipal* aMaybeScriptedPrincipal,
|
||||
|
@ -180,6 +180,8 @@ class HTMLImageElement final : public nsGenericHTMLElement,
|
||||
}
|
||||
void GetDecoding(nsAString& aValue);
|
||||
|
||||
already_AddRefed<Promise> Decode(ErrorResult& aRv);
|
||||
|
||||
net::ReferrerPolicy GetImageReferrerPolicy() override {
|
||||
return GetReferrerPolicyAsEnum();
|
||||
}
|
||||
|
@ -101,6 +101,10 @@ void SVGImageElement::GetDecoding(nsAString& aValue) {
|
||||
GetEnumAttr(nsGkAtoms::decoding, kDecodingTableDefault->tag, aValue);
|
||||
}
|
||||
|
||||
already_AddRefed<Promise> SVGImageElement::Decode(ErrorResult& aRv) {
|
||||
return nsImageLoadingContent::QueueDecodeAsync(aRv);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
nsresult SVGImageElement::LoadSVGImage(bool aForce, bool aNotify) {
|
||||
|
@ -93,6 +93,8 @@ class SVGImageElement : public SVGImageElementBase,
|
||||
}
|
||||
void GetDecoding(nsAString& aValue);
|
||||
|
||||
already_AddRefed<Promise> Decode(ErrorResult& aRv);
|
||||
|
||||
protected:
|
||||
nsresult LoadSVGImage(bool aForce, bool aNotify);
|
||||
|
||||
|
@ -42,6 +42,8 @@ interface HTMLImageElement : HTMLElement {
|
||||
readonly attribute unsigned long naturalWidth;
|
||||
readonly attribute unsigned long naturalHeight;
|
||||
readonly attribute boolean complete;
|
||||
[NewObject]
|
||||
Promise<void> decode();
|
||||
};
|
||||
|
||||
// http://www.whatwg.org/specs/web-apps/current-work/#other-elements,-attributes-and-apis
|
||||
|
@ -23,6 +23,8 @@ interface SVGImageElement : SVGGraphicsElement {
|
||||
readonly attribute SVGAnimatedPreserveAspectRatio preserveAspectRatio;
|
||||
[CEReactions, SetterThrows]
|
||||
attribute DOMString decoding;
|
||||
[NewObject]
|
||||
Promise<void> decode();
|
||||
};
|
||||
|
||||
SVGImageElement implements MozImageLoadingContent;
|
||||
|
@ -225,6 +225,8 @@ DynamicImage::StartDecoding(uint32_t aFlags) { return NS_OK; }
|
||||
|
||||
bool DynamicImage::StartDecodingWithResult(uint32_t aFlags) { return true; }
|
||||
|
||||
bool DynamicImage::RequestDecodeWithResult(uint32_t aFlags) { return true; }
|
||||
|
||||
NS_IMETHODIMP
|
||||
DynamicImage::RequestDecodeForSize(const nsIntSize& aSize, uint32_t aFlags) {
|
||||
return NS_OK;
|
||||
|
@ -202,6 +202,10 @@ bool ImageWrapper::StartDecodingWithResult(uint32_t aFlags) {
|
||||
return mInnerImage->StartDecodingWithResult(aFlags);
|
||||
}
|
||||
|
||||
bool ImageWrapper::RequestDecodeWithResult(uint32_t aFlags) {
|
||||
return mInnerImage->RequestDecodeWithResult(aFlags);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
ImageWrapper::RequestDecodeForSize(const nsIntSize& aSize, uint32_t aFlags) {
|
||||
return mInnerImage->RequestDecodeForSize(aSize, aFlags);
|
||||
|
@ -339,9 +339,12 @@ LookupResult RasterImage::LookupFrame(const IntSize& aSize, uint32_t aFlags,
|
||||
return LookupResult(MatchType::NOT_FOUND);
|
||||
}
|
||||
|
||||
const bool syncDecode = aFlags & FLAG_SYNC_DECODE;
|
||||
const bool avoidRedecode = aFlags & FLAG_AVOID_REDECODE_FOR_SIZE;
|
||||
if (result.Type() == MatchType::NOT_FOUND ||
|
||||
result.Type() == MatchType::SUBSTITUTE_BECAUSE_NOT_FOUND ||
|
||||
((aFlags & FLAG_SYNC_DECODE) && !result)) {
|
||||
(result.Type() == MatchType::SUBSTITUTE_BECAUSE_NOT_FOUND &&
|
||||
!avoidRedecode) ||
|
||||
(syncDecode && !avoidRedecode && !result)) {
|
||||
// We don't have a copy of this frame, and there's no decoder working on
|
||||
// one. (Or we're sync decoding and the existing decoder hasn't even started
|
||||
// yet.) Trigger decoding so it'll be available next time.
|
||||
@ -353,15 +356,14 @@ LookupResult RasterImage::LookupFrame(const IntSize& aSize, uint32_t aFlags,
|
||||
// The surface cache may suggest the preferred size we are supposed to
|
||||
// decode at. This should only happen if we accept substitutions.
|
||||
if (!result.SuggestedSize().IsEmpty()) {
|
||||
MOZ_ASSERT(!(aFlags & FLAG_SYNC_DECODE) &&
|
||||
(aFlags & FLAG_HIGH_QUALITY_SCALING));
|
||||
MOZ_ASSERT(!syncDecode && (aFlags & FLAG_HIGH_QUALITY_SCALING));
|
||||
requestedSize = result.SuggestedSize();
|
||||
}
|
||||
|
||||
bool ranSync = Decode(requestedSize, aFlags, aPlaybackType);
|
||||
|
||||
// If we can or did sync decode, we should already have the frame.
|
||||
if (ranSync || (aFlags & FLAG_SYNC_DECODE)) {
|
||||
if (ranSync || syncDecode) {
|
||||
result =
|
||||
LookupFrameInternal(requestedSize, aFlags, aPlaybackType, aMarkUsed);
|
||||
}
|
||||
@ -375,7 +377,7 @@ LookupResult RasterImage::LookupFrame(const IntSize& aSize, uint32_t aFlags,
|
||||
// Sync decoding guarantees that we got the frame, but if it's owned by an
|
||||
// async decoder that's currently running, the contents of the frame may not
|
||||
// be available yet. Make sure we get everything.
|
||||
if (mAllSourceData && (aFlags & FLAG_SYNC_DECODE)) {
|
||||
if (mAllSourceData && syncDecode) {
|
||||
result.Surface()->WaitUntilFinished();
|
||||
}
|
||||
|
||||
@ -1078,6 +1080,18 @@ bool RasterImage::StartDecodingWithResult(uint32_t aFlags) {
|
||||
return surface && surface->IsFinished();
|
||||
}
|
||||
|
||||
bool RasterImage::RequestDecodeWithResult(uint32_t aFlags) {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
if (mError) {
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32_t flags = aFlags | FLAG_ASYNC_NOTIFY;
|
||||
DrawableSurface surface = RequestDecodeForSizeInternal(mSize, flags);
|
||||
return surface && surface->IsFinished();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
RasterImage::RequestDecodeForSize(const IntSize& aSize, uint32_t aFlags) {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
@ -1236,6 +1236,11 @@ bool VectorImage::StartDecodingWithResult(uint32_t aFlags) {
|
||||
return mIsFullyLoaded;
|
||||
}
|
||||
|
||||
bool VectorImage::RequestDecodeWithResult(uint32_t aFlags) {
|
||||
// SVG images are ready to draw when they are loaded
|
||||
return mIsFullyLoaded;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
VectorImage::RequestDecodeForSize(const nsIntSize& aSize, uint32_t aFlags) {
|
||||
// Nothing to do for SVG images, though in theory we could rasterize to the
|
||||
|
@ -209,6 +209,10 @@ interface imgIContainer : nsISupports
|
||||
* (a "window into SVG space") based on the border image area, and we need to
|
||||
* be sure we don't subsequently scale that viewport in a way that distorts
|
||||
* its contents by stretching them more in one dimension than the other.
|
||||
*
|
||||
* FLAG_AVOID_REDECODE_FOR_SIZE: If there is already a raster surface
|
||||
* available for this image, but it is not the same size as requested, skip
|
||||
* starting a new decode for said size.
|
||||
*/
|
||||
const unsigned long FLAG_NONE = 0x0;
|
||||
const unsigned long FLAG_SYNC_DECODE = 0x1;
|
||||
@ -222,6 +226,7 @@ interface imgIContainer : nsISupports
|
||||
const unsigned long FLAG_BYPASS_SURFACE_CACHE = 0x100;
|
||||
const unsigned long FLAG_FORCE_PRESERVEASPECTRATIO_NONE = 0x200;
|
||||
const unsigned long FLAG_FORCE_UNIFORM_SCALING = 0x400;
|
||||
const unsigned long FLAG_AVOID_REDECODE_FOR_SIZE = 0x800;
|
||||
|
||||
/**
|
||||
* A constant specifying the default set of decode flags (i.e., the default
|
||||
@ -472,6 +477,17 @@ interface imgIContainer : nsISupports
|
||||
*/
|
||||
[noscript, notxpcom] boolean startDecodingWithResult(in uint32_t aFlags);
|
||||
|
||||
/*
|
||||
* This method triggers decoding for an image, but unlike startDecoding() it
|
||||
* enables the caller to provide more detailed information about the decode
|
||||
* request.
|
||||
*
|
||||
* @param aFlags Flags of the FLAG_* variety.
|
||||
* @return True there is a surface that satisfies the request and it is
|
||||
* fully decoded, else false.
|
||||
*/
|
||||
[noscript, notxpcom] boolean requestDecodeWithResult(in uint32_t aFlags);
|
||||
|
||||
/*
|
||||
* This method triggers decoding for an image, but unlike startDecoding() it
|
||||
* enables the caller to provide more detailed information about the decode
|
||||
|
@ -163,9 +163,23 @@ interface imgIRequest : nsIRequest
|
||||
/**
|
||||
* Exactly like startDecoding above except returns whether the current frame
|
||||
* of the image is complete or not.
|
||||
*
|
||||
* @param aFlags Flags of the FLAG_* variety. Only FLAG_ASYNC_NOTIFY
|
||||
* is accepted; all others are ignored.
|
||||
*/
|
||||
[noscript, notxpcom] boolean startDecodingWithResult(in uint32_t aFlags);
|
||||
|
||||
/**
|
||||
* This method triggers decoding for an image, but unlike startDecoding() it
|
||||
* enables the caller to provide more detailed information about the decode
|
||||
* request.
|
||||
*
|
||||
* @param aFlags Flags of the FLAG_* variety.
|
||||
* @return True there is a surface that satisfies the request and it is
|
||||
* fully decoded, else false.
|
||||
*/
|
||||
[noscript, notxpcom] boolean requestDecodeWithResult(in uint32_t aFlags);
|
||||
|
||||
/**
|
||||
* Locks an image. If the image does not exist yet, locks it once it becomes
|
||||
* available. The lock persists for the lifetime of the imgIRequest (until
|
||||
|
@ -543,6 +543,24 @@ bool imgRequestProxy::StartDecodingWithResult(uint32_t aFlags) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool imgRequestProxy::RequestDecodeWithResult(uint32_t aFlags) {
|
||||
if (IsValidating()) {
|
||||
mDecodeRequested = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
RefPtr<Image> image = GetImage();
|
||||
if (image) {
|
||||
return image->RequestDecodeWithResult(aFlags);
|
||||
}
|
||||
|
||||
if (GetOwner()) {
|
||||
GetOwner()->StartDecoding();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
imgRequestProxy::LockImage() {
|
||||
mLockCount++;
|
||||
|
@ -477,15 +477,6 @@ prefs: [dom.security.featurePolicy.enabled:true]
|
||||
[HTMLBodyElement interface: document.createElement("body") must inherit property "onunhandledrejection" with the proper type]
|
||||
expected: FAIL
|
||||
|
||||
[HTMLImageElement interface: operation decode()]
|
||||
expected: FAIL
|
||||
|
||||
[HTMLImageElement interface: document.createElement("img") must inherit property "decode()" with the proper type]
|
||||
expected: FAIL
|
||||
|
||||
[HTMLImageElement interface: new Image() must inherit property "decode()" with the proper type]
|
||||
expected: FAIL
|
||||
|
||||
[HTMLIFrameElement interface: attribute allowUserMedia]
|
||||
expected: FAIL
|
||||
|
||||
|
@ -1,20 +1,8 @@
|
||||
[image-decode-iframe.html]
|
||||
expected:
|
||||
ERROR
|
||||
[(misc) Decode from removed iframe fails (loaded img)]
|
||||
expected: TIMEOUT
|
||||
|
||||
[(misc) Decode from removed iframe fails (img not loaded)]
|
||||
expected: NOTRUN
|
||||
|
||||
[(misc) Decode from iframe, later removed, fails (img not loaded)]
|
||||
expected: NOTRUN
|
||||
|
||||
[HTMLImageElement.prototype.decode(), iframe tests. Decode from removed iframe fails (loaded img)]
|
||||
expected: TIMEOUT
|
||||
expected: TIMEOUT
|
||||
|
||||
[HTMLImageElement.prototype.decode(), iframe tests. Decode from removed iframe fails (img not loaded)]
|
||||
expected: NOTRUN
|
||||
expected: TIMEOUT
|
||||
|
||||
[HTMLImageElement.prototype.decode(), iframe tests. Decode from iframe, later removed, fails (img not loaded)]
|
||||
expected: NOTRUN
|
||||
|
@ -1,19 +0,0 @@
|
||||
[image-decode-path-changes-svg.tentative.html]
|
||||
[SVGImageElement.prototype.decode(), href mutation tests. xlink:href changes fail decode.]
|
||||
expected: FAIL
|
||||
|
||||
[SVGImageElement.prototype.decode(), href mutation tests. href changes fail decode.]
|
||||
expected: FAIL
|
||||
|
||||
[SVGImageElement.prototype.decode(), href mutation tests. xlink:href changes fail decode; following good decode succeeds.]
|
||||
expected: FAIL
|
||||
|
||||
[SVGImageElement.prototype.decode(), href mutation tests. href changes fail decode; following good decode succeeds.]
|
||||
expected: FAIL
|
||||
|
||||
[SVGImageElement.prototype.decode(), href mutation tests. xlink:href changes fail decode; following bad decode fails.]
|
||||
expected: FAIL
|
||||
|
||||
[SVGImageElement.prototype.decode(), href mutation tests. href changes fail decode; following bad decode fails.]
|
||||
expected: FAIL
|
||||
|
@ -1,49 +0,0 @@
|
||||
[image-decode-path-changes.html]
|
||||
[(src) Path changes fail decode.]
|
||||
expected: FAIL
|
||||
|
||||
[(src) Path changes fail decode; following good decode succeeds.]
|
||||
expected: FAIL
|
||||
|
||||
[(src) Path changes fail decode; following bad decode fails.]
|
||||
expected: FAIL
|
||||
|
||||
[(src) Path changes to the same path succeed.]
|
||||
expected: FAIL
|
||||
|
||||
[(srcset) Path changes fail decode.]
|
||||
expected: FAIL
|
||||
|
||||
[(srcset) Path changes fail decode; following good decode succeeds.]
|
||||
expected: FAIL
|
||||
|
||||
[(srcset) Path changes fail decode; following bad decode fails.]
|
||||
expected: FAIL
|
||||
|
||||
[(srcset) Path changes to the same path succeed.]
|
||||
expected: FAIL
|
||||
|
||||
[HTMLImageElement.prototype.decode(), src/srcset mutation tests. src changes fail decode.]
|
||||
expected: FAIL
|
||||
|
||||
[HTMLImageElement.prototype.decode(), src/srcset mutation tests. src changes fail decode; following good png decode succeeds.]
|
||||
expected: FAIL
|
||||
|
||||
[HTMLImageElement.prototype.decode(), src/srcset mutation tests. src changes fail decode; following good svg decode succeeds.]
|
||||
expected: FAIL
|
||||
|
||||
[HTMLImageElement.prototype.decode(), src/srcset mutation tests. src changes fail decode; following bad decode fails.]
|
||||
expected: FAIL
|
||||
|
||||
[HTMLImageElement.prototype.decode(), src/srcset mutation tests. src changes to the same path succeed.]
|
||||
expected: FAIL
|
||||
|
||||
[HTMLImageElement.prototype.decode(), src/srcset mutation tests. srcset changes fail decode.]
|
||||
expected: FAIL
|
||||
|
||||
[HTMLImageElement.prototype.decode(), src/srcset mutation tests. srcset changes fail decode; following good decode succeeds.]
|
||||
expected: FAIL
|
||||
|
||||
[HTMLImageElement.prototype.decode(), src/srcset mutation tests. srcset changes fail decode; following bad decode fails.]
|
||||
expected: FAIL
|
||||
|
@ -1,25 +0,0 @@
|
||||
[image-decode-picture.html]
|
||||
[HTMLImageElement.prototype.decode(), picture tests. Image with PNG source decodes with undefined.]
|
||||
expected: FAIL
|
||||
|
||||
[HTMLImageElement.prototype.decode(), picture tests. Image with multiple sources decodes with undefined.]
|
||||
expected: FAIL
|
||||
|
||||
[HTMLImageElement.prototype.decode(), picture tests. Image with PNG data URL source decodes with undefined.]
|
||||
expected: FAIL
|
||||
|
||||
[HTMLImageElement.prototype.decode(), picture tests. Image with SVG source decodes with undefined.]
|
||||
expected: FAIL
|
||||
|
||||
[HTMLImageElement.prototype.decode(), picture tests. Non-existent source fails decode.]
|
||||
expected: FAIL
|
||||
|
||||
[HTMLImageElement.prototype.decode(), picture tests. Corrupt image in src fails decode.]
|
||||
expected: FAIL
|
||||
|
||||
[HTMLImageElement.prototype.decode(), picture tests. Image without srcset fails decode.]
|
||||
expected: FAIL
|
||||
|
||||
[HTMLImageElement.prototype.decode(), picture tests. Multiple decodes for images with src succeed.]
|
||||
expected: FAIL
|
||||
|
@ -1,40 +0,0 @@
|
||||
[image-decode-svg.tentative.html]
|
||||
[SVGImageElement.prototype.decode(), basic tests. Image with PNG xlink:href decodes with undefined.]
|
||||
expected: FAIL
|
||||
|
||||
[SVGImageElement.prototype.decode(), basic tests. Image with PNG href decodes with undefined.]
|
||||
expected: FAIL
|
||||
|
||||
[SVGImageElement.prototype.decode(), basic tests. Image with PNG data URL xlink:href decodes with undefined.]
|
||||
expected: FAIL
|
||||
|
||||
[SVGImageElement.prototype.decode(), basic tests. Image with PNG data URL href decodes with undefined.]
|
||||
expected: FAIL
|
||||
|
||||
[SVGImageElement.prototype.decode(), basic tests. Image with SVG xlink:href decodes with undefined.]
|
||||
expected: FAIL
|
||||
|
||||
[SVGImageElement.prototype.decode(), basic tests. Image with SVG href decodes with undefined.]
|
||||
expected: FAIL
|
||||
|
||||
[SVGImageElement.prototype.decode(), basic tests. Non-existent xlink:href fails decode.]
|
||||
expected: FAIL
|
||||
|
||||
[SVGImageElement.prototype.decode(), basic tests. Non-existent href fails decode.]
|
||||
expected: FAIL
|
||||
|
||||
[SVGImageElement.prototype.decode(), basic tests. Corrupt image in xlink:href fails decode.]
|
||||
expected: FAIL
|
||||
|
||||
[SVGImageElement.prototype.decode(), basic tests. Corrupt image in href fails decode.]
|
||||
expected: FAIL
|
||||
|
||||
[SVGImageElement.prototype.decode(), basic tests. Image without xlink:href or href fails decode.]
|
||||
expected: FAIL
|
||||
|
||||
[SVGImageElement.prototype.decode(), basic tests. Multiple decodes with a xlink:href succeed.]
|
||||
expected: FAIL
|
||||
|
||||
[SVGImageElement.prototype.decode(), basic tests. Multiple decodes with a href succeed.]
|
||||
expected: FAIL
|
||||
|
@ -1,4 +0,0 @@
|
||||
[image-decode-with-quick-attach-svg.tentative.html]
|
||||
[SVGImageElement.prototype.decode(), attach to DOM before promise resolves.]
|
||||
expected: FAIL
|
||||
|
@ -1,4 +0,0 @@
|
||||
[image-decode-with-quick-attach.html]
|
||||
[HTMLImageElement.prototype.decode(), attach to DOM before promise resolves.]
|
||||
expected: FAIL
|
||||
|
@ -1,76 +0,0 @@
|
||||
[image-decode.html]
|
||||
[(src) PNG image decodes with undefined.]
|
||||
expected: FAIL
|
||||
|
||||
[(src) PNG url image decodes with undefined.]
|
||||
expected: FAIL
|
||||
|
||||
[(src) SVG image decodes with undefined.]
|
||||
expected: FAIL
|
||||
|
||||
[(src) Non-existent path fails decode.]
|
||||
expected: FAIL
|
||||
|
||||
[(src) Corrupt image fails decode.]
|
||||
expected: FAIL
|
||||
|
||||
[(src) Path-less image fails decode.]
|
||||
expected: FAIL
|
||||
|
||||
[(src) Multiple decodes succeed.]
|
||||
expected: FAIL
|
||||
|
||||
[(srcset) PNG image decodes with undefined.]
|
||||
expected: FAIL
|
||||
|
||||
[(srcset) SVG image decodes with undefined.]
|
||||
expected: FAIL
|
||||
|
||||
[(srcset) Non-existent path fails decode.]
|
||||
expected: FAIL
|
||||
|
||||
[(srcset) Multiple decodes succeed.]
|
||||
expected: FAIL
|
||||
|
||||
[HTMLImageElement.prototype.decode(), basic tests. Image with PNG src decodes with undefined.]
|
||||
expected: FAIL
|
||||
|
||||
[HTMLImageElement.prototype.decode(), basic tests. Image with PNG data URL src decodes with undefined.]
|
||||
expected: FAIL
|
||||
|
||||
[HTMLImageElement.prototype.decode(), basic tests. Image with SVG src decodes with undefined.]
|
||||
expected: FAIL
|
||||
|
||||
[HTMLImageElement.prototype.decode(), basic tests. Non-existent src fails decode.]
|
||||
expected: FAIL
|
||||
|
||||
[HTMLImageElement.prototype.decode(), basic tests. Inactive document fails decode.]
|
||||
expected: FAIL
|
||||
|
||||
[HTMLImageElement.prototype.decode(), basic tests. Adopted active image into inactive document fails decode.]
|
||||
expected: FAIL
|
||||
|
||||
[HTMLImageElement.prototype.decode(), basic tests. Adopted inactive image into active document succeeds.]
|
||||
expected: FAIL
|
||||
|
||||
[HTMLImageElement.prototype.decode(), basic tests. Corrupt image in src fails decode.]
|
||||
expected: FAIL
|
||||
|
||||
[HTMLImageElement.prototype.decode(), basic tests. Image without src/srcset fails decode.]
|
||||
expected: FAIL
|
||||
|
||||
[HTMLImageElement.prototype.decode(), basic tests. Multiple decodes for images with src succeed.]
|
||||
expected: FAIL
|
||||
|
||||
[HTMLImageElement.prototype.decode(), basic tests. Image with PNG srcset decodes with undefined.]
|
||||
expected: FAIL
|
||||
|
||||
[HTMLImageElement.prototype.decode(), basic tests. Image with SVG srcset decodes with undefined.]
|
||||
expected: FAIL
|
||||
|
||||
[HTMLImageElement.prototype.decode(), basic tests. Non-existent srcset fails decode.]
|
||||
expected: FAIL
|
||||
|
||||
[HTMLImageElement.prototype.decode(), basic tests. Multiple decodes for images with srcset succeed.]
|
||||
expected: FAIL
|
||||
|
@ -642,6 +642,11 @@ with modules["DOM"]:
|
||||
# decoding process.
|
||||
errors["NS_ERROR_DOM_JS_DECODING_ERROR"] = FAILURE(1026)
|
||||
|
||||
# Image decode errors.
|
||||
errors["NS_ERROR_DOM_IMAGE_INACTIVE_DOCUMENT"] = FAILURE(1027)
|
||||
errors["NS_ERROR_DOM_IMAGE_INVALID_REQUEST"] = FAILURE(1028)
|
||||
errors["NS_ERROR_DOM_IMAGE_BROKEN"] = FAILURE(1029)
|
||||
|
||||
# May be used to indicate when e.g. setting a property value didn't
|
||||
# actually change the value, like for obj.foo = "bar"; obj.foo = "bar";
|
||||
# the second assignment throws NS_SUCCESS_DOM_NO_OPERATION.
|
||||
|
Loading…
Reference in New Issue
Block a user