/*
 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
 *           (C) 1999 Antti Koivisto (koivisto@kde.org)
 *           (C) 2001 Dirk Mueller (mueller@kde.org)
 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All
 * rights reserved.
 * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
 * Copyright (C) 2009 Torch Mobile Inc. All rights reserved.
 * (http://www.torchmobile.com/)
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public License
 * along with this library; see the file COPYING.LIB.  If not, write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 */

#include "core/dom/Node.h"

#include "bindings/core/v8/ExceptionState.h"
#include "bindings/core/v8/NodeOrString.h"
#include "core/HTMLNames.h"
#include "core/MathMLNames.h"
#include "core/css/CSSSelector.h"
#include "core/css/resolver/StyleResolver.h"
#include "core/dom/AXObjectCache.h"
#include "core/dom/Attr.h"
#include "core/dom/Attribute.h"
#include "core/dom/ChildListMutationScope.h"
#include "core/dom/ChildNodeList.h"
#include "core/dom/DOMNodeIds.h"
#include "core/dom/Document.h"
#include "core/dom/DocumentFragment.h"
#include "core/dom/DocumentType.h"
#include "core/dom/Element.h"
#include "core/dom/ElementRareData.h"
#include "core/dom/ElementTraversal.h"
#include "core/dom/ExceptionCode.h"
#include "core/dom/GetRootNodeOptions.h"
#include "core/dom/LayoutTreeBuilderTraversal.h"
#include "core/dom/NodeRareData.h"
#include "core/dom/NodeTraversal.h"
#include "core/dom/ProcessingInstruction.h"
#include "core/dom/Range.h"
#include "core/dom/StaticNodeList.h"
#include "core/dom/StyleEngine.h"
#include "core/dom/TemplateContentDocumentFragment.h"
#include "core/dom/Text.h"
#include "core/dom/TreeScopeAdopter.h"
#include "core/dom/UserActionElementSet.h"
#include "core/dom/custom/CustomElement.h"
#include "core/dom/shadow/ElementShadow.h"
#include "core/dom/shadow/FlatTreeTraversal.h"
#include "core/dom/shadow/InsertionPoint.h"
#include "core/dom/shadow/ShadowRoot.h"
#include "core/dom/shadow/SlotAssignment.h"
#include "core/editing/EditingUtilities.h"
#include "core/editing/markers/DocumentMarkerController.h"
#include "core/events/Event.h"
#include "core/events/EventDispatchMediator.h"
#include "core/events/EventDispatcher.h"
#include "core/events/EventListener.h"
#include "core/events/GestureEvent.h"
#include "core/events/InputEvent.h"
#include "core/events/KeyboardEvent.h"
#include "core/events/MouseEvent.h"
#include "core/events/MutationEvent.h"
#include "core/events/PointerEvent.h"
#include "core/events/PointerEventFactory.h"
#include "core/events/TextEvent.h"
#include "core/events/TouchEvent.h"
#include "core/events/UIEvent.h"
#include "core/events/WheelEvent.h"
#include "core/frame/EventHandlerRegistry.h"
#include "core/frame/FrameView.h"
#include "core/frame/LocalDOMWindow.h"
#include "core/frame/LocalFrame.h"
#include "core/frame/UseCounter.h"
#include "core/html/HTMLDialogElement.h"
#include "core/html/HTMLFrameOwnerElement.h"
#include "core/html/HTMLSlotElement.h"
#include "core/input/EventHandler.h"
#include "core/layout/LayoutBox.h"
#include "core/layout/LayoutPart.h"
#include "core/page/ContextMenuController.h"
#include "core/page/Page.h"
#include "core/plugins/PluginView.h"
#include "core/svg/SVGElement.h"
#include "core/svg/graphics/SVGImage.h"
#include "platform/EventDispatchForbiddenScope.h"
#include "platform/InstanceCounters.h"
#include "platform/RuntimeEnabledFeatures.h"
#include "platform/bindings/DOMDataStore.h"
#include "platform/bindings/Microtask.h"
#include "platform/bindings/ScriptWrappableVisitor.h"
#include "platform/bindings/V8DOMWrapper.h"
#include "platform/instrumentation/tracing/TraceEvent.h"
#include "platform/instrumentation/tracing/TracedValue.h"
#include "platform/wtf/HashSet.h"
#include "platform/wtf/Vector.h"
#include "platform/wtf/allocator/Partitions.h"
#include "platform/wtf/text/CString.h"
#include "platform/wtf/text/StringBuilder.h"

