Tuesday, August 28, 2012

Greasemonkey 1.0 + jQuery: Broken, with Workaround

One of the big changes behind Greasemonkey 1.0 was moving towards the goal of not forcing the security sandbox (and all its pitfalls) upon script authors.  This is the entire reason for @grant, and specifically the @grant none setting.  In the @grant none case, the script does not get the traditional security sandbox (with XPCNativeWrappers), but rather a very thin sandbox that exclusively acts as a private scope, to hold variables for the script that don't interact with the page.

The idea was, if you want to set something in the page, you just do window.foo = 'bar', and if you don't it's just a normal var foo = 'bar'.  But there's a problem.

If you @require jQuery, it implicitly does a window.$ = window.jQuery = ...,  which exports the copy of jQuery that your script is loading into the page.  If they're different versions, there is a very real possibility of completely breaking the page.

This is Greasemonkey issue 1614, which is open and being tracked for a fix.  In the meantime, you can insert a one line fix into your script, at the top level (not inside any functions):

this.$ = this.jQuery = jQuery.noConflict(true);

This line just calls the standard jQuery noConflict() method, so that this loaded version of jQuery doesn't conflict with anything already in the page.  It's already there, it's exactly what it's for!  And saves a local (in the script) reference to the version of jQuery that you want to use.

This should let your script keep working, and also keep the page from breaking.  It's only lightly tested so far; let us know in the comments if it helps you.

No comments: