Title: [277013] trunk/Source/WebCore
Revision
277013
Author
[email protected]
Date
2021-05-05 06:14:26 -0700 (Wed, 05 May 2021)

Log Message

Use WeakHashSet instead of HashSet of raw pointes in Document and SVGDocumentExtensions
https://bugs.webkit.org/show_bug.cgi?id=225390

Reviewed by Antti Koivisto.

Replaced Document's m_documentSuspensionCallbackElements and m_articleElements as well as
SVGDocumentExtensions's m_timeContainers and m_svgFontFaceElements with WeakHashSet.

Also moved m_svgUseElements from Document to SVGDocumentExtensions as a WeakHashSet.

This patch also deletes Document::m_mediaStreamStateChangeElements which was never used,
m_mainArticleElement a WeakPtr instead of a raw pointer, replaces SVGDocumentExtensions's
m_rebuildElements, which is a temporary Vector used during tree mutations, with a Vector
of Refs instead of raw pointers.

No new tests since there should be no observable behavior differences.

* dom/Document.cpp:
(WebCore::Document::~Document): The release assert is moved to ~SVGDocumentExtensions.
(WebCore::Document::resolveStyle):
(WebCore::Document::suspend):
(WebCore::Document::resume):
(WebCore::Document::registerForDocumentSuspensionCallbacks):
(WebCore::Document::unregisterForDocumentSuspensionCallbacks):
(WebCore::Document::addSVGUseElement): Moved to SVGDocumentExtensions.
(WebCore::Document::removeSVGUseElement): Ditto.
(WebCore::Document::registerArticleElement):
(WebCore::Document::unregisterArticleElement):
(WebCore::Document::updateMainArticleElementAfterLayout):
(WebCore::Document::prepareCanvasesForDisplayIfNeeded):
(WebCore::Document::clearCanvasPreparation):
(WebCore::Document::canvasChanged):
(WebCore::Document::canvasDestroyed):
* dom/Document.h:
(WebCore::Document:: const const): Deleted.
* html/HTMLCanvasElement.cpp:
(WebCore::HTMLCanvasElement::~HTMLCanvasElement):
(WebCore::HTMLCanvasElement::didMoveToNewDocument):
(WebCore::HTMLCanvasElement::removedFromAncestor):
* style/StyleResolver.cpp:
(WebCore::Style::Resolver::addCurrentSVGFontFaceRules):
* svg/SVGDocumentExtensions.cpp:
(WebCore::SVGDocumentExtensions::~SVGDocumentExtensions): Moved the release assertion
from ~Document.
(WebCore::SVGDocumentExtensions::addTimeContainer):
(WebCore::SVGDocumentExtensions::removeTimeContainer):
(WebCore::SVGDocumentExtensions::addUseElementWithPendingShadowTreeUpdate): Moved here
Document::addSVGUseElement.
(WebCore::SVGDocumentExtensions::removeUseElementWithPendingShadowTreeUpdate): Ditto.
(WebCore::SVGDocumentExtensions::startAnimations):
(WebCore::SVGDocumentExtensions::pauseAnimations):
(WebCore::SVGDocumentExtensions::unpauseAnimations):
(WebCore::SVGDocumentExtensions::dispatchLoadEventToOutermostSVGElements):
(WebCore::SVGDocumentExtensions::rebuildElements):
(WebCore::SVGDocumentExtensions::clearTargetDependencies):
(WebCore::SVGDocumentExtensions::removeAllElementReferencesForTarget):
(WebCore::SVGDocumentExtensions::registerSVGFontFaceElement):
(WebCore::SVGDocumentExtensions::unregisterSVGFontFaceElement):
* svg/SVGDocumentExtensions.h:
(WebCore::SVGDocumentExtensions::useElementsWithPendingShadowTreeUpdate const): Added.
(WebCore::SVGDocumentExtensions::svgFontFaceElements const):
* svg/SVGUseElement.cpp:
(WebCore::SVGUseElement::insertedIntoAncestor):
(WebCore::SVGUseElement::removedFromAncestor):
(WebCore::SVGUseElement::updateShadowTree):
(WebCore::SVGUseElement::invalidateShadowTree):

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (277012 => 277013)


