<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[206890] trunk</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/206890">206890</a></dd>
<dt>Author</dt> <dd>rniwa@webkit.org</dd>
<dt>Date</dt> <dd>2016-10-06 17:46:31 -0700 (Thu, 06 Oct 2016)</dd>
</dl>

<h3>Log Message</h3>
<pre>Upgrading and constructing element should always report exception instead of rethrowing
https://bugs.webkit.org/show_bug.cgi?id=162996

Reviewed by Darin Adler.

Source/WebCore:

The latest HTML specification specifies that we must report exceptions thrown during element upgrades:
https://html.spec.whatwg.org/#upgrades

In addition, F2F during 2016 TPAC had a consensus that we should do the same for document.createElement:
https://github.com/w3c/webcomponents/issues/569

Since the HTML parser already reports the exception thrown during custom element construction as it does
not have any JS stack, these changes make exceptions thrown during upgrades and constructions.

In our implementation, this only reduces the code complexity as now we can push the logic to fallback
to HTMLUnknownElement into JSCustomElementInterface's constructElement, which has been renamed
to constructElementWithFallback, and eliminate ShouldClearException enum class entirely. Moreover,
constructElementWithFallback can now return Ref instead of RefPtr.

No new tests. Existing tests have been updated.

* bindings/js/JSCustomElementInterface.cpp:
(WebCore::JSCustomElementInterface::constructElementWithFallback): Create a HTMLUnknownElement if
an attempt to construct a custom element had failed in lieu of returning nullptr.
(WebCore::JSCustomElementInterface::tryToConstructCustomElement): Renamed from constructElement.
Always report exceptions (the same behavior as ShouldClearException::Clear).
(WebCore::JSCustomElementInterface::upgradeElement): Report exceptions instead of rethrowing.
* bindings/js/JSCustomElementInterface.h:
* dom/Document.cpp:
(WebCore::createHTMLElementWithNameValidation):
* html/parser/HTMLDocumentParser.cpp:
(WebCore::HTMLDocumentParser::runScriptsForPausedTreeBuilder):

LayoutTests:

Updated the tests to expect exceptions thrown during custom element constructions are always reported.

