宣伝。日経LinuxにてLinuxの基礎?を紹介する漫画「シス管系女子」を連載させていただいています。
以下の特設サイトにて、単行本まんがでわかるLinux シス管系女子の試し読みが可能!
SCRAPBLOG : JavaScript 製 XPCOM で配列構造・列挙構造のデータをメソッドの戻り値にする
独自に開発したXPCOMコンポーネントに対して配列を渡したり、あるいは戻り値を配列で受け取ったり、ということをやる方法はいくつかある。上記エントリではコメント欄も含めると4つの方法が紹介されていて、そのうちコメント欄にある2つはJavaScriptの配列をそのまま受け渡せるという点で有用だ。特にnsIVariantインターフェースを使うやり方は、戻り値に使う時に余計な引数を定義しなくていいので、実際にそのXPCOMコンポーネントをJavaScriptから使う時にとても使い勝手がいい。
ということでXUL/Migemoでは積極的にnsIVariantを使ってたんだけど、これがMinefield(検証したバージョンは3.7a4pre)で動かなくなってた。
結論から言うと、これはnsIVariantインターフェースのIIDが6c9eb060-8c6a-11d5-90f3-0010a4e73d9aから81e4c2de-acac-4ad6-901a-b5fb1b851a0dに変更されたせいで起こっている問題で、nsIDOMRangeのIIDが変更された時に起こった問題と同様の物だ。
変更が入ったのは昨年9月で、HTML5の新しい仕様に対応するための作業の一環として、何らかの必要があってインターフェースに機能を加えると同時にIIDも変わったらしい。nsIVariantはFROZENなインターフェースじゃないから、nsIDOMRangeの時のようにIIDが元に戻されることは多分あり得ない。よって、考えられる対策は以下のいずれかということになる 。
JavaScriptコードモジュールにするデメリットは、Thunderbird 2で利用できなくなってしまう点と、APIが変わってしまう点。バイナリを分けるデメリットは、リリースの時の作業がめんどくさくなる(XPIファイルが2つになるので)という点。どっちを選んでも大変なのは変わらない……
APIが変わってしまうことは避けたかったので、結局、後者の方で対処することにした。
前から使ってるXPI生成用シェルスクリプトに起動オプションでサフィックスを指定できるようにして、
こんなショボいスクリプトを作って、前出のスクリプトと一緒に
call xpidl.bat xulrunner-sdk-1.9.2
bash makexpi.sh -n xulmigemo -v 0 -s "1.9.2"
call xpidl.bat xulrunner-sdk-central
bash makexpi.sh -n xulmigemo -v 0 -s "central"
てな感じで実行するようにして(make.bat / make.sh)、MozillaのFTPサイトからXULRunner SDKのファイル一式を入手して、
という感じにファイルを配置するようにした。
XPIを作りたい時にはXULRunner SDKが必要になってしまうけど、スクリプトいっこ走らせれば xulmigemo-mozilla-1.9.2.xpi と xulmigemo-mozilla-central.xpi という風に複数のXPIを出力できるようになったので、リリースにかかる手間は少しは軽減された……のかな……
追記。Gomitaさんのコメントを見て、IDLファイルからincludeの行を消して試してみたら、それでちゃんとコンパイルできた。なんでだ……!!!
えーと。ずっと勘違いしてたんだけど、#include "nsISupports.idl"
みたいな行は、interface xmIXMigemoFileAccess : nsISupports
てな感じでインターフェース定義の継承元に別のインターフェースを使う場合にだけ必要で、戻り値や引数に使う分には単に interface nsIVariant;
とだけ書いておけばいいみたいですね……そうすると、コンパイル時には余計なIIDが含まれなくなって、Firefox 3.6まででも3.7以降でも問題なく使えるXPTファイルが作られるみたい。
まとめ。
interface インターフェース名;
と書く。interface インターフェース名;
だけ書く。そんなわけで、xmIXMigemo.idlの頭の所はずいぶんスッキリしました。
#include "nsISupports.idl"
#include "nsIObserver.idl"
interface nsIObserver;
interface nsIFile;
interface nsIVariant;
interface nsIDOMWindow;
interface nsIDOMDocument;
interface nsIDOMRange;
interface nsIDOMElement;
interface nsIDOMNode;
/* Utilities: You can use them for your language without additional implementation. */
[scriptable, uuid(4aca3120-ae38-11de-8a39-0800200c9a66)]
interface xmIXMigemoFileAccess : nsISupports
{
(以下略)
自分の拡張機能でもJS製XPCOMで引数や戻り値にnsIVariant型を使っていますが、今のところFirefox 3.6とFirefox 3.7a4pre (Gecko/20100325) の両者でnsIVariant絡みの問題は発生していません。
おかしいなと思って色々調べたのですが、どうやらXPTファイルの元になるIDLファイルに「#include "nsIVariant.idl"」が入っている場合にだけ問題が発生するような気がします。
試しにXUL/Migemoの3つのIDLファイルの「#include "nsIVariant.idl"」を削除してXPTを作ってみたところ、Firefox 3.6と3.7a4preの両方で動作可能なようでした。
そもそも「#include "nsIVariant.idl"」が何を意味しているのか、よくわかっておりませんが…
えぇぇぇぇ?!
#include nsIVariant.idl
の行はXULRunner SDKの中にあるnsIVariant.idlを読み込む物で、読み込んでおかないと引数や戻り値の型にnsIVariantを使えないはずなんですが……実際、手元のXULRunner SDKのxpidlでやるとどうしてもそうなりますし。
Gomitaさんはどうやってidlからxptをコンパイルされてるんでしょうか? そのやり方に解決のヒントがある気がします。
使っているSDKはかなり前(Firefox 2.0の頃)から変わっておらず、確か下記のページからダウンロードしたような記憶があります。今はリンク切れになっててダウンロードできませんが。
Gecko SDK - MDC
https://developer.mozilla.org/ja/Gecko_SDK
XPTファイルを作る手順についても、自作スクリプトで機械的にやっているのですが、肝の部分は以下のようなコマンドです。
***\gecko-sdk\bin\xpidl.exe -m typelib -w -v -I ***\gecko-sdk\idl -e components\hoge.xpt components\hoge.idl
ちなみに、自作拡張機能のIDLファイルの中に「#include nsIVariant.idl」の行は入れてませんが、「interface nsIVariant;」という行は入れてあります。fuelIApplication.idlを見てもやはり「#include nsIVariant.idl」の行はありませんですね…
http://mxr.mozilla.org/mozilla-central/source/browser/fuel/public/fuelIApplication.idl
あ、上記で「使っているSDK」というのは普段自作拡張機能で使っているSDKのことです。
今回、実験としてXUL/Migemo用のXPTを作ったのは、nsIVariantのIIDが「81e4c2de-acac-4ad6-901a-b5fb1b851a0d」に変わった後のIDLを含むSDKになります。
の末尾に2020年11月30日時点の日本の首相のファミリーネーム(ローマ字で回答)を繋げて下さい。例えば「noda」なら、「2010-03-23_nsivariant.trackbacknoda」です。これは機械的なトラックバックスパムを防止するための措置です。
writeback message: Ready to post a comment.