Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(207)

Unified Diff: third_party/WebKit/Source/core/dom/shadow/SlotScopedTraversal.cpp

Issue 2432293002: Fix focus navigation for nested slot case (Closed)
Patch Set: More proper fix Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: third_party/WebKit/Source/core/dom/shadow/SlotScopedTraversal.cpp
diff --git a/third_party/WebKit/Source/core/dom/shadow/SlotScopedTraversal.cpp b/third_party/WebKit/Source/core/dom/shadow/SlotScopedTraversal.cpp
index bbffc1cef8b7212c90bc0a9a4f10efaf0e6417bf..466d93ba8c1e6783921b192b35427f34b5605b7f 100644
--- a/third_party/WebKit/Source/core/dom/shadow/SlotScopedTraversal.cpp
+++ b/third_party/WebKit/Source/core/dom/shadow/SlotScopedTraversal.cpp
@@ -31,25 +31,32 @@ Element* SlotScopedTraversal::nearestAncestorAssignedToSlot(
}
Element* SlotScopedTraversal::next(const Element& current) {
- // current.assignedSlot returns a slot only when current is assigned
- // explicitly
- // If current is assigned to a slot, return a descendant of current, which is
- // in the assigned scope of the same slot as current.
- HTMLSlotElement* slot = current.assignedSlot();
+ Element* next = nullptr;
Element* nearestAncestorAssignedToSlot =
hayato 2016/10/24 06:43:26 Could we rename |nearestAncestorAssignedToSlot| to
kochi 2016/10/24 08:55:20 I agree the renaming, and adding "Inclusive" clari
SlotScopedTraversal::nearestAncestorAssignedToSlot(current);
- if (slot) {
- if (Element* next = ElementTraversal::next(current, &current))
- return next;
+ // Search within children of an element which is directly assigned to a slot.
hayato 2016/10/24 06:43:26 Could you remove |directly| from the comments in t
kochi 2016/10/24 08:55:20 Done.
+ if (current.assignedSlot()) {
+ next = ElementTraversal::next(current, &current);
} else {
// If current is in assigned scope, find an assigned ancestor.
DCHECK(nearestAncestorAssignedToSlot);
- if (Element* next =
- ElementTraversal::next(current, nearestAncestorAssignedToSlot))
- return next;
- slot = nearestAncestorAssignedToSlot->assignedSlot();
- DCHECK(slot);
+ if (current == nearestAncestorAssignedToSlot)
hayato 2016/10/24 06:43:26 When does it happen? It looks that current.assigne
kochi 2016/10/24 08:55:20 Good catch. Looks like an artifact while I was de
+ return nullptr;
+ next = ElementTraversal::next(current, nearestAncestorAssignedToSlot);
}
+
+ // Exclude elements that is assigned to another slot scope.
+ while (next && next->assignedSlot())
+ next = ElementTraversal::nextSkippingChildren(*next, &current);
+
+ if (next) {
+ DCHECK(!next->assignedSlot());
+ return next;
+ }
+
+ // Seek to the next element assigned to the same slot.
+ HTMLSlotElement* slot = nearestAncestorAssignedToSlot->assignedSlot();
+ DCHECK(slot);
HeapVector<Member<Node>> assignedNodes = slot->assignedNodes();
size_t currentIndex = assignedNodes.find(*nearestAncestorAssignedToSlot);
DCHECK_NE(currentIndex, kNotFound);
@@ -64,11 +71,23 @@ Element* SlotScopedTraversal::previous(const Element& current) {
Element* nearestAncestorAssignedToSlot =
SlotScopedTraversal::nearestAncestorAssignedToSlot(current);
DCHECK(nearestAncestorAssignedToSlot);
- // NodeTraversal within nearestAncestorAssignedToSlot
- if (Element* previous =
- ElementTraversal::previous(current, nearestAncestorAssignedToSlot))
- return previous;
- // If null, jump to previous assigned node's descendant
+
+ // Search within children of an element which is directly assigned to a slot.
+ Element* previous =
+ ElementTraversal::previous(current, nearestAncestorAssignedToSlot);
+
+ // TODO(kochi): repeatedly calling nearestAncestorAssignedToSlot() which
+ // is O(depth from directly slotted ancestor) and can be very slow.
+ while (previous) {
hayato 2016/10/24 06:43:26 Could you extract L81-L88 as a separate function?
kochi 2016/10/24 08:55:20 Separated as a function previousWithinSameSlotScop
+ Element* ancestor =
+ SlotScopedTraversal::nearestAncestorAssignedToSlot(*previous);
+ DCHECK(ancestor);
+ if (ancestor == nearestAncestorAssignedToSlot)
+ return previous;
+ previous = ancestor->parentElement();
+ }
+
+ // Seek to the previous element assigned to the same slot.
const HeapVector<Member<Node>> assignedNodes =
nearestAncestorAssignedToSlot->assignedSlot()->assignedNodes();
size_t currentIndex =
@@ -76,12 +95,22 @@ Element* SlotScopedTraversal::previous(const Element& current) {
DCHECK_NE(currentIndex, kNotFound);
for (; currentIndex > 0; --currentIndex) {
const Member<Node> assignedPrevious = assignedNodes[currentIndex - 1];
- if (assignedPrevious->isElementNode()) {
- if (Element* last =
- ElementTraversal::lastWithin(*toElement(assignedPrevious)))
- return last;
+ if (!assignedPrevious->isElementNode())
+ continue;
+
+ Element* last = ElementTraversal::lastWithin(*toElement(assignedPrevious));
+ if (!last)
return toElement(assignedPrevious);
+
+ while (last) {
+ Element* ancestor =
+ SlotScopedTraversal::nearestAncestorAssignedToSlot(*last);
+ DCHECK(ancestor);
+ if (ancestor == assignedPrevious)
+ return last;
+ last = ancestor->parentElement();
}
+ NOTREACHED();
}
return nullptr;
}

Powered by Google App Engine
This is Rietveld 408576698