2008-12-13 Darin Adler <darin@apple.com>
authordarin@apple.com <darin@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 15 Dec 2008 02:13:51 +0000 (02:13 +0000)
committerdarin@apple.com <darin@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 15 Dec 2008 02:13:51 +0000 (02:13 +0000)
        Reviewed by Sam Weinig.

        - half of https://bugs.webkit.org/show_bug.cgi?id=17425
          eliminate DeprecatedPtrList

        * dom/Document.cpp:
        (WebCore::Document::removeImage): Change to set slots in the vector
        to 0 rather than removing items from a list.
        (WebCore::Document::dispatchImageLoadEventsNow): Rewrite to process
        the list. Since we now use a "set to zero" design, we don't need to
        be careful about where the iterator points while iterating the list,
        instead we just have to skip zeros.

        * dom/Document.h: Use Vector instead of DeprecatedPtrList.

        * dom/EventTargetNode.cpp:
        (WebCore::EventTargetNode::dispatchGenericEvent): Use a Vector instead
        of a DeprecatedPtrList for the list of nodes to handle. Also streamlined
        the logic a bit and used goto in a couple key places.

        * dom/Node.cpp:
        (WebCore::Node::eventParentNode): Moved this function into this file
        because it's a virtual function so already can't be inlined. Also updated
        to return a ContainerNode, so it needs to be in a place where the
        definition of ContainerNode is visible, not the header file.

        * dom/Node.h: Changed return type of eventParentNode to ContainerNode
        and moved its definition into the cpp file.

        * dom/XMLTokenizerLibxml2.cpp:
        (WebCore::PendingCallbacks::~PendingCallbacks): Added a call to
        deleteAllValues here instead of setAutoDelete in the constructor, since
        we're using Deque instead of DeprecatedPtrList.
        (WebCore::PendingCallbacks::callAndRemoveFirstCallback): Changed the
        code to use an OwnPtr since the deque won't delete the callback object.

        * editing/ApplyStyleCommand.cpp:
        (WebCore::ApplyStyleCommand::applyRelativeFontStyleChange): Use a
        Vector instead of a DeprecatedPtrList.

        * svg/SVGElement.cpp:
        (WebCore::SVGElement::eventParentNode): Moved this function into this file
        because it's a virtual function so already can't be inlined. Also updated
        to return a ContainerNode.

        * svg/SVGElement.h: Changed setShadowParentNode to take a ContainerNode*,
        made eventParentNode return a ContainerNode*, and made m_shadowParent a
        ContainerNode*.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@39296 268f45cc-cd09-0410-ab3c-d52691b4dbfc

WebCore/ChangeLog
WebCore/dom/Document.cpp
WebCore/dom/Document.h
WebCore/dom/EventTargetNode.cpp
WebCore/dom/Node.cpp
WebCore/dom/Node.h
WebCore/dom/XMLTokenizerLibxml2.cpp
WebCore/editing/ApplyStyleCommand.cpp
WebCore/svg/SVGElement.cpp
WebCore/svg/SVGElement.h

