Bug 1433336 - Collect only documents which are observerd by IntersectionObserver in nsRefreshDriver::Tick(). r?smaug draft
authorHiroyuki Ikezoe <hikezoe@mozilla.com>
Fri, 26 Jan 2018 20:11:17 +0900
changeset 747567 62b17453cb7edba8b1335785f0e042d33abbf996
parent 747566 433d0fe8f0333cfa29b7f1013ee309824601569f
push id96936
push userhikezoe@mozilla.com
push dateFri, 26 Jan 2018 11:11:56 +0000
reviewerssmaug
bugs1433336, 1415780
milestone60.0a1
Bug 1433336 - Collect only documents which are observerd by IntersectionObserver in nsRefreshDriver::Tick(). r?smaug We don't need to collect whole descendants documents. This patch intentionally leaves animation events handling which is another caller of CollectDocuments in nsRefreshDriver since the animation part will be fixed in a different way in bug 1415780. MozReview-Commit-ID: INAJm1NHLuI
dom/base/nsDocument.h
dom/base/nsIDocument.h
layout/base/nsRefreshDriver.cpp
layout/base/nsRefreshDriver.h
--- a/dom/base/nsDocument.h
+++ b/dom/base/nsDocument.h
@@ -615,16 +615,20 @@ public:
 
   virtual void AddIntersectionObserver(
     mozilla::dom::DOMIntersectionObserver* aObserver) override;
   virtual void RemoveIntersectionObserver(
     mozilla::dom::DOMIntersectionObserver* aObserver) override;
   virtual void UpdateIntersectionObservations() override;
   virtual void ScheduleIntersectionObserverNotification() override;
   virtual void NotifyIntersectionObservers() override;
+  virtual bool HasIntersectionObservers() const override
+  {
+    return !mIntersectionObservers.IsEmpty();
+  }
 
   virtual void NotifyLayerManagerRecreated() override;
 
   virtual void ScheduleSVGForPresAttrEvaluation(nsSVGElement* aSVG) override;
   virtual void UnscheduleSVGForPresAttrEvaluation(nsSVGElement* aSVG) override;
   virtual void ResolveScheduledSVGPresAttrs() override;
   bool IsSynthesized();
 
--- a/dom/base/nsIDocument.h
+++ b/dom/base/nsIDocument.h
@@ -3115,16 +3115,17 @@ public:
   virtual void AddIntersectionObserver(
     mozilla::dom::DOMIntersectionObserver* aObserver) = 0;
   virtual void RemoveIntersectionObserver(
     mozilla::dom::DOMIntersectionObserver* aObserver) = 0;
 
   virtual void UpdateIntersectionObservations() = 0;
   virtual void ScheduleIntersectionObserverNotification() = 0;
   virtual void NotifyIntersectionObservers() = 0;
+  virtual bool HasIntersectionObservers() const = 0;
 
   // Dispatch a runnable related to the document.
   virtual nsresult Dispatch(mozilla::TaskCategory aCategory,
                             already_AddRefed<nsIRunnable>&& aRunnable) override;
 
   virtual nsISerialEventTarget*
   EventTargetFor(mozilla::TaskCategory aCategory) const override;
 
--- a/layout/base/nsRefreshDriver.cpp
+++ b/layout/base/nsRefreshDriver.cpp
@@ -1583,16 +1583,38 @@ CollectDocuments(nsIDocument* aDocument,
 {
   static_cast<AutoTArray<nsCOMPtr<nsIDocument>, 32>*>(aDocArray)->
     AppendElement(aDocument);
   aDocument->EnumerateSubDocuments(CollectDocuments, aDocArray);
   return true;
 }
 
 void
+nsRefreshDriver::UpdateIntersectionObservations()
+{
+  AutoTArray<nsCOMPtr<nsIDocument>, 32> documents;
+
+  if (mPresContext->Document()->HasIntersectionObservers()) {
+    documents.AppendElement(mPresContext->Document());
+  }
+
+  mPresContext->Document()->CollectDescendantDocuments(
+    documents,
+    [](const nsIDocument* document) -> bool {
+      return document->HasIntersectionObservers();
+    });
+
+  for (uint32_t i = 0; i < documents.Length(); ++i) {
+    nsIDocument* doc = documents[i];
+    doc->UpdateIntersectionObservations();
+    doc->ScheduleIntersectionObserverNotification();
+  }
+}
+
+void
 nsRefreshDriver::DispatchAnimationEvents()
 {
   if (!mPresContext) {
     return;
   }
 
   AutoTArray<nsCOMPtr<nsIDocument>, 32> documents;
   CollectDocuments(mPresContext->Document(), &documents);
@@ -1950,23 +1972,17 @@ nsRefreshDriver::Tick(int64_t aNowEpoch,
   // Update any popups that may need to be moved or hidden due to their
   // anchor changing.
   nsXULPopupManager* pm = nsXULPopupManager::GetInstance();
   if (pm) {
     pm->UpdatePopupPositions(this);
   }
 #endif
 
-  AutoTArray<nsCOMPtr<nsIDocument>, 32> documents;
-  CollectDocuments(mPresContext->Document(), &documents);
-  for (uint32_t i = 0; i < documents.Length(); ++i) {
-    nsIDocument* doc = documents[i];
-    doc->UpdateIntersectionObservations();
-    doc->ScheduleIntersectionObserverNotification();
-  }
+  UpdateIntersectionObservations();
 
   /*
    * Perform notification to imgIRequests subscribed to listen
    * for refresh events.
    */
 
   for (auto iter = mStartTable.Iter(); !iter.Done(); iter.Next()) {
     const uint32_t& delay = iter.Key();
--- a/layout/base/nsRefreshDriver.h
+++ b/layout/base/nsRefreshDriver.h
@@ -380,16 +380,17 @@ private:
     mozilla::Maybe<mozilla::TimeStamp> mStartTime;
     RequestTable mEntries;
   };
   typedef nsClassHashtable<nsUint32HashKey, ImageStartData> ImageStartTable;
 
   void DispatchPendingEvents();
   void DispatchAnimationEvents();
   void RunFrameRequestCallbacks(mozilla::TimeStamp aNowTime);
+  void UpdateIntersectionObservations();
   void Tick(int64_t aNowEpoch, mozilla::TimeStamp aNowTime);
 
   enum EnsureTimerStartedFlags {
     eNone = 0,
     eForceAdjustTimer = 1 << 0,
     eAllowTimeToGoBackwards = 1 << 1,
     eNeverAdjustTimer = 1 << 2,
   };