Home > Latest topics

Latest topics 近況報告

たまに18歳未満の人や心臓の弱い人にはお勧めできない情報が含まれることもあるかもしれない、甘くなくて酸っぱくてしょっぱいチラシの裏。RSSによる簡単な更新情報を利用したりすると、ハッピーになるかも知れませんしそうでないかも知れません。

萌えるふぉくす子さんだば子本制作プロジェクトの動向はもえじら組ブログで。

宣伝1。日経LinuxにてLinuxの基礎?を紹介する漫画「シス管系女子」を連載させていただいています。 以下の特設サイトにて、単行本まんがでわかるLinux シス管系女子の試し読みが可能! シス管系女子って何!? - 「シス管系女子」特設サイト

宣伝2。Firefox Hacks Rebooted発売中。本書の1/3を使って、再起動不要なアドオンの作り方のテクニックや非同期処理の効率のいい書き方などを解説しています。既刊のFirefox 3 Hacks拡張機能開発チュートリアルと併せてどうぞ。

Firefox Hacks Rebooted ―Mozillaテクノロジ徹底活用テクニック
浅井 智也 池田 譲治 小山田 昌史 五味渕 大賀 下田 洋志 寺田 真 松澤 太郎
オライリージャパン

Page 33/239: « 29 30 31 32 33 34 35 36 37 »

クリックされたタブを取得する方法 - Dec 25, 2009

ツリー型タブClose tab by double clickの競合について報告をもらった。

向こうのコードを見てみたら、タブバーの上でダブルクリックされた時にそのイベントがタブの中で発生したものかどうかを検出するのにevent.originalTargetとそのparentNodeだけを見ていて、ツリー型タブによって追加されたバインディングがあると判別に失敗するようになっていた。これはツリー型タブだけの問題じゃなく、バインディングを加えるあらゆるアドオンと衝突の可能性があるし、テーマによっても衝突する。バインディングに変更を加えなくても、タブの中に何か要素を追加するアドオンは全部衝突する。

いいかげん、こういう時にはDOM3 XPathを使うのが常識になってて欲しいです。こんな所で他のアドオンと衝突する可能性を残す必要はない。

clicked : function(event) {
  if (gBrowser.mTabs.length <= 1) return;
  var tab = document.evaluate(
              'ancestor-or-self::*[local-name()="tab"][1]',
              event.originalTarget,
              null,
              XPathResult.FIRST_ORDERED_NODE_TYPE,
              null
            ).singleNodeValue;
  if (tab) gBrowser.removeTab(tab);
}

こういう風に書けば、クリックされた要素の祖先まで辿って確実に判別できる。他にも絞り込みの条件を付けたければ付けられる。

「シンプルに作る事」と「手抜き」とは、必ずしも一致しませんよね。

画面の描画内容を一時的にロックしておいて、裏であれこれして最後にまとめて描画させる方法の再考 - Dec 24, 2009

画面の描画を一時停止する方法を先日書いたけど、案の定というかやっぱりというか、重大な弊害があることが分かった。また、その弊害にぶち当たらない安全なやり方も見つけることができた。

安全に画面の描画を一時停止・再開する方法は、以下の通り。

var baseWindow = window.top
                   .QueryInterface(Ci.nsIInterfaceRequestor)
                   .getInterface(Ci.nsIWebNavigation)
                   .QueryInterface(Ci.nsIDocShell)
                   .QueryInterface(Ci.nsIBaseWindow);
baseWindow.setPosition(window.innerWidth, window.innerHeight); // これで画面の描画が止まる

gBrowser.addTab(); // これによって起こる変化は画面上に現れない
gBrowser.addTab(); // この変化も画面上に現れない
gBrowser.addTab(); // 同上

baseWindow.setPosition(0, 0); // ここでやっと描画が再開される

以下、前のエントリに書いたやり方にどういう弊害があるのか、および、このエントリで紹介するやり方の方がどのくらい安全なのかについて詳しく説明する。

続きを表示する ...

整形手術 - Dec 22, 2009

僕は、整形手術には(自分がするのも、他人がするのも)抵抗があるのに、歯列矯正には抵抗がない。もし仮に自分に子供ができたとしたら、多分問答無用で矯正させると思う。

はい、何を隠そう僕自身小学校までずっと矯正やってました。ほっといたら酷い受け口(下の前歯が上の前歯よりも前に出る、アゴの出た状態)だったのを、長い時間かけて矯正しました。つまり「生まれつきの、自然に成長した状態」とは明らかに異なる形の顔を、今の僕はしてるわけです。

それって整形手術と同じじゃん。と、唐突に思った。(僕がしたようなマウスピースによる歯列矯正は保険適用外ということなので、扱い的にも「美容整形」と同じ。)

だいたい、成長してからやる歯列矯正ともなるともう完璧に「整形手術」の域だし。骨が固まってるから切って削って貼ってで形を変えてやらないといけない。骨までいじるって、整形手術の中でも相当な部類ですよね。やってる事は整形手術と何も変わらない。やってる事が同じなのに、どうして整形手術はイヤで、歯列矯正ならOKなんだろう。

というところを突き詰めて考えると僕には整形手術と歯列矯正の違いが分からなくなってきて、同じ物なんだったらなんで自分が過去にやった事は肯定する(わざわざ「本来の姿」であるところの受け口の状態に戻そうとはしない)のに他人がこれからやろうとする事は否定する(「本来の姿」を受け入れてそのままで生きることを求める)のかって話になるので、健康その他に害を及ぼさない範囲であれば、整形手術をしたがる人の事を止めてもいい道理が僕には何ら無いよなあ、だったら止められないなあ、と思いました。

追記。歯列矯正は医学的健康的にうんたらかんたらという言い訳は当然僕も考えたけど、他人から見て別にそんなブサイクでもない人が自分の容貌が自分の理想からかけ離れてる事でストレスを感じているというケースでの整形は、心の健康・安定を手に入れるための治療とか予防とかの一種であると僕は真面目に思うんですよ。前にどっかで、整形前でも十分イケメンなのに、整形してなんかオカマっぽい顔になって、でも本人はそれですごく喜んでる、そんな例を見て、美容整形も突き詰めると「本人の健康のため」「QOLを高めるため」なんだなという事を改めて感じさせられた。だから歯列矯正との違いが分からなくなったと書いたんです。

ツリー型タブ0.8.2009122103 - Dec 21, 2009

ツリー型タブはバグをつぶし始めたらきりがなくなってきたので、適当なところで打ち切ってリリースしました。バグ報告への返信で「I'll update as soon.」とか書いちゃったからというのもある。

画面の描画内容をロックするアレについては、結局ライブラリ化しましたwindow['piro.sakura.ne.jp'].stopRendering.stop()で描画停止、window['piro.sakura.ne.jp'].stopRendering.start()で再開します。複数の機能で停止/再開をネストしても大丈夫なように、呼び出し回数をカウントするようにしてあります。start()し忘れると変なことになるので注意して下さい。

他にもいくつかAPIを追加したので、自作アドオンと連携して動作させてみたい人は参考にして下さい。

