Opera10.50のECMA規格の準拠度を調べてみた

Opera10.50が登場していきなり世界最高速という触れ込みで注目を集めていて、いろいろなベンチマーク結果も公開されてますが、僕として気になるのはECMA規格にどこまで正確に準拠しているかという点です。ざっと調べてみました。実用上の大きな問題となるようなものはないものの、細かいところでは規格との食い違いが見られました。いわゆる重箱の隅を突くようなものなのですが、Opera10.10では正常だったものが異なった動作になっているものもあります。Scriptエンジンが完全に置き換えられたのでしょうか?

Array.prototype.join(separator)メソッド

Arrayの各要素を文字列にしたものと、その間をseparatorを文字列にしたもので連結する関数ですが、separatorが自分自身のとき正しくありません。Opera10.10では正しい動作でした。

var x = [1,2,3];
x.join("-");            // "1-2-3"                 OK
x.join([1,2,3]);        // "11,2,321,2,33"         OK
x.join(x);              // "123"                   NG

[訂正:x.join([1,2,3])の結果を"11,2,32,1,2,331,2,3"と書き違えていた箇所を訂正 2010/3/5]

Array.prototype.sort(comparefn)メソッド

comparefnが指定されていないとき、Arrayの要素は文字列としてソートされるが、undefinedはあらゆる文字列よりも大きなものとして処理されます。つまり、ソート結果の配列はundefiendは後ろの方に集められます。しかし、Operaではundefined であるべきところに要素が入っています。

var x = ["d","b",,"a",,"e","c"];
x.sort();               // ["a", "b", "c", "d", "e", "e", "c"]  NG

正しくは ["a", "b", "c", "d", "e", undefined, undefined ]です。

Opera10.10ではこの例自体は正しい動作です。しかし10.10にも類似の問題がありそれに関してはOpera10.50では正しい動作になっています。

ラベル中のbreak文

下記のコードでbreak文はラベルfooブロックのbreakではなくfor文のbreakになりますが、Operaではラベルfooブロックのbreakのような動作になっています。その結果、s=45と表示されます。正しくはs=0です。Opera10.10では正しく動作していました。

function test() {
  var s = 0;
  for (var i = 0; i < 10; i++) {
    s += i;
    foo: {
      break;
    }
  }
  alert("s=" + s);
}

RegExp.prototype.match()メソッド

実際上ほとんど登場しないような正規表現パターンですが、下記がNGになります。

"abc".match(/\S?/g);            // ['a', 'b', 'c', '"' ]   NG

結果の配列の最後の要素は長さゼロの文字列(空文字)が正しい動作になりますが、ダブルクォートになっています。面白いことに、"abc"の代わりに'abc'にするとシングルクォートになります。

"aaa".match(/(a*){2}/);         // null  NG
"aaa".match(/(a*){3,5}/);       // null  NG
"aaa".match(/(a*){100}/);       // null  NG

これらは、全て['aaa', '']が正しい動作になります。Operaでは照合しないという結果になってしまいます。

parseInt(string, radix)関数

前回のエントリーでparseInt('08')が8になるのはOperaだけと書きましたが、それはOpera10.10での動作でした。10.50では0で始まる文字列をradixを省略してpaseInt()すると8進数として解釈するという古い仕様(であるが多くのブラウザと同じ)の動作に戻っています。


これら以外にも細かい問題はありますが、結論としては全体的に10.10よりも10.50の方が規格の準拠性は高くなっていることが確認できました。