🪁

マジでどうでもいいWebKitのバグを修正した(Function.prototype.toString編)

2024/04/25に公開

インターナルなDiscordで人に説明したやつをそのままコピーしたものです。

https://webkit.org/blog/15375/release-notes-for-safari-technology-preview-193/ の JavaScript の Resolved Issues にあるやつです。コミットは https://github.com/WebKit/WebKit/commit/1ff045b365bb63494783062033d5ef8a0c629cb7 です。


Function.prototype.toString という関数はthisの関数を文字列化して返します。そしてビルトイン関数に対してどういう文字列を返すべきか、というのは仕様に定められています。[1]

たとえば
Function.prototype.toString.call(Array.prototype.map)"function map() { [native code] }" という文字列を返します。

さらに、アクセサプロパティのゲッター/セッター関数に対しては特別なルールがあります。function のあとに get をつけて出力する必要があるのです。たとえば Set.prototype.size はアクセサプロパティなので

const getter = Object.getOwnPropertyDescriptor(Set.prototype, "size").get;
console.log(Function.prototype.toString.call(getter));

"function get size () { [native code] } " を出力します。

しかし、WebKitの実装には、この特別なルールに従わないビルトインのアクセサプロパティがいくつか存在しました。RegExp Legacy Features のプロパティたちなどがそうです[2]

たとえば RegExp["$+"] はアクセサプロパティですが

const getter = Object.getOwnPropertyDescriptor(RegExp, "$+").get;
console.log(Function.prototype.toString.call(getter));

"function $+() { [native code] }" と出力していました。これはゲッター関数に対する Function.prototype.toString であるにも関わらず function のあとに get がないので仕様に違反しています。

なので、めっちゃわかりやすく言えば

const getter = Object.getOwnPropertyDescriptor(RegExp, "$+").get;
console.log(Function.prototype.toString.call(getter));
// 変更前: "function $+() { [native code] }"
// 変更後: "function get $+() { [native code] }"

ということです。なんじゃそりゃ。

ということで、今回自分の行った変更では、そのような一部のアクセサプロパティのゲッター・セッター関数に対する Function.prototype.toString であっても function のあとに get をつけるように修正した、ということでした。マジでどうでもいいですね。

脚注
  1. https://tc39.es/ecma262/#sec-function.prototype.tostring ↩︎

  2. https://github.com/tc39/proposal-regexp-legacy-features/ ↩︎

Discussion