画面の描画内容を一時的にロックしておいて、裏であれこれして最後にまとめて描画させる方法 - Dec 18, 2009

ツリー型タブとJetpackが同時にインストールされているとコンテンツ表示領域に何も表示されなくなってしまう、という問題の原因がやっと分かった。そこからさらに調査をして、表題のような「画面の再描画を任意に停止・再開させる」方法が見つかった。

先にやり方だけ書いとくと、こうするとできる。

var rootContentViewer = window.top
                          .QueryInterface(Ci.nsIInterfaceRequestor)
                          .getInterface(Ci.nsIWebNavigation)
                          .QueryInterface(Ci.nsIDocShell)
                          .contentViewer;
rootContentViewer.hide(); // これで画面の描画が止まる

gBrowser.addTab(); // これによって起こる変化は画面上に現れない
gBrowser.addTab(); // この変化も画面上に現れない
gBrowser.addTab(); // 同上

rootContentViewer.show(); // ここでやっと描画が再開される

24日追記。この方法には重大な弊害があることが分かりました。使用を検討している人はより安全な方法を使うようにして下さい。

以下は、これに辿り着いた経緯のお話。

続きを表示する ...

Google Chrome Extensions - Dec 16, 2009

GoogleChromeの拡張を作る上でFirefoxアドオン作者が知っておくべきやればできること « kuFirefoxアドオンの自由度は奇跡的です。millennium | Google Chrome Extensionsを読んでその奇跡を噛み締めましょう。と紹介されていたエントリを勝手に翻訳してみました。原文の著者は、Firefoxの初期開発チームの一員で、今はGoogleに転職してGoogle Chrome開発チームの一員となっているBen Goodger氏です。


Chromeチームは今日(※訳注:2009年12月8日)、Mac OS XとLinux、そして拡張機能に対応した最初のバージョンをリリースしました。これは、非常に多くの人達の1年間にわたる作業の完成を意味しており、私は開発チームがこの目標を達成できたことを誇らしく思っています。そこで、拡張機能について少し語る機会を設けることにしました。

Chrome拡張機能APIはユーザと開発者に対して、Chromeの核となる原則である「速度」「安定性」「安全性」そして「シンプルさ」を保ちながらブラウザをカスタマイズする能力を提供します。

Google Chromeの拡張機能には以下のようなことができます。

  • JavaScript、HTML、CSSなどの一般的なWeb技術によって簡単に開発できます。
  • それぞれ別々のプロセスで実行されるため、ブラウザ全体の動作を遅くさせるような問題は起こりません。
  • 限定的なAPIを持っており、各拡張機能はブラウザのタブと同様のサンドボックス内で実行されます。
  • Chrome自身と同様の自動アップデートの仕組みを使うため、開発者は彼らのソフトウェアの新しいバージョンを容易に公開することができ、ユーザは何もしなくても、最新・最高・最も安全なバージョンにアップデートし続けることができます。

Google Chrome拡張機能についての動画はここで見られます。

私はここしばらくの間、ブラウザの開発に関わり続けてきました。私の話を興味深く思う人もいるでしょうから、拡張機能の歴史について少しお話ししましょう……

かつてNetscapeがNetscape 6(ブラウザ、メールクライアント、ページ作成ツール、そしてIMクライアントのセット)を開発していた頃の要求仕様の1つとして、メールクライアント、IMクライアント、ページ作成ツールといった「選択式の」コンポーネントを含めずにブラウザだけをインストールできるようにする、というものがありました。それらのコンポーネントをインストールした場合は、メールクライアントやIMクライアント等を起動できるようにするために、ブラウザのUIに「追加の項目(メニュー項目、ツールバー上のボタンなど)」が表示されることになります。

NetscapeのフロントエンドはクロスプラットフォームなUI言語であるXULによって実装されていました。選択式のコンポーネントは、それらがインストールされている場合に「追加の項目」を加えられるよう、「オーバーレイ」と呼ばれるファイルを含んでいました。選択式のコンポーネントはそれ自身のオーバーレイや他のロジックを「XPI」ファイルの中にパッケージングされていて、インストールエンジンによってインストールされるようになっていました。

何年か後、Netscapeの後継者であるFirefoxの人気が高まると同時に、開発者達は、前述のようなコンポーネントのインストールのための仕組みを、ブラウザに対して他の機能を追加するためにも利用できるという事に気がつきました。この機能自体はNetscapeの自社製品以外が使うことを全く想定せずに作られていたので、ブラウザのUIの中でどんなAPIが公開される必要があるのかといったことに対しては十分な注意が払われていませんでした。本当に単なる内部的なAPIでしかなかったのです。そのため、人々がFirefox用の「拡張機能」の開発を始めたばかりの頃は、Firefoxに何か変更が行われるとその度に拡張機能のせいでブラウザが起動しなくなるというのが日常茶飯事でした。Firefoxの初期の頃には、ある拡張機能(※訳注:多分タブブラウザ拡張のことじゃないだろうか。というのは自意識過剰?)をインストールしていたユーザにとっては、Firefoxの新しいバージョンにアップグレードする度に「ブラウザにXBLのバインディングが適用されていません」というエラーにぶつかる、といったことも珍しくありませんでした。

Firefoxがバージョン1.0に達する前にこの問題を解決しなければならないのは明らかでしたので、私は拡張機能マネージャをFirefoxに加えることにしました。これは、インストールやアンインストールのためのやっかいなコードを書かなくても済むようにすると同時に、より重要な点として、バージョン管理のための仕組みを提供するものでした。安定したAPIが無い以上、システムは単純に、ブラウザのそのバージョンに対して互換性があると明記されていない拡張機能を無効化します。これは開発者達にとって、新しいバージョンのFirefoxがリリースされるごとに毎回、彼らの拡張機能の動作を保証しなければならないということを意味します。この仕組みは完璧でもないし、煩わしいものでしたが、しかしそれなりにうまくいったため、私達はひとそろいのAPIを凍結させなくてもよかったのです。APIの凍結を急かされていたら、まず間違いなくそれはおざなりな物になってしまっていたでしょう。

Firefoxの拡張機能は常に諸刃の剣です――それは計り知れない柔軟性を提供しますが、その引き替えに、ブラウザがアップデートされるごとに毎回動作確認を取らなければいけないというコストを開発者に対して強います。開発者の動作確認が遅れた場合、ブラウザの新バージョンがでてすぐにアップグレードしたユーザは、しばらくその拡張期能なしで過ごさなければならないか、あるいは、互換性の確認の過程を自己責任で無効化する必要があります。

私はこの歴史についての覚え書きには、面白いというだけでなくケーススタディとしても価値があると考えています。もし、Netscapeのコンポーネント式のインストールのおかげでこのブラウザのカスタマイズのための「裏口」が存在していなかったら、Firefoxに拡張機能の存在自体が全く無かったかもしれないのです。考えてみて下さい。その機能がユーザに愛されたために、Firefoxは成功したのです。これは驚異的な事です。この前例があって、ユーザが拡張機能を愛しているということが分かったので、私達Google Chromeチームは今、カスタマイズ性とChromeの核となる原則とを両立させる最良の物を作るべく、新しいAPIをゼロから作るという贅沢が許されているのです。

