Diff
Modified: branches/safari-536.26-branch/LayoutTests/ChangeLog (125128 => 125129)
--- branches/safari-536.26-branch/LayoutTests/ChangeLog 2012-08-09 00:56:13 UTC (rev 125128)
+++ branches/safari-536.26-branch/LayoutTests/ChangeLog 2012-08-09 01:02:07 UTC (rev 125129)
@@ -1,5 +1,34 @@
2012-08-07 Lucas Forschler <lforsch...@apple.com>
+ Merge 120096
+
+ 2012-06-12 Brady Eidson <beid...@apple.com>
+
+ <rdar://problem/11593686> and https://bugs.webkit.org/show_bug.cgi?id=88683
+ Garbage collection of an <img> element can cause reentrant event dispatch.
+
+ Reviewed by Darin Adler.
+
+ New tests for all users of ImageLoader:
+ * http/tests/loading/embed-image-load-outlives-gc-without-crashing-expected.txt: Added.
+ * http/tests/loading/embed-image-load-outlives-gc-without-crashing.html: Added.
+ * http/tests/loading/image-input-type-outlives-gc-without-crashing-expected.txt: Added.
+ * http/tests/loading/image-input-type-outlives-gc-without-crashing.html: Added.
+ * http/tests/loading/image-load-outlives-gc-without-crashing-expected.txt: Added.
+ * http/tests/loading/image-load-outlives-gc-without-crashing.html: Added.
+ * http/tests/loading/object-image-load-outlives-gc-without-crashing-expected.txt: Added.
+ * http/tests/loading/object-image-load-outlives-gc-without-crashing.html: Added.
+ * http/tests/loading/resources/slowimage.php: Added.
+ * http/tests/loading/svg-image-load-outlives-gc-without-crashing-expected.txt: Added.
+ * http/tests/loading/svg-image-load-outlives-gc-without-crashing.html: Added.
+ * http/tests/loading/video-poster-image-load-outlives-gc-without-crashing-expected.txt: Added.
+ * http/tests/loading/video-poster-image-load-outlives-gc-without-crashing.html: Added.
+
+ Shared sub resource for all of those tests:
+ * http/tests/loading/resources/slowimage.php: Added.
+
+2012-08-07 Lucas Forschler <lforsch...@apple.com>
+
Merge 123936
2012-07-27 Brady Eidson <beid...@apple.com>
Copied: branches/safari-536.26-branch/LayoutTests/http/tests/loading/embed-image-load-outlives-gc-without-crashing-expected.txt (from rev 120096, trunk/LayoutTests/http/tests/loading/embed-image-load-outlives-gc-without-crashing-expected.txt) (0 => 125129)
--- branches/safari-536.26-branch/LayoutTests/http/tests/loading/embed-image-load-outlives-gc-without-crashing-expected.txt (rev 0)
+++ branches/safari-536.26-branch/LayoutTests/http/tests/loading/embed-image-load-outlives-gc-without-crashing-expected.txt 2012-08-09 01:02:07 UTC (rev 125129)
@@ -0,0 +1,6 @@
+main frame - didStartProvisionalLoadForFrame
+main frame - didCommitLoadForFrame
+main frame - didFinishDocumentLoadForFrame
+main frame - didFailLoadWithError
+This has an embed element representing an image. That embed element is wrapped in a div. It removes the div, forces garbage collection, and makes sure that the window load event does not fire. It also makes sure there is no crash.
+
Copied: branches/safari-536.26-branch/LayoutTests/http/tests/loading/embed-image-load-outlives-gc-without-crashing.html (from rev 120096, trunk/LayoutTests/http/tests/loading/embed-image-load-outlives-gc-without-crashing.html) (0 => 125129)
--- branches/safari-536.26-branch/LayoutTests/http/tests/loading/embed-image-load-outlives-gc-without-crashing.html (rev 0)
+++ branches/safari-536.26-branch/LayoutTests/http/tests/loading/embed-image-load-outlives-gc-without-crashing.html 2012-08-09 01:02:07 UTC (rev 125129)
@@ -0,0 +1,53 @@
+<script>
+
+if (window.layoutTestController) {
+ layoutTestController.waitUntilDone();
+ layoutTestController.dumpAsText();
+}
+
+function loaded() {
+ // If the garbage collection causes the image load to stop and therefore causes the load event to fire on the main frame, we failed.
+ alert("FAIL: The load event fired");
+
+ if (window.layoutTestController)
+ layoutTestController.notifyDone();
+}
+
+</script>
+<body _onload_="loaded();">
+
+This has an embed element representing an image. That embed element is wrapped in a div. It removes the div, forces garbage collection, and makes sure that the window load event does not fire. It also makes sure there is no crash.<br>
+<div id="thediv">
+<embed type="image/gif" src=""
+</embed>
+</div>
+</body>
+<script>
+
+function finished() {
+ window.stop()
+ if (window.layoutTestController)
+ layoutTestController.notifyDone();
+}
+
+function forceGC() {
+ if (this.GCController)
+ GCController.collect();
+ else {
+ for (var i = 0; i < 10000; ++i) // Allocate a sufficient number of objects to force a GC.
+ ({});
+ }
+
+ setTimeout("finished();", 0);
+}
+
+function removeTheDiv() {
+ var element = window.document.getElementById("thediv");
+ element.parentNode.removeChild(element);
+ element = null;
+ setTimeout("forceGC();", 0);
+}
+
+setTimeout("removeTheDiv();", 0);
+
+</script>
Copied: branches/safari-536.26-branch/LayoutTests/http/tests/loading/image-input-type-outlives-gc-without-crashing-expected.txt (from rev 120096, trunk/LayoutTests/http/tests/loading/image-input-type-outlives-gc-without-crashing-expected.txt) (0 => 125129)
--- branches/safari-536.26-branch/LayoutTests/http/tests/loading/image-input-type-outlives-gc-without-crashing-expected.txt (rev 0)
+++ branches/safari-536.26-branch/LayoutTests/http/tests/loading/image-input-type-outlives-gc-without-crashing-expected.txt 2012-08-09 01:02:07 UTC (rev 125129)
@@ -0,0 +1,6 @@
+main frame - didStartProvisionalLoadForFrame
+main frame - didCommitLoadForFrame
+main frame - didFinishDocumentLoadForFrame
+main frame - didFailLoadWithError
+This test has a form with an input type=image element in it. The form is wrapped in a div. It removes the div, forces garbage collection, and makes sure that the window load event does not fire. It also makes sure there is no crash.
+
Copied: branches/safari-536.26-branch/LayoutTests/http/tests/loading/image-input-type-outlives-gc-without-crashing.html (from rev 120096, trunk/LayoutTests/http/tests/loading/image-input-type-outlives-gc-without-crashing.html) (0 => 125129)
--- branches/safari-536.26-branch/LayoutTests/http/tests/loading/image-input-type-outlives-gc-without-crashing.html (rev 0)
+++ branches/safari-536.26-branch/LayoutTests/http/tests/loading/image-input-type-outlives-gc-without-crashing.html 2012-08-09 01:02:07 UTC (rev 125129)
@@ -0,0 +1,54 @@
+<script>
+
+if (window.layoutTestController) {
+ layoutTestController.waitUntilDone();
+ layoutTestController.dumpAsText();
+}
+
+function loaded() {
+ // If the garbage collection causes the image load to stop and therefore causes the load event to fire on the main frame, we failed.
+ alert("FAIL: The load event fired");
+
+ if (window.layoutTestController)
+ layoutTestController.notifyDone();
+}
+
+</script>
+<body _onload_="loaded();">
+
+This test has a form with an input type=image element in it. The form is wrapped in a div. It removes the div, forces garbage collection, and makes sure that the window load event does not fire. It also makes sure there is no crash.<br>
+<div id="thediv">
+<form>
+<input type="image" src=""
+</form>
+</div>
+</body>
+<script>
+
+function finished() {
+ window.stop()
+ if (window.layoutTestController)
+ layoutTestController.notifyDone();
+}
+
+function forceGC() {
+ if (this.GCController)
+ GCController.collect();
+ else {
+ for (var i = 0; i < 10000; ++i) // Allocate a sufficient number of objects to force a GC.
+ ({});
+ }
+
+ setTimeout("finished();", 0);
+}
+
+function removeTheDiv() {
+ var element = window.document.getElementById("thediv");
+ element.parentNode.removeChild(element);
+ element = null;
+ setTimeout("forceGC();", 0);
+}
+
+setTimeout("removeTheDiv();", 0);
+
+</script>
Copied: branches/safari-536.26-branch/LayoutTests/http/tests/loading/image-load-outlives-gc-without-crashing-expected.txt (from rev 120096, trunk/LayoutTests/http/tests/loading/image-load-outlives-gc-without-crashing-expected.txt) (0 => 125129)
--- branches/safari-536.26-branch/LayoutTests/http/tests/loading/image-load-outlives-gc-without-crashing-expected.txt (rev 0)
+++ branches/safari-536.26-branch/LayoutTests/http/tests/loading/image-load-outlives-gc-without-crashing-expected.txt 2012-08-09 01:02:07 UTC (rev 125129)
@@ -0,0 +1,6 @@
+main frame - didStartProvisionalLoadForFrame
+main frame - didCommitLoadForFrame
+main frame - didFinishDocumentLoadForFrame
+main frame - didFailLoadWithError
+This test has an image inside a div. It removes the div, forces garbage collection, and makes sure that the window load event does not fire. It also makes sure there is no crash.
+
Copied: branches/safari-536.26-branch/LayoutTests/http/tests/loading/image-load-outlives-gc-without-crashing.html (from rev 120096, trunk/LayoutTests/http/tests/loading/image-load-outlives-gc-without-crashing.html) (0 => 125129)
--- branches/safari-536.26-branch/LayoutTests/http/tests/loading/image-load-outlives-gc-without-crashing.html (rev 0)
+++ branches/safari-536.26-branch/LayoutTests/http/tests/loading/image-load-outlives-gc-without-crashing.html 2012-08-09 01:02:07 UTC (rev 125129)
@@ -0,0 +1,52 @@
+<script>
+
+if (window.layoutTestController) {
+ layoutTestController.waitUntilDone();
+ layoutTestController.dumpAsText();
+}
+
+function loaded() {
+ // If the garbage collection causes the image load to stop and therefore causes the load event to fire on the main frame, we failed.
+ alert("FAIL: The load event fired");
+
+ if (window.layoutTestController)
+ layoutTestController.notifyDone();
+}
+
+</script>
+<body _onload_="loaded();">
+
+This test has an image inside a div. It removes the div, forces garbage collection, and makes sure that the window load event does not fire. It also makes sure there is no crash.<br>
+<div id="thediv">
+<img src=""
+</div>
+</body>
+<script>
+
+function finished() {
+ window.stop()
+ if (window.layoutTestController)
+ layoutTestController.notifyDone();
+}
+
+function forceGC() {
+ if (this.GCController)
+ GCController.collect();
+ else {
+ for (var i = 0; i < 10000; ++i) // Allocate a sufficient number of objects to force a GC.
+ ({});
+ }
+
+ setTimeout("finished();", 0);
+}
+
+function removeTheDiv() {
+ var element = window.document.getElementById("thediv");
+ element.parentNode.removeChild(element);
+ element = null;
+ setTimeout("forceGC();", 0);
+}
+
+setTimeout("removeTheDiv();", 0);
+
+</script>
Copied: branches/safari-536.26-branch/LayoutTests/http/tests/loading/object-image-load-outlives-gc-without-crashing-expected.txt (from rev 120096, trunk/LayoutTests/http/tests/loading/object-image-load-outlives-gc-without-crashing-expected.txt) (0 => 125129)
--- branches/safari-536.26-branch/LayoutTests/http/tests/loading/object-image-load-outlives-gc-without-crashing-expected.txt (rev 0)
+++ branches/safari-536.26-branch/LayoutTests/http/tests/loading/object-image-load-outlives-gc-without-crashing-expected.txt 2012-08-09 01:02:07 UTC (rev 125129)
@@ -0,0 +1,6 @@
+main frame - didStartProvisionalLoadForFrame
+main frame - didCommitLoadForFrame
+main frame - didFinishDocumentLoadForFrame
+main frame - didFailLoadWithError
+This has an object element representing an image. That object element is wrapped in a div. It removes the div, forces garbage collection, and makes sure that the window load event does not fire. It also makes sure there is no crash.
+
Copied: branches/safari-536.26-branch/LayoutTests/http/tests/loading/object-image-load-outlives-gc-without-crashing.html (from rev 120096, trunk/LayoutTests/http/tests/loading/object-image-load-outlives-gc-without-crashing.html) (0 => 125129)
--- branches/safari-536.26-branch/LayoutTests/http/tests/loading/object-image-load-outlives-gc-without-crashing.html (rev 0)
+++ branches/safari-536.26-branch/LayoutTests/http/tests/loading/object-image-load-outlives-gc-without-crashing.html 2012-08-09 01:02:07 UTC (rev 125129)
@@ -0,0 +1,53 @@
+<script>
+
+if (window.layoutTestController) {
+ layoutTestController.waitUntilDone();
+ layoutTestController.dumpAsText();
+}
+
+function loaded() {
+ // If the garbage collection causes the image load to stop and therefore causes the load event to fire on the main frame, we failed.
+ alert("FAIL: The load event fired");
+
+ if (window.layoutTestController)
+ layoutTestController.notifyDone();
+}
+
+</script>
+<body _onload_="loaded();">
+
+This has an object element representing an image. That object element is wrapped in a div. It removes the div, forces garbage collection, and makes sure that the window load event does not fire. It also makes sure there is no crash.<br>
+<div id="thediv">
+<object type="image/gif" data=""
+</object>
+</div>
+</body>
+<script>
+
+function finished() {
+ window.stop()
+ if (window.layoutTestController)
+ layoutTestController.notifyDone();
+}
+
+function forceGC() {
+ if (this.GCController)
+ GCController.collect();
+ else {
+ for (var i = 0; i < 10000; ++i) // Allocate a sufficient number of objects to force a GC.
+ ({});
+ }
+
+ setTimeout("finished();", 0);
+}
+
+function removeTheDiv() {
+ var element = window.document.getElementById("thediv");
+ element.parentNode.removeChild(element);
+ element = null;
+ setTimeout("forceGC();", 0);
+}
+
+setTimeout("removeTheDiv();", 0);
+
+</script>
Copied: branches/safari-536.26-branch/LayoutTests/http/tests/loading/resources/slowimage.php (from rev 120096, trunk/LayoutTests/http/tests/loading/resources/slowimage.php) (0 => 125129)
--- branches/safari-536.26-branch/LayoutTests/http/tests/loading/resources/slowimage.php (rev 0)
+++ branches/safari-536.26-branch/LayoutTests/http/tests/loading/resources/slowimage.php 2012-08-09 01:02:07 UTC (rev 125129)
@@ -0,0 +1,5 @@
+<?php
+sleep(30);
+header('Cache-Control: no-cache, must-revalidate');
+header('Location: data:image/gif;base64,R0lGODlhAQABAJAAAMjIyAAAACwAAAAAAQABAAACAgQBADs%3D');
+?>
Copied: branches/safari-536.26-branch/LayoutTests/http/tests/loading/svg-image-load-outlives-gc-without-crashing-expected.txt (from rev 120096, trunk/LayoutTests/http/tests/loading/svg-image-load-outlives-gc-without-crashing-expected.txt) (0 => 125129)
--- branches/safari-536.26-branch/LayoutTests/http/tests/loading/svg-image-load-outlives-gc-without-crashing-expected.txt (rev 0)
+++ branches/safari-536.26-branch/LayoutTests/http/tests/loading/svg-image-load-outlives-gc-without-crashing-expected.txt 2012-08-09 01:02:07 UTC (rev 125129)
@@ -0,0 +1,6 @@
+main frame - didStartProvisionalLoadForFrame
+main frame - didCommitLoadForFrame
+main frame - didFinishDocumentLoadForFrame
+main frame - didFailLoadWithError
+This has an svg element that contains an svg image element. That svg element is wrapped in a div. It removes the div, forces garbage collection, and makes sure that the window load event does not fire. It also makes sure there is no crash.
+
Copied: branches/safari-536.26-branch/LayoutTests/http/tests/loading/svg-image-load-outlives-gc-without-crashing.html (from rev 120096, trunk/LayoutTests/http/tests/loading/svg-image-load-outlives-gc-without-crashing.html) (0 => 125129)
--- branches/safari-536.26-branch/LayoutTests/http/tests/loading/svg-image-load-outlives-gc-without-crashing.html (rev 0)
+++ branches/safari-536.26-branch/LayoutTests/http/tests/loading/svg-image-load-outlives-gc-without-crashing.html 2012-08-09 01:02:07 UTC (rev 125129)
@@ -0,0 +1,54 @@
+<script>
+
+if (window.layoutTestController) {
+ layoutTestController.waitUntilDone();
+ layoutTestController.dumpAsText();
+}
+
+function loaded() {
+ // If the garbage collection causes the image load to stop and therefore causes the load event to fire on the main frame, we failed.
+ alert("FAIL: The load event fired");
+
+ if (window.layoutTestController)
+ layoutTestController.notifyDone();
+}
+
+</script>
+<body _onload_="loaded();">
+
+This has an svg element that contains an svg image element. That svg element is wrapped in a div. It removes the div, forces garbage collection, and makes sure that the window load event does not fire. It also makes sure there is no crash.<br>
+<div id="thediv">
+<svg>
+<image xlink:href="" />
+</svg>
+</div>
+</body>
+<script>
+
+function finished() {
+ window.stop()
+ if (window.layoutTestController)
+ layoutTestController.notifyDone();
+}
+
+function forceGC() {
+ if (this.GCController)
+ GCController.collect();
+ else {
+ for (var i = 0; i < 10000; ++i) // Allocate a sufficient number of objects to force a GC.
+ ({});
+ }
+
+ setTimeout("finished();", 0);
+}
+
+function removeTheDiv() {
+ var element = window.document.getElementById("thediv");
+ element.parentNode.removeChild(element);
+ element = null;
+ setTimeout("forceGC();", 0);
+}
+
+setTimeout("removeTheDiv();", 0);
+
+</script>
Copied: branches/safari-536.26-branch/LayoutTests/http/tests/loading/video-poster-image-load-outlives-gc-without-crashing-expected.txt (from rev 120096, trunk/LayoutTests/http/tests/loading/video-poster-image-load-outlives-gc-without-crashing-expected.txt) (0 => 125129)
--- branches/safari-536.26-branch/LayoutTests/http/tests/loading/video-poster-image-load-outlives-gc-without-crashing-expected.txt (rev 0)
+++ branches/safari-536.26-branch/LayoutTests/http/tests/loading/video-poster-image-load-outlives-gc-without-crashing-expected.txt 2012-08-09 01:02:07 UTC (rev 125129)
@@ -0,0 +1,6 @@
+main frame - didStartProvisionalLoadForFrame
+main frame - didCommitLoadForFrame
+main frame - didFinishDocumentLoadForFrame
+main frame - didFailLoadWithError
+This has a video element with an image for its poster frame. That video element is wrapped in a div. It removes the div, forces garbage collection, and makes sure that the window load event does not fire. It also makes sure there is no crash.
+
Copied: branches/safari-536.26-branch/LayoutTests/http/tests/loading/video-poster-image-load-outlives-gc-without-crashing.html (from rev 120096, trunk/LayoutTests/http/tests/loading/video-poster-image-load-outlives-gc-without-crashing.html) (0 => 125129)
--- branches/safari-536.26-branch/LayoutTests/http/tests/loading/video-poster-image-load-outlives-gc-without-crashing.html (rev 0)
+++ branches/safari-536.26-branch/LayoutTests/http/tests/loading/video-poster-image-load-outlives-gc-without-crashing.html 2012-08-09 01:02:07 UTC (rev 125129)
@@ -0,0 +1,53 @@
+<script>
+
+if (window.layoutTestController) {
+ layoutTestController.waitUntilDone();
+ layoutTestController.dumpAsText();
+}
+
+function loaded() {
+ // If the garbage collection causes the image load to stop and therefore causes the load event to fire on the main frame, we failed.
+ alert("FAIL: The load event fired");
+
+ if (window.layoutTestController)
+ layoutTestController.notifyDone();
+}
+
+</script>
+<body _onload_="loaded();">
+
+This has a video element with an image for its poster frame. That video element is wrapped in a div. It removes the div, forces garbage collection, and makes sure that the window load event does not fire. It also makes sure there is no crash.<br>
+<div id="thediv">
+<video poster="resources/slowimage.php">
+</video>
+</div>
+</body>
+<script>
+
+function finished() {
+ window.stop()
+ if (window.layoutTestController)
+ layoutTestController.notifyDone();
+}
+
+function forceGC() {
+ if (this.GCController)
+ GCController.collect();
+ else {
+ for (var i = 0; i < 10000; ++i) // Allocate a sufficient number of objects to force a GC.
+ ({});
+ }
+
+ setTimeout("finished();", 0);
+}
+
+function removeTheDiv() {
+ var element = window.document.getElementById("thediv");
+ element.parentNode.removeChild(element);
+ element = null;
+ setTimeout("forceGC();", 0);
+}
+
+setTimeout("removeTheDiv();", 0);
+
+</script>
Modified: branches/safari-536.26-branch/Source/WebCore/ChangeLog (125128 => 125129)
--- branches/safari-536.26-branch/Source/WebCore/ChangeLog 2012-08-09 00:56:13 UTC (rev 125128)
+++ branches/safari-536.26-branch/Source/WebCore/ChangeLog 2012-08-09 01:02:07 UTC (rev 125129)
@@ -1,5 +1,42 @@
2012-08-07 Lucas Forschler <lforsch...@apple.com>
+ Merge 120096
+
+ 2012-06-12 Brady Eidson <beid...@apple.com>
+
+ <rdar://problem/11593686> and https://bugs.webkit.org/show_bug.cgi?id=88683
+ Garbage collection of an <img> element can cause reentrant event dispatch.
+
+ Reviewed by Darin Adler.
+
+ The most straightforward solution is for ImageLoader to keep its Element alive
+ with ref/deref any time the Image is actually loading.
+
+ ImageLoader should always do this for all Elements, and if those Elements want/need
+ different behavior for when they are detached then they need to manually stop their
+ loads.
+
+ Tests: http/tests/loading/embed-image-load-outlives-gc-without-crashing.html
+ http/tests/loading/image-input-type-outlives-gc-without-crashing.html
+ http/tests/loading/image-load-outlives-gc-without-crashing.html
+ http/tests/loading/object-image-load-outlives-gc-without-crashing.html
+ http/tests/loading/svg-image-load-outlives-gc-without-crashing.html
+ http/tests/loading/video-poster-image-load-outlives-gc-without-crashing.html
+
+ * loader/ImageLoader.cpp:
+ (WebCore::ImageLoader::ImageLoader):
+ (WebCore::ImageLoader::~ImageLoader):
+ (WebCore::ImageLoader::setImage):
+ (WebCore::ImageLoader::updateFromElement):
+ (WebCore::ImageLoader::notifyFinished):
+ (WebCore::ImageLoader::updatedHasPendingLoadEvent):
+ (WebCore::ImageLoader::dispatchPendingBeforeLoadEvent):
+ (WebCore::ImageLoader::dispatchPendingLoadEvent):
+ * loader/ImageLoader.h:
+ (ImageLoader):
+
+2012-08-07 Lucas Forschler <lforsch...@apple.com>
+
Merge 123936
2012-07-27 Brady Eidson <beid...@apple.com>
Modified: branches/safari-536.26-branch/Source/WebCore/loader/ImageLoader.cpp (125128 => 125129)
--- branches/safari-536.26-branch/Source/WebCore/loader/ImageLoader.cpp 2012-08-09 00:56:13 UTC (rev 125128)
+++ branches/safari-536.26-branch/Source/WebCore/loader/ImageLoader.cpp 2012-08-09 01:02:07 UTC (rev 125129)
@@ -89,6 +89,7 @@
, m_hasPendingErrorEvent(false)
, m_imageComplete(true)
, m_loadManually(false)
+ , m_elementIsProtected(false)
{
}
@@ -108,6 +109,11 @@
ASSERT(m_hasPendingErrorEvent || !errorEventSender().hasPendingEvents(this));
if (m_hasPendingErrorEvent)
errorEventSender().cancelEvent(this);
+
+ // If the ImageLoader is being destroyed but it is still protecting its image-loading Element,
+ // remove that protection here.
+ if (m_elementIsProtected)
+ m_element->deref();
}
void ImageLoader::setImage(CachedImage* newImage)
@@ -137,6 +143,10 @@
if (RenderImageResource* imageResource = renderImageResource())
imageResource->resetAnimation();
+
+ // Only consider updating the protection ref-count of the Element immediately before returning
+ // from this function as doing so might result in the destruction of this ImageLoader.
+ updatedHasPendingLoadEvent();
}
void ImageLoader::updateFromElement()
@@ -218,6 +228,10 @@
if (RenderImageResource* imageResource = renderImageResource())
imageResource->resetAnimation();
+
+ // Only consider updating the protection ref-count of the Element immediately before returning
+ // from this function as doing so might result in the destruction of this ImageLoader.
+ updatedHasPendingLoadEvent();
}
void ImageLoader::updateFromElementIgnoringPreviousError()
@@ -257,6 +271,9 @@
if (resource->wasCanceled()) {
m_hasPendingLoadEvent = false;
+ // Only consider updating the protection ref-count of the Element immediately before returning
+ // from this function as doing so might result in the destruction of this ImageLoader.
+ updatedHasPendingLoadEvent();
return;
}
@@ -303,6 +320,24 @@
imageResource->setCachedImage(m_image.get());
}
+void ImageLoader::updatedHasPendingLoadEvent()
+{
+ // If an Element that does image loading is removed from the DOM the load event for the image is still observable.
+ // As long as the ImageLoader is actively loading, the Element itself needs to be ref'ed to keep it from being
+ // destroyed by DOM manipulation or garbage collection.
+ // If such an Element wishes for the load to stop when removed from the DOM it needs to stop the ImageLoader explicitly.
+
+ if (m_hasPendingLoadEvent == m_elementIsProtected)
+ return;
+
+ m_elementIsProtected = m_hasPendingLoadEvent;
+
+ if (m_elementIsProtected)
+ m_element->ref();
+ else
+ m_element->deref();
+}
+
void ImageLoader::dispatchPendingEvent(ImageEventSender* eventSender)
{
ASSERT(eventSender == &beforeLoadEventSender() || eventSender == &loadEventSender() || eventSender == &errorEventSender());
@@ -338,6 +373,10 @@
if (m_element->hasTagName(HTMLNames::objectTag))
static_cast<HTMLObjectElement*>(m_element)->renderFallbackContent();
+
+ // Only consider updating the protection ref-count of the Element immediately before returning
+ // from this function as doing so might result in the destruction of this ImageLoader.
+ updatedHasPendingLoadEvent();
}
void ImageLoader::dispatchPendingLoadEvent()
@@ -350,6 +389,10 @@
return;
m_hasPendingLoadEvent = false;
dispatchLoadEvent();
+
+ // Only consider updating the protection ref-count of the Element immediately before returning
+ // from this function as doing so might result in the destruction of this ImageLoader.
+ updatedHasPendingLoadEvent();
}
void ImageLoader::dispatchPendingErrorEvent()
Modified: branches/safari-536.26-branch/Source/WebCore/loader/ImageLoader.h (125128 => 125129)
--- branches/safari-536.26-branch/Source/WebCore/loader/ImageLoader.h 2012-08-09 00:56:13 UTC (rev 125128)
+++ branches/safari-536.26-branch/Source/WebCore/loader/ImageLoader.h 2012-08-09 01:02:07 UTC (rev 125129)
@@ -75,6 +75,8 @@
virtual void dispatchLoadEvent() = 0;
virtual String sourceURI(const AtomicString&) const = 0;
+ void updatedHasPendingLoadEvent();
+
void dispatchPendingBeforeLoadEvent();
void dispatchPendingLoadEvent();
void dispatchPendingErrorEvent();
@@ -90,6 +92,7 @@
bool m_hasPendingErrorEvent : 1;
bool m_imageComplete : 1;
bool m_loadManually : 1;
+ bool m_elementIsProtected : 1;
};
}