Visit Mozilla.org

Using JavaScript code modules

出典: MDC

この記事は Firefox 3 の新機能について述べています


JavaScript コードモジュールは、 Firefox 3 (Gecko 1.9) にて導入されたコンセプトで、特権を持った異なるスコープ間でコードを共有するために用いられます。また、モジュールは、グローバルな JavaScript のシングルトンオブジェクトを生成するために用いることもできます(以前は JavaScript XPCOM オブジェクトを使う必要がありました)。 JavaScript コードモジュールは、登録されたパスに配置された純粋な JavaScript のコードです。 Components.utils.import を使って、 XUL スクリプトや JavaScript XPCOM スクリプトのような特定の JavaScript のスコープへモジュールを読み込むことができます。

非常に単純な JavaScript モジュールの例を以下に示します:

var EXPORTED_SYMBOLS = ["foo", "bar"]

function foo() {
  return "foo";
}

var bar = {
  name : "bar",
  size : "3"
};

var dummy = "dummy";

モジュールは普通の JavaScript を使って、関数、オブジェクト、定数、その他あらゆる JavaScript の型のオブジェクトを生成していることに注目してください。また、モジュールは EXPORTED_SYMBOLS という名前の特別な Array を定義します。 EXPORTED_SYMBOLS 内で命名されたすべての JavaScript オブジェクトは、モジュールからエクスポートされてインポート先のスコープ内で使用可能となります。例:

Components.utils.import("resource://app/modules/my_module.jsm");

alert(foo());         // "foo" と表示される
alert(bar.size + 3);  // "6" と表示される
alert(dummy);         // 'dummy' はモジュールからエクスポートされないため、 "dummy is not defined" と表示される

Components.utils.import の動作の非常に重要な点は、モジュールが読み込まれた時点でキャッシュされ、次のインポート時は新しいバージョンのモジュールを再読み込みすることなく以前にキャッシュされたバージョンを使用するということです。これは、モジュールが複数回インポートされたときに、共有されることを意味します。モジュールをインポートしたあらゆるスコープ内で、データ、オブジェクト、関数の変更が可能となります。例えば、単一のモジュールが異なる2つの JavaScript のスコープ内へインポートされた場合、一方のスコープでの変更は他方のスコープにも影響します。

スコープ 1:

Components.utils.import("resource://app/modules/my_module.jsm");

alert(bar.size + 3);  // "6" と表示される

bar.size = 10;

スコープ 2:

Components.utils.import("resource://app/modules/my_module.jsm");

alert(foo());         // "foo" と表示される
alert(bar.size + 3);  // "13" と表示される

このような共有の動作によって、ウィンドウや XUL スクリプトや XPCOM コンポーネントをまたいでデータを共有できるシングルトンのオブジェクトを生成することが可能となります。

[編集] resource: プロトコル

Components.utils.import を使うとき、 "resource://" プロトコルを用いてコードモジュールが読み込まれることに注目してください。 resource URL の基本的な文法は以下のようになります:

resource://<alias>/<relative-path>/<file.js|jsm>

<alias> は、通常アプリケーションや XUL ランタイムとの相対的なファイルパスへのエイリアスです。 XUL ランタイムによって最初から定義されたいくつかのエイリアスがあります:

  • app - XUL アプリケーションのパスへのエイリアス。
  • gre - XUL ランタイムのパスへのエイリアス。

<relative-path> は複数の階層とすることも可能で、常に <alias> で定義されたパスに対する相対パスとなります。一般的な相対パスは "modules" であり、 XUL Runner や Firefox にて使用されています。コードモジュールは拡張子 .js や .jsm の単一の JavaScript ファイルです。

拡張機能や XUL アプリケーションへ独自のエイリアスを追加する最も簡単な方法は、 chrome manifest 内の以下のような行によって登録することです:

resource aliasname uri/to/files/

例えば、拡張機能 foo の XPI ファイルがモジュール bar.js を含むトップレベルのモジュールディレクトリを有する場合、以下の命令によってそのディレクトリへのエイリアスを作ることができます。

resource foo modules/

すると、以下の一文で JavaScript コードへモジュールをインポートすることが可能となります。

Components.utils.import("resource://foo/bar.js");

プログラムによって resource プロトコルへ独自のエイリアスを追加することもできます。例:

var ioService = Components.classes["@mozilla.org/network/io-service;1"]
                          .getService(Components.interfaces.nsIIOService);
var resProt = ioService.getProtocolHandler("resource")
                       .QueryInterface(Components.interfaces.nsIResProtocolHandler);

var aliasFile = Components.classes["@mozilla.org/file/local;1"]
                          .createInstance(Components.interfaces.nsILocalFile);
aliasFile.initWithPath("/some/absolute/path");

var aliasURI = ioService.newFileURI(aliasFile);
resProt.setSubstitution("myalias", aliasURI);

// コードモジュールはサブフォルダではなくエイリアスフォルダ直下にあるとする
Components.utils.import("resource://myalias/file.jsm");

// ...