Diff
Modified: trunk/Source/WebCore/ChangeLog (277077 => 277078)
--- trunk/Source/WebCore/ChangeLog 2021-05-06 09:44:37 UTC (rev 277077)
+++ trunk/Source/WebCore/ChangeLog 2021-05-06 10:35:08 UTC (rev 277078)
@@ -1,3 +1,103 @@
+2021-05-06 Ryosuke Niwa <[email protected]>
+
+ Replace raw pointers in SVGElementRareData and SVGDocumentExtensions with WeakHashMap and WeakPtr
+ https://bugs.webkit.org/show_bug.cgi?id=225440
+
+ Reviewed by Antti Koivisto.
+
+ Replaced the remaining use of raw pointers to Element in SVGElementRareData and SVGDocumentExtensions
+ with WeakHashSet and WeakPtr.
+
+ This patch also replaces SVGDocumentExtensions::m_elementDependencies with a new WeakHashMap
+ in SVGElementRareData for clarify & simplicity with a new terminology. When a SVG element A refers
+ to another element B via href, A's SVGElementRareData::m_referenceTarget is set to B, and A is added
+ to B's SVGElementRareData::m_referencingElements.
+
+ No new tests since there should be no observable behavior differences.
+
+ * rendering/svg/RenderSVGResource.cpp:
+ (WebCore::removeFromCacheAndInvalidateDependencies):
+ * rendering/svg/RenderSVGResourceContainer.cpp:
+ (WebCore::RenderSVGResourceContainer::registerResource):
+ * svg/SVGAnimateMotionElement.cpp:
+ (WebCore::SVGAnimateMotionElement::applyResultsToTarget):
+ * svg/SVGDocumentExtensions.cpp:
+ (WebCore::SVGDocumentExtensions::addPendingResource):
+ (WebCore::SVGDocumentExtensions::isElementWithPendingResources const):
+ (WebCore::SVGDocumentExtensions::isPendingResource const): Directly check the existence of
+ the id in m_pendingResources instead of calling isIdOfPendingResource.
+ (WebCore::SVGDocumentExtensions::removeElementFromPendingResources):
+ (WebCore::SVGDocumentExtensions::removePendingResource): Moved to the header to be inlined.
+ (WebCore::SVGDocumentExtensions::removePendingResourceForRemoval): Deleted. The code is
+ inlined in removeElementFromPendingResources instead.
+ (WebCore::SVGDocumentExtensions::markPendingResourcesForRemoval):
+ (WebCore::SVGDocumentExtensions::takeElementFromPendingResourcesForRemovalMap): Renamed
+ from removeElementFromPendingResourcesForRemovalMap.
+ (WebCore::SVGDocumentExtensions::addElementToRebuild): Added.
+ (WebCore::SVGDocumentExtensions::removeElementToRebuild): Added.
+ (WebCore::SVGDocumentExtensions::setOfElementsReferencingTarget): Deleted.
+ (WebCore::SVGDocumentExtensions::addElementReferencingTarget): Deleted.
+ (WebCore::SVGDocumentExtensions::removeAllTargetReferencesForElement): Deleted.
+ (WebCore::SVGDocumentExtensions::clearTargetDependencies):
+ (WebCore::SVGDocumentExtensions::rebuildAllElementReferencesForTarget):
+ (WebCore::SVGDocumentExtensions::removeAllElementReferencesForTarget): Deleted.
+ * svg/SVGDocumentExtensions.h:
+ (WebCore::SVGDocumentExtensions::removePendingResource):
+ * svg/SVGElement.cpp:
+ (WebCore::SVGElement::~SVGElement):
+ (WebCore::SVGElement::removedFromAncestor): Moved the most of logic in SVGDocumentExtensions's
+ clearTargetDependencies and removeAllElementReferencesForTarget here.
+ (WebCore::SVGElement::instances const):
+ (WebCore::SVGElement::referencingElements const): Added.
+ (WebCore::SVGElement::addReferencingElement): Added.
+ (WebCore::SVGElement::removeReferencingElement): Added.
+ (WebCore::SVGElement::removeElementReference): Added.
+ (WebCore::SVGElement::setCorrespondingElement):
+ (WebCore::SVGElement::addEventListener):
+ (WebCore::SVGElement::removeEventListener):
+ (WebCore::SVGElement::createAnimator):
+ (WebCore::SVGElement::buildPendingResourcesIfNeeded):
+ (WebCore::SVGElement::updateRelativeLengthsInformation):
+ (WebCore::SVGElement::invalidateInstances):
+ (WebCore:: const): Deleted.
+ * svg/SVGElement.h:
+ (WebCore::SVGElement::hasRelativeLengths const):
+ (WebCore::SVGElement::updateRelativeLengthsInformation):
+ * svg/SVGElementRareData.h:
+ (WebCore::SVGElementRareData::addInstance):
+ (WebCore::SVGElementRareData::removeInstance):
+ (WebCore::SVGElementRareData::instances const):
+ (WebCore::SVGElementRareData::addReferencingElement):
+ (WebCore::SVGElementRareData::removeReferencingElement):
+ (WebCore::SVGElementRareData::referencingElements const):
+ (WebCore::SVGElementRareData::takeReferencingElements):
+ (WebCore::SVGElementRareData::referenceTarget const):
+ (WebCore::SVGElementRareData::setReferenceTarget):
+ (WebCore::SVGElementRareData::correspondingElement):
+ (WebCore::SVGElementRareData::setCorrespondingElement):
+ (): Deleted.
+ (WebCore::SVGElementRareData:: const): Deleted.
+ * svg/SVGFEImageElement.cpp:
+ (WebCore::SVGFEImageElement::clearResourceReferences):
+ (WebCore::SVGFEImageElement::buildPendingResource):
+ * svg/SVGMPathElement.cpp:
+ (WebCore::SVGMPathElement::buildPendingResource):
+ (WebCore::SVGMPathElement::clearResourceReferences):
+ * svg/SVGPathElement.cpp:
+ (WebCore::SVGPathElement::invalidateMPathDependencies):
+ * svg/SVGTextPathElement.cpp:
+ (WebCore::SVGTextPathElement::clearResourceReferences):
+ (WebCore::SVGTextPathElement::buildPendingResource):
+ * svg/SVGUseElement.cpp:
+ (WebCore::SVGUseElement::invalidateDependentShadowTrees):
+ * svg/animation/SVGSMILElement.cpp:
+ (WebCore::SVGSMILElement::clearResourceReferences):
+ (WebCore::SVGSMILElement::buildPendingResource):
+ * svg/properties/SVGAttributeAnimator.cpp:
+ (WebCore::SVGAttributeAnimator::applyAnimatedStylePropertyChange):
+ (WebCore::SVGAttributeAnimator::removeAnimatedStyleProperty):
+ (WebCore::SVGAttributeAnimator::applyAnimatedPropertyChange):
+
2021-05-06 Cameron McCormack <[email protected]>
Split context state change item appending out of DisplayList::Recorder::canAppendItemOfType.
Modified: trunk/Source/WebCore/rendering/svg/RenderSVGResource.cpp (277077 => 277078)
--- trunk/Source/WebCore/rendering/svg/RenderSVGResource.cpp 2021-05-06 09:44:37 UTC (rev 277077)
+++ trunk/Source/WebCore/rendering/svg/RenderSVGResource.cpp 2021-05-06 10:35:08 UTC (rev 277078)
@@ -168,21 +168,18 @@
if (!is<SVGElement>(renderer.element()))
return;
- auto* dependencies = renderer.document().accessSVGExtensions().setOfElementsReferencingTarget(downcast<SVGElement>(*renderer.element()));
- if (!dependencies)
- return;
- for (auto* element : *dependencies) {
+ for (auto& element : downcast<SVGElement>(*renderer.element()).referencingElements()) {
if (auto* renderer = element->renderer()) {
// We allow cycles in SVGDocumentExtensions reference sets in order to avoid expensive
// reference graph adjustments on changes, so we need to break possible cycles here.
- static NeverDestroyed<HashSet<SVGElement*>> invalidatingDependencies;
- if (UNLIKELY(!invalidatingDependencies.get().add(element).isNewEntry)) {
+ static NeverDestroyed<WeakHashSet<SVGElement>> invalidatingDependencies;
+ if (UNLIKELY(!invalidatingDependencies.get().add(element.get()).isNewEntry)) {
// Reference cycle: we are in process of invalidating this dependant.
continue;
}
RenderSVGResource::markForLayoutAndParentResourceInvalidation(*renderer, needsLayout);
- invalidatingDependencies.get().remove(element);
+ invalidatingDependencies.get().remove(element.get());
}
}
}
Modified: trunk/Source/WebCore/rendering/svg/RenderSVGResourceContainer.cpp (277077 => 277078)
--- trunk/Source/WebCore/rendering/svg/RenderSVGResourceContainer.cpp 2021-05-06 09:44:37 UTC (rev 277077)
+++ trunk/Source/WebCore/rendering/svg/RenderSVGResourceContainer.cpp 2021-05-06 10:35:08 UTC (rev 277078)
@@ -199,15 +199,15 @@
return;
}
- std::unique_ptr<SVGDocumentExtensions::PendingElements> clients = extensions.removePendingResource(m_id);
+ auto elements = copyToVectorOf<Ref<Element>>(extensions.removePendingResource(m_id));
// Cache us with the new id.
extensions.addResource(m_id, *this);
// Update cached resources of pending clients.
- for (auto* client : *clients) {
+ for (auto& client : elements) {
ASSERT(client->hasPendingResources());
- extensions.clearHasPendingResourcesIfPossible(*client);
+ extensions.clearHasPendingResourcesIfPossible(client);
auto* renderer = client->renderer();
if (!renderer)
continue;
Modified: trunk/Source/WebCore/svg/SVGAnimateMotionElement.cpp (277077 => 277078)
--- trunk/Source/WebCore/svg/SVGAnimateMotionElement.cpp 2021-05-06 09:44:37 UTC (rev 277077)
+++ trunk/Source/WebCore/svg/SVGAnimateMotionElement.cpp 2021-05-06 10:35:08 UTC (rev 277078)
@@ -258,7 +258,7 @@
return;
// ...except in case where we have additional instances in <use> trees.
- for (auto* instance : targetElement->instances()) {
+ for (auto& instance : copyToVectorOf<Ref<SVGElement>>(targetElement->instances())) {
AffineTransform* transform = instance->supplementalTransform();
if (!transform || *transform == *targetSupplementalTransform)
continue;
Modified: trunk/Source/WebCore/svg/SVGDocumentExtensions.cpp (277077 => 277078)
--- trunk/Source/WebCore/svg/SVGDocumentExtensions.cpp 2021-05-06 09:44:37 UTC (rev 277077)
+++ trunk/Source/WebCore/svg/SVGDocumentExtensions.cpp 2021-05-06 10:35:08 UTC (rev 277078)
@@ -159,10 +159,8 @@
if (id.isEmpty())
return;
- auto result = m_pendingResources.add(id, nullptr);
- if (result.isNewEntry)
- result.iterator->value = makeUnique<PendingElements>();
- result.iterator->value->add(&element);
+ auto result = m_pendingResources.add(id, WeakHashSet<Element> { });
+ result.iterator->value.add(element);
element.setHasPendingResources();
}
@@ -179,20 +177,21 @@
{
// This algorithm takes time proportional to the number of pending resources and need not.
// If performance becomes an issue we can keep a counted set of elements and answer the question efficiently.
- for (auto& elements : m_pendingResources.values()) {
- ASSERT(elements);
- if (elements->contains(&element))
- return true;
- }
- return false;
+ return WTF::anyOf(m_pendingResources.values(), [&] (auto& elements) {
+ return elements.contains(element);
+ });
}
bool SVGDocumentExtensions::isPendingResource(Element& element, const AtomString& id) const
{
- if (!isIdOfPendingResource(id))
+ if (id.isEmpty())
return false;
- return m_pendingResources.get(id)->contains(&element);
+ auto it = m_pendingResources.find(id);
+ if (it == m_pendingResources.end())
+ return false;
+
+ return it->value.contains(element);
}
void SVGDocumentExtensions::clearHasPendingResourcesIfPossible(Element& element)
@@ -207,12 +206,9 @@
if (!m_pendingResources.isEmpty() && element.hasPendingResources()) {
Vector<AtomString> toBeRemoved;
for (auto& resource : m_pendingResources) {
- PendingElements* elements = resource.value.get();
- ASSERT(elements);
- ASSERT(!elements->isEmpty());
-
- elements->remove(&element);
- if (elements->isEmpty())
+ auto& elements = resource.value;
+ elements.remove(element);
+ if (elements.computesEmpty())
toBeRemoved.append(resource.key);
}
@@ -227,33 +223,18 @@
if (!m_pendingResourcesForRemoval.isEmpty()) {
Vector<AtomString> toBeRemoved;
for (auto& resource : m_pendingResourcesForRemoval) {
- PendingElements* elements = resource.value.get();
- ASSERT(elements);
- ASSERT(!elements->isEmpty());
-
- elements->remove(&element);
- if (elements->isEmpty())
+ auto& elements = resource.value;
+ elements.remove(element);
+ if (elements.computesEmpty())
toBeRemoved.append(resource.key);
}
// We use the removePendingResourceForRemoval function here because it deals with set lifetime correctly.
for (auto& resource : toBeRemoved)
- removePendingResourceForRemoval(resource);
+ m_pendingResourcesForRemoval.remove(resource);
}
}
-std::unique_ptr<SVGDocumentExtensions::PendingElements> SVGDocumentExtensions::removePendingResource(const AtomString& id)
-{
- ASSERT(m_pendingResources.contains(id));
- return m_pendingResources.take(id);
-}
-
-std::unique_ptr<SVGDocumentExtensions::PendingElements> SVGDocumentExtensions::removePendingResourceForRemoval(const AtomString& id)
-{
- ASSERT(m_pendingResourcesForRemoval.contains(id));
- return m_pendingResourcesForRemoval.take(id);
-}
-
void SVGDocumentExtensions::markPendingResourcesForRemoval(const AtomString& id)
{
if (id.isEmpty())
@@ -261,60 +242,43 @@
ASSERT(!m_pendingResourcesForRemoval.contains(id));
- std::unique_ptr<PendingElements> existing = m_pendingResources.take(id);
- if (existing && !existing->isEmpty())
+ auto existing = m_pendingResources.take(id);
+ if (!existing.computesEmpty())
m_pendingResourcesForRemoval.add(id, WTFMove(existing));
}
-RefPtr<Element> SVGDocumentExtensions::removeElementFromPendingResourcesForRemovalMap(const AtomString& id)
+RefPtr<Element> SVGDocumentExtensions::takeElementFromPendingResourcesForRemovalMap(const AtomString& id)
{
if (id.isEmpty())
- return 0;
+ return nullptr;
- PendingElements* resourceSet = m_pendingResourcesForRemoval.get(id);
- if (!resourceSet || resourceSet->isEmpty())
- return 0;
+ auto it = m_pendingResourcesForRemoval.find(id);
+ if (it == m_pendingResourcesForRemoval.end())
+ return nullptr;
- auto firstElement = resourceSet->begin();
- RefPtr<Element> element = *firstElement;
+ auto& resourceSet = it->value;
+ auto firstElement = makeRefPtr(resourceSet.begin().get());
+ if (!firstElement)
+ return nullptr;
- resourceSet->remove(firstElement);
+ resourceSet.remove(*firstElement);
- if (resourceSet->isEmpty())
- removePendingResourceForRemoval(id);
+ if (resourceSet.computesEmpty())
+ m_pendingResourcesForRemoval.remove(id);
- return element;
+ return firstElement;
}
-HashSet<SVGElement*>* SVGDocumentExtensions::setOfElementsReferencingTarget(SVGElement& referencedElement) const
+void SVGDocumentExtensions::addElementToRebuild(SVGElement& element)
{
- return m_elementDependencies.get(&referencedElement);
+ m_rebuildElements.append(element);
}
-void SVGDocumentExtensions::addElementReferencingTarget(SVGElement& referencingElement, SVGElement& referencedElement)
+void SVGDocumentExtensions::removeElementToRebuild(SVGElement& element)
{
- auto result = m_elementDependencies.ensure(&referencedElement, [&referencingElement] {
- return makeUnique<HashSet<SVGElement*>>(std::initializer_list<SVGElement*> { &referencingElement });
- });
- if (!result.isNewEntry)
- result.iterator->value->add(&referencingElement);
+ m_rebuildElements.removeFirst(element);
}
-void SVGDocumentExtensions::removeAllTargetReferencesForElement(SVGElement& referencingElement)
-{
- Vector<SVGElement*> toBeRemoved;
-
- for (auto& dependency : m_elementDependencies) {
- auto& referencingElements = *dependency.value;
- referencingElements.remove(&referencingElement);
- if (referencingElements.isEmpty())
- toBeRemoved.append(dependency.key);
- }
-
- for (auto& element : toBeRemoved)
- m_elementDependencies.remove(element);
-}
-
void SVGDocumentExtensions::rebuildElements()
{
auto shadowRebuildElements = std::exchange(m_rebuildElements, { });
@@ -324,11 +288,8 @@
void SVGDocumentExtensions::clearTargetDependencies(SVGElement& referencedElement)
{
- auto* referencingElements = m_elementDependencies.get(&referencedElement);
- if (!referencingElements)
- return;
- for (auto* element : *referencingElements) {
- m_rebuildElements.append(*element);
+ for (auto& element : referencedElement.referencingElements()) {
+ m_rebuildElements.append(element.get());
element->callClearTarget();
}
}
@@ -335,27 +296,10 @@
void SVGDocumentExtensions::rebuildAllElementReferencesForTarget(SVGElement& referencedElement)
{
- auto it = m_elementDependencies.find(&referencedElement);
- if (it == m_elementDependencies.end())
- return;
- ASSERT(it->key == &referencedElement);
-
- HashSet<SVGElement*>* referencingElements = it->value.get();
- Vector<SVGElement*> elementsToRebuild;
- elementsToRebuild.reserveInitialCapacity(referencingElements->size());
- for (auto* element : *referencingElements)
- elementsToRebuild.uncheckedAppend(element);
-
- for (auto* element : elementsToRebuild)
+ for (auto& element : referencedElement.referencingElements())
element->svgAttributeChanged(SVGNames::hrefAttr);
}
-void SVGDocumentExtensions::removeAllElementReferencesForTarget(SVGElement& referencedElement)
-{
- m_elementDependencies.remove(&referencedElement);
- m_rebuildElements.removeFirst(referencedElement);
-}
-
void SVGDocumentExtensions::registerSVGFontFaceElement(SVGFontFaceElement& element)
{
m_svgFontFaceElements.add(element);
Modified: trunk/Source/WebCore/svg/SVGDocumentExtensions.h (277077 => 277078)
--- trunk/Source/WebCore/svg/SVGDocumentExtensions.h 2021-05-06 09:44:37 UTC (rev 277077)
+++ trunk/Source/WebCore/svg/SVGDocumentExtensions.h 2021-05-06 10:35:08 UTC (rev 277078)
@@ -39,7 +39,6 @@
class SVGDocumentExtensions {
WTF_MAKE_NONCOPYABLE(SVGDocumentExtensions); WTF_MAKE_FAST_ALLOCATED;
public:
- typedef HashSet<Element*> PendingElements;
explicit SVGDocumentExtensions(Document&);
~SVGDocumentExtensions();
@@ -65,15 +64,12 @@
SVGResourcesCache& resourcesCache() { return *m_resourcesCache; }
- HashSet<SVGElement*>* setOfElementsReferencingTarget(SVGElement& referencedElement) const;
- void addElementReferencingTarget(SVGElement& referencingElement, SVGElement& referencedElement);
- void removeAllTargetReferencesForElement(SVGElement&);
+ void addElementToRebuild(SVGElement&);
+ void removeElementToRebuild(SVGElement&);
+ void rebuildElements();
+ void clearTargetDependencies(SVGElement&);
void rebuildAllElementReferencesForTarget(SVGElement&);
- void removeAllElementReferencesForTarget(SVGElement&);
- void clearTargetDependencies(SVGElement&);
- void rebuildElements();
-
const WeakHashSet<SVGFontFaceElement>& svgFontFaceElements() const { return m_svgFontFaceElements; }
void registerSVGFontFaceElement(SVGFontFaceElement&);
void unregisterSVGFontFaceElement(SVGFontFaceElement&);
@@ -83,9 +79,8 @@
WeakHashSet<SVGSVGElement> m_timeContainers; // For SVG 1.2 support this will need to be made more general.
WeakHashSet<SVGFontFaceElement> m_svgFontFaceElements;
HashMap<AtomString, RenderSVGResourceContainer*> m_resources;
- HashMap<AtomString, std::unique_ptr<PendingElements>> m_pendingResources; // Resources that are pending.
- HashMap<AtomString, std::unique_ptr<PendingElements>> m_pendingResourcesForRemoval; // Resources that are pending and scheduled for removal.
- HashMap<SVGElement*, std::unique_ptr<HashSet<SVGElement*>>> m_elementDependencies;
+ HashMap<AtomString, WeakHashSet<Element>> m_pendingResources; // Resources that are pending.
+ HashMap<AtomString, WeakHashSet<Element>> m_pendingResourcesForRemoval; // Resources that are pending and scheduled for removal.
std::unique_ptr<SVGResourcesCache> m_resourcesCache;
Vector<Ref<SVGElement>> m_rebuildElements;
@@ -101,15 +96,14 @@
bool isPendingResource(Element&, const AtomString& id) const;
void clearHasPendingResourcesIfPossible(Element&);
void removeElementFromPendingResources(Element&);
- std::unique_ptr<PendingElements> removePendingResource(const AtomString& id);
+ WeakHashSet<Element> removePendingResource(const AtomString& id) { return m_pendingResources.take(id); }
// The following two functions are used for scheduling a pending resource to be removed.
void markPendingResourcesForRemoval(const AtomString&);
- RefPtr<Element> removeElementFromPendingResourcesForRemovalMap(const AtomString&);
+ RefPtr<Element> takeElementFromPendingResourcesForRemovalMap(const AtomString&);
private:
bool isElementWithPendingResources(Element&) const;
- std::unique_ptr<PendingElements> removePendingResourceForRemoval(const AtomString&);
};
} // namespace WebCore
Modified: trunk/Source/WebCore/svg/SVGElement.cpp (277077 => 277078)
--- trunk/Source/WebCore/svg/SVGElement.cpp 2021-05-06 09:44:37 UTC (rev 277077)
+++ trunk/Source/WebCore/svg/SVGElement.cpp 2021-05-06 10:35:08 UTC (rev 277078)
@@ -169,13 +169,13 @@
SVGElement::~SVGElement()
{
if (m_svgRareData) {
- for (SVGElement* instance : m_svgRareData->instances())
- instance->m_svgRareData->setCorrespondingElement(nullptr);
+ RELEASE_ASSERT(m_svgRareData->referencingElements().computesEmpty());
+ for (SVGElement& instance : copyToVectorOf<Ref<SVGElement>>(instances()))
+ instance.m_svgRareData->setCorrespondingElement(nullptr);
RELEASE_ASSERT(!m_svgRareData->correspondingElement());
m_svgRareData = nullptr;
}
- document().accessSVGExtensions().rebuildAllElementReferencesForTarget(*this);
- document().accessSVGExtensions().removeAllElementReferencesForTarget(*this);
+ document().accessSVGExtensions().removeElementToRebuild(*this);
}
void SVGElement::willRecalcStyle(Style::Change change)
@@ -240,13 +240,20 @@
void SVGElement::removedFromAncestor(RemovalType removalType, ContainerNode& oldParentOfRemovedTree)
{
if (removalType.disconnectedFromDocument)
- updateRelativeLengthsInformation(false, this);
+ updateRelativeLengthsInformation(false, *this);
StyledElement::removedFromAncestor(removalType, oldParentOfRemovedTree);
if (removalType.disconnectedFromDocument) {
- document().accessSVGExtensions().clearTargetDependencies(*this);
- document().accessSVGExtensions().removeAllElementReferencesForTarget(*this);
+ auto& extensions = document().accessSVGExtensions();
+ if (m_svgRareData) {
+ for (auto& element : m_svgRareData->takeReferencingElements()) {
+ extensions.addElementToRebuild(element);
+ makeRef(element)->clearTarget();
+ }
+ RELEASE_ASSERT(m_svgRareData->referencingElements().computesEmpty());
+ }
+ extensions.removeElementToRebuild(*this);
}
invalidateInstances();
@@ -282,10 +289,10 @@
return nullptr;
}
-const HashSet<SVGElement*>& SVGElement::instances() const
+const WeakHashSet<SVGElement>& SVGElement::instances() const
{
if (!m_svgRareData) {
- static NeverDestroyed<HashSet<SVGElement*>> emptyInstances;
+ static NeverDestroyed<WeakHashSet<SVGElement>> emptyInstances;
return emptyInstances;
}
return m_svgRareData->instances();
@@ -300,6 +307,35 @@
return WTF::nullopt;
}
+Vector<Ref<SVGElement>> SVGElement::referencingElements() const
+{
+ if (!m_svgRareData)
+ return { };
+ return copyToVectorOf<Ref<SVGElement>>(m_svgRareData->referencingElements());
+}
+
+void SVGElement::addReferencingElement(SVGElement& element)
+{
+ ensureSVGRareData().addReferencingElement(element);
+ auto& rareDataOfReferencingElement = element.ensureSVGRareData();
+ RELEASE_ASSERT(!rareDataOfReferencingElement.referenceTarget());
+ rareDataOfReferencingElement.setReferenceTarget(makeWeakPtr(*this));
+}
+
+void SVGElement::removeReferencingElement(SVGElement& element)
+{
+ ensureSVGRareData().removeReferencingElement(element);
+ element.ensureSVGRareData().setReferenceTarget(nullptr);
+}
+
+void SVGElement::removeElementReference()
+{
+ if (!m_svgRareData)
+ return;
+ if (auto destination = makeRefPtr(m_svgRareData->referenceTarget()))
+ destination->removeReferencingElement(*this);
+}
+
SVGElement* SVGElement::correspondingElement() const
{
return m_svgRareData ? m_svgRareData->correspondingElement() : nullptr;
@@ -322,12 +358,12 @@
{
if (m_svgRareData) {
if (auto oldCorrespondingElement = makeRefPtr(m_svgRareData->correspondingElement()))
- oldCorrespondingElement->m_svgRareData->instances().remove(this);
+ oldCorrespondingElement->m_svgRareData->removeInstance(*this);
}
if (m_svgRareData || correspondingElement)
ensureSVGRareData().setCorrespondingElement(correspondingElement);
if (correspondingElement)
- correspondingElement->ensureSVGRareData().instances().add(this);
+ correspondingElement->ensureSVGRareData().addInstance(*this);
}
void SVGElement::parseAttribute(const QualifiedName& name, const AtomString& value)
@@ -372,7 +408,7 @@
// Add event listener to all shadow tree DOM element instances
ASSERT(!instanceUpdatesBlocked());
- for (auto* instance : instances()) {
+ for (auto& instance : copyToVectorOf<Ref<SVGElement>>(instances())) {
ASSERT(instance->correspondingElement() == this);
ASSERT(instance->isInUserAgentShadowTree());
bool result = instance->Node::addEventListener(eventType, listener.copyRef(), options);
@@ -400,7 +436,7 @@
// Remove event listener from all shadow tree DOM element instances
ASSERT(!instanceUpdatesBlocked());
- for (auto& instance : instances()) {
+ for (auto& instance : copyToVectorOf<Ref<SVGElement>>(instances())) {
ASSERT(instance->correspondingElement() == this);
ASSERT(instance->isInUserAgentShadowTree());
@@ -574,7 +610,7 @@
auto animator = propertyRegistry().createAnimator(attributeName, animationMode, calcMode, isAccumulated, isAdditive);
if (!animator)
return animator;
- for (auto* instance : instances())
+ for (auto& instance : copyToVectorOf<Ref<SVGElement>>(instances()))
instance->propertyRegistry().appendAnimatedInstance(attributeName, *animator);
return animator;
}
@@ -859,7 +895,7 @@
extensions.markPendingResourcesForRemoval(resourceId);
// Rebuild pending resources for each client of a pending resource that is being removed.
- while (auto clientElement = extensions.removeElementFromPendingResourcesForRemovalMap(resourceId)) {
+ while (auto clientElement = extensions.takeElementFromPendingResourcesForRemovalMap(resourceId)) {
ASSERT(clientElement->hasPendingResources());
if (clientElement->hasPendingResources()) {
clientElement->buildPendingResource();
@@ -902,7 +938,7 @@
return AffineTransform();
}
-void SVGElement::updateRelativeLengthsInformation(bool hasRelativeLengths, SVGElement* element)
+void SVGElement::updateRelativeLengthsInformation(bool hasRelativeLengths, SVGElement& element)
{
// If we're not yet in a document, this function will be called again from insertedIntoAncestor(). Do nothing now.
if (!isConnected())
@@ -915,18 +951,16 @@
if (hasRelativeLengths)
m_elementsWithRelativeLengths.add(element);
else {
- if (!m_elementsWithRelativeLengths.contains(element)) {
- // We were never registered. Do nothing.
+ bool neverRegistered = !m_elementsWithRelativeLengths.contains(element);
+ if (neverRegistered)
return;
- }
m_elementsWithRelativeLengths.remove(element);
}
- if (is<SVGGraphicsElement>(*element)) {
- auto parent = makeRefPtr(parentNode());
- if (is<SVGElement>(parent))
- downcast<SVGElement>(*parent).updateRelativeLengthsInformation(hasRelativeLengths, this);
+ if (is<SVGGraphicsElement>(element)) {
+ if (auto parent = makeRefPtr(parentNode()); is<SVGElement>(parent))
+ downcast<SVGElement>(*parent).updateRelativeLengthsInformation(hasRelativeLengths, *this);
}
}
@@ -940,9 +974,7 @@
if (instanceUpdatesBlocked())
return;
- auto& instances = this->instances();
- while (!instances.isEmpty()) {
- auto instance = makeRefPtr(*instances.begin());
+ for (auto& instance : copyToVectorOf<Ref<SVGElement>>(instances())) {
if (auto useElement = instance->correspondingUseElement())
useElement->invalidateShadowTree();
instance->setCorrespondingElement(nullptr);
Modified: trunk/Source/WebCore/svg/SVGElement.h (277077 => 277078)
--- trunk/Source/WebCore/svg/SVGElement.h 2021-05-06 09:44:37 UTC (rev 277077)
+++ trunk/Source/WebCore/svg/SVGElement.h 2021-05-06 10:35:08 UTC (rev 277078)
@@ -56,7 +56,7 @@
String title() const override;
virtual bool supportsMarkers() const { return false; }
- bool hasRelativeLengths() const { return !m_elementsWithRelativeLengths.isEmpty(); }
+ bool hasRelativeLengths() const { return !m_elementsWithRelativeLengths.computesEmpty(); }
virtual bool needsPendingResourceHandling() const { return true; }
bool instanceUpdatesBlocked() const;
void setInstanceUpdatesBlocked(bool);
@@ -89,10 +89,15 @@
}
// The instances of an element are clones made in shadow trees to implement <use>.
- const HashSet<SVGElement*>& instances() const;
+ const WeakHashSet<SVGElement>& instances() const;
Optional<FloatRect> getBoundingBox() const;
+ Vector<Ref<SVGElement>> referencingElements() const;
+ void addReferencingElement(SVGElement&);
+ void removeReferencingElement(SVGElement&);
+ void removeElementReference();
+
SVGElement* correspondingElement() const;
RefPtr<SVGUseElement> correspondingUseElement() const;
@@ -169,8 +174,8 @@
void removedFromAncestor(RemovalType, ContainerNode&) override;
void childrenChanged(const ChildChange&) override;
virtual bool selfHasRelativeLengths() const { return false; }
- void updateRelativeLengthsInformation() { updateRelativeLengthsInformation(selfHasRelativeLengths(), this); }
- void updateRelativeLengthsInformation(bool hasRelativeLengths, SVGElement*);
+ void updateRelativeLengthsInformation() { updateRelativeLengthsInformation(selfHasRelativeLengths(), *this); }
+ void updateRelativeLengthsInformation(bool hasRelativeLengths, SVGElement&);
void willRecalcStyle(Style::Change) override;
@@ -188,7 +193,7 @@
std::unique_ptr<SVGElementRareData> m_svgRareData;
- HashSet<SVGElement*> m_elementsWithRelativeLengths;
+ WeakHashSet<SVGElement> m_elementsWithRelativeLengths;
std::unique_ptr<SVGPropertyAnimatorFactory> m_propertyAnimatorFactory;
Modified: trunk/Source/WebCore/svg/SVGElementRareData.h (277077 => 277078)
--- trunk/Source/WebCore/svg/SVGElementRareData.h 2021-05-06 09:44:37 UTC (rev 277077)
+++ trunk/Source/WebCore/svg/SVGElementRareData.h 2021-05-06 10:35:08 UTC (rev 277078)
@@ -41,15 +41,23 @@
{
}
- HashSet<SVGElement*>& instances() { return m_instances; }
- const HashSet<SVGElement*>& instances() const { return m_instances; }
+ void addInstance(SVGElement& element) { m_instances.add(element); }
+ void removeInstance(SVGElement& element) { m_instances.remove(element); }
+ const WeakHashSet<SVGElement>& instances() const { return m_instances; }
bool instanceUpdatesBlocked() const { return m_instancesUpdatesBlocked; }
void setInstanceUpdatesBlocked(bool value) { m_instancesUpdatesBlocked = value; }
- SVGElement* correspondingElement() { return m_correspondingElement; }
- void setCorrespondingElement(SVGElement* correspondingElement) { m_correspondingElement = correspondingElement; }
+ void addReferencingElement(SVGElement& element) { m_referencingElements.add(element); }
+ void removeReferencingElement(SVGElement& element) { m_referencingElements.remove(element); }
+ const WeakHashSet<SVGElement>& referencingElements() const { return m_referencingElements; }
+ WeakHashSet<SVGElement> takeReferencingElements() { return std::exchange(m_referencingElements, { }); }
+ SVGElement* referenceTarget() const { return m_referenceTarget.get(); }
+ void setReferenceTarget(WeakPtr<SVGElement>&& element) { m_referenceTarget = WTFMove(element); }
+ SVGElement* correspondingElement() { return m_correspondingElement.get(); }
+ void setCorrespondingElement(SVGElement* correspondingElement) { m_correspondingElement = makeWeakPtr(correspondingElement); }
+
MutableStyleProperties* animatedSMILStyleProperties() const { return m_animatedSMILStyleProperties.get(); }
MutableStyleProperties& ensureAnimatedSMILStyleProperties()
{
@@ -76,8 +84,10 @@
void setNeedsOverrideComputedStyleUpdate() { m_needsOverrideComputedStyleUpdate = true; }
private:
- HashSet<SVGElement*> m_instances;
- SVGElement* m_correspondingElement { nullptr };
+ WeakHashSet<SVGElement> m_referencingElements;
+ WeakPtr<SVGElement> m_referenceTarget;
+ WeakHashSet<SVGElement> m_instances;
+ WeakPtr<SVGElement> m_correspondingElement;
bool m_instancesUpdatesBlocked : 1;
bool m_useOverrideComputedStyle : 1;
bool m_needsOverrideComputedStyleUpdate : 1;
Modified: trunk/Source/WebCore/svg/SVGFEImageElement.cpp (277077 => 277078)
--- trunk/Source/WebCore/svg/SVGFEImageElement.cpp 2021-05-06 09:44:37 UTC (rev 277077)
+++ trunk/Source/WebCore/svg/SVGFEImageElement.cpp 2021-05-06 10:35:08 UTC (rev 277078)
@@ -75,7 +75,7 @@
m_cachedImage = nullptr;
}
- document().accessSVGExtensions().removeAllTargetReferencesForElement(*this);
+ removeElementReference();
}
void SVGFEImageElement::requestImageResource()
@@ -105,11 +105,8 @@
document().accessSVGExtensions().addPendingResource(target.identifier, *this);
ASSERT(hasPendingResources());
}
- } else if (is<SVGElement>(*target.element)) {
- // 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, downcast<SVGElement>(*target.element));
- }
+ } else if (is<SVGElement>(*target.element))
+ downcast<SVGElement>(*target.element).addReferencingElement(*this);
invalidate();
}
Modified: trunk/Source/WebCore/svg/SVGMPathElement.cpp (277077 => 277078)
--- trunk/Source/WebCore/svg/SVGMPathElement.cpp 2021-05-06 09:44:37 UTC (rev 277077)
+++ trunk/Source/WebCore/svg/SVGMPathElement.cpp 2021-05-06 10:35:08 UTC (rev 277078)
@@ -65,11 +65,8 @@
document().accessSVGExtensions().addPendingResource(target.identifier, *this);
ASSERT(hasPendingResources());
}
- } else if (is<SVGElement>(*target.element)) {
- // 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, downcast<SVGElement>(*target.element));
- }
+ } else if (is<SVGElement>(*target.element))
+ downcast<SVGElement>(*target.element).addReferencingElement(*this);
targetPathChanged();
}
@@ -76,7 +73,7 @@
void SVGMPathElement::clearResourceReferences()
{
- document().accessSVGExtensions().removeAllTargetReferencesForElement(*this);
+ removeElementReference();
}
Node::InsertedIntoAncestorResult SVGMPathElement::insertedIntoAncestor(InsertionType insertionType, ContainerNode& parentOfInsertedTree)
Modified: trunk/Source/WebCore/svg/SVGPathElement.cpp (277077 => 277078)
--- trunk/Source/WebCore/svg/SVGPathElement.cpp 2021-05-06 09:44:37 UTC (rev 277077)
+++ trunk/Source/WebCore/svg/SVGPathElement.cpp 2021-05-06 10:35:08 UTC (rev 277078)
@@ -83,11 +83,9 @@
{
// <mpath> can only reference <path> but this dependency is not handled in
// markForLayoutAndParentResourceInvalidation so we update any mpath dependencies manually.
- if (HashSet<SVGElement*>* dependencies = document().accessSVGExtensions().setOfElementsReferencingTarget(*this)) {
- for (auto* element : *dependencies) {
- if (is<SVGMPathElement>(*element))
- downcast<SVGMPathElement>(*element).targetPathChanged();
- }
+ for (auto& element : referencingElements()) {
+ if (is<SVGMPathElement>(element))
+ downcast<SVGMPathElement>(element.get()).targetPathChanged();
}
}
Modified: trunk/Source/WebCore/svg/SVGTextPathElement.cpp (277077 => 277078)
--- trunk/Source/WebCore/svg/SVGTextPathElement.cpp 2021-05-06 09:44:37 UTC (rev 277077)
+++ trunk/Source/WebCore/svg/SVGTextPathElement.cpp 2021-05-06 10:35:08 UTC (rev 277078)
@@ -59,7 +59,7 @@
void SVGTextPathElement::clearResourceReferences()
{
- document().accessSVGExtensions().removeAllTargetReferencesForElement(*this);
+ removeElementReference();
}
void SVGTextPathElement::parseAttribute(const QualifiedName& name, const AtomString& value)
@@ -149,11 +149,8 @@
document().accessSVGExtensions().addPendingResource(target.identifier, *this);
ASSERT(hasPendingResources());
}
- } else if (target.element->hasTagName(SVGNames::pathTag)) {
- // 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, downcast<SVGElement>(*target.element));
- }
+ } else if (target.element->hasTagName(SVGNames::pathTag))
+ downcast<SVGElement>(*target.element).addReferencingElement(*this);
}
Node::InsertedIntoAncestorResult SVGTextPathElement::insertedIntoAncestor(InsertionType insertionType, ContainerNode& parentOfInsertedTree)
Modified: trunk/Source/WebCore/svg/SVGUseElement.cpp (277077 => 277078)
--- trunk/Source/WebCore/svg/SVGUseElement.cpp 2021-05-06 09:44:37 UTC (rev 277077)
+++ trunk/Source/WebCore/svg/SVGUseElement.cpp 2021-05-06 10:35:08 UTC (rev 277078)
@@ -534,7 +534,7 @@
void SVGUseElement::invalidateDependentShadowTrees()
{
- for (auto* instance : instances()) {
+ for (auto& instance : copyToVectorOf<Ref<SVGElement>>(instances())) {
if (auto element = instance->correspondingUseElement())
element->invalidateShadowTree();
}
Modified: trunk/Source/WebCore/svg/animation/SVGSMILElement.cpp (277077 => 277078)
--- trunk/Source/WebCore/svg/animation/SVGSMILElement.cpp 2021-05-06 09:44:37 UTC (rev 277077)
+++ trunk/Source/WebCore/svg/animation/SVGSMILElement.cpp 2021-05-06 10:35:08 UTC (rev 277078)
@@ -163,7 +163,7 @@
void SVGSMILElement::clearResourceReferences()
{
- document().accessSVGExtensions().removeAllTargetReferencesForElement(*this);
+ removeElementReference();
}
void SVGSMILElement::clearTarget()
@@ -191,13 +191,10 @@
target = WTFMove(result.element);
id = WTFMove(result.identifier);
}
- SVGElement* svgTarget = is<SVGElement>(target) ? downcast<SVGElement>(target.get()) : nullptr;
+ auto svgTarget = makeRefPtr(is<SVGElement>(target) && target->isConnected() ? downcast<SVGElement>(target.get()) : nullptr);
- if (svgTarget && !svgTarget->isConnected())
- svgTarget = nullptr;
-
if (svgTarget != targetElement())
- setTargetElement(svgTarget);
+ setTargetElement(svgTarget.get());
if (!svgTarget) {
// Do not register as pending if we are already pending this resource.
@@ -208,11 +205,8 @@
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);
- }
+ } else
+ svgTarget->addReferencingElement(*this);
}
inline QualifiedName SVGSMILElement::constructAttributeName() const
Modified: trunk/Source/WebCore/svg/properties/SVGAttributeAnimator.cpp (277077 => 277078)
--- trunk/Source/WebCore/svg/properties/SVGAttributeAnimator.cpp 2021-05-06 09:44:37 UTC (rev 277077)
+++ trunk/Source/WebCore/svg/properties/SVGAttributeAnimator.cpp 2021-05-06 10:35:08 UTC (rev 277078)
@@ -69,8 +69,8 @@
applyAnimatedStylePropertyChange(targetElement, id, value);
// If the target element has instances, update them as well, w/o requiring the <use> tree to be rebuilt.
- for (auto* instance : targetElement->instances())
- applyAnimatedStylePropertyChange(instance, id, value);
+ for (auto& instance : copyToVectorOf<Ref<SVGElement>>(targetElement->instances()))
+ applyAnimatedStylePropertyChange(instance.ptr(), id, value);
}
void SVGAttributeAnimator::removeAnimatedStyleProperty(SVGElement* element, CSSPropertyID id)
@@ -98,8 +98,8 @@
removeAnimatedStyleProperty(targetElement, id);
// If the target element has instances, update them as well, w/o requiring the <use> tree to be rebuilt.
- for (auto* instance : targetElement->instances())
- removeAnimatedStyleProperty(instance, id);
+ for (auto& instance : copyToVectorOf<Ref<SVGElement>>(targetElement->instances()))
+ removeAnimatedStyleProperty(instance.ptr(), id);
}
void SVGAttributeAnimator::applyAnimatedPropertyChange(SVGElement* element, const QualifiedName& attributeName)
@@ -121,8 +121,8 @@
applyAnimatedPropertyChange(targetElement, m_attributeName);
// If the target element has instances, update them as well, w/o requiring the <use> tree to be rebuilt.
- for (auto* instance : targetElement->instances())
- applyAnimatedPropertyChange(instance, m_attributeName);
+ for (auto& instance : copyToVectorOf<Ref<SVGElement>>(targetElement->instances()))
+ applyAnimatedPropertyChange(instance.ptr(), m_attributeName);
}
}