Chrome で Object.entries で取得出来る数が足りなくなるバグが起きた
◆ コンソール上に値を表示させるとそれ以降 Object.entries で取得する要素の数が足りない
◆ コンソール上に表示させる前は問題なし
◆ Symbol がキーにあるとその数だけプロパティが足りなくなる
◆ devtools 開いてない状態なら問題なし
◆ コンソール上に表示させる前は問題なし
◆ Symbol がキーにあるとその数だけプロパティが足りなくなる
◆ devtools 開いてない状態なら問題なし
Object.entries の結果の要素が足りない
思い通りに動かなくて原因を調べていくと信じられない現象が起きました調べていたときのスクショです
Object.entries でなぜか最後の値が取得できず原因がわからず困っていたのですが 一度そのオブジェクトを表示すると数が減るようです
何いってんだこいつ とでも突っ込まれそうなバグ報告ですがそうとしか言えません
まずデータの作成直後に Object.entries を実行すると 10 の結果が返ってきています
その後に値を直接評価して中身を確認します
10 個のデータがあるオブジェクトです
もう一度 Object.entries を実行すると 9 個しかなくなっています
ですがそのデータを確認すると中身は 10 個のデータがあります
なぜか最後のデータが Object.entries で取得できないです
最小限の再現できるコード
ライブラリ部分だったので面倒だったのですが 徐々に機能を削っていって最小限の再現できるコードを作りましたSymbol がキーのプロパティが存在することが問題みたいです
11:38:24.140 const x = {[Symbol()]: Symbol()}
x.a = 1
x.b = 1
x.c = 1
Object.entries(x)
11:38:24.153 ▶ (3) [Array(2), Array(2), Array(2)]
11:38:25.139 x
11:38:25.145 ▶ {a: 1, b: 1, c: 1, Symbol(): Symbol()}
11:38:28.114 Object.entries(x)
11:38:28.121 ▶ (2) [Array(2), Array(2)]
11:38:35.057 Object.keys(x)
11:38:35.069 ▶ (3) ["a", "b", "c"]
また Object.values でも Object.entries 同様に要素の数が足りていませんが Object.keys を使うと正常に取れました
最悪 Object.entries は Object.keys の結果に map でキーに対する値を取得して自分で Object.entreis の配列構造を作れば大丈夫そうです
それと 正確には 「最後の一つがなくなる」 という現象ではなく Symbol の数だけ後ろから要素が減るようです
11:42:16.749 const z = {[Symbol()]: 1, [Symbol()]: 2}
z.a = 1
z.b = 1
z.c = 1
Object.entries(z)
11:42:16.763 ▶ (3) [Array(2), Array(2), Array(2)]
11:42:17.569 z
11:42:17.575 ▶ {a: 1, b: 1, c: 1, Symbol(): 1, Symbol(): 2}
11:42:20.560 Object.entries(z)
11:42:20.567 ▶ [Array(2)]
要素数が 3 つなので内部的に 3 つ取り出して そのうち 2 つは Symbol なので捨てて残った 1 つだけが表示される みたいなものでしょうか
実際の環境への影響は
コンソールの実行だけで JavaScript ファイルの実行では問題ないのかと思いましたが<script>
const z = {[Symbol()]: 1, [Symbol()]: 2}
z.a = 1
z.b = 1
z.c = 1
const x = Object.entries(z).length
console.log(z)
const y = Object.entries(z).length
document.write(x === y)
</script>
この HTML のページを devtools が開かれた状態で開くと画面に表示されるのは false です
length が減っています
devtools を開いていなければ console.log での内部的な処理がされないのか true で問題なしでした
devtools があるときだけなので 通常のユーザには影響しません
……が開発する側としてはすごく困ります
修正されてた
っと 記事を書き終えて一応確認のために動かすと 発生しなくなっていましたどっちも Chrome 66 なんだけど? と思ってよく見てみると
発生していたのは 66.0.3359.139
発生していないのは 最後が 170 でした
アップデートしてみると devtools が開いていてもちゃんと動いていました
これまでマイナーアップデートで自分が気づいたバグ修正をされたことがなかったので緊急のセキュリティ修正とかくらいだろうと思ってましたが 今回のは開発者向けとは言えけっこう大きな問題でしたし 緊急の修正にでもなったのでしょうか
すぐに修正されていたのはありがたいことです