<!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>[197917] 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/197917">197917</a></dd>
<dt>Author</dt> <dd>rniwa@webkit.org</dd>
<dt>Date</dt> <dd>2016-03-09 18:33:12 -0800 (Wed, 09 Mar 2016)</dd>
</dl>

<h3>Log Message</h3>
<pre>defineElement should upgrade existing unresolved custom elements
https://bugs.webkit.org/show_bug.cgi?id=155107

Reviewed by Darin Adler.

Source/WebCore:

Added the support for upgrading existing unresolved custom elements when defineElement is called.

The current implementation upgrades elements in the order they were created and has the issue that
it keeps accumulating all elements with a hyphen in its name until defineElement is called as
documented in https://github.com/w3c/webcomponents/issues/419

This patch re-purposes IsEditingTextFlag to indicate that the node is an unresolved custom element.
Since isEditingText() is only called in textRendererIsNeeded only on Text nodes, it's mutually
exclusive with isUnresolvedCustomElement().

The list of unresolved custom elements is kept in m_upgradeCandidatesMap, a hash map of element names
to the list of unresolved elements with that name.

In addition, added the logic to use HTMLElement as the interface for unresolved custom element instead
of HTMLUnknownElement.

Test: fast/custom-elements/upgrading/upgrading-parser-created-element.html

* bindings/js/JSCustomElementInterface.cpp:
(WebCore::JSCustomElementInterface::upgradeElement): Clear the flag.
* bindings/js/JSDocumentCustom.cpp:
(WebCore::JSDocument::defineElement): Set the unique private name to keep the interface alive before
calling addElementDefinition as the call can now invoke author scripts.
* dom/CustomElementDefinitions.cpp:
(WebCore::CustomElementDefinitions::addElementDefinition): Upgrade existing unresolved elements kept
in m_upgradeCandidatesMap.
(WebCore::CustomElementDefinitions::addUpgradeCandidate): Added.
* dom/CustomElementDefinitions.h:
* dom/Document.cpp:
(WebCore::createHTMLElementWithNameValidation): Added the code to add the unresolved custom elements
to the upgrade candidates map. Also instantiate it as HTMLElement instead of HTMLUnknownElement.
(WebCore::createFallbackHTMLElement): Ditto.
* dom/Node.h:
(WebCore::Node::setIsCustomElement):
(WebCore::Node::isUnresolvedCustomElement): Added.
(WebCore::Node::setIsUnresolvedCustomElement): Added.
(WebCore::Node::setCustomElementIsResolved): Added. Clears IsEditingTextOrUnresolvedCustomElementFlag
and sets IsCustomElement.
(WebCore::Node::isEditingText): Check both IsEditingTextOrUnresolvedCustomElementFlag and IsTextFlag
for safety even though it's currently only used in textRendererIsNeeded which takes Text&amp;.
* dom/make_names.pl:
(defaultParametersHash): Added customElementInterfaceName as a parameter.
(printWrapperFactoryCppFile): Generate the code to use customElementInterfaceName when the element
for which the wrapper is created has isUnresolvedCustomElement flag set.
* html/HTMLTagNames.in: Use HTMLElement for unresolved custom elements.
* html/parser/HTMLConstructionSite.cpp:
(WebCore::HTMLConstructionSite::createHTMLElementOrFindCustomElementInterface): Added the code to add
the unresolved custom elements to the upgrade candidates map. Also instantiate it as HTMLElement instead
of HTMLUnknownElement. 

LayoutTests:

Added W3C style testharness.js tests for asynchronously defining custom elements.

