GC can collect JS wrappers of nodes in the mutation records waiting to be delivered
authorrniwa@webkit.org <rniwa@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 3 Oct 2018 00:29:46 +0000 (00:29 +0000)
committerrniwa@webkit.org <rniwa@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 3 Oct 2018 00:29:46 +0000 (00:29 +0000)
commited157d5274fb2a6c92b5a6d0b38927910dec760f
treef1b0037acc55a31f95d87d209ec836aff6df4077
parent25a7814ed6d63fabc1440726597c37e4d144d2e5
GC can collect JS wrappers of nodes in the mutation records waiting to be delivered
https://bugs.webkit.org/show_bug.cgi?id=190115

Reviewed by Geoffrey Garen.

Source/WebCore:

Fixed the bug by retaining JS wrappers of elements in mutation records using GCReachableRef.

This patch deploys GCReachableRef in two places: MutationObserver where each mutation record's
target is kept alive and MutationObserverRegistration where each node which had been removed
from an observed tree is kept alive for a subtree observation.

Test: fast/dom/MutationObserver/mutation-observer-retains-js-wrappers-of-targets-alive.html

* dom/GCReachableRef.h:
(WebCore::GCReachableRef): Made it work with hash table.
(WebCore::GCReachableRef::operator T& const):
(WebCore::GCReachableRef::GCReachableRef):
(WebCore::GCReachableRef::isHashTableDeletedValue const):
(WebCore::GCReachableRef::isHashTableEmptyValue const):
(WebCore::GCReachableRef::ptrAllowingHashTableEmptyValue const):
(WebCore::GCReachableRef::ptrAllowingHashTableEmptyValue):
(WebCore::GCReachableRef::assignToHashTableEmptyValue):
(WTF::HashTraits<WebCore::GCReachableRef<P>>::emptyValue):
(WTF::HashTraits<WebCore::GCReachableRef<P>>::constructEmptyValue):
(WTF::HashTraits<WebCore::GCReachableRef<P>>::isEmptyValue):
(WTF::HashTraits<WebCore::GCReachableRef<P>>::assignToEmpty):
(WTF::HashTraits<WebCore::GCReachableRef<P>>::peek):
(WTF::HashTraits<WebCore::GCReachableRef<P>>::take):
* dom/MutationObserver.cpp:
(WebCore::MutationObserver::takeRecords): Don't clear m_pendingTargets because that would allow wrappers
to be collected before elements in mutation records are accessed. We delay until the end of the current
microtask at which point deliver() function is called.
(WebCore::MutationObserver::disconnect):
(WebCore::MutationObserver::enqueueMutationRecord): Add the target to the list of elements to keep alive.
This is needed for a newly inserted node, a node with attribute change, etc...
(WebCore::MutationObserver::deliver): Keep the set of transient registration targets alive until mutation
records are delivered to each observer. These are nodes which had been removed from a tree and whose
subtree had still been obsreved up until this point.
* dom/MutationObserver.h:
* dom/MutationObserverRegistration.cpp:
(WebCore::MutationObserverRegistration::observedSubtreeNodeWillDetach):
(WebCore::MutationObserverRegistration::takeTransientRegistrations): Return the hash set of elemenets
that need to be kept alive so that MutationObserver::deliver can keep them alive until the deliver
function had been called.
(WebCore::MutationObserverRegistration::addRegistrationNodesToSet const):
* dom/MutationObserverRegistration.h:

LayoutTests:

Added a regression test.

* fast/dom/MutationObserver/mutation-observer-retains-js-wrappers-of-targets-alive-expected.txt: Added.
* fast/dom/MutationObserver/mutation-observer-retains-js-wrappers-of-targets-alive.html: Added.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@236781 268f45cc-cd09-0410-ab3c-d52691b4dbfc
LayoutTests/ChangeLog
LayoutTests/fast/dom/MutationObserver/mutation-observer-retains-js-wrappers-of-targets-alive-expected.txt [new file with mode: 0644]
LayoutTests/fast/dom/MutationObserver/mutation-observer-retains-js-wrappers-of-targets-alive.html [new file with mode: 0644]
Source/WebCore/ChangeLog
Source/WebCore/dom/GCReachableRef.h
Source/WebCore/dom/MutationObserver.cpp
Source/WebCore/dom/MutationObserver.h
Source/WebCore/dom/MutationObserverRegistration.cpp
Source/WebCore/dom/MutationObserverRegistration.h