namespace blink {

namespace {

// TODO(crbug.com/545926): Unsafe hack to avoid triggering the
// ThreadRestrictionVerifier on StringImpl. This should be fixed completely, and
// we should always avoid accessing these strings from the impl thread.
// Currently code that calls into this method from the impl thread tries to make
// sure that the main thread is not running at this time.
void AppendUnsafe(StringBuilder& builder, const String& off_thread_string) {
  StringImpl* impl = off_thread_string.Impl();
  if (impl) {
    builder.Append(impl->Is8Bit()
                       ? StringView(impl->Characters8(), impl->length())
                       : StringView(impl->Characters16(), impl->length()));
  }
}

}  // namespace

using namespace HTMLNames;

struct SameSizeAsNode : EventTarget {
  uint32_t node_flags_;
  Member<void*> willbe_member_[4];
  void* pointer_;
};

static_assert(sizeof(Node) <= sizeof(SameSizeAsNode), "Node should stay small");

#if DUMP_NODE_STATISTICS
using WeakNodeSet = HeapHashSet<WeakMember<Node>>;
static WeakNodeSet& liveNodeSet() {
  DEFINE_STATIC_LOCAL(WeakNodeSet, set, (new WeakNodeSet));
  return set;
}
#endif

void Node::DumpStatistics() {
#if DUMP_NODE_STATISTICS
  size_t nodesWithRareData = 0;

  size_t elementNodes = 0;
  size_t attrNodes = 0;
  size_t textNodes = 0;
  size_t cdataNodes = 0;
  size_t commentNodes = 0;
  size_t piNodes = 0;
  size_t documentNodes = 0;
  size_t docTypeNodes = 0;
  size_t fragmentNodes = 0;
  size_t shadowRootNodes = 0;

  HashMap<String, size_t> perTagCount;

  size_t attributes = 0;
  size_t elementsWithAttributeStorage = 0;
  size_t elementsWithRareData = 0;
  size_t elementsWithNamedNodeMap = 0;

  {
    ScriptForbiddenScope forbidScriptDuringRawIteration;
    for (Node* node : liveNodeSet()) {
      if (node->hasRareData()) {
        ++nodesWithRareData;
        if (node->isElementNode()) {
          ++elementsWithRareData;
          if (toElement(node)->hasNamedNodeMap())
            ++elementsWithNamedNodeMap;
        }
      }

      switch (node->getNodeType()) {
        case kElementNode: {
          ++elementNodes;

          // Tag stats
          Element* element = toElement(node);
          HashMap<String, size_t>::AddResult result =
              perTagCount.add(element->tagName(), 1);
          if (!result.isNewEntry)
            result.storedValue->value++;

          size_t attributeCount = element->attributesWithoutUpdate().size();
          if (attributeCount) {
            attributes += attributeCount;
            ++elementsWithAttributeStorage;
          }
          break;
        }
        case kAttributeNode: {
          ++attrNodes;
          break;
        }
        case kTextNode: {
          ++textNodes;
          break;
        }
        case kCdataSectionNode: {
          ++cdataNodes;
          break;
        }
        case kCommentNode: {
          ++commentNodes;
          break;
        }
        case kProcessingInstructionNode: {
          ++piNodes;
          break;
        }
        case kDocumentNode: {
          ++documentNodes;
          break;
        }
        case kDocumentTypeNode: {
          ++docTypeNodes;
          break;
        }
        case kDocumentFragmentNode: {
          if (node->isShadowRoot())
            ++shadowRootNodes;
          else
            ++fragmentNodes;
          break;
        }
      }
    }
  }

  std::stringstream perTagStream;
  for (const auto& entry : perTagCount)
    perTagStream << "  Number of <" << entry.key.utf8().data()
                 << "> tags: " << entry.value << "\n";

  LOG(INFO) << "\n"
            << "Number of Nodes: " << liveNodeSet().size() << "\n"
            << "Number of Nodes with RareData: " << nodesWithRareData << "\n\n"

            << "NodeType distribution:\n"
            << "  Number of Element nodes: " << elementNodes << "\n"
            << "  Number of Attribute nodes: " << attrNodes << "\n"
            << "  Number of Text nodes: " << textNodes << "\n"
            << "  Number of CDATASection nodes: " << cdataNodes << "\n"
            << "  Number of Comment nodes: " << commentNodes << "\n"
            << "  Number of ProcessingInstruction nodes: " << piNodes << "\n"
            << "  Number of Document nodes: " << documentNodes << "\n"
            << "  Number of DocumentType nodes: " << docTypeNodes << "\n"
            << "  Number of DocumentFragment nodes: " << fragmentNodes << "\n"
            << "  Number of ShadowRoot nodes: " << shadowRootNodes << "\n"

            << "Element tag name distibution:\n"
            << perTagStream.str()

            << "Attributes:\n"
            << "  Number of Attributes (non-Node and Node): " << attributes
            << " x " << sizeof(Attribute) << "Bytes\n"
            << "  Number of Elements with attribute storage: "
            << elementsWithAttributeStorage << " x " << sizeof(ElementData)
            << "Bytes\n"
            << "  Number of Elements with RareData: " << elementsWithRareData
            << "\n"
            << "  Number of Elements with NamedNodeMap: "
            << elementsWithNamedNodeMap << " x " << sizeof(NamedNodeMap)
            << "Bytes";
#endif
}

void Node::TrackForDebugging() {
#if DUMP_NODE_STATISTICS
  liveNodeSet().add(this);
#endif
}

Node::Node(TreeScope* tree_scope, ConstructionType type)
    : node_flags_(type),
      parent_or_shadow_host_node_(nullptr),
      tree_scope_(tree_scope),
      previous_(nullptr),
      next_(nullptr) {
  DCHECK(tree_scope_ || type == kCreateDocument || type == kCreateShadowRoot);
#if !defined(NDEBUG) || (defined(DUMP_NODE_STATISTICS) && DUMP_NODE_STATISTICS)
  TrackForDebugging();
#endif
  InstanceCounters::IncrementNodeCounter();
}

Node::~Node() {
  if (!HasRareData() && !data_.node_layout_data_->IsSharedEmptyData())
    delete data_.node_layout_data_;
  InstanceCounters::DecrementNodeCounter();
}

NodeRareData* Node::RareData() const {
  SECURITY_DCHECK(HasRareData());
  return static_cast<NodeRareData*>(data_.rare_data_);
}

NodeRareData& Node::EnsureRareData() {
  if (HasRareData())
    return *RareData();

  if (IsElementNode())
    data_.rare_data_ = ElementRareData::Create(data_.node_layout_data_);
  else
    data_.rare_data_ = NodeRareData::Create(data_.node_layout_data_);

  DCHECK(data_.rare_data_);
  SetFlag(kHasRareDataFlag);
  ScriptWrappableVisitor::WriteBarrier(this, RareData());
  return *RareData();
}

Node* Node::ToNode() {
  return this;
}

int Node::tabIndex() const {
  return 0;
}

String Node::nodeValue() const {
  return String();
}

void Node::setNodeValue(const String&) {
  // By default, setting nodeValue has no effect.
}

NodeList* Node::childNodes() {
  ThreadState::MainThreadGCForbiddenScope gc_forbidden;
  if (IsContainerNode())
    return EnsureRareData().EnsureNodeLists().EnsureChildNodeList(
        ToContainerNode(*this));
  return EnsureRareData().EnsureNodeLists().EnsureEmptyChildNodeList(*this);
}

Node* Node::PseudoAwarePreviousSibling() const {
  if (parentElement() && !previousSibling()) {
    Element* parent = parentElement();
    if (IsAfterPseudoElement() && parent->lastChild())
      return parent->lastChild();
    if (!IsBeforePseudoElement())
      return parent->GetPseudoElement(kPseudoIdBefore);
  }
  return previousSibling();
}

Node* Node::PseudoAwareNextSibling() const {
  if (parentElement() && !nextSibling()) {
    Element* parent = parentElement();
    if (IsBeforePseudoElement() && parent->HasChildren())
      return parent->firstChild();
    if (!IsAfterPseudoElement())
      return parent->GetPseudoElement(kPseudoIdAfter);
  }
  return nextSibling();
}

Node* Node::PseudoAwareFirstChild() const {
  if (IsElementNode()) {
    const Element* current_element = ToElement(this);
    Node* first = current_element->GetPseudoElement(kPseudoIdBefore);
    if (first)
      return first;
    first = current_element->firstChild();
    if (!first)
      first = current_element->GetPseudoElement(kPseudoIdAfter);
    return first;
  }

  return firstChild();
}

Node* Node::PseudoAwareLastChild() const {
  if (IsElementNode()) {
    const Element* current_element = ToElement(this);
    Node* last = current_element->GetPseudoElement(kPseudoIdAfter);
    if (last)
      return last;
    last = current_element->lastChild();
    if (!last)
      last = current_element->GetPseudoElement(kPseudoIdBefore);
    return last;
  }

  return lastChild();
}

Node& Node::TreeRoot() const {
  if (IsInTreeScope())
    return ContainingTreeScope().RootNode();
  const Node* node = this;
  while (node->parentNode())
    node = node->parentNode();
  return const_cast<Node&>(*node);
}

Node* Node::getRootNode(const GetRootNodeOptions& options) const {
  return (options.hasComposed() && options.composed()) ? &ShadowIncludingRoot()
                                                       : &TreeRoot();
}

Node* Node::insertBefore(Node* new_child,
                         Node* ref_child,
                         ExceptionState& exception_state) {
  if (IsContainerNode())
    return ToContainerNode(this)->InsertBefore(new_child, ref_child,
                                               exception_state);

  exception_state.ThrowDOMException(
      kHierarchyRequestError, "This node type does not support this method.");
  return nullptr;
}

Node* Node::replaceChild(Node* new_child,
                         Node* old_child,
                         ExceptionState& exception_state) {
  if (IsContainerNode())
    return ToContainerNode(this)->ReplaceChild(new_child, old_child,
                                               exception_state);

  exception_state.ThrowDOMException(
      kHierarchyRequestError, "This node type does not support this method.");
  return nullptr;
}

Node* Node::removeChild(Node* old_child, ExceptionState& exception_state) {
  if (IsContainerNode())
    return ToContainerNode(this)->RemoveChild(old_child, exception_state);

  exception_state.ThrowDOMException(
      kNotFoundError, "This node type does not support this method.");
  return nullptr;
}

Node* Node::appendChild(Node* new_child, ExceptionState& exception_state) {
  if (IsContainerNode())
    return ToContainerNode(this)->AppendChild(new_child, exception_state);

  exception_state.ThrowDOMException(
      kHierarchyRequestError, "This node type does not support this method.");
  return nullptr;
}

static bool IsNodeInNodes(const Node* const node,
                          const HeapVector<NodeOrString>& nodes) {
  for (const NodeOrString& node_or_string : nodes) {
    if (node_or_string.isNode() && node_or_string.getAsNode() == node)
      return true;
  }
  return false;
}

static Node* FindViablePreviousSibling(const Node& node,
                                       const HeapVector<NodeOrString>& nodes) {
  for (Node* sibling = node.previousSibling(); sibling;
       sibling = sibling->previousSibling()) {
    if (!IsNodeInNodes(sibling, nodes))
      return sibling;
  }
  return nullptr;
}

static Node* FindViableNextSibling(const Node& node,
                                   const HeapVector<NodeOrString>& nodes) {
  for (Node* sibling = node.nextSibling(); sibling;
       sibling = sibling->nextSibling()) {
    if (!IsNodeInNodes(sibling, nodes))
      return sibling;
  }
  return nullptr;
}

static Node* NodeOrStringToNode(const NodeOrString& node_or_string,
                                Document& document) {
  if (node_or_string.isNode())
    return node_or_string.getAsNode();
  return Text::Create(document, node_or_string.getAsString());
}

// Returns nullptr if an exception was thrown.
static Node* ConvertNodesIntoNode(const HeapVector<NodeOrString>& nodes,
                                  Document& document,
                                  ExceptionState& exception_state) {
  if (nodes.size() == 1)
    return NodeOrStringToNode(nodes[0], document);

  Node* fragment = DocumentFragment::Create(document);
  for (const NodeOrString& node_or_string : nodes) {
    fragment->appendChild(NodeOrStringToNode(node_or_string, document),
                          exception_state);
    if (exception_state.HadException())
      return nullptr;
  }
  return fragment;
}

void Node::Prepend(const HeapVector<NodeOrString>& nodes,
                   ExceptionState& exception_state) {
  if (Node* node = ConvertNodesIntoNode(nodes, GetDocument(), exception_state))
    insertBefore(node, firstChild(), exception_state);
}

void Node::Append(const HeapVector<NodeOrString>& nodes,
                  ExceptionState& exception_state) {
  if (Node* node = ConvertNodesIntoNode(nodes, GetDocument(), exception_state))
    appendChild(node, exception_state);
}

void Node::Before(const HeapVector<NodeOrString>& nodes,
                  ExceptionState& exception_state) {
  Node* parent = parentNode();
  if (!parent)
    return;
  Node* viable_previous_sibling = FindViablePreviousSibling(*this, nodes);
  if (Node* node = ConvertNodesIntoNode(nodes, GetDocument(), exception_state))
    parent->insertBefore(node,
                         viable_previous_sibling
                             ? viable_previous_sibling->nextSibling()
                             : parent->firstChild(),
                         exception_state);
}

void Node::After(const HeapVector<NodeOrString>& nodes,
                 ExceptionState& exception_state) {
  Node* parent = parentNode();
  if (!parent)
    return;
  Node* viable_next_sibling = FindViableNextSibling(*this, nodes);
  if (Node* node = ConvertNodesIntoNode(nodes, GetDocument(), exception_state))
    parent->insertBefore(node, viable_next_sibling, exception_state);
}

void Node::ReplaceWith(const HeapVector<NodeOrString>& nodes,
                       ExceptionState& exception_state) {
  Node* parent = parentNode();
  if (!parent)
    return;
  Node* viable_next_sibling = FindViableNextSibling(*this, nodes);
  Node* node = ConvertNodesIntoNode(nodes, GetDocument(), exception_state);
  if (exception_state.HadException())
    return;
  if (parent == parentNode())
    parent->replaceChild(node, this, exception_state);
  else
    parent->insertBefore(node, viable_next_sibling, exception_state);
}

void Node::remove(ExceptionState& exception_state) {
  if (ContainerNode* parent = parentNode())
    parent->RemoveChild(this, exception_state);
}

void Node::normalize() {
  UpdateDistribution();

  // Go through the subtree beneath us, normalizing all nodes. This means that
  // any two adjacent text nodes are merged and any empty text nodes are
  // removed.

  Node* node = this;
  while (Node* first_child = node->firstChild())
    node = first_child;
  while (node) {
    if (node == this)
      break;

    if (node->getNodeType() == kTextNode)
      node = ToText(node)->MergeNextSiblingNodesIfPossible();
    else
      node = NodeTraversal::NextPostOrder(*node);
  }
}

LayoutBox* Node::GetLayoutBox() const {
  LayoutObject* layout_object = this->GetLayoutObject();
  return layout_object && layout_object->IsBox() ? ToLayoutBox(layout_object)
                                                 : nullptr;
}

void Node::SetLayoutObject(LayoutObject* layout_object) {
  NodeRenderingData* node_layout_data =
      HasRareData() ? data_.rare_data_->GetNodeRenderingData()
                    : data_.node_layout_data_;

  // Already pointing to a non empty NodeRenderingData so just set the pointer
  // to the new LayoutObject.
  if (!node_layout_data->IsSharedEmptyData()) {
    node_layout_data->SetLayoutObject(layout_object);
    return;
  }

  if (!layout_object)
    return;

  // Swap the NodeRenderingData to point to a new NodeRenderingData instead of
  // the static SharedEmptyData instance.
  DCHECK(!node_layout_data->GetNonAttachedStyle());
  node_layout_data = new NodeRenderingData(layout_object, nullptr);
  if (HasRareData())
    data_.rare_data_->SetNodeRenderingData(node_layout_data);
  else
    data_.node_layout_data_ = node_layout_data;
}

void Node::SetNonAttachedStyle(RefPtr<ComputedStyle> non_attached_style) {
  NodeRenderingData* node_layout_data =
      HasRareData() ? data_.rare_data_->GetNodeRenderingData()
                    : data_.node_layout_data_;

  // Already pointing to a non empty NodeRenderingData so just set the pointer
  // to the new LayoutObject.
  if (!node_layout_data->IsSharedEmptyData()) {
    node_layout_data->SetNonAttachedStyle(non_attached_style);
    return;
  }

  if (!non_attached_style)
    return;

  // Swap the NodeRenderingData to point to a new NodeRenderingData instead of
  // the static SharedEmptyData instance.
  DCHECK(!node_layout_data->GetLayoutObject());
  node_layout_data = new NodeRenderingData(nullptr, non_attached_style);
  if (HasRareData())
    data_.rare_data_->SetNodeRenderingData(node_layout_data);
  else
    data_.node_layout_data_ = node_layout_data;
}

LayoutBoxModelObject* Node::GetLayoutBoxModelObject() const {
  LayoutObject* layout_object = this->GetLayoutObject();
  return layout_object && layout_object->IsBoxModelObject()
             ? ToLayoutBoxModelObject(layout_object)
             : nullptr;
}

LayoutRect Node::BoundingBox() const {
  if (GetLayoutObject())
    return LayoutRect(GetLayoutObject()->AbsoluteBoundingBoxRect());
  return LayoutRect();
}

#ifndef NDEBUG
inline static ShadowRoot* OldestShadowRootFor(const Node* node) {
  if (!node->IsElementNode())
    return nullptr;
  if (ElementShadow* shadow = ToElement(node)->Shadow())
    return &shadow->OldestShadowRoot();
  return nullptr;
}
#endif

Node& Node::ShadowIncludingRoot() const {
  if (isConnected())
    return GetDocument();
  Node* root = const_cast<Node*>(this);
  while (Node* host = root->OwnerShadowHost())
    root = host;
  while (Node* ancestor = root->parentNode())
    root = ancestor;
  DCHECK(!root->OwnerShadowHost());
  return *root;
}

bool Node::IsClosedShadowHiddenFrom(const Node& other) const {
  if (!IsInShadowTree() || GetTreeScope() == other.GetTreeScope())
    return false;

  const TreeScope* scope = &GetTreeScope();
  for (; scope->ParentTreeScope(); scope = scope->ParentTreeScope()) {
    const ContainerNode& root = scope->RootNode();
    if (root.IsShadowRoot() && !ToShadowRoot(root).IsOpenOrV0())
      break;
  }

  for (TreeScope* other_scope = &other.GetTreeScope(); other_scope;
       other_scope = other_scope->ParentTreeScope()) {
    if (other_scope == scope)
      return false;
  }
  return true;
}

bool Node::NeedsDistributionRecalc() const {
  return ShadowIncludingRoot().ChildNeedsDistributionRecalc();
}

void Node::UpdateDistribution() {
  // Extra early out to avoid spamming traces.
  if (isConnected() && !GetDocument().ChildNeedsDistributionRecalc())
    return;
  TRACE_EVENT0("blink", "Node::updateDistribution");
  ScriptForbiddenScope forbid_script;
  Node& root = ShadowIncludingRoot();
  if (root.ChildNeedsDistributionRecalc())
    root.RecalcDistribution();
}

void Node::RecalcDistribution() {
  DCHECK(ChildNeedsDistributionRecalc());

  if (IsElementNode()) {
    if (ElementShadow* shadow = ToElement(this)->Shadow())
      shadow->DistributeIfNeeded();
  }

  DCHECK(ScriptForbiddenScope::IsScriptForbidden());
  for (Node* child = firstChild(); child; child = child->nextSibling()) {
    if (child->ChildNeedsDistributionRecalc())
      child->RecalcDistribution();
  }

  for (ShadowRoot* root = YoungestShadowRoot(); root;
       root = root->OlderShadowRoot()) {
    if (root->ChildNeedsDistributionRecalc())
      root->RecalcDistribution();
  }

  ClearChildNeedsDistributionRecalc();
}

void Node::SetIsLink(bool is_link) {
  SetFlag(is_link && !SVGImage::IsInSVGImage(ToElement(this)), kIsLinkFlag);
}

void Node::SetNeedsStyleInvalidation() {
  DCHECK(IsContainerNode());
  SetFlag(kNeedsStyleInvalidationFlag);
  MarkAncestorsWithChildNeedsStyleInvalidation();
}

void Node::MarkAncestorsWithChildNeedsStyleInvalidation() {
  ScriptForbiddenScope forbid_script_during_raw_iteration;
  for (Node* node = ParentOrShadowHostNode();
       node && !node->ChildNeedsStyleInvalidation();
       node = node->ParentOrShadowHostNode())
    node->SetChildNeedsStyleInvalidation();
  GetDocument().ScheduleLayoutTreeUpdateIfNeeded();
}

void Node::MarkAncestorsWithChildNeedsDistributionRecalc() {
  ScriptForbiddenScope forbid_script_during_raw_iteration;
  for (Node* node = this; node && !node->ChildNeedsDistributionRecalc();
       node = node->ParentOrShadowHostNode()) {
    node->SetChildNeedsDistributionRecalc();
  }
  GetDocument().ScheduleLayoutTreeUpdateIfNeeded();
}

inline void Node::SetStyleChange(StyleChangeType change_type) {
  node_flags_ = (node_flags_ & ~kStyleChangeMask) | change_type;
}

void Node::MarkAncestorsWithChildNeedsStyleRecalc() {
  for (ContainerNode* p = ParentOrShadowHostNode();
       p && !p->ChildNeedsStyleRecalc(); p = p->ParentOrShadowHostNode())
    p->SetChildNeedsStyleRecalc();
  GetDocument().ScheduleLayoutTreeUpdateIfNeeded();
}

static ContainerNode* GetReattachParent(Node& node) {
  if (node.IsPseudoElement())
    return node.ParentOrShadowHostNode();
  if (node.IsChildOfV1ShadowHost()) {
    if (HTMLSlotElement* slot = node.FinalDestinationSlot())
      return slot;
  }
  if (node.IsInV0ShadowTree() || node.IsChildOfV0ShadowHost()) {
    if (ShadowWhereNodeCanBeDistributedForV0(node)) {
      if (InsertionPoint* insertion_point =
              const_cast<InsertionPoint*>(ResolveReprojection(&node))) {
        return insertion_point;
      }
    }
  }
  return node.ParentOrShadowHostNode();
}

void Node::MarkAncestorsWithChildNeedsReattachLayoutTree() {
  for (ContainerNode* p = GetReattachParent(*this);
       p && !p->ChildNeedsReattachLayoutTree(); p = GetReattachParent(*p))
    p->SetChildNeedsReattachLayoutTree();
}

void Node::SetNeedsReattachLayoutTree() {
  DCHECK(GetDocument().InStyleRecalc());
  DCHECK(!GetDocument().ChildNeedsDistributionRecalc());
  SetFlag(kNeedsReattachLayoutTree);
  MarkAncestorsWithChildNeedsReattachLayoutTree();
}

void Node::SetNeedsStyleRecalc(StyleChangeType change_type,
                               const StyleChangeReasonForTracing& reason) {
  DCHECK(change_type != kNoStyleChange);
  if (!InActiveDocument())
    return;

  TRACE_EVENT_INSTANT1(
      TRACE_DISABLED_BY_DEFAULT("devtools.timeline.invalidationTracking"),
      "StyleRecalcInvalidationTracking", TRACE_EVENT_SCOPE_THREAD, "data",
      InspectorStyleRecalcInvalidationTrackingEvent::Data(this, reason));

  StyleChangeType existing_change_type = GetStyleChangeType();
  if (change_type > existing_change_type)
    SetStyleChange(change_type);

  if (existing_change_type == kNoStyleChange)
    MarkAncestorsWithChildNeedsStyleRecalc();

  if (IsElementNode() && HasRareData())
    ToElement(*this).SetAnimationStyleChange(false);

  if (IsSVGElement())
    ToSVGElement(this)->SetNeedsStyleRecalcForInstances(change_type, reason);
}

void Node::ClearNeedsStyleRecalc() {
  node_flags_ &= ~kStyleChangeMask;

  if (IsElementNode() && HasRareData())
    ToElement(*this).SetAnimationStyleChange(false);
}

bool Node::InActiveDocument() const {
  return isConnected() && GetDocument().IsActive();
}

Node* Node::FocusDelegate() {
  return this;
}

bool Node::ShouldHaveFocusAppearance() const {
  DCHECK(IsFocused());
  return true;
}

bool Node::IsInert() const {
  if (!isConnected() || !CanParticipateInFlatTree())
    return true;

  DCHECK(!ChildNeedsDistributionRecalc());

  const HTMLDialogElement* dialog = GetDocument().ActiveModalDialog();
  if (dialog && this != GetDocument() &&
      !FlatTreeTraversal::ContainsIncludingPseudoElement(*dialog, *this)) {
    return true;
  }

  if (RuntimeEnabledFeatures::inertAttributeEnabled()) {
    const Element* element = this->IsElementNode()
                                 ? ToElement(this)
                                 : FlatTreeTraversal::ParentElement(*this);
    while (element) {
      if (element->hasAttribute(HTMLNames::inertAttr))
        return true;
      element = FlatTreeTraversal::ParentElement(*element);
    }
  }
  return GetDocument().LocalOwner() && GetDocument().LocalOwner()->IsInert();
}

unsigned Node::NodeIndex() const {
  const Node* temp_node = previousSibling();
  unsigned count = 0;
  for (count = 0; temp_node; count++)
    temp_node = temp_node->previousSibling();
  return count;
}

NodeListsNodeData* Node::NodeLists() {
  return HasRareData() ? RareData()->NodeLists() : nullptr;
}

void Node::ClearNodeLists() {
  RareData()->ClearNodeLists();
}

bool Node::IsDescendantOf(const Node* other) const {
  // Return true if other is an ancestor of this, otherwise false
  if (!other || !other->hasChildren() || isConnected() != other->isConnected())
    return false;
  if (other->GetTreeScope() != GetTreeScope())
    return false;
  if (other->IsTreeScope())
    return !IsTreeScope();
  for (const ContainerNode* n = parentNode(); n; n = n->parentNode()) {
    if (n == other)
      return true;
  }
  return false;
}

bool Node::contains(const Node* node) const {
  if (!node)
    return false;
  return this == node || node->IsDescendantOf(this);
}

bool Node::IsShadowIncludingInclusiveAncestorOf(const Node* node) const {
  if (!node)
    return false;

  if (this == node)
    return true;

  if (GetDocument() != node->GetDocument())
    return false;

  if (isConnected() != node->isConnected())
    return false;

  bool has_children = IsContainerNode() && ToContainerNode(this)->HasChildren();
  bool has_shadow = IsElementNode() && ToElement(this)->Shadow();
  if (!has_children && !has_shadow)
    return false;

  for (; node; node = node->OwnerShadowHost()) {
    if (GetTreeScope() == node->GetTreeScope())
      return contains(node);
  }

  return false;
}

bool Node::ContainsIncludingHostElements(const Node& node) const {
  const Node* current = &node;
  do {
    if (current == this)
      return true;
    if (current->IsDocumentFragment() &&
        ToDocumentFragment(current)->IsTemplateContent())
      current =
          static_cast<const TemplateContentDocumentFragment*>(current)->Host();
    else
      current = current->ParentOrShadowHostNode();
  } while (current);
  return false;
}

Node* Node::CommonAncestor(const Node& other,
                           ContainerNode* (*parent)(const Node&)) const {
  if (this == other)
    return const_cast<Node*>(this);
  if (GetDocument() != other.GetDocument())
    return nullptr;
  int this_depth = 0;
  for (const Node* node = this; node; node = parent(*node)) {
    if (node == &other)
      return const_cast<Node*>(node);
    this_depth++;
  }
  int other_depth = 0;
  for (const Node* node = &other; node; node = parent(*node)) {
    if (node == this)
      return const_cast<Node*>(this);
    other_depth++;
  }
  const Node* this_iterator = this;
  const Node* other_iterator = &other;
  if (this_depth > other_depth) {
    for (int i = this_depth; i > other_depth; --i)
      this_iterator = parent(*this_iterator);
  } else if (other_depth > this_depth) {
    for (int i = other_depth; i > this_depth; --i)
      other_iterator = parent(*other_iterator);
  }
  while (this_iterator) {
    if (this_iterator == other_iterator)
      return const_cast<Node*>(this_iterator);
    this_iterator = parent(*this_iterator);
    other_iterator = parent(*other_iterator);
  }
  DCHECK(!other_iterator);
  return nullptr;
}

void Node::ReattachLayoutTree(const AttachContext& context) {
  AttachContext reattach_context(context);
  reattach_context.performing_reattach = true;

  // We only need to detach if the node has already been through
  // attachLayoutTree().
  if (GetStyleChangeType() < kNeedsReattachStyleChange)
    DetachLayoutTree(reattach_context);
  AttachLayoutTree(reattach_context);
}

void Node::AttachLayoutTree(const AttachContext&) {
  DCHECK(GetDocument().InStyleRecalc() || IsDocumentNode());
  DCHECK(!GetDocument().Lifecycle().InDetach());
  DCHECK(NeedsAttach());
  DCHECK(!GetLayoutObject() ||
         (GetLayoutObject()->Style() &&
          (GetLayoutObject()->Parent() || GetLayoutObject()->IsLayoutView())));

  ClearNeedsStyleRecalc();
  ClearNeedsReattachLayoutTree();

  if (AXObjectCache* cache = GetDocument().AxObjectCache())
    cache->UpdateCacheAfterNodeIsAttached(this);
}

void Node::DetachLayoutTree(const AttachContext& context) {
  DCHECK(GetDocument().Lifecycle().StateAllowsDetach());
  DocumentLifecycle::DetachScope will_detach(GetDocument().Lifecycle());

  if (GetLayoutObject())
    GetLayoutObject()->DestroyAndCleanupAnonymousWrappers();
  SetLayoutObject(nullptr);
  SetStyleChange(kNeedsReattachStyleChange);
  ClearChildNeedsStyleInvalidation();
}

void Node::ReattachWhitespaceSiblingsIfNeeded(Text* start) {
  ScriptForbiddenScope forbid_script_during_raw_iteration;
  for (Node* sibling = start; sibling; sibling = sibling->nextSibling()) {
    if (sibling->IsTextNode() && ToText(sibling)->ContainsOnlyWhitespace()) {
      bool had_layout_object = !!sibling->GetLayoutObject();
      ToText(sibling)->ReattachLayoutTreeIfNeeded();
      // If sibling's layout object status didn't change we don't need to
      // continue checking other siblings since their layout object status won't
      // change either.
      if (!!sibling->GetLayoutObject() == had_layout_object)
        return;
    } else if (sibling->GetLayoutObject()) {
      return;
    }
  }
}

const ComputedStyle* Node::VirtualEnsureComputedStyle(
    PseudoId pseudo_element_specifier) {
  return ParentOrShadowHostNode()
             ? ParentOrShadowHostNode()->EnsureComputedStyle(
                   pseudo_element_specifier)
             : nullptr;
}

int Node::MaxCharacterOffset() const {
  NOTREACHED();
  return 0;
}

// FIXME: Shouldn't these functions be in the editing code?  Code that asks
// questions about HTML in the core DOM class is obviously misplaced.
bool Node::CanStartSelection() const {
  if (HasEditableStyle(*this))
    return true;

  if (GetLayoutObject()) {
    const ComputedStyle& style = GetLayoutObject()->StyleRef();
    // We allow selections to begin within an element that has
    // -webkit-user-select: none set, but if the element is draggable then
    // dragging should take priority over selection.
    if (style.UserDrag() == DRAG_ELEMENT &&
        style.UserSelect() == EUserSelect::kNone)
      return false;
  }
  ContainerNode* parent = FlatTreeTraversal::Parent(*this);
  return parent ? parent->CanStartSelection() : true;
}

// StyledElements allow inline style (style="border: 1px"), presentational
// attributes (ex. color), class names (ex. class="foo bar") and other non-basic
// styling features. They also control if this element can participate in style
// sharing.
//
// FIXME: The only things that ever go through StyleResolver that aren't
// StyledElements are PseudoElements and VTTElements. It's possible we can just
// eliminate all the checks since those elements will never have class names,
// inline style, or other things that this apparently guards against.
bool Node::IsStyledElement() const {
  return IsHTMLElement() || IsSVGElement() ||
         (IsElementNode() &&
          ToElement(this)->namespaceURI() == MathMLNames::mathmlNamespaceURI);
}

bool Node::CanParticipateInFlatTree() const {
  // TODO(hayato): Return false for pseudo elements.
  return !IsShadowRoot() && !IsActiveSlotOrActiveInsertionPoint();
}

bool Node::IsActiveSlotOrActiveInsertionPoint() const {
  return (isHTMLSlotElement(*this) &&
          toHTMLSlotElement(*this).SupportsDistribution()) ||
         IsActiveInsertionPoint(*this);
}

AtomicString Node::SlotName() const {
  DCHECK(IsSlotable());
  if (IsElementNode())
    return HTMLSlotElement::NormalizeSlotName(
        ToElement(*this).FastGetAttribute(HTMLNames::slotAttr));
  DCHECK(IsTextNode());
  return g_empty_atom;
}

bool Node::IsInV1ShadowTree() const {
  ShadowRoot* shadow_root = ContainingShadowRoot();
  return shadow_root && shadow_root->IsV1();
}

bool Node::IsInV0ShadowTree() const {
  ShadowRoot* shadow_root = ContainingShadowRoot();
  return shadow_root && !shadow_root->IsV1();
}

ElementShadow* Node::ParentElementShadow() const {
  Element* parent = parentElement();
  return parent ? parent->Shadow() : nullptr;
}

bool Node::IsChildOfV1ShadowHost() const {
  ElementShadow* parent_shadow = ParentElementShadow();
  return parent_shadow && parent_shadow->IsV1();
}

bool Node::IsChildOfV0ShadowHost() const {
  ElementShadow* parent_shadow = ParentElementShadow();
  return parent_shadow && !parent_shadow->IsV1();
}

ShadowRoot* Node::V1ShadowRootOfParent() const {
  if (Element* parent = parentElement())
    return parent->ShadowRootIfV1();
  return nullptr;
}

Element* Node::OwnerShadowHost() const {
  if (ShadowRoot* root = ContainingShadowRoot())
    return &root->host();
  return nullptr;
}

ShadowRoot* Node::ContainingShadowRoot() const {
  Node& root = GetTreeScope().RootNode();
  return root.IsShadowRoot() ? ToShadowRoot(&root) : nullptr;
}

Node* Node::NonBoundaryShadowTreeRootNode() {
  DCHECK(!IsShadowRoot());
  Node* root = this;
  while (root) {
    if (root->IsShadowRoot())
      return root;
    Node* parent = root->ParentOrShadowHostNode();
    if (parent && parent->IsShadowRoot())
      return root;
    root = parent;
  }
  return nullptr;
}

ContainerNode* Node::NonShadowBoundaryParentNode() const {
  ContainerNode* parent = parentNode();
  return parent && !parent->IsShadowRoot() ? parent : nullptr;
}

Element* Node::ParentOrShadowHostElement() const {
  ContainerNode* parent = ParentOrShadowHostNode();
  if (!parent)
    return nullptr;

  if (parent->IsShadowRoot())
    return &ToShadowRoot(parent)->host();

  if (!parent->IsElementNode())
    return nullptr;

  return ToElement(parent);
}

ContainerNode* Node::ParentOrShadowHostOrTemplateHostNode() const {
  if (IsDocumentFragment() && ToDocumentFragment(this)->IsTemplateContent())
    return static_cast<const TemplateContentDocumentFragment*>(this)->Host();
  return ParentOrShadowHostNode();
}

Document* Node::ownerDocument() const {
  Document* doc = &GetDocument();
  return doc == this ? nullptr : doc;
}

const KURL& Node::baseURI() const {
  return GetDocument().BaseURL();
}

bool Node::isEqualNode(Node* other) const {
  if (!other)
    return false;

  NodeType node_type = this->getNodeType();
  if (node_type != other->getNodeType())
    return false;

  if (nodeValue() != other->nodeValue())
    return false;

  if (IsAttributeNode()) {
    if (ToAttr(this)->localName() != ToAttr(other)->localName())
      return false;

    if (ToAttr(this)->namespaceURI() != ToAttr(other)->namespaceURI())
      return false;
  } else if (IsElementNode()) {
    if (ToElement(this)->TagQName() != ToElement(other)->TagQName())
      return false;

    if (!ToElement(this)->HasEquivalentAttributes(ToElement(other)))
      return false;
  } else if (nodeName() != other->nodeName()) {
    return false;
  }

  Node* child = firstChild();
  Node* other_child = other->firstChild();

  while (child) {
    if (!child->isEqualNode(other_child))
      return false;

    child = child->nextSibling();
    other_child = other_child->nextSibling();
  }

  if (other_child)
    return false;

  if (IsDocumentTypeNode()) {
    const DocumentType* document_type_this = ToDocumentType(this);
    const DocumentType* document_type_other = ToDocumentType(other);

    if (document_type_this->publicId() != document_type_other->publicId())
      return false;

    if (document_type_this->systemId() != document_type_other->systemId())
      return false;
  }

  return true;
}

bool Node::isDefaultNamespace(
    const AtomicString& namespace_uri_maybe_empty) const {
  // https://dom.spec.whatwg.org/#dom-node-isdefaultnamespace

  // 1. If namespace is the empty string, then set it to null.
  const AtomicString& namespace_uri = namespace_uri_maybe_empty.IsEmpty()
                                          ? g_null_atom
                                          : namespace_uri_maybe_empty;

  // 2. Let defaultNamespace be the result of running locate a namespace for
  // context object using null.
  const AtomicString& default_namespace = lookupNamespaceURI(String());

  // 3. Return true if defaultNamespace is the same as namespace, and false
  // otherwise.
  return namespace_uri == default_namespace;
}

const AtomicString& Node::lookupPrefix(
    const AtomicString& namespace_uri) const {
  // Implemented according to
  // https://dom.spec.whatwg.org/#dom-node-lookupprefix

  if (namespace_uri.IsEmpty() || namespace_uri.IsNull())
    return g_null_atom;

  const Element* context;

  switch (getNodeType()) {
    case kElementNode:
      context = ToElement(this);
      break;
    case kDocumentNode:
      context = ToDocument(this)->documentElement();
      break;
    case kDocumentFragmentNode:
    case kDocumentTypeNode:
      context = nullptr;
      break;
    case kAttributeNode:
      context = ToAttr(this)->ownerElement();
      break;
    default:
      context = parentElement();
      break;
  }

  if (!context)
    return g_null_atom;

  return context->LocateNamespacePrefix(namespace_uri);
}

const AtomicString& Node::lookupNamespaceURI(
    const String& specified_prefix) const {
  // Implemented according to
  // https://dom.spec.whatwg.org/#dom-node-lookupnamespaceuri

  // 1. If prefix is the empty string, then set it to null.
  String prefix = specified_prefix;
  if (!specified_prefix.IsNull() && specified_prefix.IsEmpty())
    prefix = String();

  // 2. Return the result of running locate a namespace for the context object
  // using prefix.

  // https://dom.spec.whatwg.org/#locate-a-namespace
  switch (getNodeType()) {
    case kElementNode: {
      const Element& element = ToElement(*this);

      // 1. If its namespace is not null and its namespace prefix is prefix,
      // then return namespace.
      if (!element.namespaceURI().IsNull() && element.prefix() == prefix)
        return element.namespaceURI();

      // 2. If it has an attribute whose namespace is the XMLNS namespace,
      // namespace prefix is "xmlns", and local name is prefix, or if prefix is
      // null and it has an attribute whose namespace is the XMLNS namespace,
      // namespace prefix is null, and local name is "xmlns", then return its
      // value if it is not the empty string, and null otherwise.
      AttributeCollection attributes = element.Attributes();
      for (const Attribute& attr : attributes) {
        if (attr.Prefix() == g_xmlns_atom && attr.LocalName() == prefix) {
          if (!attr.Value().IsEmpty())
            return attr.Value();
          return g_null_atom;
        }
        if (attr.LocalName() == g_xmlns_atom && prefix.IsNull()) {
          if (!attr.Value().IsEmpty())
            return attr.Value();
          return g_null_atom;
        }
      }

      // 3. If its parent element is null, then return null.
      // 4. Return the result of running locate a namespace on its parent
      // element using prefix.
      if (Element* parent = parentElement())
        return parent->lookupNamespaceURI(prefix);
      return g_null_atom;
    }
    case kDocumentNode:
      if (Element* de = ToDocument(this)->documentElement())
        return de->lookupNamespaceURI(prefix);
      return g_null_atom;
    case kDocumentTypeNode:
    case kDocumentFragmentNode:
      return g_null_atom;
    case kAttributeNode: {
      const Attr* attr = ToAttr(this);
      if (attr->ownerElement())
        return attr->ownerElement()->lookupNamespaceURI(prefix);
      return g_null_atom;
    }
    default:
      if (Element* parent = parentElement())
        return parent->lookupNamespaceURI(prefix);
      return g_null_atom;
  }
}

String Node::textContent(bool convert_brs_to_newlines) const {
  // This covers ProcessingInstruction and Comment that should return their
  // value when .textContent is accessed on them, but should be ignored when
  // iterated over as a descendant of a ContainerNode.
  if (IsCharacterDataNode())
    return ToCharacterData(this)->data();

  // Attribute nodes have their attribute values as textContent.
  if (IsAttributeNode())
    return ToAttr(this)->value();

  // Documents and non-container nodes (that are not CharacterData)
  // have null textContent.
  if (IsDocumentNode() || !IsContainerNode())
    return String();

  StringBuilder content;
  for (const Node& node : NodeTraversal::InclusiveDescendantsOf(*this)) {
    if (isHTMLBRElement(node) && convert_brs_to_newlines) {
      content.Append('\n');
    } else if (node.IsTextNode()) {
      content.Append(ToText(node).data());
    }
  }
  return content.ToString();
}

void Node::setTextContent(const String& text) {
  switch (getNodeType()) {
    case kAttributeNode:
    case kTextNode:
    case kCdataSectionNode:
    case kCommentNode:
    case kProcessingInstructionNode:
      setNodeValue(text);
      return;
    case kElementNode:
    case kDocumentFragmentNode: {
      // FIXME: Merge this logic into replaceChildrenWithText.
      ContainerNode* container = ToContainerNode(this);

      // Note: This is an intentional optimization.
      // See crbug.com/352836 also.
      // No need to do anything if the text is identical.
      if (container->HasOneTextChild() &&
          ToText(container->firstChild())->data() == text && !text.IsEmpty())
        return;

      ChildListMutationScope mutation(*this);
      // Note: This API will not insert empty text nodes:
      // https://dom.spec.whatwg.org/#dom-node-textcontent
      if (text.IsEmpty()) {
        container->RemoveChildren(kDispatchSubtreeModifiedEvent);
      } else {
        container->RemoveChildren(kOmitSubtreeModifiedEvent);
        container->AppendChild(GetDocument().createTextNode(text),
                               ASSERT_NO_EXCEPTION);
      }
      return;
    }
    case kDocumentNode:
    case kDocumentTypeNode:
      // Do nothing.
      return;
  }
  NOTREACHED();
}

unsigned short Node::compareDocumentPosition(
    const Node* other_node,
    ShadowTreesTreatment treatment) const {
  if (other_node == this)
    return kDocumentPositionEquivalent;

  const Attr* attr1 = getNodeType() == kAttributeNode ? ToAttr(this) : nullptr;
  const Attr* attr2 = other_node->getNodeType() == kAttributeNode
                          ? ToAttr(other_node)
                          : nullptr;

  const Node* start1 = attr1 ? attr1->ownerElement() : this;
  const Node* start2 = attr2 ? attr2->ownerElement() : other_node;

  // If either of start1 or start2 is null, then we are disconnected, since one
  // of the nodes is an orphaned attribute node.
  if (!start1 || !start2) {
    unsigned short direction = (this > other_node) ? kDocumentPositionPreceding
                                                   : kDocumentPositionFollowing;
    return kDocumentPositionDisconnected |
           kDocumentPositionImplementationSpecific | direction;
  }

  HeapVector<Member<const Node>, 16> chain1;
  HeapVector<Member<const Node>, 16> chain2;
  if (attr1)
    chain1.push_back(attr1);
  if (attr2)
    chain2.push_back(attr2);

  if (attr1 && attr2 && start1 == start2 && start1) {
    // We are comparing two attributes on the same node. Crawl our attribute map
    // and see which one we hit first.
    const Element* owner1 = attr1->ownerElement();
    AttributeCollection attributes = owner1->Attributes();
    for (const Attribute& attr : attributes) {
      // If neither of the two determining nodes is a child node and nodeType is
      // the same for both determining nodes, then an implementation-dependent
      // order between the determining nodes is returned. This order is stable
      // as long as no nodes of the same nodeType are inserted into or removed
      // from the direct container. This would be the case, for example, when
      // comparing two attributes of the same element, and inserting or removing
      // additional attributes might change the order between existing
      // attributes.
      if (attr1->GetQualifiedName() == attr.GetName())
        return kDocumentPositionImplementationSpecific |
               kDocumentPositionFollowing;
      if (attr2->GetQualifiedName() == attr.GetName())
        return kDocumentPositionImplementationSpecific |
               kDocumentPositionPreceding;
    }

    NOTREACHED();
    return kDocumentPositionDisconnected;
  }

  // If one node is in the document and the other is not, we must be
  // disconnected.  If the nodes have different owning documents, they must be
  // disconnected.  Note that we avoid comparing Attr nodes here, since they
  // return false from isConnected() all the time (which seems like a bug).
  if (start1->isConnected() != start2->isConnected() ||
      (treatment == kTreatShadowTreesAsDisconnected &&
       start1->GetTreeScope() != start2->GetTreeScope())) {
    unsigned short direction = (this > other_node) ? kDocumentPositionPreceding
                                                   : kDocumentPositionFollowing;
    return kDocumentPositionDisconnected |
           kDocumentPositionImplementationSpecific | direction;
  }

  // We need to find a common ancestor container, and then compare the indices
  // of the two immediate children.
  const Node* current;
  for (current = start1; current; current = current->ParentOrShadowHostNode())
    chain1.push_back(current);
  for (current = start2; current; current = current->ParentOrShadowHostNode())
    chain2.push_back(current);

  unsigned index1 = chain1.size();
  unsigned index2 = chain2.size();

  // If the two elements don't have a common root, they're not in the same tree.
  if (chain1[index1 - 1] != chain2[index2 - 1]) {
    unsigned short direction = (this > other_node) ? kDocumentPositionPreceding
                                                   : kDocumentPositionFollowing;
    return kDocumentPositionDisconnected |
           kDocumentPositionImplementationSpecific | direction;
  }

  unsigned connection = start1->GetTreeScope() != start2->GetTreeScope()
                            ? kDocumentPositionDisconnected |
                                  kDocumentPositionImplementationSpecific
                            : 0;

  // Walk the two chains backwards and look for the first difference.
  for (unsigned i = std::min(index1, index2); i; --i) {
    const Node* child1 = chain1[--index1];
    const Node* child2 = chain2[--index2];
    if (child1 != child2) {
      // If one of the children is an attribute, it wins.
      if (child1->getNodeType() == kAttributeNode)
        return kDocumentPositionFollowing | connection;
      if (child2->getNodeType() == kAttributeNode)
        return kDocumentPositionPreceding | connection;

      // If one of the children is a shadow root,
      if (child1->IsShadowRoot() || child2->IsShadowRoot()) {
        if (!child2->IsShadowRoot())
          return Node::kDocumentPositionFollowing | connection;
        if (!child1->IsShadowRoot())
          return Node::kDocumentPositionPreceding | connection;

        for (const ShadowRoot* child = ToShadowRoot(child2)->OlderShadowRoot();
             child; child = child->OlderShadowRoot()) {
          if (child == child1) {
            return Node::kDocumentPositionFollowing | connection;
          }
        }

        return Node::kDocumentPositionPreceding | connection;
      }

      if (!child2->nextSibling())
        return kDocumentPositionFollowing | connection;
      if (!child1->nextSibling())
        return kDocumentPositionPreceding | connection;

      // Otherwise we need to see which node occurs first.  Crawl backwards from
      // child2 looking for child1.
      for (const Node* child = child2->previousSibling(); child;
           child = child->previousSibling()) {
        if (child == child1)
          return kDocumentPositionFollowing | connection;
      }
      return kDocumentPositionPreceding | connection;
    }
  }

  // There was no difference between the two parent chains, i.e., one was a
  // subset of the other.  The shorter chain is the ancestor.
  return index1 < index2 ? kDocumentPositionFollowing |
                               kDocumentPositionContainedBy | connection
                         : kDocumentPositionPreceding |
                               kDocumentPositionContains | connection;
}

String Node::DebugName() const {
  StringBuilder name;
  AppendUnsafe(name, DebugNodeName());
  if (IsElementNode()) {
    const Element& this_element = ToElement(*this);
    if (this_element.HasID()) {
      name.Append(" id=\'");
      AppendUnsafe(name, this_element.GetIdAttribute());
      name.Append('\'');
    }

    if (this_element.HasClass()) {
      name.Append(" class=\'");
      for (size_t i = 0; i < this_element.ClassNames().size(); ++i) {
        if (i > 0)
          name.Append(' ');
        AppendUnsafe(name, this_element.ClassNames()[i]);
      }
      name.Append('\'');
    }
  }
  return name.ToString();
}

String Node::DebugNodeName() const {
  return nodeName();
}

static void DumpAttributeDesc(const Node& node,
                              const QualifiedName& name,
                              std::ostream& ostream) {
  if (!node.IsElementNode())
    return;
  const AtomicString& value = ToElement(node).getAttribute(name);
  if (value.IsEmpty())
    return;
  ostream << ' ' << name.ToString().Utf8().data() << '=' << value;
}

std::ostream& operator<<(std::ostream& ostream, const Node& node) {
  if (node.getNodeType() == Node::kProcessingInstructionNode)
    return ostream << "?" << node.nodeName().Utf8().data();
  if (node.IsShadowRoot()) {
    // nodeName of ShadowRoot is #document-fragment.  It's confused with
    // DocumentFragment.
    return ostream << "#shadow-root";
  }
  if (node.IsDocumentTypeNode())
    return ostream << "DOCTYPE " << node.nodeName().Utf8().data();

  // We avoid to print "" by utf8().data().
  ostream << node.nodeName().Utf8().data();
  if (node.IsTextNode())
    return ostream << " " << node.nodeValue();
  DumpAttributeDesc(node, HTMLNames::idAttr, ostream);
  DumpAttributeDesc(node, HTMLNames::classAttr, ostream);
  DumpAttributeDesc(node, HTMLNames::styleAttr, ostream);
  if (HasEditableStyle(node))
    ostream << " (editable)";
  if (node.GetDocument().FocusedElement() == &node)
    ostream << " (focused)";
  return ostream;
}

std::ostream& operator<<(std::ostream& ostream, const Node* node) {
  if (!node)
    return ostream << "null";
  return ostream << *node;
}

#ifndef NDEBUG

String Node::ToString() const {
  // TODO(tkent): We implemented toString() with operator<<.  We should
  // implement operator<< with toString() instead.
  std::stringstream stream;
  stream << *this;
  return String(stream.str().c_str());
}

String Node::ToTreeStringForThis() const {
  return ToMarkedTreeString(this, "*");
}

String Node::ToFlatTreeStringForThis() const {
  return ToMarkedFlatTreeString(this, "*");
}

void Node::PrintNodePathTo(std::ostream& stream) const {
  HeapVector<Member<const Node>, 16> chain;
  const Node* node = this;
  while (node->ParentOrShadowHostNode()) {
    chain.push_back(node);
    node = node->ParentOrShadowHostNode();
  }
  for (unsigned index = chain.size(); index > 0; --index) {
    const Node* node = chain[index - 1];
    if (node->IsShadowRoot()) {
      int count = 0;
      for (const ShadowRoot* shadow_root =
               ToShadowRoot(node)->OlderShadowRoot();
           shadow_root; shadow_root = shadow_root->OlderShadowRoot())
        ++count;
      stream << "/#shadow-root[" << count << "]";
      continue;
    }

    switch (node->getNodeType()) {
      case kElementNode: {
        stream << "/" << node->nodeName().Utf8().data();

        const Element* element = ToElement(node);
        const AtomicString& idattr = element->GetIdAttribute();
        bool has_id_attr = !idattr.IsNull() && !idattr.IsEmpty();
        if (node->previousSibling() || node->nextSibling()) {
          int count = 0;
          for (const Node* previous = node->previousSibling(); previous;
               previous = previous->previousSibling()) {
            if (previous->nodeName() == node->nodeName()) {
              ++count;
            }
          }
          if (has_id_attr)
            stream << "[@id=\"" << idattr.Utf8().data()
                   << "\" and position()=" << count << "]";
          else
            stream << "[" << count << "]";
        } else if (has_id_attr) {
          stream << "[@id=\"" << idattr.Utf8().data() << "\"]";
        }
        break;
      }
      case kTextNode:
        stream << "/text()";
        break;
      case kAttributeNode:
        stream << "/@" << node->nodeName().Utf8().data();
        break;
      default:
        break;
    }
  }
}

static void 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) {
  for (const Node& node : NodeTraversal::InclusiveDescendantsOf(*root_node)) {
    StringBuilder indent;
    if (node == marked_node1)
      indent.Append(marked_label1);
    if (node == marked_node2)
      indent.Append(marked_label2);
    indent.Append(base_indent);
    for (const Node* tmp_node = &node; tmp_node && tmp_node != root_node;
         tmp_node = tmp_node->ParentOrShadowHostNode())
      indent.Append('\t');
    builder.Append(indent);
    builder.Append(node.ToString());
    builder.Append("\n");
    indent.Append('\t');

    if (node.IsElementNode()) {
      const Element& element = ToElement(node);
      if (Element* pseudo = element.GetPseudoElement(kPseudoIdBefore))
        AppendMarkedTree(indent.ToString(), pseudo, marked_node1, marked_label1,
                         marked_node2, marked_label2, builder);
      if (Element* pseudo = element.GetPseudoElement(kPseudoIdAfter))
        AppendMarkedTree(indent.ToString(), pseudo, marked_node1, marked_label1,
                         marked_node2, marked_label2, builder);
      if (Element* pseudo = element.GetPseudoElement(kPseudoIdFirstLetter))
        AppendMarkedTree(indent.ToString(), pseudo, marked_node1, marked_label1,
                         marked_node2, marked_label2, builder);
      if (Element* pseudo = element.GetPseudoElement(kPseudoIdBackdrop))
        AppendMarkedTree(indent.ToString(), pseudo, marked_node1, marked_label1,
                         marked_node2, marked_label2, builder);
    }

    if (node.IsShadowRoot()) {
      if (ShadowRoot* younger_shadow_root =
              ToShadowRoot(node).YoungerShadowRoot())
        AppendMarkedTree(indent.ToString(), younger_shadow_root, marked_node1,
                         marked_label1, marked_node2, marked_label2, builder);
    } else if (ShadowRoot* oldest_shadow_root = OldestShadowRootFor(&node)) {
      AppendMarkedTree(indent.ToString(), oldest_shadow_root, marked_node1,
                       marked_label1, marked_node2, marked_label2, builder);
    }
  }
}

