/*
 * 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-2011, 2014 Apple Inc. All rights reserved.
 * Copyright (C) 2008, 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.
 *
 */

#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_DOM_NODE_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_DOM_NODE_H_

#include "base/macros.h"
#include "third_party/blink/public/mojom/input/focus_type.mojom-blink-forward.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/dom/events/event_target.h"
#include "third_party/blink/renderer/core/dom/events/simulated_click_options.h"
#include "third_party/blink/renderer/core/dom/mutation_observer_options.h"
#include "third_party/blink/renderer/core/dom/node_rare_data.h"
#include "third_party/blink/renderer/core/dom/tree_scope.h"
#include "third_party/blink/renderer/core/scroll/scroll_customization.h"
#include "third_party/blink/renderer/core/style/computed_style_constants.h"

// This needs to be here because element.cc also depends on it.
#define DUMP_NODE_STATISTICS 0

namespace blink {

class ComputedStyle;
class ContainerNode;
class Document;
class Element;
class Event;
class EventDispatchHandlingState;
class ExceptionState;
class FlatTreeNodeData;
class GetRootNodeOptions;
class HTMLQualifiedName;
class HTMLSlotElement;
class IntRect;
class KURL;
class LayoutBox;
class LayoutBoxModelObject;
class LayoutObject;
class MathMLQualifiedName;
class MutationObserver;
class MutationObserverRegistration;
class NodeList;
class NodeListsNodeData;
class NodeOrStringOrTrustedScript;
class NodeRareData;
class QualifiedName;
class RegisteredEventListener;
class SVGQualifiedName;
class ScrollState;
class ScrollStateCallback;
class ShadowRoot;
template <typename NodeType>
class StaticNodeTypeList;
using StaticNodeList = StaticNodeTypeList<Node>;
class StringOrTrustedScript;
class StyleChangeReasonForTracing;
class V8ScrollStateCallback;
class WebPluginContainerImpl;
struct PhysicalRect;

const int kDOMNodeTypeShift = 2;
const int kElementNamespaceTypeShift = 4;
const int kNodeStyleChangeShift = 17;
const int kNodeCustomElementShift = 19;

// Values for kChildNeedsStyleRecalcFlag, controlling whether a node gets its
// style recalculated.
enum StyleChangeType : uint32_t {
  // This node does not need style recalculation.
  kNoStyleChange = 0,
  // This node needs style recalculation.
  kLocalStyleChange = 1 << kNodeStyleChangeShift,
  // This node and all of its flat-tree descendeants need style recalculation.
  kSubtreeStyleChange = 2 << kNodeStyleChangeShift,
};

enum class CustomElementState : uint32_t {
  // https://dom.spec.whatwg.org/#concept-element-custom-element-state
  kUncustomized = 0,
  kCustom = 1 << kNodeCustomElementShift,
  kUndefined = 2 << kNodeCustomElementShift,
  kFailed = 3 << kNodeCustomElementShift,
};

enum class SlotChangeType {
  kSignalSlotChangeEvent,
  kSuppressSlotChangeEvent,
};

enum class CloneChildrenFlag { kClone, kSkip };

// Whether or not to force creation of a legacy layout object (i.e. disallow
// LayoutNG).
enum class LegacyLayout {
  // Allow LayoutNG, if nothing else is preventing it (runtime feature disabled,
  // specific object type not yet implemented, Element says no, etc.)
  kAuto,

  // Force legacy layout object creation.
  kForce
};

// A Node is a base class for all objects in the DOM tree.
// The spec governing this interface can be found here:
// https://dom.spec.whatwg.org/#interface-node
class CORE_EXPORT Node : public EventTarget {
  DEFINE_WRAPPERTYPEINFO();
  friend class TreeScope;
  friend class TreeScopeAdopter;

 public:
  enum NodeType {
    kElementNode = 1,
    kAttributeNode = 2,
    kTextNode = 3,
    kCdataSectionNode = 4,
    kProcessingInstructionNode = 7,
    kCommentNode = 8,
    kDocumentNode = 9,
    kDocumentTypeNode = 10,
    kDocumentFragmentNode = 11,
  };

  // Entity, EntityReference, and Notation nodes are impossible to create in
  // Blink.  But for compatibility reasons we want these enum values exist in
  // JS, and this enum makes the bindings generation not complain about
  // kEntityReferenceNode being missing from the implementation while not
  // requiring all switch(NodeType) blocks to include this deprecated constant.
  enum DeprecatedNodeType {
    kEntityReferenceNode = 5,
    kEntityNode = 6,
    kNotationNode = 12,
  };

  enum DocumentPosition {
    kDocumentPositionEquivalent = 0x00,
    kDocumentPositionDisconnected = 0x01,
    kDocumentPositionPreceding = 0x02,
    kDocumentPositionFollowing = 0x04,
    kDocumentPositionContains = 0x08,
    kDocumentPositionContainedBy = 0x10,
    kDocumentPositionImplementationSpecific = 0x20,
  };

  template <typename T>
  static void* AllocateObject(size_t size) {
    ThreadState* state =
        ThreadStateFor<ThreadingTrait<Node>::kAffinity>::GetState();
    const char* type_name = "blink::Node";
    return state->Heap().AllocateOnArenaIndex(
        state, size, BlinkGC::kNodeArenaIndex,
        GCInfoTrait<GCInfoFoldedType<T>>::Index(), type_name);
  }

  static void DumpStatistics();

  ~Node() override;

  // DOM methods & attributes for Node

  bool HasTagName(const HTMLQualifiedName&) const;
  bool HasTagName(const MathMLQualifiedName&) const;
  bool HasTagName(const SVGQualifiedName&) const;
  virtual String nodeName() const = 0;
  virtual String nodeValue() const;
  virtual void setNodeValue(const String&);
  virtual NodeType getNodeType() const = 0;
  ContainerNode* parentNode() const;
  ContainerNode* ParentNodeWithCounting() const;
  Element* parentElement() const;
  ContainerNode* ParentElementOrShadowRoot() const;
  ContainerNode* ParentElementOrDocumentFragment() const;
  Node* previousSibling() const { return previous_; }
  Node* nextSibling() const { return next_; }
  NodeList* childNodes();
  Node* firstChild() const;
  Node* lastChild() const;
  Node* getRootNode(const GetRootNodeOptions*) const;

  // Scroll Customization API. See crbug.com/410974 for details.
  void setDistributeScroll(V8ScrollStateCallback*,
                           const String& native_scroll_behavior);
  void setApplyScroll(V8ScrollStateCallback*,
                      const String& native_scroll_behavior);
  void SetApplyScroll(ScrollStateCallback*);
  void RemoveApplyScroll();
  ScrollStateCallback* GetApplyScroll();
  void NativeDistributeScroll(ScrollState&);
  void NativeApplyScroll(ScrollState&);
  void CallDistributeScroll(ScrollState&);
  void CallApplyScroll(ScrollState&);
  void WillBeginCustomizedScrollPhase(scroll_customization::ScrollDirection);
  void DidEndCustomizedScrollPhase();

  Node& TreeRoot() const;
  Node& ShadowIncludingRoot() const;
  // closed-shadow-hidden is defined at
  // https://dom.spec.whatwg.org/#concept-closed-shadow-hidden
  bool IsClosedShadowHiddenFrom(const Node&) const;

  void Prepend(const HeapVector<NodeOrStringOrTrustedScript>&, ExceptionState&);
  void Append(const HeapVector<NodeOrStringOrTrustedScript>&, ExceptionState&);
  void Before(const HeapVector<NodeOrStringOrTrustedScript>&, ExceptionState&);
  void After(const HeapVector<NodeOrStringOrTrustedScript>&, ExceptionState&);
  void ReplaceWith(const HeapVector<NodeOrStringOrTrustedScript>&,
                   ExceptionState&);
  void remove(ExceptionState&);
  void remove();

  Node* PseudoAwareNextSibling() const;
  Node* PseudoAwarePreviousSibling() const;
  Node* PseudoAwareFirstChild() const;
  Node* PseudoAwareLastChild() const;

  const KURL& baseURI() const;

  Node* insertBefore(Node* new_child, Node* ref_child, ExceptionState&);
  Node* insertBefore(Node* new_child, Node* ref_child);
  Node* replaceChild(Node* new_child, Node* old_child, ExceptionState&);
  Node* replaceChild(Node* new_child, Node* old_child);
  Node* removeChild(Node* child, ExceptionState&);
  Node* removeChild(Node* child);
  Node* appendChild(Node* new_child, ExceptionState&);
  Node* appendChild(Node* new_child);

  bool hasChildren() const { return firstChild(); }
  Node* cloneNode(bool deep, ExceptionState&) const;
  // https://dom.spec.whatwg.org/#concept-node-clone
  virtual Node* Clone(Document&, CloneChildrenFlag) const = 0;
  // This is not web-exposed. We should rename it or remove it.
  Node* cloneNode(bool deep) const;
  void normalize();

  bool isEqualNode(Node*) const;
  bool isSameNode(const Node* other) const { return this == other; }
  bool isDefaultNamespace(const AtomicString& namespace_uri) const;
  const AtomicString& lookupPrefix(const AtomicString& namespace_uri) const;
  const AtomicString& lookupNamespaceURI(const String& prefix) const;

  String textContent(bool convert_brs_to_newlines = false) const;
  void setTextContent(const String&);
  void textContent(StringOrTrustedScript& result);
  virtual void setTextContent(const StringOrTrustedScript&, ExceptionState&);

  bool SupportsAltText();

  void SetComputedStyle(scoped_refptr<const ComputedStyle> computed_style);

  // Other methods (not part of DOM)
  ALWAYS_INLINE bool IsTextNode() const {
    return GetDOMNodeType() == DOMNodeType::kText;
  }
  ALWAYS_INLINE bool IsContainerNode() const {
    return GetFlag(kIsContainerFlag);
  }
  ALWAYS_INLINE bool IsElementNode() const {
    return GetDOMNodeType() == DOMNodeType::kElement;
  }
  ALWAYS_INLINE bool IsDocumentFragment() const {
    return GetDOMNodeType() == DOMNodeType::kDocumentFragment;
  }

  ALWAYS_INLINE bool IsHTMLElement() const {
    return GetElementNamespaceType() == ElementNamespaceType::kHTML;
  }
  ALWAYS_INLINE bool IsMathMLElement() const {
    return GetElementNamespaceType() == ElementNamespaceType::kMathML;
  }
  ALWAYS_INLINE bool IsSVGElement() const {
    return GetElementNamespaceType() == ElementNamespaceType::kSVG;
  }

  DISABLE_CFI_PERF bool IsPseudoElement() const {
    return GetPseudoId() != kPseudoIdNone;
  }
  DISABLE_CFI_PERF bool IsBeforePseudoElement() const {
    return GetPseudoId() == kPseudoIdBefore;
  }
  DISABLE_CFI_PERF bool IsAfterPseudoElement() const {
    return GetPseudoId() == kPseudoIdAfter;
  }
  DISABLE_CFI_PERF bool IsMarkerPseudoElement() const {
    return GetPseudoId() == kPseudoIdMarker;
  }
  DISABLE_CFI_PERF bool IsFirstLetterPseudoElement() const {
    return GetPseudoId() == kPseudoIdFirstLetter;
  }
  virtual PseudoId GetPseudoId() const { return kPseudoIdNone; }

  CustomElementState GetCustomElementState() const {
    return static_cast<CustomElementState>(node_flags_ &
                                           kCustomElementStateMask);
  }
  bool IsCustomElement() const {
    return GetCustomElementState() != CustomElementState::kUncustomized;
  }
  void SetCustomElementState(CustomElementState);
  bool IsV0CustomElement() const { return GetFlag(kV0CustomElementFlag); }
  enum V0CustomElementState {
    kV0NotCustomElement = 0,
    kV0WaitingForUpgrade = 1 << 0,
    kV0Upgraded = 1 << 1
  };
  V0CustomElementState GetV0CustomElementState() const {
    return IsV0CustomElement()
               ? (GetFlag(kV0CustomElementUpgradedFlag) ? kV0Upgraded
                                                        : kV0WaitingForUpgrade)
               : kV0NotCustomElement;
  }
  void SetV0CustomElementState(V0CustomElementState new_state);

  virtual bool IsMediaControlElement() const { return false; }
  virtual bool IsMediaControls() const { return false; }
  virtual bool IsMediaElement() const { return false; }
  virtual bool IsTextTrackContainer() const { return false; }
  virtual bool IsVTTElement() const { return false; }
  virtual bool IsAttributeNode() const { return false; }
  virtual bool IsCharacterDataNode() const { return false; }
  virtual bool IsFrameOwnerElement() const { return false; }
  virtual bool IsMediaRemotingInterstitial() const { return false; }
  virtual bool IsPictureInPictureInterstitial() const { return false; }

  // Traverses the ancestors of this node and returns true if any of them are
  // either a MediaControlElement or MediaControls.
  bool HasMediaControlAncestor() const;

  bool IsStyledElement() const;

  bool IsDocumentNode() const;
  bool IsTreeScope() const;
  bool IsShadowRoot() const { return IsDocumentFragment() && IsTreeScope(); }
  bool IsV0InsertionPoint() const { return GetFlag(kIsV0InsertionPointFlag); }

  bool CanParticipateInFlatTree() const;
  bool IsActiveSlotOrActiveV0InsertionPoint() const;
  // A re-distribution across v0 and v1 shadow trees is not supported.
  bool IsSlotable() const {
    return IsTextNode() || (IsElementNode() && !IsV0InsertionPoint());
  }
  AtomicString SlotName() const;

  bool HasCustomStyleCallbacks() const {
    return GetFlag(kHasCustomStyleCallbacksFlag);
  }

  // If this node is in a shadow tree, returns its shadow host. Otherwise,
  // returns nullptr.
  Element* OwnerShadowHost() const;
  // crbug.com/569532: containingShadowRoot() can return nullptr even if
  // isInShadowTree() returns true.
  // This can happen when handling queued events (e.g. during execCommand())
  ShadowRoot* ContainingShadowRoot() const;
  ShadowRoot* GetShadowRoot() const;
  bool IsInUserAgentShadowRoot() const;

  // Returns nullptr, a child of ShadowRoot, or a legacy shadow root.
  Node* NonBoundaryShadowTreeRootNode();

  // Node's parent, shadow tree host.
  ContainerNode* ParentOrShadowHostNode() const;
  Element* ParentOrShadowHostElement() const;
  void SetParentOrShadowHostNode(ContainerNode*);

  // Knows about all kinds of hosts.
  ContainerNode* ParentOrShadowHostOrTemplateHostNode() const;

  // Returns the parent node, but nullptr if the parent node is a ShadowRoot.
  ContainerNode* NonShadowBoundaryParentNode() const;

  // Returns the enclosing event parent Element (or self) that, when clicked,
  // would trigger a navigation.
  Element* EnclosingLinkEventParentOrSelf() const;

  // These low-level calls give the caller responsibility for maintaining the
  // integrity of the tree.
  void SetPreviousSibling(Node* previous) { previous_ = previous; }
  void SetNextSibling(Node* next) { next_ = next; }

  virtual bool CanContainRangeEndPoint() const { return false; }

  // For <link> and <style> elements.
  virtual bool SheetLoaded() { return true; }
  enum LoadedSheetErrorStatus {
    kNoErrorLoadingSubresource,
    kErrorOccurredLoadingSubresource
  };
  virtual void NotifyLoadedSheetAndAllCriticalSubresources(
      LoadedSheetErrorStatus) {}
  virtual void StartLoadingDynamicSheet() { NOTREACHED(); }

  bool HasName() const {
    DCHECK(!IsTextNode());
    return GetFlag(kHasNameOrIsEditingTextFlag);
  }

  bool IsUserActionElement() const { return GetFlag(kIsUserActionElementFlag); }
  void SetUserActionElement(bool flag) {
    SetFlag(flag, kIsUserActionElementFlag);
  }

  bool IsActive() const {
    return IsUserActionElement() && IsUserActionElementActive();
  }
  bool InActiveChain() const {
    return IsUserActionElement() && IsUserActionElementInActiveChain();
  }
  bool IsDragged() const {
    return IsUserActionElement() && IsUserActionElementDragged();
  }
  bool IsHovered() const {
    return IsUserActionElement() && IsUserActionElementHovered();
  }
  // Note: As a shadow host whose root with delegatesFocus=false may become
  // focused state when an inner element gets focused, in that case more than
  // one elements in a document can return true for |isFocused()|.  Use
  // Element::isFocusedElementInDocument() or Document::focusedElement() to
  // check which element is exactly focused.
  bool IsFocused() const {
    return IsUserActionElement() && IsUserActionElementFocused();
  }
  bool HasFocusWithin() const {
    return IsUserActionElement() && IsUserActionElementHasFocusWithin();
  }