Firefoxでの体験は計り知れないほど有益な物でした。私は、Google Chromeの拡張機能の開発に個人的に寄与した数多くの技術者達のうちの1人ではありませんが、しかし、機能をどのように実現するかを検討する事については十分な戦歴があります。私はChrome拡張機能のチームがこのアプローチを取ることを決定した事をとても嬉しく思います。最初のマイルストーンへと私達を導いてくれた彼らに賞賛を!

カード配り問題 - Dec 16, 2009

10分プログラミング - hogehogeを見て、10分でコーディング|プログラミングに自信があるやつこい!!に挑戦してみました。

結果。コーディング(と検証)だけで6分くらいかかりました。しかもエレガントでもなんでもありません。

function Cards() {
}
Cards.prototype = {
  deal : function(aPlayers, aDeck)
  {
    var result = [];
    for (var i = 0; i < aPlayers; i++)
      result.push('');
    aDeck
      .split('')
      .slice(0, aDeck.length - (aDeck.length % aPlayers))
      .forEach(function(aCard, aIndex) {
        result[aIndex % aPlayers] += aCard;
      });
    return result;
  }
};

var c = new Cards();
alert(c.deal(4, "123123123"));

クラス名がどうとか書いてあったから馬鹿正直にそれに従ってしまったし。

追記。いかん、人数よりカード枚数が少ないときの考慮が足りてなかった。修正した。

1981忘年会に混ざってきたよ - Dec 13, 2009

1981年生忘年会#3に混ざってきました。1983の方によく参加させてもらってたけど、1981の方には行ったことがなかったので、せっかくだから申し込んでみた。

集合場所に着いたら案外人が少なくて「おや?」と思ってたら、既に1次隊が出発済みだったらしい。そこで挨拶した方がクックパッドの方で、先日のFirefox Developers Conferencesにも来られててありがとうございますみたいな話をした(1次会でも同じテーブルに座った)。

  • 1次会、坐・和民で100人オーバーだった。
  • クックパッドにも弊社代表と同姓同名な「すとうこうへい」さんがいると聞いた。なんという偶然……!
  • 店から全員に一人あたり1500円分のお食事券が配られました。ただし500円分を3枚でランチタイム使用不可、1回の利用は1人1枚までなので、使う機会がなさそうで困っています。
  • 僕の座ったテーブルは初参加の人ばかりでしかも1981生まれの人がほとんどいなかった。空気読んでなさ過ぎですね!!!
  • iPhoneの事とかAndroidの事とか上級SEはエンジニアと言えるのかどうかとか色々話した気がするけどよく覚えてません。
  • 2次会の店をamachangが探しに行くというので僕も同行した。人数が多くなりそうだったので見つからないだろうなあと思ってたけど、同じビルの地下の店であっさり決まってよかった。
  • 戻ってきた頃にはもう鍋がおじやになっていた……飲み物のラストオーダーも過ぎてた。
  • iGirlの人とは1回絡んでおかねばなあと思っていたのでここぞとばかりに挨拶させてもらった。asami81さんもこの辺のことは覚えていらっしゃった。
  • 最近よく顔を合わせるdent-de-lionさんとここでも再会した。何このヒット率。

2次会の店は、最初に用意してもらったスペースに全員おさまりきらなかったので別の部屋に主に幹事の人達が溢れる形になっていた。何故か僕もそこに混ざっていた。

  • 70人くらい残ったそうだ。
  • kiyoheroさんに、はてなハイク2に招待してもらった。つっつかれるとぶるぶる震える仕組みはcho45さんが作ってるとな。つっつかれるとぶるぶる震える仕組みはcho45さんじゃない別の人が作ったそうです。
  • あとはてなブックマークブックマーク(ノベルティグッズのしおり)を沢山もらった。
  • amachangの上着のボタンが取れたのをasami81さんが縫うのに僕のソーイングセットをお貸ししました。「なんでこんなん持ってるねん」と全員からツッコまれました。独り暮らしなら持ってて変じゃないですよね……?!
  • ドワンゴの中の人曰く、糸柳さんはあれで案外常識人で「これ以上やったらヤバイ」という線をちゃんと分かってやってるとのことなんだけど、Web上での彼を見てるとなかなかそうは思えないのが不思議です。
  • それ以外に何を話していたのか全然覚えていません。

3次会(徹夜)はまた最初の店に戻る……はずだったんだけど、2次会の店の店長?がよきに計らってくださいまして、2次会の店に併設の別の店を貸し切り状態で使うことになりました。

  • 残ったのは20~30人くらい?
  • amachangは最近Jython(Python on Java)を書いてるそうで。
    • Java書きづれー!!という魂の叫び。
    • yukobaさん「素のJava言語は今となってはアセンブラみたいなもんで、高速化のためにしか触らないよね」
    • Java書くんだったらeclipseかその元になったIDEは必須でしょという。4~5年ずっとJavaやるのなら1ヶ月かけてでもIDEに慣れておいた方が絶対に生産性が高い。→amachang「1ヶ月だけJavaをやらなきゃいけないんだけど……」→yukoba「それは……諦めるしかないね」
  • 西尾さんは今やCGアーティスト→amachang「4次元ってどうなってるの!!」というところから話が膨らんで、空間の歪みがどうとか相対性理論がどうとか原爆の仕組みがどうとか量子論がどうとか対消滅がどうとか量子コンピュータがどうとかそういう話になった。他のテーブルはオナニーがどうとかそいう話で盛り上がっていたのにここだけ何だか空気が違うよ……!!
    • yukobaさんは一時期量子コンピュータに凝っておられたそうで、量子コンピュータとは一体どういう物なのか? 何がすごいのか? 何ができないのか? といったことを色々教えてもらった。
    • 途中から話に加わって下さった方が物理を大学で専門にやってたそうで、その人も色々教えてくれた。
    • 古典的なコンピュータの上で量子コンピュータをエミュレーションする仕組みは既にあるそうで、それを使って量子コンピュータ用のプログラムをかけるんだとか。
      • evalに相当する関数の名前がmeasure(観測)というそうだ。何故なら量子コンピュータでは観測=演算だから。
    • 今の量子コンピュータは足し算引き算はできるけど、内積を求めるアルゴリズムが確立されていないそうだ。ものすごい大きな桁の足し算引き算因数分解等が1クロックでできることが量子コンピュータの最大の利点なのに、かけ算ができないんじゃ意味ないよねー。とのこと。
    • 今のCPUの進歩はもう限界が見えてる。1回目の限界はクロック数の頭打ちで、昔は5GHzとか10GHzとかいくと思われてたのに結局物理的現象の限界に阻まれて4GHz前後で止まってしまった。次の限界は微細加工の物理的限界で、トンネル効果で電子が吹っ飛んでしまうようなサイズにまで至ってしまうともうそこでおしまいなのだという。つまりあと10年くらいでCPUの進歩は完全に止まってしまうという。(マルチコアとかは、1つ1つのCPUの性能が上がらなくなったから2個4個まとめて突っ込んじまえという力業でしかない。技術が根本的に進歩したわけではない。)
    • それを解決するのが量子コンピュータだ、と期待されてたんだけどそっちも何だか最初の数年でだいたいの研究が出尽くして今ではほとんど進歩がみられないとか……
    • 代わって脚光を浴びてるのが、電子の流れではなく光を媒体として使う光コンピュータという分野なのだそうで。
  • 量子論の話に入る前は、3Dプリンタの話になってた。
    • (マンデルブロー集合とかそういう系のCGの)CGアーティストにとって、3Dプリンタがあるともっと面白いことができるんじゃないか? とか。
      • 実際、鎖のような構造を継ぎ目無しに作れるのは今の所3Dプリンタくらいのもんだ、とか。
    • 3Dプリンタには、石膏を積層して固めるタイプと、光で固まる樹脂を積層するタイプがある(あとこの場では出さなかったけど、樹脂ブロックからの削り出しタイプもある)。
    • amachang「ゲームのキャラをそのまま出力したら面白いんじゃね?」→僕「それもう既にあるよ」
      • というか模型業界では今や、CADからラピッドプロト出力というのが当たり前ですよね。
      • コトブキヤのバーチャロンシリーズのプラモなんて、ゲームのハイエンドCGをそのまま立体出力して、プラモにするためにそこからさらに加工するというステップで作られてる。
      • フィギュアのねんどろいどにもCAD設計の物がある
  • amachangとyukobaさんが抜けた後、物理をやってた人と「こういう話もとても面白かったけど、もっとどーでもいい話もしたかった(笑)」という感じの事を話して、関西地元の深夜番組の話で盛り上がりました。
    • 「おとなのえほん」は当時の男子中学生にはたまらなかった!!とか。
    • 「アニメ大好き」はよいアニオタ養成番組であった、とか。

