void InsertionPoint::removedFrom(ContainerNode* insertionPoint)
{
ShadowRoot* root = containingShadowRoot();
if (!root)
    root = insertionPoint->containingShadowRoot();

if (root) {
    if (ElementShadow* rootOwner = root->owner())
        rootOwner->setNeedsDistributionRecalc();
}

// host can be null when removedFrom() is called from ElementShadow destructor.
ElementShadow* rootOwner = root ? root->owner() : 0;

// Since this insertion point is no longer visible from the shadow subtree, it need to clean itself up.
clearDistribution();

if (m_registeredWithShadowRoot && insertionPoint->treeScope().rootNode() == root) {
    ASSERT(root);
    m_registeredWithShadowRoot = false;
    root->didRemoveInsertionPoint(this);
    if (rootOwner) {
        if (canAffectSelector())
            rootOwner->willAffectSelector();
    }
}

HTMLElement::removedFrom(insertionPoint);
}
Node* ComposedTreeWalker::traverseChild(const Node* node, TraversalDirection direction) const
{
    ASSERT(node);
    ElementShadow* shadow = shadowFor(node);
    return shadow ? traverseLightChildren(shadow->youngestShadowRoot(), direction)
            : traverseLightChildren(node, direction);
}
Beispiel #3
0
void ScopedStyleResolver::matchHostRules(ElementRuleCollector& collector, bool includeEmptyRules)
{
    if (m_atHostRules.isEmpty() || !m_scopingNode->isElementNode())
        return;

    ElementShadow* shadow = toElement(m_scopingNode)->shadow();
    if (!shadow)
        return;

    collector.clearMatchedRules();
    collector.matchedResult().ranges.lastAuthorRule = collector.matchedResult().matchedProperties.size() - 1;

    // FIXME(99827): https://bugs.webkit.org/show_bug.cgi?id=99827
    // add a new flag to ElementShadow and cache whether any @host @-rules are
    // applied to the element or not. So we can quickly exit this method
    // by using the flag.
    ShadowRoot* shadowRoot = shadow->youngestShadowRoot();
    for (; shadowRoot; shadowRoot = shadowRoot->olderShadowRoot())
        if (!ScopeContentDistribution::hasShadowElement(shadowRoot))
            break;
    // All shadow roots have <shadow>.
    if (!shadowRoot)
        shadowRoot = shadow->oldestShadowRoot();

    StyleResolver::RuleRange ruleRange = collector.matchedResult().ranges.authorRuleRange();
    collector.setBehaviorAtBoundary(static_cast<SelectorChecker::BehaviorAtBoundary>(SelectorChecker::DoesNotCrossBoundary | SelectorChecker::ScopeContainsLastMatchedElement));
    for (; shadowRoot; shadowRoot = shadowRoot->youngerShadowRoot()) {
        if (RuleSet* ruleSet = atHostRuleSetFor(shadowRoot))
            collector.collectMatchingRules(MatchRequest(ruleSet, includeEmptyRules, m_scopingNode), ruleRange);
    }

    collector.sortAndTransferMatchedRules();
}
Beispiel #4
0
void ElementShadowV0::willAffectSelector() {
  for (ElementShadow* shadow = m_elementShadow; shadow;
       shadow = shadow->containingShadow()) {
    if (shadow->isV1() || shadow->v0().needsSelectFeatureSet())
      break;
    shadow->v0().setNeedsSelectFeatureSet();
  }
  m_elementShadow->setNeedsDistributionRecalc();
}
Beispiel #5
0
void ElementShadow::willAffectSelector()
{
    for (ElementShadow* shadow = this; shadow; shadow = shadow->containingShadow()) {
        if (shadow->needsSelectFeatureSet())
            break;
        shadow->setNeedsSelectFeatureSet();
    }
    setNeedsDistributionRecalc();
}
Node* FlatTreeTraversal::traverseChild(const Node& node, TraversalDirection direction)
{
    ElementShadow* shadow = shadowFor(node);
    if (shadow) {
        ShadowRoot& shadowRoot = shadow->youngestShadowRoot();
        return resolveDistributionStartingAt(direction == TraversalDirectionForward ? shadowRoot.firstChild() : shadowRoot.lastChild(), direction);
    }
    return resolveDistributionStartingAt(direction == TraversalDirectionForward ? node.firstChild() : node.lastChild(), direction);
}
Node* ComposedShadowTreeWalker::traverseChild(const Node* node, TraversalDirection direction) const
{
    ASSERT(node);
    if (canCrossUpperBoundary()) {
        ElementShadow* shadow = shadowFor(node);
        return shadow ? traverseLightChildren(shadow->youngestShadowRoot(), direction)
            : traverseLightChildren(node, direction);
    }
    if (isShadowHost(node))
        return 0;
    return traverseLightChildren(node, direction);
}
Beispiel #8
0
Node* ComposedShadowTreeWalker::traverseSiblingOrBackToInsertionPoint(const Node* node, TraversalDirection direction)
{
    ASSERT(node);
    ElementShadow* shadow = shadowOfParent(node);
    if (!shadow)
        return traverseSiblingInCurrentTree(node, direction);
    InsertionPoint* insertionPoint = shadow->insertionPointFor(node);
    if (!insertionPoint)
        return traverseSiblingInCurrentTree(node, direction);
    if (Node* next = (direction == TraversalDirectionForward ? insertionPoint->nextTo(node) : insertionPoint->previousTo(node)))
        return traverseNode(next, direction);
    return traverseSiblingOrBackToInsertionPoint(insertionPoint, direction);
}
// FIXME: Move the following helper functions, authorShadowRootOf, firstWithinTraversingShadowTree,
// nextTraversingShadowTree to the best place, e.g. NodeTraversal.
static ShadowRoot* authorShadowRootOf(const ContainerNode& node)
{
    if (!node.isElementNode() || !isShadowHost(&node))
        return 0;

    ElementShadow* shadow = toElement(node).shadow();
    ASSERT(shadow);
    for (ShadowRoot* shadowRoot = shadow->oldestShadowRoot(); shadowRoot; shadowRoot = shadowRoot->youngerShadowRoot()) {
        if (shadowRoot->type() == ShadowRoot::AuthorShadowRoot)
            return shadowRoot;
    }
    return 0;
}
Beispiel #10
0
// FIXME: Move the following helper functions, authorShadowRootOf, firstWithinTraversingShadowTree,
// nextTraversingShadowTree to the best place, e.g. NodeTraversal.
static ShadowRoot* authorShadowRootOf(const ContainerNode& node)
{
    if (!node.isElementNode() || !isShadowHost(&node))
        return nullptr;

    ElementShadow* shadow = toElement(node).shadow();
    ASSERT(shadow);
    for (ShadowRoot* shadowRoot = shadow->oldestShadowRoot(); shadowRoot; shadowRoot = shadowRoot->youngerShadowRoot()) {
        if (shadowRoot->type() == ShadowRootType::OpenByDefault || shadowRoot->type() == ShadowRootType::Open)
            return shadowRoot;
    }
    return nullptr;
}
Beispiel #11
0
void ContentDistributor::ensureDistribution(ShadowRoot* shadowRoot)
{
    ASSERT(shadowRoot);

    Vector<ElementShadow*, 8> elementShadows;
    for (Element* current = shadowRoot->host(); current; current = current->shadowHost()) {
        ElementShadow* elementShadow = current->shadow();
        if (!elementShadow->distributor().needsDistribution())
            break;

        elementShadows.append(elementShadow);
    }

    for (size_t i = elementShadows.size(); i > 0; --i)
        elementShadows[i - 1]->distributor().distribute(elementShadows[i - 1]->host());
}
void ScopedStyleTree::collectScopedResolversForHostedShadowTrees(const Element* element, Vector<ScopedStyleResolver*, 8>& resolvers)
{
    ElementShadow* shadow = element->shadow();
    if (!shadow)
        return;

    // Adding scoped resolver for active shadow roots for shadow host styling.
    for (ShadowRoot* shadowRoot = shadow->youngestShadowRoot(); shadowRoot; shadowRoot = shadowRoot->olderShadowRoot()) {
        if (shadowRoot->hasScopedHTMLStyleChild()) {
            if (ScopedStyleResolver* resolver = scopedStyleResolverFor(*shadowRoot))
                resolvers.append(resolver);
        }
        if (!shadowRoot->containsShadowElements())
            break;
    }
}
Beispiel #13
0
void InputType::destroyShadowSubtree()
{
    ElementShadow* shadow = element()->shadow();
    if (!shadow)
        return;

    ShadowRoot* root = shadow->oldestShadowRoot();
    root->removeAllChildren();

    // It's ok to clear contents of all other ShadowRoots because they must have
    // been created by TextFieldDecorationElement, and we don't allow adding
    // AuthorShadowRoot to HTMLInputElement.
    while ((root = root->youngerShadowRoot())) {
        root->removeAllChildren();
        root->appendChild(HTMLShadowElement::create(shadowTag, element()->document()));
    }
}
void StyleScopeResolver::matchHostRules(const Element* element, Vector<RuleSet*>& matchedRules)
{
    if (m_atHostRules.isEmpty())
        return;

    ElementShadow* shadow = element->shadow();
    if (!shadow)
        return;

    // FIXME(99827): https://bugs.webkit.org/show_bug.cgi?id=99827
    // add a new flag to ElementShadow and cache whether any @host @-rules are
    // applied to the element or not. So we can quickly exit this method
    // by using the flag.
    if (ShadowRoot* shadowRoot = shadow->shadowRoot()) {
        if (RuleSet* ruleSet = atHostRuleSetFor(shadowRoot))
            matchedRules.append(ruleSet);
    }
}
void collectDestinationInsertionPoints(const Node& node, WillBeHeapVector<RawPtrWillBeMember<InsertionPoint>, 8>& results)
{
const Node* current = &node;
ElementShadow* lastElementShadow = 0;
while (true) {
    ElementShadow* shadow = shadowWhereNodeCanBeDistributed(*current);
    if (!shadow || shadow == lastElementShadow)
        return;
    lastElementShadow = shadow;
    const DestinationInsertionPoints* insertionPoints = shadow->destinationInsertionPointsFor(&node);
    if (!insertionPoints)
        return;
    for (size_t i = 0; i < insertionPoints->size(); ++i)
        results.append(insertionPoints->at(i).get());
    ASSERT(current != insertionPoints->last().get());
    current = insertionPoints->last().get();
}
}
Beispiel #16
0
void InsertionPoint::detach()
{
    ShadowRoot* root = shadowRoot();
    if (root && isActive()) {
        ElementShadow* shadow = root->owner();

        if (doesSelectFromHostChildren())
            clearDistribution(shadow);
        else if (ShadowRoot* assignedShadowRoot = assignedFrom())
            clearAssignment(assignedShadowRoot);

        // When shadow element is detached, shadow tree should be recreated to re-calculate selector for
        // other insertion points.
        shadow->setNeedsRedistributing();
    }

    ASSERT(m_distribution.isEmpty());
    HTMLElement::detach();
}
bool StyleScopeResolver::styleSharingCandidateMatchesHostRules(const Element* element)
{
    if (m_atHostRules.isEmpty())
        return false;

    ElementShadow* shadow = element->shadow();
    if (!shadow)
        return false;

    // FIXME(99827): https://bugs.webkit.org/show_bug.cgi?id=99827
    // add a new flag to ElementShadow and cache whether any@host @-rules are
    // applied to the element or not. So we can avoid always traversing
    // shadow roots.
    if (ShadowRoot* shadowRoot = shadow->shadowRoot()) {
        if (atHostRuleSetFor(shadowRoot))
            return true;
    }
    return false;
}
const InsertionPoint* resolveReprojection(const Node* projectedNode)
{
ASSERT(projectedNode);
const InsertionPoint* insertionPoint = 0;
const Node* current = projectedNode;
ElementShadow* lastElementShadow = 0;
while (true) {
    ElementShadow* shadow = shadowWhereNodeCanBeDistributed(*current);
    if (!shadow || shadow == lastElementShadow)
        break;
    lastElementShadow = shadow;
    const InsertionPoint* insertedTo = shadow->finalDestinationInsertionPointFor(projectedNode);
    if (!insertedTo)
        break;
    ASSERT(current != insertedTo);
    current = insertedTo;
    insertionPoint = insertedTo;
}
return insertionPoint;
}
Beispiel #19
0
void InsertionPoint::removedFrom(ContainerNode* insertionPoint)
{
    ShadowRoot* root = containingShadowRoot();
    if (!root)
        root = insertionPoint->containingShadowRoot();

    // host can be null when removedFrom() is called from ElementShadow destructor.
    ElementShadow* rootOwner = root ? root->owner() : 0;
    if (rootOwner)
        rootOwner->invalidateDistribution();

    // Since this insertion point is no longer visible from the shadow subtree, it need to clean itself up.
    clearDistribution();

    if (m_registeredWithShadowRoot && insertionPoint->treeScope()->rootNode() == root) {
        ASSERT(root);
        m_registeredWithShadowRoot = false;
        root->ensureScopeDistribution()->unregisterInsertionPoint(this);
    }

    HTMLElement::removedFrom(insertionPoint);
}
void ChildFrameDisconnector::collectFrameOwners(ElementShadow& shadow)
{
    for (ShadowRoot* root = &shadow.youngestShadowRoot(); root; root = root->olderShadowRoot())
        collectFrameOwners(*root);
}