Title: [205263] trunk
Revision
205263
Author
[email protected]
Date
2016-08-31 12:53:44 -0700 (Wed, 31 Aug 2016)

Log Message

HTML constructor must throw when newTarget is itself
https://bugs.webkit.org/show_bug.cgi?id=161430

Reviewed by Antti Koivisto.

Source/WebCore:

Per https://github.com/w3c/webcomponents/issues/541, we must throw a TypeError when the HTMLElement constructor
is called with new.target set to itself (i.e. new HTMLElement after registering it with a custom element).

Note that we can't check this at the time of customElements.define because it could be a Proxy object.

Also see: https://html.spec.whatwg.org/#html-element-constructors

Tests: fast/custom-elements/CustomElementRegistry.html
       fast/custom-elements/HTMLElement-constructor.html

* bindings/js/JSHTMLElementCustom.cpp:
(WebCore::constructJSHTMLElement): Throw a TypeError when NewTarget is HTMLElement constructor itself.

LayoutTests:

Added test cases for defining a custom element with the HTMLElement constructor,
and making sure the HTMLElement constructor throws an exception when newTarget is itself.

* fast/custom-elements/CustomElementRegistry-expected.txt:
* fast/custom-elements/CustomElementRegistry.html:
* fast/custom-elements/HTMLElement-constructor-expected.txt:
* fast/custom-elements/HTMLElement-constructor.html:

Modified Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (205262 => 205263)


--- trunk/LayoutTests/ChangeLog	2016-08-31 19:39:06 UTC (rev 205262)
+++ trunk/LayoutTests/ChangeLog	2016-08-31 19:53:44 UTC (rev 205263)
@@ -1,5 +1,20 @@
 2016-08-31  Ryosuke Niwa  <[email protected]>
 
+        HTML constructor must throw when newTarget is itself
+        https://bugs.webkit.org/show_bug.cgi?id=161430
+
+        Reviewed by Antti Koivisto.
+
+        Added test cases for defining a custom element with the HTMLElement constructor,
+        and making sure the HTMLElement constructor throws an exception when newTarget is itself.
+
+        * fast/custom-elements/CustomElementRegistry-expected.txt:
+        * fast/custom-elements/CustomElementRegistry.html:
+        * fast/custom-elements/HTMLElement-constructor-expected.txt:
+        * fast/custom-elements/HTMLElement-constructor.html:
+
+2016-08-31  Ryosuke Niwa  <[email protected]>
+
         Add the check for reentrancy to CustomElementRegistry
         https://bugs.webkit.org/show_bug.cgi?id=161423
 

Modified: trunk/LayoutTests/fast/custom-elements/CustomElementRegistry-expected.txt (205262 => 205263)


--- trunk/LayoutTests/fast/custom-elements/CustomElementRegistry-expected.txt	2016-08-31 19:39:06 UTC (rev 205262)
+++ trunk/LayoutTests/fast/custom-elements/CustomElementRegistry-expected.txt	2016-08-31 19:53:44 UTC (rev 205263)
@@ -1,6 +1,7 @@
 
 PASS CustomElementRegistry interface must have define as a method 
 PASS customElements.define must throw when the element interface is not a constructor 
+PASS customElements.define must not throw the constructor is HTMLElement 
 PASS customElements.define must throw with an invalid name 
 PASS customElements.define must throw when there is already a custom element of the same name 
 PASS customElements.define must throw a NotSupportedError when there is already a custom element with the same class 

Modified: trunk/LayoutTests/fast/custom-elements/CustomElementRegistry.html (205262 => 205263)


