Changeset 283590 in webkit
- Timestamp:
- Oct 5, 2021, 5:16:33 PM (5 years ago)
- Location:
- trunk
- Files:
-
- 6 added
- 4 edited
-
LayoutTests/ChangeLog (modified) (1 diff)
-
LayoutTests/intersection-observer/observe-disconnected-target-crash-expected.txt (added)
-
LayoutTests/intersection-observer/observe-disconnected-target-crash.html (added)
-
LayoutTests/intersection-observer/observe-disconnected-target-expected.txt (added)
-
LayoutTests/intersection-observer/observe-disconnected-target.html (added)
-
LayoutTests/intersection-observer/observe-then-disconnect-target-expected.txt (added)
-
LayoutTests/intersection-observer/observe-then-disconnect-target.html (added)
-
Source/WebCore/ChangeLog (modified) (1 diff)
-
Source/WebCore/page/IntersectionObserver.cpp (modified) (6 diffs)
-
Source/WebCore/page/IntersectionObserver.h (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r283587 r283590 1 2021-10-05 Chris Dumez <cdumez@apple.com> 2 3 ASSERT(m_callback->hasCallback()) under IntersectionObserver::notify() 4 https://bugs.webkit.org/show_bug.cgi?id=231235 5 <rdar://80837616> 6 7 Reviewed by Ryosuke Niwa. 8 9 Add layout test coverage both for the crash and the Web facing behavior. 10 11 * intersection-observer/observe-disconnected-target-crash-expected.txt: Added. 12 * intersection-observer/observe-disconnected-target-crash.html: Added. 13 * intersection-observer/observe-disconnected-target-expected.txt: Added. 14 * intersection-observer/observe-disconnected-target.html: Added. 15 1 16 2021-10-05 Ayumi Kojima <ayumi_kojima@apple.com> 2 17 -
trunk/Source/WebCore/ChangeLog
r283585 r283590 1 2021-10-05 Chris Dumez <cdumez@apple.com> 2 3 ASSERT(m_callback->hasCallback()) under IntersectionObserver::notify() 4 https://bugs.webkit.org/show_bug.cgi?id=231235 5 <rdar://80837616> 6 7 Reviewed by Ryosuke Niwa. 8 9 IntersectionObserver's JS callback stays alive as long as its JS wrapper and 10 its JS wrapper's lifetime relies on the IntersectionObserver::isReachableFromOpaqueRoots() 11 implementation. isReachableFromOpaqueRoots() keeps the wrapper alive as long 12 as the JS wrappers of observation / pending targets are alive. However, as per specification, 13 we always need to dispatch an observation for an observation target, even if that target 14 is not connected. Our code was already taking care of dispatching such observation. However, 15 there was nothing keeping the observation target alive in this case and thus nothing keeping 16 the JS callback alive either. 17 18 To address the issue, I am introducing a new m_targetsWaitingForFirstObservation data member 19 which holds a strong ref to the observation target until the next time we call notify(). 20 This makes sure that the observation target (and its JS wrapper) stays alive long enough for 21 us to dispatch the first observation for it. I also updated isReachableFromOpaqueRoots() to 22 return true as long as m_targetsWaitingForFirstObservation is non-empty so that the 23 IntersectionObserver's JS wrapper (and thus the JS callback) stay alive long enough too. 24 25 Tests: intersection-observer/observe-disconnected-target-crash.html 26 intersection-observer/observe-disconnected-target.html 27 28 * page/IntersectionObserver.cpp: 29 (WebCore::IntersectionObserver::observe): 30 (WebCore::IntersectionObserver::unobserve): 31 (WebCore::IntersectionObserver::removeAllTargets): 32 (WebCore::IntersectionObserver::notify): 33 (WebCore::IntersectionObserver::isReachableFromOpaqueRoots const): 34 * page/IntersectionObserver.h: 35 1 36 2021-10-05 Jean-Yves Avenard <jya@apple.com> 2 37 -
trunk/Source/WebCore/page/IntersectionObserver.cpp
r282487 r283590 170 170 m_observationTargets.append(makeWeakPtr(target)); 171 171 172 // Per the specification, we should dispatch at least one observation for the target. For this reason, we make sure to keep the 173 // target alive until this first observation. This, in turn, will keep the IntersectionObserver's JS wrapper alive via 174 // isReachableFromOpaqueRoots(), so the callback stays alive. 175 m_targetsWaitingForFirstObservation.append(target); 176 172 177 auto* document = trackingDocument(); 173 178 if (!hadObservationTargets) … … 183 188 bool removed = m_observationTargets.removeFirst(&target); 184 189 ASSERT_UNUSED(removed, removed); 190 m_targetsWaitingForFirstObservation.removeFirstMatching([&](auto& pendingTarget) { return pendingTarget.ptr() == ⌖ }); 185 191 186 192 if (!hasObservationTargets()) { … … 208 214 { 209 215 m_observationTargets.removeFirst(&target); 216 m_targetsWaitingForFirstObservation.removeFirstMatching([&](auto& pendingTarget) { return pendingTarget.ptr() == ⌖ }); 210 217 if (!hasObservationTargets()) { 211 218 if (auto* document = trackingDocument()) … … 233 240 } 234 241 m_observationTargets.clear(); 242 m_targetsWaitingForFirstObservation.clear(); 235 243 } 236 244 … … 274 282 275 283 auto takenRecords = takeRecords(); 284 auto targetsWaitingForFirstObservation = std::exchange(m_targetsWaitingForFirstObservation, { }); 276 285 277 286 // FIXME: The JSIntersectionObserver wrapper should be kept alive as long as the intersection observer can fire events. … … 299 308 return true; 300 309 } 301 return false;310 return !m_targetsWaitingForFirstObservation.isEmpty(); 302 311 } 303 312 -
trunk/Source/WebCore/page/IntersectionObserver.h
r282487 r283590 121 121 Vector<GCReachableRef<Element>> m_pendingTargets; 122 122 Vector<Ref<IntersectionObserverEntry>> m_queuedEntries; 123 Vector<GCReachableRef<Element>> m_targetsWaitingForFirstObservation; 123 124 }; 124 125
Note:
See TracChangeset
for help on using the changeset viewer.