static void 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) {
  for (const Node* node = root_node; node;
       node = FlatTreeTraversal::NextSibling(*node)) {
    StringBuilder indent;
    if (node == marked_node1)
      indent.Append(marked_label1);
    if (node == marked_node2)
      indent.Append(marked_label2);
    indent.Append(base_indent);
    builder.Append(indent);
    builder.Append(node->ToString());
    builder.Append("\n");
    indent.Append('\t');

    if (Node* child = FlatTreeTraversal::FirstChild(*node))
      AppendMarkedFlatTree(indent.ToString(), child, marked_node1,
                           marked_label1, marked_node2, marked_label2, builder);
  }
}

String Node::ToMarkedTreeString(const Node* marked_node1,
                                const char* marked_label1,
                                const Node* marked_node2,
                                const char* marked_label2) const {
  const Node* root_node;
  const Node* node = this;
  while (node->ParentOrShadowHostNode() && !isHTMLBodyElement(*node))
    node = node->ParentOrShadowHostNode();
  root_node = node;

  StringBuilder builder;
  String starting_indent;
  AppendMarkedTree(starting_indent, root_node, marked_node1, marked_label1,
                   marked_node2, marked_label2, builder);
  return builder.ToString();
}

String Node::ToMarkedFlatTreeString(const Node* marked_node1,
                                    const char* marked_label1,
                                    const Node* marked_node2,
                                    const char* marked_label2) const {
  const Node* root_node;
  const Node* node = this;
  while (node->ParentOrShadowHostNode() && !isHTMLBodyElement(*node))
    node = node->ParentOrShadowHostNode();
  root_node = node;

  StringBuilder builder;
  String starting_indent;
  AppendMarkedFlatTree(starting_indent, root_node, marked_node1, marked_label1,
                       marked_node2, marked_label2, builder);
  return builder.ToString();
}

