Add CEReactions to the remaining HTML DOM APIs
authorrniwa@webkit.org <rniwa@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 28 Oct 2016 23:49:46 +0000 (23:49 +0000)
committerrniwa@webkit.org <rniwa@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 28 Oct 2016 23:49:46 +0000 (23:49 +0000)
https://bugs.webkit.org/show_bug.cgi?id=163969

Reviewed by Chris Dumez.

Source/WebCore:

Added CEReactions to the remaining DOM and HTML APIs as needed.

Tests: fast/custom-elements/reactions-for-indieui.html
       fast/custom-elements/reactions/Document.html
       fast/custom-elements/reactions/HTMLAnchorElement.html
       fast/custom-elements/reactions/HTMLOptionElement.html
       fast/custom-elements/reactions/HTMLOptionsCollection.html
       fast/custom-elements/reactions/HTMLOutputElement.html
       fast/custom-elements/reactions/HTMLSelectElement.html
       fast/custom-elements/reactions/HTMLTableElement.html
       fast/custom-elements/reactions/HTMLTableRowElement.html
       fast/custom-elements/reactions/HTMLTableSectionElement.html
       fast/custom-elements/reactions/HTMLTitleElement.html
       fast/custom-elements/reactions/ShadowRoot.html

* bindings/js/JSHTMLOptionsCollectionCustom.cpp:
(WebCore::JSHTMLOptionsCollection::setLength):
(WebCore::JSHTMLOptionsCollection::indexSetter):
* bindings/js/JSHTMLSelectElementCustom.cpp:
(WebCore::JSHTMLSelectElement::indexSetter):
* dom/CharacterData.idl:
* dom/Document.idl:
* dom/Element.idl:
* dom/ShadowRoot.idl:
* html/HTMLAnchorElement.idl:
* html/HTMLDocument.idl:
* html/HTMLOptionElement.idl:
* html/HTMLOptionsCollection.idl:
* html/HTMLOutputElement.idl:
* html/HTMLSelectElement.idl:
* html/HTMLTableElement.idl:
* html/HTMLTableRowElement.idl:
* html/HTMLTableSectionElement.idl:
* html/HTMLTitleElement.idl:

LayoutTests:

Added W3C style testharness.js tests for CEReactions to various HTMLElements under fast/custom-elements/reactions.
Also added some WebKit specific tests using the same harness outside that directory.

* fast/custom-elements/reactions-for-indieui-expected.txt: Added.
* fast/custom-elements/reactions-for-indieui.html: Added.
* fast/custom-elements/reactions-for-webkit-extensions-expected.txt:
* fast/custom-elements/reactions-for-webkit-extensions.html:
* fast/custom-elements/reactions/Document-expected.txt: Added.
* fast/custom-elements/reactions/Document.html: Added.
* fast/custom-elements/reactions/HTMLAnchorElement-expected.txt: Added.
* fast/custom-elements/reactions/HTMLAnchorElement.html: Added.
* fast/custom-elements/reactions/HTMLOptionElement-expected.txt: Added.
* fast/custom-elements/reactions/HTMLOptionElement.html: Added.
* fast/custom-elements/reactions/HTMLOptionsCollection-expected.txt: Added.
* fast/custom-elements/reactions/HTMLOptionsCollection.html: Added.
* fast/custom-elements/reactions/HTMLOutputElement-expected.txt: Added.
* fast/custom-elements/reactions/HTMLOutputElement.html: Added.
* fast/custom-elements/reactions/HTMLSelectElement-expected.txt: Added.
* fast/custom-elements/reactions/HTMLSelectElement.html: Added.
* fast/custom-elements/reactions/HTMLTableElement-expected.txt: Added.
* fast/custom-elements/reactions/HTMLTableElement.html: Added.
* fast/custom-elements/reactions/HTMLTableRowElement-expected.txt: Added.
* fast/custom-elements/reactions/HTMLTableRowElement.html: Added.
* fast/custom-elements/reactions/HTMLTableSectionElement-expected.txt: Added.
* fast/custom-elements/reactions/HTMLTableSectionElement.html: Added.
* fast/custom-elements/reactions/HTMLTitleElement-expected.txt: Added.
* fast/custom-elements/reactions/HTMLTitleElement.html: Added.
* fast/custom-elements/reactions/ShadowRoot-expected.txt: Added.
* fast/custom-elements/reactions/ShadowRoot.html: Added.
* fast/custom-elements/resources/additional-helpers.js: Added.
* fast/custom-elements/upgrading-enqueue-reactions-expected.txt:
* fast/custom-elements/upgrading-enqueue-reactions.html:
* platform/efl/TestExpectations:
* platform/gtk/TestExpectations:

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@208082 268f45cc-cd09-0410-ab3c-d52691b4dbfc

49 files changed:
LayoutTests/ChangeLog
LayoutTests/fast/custom-elements/reactions-for-indieui-expected.txt [new file with mode: 0644]
LayoutTests/fast/custom-elements/reactions-for-indieui.html [new file with mode: 0644]
LayoutTests/fast/custom-elements/reactions-for-webkit-extensions-expected.txt
LayoutTests/fast/custom-elements/reactions-for-webkit-extensions.html
LayoutTests/fast/custom-elements/reactions/Document-expected.txt [new file with mode: 0644]
LayoutTests/fast/custom-elements/reactions/Document.html [new file with mode: 0644]
LayoutTests/fast/custom-elements/reactions/HTMLAnchorElement-expected.txt [new file with mode: 0644]
LayoutTests/fast/custom-elements/reactions/HTMLAnchorElement.html [new file with mode: 0644]
LayoutTests/fast/custom-elements/reactions/HTMLOptionElement-expected.txt [new file with mode: 0644]
LayoutTests/fast/custom-elements/reactions/HTMLOptionElement.html [new file with mode: 0644]
LayoutTests/fast/custom-elements/reactions/HTMLOptionsCollection-expected.txt [new file with mode: 0644]
LayoutTests/fast/custom-elements/reactions/HTMLOptionsCollection.html [new file with mode: 0644]
LayoutTests/fast/custom-elements/reactions/HTMLOutputElement-expected.txt [new file with mode: 0644]
LayoutTests/fast/custom-elements/reactions/HTMLOutputElement.html [new file with mode: 0644]
LayoutTests/fast/custom-elements/reactions/HTMLSelectElement-expected.txt [new file with mode: 0644]
LayoutTests/fast/custom-elements/reactions/HTMLSelectElement.html [new file with mode: 0644]
LayoutTests/fast/custom-elements/reactions/HTMLTableElement-expected.txt [new file with mode: 0644]
LayoutTests/fast/custom-elements/reactions/HTMLTableElement.html [new file with mode: 0644]
LayoutTests/fast/custom-elements/reactions/HTMLTableRowElement-expected.txt [new file with mode: 0644]
LayoutTests/fast/custom-elements/reactions/HTMLTableRowElement.html [new file with mode: 0644]
LayoutTests/fast/custom-elements/reactions/HTMLTableSectionElement-expected.txt [new file with mode: 0644]
LayoutTests/fast/custom-elements/reactions/HTMLTableSectionElement.html [new file with mode: 0644]
LayoutTests/fast/custom-elements/reactions/HTMLTitleElement-expected.txt [new file with mode: 0644]
LayoutTests/fast/custom-elements/reactions/HTMLTitleElement.html [new file with mode: 0644]
LayoutTests/fast/custom-elements/reactions/ShadowRoot-expected.txt [new file with mode: 0644]
LayoutTests/fast/custom-elements/reactions/ShadowRoot.html [new file with mode: 0644]
LayoutTests/fast/custom-elements/resources/additional-helpers.js [new file with mode: 0644]
LayoutTests/fast/custom-elements/upgrading-enqueue-reactions-expected.txt
LayoutTests/fast/custom-elements/upgrading-enqueue-reactions.html
LayoutTests/platform/efl/TestExpectations
LayoutTests/platform/gtk/TestExpectations
Source/WebCore/ChangeLog
Source/WebCore/bindings/js/JSHTMLOptionsCollectionCustom.cpp
Source/WebCore/bindings/js/JSHTMLSelectElementCustom.cpp
Source/WebCore/dom/CharacterData.idl
Source/WebCore/dom/Document.idl
Source/WebCore/dom/Element.idl
Source/WebCore/dom/ShadowRoot.idl
Source/WebCore/html/HTMLAnchorElement.idl
Source/WebCore/html/HTMLDocument.idl
Source/WebCore/html/HTMLOptionElement.idl
Source/WebCore/html/HTMLOptionsCollection.idl
Source/WebCore/html/HTMLOutputElement.idl
Source/WebCore/html/HTMLSelectElement.idl
Source/WebCore/html/HTMLTableElement.idl
Source/WebCore/html/HTMLTableRowElement.idl
Source/WebCore/html/HTMLTableSectionElement.idl
Source/WebCore/html/HTMLTitleElement.idl

index 95652b7..49a47a1 100644 (file)
@@ -1,3 +1,45 @@
+2016-10-28  Ryosuke Niwa  <rniwa@webkit.org>
+
+        Add CEReactions to the remaining HTML DOM APIs
+        https://bugs.webkit.org/show_bug.cgi?id=163969
+
+        Reviewed by Chris Dumez.
+
+        Added W3C style testharness.js tests for CEReactions to various HTMLElements under fast/custom-elements/reactions.
+        Also added some WebKit specific tests using the same harness outside that directory.
+
+        * fast/custom-elements/reactions-for-indieui-expected.txt: Added.
+        * fast/custom-elements/reactions-for-indieui.html: Added.
+        * fast/custom-elements/reactions-for-webkit-extensions-expected.txt:
+        * fast/custom-elements/reactions-for-webkit-extensions.html:
+        * fast/custom-elements/reactions/Document-expected.txt: Added.
+        * fast/custom-elements/reactions/Document.html: Added.
+        * fast/custom-elements/reactions/HTMLAnchorElement-expected.txt: Added.
+        * fast/custom-elements/reactions/HTMLAnchorElement.html: Added.
+        * fast/custom-elements/reactions/HTMLOptionElement-expected.txt: Added.
+        * fast/custom-elements/reactions/HTMLOptionElement.html: Added.
+        * fast/custom-elements/reactions/HTMLOptionsCollection-expected.txt: Added.
+        * fast/custom-elements/reactions/HTMLOptionsCollection.html: Added.
+        * fast/custom-elements/reactions/HTMLOutputElement-expected.txt: Added.
+        * fast/custom-elements/reactions/HTMLOutputElement.html: Added.
+        * fast/custom-elements/reactions/HTMLSelectElement-expected.txt: Added.
+        * fast/custom-elements/reactions/HTMLSelectElement.html: Added.
+        * fast/custom-elements/reactions/HTMLTableElement-expected.txt: Added.
+        * fast/custom-elements/reactions/HTMLTableElement.html: Added.
+        * fast/custom-elements/reactions/HTMLTableRowElement-expected.txt: Added.
+        * fast/custom-elements/reactions/HTMLTableRowElement.html: Added.
+        * fast/custom-elements/reactions/HTMLTableSectionElement-expected.txt: Added.
+        * fast/custom-elements/reactions/HTMLTableSectionElement.html: Added.
+        * fast/custom-elements/reactions/HTMLTitleElement-expected.txt: Added.
+        * fast/custom-elements/reactions/HTMLTitleElement.html: Added.
+        * fast/custom-elements/reactions/ShadowRoot-expected.txt: Added.
+        * fast/custom-elements/reactions/ShadowRoot.html: Added.
+        * fast/custom-elements/resources/additional-helpers.js: Added.
+        * fast/custom-elements/upgrading-enqueue-reactions-expected.txt:
+        * fast/custom-elements/upgrading-enqueue-reactions.html:
+        * platform/efl/TestExpectations:
+        * platform/gtk/TestExpectations:
+
 2016-10-28  Antoine Quint  <graouts@apple.com>
 
         [Modern Media Controls] Media Controller: volume control support
