<!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>[197634] 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/197634">197634</a></dd>
<dt>Author</dt> <dd>rniwa@webkit.org</dd>
<dt>Date</dt> <dd>2016-03-05 21:07:47 -0800 (Sat, 05 Mar 2016)</dd>
</dl>

<h3>Log Message</h3>
<pre>Add the support for upgrading custom elements in cloneNode
https://bugs.webkit.org/show_bug.cgi?id=155062

Reviewed by Antti Koivisto.

Source/WebCore:

Implement https://w3c.github.io/webcomponents/spec/custom/#upgrading and steps 6 through 11 in
https://w3c.github.io/webcomponents/spec/custom/#htmlelement-constructor to support upgrading elements
created by Node.prototype.cloneNode.

Tests: fast/custom-elements/lifecycle-callback-timing.html
       fast/custom-elements/upgrading/Node-cloneNode.html

* bindings/js/JSCustomElementInterface.cpp:
(WebCore::JSCustomElementInterface::upgradeElement): Added. Implements
 https://w3c.github.io/webcomponents/spec/custom/#dfn-upgrade-a-custom-element
(WebCore::JSCustomElementInterface::didUpgradeLastElementInConstructionStack): Added. Implements step 10
 &quot;Replace the last entry in definition's construction stacka with an already constructed marker.&quot;
 in https://w3c.github.io/webcomponents/spec/custom/#dom-htmlelement-constructor
* bindings/js/JSCustomElementInterface.h:
(WebCore::JSCustomElementInterface::isUpgradingElement):
(WebCore::JSCustomElementInterface::lastElementInConstructionStack):
(WebCore::JSCustomElementInterface): Added m_constructionStack. This is the construction stack:
 https://w3c.github.io/webcomponents/spec/custom/#dfn-element-definition-construction-stack
* bindings/js/JSDOMBinding.cpp:
(WebCore::throwInvalidStateError): Added.
* bindings/js/JSDOMBinding.h:
* bindings/js/JSHTMLElementCustom.cpp:
(WebCore::constructJSHTMLElement): Implement the upgrading case in:
 https://w3c.github.io/webcomponents/spec/custom/#htmlelement-constructor
* dom/Document.cpp:
(WebCore::createFallbackHTMLElement): Added. Enqueues upgrades of custom elements (enqueueElementUpgrade
 currently does nothing if there is no InvokesCustomElementLifecycleCallbacks; e.g. in other DOM APIs).
 This function implements https://w3c.github.io/webcomponents/spec/custom/#dfn-element-upgrade-algorithm
(WebCore::Document::createElement):
* dom/LifecycleCallbackQueue.cpp:
(WebCore::LifecycleQueueItem::LifecycleQueueItem): Added a generic constructor.
(WebCore::LifecycleQueueItem::invoke): Call upgradeElement when m_type is Type::ElementUpgrade.
(WebCore::LifecycleCallbackQueue::enqueueElementUpgrade): Added.
* dom/LifecycleCallbackQueue.h:
* dom/Node.idl: Added InvokesCustomElementLifecycleCallbacks on cloneNode.
* dom/make_names.pl:
(printFactoryCppFile): Added a variant of createKnownElement which takes QualifiedName. Also directly call
 find(HTML|SVG|MathML)ElementConstructorFunction in createElement that takes AtomicString to avoid an extra
 function call.
(printFactoryHeaderFile): Added a function declaration for createKnownElement that takes QualifiedName and
 outdented class and function declarations to match the modern code style guideline.

LayoutTests:

Added test cases for upgrading elements with Node.prototype.cloneNode.

