Commit 0fd72b87 authored by Kyoko Muto's avatar Kyoko Muto Committed by Commit Bot

Add Assign function

As the second step of implementing "Imperative Shadow DOM Distribution API",
this CL make assign function to assign nodes to slot in manual slotting mode.

This CL also introduces HeapVector for each slot
to store the nodes that assign introduced.

BUG=869308

Change-Id: I9b02a70f601364123fb565221d3def760408bc2a
Reviewed-on: https://chromium-review.googlesource.com/1166925Reviewed-by: default avatarHayato Ito <hayato@chromium.org>
Commit-Queue: Kyoko Muto <kymuto@google.com>
Cr-Commit-Position: refs/heads/master@{#583178}
parent 3fac86d9
......@@ -6,21 +6,47 @@ See https://crbug.com/869308
<script src="../resources/testharness.js"></script>
<script src="../resources/testharnessreport.js"></script>
<div id="host">
<div id="child1"></div>
<div id="child2"></div>
<div id="child3"></div>
</div>
<div id="host1">
</div>
</div>
<div id="host2">
</div>
</div>
<div id="host3">
</div>
<script>
const host = document.querySelector('#host');
const host1 = document.querySelector('#host1');
const host2 = document.querySelector('#host2');
const host3 = document.querySelector('#host3');
const child1 = document.querySelector('#child1');
const child2 = document.querySelector('#child2');
const child3 = document.querySelector('#child3');
const shadow_root = host.attachShadow({ mode: 'open', slotting: 'manual' });
const slot1 = document.createElement('slot');
shadow_root.appendChild(slot1);
test(() => {
assert_not_equals(host.attachShadow({ mode: 'open', slotting: 'manual' }),
assert_not_equals(host1.attachShadow({ mode: 'open', slotting: 'manual' }),
null, 'slotting manual should work');
assert_not_equals(host1.attachShadow({ mode: 'open', slotting: 'auto' }),
assert_not_equals(host2.attachShadow({ mode: 'open', slotting: 'auto' }),
null, 'slotting auto should work');
assert_throws(new TypeError(), () => {
host.attachShadow({ mode: 'open', slotting: 'exceptional' })},
host3.attachShadow({ mode: 'open', slotting: 'exceptional' })},
'others should throw exception');
}, 'attachShadow can take slotting parameter');
test(() => {
assert_array_equals(slot1.assignedElements(), []);
slot1.assign([child1]);
assert_array_equals(slot1.assignedNodes(), [child1]);
slot1.assign([child2,child3]);
assert_array_equals(slot1.assignedNodes(), [child2,child3]);
}, 'assignedNodes can be used in manual slotting');
</script>
......@@ -919,6 +919,7 @@ html element select
html element shadow
property getDistributedNodes
html element slot
property assign
property assignedElements
property assignedNodes
property name
......
......@@ -3497,6 +3497,7 @@ interface HTMLShadowElement : HTMLElement
interface HTMLSlotElement : HTMLElement
attribute @@toStringTag
getter name
method assign
method assignedElements
method assignedNodes
method constructor
......
......@@ -112,6 +112,10 @@ Node* ShadowRoot::Clone(Document&, CloneChildrenFlag) const {
return nullptr;
}
void ShadowRoot::SetSlotting(ShadowRootSlotting slotting) {
slotting_ = static_cast<unsigned short>(slotting);
}
String ShadowRoot::InnerHTMLAsString() const {
return CreateMarkup(this, kChildrenOnly);
}
......
......@@ -158,9 +158,7 @@ class CORE_EXPORT ShadowRoot final : public DocumentFragment, public TreeScope {
void SetDelegatesFocus(bool flag) { delegates_focus_ = flag; }
bool delegatesFocus() const { return delegates_focus_; }
void SetSlotting(ShadowRootSlotting slotting) {
slotting_ = static_cast<unsigned short>(slotting);
}
void SetSlotting(ShadowRootSlotting slotting);
bool IsManualSlotting() {
return slotting_ ==
static_cast<unsigned short>(ShadowRootSlotting::kManual);
......
......@@ -241,7 +241,16 @@ void SlotAssignment::RecalcAssignment() {
HTMLSlotElement* slot = nullptr;
if (!is_user_agent) {
slot = FindSlotByName(child.SlotName());
if (owner_->IsManualSlotting()) {
for (auto candidate : Slots()) {
if (candidate->ContainsInAssignedNodesCandidates(child)) {
slot = candidate;
break;
}
}
} else {
slot = FindSlotByName(child.SlotName());
}
} else {
if (user_agent_custom_assign_slot && ShouldAssignToCustomSlot(child)) {
slot = user_agent_custom_assign_slot;
......
......@@ -189,6 +189,18 @@ const HeapVector<Member<Element>> HTMLSlotElement::AssignedElementsForBinding(
return elements;
}
void HTMLSlotElement::assign(HeapVector<Member<Node>> nodes) {
ContainingShadowRoot()->GetSlotAssignment().SetNeedsAssignmentRecalc();
assigned_nodes_candidates_.clear();
for (Member<Node> child : nodes) {
assigned_nodes_candidates_.insert(child);
}
}
bool HTMLSlotElement::ContainsInAssignedNodesCandidates(Node& host_child) {
return assigned_nodes_candidates_.Contains(&host_child);
}
const HeapVector<Member<Node>>& HTMLSlotElement::GetDistributedNodes() {
DCHECK(!RuntimeEnabledFeatures::IncrementalShadowDOMEnabled());
DCHECK(!NeedsDistributionRecalc());
......@@ -691,6 +703,7 @@ void HTMLSlotElement::Trace(blink::Visitor* visitor) {
visitor->Trace(distributed_nodes_);
visitor->Trace(old_distributed_nodes_);
visitor->Trace(distributed_indices_);
visitor->Trace(assigned_nodes_candidates_);
HTMLElement::Trace(visitor);
}
......
......@@ -53,6 +53,9 @@ class CORE_EXPORT HTMLSlotElement final : public HTMLElement {
const HeapVector<Member<Element>> AssignedElementsForBinding(
const AssignedNodesOptions&);
void assign(HeapVector<Member<Node>> nodes);
bool ContainsInAssignedNodesCandidates(Node&);
const HeapVector<Member<Node>> FlattenedAssignedNodes();
Node* FirstAssignedNode() const {
......@@ -161,6 +164,8 @@ class CORE_EXPORT HTMLSlotElement final : public HTMLElement {
HeapVector<Member<Node>> assigned_nodes_;
bool slotchange_event_enqueued_ = false;
HeapHashSet<Member<Node>> assigned_nodes_candidates_;
// For IncrementalShadowDOM
HeapVector<Member<Node>> flat_tree_children_;
......
......@@ -30,4 +30,5 @@ interface HTMLSlotElement : HTMLElement {
[CEReactions, Reflect] attribute DOMString name;
[ImplementedAs=AssignedNodesForBinding] sequence<Node> assignedNodes(optional AssignedNodesOptions options);
[ImplementedAs=AssignedElementsForBinding] sequence<Elements> assignedElements(optional AssignedNodesOptions options);
[RuntimeEnabled=ManualSlotting] void assign(sequence<Node> nodes);
};
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