void TreeScope::setParentTreeScope(TreeScope& newParentScope) { // A document node cannot be re-parented. ASSERT(!rootNode().isDocumentNode()); newParentScope.guardRef(); if (m_parentTreeScope) m_parentTreeScope->guardDeref(); m_parentTreeScope = &newParentScope; setDocument(newParentScope.document()); }
RelatedNodeRetargeter::RelatedNodeRetargeter(Node& relatedNode, Node& target) : m_relatedNode(relatedNode) , m_retargetedRelatedNode(&relatedNode) { auto& targetTreeScope = target.treeScope(); TreeScope* currentTreeScope = &m_relatedNode.treeScope(); if (LIKELY(currentTreeScope == &targetTreeScope && target.inDocument() && m_relatedNode.inDocument())) return; if (¤tTreeScope->documentScope() != &targetTreeScope.documentScope()) { m_hasDifferentTreeRoot = true; m_retargetedRelatedNode = nullptr; return; } if (relatedNode.inDocument() != target.inDocument()) { m_hasDifferentTreeRoot = true; m_retargetedRelatedNode = moveOutOfAllShadowRoots(relatedNode); return; } collectTreeScopes(); // FIXME: We should collect this while constructing the event path. Vector<TreeScope*, 8> targetTreeScopeAncestors; for (TreeScope* currentTreeScope = &targetTreeScope; currentTreeScope; currentTreeScope = currentTreeScope->parentTreeScope()) targetTreeScopeAncestors.append(currentTreeScope); ASSERT_WITH_SECURITY_IMPLICATION(!targetTreeScopeAncestors.isEmpty()); unsigned i = m_ancestorTreeScopes.size(); unsigned j = targetTreeScopeAncestors.size(); ASSERT_WITH_SECURITY_IMPLICATION(m_ancestorTreeScopes.last() == targetTreeScopeAncestors.last()); while (m_ancestorTreeScopes[i - 1] == targetTreeScopeAncestors[j - 1]) { i--; j--; if (!i || !j) break; } bool lowestCommonAncestorIsDocumentScope = i + 1 == m_ancestorTreeScopes.size(); if (lowestCommonAncestorIsDocumentScope && !relatedNode.inDocument() && !target.inDocument()) { Node& targetAncestorInDocumentScope = i ? *downcast<ShadowRoot>(m_ancestorTreeScopes[i - 1]->rootNode()).shadowHost() : target; Node& relatedNodeAncestorInDocumentScope = j ? *downcast<ShadowRoot>(targetTreeScopeAncestors[j - 1]->rootNode()).shadowHost() : relatedNode; if (targetAncestorInDocumentScope.rootNode() != relatedNodeAncestorInDocumentScope.rootNode()) { m_hasDifferentTreeRoot = true; m_retargetedRelatedNode = moveOutOfAllShadowRoots(relatedNode); return; } } m_lowestCommonAncestorIndex = i; m_retargetedRelatedNode = nodeInLowestCommonAncestor(); }
void HTMLLabelElement::updateLabel(TreeScope& scope, const AtomicString& oldForAttributeValue, const AtomicString& newForAttributeValue) { if (!inDocument()) return; if (oldForAttributeValue == newForAttributeValue) return; if (!oldForAttributeValue.isEmpty()) scope.removeLabel(oldForAttributeValue, this); if (!newForAttributeValue.isEmpty()) scope.addLabel(newForAttributeValue, this); }
void DocumentOrderedMap::add(const AtomicStringImpl& key, Element& element, const TreeScope& treeScope) { ASSERT_WITH_SECURITY_IMPLICATION(element.isInTreeScope()); ASSERT_WITH_SECURITY_IMPLICATION(treeScope.rootNode()->containsIncludingShadowDOM(&element)); if (!element.isInTreeScope() || &element.document() != treeScope.documentScope()) return; Map::AddResult addResult = m_map.add(&key, MapEntry(&element)); if (addResult.isNewEntry) return; MapEntry& entry = addResult.iterator->value; ASSERT_WITH_SECURITY_IMPLICATION(entry.count); entry.element = 0; entry.count++; entry.orderedList.clear(); }
void RelatedNodeRetargeter::moveToNewTreeScope(TreeScope* previousTreeScope, TreeScope& newTreeScope) { if (m_hasDifferentTreeRoot) return; auto& currentRelatedNodeScope = m_retargetedRelatedNode->treeScope(); if (previousTreeScope != ¤tRelatedNodeScope) { // currentRelatedNode is still outside our shadow tree. New tree scope may contain currentRelatedNode // but there is no need to re-target it. Moving into a slot (thereby a deeper shadow tree) doesn't matter. return; } bool enteredSlot = newTreeScope.parentTreeScope() == previousTreeScope; if (enteredSlot) { if (m_lowestCommonAncestorIndex) { if (m_ancestorTreeScopes.isEmpty()) collectTreeScopes(); bool relatedNodeIsInSlot = m_ancestorTreeScopes[m_lowestCommonAncestorIndex - 1] == &newTreeScope; if (relatedNodeIsInSlot) { m_lowestCommonAncestorIndex--; m_retargetedRelatedNode = nodeInLowestCommonAncestor(); ASSERT(&newTreeScope == &m_retargetedRelatedNode->treeScope()); } } else ASSERT(m_retargetedRelatedNode == &m_relatedNode); } else { ASSERT(previousTreeScope->parentTreeScope() == &newTreeScope); m_lowestCommonAncestorIndex++; ASSERT_WITH_SECURITY_IMPLICATION(m_ancestorTreeScopes.isEmpty() || m_lowestCommonAncestorIndex < m_ancestorTreeScopes.size()); m_retargetedRelatedNode = downcast<ShadowRoot>(currentRelatedNodeScope.rootNode()).host(); ASSERT(&newTreeScope == &m_retargetedRelatedNode->treeScope()); } }
void RelatedNodeRetargeter::collectTreeScopes() { ASSERT(m_ancestorTreeScopes.isEmpty()); for (TreeScope* currentTreeScope = &m_relatedNode.treeScope(); currentTreeScope; currentTreeScope = currentTreeScope->parentTreeScope()) m_ancestorTreeScopes.append(currentTreeScope); ASSERT_WITH_SECURITY_IMPLICATION(!m_ancestorTreeScopes.isEmpty()); }
void TreeScope::setParentTreeScope(TreeScope& newParentScope) { // A document node cannot be re-parented. DCHECK(!rootNode().isDocumentNode()); m_parentTreeScope = &newParentScope; setDocument(newParentScope.document()); }
void DocumentOrderedMap::add(const AtomicStringImpl& key, Element& element, const TreeScope& treeScope) { UNUSED_PARAM(treeScope); ASSERT_WITH_SECURITY_IMPLICATION(element.isInTreeScope()); ASSERT_WITH_SECURITY_IMPLICATION(treeScope.rootNode().containsIncludingShadowDOM(&element)); if (!element.isInTreeScope()) return; Map::AddResult addResult = m_map.ensure(&key, [&element] { return MapEntry(&element); }); MapEntry& entry = addResult.iterator->value; #if !ASSERT_DISABLED || ENABLE(SECURITY_ASSERTIONS) ASSERT_WITH_SECURITY_IMPLICATION(!entry.registeredElements.contains(&element)); entry.registeredElements.add(&element); #endif if (addResult.isNewEntry) return; ASSERT_WITH_SECURITY_IMPLICATION(entry.count); entry.element = nullptr; entry.count++; entry.orderedList.clear(); }
static Position adjustPositionForStart(const Position& currentPosition, Node* endContainerNode) { TreeScope* treeScope = endContainerNode->treeScope(); ASSERT(currentPosition.containerNode()->treeScope() != treeScope); if (Node* ancestor = treeScope->ancestorInThisScope(currentPosition.containerNode())) { if (ancestor->contains(endContainerNode)) return positionBeforeNode(ancestor); return positionAfterNode(ancestor); } if (Node* firstChild = treeScope->rootNode()->firstChild()) return positionBeforeNode(firstChild); return Position(); }
TreeScopeEventContext::TreeScopeEventContext(TreeScope& treeScope) : m_treeScope(treeScope) , m_rootNode(treeScope.rootNode()) , m_containingClosedShadowTree(nullptr) , m_preOrder(-1) , m_postOrder(-1) { }
AtomicString SVGURIReference::fragmentIdentifierFromIRIString( const String& urlString, const TreeScope& treeScope) { SVGURLReferenceResolver resolver(urlString, treeScope.document()); if (!resolver.isLocal()) return emptyAtom; return resolver.fragmentIdentifier(); }
void InsertionPoint::attach() { TreeScope* scope = treeScope(); if (scope->isShadowRoot()) { ShadowRoot* root = toShadowRoot(scope); if (doesSelectFromHostChildren()) { distributeHostChildren(root->tree()); attachDistributedNode(); } else if (!root->olderShadowRoot()->assignedTo()) { ASSERT(!root->olderShadowRoot()->attached()); assignShadowRoot(root->olderShadowRoot()); root->olderShadowRoot()->attach(); } } HTMLElement::attach(); }
EventTarget* EventPath::findRelatedNode(TreeScope& scope, RelatedTargetMap& relatedTargetMap) { WillBeHeapVector<RawPtrWillBeMember<TreeScope>, 32> parentTreeScopes; EventTarget* relatedNode = 0; for (TreeScope* current = &scope; current; current = current->olderShadowRootOrParentTreeScope()) { parentTreeScopes.append(current); RelatedTargetMap::const_iterator iter = relatedTargetMap.find(current); if (iter != relatedTargetMap.end() && iter->value) { relatedNode = iter->value; break; } } ASSERT(relatedNode); for (WillBeHeapVector<RawPtrWillBeMember<TreeScope>, 32>::iterator iter = parentTreeScopes.begin(); iter < parentTreeScopes.end(); ++iter) relatedTargetMap.add(*iter, relatedNode); return relatedNode; }
void TreeScope::setParentTreeScope(TreeScope& newParentScope) { // A document node cannot be re-parented. ASSERT(!m_rootNode.isDocumentNode()); m_parentTreeScope = &newParentScope; setDocumentScope(newParentScope.documentScope()); }
void ElementRuleCollector::collectMatchingRules(const MatchRequest& matchRequest, StyleResolver::RuleRange& ruleRange) { ASSERT(matchRequest.ruleSet); ASSERT(m_state.element()); const StyleResolver::State& state = m_state; Element* element = state.element(); const StyledElement* styledElement = state.styledElement(); const AtomicString& pseudoId = element->shadowPseudoId(); if (!pseudoId.isEmpty()) { ASSERT(styledElement); collectMatchingRulesForList(matchRequest.ruleSet->shadowPseudoElementRules(pseudoId.impl()), matchRequest, ruleRange); } #if ENABLE(VIDEO_TRACK) if (element->isWebVTTElement()) collectMatchingRulesForList(matchRequest.ruleSet->cuePseudoRules(), matchRequest, ruleRange); #endif // Check whether other types of rules are applicable in the current tree scope. Criteria for this: // a) it's a UA rule // b) the tree scope allows author rules // c) the rules comes from a scoped style sheet within the same tree scope TreeScope* treeScope = element->treeScope(); if (!MatchingUARulesScope::isMatchingUARules() && !treeScope->applyAuthorStyles() && (!matchRequest.scope || matchRequest.scope->treeScope() != treeScope) && m_behaviorAtBoundary == SelectorChecker::DoesNotCrossBoundary) return; // We need to collect the rules for id, class, tag, and everything else into a buffer and // then sort the buffer. if (element->hasID()) collectMatchingRulesForList(matchRequest.ruleSet->idRules(element->idForStyleResolution().impl()), matchRequest, ruleRange); if (styledElement && styledElement->hasClass()) { for (size_t i = 0; i < styledElement->classNames().size(); ++i) collectMatchingRulesForList(matchRequest.ruleSet->classRules(styledElement->classNames()[i].impl()), matchRequest, ruleRange); } if (element->isLink()) collectMatchingRulesForList(matchRequest.ruleSet->linkPseudoClassRules(), matchRequest, ruleRange); if (SelectorChecker::matchesFocusPseudoClass(element)) collectMatchingRulesForList(matchRequest.ruleSet->focusPseudoClassRules(), matchRequest, ruleRange); collectMatchingRulesForList(matchRequest.ruleSet->tagRules(element->localName().impl()), matchRequest, ruleRange); collectMatchingRulesForList(matchRequest.ruleSet->universalRules(), matchRequest, ruleRange); }
Element* TreeScope::focusedElement() { Document& document = m_rootNode.document(); Element* element = document.focusedElement(); if (!element && document.page()) element = focusedFrameOwnerElement(document.page()->focusController().focusedFrame(), document.frame()); if (!element) return nullptr; TreeScope* treeScope = &element->treeScope(); while (treeScope != this && treeScope != &document) { element = downcast<ShadowRoot>(treeScope->rootNode()).host(); treeScope = &element->treeScope(); } if (this != treeScope) return nullptr; return element; }
Element* TreeScope::focusedElement() { Document* document = rootNode()->document(); Element* element = document->focusedElement(); if (!element && document->page()) element = focusedFrameOwnerElement(document->page()->focusController().focusedFrame(), document->frame()); if (!element) return 0; TreeScope* treeScope = element->treeScope(); while (treeScope != this && treeScope != document) { element = toShadowRoot(treeScope->rootNode())->hostElement(); treeScope = element->treeScope(); } if (this != treeScope) return 0; return element; }
RelatedNodeRetargeter(Node& relatedNode, TreeScope& targetTreeScope) : m_relatedNode(relatedNode) , m_retargetedRelatedNode(&relatedNode) { TreeScope* currentTreeScope = &m_relatedNode.treeScope(); if (LIKELY(currentTreeScope == &targetTreeScope)) return; if (¤tTreeScope->documentScope() != &targetTreeScope.documentScope()) { m_hasDifferentTreeRoot = true; m_retargetedRelatedNode = nullptr; return; } if (relatedNode.inDocument() != targetTreeScope.rootNode().inDocument()) { m_hasDifferentTreeRoot = true; while (m_retargetedRelatedNode->isInShadowTree()) m_retargetedRelatedNode = downcast<ShadowRoot>(m_retargetedRelatedNode->treeScope().rootNode()).host(); return; } collectTreeScopes(); // FIXME: We should collect this while constructing the event path. Vector<TreeScope*, 8> targetTreeScopeAncestors; for (TreeScope* currentTreeScope = &targetTreeScope; currentTreeScope; currentTreeScope = currentTreeScope->parentTreeScope()) targetTreeScopeAncestors.append(currentTreeScope); ASSERT_WITH_SECURITY_IMPLICATION(!targetTreeScopeAncestors.isEmpty()); unsigned i = m_ancestorTreeScopes.size(); unsigned j = targetTreeScopeAncestors.size(); ASSERT_WITH_SECURITY_IMPLICATION(m_ancestorTreeScopes.last() == targetTreeScopeAncestors.last()); while (m_ancestorTreeScopes[i - 1] == targetTreeScopeAncestors[j - 1]) { i--; j--; if (!i || !j) break; } m_lowestCommonAncestorIndex = i; m_retargetedRelatedNode = nodeInLowestCommonAncestor(); }
AtomicString SVGURIReference::fragmentIdentifierFromIRIString(const String& url, const TreeScope& treeScope) { size_t start = url.find('#'); if (start == kNotFound) return emptyAtom; const Document& document = treeScope.document(); KURL base = start ? KURL(document.baseURI(), url.substring(0, start)) : document.baseURI(); if (equalIgnoringFragmentIdentifier(base, document.url())) return AtomicString(url.substring(start + 1)); return emptyAtom; }
void StyleEngine::updateActiveStyleSheets(StyleResolverUpdateMode updateMode) { ASSERT(isMaster()); ASSERT(!document().inStyleRecalc()); if (!document().isActive()) return; if (shouldUpdateDocumentStyleSheetCollection(updateMode)) documentStyleSheetCollection()->updateActiveStyleSheets(this, updateMode); if (shouldUpdateShadowTreeStyleSheetCollection(updateMode)) { TreeScopeSet treeScopes = updateMode == FullStyleUpdate ? m_activeTreeScopes : m_dirtyTreeScopes; HashSet<TreeScope*> treeScopesRemoved; for (TreeScopeSet::iterator it = treeScopes.begin(); it != treeScopes.end(); ++it) { TreeScope* treeScope = *it; ASSERT(treeScope != m_document); ShadowTreeStyleSheetCollection* collection = static_cast<ShadowTreeStyleSheetCollection*>(styleSheetCollectionFor(*treeScope)); ASSERT(collection); collection->updateActiveStyleSheets(this, updateMode); if (!collection->hasStyleSheetCandidateNodes()) { treeScopesRemoved.add(treeScope); // When removing TreeScope from ActiveTreeScopes, // its resolver should be destroyed by invoking resetAuthorStyle. ASSERT(!treeScope->scopedStyleResolver()); } } m_activeTreeScopes.removeAll(treeScopesRemoved); } InspectorInstrumentation::activeStyleSheetsUpdated(m_document); m_usesRemUnits = documentStyleSheetCollection()->usesRemUnits(); m_dirtyTreeScopes.clear(); m_documentScopeDirty = false; }
Node* moveToParentOrShadowHost(Node& newTarget) { TreeScope& newTreeScope = newTarget.treeScope(); if (&newTreeScope == m_currentTreeScope) return m_relatedNodeInCurrentTreeScope; if (m_currentTreeScope) { ASSERT(is<ShadowRoot>(m_currentTreeScope->rootNode())); ASSERT(&newTarget == downcast<ShadowRoot>(m_currentTreeScope->rootNode()).host()); ASSERT(m_currentTreeScope->parentTreeScope() == &newTreeScope); } if (&newTreeScope == &m_relatedNodeTreeScope) m_relatedNodeInCurrentTreeScope = &m_relatedNode; else if (m_relatedNodeInCurrentTreeScope) { ASSERT(m_currentTreeScope); m_relatedNodeInCurrentTreeScope = &newTarget; } else { if (!m_currentTreeScope) { TreeScope* newTreeScopeAncestor = &newTreeScope; do { m_relatedNodeInCurrentTreeScope = findHostOfTreeScopeInTargetTreeScope(m_relatedNodeTreeScope, *newTreeScopeAncestor); newTreeScopeAncestor = newTreeScopeAncestor->parentTreeScope(); if (newTreeScopeAncestor == &m_relatedNodeTreeScope) { m_relatedNodeInCurrentTreeScope = &m_relatedNode; break; } } while (newTreeScopeAncestor && !m_relatedNodeInCurrentTreeScope); } ASSERT(m_relatedNodeInCurrentTreeScope || findHostOfTreeScopeInTargetTreeScope(newTreeScope, m_relatedNodeTreeScope) || &newTreeScope.documentScope() != &m_relatedNodeTreeScope.documentScope()); } m_currentTreeScope = &newTreeScope; return m_relatedNodeInCurrentTreeScope; }
void ScopedStyleResolver::keyframesRulesAdded(const TreeScope& treeScope) { // Called when @keyframes rules are about to be added/removed from a // TreeScope. @keyframes rules may apply to animations on elements in the // same TreeScope as the stylesheet, or the host element in the parent // TreeScope if the TreeScope is a shadow tree. ScopedStyleResolver* resolver = treeScope.scopedStyleResolver(); ScopedStyleResolver* parentResolver = treeScope.parentTreeScope() ? treeScope.parentTreeScope()->scopedStyleResolver() : nullptr; bool hadUnresolvedKeyframes = false; if (resolver && resolver->m_hasUnresolvedKeyframesRule) { resolver->m_hasUnresolvedKeyframesRule = false; hadUnresolvedKeyframes = true; } if (parentResolver && parentResolver->m_hasUnresolvedKeyframesRule) { parentResolver->m_hasUnresolvedKeyframesRule = false; hadUnresolvedKeyframes = true; } if (hadUnresolvedKeyframes) { // If an animation ended up not being started because no @keyframes // rules were found for the animation-name, we need to recalculate style // for the elements in the scope, including its shadow host if // applicable. invalidationRootForTreeScope(treeScope).setNeedsStyleRecalc( SubtreeStyleChange, StyleChangeReasonForTracing::create( StyleChangeReason::StyleSheetChange)); return; } // If we have animations running, added/removed @keyframes may affect these. treeScope.document().timeline().invalidateKeyframeEffects(treeScope); }
static inline KURL urlFromIRIStringWithFragmentIdentifier(const String& url, const TreeScope& treeScope, AtomicString& fragmentIdentifier) { size_t startOfFragmentIdentifier = url.find('#'); if (startOfFragmentIdentifier == kNotFound) return KURL(); const Document& document = treeScope.document(); // Exclude the '#' character when determining the fragmentIdentifier. fragmentIdentifier = AtomicString(url.substring(startOfFragmentIdentifier + 1)); if (startOfFragmentIdentifier) { KURL base(document.baseURI(), url.substring(0, startOfFragmentIdentifier)); return KURL(base, url.substring(startOfFragmentIdentifier)); } return KURL(document.baseURI(), url.substring(startOfFragmentIdentifier)); }
Node* HTMLCollection::namedItem(const AtomicString& name) const { // http://msdn.microsoft.com/workshop/author/dhtml/reference/methods/nameditem.asp // This method first searches for an object with a matching id // attribute. If a match is not found, the method then searches for an // object with a matching name attribute, but only on those elements // that are allowed a name attribute. ContainerNode* root = rootContainerNode(); if (name.isEmpty() || !root) return 0; if (!overridesItemAfter() && root->isInTreeScope()) { TreeScope* treeScope = root->treeScope(); Element* candidate = 0; if (treeScope->hasElementWithId(name.impl())) { if (!treeScope->containsMultipleElementsWithId(name)) candidate = treeScope->getElementById(name); } else if (treeScope->hasElementWithName(name.impl())) { if (!treeScope->containsMultipleElementsWithName(name)) { candidate = treeScope->getElementByName(name); if (candidate && type() == DocAll && (!candidate->isHTMLElement() || !nameShouldBeVisibleInDocumentAll(toHTMLElement(candidate)))) candidate = 0; } } else return 0; if (candidate && isMatchingElement(this, candidate) && (shouldOnlyIncludeDirectChildren() ? candidate->parentNode() == root : candidate->isDescendantOf(root))) return candidate; } // The pathological case. We need to walk the entire subtree. updateNameCache(); if (Vector<Element*>* idResults = idCache(name)) { if (idResults->size()) return idResults->at(0); } if (Vector<Element*>* nameResults = nameCache(name)) { if (nameResults->size()) return nameResults->at(0); } return 0; }
PassRefPtrWillBeRawPtr<ShadowRoot> createShadowRootForElementWithIDAndSetInnerHTML(TreeScope& scope, const char* hostElementID, const char* shadowRootContent) { RefPtrWillBeRawPtr<ShadowRoot> shadowRoot = scope.getElementById(AtomicString::fromUTF8(hostElementID))->createShadowRoot(ASSERT_NO_EXCEPTION); shadowRoot->setInnerHTML(String::fromUTF8(shadowRootContent), ASSERT_NO_EXCEPTION); return shadowRoot.release(); }
DocumentStyleSheetCollection::DocumentStyleSheetCollection(TreeScope& treeScope) : TreeScopeStyleSheetCollection(treeScope) { ASSERT(treeScope.rootNode() == treeScope.rootNode().document()); }
PassRefPtr<FilterEffect> ReferenceFilterBuilder::build(Filter* parentFilter, RenderObject* renderer, FilterEffect* previousEffect, const ReferenceFilterOperation* filterOperation) { if (!renderer) return nullptr; TreeScope* treeScope = &renderer->node()->treeScope(); if (DocumentResourceReference* documentResourceRef = documentResourceReference(filterOperation)) { DocumentResource* cachedSVGDocument = documentResourceRef->document(); // If we have an SVG document, this is an external reference. Otherwise // we look up the referenced node in the current document. if (cachedSVGDocument) treeScope = cachedSVGDocument->document(); } if (!treeScope) return nullptr; Element* filter = treeScope->getElementById(filterOperation->fragment()); if (!filter) { // Although we did not find the referenced filter, it might exist later // in the document. treeScope->document().accessSVGExtensions().addPendingResource(filterOperation->fragment(), toElement(renderer->node())); return nullptr; } if (!isSVGFilterElement(*filter)) return nullptr; SVGFilterElement& filterElement = toSVGFilterElement(*filter); // FIXME: Figure out what to do with SourceAlpha. Right now, we're // using the alpha of the original input layer, which is obviously // wrong. We should probably be extracting the alpha from the // previousEffect, but this requires some more processing. // This may need a spec clarification. RefPtr<SVGFilterBuilder> builder = SVGFilterBuilder::create(previousEffect, SourceAlpha::create(parentFilter)); ColorSpace filterColorSpace = ColorSpaceDeviceRGB; bool useFilterColorSpace = getSVGElementColorSpace(&filterElement, filterColorSpace); for (SVGElement* element = Traversal<SVGElement>::firstChild(filterElement); element; element = Traversal<SVGElement>::nextSibling(*element)) { if (!element->isFilterEffect()) continue; SVGFilterPrimitiveStandardAttributes* effectElement = static_cast<SVGFilterPrimitiveStandardAttributes*>(element); RefPtr<FilterEffect> effect = effectElement->build(builder.get(), parentFilter); if (!effect) continue; effectElement->setStandardAttributes(effect.get()); effect->setEffectBoundaries(SVGLengthContext::resolveRectangle<SVGFilterPrimitiveStandardAttributes>(effectElement, filterElement.primitiveUnits()->currentValue()->enumValue(), parentFilter->sourceImageRect())); ColorSpace colorSpace = filterColorSpace; if (useFilterColorSpace || getSVGElementColorSpace(effectElement, colorSpace)) effect->setOperatingColorSpace(colorSpace); builder->add(AtomicString(effectElement->result()->currentValue()->value()), effect); } return builder->lastEffect(); }