* fast/custom-elements/lifecycle-callback-timing-expected.txt:
* fast/custom-elements/lifecycle-callback-timing.html:</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsChangeLog">trunk/LayoutTests/ChangeLog</a></li>
<li><a href="#trunkLayoutTestsfastcustomelementslifecyclecallbacktimingexpectedtxt">trunk/LayoutTests/fast/custom-elements/lifecycle-callback-timing-expected.txt</a></li>
<li><a href="#trunkLayoutTestsfastcustomelementslifecyclecallbacktiminghtml">trunk/LayoutTests/fast/custom-elements/lifecycle-callback-timing.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="#trunkSourceWebCorebindingsjsJSDOMBindingcpp">trunk/Source/WebCore/bindings/js/JSDOMBinding.cpp</a></li>
<li><a href="#trunkSourceWebCorebindingsjsJSDOMBindingh">trunk/Source/WebCore/bindings/js/JSDOMBinding.h</a></li>
<li><a href="#trunkSourceWebCorebindingsjsJSHTMLElementCustomcpp">trunk/Source/WebCore/bindings/js/JSHTMLElementCustom.cpp</a></li>
<li><a href="#trunkSourceWebCoredomDocumentcpp">trunk/Source/WebCore/dom/Document.cpp</a></li>
<li><a href="#trunkSourceWebCoredomLifecycleCallbackQueuecpp">trunk/Source/WebCore/dom/LifecycleCallbackQueue.cpp</a></li>
<li><a href="#trunkSourceWebCoredomLifecycleCallbackQueueh">trunk/Source/WebCore/dom/LifecycleCallbackQueue.h</a></li>
<li><a href="#trunkSourceWebCoredomNodeidl">trunk/Source/WebCore/dom/Node.idl</a></li>
<li><a href="#trunkSourceWebCoredommake_namespl">trunk/Source/WebCore/dom/make_names.pl</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li>trunk/LayoutTests/fast/custom-elements/upgrading/</li>
<li><a href="#trunkLayoutTestsfastcustomelementsupgradingNodecloneNodeexpectedtxt">trunk/LayoutTests/fast/custom-elements/upgrading/Node-cloneNode-expected.txt</a></li>
<li><a href="#trunkLayoutTestsfastcustomelementsupgradingNodecloneNodehtml">trunk/LayoutTests/fast/custom-elements/upgrading/Node-cloneNode.html</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/ChangeLog (197633 => 197634)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/ChangeLog        2016-03-06 05:02:49 UTC (rev 197633)
+++ trunk/LayoutTests/ChangeLog        2016-03-06 05:07:47 UTC (rev 197634)
</span><span class="lines">@@ -1,3 +1,15 @@
</span><ins>+2016-03-05  Ryosuke Niwa  &lt;rniwa@webkit.org&gt;
+
+        Add the support for upgrading custom elements in cloneNode
+        https://bugs.webkit.org/show_bug.cgi?id=155062
+
+        Reviewed by Antti Koivisto.
+
+        Added test cases for upgrading elements with Node.prototype.cloneNode.
+
+        * fast/custom-elements/lifecycle-callback-timing-expected.txt:
+        * fast/custom-elements/lifecycle-callback-timing.html:
+
</ins><span class="cx"> 2016-03-05  Sam Weinig  &lt;sam@webkit.org&gt;
</span><span class="cx"> 
</span><span class="cx">         Update tests to match the latest version of the HTML5 spec.
</span></span></pre></div>
<a id="trunkLayoutTestsfastcustomelementslifecyclecallbacktimingexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/fast/custom-elements/lifecycle-callback-timing-expected.txt (197633 => 197634)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/custom-elements/lifecycle-callback-timing-expected.txt        2016-03-06 05:02:49 UTC (rev 197633)
+++ trunk/LayoutTests/fast/custom-elements/lifecycle-callback-timing-expected.txt        2016-03-06 05:07:47 UTC (rev 197634)
</span><span class="lines">@@ -1,3 +1,4 @@
</span><span class="cx"> 
</span><span class="cx"> PASS setAttribute and removeAttribute must enqueue and invoke attributeChangedCallback 
</span><ins>+PASS Calling Node.prototype.cloneNode(false) must push a new element queue to the processing stack 
</ins><span class="cx"> 
</span></span></pre></div>
<a id="trunkLayoutTestsfastcustomelementslifecyclecallbacktiminghtml"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/fast/custom-elements/lifecycle-callback-timing.html (197633 => 197634)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/custom-elements/lifecycle-callback-timing.html        2016-03-06 05:02:49 UTC (rev 197633)
+++ trunk/LayoutTests/fast/custom-elements/lifecycle-callback-timing.html        2016-03-06 05:07:47 UTC (rev 197634)
</span><span class="lines">@@ -47,6 +47,42 @@
</span><span class="cx"> 
</span><span class="cx"> }, 'setAttribute and removeAttribute must enqueue and invoke attributeChangedCallback');
</span><span class="cx"> 
</span><ins>+test(function () {
+    var shouldCloneAnotherInstance = false;
+    var anotherInstanceClone;
+    var log = [];
+
+    class SelfCloningElement extends HTMLElement {
+        constructor() {
+            super();
+            log.push([this, 'begin']);
+            if (shouldCloneAnotherInstance) {
+                shouldCloneAnotherInstance = false;
+                anotherInstanceClone = anotherInstance.cloneNode(false);
+            }
+            log.push([this, 'end']);
+        }
+    }
+    document.defineElement('self-cloning-element', SelfCloningElement);
+
+    var instance = document.createElement('self-cloning-element');
+    var anotherInstance = document.createElement('self-cloning-element');
+    shouldCloneAnotherInstance = true;
+
+    assert_equals(log.length, 4);
+    var instanceClone = instance.cloneNode(false);
+
+    assert_equals(log.length, 8);
+    assert_array_equals(log[0], [instance, 'begin']);
+    assert_array_equals(log[1], [instance, 'end']);
+    assert_array_equals(log[2], [anotherInstance, 'begin']);
+    assert_array_equals(log[3], [anotherInstance, 'end']);
+    assert_array_equals(log[4], [instanceClone, 'begin']);
+    assert_array_equals(log[5], [anotherInstanceClone, 'begin']);
+    assert_array_equals(log[6], [anotherInstanceClone, 'end']);
+    assert_array_equals(log[7], [instanceClone, 'end']);
+}, 'Calling Node.prototype.cloneNode(false) must push a new element queue to the processing stack');
+
</ins><span class="cx"> &lt;/script&gt;
</span><span class="cx"> &lt;/body&gt;
</span><span class="cx"> &lt;/html&gt;
</span></span></pre></div>
<a id="trunkLayoutTestsfastcustomelementsupgradingNodecloneNodeexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/fast/custom-elements/upgrading/Node-cloneNode-expected.txt (0 => 197634)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/custom-elements/upgrading/Node-cloneNode-expected.txt                                (rev 0)
+++ trunk/LayoutTests/fast/custom-elements/upgrading/Node-cloneNode-expected.txt        2016-03-06 05:07:47 UTC (rev 197634)
</span><span class="lines">@@ -0,0 +1,9 @@
</span><ins>+
+PASS Node.prototype.cloneNode(false) must be able to clone a custom element 
+PASS Node.prototype.cloneNode(false) must be able to clone a custom element inside an iframe 
+PASS Node.prototype.cloneNode(true) must be able to clone a descendent custom element 
+PASS Node.prototype.cloneNode(true) must be able to clone a descendent custom element 
+PASS HTMLElement constructor must throw an InvalidStateError when the top of the construction stack is marked AlreadyConstructed due to a custom element constructor constructing itself after super() call 
+PASS HTMLElement constructor must throw an InvalidStateError when the top of the construction stack is marked AlreadyConstructed due to a custom element constructor constructing itself before super() call 
+PASS Upgrading a custom element must throw InvalidStateError when the custom element's constructor returns another element 
+
</ins></span></pre></div>
<a id="trunkLayoutTestsfastcustomelementsupgradingNodecloneNodehtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/fast/custom-elements/upgrading/Node-cloneNode.html (0 => 197634)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/custom-elements/upgrading/Node-cloneNode.html                                (rev 0)
+++ trunk/LayoutTests/fast/custom-elements/upgrading/Node-cloneNode.html        2016-03-06 05:07:47 UTC (rev 197634)
</span><span class="lines">@@ -0,0 +1,169 @@
</span><ins>+&lt;!DOCTYPE html&gt;
+&lt;html&gt;
+&lt;head&gt;
+&lt;title&gt;Custom Elements: Extensions to Document interface&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;Node.prototype.cloneNode should upgrade a custom element&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;script&gt;
+
+function withNewDocumentWithABrowsingContext(callback) {
+    var iframe = document.createElement('iframe');
+    document.body.appendChild(iframe);
+    try {
+        callback(iframe.contentWindow, iframe.contentDocument);        
+    } finally {
+        document.body.removeChild(iframe);
+    }
+}
+
+test(function () {
+    class MyCustomElement extends HTMLElement {}
+    document.defineElement('my-custom-element', MyCustomElement);
+
+    var instance = document.createElement('my-custom-element');
+    assert_true(instance instanceof HTMLElement);
+    assert_true(instance instanceof MyCustomElement);
+
+    var clone = instance.cloneNode(false);
+    assert_not_equals(instance, clone);
+    assert_true(clone instanceof HTMLElement,
+        'A cloned custom element must be an instance of HTMLElement');
+    assert_true(clone instanceof MyCustomElement,
+        'A cloned custom element must be an instance of the custom element');
+}, 'Node.prototype.cloneNode(false) must be able to clone a custom element');
+
+test(function () {
+    withNewDocumentWithABrowsingContext(function (contentWindow, contentDocument) {
+        class MyCustomElement extends contentWindow.HTMLElement {}
+        contentDocument.defineElement('my-custom-element', MyCustomElement);
+
+        var instance = contentDocument.createElement('my-custom-element');
+        assert_true(instance instanceof contentWindow.HTMLElement);
+        assert_true(instance instanceof MyCustomElement);
+
+        var clone = instance.cloneNode(false);
+        assert_not_equals(instance, clone);
+        assert_true(clone instanceof contentWindow.HTMLElement,
+            'A cloned custom element must be an instance of HTMLElement');
+        assert_true(clone instanceof MyCustomElement,
+            'A cloned custom element must be an instance of the custom element');
+    });
+}, 'Node.prototype.cloneNode(false) must be able to clone a custom element inside an iframe');
+
+test(function () {
+    withNewDocumentWithABrowsingContext(function (contentWindow, contentDocument) {
+        class MyCustomElement extends contentWindow.HTMLElement { }
+        contentDocument.defineElement('my-custom-element', MyCustomElement);
+
+        var instance = contentDocument.createElement('my-custom-element');
+        var container = contentDocument.createElement('div');
+        container.appendChild(instance);
+
+        var containerClone = container.cloneNode(true);
+        assert_true(containerClone instanceof contentWindow.HTMLDivElement);
+
+        var clone = containerClone.firstChild;
+        assert_not_equals(instance, clone);
+        assert_true(clone instanceof contentWindow.HTMLElement,
+            'A cloned custom element must be an instance of HTMLElement');
+        assert_true(clone instanceof MyCustomElement,
+            'A cloned custom element must be an instance of the custom element');
+    });
+}, 'Node.prototype.cloneNode(true) must be able to clone a descendent custom element');
+
+test(function () {
+    withNewDocumentWithABrowsingContext(function (contentWindow, contentDocument) {
+        var parentNodeInConstructor;
+        var previousSiblingInConstructor;
+        var nextSiblingInConstructor;
+        class MyCustomElement extends contentWindow.HTMLElement {
+            constructor() {
+                super();
+                parentNodeInConstructor = this.parentNode;
+                previousSiblingInConstructor = this.previousSibling;
+                nextSiblingInConstructor = this.nextSibling;
+            }
+        }
+        contentDocument.defineElement('my-custom-element', MyCustomElement);
+
+        var instance = contentDocument.createElement('my-custom-element');
+        var siblingBeforeInstance = contentDocument.createElement('b');
+        var siblingAfterInstance = contentDocument.createElement('a');
+        var container = contentDocument.createElement('div');
+        container.appendChild(siblingBeforeInstance);
+        container.appendChild(instance);
+        container.appendChild(siblingAfterInstance);
+
+        var containerClone = container.cloneNode(true);
+
+        assert_equals(parentNodeInConstructor, containerClone,
+            'An upgraded element must have its parentNode set before the custom element constructor is called');
+        assert_equals(previousSiblingInConstructor, containerClone.firstChild,
+            'An upgraded element must have its previousSibling set before the custom element constructor is called');
+        assert_equals(nextSiblingInConstructor, containerClone.lastChild,
+            'An upgraded element must have its nextSibling set before the custom element constructor is called');
+    });
+}, 'Node.prototype.cloneNode(true) must be able to clone a descendent custom element');
+
+test(function () {
+    withNewDocumentWithABrowsingContext(function (contentWindow, contentDocument) {
+        class MyCustomElement extends contentWindow.HTMLElement {
+            constructor(doNotCreateItself) {
+                super();
+                if (!doNotCreateItself)
+                    new MyCustomElement(true);
+            }
+        }
+        contentDocument.defineElement('my-custom-element', MyCustomElement);
+
+        var instance = contentDocument.createElement('my-custom-element');
+        assert_throws({'name': 'InvalidStateError'}, function () { instance.cloneNode(false); });
+    });
+}, '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 () {
+    withNewDocumentWithABrowsingContext(function (contentWindow, contentDocument) {
+        class MyCustomElement extends contentWindow.HTMLElement {
+            constructor(doNotCreateItself) {
+                if (!doNotCreateItself)
+                    new MyCustomElement(true);
+                super();
+            }
+        }
+        contentDocument.defineElement('my-custom-element', MyCustomElement);
+
+        var instance = contentDocument.createElement('my-custom-element');
+        assert_throws({'name': 'InvalidStateError'}, function () { instance.cloneNode(false); });
+    });
+}, '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 () {
+    withNewDocumentWithABrowsingContext(function (contentWindow, contentDocument) {
+        var cloning = false;
+        class MyCustomElement extends contentWindow.HTMLElement {
+            constructor() {
+                super();
+                if (cloning)
+                    return contentDocument.createElement('span');
+            }
+        }
+        contentDocument.defineElement('my-custom-element', MyCustomElement);
+
+        var instance = contentDocument.createElement('my-custom-element');
+        cloning = true;
+        assert_throws({'name': 'InvalidStateError'}, function () { instance.cloneNode(false); });
+    });
+}, 'Upgrading a custom element must throw InvalidStateError when the custom element\'s constructor returns another 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 (197633 => 197634)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2016-03-06 05:02:49 UTC (rev 197633)
+++ trunk/Source/WebCore/ChangeLog        2016-03-06 05:07:47 UTC (rev 197634)
</span><span class="lines">@@ -1,3 +1,52 @@
</span><ins>+2016-03-05  Ryosuke Niwa  &lt;rniwa@webkit.org&gt;
+
+        Add the support for upgrading custom elements in cloneNode
+        https://bugs.webkit.org/show_bug.cgi?id=155062
+
+        Reviewed by Antti Koivisto.
+
+        Implement https://w3c.github.io/webcomponents/spec/custom/#upgrading and steps 6 through 11 in
+        https://w3c.github.io/webcomponents/spec/custom/#htmlelement-constructor to support upgrading elements
+        created by Node.prototype.cloneNode.
+
+        Tests: fast/custom-elements/lifecycle-callback-timing.html
+               fast/custom-elements/upgrading/Node-cloneNode.html
+
+        * bindings/js/JSCustomElementInterface.cpp:
+        (WebCore::JSCustomElementInterface::upgradeElement): Added. Implements
+         https://w3c.github.io/webcomponents/spec/custom/#dfn-upgrade-a-custom-element
+        (WebCore::JSCustomElementInterface::didUpgradeLastElementInConstructionStack): Added. Implements step 10
+         &quot;Replace the last entry in definition's construction stacka with an already constructed marker.&quot;
+         in https://w3c.github.io/webcomponents/spec/custom/#dom-htmlelement-constructor
+        * bindings/js/JSCustomElementInterface.h:
+        (WebCore::JSCustomElementInterface::isUpgradingElement):
+        (WebCore::JSCustomElementInterface::lastElementInConstructionStack):
+        (WebCore::JSCustomElementInterface): Added m_constructionStack. This is the construction stack:
+         https://w3c.github.io/webcomponents/spec/custom/#dfn-element-definition-construction-stack
+        * bindings/js/JSDOMBinding.cpp:
+        (WebCore::throwInvalidStateError): Added.
+        * bindings/js/JSDOMBinding.h:
+        * bindings/js/JSHTMLElementCustom.cpp:
+        (WebCore::constructJSHTMLElement): Implement the upgrading case in:
+         https://w3c.github.io/webcomponents/spec/custom/#htmlelement-constructor
+        * dom/Document.cpp:
+        (WebCore::createFallbackHTMLElement): Added. Enqueues upgrades of custom elements (enqueueElementUpgrade
+         currently does nothing if there is no InvokesCustomElementLifecycleCallbacks; e.g. in other DOM APIs).
+         This function implements https://w3c.github.io/webcomponents/spec/custom/#dfn-element-upgrade-algorithm
+        (WebCore::Document::createElement):
+        * dom/LifecycleCallbackQueue.cpp:
+        (WebCore::LifecycleQueueItem::LifecycleQueueItem): Added a generic constructor.
+        (WebCore::LifecycleQueueItem::invoke): Call upgradeElement when m_type is Type::ElementUpgrade.
+        (WebCore::LifecycleCallbackQueue::enqueueElementUpgrade): Added.
+        * dom/LifecycleCallbackQueue.h:
+        * dom/Node.idl: Added InvokesCustomElementLifecycleCallbacks on cloneNode.
+        * dom/make_names.pl:
+        (printFactoryCppFile): Added a variant of createKnownElement which takes QualifiedName. Also directly call
+         find(HTML|SVG|MathML)ElementConstructorFunction in createElement that takes AtomicString to avoid an extra
+         function call.
+        (printFactoryHeaderFile): Added a function declaration for createKnownElement that takes QualifiedName and
+         outdented class and function declarations to match the modern code style guideline.
+
</ins><span class="cx"> 2016-03-05  Tim Horton  &lt;timothy_horton@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Create a DOMHTMLVideoElement when wrapping &lt;video&gt; elements
</span></span></pre></div>
<a id="trunkSourceWebCorebindingsjsJSCustomElementInterfacecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/bindings/js/JSCustomElementInterface.cpp (197633 => 197634)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/bindings/js/JSCustomElementInterface.cpp        2016-03-06 05:02:49 UTC (rev 197633)
+++ trunk/Source/WebCore/bindings/js/JSCustomElementInterface.cpp        2016-03-06 05:07:47 UTC (rev 197634)
</span><span class="lines">@@ -102,6 +102,54 @@
</span><span class="cx">     return wrappedElement;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void JSCustomElementInterface::upgradeElement(Element&amp; element)
+{
+    ASSERT(element.isCustomElement());
+    if (!canInvokeCallback())
+        return;
+
+    Ref&lt;JSCustomElementInterface&gt; protect(*this);
+    JSLockHolder lock(m_isolatedWorld-&gt;vm());
+
+    if (!m_constructor)
+        return;
+
+    ScriptExecutionContext* context = scriptExecutionContext();
+    if (!context)
+        return;
+    ASSERT(context-&gt;isDocument());
+    JSDOMGlobalObject* globalObject = toJSDOMGlobalObject(context, *m_isolatedWorld);
+    ExecState* state = globalObject-&gt;globalExec();
+    if (state-&gt;hadException())
+        return;
+
+    ConstructData constructData;
+    ConstructType constructType = m_constructor-&gt;methodTable()-&gt;getConstructData(m_constructor.get(), constructData);
+    if (constructType == ConstructType::None) {
+        ASSERT_NOT_REACHED();
+        return;
+    }
+
+    m_constructionStack.append(&amp;element);
+
+    MarkedArgumentBuffer args;
+    InspectorInstrumentationCookie cookie = JSMainThreadExecState::instrumentFunctionConstruct(context, constructType, constructData);
+    JSValue returnedElement = construct(state, m_constructor.get(), constructType, constructData, args);
+    InspectorInstrumentation::didCallFunction(cookie, context);
+
+    m_constructionStack.removeLast();
+
+    if (state-&gt;hadException())
+        return;
+
+    Element* wrappedElement = JSElement::toWrapped(returnedElement);
+    if (!wrappedElement || wrappedElement != &amp;element) {
+        throwInvalidStateError(*state, &quot;Custom element constructor failed to upgrade an element&quot;);
+        return;
+    }
+    ASSERT(wrappedElement-&gt;isCustomElement());
+}
+
</ins><span class="cx"> void JSCustomElementInterface::attributeChanged(Element&amp; element, const QualifiedName&amp; attributeName, const AtomicString&amp; oldValue, const AtomicString&amp; newValue)
</span><span class="cx"> {
</span><span class="cx">     if (!canInvokeCallback())
</span><span class="lines">@@ -145,6 +193,11 @@
</span><span class="cx">     if (exception)
</span><span class="cx">         reportException(state, exception);
</span><span class="cx"> }
</span><ins>+    
+void JSCustomElementInterface::didUpgradeLastElementInConstructionStack()
+{
+    m_constructionStack.last() = nullptr;
+}
</ins><span class="cx"> 
</span><span class="cx"> } // namespace WebCore
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCorebindingsjsJSCustomElementInterfaceh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/bindings/js/JSCustomElementInterface.h (197633 => 197634)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/bindings/js/JSCustomElementInterface.h        2016-03-06 05:02:49 UTC (rev 197633)
+++ trunk/Source/WebCore/bindings/js/JSCustomElementInterface.h        2016-03-06 05:07:47 UTC (rev 197634)
</span><span class="lines">@@ -63,6 +63,8 @@
</span><span class="cx">     enum class ShouldClearException { Clear, DoNotClear };
</span><span class="cx">     RefPtr&lt;Element&gt; constructElement(const AtomicString&amp;, ShouldClearException);
</span><span class="cx"> 
</span><ins>+    void upgradeElement(Element&amp;);
+
</ins><span class="cx">     void attributeChanged(Element&amp;, const QualifiedName&amp;, const AtomicString&amp; oldValue, const AtomicString&amp; newValue);
</span><span class="cx"> 
</span><span class="cx">     ScriptExecutionContext* scriptExecutionContext() const { return ContextDestructionObserver::scriptExecutionContext(); }
</span><span class="lines">@@ -70,6 +72,10 @@
</span><span class="cx"> 
</span><span class="cx">     const QualifiedName&amp; name() const { return m_name; }
</span><span class="cx"> 
</span><ins>+    bool isUpgradingElement() const { return !m_constructionStack.isEmpty(); }
+    Element* lastElementInConstructionStack() const { return m_constructionStack.last().get(); }
+    void didUpgradeLastElementInConstructionStack();
+
</ins><span class="cx">     virtual ~JSCustomElementInterface();
</span><span class="cx"> 
</span><span class="cx"> private:
</span><span class="lines">@@ -78,6 +84,7 @@
</span><span class="cx">     QualifiedName m_name;
</span><span class="cx">     mutable JSC::Weak&lt;JSC::JSObject&gt; m_constructor;
</span><span class="cx">     RefPtr&lt;DOMWrapperWorld&gt; m_isolatedWorld;
</span><ins>+    Vector&lt;RefPtr&lt;Element&gt;, 1&gt; m_constructionStack;
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> } // namespace WebCore
</span></span></pre></div>
<a id="trunkSourceWebCorebindingsjsJSDOMBindingcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/bindings/js/JSDOMBinding.cpp (197633 => 197634)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/bindings/js/JSDOMBinding.cpp        2016-03-06 05:02:49 UTC (rev 197633)
+++ trunk/Source/WebCore/bindings/js/JSDOMBinding.cpp        2016-03-06 05:07:47 UTC (rev 197634)
</span><span class="lines">@@ -642,6 +642,13 @@
</span><span class="cx">     state.vm().throwException(&amp;state, createDOMException(&amp;state, NOT_SUPPORTED_ERR, &amp;messageString));
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void throwInvalidStateError(JSC::ExecState&amp; state, const char* message)
+{
+    ASSERT(!state.hadException());
+    String messageString(message);
+    state.vm().throwException(&amp;state, createDOMException(&amp;state, INVALID_STATE_ERR, &amp;messageString));
+}
+
</ins><span class="cx"> JSC::EncodedJSValue throwArgumentMustBeEnumError(JSC::ExecState&amp; state, unsigned argumentIndex, const char* argumentName, const char* functionInterfaceName, const char* functionName, const char* expectedValues)
</span><span class="cx"> {
</span><span class="cx">     StringBuilder builder;
</span></span></pre></div>
<a id="trunkSourceWebCorebindingsjsJSDOMBindingh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/bindings/js/JSDOMBinding.h (197633 => 197634)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/bindings/js/JSDOMBinding.h        2016-03-06 05:02:49 UTC (rev 197633)
+++ trunk/Source/WebCore/bindings/js/JSDOMBinding.h        2016-03-06 05:07:47 UTC (rev 197634)
</span><span class="lines">@@ -85,6 +85,7 @@
</span><span class="cx"> WEBCORE_EXPORT void reportDeprecatedSetterError(JSC::ExecState&amp;, const char* interfaceName, const char* attributeName);
</span><span class="cx"> 
</span><span class="cx"> void throwNotSupportedError(JSC::ExecState&amp;, const char* message);
</span><ins>+void throwInvalidStateError(JSC::ExecState&amp;, const char* message);
</ins><span class="cx"> void throwArrayElementTypeError(JSC::ExecState&amp;);
</span><span class="cx"> void throwAttributeTypeError(JSC::ExecState&amp;, const char* interfaceName, const char* attributeName, const char* expectedType);
</span><span class="cx"> WEBCORE_EXPORT void throwSequenceTypeError(JSC::ExecState&amp;);
</span></span></pre></div>
<a id="trunkSourceWebCorebindingsjsJSHTMLElementCustomcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/bindings/js/JSHTMLElementCustom.cpp (197633 => 197634)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/bindings/js/JSHTMLElementCustom.cpp        2016-03-06 05:02:49 UTC (rev 197633)
+++ trunk/Source/WebCore/bindings/js/JSHTMLElementCustom.cpp        2016-03-06 05:07:47 UTC (rev 197634)
</span><span class="lines">@@ -29,6 +29,7 @@
</span><span class="cx"> #include &quot;CustomElementDefinitions.h&quot;
</span><span class="cx"> #include &quot;Document.h&quot;
</span><span class="cx"> #include &quot;HTMLFormElement.h&quot;
</span><ins>+#include &quot;JSNodeCustom.h&quot;
</ins><span class="cx"> #include &lt;runtime/InternalFunction.h&gt;
</span><span class="cx"> #include &lt;runtime/JSWithScope.h&gt;
</span><span class="cx"> 
</span><span class="lines">@@ -57,16 +58,40 @@
</span><span class="cx">     if (!interface)
</span><span class="cx">         return throwVMTypeError(state, &quot;new.target does not define a custom element&quot;);
</span><span class="cx"> 
</span><del>-    auto* globalObject = jsConstructor-&gt;globalObject();
-    Structure* baseStructure = getDOMStructure&lt;JSHTMLElement&gt;(vm, *globalObject);
-    auto* newElementStructure = InternalFunction::createSubclassStructure(state, newTargetValue, baseStructure);
-    if (UNLIKELY(state-&gt;hadException()))
</del><ins>+    if (!interface-&gt;isUpgradingElement()) {
+        auto* globalObject = jsConstructor-&gt;globalObject();
+        Structure* baseStructure = getDOMStructure&lt;JSHTMLElement&gt;(vm, *globalObject);
+        auto* newElementStructure = InternalFunction::createSubclassStructure(state, newTargetValue, baseStructure);
+        if (UNLIKELY(state-&gt;hadException()))
+            return JSValue::encode(jsUndefined());
+
+        Ref&lt;HTMLElement&gt; element = HTMLElement::create(interface-&gt;name(), document);
+        auto* jsElement = JSHTMLElement::create(newElementStructure, globalObject, element.get());
+        cacheWrapper(globalObject-&gt;world(), element.ptr(), jsElement);
+        return JSValue::encode(jsElement);
+    }
+
+    Element* elementToUpgrade = interface-&gt;lastElementInConstructionStack();
+    if (!elementToUpgrade) {
+        throwInvalidStateError(*state, &quot;Cannot instantiate a custom element inside its own constrcutor during upgrades&quot;);
</ins><span class="cx">         return JSValue::encode(jsUndefined());
</span><ins>+    }
</ins><span class="cx"> 
</span><del>-    Ref&lt;HTMLElement&gt; element = HTMLElement::create(interface-&gt;name(), document);
-    auto* jsElement = JSHTMLElement::create(newElementStructure, globalObject, element.get());
-    cacheWrapper(globalObject-&gt;world(), element.ptr(), jsElement);
-    return JSValue::encode(jsElement);
</del><ins>+    JSValue elementWrapperValue = toJS(state, jsConstructor-&gt;globalObject(), elementToUpgrade);
+    ASSERT(elementWrapperValue.isObject());
+
+    JSValue newPrototype = newTarget-&gt;get(state, vm.propertyNames-&gt;prototype);
+    if (state-&gt;hadException())
+        return JSValue::encode(jsUndefined());
+
+    JSObject* elementWrapperObject = asObject(elementWrapperValue);
+    JSObject::setPrototype(elementWrapperObject, state, newPrototype, true /* shouldThrowIfCantSet */);
+    if (state-&gt;hadException())
+        return JSValue::encode(jsUndefined());
+
+    interface-&gt;didUpgradeLastElementInConstructionStack();
+
+    return JSValue::encode(elementWrapperValue);
</ins><span class="cx"> }
</span><span class="cx"> #endif
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCoredomDocumentcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/dom/Document.cpp (197633 => 197634)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/dom/Document.cpp        2016-03-06 05:02:49 UTC (rev 197633)
+++ trunk/Source/WebCore/dom/Document.cpp        2016-03-06 05:07:47 UTC (rev 197634)
</span><span class="lines">@@ -103,6 +103,7 @@
</span><span class="cx"> #include &quot;JSModuleLoader.h&quot;
</span><span class="cx"> #include &quot;KeyboardEvent.h&quot;
</span><span class="cx"> #include &quot;Language.h&quot;
</span><ins>+#include &quot;LifecycleCallbackQueue.h&quot;
</ins><span class="cx"> #include &quot;LoaderStrategy.h&quot;
</span><span class="cx"> #include &quot;Logging.h&quot;
</span><span class="cx"> #include &quot;MainFrame.h&quot;
</span><span class="lines">@@ -1072,15 +1073,33 @@
</span><span class="cx">     return hasValidNamespaceForElements(qName);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+static Ref&lt;HTMLElement&gt; createFallbackHTMLElement(Document&amp; document, const QualifiedName&amp; name)
+{
+#if ENABLE(CUSTOM_ELEMENTS)
+    auto* definitions = document.customElementDefinitions();
+    if (UNLIKELY(definitions)) {
+        if (auto* interface = definitions-&gt;findInterface(name)) {
+            Ref&lt;HTMLElement&gt; element = HTMLElement::create(name, document);
+            element-&gt;setIsCustomElement(); // Pre-upgrade element is still considered a custom element.
+            LifecycleCallbackQueue::enqueueElementUpgrade(element.get(), *interface);
+            return element;
+        }
+    }
+#endif
+    return HTMLUnknownElement::create(name, document);
+}
+
</ins><span class="cx"> // FIXME: This should really be in a possible ElementFactory class.
</span><span class="cx"> Ref&lt;Element&gt; Document::createElement(const QualifiedName&amp; name, bool createdByParser)
</span><span class="cx"> {
</span><span class="cx">     RefPtr&lt;Element&gt; element;
</span><span class="cx"> 
</span><span class="cx">     // FIXME: Use registered namespaces and look up in a hash to find the right factory.
</span><del>-    if (name.namespaceURI() == xhtmlNamespaceURI)
-        element = HTMLElementFactory::createElement(name, *this, nullptr, createdByParser);
-    else if (name.namespaceURI() == SVGNames::svgNamespaceURI)
</del><ins>+    if (name.namespaceURI() == xhtmlNamespaceURI) {
+        element = HTMLElementFactory::createKnownElement(name, *this, nullptr, createdByParser);
+        if (UNLIKELY(!element))
+            element = createFallbackHTMLElement(*this, name);
+    } else if (name.namespaceURI() == SVGNames::svgNamespaceURI)
</ins><span class="cx">         element = SVGElementFactory::createElement(name, *this, createdByParser);
</span><span class="cx"> #if ENABLE(MATHML)
</span><span class="cx">     else if (name.namespaceURI() == MathMLNames::mathmlNamespaceURI)
</span></span></pre></div>
<a id="trunkSourceWebCoredomLifecycleCallbackQueuecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/dom/LifecycleCallbackQueue.cpp (197633 => 197634)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/dom/LifecycleCallbackQueue.cpp        2016-03-06 05:02:49 UTC (rev 197633)
+++ trunk/Source/WebCore/dom/LifecycleCallbackQueue.cpp        2016-03-06 05:07:47 UTC (rev 197634)
</span><span class="lines">@@ -33,6 +33,7 @@
</span><span class="cx"> #include &quot;JSCustomElementInterface.h&quot;
</span><span class="cx"> #include &quot;JSDOMBinding.h&quot;
</span><span class="cx"> #include &lt;heap/Heap.h&gt;
</span><ins>+#include &lt;wtf/Optional.h&gt;
</ins><span class="cx"> #include &lt;wtf/Ref.h&gt;
</span><span class="cx"> 
</span><span class="cx"> namespace WebCore {
</span><span class="lines">@@ -40,9 +41,16 @@
</span><span class="cx"> class LifecycleQueueItem {
</span><span class="cx"> public:
</span><span class="cx">     enum class Type {
</span><ins>+        ElementUpgrade,
</ins><span class="cx">         AttributeChanged,
</span><span class="cx">     };
</span><span class="cx"> 
</span><ins>+    LifecycleQueueItem(Type type, Element&amp; element, JSCustomElementInterface&amp; interface)
+        : m_type(type)
+        , m_element(element)
+        , m_interface(interface)
+    { }
+
</ins><span class="cx">     LifecycleQueueItem(Element&amp; element, JSCustomElementInterface&amp; interface, const QualifiedName&amp; attributeName, const AtomicString&amp; oldValue, const AtomicString&amp; newValue)
</span><span class="cx">         : m_type(Type::AttributeChanged)
</span><span class="cx">         , m_element(element)
</span><span class="lines">@@ -54,14 +62,22 @@
</span><span class="cx"> 
</span><span class="cx">     void invoke()
</span><span class="cx">     {
</span><del>-        m_interface-&gt;attributeChanged(m_element.get(), m_attributeName, m_oldValue, m_newValue);
</del><ins>+        switch (m_type) {
+        case Type::ElementUpgrade:
+            m_interface-&gt;upgradeElement(m_element.get());
+            break;
+        case Type::AttributeChanged:
+            ASSERT(m_attributeName);
+            m_interface-&gt;attributeChanged(m_element.get(), m_attributeName.value(), m_oldValue, m_newValue);
+            break;
+        }
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx"> private:
</span><span class="cx">     Type m_type;
</span><span class="cx">     Ref&lt;Element&gt; m_element;
</span><span class="cx">     Ref&lt;JSCustomElementInterface&gt; m_interface;
</span><del>-    QualifiedName m_attributeName;
</del><ins>+    Optional&lt;QualifiedName&gt; m_attributeName;
</ins><span class="cx">     AtomicString m_oldValue;
</span><span class="cx">     AtomicString m_newValue;
</span><span class="cx"> };
</span><span class="lines">@@ -74,6 +90,12 @@
</span><span class="cx">     ASSERT(m_items.isEmpty());
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void LifecycleCallbackQueue::enqueueElementUpgrade(Element&amp; element, JSCustomElementInterface&amp; interface)
+{
+    if (auto* queue = CustomElementLifecycleProcessingStack::ensureCurrentQueue())
+        queue-&gt;m_items.append(LifecycleQueueItem(LifecycleQueueItem::Type::ElementUpgrade, element, interface));
+}
+
</ins><span class="cx"> void LifecycleCallbackQueue::enqueueAttributeChangedCallback(Element&amp; element, JSCustomElementInterface&amp; interface,
</span><span class="cx">     const QualifiedName&amp; attributeName, const AtomicString&amp; oldValue, const AtomicString&amp; newValue)
</span><span class="cx"> {
</span></span></pre></div>
<a id="trunkSourceWebCoredomLifecycleCallbackQueueh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/dom/LifecycleCallbackQueue.h (197633 => 197634)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/dom/LifecycleCallbackQueue.h        2016-03-06 05:02:49 UTC (rev 197633)
+++ trunk/Source/WebCore/dom/LifecycleCallbackQueue.h        2016-03-06 05:07:47 UTC (rev 197634)
</span><span class="lines">@@ -46,6 +46,8 @@
</span><span class="cx">     LifecycleCallbackQueue();
</span><span class="cx">     ~LifecycleCallbackQueue();
</span><span class="cx"> 
</span><ins>+    static void enqueueElementUpgrade(Element&amp;, JSCustomElementInterface&amp;);
+
</ins><span class="cx">     static void enqueueAttributeChangedCallback(Element&amp;, JSCustomElementInterface&amp;,
</span><span class="cx">         const QualifiedName&amp;, const AtomicString&amp; oldValue, const AtomicString&amp; newValue);
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCoredomNodeidl"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/dom/Node.idl (197633 => 197634)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/dom/Node.idl        2016-03-06 05:02:49 UTC (rev 197633)
+++ trunk/Source/WebCore/dom/Node.idl        2016-03-06 05:07:47 UTC (rev 197634)
</span><span class="lines">@@ -70,7 +70,10 @@
</span><span class="cx">     [Custom, RaisesException] Node appendChild([CustomReturn] Node newChild);
</span><span class="cx"> 
</span><span class="cx">     boolean            hasChildNodes();
</span><del>-    [NewObject, RaisesException, ImplementedAs=cloneNodeForBindings] Node cloneNode([Default=Undefined] optional boolean deep);
</del><ins>+
+    [NewObject, RaisesException, ImplementedAs=cloneNodeForBindings, InvokesCustomElementLifecycleCallbacks]
+    Node cloneNode([Default=Undefined] optional boolean deep);
+
</ins><span class="cx">     void               normalize();
</span><span class="cx"> 
</span><span class="cx">     // Introduced in DOM Level 2:
</span></span></pre></div>
<a id="trunkSourceWebCoredommake_namespl"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/dom/make_names.pl (197633 => 197634)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/dom/make_names.pl        2016-03-06 05:02:49 UTC (rev 197633)
+++ trunk/Source/WebCore/dom/make_names.pl        2016-03-06 05:07:47 UTC (rev 197634)
</span><span class="lines">@@ -1047,14 +1047,25 @@
</span><span class="cx">     return nullptr;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-Ref&lt;$parameters{namespace}Element&gt; $parameters{namespace}ElementFactory::createElement(const AtomicString&amp; name, Document&amp; document$formElementArgumentForDefinition, bool createdByParser)
</del><ins>+RefPtr&lt;$parameters{namespace}Element&gt; $parameters{namespace}ElementFactory::createKnownElement(const QualifiedName&amp; name, Document&amp; document$formElementArgumentForDefinition, bool createdByParser)
</ins><span class="cx"> {
</span><del>-    RefPtr&lt;$parameters{namespace}Element&gt; element = $parameters{namespace}ElementFactory::createKnownElement($argumentList);
-    if (LIKELY(element))
-        return element.releaseNonNull();
-    return $parameters{fallbackInterfaceName}::create(QualifiedName(nullAtom, name, ${lowercaseNamespacePrefix}NamespaceURI), document);
</del><ins>+    const ConstructorFunctionMapEntry&amp; entry = find$parameters{namespace}ElementConstructorFunction(name.localName());
+    if (LIKELY(entry.function))
+        return entry.function($argumentList);
+    return nullptr;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><ins>+Ref&lt;$parameters{namespace}Element&gt; $parameters{namespace}ElementFactory::createElement(const AtomicString&amp; localName, Document&amp; document$formElementArgumentForDefinition, bool createdByParser)
+{
+    const ConstructorFunctionMapEntry&amp; entry = find$parameters{namespace}ElementConstructorFunction(localName);
+    if (LIKELY(entry.function)) {
+        ASSERT(entry.qualifiedName);
+        const auto&amp; name = *entry.qualifiedName;
+        return entry.function($argumentList);
+    }
+    return $parameters{fallbackInterfaceName}::create(QualifiedName(nullAtom, localName, ${lowercaseNamespacePrefix}NamespaceURI), document);
+}
+
</ins><span class="cx"> Ref&lt;$parameters{namespace}Element&gt; $parameters{namespace}ElementFactory::createElement(const QualifiedName&amp; name, Document&amp; document$formElementArgumentForDefinition, bool createdByParser)
</span><span class="cx"> {
</span><span class="cx">     const ConstructorFunctionMapEntry&amp; entry = find$parameters{namespace}ElementConstructorFunction(name.localName());
</span><span class="lines">@@ -1089,29 +1100,36 @@
</span><span class="cx"> 
</span><span class="cx"> namespace WebCore {
</span><span class="cx"> 
</span><del>-    class Document;
-    class HTMLFormElement;
-    class QualifiedName;
</del><ins>+class Document;
+class HTMLFormElement;
+class QualifiedName;
</ins><span class="cx"> 
</span><del>-    class $parameters{namespace}Element;
</del><ins>+class $parameters{namespace}Element;
</ins><span class="cx"> 
</span><del>-    class $parameters{namespace}ElementFactory {
-    public:
</del><ins>+class $parameters{namespace}ElementFactory {
+public:
</ins><span class="cx"> END
</span><span class="cx"> ;
</span><span class="cx"> 
</span><del>-print F &quot;        static RefPtr&lt;$parameters{namespace}Element&gt; createKnownElement(const AtomicString&amp; localName, Document&amp;&quot;;
</del><ins>+print F &quot;static RefPtr&lt;$parameters{namespace}Element&gt; createKnownElement(const AtomicString&amp;, Document&amp;&quot;;
</ins><span class="cx"> print F &quot;, HTMLFormElement* = nullptr&quot; if $parameters{namespace} eq &quot;HTML&quot;;
</span><del>-print F &quot;, bool createdByParser = false);\n\n&quot;;
-print F &quot;        static Ref&lt;$parameters{namespace}Element&gt; createElement(const AtomicString&amp; localName, Document&amp;&quot;;
</del><ins>+print F &quot;, bool createdByParser = false);\n&quot;;
+
+print F &quot;static RefPtr&lt;$parameters{namespace}Element&gt; createKnownElement(const QualifiedName&amp;, Document&amp;&quot;;
</ins><span class="cx"> print F &quot;, HTMLFormElement* = nullptr&quot; if $parameters{namespace} eq &quot;HTML&quot;;
</span><span class="cx"> print F &quot;, bool createdByParser = false);\n&quot;;
</span><del>-print F &quot;        static Ref&lt;$parameters{namespace}Element&gt; createElement(const QualifiedName&amp; localName, Document&amp;&quot;;
</del><ins>+
+print F &quot;static Ref&lt;$parameters{namespace}Element&gt; createElement(const AtomicString&amp;, Document&amp;&quot;;
</ins><span class="cx"> print F &quot;, HTMLFormElement* = nullptr&quot; if $parameters{namespace} eq &quot;HTML&quot;;
</span><span class="cx"> print F &quot;, bool createdByParser = false);\n&quot;;
</span><span class="cx"> 
</span><ins>+print F &quot;static Ref&lt;$parameters{namespace}Element&gt; createElement(const QualifiedName&amp;, Document&amp;&quot;;
+print F &quot;, HTMLFormElement* = nullptr&quot; if $parameters{namespace} eq &quot;HTML&quot;;
+print F &quot;, bool createdByParser = false);\n&quot;;
+
</ins><span class="cx"> printf F&lt;&lt;END
</span><del>-    };
</del><ins>+};
+
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> #endif // $parameters{namespace}ElementFactory_h
</span></span></pre>
</div>
</div>

</body>
</html>