Bug 1518795 - Properly track responsive content in a connected ShadowRoot. r=smaug, a=RyanVM
authorEmilio Cobos Álvarez <emilio@crisal.io>
Wed, 09 Jan 2019 15:59:10 +0000
changeset 509381 87b11c0f4ff5507a3bc4e52f6d20a8c5760c5acc
parent 509380 7fad62ad328dbd6df5d45ba2d26c92c4f250651a
child 509382 d0a5f0121ba7f123f030e861fd1dba05bd39b0d4
push id1905
push userffxbld-merge
push dateMon, 21 Jan 2019 12:33:13 +0000
treeherdermozilla-release@c2fca1944d8c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmaug, RyanVM
bugs1518795
milestone65.0
Bug 1518795 - Properly track responsive content in a connected ShadowRoot. r=smaug, a=RyanVM Took more to write the test than the fix :) Differential Revision: https://phabricator.services.mozilla.com/D16055
dom/base/nsImageLoadingContent.cpp
dom/html/HTMLImageElement.cpp
testing/web-platform/tests/html/semantics/embedded-content/the-img-element/sizes/sizes-dynamic-002.html
--- a/dom/base/nsImageLoadingContent.cpp
+++ b/dom/base/nsImageLoadingContent.cpp
@@ -1401,22 +1401,21 @@ bool nsImageLoadingContent::HaveSize(img
   uint32_t status;
   nsresult rv = aImage->GetImageStatus(&status);
   return (NS_SUCCEEDED(rv) && (status & imgIRequest::STATUS_SIZE_AVAILABLE));
 }
 
 void nsImageLoadingContent::BindToTree(nsIDocument* aDocument,
                                        nsIContent* aParent,
                                        nsIContent* aBindingParent) {
-  // We may be entering the document, so if our image should be tracked,
-  // track it.
-  if (!aDocument) return;
-
-  TrackImage(mCurrentRequest);
-  TrackImage(mPendingRequest);
+  // We may be getting connected, if so our image should be tracked,
+  if (GetOurCurrentDoc()) {
+    TrackImage(mCurrentRequest);
+    TrackImage(mPendingRequest);
+  }
 }
 
 void nsImageLoadingContent::UnbindFromTree(bool aDeep, bool aNullParent) {
   // We may be leaving the document, so if our image is tracked, untrack it.
   nsCOMPtr<nsIDocument> doc = GetOurCurrentDoc();
   if (!doc) return;
 
   UntrackImage(mCurrentRequest);
--- a/dom/html/HTMLImageElement.cpp
+++ b/dom/html/HTMLImageElement.cpp
@@ -497,18 +497,19 @@ nsresult HTMLImageElement::BindToTree(ns
 
   nsImageLoadingContent::BindToTree(aDocument, aParent, aBindingParent);
 
   if (aParent) {
     UpdateFormOwner();
   }
 
   if (HaveSrcsetOrInPicture()) {
-    if (aDocument && !mInDocResponsiveContent) {
-      aDocument->AddResponsiveContent(this);
+    Document* doc = GetComposedDoc();
+    if (doc && !mInDocResponsiveContent) {
+      doc->AddResponsiveContent(this);
       mInDocResponsiveContent = true;
     }
 
     // Mark channel as urgent-start before load image if the image load is
     // initaiated by a user interaction.
     mUseUrgentStartForChannel = EventStateManager::IsHandlingUserInput();
 
     // Run selection algorithm when an img element is inserted into a document
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/the-img-element/sizes/sizes-dynamic-002.html
@@ -0,0 +1,33 @@
+<!doctype html>
+<html class="reftest-wait">
+<title>Image intrinsic size specified via sizes attribute reacts properly to media changes in Shadow DOM</title>
+<link rel="author" title="Emilio Cobos Álvarez" href="mailto:emilio@crisal.io">
+<link rel="match" href="sizes-dynamic-001-ref.html">
+<link rel="help" href="https://html.spec.whatwg.org/#sizes-attributes">
+<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1149357">
+<script>
+function frameLoaded(frame) {
+  let doc = frame.contentDocument;
+  let shadow = doc.getElementById("host").attachShadow({ mode: "open" });
+
+  let img = doc.createElement("img");
+  img.srcset = "/images/green-256x256.png 100w";
+  img.style.maxWidth = "100%";
+  img.setAttribute("sizes", "(min-width: 400px) 10px, 20px");
+
+  img.onload = function() {
+    img.offsetWidth; // Flush layout.
+
+    frame.width = "500";
+
+    // Trigger the viewport resize, which will trigger the image load task.
+    img.offsetWidth;
+
+    // Wait for the image load task to run.
+    setTimeout(() => document.documentElement.removeAttribute("class"), 0);
+  };
+
+  shadow.appendChild(img);
+}
+</script>
+<iframe onload="frameLoaded(this)" width="200" height="500" srcdoc='<!doctype html><div id="host"></div>'></iframe>