SpiderMonkeyのgetterとsetter

2010-04-16の記事で知ったのは今日という、自分の情報収集能力のダメさを感じている。

MozillaJavaScript実装であるSpiderMonkeyは昔から、getter,setterを独自にサポートしていたけど、ECMAScript 5th の実装に合わせて一部の実装を廃止しましたよって話。

ECMAScript 5th のgetterとsetter

Object.definePropertyの話はES5, Property Descriptor解説 - 枕を欹てて聴くが詳しいので省略。

まあともかく、Object.definePropertyと、オブジェクトリテラル表記が仕様に盛り込まれたわけで、以下の様な書き方が正式にできるようになった。

var o = {
  _prop: "",
  get prop() {
    return this._prop;
  },
  set prop(v) {
    return this._prop = v;
  }
};

昔のSpiderMonkey実装

昔のSpiderMonkeyにもgetter,setterがあったが、ECMAScript 5th とはちょい違う実装であった。

  • Object.definePropertyはない
    • 代わりに、Object.prototype.__defineGetter__,Object.prototype.__defineSetter__等が実装されていた
  • オブジェクトリテラル表記も基本的には同じだが少し違う

「オブジェクトリテラル表記も基本的には同じだが少し違う」について

var o = {
  get prop () { return "OK"; },
};
// これは以下と同じ
var o = {};
o.__defineGetter__("prop", function() { return "OK"; });

さらに、昔は以下のような書き方も可能だった。

var o = {
  get prop funcname() { return "OK"; },
};
// これは以下と同じ
var o = {};
o.__defineGetter__("prop", function funcname() { return "OK"; });

つまり、関数名を付けることができたわけ。

今の実装

このオブジェクトリテラルでの表記で関数名を付けられたのが ECMAScript 5th に合わせてできなくなった。

もちろん、Object.definePropertyで、以下の様にすれば名前を付けることは可能。

var o = {};
Object.defineProperty(o, "prop", {
  enumerable: true,
  configurable: true,
  get: function funcname() { return "OK"; },
});

Gecko2.0b11preでは

気になってFirefox4.0b11preで確認したが、上記オブジェクトリテラルでの表記は例外が出るようになっていた。

が、Object.prototype.__defineGetter__等はまだ存在する模様。よって

var o = {};
o.__defineGetter__("prop", function funcname(){ ...; });
Object.getOwnPropertyDescriptor(o, "prop").get.name; // funcname

は使える。
まあこれはFirefox内のコードでも使っているししばらくは使えそうかなという印象。今後消される可能性はあるけど。


因みに、MozillaアプリケーションでGeckoのバージョンを知りたければ、インストールディレクトリにあるplatform.iniを見れば分かる。(UAにはビルド日付はあるけど、バージョンが載ってないのよね...) または、エラーコンソールにComponents.classes["@mozilla.org/xre/runtime;1"].getService(Components.interfaces.nsIXULAppInfo).platformVersionを貼りつけて実行すれば出てくる。