Greasemonkey: Tidak dapat mengakses variabel yang ditentukan dalam<script>tags on the actual page.</script>

Dibuat pada 18 Nov 2017  ·  14Komentar  ·  Sumber: greasemonkey/greasemonkey

Dengan pembaruan ke Greasemonkey 4, banyak skrip pengguna yang menggunakan jQuery tampaknya telah rusak. Di versi sebelumnya, kode berikut akan berfungsi pada halaman yang menggunakan jQuery dalam 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.")
});

Namun, itu tidak berfungsi lagi - sebagai gantinya, Anda hanya mendapatkan $ is not defined klasik. Itu memberitahu saya bahwa Greasemonkey mungkin menjalankan skrip pengguna sebelum tag <script> dimuat. Itu aneh, bagaimanapun, mengingat skrip masih berjalan ketika document.readyState adalah interactive !

Namun yang pasti, saya mencoba mengakses jQuery setelah window.addEventListener('load', ...) . Lihatlah, berikut ini menunjukkan kesalahan yang berbeda:

// ==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!")
});

Itu tidak berjalan atau membuat kesalahan - sebaliknya, macet ketika mencoba mengakses $ . Script hanya berjalan hingga baris itu dan tidak lebih jauh.


Cobalah di halaman mana pun yang menggunakan jQuery dan Anda akan mendapatkan hasil yang sama. Menggunakan @require bukanlah solusi untuk masalah ini - untuk beberapa aplikasi, Anda memerlukan akses ke instance jQuery yang sama dengan halaman. Ini kemungkinan besar memengaruhi skrip selain jQuery juga.

duplicate

Komentar yang paling membantu

Saya sudah mencoba pendekatan itu sekarang (dalam konfigurasi yang berbeda), dan saya terus mendapatkan kesalahan izin apa pun yang saya lakukan. Ini benar-benar tidak sebanding dengan kerumitannya saat ini.

Kedengarannya kasar, tapi saya pikir saya hanya perlu merekomendasikan orang menggunakan Tampermonkey sampai ini selesai. Skrip konten, dalam inkarnasinya saat ini, benar-benar tidak cocok dengan kasus penggunaan skrip pengguna sama sekali.

Semua 14 komentar

Bukan masalah Greasemonkey, lebih merupakan masalah skrip konten Firefox.
https://developer.mozilla.org/en-US/Add-ons/WebExtensions/Content_scripts#Accessing_page_script_objects_from_content_scripts

Tetapkan window.wrappedJSObject atau gunakan unsafeWindow di mana Greasemonkey telah menetapkan objek yang dibungkus.

@Sxderp Saya tidak tahu tentang "bukan masalah Greasemonkey" - baik Tampermonkey dan Violentmonkey menangani kasus ini tanpa masalah. Tidak hanya itu, tetapi ini adalah perubahan besar yang tidak disebutkan di salah satu posting blog.

Agar berfungsi seperti yang diharapkan dengan skrip pengguna yang ada dan agar kompatibel silang dengan pengelola skrip pengguna populer lainnya, bukankah ini harus diperbaiki?

Juga ... apakah ini benar-benar menjelaskan masalah ini? Mengapa skrip membeku dan tidak hanya gagal mencari?

Saya tidak yakin tentang pembekuan. Menyalin kode Anda dan itu tidak membeku untuk saya.

Sunting: Maaf, salah paham dengan komentar 'beku'. Saya pikir maksud Anda Greasemonkey tidak berfungsi lagi. Itu 'membeku' (berhenti mengeksekusi) pada baris itu karena Javascript menyentuh kesalahan penggunaan sebelum deklarasi. Cukup yakin itu dianggap 'fatal'. Seperti pada, tidak melanjutkan mengeksekusi kode.


Melihat sekilas kode Violentmonkey, sepertinya mereka menyuntikkan skrip dengan membuat elemen <script> . Daripada menggunakan metode API tabs.executeScripts() .

Menggunakan itu memiliki kekurangannya sendiri juga, tentu saja.

Jadi... ketika Firefox berjalan ke baris itu, itu diam-diam berhenti mengeksekusi? Tanpa pesan kesalahan? Apa hal yang sangat aneh untuk dilakukan.

Bagaimanapun, bukankah tujuan untuk menjaga kompatibilitas dengan skrip pengguna yang ada? Bagaimanapun, ini bukan fitur khusus - berinteraksi dengan JavaScript halaman itu sendiri adalah hal yang sangat umum untuk dilakukan.

