<!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>[208716] 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/208716">208716</a></dd>
<dt>Author</dt> <dd>rniwa@webkit.org</dd>
<dt>Date</dt> <dd>2016-11-14 16:27:01 -0800 (Mon, 14 Nov 2016)</dd>
</dl>

<h3>Log Message</h3>
<pre>document.createElementNS doesn't construct a custom element
https://bugs.webkit.org/show_bug.cgi?id=164700

Reviewed by Darin Adler.

Source/WebCore:

Fixed the bug that document.createElementNS doesn't create a custom element or enqueue it to upgrade.

Also made constructCustomElementSynchronously not call the custom element constructors with the element's
local name as the first argument, which was a non-standard behavior added during prototyping.

Test: fast/custom-elements/DOMImplementation-createDocument.html
      fast/custom-elements/document-createElementNS.html

* bindings/js/JSCustomElementInterface.cpp:
(WebCore::JSCustomElementInterface::constructElementWithFallback): Added a variant that takes QualifiedName
instead of AtomicString.
(WebCore::constructCustomElementSynchronously): Don't add the local name as an argument.
* bindings/js/JSCustomElementInterface.h:

* dom/CustomElementRegistry.cpp:
(WebCore::CustomElementRegistry::findInterface): Just find the interface based on the local name after
checking the namespace URI to be that of the XHTML. We need to ignore the prefix for the purpose of looking
up the custom element definition as specified in the latest HTML specification:
https://html.spec.whatwg.org/multipage/scripting.html#look-up-a-custom-element-definition

* dom/DOMImplementation.cpp:
(WebCore::DOMImplementation::createDocument): Added an assertion to make sure we don't invoke scripts while
constructing the document element.

* dom/Document.cpp:
(WebCore::createUpgradeCandidateElement): Made this function create a HTMLUnknownElement instead of returning
nullptr to share more code. Also added a variant which takes QualifiedName.
(WebCore::isValidHTMLElementName): Added; helpers for createHTMLElementWithNameValidation to call isValidName
on Document with the right argument.
(WebCore::createHTMLElementWithNameValidation): Templatized the function to be called with either AtomicString
or QualifiedName for the name.
(WebCore::createFallbackHTMLElement):
(WebCore::Document::createElementNS): Call createHTMLElementWithNameValidation to create a custom element if
possible. This function ends up re-validating the element name before creating a HTMLUnknownElement but that
shouldn't be a common scenario to matter. In fact, createElementNS is a rarely used API.

LayoutTests:

Added W3C style testharness.js tests for createElementNS and DOMImplementation's createDocument.