そんな感じでダラダラしてるうちに朝が来て、忘年会は終了しました。

  • 会計の時、全然食べてないテーブルと食べまくってたテーブルとがあったために、amachangを大いに悩ませてしまった。全員で均等割にしたら怒る人出そう……と。
    • 実際僕は均等割にどちらかというと反対だったので、余計に悩ませてしまった。
  • 2次会で帰られた方の中に、デスマーチの作者の人がいたんだって……後から知った。

幹事じゃなかったのに2次会以降は幹事を務めて下さって、最後まで頭を悩ませてしまって、ありがとうございます&すみませんでした。amachang 改めて、彼はとてもいい人だなと思った。人に好かれる人、人が集まってくる人というのはこういう人を言うのだろう、と素直に思える。好奇心旺盛でまっすぐで、嫌味な所がなくて。自分が女だったら間違いなく惚れるね!!! そのくらいに彼のことがますます好きになった、そんな忘年会でした。

仏陀再誕 The REBIRTH of BUDDHA - Nov 30, 2009

ブッダ超やばい。マジヤバイ。

噂の仏陀再誕、そのうち見に行ってみたいなあ(主に怖いもの見たさで)と思っててhknさんに誘われて見に行くことになったんだけど、気がついたら東京での上映は既に終わってて……仕方がないので埼玉は桶川まで行ってきましたよ。桶川マインシアターなら12月4日までやってるそうです。

  • 糸柳さんが見に行った時の話を以前読んで、いつもの脚色が入った記述なのかとばかり思ってたんだけど、映画の内容の記述はわりとその通りだったようだ。どういう話なんだろうなあと思いながら見てたんだけど、唐突にインデペンデンス・デイになるという超展開で噴きそうになった。
    • 10分後に津波が来ますとか。もうちょっと猶予を持たせようよ。
    • 空飛ぶし。
    • 象に乗るし。
    • 何か変なうにょうにょする乗り物に乗ってドーム球場に出現するし。
    • 手からエネルギー波のようなものが出まくりです。
    • 光の翼に光の剣ときたもんだ。
  • 再誕した仏陀、シルエットで登場してきて最後まで姿を明かさないのかと思ってたら、すぐにあっさり素顔を見せて拍子抜け。
  • 真のラスボスの登場はちょっと唐突だった気が。
  • エンディングの歌、普通に普通の歌なのかと思って聞き流してたんだけど、スタッフロールに出てた曲名が「悟りにチャレンジ」で「ん?」と思って、さらに聞いてるとだんだん歌詞が耳に入ってきて「んん?」となって、最後の最後でやられました。この曲調で「悟りにチャレンジ」は反則だと思います……
  • 途中ブッダが出てきたけど、最近聖☆お兄さん読んでたからどうしても立川でバカンス中のイメージが浮かんでしまって、何だかなあと思いました。
  • ギャグは若干すべってた気がします。これは無くてもよかったんじゃね?
  • 映像のクオリティ自体は普通に高かった(最後の方のいかにもCGな人達はどうかと思ったけど)。ボールペンをノックするとか演技細かいし。声優陣も豪華。正しく劇場映画ですね。
  • 空野太陽イケメンすぐる。そしてええ声(CV:子安武人)。
  • 肩からセーターをかけてるマスコミ関係者は今では絶滅しているらしいと聞きましたが、実際どうなんでしょうか。
  • 原義的には「仏陀」は「目覚めた人」の意味だし、シャカ族のゴータマ・シッダールタの生まれ変わりを自称しなくても、別にふつーに今の時代で悟りを開いた人ってだけでいいんじゃないの? と思った。他人の言葉じゃなく自分の言葉で、他人の名の下にではなく自分の名の下に、語った方が格好いいんじゃないですかね。
  • 千葉繁が声を当ててたキャラがいつの間にか途中退場してたので、この人物をキーにして続編を作れそうですね。期待age。

という感じで結構ツッコミ気分で見てたんだけど、ストーリーもののエンターテインメント映画として大筋はそんなに悪くないと思った。キャラ同士の関係や対立構造は分かりやすいし。緩急あるし(説教シーンが長いのはご愛敬)。なんだかんだでバトルによる人死には出ないし。最後に悪人ブッ殺してハイおしまいという話でもなかったし。説教の内容も、欲望のまま貪ってはいけないとか、言ってること自体はだいたい変じゃないし。

また、主人公の一人の青年が「(宗教やってるということを明かすのが)怖かった」と語る場面や、「(敵の企みが)失敗しても、誰も宗教を信じなくなる(ので、空野太陽の言うことも誰も信じなくなる)」といったくだりに、現実の社会と宗教の関わり方が描写されている気がして、単純にネタとして笑い飛ばせはしないなあと思った。

しかし、言ってもしょうがない話だけど、「私の言うことに従いなさい」的な言い方には反発を感じた。