* fast/custom-elements/Document-createElement-expected.txt:
* fast/custom-elements/Document-createElement.html:
* fast/custom-elements/defined-pseudo-class-expected.txt:
* fast/custom-elements/defined-pseudo-class.html:
* fast/custom-elements/upgrading/Node-cloneNode.html:
* fast/custom-elements/upgrading/upgrading-parser-created-element.html:</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsChangeLog">trunk/LayoutTests/ChangeLog</a></li>
<li><a href="#trunkLayoutTestsfastcustomelementsDocumentcreateElementexpectedtxt">trunk/LayoutTests/fast/custom-elements/Document-createElement-expected.txt</a></li>
<li><a href="#trunkLayoutTestsfastcustomelementsDocumentcreateElementhtml">trunk/LayoutTests/fast/custom-elements/Document-createElement.html</a></li>
<li><a href="#trunkLayoutTestsfastcustomelementsdefinedpseudoclassexpectedtxt">trunk/LayoutTests/fast/custom-elements/defined-pseudo-class-expected.txt</a></li>
<li><a href="#trunkLayoutTestsfastcustomelementsdefinedpseudoclasshtml">trunk/LayoutTests/fast/custom-elements/defined-pseudo-class.html</a></li>
<li><a href="#trunkLayoutTestsfastcustomelementsupgradingNodecloneNodehtml">trunk/LayoutTests/fast/custom-elements/upgrading/Node-cloneNode.html</a></li>
<li><a href="#trunkLayoutTestsfastcustomelementsupgradingupgradingparsercreatedelementhtml">trunk/LayoutTests/fast/custom-elements/upgrading/upgrading-parser-created-element.html</a></li>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCorebindingsjsJSCustomElementInterfacecpp">trunk/Source/WebCore/bindings/js/JSCustomElementInterface.cpp</a></li>
<li><a href="#trunkSourceWebCorebindingsjsJSCustomElementInterfaceh">trunk/Source/WebCore/bindings/js/JSCustomElementInterface.h</a></li>
<li><a href="#trunkSourceWebCoredomDocumentcpp">trunk/Source/WebCore/dom/Document.cpp</a></li>
<li><a href="#trunkSourceWebCorehtmlparserHTMLDocumentParsercpp">trunk/Source/WebCore/html/parser/HTMLDocumentParser.cpp</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/ChangeLog (206889 => 206890)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/ChangeLog        2016-10-07 00:16:36 UTC (rev 206889)
+++ trunk/LayoutTests/ChangeLog        2016-10-07 00:46:31 UTC (rev 206890)
</span><span class="lines">@@ -1,3 +1,19 @@
</span><ins>+2016-10-06  Ryosuke Niwa  &lt;rniwa@webkit.org&gt;
+
+        Upgrading and constructing element should always report exception instead of rethrowing
+        https://bugs.webkit.org/show_bug.cgi?id=162996
+
+        Reviewed by Darin Adler.
+
+        Updated the tests to expect exceptions thrown during custom element constructions are always reported.
+
+        * fast/custom-elements/Document-createElement-expected.txt:
+        * fast/custom-elements/Document-createElement.html:
+        * fast/custom-elements/defined-pseudo-class-expected.txt:
+        * fast/custom-elements/defined-pseudo-class.html:
+        * fast/custom-elements/upgrading/Node-cloneNode.html:
+        * fast/custom-elements/upgrading/upgrading-parser-created-element.html:
+
</ins><span class="cx"> 2016-10-06  Jiewen Tan  &lt;jiewen_tan@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Add a dummy SubtleCrypto interface
</span></span></pre></div>
<a id="trunkLayoutTestsfastcustomelementsDocumentcreateElementexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/fast/custom-elements/Document-createElement-expected.txt (206889 => 206890)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/custom-elements/Document-createElement-expected.txt        2016-10-07 00:16:36 UTC (rev 206889)
+++ trunk/LayoutTests/fast/custom-elements/Document-createElement-expected.txt        2016-10-07 00:46:31 UTC (rev 206890)
</span><span class="lines">@@ -1,37 +1,37 @@
</span><span class="cx"> 
</span><span class="cx"> PASS document.createElement must create an instance of custom elements 
</span><del>-PASS document.createElement must throw a TypeError when the result of Construct is not a DOM node 
-PASS document.createElement must throw a TypeError when the result of Construct is a TextNode 
-PASS document.createElement must throw a NotSupportedError when attribute is added by setAttribute during construction 
-PASS document.createElement must throw a NotSupportedError when attribute is added by attributes.setNamedItem during construction 
-PASS document.createElement must not throw a NotSupportedError when attribute is added and removed during construction 
-PASS document.createElement must throw a NotSupportedError when a Text child is added during construction 
-PASS document.createElement must throw a NotSupportedError when a Comment child is added during construction 
-PASS document.createElement must throw a NotSupportedError when an element child is added during construction 
-PASS document.createElement must not throw a NotSupportedError when an element child is added and removed during construction 
-PASS document.createElement must throw a NotSupportedError when the element gets inserted into another element during construction 
-PASS document.createElement must not throw a NotSupportedError when the element is inserted and removed from another element during construction 
-PASS document.createElement must throw a NotSupportedError when the element is adopted into a document of a template element during construction 
-PASS document.createElement must throw a NotSupportedError when the element is inserted into a document of a template element during construction 
-PASS document.createElement must not throw a NotSupportedError when the element is adopted back from a document of a template element during construction 
-PASS document.createElement must throw a NotSupportedError when the element is adopted into a new document during construction 
-PASS document.createElement must throw a NotSupportedError when the element is inserted into a new document during construction 
-PASS document.createElement must not throw a NotSupportedError when the element is adopted back from a new document during construction 
-PASS document.createElement must throw a NotSupportedError when the element is adopted into a cloned document during construction 
-PASS document.createElement must throw a NotSupportedError when the element is inserted into a cloned document during construction 
-PASS document.createElement must not throw a NotSupportedError when the element is adopted back from a cloned document during construction 
-PASS document.createElement must throw a NotSupportedError when the element is adopted into a document created by createHTMLDocument during construction 
-PASS document.createElement must throw a NotSupportedError when the element is inserted into a document created by createHTMLDocument during construction 
-PASS document.createElement must not throw a NotSupportedError when the element is adopted back from a document created by createHTMLDocument during construction 
-PASS document.createElement must throw a NotSupportedError when the element is adopted into a HTML document created by createDocument during construction 
-PASS document.createElement must throw a NotSupportedError when the element is inserted into a HTML document created by createDocument during construction 
-PASS document.createElement must not throw a NotSupportedError when the element is adopted back from a HTML document created by createDocument during construction 
-PASS document.createElement must throw a NotSupportedError when the element is adopted into a document in an iframe during construction 
-PASS document.createElement must throw a NotSupportedError when the element is inserted into a document in an iframe during construction 
-PASS document.createElement must not throw a NotSupportedError when the element is adopted back from a document in an iframe during construction 
-PASS document.createElement must throw a NotSupportedError when the element is adopted into a HTML document fetched by XHR during construction 
-PASS document.createElement must throw a NotSupportedError when the element is inserted into a HTML document fetched by XHR during construction 
-PASS document.createElement must not throw a NotSupportedError when the element is adopted back from a HTML document fetched by XHR during construction 
-PASS document.createElement must throw a NotSupportedError when the local name of the element does not match that of the custom element 
-PASS document.createElement must re-throw an exception thrown by a custom element constructor 
</del><ins>+PASS document.createElement must report a TypeError when the result of Construct is not a DOM node 
+PASS document.createElement must report a TypeError when the result of Construct is a TextNode 
+PASS document.createElement must report a NotSupportedError when attribute is added by setAttribute during construction 
+PASS document.createElement must report a NotSupportedError when attribute is added by attributes.setNamedItem during construction 
+PASS document.createElement must not report a NotSupportedError when attribute is added and removed during construction 
+PASS document.createElement must report a NotSupportedError when a Text child is added during construction 
+PASS document.createElement must report a NotSupportedError when a Comment child is added during construction 
+PASS document.createElement must report a NotSupportedError when an element child is added during construction 
+PASS document.createElement must not report a NotSupportedError when an element child is added and removed during construction 
+PASS document.createElement must report a NotSupportedError when the element gets inserted into another element during construction 
+PASS document.createElement must not report a NotSupportedError when the element is inserted and removed from another element during construction 
+PASS document.createElement must report a NotSupportedError when the element is adopted into a document of a template element during construction 
+PASS document.createElement must report a NotSupportedError when the element is inserted into a document of a template element during construction 
+PASS document.createElement must not report a NotSupportedError when the element is adopted back from a document of a template element during construction 
+PASS document.createElement must report a NotSupportedError when the element is adopted into a new document during construction 
+PASS document.createElement must report a NotSupportedError when the element is inserted into a new document during construction 
+PASS document.createElement must not report a NotSupportedError when the element is adopted back from a new document during construction 
+PASS document.createElement must report a NotSupportedError when the element is adopted into a cloned document during construction 
+PASS document.createElement must report a NotSupportedError when the element is inserted into a cloned document during construction 
+PASS document.createElement must not report a NotSupportedError when the element is adopted back from a cloned document during construction 
+PASS document.createElement must report a NotSupportedError when the element is adopted into a document created by createHTMLDocument during construction 
+PASS document.createElement must report a NotSupportedError when the element is inserted into a document created by createHTMLDocument during construction 
+PASS document.createElement must not report a NotSupportedError when the element is adopted back from a document created by createHTMLDocument during construction 
+PASS document.createElement must report a NotSupportedError when the element is adopted into a HTML document created by createDocument during construction 
+PASS document.createElement must report a NotSupportedError when the element is inserted into a HTML document created by createDocument during construction 
+PASS document.createElement must not report a NotSupportedError when the element is adopted back from a HTML document created by createDocument during construction 
+PASS document.createElement must report a NotSupportedError when the element is adopted into a document in an iframe during construction 
+PASS document.createElement must report a NotSupportedError when the element is inserted into a document in an iframe during construction 
+PASS document.createElement must not report a NotSupportedError when the element is adopted back from a document in an iframe during construction 
+PASS document.createElement must report a NotSupportedError when the element is adopted into a HTML document fetched by XHR during construction 
+PASS document.createElement must report a NotSupportedError when the element is inserted into a HTML document fetched by XHR during construction 
+PASS document.createElement must not report a NotSupportedError when the element is adopted back from a HTML document fetched by XHR during construction 
+PASS document.createElement must report a NotSupportedError when the local name of the element does not match that of the custom element 
+PASS document.createElement must report an exception thrown by a custom element constructor 
</ins><span class="cx"> 
</span></span></pre></div>
<a id="trunkLayoutTestsfastcustomelementsDocumentcreateElementhtml"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/fast/custom-elements/Document-createElement.html (206889 => 206890)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/custom-elements/Document-createElement.html        2016-10-07 00:16:36 UTC (rev 206889)
+++ trunk/LayoutTests/fast/custom-elements/Document-createElement.html        2016-10-07 00:46:31 UTC (rev 206890)
</span><span class="lines">@@ -12,6 +12,7 @@
</span><span class="cx"> &lt;body&gt;
</span><span class="cx"> &lt;div id=&quot;log&quot;&gt;&lt;/div&gt;
</span><span class="cx"> &lt;script&gt;
</span><ins>+setup({allow_uncaught_exception:true});
</ins><span class="cx"> 
</span><span class="cx"> test(function () {
</span><span class="cx">     class MyCustomElement extends HTMLElement {};
</span><span class="lines">@@ -27,6 +28,23 @@
</span><span class="cx"> 
</span><span class="cx"> }, 'document.createElement must create an instance of custom elements');
</span><span class="cx"> 
</span><ins>+function assert_reports(expected, testFunction, message) {
+    var uncaughtError = null;
+    window.onerror = function (message, url, lineNumber, columnNumber, error) { uncaughtError = error; return true; }
+    testFunction();
+    if (typeof(expected) == 'string')
+        assert_equals(uncaughtError, expected, message);
+    else if (expected &amp;&amp; 'name' in expected)
+        assert_equals(uncaughtError.name, expected.name, message);
+    else
+      assert_equals(uncaughtError, expected, message);
+    window.onerror = null;
+}
+
+function assert_not_reports(testFunction, message) {
+    assert_reports(null, testFunction, message);
+}
+
</ins><span class="cx"> test(function () {
</span><span class="cx">     class ObjectCustomElement extends HTMLElement {
</span><span class="cx">         constructor()
</span><span class="lines">@@ -40,8 +58,11 @@
</span><span class="cx">     assert_true(instance instanceof Object);
</span><span class="cx">     assert_equals(instance.foo, 'bar');
</span><span class="cx"> 
</span><del>-    assert_throws({name: 'TypeError'}, function () { document.createElement('object-custom-element'); });
-}, 'document.createElement must throw a TypeError when the result of Construct is not a DOM node');
</del><ins>+    var instance;
+    assert_reports({name: 'TypeError'}, function () { instance = document.createElement('object-custom-element'); });
+    assert_equals(instance.localName, 'object-custom-element');
+    assert_true(instance instanceof HTMLUnknownElement);
+}, 'document.createElement must report a TypeError when the result of Construct is not a DOM node');
</ins><span class="cx"> 
</span><span class="cx"> test(function () {
</span><span class="cx">     class TextCustomElement extends HTMLElement {
</span><span class="lines">@@ -52,8 +73,11 @@
</span><span class="cx">     };
</span><span class="cx">     customElements.define('text-custom-element', TextCustomElement);
</span><span class="cx">     assert_true(new TextCustomElement instanceof Text);
</span><del>-    assert_throws({name: 'TypeError'}, function () { document.createElement('text-custom-element'); });
-}, 'document.createElement must throw a TypeError when the result of Construct is a TextNode');
</del><ins>+    var instance;
+    assert_reports({name: 'TypeError'}, function () { instance = document.createElement('text-custom-element'); });
+    assert_equals(instance.localName, 'text-custom-element');
+    assert_true(instance instanceof HTMLUnknownElement);
+}, 'document.createElement must report a TypeError when the result of Construct is a TextNode');
</ins><span class="cx"> 
</span><span class="cx"> test(function () {
</span><span class="cx">     class ElementWithAttribute extends HTMLElement {
</span><span class="lines">@@ -65,8 +89,11 @@
</span><span class="cx">     };
</span><span class="cx">     customElements.define('element-with-attribute', ElementWithAttribute);
</span><span class="cx">     assert_true(new ElementWithAttribute instanceof ElementWithAttribute);
</span><del>-    assert_throws({name: 'NotSupportedError'}, function () { document.createElement('element-with-attribute'); });
-}, 'document.createElement must throw a NotSupportedError when attribute is added by setAttribute during construction');
</del><ins>+    var instance;
+    assert_reports({name: 'NotSupportedError'}, function () { instance = document.createElement('element-with-attribute'); });
+    assert_equals(instance.localName, 'element-with-attribute');
+    assert_true(instance instanceof HTMLUnknownElement);
+}, 'document.createElement must report a NotSupportedError when attribute is added by setAttribute during construction');
</ins><span class="cx"> 
</span><span class="cx"> test(function () {
</span><span class="cx">     class ElementWithAttrNode extends HTMLElement {
</span><span class="lines">@@ -78,8 +105,11 @@
</span><span class="cx">     };
</span><span class="cx">     customElements.define('element-with-attr-node', ElementWithAttrNode);
</span><span class="cx">     assert_true(new ElementWithAttrNode instanceof ElementWithAttrNode);
</span><del>-    assert_throws({name: 'NotSupportedError'}, function () { document.createElement('element-with-attr-node'); });
-}, 'document.createElement must throw a NotSupportedError when attribute is added by attributes.setNamedItem during construction');
</del><ins>+    var instance;
+    assert_reports({name: 'NotSupportedError'}, function () { instance = document.createElement('element-with-attr-node'); });
+    assert_equals(instance.localName, 'element-with-attr-node');
+    assert_true(instance instanceof HTMLUnknownElement);
+}, 'document.createElement must report a NotSupportedError when attribute is added by attributes.setNamedItem during construction');
</ins><span class="cx"> 
</span><span class="cx"> test(function () {
</span><span class="cx">     class ElementWithNoAttributes extends HTMLElement {
</span><span class="lines">@@ -92,8 +122,10 @@
</span><span class="cx">     };
</span><span class="cx">     customElements.define('element-with-no-attiributes', ElementWithNoAttributes);
</span><span class="cx">     assert_true(new ElementWithNoAttributes instanceof ElementWithNoAttributes);
</span><del>-    assert_true(document.createElement('element-with-no-attiributes') instanceof ElementWithNoAttributes);
-}, 'document.createElement must not throw a NotSupportedError when attribute is added and removed during construction');
</del><ins>+    var instance;
+    assert_not_reports(function () { instance = document.createElement('element-with-no-attiributes'); });
+    assert_true(instance instanceof ElementWithNoAttributes);
+}, 'document.createElement must not report a NotSupportedError when attribute is added and removed during construction');
</ins><span class="cx"> 
</span><span class="cx"> test(function () {
</span><span class="cx">     class ElementWithChildText extends HTMLElement {
</span><span class="lines">@@ -105,8 +137,11 @@
</span><span class="cx">     };
</span><span class="cx">     customElements.define('element-with-child-text', ElementWithChildText);
</span><span class="cx">     assert_true(new ElementWithChildText instanceof ElementWithChildText);
</span><del>-    assert_throws({name: 'NotSupportedError'}, function () { document.createElement('element-with-child-text'); });
-}, 'document.createElement must throw a NotSupportedError when a Text child is added during construction');
</del><ins>+    var instance;
+    assert_reports({name: 'NotSupportedError'}, function () { instance = document.createElement('element-with-child-text'); });
+    assert_equals(instance.localName, 'element-with-child-text');
+    assert_true(instance instanceof HTMLUnknownElement);
+}, 'document.createElement must report a NotSupportedError when a Text child is added during construction');
</ins><span class="cx"> 
</span><span class="cx"> test(function () {
</span><span class="cx">     class ElementWithChildComment extends HTMLElement {
</span><span class="lines">@@ -118,8 +153,11 @@
</span><span class="cx">     };
</span><span class="cx">     customElements.define('element-with-child-comment', ElementWithChildComment);
</span><span class="cx">     assert_true(new ElementWithChildComment instanceof ElementWithChildComment);
</span><del>-    assert_throws({name: 'NotSupportedError'}, function () { document.createElement('element-with-child-comment'); });
-}, 'document.createElement must throw a NotSupportedError when a Comment child is added during construction');
</del><ins>+    var instance;
+    assert_reports({name: 'NotSupportedError'}, function () { instance = document.createElement('element-with-child-comment'); });
+    assert_equals(instance.localName, 'element-with-child-comment');
+    assert_true(instance instanceof HTMLUnknownElement);
+}, 'document.createElement must report a NotSupportedError when a Comment child is added during construction');
</ins><span class="cx"> 
</span><span class="cx"> test(function () {
</span><span class="cx">     class ElementWithChildElement extends HTMLElement {
</span><span class="lines">@@ -131,8 +169,11 @@
</span><span class="cx">     };
</span><span class="cx">     customElements.define('element-with-child-element', ElementWithChildElement);
</span><span class="cx">     assert_true(new ElementWithChildElement instanceof ElementWithChildElement);
</span><del>-    assert_throws({name: 'NotSupportedError'}, function () { document.createElement('element-with-child-element'); });
-}, 'document.createElement must throw a NotSupportedError when an element child is added during construction');
</del><ins>+    var instance;
+    assert_reports({name: 'NotSupportedError'}, function () { instance = document.createElement('element-with-child-element'); });
+    assert_equals(instance.localName, 'element-with-child-element');
+    assert_true(instance instanceof HTMLUnknownElement);
+}, 'document.createElement must report a NotSupportedError when an element child is added during construction');
</ins><span class="cx"> 
</span><span class="cx"> test(function () {
</span><span class="cx">     class ElementWithNoChildElements extends HTMLElement {
</span><span class="lines">@@ -144,8 +185,10 @@
</span><span class="cx">         }
</span><span class="cx">     };
</span><span class="cx">     customElements.define('element-with-no-child-elements', ElementWithNoChildElements);
</span><del>-    assert_true(document.createElement('element-with-no-child-elements') instanceof ElementWithNoChildElements);
-}, 'document.createElement must not throw a NotSupportedError when an element child is added and removed during construction');
</del><ins>+    var instance;
+    assert_not_reports(function () { instance = document.createElement('element-with-no-child-elements'); });
+    assert_true(instance instanceof ElementWithNoChildElements);
+}, 'document.createElement must not report a NotSupportedError when an element child is added and removed during construction');
</ins><span class="cx"> 
</span><span class="cx"> test(function () {
</span><span class="cx">     class ElementWithParent extends HTMLElement {
</span><span class="lines">@@ -157,8 +200,11 @@
</span><span class="cx">     };
</span><span class="cx">     customElements.define('element-with-parent', ElementWithParent);
</span><span class="cx">     assert_true(new ElementWithParent instanceof ElementWithParent);
</span><del>-    assert_throws({name: 'NotSupportedError'}, function () { document.createElement('element-with-parent'); });
-}, 'document.createElement must throw a NotSupportedError when the element gets inserted into another element during construction');
</del><ins>+    var instance;
+    assert_reports({name: 'NotSupportedError'}, function () { instance = document.createElement('element-with-parent'); });
+    assert_equals(instance.localName, 'element-with-parent');
+    assert_true(instance instanceof HTMLUnknownElement);
+}, 'document.createElement must report a NotSupportedError when the element gets inserted into another element during construction');
</ins><span class="cx"> 
</span><span class="cx"> test(function () {
</span><span class="cx">     class ElementWithNoParent extends HTMLElement {
</span><span class="lines">@@ -170,8 +216,10 @@
</span><span class="cx">         }
</span><span class="cx">     };
</span><span class="cx">     customElements.define('element-with-no-parent', ElementWithNoParent);
</span><del>-    assert_true(document.createElement('element-with-no-parent') instanceof ElementWithNoParent);
-}, 'document.createElement must not throw a NotSupportedError when the element is inserted and removed from another element during construction');
</del><ins>+    var instance;
+    assert_not_reports(function () { instance = document.createElement('element-with-no-parent'); });
+    assert_true(instance instanceof ElementWithNoParent);
+}, 'document.createElement must not report a NotSupportedError when the element is inserted and removed from another element during construction');
</ins><span class="cx"> 
</span><span class="cx"> DocumentTypes.forEach(function (entry, testNumber) {
</span><span class="cx">     if (entry.isOwner)
</span><span class="lines">@@ -192,9 +240,12 @@
</span><span class="cx">             var name = 'element-with-adopt-call-' + testNumber;
</span><span class="cx">             customElements.define(name, ElementWithAdoptCall);
</span><span class="cx">             assert_true(new ElementWithAdoptCall instanceof ElementWithAdoptCall);
</span><del>-            assert_throws({name: 'NotSupportedError'}, function () { document.createElement(name); });
</del><ins>+            var instance;
+            assert_reports({name: 'NotSupportedError'}, function () { instance = document.createElement(name); });
+            assert_equals(instance.localName, name);
+            assert_true(instance instanceof HTMLUnknownElement);
</ins><span class="cx">         });
</span><del>-    }, 'document.createElement must throw a NotSupportedError when the element is adopted into a ' + docuemntName + ' during construction');
</del><ins>+    }, 'document.createElement must report a NotSupportedError when the element is adopted into a ' + docuemntName + ' during construction');
</ins><span class="cx"> 
</span><span class="cx">     promise_test(function () {
</span><span class="cx">         return getDocument().then(function (doc) {
</span><span class="lines">@@ -208,9 +259,12 @@
</span><span class="cx">             var name = 'element-inserted-into-another-document-' + testNumber;
</span><span class="cx">             customElements.define(name, ElementInsertedIntoAnotherDocument);
</span><span class="cx">             assert_true(new ElementInsertedIntoAnotherDocument instanceof ElementInsertedIntoAnotherDocument);
</span><del>-            assert_throws({name: 'NotSupportedError'}, function () { document.createElement(name); });
</del><ins>+            var instance;
+            assert_reports({name: 'NotSupportedError'}, function () { instance = document.createElement(name); });
+            assert_equals(instance.localName, name);
+            assert_true(instance instanceof HTMLUnknownElement);
</ins><span class="cx">         });
</span><del>-    }, 'document.createElement must throw a NotSupportedError when the element is inserted into a ' + docuemntName + ' during construction');
</del><ins>+    }, 'document.createElement must report a NotSupportedError when the element is inserted into a ' + docuemntName + ' during construction');
</ins><span class="cx"> 
</span><span class="cx">     promise_test(function () {
</span><span class="cx">         return getDocument().then(function (doc) {
</span><span class="lines">@@ -224,9 +278,11 @@
</span><span class="cx">             };
</span><span class="cx">             var name = 'element-that-get-adopted-back' + testNumber;
</span><span class="cx">             customElements.define(name, ElementThatGetAdoptedBack);
</span><del>-            assert_true(document.createElement(name) instanceof ElementThatGetAdoptedBack);
</del><ins>+            var instance;
+            assert_not_reports(function () { instance = document.createElement(name); });
+            assert_true(instance instanceof ElementThatGetAdoptedBack);
</ins><span class="cx">         });
</span><del>-    }, 'document.createElement must not throw a NotSupportedError when the element is adopted back from a ' + docuemntName + ' during construction');
</del><ins>+    }, 'document.createElement must not report a NotSupportedError when the element is adopted back from a ' + docuemntName + ' during construction');
</ins><span class="cx"> });
</span><span class="cx"> 
</span><span class="cx"> test(function () {
</span><span class="lines">@@ -239,11 +295,14 @@
</span><span class="cx">     };
</span><span class="cx">     customElements.define('div-custom-element', DivCustomElement);
</span><span class="cx">     assert_true(new DivCustomElement instanceof HTMLDivElement);
</span><del>-    assert_throws({name: 'NotSupportedError'}, function () { document.createElement('div-custom-element'); });
-}, 'document.createElement must throw a NotSupportedError when the local name of the element does not match that of the custom element');
</del><ins>+    var instance;
+    assert_reports({name: 'NotSupportedError'}, function () { instance = document.createElement('div-custom-element'); });
+    assert_equals(instance.localName, 'div-custom-element');
+    assert_true(instance instanceof HTMLUnknownElement);
+}, 'document.createElement must report a NotSupportedError when the local name of the element does not match that of the custom element');
</ins><span class="cx"> 
</span><span class="cx"> test(function () {
</span><del>-    var exceptionToThrow = {message: 'exception thrown by a custom constructor'};
</del><ins>+    var exceptionToThrow = {name: 'exception thrown by a custom constructor'};
</ins><span class="cx">     class ThrowCustomElement extends HTMLElement {
</span><span class="cx">         constructor()
</span><span class="cx">         {
</span><span class="lines">@@ -254,21 +313,18 @@
</span><span class="cx">     };
</span><span class="cx">     customElements.define('throw-custom-element', ThrowCustomElement);
</span><span class="cx"> 
</span><del>-    assert_throws(null, function () { new ThrowCustomElement; });
</del><ins>+    assert_throws(exceptionToThrow, function () { new ThrowCustomElement; });
+    var instance;
+    assert_reports(exceptionToThrow, function () { instance = document.createElement('throw-custom-element'); });
+    assert_equals(instance.localName, 'throw-custom-element');
+    assert_true(instance instanceof HTMLUnknownElement);
</ins><span class="cx"> 
</span><del>-    try {
-        document.createElement('throw-custom-element');
-        assert(false, 'document.createElement must throw when a custom element constructor throws');
-    } catch (exception) {
-        assert_equals(exception, exceptionToThrow, 'document.createElement must throw the same exception custom element constructor throws');
-    }
-
</del><span class="cx">     exceptionToThrow = false;
</span><span class="cx">     var instance = document.createElement('throw-custom-element');
</span><span class="cx">     assert_true(instance instanceof ThrowCustomElement);
</span><span class="cx">     assert_equals(instance.localName, 'throw-custom-element');
</span><span class="cx"> 
</span><del>-}, 'document.createElement must re-throw an exception thrown by a custom element constructor');
</del><ins>+}, 'document.createElement must report an exception thrown by a custom element constructor');
</ins><span class="cx"> 
</span><span class="cx"> &lt;/script&gt;
</span><span class="cx"> &lt;/body&gt;
</span></span></pre></div>
<a id="trunkLayoutTestsfastcustomelementsdefinedpseudoclassexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/fast/custom-elements/defined-pseudo-class-expected.txt (206889 => 206890)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/custom-elements/defined-pseudo-class-expected.txt        2016-10-07 00:16:36 UTC (rev 206889)
+++ trunk/LayoutTests/fast/custom-elements/defined-pseudo-class-expected.txt        2016-10-07 00:46:31 UTC (rev 206890)
</span><span class="lines">@@ -1,7 +1,4 @@
</span><del>-CONSOLE MESSAGE: line 79: TypeError: The result of constructing a custom element must be a HTMLElement
</del><span class="cx"> 
</span><del>-Harness Error (FAIL), message = TypeError: The result of constructing a custom element must be a HTMLElement
-
</del><span class="cx"> PASS The defined flag of a custom element must not be set if a custom element has not been upgraded yet 
</span><span class="cx"> PASS The defined flag of a custom element must not be set if a custom element has not been upgraded yet even if the element has been defined 
</span><span class="cx"> PASS The defined flag of a custom element must be set when a custom element is successfully upgraded 
</span></span></pre></div>
<a id="trunkLayoutTestsfastcustomelementsdefinedpseudoclasshtml"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/fast/custom-elements/defined-pseudo-class.html (206889 => 206890)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/custom-elements/defined-pseudo-class.html        2016-10-07 00:16:36 UTC (rev 206889)
+++ trunk/LayoutTests/fast/custom-elements/defined-pseudo-class.html        2016-10-07 00:46:31 UTC (rev 206890)
</span><span class="lines">@@ -11,6 +11,7 @@
</span><span class="cx"> &lt;body&gt;
</span><span class="cx"> &lt;div id=&quot;log&quot;&gt;&lt;/div&gt;
</span><span class="cx"> &lt;script&gt;
</span><ins>+setup({allow_uncaught_exception:true});
</ins><span class="cx"> 
</span><span class="cx"> var upgradeCandidate = document.createElement('my-element');
</span><span class="cx"> 
</span><span class="lines">@@ -76,10 +77,14 @@
</span><span class="cx"> }
</span><span class="cx"> customElements.define('returns-another-node', ReturnsAnotherNode);
</span><span class="cx"> 
</span><ins>+var uncaughtError;
+window.onerror = function (message, url, lineNumber, columnNumber, error) { uncaughtError = error; return true; }
</ins><span class="cx"> document.write('&lt;returns-another-node&gt;&lt;/returns-another-node&gt;');
</span><ins>+window.onerror = null;
</ins><span class="cx"> 
</span><span class="cx"> test(function () {
</span><span class="cx">     var instance = document.querySelector('returns-another-node');
</span><ins>+    assert_equals(uncaughtError.name, 'TypeError', 'The HTML parser must report a TypeError when a custom element returns a non-Element node.');
</ins><span class="cx">     assert_not_equals(instance, ReturnsAnotherNode.lastInstance, 'The element inserted by HTML parser must not be the one returned by super() call');
</span><span class="cx">     assert_true(instance instanceof HTMLElement, 'The element inserted by HTML parser must be a HTMLElement');
</span><span class="cx">     assert_false(instance instanceof ReturnsAnotherNode, 'The element inserted by HTML parser must be a custom element');
</span><span class="lines">@@ -100,15 +105,16 @@
</span><span class="cx"> 
</span><span class="cx"> test(function () {
</span><span class="cx">     var matchInsideConstructor = false;
</span><del>-    customElements.define('throws-exception', class extends HTMLElement {
</del><ins>+    class ThrowsException extends HTMLElement {
</ins><span class="cx">         constructor() {
</span><span class="cx">             super();
</span><span class="cx">             matchInsideConstructor = this.matches(':defined');
</span><span class="cx">             throw {name: 'bad'};
</span><span class="cx">         }
</span><del>-    });
</del><ins>+    };
+    customElements.define('throws-exception', ThrowsException);
</ins><span class="cx">     var instance;
</span><del>-    assert_throws({name: 'bad'}, function () { instance = document.createElement('throws-exception'); });
</del><ins>+    assert_throws({name: 'bad'}, function () { instance = new ThrowsException; });
</ins><span class="cx">     assert_true(matchInsideConstructor);
</span><span class="cx"> }, 'The defined flag of a custom element must be set inside a constructor when constructing a custom element synchronously'
</span><span class="cx">     + ' even if the constructor threw an exception later');
</span><span class="lines">@@ -116,13 +122,14 @@
</span><span class="cx"> test(function () {
</span><span class="cx">     var instance = document.createElement('throws-exception-2');
</span><span class="cx">     document.body.appendChild(instance);
</span><del>-    assert_throws({name: 'bad'}, function () {
-        customElements.define('throws-exception-2', class extends HTMLElement {
-            constructor() {
-                throw {name: 'bad'};
-            }
-        });
</del><ins>+    var uncaughtError;
+    window.onerror = function (message, url, lineNumber, columnNumber, error) { uncaughtError = error; return true; }
+    customElements.define('throws-exception-2', class extends HTMLElement {
+        constructor() {
+            throw {name: 'bad'};
+        }
</ins><span class="cx">     });
</span><ins>+    assert_equals(uncaughtError.name, 'bad');
</ins><span class="cx">     assert_false(instance.matches(':defined'));
</span><span class="cx"> }, 'The defined flag of a custom element must not be set when an upgrade of a custom element fails');
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkLayoutTestsfastcustomelementsupgradingNodecloneNodehtml"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/fast/custom-elements/upgrading/Node-cloneNode.html (206889 => 206890)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/custom-elements/upgrading/Node-cloneNode.html        2016-10-07 00:16:36 UTC (rev 206889)
+++ trunk/LayoutTests/fast/custom-elements/upgrading/Node-cloneNode.html        2016-10-07 00:46:31 UTC (rev 206890)
</span><span class="lines">@@ -123,8 +123,11 @@
</span><span class="cx">         }
</span><span class="cx">         contentWindow.customElements.define('my-custom-element', MyCustomElement);
</span><span class="cx"> 
</span><del>-        var instance = contentDocument.createElement('my-custom-element');
-        assert_throws({'name': 'InvalidStateError'}, function () { instance.cloneNode(false); });
</del><ins>+        var instance = new MyCustomElement(false);
+        var uncaughtError;
+        contentWindow.onerror = function (message, url, lineNumber, columnNumber, error) { uncaughtError = error; return true; }
+        instance.cloneNode(false);
+        assert_equals(uncaughtError.name, 'InvalidStateError');
</ins><span class="cx">     });
</span><span class="cx"> }, 'HTMLElement constructor must throw an InvalidStateError when the top of the construction stack is marked AlreadyConstructed'
</span><span class="cx">     + ' due to a custom element constructor constructing itself after super() call');
</span><span class="lines">@@ -140,8 +143,11 @@
</span><span class="cx">         }
</span><span class="cx">         contentWindow.customElements.define('my-custom-element', MyCustomElement);
</span><span class="cx"> 
</span><del>-        var instance = contentDocument.createElement('my-custom-element');
-        assert_throws({'name': 'InvalidStateError'}, function () { instance.cloneNode(false); });
</del><ins>+        var instance = new MyCustomElement(false);
+        var uncaughtError;
+        contentWindow.onerror = function (message, url, lineNumber, columnNumber, error) { uncaughtError = error; return true; }
+        instance.cloneNode(false);
+        assert_equals(uncaughtError.name, 'InvalidStateError');
</ins><span class="cx">     });
</span><span class="cx"> }, 'HTMLElement constructor must throw an InvalidStateError when the top of the construction stack is marked AlreadyConstructed'
</span><span class="cx">     + ' due to a custom element constructor constructing itself before super() call');
</span><span class="lines">@@ -148,19 +154,22 @@
</span><span class="cx"> 
</span><span class="cx"> test(function () {
</span><span class="cx">     withNewDocumentWithABrowsingContext(function (contentWindow, contentDocument) {
</span><del>-        var cloning = false;
</del><ins>+        var returnSpan = false;
</ins><span class="cx">         class MyCustomElement extends contentWindow.HTMLElement {
</span><span class="cx">             constructor() {
</span><span class="cx">                 super();
</span><del>-                if (cloning)
</del><ins>+                if (returnSpan)
</ins><span class="cx">                     return contentDocument.createElement('span');
</span><span class="cx">             }
</span><span class="cx">         }
</span><span class="cx">         contentWindow.customElements.define('my-custom-element', MyCustomElement);
</span><span class="cx"> 
</span><del>-        var instance = contentDocument.createElement('my-custom-element');
-        cloning = true;
-        assert_throws({'name': 'InvalidStateError'}, function () { instance.cloneNode(false); });
</del><ins>+        var instance = new MyCustomElement(false);
+        returnSpan = true;
+        var uncaughtError;
+        contentWindow.onerror = function (message, url, lineNumber, columnNumber, error) { uncaughtError = error; return true; }
+        instance.cloneNode(false);
+        assert_equals(uncaughtError.name, 'InvalidStateError');
</ins><span class="cx">     });
</span><span class="cx"> }, 'Upgrading a custom element must throw InvalidStateError when the custom element\'s constructor returns another element');
</span><span class="cx"> 
</span><span class="lines">@@ -179,9 +188,10 @@
</span><span class="cx">             }
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        try {
-            contentWindow.customElements.define('my-custom-element', MyCustomElement);
-        } catch (e) { }
</del><ins>+        var uncaughtError;
+        contentWindow.onerror = function (message, url, lineNumber, columnNumber, error) { uncaughtError = error; return true; }
+        contentWindow.customElements.define('my-custom-element', MyCustomElement);
+        assert_equals(uncaughtError, 'bad');
</ins><span class="cx"> 
</span><span class="cx">         assert_array_equals(calls, [instance]);
</span><span class="cx">         contentDocument.body.removeChild(instance);
</span></span></pre></div>
<a id="trunkLayoutTestsfastcustomelementsupgradingupgradingparsercreatedelementhtml"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/fast/custom-elements/upgrading/upgrading-parser-created-element.html (206889 => 206890)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/custom-elements/upgrading/upgrading-parser-created-element.html        2016-10-07 00:16:36 UTC (rev 206889)
+++ trunk/LayoutTests/fast/custom-elements/upgrading/upgrading-parser-created-element.html        2016-10-07 00:46:31 UTC (rev 206890)
</span><span class="lines">@@ -18,6 +18,8 @@
</span><span class="cx"> &lt;my-other-element id=&quot;otherInstance&quot;&gt;&lt;/my-other-element&gt;
</span><span class="cx"> &lt;script&gt;
</span><span class="cx"> 
</span><ins>+setup({allow_uncaught_exception:true});
+
</ins><span class="cx"> test(function () {
</span><span class="cx">     class MyCustomElement extends HTMLElement { }
</span><span class="cx"> 
</span><span class="lines">@@ -35,7 +37,6 @@
</span><span class="cx"> 
</span><span class="cx"> }, 'Element.prototype.createElement must add an unresolved custom element to the upgrade candidates map');
</span><span class="cx"> 
</span><del>-
</del><span class="cx"> test(function () {
</span><span class="cx">     class InstantiatesItselfAfterSuper extends HTMLElement {
</span><span class="cx">         constructor(doNotCreateItself) {
</span><span class="lines">@@ -45,9 +46,10 @@
</span><span class="cx">         }
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    assert_throws({'name': 'InvalidStateError'}, function () {
-        customElements.define('instantiates-itself-after-super', InstantiatesItselfAfterSuper);
-    });
</del><ins>+    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');
</ins><span class="cx"> }, 'HTMLElement constructor must throw an InvalidStateError when the top of the construction stack is marked AlreadyConstructed'
</span><span class="cx">     + ' due to a custom element constructor constructing itself after super() call');
</span><span class="cx"> 
</span><span class="lines">@@ -60,9 +62,10 @@
</span><span class="cx">         }
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    assert_throws({'name': 'InvalidStateError'}, function () {
-        customElements.define('instantiates-itself-before-super', InstantiatesItselfBeforeSuper);
-    });
</del><ins>+    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');
</ins><span class="cx"> }, 'HTMLElement constructor must throw an InvalidStateError when the top of the construction stack is marked AlreadyConstructed'
</span><span class="cx">     + ' due to a custom element constructor constructing itself before super() call');
</span><span class="cx"> 
</span><span class="lines">@@ -80,12 +83,14 @@
</span><span class="cx">     assert_false(instance instanceof MyOtherElement);
</span><span class="cx">     assert_false(otherInstance instanceof MyOtherElement);
</span><span class="cx"> 
</span><del>-    assert_throws({'name': 'InvalidStateError'}, function () {
-        customElements.define('my-other-element', MyOtherElement);
-    });
</del><ins>+    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');
</ins><span class="cx"> 
</span><span class="cx">     assert_true(document.createElement('my-other-element') instanceof MyOtherElement,
</span><span class="cx">         'Upgrading of custom elements must happen after the definition was added to the registry.');
</span><ins>+
</ins><span class="cx"> }, 'Upgrading a custom element must throw an InvalidStateError when the returned element is not SameValue as the upgraded element');
</span><span class="cx"> 
</span><span class="cx"> &lt;/script&gt;
</span></span></pre></div>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (206889 => 206890)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2016-10-07 00:16:36 UTC (rev 206889)
+++ trunk/Source/WebCore/ChangeLog        2016-10-07 00:46:31 UTC (rev 206890)
</span><span class="lines">@@ -1,3 +1,38 @@
</span><ins>+2016-10-06  Ryosuke Niwa  &lt;rniwa@webkit.org&gt;
+
+        Upgrading and constructing element should always report exception instead of rethrowing
+        https://bugs.webkit.org/show_bug.cgi?id=162996
+
+        Reviewed by Darin Adler.
+
+        The latest HTML specification specifies that we must report exceptions thrown during element upgrades:
+        https://html.spec.whatwg.org/#upgrades
+
+        In addition, F2F during 2016 TPAC had a consensus that we should do the same for document.createElement:
+        https://github.com/w3c/webcomponents/issues/569
+
+        Since the HTML parser already reports the exception thrown during custom element construction as it does
+        not have any JS stack, these changes make exceptions thrown during upgrades and constructions.
+
+        In our implementation, this only reduces the code complexity as now we can push the logic to fallback
+        to HTMLUnknownElement into JSCustomElementInterface's constructElement, which has been renamed
+        to constructElementWithFallback, and eliminate ShouldClearException enum class entirely. Moreover,
+        constructElementWithFallback can now return Ref instead of RefPtr.
+
+        No new tests. Existing tests have been updated.
+
+        * bindings/js/JSCustomElementInterface.cpp:
+        (WebCore::JSCustomElementInterface::constructElementWithFallback): Create a HTMLUnknownElement if
+        an attempt to construct a custom element had failed in lieu of returning nullptr.
+        (WebCore::JSCustomElementInterface::tryToConstructCustomElement): Renamed from constructElement.
+        Always report exceptions (the same behavior as ShouldClearException::Clear).
+        (WebCore::JSCustomElementInterface::upgradeElement): Report exceptions instead of rethrowing.
+        * bindings/js/JSCustomElementInterface.h:
+        * dom/Document.cpp:
+        (WebCore::createHTMLElementWithNameValidation):
+        * html/parser/HTMLDocumentParser.cpp:
+        (WebCore::HTMLDocumentParser::runScriptsForPausedTreeBuilder):
+
</ins><span class="cx"> 2016-10-06  Chris Dumez  &lt;cdumez@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Overwriting an attribute event listener can lead to wrong event listener firing order
</span></span></pre></div>
<a id="trunkSourceWebCorebindingsjsJSCustomElementInterfacecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/bindings/js/JSCustomElementInterface.cpp (206889 => 206890)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/bindings/js/JSCustomElementInterface.cpp        2016-10-07 00:16:36 UTC (rev 206889)
+++ trunk/Source/WebCore/bindings/js/JSCustomElementInterface.cpp        2016-10-07 00:46:31 UTC (rev 206890)
</span><span class="lines">@@ -31,6 +31,7 @@
</span><span class="cx"> #if ENABLE(CUSTOM_ELEMENTS)
</span><span class="cx"> 
</span><span class="cx"> #include &quot;DOMWrapperWorld.h&quot;
</span><ins>+#include &quot;HTMLUnknownElement.h&quot;
</ins><span class="cx"> #include &quot;JSDOMBinding.h&quot;
</span><span class="cx"> #include &quot;JSDOMGlobalObject.h&quot;
</span><span class="cx"> #include &quot;JSElement.h&quot;
</span><span class="lines">@@ -59,8 +60,20 @@
</span><span class="cx"> 
</span><span class="cx"> static RefPtr&lt;Element&gt; constructCustomElementSynchronously(Document&amp;, VM&amp;, ExecState&amp;, JSObject* constructor, const AtomicString&amp; localName);
</span><span class="cx"> 
</span><del>-RefPtr&lt;Element&gt; JSCustomElementInterface::constructElement(const AtomicString&amp; localName, ShouldClearException shouldClearException)
</del><ins>+Ref&lt;Element&gt; JSCustomElementInterface::constructElementWithFallback(Document&amp; document, const AtomicString&amp; localName)
</ins><span class="cx"> {
</span><ins>+    if (auto element = tryToConstructCustomElement(document, localName))
+        return element.releaseNonNull();
+
+    auto element = HTMLUnknownElement::create(QualifiedName(nullAtom, localName, HTMLNames::xhtmlNamespaceURI), document);
+    element-&gt;setIsCustomElementUpgradeCandidate();
+    element-&gt;setIsFailedCustomElement(*this);
+
+    return element.get();
+}
+
+RefPtr&lt;Element&gt; JSCustomElementInterface::tryToConstructCustomElement(Document&amp; document, const AtomicString&amp; localName)
+{
</ins><span class="cx">     if (!canInvokeCallback())
</span><span class="cx">         return nullptr;
</span><span class="cx"> 
</span><span class="lines">@@ -73,20 +86,14 @@
</span><span class="cx">     if (!m_constructor)
</span><span class="cx">         return nullptr;
</span><span class="cx"> 
</span><del>-    ScriptExecutionContext* context = scriptExecutionContext();
-    if (!context)
-        return nullptr;
-    ASSERT(context-&gt;isDocument());
-
-    auto&amp; state = *context-&gt;execState();
-    RefPtr&lt;Element&gt; element = constructCustomElementSynchronously(downcast&lt;Document&gt;(*context), vm, state, m_constructor.get(), localName);
</del><ins>+    ASSERT(&amp;document == scriptExecutionContext());
+    auto&amp; state = *document.execState();
+    auto element = constructCustomElementSynchronously(document, vm, state, m_constructor.get(), localName);
</ins><span class="cx">     ASSERT(!!scope.exception() == !element);
</span><span class="cx">     if (!element) {
</span><del>-        if (shouldClearException == ShouldClearException::Clear) {
-            auto* exception = scope.exception();
-            scope.clearException();
-            reportException(&amp;state, exception);
-        }
</del><ins>+        auto* exception = scope.exception();
+        scope.clearException();
+        reportException(&amp;state, exception);
</ins><span class="cx">         return nullptr;
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="lines">@@ -186,6 +193,7 @@
</span><span class="cx"> 
</span><span class="cx">     if (UNLIKELY(scope.exception())) {
</span><span class="cx">         element.setIsFailedCustomElement(*this);
</span><ins>+        reportException(state, scope.exception());
</ins><span class="cx">         return;
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="lines">@@ -192,7 +200,7 @@
</span><span class="cx">     Element* wrappedElement = JSElement::toWrapped(returnedElement);
</span><span class="cx">     if (!wrappedElement || wrappedElement != &amp;element) {
</span><span class="cx">         element.setIsFailedCustomElement(*this);
</span><del>-        throwInvalidStateError(*state, scope, &quot;Custom element constructor failed to upgrade an element&quot;);
</del><ins>+        reportException(state, createDOMException(state, INVALID_STATE_ERR, &quot;Custom element constructor failed to upgrade an element&quot;));
</ins><span class="cx">         return;
</span><span class="cx">     }
</span><span class="cx">     element.setIsDefinedCustomElement(*this);
</span></span></pre></div>
<a id="trunkSourceWebCorebindingsjsJSCustomElementInterfaceh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/bindings/js/JSCustomElementInterface.h (206889 => 206890)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/bindings/js/JSCustomElementInterface.h        2016-10-07 00:16:36 UTC (rev 206889)
+++ trunk/Source/WebCore/bindings/js/JSCustomElementInterface.h        2016-10-07 00:46:31 UTC (rev 206890)
</span><span class="lines">@@ -63,8 +63,7 @@
</span><span class="cx">         return adoptRef(*new JSCustomElementInterface(name, callback, globalObject));
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    enum class ShouldClearException { Clear, DoNotClear };
-    RefPtr&lt;Element&gt; constructElement(const AtomicString&amp;, ShouldClearException);
</del><ins>+    Ref&lt;Element&gt; constructElementWithFallback(Document&amp;, const AtomicString&amp;);
</ins><span class="cx"> 
</span><span class="cx">     void upgradeElement(Element&amp;);
</span><span class="cx"> 
</span><span class="lines">@@ -98,6 +97,8 @@
</span><span class="cx"> private:
</span><span class="cx">     JSCustomElementInterface(const QualifiedName&amp;, JSC::JSObject* callback, JSDOMGlobalObject*);
</span><span class="cx"> 
</span><ins>+    RefPtr&lt;Element&gt; tryToConstructCustomElement(Document&amp;, const AtomicString&amp;);
+
</ins><span class="cx">     void invokeCallback(Element&amp;, JSC::JSObject* callback, const WTF::Function&lt;void(JSC::ExecState*, JSDOMGlobalObject*, JSC::MarkedArgumentBuffer&amp;)&gt;&amp; addArguments = { });
</span><span class="cx"> 
</span><span class="cx">     QualifiedName m_name;
</span></span></pre></div>
<a id="trunkSourceWebCoredomDocumentcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/dom/Document.cpp (206889 => 206890)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/dom/Document.cpp        2016-10-07 00:16:36 UTC (rev 206889)
+++ trunk/Source/WebCore/dom/Document.cpp        2016-10-07 00:46:31 UTC (rev 206890)
</span><span class="lines">@@ -893,7 +893,7 @@
</span><span class="cx">         auto* registry = window-&gt;customElementRegistry();
</span><span class="cx">         if (UNLIKELY(registry)) {
</span><span class="cx">             if (auto* elementInterface = registry-&gt;findInterface(localName))
</span><del>-                return elementInterface-&gt;constructElement(localName, JSCustomElementInterface::ShouldClearException::DoNotClear);
</del><ins>+                return elementInterface-&gt;constructElementWithFallback(document, localName);
</ins><span class="cx">         }
</span><span class="cx">     }
</span><span class="cx"> #endif
</span></span></pre></div>
<a id="trunkSourceWebCorehtmlparserHTMLDocumentParsercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/html/parser/HTMLDocumentParser.cpp (206889 => 206890)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/html/parser/HTMLDocumentParser.cpp        2016-10-07 00:16:36 UTC (rev 206889)
+++ trunk/Source/WebCore/html/parser/HTMLDocumentParser.cpp        2016-10-07 00:46:31 UTC (rev 206890)
</span><span class="lines">@@ -197,15 +197,8 @@
</span><span class="cx"> 
</span><span class="cx">         // https://html.spec.whatwg.org/#create-an-element-for-the-token
</span><span class="cx">         auto&amp; elementInterface = constructionData-&gt;elementInterface.get();
</span><del>-        RefPtr&lt;Element&gt; newElement = elementInterface.constructElement(constructionData-&gt;name, JSCustomElementInterface::ShouldClearException::Clear);
-        if (!newElement) {
-            ASSERT(!m_treeBuilder-&gt;isParsingTemplateContents());
-            newElement = HTMLUnknownElement::create(QualifiedName(nullAtom, constructionData-&gt;name, xhtmlNamespaceURI), *document());
-            newElement-&gt;setIsCustomElementUpgradeCandidate();
-            newElement-&gt;setIsFailedCustomElement(elementInterface);
-        }
-
-        m_treeBuilder-&gt;didCreateCustomOrCallbackElement(newElement.releaseNonNull(), *constructionData);
</del><ins>+        auto newElement = elementInterface.constructElementWithFallback(*document(), constructionData-&gt;name);
+        m_treeBuilder-&gt;didCreateCustomOrCallbackElement(WTFMove(newElement), *constructionData);
</ins><span class="cx">         return;
</span><span class="cx">     }
</span><span class="cx"> #endif
</span></span></pre>
</div>
</div>

</body>
</html>