Source/WebCore/ChangeLog

 12020-10-19 Commit Queue <commit-queue@webkit.org>
 2
 3 Unreviewed, reverting r267175 and r267779.
 4 https://bugs.webkit.org/show_bug.cgi?id=217923
 5
 6 Regressed NYTimes's DOM content loaded time by 400%
 7
 8 Reverted changesets:
 9
 10 "MutationObserverRegistration should be ref counted"
 11 https://bugs.webkit.org/show_bug.cgi?id=216528
 12 https://trac.webkit.org/changeset/267175
 13
 14 "Crash while loading a confluence page"
 15 https://bugs.webkit.org/show_bug.cgi?id=217111
 16 https://trac.webkit.org/changeset/267779
 17
1182020-10-19 Patrick Angle <pangle@apple.com>
219
320 Web Inspector: REGRESSION(r265231): Overlay: node info sometimes draws on one line

Source/WebCore/dom/MutationObserver.cpp

@@void MutationObserver::disconnect()
120120{
121121 m_pendingTargets.clear();
122122 m_records.clear();
123  auto registrationAndNodeList = WTF::compactMap(m_registrations, [](auto* registration) -> Optional<std::pair<Ref<Node>, Ref<MutationObserverRegistration>>> {
124  auto node = registration->stopObserving();
125  if (!node)
126  return WTF::nullopt;
127  return { { node.releaseNonNull(), makeRef(*registration) } };
128  });
129  for (auto& registrationAndNode : registrationAndNodeList)
130  registrationAndNode.first->unregisterMutationObserver(registrationAndNode.second.get());
 123 HashSet<MutationObserverRegistration*> registrations(m_registrations);
 124 for (auto* registration : registrations)
 125 registration->node().unregisterMutationObserver(*registration);
131126}
132127
133128void MutationObserver::observationStarted(MutationObserverRegistration& registration)
134129{
135  auto result = m_registrations.add(&registration);
136  RELEASE_ASSERT(result.isNewEntry);
 130 ASSERT(!m_registrations.contains(&registration));
 131 m_registrations.add(&registration);
137132}
138133
139134void MutationObserver::observationEnded(MutationObserverRegistration& registration)
140135{
141  auto removed = m_registrations.remove(&registration);
142  RELEASE_ASSERT(removed);
 136 ASSERT(m_registrations.contains(&registration));
 137 m_registrations.remove(&registration);
143138}
144139
145140void MutationObserver::enqueueMutationRecord(Ref<MutationRecord>&& mutation)