static ContainerNode* ParentOrShadowHostOrFrameOwner(const Node* node) {
  ContainerNode* parent = node->ParentOrShadowHostNode();
  if (!parent && node->GetDocument().GetFrame())
    parent = node->GetDocument().GetFrame()->DeprecatedLocalOwner();
  return parent;
}

static void PrintSubTreeAcrossFrame(const Node* node,
                                    const Node* marked_node,
                                    const String& indent,
                                    std::ostream& stream) {
  if (node == marked_node)
    stream << "*";
  stream << indent.Utf8().data() << *node << "\n";
  if (node->IsShadowRoot()) {
    if (ShadowRoot* younger_shadow_root =
            ToShadowRoot(node)->YoungerShadowRoot())
      PrintSubTreeAcrossFrame(younger_shadow_root, marked_node, indent + "\t",
                              stream);
  } else {
    if (node->IsFrameOwnerElement())
      PrintSubTreeAcrossFrame(ToHTMLFrameOwnerElement(node)->contentDocument(),
                              marked_node, indent + "\t", stream);
    if (ShadowRoot* oldest_shadow_root = OldestShadowRootFor(node))
      PrintSubTreeAcrossFrame(oldest_shadow_root, marked_node, indent + "\t",
                              stream);
  }
  for (const Node* child = node->firstChild(); child;
       child = child->nextSibling())
    PrintSubTreeAcrossFrame(child, marked_node, indent + "\t", stream);
}

