Greasemonkey 4のアップデートにより、jQueryを使用する多くのユーザースクリプトが壊れているようです。 以前のバージョンでは、次のコードは<script>
タグでjQueryを使用するページで機能していました。
// ==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.")
});
ただし、これは機能しなくなりました。代わりに、従来の$ is not defined
取得するだけです。 これは、 <script>
タグが読み込まれる前に、Greasemonkeyがユーザースクリプトを実行している可能性があることを示しています。 ただし、 document.readyState
がinteractive
場合でもスクリプトが実行されるので、これは奇妙なことです。
ただし、確かに、 window.addEventListener('load', ...)
後にjQueryにアクセスしてみました。 見よ、以下は別のエラーを示しています。
// ==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!")
});
実行もエラーもスローしません。代わりに、 $
にアクセスしようとすると
jQueryを使用するすべてのページで試してみると、同じ結果が得られるはずです。 @require
を使用しても、この問題の解決策にはなりません。一部のアプリケーションでは、ページと同じjQueryのインスタンスにアクセスする必要があります。 これは、jQuery以外のスクリプトにも影響を与える可能性があります。
実際にはGreasemonkeyの問題ではなく、Firefoxコンテンツスクリプトの問題です。
https://developer.mozilla.org/en-US/Add-ons/WebExtensions/Content_scripts#Accessing_page_script_objects_from_content_scripts
独自のwindow.wrappedJSObject
割り当てるか、Greasemonkeyがすでにラップされたオブジェクトを割り当てているunsafeWindow
を使用します。
@Sxderp 「Greasemonkeyの問題ではない」ことについてはわかりません。TampermonkeyとViolentmonkeyの両方が、このケースを問題なく処理します。 それだけでなく、これはどのブログ投稿にも言及されていない重大な変更です。
既存のユーザースクリプトで期待どおりに機能し、他の一般的なユーザースクリプトマネージャーと相互互換性を持たせるために、これを修正する必要がありますか?
また...これは本当に問題を説明していますか? ルックアップが失敗しただけでなく、スクリプトがフリーズするのはなぜですか?
凍結についてはよくわかりません。 あなたのコードをコピーしました、そしてそれは私のためにフリーズしません。
編集:申し訳ありませんが、「フリーズ」コメントを誤解しました。 Greasemonkeyがもう機能しないという意味だと思いました。 Javascriptが宣言エラーの前に使用にヒットしたため、その行で「フリーズ」(実行を停止)します。 それが「致命的」と見なされることはかなり確実です。 のように、コードの実行を継続しません。
Violentmonkeyコードをざっと見てみると、 <script>
要素を作成してスクリプトを挿入しているように見えtabs.executeScripts()
APIメソッドを使用するのではなく。
もちろん、それを使用することにはそれ自身の欠点もあります。
それで... Firefoxがその行にぶつかると、それはただ静かに実行を停止しますか? エラーメッセージなし? なんて信じられないほど奇妙なことなのでしょう。
いずれにせよ、既存のユーザースクリプトとの互換性を維持することは目標ではありませんか? 結局のところ、これはニッチな機能ではありません。ページ自体のJavaScriptとのインターフェースは非常に一般的なことです。
いずれにせよ、既存のユーザースクリプトとの互換性を維持することは目標ではありませんか?
もちろん。 私たちは完璧ではありません。これは、ボランティアによって作成された無料のオープンソースプロジェクトです。
この時点で、これを改善する方法についての計画がありますが、Mozillaが安全に実行できるようにする機能を実装するのを待っています。 #2549
@arantius少し対立的に外れたかもしれないと思います...ごめんなさい。
ここでは、使いやすさよりもセキュリティを優先するというのは、考え抜かれた決断だと思います。 状況が解決するまで、スクリプト作成者側の回避策として何ができるでしょうか。 私の特定のケースでは、スクリプトの先頭でvar $ = window.wrappedJSObject.$;
とvar $= unsafeWindow.$;
両方を試しましたが、 $(document).ready(...)
を使おうとすると別のエラーが発生しました: Error: Permission denied to access property Symbol.toStringTag
。
エラー:プロパティSymbol.toStringTagへのアクセスが許可されていません
これはwindow.wrappedJSObject.$
問題ではないと思いますが、オブジェクトリテラルとして、またはnew
コンストラクターを使用して、ユーザースクリプトで作成した他のオブジェクトが適切にインポートされていません。アクセスしようとしているスコープ(おそらくページのウィンドウスコープ)。
上記のリンクは、必要なcloneInto
詳細を提供します。
いいえ、問題はwindow.wrappedJSObject.$
あると確信しています。 以下は、まったく同じエラーで失敗します。
// ==UserScript==
// <strong i="7">@name</strong> Variable access test
// <strong i="8">@namespace</strong> example.com
// ==/UserScript==
var $ = window.wrappedJSObject.$;
$(document).ready(function() {});
ただし、これは黙って失敗します。
// ==UserScript==
// <strong i="12">@name</strong> Variable access test
// <strong i="13">@namespace</strong> example.com
// ==/UserScript==
var $ = window.wrappedJSObject.$;
$.ready(function() {});
cloneInto
を使用してみましたが、役に立ちません。 $
のページのインスタンスを使用する短い例のユーザースクリプトを提供できると思いますか?
ああ、その場合、あなたはその機能にアクセスする許可を持っていません。 次に、 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);
私は今(さまざまな構成で)そのアプローチを試しましたが、何をしても許可エラーが発生し続けます。 この時点で面倒なことは本当に価値がありません。
厳しいように聞こえますが、これが邪魔にならないまで、Tampermonkeyの使用を推奨する必要があると思います。 コンテンツスクリプトは、現在の形では、実際にはユーザースクリプトのユースケースにまったく適合していません。
@obskyrに同意し、
+ 1、Tampermonkey(https://addons.mozilla.org/en-US/firefox/addon/tampermonkey/)に移動しましたが、私のスクリプトはすべてそこで機能しているようです。
+ 1、Tampermonkey(https://addons.mozilla.org/en-US/firefox/addon/tampermonkey/)に移動しましたが、私のスクリプトはすべてそこで機能しているようです。
これは短期的には機能する可能性があり、スクリプトを実行し続けることは問題なく機能しますが、長期的には、完全な置換に依存することは誤った決定である可能性があります。 短期的な成功は近視眼的かもしれません... ;-)
代わりにTMを使用していますが、いくつか問題があり、否定できません。 さらに、FF Quantumにはセキュリティ上の問題がある可能性があるため、機能しますが、単一のソリューションのみに依存するべきではありません...
とにかく、誰もがFirefoxを使用しているわけではないので、スクリプトでTMをサポートする必要があります。 つまり、GMとTMをサポートする前は、今ではTMだけです。 これまでのところ問題はありませんでした。
最も参考になるコメント
私は今(さまざまな構成で)そのアプローチを試しましたが、何をしても許可エラーが発生し続けます。 この時点で面倒なことは本当に価値がありません。
厳しいように聞こえますが、これが邪魔にならないまで、Tampermonkeyの使用を推奨する必要があると思います。 コンテンツスクリプトは、現在の形では、実際にはユーザースクリプトのユースケースにまったく適合していません。