  // True if the style recalc process should recalculate style for this node.
  bool NeedsStyleRecalc() const {
    return GetStyleChangeType() != kNoStyleChange;
  }
  StyleChangeType GetStyleChangeType() const {
    return static_cast<StyleChangeType>(node_flags_ & kStyleChangeMask);
  }
  // True if the style recalculation process should traverse this node's
  // children when looking for nodes that need recalculation.
  bool ChildNeedsStyleRecalc() const {
    return GetFlag(kChildNeedsStyleRecalcFlag);
  }
  bool IsLink() const { return GetFlag(kIsLinkFlag); }
  bool IsEditingText() const {
    DCHECK(IsTextNode());
    return GetFlag(kHasNameOrIsEditingTextFlag);
  }

  void SetHasName(bool f) {
    DCHECK(!IsTextNode());
    SetFlag(f, kHasNameOrIsEditingTextFlag);
  }
  void SetChildNeedsStyleRecalc() { SetFlag(kChildNeedsStyleRecalcFlag); }
  void ClearChildNeedsStyleRecalc() { ClearFlag(kChildNeedsStyleRecalcFlag); }

  // Sets the flag for the current node and also calls
  // MarkAncestorsWithChildNeedsStyleRecalc
  void SetNeedsStyleRecalc(StyleChangeType, const StyleChangeReasonForTracing&);
  void ClearNeedsStyleRecalc();

  // Propagates a dirty bit breadcrumb for this element up the ancestor chain.
  void MarkAncestorsWithChildNeedsStyleRecalc();

  // Traverses subtree (include pseudo elements and shadow trees) and
  // invalidates nodes whose styles depend on font metrics (e.g., 'ex' unit).
  void MarkSubtreeNeedsStyleRecalcForFontUpdates();

  // Nodes which are not connected are style clean. Mark them for style recalc
  // when inserting them into a document. This method was added as a light-
  // weight alternative to SetNeedsStyleRecalc because using that method caused
  // a micro-benchmark regression (https://crbug.com/926343).
  void SetStyleChangeOnInsertion() {
    DCHECK(isConnected());
    if (ShouldSkipMarkingStyleDirty())
      return;
    if (!NeedsStyleRecalc())
      SetStyleChange(kLocalStyleChange);
    MarkAncestorsWithChildNeedsStyleRecalc();
  }

  bool NeedsReattachLayoutTree() const {
    return GetFlag(kNeedsReattachLayoutTree);
  }
  bool ChildNeedsReattachLayoutTree() const {
    return GetFlag(kChildNeedsReattachLayoutTree);
  }

  void SetNeedsReattachLayoutTree();
  void SetChildNeedsReattachLayoutTree() {
    SetFlag(kChildNeedsReattachLayoutTree);
  }

  void ClearNeedsReattachLayoutTree() { ClearFlag(kNeedsReattachLayoutTree); }
  void ClearChildNeedsReattachLayoutTree() {
    ClearFlag(kChildNeedsReattachLayoutTree);
  }

  void MarkAncestorsWithChildNeedsReattachLayoutTree();

  // Mark node for forced layout tree re-attach during next lifecycle update.
  // This is to trigger layout tree re-attachment when we cannot detect that we
  // need to re-attach based on the computed style changes. This can happen when
  // re-slotting shadow host children, for instance.
  void SetForceReattachLayoutTree();
  bool GetForceReattachLayoutTree() const {
    return GetFlag(kForceReattachLayoutTree);
  }

  bool IsDirtyForStyleRecalc() const {
    return NeedsStyleRecalc() || GetForceReattachLayoutTree();
  }

  bool NeedsDistributionRecalc() const;

  bool ChildNeedsDistributionRecalc() const {
    return GetFlag(kChildNeedsDistributionRecalcFlag);
  }
  void SetChildNeedsDistributionRecalc() {
    SetFlag(kChildNeedsDistributionRecalcFlag);
  }
  void ClearChildNeedsDistributionRecalc() {
    ClearFlag(kChildNeedsDistributionRecalcFlag);
  }
  void MarkAncestorsWithChildNeedsDistributionRecalc();

  // True if the style invalidation process should traverse this node's children
  // when looking for pending invalidations.
  bool ChildNeedsStyleInvalidation() const {
    return GetFlag(kChildNeedsStyleInvalidationFlag);
  }
  void SetChildNeedsStyleInvalidation() {
    SetFlag(kChildNeedsStyleInvalidationFlag);
  }
  void ClearChildNeedsStyleInvalidation() {
    ClearFlag(kChildNeedsStyleInvalidationFlag);
  }
  void MarkAncestorsWithChildNeedsStyleInvalidation();

  // True if there are pending invalidations against this node.
  bool NeedsStyleInvalidation() const {
    return GetFlag(kNeedsStyleInvalidationFlag);
  }
  void ClearNeedsStyleInvalidation() { ClearFlag(kNeedsStyleInvalidationFlag); }
  // Sets the flag for the current node and also calls
  // MarkAncestorsWithChildNeedsStyleInvalidation
  void SetNeedsStyleInvalidation();

  // This needs to be called before using FlatTreeTraversal.
  // Once Shadow DOM v0 is removed, this function can be removed.
  void UpdateDistributionForFlatTreeTraversal() {
    UpdateDistributionInternal();
  }

  // This is not what you might want to call in most cases.
  // You should call UpdateDistributionForFlatTreeTraversal, instead.
  // Only the implementation of v0 shadow trees uses this.
  void UpdateDistributionForLegacyDistributedNodes() {
    // The implementation is same to UpdateDistributionForFlatTreeTraversal.
    UpdateDistributionInternal();
  }

  // Please don't use this function.
  // Background: When we investigated the usage of (old) UpdateDistribution,
  // some caller's intents were unclear. Thus, we had to introduce this function
  // for the sake of safety. If we can figure out the intent of each caller, we
  // can replace that with calling UpdateDistributionForFlatTreeTraversal (or
  // just RecalcSlotAssignments()) on a case-by-case basis.
  void UpdateDistributionForUnknownReasons();

  bool MayContainLegacyNodeTreeWhereDistributionShouldBeSupported() const;

  void SetIsLink(bool f);