* fast/custom-elements/DOMImplementation-createDocument-expected.txt: Added.
* fast/custom-elements/DOMImplementation-createDocument.html: Added.
* fast/custom-elements/document-createElementNS-expected.txt: Added.
* fast/custom-elements/document-createElementNS.html: Added.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsChangeLog">trunk/LayoutTests/ChangeLog</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="#trunkSourceWebCoredomCustomElementRegistrycpp">trunk/Source/WebCore/dom/CustomElementRegistry.cpp</a></li>
<li><a href="#trunkSourceWebCoredomDOMImplementationcpp">trunk/Source/WebCore/dom/DOMImplementation.cpp</a></li>
<li><a href="#trunkSourceWebCoredomDocumentcpp">trunk/Source/WebCore/dom/Document.cpp</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsfastcustomelementsDOMImplementationcreateDocumentexpectedtxt">trunk/LayoutTests/fast/custom-elements/DOMImplementation-createDocument-expected.txt</a></li>
<li><a href="#trunkLayoutTestsfastcustomelementsDOMImplementationcreateDocumenthtml">trunk/LayoutTests/fast/custom-elements/DOMImplementation-createDocument.html</a></li>
<li><a href="#trunkLayoutTestsfastcustomelementsdocumentcreateElementNSexpectedtxt">trunk/LayoutTests/fast/custom-elements/document-createElementNS-expected.txt</a></li>
<li><a href="#trunkLayoutTestsfastcustomelementsdocumentcreateElementNShtml">trunk/LayoutTests/fast/custom-elements/document-createElementNS.html</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/ChangeLog (208715 => 208716)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/ChangeLog        2016-11-15 00:19:24 UTC (rev 208715)
+++ trunk/LayoutTests/ChangeLog        2016-11-15 00:27:01 UTC (rev 208716)
</span><span class="lines">@@ -1,3 +1,17 @@
</span><ins>+2016-11-14  Ryosuke Niwa  &lt;rniwa@webkit.org&gt;
+
+        document.createElementNS doesn't construct a custom element
+        https://bugs.webkit.org/show_bug.cgi?id=164700
+
+        Reviewed by Darin Adler.
+
+        Added W3C style testharness.js tests for createElementNS and DOMImplementation's createDocument.
+
+        * fast/custom-elements/DOMImplementation-createDocument-expected.txt: Added.
+        * fast/custom-elements/DOMImplementation-createDocument.html: Added.
+        * fast/custom-elements/document-createElementNS-expected.txt: Added.
+        * fast/custom-elements/document-createElementNS.html: Added.
+
</ins><span class="cx"> 2016-11-14  Dean Jackson  &lt;dino@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Handle filter() image type in new CSS Parser
</span></span></pre></div>
<a id="trunkLayoutTestsfastcustomelementsDOMImplementationcreateDocumentexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/fast/custom-elements/DOMImplementation-createDocument-expected.txt (0 => 208716)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/custom-elements/DOMImplementation-createDocument-expected.txt                                (rev 0)
+++ trunk/LayoutTests/fast/custom-elements/DOMImplementation-createDocument-expected.txt        2016-11-15 00:27:01 UTC (rev 208716)
</span><span class="lines">@@ -0,0 +1,3 @@
</span><ins>+
+PASS document.createElement invoke a custom element constructor with no arguments 
+
</ins></span></pre></div>
<a id="trunkLayoutTestsfastcustomelementsDOMImplementationcreateDocumenthtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/fast/custom-elements/DOMImplementation-createDocument.html (0 => 208716)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/custom-elements/DOMImplementation-createDocument.html                                (rev 0)
+++ trunk/LayoutTests/fast/custom-elements/DOMImplementation-createDocument.html        2016-11-15 00:27:01 UTC (rev 208716)
</span><span class="lines">@@ -0,0 +1,41 @@
</span><ins>+&lt;!DOCTYPE html&gt;
+&lt;html&gt;
+&lt;head&gt;
+&lt;title&gt;Custom Elements: document.implementation.createElement must not instantiate a custom element&lt;/title&gt;
+&lt;meta name=&quot;author&quot; title=&quot;Ryosuke Niwa&quot; href=&quot;mailto:rniwa@webkit.org&quot;&gt;
+&lt;meta name=&quot;assert&quot; content=&quot;document.implementation.createElement must not instantiate a custom element&quot;&gt;
+&lt;link rel=&quot;help&quot; content=&quot;https://dom.spec.whatwg.org/#dom-domimplementation-createdocument&quot;&gt;
+&lt;link rel=&quot;help&quot; content=&quot;https://html.spec.whatwg.org/#look-up-a-custom-element-definition&quot;&gt;
+&lt;script src=&quot;../../resources/testharness.js&quot;&gt;&lt;/script&gt;
+&lt;script src=&quot;../../resources/testharnessreport.js&quot;&gt;&lt;/script&gt;
+&lt;script src=&quot;../../imported/w3c/web-platform-tests/custom-elements/resources/custom-elements-helpers.js&quot;&gt;&lt;/script&gt;
+&lt;/head&gt;
+&lt;body&gt;
+&lt;div id=&quot;log&quot;&gt;&lt;/div&gt;
+&lt;script&gt;
+
+const xhtmlNamespaceURI = 'http://www.w3.org/1999/xhtml';
+
+test_with_window((contentWindow, contentDocument) =&gt; {
+    let constructorCount = 0;
+    class MyCustomElement extends contentWindow.HTMLElement {
+        constructor() {
+            super();
+            constructorCount++;
+        }
+    }
+    contentWindow.customElements.define('my-custom-element', MyCustomElement);
+    const instance = contentDocument.createElement('my-custom-element');
+    assert_true(instance instanceof MyCustomElement);
+    assert_equals(constructorCount, 1);
+
+    const newDocument = contentDocument.implementation.createDocument(xhtmlNamespaceURI, 'my-custom-element', null);
+    assert_equals(constructorCount, 1);
+    assert_true(newDocument.documentElement instanceof contentWindow.HTMLElement);
+    assert_equals(newDocument.documentElement.localName, 'my-custom-element');
+    assert_false(newDocument.documentElement instanceof MyCustomElement);
+}, 'document.createElement invoke a custom element constructor with no arguments');
+
+&lt;/script&gt;
+&lt;/body&gt;
+&lt;/html&gt;
</ins></span></pre></div>
<a id="trunkLayoutTestsfastcustomelementsdocumentcreateElementNSexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/fast/custom-elements/document-createElementNS-expected.txt (0 => 208716)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/custom-elements/document-createElementNS-expected.txt                                (rev 0)
+++ trunk/LayoutTests/fast/custom-elements/document-createElementNS-expected.txt        2016-11-15 00:27:01 UTC (rev 208716)
</span><span class="lines">@@ -0,0 +1,6 @@
</span><ins>+
+PASS document.createElement invoke a custom element constructor with no arguments 
+PASS document.createElementNS must create an instance of custom elements 
+PASS document.createElementNS must set the prefix after constructing a custom element 
+PASS document.createElementNS must use the element returned by the constructor 
+
</ins></span></pre></div>
<a id="trunkLayoutTestsfastcustomelementsdocumentcreateElementNShtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/fast/custom-elements/document-createElementNS.html (0 => 208716)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/custom-elements/document-createElementNS.html                                (rev 0)
+++ trunk/LayoutTests/fast/custom-elements/document-createElementNS.html        2016-11-15 00:27:01 UTC (rev 208716)
</span><span class="lines">@@ -0,0 +1,89 @@
</span><ins>+&lt;!DOCTYPE html&gt;
+&lt;html&gt;
+&lt;head&gt;
+&lt;title&gt;Custom Elements: document.createElementNS must create an element with synchronous custom elements flag set&lt;/title&gt;
+&lt;meta name=&quot;author&quot; title=&quot;Ryosuke Niwa&quot; href=&quot;mailto:rniwa@webkit.org&quot;&gt;
+&lt;meta name=&quot;assert&quot; content=&quot;document.createElementNS must create an element with synchronous custom elements flag set&quot;&gt;
+&lt;link rel=&quot;help&quot; content=&quot;https://dom.spec.whatwg.org/#dom-document-createelementns&quot;&gt;
+&lt;link rel=&quot;help&quot; content=&quot;https://dom.spec.whatwg.org/#concept-create-element&quot;&gt;
+&lt;script src=&quot;../../resources/testharness.js&quot;&gt;&lt;/script&gt;
+&lt;script src=&quot;../../resources/testharnessreport.js&quot;&gt;&lt;/script&gt;
+&lt;script src=&quot;../../imported/w3c/web-platform-tests/custom-elements/resources/custom-elements-helpers.js&quot;&gt;&lt;/script&gt;
+&lt;/head&gt;
+&lt;body&gt;
+&lt;div id=&quot;log&quot;&gt;&lt;/div&gt;
+&lt;script&gt;
+
+const xhtmlNamespaceURI = 'http://www.w3.org/1999/xhtml';
+
+test_with_window((contentWindow, contentDocument) =&gt; {
+    let constructorArguments;
+    class MyCustomElement extends contentWindow.HTMLElement {
+        constructor() {
+            constructorArguments = Array.from(arguments);
+            super();
+        }
+    }
+    contentWindow.customElements.define('my-custom-element', MyCustomElement);
+    const instance = contentDocument.createElement('my-custom-element');
+    assert_true(instance instanceof MyCustomElement);
+    assert_array_equals(constructorArguments, []);
+}, 'document.createElement invoke a custom element constructor with no arguments');
+
+test_with_window((contentWindow, contentDocument) =&gt; {
+    class MyCustomElement extends contentWindow.HTMLElement {};
+
+    const upgradeCandidate = contentDocument.createElementNS(xhtmlNamespaceURI, 'my-custom-element');
+    assert_true(upgradeCandidate instanceof contentWindow.HTMLElement);
+    assert_false(upgradeCandidate instanceof MyCustomElement);
+
+    contentWindow.customElements.define('my-custom-element', MyCustomElement);
+    const instance = contentDocument.createElementNS(xhtmlNamespaceURI, 'my-custom-element');
+    assert_true(instance instanceof MyCustomElement);
+    assert_equals(instance.localName, 'my-custom-element');
+    assert_equals(instance.namespaceURI, xhtmlNamespaceURI);
+}, 'document.createElementNS must create an instance of custom elements');
+
+test_with_window((contentWindow, contentDocument) =&gt; {
+    class MyCustomElement extends contentWindow.HTMLElement {};
+    contentWindow.customElements.define('element-with-prefix', MyCustomElement);
+
+    const instance = contentDocument.createElementNS(xhtmlNamespaceURI, 'foo:element-with-prefix');
+    assert_true(instance instanceof MyCustomElement);
+    assert_equals(instance.localName, 'element-with-prefix');
+    assert_equals(instance.namespaceURI, xhtmlNamespaceURI);
+    assert_equals(instance.prefix, 'foo');
+}, 'document.createElementNS must set the prefix after constructing a custom element');
+
+test_with_window((contentWindow, contentDocument) =&gt; {
+    let innerElement;
+    let innerElementPrefix;
+    let outerElement;
+    let outerElementPrefix;
+    class MyCustomElement extends contentWindow.HTMLElement {
+        constructor(isInnerCall) {
+            if (isInnerCall) {
+                innerElement = super();
+                innerElementPrefix = innerElement.prefix;
+                return innerElement;
+            }
+            outerElement = super();
+            outerElementPrefix = outerElement.prefix;
+            return new MyCustomElement(true);
+        }
+    }
+    contentWindow.customElements.define('custom-element', MyCustomElement);
+
+    const instance = contentDocument.createElementNS(xhtmlNamespaceURI, 'foo:custom-element');
+    assert_true(instance instanceof MyCustomElement);
+    assert_equals(instance.localName, 'custom-element');
+    assert_equals(instance.namespaceURI, xhtmlNamespaceURI);
+    assert_equals(instance.prefix, 'foo');
+    assert_equals(instance, innerElement, 'document.createElementNS must create an element with the synchronous custom elements flag set');
+    assert_equals(innerElementPrefix, null, 'HTML constructor must not set prefix');
+    assert_equals(outerElementPrefix, null, 'HTML constructor must not set prefix');
+}, 'document.createElementNS must use the element returned by the constructor');
+
+&lt;/script&gt;
+&lt;/body&gt;
+&lt;/html&gt;
</ins></span></pre></div>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (208715 => 208716)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2016-11-15 00:19:24 UTC (rev 208715)
+++ trunk/Source/WebCore/ChangeLog        2016-11-15 00:27:01 UTC (rev 208716)
</span><span class="lines">@@ -1,3 +1,46 @@
</span><ins>+2016-11-14  Ryosuke Niwa  &lt;rniwa@webkit.org&gt;
+
+        document.createElementNS doesn't construct a custom element
+        https://bugs.webkit.org/show_bug.cgi?id=164700
+
+        Reviewed by Darin Adler.
+
+        Fixed the bug that document.createElementNS doesn't create a custom element or enqueue it to upgrade.
+
+        Also made constructCustomElementSynchronously not call the custom element constructors with the element's
+        local name as the first argument, which was a non-standard behavior added during prototyping.
+
+        Test: fast/custom-elements/DOMImplementation-createDocument.html
+              fast/custom-elements/document-createElementNS.html
+
+        * bindings/js/JSCustomElementInterface.cpp:
+        (WebCore::JSCustomElementInterface::constructElementWithFallback): Added a variant that takes QualifiedName
+        instead of AtomicString.
+        (WebCore::constructCustomElementSynchronously): Don't add the local name as an argument.
+        * bindings/js/JSCustomElementInterface.h:
+
+        * dom/CustomElementRegistry.cpp:
+        (WebCore::CustomElementRegistry::findInterface): Just find the interface based on the local name after
+        checking the namespace URI to be that of the XHTML. We need to ignore the prefix for the purpose of looking
+        up the custom element definition as specified in the latest HTML specification:
+        https://html.spec.whatwg.org/multipage/scripting.html#look-up-a-custom-element-definition
+
+        * dom/DOMImplementation.cpp:
+        (WebCore::DOMImplementation::createDocument): Added an assertion to make sure we don't invoke scripts while
+        constructing the document element.
+
+        * dom/Document.cpp:
+        (WebCore::createUpgradeCandidateElement): Made this function create a HTMLUnknownElement instead of returning
+        nullptr to share more code. Also added a variant which takes QualifiedName.
+        (WebCore::isValidHTMLElementName): Added; helpers for createHTMLElementWithNameValidation to call isValidName
+        on Document with the right argument.
+        (WebCore::createHTMLElementWithNameValidation): Templatized the function to be called with either AtomicString
+        or QualifiedName for the name.
+        (WebCore::createFallbackHTMLElement):
+        (WebCore::Document::createElementNS): Call createHTMLElementWithNameValidation to create a custom element if
+        possible. This function ends up re-validating the element name before creating a HTMLUnknownElement but that
+        shouldn't be a common scenario to matter. In fact, createElementNS is a rarely used API.
+
</ins><span class="cx"> 2016-11-14  Chris Dumez  &lt;cdumez@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Avoid copying attributes vector when constructing a CustomElement in HTMLTreeBuilder
</span></span></pre></div>
<a id="trunkSourceWebCorebindingsjsJSCustomElementInterfacecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/bindings/js/JSCustomElementInterface.cpp (208715 => 208716)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/bindings/js/JSCustomElementInterface.cpp        2016-11-15 00:19:24 UTC (rev 208715)
+++ trunk/Source/WebCore/bindings/js/JSCustomElementInterface.cpp        2016-11-15 00:27:01 UTC (rev 208716)
</span><span class="lines">@@ -67,9 +67,24 @@
</span><span class="cx">     element-&gt;setIsCustomElementUpgradeCandidate();
</span><span class="cx">     element-&gt;setIsFailedCustomElement(*this);
</span><span class="cx"> 
</span><del>-    return element.get();
</del><ins>+    return WTFMove(element);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><ins>+Ref&lt;Element&gt; JSCustomElementInterface::constructElementWithFallback(Document&amp; document, const QualifiedName&amp; name)
+{
+    if (auto element = tryToConstructCustomElement(document, name.localName())) {
+        if (name.prefix() != nullAtom)
+            element-&gt;setPrefix(name.prefix());
+        return element.releaseNonNull();
+    }
+
+    auto element = HTMLUnknownElement::create(name, document);
+    element-&gt;setIsCustomElementUpgradeCandidate();
+    element-&gt;setIsFailedCustomElement(*this);
+
+    return WTFMove(element);
+}
+
</ins><span class="cx"> RefPtr&lt;Element&gt; JSCustomElementInterface::tryToConstructCustomElement(Document&amp; document, const AtomicString&amp; localName)
</span><span class="cx"> {
</span><span class="cx">     if (!canInvokeCallback())
</span><span class="lines">@@ -110,10 +125,8 @@
</span><span class="cx">         return nullptr;
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    InspectorInstrumentationCookie cookie = JSMainThreadExecState::instrumentFunctionConstruct(&amp;document, constructType, constructData);
</ins><span class="cx">     MarkedArgumentBuffer args;
</span><del>-    args.append(jsStringWithCache(&amp;state, localName));
-
-    InspectorInstrumentationCookie cookie = JSMainThreadExecState::instrumentFunctionConstruct(&amp;document, constructType, constructData);
</del><span class="cx">     JSValue newElement = construct(&amp;state, constructor, constructType, constructData, args);
</span><span class="cx">     InspectorInstrumentation::didCallFunction(cookie, &amp;document);
</span><span class="cx">     RETURN_IF_EXCEPTION(scope, nullptr);
</span></span></pre></div>
<a id="trunkSourceWebCorebindingsjsJSCustomElementInterfaceh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/bindings/js/JSCustomElementInterface.h (208715 => 208716)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/bindings/js/JSCustomElementInterface.h        2016-11-15 00:19:24 UTC (rev 208715)
+++ trunk/Source/WebCore/bindings/js/JSCustomElementInterface.h        2016-11-15 00:27:01 UTC (rev 208716)
</span><span class="lines">@@ -59,6 +59,7 @@
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     Ref&lt;Element&gt; constructElementWithFallback(Document&amp;, const AtomicString&amp;);
</span><ins>+    Ref&lt;Element&gt; constructElementWithFallback(Document&amp;, const QualifiedName&amp;);
</ins><span class="cx"> 
</span><span class="cx">     void upgradeElement(Element&amp;);
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCoredomCustomElementRegistrycpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/dom/CustomElementRegistry.cpp (208715 => 208716)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/dom/CustomElementRegistry.cpp        2016-11-15 00:19:24 UTC (rev 208715)
+++ trunk/Source/WebCore/dom/CustomElementRegistry.cpp        2016-11-15 00:27:01 UTC (rev 208716)
</span><span class="lines">@@ -87,11 +87,9 @@
</span><span class="cx"> 
</span><span class="cx"> JSCustomElementInterface* CustomElementRegistry::findInterface(const QualifiedName&amp; name) const
</span><span class="cx"> {
</span><del>-    ASSERT(!name.hasPrefix());
</del><span class="cx">     if (name.namespaceURI() != HTMLNames::xhtmlNamespaceURI)
</span><span class="cx">         return nullptr;
</span><del>-    auto it = m_nameMap.find(name.localName());
-    return it == m_nameMap.end() || it-&gt;value-&gt;name() != name ? nullptr : const_cast&lt;JSCustomElementInterface*&gt;(it-&gt;value.ptr());
</del><ins>+    return m_nameMap.get(name.localName());
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> JSCustomElementInterface* CustomElementRegistry::findInterface(const AtomicString&amp; name) const
</span></span></pre></div>
<a id="trunkSourceWebCoredomDOMImplementationcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/dom/DOMImplementation.cpp (208715 => 208716)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/dom/DOMImplementation.cpp        2016-11-15 00:19:24 UTC (rev 208715)
+++ trunk/Source/WebCore/dom/DOMImplementation.cpp        2016-11-15 00:27:01 UTC (rev 208716)
</span><span class="lines">@@ -114,6 +114,7 @@
</span><span class="cx"> 
</span><span class="cx">     RefPtr&lt;Element&gt; documentElement;
</span><span class="cx">     if (!qualifiedName.isEmpty()) {
</span><ins>+        ASSERT(!document-&gt;domWindow()); // If domWindow is not null, createElementNS could find CustomElementRegistry and arbitrary scripts.
</ins><span class="cx">         auto result = document-&gt;createElementNS(namespaceURI, qualifiedName);
</span><span class="cx">         if (result.hasException())
</span><span class="cx">             return result.releaseException();
</span></span></pre></div>
<a id="trunkSourceWebCoredomDocumentcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/dom/Document.cpp (208715 => 208716)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/dom/Document.cpp        2016-11-15 00:19:24 UTC (rev 208715)
+++ trunk/Source/WebCore/dom/Document.cpp        2016-11-15 00:27:01 UTC (rev 208716)
</span><span class="lines">@@ -861,22 +861,36 @@
</span><span class="cx">     styleScope().clearResolver();
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-static ALWAYS_INLINE RefPtr&lt;HTMLElement&gt; createUpgradeCandidateElement(Document&amp; document, const QualifiedName&amp; name)
</del><ins>+static ALWAYS_INLINE Ref&lt;HTMLElement&gt; createUpgradeCandidateElement(Document&amp; document, const QualifiedName&amp; name)
</ins><span class="cx"> {
</span><del>-    if (!RuntimeEnabledFeatures::sharedFeatures().customElementsEnabled())
-        return nullptr;
</del><ins>+    if (!RuntimeEnabledFeatures::sharedFeatures().customElementsEnabled()
+        || Document::validateCustomElementName(name.localName()) != CustomElementNameValidationStatus::Valid)
+        return HTMLUnknownElement::create(name, document);
</ins><span class="cx"> 
</span><del>-    if (Document::validateCustomElementName(name.localName()) != CustomElementNameValidationStatus::Valid)
-        return nullptr;
-
</del><span class="cx">     auto element = HTMLElement::create(name, document);
</span><span class="cx">     element-&gt;setIsCustomElementUpgradeCandidate();
</span><del>-    return WTFMove(element);
</del><ins>+    return element;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-static ExceptionOr&lt;Ref&lt;Element&gt;&gt; createHTMLElementWithNameValidation(Document&amp; document, const AtomicString&amp; localName)
</del><ins>+static ALWAYS_INLINE Ref&lt;HTMLElement&gt; createUpgradeCandidateElement(Document&amp; document, const AtomicString&amp; localName)
</ins><span class="cx"> {
</span><del>-    auto element = HTMLElementFactory::createKnownElement(localName, document);
</del><ins>+    return createUpgradeCandidateElement(document, QualifiedName { nullAtom, localName, xhtmlNamespaceURI });
+}
+
+static inline bool isValidHTMLElementName(const AtomicString&amp; localName)
+{
+    return Document::isValidName(localName);
+}
+
+static inline bool isValidHTMLElementName(const QualifiedName&amp; name)
+{
+    return Document::isValidName(name.localName());
+}
+
+template&lt;typename NameType&gt;
+static ExceptionOr&lt;Ref&lt;Element&gt;&gt; createHTMLElementWithNameValidation(Document&amp; document, const NameType&amp; name)
+{
+    auto element = HTMLElementFactory::createKnownElement(name, document);
</ins><span class="cx">     if (LIKELY(element))
</span><span class="cx">         return Ref&lt;Element&gt; { element.releaseNonNull() };
</span><span class="cx"> 
</span><span class="lines">@@ -883,20 +897,15 @@
</span><span class="cx">     if (auto* window = document.domWindow()) {
</span><span class="cx">         auto* registry = window-&gt;customElementRegistry();
</span><span class="cx">         if (UNLIKELY(registry)) {
</span><del>-            if (auto* elementInterface = registry-&gt;findInterface(localName))
-                return elementInterface-&gt;constructElementWithFallback(document, localName);
</del><ins>+            if (auto* elementInterface = registry-&gt;findInterface(name))
+                return elementInterface-&gt;constructElementWithFallback(document, name);
</ins><span class="cx">         }
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    if (UNLIKELY(!Document::isValidName(localName)))
</del><ins>+    if (UNLIKELY(!isValidHTMLElementName(name)))
</ins><span class="cx">         return Exception { INVALID_CHARACTER_ERR };
</span><span class="cx"> 
</span><del>-    QualifiedName qualifiedName { nullAtom, localName, xhtmlNamespaceURI };
-
-    if (auto element = createUpgradeCandidateElement(document, qualifiedName))
-        return Ref&lt;Element&gt; { element.releaseNonNull() };
-
-    return Ref&lt;Element&gt; { HTMLUnknownElement::create(qualifiedName, document) };
</del><ins>+    return Ref&lt;Element&gt; { createUpgradeCandidateElement(document, name) };
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> ExceptionOr&lt;Ref&lt;Element&gt;&gt; Document::createElementForBindings(const AtomicString&amp; name)
</span><span class="lines">@@ -1055,9 +1064,7 @@
</span><span class="cx">         }
</span><span class="cx">     }
</span><span class="cx">     // FIXME: Should we also check the equality of prefix between the custom element and name?
</span><del>-    if (auto element = createUpgradeCandidateElement(document, name))
-        return element.releaseNonNull();
-    return HTMLUnknownElement::create(name, document);
</del><ins>+    return createUpgradeCandidateElement(document, name);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> // FIXME: This should really be in a possible ElementFactory class.
</span><span class="lines">@@ -1159,6 +1166,10 @@
</span><span class="cx">     QualifiedName parsedName { parseResult.releaseReturnValue() };
</span><span class="cx">     if (!hasValidNamespaceForElements(parsedName))
</span><span class="cx">         return Exception { NAMESPACE_ERR };
</span><ins>+
+    if (parsedName.namespaceURI() == xhtmlNamespaceURI)
+        return createHTMLElementWithNameValidation(*this, parsedName);
+
</ins><span class="cx">     return createElement(parsedName, false);
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre>
</div>
</div>

</body>
</html>