Index: Source/core/dom/Document.cpp |
diff --git a/Source/core/dom/Document.cpp b/Source/core/dom/Document.cpp |
index f2929f0eb0859debabec50951d240a1dfae0d4b2..17c62fdbc0bf3174b01e01d864dc485b18461394 100644 |
--- a/Source/core/dom/Document.cpp |
+++ b/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" |
@@ -226,6 +227,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. |
@@ -422,6 +425,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) |
@@ -5632,6 +5636,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) |
@@ -5688,6 +5730,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); |