ENCA 11日目: SharedArrayBuffer のオプショナル化
SharedArrayBuffer
のオプショナル化
ES2017 に満を持して入った SharedArrayBuffer
でしたが、その後 CPU の投機的実行を悪用した Spectre 脆弱性が発見されてしまい、攻撃を緩和するために高精度に時間が測定できる performance.now()
の精度が落とされ、SharedArrayBuffer
が無効化されてしまうこととなりました。
詳しくは jxck さんのブログ記事を参考にしてください。
さて言語仕様側でもこの対応が必要となり、グローバル変数から SharedArrayBuffer
を取り除いて良いこととする変更が承認されました。
SharedArrayBuffer
を有効化する
クロスオリジン分離で ブラウザで SharedArrayBuffer
を有効化するには HTTPS で配信された安全なコンテキストであることと、Cross-Origin-Opener-Policy
(COOP) と Cross-Origin-Embedder-Policy
(COEP) フィールドを使ってクロスオリジン分離する必要があります。
なお余談ですが、クロスオリジン分離になっていなくても SharedArrayBuffer
コンストラクタ自体をグローバル変数から取り除く必要はなく、postMessage
などでやり取りする箇所でせき止めれば十分です。互換性の観点からグローバル変数から取り除いたままになっていますが、実はクロスオリジン分離でなくても WebAssembly.Memory
を使ってコンストラクタを取得できます(役には立ちませんが)。
const memory = new WebAssembly.Memory({ shared: true, initial: 0, maximum: 0 });
const SharedArrayBuffer = memory.buffer.constructor;
これについては HTML Standard にも書かれています。
If agent's agent cluster's cross-origin isolation mode is
"none"
, then:
- Let global be realm's global object.
- Let status be !
global.[[Delete]]("SharedArrayBuffer")
.- Assert: status is
true
.Note: This is done for compatibility with web content and there is some hope that this can be removed in the future. Web developers can still get at the constructor through
new WebAssembly.Memory({ shared:true, initial:0, maximum:0 }).buffer.constructor
.
Discussion