Changeset 41766 in webkit


Ignore:
Timestamp:
Mar 17, 2009, 10:02:19 AM (16 years ago)
Author:
Darin Adler
Message:

WebCore:

2009-03-17 Darin Adler <Darin Adler>

Reviewed by Alexey Proskuryakov.

Bug 24624: Crash in imageLoadEventTimerFired after adoptNode used on <img>,
seen with inspector, which uses adoptNode
https://bugs.webkit.org/show_bug.cgi?id=24624
rdar://problem/6422850

Test: fast/dom/HTMLImageElement/image-load-cross-document.html

  • dom/Document.cpp: (WebCore::Document::Document): Removed m_imageLoadEventTimer. (WebCore::Document::detach): Removed m_imageLoadEventDispatchSoonList and m_imageLoadEventDispatchingList. (WebCore::Document::implicitClose): Called ImageLoader::dispatchPendingLoadEvents instead of dispatchImageLoadEventsNow.
  • dom/Document.h: Removed ImageLoader, dispatchImageLoadEventSoon, dispatchImageLoadEventsNow, removeImage, m_imageLoadEventDispatchSoonList, m_imageLoadEventDispatchingList, m_imageLoadEventTimer, and imageLoadEventTimerFired.
  • loader/ImageLoader.cpp: (WebCore::loadEventSender): Added. Returns the single global ImageLoadEventSender object used privately as the target of the load event timer. (WebCore::ImageLoader::~ImageLoader): Call ImageLoadEventSender::cancelLoadEvent rather than Document::removeImage. (WebCore::ImageLoader::setImage): Use m_element directly, not element(). (WebCore::ImageLoader::updateFromElement): Ditto. Also name the local variable document instead of doc. (WebCore::ImageLoader::notifyFinished): Call ImageLoadEventSender::dispatchLoadEventSoon rather than Document::dispatchImageLoadEventSoon. (WebCore::ImageLoader::dispatchPendingLoadEvent): Added. Handles the common logic about when load events can be dispatched so that dispatchLoadEvent only has to have the specific part for each derived class. This includes a check that the document is attached, which used to be handled by having documents empty out the image load event vectors in the detach function. (WebCore::ImageLoader::dispatchPendingLoadEvents): Added. Calls the appropriate function on the ImageLoadEventSender, which avoids the need to have that class be public in the ImageLoader header. (WebCore::ImageLoadEventSender::ImageLoadEventSender): Added. Has the code that was previously in the Document constructor. (WebCore::ImageLoadEventSender::dispatchLoadEventSoon): Added. Has the code that was previously in Document::dispatchImageLoadEventSoon. (WebCore::ImageLoadEventSender::cancelLoadEvent): Added. Has the code that was previously in Document::removeImage. (WebCore::ImageLoadEventSender::dispatchPendingLoadEvents): Added. Has the code that was previously in Document::dispatchImageLoadEventsNow. (WebCore::ImageLoadEventSender::timerFired): Added. Calls dispatchPendingLoadEvents.
  • loader/ImageLoader.h: Improved comments. Made the virtual functions private or protected rather than public. Added static dispatchPendingLoadEvents function for use by Document and private dispatchPendingLoadEvent function for use by ImageLoadEventSender. Made setLoadingImage private and eliminated setHaveFiredLoadEvent since that can all be done inside the class without any member functions.
  • html/HTMLImageLoader.cpp: (WebCore::HTMLImageLoader::dispatchLoadEvent): Removed logic to check whether a load event already fired and whether image() is 0. These are now both base class responsibilities.
  • svg/SVGImageLoader.cpp: (WebCore::SVGImageLoader::dispatchLoadEvent): Ditto.
  • wml/WMLImageLoader.cpp: (WebCore::WMLImageLoader::dispatchLoadEvent): Ditto.

LayoutTests:

2009-03-17 Darin Adler <Darin Adler>

Reviewed by Alexey Proskuryakov.

Bug 24624: Crash in imageLoadEventTimerFired after adoptNode used on <img>,
seen with inspector, which uses adoptNode
https://bugs.webkit.org/show_bug.cgi?id=24624
rdar://problem/6422850

This test has one significant disadvantage. When it fails, the crash typically
occurs during a subsequent test, not this one. It would be great if someone figured
out at some point how to improve that.

  • fast/dom/HTMLImageElement/image-load-cross-document-expected.txt: Added.
  • fast/dom/HTMLImageElement/image-load-cross-document.html: Added.
  • fast/dom/HTMLImageElement/resources/image-load-subframe.html: Added.