--- trunk/Source/WebCore/ChangeLog	2021-05-05 12:47:51 UTC (rev 277012)
+++ trunk/Source/WebCore/ChangeLog	2021-05-05 13:14:26 UTC (rev 277013)
@@ -1,3 +1,72 @@
+2021-05-05  Ryosuke Niwa  <[email protected]>
+
+        Use WeakHashSet instead of HashSet of raw pointes in Document and SVGDocumentExtensions
+        https://bugs.webkit.org/show_bug.cgi?id=225390
+
+        Reviewed by Antti Koivisto.
+
+        Replaced Document's m_documentSuspensionCallbackElements and m_articleElements as well as
+        SVGDocumentExtensions's m_timeContainers and m_svgFontFaceElements with WeakHashSet.
+
+        Also moved m_svgUseElements from Document to SVGDocumentExtensions as a WeakHashSet.
+
+        This patch also deletes Document::m_mediaStreamStateChangeElements which was never used,
+        m_mainArticleElement a WeakPtr instead of a raw pointer, replaces SVGDocumentExtensions's
+        m_rebuildElements, which is a temporary Vector used during tree mutations, with a Vector
+        of Refs instead of raw pointers.
+
+        No new tests since there should be no observable behavior differences.
+
+        * dom/Document.cpp:
+        (WebCore::Document::~Document): The release assert is moved to ~SVGDocumentExtensions.
+        (WebCore::Document::resolveStyle):
+        (WebCore::Document::suspend):
+        (WebCore::Document::resume):
+        (WebCore::Document::registerForDocumentSuspensionCallbacks):
+        (WebCore::Document::unregisterForDocumentSuspensionCallbacks):
+        (WebCore::Document::addSVGUseElement): Moved to SVGDocumentExtensions.
+        (WebCore::Document::removeSVGUseElement): Ditto.
+        (WebCore::Document::registerArticleElement):
+        (WebCore::Document::unregisterArticleElement):
+        (WebCore::Document::updateMainArticleElementAfterLayout):
+        (WebCore::Document::prepareCanvasesForDisplayIfNeeded):
+        (WebCore::Document::clearCanvasPreparation):
+        (WebCore::Document::canvasChanged):
+        (WebCore::Document::canvasDestroyed):
+        * dom/Document.h:
+        (WebCore::Document:: const const): Deleted.
+        * html/HTMLCanvasElement.cpp:
+        (WebCore::HTMLCanvasElement::~HTMLCanvasElement):
+        (WebCore::HTMLCanvasElement::didMoveToNewDocument):
+        (WebCore::HTMLCanvasElement::removedFromAncestor):
+        * style/StyleResolver.cpp:
+        (WebCore::Style::Resolver::addCurrentSVGFontFaceRules):
+        * svg/SVGDocumentExtensions.cpp:
+        (WebCore::SVGDocumentExtensions::~SVGDocumentExtensions): Moved the release assertion
+        from ~Document.
+        (WebCore::SVGDocumentExtensions::addTimeContainer):
+        (WebCore::SVGDocumentExtensions::removeTimeContainer):
+        (WebCore::SVGDocumentExtensions::addUseElementWithPendingShadowTreeUpdate): Moved here
+        Document::addSVGUseElement.
+        (WebCore::SVGDocumentExtensions::removeUseElementWithPendingShadowTreeUpdate): Ditto.
+        (WebCore::SVGDocumentExtensions::startAnimations):
+        (WebCore::SVGDocumentExtensions::pauseAnimations):
+        (WebCore::SVGDocumentExtensions::unpauseAnimations):
+        (WebCore::SVGDocumentExtensions::dispatchLoadEventToOutermostSVGElements):
+        (WebCore::SVGDocumentExtensions::rebuildElements):
+        (WebCore::SVGDocumentExtensions::clearTargetDependencies):
+        (WebCore::SVGDocumentExtensions::removeAllElementReferencesForTarget):
+        (WebCore::SVGDocumentExtensions::registerSVGFontFaceElement):
+        (WebCore::SVGDocumentExtensions::unregisterSVGFontFaceElement):
+        * svg/SVGDocumentExtensions.h:
+        (WebCore::SVGDocumentExtensions::useElementsWithPendingShadowTreeUpdate const): Added.
+        (WebCore::SVGDocumentExtensions::svgFontFaceElements const):
+        * svg/SVGUseElement.cpp:
+        (WebCore::SVGUseElement::insertedIntoAncestor):
+        (WebCore::SVGUseElement::removedFromAncestor):
+        (WebCore::SVGUseElement::updateShadowTree):
+        (WebCore::SVGUseElement::invalidateShadowTree):
+
 2021-05-05  Chris Lord  <[email protected]>
 
         OffscreenCanvas should preserve context transform after transferToImageBitmap

