...

View Full Version : IE Stack Overflow



jkd
02-23-2007, 05:58 PM
Before dissecting my code line-by-line, I am curious if anybody else here has encountered this.

My code is too lengthy to post, but the code itself is irrelevant. In both Internet Explorer 6 and 7, a certain page is viewed. Everything is golden, then you navigate away. When you click the back button, a stack overflow on "line 0" occurs.

Now, I am not clobbering the stack. In fact, I'm just declaring tons of functions and adding event listeners - no iteration or recursion of any kind.

I imagine it has to do with IE's scripting engine caching the environment of the page onunload, so that when the page navigates back there are some internal references circling about which shouldn't be there. (I've tried deleting and unattaching *everything* onbeforeunload without any success.)

Anybody seen this before?

MikeFoster
02-23-2007, 06:38 PM
No, I don't think I have seen that.


I imagine it has to do with IE's scripting engine caching the environment of the page onunload, so that when the page navigates back there are some internal references circling about which shouldn't be there.

That was my first thought, too.

Can you give us a link to the page? I'd be glad to give it a try.

jkd
02-24-2007, 06:04 AM
I would, but it's very much an internal thing that only beta testers have access to at the moment. If I figure out, I will be sure to try to document it.

MikeFoster
02-24-2007, 08:47 AM
Ok. Good luck! :)

jkd
02-26-2007, 10:41 PM
function preload() {
var image = new Image();
var images = Array.prototype.slice.call(arguments, 0);
image.onload = function() {
if (images.length)
this.src = images.pop();
}
image.src = images.pop();
}


Generates the stack overflow when called with all the images already cached (e.g. clicking back to a page containing a call to this).

Replacing that with this:


function preload() {
var image = new Image();
var images = Array.prototype.slice.call(arguments, 0);

for (var i = 0; i < images.length; i++)
(function(img) {
img.src = images[i];
})(new Image());
}


Does not produce the error. Fairly bizarre.

RoyW
02-27-2007, 04:31 PM
A long time ago I was working on an image slide show that pre-fetched images as the current image was being viewed. I used image.onload and came across a situation I had not expected. The image.onload function was being called before it had finished. i found that the img.onload is not like setTimeout in that if an image onload fires it does not wait untill other onloads have finished before calling the function.
Consider


image.onload = function() {
this.src = some_array[i];
i=i+1;
window.status = i;
}


as soon as the line "this.src = some_array[i];" is executed, if the image is already cached, the onload fires and the function re-enters before the other 2 lines can execute.

That explains the recursion.

As for the stack overflow, when your onload function gets executed isn't it executing in the global scope? The function preload() has finished so the local variables no longer exist. This would mean "images.pop()" would be referring to the global array document.images. I don't think the length of that array could change.

What I see happening is the function recursively tries to pre-cache the last image in the document.

The "at line 0" is probably because the code is executing in the callback.

try this


function preload() {
var image = new Image();
var images = Array.prototype.slice.call(arguments, 0);
image.images = images;
image.onload = function() {
if (this.images.length)
this.src = this.images.pop();
}
image.src = images.pop();
}

This will probably still recurse but should not overflow.

jkd
02-27-2007, 06:29 PM
As for the stack overflow, when your onload function gets executed isn't it executing in the global scope? The function preload() has finished so the local variables no longer exist. This would mean "images.pop()" would be referring to the global array document.images. I don't think the length of that array could change.

The local variables are contained within the closure of the onload function, so they should never go out of scope.

RoyW
02-27-2007, 06:49 PM
Hi,
I am not too up on closeures but woudn't you have to do
new preLoad();
instead of just calling preLoad() for the variables to stick around?

jkd
02-28-2007, 12:48 AM
Nope. No need for objects. A closure simply is a new scope that has access to the variables in its parent scopes (but more local identifiers taking precedence), which happens every time to declare a function.



EZ Archive Ads Plugin for vBulletin Copyright 2006 Computer Help Forum