void Node::ShowTreeForThisAcrossFrame() const {
  const Node* root_node = this;
  while (ParentOrShadowHostOrFrameOwner(root_node))
    root_node = ParentOrShadowHostOrFrameOwner(root_node);
  std::stringstream stream;
  PrintSubTreeAcrossFrame(root_node, this, "", stream);
  LOG(INFO) << "\n" << stream.str();
}

#endif

// --------

Element* Node::EnclosingLinkEventParentOrSelf() const {
  const Node* result = nullptr;
  for (const Node* node = this; node; node = FlatTreeTraversal::Parent(*node)) {
    // For imagemaps, the enclosing link node is the associated area element not
    // the image itself.  So we don't let images be the enclosingLinkNode, even
    // though isLink sometimes returns true for them.
    if (node->IsLink() && !isHTMLImageElement(*node)) {
      // Casting to Element is safe because only HTMLAnchorElement,
      // HTMLImageElement and SVGAElement can return true for isLink().
      result = node;
      break;
    }
  }

  return ToElement(const_cast<Node*>(result));
}

const AtomicString& Node::InterfaceName() const {
  return EventTargetNames::Node;
}

ExecutionContext* Node::GetExecutionContext() const {
  return GetDocument().ContextDocument();
}

void Node::WillMoveToNewDocument(Document& old_document,
                                 Document& new_document) {
  if (!old_document.GetPage() ||
      old_document.GetPage() == new_document.GetPage())
    return;

  old_document.GetPage()->GetEventHandlerRegistry().DidMoveOutOfPage(*this);
}

