Re: [whatwg/dom] MutationObserver callbacks happen in unexpected order. (Issue #1105)

WebReflection left a comment (whatwg/dom#1105)

This thread has been mentioned again and I forgot to answer to https://github.com/whatwg/dom/issues/1105#issuecomment-1231127985 so, for history and clarification sake, let's put my advice in practice:

```html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <script type="module">
    new MutationObserver(mutationList => {
      for (const { addedNodes, removedNodes, target } of mutationList) {
        for (const node of removedNodes) {
          // node.parentNode *might* be different from `target`
          console.log(`disconnected from ${target.localName}#${target.id}`);
        }
        for (const node of addedNodes) {
          // node.parentNode *might* be different from `target`
          console.log(`connected to ${target.localName}#${target.id}`);
        }
      }
    }).observe(
      document.body,
      {
        childList: true,
        subtree: true
      }
    );

    const target = document.createElement('hr');
    a.appendChild(target);
    b.appendChild(target);
    c.appendChild(target);

    // connected to div#a
    // disconnected from div#a
    // connected to div#b
    // disconnected from div#b
    // connected to div#c
  </script>
</head>
<body>
  <div id="a"></div>
  <div id="b"></div>
  <div id="c"></div>
</body>
</html>
```

The order is correct, all operations are logged exactly as these happened in the order these happened and if we're asking for anything synchronous that order would bill identical/the same.

If all mutations were synchronous then side effects happening when a node is moved in between nodes (i.e. inside B) then B could do operations and *the net result* makes no sense because in B nobody can know if the node will be moved into C after so that having this API asynchronous makes that possible by comparing the moved node `parentNode` VS the `target` node provided by the mutation *Record*.

Accordingly, the OP of this issue is solved because:

  * the order is not unexpected, it's predictable and correct as long as removed nodes are looped before added nodes
  * if this API was synchronous, understanding the node has been moved again to obtain that "*net 0*" would not be possible, so that the requirement is somehow contradicting the current state of affairs

I hope this helps whoever needs to really track mutations in a way that mimics sync API but that actually provides even more value for complex use cases.

-- 
Reply to this email directly or view it on GitHub:
https://github.com/whatwg/dom/issues/1105#issuecomment-2834151956
You are receiving this because you are subscribed to this thread.

Message ID: <whatwg/dom/issues/1105/2834151956@github.com>

Received on Monday, 28 April 2025 06:51:35 UTC