Greasemonkey: Não é possível acessar as variáveis ​​definidas em<script>tags on the actual page.</script>

Criado em 18 nov. 2017  ·  14Comentários  ·  Fonte: greasemonkey/greasemonkey

Com a atualização para Greasemonkey 4, muitos scripts de usuário usando jQuery parecem ter sido corrompidos. Nas versões anteriores, o código a seguir funcionaria em uma página usando jQuery em uma tag <script> :

// ==UserScript==
// <strong i="7">@name</strong>        Variable access test
// <strong i="8">@namespace</strong>   example.com
// ==/UserScript==

$.ready(document, function() {
    console.log("Accessed jQuery successfully.")
});

No entanto, isso não funciona mais - em vez disso, você apenas obtém um $ is not defined clássico. Isso me diz que o Greasemonkey pode estar executando o userscript antes que a tag <script> seja carregada. Isso é estranho, no entanto, visto que o script ainda é executado quando document.readyState é interactive !

Para ter certeza, porém, tentei acessar o jQuery depois de window.addEventListener('load', ...) . Eis que o seguinte exibe um erro diferente:

// ==UserScript==
// <strong i="19">@name</strong>        Variable access test
// <strong i="20">@namespace</strong>   example.com
// ==/UserScript==

window.addEventListener('load', function() {
    console.log("Before accessing jQuery")
    $;
    console.log("Accessed jQuery successfully!")
});

Ele não é executado nem emite um erro - em vez disso, ele congela ao tentar acessar $ . O script simplesmente vai até essa linha e nada mais.


Experimente em qualquer página que use jQuery e você deverá obter o mesmo resultado. Usar @require não é uma solução para este problema - para alguns aplicativos, você precisa acessar a mesma instância do jQuery que a página. Isso provavelmente afeta outros scripts além do jQuery também.

duplicate

Comentários muito úteis

Eu tentei essa abordagem agora (em configurações diferentes) e continuo recebendo erros de permissão independentemente do que faço. Realmente não vale a pena o incômodo neste momento.

Parece duro, mas acho que vou ter que recomendar às pessoas que usem Tampermonkey até que isso esteja fora do caminho. Os scripts de conteúdo, em sua encarnação atual, realmente não se encaixam muito bem no caso de uso do script de usuário.

Todos 14 comentários

Não é realmente um problema do Greasemonkey, é mais um problema de script de conteúdo do Firefox.
https://developer.mozilla.org/en-US/Add-ons/WebExtensions/Content_scripts#Accessing_page_script_objects_from_content_scripts

Atribua seu próprio window.wrappedJSObject ou use unsafeWindow no qual Greasemonkey já atribuiu o objeto empacotado.

@Sxderp Não sei "não é realmente um problema do Greasemonkey" - Tampermonkey e Violentmonkey tratam desse caso sem problemas. Não só isso, mas essa é uma mudança significativa que não é mencionada em nenhuma das postagens do blog.

Para funcionar como esperado com scripts de usuários existentes e ser compatível com outros gerenciadores de scripts de usuários populares, isso não deveria ser corrigido?

Além disso ... isso realmente explica o problema? Por que o script congelaria e não apenas apresentaria uma falha na pesquisa?

Não tenho certeza sobre o congelamento. Copiou seu código e não congela para mim.

Edit: Desculpe, entendeu mal o comentário 'congelar'. Achei que você quisesse dizer que o Greasemonkey não funciona mais. Ele 'congela' (para de executar) nessa linha porque o Javascript atinge um uso antes do erro de declaração. Tenho certeza de que isso é considerado "fatal". Como em, não continua executando o código.


Dando uma olhada rápida no código do Violentmonkey, parece que eles injetam scripts criando <script> elementos . Em vez de usar o método de API tabs.executeScripts() .

Usar isso também tem suas desvantagens, é claro.

Então ... quando o Firefox é executado nessa linha, ele simplesmente para de executar silenciosamente? Sem nenhuma mensagem de erro? Que coisa incrivelmente estranha de se fazer.

Em qualquer caso, não é uma meta manter a compatibilidade com scripts de usuário existentes? Afinal, esse não é um recurso de nicho - fazer a interface com o próprio JavaScript da página é algo muito comum.

Em qualquer caso, não é uma meta manter a compatibilidade com scripts de usuário existentes?

Claro que é. Não somos perfeitos, e este é um projeto de código aberto gratuito criado por voluntários com apenas um limite de tempo livre.

Neste ponto, eu tenho um plano de como melhorar isso, mas estou esperando o Mozilla implementar um recurso que tornaria possível fazer isso com segurança. # 2549

@arantius Eu acho que devo ter

