Changeset 85375 in webkit


Ignore:
Timestamp:
Apr 29, 2011 5:57:39 PM (13 years ago)
Author:
ggaren@apple.com
Message:

2011-04-29 Geoffrey Garen <ggaren@apple.com>

Reviewed by Alexey Proskuryakov.

REGRESSION: r83938 abandons GC memory
https://bugs.webkit.org/show_bug.cgi?id=59604

This bug was caused by script and image elements waiting indefinitely
for their loads to finish.

  • bindings/js/JSNodeCustom.cpp: (WebCore::isReachableFromDOM): Don't test for the load event firing, since the load event doesn't fire in cases of canceled or errored loads. Instead, test hasPendingActivity().


Don't do this test at all for script elements because script elements
can't load while outside the document. (fast/dom/script-element-gc.html
verifies that this is correct.)

  • html/HTMLImageElement.cpp: (WebCore::HTMLImageElement::hasPendingActivity):
  • html/HTMLImageElement.h:
  • loader/ImageLoader.cpp: (WebCore::ImageEventSender::hasPendingEvents): (WebCore::ImageLoader::hasPendingLoadEvent):
  • loader/ImageLoader.h: Added API for finding out if an image element has pending activity.
  • loader/cache/CachedResource.cpp: (WebCore::CachedResource::setRequest): All loads are supposed to end in data(allDataReceived = true) or error(), but in the edge case of a canceled load, all we get is a call to setRequest(0). Be sure to record that we're no longer loading in that case, otherwise our element will leak forever, waiting for its load to complete.

2011-04-29 Geoffrey Garen <ggaren@apple.com>

Reviewed by Alexey Proskuryakov.

REGRESSION: r83938 abandons GC memory
https://bugs.webkit.org/show_bug.cgi?id=59604


Test an edge case of an image that has finished loading but has not yet
fired its load event.

  • fast/dom/gc-image-element-expected.txt: Added.
  • fast/dom/gc-image-element.html: Added.