diff --git a/LayoutTests/fast/custom-elements/reactions-for-indieui-expected.txt b/LayoutTests/fast/custom-elements/reactions-for-indieui-expected.txt
new file mode 100644 (file)
index 0000000..9f1d168
--- /dev/null
@@ -0,0 +1,4 @@
+
+PASS uiactions on Element must enqueue an attributeChanged reaction when adding uiactions content attribute 
+PASS uiactions on Element must enqueue an attributeChanged reaction when replacing an existing attribute 
+
diff --git a/LayoutTests/fast/custom-elements/reactions-for-indieui.html b/LayoutTests/fast/custom-elements/reactions-for-indieui.html
new file mode 100644 (file)
index 0000000..bbb5d78
--- /dev/null
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>Custom Elements: CEReactions on uiactions of Element interface</title>
+<meta name="author" title="Ryosuke Niwa" href="mailto:rniwa@webkit.org">
+<meta name="assert" content="uiactions of Element interface must have CEReactions">
+<meta name="help" content="https://dom.spec.whatwg.org/#node">
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
+<script src="../../imported/w3c/web-platform-tests/custom-elements/resources/custom-elements-helpers.js"></script>
+<script src="../../imported/w3c/web-platform-tests/custom-elements/reactions/resources/reactions.js"></script>
+</head>
+<body>
+<div id="log"></div>
+<script>
+
+testReflectAttribute('uiactions', 'uiactions', 'delete', 'dismiss', 'uiactions on Element');
+
+</script>
+</body>
+</html>
index f4387cc..ad71977 100644 (file)
@@ -1,4 +1,12 @@
 
 PASS dropzone on HTMLElement must enqueue an attributeChanged reaction when adding webkitdropzone content attribute 
 PASS dropzone on HTMLElement must enqueue an attributeChanged reaction when replacing an existing attribute 
+PASS data on CharacterData must enqueue an attributeChanged reaction when replacing an existing attribute 
+PASS data on CharacterData must not enqueue an attributeChanged reaction when replacing an existing unobserved attribute 
+PASS appendData on CharacterData must enqueue an attributeChangedCallback when mutating an existing attribute 
+PASS insertData on CharacterData must enqueue an attributeChangedCallback when mutating an existing attribute 
+PASS deleteData on CharacterData must enqueue an attributeChangedCallback when mutating an existing attribute 
+PASS replaceData on CharacterData must enqueue an attributeChangedCallback when mutating an existing attribute 
+PASS remove(HTMLOptionElement) on HTMLOptionsCollection must enqueue disconnectedCallback when removing a custom element 
+PASS remove(HTMLOptionElement) on HTMLSelectElement must enqueue disconnectedCallback when removing a custom element 
 
index ac65757..25f1711 100644 (file)
@@ -1,14 +1,15 @@
 <!DOCTYPE html>
 <html>
 <head>
-<title>Custom Elements: CEReactions on HTMLElement interface</title>
+<title>Custom Elements: CEReactions on HTMLElement and Attr interfaces</title>
 <meta name="author" title="Ryosuke Niwa" href="mailto:rniwa@webkit.org">
-<meta name="assert" content="webkitdropzone of HTMLElement interface must have CEReactions">
+<meta name="assert" content="webkitdropzone of HTMLElement and Attr interface must have CEReactions">
 <meta name="help" content="https://dom.spec.whatwg.org/#node">
 <script src="../../resources/testharness.js"></script>
 <script src="../../resources/testharnessreport.js"></script>
 <script src="../../imported/w3c/web-platform-tests/custom-elements/resources/custom-elements-helpers.js"></script>
 <script src="../../imported/w3c/web-platform-tests/custom-elements/reactions/resources/reactions.js"></script>
+<script src="resources/additional-helpers.js"></script>
 </head>
 <body>
 <div id="log"></div>
 
 testReflectAttribute('webkitdropzone', 'webkitdropzone', 'copy', 'move', 'dropzone on HTMLElement');
 
+testAttributeMutator(function (element, name, value) {
+    element.attributes[name].firstChild.data = value;
+}, 'data on CharacterData');
+
+test(function () {
+    var element = define_new_custom_element(['title']);
+    var instance = document.createElement(element.name);
+    instance.setAttribute('title', 'hello');
+    assert_array_equals(element.takeLog().types(), ['constructed', 'attributeChanged']);
+    instance.attributes.title.firstChild.appendData(' world');
+    var logEntries = element.takeLog();
+    assert_array_equals(logEntries.types(), ['attributeChanged']);
+    assert_attribute_log_entry(logEntries.last(), {name: 'title', oldValue: 'hello', newValue: 'hello world', namespace: null});
+}, 'appendData on CharacterData must enqueue an attributeChangedCallback when mutating an existing attribute');
+
+test(function () {
+    var element = define_new_custom_element(['title']);
+    var instance = document.createElement(element.name);
+    instance.setAttribute('title', 'foo');
+    assert_array_equals(element.takeLog().types(), ['constructed', 'attributeChanged']);
+    instance.attributes.title.firstChild.insertData(2, 'bar');
+    var logEntries = element.takeLog();
+    assert_array_equals(logEntries.types(), ['attributeChanged']);
+    assert_attribute_log_entry(logEntries.last(), {name: 'title', oldValue: 'foo', newValue: 'fobaro', namespace: null});
+}, 'insertData on CharacterData must enqueue an attributeChangedCallback when mutating an existing attribute');
+
+test(function () {
+    var element = define_new_custom_element(['title']);
+    var instance = document.createElement(element.name);
+    instance.setAttribute('title', 'hello world');
+    assert_array_equals(element.takeLog().types(), ['constructed', 'attributeChanged']);
+    instance.attributes.title.firstChild.deleteData(5, 100);
+    var logEntries = element.takeLog();
+    assert_array_equals(logEntries.types(), ['attributeChanged']);
+    assert_attribute_log_entry(logEntries.last(), {name: 'title', oldValue: 'hello world', newValue: 'hello', namespace: null});
+}, 'deleteData on CharacterData must enqueue an attributeChangedCallback when mutating an existing attribute');
+
+test(function () {
+    var element = define_new_custom_element(['title']);
+    var instance = document.createElement(element.name);
+    instance.setAttribute('title', 'hello');
+    assert_array_equals(element.takeLog().types(), ['constructed', 'attributeChanged']);
+    instance.attributes.title.firstChild.replaceData(1, 4, 'i');
+    var logEntries = element.takeLog();
+    assert_array_equals(logEntries.types(), ['attributeChanged']);
+    assert_attribute_log_entry(logEntries.last(), {name: 'title', oldValue: 'hello', newValue: 'hi', namespace: null});
+}, 'replaceData on CharacterData must enqueue an attributeChangedCallback when mutating an existing attribute');
+
+test_with_window(function (contentWindow) {
+    const element = define_custom_element_in_window(contentWindow, 'custom-element', []);
+
+    const contentDocument = contentWindow.document;
+    contentDocument.body.innerHTML = `<select><option></option></select>`;
+    const option = contentDocument.querySelector('option');
+
+    const instance = contentDocument.createElement(element.name);
+    option.appendChild(instance);
+    instance.textContent = 'hello';
+
+    assert_array_equals(element.takeLog().types(), ['constructed', 'connected']);
+    assert_equals(option.innerHTML, '<custom-element>hello</custom-element>');
+
+    const select = contentDocument.querySelector('select');
+    assert_equals(select.options[0], option);
+    select.options.remove(option);
+    assert_equals(select.options.length, 0);
+    assert_array_equals(element.takeLog().types(), ['disconnected']);
+}, 'remove(HTMLOptionElement) on HTMLOptionsCollection must enqueue disconnectedCallback when removing a custom element');
+
+test_with_window(function (contentWindow) {
+    const element = define_custom_element_in_window(contentWindow, 'custom-element', []);
+
+    const contentDocument = contentWindow.document;
+    contentDocument.body.innerHTML = `<select><option></option></select>`;
+    const option = contentDocument.querySelector('option');
+
+    const instance = contentDocument.createElement(element.name);
+    option.appendChild(instance);
+    instance.textContent = 'hello';
+
+    assert_array_equals(element.takeLog().types(), ['constructed', 'connected']);
+    assert_equals(option.innerHTML, '<custom-element>hello</custom-element>');
+
+    const select = contentDocument.querySelector('select');
+    assert_equals(select.options[0], option);
+    select.remove(option);
+    assert_equals(select.options.length, 0);
+    assert_array_equals(element.takeLog().types(), ['disconnected']);
+}, 'remove(HTMLOptionElement) on HTMLSelectElement must enqueue disconnectedCallback when removing a custom element');
+
 </script>
 </body>
 </html>
