replaceChild method

  1. @override
Node? replaceChild(
  1. Node newNode,
  2. Node oldNode
)
override

Implementation

@override
Node? replaceChild(Node newNode, Node oldNode) {
  // https://dom.spec.whatwg.org/#concept-node-replace
  // Step 2 to 6 are already done at C++ side.

  bool isOldChildConnected = oldNode.isConnected;

  // 7. Let reference child be child’s next sibling.
  Node? next = oldNode.nextSibling;

  // 8. If reference child is node, set it to node’s next sibling.
  if (next == newNode) next = newNode.nextSibling;

  // 10. Adopt node into parent’s node document.
  // Though the following CollectChildrenAndRemoveFromOldParent() also calls
  // RemoveChild(), we'd like to call RemoveChild() here to make a separated
  // MutationRecord.
  ContainerNode? newChildParent = newNode.parentNode;
  if (newChildParent != null) {
    newChildParent.removeChild(newNode);
  }

  // 9. Let previousSibling be child’s previous sibling.
  // 11. Let removedNodes be the empty list.
  // 15. Queue a mutation record of "childList" for target parent with
  // addedNodes nodes, removedNodes removedNodes, nextSibling reference child,
  // and previousSibling previousSibling.

  // 12. If child’s parent is not null, run these substeps:
  //    1. Set removedNodes to a list solely containing child.
  //    2. Remove child from its parent with the suppress observers flag set.
  ContainerNode? oldChildParent = oldNode.parentNode;
  if (oldChildParent != null) {
    oldChildParent.removeChild(oldNode);
  }

  List<Node> targets = [];

  // 13. Let nodes be node’s children if node is a DocumentFragment node, and
  // a list containing solely node otherwise.
  if (!collectChildrenAndRemoveFromOldParent(newNode, targets)) return oldNode;
  // 10. Adopt node into parent’s node document.
  // 14. Insert node into parent before reference child with the suppress
  // observers flag set.
  if (next != null) {
    _insertNode(targets, next, _adoptAndInsertBefore);
  } else {
    _insertNode(targets, null, _adoptAndAppendChild);
  }

  if (isOldChildConnected) {
    oldNode.disconnectedCallback();
    newNode.connectedCallback();
  }

  didInsertNode(targets, next);

  return oldNode;
}