理想とかけ離れている自分に失望して、「誰か答えを教えてくれよ」「誰か導いてくれよ」と思った事もあったけれども。結局、人に言われるままに丸呑みした答えは自分の中で身に付いていなくて、だから他の人に別の「答え」を突きつけられたら簡単に揺らいでしまって、そんな感じでいつまでもぐらぐらし続けてしまう。人それぞれ違う前提があって、与えられた「答え」が100%当てはまらない所があって、でも新しく与えられた「答え」の方が正しいと思いたいから、自分に当てはまらない部分を無視して無理に当てはめようとして、「答え」に当てはまらない自分の方がおかしいんじゃないかと思ったりして。その繰り返しだったんじゃないかって気がする。そうじゃなくて、自分の前提に基づいて考えて、自分にちゃんと当てはまるように自分で組み立てた答えじゃないと、素直には受け入れられないし自信も持てない。僕の場合は、そんな気がする。

「仏陀がその時代の価値観を決める(その権限を持っている)」的な話にも、強い抵抗を感じた。「正しい」と定められた範囲から漏れてしまった人は「間違っている」という烙印を押されなければならないの? 同性愛者として生まれた人が異性愛者にはなれない(「治療」できるものではない)ように、「正しい」と定められた範囲にどう足掻いても入れない人は救いの対象外?

だから、空野太陽や主人公達が「教えを広める」的な所に帰結するのが、短絡的だと思えて僕には残念だった。宗教の映画だからそうなるのが当然なんだけど(混沌とした世の中で多様な価値観の中で翻弄されて辛い思いをしている人や、自分の力ではどうにもならない苦境に置かれて苦しんでる人に、ひとつの分かりやすい答え・指針を示して安心を与えるのが、宗教の本質だと僕は思ってる)。

まあ何にせよ、桶川までわざわざ見に行って損はなかったと僕は思ってます。(←タダ券のくせに何という上から目線!)

追記。破壊屋_仏陀再誕に(ネタバレを含む)詳しい解説があった。病院の地縛霊のセリフとか、「なるほどあのシーンのあの描写にはそういう背景があったのかー」と、幸福の科学の教義に詳しくない僕には参考になった。

追記。幸福実現党の研究(12)映画「仏陀再誕」徹底分析[絵文録ことのは]2009/11/03に仏教の教えとの対比があった。僕は仏教にも詳しくなかったので、「ほうほう仏教ではそこはそういう風になっているのか」と参考になった。

拡張機能におけるeval()の5つの間違った使い方 - Nov 28, 2009

以下、Adblock Plus and (a little) more: Five wrong reasons to use eval() in an extensionのいいかげんな訳です。XUL/Migemoのバージョンアップ時のエディタによるレビューのコメントで「今回は公開を承認するけど、次からはeval()はなるべく減らすように。詳しくはこれを読んで。」と指摘されたので、自分が読むために訳してみました。誤訳があったら指摘して。一部のサンプルコードは見やすさのためにインデントを勝手に加えてます。

ちなみに、僕は5番目の点(こういう用途でeval()を使うなという話)については反対の立場です。拡張機能同士を協調して動作させたいなら、むしろeval()を使って関数を書き換えるやり方を使う方が望ましいとすら考えています。なので参考のために、似たような立場と思われるSimon氏・Dorando氏のコメントも訳しています。

2010年2月8日追記。このエントリで述べられている内容に対する反論を公開しました。できればそちらも併せてご覧下さい。


過剰に使われているJavaScriptの機能のひとつに、eval()関数があります。私はそれが非常に多くの拡張機能で利用されているのを見てきましたが、そのうちのごく一部だけが正しい使われ方をしています。ですので、eval()のすべての間違った使い方について説明したいと思います。

1. JSON形式のデータのパースのため

今日において、JSONはデータを保存するためのポピュラーな形式となっています。その最大の特長は、パースが非常に簡単であるということです。単に data = eval(json) という風に書けば、それだけで事足ります。

うまい話には裏があるんじゃないの? その通り。このjsonという変数は {foo: "bar" + alert(Components.classes)} のような内容が含まれるかもしれず、このようなJavaScriptのコードを実行してしまうと、あなたが意図していなかった結果になってしまうでしょう。このように、信頼できない情報源からやってきたデータをJSONとしてパースする用途にはeval()は全く不向きです。それがFirefoxの拡張機能であるなら、どんなWebサーバから送られてくるデータも信頼できません。もしそれがあなたのWebサーバであっても、ハックされて(※訳註:原文ではhacked)いるかもしれませんし、ユーザへの通信経路上で情報が改竄されているかもしれません(特に、暗号化されていない接続では)。あなたは、ユーザを危険な状況に晒したくはないでしょう。

それだけではありません。そのデータが拡張機能自身によって(例えば、ブラウザ終了時の状態を保存するためなどの目的で)書き出されたデータであっても、常に信頼できるとは限りません。その中にはひょっとしたら、Webから受け取ったデータが含まれるかもしれません。もしJSONを書き出す処理にバグがあって、JavaScriptの文字列として書き出すべき物が文字列になっていなければ、それをJSONとして解釈しようとした時、知らない間にJavaScriptのコードとして実行されてしまうでしょう。これが、JSON処理専用の機能を必ず使うようにした方が良い理由です。JSON処理専用の機能は、不正なデータを受け取った時にもJavaScriptのコードとして実行してしまわないので安全です。

2. プロパティ名が動的に変化する時に、そのオブジェクトのプロパティにアクセスするため

obj.fooNNnという変数の値である、というプロパティにアクセスしたいとき、どんなコードを書けばよいでしょうか? これは、あなたがアクセスしなければいけないプロパティの名前が事前には分からなくて、動的に決定されるものであるという場合のことです。拡張機能の中には、これを eval("obj.foo" + n) のようなやり方で解決しているものがあります。この時、その拡張機能はnの値の中に危険な内容が含まれていないかを検証する必要があるでしょう――でも、どうやって?

幸いにも、この質問の答えを考える必要はありません。もっといい方法があります。JavaScriptではすべてのオブジェクトが連想配列である(※訳註:原文ではassociative arrays)ことを思い出してください。言い換えると、obj.fooobj["foo"] は全く同じ意味で、すべてのプロパティは配列の要素としてアクセスできるのです。ですから、前述のような問題を解決するには単に obj["foo" + n] とだけ書けばよく、この操作は、何も他の余計なことをすることなく常にそのプロパティにアクセスするでしょう。

では、メソッド(関数)の場合は? JavaScriptではメソッドも、値が関数オブジェクトであるという違いがあるだけのただのプロパティです。その関数を this が正しい値を示すようにして呼び出すために、Function.call() というメソッドが利用できます:

var method = obj["foo" + n];
method.call(obj, param1, param2);

あるいは簡潔にこう書くこともできます:

obj["foo" + n](param1, param2);

同じアプローチが、グローバル変数やグローバルな関数に対しても使えます。「グローバルオブジェクト」のすべてのプロパティはwindowのプロパティとして参照できます。window.foowindow["foo"] は、グローバル変数fooの値を返すでしょう。(※訳註:JavaScriptコードモジュールなどwindowが使えない変数スコープでも、 (function() { return this; })() とすればその実行時の変数スコープのグローバルオブジェクトを取得できます。)

