Beispiel #1
0
void ElementShadow::distribute()
{
    host()->setNeedsStyleRecalc();
    Vector<HTMLShadowElement*, 32> shadowInsertionPoints;
    DistributionPool pool(*host());

    for (ShadowRoot* root = youngestShadowRoot(); root; root = root->olderShadowRoot()) {
        HTMLShadowElement* shadowInsertionPoint = 0;
        const Vector<RefPtr<InsertionPoint> >& insertionPoints = root->descendantInsertionPoints();
        for (size_t i = 0; i < insertionPoints.size(); ++i) {
            InsertionPoint* point = insertionPoints[i].get();
            if (!point->isActive())
                continue;
            if (isHTMLShadowElement(point)) {
                if (!shadowInsertionPoint)
                    shadowInsertionPoint = toHTMLShadowElement(point);
            } else {
                pool.distributeTo(point, this);
                if (ElementShadow* shadow = shadowWhereNodeCanBeDistributed(*point))
                    shadow->setNeedsDistributionRecalc();
            }
        }
        if (shadowInsertionPoint) {
            shadowInsertionPoints.append(shadowInsertionPoint);
            if (shadowInsertionPoint->hasChildNodes())
                pool.populateChildren(*shadowInsertionPoint);
        } else {
            pool.clear();
        }
    }

    for (size_t i = shadowInsertionPoints.size(); i > 0; --i) {
        HTMLShadowElement* shadowInsertionPoint = shadowInsertionPoints[i - 1];
        ShadowRoot* root = shadowInsertionPoint->containingShadowRoot();
        ASSERT(root);
        if (root->isOldest()) {
            pool.distributeTo(shadowInsertionPoint, this);
        } else if (root->olderShadowRoot()->type() == root->type()) {
            // Only allow reprojecting older shadow roots between the same type to
            // disallow reprojecting UA elements into author shadows.
            DistributionPool olderShadowRootPool(*root->olderShadowRoot());
            olderShadowRootPool.distributeTo(shadowInsertionPoint, this);
            root->olderShadowRoot()->setShadowInsertionPointOfYoungerShadowRoot(shadowInsertionPoint);
        }
        if (ElementShadow* shadow = shadowWhereNodeCanBeDistributed(*shadowInsertionPoint))
            shadow->setNeedsDistributionRecalc();
    }
}
ContainerNode* FlatTreeTraversal::traverseParent(const Node& node, ParentTraversalDetails* details)
{
    // TODO(hayato): Stop this hack for a pseudo element because a pseudo element is not a child of its parentOrShadowHostNode() in a flat tree.
    if (node.isPseudoElement())
        return node.parentOrShadowHostNode();

    if (node.isChildOfV1ShadowHost()) {
        HTMLSlotElement* slot = finalDestinationSlotFor(node);
        if (!slot)
            return nullptr;
        return traverseParent(*slot);
    }

    Element* parent = node.parentElement();
    if (parent && isHTMLSlotElement(parent)) {
        HTMLSlotElement& slot = toHTMLSlotElement(*parent);
        if (!slot.assignedNodes().isEmpty())
            return nullptr;
        return traverseParent(slot, details);
    }

    if (canBeDistributedToInsertionPoint(node))
        return traverseParentForV0(node, details);

    DCHECK(!shadowWhereNodeCanBeDistributed(node));
    return traverseParentOrHost(node);
}
// TODO(hayato): This may return a wrong result for a node which is not in a
// document flat tree.  See FlatTreeTraversalTest's redistribution test for details.
Node* FlatTreeTraversal::traverseSiblings(const Node& node, TraversalDirection direction)
{
    if (node.isChildOfV1ShadowHost())
        return traverseSiblingsForV1HostChild(node, direction);

    if (shadowWhereNodeCanBeDistributed(node))
        return traverseSiblingsForV0Distribution(node, direction);

    if (Node* found = resolveDistributionStartingAt(direction == TraversalDirectionForward ? node.nextSibling() : node.previousSibling(), direction))
        return found;

    if (!node.isInV0ShadowTree())
        return nullptr;

    // For v0 older shadow tree
    if (node.parentNode() && node.parentNode()->isShadowRoot()) {
        ShadowRoot* parentShadowRoot = toShadowRoot(node.parentNode());
        if (!parentShadowRoot->isYoungest()) {
            HTMLShadowElement* assignedInsertionPoint = parentShadowRoot->shadowInsertionPointOfYoungerShadowRoot();
            DCHECK(assignedInsertionPoint);
            return traverseSiblings(*assignedInsertionPoint, direction);
        }
    }
    return nullptr;
}
ContainerNode* FlatTreeTraversal::traverseParentForV0(const Node& node, ParentTraversalDetails* details)
{
    if (shadowWhereNodeCanBeDistributed(node)) {
        if (const InsertionPoint* insertionPoint = resolveReprojection(&node)) {
            if (details)
                details->didTraverseInsertionPoint(insertionPoint);
            // The node is distributed. But the distribution was stopped at this insertion point.
            if (shadowWhereNodeCanBeDistributed(*insertionPoint))
                return nullptr;
            return traverseParent(*insertionPoint);
        }
        return nullptr;
    }
    ContainerNode* parent = traverseParentOrHost(node);
    if (isActiveInsertionPoint(*parent))
        return nullptr;
    return parent;
}
// FIXME: Use an iterative algorithm so that it can be inlined.
// https://bugs.webkit.org/show_bug.cgi?id=90415
Node* ComposedTreeWalker::traverseParent(const Node* node, ParentTraversalDetails* details) const
{
    if (node->isPseudoElement())
        return node->parentOrShadowHostNode();

    if (shadowWhereNodeCanBeDistributed(*node)) {
        if (const InsertionPoint* insertionPoint = resolveReprojection(node)) {
            if (details)
                details->didTraverseInsertionPoint(insertionPoint);
            // The node is distributed. But the distribution was stopped at this insertion point.
            if (shadowWhereNodeCanBeDistributed(*insertionPoint))
                return 0;
            return traverseParentOrHost(insertionPoint, details);
        }
        return 0;
    }
    return traverseParentOrHost(node, details);
}
Beispiel #6
0
void ElementShadow::distributeV0()
{
    host()->setNeedsStyleRecalc(SubtreeStyleChange, StyleChangeReasonForTracing::create(StyleChangeReason::Shadow));
    WillBeHeapVector<RawPtrWillBeMember<HTMLShadowElement>, 32> shadowInsertionPoints;
    DistributionPool pool(*host());

    for (ShadowRoot* root = &youngestShadowRoot(); root; root = root->olderShadowRoot()) {
        HTMLShadowElement* shadowInsertionPoint = 0;
        const WillBeHeapVector<RefPtrWillBeMember<InsertionPoint>>& insertionPoints = root->descendantInsertionPoints();
        for (size_t i = 0; i < insertionPoints.size(); ++i) {
            InsertionPoint* point = insertionPoints[i].get();
            if (!point->isActive())
                continue;
            if (isHTMLShadowElement(*point)) {
                ASSERT(!shadowInsertionPoint);
                shadowInsertionPoint = toHTMLShadowElement(point);
                shadowInsertionPoints.append(shadowInsertionPoint);
            } else {
                pool.distributeTo(point, this);
                if (ElementShadow* shadow = shadowWhereNodeCanBeDistributed(*point))
                    shadow->setNeedsDistributionRecalc();
            }
        }
    }

    for (size_t i = shadowInsertionPoints.size(); i > 0; --i) {
        HTMLShadowElement* shadowInsertionPoint = shadowInsertionPoints[i - 1];
        ShadowRoot* root = shadowInsertionPoint->containingShadowRoot();
        ASSERT(root);
        if (root->isOldest()) {
            pool.distributeTo(shadowInsertionPoint, this);
        } else if (root->olderShadowRoot()->type() == root->type()) {
            // Only allow reprojecting older shadow roots between the same type to
            // disallow reprojecting UA elements into author shadows.
            DistributionPool olderShadowRootPool(*root->olderShadowRoot());
            olderShadowRootPool.distributeTo(shadowInsertionPoint, this);
            root->olderShadowRoot()->setShadowInsertionPointOfYoungerShadowRoot(shadowInsertionPoint);
        }
        if (ElementShadow* shadow = shadowWhereNodeCanBeDistributed(*shadowInsertionPoint))
            shadow->setNeedsDistributionRecalc();
    }
    InspectorInstrumentation::didPerformElementShadowDistribution(host());
}
Node* ComposedTreeWalker::traverseSiblingOrBackToInsertionPoint(const Node* node, TraversalDirection direction)
{
    ASSERT(node);

    if (!shadowWhereNodeCanBeDistributed(*node))
        return traverseSiblingInCurrentTree(node, direction);

    const InsertionPoint* insertionPoint = resolveReprojection(node);
    if (!insertionPoint)
        return traverseSiblingInCurrentTree(node, direction);

    if (Node* found = traverseDistributedNodes(direction == TraversalDirectionForward ? insertionPoint->nextTo(node) : insertionPoint->previousTo(node), insertionPoint, direction))
        return found;
    return traverseSiblingOrBackToInsertionPoint(insertionPoint, direction);
}