Location:
trunk
Files:
3 added
9 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r41759 r41766  
     12009-03-17  Darin Adler  <darin@apple.com>
     2
     3        Reviewed by Alexey Proskuryakov.
     4
     5        Bug 24624: Crash in imageLoadEventTimerFired after adoptNode used on <img>,
     6        seen with inspector, which uses adoptNode
     7        https://bugs.webkit.org/show_bug.cgi?id=24624
     8        rdar://problem/6422850
     9
     10        This test has one significant disadvantage. When it fails, the crash typically
     11        occurs during a subsequent test, not this one. It would be great if someone figured
     12        out at some point how to improve that.
     13
     14        * fast/dom/HTMLImageElement/image-load-cross-document-expected.txt: Added.
     15        * fast/dom/HTMLImageElement/image-load-cross-document.html: Added.
     16        * fast/dom/HTMLImageElement/resources/image-load-subframe.html: Added.
     17
    1182009-03-17  Alexey Proskuryakov  <ap@webkit.org>
    219
  • trunk/WebCore/ChangeLog

    r41765 r41766  
     12009-03-17  Darin Adler  <darin@apple.com>
     2
     3        Reviewed by Alexey Proskuryakov.
     4
     5        Bug 24624: Crash in imageLoadEventTimerFired after adoptNode used on <img>,
     6        seen with inspector, which uses adoptNode
     7        https://bugs.webkit.org/show_bug.cgi?id=24624
     8        rdar://problem/6422850
     9
     10        Test: fast/dom/HTMLImageElement/image-load-cross-document.html
     11
     12        * dom/Document.cpp:
     13        (WebCore::Document::Document): Removed m_imageLoadEventTimer.
     14        (WebCore::Document::detach): Removed m_imageLoadEventDispatchSoonList and
     15        m_imageLoadEventDispatchingList.
     16        (WebCore::Document::implicitClose): Called ImageLoader::dispatchPendingLoadEvents
     17        instead of dispatchImageLoadEventsNow.
     18
     19        * dom/Document.h: Removed ImageLoader, dispatchImageLoadEventSoon,
     20        dispatchImageLoadEventsNow, removeImage, m_imageLoadEventDispatchSoonList,
     21        m_imageLoadEventDispatchingList, m_imageLoadEventTimer, and imageLoadEventTimerFired.
     22
     23        * loader/ImageLoader.cpp:
     24        (WebCore::loadEventSender): Added. Returns the single global ImageLoadEventSender
     25        object used privately as the target of the load event timer.
     26        (WebCore::ImageLoader::~ImageLoader): Call ImageLoadEventSender::cancelLoadEvent
     27        rather than Document::removeImage.
     28        (WebCore::ImageLoader::setImage): Use m_element directly, not element().
     29        (WebCore::ImageLoader::updateFromElement): Ditto. Also name the local variable
     30        document instead of doc.
     31        (WebCore::ImageLoader::notifyFinished): Call ImageLoadEventSender::dispatchLoadEventSoon
     32        rather than Document::dispatchImageLoadEventSoon.
     33        (WebCore::ImageLoader::dispatchPendingLoadEvent): Added. Handles the common logic
     34        about when load events can be dispatched so that dispatchLoadEvent only has to
     35        have the specific part for each derived class. This includes a check that the
     36        document is attached, which used to be handled by having documents empty out the
     37        image load event vectors in the detach function.
     38        (WebCore::ImageLoader::dispatchPendingLoadEvents): Added. Calls the appropriate
     39        function on the ImageLoadEventSender, which avoids the need to have that class be
     40        public in the ImageLoader header.
     41        (WebCore::ImageLoadEventSender::ImageLoadEventSender): Added. Has the code that
     42        was previously in the Document constructor.
     43        (WebCore::ImageLoadEventSender::dispatchLoadEventSoon): Added. Has the code that
     44        was previously in Document::dispatchImageLoadEventSoon.
     45        (WebCore::ImageLoadEventSender::cancelLoadEvent): Added. Has the code that was
     46        previously in Document::removeImage.
     47        (WebCore::ImageLoadEventSender::dispatchPendingLoadEvents): Added. Has the code
     48        that was previously in Document::dispatchImageLoadEventsNow.
     49        (WebCore::ImageLoadEventSender::timerFired): Added. Calls dispatchPendingLoadEvents.
     50
     51        * loader/ImageLoader.h: Improved comments. Made the virtual functions private
     52        or protected rather than public. Added static dispatchPendingLoadEvents function
     53        for use by Document and private dispatchPendingLoadEvent function for use by
     54        ImageLoadEventSender. Made setLoadingImage private and eliminated
     55        setHaveFiredLoadEvent since that can all be done inside the class without any
     56        member functions.
     57
     58        * html/HTMLImageLoader.cpp:
     59        (WebCore::HTMLImageLoader::dispatchLoadEvent): Removed logic to check whether a
     60        load event already fired and whether image() is 0. These are now both base class
     61        responsibilities.
     62        * svg/SVGImageLoader.cpp:
     63        (WebCore::SVGImageLoader::dispatchLoadEvent): Ditto.
     64        * wml/WMLImageLoader.cpp:
     65        (WebCore::WMLImageLoader::dispatchLoadEvent): Ditto.
     66
    1672009-03-17  Dimitri Glazkov  <dglazkov@chromium.org>
    268
  • trunk/WebCore/dom/Document.cpp

    r41549 r41766  
    285285    , m_title("")
    286286    , m_titleSetExplicitly(false)
    287     , m_imageLoadEventTimer(this, &Document::imageLoadEventTimerFired)
    288287    , m_updateFocusAppearanceTimer(this, &Document::updateFocusAppearanceTimerFired)
    289288#if ENABLE(XSLT)
     
    12971296    // indicate destruction mode,  i.e. attached() but renderer == 0
    12981297    setRenderer(0);
    1299    
    1300     // Empty out these lists as a performance optimization, since detaching
    1301     // all the individual render objects will cause all the RenderImage
    1302     // objects to remove themselves from the lists.
    1303     m_imageLoadEventDispatchSoonList.clear();
    1304     m_imageLoadEventDispatchingList.clear();
    1305    
     1298
    13061299    m_hoverNode = 0;
    13071300    m_focusedNode = 0;
     
    15831576        f->animation()->resumeAnimations(this);
    15841577
    1585     dispatchImageLoadEventsNow();
    1586     this->dispatchWindowEvent(eventNames().loadEvent, false, false);
     1578    ImageLoader::dispatchPendingLoadEvents();
     1579    dispatchWindowEvent(eventNames().loadEvent, false, false);
    15871580    if (f)
    15881581        f->loader()->handledOnloadEvents();
     
    28752868{
    28762869    setWindowInlineEventListenerForType(eventType, createEventListener(attr->localName().string(), attr->value(), 0));
    2877 }
    2878 
    2879 void Document::dispatchImageLoadEventSoon(ImageLoader* image)
    2880 {
    2881     m_imageLoadEventDispatchSoonList.append(image);
    2882     if (!m_imageLoadEventTimer.isActive())
    2883         m_imageLoadEventTimer.startOneShot(0);
    2884 }
    2885 
    2886 void Document::removeImage(ImageLoader* image)
    2887 {
    2888     // Remove instances of this image from both lists.
    2889     // Use loops because we allow multiple instances to get into the lists.
    2890     size_t size = m_imageLoadEventDispatchSoonList.size();
    2891     for (size_t i = 0; i < size; ++i) {
    2892         if (m_imageLoadEventDispatchSoonList[i] == image)
    2893             m_imageLoadEventDispatchSoonList[i] = 0;
    2894     }
    2895     size = m_imageLoadEventDispatchingList.size();
    2896     for (size_t i = 0; i < size; ++i) {
    2897         if (m_imageLoadEventDispatchingList[i] == image)
    2898             m_imageLoadEventDispatchingList[i] = 0;
    2899     }
    2900     if (m_imageLoadEventDispatchSoonList.isEmpty())
    2901         m_imageLoadEventTimer.stop();
    2902 }
    2903 
    2904 void Document::dispatchImageLoadEventsNow()
    2905 {
    2906     // Need to avoid re-entering this function; if new dispatches are
    2907     // scheduled before the parent finishes processing the list, they
    2908     // will set a timer and eventually be processed.
    2909     if (!m_imageLoadEventDispatchingList.isEmpty())
    2910         return;
    2911 
    2912     m_imageLoadEventTimer.stop();
    2913 
    2914     m_imageLoadEventDispatchingList = m_imageLoadEventDispatchSoonList;
    2915     m_imageLoadEventDispatchSoonList.clear();
    2916     size_t size = m_imageLoadEventDispatchingList.size();
    2917     for (size_t i = 0; i < size; ++i) {
    2918         if (ImageLoader* image = m_imageLoadEventDispatchingList[i])
    2919             image->dispatchLoadEvent();
    2920     }
    2921     m_imageLoadEventDispatchingList.clear();
    2922 }
    2923 
    2924 void Document::imageLoadEventTimerFired(Timer<Document>*)
    2925 {
    2926     dispatchImageLoadEventsNow();
    29272870}
    29282871
  • trunk/WebCore/dom/Document.h

    r41549 r41766  
    8484    class HTMLInputElement;
    8585    class HTMLMapElement;
    86     class ImageLoader;
    8786    class IntPoint;
    8887    class JSNode;
     
    640639    void processHttpEquiv(const String& equiv, const String& content);
    641640   
    642     void dispatchImageLoadEventSoon(ImageLoader*);
    643     void dispatchImageLoadEventsNow();
    644     void removeImage(ImageLoader*);
    645    
    646641    // Returns the owning element in the parent document.
    647642    // Returns 0 if this is the top level document.
     
    922917    mutable AXObjectCache* m_axObjectCache;
    923918   
    924     Vector<ImageLoader*> m_imageLoadEventDispatchSoonList;
    925     Vector<ImageLoader*> m_imageLoadEventDispatchingList;
    926     Timer<Document> m_imageLoadEventTimer;
    927 
    928919    Timer<Document> m_updateFocusAppearanceTimer;
    929920
     
    10371028    void updateTitle();
    10381029    void removeAllDisconnectedNodeEventListeners();
    1039     void imageLoadEventTimerFired(Timer<Document>*);
    10401030    void updateFocusAppearanceTimerFired(Timer<Document>*);
    10411031    void updateBaseURL();
  • trunk/WebCore/html/HTMLImageLoader.cpp

    r38094 r41766  
    4343void HTMLImageLoader::dispatchLoadEvent()
    4444{
    45     if (!haveFiredLoadEvent() && image()) {
    46         setHaveFiredLoadEvent(true);
    47         element()->dispatchEventForType(image()->errorOccurred() ? eventNames().errorEvent : eventNames().loadEvent, false, false);
    48     }
     45    element()->dispatchEventForType(image()->errorOccurred() ? eventNames().errorEvent : eventNames().loadEvent, false, false);
    4946}
    5047
  • trunk/WebCore/loader/ImageLoader.cpp

    r40638 r41766  
    22 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
    33 *           (C) 1999 Antti Koivisto (koivisto@kde.org)
    4  * Copyright (C) 2004, 2005, 2006, 2007 Apple Inc. All rights reserved.
     4 * Copyright (C) 2004, 2005, 2006, 2007, 2009 Apple Inc. All rights reserved.
    55 *
    66 * This library is free software; you can redistribute it and/or
     
    3232namespace WebCore {
    3333
    34 ImageLoader::ImageLoader(Element* elt)
    35     : m_element(elt)
     34class ImageLoadEventSender {
     35public:
     36    ImageLoadEventSender();
     37
     38    void dispatchLoadEventSoon(ImageLoader*);
     39    void cancelLoadEvent(ImageLoader*);
     40
     41    void dispatchPendingLoadEvents();
     42
     43private:
     44    ~ImageLoadEventSender();
     45
     46    void timerFired(Timer<ImageLoadEventSender>*);
     47
     48    Timer<ImageLoadEventSender> m_timer;
     49    Vector<ImageLoader*> m_dispatchSoonList;
     50    Vector<ImageLoader*> m_dispatchingList;
     51};
     52
     53static ImageLoadEventSender& loadEventSender()
     54{
     55    DEFINE_STATIC_LOCAL(ImageLoadEventSender, sender, ());
     56    return sender;
     57}
     58
     59ImageLoader::ImageLoader(Element* element)
     60    : m_element(element)
    3661    , m_image(0)
    3762    , m_firedLoad(true)
     
    4570    if (m_image)
    4671        m_image->removeClient(this);
    47     m_element->document()->removeImage(this);
     72    loadEventSender().cancelLoadEvent(this);
    4873}
    4974
     
    6287    }
    6388
    64     if (RenderObject* renderer = element()->renderer()) {
     89    if (RenderObject* renderer = m_element->renderer()) {
    6590        if (!renderer->isImage())
    6691            return;
     
    81106    // If we're not making renderers for the page, then don't load images.  We don't want to slow
    82107    // down the raw HTML parsing case by loading images we don't intend to display.
    83     Element* elem = element();
    84     Document* doc = elem->document();
    85     if (!doc->renderer())
    86         return;
    87 
    88     AtomicString attr = elem->getAttribute(elem->imageSourceAttributeName());
     108    Document* document = m_element->document();
     109    if (!document->renderer())
     110        return;
     111
     112    AtomicString attr = m_element->getAttribute(m_element->imageSourceAttributeName());
    89113
    90114    if (attr == m_failedLoadURL)
     
    96120    // need (<rdar://problem/5994621>).
    97121    CachedImage* newImage = 0;
    98     if (!(attr.isNull() || attr.isEmpty() && doc->baseURI().isLocalFile())) {
     122    if (!(attr.isNull() || attr.isEmpty() && document->baseURI().isLocalFile())) {
    99123        if (m_loadManually) {
    100             doc->docLoader()->setAutoLoadImages(false);
     124            document->docLoader()->setAutoLoadImages(false);
    101125            newImage = new CachedImage(sourceURI(attr));
    102126            newImage->setLoading(true);
    103             newImage->setDocLoader(doc->docLoader());
    104             doc->docLoader()->m_documentResources.set(newImage->url(), newImage);
     127            newImage->setDocLoader(document->docLoader());
     128            document->docLoader()->m_documentResources.set(newImage->url(), newImage);
    105129        } else
    106             newImage = doc->docLoader()->requestImage(sourceURI(attr));
     130            newImage = document->docLoader()->requestImage(sourceURI(attr));
    107131
    108132        // If we do not have an image here, it means that a cross-site
     
    120144    }
    121145
    122     if (RenderObject* renderer = elem->renderer()) {
     146    if (RenderObject* renderer = m_element->renderer()) {
    123147        if (!renderer->isImage())
    124148            return;
     
    140164    m_imageComplete = true;
    141165
    142     Element* elem = element();
    143     elem->document()->dispatchImageLoadEventSoon(this);
    144 
    145     if (RenderObject* renderer = elem->renderer()) {
     166    loadEventSender().dispatchLoadEventSoon(this);
     167
     168    if (RenderObject* renderer = m_element->renderer()) {
    146169        if (!renderer->isImage())
    147170            return;
     
    151174}
    152175
    153 }
     176void ImageLoader::dispatchPendingLoadEvent()
     177{
     178    if (m_firedLoad)
     179        return;
     180    if (!m_image)
     181        return;
     182    if (!m_element->document()->attached())
     183        return;
     184    m_firedLoad = true;
     185    dispatchLoadEvent();
     186}
     187
     188void ImageLoader::dispatchPendingLoadEvents()
     189{
     190    loadEventSender().dispatchPendingLoadEvents();
     191}
     192
     193ImageLoadEventSender::ImageLoadEventSender()
     194    : m_timer(this, &ImageLoadEventSender::timerFired)
     195{
     196}
     197
     198void ImageLoadEventSender::dispatchLoadEventSoon(ImageLoader* loader)
     199{
     200    m_dispatchSoonList.append(loader);
     201    if (!m_timer.isActive())
     202        m_timer.startOneShot(0);
     203}
     204
     205void ImageLoadEventSender::cancelLoadEvent(ImageLoader* loader)
     206{
     207    // Remove instances of this loader from both lists.
     208    // Use loops because we allow multiple instances to get into the lists.
     209    size_t size = m_dispatchSoonList.size();
     210    for (size_t i = 0; i < size; ++i) {
     211        if (m_dispatchSoonList[i] == loader)
     212            m_dispatchSoonList[i] = 0;
     213    }
     214    size = m_dispatchingList.size();
     215    for (size_t i = 0; i < size; ++i) {
     216        if (m_dispatchingList[i] == loader)
     217            m_dispatchingList[i] = 0;
     218    }
     219    if (m_dispatchSoonList.isEmpty())
     220        m_timer.stop();
     221}
     222
     223void ImageLoadEventSender::dispatchPendingLoadEvents()
     224{
     225    // Need to avoid re-entering this function; if new dispatches are
     226    // scheduled before the parent finishes processing the list, they
     227    // will set a timer and eventually be processed.
     228    if (!m_dispatchingList.isEmpty())
     229        return;
     230
     231    m_timer.stop();
     232
     233    m_dispatchingList.swap(m_dispatchSoonList);
     234    size_t size = m_dispatchingList.size();
     235    for (size_t i = 0; i < size; ++i) {
     236        if (ImageLoader* loader = m_dispatchingList[i])
     237            loader->dispatchPendingLoadEvent();
     238    }
     239    m_dispatchingList.clear();
     240}
     241
     242void ImageLoadEventSender::timerFired(Timer<ImageLoadEventSender>*)
     243{
     244    dispatchPendingLoadEvents();
     245}
     246
     247}
  • trunk/WebCore/loader/ImageLoader.h

    r39104 r41766  
    22 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
    33 *           (C) 1999 Antti Koivisto (koivisto@kde.org)
    4  * Copyright (C) 2004 Apple Computer, Inc.
     4 * Copyright (C) 2004, 2009 Apple Inc. All rights reserved.
    55 *
    66 * This library is free software; you can redistribute it and/or
     
    3131
    3232class Element;
     33class ImageLoadEventSender;
    3334
    3435class ImageLoader : public CachedResourceClient {
     
    3738    virtual ~ImageLoader();
    3839
     40    // This function should be called when the element is attached to a document; starts
     41    // loading if a load hasn't already been started.
    3942    void updateFromElement();
    4043
    41     // This method should be called after the 'src' attribute
    42     // is set (even when it is not modified) to force the update
    43     // and match Firefox and Opera.
     44    // This function should be called whenever the 'src' attribute is set, even if its value
     45    // doesn't change; starts new load unconditionally (matches Firefox and Opera behavior).
    4446    void updateFromElementIgnoringPreviousError();
    45 
    46     virtual void dispatchLoadEvent() = 0;
    47     virtual String sourceURI(const AtomicString&) const = 0;
    4847
    4948    Element* element() const { return m_element; }
     
    5554    void setLoadManually(bool loadManually) { m_loadManually = loadManually; }
    5655
    57     // CachedResourceClient API
     56    bool haveFiredLoadEvent() const { return m_firedLoad; }
     57
     58    static void dispatchPendingLoadEvents();
     59
     60protected:
    5861    virtual void notifyFinished(CachedResource*);
    5962
    60     bool haveFiredLoadEvent() const { return m_firedLoad; }
    61 protected:
     63private:
     64    virtual void dispatchLoadEvent() = 0;
     65    virtual String sourceURI(const AtomicString&) const = 0;
     66
     67    friend class ImageLoadEventSender;
     68    void dispatchPendingLoadEvent();
     69
    6270    void setLoadingImage(CachedImage*);
    63    
    64     void setHaveFiredLoadEvent(bool firedLoad) { m_firedLoad = firedLoad; }
    6571
    66 private:
    6772    Element* m_element;
    6873    CachedResourceHandle<CachedImage> m_image;
  • trunk/WebCore/svg/SVGImageLoader.cpp

    r38094 r41766  
    4343void SVGImageLoader::dispatchLoadEvent()
    4444{
    45     if (!haveFiredLoadEvent() && image()) {
    46         setHaveFiredLoadEvent(true);
    47        
    48         if (image()->errorOccurred())
    49             element()->dispatchEventForType(eventNames().errorEvent, false, false);
    50         else {
    51             SVGImageElement* imageElement = static_cast<SVGImageElement*>(element());
    52             if (imageElement->externalResourcesRequiredBaseValue())
    53                 imageElement->sendSVGLoadEventIfPossible(true);
    54         }
     45    if (image()->errorOccurred())
     46        element()->dispatchEventForType(eventNames().errorEvent, false, false);
     47    else {
     48        SVGImageElement* imageElement = static_cast<SVGImageElement*>(element());
     49        if (imageElement->externalResourcesRequiredBaseValue())
     50            imageElement->sendSVGLoadEventIfPossible(true);
    5551    }
    5652}
  • trunk/WebCore/wml/WMLImageLoader.cpp

    r39432 r41766  
    4646{
    4747    // WML doesn't fire any events.
    48     if (haveFiredLoadEvent())
    49         return;
    50 
    51     setHaveFiredLoadEvent(true);
    5248}
    5349
Note: See TracChangeset for help on using the changeset viewer.