index 513c934..448953e 100644 (file)
@@ -1,3 +1,54 @@
+2008-12-13  Darin Adler  <darin@apple.com>
+
+        Reviewed by Sam Weinig.
+
+        - half of https://bugs.webkit.org/show_bug.cgi?id=17425
+          eliminate DeprecatedPtrList
+
+        * dom/Document.cpp:
+        (WebCore::Document::removeImage): Change to set slots in the vector
+        to 0 rather than removing items from a list.
+        (WebCore::Document::dispatchImageLoadEventsNow): Rewrite to process
+        the list. Since we now use a "set to zero" design, we don't need to
+        be careful about where the iterator points while iterating the list,
+        instead we just have to skip zeros.
+
+        * dom/Document.h: Use Vector instead of DeprecatedPtrList.
+
+        * dom/EventTargetNode.cpp:
+        (WebCore::EventTargetNode::dispatchGenericEvent): Use a Vector instead
+        of a DeprecatedPtrList for the list of nodes to handle. Also streamlined
+        the logic a bit and used goto in a couple key places.
+
+        * dom/Node.cpp:
+        (WebCore::Node::eventParentNode): Moved this function into this file
+        because it's a virtual function so already can't be inlined. Also updated
+        to return a ContainerNode, so it needs to be in a place where the
+        definition of ContainerNode is visible, not the header file.
+
+        * dom/Node.h: Changed return type of eventParentNode to ContainerNode
+        and moved its definition into the cpp file.
+
+        * dom/XMLTokenizerLibxml2.cpp:
+        (WebCore::PendingCallbacks::~PendingCallbacks): Added a call to
+        deleteAllValues here instead of setAutoDelete in the constructor, since
+        we're using Deque instead of DeprecatedPtrList.
+        (WebCore::PendingCallbacks::callAndRemoveFirstCallback): Changed the
+        code to use an OwnPtr since the deque won't delete the callback object.
+
+        * editing/ApplyStyleCommand.cpp:
+        (WebCore::ApplyStyleCommand::applyRelativeFontStyleChange): Use a
+        Vector instead of a DeprecatedPtrList.
+
+        * svg/SVGElement.cpp:
+        (WebCore::SVGElement::eventParentNode): Moved this function into this file
+        because it's a virtual function so already can't be inlined. Also updated
+        to return a ContainerNode.
+
+        * svg/SVGElement.h: Changed setShadowParentNode to take a ContainerNode*,
+        made eventParentNode return a ContainerNode*, and made m_shadowParent a
+        ContainerNode*.
+
 2008-12-14  Nikolas Zimmermann  <nikolas.zimmermann@torchmobile.com>
 
         Reviewed by George Staikos.
 
 2008-12-10  Simon Fraser  <simon.fraser@apple.com>
 
-        Reviewed by Sam Weinig
+        Reviewed by Sam Weinig.
 
         https://bugs.webkit.org/show_bug.cgi?id=22793
 
index 8f844d4..73895ed 100644 (file)
@@ -2847,32 +2847,36 @@ void Document::removeImage(ImageLoader* image)
 {
     // Remove instances of this image from both lists.
     // Use loops because we allow multiple instances to get into the lists.
-    while (m_imageLoadEventDispatchSoonList.removeRef(image)) { }
-    while (m_imageLoadEventDispatchingList.removeRef(image)) { }
+    size_t size = m_imageLoadEventDispatchSoonList.size();
+    for (size_t i = 0; i < size; ++i) {
+        if (m_imageLoadEventDispatchSoonList[i] == image)
+            m_imageLoadEventDispatchSoonList[i] = 0;
+    }
+    size = m_imageLoadEventDispatchingList.size();
+    for (size_t i = 0; i < size; ++i) {
+        if (m_imageLoadEventDispatchingList[i] == image)
+            m_imageLoadEventDispatchingList[i] = 0;
+    }
     if (m_imageLoadEventDispatchSoonList.isEmpty())
         m_imageLoadEventTimer.stop();
 }
 
 void Document::dispatchImageLoadEventsNow()
 {
-    // need to avoid re-entering this function; if new dispatches are
+    // Need to avoid re-entering this function; if new dispatches are
     // scheduled before the parent finishes processing the list, they
-    // will set a timer and eventually be processed
+    // will set a timer and eventually be processed.
     if (!m_imageLoadEventDispatchingList.isEmpty())
         return;
 
     m_imageLoadEventTimer.stop();
-    
+
     m_imageLoadEventDispatchingList = m_imageLoadEventDispatchSoonList;
     m_imageLoadEventDispatchSoonList.clear();
-    for (DeprecatedPtrListIterator<ImageLoader> it(m_imageLoadEventDispatchingList); it.current();) {
-        ImageLoader* image = it.current();
-        // Must advance iterator *before* dispatching call.
-        // Otherwise, it might be advanced automatically if dispatching the call had a side effect
-        // of destroying the current ImageLoader, and then we would advance past the *next* item,
-        // missing one altogether.
-        ++it;
-        image->dispatchLoadEvent();
+    size_t size = m_imageLoadEventDispatchingList.size();
+    for (size_t i = 0; i < size; ++i) {
+        if (ImageLoader* image = m_imageLoadEventDispatchingList[i])
+            image->dispatchLoadEvent();
     }
     m_imageLoadEventDispatchingList.clear();
 }
index 6eae3fb..a52c428 100644 (file)
@@ -29,7 +29,6 @@
 
 #include "Attr.h"
 #include "Color.h"
-#include "DeprecatedPtrList.h"
 #include "DocumentMarker.h"
 #include "HTMLCollection.h"
 #include "HTMLFormElement.h"
@@ -907,8 +906,8 @@ private:
 
     mutable AXObjectCache* m_axObjectCache;
     
-    DeprecatedPtrList<ImageLoader> m_imageLoadEventDispatchSoonList;
-    DeprecatedPtrList<ImageLoader> m_imageLoadEventDispatchingList;
+    Vector<ImageLoader*> m_imageLoadEventDispatchSoonList;
+    Vector<ImageLoader*> m_imageLoadEventDispatchingList;
     Timer<Document> m_imageLoadEventTimer;
 
     Timer<Document> m_updateFocusAppearanceTimer;
index ef4542c..8553da7 100644 (file)
@@ -273,131 +273,128 @@ bool EventTargetNode::dispatchEvent(PassRefPtr<Event> e, ExceptionCode& ec)
     return dispatchGenericEvent(evt.release(), ec);
 }
 
