[webkit-changes] cvs commit: WebCore/khtml/xml dom2_traversalimpl.cpp dom_docimpl.cpp dom_docimpl.h dom_nodeimpl.cpp dom_nodeimpl.h

David harrison at opensource.apple.com
Thu Oct 27 16:15:06 PDT 2005


harrison    05/10/27 16:15:06

  Modified:    .        ChangeLog
               khtml/ecma kjs_html.cpp xmlhttprequest.cpp
               khtml/html html_baseimpl.cpp html_baseimpl.h
                        html_objectimpl.cpp
               khtml/xml dom2_traversalimpl.cpp dom_docimpl.cpp
                        dom_docimpl.h dom_nodeimpl.cpp dom_nodeimpl.h
  Log:
          Reviewed by Justin Garcia and Dave Hyatt.
  
          <rdar://problem/4134884> crash trying to forward msg - khtml::RenderBlock::addChildToFlow
  
          Problem was that onunload events were being fired while in the middle of trying to detach, which resulted in updateDocumentsRendering re-attaching the previously detached nodes.  Similar problem with load events while attaching.
  
          Solved by eliminating load and unload for object nodes, pre-sending unload before detach, and sending dom mutation and load events after attaching.
  
          Also, added asserts to catch this problem more easily in the future.
  
          Added test:
          * fast/events/event-targets.html
          Make sure that load and unload events do not fire on certain objects.
  
          * khtml/ecma/kjs_html.cpp:
          (KJS::Image::notifyFinished):
          Use constant string for "load" event name.
          * khtml/ecma/xmlhttprequest.cpp:
          (KJS::XMLHttpRequest::changeState):
          Use constant strings for "load" and "readystatechange" event names.
          * khtml/html/html_baseimpl.cpp:
          (HTMLFrameElementImpl::close):
          (HTMLFrameElementImpl::willRemove):
          (HTMLFrameElementImpl::detach):
          Add willRemove() function.
          * khtml/html/html_baseimpl.h:
          Add willRemove() function.
          * khtml/html/html_objectimpl.cpp:
          (DOM::HTMLObjectElementImpl::attach):
          (DOM::HTMLObjectElementImpl::detach):
          Stop needlessly sending load and unload events for OBJECT elements.
          * khtml/xml/dom2_traversalimpl.cpp:
          (DOM::NodeIteratorImpl::notifyBeforeNodeRemoval):
          Rename local variable from willRemove to removedNode for clarity.
          * khtml/xml/dom_docimpl.cpp:
          (DocumentImpl::DocumentImpl):
          (DocumentImpl::forbidEventDispatch):
          (DocumentImpl::allowEventDispatch):
          (DocumentImpl::eventDispatchForbidden):
          (DocumentImpl::createEvent):
          Add mechanism to prevent event dispatch.
          * khtml/xml/dom_docimpl.h:
          * khtml/xml/dom_nodeimpl.cpp:
          (DOM::NodeImpl::dispatchEvent):
          (DOM::NodeImpl::dispatchGenericEvent):
          (DOM::NodeImpl::dispatchHTMLEvent):
          (DOM::NodeImpl::dispatchWindowEvent):
          (DOM::NodeImpl::dispatchMouseEvent):
          (DOM::NodeImpl::dispatchSimulatedMouseEvent):
          (DOM::NodeImpl::dispatchUIEvent):
          (DOM::NodeImpl::dispatchSubtreeModifiedEvent):
          (DOM::NodeImpl::dispatchKeyEvent):
          (DOM::NodeImpl::dispatchWheelEvent):
          (DOM::NodeImpl::willRemove):
          (DOM::ContainerNodeImpl::insertBefore):
          (DOM::ContainerNodeImpl::replaceChild):
          (DOM::ContainerNodeImpl::willRemove):
          (DOM::ContainerNodeImpl::willRemoveChild):
          (DOM::ContainerNodeImpl::removeChild):
          (DOM::ContainerNodeImpl::removeChildren):
          (DOM::ContainerNodeImpl::appendChild):
          (DOM::ContainerNodeImpl::addChild):
          (DOM::ContainerNodeImpl::dispatchChildInsertedEvents):
          (DOM::ContainerNodeImpl::dispatchChildRemovalEvents):
          Prevent event dispatch during DOM node removals and additions.
          * khtml/xml/dom_nodeimpl.h:
  
  Revision  Changes    Path
  1.306     +69 -0     WebCore/ChangeLog
  
  Index: ChangeLog
  ===================================================================
  RCS file: /cvs/root/WebCore/ChangeLog,v
  retrieving revision 1.305
  retrieving revision 1.306
  diff -u -r1.305 -r1.306
  --- ChangeLog	27 Oct 2005 22:35:50 -0000	1.305
  +++ ChangeLog	27 Oct 2005 23:14:56 -0000	1.306
  @@ -1,5 +1,74 @@
   2005-10-27  David Harrison  <harrison at apple.com>
   
  +        Reviewed by Justin Garcia and Dave Hyatt.
  +
  +        <rdar://problem/4134884> crash trying to forward msg - khtml::RenderBlock::addChildToFlow
  +
  +        Problem was that onunload events were being fired while in the middle of trying to detach, which resulted in updateDocumentsRendering re-attaching the previously detached nodes.  Similar problem with load events while attaching.
  +        
  +        Solved by eliminating load and unload for object nodes, pre-sending unload before detach, and sending dom mutation and load events after attaching.
  +        
  +        Also, added asserts to catch this problem more easily in the future.
  +        
  +        Added test:
  +        * fast/events/event-targets.html
  +        Make sure that load and unload events do not fire on certain objects.
  +        
  +        * khtml/ecma/kjs_html.cpp:
  +        (KJS::Image::notifyFinished):
  +        Use constant string for "load" event name.
  +        * khtml/ecma/xmlhttprequest.cpp:
  +        (KJS::XMLHttpRequest::changeState):
  +        Use constant strings for "load" and "readystatechange" event names.
  +        * khtml/html/html_baseimpl.cpp:
  +        (HTMLFrameElementImpl::close):
  +        (HTMLFrameElementImpl::willRemove):
  +        (HTMLFrameElementImpl::detach):
  +        Add willRemove() function.
  +        * khtml/html/html_baseimpl.h:
  +        Add willRemove() function.
  +        * khtml/html/html_objectimpl.cpp:
  +        (DOM::HTMLObjectElementImpl::attach):
  +        (DOM::HTMLObjectElementImpl::detach):
  +        Stop needlessly sending load and unload events for OBJECT elements.
  +        * khtml/xml/dom2_traversalimpl.cpp:
  +        (DOM::NodeIteratorImpl::notifyBeforeNodeRemoval):
  +        Rename local variable from willRemove to removedNode for clarity.
  +        * khtml/xml/dom_docimpl.cpp:
  +        (DocumentImpl::DocumentImpl):
  +        (DocumentImpl::forbidEventDispatch):
  +        (DocumentImpl::allowEventDispatch):
  +        (DocumentImpl::eventDispatchForbidden):
  +        (DocumentImpl::createEvent):
  +        Add mechanism to prevent event dispatch.
  +        * khtml/xml/dom_docimpl.h:
  +        * khtml/xml/dom_nodeimpl.cpp:
  +        (DOM::NodeImpl::dispatchEvent):
  +        (DOM::NodeImpl::dispatchGenericEvent):
  +        (DOM::NodeImpl::dispatchHTMLEvent):
  +        (DOM::NodeImpl::dispatchWindowEvent):
  +        (DOM::NodeImpl::dispatchMouseEvent):
  +        (DOM::NodeImpl::dispatchSimulatedMouseEvent):
  +        (DOM::NodeImpl::dispatchUIEvent):
  +        (DOM::NodeImpl::dispatchSubtreeModifiedEvent):
  +        (DOM::NodeImpl::dispatchKeyEvent):
  +        (DOM::NodeImpl::dispatchWheelEvent):
  +        (DOM::NodeImpl::willRemove):
  +        (DOM::ContainerNodeImpl::insertBefore):
  +        (DOM::ContainerNodeImpl::replaceChild):
  +        (DOM::ContainerNodeImpl::willRemove):
  +        (DOM::ContainerNodeImpl::willRemoveChild):
  +        (DOM::ContainerNodeImpl::removeChild):
  +        (DOM::ContainerNodeImpl::removeChildren):
  +        (DOM::ContainerNodeImpl::appendChild):
  +        (DOM::ContainerNodeImpl::addChild):
  +        (DOM::ContainerNodeImpl::dispatchChildInsertedEvents):
  +        (DOM::ContainerNodeImpl::dispatchChildRemovalEvents):
  +        Prevent event dispatch during DOM node removals and additions.
  +        * khtml/xml/dom_nodeimpl.h:
  +
  +2005-10-27  David Harrison  <harrison at apple.com>
  +
           Reviewed by Tim Omerick.
   
           <rdar://problem/4251172> AX: Safari crashes on www.mozilla.org with Voice Over - khtml::RenderImage::imageMap
  
  
  
  1.143     +3 -1      WebCore/khtml/ecma/kjs_html.cpp
  
  Index: kjs_html.cpp
  ===================================================================
  RCS file: /cvs/root/WebCore/khtml/ecma/kjs_html.cpp,v
  retrieving revision 1.142
  retrieving revision 1.143
  diff -u -r1.142 -r1.143
  --- kjs_html.cpp	26 Oct 2005 19:44:05 -0000	1.142
  +++ kjs_html.cpp	27 Oct 2005 23:14:59 -0000	1.143
  @@ -27,6 +27,7 @@
   #include "xml/dom2_eventsimpl.h"
   
   #include "xml/dom_textimpl.h"
  +#include "xml/EventNames.h"
   #include "html/html_baseimpl.h"
   #include "html/html_blockimpl.h"
   #include "html/html_canvasimpl.h"
  @@ -66,6 +67,7 @@
   #endif
   
   using namespace DOM::HTMLNames;
  +using namespace DOM::EventNames;
   
   using DOM::DOMString;
   using DOM::DocumentImpl;
  @@ -3720,7 +3722,7 @@
       int ignoreException;
       EventImpl *ev = doc->createEvent("HTMLEvents", ignoreException);
       ev->ref();
  -    ev->initEvent("load", true, true);
  +    ev->initEvent(loadEvent, true, true);
       onLoadListener->handleEventImpl(ev, true);
       ev->deref();
     }
  
  
  
  1.44      +4 -2      WebCore/khtml/ecma/xmlhttprequest.cpp
  
  Index: xmlhttprequest.cpp
  ===================================================================
  RCS file: /cvs/root/WebCore/khtml/ecma/xmlhttprequest.cpp,v
  retrieving revision 1.43
  retrieving revision 1.44
  diff -u -r1.43 -r1.44
  --- xmlhttprequest.cpp	3 Oct 2005 21:12:14 -0000	1.43
  +++ xmlhttprequest.cpp	27 Oct 2005 23:15:00 -0000	1.44
  @@ -28,6 +28,7 @@
   #include "misc/loader.h"
   #include "html/html_documentimpl.h"
   #include "xml/dom2_eventsimpl.h"
  +#include "xml/EventNames.h"
   
   #include "khtml_part.h"
   #include "khtmlview.h"
  @@ -45,6 +46,7 @@
   
   using DOM::DocumentImpl;
   using DOM::EventImpl;
  +using namespace DOM::EventNames;
   
   using khtml::Decoder;
   
  @@ -262,7 +264,7 @@
         int ignoreException;
         EventImpl *ev = doc->createEvent("HTMLEvents", ignoreException);
         ev->ref();
  -      ev->initEvent("readystatechange", true, true);
  +      ev->initEvent(readystatechangeEvent, true, true);
         onReadyStateChangeListener->handleEventImpl(ev, true);
         ev->deref();
       }
  @@ -271,7 +273,7 @@
         int ignoreException;
         EventImpl *ev = doc->createEvent("HTMLEvents", ignoreException);
         ev->ref();
  -      ev->initEvent("load", true, true);
  +      ev->initEvent(loadEvent, true, true);
         onLoadListener->handleEventImpl(ev, true);
         ev->deref();
       }
  
  
  
  1.82      +19 -10    WebCore/khtml/html/html_baseimpl.cpp
  
  Index: html_baseimpl.cpp
  ===================================================================
  RCS file: /cvs/root/WebCore/khtml/html/html_baseimpl.cpp,v
  retrieving revision 1.81
  retrieving revision 1.82
  diff -u -r1.81 -r1.82
  --- html_baseimpl.cpp	3 Oct 2005 21:12:27 -0000	1.81
  +++ html_baseimpl.cpp	27 Oct 2005 23:15:01 -0000	1.82
  @@ -483,7 +483,7 @@
       part->requestFrame(static_cast<RenderFrame*>(m_render), relativeURL.qstring(), m_name.qstring());
   }
   
  -void HTMLFrameElementImpl::detach()
  +void HTMLFrameElementImpl::close()
   {
       KHTMLPart *part = getDocument()->part();
   
  @@ -493,7 +493,25 @@
           if (framePart)
               framePart->frameDetached();
       }
  +}
  +
  +void HTMLFrameElementImpl::willRemove()
  +{
  +    // close the frame and dissociate the renderer, but leave the
  +    // node attached so that frame does not get re-attached before
  +    // actually leaving the document.  see <rdar://problem/4132581>
  +    close();
  +    if (m_render) {
  +        m_render->destroy();
  +        m_render = 0;
  +    }
  +    
  +    HTMLElementImpl::willRemove();
  +}
   
  +void HTMLFrameElementImpl::detach()
  +{
  +    close();
       HTMLElementImpl::detach();
   }
   
  @@ -735,15 +753,6 @@
       HTMLElementImpl::defaultEventHandler(evt);
   }
   
  -void HTMLFrameSetElementImpl::detach()
  -{
  -    if(attached())
  -        // ### send the event when we actually get removed from the doc instead of here
  -        dispatchHTMLEvent(unloadEvent,false,false);
  -
  -    HTMLElementImpl::detach();
  -}
  -
   void HTMLFrameSetElementImpl::recalcStyle( StyleChange ch )
   {
       if (changed() && m_render) {
  
  
  
  1.31      +2 -1      WebCore/khtml/html/html_baseimpl.h
  
  Index: html_baseimpl.h
  ===================================================================
  RCS file: /cvs/root/WebCore/khtml/html/html_baseimpl.h,v
  retrieving revision 1.30
  retrieving revision 1.31
  diff -u -r1.30 -r1.31
  --- html_baseimpl.h	21 Jul 2005 04:10:52 -0000	1.30
  +++ html_baseimpl.h	27 Oct 2005 23:15:01 -0000	1.31
  @@ -102,6 +102,8 @@
     
       virtual void parseMappedAttribute(MappedAttributeImpl *);
       virtual void attach();
  +    void close();
  +    virtual void willRemove();
       virtual void detach();
       virtual bool rendererIsNeeded(khtml::RenderStyle *);
       virtual khtml::RenderObject *createRenderer(RenderArena *, khtml::RenderStyle *);
  @@ -190,7 +192,6 @@
       int totalRows() const { return m_totalRows; }
       int totalCols() const { return m_totalCols; }
       int border() const { return m_border; }
  -    virtual void detach();
   
       virtual void recalcStyle( StyleChange ch );
       
  
  
  
  1.86      +0 -5      WebCore/khtml/html/html_objectimpl.cpp
  
  Index: html_objectimpl.cpp
  ===================================================================
  RCS file: /cvs/root/WebCore/khtml/html/html_objectimpl.cpp,v
  retrieving revision 1.85
  retrieving revision 1.86
  diff -u -r1.85 -r1.86
  --- html_objectimpl.cpp	25 Oct 2005 23:46:24 -0000	1.85
  +++ html_objectimpl.cpp	27 Oct 2005 23:15:01 -0000	1.86
  @@ -756,7 +756,6 @@
                   // this method or recalcStyle (which also calls updateWidget) to be called.
                   needWidgetUpdate = false;
                   static_cast<RenderPartObject*>(m_render)->updateWidget();
  -                dispatchHTMLEvent(loadEvent,false,false);
               } else {
                   needWidgetUpdate = true;
                   setChanged();
  @@ -767,11 +766,7 @@
   
   void HTMLObjectElementImpl::detach()
   {
  -    // Only bother with an unload event if we had a render object.  - dwh
       if (attached() && m_render && !m_useFallbackContent) {
  -        // ### do this when we are actualy removed from document instead
  -        dispatchHTMLEvent(unloadEvent,false,false);
  -        
           // Update the widget the next time we attach (detaching destroys the plugin).
           needWidgetUpdate = true;
       }
  
  
  
  1.14      +12 -12    WebCore/khtml/xml/dom2_traversalimpl.cpp
  
  Index: dom2_traversalimpl.cpp
  ===================================================================
  RCS file: /cvs/root/WebCore/khtml/xml/dom2_traversalimpl.cpp,v
  retrieving revision 1.13
  retrieving revision 1.14
  diff -u -r1.13 -r1.14
  --- dom2_traversalimpl.cpp	3 Oct 2005 21:12:51 -0000	1.13
  +++ dom2_traversalimpl.cpp	27 Oct 2005 23:15:02 -0000	1.14
  @@ -186,36 +186,36 @@
           old->deref();
   }
   
  -void NodeIteratorImpl::notifyBeforeNodeRemoval(NodeImpl *willRemove)
  +void NodeIteratorImpl::notifyBeforeNodeRemoval(NodeImpl *removedNode)
   {
       // Iterator is not affected if the removed node is the reference node and is the root.
       // or if removed node is not the reference node, or the ancestor of the reference node.
  -    if (!willRemove || willRemove == root())
  +    if (!removedNode || removedNode == root())
           return;
  -    bool willRemoveReferenceNode = willRemove == referenceNode();
  -    bool willRemoveReferenceNodeAncestor = referenceNode() && referenceNode()->isAncestor(willRemove);
  +    bool willRemoveReferenceNode = removedNode == referenceNode();
  +    bool willRemoveReferenceNodeAncestor = referenceNode() && referenceNode()->isAncestor(removedNode);
       if (!willRemoveReferenceNode && !willRemoveReferenceNodeAncestor)
           return;
   
       if (pointerBeforeReferenceNode()) {
  -        NodeImpl *node = findNextNode(willRemove);
  +        NodeImpl *node = findNextNode(removedNode);
           if (node) {
               // Move out from under the node being removed if the reference node is
               // a descendant of the node being removed.
               if (willRemoveReferenceNodeAncestor) {
  -                while (node && node->isAncestor(willRemove))
  +                while (node && node->isAncestor(removedNode))
                       node = findNextNode(node);
               }
               if (node)
                   setReferenceNode(node);
           }
           else {
  -            node = findPreviousNode(willRemove);
  +            node = findPreviousNode(removedNode);
               if (node) {
                   // Move out from under the node being removed if the reference node is
                   // a descendant of the node being removed.
                   if (willRemoveReferenceNodeAncestor) {
  -                    while (node && node->isAncestor(willRemove))
  +                    while (node && node->isAncestor(removedNode))
                           node = findPreviousNode(node);
                   }
                   if (node) {
  @@ -229,23 +229,23 @@
           }
       }
       else {
  -        NodeImpl *node = findPreviousNode(willRemove);
  +        NodeImpl *node = findPreviousNode(removedNode);
           if (node) {
               // Move out from under the node being removed if the reference node is
               // a descendant of the node being removed.
               if (willRemoveReferenceNodeAncestor) {
  -                while (node && node->isAncestor(willRemove))
  +                while (node && node->isAncestor(removedNode))
                       node = findPreviousNode(node);
               }
               if (node)
                   setReferenceNode(node);
           }
           else {
  -            node = findNextNode(willRemove);
  +            node = findNextNode(removedNode);
                   // Move out from under the node being removed if the reference node is
                   // a descendant of the node being removed.
                   if (willRemoveReferenceNodeAncestor) {
  -                    while (node && node->isAncestor(willRemove))
  +                    while (node && node->isAncestor(removedNode))
                           node = findPreviousNode(node);
                   }
                   if (node)
  
  
  
  1.264     +21 -0     WebCore/khtml/xml/dom_docimpl.cpp
  
  Index: dom_docimpl.cpp
  ===================================================================
  RCS file: /cvs/root/WebCore/khtml/xml/dom_docimpl.cpp,v
  retrieving revision 1.263
  retrieving revision 1.264
  diff -u -r1.263 -r1.264
  --- dom_docimpl.cpp	27 Oct 2005 22:34:49 -0000	1.263
  +++ dom_docimpl.cpp	27 Oct 2005 23:15:03 -0000	1.264
  @@ -453,6 +453,7 @@
       resetVisitedLinkColor();
       resetActiveLinkColor();
   
  +    m_eventDispatchForbidden = 0;
       m_processingLoadEvent = false;
       m_startTime.restart();
       m_overMinimumLayoutThreshold = false;
  @@ -2379,8 +2380,28 @@
       return m_defaultView;
   }
   
  +void DocumentImpl::forbidEventDispatch()
  +{
  +    m_eventDispatchForbidden += 1;
  +}
  +
  +void DocumentImpl::allowEventDispatch()
  +{
  +    ASSERT(m_eventDispatchForbidden > 0);
  +    m_eventDispatchForbidden -= 1;
  +}
  +
  +bool DocumentImpl::eventDispatchForbidden()
  +{
  +    return m_eventDispatchForbidden > 0;
  +}
  +
   EventImpl *DocumentImpl::createEvent(const DOMString &eventType, int &exceptioncode)
   {
  +    // createEvent ought to be at a time completely separate from DOM modifications that forbidEventDispatch
  +    // (of course, the event _could_ be sent later, but this seems like a good bottleneck)
  +    ASSERT(!eventDispatchForbidden());
  +    
       if (eventType == "UIEvents" || eventType == "UIEvent")
           return new UIEventImpl();
       else if (eventType == "MouseEvents" || eventType == "MouseEvent")
  
  
  
  1.134     +5 -1      WebCore/khtml/xml/dom_docimpl.h
  
  Index: dom_docimpl.h
  ===================================================================
  RCS file: /cvs/root/WebCore/khtml/xml/dom_docimpl.h,v
  retrieving revision 1.133
  retrieving revision 1.134
  diff -u -r1.133 -r1.134
  --- dom_docimpl.h	27 Oct 2005 22:34:50 -0000	1.133
  +++ dom_docimpl.h	27 Oct 2005 23:15:03 -0000	1.134
  @@ -424,6 +424,9 @@
       void detachNodeIterator(NodeIteratorImpl *ni);
       void notifyBeforeNodeRemoval(NodeImpl *n);
       AbstractViewImpl *defaultView() const;
  +    void forbidEventDispatch();
  +    void allowEventDispatch();
  +    bool eventDispatchForbidden();
       EventImpl *createEvent(const DOMString &eventType, int &exceptioncode);
   
       // keep track of what types of event listeners are registered, so we don't
  @@ -672,7 +675,7 @@
       bool m_closeAfterStyleRecalc;
       bool m_usesDescendantRules;
       bool m_usesSiblingRules;
  -
  +    
       DOMString m_title;
       bool m_titleSetExplicitly;
       NodeImpl *m_titleElement;
  @@ -685,6 +688,7 @@
       KWQAccObjectCache* m_accCache;
   #endif
       
  +    int m_eventDispatchForbidden;
       QPtrList<HTMLImageLoader> m_imageLoadEventDispatchSoonList;
       QPtrList<HTMLImageLoader> m_imageLoadEventDispatchingList;
       int m_imageLoadEventTimer;
  
  
  
  1.205     +81 -12    WebCore/khtml/xml/dom_nodeimpl.cpp
  
  Index: dom_nodeimpl.cpp
  ===================================================================
  RCS file: /cvs/root/WebCore/khtml/xml/dom_nodeimpl.cpp,v
  retrieving revision 1.204
  retrieving revision 1.205
  diff -u -r1.204 -r1.205
  --- dom_nodeimpl.cpp	26 Oct 2005 20:44:12 -0000	1.204
  +++ dom_nodeimpl.cpp	27 Oct 2005 23:15:04 -0000	1.205
  @@ -507,6 +507,7 @@
   
   bool NodeImpl::dispatchEvent(EventImpl *evt, int &exceptioncode, bool tempEvent)
   {
  +    assert(!getDocument()->eventDispatchForbidden());
       if (!evt || evt->type().isEmpty()) { 
           exceptioncode = EventException::_EXCEPTION_OFFSET + EventException::UNSPECIFIED_EVENT_TYPE_ERR;
           return false;
  @@ -550,6 +551,7 @@
   
   bool NodeImpl::dispatchGenericEvent( EventImpl *evt, int &/*exceptioncode */)
   {
  +    assert(!getDocument()->eventDispatchForbidden());
       assert(evt->target());
   
       evt->ref();
  @@ -650,12 +652,14 @@
   
   bool NodeImpl::dispatchHTMLEvent(const AtomicString &eventType, bool canBubbleArg, bool cancelableArg)
   {
  +    assert(!getDocument()->eventDispatchForbidden());
       int exceptioncode = 0;
       return dispatchEvent(new EventImpl(eventType, canBubbleArg, cancelableArg), exceptioncode, true);
   }
   
   bool NodeImpl::dispatchWindowEvent(const AtomicString &eventType, bool canBubbleArg, bool cancelableArg)
   {
  +    assert(!getDocument()->eventDispatchForbidden());
       int exceptioncode = 0;
       EventImpl *evt = new EventImpl(eventType, canBubbleArg, cancelableArg);
       evt->ref();
  @@ -696,6 +700,7 @@
   
   bool NodeImpl::dispatchMouseEvent(QMouseEvent *_mouse, const AtomicString &overrideType, int overrideDetail)
   {
  +    assert(!getDocument()->eventDispatchForbidden());
       int detail = overrideDetail; // defaults to 0
       AtomicString eventType;
       if (!overrideType.isEmpty()) {
  @@ -754,6 +759,7 @@
   
   bool NodeImpl::dispatchSimulatedMouseEvent(const AtomicString &eventType)
   {
  +    assert(!getDocument()->eventDispatchForbidden());
       // Like Gecko, we just pass 0 for everything when we make a fake mouse event.
       // Internet Explorer instead gives the current mouse position and state.
       return dispatchMouseEvent(eventType, 0, 0, 0, 0, 0, 0, false, false, false, false);
  @@ -763,6 +769,7 @@
       int clientX, int clientY, int screenX, int screenY,
       bool ctrlKey, bool altKey, bool shiftKey, bool metaKey)
   {
  +    assert(!getDocument()->eventDispatchForbidden());
       if (disabled()) // Don't even send DOM events for disabled controls..
           return true;
   
  @@ -818,6 +825,7 @@
   
   bool NodeImpl::dispatchUIEvent(const AtomicString &eventType, int detail)
   {
  +    assert(!getDocument()->eventDispatchForbidden());
       assert (!( (eventType != DOMFocusInEvent &&
                   eventType != DOMFocusOutEvent &&
                   eventType != DOMActivateEvent)));
  @@ -894,6 +902,10 @@
   
   bool NodeImpl::dispatchSubtreeModifiedEvent(bool sendChildrenChanged)
   {
  +    // forbidder will send this event later
  +    if (getDocument()->eventDispatchForbidden())
  +        return true;
  +
       // FIXME: Pull this whole if clause out of this function.
       if (sendChildrenChanged) {
           notifyNodeListsChildrenChanged();
  @@ -910,6 +922,7 @@
   
   bool NodeImpl::dispatchKeyEvent(QKeyEvent *key)
   {
  +    assert(!getDocument()->eventDispatchForbidden());
       int exceptioncode = 0;
       //kdDebug(6010) << "DOM::NodeImpl: dispatching keyboard event" << endl;
       KeyboardEventImpl *keyboardEventImpl = new KeyboardEventImpl(key, getDocument()->defaultView());
  @@ -930,10 +943,12 @@
   
       keyboardEventImpl->deref();
       return r;
  +
   }
   
   void NodeImpl::dispatchWheelEvent(QWheelEvent *e)
   {
  +    assert(!getDocument()->eventDispatchForbidden());
       if (e->delta() == 0)
           return;
   
  @@ -1241,6 +1256,10 @@
       m_attached = true;
   }
   
  +void NodeImpl::willRemove()
  +{
  +}
  +
   void NodeImpl::detach()
   {
   //    assert(m_attached);
  @@ -1894,6 +1913,7 @@
               return 0;
   
           // Add child in the correct position
  +        getDocument()->forbidEventDispatch();
           if (prev)
               prev->setNextSibling(child);
           else
  @@ -1907,7 +1927,8 @@
           // ### should we detach() it first if it's already attached?
           if (attached() && !child->attached())
               child->attach();
  -
  +        getDocument()->allowEventDispatch();
  +        
           // Dispatch the mutation events
           dispatchChildInsertedEvents(child,exceptioncode);
   
  @@ -1954,6 +1975,7 @@
   
       // Add the new child(ren)
       while (child) {
  +        getDocument()->forbidEventDispatch();
           nextChild = isFragment ? child->nextSibling() : 0;
   
           // If child is already present in the tree, first remove it
  @@ -1976,6 +1998,7 @@
           // ### should we detach() it first if it's already attached?
           if (attached() && !child->attached())
               child->attach();
  +        getDocument()->allowEventDispatch();
   
           // Dispatch the mutation events
           dispatchChildInsertedEvents(child,exceptioncode);
  @@ -1990,6 +2013,28 @@
       return oldChild;
   }
   
  +void ContainerNodeImpl::willRemove()
  +{
  +    for (NodeImpl *n = _first; n != 0; n = n->nextSibling()) {
  +        n->willRemove();
  +    }
  +}
  +
  +int ContainerNodeImpl::willRemoveChild(NodeImpl *child)
  +{
  +    int exceptionCode = 0;
  +
  +    // fire removed from document mutation events.
  +    dispatchChildRemovalEvents(child, exceptionCode);
  +    if (exceptionCode)
  +        return exceptionCode;
  +
  +    if (child->attached())
  +        child->willRemove();
  +    
  +    return 0;
  +}
  +
   NodeImpl *ContainerNodeImpl::removeChild ( NodeImpl *oldChild, int &exceptioncode )
   {
       exceptioncode = 0;
  @@ -2005,9 +2050,12 @@
           exceptioncode = DOMException::NOT_FOUND_ERR;
           return 0;
       }
  +    
  +    // update auxiliary doc info (e.g. iterators) to note that node is being removed
  +    // FIX: This looks redundant with same call from dispatchChildRemovalEvents in willRemoveChild
  +//  getDocument()->notifyBeforeNodeRemoval(oldChild); // ### use events instead
   
  -    // Dispatch pre-removal mutation events
  -    getDocument()->notifyBeforeNodeRemoval(oldChild); // ### use events instead
  +    // dispatch pre-removal mutation events
       if (getDocument()->hasListenerType(DocumentImpl::DOMNODEREMOVED_LISTENER)) {
   	oldChild->dispatchEvent(new MutationEventImpl(DOMNodeRemovedEvent,
   			     true,false,this,DOMString(),DOMString(),DOMString(),0),exceptioncode,true);
  @@ -2015,10 +2063,12 @@
   	    return 0;
       }
   
  -    dispatchChildRemovalEvents(oldChild,exceptioncode);
  +    exceptioncode = willRemoveChild(oldChild);
       if (exceptioncode)
           return 0;
   
  +    getDocument()->forbidEventDispatch();
  +
       // Remove from rendering tree
       if (oldChild->attached())
           oldChild->detach();
  @@ -2039,6 +2089,8 @@
   
       getDocument()->setDocumentChanged(true);
   
  +    getDocument()->allowEventDispatch();
  +
       // Dispatch post-removal mutation events
       dispatchSubtreeModifiedEvent();
   
  @@ -2050,22 +2102,28 @@
       return oldChild;
   }
   
  +// this differs from other remove functions because it forcibly removes all the children,
  +// regardless of read-only status or event exceptions, e.g.
   void ContainerNodeImpl::removeChildren()
   {
  +    NodeImpl *n;
  +    
       if (!_first)
           return;
   
  -    int exceptionCode;
  -    while (NodeImpl *n = _first) {
  +    // do any prep work needed before actually starting to detach
  +    // and remove... e.g. stop loading frames, fire unload events
  +    for (n = _first; n != 0; n = n->nextSibling())
  +        willRemoveChild(n);
  +    
  +    getDocument()->forbidEventDispatch();
  +    while ((n = _first) != 0) {
           NodeImpl *next = n->nextSibling();
           
           n->ref();
   
  -        // Fire removed from document mutation events.
  -        dispatchChildRemovalEvents(n, exceptionCode);
  -
           if (n->attached())
  -	    n->detach();
  +            n->detach();
           n->setPreviousSibling(0);
           n->setNextSibling(0);
           n->setParent(0);
  @@ -2078,6 +2136,7 @@
           _first = next;
       }
       _last = 0;
  +    getDocument()->allowEventDispatch();
       
       // Dispatch a single post-removal mutation event denoting a modified subtree.
       dispatchSubtreeModifiedEvent();
  @@ -2110,6 +2169,7 @@
       NodeImpl *child = isFragment ? newChild->firstChild() : newChild;
   
       while (child) {
  +        getDocument()->forbidEventDispatch();
           nextChild = isFragment ? child->nextSibling() : 0;
   
           // If child is already present in the tree, first remove it
  @@ -2138,7 +2198,9 @@
           // ### should we detach() it first if it's already attached?
           if (attached() && !child->attached())
               child->attach();
  -          
  +        
  +        getDocument()->allowEventDispatch();
  +        
           // Dispatch the mutation events
           dispatchChildInsertedEvents(child,exceptioncode);
   
  @@ -2202,6 +2264,8 @@
       if (getDocument()->isHTMLDocument() && !childAllowed(newChild))
           return 0;
   
  +    getDocument()->forbidEventDispatch();
  +
       // just add it...
       newChild->setParent(this);
   
  @@ -2220,6 +2284,8 @@
           newChild->insertedIntoDocument();
       childrenChanged();
   
  +    getDocument()->allowEventDispatch();
  +    
       if(newChild->nodeType() == Node::ELEMENT_NODE)
           return newChild;
       return this;
  @@ -2489,6 +2555,7 @@
   
   void ContainerNodeImpl::dispatchChildInsertedEvents( NodeImpl *child, int &exceptioncode )
   {
  +    assert(!getDocument()->eventDispatchForbidden());
       if (inDocument())
           child->insertedIntoDocument();
       else
  @@ -2517,8 +2584,10 @@
   // base class for nodes that may have children
   void ContainerNodeImpl::dispatchChildRemovalEvents( NodeImpl *child, int &exceptioncode )
   {
  -    // Dispatch pre-removal mutation events
  +    // update auxiliary doc info (e.g. iterators) to note that node is being removed
       getDocument()->notifyBeforeNodeRemoval(child); // ### use events instead
  +
  +    // dispatch pre-removal mutation events
       if (getDocument()->hasListenerType(DocumentImpl::DOMNODEREMOVED_LISTENER)) {
   	child->dispatchEvent(new MutationEventImpl(DOMNodeRemovedEvent,
   			     true,false,this,DOMString(),DOMString(),DOMString(),0),exceptioncode,true);
  
  
  
  1.111     +3 -0      WebCore/khtml/xml/dom_nodeimpl.h
  
  Index: dom_nodeimpl.h
  ===================================================================
  RCS file: /cvs/root/WebCore/khtml/xml/dom_nodeimpl.h,v
  retrieving revision 1.110
  retrieving revision 1.111
  diff -u -r1.110 -r1.111
  --- dom_nodeimpl.h	26 Oct 2005 20:44:12 -0000	1.110
  +++ dom_nodeimpl.h	27 Oct 2005 23:15:04 -0000	1.111
  @@ -385,6 +385,7 @@
        */
       virtual void detach();
   
  +    virtual void willRemove();
       void createRendererIfNeeded();
       virtual khtml::RenderStyle *styleForRenderer(khtml::RenderObject *parent);
       virtual bool rendererIsNeeded(khtml::RenderStyle *);
  @@ -522,6 +523,8 @@
       virtual bool hasChildNodes (  ) const;
   
       // Other methods (not part of DOM)
  +    void willRemove();
  +    int willRemoveChild(NodeImpl *child);
       void removeChildren();
       void cloneChildNodes(NodeImpl *clone);
   
  
  
  



More information about the webkit-changes mailing list