Bug Tracker

Opened 10 years ago

Closed 10 years ago

Last modified 8 years ago

#4787 closed bug (fixed)

$(document).ready() frame detection / cross-domain error in IE6

Reported by: richdougherty Owned by:
Priority: major Milestone: 1.4
Component: event Version: 1.3.2
Keywords: Cc:
Blocked by: Blocking:

Description

I am using JQuery within frames that set document.domain. This is causing problems for me in IE6 but not in FF2.

The frame detection code in JQuery 1.3.2 (used in ready(), added in #3988) seems to cause an 'Access is denied' exception when I subsequently try to access window.frameElement. The problem seems to be the fact that JQuery accesses window.top, which causes some weird time-dependent interaction with window.frameElement.

Here is a two-frame test case that illustrates the problem caused by window.top. The parent frame sets document.domain to localhost and includes a child iframe. The child iframe likewise sets document.domain to localhost and then it tries to access window.frameElement. This access may cause an exception (presumably 'Access is denied'), in which case it tries again in 100ms. It keeps trying until it succeeds, which - strangely enough - seems to happen if it keeps trying for long enough.

With the code shown below, window.frameElement is accessible straight away. But I uncomment window.top or window.parent and try it again then it will takes 9-15 seconds for window.frameElement to become available.

parent.html

<html>
<body>
<h2>Parent</h2>
<script type="text/javascript">
document.domain = 'localhost';
</script>
<iframe src="child.html" height="200" width="200"/>
</body>
</html>

child.html

<html>
<body>
<h2>Child</h2>
<script type="text/javascript">

// If any of the following lines are uncommented, then it
// will take 9-14 seconds for polling to succeed.
//window.top;
//window.parent;

document.domain = 'localhost';

function time() {
    return (new Date()).getTime();
}

var start = time();
var attempts = 0;
function attempt() {
}

function poll() {
    attempts++;
    var result;
    try {
        window.frameElement;
        // Success! Show the time taken.
        alert('attempts: ' + attempts + ', time: ' + (time() - start));
    } catch (e /* Access is denied */ ) {
        // Failure. Try again in 100ms.
        setTimeout(poll, 100);
    }
}

poll();
</script>
</body>
</html>

After finding this out I was able to get JQuery working for me by changing its frame detection code from

// If IE and not an iframe
// continually check to see if the document is ready
if ( document.documentElement.doScroll && window == window.top ) (function(){
    ...

to

// Check if we're in a frame by looking for enclosing element.
var toplevel;
try {
  toplevel = window.frameElement === undefined;
} catch ( error ) {
  // Assume we're in a frame that cannot access its parent frame.
  toplevel = false;
}

// If IE and not an iframe
// continually check to see if the document is ready
if ( document.documentElement.doScroll && toplevel ) (function(){

There's probably a better way to fix this, but I'm including it in case it helps.

More details: IE 6.0.2900.2180.xpsp_sp2.qfe.090206-1239 Windows XP Pro 5.1.2600 SP2 Build 2600

Change History (3)

comment:1 Changed 10 years ago by richdougherty

I should also say, I can reproduce this problem reliably by refreshing the page once it has already been loaded once. It doesn't (usually) occur when I first load the page in a fresh browser.

comment:2 Changed 10 years ago by jdalton

The delay is also gone if you remove setting the document.domain in the parent.html. I can reproduce your test case. This is a great find. Thanx.

comment:3 Changed 10 years ago by john

Component: coreevent
Resolution: fixed
Status: newclosed
Note: See TracTickets for help on using tickets.