diff --git a/LayoutTests/fast/custom-elements/reactions/Document-expected.txt b/LayoutTests/fast/custom-elements/reactions/Document-expected.txt
new file mode 100644 (file)
index 0000000..2cfe5dc
--- /dev/null
@@ -0,0 +1,10 @@
+
+PASS title on Document must enqueue disconnectedCallback when removing a custom element 
+PASS body on Document must enqueue disconnectedCallback when removing a custom element 
+PASS body on Document must enqueue connectedCallback when inserting a custom element 
+PASS open on Document must enqueue disconnectedCallback when removing a custom element 
+PASS write on Document must enqueue disconnectedCallback when removing a custom element 
+PASS write on Document must enqueue connectedCallback after constructing a custom element 
+PASS writeln on Document must enqueue disconnectedCallback when removing a custom element 
+PASS writeln on Document must enqueue connectedCallback after constructing a custom element 
+
diff --git a/LayoutTests/fast/custom-elements/reactions/Document.html b/LayoutTests/fast/custom-elements/reactions/Document.html
new file mode 100644 (file)
index 0000000..b7a8225
--- /dev/null
@@ -0,0 +1,112 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>Custom Elements: CEReactions on Document interface</title>
+<meta name="author" title="Ryosuke Niwa" href="mailto:rniwa@webkit.org">
+<meta name="assert" content="title, body, open, write, and writeln of Document interface must have CEReactions">
+<meta name="help" content="https://dom.spec.whatwg.org/#node">
+<script src="../../../resources/testharness.js"></script>
+<script src="../../../resources/testharnessreport.js"></script>
+<script src="../../../imported/w3c/web-platform-tests/custom-elements/resources/custom-elements-helpers.js"></script>
+<script src="../../../imported/w3c/web-platform-tests/custom-elements/reactions/resources/reactions.js"></script>
+<script src="../resources/additional-helpers.js"></script>
+</head>
+<body>
+<div id="log"></div>
+<script>
+
+test_with_window(function (contentWindow) {
+    const element = define_custom_element_in_window(contentWindow, 'custom-element', []);
+
+    const contentDocument = contentWindow.document;
+    contentDocument.title = '';
+    const title = contentDocument.querySelector('title');
+    const instance = document.createElement('custom-element');
+    title.appendChild(instance);
+    instance.textContent = 'hello';
+
+    assert_array_equals(element.takeLog().types(), ['constructed', 'connected']);
+    assert_equals(title.innerHTML, '<custom-element>hello</custom-element>');
+
+    title.text = 'world';
+    assert_equals(title.innerHTML, 'world');
+    assert_array_equals(element.takeLog().types(), ['disconnected']);
+}, 'title on Document must enqueue disconnectedCallback when removing a custom element');
+
+test_with_window(function (contentWindow) {
+    const element = define_custom_element_in_window(contentWindow, 'custom-element', []);
+
+    const contentDocument = contentWindow.document;
+    const body = contentDocument.body;
+    body.innerHTML = '<custom-element>hello</custom-element>';
+
+    assert_array_equals(element.takeLog().types(), ['constructed', 'connected']);
+    assert_equals(body.innerHTML, '<custom-element>hello</custom-element>');
+
+    contentDocument.body = document.createElement('body');
+    assert_array_equals(element.takeLog().types(), ['disconnected']);
+}, 'body on Document must enqueue disconnectedCallback when removing a custom element');
+
+test_with_window(function (contentWindow) {
+    const element = define_custom_element_in_window(contentWindow, 'custom-element', []);
+
+    const contentDocument = contentWindow.document;
+    const instance = contentDocument.createElement('custom-element');
+    const body = contentDocument.createElement('body');
+    body.appendChild(instance);
+
+    assert_array_equals(element.takeLog().types(), ['constructed']);
+    assert_equals(body.innerHTML, '<custom-element></custom-element>');
+
+    contentDocument.body = body;
+    assert_array_equals(element.takeLog().types(), ['connected']);
+}, 'body on Document must enqueue connectedCallback when inserting a custom element');
+
+test_with_window(function (contentWindow) {
+    const element = define_custom_element_in_window(contentWindow, 'custom-element', []);
+
+    const contentDocument = contentWindow.document;
+    contentDocument.body.innerHTML = '<custom-element></custom-element>';
+    assert_array_equals(element.takeLog().types(), ['constructed', 'connected']);
+
+    contentDocument.open();
+    assert_array_equals(element.takeLog().types(), ['disconnected']);
+}, 'open on Document must enqueue disconnectedCallback when removing a custom element');
+
+test_with_window(function (contentWindow) {
+    const element = define_custom_element_in_window(contentWindow, 'custom-element', []);
+
+    const contentDocument = contentWindow.document;
+    contentDocument.body.innerHTML = '<custom-element></custom-element>';
+    assert_array_equals(element.takeLog().types(), ['constructed', 'connected']);
+
+    contentDocument.write('');
+    assert_array_equals(element.takeLog().types(), ['disconnected']);
+}, 'write on Document must enqueue disconnectedCallback when removing a custom element');
+
+test_with_window(function (contentWindow) {
+    const element = define_custom_element_in_window(contentWindow, 'custom-element', []);
+    contentWindow.document.write('<custom-element></custom-element>');
+    assert_array_equals(element.takeLog().types(), ['constructed', 'connected']);
+}, 'write on Document must enqueue connectedCallback after constructing a custom element');
+
+test_with_window(function (contentWindow) {
+    const element = define_custom_element_in_window(contentWindow, 'custom-element', []);
+
+    const contentDocument = contentWindow.document;
+    contentDocument.body.innerHTML = '<custom-element></custom-element>';
+    assert_array_equals(element.takeLog().types(), ['constructed', 'connected']);
+
+    contentDocument.writeln('');
+    assert_array_equals(element.takeLog().types(), ['disconnected']);
+}, 'writeln on Document must enqueue disconnectedCallback when removing a custom element');
+
+test_with_window(function (contentWindow) {
+    const element = define_custom_element_in_window(contentWindow, 'custom-element', []);
+    contentWindow.document.writeln('<custom-element></custom-element>');
+    assert_array_equals(element.takeLog().types(), ['constructed', 'connected']);
+}, 'writeln on Document must enqueue connectedCallback after constructing a custom element');
+
+</script>
+</body>
+</html>
diff --git a/LayoutTests/fast/custom-elements/reactions/HTMLAnchorElement-expected.txt b/LayoutTests/fast/custom-elements/reactions/HTMLAnchorElement-expected.txt
new file mode 100644 (file)
index 0000000..72986c4
--- /dev/null
@@ -0,0 +1,3 @@
+
+PASS text on HTMLAnchorElement must enqueue disconnectedCallback when removing a custom element 
+
diff --git a/LayoutTests/fast/custom-elements/reactions/HTMLAnchorElement.html b/LayoutTests/fast/custom-elements/reactions/HTMLAnchorElement.html
new file mode 100644 (file)
index 0000000..5ab16da
--- /dev/null
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>Custom Elements: CEReactions on HTMLAnchorElement interface</title>
+<meta name="author" title="Ryosuke Niwa" href="mailto:rniwa@webkit.org">
+<meta name="assert" content="text of HTMLAnchorElement interface must have CEReactions">
+<meta name="help" content="https://dom.spec.whatwg.org/#node">
+<script src="../../../resources/testharness.js"></script>
+<script src="../../../resources/testharnessreport.js"></script>
+<script src="../../../imported/w3c/web-platform-tests/custom-elements/resources/custom-elements-helpers.js"></script>
+<script src="../../../imported/w3c/web-platform-tests/custom-elements/reactions/resources/reactions.js"></script>
+<script src="../resources/additional-helpers.js"></script>
+</head>
+<body>
+<div id="log"></div>
+<script>
+
+test_with_window(function (contentWindow) {
+    const element = define_custom_element_in_window(contentWindow, 'custom-element', []);
+
+    const contentDocument = contentWindow.document;
+    contentDocument.body.innerHTML = `<a><custom-element>hello</custom-element></a>`;
+    const anchor = contentDocument.querySelector('a');
+
+    assert_array_equals(element.takeLog().types(), ['constructed', 'connected']);
+    assert_equals(anchor.innerHTML, '<custom-element>hello</custom-element>');
+
+    anchor.text = 'world';
+    assert_equals(anchor.innerHTML, 'world');
+    assert_array_equals(element.takeLog().types(), ['disconnected']);
+}, 'text on HTMLAnchorElement must enqueue disconnectedCallback when removing a custom element');
+
+</script>
+</body>
+</html>
diff --git a/LayoutTests/fast/custom-elements/reactions/HTMLOptionElement-expected.txt b/LayoutTests/fast/custom-elements/reactions/HTMLOptionElement-expected.txt
new file mode 100644 (file)
index 0000000..a2b99f0
--- /dev/null
@@ -0,0 +1,3 @@
+
+PASS text on HTMLOptionElement must enqueue disconnectedCallback when removing a custom element 
+
diff --git a/LayoutTests/fast/custom-elements/reactions/HTMLOptionElement.html b/LayoutTests/fast/custom-elements/reactions/HTMLOptionElement.html
new file mode 100644 (file)
index 0000000..e3c584d
--- /dev/null
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>Custom Elements: CEReactions on HTMLOptionElement interface</title>
+<meta name="author" title="Ryosuke Niwa" href="mailto:rniwa@webkit.org">
+<meta name="assert" content="text of HTMLOptionElement interface must have CEReactions">
+<meta name="help" content="https://dom.spec.whatwg.org/#node">
+<script src="../../../resources/testharness.js"></script>
+<script src="../../../resources/testharnessreport.js"></script>
+<script src="../../../imported/w3c/web-platform-tests/custom-elements/resources/custom-elements-helpers.js"></script>
+<script src="../../../imported/w3c/web-platform-tests/custom-elements/reactions/resources/reactions.js"></script>
+<script src="../resources/additional-helpers.js"></script>
+</head>
+<body>
+<div id="log"></div>
+<script>
+
+test_with_window(function (contentWindow) {
+    const element = define_custom_element_in_window(contentWindow, 'custom-element', []);
+
+    const contentDocument = contentWindow.document;
+    contentDocument.body.innerHTML = `<select><option></option></select>`;
+    const option = contentDocument.querySelector('option');
+    const instance = document.createElement('custom-element');
+    option.appendChild(instance);
+    instance.textContent = 'hello';
+
+    assert_array_equals(element.takeLog().types(), ['constructed', 'connected']);
+    assert_equals(option.innerHTML, '<custom-element>hello</custom-element>');
+
+    option.text = 'world';
+    assert_equals(option.innerHTML, 'world');
+    assert_array_equals(element.takeLog().types(), ['disconnected']);
+}, 'text on HTMLOptionElement must enqueue disconnectedCallback when removing a custom element');
+
+</script>
+</body>
+</html>
diff --git a/LayoutTests/fast/custom-elements/reactions/HTMLOptionsCollection-expected.txt b/LayoutTests/fast/custom-elements/reactions/HTMLOptionsCollection-expected.txt
new file mode 100644 (file)
index 0000000..4bb5dd0
--- /dev/null
@@ -0,0 +1,7 @@
+
+PASS length on HTMLOptionsCollection must enqueue disconnectedCallback when removing a custom element 
+PASS The indexed setter on HTMLOptionsCollection must enqueue connectedCallback when inserting a custom element 
+PASS The indexed setter on HTMLOptionsCollection must enqueue disconnectedCallback when removing a custom element 
+PASS add on HTMLOptionsCollection must enqueue connectedCallback when inserting a custom element 
+PASS remove on HTMLOptionsCollection must enqueue disconnectedCallback when removing a custom element 
+
diff --git a/LayoutTests/fast/custom-elements/reactions/HTMLOptionsCollection.html b/LayoutTests/fast/custom-elements/reactions/HTMLOptionsCollection.html
new file mode 100644 (file)
index 0000000..0015e9f
--- /dev/null
@@ -0,0 +1,125 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>Custom Elements: CEReactions on HTMLOptionsCollection interface</title>
+<meta name="author" title="Ryosuke Niwa" href="mailto:rniwa@webkit.org">
+<meta name="assert" content="length, the indexed setter, add, and remove of HTMLOptionsCollection interface must have CEReactions">
+<meta name="help" content="https://dom.spec.whatwg.org/#node">
+<script src="../../../resources/testharness.js"></script>
+<script src="../../../resources/testharnessreport.js"></script>
+<script src="../../../imported/w3c/web-platform-tests/custom-elements/resources/custom-elements-helpers.js"></script>
+<script src="../../../imported/w3c/web-platform-tests/custom-elements/reactions/resources/reactions.js"></script>
+<script src="../resources/additional-helpers.js"></script>
+</head>
+<body>
+<div id="log"></div>
+<script>
+
+test_with_window(function (contentWindow) {
+    const element = define_custom_element_in_window(contentWindow, 'custom-element', []);
+
+    const contentDocument = contentWindow.document;
+    contentDocument.body.innerHTML = `<select><option></option></select>`;
+    const option = contentDocument.querySelector('option');
+
+    const instance = contentDocument.createElement(element.name);
+    option.appendChild(instance);
+    instance.textContent = 'hello';
+
+    assert_array_equals(element.takeLog().types(), ['constructed', 'connected']);
+    assert_equals(option.innerHTML, '<custom-element>hello</custom-element>');
+
+    const select = contentDocument.querySelector('select');
+    assert_equals(select.options[0], option);
+    select.options.length = 0;
+    assert_equals(select.firstChild, null);
+    assert_array_equals(element.takeLog().types(), ['disconnected']);
+}, 'length on HTMLOptionsCollection must enqueue disconnectedCallback when removing a custom element');
+
+test_with_window(function (contentWindow) {
+    const element = define_custom_element_in_window(contentWindow, 'custom-element', []);
+
+    const contentDocument = contentWindow.document;
+    contentDocument.body.innerHTML = `<select></select>`;
+    const select = contentDocument.querySelector('select');
+
+    const option = contentDocument.createElement('option');
+    const instance = contentDocument.createElement(element.name);
+    option.appendChild(instance);
+    instance.textContent = 'hello';
+
+    assert_array_equals(element.takeLog().types(), ['constructed']);
+    assert_equals(option.innerHTML, '<custom-element>hello</custom-element>');
+
+    assert_equals(select.options.length, 0);
+    select.options[0] = option;
+    assert_equals(select.options.length, 1);
+    assert_array_equals(element.takeLog().types(), ['connected']);
+}, 'The indexed setter on HTMLOptionsCollection must enqueue connectedCallback when inserting a custom element');
+
+test_with_window(function (contentWindow) {
+    const element = define_custom_element_in_window(contentWindow, 'custom-element', []);
+
+    const contentDocument = contentWindow.document;
+    contentDocument.body.innerHTML = `<select><option></option></select>`;
+    const option = contentDocument.querySelector('option');
+
+    const instance = contentDocument.createElement(element.name);
+    option.appendChild(instance);
+    instance.textContent = 'hello';
+
+    assert_array_equals(element.takeLog().types(), ['constructed', 'connected']);
+    assert_equals(option.innerHTML, '<custom-element>hello</custom-element>');
+
+    const select = contentDocument.querySelector('select');
+    assert_equals(select.options[0], option);
+    select.options[0] = null;
+    assert_equals(select.options.length, 0);
+    assert_array_equals(element.takeLog().types(), ['disconnected']);
+}, 'The indexed setter on HTMLOptionsCollection must enqueue disconnectedCallback when removing a custom element');
+
+test_with_window(function (contentWindow) {
+    const element = define_custom_element_in_window(contentWindow, 'custom-element', []);
+
+    const contentDocument = contentWindow.document;
+    contentDocument.body.innerHTML = `<select></select>`;
+    const select = contentDocument.querySelector('select');
+
+    const option = contentDocument.createElement('option');
+    const instance = contentDocument.createElement(element.name);
+    option.appendChild(instance);
+    instance.textContent = 'hello';
+
+    assert_array_equals(element.takeLog().types(), ['constructed']);
+    assert_equals(option.innerHTML, '<custom-element>hello</custom-element>');
+
+    assert_equals(select.options.length, 0);
+    select.options.add(option);
+    assert_equals(select.options.length, 1);
+    assert_array_equals(element.takeLog().types(), ['connected']);
+}, 'add on HTMLOptionsCollection must enqueue connectedCallback when inserting a custom element');
+
+test_with_window(function (contentWindow) {
+    const element = define_custom_element_in_window(contentWindow, 'custom-element', []);
+
+    const contentDocument = contentWindow.document;
+    contentDocument.body.innerHTML = `<select><option></option></select>`;
+    const option = contentDocument.querySelector('option');
+
+    const instance = contentDocument.createElement(element.name);
+    option.appendChild(instance);
+    instance.textContent = 'hello';
+
+    assert_array_equals(element.takeLog().types(), ['constructed', 'connected']);
+    assert_equals(option.innerHTML, '<custom-element>hello</custom-element>');
+
+    const select = contentDocument.querySelector('select');
+    assert_equals(select.options[0], option);
+    select.options.remove(0);
+    assert_equals(select.options.length, 0);
+    assert_array_equals(element.takeLog().types(), ['disconnected']);
+}, 'remove on HTMLOptionsCollection must enqueue disconnectedCallback when removing a custom element');
+
+</script>
+</body>
+</html>
diff --git a/LayoutTests/fast/custom-elements/reactions/HTMLOutputElement-expected.txt b/LayoutTests/fast/custom-elements/reactions/HTMLOutputElement-expected.txt
new file mode 100644 (file)
index 0000000..28f3dd4
--- /dev/null
@@ -0,0 +1,4 @@
+
+PASS value on HTMLOutputElement must enqueue disconnectedCallback when removing a custom element 
+PASS defaultValue on HTMLOutputElement must enqueue disconnectedCallback when removing a custom element 
+
diff --git a/LayoutTests/fast/custom-elements/reactions/HTMLOutputElement.html b/LayoutTests/fast/custom-elements/reactions/HTMLOutputElement.html
new file mode 100644 (file)
index 0000000..4763413
--- /dev/null
@@ -0,0 +1,50 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>Custom Elements: CEReactions on HTMLOutputElement interface</title>
+<meta name="author" title="Ryosuke Niwa" href="mailto:rniwa@webkit.org">
+<meta name="assert" content="value and defaultValue of HTMLOutputElement interface must have CEReactions">
+<meta name="help" content="https://dom.spec.whatwg.org/#node">
+<script src="../../../resources/testharness.js"></script>
+<script src="../../../resources/testharnessreport.js"></script>
+<script src="../../../imported/w3c/web-platform-tests/custom-elements/resources/custom-elements-helpers.js"></script>
+<script src="../../../imported/w3c/web-platform-tests/custom-elements/reactions/resources/reactions.js"></script>
+<script src="../resources/additional-helpers.js"></script>
+</head>
+<body>
+<div id="log"></div>
+<script>
+
+test_with_window(function (contentWindow) {
+    const element = define_custom_element_in_window(contentWindow, 'custom-element', []);
+
+    const contentDocument = contentWindow.document;
+    contentDocument.body.innerHTML = `<output><custom-element>hello</custom-element></output>`;
+    const anchor = contentDocument.querySelector('output');
+
+    assert_array_equals(element.takeLog().types(), ['constructed', 'connected']);
+    assert_equals(anchor.innerHTML, '<custom-element>hello</custom-element>');
+
+    anchor.value = 'world';
+    assert_equals(anchor.innerHTML, 'world');
+    assert_array_equals(element.takeLog().types(), ['disconnected']);
+}, 'value on HTMLOutputElement must enqueue disconnectedCallback when removing a custom element');
+
+test_with_window(function (contentWindow) {
+    const element = define_custom_element_in_window(contentWindow, 'custom-element', []);
+
+    const contentDocument = contentWindow.document;
+    contentDocument.body.innerHTML = `<output><custom-element>hello</custom-element></output>`;
+    const anchor = contentDocument.querySelector('output');
+
+    assert_array_equals(element.takeLog().types(), ['constructed', 'connected']);
+    assert_equals(anchor.innerHTML, '<custom-element>hello</custom-element>');
+
+    anchor.defaultValue = 'world';
+    assert_equals(anchor.innerHTML, 'world');
+    assert_array_equals(element.takeLog().types(), ['disconnected']);
+}, 'defaultValue on HTMLOutputElement must enqueue disconnectedCallback when removing a custom element');
+
+</script>
+</body>
+</html>
diff --git a/LayoutTests/fast/custom-elements/reactions/HTMLSelectElement-expected.txt b/LayoutTests/fast/custom-elements/reactions/HTMLSelectElement-expected.txt
new file mode 100644 (file)
index 0000000..36f1d97
--- /dev/null
@@ -0,0 +1,7 @@
+
+PASS length on HTMLSelectElement must enqueue disconnectedCallback when removing a custom element 
+PASS The indexed setter on HTMLSelectElement must enqueue connectedCallback when inserting a custom element 
+PASS The indexed setter on HTMLSelectElement must enqueue disconnectedCallback when removing a custom element 
+PASS add on HTMLSelectElement must enqueue connectedCallback when inserting a custom element 
+PASS remove on HTMLSelectElement must enqueue disconnectedCallback when removing a custom element 
+
diff --git a/LayoutTests/fast/custom-elements/reactions/HTMLSelectElement.html b/LayoutTests/fast/custom-elements/reactions/HTMLSelectElement.html
new file mode 100644 (file)
index 0000000..5eed053
--- /dev/null
@@ -0,0 +1,125 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>Custom Elements: CEReactions on HTMLSelectElement interface</title>
+<meta name="author" title="Ryosuke Niwa" href="mailto:rniwa@webkit.org">
+<meta name="assert" content="length, add, remove, and the setter of HTMLSelectElement interface must have CEReactions">
+<meta name="help" content="https://dom.spec.whatwg.org/#node">
+<script src="../../../resources/testharness.js"></script>
+<script src="../../../resources/testharnessreport.js"></script>
+<script src="../../../imported/w3c/web-platform-tests/custom-elements/resources/custom-elements-helpers.js"></script>
+<script src="../../../imported/w3c/web-platform-tests/custom-elements/reactions/resources/reactions.js"></script>
+<script src="../resources/additional-helpers.js"></script>
+</head>
+<body>
+<div id="log"></div>
+<script>
+
+test_with_window(function (contentWindow) {
+    const element = define_custom_element_in_window(contentWindow, 'custom-element', []);
+
+    const contentDocument = contentWindow.document;
+    contentDocument.body.innerHTML = `<select><option></option></select>`;
+    const option = contentDocument.querySelector('option');
+
+    const instance = contentDocument.createElement(element.name);
+    option.appendChild(instance);
+    instance.textContent = 'hello';
+
+    assert_array_equals(element.takeLog().types(), ['constructed', 'connected']);
+    assert_equals(option.innerHTML, '<custom-element>hello</custom-element>');
+
+    const select = contentDocument.querySelector('select');
+    assert_equals(select.length, 1);
+    select.length = 0;
+    assert_equals(select.firstChild, null);
+    assert_array_equals(element.takeLog().types(), ['disconnected']);
+}, 'length on HTMLSelectElement must enqueue disconnectedCallback when removing a custom element');
+
+test_with_window(function (contentWindow) {
+    const element = define_custom_element_in_window(contentWindow, 'custom-element', []);
+
+    const contentDocument = contentWindow.document;
+    contentDocument.body.innerHTML = `<select></select>`;
+    const select = contentDocument.querySelector('select');
+
+    const option = contentDocument.createElement('option');
+    const instance = contentDocument.createElement(element.name);
+    option.appendChild(instance);
+    instance.textContent = 'hello';
+
+    assert_array_equals(element.takeLog().types(), ['constructed']);
+    assert_equals(option.innerHTML, '<custom-element>hello</custom-element>');
+
+    assert_equals(select.options.length, 0);
+    select[0] = option;
+    assert_equals(select.options.length, 1);
+    assert_array_equals(element.takeLog().types(), ['connected']);
+}, 'The indexed setter on HTMLSelectElement must enqueue connectedCallback when inserting a custom element');
+
+test_with_window(function (contentWindow) {
+    const element = define_custom_element_in_window(contentWindow, 'custom-element', []);
+
+    const contentDocument = contentWindow.document;
+    contentDocument.body.innerHTML = `<select><option></option></select>`;
+    const option = contentDocument.querySelector('option');
+
+    const instance = contentDocument.createElement(element.name);
+    option.appendChild(instance);
+    instance.textContent = 'hello';
+
+    assert_array_equals(element.takeLog().types(), ['constructed', 'connected']);
+    assert_equals(option.innerHTML, '<custom-element>hello</custom-element>');
+
+    const select = contentDocument.querySelector('select');
+    assert_equals(select.options[0], option);
+    select[0] = null;
+    assert_equals(select.options.length, 0);
+    assert_array_equals(element.takeLog().types(), ['disconnected']);
+}, 'The indexed setter on HTMLSelectElement must enqueue disconnectedCallback when removing a custom element');
+
+test_with_window(function (contentWindow) {
+    const element = define_custom_element_in_window(contentWindow, 'custom-element', []);
+
+    const contentDocument = contentWindow.document;
+    contentDocument.body.innerHTML = `<select></select>`;
+    const select = contentDocument.querySelector('select');
+
+    const option = contentDocument.createElement('option');
+    const instance = contentDocument.createElement(element.name);
+    option.appendChild(instance);
+    instance.textContent = 'hello';
+
+    assert_array_equals(element.takeLog().types(), ['constructed']);
+    assert_equals(option.innerHTML, '<custom-element>hello</custom-element>');
+
+    assert_equals(select.options.length, 0);
+    select.add(option);
+    assert_equals(select.options.length, 1);
+    assert_array_equals(element.takeLog().types(), ['connected']);
+}, 'add on HTMLSelectElement must enqueue connectedCallback when inserting a custom element');
+
+test_with_window(function (contentWindow) {
+    const element = define_custom_element_in_window(contentWindow, 'custom-element', []);
+
+    const contentDocument = contentWindow.document;
+    contentDocument.body.innerHTML = `<select><option></option></select>`;
+    const option = contentDocument.querySelector('option');
+
+    const instance = contentDocument.createElement(element.name);
+    option.appendChild(instance);
+    instance.textContent = 'hello';
+
+    assert_array_equals(element.takeLog().types(), ['constructed', 'connected']);
+    assert_equals(option.innerHTML, '<custom-element>hello</custom-element>');
+
+    const select = contentDocument.querySelector('select');
+    assert_equals(select.options[0], option);
+    select.remove(0);
+    assert_equals(select.options.length, 0);
+    assert_array_equals(element.takeLog().types(), ['disconnected']);
+}, 'remove on HTMLSelectElement must enqueue disconnectedCallback when removing a custom element');
+
+</script>
+</body>
+</html>
diff --git a/LayoutTests/fast/custom-elements/reactions/HTMLTableElement-expected.txt b/LayoutTests/fast/custom-elements/reactions/HTMLTableElement-expected.txt
new file mode 100644 (file)
index 0000000..3131e12
--- /dev/null
@@ -0,0 +1,12 @@
+
+PASS caption on HTMLTableElement must enqueue connectedCallback when inserting a custom element 
+PASS caption on HTMLTableElement must enqueue disconnectedCallback when removing a custom element 
+PASS deleteCaption() on HTMLTableElement must enqueue disconnectedCallback when removing a custom element 
+PASS tHead on HTMLTableElement must enqueue connectedCallback when inserting a custom element 
+PASS tHead on HTMLTableElement must enqueue disconnectedCallback when removing a custom element 
+PASS deleteTHead() on HTMLTableElement must enqueue disconnectedCallback when removing a custom element 
+PASS tFoot on HTMLTableElement must enqueue connectedCallback when inserting a custom element 
+PASS tFoot on HTMLTableElement must enqueue disconnectedCallback when removing a custom element 
+PASS deleteTFoot() on HTMLTableElement must enqueue disconnectedCallback when removing a custom element 
+PASS deleteRow() on HTMLTableElement must enqueue disconnectedCallback when removing a custom element 
+
diff --git a/LayoutTests/fast/custom-elements/reactions/HTMLTableElement.html b/LayoutTests/fast/custom-elements/reactions/HTMLTableElement.html
new file mode 100644 (file)
index 0000000..0f92b60
--- /dev/null
@@ -0,0 +1,194 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>Custom Elements: CEReactions on HTMLTableElement interface</title>
+<meta name="author" title="Ryosuke Niwa" href="mailto:rniwa@webkit.org">
+<meta name="assert" content="caption, deleteCaption, thead, deleteTHead, tFoot, deleteTFoot, and deleteRow of HTMLTableElement interface must have CEReactions">
+<meta name="help" content="https://dom.spec.whatwg.org/#node">
+<script src="../../../resources/testharness.js"></script>
+<script src="../../../resources/testharnessreport.js"></script>
+<script src="../../../imported/w3c/web-platform-tests/custom-elements/resources/custom-elements-helpers.js"></script>
+<script src="../../../imported/w3c/web-platform-tests/custom-elements/reactions/resources/reactions.js"></script>
+<script src="../resources/additional-helpers.js"></script>
+</head>
+<body>
+<div id="log"></div>
+<script>
+
+test_with_window(function (contentWindow) {
+    const element = define_custom_element_in_window(contentWindow, 'custom-element', []);
+
+    const contentDocument = contentWindow.document;
+    contentDocument.body.innerHTML = `<table></table>`;
+    const table = contentDocument.querySelector('table');
+
+    const caption = contentDocument.createElement('caption');
+    caption.innerHTML = '<custom-element>hello</custom-element>';
+
+    assert_array_equals(element.takeLog().types(), ['constructed']);
+    assert_equals(caption.innerHTML, '<custom-element>hello</custom-element>');
+
+    assert_equals(table.caption, null);
+    table.caption = caption;
+    assert_array_equals(element.takeLog().types(), ['connected']);
+}, 'caption on HTMLTableElement must enqueue connectedCallback when inserting a custom element');
+
+test_with_window(function (contentWindow) {
+    const element = define_custom_element_in_window(contentWindow, 'custom-element', []);
+
+    const contentDocument = contentWindow.document;
+    contentDocument.body.innerHTML = `<table><caption><custom-element>hello</custom-element></caption></table>`;
+    const caption = contentDocument.querySelector('caption');
+    assert_array_equals(element.takeLog().types(), ['constructed', 'connected']);
+    assert_equals(caption.innerHTML, '<custom-element>hello</custom-element>');
+
+    const table = contentDocument.querySelector('table');
+    assert_equals(table.caption, caption);
+    const newCaption = contentDocument.createElement('caption');
+    table.caption = newCaption; // Chrome doesn't support setting to null.
+    assert_equals(table.caption, newCaption);
+    assert_array_equals(element.takeLog().types(), ['disconnected']);
+}, 'caption on HTMLTableElement must enqueue disconnectedCallback when removing a custom element');
+
+test_with_window(function (contentWindow) {
+    const element = define_custom_element_in_window(contentWindow, 'custom-element', []);
+
+    const contentDocument = contentWindow.document;
+    contentDocument.body.innerHTML = `<table><caption><custom-element>hello</custom-element></caption></table>`;
+    const caption = contentDocument.querySelector('caption');
+    assert_array_equals(element.takeLog().types(), ['constructed', 'connected']);
+    assert_equals(caption.innerHTML, '<custom-element>hello</custom-element>');
+
+    const table = contentDocument.querySelector('table');
+    assert_equals(table.caption, caption);
+    const newCaption = contentDocument.createElement('caption');
+    table.deleteCaption();
+    assert_equals(table.caption, null);
+    assert_array_equals(element.takeLog().types(), ['disconnected']);
+}, 'deleteCaption() on HTMLTableElement must enqueue disconnectedCallback when removing a custom element');
+
+
+test_with_window(function (contentWindow) {
+    const element = define_custom_element_in_window(contentWindow, 'custom-element', []);
+
+    const contentDocument = contentWindow.document;
+    contentDocument.body.innerHTML = `<table></table>`;
+    const table = contentDocument.querySelector('table');
+
+    const thead = contentDocument.createElement('thead');
+    thead.innerHTML = '<tr><td><custom-element>hello</custom-element></td></tr>';
+
+    assert_array_equals(element.takeLog().types(), ['constructed']);
+    assert_equals(thead.innerHTML, '<tr><td><custom-element>hello</custom-element></td></tr>');
+
+    assert_equals(table.tHead, null);
+    table.tHead = thead;
+    assert_array_equals(element.takeLog().types(), ['connected']);
+}, 'tHead on HTMLTableElement must enqueue connectedCallback when inserting a custom element');
+
+test_with_window(function (contentWindow) {
+    const element = define_custom_element_in_window(contentWindow, 'custom-element', []);
+
+    const contentDocument = contentWindow.document;
+    contentDocument.body.innerHTML = `<table><thead><tr><td><custom-element>hello</custom-element></td></tr></thead></table>`;
+    const thead = contentDocument.querySelector('thead');
+    assert_array_equals(element.takeLog().types(), ['constructed', 'connected']);
+    assert_equals(thead.innerHTML, '<tr><td><custom-element>hello</custom-element></td></tr>');
+
+    const table = contentDocument.querySelector('table');
+    assert_equals(table.tHead, thead);
+    const newThead = contentDocument.createElement('thead');
+    table.tHead = newThead; // Chrome doesn't support setting to null.
+    assert_equals(table.tHead, newThead);
+    assert_array_equals(element.takeLog().types(), ['disconnected']);
+}, 'tHead on HTMLTableElement must enqueue disconnectedCallback when removing a custom element');
+
+test_with_window(function (contentWindow) {
+    const element = define_custom_element_in_window(contentWindow, 'custom-element', []);
+
+    const contentDocument = contentWindow.document;
+    contentDocument.body.innerHTML = `<table><thead><tr><td><custom-element>hello</custom-element></td></tr></thead></table>`;
+    const thead = contentDocument.querySelector('thead');
+    assert_array_equals(element.takeLog().types(), ['constructed', 'connected']);
+    assert_equals(thead.innerHTML, '<tr><td><custom-element>hello</custom-element></td></tr>');
+
+    const table = contentDocument.querySelector('table');
+    assert_equals(table.tHead, thead);
+    table.deleteTHead();
+    assert_equals(table.tHead, null);
+    assert_array_equals(element.takeLog().types(), ['disconnected']);
+}, 'deleteTHead() on HTMLTableElement must enqueue disconnectedCallback when removing a custom element');
+
+
+test_with_window(function (contentWindow) {
+    const element = define_custom_element_in_window(contentWindow, 'custom-element', []);
+
+    const contentDocument = contentWindow.document;
+    contentDocument.body.innerHTML = `<table></table>`;
+    const table = contentDocument.querySelector('table');
+
+    const tfoot = contentDocument.createElement('tfoot');
+    tfoot.innerHTML = '<tr><td><custom-element>hello</custom-element></td></tr>';
+
+    assert_array_equals(element.takeLog().types(), ['constructed']);
+    assert_equals(tfoot.innerHTML, '<tr><td><custom-element>hello</custom-element></td></tr>');
+
+    assert_equals(table.tFoot, null);
+    table.tFoot = tfoot;
+    assert_array_equals(element.takeLog().types(), ['connected']);
+}, 'tFoot on HTMLTableElement must enqueue connectedCallback when inserting a custom element');
+
+test_with_window(function (contentWindow) {
+    const element = define_custom_element_in_window(contentWindow, 'custom-element', []);
+
+    const contentDocument = contentWindow.document;
+    contentDocument.body.innerHTML = `<table><tfoot><tr><td><custom-element>hello</custom-element></td></tr></tfoot></table>`;
+    const tfoot = contentDocument.querySelector('tfoot');
+    assert_array_equals(element.takeLog().types(), ['constructed', 'connected']);
+    assert_equals(tfoot.innerHTML, '<tr><td><custom-element>hello</custom-element></td></tr>');
+
+    const table = contentDocument.querySelector('table');
+    assert_equals(table.tFoot, tfoot);
+    const newThead = contentDocument.createElement('tfoot');
+    table.tFoot = newThead; // Chrome doesn't support setting to null.
+    assert_equals(table.tFoot, newThead);
+    assert_array_equals(element.takeLog().types(), ['disconnected']);
+}, 'tFoot on HTMLTableElement must enqueue disconnectedCallback when removing a custom element');
+
+test_with_window(function (contentWindow) {
+    const element = define_custom_element_in_window(contentWindow, 'custom-element', []);
+
+    const contentDocument = contentWindow.document;
+    contentDocument.body.innerHTML = `<table><tfoot><tr><td><custom-element>hello</custom-element></td></tr></tfoot></table>`;
+    const tfoot = contentDocument.querySelector('tfoot');
+    assert_array_equals(element.takeLog().types(), ['constructed', 'connected']);
+    assert_equals(tfoot.innerHTML, '<tr><td><custom-element>hello</custom-element></td></tr>');
+
+    const table = contentDocument.querySelector('table');
+    assert_equals(table.tFoot, tfoot);
+    table.deleteTFoot();
+    assert_equals(table.tFoot, null);
+    assert_array_equals(element.takeLog().types(), ['disconnected']);
+}, 'deleteTFoot() on HTMLTableElement must enqueue disconnectedCallback when removing a custom element');
+
+
+test_with_window(function (contentWindow) {
+    const element = define_custom_element_in_window(contentWindow, 'custom-element', []);
+
+    const contentDocument = contentWindow.document;
+    contentDocument.body.innerHTML = `<table><tr><td><custom-element>hello</custom-element></td></tr></table>`;
+    const tr = contentDocument.querySelector('tr');
+    assert_array_equals(element.takeLog().types(), ['constructed', 'connected']);
+    assert_equals(tr.innerHTML, '<td><custom-element>hello</custom-element></td>');
+
+    const table = contentDocument.querySelector('table');
+    assert_equals(table.rows.length, 1);
+    assert_equals(table.rows[0], tr);
+    table.deleteRow(0);
+    assert_equals(table.rows.length, 0);
+    assert_array_equals(element.takeLog().types(), ['disconnected']);
+}, 'deleteRow() on HTMLTableElement must enqueue disconnectedCallback when removing a custom element');
+
+</script>
+</body>
+</html>
diff --git a/LayoutTests/fast/custom-elements/reactions/HTMLTableRowElement-expected.txt b/LayoutTests/fast/custom-elements/reactions/HTMLTableRowElement-expected.txt
new file mode 100644 (file)
index 0000000..dc62117
--- /dev/null
@@ -0,0 +1,3 @@
+
+PASS deleteCell() on HTMLTableRowElement must enqueue disconnectedCallback when removing a custom element 
+
diff --git a/LayoutTests/fast/custom-elements/reactions/HTMLTableRowElement.html b/LayoutTests/fast/custom-elements/reactions/HTMLTableRowElement.html
new file mode 100644 (file)
index 0000000..9fde0d7
--- /dev/null
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>Custom Elements: CEReactions on HTMLTableRowElement interface</title>
+<meta name="author" title="Ryosuke Niwa" href="mailto:rniwa@webkit.org">
+<meta name="assert" content="deleteCell of HTMLTableRowElement interface must have CEReactions">
+<meta name="help" content="https://dom.spec.whatwg.org/#node">
+<script src="../../../resources/testharness.js"></script>
+<script src="../../../resources/testharnessreport.js"></script>
+<script src="../../../imported/w3c/web-platform-tests/custom-elements/resources/custom-elements-helpers.js"></script>
+<script src="../../../imported/w3c/web-platform-tests/custom-elements/reactions/resources/reactions.js"></script>
+<script src="../resources/additional-helpers.js"></script>
+</head>
+<body>
+<div id="log"></div>
+<script>
+
+test_with_window(function (contentWindow) {
+    const element = define_custom_element_in_window(contentWindow, 'custom-element', []);
+
+    const contentDocument = contentWindow.document;
+    contentDocument.body.innerHTML = `<table><tr><td><custom-element>hello</custom-element></td></tr></table>`;
+    const td = contentDocument.querySelector('td');
+    assert_array_equals(element.takeLog().types(), ['constructed', 'connected']);
+    assert_equals(td.innerHTML, '<custom-element>hello</custom-element>');
+
+    const table = contentDocument.querySelector('table');
+    const row = table.rows[0];
+    assert_equals(row.cells[0], td);
+    row.deleteCell(0);
+    assert_equals(row.cells.length, 0);
+    assert_array_equals(element.takeLog().types(), ['disconnected']);
+}, 'deleteCell() on HTMLTableRowElement must enqueue disconnectedCallback when removing a custom element');
+
+</script>
+</body>
+</html>
diff --git a/LayoutTests/fast/custom-elements/reactions/HTMLTableSectionElement-expected.txt b/LayoutTests/fast/custom-elements/reactions/HTMLTableSectionElement-expected.txt
new file mode 100644 (file)
index 0000000..1a04bca
--- /dev/null
@@ -0,0 +1,4 @@
+
+PASS deleteRow() on HTMLTableSectionElement on thead must enqueue disconnectedCallback when removing a custom element 
+PASS deleteRow() on HTMLTableSectionElement on tfoot must enqueue disconnectedCallback when removing a custom element 
+
diff --git a/LayoutTests/fast/custom-elements/reactions/HTMLTableSectionElement.html b/LayoutTests/fast/custom-elements/reactions/HTMLTableSectionElement.html
new file mode 100644 (file)
index 0000000..d0985da
--- /dev/null
@@ -0,0 +1,50 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>Custom Elements: CEReactions on HTMLTableSectionElement interface</title>
+<meta name="author" title="Ryosuke Niwa" href="mailto:rniwa@webkit.org">
+<meta name="assert" content="deleteRow of HTMLTableSectionElement interface must have CEReactions">
+<meta name="help" content="https://dom.spec.whatwg.org/#node">
+<script src="../../../resources/testharness.js"></script>
+<script src="../../../resources/testharnessreport.js"></script>
+<script src="../../../imported/w3c/web-platform-tests/custom-elements/resources/custom-elements-helpers.js"></script>
+<script src="../../../imported/w3c/web-platform-tests/custom-elements/reactions/resources/reactions.js"></script>
+<script src="../resources/additional-helpers.js"></script>
+</head>
+<body>
+<div id="log"></div>
+<script>
+
+test_with_window(function (contentWindow) {
+    const element = define_custom_element_in_window(contentWindow, 'custom-element', []);
+
+    const contentDocument = contentWindow.document;
+    contentDocument.body.innerHTML = `<table><thead><tr><td><custom-element>hello</custom-element></td></tr></thead></table>`;
+    const thead = contentDocument.querySelector('thead');
+    assert_array_equals(element.takeLog().types(), ['constructed', 'connected']);
+    assert_equals(thead.innerHTML, '<tr><td><custom-element>hello</custom-element></td></tr>');
+
+    const table = contentDocument.querySelector('table');
+    assert_equals(table.tHead, thead);
+    table.tHead.deleteRow(0);
+    assert_array_equals(element.takeLog().types(), ['disconnected']);
+}, 'deleteRow() on HTMLTableSectionElement on thead must enqueue disconnectedCallback when removing a custom element');
+
+test_with_window(function (contentWindow) {
+    const element = define_custom_element_in_window(contentWindow, 'custom-element', []);
+
+    const contentDocument = contentWindow.document;
+    contentDocument.body.innerHTML = `<table><tfoot><tr><td><custom-element>hello</custom-element></td></tr></tfoot></table>`;
+    const tfoot = contentDocument.querySelector('tfoot');
+    assert_array_equals(element.takeLog().types(), ['constructed', 'connected']);
+    assert_equals(tfoot.innerHTML, '<tr><td><custom-element>hello</custom-element></td></tr>');
+
+    const table = contentDocument.querySelector('table');
+    assert_equals(table.tFoot, tfoot);
+    table.tFoot.deleteRow(0);
+    assert_array_equals(element.takeLog().types(), ['disconnected']);
+}, 'deleteRow() on HTMLTableSectionElement on tfoot must enqueue disconnectedCallback when removing a custom element');
+
+</script>
+</body>
+</html>
diff --git a/LayoutTests/fast/custom-elements/reactions/HTMLTitleElement-expected.txt b/LayoutTests/fast/custom-elements/reactions/HTMLTitleElement-expected.txt
new file mode 100644 (file)
index 0000000..d76ac3f
--- /dev/null
@@ -0,0 +1,3 @@
+
+PASS text on HTMLTitleElement must enqueue disconnectedCallback when removing a custom element 
+
diff --git a/LayoutTests/fast/custom-elements/reactions/HTMLTitleElement.html b/LayoutTests/fast/custom-elements/reactions/HTMLTitleElement.html
new file mode 100644 (file)
index 0000000..ace832a
--- /dev/null
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>Custom Elements: CEReactions on HTMLTitleElement interface</title>
+<meta name="author" title="Ryosuke Niwa" href="mailto:rniwa@webkit.org">
+<meta name="assert" content="text of HTMLTitleElement interface must have CEReactions">
+<meta name="help" content="https://dom.spec.whatwg.org/#node">
+<script src="../../../resources/testharness.js"></script>
+<script src="../../../resources/testharnessreport.js"></script>
+<script src="../../../imported/w3c/web-platform-tests/custom-elements/resources/custom-elements-helpers.js"></script>
+<script src="../../../imported/w3c/web-platform-tests/custom-elements/reactions/resources/reactions.js"></script>
+<script src="../resources/additional-helpers.js"></script>
+</head>
+<body>
+<div id="log"></div>
+<script>
+
+test_with_window(function (contentWindow) {
+    const element = define_custom_element_in_window(contentWindow, 'custom-element', []);
+    const instance = contentWindow.document.createElement(element.name);
+    assert_array_equals(element.takeLog().types(), ['constructed']);
+
+    contentWindow.document.title = 'hello';
+    var titleElement = contentWindow.document.querySelector('title');
+    titleElement.appendChild(instance);
+    assert_array_equals(element.takeLog().types(), ['connected']);
+    assert_equals(titleElement.childNodes.length, 2);
+
+    titleElement.text = 'world';
+    assert_equals(titleElement.childNodes.length, 1);
+    assert_array_equals(element.takeLog().types(), ['disconnected']);
+}, 'text on HTMLTitleElement must enqueue disconnectedCallback when removing a custom element');
+
+</script>
+</body>
+</html>
diff --git a/LayoutTests/fast/custom-elements/reactions/ShadowRoot-expected.txt b/LayoutTests/fast/custom-elements/reactions/ShadowRoot-expected.txt
new file mode 100644 (file)
index 0000000..23cc3bd
--- /dev/null
@@ -0,0 +1,5 @@
+
+PASS innerHTML on ShadowRoot must upgrade a custom element 
+PASS innerHTML on ShadowRoot must enqueue connectedCallback on newly upgraded custom elements when the shadow root is connected 
+PASS innerHTML on ShadowRoot must enqueue disconnectedCallback when removing a custom element 
+
diff --git a/LayoutTests/fast/custom-elements/reactions/ShadowRoot.html b/LayoutTests/fast/custom-elements/reactions/ShadowRoot.html
new file mode 100644 (file)
index 0000000..4b3a392
--- /dev/null
@@ -0,0 +1,59 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>Custom Elements: CEReactions on ShadowRoot interface</title>
+<meta name="author" title="Ryosuke Niwa" href="mailto:rniwa@webkit.org">
+<meta name="assert" content="innerHTML of ShadowRoot interface must have CEReactions">
+<meta name="help" content="https://dom.spec.whatwg.org/#node">
+<script src="../../../resources/testharness.js"></script>
+<script src="../../../resources/testharnessreport.js"></script>
+<script src="../../../imported/w3c/web-platform-tests/custom-elements/resources/custom-elements-helpers.js"></script>
+<script src="../../../imported/w3c/web-platform-tests/custom-elements/reactions/resources/reactions.js"></script>
+<script src="../resources/additional-helpers.js"></script>
+</head>
+<body>
+<div id="log"></div>
+<script>
+
+test_with_window(function (contentWindow) {
+    const element = define_custom_element_in_window(contentWindow, 'custom-element', []);
+
+    const contentDocument = contentWindow.document;
+    const host = contentDocument.createElement('div');
+    const shadowRoot = host.attachShadow({mode: 'closed'});
+    shadowRoot.innerHTML = '<custom-element></custom-element>';
+
+    assert_array_equals(element.takeLog().types(), ['constructed']);
+}, 'innerHTML on ShadowRoot must upgrade a custom element');
+
+test_with_window(function (contentWindow) {
+    const element = define_custom_element_in_window(contentWindow, 'custom-element', []);
+
+    const contentDocument = contentWindow.document;
+    const host = contentDocument.createElement('div');
+    contentDocument.body.appendChild(host);
+    const shadowRoot = host.attachShadow({mode: 'closed'});
+    shadowRoot.innerHTML = '<custom-element></custom-element>';
+
+    assert_array_equals(element.takeLog().types(), ['constructed', 'connected']);
+}, 'innerHTML on ShadowRoot must enqueue connectedCallback on newly upgraded custom elements when the shadow root is connected');
+
+test_with_window(function (contentWindow) {
+    const element = define_custom_element_in_window(contentWindow, 'custom-element', []);
+
+    const contentDocument = contentWindow.document;
+    const host = contentDocument.createElement('div');
+    contentDocument.body.appendChild(host);
+
+    const shadowRoot = host.attachShadow({mode: 'closed'});
+    shadowRoot.innerHTML = '<custom-element></custom-element>';
+    assert_array_equals(element.takeLog().types(), ['constructed', 'connected']);
+
+    shadowRoot.innerHTML = '';
+    assert_array_equals(element.takeLog().types(), ['disconnected']);
+
+}, 'innerHTML on ShadowRoot must enqueue disconnectedCallback when removing a custom element');
+
+</script>
+</body>
+</html>
diff --git a/LayoutTests/fast/custom-elements/resources/additional-helpers.js b/LayoutTests/fast/custom-elements/resources/additional-helpers.js
new file mode 100644 (file)
index 0000000..3bb918e
--- /dev/null
@@ -0,0 +1,48 @@
+function create_constructor_log(element) {
+    return {type: 'constructed', element: element};
+}
+
+function assert_constructor_log_entry(log, element) {
+    assert_equals(log.type, 'constructed');
+    assert_equals(log.element, element);
+}
+
+function create_connected_callback_log(element) {
+    return {type: 'connected', element: element};
+}
+
+function assert_connected_log_entry(log, element) {
+    assert_equals(log.type, 'connected');
+    assert_equals(log.element, element);
+}
+
+function define_custom_element_in_window(window, name, observedAttributes) {
+    let log = [];
+
+    class CustomElement extends window.HTMLElement {
+        constructor() {
+            super();
+            log.push({type: 'constructed', element: this});
+        }
+        attributeChangedCallback(...args) {
+            log.push(create_attribute_changed_callback_log(this, ...args));
+        }
+        connectedCallback() { log.push({type: 'connected', element: this}); }
+        disconnectedCallback() { log.push({type: 'disconnected', element: this}); }
+        adoptedCallback(oldDocument, newDocument) { log.push({type: 'adopted', element: this, oldDocument: oldDocument, newDocument: newDocument}); }
+    }
+    CustomElement.observedAttributes = observedAttributes;
+
+    window.customElements.define(name, CustomElement);
+
+    return {
+        name: name,
+        class: CustomElement,
+        takeLog: function () {
+            let currentLog = log; log = [];
+            currentLog.types = () => currentLog.map((entry) => entry.type);
+            currentLog.last = () => currentLog[currentLog.length - 1];
+            return currentLog;
+        }
+    };
+}
index 78e03e4..a0dddea 100644 (file)
@@ -1,4 +1,4 @@
-CONSOLE MESSAGE: line 157: Exception thrown as a part of test
+CONSOLE MESSAGE: line 140: Exception thrown as a part of test
 
 PASS Upgrading a custom element must enqueue attributeChangedCallback on each attribute 
 PASS Upgrading a custom element not must enqueue attributeChangedCallback on unobserved attributes 
