Index: third_party/WebKit/Source/core/dom/IntersectionObserver.cpp |
diff --git a/third_party/WebKit/Source/core/dom/IntersectionObserver.cpp b/third_party/WebKit/Source/core/dom/IntersectionObserver.cpp |
index 2a9cd6f082099d2d6f1c4e72da891af2950a7052..b29b69e8b46ed857ca07cd7f76d5b958fd182fe6 100644 |
--- a/third_party/WebKit/Source/core/dom/IntersectionObserver.cpp |
+++ b/third_party/WebKit/Source/core/dom/IntersectionObserver.cpp |
@@ -186,6 +186,7 @@ |
void IntersectionObserver::observe(Element* target, ExceptionState& exceptionState) |
{ |
+ checkRootAndDetachIfNeeded(); |
if (!m_root) { |
exceptionState.throwDOMException(HierarchyRequestError, "Invalid observer: root element or containing document has been deleted."); |
return; |
@@ -220,6 +221,7 @@ |
void IntersectionObserver::unobserve(Element* target, ExceptionState&) |
{ |
+ checkRootAndDetachIfNeeded(); |
if (!target || !target->intersectionObserverData()) |
return; |
// TODO(szager): unobserve callback |
@@ -229,6 +231,7 @@ |
void IntersectionObserver::computeIntersectionObservations(double timestamp) |
{ |
+ checkRootAndDetachIfNeeded(); |
if (!m_root) |
return; |
for (auto& observation : m_observations) |
@@ -251,6 +254,7 @@ |
HeapVector<Member<IntersectionObserverEntry>> IntersectionObserver::takeRecords() |
{ |
+ checkRootAndDetachIfNeeded(); |
HeapVector<Member<IntersectionObserverEntry>> entries; |
entries.swap(m_entries); |
return entries; |
@@ -295,6 +299,8 @@ |
void IntersectionObserver::deliver() |
{ |
+ checkRootAndDetachIfNeeded(); |
+ |
if (m_entries.isEmpty()) |
return; |
@@ -305,6 +311,7 @@ |
void IntersectionObserver::setActive(bool active) |
{ |
+ checkRootAndDetachIfNeeded(); |
for (auto& observation : m_observations) |
observation->setActive(m_root && active && isDescendantOfRoot(observation->target())); |
} |
@@ -317,17 +324,25 @@ |
|| m_leftMargin.type() == Percent); |
} |
-void IntersectionObserver::rootDisappearedCallback(Visitor* visitor, void* self) |
-{ |
- IntersectionObserver* observer = static_cast<IntersectionObserver*>(self); |
- observer->disconnect(); |
+void IntersectionObserver::checkRootAndDetachIfNeeded() |
+{ |
+#if ENABLE(OILPAN) |
+ // TODO(szager): Pre-oilpan, ElementIntersectionObserverData::dispose() will take |
+ // care of this cleanup. When oilpan ships, there will be a potential leak of the |
+ // callback's execution context when the root goes away. For a detailed explanation: |
+ // |
+ // https://goo.gl/PC2Baj |
+ // |
+ // When that happens, this method should catch most potential leaks, but a complete |
+ // solution will still be needed, along the lines described in the above link. |
+ if (m_root) |
+ return; |
+ disconnect(); |
+#endif |
} |
DEFINE_TRACE(IntersectionObserver) |
{ |
-#if ENABLE(OILPAN) |
- visitor->registerWeakMembers(this, m_root.get(), IntersectionObserver::rootDisappearedCallback); |
-#endif |
visitor->trace(m_callback); |
visitor->trace(m_root); |
visitor->trace(m_observations); |