Acho que é uma decisão bem pensada priorizar a segurança sobre a usabilidade aqui. Até que a situação seja resolvida, o que podemos fazer como solução alternativa no lado do autor do script? No meu caso específico, tentei var $ = window.wrappedJSObject.$; e var $= unsafeWindow.$; no início de um script, mas isso me deu outro erro ao tentar usar $(document).ready(...) : Error: Permission denied to access property Symbol.toStringTag .

Erro: permissão negada para acessar a propriedade Symbol.toStringTag

Não acho que seja um problema de window.wrappedJSObject.$ mas sim algum outro objeto que você criou no script de usuário, seja como um objeto literal ou com o construtor new , não foi importado corretamente para o escopo no qual você está tentando acessá-lo (provavelmente o escopo da janela da página).

O link acima fornece detalhes sobre cloneInto que você precisa.

Não, estou quase certo de que o problema é com window.wrappedJSObject.$ . O seguinte falha com o mesmo erro:

// ==UserScript==
// <strong i="7">@name</strong>        Variable access test
// <strong i="8">@namespace</strong>   example.com
// ==/UserScript==

var $ = window.wrappedJSObject.$;

$(document).ready(function() {});

Isso, no entanto, falha silenciosamente:

// ==UserScript==
// <strong i="12">@name</strong>        Variable access test
// <strong i="13">@namespace</strong>   example.com
// ==/UserScript==

var $ = window.wrappedJSObject.$;

$.ready(function() {});

Tentei usar cloneInto , mas não ajudou. Você acha que poderia fornecer um breve exemplo de script de usuário que usa a instância da página de $ ?

Ah, nesse caso você não tem permissão para acessar a função. Em seguida, você precisa usar exportFunction .

// ==UserScript==
// <strong i="7">@name</strong>         ExampleJQuery
// <strong i="8">@version</strong>      1
// <strong i="9">@include</strong>      *
// <strong i="10">@grant</strong>        none
// ==/UserScript==

var unsafeWindow = window.wrappedJSObject;
var $;

// For sanity just return if we don't have the object
if (typeof unsafeWindow.$ === 'undefined') {
  console.log('No jQuery object, returning');
  return;
} else {
  $ = unsafeWindow.$;
}

// Create the function we want to export
function onReady() {
  console.log("I'm ready!");
}
// Export it. Some details on this.
// Argument 1. The function to export
// Argument 2. The scope to export it to. In general this will be window,
//             or some object in the scope. While it is valid to use
//             "window", I prefer to use "unsafeWindow" if I'm exporting
//             into that scope. I find it less confusing.
// Return      This is a reference to exported function. In general you'll
//             assign this to some property of the scope you're exporting
//             into. However, it's not always neccessary. For example, if
//             you're going to use it as a callback (like for .ready())
//             then you don't need to assign it into the exported scope.
//             But if you want it globally (or scopally) accessable then
//             you need to assign it.
let exported_onReady = exportFunction(onReady, unsafeWindow);
// OR
// unsafeWindow.onReady = exportFunction(onReady, unsafeWindow);

$(document).ready(exported_onReady);
// OR
// $(document).ready(unsafeWindow.onReady);

Eu tentei essa abordagem agora (em configurações diferentes) e continuo recebendo erros de permissão independentemente do que faço. Realmente não vale a pena o incômodo neste momento.

Parece duro, mas acho que vou ter que recomendar às pessoas que usem Tampermonkey até que isso esteja fora do caminho. Os scripts de conteúdo, em sua encarnação atual, realmente não se encaixam muito bem no caso de uso do script de usuário.

Concordo com @obskyr , apenas recomendo meu pessoal para usar tampermonkey

+1, movido para Tampermonkey (https://addons.mozilla.org/en-US/firefox/addon/tampermonkey/), parece que todos os meus scripts funcionam lá.

+1, movido para Tampermonkey (https://addons.mozilla.org/en-US/firefox/addon/tampermonkey/), parece que todos os meus scripts funcionam lá.

Isso pode funcionar a curto prazo e funciona bem para manter os scripts em execução, mas, a longo prazo, pode ser uma decisão falsa confiar em uma substituição completa. O sucesso de curto prazo pode ser míope ... ;-)

Eu uso o TM como um substituto, mas há alguns problemas com ele, não posso negar. Além disso, pode haver alguns problemas de segurança com FF Quantum, por isso funciona, mas não se deve confiar em uma única solução apenas ...

Bem, eu preciso oferecer suporte ao TM em meus scripts, porque nem todo mundo usa o Firefox. Antes eu apoiava GM e TM, agora é apenas TM. Não notei nenhum problema até agora.

Esta página foi útil?
0 / 5 - 0 avaliações