  bool HasEventTargetData() const { return GetFlag(kHasEventTargetDataFlag); }
  void SetHasEventTargetData(bool flag) {
    SetFlag(flag, kHasEventTargetDataFlag);
  }

  virtual void SetFocused(bool flag, mojom::blink::FocusType);
  void SetHasFocusWithin(bool flag);
  virtual void SetDragged(bool flag);

  virtual const Node* FocusDelegate() const;
  // This is called only when the node is focused.
  virtual bool ShouldHaveFocusAppearance() const;

  // Whether the node is inert:
  // https://html.spec.whatwg.org/C/#inert
  // https://github.com/WICG/inert/blob/master/README.md
  // This can't be in Element because text nodes must be recognized as
  // inert to prevent text selection.
  bool IsInert() const;

  virtual PhysicalRect BoundingBox() const;
  IntRect PixelSnappedBoundingBox() const;

  // BoundingBoxForScrollIntoView() is the node's scroll snap area.
  // It is expanded from the BoundingBox() by scroll-margin.
  // https://drafts.csswg.org/css-scroll-snap-1/#scroll-snap-area
  PhysicalRect BoundingBoxForScrollIntoView() const;

  unsigned NodeIndex() const;

  // Returns the DOM ownerDocument attribute. This method never returns null,
  // except in the case of a Document node.
  Document* ownerDocument() const;

  // Returns the document associated with this node. A Document node returns
  // itself.
  Document& GetDocument() const { return GetTreeScope().GetDocument(); }

  TreeScope& GetTreeScope() const {
    DCHECK(tree_scope_);
    return *tree_scope_;
  }

  TreeScope& ContainingTreeScope() const {
    DCHECK(IsInTreeScope());
    return *tree_scope_;
  }

  // Returns the tree scope where this element originated.
  // Use this when resolving element references for (CSS url(...)s and #id).
  // This differs from GetTreeScope for shadow clones inside <svg:use/>.
  TreeScope& OriginatingTreeScope() const;

  bool InActiveDocument() const;

  // Returns true if this node is connected to a document, false otherwise.
  // See https://dom.spec.whatwg.org/#connected for the definition.
  bool isConnected() const { return GetFlag(kIsConnectedFlag); }

  bool IsInDocumentTree() const { return isConnected() && !IsInShadowTree(); }
  bool IsInShadowTree() const { return GetFlag(kIsInShadowTreeFlag); }
  bool IsInTreeScope() const {
    return GetFlag(
        static_cast<NodeFlags>(kIsConnectedFlag | kIsInShadowTreeFlag));
  }

  ShadowRoot* ParentElementShadowRoot() const;
  bool IsInV1ShadowTree() const;
  bool IsInV0ShadowTree() const;
  bool IsChildOfV1ShadowHost() const;
  bool IsChildOfV0ShadowHost() const;
  ShadowRoot* V1ShadowRootOfParent() const;
  Element* FlatTreeParentForChildDirty() const;
  ContainerNode* GetStyleRecalcParent() const;
  Element* GetReattachParent() const { return FlatTreeParentForChildDirty(); }

  bool IsDocumentTypeNode() const { return getNodeType() == kDocumentTypeNode; }
  virtual bool ChildTypeAllowed(NodeType) const { return false; }
  unsigned CountChildren() const;

  bool IsDescendantOf(const Node*) const;
  bool contains(const Node*) const;
  // https://dom.spec.whatwg.org/#concept-shadow-including-inclusive-ancestor
  bool IsShadowIncludingInclusiveAncestorOf(const Node&) const;
  // https://dom.spec.whatwg.org/#concept-shadow-including-ancestor
  bool IsShadowIncludingAncestorOf(const Node&) const;
  bool ContainsIncludingHostElements(const Node&) const;
  Node* CommonAncestor(const Node&,
                       ContainerNode* (*parent)(const Node&)) const;

  // Whether or not a selection can be started in this object
  virtual bool CanStartSelection() const;

  // ---------------------------------------------------------------------------
  // Integration with layout tree

  // As layoutObject() includes a branch you should avoid calling it repeatedly
  // in hot code paths.
  // Note that if a Node has a layoutObject, it's parentNode is guaranteed to
  // have one as well.
  LayoutObject* GetLayoutObject() const {
    return HasRareData()
               ? DataAsNodeRareData()->GetNodeRenderingData()->GetLayoutObject()
               : DataAsNodeRenderingData()->GetLayoutObject();
  }
  void SetLayoutObject(LayoutObject*);
  // Use these two methods with caution.
  LayoutBox* GetLayoutBox() const;
  LayoutBoxModelObject* GetLayoutBoxModelObject() const;

  struct AttachContext {
    STACK_ALLOCATED();

   public:
    // Keep track of previously attached in-flow box during attachment so that
    // we don't need to backtrack past display:none/contents and out of flow
    // objects when we need to do whitespace re-attachment.
    LayoutObject* previous_in_flow = nullptr;
    // The parent LayoutObject to use when inserting a new child into the layout
    // tree in LayoutTreeBuilder::CreateLayoutObject.
    LayoutObject* parent = nullptr;
    // LayoutObject to be used as the next pointer when inserting a LayoutObject
    // into the tree.
    LayoutObject* next_sibling = nullptr;
    // Set to true if the AttachLayoutTree is done as part of the
    // RebuildLayoutTree pass.
    bool performing_reattach = false;
    // True if the previous_in_flow member is up-to-date, even if it is nullptr.
    bool use_previous_in_flow = false;
    // True if the next_sibling member is up-to-date, even if it is nullptr.
    bool next_sibling_valid = false;
    // True if we need to force legacy layout objects for the entire subtree.
    bool force_legacy_layout = false;

    AttachContext() {}
  };