* fast/custom-elements/upgrading/Node-cloneNode.html:
* fast/custom-elements/upgrading/upgrading-parser-created-element-expected.txt: Added.
* fast/custom-elements/upgrading/upgrading-parser-created-element.html: Added.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsChangeLog">trunk/LayoutTests/ChangeLog</a></li>
<li><a href="#trunkLayoutTestsfastcustomelementsupgradingNodecloneNodehtml">trunk/LayoutTests/fast/custom-elements/upgrading/Node-cloneNode.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="#trunkSourceWebCorebindingsjsJSDocumentCustomcpp">trunk/Source/WebCore/bindings/js/JSDocumentCustom.cpp</a></li>
<li><a href="#trunkSourceWebCoredomCustomElementDefinitionscpp">trunk/Source/WebCore/dom/CustomElementDefinitions.cpp</a></li>
<li><a href="#trunkSourceWebCoredomCustomElementDefinitionsh">trunk/Source/WebCore/dom/CustomElementDefinitions.h</a></li>
<li><a href="#trunkSourceWebCoredomDocumentcpp">trunk/Source/WebCore/dom/Document.cpp</a></li>
<li><a href="#trunkSourceWebCoredomNodeh">trunk/Source/WebCore/dom/Node.h</a></li>
<li><a href="#trunkSourceWebCoredommake_namespl">trunk/Source/WebCore/dom/make_names.pl</a></li>
<li><a href="#trunkSourceWebCorehtmlHTMLTagNamesin">trunk/Source/WebCore/html/HTMLTagNames.in</a></li>
<li><a href="#trunkSourceWebCorehtmlparserHTMLConstructionSitecpp">trunk/Source/WebCore/html/parser/HTMLConstructionSite.cpp</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsfastcustomelementsupgradingupgradingparsercreatedelementexpectedtxt">trunk/LayoutTests/fast/custom-elements/upgrading/upgrading-parser-created-element-expected.txt</a></li>
<li><a href="#trunkLayoutTestsfastcustomelementsupgradingupgradingparsercreatedelementhtml">trunk/LayoutTests/fast/custom-elements/upgrading/upgrading-parser-created-element.html</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/ChangeLog (197916 => 197917)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/ChangeLog        2016-03-10 02:05:49 UTC (rev 197916)
+++ trunk/LayoutTests/ChangeLog        2016-03-10 02:33:12 UTC (rev 197917)
</span><span class="lines">@@ -1,3 +1,16 @@
</span><ins>+2016-03-09  Ryosuke Niwa  &lt;rniwa@webkit.org&gt;
+
+        defineElement should upgrade existing unresolved custom elements
+        https://bugs.webkit.org/show_bug.cgi?id=155107
+
+        Reviewed by Darin Adler.
+
+        Added W3C style testharness.js tests for asynchronously defining custom elements.
+
+        * fast/custom-elements/upgrading/Node-cloneNode.html:
+        * fast/custom-elements/upgrading/upgrading-parser-created-element-expected.txt: Added.
+        * fast/custom-elements/upgrading/upgrading-parser-created-element.html: Added.
+
</ins><span class="cx"> 2016-03-09  Saam Barati  &lt;sbarati@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         ES6: Implement lexical scoping for function definitions in strict mode
</span></span></pre></div>
<a id="trunkLayoutTestsfastcustomelementsupgradingNodecloneNodehtml"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/fast/custom-elements/upgrading/Node-cloneNode.html (197916 => 197917)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/custom-elements/upgrading/Node-cloneNode.html        2016-03-10 02:05:49 UTC (rev 197916)
+++ trunk/LayoutTests/fast/custom-elements/upgrading/Node-cloneNode.html        2016-03-10 02:33:12 UTC (rev 197917)
</span><span class="lines">@@ -1,7 +1,7 @@
</span><span class="cx"> &lt;!DOCTYPE html&gt;
</span><span class="cx"> &lt;html&gt;
</span><span class="cx"> &lt;head&gt;
</span><del>-&lt;title&gt;Custom Elements: Extensions to Document interface&lt;/title&gt;
</del><ins>+&lt;title&gt;Custom Elements: Upgrading&lt;/title&gt;
</ins><span class="cx"> &lt;meta name=&quot;author&quot; title=&quot;Ryosuke Niwa&quot; href=&quot;mailto:rniwa@webkit.org&quot;&gt;
</span><span class="cx"> &lt;meta name=&quot;assert&quot; content=&quot;Node.prototype.cloneNode should upgrade a custom element&quot;&gt;
</span><span class="cx"> &lt;link rel=&quot;help&quot; href=&quot;https://w3c.github.io/webcomponents/spec/custom/#upgrading&quot;&gt;
</span></span></pre></div>
<a id="trunkLayoutTestsfastcustomelementsupgradingupgradingparsercreatedelementexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/fast/custom-elements/upgrading/upgrading-parser-created-element-expected.txt (0 => 197917)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/custom-elements/upgrading/upgrading-parser-created-element-expected.txt                                (rev 0)
+++ trunk/LayoutTests/fast/custom-elements/upgrading/upgrading-parser-created-element-expected.txt        2016-03-10 02:33:12 UTC (rev 197917)
</span><span class="lines">@@ -0,0 +1,6 @@
</span><ins>+
+PASS Element.prototype.createElement must add an unresolved custom element to the upgrade candidates map 
+PASS HTMLElement constructor must throw an InvalidStateError when the top of the construction stack is marked AlreadyConstructed due to a custom element constructor constructing itself after super() call 
+PASS HTMLElement constructor must throw an InvalidStateError when the top of the construction stack is marked AlreadyConstructed due to a custom element constructor constructing itself before super() call 
+PASS Upgrading a custom element must throw an InvalidStateError when the returned element is not SameValue as the upgraded element 
+
</ins></span></pre></div>
<a id="trunkLayoutTestsfastcustomelementsupgradingupgradingparsercreatedelementhtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/fast/custom-elements/upgrading/upgrading-parser-created-element.html (0 => 197917)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/custom-elements/upgrading/upgrading-parser-created-element.html                                (rev 0)
+++ trunk/LayoutTests/fast/custom-elements/upgrading/upgrading-parser-created-element.html        2016-03-10 02:33:12 UTC (rev 197917)
</span><span class="lines">@@ -0,0 +1,93 @@
</span><ins>+&lt;!DOCTYPE html&gt;
+&lt;html&gt;
+&lt;head&gt;
+&lt;title&gt;Custom Elements: Upgrading unresolved elements&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;HTML parser must add an unresolved custom element to the upgrade candidates map&quot;&gt;
+&lt;link rel=&quot;help&quot; href=&quot;https://w3c.github.io/webcomponents/spec/custom/#upgrading&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;link rel='stylesheet' href='../../../resources/testharness.css'&gt;
+&lt;/head&gt;
+&lt;body&gt;
+&lt;div id=&quot;log&quot;&gt;&lt;/div&gt;
+&lt;my-custom-element&gt;&lt;/my-custom-element&gt;
+&lt;instantiates-itself-after-super&gt;&lt;/instantiates-itself-after-super&gt;
+&lt;instantiates-itself-before-super&gt;&lt;/instantiates-itself-before-super&gt;
+&lt;my-other-element id=&quot;instance&quot;&gt;&lt;/my-other-element&gt;
+&lt;my-other-element id=&quot;otherInstance&quot;&gt;&lt;/my-other-element&gt;
+&lt;script&gt;
+
+test(function () {
+    class MyCustomElement extends HTMLElement { }
+
+    var instance = document.querySelector('my-custom-element');
+    assert_true(instance instanceof HTMLElement);
+    assert_false(instance instanceof HTMLUnknownElement,
+        'an unresolved custom element should not be an instance of HTMLUnknownElement');
+    assert_false(instance instanceof MyCustomElement);
+
+    document.defineElement('my-custom-element', MyCustomElement);
+
+    assert_true(instance instanceof HTMLElement);
+    assert_true(instance instanceof MyCustomElement,
+        'Calling defineElement must upgrade existing custom elements');
+
+}, 'Element.prototype.createElement must add an unresolved custom element to the upgrade candidates map');
+
+
+test(function () {
+    class InstantiatesItselfAfterSuper extends HTMLElement {
+        constructor(doNotCreateItself) {
+            super();
+            if (!doNotCreateItself)
+                new InstantiatesItselfAfterSuper(true);
+        }
+    }
+
+    assert_throws({'name': 'InvalidStateError'}, function () {
+        document.defineElement('instantiates-itself-after-super', InstantiatesItselfAfterSuper);
+    });
+}, 'HTMLElement constructor must throw an InvalidStateError when the top of the construction stack is marked AlreadyConstructed'
+    + ' due to a custom element constructor constructing itself after super() call');
+
+test(function () {
+    class InstantiatesItselfBeforeSuper extends HTMLElement {
+        constructor(doNotCreateItself) {
+            if (!doNotCreateItself)
+                new InstantiatesItselfBeforeSuper(true);
+            super();
+        }
+    }
+
+    assert_throws({'name': 'InvalidStateError'}, function () {
+        document.defineElement('instantiates-itself-before-super', InstantiatesItselfBeforeSuper);
+    });
+}, 'HTMLElement constructor must throw an InvalidStateError when the top of the construction stack is marked AlreadyConstructed'
+    + ' due to a custom element constructor constructing itself before super() call');
+
+test(function () {
+    class MyOtherElement extends HTMLElement {
+        constructor() {
+            super();
+            if (this == instance)
+                return otherInstance;
+        }
+    }
+    var instance = document.getElementById('instance');
+    var otherInstance = document.getElementById('otherInstance');
+
+    assert_false(instance instanceof MyOtherElement);
+    assert_false(otherInstance instanceof MyOtherElement);
+
+    assert_throws({'name': 'InvalidStateError'}, function () {
+        document.defineElement('my-other-element', MyOtherElement);
+    });
+
+    assert_true(document.createElement('my-other-element') instanceof MyOtherElement,
+        'Upgrading of custom elements must happen after the definition was added to the registry.');
+}, 'Upgrading a custom element must throw an InvalidStateError when the returned element is not SameValue as the upgraded element');
+
+&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 (197916 => 197917)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2016-03-10 02:05:49 UTC (rev 197916)
+++ trunk/Source/WebCore/ChangeLog        2016-03-10 02:33:12 UTC (rev 197917)
</span><span class="lines">@@ -1,3 +1,60 @@
</span><ins>+2016-03-09  Ryosuke Niwa  &lt;rniwa@webkit.org&gt;
+
+        defineElement should upgrade existing unresolved custom elements
+        https://bugs.webkit.org/show_bug.cgi?id=155107
+
+        Reviewed by Darin Adler.
+
+        Added the support for upgrading existing unresolved custom elements when defineElement is called.
+
+        The current implementation upgrades elements in the order they were created and has the issue that
+        it keeps accumulating all elements with a hyphen in its name until defineElement is called as
+        documented in https://github.com/w3c/webcomponents/issues/419
+
+        This patch re-purposes IsEditingTextFlag to indicate that the node is an unresolved custom element.
+        Since isEditingText() is only called in textRendererIsNeeded only on Text nodes, it's mutually
+        exclusive with isUnresolvedCustomElement().
+
+        The list of unresolved custom elements is kept in m_upgradeCandidatesMap, a hash map of element names
+        to the list of unresolved elements with that name.
+
+        In addition, added the logic to use HTMLElement as the interface for unresolved custom element instead
+        of HTMLUnknownElement.
+
+        Test: fast/custom-elements/upgrading/upgrading-parser-created-element.html
+
+        * bindings/js/JSCustomElementInterface.cpp:
+        (WebCore::JSCustomElementInterface::upgradeElement): Clear the flag.
+        * bindings/js/JSDocumentCustom.cpp:
+        (WebCore::JSDocument::defineElement): Set the unique private name to keep the interface alive before
+        calling addElementDefinition as the call can now invoke author scripts.
+        * dom/CustomElementDefinitions.cpp:
+        (WebCore::CustomElementDefinitions::addElementDefinition): Upgrade existing unresolved elements kept
+        in m_upgradeCandidatesMap.
+        (WebCore::CustomElementDefinitions::addUpgradeCandidate): Added.
+        * dom/CustomElementDefinitions.h:
+        * dom/Document.cpp:
+        (WebCore::createHTMLElementWithNameValidation): Added the code to add the unresolved custom elements
+        to the upgrade candidates map. Also instantiate it as HTMLElement instead of HTMLUnknownElement.
+        (WebCore::createFallbackHTMLElement): Ditto.
+        * dom/Node.h:
+        (WebCore::Node::setIsCustomElement):
+        (WebCore::Node::isUnresolvedCustomElement): Added.
+        (WebCore::Node::setIsUnresolvedCustomElement): Added.
+        (WebCore::Node::setCustomElementIsResolved): Added. Clears IsEditingTextOrUnresolvedCustomElementFlag
+        and sets IsCustomElement.
+        (WebCore::Node::isEditingText): Check both IsEditingTextOrUnresolvedCustomElementFlag and IsTextFlag
+        for safety even though it's currently only used in textRendererIsNeeded which takes Text&amp;.
+        * dom/make_names.pl:
+        (defaultParametersHash): Added customElementInterfaceName as a parameter.
+        (printWrapperFactoryCppFile): Generate the code to use customElementInterfaceName when the element
+        for which the wrapper is created has isUnresolvedCustomElement flag set.
+        * html/HTMLTagNames.in: Use HTMLElement for unresolved custom elements.
+        * html/parser/HTMLConstructionSite.cpp:
+        (WebCore::HTMLConstructionSite::createHTMLElementOrFindCustomElementInterface): Added the code to add
+        the unresolved custom elements to the upgrade candidates map. Also instantiate it as HTMLElement instead
+        of HTMLUnknownElement. 
+
</ins><span class="cx"> 2016-03-09  Enrica Casucci  &lt;enrica@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Retrieve additional context for some data detector link for preview and action menu.
</span></span></pre></div>
<a id="trunkSourceWebCorebindingsjsJSCustomElementInterfacecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/bindings/js/JSCustomElementInterface.cpp (197916 => 197917)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/bindings/js/JSCustomElementInterface.cpp        2016-03-10 02:05:49 UTC (rev 197916)
+++ trunk/Source/WebCore/bindings/js/JSCustomElementInterface.cpp        2016-03-10 02:33:12 UTC (rev 197917)
</span><span class="lines">@@ -104,7 +104,7 @@
</span><span class="cx"> 
</span><span class="cx"> void JSCustomElementInterface::upgradeElement(Element&amp; element)
</span><span class="cx"> {
</span><del>-    ASSERT(element.isCustomElement());
</del><ins>+    ASSERT(element.isUnresolvedCustomElement());
</ins><span class="cx">     if (!canInvokeCallback())
</span><span class="cx">         return;
</span><span class="cx"> 
</span><span class="lines">@@ -147,6 +147,7 @@
</span><span class="cx">         throwInvalidStateError(*state, &quot;Custom element constructor failed to upgrade an element&quot;);
</span><span class="cx">         return;
</span><span class="cx">     }
</span><ins>+    wrappedElement-&gt;setCustomElementIsResolved();
</ins><span class="cx">     ASSERT(wrappedElement-&gt;isCustomElement());
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCorebindingsjsJSDocumentCustomcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/bindings/js/JSDocumentCustom.cpp (197916 => 197917)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/bindings/js/JSDocumentCustom.cpp        2016-03-10 02:05:49 UTC (rev 197916)
+++ trunk/Source/WebCore/bindings/js/JSDocumentCustom.cpp        2016-03-10 02:33:12 UTC (rev 197917)
</span><span class="lines">@@ -180,11 +180,12 @@
</span><span class="cx">     // FIXME: 13. Let detachedCallback be Get(prototype, &quot;detachedCallback&quot;). Rethrow any exceptions.
</span><span class="cx">     // FIXME: 14. Let attributeChangedCallback be Get(prototype, &quot;attributeChangedCallback&quot;). Rethrow any exceptions.
</span><span class="cx"> 
</span><del>-    QualifiedName name(nullAtom, tagName, HTMLNames::xhtmlNamespaceURI);
-    definitions.addElementDefinition(JSCustomElementInterface::create(name, object, globalObject()));
</del><span class="cx">     PrivateName uniquePrivateName;
</span><span class="cx">     globalObject()-&gt;putDirect(globalObject()-&gt;vm(), uniquePrivateName, object);
</span><span class="cx"> 
</span><ins>+    QualifiedName name(nullAtom, tagName, HTMLNames::xhtmlNamespaceURI);
+    definitions.addElementDefinition(JSCustomElementInterface::create(name, object, globalObject()));
+
</ins><span class="cx">     // FIXME: 17. Let map be registry's upgrade candidates map.
</span><span class="cx">     // FIXME: 18. Upgrade a newly-defined element given map and definition.
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCoredomCustomElementDefinitionscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/dom/CustomElementDefinitions.cpp (197916 => 197917)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/dom/CustomElementDefinitions.cpp        2016-03-10 02:05:49 UTC (rev 197916)
+++ trunk/Source/WebCore/dom/CustomElementDefinitions.cpp        2016-03-10 02:33:12 UTC (rev 197917)
</span><span class="lines">@@ -74,9 +74,35 @@
</span><span class="cx">     AtomicString localName = interface-&gt;name().localName();
</span><span class="cx">     ASSERT(!m_nameMap.contains(localName));
</span><span class="cx">     m_constructorMap.add(interface-&gt;constructor(), interface.ptr());
</span><del>-    m_nameMap.add(localName, WTFMove(interface));
</del><ins>+    m_nameMap.add(localName, interface.copyRef());
+
+    auto candidateList = m_upgradeCandidatesMap.find(localName);
+    if (candidateList == m_upgradeCandidatesMap.end())
+        return;
+
+    Vector&lt;RefPtr&lt;Element&gt;&gt; list(WTFMove(candidateList-&gt;value));
+
+    m_upgradeCandidatesMap.remove(localName);
+
+    for (auto&amp; candidate : list) {
+        ASSERT(candidate);
+        interface-&gt;upgradeElement(*candidate);
+    }
+
+    // We should not be adding more upgrade candidate for this local name.
+    ASSERT(!m_upgradeCandidatesMap.contains(localName));
</ins><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void CustomElementDefinitions::addUpgradeCandidate(Element&amp; candidate)
+{
+    auto result = m_upgradeCandidatesMap.ensure(candidate.localName(), [] {
+        return Vector&lt;RefPtr&lt;Element&gt;&gt;();
+    });
+    auto&amp; nodeVector = result.iterator-&gt;value;
+    ASSERT(!nodeVector.contains(&amp;candidate));
+    nodeVector.append(&amp;candidate);
+}
+
</ins><span class="cx"> JSCustomElementInterface* CustomElementDefinitions::findInterface(const QualifiedName&amp; name) const
</span><span class="cx"> {
</span><span class="cx">     auto it = m_nameMap.find(name.localName());
</span></span></pre></div>
<a id="trunkSourceWebCoredomCustomElementDefinitionsh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/dom/CustomElementDefinitions.h (197916 => 197917)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/dom/CustomElementDefinitions.h        2016-03-10 02:05:49 UTC (rev 197916)
+++ trunk/Source/WebCore/dom/CustomElementDefinitions.h        2016-03-10 02:33:12 UTC (rev 197917)
</span><span class="lines">@@ -49,6 +49,7 @@
</span><span class="cx">     WTF_MAKE_FAST_ALLOCATED;
</span><span class="cx"> public:
</span><span class="cx">     void addElementDefinition(Ref&lt;JSCustomElementInterface&gt;&amp;&amp;);
</span><ins>+    void addUpgradeCandidate(Element&amp;);
</ins><span class="cx"> 
</span><span class="cx">     JSCustomElementInterface* findInterface(const QualifiedName&amp;) const;
</span><span class="cx">     JSCustomElementInterface* findInterface(const AtomicString&amp;) const;
</span><span class="lines">@@ -59,6 +60,7 @@
</span><span class="cx">     static NameStatus checkName(const AtomicString&amp; tagName);
</span><span class="cx"> 
</span><span class="cx"> private:
</span><ins>+    HashMap&lt;AtomicString, Vector&lt;RefPtr&lt;Element&gt;&gt;&gt; m_upgradeCandidatesMap;
</ins><span class="cx">     HashMap&lt;AtomicString, RefPtr&lt;JSCustomElementInterface&gt;&gt; m_nameMap;
</span><span class="cx">     HashMap&lt;const JSC::JSObject*, JSCustomElementInterface*&gt; m_constructorMap;
</span><span class="cx"> };
</span></span></pre></div>
<a id="trunkSourceWebCoredomDocumentcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/dom/Document.cpp (197916 => 197917)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/dom/Document.cpp        2016-03-10 02:05:49 UTC (rev 197916)
+++ trunk/Source/WebCore/dom/Document.cpp        2016-03-10 02:33:12 UTC (rev 197917)
</span><span class="lines">@@ -899,7 +899,18 @@
</span><span class="cx">         return nullptr;
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    return HTMLUnknownElement::create(QualifiedName(nullAtom, localName, xhtmlNamespaceURI), document);
</del><ins>+    QualifiedName qualifiedName(nullAtom, localName, xhtmlNamespaceURI);
+
+#if ENABLE(CUSTOM_ELEMENTS)
+    if (CustomElementDefinitions::checkName(localName) == CustomElementDefinitions::NameStatus::Valid) {
+        Ref&lt;HTMLElement&gt; element = HTMLElement::create(qualifiedName, document);
+        element-&gt;setIsUnresolvedCustomElement();
+        document.ensureCustomElementDefinitions().addUpgradeCandidate(element.get());
+        return WTFMove(element);
+    }
+#endif
+
+    return HTMLUnknownElement::create(qualifiedName, document);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> RefPtr&lt;Element&gt; Document::createElementForBindings(const AtomicString&amp; name, ExceptionCode&amp; ec)
</span><span class="lines">@@ -1080,11 +1091,18 @@
</span><span class="cx">     if (UNLIKELY(definitions)) {
</span><span class="cx">         if (auto* interface = definitions-&gt;findInterface(name)) {
</span><span class="cx">             Ref&lt;HTMLElement&gt; element = HTMLElement::create(name, document);
</span><del>-            element-&gt;setIsCustomElement(); // Pre-upgrade element is still considered a custom element.
</del><ins>+            element-&gt;setIsUnresolvedCustomElement();
</ins><span class="cx">             LifecycleCallbackQueue::enqueueElementUpgrade(element.get(), *interface);
</span><span class="cx">             return element;
</span><span class="cx">         }
</span><span class="cx">     }
</span><ins>+    // FIXME: Should we also check the equality of prefix between the custom element and name?
+    if (CustomElementDefinitions::checkName(name.localName()) == CustomElementDefinitions::NameStatus::Valid) {
+        Ref&lt;HTMLElement&gt; element = HTMLElement::create(name, document);
+        element-&gt;setIsUnresolvedCustomElement();
+        document.ensureCustomElementDefinitions().addUpgradeCandidate(element.get());
+        return element;
+    }
</ins><span class="cx"> #endif
</span><span class="cx">     return HTMLUnknownElement::create(name, document);
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceWebCoredomNodeh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/dom/Node.h (197916 => 197917)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/dom/Node.h        2016-03-10 02:05:49 UTC (rev 197916)
+++ trunk/Source/WebCore/dom/Node.h        2016-03-10 02:33:12 UTC (rev 197917)
</span><span class="lines">@@ -266,7 +266,11 @@
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(CUSTOM_ELEMENTS)
</span><span class="cx">     bool isCustomElement() const { return getFlag(IsCustomElement); }
</span><del>-    void setIsCustomElement() { return setFlag(IsCustomElement); }
</del><ins>+    void setIsCustomElement() { setFlag(IsCustomElement); }
+
+    bool isUnresolvedCustomElement() const { return isElementNode() &amp;&amp; getFlag(IsEditingTextOrUnresolvedCustomElementFlag); }
+    void setIsUnresolvedCustomElement() { setFlag(IsEditingTextOrUnresolvedCustomElementFlag); }
+    void setCustomElementIsResolved();
</ins><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="cx">     // Returns null, a child of ShadowRoot, or a legacy shadow root.
</span><span class="lines">@@ -320,7 +324,7 @@
</span><span class="cx">     StyleChangeType styleChangeType() const { return static_cast&lt;StyleChangeType&gt;(m_nodeFlags &amp; StyleChangeMask); }
</span><span class="cx">     bool childNeedsStyleRecalc() const { return getFlag(ChildNeedsStyleRecalcFlag); }
</span><span class="cx">     bool styleIsAffectedByPreviousSibling() const { return getFlag(StyleIsAffectedByPreviousSibling); }
</span><del>-    bool isEditingText() const { return getFlag(IsEditingTextFlag); }
</del><ins>+    bool isEditingText() const { return getFlag(IsTextFlag) &amp;&amp; getFlag(IsEditingTextOrUnresolvedCustomElementFlag); }
</ins><span class="cx"> 
</span><span class="cx">     void setChildNeedsStyleRecalc() { setFlag(ChildNeedsStyleRecalcFlag); }
</span><span class="cx">     void clearChildNeedsStyleRecalc() { m_nodeFlags &amp;= ~(ChildNeedsStyleRecalcFlag | DirectChildNeedsStyleRecalcFlag); }
</span><span class="lines">@@ -595,7 +599,7 @@
</span><span class="cx">         IsParsingChildrenFinishedFlag = 1 &lt;&lt; 13, // Element
</span><span class="cx"> 
</span><span class="cx">         StyleChangeMask = 1 &lt;&lt; nodeStyleChangeShift | 1 &lt;&lt; (nodeStyleChangeShift + 1) | 1 &lt;&lt; (nodeStyleChangeShift + 2),
</span><del>-        IsEditingTextFlag = 1 &lt;&lt; 17,
</del><ins>+        IsEditingTextOrUnresolvedCustomElementFlag = 1 &lt;&lt; 17,
</ins><span class="cx">         IsNamedFlowContentNodeFlag = 1 &lt;&lt; 18,
</span><span class="cx">         HasSyntheticAttrChildNodesFlag = 1 &lt;&lt; 19,
</span><span class="cx">         HasCustomStyleResolveCallbacksFlag = 1 &lt;&lt; 20,
</span><span class="lines">@@ -634,7 +638,7 @@
</span><span class="cx">         CreateHTMLElement = CreateStyledElement | IsHTMLFlag,
</span><span class="cx">         CreateSVGElement = CreateStyledElement | IsSVGFlag | HasCustomStyleResolveCallbacksFlag,
</span><span class="cx">         CreateDocument = CreateContainer | InDocumentFlag,
</span><del>-        CreateEditingText = CreateText | IsEditingTextFlag,
</del><ins>+        CreateEditingText = CreateText | IsEditingTextOrUnresolvedCustomElementFlag,
</ins><span class="cx">         CreateMathMLElement = CreateStyledElement | IsMathMLFlag
</span><span class="cx">     };
</span><span class="cx">     Node(Document&amp;, ConstructionType);
</span><span class="lines">@@ -769,6 +773,16 @@
</span><span class="cx">     return parentNode();
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+#if ENABLE(CUSTOM_ELEMENTS)
+
+inline void Node::setCustomElementIsResolved()
+{
+    clearFlag(IsEditingTextOrUnresolvedCustomElementFlag);
+    setFlag(IsCustomElement);
+}
+
+#endif
+
</ins><span class="cx"> } // namespace WebCore
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(TREE_DEBUGGING)
</span></span></pre></div>
<a id="trunkSourceWebCoredommake_namespl"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/dom/make_names.pl (197916 => 197917)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/dom/make_names.pl        2016-03-10 02:05:49 UTC (rev 197916)
+++ trunk/Source/WebCore/dom/make_names.pl        2016-03-10 02:33:12 UTC (rev 197917)
</span><span class="lines">@@ -216,6 +216,7 @@
</span><span class="cx">         'attrsNullNamespace' =&gt; 0,
</span><span class="cx">         'fallbackInterfaceName' =&gt; '',
</span><span class="cx">         'fallbackJSInterfaceName' =&gt; '',
</span><ins>+        'customElementInterfaceName' =&gt; '',
</ins><span class="cx">     );
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -1318,6 +1319,20 @@
</span><span class="cx">         populate$parameters{namespace}WrapperMap(functions);
</span><span class="cx">     if (auto function = functions.get().get(element-&gt;localName().impl()))
</span><span class="cx">         return function(globalObject, element);
</span><ins>+END
+;
+
+    if ($parameters{customElementInterfaceName}) {
+        print F &lt;&lt;END
+#if ENABLE(CUSTOM_ELEMENTS)
+    if (element-&gt;isUnresolvedCustomElement())
+        return CREATE_DOM_WRAPPER(globalObject, $parameters{customElementInterfaceName}, element.get());
+#endif
+END
+;
+    }
+
+    print F &lt;&lt;END
</ins><span class="cx">     return CREATE_DOM_WRAPPER(globalObject, $parameters{fallbackJSInterfaceName}, element.get());
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCorehtmlHTMLTagNamesin"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/html/HTMLTagNames.in (197916 => 197917)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/html/HTMLTagNames.in        2016-03-10 02:05:49 UTC (rev 197916)
+++ trunk/Source/WebCore/html/HTMLTagNames.in        2016-03-10 02:33:12 UTC (rev 197917)
</span><span class="lines">@@ -2,6 +2,7 @@
</span><span class="cx"> namespacePrefix=&quot;xhtml&quot;
</span><span class="cx"> namespaceURI=&quot;http://www.w3.org/1999/xhtml&quot;
</span><span class="cx"> fallbackInterfaceName=&quot;HTMLUnknownElement&quot;
</span><ins>+customElementInterfaceName=&quot;HTMLElement&quot;
</ins><span class="cx"> 
</span><span class="cx"> a interfaceName=HTMLAnchorElement
</span><span class="cx"> abbr interfaceName=HTMLElement
</span></span></pre></div>
<a id="trunkSourceWebCorehtmlparserHTMLConstructionSitecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/html/parser/HTMLConstructionSite.cpp (197916 => 197917)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/html/parser/HTMLConstructionSite.cpp        2016-03-10 02:05:49 UTC (rev 197916)
+++ trunk/Source/WebCore/html/parser/HTMLConstructionSite.cpp        2016-03-10 02:33:12 UTC (rev 197917)
</span><span class="lines">@@ -672,20 +672,29 @@
</span><span class="cx">     bool insideTemplateElement = !ownerDocument.frame();
</span><span class="cx">     RefPtr&lt;Element&gt; element = HTMLElementFactory::createKnownElement(localName, ownerDocument, insideTemplateElement ? nullptr : form(), true);
</span><span class="cx">     if (UNLIKELY(!element)) {
</span><del>-
</del><span class="cx"> #if ENABLE(CUSTOM_ELEMENTS)
</span><del>-        auto* definitions = ownerDocumentForCurrentNode().customElementDefinitions();
-        if (customElementInterface &amp;&amp; UNLIKELY(definitions)) {
-            if (auto* interface = definitions-&gt;findInterface(localName)) {
-                *customElementInterface = interface;
-                return nullptr;
</del><ins>+        if (customElementInterface) {
+            auto* definitions = ownerDocument.customElementDefinitions();
+            if (UNLIKELY(definitions)) {
+                if (auto* interface = definitions-&gt;findInterface(localName)) {
+                    *customElementInterface = interface;
+                    return nullptr;
+                }
</ins><span class="cx">             }
</span><span class="cx">         }
</span><span class="cx"> #else
</span><span class="cx">         UNUSED_PARAM(customElementInterface);
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><del>-        element = HTMLUnknownElement::create(QualifiedName(nullAtom, localName, xhtmlNamespaceURI), ownerDocumentForCurrentNode());
</del><ins>+        QualifiedName qualifiedName(nullAtom, localName, xhtmlNamespaceURI);
+#if ENABLE(CUSTOM_ELEMENTS)
+        if (CustomElementDefinitions::checkName(localName) == CustomElementDefinitions::NameStatus::Valid) {
+            element = HTMLElement::create(qualifiedName, ownerDocument);
+            element-&gt;setIsUnresolvedCustomElement();
+            ownerDocument.ensureCustomElementDefinitions().addUpgradeCandidate(*element);
+        } else
+#endif
+            element = HTMLUnknownElement::create(qualifiedName, ownerDocument);
</ins><span class="cx">     }
</span><span class="cx">     ASSERT(element);
</span><span class="cx"> 
</span></span></pre>
</div>
</div>

</body>
</html>