Title: [197765] trunk
- Revision
- 197765
- Author
- [email protected]
- Date
- 2016-03-08 07:14:54 -0800 (Tue, 08 Mar 2016)
Log Message
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.
* fast/dom/ImageDocument-world-leak-expected.txt: Added.
* fast/dom/ImageDocument-world-leak.html: Added.
Modified Paths
Added Paths
Diff
Modified: trunk/LayoutTests/ChangeLog (197764 => 197765)
--- trunk/LayoutTests/ChangeLog 2016-03-08 14:59:53 UTC (rev 197764)
+++ trunk/LayoutTests/ChangeLog 2016-03-08 15:14:54 UTC (rev 197765)
@@ -1,3 +1,19 @@
+2016-03-08 Andreas Kling <[email protected]>
+
+ ImageDocuments leak their world.
+ <https://webkit.org/b/155167>
+ <rdar://problem/24987363>
+
+ Reviewed by Antti Koivisto.
+
+ 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.
+
+ * fast/dom/ImageDocument-world-leak-expected.txt: Added.
+ * fast/dom/ImageDocument-world-leak.html: Added.
+
2016-03-08 Alejandro G. Castro <[email protected]>
Unreviewed EFL build fix after r197752.
Added: trunk/LayoutTests/fast/dom/ImageDocument-world-leak-expected.txt (0 => 197765)
--- trunk/LayoutTests/fast/dom/ImageDocument-world-leak-expected.txt (rev 0)
+++ trunk/LayoutTests/fast/dom/ImageDocument-world-leak-expected.txt 2016-03-08 15:14:54 UTC (rev 197765)
@@ -0,0 +1,4 @@
+Test that ImageDocuments don't leak their world.
+
+Number of live documents: 2 (was 2)
+
Added: trunk/LayoutTests/fast/dom/ImageDocument-world-leak.html (0 => 197765)
--- trunk/LayoutTests/fast/dom/ImageDocument-world-leak.html (rev 0)
+++ trunk/LayoutTests/fast/dom/ImageDocument-world-leak.html 2016-03-08 15:14:54 UTC (rev 197765)
@@ -0,0 +1,51 @@
+<head>
+<script>
+function gc() {
+ if (window.GCController)
+ GCController.collect();
+}
+
+function numberOfLiveDocuments() {
+ if (window.internals)
+ return window.internals.numberOfLiveDocuments();
+ return 1;
+}
+
+gc();
+
+iterations = 10;
+if (window.testRunner) {
+ testRunner.dumpAsText();
+ testRunner.waitUntilDone();
+}
+
+function test() {
+ var f = document.getElementById("frame");
+ f._onload_ = function() {
+ f.contentDocument.open();
+ f.contentDocument.close();
+ --iterations;
+ if (iterations)
+ setTimeout("test()", 0);
+ else {
+ gc();
+ var out = document.getElementById("out");
+ out.innerText += "Number of live documents: " + numberOfLiveDocuments() + " (was " + numberOfLiveDocumentsAtStart + ")";
+ if (window.testRunner)
+ testRunner.notifyDone();
+ }
+ }
+ f.setAttribute("src", "resources/apple.gif");
+}
+
+function begin() {
+ numberOfLiveDocumentsAtStart = numberOfLiveDocuments();
+ test();
+}
+</script>
+</head>
+<body _onload_="begin()">
+ <p>Test that ImageDocuments don't leak their world. </p>
+ <pre id="out"></pre>
+ <iframe id="frame"></iframe>
+</body>
Modified: trunk/Source/WebCore/ChangeLog (197764 => 197765)
--- trunk/Source/WebCore/ChangeLog 2016-03-08 14:59:53 UTC (rev 197764)
+++ trunk/Source/WebCore/ChangeLog 2016-03-08 15:14:54 UTC (rev 197765)
@@ -1,3 +1,36 @@
+2016-03-08 Andreas Kling <[email protected]>
+
+ ImageDocuments leak their world.
+ <https://webkit.org/b/155167>
+ <rdar://problem/24987363>
+
+ Reviewed by Antti Koivisto.
+
+ 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):
+
2016-03-07 Antti Koivisto <[email protected]>
ElementRuleCollector should not mutate document and style
Modified: trunk/Source/WebCore/loader/ImageLoader.cpp (197764 => 197765)
--- trunk/Source/WebCore/loader/ImageLoader.cpp 2016-03-08 14:59:53 UTC (rev 197764)
+++ trunk/Source/WebCore/loader/ImageLoader.cpp 2016-03-08 15:14:54 UTC (rev 197765)
@@ -188,6 +188,7 @@
bool autoLoadOtherImages = document.cachedResourceLoader().autoLoadImages();
document.cachedResourceLoader().setAutoLoadImages(false);
newImage = new CachedImage(request.resourceRequest(), m_element.document().page()->sessionID());
+ newImage->setStatus(CachedResource::Pending);
newImage->setLoading(true);
newImage->setOwningCachedResourceLoader(&document.cachedResourceLoader());
document.cachedResourceLoader().m_documentResources.set(newImage->url(), newImage.get());
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes