Index: third_party/WebKit/Source/core/dom/Document.cpp |
diff --git a/third_party/WebKit/Source/core/dom/Document.cpp b/third_party/WebKit/Source/core/dom/Document.cpp |
index dff02f7249fa660d7e136ddbdfd24c7ad473be35..f1dc8aa2a25016a9ce2712d2e59baf99cce0a78f 100644 |
--- a/third_party/WebKit/Source/core/dom/Document.cpp |
+++ b/third_party/WebKit/Source/core/dom/Document.cpp |
@@ -76,6 +76,7 @@ |
#include "core/dom/ExceptionCode.h" |
#include "core/dom/ExecutionContextTask.h" |
#include "core/dom/FrameRequestCallback.h" |
+#include "core/dom/IntersectionObserver.h" |
#include "core/dom/LayoutTreeBuilderTraversal.h" |
#include "core/dom/MainThreadTaskRunner.h" |
#include "core/dom/Microtask.h" |
@@ -232,6 +233,8 @@ namespace blink { |
using namespace HTMLNames; |
+using IntersectionObserverVector = WillBeHeapVector<RefPtrWillBeMember<IntersectionObserver>>; |
+ |
static const unsigned cMaxWriteRecursionDepth = 21; |
// This amount of time must have elapsed before we will even consider scheduling a layout without a delay. |
@@ -430,6 +433,7 @@ Document::Document(const DocumentInit& initializer, DocumentClassFlags documentC |
, m_loadEventDelayCount(0) |
, m_loadEventDelayTimer(this, &Document::loadEventDelayTimerFired) |
, m_pluginLoadingTimer(this, &Document::pluginLoadingTimerFired) |
+ , m_deliverIntersectionObservationsTimer(this, &Document::deliverIntersectionObservationsTimerFired) |
, m_documentTiming(*this) |
, m_writeRecursionIsTooDeep(false) |
, m_writeRecursionDepth(0) |
@@ -5672,6 +5676,44 @@ bool Document::isPrivilegedContext(String& errorMessage, const PrivilegeContextC |
return true; |
} |
+void Document::activateIntersectionObserver(IntersectionObserver& observer) |
+{ |
+ if (m_activeIntersectionObservers.isEmpty()) |
+ m_deliverIntersectionObservationsTimer.startOneShot(0, FROM_HERE); |
+ |
+ m_activeIntersectionObservers.add(&observer); |
+} |
+ |
+void Document::resumeSuspendedIntersectionObservers() |
+{ |
+ ASSERT(isMainThread()); |
+ if (m_suspendedIntersectionObservers.isEmpty()) |
+ return; |
+ |
+ IntersectionObserverVector suspended; |
+ copyToVector(m_suspendedIntersectionObservers, suspended); |
+ for (size_t i = 0; i < suspended.size(); ++i) { |
+ if (!suspended[i]->shouldBeSuspended()) { |
+ m_suspendedIntersectionObservers.remove(suspended[i]); |
+ activateIntersectionObserver(*suspended[i]); |
+ } |
+ } |
+} |
+ |
+void Document::deliverIntersectionObservationsTimerFired(Timer<Document>*) |
+{ |
+ ASSERT(isMainThread()); |
+ IntersectionObserverVector observers; |
+ copyToVector(m_activeIntersectionObservers, observers); |
+ m_activeIntersectionObservers.clear(); |
+ for (size_t i = 0; i < observers.size(); ++i) { |
+ if (observers[i]->shouldBeSuspended()) |
+ m_suspendedIntersectionObservers.add(observers[i]); |
+ else |
+ observers[i]->deliver(); |
+ } |
+} |
+ |
DEFINE_TRACE(Document) |
{ |
#if ENABLE(OILPAN) |
@@ -5728,6 +5770,8 @@ DEFINE_TRACE(Document) |
visitor->trace(m_compositorPendingAnimations); |
visitor->trace(m_contextDocument); |
visitor->trace(m_canvasFontCache); |
+ visitor->trace(m_activeIntersectionObservers); |
+ visitor->trace(m_suspendedIntersectionObservers); |
WillBeHeapSupplementable<Document>::trace(visitor); |
#endif |
TreeScope::trace(visitor); |