Bug 1390396 - Reenable mochitests for custom elements lifecycle callbacks; r=smaug
authorEdgar Chen <echen@mozilla.com>
Tue, 03 Oct 2017 17:22:58 +0800
changeset 393050 b4a1ab50128ef069d2a1853c9f6ad462a1f7161d
parent 393049 18f77ef35a2231f8fa2d4ba37e3e5c7d3cbee469
child 393051 af8727e2028e660aa0f7525c0e1c784d8edafff7
push id32953
push usershindli@mozilla.com
push dateWed, 22 Nov 2017 21:28:42 +0000
treeherdermozilla-central@f5dafe8991b3 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmaug
bugs1390396
milestone59.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 1390396 - Reenable mochitests for custom elements lifecycle callbacks; r=smaug Attribute changed callback now is fired only when the attribute is in observedAttributes list which is introduced in latest spec, so in this patch, we change the tests for attribute changed callback to use customElements.define() to register customElements definition instead. MozReview-Commit-ID: 2s1qj3UsFUS
dom/tests/mochitest/webcomponents/mochitest.ini
dom/tests/mochitest/webcomponents/test_custom_element_callback_innerhtml.html
dom/tests/mochitest/webcomponents/test_custom_element_in_shadow.html
dom/tests/mochitest/webcomponents/test_custom_element_lifecycle.html
dom/tests/mochitest/webcomponents/test_custom_element_stack.html
dom/tests/mochitest/webcomponents/test_document_register_lifecycle.html
dom/tests/mochitest/webcomponents/test_document_register_stack.html
--- a/dom/tests/mochitest/webcomponents/mochitest.ini
+++ b/dom/tests/mochitest/webcomponents/mochitest.ini
@@ -5,45 +5,41 @@ support-files =
 
 [test_bug900724.html]
 [test_bug1017896.html]
 [test_bug1176757.html]
 [test_bug1276240.html]
 [test_content_element.html]
 skip-if = true # Triggers assertions about flattened tree inconsistencies and it's going away in bug 1418002.
 [test_custom_element_callback_innerhtml.html]
-skip-if = true # disabled - See bug 1390396
 [test_custom_element_htmlconstructor.html]
 skip-if = os == 'android' # bug 1323645
 support-files =
   htmlconstructor_autonomous_tests.js
   htmlconstructor_builtin_tests.js
 [test_custom_element_in_shadow.html]
-skip-if = true # disabled - See bug 1390396
 [test_custom_element_register_invalid_callbacks.html]
 [test_custom_element_throw_on_dynamic_markup_insertion.html]
 [test_custom_element_get.html]
 [test_custom_element_when_defined.html]
 [test_custom_element_upgrade.html]
 support-files =
   test_upgrade_page.html
   upgrade_tests.js
+[test_custom_element_lifecycle.html]
+[test_custom_element_stack.html]
 [test_nested_content_element.html]
 [test_dest_insertion_points.html]
 [test_fallback_dest_insertion_points.html]
 [test_detached_style.html]
 [test_dynamic_content_element_matching.html]
 [test_document_adoptnode.html]
 [test_document_importnode.html]
 [test_document_register.html]
-[test_document_register_lifecycle.html]
-skip-if = true # disabled - See bug 1390396
 [test_document_register_parser.html]
-[test_document_register_stack.html]
-skip-if = true # disabled - See bug 1390396
 [test_document_shared_registry.html]
 [test_event_retarget.html]
 [test_event_stopping.html]
 [test_template.html]
 [test_template_xhtml.html]
 [test_template_custom_elements.html]
 [test_shadowroot.html]
 [test_shadowroot_inert_element.html]
--- a/dom/tests/mochitest/webcomponents/test_custom_element_callback_innerhtml.html
+++ b/dom/tests/mochitest/webcomponents/test_custom_element_callback_innerhtml.html
@@ -1,34 +1,30 @@
 <!DOCTYPE HTML>
 <html>
 <!--
 https://bugzilla.mozilla.org/show_bug.cgi?id=1102502
 -->
 <head>
-  <title>Test for attached callback for element created in the document by the parser</title>
+  <title>Test for connected callback for element created in the document by the parser</title>
   <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
 </head>
 <body>
 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1102502">Bug 1102502</a>
 <div id="container"></div>
 
 <script>
 
 SimpleTest.waitForExplicitFinish();
 
 var connectedCallbackCount = 0;
 
 var p = Object.create(HTMLElement.prototype);
 