-bool EventTargetNode::dispatchGenericEvent(PassRefPtr<Event> e, ExceptionCode& ec)
+bool EventTargetNode::dispatchGenericEvent(PassRefPtr<Event> prpEvent, ExceptionCode& ec)
 {
-    RefPtr<Event> evt(e);
+    RefPtr<Event> event(prpEvent);
 
     ASSERT(!eventDispatchForbidden());
-    ASSERT(evt->target());
-    ASSERT(!evt->type().isNull()); // JavaScript code could create an event with an empty name
-
-    // work out what nodes to send event to
-    DeprecatedPtrList<Node> nodeChain;
-
+    ASSERT(event->target());
+    ASSERT(!event->type().isNull()); // JavaScript code can create an event with an empty name, but not null.
+
+    // Make a vector of ancestors to send the event to.
+    // If the node is not in a document just send the event to it.
+    // Be sure to ref all of nodes since event handlers could result in the last reference going away.
+    RefPtr<EventTargetNode> thisNode(this);
+    Vector<RefPtr<ContainerNode> > ancestors;
     if (inDocument()) {
-        for (Node* n = this; n; n = n->eventParentNode()) {
+        for (ContainerNode* ancestor = eventParentNode(); ancestor; ancestor = ancestor->eventParentNode()) {
 #if ENABLE(SVG)
-            // Skip <use> shadow tree elements    
-            if (n->isSVGElement() && n->isShadowNode())
+            // Skip <use> shadow tree elements.
+            if (ancestor->isSVGElement() && ancestor->isShadowNode())
                 continue;
 #endif
-            n->ref();
-            nodeChain.prepend(n);
+            ancestors.append(ancestor);
         }
-    } else {
-        // if node is not in the document just send event to itself 
-        ref();
-        nodeChain.prepend(this);
     }
 
-    DeprecatedPtrListIterator<Node> it(nodeChain);
-
-    // Before we begin dispatching events, give the target node a chance to do some work prior
-    // to the DOM event handlers getting a crack.
-    void* data = preDispatchEventHandler(evt.get());
-
-    // trigger any capturing event handlers on our way down
-    evt->setEventPhase(Event::CAPTURING_PHASE);
-    it.toFirst();
-
-    // Handle window events for capture phase, except load events, this quirk is needed
-    // because Mozilla used to never propagate load events to the window object
-    if (evt->type() != eventNames().loadEvent && it.current()->isDocumentNode() && !evt->propagationStopped())
-        static_cast<Document*>(it.current())->handleWindowEvent(evt.get(), true);
-
-    EventTargetNode* eventTargetNode = 0;
-    for (; it.current() && it.current() != this && !evt->propagationStopped(); ++it) {
-        eventTargetNode = EventTargetNodeCast(it.current());
-        evt->setCurrentTarget(eventTargetRespectingSVGTargetRules(eventTargetNode));
-
-        eventTargetNode->handleLocalEvents(evt.get(), true);
+    // Set up a pointer to indicate whether to dispatch window events.
+    // We don't dispatch load events to the window. That quirk was originally
+    // added because Mozilla doesn't propagate load events to the window object.
+    Document* documentForWindowEvents = 0;
+    if (event->type() != eventNames().loadEvent) {
+        EventTargetNode* topLevelContainer = ancestors.isEmpty() ? this : ancestors.last().get();
+        if (topLevelContainer->isDocumentNode())
+            documentForWindowEvents = static_cast<Document*>(topLevelContainer);
     }
 
-    // dispatch to the actual target node
-    it.toLast();
-
-    if (!evt->propagationStopped()) {
-        evt->setEventPhase(Event::AT_TARGET);
-
-        eventTargetNode = EventTargetNodeCast(it.current());
-        evt->setCurrentTarget(eventTargetRespectingSVGTargetRules(eventTargetNode));
+    // Give the target node a chance to do some work before DOM event handlers get a crack.
+    void* data = preDispatchEventHandler(event.get());
+    if (event->propagationStopped())
+        goto doneDispatching;
 
-        // We do want capturing event listeners to be invoked here, even though
-        // that violates the specification since Mozilla does it.
-        eventTargetNode->handleLocalEvents(evt.get(), true);
+    // Trigger capturing event handlers, starting at the top and working our way down.
+    event->setEventPhase(Event::CAPTURING_PHASE);
 
-        eventTargetNode->handleLocalEvents(evt.get(), false);
+    if (documentForWindowEvents) {
+        event->setCurrentTarget(documentForWindowEvents);
+        documentForWindowEvents->handleWindowEvent(event.get(), true);
+        if (event->propagationStopped())
+            goto doneDispatching;
+    }
+    for (size_t i = ancestors.size(); i; --i) {
+        ContainerNode* ancestor = ancestors[i - 1].get();
+        event->setCurrentTarget(eventTargetRespectingSVGTargetRules(ancestor));
+        ancestor->handleLocalEvents(event.get(), true);
+        if (event->propagationStopped())
+            goto doneDispatching;
     }
 
-    --it;
-
-    // ok, now bubble up again (only non-capturing event handlers will be called)
-    // ### recalculate the node chain here? (e.g. if target node moved in document by previous event handlers)
-    // no. the DOM specs says:
-    // The chain of EventTargets from the event target to the top of the tree
-    // is determined before the initial dispatch of the event.
-    // If modifications occur to the tree during event processing,
-    // event flow will proceed based on the initial state of the tree.
-    //
-    // since the initial dispatch is before the capturing phase,
-    // there's no need to recalculate the node chain.
-    // (tobias)
-
-    if (evt->bubbles()) {
-        evt->setEventPhase(Event::BUBBLING_PHASE);
-
-        for (; it.current() && !evt->propagationStopped() && !evt->cancelBubble(); --it) {
-            eventTargetNode = EventTargetNodeCast(it.current());
-            evt->setCurrentTarget(eventTargetRespectingSVGTargetRules(eventTargetNode));
-
-            eventTargetNode->handleLocalEvents(evt.get(), false);
+    event->setEventPhase(Event::AT_TARGET);
+
+    // We do want capturing event listeners to be invoked here, even though
+    // that violates some versions of the DOM specification; Mozilla does it.
+    event->setCurrentTarget(eventTargetRespectingSVGTargetRules(this));
+    handleLocalEvents(event.get(), true);
+    if (event->propagationStopped())
+        goto doneDispatching;
+    handleLocalEvents(event.get(), false);
+    if (event->propagationStopped())
+        goto doneDispatching;
+
+    if (event->bubbles() && !event->cancelBubble()) {
+        // Trigger bubbling event handlers, starting at the bottom and working our way up.
+        event->setEventPhase(Event::BUBBLING_PHASE);
+
+        size_t size = ancestors.size();
+        for (size_t i = 0; i < size; ++i) {
+            ContainerNode* ancestor = ancestors[i].get();
+            event->setCurrentTarget(eventTargetRespectingSVGTargetRules(ancestor));
+            ancestor->handleLocalEvents(event.get(), false);
+            if (event->propagationStopped() || event->cancelBubble())
+                goto doneDispatching;
+        }
+        if (documentForWindowEvents) {
+            event->setCurrentTarget(documentForWindowEvents);
+            documentForWindowEvents->handleWindowEvent(event.get(), false);
+            if (event->propagationStopped() || event->cancelBubble())
+                goto doneDispatching;
         }
-
-        it.toFirst();
-
-        // Handle window events for bubbling phase, except load events, this quirk is needed
-        // because Mozilla used to never propagate load events at all
-        if (evt->type() != eventNames().loadEvent && it.current()->isDocumentNode() && !evt->propagationStopped() && !evt->cancelBubble()) {
-            evt->setCurrentTarget(EventTargetNodeCast(it.current()));
-            static_cast<Document*>(it.current())->handleWindowEvent(evt.get(), false);
-        } 
     }
 
-    evt->setCurrentTarget(0);
-    evt->setEventPhase(0); // I guess this is correct, the spec does not seem to say
-                           // anything about the default event handler phase.
-
-
-    // Now call the post dispatch.
-    postDispatchEventHandler(evt.get(), data);
-
-    // now we call all default event handlers (this is not part of DOM - it is internal to WebCore)
-    it.toLast();
-
-    if (evt->bubbles())
-        for (; it.current() && !evt->defaultPrevented() && !evt->defaultHandled(); --it)
-            EventTargetNodeCast(it.current())->defaultEventHandler(evt.get());
-    else if (!evt->defaultPrevented() && !evt->defaultHandled())
-        EventTargetNodeCast(it.current())->defaultEventHandler(evt.get());
-
-    // deref all nodes in chain
-    it.toFirst();
-    for (; it.current(); ++it)
-        it.current()->deref(); // this may delete us
+doneDispatching:
+    event->setCurrentTarget(0);
+    event->setEventPhase(0);
+
+    // Pass the data from the preDispatchEventHandler to the postDispatchEventHandler.
+    postDispatchEventHandler(event.get(), data);
+
+    // Call default event handlers. While the DOM does have a concept of preventing
+    // default handling, the detail of which handlers are called is an internal
+    // implementation detail and not part of the DOM.
+    if (!event->defaultPrevented() && !event->defaultHandled()) {
+        // Non-bubbling events call only one default event handler, the one for the target.
+        defaultEventHandler(event.get());
+        ASSERT(!event->defaultPrevented());
+        if (event->defaultHandled())
+            goto doneWithDefault;
+        // For bubbling events, call default event handlers on the same targets in the
+        // same order as the bubbling phase.
+        if (event->bubbles()) {
+            size_t size = ancestors.size();
+            for (size_t i = 0; i < size; ++i) {
+                ContainerNode* ancestor = ancestors[i].get();
+                ancestor->defaultEventHandler(event.get());
+                ASSERT(!event->defaultPrevented());
+                if (event->defaultHandled())
+                    goto doneWithDefault;
+            }
+        }
+    }
 
+doneWithDefault:
     Document::updateDocumentsRendering();
 
-    return !evt->defaultPrevented(); // ### what if defaultPrevented was called before dispatchEvent?
+    return !event->defaultPrevented();
 }
 
 bool EventTargetNode::dispatchSubtreeModifiedEvent()
index a5b482b..d6eb402 100644 (file)
@@ -1916,6 +1916,13 @@ void Node::getSubresourceURLs(ListHashSet<KURL>& urls) const
     addSubresourceAttributeURLs(urls);
 }
 
+ContainerNode* Node::eventParentNode()
+{
+    Node* parent = parentNode();
+    ASSERT(!parent || parent->isContainerNode());
+    return static_cast<ContainerNode*>(parent);
+}
+
 // --------
 
 } // namespace WebCore
index e1259b6..9e0d1f1 100644 (file)
@@ -184,7 +184,7 @@ public:
     bool isInShadowTree();
 
     // The node's parent for the purpose of event capture and bubbling.
-    virtual Node* eventParentNode() { return parentNode(); }
+    virtual ContainerNode* eventParentNode();
 
     bool isBlockFlow() const;
     bool isBlockFlowOrBlockTable() const;
index 5ea0836..6f5e1cf 100644 (file)
 #include <libxslt/xslt.h>
 #endif
 
-
 using namespace std;
 
 namespace WebCore {
 
-class PendingCallbacks {
+class PendingCallbacks : Noncopyable {
 public:
-    PendingCallbacks()
+    ~PendingCallbacks()
     {
-        m_callbacks.setAutoDelete(true);
+        deleteAllValues(m_callbacks);
     }
     
     void appendStartElementNSCallback(const xmlChar* xmlLocalName, const xmlChar* xmlPrefix, const xmlChar* xmlURI, int nb_namespaces,
@@ -87,7 +86,7 @@ public:
             callback->namespaces[i] = xmlStrdup(namespaces[i]);
         callback->nb_attributes = nb_attributes;
         callback->nb_defaulted = nb_defaulted;
-        callback->attributes =  reinterpret_cast<xmlChar**>(xmlMalloc(sizeof(xmlChar*) * nb_attributes * 5));
+        callback->attributes = reinterpret_cast<xmlChar**>(xmlMalloc(sizeof(xmlChar*) * nb_attributes * 5));
         for (int i = 0; i < nb_attributes; i++) {
             // Each attribute has 5 elements in the array:
             // name, prefix, uri, value and an end pointer.
@@ -118,7 +117,7 @@ public:
         callback->s = xmlStrndup(s, len);
         callback->len = len;
         
-        m_callbacks.append(callback);        
+        m_callbacks.append(callback);
     }
     
     void appendProcessingInstructionCallback(const xmlChar* target, const xmlChar* data)
@@ -175,23 +174,20 @@ public:
 
     void callAndRemoveFirstCallback(XMLTokenizer* tokenizer)
     {
-        PendingCallback* cb = m_callbacks.getFirst();
-            
-        cb->call(tokenizer);
+        OwnPtr<PendingCallback> callback(m_callbacks.first());
         m_callbacks.removeFirst();
+        callback->call(tokenizer);
     }
     
     bool isEmpty() const { return m_callbacks.isEmpty(); }
     
 private:    
-    struct PendingCallback {        
-        
-        virtual ~PendingCallback() { } 
-
+    struct PendingCallback {  
+        virtual ~PendingCallback() { }
         virtual void call(XMLTokenizer* tokenizer) = 0;
     };  
     
-    struct PendingStartElementNSCallback : public PendingCallback {        
+    struct PendingStartElementNSCallback : public PendingCallback {
         virtual ~PendingStartElementNSCallback() {
             xmlFree(xmlLocalName);
             xmlFree(xmlPrefix);
@@ -323,8 +319,7 @@ private:
         int columnNumber;
     };
     
-public:
-    DeprecatedPtrList<PendingCallback> m_callbacks;
+    Deque<PendingCallback*> m_callbacks;
 };
 // --------------------------------
 
@@ -1352,5 +1347,3 @@ HashMap<String, String> parseAttributes(const String& string, bool& attrsOK)
 }
 
 }
-
-
index 079877f..8ffd1b1 100644 (file)
@@ -515,30 +515,30 @@ void ApplyStyleCommand::applyRelativeFontStyleChange(CSSMutableStyleDeclaration
         startingFontSizes.set(node, computedFontSize(node));
 
     // These spans were added by us. If empty after font size changes, they can be removed.
-    DeprecatedPtrList<Node> unstyledSpans;
+    Vector<RefPtr<HTMLElement> > unstyledSpans;
     
-    Node *lastStyledNode = 0;
-    for (Node *node = startNode; node != beyondEnd; node = node->traverseNextNode()) {
-        HTMLElement *elem = 0;
+    NodelastStyledNode = 0;
+    for (Nodenode = startNode; node != beyondEnd; node = node->traverseNextNode()) {
+        RefPtr<HTMLElement> element;
         if (node->isHTMLElement()) {
             // Only work on fully selected nodes.
             if (!nodeFullySelected(node, start, end))
                 continue;
-            elem = static_cast<HTMLElement *>(node);
+            element = static_cast<HTMLElement*>(node);
         } else if (node->isTextNode() && node->renderer() && node->parentNode() != lastStyledNode) {
             // Last styled node was not parent node of this text node, but we wish to style this
             // text node. To make this possible, add a style span to surround this text node.
             RefPtr<HTMLElement> span = createStyleSpanElement(document());
             insertNodeBefore(span.get(), node);
             surroundNodeRangeWithElement(node, node, span.get());
-            elem = span.get();
+            element = span.release();
         }  else {
             // Only handle HTML elements and text nodes.
             continue;
         }
         lastStyledNode = node;
-        
-        CSSMutableStyleDeclaration* inlineStyleDecl = elem->getInlineStyleDecl();
+
+        CSSMutableStyleDeclaration* inlineStyleDecl = element->getInlineStyleDecl();
         float currentFontSize = computedFontSize(node);
         float desiredFontSize = max(MinimumFontSize, startingFontSizes.get(node) + adjustment);
         RefPtr<CSSValue> value = inlineStyleDecl->getPropertyCSSValue(CSSPropertyFontSize);
@@ -548,17 +548,18 @@ void ApplyStyleCommand::applyRelativeFontStyleChange(CSSMutableStyleDeclaration
         }
         if (currentFontSize != desiredFontSize) {
             inlineStyleDecl->setProperty(CSSPropertyFontSize, String::number(desiredFontSize) + "px", false, false);
-            setNodeAttribute(elem, styleAttr, inlineStyleDecl->cssText());
+            setNodeAttribute(element.get(), styleAttr, inlineStyleDecl->cssText());
         }
         if (inlineStyleDecl->length() == 0) {
-            removeNodeAttribute(elem, styleAttr);
-            if (isUnstyledStyleSpan(elem))
-                unstyledSpans.append(elem);
+            removeNodeAttribute(element.get(), styleAttr);
+            if (isUnstyledStyleSpan(element.get()))
+                unstyledSpans.append(element.release());
         }
     }
 
-    for (DeprecatedPtrListIterator<Node> it(unstyledSpans); it.current(); ++it)
-        removeNodePreservingChildren(it.current());
+    size_t size = unstyledSpans.size();
+    for (size_t i = 0; i < size; ++i)
+        removeNodePreservingChildren(unstyledSpans[i].get());
 }
 
 #undef NoFontDelta
index 7c1dcc3..29ba9a0 100644 (file)
@@ -288,6 +288,11 @@ void SVGElement::setSynchronizedSVGAttributes(bool value) const
     m_areSVGAttributesValid = value;
 }
 
+ContainerNode* SVGElement::eventParentNode()
+{
+    return m_shadowParent ? m_shadowParent : StyledElement::eventParentNode();
+}
+
 }
 
 #endif // ENABLE(SVG)
index 4dac380..496c2b0 100644 (file)
@@ -66,8 +66,8 @@ namespace WebCore {
 
         virtual bool isShadowNode() const { return m_shadowParent; }
         virtual Node* shadowParentNode() { return m_shadowParent; }
-        void setShadowParentNode(Node* node) { m_shadowParent = node; }
-        virtual Node* eventParentNode() { return isShadowNode() ? shadowParentNode() : parentNode(); }
+        void setShadowParentNode(ContainerNode* node) { m_shadowParent = node; }
+        virtual ContainerNode* eventParentNode();
 
         // For SVGTests
         virtual bool isValid() const { return true; }
@@ -130,7 +130,7 @@ namespace WebCore {
 
         virtual bool haveLoadedRequiredResources();
 
-        Node* m_shadowParent;
+        ContainerNode* m_shadowParent;
         mutable HashMap<String, const SVGAnimatedPropertyBase*> m_svgPropertyMap;
 
         SVGCursorElement* m_cursorElement;