Changeset 98121 in webkit


Ignore:
Timestamp:
Oct 21, 2011 12:19:56 PM (13 years ago)
Author:
adamk@chromium.org
Message:

[MutationObservers] Implement WebKitMutationObserver.observe for childList changes
https://bugs.webkit.org/show_bug.cgi?id=68955

Patch by Rafael Weinstein <rafaelw@chromium.org> on 2011-10-21
Reviewed by Ryosuke Niwa.

Source/WebCore:

This patch adds a ChildListMutationScope object which manages the coalescing of
multiple child removals and additions within DOM operations into single childList
mutation records.

Note that this patch doesn't cover all the cases which can be coalesced (it only
covers ContainerNode.*, and Node.innerHTML/innerText). A separate bug,
https://bugs.webkit.org/show_bug.cgi?id=70385, has been opened to track the
remaining cases.

Test: fast/mutation/observe-childList.html

  • CMakeLists.txt:
  • GNUmakefile.list.am:
  • WebCore.gypi:
  • WebCore.pro:
  • WebCore.vcproj/WebCore.vcproj:
  • WebCore.xcodeproj/project.pbxproj:
  • dom/ChildListMutationScope.cpp: Added.

(WebCore::ChildListAccumulation::ChildListAccumulation::ChildListAccumulation):
(WebCore::ChildListAccumulation::ChildListAccumulation::~ChildListAccumulation):
(WebCore::ChildListAccumulation::ChildListAccumulation::childAdded):
(WebCore::ChildListAccumulation::ChildListAccumulation::willRemoveChild):
(WebCore::ChildListAccumulation::ChildListAccumulation::dispatch):
(WebCore::ChildListAccumulation::ChildListAccumulation::clear):
(WebCore::ChildListAccumulation::ChildListAccumulation::isEmpty):
(WebCore::ChildListAccumulation::ChildListAccumulator::ChildListAccumulator):
(WebCore::ChildListAccumulation::ChildListAccumulator::~ChildListAccumulator):
(WebCore::ChildListAccumulation::ChildListAccumulator::initialize):
(WebCore::ChildListAccumulation::ChildListAccumulator::instance):
(WebCore::ChildListAccumulation::ChildListAccumulator::childAdded):
(WebCore::ChildListAccumulation::ChildListAccumulator::willRemoveChild):
(WebCore::ChildListAccumulation::ChildListAccumulator::incrementScopingLevel):
(WebCore::ChildListAccumulation::ChildListAccumulator::decrementScopingLevel):
(WebCore::ChildListMutationScope::ChildListMutationScope):
(WebCore::ChildListMutationScope::~ChildListMutationScope):
(WebCore::ChildListMutationScope::childAdded):
(WebCore::ChildListMutationScope::willRemoveChild):

  • dom/ChildListMutationScope.h: Added.
  • dom/ContainerNode.cpp:

(WebCore::ContainerNode::insertBefore):
(WebCore::ContainerNode::replaceChild):
(WebCore::willRemoveChildren):
(WebCore::dispatchChildInsertionEvents):
(WebCore::dispatchChildRemovalEvents):

  • dom/Element.cpp:

(WebCore::enqueueAttributesMutationRecord):

  • dom/Node.cpp:

(WebCore::Node::setTextContent):
(WebCore::Node::registeredMutationObserversOfType):

  • dom/WebKitMutationObserver.cpp:

(WebCore::WebKitMutationObserver::disconnect):

  • html/HTMLElement.cpp:

(WebCore::replaceChildrenWithFragment):
(WebCore::replaceChildrenWithText):

LayoutTests:

  • fast/mutation/observe-attributes-expected.txt:
  • fast/mutation/observe-attributes.html:
  • fast/mutation/observe-childList-expected.txt: Added.
  • fast/mutation/observe-childList.html: Added.