-p.createdCallback = function() {
-  ok(true, "createdCallback called.");
-};
-
 p.connectedCallback = function() {
   ok(true, "connectedCallback should be called when the parser creates an element in the document.");
   connectedCallbackCount++;
   // connectedCallback should be called twice, once for the element created for innerHTML and
   // once for the element created in this document.
   if (connectedCallbackCount == 2) {
     SimpleTest.finish();
   }
--- a/dom/tests/mochitest/webcomponents/test_custom_element_in_shadow.html
+++ b/dom/tests/mochitest/webcomponents/test_custom_element_in_shadow.html
@@ -11,122 +11,110 @@ https://bugzilla.mozilla.org/show_bug.cg
 <body>
 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1087460">Bug 1087460</a>
 <div id="container"></div>
 
 <script>
 
 // Test callback for custom element when used after registration.
 
-var createdCallbackCount = 0;
-var attachedCallbackCount = 0;
-var detachedCallbackCount = 0;
+var connectedCallbackCount = 0;
+var disconnectedCallbackCount = 0;
 var attributeChangedCallbackCount = 0;
 
-var p1 = Object.create(HTMLElement.prototype);
+class Foo extends HTMLElement
+{
+  connectedCallback() {
+    connectedCallbackCount++;
+  }
 
-p1.createdCallback = function() {
-  createdCallbackCount++;
-};
-
-p1.attachedCallback = function() {
-  attachedCallbackCount++;
-};
+  disconnectedCallback() {
+    disconnectedCallbackCount++;
+  }
 
-p1.detachedCallback = function() {
-  detachedCallbackCount++;
-};
+  attributeChangedCallback(aName, aOldValue, aNewValue) {
+    attributeChangedCallbackCount++;
+  }
 
-p1.attributeChangedCallback = function(name, oldValue, newValue) {
-  attributeChangedCallbackCount++;
-};
+  static get observedAttributes() {
+    return ["data-foo"];
+  }
+}
 
-document.registerElement("x-foo", { prototype: p1 });
+customElements.define("x-foo", Foo);
 
 var container = document.getElementById("container");
 var shadow = container.createShadowRoot();
-
-is(createdCallbackCount, 0, "createdCallback should not be called more than once in this test.");
 var customElem = document.createElement("x-foo");
-is(createdCallbackCount, 1, "createdCallback should be called after creating custom element.");
 
 is(attributeChangedCallbackCount, 0, "attributeChangedCallback should not be called after just creating an element.");
 customElem.setAttribute("data-foo", "bar");
 is(attributeChangedCallbackCount, 1, "attributeChangedCallback should be called after setting an attribute.");
 
-is(attachedCallbackCount, 0, "attachedCallback should not be called on an element that is not in a document/composed document.");
+is(connectedCallbackCount, 0, "connectedCallback should not be called on an element that is not in a document/composed document.");
 shadow.appendChild(customElem);
-is(attachedCallbackCount, 1, "attachedCallback should be called after attaching custom element to the composed document.");
+is(connectedCallbackCount, 1, "connectedCallback should be called after attaching custom element to the composed document.");
 
-is(detachedCallbackCount, 0, "detachedCallback should not be called without detaching custom element.");
+is(disconnectedCallbackCount, 0, "disconnectedCallback should not be called without detaching custom element.");
 shadow.removeChild(customElem);
-is(detachedCallbackCount, 1, "detachedCallback should be called after detaching custom element from the composed document.");
+is(disconnectedCallbackCount, 1, "disconnectedCallback should be called after detaching custom element from the composed document.");
 
 // Test callback for custom element already in the composed doc when created.
 
-createdCallbackCount = 0;
-attachedCallbackCount = 0;
-detachedCallbackCount = 0;
+connectedCallbackCount = 0;
+disconnectedCallbackCount = 0;
 attributeChangedCallbackCount = 0;
 
 shadow.innerHTML = "<x-foo></x-foo>";
-is(createdCallbackCount, 1, "createdCallback should be called after creating a custom element.");
-is(attachedCallbackCount, 1, "attachedCallback should be called after creating an element in the composed document.");
+is(connectedCallbackCount, 1, "connectedCallback should be called after creating an element in the composed document.");
 
 shadow.innerHTML = "";
-is(detachedCallbackCount, 1, "detachedCallback should be called after detaching custom element from the composed document.");
+is(disconnectedCallbackCount, 1, "disconnectedCallback should be called after detaching custom element from the composed document.");
 
 // Test callback for custom element in shadow DOM when host attached/detached to/from document.
 
-createdCallbackCount = 0;
-attachedCallbackCount = 0;
-detachedCallbackCount = 0;
+connectedCallbackCount = 0;
+disconnectedCallbackCount = 0;
 attributeChangedCallbackCount = 0;
 
 var host = document.createElement("div");
 shadow = host.createShadowRoot();
 customElem = document.createElement("x-foo");
 
-is(attachedCallbackCount, 0, "attachedCallback should not be called on newly created element.");
+is(connectedCallbackCount, 0, "connectedCallback should not be called on newly created element.");
 shadow.appendChild(customElem);
-is(attachedCallbackCount, 0, "attachedCallback should not be called on attaching to a tree that is not in the composed document.");
+is(connectedCallbackCount, 0, "connectedCallback should not be called on attaching to a tree that is not in the composed document.");
 
-is(attachedCallbackCount, 0, "detachedCallback should not be called.");
+is(disconnectedCallbackCount, 0, "disconnectedCallback should not be called.");
 shadow.removeChild(customElem);
-is(detachedCallbackCount, 0, "detachedCallback should not be called when detaching from a tree that is not in the composed document.");
+is(disconnectedCallbackCount, 0, "disconnectedCallback should not be called when detaching from a tree that is not in the composed document.");
 
 shadow.appendChild(customElem);
-is(attachedCallbackCount, 0, "attachedCallback should still not be called after reattaching to a shadow tree that is not in the composed document.");
+is(connectedCallbackCount, 0, "connectedCallback should still not be called after reattaching to a shadow tree that is not in the composed document.");
 
 container.appendChild(host);
-is(attachedCallbackCount, 1, "attachedCallback should be called after host is inserted into document.");
+is(connectedCallbackCount, 1, "connectedCallback should be called after host is inserted into document.");
 
 container.removeChild(host);
-is(detachedCallbackCount, 1, "detachedCallback should be called after host is removed from document.");
+is(disconnectedCallbackCount, 1, "disconnectedCallback should be called after host is removed from document.");
 
 // Test callback for custom element for upgraded element.
 
-createdCallbackCount = 0;
-attachedCallbackCount = 0;
-detachedCallbackCount = 0;
+connectedCallbackCount = 0;
+disconnectedCallbackCount = 0;
 attributeChangedCallbackCount = 0;
 
 shadow = container.shadowRoot;
 shadow.innerHTML = "<x-bar></x-bar>";
 
 var p2 = Object.create(HTMLElement.prototype);
 
-p2.createdCallback = function() {
-  createdCallbackCount++;
-};
-
-p2.attachedCallback = function() {
-  attachedCallbackCount++;
+p2.connectedCallback = function() {
+  connectedCallbackCount++;
 };
 
 document.registerElement("x-bar", { prototype: p2 });
-is(createdCallbackCount, 1, "createdCallback should be called after registering element.");
-is(attachedCallbackCount, 1, "attachedCallback should be called after upgrading element in composed document.");
+is(connectedCallbackCount, 1, "connectedCallback should be called after upgrading element in composed document.");
 
 </script>
 
 </body>
 </html>
rename from dom/tests/mochitest/webcomponents/test_document_register_lifecycle.html
rename to dom/tests/mochitest/webcomponents/test_custom_element_lifecycle.html
--- a/dom/tests/mochitest/webcomponents/test_document_register_lifecycle.html
+++ b/dom/tests/mochitest/webcomponents/test_custom_element_lifecycle.html
@@ -18,295 +18,273 @@ https://bugzilla.mozilla.org/show_bug.cg
 
 var container = document.getElementById("container");
 
 // Tests callbacks after registering element type that is already in the document.
 // create element in document -> register -> remove from document
 function testRegisterUnresolved() {
   var helloElem = document.getElementById("hello");
 
-  var createdCallbackCalled = false;
-  var attachedCallbackCalled = false;
-  var detachedCallbackCalled = false;
+  var connectedCallbackCalled = false;
+  var disconnectedCallbackCalled = false;
 
   var p = Object.create(HTMLElement.prototype);
-  p.createdCallback = function() {
-    is(helloElem.__proto__, p, "Prototype should be adjusted just prior to invoking the created callback.");
-    is(createdCallbackCalled, false, "Created callback should only be called once in this tests.");
+  p.connectedCallback = function() {
+    is(connectedCallbackCalled, false, "Connected callback should only be called once in this test.");
     is(this, helloElem, "The 'this' value should be the custom element.");
-    createdCallbackCalled = true;
+    connectedCallbackCalled = true;
   };
 
-  p.attachedCallback = function() {
-    is(createdCallbackCalled, true, "Created callback should be called before attached");
-    is(attachedCallbackCalled, false, "attached callback should only be called once in this test.");
-    is(this, helloElem, "The 'this' value should be the custom element.");
-    attachedCallbackCalled = true;
-  };
-
-  p.detachedCallback = function() {
-    is(attachedCallbackCalled, true, "attached callback should be called before detached");
-    is(detachedCallbackCalled, false, "detached callback should only be called once in this test.");
-    detachedCallbackCalled = true;
+  p.disconnectedCallback = function() {
+    is(connectedCallbackCalled, true, "Connected callback should be called before detached");
+    is(disconnectedCallbackCalled, false, "Disconnected callback should only be called once in this test.");
+    disconnectedCallbackCalled = true;
     is(this, helloElem, "The 'this' value should be the custom element.");
     runNextTest();
   };
 
   p.attributeChangedCallback = function(name, oldValue, newValue) {
     ok(false, "attributeChanged callback should never be called in this test.");
   };
 
   document.registerElement("x-hello", { prototype: p });
-  is(createdCallbackCalled, true, "created callback should be called when control returns to script from user agent code");
 
-  // Remove element from document to trigger detached callback.
+  // Remove element from document to trigger disconnected callback.
   container.removeChild(helloElem);
 }
 
 // Tests callbacks after registering an extended element type that is already in the document.
 // create element in document -> register -> remove from document
 function testRegisterUnresolvedExtended() {
   var buttonElem = document.getElementById("extbutton");
 
-  var createdCallbackCalled = false;
-  var attachedCallbackCalled = false;
-  var detachedCallbackCalled = false;
+  var connectedCallbackCalled = false;
+  var disconnectedCallbackCalled = false;
 
   var p = Object.create(HTMLButtonElement.prototype);
-  p.createdCallback = function() {
-    is(buttonElem.__proto__, p, "Prototype should be adjusted just prior to invoking the created callback.");
-    is(createdCallbackCalled, false, "Created callback should only be called once in this tests.");
+  p.connectedCallback = function() {
+    is(connectedCallbackCalled, false, "Connected callback should only be called once in this test.");
     is(this, buttonElem, "The 'this' value should be the custom element.");
-    createdCallbackCalled = true;
+    connectedCallbackCalled = true;
   };
 
-  p.attachedCallback = function() {
-    is(createdCallbackCalled, true, "Created callback should be called before attached");
-    is(attachedCallbackCalled, false, "attached callback should only be called once in this test.");
-    is(this, buttonElem, "The 'this' value should be the custom element.");
-    attachedCallbackCalled = true;
-  };
-
-  p.detachedCallback = function() {
-    is(attachedCallbackCalled, true, "attached callback should be called before detached");
-    is(detachedCallbackCalled, false, "detached callback should only be called once in this test.");
-    detachedCallbackCalled = true;
+  p.disconnectedCallback = function() {
+    is(connectedCallbackCalled, true, "Connected callback should be called before detached");
+    is(disconnectedCallbackCalled, false, "Disconnected callback should only be called once in this test.");
+    disconnectedCallbackCalled = true;
     is(this, buttonElem, "The 'this' value should be the custom element.");
     runNextTest();
   };
 
   p.attributeChangedCallback = function(name, oldValue, newValue) {
     ok(false, "attributeChanged callback should never be called in this test.");
   };
 
   document.registerElement("x-button", { prototype: p, extends: "button" });
-  is(createdCallbackCalled, true, "created callback should be called when control returns to script from user agent code");
 
-  // Remove element from document to trigger detached callback.
+  // Remove element from document to trigger disconnected callback.
   container.removeChild(buttonElem);
 }
 
 function testInnerHTML() {
-  var createdCallbackCalled = false;
+  var connectedCallbackCalled = false;
 
   var p = Object.create(HTMLElement.prototype);
-  p.createdCallback = function() {
-    is(createdCallbackCalled, false, "created callback should only be called once in this test.");
-    createdCallbackCalled = true;
+  p.connectedCallback = function() {
+    is(connectedCallbackCalled, false, "Connected callback should only be called once in this test.");
+    connectedCallbackCalled = true;
   };
 
   document.registerElement("x-inner-html", { prototype: p });
   var div = document.createElement(div);
+  document.documentElement.appendChild(div);
   div.innerHTML = '<x-inner-html></x-inner-html>';
-  is(createdCallbackCalled, true, "created callback should be called after setting innerHTML.");
+  is(connectedCallbackCalled, true, "Connected callback should be called after setting innerHTML.");
   runNextTest();
 }
 
 function testInnerHTMLExtended() {
-  var createdCallbackCalled = false;
+  var connectedCallbackCalled = false;
 
   var p = Object.create(HTMLButtonElement.prototype);
-  p.createdCallback = function() {
-    is(createdCallbackCalled, false, "created callback should only be called once in this test.");
-    createdCallbackCalled = true;
+  p.connectedCallback = function() {
+    is(connectedCallbackCalled, false, "Connected callback should only be called once in this test.");
+    connectedCallbackCalled = true;
   };
 
   document.registerElement("x-inner-html-extended", { prototype: p, extends: "button" });
   var div = document.createElement(div);
+  document.documentElement.appendChild(div);
   div.innerHTML = '<button is="x-inner-html-extended"></button>';
-  is(createdCallbackCalled, true, "created callback should be called after setting innerHTML.");
+  is(connectedCallbackCalled, true, "Connected callback should be called after setting innerHTML.");
   runNextTest();
 }
 
 function testInnerHTMLUpgrade() {
-  var createdCallbackCalled = false;
+  var connectedCallbackCalled = false;
 
   var div = document.createElement(div);
+  document.documentElement.appendChild(div);
   div.innerHTML = '<x-inner-html-upgrade></x-inner-html-upgrade>';
 
   var p = Object.create(HTMLElement.prototype);
-  p.createdCallback = function() {
-    is(createdCallbackCalled, false, "created callback should only be called once in this test.");
-    createdCallbackCalled = true;
+  p.connectedCallback = function() {
+    is(connectedCallbackCalled, false, "Connected callback should only be called once in this test.");
+    connectedCallbackCalled = true;
   };
 
   document.registerElement("x-inner-html-upgrade", { prototype: p });
-  is(createdCallbackCalled, true, "created callback should be called after registering.");
+  is(connectedCallbackCalled, true, "Connected callback should be called after registering.");
   runNextTest();
 }
 
 function testInnerHTMLExtendedUpgrade() {
-  var createdCallbackCalled = false;
+  var connectedCallbackCalled = false;
 
   var div = document.createElement(div);
+  document.documentElement.appendChild(div);
   div.innerHTML = '<button is="x-inner-html-extended-upgrade"></button>';
 
   var p = Object.create(HTMLButtonElement.prototype);
-  p.createdCallback = function() {
-    is(createdCallbackCalled, false, "created callback should only be called once in this test.");
-    createdCallbackCalled = true;
+  p.connectedCallback = function() {
+    is(connectedCallbackCalled, false, "Connected callback should only be called once in this test.");
+    connectedCallbackCalled = true;
   };
 
   document.registerElement("x-inner-html-extended-upgrade", { prototype: p, extends: "button" });
-  is(createdCallbackCalled, true, "created callback should be called after registering.");
+  is(connectedCallbackCalled, true, "Connected callback should be called after registering.");
   runNextTest();
 }
 
 // Test callback when creating element after registering an element type.
 // register -> create element -> insert into document -> remove from document
 function testRegisterResolved() {
-  var createdCallbackCalled = false;
-  var attachedCallbackCalled = false;
-  var detachedCallbackCalled = false;
-
-  var createdCallbackThis;
+  var connectedCallbackCalled = false;
+  var disconnectedCallbackCalled = false;
 
   var p = Object.create(HTMLElement.prototype);
-  p.createdCallback = function() {
-    is(createdCallbackCalled, false, "Created callback should only be called once in this test.");
-    createdCallbackThis = this;
-    createdCallbackCalled = true;
+  p.connectedCallback = function() {
+    is(connectedCallbackCalled, false, "Connected callback should only be called on in this test.");
+    is(this, createdElement, "The 'this' value should be the custom element.");
+    connectedCallbackCalled = true;
   };
 
-  p.attachedCallback = function() {
-    is(createdCallbackCalled, true, "created callback should be called before attached callback.");
-    is(attachedCallbackCalled, false, "attached callback should only be called on in this test.");
+  p.disconnectedCallback = function() {
+    is(connectedCallbackCalled, true, "Connected callback should be called before detached");
+    is(disconnectedCallbackCalled, false, "Disconnected callback should only be called once in this test.");
     is(this, createdElement, "The 'this' value should be the custom element.");
-    attachedCallbackCalled = true;
-  };
-
-  p.detachedCallback = function() {
-    is(attachedCallbackCalled, true, "attached callback should be called before detached");
-    is(detachedCallbackCalled, false, "detached callback should only be called once in this test.");
-    is(this, createdElement, "The 'this' value should be the custom element.");
-    detachedCallbackCalled = true;
+    disconnectedCallbackCalled = true;
     runNextTest();
   };
 
   p.attributeChangedCallback = function() {
     ok(false, "attributeChanged callback should never be called in this test.");
   };
 
   document.registerElement("x-resolved", { prototype: p });
-  is(createdCallbackCalled, false, "Created callback should not be called when custom element instance has not been created.");
 
   var createdElement = document.createElement("x-resolved");
-  is(createdCallbackThis, createdElement, "The 'this' value in the created callback should be the custom element.");
   is(createdElement.__proto__, p, "Prototype of custom element should be the registered prototype.");
 
   // Insert element into document to trigger attached callback.
   container.appendChild(createdElement);
 
   // Remove element from document to trigger detached callback.
   container.removeChild(createdElement);
 }
 
 // Callbacks should always be the same ones when registered.
 function testChangingCallback() {
-  var p = Object.create(HTMLElement.prototype);
   var callbackCalled = false;
-  p.attributeChangedCallback = function(name, oldValue, newValue) {
-    is(callbackCalled, false, "Callback should only be called once in this test.");
-    callbackCalled = true;
-    runNextTest();
-  };
+
+  class TestCallback extends HTMLElement
+  {
+    attributeChangedCallback(aName, aOldValue, aNewValue) {
+      is(callbackCalled, false, "Callback should only be called once in this test.");
+      callbackCalled = true;
+      runNextTest();
+    }
 
-  document.registerElement("x-test-callback", { prototype: p });
+    static get observedAttributes() {
+      return ["data-foo"];
+    }
+  }
 
-  p.attributeChangedCallback = function(name, oldValue, newValue) {
+  customElements.define("x-test-callback", TestCallback);
+
+  TestCallback.prototype.attributeChangedCallback = function(name, oldValue, newValue) {
     ok(false, "Only callbacks at registration should be called.");
   };
 
   var elem = document.createElement("x-test-callback");
-  elem.setAttribute("foo", "bar");
+  elem.setAttribute("data-foo", "bar");
 }
 
 function testAttributeChanged() {
-  var createdCallbackCalled = false;
-
   var createdElement;
-  var createdCallbackThis;
-
-  var p = Object.create(HTMLElement.prototype);
-  p.createdCallback = function() {
-    is(createdCallbackCalled, false, "Created callback should only be called once in this test.");
-    createdCallbackThis = this;
-    createdCallbackCalled = true;
-  };
-
   // Sequence of callback arguments that we expect from attribute changed callback
   // after changing attributes values in a specific order.
   var expectedCallbackArguments = [
     // [oldValue, newValue]
     [null, "newvalue"], // Setting the attribute value to "newvalue"
     ["newvalue", "nextvalue"], // Changing the attribute value from "newvalue" to "nextvalue"
     ["nextvalue", ""], // Changing the attribute value from "nextvalue" to empty string
     ["", null], // Removing the attribute.
   ];
 
-  p.attributeChangedCallback = function(name, oldValue, newValue) {
-    is(createdCallbackCalled, true, "created callback should be called before attribute changed.");
-    is(this, createdElement, "The 'this' value should be the custom element.");
-    ok(expectedCallbackArguments.length > 0, "Attribute changed callback should not be called more than expected.");
+  class AttrChange extends HTMLElement
+  {
+    attributeChangedCallback(name, oldValue, newValue) {
+      is(this, createdElement, "The 'this' value should be the custom element.");
+      ok(expectedCallbackArguments.length > 0, "Attribute changed callback should not be called more than expected.");
 
-    is(name, "changeme", "name arugment in attribute changed callback should be the name of the changed attribute.");
+      is(name, "changeme", "name arugment in attribute changed callback should be the name of the changed attribute.");
 
-    var expectedArgs = expectedCallbackArguments.shift();
-    is(oldValue, expectedArgs[0], "The old value argument should match the expected value.");
-    is(newValue, expectedArgs[1], "The new value argument should match the expected value.");
+      var expectedArgs = expectedCallbackArguments.shift();
+      is(oldValue, expectedArgs[0], "The old value argument should match the expected value.");
+      is(newValue, expectedArgs[1], "The new value argument should match the expected value.");
 
-    if (expectedCallbackArguments.length === 0) {
-      // Done with the attribute changed callback test.
-      runNextTest();
+      if (expectedCallbackArguments.length === 0) {
+        // Done with the attribute changed callback test.
+        runNextTest();
+      }
     }
-  };
 
-  document.registerElement("x-attrchange", { prototype: p });
+    static get observedAttributes() {
+      return ["changeme"];
+    }
+  }
 
-  var createdElement = document.createElement("x-attrchange");
-  is(createdCallbackThis, createdElement, "The 'this' value in the created callback should be the custom element.");
+  customElements.define("x-attrchange", AttrChange);
+
+  createdElement = document.createElement("x-attrchange");
   createdElement.setAttribute("changeme", "newvalue");
   createdElement.setAttribute("changeme", "nextvalue");
   createdElement.setAttribute("changeme", "");
   createdElement.removeAttribute("changeme");
 }
 
 function testAttributeChangedExtended() {
-  var p = Object.create(HTMLButtonElement.prototype);
-  var callbackCalled = 0;
-  p.attributeChangedCallback = function(name, oldValue, newValue) {
-    callbackCalled++;
-    if (callbackCalled > 2) {
-      is(false, "Got unexpected attribute changed callback.");
-    } else if (callbackCalled === 2) {
+  var callbackCalled = false;
+
+  class ExtnededAttributeChange extends HTMLButtonElement
+  {
+    attributeChangedCallback(name, oldValue, newValue) {
+      is(callbackCalled, false, "Callback should only be called once in this test.");
+      callbackCalled = true;
       runNextTest();
     }
-  };
 
-  document.registerElement("x-extended-attribute-change", { prototype: p, extends: "button" });
+    static get observedAttributes() {
+      return ["foo"];
+    }
+  }
+
+  customElements.define("x-extended-attribute-change", ExtnededAttributeChange,
+                        { extends: "button" });
 
   var elem = document.createElement("button", {is: "x-extended-attribute-change"});
   elem.setAttribute("foo", "bar");
 }
 
 // Creates a custom element that is an upgrade candidate (no registration)
 // and mutate the element in ways that would call callbacks for registered
 // elements.
@@ -341,37 +319,37 @@ function testNotInDocEnterLeave() {
   var divNotInDoc = document.createElement("div");
   divNotInDoc.appendChild(createdElement);
   divNotInDoc.removeChild(createdElement);
 
   runNextTest();
 }
 
 function testEnterLeaveView() {
-  var attachedCallbackCalled = false;
-  var detachedCallbackCalled = false;
+  var connectedCallbackCalled = false;
+  var disconnectedCallbackCalled = false;
 
   var p = Object.create(HTMLElement.prototype);
-  p.attachedCallback = function() {
-    is(attachedCallbackCalled, false, "attached callback should only be called on in this test.");
-    attachedCallbackCalled = true;
+  p.connectedCallback = function() {
+    is(connectedCallbackCalled, false, "Connected callback should only be called on in this test.");
+    connectedCallbackCalled = true;
   };
 
-  p.detachedCallback = function() {
-    is(attachedCallbackCalled, true, "attached callback should be called before detached");
-    is(detachedCallbackCalled, false, "detached callback should only be called once in this test.");
-    detachedCallbackCalled = true;
+  p.disconnectedCallback = function() {
+    is(connectedCallbackCalled, true, "Connected callback should be called before detached");
+    is(disconnectedCallbackCalled, false, "Disconnected callback should only be called once in this test.");
+    disconnectedCallbackCalled = true;
     runNextTest();
   };
 
   var div = document.createElement("div");
   document.registerElement("x-element-in-div", { prototype: p });
   var customElement = document.createElement("x-element-in-div");
   div.appendChild(customElement);
-  is(attachedCallbackCalled, false, "Appending a custom element to a node that is not in the document should not call the attached callback.");
+  is(connectedCallbackCalled, false, "Appending a custom element to a node that is not in the document should not call the connected callback.");
 
   container.appendChild(div);
   container.removeChild(div);
 }
 
 var testFunctions = [
   testRegisterUnresolved,
   testRegisterUnresolvedExtended,
@@ -387,16 +365,17 @@ var testFunctions = [
   testNotInDocEnterLeave,
   testEnterLeaveView,
   SimpleTest.finish
 ];
 
 function runNextTest() {
   if (testFunctions.length > 0) {
     var nextTestFunction = testFunctions.shift();
+    info(`Start ${nextTestFunction.name} ...`);
     nextTestFunction();
   }
 }
 
 SimpleTest.waitForExplicitFinish();
 
 runNextTest();
 
rename from dom/tests/mochitest/webcomponents/test_document_register_stack.html
rename to dom/tests/mochitest/webcomponents/test_custom_element_stack.html
--- a/dom/tests/mochitest/webcomponents/test_document_register_stack.html
+++ b/dom/tests/mochitest/webcomponents/test_custom_element_stack.html
@@ -11,139 +11,124 @@ https://bugzilla.mozilla.org/show_bug.cg
 <body>
 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=783129">Bug 783129</a>
 <div id="container">
 </div>
 <script>
 
 var container = document.getElementById("container");
 
-// Test changing attributes in the created callback on an element
-// created after registration.
-function testChangeAttributeInCreatedCallback() {
-  var createdCallbackCalled = false;
+function testChangeAttributeInEnteredViewCallback() {
   var attributeChangedCallbackCalled = false;
-
-  var p = Object.create(HTMLElement.prototype);
-  p.createdCallback = function() {
-    is(createdCallbackCalled, false, "Created callback should be called before attached callback.");
-    createdCallbackCalled = true;
-    is(attributeChangedCallbackCalled, false, "Attribute changed callback should not have been called prior to setting the attribute.");
-    this.setAttribute("foo", "bar");
-    is(attributeChangedCallbackCalled, true, "While element is being created, element should be added to the current element callback queue.");
-    runNextTest();
-  };
-
-  p.attributeChangedCallback = function(name, oldValue, newValue) {
-    is(createdCallbackCalled, true, "attributeChanged callback should be called after the created callback because it was enqueued during created callback.");
-    is(attributeChangedCallbackCalled, false, "attributeChanged callback should only be called once in this tests.");
-    is(newValue, "bar", "The new value should be 'bar'");
-    attributeChangedCallbackCalled = true;
-  };
+  var connectedCallbackCalled = false;
 
-  document.registerElement("x-one", { prototype: p });
-  document.createElement("x-one");
-}
-
-function testChangeAttributeInEnteredViewCallback() {
-  var p = Object.create(HTMLElement.prototype);
-  var attributeChangedCallbackCalled = false;
-  var attachedCallbackCalled = false;
+  class Two extends HTMLElement
+  {
+    connectedCallback() {
+      is(connectedCallbackCalled, false, "Connected callback should be called only once in this test.");
+      connectedCallbackCalled = true;
+      is(attributeChangedCallbackCalled, false, "Attribute changed callback should not be called before changing attribute.");
+      this.setAttribute("foo", "bar");
+      is(attributeChangedCallbackCalled, true, "Transition from user-agent implementation to script should result in attribute changed callback being called.");
+      runNextTest();
+    }
 
-  p.attachedCallback = function() {
-    is(attachedCallbackCalled, false, "attached callback should be called only once in this test.");
-    attachedCallbackCalled = true;
-    is(attributeChangedCallbackCalled, false, "Attribute changed callback should not be called before changing attribute.");
-    this.setAttribute("foo", "bar");
-    is(attributeChangedCallbackCalled, true, "Transition from user-agent implementation to script should result in attribute changed callback being called.");
-    runNextTest();
-  };
+    attributeChangedCallback() {
+      is(connectedCallbackCalled, true, "Connected callback should have been called prior to attribute changed callback.");
+      is(attributeChangedCallbackCalled, false, "Attribute changed callback should only be called once in this tests.");
+      attributeChangedCallbackCalled = true;
+    }
 
-  p.attributeChangedCallback = function() {
-    is(attachedCallbackCalled, true, "attached callback should have been called prior to attribute changed callback.");
-    is(attributeChangedCallbackCalled, false, "attributeChanged callback should only be called once in this tests.");
-    attributeChangedCallbackCalled = true;
-  };
+    static get observedAttributes() {
+      return ["foo"];
+    }
+  }
 
-  document.registerElement("x-two", { prototype: p });
+  customElements.define("x-two", Two);
   var elem = document.createElement("x-two");
 
   var container = document.getElementById("container");
   container.appendChild(elem);
 }
 
 function testLeaveViewInEnteredViewCallback() {
   var p = Object.create(HTMLElement.prototype);
-  var attachedCallbackCalled = false;
-  var detachedCallbackCalled = false;
+  var connectedCallbackCalled = false;
+  var disconnectedCallbackCalled = false;
   var container = document.getElementById("container");
 
-  p.attachedCallback = function() {
+  p.connectedCallback = function() {
     is(this.parentNode, container, "Parent node should the container in which the node was appended.");
-    is(attachedCallbackCalled, false, "attached callback should be called only once in this test.");
-    attachedCallbackCalled = true;
-    is(detachedCallbackCalled, false, "detached callback should not be called prior to removing element from document.");
+    is(connectedCallbackCalled, false, "Connected callback should be called only once in this test.");
+    connectedCallbackCalled = true;
+    is(disconnectedCallbackCalled, false, "Disconnected callback should not be called prior to removing element from document.");
     container.removeChild(this);
-    is(detachedCallbackCalled, true, "Transition from user-agent implementation to script should run left view callback.");
+    is(disconnectedCallbackCalled, true, "Transition from user-agent implementation to script should run left view callback.");
     runNextTest();
   };
 
-  p.detachedCallback = function() {
-    is(detachedCallbackCalled, false, "The detached callback should only be called once in this test.");
-    is(attachedCallbackCalled, true, "The attached callback should be called prior to detached callback.");
-    detachedCallbackCalled = true;
+  p.disconnectedCallback = function() {
+    is(disconnectedCallbackCalled, false, "The disconnected callback should only be called once in this test.");
+    is(connectedCallbackCalled, true, "The connected callback should be called prior to disconnected callback.");
+    disconnectedCallbackCalled = true;
   };
 
   document.registerElement("x-three", { prototype: p });
   var elem = document.createElement("x-three");
 
   container.appendChild(elem);
 }
 
 function testStackedAttributeChangedCallback() {
-  var p = Object.create(HTMLElement.prototype);
   var attributeChangedCallbackCount = 0;
 
   var attributeSequence = ["foo", "bar", "baz"];
 
-  p.attributeChangedCallback = function(attrName, oldValue, newValue) {
-    if (newValue == "baz") {
-      return;
+  class Four extends HTMLElement
+  {
+    attributeChangedCallback(attrName, oldValue, newValue) {
+      if (newValue == "baz") {
+        return;
+      }
+
+      var nextAttribute = attributeSequence.shift();
+      ok(true, nextAttribute);
+      // Setting this attribute will call this function again, when
+      // control returns to the script, the last attribute in the sequence should
+      // be set on the element.
+      this.setAttribute("foo", nextAttribute);
+      is(this.getAttribute("foo"), "baz", "The last value in the sequence should be the value of the attribute.");
+
+      attributeChangedCallbackCount++;
+      if (attributeChangedCallbackCount == 3) {
+        runNextTest();
+      }
     }
 
-    var nextAttribute = attributeSequence.shift();
-    ok(true, nextAttribute);
-    // Setting this attribute will call this function again, when
-    // control returns to the script, the last attribute in the sequence should
-    // be set on the element.
-    this.setAttribute("foo", nextAttribute);
-    is(this.getAttribute("foo"), "baz", "The last value in the sequence should be the value of the attribute.");
+    static get observedAttributes() {
+      return ["foo"];
+    }
+  }
 
-    attributeChangedCallbackCount++;
-    if (attributeChangedCallbackCount == 3) {
-      runNextTest();
-    }
-  };
-
-  document.registerElement("x-four", { prototype: p });
+  customElements.define("x-four", Four);
   var elem = document.createElement("x-four");
   elem.setAttribute("foo", "changeme");
 }
 
 var testFunctions = [
-  testChangeAttributeInCreatedCallback,
   testChangeAttributeInEnteredViewCallback,
   testLeaveViewInEnteredViewCallback,
   testStackedAttributeChangedCallback,
   SimpleTest.finish
 ];
 
 function runNextTest() {
   if (testFunctions.length > 0) {
     var nextTestFunction = testFunctions.shift();
+    info(`Start ${nextTestFunction.name} ...`);
     nextTestFunction();
   }
 }
 
 SimpleTest.waitForExplicitFinish();
 
 runNextTest();