Bug 1259482 - Ensure that image loads are never dropped on the floor when queued for later. r=johns
authorJosh Matthews <josh@joshmatthews.net>
Wed, 30 Mar 2016 12:39:59 -0400
changeset 290906 5df20795af1438c88a7997255e52ac44ec07047e
parent 290905 7c4258b493b12d00a89276c41a5f39cdcf28d2fc
child 290907 25ff944d5dc9454055426d021889fb700b8ff55a
push id74427
push userjosh@joshmatthews.net
push dateWed, 30 Mar 2016 16:40:42 +0000
treeherdermozilla-inbound@5df20795af14 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjohns
bugs1259482
milestone48.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1259482 - Ensure that image loads are never dropped on the floor when queued for later. r=johns
dom/html/HTMLImageElement.cpp
dom/html/HTMLImageElement.h
dom/html/reftests/reftest.list
dom/html/reftests/responsive-image-load-shortcircuit-ref.html
dom/html/reftests/responsive-image-load-shortcircuit.html
--- a/dom/html/HTMLImageElement.cpp
+++ b/dom/html/HTMLImageElement.cpp
@@ -93,16 +93,20 @@ public:
     if (mElement->mPendingImageLoadTask == this) {
       mElement->mPendingImageLoadTask = nullptr;
       mElement->LoadSelectedImage(true, true, mAlwaysLoad);
     }
     mDocument->UnblockOnload(false);
     return NS_OK;
   }
 
+  bool AlwaysLoad() {
+    return mAlwaysLoad;
+  }
+
 private:
   ~ImageLoadTask() {}
   RefPtr<HTMLImageElement> mElement;
   nsCOMPtr<nsIDocument> mDocument;
   bool mAlwaysLoad;
 };
 
 HTMLImageElement::HTMLImageElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo)
@@ -894,17 +898,23 @@ void
 HTMLImageElement::QueueImageLoadTask(bool aAlwaysLoad)
 {
   // If loading is temporarily disabled, we don't want to queue tasks
   // that may then run when loading is re-enabled.
   if (!LoadingEnabled() || !this->OwnerDoc()->IsCurrentActiveDocument()) {
     return;
   }
 
-  nsCOMPtr<nsIRunnable> task = new ImageLoadTask(this, aAlwaysLoad);
+  // Ensure that we don't overwrite a previous load request that requires
+  // a complete load to occur.
+  bool alwaysLoad = aAlwaysLoad;
+  if (mPendingImageLoadTask) {
+    alwaysLoad = alwaysLoad || mPendingImageLoadTask->AlwaysLoad();
+  }
+  RefPtr<ImageLoadTask> task = new ImageLoadTask(this, alwaysLoad);
   // The task checks this to determine if it was the last
   // queued event, and so earlier tasks are implicitly canceled.
   mPendingImageLoadTask = task;
   nsContentUtils::RunInStableState(task.forget());
 }
 
 bool
 HTMLImageElement::HaveSrcsetOrInPicture()
--- a/dom/html/HTMLImageElement.h
+++ b/dom/html/HTMLImageElement.h
@@ -17,16 +17,18 @@
 
 // Only needed for IsPictureEnabled()
 #include "mozilla/dom/HTMLPictureElement.h"
 
 namespace mozilla {
 class EventChainPreVisitor;
 namespace dom {
 
+class ImageLoadTask;
+
 class ResponsiveImageSelector;
 class HTMLImageElement final : public nsGenericHTMLElement,
                                public nsImageLoadingContent,
                                public nsIDOMHTMLImageElement
 {
   friend class HTMLSourceElement;
   friend class HTMLPictureElement;
   friend class ImageLoadTask;
@@ -357,15 +359,15 @@ protected:
 
 private:
   bool SourceElementMatches(nsIContent* aSourceNode);
 
   static void MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
                                     nsRuleData* aData);
 
   bool mInDocResponsiveContent;
-  nsCOMPtr<nsIRunnable> mPendingImageLoadTask;
+  RefPtr<ImageLoadTask> mPendingImageLoadTask;
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif /* mozilla_dom_HTMLImageElement_h */
--- a/dom/html/reftests/reftest.list
+++ b/dom/html/reftests/reftest.list
@@ -29,16 +29,18 @@ skip-if(B2G) == 41464-1b.html 41464-1-re
 skip-if(Android||B2G) == 649134-2.html 649134-2-ref.html
 
 == bug448564-1_malformed.html bug448564-1_well-formed.html
 == bug448564-1_malformed.html bug448564-1_ideal.html
 
 == bug448564-4a.html          bug448564-4b.html
 == bug502168-1_malformed.html bug502168-1_well-formed.html
 
+== responsive-image-load-shortcircuit.html responsive-image-load-shortcircuit-ref.html
+
 # Test that image documents taken into account CSS properties like
 # image-orientation when determining the size of the image.
 # (Fuzzy necessary due to pixel-wise comparison of different JPEGs.
 # The vast majority of the fuzziness comes from Linux and WinXP.)
 fuzzy(1,149) == bug917595-iframe-1.html    bug917595-1-ref.html
 skip-if(B2G||Mulet) fuzzy-if((!B2G&&!Mulet),3,640) == bug917595-exif-rotated.jpg bug917595-pixel-rotated.jpg # bug 1060869 # Bug 1150490 disabling on Mulet as on B2G
 
 # Test support for SVG-as-image in <picture> elements.
new file mode 100644
--- /dev/null
+++ b/dom/html/reftests/responsive-image-load-shortcircuit-ref.html
@@ -0,0 +1,1 @@
+<iframe srcdoc="<img src=pass.png>" width="300px"></iframe>
new file mode 100644
--- /dev/null
+++ b/dom/html/reftests/responsive-image-load-shortcircuit.html
@@ -0,0 +1,15 @@
+<html class="reftest-wait">
+<iframe srcdoc="<img srcset=red.png>" width="150px"></iframe>
+<script>
+  var iframe = document.querySelector('iframe');
+  iframe.onload = function() {
+    var doc = iframe.contentDocument;
+    var img = doc.querySelector('img');
+    img.srcset = "pass.png";
+    iframe.width = "300px";
+    img.onload = function() {
+      document.documentElement.classList.remove('reftest-wait');
+    };
+  }
+</script>
+</html>