Changeset 99593 in webkit


Ignore:
Timestamp:
Nov 8, 2011 10:29:54 AM (12 years ago)
Author:
adamk@chromium.org
Message:

Only walk up the tree in search of MutationObservers if one has been added
https://bugs.webkit.org/show_bug.cgi?id=71499

Reviewed by Ojan Vafai.

Source/WebCore:

Analogous to m_listenerTypes, added an m_subtreeMutationObserverTypes field
to Document that keeps track of which observer types have been added.
This allows us to avoid doing any extra work if MutationObservers are
not attached to a document.

This could be improved upon to keep a count of each type, as removing
an observer currently has no effect on m_subtreeMutationObserverTypes.
But that would require a more complex implementation: one counter per
mutation type. And it would be easier to get wrong: if the counter
gets out of sync with the actual state of the DOM, we could start
dropping mutation notifications.

Test: fast/mutation/cross-document.html

  • dom/Document.h:

(WebCore::Document::hasSubtreeMutationObserverOfType):
(WebCore::Document::hasSubtreeMutationObserver):
(WebCore::Document::addSubtreeMutationObserverTypes):

  • dom/MutationObserverRegistration.h:

(WebCore::MutationObserverRegistration::isSubtree):
(WebCore::MutationObserverRegistration::deliveryOptions):
(WebCore::MutationObserverRegistration::mutationTypes):

  • dom/Node.cpp:

(WebCore::Node::didMoveToNewOwnerDocument): Update mutationObserverTypes when a Node is moved to a new document.
(WebCore::Node::getRegisteredMutationObserversOfType): Exit early if it's known that no observers of |type| are registered.
(WebCore::Node::notifyMutationObserversNodeWillDetach): Exit early if it's known no subtree observers of any type are registered.

  • dom/WebKitMutationObserver.cpp:

(WebCore::WebKitMutationObserver::observe): Update mutationObserverTypes when an observation occurs.

  • dom/WebKitMutationObserver.h: Add WebKitMutationObserver::AllMutationTypes to enum

LayoutTests:

Created a basic test showing that MutationObservers
are preserved when a Node switches documents.

  • fast/mutation/cross-document-expected.txt: Added.
  • fast/mutation/cross-document.html: Added.
