<!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>[205340] 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/205340">205340</a></dd>
<dt>Author</dt> <dd>rniwa@webkit.org</dd>
<dt>Date</dt> <dd>2016-09-01 23:17:17 -0700 (Thu, 01 Sep 2016)</dd>
</dl>

<h3>Log Message</h3>
<pre>Only update connected custom elements
https://bugs.webkit.org/show_bug.cgi?id=161480

Reviewed by Yusuke Suzuki.

Source/WebCore:

In the latest specs, creating an element only upgrades an element if the custom element had already been defined:
https://dom.spec.whatwg.org/#concept-create-element

Otherwise, an element remains unresolved until it gets connected to the document associated with the global object:
https://dom.spec.whatwg.org/#concept-node-insert

This patch removes the upgrade candidate map in CustomElementRegistry, and traverses the entire document associated
with global object (DOMWindow) in addElementDefinition: https://html.spec.whatwg.org/#dom-customelementregistry-define

The traversal is done in the shadow-including tree order (different from depth-first preorder traversal of flat tree)
since it doesn't enter slots and children of shadow hosts are always visited even if they are not assigned to a slot:
https://dom.spec.whatwg.org/#concept-shadow-including-tree-order

Test: fast/custom-elements/enqueue-custom-element-upgrade-reaction.html

* bindings/js/JSCustomElementInterface.cpp:
(WebCore::JSCustomElementInterface::upgradeElement): Assert that the element being upgraded as the same qualified name
as the custom element interface.
* bindings/js/JSCustomElementRegistryCustom.cpp:
(WebCore::JSCustomElementRegistry::define): Moved the code to resolve the promise from here to addElementDefinition.
Also cleaned up the code to extract callbacks a little.
* dom/CustomElementReactionQueue.cpp:
(WebCore::CustomElementReactionQueue::enqueueElementUpgrade): Added an assertion.
(WebCore::CustomElementReactionQueue::enqueueElementUpgradeIfDefined): Added. Upgrade an element if the custom element
had already been defined.
* dom/CustomElementReactionQueue.h:
* dom/CustomElementRegistry.cpp:
(WebCore::CustomElementRegistry::create): Stores the reference to DOMWindow to find its document in addElementDefinition.
(WebCore::CustomElementRegistry::CustomElementRegistry): Ditto.
(WebCore::enqueueUpgradeInShadowIncludingTreeOrder): Added. Enqueue upgrade reactions in shadow-including tree order.
(WebCore::CustomElementRegistry::addElementDefinition): Upgrade all unresolved elements that matches this definition and
resolve the the promise returned by &quot;whenDefined&quot; if there is any.
(WebCore::CustomElementRegistry::addUpgradeCandidate): Deleted.
(WebCore::CustomElementRegistry::findInterface): Added a new variant that takes an element.
* dom/CustomElementRegistry.h:
* dom/Document.cpp:
(WebCore::createUpgradeCandidateElement): No longer takes DOMWindow since we don't upgrade synchronously here. It's also
wrong not to mark the element as unresolved custom element in a document without a browsing context per new semantics.
(WebCore::createHTMLElementWithNameValidation): Ditto.
(WebCore::createFallbackHTMLElement): Ditto.
* dom/Element.cpp:
(WebCore::Element::insertedInto): Enqueue an upgrade reaction if this is an unsolved custom element and there is now
a definition for it (the latter condition is checked in enqueueElementUpgradeIfDefined).
* html/parser/HTMLConstructionSite.cpp:
(WebCore::HTMLConstructionSite::createHTMLElementOrFindCustomElementInterface): Don't upgrade this element until it gets
connected to a document in Element::insertedInto.
* page/DOMWindow.cpp:
(WebCore::DOMWindow::ensureCustomElementRegistry):

LayoutTests:

Added a W3c-style testharness.js test for https://html.spec.whatwg.org/#enqueue-a-custom-element-upgrade-reaction
and added more test cases for :defined and customElements.define.