index 45e4316..cc5c6b2 100644 (file)
@@ -8,30 +8,13 @@
 <script src="../../resources/testharness.js"></script>
 <script src="../../resources/testharnessreport.js"></script>
 <script src="../../imported/w3c/web-platform-tests/custom-elements/resources/custom-elements-helpers.js"></script>
+<script src="resources/additional-helpers.js"></script>
 </head>
 <body>
 <div id="log"></div>
 <script>
 setup({allow_uncaught_exception:true});
 
-function create_constructor_log(element) {
-    return {type: 'constructed', element: element};
-}
-
-function assert_constructor_log_entry(log, element) {
-    assert_equals(log.type, 'constructed');
-    assert_equals(log.element, element);
-}
-
-function create_connected_callback_log(element) {
-    return {type: 'connected', element: element};
-}
-
-function assert_connected_log_entry(log, element) {
-    assert_equals(log.type, 'connected');
-    assert_equals(log.element, element);
-}
-
 test_with_window(function (contentWindow) {
     const contentDocument = contentWindow.document;
     contentDocument.write('<test-element id="some" title="This is a test">');
index d832820..9267da5 100644 (file)
@@ -1636,6 +1636,7 @@ webkit.org/b/88080 http/tests/pointer-lock [ Skip ]
 
 # Requires INDIE_UI support
 webkit.org/b/111446 indieui [ Skip ]
+webkit.org/b/111446 fast/custom-elements/reactions-for-indieui.html [ Skip ]
 
 # Requires support for Web notifications
 webkit.org/b/73544 fast/notifications [ Skip ]
index c5df726..e86e5d2 100644 (file)
@@ -176,6 +176,7 @@ http/tests/notifications/legacy/notification-request-permission-then-navigate.ht
 
 # Datalist is not yet enabled.
 webkit.org/b/98934 fast/forms/datalist [ Skip ]
+webkit.org/b/98934 fast/custom-elements/reactions-for-indieui.html [ Skip ]
 
 # ENABLE_INPUT_TYPE_* are not enabled.
 webkit.org/b/98936 fast/forms/date [ Skip ]
index 9f8607f..a9678d1 100644 (file)
@@ -1,3 +1,45 @@
+2016-10-28  Ryosuke Niwa  <rniwa@webkit.org>
+
+        Add CEReactions to the remaining HTML DOM APIs
+        https://bugs.webkit.org/show_bug.cgi?id=163969
+
+        Reviewed by Chris Dumez.
+
+        Added CEReactions to the remaining DOM and HTML APIs as needed.
+
+        Tests: fast/custom-elements/reactions-for-indieui.html
+               fast/custom-elements/reactions/Document.html
+               fast/custom-elements/reactions/HTMLAnchorElement.html
+               fast/custom-elements/reactions/HTMLOptionElement.html
+               fast/custom-elements/reactions/HTMLOptionsCollection.html
+               fast/custom-elements/reactions/HTMLOutputElement.html
+               fast/custom-elements/reactions/HTMLSelectElement.html
+               fast/custom-elements/reactions/HTMLTableElement.html
+               fast/custom-elements/reactions/HTMLTableRowElement.html
+               fast/custom-elements/reactions/HTMLTableSectionElement.html
+               fast/custom-elements/reactions/HTMLTitleElement.html
+               fast/custom-elements/reactions/ShadowRoot.html
+
+        * bindings/js/JSHTMLOptionsCollectionCustom.cpp:
+        (WebCore::JSHTMLOptionsCollection::setLength):
+        (WebCore::JSHTMLOptionsCollection::indexSetter):
+        * bindings/js/JSHTMLSelectElementCustom.cpp:
+        (WebCore::JSHTMLSelectElement::indexSetter):
+        * dom/CharacterData.idl:
+        * dom/Document.idl:
+        * dom/Element.idl:
+        * dom/ShadowRoot.idl:
+        * html/HTMLAnchorElement.idl:
+        * html/HTMLDocument.idl:
+        * html/HTMLOptionElement.idl:
+        * html/HTMLOptionsCollection.idl:
+        * html/HTMLOutputElement.idl:
+        * html/HTMLSelectElement.idl:
+        * html/HTMLTableElement.idl:
+        * html/HTMLTableRowElement.idl:
+        * html/HTMLTableSectionElement.idl:
+        * html/HTMLTitleElement.idl:
+
 2016-10-28  Antoine Quint  <graouts@apple.com>
 
         [Modern Media Controls] Media Controller: volume control support
index e49b8a6..0439b4b 100644 (file)
@@ -20,6 +20,7 @@
 #include "config.h"
 #include "JSHTMLOptionsCollection.h"
 
+#include "CustomElementReactionQueue.h"
 #include "ExceptionCode.h"
 #include "HTMLNames.h"
 #include "HTMLOptionElement.h"
@@ -49,6 +50,10 @@ bool JSHTMLOptionsCollection::nameGetter(ExecState* exec, PropertyName propertyN
 
 void JSHTMLOptionsCollection::setLength(ExecState& state, JSValue value)
 {
+#if ENABLE(CUSTOM_ELEMENTS)
+    CustomElementReactionStack customElementReactionStack;
+#endif
+
     ExceptionCode ec = 0;
     unsigned newLength = 0;
     double lengthValue = value.toNumber(&state);
@@ -67,6 +72,10 @@ void JSHTMLOptionsCollection::setLength(ExecState& state, JSValue value)
 
 void JSHTMLOptionsCollection::indexSetter(ExecState* exec, unsigned index, JSValue value)
 {
+#if ENABLE(CUSTOM_ELEMENTS)
+    CustomElementReactionStack customElementReactionStack;
+#endif
+
     selectIndexSetter(&wrapped().selectElement(), exec, index, value);
 }
 
index 40dcc46..7348eeb 100644 (file)
@@ -21,6 +21,7 @@
 #include "config.h"
 #include "JSHTMLSelectElementCustom.h"
 
+#include "CustomElementReactionQueue.h"
 #include "ExceptionCode.h"
 #include "HTMLNames.h"
 #include "HTMLOptionElement.h"
@@ -49,6 +50,9 @@ void selectIndexSetter(HTMLSelectElement* select, JSC::ExecState* exec, unsigned
 
 void JSHTMLSelectElement::indexSetter(JSC::ExecState* exec, unsigned index, JSC::JSValue value)
 {
+#if ENABLE(CUSTOM_ELEMENTS)
+    CustomElementReactionStack customElementReactionStack;
+#endif
     selectIndexSetter(&wrapped(), exec, index, value);
 }
 
index 0b13990..48142a0 100644 (file)
  */
 
 interface CharacterData : Node {
-    [TreatNullAs=EmptyString] attribute DOMString data;
+    [CEReactions, TreatNullAs=EmptyString] attribute DOMString data;
     readonly attribute unsigned long length;
 
     [MayThrowLegacyException] DOMString? substringData(unsigned long offset, unsigned long length);
 
-    void appendData(DOMString data);
-    [MayThrowLegacyException] void insertData(unsigned long offset, DOMString data);
-    [MayThrowLegacyException] void deleteData(unsigned long offset, unsigned long length);
-    [MayThrowLegacyException] void replaceData(unsigned long offset, unsigned long length, DOMString data);
+    [CEReactions] void appendData(DOMString data);
+    [CEReactions, MayThrowLegacyException] void insertData(unsigned long offset, DOMString data);
+    [CEReactions, MayThrowLegacyException] void deleteData(unsigned long offset, unsigned long length);
+    [CEReactions, MayThrowLegacyException] void replaceData(unsigned long offset, unsigned long length, DOMString data);
 };
 
 CharacterData implements ChildNode;
index 0405959..93c2a09 100644 (file)
@@ -91,7 +91,7 @@
     boolean queryCommandSupported(DOMString command);
     DOMString queryCommandValue(DOMString command);
 
-    attribute DOMString title;
+    [CEReactions] attribute DOMString title;
     attribute DOMString dir;
     attribute DOMString designMode;
 
 
     [GetterMayThrowLegacyException, SetterMayThrowLegacyException] attribute USVString cookie;
 
-    [SetterMayThrowLegacyException, ImplementedAs=bodyOrFrameset] attribute HTMLElement? body;
+    [CEReactions, ImplementedAs=bodyOrFrameset, SetterMayThrowLegacyException] attribute HTMLElement? body;
 
     readonly attribute HTMLHeadElement? head;
     readonly attribute HTMLCollection images;
index bacdd63..38b606a 100644 (file)
 #endif
 
 #if defined(ENABLE_INDIE_UI) && ENABLE_INDIE_UI
-    [Reflect] attribute DOMString uiactions;
+    [CEReactions, Reflect] attribute DOMString uiactions;
 #endif
 
     [CEReactions, MayThrowLegacyException] Element insertAdjacentElement(DOMString where, Element element);
index bb878a1..a23ebd0 100644 (file)
@@ -30,7 +30,7 @@
     readonly attribute ShadowRootMode   mode;
     readonly attribute Element          host;
 
-    [TreatNullAs=EmptyString, SetterMayThrowLegacyException] attribute DOMString innerHTML;
+    [CEReactions, SetterMayThrowLegacyException, TreatNullAs=EmptyString] attribute DOMString innerHTML;
 };
 
 ShadowRoot implements DocumentOrShadowRoot;
index f7cede1..7486d03 100644 (file)
@@ -31,7 +31,7 @@ interface HTMLAnchorElement : HTMLElement {
     [Reflect] attribute DOMString target;
     [Reflect] attribute DOMString type;
 
-    attribute DOMString text;
+    [CEReactions] attribute DOMString text;
 
     [PutForwards=value] readonly attribute DOMTokenList relList;
 };
index 673edde..21aa234 100644 (file)
     NewImpurePropertyFiresWatchpoints,
     OverrideBuiltins,
 ] interface HTMLDocument : Document {
-    [Custom, ForwardDeclareInHeader] void open();
+    [CEReactions, Custom, ForwardDeclareInHeader] void open();
     void close();
-    [Custom] void write(optional DOMString text);
-    [Custom] void writeln(optional DOMString text);
+    [CEReactions, Custom] void write(optional DOMString text);
+    [CEReactions, Custom] void writeln(optional DOMString text);
 
     [Custom, Replaceable] readonly attribute HTMLAllCollection all;
 
index 77be6f6..58dd197 100644 (file)
@@ -30,6 +30,6 @@
     attribute boolean selected;
     attribute DOMString value;
 
-    attribute DOMString text;
+    [CEReactions] attribute DOMString text;
     readonly attribute long index;
 };
index 6f85261..92c7bf6 100644 (file)
     JSGenerateToNativeObject,
 ] interface HTMLOptionsCollection : HTMLCollection {
     attribute long selectedIndex;
-    [CustomSetter, SetterMayThrowLegacyException] attribute unsigned long length;
+    [CEReactions, CustomSetter, SetterMayThrowLegacyException] attribute unsigned long length;
 
     getter HTMLOptionElement? item(unsigned long index);
     getter HTMLOptionElement? namedItem(DOMString name);
 
-    [MayThrowException] void add((HTMLOptionElement or HTMLOptGroupElement) element, optional (HTMLElement or long)? before = null);
+    [CEReactions, MayThrowException] void add((HTMLOptionElement or HTMLOptGroupElement) element, optional (HTMLElement or long)? before = null);
 
-    void remove(long index);
+    [CEReactions] void remove(long index);
     // FIXME: This overload is not in the specification and has been dropped in Blink.
-    void remove(HTMLOptionElement option);
+    [CEReactions] void remove(HTMLOptionElement option);
 };
index 57f1b6a..d527684 100644 (file)
@@ -29,8 +29,8 @@ interface HTMLOutputElement : HTMLElement {
     [Reflect] attribute DOMString name;
 
     readonly attribute DOMString type;
-    [TreatNullAs=EmptyString] attribute DOMString defaultValue;
-    [TreatNullAs=EmptyString] attribute DOMString value;
+    [CEReactions, TreatNullAs=EmptyString] attribute DOMString defaultValue;
+    [CEReactions, TreatNullAs=EmptyString] attribute DOMString value;
 
     readonly attribute boolean willValidate;
     readonly attribute ValidityState validity;
index 07a8c3d..465e5d3 100644 (file)
     readonly attribute DOMString type;
 
     readonly attribute HTMLOptionsCollection options;
-    [SetterMayThrowLegacyException] attribute unsigned long length;
+    [CEReactions, SetterMayThrowLegacyException] attribute unsigned long length;
 
     getter HTMLOptionElement? item(unsigned long index);
     HTMLOptionElement? namedItem(DOMString name);
 
-    [MayThrowException] void add((HTMLOptionElement or HTMLOptGroupElement) element, optional (HTMLElement or long)? before = null);
+    [CEReactions, MayThrowException] void add((HTMLOptionElement or HTMLOptGroupElement) element, optional (HTMLElement or long)? before = null);
 
     [MayThrowLegacyException] void remove(); // ChildNode overload
     // FIXME: This overload is not in the specification and was dropped in Blink.
-    void remove(HTMLOptionElement option);
-    [ImplementedAs=removeByIndex] void remove(long index);
+    [CEReactions] void remove(HTMLOptionElement option);
+    [CEReactions, ImplementedAs=removeByIndex] void remove(long index);
 
     readonly attribute HTMLCollection selectedOptions;
     attribute long selectedIndex;
index eb53b28..6f80816 100644 (file)
@@ -19,9 +19,9 @@
  */
 
 interface HTMLTableElement : HTMLElement {
-    [SetterMayThrowLegacyException] attribute HTMLTableCaptionElement? caption;
-    [SetterMayThrowLegacyException] attribute HTMLTableSectionElement? tHead;
-    [SetterMayThrowLegacyException] attribute HTMLTableSectionElement? tFoot;
+    [CEReactions, SetterMayThrowLegacyException] attribute HTMLTableCaptionElement? caption;
+    [CEReactions, SetterMayThrowLegacyException] attribute HTMLTableSectionElement? tHead;
+    [CEReactions, SetterMayThrowLegacyException] attribute HTMLTableSectionElement? tFoot;
 
     readonly attribute HTMLCollection rows;
     readonly attribute HTMLCollection tBodies;
@@ -38,14 +38,14 @@ interface HTMLTableElement : HTMLElement {
     [Reflect] attribute DOMString width;
 
     HTMLElement createTHead();
-    void deleteTHead();
+    [CEReactions] void deleteTHead();
     HTMLElement createTFoot();
-    void deleteTFoot();
+    [CEReactions] void deleteTFoot();
     HTMLElement createTBody();
     HTMLElement createCaption();
-    void deleteCaption();
+    [CEReactions] void deleteCaption();
 
     [MayThrowLegacyException] HTMLElement insertRow(optional long index = -1);
-    [MayThrowLegacyException] void deleteRow(long index);
+    [CEReactions, MayThrowLegacyException] void deleteRow(long index);
 };
 
index 7cc5b3a..b0d45ad 100644 (file)
@@ -28,6 +28,6 @@ interface HTMLTableRowElement : HTMLElement {
     [Reflect=charoff] attribute DOMString chOff;
     [Reflect] attribute DOMString vAlign;
     [MayThrowLegacyException] HTMLElement insertCell(optional long index = -1);
-    [MayThrowLegacyException] void deleteCell(long index);
+    [CEReactions, MayThrowLegacyException] void deleteCell(long index);
 };
 
index 7937c7d..54c5dc2 100644 (file)
@@ -27,6 +27,6 @@
     [Reflect] attribute DOMString vAlign;
     readonly attribute HTMLCollection rows;
     [MayThrowLegacyException] HTMLElement insertRow(optional long index = -1);
-    [MayThrowLegacyException] void deleteRow(long index);
+    [CEReactions, MayThrowLegacyException] void deleteRow(long index);
 };
 
index 406976d..7af6c18 100644 (file)
@@ -18,6 +18,6 @@
  */
 
 interface HTMLTitleElement : HTMLElement {
-    attribute DOMString text;
+    [CEReactions] attribute DOMString text;
 };