Diff
Modified: trunk/LayoutTests/ChangeLog (205059 => 205060)
--- trunk/LayoutTests/ChangeLog 2016-08-26 23:47:40 UTC (rev 205059)
+++ trunk/LayoutTests/ChangeLog 2016-08-27 00:04:08 UTC (rev 205060)
@@ -1,3 +1,21 @@
+2016-08-23 Ryosuke Niwa <[email protected]>
+
+ Adopted custom element's callbacks should continue to work
+ https://bugs.webkit.org/show_bug.cgi?id=161065
+
+ Reviewed by Andreas Kling.
+
+ Added test cases for adopting custom elements into various kinds of documents.
+
+ * fast/custom-elements/connected-callbacks-expected.txt:
+ * fast/custom-elements/connected-callbacks.html:
+ * fast/custom-elements/defined-pseudo-class-expected.txt:
+ * fast/custom-elements/defined-pseudo-class.html:
+ * fast/custom-elements/disconnected-callbacks-expected.txt:
+ * fast/custom-elements/disconnected-callbacks.html:
+ * fast/custom-elements/resources/document-types.js: Added.
+ * fast/custom-elements/resources/empty-html-document.html: Added.
+
2016-08-26 Ryan Haddad <[email protected]>
Marking webgl/max-active-contexts-webglcontextlost-prevent-default.html as flaky on mac-wk1.
Modified: trunk/LayoutTests/fast/custom-elements/connected-callbacks-expected.txt (205059 => 205060)
--- trunk/LayoutTests/fast/custom-elements/connected-callbacks-expected.txt 2016-08-26 23:47:40 UTC (rev 205059)
+++ trunk/LayoutTests/fast/custom-elements/connected-callbacks-expected.txt 2016-08-27 00:04:08 UTC (rev 205060)
@@ -1,10 +1,43 @@
PASS Inserting a custom element into a document must enqueue and invoke connectedCallback
-PASS Inserting a custom element into a detached node must not enqueue and invoke connectedCallback
-FAIL Inserting a custom element into a window-less document must enqueue and invoke connectedCallback assert_array_equals: lengths differ, expected 2 got 0
-PASS Inserting an ancestor of a custom element into a document must enqueue and invoke connectedCallback
-FAIL Inserting an ancestor of custom element into a window-less document must enqueue and invoke connectedCallback assert_array_equals: lengths differ, expected 2 got 0
-PASS Inserting a custom element into a connected shadow tree must enqueue and invoke connectedCallback
-PASS Inserting the shadow host of a shadow tree with a custom element into a document must enqueue and invoke connectedCallback
-PASS Inserting a custom element into a detached shadow tree must not enqueue and invoke connectedCallback
+PASS Inserting an ancestor of custom element into a document must enqueue and invoke connectedCallback
+PASS Inserting a custom element into a shadow tree in a document must enqueue and invoke connectedCallback
+PASS Inserting the shadow host of a custom element into a document must enqueue and invoke connectedCallback
+PASS Inserting a custom element into a detached shadow tree that belongs to a document must not enqueue and invoke connectedCallback
+PASS Inserting a custom element into a document of a template element must enqueue and invoke connectedCallback
+PASS Inserting an ancestor of custom element into a document of a template element must enqueue and invoke connectedCallback
+PASS Inserting a custom element into a shadow tree in a document of a template element must enqueue and invoke connectedCallback
+PASS Inserting the shadow host of a custom element into a document of a template element must enqueue and invoke connectedCallback
+PASS Inserting a custom element into a detached shadow tree that belongs to a document of a template element must not enqueue and invoke connectedCallback
+PASS Inserting a custom element into a new document must enqueue and invoke connectedCallback
+PASS Inserting an ancestor of custom element into a new document must enqueue and invoke connectedCallback
+PASS Inserting a custom element into a shadow tree in a new document must enqueue and invoke connectedCallback
+PASS Inserting the shadow host of a custom element into a new document must enqueue and invoke connectedCallback
+PASS Inserting a custom element into a detached shadow tree that belongs to a new document must not enqueue and invoke connectedCallback
+PASS Inserting a custom element into a cloned document must enqueue and invoke connectedCallback
+PASS Inserting an ancestor of custom element into a cloned document must enqueue and invoke connectedCallback
+PASS Inserting a custom element into a shadow tree in a cloned document must enqueue and invoke connectedCallback
+PASS Inserting the shadow host of a custom element into a cloned document must enqueue and invoke connectedCallback
+PASS Inserting a custom element into a detached shadow tree that belongs to a cloned document must not enqueue and invoke connectedCallback
+PASS Inserting a custom element into a document created by createHTMLDocument must enqueue and invoke connectedCallback
+PASS Inserting an ancestor of custom element into a document created by createHTMLDocument must enqueue and invoke connectedCallback
+PASS Inserting a custom element into a shadow tree in a document created by createHTMLDocument must enqueue and invoke connectedCallback
+PASS Inserting the shadow host of a custom element into a document created by createHTMLDocument must enqueue and invoke connectedCallback
+PASS Inserting a custom element into a detached shadow tree that belongs to a document created by createHTMLDocument must not enqueue and invoke connectedCallback
+PASS Inserting a custom element into a HTML document created by createDocument must enqueue and invoke connectedCallback
+PASS Inserting an ancestor of custom element into a HTML document created by createDocument must enqueue and invoke connectedCallback
+PASS Inserting a custom element into a shadow tree in a HTML document created by createDocument must enqueue and invoke connectedCallback
+PASS Inserting the shadow host of a custom element into a HTML document created by createDocument must enqueue and invoke connectedCallback
+PASS Inserting a custom element into a detached shadow tree that belongs to a HTML document created by createDocument must not enqueue and invoke connectedCallback
+PASS Inserting a custom element into a document in an iframe must enqueue and invoke connectedCallback
+PASS Inserting an ancestor of custom element into a document in an iframe must enqueue and invoke connectedCallback
+PASS Inserting a custom element into a shadow tree in a document in an iframe must enqueue and invoke connectedCallback
+PASS Inserting the shadow host of a custom element into a document in an iframe must enqueue and invoke connectedCallback
+PASS Inserting a custom element into a detached shadow tree that belongs to a document in an iframe must not enqueue and invoke connectedCallback
+PASS Inserting a custom element into a HTML document fetched by XHR must enqueue and invoke connectedCallback
+PASS Inserting an ancestor of custom element into a HTML document fetched by XHR must enqueue and invoke connectedCallback
+PASS Inserting a custom element into a shadow tree in a HTML document fetched by XHR must enqueue and invoke connectedCallback
+PASS Inserting the shadow host of a custom element into a HTML document fetched by XHR must enqueue and invoke connectedCallback
+PASS Inserting a custom element into a detached shadow tree that belongs to a HTML document fetched by XHR must not enqueue and invoke connectedCallback
+
Modified: trunk/LayoutTests/fast/custom-elements/connected-callbacks.html (205059 => 205060)
--- trunk/LayoutTests/fast/custom-elements/connected-callbacks.html 2016-08-26 23:47:40 UTC (rev 205059)
+++ trunk/LayoutTests/fast/custom-elements/connected-callbacks.html 2016-08-27 00:04:08 UTC (rev 205060)
@@ -7,6 +7,7 @@
<link rel="help" href=""
<script src=""
<script src=""
+<script src=""
<link rel='stylesheet' href=''>
</head>
<body>
@@ -20,85 +21,69 @@
}
customElements.define('my-custom-element', MyCustomElement);
-test(function () {
- var instance = document.createElement('my-custom-element');
+DocumentTypes.forEach(function (entry) {
+ var documentName = entry.name;
+ var getDocument = entry.create;
- calls = [];
- document.body.appendChild(instance);
- assert_array_equals(calls, ['connected', instance]);
-}, 'Inserting a custom element into a document must enqueue and invoke connectedCallback');
+ promise_test(function () {
+ return getDocument().then(function (doc) {
+ var instance = document.createElement('my-custom-element');
+ calls = [];
+ doc.documentElement.appendChild(instance);
+ assert_array_equals(calls, ['connected', instance]);
+ });
+ }, 'Inserting a custom element into a ' + documentName + ' must enqueue and invoke connectedCallback');
-test(function () {
- var instance = document.createElement('my-custom-element');
+ promise_test(function () {
+ return getDocument().then(function (doc) {
+ var instance = document.createElement('my-custom-element');
+ var parent = document.createElement('div');
+ parent.appendChild(instance);
+ calls = [];
+ doc.documentElement.appendChild(parent);
+ assert_array_equals(calls, ['connected', instance]);
+ });
+ }, 'Inserting an ancestor of custom element into a ' + documentName + ' must enqueue and invoke connectedCallback');
- calls = [];
- var parent = document.createElement('div');
- parent.appendChild(instance);
- assert_array_equals(calls, []);
-}, 'Inserting a custom element into a detached node must not enqueue and invoke connectedCallback');
+ promise_test(function () {
+ return getDocument().then(function (doc) {
+ var instance = document.createElement('my-custom-element');
+ var host = doc.createElementNS('http://www.w3.org/1999/xhtml', 'div');
+ var shadowRoot = host.attachShadow({mode: 'closed'});
+ doc.documentElement.appendChild(host);
-test(function () {
- var instance = document.createElement('my-custom-element');
- var documentWithoutWindow = document.implementation.createHTMLDocument();
+ calls = [];
+ shadowRoot.appendChild(instance);
+ assert_array_equals(calls, ['connected', instance]);
+ });
+ }, 'Inserting a custom element into a shadow tree in a ' + documentName + ' must enqueue and invoke connectedCallback');
- calls = [];
- documentWithoutWindow.body.appendChild(instance);
- assert_array_equals(calls, ['connected', instance]);
-}, 'Inserting a custom element into a window-less document must enqueue and invoke connectedCallback');
+ promise_test(function () {
+ return getDocument().then(function (doc) {
+ var instance = document.createElement('my-custom-element');
+ var host = doc.createElementNS('http://www.w3.org/1999/xhtml', 'div');
+ var shadowRoot = host.attachShadow({mode: 'closed'});
+ shadowRoot.appendChild(instance);
-test(function () {
- var instance = document.createElement('my-custom-element');
- var parent = document.createElement('div');
- parent.appendChild(instance);
+ calls = [];
+ doc.documentElement.appendChild(host);
+ assert_array_equals(calls, ['connected', instance]);
+ });
+ }, 'Inserting the shadow host of a custom element into a ' + documentName + ' must enqueue and invoke connectedCallback');
- calls = [];
- document.body.appendChild(parent);
- assert_array_equals(calls, ['connected', instance]);
-}, 'Inserting an ancestor of a custom element into a document must enqueue and invoke connectedCallback');
+ promise_test(function () {
+ return getDocument().then(function (doc) {
+ var instance = document.createElement('my-custom-element');
+ var host = doc.createElementNS('http://www.w3.org/1999/xhtml', 'div');
+ var shadowRoot = host.attachShadow({mode: 'closed'});
-test(function () {
- var instance = document.createElement('my-custom-element');
- var parent = document.createElement('div');
- parent.appendChild(instance);
- var documentWithoutWindow = document.implementation.createHTMLDocument();
+ calls = [];
+ shadowRoot.appendChild(instance);
+ assert_array_equals(calls, []);
+ });
+ }, 'Inserting a custom element into a detached shadow tree that belongs to a ' + documentName + ' must not enqueue and invoke connectedCallback');
+});
- calls = [];
- documentWithoutWindow.body.appendChild(parent);
- assert_array_equals(calls, ['connected', instance]);
-}, 'Inserting an ancestor of custom element into a window-less document must enqueue and invoke connectedCallback');
-
-test(function () {
- var instance = document.createElement('my-custom-element');
- var host = document.createElement('div');
- var shadowRoot = host.attachShadow({mode: 'closed'});
- document.body.appendChild(host);
-
- calls = [];
- shadowRoot.appendChild(instance);
- assert_array_equals(calls, ['connected', instance]);
-}, 'Inserting a custom element into a connected shadow tree must enqueue and invoke connectedCallback');
-
-test(function () {
- var instance = document.createElement('my-custom-element');
- var host = document.createElement('div');
- var shadowRoot = host.attachShadow({mode: 'closed'});
- shadowRoot.appendChild(instance);
-
- calls = [];
- document.body.appendChild(host);
- assert_array_equals(calls, ['connected', instance]);
-}, 'Inserting the shadow host of a shadow tree with a custom element into a document must enqueue and invoke connectedCallback');
-
-test(function () {
- var instance = document.createElement('my-custom-element');
- var host = document.createElement('div');
- var shadowRoot = host.attachShadow({mode: 'closed'});
-
- calls = [];
- shadowRoot.appendChild(instance);
- assert_array_equals(calls, []);
-}, 'Inserting a custom element into a detached shadow tree must not enqueue and invoke connectedCallback');
-
</script>
</body>
</html>
Modified: trunk/LayoutTests/fast/custom-elements/defined-pseudo-class-expected.txt (205059 => 205060)
--- trunk/LayoutTests/fast/custom-elements/defined-pseudo-class-expected.txt 2016-08-26 23:47:40 UTC (rev 205059)
+++ trunk/LayoutTests/fast/custom-elements/defined-pseudo-class-expected.txt 2016-08-27 00:04:08 UTC (rev 205060)
@@ -1,5 +1,5 @@
-PASS The defined flag of a custom element must 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
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 a custom element created by HTML parser must be unset if there is no matching definition
Modified: trunk/LayoutTests/fast/custom-elements/defined-pseudo-class.html (205059 => 205060)
--- trunk/LayoutTests/fast/custom-elements/defined-pseudo-class.html 2016-08-26 23:47:40 UTC (rev 205059)
+++ trunk/LayoutTests/fast/custom-elements/defined-pseudo-class.html 2016-08-27 00:04:08 UTC (rev 205060)
@@ -16,7 +16,7 @@
test(function () {
assert_false(upgradeCandidate.matches(':defined'));
-}, 'The defined flag of a custom element must be set if a custom element has not been upgraded yet');
+}, 'The defined flag of a custom element must not be set if a custom element has not been upgraded yet');
var matchInsideConstructor;
class MyElement extends HTMLElement {
Modified: trunk/LayoutTests/fast/custom-elements/disconnected-callbacks-expected.txt (205059 => 205060)
--- trunk/LayoutTests/fast/custom-elements/disconnected-callbacks-expected.txt 2016-08-26 23:47:40 UTC (rev 205059)
+++ trunk/LayoutTests/fast/custom-elements/disconnected-callbacks-expected.txt 2016-08-27 00:04:08 UTC (rev 205060)
@@ -1,10 +1,43 @@
PASS Removing a custom element from a document must enqueue and invoke disconnectedCallback
-PASS Removing a custom element from a detahed node must not enqueue and invoke connectedCallback
-FAIL Removing a custom element from a window-less document must enqueue and invoke disconnectedCallback assert_array_equals: lengths differ, expected 2 got 0
-PASS Removing an ancestor of a custom element from a document must enqueue and invoke disconnectedCallback
-FAIL Removing an ancestor of custom element from a a window-less document must enqueue and invoke disconnectedCallback assert_array_equals: lengths differ, expected 2 got 0
-PASS Removing a custom element from a connected shadow tree must enqueue and invoke disconnectedCallback
-PASS Removing the shadow host of a shadow tree with a custom element from a document must enqueue and invoke disconnectedCallback
-PASS Removing a custom element from a detached shadow tree must not enqueue and invoke disconnectedCallback
+PASS Removing an ancestor of custom element from a document must enqueue and invoke disconnectedCallback
+PASS Removing a custom element from a shadow tree in a document must enqueue and invoke disconnectedCallback
+PASS Removing the shadow host of a custom element from adocument must enqueue and invoke disconnectedCallback
+PASS Removing a custom element from a detached shadow tree that belongs to a document must not enqueue and invoke disconnectedCallback
+PASS Removing a custom element from a document of a template element must enqueue and invoke disconnectedCallback
+PASS Removing an ancestor of custom element from a document of a template element must enqueue and invoke disconnectedCallback
+PASS Removing a custom element from a shadow tree in a document of a template element must enqueue and invoke disconnectedCallback
+PASS Removing the shadow host of a custom element from adocument of a template element must enqueue and invoke disconnectedCallback
+PASS Removing a custom element from a detached shadow tree that belongs to a document of a template element must not enqueue and invoke disconnectedCallback
+PASS Removing a custom element from a new document must enqueue and invoke disconnectedCallback
+PASS Removing an ancestor of custom element from a new document must enqueue and invoke disconnectedCallback
+PASS Removing a custom element from a shadow tree in a new document must enqueue and invoke disconnectedCallback
+PASS Removing the shadow host of a custom element from anew document must enqueue and invoke disconnectedCallback
+PASS Removing a custom element from a detached shadow tree that belongs to a new document must not enqueue and invoke disconnectedCallback
+PASS Removing a custom element from a cloned document must enqueue and invoke disconnectedCallback
+PASS Removing an ancestor of custom element from a cloned document must enqueue and invoke disconnectedCallback
+PASS Removing a custom element from a shadow tree in a cloned document must enqueue and invoke disconnectedCallback
+PASS Removing the shadow host of a custom element from acloned document must enqueue and invoke disconnectedCallback
+PASS Removing a custom element from a detached shadow tree that belongs to a cloned document must not enqueue and invoke disconnectedCallback
+PASS Removing a custom element from a document created by createHTMLDocument must enqueue and invoke disconnectedCallback
+PASS Removing an ancestor of custom element from a document created by createHTMLDocument must enqueue and invoke disconnectedCallback
+PASS Removing a custom element from a shadow tree in a document created by createHTMLDocument must enqueue and invoke disconnectedCallback
+PASS Removing the shadow host of a custom element from adocument created by createHTMLDocument must enqueue and invoke disconnectedCallback
+PASS Removing a custom element from a detached shadow tree that belongs to a document created by createHTMLDocument must not enqueue and invoke disconnectedCallback
+PASS Removing a custom element from a HTML document created by createDocument must enqueue and invoke disconnectedCallback
+PASS Removing an ancestor of custom element from a HTML document created by createDocument must enqueue and invoke disconnectedCallback
+PASS Removing a custom element from a shadow tree in a HTML document created by createDocument must enqueue and invoke disconnectedCallback
+PASS Removing the shadow host of a custom element from aHTML document created by createDocument must enqueue and invoke disconnectedCallback
+PASS Removing a custom element from a detached shadow tree that belongs to a HTML document created by createDocument must not enqueue and invoke disconnectedCallback
+PASS Removing a custom element from a document in an iframe must enqueue and invoke disconnectedCallback
+PASS Removing an ancestor of custom element from a document in an iframe must enqueue and invoke disconnectedCallback
+PASS Removing a custom element from a shadow tree in a document in an iframe must enqueue and invoke disconnectedCallback
+PASS Removing the shadow host of a custom element from adocument in an iframe must enqueue and invoke disconnectedCallback
+PASS Removing a custom element from a detached shadow tree that belongs to a document in an iframe must not enqueue and invoke disconnectedCallback
+PASS Removing a custom element from a HTML document fetched by XHR must enqueue and invoke disconnectedCallback
+PASS Removing an ancestor of custom element from a HTML document fetched by XHR must enqueue and invoke disconnectedCallback
+PASS Removing a custom element from a shadow tree in a HTML document fetched by XHR must enqueue and invoke disconnectedCallback
+PASS Removing the shadow host of a custom element from aHTML document fetched by XHR must enqueue and invoke disconnectedCallback
+PASS Removing a custom element from a detached shadow tree that belongs to a HTML document fetched by XHR must not enqueue and invoke disconnectedCallback
+
Modified: trunk/LayoutTests/fast/custom-elements/disconnected-callbacks.html (205059 => 205060)
--- trunk/LayoutTests/fast/custom-elements/disconnected-callbacks.html 2016-08-26 23:47:40 UTC (rev 205059)
+++ trunk/LayoutTests/fast/custom-elements/disconnected-callbacks.html 2016-08-27 00:04:08 UTC (rev 205060)
@@ -7,6 +7,7 @@
<link rel="help" href=""
<script src=""
<script src=""
+<script src=""
<link rel='stylesheet' href=''>
</head>
<body>
@@ -20,94 +21,74 @@
}
customElements.define('my-custom-element', MyCustomElement);
-test(function () {
- var instance = document.createElement('my-custom-element');
- document.body.appendChild(instance);
+DocumentTypes.forEach(function (entry) {
+ var documentName = entry.name;
+ var getDocument = entry.create;
- calls = [];
- document.body.removeChild(instance);
- assert_array_equals(calls, ['disconnected', instance]);
-}, 'Removing a custom element from a document must enqueue and invoke disconnectedCallback');
+ promise_test(function () {
+ return getDocument().then(function (doc) {
+ var instance = document.createElement('my-custom-element');
+ doc.documentElement.appendChild(instance);
+ calls = [];
+ doc.documentElement.removeChild(instance);
+ assert_array_equals(calls, ['disconnected', instance]);
+ });
+ }, 'Removing a custom element from a ' + documentName + ' must enqueue and invoke disconnectedCallback');
-test(function () {
- var instance = document.createElement('my-custom-element');
- var parent = document.createElement('div');
- parent.appendChild(instance);
+ promise_test(function () {
+ return getDocument().then(function (doc) {
+ var instance = document.createElement('my-custom-element');
+ var parent = document.createElement('div');
+ parent.appendChild(instance);
+ doc.documentElement.appendChild(parent);
+ calls = [];
+ doc.documentElement.removeChild(parent);
+ assert_array_equals(calls, ['disconnected', instance]);
+ });
+ }, 'Removing an ancestor of custom element from a ' + documentName + ' must enqueue and invoke disconnectedCallback');
- calls = [];
- parent.removeChild(instance);
- assert_array_equals(calls, []);
-}, 'Removing a custom element from a detahed node must not enqueue and invoke connectedCallback');
+ promise_test(function () {
+ return getDocument().then(function (doc) {
+ var instance = document.createElement('my-custom-element');
+ var host = doc.createElementNS('http://www.w3.org/1999/xhtml', 'div');
+ var shadowRoot = host.attachShadow({mode: 'closed'});
+ doc.documentElement.appendChild(host);
+ shadowRoot.appendChild(instance);
-test(function () {
- var instance = document.createElement('my-custom-element');
- var documentWithoutWindow = document.implementation.createHTMLDocument();
- documentWithoutWindow.body.appendChild(instance);
+ calls = [];
+ shadowRoot.removeChild(instance);
+ assert_array_equals(calls, ['disconnected', instance]);
+ });
+ }, 'Removing a custom element from a shadow tree in a ' + documentName + ' must enqueue and invoke disconnectedCallback');
- calls = [];
- documentWithoutWindow.body.removeChild(instance);
- assert_array_equals(calls, ['disconnected', instance]);
-}, 'Removing a custom element from a window-less document must enqueue and invoke disconnectedCallback');
+ promise_test(function () {
+ return getDocument().then(function (doc) {
+ var instance = document.createElement('my-custom-element');
+ var host = doc.createElementNS('http://www.w3.org/1999/xhtml', 'div');
+ var shadowRoot = host.attachShadow({mode: 'closed'});
+ shadowRoot.appendChild(instance);
+ doc.documentElement.appendChild(host);
-test(function () {
- var instance = document.createElement('my-custom-element');
- var parent = document.createElement('div');
- parent.appendChild(instance);
- document.body.appendChild(parent);
+ calls = [];
+ doc.documentElement.removeChild(host);
+ assert_array_equals(calls, ['disconnected', instance]);
+ });
+ }, 'Removing the shadow host of a custom element from a' + documentName + ' must enqueue and invoke disconnectedCallback');
- calls = [];
- document.body.removeChild(parent);
- assert_array_equals(calls, ['disconnected', instance]);
-}, 'Removing an ancestor of a custom element from a document must enqueue and invoke disconnectedCallback');
+ promise_test(function () {
+ return getDocument().then(function (doc) {
+ var instance = document.createElement('my-custom-element');
+ var host = doc.createElementNS('http://www.w3.org/1999/xhtml', 'div');
+ var shadowRoot = host.attachShadow({mode: 'closed'});
+ shadowRoot.appendChild(instance);
-test(function () {
- var instance = document.createElement('my-custom-element');
- var parent = document.createElement('div');
- parent.appendChild(instance);
- var documentWithoutWindow = document.implementation.createHTMLDocument();
- documentWithoutWindow.body.appendChild(parent);
+ calls = [];
+ shadowRoot.removeChild(instance);
+ assert_array_equals(calls, []);
+ });
+ }, 'Removing a custom element from a detached shadow tree that belongs to a ' + documentName + ' must not enqueue and invoke disconnectedCallback');
+});
- calls = [];
- documentWithoutWindow.body.removeChild(parent);
- assert_array_equals(calls, ['disconnected', instance]);
-}, 'Removing an ancestor of custom element from a a window-less document must enqueue and invoke disconnectedCallback');
-
-test(function () {
- var instance = document.createElement('my-custom-element');
- var host = document.createElement('div');
- document.body.appendChild(host);
- var shadowRoot = host.attachShadow({mode: 'closed'});
- shadowRoot.appendChild(instance);
-
- calls = [];
- shadowRoot.removeChild(instance);
- assert_array_equals(calls, ['disconnected', instance]);
-}, 'Removing a custom element from a connected shadow tree must enqueue and invoke disconnectedCallback');
-
-test(function () {
- var instance = document.createElement('my-custom-element');
- var host = document.createElement('div');
- var shadowRoot = host.attachShadow({mode: 'closed'});
- shadowRoot.appendChild(instance);
- document.body.appendChild(host);
-
- calls = [];
- document.body.removeChild(host);
- assert_array_equals(calls, ['disconnected', instance]);
-}, 'Removing the shadow host of a shadow tree with a custom element from a document must enqueue and invoke disconnectedCallback');
-
-test(function () {
- var instance = document.createElement('my-custom-element');
- var host = document.createElement('div');
- var shadowRoot = host.attachShadow({mode: 'closed'});
- shadowRoot.appendChild(instance);
-
- calls = [];
- shadowRoot.removeChild(instance);
- assert_array_equals(calls, []);
-}, 'Removing a custom element from a detached shadow tree must not enqueue and invoke disconnectedCallback');
-
-
</script>
</body>
</html>
Added: trunk/LayoutTests/fast/custom-elements/resources/document-types.js (0 => 205060)
--- trunk/LayoutTests/fast/custom-elements/resources/document-types.js (rev 0)
+++ trunk/LayoutTests/fast/custom-elements/resources/document-types.js 2016-08-27 00:04:08 UTC (rev 205060)
@@ -0,0 +1,74 @@
+const DocumentTypes = [
+ {
+ name: 'document',
+ create: function () { return Promise.resolve(document); }
+ },
+ {
+ name: 'document of a template element',
+ create: function () {
+ return new Promise(function (resolve) {
+ var template = document.createElementNS('http://www.w3.org/1999/xhtml', 'template');
+ var doc = template.content.ownerDocument;
+ if (!doc.documentElement)
+ doc.appendChild(doc.createElement('html'));
+ resolve(doc);
+ });
+ }
+ },
+ {
+ name: 'new document',
+ create: function () {
+ return new Promise(function (resolve) {
+ var doc = new Document();
+ doc.appendChild(doc.createElement('html'));
+ resolve(doc);
+ });
+ }
+ },
+ {
+ name: 'cloned document',
+ create: function () {
+ return new Promise(function (resolve) {
+ var doc = document.cloneNode(false);
+ doc.appendChild(doc.createElement('html'));
+ resolve(doc);
+ });
+ }
+ },
+ {
+ name: 'document created by createHTMLDocument',
+ create: function () {
+ return Promise.resolve(document.implementation.createHTMLDocument());
+ }
+ },
+ {
+ name: 'HTML document created by createDocument',
+ create: function () {
+ return Promise.resolve(document.implementation.createDocument('http://www.w3.org/1999/xhtml', 'html', null));
+ }
+ },
+ {
+ name: 'document in an iframe',
+ create: function () {
+ return new Promise(function (resolve, reject) {
+ var iframe = document.createElement('iframe');
+ iframe._onload_ = function () { resolve(iframe.contentDocument); }
+ iframe._onerror_ = function () { reject('Failed to load an empty iframe'); }
+ document.body.appendChild(iframe);
+ });
+ }
+ },
+ {
+ name: 'HTML document fetched by XHR',
+ create: function () {
+ return new Promise(function (resolve, reject) {
+ var xhr = new XMLHttpRequest();
+ xhr.open('GET', 'resources/empty-html-document.html');
+ xhr.overrideMimeType('text/xml');
+ xhr._onload_ = function () { resolve(xhr.responseXML); }
+ xhr._onerror_ = function () { reject('Failed to fetch the document'); }
+ xhr.send();
+ });
+ }
+ }
+];
\ No newline at end of file
Added: trunk/LayoutTests/fast/custom-elements/resources/empty-html-document.html (0 => 205060)
--- trunk/LayoutTests/fast/custom-elements/resources/empty-html-document.html (rev 0)
+++ trunk/LayoutTests/fast/custom-elements/resources/empty-html-document.html 2016-08-27 00:04:08 UTC (rev 205060)
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<html>
+<body>
+</body>
+</html>
Modified: trunk/Source/WebCore/ChangeLog (205059 => 205060)
--- trunk/Source/WebCore/ChangeLog 2016-08-26 23:47:40 UTC (rev 205059)
+++ trunk/Source/WebCore/ChangeLog 2016-08-27 00:04:08 UTC (rev 205060)
@@ -1,3 +1,38 @@
+2016-08-23 Ryosuke Niwa <[email protected]>
+
+ Adopted custom element's callbacks should continue to work
+ https://bugs.webkit.org/show_bug.cgi?id=161065
+
+ Reviewed by Andreas Kling.
+
+ When a custom element is adopted into another document, its reaction callbacks need to continue to work.
+ Because a different document may have its own global object, each custom element needs to remember its
+ original global object or JSCustomElementInterface. This patch adds the latter to the element rare data.
+
+ Tests: fast/custom-elements/connected-callbacks.html
+ fast/custom-elements/disconnected-callbacks.html
+
+ * bindings/js/JSCustomElementInterface.cpp:
+ (WebCore::JSCustomElementInterface::constructElement):
+ (WebCore::JSCustomElementInterface::upgradeElement):
+ * dom/CustomElementReactionQueue.cpp:
+ (WebCore::findInterfaceForCustomElement): Deleted.
+ (WebCore::CustomElementReactionQueue::enqueueConnectedCallbackIfNeeded):
+ (WebCore::CustomElementReactionQueue::enqueueDisconnectedCallbackIfNeeded):
+ (WebCore::CustomElementReactionQueue::enqueueAttributeChangedCallbackIfNeeded):
+ * dom/Element.cpp:
+ (WebCore::Element::insertedInto): Invoke callbacks even when the current document is not a HTML document.
+ (WebCore::Element::removedFrom): Ditto.
+ (WebCore::Element::setCustomElementIsResolved): Moved from Node. Add the element interface to the rare data.
+ (WebCore::Element::customElementInterface): Added.
+ * dom/Element.h:
+ * dom/ElementRareData.cpp:
+ * dom/ElementRareData.h:
+ (WebCore::ElementRareData::customElementInterface): Added.
+ (WebCore::ElementRareData::setCustomElementInterface): Added.
+ * dom/Node.h:
+ ((WebCore::Node::setCustomElementIsResolved): Deleted.
+
2016-08-26 Zalan Bujtas <[email protected]>
ASSERT_NOT_REACHED() is touched in WebCore::minimumValueForLength
Modified: trunk/Source/WebCore/bindings/js/JSCustomElementInterface.cpp (205059 => 205060)
--- trunk/Source/WebCore/bindings/js/JSCustomElementInterface.cpp 2016-08-26 23:47:40 UTC (rev 205059)
+++ trunk/Source/WebCore/bindings/js/JSCustomElementInterface.cpp 2016-08-27 00:04:08 UTC (rev 205060)
@@ -98,7 +98,7 @@
Element* wrappedElement = JSElement::toWrapped(newElement);
if (!wrappedElement)
return nullptr;
- wrappedElement->setCustomElementIsResolved();
+ wrappedElement->setCustomElementIsResolved(*this);
return wrappedElement;
}
@@ -147,8 +147,7 @@
throwInvalidStateError(*state, "Custom element constructor failed to upgrade an element");
return;
}
- wrappedElement->setCustomElementIsResolved();
- ASSERT(wrappedElement->isCustomElement());
+ wrappedElement->setCustomElementIsResolved(*this);
}
void JSCustomElementInterface::invokeCallback(Element& element, JSObject* callback, const WTF::Function<void(ExecState*, MarkedArgumentBuffer&)>& addArguments)
Modified: trunk/Source/WebCore/dom/CustomElementReactionQueue.cpp (205059 => 205060)
--- trunk/Source/WebCore/dom/CustomElementReactionQueue.cpp 2016-08-26 23:47:40 UTC (rev 205059)
+++ trunk/Source/WebCore/dom/CustomElementReactionQueue.cpp 2016-08-27 00:04:08 UTC (rev 205060)
@@ -106,23 +106,9 @@
queue->m_items.append({CustomElementReactionQueueItem::Type::ElementUpgrade, element, elementInterface});
}
-static JSCustomElementInterface* findInterfaceForCustomElement(Element& element)
-{
- ASSERT(element.isCustomElement());
- auto* window = element.document().domWindow();
- if (!window)
- return nullptr;
-
- auto* registry = window->customElementRegistry();
- if (!registry)
- return nullptr;
-
- return registry->findInterface(element.tagQName());
-}
-
void CustomElementReactionQueue::enqueueConnectedCallbackIfNeeded(Element& element)
{
- auto* elementInterface = findInterfaceForCustomElement(element);
+ auto* elementInterface = element.customElementInterface();
if (!elementInterface)
return;
@@ -132,7 +118,7 @@
void CustomElementReactionQueue::enqueueDisconnectedCallbackIfNeeded(Element& element)
{
- auto* elementInterface = findInterfaceForCustomElement(element);
+ auto* elementInterface = element.customElementInterface();
if (!elementInterface)
return;
@@ -142,7 +128,7 @@
void CustomElementReactionQueue::enqueueAttributeChangedCallbackIfNeeded(Element& element, const QualifiedName& attributeName, const AtomicString& oldValue, const AtomicString& newValue)
{
- auto* elementInterface = findInterfaceForCustomElement(element);
+ auto* elementInterface = element.customElementInterface();
if (!elementInterface || !elementInterface->observesAttribute(attributeName.localName()))
return;
Modified: trunk/Source/WebCore/dom/Element.cpp (205059 => 205060)
--- trunk/Source/WebCore/dom/Element.cpp 2016-08-26 23:47:40 UTC (rev 205059)
+++ trunk/Source/WebCore/dom/Element.cpp 2016-08-27 00:04:08 UTC (rev 205060)
@@ -1574,7 +1574,8 @@
// This element is new to the shadow tree (and its tree scope) only if the parent into which this element
// or its ancestor is inserted belongs to the same tree scope as this element's.
TreeScope* newScope = &insertionPoint.treeScope();
- HTMLDocument* newDocument = !wasInDocument && inDocument() && is<HTMLDocument>(newScope->documentScope()) ? &downcast<HTMLDocument>(newScope->documentScope()) : nullptr;
+ bool becomeConnected = !wasInDocument && inDocument();
+ HTMLDocument* newDocument = becomeConnected && is<HTMLDocument>(newScope->documentScope()) ? &downcast<HTMLDocument>(newScope->documentScope()) : nullptr;
if (newScope != &treeScope())
newScope = nullptr;
@@ -1600,7 +1601,7 @@
}
#if ENABLE(CUSTOM_ELEMENTS)
- if (newDocument && UNLIKELY(isCustomElement()))
+ if (becomeConnected && UNLIKELY(isCustomElement()))
CustomElementReactionQueue::enqueueConnectedCallbackIfNeeded(*this);
#endif
@@ -1622,7 +1623,8 @@
if (insertionPoint.isInTreeScope()) {
TreeScope* oldScope = &insertionPoint.treeScope();
- HTMLDocument* oldDocument = inDocument() && is<HTMLDocument>(oldScope->documentScope()) ? &downcast<HTMLDocument>(oldScope->documentScope()) : nullptr;
+ bool becomeDisconnected = inDocument();
+ HTMLDocument* oldDocument = becomeDisconnected && is<HTMLDocument>(oldScope->documentScope()) ? &downcast<HTMLDocument>(oldScope->documentScope()) : nullptr;
// ContainerNode::removeBetween always sets the removed chid's tree scope to Document's but InTreeScope flag is unset in Node::removedFrom.
// So this element has been removed from the old tree scope only if InTreeScope flag is set and this element's tree scope is Document's.
@@ -1651,7 +1653,7 @@
}
#if ENABLE(CUSTOM_ELEMENTS)
- if (oldDocument && UNLIKELY(isCustomElement()))
+ if (becomeDisconnected && UNLIKELY(isCustomElement()))
CustomElementReactionQueue::enqueueDisconnectedCallbackIfNeeded(*this);
#endif
}
@@ -1821,6 +1823,27 @@
return *shadowRoot;
}
+
+#if ENABLE(CUSTOM_ELEMENTS)
+
+void Element::setCustomElementIsResolved(JSCustomElementInterface& elementInterface)
+{
+ clearFlag(IsEditingTextOrUnresolvedCustomElementFlag);
+ setFlag(IsCustomElement);
+ ensureElementRareData().setCustomElementInterface(elementInterface);
+}
+
+JSCustomElementInterface* Element::customElementInterface() const
+{
+ ASSERT(isCustomElement());
+ if (!hasRareData())
+ return nullptr;
+ return elementRareData()->customElementInterface();
+}
+
+#endif
+
+
const AtomicString& Element::shadowPseudoId() const
{
return pseudo();
Modified: trunk/Source/WebCore/dom/Element.h (205059 => 205060)
--- trunk/Source/WebCore/dom/Element.h 2016-08-26 23:47:40 UTC (rev 205059)
+++ trunk/Source/WebCore/dom/Element.h 2016-08-27 00:04:08 UTC (rev 205060)
@@ -44,6 +44,7 @@
class ElementRareData;
class HTMLDocument;
class IntSize;
+class JSCustomElementInterface;
class KeyboardEvent;
class Locale;
class PlatformKeyboardEvent;
@@ -272,6 +273,11 @@
ShadowRoot* userAgentShadowRoot() const;
WEBCORE_EXPORT ShadowRoot& ensureUserAgentShadowRoot();
+#if ENABLE(CUSTOM_ELEMENTS)
+ void setCustomElementIsResolved(JSCustomElementInterface&);
+ JSCustomElementInterface* customElementInterface() const;
+#endif
+
// FIXME: this should not be virtual, do not override this.
virtual const AtomicString& shadowPseudoId() const;
Modified: trunk/Source/WebCore/dom/ElementRareData.cpp (205059 => 205060)
--- trunk/Source/WebCore/dom/ElementRareData.cpp 2016-08-26 23:47:40 UTC (rev 205059)
+++ trunk/Source/WebCore/dom/ElementRareData.cpp 2016-08-27 00:04:08 UTC (rev 205060)
@@ -44,7 +44,11 @@
RegionOversetState regionOversetState;
LayoutSize sizeForResizing;
IntPoint savedLayerScrollPosition;
+#if ENABLE(CUSTOM_ELEMENTS)
+ void* pointers[8];
+#else
void* pointers[7];
+#endif
};
static_assert(sizeof(ElementRareData) == sizeof(SameSizeAsElementRareData), "ElementRareData should stay small");
Modified: trunk/Source/WebCore/dom/ElementRareData.h (205059 => 205060)
--- trunk/Source/WebCore/dom/ElementRareData.h 2016-08-26 23:47:40 UTC (rev 205059)
+++ trunk/Source/WebCore/dom/ElementRareData.h 2016-08-27 00:04:08 UTC (rev 205060)
@@ -24,6 +24,7 @@
#include "DOMTokenList.h"
#include "DatasetDOMStringMap.h"
+#include "JSCustomElementInterface.h"
#include "NamedNodeMap.h"
#include "NodeRareData.h"
#include "PseudoElement.h"
@@ -93,6 +94,11 @@
ShadowRoot* shadowRoot() const { return m_shadowRoot.get(); }
void setShadowRoot(RefPtr<ShadowRoot>&& shadowRoot) { m_shadowRoot = WTFMove(shadowRoot); }
+#if ENABLE(CUSTOM_ELEMENTS)
+ JSCustomElementInterface* customElementInterface() { return m_customElementInterface.get(); }
+ void setCustomElementInterface(JSCustomElementInterface& customElementInterface) { m_customElementInterface = &customElementInterface; }
+#endif
+
NamedNodeMap* attributeMap() const { return m_attributeMap.get(); }
void setAttributeMap(std::unique_ptr<NamedNodeMap> attributeMap) { m_attributeMap = WTFMove(attributeMap); }
@@ -149,6 +155,9 @@
std::unique_ptr<DatasetDOMStringMap> m_dataset;
std::unique_ptr<DOMTokenList> m_classList;
RefPtr<ShadowRoot> m_shadowRoot;
+#if ENABLE(CUSTOM_ELEMENTS)
+ RefPtr<JSCustomElementInterface> m_customElementInterface;
+#endif
std::unique_ptr<NamedNodeMap> m_attributeMap;
RefPtr<PseudoElement> m_beforePseudoElement;
Modified: trunk/Source/WebCore/dom/Node.h (205059 => 205060)
--- trunk/Source/WebCore/dom/Node.h 2016-08-26 23:47:40 UTC (rev 205059)
+++ trunk/Source/WebCore/dom/Node.h 2016-08-27 00:04:08 UTC (rev 205060)
@@ -267,7 +267,6 @@
bool isUnresolvedCustomElement() const { return isElementNode() && getFlag(IsEditingTextOrUnresolvedCustomElementFlag); }
void setIsUnresolvedCustomElement() { setFlag(IsEditingTextOrUnresolvedCustomElementFlag); }
- void setCustomElementIsResolved();
#endif
// Returns null, a child of ShadowRoot, or a legacy shadow root.
@@ -769,16 +768,6 @@
return parentNode();
}
-#if ENABLE(CUSTOM_ELEMENTS)
-
-inline void Node::setCustomElementIsResolved()
-{
- clearFlag(IsEditingTextOrUnresolvedCustomElementFlag);
- setFlag(IsCustomElement);
-}
-
-#endif
-
} // namespace WebCore
#if ENABLE(TREE_DEBUGGING)