Commit 63c4f9f5 authored by Yu Han's avatar Yu Han Committed by Commit Bot

Adds slotAssignmentMode to the shadow root bindings.

Prior to this CL, the previous implementation of imperative slot API uses
'slotting' as an optional parameter for Element.attachShadow(). However,
based on the feedback by JanMiksovsky@ in
https://github.com/w3c/webcomponents/pull/866, the parameter should be
changed to 'slotAssignment' to make it align with other members,
assignNodes(), assignElements(). I agree with this feedback.

This CL updates the following:
1. update bindings where the previous 'slotting' was used to
 'slotAssignment'.
2. Updated the enum type of slotAssignment. It should be,
 SlotAssignmentMode [auto | manual].
3. Added attribute 'slotAssignment' to Shadow_Root.idl and updated
 global-interface-listing-expected.txt.
4. Modify existing tests from using slotting to slotAssignment.
5. Removed test that'll be covered by
 external/wpt/shadow-dom/slots-imperative-slot-api.tentative.html.
https://chromium-review.googlesource.com/c/chromium/src/+/2083742
I'll update this CL with the correct
 slots-imperative-slot-api.tentative-expected.txt once that CL lands.

Bug: 869308
Change-Id: I0fb1a9e11c88d52fc0b0570f3f3e1f5bf834f858
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2084376
Commit-Queue: Yu Han <yuzhehan@chromium.org>
Reviewed-by: default avatarMason Freed <masonfreed@chromium.org>
Reviewed-by: default avatarHayato Ito <hayato@chromium.org>
Cr-Commit-Position: refs/heads/master@{#748116}
parent 5df06c82
...@@ -11,7 +11,7 @@ customElements.define("my-summary", MySummaryElement); ...@@ -11,7 +11,7 @@ customElements.define("my-summary", MySummaryElement);
customElements.define("my-detail", class extends HTMLElement { customElements.define("my-detail", class extends HTMLElement {
constructor() { constructor() {
super(); super();
this.attachShadow({ mode: "open", slotting: "manual" }); this.attachShadow({ mode: "open", slotAssignment: "manual" });
} }
connectedCallback() { connectedCallback() {
const target = this; const target = this;
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
</div> </div>
<script> <script>
const host = document.querySelector("#host"); const host = document.querySelector("#host");
const shadow_root = host.attachShadow({ mode: 'open', slotting: 'auto' }); const shadow_root = host.attachShadow({ mode: 'open', slotAssignment: 'auto' });
const slot1 = document.createElement("slot"); const slot1 = document.createElement("slot");
const child1 = document.createElement("child"); const child1 = document.createElement("child");
shadow_root.appendChild(slot1); shadow_root.appendChild(slot1);
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
</div> </div>
<script> <script>
const host = document.querySelector("#host"); const host = document.querySelector("#host");
const shadow_root = host.attachShadow({ mode: 'open', slotting: 'manual' }); const shadow_root = host.attachShadow({ mode: 'open', slotAssignment: 'manual' });
const slot1 = document.createElement("slot"); const slot1 = document.createElement("slot");
const child1 = document.createElement("child"); const child1 = document.createElement("child");
slot1.assign([child1]); slot1.assign([child1]);
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
</div> </div>
<script> <script>
const host = document.querySelector("#host"); const host = document.querySelector("#host");
const shadow_root = host.attachShadow({ mode: 'open', slotting: 'manual' }); const shadow_root = host.attachShadow({ mode: 'open', slotAssignment: 'manual' });
const slot1 = document.createElement("slot"); const slot1 = document.createElement("slot");
const child1 = document.createElement("child"); const child1 = document.createElement("child");
shadow_root.appendChild(slot1); shadow_root.appendChild(slot1);
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
</div> </div>
<script> <script>
const host = document.querySelector("#host"); const host = document.querySelector("#host");
const shadow_root = host.attachShadow({ mode: 'open', slotting: 'manual' }); const shadow_root = host.attachShadow({ mode: 'open', slotAssignment: 'manual' });
const slot1 = document.createElement("slot"); const slot1 = document.createElement("slot");
const child1 = document.createElement("child"); const child1 = document.createElement("child");
slot1.assign([child1]); slot1.assign([child1]);
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
</div> </div>
<script> <script>
const host = document.querySelector("#host"); const host = document.querySelector("#host");
const shadow_root = host.attachShadow({ mode: 'open', slotting: 'manual' }); const shadow_root = host.attachShadow({ mode: 'open', slotAssignment: 'manual' });
const slot1 = document.createElement("slot"); const slot1 = document.createElement("slot");
const child1 = document.createElement("child"); const child1 = document.createElement("child");
slot1.assign([child1]); slot1.assign([child1]);
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
</div> </div>
<script> <script>
const host = document.querySelector("#host"); const host = document.querySelector("#host");
const shadow_root = host.attachShadow({ mode: 'open', slotting: 'manual' }); const shadow_root = host.attachShadow({ mode: 'open', slotAssignment: 'manual' });
const slot1 = document.createElement("slot"); const slot1 = document.createElement("slot");
const child1 = document.createElement("child"); const child1 = document.createElement("child");
const child = document.querySelector("#child"); const child = document.querySelector("#child");
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
<script> <script>
const host = document.querySelector("#host"); const host = document.querySelector("#host");
const child1 = document.querySelector("#child1"); const child1 = document.querySelector("#child1");
const shadow_root = host.attachShadow({ mode: "open", slotting: "manual" }); const shadow_root = host.attachShadow({ mode: "open", slotAssignment: "manual" });
window.onload = function() { window.onload = function() {
PerfTestRunner.measureTime({ PerfTestRunner.measureTime({
description: "Measure performance of slot assignment in manual-slotting mode in shadow root.", description: "Measure performance of slot assignment in manual-slotting mode in shadow root.",
......
...@@ -3738,7 +3738,7 @@ ShadowRoot* Element::attachShadow(const ShadowRootInit* shadow_root_init_dict, ...@@ -3738,7 +3738,7 @@ ShadowRoot* Element::attachShadow(const ShadowRootInit* shadow_root_init_dict,
DCHECK(!shadow_root_init_dict->hasMode() || !GetShadowRoot()); DCHECK(!shadow_root_init_dict->hasMode() || !GetShadowRoot());
bool delegates_focus = shadow_root_init_dict->hasDelegatesFocus() && bool delegates_focus = shadow_root_init_dict->hasDelegatesFocus() &&
shadow_root_init_dict->delegatesFocus(); shadow_root_init_dict->delegatesFocus();
bool manual_slotting = shadow_root_init_dict->slotting() == "manual"; bool manual_slotting = shadow_root_init_dict->slotAssignment() == "manual";
return &AttachShadowRootInternal(type, delegates_focus, manual_slotting); return &AttachShadowRootInternal(type, delegates_focus, manual_slotting);
} }
...@@ -3768,8 +3768,9 @@ ShadowRoot& Element::AttachShadowRootInternal(ShadowRootType type, ...@@ -3768,8 +3768,9 @@ ShadowRoot& Element::AttachShadowRootInternal(ShadowRootType type,
GetDocument().SetShadowCascadeOrder(ShadowCascadeOrder::kShadowCascadeV1); GetDocument().SetShadowCascadeOrder(ShadowCascadeOrder::kShadowCascadeV1);
ShadowRoot& shadow_root = CreateAndAttachShadowRoot(type); ShadowRoot& shadow_root = CreateAndAttachShadowRoot(type);
shadow_root.SetDelegatesFocus(delegates_focus); shadow_root.SetDelegatesFocus(delegates_focus);
shadow_root.SetSlotting(manual_slotting ? ShadowRootSlotting::kManual shadow_root.SetSlotAssignmentMode(manual_slotting
: ShadowRootSlotting::kAuto); ? SlotAssignmentMode::kManual
: SlotAssignmentMode::kAuto);
return shadow_root; return shadow_root;
} }
......
...@@ -71,7 +71,7 @@ ShadowRoot::ShadowRoot(Document& document, ShadowRootType type) ...@@ -71,7 +71,7 @@ ShadowRoot::ShadowRoot(Document& document, ShadowRootType type)
type_(static_cast<unsigned>(type)), type_(static_cast<unsigned>(type)),
registered_with_parent_shadow_root_(false), registered_with_parent_shadow_root_(false),
delegates_focus_(false), delegates_focus_(false),
slotting_(static_cast<unsigned>(ShadowRootSlotting::kAuto)), slot_assignment_mode_(static_cast<unsigned>(SlotAssignmentMode::kAuto)),
needs_distribution_recalc_(false), needs_distribution_recalc_(false),
unused_(0) { unused_(0) {
if (IsV0()) if (IsV0())
...@@ -109,8 +109,8 @@ Node* ShadowRoot::Clone(Document&, CloneChildrenFlag) const { ...@@ -109,8 +109,8 @@ Node* ShadowRoot::Clone(Document&, CloneChildrenFlag) const {
return nullptr; return nullptr;
} }
void ShadowRoot::SetSlotting(ShadowRootSlotting slotting) { void ShadowRoot::SetSlotAssignmentMode(SlotAssignmentMode assignment_mode) {
slotting_ = static_cast<unsigned>(slotting); slot_assignment_mode_ = static_cast<unsigned>(assignment_mode);
} }
String ShadowRoot::InnerHTMLAsString() const { String ShadowRoot::InnerHTMLAsString() const {
......
...@@ -47,7 +47,7 @@ class WhitespaceAttacher; ...@@ -47,7 +47,7 @@ class WhitespaceAttacher;
enum class ShadowRootType { V0, kOpen, kClosed, kUserAgent }; enum class ShadowRootType { V0, kOpen, kClosed, kUserAgent };
enum class ShadowRootSlotting { kManual, kAuto }; enum class SlotAssignmentMode { kManual, kAuto };
class CORE_EXPORT ShadowRoot final : public DocumentFragment, public TreeScope { class CORE_EXPORT ShadowRoot final : public DocumentFragment, public TreeScope {
DEFINE_WRAPPERTYPEINFO(); DEFINE_WRAPPERTYPEINFO();
...@@ -153,9 +153,16 @@ class CORE_EXPORT ShadowRoot final : public DocumentFragment, public TreeScope { ...@@ -153,9 +153,16 @@ class CORE_EXPORT ShadowRoot final : public DocumentFragment, public TreeScope {
void SetDelegatesFocus(bool flag) { delegates_focus_ = flag; } void SetDelegatesFocus(bool flag) { delegates_focus_ = flag; }
bool delegatesFocus() const { return delegates_focus_; } bool delegatesFocus() const { return delegates_focus_; }
void SetSlotting(ShadowRootSlotting slotting); void SetSlotAssignmentMode(SlotAssignmentMode assignment);
bool IsManualSlotting() { bool IsManualSlotting() const {
return slotting_ == static_cast<unsigned>(ShadowRootSlotting::kManual); return slot_assignment_mode_ ==
static_cast<unsigned>(SlotAssignmentMode::kManual);
}
SlotAssignmentMode GetSlotAssignmentMode() const {
return static_cast<SlotAssignmentMode>(slot_assignment_mode_);
}
String slotAssignment() const {
return IsManualSlotting() ? "manual" : "auto";
} }
bool ContainsShadowRoots() const { return child_shadow_root_count_; } bool ContainsShadowRoots() const { return child_shadow_root_count_; }
...@@ -188,7 +195,7 @@ class CORE_EXPORT ShadowRoot final : public DocumentFragment, public TreeScope { ...@@ -188,7 +195,7 @@ class CORE_EXPORT ShadowRoot final : public DocumentFragment, public TreeScope {
unsigned type_ : 2; unsigned type_ : 2;
unsigned registered_with_parent_shadow_root_ : 1; unsigned registered_with_parent_shadow_root_ : 1;
unsigned delegates_focus_ : 1; unsigned delegates_focus_ : 1;
unsigned slotting_ : 1; unsigned slot_assignment_mode_ : 1;
unsigned needs_distribution_recalc_ : 1; unsigned needs_distribution_recalc_ : 1;
unsigned unused_ : 10; unsigned unused_ : 10;
......
...@@ -32,6 +32,7 @@ interface ShadowRoot : DocumentFragment { ...@@ -32,6 +32,7 @@ interface ShadowRoot : DocumentFragment {
readonly attribute Element host; readonly attribute Element host;
[CEReactions, CustomElementCallbacks, Custom=Setter] attribute HTMLString innerHTML; [CEReactions, CustomElementCallbacks, Custom=Setter] attribute HTMLString innerHTML;
readonly attribute boolean delegatesFocus; readonly attribute boolean delegatesFocus;
[RuntimeEnabled=ManualSlotting] readonly attribute SlotAssignmentMode slotAssignment;
}; };
ShadowRoot includes DocumentOrShadowRoot; ShadowRoot includes DocumentOrShadowRoot;
...@@ -5,10 +5,10 @@ ...@@ -5,10 +5,10 @@
// Spec: https://w3c.github.io/webcomponents/spec/shadow/#shadowrootinit-dictionary // Spec: https://w3c.github.io/webcomponents/spec/shadow/#shadowrootinit-dictionary
enum ShadowRootMode { "open", "closed" }; enum ShadowRootMode { "open", "closed" };
enum ShadowRootSlottingMode { "manual", "auto" }; enum SlotAssignmentMode { "manual", "auto" };
dictionary ShadowRootInit { dictionary ShadowRootInit {
required ShadowRootMode mode; required ShadowRootMode mode;
boolean delegatesFocus; boolean delegatesFocus;
[RuntimeEnabled=ManualSlotting] ShadowRootSlottingMode slotting; [RuntimeEnabled=ManualSlotting] SlotAssignmentMode slotAssignment;
}; };
This is a testharness.js-based test. This is a testharness.js-based test.
FAIL attachShadow can take slotAssignment parameter. assert_throws_js: others should throw exception function "() => { PASS attachShadow can take slotAssignment parameter.
tTree.host3.attachShadow({ mode: 'open', slotAssignment: 'exceptional' })}" did not throw
FAIL Imperative slot API throws exception when not slotAssignment != 'manual'. assert_throws_dom: function "() => { tTree.s1.assign([]); }" did not throw FAIL Imperative slot API throws exception when not slotAssignment != 'manual'. assert_throws_dom: function "() => { tTree.s1.assign([]); }" did not throw
FAIL Imperative slot API throws exception when slotable parentNode != slot's host. assert_throws_dom: function "() => { tTree.s2.assign([tTree.c1]); }" did not throw FAIL Imperative slot API throws exception when slotable parentNode != slot's host. assert_throws_dom: function "() => { tTree.s2.assign([tTree.c1]); }" did not throw
FAIL Imperative slot API can assign nodes in manual slot assignment. assert_equals: expected null but got Element node <slot id="s1"></slot> FAIL Imperative slot API can assign nodes in manual slot assignment. assert_equals: expected null but got Element node <slot id="s1"></slot>
......
...@@ -12,7 +12,7 @@ See https://crbug.com/869308 ...@@ -12,7 +12,7 @@ See https://crbug.com/869308
<script> <script>
const host = document.querySelector("#host"); const host = document.querySelector("#host");
const child1 = document.querySelector("#child1"); const child1 = document.querySelector("#child1");
const shadow_root = host.attachShadow({ mode: "open", slotting: "manual" }); const shadow_root = host.attachShadow({ mode: "open", slotAssignment: "manual" });
const slot1 = document.createElement("slot"); const slot1 = document.createElement("slot");
const slot2 = document.createElement("slot"); const slot2 = document.createElement("slot");
shadow_root.appendChild(slot1); shadow_root.appendChild(slot1);
......
...@@ -6,27 +6,11 @@ See https://crbug.com/869308 ...@@ -6,27 +6,11 @@ See https://crbug.com/869308
<script src="../resources/testharness.js"></script> <script src="../resources/testharness.js"></script>
<script src="../resources/testharnessreport.js"></script> <script src="../resources/testharnessreport.js"></script>
<script src="resources/shadow-dom.js"></script> <script src="resources/shadow-dom.js"></script>
<div id="test1">
<div id="host"></div>
<div id="host1"></div>
<div id="host2"></div>
</div>
<script>
test(() => {
let n = createTestTree(test1);
assert_not_equals(n.host.attachShadow({ mode: 'open', slotting: 'manual' }),
null, 'slotting manual should work');
assert_not_equals(n.host1.attachShadow({ mode: 'open', slotting: 'auto' }),
null, 'slotting auto should work');
assert_throws_js(TypeError, () => {
n.host2.attachShadow({ mode: 'open', slotting: 'exceptional' })},
'others should throw exception');
}, 'attachShadow can take slotting parameter');
</script> </script>
<div id="test2"> <div id="test2">
<div id="host"> <div id="host">
<template id="shadow_root" data-mode="open" data-slotting="manual"> <template id="shadow_root" data-mode="open" data-slot-assignment="manual">
<slot id="s1"></slot> <slot id="s1"></slot>
<slot id="s2"></slot> <slot id="s2"></slot>
<slot id="s3"></slot> <slot id="s3"></slot>
...@@ -37,7 +21,7 @@ test(() => { ...@@ -37,7 +21,7 @@ test(() => {
</div> </div>
<div id="c4"></div> <div id="c4"></div>
<div id="host4"> <div id="host4">
<template id="shadow_root1" data-mode="open" data-slotting="manual"> <template id="shadow_root1" data-mode="open" data-slot-assignment="manual">
<slot id="s5" name="s5"></slot> <slot id="s5" name="s5"></slot>
</template> </template>
</div> </div>
......
...@@ -11,7 +11,7 @@ customElements.define("my-summary", MySummaryElement); ...@@ -11,7 +11,7 @@ customElements.define("my-summary", MySummaryElement);
customElements.define("my-detail", class extends HTMLElement { customElements.define("my-detail", class extends HTMLElement {
constructor() { constructor() {
super(); super();
this.attachShadow({ mode: "open", slotting: "manual" }); this.attachShadow({ mode: "open", slotAssignment: "manual" });
} }
connectedCallback() { connectedCallback() {
const target = this; const target = this;
......
...@@ -76,10 +76,10 @@ function createTestTree(node) { ...@@ -76,10 +76,10 @@ function createTestTree(node) {
if (template.getAttribute('data-mode') === 'v0') { if (template.getAttribute('data-mode') === 'v0') {
// For legacy Shadow DOM // For legacy Shadow DOM
shadowRoot = parent.createShadowRoot(); shadowRoot = parent.createShadowRoot();
} else if (template.getAttribute('data-slotting') === 'manual') { } else if (template.getAttribute('data-slot-assignment') === 'manual') {
shadowRoot = shadowRoot =
parent.attachShadow({mode: template.getAttribute('data-mode'), parent.attachShadow({mode: template.getAttribute('data-mode'),
slotting: 'manual'}); slotAssignment: 'manual'});
} else { } else {
shadowRoot = shadowRoot =
parent.attachShadow({mode: template.getAttribute('data-mode')}); parent.attachShadow({mode: template.getAttribute('data-mode')});
......
...@@ -8006,6 +8006,7 @@ interface ShadowRoot : DocumentFragment ...@@ -8006,6 +8006,7 @@ interface ShadowRoot : DocumentFragment
getter mode getter mode
getter pictureInPictureElement getter pictureInPictureElement
getter pointerLockElement getter pointerLockElement
getter slotAssignment
getter styleSheets getter styleSheets
method constructor method constructor
method elementFromPoint method elementFromPoint
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment