Bug 1522288 - Start using microtask for img loading and img decode r=smaug

Differential Revision: https://phabricator.services.mozilla.com/D38717

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Sean Feng 2019-07-22 17:35:20 +00:00
Родитель 224562181c
Коммит cb9b749a6c
2 изменённых файлов: 20 добавлений и 11 удалений

Просмотреть файл

@ -43,6 +43,7 @@
#include "mozAutoDocUpdate.h" #include "mozAutoDocUpdate.h"
#include "mozilla/AsyncEventDispatcher.h" #include "mozilla/AsyncEventDispatcher.h"
#include "mozilla/AutoRestore.h" #include "mozilla/AutoRestore.h"
#include "mozilla/CycleCollectedJSContext.h"
#include "mozilla/EventStateManager.h" #include "mozilla/EventStateManager.h"
#include "mozilla/EventStates.h" #include "mozilla/EventStates.h"
#include "mozilla/dom/Element.h" #include "mozilla/dom/Element.h"
@ -352,18 +353,22 @@ already_AddRefed<Promise> nsImageLoadingContent::QueueDecodeAsync(
return nullptr; return nullptr;
} }
class QueueDecodeTask final : public Runnable { class QueueDecodeTask final : public MicroTaskRunnable {
public: public:
QueueDecodeTask(nsImageLoadingContent* aOwner, Promise* aPromise, QueueDecodeTask(nsImageLoadingContent* aOwner, Promise* aPromise,
uint32_t aRequestGeneration) uint32_t aRequestGeneration)
: Runnable("nsImageLoadingContent::QueueDecodeTask"), : MicroTaskRunnable(),
mOwner(aOwner), mOwner(aOwner),
mPromise(aPromise), mPromise(aPromise),
mRequestGeneration(aRequestGeneration) {} mRequestGeneration(aRequestGeneration) {}
NS_IMETHOD Run() override { virtual void Run(AutoSlowOperation& aAso) override {
mOwner->DecodeAsync(std::move(mPromise), mRequestGeneration); mOwner->DecodeAsync(std::move(mPromise), mRequestGeneration);
return NS_OK; }
virtual bool Suppressed() override {
nsIGlobalObject* global = mOwner->GetOurOwnerDoc()->GetScopeObject();
return global && global->IsInSyncOperation();
} }
private: private:
@ -378,13 +383,12 @@ already_AddRefed<Promise> nsImageLoadingContent::QueueDecodeAsync(
} }
auto task = MakeRefPtr<QueueDecodeTask>(this, promise, mRequestGeneration); auto task = MakeRefPtr<QueueDecodeTask>(this, promise, mRequestGeneration);
nsContentUtils::RunInStableState(task.forget()); CycleCollectedJSContext::Get()->DispatchToMicroTask(task.forget());
return promise.forget(); return promise.forget();
} }
void nsImageLoadingContent::DecodeAsync(RefPtr<Promise>&& aPromise, void nsImageLoadingContent::DecodeAsync(RefPtr<Promise>&& aPromise,
uint32_t aRequestGeneration) { uint32_t aRequestGeneration) {
MOZ_ASSERT(nsContentUtils::IsInStableOrMetaStableState());
MOZ_ASSERT(aPromise); MOZ_ASSERT(aPromise);
MOZ_ASSERT(mOutstandingDecodePromises > mDecodePromises.Length()); MOZ_ASSERT(mOutstandingDecodePromises > mDecodePromises.Length());

Просмотреть файл

@ -41,6 +41,7 @@
#include "imgRequestProxy.h" #include "imgRequestProxy.h"
#include "nsILoadGroup.h" #include "nsILoadGroup.h"
#include "mozilla/CycleCollectedJSContext.h"
#include "mozilla/EventDispatcher.h" #include "mozilla/EventDispatcher.h"
#include "mozilla/EventStates.h" #include "mozilla/EventStates.h"
@ -75,11 +76,11 @@ namespace dom {
// Calls LoadSelectedImage on host element unless it has been superseded or // Calls LoadSelectedImage on host element unless it has been superseded or
// canceled -- this is the synchronous section of "update the image data". // canceled -- this is the synchronous section of "update the image data".
// https://html.spec.whatwg.org/multipage/embedded-content.html#update-the-image-data // https://html.spec.whatwg.org/multipage/embedded-content.html#update-the-image-data
class ImageLoadTask : public Runnable { class ImageLoadTask : public MicroTaskRunnable {
public: public:
ImageLoadTask(HTMLImageElement* aElement, bool aAlwaysLoad, ImageLoadTask(HTMLImageElement* aElement, bool aAlwaysLoad,
bool aUseUrgentStartForChannel) bool aUseUrgentStartForChannel)
: Runnable("dom::ImageLoadTask"), : MicroTaskRunnable(),
mElement(aElement), mElement(aElement),
mAlwaysLoad(aAlwaysLoad), mAlwaysLoad(aAlwaysLoad),
mUseUrgentStartForChannel(aUseUrgentStartForChannel) { mUseUrgentStartForChannel(aUseUrgentStartForChannel) {
@ -87,14 +88,18 @@ class ImageLoadTask : public Runnable {
mDocument->BlockOnload(); mDocument->BlockOnload();
} }
NS_IMETHOD Run() override { virtual void Run(AutoSlowOperation& aAso) override {
if (mElement->mPendingImageLoadTask == this) { if (mElement->mPendingImageLoadTask == this) {
mElement->mPendingImageLoadTask = nullptr; mElement->mPendingImageLoadTask = nullptr;
mElement->mUseUrgentStartForChannel = mUseUrgentStartForChannel; mElement->mUseUrgentStartForChannel = mUseUrgentStartForChannel;
mElement->LoadSelectedImage(true, true, mAlwaysLoad); mElement->LoadSelectedImage(true, true, mAlwaysLoad);
} }
mDocument->UnblockOnload(false); mDocument->UnblockOnload(false);
return NS_OK; }
virtual bool Suppressed() override {
nsIGlobalObject* global = mElement->GetOwnerGlobal();
return global && global->IsInSyncOperation();
} }
bool AlwaysLoad() { return mAlwaysLoad; } bool AlwaysLoad() { return mAlwaysLoad; }
@ -790,7 +795,7 @@ void HTMLImageElement::QueueImageLoadTask(bool aAlwaysLoad) {
// The task checks this to determine if it was the last // The task checks this to determine if it was the last
// queued event, and so earlier tasks are implicitly canceled. // queued event, and so earlier tasks are implicitly canceled.
mPendingImageLoadTask = task; mPendingImageLoadTask = task;
nsContentUtils::RunInStableState(task.forget()); CycleCollectedJSContext::Get()->DispatchToMicroTask(task.forget());
} }
bool HTMLImageElement::HaveSrcsetOrInPicture() { bool HTMLImageElement::HaveSrcsetOrInPicture() {