Bug 1455903 - Make EditorBase::CloneAttributesWithTransaction() set sourceElement to aSourceElement rather than aDestElement r=m_kato
authorMasayuki Nakano <masayuki@d-toybox.com>
Mon, 23 Apr 2018 18:02:50 +0900
changeset 471352 be5ba8b6dea2d025e0e1f7268336e1d1f0c32399
parent 471351 74e2c5b3e825a5596c004056e92bb0461a552477
child 471353 3577a6b9b1a13a0dfd93073f4ef9209c08764eb4
push id1728
push userjlund@mozilla.com
push dateMon, 18 Jun 2018 21:12:27 +0000
treeherdermozilla-release@c296fde26f5f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersm_kato
bugs1455903, 1451672
milestone61.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1455903 - Make EditorBase::CloneAttributesWithTransaction() set sourceElement to aSourceElement rather than aDestElement r=m_kato This is simple mistake of bug 1451672. EditorBase::CloneAttributesWithTransaction() sets both sourceElement and destElement to aDestElement, but of course, it should set sourceElement to aSourceElement. Additionally, this patch adds mozilla specific web-platform tests to check attribute cloning with basic edit operation. MozReview-Commit-ID: GM1VjRHG7C3
editor/libeditor/EditorBase.cpp
testing/web-platform/meta/MANIFEST.json
testing/web-platform/mozilla/meta/MANIFEST.json
testing/web-platform/mozilla/meta/editor/cloning_attributes.html.ini
testing/web-platform/mozilla/tests/editor/cloning_attributes.html
--- a/editor/libeditor/EditorBase.cpp
+++ b/editor/libeditor/EditorBase.cpp
@@ -2553,17 +2553,17 @@ EditorBase::CloneAttributesWithTransacti
   // Use transaction system for undo only if destination is already in the
   // document
   Element* rootElement = GetRoot();
   if (NS_WARN_IF(!rootElement)) {
     return;
   }
 
   OwningNonNull<Element> destElement(aDestElement);
-  OwningNonNull<Element> sourceElement(aDestElement);
+  OwningNonNull<Element> sourceElement(aSourceElement);
   bool isDestElementInBody = rootElement->Contains(destElement);
 
   // Clear existing attributes
   RefPtr<nsDOMAttributeMap> destAttributes = destElement->Attributes();
   while (RefPtr<Attr> attr = destAttributes->Item(0)) {
     if (isDestElementInBody) {
       RemoveAttributeWithTransaction(destElement,
                                      *attr->NodeInfo()->NameAtom());
--- a/testing/web-platform/meta/MANIFEST.json
+++ b/testing/web-platform/meta/MANIFEST.json
@@ -554892,29 +554892,29 @@
    "49bc4349b4e7a85d88cacd54227355aa986535f1",
    "testharness"
   ],
   "fetch/api/request/request-init-002.html": [
    "e6647394acca551e354b27c16013ef713c8ba64e",
    "testharness"
   ],
   "fetch/api/request/request-init-003.sub.html": [
-   "f3084c91090e9c86c5586e947e63baf4990b582e",
+   "98e47b378d13b9b94601eb7c6035c457d53151ca",
    "testharness"
   ],
   "fetch/api/request/request-keepalive-quota.html": [
    "0b9786a3878a361ba8ec3291216d475bd5148541",
    "testharness"
   ],
   "fetch/api/request/request-keepalive.html": [
    "e6c2afd6cef41d358016d4d021b7c3e0e1185704",
    "testharness"
   ],
   "fetch/api/request/request-structure.html": [
-   "cc2471d809fcf7842c38762614c656bb45bb0fc7",
+   "b01d5ae0d56c22d2b86e0efd2cf64ac938770b11",
    "testharness"
   ],
   "fetch/api/request/request-type-attribute-historical.html": [
    "68620f3ea16b7ae1a9f1efde1cd0bb47f1150b9f",
    "testharness"
   ],
   "fetch/api/request/resources/cache.py": [
    "3cd7d5191fe33b2f2dab571a4b006d8332fdf42e",
@@ -557324,17 +557324,17 @@
    "fb63063e0ff1ca6aaa350fae9b8f01bed5f9771f",
    "testharness"
   ],
   "html/browsers/browsing-the-web/scroll-to-fragid/navigate-helpers.js": [
    "5b318196cb31c35e1b39eccd9e6a131a882f1a90",
    "support"
   ],
   "html/browsers/browsing-the-web/scroll-to-fragid/replacement-enabled.html": [
-   "99a355c63562aded2e2b252d989de332e8c12a0d",
+   "c74f0c4c6b2a11d51b87ef7a14bc68c4b0fe0ecd",
    "testharness"
   ],
   "html/browsers/browsing-the-web/scroll-to-fragid/scroll-frag-percent-encoded.html": [
    "ac172eb5c05ee24b8e3059cbc68851729f1be943",
    "testharness"
   ],
   "html/browsers/browsing-the-web/scroll-to-fragid/scroll-to-anchor-name.html": [
    "9bc91bc9bb368e8bf42810ed8aed936a6c9d581a",
@@ -557592,17 +557592,17 @@
    "96bef5eb28559046686f81a7885471e9f4b053a0",
    "support"
   ],
   "html/browsers/browsing-the-web/unloading-documents/unload/007-2.html": [
    "9d9603c8581e26a68022e5781252fb7a19550b49",
    "support"
   ],
   "html/browsers/browsing-the-web/unloading-documents/unload/007.html": [
-   "bfb39279cb1e49176f4c77e0253dd92642f53f34",
+   "ac12d25b792d284b377e889565351f626df7627e",
    "testharness"
   ],
   "html/browsers/browsing-the-web/unloading-documents/unload/008-1.html": [
    "4cb08d9f14425399b36352bb813c88c0403c951c",
    "support"
   ],
   "html/browsers/browsing-the-web/unloading-documents/unload/008.html": [
    "cadd67773d3bf25399a0207ae6d1fa6684dd1781",
@@ -603580,17 +603580,17 @@
    "9745045131b5b37094470dad2b59fa85c0fd1f0f",
    "testharness"
   ],
   "upgrade-insecure-requests/image-upgrade.https.html": [
    "22f2a05853efc4977d7c427f80898cd8671f3aaa",
    "testharness"
   ],
   "upgrade-insecure-requests/link-upgrade.sub.https.html": [
-   "314f8cbd0a8dd96da33d450a3b4b6b2317cad68f",
+   "d8279d5c8b46259643bd960374398ea4d8a455f8",
    "testharness"
   ],
   "upgrade-insecure-requests/link-upgrade/basic-link-no-upgrade.sub.html": [
    "05d450051981b22ac2b9e903b60435ca695b3ad2",
    "support"
   ],
   "upgrade-insecure-requests/link-upgrade/basic-link-no-upgrade.sub.html.headers": [
    "658f2c2be22add1a5be72b1e19ba340d024a4832",
--- a/testing/web-platform/mozilla/meta/MANIFEST.json
+++ b/testing/web-platform/mozilla/meta/MANIFEST.json
@@ -464,16 +464,22 @@
     ]
    ],
    "dom/throttling/throttling-ws.window.js": [
     [
      "/_mozilla/dom/throttling/throttling-ws.window.html",
      {}
     ]
    ],
