static inline void removeDisallowedElementsFromSubtree(SVGElement& subtree) { ASSERT(!subtree.inDocument()); Vector<Element*> toRemove; auto it = descendantsOfType<Element>(subtree).begin(); auto end = descendantsOfType<Element>(subtree).end(); while (it != end) { if (isDisallowedElement(*it)) { toRemove.append(&*it); it.traverseNextSkippingChildren(); continue; } ++it; } // The subtree is not in document so this won't generate events that could mutate the tree. for (unsigned i = 0; i < toRemove.size(); ++i) toRemove[i]->parentNode()->removeChild(toRemove[i]); }
void SVGSMILElement::buildPendingResource() { clearResourceAndEventBaseReferences(); if (!inDocument()) { // Reset the target element if we are no longer in the document. setTargetElement(nullptr); return; } AtomicString id; const AtomicString& href = SVGURIReference::legacyHrefString(*this); Element* target; if (href.isEmpty()) target = parentNode() && parentNode()->isElementNode() ? toElement(parentNode()) : nullptr; else target = SVGURIReference::targetElementFromIRIString(href, treeScope(), &id); SVGElement* svgTarget = target && target->isSVGElement() ? toSVGElement(target) : nullptr; if (svgTarget && !svgTarget->inDocument()) svgTarget = nullptr; if (svgTarget != targetElement()) setTargetElement(svgTarget); if (!svgTarget) { // Do not register as pending if we are already pending this resource. if (document().accessSVGExtensions().isElementPendingResource(this, id)) return; if (!id.isEmpty()) { document().accessSVGExtensions().addPendingResource(id, this); ASSERT(hasPendingResources()); } } else { // Register us with the target in the dependencies map. Any change of hrefElement // that leads to relayout/repainting now informs us, so we can react to it. addReferenceTo(svgTarget); } connectEventBaseConditions(); }
void SVGSMILElement::buildPendingResource() { clearResourceReferences(); if (!inDocument()) { // Reset the target element if we are no longer in the document. setTargetElement(0); return; } String id; String href = getAttribute(XLinkNames::hrefAttr); Element* target; if (href.isEmpty()) target = parentNode() && parentNode()->isElementNode() ? toElement(parentNode()) : 0; else target = SVGURIReference::targetElementFromIRIString(href, document(), &id); SVGElement* svgTarget = target && target->isSVGElement() ? toSVGElement(target) : 0; if (svgTarget && !svgTarget->inDocument()) svgTarget = 0; if (svgTarget != targetElement()) setTargetElement(svgTarget); if (!svgTarget) { // Do not register as pending if we are already pending this resource. if (document()->accessSVGExtensions()->isElementPendingResource(this, id)) return; if (!id.isEmpty()) { document()->accessSVGExtensions()->addPendingResource(id, this); ASSERT(hasPendingResources()); } } else { // Register us with the target in the dependencies map. Any change of hrefElement // that leads to relayout/repainting now informs us, so we can react to it. document()->accessSVGExtensions()->addElementReferencingTarget(this, svgTarget); } }
static void removeDisallowedElementsFromSubtree(SVGElement& subtree) { // Remove disallowed elements after the fact rather than not cloning them in the first place. // This optimizes for the normal case where none of those elements are present. // This function is used only on elements in subtrees that are not yet in documents, so // mutation events are not a factor; there are no event listeners to handle those events. // Assert that it's not in a document to make sure callers are still using it this way. ASSERT(!subtree.inDocument()); Vector<Element*> disallowedElements; auto descendants = descendantsOfType<Element>(subtree); for (auto it = descendants.begin(), end = descendants.end(); it != end; ) { if (isDisallowedElement(*it)) { disallowedElements.append(&*it); it.traverseNextSkippingChildren(); continue; } ++it; } for (auto* element : disallowedElements) element->parentNode()->removeChild(element); }