void SVGElement::removedFrom(ContainerNode* rootParent) { bool wasInDocument = rootParent->inDocument(); if (wasInDocument && hasRelativeLengths()) { // The root of the subtree being removed should take itself out from its parent's relative // length set. For the other nodes in the subtree we don't need to do anything: they will // get their own removedFrom() notification and just clear their sets. if (rootParent->isSVGElement() && !parentNode()) { ASSERT(toSVGElement(rootParent)->m_elementsWithRelativeLengths.contains(this)); toSVGElement(rootParent)->updateRelativeLengthsInformation(false, this); } m_elementsWithRelativeLengths.clear(); } ASSERT_WITH_SECURITY_IMPLICATION(!rootParent->isSVGElement() || !toSVGElement(rootParent)->m_elementsWithRelativeLengths.contains(this)); Element::removedFrom(rootParent); if (wasInDocument) { rebuildAllIncomingReferences(); removeAllIncomingReferences(); } invalidateInstances(); }
SVGElement::~SVGElement() { ASSERT(inDocument() || !hasRelativeLengths()); if (!hasSVGRareData()) ASSERT(!SVGElementRareData::rareDataMap().contains(this)); else { SVGElementRareData::SVGElementRareDataMap& rareDataMap = SVGElementRareData::rareDataMap(); SVGElementRareData::SVGElementRareDataMap::iterator it = rareDataMap.find(this); ASSERT_WITH_SECURITY_IMPLICATION(it != rareDataMap.end()); SVGElementRareData* rareData = it->value; rareData->destroyAnimatedSMILStyleProperties(); if (SVGCursorElement* cursorElement = rareData->cursorElement()) cursorElement->removeClient(this); if (CSSCursorImageValue* cursorImageValue = rareData->cursorImageValue()) cursorImageValue->removeReferencedElement(this); delete rareData; // The rare data cleanup may have caused other SVG nodes to be deleted, // modifying the rare data map. Do not rely on the existing iterator. ASSERT(rareDataMap.contains(this)); rareDataMap.remove(this); // Clear HasSVGRareData flag now so that we are in a consistent state when // calling rebuildAllElementReferencesForTarget() and // removeAllElementReferencesForTarget() below. clearHasSVGRareData(); } document().accessSVGExtensions().rebuildAllElementReferencesForTarget(this); document().accessSVGExtensions().removeAllElementReferencesForTarget(this); }
void SVGElement::invalidateRelativeLengthClients(SubtreeLayoutScope* layoutScope) { if (!inDocument()) return; ASSERT(!m_inRelativeLengthClientsInvalidation); #if ENABLE(ASSERT) TemporaryChange<bool> inRelativeLengthClientsInvalidationChange(m_inRelativeLengthClientsInvalidation, true); #endif if (LayoutObject* layoutObject = this->layoutObject()) { if (hasRelativeLengths() && layoutObject->isSVGResourceContainer()) toLayoutSVGResourceContainer(layoutObject)->invalidateCacheAndMarkForLayout(layoutScope); else if (selfHasRelativeLengths()) layoutObject->setNeedsLayoutAndFullPaintInvalidation(LayoutInvalidationReason::Unknown, MarkContainerChain, layoutScope); } for (SVGElement* element : m_elementsWithRelativeLengths) { if (element != this) element->invalidateRelativeLengthClients(layoutScope); } }
SVGElement::~SVGElement() { ASSERT(inDocument() || !hasRelativeLengths()); // The below teardown is all handled by weak pointer processing in oilpan. #if !ENABLE(OILPAN) if (hasSVGRareData()) { if (SVGCursorElement* cursorElement = svgRareData()->cursorElement()) cursorElement->removeReferencedElement(this); if (CSSCursorImageValue* cursorImageValue = svgRareData()->cursorImageValue()) cursorImageValue->removeReferencedElement(this); // Clear the rare data now so that we are in a consistent state when // calling rebuildAllElementReferencesForTarget() below. m_SVGRareData.clear(); } // With Oilpan, either removedFrom has been called or the document is dead // as well and there is no reason to clear out the references. document().accessSVGExtensions().rebuildAllElementReferencesForTarget(this); document().accessSVGExtensions().removeAllElementReferencesForTarget(this); #endif }