Bagaimanapun, bukankah tujuan untuk menjaga kompatibilitas dengan skrip pengguna yang ada?

Tentu saja. Kami tidak sempurna, dan ini adalah proyek open source gratis yang dibuat oleh para sukarelawan dengan hanya begitu banyak waktu luang.

Pada titik ini, saya memiliki rencana untuk meningkatkan ini, tetapi menunggu Mozilla untuk mengimplementasikan fitur yang memungkinkan untuk melakukannya dengan aman. #2549

@arantius Saya pikir saya mungkin sedikit konfrontatif... Maaf tentang itu.

Saya kira ini adalah keputusan yang matang untuk memprioritaskan keamanan daripada kegunaan di sini. Sampai situasi teratasi, apa yang bisa kita lakukan sebagai solusi di sisi penulis naskah? Dalam kasus khusus saya, saya mencoba var $ = window.wrappedJSObject.$; dan var $= unsafeWindow.$; di bagian atas skrip, tetapi itu memberi saya kesalahan lain saat mencoba menggunakan $(document).ready(...) : Error: Permission denied to access property Symbol.toStringTag .

Kesalahan: Izin ditolak untuk mengakses properti Symbol.toStringTag

Saya tidak berpikir itu masalah window.wrappedJSObject.$ melainkan beberapa objek lain yang Anda buat di skrip pengguna, baik sebagai objek literal atau dengan konstruktor new , belum diimpor dengan benar ke cakupan tempat Anda mencoba mengaksesnya (mungkin cakupan jendela halaman).

Tautan di atas memberikan detail tentang cloneInto yang Anda perlukan.

Tidak, saya cukup yakin masalahnya ada pada window.wrappedJSObject.$ . Berikut ini gagal dengan kesalahan yang sama:

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

var $ = window.wrappedJSObject.$;

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

Namun, ini gagal secara diam-diam:

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

var $ = window.wrappedJSObject.$;

$.ready(function() {});

Saya sudah mencoba menggunakan cloneInto , tetapi tidak membantu. Apakah menurut Anda Anda dapat memberikan contoh singkat skrip pengguna yang menggunakan instance halaman $ ?

Ah, dalam hal ini Anda tidak memiliki izin untuk mengakses fungsi tersebut. Anda kemudian perlu menggunakan 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);

Saya sudah mencoba pendekatan itu sekarang (dalam konfigurasi yang berbeda), dan saya terus mendapatkan kesalahan izin apa pun yang saya lakukan. Ini benar-benar tidak sebanding dengan kerumitannya saat ini.

Kedengarannya kasar, tapi saya pikir saya hanya perlu merekomendasikan orang menggunakan Tampermonkey sampai ini selesai. Skrip konten, dalam inkarnasinya saat ini, benar-benar tidak cocok dengan kasus penggunaan skrip pengguna sama sekali.

Setuju dengan @obskyr , rekomendasikan saja orang-orang saya untuk menggunakan tampermonkey

+1, dipindahkan ke Tampermonkey (https://addons.mozilla.org/en-US/firefox/addon/tampermonkey/), sepertinya semua skrip saya berfungsi di sana.

+1, dipindahkan ke Tampermonkey (https://addons.mozilla.org/en-US/firefox/addon/tampermonkey/), sepertinya semua skrip saya berfungsi di sana.

Ini mungkin berfungsi dalam jangka pendek, dan berfungsi dengan baik untuk membuat skrip tetap berjalan, tetapi dalam jangka panjang, itu bisa menjadi keputusan yang salah untuk mengandalkan substitusi lengkap. Kesuksesan jangka pendek mungkin terlihat sebentar... ;-)

Saya menggunakan TM sebagai pengganti, tetapi ada beberapa masalah, saya tidak dapat menyangkalnya. Selain itu, mungkin ada beberapa masalah keamanan dengan FF Quantum, jadi ini berfungsi, tetapi orang tidak boleh hanya mengandalkan satu solusi ...

Yah, saya harus mendukung TM dalam skrip saya karena tidak semua orang menggunakan Firefox. Jadi sebelumnya saya mendukung GM dan TM, sekarang hanya TM. Tidak melihat ada masalah sejauh ini.

Apakah halaman ini membantu?
0 / 5 - 0 peringkat