Location:
trunk
Files:
4 added
15 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r98120 r98121  
     12011-10-21  Rafael Weinstein  <rafaelw@chromium.org>
     2
     3        [MutationObservers] Implement WebKitMutationObserver.observe for childList changes
     4        https://bugs.webkit.org/show_bug.cgi?id=68955
     5
     6        Reviewed by Ryosuke Niwa.
     7
     8        * fast/mutation/observe-attributes-expected.txt:
     9        * fast/mutation/observe-attributes.html:
     10        * fast/mutation/observe-childList-expected.txt: Added.
     11        * fast/mutation/observe-childList.html: Added.
     12
    1132011-10-21  Julien Chaffraix  <jchaffraix@webkit.org>
    214
  • trunk/LayoutTests/fast/mutation/observe-attributes-expected.txt

    r97789 r98121  
    2424PASS mutations is null
    2525
    26 Testing that re-observing the same node with the same observing has the effect of resetting the options.
     26Testing that re-observing the same node with the same observer has the effect of resetting the options.
    2727PASS calls is 1
    2828PASS mutations.length is 1
  • trunk/LayoutTests/fast/mutation/observe-attributes.html

    r97925 r98121  
    1111
    1212window.jsTestIsAsync = true;
    13 var mutations;
    14 var mutations2;
     13var mutations, mutations2;
    1514var calls;
    1615
     
    108107
    109108    function start() {
    110         debug('Testing that re-observing the same node with the same observing has the effect of resetting the options.');
     109        debug('Testing that re-observing the same node with the same observer has the effect of resetting the options.');
    111110   
    112111                calls = 0;
  • trunk/Source/WebCore/CMakeLists.txt

    r98069 r98121  
    514514    dom/CharacterData.cpp
    515515    dom/CheckedRadioButtons.cpp
     516    dom/ChildListMutationScope.cpp
    516517    dom/ChildNodeList.cpp
    517518    dom/ClassNodeList.cpp
  • trunk/Source/WebCore/ChangeLog

    r98117 r98121  
     12011-10-21  Rafael Weinstein  <rafaelw@chromium.org>
     2
     3        [MutationObservers] Implement WebKitMutationObserver.observe for childList changes
     4        https://bugs.webkit.org/show_bug.cgi?id=68955
     5
     6        Reviewed by Ryosuke Niwa.
     7
     8        This patch adds a ChildListMutationScope object which manages the coalescing of
     9        multiple child removals and additions within DOM operations into single childList
     10        mutation records.
     11
     12        Note that this patch doesn't cover all the cases which can be coalesced (it only
     13        covers ContainerNode.*, and Node.innerHTML/innerText). A separate bug,
     14        https://bugs.webkit.org/show_bug.cgi?id=70385, has been opened to track the
     15        remaining cases.
     16
     17        Test: fast/mutation/observe-childList.html
     18
     19        * CMakeLists.txt:
     20        * GNUmakefile.list.am:
     21        * WebCore.gypi:
     22        * WebCore.pro:
     23        * WebCore.vcproj/WebCore.vcproj:
     24        * WebCore.xcodeproj/project.pbxproj:
     25        * dom/ChildListMutationScope.cpp: Added.
     26        (WebCore::ChildListAccumulation::ChildListAccumulation::ChildListAccumulation):
     27        (WebCore::ChildListAccumulation::ChildListAccumulation::~ChildListAccumulation):
     28        (WebCore::ChildListAccumulation::ChildListAccumulation::childAdded):
     29        (WebCore::ChildListAccumulation::ChildListAccumulation::willRemoveChild):
     30        (WebCore::ChildListAccumulation::ChildListAccumulation::dispatch):
     31        (WebCore::ChildListAccumulation::ChildListAccumulation::clear):
     32        (WebCore::ChildListAccumulation::ChildListAccumulation::isEmpty):
     33        (WebCore::ChildListAccumulation::ChildListAccumulator::ChildListAccumulator):
     34        (WebCore::ChildListAccumulation::ChildListAccumulator::~ChildListAccumulator):
     35        (WebCore::ChildListAccumulation::ChildListAccumulator::initialize):
     36        (WebCore::ChildListAccumulation::ChildListAccumulator::instance):
     37        (WebCore::ChildListAccumulation::ChildListAccumulator::childAdded):
     38        (WebCore::ChildListAccumulation::ChildListAccumulator::willRemoveChild):
     39        (WebCore::ChildListAccumulation::ChildListAccumulator::incrementScopingLevel):
     40        (WebCore::ChildListAccumulation::ChildListAccumulator::decrementScopingLevel):
     41        (WebCore::ChildListMutationScope::ChildListMutationScope):
     42        (WebCore::ChildListMutationScope::~ChildListMutationScope):
     43        (WebCore::ChildListMutationScope::childAdded):
     44        (WebCore::ChildListMutationScope::willRemoveChild):
     45        * dom/ChildListMutationScope.h: Added.
     46        * dom/ContainerNode.cpp:
     47        (WebCore::ContainerNode::insertBefore):
     48        (WebCore::ContainerNode::replaceChild):
     49        (WebCore::willRemoveChildren):
     50        (WebCore::dispatchChildInsertionEvents):
     51        (WebCore::dispatchChildRemovalEvents):
     52        * dom/Element.cpp:
     53        (WebCore::enqueueAttributesMutationRecord):
     54        * dom/Node.cpp:
     55        (WebCore::Node::setTextContent):
     56        (WebCore::Node::registeredMutationObserversOfType):
     57        * dom/WebKitMutationObserver.cpp:
     58        (WebCore::WebKitMutationObserver::disconnect):
     59        * html/HTMLElement.cpp:
     60        (WebCore::replaceChildrenWithFragment):
     61        (WebCore::replaceChildrenWithText):
     62
    1632011-10-21  Sheriff Bot  <webkit.review.bot@gmail.com>
    264
  • trunk/Source/WebCore/GNUmakefile.list.am

    r98044 r98121  
    11231123        Source/WebCore/dom/CheckedRadioButtons.cpp \
    11241124        Source/WebCore/dom/CheckedRadioButtons.h \
     1125        Source/WebCore/dom/ChildListMutationScope.cpp \
     1126        Source/WebCore/dom/ChildListMutationScope.h \
    11251127        Source/WebCore/dom/ChildNodeList.cpp \
    11261128        Source/WebCore/dom/ChildNodeList.h \
  • trunk/Source/WebCore/WebCore.gypi

    r98044 r98121  
    51285128            'dom/CharacterData.cpp',
    51295129            'dom/CheckedRadioButtons.cpp',
     5130            'dom/ChildListMutationScope.cpp',
     5131            'dom/ChildListMutationScope.h',
    51305132            'dom/ChildNodeList.cpp',
    51315133            'dom/ChildNodeList.h',
  • trunk/Source/WebCore/WebCore.pro

    r98000 r98121  
    466466    dom/CharacterData.cpp \
    467467    dom/CheckedRadioButtons.cpp \
     468    dom/ChildListMutationScope.cpp \
    468469    dom/ChildNodeList.cpp \
    469470    dom/ClassNodeList.cpp \
  • trunk/Source/WebCore/WebCore.vcproj/WebCore.vcproj

    r98044 r98121  
    4387543875                        </File>
    4387643876                        <File
     43877                                RelativePath="..\dom\ChildListMutationScope.cpp"
     43878                                >
     43879                                <FileConfiguration
     43880                                        Name="Debug|Win32"
     43881                                        ExcludedFromBuild="true"
     43882                                        >
     43883                                        <Tool
     43884                                                Name="VCCLCompilerTool"
     43885                                        />
     43886                                </FileConfiguration>
     43887                                <FileConfiguration
     43888                                        Name="Release|Win32"
     43889                                        ExcludedFromBuild="true"
     43890                                        >
     43891                                        <Tool
     43892                                                Name="VCCLCompilerTool"
     43893                                        />
     43894                                </FileConfiguration>
     43895                                <FileConfiguration
     43896                                        Name="Debug_Cairo_CFLite|Win32"
     43897                                        ExcludedFromBuild="true"
     43898                                        >
     43899                                        <Tool
     43900                                                Name="VCCLCompilerTool"
     43901                                        />
     43902                                </FileConfiguration>
     43903                                <FileConfiguration
     43904                                        Name="Release_Cairo_CFLite|Win32"
     43905                                        ExcludedFromBuild="true"
     43906                                        >
     43907                                        <Tool
     43908                                                Name="VCCLCompilerTool"
     43909                                        />
     43910                                </FileConfiguration>
     43911                                <FileConfiguration
     43912                                        Name="Debug_All|Win32"
     43913                                        ExcludedFromBuild="true"
     43914                                        >
     43915                                        <Tool
     43916                                                Name="VCCLCompilerTool"
     43917                                        />
     43918                                </FileConfiguration>
     43919                                <FileConfiguration
     43920                                        Name="Production|Win32"
     43921                                        ExcludedFromBuild="true"
     43922                                        >
     43923                                        <Tool
     43924                                                Name="VCCLCompilerTool"
     43925                                        />
     43926                                </FileConfiguration>
     43927                        </File>
     43928                        <File
     43929                                RelativePath="..\dom\ChildListMutationScope.h"
     43930                                >
     43931                        </File>
     43932                        <File
    4387743933                                RelativePath="..\dom\ChildNodeList.cpp"
    4387843934                                >
  • trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj

    r98044 r98121  
    58085808                D3D4E972130C7CFE007BA540 /* HTMLSummaryElement.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D3D4E970130C7CFE007BA540 /* HTMLSummaryElement.cpp */; };
    58095809                D3D4E973130C7CFE007BA540 /* HTMLSummaryElement.h in Headers */ = {isa = PBXBuildFile; fileRef = D3D4E971130C7CFE007BA540 /* HTMLSummaryElement.h */; };
     5810                D619A307144E00BE004BC302 /* ChildListMutationScope.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D619A305144E00BE004BC302 /* ChildListMutationScope.cpp */; };
     5811                D619A308144E00BE004BC302 /* ChildListMutationScope.h in Headers */ = {isa = PBXBuildFile; fileRef = D619A306144E00BE004BC302 /* ChildListMutationScope.h */; };
    58105812                D70AD65713E1342B005B50B4 /* RenderRegion.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D70AD65513E1342B005B50B4 /* RenderRegion.cpp */; };
    58115813                D70AD65813E1342B005B50B4 /* RenderRegion.h in Headers */ = {isa = PBXBuildFile; fileRef = D70AD65613E1342B005B50B4 /* RenderRegion.h */; };
     
    1314013142                D3D4E970130C7CFE007BA540 /* HTMLSummaryElement.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = HTMLSummaryElement.cpp; sourceTree = "<group>"; };
    1314113143                D3D4E971130C7CFE007BA540 /* HTMLSummaryElement.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HTMLSummaryElement.h; sourceTree = "<group>"; };
     13144                D619A305144E00BE004BC302 /* ChildListMutationScope.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ChildListMutationScope.cpp; sourceTree = "<group>"; };
     13145                D619A306144E00BE004BC302 /* ChildListMutationScope.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ChildListMutationScope.h; sourceTree = "<group>"; };
    1314213146                D70AD65513E1342B005B50B4 /* RenderRegion.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RenderRegion.cpp; sourceTree = "<group>"; };
    1314313147                D70AD65613E1342B005B50B4 /* RenderRegion.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RenderRegion.h; sourceTree = "<group>"; };
     
    2101621020                                93F925420F7EF5B8007E37C9 /* CheckedRadioButtons.cpp */,
    2101721021                                93F925410F7EF5B8007E37C9 /* CheckedRadioButtons.h */,
     21022                                D619A305144E00BE004BC302 /* ChildListMutationScope.cpp */,
     21023                                D619A306144E00BE004BC302 /* ChildListMutationScope.h */,
    2101821024                                A818721A0977D3C0005826D9 /* ChildNodeList.cpp */,
    2101921025                                A81872150977D3C0005826D9 /* ChildNodeList.h */,
     
    2183121837                                A00B721A11DE6428008AB9FF /* CheckedInt.h in Headers */,
    2183221838                                93F925430F7EF5B8007E37C9 /* CheckedRadioButtons.h in Headers */,
     21839                                D619A308144E00BE004BC302 /* ChildListMutationScope.h in Headers */,
    2183321840                                A81872200977D3C0005826D9 /* ChildNodeList.h in Headers */,
    2183421841                                14D823520AF92A790004F057 /* Chrome.h in Headers */,
     
    2518125188                                F55B3DB11251F12D003EF269 /* CheckboxInputType.cpp in Sources */,
    2518225189                                93F925440F7EF5B8007E37C9 /* CheckedRadioButtons.cpp in Sources */,
     25190                                D619A307144E00BE004BC302 /* ChildListMutationScope.cpp in Sources */,
    2518325191                                A81872250977D3C0005826D9 /* ChildNodeList.cpp in Sources */,
    2518425192                                14D8238B0AF92DF60004F057 /* Chrome.cpp in Sources */,
  • trunk/Source/WebCore/dom/ContainerNode.cpp

    r93071 r98121  
    2525
    2626#include "BeforeLoadEvent.h"
    27 #include "MemoryCache.h"
     27#include "ChildListMutationScope.h"
    2828#include "ContainerNodeAlgorithms.h"
    2929#include "DeleteButtonController.h"
     
    3535#include "InlineTextBox.h"
    3636#include "InspectorInstrumentation.h"
     37#include "MemoryCache.h"
    3738#include "MutationEvent.h"
    3839#include "ResourceLoadScheduler.h"
     
    142143        return true;
    143144
     145#if ENABLE(MUTATION_OBSERVERS)
     146    ChildListMutationScope mutation(this);
     147#endif
     148
    144149    RefPtr<Node> next = refChild;
    145150    RefPtr<Node> refChildPreviousSibling = refChild->previousSibling();
     
    273278    }
    274279
     280#if ENABLE(MUTATION_OBSERVERS)
     281    ChildListMutationScope mutation(this);
     282#endif
     283
    275284    RefPtr<Node> prev = oldChild->previousSibling();
    276285    RefPtr<Node> next = oldChild->nextSibling();
     
    401410    collectNodes(container, children);
    402411
     412#if ENABLE(MUTATION_OBSERVERS)
     413    ChildListMutationScope mutation(container);
     414#endif
     415
    403416    for (NodeVector::const_iterator it = children.begin(); it != children.end(); it++) {
    404417        Node* child = it->get();
     
    611624    if (targets.isEmpty())
    612625        return true;
     626
     627#if ENABLE(MUTATION_OBSERVERS)
     628    ChildListMutationScope mutation(this);
     629#endif
    613630
    614631    // Now actually add the child(ren)
     
    10961113    RefPtr<Document> document = child->document();
    10971114
     1115#if ENABLE(MUTATION_OBSERVERS)
     1116    if (c->parentNode()) {
     1117        ChildListMutationScope mutation(c->parentNode());
     1118        mutation.childAdded(c);
     1119    }
     1120#endif
     1121
    10981122    if (c->parentNode() && document->hasListenerType(Document::DOMNODEINSERTED_LISTENER))
    10991123        c->dispatchScopedEvent(MutationEvent::create(eventNames().DOMNodeInsertedEvent, true, c->parentNode()));
     
    11171141    RefPtr<Document> document = child->document();
    11181142
     1143#if ENABLE(MUTATION_OBSERVERS)
     1144    if (c->parentNode()) {
     1145        ChildListMutationScope mutation(c->parentNode());
     1146        mutation.willRemoveChild(c);
     1147    }
     1148#endif
     1149
    11191150    // dispatch pre-removal mutation events
    11201151    if (c->parentNode() && document->hasListenerType(Document::DOMNODEREMOVED_LISTENER))
  • trunk/Source/WebCore/dom/Element.cpp

    r97670 r98121  
    626626
    627627    RefPtr<MutationRecord> mutation = MutationRecord::createAttributes(element, name);
    628     for (Vector<WebKitMutationObserver*>::iterator iter = observers.begin(); iter != observers.end(); ++iter)
    629         (*iter)->enqueueMutationRecord(mutation);
     628    for (size_t i = 0; i < observers.size(); ++i)
     629        observers[i]->enqueueMutationRecord(mutation);
    630630}
    631631#endif
  • trunk/Source/WebCore/dom/Node.cpp

    r97878 r98121  
    2929#include "Attr.h"
    3030#include "Attribute.h"
     31#include "ChildListMutationScope.h"
    3132#include "Chrome.h"
    3233#include "ChromeClient.h"
     
    21312132        case SHADOW_ROOT_NODE: {
    21322133            ContainerNode* container = toContainerNode(this);
     2134#if ENABLE(MUTATION_OBSERVERS)
     2135            ChildListMutationScope mutation(this);
     2136#endif
    21332137            container->removeChildren();
    21342138            if (!text.isEmpty())
     
    27012705        return;
    27022706
    2703     for (Vector<MutationObserverEntry>::iterator iter = observerEntries->begin(); iter != observerEntries->end(); ++iter) {
    2704         if (iter->matches(type))
    2705             observers.append(iter->observer.get());
     2707    for (size_t i = 0; i < observerEntries->size(); ++i) {
     2708        if ((*observerEntries)[i].matches(type))
     2709            observers.append((*observerEntries)[i].observer.get());
    27062710    }
    27072711}
  • trunk/Source/WebCore/dom/WebKitMutationObserver.cpp

    r97714 r98121  
    6666void WebKitMutationObserver::disconnect()
    6767{
    68     for (Vector<Node*>::iterator iter = m_observedNodes.begin(); iter !=  m_observedNodes.end(); ++iter)
    69         (*iter)->unregisterMutationObserver(this);
     68    for (size_t i = 0; i < m_observedNodes.size(); ++i)
     69        m_observedNodes[i]->unregisterMutationObserver(this);
    7070
    7171    m_observedNodes.clear();
  • trunk/Source/WebCore/html/HTMLElement.cpp

    r97551 r98121  
    2828#include "CSSPropertyNames.h"
    2929#include "CSSValueKeywords.h"
     30#include "ChildListMutationScope.h"
    3031#include "DocumentFragment.h"
    3132#include "Event.h"
     
    318319static void replaceChildrenWithFragment(HTMLElement* element, PassRefPtr<DocumentFragment> fragment, ExceptionCode& ec)
    319320{
     321#if ENABLE(MUTATION_OBSERVERS)
     322    ChildListMutationScope mutation(element);
     323#endif
     324
    320325    if (!fragment->firstChild()) {
    321326        element->removeChildren();
     
    339344static void replaceChildrenWithText(HTMLElement* element, const String& text, ExceptionCode& ec)
    340345{
     346#if ENABLE(MUTATION_OBSERVERS)
     347    ChildListMutationScope mutation(element);
     348#endif
     349
    341350    if (hasOneTextChild(element)) {
    342351        static_cast<Text*>(element->firstChild())->setData(text, ec);
Note: See TracChangeset for help on using the changeset viewer.