Greasemonkey: No se puede acceder a las variables definidas en<script>tags on the actual page.</script>

Creado en 18 nov. 2017  ·  14Comentarios  ·  Fuente: greasemonkey/greasemonkey

Con la actualización a Greasemonkey 4, muchos scripts de usuario que usan jQuery parecen haberse roto. En las versiones anteriores, el siguiente código funcionaría en una página usando jQuery en una etiqueta <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.")
});

Sin embargo, eso ya no funciona; en su lugar, solo obtienes un $ is not defined clásico. Eso me dice que Greasemonkey podría estar ejecutando el script de usuario antes de que se cargue la etiqueta <script> . Sin embargo, eso es extraño, ya que el script aún se ejecuta cuando document.readyState es interactive !

Sin embargo, para estar seguro, intenté acceder a jQuery después de window.addEventListener('load', ...) . He aquí, lo siguiente exhibe un error 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!")
});

No se ejecuta ni arroja un error; en cambio, se congela al intentar acceder a $ . El script simplemente corre hasta esa línea y no más.


Pruébelo en cualquier página que use jQuery y obtendrá el mismo resultado. Usar @require no es una solución a este problema; para algunas aplicaciones, necesita acceder a la misma instancia de jQuery que la página. Lo más probable es que esto también afecte a otros scripts que no sean jQuery.

duplicate

Comentario más útil

Probé ese enfoque ahora (en diferentes configuraciones), y sigo recibiendo errores de permiso en todo lo que hago. Realmente no vale la pena molestarse en este momento.

Suena duro, pero creo que tendré que recomendar a las personas que utilicen Tampermonkey hasta que esto se solucione. Los scripts de contenido, en su encarnación actual, realmente no se ajustan muy bien al caso de uso del script de usuario.

Todos 14 comentarios

No es realmente un problema de Greasemonkey, más bien un problema de script de contenido de Firefox.
https://developer.mozilla.org/en-US/Add-ons/WebExtensions/Content_scripts#Accessing_page_script_objects_from_content_scripts

Asigne su propio window.wrappedJSObject o use unsafeWindow en el que Greasemonkey ya ha asignado el objeto envuelto.

@Sxderp No sé acerca de "no es realmente un problema de Greasemonkey" - tanto Tampermonkey como Violentmonkey manejan este mismo caso sin problemas. No solo eso, sino que este es un cambio importante que no se menciona en ninguna de las publicaciones del blog.

Para funcionar como se esperaba con los scripts de usuario existentes y ser compatible con otros gestores de script de usuario populares, ¿no debería solucionarse esto?

Además ... ¿esto realmente explica el problema? ¿Por qué se congelaría el script y no solo fallaría la búsqueda?

No estoy seguro de la congelación. Copió su código y no se congela para mí.

Editar: Lo siento, entendí mal el comentario de 'congelar'. Pensé que querías decir que Greasemonkey ya no funciona. Se 'congela' (deja de ejecutarse) en esa línea porque Javascript golpea un uso antes del error de declaración. Estoy bastante seguro de que eso se considera "fatal". Como en, no continúa ejecutando código.


Echando un vistazo rápido al código Violentmonkey, parece que se inyectan mediante la creación de guiones <script> elementos . En lugar de usar el método tabs.executeScripts() API.

Usar eso también tiene sus propios inconvenientes, por supuesto.

Entonces ... cuando Firefox se encuentra con esa línea, ¿deja de ejecutarse silenciosamente? ¿Sin ningún mensaje de error? Qué cosa tan increíblemente extraña de hacer.

En cualquier caso, ¿no es un objetivo mantener la compatibilidad con los scripts de usuario existentes? Después de todo, esta no es una característica de nicho: interactuar con el propio JavaScript de la página es algo muy común.

En cualquier caso, ¿no es un objetivo mantener la compatibilidad con los scripts de usuario existentes?

Por supuesto que es. No somos perfectos, y este es un proyecto de código abierto gratuito creado por voluntarios con poco tiempo libre.

En este punto, tengo un plan sobre cómo mejorar esto, pero está esperando que Mozilla implemente una función que permita hacerlo de forma segura. N.º 2549

@arantius Creo que podría haber sido un poco confrontativo ... Lo siento por eso.

Supongo que es una decisión bien pensada priorizar la seguridad sobre la usabilidad aquí. Hasta que la situación se resuelva, ¿qué podemos hacer como solución en el lado del autor del guión? En mi caso específico, probé var $ = window.wrappedJSObject.$; y var $= unsafeWindow.$; en la parte superior de un script, pero eso me dio otro error al intentar usar $(document).ready(...) : Error: Permission denied to access property Symbol.toStringTag .

Error: Permiso denegado para acceder a la propiedad Symbol.toStringTag

No creo que sea un problema del window.wrappedJSObject.$ sino que algún otro objeto que creó en el script de usuario, ya sea como un objeto literal o con el constructor new , no se ha importado correctamente a ámbito en el que está intentando acceder a él (probablemente el ámbito de la ventana de la página).

El enlace anterior proporciona detalles sobre cloneInto que es lo que necesitará.

No, estoy bastante seguro de que el problema está en window.wrappedJSObject.$ . Lo siguiente falla con el mismo error:

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

var $ = window.wrappedJSObject.$;

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

Esto, sin embargo, falla silenciosamente:

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

var $ = window.wrappedJSObject.$;

$.ready(function() {});

Intenté usar cloneInto , pero no ayudó. ¿Crees que podrías proporcionar un breve ejemplo de script de usuario que use la instancia de la página de $ ?

Ah, en ese caso no tienes permiso para acceder a la función. Luego debe 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);

Probé ese enfoque ahora (en diferentes configuraciones), y sigo recibiendo errores de permiso en todo lo que hago. Realmente no vale la pena molestarse en este momento.

Suena duro, pero creo que tendré que recomendar a las personas que utilicen Tampermonkey hasta que esto se solucione. Los scripts de contenido, en su encarnación actual, realmente no se ajustan muy bien al caso de uso del script de usuario.

De acuerdo con @obskyr , solo recomiendo a mi gente que use tampermonkey

+1, movido a Tampermonkey (https://addons.mozilla.org/en-US/firefox/addon/tampermonkey/), parece que todos mis scripts funcionan allí.

+1, movido a Tampermonkey (https://addons.mozilla.org/en-US/firefox/addon/tampermonkey/), parece que todos mis scripts funcionan allí.

Esto puede funcionar a corto plazo y funciona bien para mantener los scripts en ejecución, pero a la larga, podría ser una decisión falsa confiar en una sustitución completa. El éxito a corto plazo puede ser miope ... ;-)

Utilizo la MT como sustituto, pero hay algunos problemas con ella, no puedo negarlo. Además, puede haber algunos problemas de seguridad con FF Quantum, por lo que funciona, pero no se debe confiar en una única solución ...

Bueno, necesito admitir TM en mis scripts de todos modos porque no todos usan Firefox. Entonces, antes apoyaba a GM y TM, ahora es solo TM. No noté ningún problema hasta ahora.

¿Fue útil esta página
0 / 5 - 0 calificaciones