Throw TypeError when custom element constructor returns a wrong element or tries...
authorrniwa@webkit.org <rniwa@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 15 Apr 2019 21:49:06 +0000 (21:49 +0000)
committerrniwa@webkit.org <rniwa@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 15 Apr 2019 21:49:06 +0000 (21:49 +0000)
https://bugs.webkit.org/show_bug.cgi?id=196892

Reviewed by Dean Jackson.

LayoutTests/imported/w3c:

Update the tests according to https://github.com/web-platform-tests/wpt/pull/16328.

* web-platform-tests/custom-elements/upgrading/Node-cloneNode-expected.txt:
* web-platform-tests/custom-elements/upgrading/Node-cloneNode.html:
* web-platform-tests/custom-elements/upgrading/upgrading-parser-created-element-expected.txt:
* web-platform-tests/custom-elements/upgrading/upgrading-parser-created-element.html:

Source/WebCore:

Throw TypeError instead of InvalidStateError for consistency. This updates WebKit's custom elements
implementation for https://github.com/whatwg/html/pull/4525.

Tests: imported/w3c/web-platform-tests/custom-elements/upgrading/Node-cloneNode.html
       imported/w3c/web-platform-tests/custom-elements/upgrading/upgrading-parser-created-element.html

* bindings/js/JSCustomElementInterface.cpp:
(WebCore::JSCustomElementInterface::upgradeElement):
* bindings/js/JSHTMLElementCustom.cpp:
(WebCore::constructJSHTMLElement):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@244293 268f45cc-cd09-0410-ab3c-d52691b4dbfc

LayoutTests/imported/w3c/ChangeLog
LayoutTests/imported/w3c/web-platform-tests/custom-elements/upgrading/Node-cloneNode-expected.txt
LayoutTests/imported/w3c/web-platform-tests/custom-elements/upgrading/Node-cloneNode.html
LayoutTests/imported/w3c/web-platform-tests/custom-elements/upgrading/upgrading-parser-created-element-expected.txt
LayoutTests/imported/w3c/web-platform-tests/custom-elements/upgrading/upgrading-parser-created-element.html
Source/WebCore/ChangeLog
Source/WebCore/bindings/js/JSCustomElementInterface.cpp
Source/WebCore/bindings/js/JSHTMLElementCustom.cpp

index 6c1f093..99bd619 100644 (file)
@@ -1,3 +1,17 @@
+2019-04-12  Ryosuke Niwa  <rniwa@webkit.org>
+
+        Throw TypeError when custom element constructor returns a wrong element or tries to create itself
+        https://bugs.webkit.org/show_bug.cgi?id=196892
+
+        Reviewed by Dean Jackson.
+
+        Update the tests according to https://github.com/web-platform-tests/wpt/pull/16328.
+
+        * web-platform-tests/custom-elements/upgrading/Node-cloneNode-expected.txt:
+        * web-platform-tests/custom-elements/upgrading/Node-cloneNode.html:
+        * web-platform-tests/custom-elements/upgrading/upgrading-parser-created-element-expected.txt:
+        * web-platform-tests/custom-elements/upgrading/upgrading-parser-created-element.html:
+
 2019-04-12  Rob Buis  <rbuis@igalia.com>
 
         Import WPT preload tests
index ab438ec..b33b3ad 100644 (file)
@@ -5,8 +5,8 @@ FAIL Node.prototype.cloneNode(false) must be able to clone as a customized built
 PASS Node.prototype.cloneNode(false) must be able to clone a custom element inside an iframe 
 PASS Node.prototype.cloneNode(true) must be able to clone a descendent custom element 
 PASS Node.prototype.cloneNode(true) must set parentNode, previousSibling, and nextSibling before upgrading custom elements 
-PASS HTMLElement constructor must throw an InvalidStateError when the top of the construction stack is marked AlreadyConstructed due to a custom element constructor constructing itself after super() call 
-PASS HTMLElement constructor must throw an InvalidStateError when the top of the construction stack is marked AlreadyConstructed due to a custom element constructor constructing itself before super() call 
-PASS Upgrading a custom element must throw InvalidStateError when the custom element's constructor returns another element 
+PASS HTMLElement constructor must throw an TypeError when the top of the construction stack is marked AlreadyConstructed due to a custom element constructor constructing itself after super() call 
+PASS HTMLElement constructor must throw an TypeError when the top of the construction stack is marked AlreadyConstructed due to a custom element constructor constructing itself before super() call 
+PASS Upgrading a custom element must throw TypeError when the custom element's constructor returns another element 
 PASS Inserting an element must not try to upgrade a custom element when it had already failed to upgrade once 
 
