To insert a node node into a node parent before null or a node child, with an optional boolean suppressObservers (default false):

  1. Let nodes be node’s children, if node is a DocumentFragment node; otherwise « node ».

  2. Let count be nodes’s size.

  3. If count is 0, then return.

  4. If node is a DocumentFragment node:

    1. Remove its children with suppressObservers set to true.

    2. Queue a tree mutation record for node with « », nodes, null, and null.

      This step intentionally does not pay attention to suppressObservers.

  5. If child is non-null:

    1. For each live range whose start node is parent and start offset is greater than child’s index: increase its start offset by count.

    2. For each live range whose end node is parent and end offset is greater than child’s index: increase its end offset by count.

  6. Let previousSibling be child’s previous sibling or parent’s last child if child is null.

  7. For each node in nodes, in tree order:

    1. Adopt node into parent’s node document.

    2. If child is null, then append node to parent’s children.

    3. Otherwise, insert node into parent’s children before child’s index.

    4. If parent is a shadow host whose shadow root’s slot assignment is "named" and node is a slottable, then assign a slot for node.

    5. If parent’s root is a shadow root, and parent is a slot whose assigned nodes is the empty list, then run signal a slot change for parent.

    6. Run assign slottables for a tree with node’s root.

    7. For each shadow-including inclusive descendant inclusiveDescendant of node, in shadow-including tree order:

      1. Run the insertion steps with inclusiveDescendant.

      2. If inclusiveDescendant is not connected, then continue.

      3. If inclusiveDescendant is an element and inclusiveDescendant’s custom element registry is non-null:

        1. If inclusiveDescendant’s custom element registry’s is scoped is true, then append inclusiveDescendant’s node document to inclusiveDescendant’s custom element registry’s scoped document set.

        2. If inclusiveDescendant is custom, then enqueue a custom element callback reaction with inclusiveDescendant, callback name "connectedCallback", and « ».

        3. Otherwise, try to upgrade inclusiveDescendant.

          If this successfully upgrades inclusiveDescendant, its connectedCallback will be enqueued automatically during the upgrade an element algorithm.

      4. Otherwise, if inclusiveDescendant is a shadow root, inclusiveDescendant’s custom element registry is non-null, and inclusiveDescendant’s custom element registry’s is scoped is true, then append inclusiveDescendant’s node document to inclusiveDescendant’s custom element registry’s scoped document set.

  8. If suppressObservers is false, then queue a tree mutation record for parent with nodes, « », previousSibling, and child.

  9. Run the children changed steps for parent.

  10. Let staticNodeList be a list of nodes, initially « ».

    We collect all nodes before calling the post-connection steps on any one of them, instead of calling the post-connection steps while we’re traversing the node tree. This is because the post-connection steps can modify the tree’s structure, making live traversal unsafe, possibly leading to the post-connection steps being called multiple times on the same node.

  11. For each node of nodes, in tree order:

    1. For each shadow-including inclusive descendant inclusiveDescendant of node, in shadow-including tree order: append inclusiveDescendant to staticNodeList.

  12. For each node of staticNodeList: if node is connected, then run the post-connection steps with node.