<!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 "whenDefined" 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 "get" and "whenDefined" test cases consistent
with ones for "define".
* 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 <rniwa@webkit.org>
+
+ 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 "get" and "whenDefined" test cases consistent
+ with ones for "define".
+ * 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 <gyuyoung.kim@webkit.org>
</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, "prototype")
</span><span class="cx"> PASS Custom Elements: CustomElementRegistry interface
</span><span class="cx"> PASS customElements.define must get "prototype" 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 "observedAttributes" fails to convert if "attributeChangedCallback" 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 "get" must return undefined when the registry does not contain an entry with the given name
-PASS "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 "get" return the constructor of the entry with the given name when there is a matching entry.
-PASS "whenDefined" must return a promise for a valid custom element name
-PASS "whenDefined" must return the same promise each time invoked for a valid custom element name which has not been defined
-PASS "whenDefined" must return an unresolved promise when the registry does not contain the entry with the given name
-PASS "whenDefined" must return a rejected promise when the given name is not a valid custom element name
-PASS "whenDefined" must return a resolved promise when the registry contains the entry with the given name
-PASS "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 "whenDefined" must be resolved by "define"
</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 "define"
</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 "prototype"');
</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, "prototype")', {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, '"get" exists on CustomElementRegistry.prototype');
</span><span class="cx"> assert_true('get' in customElements, '"get" 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>-}, '"get" 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>-}, '"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');
</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>-}, '"get" 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>-}, '"whenDefined" 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>-}, '"whenDefined" 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 "whenDefined" must not be resolved until a custom element is defined');
</span><span class="cx"> assert_false(rejected, 'The promise returned by "whenDefined" must not be rejected until a custom element is defined');
</span><span class="cx"> });
</span><del>-}, '"whenDefined" 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 "whenDefined" must be resolved when a custom element is defined');
</span><span class="cx"> assert_true('rejected' in promise, 'The promise returned by "whenDefined" must not be rejected when a custom element is defined');
</span><span class="cx"> });
</span><del>-}, '"whenDefined" 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 "whenDefined" must be resolved with "undefined" when a custom element is defined');
</span><span class="cx"> assert_false('rejected' in promise, 'The promise returned by "whenDefined" must not be rejected when a custom element is defined');
</span><span class="cx"> });
</span><del>-}, '"whenDefined" 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 "whenDefined" must be resolved with "undefined" when a custom element is defined');
</span><span class="cx"> assert_false('rejected' in promise2, 'The promise returned by "whenDefined" must not be rejected when a custom element is defined');
</span><span class="cx"> });
</span><del>-}, '"whenDefined" 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 "whenDefined" must be resolved with "undefined" when a custom element is defined');
</span><span class="cx"> assert_false('rejected' in promiseAfterDefine, 'The promise returned by "whenDefined" must not be rejected when a custom element is defined');
</span><span class="cx"> });
</span><del>-}, 'A promise returned by "whenDefined" must be resolved by "define"');
</del><ins>+}, 'A promise returned by customElements.whenDefined must be resolved by "define"');
</ins><span class="cx">
</span><span class="cx"> </script>
</span><span class="cx"> </body>
</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('<my-other-element></my-other-element>');
</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 "define" 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 "define" 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>+<!DOCTYPE html>
+<html>
+<head>
+<title>Custom Elements: Enqueue a custom element upgrade reaction</title>
+<meta name="author" title="Ryosuke Niwa" href="mailto:rniwa@webkit.org">
+<meta name="assert" content="Enqueue a custom element upgrade reaction must upgrade a custom element">
+<link rel="help" href="https://dom.spec.whatwg.org/#concept-create-element">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/scripting.html#concept-try-upgrade">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/scripting.html#enqueue-a-custom-element-upgrade-reaction">
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
+<link rel='stylesheet' href='../../resources/testharness.css'>
+<script src="resources/document-types.js"></script>
+</head>
+<body>
+<div id="log"></div>
+<script>
+
+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 && !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, '"define" 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, '"define" 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 && 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);
+
+ });
+ }, '"define" 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);
+ });
+ }, '"define" 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');
+
+});
+
+</script>
+</body>
+</html>
</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 <rniwa@webkit.org>
+
+ 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 "whenDefined" 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 <utatane.tea@gmail.com>
</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& 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(&vm, "connectedCallback"));
</del><ins>+ if (auto* connectedCallback = getCustomElementCallback(state, prototypeObject, Identifier::fromString(&vm, "connectedCallback")))
+ elementInterface->setConnectedCallback(connectedCallback);
</ins><span class="cx"> if (state.hadException())
</span><span class="cx"> return jsUndefined();
</span><del>- if (connectedCallback)
- elementInterface->setConnectedCallback(connectedCallback);
</del><span class="cx">
</span><del>- auto* disconnectedCallback = getCustomElementCallback(state, prototypeObject, Identifier::fromString(&vm, "disconnectedCallback"));
</del><ins>+ if (auto* disconnectedCallback = getCustomElementCallback(state, prototypeObject, Identifier::fromString(&vm, "disconnectedCallback")))
+ elementInterface->setDisconnectedCallback(disconnectedCallback);
</ins><span class="cx"> if (state.hadException())
</span><span class="cx"> return jsUndefined();
</span><del>- if (disconnectedCallback)
- elementInterface->setDisconnectedCallback(disconnectedCallback);
</del><span class="cx">
</span><del>- auto* adoptedCallback = getCustomElementCallback(state, prototypeObject, Identifier::fromString(&vm, "adoptedCallback"));
</del><ins>+ if (auto* adoptedCallback = getCustomElementCallback(state, prototypeObject, Identifier::fromString(&vm, "adoptedCallback")))
+ elementInterface->setAdoptedCallback(adoptedCallback);
</ins><span class="cx"> if (state.hadException())
</span><span class="cx"> return jsUndefined();
</span><del>- if (adoptedCallback)
- elementInterface->setAdoptedCallback(adoptedCallback);
</del><span class="cx">
</span><span class="cx"> auto* attributeChangedCallback = getCustomElementCallback(state, prototypeObject, Identifier::fromString(&vm, "attributeChangedCallback"));
</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& promiseMap = registry.promiseMap();
- auto promise = promiseMap.take(localName);
- if (promise)
- promise.value()->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& element, JSCustomElementInterface& 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->m_items.append({CustomElementReactionQueueItem::Type::ElementUpgrade, element, elementInterface});
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+void CustomElementReactionQueue::enqueueElementUpgradeIfDefined(Element& element)
+{
+ ASSERT(element.inDocument());
+ ASSERT(element.isUnresolvedCustomElement());
+ auto* window = element.document().domWindow();
+ if (!window)
+ return;
+
+ auto* registry = window->customElementRegistry();
+ if (!registry)
+ return;
+
+ auto* elementInterface = registry->findInterface(element);
+ if (!elementInterface)
+ return;
+
+ enqueueElementUpgrade(element, *elementInterface);
+}
+
</ins><span class="cx"> void CustomElementReactionQueue::enqueueConnectedCallbackIfNeeded(Element& 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&, JSCustomElementInterface&);
</span><ins>+ static void enqueueElementUpgradeIfDefined(Element&);
</ins><span class="cx"> static void enqueueConnectedCallbackIfNeeded(Element&);
</span><span class="cx"> static void enqueueDisconnectedCallbackIfNeeded(Element&);
</span><span class="cx"> static void enqueueAdoptedCallbackIfNeeded(Element&, Document& oldDocument, Document& 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 "CustomElementReactionQueue.h"
+#include "DOMWindow.h"
</ins><span class="cx"> #include "Document.h"
</span><span class="cx"> #include "Element.h"
</span><ins>+#include "ElementTraversal.h"
</ins><span class="cx"> #include "JSCustomElementInterface.h"
</span><span class="cx"> #include "JSDOMPromise.h"
</span><span class="cx"> #include "MathMLNames.h"
</span><span class="cx"> #include "QualifiedName.h"
</span><span class="cx"> #include "SVGNames.h"
</span><ins>+#include "ShadowRoot.h"
</ins><span class="cx"> #include <runtime/JSCJSValueInlines.h>
</span><span class="cx"> #include <wtf/text/AtomicString.h>
</span><span class="cx">
</span><span class="cx"> namespace WebCore {
</span><span class="cx">
</span><del>-Ref<CustomElementRegistry> CustomElementRegistry::create()
</del><ins>+Ref<CustomElementRegistry> CustomElementRegistry::create(DOMWindow& 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& 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& node, JSCustomElementInterface& elementInterface)
+{
+ for (Element* element = ElementTraversal::firstWithin(node); element; element = ElementTraversal::next(*element)) {
+ if (element->isUnresolvedCustomElement() && element->tagQName() == elementInterface.name())
+ CustomElementReactionQueue::enqueueElementUpgrade(*element, elementInterface);
+ if (auto* shadowRoot = element->shadowRoot()) {
+ if (shadowRoot->mode() != ShadowRoot::Mode::UserAgent)
+ enqueueUpgradeInShadowIncludingTreeOrder(*shadowRoot, elementInterface);
+ }
+ }
+}
+
</ins><span class="cx"> void CustomElementRegistry::addElementDefinition(Ref<JSCustomElementInterface>&& elementInterface)
</span><span class="cx"> {
</span><span class="cx"> AtomicString localName = elementInterface->name().localName();
</span><span class="lines">@@ -58,35 +76,23 @@
</span><span class="cx"> m_constructorMap.add(elementInterface->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<RefPtr<Element>> list(WTFMove(candidateList->value));
-
- m_upgradeCandidatesMap.remove(localName);
-
- for (auto& candidate : list) {
- ASSERT(candidate);
- elementInterface->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()->resolve(nullptr);
</ins><span class="cx"> }
</span><span class="cx">
</span><del>-void CustomElementRegistry::addUpgradeCandidate(Element& candidate)
</del><ins>+JSCustomElementInterface* CustomElementRegistry::findInterface(const Element& element) const
</ins><span class="cx"> {
</span><del>- auto result = m_upgradeCandidatesMap.ensure(candidate.localName(), [] {
- return Vector<RefPtr<Element>>();
- });
- auto& nodeVector = result.iterator->value;
- ASSERT(!nodeVector.contains(&candidate));
- nodeVector.append(&candidate);
</del><ins>+ return findInterface(element.tagQName());
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> JSCustomElementInterface* CustomElementRegistry::findInterface(const QualifiedName& 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->value->name() != name ? nullptr : const_cast<JSCustomElementInterface*>(it->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<CustomElementRegistry> {
</span><span class="cx"> public:
</span><del>- static Ref<CustomElementRegistry> create();
</del><ins>+ static Ref<CustomElementRegistry> create(DOMWindow&);
</ins><span class="cx"> ~CustomElementRegistry();
</span><span class="cx">
</span><span class="cx"> void addElementDefinition(Ref<JSCustomElementInterface>&&);
</span><del>- void addUpgradeCandidate(Element&);
</del><span class="cx">
</span><span class="cx"> bool& elementDefinitionIsRunning() { return m_elementDefinitionIsRunning; }
</span><span class="cx">
</span><ins>+ JSCustomElementInterface* findInterface(const Element&) const;
</ins><span class="cx"> JSCustomElementInterface* findInterface(const QualifiedName&) const;
</span><span class="cx"> JSCustomElementInterface* findInterface(const AtomicString&) const;
</span><span class="cx"> JSCustomElementInterface* findInterface(const JSC::JSObject*) const;
</span><span class="lines">@@ -68,9 +69,9 @@
</span><span class="cx"> HashMap<AtomicString, Ref<DeferredWrapper>>& promiseMap() { return m_promiseMap; }
</span><span class="cx">
</span><span class="cx"> private:
</span><del>- CustomElementRegistry();
</del><ins>+ CustomElementRegistry(DOMWindow&);
</ins><span class="cx">
</span><del>- HashMap<AtomicString, Vector<RefPtr<Element>>> m_upgradeCandidatesMap;
</del><ins>+ DOMWindow& m_window;
</ins><span class="cx"> HashMap<AtomicString, Ref<JSCustomElementInterface>> m_nameMap;
</span><span class="cx"> HashMap<const JSC::JSObject*, JSCustomElementInterface*> m_constructorMap;
</span><span class="cx"> HashMap<AtomicString, Ref<DeferredWrapper>> 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<HTMLElement> createUpgradeCandidateElement(Document& document, DOMWindow* window, const QualifiedName& name)
</del><ins>+static ALWAYS_INLINE RefPtr<HTMLElement> createUpgradeCandidateElement(Document& document, const QualifiedName& 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->setIsUnresolvedCustomElement();
</span><del>- window->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 && 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 && Document::validateCustomElementName(localName) == CustomElementNameValidationStatus::Valid) {
</span><span class="cx"> element = HTMLElement::create(qualifiedName, ownerDocument);
</span><span class="cx"> element->setIsUnresolvedCustomElement();
</span><del>- window->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& 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>