Changeset 234884 in webkit


Ignore:
Timestamp:
Aug 15, 2018 7:13:06 AM (6 years ago)
Author:
ajuma@chromium.org
Message:

[IntersectionObserver] Do not hold a strong reference to the root element
https://bugs.webkit.org/show_bug.cgi?id=188575

Reviewed by Simon Fraser.

Source/WebCore:

Make IntersectionObserver have only a raw pointer to its root element rather than
a reference, so that an otherwise-unreachable root isn't kept alive. Add logic to
to clear this pointer when the root element gets deleted.

Test: intersection-observer/root-element-deleted.html

  • dom/Element.cpp:

(WebCore::Element::~Element):
(WebCore::Element::disconnectFromIntersectionObservers):
(WebCore::Element::ensureIntersectionObserverData):
(WebCore::Element::intersectionObserverData):

  • dom/Element.h:
  • dom/ElementRareData.cpp:
  • dom/ElementRareData.h:

(WebCore::ElementRareData::intersectionObserverData):
(WebCore::ElementRareData::setIntersectionObserverData):

  • page/IntersectionObserver.cpp:

(WebCore::IntersectionObserver::create):
(WebCore::IntersectionObserver::IntersectionObserver):
(WebCore::IntersectionObserver::~IntersectionObserver):
(WebCore::IntersectionObserver::rootDestroyed):

  • page/IntersectionObserver.h:

(WebCore::IntersectionObserver::root const):

LayoutTests:

  • intersection-observer/root-element-deleted-expected.txt: Added.
  • intersection-observer/root-element-deleted.html: Added.