@@void MutationObserver::deliver()
191186{
192187 ASSERT(canDeliver());
193188
 189 // Calling takeTransientRegistrations() can modify m_registrations, so it's necessary
 190 // to make a copy of the transient registrations before operating on them.
 191 Vector<MutationObserverRegistration*, 1> transientRegistrations;
194192 Vector<std::unique_ptr<HashSet<GCReachableRef<Node>>>, 1> nodesToKeepAlive;
195193 HashSet<GCReachableRef<Node>> pendingTargets;
196194 pendingTargets.swap(m_pendingTargets);
197  auto registrations = WTF::map(m_registrations, [](auto* registration) { return makeRef(*registration); });
198  for (auto& registration : registrations) {
 195 for (auto* registration : m_registrations) {
199196 if (registration->hasTransientRegistrations())
200  nodesToKeepAlive.append(registration->takeTransientRegistrations());
 197 transientRegistrations.append(registration);
201198 }
 199 for (auto& registration : transientRegistrations)
 200 nodesToKeepAlive.append(registration->takeTransientRegistrations());
202201
203202 if (m_records.isEmpty()) {
204203 ASSERT(m_pendingTargets.isEmpty());

Source/WebCore/dom/MutationObserverRegistration.cpp

3737
3838namespace WebCore {
3939
40 Ref<MutationObserverRegistration> MutationObserverRegistration::create(MutationObserver& observer, Node& node, MutationObserverOptions options, const HashSet<AtomString>& attributeFilter)
41 {
42  return adoptRef(*new MutationObserverRegistration(observer, node, options, attributeFilter));
43 }
44 
4540MutationObserverRegistration::MutationObserverRegistration(MutationObserver& observer, Node& node, MutationObserverOptions options, const HashSet<AtomString>& attributeFilter)
4641 : m_observer(observer)
47  , m_node(makeWeakPtr(node))
 42 , m_node(node)
4843 , m_options(options)
4944 , m_attributeFilter(attributeFilter)
5045{

@@void MutationObserverRegistration::observedSubtreeNodeWillDetach(Node& node)
7267 node.registerTransientMutationObserver(*this);
7368 m_observer->setHasTransientRegistration(node.document());
7469
75  if (!m_transientRegistrationNodes)
 70 if (!m_transientRegistrationNodes) {
7671 m_transientRegistrationNodes = makeUnique<HashSet<GCReachableRef<Node>>>();
 72
 73 ASSERT(!m_nodeKeptAlive);
 74 m_nodeKeptAlive = &m_node; // Balanced in takeTransientRegistrations.
 75 }
7776 m_transientRegistrationNodes->add(node);
7877}
7978
8079std::unique_ptr<HashSet<GCReachableRef<Node>>> MutationObserverRegistration::takeTransientRegistrations()
8180{
82  if (!m_transientRegistrationNodes)
 81 if (!m_transientRegistrationNodes) {
 82 ASSERT(!m_nodeKeptAlive);
8383 return nullptr;
 84 }
8485
85  auto transientNodes = WTFMove(m_transientRegistrationNodes);
86  for (auto& node : *transientNodes)
 86 for (auto& node : *m_transientRegistrationNodes)
8787 node->unregisterTransientMutationObserver(*this);
8888
89  return transientNodes;
 89 auto returnValue = WTFMove(m_transientRegistrationNodes);
 90
 91 ASSERT(m_nodeKeptAlive);
 92 m_nodeKeptAlive = nullptr; // Balanced in observeSubtreeNodeWillDetach.
 93
 94 return returnValue;
9095}
9196
9297bool MutationObserverRegistration::shouldReceiveMutationFrom(Node& node, MutationObserver::MutationType type, const QualifiedName* attributeName) const

@@bool MutationObserverRegistration::shouldReceiveMutationFrom(Node& node, Mutatio
95100 if (!(m_options & type))
96101 return false;
97102
98  if (m_node.get() != &node && !isSubtree())
 103 if (&m_node != &node && !isSubtree())
99104 return false;
100105
101106 if (type != MutationObserver::Attributes || !(m_options & MutationObserver::AttributeFilter))

@@bool MutationObserverRegistration::shouldReceiveMutationFrom(Node& node, Mutatio
107112 return m_attributeFilter.contains(attributeName->localName());
108113}
109114
110 RefPtr<Node> MutationObserverRegistration::stopObserving()
111 {
112  if (m_hasStoppedObservingNode)
113  return nullptr;
114  m_hasStoppedObservingNode = true;
115  return makeRefPtr(m_node.get());
116 }
117 
118115void MutationObserverRegistration::addRegistrationNodesToSet(HashSet<Node*>& nodes) const
119116{
120  ASSERT(m_node.get() || m_transientRegistrationNodes);
121  if (auto* observedNode = m_node.get())
122  nodes.add(observedNode);
 117 nodes.add(&m_node);
123118 if (!m_transientRegistrationNodes)
124119 return;
125120 for (auto& node : *m_transientRegistrationNodes)

Source/WebCore/dom/MutationObserverRegistration.h

3333#include "GCReachableRef.h"
3434#include "MutationObserver.h"
3535#include <wtf/HashSet.h>
36 #include <wtf/WeakPtr.h>
3736#include <wtf/text/AtomString.h>
3837#include <wtf/text/AtomStringHash.h>
3938

@@namespace WebCore {
4140
4241class QualifiedName;
4342
44 class MutationObserverRegistration : public RefCounted<MutationObserverRegistration> {
 43class MutationObserverRegistration {
4544 WTF_MAKE_FAST_ALLOCATED;
4645public:
47  static Ref<MutationObserverRegistration> create(MutationObserver&, Node&, MutationObserverOptions, const HashSet<AtomString>& attributeFilter);
48 
 46 MutationObserverRegistration(MutationObserver&, Node&, MutationObserverOptions, const HashSet<AtomString>& attributeFilter);
4947 ~MutationObserverRegistration();
5048
5149 void resetObservation(MutationObserverOptions, const HashSet<AtomString>& attributeFilter);

@@public:
5755 bool isSubtree() const { return m_options & MutationObserver::Subtree; }
5856
5957 MutationObserver& observer() { return m_observer.get(); }
60  Node* node() { return m_node.get(); }
61  RefPtr<Node> stopObserving();
 58 Node& node() { return m_node; }
6259 MutationRecordDeliveryOptions deliveryOptions() const { return m_options & (MutationObserver::AttributeOldValue | MutationObserver::CharacterDataOldValue); }
6360 MutationObserverOptions mutationTypes() const { return m_options & MutationObserver::AllMutationTypes; }
6461
6562 void addRegistrationNodesToSet(HashSet<Node*>&) const;
6663
6764private:
68  MutationObserverRegistration(MutationObserver&, Node&, MutationObserverOptions, const HashSet<AtomString>& attributeFilter);
69 
7065 Ref<MutationObserver> m_observer;
71  WeakPtr<Node> m_node;
72  bool m_hasStoppedObservingNode { false };
73  MutationObserverOptions m_options;
 66 Node& m_node;
 67 RefPtr<Node> m_nodeKeptAlive;
7468 std::unique_ptr<HashSet<GCReachableRef<Node>>> m_transientRegistrationNodes;
 69 MutationObserverOptions m_options;
7570 HashSet<AtomString> m_attributeFilter;
7671};
7772

Source/WebCore/dom/Node.cpp

@@inline void Node::NodeRareDataDeleter::operator()(NodeRareData* rareData) const
429429void Node::clearRareData()
430430{
431431 ASSERT(hasRareData());
432  ASSERT(rareData()->transientMutationObserverRegistry().isEmpty());
 432 ASSERT(!transientMutationObserverRegistry() || transientMutationObserverRegistry()->isEmpty());
 433
433434 m_rareDataWithBitfields.setPointer(nullptr);
434435}
435436

@@void Node::moveNodeToNewDocument(Document& oldDocument, Document& newDocument)
20392040 oldDocument.decrementReferencingNodeCount();
20402041
20412042 if (hasRareData()) {
2042  auto* rareData = this->rareData();
2043  if (auto* nodeLists = rareData->nodeLists())
 2043 if (auto* nodeLists = rareData()->nodeLists())
20442044 nodeLists->adoptDocument(oldDocument, newDocument);
2045  if (auto* registry = rareData->mutationObserverRegistryIfExists()) {
 2045 if (auto* registry = mutationObserverRegistry()) {
20462046 for (auto& registration : *registry)
20472047 newDocument.addMutationObserverTypes(registration->mutationTypes());
20482048 }
2049  for (auto& registration : rareData->transientMutationObserverRegistry())
2050  newDocument.addMutationObserverTypes(registration->mutationTypes());
 2049 if (auto* transientRegistry = transientMutationObserverRegistry()) {
 2050 for (auto& registration : *transientRegistry)
 2051 newDocument.addMutationObserverTypes(registration->mutationTypes());
 2052 }
 2053 } else {
 2054 ASSERT(!mutationObserverRegistry());
 2055 ASSERT(!transientMutationObserverRegistry());
20512056 }
20522057
20532058 oldDocument.moveNodeIteratorsToNewDocument(*this, newDocument);

@@void Node::clearEventTargetData()
22472252 eventTargetDataMap().remove(this);
22482253}
22492254
2250 template<typename Registry> static inline void collectMatchingObserversForMutation(HashMap<Ref<MutationObserver>, MutationRecordDeliveryOptions>& observers, Registry& registry, Node& target, MutationObserver::MutationType type, const QualifiedName* attributeName)
 2255Vector<std::unique_ptr<MutationObserverRegistration>>* Node::mutationObserverRegistry()
 2256{
 2257 if (!hasRareData())
 2258 return nullptr;
 2259 auto* data = rareData()->mutationObserverData();
 2260 if (!data)
 2261 return nullptr;
 2262 return &data->registry;
 2263}
 2264
 2265HashSet<MutationObserverRegistration*>* Node::transientMutationObserverRegistry()
22512266{
2252  for (auto& registration : registry) {
 2267 if (!hasRareData())
 2268 return nullptr;
 2269 auto* data = rareData()->mutationObserverData();
 2270 if (!data)
 2271 return nullptr;
 2272 return &data->transientRegistry;
 2273}
 2274
 2275template<typename Registry> static inline void collectMatchingObserversForMutation(HashMap<Ref<MutationObserver>, MutationRecordDeliveryOptions>& observers, Registry* registry, Node& target, MutationObserver::MutationType type, const QualifiedName* attributeName)
 2276{
 2277 if (!registry)
 2278 return;
 2279
 2280 for (auto& registration : *registry) {
22532281 if (registration->shouldReceiveMutationFrom(target, type, attributeName)) {
22542282 auto deliveryOptions = registration->deliveryOptions();
22552283 auto result = observers.add(registration->observer(), deliveryOptions);

@@HashMap<Ref<MutationObserver>, MutationRecordDeliveryOptions> Node::registeredMu
22632291{
22642292 HashMap<Ref<MutationObserver>, MutationRecordDeliveryOptions> result;
22652293 ASSERT((type == MutationObserver::Attributes && attributeName) || !attributeName);
2266  for (auto node = makeRefPtr(this); node; node = node->parentNode()) {
2267  if (!node->hasRareData())
2268  continue;
2269  auto* rareData = node->rareData();
2270  if (auto* registry = rareData->mutationObserverRegistryIfExists())
2271  collectMatchingObserversForMutation(result, *registry, *this, type, attributeName);
2272  collectMatchingObserversForMutation(result, rareData->transientMutationObserverRegistry(), *this, type, attributeName);
 2294 collectMatchingObserversForMutation(result, mutationObserverRegistry(), *this, type, attributeName);
 2295 collectMatchingObserversForMutation(result, transientMutationObserverRegistry(), *this, type, attributeName);
 2296 for (Node* node = parentNode(); node; node = node->parentNode()) {
 2297 collectMatchingObserversForMutation(result, node->mutationObserverRegistry(), *this, type, attributeName);
 2298 collectMatchingObserversForMutation(result, node->transientMutationObserverRegistry(), *this, type, attributeName);
22732299 }
22742300 return result;
22752301}
22762302
22772303void Node::registerMutationObserver(MutationObserver& observer, MutationObserverOptions options, const HashSet<AtomString>& attributeFilter)
22782304{
2279  auto& registry = ensureRareData().mutationObserverRegistry();
2280  auto index = registry.findMatching([&observer](auto& registration) { return &registration->observer() == &observer; });
2281  if (index != notFound) {
2282  auto registration = registry[index].copyRef();
2283  registration->resetObservation(options, attributeFilter);
2284  document().addMutationObserverTypes(registration->mutationTypes());
2285  return;
 2305 MutationObserverRegistration* registration = nullptr;
 2306 auto& registry = ensureRareData().ensureMutationObserverData().registry;
 2307
 2308 for (auto& candidateRegistration : registry) {
 2309 if (&candidateRegistration->observer() == &observer) {
 2310 registration = candidateRegistration.get();
 2311 registration->resetObservation(options, attributeFilter);
 2312 }
22862313 }
2287  auto newRegistration = MutationObserverRegistration::create(observer, *this, options, attributeFilter);
2288  document().addMutationObserverTypes(newRegistration->mutationTypes());
2289  registry.append(WTFMove(newRegistration));
 2314
 2315 if (!registration) {
 2316 registry.append(makeUnique<MutationObserverRegistration>(observer, *this, options, attributeFilter));
 2317 registration = registry.last().get();
 2318 }
 2319
 2320 document().addMutationObserverTypes(registration->mutationTypes());
22902321}
22912322
22922323void Node::unregisterMutationObserver(MutationObserverRegistration& registration)
22932324{
2294  ASSERT(hasRareData());
2295  auto* registry = rareData()->mutationObserverRegistryIfExists();
 2325 auto* registry = mutationObserverRegistry();
22962326 ASSERT(registry);
2297  auto removed = registry->removeFirstMatching([&registration] (auto& current) {
2298  return current.ptr() == &registration;
 2327 if (!registry)
 2328 return;
 2329
 2330 registry->removeFirstMatching([&registration] (auto& current) {
 2331 return current.get() == &registration;
22992332 });
2300  RELEASE_ASSERT(removed);
23012333}
23022334
23032335void Node::registerTransientMutationObserver(MutationObserverRegistration& registration)
23042336{
2305  ensureRareData().transientMutationObserverRegistry().add(registration);
 2337 ensureRareData().ensureMutationObserverData().transientRegistry.add(&registration);
23062338}
23072339
23082340void Node::unregisterTransientMutationObserver(MutationObserverRegistration& registration)
23092341{
2310  ASSERT(hasRareData());
2311  bool removed = rareData()->transientMutationObserverRegistry().remove(&registration);
2312  RELEASE_ASSERT(removed);
 2342 auto* transientRegistry = transientMutationObserverRegistry();
 2343 ASSERT(transientRegistry);
 2344 if (!transientRegistry)
 2345 return;
 2346
 2347 ASSERT(transientRegistry->contains(&registration));
 2348 transientRegistry->remove(&registration);
23132349}
23142350
23152351void Node::notifyMutationObserversNodeWillDetach()

@@void Node::notifyMutationObserversNodeWillDetach()
23182354 return;
23192355
23202356 for (Node* node = parentNode(); node; node = node->parentNode()) {
2321  if (!node->hasRareData())
2322  continue;
2323  auto* rareData = node->rareData();
2324  if (auto* registry = rareData->mutationObserverRegistryIfExists()) {
 2357 if (auto* registry = node->mutationObserverRegistry()) {
23252358 for (auto& registration : *registry)
23262359 registration->observedSubtreeNodeWillDetach(*this);
23272360 }
2328  for (auto& registration : rareData->transientMutationObserverRegistry())
2329  registration->observedSubtreeNodeWillDetach(*this);
 2361 if (auto* transientRegistry = node->transientMutationObserverRegistry()) {
 2362 for (auto* registration : *transientRegistry)
 2363 registration->observedSubtreeNodeWillDetach(*this);
 2364 }
23302365 }
23312366}
23322367

Source/WebCore/dom/Node.h

@@private:
700700 void trackForDebugging();
701701 void materializeRareData();
702702
 703 Vector<std::unique_ptr<MutationObserverRegistration>>* mutationObserverRegistry();
 704 HashSet<MutationObserverRegistration*>* transientMutationObserverRegistry();
 705
703706 void adjustStyleValidity(Style::Validity, Style::InvalidationMode);
704707
705708 void* opaqueRootSlow() const;

Source/WebCore/dom/NodeRareData.cpp

@@namespace WebCore {
3838struct SameSizeAsNodeRareData {
3939 uint32_t m_tabIndex;
4040 uint32_t m_childIndexAndIsElementRareDataFlag;
41  void* m_pointer[3];
42 #if CHECK_HASHTABLE_ITERATORS
43  void* m_hashTableIteratorsAndMutex[2];
44 #endif
 41 void* m_pointer[2];
4542};
4643
4744COMPILE_ASSERT(sizeof(NodeRareData) == sizeof(SameSizeAsNodeRareData), NodeRareDataShouldStaySmall);

Source/WebCore/dom/NodeRareData.h

@@private:
229229 CollectionCacheMap m_cachedCollections;
230230};
231231
 232class NodeMutationObserverData {
 233 WTF_MAKE_NONCOPYABLE(NodeMutationObserverData); WTF_MAKE_FAST_ALLOCATED;
 234public:
 235 Vector<std::unique_ptr<MutationObserverRegistration>> registry;
 236 HashSet<MutationObserverRegistration*> transientRegistry;
 237
 238 NodeMutationObserverData() { }
 239};
 240
232241DECLARE_ALLOCATOR_WITH_HEAP_IDENTIFIER(NodeRareData);
233242class NodeRareData {
234243 WTF_MAKE_NONCOPYABLE(NodeRareData);

@@public:
275284 return *m_nodeLists;
276285 }
277286
278  using MutationObserverRegistryVector = Vector<Ref<MutationObserverRegistration>, 4>;
279 
280  MutationObserverRegistryVector& mutationObserverRegistry()
281  {
282  if (!m_mutationObserverRegistry)
283  m_mutationObserverRegistry = makeUnique<MutationObserverRegistryVector>();
284  return *m_mutationObserverRegistry;
285  }
286  MutationObserverRegistryVector* mutationObserverRegistryIfExists()
287  {
288  return m_mutationObserverRegistry.get();
289  }
290  HashSet<Ref<MutationObserverRegistration>>& transientMutationObserverRegistry()
 287 NodeMutationObserverData* mutationObserverData() { return m_mutationObserverData.get(); }
 288 NodeMutationObserverData& ensureMutationObserverData()
291289 {
292  return m_transientMutationObserverRegistry;
 290 if (!m_mutationObserverData)
 291 m_mutationObserverData = makeUnique<NodeMutationObserverData>();
 292 return *m_mutationObserverData;
293293 }
294294
295295#if DUMP_NODE_STATISTICS

@@public:
298298 OptionSet<UseType> result;
299299 if (m_nodeLists)
300300 result.add(UseType::NodeList);
301  if (m_mutationObserverRegistry || m_transientMutationObserverRegistry.capacity())
 301 if (m_mutationObserverData)
302302 result.add(UseType::MutationObserver);
303303 return result;
304304 }

@@private:
313313 bool m_isElementRareData;
314314
315315 std::unique_ptr<NodeListsNodeData> m_nodeLists;
316  std::unique_ptr<MutationObserverRegistryVector> m_mutationObserverRegistry;
317  HashSet<Ref<MutationObserverRegistration>> m_transientMutationObserverRegistry;
 316 std::unique_ptr<NodeMutationObserverData> m_mutationObserverData;
318317};
319318
320319template<> struct NodeListTypeIdentifier<NameNodeList> {

LayoutTests/ChangeLog

 12020-10-19 Commit Queue <commit-queue@webkit.org>
 2
 3 Unreviewed, reverting r267175 and r267779.
 4 https://bugs.webkit.org/show_bug.cgi?id=217923
 5
 6 Regressed NYTimes's DOM content loaded time by 400%
 7
 8 Reverted changesets:
 9
 10 "MutationObserverRegistration should be ref counted"
 11 https://bugs.webkit.org/show_bug.cgi?id=216528
 12 https://trac.webkit.org/changeset/267175
 13
 14 "Crash while loading a confluence page"
 15 https://bugs.webkit.org/show_bug.cgi?id=217111
 16 https://trac.webkit.org/changeset/267779
 17
1182020-10-19 Hector Lopez <hector_i_lopez@apple.com>
219
320 REGRESSION(r268615-268616?): [ Win10 wk1 EWS ] 3 animation tests are a constant failure

LayoutTests/fast/dom/MutationObserver/disconnect-twice-expected.txt

1 This tests disconnecting MutationObserver twice while keeping a transient observation going.
2 WebKit should not crash and you should see PASS below.
3 
4 PASS

LayoutTests/fast/dom/MutationObserver/disconnect-twice.html

1 <!DOCTYPE html>
2 <html>
3 <body>
4 <p>This tests disconnecting MutationObserver twice while keeping a transient observation going.<br>
5 WebKit should not crash and you should see PASS below.</p>
6 <div id="child"><div></div></div>
7 <script>
8 
9 if (window.testRunner)
10  testRunner.dumpAsText();
11 
12 const observer = new MutationObserver((records) => {
13 });
14 
15 observer.observe(document.body, {childList: true, subtree: true});
16 child.remove();
17 observer.disconnect();
18 observer.disconnect();
19 
20 document.write('PASS');
21 
22 </script>
23 </body>
24 </html>