Commit 75f3875b authored by Kyoko Muto's avatar Kyoko Muto Committed by Commit Bot

Add SlottingChildTable in ShadowTree for manual-slotting mode

This CL make Hashmap in ShadowTree to connect nodes to slot in manual slotting mode.

BUG=869308

Change-Id: I59e6bfcb1dc2a91cf3344623bbbf6f7c8545af0a
Reviewed-on: https://chromium-review.googlesource.com/1174133Reviewed-by: default avatarHayato Ito <hayato@chromium.org>
Commit-Queue: Kyoko Muto <kymuto@google.com>
Cr-Commit-Position: refs/heads/master@{#583212}
parent 649fed42
...@@ -30,7 +30,9 @@ const child2 = document.querySelector('#child2'); ...@@ -30,7 +30,9 @@ const child2 = document.querySelector('#child2');
const child3 = document.querySelector('#child3'); const child3 = document.querySelector('#child3');
const shadow_root = host.attachShadow({ mode: 'open', slotting: 'manual' }); const shadow_root = host.attachShadow({ mode: 'open', slotting: 'manual' });
const slot1 = document.createElement('slot'); const slot1 = document.createElement('slot');
const slot2 = document.createElement('slot');
shadow_root.appendChild(slot1); shadow_root.appendChild(slot1);
shadow_root.appendChild(slot2);
test(() => { test(() => {
assert_not_equals(host1.attachShadow({ mode: 'open', slotting: 'manual' }), assert_not_equals(host1.attachShadow({ mode: 'open', slotting: 'manual' }),
...@@ -44,8 +46,17 @@ test(() => { ...@@ -44,8 +46,17 @@ test(() => {
test(() => { test(() => {
assert_array_equals(slot1.assignedElements(), []); assert_array_equals(slot1.assignedElements(), []);
assert_equals(child1.assignedSlot, null);
slot1.assign([child1]); slot1.assign([child1]);
assert_array_equals(slot1.assignedNodes(), [child1]); assert_array_equals(slot1.assignedNodes(), [child1]);
assert_equals(child1.assignedSlot, slot1);
slot2.assign([child1]);
assert_array_equals(slot1.assignedNodes(), []);
assert_equals(child1.assignedSlot, slot2);
slot1.assign([child2,child3]); slot1.assign([child2,child3]);
assert_array_equals(slot1.assignedNodes(), [child2,child3]); assert_array_equals(slot1.assignedNodes(), [child2,child3]);
}, 'assignedNodes can be used in manual slotting'); }, 'assignedNodes can be used in manual slotting');
......
...@@ -242,12 +242,7 @@ void SlotAssignment::RecalcAssignment() { ...@@ -242,12 +242,7 @@ void SlotAssignment::RecalcAssignment() {
HTMLSlotElement* slot = nullptr; HTMLSlotElement* slot = nullptr;
if (!is_user_agent) { if (!is_user_agent) {
if (owner_->IsManualSlotting()) { if (owner_->IsManualSlotting()) {
for (auto candidate : Slots()) { slot = FindLastAssignedSlot(const_cast<Node&>(child));
if (candidate->ContainsInAssignedNodesCandidates(child)) {
slot = candidate;
break;
}
}
} else { } else {
slot = FindSlotByName(child.SlotName()); slot = FindSlotByName(child.SlotName());
} }
...@@ -344,7 +339,9 @@ HTMLSlotElement* SlotAssignment::FindSlot(const Node& node) const { ...@@ -344,7 +339,9 @@ HTMLSlotElement* SlotAssignment::FindSlot(const Node& node) const {
return nullptr; return nullptr;
if (owner_->IsUserAgent()) if (owner_->IsUserAgent())
return FindSlotInUserAgentShadow(node); return FindSlotInUserAgentShadow(node);
return FindSlotByName(node.SlotName()); return owner_->IsManualSlotting()
? FindLastAssignedSlot(const_cast<Node&>(node))
: FindSlotByName(node.SlotName());
} }
HTMLSlotElement* SlotAssignment::FindSlotByName( HTMLSlotElement* SlotAssignment::FindSlotByName(
...@@ -363,6 +360,28 @@ HTMLSlotElement* SlotAssignment::FindSlotInUserAgentShadow( ...@@ -363,6 +360,28 @@ HTMLSlotElement* SlotAssignment::FindSlotInUserAgentShadow(
return user_agent_default_slot; return user_agent_default_slot;
} }
HTMLSlotElement* SlotAssignment::FindLastAssignedSlot(Node& node) const {
auto it = child_assigned_slot_history_.find(&node);
if (it == child_assigned_slot_history_.end())
return nullptr;
return it.Get()->value.back();
}
void SlotAssignment::InsertSlotInChildSlotMap(
HTMLSlotElement& slot,
const HeapVector<Member<Node>>& nodes) {
for (Member<Node> child : nodes) {
auto it = child_assigned_slot_history_.find(child);
if (it == child_assigned_slot_history_.end()) {
HeapVector<Member<HTMLSlotElement>> tmp;
tmp.push_back(slot);
child_assigned_slot_history_.Set(child, tmp);
} else {
it.Get()->value.push_back(slot);
}
}
}
void SlotAssignment::CollectSlots() { void SlotAssignment::CollectSlots() {
DCHECK(needs_collect_slots_); DCHECK(needs_collect_slots_);
slots_.clear(); slots_.clear();
...@@ -389,6 +408,7 @@ void SlotAssignment::Trace(blink::Visitor* visitor) { ...@@ -389,6 +408,7 @@ void SlotAssignment::Trace(blink::Visitor* visitor) {
visitor->Trace(slots_); visitor->Trace(slots_);
visitor->Trace(slot_map_); visitor->Trace(slot_map_);
visitor->Trace(owner_); visitor->Trace(owner_);
visitor->Trace(child_assigned_slot_history_);
} }
} // namespace blink } // namespace blink
...@@ -44,6 +44,9 @@ class SlotAssignment final : public GarbageCollected<SlotAssignment> { ...@@ -44,6 +44,9 @@ class SlotAssignment final : public GarbageCollected<SlotAssignment> {
bool FindHostChildBySlotName(const AtomicString& slot_name) const; bool FindHostChildBySlotName(const AtomicString& slot_name) const;
void InsertSlotInChildSlotMap(HTMLSlotElement& slot,
const HeapVector<Member<Node>>& nodes);
void Trace(blink::Visitor*); void Trace(blink::Visitor*);
// For Incremental Shadow DOM // For Incremental Shadow DOM
...@@ -64,6 +67,8 @@ class SlotAssignment final : public GarbageCollected<SlotAssignment> { ...@@ -64,6 +67,8 @@ class SlotAssignment final : public GarbageCollected<SlotAssignment> {
HTMLSlotElement* FindSlotInUserAgentShadow(const Node&) const; HTMLSlotElement* FindSlotInUserAgentShadow(const Node&) const;
HTMLSlotElement* FindLastAssignedSlot(Node&) const;
void CollectSlots(); void CollectSlots();
HTMLSlotElement* GetCachedFirstSlotWithoutAccessingNodeTree( HTMLSlotElement* GetCachedFirstSlotWithoutAccessingNodeTree(
const AtomicString& slot_name); const AtomicString& slot_name);
...@@ -78,6 +83,8 @@ class SlotAssignment final : public GarbageCollected<SlotAssignment> { ...@@ -78,6 +83,8 @@ class SlotAssignment final : public GarbageCollected<SlotAssignment> {
HeapVector<Member<HTMLSlotElement>> slots_; HeapVector<Member<HTMLSlotElement>> slots_;
Member<TreeOrderedMap> slot_map_; Member<TreeOrderedMap> slot_map_;
HeapHashMap<Member<Node>, HeapVector<Member<HTMLSlotElement>>>
child_assigned_slot_history_;
WeakMember<ShadowRoot> owner_; WeakMember<ShadowRoot> owner_;
unsigned needs_collect_slots_ : 1; unsigned needs_collect_slots_ : 1;
unsigned needs_assignment_recalc_ : 1; // For Incremental Shadow DOM unsigned needs_assignment_recalc_ : 1; // For Incremental Shadow DOM
......
...@@ -190,6 +190,8 @@ const HeapVector<Member<Element>> HTMLSlotElement::AssignedElementsForBinding( ...@@ -190,6 +190,8 @@ const HeapVector<Member<Element>> HTMLSlotElement::AssignedElementsForBinding(
} }
void HTMLSlotElement::assign(HeapVector<Member<Node>> nodes) { void HTMLSlotElement::assign(HeapVector<Member<Node>> nodes) {
ContainingShadowRoot()->GetSlotAssignment().InsertSlotInChildSlotMap(*this,
nodes);
ContainingShadowRoot()->GetSlotAssignment().SetNeedsAssignmentRecalc(); ContainingShadowRoot()->GetSlotAssignment().SetNeedsAssignmentRecalc();
assigned_nodes_candidates_.clear(); assigned_nodes_candidates_.clear();
for (Member<Node> child : nodes) { for (Member<Node> child : 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