public
Last active

`unsafeWindow` polyfill (for use in user scripts)

  • Download Gist
unsafeWindow.user.js
JavaScript
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
// ==UserScript==
// @name Emulate `unsafeWindow` in browsers that don’t support it.
// ==/UserScript==
 
// http://mths.be/unsafewindow
window.unsafeWindow || (
unsafeWindow = (function() {
var el = document.createElement('p');
el.setAttribute('onclick', 'return window;');
return el.onclick();
}())
);
 
// You can now use `unsafeWindow`, ehm, safely.
console.log(unsafeWindow);
// If the current document uses a JavaScript library, you can use it in
// your user script like this:
console.log(unsafeWindow.jQuery);

Other things I’ve tried:

  • document.defaultView: returns a window object but doesn’t inherit global variables from the document (e.g. unsafeWindow.jQuery === undefined)

  • Function('return window')() (or even Function('return this')()) (suggested by @jdalton): same as above

  • window.wrappedJSObject (to which unsafeWindow is an alias in Greasemonkey)

P.S. It bothers me that in the fallback case, unsafeWindow is an implied global, but window.unsafeWindow = … (or this.unsafeWindow = …) don’t work.

[Update]

Used === instead of == and finally instead of an empty catch.

var gm_win = (function(){
    var a;
    try {
        a = unsafeWindow === window ? false : unsafeWindow;
    } finally {
        return a || (function(){
            var e = document.createElement('p');
            e.setAttribute('onclick', 'return window;');
            return e.onclick();
        }());
    }
}());

console.log(gm_win.SOMEAUTHKEY);

[Original]

This snippet is helpful, and it works when used in Opera and Chrome. However, I find that GM's unsafeWindow becomes invalid if this is used in Firefox. Probably because it's not part of the window object. In other words, I can't get it to work in Firefox.

Here's my solution.

var gm_uwin = (function(){
    var a;
    try {
        a = unsafeWindow == window ? false : unsafeWindow; // Chrome: window == unsafeWindow
    } catch(e) { }
    return a || (function(){
            var el = document.createElement('p');
            el.setAttribute('onclick', 'return window;');
            return el.onclick();
        }());
}());

console.log(gm_uwin.SOMEAUTHKEY); // This works in all three browsers.

Chrome creates an anon function that wraps window as the argument for unsafeWindow so they are actually the same safe-window object. Opera will throw an error. If a is false the fill is used, otherwise the real unsafeWindow is returned for Firefox.

@mathiasbynens
Is it just me or did they fix it in the latest Canary?
It returns the safe window, not the unsafe one anymore.

Think there is a issue on Canary Build 28.0.1477.2

It seems like this no longer works in Chrome 29.

Please sign in to comment on this gist.

Something went wrong with that request. Please try again.