Modified: trunk/Source/WebCore/dom/Document.cpp (277012 => 277013)


--- trunk/Source/WebCore/dom/Document.cpp	2021-05-05 12:47:51 UTC (rev 277012)
+++ trunk/Source/WebCore/dom/Document.cpp	2021-05-05 13:14:26 UTC (rev 277013)
@@ -779,7 +779,6 @@
 
     RELEASE_ASSERT_WITH_SECURITY_IMPLICATION(m_listsInvalidatedAtDocument.isEmpty());
     RELEASE_ASSERT_WITH_SECURITY_IMPLICATION(m_collectionsInvalidatedAtDocument.isEmpty());
-    RELEASE_ASSERT_WITH_SECURITY_IMPLICATION(m_svgUseElements.isEmpty());
 
     for (unsigned count : m_nodeListAndCollectionCounts)
         ASSERT_UNUSED(count, !count);
@@ -2007,8 +2006,8 @@
     RenderView::RepaintRegionAccumulator repaintRegionAccumulator(renderView());
 
     // FIXME: Do this update per tree scope.
-    {
-        auto elements = copyToVectorOf<RefPtr<SVGUseElement>>(m_svgUseElements);
+    if (auto* extensions = m_svgExtensions.get()) {
+        auto elements = copyToVectorOf<Ref<SVGUseElement>>(extensions->useElementsWithPendingShadowTreeUpdate());
         // We can't clear m_svgUseElements here because updateShadowTree may end up executing arbitrary scripts
         // which may insert new SVG use elements or remove existing ones inside sync IPC via ImageLoader::updateFromElement.
         for (auto& element : elements)
@@ -5648,8 +5647,8 @@
 
     documentWillBecomeInactive();
 
-    for (auto* element : m_documentSuspensionCallbackElements)
-        element->prepareForDocumentSuspension();
+    for (auto& element : m_documentSuspensionCallbackElements)
+        element.prepareForDocumentSuspension();
 
 #if ASSERT_ENABLED
     // Clear the update flag to be able to check if the viewport arguments update
@@ -5696,7 +5695,7 @@
     if (!m_isSuspended)
         return;
 
-    for (auto* element : copyToVector(m_documentSuspensionCallbackElements))
+    for (auto element : copyToVectorOf<Ref<Element>>(m_documentSuspensionCallbackElements))
         element->resumeFromDocumentSuspension();
 
     if (renderView())
@@ -5726,12 +5725,12 @@
 
 void Document::registerForDocumentSuspensionCallbacks(Element& element)
 {
-    m_documentSuspensionCallbackElements.add(&element);
+    m_documentSuspensionCallbackElements.add(element);
 }
 
 void Document::unregisterForDocumentSuspensionCallbacks(Element& element)
 {
-    m_documentSuspensionCallbackElements.remove(&element);
+    m_documentSuspensionCallbackElements.remove(element);
 }
 
 bool Document::audioPlaybackRequiresUserGesture() const
@@ -6054,18 +6053,6 @@
     return *m_svgExtensions;
 }
 
-void Document::addSVGUseElement(SVGUseElement& element)
-{
-    auto result = m_svgUseElements.add(&element);
-    RELEASE_ASSERT_WITH_SECURITY_IMPLICATION(result.isNewEntry);
-}
-
-void Document::removeSVGUseElement(SVGUseElement& element)
-{
-    m_svgUseElements.remove(&element);
-    // FIXME: Assert that element was in m_svgUseElements once re-entrancy to update style and layout have been removed.
-}
-
 bool Document::hasSVGRootNode() const
 {
     return documentElement() && documentElement()->hasTagName(SVGNames::svgTag);
@@ -8342,12 +8329,12 @@
 
 void Document::registerArticleElement(Element& article)
 {
-    m_articleElements.add(&article);
+    m_articleElements.add(article);
 }
 
 void Document::unregisterArticleElement(Element& article)
 {
-    m_articleElements.remove(&article);
+    m_articleElements.remove(article);
     if (m_mainArticleElement == &article)
         m_mainArticleElement = nullptr;
 }
@@ -8367,29 +8354,29 @@
 
     m_mainArticleElement = nullptr;
 
-    auto numberOfArticles = m_articleElements.size();
+    auto numberOfArticles = m_articleElements.computeSize();
     if (!numberOfArticles || numberOfArticles > maxNumberOfArticlesBeforeIgnoringMainContentArticle)
         return;
 
-    Element* tallestArticle = nullptr;
+    RefPtr<Element> tallestArticle;
     float tallestArticleHeight = 0;
     float tallestArticleWidth = 0;
     float secondTallestArticleHeight = 0;
 
-    for (auto* article : m_articleElements) {
-        auto* box = article->renderBox();
+    for (auto& article : m_articleElements) {
+        auto* box = article.renderBox();
         float height = box ? box->height().toFloat() : 0;
         if (height >= tallestArticleHeight) {
             secondTallestArticleHeight = tallestArticleHeight;
             tallestArticleHeight = height;
             tallestArticleWidth = box ? box->width().toFloat() : 0;
-            tallestArticle = article;
+            tallestArticle = &article;
         } else if (height >= secondTallestArticleHeight)
             secondTallestArticleHeight = height;
     }
 
     if (numberOfArticles == 1) {
-        m_mainArticleElement = tallestArticle;
+        m_mainArticleElement = makeWeakPtr(tallestArticle.get());
         return;
     }
 
@@ -8403,7 +8390,7 @@
     if (tallestArticleWidth * tallestArticleHeight < minimumViewportAreaFactor * (viewportSize.width() * viewportSize.height()).toFloat())
         return;
 
-    m_mainArticleElement = tallestArticle;
+    m_mainArticleElement = makeWeakPtr(tallestArticle.get());
 }
 
 #if ENABLE(RESOURCE_LOAD_STATISTICS)
@@ -8957,7 +8944,9 @@
     // that would mutate our m_canvasesNeedingDisplayPreparation list. It
     // would be nice if this could be enforced to remove the copyToVector.
 
-    for (auto* canvas : copyToVector(m_canvasesNeedingDisplayPreparation)) {
+    auto canvases = copyToVectorOf<Ref<HTMLCanvasElement>>(m_canvasesNeedingDisplayPreparation);
+    m_canvasesNeedingDisplayPreparation.clear();
+    for (auto& canvas : canvases) {
         // However, if they are not in the document body, then they won't
         // be composited and thus don't need preparation. Unfortunately they
         // can't tell at the time they were added to the list, since they
@@ -8964,14 +8953,11 @@
         // could be inserted or removed from the document body afterwards.
         if (!canvas->isInTreeScope())
             continue;
-
-        auto protectedCanvas = makeRef(*canvas);
-        protectedCanvas->prepareForDisplay();
+        canvas->prepareForDisplay();
     }
-    m_canvasesNeedingDisplayPreparation.clear();
 }
 
-void Document::clearCanvasPreparation(HTMLCanvasElement* canvas)
+void Document::clearCanvasPreparation(HTMLCanvasElement& canvas)
 {
     m_canvasesNeedingDisplayPreparation.remove(canvas);
 }
@@ -8978,19 +8964,19 @@
 
 void Document::canvasChanged(CanvasBase& canvasBase, const Optional<FloatRect>&)
 {
-    if (is<HTMLCanvasElement>(canvasBase)) {
-        auto* canvas = downcast<HTMLCanvasElement>(&canvasBase);
-        if (canvas->needsPreparationForDisplay())
-            m_canvasesNeedingDisplayPreparation.add(canvas);
-    }
+    if (!is<HTMLCanvasElement>(canvasBase))
+        return;
+    auto& canvas = downcast<HTMLCanvasElement>(canvasBase);
+    if (canvas.needsPreparationForDisplay())
+        m_canvasesNeedingDisplayPreparation.add(canvas);
 }
 
 void Document::canvasDestroyed(CanvasBase& canvasBase)
 {
-    if (is<HTMLCanvasElement>(canvasBase)) {
-        auto* canvas = downcast<HTMLCanvasElement>(&canvasBase);
-        m_canvasesNeedingDisplayPreparation.remove(canvas);
-    }
+    if (!is<HTMLCanvasElement>(canvasBase))
+        return;
+    auto& canvas = downcast<HTMLCanvasElement>(canvasBase);
+    m_canvasesNeedingDisplayPreparation.remove(canvas);
 }
 
 JSC::VM& Document::vm()

Modified: trunk/Source/WebCore/dom/Document.h (277012 => 277013)


--- trunk/Source/WebCore/dom/Document.h	2021-05-05 12:47:51 UTC (rev 277012)
+++ trunk/Source/WebCore/dom/Document.h	2021-05-05 13:14:26 UTC (rev 277013)
@@ -1150,10 +1150,6 @@
     WEBCORE_EXPORT const SVGDocumentExtensions* svgExtensions();
     WEBCORE_EXPORT SVGDocumentExtensions& accessSVGExtensions();
 
-    void addSVGUseElement(SVGUseElement&);
-    void removeSVGUseElement(SVGUseElement&);
-    HashSet<SVGUseElement*> const svgUseElements() const { return m_svgUseElements; }
-
     void initSecurityContext();
     void initContentSecurityPolicy();
 
@@ -1611,7 +1607,7 @@
     const FrameSelection& selection() const { return m_selection; }
 
     void prepareCanvasesForDisplayIfNeeded();
-    void clearCanvasPreparation(HTMLCanvasElement*);
+    void clearCanvasPreparation(HTMLCanvasElement&);
     void canvasChanged(CanvasBase&, const Optional<FloatRect>&) final;
     void canvasResized(CanvasBase&) final { };
     void canvasDestroyed(CanvasBase&) final;
@@ -1859,12 +1855,11 @@
     RefPtr<XPathEvaluator> m_xpathEvaluator;
 
     std::unique_ptr<SVGDocumentExtensions> m_svgExtensions;
-    HashSet<SVGUseElement*> m_svgUseElements;
 
     // Collection of canvas objects that need to do work after they've
     // rendered but before compositing, for the next frame. The set is
     // cleared after they've been called.
-    HashSet<HTMLCanvasElement*> m_canvasesNeedingDisplayPreparation;
+    WeakHashSet<HTMLCanvasElement> m_canvasesNeedingDisplayPreparation;
 
 #if ENABLE(DARK_MODE_CSS)
     OptionSet<ColorScheme> m_colorScheme;
@@ -1873,7 +1868,7 @@
 
     HashMap<String, RefPtr<HTMLCanvasElement>> m_cssCanvasElements;
 
-    HashSet<Element*> m_documentSuspensionCallbackElements;
+    WeakHashSet<Element> m_documentSuspensionCallbackElements;
 
 #if ENABLE(VIDEO)
     WeakHashSet<HTMLMediaElement> m_mediaElements;
@@ -1884,8 +1879,8 @@
     WeakPtr<HTMLMediaElement> m_mediaElementShowingTextTrack;
 #endif
 
-    Element* m_mainArticleElement { nullptr };
-    HashSet<Element*> m_articleElements;
+    WeakPtr<Element> m_mainArticleElement;
+    WeakHashSet<Element> m_articleElements;
 
     HashSet<VisibilityChangeClient*> m_visibilityStateCallbackClients;
 
@@ -2131,7 +2126,6 @@
     std::unique_ptr<PendingScrollEventTargetList> m_pendingScrollEventTargetList;
 
 #if ENABLE(MEDIA_STREAM)
-    HashSet<HTMLMediaElement*> m_mediaStreamStateChangeElements;
     String m_idHashSalt;
     bool m_hasHadCaptureMediaStreamTrack { false };
 #endif

Modified: trunk/Source/WebCore/html/HTMLCanvasElement.cpp (277012 => 277013)


--- trunk/Source/WebCore/html/HTMLCanvasElement.cpp	2021-05-05 12:47:51 UTC (rev 277012)
+++ trunk/Source/WebCore/html/HTMLCanvasElement.cpp	2021-05-05 13:14:26 UTC (rev 277013)
@@ -155,7 +155,7 @@
     // downcasts the CanvasBase object to HTMLCanvasElement. That invokes virtual methods, which should be
     // avoided in destructors, but works as long as it's done before HTMLCanvasElement destructs completely.
     notifyObserversCanvasDestroyed();
-    document().clearCanvasPreparation(this);
+    document().clearCanvasPreparation(*this);
 
     m_context = nullptr; // Ensure this goes away before the ImageBuffer.
     setImageBuffer(nullptr);
@@ -1055,7 +1055,7 @@
 void HTMLCanvasElement::didMoveToNewDocument(Document& oldDocument, Document& newDocument)
 {
     if (needsPreparationForDisplay()) {
-        oldDocument.clearCanvasPreparation(this);
+        oldDocument.clearCanvasPreparation(*this);
         removeObserver(oldDocument);
         addObserver(newDocument);
     }
@@ -1080,7 +1080,7 @@
 void HTMLCanvasElement::removedFromAncestor(RemovalType removalType, ContainerNode& oldParentOfRemovedTree)
 {
     if (needsPreparationForDisplay() && removalType.disconnectedFromDocument) {
-        oldParentOfRemovedTree.document().clearCanvasPreparation(this);
+        oldParentOfRemovedTree.document().clearCanvasPreparation(*this);
         removeObserver(oldParentOfRemovedTree.document());
     }
 

Modified: trunk/Source/WebCore/style/StyleResolver.cpp (277012 => 277013)


--- trunk/Source/WebCore/style/StyleResolver.cpp	2021-05-05 12:47:51 UTC (rev 277012)
+++ trunk/Source/WebCore/style/StyleResolver.cpp	2021-05-05 13:14:26 UTC (rev 277013)
@@ -130,9 +130,9 @@
 void Resolver::addCurrentSVGFontFaceRules()
 {
     if (m_document.svgExtensions()) {
-        const HashSet<SVGFontFaceElement*>& svgFontFaceElements = m_document.svgExtensions()->svgFontFaceElements();
-        for (auto* svgFontFaceElement : svgFontFaceElements)
-            m_document.fontSelector().addFontFaceRule(svgFontFaceElement->fontFaceRule(), svgFontFaceElement->isInUserAgentShadowTree());
+        auto& svgFontFaceElements = m_document.svgExtensions()->svgFontFaceElements();
+        for (auto& svgFontFaceElement : svgFontFaceElements)
+            m_document.fontSelector().addFontFaceRule(svgFontFaceElement.fontFaceRule(), svgFontFaceElement.isInUserAgentShadowTree());
     }
 }
 

Modified: trunk/Source/WebCore/svg/SVGDocumentExtensions.cpp (277012 => 277013)


--- trunk/Source/WebCore/svg/SVGDocumentExtensions.cpp	2021-05-05 12:47:51 UTC (rev 277012)
+++ trunk/Source/WebCore/svg/SVGDocumentExtensions.cpp	2021-05-05 13:14:26 UTC (rev 277013)
@@ -30,6 +30,7 @@
 #include "Page.h"
 #include "SMILTimeContainer.h"
 #include "SVGElement.h"
+#include "SVGFontFaceElement.h"
 #include "SVGResourcesCache.h"
 #include "SVGSMILElement.h"
 #include "SVGSVGElement.h"
@@ -46,11 +47,14 @@
 {
 }
 
-SVGDocumentExtensions::~SVGDocumentExtensions() = default;
+SVGDocumentExtensions::~SVGDocumentExtensions()
+{
+    RELEASE_ASSERT_WITH_SECURITY_IMPLICATION(m_useElementsWithPendingShadowTreeUpdate.computesEmpty());
+}
 
 void SVGDocumentExtensions::addTimeContainer(SVGSVGElement& element)
 {
-    m_timeContainers.add(&element);
+    m_timeContainers.add(element);
     if (m_areAnimationsPaused)
         element.pauseAnimations();
 }
@@ -57,7 +61,7 @@
 
 void SVGDocumentExtensions::removeTimeContainer(SVGSVGElement& element)
 {
-    m_timeContainers.remove(&element);
+    m_timeContainers.remove(element);
 }
 
 void SVGDocumentExtensions::addResource(const AtomString& id, RenderSVGResourceContainer& resource)
@@ -85,6 +89,20 @@
     return m_resources.get(id);
 }
 
+
+void SVGDocumentExtensions::addUseElementWithPendingShadowTreeUpdate(SVGUseElement& element)
+{
+    auto result = m_useElementsWithPendingShadowTreeUpdate.add(element);
+    RELEASE_ASSERT_WITH_SECURITY_IMPLICATION(result.isNewEntry);
+}
+
+void SVGDocumentExtensions::removeUseElementWithPendingShadowTreeUpdate(SVGUseElement& element)
+{
+    m_useElementsWithPendingShadowTreeUpdate.remove(element);
+    // FIXME: Assert that element was in m_svgUseElements once re-entrancy to update style and layout have been removed.
+}
+
+
 void SVGDocumentExtensions::startAnimations()
 {
     // FIXME: Eventually every "Time Container" will need a way to latch on to some global timer
@@ -91,8 +109,7 @@
     // starting animations for a document will do this "latching"
     // FIXME: We hold a ref pointers to prevent a shadow tree from getting removed out from underneath us.
     // In the future we should refactor the use-element to avoid this. See https://webkit.org/b/53704
-    Vector<RefPtr<SVGSVGElement>> timeContainers;
-    timeContainers.appendRange(m_timeContainers.begin(), m_timeContainers.end());
+    auto timeContainers = copyToVectorOf<Ref<SVGSVGElement>>(m_timeContainers);
     for (auto& element : timeContainers)
         element->timeContainer().begin();
 }
@@ -100,7 +117,7 @@
 void SVGDocumentExtensions::pauseAnimations()
 {
     for (auto& container : m_timeContainers)
-        container->pauseAnimations();
+        container.pauseAnimations();
     m_areAnimationsPaused = true;
 }
 
@@ -107,15 +124,13 @@
 void SVGDocumentExtensions::unpauseAnimations()
 {
     for (auto& container : m_timeContainers)
-        container->unpauseAnimations();
+        container.unpauseAnimations();
     m_areAnimationsPaused = false;
 }
 
 void SVGDocumentExtensions::dispatchLoadEventToOutermostSVGElements()
 {
-    Vector<RefPtr<SVGSVGElement>> timeContainers;
-    timeContainers.appendRange(m_timeContainers.begin(), m_timeContainers.end());
-
+    auto timeContainers = copyToVectorOf<Ref<SVGSVGElement>>(m_timeContainers);
     for (auto& container : timeContainers) {
         if (!container->isOutermostSVGSVGElement())
             continue;
@@ -302,8 +317,8 @@
 
 void SVGDocumentExtensions::rebuildElements()
 {
-    Vector<SVGElement*> shadowRebuildElements = WTFMove(m_rebuildElements);
-    for (auto* element : shadowRebuildElements)
+    auto shadowRebuildElements = std::exchange(m_rebuildElements, { });
+    for (auto& element : shadowRebuildElements)
         element->svgAttributeChanged(SVGNames::hrefAttr);
 }
 
@@ -313,7 +328,7 @@
     if (!referencingElements)
         return;
     for (auto* element : *referencingElements) {
-        m_rebuildElements.append(element);
+        m_rebuildElements.append(*element);
         element->callClearTarget();
     }
 }
@@ -338,18 +353,18 @@
 void SVGDocumentExtensions::removeAllElementReferencesForTarget(SVGElement& referencedElement)
 {
     m_elementDependencies.remove(&referencedElement);
-    m_rebuildElements.removeFirst(&referencedElement);
+    m_rebuildElements.removeFirst(referencedElement);
 }
 
 void SVGDocumentExtensions::registerSVGFontFaceElement(SVGFontFaceElement& element)
 {
-    m_svgFontFaceElements.add(&element);
+    m_svgFontFaceElements.add(element);
 }
 
 void SVGDocumentExtensions::unregisterSVGFontFaceElement(SVGFontFaceElement& element)
 {
-    ASSERT(m_svgFontFaceElements.contains(&element));
-    m_svgFontFaceElements.remove(&element);
+    ASSERT(m_svgFontFaceElements.contains(element));
+    m_svgFontFaceElements.remove(element);
 }
 
 }

Modified: trunk/Source/WebCore/svg/SVGDocumentExtensions.h (277012 => 277013)


--- trunk/Source/WebCore/svg/SVGDocumentExtensions.h	2021-05-05 12:47:51 UTC (rev 277012)
+++ trunk/Source/WebCore/svg/SVGDocumentExtensions.h	2021-05-05 13:14:26 UTC (rev 277013)
@@ -50,6 +50,10 @@
     void removeResource(const AtomString& id);
     RenderSVGResourceContainer* resourceById(const AtomString& id) const;
 
+    void addUseElementWithPendingShadowTreeUpdate(SVGUseElement&);
+    void removeUseElementWithPendingShadowTreeUpdate(SVGUseElement&);
+    const WeakHashSet<SVGUseElement>& useElementsWithPendingShadowTreeUpdate() const { return m_useElementsWithPendingShadowTreeUpdate; }
+
     void startAnimations();
     void pauseAnimations();
     void unpauseAnimations();
@@ -70,14 +74,14 @@
     void clearTargetDependencies(SVGElement&);
     void rebuildElements();
 
-    const HashSet<SVGFontFaceElement*>& svgFontFaceElements() const { return m_svgFontFaceElements; }
+    const WeakHashSet<SVGFontFaceElement>& svgFontFaceElements() const { return m_svgFontFaceElements; }
     void registerSVGFontFaceElement(SVGFontFaceElement&);
     void unregisterSVGFontFaceElement(SVGFontFaceElement&);
 
 private:
     Document& m_document;
-    HashSet<SVGSVGElement*> m_timeContainers; // For SVG 1.2 support this will need to be made more general.
-    HashSet<SVGFontFaceElement*> m_svgFontFaceElements;
+    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.
@@ -84,7 +88,8 @@
     HashMap<SVGElement*, std::unique_ptr<HashSet<SVGElement*>>> m_elementDependencies;
     std::unique_ptr<SVGResourcesCache> m_resourcesCache;
 
-    Vector<SVGElement*> m_rebuildElements;
+    Vector<Ref<SVGElement>> m_rebuildElements;
+    WeakHashSet<SVGUseElement> m_useElementsWithPendingShadowTreeUpdate;
     bool m_areAnimationsPaused;
 
 public:

Modified: trunk/Source/WebCore/svg/SVGUseElement.cpp (277012 => 277013)


--- trunk/Source/WebCore/svg/SVGUseElement.cpp	2021-05-05 12:47:51 UTC (rev 277012)
+++ trunk/Source/WebCore/svg/SVGUseElement.cpp	2021-05-05 13:14:26 UTC (rev 277013)
@@ -99,7 +99,7 @@
     SVGGraphicsElement::insertedIntoAncestor(insertionType, parentOfInsertedTree);
     if (insertionType.connectedToDocument) {
         if (m_shadowTreeNeedsUpdate)
-            document().addSVGUseElement(*this);
+            document().accessSVGExtensions().addUseElementWithPendingShadowTreeUpdate(*this);
         invalidateShadowTree();
         // FIXME: Move back the call to updateExternalDocument() here once notifyFinished is made always async.
         return InsertedIntoAncestorResult::NeedsPostInsertionCallback;
@@ -118,7 +118,7 @@
     // and SVGUseElement::updateExternalDocument which calls invalidateShadowTree().
     if (removalType.disconnectedFromDocument) {
         if (m_shadowTreeNeedsUpdate)
-            document().removeSVGUseElement(*this);
+            document().accessSVGExtensions().removeUseElementWithPendingShadowTreeUpdate(*this);
     }
     SVGGraphicsElement::removedFromAncestor(removalType, oldParentOfRemovedTree);
     if (removalType.disconnectedFromDocument) {
@@ -225,7 +225,7 @@
 
     if (!isConnected())
         return;
-    document().removeSVGUseElement(*this);
+    document().accessSVGExtensions().removeUseElementWithPendingShadowTreeUpdate(*this);
 
     String targetID;
     auto* target = findTarget(&targetID);
@@ -529,7 +529,7 @@
     invalidateStyleAndRenderersForSubtree();
     invalidateDependentShadowTrees();
     if (isConnected())
-        document().addSVGUseElement(*this);
+        document().accessSVGExtensions().addUseElementWithPendingShadowTreeUpdate(*this);
 }
 
 void SVGUseElement::invalidateDependentShadowTrees()
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to