Location:
trunk
Files:
2 added
8 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r85374 r85375  
     12011-04-29  Geoffrey Garen  <ggaren@apple.com>
     2
     3        Reviewed by Alexey Proskuryakov.
     4
     5        REGRESSION: r83938 abandons GC memory
     6        https://bugs.webkit.org/show_bug.cgi?id=59604
     7       
     8        Test an edge case of an image that has finished loading but has not yet
     9        fired its load event.
     10
     11        * fast/dom/gc-image-element-expected.txt: Added.
     12        * fast/dom/gc-image-element.html: Added.
     13
    1142011-04-29  Emil Eklund  <eae@chromium.org>
    215
  • trunk/Source/WebCore/ChangeLog

    r85374 r85375  
     12011-04-29  Geoffrey Garen  <ggaren@apple.com>
     2
     3        Reviewed by Alexey Proskuryakov.
     4
     5        REGRESSION: r83938 abandons GC memory
     6        https://bugs.webkit.org/show_bug.cgi?id=59604
     7
     8        This bug was caused by script and image elements waiting indefinitely
     9        for their loads to finish.
     10
     11        * bindings/js/JSNodeCustom.cpp:
     12        (WebCore::isReachableFromDOM): Don't test for the load event firing,
     13        since the load event doesn't fire in cases of canceled or errored loads.
     14        Instead, test hasPendingActivity().
     15       
     16        Don't do this test at all for script elements because script elements
     17        can't load while outside the document. (fast/dom/script-element-gc.html
     18        verifies that this is correct.)
     19
     20        * html/HTMLImageElement.cpp:
     21        (WebCore::HTMLImageElement::hasPendingActivity):
     22        * html/HTMLImageElement.h:
     23        * loader/ImageLoader.cpp:
     24        (WebCore::ImageEventSender::hasPendingEvents):
     25        (WebCore::ImageLoader::hasPendingLoadEvent):
     26        * loader/ImageLoader.h: Added API for finding out if an image element
     27        has pending activity.
     28
     29        * loader/cache/CachedResource.cpp:
     30        (WebCore::CachedResource::setRequest): All loads are supposed to end in
     31        data(allDataReceived = true) or error(), but in the edge case of a
     32        canceled load, all we get is a call to setRequest(0). Be sure to
     33        record that we're no longer loading in that case, otherwise our element
     34        will leak forever, waiting for its load to complete.
     35
    1362011-04-29  Emil Eklund  <eae@chromium.org>
    237
  • trunk/Source/WebCore/bindings/js/JSNodeCustom.cpp

    r84812 r85375  
    2828
    2929#include "Attr.h"
     30#include "CachedImage.h"
     31#include "CachedScript.h"
    3032#include "CDATASection.h"
    3133#include "Comment.h"
     
    104106{
    105107    if (!node->inDocument()) {
    106         // If a wrapper is the last reference to an image or script element
     108        // If a wrapper is the last reference to an image element
    107109        // that is loading but not in the document, the wrapper is observable
    108110        // because it is the only thing keeping the image element alive, and if
    109         // the image element is destroyed, its load event will not fire.
     111        // the element is destroyed, its load event will not fire.
    110112        // FIXME: The DOM should manage this issue without the help of JavaScript wrappers.
    111         if (node->hasTagName(imgTag) && !static_cast<HTMLImageElement*>(node)->haveFiredLoadEvent())
    112             return true;
    113         if (node->hasTagName(scriptTag) && !static_cast<HTMLScriptElement*>(node)->haveFiredLoadEvent())
    114             return true;
     113        if (node->hasTagName(imgTag)) {
     114            if (static_cast<HTMLImageElement*>(node)->hasPendingActivity())
     115                return true;
     116        }
    115117    #if ENABLE(VIDEO)
    116         if (node->hasTagName(audioTag) && !static_cast<HTMLAudioElement*>(node)->paused())
    117             return true;
     118        else if (node->hasTagName(audioTag)) {
     119            if (!static_cast<HTMLAudioElement*>(node)->paused())
     120                return true;
     121        }
    118122    #endif
    119123
  • trunk/Source/WebCore/html/HTMLImageElement.cpp

    r69868 r85375  
    386386}
    387387
     388bool HTMLImageElement::hasPendingActivity()
     389{
     390    return (cachedImage() && cachedImage()->isLoading()) || m_imageLoader.hasPendingLoadEvent();
     391}
     392
    388393void HTMLImageElement::addSubresourceAttributeURLs(ListHashSet<KURL>& urls) const
    389394{
  • trunk/Source/WebCore/html/HTMLImageElement.h

    r78232 r85375  
    7474
    7575    bool haveFiredLoadEvent() const { return m_imageLoader.haveFiredLoadEvent(); }
     76    bool hasPendingActivity();
    7677
    7778protected:
  • trunk/Source/WebCore/loader/ImageLoader.cpp

    r76248 r85375  
    6868    void dispatchPendingEvents();
    6969
    70 #if !ASSERT_DISABLED
    7170    bool hasPendingEvents(ImageLoader* loader) { return m_dispatchSoonList.find(loader) != notFound; }
    72 #endif
    7371
    7472private:
     
    313311}
    314312
     313bool ImageLoader::hasPendingLoadEvent()
     314{
     315    return loadEventSender().hasPendingEvents(this);
     316}
     317
    315318ImageEventSender::ImageEventSender(const AtomicString& eventType)
    316319    : m_eventType(eventType)
  • trunk/Source/WebCore/loader/ImageLoader.h

    r66223 r85375  
    5959    bool haveFiredBeforeLoadEvent() const { return m_firedBeforeLoad; }
    6060    bool haveFiredLoadEvent() const { return m_firedLoad; }
     61    bool hasPendingLoadEvent();
    6162
    6263    static void dispatchPendingBeforeLoadEvents();
  • trunk/Source/WebCore/loader/cache/CachedResource.cpp

    r84110 r85375  
    250250        m_status = Pending;
    251251    m_request = request;
     252
     253    // All loads finish with data(allDataReceived = true) or error(), except for
     254    // canceled loads, which silently set our request to 0. Be sure to set our
     255    // loading flag to false in that case, so we don't seem to continue loading
     256    // forever.
     257    if (!m_request)
     258        setLoading(false);
     259
    252260    if (canDelete() && !inCache())
    253261        delete this;
Note: See TracChangeset for help on using the changeset viewer.