3. 関数に対して、その関数が処理を終えたあとに何をするべきかを示すため

私が時々見かけるひとつのパターンは、このような関数の呼び出し方です:

foo("window.close()");

その関数は他の場面で、異なるJavaScriptのコードをパラメータとして渡されていました。そして関数が処理を終えた後で、パラメータとして渡された内容を動作の指定として eval() で実行するようになっていました。

どう見ても、ここにはセキュリティ上の問題はありません(※訳註:もちろん、パラメータで渡す内容にWebから取ってきたデータが含まれる可能性がある時は問題外ですよ!)。では、このアプローチの一体どこが間違っているのでしょうか? 実際には、以下のような問題があります:

  • このコードはeval()が呼ばれるまでコンパイルされないでしょう。これは、それ以外の部分のコードについてはスクリプトが読み込まれた時にすぐにJavaScriptインタープリタが文法エラーを報告するのに対して、関数のパラメータとして渡されたコードの文法エラーは後になってからしか報告されないため、そのコードが実行されるような経路を辿る操作をあなたがテストしなかった場合に、問題が見過ごされてしまうだろうということを意味します。
  • もう1つの問題は、そのコードの中で起こったエラーに対して、JavaScriptインタープリタが正しいソースファイルと行番号を報告することができず、どこで問題が起こったのかを知ることができないという点です。このようなエラーのデバッグはとても面倒です。
  • 付け加えると、foo()に対して実行して欲しいコードをパラメータとして渡すというのは普通のやり方ではなく、見苦しい回避方法を色々と必要とします。(※訳註:ダブルクォーテーションをエスケープしないといけない、など。)

幸いにも、クロージャを使うことによってそれらの問題は解決できます(※訳註:この例はクロージャではなく関数リテラルとか関数オブジェクトとかその辺の話だと思うんですが……)。以下は、前述のコードを少し書き換えた例です:

foo(function(error)
{
  alert(error);
  window.close();
});

そしてfoo()という関数の内容は以下のようになるでしょう:

function foo(callback)
{
  ...
  callback("Full success");
}

4. HTMLやXULにインラインで記述されたイベントハンドラを実行するため

以下のようなボタンがあると仮定しましょう:

<button id="button" oncommand="doSomething();"/>

このイベントハンドラを実行するために eval(document.getElementById("button").getAttribute("oncommand")) としてはいけないのは何故でしょうか? その要素が実際にクリックされたなどの場合以外の所でイベントハンドラを実行するための方法として、拡張機能の中ではしばしばこのようなやり方が用いられます。しかしながら実は、commandイベントを生成する方法のほうがもっと簡単で、しかもイベントハンドラがどのように定義されていようとも正常に動作することが期待できます:

document.getElementById("button").doCommand();

doCommand()というメソッドは、すべてのXUL要素で利用可能です。他のイベントに対しては、document.createEvent()を使って本当のイベントオブジェクトを生成する方がよいでしょう――何故なら、イベントハンドラがそれを期待しているでしょうから。例えば:

var event = document.createEvent("MouseEvents");
event.initMouseEvent("click", true, true, window,
                     0, 0, 0, 0, 0,
                     false, false, false, false,
                     0, null);
document.getElementById("button").dispatchEvent(event);

では、あなたが「onfooaction」という風な独自の属性を定義していて、それがいかなる実際のイベントとも関連付けられていない場合には? このような場面でも、eval()を使うのは最良の選択とは言えません。何故なら、eval()を呼び出した関数の実行コンテキストにおいてコードが実行されてしまうからです。もしそのイベントハンドラがfooというグローバル変数を参照したとして、あなたがそのイベントハンドラを呼んでいる関数の中にfooという名前のローカルな変数があったら――そのイベントハンドラは意図しないままにそのローカル変数にアクセスしてしまうでしょう。そしてもちろん、その時イベントハンドラに対してパラメータを渡すこともできません。よりベターな解決策は、そのイベントハンドラのための関数を作る事でしょう:

var handler = new Function("param1", "param2",
                           document.getElementById("button")
                                   .getAttribute("onfooaction"));
handler("foo", "bar");

このシナリオでは、このイベントハンドラは「foo」をparam1という名前の引数として、「bar」をparam2として受け取るでしょう。(これは、よくあるインラインで記述されたイベントハンドラに対してeventというパラメータを渡す時にも使えます。)

5. ブラウザの関数を書き換えるため

以下のようなことをしているコードをよく見かけます:

gBrowser.foo = eval(gBrowser.foo
                            .toString()
                            .replace("foo", "bar"));

このようなやり方でブラウザの関数を書き換えている人は、公の場所でおしりペンペンされることをお勧めします。それは、ブラウザの関数を新しい関数で単に置き換えてしまうだけの拡張機能に比べてほんのちょっとだけマシであるに過ぎません。どちらの場合も、書き換えられようとしているコードが変化しないことを前提にしていますが――しかし、もしそれが起こったら? 最良のケースでは、その拡張機能は大きな損害を与えることなく単に動作しなくなるでしょう。しかしひょっとすると、ブラウザを壊してしまうかもしれません。あるいは、ブラウザのその関数がセキュリティ上の問題の修正のために書き換えられたとしたら、その拡張機能は同じセキュリティ上の問題をまた持ち込んでしまうかもしれません。

言い換えると――この使い方はしてはいけません。ほとんどの場合で、このアイデアはブラウザの関数の動作を変えるのではなく、その関数の前後に追加の処理を挿入するために使われています。幸いなことに、それをするためのもっと危険でないやり方として、ここでもクロージャを使えば元の関数を単純にあなたの関数で包み込むことができます:

var origFoo = gBrowser.foo;
gBrowser.foo = function(param1, param2)
{
  if (param1 == "top secret")
    doSomethingBeforeFoo();
  var result = origFoo.apply(this, arguments);
  if (result == null)
    doSomethingAfterFoo();
  return result;
}

元の関数にすべてのパラメータを渡すためにFunction.apply()を使うことに注意してください。その関数が今現在2つだけパラメータを受け取っているとしても、将来のバージョンのブラウザでは変わるかもしれません。あなたの拡張機能は新しいパラメータに対して何をすればよいのか知っているかもしれませんが、元の関数の動作を壊さないために、それらの新しいパラメータはそのまま元の関数へ引き渡しましょう。

eval()の正しい使い方とは?

私は、eval()関数の有効な使い方はそれほど無いと思っています。拡張機能の中にはユーザに対して、評価可能なJavaScriptのコードを入力させることを許しているものもあります。そのスクリプトが関数のパラメータとして値を受け取る必要があり、関数を作り変数を渡すのにFunction()コンストラクタを使うことが依然として望ましいとしても、これはeval()の妥当な使い方でしょう。

もう1つのeval()の使い方として、状況に応じて定数を宣言するためにも使えます:

if (typeof MY_CONSTANT == "undefined")
  eval("const MY_CONSTANT = 'foo'");