void Node::DidMoveToNewDocument(Document& old_document) {
  TreeScopeAdopter::EnsureDidMoveToNewDocumentWasCalled(old_document);

  if (const EventTargetData* event_target_data = this->GetEventTargetData()) {
    const EventListenerMap& listener_map =
        event_target_data->event_listener_map;
    if (!listener_map.IsEmpty()) {
      for (const auto& type : listener_map.EventTypes())
        GetDocument().AddListenerTypeIfNeeded(type, *this);
    }
  }

  old_document.Markers().RemoveMarkersForNode(this);
  if (GetDocument().GetPage() &&
      GetDocument().GetPage() != old_document.GetPage()) {
    GetDocument().GetPage()->GetEventHandlerRegistry().DidMoveIntoPage(*this);
  }

  if (const HeapVector<TraceWrapperMember<MutationObserverRegistration>>*
          registry = MutationObserverRegistry()) {
    for (const auto& registration : *registry) {
      GetDocument().AddMutationObserverTypes(registration->MutationTypes());
    }
  }

  if (TransientMutationObserverRegistry()) {
    for (MutationObserverRegistration* registration :
         *TransientMutationObserverRegistry())
      GetDocument().AddMutationObserverTypes(registration->MutationTypes());
  }
}

void Node::AddedEventListener(const AtomicString& event_type,
                              RegisteredEventListener& registered_listener) {
  EventTarget::AddedEventListener(event_type, registered_listener);
  GetDocument().AddListenerTypeIfNeeded(event_type, *this);
  if (Page* page = GetDocument().GetPage())
    page->GetEventHandlerRegistry().DidAddEventHandler(
        *this, event_type, registered_listener.Options());
}

void Node::RemovedEventListener(
    const AtomicString& event_type,
    const RegisteredEventListener& registered_listener) {
  EventTarget::RemovedEventListener(event_type, registered_listener);
  // FIXME: Notify Document that the listener has vanished. We need to keep
  // track of a number of listeners for each type, not just a bool - see
  // https://bugs.webkit.org/show_bug.cgi?id=33861
  if (Page* page = GetDocument().GetPage())
    page->GetEventHandlerRegistry().DidRemoveEventHandler(
        *this, event_type, registered_listener.Options());
}

void Node::RemoveAllEventListeners() {
  if (HasEventListeners() && GetDocument().GetPage())
    GetDocument()
        .GetPage()
        ->GetEventHandlerRegistry()
        .DidRemoveAllEventHandlers(*this);
  EventTarget::RemoveAllEventListeners();
}

void Node::RemoveAllEventListenersRecursively() {
  ScriptForbiddenScope forbid_script_during_raw_iteration;
  for (Node& node : NodeTraversal::StartsAt(*this)) {
    node.RemoveAllEventListeners();
    for (ShadowRoot* root = node.YoungestShadowRoot(); root;
         root = root->OlderShadowRoot())
      root->RemoveAllEventListenersRecursively();
  }
}

using EventTargetDataMap =
    PersistentHeapHashMap<WeakMember<Node>, Member<EventTargetData>>;
static EventTargetDataMap& GetEventTargetDataMap() {
  DEFINE_STATIC_LOCAL(EventTargetDataMap, map, ());
  return map;
}

EventTargetData* Node::GetEventTargetData() {
  return HasEventTargetData() ? GetEventTargetDataMap().at(this) : nullptr;
}

EventTargetData& Node::EnsureEventTargetData() {
  if (HasEventTargetData())
    return *GetEventTargetDataMap().at(this);
  DCHECK(!GetEventTargetDataMap().Contains(this));
  SetHasEventTargetData(true);
  EventTargetData* data = new EventTargetData;
  GetEventTargetDataMap().Set(this, data);
  return *data;
}

const HeapVector<TraceWrapperMember<MutationObserverRegistration>>*
Node::MutationObserverRegistry() {
  if (!HasRareData())
    return nullptr;
  NodeMutationObserverData* data = RareData()->MutationObserverData();
  if (!data)
    return nullptr;
  return &data->Registry();
}

const HeapHashSet<TraceWrapperMember<MutationObserverRegistration>>*
Node::TransientMutationObserverRegistry() {
  if (!HasRareData())
    return nullptr;
  NodeMutationObserverData* data = RareData()->MutationObserverData();
  if (!data)
    return nullptr;
  return &data->TransientRegistry();
}

