Как сделать 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) { ... });
). Это делает код более паршивым, но так оно и есть.