+   "editor/cloning_attributes.html": [
+    [
+     "/_mozilla/editor/cloning_attributes.html",
+     {}
+    ]
+   ],
    "editor/initial_selection_on_focus.html": [
     [
      "/_mozilla/editor/initial_selection_on_focus.html",
      {}
     ]
    ],
    "editor/joining_nodes.html": [
     [
@@ -1029,16 +1035,20 @@
   "dom/throttling/throttling-webrtc.window.js": [
    "02e6acec2ff275e0e935cb6d903d348f98d5d437",
    "testharness"
   ],
   "dom/throttling/throttling-ws.window.js": [
    "67a981ba2a4d08b684947ed42aba6648dcd262b4",
    "testharness"
   ],
+  "editor/cloning_attributes.html": [
+   "257023d742dd84a93816e05d24f380e27405db66",
+   "testharness"
+  ],
   "editor/initial_selection_on_focus.html": [
    "06948dbf72160a7de5a0baaa2f6cf1bb54fbeb8f",
    "testharness"
   ],
   "editor/joining_nodes.html": [
    "048cf7d99acdecb927f97c4554c4d04ca8b15a8a",
    "testharness"
   ],
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/mozilla/meta/editor/cloning_attributes.html.ini
@@ -0,0 +1,68 @@
+[cloning_attributes.html]
+  type: testharness
+  [Should clone attributes of <span> element in <p> to <span> in new <p>, right element, id attribute]
+    expected: FAIL
+
+  [Should clone attributes of <span> element at end of <p> to <span> in new <p>, right element, id attribute]
+    expected: FAIL
+
+  [Should clone attributes of <li> element at splitting at middle of the <li>, right element, id attribute]
+    expected: FAIL
+
+  [Should clone attributes of <li> element at splitting at end of the <li>, right element, id attribute]
+    expected: FAIL
+
+  [Should clone attributes of <span> element in <li> to <span> in new <li>, right element, id attribute]
+    expected: FAIL
+
+  [Should clone attributes of <span> element at end of <li> to <span> in new <li>, right element, id attribute]
+    expected: FAIL
+
+  [Should clone attributes of <dt> element to new <dt> element at splitting at middle of the <dt>, right element, id attribute]
+    expected: FAIL
+
+  [Should clone attributes of <span> element in <dt> to <span> in new <dd>, right element, id attribute]
+    expected: FAIL
+
+  [Should clone attributes of <dd> element to new <dd> element at splitting at middle of the <dd>, right element, id attribute]
+    expected: FAIL
+
+  [Should clone attributes of <span> element in <dd> to <span> in new <dd>, right element, id attribute]
+    expected: FAIL
+
+  [Should clone attributes of <h1> element to new <h1> at splitting it at middle of the <h1>, right element, id attribute]
+    expected: FAIL
+
+  [Should clone attributes of <span> element in <h1> to <span> in new <h1>, right element, id attribute]
+    expected: FAIL
+
+  [Should clone attributes of <h2> element to new <h2> at splitting it at middle of the <h2>, right element, id attribute]
+    expected: FAIL
+
+  [Should clone attributes of <span> element in <h2> to <span> in new <h2>, right element, id attribute]
+    expected: FAIL
+
+  [Should clone attributes of <h3> element to new <h3> at splitting it at middle of the <h3>, right element, id attribute]
+    expected: FAIL
+
+  [Should clone attributes of <span> element in <h3> to <span> in new <h3>, right element, id attribute]
+    expected: FAIL
+
+  [Should clone attributes of <h4> element to new <h4> at splitting it at middle of the <h4>, right element, id attribute]
+    expected: FAIL
+
+  [Should clone attributes of <span> element in <h4> to <span> in new <h4>, right element, id attribute]
+    expected: FAIL
+
+  [Should clone attributes of <h5> element to new <h5> at splitting it at middle of the <h5>, right element, id attribute]
+    expected: FAIL
+
+  [Should clone attributes of <span> element in <h5> to <span> in new <h5>, right element, id attribute]
+    expected: FAIL
+
+  [Should clone attributes of <h6> element to new <h6> at splitting it at middle of the <h6>, right element, id attribute]
+    expected: FAIL
+
+  [Should clone attributes of <span> element in <h6> to <span> in new <h6>, right element, id attribute]
+    expected: FAIL
+
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/editor/cloning_attributes.html
@@ -0,0 +1,728 @@
+<!doctype html>
+<html>
+<head>
+<meta charset=utf-8>
+<title>Cloning attributes</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+</head>
+<body>
+<script>
+"use strict";
+
+(function() {
+  // These tests assume that id attribute should be only in the left element.
+  // However, this is not standardized and other browsers may behave
+  // differently.  So, it's okay to change the behavior for id attribute
+  // for compatibility with the other browsers.
+  const kTests = [
+    { description: "Should clone attributes of <p> element at splitting at middle of the <p>",
+      innerHTML: "<p foo=\"bar\" id=\"original\">foobar</p>",
+      getLeftElement: function (aEditor) {
+        return aEditor.firstChild;
+      },
+      getRightElement: function (aEditor) {
+        return aEditor.firstChild.nextSibling;
+      },
+      expectedToCloneAttributes: true,
+      expectedAttributes: {
+        foo: "bar",
+        id: "original",
+      },
+      doIt: function (aEditor) {
+        window.getSelection().collapse(aEditor.firstChild.firstChild, 3);
+        document.execCommand("insertParagraph", false);
+      }, },
+    { description: "Should clone attributes of <p> element at splitting at end of the <p>",
+      innerHTML: "<p foo=\"bar\" id=\"original\">foobar</p>",
+      getLeftElement: function (aEditor) {
+        return aEditor.firstChild;
+      },
+      getRightElement: function (aEditor) {
+        return aEditor.firstChild.nextSibling;
+      },
+      expectedToCloneAttributes: true,
+      expectedAttributes: {
+        foo: "bar",
+        id: "original",
+      },
+      doIt: function (aEditor) {
+        window.getSelection().collapse(aEditor.firstChild.firstChild, 6);
+        document.execCommand("insertParagraph", false);
+      }, },
+    { description: "Should clone attributes of <span> element in <p> to <span> in new <p>",
+      innerHTML: "<p>fo<span id=\"original\" style=\"font-weight: bold;\">ob</span>ar</p>",
+      getLeftElement: function (aEditor) {
+        return aEditor.firstChild.firstChild.nextSibling;
+      },
+      getRightElement: function (aEditor) {
+        return aEditor.firstChild.nextSibling.firstChild;;
+      },
+      expectedToCloneAttributes: true,
+      expectedAttributes: {
+        style: "font-weight: bold;",
+        id: "original",
+      },
+      doIt: function (aEditor) {
+        window.getSelection().collapse(aEditor.firstChild.firstChild.nextSibling.firstChild, 1);
+        document.execCommand("insertParagraph", false);
+      }, },
+    { description: "Should clone attributes of <span> element at end of <p> to <span> in new <p>",
+      innerHTML: "<p>fo<span id=\"original\" style=\"font-weight: bold;\">ob</span></p>",
+      getLeftElement: function (aEditor) {
+        return aEditor.firstChild.firstChild.nextSibling;
+      },
+      getRightElement: function (aEditor) {
+        return aEditor.firstChild.nextSibling.firstChild;;
+      },
+      expectedToCloneAttributes: true,
+      expectedAttributes: {
+        style: "font-weight: bold;",
+        id: "original",
+      },
+      doIt: function (aEditor) {
+        window.getSelection().collapse(aEditor.firstChild.firstChild.nextSibling.firstChild, 2);
+        document.execCommand("insertParagraph", false);
+      }, },
+    { description: "Should clone attributes of <li> element at splitting at middle of the <li>",
+      innerHTML: "<ul><li foo=\"bar\" id=\"original\">foobar</li></ul>",
+      getLeftElement: function (aEditor) {
+        return aEditor.firstChild.firstChild;
+      },
+      getRightElement: function (aEditor) {
+        return aEditor.firstChild.firstChild.nextSibling;
+      },
+      expectedToCloneAttributes: true,
+      expectedAttributes: {
+        foo: "bar",
+        id: "original",
+      },
+      doIt: function (aEditor) {
+        window.getSelection().collapse(aEditor.firstChild.firstChild.firstChild, 3);
+        document.execCommand("insertParagraph", false);
+      }, },
+    { description: "Should clone attributes of <li> element at splitting at end of the <li>",
+      innerHTML: "<ul><li foo=\"bar\" id=\"original\">foobar</li></ul>",
+      getLeftElement: function (aEditor) {
+        return aEditor.firstChild.firstChild;
+      },
+      getRightElement: function (aEditor) {
+        return aEditor.firstChild.firstChild.nextSibling;
+      },
+      expectedToCloneAttributes: true,
+      expectedAttributes: {
+        foo: "bar",
+        id: "original",
+      },
+      doIt: function (aEditor) {
+        window.getSelection().collapse(aEditor.firstChild.firstChild.firstChild, 6);
+        document.execCommand("insertParagraph", false);
+      }, },
+    { description: "Should clone attributes of <span> element in <li> to <span> in new <li>",
+      innerHTML: "<ul><li>fo<span id=\"original\" style=\"font-weight: bold;\">ob</span>ar</li></ul>",
+      getLeftElement: function (aEditor) {
+        return aEditor.firstChild.firstChild.firstChild.nextSibling;
+      },
+      getRightElement: function (aEditor) {
+        return aEditor.firstChild.firstChild.nextSibling.firstChild;;
+      },
+      expectedToCloneAttributes: true,
+      expectedAttributes: {
+        style: "font-weight: bold;",
+        id: "original",
+      },
+      doIt: function (aEditor) {
+        window.getSelection().collapse(aEditor.firstChild.firstChild.firstChild.nextSibling.firstChild, 1);
+        document.execCommand("insertParagraph", false);
+      }, },
+    { description: "Should clone attributes of <span> element at end of <li> to <span> in new <li>",
+      innerHTML: "<ul><li>fo<span id=\"original\" style=\"font-weight: bold;\">ob</span></li></ul>",
+      getLeftElement: function (aEditor) {
+        return aEditor.firstChild.firstChild.firstChild.nextSibling;
+      },
+      getRightElement: function (aEditor) {
+        return aEditor.firstChild.firstChild.nextSibling.firstChild;;
+      },
+      expectedToCloneAttributes: true,
+      expectedAttributes: {
+        style: "font-weight: bold;",
+        id: "original",
+      },
+      doIt: function (aEditor) {
+        window.getSelection().collapse(aEditor.firstChild.firstChild.firstChild.nextSibling.firstChild, 2);
+        document.execCommand("insertParagraph", false);
+      }, },
+    { description: "Should clone attributes of <dt> element to new <dt> element at splitting at middle of the <dt>",
+      innerHTML: "<dl><dt foo=\"bar\" id=\"original\">foobar</dt></dl>",
+      getLeftElement: function (aEditor) {
+        return aEditor.firstChild.firstChild;
+      },
+      getRightElement: function (aEditor) {
+        return aEditor.firstChild.firstChild.nextSibling;
+      },
+      expectedToCloneAttributes: true,
+      expectedAttributes: {
+        foo: "bar",
+        id: "original",
+      },
+      doIt: function (aEditor) {
+        window.getSelection().collapse(aEditor.firstChild.firstChild.firstChild, 3);
+        document.execCommand("insertParagraph", false);
+      }, },
+    { description: "Should NOT clone attributes of <dt> element to new <dd> element at splitting at end of the <dt>",
+      innerHTML: "<dl><dt foo=\"bar\" id=\"original\">foobar</dt></dl>",
+      getLeftElement: function (aEditor) {
+        return aEditor.firstChild.firstChild;
+      },
+      getRightElement: function (aEditor) {
+        return aEditor.firstChild.firstChild.nextSibling;
+      },
+      expectedToCloneAttributes: false,
+      expectedAttributes: {
+        foo: "bar",
+        id: "original",
+      },
+      doIt: function (aEditor) {
+        window.getSelection().collapse(aEditor.firstChild.firstChild.firstChild, 6);
+        document.execCommand("insertParagraph", false);
+      }, },
+    { description: "Should clone attributes of <span> element in <dt> to <span> in new <dd>",
+      innerHTML: "<dl><dt>fo<span id=\"original\" style=\"font-weight: bold;\">ob</span>ar</dt></dl>",
+      getLeftElement: function (aEditor) {
+        return aEditor.firstChild.firstChild.firstChild.nextSibling;
+      },
+      getRightElement: function (aEditor) {
+        return aEditor.firstChild.firstChild.nextSibling.firstChild;;
+      },
+      expectedToCloneAttributes: true,
+      expectedAttributes: {
+        style: "font-weight: bold;",
+        id: "original",
+      },
+      doIt: function (aEditor) {
+        window.getSelection().collapse(aEditor.firstChild.firstChild.firstChild.nextSibling.firstChild, 1);
+        document.execCommand("insertParagraph", false);
+      }, },
+    { description: "Should NOT clone attributes of <span> element at end of <dt> to new <dd>",
+      innerHTML: "<dl><dt>fo<span id=\"original\" style=\"font-weight: bold;\">ob</span></dt></dl>",
+      getLeftElement: function (aEditor) {
+        return aEditor.firstChild.firstChild.firstChild.nextSibling;
+      },
+      getRightElement: function (aEditor) {
+        return aEditor.firstChild.firstChild.nextSibling.firstChild;;
+      },
+      expectedToCloneAttributes: false,
+      expectedAttributes: {
+        style: "font-weight: bold;",
+        id: "original",
+      },
+      doIt: function (aEditor) {
+        window.getSelection().collapse(aEditor.firstChild.firstChild.firstChild.nextSibling.firstChild, 2);
+        document.execCommand("insertParagraph", false);
+      }, },
+    { description: "Should clone attributes of <dd> element to new <dd> element at splitting at middle of the <dd>",
+      innerHTML: "<dl><dd foo=\"bar\" id=\"original\">foobar</dd></dl>",
+      getLeftElement: function (aEditor) {
+        return aEditor.firstChild.firstChild;
+      },
+      getRightElement: function (aEditor) {
+        return aEditor.firstChild.firstChild.nextSibling;
+      },
+      expectedToCloneAttributes: true,
+      expectedAttributes: {
+        foo: "bar",
+        id: "original",
+      },
+      doIt: function (aEditor) {
+        window.getSelection().collapse(aEditor.firstChild.firstChild.firstChild, 3);
+        document.execCommand("insertParagraph", false);
+      }, },
+    { description: "Should NOT clone attributes of <dd> element to new <dt> element at splitting at end of the <dd>",
+      innerHTML: "<dl><dd foo=\"bar\" id=\"original\">foobar</dd></dl>",
+      getLeftElement: function (aEditor) {
+        return aEditor.firstChild.firstChild;
+      },
+      getRightElement: function (aEditor) {
+        return aEditor.firstChild.firstChild.nextSibling;
+      },
+      expectedToCloneAttributes: false,
+      expectedAttributes: {
+        foo: "bar",
+        id: "original",
+      },
+      doIt: function (aEditor) {
+        window.getSelection().collapse(aEditor.firstChild.firstChild.firstChild, 6);
+        document.execCommand("insertParagraph", false);
+      }, },
+    { description: "Should clone attributes of <span> element in <dd> to <span> in new <dd>",
+      innerHTML: "<dl><dd>fo<span id=\"original\" style=\"font-weight: bold;\">ob</span>ar</dd></dl>",
+      getLeftElement: function (aEditor) {
+        return aEditor.firstChild.firstChild.firstChild.nextSibling;
+      },
+      getRightElement: function (aEditor) {
+        return aEditor.firstChild.firstChild.nextSibling.firstChild;;
+      },
+      expectedToCloneAttributes: true,
+      expectedAttributes: {
+        style: "font-weight: bold;",
+        id: "original",
+      },
+      doIt: function (aEditor) {
+        window.getSelection().collapse(aEditor.firstChild.firstChild.firstChild.nextSibling.firstChild, 1);
+        document.execCommand("insertParagraph", false);
+      }, },
+    { description: "Should NOT clone attributes of <span> element at end of <dd> to new <dt>",
+      innerHTML: "<dl><dd>fo<span id=\"original\" style=\"font-weight: bold;\">ob</span></dd></dl>",
+      getLeftElement: function (aEditor) {
+        return aEditor.firstChild.firstChild.firstChild.nextSibling;
+      },
+      getRightElement: function (aEditor) {
+        return aEditor.firstChild.firstChild.nextSibling.firstChild;;
+      },
+      expectedToCloneAttributes: false,
+      expectedAttributes: {
+        style: "font-weight: bold;",
+        id: "original",
+      },
+      doIt: function (aEditor) {
+        window.getSelection().collapse(aEditor.firstChild.firstChild.firstChild.nextSibling.firstChild, 2);
+        document.execCommand("insertParagraph", false);
+      }, },
+    { description: "Should clone attributes of <h1> element to new <h1> at splitting it at middle of the <h1>",
+      innerHTML: "<h1 foo=\"bar\" id=\"original\">foobar</h1>",
+      getLeftElement: function (aEditor) {
+        return aEditor.firstChild;
+      },
+      getRightElement: function (aEditor) {
+        return aEditor.firstChild.nextSibling;
+      },
+      expectedToCloneAttributes: true,
+      expectedAttributes: {
+        foo: "bar",
+        id: "original",
+      },
+      doIt: function (aEditor) {
+        window.getSelection().collapse(aEditor.firstChild.firstChild, 3);
+        document.execCommand("insertParagraph", false);
+      }, },
+    { description: "Should NOT clone attributes of <h1> element to new <div> at splitting it at end of the <h1>",
+      innerHTML: "<h1 foo=\"bar\" id=\"original\">foobar</h1>",
+      getLeftElement: function (aEditor) {
+        return aEditor.firstChild;
+      },
+      getRightElement: function (aEditor) {
+        return aEditor.firstChild.nextSibling;
+      },
+      expectedToCloneAttributes: false,
+      expectedAttributes: {
+        foo: "bar",
+        id: "original",
+      },
+      doIt: function (aEditor) {
+        window.getSelection().collapse(aEditor.firstChild.firstChild, 6);
+        document.execCommand("insertParagraph", false);
+      }, },
+    { description: "Should clone attributes of <span> element in <h1> to <span> in new <h1>",
+      innerHTML: "<h1>fo<span id=\"original\" style=\"font-weight: bold;\">ob</span>ar</h1>",
+      getLeftElement: function (aEditor) {
+        return aEditor.firstChild.firstChild.nextSibling;
+      },
+      getRightElement: function (aEditor) {
+        return aEditor.firstChild.nextSibling.firstChild;;
+      },
+      expectedToCloneAttributes: true,
+      expectedAttributes: {
+        style: "font-weight: bold;",
+        id: "original",
+      },
+      doIt: function (aEditor) {
+        window.getSelection().collapse(aEditor.firstChild.firstChild.nextSibling.firstChild, 1);
+        document.execCommand("insertParagraph", false);
+      }, },
+    { description: "Should NOT clone attributes of <span> element at end of <h1> to new <div>",
+      innerHTML: "<h1>fo<span id=\"original\" style=\"font-weight: bold;\">ob</span></h1>",
+      getLeftElement: function (aEditor) {
+        return aEditor.firstChild.firstChild.nextSibling;
+      },
+      getRightElement: function (aEditor) {
+        return aEditor.firstChild.nextSibling.firstChild;;
+      },
+      expectedToCloneAttributes: false,
+      expectedAttributes: {
+        style: "font-weight: bold;",
+        id: "original",
+      },
+      doIt: function (aEditor) {
+        window.getSelection().collapse(aEditor.firstChild.firstChild.nextSibling.firstChild, 2);
+        document.execCommand("insertParagraph", false);
+      }, },
+    { description: "Should clone attributes of <h2> element to new <h2> at splitting it at middle of the <h2>",
+      innerHTML: "<h2 foo=\"bar\" id=\"original\">foobar</h2>",
+      getLeftElement: function (aEditor) {
+        return aEditor.firstChild;
+      },
+      getRightElement: function (aEditor) {
+        return aEditor.firstChild.nextSibling;
+      },
+      expectedToCloneAttributes: true,
+      expectedAttributes: {
+        foo: "bar",
+        id: "original",
+      },
+      doIt: function (aEditor) {
+        window.getSelection().collapse(aEditor.firstChild.firstChild, 3);
+        document.execCommand("insertParagraph", false);
+      }, },
+    { description: "Should NOT clone attributes of <h2> element to new <div> at splitting it at end of the <h2>",
+      innerHTML: "<h2 foo=\"bar\" id=\"original\">foobar</h2>",
+      getLeftElement: function (aEditor) {
+        return aEditor.firstChild;
+      },
+      getRightElement: function (aEditor) {
+        return aEditor.firstChild.nextSibling;
+      },
+      expectedToCloneAttributes: false,
+      expectedAttributes: {
+        foo: "bar",
+        id: "original",
+      },
+      doIt: function (aEditor) {
+        window.getSelection().collapse(aEditor.firstChild.firstChild, 6);
+        document.execCommand("insertParagraph", false);
+      }, },
+    { description: "Should clone attributes of <span> element in <h2> to <span> in new <h2>",
+      innerHTML: "<h2>fo<span id=\"original\" style=\"font-weight: bold;\">ob</span>ar</h2>",
+      getLeftElement: function (aEditor) {
+        return aEditor.firstChild.firstChild.nextSibling;
+      },
+      getRightElement: function (aEditor) {
+        return aEditor.firstChild.nextSibling.firstChild;;
+      },
+      expectedToCloneAttributes: true,
+      expectedAttributes: {
+        style: "font-weight: bold;",
+        id: "original",
+      },
+      doIt: function (aEditor) {
+        window.getSelection().collapse(aEditor.firstChild.firstChild.nextSibling.firstChild, 1);
+        document.execCommand("insertParagraph", false);
+      }, },
+    { description: "Should NOT clone attributes of <span> element at end of <h2> to new <div>",
+      innerHTML: "<h2>fo<span id=\"original\" style=\"font-weight: bold;\">ob</span></h2>",
+      getLeftElement: function (aEditor) {
+        return aEditor.firstChild.firstChild.nextSibling;
+      },
+      getRightElement: function (aEditor) {
+        return aEditor.firstChild.nextSibling.firstChild;;
+      },
+      expectedToCloneAttributes: false,
+      expectedAttributes: {
+        style: "font-weight: bold;",
+        id: "original",
+      },
+      doIt: function (aEditor) {
+        window.getSelection().collapse(aEditor.firstChild.firstChild.nextSibling.firstChild, 2);
+        document.execCommand("insertParagraph", false);
+      }, },
+    { description: "Should clone attributes of <h3> element to new <h3> at splitting it at middle of the <h3>",
+      innerHTML: "<h3 foo=\"bar\" id=\"original\">foobar</h3>",
+      getLeftElement: function (aEditor) {
+        return aEditor.firstChild;
+      },
+      getRightElement: function (aEditor) {
+        return aEditor.firstChild.nextSibling;
+      },
+      expectedToCloneAttributes: true,
+      expectedAttributes: {
+        foo: "bar",
+        id: "original",
+      },
+      doIt: function (aEditor) {
+        window.getSelection().collapse(aEditor.firstChild.firstChild, 3);
+        document.execCommand("insertParagraph", false);
+      }, },
+    { description: "Should NOT clone attributes of <h3> element to new <div> at splitting it at end of the <h3>",
+      innerHTML: "<h3 foo=\"bar\" id=\"original\">foobar</h3>",
+      getLeftElement: function (aEditor) {
+        return aEditor.firstChild;
+      },
+      getRightElement: function (aEditor) {
+        return aEditor.firstChild.nextSibling;
+      },
+      expectedToCloneAttributes: false,
+      expectedAttributes: {
+        foo: "bar",
+        id: "original",
+      },
+      doIt: function (aEditor) {
+        window.getSelection().collapse(aEditor.firstChild.firstChild, 6);
+        document.execCommand("insertParagraph", false);
+      }, },
+    { description: "Should clone attributes of <span> element in <h3> to <span> in new <h3>",
+      innerHTML: "<h3>fo<span id=\"original\" style=\"font-weight: bold;\">ob</span>ar</h3>",
+      getLeftElement: function (aEditor) {
+        return aEditor.firstChild.firstChild.nextSibling;
+      },
+      getRightElement: function (aEditor) {
+        return aEditor.firstChild.nextSibling.firstChild;;
+      },
+      expectedToCloneAttributes: true,
+      expectedAttributes: {
+        style: "font-weight: bold;",
+        id: "original",
+      },
+      doIt: function (aEditor) {
+        window.getSelection().collapse(aEditor.firstChild.firstChild.nextSibling.firstChild, 1);
+        document.execCommand("insertParagraph", false);
+      }, },
+    { description: "Should NOT clone attributes of <span> element at end of <h3> to new <div>",
+      innerHTML: "<h3>fo<span id=\"original\" style=\"font-weight: bold;\">ob</span></h3>",
+      getLeftElement: function (aEditor) {
+        return aEditor.firstChild.firstChild.nextSibling;
+      },
+      getRightElement: function (aEditor) {
+        return aEditor.firstChild.nextSibling.firstChild;;
+      },
+      expectedToCloneAttributes: false,
+      expectedAttributes: {
+        style: "font-weight: bold;",
+        id: "original",
+      },
+      doIt: function (aEditor) {
+        window.getSelection().collapse(aEditor.firstChild.firstChild.nextSibling.firstChild, 2);
+        document.execCommand("insertParagraph", false);
+      }, },
+    { description: "Should clone attributes of <h4> element to new <h4> at splitting it at middle of the <h4>",
+      innerHTML: "<h4 foo=\"bar\" id=\"original\">foobar</h4>",
+      getLeftElement: function (aEditor) {
+        return aEditor.firstChild;
+      },
+      getRightElement: function (aEditor) {
+        return aEditor.firstChild.nextSibling;
+      },
+      expectedToCloneAttributes: true,
+      expectedAttributes: {
+        foo: "bar",
+        id: "original",
+      },
+      doIt: function (aEditor) {
+        window.getSelection().collapse(aEditor.firstChild.firstChild, 3);
+        document.execCommand("insertParagraph", false);
+      }, },
+    { description: "Should NOT clone attributes of <h4> element to new <div> at splitting it at end of the <h4>",
+      innerHTML: "<h4 foo=\"bar\" id=\"original\">foobar</h4>",
+      getLeftElement: function (aEditor) {
+        return aEditor.firstChild;
+      },
+      getRightElement: function (aEditor) {
+        return aEditor.firstChild.nextSibling;
+      },
+      expectedToCloneAttributes: false,
+      expectedAttributes: {
+        foo: "bar",
+        id: "original",
+      },
+      doIt: function (aEditor) {
+        window.getSelection().collapse(aEditor.firstChild.firstChild, 6);
+        document.execCommand("insertParagraph", false);
+      }, },
+    { description: "Should clone attributes of <span> element in <h4> to <span> in new <h4>",
+      innerHTML: "<h4>fo<span id=\"original\" style=\"font-weight: bold;\">ob</span>ar</h4>",
+      getLeftElement: function (aEditor) {
+        return aEditor.firstChild.firstChild.nextSibling;
+      },
+      getRightElement: function (aEditor) {
+        return aEditor.firstChild.nextSibling.firstChild;;
+      },
+      expectedToCloneAttributes: true,
+      expectedAttributes: {
+        style: "font-weight: bold;",
+        id: "original",
+      },
+      doIt: function (aEditor) {
+        window.getSelection().collapse(aEditor.firstChild.firstChild.nextSibling.firstChild, 1);
+        document.execCommand("insertParagraph", false);
+      }, },
+    { description: "Should NOT clone attributes of <span> element at end of <h4> to new <div>",
+      innerHTML: "<h4>fo<span id=\"original\" style=\"font-weight: bold;\">ob</span></h4>",
+      getLeftElement: function (aEditor) {
+        return aEditor.firstChild.firstChild.nextSibling;
+      },
+      getRightElement: function (aEditor) {
+        return aEditor.firstChild.nextSibling.firstChild;;
+      },
+      expectedToCloneAttributes: false,
+      expectedAttributes: {
+        style: "font-weight: bold;",
+        id: "original",
+      },
+      doIt: function (aEditor) {
+        window.getSelection().collapse(aEditor.firstChild.firstChild.nextSibling.firstChild, 2);
+        document.execCommand("insertParagraph", false);
+      }, },
+    { description: "Should clone attributes of <h5> element to new <h5> at splitting it at middle of the <h5>",
+      innerHTML: "<h5 foo=\"bar\" id=\"original\">foobar</h5>",
+      getLeftElement: function (aEditor) {
+        return aEditor.firstChild;
+      },
+      getRightElement: function (aEditor) {
+        return aEditor.firstChild.nextSibling;
+      },
+      expectedToCloneAttributes: true,
+      expectedAttributes: {
+        foo: "bar",
+        id: "original",
+      },
+      doIt: function (aEditor) {
+        window.getSelection().collapse(aEditor.firstChild.firstChild, 3);
+        document.execCommand("insertParagraph", false);
+      }, },
+    { description: "Should NOT clone attributes of <h5> element to new <div> at splitting it at end of the <h5>",
+      innerHTML: "<h5 foo=\"bar\" id=\"original\">foobar</h5>",
+      getLeftElement: function (aEditor) {
+        return aEditor.firstChild;
+      },
+      getRightElement: function (aEditor) {
+        return aEditor.firstChild.nextSibling;
+      },
+      expectedToCloneAttributes: false,
+      expectedAttributes: {
+        foo: "bar",
+        id: "original",
+      },
+      doIt: function (aEditor) {
+        window.getSelection().collapse(aEditor.firstChild.firstChild, 6);
+        document.execCommand("insertParagraph", false);
+      }, },
+    { description: "Should clone attributes of <span> element in <h5> to <span> in new <h5>",
+      innerHTML: "<h5>fo<span id=\"original\" style=\"font-weight: bold;\">ob</span>ar</h5>",
+      getLeftElement: function (aEditor) {
+        return aEditor.firstChild.firstChild.nextSibling;
+      },
+      getRightElement: function (aEditor) {
+        return aEditor.firstChild.nextSibling.firstChild;;
+      },
+      expectedToCloneAttributes: true,
+      expectedAttributes: {
+        style: "font-weight: bold;",
+        id: "original",
+      },
+      doIt: function (aEditor) {
+        window.getSelection().collapse(aEditor.firstChild.firstChild.nextSibling.firstChild, 1);
+        document.execCommand("insertParagraph", false);
+      }, },
+    { description: "Should NOT clone attributes of <span> element at end of <h5> to new <div>",
+      innerHTML: "<h5>fo<span id=\"original\" style=\"font-weight: bold;\">ob</span></h5>",
+      getLeftElement: function (aEditor) {
+        return aEditor.firstChild.firstChild.nextSibling;
+      },
+      getRightElement: function (aEditor) {
+        return aEditor.firstChild.nextSibling.firstChild;;
+      },
+      expectedToCloneAttributes: false,
+      expectedAttributes: {
+        style: "font-weight: bold;",
+        id: "original",
+      },
+      doIt: function (aEditor) {
+        window.getSelection().collapse(aEditor.firstChild.firstChild.nextSibling.firstChild, 2);
+        document.execCommand("insertParagraph", false);
+      }, },
+    { description: "Should clone attributes of <h6> element to new <h6> at splitting it at middle of the <h6>",
+      innerHTML: "<h6 foo=\"bar\" id=\"original\">foobar</h6>",
+      getLeftElement: function (aEditor) {
+        return aEditor.firstChild;
+      },
+      getRightElement: function (aEditor) {
+        return aEditor.firstChild.nextSibling;
+      },
+      expectedToCloneAttributes: true,
+      expectedAttributes: {
+        foo: "bar",
+        id: "original",
+      },
+      doIt: function (aEditor) {
+        window.getSelection().collapse(aEditor.firstChild.firstChild, 3);
+        document.execCommand("insertParagraph", false);
+      }, },
+    { description: "Should NOT clone attributes of <h6> element to new <div> at splitting it at end of the <h6>",
+      innerHTML: "<h6 foo=\"bar\" id=\"original\">foobar</h6>",
+      getLeftElement: function (aEditor) {
+        return aEditor.firstChild;
+      },
+      getRightElement: function (aEditor) {
+        return aEditor.firstChild.nextSibling;
+      },
+      expectedToCloneAttributes: false,
+      expectedAttributes: {
+        foo: "bar",
+        id: "original",
+      },
+      doIt: function (aEditor) {
+        window.getSelection().collapse(aEditor.firstChild.firstChild, 6);
+        document.execCommand("insertParagraph", false);
+      }, },
+    { description: "Should clone attributes of <span> element in <h6> to <span> in new <h6>",
+      innerHTML: "<h6>fo<span id=\"original\" style=\"font-weight: bold;\">ob</span>ar</h6>",
+      getLeftElement: function (aEditor) {
+        return aEditor.firstChild.firstChild.nextSibling;
+      },
+      getRightElement: function (aEditor) {
+        return aEditor.firstChild.nextSibling.firstChild;;
+      },
+      expectedToCloneAttributes: true,
+      expectedAttributes: {
+        style: "font-weight: bold;",
+        id: "original",
+      },
+      doIt: function (aEditor) {
+        window.getSelection().collapse(aEditor.firstChild.firstChild.nextSibling.firstChild, 1);
+        document.execCommand("insertParagraph", false);
+      }, },
+    { description: "Should NOT clone attributes of <span> element at end of <h6> to new <div>",
+      innerHTML: "<h6>fo<span id=\"original\" style=\"font-weight: bold;\">ob</span></h6>",
+      getLeftElement: function (aEditor) {
+        return aEditor.firstChild.firstChild.nextSibling;
+      },
+      getRightElement: function (aEditor) {
+        return aEditor.firstChild.nextSibling.firstChild;;
+      },
+      expectedToCloneAttributes: false,
+      expectedAttributes: {
+        style: "font-weight: bold;",
+        id: "original",
+      },
+      doIt: function (aEditor) {
+        window.getSelection().collapse(aEditor.firstChild.firstChild.nextSibling.firstChild, 2);
+        document.execCommand("insertParagraph", false);
+      }, },
+  ];
+
+  document.body.innerHTML = "<div id=\"editor\" contenteditable></div>";
+  let editor = document.getElementById("editor");
+  editor.focus();
+  let selection = document.getSelection();
+
+  for (const kTest of kTests) {
+    editor.innerHTML = kTest.innerHTML;
+    editor.focus();
+    kTest.doIt(editor);
+    let leftElement = kTest.getLeftElement(editor);
+    for (const kAttr in kTest.expectedAttributes) {
+      test(function () {
+        assert_equals(leftElement.getAttribute(kAttr),
+                      kTest.expectedAttributes[kAttr]);
+      }, kTest.description + "left Element, " + kAttr + " attribute");
+    }
+    let rightElement = kTest.getRightElement(editor);
+    for (const kAttr in kTest.expectedAttributes) {
+      test(function () {
+        assert_equals(rightElement.getAttribute(kAttr),
+                      !kTest.expectedToCloneAttributes || kAttr === "id"  ? null : kTest.expectedAttributes[kAttr]);
+      }, kTest.description + ", right element, " + kAttr + " attribute");
+    }
+  }
+})();
+</script>
+</body>
+</html>