Permalink
Show file tree
Hide file tree
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Fix the remaining WPT failures for imperative slot API
https://bugs.webkit.org/show_bug.cgi?id=243817 Reviewed by Chris Dumez. This patch improves the imperative slot API implementation in WebKit by adding support for slotchange event. * LayoutTests/fast/shadow-dom/manual-assignment-multiple-shadow-roots-expected.txt: Added. * LayoutTests/fast/shadow-dom/manual-assignment-multiple-shadow-roots.html: Added. * LayoutTests/imported/w3c/web-platform-tests/shadow-dom/imperative-slot-api-expected.txt: * LayoutTests/imported/w3c/web-platform-tests/shadow-dom/imperative-slot-api-slotchange-expected.txt: * LayoutTests/platform/win/TestExpectations: * Source/WebCore/dom/Node.cpp: (WebCore::Node::setManuallyAssignedSlot): Destruct the renderer when the assigned slot of this node changes. * Source/WebCore/dom/ShadowRoot.cpp: (WebCore::ShadowRoot::didRemoveManuallyAssignedNode): Added. * Source/WebCore/dom/ShadowRoot.h: * Source/WebCore/dom/SlotAssignment.cpp: (WebCore::NamedSlotAssignment::didRemoveManuallyAssignedNode): Added. (WebCore::NamedSlotAssignment::willRemoveAssignedNode): (WebCore::ManualSlotAssignment::assignedNodesForSlot): (WebCore::ManualSlotAssignment::addSlotElementByName): Added the logic to enqueue a slotchange event. (WebCore::ManualSlotAssignment::removeSlotElementByName): Ditto. (WebCore::ManualSlotAssignment::slotManualAssignmentDidChange): Now notifies slots in other shadow trees about changes in assigned nodes to enqueue slotchange event. (WebCore::ManualSlotAssignment::didRemoveManuallyAssignedNode): Added. Gets called when one of the assigned nodes to re-assigned to a slot in another tree. (WebCore::ManualSlotAssignment::willRemoveAssignedNode): Added the logic to enqueue a slotchange event. * Source/WebCore/dom/SlotAssignment.h: (WebCore::ShadowRoot::willRemoveAssignedNode): * Source/WebCore/html/HTMLSlotElement.cpp: (WebCore::HTMLSlotElement::assign): Added the logic to clear the previously assigned slot. Canonical link: https://commits.webkit.org/253359@main
- Loading branch information
Showing
11 changed files
with
232 additions
and
31 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
|
||
PASS slot assigned of nodes in other shadow trees | ||
PASS orphan slot assigned of nodes in another shadow tree | ||
PASS orphan slot assigned of nodes in multiple other shadow trees | ||
PASS slot assigned of nodes in multiple other shadow trees | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,137 @@ | ||
<!DOCTYPE html> | ||
<html> | ||
<body> | ||
<div id="container"></div> | ||
<script src="../../resources/testharness.js"></script> | ||
<script src="../../resources/testharnessreport.js"></script> | ||
<script> | ||
|
||
promise_test(async () => { | ||
let logs = []; | ||
function logger(event) { logs.push(this); } | ||
|
||
container.innerHTML = `<div id="hostA"><div id="childA1"></div><div id="childA2"></div></div><div id="hostB"></div>`; | ||
|
||
const shadowRootA = hostA.attachShadow({mode: 'closed', slotAssignment: 'manual'}); | ||
const slotA = shadowRootA.appendChild(document.createElement('slot')); | ||
slotA.id = 'A'; | ||
slotA.assign(childA1, childA2); | ||
slotA.addEventListener('slotchange', logger); | ||
|
||
await new Promise((resolve) => setTimeout(resolve, 0)); | ||
|
||
assert_array_equals(logs, [slotA]); | ||
logs = []; | ||
|
||
const shadowRootB = hostB.attachShadow({mode: 'closed', slotAssignment: 'manual'}); | ||
const slotB = shadowRootB.appendChild(document.createElement('slot')); | ||
slotB.id = 'B'; | ||
slotB.assign(childA1); | ||
slotB.addEventListener('slotchange', logger); | ||
|
||
await new Promise((resolve) => setTimeout(resolve, 0)); | ||
assert_array_equals(logs, [slotA]); | ||
}, 'slot assigned of nodes in other shadow trees'); | ||
|
||
promise_test(async () => { | ||
let logs = []; | ||
function logger(event) { logs.push(this); } | ||
|
||
container.innerHTML = `<div id="hostA"><div id="child1"></div><div id="child2"></div></div>`; | ||
|
||
const shadowRootA = hostA.attachShadow({mode: 'closed', slotAssignment: 'manual'}); | ||
const slotA = shadowRootA.appendChild(document.createElement('slot')); | ||
slotA.id = 'A'; | ||
slotA.assign(child1, child2); | ||
slotA.addEventListener('slotchange', logger); | ||
|
||
await new Promise((resolve) => setTimeout(resolve, 0)); | ||
|
||
assert_array_equals(logs, [slotA]); | ||
logs = []; | ||
|
||
const slotB = document.createElement('slot'); | ||
slotB.assign(child2); | ||
|
||
await new Promise((resolve) => setTimeout(resolve, 0)); | ||
assert_array_equals(logs, [slotA]); | ||
}, 'orphan slot assigned of nodes in another shadow tree'); | ||
|
||
promise_test(async () => { | ||
let logs = []; | ||
function logger(event) { logs.push(this); } | ||
|
||
container.innerHTML = `<div id="hostA"><div id="childA1"></div><div id="childA2"></div><div id="childA3"></div><div id="childA4"></div></div> | ||
<div id="hostB"><div id="childB1"></div><div id="childB2"></div></div> | ||
<div id="hostC"></div>`; | ||
|
||
const shadowRootB = hostB.attachShadow({mode: 'closed', slotAssignment: 'manual'}); | ||
const slotB = shadowRootB.appendChild(document.createElement('slot')); | ||
slotB.id = 'B'; | ||
slotB.assign(childB1, childB2); | ||
slotB.addEventListener('slotchange', logger); | ||
|
||
const shadowRootA = hostA.attachShadow({mode: 'closed', slotAssignment: 'manual'}); | ||
const slotA1 = shadowRootA.appendChild(document.createElement('slot')); | ||
slotA1.id = 'A1'; | ||
slotA1.assign(childA1, childA2); | ||
slotA1.addEventListener('slotchange', logger); | ||
|
||
const slotA2 = shadowRootA.appendChild(document.createElement('slot')); | ||
slotA2.id = 'A2'; | ||
slotA2.assign(childA3, childA4); | ||
slotA2.addEventListener('slotchange', logger); | ||
|
||
await new Promise((resolve) => setTimeout(resolve, 0)); | ||
|
||
assert_array_equals(logs, [slotB, slotA1, slotA2]); | ||
logs = []; | ||
|
||
const slotC = document.createElement('slot'); | ||
slotC.assign(childB1, childA3, childA2); | ||
|
||
await new Promise((resolve) => setTimeout(resolve, 0)); | ||
assert_array_equals(logs, [slotB, slotA2, slotA1]); | ||
}, 'orphan slot assigned of nodes in multiple other shadow trees'); | ||
|
||
promise_test(async () => { | ||
let logs = []; | ||
function logger(event) { logs.push(this); } | ||
|
||
container.innerHTML = `<div id="hostA"><div id="childA1"></div><div id="childA2"></div><div id="childA3"></div><div id="childA4"></div></div> | ||
<div id="hostB"><div id="childB1"></div><div id="childB2"></div></div> | ||
<div id="hostC"></div>`; | ||
|
||
const shadowRootB = hostB.attachShadow({mode: 'closed', slotAssignment: 'manual'}); | ||
const slotB = shadowRootB.appendChild(document.createElement('slot')); | ||
slotB.id = 'B'; | ||
slotB.assign(childB1, childB2); | ||
slotB.addEventListener('slotchange', logger); | ||
|
||
const shadowRootA = hostA.attachShadow({mode: 'closed', slotAssignment: 'manual'}); | ||
const slotA1 = shadowRootA.appendChild(document.createElement('slot')); | ||
slotA1.id = 'A1'; | ||
slotA1.assign(childA1, childA2); | ||
slotA1.addEventListener('slotchange', logger); | ||
|
||
const slotA2 = shadowRootA.appendChild(document.createElement('slot')); | ||
slotA2.id = 'A2'; | ||
slotA2.assign(childA3, childA4); | ||
slotA2.addEventListener('slotchange', logger); | ||
|
||
await new Promise((resolve) => setTimeout(resolve, 0)); | ||
|
||
assert_array_equals(logs, [slotB, slotA1, slotA2]); | ||
logs = []; | ||
|
||
const shadowRootC = hostC.attachShadow({mode: 'closed', slotAssignment: 'manual'}); | ||
const slotC = shadowRootC.appendChild(document.createElement('slot')); | ||
slotC.assign(childB1, childA3, childA2); | ||
|
||
await new Promise((resolve) => setTimeout(resolve, 0)); | ||
assert_array_equals(logs, [slotB, slotA2, slotA1]); | ||
}, 'slot assigned of nodes in multiple other shadow trees'); | ||
|
||
</script> | ||
</body> | ||
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,17 +1,15 @@ | ||
|
||
Harness Error (TIMEOUT), message = null | ||
|
||
PASS slotchange event must not fire synchronously. | ||
PASS slotchange event should not fire when assignments do not change assignedNodes. | ||
PASS slotchange event should not fire when same node is assigned. | ||
PASS Fire slotchange event when slot's assigned nodes changes. | ||
PASS Fire slotchange event on previous slot and new slot when node is reassigned. | ||
PASS Fire slotchange event on node assignment and when assigned node is removed. | ||
PASS Fire slotchange event when order of assigned nodes changes. | ||
TIMEOUT Fire slotchange event when assigned node is removed. Test timed out | ||
NOTRUN Fire slotchange event when removing a slot from Shadows Root that changes its assigned nodes. | ||
PASS Fire slotchange event when assigned node is removed. | ||
PASS Fire slotchange event when removing a slot from Shadows Root that changes its assigned nodes. | ||
PASS No slotchange event when adding or removing an empty slot. | ||
PASS No slotchange event when adding another slotable. | ||
PASS Fire slotchange event when assign node to nested slot, ensure event bubbles ups. | ||
NOTRUN Signal a slot change should be done in tree order. | ||
PASS Signal a slot change should be done in tree order. | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.