Safari の Date の修正2006年10月25日 20時57分

Safari の Date#setMonth にバグがあると聞いて試してみたところ、そもそも Date コンストラクタからして月の負数指定に対応していない様子。やれやれ仕方のない子だな WebKit はというわけで Date オブジェクト自体を書き換えるスクリプトを書いてみた。適用すると Date コンストラクタ、 Date.UTCDate#setMonthDate#setUTCMonthDate#setFullYearDate#setUTCFullYear で月を指定する際に負数を使えるようになる。

13 以上の数も扱えないことに気づいたのでテストケースを修正。スクリプトはそのままで通用する。

書いている途中で気づいたのだが、WebKit、というより JavaScriptCore では関数の引数と arguments オブジェクトのプロパティが値を共有しない。つまり、function f(arg1, arg2, ...) { ... } としたとき、argN を変更しても arguments[N-1] にはその変更が反映されないし、逆も同じだ。まったくもってこれはひどい。Date#setMonth への負数指定も、引数と arguments オブジェクトでの値の共有も、すでに開発版では修正されているようだが、よくまあここまで気づかなかった / 放っておいたものだなと思ってしまう。

それから、これは Konqueror / KJS でも同じだが、組み込みオブジェクトのプロトタイプオブジェクト (String.prototype など) には constructor プロパティを設定できない。仕方がないので上述のスクリプトではインスタンスに constructor プロパティを設定している。

ほかにも開発版ではいろいろと修正されているようだったので、まとめて Safari の JavaScript の不備を大幅に更新した。DOM 周りの拡張にもいくらか触れている。

なお、Date#setMonth を直すだけでいいのなら、以下のようにするのが簡単かと思う。

Date.prototype.setMonth = function (month, date) {
  return this.setFullYear(
    this.getFullYear() + Math.floor(month / 12),
    ((month %= 12) < 0) ? month + 12 : month,
    (arguments.length >= 2) ? date : this.getDate()
  );
};