TinyTableV3 のソート実装における文字列比較の問題点

・Date.prototype.toString, Date.prototype.toUTCString で解釈し得ない値が引数の取られたとき、戻り値は実装依存となる。(ES5 規定) ・ほとんどのブラウザでは Date.parse('1') は NaN を返すが、Google Chrome 7 は数値を返す。
0
think49 @think49

TinyTableV3 は Google Chrome 7 のソート結果がおかしくなる。( http://goo.gl/rEWH )

2010-11-02 02:45:45
think49 @think49

値を比較しているコードは function cp(f,c){ の辺り。

2010-11-02 02:46:01
think49 @think49

(step1) string1.toLowerCase(); string2.toLowerCase(); で両値を小文字に変換

2010-11-02 02:46:12
think49 @think49

(step2) parseFloat() でNumber型の値に変換し、両値とも NaN でなければ string1, string2 に代入

2010-11-02 02:46:18
think49 @think49

(step3) Date.parse(); でDate値としてパースし、両値とも NaN でなければ string1, string2 に代入

2010-11-02 02:47:25
think49 @think49

(step4) string1 と string2 を比較し、string1 > string2 なら「1」を、string1 < string2 なら「-1」を、それ以外(string1 === string2) なら「0」を返す

2010-11-02 02:48:40
think49 @think49

問題は明らかに (step3) にある。

2010-11-02 02:49:08
think49 @think49

"一般に、その実装の toString か toUTCString メソッドによって生成されえない文字列を与えられたときの Date.parse に生成される値は、実装依存である。" ( ES3 : http://goo.gl/stGI )

2010-11-02 02:50:37
think49 @think49

"in general, the value produced by Date.parse is implementation-dependent when given any String value ..." ( ES5: http://goo.gl/G8KO )

2010-11-02 02:53:22
think49 @think49

ate.prototype.toString, Date.prototype.toUTCString で解釈し得ない値が引数の取られたとき、戻り値は実装依存となる。

2010-11-02 02:54:13
think49 @think49

Date.parse(1) を評価するとき、IE8, Firefox v3.6.12, Opera v10.62 は NaN を返す。 Google Chrome 7 は数値を返す。

2010-11-02 02:57:46
think49 @think49

そして、Google Chrome 7 において (Date.parse(1) === Date.parse(-1)) は true となる。

2010-11-02 02:57:57
think49 @think49

TinyTableV3 は NaN を返す挙動を期待しているが、Date.parse はDateフォーマットではない引数に対してどのような値を返すかは実装依存と ES5 で規定されているので好ましい実装ではないと思う。

2010-11-02 03:00:57
think49 @think49

修正方法としては string1 及び string2 が Date.parse でパース可能な値かどうか正規表現でチェックする事だと思うけど、Dateの書式がESで規定されていない感じなので良くわからない…。

2010-11-02 03:05:16
think49 @think49

ただ、"1" と "-1" の比較ぐらいなら簡単にできる。 そもそも、parseFloat でNumber型の値に変換できた時点で Date.parse を実行しなくて良いはずだ。

2010-11-02 03:06:35
think49 @think49

(step2) で両値が NaN と判定できた時点で Date.parse を実行しなければ解決できると思う。

2010-11-02 03:07:25
think49 @think49

厳密には Date.parse を実行できるか見るために先に正規表現による判定が先にあるべきな気もするけど、とりあえずは修正できるんじゃないかなと。

2010-11-02 03:09:37
think49 @think49

実証コードを ideone.com ( http://ideone.com/A4M7k ) にUPした。 ideone.com では rhino を使っており、Date.parse('1') は NaN を返す模様。

2010-11-02 03:22:01
think49 @think49

ideone.com に適応させるため print() を使っているが、console.log() に一括置換すれば Google Chrome 7 で同現象を再現できる。

2010-11-02 03:22:24