Bug 1925011 [wpt PR 48648] - Support custom element reactions for moveBefore, a=testonly

Automatic update from web-platform-tests
Support custom element reactions for moveBefore

- A new custom element reaction: connectedMoveCallback
- Called when the moved element is re-inserted
- Falls back to calling disconnectedMove/connectedMove if not provided.

Bug: 40150299
Change-Id: I0d3ed83ca03bbffcd2db79d1c421d8d155a4d9c8
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5920804
Reviewed-by: Dominic Farolino <dom@chromium.org>
Commit-Queue: Noam Rosenthal <nrosenthal@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1369383}

--

wpt-commits: c17fab297bdc750e97907281fabfbcbead8e993f
wpt-pr: 48648
This commit is contained in:
Noam Rosenthal 2024-10-16 22:19:13 +00:00 committed by moz-wptsync-bot
parent 978cdf99c9
commit 088d86ea1e
2 changed files with 125 additions and 8 deletions

View File

@ -11,6 +11,8 @@
<div id="log"></div>
<script>
const moveBefore_supported = ("moveBefore" in Node.prototype);
test(function () {
assert_true('define' in CustomElementRegistry.prototype, '"define" exists on CustomElementRegistry.prototype');
assert_true('define' in customElements, '"define" exists on window.customElements');
@ -273,7 +275,9 @@ test(function () {
}
});
customElements.define('element-with-proxy-prototype', constructor);
assert_array_equals(calls, ['connectedCallback', 'disconnectedCallback', 'adoptedCallback', 'attributeChangedCallback']);
assert_array_equals(calls,
moveBefore_supported ? ['connectedCallback', 'disconnectedCallback', 'connectedMoveCallback', 'adoptedCallback', 'attributeChangedCallback'] :
['connectedCallback', 'disconnectedCallback', 'adoptedCallback', 'attributeChangedCallback']);
}, 'customElements.define must get callbacks of the constructor prototype');
test(function () {
@ -305,7 +309,10 @@ test(function () {
}
});
assert_throws_js(TypeError, function () { customElements.define('element-with-throwing-callback', constructor); });
assert_array_equals(calls, ['connectedCallback', 'disconnectedCallback', 'adoptedCallback'],
assert_array_equals(calls,
moveBefore_supported ?
['connectedCallback', 'disconnectedCallback', 'connectedMoveCallback', 'adoptedCallback'] :
['connectedCallback', 'disconnectedCallback', 'adoptedCallback'],
'customElements.define must not get callbacks after one of the conversion throws');
}, 'customElements.define must rethrow an exception thrown while converting a callback value to Function callback type');
@ -332,11 +339,14 @@ test(function () {
}
});
customElements.define('element-with-attribute-changed-callback', proxy);
assert_array_equals(prototypeCalls, [1, 'connectedCallback', 2, 'disconnectedCallback', 3, 'adoptedCallback', 4, 'attributeChangedCallback']);
assert_array_equals(prototypeCalls,
moveBefore_supported ?
[1, 'connectedCallback', 2, 'disconnectedCallback', 3, 'connectedMoveCallback', 4, 'adoptedCallback', 5, 'attributeChangedCallback'] :
[1, 'connectedCallback', 2, 'disconnectedCallback', 3, 'adoptedCallback', 4, 'attributeChangedCallback']);
assert_array_equals(constructorCalls, [0, 'prototype',
5, 'observedAttributes',
6, 'disabledFeatures',
7, 'formAssociated']);
6, 'observedAttributes',
7, 'disabledFeatures',
8, 'formAssociated']);
}, 'customElements.define must get "observedAttributes" property on the constructor prototype when "attributeChangedCallback" is present');
test(function () {
@ -492,6 +502,10 @@ test(function () {
'"formAssociated" on the constructor');
assert_array_equals(
prototypeCalls,
moveBefore_supported ? ['connectedCallback', 'disconnectedCallback', 'connectedMoveCallback', 'adoptedCallback',
'attributeChangedCallback', 'formAssociatedCallback',
'formResetCallback', 'formDisabledCallback',
'formStateRestoreCallback'] :
['connectedCallback', 'disconnectedCallback', 'adoptedCallback',
'attributeChangedCallback', 'formAssociatedCallback',
'formResetCallback', 'formDisabledCallback',
@ -521,7 +535,10 @@ test(function () {
});
assert_throws_exactly(err,
() => customElements.define('element-with-throwing-callback-2', proxy));
assert_array_equals(calls, ['connectedCallback', 'disconnectedCallback',
assert_array_equals(calls, moveBefore_supported ? ['connectedCallback', 'disconnectedCallback', 'connectedMoveCallback',
'adoptedCallback', 'attributeChangedCallback',
'formAssociatedCallback', 'formResetCallback',
'formDisabledCallback'] : ['connectedCallback', 'disconnectedCallback',
'adoptedCallback', 'attributeChangedCallback',
'formAssociatedCallback', 'formResetCallback',
'formDisabledCallback'],
@ -538,7 +555,9 @@ test(function () {
});
assert_throws_js(TypeError,
() => customElements.define('element-with-throwing-callback-3', proxy));
assert_array_equals(calls2, ['connectedCallback', 'disconnectedCallback',
assert_array_equals(calls2, moveBefore_supported ? ['connectedCallback', 'disconnectedCallback', 'connectedMoveCallback',
'adoptedCallback', 'attributeChangedCallback',
'formAssociatedCallback', 'formResetCallback'] : ['connectedCallback', 'disconnectedCallback',
'adoptedCallback', 'attributeChangedCallback',
'formAssociatedCallback', 'formResetCallback'],
'customElements.define must not get callbacks after one of the get throws');

View File

@ -0,0 +1,98 @@
<!DOCTYPE html>
<title>Node.moveBefore custom element reactions</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script>
;
</script>
<body>
<section id="section"></section>
<script>
promise_test(async t => {
const ce = document.getElementById("ce");
let reactions = [];
const element_name = `ce-${performance.now()}`;
customElements.define(element_name,
class MockCustomElement extends HTMLElement {
connectedCallback() { reactions.push("connected"); }
disconnectedCallback() { reactions.push("disconnected"); }
});
const element = document.createElement(element_name);
t.add_cleanup(() => element.remove());
document.body.append(element);
await Promise.resolve();
reactions = [];
document.getElementById("section").moveBefore(element, null);
await Promise.resolve();
assert_array_equals(reactions, ["disconnected", "connected"]);
}, "the disconnected/connected callbacks should be called when no other callback is defined");
promise_test(async t => {
const ce = document.getElementById("ce");
let reactions = [];
const element_name = `ce-${performance.now()}`;
customElements.define(element_name,
class MockCustomElement extends HTMLElement {
connectedCallback() { reactions.push(this.isConnected); }
disconnectedCallback() { reactions.push(this.isConnected); }
});
const element = document.createElement(element_name);
t.add_cleanup(() => element.remove());
document.body.append(element);
await Promise.resolve();
reactions = [];
document.getElementById("section").moveBefore(element, null);
await Promise.resolve();
assert_array_equals(reactions, [true, true]);
}, "the element should stay connected during the callbacks");
promise_test(async t => {
const ce = document.getElementById("ce");
let reactions = [];
const element_name = `ce-${performance.now()}`;
customElements.define(element_name,
class MockCustomElement extends HTMLElement {
connectedMoveCallback() { reactions.push("connectedMove"); }
connectedCallback() { reactions.push("connected"); }
disconnectedCallback() { reactions.push("disconnected"); }
});
const element = document.createElement(element_name);
t.add_cleanup(() => element.remove());
document.body.append(element);
await Promise.resolve();
reactions = [];
document.getElementById("section").moveBefore(element, null);
await Promise.resolve();
assert_array_equals(reactions, ["connectedMove"]);
}, "When connectedMoveCallback is defined, it is called instead of disconnectedCallback/connectedCallback");
promise_test(async t => {
const ce = document.getElementById("ce");
let reactions = [];
const outer_element_name = `ce-${performance.now()}-outer`;
const inner_element_name = `ce-${performance.now()}-inner`;
customElements.define(outer_element_name,
class MockCustomElement extends HTMLElement {
connectedCallback() { reactions.push("outer connected"); }
disconnectedCallback() { reactions.push("outer disconnected"); }
});
customElements.define(inner_element_name,
class MockCustomElement extends HTMLElement {
connectedCallback() { reactions.push("inner connected"); }
disconnectedCallback() { reactions.push("inner disconnected"); }
});
const outer = document.createElement(outer_element_name);
const inner = document.createElement(inner_element_name);
t.add_cleanup(() => outer.remove());
outer.append(inner);
document.body.append(outer);
await Promise.resolve();
reactions = [];
document.getElementById("section").moveBefore(outer, null);
await Promise.resolve();
assert_array_equals(reactions, ["outer disconnected", "outer connected", "inner disconnected", "inner connected"]);
}, "Reactions to atomic move are called in order of element, not in order of operation");
</script>
</body>