2018.10.31更新
このバグはiOS 12.1で修正されました。良い一日をお過ごしください〜
新しくリリースされた iOS 12 Safari で、配列の値の状態に問題があることがわかりました。たとえば、次のようなコードです。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0">
<title>iOS 12 Safari bugs</title>
<script type="text/javascript">
window.addEventListener("load", function ()
{
let arr = [1, 2, 3, 4, 5];
alert(arr.join());
document.querySelector("button").addEventListener("click", function ()
{
arr.reverse();
});
});
</script>
</head>
<body>
<button>Array.reverse()</button>
<p style="color:red;">test: click button and refresh page, code:</p>
</body>
</html>
ページを更新した後も、配列の値は逆になっています。これはバグでしょうか、それとも新しい Safari の機能でしょうか?
こちらはデモページです。iOS 12 Safari で使用してみてください。参考:
ベストアンサー1
それは間違いなくバグです! そして非常に深刻なバグです。
このバグは、すべての値がプリミティブ リテラルである配列初期化子の最適化が原因です。たとえば、次の関数があるとします。
function buildArray() {
return [1, null, 'x'];
}
の呼び出しから返されるすべての配列参照はbuildArray()
同じメモリにリンクされ、などの一部のメソッドtoString()
は結果をキャッシュします。通常、一貫性を保つために、このような最適化された配列に対する変更可能な操作はデータを別のメモリ領域にコピーしてリンクします。このパターンはコピーオンライト、略して CoW とも呼ばれます。
このreverse()
メソッドは配列を変更するため、コピーオンライトをトリガーするはずです。しかし、元の実装者 (Apple の Keith Miller) がreverse()
多くのテストケースを作成したにもかかわらず、このケースを見逃したため、コピーオンライトはトリガーされませんでした。
このバグはアップルに報告8月21日。修正WebKitリポジトリに登場2018 年 8 月 27 日にリリースされ、2018 年 10 月 30 日に Safari 12.0.1 および iOS 12.1 で出荷されました。