// Copyright 2014 The Cobalt Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "cobalt/dom/node.h"

#include <memory>
#include <vector>

#include "base/lazy_instance.h"
#include "base/trace_event/trace_event.h"
#include "cobalt/base/polymorphic_downcast.h"
#include "cobalt/cssom/css_rule_visitor.h"
#include "cobalt/cssom/css_style_rule.h"
#include "cobalt/dom/cdata_section.h"
#include "cobalt/dom/comment.h"
#include "cobalt/dom/document.h"
#include "cobalt/dom/document_type.h"
#include "cobalt/dom/dom_exception.h"
#include "cobalt/dom/dom_settings.h"
#include "cobalt/dom/element.h"
#include "cobalt/dom/global_stats.h"
#include "cobalt/dom/html_collection.h"
#include "cobalt/dom/html_element_context.h"
#include "cobalt/dom/mutation_reporter.h"
#include "cobalt/dom/node_descendants_iterator.h"
#include "cobalt/dom/node_list.h"
#include "cobalt/dom/node_list_live.h"
#include "cobalt/dom/rule_matching.h"
#include "cobalt/dom/text.h"
#include "cobalt/dom/window.h"
#if defined(OS_STARBOARD)
#include "starboard/configuration.h"
#if SB_HAS(CORE_DUMP_HANDLER_SUPPORT)
#define HANDLE_CORE_DUMP
#include STARBOARD_CORE_DUMP_HANDLER_INCLUDE
#endif  // SB_HAS(CORE_DUMP_HANDLER_SUPPORT)
#endif  // defined(OS_STARBOARD)