--- trunk/LayoutTests/fast/custom-elements/CustomElementRegistry.html	2016-08-31 19:39:06 UTC (rev 205262)
+++ trunk/LayoutTests/fast/custom-elements/CustomElementRegistry.html	2016-08-31 19:53:44 UTC (rev 205263)
@@ -29,6 +29,10 @@
 }, 'customElements.define must throw when the element interface is not a constructor');
 
 test(function () {
+    customElements.define('custom-html-element', HTMLElement);
+}, 'customElements.define must not throw the constructor is HTMLElement');
+
+test(function () {
     class MyCustomElement extends HTMLElement {};
 
     assert_throws({'name': 'SyntaxError'}, function () { customElements.define(null, MyCustomElement); },

Modified: trunk/LayoutTests/fast/custom-elements/HTMLElement-constructor-expected.txt (205262 => 205263)


--- trunk/LayoutTests/fast/custom-elements/HTMLElement-constructor-expected.txt	2016-08-31 19:39:06 UTC (rev 205262)
+++ trunk/LayoutTests/fast/custom-elements/HTMLElement-constructor-expected.txt	2016-08-31 19:53:44 UTC (rev 205263)
@@ -1,6 +1,7 @@
 
-PASS HTMLElement constructor must throw a TypeError when there is no derived class 
-PASS HTMLElement constructor must throw TypeError when custom element is not well defined 
+PASS HTMLElement constructor must throw a TypeError when NewTarget is equal to itself 
+PASS HTMLElement constructor must throw a TypeError when NewTarget is equal to itself via a Proxy object 
+PASS HTMLElement constructor must throw TypeError when it has not been defined by customElements.define 
 PASS HTMLElement constructor must infer the tag name from the element interface 
 PASS HTMLElement constructor must allow subclassing a custom element 
 PASS HTMLElement constructor must allow subclassing an user-defined subclass of HTMLElement 

Modified: trunk/LayoutTests/fast/custom-elements/HTMLElement-constructor.html (205262 => 205263)


--- trunk/LayoutTests/fast/custom-elements/HTMLElement-constructor.html	2016-08-31 19:39:06 UTC (rev 205262)
+++ trunk/LayoutTests/fast/custom-elements/HTMLElement-constructor.html	2016-08-31 19:53:44 UTC (rev 205263)
@@ -4,6 +4,7 @@
 <title>Custom Elements: HTMLElement must allow subclassing</title>
 <meta name="author" title="Ryosuke Niwa" href=""
 <meta name="assert" content="HTMLElement must allow subclassing">
+<link rel="help" href=""
 <script src=""
 <script src=""
 <link rel='stylesheet' href=''>
@@ -13,16 +14,19 @@
 <script>
 
 test(function () {
-    class SomeDefinedElement extends HTMLElement {};
-    customElements.define('defined-element', SomeDefinedElement);
-    assert_throws({'name': 'TypeError'}, function () { new HTMLElement('defined-element'); });
-}, 'HTMLElement constructor must throw a TypeError when there is no derived class');
+    customElements.define('html-custom-element', HTMLElement);
+    assert_throws({'name': 'TypeError'}, function () { new HTMLElement(); });
+}, 'HTMLElement constructor must throw a TypeError when NewTarget is equal to itself');
 
 test(function () {
+    customElements.define('html-proxy-custom-element', new Proxy(HTMLElement, {}));
+    assert_throws({'name': 'TypeError'}, function () { new HTMLElement(); });
+}, 'HTMLElement constructor must throw a TypeError when NewTarget is equal to itself via a Proxy object');
+
+test(function () {
     class SomeCustomElement extends HTMLElement {};
-    assert_throws({'name': 'TypeError'}, function () { new SomeCustomElement; },
-        'Instantiating a custom element without calling customElements.define must throw TypeError');
-}, 'HTMLElement constructor must throw TypeError when custom element is not well defined');
+    assert_throws({'name': 'TypeError'}, function () { new SomeCustomElement; });
+}, 'HTMLElement constructor must throw TypeError when it has not been defined by customElements.define');
 
 test(function () {
     class CustomElementWithInferredTagName extends HTMLElement {};

Modified: trunk/Source/WebCore/ChangeLog (205262 => 205263)


--- trunk/Source/WebCore/ChangeLog	2016-08-31 19:39:06 UTC (rev 205262)
+++ trunk/Source/WebCore/ChangeLog	2016-08-31 19:53:44 UTC (rev 205263)
@@ -1,5 +1,25 @@
 2016-08-31  Ryosuke Niwa  <[email protected]>
 
+        HTML constructor must throw when newTarget is itself
+        https://bugs.webkit.org/show_bug.cgi?id=161430
+
+        Reviewed by Antti Koivisto.
+
+        Per https://github.com/w3c/webcomponents/issues/541, we must throw a TypeError when the HTMLElement constructor
+        is called with new.target set to itself (i.e. new HTMLElement after registering it with a custom element).
+
+        Note that we can't check this at the time of customElements.define because it could be a Proxy object.
+
+        Also see: https://html.spec.whatwg.org/#html-element-constructors
+
+        Tests: fast/custom-elements/CustomElementRegistry.html
+               fast/custom-elements/HTMLElement-constructor.html
+
+        * bindings/js/JSHTMLElementCustom.cpp:
+        (WebCore::constructJSHTMLElement): Throw a TypeError when NewTarget is HTMLElement constructor itself.
+
+2016-08-31  Ryosuke Niwa  <[email protected]>
+
         Rebaseline binding tests after r205257.
 
         * bindings/scripts/test/JS/JSTestObj.cpp:

Modified: trunk/Source/WebCore/bindings/js/JSHTMLElementCustom.cpp (205262 => 205263)


--- trunk/Source/WebCore/bindings/js/JSHTMLElementCustom.cpp	2016-08-31 19:39:06 UTC (rev 205262)
+++ trunk/Source/WebCore/bindings/js/JSHTMLElementCustom.cpp	2016-08-31 19:53:44 UTC (rev 205263)
@@ -54,6 +54,12 @@
         return throwConstructorScriptExecutionContextUnavailableError(exec, scope, "HTMLElement");
     ASSERT(context->isDocument());
 
+    JSValue newTargetValue = exec.thisValue();
+    auto* globalObject = jsConstructor->globalObject();
+    JSValue htmlElementConstructorValue = JSHTMLElement::getConstructor(vm, globalObject);
+    if (newTargetValue == htmlElementConstructorValue)
+        return throwVMTypeError(&exec, scope, ASCIILiteral("new.target is not a valid custom element constructor"));
+
     auto& document = downcast<Document>(*context);
 
     auto* window = document.domWindow();
@@ -64,7 +70,6 @@
     if (!registry)
         return throwVMTypeError(&exec, scope, ASCIILiteral("new.target is not a valid custom element constructor"));
 
-    JSValue newTargetValue = exec.thisValue();
     JSObject* newTarget = newTargetValue.getObject();
     auto* elementInterface = registry->findInterface(newTarget);
     if (!elementInterface)
@@ -71,7 +76,6 @@
         return throwVMTypeError(&exec, scope, ASCIILiteral("new.target does not define a custom element"));
 
     if (!elementInterface->isUpgradingElement()) {
-        auto* globalObject = jsConstructor->globalObject();
         Structure* baseStructure = getDOMStructure<JSHTMLElement>(vm, *globalObject);
         auto* newElementStructure = InternalFunction::createSubclassStructure(&exec, newTargetValue, baseStructure);
         if (UNLIKELY(exec.hadException()))
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to