こうすることによって、もし他のスクリプトで同じ名前の定数が定義されていても、あなたは文法エラーを目にしなくて済むでしょう。しかしながら、私はこれはその場しのぎのやり方だと思います。もし同じ名前空間で実行される未知のスクリプトと衝突することを恐れているのなら、あなたは他のスクリプトが使わないような一意な名前を定数(グローバル変数も)に与えるように気をつけるべきです。また、あなた自身のスクリプトについても、定数宣言を含んでいるスクリプトを複数回読み込まないように気をつけてください。

最後に、実行時にそれ自身のコードを生成するためにeval()を大量に使う、分かりにくい・「圧縮」されたスクリプトもあります。Webにおいては「圧縮された」スクリプトに価値があることは認めますが、拡張機能の中で同じ事をやることにはほとんど意味がありません。拡張機能は1度だけしかダウンロードされませんから、ダウンロードにかかる時間をたった2秒だけ節約できても、誰も喜ばないでしょう。また、「圧縮」されたスクリプトはロードされ実行される度に毎回、処理に余計な時間を食うことでしょう。

エントリにつけられたコメント

1. Simonによるコメント

5番目について。関数の中のコードに手を入れる(単にコードの前後に処理を付け加えるだけでは実現不可能で、関数全体を書き換えないといけないような場合)方法として、どんなやり方なら勧められるというのでしょうか? また、ある1つの拡張機能があなたの推奨しているやり方を実行したら、関数の中身を書き換えるタイプの他のすべての拡張機能の動作が妨げられ、それらの拡張機能はすべてのコードを書き直すことを強いられるので、拡張機能同士が円満に共存できなくなるでしょう。

私は元々はあなたが勧めているようなやり方を取っていましたが、しかしeval()を使うことによってしか解決できないような非互換性の問題に何度か遭遇してきました。より良いやり方があるのなら私は喜んでそれを採用するつもりですが、残念ながら、私にはあなたが勧めているやり方が問題を解決してくれるようには見えません……

4番目について。new Function("some code")eval("some code")と比べてどのように安全なのでしょうか? bug 477380であなたはeval()を禁止することを提案していますが、new Function()も禁止しないと無意味なのではないでしょうか。

Wladimir Palantによる返信:

あなたが書いたわけではない関数の中身に対して変更を行う事は、一般的に言ってよいアイデアではありません。あなたがどんな風にそれをやったとしても、必ず酷い結果になるでしょう。他の手段(例えばObject.watch()など)であなたがやりたいことを実現できないのであれば、多分あなたはそれをするべきではないのでしょう。

new Function()について。それはeval()に比べて本質的に安全であるとは言えませんが、それはたいていの場合静的なコードのために使われ、それほど多くの問題を持ち込みません。これは、トラブルを抱え込まないようにするための良いコーディングの習慣ということです。

2. Mookによるコメント

特権が無いWebページの場合でも同じ事が言えるのでしょうか? Gecko 1.9.1はグローバルなJSONオブジェクトを実装するそうですが、evalInSandboxと同等のものはあるのでしょうか?

evalInSandboxを使うためにUniversalXPConnect権限が必要なのは困ります……

Wladimir Palantによる返信:

クロスサイトスクリプティングを防ぐことについて話しているのだと思いますが――スクリプトのためのサンドボックスは十分な対策とは言えません。これについてはbug 341604(※訳註:IEの独自拡張であるiframe要素のsecurity属性の実装についてのバグ)とWHATWGのWeb Appsの仕様のiframe要素のsandbox属性を参照してください。

5. Dorandoによるコメント

5番目について、例えば元の関数 gBrowser.foo について以下の場合を仮定しましょう(似たようなコードはMozillaのコードベースから簡単に見つけられます。例えばtabbrowser.xmlで「.isTrusted」や「permitUnload」を検索してみてください):

gBrowser.foo = function(param1, param2)
{
  if(!gBrowser.isItSaveToDoSomethingBeforeFoo())
    return;

  if (param1 == "do_nothing")
    return;

  var color = "red";
  doSomething(color, param2.length);

  if (param2 == "some_extensions_want_to_prevent_this")
    doSomethingAnnoying("dark"+color);
}
  1. 関数内でdoSomething()が実行された時に、常にdoSomethingAfterFoo()を実行するようにしたい、という時はどうすればいいのでしょうか?
  2. 関数内でdoSomething()が実行されるであろう時に、常にdoSomethingBeforeFoo()を実行するようにしたい、という時はどうすればいいのでしょうか? 元のコードのうちいくらかを複製することはできますが、それは既に修正されたセキュリティの問題をまた持ち込みかねず、関数を単に書き換えるだけにしない事のメリットを打ち消してしまいかねません。関数に対して行われる変更を常に参照し続けることは、いくつかのシチュエーションでは上手く行くでしょうが、私に言わせてもらうとそれは大変すぎます。(そしておそらくコードをいくらか遅くさせるでしょう。)
  3. gBrowser.foodoSomethingAnnoying()を実行するのを食い止めたい時はどうすればいいのでしょうか?
  4. gBrowser.fooが使う色をgreenに変えたい時はどうすればいいのでしょうか? 追加の関数を置き換えてその呼び出し元関数を確認するようにするという手もありますが、私にとってはそれは何かを壊してしまう可能性を増大させるものでしかないです。関数に本来の処理を行わせた後でその変更を後から取り消すというやり方も、可能ではありますが、良いユーザ体験をもたらすものとは思えません。

どちらの場合も、書き換えられようとしているコードが変化しないことを前提にしていますが――しかし、もしそれが起こったら?

maxVersionはそのために存在しています。

あるいは、ブラウザのその関数がセキュリティ上の問題の修正のために書き換えられたとしたら、その拡張機能は同じセキュリティ上の問題をまた持ち込んでしまうかもしれません。

isItSaveToDoSomethingBeforeFooが導入されて、doSomethingBeforeFoo();eval()でパッチを当てられた場合と同様の内容を含むようになったとしたら、(※訳註:ここで推奨されているやり方の方の)関数の置き換えでも同じ問題が起こり得ます。

その一方で、拡張機能の作者はeval()によって、(セキュリティに関するものも含めて)バグがFirefox本体側で修正されるよりも前にパッチを適用することができます。そのバグが本体側で修正された後は、書き換え対象のコードが見つからなくなるので、eval()によるパッチ適用は望ましい形で失敗する(※訳註:何の変化ももたらさず悪影響も及ぼさないということ)でしょう。

あなたが書いたわけではない関数の中身に対して変更を行う事は、一般的に言ってよいアイデアではありません。

もちろんです、それは組み込みのどんな機能の挙動を変えることについても常に言えることです。しかし拡張機能の作者にとっては、やりたいことを実現するための組み込みのインターフェースや関数が存在しない時に、それを実現するための唯一の手段がこれであるという場合もあります。

Simonが既に指摘していることの繰り返しになりますが、関数へパッチを当てるのではなく関数を丸ごと置き換えるという(※訳註:ここで推奨されている)やり方は、私が述べたようなことをやろうとしているすべての拡張機能に対してそれを完全に妨げてしまいます。ですからどうか、あなたが代替になる方法を提案できないのなら、このような手法を推奨しないでください。

