1 /*
2  * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
3  *           (C) 1999 Antti Koivisto (koivisto@kde.org)
4  *           (C) 2001 Dirk Mueller (mueller@kde.org)
5  * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All
6  * rights reserved.
7  * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
8  * Copyright (C) 2009 Torch Mobile Inc. All rights reserved.
9  * (http://www.torchmobile.com/)
10  *
11  * This library is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU Library General Public
13  * License as published by the Free Software Foundation; either
14  * version 2 of the License, or (at your option) any later version.
15  *
16  * This library is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
19  * Library General Public License for more details.
20  *
21  * You should have received a copy of the GNU Library General Public License
22  * along with this library; see the file COPYING.LIB.  If not, write to
23  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
24  * Boston, MA 02110-1301, USA.
25  */
26 
27 #include "third_party/blink/renderer/core/dom/node.h"
28 
29 #include <algorithm>
30 
31 #include "third_party/blink/public/mojom/input/focus_type.mojom-blink.h"
32 #include "third_party/blink/renderer/bindings/core/v8/node_or_string_or_trusted_script.h"
33 #include "third_party/blink/renderer/bindings/core/v8/string_or_trusted_script.h"
34 #include "third_party/blink/renderer/bindings/core/v8/v8_get_root_node_options.h"
35 #include "third_party/blink/renderer/core/accessibility/ax_object_cache.h"
36 #include "third_party/blink/renderer/core/animation/scroll_timeline.h"
37 #include "third_party/blink/renderer/core/css/css_selector.h"
38 #include "third_party/blink/renderer/core/css/resolver/style_resolver.h"
39 #include "third_party/blink/renderer/core/css/style_change_reason.h"
40 #include "third_party/blink/renderer/core/css/style_engine.h"
41 #include "third_party/blink/renderer/core/display_lock/display_lock_document_state.h"
42 #include "third_party/blink/renderer/core/display_lock/display_lock_utilities.h"
43 #include "third_party/blink/renderer/core/dom/attr.h"
44 #include "third_party/blink/renderer/core/dom/attribute.h"
45 #include "third_party/blink/renderer/core/dom/child_list_mutation_scope.h"
46 #include "third_party/blink/renderer/core/dom/child_node_list.h"
47 #include "third_party/blink/renderer/core/dom/document.h"
48 #include "third_party/blink/renderer/core/dom/document_fragment.h"
49 #include "third_party/blink/renderer/core/dom/document_type.h"
50 #include "third_party/blink/renderer/core/dom/dom_node_ids.h"
51 #include "third_party/blink/renderer/core/dom/element.h"
52 #include "third_party/blink/renderer/core/dom/element_rare_data.h"
53 #include "third_party/blink/renderer/core/dom/element_traversal.h"
54 #include "third_party/blink/renderer/core/dom/events/add_event_listener_options_resolved.h"
55 #include "third_party/blink/renderer/core/dom/events/event.h"
56 #include "third_party/blink/renderer/core/dom/events/event_dispatch_forbidden_scope.h"
57 #include "third_party/blink/renderer/core/dom/events/event_dispatcher.h"
58 #include "third_party/blink/renderer/core/dom/events/event_listener.h"
59 #include "third_party/blink/renderer/core/dom/events/event_path.h"
60 #include "third_party/blink/renderer/core/dom/flat_tree_node_data.h"
61 #include "third_party/blink/renderer/core/dom/flat_tree_traversal.h"
62 #include "third_party/blink/renderer/core/dom/layout_tree_builder_traversal.h"
63 #include "third_party/blink/renderer/core/dom/mutation_observer_registration.h"
64 #include "third_party/blink/renderer/core/dom/node_computed_style.h"
65 #include "third_party/blink/renderer/core/dom/node_lists_node_data.h"
66 #include "third_party/blink/renderer/core/dom/node_rare_data.h"
67 #include "third_party/blink/renderer/core/dom/node_traversal.h"
68 #include "third_party/blink/renderer/core/dom/processing_instruction.h"
69 #include "third_party/blink/renderer/core/dom/range.h"
70 #include "third_party/blink/renderer/core/dom/shadow_root.h"
71 #include "third_party/blink/renderer/core/dom/slot_assignment.h"
72 #include "third_party/blink/renderer/core/dom/slot_assignment_engine.h"
73 #include "third_party/blink/renderer/core/dom/static_node_list.h"
74 #include "third_party/blink/renderer/core/dom/template_content_document_fragment.h"
75 #include "third_party/blink/renderer/core/dom/text.h"
76 #include "third_party/blink/renderer/core/dom/tree_scope_adopter.h"
77 #include "third_party/blink/renderer/core/dom/user_action_element_set.h"
78 #include "third_party/blink/renderer/core/dom/v0_insertion_point.h"
79 #include "third_party/blink/renderer/core/editing/editing_utilities.h"
80 #include "third_party/blink/renderer/core/editing/markers/document_marker_controller.h"
81 #include "third_party/blink/renderer/core/events/event_util.h"
82 #include "third_party/blink/renderer/core/events/gesture_event.h"
83 #include "third_party/blink/renderer/core/events/input_event.h"
84 #include "third_party/blink/renderer/core/events/keyboard_event.h"
85 #include "third_party/blink/renderer/core/events/mouse_event.h"
86 #include "third_party/blink/renderer/core/events/mutation_event.h"
87 #include "third_party/blink/renderer/core/events/pointer_event.h"
88 #include "third_party/blink/renderer/core/events/pointer_event_factory.h"
89 #include "third_party/blink/renderer/core/events/text_event.h"
90 #include "third_party/blink/renderer/core/events/touch_event.h"
91 #include "third_party/blink/renderer/core/events/ui_event.h"
92 #include "third_party/blink/renderer/core/events/wheel_event.h"
93 #include "third_party/blink/renderer/core/exported/web_plugin_container_impl.h"
94 #include "third_party/blink/renderer/core/frame/event_handler_registry.h"
95 #include "third_party/blink/renderer/core/frame/local_dom_window.h"
96 #include "third_party/blink/renderer/core/frame/local_frame.h"
97 #include "third_party/blink/renderer/core/frame/local_frame_client.h"
98 #include "third_party/blink/renderer/core/frame/local_frame_view.h"
99 #include "third_party/blink/renderer/core/frame/visual_viewport.h"
100 #include "third_party/blink/renderer/core/fullscreen/fullscreen.h"
101 #include "third_party/blink/renderer/core/html/custom/custom_element.h"
102 #include "third_party/blink/renderer/core/html/html_dialog_element.h"
103 #include "third_party/blink/renderer/core/html/html_frame_owner_element.h"
104 #include "third_party/blink/renderer/core/html/html_slot_element.h"
105 #include "third_party/blink/renderer/core/html_names.h"
106 #include "third_party/blink/renderer/core/input/event_handler.h"
107 #include "third_party/blink/renderer/core/input/input_device_capabilities.h"
108 #include "third_party/blink/renderer/core/layout/layout_box.h"
109 #include "third_party/blink/renderer/core/layout/layout_embedded_content.h"
110 #include "third_party/blink/renderer/core/layout/layout_shift_tracker.h"
111 #include "third_party/blink/renderer/core/layout/layout_view.h"
112 #include "third_party/blink/renderer/core/mathml_names.h"
113 #include "third_party/blink/renderer/core/page/context_menu_controller.h"
114 #include "third_party/blink/renderer/core/page/page.h"
115 #include "third_party/blink/renderer/core/page/scrolling/scroll_customization_callbacks.h"
116 #include "third_party/blink/renderer/core/page/scrolling/scroll_state.h"
117 #include "third_party/blink/renderer/core/page/scrolling/scroll_state_callback.h"
118 #include "third_party/blink/renderer/core/page/scrolling/top_document_root_scroller_controller.h"
119 #include "third_party/blink/renderer/core/paint/paint_layer.h"
120 #include "third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h"
121 #include "third_party/blink/renderer/core/probe/core_probes.h"
122 #include "third_party/blink/renderer/core/svg/graphics/svg_image.h"
123 #include "third_party/blink/renderer/core/svg/svg_element.h"
124 #include "third_party/blink/renderer/core/trustedtypes/trusted_script.h"
125 #include "third_party/blink/renderer/platform/bindings/dom_data_store.h"
126 #include "third_party/blink/renderer/platform/bindings/exception_state.h"
127 #include "third_party/blink/renderer/platform/bindings/microtask.h"
128 #include "third_party/blink/renderer/platform/bindings/v8_dom_wrapper.h"
129 #include "third_party/blink/renderer/platform/heap/heap.h"
130 #include "third_party/blink/renderer/platform/instrumentation/instance_counters.h"
131 #include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h"
132 #include "third_party/blink/renderer/platform/instrumentation/tracing/traced_value.h"
133 #include "third_party/blink/renderer/platform/instrumentation/use_counter.h"
134 #include "third_party/blink/renderer/platform/runtime_enabled_features.h"
135 #include "third_party/blink/renderer/platform/wtf/allocator/partitions.h"
136 #include "third_party/blink/renderer/platform/wtf/hash_set.h"
137 #include "third_party/blink/renderer/platform/wtf/size_assertions.h"
138 #include "third_party/blink/renderer/platform/wtf/text/character_visitor.h"
139 #include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
140 #include "third_party/blink/renderer/platform/wtf/vector.h"
141 
142 namespace blink {
143 
144 namespace {
145 
146 // We need to retain the scroll customization callbacks until the element
147 // they're associated with is destroyed. It would be simplest if the callbacks
148 // could be stored in ElementRareData, but we can't afford the space increase.
149 // Instead, keep the scroll customization callbacks here. The other option would
150 // be to store these callbacks on the Page or document, but that necessitates a
151 // bunch more logic for transferring the callbacks between Pages when elements
152 // are moved around.
GetScrollCustomizationCallbacks()153 ScrollCustomizationCallbacks& GetScrollCustomizationCallbacks() {
154   DEFINE_STATIC_LOCAL(Persistent<ScrollCustomizationCallbacks>,
155                       scroll_customization_callbacks,
156                       (MakeGarbageCollected<ScrollCustomizationCallbacks>()));
157   return *scroll_customization_callbacks;
158 }
159 
160 // TODO(crbug.com/545926): Unsafe hack to avoid triggering the
161 // ThreadRestrictionVerifier on StringImpl. This should be fixed completely, and
162 // we should always avoid accessing these strings from the impl thread.
163 // Currently code that calls into this method from the impl thread tries to make
164 // sure that the main thread is not running at this time.
AppendUnsafe(StringBuilder & builder,const String & off_thread_string)165 void AppendUnsafe(StringBuilder& builder, const String& off_thread_string) {
166   StringImpl* impl = off_thread_string.Impl();
167   if (impl) {
168     WTF::VisitCharacters(*impl, [&](const auto* chars, unsigned length) {
169       builder.Append(chars, length);
170     });
171   }
172 }
173 
174 }  // namespace
175 
176 using ReattachHookScope = LayoutShiftTracker::ReattachHookScope;
177 
178 struct SameSizeAsNode : EventTarget {
179   uint32_t node_flags_;
180   Member<void*> willbe_member_[4];
181   Member<NodeData> member_;
182 #if !DCHECK_IS_ON()
183   // Increasing size of Member increases size of Node.
184   ASSERT_SIZE(Member<NodeData>, void*);
185 #endif  // !DCHECK_IS_ON()
186 };
187 
188 ASSERT_SIZE(Node, SameSizeAsNode);
189 
190 #if DUMP_NODE_STATISTICS
191 using WeakNodeSet = HeapHashSet<WeakMember<Node>>;
liveNodeSet()192 static WeakNodeSet& liveNodeSet() {
193   DEFINE_STATIC_LOCAL(WeakNodeSet, set, (new WeakNodeSet));
194   return set;
195 }
196 #endif
197 
DumpStatistics()198 void Node::DumpStatistics() {
199 #if DUMP_NODE_STATISTICS
200   size_t nodesWithRareData = 0;
201 
202   size_t elementNodes = 0;
203   size_t attrNodes = 0;
204   size_t textNodes = 0;
205   size_t cdataNodes = 0;
206   size_t commentNodes = 0;
207   size_t piNodes = 0;
208   size_t documentNodes = 0;
209   size_t docTypeNodes = 0;
210   size_t fragmentNodes = 0;
211   size_t shadowRootNodes = 0;
212 
213   HashMap<String, size_t> perTagCount;
214 
215   size_t attributes = 0;
216   size_t elementsWithAttributeStorage = 0;
217   size_t elementsWithRareData = 0;
218   size_t elementsWithNamedNodeMap = 0;
219 
220   {
221     ScriptForbiddenScope forbidScriptDuringRawIteration;
222     for (Node* node : liveNodeSet()) {
223       if (node->hasRareData()) {
224         ++nodesWithRareData;
225         if (auto* element = DynamicTo<Element>(node)) {
226           ++elementsWithRareData;
227           if (element->hasNamedNodeMap())
228             ++elementsWithNamedNodeMap;
229         }
230       }
231 
232       switch (node->getNodeType()) {
233         case kElementNode: {
234           ++elementNodes;
235 
236           // Tag stats
237           auto* element = To<Element>(node);
238           HashMap<String, size_t>::AddResult result =
239               perTagCount.add(element->tagName(), 1);
240           if (!result.isNewEntry)
241             result.storedValue->value++;
242 
243           size_t attributeCount = element->attributesWithoutUpdate().size();
244           if (attributeCount) {
245             attributes += attributeCount;
246             ++elementsWithAttributeStorage;
247           }
248           break;
249         }
250         case kAttributeNode: {
251           ++attrNodes;
252           break;
253         }
254         case kTextNode: {
255           ++textNodes;
256           break;
257         }
258         case kCdataSectionNode: {
259           ++cdataNodes;
260           break;
261         }
262         case kCommentNode: {
263           ++commentNodes;
264           break;
265         }
266         case kProcessingInstructionNode: {
267           ++piNodes;
268           break;
269         }
270         case kDocumentNode: {
271           ++documentNodes;
272           break;
273         }
274         case kDocumentTypeNode: {
275           ++docTypeNodes;
276           break;
277         }
278         case kDocumentFragmentNode: {
279           if (node->isShadowRoot())
280             ++shadowRootNodes;
281           else
282             ++fragmentNodes;
283           break;
284         }
285       }
286     }
287   }
288 
289   std::stringstream perTagStream;
290   for (const auto& entry : perTagCount)
291     perTagStream << "  Number of <" << entry.key.utf8().data()
292                  << "> tags: " << entry.value << "\n";
293 
294   LOG(INFO) << "\n"
295             << "Number of Nodes: " << liveNodeSet().size() << "\n"
296             << "Number of Nodes with RareData: " << nodesWithRareData << "\n\n"
297 
298             << "NodeType distribution:\n"
299             << "  Number of Element nodes: " << elementNodes << "\n"
300             << "  Number of Attribute nodes: " << attrNodes << "\n"
301             << "  Number of Text nodes: " << textNodes << "\n"
302             << "  Number of CDATASection nodes: " << cdataNodes << "\n"
303             << "  Number of Comment nodes: " << commentNodes << "\n"
304             << "  Number of ProcessingInstruction nodes: " << piNodes << "\n"
305             << "  Number of Document nodes: " << documentNodes << "\n"
306             << "  Number of DocumentType nodes: " << docTypeNodes << "\n"
307             << "  Number of DocumentFragment nodes: " << fragmentNodes << "\n"
308             << "  Number of ShadowRoot nodes: " << shadowRootNodes << "\n"
309 
310             << "Element tag name distibution:\n"
311             << perTagStream.str()
312 
313             << "Attributes:\n"
314             << "  Number of Attributes (non-Node and Node): " << attributes
315             << " x " << sizeof(Attribute) << "Bytes\n"
316             << "  Number of Elements with attribute storage: "
317             << elementsWithAttributeStorage << " x " << sizeof(ElementData)
318             << "Bytes\n"
319             << "  Number of Elements with RareData: " << elementsWithRareData
320             << "\n"
321             << "  Number of Elements with NamedNodeMap: "
322             << elementsWithNamedNodeMap << " x " << sizeof(NamedNodeMap)
323             << "Bytes";
324 #endif
325 }
326 
TrackForDebugging()327 void Node::TrackForDebugging() {
328 #if DUMP_NODE_STATISTICS
329   liveNodeSet().add(this);
330 #endif
331 }
332 
Node(TreeScope * tree_scope,ConstructionType type)333 Node::Node(TreeScope* tree_scope, ConstructionType type)
334     : node_flags_(type),
335       parent_or_shadow_host_node_(nullptr),
336       tree_scope_(tree_scope),
337       previous_(nullptr),
338       next_(nullptr),
339       data_(&NodeRenderingData::SharedEmptyData()) {
340   DCHECK(tree_scope_ || type == kCreateDocument || type == kCreateShadowRoot);
341 #if !defined(NDEBUG) || (defined(DUMP_NODE_STATISTICS) && DUMP_NODE_STATISTICS)
342   TrackForDebugging();
343 #endif
344   InstanceCounters::IncrementCounter(InstanceCounters::kNodeCounter);
345   // Document is required for probe sink.
346   if (tree_scope_)
347     probe::NodeCreated(this);
348 }
349 
~Node()350 Node::~Node() {
351   InstanceCounters::DecrementCounter(InstanceCounters::kNodeCounter);
352 }
353 
CreateRareData()354 NodeRareData& Node::CreateRareData() {
355   if (IsElementNode()) {
356     data_ = MakeGarbageCollected<ElementRareData>(DataAsNodeRenderingData());
357   } else {
358     data_ = MakeGarbageCollected<NodeRareData>(DataAsNodeRenderingData());
359   }
360 
361   DCHECK(data_);
362   SetFlag(kHasRareDataFlag);
363   return *RareData();
364 }
365 
ToNode()366 Node* Node::ToNode() {
367   return this;
368 }
369 
nodeValue() const370 String Node::nodeValue() const {
371   return String();
372 }
373 
setNodeValue(const String &)374 void Node::setNodeValue(const String&) {
375   // By default, setting nodeValue has no effect.
376 }
377 
parentNode() const378 ContainerNode* Node::parentNode() const {
379   return IsShadowRoot() ? nullptr : ParentOrShadowHostNode();
380 }
381 
childNodes()382 NodeList* Node::childNodes() {
383   auto* this_node = DynamicTo<ContainerNode>(this);
384   if (this_node)
385     return EnsureRareData().EnsureNodeLists().EnsureChildNodeList(*this_node);
386   return EnsureRareData().EnsureNodeLists().EnsureEmptyChildNodeList(*this);
387 }
388 
PseudoAwarePreviousSibling() const389 Node* Node::PseudoAwarePreviousSibling() const {
390   Element* parent = parentElement();
391   if (!parent || previousSibling())
392     return previousSibling();
393   switch (GetPseudoId()) {
394     case kPseudoIdAfter:
395       if (Node* previous = parent->lastChild())
396         return previous;
397       FALLTHROUGH;
398     case kPseudoIdNone:
399       if (Node* previous = parent->GetPseudoElement(kPseudoIdBefore))
400         return previous;
401       FALLTHROUGH;
402     case kPseudoIdBefore:
403       if (Node* previous = parent->GetPseudoElement(kPseudoIdMarker))
404         return previous;
405       FALLTHROUGH;
406     case kPseudoIdMarker:
407       break;
408     default:
409       NOTREACHED();
410   }
411   return nullptr;
412 }
413 
PseudoAwareNextSibling() const414 Node* Node::PseudoAwareNextSibling() const {
415   Element* parent = parentElement();
416   if (!parent || nextSibling())
417     return nextSibling();
418   switch (GetPseudoId()) {
419     case kPseudoIdMarker:
420       if (Node* next = parent->GetPseudoElement(kPseudoIdBefore))
421         return next;
422       FALLTHROUGH;
423     case kPseudoIdBefore:
424       if (parent->HasChildren())
425         return parent->firstChild();
426       FALLTHROUGH;
427     case kPseudoIdNone:
428       if (Node* next = parent->GetPseudoElement(kPseudoIdAfter))
429         return next;
430       FALLTHROUGH;
431     case kPseudoIdAfter:
432       break;
433     default:
434       NOTREACHED();
435   }
436   return nullptr;
437 }
438 
PseudoAwareFirstChild() const439 Node* Node::PseudoAwareFirstChild() const {
440   if (const auto* current_element = DynamicTo<Element>(this)) {
441     if (Node* first = current_element->GetPseudoElement(kPseudoIdMarker))
442       return first;
443     if (Node* first = current_element->GetPseudoElement(kPseudoIdBefore))
444       return first;
445     if (Node* first = current_element->firstChild())
446       return first;
447     return current_element->GetPseudoElement(kPseudoIdAfter);
448   }
449 
450   return firstChild();
451 }
452 
PseudoAwareLastChild() const453 Node* Node::PseudoAwareLastChild() const {
454   if (const auto* current_element = DynamicTo<Element>(this)) {
455     if (Node* last = current_element->GetPseudoElement(kPseudoIdAfter))
456       return last;
457     if (Node* last = current_element->lastChild())
458       return last;
459     if (Node* last = current_element->GetPseudoElement(kPseudoIdBefore))
460       return last;
461     return current_element->GetPseudoElement(kPseudoIdMarker);
462   }
463 
464   return lastChild();
465 }
466 
TreeRoot() const467 Node& Node::TreeRoot() const {
468   if (IsInTreeScope())
469     return ContainingTreeScope().RootNode();
470   const Node* node = this;
471   while (node->parentNode())
472     node = node->parentNode();
473   return const_cast<Node&>(*node);
474 }
475 
getRootNode(const GetRootNodeOptions * options) const476 Node* Node::getRootNode(const GetRootNodeOptions* options) const {
477   return (options->hasComposed() && options->composed())
478              ? &ShadowIncludingRoot()
479              : &TreeRoot();
480 }
481 
setDistributeScroll(V8ScrollStateCallback * scroll_state_callback,const String & native_scroll_behavior)482 void Node::setDistributeScroll(V8ScrollStateCallback* scroll_state_callback,
483                                const String& native_scroll_behavior) {
484   GetScrollCustomizationCallbacks().SetDistributeScroll(
485       this, ScrollStateCallbackV8Impl::Create(scroll_state_callback,
486                                               native_scroll_behavior));
487 }
488 
setApplyScroll(V8ScrollStateCallback * scroll_state_callback,const String & native_scroll_behavior)489 void Node::setApplyScroll(V8ScrollStateCallback* scroll_state_callback,
490                           const String& native_scroll_behavior) {
491   SetApplyScroll(ScrollStateCallbackV8Impl::Create(scroll_state_callback,
492                                                    native_scroll_behavior));
493 }
494 
SetApplyScroll(ScrollStateCallback * scroll_state_callback)495 void Node::SetApplyScroll(ScrollStateCallback* scroll_state_callback) {
496   GetScrollCustomizationCallbacks().SetApplyScroll(this, scroll_state_callback);
497 }
498 
RemoveApplyScroll()499 void Node::RemoveApplyScroll() {
500   GetScrollCustomizationCallbacks().RemoveApplyScroll(this);
501 }
502 
GetApplyScroll()503 ScrollStateCallback* Node::GetApplyScroll() {
504   return GetScrollCustomizationCallbacks().GetApplyScroll(this);
505 }
506 
NativeDistributeScroll(ScrollState & scroll_state)507 void Node::NativeDistributeScroll(ScrollState& scroll_state) {
508   if (scroll_state.FullyConsumed())
509     return;
510 
511   scroll_state.distributeToScrollChainDescendant();
512 
513   // The scroll doesn't propagate, and we're currently scrolling an element
514   // other than this one, prevent the scroll from propagating to this element.
515   if (scroll_state.DeltaConsumedForScrollSequence() &&
516       scroll_state.CurrentNativeScrollingNode() != this) {
517     return;
518   }
519 
520   const double delta_x = scroll_state.deltaX();
521   const double delta_y = scroll_state.deltaY();
522 
523   CallApplyScroll(scroll_state);
524 
525   if (delta_x != scroll_state.deltaX() || delta_y != scroll_state.deltaY())
526     scroll_state.SetCurrentNativeScrollingNode(this);
527 }
528 
NativeApplyScroll(ScrollState & scroll_state)529 void Node::NativeApplyScroll(ScrollState& scroll_state) {
530   if (!GetLayoutObject())
531     return;
532 
533   // All elements in the scroll chain should be boxes. However, in a scroll
534   // gesture sequence, the scroll chain is only computed on GestureScrollBegin.
535   // The type of layout object of the nodes in the scroll chain can change
536   // between GestureScrollUpdate and GestureScrollBegin (e.g. from script
537   // setting one of the nodes to display:inline). If there is no box there will
538   // not be a scrollable area to scroll, so just return.
539   if (!GetLayoutObject()->IsBox())
540     return;
541 
542   if (scroll_state.FullyConsumed())
543     return;
544 
545   FloatSize delta(scroll_state.deltaX(), scroll_state.deltaY());
546 
547   if (delta.IsZero())
548     return;
549 
550   // TODO: This should use updateStyleAndLayoutForNode.
551   GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kScroll);
552 
553   ScrollableArea* scrollable_area =
554       ScrollableArea::GetForScrolling(To<LayoutBox>(GetLayoutObject()));
555   if (!scrollable_area)
556     return;
557   LayoutBox* box_to_scroll = scrollable_area->GetLayoutBox();
558 
559   // TODO(bokan): This is a hack to fix https://crbug.com/977954. If we have a
560   // non-default root scroller, scrolling from one of its siblings or a fixed
561   // element will chain up to the root node without passing through the root
562   // scroller. This should scroll the visual viewport (so we can still pan
563   // while zoomed) but not by using the RootFrameViewport, which would cause
564   // scrolling in the root scroller element. Implementing this on the main
565   // thread is awkward since we assume only Nodes are scrollable but the
566   // VisualViewport isn't a Node. See LTHI::ApplyScroll for the equivalent
567   // behavior in CC.
568   bool also_scroll_visual_viewport = GetDocument().GetFrame() &&
569                                      GetDocument().GetFrame()->IsMainFrame() &&
570                                      IsA<LayoutView>(box_to_scroll);
571   DCHECK(!also_scroll_visual_viewport ||
572          !box_to_scroll->IsGlobalRootScroller());
573 
574   ScrollResult result =
575       scrollable_area->UserScroll(scroll_state.delta_granularity(), delta,
576                                   ScrollableArea::ScrollCallback());
577 
578   // Also try scrolling the visual viewport if we're at the end of the scroll
579   // chain.
580   if (!result.DidScroll() && also_scroll_visual_viewport) {
581     result = GetDocument().GetPage()->GetVisualViewport().UserScroll(
582         scroll_state.delta_granularity(), delta,
583         ScrollableArea::ScrollCallback());
584   }
585 
586   if (!result.DidScroll())
587     return;
588 
589   // FIXME: Native scrollers should only consume the scroll they
590   // apply. See crbug.com/457765.
591   scroll_state.ConsumeDeltaNative(delta.Width(), delta.Height());
592 
593   // We need to setCurrentNativeScrollingElement in both the
594   // distributeScroll and applyScroll default implementations so
595   // that if JS overrides one of these methods, but not the
596   // other, this bookkeeping remains accurate.
597   scroll_state.SetCurrentNativeScrollingNode(this);
598 }
599 
CallDistributeScroll(ScrollState & scroll_state)600 void Node::CallDistributeScroll(ScrollState& scroll_state) {
601   TRACE_EVENT0("input", "Node::CallDistributeScroll");
602   ScrollStateCallback* callback =
603       GetScrollCustomizationCallbacks().GetDistributeScroll(this);
604 
605   // TODO(bokan): Need to add tests before we allow calling custom callbacks
606   // for non-touch modalities. For now, just call into the native callback but
607   // allow the viewport scroll callback so we don't disable overscroll.
608   // crbug.com/623079.
609   bool disable_custom_callbacks = !scroll_state.isDirectManipulation() &&
610                                   !GetDocument()
611                                        .GetPage()
612                                        ->GlobalRootScrollerController()
613                                        .IsViewportScrollCallback(callback);
614 
615   bool is_global_root_scroller =
616       GetLayoutObject() && GetLayoutObject()->IsGlobalRootScroller();
617 
618   disable_custom_callbacks |=
619       !is_global_root_scroller &&
620       RuntimeEnabledFeatures::ScrollCustomizationEnabled() &&
621       !GetScrollCustomizationCallbacks().InScrollPhase(this);
622 
623   if (!callback || disable_custom_callbacks) {
624     NativeDistributeScroll(scroll_state);
625     return;
626   }
627   if (callback->GetNativeScrollBehavior() !=
628       NativeScrollBehavior::kPerformAfterNativeScroll)
629     callback->Invoke(&scroll_state);
630   if (callback->GetNativeScrollBehavior() !=
631       NativeScrollBehavior::kDisableNativeScroll)
632     NativeDistributeScroll(scroll_state);
633   if (callback->GetNativeScrollBehavior() ==
634       NativeScrollBehavior::kPerformAfterNativeScroll)
635     callback->Invoke(&scroll_state);
636 }
637 
CallApplyScroll(ScrollState & scroll_state)638 void Node::CallApplyScroll(ScrollState& scroll_state) {
639   TRACE_EVENT0("input", "Node::CallApplyScroll");
640 
641   if (!GetDocument().GetPage()) {
642     // We should always have a Page if we're scrolling. See
643     // crbug.com/689074 for details.
644     NOTREACHED();
645     return;
646   }
647 
648   ScrollStateCallback* callback =
649       GetScrollCustomizationCallbacks().GetApplyScroll(this);
650 
651   // TODO(bokan): Need to add tests before we allow calling custom callbacks
652   // for non-touch modalities. For now, just call into the native callback but
653   // allow the viewport scroll callback so we don't disable overscroll.
654   // crbug.com/623079.
655   bool disable_custom_callbacks = !scroll_state.isDirectManipulation() &&
656                                   !GetDocument()
657                                        .GetPage()
658                                        ->GlobalRootScrollerController()
659                                        .IsViewportScrollCallback(callback);
660 
661   bool is_global_root_scroller =
662       GetLayoutObject() && GetLayoutObject()->IsGlobalRootScroller();
663 
664   disable_custom_callbacks |=
665       !is_global_root_scroller &&
666       RuntimeEnabledFeatures::ScrollCustomizationEnabled() &&
667       !GetScrollCustomizationCallbacks().InScrollPhase(this);
668 
669   if (!callback || disable_custom_callbacks) {
670     NativeApplyScroll(scroll_state);
671     return;
672   }
673   if (callback->GetNativeScrollBehavior() !=
674       NativeScrollBehavior::kPerformAfterNativeScroll)
675     callback->Invoke(&scroll_state);
676   if (callback->GetNativeScrollBehavior() !=
677       NativeScrollBehavior::kDisableNativeScroll)
678     NativeApplyScroll(scroll_state);
679   if (callback->GetNativeScrollBehavior() ==
680       NativeScrollBehavior::kPerformAfterNativeScroll)
681     callback->Invoke(&scroll_state);
682 }
683 
WillBeginCustomizedScrollPhase(scroll_customization::ScrollDirection direction)684 void Node::WillBeginCustomizedScrollPhase(
685     scroll_customization::ScrollDirection direction) {
686   DCHECK(!GetScrollCustomizationCallbacks().InScrollPhase(this));
687   LayoutBox* box = GetLayoutBox();
688   if (!box)
689     return;
690 
691   scroll_customization::ScrollDirection scroll_customization =
692       box->Style()->ScrollCustomization();
693 
694   GetScrollCustomizationCallbacks().SetInScrollPhase(
695       this, direction & scroll_customization);
696 }
697 
DidEndCustomizedScrollPhase()698 void Node::DidEndCustomizedScrollPhase() {
699   GetScrollCustomizationCallbacks().SetInScrollPhase(this, false);
700 }
701 
insertBefore(Node * new_child,Node * ref_child,ExceptionState & exception_state)702 Node* Node::insertBefore(Node* new_child,
703                          Node* ref_child,
704                          ExceptionState& exception_state) {
705   auto* this_node = DynamicTo<ContainerNode>(this);
706   if (this_node)
707     return this_node->InsertBefore(new_child, ref_child, exception_state);
708 
709   exception_state.ThrowDOMException(
710       DOMExceptionCode::kHierarchyRequestError,
711       "This node type does not support this method.");
712   return nullptr;
713 }
714 
insertBefore(Node * new_child,Node * ref_child)715 Node* Node::insertBefore(Node* new_child, Node* ref_child) {
716   return insertBefore(new_child, ref_child, ASSERT_NO_EXCEPTION);
717 }
718 
replaceChild(Node * new_child,Node * old_child,ExceptionState & exception_state)719 Node* Node::replaceChild(Node* new_child,
720                          Node* old_child,
721                          ExceptionState& exception_state) {
722   auto* this_node = DynamicTo<ContainerNode>(this);
723   if (this_node)
724     return this_node->ReplaceChild(new_child, old_child, exception_state);
725 
726   exception_state.ThrowDOMException(
727       DOMExceptionCode::kHierarchyRequestError,
728       "This node type does not support this method.");
729   return nullptr;
730 }
731 
replaceChild(Node * new_child,Node * old_child)732 Node* Node::replaceChild(Node* new_child, Node* old_child) {
733   return replaceChild(new_child, old_child, ASSERT_NO_EXCEPTION);
734 }
735 
removeChild(Node * old_child,ExceptionState & exception_state)736 Node* Node::removeChild(Node* old_child, ExceptionState& exception_state) {
737   auto* this_node = DynamicTo<ContainerNode>(this);
738   if (this_node)
739     return this_node->RemoveChild(old_child, exception_state);
740 
741   exception_state.ThrowDOMException(
742       DOMExceptionCode::kNotFoundError,
743       "This node type does not support this method.");
744   return nullptr;
745 }
746 
removeChild(Node * old_child)747 Node* Node::removeChild(Node* old_child) {
748   return removeChild(old_child, ASSERT_NO_EXCEPTION);
749 }
750 
appendChild(Node * new_child,ExceptionState & exception_state)751 Node* Node::appendChild(Node* new_child, ExceptionState& exception_state) {
752   auto* this_node = DynamicTo<ContainerNode>(this);
753   if (this_node)
754     return this_node->AppendChild(new_child, exception_state);
755 
756   exception_state.ThrowDOMException(
757       DOMExceptionCode::kHierarchyRequestError,
758       "This node type does not support this method.");
759   return nullptr;
760 }
761 
appendChild(Node * new_child)762 Node* Node::appendChild(Node* new_child) {
763   return appendChild(new_child, ASSERT_NO_EXCEPTION);
764 }
765 
IsNodeInNodes(const Node * const node,const HeapVector<NodeOrStringOrTrustedScript> & nodes)766 static bool IsNodeInNodes(
767     const Node* const node,
768     const HeapVector<NodeOrStringOrTrustedScript>& nodes) {
769   for (const NodeOrStringOrTrustedScript& node_or_string : nodes) {
770     if (node_or_string.IsNode() && node_or_string.GetAsNode() == node)
771       return true;
772   }
773   return false;
774 }
775 
FindViablePreviousSibling(const Node & node,const HeapVector<NodeOrStringOrTrustedScript> & nodes)776 static Node* FindViablePreviousSibling(
777     const Node& node,
778     const HeapVector<NodeOrStringOrTrustedScript>& nodes) {
779   for (Node* sibling = node.previousSibling(); sibling;
780        sibling = sibling->previousSibling()) {
781     if (!IsNodeInNodes(sibling, nodes))
782       return sibling;
783   }
784   return nullptr;
785 }
786 
FindViableNextSibling(const Node & node,const HeapVector<NodeOrStringOrTrustedScript> & nodes)787 static Node* FindViableNextSibling(
788     const Node& node,
789     const HeapVector<NodeOrStringOrTrustedScript>& nodes) {
790   for (Node* sibling = node.nextSibling(); sibling;
791        sibling = sibling->nextSibling()) {
792     if (!IsNodeInNodes(sibling, nodes))
793       return sibling;
794   }
795   return nullptr;
796 }
797 
NodeOrStringToNode(const NodeOrStringOrTrustedScript & node_or_string,Document & document,bool needs_trusted_types_check,ExceptionState & exception_state)798 static Node* NodeOrStringToNode(
799     const NodeOrStringOrTrustedScript& node_or_string,
800     Document& document,
801     bool needs_trusted_types_check,
802     ExceptionState& exception_state) {
803   if (!needs_trusted_types_check) {
804     // Without trusted type checks, we simply extract the string from whatever
805     // constituent type we find.
806     if (node_or_string.IsNode())
807       return node_or_string.GetAsNode();
808     if (node_or_string.IsTrustedScript()) {
809       return Text::Create(document,
810                           node_or_string.GetAsTrustedScript()->toString());
811     }
812     return Text::Create(document, node_or_string.GetAsString());
813   }
814 
815   // With trusted type checks, we can process trusted script or non-text nodes
816   // directly. Strings or text nodes need to be checked.
817   if (node_or_string.IsNode() && !node_or_string.GetAsNode()->IsTextNode())
818     return node_or_string.GetAsNode();
819 
820   if (node_or_string.IsTrustedScript()) {
821     return Text::Create(document,
822                         node_or_string.GetAsTrustedScript()->toString());
823   }
824 
825   String string_value = node_or_string.IsString()
826                             ? node_or_string.GetAsString()
827                             : node_or_string.GetAsNode()->textContent();
828 
829   string_value = TrustedTypesCheckForScript(
830       string_value, document.GetExecutionContext(), exception_state);
831   if (exception_state.HadException())
832     return nullptr;
833   return Text::Create(document, string_value);
834 }
835 
836 // Returns nullptr if an exception was thrown.
ConvertNodesIntoNode(const Node * parent,const HeapVector<NodeOrStringOrTrustedScript> & nodes,Document & document,ExceptionState & exception_state)837 static Node* ConvertNodesIntoNode(
838     const Node* parent,
839     const HeapVector<NodeOrStringOrTrustedScript>& nodes,
840     Document& document,
841     ExceptionState& exception_state) {
842   bool needs_check = IsA<HTMLScriptElement>(parent) &&
843                      document.GetExecutionContext() &&
844                      document.GetExecutionContext()->RequireTrustedTypes();
845 
846   if (nodes.size() == 1)
847     return NodeOrStringToNode(nodes[0], document, needs_check, exception_state);
848 
849   Node* fragment = DocumentFragment::Create(document);
850   for (const NodeOrStringOrTrustedScript& node_or_string_or_trusted_script :
851        nodes) {
852     Node* node = NodeOrStringToNode(node_or_string_or_trusted_script, document,
853                                     needs_check, exception_state);
854     if (node)
855       fragment->appendChild(node, exception_state);
856     if (exception_state.HadException())
857       return nullptr;
858   }
859   return fragment;
860 }
861 
Prepend(const HeapVector<NodeOrStringOrTrustedScript> & nodes,ExceptionState & exception_state)862 void Node::Prepend(const HeapVector<NodeOrStringOrTrustedScript>& nodes,
863                    ExceptionState& exception_state) {
864   auto* this_node = DynamicTo<ContainerNode>(this);
865   if (!this_node) {
866     exception_state.ThrowDOMException(
867         DOMExceptionCode::kHierarchyRequestError,
868         "This node type does not support this method.");
869     return;
870   }
871 
872   if (Node* node =
873           ConvertNodesIntoNode(this, nodes, GetDocument(), exception_state))
874     this_node->InsertBefore(node, firstChild(), exception_state);
875 }
876 
Append(const HeapVector<NodeOrStringOrTrustedScript> & nodes,ExceptionState & exception_state)877 void Node::Append(const HeapVector<NodeOrStringOrTrustedScript>& nodes,
878                   ExceptionState& exception_state) {
879   auto* this_node = DynamicTo<ContainerNode>(this);
880   if (!this_node) {
881     exception_state.ThrowDOMException(
882         DOMExceptionCode::kHierarchyRequestError,
883         "This node type does not support this method.");
884     return;
885   }
886 
887   if (Node* node =
888           ConvertNodesIntoNode(this, nodes, GetDocument(), exception_state))
889     this_node->AppendChild(node, exception_state);
890 }
891 
Before(const HeapVector<NodeOrStringOrTrustedScript> & nodes,ExceptionState & exception_state)892 void Node::Before(const HeapVector<NodeOrStringOrTrustedScript>& nodes,
893                   ExceptionState& exception_state) {
894   Node* parent = parentNode();
895   if (!parent)
896     return;
897   auto* parent_node = DynamicTo<ContainerNode>(parent);
898   if (!parent_node) {
899     exception_state.ThrowDOMException(
900         DOMExceptionCode::kHierarchyRequestError,
901         "This node type does not support this method.");
902     return;
903   }
904   Node* viable_previous_sibling = FindViablePreviousSibling(*this, nodes);
905   if (Node* node =
906           ConvertNodesIntoNode(parent, nodes, GetDocument(), exception_state)) {
907     parent_node->InsertBefore(node,
908                               viable_previous_sibling
909                                   ? viable_previous_sibling->nextSibling()
910                                   : parent->firstChild(),
911                               exception_state);
912   }
913 }
914 
After(const HeapVector<NodeOrStringOrTrustedScript> & nodes,ExceptionState & exception_state)915 void Node::After(const HeapVector<NodeOrStringOrTrustedScript>& nodes,
916                  ExceptionState& exception_state) {
917   Node* parent = parentNode();
918   if (!parent)
919     return;
920   auto* parent_node = DynamicTo<ContainerNode>(parent);
921   if (!parent_node) {
922     exception_state.ThrowDOMException(
923         DOMExceptionCode::kHierarchyRequestError,
924         "This node type does not support this method.");
925     return;
926   }
927   Node* viable_next_sibling = FindViableNextSibling(*this, nodes);
928   if (Node* node =
929           ConvertNodesIntoNode(parent, nodes, GetDocument(), exception_state))
930     parent_node->InsertBefore(node, viable_next_sibling, exception_state);
931 }
932 
ReplaceWith(const HeapVector<NodeOrStringOrTrustedScript> & nodes,ExceptionState & exception_state)933 void Node::ReplaceWith(const HeapVector<NodeOrStringOrTrustedScript>& nodes,
934                        ExceptionState& exception_state) {
935   Node* parent = parentNode();
936   if (!parent)
937     return;
938   auto* parent_node = DynamicTo<ContainerNode>(parent);
939   if (!parent_node) {
940     exception_state.ThrowDOMException(
941         DOMExceptionCode::kHierarchyRequestError,
942         "This node type does not support this method.");
943     return;
944   }
945 
946   Node* viable_next_sibling = FindViableNextSibling(*this, nodes);
947   Node* node =
948       ConvertNodesIntoNode(parent, nodes, GetDocument(), exception_state);
949   if (exception_state.HadException())
950     return;
951   if (parent_node == parentNode())
952     parent_node->ReplaceChild(node, this, exception_state);
953   else
954     parent_node->InsertBefore(node, viable_next_sibling, exception_state);
955 }
956 
957 // https://dom.spec.whatwg.org/#dom-parentnode-replacechildren
ReplaceChildren(const HeapVector<NodeOrStringOrTrustedScript> & nodes,ExceptionState & exception_state)958 void Node::ReplaceChildren(const HeapVector<NodeOrStringOrTrustedScript>& nodes,
959                            ExceptionState& exception_state) {
960   auto* this_node = DynamicTo<ContainerNode>(this);
961   if (!this_node) {
962     exception_state.ThrowDOMException(
963         DOMExceptionCode::kHierarchyRequestError,
964         "This node type does not support this method.");
965     return;
966   }
967 
968   // 1. Let node be the result of converting nodes into a node given nodes and
969   // this’s node document.
970   Node* node =
971       ConvertNodesIntoNode(this, nodes, GetDocument(), exception_state);
972   if (exception_state.HadException())
973     return;
974 
975   // 2. Ensure pre-insertion validity of node into this before null.
976   if (!this_node->EnsurePreInsertionValidity(*node, nullptr, nullptr,
977                                              exception_state))
978     return;
979 
980   // 3. Replace all with node within this.
981   ChildListMutationScope mutation(*this);
982   while (Node* first_child = firstChild()) {
983     removeChild(first_child, exception_state);
984     if (exception_state.HadException())
985       return;
986   }
987 
988   appendChild(node, exception_state);
989 }
990 
remove(ExceptionState & exception_state)991 void Node::remove(ExceptionState& exception_state) {
992   if (ContainerNode* parent = parentNode())
993     parent->RemoveChild(this, exception_state);
994 }
995 
remove()996 void Node::remove() {
997   remove(ASSERT_NO_EXCEPTION);
998 }
999 
cloneNode(bool deep,ExceptionState & exception_state) const1000 Node* Node::cloneNode(bool deep, ExceptionState& exception_state) const {
1001   // https://dom.spec.whatwg.org/#dom-node-clonenode
1002 
1003   // 1. If this is a shadow root, then throw a "NotSupportedError" DOMException.
1004   if (IsShadowRoot()) {
1005     exception_state.ThrowDOMException(DOMExceptionCode::kNotSupportedError,
1006                                       "ShadowRoot nodes are not clonable.");
1007     return nullptr;
1008   }
1009 
1010   // 2. Return a clone of this, with the clone children flag set if deep is
1011   // true, and the clone shadows flag set if this is a DocumentFragment whose
1012   // host is an HTML template element.
1013   auto* fragment = DynamicTo<DocumentFragment>(this);
1014   bool clone_shadows_flag = fragment && fragment->IsTemplateContent() &&
1015                             RuntimeEnabledFeatures::DeclarativeShadowDOMEnabled(
1016                                 GetExecutionContext());
1017   return Clone(GetDocument(),
1018                deep ? (clone_shadows_flag ? CloneChildrenFlag::kCloneWithShadows
1019                                           : CloneChildrenFlag::kClone)
1020                     : CloneChildrenFlag::kSkip);
1021 }
1022 
cloneNode(bool deep) const1023 Node* Node::cloneNode(bool deep) const {
1024   return cloneNode(deep, ASSERT_NO_EXCEPTION);
1025 }
1026 
normalize()1027 void Node::normalize() {
1028   UpdateDistributionForFlatTreeTraversal();
1029 
1030   // Go through the subtree beneath us, normalizing all nodes. This means that
1031   // any two adjacent text nodes are merged and any empty text nodes are
1032   // removed.
1033 
1034   Node* node = this;
1035   while (Node* first_child = node->firstChild())
1036     node = first_child;
1037   while (node) {
1038     if (node == this)
1039       break;
1040 
1041     if (node->getNodeType() == kTextNode)
1042       node = To<Text>(node)->MergeNextSiblingNodesIfPossible();
1043     else
1044       node = NodeTraversal::NextPostOrder(*node);
1045   }
1046 }
1047 
GetLayoutBox() const1048 LayoutBox* Node::GetLayoutBox() const {
1049   return DynamicTo<LayoutBox>(GetLayoutObject());
1050 }
1051 
SetLayoutObject(LayoutObject * layout_object)1052 void Node::SetLayoutObject(LayoutObject* layout_object) {
1053   NodeRenderingData* node_layout_data =
1054       HasRareData() ? DataAsNodeRareData()->GetNodeRenderingData()
1055                     : DataAsNodeRenderingData();
1056 
1057   // Already pointing to a non empty NodeRenderingData so just set the pointer
1058   // to the new LayoutObject.
1059   if (!node_layout_data->IsSharedEmptyData()) {
1060     node_layout_data->SetLayoutObject(layout_object);
1061     return;
1062   }
1063 
1064   if (!layout_object)
1065     return;
1066 
1067   // Swap the NodeRenderingData to point to a new NodeRenderingData instead of
1068   // the static SharedEmptyData instance.
1069   DCHECK(!node_layout_data->GetComputedStyle());
1070   node_layout_data =
1071       MakeGarbageCollected<NodeRenderingData>(layout_object, nullptr);
1072   if (HasRareData()) {
1073     DataAsNodeRareData()->SetNodeRenderingData(node_layout_data);
1074   } else {
1075     data_ = node_layout_data;
1076   }
1077 }
1078 
SetComputedStyle(scoped_refptr<const ComputedStyle> computed_style)1079 void Node::SetComputedStyle(scoped_refptr<const ComputedStyle> computed_style) {
1080   // We don't set computed style for text nodes.
1081   DCHECK(IsElementNode());
1082 
1083   NodeRenderingData* node_layout_data =
1084       HasRareData() ? DataAsNodeRareData()->GetNodeRenderingData()
1085                     : DataAsNodeRenderingData();
1086 
1087   // Already pointing to a non empty NodeRenderingData so just set the pointer
1088   // to the new LayoutObject.
1089   if (!node_layout_data->IsSharedEmptyData()) {
1090     node_layout_data->SetComputedStyle(computed_style);
1091     return;
1092   }
1093 
1094   if (!computed_style)
1095     return;
1096 
1097   // Ensure we only set computed style for elements which are not part of the
1098   // flat tree unless it's enforced for getComputedStyle().
1099   DCHECK(computed_style->IsEnsuredInDisplayNone() ||
1100          LayoutTreeBuilderTraversal::Parent(*this));
1101 
1102   // Swap the NodeRenderingData to point to a new NodeRenderingData instead of
1103   // the static SharedEmptyData instance.
1104   DCHECK(!node_layout_data->GetLayoutObject());
1105   node_layout_data =
1106       MakeGarbageCollected<NodeRenderingData>(nullptr, computed_style);
1107   if (HasRareData()) {
1108     DataAsNodeRareData()->SetNodeRenderingData(node_layout_data);
1109   } else {
1110     data_ = node_layout_data;
1111   }
1112 }
1113 
GetLayoutBoxModelObject() const1114 LayoutBoxModelObject* Node::GetLayoutBoxModelObject() const {
1115   return DynamicTo<LayoutBoxModelObject>(GetLayoutObject());
1116 }
1117 
BoundingBox() const1118 PhysicalRect Node::BoundingBox() const {
1119   if (GetLayoutObject())
1120     return PhysicalRect(GetLayoutObject()->AbsoluteBoundingBoxRect());
1121   return PhysicalRect();
1122 }
1123 
PixelSnappedBoundingBox() const1124 IntRect Node::PixelSnappedBoundingBox() const {
1125   return PixelSnappedIntRect(BoundingBox());
1126 }
1127 
BoundingBoxForScrollIntoView() const1128 PhysicalRect Node::BoundingBoxForScrollIntoView() const {
1129   if (GetLayoutObject()) {
1130     return GetLayoutObject()->AbsoluteBoundingBoxRectForScrollIntoView();
1131   }
1132 
1133   return PhysicalRect();
1134 }
1135 
ShadowIncludingRoot() const1136 Node& Node::ShadowIncludingRoot() const {
1137   if (isConnected())
1138     return GetDocument();
1139   Node* root = const_cast<Node*>(this);
1140   while (Node* host = root->OwnerShadowHost())
1141     root = host;
1142   while (Node* ancestor = root->parentNode())
1143     root = ancestor;
1144   DCHECK(!root->OwnerShadowHost());
1145   return *root;
1146 }
1147 
IsClosedShadowHiddenFrom(const Node & other) const1148 bool Node::IsClosedShadowHiddenFrom(const Node& other) const {
1149   if (!IsInShadowTree() || GetTreeScope() == other.GetTreeScope())
1150     return false;
1151 
1152   const TreeScope* scope = &GetTreeScope();
1153   for (; scope->ParentTreeScope(); scope = scope->ParentTreeScope()) {
1154     const ContainerNode& root = scope->RootNode();
1155     auto* shadow_root = DynamicTo<ShadowRoot>(root);
1156     if (shadow_root && !shadow_root->IsOpenOrV0())
1157       break;
1158   }
1159 
1160   for (TreeScope* other_scope = &other.GetTreeScope(); other_scope;
1161        other_scope = other_scope->ParentTreeScope()) {
1162     if (other_scope == scope)
1163       return false;
1164   }
1165   return true;
1166 }
1167 
NeedsDistributionRecalc() const1168 bool Node::NeedsDistributionRecalc() const {
1169   return ShadowIncludingRoot().ChildNeedsDistributionRecalc();
1170 }
1171 
MayContainLegacyNodeTreeWhereDistributionShouldBeSupported() const1172 bool Node::MayContainLegacyNodeTreeWhereDistributionShouldBeSupported() const {
1173   if (isConnected() && !GetDocument().MayContainV0Shadow()) {
1174     // TODO(crbug.com/787717): Some built-in elements still use <content>
1175     // elements in their user-agent shadow roots. DCHECK() fails if such an
1176     // element is used.
1177     DCHECK(!GetDocument().ChildNeedsDistributionRecalc());
1178     return false;
1179   }
1180   return true;
1181 }
1182 
UpdateDistributionForUnknownReasons()1183 void Node::UpdateDistributionForUnknownReasons() {
1184   UpdateDistributionInternal();
1185   // For the sake of safety, call RecalcSlotAssignments as well as
1186   // UpdateDistribution().
1187   if (isConnected())
1188     GetDocument().GetSlotAssignmentEngine().RecalcSlotAssignments();
1189 }
1190 
UpdateDistributionInternal()1191 void Node::UpdateDistributionInternal() {
1192   if (!MayContainLegacyNodeTreeWhereDistributionShouldBeSupported())
1193     return;
1194   // Extra early out to avoid spamming traces.
1195   if (isConnected() && !GetDocument().ChildNeedsDistributionRecalc())
1196     return;
1197   TRACE_EVENT0("blink", "Node::updateDistribution");
1198   ScriptForbiddenScope forbid_script;
1199   Node& root = ShadowIncludingRoot();
1200   if (root.ChildNeedsDistributionRecalc())
1201     root.RecalcDistribution();
1202 }
1203 
RecalcDistribution()1204 void Node::RecalcDistribution() {
1205   DCHECK(ChildNeedsDistributionRecalc());
1206 
1207   if (GetShadowRoot())
1208     GetShadowRoot()->DistributeIfNeeded();
1209 
1210   DCHECK(ScriptForbiddenScope::IsScriptForbidden());
1211   for (Node* child = firstChild(); child; child = child->nextSibling()) {
1212     if (child->ChildNeedsDistributionRecalc())
1213       child->RecalcDistribution();
1214   }
1215 
1216   if (ShadowRoot* root = GetShadowRoot()) {
1217     if (root->ChildNeedsDistributionRecalc())
1218       root->RecalcDistribution();
1219   }
1220 
1221   ClearChildNeedsDistributionRecalc();
1222 }
1223 
SetIsLink(bool is_link)1224 void Node::SetIsLink(bool is_link) {
1225   SetFlag(is_link && !SVGImage::IsInSVGImage(To<Element>(this)), kIsLinkFlag);
1226 }
1227 
SetNeedsStyleInvalidation()1228 void Node::SetNeedsStyleInvalidation() {
1229   DCHECK(IsContainerNode());
1230   SetFlag(kNeedsStyleInvalidationFlag);
1231   MarkAncestorsWithChildNeedsStyleInvalidation();
1232 }
1233 
MarkAncestorsWithChildNeedsStyleInvalidation()1234 void Node::MarkAncestorsWithChildNeedsStyleInvalidation() {
1235   ScriptForbiddenScope forbid_script_during_raw_iteration;
1236   ContainerNode* ancestor = ParentOrShadowHostNode();
1237   bool parent_dirty = ancestor && ancestor->NeedsStyleInvalidation();
1238   for (; ancestor && !ancestor->ChildNeedsStyleInvalidation();
1239        ancestor = ancestor->ParentOrShadowHostNode()) {
1240     if (!ancestor->isConnected())
1241       return;
1242     ancestor->SetChildNeedsStyleInvalidation();
1243     if (ancestor->NeedsStyleInvalidation())
1244       break;
1245   }
1246   if (!isConnected())
1247     return;
1248   // If the parent node is already dirty, we can keep the same invalidation
1249   // root. The early return here is a performance optimization.
1250   if (parent_dirty)
1251     return;
1252   GetDocument().GetStyleEngine().UpdateStyleInvalidationRoot(ancestor, this);
1253   GetDocument().ScheduleLayoutTreeUpdateIfNeeded();
1254 }
1255 
MarkAncestorsWithChildNeedsDistributionRecalc()1256 void Node::MarkAncestorsWithChildNeedsDistributionRecalc() {
1257   ScriptForbiddenScope forbid_script_during_raw_iteration;
1258   for (Node* node = this; node && !node->ChildNeedsDistributionRecalc();
1259        node = node->ParentOrShadowHostNode()) {
1260     node->SetChildNeedsDistributionRecalc();
1261   }
1262   GetDocument().ScheduleLayoutTreeUpdateIfNeeded();
1263 }
1264 
MarkSubtreeNeedsStyleRecalcForFontUpdates()1265 void Node::MarkSubtreeNeedsStyleRecalcForFontUpdates() {
1266   if (GetStyleChangeType() == kSubtreeStyleChange)
1267     return;
1268 
1269   if (IsElementNode()) {
1270     const ComputedStyle* style = GetComputedStyle();
1271     if (!style)
1272       return;
1273 
1274     // We require font-specific metrics to resolve length units 'ex' and 'ch',
1275     // and to compute the adjusted font size when 'font-size-adjust' is set. All
1276     // other style computations are unaffected by font loading.
1277     if (!NeedsStyleRecalc()) {
1278       if (style->DependsOnFontMetrics() ||
1279           To<Element>(this)->PseudoElementStylesDependOnFontMetrics()) {
1280         SetNeedsStyleRecalc(
1281             kLocalStyleChange,
1282             StyleChangeReasonForTracing::Create(style_change_reason::kFonts));
1283       }
1284     }
1285 
1286     if (Node* shadow_root = GetShadowRoot())
1287       shadow_root->MarkSubtreeNeedsStyleRecalcForFontUpdates();
1288   }
1289 
1290   for (Node* child = firstChild(); child; child = child->nextSibling())
1291     child->MarkSubtreeNeedsStyleRecalcForFontUpdates();
1292 }
1293 
1294 #if DCHECK_IS_ON()
1295 namespace {
1296 class AllowDirtyShadowV0TraversalScope {
1297   STACK_ALLOCATED();
1298 
1299  public:
AllowDirtyShadowV0TraversalScope(Document & document)1300   explicit AllowDirtyShadowV0TraversalScope(Document& document)
1301       : document_(&document),
1302         old_value_(document.AllowDirtyShadowV0Traversal()) {
1303     document.SetAllowDirtyShadowV0Traversal(true);
1304   }
~AllowDirtyShadowV0TraversalScope()1305   ~AllowDirtyShadowV0TraversalScope() {
1306     document_->SetAllowDirtyShadowV0Traversal(old_value_);
1307   }
1308 
1309  private:
1310   Document* document_;
1311   bool old_value_;
1312 };
1313 }  // namespace
1314 #define ALLOW_DIRTY_SHADOW_V0_TRAVERSAL_SCOPE(document) \
1315   AllowDirtyShadowV0TraversalScope traversal_scope(document)
1316 #else  // DCHECK_IS_ON()
1317 #define ALLOW_DIRTY_SHADOW_V0_TRAVERSAL_SCOPE(document)
1318 #endif  // DCHECK_IS_ON()
1319 
ShouldSkipMarkingStyleDirty() const1320 bool Node::ShouldSkipMarkingStyleDirty() const {
1321   if (GetComputedStyle())
1322     return false;
1323 
1324   ALLOW_DIRTY_SHADOW_V0_TRAVERSAL_SCOPE(GetDocument());
1325 
1326   // If we don't have a computed style, and our parent element does not have a
1327   // computed style it's not necessary to mark this node for style recalc.
1328   if (auto* parent = GetStyleRecalcParent()) {
1329     while (parent && !parent->CanParticipateInFlatTree())
1330       parent = parent->GetStyleRecalcParent();
1331     return !parent || !parent->GetComputedStyle();
1332   }
1333   // If this is the root element, and it does not have a computed style, we
1334   // still need to mark it for style recalc since it may change from
1335   // display:none. Otherwise, the node is not in the flat tree, and we can
1336   // skip marking it dirty.
1337   auto* root_element = GetDocument().documentElement();
1338   return root_element && root_element != this;
1339 }
1340 
MarkAncestorsWithChildNeedsStyleRecalc()1341 void Node::MarkAncestorsWithChildNeedsStyleRecalc() {
1342   ALLOW_DIRTY_SHADOW_V0_TRAVERSAL_SCOPE(GetDocument());
1343   ContainerNode* style_parent = GetStyleRecalcParent();
1344   bool parent_dirty = style_parent && style_parent->IsDirtyForStyleRecalc();
1345   ContainerNode* ancestor = style_parent;
1346   for (; ancestor && !ancestor->ChildNeedsStyleRecalc();
1347        ancestor = ancestor->GetStyleRecalcParent()) {
1348     if (!ancestor->isConnected())
1349       return;
1350     ancestor->SetChildNeedsStyleRecalc();
1351     if (ancestor->IsDirtyForStyleRecalc())
1352       break;
1353     // If we reach a locked ancestor, we should abort since the ancestor marking
1354     // will be done when the lock is committed.
1355     if (RuntimeEnabledFeatures::CSSContentVisibilityEnabled()) {
1356       auto* ancestor_element = DynamicTo<Element>(ancestor);
1357       if (ancestor_element &&
1358           ancestor_element->ChildStyleRecalcBlockedByDisplayLock()) {
1359         break;
1360       }
1361     }
1362   }
1363   if (!isConnected())
1364     return;
1365   // If the parent node is already dirty, we can keep the same recalc root. The
1366   // early return here is a performance optimization.
1367   if (parent_dirty)
1368     return;
1369   // If we are outside the flat tree we should not update the recalc root
1370   // because we should not traverse those nodes from StyleEngine::RecalcStyle().
1371   if (const ComputedStyle* current_style = GetComputedStyle()) {
1372     if (current_style->IsEnsuredOutsideFlatTree())
1373       return;
1374   } else {
1375     while (style_parent && !style_parent->CanParticipateInFlatTree())
1376       style_parent = style_parent->GetStyleRecalcParent();
1377     if (style_parent) {
1378       if (const auto* parent_style = style_parent->GetComputedStyle()) {
1379         if (parent_style->IsEnsuredOutsideFlatTree())
1380           return;
1381       }
1382     }
1383   }
1384   // If we're in a locked subtree, then we should not update the style recalc
1385   // roots. These would be updated when we commit the lock. If we have locked
1386   // display locks somewhere in the document, we iterate up the ancestor chain
1387   // to check if we're in one such subtree.
1388   if (RuntimeEnabledFeatures::CSSContentVisibilityEnabled() &&
1389       GetDocument().GetDisplayLockDocumentState().LockedDisplayLockCount() >
1390           0) {
1391     for (auto* ancestor_copy = ancestor; ancestor_copy;
1392          ancestor_copy = ancestor_copy->GetStyleRecalcParent()) {
1393       auto* ancestor_copy_element = DynamicTo<Element>(ancestor_copy);
1394       if (ancestor_copy_element &&
1395           ancestor_copy_element->ChildStyleRecalcBlockedByDisplayLock()) {
1396         return;
1397       }
1398     }
1399   }
1400 
1401   GetDocument().GetStyleEngine().UpdateStyleRecalcRoot(ancestor, this);
1402   GetDocument().ScheduleLayoutTreeUpdateIfNeeded();
1403 }
1404 
FlatTreeParentForChildDirty() const1405 Element* Node::FlatTreeParentForChildDirty() const {
1406   if (IsPseudoElement())
1407     return ParentOrShadowHostElement();
1408   if (IsChildOfV1ShadowHost()) {
1409     if (auto* data = GetFlatTreeNodeData())
1410       return data->AssignedSlot();
1411     return nullptr;
1412   }
1413   if (IsInV0ShadowTree() || IsChildOfV0ShadowHost()) {
1414     if (ShadowRootWhereNodeCanBeDistributedForV0(*this)) {
1415       if (V0InsertionPoint* insertion_point =
1416               const_cast<V0InsertionPoint*>(ResolveReprojection(this))) {
1417         return insertion_point;
1418       }
1419       return nullptr;
1420     }
1421   }
1422   return ParentOrShadowHostElement();
1423 }
1424 
MarkAncestorsWithChildNeedsReattachLayoutTree()1425 void Node::MarkAncestorsWithChildNeedsReattachLayoutTree() {
1426   DCHECK(isConnected());
1427   Element* ancestor = GetReattachParent();
1428   bool parent_dirty = ancestor && ancestor->NeedsReattachLayoutTree();
1429   for (; ancestor && !ancestor->ChildNeedsReattachLayoutTree();
1430        ancestor = ancestor->GetReattachParent()) {
1431     ancestor->SetChildNeedsReattachLayoutTree();
1432     if (ancestor->NeedsReattachLayoutTree())
1433       break;
1434   }
1435   // If the parent node is already dirty, we can keep the same rebuild root. The
1436   // early return here is a performance optimization.
1437   if (parent_dirty)
1438     return;
1439   GetDocument().GetStyleEngine().UpdateLayoutTreeRebuildRoot(ancestor, this);
1440 }
1441 
SetNeedsReattachLayoutTree()1442 void Node::SetNeedsReattachLayoutTree() {
1443   DCHECK(GetDocument().InStyleRecalc());
1444   DCHECK(!GetDocument().ChildNeedsDistributionRecalc());
1445   DCHECK(IsElementNode() || IsTextNode());
1446   DCHECK(InActiveDocument());
1447   SetFlag(kNeedsReattachLayoutTree);
1448   MarkAncestorsWithChildNeedsReattachLayoutTree();
1449 }
1450 
SetNeedsStyleRecalc(StyleChangeType change_type,const StyleChangeReasonForTracing & reason)1451 void Node::SetNeedsStyleRecalc(StyleChangeType change_type,
1452                                const StyleChangeReasonForTracing& reason) {
1453   DCHECK(!GetDocument().GetStyleEngine().InRebuildLayoutTree());
1454   DCHECK(change_type != kNoStyleChange);
1455   DCHECK(IsElementNode() || IsTextNode());
1456 
1457   if (!InActiveDocument())
1458     return;
1459   if (ShouldSkipMarkingStyleDirty())
1460     return;
1461 
1462   TRACE_EVENT_INSTANT1(
1463       TRACE_DISABLED_BY_DEFAULT("devtools.timeline.invalidationTracking"),
1464       "StyleRecalcInvalidationTracking", TRACE_EVENT_SCOPE_THREAD, "data",
1465       inspector_style_recalc_invalidation_tracking_event::Data(
1466           this, change_type, reason));
1467 
1468   StyleChangeType existing_change_type = GetStyleChangeType();
1469   if (change_type > existing_change_type)
1470     SetStyleChange(change_type);
1471 
1472   auto* this_element = DynamicTo<Element>(this);
1473   if (existing_change_type == kNoStyleChange)
1474     MarkAncestorsWithChildNeedsStyleRecalc();
1475 
1476   if (this_element && HasRareData())
1477     this_element->SetAnimationStyleChange(false);
1478 
1479   if (auto* svg_element = DynamicTo<SVGElement>(this))
1480     svg_element->SetNeedsStyleRecalcForInstances(change_type, reason);
1481 }
1482 
ClearNeedsStyleRecalc()1483 void Node::ClearNeedsStyleRecalc() {
1484   node_flags_ &= ~kStyleChangeMask;
1485   ClearFlag(kForceReattachLayoutTree);
1486 
1487   auto* element = DynamicTo<Element>(this);
1488   if (element && HasRareData())
1489     element->SetAnimationStyleChange(false);
1490 }
1491 
InActiveDocument() const1492 bool Node::InActiveDocument() const {
1493   return isConnected() && GetDocument().IsActive();
1494 }
1495 
ShouldHaveFocusAppearance() const1496 bool Node::ShouldHaveFocusAppearance() const {
1497   DCHECK(IsFocused());
1498   return true;
1499 }
1500 
IsInert() const1501 bool Node::IsInert() const {
1502   if (!isConnected() || !CanParticipateInFlatTree())
1503     return true;
1504 
1505   DCHECK(!ChildNeedsDistributionRecalc());
1506 
1507   if (this != GetDocument() && this != GetDocument().documentElement()) {
1508     const Element* modal_element = GetDocument().ActiveModalDialog();
1509     if (!modal_element)
1510       modal_element = Fullscreen::FullscreenElementFrom(GetDocument());
1511     if (modal_element && !FlatTreeTraversal::ContainsIncludingPseudoElement(
1512                              *modal_element, *this)) {
1513       return true;
1514     }
1515   }
1516 
1517   if (RuntimeEnabledFeatures::InertAttributeEnabled()) {
1518     const auto* element = DynamicTo<Element>(this);
1519     if (!element)
1520       element = FlatTreeTraversal::ParentElement(*this);
1521 
1522     while (element) {
1523       if (element->FastHasAttribute(html_names::kInertAttr))
1524         return true;
1525       element = FlatTreeTraversal::ParentElement(*element);
1526     }
1527   }
1528   return GetDocument().GetFrame() && GetDocument().GetFrame()->IsInert();
1529 }
1530 
NodeIndex() const1531 unsigned Node::NodeIndex() const {
1532   const Node* temp_node = previousSibling();
1533   unsigned count = 0;
1534   for (count = 0; temp_node; count++)
1535     temp_node = temp_node->previousSibling();
1536   return count;
1537 }
1538 
NodeLists()1539 NodeListsNodeData* Node::NodeLists() {
1540   return HasRareData() ? RareData()->NodeLists() : nullptr;
1541 }
1542 
ClearNodeLists()1543 void Node::ClearNodeLists() {
1544   RareData()->ClearNodeLists();
1545 }
1546 
EnsureFlatTreeNodeData()1547 FlatTreeNodeData& Node::EnsureFlatTreeNodeData() {
1548   return EnsureRareData().EnsureFlatTreeNodeData();
1549 }
1550 
GetFlatTreeNodeData() const1551 FlatTreeNodeData* Node::GetFlatTreeNodeData() const {
1552   if (!HasRareData())
1553     return nullptr;
1554   return RareData()->GetFlatTreeNodeData();
1555 }
1556 
ClearFlatTreeNodeData()1557 void Node::ClearFlatTreeNodeData() {
1558   if (FlatTreeNodeData* data = GetFlatTreeNodeData())
1559     data->Clear();
1560 }
1561 
ClearFlatTreeNodeDataIfHostChanged(const ContainerNode & parent)1562 void Node::ClearFlatTreeNodeDataIfHostChanged(const ContainerNode& parent) {
1563   if (FlatTreeNodeData* data = GetFlatTreeNodeData()) {
1564     if (data->AssignedSlot() &&
1565         data->AssignedSlot()->OwnerShadowHost() != &parent) {
1566       data->Clear();
1567     }
1568   }
1569 }
1570 
IsDescendantOf(const Node * other) const1571 bool Node::IsDescendantOf(const Node* other) const {
1572   DCHECK(this);  // Necessary for clusterfuzz tooling to get a useful backtrace
1573 
1574   // Return true if other is an ancestor of this, otherwise false
1575   if (!other || isConnected() != other->isConnected())
1576     return false;
1577   if (other->GetTreeScope() != GetTreeScope())
1578     return false;
1579   if (other->IsTreeScope())
1580     return !IsTreeScope();
1581   for (const ContainerNode* n = parentNode(); n; n = n->parentNode()) {
1582     if (n == other)
1583       return true;
1584   }
1585   return false;
1586 }
1587 
contains(const Node * node) const1588 bool Node::contains(const Node* node) const {
1589   if (!node)
1590     return false;
1591   return this == node || node->IsDescendantOf(this);
1592 }
1593 
IsShadowIncludingInclusiveAncestorOf(const Node & node) const1594 bool Node::IsShadowIncludingInclusiveAncestorOf(const Node& node) const {
1595   return this == &node || IsShadowIncludingAncestorOf(node);
1596 }
1597 
IsShadowIncludingAncestorOf(const Node & node) const1598 bool Node::IsShadowIncludingAncestorOf(const Node& node) const {
1599   // In the following case, contains(host) below returns true.
1600   if (this == &node)
1601     return false;
1602 
1603   if (GetDocument() != node.GetDocument())
1604     return false;
1605 
1606   if (isConnected() != node.isConnected())
1607     return false;
1608 
1609   auto* this_node = DynamicTo<ContainerNode>(this);
1610   bool has_children = this_node ? this_node->HasChildren() : false;
1611   bool has_shadow = IsShadowHost(this);
1612   if (!has_children && !has_shadow)
1613     return false;
1614 
1615   for (const Node* host = &node; host; host = host->OwnerShadowHost()) {
1616     if (GetTreeScope() == host->GetTreeScope())
1617       return contains(host);
1618   }
1619 
1620   return false;
1621 }
1622 
ContainsIncludingHostElements(const Node & node) const1623 bool Node::ContainsIncludingHostElements(const Node& node) const {
1624   const Node* current = &node;
1625   do {
1626     if (current == this)
1627       return true;
1628     auto* curr_fragment = DynamicTo<DocumentFragment>(current);
1629     if (curr_fragment && curr_fragment->IsTemplateContent())
1630       current =
1631           static_cast<const TemplateContentDocumentFragment*>(current)->Host();
1632     else
1633       current = current->ParentOrShadowHostNode();
1634   } while (current);
1635   return false;
1636 }
1637 
CommonAncestor(const Node & other,ContainerNode * (* parent)(const Node &)) const1638 Node* Node::CommonAncestor(const Node& other,
1639                            ContainerNode* (*parent)(const Node&)) const {
1640   if (this == other)
1641     return const_cast<Node*>(this);
1642   if (GetDocument() != other.GetDocument())
1643     return nullptr;
1644   int this_depth = 0;
1645   for (const Node* node = this; node; node = parent(*node)) {
1646     if (node == &other)
1647       return const_cast<Node*>(node);
1648     this_depth++;
1649   }
1650   int other_depth = 0;
1651   for (const Node* node = &other; node; node = parent(*node)) {
1652     if (node == this)
1653       return const_cast<Node*>(this);
1654     other_depth++;
1655   }
1656   const Node* this_iterator = this;
1657   const Node* other_iterator = &other;
1658   if (this_depth > other_depth) {
1659     for (int i = this_depth; i > other_depth; --i)
1660       this_iterator = parent(*this_iterator);
1661   } else if (other_depth > this_depth) {
1662     for (int i = other_depth; i > this_depth; --i)
1663       other_iterator = parent(*other_iterator);
1664   }
1665   while (this_iterator) {
1666     if (this_iterator == other_iterator)
1667       return const_cast<Node*>(this_iterator);
1668     this_iterator = parent(*this_iterator);
1669     other_iterator = parent(*other_iterator);
1670   }
1671   DCHECK(!other_iterator);
1672   return nullptr;
1673 }
1674 
ReattachLayoutTree(AttachContext & context)1675 void Node::ReattachLayoutTree(AttachContext& context) {
1676   context.performing_reattach = true;
1677   ReattachHookScope reattach_scope(*this);
1678 
1679   DetachLayoutTree(context.performing_reattach);
1680   AttachLayoutTree(context);
1681   DCHECK(!NeedsReattachLayoutTree());
1682 }
1683 
AttachLayoutTree(AttachContext & context)1684 void Node::AttachLayoutTree(AttachContext& context) {
1685   DCHECK(GetDocument().InStyleRecalc() || IsDocumentNode());
1686   DCHECK(!GetDocument().Lifecycle().InDetach());
1687   DCHECK(!context.performing_reattach ||
1688          GetDocument().GetStyleEngine().InRebuildLayoutTree());
1689 
1690   LayoutObject* layout_object = GetLayoutObject();
1691   DCHECK(!layout_object ||
1692          (layout_object->Style() &&
1693           (layout_object->Parent() || IsA<LayoutView>(layout_object))));
1694 
1695   ClearNeedsReattachLayoutTree();
1696 
1697   if (AXObjectCache* cache = GetDocument().ExistingAXObjectCache())
1698     cache->UpdateCacheAfterNodeIsAttached(this);
1699 
1700   if (context.performing_reattach)
1701     ReattachHookScope::NotifyAttach(*this);
1702 }
1703 
DetachLayoutTree(bool performing_reattach)1704 void Node::DetachLayoutTree(bool performing_reattach) {
1705   DCHECK(GetDocument().Lifecycle().StateAllowsDetach());
1706   DCHECK(!performing_reattach ||
1707          GetDocument().GetStyleEngine().InRebuildLayoutTree());
1708   DocumentLifecycle::DetachScope will_detach(GetDocument().Lifecycle());
1709 
1710   if (performing_reattach)
1711     ReattachHookScope::NotifyDetach(*this);
1712 
1713   if (GetLayoutObject())
1714     GetLayoutObject()->DestroyAndCleanupAnonymousWrappers();
1715   SetLayoutObject(nullptr);
1716   if (!performing_reattach) {
1717     // We are clearing the ComputedStyle for elements, which means we should not
1718     // need to recalc style. Also, this way we can detect if we need to remove
1719     // this Node as a StyleRecalcRoot if this detach is because the node is
1720     // removed from the flat tree. That is necessary because we are not allowed
1721     // to have a style recalc root outside the flat tree when traversing the
1722     // flat tree for style recalc (see StyleRecalcRoot::RemovedFromFlatTree()).
1723     ClearNeedsStyleRecalc();
1724     ClearChildNeedsStyleRecalc();
1725   }
1726 }
1727 
VirtualEnsureComputedStyle(PseudoId pseudo_element_specifier)1728 const ComputedStyle* Node::VirtualEnsureComputedStyle(
1729     PseudoId pseudo_element_specifier) {
1730   return ParentOrShadowHostNode()
1731              ? ParentOrShadowHostNode()->EnsureComputedStyle(
1732                    pseudo_element_specifier)
1733              : nullptr;
1734 }
1735 
SetForceReattachLayoutTree()1736 void Node::SetForceReattachLayoutTree() {
1737   DCHECK(!GetDocument().GetStyleEngine().InRebuildLayoutTree());
1738   DCHECK(IsElementNode() || IsTextNode());
1739   if (GetForceReattachLayoutTree())
1740     return;
1741   if (!InActiveDocument())
1742     return;
1743   if (IsElementNode()) {
1744     if (!GetComputedStyle()) {
1745       DCHECK(!GetLayoutObject());
1746       return;
1747     }
1748   } else {
1749     DCHECK(IsTextNode());
1750     if (!GetLayoutObject() && ShouldSkipMarkingStyleDirty())
1751       return;
1752   }
1753   SetFlag(kForceReattachLayoutTree);
1754   if (!NeedsStyleRecalc()) {
1755     // Make sure we traverse down to this node during style recalc.
1756     MarkAncestorsWithChildNeedsStyleRecalc();
1757   }
1758 }
1759 
1760 // FIXME: Shouldn't these functions be in the editing code?  Code that asks
1761 // questions about HTML in the core DOM class is obviously misplaced.
CanStartSelection() const1762 bool Node::CanStartSelection() const {
1763   if (DisplayLockUtilities::NearestLockedExclusiveAncestor(*this))
1764     GetDocument().UpdateStyleAndLayoutTreeForNode(this);
1765   if (HasEditableStyle(*this))
1766     return true;
1767 
1768   if (GetLayoutObject()) {
1769     const ComputedStyle& style = GetLayoutObject()->StyleRef();
1770     if (style.UserSelect() == EUserSelect::kNone)
1771       return false;
1772     // We allow selections to begin within |user-select: text/all| sub trees
1773     // but not if the element is draggable.
1774     if (style.UserDrag() != EUserDrag::kElement &&
1775         (style.UserSelect() == EUserSelect::kText ||
1776          style.UserSelect() == EUserSelect::kAll))
1777       return true;
1778   }
1779   ContainerNode* parent = FlatTreeTraversal::Parent(*this);
1780   return parent ? parent->CanStartSelection() : true;
1781 }
1782 
NotifyPriorityScrollAnchorStatusChanged()1783 void Node::NotifyPriorityScrollAnchorStatusChanged() {
1784   auto* node = this;
1785   while (node && !node->GetLayoutObject())
1786     node = FlatTreeTraversal::Parent(*node);
1787   if (node) {
1788     DCHECK(node->GetLayoutObject());
1789     node->GetLayoutObject()->NotifyPriorityScrollAnchorStatusChanged();
1790   }
1791 }
1792 
1793 // StyledElements allow inline style (style="border: 1px"), presentational
1794 // attributes (ex. color), class names (ex. class="foo bar") and other non-basic
1795 // styling features. They also control if this element can participate in style
1796 // sharing.
1797 //
1798 // FIXME: The only things that ever go through StyleResolver that aren't
1799 // StyledElements are PseudoElements and VTTElements. It's possible we can just
1800 // eliminate all the checks since those elements will never have class names,
1801 // inline style, or other things that this apparently guards against.
IsStyledElement() const1802 bool Node::IsStyledElement() const {
1803   auto* this_element = DynamicTo<Element>(this);
1804   return IsHTMLElement() || IsSVGElement() || IsMathMLElement() ||
1805          (!RuntimeEnabledFeatures::MathMLCoreEnabled() && this_element &&
1806           this_element->namespaceURI() == mathml_names::kNamespaceURI);
1807 }
1808 
CanParticipateInFlatTree() const1809 bool Node::CanParticipateInFlatTree() const {
1810   // TODO(hayato): Return false for pseudo elements.
1811   return !IsShadowRoot() && !IsActiveV0InsertionPoint(*this);
1812 }
1813 
IsActiveSlotOrActiveV0InsertionPoint() const1814 bool Node::IsActiveSlotOrActiveV0InsertionPoint() const {
1815   return ToHTMLSlotElementIfSupportsAssignmentOrNull(*this) ||
1816          IsActiveV0InsertionPoint(*this);
1817 }
1818 
SlotName() const1819 AtomicString Node::SlotName() const {
1820   DCHECK(IsSlotable());
1821   if (IsElementNode()) {
1822     return HTMLSlotElement::NormalizeSlotName(
1823         To<Element>(*this).FastGetAttribute(html_names::kSlotAttr));
1824   }
1825   DCHECK(IsTextNode());
1826   return g_empty_atom;
1827 }
1828 
IsInV1ShadowTree() const1829 bool Node::IsInV1ShadowTree() const {
1830   ShadowRoot* shadow_root = ContainingShadowRoot();
1831   return shadow_root && shadow_root->IsV1();
1832 }
1833 
IsInV0ShadowTree() const1834 bool Node::IsInV0ShadowTree() const {
1835   ShadowRoot* shadow_root = ContainingShadowRoot();
1836   return shadow_root && !shadow_root->IsV1();
1837 }
1838 
ParentElementShadowRoot() const1839 ShadowRoot* Node::ParentElementShadowRoot() const {
1840   Element* parent = parentElement();
1841   return parent ? parent->GetShadowRoot() : nullptr;
1842 }
1843 
IsChildOfV1ShadowHost() const1844 bool Node::IsChildOfV1ShadowHost() const {
1845   ShadowRoot* parent_shadow_root = ParentElementShadowRoot();
1846   return parent_shadow_root && parent_shadow_root->IsV1();
1847 }
1848 
IsChildOfV0ShadowHost() const1849 bool Node::IsChildOfV0ShadowHost() const {
1850   ShadowRoot* parent_shadow_root = ParentElementShadowRoot();
1851   return parent_shadow_root && !parent_shadow_root->IsV1();
1852 }
1853 
V1ShadowRootOfParent() const1854 ShadowRoot* Node::V1ShadowRootOfParent() const {
1855   if (Element* parent = parentElement())
1856     return parent->ShadowRootIfV1();
1857   return nullptr;
1858 }
1859 
OwnerShadowHost() const1860 Element* Node::OwnerShadowHost() const {
1861   if (ShadowRoot* root = ContainingShadowRoot())
1862     return &root->host();
1863   return nullptr;
1864 }
1865 
ContainingShadowRoot() const1866 ShadowRoot* Node::ContainingShadowRoot() const {
1867   Node& root = GetTreeScope().RootNode();
1868   return DynamicTo<ShadowRoot>(root);
1869 }
1870 
NonBoundaryShadowTreeRootNode()1871 Node* Node::NonBoundaryShadowTreeRootNode() {
1872   DCHECK(!IsShadowRoot());
1873   Node* root = this;
1874   while (root) {
1875     if (root->IsShadowRoot())
1876       return root;
1877     Node* parent = root->ParentOrShadowHostNode();
1878     if (parent && parent->IsShadowRoot())
1879       return root;
1880     root = parent;
1881   }
1882   return nullptr;
1883 }
1884 
NonShadowBoundaryParentNode() const1885 ContainerNode* Node::NonShadowBoundaryParentNode() const {
1886   ContainerNode* parent = parentNode();
1887   return parent && !parent->IsShadowRoot() ? parent : nullptr;
1888 }
1889 
ParentOrShadowHostElement() const1890 Element* Node::ParentOrShadowHostElement() const {
1891   ContainerNode* parent = ParentOrShadowHostNode();
1892   if (!parent)
1893     return nullptr;
1894 
1895   if (auto* shadow_root = DynamicTo<ShadowRoot>(parent))
1896     return &shadow_root->host();
1897 
1898   return DynamicTo<Element>(parent);
1899 }
1900 
ParentOrShadowHostOrTemplateHostNode() const1901 ContainerNode* Node::ParentOrShadowHostOrTemplateHostNode() const {
1902   auto* this_fragment = DynamicTo<DocumentFragment>(this);
1903   if (this_fragment && this_fragment->IsTemplateContent())
1904     return static_cast<const TemplateContentDocumentFragment*>(this)->Host();
1905   return ParentOrShadowHostNode();
1906 }
1907 
OriginatingTreeScope() const1908 TreeScope& Node::OriginatingTreeScope() const {
1909   if (const SVGElement* svg_element = DynamicTo<SVGElement>(this)) {
1910     if (const SVGElement* corr_element = svg_element->CorrespondingElement()) {
1911       DCHECK(!corr_element->CorrespondingElement());
1912       return corr_element->GetTreeScope();
1913     }
1914   }
1915   return GetTreeScope();
1916 }
1917 
ownerDocument() const1918 Document* Node::ownerDocument() const {
1919   Document* doc = &GetDocument();
1920   return doc == this ? nullptr : doc;
1921 }
1922 
baseURI() const1923 const KURL& Node::baseURI() const {
1924   return GetDocument().BaseURL();
1925 }
1926 
isEqualNode(Node * other) const1927 bool Node::isEqualNode(Node* other) const {
1928   if (!other)
1929     return false;
1930 
1931   NodeType node_type = getNodeType();
1932   if (node_type != other->getNodeType())
1933     return false;
1934 
1935   if (nodeValue() != other->nodeValue())
1936     return false;
1937 
1938   if (auto* this_attr = DynamicTo<Attr>(this)) {
1939     auto* other_attr = To<Attr>(other);
1940     if (this_attr->localName() != other_attr->localName())
1941       return false;
1942 
1943     if (this_attr->namespaceURI() != other_attr->namespaceURI())
1944       return false;
1945   } else if (auto* this_element = DynamicTo<Element>(this)) {
1946     auto* other_element = DynamicTo<Element>(other);
1947     if (this_element->TagQName() != other_element->TagQName())
1948       return false;
1949 
1950     if (!this_element->HasEquivalentAttributes(*other_element))
1951       return false;
1952   } else if (nodeName() != other->nodeName()) {
1953     return false;
1954   }
1955 
1956   Node* child = firstChild();
1957   Node* other_child = other->firstChild();
1958 
1959   while (child) {
1960     if (!child->isEqualNode(other_child))
1961       return false;
1962 
1963     child = child->nextSibling();
1964     other_child = other_child->nextSibling();
1965   }
1966 
1967   if (other_child)
1968     return false;
1969 
1970   if (const auto* document_type_this = DynamicTo<DocumentType>(this)) {
1971     const auto* document_type_other = To<DocumentType>(other);
1972 
1973     if (document_type_this->publicId() != document_type_other->publicId())
1974       return false;
1975 
1976     if (document_type_this->systemId() != document_type_other->systemId())
1977       return false;
1978   }
1979 
1980   return true;
1981 }
1982 
isDefaultNamespace(const AtomicString & namespace_uri_maybe_empty) const1983 bool Node::isDefaultNamespace(
1984     const AtomicString& namespace_uri_maybe_empty) const {
1985   // https://dom.spec.whatwg.org/#dom-node-isdefaultnamespace
1986 
1987   // 1. If namespace is the empty string, then set it to null.
1988   const AtomicString& namespace_uri = namespace_uri_maybe_empty.IsEmpty()
1989                                           ? g_null_atom
1990                                           : namespace_uri_maybe_empty;
1991 
1992   // 2. Let defaultNamespace be the result of running locate a namespace for
1993   // context object using null.
1994   const AtomicString& default_namespace = lookupNamespaceURI(String());
1995 
1996   // 3. Return true if defaultNamespace is the same as namespace, and false
1997   // otherwise.
1998   return namespace_uri == default_namespace;
1999 }
2000 
lookupPrefix(const AtomicString & namespace_uri) const2001 const AtomicString& Node::lookupPrefix(
2002     const AtomicString& namespace_uri) const {
2003   // Implemented according to
2004   // https://dom.spec.whatwg.org/#dom-node-lookupprefix
2005 
2006   if (namespace_uri.IsEmpty() || namespace_uri.IsNull())
2007     return g_null_atom;
2008 
2009   const Element* context;
2010 
2011   switch (getNodeType()) {
2012     case kElementNode:
2013       context = To<Element>(this);
2014       break;
2015     case kDocumentNode:
2016       context = To<Document>(this)->documentElement();
2017       break;
2018     case kDocumentFragmentNode:
2019     case kDocumentTypeNode:
2020       context = nullptr;
2021       break;
2022     case kAttributeNode:
2023       context = To<Attr>(this)->ownerElement();
2024       break;
2025     default:
2026       context = parentElement();
2027       break;
2028   }
2029 
2030   if (!context)
2031     return g_null_atom;
2032 
2033   return context->LocateNamespacePrefix(namespace_uri);
2034 }
2035 
lookupNamespaceURI(const String & specified_prefix) const2036 const AtomicString& Node::lookupNamespaceURI(
2037     const String& specified_prefix) const {
2038   // Implemented according to
2039   // https://dom.spec.whatwg.org/#dom-node-lookupnamespaceuri
2040 
2041   // 1. If prefix is the empty string, then set it to null.
2042   String prefix = specified_prefix;
2043   if (!specified_prefix.IsNull() && specified_prefix.IsEmpty())
2044     prefix = String();
2045 
2046   // 2. Return the result of running locate a namespace for the context object
2047   // using prefix.
2048 
2049   // https://dom.spec.whatwg.org/#locate-a-namespace
2050   switch (getNodeType()) {
2051     case kElementNode: {
2052       const auto& element = To<Element>(*this);
2053 
2054       // 1. If its namespace is not null and its namespace prefix is prefix,
2055       // then return namespace.
2056       if (!element.namespaceURI().IsNull() && element.prefix() == prefix)
2057         return element.namespaceURI();
2058 
2059       // 2. If it has an attribute whose namespace is the XMLNS namespace,
2060       // namespace prefix is "xmlns", and local name is prefix, or if prefix is
2061       // null and it has an attribute whose namespace is the XMLNS namespace,
2062       // namespace prefix is null, and local name is "xmlns", then return its
2063       // value if it is not the empty string, and null otherwise.
2064       AttributeCollection attributes = element.Attributes();
2065       for (const Attribute& attr : attributes) {
2066         if (attr.Prefix() == g_xmlns_atom && attr.LocalName() == prefix) {
2067           if (!attr.Value().IsEmpty())
2068             return attr.Value();
2069           return g_null_atom;
2070         }
2071         if (attr.LocalName() == g_xmlns_atom && prefix.IsNull()) {
2072           if (!attr.Value().IsEmpty())
2073             return attr.Value();
2074           return g_null_atom;
2075         }
2076       }
2077 
2078       // 3. If its parent element is null, then return null.
2079       // 4. Return the result of running locate a namespace on its parent
2080       // element using prefix.
2081       if (Element* parent = parentElement())
2082         return parent->lookupNamespaceURI(prefix);
2083       return g_null_atom;
2084     }
2085     case kDocumentNode:
2086       if (Element* de = To<Document>(this)->documentElement())
2087         return de->lookupNamespaceURI(prefix);
2088       return g_null_atom;
2089     case kDocumentTypeNode:
2090     case kDocumentFragmentNode:
2091       return g_null_atom;
2092     case kAttributeNode: {
2093       const auto* attr = To<Attr>(this);
2094       if (attr->ownerElement())
2095         return attr->ownerElement()->lookupNamespaceURI(prefix);
2096       return g_null_atom;
2097     }
2098     default:
2099       if (Element* parent = parentElement())
2100         return parent->lookupNamespaceURI(prefix);
2101       return g_null_atom;
2102   }
2103 }
2104 
textContent(bool convert_brs_to_newlines) const2105 String Node::textContent(bool convert_brs_to_newlines) const {
2106   // This covers ProcessingInstruction and Comment that should return their
2107   // value when .textContent is accessed on them, but should be ignored when
2108   // iterated over as a descendant of a ContainerNode.
2109   if (auto* character_data = DynamicTo<CharacterData>(this))
2110     return character_data->data();
2111 
2112   // Attribute nodes have their attribute values as textContent.
2113   if (auto* attr = DynamicTo<Attr>(this))
2114     return attr->value();
2115 
2116   // Documents and non-container nodes (that are not CharacterData)
2117   // have null textContent.
2118   if (IsDocumentNode() || !IsContainerNode())
2119     return String();
2120 
2121   StringBuilder content;
2122   for (const Node& node : NodeTraversal::InclusiveDescendantsOf(*this)) {
2123     if (IsA<HTMLBRElement>(node) && convert_brs_to_newlines) {
2124       content.Append('\n');
2125     } else if (auto* text_node = DynamicTo<Text>(node)) {
2126       content.Append(text_node->data());
2127     }
2128   }
2129   return content.ToString();
2130 }
2131 
setTextContent(const StringOrTrustedScript & string_or_trusted_script,ExceptionState & exception_state)2132 void Node::setTextContent(const StringOrTrustedScript& string_or_trusted_script,
2133                           ExceptionState& exception_state) {
2134   String value =
2135       string_or_trusted_script.IsString()
2136           ? string_or_trusted_script.GetAsString()
2137           : string_or_trusted_script.IsTrustedScript()
2138                 ? string_or_trusted_script.GetAsTrustedScript()->toString()
2139                 : g_empty_string;
2140   setTextContent(value);
2141 }
2142 
textContent(StringOrTrustedScript & result)2143 void Node::textContent(StringOrTrustedScript& result) {
2144   String value = textContent();
2145   if (!value.IsNull())
2146     result.SetString(value);
2147 }
2148 
setTextContent(const String & text)2149 void Node::setTextContent(const String& text) {
2150   switch (getNodeType()) {
2151     case kAttributeNode:
2152     case kTextNode:
2153     case kCdataSectionNode:
2154     case kCommentNode:
2155     case kProcessingInstructionNode:
2156       setNodeValue(text);
2157       return;
2158     case kElementNode:
2159     case kDocumentFragmentNode: {
2160       // FIXME: Merge this logic into replaceChildrenWithText.
2161       auto* container = To<ContainerNode>(this);
2162 
2163       // Note: This is an intentional optimization.
2164       // See crbug.com/352836 also.
2165       // No need to do anything if the text is identical.
2166       if (container->HasOneTextChild() &&
2167           To<Text>(container->firstChild())->data() == text && !text.IsEmpty())
2168         return;
2169 
2170       ChildListMutationScope mutation(*this);
2171       // Note: This API will not insert empty text nodes:
2172       // https://dom.spec.whatwg.org/#dom-node-textcontent
2173       if (text.IsEmpty()) {
2174         container->RemoveChildren(kDispatchSubtreeModifiedEvent);
2175       } else {
2176         container->RemoveChildren(kOmitSubtreeModifiedEvent);
2177         container->AppendChild(GetDocument().createTextNode(text),
2178                                ASSERT_NO_EXCEPTION);
2179       }
2180       return;
2181     }
2182     case kDocumentNode:
2183     case kDocumentTypeNode:
2184       // Do nothing.
2185       return;
2186   }
2187   NOTREACHED();
2188 }
2189 
compareDocumentPosition(const Node * other_node,ShadowTreesTreatment treatment) const2190 uint16_t Node::compareDocumentPosition(const Node* other_node,
2191                                        ShadowTreesTreatment treatment) const {
2192   if (other_node == this)
2193     return kDocumentPositionEquivalent;
2194 
2195   const auto* attr1 = DynamicTo<Attr>(this);
2196   const Attr* attr2 = DynamicTo<Attr>(other_node);
2197 
2198   const Node* start1 = attr1 ? attr1->ownerElement() : this;
2199   const Node* start2 = attr2 ? attr2->ownerElement() : other_node;
2200 
2201   // If either of start1 or start2 is null, then we are disconnected, since one
2202   // of the nodes is an orphaned attribute node.
2203   if (!start1 || !start2) {
2204     uint16_t direction = (this > other_node) ? kDocumentPositionPreceding
2205                                              : kDocumentPositionFollowing;
2206     return kDocumentPositionDisconnected |
2207            kDocumentPositionImplementationSpecific | direction;
2208   }
2209 
2210   HeapVector<Member<const Node>, 16> chain1;
2211   HeapVector<Member<const Node>, 16> chain2;
2212   if (attr1)
2213     chain1.push_back(attr1);
2214   if (attr2)
2215     chain2.push_back(attr2);
2216 
2217   if (attr1 && attr2 && start1 == start2 && start1) {
2218     // We are comparing two attributes on the same node. Crawl our attribute map
2219     // and see which one we hit first.
2220     const Element* owner1 = attr1->ownerElement();
2221     AttributeCollection attributes = owner1->Attributes();
2222     for (const Attribute& attr : attributes) {
2223       // If neither of the two determining nodes is a child node and nodeType is
2224       // the same for both determining nodes, then an implementation-dependent
2225       // order between the determining nodes is returned. This order is stable
2226       // as long as no nodes of the same nodeType are inserted into or removed
2227       // from the direct container. This would be the case, for example, when
2228       // comparing two attributes of the same element, and inserting or removing
2229       // additional attributes might change the order between existing
2230       // attributes.
2231       if (attr1->GetQualifiedName() == attr.GetName())
2232         return kDocumentPositionImplementationSpecific |
2233                kDocumentPositionFollowing;
2234       if (attr2->GetQualifiedName() == attr.GetName())
2235         return kDocumentPositionImplementationSpecific |
2236                kDocumentPositionPreceding;
2237     }
2238 
2239     NOTREACHED();
2240     return kDocumentPositionDisconnected;
2241   }
2242 
2243   // If one node is in the document and the other is not, we must be
2244   // disconnected.  If the nodes have different owning documents, they must be
2245   // disconnected.  Note that we avoid comparing Attr nodes here, since they
2246   // return false from isConnected() all the time (which seems like a bug).
2247   if (start1->isConnected() != start2->isConnected() ||
2248       (treatment == kTreatShadowTreesAsDisconnected &&
2249        start1->GetTreeScope() != start2->GetTreeScope())) {
2250     uint16_t direction = (this > other_node) ? kDocumentPositionPreceding
2251                                              : kDocumentPositionFollowing;
2252     return kDocumentPositionDisconnected |
2253            kDocumentPositionImplementationSpecific | direction;
2254   }
2255 
2256   // We need to find a common ancestor container, and then compare the indices
2257   // of the two immediate children.
2258   const Node* current;
2259   for (current = start1; current; current = current->ParentOrShadowHostNode())
2260     chain1.push_back(current);
2261   for (current = start2; current; current = current->ParentOrShadowHostNode())
2262     chain2.push_back(current);
2263 
2264   unsigned index1 = chain1.size();
2265   unsigned index2 = chain2.size();
2266 
2267   // If the two elements don't have a common root, they're not in the same tree.
2268   if (chain1[index1 - 1] != chain2[index2 - 1]) {
2269     uint16_t direction = (this > other_node) ? kDocumentPositionPreceding
2270                                              : kDocumentPositionFollowing;
2271     return kDocumentPositionDisconnected |
2272            kDocumentPositionImplementationSpecific | direction;
2273   }
2274 
2275   unsigned connection = start1->GetTreeScope() != start2->GetTreeScope()
2276                             ? kDocumentPositionDisconnected |
2277                                   kDocumentPositionImplementationSpecific
2278                             : 0;
2279 
2280   // Walk the two chains backwards and look for the first difference.
2281   for (unsigned i = std::min(index1, index2); i; --i) {
2282     const Node* child1 = chain1[--index1];
2283     const Node* child2 = chain2[--index2];
2284     if (child1 != child2) {
2285       // If one of the children is an attribute, it wins.
2286       if (child1->getNodeType() == kAttributeNode)
2287         return kDocumentPositionFollowing | connection;
2288       if (child2->getNodeType() == kAttributeNode)
2289         return kDocumentPositionPreceding | connection;
2290 
2291       // If one of the children is a shadow root,
2292       if (child1->IsShadowRoot() || child2->IsShadowRoot()) {
2293         if (!child2->IsShadowRoot())
2294           return Node::kDocumentPositionFollowing | connection;
2295         if (!child1->IsShadowRoot())
2296           return Node::kDocumentPositionPreceding | connection;
2297 
2298         return Node::kDocumentPositionPreceding | connection;
2299       }
2300 
2301       if (!child2->nextSibling())
2302         return kDocumentPositionFollowing | connection;
2303       if (!child1->nextSibling())
2304         return kDocumentPositionPreceding | connection;
2305 
2306       // Otherwise we need to see which node occurs first.  Crawl backwards from
2307       // child2 looking for child1.
2308       for (const Node* child = child2->previousSibling(); child;
2309            child = child->previousSibling()) {
2310         if (child == child1)
2311           return kDocumentPositionFollowing | connection;
2312       }
2313       return kDocumentPositionPreceding | connection;
2314     }
2315   }
2316 
2317   // There was no difference between the two parent chains, i.e., one was a
2318   // subset of the other.  The shorter chain is the ancestor.
2319   return index1 < index2 ? kDocumentPositionFollowing |
2320                                kDocumentPositionContainedBy | connection
2321                          : kDocumentPositionPreceding |
2322                                kDocumentPositionContains | connection;
2323 }
2324 
InvalidateIfHasEffectiveAppearance() const2325 void Node::InvalidateIfHasEffectiveAppearance() const {
2326   auto* layout_object = GetLayoutObject();
2327   if (!layout_object)
2328     return;
2329 
2330   if (!layout_object->StyleRef().HasEffectiveAppearance())
2331     return;
2332 
2333   layout_object->SetSubtreeShouldDoFullPaintInvalidation();
2334 }
2335 
DebugName() const2336 String Node::DebugName() const {
2337   StringBuilder name;
2338   AppendUnsafe(name, DebugNodeName());
2339   if (const auto* this_element = DynamicTo<Element>(this)) {
2340     if (this_element->HasID()) {
2341       name.Append(" id=\'");
2342       AppendUnsafe(name, this_element->GetIdAttribute());
2343       name.Append('\'');
2344     }
2345 
2346     if (this_element->HasClass()) {
2347       name.Append(" class=\'");
2348       for (wtf_size_t i = 0; i < this_element->ClassNames().size(); ++i) {
2349         if (i > 0)
2350           name.Append(' ');
2351         AppendUnsafe(name, this_element->ClassNames()[i]);
2352       }
2353       name.Append('\'');
2354     }
2355   }
2356   return name.ToString();
2357 }
2358 
DebugNodeName() const2359 String Node::DebugNodeName() const {
2360   return nodeName();
2361 }
2362 
DumpAttributeDesc(const Node & node,const QualifiedName & name,StringBuilder & builder)2363 static void DumpAttributeDesc(const Node& node,
2364                               const QualifiedName& name,
2365                               StringBuilder& builder) {
2366   auto* element = DynamicTo<Element>(node);
2367   if (!element)
2368     return;
2369   const AtomicString& value = element->getAttribute(name);
2370   if (value.IsEmpty())
2371     return;
2372   builder.Append(' ');
2373   builder.Append(name.ToString());
2374   builder.Append("=");
2375   builder.Append(String(value).EncodeForDebugging());
2376 }
2377 
operator <<(std::ostream & ostream,const Node & node)2378 std::ostream& operator<<(std::ostream& ostream, const Node& node) {
2379   return ostream << node.ToString().Utf8();
2380 }
2381 
operator <<(std::ostream & ostream,const Node * node)2382 std::ostream& operator<<(std::ostream& ostream, const Node* node) {
2383   if (!node)
2384     return ostream << "null";
2385   return ostream << *node;
2386 }
2387 
ToString() const2388 String Node::ToString() const {
2389   if (getNodeType() == Node::kProcessingInstructionNode)
2390     return "?" + nodeName();
2391   if (auto* shadow_root = DynamicTo<ShadowRoot>(this)) {
2392     // nodeName of ShadowRoot is #document-fragment.  It's confused with
2393     // DocumentFragment.
2394     std::stringstream shadow_root_type;
2395     shadow_root_type << shadow_root->GetType();
2396     String shadow_root_type_str(shadow_root_type.str().c_str());
2397     return "#shadow-root(" + shadow_root_type_str + ")";
2398   }
2399   if (IsDocumentTypeNode())
2400     return "DOCTYPE " + nodeName();
2401 
2402   StringBuilder builder;
2403   builder.Append(nodeName());
2404   if (IsTextNode()) {
2405     builder.Append(" ");
2406     builder.Append(nodeValue().EncodeForDebugging());
2407     return builder.ToString();
2408   }
2409   DumpAttributeDesc(*this, html_names::kIdAttr, builder);
2410   DumpAttributeDesc(*this, html_names::kClassAttr, builder);
2411   DumpAttributeDesc(*this, html_names::kStyleAttr, builder);
2412   if (HasEditableStyle(*this))
2413     builder.Append(" (editable)");
2414   if (GetDocument().FocusedElement() == this)
2415     builder.Append(" (focused)");
2416   return builder.ToString();
2417 }
2418 
2419 #if DCHECK_IS_ON()
2420 
ToTreeStringForThis() const2421 String Node::ToTreeStringForThis() const {
2422   return ToMarkedTreeString(this, "*");
2423 }
2424 
ToFlatTreeStringForThis() const2425 String Node::ToFlatTreeStringForThis() const {
2426   return ToMarkedFlatTreeString(this, "*");
2427 }
2428 
PrintNodePathTo(std::ostream & stream) const2429 void Node::PrintNodePathTo(std::ostream& stream) const {
2430   HeapVector<Member<const Node>, 16> chain;
2431   const Node* parent_node = this;
2432   while (parent_node->ParentOrShadowHostNode()) {
2433     chain.push_back(parent_node);
2434     parent_node = parent_node->ParentOrShadowHostNode();
2435   }
2436   for (unsigned index = chain.size(); index > 0; --index) {
2437     const Node* node = chain[index - 1];
2438     if (node->IsShadowRoot()) {
2439       stream << "/#shadow-root";
2440       continue;
2441     }
2442 
2443     switch (node->getNodeType()) {
2444       case kElementNode: {
2445         stream << "/" << node->nodeName().Utf8();
2446 
2447         const auto* element = To<Element>(node);
2448         const AtomicString& idattr = element->GetIdAttribute();
2449         bool has_id_attr = !idattr.IsNull() && !idattr.IsEmpty();
2450         if (node->previousSibling() || node->nextSibling()) {
2451           int count = 0;
2452           for (const Node* previous = node->previousSibling(); previous;
2453                previous = previous->previousSibling()) {
2454             if (previous->nodeName() == node->nodeName()) {
2455               ++count;
2456             }
2457           }
2458           if (has_id_attr)
2459             stream << "[@id=\"" << idattr.Utf8()
2460                    << "\" and position()=" << count << "]";
2461           else
2462             stream << "[" << count << "]";
2463         } else if (has_id_attr) {
2464           stream << "[@id=\"" << idattr.Utf8() << "\"]";
2465         }
2466         break;
2467       }
2468       case kTextNode:
2469         stream << "/text()";
2470         break;
2471       case kAttributeNode:
2472         stream << "/@" << node->nodeName().Utf8();
2473         break;
2474       default:
2475         break;
2476     }
2477   }
2478 }
2479 
AppendMarkedTree(const String & base_indent,const Node * root_node,const Node * marked_node1,const char * marked_label1,const Node * marked_node2,const char * marked_label2,StringBuilder & builder)2480 static void AppendMarkedTree(const String& base_indent,
2481                              const Node* root_node,
2482                              const Node* marked_node1,
2483                              const char* marked_label1,
2484                              const Node* marked_node2,
2485                              const char* marked_label2,
2486                              StringBuilder& builder) {
2487   for (const Node& node : NodeTraversal::InclusiveDescendantsOf(*root_node)) {
2488     StringBuilder indent;
2489     if (node == marked_node1)
2490       indent.Append(marked_label1);
2491     if (node == marked_node2)
2492       indent.Append(marked_label2);
2493     indent.Append(base_indent);
2494     for (const Node* tmp_node = &node; tmp_node && tmp_node != root_node;
2495          tmp_node = tmp_node->ParentOrShadowHostNode())
2496       indent.Append('\t');
2497     builder.Append(indent);
2498     builder.Append(node.ToString());
2499     builder.Append("\n");
2500     indent.Append('\t');
2501 
2502     if (const auto* element = DynamicTo<Element>(node)) {
2503       if (Element* pseudo = element->GetPseudoElement(kPseudoIdMarker)) {
2504         AppendMarkedTree(indent.ToString(), pseudo, marked_node1, marked_label1,
2505                          marked_node2, marked_label2, builder);
2506       }
2507       if (Element* pseudo = element->GetPseudoElement(kPseudoIdBefore))
2508         AppendMarkedTree(indent.ToString(), pseudo, marked_node1, marked_label1,
2509                          marked_node2, marked_label2, builder);
2510       if (Element* pseudo = element->GetPseudoElement(kPseudoIdAfter))
2511         AppendMarkedTree(indent.ToString(), pseudo, marked_node1, marked_label1,
2512                          marked_node2, marked_label2, builder);
2513       if (Element* pseudo = element->GetPseudoElement(kPseudoIdFirstLetter))
2514         AppendMarkedTree(indent.ToString(), pseudo, marked_node1, marked_label1,
2515                          marked_node2, marked_label2, builder);
2516       if (Element* pseudo = element->GetPseudoElement(kPseudoIdBackdrop))
2517         AppendMarkedTree(indent.ToString(), pseudo, marked_node1, marked_label1,
2518                          marked_node2, marked_label2, builder);
2519     }
2520 
2521     if (ShadowRoot* shadow_root = node.GetShadowRoot()) {
2522       AppendMarkedTree(indent.ToString(), shadow_root, marked_node1,
2523                        marked_label1, marked_node2, marked_label2, builder);
2524     }
2525   }
2526 }
2527 
AppendMarkedFlatTree(const String & base_indent,const Node * root_node,const Node * marked_node1,const char * marked_label1,const Node * marked_node2,const char * marked_label2,StringBuilder & builder)2528 static void AppendMarkedFlatTree(const String& base_indent,
2529                                  const Node* root_node,
2530                                  const Node* marked_node1,
2531                                  const char* marked_label1,
2532                                  const Node* marked_node2,
2533                                  const char* marked_label2,
2534                                  StringBuilder& builder) {
2535   for (const Node* node = root_node; node;
2536        node = FlatTreeTraversal::NextSibling(*node)) {
2537     StringBuilder indent;
2538     if (node == marked_node1)
2539       indent.Append(marked_label1);
2540     if (node == marked_node2)
2541       indent.Append(marked_label2);
2542     indent.Append(base_indent);
2543     builder.Append(indent);
2544     builder.Append(node->ToString());
2545     builder.Append("\n");
2546     indent.Append('\t');
2547 
2548     if (Node* child = FlatTreeTraversal::FirstChild(*node))
2549       AppendMarkedFlatTree(indent.ToString(), child, marked_node1,
2550                            marked_label1, marked_node2, marked_label2, builder);
2551   }
2552 }
2553 
ToMarkedTreeString(const Node * marked_node1,const char * marked_label1,const Node * marked_node2,const char * marked_label2) const2554 String Node::ToMarkedTreeString(const Node* marked_node1,
2555                                 const char* marked_label1,
2556                                 const Node* marked_node2,
2557                                 const char* marked_label2) const {
2558   const Node* root_node;
2559   const Node* node = this;
2560   while (node->ParentOrShadowHostNode() && !IsA<HTMLBodyElement>(*node))
2561     node = node->ParentOrShadowHostNode();
2562   root_node = node;
2563 
2564   StringBuilder builder;
2565   String starting_indent;
2566   AppendMarkedTree(starting_indent, root_node, marked_node1, marked_label1,
2567                    marked_node2, marked_label2, builder);
2568   return builder.ToString();
2569 }
2570 
ToMarkedFlatTreeString(const Node * marked_node1,const char * marked_label1,const Node * marked_node2,const char * marked_label2) const2571 String Node::ToMarkedFlatTreeString(const Node* marked_node1,
2572                                     const char* marked_label1,
2573                                     const Node* marked_node2,
2574                                     const char* marked_label2) const {
2575   const Node* root_node;
2576   const Node* node = this;
2577   while (node->ParentOrShadowHostNode() && !IsA<HTMLBodyElement>(*node))
2578     node = node->ParentOrShadowHostNode();
2579   root_node = node;
2580 
2581   StringBuilder builder;
2582   String starting_indent;
2583   AppendMarkedFlatTree(starting_indent, root_node, marked_node1, marked_label1,
2584                        marked_node2, marked_label2, builder);
2585   return builder.ToString();
2586 }
2587 
ParentOrShadowHostOrFrameOwner(const Node * node)2588 static ContainerNode* ParentOrShadowHostOrFrameOwner(const Node* node) {
2589   ContainerNode* parent = node->ParentOrShadowHostNode();
2590   if (!parent && node->GetDocument().GetFrame())
2591     parent = node->GetDocument().GetFrame()->DeprecatedLocalOwner();
2592   return parent;
2593 }
2594 
PrintSubTreeAcrossFrame(const Node * node,const Node * marked_node,const String & indent,std::ostream & stream)2595 static void PrintSubTreeAcrossFrame(const Node* node,
2596                                     const Node* marked_node,
2597                                     const String& indent,
2598                                     std::ostream& stream) {
2599   if (node == marked_node)
2600     stream << "*";
2601   stream << indent.Utf8() << *node << "\n";
2602   if (auto* frame_owner_element = DynamicTo<HTMLFrameOwnerElement>(node)) {
2603     PrintSubTreeAcrossFrame(frame_owner_element->contentDocument(), marked_node,
2604                             indent + "\t", stream);
2605   }
2606   if (ShadowRoot* shadow_root = node->GetShadowRoot())
2607     PrintSubTreeAcrossFrame(shadow_root, marked_node, indent + "\t", stream);
2608   for (const Node* child = node->firstChild(); child;
2609        child = child->nextSibling())
2610     PrintSubTreeAcrossFrame(child, marked_node, indent + "\t", stream);
2611 }
2612 
ShowTreeForThisAcrossFrame() const2613 void Node::ShowTreeForThisAcrossFrame() const {
2614   const Node* root_node = this;
2615   while (ParentOrShadowHostOrFrameOwner(root_node))
2616     root_node = ParentOrShadowHostOrFrameOwner(root_node);
2617   std::stringstream stream;
2618   PrintSubTreeAcrossFrame(root_node, this, "", stream);
2619   LOG(INFO) << "\n" << stream.str();
2620 }
2621 
2622 #endif
2623 
2624 // --------
2625 
EnclosingLinkEventParentOrSelf() const2626 Element* Node::EnclosingLinkEventParentOrSelf() const {
2627   // https://crbug.com/784492
2628   DCHECK(this);
2629 
2630   for (const Node* node = this; node; node = FlatTreeTraversal::Parent(*node)) {
2631     // For imagemaps, the enclosing link node is the associated area element not
2632     // the image itself.  So we don't let images be the enclosingLinkNode, even
2633     // though isLink sometimes returns true for them.
2634     if (node->IsLink() && !IsA<HTMLImageElement>(*node)) {
2635       // Casting to Element is safe because only HTMLAnchorElement,
2636       // HTMLImageElement and SVGAElement can return true for isLink().
2637       return To<Element>(const_cast<Node*>(node));
2638     }
2639   }
2640 
2641   return nullptr;
2642 }
2643 
InterfaceName() const2644 const AtomicString& Node::InterfaceName() const {
2645   return event_target_names::kNode;
2646 }
2647 
GetExecutionContext() const2648 ExecutionContext* Node::GetExecutionContext() const {
2649   return GetDocument().GetExecutionContext();
2650 }
2651 
WillMoveToNewDocument(Document & old_document,Document & new_document)2652 void Node::WillMoveToNewDocument(Document& old_document,
2653                                  Document& new_document) {
2654   if (!old_document.GetPage() ||
2655       old_document.GetPage() == new_document.GetPage())
2656     return;
2657 
2658   old_document.GetFrame()->GetEventHandlerRegistry().DidMoveOutOfPage(*this);
2659 
2660   if (auto* this_element = DynamicTo<Element>(this)) {
2661     StylePropertyMapReadOnly* computed_style_map_item =
2662         old_document.RemoveComputedStyleMapItem(this_element);
2663     if (computed_style_map_item) {
2664       new_document.AddComputedStyleMapItem(this_element,
2665                                            computed_style_map_item);
2666     }
2667   }
2668 }
2669 
DidMoveToNewDocument(Document & old_document)2670 void Node::DidMoveToNewDocument(Document& old_document) {
2671   TreeScopeAdopter::EnsureDidMoveToNewDocumentWasCalled(old_document);
2672 
2673   if (const EventTargetData* event_target_data = GetEventTargetData()) {
2674     const EventListenerMap& listener_map =
2675         event_target_data->event_listener_map;
2676     if (!listener_map.IsEmpty()) {
2677       for (const auto& type : listener_map.EventTypes())
2678         GetDocument().AddListenerTypeIfNeeded(type, *this);
2679     }
2680   }
2681   if (auto* text_node = DynamicTo<Text>(this))
2682     old_document.Markers().RemoveMarkersForNode(*text_node);
2683   if (GetDocument().GetPage() &&
2684       GetDocument().GetPage() != old_document.GetPage()) {
2685     GetDocument().GetFrame()->GetEventHandlerRegistry().DidMoveIntoPage(*this);
2686   }
2687 
2688   if (const HeapVector<Member<MutationObserverRegistration>>* registry =
2689           MutationObserverRegistry()) {
2690     for (const auto& registration : *registry) {
2691       GetDocument().AddMutationObserverTypes(registration->MutationTypes());
2692     }
2693   }
2694 
2695   if (TransientMutationObserverRegistry()) {
2696     for (MutationObserverRegistration* registration :
2697          *TransientMutationObserverRegistry())
2698       GetDocument().AddMutationObserverTypes(registration->MutationTypes());
2699   }
2700 }
2701 
AddedEventListener(const AtomicString & event_type,RegisteredEventListener & registered_listener)2702 void Node::AddedEventListener(const AtomicString& event_type,
2703                               RegisteredEventListener& registered_listener) {
2704   EventTarget::AddedEventListener(event_type, registered_listener);
2705   GetDocument().AddListenerTypeIfNeeded(event_type, *this);
2706   if (auto* frame = GetDocument().GetFrame()) {
2707     frame->GetEventHandlerRegistry().DidAddEventHandler(
2708         *this, event_type, registered_listener.Options());
2709     // We need to track the existence of the visibilitychange event listeners to
2710     // enable/disable sudden terminations.
2711     if (IsDocumentNode() && event_type == event_type_names::kVisibilitychange) {
2712       frame->AddedSuddenTerminationDisablerListener(*this, event_type);
2713     }
2714   }
2715   if (AXObjectCache* cache = GetDocument().ExistingAXObjectCache())
2716     cache->HandleEventListenerAdded(*this, event_type);
2717 }
2718 
RemovedEventListener(const AtomicString & event_type,const RegisteredEventListener & registered_listener)2719 void Node::RemovedEventListener(
2720     const AtomicString& event_type,
2721     const RegisteredEventListener& registered_listener) {
2722   EventTarget::RemovedEventListener(event_type, registered_listener);
2723   // FIXME: Notify Document that the listener has vanished. We need to keep
2724   // track of a number of listeners for each type, not just a bool - see
2725   // https://bugs.webkit.org/show_bug.cgi?id=33861
2726   if (auto* frame = GetDocument().GetFrame()) {
2727     frame->GetEventHandlerRegistry().DidRemoveEventHandler(
2728         *this, event_type, registered_listener.Options());
2729     // We need to track the existence of the visibilitychange event listeners to
2730     // enable/disable sudden terminations.
2731     if (IsDocumentNode() && event_type == event_type_names::kVisibilitychange) {
2732       frame->RemovedSuddenTerminationDisablerListener(*this, event_type);
2733     }
2734   }
2735   if (AXObjectCache* cache = GetDocument().ExistingAXObjectCache())
2736     cache->HandleEventListenerRemoved(*this, event_type);
2737 }
2738 
RemoveAllEventListeners()2739 void Node::RemoveAllEventListeners() {
2740   Vector<AtomicString> event_types = EventTypes();
2741   if (HasEventListeners() && GetDocument().GetPage())
2742     GetDocument()
2743         .GetFrame()
2744         ->GetEventHandlerRegistry()
2745         .DidRemoveAllEventHandlers(*this);
2746   EventTarget::RemoveAllEventListeners();
2747   if (AXObjectCache* cache = GetDocument().ExistingAXObjectCache()) {
2748     for (const AtomicString& event_type : event_types)
2749       cache->HandleEventListenerRemoved(*this, event_type);
2750   }
2751 }
2752 
RemoveAllEventListenersRecursively()2753 void Node::RemoveAllEventListenersRecursively() {
2754   ScriptForbiddenScope forbid_script_during_raw_iteration;
2755   for (Node& node : NodeTraversal::StartsAt(*this)) {
2756     node.RemoveAllEventListeners();
2757     if (ShadowRoot* root = node.GetShadowRoot())
2758       root->RemoveAllEventListenersRecursively();
2759   }
2760 }
2761 
2762 using EventTargetDataMap =
2763     HeapHashMap<WeakMember<Node>, Member<EventTargetData>>;
GetEventTargetDataMap()2764 static EventTargetDataMap& GetEventTargetDataMap() {
2765   DEFINE_STATIC_LOCAL(Persistent<EventTargetDataMap>, map,
2766                       (MakeGarbageCollected<EventTargetDataMap>()));
2767   return *map;
2768 }
2769 
GetEventTargetData()2770 EventTargetData* Node::GetEventTargetData() {
2771   return HasEventTargetData() ? GetEventTargetDataMap().at(this) : nullptr;
2772 }
2773 
EnsureEventTargetData()2774 EventTargetData& Node::EnsureEventTargetData() {
2775   if (HasEventTargetData())
2776     return *GetEventTargetDataMap().at(this);
2777   DCHECK(!GetEventTargetDataMap().Contains(this));
2778   EventTargetData* data = MakeGarbageCollected<EventTargetData>();
2779   GetEventTargetDataMap().Set(this, data);
2780   SetHasEventTargetData(true);
2781   return *data;
2782 }
2783 
2784 const HeapVector<Member<MutationObserverRegistration>>*
MutationObserverRegistry()2785 Node::MutationObserverRegistry() {
2786   if (!HasRareData())
2787     return nullptr;
2788   NodeMutationObserverData* data = RareData()->MutationObserverData();
2789   if (!data)
2790     return nullptr;
2791   return &data->Registry();
2792 }
2793 
2794 const HeapHashSet<Member<MutationObserverRegistration>>*
TransientMutationObserverRegistry()2795 Node::TransientMutationObserverRegistry() {
2796   if (!HasRareData())
2797     return nullptr;
2798   NodeMutationObserverData* data = RareData()->MutationObserverData();
2799   if (!data)
2800     return nullptr;
2801   return &data->TransientRegistry();
2802 }
2803 
2804 template <typename Registry>
CollectMatchingObserversForMutation(HeapHashMap<Member<MutationObserver>,MutationRecordDeliveryOptions> & observers,Registry * registry,Node & target,MutationType type,const QualifiedName * attribute_name)2805 static inline void CollectMatchingObserversForMutation(
2806     HeapHashMap<Member<MutationObserver>, MutationRecordDeliveryOptions>&
2807         observers,
2808     Registry* registry,
2809     Node& target,
2810     MutationType type,
2811     const QualifiedName* attribute_name) {
2812   if (!registry)
2813     return;
2814 
2815   for (const auto& registration : *registry) {
2816     if (registration->ShouldReceiveMutationFrom(target, type, attribute_name)) {
2817       MutationRecordDeliveryOptions delivery_options =
2818           registration->DeliveryOptions();
2819       HeapHashMap<Member<MutationObserver>,
2820                   MutationRecordDeliveryOptions>::AddResult result =
2821           observers.insert(&registration->Observer(), delivery_options);
2822       if (!result.is_new_entry)
2823         result.stored_value->value |= delivery_options;
2824     }
2825   }
2826 }
2827 
GetRegisteredMutationObserversOfType(HeapHashMap<Member<MutationObserver>,MutationRecordDeliveryOptions> & observers,MutationType type,const QualifiedName * attribute_name)2828 void Node::GetRegisteredMutationObserversOfType(
2829     HeapHashMap<Member<MutationObserver>, MutationRecordDeliveryOptions>&
2830         observers,
2831     MutationType type,
2832     const QualifiedName* attribute_name) {
2833   DCHECK((type == kMutationTypeAttributes && attribute_name) ||
2834          !attribute_name);
2835   CollectMatchingObserversForMutation(observers, MutationObserverRegistry(),
2836                                       *this, type, attribute_name);
2837   CollectMatchingObserversForMutation(observers,
2838                                       TransientMutationObserverRegistry(),
2839                                       *this, type, attribute_name);
2840   ScriptForbiddenScope forbid_script_during_raw_iteration;
2841   for (Node* node = parentNode(); node; node = node->parentNode()) {
2842     CollectMatchingObserversForMutation(observers,
2843                                         node->MutationObserverRegistry(), *this,
2844                                         type, attribute_name);
2845     CollectMatchingObserversForMutation(
2846         observers, node->TransientMutationObserverRegistry(), *this, type,
2847         attribute_name);
2848   }
2849 }
2850 
RegisterMutationObserver(MutationObserver & observer,MutationObserverOptions options,const HashSet<AtomicString> & attribute_filter)2851 void Node::RegisterMutationObserver(
2852     MutationObserver& observer,
2853     MutationObserverOptions options,
2854     const HashSet<AtomicString>& attribute_filter) {
2855   MutationObserverRegistration* registration = nullptr;
2856   for (const auto& item :
2857        EnsureRareData().EnsureMutationObserverData().Registry()) {
2858     if (&item->Observer() == &observer) {
2859       registration = item.Get();
2860       registration->ResetObservation(options, attribute_filter);
2861     }
2862   }
2863 
2864   if (!registration) {
2865     registration = MakeGarbageCollected<MutationObserverRegistration>(
2866         observer, this, options, attribute_filter);
2867     EnsureRareData().EnsureMutationObserverData().AddRegistration(registration);
2868   }
2869 
2870   GetDocument().AddMutationObserverTypes(registration->MutationTypes());
2871 }
2872 
UnregisterMutationObserver(MutationObserverRegistration * registration)2873 void Node::UnregisterMutationObserver(
2874     MutationObserverRegistration* registration) {
2875   const HeapVector<Member<MutationObserverRegistration>>* registry =
2876       MutationObserverRegistry();
2877   DCHECK(registry);
2878   if (!registry)
2879     return;
2880 
2881   // FIXME: Simplify the registration/transient registration logic to make this
2882   // understandable by humans.  The explicit dispose() is needed to have the
2883   // registration object unregister itself promptly.
2884   registration->Dispose();
2885   EnsureRareData().EnsureMutationObserverData().RemoveRegistration(
2886       registration);
2887 }
2888 
RegisterTransientMutationObserver(MutationObserverRegistration * registration)2889 void Node::RegisterTransientMutationObserver(
2890     MutationObserverRegistration* registration) {
2891   EnsureRareData().EnsureMutationObserverData().AddTransientRegistration(
2892       registration);
2893 }
2894 
UnregisterTransientMutationObserver(MutationObserverRegistration * registration)2895 void Node::UnregisterTransientMutationObserver(
2896     MutationObserverRegistration* registration) {
2897   const HeapHashSet<Member<MutationObserverRegistration>>* transient_registry =
2898       TransientMutationObserverRegistry();
2899   DCHECK(transient_registry);
2900   if (!transient_registry)
2901     return;
2902 
2903   EnsureRareData().EnsureMutationObserverData().RemoveTransientRegistration(
2904       registration);
2905 }
2906 
NotifyMutationObserversNodeWillDetach()2907 void Node::NotifyMutationObserversNodeWillDetach() {
2908   if (!GetDocument().HasMutationObservers())
2909     return;
2910 
2911   ScriptForbiddenScope forbid_script_during_raw_iteration;
2912   for (Node* node = parentNode(); node; node = node->parentNode()) {
2913     if (const HeapVector<Member<MutationObserverRegistration>>* registry =
2914             node->MutationObserverRegistry()) {
2915       for (const auto& registration : *registry)
2916         registration->ObservedSubtreeNodeWillDetach(*this);
2917     }
2918 
2919     if (const HeapHashSet<Member<MutationObserverRegistration>>*
2920             transient_registry = node->TransientMutationObserverRegistry()) {
2921       for (auto& registration : *transient_registry)
2922         registration->ObservedSubtreeNodeWillDetach(*this);
2923     }
2924   }
2925 }
2926 
HandleLocalEvents(Event & event)2927 void Node::HandleLocalEvents(Event& event) {
2928   if (!HasEventTargetData())
2929     return;
2930 
2931   if (IsDisabledFormControl(this) && IsA<MouseEvent>(event) &&
2932       !RuntimeEnabledFeatures::SendMouseEventsDisabledFormControlsEnabled()) {
2933     if (HasEventListeners(event.type())) {
2934       UseCounter::Count(GetDocument(),
2935                         WebFeature::kDispatchMouseEventOnDisabledFormControl);
2936       if (event.type() == event_type_names::kMousedown ||
2937           event.type() == event_type_names::kMouseup) {
2938         UseCounter::Count(
2939             GetDocument(),
2940             WebFeature::kDispatchMouseUpDownEventOnDisabledFormControl);
2941       }
2942     }
2943     return;
2944   }
2945 
2946   FireEventListeners(event);
2947 }
2948 
DispatchScopedEvent(Event & event)2949 void Node::DispatchScopedEvent(Event& event) {
2950   event.SetTrusted(true);
2951   EventDispatcher::DispatchScopedEvent(*this, event);
2952 }
2953 
DispatchEventInternal(Event & event)2954 DispatchEventResult Node::DispatchEventInternal(Event& event) {
2955   return EventDispatcher::DispatchEvent(*this, event);
2956 }
2957 
DispatchSubtreeModifiedEvent()2958 void Node::DispatchSubtreeModifiedEvent() {
2959   if (IsInShadowTree())
2960     return;
2961 
2962 #if DCHECK_IS_ON()
2963   DCHECK(!EventDispatchForbiddenScope::IsEventDispatchForbidden());
2964 #endif
2965 
2966   if (!GetDocument().HasListenerType(Document::kDOMSubtreeModifiedListener))
2967     return;
2968 
2969   DispatchScopedEvent(*MutationEvent::Create(
2970       event_type_names::kDOMSubtreeModified, Event::Bubbles::kYes));
2971 }
2972 
DispatchDOMActivateEvent(int detail,Event & underlying_event)2973 DispatchEventResult Node::DispatchDOMActivateEvent(int detail,
2974                                                    Event& underlying_event) {
2975 #if DCHECK_IS_ON()
2976   DCHECK(!EventDispatchForbiddenScope::IsEventDispatchForbidden());
2977 #endif
2978   UIEvent& event = *UIEvent::Create();
2979   event.initUIEvent(event_type_names::kDOMActivate, true, true,
2980                     GetDocument().domWindow(), detail);
2981   event.SetUnderlyingEvent(&underlying_event);
2982   event.SetComposed(underlying_event.composed());
2983   if (!isConnected())
2984     event.SetCopyEventPathFromUnderlyingEvent();
2985   DispatchScopedEvent(event);
2986 
2987   // TODO(dtapuska): Dispatching scoped events shouldn't check the return
2988   // type because the scoped event could get put off in the delayed queue.
2989   return EventTarget::GetDispatchEventResult(event);
2990 }
2991 
DispatchSimulatedClick(const Event * underlying_event,SimulatedClickMouseEventOptions event_options,SimulatedClickCreationScope scope)2992 void Node::DispatchSimulatedClick(const Event* underlying_event,
2993                                   SimulatedClickMouseEventOptions event_options,
2994                                   SimulatedClickCreationScope scope) {
2995   if (auto* element = IsElementNode() ? To<Element>(this) : parentElement()) {
2996     element->ActivateDisplayLockIfNeeded(
2997         DisplayLockActivationReason::kSimulatedClick);
2998   }
2999   EventDispatcher::DispatchSimulatedClick(*this, underlying_event,
3000                                           event_options, scope);
3001 }
3002 
DefaultEventHandler(Event & event)3003 void Node::DefaultEventHandler(Event& event) {
3004   if (event.target() != this)
3005     return;
3006   const AtomicString& event_type = event.type();
3007   if (event_type == event_type_names::kKeydown ||
3008       event_type == event_type_names::kKeypress ||
3009       event_type == event_type_names::kKeyup) {
3010     if (auto* keyboard_event = DynamicTo<KeyboardEvent>(&event)) {
3011       if (LocalFrame* frame = GetDocument().GetFrame()) {
3012         frame->GetEventHandler().DefaultKeyboardEventHandler(keyboard_event);
3013       }
3014     }
3015   } else if (event_type == event_type_names::kClick) {
3016     auto* ui_event = DynamicTo<UIEvent>(event);
3017     int detail = ui_event ? ui_event->detail() : 0;
3018     if (DispatchDOMActivateEvent(detail, event) !=
3019         DispatchEventResult::kNotCanceled)
3020       event.SetDefaultHandled();
3021   } else if (event_type == event_type_names::kContextmenu &&
3022              IsA<MouseEvent>(event)) {
3023     if (Page* page = GetDocument().GetPage()) {
3024       page->GetContextMenuController().HandleContextMenuEvent(
3025           To<MouseEvent>(&event));
3026     }
3027   } else if (event_type == event_type_names::kTextInput) {
3028     if (event.HasInterface(event_interface_names::kTextEvent)) {
3029       if (LocalFrame* frame = GetDocument().GetFrame()) {
3030         frame->GetEventHandler().DefaultTextInputEventHandler(
3031             To<TextEvent>(&event));
3032       }
3033     }
3034   } else if (RuntimeEnabledFeatures::MiddleClickAutoscrollEnabled() &&
3035              event_type == event_type_names::kMousedown &&
3036              IsA<MouseEvent>(event)) {
3037     auto& mouse_event = To<MouseEvent>(event);
3038     if (mouse_event.button() ==
3039         static_cast<int16_t>(WebPointerProperties::Button::kMiddle)) {
3040       if (EnclosingLinkEventParentOrSelf())
3041         return;
3042 
3043       // Avoid that canBeScrolledAndHasScrollableArea changes layout tree
3044       // structure.
3045       // FIXME: We should avoid synchronous layout if possible. We can
3046       // remove this synchronous layout if we avoid synchronous layout in
3047       // LayoutTextControlSingleLine::scrollHeight
3048       GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kInput);
3049       LayoutObject* layout_object = GetLayoutObject();
3050       while (layout_object && (!layout_object->IsBox() ||
3051                                !To<LayoutBox>(layout_object)
3052                                     ->CanBeScrolledAndHasScrollableArea())) {
3053         if (auto* document = DynamicTo<Document>(layout_object->GetNode())) {
3054           Element* owner = document->LocalOwner();
3055           layout_object = owner ? owner->GetLayoutObject() : nullptr;
3056         } else {
3057           layout_object = layout_object->Parent();
3058         }
3059       }
3060       if (layout_object) {
3061         if (LocalFrame* frame = GetDocument().GetFrame())
3062           frame->GetEventHandler().StartMiddleClickAutoscroll(layout_object);
3063       }
3064     }
3065   }
3066 }
3067 
UpdateHadKeyboardEvent(const Event & event)3068 void Node::UpdateHadKeyboardEvent(const Event& event) {
3069   if (GetDocument().HadKeyboardEvent())
3070     return;
3071 
3072   GetDocument().SetHadKeyboardEvent(true);
3073 
3074   // Changes to HadKeyboardEvent may affect :focus-visible matching,
3075   // ShouldHaveFocusAppearance and theme painting.
3076   if (GetLayoutObject()) {
3077     InvalidateIfHasEffectiveAppearance();
3078 
3079     auto* this_node = DynamicTo<ContainerNode>(this);
3080     if (RuntimeEnabledFeatures::CSSFocusVisibleEnabled() && this_node)
3081       this_node->FocusVisibleStateChanged();
3082   }
3083 }
3084 
HasActivationBehavior() const3085 bool Node::HasActivationBehavior() const {
3086   return false;
3087 }
3088 
WillRespondToMouseMoveEvents()3089 bool Node::WillRespondToMouseMoveEvents() {
3090   if (IsDisabledFormControl(this))
3091     return false;
3092   return HasEventListeners(event_type_names::kMousemove) ||
3093          HasEventListeners(event_type_names::kMouseover) ||
3094          HasEventListeners(event_type_names::kMouseout);
3095 }
3096 
WillRespondToMouseClickEvents()3097 bool Node::WillRespondToMouseClickEvents() {
3098   if (IsDisabledFormControl(this))
3099     return false;
3100   GetDocument().UpdateStyleAndLayoutTree();
3101   return HasEditableStyle(*this) ||
3102          HasAnyEventListeners(event_util::MouseButtonEventTypes());
3103 }
3104 
ConnectedSubframeCount() const3105 unsigned Node::ConnectedSubframeCount() const {
3106   return HasRareData() ? RareData()->ConnectedSubframeCount() : 0;
3107 }
3108 
IncrementConnectedSubframeCount()3109 void Node::IncrementConnectedSubframeCount() {
3110   DCHECK(IsContainerNode());
3111   EnsureRareData().IncrementConnectedSubframeCount();
3112 }
3113 
DecrementConnectedSubframeCount()3114 void Node::DecrementConnectedSubframeCount() {
3115   RareData()->DecrementConnectedSubframeCount();
3116 }
3117 
getDestinationInsertionPoints()3118 StaticNodeList* Node::getDestinationInsertionPoints() {
3119   // TODO(crbug.com/937746): Anything caught by this DCHECK is using the
3120   // now-removed Shadow DOM v0 API.
3121   DCHECK(false)
3122       << "Shadow DOM v0 has been removed (getDestinationInsertionPoints).";
3123 
3124   UpdateDistributionForLegacyDistributedNodes();
3125   HeapVector<Member<V0InsertionPoint>, 8> insertion_points;
3126   CollectDestinationInsertionPoints(*this, insertion_points);
3127   HeapVector<Member<Node>> filtered_insertion_points;
3128   for (const auto& insertion_point : insertion_points) {
3129     DCHECK(insertion_point->ContainingShadowRoot());
3130     if (!insertion_point->ContainingShadowRoot()->IsOpenOrV0())
3131       break;
3132     filtered_insertion_points.push_back(insertion_point);
3133   }
3134   return StaticNodeList::Adopt(filtered_insertion_points);
3135 }
3136 
AssignedSlot() const3137 HTMLSlotElement* Node::AssignedSlot() const {
3138   DCHECK(!IsPseudoElement());
3139   ShadowRoot* root = V1ShadowRootOfParent();
3140   if (!root)
3141     return nullptr;
3142 
3143   if (!root->HasSlotAssignment())
3144     return nullptr;
3145 
3146   // TODO(hayato): Node::AssignedSlot() shouldn't be called while
3147   // in executing RecalcAssignment(), however, unfortunately,
3148   // that could happen as follows:
3149   //
3150   // 1. RecalcAssignment() can detach a node
3151   // 2. Then, DetachLayoutTree() may use FlatTreeTraversal via the hook of
3152   // AXObjectCacheImpl::ChildrenChanged().
3153   //
3154   // Note that using FlatTreeTraversal in detaching layout tree should be banned
3155   // in the long term.
3156   //
3157   // If we can remove such code path, we don't need to check
3158   // IsInSlotAssignmentRecalc() here.
3159   if (GetDocument().IsInSlotAssignmentRecalc()) {
3160     // FlatTreeNodeData is not realiable here. Entering slow path.
3161     return root->AssignedSlotFor(*this);
3162   }
3163 
3164   // Recalc assignment, if necessary, to make sure the FlatTreeNodeData is not
3165   // dirty. RecalcAssignment() is almost no-op if we don't need to recalc.
3166   root->GetSlotAssignment().RecalcAssignment();
3167   if (FlatTreeNodeData* data = GetFlatTreeNodeData()) {
3168     DCHECK_EQ(root->AssignedSlotFor(*this), data->AssignedSlot());
3169     return data->AssignedSlot();
3170   }
3171   return nullptr;
3172 }
3173 
assignedSlotForBinding()3174 HTMLSlotElement* Node::assignedSlotForBinding() {
3175   // assignedSlot doesn't need to recalc slot assignment
3176   if (ShadowRoot* root = V1ShadowRootOfParent()) {
3177     if (root->GetType() == ShadowRootType::kOpen)
3178       return AssignedSlot();
3179   }
3180   return nullptr;
3181 }
3182 
SetFocused(bool flag,mojom::blink::FocusType focus_type)3183 void Node::SetFocused(bool flag, mojom::blink::FocusType focus_type) {
3184   if (focus_type == mojom::blink::FocusType::kMouse)
3185     GetDocument().SetHadKeyboardEvent(false);
3186   GetDocument().UserActionElements().SetFocused(this, flag);
3187 }
3188 
SetHasFocusWithin(bool flag)3189 void Node::SetHasFocusWithin(bool flag) {
3190   GetDocument().UserActionElements().SetHasFocusWithin(this, flag);
3191 }
3192 
SetDragged(bool flag)3193 void Node::SetDragged(bool flag) {
3194   GetDocument().UserActionElements().SetDragged(this, flag);
3195 }
3196 
IsUserActionElementActive() const3197 bool Node::IsUserActionElementActive() const {
3198   DCHECK(IsUserActionElement());
3199   return GetDocument().UserActionElements().IsActive(this);
3200 }
3201 
IsUserActionElementInActiveChain() const3202 bool Node::IsUserActionElementInActiveChain() const {
3203   DCHECK(IsUserActionElement());
3204   return GetDocument().UserActionElements().IsInActiveChain(this);
3205 }
3206 
IsUserActionElementDragged() const3207 bool Node::IsUserActionElementDragged() const {
3208   DCHECK(IsUserActionElement());
3209   return GetDocument().UserActionElements().IsDragged(this);
3210 }
3211 
IsUserActionElementHovered() const3212 bool Node::IsUserActionElementHovered() const {
3213   DCHECK(IsUserActionElement());
3214   return GetDocument().UserActionElements().IsHovered(this);
3215 }
3216 
IsUserActionElementFocused() const3217 bool Node::IsUserActionElementFocused() const {
3218   DCHECK(IsUserActionElement());
3219   return GetDocument().UserActionElements().IsFocused(this);
3220 }
3221 
IsUserActionElementHasFocusWithin() const3222 bool Node::IsUserActionElementHasFocusWithin() const {
3223   DCHECK(IsUserActionElement());
3224   return GetDocument().UserActionElements().HasFocusWithin(this);
3225 }
3226 
SetCustomElementState(CustomElementState new_state)3227 void Node::SetCustomElementState(CustomElementState new_state) {
3228   CustomElementState old_state = GetCustomElementState();
3229 
3230   switch (new_state) {
3231     case CustomElementState::kUncustomized:
3232       NOTREACHED();  // Everything starts in this state
3233       return;
3234 
3235     case CustomElementState::kUndefined:
3236       DCHECK_EQ(CustomElementState::kUncustomized, old_state);
3237       break;
3238 
3239     case CustomElementState::kCustom:
3240       DCHECK(old_state == CustomElementState::kUndefined ||
3241              old_state == CustomElementState::kFailed ||
3242              old_state == CustomElementState::kPreCustomized);
3243       break;
3244 
3245     case CustomElementState::kFailed:
3246       DCHECK_NE(CustomElementState::kFailed, old_state);
3247       break;
3248 
3249     case CustomElementState::kPreCustomized:
3250       DCHECK_EQ(CustomElementState::kFailed, old_state);
3251       break;
3252   }
3253 
3254   DCHECK(IsHTMLElement());
3255   DCHECK_NE(kV0Upgraded, GetV0CustomElementState());
3256 
3257   auto* element = To<Element>(this);
3258   bool was_defined = element->IsDefined();
3259 
3260   node_flags_ = (node_flags_ & ~kCustomElementStateMask) |
3261                 static_cast<NodeFlags>(new_state);
3262   DCHECK(new_state == GetCustomElementState());
3263 
3264   if (element->IsDefined() != was_defined) {
3265     element->PseudoStateChanged(CSSSelector::kPseudoDefined);
3266     if (RuntimeEnabledFeatures::CustomElementsV0Enabled())
3267       element->PseudoStateChanged(CSSSelector::kPseudoUnresolved);
3268   }
3269 }
3270 
SetV0CustomElementState(V0CustomElementState new_state)3271 void Node::SetV0CustomElementState(V0CustomElementState new_state) {
3272   DCHECK(RuntimeEnabledFeatures::CustomElementsV0Enabled());
3273   V0CustomElementState old_state = GetV0CustomElementState();
3274 
3275   switch (new_state) {
3276     case kV0NotCustomElement:
3277       NOTREACHED();  // Everything starts in this state
3278       return;
3279 
3280     case kV0WaitingForUpgrade:
3281       DCHECK_EQ(kV0NotCustomElement, old_state);
3282       break;
3283 
3284     case kV0Upgraded:
3285       DCHECK_EQ(kV0WaitingForUpgrade, old_state);
3286       break;
3287   }
3288 
3289   DCHECK(IsHTMLElement() || IsSVGElement());
3290   DCHECK(CustomElementState::kCustom != GetCustomElementState());
3291   SetFlag(kV0CustomElementFlag);
3292   SetFlag(new_state == kV0Upgraded, kV0CustomElementUpgradedFlag);
3293 
3294   if (old_state == kV0NotCustomElement || new_state == kV0Upgraded) {
3295     To<Element>(this)->PseudoStateChanged(CSSSelector::kPseudoUnresolved);
3296     To<Element>(this)->PseudoStateChanged(CSSSelector::kPseudoDefined);
3297   }
3298 }
3299 
CheckSlotChange(SlotChangeType slot_change_type)3300 void Node::CheckSlotChange(SlotChangeType slot_change_type) {
3301   // Common check logic is used in both cases, "after inserted" and "before
3302   // removed".
3303 
3304   // Relevant DOM Standard:
3305   // https://dom.spec.whatwg.org/#concept-node-insert
3306   // https://dom.spec.whatwg.org/#concept-node-remove
3307 
3308   // This function is usually called while DOM Mutation is still in-progress.
3309   // For "after inserted" case, we assume that a parent and a child have been
3310   // already connected. For "before removed" case, we assume that a parent and a
3311   // child have not been disconnected yet.
3312 
3313   if (!IsSlotable())
3314     return;
3315 
3316   if (ShadowRoot* root = V1ShadowRootOfParent()) {
3317     // A shadow host's child can be assigned to a slot in the host's shadow
3318     // tree.
3319 
3320     // Although DOM Standard requires "assign a slot for node / run assign
3321     // slotables" at this timing, we skip it as an optimization.
3322     if (HTMLSlotElement* slot = root->AssignedSlotFor(*this))
3323       slot->DidSlotChange(slot_change_type);
3324   } else if (IsInV1ShadowTree()) {
3325     // Checking for fallback content if the node is in a v1 shadow tree.
3326     if (auto* parent_slot = DynamicTo<HTMLSlotElement>(parentElement())) {
3327       DCHECK(parent_slot->SupportsAssignment());
3328       // The parent_slot's assigned nodes might not be calculated because they
3329       // are lazy evaluated later at UpdateDistribution() so we have to check it
3330       // here.
3331       if (!parent_slot->HasAssignedNodesSlow())
3332         parent_slot->DidSlotChange(slot_change_type);
3333     }
3334   }
3335 }
3336 
IsEffectiveRootScroller() const3337 bool Node::IsEffectiveRootScroller() const {
3338   return GetLayoutObject() ? GetLayoutObject()->IsEffectiveRootScroller()
3339                            : false;
3340 }
3341 
AutoscrollBox()3342 LayoutBox* Node::AutoscrollBox() {
3343   return nullptr;
3344 }
3345 
StopAutoscroll()3346 void Node::StopAutoscroll() {}
3347 
GetWebPluginContainer() const3348 WebPluginContainerImpl* Node::GetWebPluginContainer() const {
3349   if (!IsA<HTMLObjectElement>(this) && !IsA<HTMLEmbedElement>(this)) {
3350     return nullptr;
3351   }
3352 
3353   if (auto* embedded = DynamicTo<LayoutEmbeddedContent>(GetLayoutObject()))
3354     return embedded->Plugin();
3355   return nullptr;
3356 }
3357 
HasMediaControlAncestor() const3358 bool Node::HasMediaControlAncestor() const {
3359   const Node* current = this;
3360 
3361   while (current) {
3362     if (current->IsMediaControls() || current->IsMediaControlElement())
3363       return true;
3364 
3365     if (current->IsShadowRoot())
3366       current = current->OwnerShadowHost();
3367     else
3368       current = current->ParentOrShadowHostElement();
3369   }
3370 
3371   return false;
3372 }
3373 
FlatTreeParentChanged()3374 void Node::FlatTreeParentChanged() {
3375   if (!isConnected())
3376     return;
3377   // TODO(futhark): Replace with DCHECK(IsSlotable()) when Shadow DOM V0 support
3378   // is removed.
3379   if (!IsElementNode() && !IsTextNode()) {
3380     DCHECK(GetDocument().MayContainV0Shadow());
3381     return;
3382   }
3383   if (const ComputedStyle* style = GetComputedStyle()) {
3384     // We are moving a node with ensured computed style into the flat tree.
3385     // Clear ensured styles so that we can use IsEnsuredOutsideFlatTree() to
3386     // determine that we are outside the flat tree before updating the style
3387     // recalc root in MarkAncestorsWithChildNeedsStyleRecalc().
3388     if (style->IsEnsuredOutsideFlatTree())
3389       DetachLayoutTree();
3390   }
3391   // The node changed the flat tree position by being slotted to a new slot or
3392   // slotted for the first time. We need to recalc style since the inheritance
3393   // parent may have changed.
3394   if (NeedsStyleRecalc()) {
3395     // The ancestor chain may have changed. We need to make sure that the
3396     // child-dirty flags are updated, but the SetNeedsStyleRecalc() call below
3397     // will skip MarkAncestorsWithChildNeedsStyleRecalc() if the node was
3398     // already dirty.
3399     MarkAncestorsWithChildNeedsStyleRecalc();
3400   }
3401   SetNeedsStyleRecalc(kLocalStyleChange,
3402                       StyleChangeReasonForTracing::Create(
3403                           style_change_reason::kFlatTreeChange));
3404   // We also need to force a layout tree re-attach since the layout tree parent
3405   // box may have changed.
3406   SetForceReattachLayoutTree();
3407 }
3408 
RemovedFromFlatTree()3409 void Node::RemovedFromFlatTree() {
3410   // This node was previously part of the flat tree, but due to slot re-
3411   // assignment it no longer is. We need to detach the layout tree and notify
3412   // the StyleEngine in case the StyleRecalcRoot is removed from the flat tree.
3413   DetachLayoutTree();
3414   GetDocument().GetStyleEngine().RemovedFromFlatTree(*this);
3415 }
3416 
RegisterScrollTimeline(ScrollTimeline * timeline)3417 void Node::RegisterScrollTimeline(ScrollTimeline* timeline) {
3418   EnsureRareData().RegisterScrollTimeline(timeline);
3419 }
UnregisterScrollTimeline(ScrollTimeline * timeline)3420 void Node::UnregisterScrollTimeline(ScrollTimeline* timeline) {
3421   EnsureRareData().UnregisterScrollTimeline(timeline);
3422 }
3423 
Trace(Visitor * visitor) const3424 void Node::Trace(Visitor* visitor) const {
3425   visitor->Trace(parent_or_shadow_host_node_);
3426   visitor->Trace(previous_);
3427   visitor->Trace(next_);
3428   visitor->Trace(data_);
3429   visitor->Trace(tree_scope_);
3430   EventTarget::Trace(visitor);
3431 }
3432 
3433 }  // namespace blink
3434 
3435 #if DCHECK_IS_ON()
3436 
showNode(const blink::Node * node)3437 void showNode(const blink::Node* node) {
3438   if (node)
3439     LOG(INFO) << *node;
3440   else
3441     LOG(INFO) << "Cannot showNode for <null>";
3442 }
3443 
showTree(const blink::Node * node)3444 void showTree(const blink::Node* node) {
3445   if (node)
3446     LOG(INFO) << "\n" << node->ToTreeStringForThis().Utf8();
3447   else
3448     LOG(INFO) << "Cannot showTree for <null>";
3449 }
3450 
showNodePath(const blink::Node * node)3451 void showNodePath(const blink::Node* node) {
3452   if (node) {
3453     std::stringstream stream;
3454     node->PrintNodePathTo(stream);
3455     LOG(INFO) << stream.str();
3456   } else {
3457     LOG(INFO) << "Cannot showNodePath for <null>";
3458   }
3459 }
3460 
3461 #endif
3462