* fast/custom-elements/CustomElementRegistry.html: Revised descriptions for &quot;get&quot; and &quot;whenDefined&quot; test cases consistent
with ones for &quot;define&quot;.
* fast/custom-elements/defined-pseudo-class-expected.txt:
* fast/custom-elements/defined-pseudo-class.html:
* fast/custom-elements/enqueue-custom-element-upgrade-reaction-expected.txt: Added.
* fast/custom-elements/enqueue-custom-element-upgrade-reaction.html: Added.
* fast/custom-elements/resources/document-types.js:
(create):</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsChangeLog">trunk/LayoutTests/ChangeLog</a></li>
<li><a href="#trunkLayoutTestsfastcustomelementsCustomElementRegistryexpectedtxt">trunk/LayoutTests/fast/custom-elements/CustomElementRegistry-expected.txt</a></li>
<li><a href="#trunkLayoutTestsfastcustomelementsCustomElementRegistryhtml">trunk/LayoutTests/fast/custom-elements/CustomElementRegistry.html</a></li>
<li><a href="#trunkLayoutTestsfastcustomelementsdefinedpseudoclassexpectedtxt">trunk/LayoutTests/fast/custom-elements/defined-pseudo-class-expected.txt</a></li>
<li><a href="#trunkLayoutTestsfastcustomelementsdefinedpseudoclasshtml">trunk/LayoutTests/fast/custom-elements/defined-pseudo-class.html</a></li>
<li><a href="#trunkLayoutTestsfastcustomelementsresourcesdocumenttypesjs">trunk/LayoutTests/fast/custom-elements/resources/document-types.js</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="#trunkSourceWebCorebindingsjsJSCustomElementRegistryCustomcpp">trunk/Source/WebCore/bindings/js/JSCustomElementRegistryCustom.cpp</a></li>
<li><a href="#trunkSourceWebCoredomCustomElementReactionQueuecpp">trunk/Source/WebCore/dom/CustomElementReactionQueue.cpp</a></li>
<li><a href="#trunkSourceWebCoredomCustomElementReactionQueueh">trunk/Source/WebCore/dom/CustomElementReactionQueue.h</a></li>
<li><a href="#trunkSourceWebCoredomCustomElementRegistrycpp">trunk/Source/WebCore/dom/CustomElementRegistry.cpp</a></li>
<li><a href="#trunkSourceWebCoredomCustomElementRegistryh">trunk/Source/WebCore/dom/CustomElementRegistry.h</a></li>
<li><a href="#trunkSourceWebCoredomDocumentcpp">trunk/Source/WebCore/dom/Document.cpp</a></li>
<li><a href="#trunkSourceWebCoredomElementcpp">trunk/Source/WebCore/dom/Element.cpp</a></li>
<li><a href="#trunkSourceWebCorehtmlparserHTMLConstructionSitecpp">trunk/Source/WebCore/html/parser/HTMLConstructionSite.cpp</a></li>
<li><a href="#trunkSourceWebCorepageDOMWindowcpp">trunk/Source/WebCore/page/DOMWindow.cpp</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsfastcustomelementsenqueuecustomelementupgradereactionexpectedtxt">trunk/LayoutTests/fast/custom-elements/enqueue-custom-element-upgrade-reaction-expected.txt</a></li>
<li><a href="#trunkLayoutTestsfastcustomelementsenqueuecustomelementupgradereactionhtml">trunk/LayoutTests/fast/custom-elements/enqueue-custom-element-upgrade-reaction.html</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/ChangeLog (205339 => 205340)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/ChangeLog        2016-09-02 04:41:11 UTC (rev 205339)
+++ trunk/LayoutTests/ChangeLog        2016-09-02 06:17:17 UTC (rev 205340)
</span><span class="lines">@@ -1,3 +1,22 @@
</span><ins>+2016-09-01  Ryosuke Niwa  &lt;rniwa@webkit.org&gt;
+
+        Only update connected custom elements
+        https://bugs.webkit.org/show_bug.cgi?id=161480
+
+        Reviewed by Yusuke Suzuki.
+
+        Added a W3c-style testharness.js test for https://html.spec.whatwg.org/#enqueue-a-custom-element-upgrade-reaction
+        and added more test cases for :defined and customElements.define.
+
+        * fast/custom-elements/CustomElementRegistry.html: Revised descriptions for &quot;get&quot; and &quot;whenDefined&quot; test cases consistent
+        with ones for &quot;define&quot;.
+        * fast/custom-elements/defined-pseudo-class-expected.txt:
+        * fast/custom-elements/defined-pseudo-class.html:
+        * fast/custom-elements/enqueue-custom-element-upgrade-reaction-expected.txt: Added.
+        * fast/custom-elements/enqueue-custom-element-upgrade-reaction.html: Added.
+        * fast/custom-elements/resources/document-types.js:
+        (create):
+
</ins><span class="cx"> 2016-09-01  Gyuyoung Kim  &lt;gyuyoung.kim@webkit.org&gt;
</span><span class="cx"> 
</span><span class="cx">         [EFL] Mark failing tests to failure
</span></span></pre></div>
<a id="trunkLayoutTestsfastcustomelementsCustomElementRegistryexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/fast/custom-elements/CustomElementRegistry-expected.txt (205339 => 205340)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/custom-elements/CustomElementRegistry-expected.txt        2016-09-02 04:41:11 UTC (rev 205339)
+++ trunk/LayoutTests/fast/custom-elements/CustomElementRegistry-expected.txt        2016-09-02 06:17:17 UTC (rev 205340)
</span><span class="lines">@@ -8,6 +8,7 @@
</span><span class="cx"> PASS customElements.define must throw a NotSupportedError when element definition is running flag is set 
</span><span class="cx"> PASS customElements.define must check IsConstructor on the constructor before checking the element definition is running flag 
</span><span class="cx"> PASS customElements.define must validate the custom element name before checking the element definition is running flag 
</span><ins>+PASS customElements.define unset the element definition is running flag before upgrading custom elements 
</ins><span class="cx"> PASS customElements.define must not throw when defining another custom element in a different global object during Get(constructor, &quot;prototype&quot;) 
</span><span class="cx"> PASS Custom Elements: CustomElementRegistry interface 
</span><span class="cx"> PASS customElements.define must get &quot;prototype&quot; property of the constructor 
</span><span class="lines">@@ -23,15 +24,16 @@
</span><span class="cx"> PASS customElements.define must rethrow an exception thrown while retrieving Symbol.iterator on observedAttributes 
</span><span class="cx"> PASS customElements.define must not throw even if &quot;observedAttributes&quot; fails to convert if &quot;attributeChangedCallback&quot; is not defined 
</span><span class="cx"> PASS customElements.define must define an instantiatable custom element 
</span><ins>+PASS customElements.define must upgrade elements in the shadow-including tree order 
</ins><span class="cx"> PASS CustomElementRegistry interface must have get as a method 
</span><del>-PASS &quot;get&quot; must return undefined when the registry does not contain an entry with the given name 
-PASS &quot;get&quot; must return undefined when the registry does not contain an entry with the given name even if the name was not a valid custom element name 
-PASS &quot;get&quot; return the constructor of the entry with the given name when there is a matching entry. 
-PASS &quot;whenDefined&quot; must return a promise for a valid custom element name 
-PASS &quot;whenDefined&quot; must return the same promise each time invoked for a valid custom element name which has not been defined 
-PASS &quot;whenDefined&quot; must return an unresolved promise when the registry does not contain the entry with the given name 
-PASS &quot;whenDefined&quot; must return a rejected promise when the given name is not a valid custom element name 
-PASS &quot;whenDefined&quot; must return a resolved promise when the registry contains the entry with the given name 
-PASS &quot;whenDefined&quot; must return a new resolved promise each time invoked when the registry contains the entry with the given name 
-PASS A promise returned by &quot;whenDefined&quot; must be resolved by &quot;define&quot; 
</del><ins>+PASS customElements.get must return undefined when the registry does not contain an entry with the given name 
+PASS customElements.get must return undefined when the registry does not contain an entry with the given name even if the name was not a valid custom element name 
+PASS customElements.get return the constructor of the entry with the given name when there is a matching entry. 
+PASS customElements.whenDefined must return a promise for a valid custom element name 
+PASS customElements.whenDefined must return the same promise each time invoked for a valid custom element name which has not been defined 
+PASS customElements.whenDefined must return an unresolved promise when the registry does not contain the entry with the given name 
+PASS customElements.whenDefined must return a rejected promise when the given name is not a valid custom element name 
+PASS customElements.whenDefined must return a resolved promise when the registry contains the entry with the given name 
+PASS customElements.whenDefined must return a new resolved promise each time invoked when the registry contains the entry with the given name 
+PASS A promise returned by customElements.whenDefined must be resolved by &quot;define&quot; 
</ins><span class="cx"> 
</span></span></pre></div>
<a id="trunkLayoutTestsfastcustomelementsCustomElementRegistryhtml"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/fast/custom-elements/CustomElementRegistry.html (205339 => 205340)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/custom-elements/CustomElementRegistry.html        2016-09-02 04:41:11 UTC (rev 205339)
+++ trunk/LayoutTests/fast/custom-elements/CustomElementRegistry.html        2016-09-02 06:17:17 UTC (rev 205340)
</span><span class="lines">@@ -149,6 +149,31 @@
</span><span class="cx">     assert_array_equals(calls, ['prototype'], 'customElements.define must get &quot;prototype&quot;');
</span><span class="cx"> }, 'customElements.define must validate the custom element name before checking the element definition is running flag');
</span><span class="cx"> 
</span><ins>+test(function () {
+    var unresolvedElement = document.createElement('constructor-calls-define');
+    document.body.appendChild(unresolvedElement);
+    var elementUpgradedDuringUpgrade = document.createElement('defined-during-upgrade');
+    document.body.appendChild(elementUpgradedDuringUpgrade);
+
+    var DefinedDuringUpgrade = class extends HTMLElement { };
+
+    class ConstructorCallsDefine extends HTMLElement {
+        constructor() {
+            customElements.define('defined-during-upgrade', DefinedDuringUpgrade);
+            assert_false(unresolvedElement instanceof ConstructorCallsDefine);
+            assert_true(elementUpgradedDuringUpgrade instanceof DefinedDuringUpgrade);
+            super();
+            assert_true(unresolvedElement instanceof ConstructorCallsDefine);
+            assert_true(elementUpgradedDuringUpgrade instanceof DefinedDuringUpgrade);
+        }
+    }
+
+    assert_false(unresolvedElement instanceof ConstructorCallsDefine);
+    assert_false(elementUpgradedDuringUpgrade instanceof DefinedDuringUpgrade);
+
+    customElements.define('constructor-calls-define', ConstructorCallsDefine);
+}, 'customElements.define unset the element definition is running flag before upgrading custom elements');
+
</ins><span class="cx"> (function () {
</span><span class="cx">     var testCase = async_test('customElements.define must not throw'
</span><span class="cx">         +' when defining another custom element in a different global object during Get(constructor, &quot;prototype&quot;)', {timeout: 100});
</span><span class="lines">@@ -384,6 +409,41 @@
</span><span class="cx"> }, 'customElements.define must define an instantiatable custom element');
</span><span class="cx"> 
</span><span class="cx"> test(function () {
</span><ins>+    var disconnectedElement = document.createElement('some-custom');
+    var connectedElementBeforeShadowHost = document.createElement('some-custom');
+    var connectedElementAfterShadowHost = document.createElement('some-custom');
+    var elementInShadowTree = document.createElement('some-custom');
+    var childElementOfShadowHost = document.createElement('some-custom');
+    var customShadowHost = document.createElement('some-custom');
+    var elementInNestedShadowTree = document.createElement('some-custom');
+
+    var container = document.createElement('div');
+    var shadowHost = document.createElement('div');
+    var shadowRoot = shadowHost.attachShadow({mode: 'closed'});
+    container.appendChild(connectedElementBeforeShadowHost);
+    container.appendChild(shadowHost);
+    container.appendChild(connectedElementAfterShadowHost);
+    shadowHost.appendChild(childElementOfShadowHost);
+    shadowRoot.appendChild(elementInShadowTree);
+    shadowRoot.appendChild(customShadowHost);
+
+    var innerShadowRoot = customShadowHost.attachShadow({mode: 'closed'});
+    innerShadowRoot.appendChild(elementInNestedShadowTree);
+
+    var calls = [];
+    class SomeCustomElement extends HTMLElement {
+        constructor() {
+            super();
+            calls.push(this);
+        }
+    };
+
+    document.body.appendChild(container);
+    customElements.define('some-custom', SomeCustomElement);
+    assert_array_equals(calls, [connectedElementBeforeShadowHost, elementInShadowTree, customShadowHost, elementInNestedShadowTree, childElementOfShadowHost, connectedElementAfterShadowHost]);
+}, 'customElements.define must upgrade elements in the shadow-including tree order');
+
+test(function () {
</ins><span class="cx">     assert_true('get' in CustomElementRegistry.prototype, '&quot;get&quot; exists on CustomElementRegistry.prototype');
</span><span class="cx">     assert_true('get' in customElements, '&quot;get&quot; exists on window.customElements');
</span><span class="cx"> }, 'CustomElementRegistry interface must have get as a method');
</span><span class="lines">@@ -390,7 +450,7 @@
</span><span class="cx"> 
</span><span class="cx"> test(function () {
</span><span class="cx">     assert_equals(customElements.get('a-b'), undefined);
</span><del>-}, '&quot;get&quot; must return undefined when the registry does not contain an entry with the given name');
</del><ins>+}, 'customElements.get must return undefined when the registry does not contain an entry with the given name');
</ins><span class="cx"> 
</span><span class="cx"> test(function () {
</span><span class="cx">     assert_equals(customElements.get('html'), undefined);
</span><span class="lines">@@ -398,7 +458,7 @@
</span><span class="cx">     assert_equals(customElements.get('div'), undefined);
</span><span class="cx">     assert_equals(customElements.get('g'), undefined);
</span><span class="cx">     assert_equals(customElements.get('ab'), undefined);
</span><del>-}, '&quot;get&quot; must return undefined when the registry does not contain an entry with the given name even if the name was not a valid custom element name');
</del><ins>+}, 'customElements.get must return undefined when the registry does not contain an entry with the given name even if the name was not a valid custom element name');
</ins><span class="cx"> 
</span><span class="cx"> test(function () {
</span><span class="cx">     assert_equals(customElements.get('existing-custom-element'), undefined);
</span><span class="lines">@@ -405,15 +465,15 @@
</span><span class="cx">     class ExistingCustomElement extends HTMLElement {};
</span><span class="cx">     customElements.define('existing-custom-element', ExistingCustomElement);
</span><span class="cx">     assert_equals(customElements.get('existing-custom-element'), ExistingCustomElement);
</span><del>-}, '&quot;get&quot; return the constructor of the entry with the given name when there is a matching entry.');
</del><ins>+}, 'customElements.get return the constructor of the entry with the given name when there is a matching entry.');
</ins><span class="cx"> 
</span><span class="cx"> test(function () {
</span><span class="cx">     assert_true(customElements.whenDefined('some-name') instanceof Promise);
</span><del>-}, '&quot;whenDefined&quot; must return a promise for a valid custom element name');
</del><ins>+}, 'customElements.whenDefined must return a promise for a valid custom element name');
</ins><span class="cx"> 
</span><span class="cx"> test(function () {
</span><span class="cx">     assert_equals(customElements.whenDefined('some-name'), customElements.whenDefined('some-name'));
</span><del>-}, '&quot;whenDefined&quot; must return the same promise each time invoked for a valid custom element name which has not been defined');
</del><ins>+}, 'customElements.whenDefined must return the same promise each time invoked for a valid custom element name which has not been defined');
</ins><span class="cx"> 
</span><span class="cx"> promise_test(function () {
</span><span class="cx">     var resolved = false;
</span><span class="lines">@@ -423,7 +483,7 @@
</span><span class="cx">         assert_false(resolved, 'The promise returned by &quot;whenDefined&quot; must not be resolved until a custom element is defined');
</span><span class="cx">         assert_false(rejected, 'The promise returned by &quot;whenDefined&quot; must not be rejected until a custom element is defined');
</span><span class="cx">     });    
</span><del>-}, '&quot;whenDefined&quot; must return an unresolved promise when the registry does not contain the entry with the given name')
</del><ins>+}, 'customElements.whenDefined must return an unresolved promise when the registry does not contain the entry with the given name')
</ins><span class="cx"> 
</span><span class="cx"> promise_test(function () {
</span><span class="cx">     var promise = customElements.whenDefined('badname');
</span><span class="lines">@@ -436,7 +496,7 @@
</span><span class="cx">         assert_false('resolved' in promise, 'The promise returned by &quot;whenDefined&quot; must be resolved when a custom element is defined');
</span><span class="cx">         assert_true('rejected' in promise, 'The promise returned by &quot;whenDefined&quot; must not be rejected when a custom element is defined');
</span><span class="cx">     });
</span><del>-}, '&quot;whenDefined&quot; must return a rejected promise when the given name is not a valid custom element name');
</del><ins>+}, 'customElements.whenDefined must return a rejected promise when the given name is not a valid custom element name');
</ins><span class="cx"> 
</span><span class="cx"> promise_test(function () {
</span><span class="cx">     customElements.define('preexisting-custom-element', class extends HTMLElement { });
</span><span class="lines">@@ -453,7 +513,7 @@
</span><span class="cx">             'The promise returned by &quot;whenDefined&quot; must be resolved with &quot;undefined&quot; when a custom element is defined');
</span><span class="cx">         assert_false('rejected' in promise, 'The promise returned by &quot;whenDefined&quot; must not be rejected when a custom element is defined');
</span><span class="cx">     });
</span><del>-}, '&quot;whenDefined&quot; must return a resolved promise when the registry contains the entry with the given name');
</del><ins>+}, 'customElements.whenDefined must return a resolved promise when the registry contains the entry with the given name');
</ins><span class="cx"> 
</span><span class="cx"> promise_test(function () {
</span><span class="cx">     class AnotherExistingCustomElement extends HTMLElement {};
</span><span class="lines">@@ -479,7 +539,7 @@
</span><span class="cx">         assert_equals(promise2.resolved, undefined, 'The promise returned by &quot;whenDefined&quot; must be resolved with &quot;undefined&quot; when a custom element is defined');
</span><span class="cx">         assert_false('rejected' in promise2, 'The promise returned by &quot;whenDefined&quot; must not be rejected when a custom element is defined');
</span><span class="cx">     });
</span><del>-}, '&quot;whenDefined&quot; must return a new resolved promise each time invoked when the registry contains the entry with the given name');
</del><ins>+}, 'customElements.whenDefined must return a new resolved promise each time invoked when the registry contains the entry with the given name');
</ins><span class="cx"> 
</span><span class="cx"> promise_test(function () {
</span><span class="cx">     var promise = customElements.whenDefined('element-defined-after-whendefined');
</span><span class="lines">@@ -514,7 +574,7 @@
</span><span class="cx">             'The promise returned by &quot;whenDefined&quot; must be resolved with &quot;undefined&quot; when a custom element is defined');
</span><span class="cx">         assert_false('rejected' in promiseAfterDefine, 'The promise returned by &quot;whenDefined&quot; must not be rejected when a custom element is defined');
</span><span class="cx">     });
</span><del>-}, 'A promise returned by &quot;whenDefined&quot; must be resolved by &quot;define&quot;');
</del><ins>+}, 'A promise returned by customElements.whenDefined must be resolved by &quot;define&quot;');
</ins><span class="cx"> 
</span><span class="cx"> &lt;/script&gt;
</span><span class="cx"> &lt;/body&gt;
</span></span></pre></div>
<a id="trunkLayoutTestsfastcustomelementsdefinedpseudoclassexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/fast/custom-elements/defined-pseudo-class-expected.txt (205339 => 205340)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/custom-elements/defined-pseudo-class-expected.txt        2016-09-02 04:41:11 UTC (rev 205339)
+++ trunk/LayoutTests/fast/custom-elements/defined-pseudo-class-expected.txt        2016-09-02 06:17:17 UTC (rev 205340)
</span><span class="lines">@@ -1,7 +1,9 @@
</span><span class="cx"> 
</span><span class="cx"> PASS The defined flag of a custom element must not be set if a custom element has not been upgraded yet 
</span><ins>+PASS The defined flag of a custom element must not be set if a custom element has not been upgraded yet even if the element has been defined 
</ins><span class="cx"> PASS The defined flag of a custom element must be set when a custom element is successfully upgraded 
</span><span class="cx"> PASS The defined flag of a custom element must be set if there is a matching definition 
</span><ins>+PASS The defined flag of an upgraded custom element must be set 
</ins><span class="cx"> PASS The defined flag of a custom element created by HTML parser must be unset if there is no matching definition 
</span><span class="cx"> PASS The defined flag of a custom element created by HTML parser must be set if there is a matching definition 
</span><span class="cx"> PASS The defined flag of a custom element created by HTML parser must be set after checking the returned result is an instance of HTMLElement 
</span></span></pre></div>
<a id="trunkLayoutTestsfastcustomelementsdefinedpseudoclasshtml"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/fast/custom-elements/defined-pseudo-class.html (205339 => 205340)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/custom-elements/defined-pseudo-class.html        2016-09-02 04:41:11 UTC (rev 205339)
+++ trunk/LayoutTests/fast/custom-elements/defined-pseudo-class.html        2016-09-02 06:17:17 UTC (rev 205340)
</span><span class="lines">@@ -28,6 +28,11 @@
</span><span class="cx"> customElements.define('my-element', MyElement);
</span><span class="cx"> 
</span><span class="cx"> test(function () {
</span><ins>+    assert_false(upgradeCandidate.matches(':defined'));
+}, 'The defined flag of a custom element must not be set if a custom element has not been upgraded yet even if the element has been defined');
+
+test(function () {
+    document.body.appendChild(upgradeCandidate);
</ins><span class="cx">     assert_true(upgradeCandidate.matches(':defined'));
</span><span class="cx">     assert_false(matchInsideConstructor, 'Upgrading a custom element must set defined flag after invoking the constructor');
</span><span class="cx"> }, 'The defined flag of a custom element must be set when a custom element is successfully upgraded');
</span><span class="lines">@@ -38,6 +43,12 @@
</span><span class="cx">     assert_false(matchInsideConstructor, 'Creating a custom element must set defined flag after invoking the constructor');
</span><span class="cx"> }, 'The defined flag of a custom element must be set if there is a matching definition');
</span><span class="cx"> 
</span><ins>+test(function () {
+    var upgradedElement = document.createElement('my-element').cloneNode(true);
+    assert_true(upgradedElement.matches(':defined'));
+    assert_false(matchInsideConstructor, 'Creating a custom element must set defined flag after invoking the constructor');
+}, 'The defined flag of an upgraded custom element must be set');
+
</ins><span class="cx"> document.write('&lt;my-other-element&gt;&lt;/my-other-element&gt;');
</span><span class="cx"> 
</span><span class="cx"> test(function () {
</span></span></pre></div>
<a id="trunkLayoutTestsfastcustomelementsenqueuecustomelementupgradereactionexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/fast/custom-elements/enqueue-custom-element-upgrade-reaction-expected.txt (0 => 205340)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/custom-elements/enqueue-custom-element-upgrade-reaction-expected.txt                                (rev 0)
+++ trunk/LayoutTests/fast/custom-elements/enqueue-custom-element-upgrade-reaction-expected.txt        2016-09-02 06:17:17 UTC (rev 205340)
</span><span class="lines">@@ -0,0 +1,27 @@
</span><ins>+
+PASS Creating an element in document of a template element must not enqueue a custom element upgrade reaction because the document does not have a browsing context 
+PASS Creating an element in document of a template element and inserting into the document must not enqueue a custom element upgrade reaction 
+PASS Creating an element in document of a template element and adopting back to a document with browsing context must enqueue a custom element upgrade reaction 
+PASS Creating an element in new document must not enqueue a custom element upgrade reaction because the document does not have a browsing context 
+PASS Creating an element in new document and inserting into the document must not enqueue a custom element upgrade reaction 
+PASS Creating an element in new document and adopting back to a document with browsing context must enqueue a custom element upgrade reaction 
+PASS Creating an element in cloned document must not enqueue a custom element upgrade reaction because the document does not have a browsing context 
+PASS Creating an element in cloned document and inserting into the document must not enqueue a custom element upgrade reaction 
+PASS Creating an element in cloned document and adopting back to a document with browsing context must enqueue a custom element upgrade reaction 
+PASS Creating an element in document created by createHTMLDocument must not enqueue a custom element upgrade reaction because the document does not have a browsing context 
+PASS Creating an element in document created by createHTMLDocument and inserting into the document must not enqueue a custom element upgrade reaction 
+PASS Creating an element in document created by createHTMLDocument and adopting back to a document with browsing context must enqueue a custom element upgrade reaction 
+PASS Creating an element in HTML document created by createDocument must not enqueue a custom element upgrade reaction because the document does not have a browsing context 
+PASS Creating an element in HTML document created by createDocument and inserting into the document must not enqueue a custom element upgrade reaction 
+PASS Creating an element in HTML document created by createDocument and adopting back to a document with browsing context must enqueue a custom element upgrade reaction 
+PASS Creating an element in HTML document fetched by XHR must not enqueue a custom element upgrade reaction because the document does not have a browsing context 
+PASS Creating an element in HTML document fetched by XHR and inserting into the document must not enqueue a custom element upgrade reaction 
+PASS Creating an element in HTML document fetched by XHR and adopting back to a document with browsing context must enqueue a custom element upgrade reaction 
+PASS Creating an element in document in an iframe must not enqueue a custom element upgrade reaction if there is no matching definition 
+PASS Creating an element in document in an iframe must enqueue a custom element upgrade reaction if there is a matching definition 
+PASS &quot;define&quot; in document in an iframe must not enqueue a custom element upgrade reaction on a disconnected unresolved custom element 
+PASS Inserting an unresolved custom element into document in an iframe must enqueue a custom element upgrade reaction 
+PASS &quot;define&quot; in document in an iframe must enqueue a custom element upgrade reaction on a connected unresolved custom element 
+PASS Adopting (and leaving disconnceted) an unresolved custom element into document in an iframe must not enqueue a custom element upgrade reaction 
+PASS Adopting and inserting an unresolved custom element into document in an iframe must enqueue a custom element upgrade reaction 
+
</ins></span></pre></div>
<a id="trunkLayoutTestsfastcustomelementsenqueuecustomelementupgradereactionhtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/fast/custom-elements/enqueue-custom-element-upgrade-reaction.html (0 => 205340)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/custom-elements/enqueue-custom-element-upgrade-reaction.html                                (rev 0)
+++ trunk/LayoutTests/fast/custom-elements/enqueue-custom-element-upgrade-reaction.html        2016-09-02 06:17:17 UTC (rev 205340)
</span><span class="lines">@@ -0,0 +1,189 @@
</span><ins>+&lt;!DOCTYPE html&gt;
+&lt;html&gt;
+&lt;head&gt;
+&lt;title&gt;Custom Elements: Enqueue a custom element upgrade reaction&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;Enqueue a custom element upgrade reaction must upgrade a custom element&quot;&gt;
+&lt;link rel=&quot;help&quot; href=&quot;https://dom.spec.whatwg.org/#concept-create-element&quot;&gt;
+&lt;link rel=&quot;help&quot; href=&quot;https://html.spec.whatwg.org/multipage/scripting.html#concept-try-upgrade&quot;&gt;
+&lt;link rel=&quot;help&quot; href=&quot;https://html.spec.whatwg.org/multipage/scripting.html#enqueue-a-custom-element-upgrade-reaction&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;script src=&quot;resources/document-types.js&quot;&gt;&lt;/script&gt;
+&lt;/head&gt;
+&lt;body&gt;
+&lt;div id=&quot;log&quot;&gt;&lt;/div&gt;
+&lt;script&gt;
+
+class PredefinedCustomElement extends HTMLElement {}
+customElements.define('predefined-custom-element', PredefinedCustomElement);
+
+var customElementNumber = 1;
+function generateNextCustomElementName() { return 'custom-' + customElementNumber++; }
+
+DocumentTypes.filter(function (entry) { return !entry.isOwner &amp;&amp; !entry.hasBrowsingContext; }).forEach(function (entry) {
+    var documentName = entry.name;
+    var getDocument = entry.create;
+
+    promise_test(function () {
+        return getDocument().then(function (doc) {
+            assert_false(doc.createElement('predefined-custom-element') instanceof PredefinedCustomElement);
+        });
+    }, 'Creating an element in ' + documentName + ' must not enqueue a custom element upgrade reaction'
+        + ' because the document does not have a browsing context');
+
+    promise_test(function () {
+        var name = generateNextCustomElementName();
+        var unresolvedElement = document.createElement(name);
+
+        assert_equals(unresolvedElement.__proto__, HTMLElement.prototype,
+            '[[Prototype]] internal slot of the unresolved custom element must be the HTMLElement prototype');
+
+        return getDocument().then(function (doc) {
+            var unresolvedElementInDoc = doc.createElement(name);
+            var prototype = (unresolvedElementInDoc.namespaceURI == 'http://www.w3.org/1999/xhtml' ? HTMLElement : Element).prototype;
+
+            assert_equals(unresolvedElementInDoc.__proto__, prototype,
+                '[[Prototype]] internal slot of the unresolved custom element must be the ' + prototype.toString() + ' prototype');
+            var someCustomElement = class extends HTMLElement {};
+            customElements.define(name, someCustomElement);
+            assert_equals(unresolvedElementInDoc.__proto__, prototype, '&quot;define&quot; must not upgrade a disconnected unresolved custom elements');
+            doc.documentElement.appendChild(unresolvedElementInDoc);
+            assert_equals(unresolvedElementInDoc.__proto__, prototype,
+                'Inserting an element into a document without a browsing context must not enqueue a custom element upgrade reaction');
+        });
+    }, 'Creating an element in ' + documentName + ' and inserting into the document must not enqueue a custom element upgrade reaction');
+
+    promise_test(function () {
+        var name = generateNextCustomElementName();
+        var unresolvedElement = document.createElement(name);
+
+        assert_equals(unresolvedElement.__proto__, HTMLElement.prototype,
+            '[[Prototype]] internal slot of the unresolved custom element must be the HTMLElement prototype');
+
+        return getDocument().then(function (doc) {
+            var unresolvedElementInDoc = doc.createElement(name);
+            var prototype = (unresolvedElementInDoc.namespaceURI == 'http://www.w3.org/1999/xhtml' ? HTMLElement : Element).prototype;
+
+            assert_equals(unresolvedElementInDoc.__proto__, prototype,
+                '[[Prototype]] internal slot of the unresolved custom element must be the ' + prototype.toString() + ' prototype');
+            var someCustomElement = class extends HTMLElement {};
+            customElements.define(name, someCustomElement);
+            assert_equals(unresolvedElementInDoc.__proto__, prototype, '&quot;define&quot; must not upgrade a disconnected unresolved custom elements');
+            document.body.appendChild(unresolvedElementInDoc);
+
+            if (unresolvedElementInDoc.namespaceURI == 'http://www.w3.org/1999/xhtml') {
+                assert_equals(unresolvedElementInDoc.__proto__, someCustomElement.prototype,
+                    'Inserting an element into a document with a browsing context must enqueue a custom element upgrade reaction');
+            } else {
+                assert_equals(unresolvedElementInDoc.__proto__, prototype,
+                    'Looking up a custom element definition must return null if the element is not in the HTML namespace');
+            }
+        });
+    }, 'Creating an element in ' + documentName + ' and adopting back to a document with browsing context must enqueue a custom element upgrade reaction');
+
+});
+
+DocumentTypes.filter(function (entry) { return !entry.isOwner &amp;&amp; entry.hasBrowsingContext; }).forEach(function (entry) {
+    var documentName = entry.name;
+    var getDocument = entry.create;
+
+    promise_test(function () {
+        return getDocument().then(function (doc) {
+            assert_false(doc.createElement('predefined-custom-element') instanceof PredefinedCustomElement);
+        });
+    }, 'Creating an element in ' + documentName + ' must not enqueue a custom element upgrade reaction if there is no matching definition');
+
+    promise_test(function () {
+        return getDocument().then(function (doc) {
+            var docWindow = doc.defaultView;
+            class DistinctPredefinedCustomElement extends docWindow.HTMLElement { };
+            docWindow.customElements.define('predefined-custom-element', DistinctPredefinedCustomElement);
+            assert_true(doc.createElement('predefined-custom-element') instanceof DistinctPredefinedCustomElement);
+        });
+    }, 'Creating an element in ' + documentName + ' must enqueue a custom element upgrade reaction if there is a matching definition');
+
+    promise_test(function () {
+        var unresolvedElement = document.createElement('unresolved-element');
+        return getDocument().then(function (doc) {
+            var docWindow = doc.defaultView;
+            class UnresolvedElement extends docWindow.HTMLElement { };
+            var unresolvedElementInDoc = doc.createElement('unresolved-element');
+
+            assert_equals(unresolvedElement.__proto__, HTMLElement.prototype);
+            assert_equals(unresolvedElementInDoc.__proto__, docWindow.HTMLElement.prototype);
+
+            docWindow.customElements.define('unresolved-element', UnresolvedElement);
+
+            assert_equals(unresolvedElement.__proto__, HTMLElement.prototype);
+            assert_equals(unresolvedElementInDoc.__proto__, docWindow.HTMLElement.prototype);
+
+        });
+    }, '&quot;define&quot; in ' + documentName + ' must not enqueue a custom element upgrade reaction on a disconnected unresolved custom element');
+
+    promise_test(function () {
+        var unresolvedElement = document.createElement('unresolved-element');
+        return getDocument().then(function (doc) {
+            var docWindow = doc.defaultView;
+            class UnresolvedElement extends docWindow.HTMLElement { };
+            var unresolvedElementInDoc = doc.createElement('unresolved-element');
+
+            assert_equals(unresolvedElement.__proto__, HTMLElement.prototype);
+            assert_equals(unresolvedElementInDoc.__proto__, docWindow.HTMLElement.prototype);
+
+            docWindow.customElements.define('unresolved-element', UnresolvedElement);
+            doc.documentElement.appendChild(unresolvedElementInDoc);
+
+            assert_equals(unresolvedElement.__proto__, HTMLElement.prototype);
+            assert_equals(unresolvedElementInDoc.__proto__, UnresolvedElement.prototype);
+        });
+    }, 'Inserting an unresolved custom element into ' + documentName + ' must enqueue a custom element upgrade reaction');
+
+    promise_test(function () {
+        var unresolvedElement = document.createElement('unresolved-element');
+        return getDocument().then(function (doc) {
+            var docWindow = doc.defaultView;
+            class UnresolvedElement extends docWindow.HTMLElement { };
+            var unresolvedElementInDoc = doc.createElement('unresolved-element');
+            doc.documentElement.appendChild(unresolvedElementInDoc);
+
+            assert_equals(unresolvedElement.__proto__, HTMLElement.prototype);
+            assert_equals(unresolvedElementInDoc.__proto__, docWindow.HTMLElement.prototype);
+
+            docWindow.customElements.define('unresolved-element', UnresolvedElement);
+
+            assert_equals(unresolvedElement.__proto__, HTMLElement.prototype);
+            assert_equals(unresolvedElementInDoc.__proto__, UnresolvedElement.prototype);
+        });
+    }, '&quot;define&quot; in ' + documentName + ' must enqueue a custom element upgrade reaction on a connected unresolved custom element');
+
+    promise_test(function () {
+        var unresolvedElement = document.createElement('unresolved-element');
+        return getDocument().then(function (doc) {
+            var docWindow = doc.defaultView;
+            class UnresolvedElement extends docWindow.HTMLElement { };
+            assert_false(unresolvedElement instanceof UnresolvedElement);
+            docWindow.customElements.define('unresolved-element', UnresolvedElement);
+            doc.adoptNode(unresolvedElement);
+            assert_false(unresolvedElement instanceof UnresolvedElement);
+        });
+    }, 'Adopting (and leaving disconnceted) an unresolved custom element into ' + documentName + ' must not enqueue a custom element upgrade reaction');
+
+    promise_test(function () {
+        var unresolvedElement = document.createElement('unresolved-element');
+        return getDocument().then(function (doc) {
+            var docWindow = doc.defaultView;
+            class UnresolvedElement extends docWindow.HTMLElement { };
+            assert_false(unresolvedElement instanceof UnresolvedElement);
+            docWindow.customElements.define('unresolved-element', UnresolvedElement);
+            doc.documentElement.appendChild(unresolvedElement);
+            assert_true(unresolvedElement instanceof UnresolvedElement);
+        });
+    }, 'Adopting and inserting an unresolved custom element into ' + documentName + ' must enqueue a custom element upgrade reaction');
+
+});
+
+&lt;/script&gt;
+&lt;/body&gt;
+&lt;/html&gt;
</ins></span></pre></div>
<a id="trunkLayoutTestsfastcustomelementsresourcesdocumenttypesjs"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/fast/custom-elements/resources/document-types.js (205339 => 205340)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/custom-elements/resources/document-types.js        2016-09-02 04:41:11 UTC (rev 205339)
+++ trunk/LayoutTests/fast/custom-elements/resources/document-types.js        2016-09-02 06:17:17 UTC (rev 205340)
</span><span class="lines">@@ -3,6 +3,7 @@
</span><span class="cx">         name: 'document',
</span><span class="cx">         create: function () { return Promise.resolve(document); },
</span><span class="cx">         isOwner: true,
</span><ins>+        hasBrowsingContext: true,
</ins><span class="cx">     },
</span><span class="cx">     {
</span><span class="cx">         name: 'document of a template element',
</span><span class="lines">@@ -14,7 +15,8 @@
</span><span class="cx">                     doc.appendChild(doc.createElement('html'));
</span><span class="cx">                 resolve(doc);
</span><span class="cx">             });
</span><del>-        }
</del><ins>+        },
+        hasBrowsingContext: false,
</ins><span class="cx">     },
</span><span class="cx">     {
</span><span class="cx">         name: 'new document',
</span><span class="lines">@@ -24,7 +26,8 @@
</span><span class="cx">                 doc.appendChild(doc.createElement('html'));
</span><span class="cx">                 resolve(doc);
</span><span class="cx">             });
</span><del>-        }
</del><ins>+        },
+        hasBrowsingContext: false,
</ins><span class="cx">     },
</span><span class="cx">     {
</span><span class="cx">         name: 'cloned document',
</span><span class="lines">@@ -34,19 +37,22 @@
</span><span class="cx">                 doc.appendChild(doc.createElement('html'));
</span><span class="cx">                 resolve(doc);
</span><span class="cx">             });
</span><del>-        }
</del><ins>+        },
+        hasBrowsingContext: false,
</ins><span class="cx">     },
</span><span class="cx">     {
</span><span class="cx">         name: 'document created by createHTMLDocument',
</span><span class="cx">         create: function () {
</span><span class="cx">             return Promise.resolve(document.implementation.createHTMLDocument());
</span><del>-        }
</del><ins>+        },
+        hasBrowsingContext: false,
</ins><span class="cx">     },
</span><span class="cx">     {
</span><span class="cx">         name: 'HTML document created by createDocument',
</span><span class="cx">         create: function () {
</span><span class="cx">             return Promise.resolve(document.implementation.createDocument('http://www.w3.org/1999/xhtml', 'html', null));
</span><del>-        }
</del><ins>+        },
+        hasBrowsingContext: false,
</ins><span class="cx">     },
</span><span class="cx">     {
</span><span class="cx">         name: 'document in an iframe',
</span><span class="lines">@@ -57,7 +63,8 @@
</span><span class="cx">                 iframe.onerror = function () { reject('Failed to load an empty iframe'); }
</span><span class="cx">                 document.body.appendChild(iframe);
</span><span class="cx">             });
</span><del>-        }
</del><ins>+        },
+        hasBrowsingContext: true,
</ins><span class="cx">     },
</span><span class="cx">     {
</span><span class="cx">         name: 'HTML document fetched by XHR',
</span><span class="lines">@@ -70,6 +77,7 @@
</span><span class="cx">                 xhr.onerror = function () { reject('Failed to fetch the document'); }
</span><span class="cx">                 xhr.send();
</span><span class="cx">             });
</span><del>-        }
</del><ins>+        },
+        hasBrowsingContext: false,
</ins><span class="cx">     }
</span><span class="cx"> ];
</span><span class="cx">\ No newline at end of file
</span></span></pre></div>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (205339 => 205340)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2016-09-02 04:41:11 UTC (rev 205339)
+++ trunk/Source/WebCore/ChangeLog        2016-09-02 06:17:17 UTC (rev 205340)
</span><span class="lines">@@ -1,3 +1,59 @@
</span><ins>+2016-09-01  Ryosuke Niwa  &lt;rniwa@webkit.org&gt;
+
+        Only update connected custom elements
+        https://bugs.webkit.org/show_bug.cgi?id=161480
+
+        Reviewed by Yusuke Suzuki.
+
+        In the latest specs, creating an element only upgrades an element if the custom element had already been defined:
+        https://dom.spec.whatwg.org/#concept-create-element
+
+        Otherwise, an element remains unresolved until it gets connected to the document associated with the global object:
+        https://dom.spec.whatwg.org/#concept-node-insert
+
+        This patch removes the upgrade candidate map in CustomElementRegistry, and traverses the entire document associated
+        with global object (DOMWindow) in addElementDefinition: https://html.spec.whatwg.org/#dom-customelementregistry-define
+
+        The traversal is done in the shadow-including tree order (different from depth-first preorder traversal of flat tree)
+        since it doesn't enter slots and children of shadow hosts are always visited even if they are not assigned to a slot:
+        https://dom.spec.whatwg.org/#concept-shadow-including-tree-order
+
+        Test: fast/custom-elements/enqueue-custom-element-upgrade-reaction.html
+
+        * bindings/js/JSCustomElementInterface.cpp:
+        (WebCore::JSCustomElementInterface::upgradeElement): Assert that the element being upgraded as the same qualified name
+        as the custom element interface.
+        * bindings/js/JSCustomElementRegistryCustom.cpp:
+        (WebCore::JSCustomElementRegistry::define): Moved the code to resolve the promise from here to addElementDefinition.
+        Also cleaned up the code to extract callbacks a little.
+        * dom/CustomElementReactionQueue.cpp:
+        (WebCore::CustomElementReactionQueue::enqueueElementUpgrade): Added an assertion.
+        (WebCore::CustomElementReactionQueue::enqueueElementUpgradeIfDefined): Added. Upgrade an element if the custom element
+        had already been defined.
+        * dom/CustomElementReactionQueue.h:
+        * dom/CustomElementRegistry.cpp:
+        (WebCore::CustomElementRegistry::create): Stores the reference to DOMWindow to find its document in addElementDefinition.
+        (WebCore::CustomElementRegistry::CustomElementRegistry): Ditto.
+        (WebCore::enqueueUpgradeInShadowIncludingTreeOrder): Added. Enqueue upgrade reactions in shadow-including tree order.
+        (WebCore::CustomElementRegistry::addElementDefinition): Upgrade all unresolved elements that matches this definition and
+        resolve the the promise returned by &quot;whenDefined&quot; if there is any.
+        (WebCore::CustomElementRegistry::addUpgradeCandidate): Deleted.
+        (WebCore::CustomElementRegistry::findInterface): Added a new variant that takes an element.
+        * dom/CustomElementRegistry.h:
+        * dom/Document.cpp:
+        (WebCore::createUpgradeCandidateElement): No longer takes DOMWindow since we don't upgrade synchronously here. It's also
+        wrong not to mark the element as unresolved custom element in a document without a browsing context per new semantics.
+        (WebCore::createHTMLElementWithNameValidation): Ditto.
+        (WebCore::createFallbackHTMLElement): Ditto.
+        * dom/Element.cpp:
+        (WebCore::Element::insertedInto): Enqueue an upgrade reaction if this is an unsolved custom element and there is now
+        a definition for it (the latter condition is checked in enqueueElementUpgradeIfDefined).
+        * html/parser/HTMLConstructionSite.cpp:
+        (WebCore::HTMLConstructionSite::createHTMLElementOrFindCustomElementInterface): Don't upgrade this element until it gets
+        connected to a document in Element::insertedInto.
+        * page/DOMWindow.cpp:
+        (WebCore::DOMWindow::ensureCustomElementRegistry):
+
</ins><span class="cx"> 2016-09-01  Yusuke Suzuki  &lt;utatane.tea@gmail.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Add toJS for JSC::PrivateName
</span></span></pre></div>
<a id="trunkSourceWebCorebindingsjsJSCustomElementInterfacecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/bindings/js/JSCustomElementInterface.cpp (205339 => 205340)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/bindings/js/JSCustomElementInterface.cpp        2016-09-02 04:41:11 UTC (rev 205339)
+++ trunk/Source/WebCore/bindings/js/JSCustomElementInterface.cpp        2016-09-02 06:17:17 UTC (rev 205340)
</span><span class="lines">@@ -104,6 +104,7 @@
</span><span class="cx"> 
</span><span class="cx"> void JSCustomElementInterface::upgradeElement(Element&amp; element)
</span><span class="cx"> {
</span><ins>+    ASSERT(element.tagQName() == name());
</ins><span class="cx">     ASSERT(element.isUnresolvedCustomElement());
</span><span class="cx">     if (!canInvokeCallback())
</span><span class="cx">         return;
</span></span></pre></div>
<a id="trunkSourceWebCorebindingsjsJSCustomElementRegistryCustomcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/bindings/js/JSCustomElementRegistryCustom.cpp (205339 => 205340)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/bindings/js/JSCustomElementRegistryCustom.cpp        2016-09-02 04:41:11 UTC (rev 205339)
+++ trunk/Source/WebCore/bindings/js/JSCustomElementRegistryCustom.cpp        2016-09-02 06:17:17 UTC (rev 205340)
</span><span class="lines">@@ -127,23 +127,20 @@
</span><span class="cx">     QualifiedName name(nullAtom, localName, HTMLNames::xhtmlNamespaceURI);
</span><span class="cx">     auto elementInterface = JSCustomElementInterface::create(name, constructor, globalObject());
</span><span class="cx"> 
</span><del>-    auto* connectedCallback = getCustomElementCallback(state, prototypeObject, Identifier::fromString(&amp;vm, &quot;connectedCallback&quot;));
</del><ins>+    if (auto* connectedCallback = getCustomElementCallback(state, prototypeObject, Identifier::fromString(&amp;vm, &quot;connectedCallback&quot;)))
+        elementInterface-&gt;setConnectedCallback(connectedCallback);
</ins><span class="cx">     if (state.hadException())
</span><span class="cx">         return jsUndefined();
</span><del>-    if (connectedCallback)
-        elementInterface-&gt;setConnectedCallback(connectedCallback);
</del><span class="cx"> 
</span><del>-    auto* disconnectedCallback = getCustomElementCallback(state, prototypeObject, Identifier::fromString(&amp;vm, &quot;disconnectedCallback&quot;));
</del><ins>+    if (auto* disconnectedCallback = getCustomElementCallback(state, prototypeObject, Identifier::fromString(&amp;vm, &quot;disconnectedCallback&quot;)))
+        elementInterface-&gt;setDisconnectedCallback(disconnectedCallback);
</ins><span class="cx">     if (state.hadException())
</span><span class="cx">         return jsUndefined();
</span><del>-    if (disconnectedCallback)
-        elementInterface-&gt;setDisconnectedCallback(disconnectedCallback);
</del><span class="cx"> 
</span><del>-    auto* adoptedCallback = getCustomElementCallback(state, prototypeObject, Identifier::fromString(&amp;vm, &quot;adoptedCallback&quot;));
</del><ins>+    if (auto* adoptedCallback = getCustomElementCallback(state, prototypeObject, Identifier::fromString(&amp;vm, &quot;adoptedCallback&quot;)))
+        elementInterface-&gt;setAdoptedCallback(adoptedCallback);
</ins><span class="cx">     if (state.hadException())
</span><span class="cx">         return jsUndefined();
</span><del>-    if (adoptedCallback)
-        elementInterface-&gt;setAdoptedCallback(adoptedCallback);
</del><span class="cx"> 
</span><span class="cx">     auto* attributeChangedCallback = getCustomElementCallback(state, prototypeObject, Identifier::fromString(&amp;vm, &quot;attributeChangedCallback&quot;));
</span><span class="cx">     if (state.hadException())
</span><span class="lines">@@ -161,14 +158,6 @@
</span><span class="cx"> 
</span><span class="cx">     registry.addElementDefinition(WTFMove(elementInterface));
</span><span class="cx"> 
</span><del>-    // FIXME: 17. Let map be registry's upgrade candidates map.
-    // FIXME: 18. Upgrade a newly-defined element given map and definition.
-
-    auto&amp; promiseMap = registry.promiseMap();
-    auto promise = promiseMap.take(localName);
-    if (promise)
-        promise.value()-&gt;resolve(nullptr);
-
</del><span class="cx">     return jsUndefined();
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCoredomCustomElementReactionQueuecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/dom/CustomElementReactionQueue.cpp (205339 => 205340)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/dom/CustomElementReactionQueue.cpp        2016-09-02 04:41:11 UTC (rev 205339)
+++ trunk/Source/WebCore/dom/CustomElementReactionQueue.cpp        2016-09-02 06:17:17 UTC (rev 205340)
</span><span class="lines">@@ -116,10 +116,30 @@
</span><span class="cx"> 
</span><span class="cx"> void CustomElementReactionQueue::enqueueElementUpgrade(Element&amp; element, JSCustomElementInterface&amp; elementInterface)
</span><span class="cx"> {
</span><ins>+    ASSERT(element.tagQName() == elementInterface.name());
</ins><span class="cx">     if (auto* queue = CustomElementReactionStack::ensureCurrentQueue())
</span><span class="cx">         queue-&gt;m_items.append({CustomElementReactionQueueItem::Type::ElementUpgrade, element, elementInterface});
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void CustomElementReactionQueue::enqueueElementUpgradeIfDefined(Element&amp; element)
+{
+    ASSERT(element.inDocument());
+    ASSERT(element.isUnresolvedCustomElement());
+    auto* window = element.document().domWindow();
+    if (!window)
+        return;
+
+    auto* registry = window-&gt;customElementRegistry();
+    if (!registry)
+        return;
+
+    auto* elementInterface = registry-&gt;findInterface(element);
+    if (!elementInterface)
+        return;
+
+    enqueueElementUpgrade(element, *elementInterface);
+}
+
</ins><span class="cx"> void CustomElementReactionQueue::enqueueConnectedCallbackIfNeeded(Element&amp; element)
</span><span class="cx"> {
</span><span class="cx">     ASSERT(element.isCustomElement());
</span></span></pre></div>
<a id="trunkSourceWebCoredomCustomElementReactionQueueh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/dom/CustomElementReactionQueue.h (205339 => 205340)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/dom/CustomElementReactionQueue.h        2016-09-02 04:41:11 UTC (rev 205339)
+++ trunk/Source/WebCore/dom/CustomElementReactionQueue.h        2016-09-02 06:17:17 UTC (rev 205340)
</span><span class="lines">@@ -46,6 +46,7 @@
</span><span class="cx">     ~CustomElementReactionQueue();
</span><span class="cx"> 
</span><span class="cx">     static void enqueueElementUpgrade(Element&amp;, JSCustomElementInterface&amp;);
</span><ins>+    static void enqueueElementUpgradeIfDefined(Element&amp;);
</ins><span class="cx">     static void enqueueConnectedCallbackIfNeeded(Element&amp;);
</span><span class="cx">     static void enqueueDisconnectedCallbackIfNeeded(Element&amp;);
</span><span class="cx">     static void enqueueAdoptedCallbackIfNeeded(Element&amp;, Document&amp; oldDocument, Document&amp; newDocument);
</span></span></pre></div>
<a id="trunkSourceWebCoredomCustomElementRegistrycpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/dom/CustomElementRegistry.cpp (205339 => 205340)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/dom/CustomElementRegistry.cpp        2016-09-02 04:41:11 UTC (rev 205339)
+++ trunk/Source/WebCore/dom/CustomElementRegistry.cpp        2016-09-02 06:17:17 UTC (rev 205340)
</span><span class="lines">@@ -28,29 +28,47 @@
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(CUSTOM_ELEMENTS)
</span><span class="cx"> 
</span><ins>+#include &quot;CustomElementReactionQueue.h&quot;
+#include &quot;DOMWindow.h&quot;
</ins><span class="cx"> #include &quot;Document.h&quot;
</span><span class="cx"> #include &quot;Element.h&quot;
</span><ins>+#include &quot;ElementTraversal.h&quot;
</ins><span class="cx"> #include &quot;JSCustomElementInterface.h&quot;
</span><span class="cx"> #include &quot;JSDOMPromise.h&quot;
</span><span class="cx"> #include &quot;MathMLNames.h&quot;
</span><span class="cx"> #include &quot;QualifiedName.h&quot;
</span><span class="cx"> #include &quot;SVGNames.h&quot;
</span><ins>+#include &quot;ShadowRoot.h&quot;
</ins><span class="cx"> #include &lt;runtime/JSCJSValueInlines.h&gt;
</span><span class="cx"> #include &lt;wtf/text/AtomicString.h&gt;
</span><span class="cx"> 
</span><span class="cx"> namespace WebCore {
</span><span class="cx"> 
</span><del>-Ref&lt;CustomElementRegistry&gt; CustomElementRegistry::create()
</del><ins>+Ref&lt;CustomElementRegistry&gt; CustomElementRegistry::create(DOMWindow&amp; window)
</ins><span class="cx"> {
</span><del>-    return adoptRef(*new CustomElementRegistry());
</del><ins>+    return adoptRef(*new CustomElementRegistry(window));
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-CustomElementRegistry::CustomElementRegistry()
</del><ins>+CustomElementRegistry::CustomElementRegistry(DOMWindow&amp; window)
+    : m_window(window)
</ins><span class="cx"> { }
</span><span class="cx"> 
</span><span class="cx"> CustomElementRegistry::~CustomElementRegistry()
</span><span class="cx"> { }
</span><span class="cx"> 
</span><ins>+// https://dom.spec.whatwg.org/#concept-shadow-including-tree-order
+static void enqueueUpgradeInShadowIncludingTreeOrder(ContainerNode&amp; node, JSCustomElementInterface&amp; elementInterface)
+{
+    for (Element* element = ElementTraversal::firstWithin(node); element; element = ElementTraversal::next(*element)) {
+        if (element-&gt;isUnresolvedCustomElement() &amp;&amp; element-&gt;tagQName() == elementInterface.name())
+            CustomElementReactionQueue::enqueueElementUpgrade(*element, elementInterface);
+        if (auto* shadowRoot = element-&gt;shadowRoot()) {
+            if (shadowRoot-&gt;mode() != ShadowRoot::Mode::UserAgent)
+                enqueueUpgradeInShadowIncludingTreeOrder(*shadowRoot, elementInterface);
+        }
+    }
+}
+
</ins><span class="cx"> void CustomElementRegistry::addElementDefinition(Ref&lt;JSCustomElementInterface&gt;&amp;&amp; elementInterface)
</span><span class="cx"> {
</span><span class="cx">     AtomicString localName = elementInterface-&gt;name().localName();
</span><span class="lines">@@ -58,35 +76,23 @@
</span><span class="cx">     m_constructorMap.add(elementInterface-&gt;constructor(), elementInterface.ptr());
</span><span class="cx">     m_nameMap.add(localName, elementInterface.copyRef());
</span><span class="cx"> 
</span><del>-    auto candidateList = m_upgradeCandidatesMap.find(localName);
-    if (candidateList == m_upgradeCandidatesMap.end())
-        return;
</del><ins>+    if (auto* document = m_window.document())
+        enqueueUpgradeInShadowIncludingTreeOrder(*document, elementInterface.get());
</ins><span class="cx"> 
</span><del>-    Vector&lt;RefPtr&lt;Element&gt;&gt; list(WTFMove(candidateList-&gt;value));
-
-    m_upgradeCandidatesMap.remove(localName);
-
-    for (auto&amp; candidate : list) {
-        ASSERT(candidate);
-        elementInterface-&gt;upgradeElement(*candidate);
-    }
-
-    // We should not be adding more upgrade candidate for this local name.
-    ASSERT(!m_upgradeCandidatesMap.contains(localName));
</del><ins>+    if (auto promise = m_promiseMap.take(localName))
+        promise.value()-&gt;resolve(nullptr);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-void CustomElementRegistry::addUpgradeCandidate(Element&amp; candidate)
</del><ins>+JSCustomElementInterface* CustomElementRegistry::findInterface(const Element&amp; element) const
</ins><span class="cx"> {
</span><del>-    auto result = m_upgradeCandidatesMap.ensure(candidate.localName(), [] {
-        return Vector&lt;RefPtr&lt;Element&gt;&gt;();
-    });
-    auto&amp; nodeVector = result.iterator-&gt;value;
-    ASSERT(!nodeVector.contains(&amp;candidate));
-    nodeVector.append(&amp;candidate);
</del><ins>+    return findInterface(element.tagQName());
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> JSCustomElementInterface* CustomElementRegistry::findInterface(const QualifiedName&amp; name) const
</span><span class="cx"> {
</span><ins>+    ASSERT(!name.hasPrefix());
+    if (name.namespaceURI() != HTMLNames::xhtmlNamespaceURI)
+        return nullptr;
</ins><span class="cx">     auto it = m_nameMap.find(name.localName());
</span><span class="cx">     return it == m_nameMap.end() || it-&gt;value-&gt;name() != name ? nullptr : const_cast&lt;JSCustomElementInterface*&gt;(it-&gt;value.ptr());
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceWebCoredomCustomElementRegistryh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/dom/CustomElementRegistry.h (205339 => 205340)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/dom/CustomElementRegistry.h        2016-09-02 04:41:11 UTC (rev 205339)
+++ trunk/Source/WebCore/dom/CustomElementRegistry.h        2016-09-02 06:17:17 UTC (rev 205340)
</span><span class="lines">@@ -43,6 +43,7 @@
</span><span class="cx"> namespace WebCore {
</span><span class="cx"> 
</span><span class="cx"> class CustomElementRegistry;
</span><ins>+class DOMWindow;
</ins><span class="cx"> class DeferredWrapper;
</span><span class="cx"> class Element;
</span><span class="cx"> class JSCustomElementInterface;
</span><span class="lines">@@ -50,14 +51,14 @@
</span><span class="cx"> 
</span><span class="cx"> class CustomElementRegistry : public RefCounted&lt;CustomElementRegistry&gt; {
</span><span class="cx"> public:
</span><del>-    static Ref&lt;CustomElementRegistry&gt; create();
</del><ins>+    static Ref&lt;CustomElementRegistry&gt; create(DOMWindow&amp;);
</ins><span class="cx">     ~CustomElementRegistry();
</span><span class="cx"> 
</span><span class="cx">     void addElementDefinition(Ref&lt;JSCustomElementInterface&gt;&amp;&amp;);
</span><del>-    void addUpgradeCandidate(Element&amp;);
</del><span class="cx"> 
</span><span class="cx">     bool&amp; elementDefinitionIsRunning() { return m_elementDefinitionIsRunning; }
</span><span class="cx"> 
</span><ins>+    JSCustomElementInterface* findInterface(const Element&amp;) const;
</ins><span class="cx">     JSCustomElementInterface* findInterface(const QualifiedName&amp;) const;
</span><span class="cx">     JSCustomElementInterface* findInterface(const AtomicString&amp;) const;
</span><span class="cx">     JSCustomElementInterface* findInterface(const JSC::JSObject*) const;
</span><span class="lines">@@ -68,9 +69,9 @@
</span><span class="cx">     HashMap&lt;AtomicString, Ref&lt;DeferredWrapper&gt;&gt;&amp; promiseMap() { return m_promiseMap; }
</span><span class="cx"> 
</span><span class="cx"> private:
</span><del>-    CustomElementRegistry();
</del><ins>+    CustomElementRegistry(DOMWindow&amp;);
</ins><span class="cx"> 
</span><del>-    HashMap&lt;AtomicString, Vector&lt;RefPtr&lt;Element&gt;&gt;&gt; m_upgradeCandidatesMap;
</del><ins>+    DOMWindow&amp; m_window;
</ins><span class="cx">     HashMap&lt;AtomicString, Ref&lt;JSCustomElementInterface&gt;&gt; m_nameMap;
</span><span class="cx">     HashMap&lt;const JSC::JSObject*, JSCustomElementInterface*&gt; m_constructorMap;
</span><span class="cx">     HashMap&lt;AtomicString, Ref&lt;DeferredWrapper&gt;&gt; m_promiseMap;
</span></span></pre></div>
<a id="trunkSourceWebCoredomDocumentcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/dom/Document.cpp (205339 => 205340)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/dom/Document.cpp        2016-09-02 04:41:11 UTC (rev 205339)
+++ trunk/Source/WebCore/dom/Document.cpp        2016-09-02 06:17:17 UTC (rev 205340)
</span><span class="lines">@@ -881,9 +881,9 @@
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(CUSTOM_ELEMENTS)
</span><del>-static ALWAYS_INLINE RefPtr&lt;HTMLElement&gt; createUpgradeCandidateElement(Document&amp; document, DOMWindow* window, const QualifiedName&amp; name)
</del><ins>+static ALWAYS_INLINE RefPtr&lt;HTMLElement&gt; createUpgradeCandidateElement(Document&amp; document, const QualifiedName&amp; name)
</ins><span class="cx"> {
</span><del>-    if (!window || !RuntimeEnabledFeatures::sharedFeatures().customElementsEnabled())
</del><ins>+    if (!RuntimeEnabledFeatures::sharedFeatures().customElementsEnabled())
</ins><span class="cx">         return nullptr;
</span><span class="cx"> 
</span><span class="cx">     if (Document::validateCustomElementName(name.localName()) != CustomElementNameValidationStatus::Valid)
</span><span class="lines">@@ -891,7 +891,6 @@
</span><span class="cx"> 
</span><span class="cx">     auto element = HTMLElement::create(name, document);
</span><span class="cx">     element-&gt;setIsUnresolvedCustomElement();
</span><del>-    window-&gt;ensureCustomElementRegistry().addUpgradeCandidate(element.get());
</del><span class="cx">     return WTFMove(element);
</span><span class="cx"> }
</span><span class="cx"> #endif
</span><span class="lines">@@ -921,7 +920,7 @@
</span><span class="cx">     QualifiedName qualifiedName(nullAtom, localName, xhtmlNamespaceURI);
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(CUSTOM_ELEMENTS)
</span><del>-    if (auto element = createUpgradeCandidateElement(document, window, qualifiedName))
</del><ins>+    if (auto element = createUpgradeCandidateElement(document, qualifiedName))
</ins><span class="cx">         return WTFMove(element);
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="lines">@@ -1099,7 +1098,7 @@
</span><span class="cx">         }
</span><span class="cx">     }
</span><span class="cx">     // FIXME: Should we also check the equality of prefix between the custom element and name?
</span><del>-    if (auto element = createUpgradeCandidateElement(document, window, name))
</del><ins>+    if (auto element = createUpgradeCandidateElement(document, name))
</ins><span class="cx">         return element.releaseNonNull();
</span><span class="cx"> #endif
</span><span class="cx">     return HTMLUnknownElement::create(name, document);
</span></span></pre></div>
<a id="trunkSourceWebCoredomElementcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/dom/Element.cpp (205339 => 205340)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/dom/Element.cpp        2016-09-02 04:41:11 UTC (rev 205339)
+++ trunk/Source/WebCore/dom/Element.cpp        2016-09-02 06:17:17 UTC (rev 205340)
</span><span class="lines">@@ -1606,8 +1606,13 @@
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(CUSTOM_ELEMENTS)
</span><del>-    if (becomeConnected &amp;&amp; UNLIKELY(isCustomElement()))
-        CustomElementReactionQueue::enqueueConnectedCallbackIfNeeded(*this);
</del><ins>+    if (becomeConnected) {
+        if (UNLIKELY(isUnresolvedCustomElement()))
+            CustomElementReactionQueue::enqueueElementUpgradeIfDefined(*this);
+        if (UNLIKELY(isCustomElement()))
+            CustomElementReactionQueue::enqueueConnectedCallbackIfNeeded(*this);
+    }
+
</ins><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="cx">     return InsertionDone;
</span></span></pre></div>
<a id="trunkSourceWebCorehtmlparserHTMLConstructionSitecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/html/parser/HTMLConstructionSite.cpp (205339 => 205340)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/html/parser/HTMLConstructionSite.cpp        2016-09-02 04:41:11 UTC (rev 205339)
+++ trunk/Source/WebCore/html/parser/HTMLConstructionSite.cpp        2016-09-02 06:17:17 UTC (rev 205340)
</span><span class="lines">@@ -678,7 +678,6 @@
</span><span class="cx">         if (window &amp;&amp; Document::validateCustomElementName(localName) == CustomElementNameValidationStatus::Valid) {
</span><span class="cx">             element = HTMLElement::create(qualifiedName, ownerDocument);
</span><span class="cx">             element-&gt;setIsUnresolvedCustomElement();
</span><del>-            window-&gt;ensureCustomElementRegistry().addUpgradeCandidate(*element);
</del><span class="cx">         } else
</span><span class="cx"> #endif
</span><span class="cx">             element = HTMLUnknownElement::create(qualifiedName, ownerDocument);
</span></span></pre></div>
<a id="trunkSourceWebCorepageDOMWindowcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/page/DOMWindow.cpp (205339 => 205340)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/page/DOMWindow.cpp        2016-09-02 04:41:11 UTC (rev 205339)
+++ trunk/Source/WebCore/page/DOMWindow.cpp        2016-09-02 06:17:17 UTC (rev 205340)
</span><span class="lines">@@ -625,7 +625,7 @@
</span><span class="cx"> CustomElementRegistry&amp; DOMWindow::ensureCustomElementRegistry()
</span><span class="cx"> {
</span><span class="cx">     if (!m_customElementRegistry)
</span><del>-        m_customElementRegistry = CustomElementRegistry::create();
</del><ins>+        m_customElementRegistry = CustomElementRegistry::create(*this);
</ins><span class="cx">     return *m_customElementRegistry;
</span><span class="cx"> }
</span><span class="cx"> #endif
</span></span></pre>
</div>
</div>

</body>
</html>