<!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
"Replace the last entry in definition's construction stacka with an already constructed marker."
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 <rniwa@webkit.org>
+
+ 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 <sam@webkit.org>
</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"> </script>
</span><span class="cx"> </body>
</span><span class="cx"> </html>
</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>+<!DOCTYPE html>
+<html>
+<head>
+<title>Custom Elements: Extensions to Document interface</title>
+<meta name="author" title="Ryosuke Niwa" href="mailto:rniwa@webkit.org">
+<meta name="assert" content="Node.prototype.cloneNode should upgrade a custom element">
+<link rel="help" href="https://w3c.github.io/webcomponents/spec/custom/#upgrading">
+<script src="../../../resources/testharness.js"></script>
+<script src="../../../resources/testharnessreport.js"></script>
+<link rel='stylesheet' href='../../../resources/testharness.css'>
+</head>
+<body>
+<div id="log"></div>
+<script>
+
+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');
+
+</script>
+</body>
+</html>
</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 <rniwa@webkit.org>
+
+ 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
+ "Replace the last entry in definition's construction stacka with an already constructed marker."
+ 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 <timothy_horton@apple.com>
</span><span class="cx">
</span><span class="cx"> Create a DOMHTMLVideoElement when wrapping <video> 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& element)
+{
+ ASSERT(element.isCustomElement());
+ if (!canInvokeCallback())
+ return;
+
+ Ref<JSCustomElementInterface> protect(*this);
+ JSLockHolder lock(m_isolatedWorld->vm());
+
+ if (!m_constructor)
+ return;
+
+ ScriptExecutionContext* context = scriptExecutionContext();
+ if (!context)
+ return;
+ ASSERT(context->isDocument());
+ JSDOMGlobalObject* globalObject = toJSDOMGlobalObject(context, *m_isolatedWorld);
+ ExecState* state = globalObject->globalExec();
+ if (state->hadException())
+ return;
+
+ ConstructData constructData;
+ ConstructType constructType = m_constructor->methodTable()->getConstructData(m_constructor.get(), constructData);
+ if (constructType == ConstructType::None) {
+ ASSERT_NOT_REACHED();
+ return;
+ }
+
+ m_constructionStack.append(&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->hadException())
+ return;
+
+ Element* wrappedElement = JSElement::toWrapped(returnedElement);
+ if (!wrappedElement || wrappedElement != &element) {
+ throwInvalidStateError(*state, "Custom element constructor failed to upgrade an element");
+ return;
+ }
+ ASSERT(wrappedElement->isCustomElement());
+}
+
</ins><span class="cx"> void JSCustomElementInterface::attributeChanged(Element& element, const QualifiedName& attributeName, const AtomicString& oldValue, const AtomicString& 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<Element> constructElement(const AtomicString&, ShouldClearException);
</span><span class="cx">
</span><ins>+ void upgradeElement(Element&);
+
</ins><span class="cx"> void attributeChanged(Element&, const QualifiedName&, const AtomicString& oldValue, const AtomicString& 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& 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<JSC::JSObject> m_constructor;
</span><span class="cx"> RefPtr<DOMWrapperWorld> m_isolatedWorld;
</span><ins>+ Vector<RefPtr<Element>, 1> 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(&state, createDOMException(&state, NOT_SUPPORTED_ERR, &messageString));
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+void throwInvalidStateError(JSC::ExecState& state, const char* message)
+{
+ ASSERT(!state.hadException());
+ String messageString(message);
+ state.vm().throwException(&state, createDOMException(&state, INVALID_STATE_ERR, &messageString));
+}
+
</ins><span class="cx"> JSC::EncodedJSValue throwArgumentMustBeEnumError(JSC::ExecState& 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&, const char* interfaceName, const char* attributeName);
</span><span class="cx">
</span><span class="cx"> void throwNotSupportedError(JSC::ExecState&, const char* message);
</span><ins>+void throwInvalidStateError(JSC::ExecState&, const char* message);
</ins><span class="cx"> void throwArrayElementTypeError(JSC::ExecState&);
</span><span class="cx"> void throwAttributeTypeError(JSC::ExecState&, const char* interfaceName, const char* attributeName, const char* expectedType);
</span><span class="cx"> WEBCORE_EXPORT void throwSequenceTypeError(JSC::ExecState&);
</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 "CustomElementDefinitions.h"
</span><span class="cx"> #include "Document.h"
</span><span class="cx"> #include "HTMLFormElement.h"
</span><ins>+#include "JSNodeCustom.h"
</ins><span class="cx"> #include <runtime/InternalFunction.h>
</span><span class="cx"> #include <runtime/JSWithScope.h>
</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, "new.target does not define a custom element");
</span><span class="cx">
</span><del>- auto* globalObject = jsConstructor->globalObject();
- Structure* baseStructure = getDOMStructure<JSHTMLElement>(vm, *globalObject);
- auto* newElementStructure = InternalFunction::createSubclassStructure(state, newTargetValue, baseStructure);
- if (UNLIKELY(state->hadException()))
</del><ins>+ if (!interface->isUpgradingElement()) {
+ auto* globalObject = jsConstructor->globalObject();
+ Structure* baseStructure = getDOMStructure<JSHTMLElement>(vm, *globalObject);
+ auto* newElementStructure = InternalFunction::createSubclassStructure(state, newTargetValue, baseStructure);
+ if (UNLIKELY(state->hadException()))
+ return JSValue::encode(jsUndefined());
+
+ Ref<HTMLElement> element = HTMLElement::create(interface->name(), document);
+ auto* jsElement = JSHTMLElement::create(newElementStructure, globalObject, element.get());
+ cacheWrapper(globalObject->world(), element.ptr(), jsElement);
+ return JSValue::encode(jsElement);
+ }
+
+ Element* elementToUpgrade = interface->lastElementInConstructionStack();
+ if (!elementToUpgrade) {
+ throwInvalidStateError(*state, "Cannot instantiate a custom element inside its own constrcutor during upgrades");
</ins><span class="cx"> return JSValue::encode(jsUndefined());
</span><ins>+ }
</ins><span class="cx">
</span><del>- Ref<HTMLElement> element = HTMLElement::create(interface->name(), document);
- auto* jsElement = JSHTMLElement::create(newElementStructure, globalObject, element.get());
- cacheWrapper(globalObject->world(), element.ptr(), jsElement);
- return JSValue::encode(jsElement);
</del><ins>+ JSValue elementWrapperValue = toJS(state, jsConstructor->globalObject(), elementToUpgrade);
+ ASSERT(elementWrapperValue.isObject());
+
+ JSValue newPrototype = newTarget->get(state, vm.propertyNames->prototype);
+ if (state->hadException())
+ return JSValue::encode(jsUndefined());
+
+ JSObject* elementWrapperObject = asObject(elementWrapperValue);
+ JSObject::setPrototype(elementWrapperObject, state, newPrototype, true /* shouldThrowIfCantSet */);
+ if (state->hadException())
+ return JSValue::encode(jsUndefined());
+
+ interface->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 "JSModuleLoader.h"
</span><span class="cx"> #include "KeyboardEvent.h"
</span><span class="cx"> #include "Language.h"
</span><ins>+#include "LifecycleCallbackQueue.h"
</ins><span class="cx"> #include "LoaderStrategy.h"
</span><span class="cx"> #include "Logging.h"
</span><span class="cx"> #include "MainFrame.h"
</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<HTMLElement> createFallbackHTMLElement(Document& document, const QualifiedName& name)
+{
+#if ENABLE(CUSTOM_ELEMENTS)
+ auto* definitions = document.customElementDefinitions();
+ if (UNLIKELY(definitions)) {
+ if (auto* interface = definitions->findInterface(name)) {
+ Ref<HTMLElement> element = HTMLElement::create(name, document);
+ element->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<Element> Document::createElement(const QualifiedName& name, bool createdByParser)
</span><span class="cx"> {
</span><span class="cx"> RefPtr<Element> 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 "JSCustomElementInterface.h"
</span><span class="cx"> #include "JSDOMBinding.h"
</span><span class="cx"> #include <heap/Heap.h>
</span><ins>+#include <wtf/Optional.h>
</ins><span class="cx"> #include <wtf/Ref.h>
</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& element, JSCustomElementInterface& interface)
+ : m_type(type)
+ , m_element(element)
+ , m_interface(interface)
+ { }
+
</ins><span class="cx"> LifecycleQueueItem(Element& element, JSCustomElementInterface& interface, const QualifiedName& attributeName, const AtomicString& oldValue, const AtomicString& 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->attributeChanged(m_element.get(), m_attributeName, m_oldValue, m_newValue);
</del><ins>+ switch (m_type) {
+ case Type::ElementUpgrade:
+ m_interface->upgradeElement(m_element.get());
+ break;
+ case Type::AttributeChanged:
+ ASSERT(m_attributeName);
+ m_interface->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<Element> m_element;
</span><span class="cx"> Ref<JSCustomElementInterface> m_interface;
</span><del>- QualifiedName m_attributeName;
</del><ins>+ Optional<QualifiedName> 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& element, JSCustomElementInterface& interface)
+{
+ if (auto* queue = CustomElementLifecycleProcessingStack::ensureCurrentQueue())
+ queue->m_items.append(LifecycleQueueItem(LifecycleQueueItem::Type::ElementUpgrade, element, interface));
+}
+
</ins><span class="cx"> void LifecycleCallbackQueue::enqueueAttributeChangedCallback(Element& element, JSCustomElementInterface& interface,
</span><span class="cx"> const QualifiedName& attributeName, const AtomicString& oldValue, const AtomicString& 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&, JSCustomElementInterface&);
+
</ins><span class="cx"> static void enqueueAttributeChangedCallback(Element&, JSCustomElementInterface&,
</span><span class="cx"> const QualifiedName&, const AtomicString& oldValue, const AtomicString& 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<$parameters{namespace}Element> $parameters{namespace}ElementFactory::createElement(const AtomicString& name, Document& document$formElementArgumentForDefinition, bool createdByParser)
</del><ins>+RefPtr<$parameters{namespace}Element> $parameters{namespace}ElementFactory::createKnownElement(const QualifiedName& name, Document& document$formElementArgumentForDefinition, bool createdByParser)
</ins><span class="cx"> {
</span><del>- RefPtr<$parameters{namespace}Element> 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& 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<$parameters{namespace}Element> $parameters{namespace}ElementFactory::createElement(const AtomicString& localName, Document& document$formElementArgumentForDefinition, bool createdByParser)
+{
+ const ConstructorFunctionMapEntry& entry = find$parameters{namespace}ElementConstructorFunction(localName);
+ if (LIKELY(entry.function)) {
+ ASSERT(entry.qualifiedName);
+ const auto& name = *entry.qualifiedName;
+ return entry.function($argumentList);
+ }
+ return $parameters{fallbackInterfaceName}::create(QualifiedName(nullAtom, localName, ${lowercaseNamespacePrefix}NamespaceURI), document);
+}
+
</ins><span class="cx"> Ref<$parameters{namespace}Element> $parameters{namespace}ElementFactory::createElement(const QualifiedName& name, Document& document$formElementArgumentForDefinition, bool createdByParser)
</span><span class="cx"> {
</span><span class="cx"> const ConstructorFunctionMapEntry& 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 " static RefPtr<$parameters{namespace}Element> createKnownElement(const AtomicString& localName, Document&";
</del><ins>+print F "static RefPtr<$parameters{namespace}Element> createKnownElement(const AtomicString&, Document&";
</ins><span class="cx"> print F ", HTMLFormElement* = nullptr" if $parameters{namespace} eq "HTML";
</span><del>-print F ", bool createdByParser = false);\n\n";
-print F " static Ref<$parameters{namespace}Element> createElement(const AtomicString& localName, Document&";
</del><ins>+print F ", bool createdByParser = false);\n";
+
+print F "static RefPtr<$parameters{namespace}Element> createKnownElement(const QualifiedName&, Document&";
</ins><span class="cx"> print F ", HTMLFormElement* = nullptr" if $parameters{namespace} eq "HTML";
</span><span class="cx"> print F ", bool createdByParser = false);\n";
</span><del>-print F " static Ref<$parameters{namespace}Element> createElement(const QualifiedName& localName, Document&";
</del><ins>+
+print F "static Ref<$parameters{namespace}Element> createElement(const AtomicString&, Document&";
</ins><span class="cx"> print F ", HTMLFormElement* = nullptr" if $parameters{namespace} eq "HTML";
</span><span class="cx"> print F ", bool createdByParser = false);\n";
</span><span class="cx">
</span><ins>+print F "static Ref<$parameters{namespace}Element> createElement(const QualifiedName&, Document&";
+print F ", HTMLFormElement* = nullptr" if $parameters{namespace} eq "HTML";
+print F ", bool createdByParser = false);\n";
+
</ins><span class="cx"> printf F<<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>