Exemple #1
0
void TextTrackCue::copyWebVTTNodeToDOMTree(ContainerNode* webVTTNode, ContainerNode* parent)
{
    for (Node* node = webVTTNode->firstChild(); node; node = node->nextSibling()) {
        RefPtr<Node> clonedNode;
        if (node->isWebVTTElement())
            clonedNode = toWebVTTElement(node)->createEquivalentHTMLElement(ownerDocument());
        else
            clonedNode = node->cloneNode(false);
        parent->appendChild(clonedNode, ASSERT_NO_EXCEPTION);
        if (node->isContainerNode())
            copyWebVTTNodeToDOMTree(toContainerNode(node), toContainerNode(clonedNode.get()));
    }
}
Exemple #2
0
void VTTCue::copyVTTNodeToDOMTree(ContainerNode* vttNode, ContainerNode* parent)
{
    for (Node* node = vttNode->firstChild(); node; node = node->nextSibling()) {
        RefPtrWillBeRawPtr<Node> clonedNode;
        if (node->isVTTElement())
            clonedNode = toVTTElement(node)->createEquivalentHTMLElement(document());
        else
            clonedNode = node->cloneNode(false);
        parent->appendChild(clonedNode);
        if (node->isContainerNode())
            copyVTTNodeToDOMTree(toContainerNode(node), toContainerNode(clonedNode));
    }
}
Exemple #3
0
ContainerNode* LiveNodeListBase::rootContainerNode() const
{
    Node* rootNode = this->rootNode();
    if (!rootNode->isContainerNode())
        return 0;
    return toContainerNode(rootNode);
}
Exemple #4
0
Node& NodeTraversal::lastWithinOrSelf(Node& current) {
  Node* lastDescendant =
      current.isContainerNode()
          ? NodeTraversal::lastWithin(toContainerNode(current))
          : 0;
  return lastDescendant ? *lastDescendant : current;
}
ContainerNode* parent(const Node* node, ParentDetails* details)
{
    // FIXME: Once everything lazy attaches we should assert that we don't need a distribution recalc here.
    ComposedShadowTreeWalker walker(node, ComposedShadowTreeWalker::CrossUpperBoundary, ComposedShadowTreeWalker::CanStartFromShadowBoundary);
    ContainerNode* found = toContainerNode(walker.traverseParent(walker.get(), details));
    return details->outOfComposition() ? 0 : found;
}
void ComposedShadowTreeWalker::findParent(const Node* node, ParentTraversalDetails* details)
{
    ComposedShadowTreeWalker walker(node, CrossUpperBoundary, CanStartFromShadowBoundary);
    ContainerNode* found = toContainerNode(walker.traverseParent(walker.get(), details));
    if (found)
        details->didFindNode(found);
}
void MainThreadDebugger::querySelectorAllCallback(
    const v8::FunctionCallbackInfo<v8::Value>& info) {
  if (info.Length() < 1)
    return;
  String selector = toCoreStringWithUndefinedOrNullCheck(info[0]);
  if (selector.isEmpty())
    return;
  Node* node = secondArgumentAsNode(info);
  if (!node || !node->isContainerNode())
    return;
  ExceptionState exceptionState(ExceptionState::ExecutionContext, "$$",
                                "CommandLineAPI", info.Holder(),
                                info.GetIsolate());
  // toV8(elementList) doesn't work here, since we need a proper Array instance,
  // not NodeList.
  StaticElementList* elementList = toContainerNode(node)->querySelectorAll(
      AtomicString(selector), exceptionState);
  if (exceptionState.hadException() || !elementList)
    return;
  v8::Isolate* isolate = info.GetIsolate();
  v8::Local<v8::Context> context = isolate->GetCurrentContext();
  v8::Local<v8::Array> nodes = v8::Array::New(isolate, elementList->length());
  for (size_t i = 0; i < elementList->length(); ++i) {
    Element* element = elementList->item(i);
    if (!createDataPropertyInArray(
             context, nodes, i, toV8(element, info.Holder(), info.GetIsolate()))
             .FromMaybe(false))
      return;
  }
  info.GetReturnValue().Set(nodes);
}
void TreeBoundaryCrossingRules::collectTreeBoundaryCrossingRules(Element* element, ElementRuleCollector& collector, bool includeEmptyRules)
{
    if (m_treeBoundaryCrossingRuleSetMap.isEmpty())
        return;

    RuleRange ruleRange = collector.matchedResult().ranges.authorRuleRange();

    // When comparing rules declared in outer treescopes, outer's rules win.
    CascadeOrder outerCascadeOrder = size() + size();
    // When comparing rules declared in inner treescopes, inner's rules win.
    CascadeOrder innerCascadeOrder = size();

    for (DocumentOrderedList::iterator it = m_scopingNodes.begin(); it != m_scopingNodes.end(); ++it) {
        const ContainerNode* scopingNode = toContainerNode(*it);
        CSSStyleSheetRuleSubSet* ruleSubSet = m_treeBoundaryCrossingRuleSetMap.get(scopingNode);
        bool isInnerTreeScope = element->treeScope().isInclusiveAncestorOf(scopingNode->treeScope());

        CascadeOrder cascadeOrder = isInnerTreeScope ? innerCascadeOrder : outerCascadeOrder;
        for (CSSStyleSheetRuleSubSet::iterator it = ruleSubSet->begin(); it != ruleSubSet->end(); ++it) {
            CSSStyleSheet* parentStyleSheet = it->first;
            RuleSet* ruleSet = it->second.get();
            collector.collectMatchingRules(MatchRequest(ruleSet, includeEmptyRules, scopingNode, parentStyleSheet), ruleRange, SelectorChecker::ScopeContainsLastMatchedElement, ignoreCascadeScope, cascadeOrder);
        }
        ++innerCascadeOrder;
        --outerCascadeOrder;
    }
}
Exemple #9
0
void TextTrackCue::copyWebVTTNodeToDOMTree(ContainerNode* webVTTNode, ContainerNode* parent)
{
    for (Node* node = webVTTNode->firstChild(); node; node = node->nextSibling()) {
        RefPtr<Node> clonedNode;
        // Specs require voice and class WebVTT elements to be spans for DOM trees.
        if (node->hasTagName(voiceElementTagName()) || node->hasTagName(classElementTagName())) {
            clonedNode = HTMLSpanElement::create(spanTag, static_cast<Document*>(m_scriptExecutionContext));
            toElement(clonedNode.get())->setAttribute(classAttr, toElement(node)->getAttribute(classAttr));
            toElement(clonedNode.get())->setAttribute(titleAttr, toElement(node)->getAttribute(voiceAttributeName()));
        } else
            clonedNode = node->cloneNode(false);

        parent->appendChild(clonedNode, ASSERT_NO_EXCEPTION);
        if (node->isContainerNode())
            copyWebVTTNodeToDOMTree(toContainerNode(node), toContainerNode(clonedNode.get()));
    }
}
ContainerNode* parent(const Node* node, ParentDetails* details)
{
    // FIXME(morrita): We should ensure shadow tree distribution to be valid here through ContentDistributor::ensureDistribution().
    // Currently we rely on the caller side since doing it here is expensive.
    ComposedShadowTreeWalker walker(node, ComposedShadowTreeWalker::CrossUpperBoundary, ComposedShadowTreeWalker::CanStartFromShadowBoundary);
    ContainerNode* found = toContainerNode(walker.traverseParent(walker.get(), details));
    return details->outOfComposition() ? 0 : found;
}
ContainerNode* parent(const Node* node, ParentDetails* details)
{
    ASSERT(node);
    ASSERT(!node->document().childNeedsDistributionRecalc());
    if (isActiveInsertionPoint(*node))
        return 0;
    ComposedTreeWalker walker(node, ComposedTreeWalker::CanStartFromShadowBoundary);
    return toContainerNode(walker.traverseParent(walker.get(), details));
}
Exemple #12
0
WebElement WebNode::querySelector(const WebString& tag, WebExceptionCode& ec) const
{
    TrackExceptionState exceptionState;
    WebElement element;
    if (m_private->isContainerNode())
        element = toContainerNode(m_private.get())->querySelector(tag, exceptionState);
    ec = exceptionState.code();
    return element;
}
Exemple #13
0
DocumentFragment* createFragmentFromMarkupWithContext(
    Document& document,
    const String& markup,
    unsigned fragmentStart,
    unsigned fragmentEnd,
    const String& baseURL,
    ParserContentPolicy parserContentPolicy) {
  // FIXME: Need to handle the case where the markup already contains these
  // markers.

  StringBuilder taggedMarkup;
  taggedMarkup.append(markup.left(fragmentStart));
  MarkupFormatter::appendComment(taggedMarkup, fragmentMarkerTag);
  taggedMarkup.append(
      markup.substring(fragmentStart, fragmentEnd - fragmentStart));
  MarkupFormatter::appendComment(taggedMarkup, fragmentMarkerTag);
  taggedMarkup.append(markup.substring(fragmentEnd));

  DocumentFragment* taggedFragment = createFragmentFromMarkup(
      document, taggedMarkup.toString(), baseURL, parserContentPolicy);

  Comment* nodeBeforeContext = nullptr;
  Comment* nodeAfterContext = nullptr;
  if (!findNodesSurroundingContext(taggedFragment, nodeBeforeContext,
                                   nodeAfterContext))
    return nullptr;

  Document* taggedDocument = Document::create();
  taggedDocument->setContextFeatures(document.contextFeatures());

  Element* root = Element::create(QualifiedName::null(), taggedDocument);
  root->appendChild(taggedFragment);
  taggedDocument->appendChild(root);

  Range* range = Range::create(
      *taggedDocument,
      Position::afterNode(nodeBeforeContext).parentAnchoredEquivalent(),
      Position::beforeNode(nodeAfterContext).parentAnchoredEquivalent());

  Node* commonAncestor = range->commonAncestorContainer();
  HTMLElement* specialCommonAncestor =
      ancestorToRetainStructureAndAppearanceWithNoLayoutObject(commonAncestor);

  // When there's a special common ancestor outside of the fragment, we must
  // include it as well to preserve the structure and appearance of the
  // fragment. For example, if the fragment contains TD, we need to include the
  // enclosing TABLE tag as well.
  DocumentFragment* fragment = DocumentFragment::create(document);
  if (specialCommonAncestor)
    fragment->appendChild(specialCommonAncestor);
  else
    fragment->parserTakeAllChildrenFrom(toContainerNode(*commonAncestor));

  trimFragment(fragment, nodeBeforeContext, nodeAfterContext);

  return fragment;
}
Exemple #14
0
inline static void cloneChildNodesAvoidingDeleteButton(ContainerNode* parent, ContainerNode* clonedParent, HTMLElement* deleteButtonContainerElement)
{
    ExceptionCode ec = 0;
    for (Node* child = parent->firstChild(); child && !ec; child = child->nextSibling()) {

#if ENABLE(DELETION_UI)
        if (child == deleteButtonContainerElement)
            continue;
#else
        UNUSED_PARAM(deleteButtonContainerElement);
#endif

        RefPtr<Node> clonedChild = child->cloneNode(false);
        clonedParent->appendChild(clonedChild, ec);

        if (!ec && child->isContainerNode())
            cloneChildNodesAvoidingDeleteButton(toContainerNode(child), toContainerNode(clonedChild.get()), deleteButtonContainerElement);
    }
}
Exemple #15
0
static void willRemoveChild(Node* child)
{
    ASSERT(child->parentNode());
    ChildListMutationScope(child->parentNode()).willRemoveChild(child);
    child->notifyMutationObserversNodeWillDetach();
    dispatchChildRemovalEvents(child);
    child->document().nodeWillBeRemoved(child); // e.g. mutation event listener can create a new range.
    if (child->isContainerNode())
        ChildFrameDisconnector(toContainerNode(child)).disconnect();
}
Exemple #16
0
static void collectChildrenAndRemoveFromOldParent(Node* node, NodeVector& nodes, ExceptionCode& ec)
{
    if (node->nodeType() != Node::DOCUMENT_FRAGMENT_NODE) {
        nodes.append(node);
        if (ContainerNode* oldParent = node->parentNode())
            oldParent->removeChild(node, ec);
        return;
    }
    getChildNodes(node, nodes);
    toContainerNode(node)->removeChildren();
}
Exemple #17
0
static void collectChildrenAndRemoveFromOldParent(Node& node, NodeVector& nodes, ExceptionCode& ec)
{
    if (!node.isDocumentFragment()) {
        nodes.append(node);
        if (ContainerNode* oldParent = node.parentNode())
            oldParent->removeChild(&node, ec);
        return;
    }

    getChildNodes(node, nodes);
    toContainerNode(node).removeChildren();
}
Exemple #18
0
void InspectorNodeFinder::searchUsingCSSSelectors(Node* parentNode)
{
    if (!parentNode->isContainerNode())
        return;

    ExceptionCode ec = 0;
    RefPtr<NodeList> nodeList = toContainerNode(parentNode)->querySelectorAll(m_whitespaceTrimmedQuery, ec);
    if (ec || !nodeList)
        return;

    unsigned size = nodeList->length();
    for (unsigned i = 0; i < size; ++i)
        m_results.add(nodeList->item(i));
}
Exemple #19
0
void ContainerNode::willRemoveChild(Node& child)
{
    ASSERT(child.parentNode());

    ChildListMutationScope(*child.parentNode()).willRemoveChild(child);
    child.notifyMutationObserversNodeWillDetach();
    dispatchChildRemovalEvents(child);

    if (child.parentNode() != this)
        return;

    child.document().nodeWillBeRemoved(&child); // e.g. mutation event listener can create a new range.
    if (child.isContainerNode())
        disconnectSubframesIfNeeded(toContainerNode(child), RootAndDescendants);
}
void MainThreadDebugger::querySelectorCallback(const v8::FunctionCallbackInfo<v8::Value>& info)
{
    if (info.Length() < 1)
        return;
    String selector = toCoreStringWithUndefinedOrNullCheck(info[0]);
    if (selector.isEmpty())
        return;
    Node* node = secondArgumentAsNode(info);
    if (!node || !node->isContainerNode())
        return;
    ExceptionState exceptionState(ExceptionState::ExecutionContext, "$", "CommandLineAPI", info.Holder(), info.GetIsolate());
    Element* element = toContainerNode(node)->querySelector(AtomicString(selector), exceptionState);
    if (exceptionState.throwIfNeeded())
        return;
    if (element)
        info.GetReturnValue().Set(toV8(element, info.Holder(), info.GetIsolate()));
    else
        info.GetReturnValue().Set(v8::Null(info.GetIsolate()));
}
void RemoveNodePreservingChildrenCommand::doApply(EditingState* editingState) {
  ABORT_EDITING_COMMAND_IF(!m_node->parentNode());
  ABORT_EDITING_COMMAND_IF(!hasEditableStyle(*m_node->parentNode()));
  if (m_node->isContainerNode()) {
    NodeVector children;
    getChildNodes(toContainerNode(*m_node), children);

    for (auto& currentChild : children) {
      Node* child = currentChild.release();
      removeNode(child, editingState, m_shouldAssumeContentIsAlwaysEditable);
      if (editingState->isAborted())
        return;
      insertNodeBefore(child, m_node, editingState,
                       m_shouldAssumeContentIsAlwaysEditable);
      if (editingState->isAborted())
        return;
    }
  }
  removeNode(m_node, editingState, m_shouldAssumeContentIsAlwaysEditable);
}
void TreeBoundaryCrossingRules::collectTreeBoundaryCrossingRules(Element* element, ElementRuleCollector& collector, bool includeEmptyRules)
{
    if (m_treeBoundaryCrossingRuleSetMap.isEmpty())
        return;

    RuleRange ruleRange = collector.matchedResult().ranges.authorRuleRange();

    // When comparing rules declared in outer treescopes, outer's rules win.
    CascadeOrder outerCascadeOrder = size() + size();
    // When comparing rules declared in inner treescopes, inner's rules win.
    CascadeOrder innerCascadeOrder = size();

    for (DocumentOrderedList::iterator it = m_scopingNodes.begin(); it != m_scopingNodes.end(); ++it) {
        const ContainerNode* scopingNode = toContainerNode(*it);
        CSSStyleSheetRuleSubSet* ruleSubSet = m_treeBoundaryCrossingRuleSetMap.get(scopingNode);
        unsigned boundaryBehavior = SelectorChecker::ScopeContainsLastMatchedElement;
        bool isInnerTreeScope = element->treeScope().isInclusiveAncestorOf(scopingNode->treeScope());

        // If a given scoping node is a shadow root and a given element is in a descendant tree of tree hosted by
        // the scoping node's shadow host, we should use ScopeIsShadowHost.
        if (scopingNode && scopingNode->isShadowRoot()) {
            if (element->isInDescendantTreeOf(toShadowRoot(scopingNode)->host()))
                boundaryBehavior |= SelectorChecker::ScopeIsShadowHost;
            scopingNode = toShadowRoot(scopingNode)->host();
        }

        CascadeOrder cascadeOrder = isInnerTreeScope ? innerCascadeOrder : outerCascadeOrder;
        for (CSSStyleSheetRuleSubSet::iterator it = ruleSubSet->begin(); it != ruleSubSet->end(); ++it) {
            CSSStyleSheet* parentStyleSheet = it->first;
            RuleSet* ruleSet = it->second.get();
            collector.collectMatchingRules(MatchRequest(ruleSet, includeEmptyRules, scopingNode, parentStyleSheet), ruleRange, static_cast<SelectorChecker::BehaviorAtBoundary>(boundaryBehavior), ignoreCascadeScope, cascadeOrder);
        }
        ++innerCascadeOrder;
        --outerCascadeOrder;
    }
}
inline bool SelectorDataList::selectorMatches(const SelectorData& selectorData, Element* element, const Node* rootNode) const
{
    if (selectorData.isFastCheckable && !element->isSVGElement()) {
        SelectorCheckerFastPath selectorCheckerFastPath(selectorData.selector, element);
        if (!selectorCheckerFastPath.matchesRightmostSelector(SelectorChecker::VisitedMatchDisabled))
            return false;
        return selectorCheckerFastPath.matches();
    }

    SelectorChecker selectorChecker(element->document(), SelectorChecker::QueryingRules);
    SelectorChecker::SelectorCheckingContext selectorCheckingContext(selectorData.selector, element, SelectorChecker::VisitedMatchDisabled);
    selectorCheckingContext.behaviorAtBoundary = SelectorChecker::StaysWithinTreeScope;
    selectorCheckingContext.scope = !rootNode->isDocumentNode() && rootNode->isContainerNode() ? toContainerNode(rootNode) : 0;
    PseudoId ignoreDynamicPseudo = NOPSEUDO;
    return selectorChecker.match(selectorCheckingContext, ignoreDynamicPseudo) == SelectorChecker::SelectorMatches;
}
Exemple #24
0
Node* StyledMarkupAccumulator::traverseNodesForSerialization(Node* startNode, Node* pastEnd, NodeTraversalMode traversalMode)
{
    const bool shouldEmit = traversalMode == EmitString;
    Vector<RawPtr<ContainerNode> > ancestorsToClose;
    Node* next;
    Node* lastClosed = 0;
    for (Node* n = startNode; n != pastEnd; n = next) {
        // According to <rdar://problem/5730668>, it is possible for n to blow
        // past pastEnd and become null here. This shouldn't be possible.
        // This null check will prevent crashes (but create too much markup)
        // and the ASSERT will hopefully lead us to understanding the problem.
        ASSERT(n);
        if (!n)
            break;

        next = NodeTraversal::next(*n);
        bool openedTag = false;

        if (isBlock(n) && canHaveChildrenForEditing(n) && next == pastEnd)
            // Don't write out empty block containers that aren't fully selected.
            continue;

        if (!n->renderer() && m_shouldAnnotate != AnnotateForNavigationTransition) {
            next = NodeTraversal::nextSkippingChildren(*n);
            // Don't skip over pastEnd.
            if (pastEnd && pastEnd->isDescendantOf(n))
                next = pastEnd;
        } else {
            // Add the node to the markup if we're not skipping the descendants
            if (shouldEmit)
                appendStartTag(*n);

            // If node has no children, close the tag now.
            if (n->isContainerNode() && toContainerNode(n)->hasChildren()) {
                openedTag = true;
                ancestorsToClose.append(toContainerNode(n));
            } else {
                if (shouldEmit && n->isElementNode())
                    appendEndTag(toElement(*n));
                lastClosed = n;
            }
        }

        // If we didn't insert open tag and there's no more siblings or we're at the end of the traversal, take care of ancestors.
        // FIXME: What happens if we just inserted open tag and reached the end?
        if (!openedTag && (!n->nextSibling() || next == pastEnd)) {
            // Close up the ancestors.
            while (!ancestorsToClose.isEmpty()) {
                ContainerNode* ancestor = ancestorsToClose.last();
                ASSERT(ancestor);
                if (next != pastEnd && next->isDescendantOf(ancestor))
                    break;
                // Not at the end of the range, close ancestors up to sibling of next node.
                if (shouldEmit && ancestor->isElementNode())
                    appendEndTag(toElement(*ancestor));
                lastClosed = ancestor;
                ancestorsToClose.removeLast();
            }

            // Surround the currently accumulated markup with markup for ancestors we never opened as we leave the subtree(s) rooted at those ancestors.
            ContainerNode* nextParent = next ? next->parentNode() : 0;
            if (next != pastEnd && n != nextParent) {
                Node* lastAncestorClosedOrSelf = n->isDescendantOf(lastClosed) ? lastClosed : n;
                for (ContainerNode* parent = lastAncestorClosedOrSelf->parentNode(); parent && parent != nextParent; parent = parent->parentNode()) {
                    // All ancestors that aren't in the ancestorsToClose list should either be a) unrendered:
                    if (!parent->renderer())
                        continue;
                    // or b) ancestors that we never encountered during a pre-order traversal starting at startNode:
                    ASSERT(startNode->isDescendantOf(parent));
                    if (shouldEmit)
                        wrapWithNode(*parent);
                    lastClosed = parent;
                }
            }
        }
    }

    return lastClosed;
}
ContainerNode* parentSlow(const Node* node, ParentDetails* details)
{
    ComposedShadowTreeWalker walker(node, ComposedShadowTreeWalker::CrossUpperBoundary, ComposedShadowTreeWalker::CanStartFromShadowBoundary);
    ContainerNode* found = toContainerNode(walker.traverseParent(walker.get(), details));
    return details->outOfComposition() ? 0 : found;
}