Greasemonkey has been a Firefox extension for well over a decade, with version 0.3.5 dating from 2005. We've grown and changed a lot over that time. With the upcoming Firefox 57 release, we need to change even more. Mozilla is completely replacing the extension system in Firefox, to align with the budding Browser Extension standard, based on/shared with Google Chrome.
As a result, version 4 of Greasemonkey is a nearly complete re-write. Its interface and feature set have been rebuilt in order to best to work with coming Firefox versions. A variety of compromises have been made. We've elected to make a rare backwards incompatible change.
If you are a regular user, please continue reading Greasemonkey 4 For Users.
If you are a developer, please continue reading Greasemonkey 4 For Script Authors.
Wednesday, September 20, 2017
Greasemonkey 4 For Script Authors
As mentioned in the main post, Greasemonkey 4 is changing to be compatible with the Browser Extension API. At its core, this set of APIs is completely asynchronous. Greasemonkey's old "GM_" APIs are typically synchronous.
First, there is only an embedded editor. Browser Extensions have no access to the file system, so you can no longer author user scripts in your familiar text editor.
There is only one object provided to user scripts now, named GM. It has several properties. One of them is info – the equivalent of the old GM_info. There are also several methods of this object: getResourceUrl, deleteValue/getValue/listValues/setValue, xmlHttpRequest.
To use these methods you still need @grant, and use the new name, e.g.:
In general these methods work like their old counterparts, but their return values are Promises. The async and await keywords make asynchronous promises easy to work with. For example:
If you'd like your script to be compatible with Greasemonkey 4 and also Greasemonkey 3 (or other user script engines), we have provided a polyfill, which makes new-style API calls work on top of older engines. To use it: 1) keep your old-API @grant line, 2) add a new-API @grant line, 4) require the polyfill script, 4) switch your code to use new-API style (and probably async/await). So the above example might look like:
Why?
There exist other user script engines which have already done the work of bridging the gap. Greasemonkey has elected to move exclusively towards a more performant asynchronous model. Eventually in the future, such scripts will be faster.What?
The Greasespot Wiki has been updated to explain Greasemonkey 4 in detail. Here's a quick summary.First, there is only an embedded editor. Browser Extensions have no access to the file system, so you can no longer author user scripts in your familiar text editor.
There is only one object provided to user scripts now, named GM. It has several properties. One of them is info – the equivalent of the old GM_info. There are also several methods of this object: getResourceUrl, deleteValue/getValue/listValues/setValue, xmlHttpRequest.
To use these methods you still need @grant, and use the new name, e.g.:
// @grant GM.setValueThe new form has a dot, where the old form has an underscore. You may specify both @grants, if you'd like to be compatible with Greasemonkey 4 and other user script engines at the same time. As of today, there is no support for: GM_log (use console.log), GM_addStyle, GM_registerMenuCommand, nor GM_getResourceText.
In general these methods work like their old counterparts, but their return values are Promises. The async and await keywords make asynchronous promises easy to work with. For example:
// ==UserScript==Here the GM.getValue() method actually returns a promise, but the await keyword transparently converts that to its resolved value, allowing us to write code just as if the value was directly returned – with neither callbacks nor promise resolution. See the documentation on async and await.
// @name GM set/get demo
// @grant GM.getValue
// @grant GM.setValue
// ==/UserScript==
(async function() {
console.log('Starting the get/set demo ...');
let i = await GM.getValue('i', 0);
console.log(`This time, i was ${i}.`);
GM.setValue('i', i+1);
})();
If you'd like your script to be compatible with Greasemonkey 4 and also Greasemonkey 3 (or other user script engines), we have provided a polyfill, which makes new-style API calls work on top of older engines. To use it: 1) keep your old-API @grant line, 2) add a new-API @grant line, 4) require the polyfill script, 4) switch your code to use new-API style (and probably async/await). So the above example might look like:
// ==UserScript==With the exact same new-API style code as above. Such a script can be installed in either Greasemonkey 4 or Greasemonkey 3 (or TamperMonkey, or ViolentMonkey, etc.) and work as intended.
// @name GM set/get demo
// @require https://greasemonkey.github.io/gm4-polyfill/gm4-polyfill.js// @grant GM.getValue
// @grant GM_getValue// @grant GM.setValue
// @grant GM_setValue
// ==/UserScript==
...
unsafeWindow
Due to the more limited abilities that the new extension system gives us, we are currently unable to make @grant none scripts work in the same way. Most importantly, they have a different connection to unsafeWindow. For the short term at least, it's a good idea to adopt cloneInto and exportFunction.Naming
Do note that new style APIs have slightly different names. In short, a consistent naming style has been adopted: all words and acronyms get a consistent case. So what was before GM_getResourceURL is now GM.getResourceUrl. What was GM_xmlhttpRequest is now GM_xmlHttpRequest. In the near future the Greasespot Wiki will be updated with all details of the new APIs, including exact names with case.Feedback
We welcome feedback, reach out via the greasemonkey-users discussion group. Please also keep in mind the volunteer nature of this open source project when doing so!Greasemonkey 4 For Users
As mentioned in the main post, Greasemonkey 4 is changing how it runs user scripts. Many user scripts will continue to run as expected, but this will break some scripts. If you rely on such scripts, you might want to install Violentmonkey or Tampermonkey, both of which provide better compatibility for existing scripts.
We welcome feedback, reach out via the greasemonkey-users discussion group. Please also keep in mind the volunteer nature of this open source project when doing so!
Scripts
If you'd prefer to stick with Greasemonkey, you'll need to wait for the script to be updated to be compatible. Find the original author of your script, and ask them to update for Greasemonkey 4 compatibility. Referencing this post may help. And please know that we'll continue working to improve further and further as time goes on!Features
Due to the external deadline (when Firefox 57 comes, Greasemonkey 3 won't work anymore) not all features you're used to are available. For example: Firefox Sync and script auto update are missing. There are no per-script settings (custom include/exclude), and some of the UI is still quite basic. This as well will be improved in the future.We welcome feedback, reach out via the greasemonkey-users discussion group. Please also keep in mind the volunteer nature of this open source project when doing so!
Tuesday, September 19, 2017
Greasemonkey 3.12 Release
The entire list of bugs handled in this release is also available via the 3.12 milestone
on GitHub. Note that as always it takes some time for Mozilla to
review the new version. If you're interested in staying on the bleeding
edge, try installing the development channel beta release. If you are using this version and notice problems, it's best to log an issue or let us know at greasemonkey-dev (and be clear that it's with this version).
Fixed bugs:
Fixed bugs:
- Repair rare breakage in GM_getValue/GM_setValue. (#2506)
- Migrate existing scripts to a WebExtension (for Firefox 57+) compatible data storage location. (#2551)