RenderObject* NodeRenderingContext::previousRenderer() const
{
    ASSERT(m_node->renderer() || m_location != LocationUndetermined);
    if (RenderObject* renderer = m_node->renderer())
        return renderer->previousSibling();

    if (m_parentFlowRenderer)
        return m_parentFlowRenderer->previousRendererForNode(m_node);

    if (m_phase == AttachContentForwarded) {
        if (RenderObject* found = previousRendererOf(m_includer, m_node))
            return found;
        return NodeRenderingContext(m_includer).previousRenderer();
    }

    // FIXME: We should have the same O(N^2) avoidance as nextRenderer does
    // however, when I tried adding it, several tests failed.
    for (Node* node = m_node->previousSibling(); node; node = node->previousSibling()) {
        if (node->renderer()) {
            // Do not return elements that are attached to a different flow-thread.
            if (node->renderer()->style() && !node->renderer()->style()->flowThread().isEmpty())
                continue;
            return node->renderer();
        }
        if (node->isContentElement()) {
            if (RenderObject* last = lastRendererOf(toHTMLContentElement(node)))
                return last;
        }
    }

    if (m_phase == AttachContentFallback)
        return NodeRenderingContext(m_node->parentNode()).previousRenderer();

    return 0;
}
Example #2
0
void DistributionPool::distributeTo(InsertionPoint* insertionPoint,
                                    ElementShadowV0* elementShadow) {
  DistributedNodes distributedNodes;

  for (size_t i = 0; i < m_nodes.size(); ++i) {
    if (m_distributed[i])
      continue;

    if (isHTMLContentElement(*insertionPoint) &&
        !toHTMLContentElement(insertionPoint)->canSelectNode(m_nodes, i))
      continue;

    Node* node = m_nodes[i];
    distributedNodes.append(node);
    elementShadow->didDistributeNode(node, insertionPoint);
    m_distributed[i] = true;
  }

  // Distributes fallback elements
  if (insertionPoint->isContentInsertionPoint() && distributedNodes.isEmpty()) {
    for (Node* fallbackNode = insertionPoint->firstChild(); fallbackNode;
         fallbackNode = fallbackNode->nextSibling()) {
      distributedNodes.append(fallbackNode);
      elementShadow->didDistributeNode(fallbackNode, insertionPoint);
    }
  }
  insertionPoint->setDistributedNodes(distributedNodes);
}
Element* HTMLDetailsElement::findMainSummary() const
{
    if (HTMLSummaryElement* summary = Traversal<HTMLSummaryElement>::firstChild(*this))
        return summary;

    HTMLContentElement* content = toHTMLContentElement(closedShadowRoot()->firstChild());
    ASSERT(content->firstChild() && isHTMLSummaryElement(*content->firstChild()));
    return toElement(content->firstChild());
}
Example #4
0
bool Internals::isValidContentSelect(Element* contentElement, ExceptionCode& ec)
{
    if (!contentElement || !contentElement->isContentElement()) {
        ec = INVALID_ACCESS_ERR;
        return false;
    }

    return toHTMLContentElement(contentElement)->isSelectValid();
}
Example #5
0
Element* HTMLDetailsElement::findMainSummary() const
{
    for (Element* child = ElementTraversal::firstWithin(*this); child; child = ElementTraversal::nextSibling(*child)) {
        if (child->hasTagName(summaryTag))
            return child;
    }

    HTMLContentElement* content = toHTMLContentElement(userAgentShadowRoot()->firstChild());
    ASSERT(content->firstChild() && content->firstChild()->hasTagName(summaryTag));
    return toElement(content->firstChild());
}
NodeRenderingContext::NodeRenderingContext(Node* node)
    : m_location(LocationNotInTree)
    , m_phase(AttachStraight)
    , m_node(node)
    , m_parentNodeForRenderingAndStyle(0)
    , m_visualParentShadowRoot(0)
    , m_includer(0)
    , m_style(0)
    , m_parentFlowRenderer(0)
{
    ContainerNode* parent = m_node->parentOrHostNode();
    if (!parent)
        return;

    if (parent->isShadowRoot()) {
        m_location = LocationShadowChild;
        m_parentNodeForRenderingAndStyle = parent->shadowHost();
        return;
    }

    m_location = LocationLightChild;

    if (parent->isElementNode()) {
        m_visualParentShadowRoot = toElement(parent)->shadowRoot();

        if (m_visualParentShadowRoot) {
            if ((m_includer = m_visualParentShadowRoot->includerFor(m_node))
                    && m_visualParentShadowRoot->isInclusionSelectorActive()) {
                m_phase = AttachContentForwarded;
                m_parentNodeForRenderingAndStyle = NodeRenderingContext(m_includer).parentNodeForRenderingAndStyle();
                return;
            }

            m_phase = AttachContentLight;
            m_parentNodeForRenderingAndStyle = parent;
            return;
        }

        if (parent->isContentElement()) {
            HTMLContentElement* shadowContentElement = toHTMLContentElement(parent);
            if (!shadowContentElement->hasInclusion()) {
                m_phase = AttachContentFallback;
                m_parentNodeForRenderingAndStyle = NodeRenderingContext(parent).parentNodeForRenderingAndStyle();
                return;
            }
        }
    }

    m_parentNodeForRenderingAndStyle = parent;
}
Example #7
0
void ElementShadow::collectSelectFeatureSetFrom(ShadowRoot& root)
{
    if (!root.containsShadowRoots() && !root.containsContentElements())
        return;

    for (Element& element : ElementTraversal::descendantsOf(root)) {
        if (ElementShadow* shadow = element.shadow())
            m_selectFeatures.add(shadow->ensureSelectFeatureSet());
        if (!isHTMLContentElement(element))
            continue;
        const CSSSelectorList& list = toHTMLContentElement(element).selectorList();
        m_selectFeatures.collectFeaturesFromSelectorList(list);
    }
}
Example #8
0
void ElementShadow::collectSelectFeatureSetFrom(ShadowRoot& root)
{
    if (!root.containsShadowRoots() && !root.containsContentElements())
        return;

    for (Element* element = ElementTraversal::firstWithin(root); element; element = ElementTraversal::next(*element, &root)) {
        if (ElementShadow* shadow = element->shadow())
            m_selectFeatures.add(shadow->ensureSelectFeatureSet());
        if (!isHTMLContentElement(*element))
            continue;
        const CSSSelectorList& list = toHTMLContentElement(*element).selectorList();
        for (const CSSSelector* selector = list.first(); selector; selector = CSSSelectorList::next(*selector)) {
            for (const CSSSelector* component = selector; component; component = component->tagHistory())
                m_selectFeatures.collectFeaturesFromSelector(*component);
        }
    }
}
RenderObject* NodeRenderingContext::nextRenderer() const
{
    ASSERT(m_node->renderer() || m_location != LocationUndetermined);
    if (RenderObject* renderer = m_node->renderer())
        return renderer->nextSibling();

    if (m_parentFlowRenderer)
        return m_parentFlowRenderer->nextRendererForNode(m_node);

    if (m_phase == AttachContentForwarded) {
        if (RenderObject* found = nextRendererOf(m_includer, m_node))
            return found;
        return NodeRenderingContext(m_includer).nextRenderer();
    }

    // Avoid an O(n^2) problem with this function by not checking for
    // nextRenderer() when the parent element hasn't attached yet.
    if (m_node->parentOrHostNode() && !m_node->parentOrHostNode()->attached() && m_phase != AttachContentFallback)
        return 0;

    for (Node* node = m_node->nextSibling(); node; node = node->nextSibling()) {
        if (node->renderer()) {
            // Do not return elements that are attached to a different flow-thread.
            if (node->renderer()->style() && !node->renderer()->style()->flowThread().isEmpty())
                continue;
            return node->renderer();
        }
        if (node->isContentElement()) {
            if (RenderObject* first = firstRendererOf(toHTMLContentElement(node)))
                return first;
        }
    }

    if (m_phase == AttachContentFallback)
        return NodeRenderingContext(m_node->parentNode()).nextRenderer();

    return 0;
}