yossydev Blog

ecma262とtest262へのコントリビュートと背景

publishedAt:
2025/03/04
updatedAt:
2025/03/04
目次

Intro

最近、ecma262とtest262へそれぞれPRがマージされました。

筆者としては、こういうのはコントリビュートしたことよりもすることになったきっかけの方が気になるので、ブログにまとめようと思います。

Editorial: Store ToString(𝔽(k)) in a variable for consistency

まずはecma262へ出したPRから。これは筆者がNovaにTypedArray周りのパッチを送っている時に気付いたものです。

基本的にTypedArrayはArrayと仕様書で似ている点は多いです。 その中で、以下のような違いを見つけました。

Array.prototype.indexOfTypedArray.prototype.indexOf
Array indexOfTypedArray indexOf

本当に細かいですが、Array.prototype.indexOflet Pk = ! ToString(𝔽(k))とPkに代入しているのに対し、TypedArray.prototype.indexOfではそのまま、Let _elementK_ be ! Get(_O_, ! ToString(𝔽(_k_)))となっています。

これによってエンジン側の処理速度が変わる、みたいなのは特にないと思うんですが、実装する際に一度変数に入れさせてくれた方が綺麗だし自然なので、記念に直しておくかーって感じでした。

ちなみに余談でこれは別ブログに書こうと思いますが、最適化の観点でここのループ処理結構変えたので、そもそもToStringは使ってないです。なので本当にただ仕様書を直した人になりました。

Update String.fromCodePoint info to align with latest ECMAScript spec

次にtest262です。

これはNovaでString.fromCodePointsを実装して、そして別の機会にtest262を眺めているときに気付いたものです。

test262には、そのテストがecma262のどこをテストしているのかのメタ情報をInfoに書いて示してくれています。例えば以下のように。

1. Let result be the empty String.
2. For each element next of codePoints, do
    a. Let nextCP be ? ToNumber(next).
    b. If nextCP is not an integral Number, throw a RangeError exception.
    c. If ℝ(nextCP) < 0 or ℝ(nextCP) > 0x10FFFF, throw a RangeError exception.
...
ref: https://github.com/tc39/test262/blob/9d8efae5c2c1848b9c3362c4aa81dd360ff8d3a7/test/built-ins/String/fromCodePoint/argument-is-Symbol.js#L10-L15

これは筆者としてはとてもありがたく、何かしらのbuilt-inを実装するとそれに関するtest262がpassしているかをチェックします。

passしているものは問題ないですが、crashやfailするとそのテストを読み、その際に書いてあるInfoから大体の箇所を予測します。

ただ、このInfoはなかなかメンテされておらず、普通に結構古い情報が書いてあったりします。今回のString.fromCodePointも、2020年に更新されてからそのままになっていました。(#2018 #2152

これが更新されていないと、エディタで検索したときになんかヒットしない。みたいなケースになるので、絶妙に不便だったりします。

このケースは他にもあり、例えばToIntergerとかあったりします。

実はecma262上にはもうToIntergerはもうなく、全てToIntegerOrInfinityって名前にrenameされています。(背景までは追えてないですがPRはEditorial: Make numeric values and operations default to mathematical values #2007) しかしecma262のInfoには大量にまだToIntergerが残っています。

これを直してもいいんですが、PR出した際に以下のようなレビューをもらいました。

No strong feelings for or against this, but there are thousands of tests that have outdated metadata due to editorial changes - unless there's a way to automate these updates it won't be feasible to keep tests in sync with the spec.

ようは手動で追従するのではなく自動で変更される仕組みを作るべきだという、あまりにもそれはそうって感じのコメントでした。。 まぁけどやってる内容が間違いではないのでマージしてもらいましたが、確かに仕様書の変更を手動で変更していくのは非現実的ではあるので、とりあえずPR出すのはやめておくかーという感じです。

とりあえず、Before/Afterでは以下のような感じです。

BeforeAfter
1. Let codePoints be a List containing the arguments passed to this function.
...
5. Repeat while nextIndex < length
    a. Let next be codePoints[nextIndex].
    b. Let nextCP be ToNumber(next).
    ...
6. Return the String value whose elements are, in order, the elements in the
List elements. If length is 0, the empty string is returned.
1. Let result be the empty String.
2. For each element next of codePoints, do
    a. Let nextCP be ? ToNumber(next).
    b. If nextCP is not an integral Number, throw a RangeError exception.
    c. If ℝ(nextCP) < 0 or ℝ(nextCP) > 0x10FFFF, throw a RangeError exception.
    d. Set result to the string-concatenation of result and UTF16EncodeCodePoint(ℝ(nextCP)).
3. Assert: If codePoints is empty, then result is the empty String.
4. Return result.

まとめ

ここまで読んでもらうと本当に些細な変更だとわかると思うし、めちゃくちゃ大した理由があったわけでもなかったんですが、 起こしたアクションの結果ではなく、その結果を起こすまでの過程は何においても気になるところだと思うので、今後もこういうのは残していこうと思います。

0