template <typename Registry>
static inline void CollectMatchingObserversForMutation(
    HeapHashMap<Member<MutationObserver>, MutationRecordDeliveryOptions>&
        observers,
    Registry* registry,
    Node& target,
    MutationObserver::MutationType type,
    const QualifiedName* attribute_name) {
  if (!registry)
    return;

  for (const auto& registration : *registry) {
    if (registration->ShouldReceiveMutationFrom(target, type, attribute_name)) {
      MutationRecordDeliveryOptions delivery_options =
          registration->DeliveryOptions();
      HeapHashMap<Member<MutationObserver>,
                  MutationRecordDeliveryOptions>::AddResult result =
          observers.insert(&registration->Observer(), delivery_options);
      if (!result.is_new_entry)
        result.stored_value->value |= delivery_options;
    }
  }
}

void Node::GetRegisteredMutationObserversOfType(
    HeapHashMap<Member<MutationObserver>, MutationRecordDeliveryOptions>&
        observers,
    MutationObserver::MutationType type,
    const QualifiedName* attribute_name) {
  DCHECK((type == MutationObserver::kAttributes && attribute_name) ||
         !attribute_name);
  CollectMatchingObserversForMutation(observers, MutationObserverRegistry(),
                                      *this, type, attribute_name);
  CollectMatchingObserversForMutation(observers,
                                      TransientMutationObserverRegistry(),
                                      *this, type, attribute_name);
  ScriptForbiddenScope forbid_script_during_raw_iteration;
  for (Node* node = parentNode(); node; node = node->parentNode()) {
    CollectMatchingObserversForMutation(observers,
                                        node->MutationObserverRegistry(), *this,
                                        type, attribute_name);
    CollectMatchingObserversForMutation(
        observers, node->TransientMutationObserverRegistry(), *this, type,
        attribute_name);
  }
}

void Node::RegisterMutationObserver(
    MutationObserver& observer,
    MutationObserverOptions options,
    const HashSet<AtomicString>& attribute_filter) {
  MutationObserverRegistration* registration = nullptr;
  for (const auto& item :
       EnsureRareData().EnsureMutationObserverData().Registry()) {
    if (&item->Observer() == &observer) {
      registration = item.Get();
      registration->ResetObservation(options, attribute_filter);
    }
  }

  if (!registration) {
    registration = MutationObserverRegistration::Create(observer, this, options,
                                                        attribute_filter);
    EnsureRareData().EnsureMutationObserverData().AddRegistration(registration);
  }

  GetDocument().AddMutationObserverTypes(registration->MutationTypes());
}

void Node::UnregisterMutationObserver(
    MutationObserverRegistration* registration) {
  const HeapVector<TraceWrapperMember<MutationObserverRegistration>>* registry =
      MutationObserverRegistry();
  DCHECK(registry);
  if (!registry)
    return;

  // FIXME: Simplify the registration/transient registration logic to make this
  // understandable by humans.  The explicit dispose() is needed to have the
  // registration object unregister itself promptly.
  registration->Dispose();
  EnsureRareData().EnsureMutationObserverData().RemoveRegistration(
      registration);
}

void Node::RegisterTransientMutationObserver(
    MutationObserverRegistration* registration) {
  EnsureRareData().EnsureMutationObserverData().AddTransientRegistration(
      registration);
}

void Node::UnregisterTransientMutationObserver(
    MutationObserverRegistration* registration) {
  const HeapHashSet<TraceWrapperMember<MutationObserverRegistration>>*
      transient_registry = TransientMutationObserverRegistry();
  DCHECK(transient_registry);
  if (!transient_registry)
    return;

  EnsureRareData().EnsureMutationObserverData().RemoveTransientRegistration(
      registration);
}

void Node::NotifyMutationObserversNodeWillDetach() {
  if (!GetDocument().HasMutationObservers())
    return;

  ScriptForbiddenScope forbid_script_during_raw_iteration;
  for (Node* node = parentNode(); node; node = node->parentNode()) {
    if (const HeapVector<TraceWrapperMember<MutationObserverRegistration>>*
            registry = node->MutationObserverRegistry()) {
      for (const auto& registration : *registry)
        registration->ObservedSubtreeNodeWillDetach(*this);
    }

    if (const HeapHashSet<TraceWrapperMember<MutationObserverRegistration>>*
            transient_registry = node->TransientMutationObserverRegistry()) {
      for (auto& registration : *transient_registry)
        registration->ObservedSubtreeNodeWillDetach(*this);
    }
  }
}

void Node::HandleLocalEvents(Event& event) {
  if (!HasEventTargetData())
    return;

  if (IsDisabledFormControl(this) && event.IsMouseEvent() &&
      !RuntimeEnabledFeatures::sendMouseEventsDisabledFormControlsEnabled()) {
    UseCounter::Count(GetDocument(),
                      UseCounter::kDispatchMouseEventOnDisabledFormControl);
    return;
  }

  FireEventListeners(&event);
}

void Node::DispatchScopedEvent(Event* event) {
  event->SetTrusted(true);
  EventDispatcher::DispatchScopedEvent(*this, event->CreateMediator());
}

DispatchEventResult Node::DispatchEventInternal(Event* event) {
  return EventDispatcher::DispatchEvent(*this, event->CreateMediator());
}

void Node::DispatchSubtreeModifiedEvent() {
  if (IsInShadowTree())
    return;

#if DCHECK_IS_ON()
  DCHECK(!EventDispatchForbiddenScope::IsEventDispatchForbidden());
#endif

  if (!GetDocument().HasListenerType(Document::kDOMSubtreeModifiedListener))
    return;

  DispatchScopedEvent(
      MutationEvent::Create(EventTypeNames::DOMSubtreeModified, true));
}

DispatchEventResult Node::DispatchDOMActivateEvent(int detail,
                                                   Event& underlying_event) {
#if DCHECK_IS_ON()
  DCHECK(!EventDispatchForbiddenScope::IsEventDispatchForbidden());
#endif
  UIEvent* event = UIEvent::Create();
  event->initUIEvent(EventTypeNames::DOMActivate, true, true,
                     GetDocument().domWindow(), detail);
  event->SetUnderlyingEvent(&underlying_event);
  event->SetComposed(underlying_event.composed());
  DispatchScopedEvent(event);

  // TODO(dtapuska): Dispatching scoped events shouldn't check the return
  // type because the scoped event could get put off in the delayed queue.
  return EventTarget::GetDispatchEventResult(*event);
}

void Node::CreateAndDispatchPointerEvent(const AtomicString& mouse_event_name,
                                         const WebMouseEvent& mouse_event,
                                         LocalDOMWindow* view) {
  AtomicString pointer_event_name;
  if (mouse_event_name == EventTypeNames::mousemove)
    pointer_event_name = EventTypeNames::pointermove;
  else if (mouse_event_name == EventTypeNames::mousedown)
    pointer_event_name = EventTypeNames::pointerdown;
  else if (mouse_event_name == EventTypeNames::mouseup)
    pointer_event_name = EventTypeNames::pointerup;
  else
    return;

  PointerEventInit pointer_event_init;

  pointer_event_init.setPointerId(PointerEventFactory::kMouseId);
  pointer_event_init.setPointerType("mouse");
  pointer_event_init.setIsPrimary(true);
  pointer_event_init.setButtons(
      MouseEvent::WebInputEventModifiersToButtons(mouse_event.GetModifiers()));

  pointer_event_init.setBubbles(true);
  pointer_event_init.setCancelable(true);
  pointer_event_init.setComposed(true);
  pointer_event_init.setDetail(0);

  pointer_event_init.setScreenX(mouse_event.PositionInScreen().x);
  pointer_event_init.setScreenY(mouse_event.PositionInScreen().y);

  IntPoint location_in_frame_zoomed;
  if (view && view->GetFrame() && view->GetFrame()->View()) {
    LocalFrame* frame = view->GetFrame();
    FrameView* frame_view = frame->View();
    IntPoint location_in_contents = frame_view->RootFrameToContents(
        FlooredIntPoint(mouse_event.PositionInRootFrame()));
    location_in_frame_zoomed =
        frame_view->ContentsToFrame(location_in_contents);
    float scale_factor = 1 / frame->PageZoomFactor();
    location_in_frame_zoomed.Scale(scale_factor, scale_factor);
  }

  // Set up initial values for coordinates.
  pointer_event_init.setClientX(location_in_frame_zoomed.X());
  pointer_event_init.setClientY(location_in_frame_zoomed.Y());

  if (pointer_event_name == EventTypeNames::pointerdown ||
      pointer_event_name == EventTypeNames::pointerup) {
    pointer_event_init.setButton(static_cast<int>(mouse_event.button));
  } else {
    pointer_event_init.setButton(
        static_cast<int>(WebPointerProperties::Button::kNoButton));
  }

  UIEventWithKeyState::SetFromWebInputEventModifiers(
      pointer_event_init,
      static_cast<WebInputEvent::Modifiers>(mouse_event.GetModifiers()));
  pointer_event_init.setView(view);

  DispatchEvent(PointerEvent::Create(pointer_event_name, pointer_event_init));
}

void Node::DispatchMouseEvent(const WebMouseEvent& native_event,
                              const AtomicString& mouse_event_type,
                              int detail,
                              const String& canvas_region_id,
                              Node* related_target) {
  CreateAndDispatchPointerEvent(mouse_event_type, native_event,
                                GetDocument().domWindow());
  DispatchEvent(MouseEvent::Create(mouse_event_type, GetDocument().domWindow(),
                                   native_event, detail, canvas_region_id,
                                   related_target));
}

void Node::DispatchSimulatedClick(Event* underlying_event,
                                  SimulatedClickMouseEventOptions event_options,
                                  SimulatedClickCreationScope scope) {
  EventDispatcher::DispatchSimulatedClick(*this, underlying_event,
                                          event_options, scope);
}

void Node::DispatchInputEvent() {
  // Legacy 'input' event for forms set value and checked.
  DispatchScopedEvent(Event::CreateBubble(EventTypeNames::input));
}

void Node::DefaultEventHandler(Event* event) {
  if (event->target() != this)
    return;
  const AtomicString& event_type = event->type();
  if (event_type == EventTypeNames::keydown ||
      event_type == EventTypeNames::keypress) {
    if (event->IsKeyboardEvent()) {
      if (LocalFrame* frame = GetDocument().GetFrame())
        frame->GetEventHandler().DefaultKeyboardEventHandler(
            ToKeyboardEvent(event));
    }
  } else if (event_type == EventTypeNames::click) {
    int detail =
        event->IsUIEvent() ? static_cast<UIEvent*>(event)->detail() : 0;
    if (DispatchDOMActivateEvent(detail, *event) !=
        DispatchEventResult::kNotCanceled)
      event->SetDefaultHandled();
  } else if (event_type == EventTypeNames::contextmenu) {
    if (Page* page = GetDocument().GetPage())
      page->GetContextMenuController().HandleContextMenuEvent(event);
  } else if (event_type == EventTypeNames::textInput) {
    if (event->HasInterface(EventNames::TextEvent)) {
      if (LocalFrame* frame = GetDocument().GetFrame())
        frame->GetEventHandler().DefaultTextInputEventHandler(
            ToTextEvent(event));
    }
  } else if (RuntimeEnabledFeatures::middleClickAutoscrollEnabled() &&
             event_type == EventTypeNames::mousedown && event->IsMouseEvent()) {
    MouseEvent* mouse_event = ToMouseEvent(event);
    if (mouse_event->button() ==
        static_cast<short>(WebPointerProperties::Button::kMiddle)) {
      if (EnclosingLinkEventParentOrSelf())
        return;

      // Avoid that canBeScrolledAndHasScrollableArea changes layout tree
      // structure.
      // FIXME: We should avoid synchronous layout if possible. We can
      // remove this synchronous layout if we avoid synchronous layout in
      // LayoutTextControlSingleLine::scrollHeight
      GetDocument().UpdateStyleAndLayoutIgnorePendingStylesheets();
      LayoutObject* layout_object = this->GetLayoutObject();
      while (
          layout_object &&
          (!layout_object->IsBox() ||
           !ToLayoutBox(layout_object)->CanBeScrolledAndHasScrollableArea())) {
        if (layout_object->GetNode() &&
            layout_object->GetNode()->IsDocumentNode()) {
          Element* owner = ToDocument(layout_object->GetNode())->LocalOwner();
          layout_object = owner ? owner->GetLayoutObject() : nullptr;
        } else {
          layout_object = layout_object->Parent();
        }
      }
      if (layout_object) {
        if (LocalFrame* frame = GetDocument().GetFrame())
          frame->GetEventHandler().StartMiddleClickAutoscroll(layout_object);
      }
    }
  } else if (event->type() == EventTypeNames::webkitEditableContentChanged) {
    // TODO(chongz): Remove after shipped.
    // New InputEvent are dispatched in Editor::appliedEditing, etc.
    if (!RuntimeEnabledFeatures::inputEventEnabled())
      DispatchInputEvent();
  }
}

