ImageDocuments leak their world.
authorakling@apple.com <akling@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 9 Mar 2016 12:00:32 +0000 (12:00 +0000)
committerakling@apple.com <akling@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 9 Mar 2016 12:00:32 +0000 (12:00 +0000)
commitf3d66b48d734dd97e4f5f526e8955e4966b1cc7e
tree7b8a71c175cfcf4ce8ebb0c64f6f00402defb324
parent91aa78289a97e9ab7f945e4a86c8ae0a820ab5b7
ImageDocuments leak their world.
<https://webkit.org/b/155167>
<rdar://problem/24987363>

Reviewed by Antti Koivisto.

Source/WebCore:

ImageDocument uses a special code path in ImageLoader in order to manually
control how the image is loaded. It has to do this because the ImageDocument
is really just a synthetic wrapper around a main resource that's an image.

This custom loading code had a bug where it would create a new CachedImage
and neglect to set its CachedResource::m_state flag to Pending (which is
normally set by CachedResource::load(), but we don't call that for these.)

This meant that when ImageDocument called CachedImage::finishLoading() to
trigger the notifyFinished() callback path, the image would look at its
loading state and see that it was Unknown (not Pending), and conclude that
it hadn't loaded yet. So we never got the notifyFinished() signal.

The world leaks here because ImageLoader slaps a ref on its <img> element
while it waits for the loading operation to complete. Once finished, whether
successfully or with an error, it derefs the <img>.

Since we never fired notifyFinished(), we ended up with an extra ref on
these <img> forever, and then the element kept its document alive too.

Test: fast/dom/ImageDocument-world-leak.html

* loader/ImageLoader.cpp:
(WebCore::ImageLoader::updateFromElement):

LayoutTests:

Made a little test that loads an image into an <iframe> 10 times and then
triggers a garbage collection and checks that all the documents got destroyed.

Prior to this change, all 10 ImageDocuments would remain alive at the end.

This got rolled out the first time because it failed on bots. It failed due
to expecting a specific number of documents to be live at the start of the
test, which was not reliable on bots since we appear to have more leaks(!)

Tweaked the test to check the delta in live document count instead.

* fast/dom/ImageDocument-world-leak-expected.txt: Added.
* fast/dom/ImageDocument-world-leak.html: Added.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@197856 268f45cc-cd09-0410-ab3c-d52691b4dbfc
LayoutTests/ChangeLog
LayoutTests/fast/dom/ImageDocument-world-leak-expected.txt [new file with mode: 0644]
LayoutTests/fast/dom/ImageDocument-world-leak.html [new file with mode: 0644]
Source/WebCore/ChangeLog
Source/WebCore/loader/ImageLoader.cpp