Hatena::Groupos0x

FFFF RSSフィード

0xFFのメモです。

2008 March 18th Tuesday

Greasemonkeyの小話

| 15:26 | Greasemonkeyの小話 - FFFF を含むブックマーク はてなブックマーク - Greasemonkeyの小話 - FFFF

Big Sky :: Greasemonkeyで実行されるスクリプトはイケてるのか?より、

// ==UserScript==
// @name           broken source
// @namespace      xxxxxx
// @description    broken source
// @include        http://*
// ==/UserScript==

})();
(function () {

これがエラーにならないって話。

http://svn.devjavu.com/greasemonkey/trunk/src/components/greasemonkey.js

で、

      var scriptSrc = "(function(){\n" +
                         requires.join("\n") +
                         "\n" +
                         contents +
                         "\n})()";
      this.evalInSandbox(scriptSrc,
                         url,
                         sandbox,
                         script);

こんな風にしてるから、確かに1個上のはエラーにならない。(このevalInSandboxは独自メソッドで、実際にevalInSandboxしてるのはそのメソッドの中で、Components.utils.evalInSandboxを呼んでいる)

じゃあ、この無理やり関数を切った間で変数を作ったらそいつの扱いはどうなるんだろうと思い、少し調べてみた。

// ==UserScript==
// @name           broken source
// @namespace      xxxxxx
// @description    broken source
// @include        http://*
// ==/UserScript==

})();

var hoge = {};

(function () {

こんな風に関数を切ったところで変数を宣言してみる。これは以下のパターンが考えられる。

  1. thisのプロパティに追加 (this.hoge)
  2. windowのプロパティに追加(普通のHTMLページでの挙動) (window.hoge)
  3. unsafeWindowのプロパティに追加(これはどう考えてもないけど) (unsafeWindow.hoge)
  4. どのプロパティにも追加されない

結果、thisのプロパティだけに追加されて、windowのプロパティにはならなかった。そもそも、evalInSandboxで実行されるとき、thisとwindowは違うものになっているので当然な挙動。

で、その後に実行されるScriptでその変数が参照可能か調べてみた。

// ==UserScript==
// @name           broken source2
// @namespace      xxxxxx
// @description    broken source
// @include        http://*
// ==/UserScript==

})();

console.log(typeof(hoge), this.hoge, window.hoge, unsafeWindow.hoge);

(function () {

結果は全てundefined

そんな気はしてたけど、Greasemonkeyグローバル変数を汚染しないのは無名関数で囲ってあるからではなく、evalInSandboxで安全に実行されているから。気持ちの悪い"(function(){" "})()"はおそらくそれが必要だったころの名残かなにかで、現在は不要なんじゃないかと思われる。いきなりreturn;できるってメリット?はあるな。というか、そう書かれている(AutoPagerizeとかの)Scriptがエラーにならないように互換性のため残ってるのかもしれない。