Commit 4aff7080 authored by Olli Pettay's avatar Olli Pettay
Browse files

Bug 1799354 - MutationRecord missing for Element.replaceChildren, r=peterv

parent 6579381c
Loading
Loading
Loading
Loading
+0 −1
Original line number Diff line number Diff line
@@ -3962,7 +3962,6 @@ void Element::InsertAdjacentHTML(const nsAString& aPosition,
  // listeners on the fragment that comes from the parser.
  nsAutoScriptBlockerSuppressNodeRemoved scriptBlocker;

  nsAutoMutationBatch mb(destination, true, false);
  switch (position) {
    case eBeforeBegin:
      destination->InsertBefore(*fragment, this, aError);
+7 −3
Original line number Diff line number Diff line
@@ -2143,7 +2143,7 @@ void nsINode::ReplaceChildren(nsINode* aNode, ErrorResult& aRv) {
  // Needed when used in combination with contenteditable (maybe)
  mozAutoDocUpdate updateBatch(OwnerDoc(), true);

  nsAutoMutationBatch mb(this, true, false);
  nsAutoMutationBatch mb(this, true, true);

  // Replace all with node within this.
  while (mFirstChild) {
@@ -2731,10 +2731,14 @@ nsINode* nsINode::ReplaceOrInsertBefore(bool aReplace, nsINode* aNewChild,
   */
  nsINode* result = aReplace ? aRefChild : aNewChild;
  if (nodeType == DOCUMENT_FRAGMENT_NODE) {
    if (!aReplace) {
    nsAutoMutationBatch* mutationBatch = nsAutoMutationBatch::GetCurrentBatch();
    if (mutationBatch && mutationBatch != &mb) {
      mutationBatch = nullptr;
    } else if (!aReplace) {
      mb.Init(this, true, true);
      mutationBatch = nsAutoMutationBatch::GetCurrentBatch();
    }
    nsAutoMutationBatch* mutationBatch = nsAutoMutationBatch::GetCurrentBatch();

    if (mutationBatch) {
      mutationBatch->RemovalDone();
      mutationBatch->SetPrevSibling(
+79 −0
Original line number Diff line number Diff line
@@ -121,6 +121,85 @@

  test_replacechildren(document.createElement('div'), 'Element');
  test_replacechildren(document.createDocumentFragment(), 'DocumentFragment');

  async_test(t => {
    let root = document.createElement("div");
    root.innerHTML = "<div id='a'>text<div id='b'>text2</div></div>";
    const a = root.firstChild;
    const b = a.lastChild;
    const txt = b.previousSibling;
    const txt2 = b.firstChild;

    const observer = new MutationObserver((mutations) => {

      assert_equals(mutations.length, 2, "mutations.length");

      assert_equals(mutations[0].target.id, "a", "Target of the removal");
      assert_equals(mutations[0].addedNodes.length, 0, "Should not have added nodes");
      assert_equals(mutations[0].removedNodes.length, 1, "Should have 1 removed node");
      assert_equals(mutations[0].removedNodes[0], txt, "Should have removed txt node");

      assert_equals(mutations[1].target.id, "b", "Target of the replaceChildren");
      assert_equals(mutations[1].removedNodes.length, 1, "Should have removed 1 node");
      assert_equals(mutations[1].removedNodes[0], txt2, "Should have removed txt2 node");
      assert_equals(mutations[1].addedNodes.length, 1, "Should have added a node");
      assert_equals(mutations[1].addedNodes[0], txt, "Should have added txt node");

      observer.disconnect();
      t.done();
    });

    observer.observe(a,  {
      subtree: true,
      childList: true
    });

    b.replaceChildren(txt);
  }, "There should be a MutationRecord for the node removed from another parent node.");

  async_test(t => {
    // This is almost the same test as above, but passes two nodes to replaceChildren.

    let root = document.createElement("div");
    root.innerHTML = "<div id='a'><div id='c'></div>text<div id='b'>text2</div></div>";
    const a = root.firstChild;
    const b = a.lastChild;
    const c = a.firstChild;
    const txt = b.previousSibling;
    const txt2 = b.firstChild;

    const observer = new MutationObserver((mutations) => {

      assert_equals(mutations.length, 3, "mutations.length");

      assert_equals(mutations[0].target.id, "a", "Target of the removal");
      assert_equals(mutations[0].addedNodes.length, 0, "Should not have added nodes");
      assert_equals(mutations[0].removedNodes.length, 1, "Should have 1 removed node");
      assert_equals(mutations[0].removedNodes[0], c, "Should have removed c node");

      assert_equals(mutations[1].target.id, "a", "Target of the removal");
      assert_equals(mutations[1].addedNodes.length, 0, "Should not have added nodes");
      assert_equals(mutations[1].removedNodes.length, 1, "Should have 1 removed node");
      assert_equals(mutations[1].removedNodes[0], txt, "Should have removed txt node");

      assert_equals(mutations[2].target.id, "b", "Target of the replaceChildren");
      assert_equals(mutations[2].removedNodes.length, 1, "Should have removed 1 node");
      assert_equals(mutations[2].removedNodes[0], txt2, "Should have removed txt2 node");
      assert_equals(mutations[2].addedNodes.length, 2, "Should have added a node");
      assert_equals(mutations[2].addedNodes[0], c, "Should have added c node");
      assert_equals(mutations[2].addedNodes[1], txt, "Should have added txt node");

      observer.disconnect();
      t.done();
    });

    observer.observe(a,  {
      subtree: true,
      childList: true
    });

    b.replaceChildren(c, txt);
  }, "There should be MutationRecords for the nodes removed from another parent node.");
</script>

</html>