namespace cobalt {
namespace dom {

// Diagram for DispatchEvent:
//  https://www.w3.org/TR/DOM-Level-3-Events/#event-flow
bool Node::DispatchEvent(const scoped_refptr<Event>& event) {
  DCHECK(event);
  DCHECK(!event->IsBeingDispatched());
  DCHECK(event->initialized_flag());

  TRACE_EVENT1("cobalt::dom", "Node::DispatchEvent", "event",
               event->type().c_str());

  if (!event || event->IsBeingDispatched() || !event->initialized_flag()) {
    return false;
  }

  // The event is now being dispatched. Track it in the global stats.
  GlobalStats::GetInstance()->StartJavaScriptEvent();

  scoped_refptr<Window> window;
  if (IsInDocument()) {
    DCHECK(node_document());
    window = node_document()->default_view();
  }

  if (window) {
    window->OnStartDispatchEvent(event);
  }

  typedef std::vector<scoped_refptr<Node> > Ancestors;
  Ancestors ancestors;
  for (Node* current = this->parent_node(); current != NULL;
       current = current->parent_node()) {
    ancestors.push_back(current);
  }

  event->set_target(this);

  // The capture phase: The event object propagates through the target's
  // ancestors from the Window to the target's parent. This phase is also known
  // as the capturing phase.
  event->set_event_phase(Event::kCapturingPhase);
  if (window) {
    window->FireEventOnListeners(event);
  }
  if (!event->propagation_stopped() && !ancestors.empty()) {
    for (Ancestors::reverse_iterator iter = ancestors.rbegin();
         iter != ancestors.rend() && !event->propagation_stopped(); ++iter) {
      (*iter)->FireEventOnListeners(event);
    }
  }

  if (!event->propagation_stopped()) {
    // The target phase: The event object arrives at the event object's event
    // target. This phase is also known as the at-target phase.
    event->set_event_phase(Event::kAtTarget);
    FireEventOnListeners(event);
  }

  // If the event type indicates that the event doesn't bubble, then the event
  // object will halt after completion of this phase.
  if (!event->propagation_stopped() && event->bubbles()) {
    if (!ancestors.empty()) {
      // The bubble phase: The event object propagates through the target's
      // ancestors in reverse order, starting with the target's parent and
      // ending with the Window. This phase is also known as the bubbling phase.
      event->set_event_phase(Event::kBubblingPhase);
      for (Ancestors::iterator iter = ancestors.begin();
           iter != ancestors.end() && !event->propagation_stopped(); ++iter) {
        (*iter)->FireEventOnListeners(event);
      }
      if (window) {
        window->FireEventOnListeners(event);
      }
    }
  }

  event->set_event_phase(Event::kNone);

  if (window) {
    window->OnStopDispatchEvent(event);
  }

  // The event has completed being dispatched. Stop tracking it in the global
  // stats.
  GlobalStats::GetInstance()->StopJavaScriptEvent();

  return !event->default_prevented();
}

// Algorithm for owner_document:
//   https://www.w3.org/TR/2015/WD-dom-20150618/#dom-node-ownerdocument
Document* Node::owner_document() const {
  // 1. If the context object is a document, return null.
  if (IsDocument()) {
    return NULL;
  }
  // 2. Return the node document.
  return node_document();
}

Element* Node::parent_element() const {
  return parent_ ? parent_->AsElement() : NULL;
}

bool Node::HasChildNodes() const { return first_child_.get() != NULL; }

scoped_refptr<NodeList> Node::child_nodes() const {
  return NodeListLive::CreateWithChildren(this);
}

// Algorithm for CloneNode:
//   https://www.w3.org/TR/2015/WD-dom-20150618/#dom-node-clonenode
scoped_refptr<Node> Node::CloneNode(bool deep) const {
  TRACK_MEMORY_SCOPE("DOM");
  TRACE_EVENT0("cobalt::dom", "Node::CloneNode()");
  scoped_refptr<Node> new_node = Duplicate();
  DCHECK(new_node);
  if (deep) {
    scoped_refptr<Node> child = first_child_;
    while (child) {
      scoped_refptr<Node> new_child = child->CloneNode(true);
      DCHECK(new_child);
      new_node->AppendChild(new_child);
      child = child->next_sibling_;
    }
  }
  return new_node;
}

bool Node::Contains(const scoped_refptr<Node>& other_node) const {
  const Node* candidate = other_node.get();
  while (candidate) {
    if (this == candidate) {
      return true;
    }
    candidate = candidate->parent_node();
  }
  return false;
}

// Algorithm for InsertBefore:
//   https://www.w3.org/TR/dom/#dom-node-insertbefore
scoped_refptr<Node> Node::InsertBefore(
    const scoped_refptr<Node>& new_child,
    const scoped_refptr<Node>& reference_child) {
  TRACE_EVENT0("cobalt::dom", "Node::InsertBefore()");
  // The insertBefore(node, child) method must return the result of
  // pre-inserting node into the context object before child.
  return PreInsert(new_child, reference_child);
}

// Algorithm for AppendChild:
//   https://www.w3.org/TR/dom/#dom-node-appendchild
scoped_refptr<Node> Node::AppendChild(const scoped_refptr<Node>& new_child) {
  TRACE_EVENT0("cobalt::dom", "Node::AppendChild()");
  // The appendChild(node) method must return the result of appending node to
  // the context object.
  // To append a node to a parent, pre-insert node into parent before null.
  return PreInsert(new_child, NULL);
}

// Algorithm for ReplaceChild:
//   https://www.w3.org/TR/dom/#dom-node-replacechild
scoped_refptr<Node> Node::ReplaceChild(const scoped_refptr<Node>& node,
                                       const scoped_refptr<Node>& child) {
  TRACE_EVENT0("cobalt::dom", "Node::ReplaceChild()");
  // The replaceChild(node, child) method must return the result of replacing
  // child with node within the context object.
  // To replace a child with node within a parent, run these steps:
  //   https://www.w3.org/TR/dom/#concept-node-replace

  // Custom, not in any spec.
  if (!node || !child) {
    // TODO: Throw JS ReferenceError.
    return NULL;
  }
  if (child == node) {
    return node;
  }

  // 1. If parent is not a Document, DocumentFragment, or Element node, throw a
  // "HierarchyRequestError".
  if (!IsDocument() && !IsElement()) {
    // TODO: Throw JS HierarchyRequestError.
    return NULL;
  }

  // 2. If node is a host-including inclusive ancestor of parent, throw a
  // "HierarchyRequestError".
  Node* ancestor = this;
  while (ancestor) {
    if (node == ancestor) {
      // TODO: Throw JS HierarchyRequestError.
      return NULL;
    }
    ancestor = ancestor->parent_;
  }

  // 3. If child's parent is not parent, throw a "NotFoundError" exception.
  if (child->parent_ != this) {
    // TODO: Throw JS NotFoundError.
    return NULL;
  }

  // 4. If node is not a DocumentFragment, DocumentType, Element, Text,
  // ProcessingInstruction, or Comment node, throw a "HierarchyRequestError".
  // Note: Since we support CDATASection, it is also included here, so the only
  // type that is excluded is document.
  if (node->IsDocument()) {
    // TODO: Throw JS HierarchyRequestError.
    return NULL;
  }

  // 5. If either node is a Text node and parent is a document, or node is a
  // doctype and parent is not a document, throw a "HierarchyRequestError".
  if ((node->IsText() && IsDocument()) ||
      (node->IsDocumentType() && !IsDocument())) {
    // TODO: Throw JS HierarchyRequestError.
    return NULL;
  }

  // 6. Not needed by Cobalt.

  // 7. Let reference child be child's next sibling.
  scoped_refptr<Node> reference_child = child->next_sibling_;

  // 8. If reference child is node, set it to node's next sibling.
  if (reference_child == node) {
    reference_child = node->next_sibling_;
  }

  // 9. Adopt node into parent's node document.
  node->AdoptIntoDocument(node_document_.get());

  // 10. Remove child from its parent with the suppress observers flag set.
  Remove(child, true);

  // 11. Insert node into parent before reference child with the suppress
  // observers flag set.
  Insert(node, reference_child, true);

  // 12. Let nodes be node's children if node is a DocumentFragment node, and a
  // list containing solely node otherwise.
  // 13. Queue a mutation record of "childList" for target parent with
  // addedNodes nodes, removedNodes a list solely containing child, nextSibling
  // reference child, and previousSibling child's previous sibling.
  MutationReporter mutation_reporter(this, GatherInclusiveAncestorsObservers());
  scoped_refptr<dom::NodeList> added_nodes = new dom::NodeList();
  added_nodes->AppendNode(node);
  scoped_refptr<dom::NodeList> removed_nodes = new dom::NodeList();
  removed_nodes->AppendNode(child);
  mutation_reporter.ReportChildListMutation(
      added_nodes, removed_nodes,
      child->previous_sibling_ /* previous_sibling */,
      reference_child /* next_sibling */);

  return child;
}

// Algorithm for RemoveChild:
//   https://www.w3.org/TR/dom/#dom-node-removechild
scoped_refptr<Node> Node::RemoveChild(const scoped_refptr<Node>& node) {
  TRACE_EVENT0("cobalt::dom", "Node::RemoveChild()");
  // The removeChild(child) method must return the result of pre-removing child
  // from the context object.
  return PreRemove(node);
}

scoped_refptr<HTMLCollection> Node::children() {
  if (!children_collection_) {
    children_collection_ = HTMLCollection::CreateWithChildElements(this);
  }
  return children_collection_;
}

Element* Node::first_element_child() const {
  Node* child = first_child();
  while (child) {
    if (child->IsElement()) {
      return child->AsElement();
    }
    child = child->next_sibling();
  }
  return NULL;
}

Element* Node::last_element_child() const {
  Node* child = last_child();
  while (child) {
    if (child->IsElement()) {
      return child->AsElement();
    }
    child = child->previous_sibling();
  }
  return NULL;
}

unsigned int Node::child_element_count() const {
  unsigned int num_elements = 0;
  const Node* child = first_child();
  while (child) {
    if (child->IsElement()) {
      ++num_elements;
    }
    child = child->next_sibling();
  }
  return num_elements;
}

scoped_refptr<Element> Node::QuerySelector(const std::string& selectors) {
  return dom::QuerySelector(
      this, selectors, node_document_->html_element_context()->css_parser());
}

scoped_refptr<NodeList> Node::QuerySelectorAll(const std::string& selectors) {
  return dom::QuerySelectorAll(
      this, selectors, node_document_->html_element_context()->css_parser());
}

Element* Node::previous_element_sibling() const {
  Node* sibling = previous_sibling();
  while (sibling) {
    if (sibling->IsElement()) {
      return sibling->AsElement();
    }
    sibling = sibling->previous_sibling();
  }
  return NULL;
}

Element* Node::next_element_sibling() const {
  Node* sibling = next_sibling();
  while (sibling) {
    if (sibling->IsElement()) {
      return sibling->AsElement();
    }
    sibling = sibling->next_sibling();
  }
  return NULL;
}

// Algorithm for AdoptIntoDocument:
//   https://www.w3.org/TR/dom/#concept-node-adopt
void Node::AdoptIntoDocument(Document* document) {
  TRACE_EVENT0("cobalt::dom", "Node::AdoptIntoDocument()");
  DCHECK(!IsDocument());
  if (!document) {
    return;
  }

  // 1, Not needed by Cobalt.

  // 2. If node's parent is not null, remove node from its parent.
  if (parent_) {
    parent_->RemoveChild(this);
  }

  // 3. Set node's inclusive descendants's node document to document.
  node_document_ = base::AsWeakPtr(document);
  NodeDescendantsIterator it(this);
  Node* descendant = it.First();
  while (descendant) {
    descendant->node_document_ = base::AsWeakPtr(document);
    descendant = it.Next();
  }

  // 4. Not needed by Cobalt.
}

Node* Node::GetRootNode() {
  Node* root = this;
  while (root->parent_node()) {
    root = root->parent_node();
  }
  return root;
}

CDATASection* Node::AsCDATASection() { return NULL; }

Comment* Node::AsComment() { return NULL; }

Document* Node::AsDocument() { return NULL; }

DocumentType* Node::AsDocumentType() { return NULL; }

Element* Node::AsElement() { return NULL; }

Text* Node::AsText() { return NULL; }

const base::DebuggerHooks& Node::debugger_hooks() const {
  return base::polymorphic_downcast<DOMSettings*>(
             node_document()->html_element_context()->environment_settings())
      ->debugger_hooks();
}

void Node::TraceMembers(script::Tracer* tracer) {
  EventTarget::TraceMembers(tracer);

  tracer->Trace(node_document_);
  tracer->Trace(parent_);
  tracer->Trace(previous_sibling_);
  tracer->Trace(last_child_);
  tracer->Trace(first_child_);
  tracer->Trace(next_sibling_);
  tracer->Trace(registered_observers_);
  tracer->Trace(children_collection_);
}

Node::Node(Document* document)
    : Node(document->html_element_context(), document) {}

Node::Node(HTMLElementContext* html_element_context, Document* document)
    : EventTarget(html_element_context->environment_settings()),
      node_document_(base::AsWeakPtr(document)),
      parent_(NULL),
      previous_sibling_(NULL),
      last_child_(NULL),
      inserted_into_document_(false),
      node_generation_(kInitialNodeGeneration),
      ALLOW_THIS_IN_INITIALIZER_LIST(registered_observers_(this)) {
  DCHECK(node_document_);
  GlobalStats::GetInstance()->Add(this);
}

Node::~Node() {
  Node* node = last_child_;
  while (node) {
    node->parent_ = NULL;
    node->next_sibling_ = NULL;

    Node* previous_sibling = node->previous_sibling_;
    node->previous_sibling_ = NULL;
    node = previous_sibling;
  }
  GlobalStats::GetInstance()->Remove(this);
}

void Node::OnInsertedIntoDocument() {
  DCHECK(node_document_);
  DCHECK(!inserted_into_document_);
  inserted_into_document_ = true;

  Node* child = first_child_.get();
  while (child) {
    child->OnInsertedIntoDocument();
    child = child->next_sibling_.get();
  }
}

void Node::OnRemovedFromDocument() {
  DCHECK(inserted_into_document_);
  inserted_into_document_ = false;

  Node* child = first_child_.get();
  while (child) {
    child->OnRemovedFromDocument();
    child = child->next_sibling_.get();
  }
}

void Node::MarkNotDisplayedOnNodeAndDescendants() {
  MarkNotDisplayedOnDescendants();
}

void Node::PurgeCachedBackgroundImagesOfNodeAndDescendants() {
  PurgeCachedBackgroundImagesOfDescendants();
}

void Node::InvalidateComputedStylesOfNodeAndDescendants() {
  InvalidateComputedStylesOfDescendants();
}

void Node::InvalidateLayoutBoxesOfNodeAndAncestors() {
  InvalidateLayoutBoxesOfAncestors();
}

void Node::InvalidateLayoutBoxesOfNodeAndDescendants() {
  InvalidateLayoutBoxesOfDescendants();
}

void Node::MarkNotDisplayedOnDescendants() {
  Node* child = first_child_.get();
  while (child) {
    child->MarkNotDisplayedOnNodeAndDescendants();
    child = child->next_sibling_.get();
  }
}

void Node::PurgeCachedBackgroundImagesOfDescendants() {
  Node* child = first_child_.get();
  while (child) {
    child->PurgeCachedBackgroundImagesOfNodeAndDescendants();
    child = child->next_sibling_.get();
  }
}

void Node::InvalidateComputedStylesOfDescendants() {
  Node* child = first_child_.get();
  while (child) {
    child->InvalidateComputedStylesOfNodeAndDescendants();
    child = child->next_sibling_.get();
  }
}

void Node::InvalidateLayoutBoxesOfAncestors() {
  if (parent_) {
    parent_->InvalidateLayoutBoxesOfNodeAndAncestors();
  }
}

void Node::InvalidateLayoutBoxesOfDescendants() {
  Node* child = first_child_;
  while (child) {
    child->InvalidateLayoutBoxesOfNodeAndDescendants();
    child = child->next_sibling_.get();
  }
}

void Node::UpdateGenerationForNodeAndAncestors() {
  if (++node_generation_ == kInvalidNodeGeneration) {
    node_generation_ = kInitialNodeGeneration;
  }
  if (parent_) {
    parent_->UpdateGenerationForNodeAndAncestors();
  }
}

std::unique_ptr<Node::RegisteredObserverVector>
Node::GatherInclusiveAncestorsObservers() {
  std::unique_ptr<RegisteredObserverVector> inclusive_observers(
      new RegisteredObserverVector());
  Node* current = this;
  while (current) {
    const RegisteredObserverList::RegisteredObserverVector& node_observers =
        current->registered_observers_.registered_observers();
    inclusive_observers->insert(inclusive_observers->end(),
                                node_observers.begin(), node_observers.end());
    current = current->parent_;
  }
  return inclusive_observers;
}

// Algorithm for EnsurePreInsertionValidity:
//   https://www.w3.org/TR/dom/#concept-node-ensure-pre-insertion-validity
bool Node::EnsurePreInsertionValidity(const scoped_refptr<Node>& node,
                                      const scoped_refptr<Node>& child) {
  if (!node) {
    return false;
  }

  // 1. If parent is not a Document, DocumentFragment, or Element node, throw a
  // "HierarchyRequestError".
  if (!IsDocument() && !IsElement()) {
    // TODO: Throw JS HierarchyRequestError.
    return false;
  }

  // 2. If node is a host-including inclusive ancestor of parent, throw a
  // "HierarchyRequestError".
  Node* ancestor = this;
  while (ancestor) {
    if (node == ancestor) {
      // TODO: Throw JS HierarchyRequestError.
      return false;
    }
    ancestor = ancestor->parent_;
  }

  // 3. If child is not null and its parent is not parent, throw a
  // "NotFoundError" exception.
  if (child && child->parent_ != this) {
    // TODO: Throw JS NotFoundError.
    return false;
  }

  // 4. If node is not a DocumentFragment, DocumentType, Element, Text,
  // ProcessingInstruction, or Comment node, throw a "HierarchyRequestError".
  // Note: Since we support CDATASection, it is also included here, so the only
  // type that is excluded is document.
  if (node->IsDocument()) {
    // TODO: Throw JS HierarchyRequestError.
    return false;
  }

  // 5. If either node is a Text node and parent is a document, or node is a
  // doctype and parent is not a document, throw a "HierarchyRequestError".
  if ((node->IsText() && IsDocument()) ||
      (node->IsDocumentType() && !IsDocument())) {
    // TODO: Throw JS HierarchyRequestError.
    return false;
  }

  // 6. Not needed by Cobalt.

  return true;
}

// Algorithm for PreInsert:
//   https://www.w3.org/TR/dom/#concept-node-pre-insert
scoped_refptr<Node> Node::PreInsert(const scoped_refptr<Node>& node,
                                    const scoped_refptr<Node>& child) {
  TRACE_EVENT0("cobalt::dom", "Node::PreInsert()");
  // 1. Ensure pre-insertion validity of node into parent before child.
  if (!EnsurePreInsertionValidity(node, child)) {
    return NULL;
  }

  // 2. Let reference child be child.
  // 3. If reference child is node, set it to node's next sibling.
  // 4. Adopt node into parent's node document.
  // 5. Insert node into parent before reference child.
  node->AdoptIntoDocument(node_document_.get());
  Insert(node, child == node ? child->next_sibling_ : child, false);

  // 6. Return node.
  return node;
}

// Algorithm for Insert:
//   https://www.w3.org/TR/dom/#concept-node-insert
void Node::Insert(const scoped_refptr<Node>& node,
                  const scoped_refptr<Node>& child, bool suppress_observers) {
  TRACE_EVENT0("cobalt::dom", "Node::Insert()");
  // 1. 2. Not needed by Cobalt.
  // 3. Let nodes be node's children if node is a DocumentFragment node, and a
  // list containing solely node otherwise.
  // 4. 5. Not needed by Cobalt.
  // 6. If suppress observers flag is unset, queue a mutation record of
  //    "childList" for parent with addedNodes nodes, nextSibling child, and
  //    previousSibling child's previous sibling or parent's last child if
  //    child is null.
  // 7. For each newNode in nodes, in tree order, run these substeps:
  //   1. Insert newNode into parent before child or at the end of parent if
  //   child is null.
  //   2. Run the insertion steps with newNode.

  if (!suppress_observers) {
    std::unique_ptr<RegisteredObserverVector> observers =
        GatherInclusiveAncestorsObservers();
    if (!observers->empty()) {
      MutationReporter mutation_reporter(this, std::move(observers));
      scoped_refptr<dom::NodeList> added_nodes = new dom::NodeList();
      added_nodes->AppendNode(node);
      mutation_reporter.ReportChildListMutation(
          added_nodes, NULL,
          child ? child->previous_sibling_
                : this->last_child_ /* previous_sibling */,
          child /* next_sibling */);
    }
  }

  node->parent_ = this;

  scoped_refptr<Node> next_sibling = child;
  Node* previous_sibling =
      next_sibling ? next_sibling->previous_sibling_ : last_child_;

  if (previous_sibling) {
    previous_sibling->next_sibling_ = node;
  } else {
    first_child_ = node;
  }
  node->previous_sibling_ = previous_sibling;

  if (next_sibling) {
    next_sibling->previous_sibling_ = node;
  } else {
    last_child_ = node;
  }
  node->next_sibling_ = next_sibling;

  // Custom, not in any spec.

  OnMutation();
  node->UpdateGenerationForNodeAndAncestors();

  // Invalidate the layout boxes of the new parent as a result of its children
  // being changed.
  // NOTE: The added node does not have any invalidations done, because they
  // occur on the remove and are guaranteed to not be needed at this point.
  InvalidateLayoutBoxesOfNodeAndAncestors();

  if (inserted_into_document_) {
    node->OnInsertedIntoDocument();
    Document* document = node_document();
    if (document) {
      document->OnDOMMutation();
    }
  }
}

// Algorithm for PreRemove:
//   https://www.w3.org/TR/dom/#concept-node-pre-remove
scoped_refptr<Node> Node::PreRemove(const scoped_refptr<Node>& child) {
  TRACE_EVENT0("cobalt::dom", "Node::PreRemove()");
  // 1. If child's parent is not parent, throw a "NotFoundError" exception.
  if (!child || child->parent_ != this) {
    // TODO: Throw JS NotFoundError.
    return NULL;
  }

  // 2. Remove child from parent.
  Remove(child, false);

  // 3. Return child.
  return child;
}

// Algorithm for Remove:
//   https://www.w3.org/TR/dom/#concept-node-remove
void Node::Remove(const scoped_refptr<Node>& node, bool suppress_observers) {
  DCHECK(node);
  TRACE_EVENT0("cobalt::dom", "Node::Remove()");

  OnMutation();
  node->UpdateGenerationForNodeAndAncestors();

  // Invalidate the layout boxes of the previous parent as a result of its
  // children being changed.
  InvalidateLayoutBoxesOfNodeAndAncestors();

  // Purge any cached background images now that this node and its descendants
  // are no longer in the tree, so that the images can be released from the
  // resource cache.
  node->PurgeCachedBackgroundImagesOfNodeAndDescendants();

  // Invalidate the styles and layout boxes of the node being removed from
  // the tree. These are no longer valid as a result of the child and its
  // descendants losing their inherited styles.
  node->InvalidateComputedStylesOfNodeAndDescendants();
  node->InvalidateLayoutBoxesOfNodeAndDescendants();

  bool was_inserted_to_document = node->inserted_into_document_;
  if (was_inserted_to_document) {
    node->OnRemovedFromDocument();
    node->MarkNotDisplayedOnNodeAndDescendants();
  }

  // 1. 5. Not needed by Cobalt.
  // 6. Let oldPreviousSibling be node's previous sibling
  // 7. If suppress observers flag is unset, queue a mutation record of
  // "childList" for parent with removedNodes a list solely containing node,
  // nextSibling node's next sibling, and previousSibling oldPreviousSibling.
  // 8. For each ancestor ancestor of node, if ancestor has any registered
  // observers whose options's subtree is true, then for each such registered
  // observer registered, append a transient registered observer whose observer
  // and options are identical to those of registered and source which is
  // registered to node's list of registered observers.
  // 9. Remove node from its parent.
  // 10. Run the removing steps with node, parent, and oldPreviousSibling.

  std::unique_ptr<RegisteredObserverVector> observers =
      GatherInclusiveAncestorsObservers();
  if (!observers->empty()) {
    // Step 7 - Queue a mutation record.
    if (!suppress_observers) {
      MutationReporter mutation_reporter(this, std::move(observers));
      scoped_refptr<dom::NodeList> removed_nodes = new dom::NodeList();
      removed_nodes->AppendNode(node);
      mutation_reporter.ReportChildListMutation(
          NULL, removed_nodes, node->previous_sibling_ /* previous_sibling */,
          node->next_sibling_ /* next_sibling */);
    }
    // TODO: transient registered observers.
  }

  if (node->previous_sibling_) {
    node->previous_sibling_->next_sibling_ = node->next_sibling_;
  } else {
    first_child_ = node->next_sibling_;
  }
  if (node->next_sibling_) {
    node->next_sibling_->previous_sibling_ = node->previous_sibling_;
  } else {
    last_child_ = node->previous_sibling_;
  }
  node->parent_ = NULL;
  node->previous_sibling_ = NULL;
  node->next_sibling_ = NULL;

  // Custom, not in any spec.

  if (was_inserted_to_document) {
    scoped_refptr<Document> document = node->owner_document();
    if (document) {
      document->OnDOMMutation();
    }
  }
}

// Algorithm for ReplaceAll:
//   https://www.w3.org/TR/dom/#concept-node-replace-all
void Node::ReplaceAll(const scoped_refptr<Node>& node) {
  TRACE_EVENT0("cobalt::dom", "Node::ReplaceAll()");
  // 1. If node is not null, adopt node into parent's node document.
  if (node) {
    node->AdoptIntoDocument(this->node_document());
  }

  // 2. Let removedNodes be parent's children.
  scoped_refptr<NodeList> removed_nodes = new NodeList();
  scoped_refptr<Node> next_child = first_child_;
  while (next_child) {
    removed_nodes->AppendNode(next_child);
    next_child = next_child->next_sibling();
  }

  // 3. Let addedNodes be the empty list if node is null, node's children if
  //    node is a DocumentFragment node, and a list containing node otherwise.
  scoped_refptr<NodeList> added_nodes = new NodeList();
  if (node) {
    added_nodes->AppendNode(node);
  }

  // 4. Remove all parent's children, in tree order, with the suppress observers
  //    flag set.
  while (HasChildNodes()) {
    Remove(first_child(), true);
  }

  // 5. If node is not null, insert node into parent before null with the
  //    suppress observers flag set.
  if (node) {
    Insert(node, NULL, true);
  }

  // 6. Queue a mutation record of "childList" for parent with addedNodes
  //    addedNodes and removedNodes removedNodes.
  std::unique_ptr<RegisteredObserverVector> observers =
      GatherInclusiveAncestorsObservers();
  if (!observers->empty()) {
    MutationReporter mutation_reporter(this, std::move(observers));
    scoped_refptr<dom::NodeList> new_added_nodes = new dom::NodeList();
    if (node) {
      new_added_nodes->AppendNode(node);
    }
    if (new_added_nodes->length() > 0 || removed_nodes->length() > 0) {
      mutation_reporter.ReportChildListMutation(new_added_nodes, removed_nodes,
                                                NULL /* previous_sibling */,
                                                NULL /* next_sibling */);
    }
  }
}

}  // namespace dom
}  // namespace cobalt
