読者です 読者をやめる 読者になる 読者になる

いつのまにか @require なんてものが。

require しても展開されるのは sandbox 側だったという当たり前の悲劇。

そんなこんなで Opera の User JavaScript はちょこちょこ書いてるんですが、Greasemonkey は入れてすらいなかったとふと気づき、入れたりブログ読んでたりしたら今は @require なんていうメタ構文が使えたりするらしい。おお。Prototype やら jQuery やらを、いちいち XHR で取りに行って eval したりしなくて良いって訳ですね?!

と思って、

// ==UserScript==
// @name          Unko Script
// @include        http://d.hatena.ne.jp/oogatta/*
// @require        http://ajax.googleapis.com/ajax/libs/jquery/1.3.0/jquery.min.js
// ==/UserScript==

とかってやったら、なんと、この jQueryGreasemonkey の sandbox 内(XPCNativeWrapperされちゃってる中)に展開されちゃいやんの。ってすごく当たり前だけど。
なので sandbox の外、本当のコンテンツの方のwindowjQuery なりがもともと展開されてないようだと、$ やらなんやらなんかうまく動かんです。あー、頭こんがらかってきた。XPCNativeWrapper の MDC のドキュメントもまだちゃんと読んでないし…。

というわけで、"should be avoided" なunsafeWindowを使って今日は逃げてみたりした…。

// ==UserScript==
// @name          Unko Script
// @include        http://d.hatena.ne.jp/oogatta/*
// @require        http://ajax.googleapis.com/ajax/libs/jquery/1.3.0/jquery.min.js
// ==/UserScript==
(function(){
    var _$;
    var _debug = function(obj){ unsafeWindow.console.debug(obj); };;
    Function.prototype.run = function() { this(); };

    // set up jQuery on the unsafe side.
    (function init() {
        unsafeWindow._jQuery = jQuery;

        var script = document.createElement('script');
        script.src  = 'http://ajax.googleapis.com/ajax/libs/jquery/1.3.0/jquery.min.js';
        script.type = 'text/javascript';
        unsafeWindow._jQuery('head')[0].appendChild(script);
    }).run();

    // wait for the "unsafe jQuery" getting loaded
    (function wait() {
        if( typeof unsafeWindow.jQuery === 'undefined' ) {
            window.setTimeout(wait,100);
        }
        else {
            init();
            honyarara();
        }
        return;
    }).run();

    // init
    var init = function init() {
        delete unsafeWindow._jQuery;
        _$ = unsafeWindow.jQuery;
    };

    // honyarara
    var honyarara = function honyarara() {
        // honya honya
    };

})();

あーあ…。我ながら何だこれは…。しかも僕ぁ、jQuery 苦手なんであります…。Prototype 使わせてくださいであります…。でも Prototype.js を @require すると、こちらのブログの方も仰ってる通り、意味不明なエラーが出るんであります…。おおい、おいおい…。(追記:HTMLElement.prototype が undefined なためでした。unsafeWindow.HTMLElement.prototype も undefined でした。

sandbox 側のライブラリがうまく unsafeWindow 側の DOM 要素を操作できないのは、window って直書きしてあったりするのはもちろんだけど、プロパティの read は出来ても write は出来なかったりする XPCNativeWrapper のおかげらしい。明日のタスクとします。