あなたがどんな風にそれをやったとしても、必ず酷い結果になるでしょう。

(以下翻訳中)

今まで私がみてきた限りでは、ほとんどの最小の変更がそれを壊しうるという事実にもかかわらず、(APIの変更を含む)他の種類の変更によってコードが動かなくなるケースの方が、eval()によるパッチの適用が原因で動かなくなるケースよりも多く見られました。

Wladimir Palantによる返信:
  1. あなたはgBrowser.foowindow.doSomethingの両方を拡張する必要があります。gBrowser.fooの開始時にフラグ変数をfalseにセットして、window.doSomethingがそれをtrueにする、doSomethingAfterFooはそのフラグ変数がtrueになった時にだけ呼ばれる、という具合です。
  2. 私はあなたが、予知能力を持ったモジュールを必要としているとは思いません――あなたがやりたいのは、gBrowser.foowindow.doSomethingを呼んだ時にdoSomethingBeforeFooを呼ぶ、という事でしょう(window.doSomethingが他の場所から呼ばれた場合を除いて)。このような場合、やはり両方の関数を拡張するべきです。gBrowser.fooの開始時にフラグ変数をtrueにセットして、終了時にそれをfalseにセットする。window.doSomethingの開始時に、そのフラグ変数の値がtrueであるならdoSomethingBeforeFooを実行する。という具合です。
  3. bのやり方と同じ手法でgBrowser.fooを拡張し、doSomethingAnnoyingについてもそのフラグ変数がtrueな時は何もしないように拡張することで、可能でしょう。ただし、あなたが本当にそれをする必要があって、それが何をどのように壊すのかについては、改めてよく考えてください。
  4. bのやり方と同じ手法でgBrowser.fooを拡張し、doSomethingについてもそのフラグ変数がtrueで且つarguments[0]"red"である場合にarguments[0]"green"に置き換えるように拡張すれば、それも可能でしょう。ただしその場合も、やる前にその影響をよく考えてください。

maxVersionの仕組みについては、大抵の拡張機能は「バージョン3.0.*に対して互換性がある」という風に指定されているので、セキュリティの修正やマイナーリリースでの変更をキャッチアップしてくれません。

その一方で、拡張機能の作者はeval()によって、(セキュリティに関するものも含めて)バグがFirefox本体側で修正されるよりも前にパッチを適用することができます。――このような方法でバグにパッチを当てるのは、実に宜しくないアイデアです。Bugzillaにバグを報告して、ちゃんとしたパッチを書いてください。それが確かに明らかにバグで、安全に修正できるのであれば、その修正はマイナーリリースに取り込まれるでしょう。もしあなたが間違ったことをしていれば、フィードバックを得られるでしょう――それは、誰にも何も尋ねずに「パッチ適用」をしてブラウザの機能を壊してしまうよりも良いことです。

6. Dorandoによるコメント

doSomething(あるいは他の関数)は、 Components.classes[""].createInstance().doSomething(); という風な(※訳註:置き換え不能なネイティブのメソッドを呼ぶ)コードかもしれませんし、関数ではなくべた書きされたコードのブロックかもしれませんし、あるいは、その処理がとても頻繁に呼ばれる機能である場合は置き換え後の関数によって度し難いほどの余計な処理時間がかかるかもしれません(特に、複数の拡張機能がそういうことをするのなら)。

maxVersionの仕組みについては、大抵の拡張機能は「バージョン3.0.*に対して互換性がある」という風に指定されているので、セキュリティの修正やマイナーリリースでの変更をキャッチアップしてくれません。

これは「必ず酷い結果になる」という未来予測への反論ですよ。あなたが言っているのは実際には拡張機能の作者の過ちです。また、私に言わせれば、既存のコードを動かなくしてしまうような変更がMozillaのセキュリティアップデートで行われることがあまりに多すぎます(私が知っている最近の例はBug 442333(※訳註:eval()の第2引数の廃止を決定したバグ)です)。

このような方法でバグにパッチを当てるのは、実に宜しくないアイデアです。Bugzillaにバグを報告して、ちゃんとしたパッチを書いてください。

既にBugzillaに報告されていたり、次のメジャーリリースに修正が取り込まれることが確定していたりするなら、同じコードを使えるでしょう。そのバグが外部の(※訳註:拡張機能などの)コードに対してのみ影響を与えるものである場合は特に、(パッチが提出されていても)そのバグが実際に修正されるまでには何ヶ月もかかることがあります。

それが確かに明らかにバグで、安全に修正できるのであれば、その修正はマイナーリリースに取り込まれるでしょう。

その修正が次のマイナーリリースに取り込まれたと仮定しても、それには最低でも1ヶ月はかかります。その修正内容をバックポートすることはそれほど害を及ぼさないでしょう。

~誰にも何も尋ねずに「パッチ適用」をしてブラウザの機能を壊してしまうよりも良いことです。

もしその拡張機能の意図するところが、そのシチュエーションにおいて行われる通常の挙動を変更する事なのであれば、それは初期状態の挙動を壊してしまおうとするもののように見えるでしょう。

7. Simonのコメント

ちなみに、異なる実行コンテキストでコードを動的に実行することは、eval()のもう1つの妥当な使い方です。

eval("code to inject", context);

あるいは

domWindow.eval("code to inject");

これらは、コードを一時ファイルに書き出して、サブスクリプトローダーで読み込ませ、一時ファイルを削除する、という風なやり方によってのみ置き換えることができます。なぜなら、サブスクリプトローダーは依然としてdata: URIの読み込みを許可していないからです。(この回避策は実に面倒です。テンポラリファイルを使うことは他の問題を引き起こしかねませんから。)

Wladimir Palantによる返信:

「異なる実行コンテキスト」というのは、「特権がないコンテキスト」という意味ですか? それは別物です、そのコードはChrome権限を得ることはないでしょう。

8. Simonのコメント

「異なる実行コンテキスト」というのは、「特権がないコンテキスト」という意味ですか?

そうとは限りません。nsIWindowMediatorによって返されたDOMWindowのコンテキストは、Chrome権限のあるオブジェクトと同じになり得ます。(サブスクリプトローダーを使って読み込ませたスクリプトや、XBLのバインディングの中に書かれたスクリプトのようにwindowオブジェクトを汚染することなく動的に使われるスクリプトにおいては。)

最初の影響を見るには、以下のコードをエラーコンソールで実行してみてください:

Components.classes["@mozilla.org/appshell/window-mediator;1"]
          .getService(Components.interfaces.nsIWindowMediator)
          .getMostRecentWindow("navigator:browser")
          .eval("location");

Page 33/239: « 29 30 31 32 33 34 35 36 37 »

Powered by blosxom 2.0 + starter kit
Home

カテゴリ一覧

過去の記事

1999.2~2005.8

最近のつぶやき

オススメ

Mozilla Firefox ブラウザ無料ダウンロード