Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Object.create fails for IE<9 if document.domain is set #150

Closed
angus-c opened this issue Feb 6, 2013 · 14 comments
Closed

Object.create fails for IE<9 if document.domain is set #150

angus-c opened this issue Feb 6, 2013 · 14 comments

Comments

@angus-c
Copy link

angus-c commented Feb 6, 2013

If the main document has domain attribute set then we get a permission denied error trying to access iframe.contentWindow.Object (due to same-domain restriction)

Tried to patch it up with very hokey iframe.src code:

iframe.src = "javascript:'<script>window.onload=function(){document.write(\\'<script>document.domain=\\\"" + document.domain + "\\\";<\\\\/script>\\');document.close();};<\/script>'";

but it didn't do the trick.

This issue is preventing twitter.com from upgrading to latest es5-shim

@kriskowal
Copy link
Member

The use of the iframe is a recent addition. We may be able to back it out. Thanks.

@ghost
Copy link

ghost commented Feb 6, 2013

@kriskowal
Copy link
Member

Looks like we can’t back it out. This is our only recourse for getting Object.create(null) to work on IE.

@angus-c, one issue I see with the solution you tried is that there is a chance that the onload handler is introducing a race between the iframe loading and the first use of Object.create. Does the domain need to be assigned after the load event?

@angus-c
Copy link
Author

angus-c commented Feb 6, 2013

The code is currently in an IIFE - so gets invoked even if Object.create(null)
not used. Could make it contingent on Object.create(null) so doesn't break
in loading. I think Brandon mentioned this

Yes agree about the sync issue.

On Wed, Feb 6, 2013 at 12:47 PM, Kris Kowal notifications@github.comwrote:

Looks like we can’t back it out. This is our only recourse for getting
Object.create(null) to work on IE.

@angus-c https://github.com/angus-c, one issue I see with the solution
you tried is that there is a chance that the onload handler is introducing
a race between the iframe loading and the first use of Object.create. Does
the domain need to be assigned after the load event?


Reply to this email directly or view it on GitHubhttps://github.com//issues/150#issuecomment-13204211.

@kriskowal
Copy link
Member

Okay. Let’s set up the iframe on the first use.

@kriskowal
Copy link
Member

@angus-c, can you check out the pull request I just posted and let me know if that resolves the issue for you?

@ghost
Copy link

ghost commented Feb 6, 2013

Actually, I believe new ActiveXObject("htmlfile") is a viable alternative to a frame in IE (though it needs to be cached so that it's not garbage collected; the cache can be cleared via cache.length = 0 on unload).

We used something like this in FuseJS:

// `cache` and the listener only need to be set up once.
var cache = [];
if (typeof attachEvent != "undefined") {
  attachEvent("onunload", function() {
    cache.length = 0;
});
// ...
var doc = new ActiveXObject("htmlfile");
doc.write("<script><\/script>");
doc.close();
cache.push(doc);
var empty = doc.parentWindow.Object.prototype;
// ...

@ghost
Copy link

ghost commented Feb 6, 2013

FuseJS is exactly who I was thinking of earlier: "I know people have used hidden iframes or SOMETHING for shims in old IE and been successful". I think that is likely to be the winner, as I have a feeling the above delayed-loading solution doesn't address the underlying problem (haven't tested it though).

@kriskowal
Copy link
Member

@kitcambridge, go for it!

@ghost
Copy link

ghost commented Feb 6, 2013

Working on a branch now—we'll probably want to keep the frame around for cases where the browser doesn't support __proto__ or ActiveX (i.e., older versions of Opera), or ActiveX is disabled.

@angus-c
Copy link
Author

angus-c commented Feb 6, 2013

Still failing in same place - not sure why, given your change - hard to
debug minified code.
In any case @kit's fix looks promising - as it would actually support
Object.create(null)

On Wed, Feb 6, 2013 at 1:08 PM, Kris Kowal notifications@github.com wrote:

@angus-c https://github.com/angus-c, can you check out the pull request
I just posted and let me know if that resolves the issue for you?


Reply to this email directly or view it on GitHubhttps://github.com//issues/150#issuecomment-13205207.

@jdalton
Copy link
Contributor

jdalton commented Mar 7, 2013

Yap, as Kit pointed out we used, in part, iframes and ActiveX for "Sandboxed Natives". The ActiveX('htmlfile') avoids issues with HTTPS mixed content warnings in IE6 and document.domain issues in older IE. Notice that we clear the cache on window unload, that's because there is a memory-leak associated with ActiveX('htmlfile') and that helped avoid it.

@jdalton
Copy link
Contributor

jdalton commented Mar 7, 2013

Here is notes from an old WIP rewrite of Sandboxed Natives (I should really revisit that):

// The htmlfile ActiveX object is supported by IE4+ and avoids https mixed
// content warnings in IE6. It's also used to workaround access denied errors
// thrown when using iframes to create sandboxes after the `document.domain` is
// set (Opera 9.25 is out of luck here).
!isHostType( window, 'XMLHttpRequest' ) && window.location == 'https:' && has.activex ||
// iframes are the fastest and prefered technique
has.iframe ||
// optimized Node.js support
has.nodejs ||
// A fallback for non browser environments supported by JavaScript engines
// such as Carakan, JaegerMonkey, JavaScriptCore, KJS, Nitro, Rhino,
// SpiderMonkey, SquirrelFish (Extreme), Tamarin, TraceMonkey, and V8.
has.proto;

@ryanve
Copy link

ryanve commented May 12, 2013

Another possible way to quasi-emulate Object.create(null) would be to convert a plain object into an emptyParent by setting all its properties/dontEnums to undefined (such that they override Object.prototype properties without modifying them). Then Object.create(null) could do Object.create(emptyParent). It's not exactly the same, but for most uses, it would suffice.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants