Side navigation
#4787 closed bug (fixed)
Opened June 19, 2009 03:59AM UTC
Closed November 11, 2009 06:57PM UTC
Last modified March 15, 2012 07:47PM UTC
$(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
Attachments (0)
Change History (3)
Changed June 19, 2009 04:11AM UTC by comment:1
Changed June 24, 2009 04:43PM UTC by comment:2
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.
Changed November 11, 2009 06:57PM UTC by comment:3
component: | core → event |
---|---|
resolution: | → fixed |
status: | new → closed |
Rich, landed your patch - thanks!
http://github.com/jquery/jquery/commit/bf71575bb4f37321b71ef8ce21c8208ad2b192da
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.