Beispiel #1
0
void ShadowTree::recalcShadowTreeStyle(Node::StyleChange change)
{
    ShadowRoot* youngest = youngestShadowRoot();
    if (!youngest)
        return;

    if (needsReattachHostChildrenAndShadow())
        reattachHostChildrenAndShadow();
    else {
        StyleResolver* styleResolver = youngest->document()->styleResolver();

        styleResolver->pushParentShadowRoot(youngest);
        for (Node* n = youngest->firstChild(); n; n = n->nextSibling()) {
            if (n->isElementNode())
                static_cast<Element*>(n)->recalcStyle(change);
            else if (n->isTextNode())
                toText(n)->recalcTextStyle(change);
        }
        styleResolver->popParentShadowRoot(youngest);
    }

    clearNeedsReattachHostChildrenAndShadow();
    for (ShadowRoot* root = youngestShadowRoot(); root; root = root->olderShadowRoot()) {
        root->clearNeedsStyleRecalc();
        root->clearChildNeedsStyleRecalc();
    }
}
Beispiel #2
0
void ShadowTree::reattachHostChildrenAndShadow()
{
    ASSERT(youngestShadowRoot());

    Element* hostNode = youngestShadowRoot()->host();
    hostNode->detachChildrenIfNeeded();
    reattach();
    hostNode->attachChildrenIfNeeded();
}
Beispiel #3
0
bool ElementShadow::childNeedsStyleRecalc() const
{
    ASSERT(youngestShadowRoot());
    for (ShadowRoot* root = youngestShadowRoot(); root; root = root->olderShadowRoot())
        if (root->childNeedsStyleRecalc())
            return true;

    return false;
}
Beispiel #4
0
bool ShadowTree::needsStyleRecalc()
{
    ASSERT(youngestShadowRoot());
    for (ShadowRoot* root = youngestShadowRoot(); root; root = root->olderShadowRoot())
        if (root->needsStyleRecalc())
            return true;

    return false;
}
Beispiel #5
0
void ElementShadow::attach()
{
    ContentDistributor::ensureDistribution(youngestShadowRoot());

    for (ShadowRoot* root = youngestShadowRoot(); root; root = root->olderShadowRoot()) {
        if (!root->attached())
            root->attach();
    }
}
Beispiel #6
0
void ShadowTree::hostChildrenChanged()
{
    ASSERT(youngestShadowRoot());

    if (!youngestShadowRoot()->hasInsertionPoint())
        return;

    // This results in forced detaching/attaching of the shadow render tree. See ShadowRoot::recalcStyle().
    setNeedsReattachHostChildrenAndShadow();
}
Beispiel #7
0
void ElementShadow::detach()
{
    for (ShadowRoot* root = youngestShadowRoot(); root; root = root->olderShadowRoot()) {
        if (root->attached())
            root->detach();
    }
}
Beispiel #8
0
void ElementShadow::removeAllEventListeners()
{
    for (ShadowRoot* root = youngestShadowRoot(); root; root = root->olderShadowRoot()) {
        for (Node* node = root; node; node = NodeTraversal::next(node))
            node->removeAllEventListeners();
    }
}
Beispiel #9
0
ShadowRoot& ElementShadow::addShadowRoot(Element& shadowHost, ShadowRootType type)
{
    EventDispatchForbiddenScope assertNoEventDispatch;
    ScriptForbiddenScope forbidScript;

    if (type == ShadowRootType::V0 && m_shadowRoot) {
        DCHECK_EQ(m_shadowRoot->type(), ShadowRootType::V0);
        Deprecation::countDeprecation(shadowHost.document(), UseCounter::ElementCreateShadowRootMultiple);
    }

    if (m_shadowRoot) {
        // TODO(hayato): Is the order, from the youngest to the oldest, important?
        for (ShadowRoot* root = &youngestShadowRoot(); root; root = root->olderShadowRoot())
            root->lazyReattachIfAttached();
    }

    ShadowRoot* shadowRoot = ShadowRoot::create(shadowHost.document(), type);
    shadowRoot->setParentOrShadowHostNode(&shadowHost);
    shadowRoot->setParentTreeScope(shadowHost.treeScope());
    appendShadowRoot(*shadowRoot);
    setNeedsDistributionRecalc();

    shadowRoot->insertedInto(&shadowHost);
    shadowHost.setChildNeedsStyleRecalc();
    shadowHost.setNeedsStyleRecalc(SubtreeStyleChange, StyleChangeReasonForTracing::create(StyleChangeReason::Shadow));

    InspectorInstrumentation::didPushShadowRoot(&shadowHost, shadowRoot);

    return *shadowRoot;
}
Beispiel #10
0
void ElementShadow::distribute()
{
    if (isV1())
        youngestShadowRoot().distributeV1();
    else
        distributeV0();
}
Beispiel #11
0
void ElementShadow::clearDistribution()
{
    m_nodeToInsertionPoints.clear();

    for (ShadowRoot* root = &youngestShadowRoot(); root; root = root->olderShadowRoot())
        root->setShadowInsertionPointOfYoungerShadowRoot(nullptr);
}
Beispiel #12
0
void ElementShadow::detach(const Node::AttachContext& context)
{
    Node::AttachContext childrenContext(context);
    childrenContext.resolvedStyle = 0;

    for (ShadowRoot* root = &youngestShadowRoot(); root; root = root->olderShadowRoot())
        root->detach(childrenContext);
}
Beispiel #13
0
bool ElementShadow::resolveApplyAuthorStyles() const
{
    for (const ShadowRoot* shadowRoot = youngestShadowRoot(); shadowRoot; shadowRoot = shadowRoot->olderShadowRoot()) {
        if (shadowRoot->applyAuthorStyles())
            return true;
        if (!shadowRoot->containsShadowElements())
            break;
    }
    return false;
}
Beispiel #14
0
bool ElementShadow::containsActiveStyles() const
{
    for (ShadowRoot* root = youngestShadowRoot(); root; root = root->olderShadowRoot()) {
        if (root->hasScopedHTMLStyleChild())
            return true;
        if (!root->containsShadowElements())
            return false;
    }
    return false;
}
Beispiel #15
0
void ElementShadow::appendShadowRoot(ShadowRoot& shadowRoot)
{
    if (!m_shadowRoot) {
        m_shadowRoot = &shadowRoot;
        return;
    }
    ShadowRoot& youngest = youngestShadowRoot();
    DCHECK(shadowRoot.type() == ShadowRootType::V0);
    DCHECK(youngest.type() == ShadowRootType::V0);
    youngest.setYoungerShadowRoot(shadowRoot);
    shadowRoot.setOlderShadowRoot(youngest);
}
Beispiel #16
0
void ShadowTree::attach()
{
    // Children of m_selector is populated lazily in
    // ensureSelector(), and here we just ensure that it is in clean state.
    ASSERT(!selector().hasPopulated());

    selector().willSelect();
    for (ShadowRoot* root = youngestShadowRoot(); root; root = root->olderShadowRoot()) {
        if (!root->attached())
            root->attach();
    }
    selector().didSelect();
}
Beispiel #17
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();
    }
}
Beispiel #18
0
void ElementShadowV0::distribute() {
  HeapVector<Member<HTMLShadowElement>, 32> shadowInsertionPoints;
  DistributionPool pool(m_elementShadow->host());

  for (ShadowRoot* root = &youngestShadowRoot(); root;
       root = root->olderShadowRoot()) {
    HTMLShadowElement* shadowInsertionPoint = 0;
    for (const auto& point : root->descendantInsertionPoints()) {
      if (!point->isActive())
        continue;
      if (isHTMLShadowElement(*point)) {
        DCHECK(!shadowInsertionPoint);
        shadowInsertionPoint = toHTMLShadowElement(point);
        shadowInsertionPoints.append(shadowInsertionPoint);
      } else {
        pool.distributeTo(point, this);
        if (ElementShadow* shadow =
                shadowWhereNodeCanBeDistributedForV0(*point))
          shadow->setNeedsDistributionRecalc();
      }
    }
  }

  for (size_t i = shadowInsertionPoints.size(); i > 0; --i) {
    HTMLShadowElement* shadowInsertionPoint = shadowInsertionPoints[i - 1];
    ShadowRoot* root = shadowInsertionPoint->containingShadowRoot();
    DCHECK(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 =
            shadowWhereNodeCanBeDistributedForV0(*shadowInsertionPoint))
      shadow->setNeedsDistributionRecalc();
  }
  InspectorInstrumentation::didPerformElementShadowDistribution(
      &m_elementShadow->host());
}
Beispiel #19
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());
}
Beispiel #20
0
bool ElementShadow::hasSameStyles(const ElementShadow* other) const
{
    ShadowRoot* root = &youngestShadowRoot();
    ShadowRoot* otherRoot = &other->youngestShadowRoot();
    while (root || otherRoot) {
        if (!root || !otherRoot)
            return false;

        StyleSheetList& list = root->styleSheets();
        StyleSheetList& otherList = otherRoot->styleSheets();

        if (list.length() != otherList.length())
            return false;

        for (size_t i = 0; i < list.length(); i++) {
            if (toCSSStyleSheet(list.item(i))->contents() != toCSSStyleSheet(otherList.item(i))->contents())
                return false;
        }
        root = root->olderShadowRoot();
        otherRoot = otherRoot->olderShadowRoot();
    }

    return true;
}
Beispiel #21
0
ShadowRoot& ElementShadow::addShadowRoot(Element& shadowHost, ShadowRoot::ShadowRootType type)
{
    RefPtr<ShadowRoot> shadowRoot = ShadowRoot::create(shadowHost.document(), type);

    for (ShadowRoot* root = youngestShadowRoot(); root; root = root->olderShadowRoot())
        root->lazyReattachIfAttached();

    shadowRoot->setParentOrShadowHostNode(&shadowHost);
    shadowRoot->setParentTreeScope(shadowHost.treeScope());
    m_shadowRoots.push(shadowRoot.get());
    ChildNodeInsertionNotifier(shadowHost).notify(*shadowRoot);
    setNeedsDistributionRecalc();

    // addShadowRoot() affects apply-author-styles. However, we know that the youngest shadow root has not had any children yet.
    // The youngest shadow root's apply-author-styles is default (false). So we can just set m_applyAuthorStyles false.
    m_applyAuthorStyles = false;

    shadowHost.didAddShadowRoot(*shadowRoot);
    InspectorInstrumentation::didPushShadowRoot(&shadowHost, shadowRoot.get());

    ASSERT(m_shadowRoots.head());
    ASSERT(shadowRoot.get() == m_shadowRoots.head());
    return *m_shadowRoots.head();
}
Beispiel #22
0
void ElementShadow::recalcStyle(Node::StyleChange change)
{
    for (ShadowRoot* root = youngestShadowRoot(); root; root = root->olderShadowRoot())
        root->recalcStyle(change);
}
Beispiel #23
0
Internals::ShadowRootIfShadowDOMEnabledOrNode* Internals::shadowRoot(Element* host, ExceptionCode& ec)
{
    // FIXME: Internals::shadowRoot() in tests should be converted to youngestShadowRoot() or oldestShadowRoot().
    // https://bugs.webkit.org/show_bug.cgi?id=78465
    return youngestShadowRoot(host, ec);
}
Beispiel #24
0
void ShadowTree::setParentTreeScope(TreeScope* scope)
{
    for (ShadowRoot* root = youngestShadowRoot(); root; root = root->olderShadowRoot())
        root->setParentTreeScope(scope);
}
Beispiel #25
0
bool ShadowTree::needsReattachHostChildrenAndShadow()
{
    return m_needsRecalculateContent || (youngestShadowRoot() && youngestShadowRoot()->hasInsertionPoint());
}
Beispiel #26
0
void ElementShadow::distributeV1()
{
    if (!m_slotAssignment)
        m_slotAssignment = SlotAssignment::create();
    m_slotAssignment->resolveAssignment(youngestShadowRoot());
}