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* nearestAncestorAssignedToSlot = SlotScopedTraversal::nearestAncestorAssignedToSlot(current);
    if (slot) {
        if (Element* next = ElementTraversal::next(current, &current))
            return next;
    } else {
        // If current is in assigned scope, find an assigned ancestor.
        ASSERT(nearestAncestorAssignedToSlot);
        if (Element* next = ElementTraversal::next(current, nearestAncestorAssignedToSlot))
            return next;
        slot = nearestAncestorAssignedToSlot->assignedSlot();
        ASSERT(slot);
    }
    HeapVector<Member<Node>> assignedNodes = slot->getAssignedNodes();
    size_t currentIndex = assignedNodes.find(*nearestAncestorAssignedToSlot);
    ASSERT(currentIndex != kNotFound);
    for (++currentIndex; currentIndex < assignedNodes.size(); ++currentIndex) {
        if (assignedNodes[currentIndex]->isElementNode())
            return toElement(assignedNodes[currentIndex]);
    }
    return nullptr;
}
Node* FlatTreeTraversal::traverseSiblingsForV1HostChild(const Node& node, TraversalDirection direction)
{
    HTMLSlotElement* slot = finalDestinationSlotFor(node);
    if (!slot)
        return nullptr;
    if (Node* siblingInDistributedNodes = (direction == TraversalDirectionForward ? slot->distributedNodeNextTo(node) : slot->distributedNodePreviousTo(node)))
        return siblingInDistributedNodes;
    return traverseSiblings(*slot, direction);
}
void SlotAssignment::assign(Node& hostChild, HTMLSlotElement& slot)
{
    m_assignment.add(&hostChild, &slot);
    slot.appendAssignedNode(hostChild);
    if (isHTMLSlotElement(hostChild))
        slot.appendDistributedNodes(toHTMLSlotElement(hostChild).getDistributedNodes());
    else
        slot.appendDistributedNode(hostChild);
}
static HTMLSlotElement* finalDestinationSlotFor(const Node& node)
{
    HTMLSlotElement* slot = node.assignedSlot();
    if (!slot)
        return nullptr;
    for (HTMLSlotElement* next = slot->assignedSlot(); next; next = next->assignedSlot()) {
        slot = next;
    }
    return slot;
}
Beispiel #5
0
static bool wasInShadowTreeBeforeInserted(HTMLSlotElement& slot,
                                          ContainerNode& insertionPoint) {
  ShadowRoot* root1 = slot.containingShadowRoot();
  ShadowRoot* root2 = insertionPoint.containingShadowRoot();
  if (root1 && root2 && root1 == root2)
    return false;
  return root1;
}
Beispiel #6
0
static void flattenAssignedNodes(Vector<Node*>& nodes, const HTMLSlotElement& slot)
{
    auto* assignedNodes = slot.assignedNodes();
    if (!assignedNodes) {
        for (Node* child = slot.firstChild(); child; child = child->nextSibling()) {
            if (is<HTMLSlotElement>(*child))
                flattenAssignedNodes(nodes, downcast<HTMLSlotElement>(*child));
            else if (is<Text>(*child) || is<Element>(*child))
                nodes.append(child);
        }
        return;
    }
    for (Node* node : *assignedNodes) {
        if (is<HTMLSlotElement>(*node))
            flattenAssignedNodes(nodes, downcast<HTMLSlotElement>(*node));
        else
            nodes.append(node);
    }
}
Beispiel #7
0
void SlotAssignment::didChangeSlot(const AtomicString& slotAttrValue, ShadowRoot& shadowRoot)
{
    auto& slotName = slotNameFromAttributeValue(slotAttrValue);
    auto it = m_slots.find(slotName);
    if (it == m_slots.end())
        return;

    HTMLSlotElement* slotElement = findFirstSlotElement(*it->value, shadowRoot);
    if (!slotElement)
        return;

    shadowRoot.host()->invalidateStyleAndRenderersForSubtree();
    m_slotAssignmentsIsValid = false;

    if (shadowRoot.mode() == ShadowRootMode::UserAgent)
        return;

    slotElement->enqueueSlotChangeEvent();
}
void StyleInvalidator::invalidateSlotDistributedElements(HTMLSlotElement& slot, const RecursionData& recursionData) const
{
    for (auto& distributedNode : slot.getDistributedNodes()) {
        if (distributedNode->needsStyleRecalc())
            continue;
        if (!distributedNode->isElementNode())
            continue;
        if (recursionData.matchesCurrentInvalidationSetsAsSlotted(toElement(*distributedNode)))
            distributedNode->setNeedsStyleRecalc(LocalStyleChange, StyleChangeReasonForTracing::create(StyleChangeReason::StyleInvalidator));
    }
}
Element* SlotScopedTraversal::next(const Element& current) {
  Element* nearestInclusiveAncestorAssignedToSlot =
      SlotScopedTraversal::nearestInclusiveAncestorAssignedToSlot(current);
  DCHECK(nearestInclusiveAncestorAssignedToSlot);
  // Search within children of an element which is assigned to a slot.
  if (Element* next = nextSkippingChildrenOfShadowHost(
          current, *nearestInclusiveAncestorAssignedToSlot))
    return next;

  // Seek to the next element assigned to the same slot.
  HTMLSlotElement* slot =
      nearestInclusiveAncestorAssignedToSlot->assignedSlot();
  DCHECK(slot);
  const HeapVector<Member<Node>>& assignedNodes = slot->assignedNodes();
  size_t currentIndex =
      assignedNodes.find(*nearestInclusiveAncestorAssignedToSlot);
  DCHECK_NE(currentIndex, kNotFound);
  for (++currentIndex; currentIndex < assignedNodes.size(); ++currentIndex) {
    if (assignedNodes[currentIndex]->isElementNode())
      return toElement(assignedNodes[currentIndex]);
  }
  return nullptr;
}