Diff
Modified: trunk/LayoutTests/ChangeLog (205339 => 205340)
--- trunk/LayoutTests/ChangeLog 2016-09-02 04:41:11 UTC (rev 205339)
+++ trunk/LayoutTests/ChangeLog 2016-09-02 06:17:17 UTC (rev 205340)
@@ -1,3 +1,22 @@
+2016-09-01 Ryosuke Niwa <rn...@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):
+
2016-09-01 Gyuyoung Kim <gyuyoung....@webkit.org>
[EFL] Mark failing tests to failure
Modified: trunk/LayoutTests/fast/custom-elements/CustomElementRegistry-expected.txt (205339 => 205340)
--- 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)
@@ -8,6 +8,7 @@
PASS customElements.define must throw a NotSupportedError when element definition is running flag is set
PASS customElements.define must check IsConstructor on the constructor before checking the element definition is running flag
PASS customElements.define must validate the custom element name before checking the element definition is running flag
+PASS customElements.define unset the element definition is running flag before upgrading custom elements
PASS customElements.define must not throw when defining another custom element in a different global object during Get(constructor, "prototype")
PASS Custom Elements: CustomElementRegistry interface
PASS customElements.define must get "prototype" property of the constructor
@@ -23,15 +24,16 @@
PASS customElements.define must rethrow an exception thrown while retrieving Symbol.iterator on observedAttributes
PASS customElements.define must not throw even if "observedAttributes" fails to convert if "attributeChangedCallback" is not defined
PASS customElements.define must define an instantiatable custom element
+PASS customElements.define must upgrade elements in the shadow-including tree order
PASS CustomElementRegistry interface must have get as a method
-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"
+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"
Modified: trunk/LayoutTests/fast/custom-elements/CustomElementRegistry.html (205339 => 205340)
--- 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)
@@ -149,6 +149,31 @@
assert_array_equals(calls, ['prototype'], 'customElements.define must get "prototype"');
}, 'customElements.define must validate the custom element name before checking the element definition is running flag');
+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');
+
(function () {
var testCase = async_test('customElements.define must not throw'
+' when defining another custom element in a different global object during Get(constructor, "prototype")', {timeout: 100});
@@ -384,6 +409,41 @@
}, 'customElements.define must define an instantiatable custom element');
test(function () {
+ 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 () {
assert_true('get' in CustomElementRegistry.prototype, '"get" exists on CustomElementRegistry.prototype');
assert_true('get' in customElements, '"get" exists on window.customElements');
}, 'CustomElementRegistry interface must have get as a method');
@@ -390,7 +450,7 @@
test(function () {
assert_equals(customElements.get('a-b'), undefined);
-}, '"get" must return undefined when the registry does not contain an entry with the given name');
+}, 'customElements.get must return undefined when the registry does not contain an entry with the given name');
test(function () {
assert_equals(customElements.get('html'), undefined);
@@ -398,7 +458,7 @@
assert_equals(customElements.get('div'), undefined);
assert_equals(customElements.get('g'), undefined);
assert_equals(customElements.get('ab'), undefined);
-}, '"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');
+}, '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');
test(function () {
assert_equals(customElements.get('existing-custom-element'), undefined);
@@ -405,15 +465,15 @@
class ExistingCustomElement extends HTMLElement {};
customElements.define('existing-custom-element', ExistingCustomElement);
assert_equals(customElements.get('existing-custom-element'), ExistingCustomElement);
-}, '"get" return the constructor of the entry with the given name when there is a matching entry.');
+}, 'customElements.get return the constructor of the entry with the given name when there is a matching entry.');
test(function () {
assert_true(customElements.whenDefined('some-name') instanceof Promise);
-}, '"whenDefined" must return a promise for a valid custom element name');
+}, 'customElements.whenDefined must return a promise for a valid custom element name');
test(function () {
assert_equals(customElements.whenDefined('some-name'), customElements.whenDefined('some-name'));
-}, '"whenDefined" must return the same promise each time invoked for a valid custom element name which has not been defined');
+}, 'customElements.whenDefined must return the same promise each time invoked for a valid custom element name which has not been defined');
promise_test(function () {
var resolved = false;
@@ -423,7 +483,7 @@
assert_false(resolved, 'The promise returned by "whenDefined" must not be resolved until a custom element is defined');
assert_false(rejected, 'The promise returned by "whenDefined" must not be rejected until a custom element is defined');
});
-}, '"whenDefined" must return an unresolved promise when the registry does not contain the entry with the given name')
+}, 'customElements.whenDefined must return an unresolved promise when the registry does not contain the entry with the given name')
promise_test(function () {
var promise = customElements.whenDefined('badname');
@@ -436,7 +496,7 @@
assert_false('resolved' in promise, 'The promise returned by "whenDefined" must be resolved when a custom element is defined');
assert_true('rejected' in promise, 'The promise returned by "whenDefined" must not be rejected when a custom element is defined');
});
-}, '"whenDefined" must return a rejected promise when the given name is not a valid custom element name');
+}, 'customElements.whenDefined must return a rejected promise when the given name is not a valid custom element name');
promise_test(function () {
customElements.define('preexisting-custom-element', class extends HTMLElement { });
@@ -453,7 +513,7 @@
'The promise returned by "whenDefined" must be resolved with "undefined" when a custom element is defined');
assert_false('rejected' in promise, 'The promise returned by "whenDefined" must not be rejected when a custom element is defined');
});
-}, '"whenDefined" must return a resolved promise when the registry contains the entry with the given name');
+}, 'customElements.whenDefined must return a resolved promise when the registry contains the entry with the given name');
promise_test(function () {
class AnotherExistingCustomElement extends HTMLElement {};
@@ -479,7 +539,7 @@
assert_equals(promise2.resolved, undefined, 'The promise returned by "whenDefined" must be resolved with "undefined" when a custom element is defined');
assert_false('rejected' in promise2, 'The promise returned by "whenDefined" must not be rejected when a custom element is defined');
});
-}, '"whenDefined" must return a new resolved promise each time invoked when the registry contains the entry with the given name');
+}, 'customElements.whenDefined must return a new resolved promise each time invoked when the registry contains the entry with the given name');
promise_test(function () {
var promise = customElements.whenDefined('element-defined-after-whendefined');
@@ -514,7 +574,7 @@
'The promise returned by "whenDefined" must be resolved with "undefined" when a custom element is defined');
assert_false('rejected' in promiseAfterDefine, 'The promise returned by "whenDefined" must not be rejected when a custom element is defined');
});
-}, 'A promise returned by "whenDefined" must be resolved by "define"');
+}, 'A promise returned by customElements.whenDefined must be resolved by "define"');
</script>
</body>
Modified: trunk/LayoutTests/fast/custom-elements/defined-pseudo-class-expected.txt (205339 => 205340)
--- 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)
@@ -1,7 +1,9 @@
PASS The defined flag of a custom element must not be set if a custom element has not been upgraded yet
+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
PASS The defined flag of a custom element must be set when a custom element is successfully upgraded
PASS The defined flag of a custom element must be set if there is a matching definition
+PASS The defined flag of an upgraded custom element must be set
PASS The defined flag of a custom element created by HTML parser must be unset if there is no matching definition
PASS The defined flag of a custom element created by HTML parser must be set if there is a matching definition
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
Modified: trunk/LayoutTests/fast/custom-elements/defined-pseudo-class.html (205339 => 205340)
--- 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)
@@ -28,6 +28,11 @@
customElements.define('my-element', MyElement);
test(function () {
+ 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);
assert_true(upgradeCandidate.matches(':defined'));
assert_false(matchInsideConstructor, 'Upgrading a custom element must set defined flag after invoking the constructor');
}, 'The defined flag of a custom element must be set when a custom element is successfully upgraded');
@@ -38,6 +43,12 @@
assert_false(matchInsideConstructor, 'Creating a custom element must set defined flag after invoking the constructor');
}, 'The defined flag of a custom element must be set if there is a matching definition');
+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');
+
document.write('<my-other-element></my-other-element>');
test(function () {
Added: trunk/LayoutTests/fast/custom-elements/enqueue-custom-element-upgrade-reaction-expected.txt (0 => 205340)
--- 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)
@@ -0,0 +1,27 @@
+
+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
+
Added: trunk/LayoutTests/fast/custom-elements/enqueue-custom-element-upgrade-reaction.html (0 => 205340)
--- 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)
@@ -0,0 +1,189 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>Custom Elements: Enqueue a custom element upgrade reaction</title>
+<meta name="author" title="Ryosuke Niwa" href=""
+<meta name="assert" content="Enqueue a custom element upgrade reaction must upgrade a custom element">
+<link rel="help" href=""
+<link rel="help" href=""
+<link rel="help" href=""
+<script src=""
+<script src=""
+<link rel='stylesheet' href=''>
+<script src=""
+</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>
Modified: trunk/LayoutTests/fast/custom-elements/resources/document-types.js (205339 => 205340)
--- 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)
@@ -3,6 +3,7 @@
name: 'document',
create: function () { return Promise.resolve(document); },
isOwner: true,
+ hasBrowsingContext: true,
},
{
name: 'document of a template element',
@@ -14,7 +15,8 @@
doc.appendChild(doc.createElement('html'));
resolve(doc);
});
- }
+ },
+ hasBrowsingContext: false,
},
{
name: 'new document',
@@ -24,7 +26,8 @@
doc.appendChild(doc.createElement('html'));
resolve(doc);
});
- }
+ },
+ hasBrowsingContext: false,
},
{
name: 'cloned document',
@@ -34,19 +37,22 @@
doc.appendChild(doc.createElement('html'));
resolve(doc);
});
- }
+ },
+ hasBrowsingContext: false,
},
{
name: 'document created by createHTMLDocument',
create: function () {
return Promise.resolve(document.implementation.createHTMLDocument());
- }
+ },
+ hasBrowsingContext: false,
},
{
name: 'HTML document created by createDocument',
create: function () {
return Promise.resolve(document.implementation.createDocument('http://www.w3.org/1999/xhtml', 'html', null));
- }
+ },
+ hasBrowsingContext: false,
},
{
name: 'document in an iframe',
@@ -57,7 +63,8 @@
iframe._onerror_ = function () { reject('Failed to load an empty iframe'); }
document.body.appendChild(iframe);
});
- }
+ },
+ hasBrowsingContext: true,
},
{
name: 'HTML document fetched by XHR',
@@ -70,6 +77,7 @@
xhr._onerror_ = function () { reject('Failed to fetch the document'); }
xhr.send();
});
- }
+ },
+ hasBrowsingContext: false,
}
];
\ No newline at end of file
Modified: trunk/Source/WebCore/ChangeLog (205339 => 205340)
--- 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)
@@ -1,3 +1,59 @@
+2016-09-01 Ryosuke Niwa <rn...@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):
+
2016-09-01 Yusuke Suzuki <utatane....@gmail.com>
Add toJS for JSC::PrivateName
Modified: trunk/Source/WebCore/bindings/js/JSCustomElementInterface.cpp (205339 => 205340)
--- 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)
@@ -104,6 +104,7 @@
void JSCustomElementInterface::upgradeElement(Element& element)
{
+ ASSERT(element.tagQName() == name());
ASSERT(element.isUnresolvedCustomElement());
if (!canInvokeCallback())
return;
Modified: trunk/Source/WebCore/bindings/js/JSCustomElementRegistryCustom.cpp (205339 => 205340)
--- 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)
@@ -127,23 +127,20 @@
QualifiedName name(nullAtom, localName, HTMLNames::xhtmlNamespaceURI);
auto elementInterface = JSCustomElementInterface::create(name, constructor, globalObject());
- auto* connectedCallback = getCustomElementCallback(state, prototypeObject, Identifier::fromString(&vm, "connectedCallback"));
+ if (auto* connectedCallback = getCustomElementCallback(state, prototypeObject, Identifier::fromString(&vm, "connectedCallback")))
+ elementInterface->setConnectedCallback(connectedCallback);
if (state.hadException())
return jsUndefined();
- if (connectedCallback)
- elementInterface->setConnectedCallback(connectedCallback);
- auto* disconnectedCallback = getCustomElementCallback(state, prototypeObject, Identifier::fromString(&vm, "disconnectedCallback"));
+ if (auto* disconnectedCallback = getCustomElementCallback(state, prototypeObject, Identifier::fromString(&vm, "disconnectedCallback")))
+ elementInterface->setDisconnectedCallback(disconnectedCallback);
if (state.hadException())
return jsUndefined();
- if (disconnectedCallback)
- elementInterface->setDisconnectedCallback(disconnectedCallback);
- auto* adoptedCallback = getCustomElementCallback(state, prototypeObject, Identifier::fromString(&vm, "adoptedCallback"));
+ if (auto* adoptedCallback = getCustomElementCallback(state, prototypeObject, Identifier::fromString(&vm, "adoptedCallback")))
+ elementInterface->setAdoptedCallback(adoptedCallback);
if (state.hadException())
return jsUndefined();
- if (adoptedCallback)
- elementInterface->setAdoptedCallback(adoptedCallback);
auto* attributeChangedCallback = getCustomElementCallback(state, prototypeObject, Identifier::fromString(&vm, "attributeChangedCallback"));
if (state.hadException())
@@ -161,14 +158,6 @@
registry.addElementDefinition(WTFMove(elementInterface));
- // 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);
-
return jsUndefined();
}
Modified: trunk/Source/WebCore/dom/CustomElementReactionQueue.cpp (205339 => 205340)
--- 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)
@@ -116,10 +116,30 @@
void CustomElementReactionQueue::enqueueElementUpgrade(Element& element, JSCustomElementInterface& elementInterface)
{
+ ASSERT(element.tagQName() == elementInterface.name());
if (auto* queue = CustomElementReactionStack::ensureCurrentQueue())
queue->m_items.append({CustomElementReactionQueueItem::Type::ElementUpgrade, element, elementInterface});
}
+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);
+}
+
void CustomElementReactionQueue::enqueueConnectedCallbackIfNeeded(Element& element)
{
ASSERT(element.isCustomElement());
Modified: trunk/Source/WebCore/dom/CustomElementReactionQueue.h (205339 => 205340)
--- 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)
@@ -46,6 +46,7 @@
~CustomElementReactionQueue();
static void enqueueElementUpgrade(Element&, JSCustomElementInterface&);
+ static void enqueueElementUpgradeIfDefined(Element&);
static void enqueueConnectedCallbackIfNeeded(Element&);
static void enqueueDisconnectedCallbackIfNeeded(Element&);
static void enqueueAdoptedCallbackIfNeeded(Element&, Document& oldDocument, Document& newDocument);
Modified: trunk/Source/WebCore/dom/CustomElementRegistry.cpp (205339 => 205340)
--- 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)
@@ -28,29 +28,47 @@
#if ENABLE(CUSTOM_ELEMENTS)
+#include "CustomElementReactionQueue.h"
+#include "DOMWindow.h"
#include "Document.h"
#include "Element.h"
+#include "ElementTraversal.h"
#include "JSCustomElementInterface.h"
#include "JSDOMPromise.h"
#include "MathMLNames.h"
#include "QualifiedName.h"
#include "SVGNames.h"
+#include "ShadowRoot.h"
#include <runtime/JSCJSValueInlines.h>
#include <wtf/text/AtomicString.h>
namespace WebCore {
-Ref<CustomElementRegistry> CustomElementRegistry::create()
+Ref<CustomElementRegistry> CustomElementRegistry::create(DOMWindow& window)
{
- return adoptRef(*new CustomElementRegistry());
+ return adoptRef(*new CustomElementRegistry(window));
}
-CustomElementRegistry::CustomElementRegistry()
+CustomElementRegistry::CustomElementRegistry(DOMWindow& window)
+ : m_window(window)
{ }
CustomElementRegistry::~CustomElementRegistry()
{ }
+// 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);
+ }
+ }
+}
+
void CustomElementRegistry::addElementDefinition(Ref<JSCustomElementInterface>&& elementInterface)
{
AtomicString localName = elementInterface->name().localName();
@@ -58,35 +76,23 @@
m_constructorMap.add(elementInterface->constructor(), elementInterface.ptr());
m_nameMap.add(localName, elementInterface.copyRef());
- auto candidateList = m_upgradeCandidatesMap.find(localName);
- if (candidateList == m_upgradeCandidatesMap.end())
- return;
+ if (auto* document = m_window.document())
+ enqueueUpgradeInShadowIncludingTreeOrder(*document, elementInterface.get());
- 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));
+ if (auto promise = m_promiseMap.take(localName))
+ promise.value()->resolve(nullptr);
}
-void CustomElementRegistry::addUpgradeCandidate(Element& candidate)
+JSCustomElementInterface* CustomElementRegistry::findInterface(const Element& element) const
{
- auto result = m_upgradeCandidatesMap.ensure(candidate.localName(), [] {
- return Vector<RefPtr<Element>>();
- });
- auto& nodeVector = result.iterator->value;
- ASSERT(!nodeVector.contains(&candidate));
- nodeVector.append(&candidate);
+ return findInterface(element.tagQName());
}
JSCustomElementInterface* CustomElementRegistry::findInterface(const QualifiedName& name) const
{
+ ASSERT(!name.hasPrefix());
+ if (name.namespaceURI() != HTMLNames::xhtmlNamespaceURI)
+ return nullptr;
auto it = m_nameMap.find(name.localName());
return it == m_nameMap.end() || it->value->name() != name ? nullptr : const_cast<JSCustomElementInterface*>(it->value.ptr());
}
Modified: trunk/Source/WebCore/dom/CustomElementRegistry.h (205339 => 205340)
--- 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)
@@ -43,6 +43,7 @@
namespace WebCore {
class CustomElementRegistry;
+class DOMWindow;
class DeferredWrapper;
class Element;
class JSCustomElementInterface;
@@ -50,14 +51,14 @@
class CustomElementRegistry : public RefCounted<CustomElementRegistry> {
public:
- static Ref<CustomElementRegistry> create();
+ static Ref<CustomElementRegistry> create(DOMWindow&);
~CustomElementRegistry();
void addElementDefinition(Ref<JSCustomElementInterface>&&);
- void addUpgradeCandidate(Element&);
bool& elementDefinitionIsRunning() { return m_elementDefinitionIsRunning; }
+ JSCustomElementInterface* findInterface(const Element&) const;
JSCustomElementInterface* findInterface(const QualifiedName&) const;
JSCustomElementInterface* findInterface(const AtomicString&) const;
JSCustomElementInterface* findInterface(const JSC::JSObject*) const;
@@ -68,9 +69,9 @@
HashMap<AtomicString, Ref<DeferredWrapper>>& promiseMap() { return m_promiseMap; }
private:
- CustomElementRegistry();
+ CustomElementRegistry(DOMWindow&);
- HashMap<AtomicString, Vector<RefPtr<Element>>> m_upgradeCandidatesMap;
+ DOMWindow& m_window;
HashMap<AtomicString, Ref<JSCustomElementInterface>> m_nameMap;
HashMap<const JSC::JSObject*, JSCustomElementInterface*> m_constructorMap;
HashMap<AtomicString, Ref<DeferredWrapper>> m_promiseMap;
Modified: trunk/Source/WebCore/dom/Document.cpp (205339 => 205340)
--- 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)
@@ -881,9 +881,9 @@
}
#if ENABLE(CUSTOM_ELEMENTS)
-static ALWAYS_INLINE RefPtr<HTMLElement> createUpgradeCandidateElement(Document& document, DOMWindow* window, const QualifiedName& name)
+static ALWAYS_INLINE RefPtr<HTMLElement> createUpgradeCandidateElement(Document& document, const QualifiedName& name)
{
- if (!window || !RuntimeEnabledFeatures::sharedFeatures().customElementsEnabled())
+ if (!RuntimeEnabledFeatures::sharedFeatures().customElementsEnabled())
return nullptr;
if (Document::validateCustomElementName(name.localName()) != CustomElementNameValidationStatus::Valid)
@@ -891,7 +891,6 @@
auto element = HTMLElement::create(name, document);
element->setIsUnresolvedCustomElement();
- window->ensureCustomElementRegistry().addUpgradeCandidate(element.get());
return WTFMove(element);
}
#endif
@@ -921,7 +920,7 @@
QualifiedName qualifiedName(nullAtom, localName, xhtmlNamespaceURI);
#if ENABLE(CUSTOM_ELEMENTS)
- if (auto element = createUpgradeCandidateElement(document, window, qualifiedName))
+ if (auto element = createUpgradeCandidateElement(document, qualifiedName))
return WTFMove(element);
#endif
@@ -1099,7 +1098,7 @@
}
}
// FIXME: Should we also check the equality of prefix between the custom element and name?
- if (auto element = createUpgradeCandidateElement(document, window, name))
+ if (auto element = createUpgradeCandidateElement(document, name))
return element.releaseNonNull();
#endif
return HTMLUnknownElement::create(name, document);
Modified: trunk/Source/WebCore/dom/Element.cpp (205339 => 205340)
--- 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)
@@ -1606,8 +1606,13 @@
}
#if ENABLE(CUSTOM_ELEMENTS)
- if (becomeConnected && UNLIKELY(isCustomElement()))
- CustomElementReactionQueue::enqueueConnectedCallbackIfNeeded(*this);
+ if (becomeConnected) {
+ if (UNLIKELY(isUnresolvedCustomElement()))
+ CustomElementReactionQueue::enqueueElementUpgradeIfDefined(*this);
+ if (UNLIKELY(isCustomElement()))
+ CustomElementReactionQueue::enqueueConnectedCallbackIfNeeded(*this);
+ }
+
#endif
return InsertionDone;
Modified: trunk/Source/WebCore/html/parser/HTMLConstructionSite.cpp (205339 => 205340)
--- 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)
@@ -678,7 +678,6 @@
if (window && Document::validateCustomElementName(localName) == CustomElementNameValidationStatus::Valid) {
element = HTMLElement::create(qualifiedName, ownerDocument);
element->setIsUnresolvedCustomElement();
- window->ensureCustomElementRegistry().addUpgradeCandidate(*element);
} else
#endif
element = HTMLUnknownElement::create(qualifiedName, ownerDocument);
Modified: trunk/Source/WebCore/page/DOMWindow.cpp (205339 => 205340)
--- 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)
@@ -625,7 +625,7 @@
CustomElementRegistry& DOMWindow::ensureCustomElementRegistry()
{
if (!m_customElementRegistry)
- m_customElementRegistry = CustomElementRegistry::create();
+ m_customElementRegistry = CustomElementRegistry::create(*this);
return *m_customElementRegistry;
}
#endif