Location:
trunk
Files:
2 added
8 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r234878 r234884  
     12018-08-15  Ali Juma  <ajuma@chromium.org>
     2
     3        [IntersectionObserver] Do not hold a strong reference to the root element
     4        https://bugs.webkit.org/show_bug.cgi?id=188575
     5
     6        Reviewed by Simon Fraser.
     7
     8        * intersection-observer/root-element-deleted-expected.txt: Added.
     9        * intersection-observer/root-element-deleted.html: Added.
     10
    1112018-08-14  Zalan Bujtas  <zalan@apple.com>
    212
  • trunk/Source/WebCore/ChangeLog

    r234883 r234884  
     12018-08-15  Ali Juma  <ajuma@chromium.org>
     2
     3        [IntersectionObserver] Do not hold a strong reference to the root element
     4        https://bugs.webkit.org/show_bug.cgi?id=188575
     5
     6        Reviewed by Simon Fraser.
     7
     8        Make IntersectionObserver have only a raw pointer to its root element rather than
     9        a reference, so that an otherwise-unreachable root isn't kept alive. Add logic to
     10        to clear this pointer when the root element gets deleted.
     11
     12        Test: intersection-observer/root-element-deleted.html
     13
     14        * dom/Element.cpp:
     15        (WebCore::Element::~Element):
     16        (WebCore::Element::disconnectFromIntersectionObservers):
     17        (WebCore::Element::ensureIntersectionObserverData):
     18        (WebCore::Element::intersectionObserverData):
     19        * dom/Element.h:
     20        * dom/ElementRareData.cpp:
     21        * dom/ElementRareData.h:
     22        (WebCore::ElementRareData::intersectionObserverData):
     23        (WebCore::ElementRareData::setIntersectionObserverData):
     24        * page/IntersectionObserver.cpp:
     25        (WebCore::IntersectionObserver::create):
     26        (WebCore::IntersectionObserver::IntersectionObserver):
     27        (WebCore::IntersectionObserver::~IntersectionObserver):
     28        (WebCore::IntersectionObserver::rootDestroyed):
     29        * page/IntersectionObserver.h:
     30        (WebCore::IntersectionObserver::root const):
     31
    1322018-08-14  Zan Dobersek  <zdobersek@igalia.com>
    233
  • trunk/Source/WebCore/dom/Element.cpp

    r234683 r234884  
    188188    ASSERT(!afterPseudoElement());
    189189
     190#if ENABLE(INTERSECTION_OBSERVER)
     191    disconnectFromIntersectionObservers();
     192#endif
     193
    190194    removeShadowRoot();
    191195
     
    32343238#endif
    32353239
     3240#if ENABLE(INTERSECTION_OBSERVER)
     3241void Element::disconnectFromIntersectionObservers()
     3242{
     3243    auto* observerData = intersectionObserverData();
     3244    if (!observerData)
     3245        return;
     3246
     3247    for (auto* observer : observerData->observers)
     3248        observer->rootDestroyed();
     3249    observerData->observers.clear();
     3250}
     3251
     3252IntersectionObserverData& Element::ensureIntersectionObserverData()
     3253{
     3254    auto& rareData = ensureElementRareData();
     3255    if (!rareData.intersectionObserverData())
     3256        rareData.setIntersectionObserverData(std::make_unique<IntersectionObserverData>());
     3257    return *rareData.intersectionObserverData();
     3258}
     3259
     3260IntersectionObserverData* Element::intersectionObserverData()
     3261{
     3262    return hasRareData() ? elementRareData()->intersectionObserverData() : nullptr;
     3263}
     3264#endif
     3265
    32363266SpellcheckAttributeState Element::spellcheckAttributeState() const
    32373267{
  • trunk/Source/WebCore/dom/Element.h

    r234803 r234884  
    5757struct ElementStyle;
    5858
     59#if ENABLE(INTERSECTION_OBSERVER)
     60struct IntersectionObserverData;
     61#endif
     62
    5963enum SpellcheckAttributeState {
    6064    SpellcheckAttributeTrue,
     
    568572    void setAttributeEventListener(const AtomicString& eventType, const QualifiedName& attributeName, const AtomicString& value);
    569573
     574#if ENABLE(INTERSECTION_OBSERVER)
     575    IntersectionObserverData& ensureIntersectionObserverData();
     576    IntersectionObserverData* intersectionObserverData();
     577#endif
     578
    570579    Element* findAnchorElementForLink(String& outAnchorName);
    571580
     
    645654#if ENABLE(TREE_DEBUGGING)
    646655    void formatForDebugger(char* buffer, unsigned length) const override;
     656#endif
     657
     658#if ENABLE(INTERSECTION_OBSERVER)
     659    void disconnectFromIntersectionObservers();
    647660#endif
    648661
  • trunk/Source/WebCore/dom/ElementRareData.cpp

    r228427 r234884  
    4545    IntPoint savedLayerScrollPosition;
    4646    void* pointers[8];
     47#if ENABLE(INTERSECTION_OBSERVER)
     48    void* intersectionObserverData;
     49#endif
     50
    4751};
    4852
  • trunk/Source/WebCore/dom/ElementRareData.h

    r229537 r234884  
    2525#include "DOMTokenList.h"
    2626#include "DatasetDOMStringMap.h"
     27#include "IntersectionObserver.h"
    2728#include "NamedNodeMap.h"
    2829#include "NodeRareData.h"
     
    116117    bool hasCSSAnimation() const { return m_hasCSSAnimation; }
    117118    void setHasCSSAnimation(bool value) { m_hasCSSAnimation = value; }
     119
     120#if ENABLE(INTERSECTION_OBSERVER)
     121    IntersectionObserverData* intersectionObserverData() { return m_intersectionObserverData.get(); }
     122    void setIntersectionObserverData(std::unique_ptr<IntersectionObserverData>&& data) { m_intersectionObserverData = WTFMove(data); }
     123#endif
    118124
    119125private:
     
    150156    std::unique_ptr<CustomElementReactionQueue> m_customElementReactionQueue;
    151157    std::unique_ptr<NamedNodeMap> m_attributeMap;
     158#if ENABLE(INTERSECTION_OBSERVER)
     159    std::unique_ptr<IntersectionObserverData> m_intersectionObserverData;
     160#endif
    152161
    153162    RefPtr<PseudoElement> m_beforePseudoElement;
  • trunk/Source/WebCore/page/IntersectionObserver.cpp

    r234851 r234884  
    101101    }
    102102
    103     return adoptRef(*new IntersectionObserver(WTFMove(callback), WTFMove(init.root), rootMarginOrException.releaseReturnValue(), WTFMove(thresholds)));
     103    return adoptRef(*new IntersectionObserver(WTFMove(callback), init.root, rootMarginOrException.releaseReturnValue(), WTFMove(thresholds)));
    104104}
    105105
    106 IntersectionObserver::IntersectionObserver(Ref<IntersectionObserverCallback>&& callback, RefPtr<Element>&& root, LengthBox&& parsedRootMargin, Vector<double>&& thresholds)
    107     : m_root(WTFMove(root))
     106IntersectionObserver::IntersectionObserver(Ref<IntersectionObserverCallback>&& callback, Element* root, LengthBox&& parsedRootMargin, Vector<double>&& thresholds)
     107    : m_root(root)
    108108    , m_rootMargin(WTFMove(parsedRootMargin))
    109109    , m_thresholds(WTFMove(thresholds))
    110110    , m_callback(WTFMove(callback))
    111111{
     112    if (m_root) {
     113        auto& observerData = m_root->ensureIntersectionObserverData();
     114        observerData.observers.append(this);
     115    }
     116}
     117
     118IntersectionObserver::~IntersectionObserver()
     119{
     120    if (m_root)
     121        m_root->intersectionObserverData()->observers.removeFirst(this);
    112122}
    113123
     
    146156}
    147157
     158void IntersectionObserver::rootDestroyed()
     159{
     160    ASSERT(m_root);
     161    disconnect();
     162    m_root = nullptr;
     163}
    148164
    149165} // namespace WebCore
  • trunk/Source/WebCore/page/IntersectionObserver.h

    r234818 r234884  
    3939class Element;
    4040
     41struct IntersectionObserverData {
     42    // IntersectionObservers for which the element that owns this IntersectionObserverData is the root.
     43    // The IntersectionObservers are owned by JavaScript wrappers and by IntersectionObserverRegistrations
     44    // for each target currently being observed.
     45    Vector<IntersectionObserver*> observers;
     46
     47    // FIXME: Create and track IntersectionObserverRegistrations.
     48};
     49
    4150class IntersectionObserver : public RefCounted<IntersectionObserver> {
    4251public:
    4352    struct Init {
    44         RefPtr<Element> root;
     53        Element* root { nullptr };
    4554        String rootMargin;
    4655        Variant<double, Vector<double>> threshold;
     
    4857
    4958    static ExceptionOr<Ref<IntersectionObserver>> create(Ref<IntersectionObserverCallback>&&, Init&&);
    50    
    51     Element* root() const { return m_root.get(); }
     59
     60    ~IntersectionObserver();
     61
     62    Element* root() const { return m_root; }
    5263    String rootMargin() const;
    5364    const Vector<double>& thresholds() const { return m_thresholds; }
     
    5970    Vector<RefPtr<IntersectionObserverEntry>> takeRecords();
    6071
     72    void rootDestroyed();
     73
    6174private:
    62     IntersectionObserver(Ref<IntersectionObserverCallback>&&, RefPtr<Element>&& root, LengthBox&& parsedRootMargin, Vector<double>&& thresholds);
     75    IntersectionObserver(Ref<IntersectionObserverCallback>&&, Element* root, LengthBox&& parsedRootMargin, Vector<double>&& thresholds);
    6376   
    64     RefPtr<Element> m_root;
     77    Element* m_root;
    6578    LengthBox m_rootMargin;
    6679    Vector<double> m_thresholds;
Note: See TracChangeset for help on using the changeset viewer.