Closed
Bug 1211528
Opened 9 years ago
Closed 9 years ago
onload() event operator in <img> tag fires before decoding is complete
Categories
(Core :: DOM: Events, defect)
Tracking
()
RESOLVED
INVALID
People
(Reporter: brodhead.tom, Unassigned)
Details
Attachments
(1 file)
291 bytes,
text/html
|
Details |
User Agent: Mozilla/5.0 (Windows NT 6.3; WOW64; rv:41.0) Gecko/20100101 Firefox/41.0
Build ID: 20150929144111
Steps to reproduce:
This script proves that Firefox is mishandling the onload() event in <img> tags, both on desktop and mobile devices. When run in Chrome, IE, Safari, or any of their derivatives, the alert() boxes successively show 1, 2, and then 3, as expected. In Firefox, Tor, and the other browsers based on Firefox, the alert boxes successively show 3, 2, and then 1...the *opposite* order in which they should appear:
<!DOCTYPE html>
<img onload="loadImage()" src="image01.jpg" /></a>
<img onload="loadImage()" src="image02.jpg" /></a>
<img onload="loadImage()" src="image03.jpg" /></a>
<script>
var loaded_counter = 0;
function loadImage() {
loaded_counter++;
alert(loaded_counter);
}
</script>
Actual results:
As described above, Firefox shows the counter variable decrementing, not incrementing. A clue to what is happening occurs when testing this on the Tor browser, which runs more slowly than the other Firefox-based browsers. When running this in Tor, the alert() boxes first quickly flash without stopping for interaction (i.e. without stopping for the user to click "OK") while showing an *incrementing* of the counter variable from 1 to 3, but only displaying for a split second each. Then the first true, interactive alert box appeared, showing the incorrect "3", not "1" (as should be the case). The non-Tor Firefox-based browsers run quickly enough that the quick flashing of the non-interactive (i.e. non-pausing) alert() boxes cannot be seen. My guess is that Firefox is processing onload() each time it is encountered as the <img> tags are first read--and in some abstracted way that prevents interaction with alert boxes, etc., and processed so quickly in non-Tor Firefox browsers that they can't be seen as the flash by. It's only after quickly doing this that the alert()s are displayed. And because they are returning in the opposite order, it seems that Firefox is placing them on a stack, with the topmost one is processed first, thus causing the first interactive alert box to display 3, not 1, and then decrement.
Expected results:
As explained above, the alert() boxes should show 1, 2, and then 3, not 3, 2, and 1. You can increase the number of <img> tags in the sample code and put additional images in the queue; you'll see that the alert() box numbers *decrement* from the total number of images down to 1 when run in Firefox and its derivatives, instead of incrementing from 1 to the total number of images, which is what all of the other browsers do. I've checked this on MANY Firefox-based browsers, both desktop and mobile (i.e. Adblock Browser for Android) and the result is the same. This must be part of the core functionality of how Firefox parses and processes onload() events in the case of images, or perhaps onload() events regardless of the type. The documented behavior of onload() in an <img> tag is that it should fire only when the image is fully loaded. This causes my code to fall over in Firefox, and I've had to write a patch to detect whether the browser is Firefox-based and then reroute my routine that is dependent on the successful loading of each image. This *MUST* be corrected and every browser maker based on Mozilla Firefox should be alerted when it is fixed, else my code (and the code of other developers) will work on the main Firefox browser but not on the ancillary browsers.
Updated•9 years ago
|
Component: Untriaged → DOM: Events
Product: Firefox → Core
This has nothing to do with <img>, and everything to do with alert. If you replace alert(loaded_counter) with console.log(loaded_counter) you will see the expected behavior.
Status: UNCONFIRMED → RESOLVED
Closed: 9 years ago
Resolution: --- → DUPLICATE
Comment 2•9 years ago
|
||
And in particular, please see bug 1173716 comment 2, which pretty much describes exactly what's going on in this testcase.
Of course so do the "Actual results" in this bug, which describe the alert boxes coming up in the right order, stacking newest on top, then being dismissed in top to bottom order by the user...
Reporter | ||
Comment 3•9 years ago
|
||
Okay, here is the proof, using your methodology. Select 3 *LARGE* image files--mine were 26MB each--and run the following code with the console open. You'll see that the console quickly logs 1 2 3 for the three counter variables...but the images aren't fully loaded yet! Using small image files won't reveal this problem, because they finish loading asynchronously before or at the same time that the counter variables are printed to the console log. You need to use HUGE images, like 25MB or greater, and then you'll see that onload() is being executed before the loading process is complete.
This was causing my code to fail on Firefox, but not on Chrome, Safari, and even IE. I had to devise a special routine to account for Firefox's failings here in order for my site to function correctly.
Here, try this code and please let me know if it doesn't provide the same result that I got:
<!DOCTYPE html>
<?php
$time1 = time();
$time2 =+ $time1;
$time3 =+ $time2;
?>
<img onload="loadImage()" src="image01.jpg?t=<?php echo $time1;?>" />
<img onload="loadImage()" src="image02.jpg?t=<?php echo $time2;?>" />
<img onload="loadImage()" src="image03.jpg?t=<?php echo $time3;?>" />
<script>
var loaded_counter = 0;
function loadImage() {
loaded_counter++;
console.log(loaded_counter);
}
</script>
Status: RESOLVED → UNCONFIRMED
Resolution: DUPLICATE → ---
Comment 4•9 years ago
|
||
Just to check, how are you detecting whether the images are "fully loaded"? Seth, is it possible possible that onload fires after the image is loaded but before it's decoded/painted.
> This was causing my code to fail on Firefox,
What code failed, exactly, and in what fashion?
Flags: needinfo?(seth)
Reporter | ||
Comment 5•9 years ago
|
||
I just realized that I performed my console log test on Chrome and not on Firefox. On Chrome, the counter is incremented fully before the images are loaded, which is incorrect. This is not the case with the console log in Firefox, in which the counters are executed as soon as the *last* image is loaded (it appears that way), so that's partially correct (it should show each counter value after each successive image is loaded, not all three at once when the last image is loaded). Regardless, my site works in Chrome, Safari, and IE, as the images need to be fully loaded in order for other things to be loaded; the other things are loaded on those browsers AFTER the images appear/become accessible...that's the proof. On Firefox, the other things are loaded *BEFORE* the images are loaded (I can click on a link to them after the other things load and the images aren't available yet...they're still in the queue...that's how I know, and that's not the case with the other browsers). Something's rotten in Denmark...
As far as I know we do not wait for image decodes before firing onload, nor does any other browser.
Reporter | ||
Comment 7•9 years ago
|
||
Then you should verify that, please. If Firefox does not wait and the others do wait, then the problem is that it does not wait, and it should wait for the decode. As I've written, I've had to account for this issue in order for my site to work cross-platform.
I've found another developer who ran into this problem and posted a bug report here a few years ago, so the problem has been around at least since this post:
https://bugzilla.mozilla.org/show_bug.cgi?id=626613
Comment 8•9 years ago
|
||
(In reply to Boris Zbarsky [:bz] from comment #4)
> Just to check, how are you detecting whether the images are "fully loaded"?
> Seth, is it possible possible that onload fires after the image is loaded
> but before it's decoded/painted.
We fire the load event for images when two conditions are met:
1. The image data has fully loaded from the network, guaranteeing that synchronous operations like canvas.drawImage() can succeed.
2. We have decoded enough of the image's header to successfully determine its intrinsic size.
It can absolutely fire before the image has been fully decoded or painted. This should be unobservable from JavaScript.
Flags: needinfo?(seth)
Comment 9•9 years ago
|
||
(In reply to brodhead.tom from comment #7)
> As I've written, I've had to account for this issue in order for
> my site to work cross-platform.
Forgive me if it was posted earlier and I missed it, but do you have a test case which demonstrates your actual problem? Not alert() or console.log(), but the actual issue you're encountering on your real site?
Comment 10•9 years ago
|
||
> in which the counters are executed as soon as the *last* image is loaded (it appears
> that way), so that's partially correct (it should show each counter value after each
> successive image is loaded, not all three at once when the last image is loaded)
How are you defining "loaded" here?
> On Firefox, the other things are loaded *BEFORE* the images are loaded (I can click on a
> link to them after the other things load and the images aren't available yet
Aren't available in what sense? Not visible to the user? Not laid out on the web page correctly? Something else?
Updated•9 years ago
|
Summary: onload() event operator in <img> tag fires prematurely → onload() event operator in <img> tag fires before decoding is complete
Status: UNCONFIRMED → RESOLVED
Closed: 9 years ago → 9 years ago
Resolution: --- → INVALID
You need to log in
before you can comment on or make changes to this bug.
Description
•