Bug 1619858 - Use an intersection observer per document for lazyload. r=hiro
authorEmilio Cobos Álvarez <emilio@crisal.io>
Wed, 04 Mar 2020 21:11:43 +0000
changeset 516918 9580f250e2fc1a40734578a9e293732eaff57c67
parent 516917 bbefb498a0c030229fdc8621cba3198854a01b74
child 516919 07950851001aadb57cf196345cfade4af98339ae
push id37183
push usernerli@mozilla.com
push dateThu, 05 Mar 2020 04:16:49 +0000
treeherdermozilla-central@1e4b37c9e558 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewershiro
bugs1619858
milestone75.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 1619858 - Use an intersection observer per document for lazyload. r=hiro We can't observe when the sub-document gets detached from the root document to drop the observation, so this is the sound thing to do. Differential Revision: https://phabricator.services.mozilla.com/D65362
dom/base/Document.cpp
testing/web-platform/tests/html/semantics/embedded-content/the-img-element/image-loading-lazy-subframe-detached-crash.html
--- a/dom/base/Document.cpp
+++ b/dom/base/Document.cpp
@@ -14683,29 +14683,24 @@ void Document::NotifyIntersectionObserve
   for (const auto& observer : observers) {
     if (observer) {
       observer->Notify();
     }
   }
 }
 
 DOMIntersectionObserver* Document::GetLazyLoadImageObserver() {
-  Document* rootDoc = nsContentUtils::GetRootDocument(this);
-  MOZ_ASSERT(rootDoc);
-
-  if (rootDoc->mLazyLoadImageObserver) {
-    return rootDoc->mLazyLoadImageObserver;
-  }
-
-  if (nsPIDOMWindowInner* inner = rootDoc->GetInnerWindow()) {
-    rootDoc->mLazyLoadImageObserver =
-        DOMIntersectionObserver::CreateLazyLoadObserver(inner);
-  }
-
-  return rootDoc->mLazyLoadImageObserver;
+  if (!mLazyLoadImageObserver) {
+    if (nsPIDOMWindowInner* inner = GetInnerWindow()) {
+      mLazyLoadImageObserver =
+          DOMIntersectionObserver::CreateLazyLoadObserver(inner);
+    }
+  }
+
+  return mLazyLoadImageObserver;
 }
 
 static CallState NotifyLayerManagerRecreatedCallback(Document& aDocument,
                                                      void*) {
   aDocument.NotifyLayerManagerRecreated();
   return CallState::Continue;
 }
 
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/the-img-element/image-loading-lazy-subframe-detached-crash.html
@@ -0,0 +1,26 @@
+<!doctype html>
+<html class="test-wait">
+<title>Crash when detaching a frame during a lazy-load operation</title>
+<link rel="author" href="mailto:emilio@crisal.io" title="Emilio Cobos Álvarez">
+<link rel="author" href="https://mozilla.org" title="Mozilla">
+<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1619858">
+<iframe srcdoc=""></iframe>
+<script>
+onload = function() {
+  let frame = document.querySelector("iframe");
+  frame.contentDocument.body.innerHTML = `
+    <div style="height: 300vh"></div>
+    <img loading="lazy" src="/images/blue96x96.png" width=96 height=96>
+  `;
+  let img = frame.contentDocument.querySelector("img");
+  new IntersectionObserver(() => {
+    frame.remove();
+    requestAnimationFrame(function() {
+      requestAnimationFrame(function() {
+        document.documentElement.className = "";
+      });
+    });
+  }).observe(img);
+  frame.contentWindow.scrollTo(0, img.getBoundingClientRect().top);
+};
+</script>