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 291083 5df20795af1438c88a7997255e52ac44ec07047e
parent 291082 7c4258b493b12d00a89276c41a5f39cdcf28d2fc
child 291084 25ff944d5dc9454055426d021889fb700b8ff55a
push id19656
push usergwagner@mozilla.com
push dateMon, 04 Apr 2016 13:43:23 +0000
treeherderb2g-inbound@e99061fde28a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjohns
bugs1259482
milestone48.0a1
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>