index 1a8786e..364cecd 100644 (file)
@@ -165,8 +165,8 @@ test(function () {
     var uncaughtError;
     window.onerror = function (message, url, lineNumber, columnNumber, error) { uncaughtError = error; return true; }
     instance.cloneNode(false);
-    assert_equals(uncaughtError.name, 'InvalidStateError');
-}, 'HTMLElement constructor must throw an InvalidStateError when the top of the construction stack is marked AlreadyConstructed'
+    assert_equals(uncaughtError.name, 'TypeError');
+}, 'HTMLElement constructor must throw an TypeError when the top of the construction stack is marked AlreadyConstructed'
     + ' due to a custom element constructor constructing itself after super() call');
 
 test(function () {
@@ -183,8 +183,8 @@ test(function () {
     var uncaughtError;
     window.onerror = function (message, url, lineNumber, columnNumber, error) { uncaughtError = error; return true; }
     instance.cloneNode(false);
-    assert_equals(uncaughtError.name, 'InvalidStateError');
-}, 'HTMLElement constructor must throw an InvalidStateError when the top of the construction stack is marked AlreadyConstructed'
+    assert_equals(uncaughtError.name, 'TypeError');
+}, 'HTMLElement constructor must throw an TypeError when the top of the construction stack is marked AlreadyConstructed'
     + ' due to a custom element constructor constructing itself before super() call');
 
 test(function () {
@@ -203,8 +203,8 @@ test(function () {
     var uncaughtError;
     window.onerror = function (message, url, lineNumber, columnNumber, error) { uncaughtError = error; return true; }
     instance.cloneNode(false);
-    assert_equals(uncaughtError.name, 'InvalidStateError');
-}, 'Upgrading a custom element must throw InvalidStateError when the custom element\'s constructor returns another element');
+    assert_equals(uncaughtError.name, 'TypeError');
+}, 'Upgrading a custom element must throw TypeError when the custom element\'s constructor returns another element');
 
 test(function () {
     var instance = document.createElement('my-custom-element-throw-exception');
index 680cbf6..c6f5a6f 100644 (file)
@@ -1,6 +1,8 @@
 
 PASS Element.prototype.createElement must add an unresolved custom element to the upgrade candidates map 
-PASS HTMLElement constructor must throw an InvalidStateError when the top of the construction stack is marked AlreadyConstructed due to a custom element constructor constructing itself after super() call 
-PASS HTMLElement constructor must throw an InvalidStateError when the top of the construction stack is marked AlreadyConstructed due to a custom element constructor constructing itself before super() call 
-PASS Upgrading a custom element must throw an InvalidStateError when the returned element is not SameValue as the upgraded element 
+PASS HTMLElement constructor must throw an TypeError when the top of the construction stack is marked AlreadyConstructed due to a custom element constructor constructing itself after super() call 
+PASS HTMLElement constructor must throw an TypeError when the top of the construction stack is marked AlreadyConstructed due to a custom element constructor constructing itself before super() call 
+PASS Upgrading a custom element must throw an TypeError when the returned element is not SameValue as the upgraded element 
+PASS Upgrading a custom element whose constructor returns a Text node must throw 
+PASS Upgrading a custom element whose constructor returns an Element must throw 
 
index 7cc3b18..0f7f957 100644 (file)
@@ -15,6 +15,8 @@
 <instantiates-itself-before-super></instantiates-itself-before-super>
 <my-other-element id="instance"></my-other-element>
 <my-other-element id="otherInstance"></my-other-element>
+<not-an-element></not-an-element>
+<not-an-html-element></not-an-html-element>
 <script>
 
 setup({allow_uncaught_exception:true});
@@ -48,8 +50,8 @@ test(function () {
     var uncaughtError;
     window.onerror = function (message, url, lineNumber, columnNumber, error) { uncaughtError = error; return true; }
     customElements.define('instantiates-itself-after-super', InstantiatesItselfAfterSuper);
-    assert_equals(uncaughtError.name, 'InvalidStateError');
-}, 'HTMLElement constructor must throw an InvalidStateError when the top of the construction stack is marked AlreadyConstructed'
+    assert_equals(uncaughtError.name, 'TypeError');
+}, 'HTMLElement constructor must throw an TypeError when the top of the construction stack is marked AlreadyConstructed'
     + ' due to a custom element constructor constructing itself after super() call');
 
 test(function () {
@@ -64,8 +66,8 @@ test(function () {
     var uncaughtError;
     window.onerror = function (message, url, lineNumber, columnNumber, error) { uncaughtError = error; return true; }
     customElements.define('instantiates-itself-before-super', InstantiatesItselfBeforeSuper);
-    assert_equals(uncaughtError.name, 'InvalidStateError');
-}, 'HTMLElement constructor must throw an InvalidStateError when the top of the construction stack is marked AlreadyConstructed'
+    assert_equals(uncaughtError.name, 'TypeError');
+}, 'HTMLElement constructor must throw an TypeError when the top of the construction stack is marked AlreadyConstructed'
     + ' due to a custom element constructor constructing itself before super() call');
 
 test(function () {
@@ -85,12 +87,38 @@ test(function () {
     var uncaughtError;
     window.onerror = function (message, url, lineNumber, columnNumber, error) { uncaughtError = error; return true; }
     customElements.define('my-other-element', MyOtherElement);
-    assert_equals(uncaughtError.name, 'InvalidStateError');
+    assert_equals(uncaughtError.name, 'TypeError');
 
     assert_true(document.createElement('my-other-element') instanceof MyOtherElement,
         'Upgrading of custom elements must happen after the definition was added to the registry.');
 
-}, 'Upgrading a custom element must throw an InvalidStateError when the returned element is not SameValue as the upgraded element');
+}, 'Upgrading a custom element must throw an TypeError when the returned element is not SameValue as the upgraded element');
+
+test(() => {
+  class NotAnElement extends HTMLElement {
+    constructor() {
+      return new Text();
+    }
+  }
+
+  let uncaughtError;
+  window.onerror = function (message, url, lineNumber, columnNumber, error) { uncaughtError = error; return true; }
+  customElements.define("not-an-element", NotAnElement);
+  assert_equals(uncaughtError.name, "TypeError");
+}, "Upgrading a custom element whose constructor returns a Text node must throw");
+
+test(() => {
+  class NotAnHTMLElement extends HTMLElement {
+    constructor() {
+      return document.createElementNS("", "test");
+    }
+  }
+
+  let uncaughtError;
+  window.onerror = function (message, url, lineNumber, columnNumber, error) { uncaughtError = error; return true; }
+  customElements.define("not-an-html-element", NotAnHTMLElement);
+  assert_equals(uncaughtError.name, "TypeError");
+}, "Upgrading a custom element whose constructor returns an Element must throw");
 
 </script>
 </body>
index 0d2047c..9ce2213 100644 (file)
@@ -1,3 +1,21 @@
+2019-04-12  Ryosuke Niwa  <rniwa@webkit.org>
+
+        Throw TypeError when custom element constructor returns a wrong element or tries to create itself
+        https://bugs.webkit.org/show_bug.cgi?id=196892
+
+        Reviewed by Dean Jackson.
+
+        Throw TypeError instead of InvalidStateError for consistency. This updates WebKit's custom elements
+        implementation for https://github.com/whatwg/html/pull/4525.
+
+        Tests: imported/w3c/web-platform-tests/custom-elements/upgrading/Node-cloneNode.html
+               imported/w3c/web-platform-tests/custom-elements/upgrading/upgrading-parser-created-element.html
+
+        * bindings/js/JSCustomElementInterface.cpp:
+        (WebCore::JSCustomElementInterface::upgradeElement):
+        * bindings/js/JSHTMLElementCustom.cpp:
+        (WebCore::constructJSHTMLElement):
+
 2019-04-15  Don Olmstead  <don.olmstead@sony.com>
 
         [CMake] WebCore derived sources should only be referenced inside WebCore
index 9ccb1f4..9ff543f 100644 (file)
@@ -214,7 +214,7 @@ void JSCustomElementInterface::upgradeElement(Element& element)
     Element* wrappedElement = JSElement::toWrapped(vm, returnedElement);
     if (!wrappedElement || wrappedElement != &element) {
         element.setIsFailedCustomElement(*this);
-        reportException(state, createDOMException(state, InvalidStateError, "Custom element constructor failed to upgrade an element"));
+        reportException(state, createDOMException(state, TypeError, "Custom element constructor returned a wrong element"));
         return;
     }
     element.setIsDefinedCustomElement(*this);
index fa5d081..7a29ba2 100644 (file)
@@ -89,7 +89,7 @@ EncodedJSValue JSC_HOST_CALL constructJSHTMLElement(ExecState& exec)
 
     Element* elementToUpgrade = elementInterface->lastElementInConstructionStack();
     if (!elementToUpgrade) {
-        throwInvalidStateError(exec, scope, "Cannot instantiate a custom element inside its own constructor during upgrades"_s);
+        throwTypeError(&exec, scope, "Cannot instantiate a custom element inside its own constructor during upgrades"_s);
         return JSValue::encode(jsUndefined());
     }