SharedArrayBuffer
Baseline
Widely available
*
This feature is well established and works across many devices and browser versions. It’s been available across browsers since 2021年12月.
* Some parts of this feature may have varying levels of support.
SharedArrayBuffer オブジェクトは、一般的な、生のバイナリーデータバッファーを表すために使用されます。ArrayBuffer オブジェクトと似ていますが、こちらは共有メモリー上にビューを生成するために使用されます。SharedArrayBuffer は移譲可能オブジェクトではありません。この点では ArrayBuffer が移譲可能であるのとは異なります。
解説
SharedArrayBuffer オブジェクトを使用して、クラスター内のあるエージェントから別のエージェント (エージェントとは、ウェブページのメインプログラムまたはそのウェブワーカーのひとつ) へ、SharedArrayBuffer オブジェクトを使用してメモリーを共有するために、postMessage と構造化複製を使用します。
構造化複製アルゴリズムは SharedArrayBuffer と、SharedArrayBuffer にマッピングされた型付き配列を受け入れます。どちらの場合も SharedArrayBuffer オブジェクトは受信者に転送されて、受信側のエージェントで新たなプライベートの SharedArrayBuffer オブジェクトになります(ArrayBuffer と同じように)。しかし、2 つの SharedArrayBuffer オブジェクトから参照される共有データブロックは同一のデータブロックであり、あるエージェントによるブロックへの副作用は、結果的に他方のエージェントからも見えます。
const sab = new SharedArrayBuffer(1024);
worker.postMessage(sab);
共有メモリーは、ワーカー内でもメインスレッド内でも同時に生成や更新ができます。システム (CPU、OS、ブラウザー) によっては、変更がすべてのコンテキストに通知されるまでに少々時間がかかります。同期するためには、不可分操作が必要です。
SharedArrayBuffer オブジェクトは、以下のように一部のウェブ API で使用されています。
セキュリティの要件
共有メモリーと高解像度タイマーは、Spectre の対策として 2018 年の初めに事実上無効化されました。 2020 年には、共有メモリーを再び有効にするために、新しい安全なアプローチが標準化されました。
共有メモリーを使用するには、文書が保護されたコンテキスト内にあり、オリジン同士が分離されている必要があります。
Window.crossOriginIsolated と WorkerGlobalScope.crossOriginIsolated のプロパティを使用して、文書のオリジン同士が分離されているかどうかを調べることができます。
const myWorker = new Worker("worker.js");
if (crossOriginIsolated) {
const buffer = new SharedArrayBuffer(16);
myWorker.postMessage(buffer);
} else {
const buffer = new ArrayBuffer(16);
myWorker.postMessage(buffer);
}
オリジン同士が分離されている場合、 postMessage() は SharedArrayBuffer オブジェクトに例外を発生させなくなり、従ってスレッド間での共有メモリーが利用できるようになります。
API の利用可能性
上記のセキュリティ対策の有無により、各種メモリー共有 API の利用可能性は異なります。
Atomicsオブジェクトは常に利用できます。SharedArrayBufferオブジェクトは原則として常に利用できますが、残念ながら、ウェブコンテンツとの互換性のために、上記の 2 つのヘッダーが設定されていない限り、グローバルオブジェクトのコンストラクターは隠されます。この制限は将来的に取り除かれることが期待されています。WebAssembly.Memoryはまだインスタンスを取得するために使用することができます。- 上記の 2 つのヘッダーが設定されていない限り、さまざまな
postMessage()API がSharedArrayBufferオブジェクトに対して例外を発生することになります。これらが設定された場合は、Windowオブジェクトと専用ワーカーのpostMessage()が機能し、メモリーを共有できるようになります。
WebAssembly の共有メモリー
WebAssembly.Memory オブジェクトは、コンストラクターの shared フラグで作成することができます。このフラグを true に設定すると、構築されたメモリーオブジェクトは SharedArrayBuffer と同様に postMessage() を通じてワーカー間で共有でき、メモリーオブジェクトの背後となる buffer は SharedArrayBuffer となります。したがって、ワーカー間で SharedArrayBuffer を共有するための上記の要件は、WebAssembly.Memory.Buffer を共有する場合にも当てはまります。
WebAssembly Threads の提案では、新しい不可分命令の集合も定義されています。 SharedArrayBuffer とそのメソッドが無条件に有効であるように(そしてスレッド間の共有のみが新しいヘッダー上で制限されます)、 WebAssembly の不可分命令も無条件に許可されます。
SharedArrayBuffer の成長
SharedArrayBuffer オブジェクトは SharedArrayBuffer() コンストラクターを呼び出す際に maxByteLength オプションを含めることで成長可能にすることができます。また、SharedArrayBuffer の growable および maxByteLength プロパティを参照すれば、そのサイズが成長可能かどうかを調べることが可能であり、最大サイズは何であるかがわかります。成長可能な SharedArrayBuffer には grow() を呼び出して新しいサイズを割り当てることができます。新しいバイトは 0 に初期化されます。
これらの機能により、SharedArrayBuffer をより効率的に成長させることができます。そうしないと、新しいサイズのバッファーコピーを作成しなければなりません。また、この点において、JavaScript は WebAssembly と同等になります(Wasm のリニアメモリーは WebAssembly.Memory.prototype.grow() でサイズを変更することができます)。
セキュリティ上の理由から、SharedArrayBuffer はサイズを縮小することはできませんが、大きくすることはできます。
コンストラクター
-
新しい
SharedArrayBufferオブジェクトを生成します。
静的プロパティ
-
SharedArrayBufferのメソッドから返値を構築する際に使用されるコンストラクターを返します。
インスタンスプロパティ
これらのプロパティは SharedArrayBuffer.prototype で定義されており、すべての SharedArrayBuffer インスタンスで共有されます。
-
配列のサイズ(バイト単位)。これは配列の構築時に設定され、
SharedArrayBufferが成長可能である場合にのみSharedArrayBuffer.prototype.grow()メソッドを使用して変更することができます。 -
インスタンスオブジェクトを作成したコンストラクター関数です。SharedArrayBuffer`インスタンスの場合、初期値は
SharedArrayBufferコンストラクターです。 -
読み取り専用です。
SharedArrayBufferが成長可能な場合はtrueを、そうでない場合はfalseを返します。 -
読み取り専用で、
SharedArrayBufferが成長できる最大長をバイト数で指定します。これは配列が構築される際に設定され、変更することはできません。 -
[Symbol.toStringTag]プロパティの初期値は文字列"SharedArrayBuffer"です。このプロパティはObject.prototype.toString()で使用されます。
インスタンスメソッド
-
SharedArrayBufferを指定したサイズ(バイト単位)まで成長させます。 -
新しい
SharedArrayBufferを作成し、その中身をこのSharedArrayBufferのbeginの位置からendの位置の一つ手前までのバイトをコピーして返します。beginまたはendが負の数の場合は、配列の先頭からではなく末尾からの位置で参照します。
例
>新しい SharedArrayBuffer の生成
const sab = new SharedArrayBuffer(1024);
SharedArrayBuffer の分割
sab.slice(); // SharedArrayBuffer { byteLength: 1024 }
sab.slice(2); // SharedArrayBuffer { byteLength: 1022 }
sab.slice(-2); // SharedArrayBuffer { byteLength: 2 }
sab.slice(0, 1); // SharedArrayBuffer { byteLength: 1 }
WebGL バッファー内での使用
const canvas = document.querySelector("canvas");
const gl = canvas.getContext("webgl");
const buffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
gl.bufferData(gl.ARRAY_BUFFER, sab, gl.STATIC_DRAW);
仕様書
| Specification |
|---|
| ECMAScript® 2026 Language Specification> # sec-sharedarraybuffer-objects> |
ブラウザーの互換性
Loading…
関連情報
AtomicsArrayBuffer- JavaScript 型付き配列
- ウェブワーカー
- 共有メモリー – 簡潔なチュートリアル (TC39 ecmascript-sharedmem の提案)
- A Taste of JavaScript's New Parallel Primitives (hacks.mozilla.org, 2016)
- COOP and COEP explained (the Chrome team, 2020)
Cross-Origin-Opener-PolicyCross-Origin-Embedder-PolicyCross-Origin-Resource-PolicyWindow.crossOriginIsolatedおよびWorkerGlobalScope.crossOriginIsolated- SharedArrayBuffer updates in Android Chrome 88 and Desktop Chrome 92 (developer.chrome.com, 2021)