Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SharedArrayBuffer の記事を更新 #10881

Merged
merged 5 commits into from Jan 8, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
@@ -0,0 +1,80 @@
---
title: get SharedArrayBuffer[@@species]
slug: Web/JavaScript/Reference/Global_Objects/SharedArrayBuffer/@@species
l10n:
sourceCommit: 0f248adcab759bdad247a5dbfb7da12dc32bce59
---

{{JSRef}}

**`SharedArrayBuffer[@@species]`** アクセサープロパティは、`SharedArrayBuffer` の各メソッドから返される値を作成するために使用されるコンストラクター(種)を返します。

> **警告:** `@@species` が存在すると、任意のコードの実行が可能になり、セキュリティ上の脆弱性が生じる可能性があります。また、ある種の最適化も非常に難しくなります。エンジンの実装者たちは、[この機能を削除するかどうか調査しています](https://github.com/tc39/proposal-rm-builtin-subclassing)。可能であれば、この機能に頼ることは避けてください。

## 構文

```js-nolint
SharedArrayBuffer[Symbol.species]
```

### 返値

`get @@species` が呼び出されたコンストラクター (`this`) の値です。この返値は、新しい配列バッファーを作成するための配列バッファーのメソッドから返される値を構成するために使用されます。

## 解説

`@@species` アクセサープロパティは `SharedArrayBuffer` オブジェクトの既定のコンストラクターを返します。サブクラスのコンストラクターはこれを上書きして、コンストラクターの割り当てを変更することができます。既定の実装では、基本的に次のようになります。

```js
// 説明のための仮想的な基礎実装
class SharedArrayBuffer {
static get [Symbol.species]() {
return this;
}
}
```

この多態的な実装のため、派生したサブクラスの `@@species` も既定でコンストラクター自身を返すことになります。

```js
class SubArrayBuffer extends SharedArrayBuffer {}
SubArrayBuffer[Symbol.species] === SharedArrayBuffer; // true
```

既存の配列を変更せず、新しい配列バッファーのインスタンスを返す配列バッファーのメソッド(例えば [`slice()`](/ja/docs/Web/JavaScript/Reference/Global_Objects/SharedArrayBuffer/slice))を呼び出すと、その配列の `constructor[@@species]` にアクセスすることになります。返されたコンストラクターは配列バッファーメソッドの返値を構築するために使用されます。

## 例

### 通常のオブジェクトにおける種

`@@species` プロパティは、既定のコンストラクター関数、つまり `SharedArrayBuffer` であれば `SharedArrayBuffer` コンストラクターが返されます。

```js
SharedArrayBuffer[Symbol.species]; // function SharedArrayBuffer()
```

### 派生オブジェクトにおける種

独自の `SharedArrayBuffer` サブクラスのインスタンス、例えば `MySharedArrayBuffer` では、その `MySharedArrayBuffer` の種は `MySharedArrayBuffer` コンストラクターになります。しかし、派生クラスのメソッドで親の `SharedArrayBuffer` オブジェクトを返すために、これを上書きしたいと思うかもしれません。

```js
class MySharedArrayBuffer extends SharedArrayBuffer {
// 種を MySharedArrayBuffer から親である SharedArrayBuffer コンストラクターで上書きする。
static get [Symbol.species]() {
return SharedArrayBuffer;
}
}
```

## 仕様書

{{Specifications}}

## ブラウザーの互換性

{{Compat}}

## 関連情報

- {{jsxref("SharedArrayBuffer")}}
- {{jsxref("Symbol.species")}}
@@ -1,11 +1,13 @@
---
title: SharedArrayBuffer.prototype.byteLength
slug: Web/JavaScript/Reference/Global_Objects/SharedArrayBuffer/byteLength
l10n:
sourceCommit: c4e3558ee1045803df4a685f11f94dca273cd5fe
---

{{JSRef}}

**`byteLength`** アクセサープロパティは 、{{jsxref("SharedArrayBuffer")}} の長さをバイト単位で表します。
**`byteLength`** アクセサープロパティは、{{jsxref("SharedArrayBuffer")}} の長さをバイト単位で表します。

{{EmbedInteractiveExample("pages/js/sharedarraybuffer-bytelength.html","shorter")}}

Expand All @@ -18,7 +20,7 @@ slug: Web/JavaScript/Reference/Global_Objects/SharedArrayBuffer/byteLength
### byteLength の使用

```js
var sab = new SharedArrayBuffer(1024);
const sab = new SharedArrayBuffer(1024);
sab.byteLength; // 1024
```

Expand Down
@@ -1,38 +1,36 @@
---
title: SharedArrayBuffer
slug: Web/JavaScript/Reference/Global_Objects/SharedArrayBuffer
l10n:
sourceCommit: 1c7cd798570353939e221d4282af014ea04726ac
---

{{JSRef}}

**`SharedArrayBuffer`** オブジェクトは、固定長の生バイナリデータバッファーのジェネリックを表すために使用されます。{{jsxref("ArrayBuffer")}} オブジェクトと似ていますが、こちらは共有メモリー上にビューを生成するために使用されます。 `ArrayBuffer` と異なり、`SharedArrayBuffer` は分離できません
**`SharedArrayBuffer`** オブジェクトは、固定長の生バイナリデータバッファーのジェネリックを表すために使用されます。{{jsxref("ArrayBuffer")}} オブジェクトと似ていますが、こちらは共有メモリー上にビューを生成するために使用されます。 `ArrayBuffer` が[移譲可能オブジェクト](/ja/docs/Web/API/Web_Workers_API/Transferable_objects)であるのとは異なり、`SharedArrayBuffer` は移譲可能ではありません

## 解説

### メモリーの割り当てと共有

クラスター内のあるエージェントから別のエージェント (エージェントとは、ウェブページのメインプログラムまたはそのウェブワーカーのひとつ) へ、{{jsxref("SharedArrayBuffer")}} オブジェクトを使用してメモリーを共有するために、[`postMessage`](/ja/docs/Web/API/Worker/postMessage) と[構造化複製](/ja/docs/Web/API/Web_Workers_API/Structured_clone_algorithm)を使用します。
{{jsxref("SharedArrayBuffer")}} オブジェクトを使用して、クラスター内のあるエージェントから別のエージェント (エージェントとは、ウェブページのメインプログラムまたはそのウェブワーカーのひとつ) へ、{{jsxref("SharedArrayBuffer")}} オブジェクトを使用してメモリーを共有するために、[`postMessage`](/ja/docs/Web/API/Worker/postMessage) と[構造化複製](/ja/docs/Web/API/Web_Workers_API/Structured_clone_algorithm)を使用します。

構造化複製アルゴリズムは `SharedArrayBuffer` と、`SharedArrayBuffer` にマッピングされた型付き配列を受け入れます。どちらの場合も `SharedArrayBuffer` オブジェクトは受信者に転送されて、受信側のエージェントで新たなプライベートの SharedArrayBuffer オブジェクトになります ({{jsxref("ArrayBuffer")}} と同じように)。しかし、2 つの `SharedArrayBuffer` オブジェクトから参照される共有データブロックは同一のデータブロックであり、あるエージェントによるブロックへの副作用は、結果的に他方のエージェントからも見えます。

```js
var sab = new SharedArrayBuffer(1024);
const sab = new SharedArrayBuffer(1024);
worker.postMessage(sab);
```

### Atomic 操作による共有メモリーを更新や同期

共有メモリーは、ワーカー内でもメインスレッド内でも同時に生成や更新ができます。システム (CPU、 OS、ブラウザー) によっては、変更がすべてのコンテキストに通知されるまでに少々時間がかかります。同期するためには、{{jsxref("Atomics", "不可分", "", 1)}}操作が必要です。

<h3 id="APIs_which_use_SharedArrayBuffer_objects">SharedArrayBuffer オブジェクトを使用する API</h3>
`SharedArrayBuffer` オブジェクトは、以下のように一部のウェブ API で使用されています。

- [`WebGLRenderingContext.bufferData()`](/ja/docs/Web/API/WebGLRenderingContext/bufferData)
- [`WebGLRenderingContext.bufferSubData()`](/ja/docs/Web/API/WebGLRenderingContext/bufferSubData)
- [`WebGL2RenderingContext.getBufferSubData()`](/ja/docs/Web/API/WebGL2RenderingContext/getBufferSubData)

### セキュリティの要件

共有メモリーと高解像度タイマーは、 [Spectre](https://ja.wikipedia.org/wiki/Spectre) の対策として 2018 年の初めに事実上[無効化されました](https://blog.mozilla.org/security/2018/01/03/mitigations-landing-new-class-timing-attack/)。 2020 年には、共有メモリーを再び有効にするために、新しい安全なアプローチが標準化されました。いくつかのセキュリティ対策を施すことで、 [`postMessage()`](/ja/docs/Web/API/Window/postMessage) が `SharedArrayBuffer` オブジェクトを渡すことができなくなり、スレッド間の共有メモリーが利用できるようになります。
共有メモリーと高解像度タイマーは、 [Spectre](https://ja.wikipedia.org/wiki/Spectre) の対策として 2018 年の初めに事実上[無効化されました](https://blog.mozilla.org/security/2018/01/03/mitigations-landing-new-class-timing-attack/)。 2020 年には、共有メモリーを再び有効にするために、新しい安全なアプローチが標準化されました。

基本的な要件として、文書が[安全なコンテキスト](/ja/docs/Web/Security/Secure_Contexts)にある必要があります。

Expand All @@ -41,12 +39,12 @@ worker.postMessage(sab);
- [`Cross-Origin-Opener-Policy`](/ja/docs/Web/HTTP/Headers/Cross-Origin-Opener-Policy) で `same-origin` の値を指定すること (オリジンを攻撃者から守るため)
- [`Cross-Origin-Embedder-Policy`](/ja/docs/Web/HTTP/Headers/Cross-Origin-Embedder-Policy) で `require-corp` の値を指定すること (被害者を自分のオリジンから守るため)

```plain
```http
Cross-Origin-Opener-Policy: same-origin
Cross-Origin-Embedder-Policy: require-corp
```

オリジン間の分離が成功したかどうかは、ウィンドウとワーカーのコンテキストで利用できる [`crossOriginIsolated`](/ja/docs/Web/API/WindowOrWorkerGlobalScope/crossOriginIsolated) プロパティを使って確認することができます。
オリジン間の分離が成功したかどうかは、ウィンドウとワーカーのコンテキストで利用できる [`crossOriginIsolated`](/ja/docs/Web/API/crossOriginIsolated) プロパティを使って確認することができます。

```js
if (crossOriginIsolated) {
Expand All @@ -56,21 +54,25 @@ if (crossOriginIsolated) {
}
```

また、ブラウザー (Firefox 79など) で展開され始めている[共有メモリーの計画的な変更](/ja/docs/Web/JavaScript/Reference/Global_Objects/SharedArrayBuffer/Planned_changes)も参照してください
これらの 2 つのヘッダーが設定されていた場合、 `postMessage()` は `SharedArrayBuffer` オブジェクトに例外を発生させなくなり、従ってスレッド間での共有メモリーが利用できるようになります

### SharedArrayBuffer の生成には new 演算子が必要
入れ子の文書と専用ワーカーは同様に、 [`Cross-Origin-Embedder-Policy`](/ja/docs/Web/HTTP/Headers/Cross-Origin-Embedder-Policy) ヘッダーを同じ値で設定する必要があります。同一オリジンの入れ子の文書とサブリソースについては、これ以上の変更は必要ありません。同一サイト(ただし別オリジン)の入れ子の文書とサブリソースは、 [`Cross-Origin-Resource-Policy`](/ja/docs/Web/HTTP/Headers/Cross-Origin-Resource-Policy) ヘッダーを `same-site` という値で設定する必要があります。そして、同様に別オリジン(かつ別サイト)のものは、 `cross-origin` を値として同じヘッダーを設定する必要があります。 [`Cross-Origin-Resource-Policy`](/ja/docs/Web/HTTP/Headers/Cross-Origin-Resource-Policy) ヘッダーを `same-origin` 以外の値に設定すると、[Spectre](<https://en.wikipedia.org/wiki/Spectre_(security_vulnerability)>) などの潜在的な攻撃にリソースがさらされることになることに注意してください。

`SharedArrayBuffer` コンストラクターは、{{jsxref("Operators/new", "new")}} 演算子で呼び出す必要があります。`new` 演算子なしで関数として `SharedArrayBuffer` コンストラクターを呼び出すと、{{jsxref("TypeError")}} が発生します
[`Cross-Origin-Opener-Policy`](/ja/docs/Web/HTTP/Headers/Cross-Origin-Opener-Policy) ヘッダーはポップアップへの参照を保持するための能力を制限していることに注意してください。2 つの最上位のウィンドウコンテキスト間の直接アクセスは、基本的に、同一オリジンであり、同じ 2 つの値を持つヘッダーを運んでいる場合にのみ動作するようになっています

```js example-bad
var sab = SharedArrayBuffer(1024);
// TypeError: calling a builtin SharedArrayBuffer constructor
// new がない形は禁止されています
```
### API の利用可能性

```js example-good
var sab = new SharedArrayBuffer(1024);
```
上記のセキュリティ対策の有無により、各種メモリー共有 API の利用可能性は異なります。

- `Atomics` オブジェクトは常に利用できます。
- `SharedArrayBuffer` オブジェクトは原則として常に利用できますが、残念ながら、ウェブコンテンツとの互換性のために、上記の 2 つのヘッダーが設定されていない限り、グローバルオブジェクトのコンストラクターは隠されます。この制限は将来的に取り除かれることが期待されています。[`WebAssembly.Memory`](/ja/docs/WebAssembly/JavaScript_interface/Memory) はまだインスタンスを取得するために使用することができます。
- 上記の 2 つのヘッダーが設定されていない限り、さまざまな `postMessage()` API が `SharedArrayBuffer` オブジェクトに対して例外を発生することになります。これらが設定された場合は、`Window` オブジェクトと専用ワーカーの `postMessage()` が機能し、メモリーを共有できるようになります。

### WebAssembly の共有メモリー

[`WebAssembly.Memory`](/ja/docs/WebAssembly/JavaScript_interface/Memory) オブジェクトは、コンストラクターの [`shared`](/ja/docs/WebAssembly/JavaScript_interface/Memory/Memory#shared) フラグで作成することができます。このフラグを `true` に設定すると、構築されたメモリーオブジェクトは `SharedArrayBuffer` と同様に `postMessage()` を通じてワーカー間で共有でき、メモリーオブジェクトの背後となる [`buffer`](/ja/docs/WebAssembly/JavaScript_interface/Memory/buffer) は `SharedArrayBuffer` となります。したがって、ワーカー間で `SharedArrayBuffer` を共有するための上記の要件は、`WebAssembly.Memory.Buffer` を共有する場合にも当てはまります。

WebAssembly Threads の提案では、新しい[不可分](https://github.com/WebAssembly/threads/blob/master/proposals/threads/Overview.md#atomic-memory-accesses)命令の集合も定義されています。`SharedArrayBuffer` とそのメソッドが無条件に有効であるように(そしてスレッド間の共有のみが新しいヘッダー上で制限されます)、WebAssembly の不可分命令も無条件に許可されます。

## コンストラクター

Expand All @@ -79,36 +81,38 @@ var sab = new SharedArrayBuffer(1024);

## インスタンスプロパティ

- `SharedArrayBuffer.prototype[@@toStringTag]`
- : [`@@toStringTag`](/ja/docs/Web/JavaScript/Reference/Global_Objects/Symbol/toStringTag) プロパティの初期値は文字列 `"SharedArrayBuffer"` です。このプロパティは {{jsxref("Object.prototype.toString()")}} で使用されます。
- {{jsxref("SharedArrayBuffer.prototype.byteLength")}}
- : 配列の大きさをバイト数で表します。これは配列が構築されたときに確立され、変更することはできません。**読み取り専用です。**

## インスタンスメソッド

- {{jsxref("SharedArrayBuffer.slice", "SharedArrayBuffer.prototype.slice(begin, end)")}}
- {{jsxref("SharedArrayBuffer.prototype.slice()")}}
- : 新しい `SharedArrayBuffer` を作成し、その中身をこの `SharedArrayBuffer` の `begin` の位置から `end` の位置の一つ手前までのバイトをコピーして返します。 `begin` または `end` が負の数の場合は、配列の先頭からではなく末尾からの位置で参照します。

## 例

### 新しい SharedArrayBuffer の生成

```js
var sab = new SharedArrayBuffer(1024);
const sab = new SharedArrayBuffer(1024);
```

### SharedArrayBuffer の分割

```js
sab.slice(); // SharedArrayBuffer { byteLength: 1024 }
sab.slice(2); // SharedArrayBuffer { byteLength: 1022 }
sab.slice(-2); // SharedArrayBuffer { byteLength: 2 }
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 バッファー内での使用

```js
const canvas = document.querySelector('canvas');
const gl = canvas.getContext('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);
Expand All @@ -127,7 +131,13 @@ gl.bufferData(gl.ARRAY_BUFFER, sab, gl.STATIC_DRAW);
- {{jsxref("Atomics")}}
- {{jsxref("ArrayBuffer")}}
- [JavaScript 型付き配列](/ja/docs/Web/JavaScript/Typed_arrays)
- [Web Worker](/ja/docs/Web/API/Web_Workers_API)
- [ウェブワーカー](/ja/docs/Web/API/Web_Workers_API)
- [parlib-simple](https://github.com/lars-t-hansen/parlib-simple) – 同期と作業分配抽象化を提供するシンプルなライブラリー
- [共有メモリー – 簡潔なチュートリアル](https://github.com/tc39/ecmascript_sharedmem/blob/master/TUTORIAL.md)
- [共有メモリー – 簡潔なチュートリアル](https://github.com/tc39/proposal-ecmascript-sharedmem/blob/main/TUTORIAL.md)
- [JavaScript の並列処理機能を味見してみる](https://dev.mozilla.jp/2016/05/a-taste-of-javascripts-new-parallel-primitives/)
- [COOP and COEP explained](https://docs.google.com/document/d/1zDlfvfTJ_9e8Jdc8ehuV4zMEu9ySMCiTGMS9y0GU92k/edit).
- `Cross-Origin-Opener-Policy`: [whatwg/html issue #3740](https://github.com/whatwg/html/issues/3740), [draft specification](https://gist.github.com/annevk/6f2dd8c79c77123f39797f6bdac43f3e).
- `Cross-Origin-Embedder-Policy`: [whatwg/html issue #4175](https://github.com/whatwg/html/issues/4175), [draft specification](https://mikewest.github.io/corpp/).
- `Cross-Origin-Resource-Policy`: [Fetch で標準化され](https://fetch.spec.whatwg.org/#cross-origin-resource-policy-header)、新しい `cross-origin` 値が `Cross-Origin-Embedder-Policy` の効果の一部になります。
- `postMessage()` の変更と [`self.crossOriginIsolated`](/ja/docs/Web/API/crossOriginIsolated): [whatwg/html issue #4732](https://github.com/whatwg/html/issues/4732), [whatwg/html issue #4872](https://github.com/whatwg/html/issues/4872), [draft specification](https://github.com/whatwg/html/pull/4734).
- [SharedArrayBuffer updates in Android Chrome 88 and Desktop Chrome 92](https://developer.chrome.com/blog/enabling-shared-array-buffer/)