Location:
trunk
Files:
2 added
8 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r99590 r99593  
     12011-11-08  Adam Klein  <adamk@chromium.org>
     2
     3        Only walk up the tree in search of MutationObservers if one has been added
     4        https://bugs.webkit.org/show_bug.cgi?id=71499
     5
     6        Reviewed by Ojan Vafai.
     7
     8        Created a basic test showing that MutationObservers
     9        are preserved when a Node switches documents.
     10
     11        * fast/mutation/cross-document-expected.txt: Added.
     12        * fast/mutation/cross-document.html: Added.
     13
    1142011-11-08  Ojan Vafai  <ojan@chromium.org>
    215
  • trunk/Source/WebCore/ChangeLog

    r99592 r99593  
     12011-11-08  Adam Klein  <adamk@chromium.org>
     2
     3        Only walk up the tree in search of MutationObservers if one has been added
     4        https://bugs.webkit.org/show_bug.cgi?id=71499
     5
     6        Reviewed by Ojan Vafai.
     7
     8        Analogous to m_listenerTypes, added an m_subtreeMutationObserverTypes field
     9        to Document that keeps track of which observer types have been added.
     10        This allows us to avoid doing any extra work if MutationObservers are
     11        not attached to a document.
     12
     13        This could be improved upon to keep a count of each type, as removing
     14        an observer currently has no effect on m_subtreeMutationObserverTypes.
     15        But that would require a more complex implementation: one counter per
     16        mutation type. And it would be easier to get wrong: if the counter
     17        gets out of sync with the actual state of the DOM, we could start
     18        dropping mutation notifications.
     19
     20        Test: fast/mutation/cross-document.html
     21
     22        * dom/Document.h:
     23        (WebCore::Document::hasSubtreeMutationObserverOfType):
     24        (WebCore::Document::hasSubtreeMutationObserver):
     25        (WebCore::Document::addSubtreeMutationObserverTypes):
     26        * dom/MutationObserverRegistration.h:
     27        (WebCore::MutationObserverRegistration::isSubtree):
     28        (WebCore::MutationObserverRegistration::deliveryOptions):
     29        (WebCore::MutationObserverRegistration::mutationTypes):
     30        * dom/Node.cpp:
     31        (WebCore::Node::didMoveToNewOwnerDocument): Update mutationObserverTypes when a Node is moved to a new document.
     32        (WebCore::Node::getRegisteredMutationObserversOfType): Exit early if it's known that no observers of |type| are registered.
     33        (WebCore::Node::notifyMutationObserversNodeWillDetach): Exit early if it's known no subtree observers of any type are registered.
     34        * dom/WebKitMutationObserver.cpp:
     35        (WebCore::WebKitMutationObserver::observe): Update mutationObserverTypes when an observation occurs.
     36        * dom/WebKitMutationObserver.h: Add WebKitMutationObserver::AllMutationTypes to enum
     37
    1382011-11-08  Andreas Kling  <kling@webkit.org>
    239
  • trunk/Source/WebCore/dom/Document.cpp

    r99579 r99593  
    361361    , m_compatibilityModeLocked(false)
    362362    , m_domTreeVersion(++s_globalTreeVersion)
     363#if ENABLE(MUTATION_OBSERVERS)
     364    , m_subtreeMutationObserverTypes(0)
     365#endif
    363366    , m_styleSheets(StyleSheetList::create(this))
    364367    , m_readyState(Complete)
  • trunk/Source/WebCore/dom/Document.h

    r98724 r99593  
    4747#include "TreeScope.h"
    4848#include "ViewportArguments.h"
     49#include "WebKitMutationObserver.h"
    4950#include <wtf/Deque.h>
    5051#include <wtf/FixedArray.h>
     
    777778    void addListenerTypeIfNeeded(const AtomicString& eventType);
    778779
     780#if ENABLE(MUTATION_OBSERVERS)
     781    bool hasSubtreeMutationObserverOfType(WebKitMutationObserver::MutationType type) const
     782    {
     783        return m_subtreeMutationObserverTypes & type;
     784    }
     785    bool hasSubtreeMutationObserver() const { return m_subtreeMutationObserverTypes; }
     786    void addSubtreeMutationObserverTypes(MutationObserverOptions types) { m_subtreeMutationObserverTypes |= types; }
     787#endif
     788
    779789    CSSStyleDeclaration* getOverrideStyle(Element*, const String& pseudoElt);
    780790
     
    12381248
    12391249    unsigned short m_listenerTypes;
     1250
     1251#if ENABLE(MUTATION_OBSERVERS)
     1252    MutationObserverOptions m_subtreeMutationObserverTypes;
     1253#endif
    12401254
    12411255    RefPtr<StyleSheetList> m_styleSheets; // All of the stylesheets that are currently in effect for our media type and stylesheet set.
  • trunk/Source/WebCore/dom/MutationObserverRegistration.h

    r99338 r99593  
    5454
    5555    bool shouldReceiveMutationFrom(Node*, WebKitMutationObserver::MutationType);
     56    bool isSubtree() const { return m_options & WebKitMutationObserver::Subtree; }
    5657
    5758    WebKitMutationObserver* observer() { return m_observer.get(); }
    58     MutationRecordDeliveryOptions deliveryOptions() { return m_options & (WebKitMutationObserver::AttributeOldValue | WebKitMutationObserver::CharacterDataOldValue); }
     59    MutationRecordDeliveryOptions deliveryOptions() const { return m_options & (WebKitMutationObserver::AttributeOldValue | WebKitMutationObserver::CharacterDataOldValue); }
     60    MutationObserverOptions mutationTypes() const { return m_options & WebKitMutationObserver::AllMutationTypes; }
    5961
    6062private:
  • trunk/Source/WebCore/dom/Node.cpp

    r99338 r99593  
    25452545    ASSERT(!didMoveToNewOwnerDocumentWasCalled);
    25462546    setDidMoveToNewOwnerDocumentWasCalled(true);
     2547
     2548    // FIXME: Event listener types for this node should be set on the new owner document here.
     2549
     2550#if ENABLE(MUTATION_OBSERVERS)
     2551    if (Vector<OwnPtr<MutationObserverRegistration> >* registry = mutationObserverRegistry()) {
     2552        for (size_t i = 0; i < registry->size(); ++i) {
     2553            if (registry->at(i)->isSubtree())
     2554                document()->addSubtreeMutationObserverTypes(registry->at(i)->mutationTypes());
     2555        }
     2556    }
     2557
     2558    if (HashSet<MutationObserverRegistration*>* transientRegistry = transientMutationObserverRegistry()) {
     2559        for (HashSet<MutationObserverRegistration*>::iterator iter = transientRegistry->begin(); iter != transientRegistry->end(); ++iter) {
     2560            if ((*iter)->isSubtree())
     2561                document()->addSubtreeMutationObserverTypes((*iter)->mutationTypes());
     2562        }
     2563    }
     2564#endif
    25472565}
    25482566
     
    27352753void Node::getRegisteredMutationObserversOfType(HashMap<WebKitMutationObserver*, MutationRecordDeliveryOptions>& observers, WebKitMutationObserver::MutationType type)
    27362754{
    2737     for (Node* node = this; node; node = node->parentNode())
     2755    collectMatchingObserversForMutation(observers, this, type);
     2756
     2757    if (!document()->hasSubtreeMutationObserverOfType(type))
     2758        return;
     2759
     2760    for (Node* node = parentNode(); node; node = node->parentNode())
    27382761        collectMatchingObserversForMutation(observers, node, type);
    27392762}
     
    27862809void Node::notifyMutationObserversNodeWillDetach()
    27872810{
     2811    if (!document()->hasSubtreeMutationObserver())
     2812        return;
     2813
    27882814    for (Node* node = parentNode(); node; node = node->parentNode()) {
    27892815        if (Vector<OwnPtr<MutationObserverRegistration> >* registry = node->mutationObserverRegistry()) {
  • trunk/Source/WebCore/dom/WebKitMutationObserver.cpp

    r99338 r99593  
    3535#include "WebKitMutationObserver.h"
    3636
     37#include "Document.h"
    3738#include "MutationCallback.h"
    3839#include "MutationObserverRegistration.h"
     
    6263    MutationObserverRegistration* registration = node->registerMutationObserver(this);
    6364    registration->resetObservation(options);
     65
     66    if (registration->isSubtree())
     67        node->document()->addSubtreeMutationObserverTypes(registration->mutationTypes());
    6468}
    6569
  • trunk/Source/WebCore/dom/WebKitMutationObserver.h

    r99338 r99593  
    5656        ChildList = 1 << 0,
    5757        Attributes = 1 << 1,
    58         CharacterData = 1 << 2
     58        CharacterData = 1 << 2,
     59
     60        AllMutationTypes = ChildList | Attributes | CharacterData
    5961    };
    6062
Note: See TracChangeset for help on using the changeset viewer.