void Node::WillCallDefaultEventHandler(const Event&) {}

bool Node::WillRespondToMouseMoveEvents() {
  if (IsDisabledFormControl(this))
    return false;
  return HasEventListeners(EventTypeNames::mousemove) ||
         HasEventListeners(EventTypeNames::mouseover) ||
         HasEventListeners(EventTypeNames::mouseout);
}

bool Node::WillRespondToMouseClickEvents() {
  if (IsDisabledFormControl(this))
    return false;
  GetDocument().UpdateStyleAndLayoutTree();
  return HasEditableStyle(*this) ||
         HasEventListeners(EventTypeNames::mouseup) ||
         HasEventListeners(EventTypeNames::mousedown) ||
         HasEventListeners(EventTypeNames::click) ||
         HasEventListeners(EventTypeNames::DOMActivate);
}

bool Node::WillRespondToTouchEvents() {
  if (IsDisabledFormControl(this))
    return false;
  return HasEventListeners(EventTypeNames::touchstart) ||
         HasEventListeners(EventTypeNames::touchmove) ||
         HasEventListeners(EventTypeNames::touchcancel) ||
         HasEventListeners(EventTypeNames::touchend);
}

unsigned Node::ConnectedSubframeCount() const {
  return HasRareData() ? RareData()->ConnectedSubframeCount() : 0;
}

void Node::IncrementConnectedSubframeCount() {
  DCHECK(IsContainerNode());
  EnsureRareData().IncrementConnectedSubframeCount();
}

void Node::DecrementConnectedSubframeCount() {
  RareData()->DecrementConnectedSubframeCount();
}

StaticNodeList* Node::getDestinationInsertionPoints() {
  UpdateDistribution();
  HeapVector<Member<InsertionPoint>, 8> insertion_points;
  CollectDestinationInsertionPoints(*this, insertion_points);
  HeapVector<Member<Node>> filtered_insertion_points;
  for (const auto& insertion_point : insertion_points) {
    DCHECK(insertion_point->ContainingShadowRoot());
    if (!insertion_point->ContainingShadowRoot()->IsOpenOrV0())
      break;
    filtered_insertion_points.push_back(insertion_point);
  }
  return StaticNodeList::Adopt(filtered_insertion_points);
}

HTMLSlotElement* Node::AssignedSlot() const {
  // assignedSlot doesn't need to call updateDistribution().
  DCHECK(!IsPseudoElement());
  if (ShadowRoot* root = V1ShadowRootOfParent())
    return root->AssignedSlotFor(*this);
  return nullptr;
}

HTMLSlotElement* Node::FinalDestinationSlot() const {
  HTMLSlotElement* slot = AssignedSlot();
  if (!slot)
    return nullptr;
  for (HTMLSlotElement* next = slot->AssignedSlot(); next;
       next = next->AssignedSlot()) {
    slot = next;
  }
  return slot;
}

HTMLSlotElement* Node::assignedSlotForBinding() {
  // assignedSlot doesn't need to call updateDistribution().
  if (ShadowRoot* root = V1ShadowRootOfParent()) {
    if (root->GetType() == ShadowRootType::kOpen)
      return root->AssignedSlotFor(*this);
  }
  return nullptr;
}

void Node::SetFocused(bool flag, WebFocusType focus_type) {
  GetDocument().UserActionElements().SetFocused(this, flag);
}

void Node::SetHasFocusWithin(bool flag) {
  GetDocument().UserActionElements().SetHasFocusWithin(this, flag);
}

void Node::SetActive(bool flag) {
  GetDocument().UserActionElements().SetActive(this, flag);
}

void Node::SetDragged(bool flag) {
  GetDocument().UserActionElements().SetDragged(this, flag);
}

void Node::SetHovered(bool flag) {
  GetDocument().UserActionElements().SetHovered(this, flag);
}

bool Node::IsUserActionElementActive() const {
  DCHECK(IsUserActionElement());
  return GetDocument().UserActionElements().IsActive(this);
}

bool Node::IsUserActionElementInActiveChain() const {
  DCHECK(IsUserActionElement());
  return GetDocument().UserActionElements().IsInActiveChain(this);
}

bool Node::IsUserActionElementDragged() const {
  DCHECK(IsUserActionElement());
  return GetDocument().UserActionElements().IsDragged(this);
}

bool Node::IsUserActionElementHovered() const {
  DCHECK(IsUserActionElement());
  return GetDocument().UserActionElements().IsHovered(this);
}

bool Node::IsUserActionElementFocused() const {
  DCHECK(IsUserActionElement());
  return GetDocument().UserActionElements().IsFocused(this);
}

bool Node::IsUserActionElementHasFocusWithin() const {
  DCHECK(IsUserActionElement());
  return GetDocument().UserActionElements().HasFocusWithin(this);
}

void Node::SetCustomElementState(CustomElementState new_state) {
  CustomElementState old_state = GetCustomElementState();

  switch (new_state) {
    case CustomElementState::kUncustomized:
      NOTREACHED();  // Everything starts in this state
      return;

    case CustomElementState::kUndefined:
      DCHECK_EQ(CustomElementState::kUncustomized, old_state);
      break;

    case CustomElementState::kCustom:
      DCHECK_EQ(CustomElementState::kUndefined, old_state);
      break;

    case CustomElementState::kFailed:
      DCHECK_NE(CustomElementState::kFailed, old_state);
      break;
  }

  DCHECK(IsHTMLElement());
  DCHECK_NE(kV0Upgraded, GetV0CustomElementState());

  Element* element = ToElement(this);
  bool was_defined = element->IsDefined();

  node_flags_ = (node_flags_ & ~kCustomElementStateMask) |
                static_cast<NodeFlags>(new_state);
  DCHECK(new_state == GetCustomElementState());

  if (element->IsDefined() != was_defined)
    element->PseudoStateChanged(CSSSelector::kPseudoDefined);
}

void Node::SetV0CustomElementState(V0CustomElementState new_state) {
  V0CustomElementState old_state = GetV0CustomElementState();

  switch (new_state) {
    case kV0NotCustomElement:
      NOTREACHED();  // Everything starts in this state
      return;

    case kV0WaitingForUpgrade:
      DCHECK_EQ(kV0NotCustomElement, old_state);
      break;

    case kV0Upgraded:
      DCHECK_EQ(kV0WaitingForUpgrade, old_state);
      break;
  }

  DCHECK(IsHTMLElement() || IsSVGElement());
  DCHECK(CustomElementState::kCustom != GetCustomElementState());
  SetFlag(kV0CustomElementFlag);
  SetFlag(new_state == kV0Upgraded, kV0CustomElementUpgradedFlag);

  if (old_state == kV0NotCustomElement || new_state == kV0Upgraded)
    ToElement(this)->PseudoStateChanged(CSSSelector::kPseudoUnresolved);
}

void Node::CheckSlotChange(SlotChangeType slot_change_type) {
  // Common check logic is used in both cases, "after inserted" and "before
  // removed".
  if (!IsSlotable())
    return;
  if (ShadowRoot* root = V1ShadowRootOfParent()) {
    // Relevant DOM Standard:
    // https://dom.spec.whatwg.org/#concept-node-insert
    // - 6.1.2: If parent is a shadow host and node is a slotable, then assign a
    //   slot for node.
    // https://dom.spec.whatwg.org/#concept-node-remove
    // - 10. If node is assigned, then run assign slotables for node’s assigned
    //   slot.

    // Although DOM Standard requires "assign a slot for node / run assign
    // slotables" at this timing, we skip it as an optimization.
    if (HTMLSlotElement* slot = root->AssignedSlotFor(*this))
      slot->DidSlotChange(slot_change_type);
  } else {
    // Relevant DOM Standard:
    // https://dom.spec.whatwg.org/#concept-node-insert
    // - 6.1.3: If parent is a slot whose assigned nodes is the empty list, then
    //   run signal a slot change for parent.
    // https://dom.spec.whatwg.org/#concept-node-remove
    // - 11. If parent is a slot whose assigned nodes is the empty list, then
    //   run signal a slot change for parent.
    Element* parent = parentElement();
    if (parent && isHTMLSlotElement(parent)) {
      HTMLSlotElement& parent_slot = toHTMLSlotElement(*parent);
      // TODO(hayato): Support slotchange for slots in non-shadow trees.
      if (ShadowRoot* root = ContainingShadowRoot()) {
        if (root && root->IsV1() && !parent_slot.HasAssignedNodesSlow())
          parent_slot.DidSlotChange(slot_change_type);
      }
    }
  }
}

WebPluginContainerBase* Node::GetWebPluginContainerBase() const {
  if (!isHTMLObjectElement(this) && !isHTMLEmbedElement(this)) {
    return nullptr;
  }

  LayoutObject* object = GetLayoutObject();
  if (object && object->IsLayoutPart()) {
    PluginView* plugin = ToLayoutPart(object)->Plugin();
    if (plugin) {
      return plugin->GetWebPluginContainerBase();
    }
  }

  return nullptr;
}

DEFINE_TRACE(Node) {
  visitor->Trace(parent_or_shadow_host_node_);
  visitor->Trace(previous_);
  visitor->Trace(next_);
  // rareData() and m_data.m_layoutObject share their storage. We have to trace
  // only one of them.
  if (HasRareData())
    visitor->Trace(RareData());

  visitor->Trace(tree_scope_);
  EventTarget::Trace(visitor);
}

DEFINE_TRACE_WRAPPERS(Node) {
  visitor->TraceWrappersWithManualWriteBarrier(parent_or_shadow_host_node_);
  visitor->TraceWrappersWithManualWriteBarrier(previous_);
  visitor->TraceWrappersWithManualWriteBarrier(next_);
  if (HasRareData())
    visitor->TraceWrappers(RareData());
  EventTarget::TraceWrappers(visitor);
}

}  // namespace blink

#ifndef NDEBUG

void showNode(const blink::Node* node) {
  if (node)
    LOG(INFO) << *node;
  else
    LOG(INFO) << "Cannot showNode for <null>";
}

void showTree(const blink::Node* node) {
  if (node)
    LOG(INFO) << "\n" << node->ToTreeStringForThis().Utf8().data();
  else
    LOG(INFO) << "Cannot showTree for <null>";
}

void showNodePath(const blink::Node* node) {
  if (node) {
    std::stringstream stream;
    node->PrintNodePathTo(stream);
    LOG(INFO) << stream.str();
  } else {
    LOG(INFO) << "Cannot showNodePath for <null>";
  }
}

#endif
