Changeset 73684 in webkit


Ignore:
Timestamp:
Dec 9, 2010 9:08:04 PM (13 years ago)
Author:
rniwa@webkit.org
Message:

2010-12-09 Ryosuke Niwa <rniwa@webkit.org>

Reviewed by Ojan Vafai.

Implemented DOM mutations events as scoped events. A scoped event is an event whose
dispatch is done via ScopedEventQueue. The behavior of the queue is controlled by
EventQueueScope objects (RAII idiom), which increments and decrements the scoping level
on its constructor and destructor respectively.

When the scoping level is 0 (initial level), scoped events are dispatched as soon as
they are enqueued and act like synchronous events. When the scoping level is greater than 0,
however, events are queued in ScopedEventQueue and their dispatches are delayed until
the scoping level goes back to 0 (by the destruction of EventQueueScope).

DOMSubtreeModified, DOMNodeInserted, DOMNodeRemoved, DOMNodeRemovedFromDocument,
DOMNodeInsertedIntoDocument, DOMFocusIn, DOMFocusOut, focusin, and focusout are treated as
scoped events, and a scope object is instantiated in EditCommand::apply to delay dispatches
of the events until the completion of each call of EditCommand::doApply.

Test: fast/events/mutation/execCommands.html

  • Android.mk: Added ScopedEventQueue.cpp.
  • CMakeLists.txt: Ditto.
  • WebCore.pro: Ditto.
  • GNUmakefile.am: Added ScopedEventQueue.cpp and ScopedEventQueue.h.
  • WebCore.gypi: Ditto.
  • WebCore.vcproj/project.vcproj: Ditto.
  • WebCore.xcodeproj/project.pbxproj: Ditto.
  • dom/ContainerNode.cpp: (WebCore::dispatchChildInsertionEvents): Calls dispatchScopedEvent. (WebCore::dispatchChildRemovalEvents): Ditto.
  • dom/DOMAllInOne.cpp: Added ScopedEventQueue.cpp.
  • dom/Element.cpp: (WebCore::Element::dispatchAttrRemovalEvent): Ditto. (WebCore::Element::dispatchAttrAdditionEvent): Ditto.
  • dom/Node.cpp: (WebCore::Node::dispatchScopedEvent): Added. (WebCore::Node::dispatchSubtreeModifiedEvent): Calls dispatchScopedEvent.
  • dom/Node.h:
  • dom/ScopedEventQueue.cpp: Added. (WebCore::ScopedEventQueue::initialize): Added. (WebCore::ScopedEventQueue::enqueueEvent): Added. (WebCore::ScopedEventQueue::dispatchAllEvents): Added. (WebCore::ScopedEventQueue::dispatchEvent): Added. (WebCore::ScopedEventQueue::instance): Added. (WebCore::ScopedEventQueue::incrementScopingLevel): Added. (WebCore::ScopedEventQueue::decrementScopingLevel): Added.
  • dom/ScopedEventQueue.h: Added. (WebCore::ScopedEventQueue::~ScopedEventQueue): Added. (WebCore::ScopedEventQueue::ScopedEventQueue): Added. (WebCore::EventQueueScope::EventQueueScope): Added. (WebCore::EventQueueScope::~EventQueueScope): Added.
  • editing/EditCommand.cpp: (WebCore::EditCommand::apply): Instantiates EventQueueScope.

2010-12-09 Ryosuke Niwa <rniwa@webkit.org>

Reviewed by Ojan Vafai.

Added a test to ensure no DOM mutation events are fired while execCommand is in progress.

  • fast/events/crash-on-mutate-during-drop.html: DOMNodeInserted is fired after BR is detached from the document, and can't be observed. Modify the DOM when text node is inserted.
  • fast/events/mutation: Added.
  • fast/events/mutation/execCommands.html: Added.
Location:
trunk
Files:
5 added
16 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r73681 r73684  
     12010-12-09  Ryosuke Niwa  <rniwa@webkit.org>
     2
     3        Reviewed by Ojan Vafai.
     4
     5        Added a test to ensure no DOM mutation events are fired while execCommand is in progress.
     6
     7        * fast/events/crash-on-mutate-during-drop.html: DOMNodeInserted is fired after BR is detached
     8        from the document, and can't be observed. Modify the DOM when text node is inserted.
     9        * fast/events/mutation: Added.
     10        * fast/events/mutation/execCommands.html: Added.
     11
    1122010-12-09  Abhishek Arya  <inferno@chromium.org>
    213
  • trunk/LayoutTests/fast/events/crash-on-mutate-during-drop.html

    r41403 r73684  
    33<script>
    44function foo() {
    5     if (event.type == "DOMNodeInserted" && event.target.nodeName == "BR")
     5    if (event.type == "DOMNodeInserted" && event.target.nodeType == 3)
    66        document.body.innerHTML = "PASSED";
    77}
     
    1313    window.layoutTestController.dumpAsText();
    1414
    15     document.body.addEventListener("DOMNodeInserted", function() { foo() }, true);
     15    document.addEventListener("DOMNodeInserted", function() { foo() }, true);
    1616
    1717    // Select the element 'dragSource'.
  • trunk/WebCore/Android.mk

    r73535 r73684  
    166166        dom/Range.cpp \
    167167        dom/RegisteredEventListener.cpp \
     168        dom/ScopedEventQueue.cpp \
    168169        dom/ScriptableDocumentParser.cpp \
    169170        dom/ScriptElement.cpp \
  • trunk/WebCore/CMakeLists.txt

    r73672 r73684  
    882882    dom/Range.cpp
    883883    dom/RegisteredEventListener.cpp
     884    dom/ScopedEventQueue.cpp
    884885    dom/ScriptableDocumentParser.cpp
    885886    dom/ScriptElement.cpp
  • trunk/WebCore/ChangeLog

    r73683 r73684  
     12010-12-09  Ryosuke Niwa  <rniwa@webkit.org>
     2
     3        Reviewed by Ojan Vafai.
     4
     5        Implemented DOM mutations events as scoped events. A scoped event is an event whose
     6        dispatch is done via ScopedEventQueue. The behavior of the queue is controlled by
     7        EventQueueScope objects (RAII idiom), which increments and decrements the scoping level
     8        on its constructor and destructor respectively.
     9
     10        When the scoping level is 0 (initial level), scoped events are dispatched as soon as
     11        they are enqueued and act like synchronous events. When the scoping level is greater than 0,
     12        however, events are queued in ScopedEventQueue and their dispatches are delayed until
     13        the scoping level goes back to 0 (by the destruction of EventQueueScope).
     14
     15        DOMSubtreeModified, DOMNodeInserted, DOMNodeRemoved, DOMNodeRemovedFromDocument,
     16        DOMNodeInsertedIntoDocument, DOMFocusIn, DOMFocusOut, focusin, and focusout are treated as
     17        scoped events, and a scope object is instantiated in EditCommand::apply to delay dispatches
     18        of the events until the completion of each call of EditCommand::doApply.
     19
     20        Test: fast/events/mutation/execCommands.html
     21
     22        * Android.mk: Added ScopedEventQueue.cpp.
     23        * CMakeLists.txt: Ditto.
     24        * WebCore.pro: Ditto.
     25        * GNUmakefile.am: Added ScopedEventQueue.cpp and ScopedEventQueue.h.
     26        * WebCore.gypi:  Ditto.
     27        * WebCore.vcproj/project.vcproj: Ditto.
     28        * WebCore.xcodeproj/project.pbxproj: Ditto.
     29        * dom/ContainerNode.cpp:
     30        (WebCore::dispatchChildInsertionEvents): Calls dispatchScopedEvent.
     31        (WebCore::dispatchChildRemovalEvents): Ditto.
     32        * dom/DOMAllInOne.cpp: Added ScopedEventQueue.cpp.
     33        * dom/Element.cpp:
     34        (WebCore::Element::dispatchAttrRemovalEvent): Ditto.
     35        (WebCore::Element::dispatchAttrAdditionEvent): Ditto.
     36        * dom/Node.cpp:
     37        (WebCore::Node::dispatchScopedEvent): Added.
     38        (WebCore::Node::dispatchSubtreeModifiedEvent): Calls dispatchScopedEvent.
     39        * dom/Node.h:
     40        * dom/ScopedEventQueue.cpp: Added.
     41        (WebCore::ScopedEventQueue::initialize): Added.
     42        (WebCore::ScopedEventQueue::enqueueEvent): Added.
     43        (WebCore::ScopedEventQueue::dispatchAllEvents): Added.
     44        (WebCore::ScopedEventQueue::dispatchEvent): Added.
     45        (WebCore::ScopedEventQueue::instance): Added.
     46        (WebCore::ScopedEventQueue::incrementScopingLevel): Added.
     47        (WebCore::ScopedEventQueue::decrementScopingLevel): Added.
     48        * dom/ScopedEventQueue.h: Added.
     49        (WebCore::ScopedEventQueue::~ScopedEventQueue): Added.
     50        (WebCore::ScopedEventQueue::ScopedEventQueue): Added.
     51        (WebCore::EventQueueScope::EventQueueScope): Added.
     52        (WebCore::EventQueueScope::~EventQueueScope): Added.
     53        * editing/EditCommand.cpp:
     54        (WebCore::EditCommand::apply): Instantiates EventQueueScope.
     55
    1562010-12-09  Sam Weinig  <sam@webkit.org>
    257
  • trunk/WebCore/GNUmakefile.am

    r73674 r73684  
    12691269        WebCore/dom/RegisteredEventListener.cpp \
    12701270        WebCore/dom/RegisteredEventListener.h \
     1271        WebCore/dom/ScopedEventQueue.cpp \
     1272        WebCore/dom/ScopedEventQueue.h \
    12711273        WebCore/dom/ScriptableDocumentParser.cpp \
    12721274        WebCore/dom/ScriptableDocumentParser.h \
  • trunk/WebCore/WebCore.gypi

    r73663 r73684  
    13191319            'dom/RegisteredEventListener.cpp',
    13201320            'dom/RegisteredEventListener.h',
     1321            'dom/ScopedEventQueue.cpp',
     1322            'dom/ScopedEventQueue.h',
    13211323            'dom/ScriptableDocumentParser.cpp',
    13221324            'dom/ScriptableDocumentParser.h',
  • trunk/WebCore/WebCore.pro

    r73602 r73684  
    763763    dom/RawDataDocumentParser.h \
    764764    dom/RegisteredEventListener.cpp \
     765    dom/ScopedEventQueue.cpp \
    765766    dom/ScriptableDocumentParser.cpp \
    766767    dom/ScriptElement.cpp \
  • trunk/WebCore/WebCore.vcproj/WebCore.vcproj

    r73535 r73684  
    4531545315                        </File>
    4531645316                        <File
     45317                                RelativePath="..\dom\ScopedEventQueue.cpp"
     45318                                >
     45319                                <FileConfiguration
     45320                                        Name="Debug|Win32"
     45321                                        ExcludedFromBuild="true"
     45322                                        >
     45323                                        <Tool
     45324                                                Name="VCCLCompilerTool"
     45325                                        />
     45326                                </FileConfiguration>
     45327                                <FileConfiguration
     45328                                        Name="Release|Win32"
     45329                                        ExcludedFromBuild="true"
     45330                                        >
     45331                                        <Tool
     45332                                                Name="VCCLCompilerTool"
     45333                                        />
     45334                                </FileConfiguration>
     45335                                <FileConfiguration
     45336                                        Name="Debug_Cairo_CFLite|Win32"
     45337                                        ExcludedFromBuild="true"
     45338                                        >
     45339                                        <Tool
     45340                                                Name="VCCLCompilerTool"
     45341                                        />
     45342                                </FileConfiguration>
     45343                                <FileConfiguration
     45344                                        Name="Release_Cairo_CFLite|Win32"
     45345                                        ExcludedFromBuild="true"
     45346                                        >
     45347                                        <Tool
     45348                                                Name="VCCLCompilerTool"
     45349                                        />
     45350                                </FileConfiguration>
     45351                                <FileConfiguration
     45352                                        Name="Debug_All|Win32"
     45353                                        ExcludedFromBuild="true"
     45354                                        >
     45355                                        <Tool
     45356                                                Name="VCCLCompilerTool"
     45357                                        />
     45358                                </FileConfiguration>
     45359                                <FileConfiguration
     45360                                        Name="Release_LTCG|Win32"
     45361                                        ExcludedFromBuild="true"
     45362                                        >
     45363                                        <Tool
     45364                                                Name="VCCLCompilerTool"
     45365                                        />
     45366                                </FileConfiguration>
     45367                        </File>
     45368                        <File
     45369                                RelativePath="..\dom\ScopedEventQueue.h"
     45370                                >
     45371                        </File>
     45372                        <File
    4531745373                                RelativePath="..\dom\ScriptableDocumentParser.cpp"
    4531845374                                >
  • trunk/WebCore/WebCore.xcodeproj/project.pbxproj

    r73644 r73684  
    30303030                9BAB6C6C12550631001626D4 /* EditingStyle.h in Headers */ = {isa = PBXBuildFile; fileRef = 9BAB6C6A12550631001626D4 /* EditingStyle.h */; settings = {ATTRIBUTES = (Private, ); }; };
    30313031                9BAB6C6D12550631001626D4 /* EditingStyle.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9BAB6C6B12550631001626D4 /* EditingStyle.cpp */; };
     3032                9BD0BF9312A42BF50072FD43 /* ScopedEventQueue.h in Headers */ = {isa = PBXBuildFile; fileRef = 9BD0BF9112A42BF50072FD43 /* ScopedEventQueue.h */; };
     3033                9BD0BF9412A42BF50072FD43 /* ScopedEventQueue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9BD0BF9212A42BF50072FD43 /* ScopedEventQueue.cpp */; };
    30323034                9F0D6B2E121BFEBA006C0288 /* InspectorProfilerAgent.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9F0D6B2C121BFEBA006C0288 /* InspectorProfilerAgent.cpp */; };
    30333035                9F0D6B2F121BFEBA006C0288 /* InspectorProfilerAgent.h in Headers */ = {isa = PBXBuildFile; fileRef = 9F0D6B2D121BFEBA006C0288 /* InspectorProfilerAgent.h */; };
     
    93429344                9BAB6C6A12550631001626D4 /* EditingStyle.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EditingStyle.h; sourceTree = "<group>"; };
    93439345                9BAB6C6B12550631001626D4 /* EditingStyle.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = EditingStyle.cpp; sourceTree = "<group>"; };
     9346                9BD0BF9112A42BF50072FD43 /* ScopedEventQueue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ScopedEventQueue.h; sourceTree = "<group>"; };
     9347                9BD0BF9212A42BF50072FD43 /* ScopedEventQueue.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ScopedEventQueue.cpp; sourceTree = "<group>"; };
    93449348                9F0D6B2C121BFEBA006C0288 /* InspectorProfilerAgent.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = InspectorProfilerAgent.cpp; sourceTree = "<group>"; };
    93459349                9F0D6B2D121BFEBA006C0288 /* InspectorProfilerAgent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InspectorProfilerAgent.h; sourceTree = "<group>"; };
     
    1886118865                                85031B350A44EFC700F992E0 /* RegisteredEventListener.cpp */,
    1886218866                                85031B360A44EFC700F992E0 /* RegisteredEventListener.h */,
     18867                                9BD0BF9212A42BF50072FD43 /* ScopedEventQueue.cpp */,
     18868                                9BD0BF9112A42BF50072FD43 /* ScopedEventQueue.h */,
    1886318869                                A84D82C011D3474800972990 /* ScriptableDocumentParser.cpp */,
    1886418870                                A84D82BF11D3474800972990 /* ScriptableDocumentParser.h */,
     
    2147021476                                1CEFC9B90D78DC8C007D2579 /* SchedulePair.h in Headers */,
    2147121477                                5162C7F511F77EFB00612EFE /* SchemeRegistry.h in Headers */,
     21478                                9BD0BF9312A42BF50072FD43 /* ScopedEventQueue.h in Headers */,
    2147221479                                BCEC01BE0C274DAC009F4EC9 /* Screen.h in Headers */,
    2147321480                                A84D82C111D3474800972990 /* ScriptableDocumentParser.h in Headers */,
     
    2424024247                                1CE24F970D7CAF0E007E04C2 /* SchedulePairMac.mm in Sources */,
    2424124248                                5162C7F411F77EFB00612EFE /* SchemeRegistry.cpp in Sources */,
     24249                                9BD0BF9412A42BF50072FD43 /* ScopedEventQueue.cpp in Sources */,
    2424224250                                BCEC01BD0C274DAC009F4EC9 /* Screen.cpp in Sources */,
    2424324251                                A84D82C211D3474800972990 /* ScriptableDocumentParser.cpp in Sources */,
  • trunk/WebCore/dom/ContainerNode.cpp

    r72259 r73684  
    10281028
    10291029    if (c->parentNode() && document->hasListenerType(Document::DOMNODEINSERTED_LISTENER))
    1030         c->dispatchEvent(MutationEvent::create(eventNames().DOMNodeInsertedEvent, true, c->parentNode()));
     1030        c->dispatchScopedEvent(MutationEvent::create(eventNames().DOMNodeInsertedEvent, true, c->parentNode()));
    10311031
    10321032    // dispatch the DOMNodeInsertedIntoDocument event to all descendants
    10331033    if (c->inDocument() && document->hasListenerType(Document::DOMNODEINSERTEDINTODOCUMENT_LISTENER)) {
    10341034        for (; c; c = c->traverseNextNode(child))
    1035             c->dispatchEvent(MutationEvent::create(eventNames().DOMNodeInsertedIntoDocumentEvent, false));
     1035            c->dispatchScopedEvent(MutationEvent::create(eventNames().DOMNodeInsertedIntoDocumentEvent, false));
    10361036    }
    10371037}
     
    10501050    // dispatch pre-removal mutation events
    10511051    if (c->parentNode() && document->hasListenerType(Document::DOMNODEREMOVED_LISTENER))
    1052         c->dispatchEvent(MutationEvent::create(eventNames().DOMNodeRemovedEvent, true, c->parentNode()));
     1052        c->dispatchScopedEvent(MutationEvent::create(eventNames().DOMNodeRemovedEvent, true, c->parentNode()));
    10531053
    10541054    // dispatch the DOMNodeRemovedFromDocument event to all descendants
    10551055    if (c->inDocument() && document->hasListenerType(Document::DOMNODEREMOVEDFROMDOCUMENT_LISTENER)) {
    10561056        for (; c; c = c->traverseNextNode(child))
    1057             c->dispatchEvent(MutationEvent::create(eventNames().DOMNodeRemovedFromDocumentEvent, false));
     1057            c->dispatchScopedEvent(MutationEvent::create(eventNames().DOMNodeRemovedFromDocumentEvent, false));
    10581058    }
    10591059}
  • trunk/WebCore/dom/DOMAllInOne.cpp

    r71934 r73684  
    101101#include "Range.cpp"
    102102#include "RegisteredEventListener.cpp"
     103#include "ScopedEventQueue.cpp"
    103104#include "ScriptElement.cpp"
    104105#include "ScriptExecutionContext.cpp"
  • trunk/WebCore/dom/Element.cpp

    r73618 r73684  
    12191219        return;
    12201220    ExceptionCode ec = 0;
    1221     dispatchEvent(MutationEvent::create(DOMAttrModifiedEvent, true, attr, attr->value(),
     1221    dispatchScopedEvent(MutationEvent::create(DOMAttrModifiedEvent, true, attr, attr->value(),
    12221222        attr->value(), document()->attrName(attr->id()), MutationEvent::REMOVAL), ec);
    12231223#endif
     
    12321232        return;
    12331233    ExceptionCode ec = 0;
    1234     dispatchEvent(MutationEvent::create(DOMAttrModifiedEvent, true, attr, attr->value(),
     1234    dispatchScopedEvent(MutationEvent::create(DOMAttrModifiedEvent, true, attr, attr->value(),
    12351235        attr->value(), document()->attrName(attr->id()), MutationEvent::ADDITION), ec);
    12361236#endif
  • trunk/WebCore/dom/Node.cpp

    r73618 r73684  
    7171#include "RegisteredEventListener.h"
    7272#include "RenderBox.h"
     73#include "ScopedEventQueue.h"
    7374#include "ScriptController.h"
    7475#include "SelectorNodeList.h"
     
    25802581}
    25812582
     2583void Node::dispatchScopedEvent(PassRefPtr<Event> event)
     2584{
     2585    // We need to set the target here because it can go away by the time we actually fire the event.
     2586    event->setTarget(eventTargetRespectingSVGTargetRules(this));
     2587
     2588    ScopedEventQueue::instance()->enqueueEvent(event);
     2589}
     2590
    25822591static const EventContext* topEventContext(const Vector<EventContext>& ancestors)
    25832592{
     
    26942703        return;
    26952704
    2696     dispatchEvent(MutationEvent::create(eventNames().DOMSubtreeModifiedEvent, true));
     2705    dispatchScopedEvent(MutationEvent::create(eventNames().DOMSubtreeModifiedEvent, true));
    26972706}
    26982707
     
    27042713   
    27052714    bool cancelable = eventType == eventNames().DOMActivateEvent;
    2706    
     2715
    27072716    RefPtr<UIEvent> event = UIEvent::create(eventType, true, cancelable, document()->defaultView(), detail);
    27082717    event->setUnderlyingEvent(underlyingEvent);
    2709     dispatchEvent(event.release());
     2718    dispatchScopedEvent(event.release());
    27102719}
    27112720
  • trunk/WebCore/dom/Node.h

    r73618 r73684  
    521521
    522522    using EventTarget::dispatchEvent;
    523     virtual bool dispatchEvent(PassRefPtr<Event>);
     523    bool dispatchEvent(PassRefPtr<Event>);
     524    void dispatchScopedEvent(PassRefPtr<Event>);
    524525
    525526    bool dispatchGenericEvent(PassRefPtr<Event>);
  • trunk/WebCore/editing/EditCommand.cpp

    r73416 r73684  
    3434#include "EventNames.h"
    3535#include "Frame.h"
     36#include "ScopedEventQueue.h"
    3637#include "SelectionController.h"
    3738#include "VisiblePosition.h"
     
    8586        updateLayout();
    8687
    87     DeleteButtonController* deleteButtonController = frame->editor()->deleteButtonController();
    88     deleteButtonController->disable();
    89     doApply();
    90     deleteButtonController->enable();
     88    {
     89        EventQueueScope scope;
     90        DeleteButtonController* deleteButtonController = frame->editor()->deleteButtonController();
     91        deleteButtonController->disable();
     92        doApply();
     93        deleteButtonController->enable();
     94    }
    9195
    9296    if (isTopLevelCommand()) {
Note: See TracChangeset for help on using the changeset viewer.