Как сделать GM_getValue существующим в Greasemonkey в Firefox?

Кандидат в дураки для предыдущих версий GM. Проблема, скорее всего, где-то в разных областях, где могут работать пользовательские скрипты, как описано здесь. Однако, как описано здесь, эта функциональность в настоящее время недокументирована для Greasemonkey 4.0.

У меня есть этот демо-скрипт Greasemonkey:

// ==UserScript==
// @name         GM_getValue, GM_setValue don't work demo
// @version      0.2
// @author       You
// @include      /^https:\/\/stackru.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);

Вызывая это с https://stackru.com/, хорошо видно, что это называется.

Тем не менее, я получаю эту ошибку на консоли:

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

Я много копал документы, но кажется GM_{get,set}Value просто не хочу существовать.

Почему это так? Как заставить это работать?

Я использую Firefox.

1 ответ

Решение

GM_getValue а также GM_setValue теперь устарели в GreaseMonkey. Правильные методы GM.setValue а также GM.getValue,

Документация GreaseMonkey часто использует старые имена вызовов API, что является постоянной ошибкой. Возможно, это не было правильно обновлено.

Как сказано в документации, функции GM могут работать в разных областях. К сожалению, я до сих пор не нашел никакой информации о том, какие области существуют и как мы можем переключаться между ними.

Старые ссылки везде в сети, используя GM_getValue все устарели.

Важные вещи:

  • В то время как GM_getValue были функции с возвращаемым значением, GM.getValue а также GM.setValue вернуть Promise s.
  • Вы можете использовать их почти так же, как вы использовали в старых, хороших версиях, используя await вызов.

Этот пример по удаленной ссылке работает:

// ==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');
})();

Тем не менее, до сих пор нет более четкой документации по областям и тому, как мы можем взаимодействовать с ними.

Кажется, есть как минимум две области применения:

  • В одном из них вы можете манипулировать DOM, но не имеете доступа к GM.* API.
  • В другом у вас есть доступ к GM.* API (и, следовательно, вы можете создать постоянное локальное хранилище для сценариев), но не имеете доступа к DOM.
  • Между областями мы можем общаться через асинхронные вызовы.
  • Почему эта проблема повышает безопасность, вероятно, даже разработчики GM не могли бы сказать.

Таким образом, способ разработки новых сценариев GreaseMonkey для 4.0 состоит в том, чтобы начать с их примера сценария, а затем следовать инкрементному пути проб и ошибок.


Расширение: еще одна проблема, которую я нашел: существование await в скрипте, кажется, заставляет greasemonkey игнорировать весь скрипт et al. В этом примере этого не происходит, но в более сложных сценариях это происходит. Я не отлаживал это слишком глубоко - я просто игнорирую await и использовать обещания по-старому (GM.getValue("myValue").then(function(myValue) { ... });). Это делает код более паршивым, но так оно и есть.

Другие вопросы по тегам