  // Attaches this node to the layout tree. This calculates the style to be
  // applied to the node and creates an appropriate LayoutObject which will be
  // inserted into the tree (except when the style has display: none). This
  // makes the node visible in the LocalFrameView.
  virtual void AttachLayoutTree(AttachContext&);

  // Detaches the node from the layout tree, making it invisible in the rendered
  // view. This method will remove the node's layout object from the layout tree
  // and delete it.
  virtual void DetachLayoutTree(bool performing_reattach = false);

  void ReattachLayoutTree(AttachContext&);

  // ---------------------------------------------------------------------------
  // Inline ComputedStyle accessors
  //
  // Note that the following 'inline' functions are not defined in this header,
  // but in node_computed_style.h. Please include that file if you want to use
  // these functions.
  ComputedStyle* MutableComputedStyleForEditingDeprecated() const;
  const ComputedStyle* GetComputedStyle() const;
  const ComputedStyle* ParentComputedStyle() const;
  const ComputedStyle& ComputedStyleRef() const;
  bool ShouldSkipMarkingStyleDirty() const;

  const ComputedStyle* EnsureComputedStyle(
      PseudoId pseudo_element_specifier = kPseudoIdNone) {
    return VirtualEnsureComputedStyle(pseudo_element_specifier);
  }

  // ---------------------------------------------------------------------------
  // Notification of document structure changes (see container_node.h for more
  // notification methods)
  //
  // At first, Blinkt notifies the node that it has been inserted into the
  // document. This is called during document parsing, and also when a node is
  // added through the DOM methods insertBefore(), appendChild() or
  // replaceChild(). The call happens _after_ the node has been added to the
  // tree.  This is similar to the DOMNodeInsertedIntoDocument DOM event, but
  // does not require the overhead of event dispatching.
  //
  // Blink notifies this callback regardless if the subtree of the node is a
  // document tree or a floating subtree.  Implementation can determine the type
  // of subtree by seeing insertionPoint->isConnected().  For a performance
  // reason, notifications are delivered only to ContainerNode subclasses if the
  // insertionPoint is out of document.
  //
  // There are another callback named didNotifySubtreeInsertionsToDocument(),
  // which is called after all the descendant is notified, if this node was
  // inserted into the document tree. Only a few subclasses actually need
  // this. To utilize this, the node should return
  // InsertionShouldCallDidNotifySubtreeInsertions from insertedInto().
  //
  enum InsertionNotificationRequest {
    kInsertionDone,
    kInsertionShouldCallDidNotifySubtreeInsertions
  };

  virtual InsertionNotificationRequest InsertedInto(
      ContainerNode& insertion_point);
  virtual void DidNotifySubtreeInsertionsToDocument() {}

  // Notifies the node that it is no longer part of the tree.
  //
  // This is a dual of insertedInto(), and is similar to the
  // DOMNodeRemovedFromDocument DOM event, but does not require the overhead of
  // event dispatching, and is called _after_ the node is removed from the tree.
  //
  virtual void RemovedFrom(ContainerNode& insertion_point);

  // FIXME(dominicc): This method is not debug-only--it is used by
  // Tracing--rename it to something indicative.
  String DebugName() const;

  String ToString() const;

#if DCHECK_IS_ON()
  String ToTreeStringForThis() const;
  String ToFlatTreeStringForThis() const;
  void PrintNodePathTo(std::ostream&) const;
  String ToMarkedTreeString(const Node* marked_node1,
                            const char* marked_label1,
                            const Node* marked_node2 = nullptr,
                            const char* marked_label2 = nullptr) const;
  String ToMarkedFlatTreeString(const Node* marked_node1,
                                const char* marked_label1,
                                const Node* marked_node2 = nullptr,
                                const char* marked_label2 = nullptr) const;
  void ShowTreeForThisAcrossFrame() const;
#endif

  NodeListsNodeData* NodeLists();
  void ClearNodeLists();

  FlatTreeNodeData* GetFlatTreeNodeData() const;
  FlatTreeNodeData& EnsureFlatTreeNodeData();
  void ClearFlatTreeNodeData();
  void ClearFlatTreeNodeDataIfHostChanged(const ContainerNode& parent);

  virtual bool WillRespondToMouseMoveEvents();
  virtual bool WillRespondToMouseClickEvents();

  enum ShadowTreesTreatment {
    kTreatShadowTreesAsDisconnected,
    kTreatShadowTreesAsComposed
  };

  uint16_t compareDocumentPosition(
      const Node*,
      ShadowTreesTreatment = kTreatShadowTreesAsDisconnected) const;

  const AtomicString& InterfaceName() const override;
  ExecutionContext* GetExecutionContext() const final;

  void RemoveAllEventListeners() override;
  void RemoveAllEventListenersRecursively();

  // Handlers to do/undo actions on the target node before an event is
  // dispatched to it and after the event has been dispatched.  The data pointer
  // is handed back by the preDispatch and passed to postDispatch.
  virtual EventDispatchHandlingState* PreDispatchEventHandler(Event&) {
    return nullptr;
  }
  virtual void PostDispatchEventHandler(Event&, EventDispatchHandlingState*) {}

  void DispatchScopedEvent(Event&);

  virtual void HandleLocalEvents(Event&);

  void DispatchSubtreeModifiedEvent();
  DispatchEventResult DispatchDOMActivateEvent(int detail,
                                               Event& underlying_event);

  void DispatchSimulatedClick(const Event* underlying_event,
                              SimulatedClickMouseEventOptions = kSendNoEvents,
                              SimulatedClickCreationScope =
                                  SimulatedClickCreationScope::kFromUserAgent);

  // Perform the default action for an event.
  virtual void DefaultEventHandler(Event&);
  void UpdateHadKeyboardEvent(const Event&);
  // Should return true if this Node has activation behavior.
  // https://dom.spec.whatwg.org/#eventtarget-activation-behavior
  virtual bool HasActivationBehavior() const;

  EventTargetData* GetEventTargetData() override;
  EventTargetData& EnsureEventTargetData() override;

  void GetRegisteredMutationObserversOfType(
      HeapHashMap<Member<MutationObserver>, MutationRecordDeliveryOptions>&,
      MutationType,
      const QualifiedName* attribute_name);
  void RegisterMutationObserver(MutationObserver&,
                                MutationObserverOptions,
                                const HashSet<AtomicString>& attribute_filter);
  void UnregisterMutationObserver(MutationObserverRegistration*);
  void RegisterTransientMutationObserver(MutationObserverRegistration*);
  void UnregisterTransientMutationObserver(MutationObserverRegistration*);
  void NotifyMutationObserversNodeWillDetach();

  unsigned ConnectedSubframeCount() const;
  void IncrementConnectedSubframeCount();
  void DecrementConnectedSubframeCount();

  StaticNodeList* getDestinationInsertionPoints();
  HTMLSlotElement* AssignedSlot() const;
  HTMLSlotElement* assignedSlotForBinding();

  bool IsFinishedParsingChildren() const {
    return GetFlag(kIsFinishedParsingChildrenFlag);
  }

  void CheckSlotChange(SlotChangeType);
  void CheckSlotChangeAfterInserted() {
    CheckSlotChange(SlotChangeType::kSignalSlotChangeEvent);
  }
  void CheckSlotChangeBeforeRemoved() {
    CheckSlotChange(SlotChangeType::kSignalSlotChangeEvent);
  }

  void FlatTreeParentChanged();
  void RemovedFromFlatTree();

  void SetHasDuplicateAttributes() { SetFlag(kHasDuplicateAttributes); }
  bool HasDuplicateAttribute() const {
    return GetFlag(kHasDuplicateAttributes);
  }

  bool IsEffectiveRootScroller() const;

  virtual LayoutBox* AutoscrollBox();
  virtual void StopAutoscroll();

  // If the node is a plugin, then this returns its WebPluginContainer.
  WebPluginContainerImpl* GetWebPluginContainer() const;

  void Trace(Visitor*) override;

 private:
  enum NodeFlags : uint32_t {
    kHasRareDataFlag = 1,

    // Node type flags. These never change once created.
    kIsContainerFlag = 1 << 1,
    kDOMNodeTypeMask = 0x3 << kDOMNodeTypeShift,
    kElementNamespaceTypeMask = 0x3 << kElementNamespaceTypeShift,
    kIsV0InsertionPointFlag = 1 << 6,

    // Changes based on if the element should be treated like a link,
    // ex. When setting the href attribute on an <a>.
    kIsLinkFlag = 1 << 7,

    // Changes based on :hover, :active and :focus state.
    kIsUserActionElementFlag = 1 << 8,

    // Tree state flags. These change when the element is added/removed
    // from a DOM tree.
    kIsConnectedFlag = 1 << 9,
    kIsInShadowTreeFlag = 1 << 10,

    // Set by the parser when the children are done parsing.
    kIsFinishedParsingChildrenFlag = 1 << 11,

    // Flags related to recalcStyle.
    kHasCustomStyleCallbacksFlag = 1 << 12,
    kChildNeedsStyleInvalidationFlag = 1 << 13,
    kNeedsStyleInvalidationFlag = 1 << 14,
    kChildNeedsDistributionRecalcFlag = 1 << 15,
    kChildNeedsStyleRecalcFlag = 1 << 16,
    kStyleChangeMask = 0x3 << kNodeStyleChangeShift,

    kCustomElementStateMask = 0x3 << kNodeCustomElementShift,

    kHasNameOrIsEditingTextFlag = 1 << 21,
    kHasEventTargetDataFlag = 1 << 22,

    kV0CustomElementFlag = 1 << 23,
    kV0CustomElementUpgradedFlag = 1 << 24,

    kNeedsReattachLayoutTree = 1 << 25,
    kChildNeedsReattachLayoutTree = 1 << 26,

    kHasDuplicateAttributes = 1 << 27,

    kForceReattachLayoutTree = 1 << 28,

    kDefaultNodeFlags = kIsFinishedParsingChildrenFlag,

    // 4 bits remaining.
  };

  ALWAYS_INLINE bool GetFlag(NodeFlags mask) const {
    return node_flags_ & mask;
  }
  void SetFlag(bool f, NodeFlags mask) {
    node_flags_ = (node_flags_ & ~mask) | (-(int32_t)f & mask);
  }
  void SetFlag(NodeFlags mask) { node_flags_ |= mask; }
  void ClearFlag(NodeFlags mask) { node_flags_ &= ~mask; }

  enum class DOMNodeType : uint32_t {
    kElement = 0,
    kText = 1 << kDOMNodeTypeShift,
    kDocumentFragment = 2 << kDOMNodeTypeShift,
    kOther = 3 << kDOMNodeTypeShift,
  };
  ALWAYS_INLINE DOMNodeType GetDOMNodeType() const {
    return static_cast<DOMNodeType>(node_flags_ & kDOMNodeTypeMask);
  }

  enum class ElementNamespaceType : uint32_t {
    kHTML = 0,
    kMathML = 1 << kElementNamespaceTypeShift,
    kSVG = 2 << kElementNamespaceTypeShift,
    kOther = 3 << kElementNamespaceTypeShift,
  };
  ALWAYS_INLINE ElementNamespaceType GetElementNamespaceType() const {
    return static_cast<ElementNamespaceType>(node_flags_ &
                                             kElementNamespaceTypeMask);
  }

 protected:
  enum ConstructionType {
    kCreateOther = kDefaultNodeFlags |
                   static_cast<NodeFlags>(DOMNodeType::kOther) |
                   static_cast<NodeFlags>(ElementNamespaceType::kOther),
    kCreateText = kDefaultNodeFlags |
                  static_cast<NodeFlags>(DOMNodeType::kText) |
                  static_cast<NodeFlags>(ElementNamespaceType::kOther),
    kCreateContainer = kDefaultNodeFlags | kIsContainerFlag |
                       static_cast<NodeFlags>(DOMNodeType::kOther) |
                       static_cast<NodeFlags>(ElementNamespaceType::kOther),
    kCreateElement = kDefaultNodeFlags | kIsContainerFlag |
                     static_cast<NodeFlags>(DOMNodeType::kElement) |
                     static_cast<NodeFlags>(ElementNamespaceType::kOther),
    kCreateDocumentFragment =
        kDefaultNodeFlags | kIsContainerFlag |
        static_cast<NodeFlags>(DOMNodeType::kDocumentFragment) |
        static_cast<NodeFlags>(ElementNamespaceType::kOther),
    kCreateShadowRoot = kCreateDocumentFragment | kIsInShadowTreeFlag,
    kCreateHTMLElement = kDefaultNodeFlags | kIsContainerFlag |
                         static_cast<NodeFlags>(DOMNodeType::kElement) |
                         static_cast<NodeFlags>(ElementNamespaceType::kHTML),
    kCreateMathMLElement =
        kDefaultNodeFlags | kIsContainerFlag |
        static_cast<NodeFlags>(DOMNodeType::kElement) |
        static_cast<NodeFlags>(ElementNamespaceType::kMathML),
    kCreateSVGElement = kDefaultNodeFlags | kIsContainerFlag |
                        static_cast<NodeFlags>(DOMNodeType::kElement) |
                        static_cast<NodeFlags>(ElementNamespaceType::kSVG),
    kCreateDocument = kCreateContainer | kIsConnectedFlag,
    kCreateV0InsertionPoint = kCreateHTMLElement | kIsV0InsertionPointFlag,
    kCreateEditingText = kCreateText | kHasNameOrIsEditingTextFlag,
  };

  Node(TreeScope*, ConstructionType);

  void WillMoveToNewDocument(Document& old_document, Document& new_document);
  virtual void DidMoveToNewDocument(Document& old_document);

  void AddedEventListener(const AtomicString& event_type,
                          RegisteredEventListener&) override;
  void RemovedEventListener(const AtomicString& event_type,
                            const RegisteredEventListener&) override;
  DispatchEventResult DispatchEventInternal(Event&) override;

  bool HasRareData() const { return GetFlag(kHasRareDataFlag); }

  NodeRareData* RareData() const {
    SECURITY_DCHECK(HasRareData());
    return DataAsNodeRareData();
  }
  NodeRareData& EnsureRareData() {
    if (HasRareData())
      return *RareData();

    return CreateRareData();
  }

  void SetHasCustomStyleCallbacks() {
    SetFlag(true, kHasCustomStyleCallbacksFlag);
  }

  void SetTreeScope(TreeScope* scope) { tree_scope_ = scope; }
  void SetIsFinishedParsingChildren(bool value) {
    SetFlag(value, kIsFinishedParsingChildrenFlag);
  }

 private:
  // Gets nodeName without caching AtomicStrings. Used by
  // debugName. Compositor may call debugName from the "impl" thread
  // during "commit". The main thread is stopped at that time, but
  // it is not safe to cache AtomicStrings because those are
  // per-thread.
  virtual String DebugNodeName() const;

  Node* ToNode() final;

  bool IsUserActionElementActive() const;
  bool IsUserActionElementInActiveChain() const;
  bool IsUserActionElementDragged() const;
  bool IsUserActionElementHovered() const;
  bool IsUserActionElementFocused() const;
  bool IsUserActionElementHasFocusWithin() const;

  void UpdateDistributionInternal();
  void RecalcDistribution();

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

  virtual const ComputedStyle* VirtualEnsureComputedStyle(
      PseudoId = kPseudoIdNone);

  void TrackForDebugging();

  NodeRareData& CreateRareData();

  const HeapVector<Member<MutationObserverRegistration>>*
  MutationObserverRegistry();
  const HeapHashSet<Member<MutationObserverRegistration>>*
  TransientMutationObserverRegistry();

  NodeRareData* DataAsNodeRareData() const {
    DCHECK(HasRareData());
    return reinterpret_cast<NodeRareData*>(data_.Get());
  }
  NodeRenderingData* DataAsNodeRenderingData() const {
    DCHECK(!HasRareData());
    return reinterpret_cast<NodeRenderingData*>(data_.Get());
  }

  uint32_t node_flags_;
  Member<Node> parent_or_shadow_host_node_;
  Member<TreeScope> tree_scope_;
  Member<Node> previous_;
  Member<Node> next_;
  // When a node has rare data we move the layoutObject into the rare data.
  Member<NodeData> data_;
};

inline void Node::SetParentOrShadowHostNode(ContainerNode* parent) {
  DCHECK(IsMainThread());
  parent_or_shadow_host_node_ = reinterpret_cast<Node*>(parent);
}

inline ContainerNode* Node::ParentOrShadowHostNode() const {
  DCHECK(IsMainThread());
  return reinterpret_cast<ContainerNode*>(parent_or_shadow_host_node_.Get());
}

// Allow equality comparisons of Nodes by reference or pointer, interchangeably.
DEFINE_COMPARISON_OPERATORS_WITH_REFERENCES(Node)

CORE_EXPORT std::ostream& operator<<(std::ostream&, const Node&);
CORE_EXPORT std::ostream& operator<<(std::ostream&, const Node*);

}  // namespace blink

#if DCHECK_IS_ON()
// Outside the blink namespace for ease of invocation from gdb.
void showNode(const blink::Node*);
void showTree(const blink::Node*);
void showNodePath(const blink::Node*);
#endif

#endif  // THIRD_PARTY_BLINK_RENDERER_CORE_DOM_NODE_H_
