NEW6656
Clearing or changing img.src does not cancel the image load already in flight
https://bugs.webkit.org/show_bug.cgi?id=6656
Summary Clearing or changing img.src does not cancel the image load already in flight
Thomas Fuchs
Reported 2006-01-18 15:12:26 PST
When IMG elements or JavaScript Image objects are completely removed (setting .innerHTML of a container to an empty string or deleting the Image object) image loading continues in the background.
Attachments
Simplified test cases for plain HTML, JavaScript Image objects and generated HTML (watch the activity window) (554 bytes, text/html)
2006-01-18 15:13 PST, Thomas Fuchs
no flags
probe.zip (10.90 KB, application/zip)
2026-08-26 02:51 PDT, Karl Dubost
no flags
Thomas Fuchs
Comment 1 2006-01-18 15:13:26 PST
Created attachment 5764 [details] Simplified test cases for plain HTML, JavaScript Image objects and generated HTML (watch the activity window)
Mark Rowe (bdash)
Comment 2 2006-01-18 15:18:19 PST
It seems logical to me that removing the image completely from the page by the three means shown should cancel loading the image. Thanks for the great test case Thomas.
Chas Conway
Comment 3 2007-09-19 08:29:22 PDT
I was about to file a similar bug regarding identical behavior with MJPG streams. I am trying to switch an image's source between a static and motion jpeg file to save bandwidth when the video is not needed, but no matter what I do to it, short of reloading the page, it continues to load the MJPG data stream once it's been requested once. http://discord.itg.uiuc.edu/testing/MJPG_test.html This video stream may sometimes be black, but you will still see ~100KB/s in the activity monitor. This test case shows that the MJPG stream continues downloading after switching the src to a static image and even after deleting the image's DOM node.
Dave Hyatt
Comment 4 2007-09-19 13:31:46 PDT
This is actually by design. I can see how it would be bad if the resource is large though. (The idea is to go ahead and let the load complete so that the image gets into the cache to be resuable.)
Chas Conway
Comment 5 2007-09-19 13:42:00 PDT
(In reply to comment #4) > This is actually by design. I can see how it would be bad if the resource is > large though. (The idea is to go ahead and let the load complete so that the > image gets into the cache to be resuable.) > That's good to know. I don't know much about MJPG resources; can they be finite-length as well? In this case the MJPG stream is live and continues on forever negating any reason to try caching it. Is there a way to detect that the stream is not finite and cancel the behavior?
Wichert Akkerman
Comment 6 2008-12-08 02:08:26 PST
What was the design decision made here? This issue breaks image lazy loading tricks, making pages with many images below the fold extremely expensive for people using webkit.
Mark Rowe (bdash)
Comment 7 2009-03-26 09:03:54 PDT
Bryan Field-Elliot
Comment 8 2009-04-17 12:53:51 PDT
Can someone please advise what the status of this bug is? And what is the link in the previous comment for? ("<rdar://problem/6726455>"). Thank you.
Kyle Hotchkiss
Comment 9 2010-01-28 12:23:34 PST
http://www.appelsiini.net/projects/lazyload .. Why can't the model of this plugin just be applied, or maybe when it sees something like this used, it doesn't ignore it.
Alexey Proskuryakov
Comment 10 2010-02-25 15:55:03 PST
*** Bug 35377 has been marked as a duplicate of this bug. ***
lbzwischenbrugger
Comment 11 2010-02-26 08:27:04 PST
Finish loading or not If the src attribute of an image is changed by javascript a new Image will be loaded. In some cases the previous loaded image is not fully loaded. It is a "nice idea" to complete loading for caching reasons. But there are some problems with that. Loading continues also when an image Element is removed from DOM tree or an Image object is deleted. Dealing with partly loaded Images ----------------------------------- I see 3 possibilities A.) Continue loading even if the image is not requested anymore WebKit Browsers continue loading. Firefox stops loading. If the image is loaded to 99% it's cool to continue loading for cache. If it's many times only 10% it makes the app slow. B.) Stop loading, dump the partly loaded images If the programmer needs to preload images he/she can do that with an Image Object. It's also possible to create an Element with tagName "img" an, set the src Attribute and set the style to display:none. If the images is needed change display property to "" or "inline" with javascript; C.) Stop loading, save the partly loaded images. If the image is requested again load the rest of the image. see: http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html 14.16 Content-Range That would be cool if it's really fast code. I don't knoww if web servers loose speed with in aktive "Content-Range" http header. This is als used for large file downloads. More details on this header: http://www.west-wind.com/WebLog/posts/244.aspx WebKit Status: -------------- There is no possibility for programmers to abort loading an image. Webkit has a really fast image rendering and zoom engine. For web applications (browser maps) that deal with lots of images it's good to have excellent image rendering. However, the user will not be really satisfied - because of this image loading issue.
lbzwischenbrugger
Comment 12 2010-03-09 03:22:36 PST
Here is a more komplex testcase: http://www.khtml.org/webkitbug/ It's webmap. if you zoom in/out very fast, firefox is fast loading the images. Btw. if an images has in Etag but is in cache, the image could be displayed immediately. If the ETag has changed the picture on the page can be changed for the new one.
paradox
Comment 13 2010-04-26 19:20:52 PDT
This script is probably the most common use of this technique http://www.appelsiini.net/projects/lazyload An example can be seen here: http://www.appelsiini.net/projects/lazyload/enabled.html
Alexey Proskuryakov
Comment 14 2011-08-26 15:42:33 PDT
It's my fault that this bug is about two separate issues now (removing an element or changing its src). Even though both are by design, these are not identical. Perhaps bug 35377 should be un-duped.
Simon Fraser (smfr)
Comment 15 2011-08-26 16:53:20 PDT
I reopened bug 35377.
lbzwischenbrugger
Comment 16 2011-08-26 19:18:41 PDT
I reported bug 35377 and also made a comment here for the same bug. For me it looks pretty much the same. There are many methods to cancel image loading: img.setAttribute("src",""); img.src=""; img.parentNode.innerHTML=""; img.parentNode.textContent=""; img.parentNode.removeChild(img); img.parentNode.replaceChild(img2); (maybe not complete) btw. when I reported this bug I was in Cambodia and had a slow internet connection. Bandwidth was about 300 kBit shared for a guesthouse, the ping indicated that it was a satellite link. Under this conditions webkit browsers are not the first choice mainly because of the bug I think. Now I'm connected to the internet with a 10MBit line again and here I don't feel a bad impact of the bug. To find a good solution, the programmer maybe should simulate slow internet speed as you find in many parts of this world. "netem" could do that for example.
Brady Eidson
Comment 17 2018-06-05 12:24:50 PDT
Talking to a dev from BaseCamp right now at WWDC. "In other browsers, doing something to get an IMG created does not synchronously start a network load - That only happens after the runloop spins. WebKit synchronously starts the load, even JS immediately sets the src the null. This is super duper wasteful in our app (We clone dom trees, etc etc)"
Javan Makhmali
Comment 18 2018-06-06 08:01:32 PDT
Hello, another Basecamp developer here with more details. We use `MutationObserver` to detect when images are added to the DOM and swap their "src" attribute with a tiny placeholder image. Then we restore the original "src" as images are scrolled into the viewport. This technique is commonly referred to as “lazy loading” and is intended to avoid unnecessary network requests for images that may never be viewed. Due to this WebKit issue, our approach doesn’t work in Safari because the original image is always loaded. Additionally (this may be a separate issue), cloning <img> elements causes them to load *again* even if the cloned node is detached from the DOM. For example, running `document.body.cloneNode(true)` reloads all of its images. This affects our Turbolinks (https://github.com/turbolinks/turbolinks) library, which stores “snapshots” of pages by cloning them. I made a video to help illustrate the problem: https://www.youtube.com/watch?v=p6bkcjoyP1M In Safari (left), every image on the page is loaded initially, and then loaded again when scrolled into view. Cloning <body> loads all of its images once more. In Chrome (right), only the first image loads initially and the rest are canceled. Cloning <body> makes no additional network requests. My example application and its source code are available here: https://glitch.com/~jealous-moon Thanks for your time!
Karl Dubost
Comment 23 2026-08-26 02:51:15 PDT
Created attachment 481161 [details] probe.zip Instructions are inside the folder to run the probe which has an http server and an html file. # Run it python3 server.py 8656 Then open, in each browser, with a build label: http://127.0.0.1:8656/?build=Safari-26.2 http://127.0.0.1:8656/?build=STP-251 http://127.0.0.1:8656/?build=Chrome-154 http://127.0.0.1:8656/?build=Firefox-156 Press "Run the probe". It takes about 30 seconds.
Karl Dubost
Comment 24 2026-08-26 02:51:58 PDT
Measured in three engines on the same machine, 2026-08-26. The probe serves one valid 3.00 MB PNG dripped out over three seconds, and records at the server whether the browser read it to the end or hung up early. Cancellation is not observable from the page, only from the other end of the socket, which is why every earlier attempt on this bug ended in "watch the activity window". Removing the element, the case this bug is titled after: STP 251 Chrome 154 Firefox 156 img.remove() mid-load 3.00 MB 3.00 MB 3.00 MB container.innerHTML = "" mid-load 3.00 MB 3.00 MB 3.00 MB last Image() reference dropped 3.00 MB 3.00 MB 3.00 MB 3.00 MB is the whole file. All three engines finish the download after the element is gone. Changing the source, for contrast, same probe, same run: STP 251 Chrome 154 Firefox 156 img.src = "" mid-load 3.00 MB 0.61 MB 0.64 MB img.removeAttribute("src") 3.00 MB 0.61 MB 0.64 MB img.src = a different URL 3.00 MB 0.64 MB 0.64 MB The smaller numbers are where the engine hung up, about 0.7s in. So the other two engines do cancel, just not on removal. The spec permits the removal behaviour. Removal is a relevant mutation, so "update the image data" re-runs, but with an unchanged src it lands on step 15: "If urlString is the same as the current request's current URL and the current request's state is partially available: Abort the image request for the pending request. ... Return." The pending request, not the current one. The in-flight load is the current request, and the algorithm leaves it running. https://html.spec.whatwg.org/multipage/images.html#updating-the-image-data So comment 4 still describes what every engine does, and what the spec allows. Comment 11 says Firefox stops loading and comment 18 says Chrome cancels the rest; neither holds now, at least not for removal. What is left of this bug after that, and it is real: * img.src = "" and img.removeAttribute("src") must abort the current request per step 11.1, and WebKit is the only one of the three that does not. That is a plain conformance bug. * The fetch starts in the same task as the assignment. Step 8 requires a microtask first and step 9 requires that only the last instance take effect, so "img.src = A; img.src = B" in one task must not request A. WebKit downloads A in full; Chrome and Firefox never ask for it. That is the cause of the lazy-loading complaint in comment 17 and comment 18. The lazy-loading pattern from comment 18, run verbatim, costs Firefox nothing, Chrome 32 kB, and WebKit the whole 3.00 MB. * Four tests under imported/w3c/web-platform-tests/html/semantics/embedded-content/the-img-element/update-the-image-data/ already have FAIL baselines in the tree for that second point, 14 subtests between them. * Comment 18's other claim, that cloning refetches, no longer reproduces in any engine. SUGGEST retitling or splitting: the title names the one part that is not a bug, which is most of why this has stayed open since 2006. Environment: macOS. Safari Technology Preview 251, Chrome 154, Firefox 156.
Karl Dubost
Comment 25 2026-08-26 02:59:26 PDT
*** Bug 35377 has been marked as a duplicate of this bug. ***
Karl Dubost
Comment 26 2026-08-26 03:12:32 PDT
I opened a new bug for the microtask specific issue. https://bugs.webkit.org/show_bug.cgi?id=322584
Note You need to log in before you can comment on or make changes to this bug.