[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