Components.utils.import/unload のメモ

Gecko 7.0 から Components.utils.unload() というメソッドが実装された。

詳細は上の記事を見るべきだが、挙動としては、

  • Components.utils.import() で load したモジュール(のオブジェクト)を unload する
  • メソッドを呼び出した時点では、unload されたモジュール(のオブジェクト)への参照は消えない
  • 次に Components.utils.import() を呼び出した際に、新しく load されたモジュール(のオブジェクト)への参照に切り替わる

といった具合になっている。
Components.utils.import() には省略可能な第2引数があって、第2引数にオブジェクトを渡してやると、そのオブジェクトに新しいメンバが追加され、そのメンバがモジュールへ参照するようになる。
で、Components.utils.unload() 後に参照がどうのこうのとあって、気になって調べてみた。

サンプルコード

以下のコードを Firefox*1 の Scratchpad にて、chrome権限にて実行した

let a = {};
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm", a);
alert(a.XPCOMUtils.hogehoge);//undefined
a.XPCOMUtils.hogehoge = "hogehoge";
alert(a.XPCOMUtils.hogehoge);//"hogehoge"
Components.utils.unload("resource://gre/modules/XPCOMUtils.jsm");//unload
alert(a.XPCOMUtils.hogehoge);//"hogehoge"
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
alert(a.XPCOMUtils.hogehoge);//"hogehoge"
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm", a);
alert(a.XPCOMUtils.hogehoge);//undefined

結果

  • Components.utils.import() の第2引数にオブジェクトを指定している場合、Components.utils.unload() を経ても、メンバの保持するモジュールへの古い参照はそのまま
  • unload後の Components.utils.import() の際に、第2引数に初回の load 時に指定したオブジェクトを渡してやると、新しい参照へと切り替わる

その他

JSコードモジュール内のオブジェクトを nsIObserverService とかでオブザーバとして登録してる場合、Components.utils.unload() の際に、登録解除する手段が無いので、nsIWeakReference とかで弱参照にした方がいいんじゃないか?

*1:Mozilla/5.0 (Windows NT 6.1; WOW64; rv:9.0a1) Gecko/20110916 Firefox/9.0a1