How to make GM_getValue existent in Greasemonkey on Firefox?
Asked Answered
T

1

9

I have this Greasemonkey demo script:

// ==UserScript==
// @name         GM_getValue, GM_setValue don't work demo
// @version      0.2
// @author       You
// @include      /^https:\/\/stackoverflow.com/$/
// @grant        GM_getValue
// @grant        GM_setValue
// @run-at       document-end
// ==/UserScript==

console.log('script started');
var id = GM_getValue('testName', 0);
console.log('got ' + id);
id++;
GM_setValue('testName', id);

Calling this with the https://stackoverflow.com/, it is well visible that it is called.

However, I get this error on the console:

Script error:  
ReferenceError: GM_getValue is not defined
Stack trace:
userScript@user-script:demosrv/GM_getValue%2C%20GM_setValue%20don%27t%20work%20demo:372:5
scopeWrapper@user-script:demosrv/GM_getValue%2C%20GM_setValue%20don%27t%20work%20demo:381:9
@user-script:demosrv/GM_getValue%2C%20GM_setValue%20don%27t%20work%20demo:361:17

I've digged docs a lot, but it seems GM_{get,set}Value simply don't want to exist.

Why is it so? How to make it working?

I am using Firefox.

Thagard answered 24/11, 2017 at 15:36 Comment(1)
Extension from the future: I've recently tried Tampermonkey. It looks far better in all senses. It is compatible with Greasemonkey userscripts.Thagard
T
17

GM_getValue and GM_setValue are now obsolete in the GreaseMonkey. The correct methods are GM.setValue and GM.getValue.

The GreaseMonkey documentation uses often the old API call names, which is a continuous error in it. Probably it wasn't correctly updated.

As the documentation here says, GM functions can run in different scopes. Unfortunately, I didn't find any info until now, which scopes are existing and how can we switch between them.

The old references manywhere on the net, using GM_getValue are all obsolete.

The important things:

  • While GM_getValue were functions with a return value, GM.getValue and GM.setValue return Promises.
  • You can use them nearly as you used in the old, nice versions, using the await call.

This example on the remote link, works:

// ==UserScript==
// @name        Greasemonkey set-and-get Example
// @description Stores and logs a counter of executions.
// @grant       GM.setValue
// @grant       GM.getValue
// ==/UserScript==

(async () => {
  let count_before = await GM.getValue('count', 0);

  // Note awaiting the set -- required so the next get sees this set.
  await GM.setValue('count', count_before + 1);

  // Get the value again, just to demonstrate order-of-operations.
  let count_after = await GM.getValue('count');

  console.log('Greasemonkey set-and-get Example has run', count_after, 'times');
})();

However, there is still no more clear documentation about the scopes and how can we interact with them.

It seems, there are at least two scopes:

  • In one of them, you can manipulate the DOM, but don't have access to the GM.* API.
  • In another, you have access to the GM.* API (and thus, you can make script-local persistent storage), but don't have access to the DOM.
  • Between the scopes, we can communicate through asychronous calls.
  • Why would this trouble increase the security, probably not even the GM developer(s) could say.

Thus, the way to develop new GreaseMonkey scripts for 4.0, is to start with their example script and then follow an incremental trial & error path.


Extension: another trouble I've found: the existence of await in the script seems to make greasemonkey to ignore the whole script et al. In the example, it doesn't seem to happen, but in more complex scripts, it does. I didn't debug it too deeply - I simply ignore await and use the Promises on the old way (GM.getValue("myValue").then(function(myValue) { ... });). It makes the code more crappy, but so is it.

Thagard answered 24/11, 2017 at 15:42 Comment(5)
Yeap, I can't seem to reproduce their example in the documentation. The moment GreaseMonkey sees the await word in the script, it just doesn't execute the script. This is horrible.Bouncy
@Sudhi Yeah. But, for example, the example works. As I tried to extend it, it suddenly stopped working on a point. I have no idea, why. Maybe this userscript ignorer feature of the GM is initiated by the existence of await and yet another thing - I don't know, exactly what.Thagard
Thanks. I couldn't figure out either. I gave up, and decided to go back to 3.17 on FirefoxESR. Now GM_getValue('foo', 'init'); returns null to me :-/Bouncy
@Sudhi Promises are not so bad on second spot as for the first, and I don't like to downgrade. So I solved the problem with promises, but without await. I have no idea, what could make such a popular software so badly maintained.Thagard
Chiming in here to say thank you for confirming that the presence of await makes GreaseMonkey entirely ignore the script - I felt sure I must be missing something.Gallant

© 2022 - 2024 — McMap. All rights reserved.