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())); } }
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)); } }
ContainerNode* LiveNodeListBase::rootContainerNode() const { Node* rootNode = this->rootNode(); if (!rootNode->isContainerNode()) return 0; return toContainerNode(rootNode); }
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; } }
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)); }
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; }
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; }
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); } }
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(); }
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(); }
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(); }
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)); }
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; }
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; }