static ContainerNode* traverseParent(const Node* node, ShadowRootCrossing shadowRootCrossing) { if (node->isPseudoElement()) return toPseudoElement(node)->hostElement(); if (shadowRootCrossing == DontCrossShadowRoot && node->isShadowRoot()) return 0; if (nodeCanBeDistributed(node)) { if (InsertionPoint* insertionPoint = findInsertionPointOf(node)) return traverseParent(insertionPoint, shadowRootCrossing); return nullptr; } ContainerNode* parent = node->parentNode(); if (!parent) return nullptr; if (parent->isShadowRoot()) return shadowRootCrossing == CrossShadowRoot ? toShadowRoot(parent)->hostElement() : parent; if (parent->isInsertionPoint()) { const InsertionPoint* insertionPoint = toInsertionPoint(parent); if (insertionPoint->hasDistribution()) return nullptr; if (insertionPoint->isActive()) return traverseParent(parent, shadowRootCrossing); } return parent; }
inline EventTarget& eventTargetRespectingTargetRules(Node& referenceNode) { if (referenceNode.isPseudoElement()) { EventTarget* hostElement = toPseudoElement(referenceNode).hostElement(); ASSERT(hostElement); return *hostElement; } #if ENABLE(SVG) if (!referenceNode.isSVGElement() || !referenceNode.isInShadowTree()) return referenceNode; // Spec: The event handling for the non-exposed tree works as if the referenced element had been textually included // as a deeply cloned child of the 'use' element, except that events are dispatched to the SVGElementInstance objects Node* rootNode = referenceNode.treeScope().rootNode(); Element* shadowHostElement = rootNode->isShadowRoot() ? toShadowRoot(rootNode)->hostElement() : 0; // At this time, SVG nodes are not supported in non-<use> shadow trees. if (!shadowHostElement || !shadowHostElement->hasTagName(SVGNames::useTag)) return referenceNode; SVGUseElement* useElement = toSVGUseElement(shadowHostElement); if (SVGElementInstance* instance = useElement->instanceForShadowTreeElement(&referenceNode)) return *instance; #endif return referenceNode; }
PassRefPtr<TypeBuilder::LayerTree::Layer> InspectorLayerTreeAgent::buildObjectForLayer(ErrorString* errorString, RenderLayer* renderLayer) { RenderObject* renderer = &renderLayer->renderer(); RenderLayerBacking* backing = renderLayer->backing(); Node* node = renderer->node(); bool isReflection = renderLayer->isReflection(); bool isGenerated = (isReflection ? renderer->parent() : renderer)->isBeforeOrAfterContent(); bool isAnonymous = renderer->isAnonymous(); if (renderer->isRenderView()) node = &renderer->document(); else if (isReflection && isGenerated) node = renderer->parent()->generatingElement(); else if (isGenerated) node = renderer->generatingNode(); else if (isReflection || isAnonymous) node = renderer->parent()->element(); // Basic set of properties. RefPtr<TypeBuilder::LayerTree::Layer> layerObject = TypeBuilder::LayerTree::Layer::create() .setLayerId(bind(renderLayer)) .setNodeId(idForNode(errorString, node)) .setBounds(buildObjectForIntRect(renderer->absoluteBoundingBoxRect())) .setMemory(backing->backingStoreMemoryEstimate()) .setCompositedBounds(buildObjectForIntRect(enclosingIntRect(backing->compositedBounds()))) .setPaintCount(backing->graphicsLayer()->repaintCount()); if (node && node->shadowHost()) layerObject->setIsInShadowTree(true); if (isReflection) layerObject->setIsReflection(true); if (isGenerated) { if (isReflection) renderer = renderer->parent(); layerObject->setIsGeneratedContent(true); layerObject->setPseudoElementId(bindPseudoElement(toPseudoElement(renderer->node()))); if (renderer->isBeforeContent()) layerObject->setPseudoElement("before"); else if (renderer->isAfterContent()) layerObject->setPseudoElement("after"); } // FIXME: RenderView is now really anonymous but don't tell about it to the frontend before making sure it can handle it. if (isAnonymous && !renderer->isRenderView()) { layerObject->setIsAnonymous(true); if (RenderStyle* style = renderer->style()) { if (style->styleType() == FIRST_LETTER) layerObject->setPseudoElement("first-letter"); else if (style->styleType() == FIRST_LINE) layerObject->setPseudoElement("first-line"); } } return layerObject; }
ContainerNode* parent(const Node& node, ParentDetails* details) { // TODO(hayato): Uncomment this once we can be sure // LayoutTreeBuilderTraversal::parent() is used only for a node which is // connected. // DCHECK(node.isConnected()); if (node.isPseudoElement()) { assertPseudoElementParent(toPseudoElement(node)); return node.parentNode(); } return FlatTreeTraversal::parent(node, details); }
Node* previousSibling(const Node& node) { if (node.isAfterPseudoElement()) { assertPseudoElementParent(toPseudoElement(node)); if (Node* previous = FlatTreeTraversal::lastChild(*node.parentNode())) return previous; } else { if (node.isBeforePseudoElement()) return nullptr; if (Node* previous = FlatTreeTraversal::previousSibling(node)) return previous; } Node* parent = FlatTreeTraversal::parent(node); if (parent && parent->isElementNode()) return toElement(parent)->pseudoElement(PseudoIdBefore); return nullptr; }
// FIXME: Use an iterative algorithm so that it can be inlined. // https://bugs.webkit.org/show_bug.cgi?id=90415 Node* ComposedShadowTreeWalker::traverseParent(const Node* node, ParentTraversalDetails* details) const { if (node->isPseudoElement()) return toPseudoElement(node)->hostElement(); if (!canCrossUpperBoundary() && node->isShadowRoot()) return 0; if (nodeCanBeDistributed(node)) { if (InsertionPoint* insertionPoint = resolveReprojection(node)) { if (details) details->didTraverseInsertionPoint(insertionPoint); return traverseParent(insertionPoint, details); } // The node is a non-distributed light child or older shadow's child. if (details) details->childWasOutOfComposition(); } return traverseParentInCurrentTree(node, details); }
static Node* nodeOrHostIfPseudoElement(Node* node) { return node->isPseudoElement() ? toPseudoElement(node)->hostElement() : node; }
static inline Element* parentOrPseudoHostElement(const RenderObject* object) { if (object->node()->isPseudoElement()) return toPseudoElement(object->node())->hostElement(); return toElement(object->node())->parentElement(); }