WHATWG

HTML — web worker

Living Standard —

この日本語訳は非公式な文書です…(翻訳更新:

このページは、WHATWGによる HTML 仕様の § Web Workers を日本語に翻訳したものです。 (初公表日:

索引など

10. web worker

10.1. 序論

10.1.1. 視野

この節は規範的ではない。This section is non-normative.

この仕様は、 他の UI スクリプトから独立に,バックグラウンドでスクリプトを走らすための API を定義する。 This specification defines an API for running scripts in the background independently of any user interface scripts.

それは、 次を許容する :クリックその他 利用者によるやりとりに応答するスクリプトから中断されることなく, 長期に渡りスクリプトを走らせる — すなわち、 ページを即応可能に保ちながら,長いタスクを実行する。 This allows for long-running scripts that are not interrupted by scripts that respond to clicks or other user interactions, and allows long tasks to be executed without yielding to keep the page responsive.

worker (これらのバックグラウンドスクリプトの ここでの名称)は、 比較的 重いので,多数の同時利用は意図されていない。 例えば、 画像内に幾千万ある画素ごとに異なる worker を立ち上げるのは不適切である。 下の例に worker の適切な利用を示す: Workers (as these background scripts are called herein) are relatively heavy-weight, and are not intended to be used in large numbers. For example, it would be inappropriate to launch one worker for each pixel of a four megapixel image. The examples below show some appropriate uses of workers.

一般に,worker は長時間居残り続けるので、 開始時の処理能コスト, およびインスタンスごとのメモリーコストは,高くつくものと予期されている。 Generally, workers are expected to be long-lived, have a high start-up performance cost, and a high per-instance memory cost.

10.1.2. 例

この節は規範的ではない。This section is non-normative.

worker には様々な利用がある。 以下の各下位節に,その利用を示す。 There are a variety of uses that workers can be put to. The following subsections show various examples of this use.

10.1.2.1. バックグラウンドで数値計算し続ける worker

この節は規範的ではない。This section is non-normative.

worker の最も単純な利用は、 UI を中断せずに計算量の大きな仕事を遂行するものである。 The simplest use of workers is for performing a computationally expensive task without interrupting the user interface.

この例では、 メイン文書が worker を生み出して, (素朴な)素数の計算を行い, 見つかった最新の素数を漸進的に表示し続ける。 In this example, the main document spawns a worker to (naïvely) compute prime numbers, and progressively displays the most recently found prime number.

メインページは次で与えられる: The main page is as follows:

<!DOCTYPE HTML>
<html>
 <head>
  <meta charset="utf-8">
  <title>worker 例: 単コアによる計算</title>
 </head>
 <body>
  <p>これまでに見つかった最大の素数は:<output id="result"></output></p>

<script>
   var worker = new Worker('worker.js');
   worker.onmessage = function (event) {
     document.getElementById('result').textContent = event.data;
   };
</script>

 </body>
</html>

new Worker() 構築子の call により,worker が作成され、[ その worker を表現し, その worker と通信する, Worker オブジェクト ]が返される。 オブジェクトの onmessage イベントハンドラには、 worker からメッセージを受信するコードを入れられる。 The Worker() constructor call creates a worker and returns a Worker object representing that worker, which is used to communicate with the worker. That object's onmessage event handler allows the code to receive messages from the worker.

worker 自身は次で与えられる: The worker itself is as follows:

var n = 1;
search: while (true) {
  n += 1;
  for (var i = 2; i <= Math.sqrt(n); i += 1)
    if (n % i == 0)
     continue search;
  /* 
素数発見!
found a prime! */
  postMessage(n);
}

【 いきなり postMessage() が大域関数として登場している所からも推察されるように、 ちょうど通常時におけるスクリプトの Window オブジェクトにあたる, worker 用のスクリプト実行環境を与える大域オブジェクト (§ 大域スコープ)が, (worker を生み出した側の実行環境とは別に) 存在している、 と考えれば,この仕様の残りの部分も理解し易い。 】

このコードは、 単純な,最適化されていない,素数の探索ルーチンである。 postMessage() が、 見つかった素数をメッセージにしてページに返信するメソッドである。 The bulk of this code is simply an unoptimized search for a prime number. The postMessage() method is used to send a message back to the page when a prime is found.

この例をオンラインで見る View this example online.

10.1.2.2. JavaScript モジュールを worker として利用する

この節は規範的ではない。This section is non-normative.

これまでの どの例も古典スクリプトを走らす worker を示してきたが、 worker は,モジュールスクリプトを利用してインスタンス化することもできる — これには、 通例的に,次に挙げる便益がある:

  • JavaScript import 文を利用して他のモジュールを import する能
  • 既定で strict モードになる
  • worker の大域スコープを汚さない,トップレベルの宣言
All of our examples so far show workers that run classic scripts. Workers can instead be instantiated using module scripts, which have the usual benefits: the ability to use the JavaScript import statement to import other modules; strict mode by default; and top-level declarations not polluting the worker's global scope.

import 文が可用になったことに伴い、 importScripts() メソッドは,モジュール worker の内側では自動的に失敗することになる。 As the import statement is available, the importScripts() method will automatically fail inside module workers.

この例では、 メイン文書が[ メインスレッドの外で画像操作を行う worker ]を利用する。 それは、 別のモジュールから利用されるフィルタを import する。 In this example, the main document uses a worker to do off-main-thread image manipulation. It imports the filters used from another module.

メインページは: The main page is as follows:

<!DOCTYPE html>
<meta charset="utf-8">
<title>worker 例: 画像を復号する</title>

<p>
  <label>
    復号する画像の URL を入れてください
    <input type="url" id="image-url" list="image-list">
    <datalist id="image-list">
      <option value="https://html.spec.whatwg.org/images/drawImage.png">
      <option value="https://html.spec.whatwg.org/images/robots.jpeg">
      <option value="https://html.spec.whatwg.org/images/arcTo2.png">
    </datalist>
  </label>
</p>

<p>
  <label>
    適用するフィルタを選んでください
    <select id="filter">
      <option value="none">none</option>
      <option value="grayscale">grayscale</option>
      <option value="brighten">brighten by 20%</option>
    </select>
  </label>
</p>

<div id="output"></div>

<script type="module">
  const worker = new Worker("worker.js", { type: "module" });
  worker.onmessage = receiveFromWorker;

  const url = document.querySelector("#image-url");
  const filter = document.querySelector("#filter");
  const output = document.querySelector("#output");

  url.oninput = updateImage;
  filter.oninput = sendToWorker;

  let imageData, context;

  function updateImage() {
    const img = new Image();
    img.src = url.value;

    img.onload = () => {

      const canvas = document.createElement("canvas");
      canvas.width = img.width;
      canvas.height = img.height;

      context = canvas.getContext("2d");
      context.drawImage(img, 0, 0);
      imageData = context.getImageData(0, 0, canvas.width, canvas.height);

      sendToWorker();
      output.replaceChildren(canvas);
    };
  }

  function sendToWorker() {
    worker.postMessage({ imageData, filter: filter.value });
  }

  function receiveFromWorker(e) {
    context.putImageData(e.data, 0, 0);
  }
</script>

worker ファイルは: The worker file is then:

import * as filters from "./filters.js";

self.onmessage = e => {
  const { imageData, filter } = e.data;
  filters[filter](imageData);
  self.postMessage(imageData, [imageData.data.buffer]);
};

これは、 次のファイル filters.js を import する: Which imports the file filters.js:

export function none() {}

export function grayscale({ data: d }) {
  for (let i = 0; i < d.length; i += 4) {
    const [r, g, b] = [d[i], d[i + 1], d[i + 2]];
    /* 
RGB に対する CIE 輝度
— 人の目は 赤, 青 に鈍感なので,それらを減衰する
CIE luminance for the RGB
— The human eye is bad at seeing red and blue, so we de-emphasize them. */
    d[i] = d[i + 1] = d[i + 2] = 0.2126 * r + 0.7152 * g + 0.0722 * b;
  }
};

export function brighten({ data: d }) {
  for (let i = 0; i < d.length; ++i) {
    d[i] *= 1.2;
  }
};

この例をオンラインで見る View this example online.

10.1.2.3. 共用 worker 序論

この節は規範的ではない。This section is non-normative.

この節では、 Hello World の例を利用して,共用 worker を導入する。 共用 worker においては、 各 worker が複数の接続を有し得るので,少し異なる API が利用される。 This section introduces shared workers using a Hello World example. Shared workers use slightly different APIs, since each worker can have multiple connections.

この最初の例では、[ ページから worker に どう接続するか ]および[ 接続時に worker がページに向けてメッセージを どう返信するか ]を示す。 受信されたメッセージは、 ログに表示される。 This first example shows how you connect to a worker and how a worker can send a message back to the page when it connects to it. Received messages are displayed in a log.

HTML ページをここに示す: Here is the HTML page:

<!DOCTYPE HTML>
<meta charset="utf-8">
<title>共用 worker : デモ 1</title>
<pre id="log">Log:</pre>

<script>
  var worker = new SharedWorker('test.js');
  var log = document.getElementById('log');
  worker.port.onmessage = function(e) { /* 
worker.onmessage ではないことに注意
note: not worker.onmessage! */
    log.textContent += '\n' + e.data;
  }
</script>

JavaScript worker は次になる: Here is the JavaScript worker:

onconnect = function(e) {
  var port = e.ports[0];
  port.postMessage('Hello World!');
}

onconnect の名が示唆するように、 接続が確立され次第,worker の大域スコープに属する onconnect() が呼び出される。 】

この例をオンラインで見る View this example online.


次の例は、 2 つの変更により,最初のものを拡張する: まず, メッセージはイベントハンドラ IDL 属性の代わりに addEventListener() を利用して受信される。 次に,メッセージは worker に向けて送信され, それに対し worker が別のメッセージを返信するようにしている。 受信されたメッセージは再びログに表示される。 This second example extends the first one by changing two things: first, messages are received using addEventListener() instead of an event handler IDL attribute, and second, a message is sent to the worker, causing the worker to send another message in return. Received messages are again displayed in a log.

HTML ページは: Here is the HTML page:

<!DOCTYPE HTML>
<meta charset="utf-8">
<title>共用 worker : デモ 2</title>
<pre id="log">Log:</pre>

<script>
  var worker = new SharedWorker('test.js');
  var log = document.getElementById('log');
  worker.port.addEventListener('message', function(e) {
    log.textContent += '\n' + e.data;
  }, false);
  worker.port.start(); /* 
注記: addEventListener() を利用した場合はこれが必要になる
note: need this when using addEventListener */
  worker.port.postMessage('ping');
</script>

JavaScript worker は: Here is the JavaScript worker:

onconnect = function(e) {
  var port = e.ports[0];
  port.postMessage('Hello World!');
  port.onmessage = function(e) {
    port.postMessage('pong'); /* 
e.ports[0].postMessage ではないことに注意
not e.ports[0].postMessage! */
    /* 
e.target.postMessage('pong'); でもいける
e.target.postMessage('pong'); would work also */
  }
}

この例をオンラインで見る View this example online.


最後の例は、 2 つのページから同じ worker に接続させる方法を示す。 この例では, 2 番目のページは 単に最初のページの iframe に入れられているが、 同じ原理は,[ 別々なトップレベル辿り可能に属する まったく別々なページ ]であっても通用する。 Finally, the example is extended to show how two pages can connect to the same worker; in this case, the second page is merely in an iframe on the first page, but the same principle would apply to an entirely separate page in a separate top-level traversable.

外縁 HTML ページ: Here is the outer HTML page:

<!DOCTYPE HTML>
<meta charset="utf-8">
<title>共用 worker : デモ 3</title>
<pre id="log">Log:</pre>

<script>
  var worker = new SharedWorker('test.js');
  var log = document.getElementById('log');
  worker.port.addEventListener('message', function(e) {
    log.textContent += '\n' + e.data;
  }, false);
  worker.port.start();
  worker.port.postMessage('ping');
</script>

<iframe src="inner.html"></iframe>

内縁 HTML ページ: Here is the inner HTML page:

<!DOCTYPE HTML>
<meta charset="utf-8">
<title>共用 worker : デモ 3 inner frame</title>
<pre id=log>Inner log:</pre>

<script>
  var worker = new SharedWorker('test.js');
  var log = document.getElementById('log');
  worker.port.onmessage = function(e) {
   log.textContent += '\n' + e.data;
  }
</script>

JavaScript worker は: Here is the JavaScript worker:

var count = 0;
onconnect = function(e) {
  count += 1;
  var port = e.ports[0];
  port.postMessage('Hello World! You are connection #' + count);
  port.onmessage = function(e) {
    port.postMessage('pong');
  }
}

この例をオンラインで見る View this example online.

10.1.2.4. 共用 worker の利用による状態の共有

この節は規範的ではない。This section is non-normative.

次の例では、 同じマップを表示する複数の window (ビューア)を開けるようになっている。 すべての window が同じマップ情報を共有し、 単独の worker が すべてのビューアを協調する。 各ビューアの中では,他と独立にマップ内を動き回れ、 いずれかのビューアにてマップ内に何らかのデータが置かれたときは, すべてのビューアが更新される。 In this example, multiple windows (viewers) can be opened that are all viewing the same map. All the windows share the same map information, with a single worker coordinating all the viewers. Each viewer can move around independently, but if they set any data on the map, all the viewers are updated.

メインページは、 興味を引くものではなく, ビューアを開く仕方を供するものでしかない: The main page isn't interesting, it merely provides a way to open the viewers:

<!DOCTYPE HTML>
<html>
 <head>
  <meta charset="utf-8">
  <title>worker 例: Multiviewer</title>

<script>
   function openViewer() {
     window.open('viewer.html');
   }
</script>

 </head>
 <body>
  <p><button type=button onclick="openViewer()">新たなビューアを開く</button></p>
  <p>各ビューアは新たな window を開きます。好きなだけ,いくつでもビューアを開けます。それらはすべて同じデータを表示します。</p>
 </body>
</html>

より深く関わるのは、 ビューアである: The viewer is more involved:

<!DOCTYPE HTML>
<html>
 <head>
  <meta charset="utf-8">
  <title>worker 例: Multiviewer ビューア</title>

<script>
   var worker = new SharedWorker('worker.js', 'core');

   /* 
環境設定
CONFIGURATION */
   function configure(event) {
     if (event.data.substr(0, 4) != 'cfg ') return;
     var name = event.data.substr(4).split(' ', 1)[0];
     /* 
名前が name であることを示すために表示を更新する
update display to mention our name is name */
     document.getElementsByTagName('h1')[0].textContent += ' ' + name;
     /* 
このリスナはもう不要
no longer need this listener */
     worker.port.removeEventListener('message', configure, false);
   }
   worker.port.addEventListener('message', configure, false);

   /* 
マップ
MAP */
   function paintMap(event) {
     if (event.data.substr(0, 4) != 'map ') return;
     var data = event.data.substr(4).split(',');
     /* 
data[0] .. data[8] の各升を表示する
display tiles data[0] .. data[8] */
     var canvas = document.getElementById('map');
     var context = canvas.getContext('2d');
     for (var y = 0; y < 3; y += 1) {
       for (var x = 0; x < 3; x += 1) {
         var tile = data[y * 3 + x];
         if (tile == '0')
           context.fillStyle = 'green';
         else 
           context.fillStyle = 'maroon';
         context.fillRect(x * 50, y * 50, 50, 50);
       }
     }
   }
   worker.port.addEventListener('message', paintMap, false);

   /* 
公開チャット
PUBLIC CHAT */
   function updatePublicChat(event) {
     if (event.data.substr(0, 4) != 'txt ') return;
     var name = event.data.substr(4).split(' ', 1)[0];
     var message = event.data.substr(4 + name.length + 1);
     /* 
公開チャットに "<name> message" を表示する
display "<name> message" in public chat */
     var public = document.getElementById('public');
     var p = document.createElement('p');
     var n = document.createElement('button');
     n.textContent = '<' + name + '> ';
     n.onclick = function () { worker.port.postMessage('msg ' + name); };
     p.appendChild(n);
     var m = document.createElement('span');
     m.textContent = message;
     p.appendChild(m);
     public.appendChild(p);
   }
   worker.port.addEventListener('message', updatePublicChat, false);

   /* 
非公開チャット
PRIVATE CHAT */
   function startPrivateChat(event) {
     if (event.data.substr(0, 4) != 'msg ') return;
     var name = event.data.substr(4).split(' ', 1)[0];
     var port = event.ports[0];
     /* 
非公開チャット UI を表示する
display a private chat UI */
     var ul = document.getElementById('private');
     var li = document.createElement('li');
     var h3 = document.createElement('h3');
     h3.textContent = 'Private chat with ' + name;
     li.appendChild(h3);
     var div = document.createElement('div');
     var addMessage = function(name, message) {
       var p = document.createElement('p');
       var n = document.createElement('strong');
       n.textContent = '<' + name + '> ';
       p.appendChild(n);
       var t = document.createElement('span');
       t.textContent = message;
       p.appendChild(t);
       div.appendChild(p);
     };
     port.onmessage = function (event) {
       addMessage(name, event.data);
     };
     li.appendChild(div);
     var form = document.createElement('form');
     var p = document.createElement('p');
     var input = document.createElement('input');
     input.size = 50;
     p.appendChild(input);
     p.appendChild(document.createTextNode(' '));
     var button = document.createElement('button');
     button.textContent = 'Post';
     p.appendChild(button);
     form.onsubmit = function () {
       port.postMessage(input.value);
       addMessage('me', input.value);
       input.value = '';
       return false;
     };
     form.appendChild(p);
     li.appendChild(form);
     ul.appendChild(li);
   }
   worker.port.addEventListener('message', startPrivateChat, false);

   worker.port.start();
</script>

 </head>
 <body>
  <h1>Viewer</h1>
  <h2>Map</h2>
  <p><canvas id="map" height=150 width=150></canvas></p>
  <p>
   <button type=button onclick="worker.port.postMessage('mov left')"
   >Left</button>
   <button type=button onclick="worker.port.postMessage('mov up')"
   >Up</button>
   <button type=button onclick="worker.port.postMessage('mov down')"
   >Down</button>
   <button type=button onclick="worker.port.postMessage('mov right')"
   >Right</button>
   <button type=button onclick="worker.port.postMessage('set 0')"
   >Set 0</button>
   <button type=button onclick="worker.port.postMessage('set 1')"
   >Set 1</button>
  </p>
  <h2>Public Chat</h2>
  <div id="public"></div>
  <form onsubmit="worker.port.postMessage('txt ' + message.value);
    message.value = ''; return false;"
  >
   <p>
    <input type="text" name="message" size="50">
    <button>Post</button>
   </p>
  </form>
  <h2>Private Chat</h2>
  <ul id="private"></ul>
 </body>
</html>

ビューアの書かれ方には、 着目すべき点がいくつかある。 There are several key things worth noting about the way the viewer is written.

複数のリスナ: このコードは、 1 個のメッセージ処理関数の代わりに, 複数のイベントリスナを付け加えている — それぞれがメッセージに関連するかどうか簡単な検査を遂行するような。 この例では,さほど大きな相違は生じないが、 幾人かの作者達が協同する中で, worker との通信に単独のポートの利用が求まれる状況においても、 すべての変更を単独のイベント取り扱い関数に加えることなく, 独立なコードでそれが可能になる。 Multiple listeners. Instead of a single message processing function, the code here attaches multiple event listeners, each one performing a quick check to see if it is relevant for the message. In this example it doesn't make much difference, but if multiple authors wanted to collaborate using a single port to communicate with a worker, it would allow for independent code instead of changes having to all be made to a single event handling function.

このような仕方でイベントリスナを登録した場合、 この例の configure() メソッドのように, 事を終えたリスナを個別的に未登録にすることも可能になる。 Registering event listeners in this way also allows you to unregister specific listeners when you are done with them, as is done with the configure() method in this example.

最後に,worker : Finally, the worker:

var nextName = 0;
function getNextName() {
  /* 
もっと親しみ易い名前にすることもできたが、
今の所は,ただの番号。
this could use more friendly names but for now just return a number */
  return nextName++;
}

var map = [
 [0, 0, 0, 0, 0, 0, 0],
 [1, 1, 0, 1, 0, 1, 1],
 [0, 1, 0, 1, 0, 0, 0],
 [0, 1, 0, 1, 0, 1, 1],
 [0, 0, 0, 1, 0, 0, 0],
 [1, 0, 0, 1, 1, 1, 1],
 [1, 1, 0, 1, 1, 0, 1],
];

function wrapX(x) {
  if (x < 0) return wrapX(x + map[0].length);
  if (x >= map[0].length) return wrapX(x - map[0].length);
  return x;
}

function wrapY(y) {
  if (y < 0) return wrapY(y + map.length);
  if (y >= map[0].length) return wrapY(y - map.length);
  return y;
}

function wrap(val, min, max) {
  if (val < min)
    return val + (max - min) + 1;
  if (val > max)
    return val - (max - min) - 1;
  return val;
}

function sendMapData(viewer) {
  var data = '';
  for (var y = viewer.y - 1; y <= viewer.y + 1; y += 1) {
    for (var x = viewer.x - 1; x <= viewer.x + 1; x += 1) {
      if (data != '')
        data += ',';
      data += map[wrap(y, 0, map[0].length-1)][wrap(x, 0, map.length-1)];
    }
  }
  viewer.port.postMessage('map ' + data);
}

var viewers = {};
onconnect = function (event) {
  var name = getNextName();
  event.ports[0]._data = { port: event.ports[0], name: name, x: 0, y: 0, };
  viewers[name] = event.ports[0]._data;
  event.ports[0].postMessage('cfg ' + name);
  event.ports[0].onmessage = getMessage;
  sendMapData(event.ports[0]._data);
};

function getMessage(event) {
  switch (event.data.substr(0, 4)) {
    case 'mov ':
      var direction = event.data.substr(4);
      var dx = 0;
      var dy = 0;
      switch (direction) {
        case 'up': dy = -1; break;
        case 'down': dy = 1; break;
        case 'left': dx = -1; break;
        case 'right': dx = 1; break;
      }
      event.target._data.x = wrapX(event.target._data.x + dx);
      event.target._data.y = wrapY(event.target._data.y + dy);
      sendMapData(event.target._data);
      break;
    case 'set ':
      var value = event.data.substr(4);
      map[event.target._data.y][event.target._data.x] = value;
      for (var viewer in viewers)
        sendMapData(viewers[viewer]);
      break;
    case 'txt ':
      var name = event.target._data.name;
      var message = event.data.substr(4);
      for (var viewer in viewers)
        viewers[viewer].port.postMessage('txt ' + name + ' ' + message);
      break;
    case 'msg ':
      var party1 = event.target._data;
      var party2 = viewers[event.data.substr(4).split(' ', 1)[0]];
      if (party2) {
        var channel = new MessageChannel();
        party1.port.postMessage('msg ' + party2.name, [channel.port1]);
        party2.port.postMessage('msg ' + party1.name, [channel.port2]);
      }
      break;
  }
}

複数のページへの接続法: このスクリプトは、 複数の接続をリッスンするために, onconnect イベントリスナを利用している。 Connecting to multiple pages. The script uses the onconnect event listener to listen for multiple connections.

直通チャネル: worker が, 一方のビューアから他方のビューアを指名する "msg" メッセージを受信したときには、 両者の間に直な接続が設定しておかれる — worker がすべてのメッセージを代理しなくとも、 両ビューアは直に通信できる。 Direct channels. When the worker receives a "msg" message from one viewer naming another viewer, it sets up a direct connection between the two, so that the two viewers can communicate directly without the worker having to proxy all the messages.

この例をオンラインで見る View this example online.

10.1.2.5. 委任

この節は規範的ではない。This section is non-normative.

複コア CPU の普及に伴い、 計算量の大きな仕事を複数の worker に分業させて, より良い処理能が得られるようになっている。 この例では、 1 〜 10,000,000 に付番された計算量の大きな仕事を 10 等分して, 10 個の下位 worker に遂行させる。 With multicore CPUs becoming prevalent, one way to obtain better performance is to split computationally expensive tasks amongst multiple workers. In this example, a computationally expensive task that is to be performed for every number from 1 to 10,000,000 is farmed out to ten subworkers.

メインページは、 単に結果を報告する: The main page is as follows, it just reports the result:

<!DOCTYPE HTML>
<html>
 <head>
  <meta charset="utf-8">
  <title>worker 例: 複コアによる計算</title>
 </head>
 <body>
  <p>Result: <output id="result"></output></p>

<script>
   var worker = new Worker('worker.js');
   worker.onmessage = function (event) {
     document.getElementById('result').textContent = event.data;
   };
</script>

 </body>
</html>

worker 自身は: The worker itself is as follows:

/* 
設定
settings */
var num_workers = 10;
var items_per_worker = 1000000;

/* 
worker を開始する
start the workers */
var result = 0;
var pending_workers = num_workers;
for (var i = 0; i < num_workers; i += 1) {
  var worker = new Worker('core.js');
  worker.postMessage(i * items_per_worker);
  worker.postMessage((i+1) * items_per_worker);
  worker.onmessage = storeResult;
}

/* 
結果を取り扱う
handle the results */
function storeResult(event) {
  result += 1*event.data;
  pending_workers -= 1;
  if (pending_workers <= 0)
    postMessage(result); /* 
完成!
finished! */
}

それは、 一連の下位 worker を開始させるループと, 各 下位 worker から返される応答を待機するハンドラからなる。 It consists of a loop to start the subworkers, and then a handler that waits for all the subworkers to respond.

下位 worker の実装は: The subworkers are implemented as follows:

var start;
onmessage = getStart;
function getStart(event) {
  start = 1*event.data;
  onmessage = getEnd;
}

var end;
function getEnd(event) {
  end = 1*event.data;
  onmessage = null;
  work();
}

function work() {
  var result = 0;
  for (var i = start; i < end; i += 1) {
    /* 
何か複階的な計算がここで遂行される
perform some complex calculation here */
    result += 1;
  }
  postMessage(result);
  close();
}

これらはそれぞれ、 2 度のイベントで 2 個の番号を受信して, それにより指定される付番範囲の計算を遂行して, 結果を親に報告する。 They receive two numbers in two events, perform the computation for the range of numbers thus specified, and then report the result back to the parent.

この例をオンラインで見る View this example online.

10.1.2.6. ライブラリを供するとき

この節は規範的ではない。This section is non-normative.

次の 3 種のタスクを供する,ある暗号化ライブラリが可用であるとする: Suppose that a cryptography library is made available that provides three tasks:

( 公開鍵, 私用鍵 ) ペアを生成する: Generate a public/private key pair
渡されたポートに, 2 個のメッセージ — 最初に公開鍵,次に私用鍵 — を送信する。 Takes a port, on which it will send two messages, first the public key and then the private key.
所与の ( 平文, 公開鍵 ) から,対応する暗号文を返す: Given a plaintext and a public key, return the corresponding ciphertext
渡されたポートに,任意個数のメッセージ — 最初に公開鍵,以降は平文 — を送信する。 各 平文は、 暗号化されてから暗号文と同じチャネルに送信される。 内容を暗号化し終えたなら,ポートを close できる。 Takes a port, to which any number of messages can be sent, the first giving the public key, and the remainder giving the plaintext, each of which is encrypted and then sent on that same channel as the ciphertext. The user can close the port when it is done encrypting content.
所与の ( 暗号文, 私用鍵 ) 対応する平文を返す Given a ciphertext and a private key, return the corresponding plaintext
渡されたポートに,任意個数のメッセージ — 最初に私用鍵,以降は暗号文 — を送信する。 各 暗号文は、 復号されてから平文と同じチャネルに送信される。 内容を復号し終えたなら,ポートを close できる。 Takes a port, to which any number of messages can be sent, the first giving the private key, and the remainder giving the ciphertext, each of which is decrypted and then sent on that same channel as the plaintext. The user can close the port when it is done decrypting content.

ライブラリ自身は: The library itself is as follows:

function handleMessage(e) {
  if (e.data == "genkeys")
    genkeys(e.ports[0]);
  else if (e.data == "encrypt")
    encrypt(e.ports[0]);
  else if (e.data == "decrypt")
    decrypt(e.ports[0]);
}

function genkeys(p) {
  var keys = _generateKeyPair();
  p.postMessage(keys[0]);
  p.postMessage(keys[1]);
}

function encrypt(p) {
  var key, state = 0;
  p.onmessage = function (e) {
    if (state == 0) {
      key = e.data;
      state = 1;
    } else {
      p.postMessage(_encrypt(key, e.data));
    }
  };
}

function decrypt(p) {
  var key, state = 0;
  p.onmessage = function (e) {
    if (state == 0) {
      key = e.data;
      state = 1;
    } else {
      p.postMessage(_decrypt(key, e.data));
    }
  };
}

/* 
共用 worker , 専用 worker どちらとして利用されていても,サポートする
support being used as a shared worker as well as a dedicated worker */
if ('onmessage' in this) /* 専用 worker  */
  onmessage = handleMessage;
else /* 共用 worker  */
  onconnect = function (e) { e.port.onmessage = handleMessage; }

/* 
“暗号” 関数:
the "crypto" functions: */

function _generateKeyPair() {
  return [Math.random(), Math.random()];
}

function _encrypt(k, s) {
  return 'encrypted-' + k + ' ' + s;
}

function _decrypt(k, s) {
  return s.substr(s.indexOf(' ')+1);
}

ここでの暗号関数は、 単なるスタブであり,本当の暗号化は行わないことに注意。 Note that the crypto functions here are just stubs and don't do real cryptography.

このライブラリは、 次のようにも利用できる: This library could be used as follows:

<!DOCTYPE HTML>
<html>
 <head>
  <meta charset="utf-8">
  <title>Worker example: Crypto library</title>
  <script>
   const cryptoLib = new Worker('libcrypto-v1.js'); /* 
あるいは 'libcrypto-v2.js' も利用できる
or could use 'libcrypto-v2.js' */
   function startConversation(source, message) {
     const messageChannel = new MessageChannel();
     source.postMessage(message, [messageChannel.port2]);
     return messageChannel.port1;
   }
   function getKeys() {
     let state = 0;
     startConversation(cryptoLib, "genkeys").onmessage = function (e) {
       if (state === 0)
         document.getElementById('public').value = e.data;
       else if (state === 1)
         document.getElementById('private').value = e.data;
       state += 1;
     };
   }
   function enc() {
     const port = startConversation(cryptoLib, "encrypt");
     port.postMessage(document.getElementById('public').value);
     port.postMessage(document.getElementById('input').value);
     port.onmessage = function (e) {
       document.getElementById('input').value = e.data;
       port.close();
     };
   }
   function dec() {
     const port = startConversation(cryptoLib, "decrypt");
     port.postMessage(document.getElementById('private').value);
     port.postMessage(document.getElementById('input').value);
     port.onmessage = function (e) {
       document.getElementById('input').value = e.data;
       port.close();
     };
   }
  </script>
  <style>
   textarea { display: block; }
  </style>
 </head>
 <body onload="getKeys()">
  <fieldset>
   <legend>Keys</legend>
   <p><label>Public Key: <textarea id="public"></textarea></label></p>
   <p><label>Private Key: <textarea id="private"></textarea></label></p>
  </fieldset>
  <p><label>Input: <textarea id="input"></textarea></label></p>
  <p><button onclick="enc()">Encrypt</button> <button onclick="dec()">Decrypt</button></p>
 </body>
</html>

この API の後のバージョンでは、 すべての暗号作業を下位 worker に負荷を委譲するよう求まれるかもしれない。 これは、 次のように行うこともできる: A later version of the API, though, might want to offload all the crypto work onto subworkers. This could be done as follows:

function handleMessage(e) {
  if (e.data == "genkeys")
    genkeys(e.ports[0]);
  else if (e.data == "encrypt")
    encrypt(e.ports[0]);
  else if (e.data == "decrypt")
    decrypt(e.ports[0]);
}

function genkeys(p) {
  var generator = new Worker('libcrypto-v2-generator.js');
  generator.postMessage('', [p]);
}

function encrypt(p) {
  p.onmessage = function (e) {
    var key = e.data;
    var encryptor = new Worker('libcrypto-v2-encryptor.js');
    encryptor.postMessage(key, [p]);
  };
}

function encrypt(p) {
  p.onmessage = function (e) {
    var key = e.data;
    var decryptor = new Worker('libcrypto-v2-decryptor.js');
    decryptor.postMessage(key, [p]);
  };
}

/* 
共用 worker , 専用 worker どちらとして利用されていても,サポートする
support being used as a shared worker as well as a dedicated worker */
if ('onmessage' in this) /* 
専用 worker 
dedicated worker */
  onmessage = handleMessage;
else /* 
共用 worker 
shared worker */
  onconnect = function (e) { e.ports[0].onmessage = handleMessage };

小分けにされた下位 worker は: The little subworkers would then be as follows.

鍵ペアの生成用: For generating key pairs:

onmessage = function (e) {
  var k = _generateKeyPair();
  e.ports[0].postMessage(k[0]);
  e.ports[0].postMessage(k[1]);
  close();
}

function _generateKeyPair() {
  return [Math.random(), Math.random()];
}

暗号化用: For encrypting:

onmessage = function (e) {
  var key = e.data;
  e.ports[0].onmessage = function (e) {
    var s = e.data;
    postMessage(_encrypt(key, s));
  }
}

function _encrypt(k, s) {
  return 'encrypted-' + k + ' ' + s;
}

復号用: For decrypting:

onmessage = function (e) {
  var key = e.data;
  e.ports[0].onmessage = function (e) {
    var s = e.data;
    postMessage(_decrypt(key, s));
  }
}

function _decrypt(k, s) {
  return s.substr(s.indexOf(' ')+1);
}

API は変更されてないので、 API の利用者は,これが起きていることを知る必要すらない。 ライブラリは、 メッセージチャネルを利用してデータを受容しているが, 自身の API を変更することなく下位 worker に委任できる。 Notice how the users of the API don't have to even know that this is happening — the API hasn't changed; the library can delegate to subworkers without changing its API, even though it is accepting data using message channels.

この例をオンラインで見るView this example online.

10.1.3. チュートリアル

10.1.3.1. 専用 worker の作成法

この節は規範的ではない。This section is non-normative.

worker を作成するためには JavaScript ファイルの URL を要する。 そのファイルの URL のみを引数として new Worker() 構築子を呼び出せば、 worker が作成されて返される: Creating a worker requires a URL to a JavaScript file. The Worker() constructor is invoked with the URL to that file as its only argument; a worker is then created and returned:

var worker = new Worker('helper.js');

古典スクリプトでなくモジュールスクリプトとして解釈させたいときは、 記し方を少し違える必要がある: If you want your worker script to be interpreted as a module script instead of the default classic script, you need to use a slightly different signature:

var worker = new Worker('helper.mjs', { type: "module" });
10.1.3.2. 専用 worker との通信法

この節は規範的ではない。This section is non-normative.

専用 worker は暗黙的に MessagePort オブジェクトを利用する。 したがって、[ 有構造データの送信法, バイナリデータの転送法, 他のポートへの転送法 ]など, MessagePort と同じ特能をサポートする。 Dedicated workers use MessagePort objects behind the scenes, and thus support all the same features, such as sending structured data, transferring binary data, and transferring other ports.

専用 worker からメッセージを受信するためには、 Worker オブジェクトの onmessage イベントハンドラ IDL 属性を利用する: To receive messages from a dedicated worker, use the onmessage event handler IDL attribute on the Worker object:

worker.onmessage = function (event) { ... };

addEventListener() メソッドも利用できる。 You can also use the addEventListener() method.

注記: 専用 worker に利用される暗黙的な MessagePort には、 その作成時にポートメッセージキューが暗黙的に備わり,可能化される。 したがって、 Worker インタフェースには, MessagePort インタフェースの start() メソッドに等価なものはない。 The implicit MessagePort used by dedicated workers has its port message queue implicitly enabled when it is created, so there is no equivalent to the MessagePort interface's start() method on the Worker interface.

データを worker へ送信するためには、 postMessage() メソッドを利用する。 有構造データもこの通信チャネルを通して送信できる。 (何個かの) ArrayBuffer オブジェクトを効率的に送信する(クローンせずに転送する)ためには、 それらを配列にして 2 個目の引数に渡す。 To send data to a worker, use the postMessage() method. Structured data can be sent over this communication channel. To send ArrayBuffer objects efficiently (by transferring them rather than cloning them), list them in an array in the second argument.

worker.postMessage({
  operation: 'find-edges',
  input: buffer, /* 
ArrayBuffer オブジェクト
an ArrayBuffer object */
  threshold: 0.6,
}, [buffer]);

worker の内側でメッセージを受信するときは、 onmessage イベントハンドラ IDL 属性を利用する。 To receive a message inside the worker, the onmessage event handler IDL attribute is used.

onmessage = function (event) { ... };

ここでもまた addEventListener() メソッドを利用できる。 You can again also use the addEventListener() method.

いずれの場合も,データはイベントオブジェクトの data 属性に供される。 In either case, the data is provided in the event object's data attribute.

メッセージの返信時にも, postMessage() を利用する。 有構造データも同じようにサポートされる。 To send messages back, you again use postMessage(). It supports the structured data in the same manner.

postMessage(event.data.input, [event.data.input]); /* 
バッファを返送
transfer the buffer back */
10.1.3.3. 共用 worker

この節は規範的ではない。This section is non-normative.

共用 worker は、 その作成時に利用したスクリプトの URL により識別され, 名前(省略可能)も明示的に付与できる。 名前があれば、 ある特定の共用 worker に対し複数のインスタンスを開始することも可能になる。 Shared workers are identified by the URL of the script used to create it, optionally with an explicit name. The name allows multiple instances of a particular shared worker to be started.

共用 worker は,生成元のスコープに属する(生成元ごとに分別される)。 互いに異なるサイトが同じ名前のものを利用したとしても,衝突することはない。 しかしながら、 同じサイト内の 2 つのページで, 同じ共用 worker 名に異なるスクリプト URL を伴わせて利用した場合、 失敗することになる。 Shared workers are scoped by origin. Two different sites using the same names will not collide. However, if a page tries to use the same shared worker name as another page on the same site, but with a different script URL, it will fail.

共用 worker の作成には、 new SharedWorker() 構築子を利用する。 この構築子は、 最初の 2 個の引数に[ 利用するスクリプトの URL , worker の名前(省略可能) ]をとる。 Creating shared workers is done using the SharedWorker() constructor. This constructor takes the URL to the script to use for its first argument, and the name of the worker, if any, as the second argument.

var worker = new SharedWorker('service.js');

共用 worker と通信するときは、 明示的な MessagePort オブジェクトを通して行う。 new SharedWorker() 構築子から返されるオブジェクトは、 そのポートへの参照を port 属性に保持する。 Communicating with shared workers is done with explicit MessagePort objects. The object returned by the SharedWorker() constructor holds a reference to the port on its port attribute.

worker.port.onmessage = function (event) { ... };
worker.port.postMessage('some message');
worker.port.postMessage({
   foo: 'structured',
   bar: ['data', 'also', 'possible']
});

共用 worker の内側では、 connect イベントを利用して, 新たなクライアントからの接続が告知される。 新たなクライアント用のポートは、 このイベントオブジェクトの source 属性により与えられる。 Inside the shared worker, new clients of the worker are announced using the connect event. The port for the new client is given by the event object's source attribute.

onconnect = function (event) {
  var newPort = event.source;
  /* 
リスナを設定しておく
set up a listener */
  newPort.onmessage = function (event) { ... };
  /* 
ポートにメッセージを返信する
send a message back to the port */
  newPort.postMessage('ready!'); /* 
もちろん、
有構造データも返信できる
can also send structured data, of course */
};

【この訳に特有な表記規約】

この訳において(主にアルゴリズム内で)利用される各種記号( ε, ← , IF, THROW, 等々)の意味や定義の詳細は、共通な慣用表現, アルゴリズムに共通して利用される表記を参照されたし。

10.2. 基盤

この仕様は、 2 種類の worker — 専用 worker , 共用 worker — を定義する。 専用 worker は,作成時にその作成元へリンクされるが、 メッセージポートを利用することで, 他の閲覧文脈や worker へも通信できる。 一方で、 共用 worker には,名前があり、 その作成後に それへの参照を得ておけば, 同じ生成元上で走っているどのスクリプトとも通信できる。 Service Workers は、 また別の種類の worker を定義する。 [SW] This standard defines two kinds of workers: dedicated workers, and shared workers. Dedicated workers, once created, are linked to their creator, but message ports can be used to communicate from a dedicated worker to multiple other browsing contexts or workers. Shared workers, on the other hand, are named, and once created any script running in the same origin can obtain a reference to that worker and communicate with it. Service Workers defines a third kind. [SW]

10.2.1. 大域スコープ

大域スコープが worker の “内側” である。 The global scope is the "inside" of a worker.

【 すなわち、 同じ worker が, “二つの顔” — その内側で走っているスクリプトに公開する WorkerGlobalScope オブジェクト(大域スコープ), それを外側から利用するスクリプトに公開する Worker オブジェクト — を持つ (共用 worker の場合、 後者は,当の worker を共有している大域環境の個数だけ複数あり得る)。 】

10.2.1.1. WorkerGlobalScope 共通インタフェース
[Exposed=Worker]
interface WorkerGlobalScope : EventTarget {
  readonly attribute WorkerGlobalScope self;
  readonly attribute WorkerLocation location;
  readonly attribute WorkerNavigator navigator;
  undefined importScripts((TrustedScriptURL or USVString)... urls);

  attribute OnErrorEventHandler onerror;
  attribute EventHandler onlanguagechange;
  attribute EventHandler onoffline;
  attribute EventHandler ononline;
  attribute EventHandler onrejectionhandled;
  attribute EventHandler onunhandledrejection;
};

WorkerGlobalScope は、 各種 worker 大域スコープオブジェクトの基底クラスとしてサーブする — そのようなオブジェクトの型には、 特に次に挙げるものが含まれる :DedicatedWorkerGlobalScope, SharedWorkerGlobalScope, ServiceWorkerGlobalScope WorkerGlobalScope serves as the base class for specific types of worker global scope objects, including DedicatedWorkerGlobalScope, SharedWorkerGlobalScope, and ServiceWorkerGlobalScope.

WorkerGlobalScope オブジェクトには、 次に挙げるものが結び付けられる:

所有者集合 A WorkerGlobalScope object has an associated owner set\
DocumentWorkerGlobalScope ]オブジェクトたちが成す集合 — 初期時は空とする。 この worker を[ 作成する/得る ]ときに拡充される。 (a set of Document and WorkerGlobalScope objects). It is initially empty and populated when the worker is created or obtained.
注記: 単独の所有者ではなく集合にされているのは、 SharedWorkerGlobalScope オブジェクトに適応するためである。 It is a set, instead of a single owner, to accommodate SharedWorkerGlobalScope objects.
種別 A WorkerGlobalScope object has an associated type\
作成時に,次のいずれかに設定される :"classic" / "module" ("classic" or "module"). It is set during creation.
URL A WorkerGlobalScope object has an associated url\
null または URL — 初期時は null とする。 (null or a URL). It is initially null.
【 少なくとも,API からアクセスされる時点までには、 null 以外に設定されることになる。 】
名前 A WorkerGlobalScope object has an associated name\
文字列 — 作成時に設定される。 (a string). It is set during creation.

注記: 名前の意味論は、 WorkerGlobalScope の下位クラスごとに異なり得る: The name can have different semantics for each subclass of WorkerGlobalScope.\

  • DedicatedWorkerGlobalScope 用には、 単純に開発者が給する名前であり,ほぼデバッグ目的に限り有用になる。 For DedicatedWorkerGlobalScope instances, it is simply a developer-supplied name, useful mostly for debugging purposes.\
  • SharedWorkerGlobalScope 用には、 共通な共用 worker への参照を new SharedWorker() 構築子を介して得ることを許容する。 For SharedWorkerGlobalScope instances, it allows obtaining a reference to a common shared worker via the SharedWorker() constructor.\
  • ServiceWorkerGlobalScope 用には、 意味を成さない (そのため、 JavaScript API を通して公開されることもない)。 For ServiceWorkerGlobalScope objects, it doesn't make sense (and as such isn't exposed through the JavaScript API at all).
施策コンテナ A WorkerGlobalScope object has an associated policy container\
施策コンテナ — 初期時は新たな施策コンテナとする。 (a policy container). It is initially a new policy container.
埋め込み元施策 A WorkerGlobalScope object has an associated embedder policy\
埋め込み元施策 (an embedder policy).
モジュールマップ A WorkerGlobalScope object has an associated module map.\
モジュールマップ — 初期時は空とする。 It is a module map, initially empty.
非同一生成元能力は隔離されるか A WorkerGlobalScope object has an associated cross-origin isolated capability\
真偽値 — 初期時は false とする。 boolean. It is initially false.
workerGlobal.self
workerGlobal 自身を返す。 Returns workerGlobal.
workerGlobal.location
workerGlobalWorkerLocation オブジェクトを返す。 Returns workerGlobal's WorkerLocation object.
workerGlobal.navigator
workerGlobalWorkerNavigator オブジェクトを返す。 Returns workerGlobal's WorkerNavigator object.
workerGlobal.importScripts(...urls)
urls を成す各 URL を — 渡された順に一つずつ — fetch して, 実行して, 結果を返す (あるいは、 どこかで不具合があれば例外を投出する)。 Fetches each URL in urls, executes them one-by-one in the order they are passed, and then returns (or throws if something went amiss).
self 取得子手続きは :RETURN これ° The self attribute must return the WorkerGlobalScope object itself.

location 取得子手続きは

  1. Assertこれ°worker 所在オブジェクト ε
  2. RETURN これ°worker 所在オブジェクト

注記: WorkerLocation オブジェクトが作成されるのは, WorkerGlobalScope オブジェクトより後になるが、 それはスクリプトからは観測し得ないので,問題にはならない。

The location attribute must return the WorkerLocation object whose associated WorkerGlobalScope object is the WorkerGlobalScope object.While the WorkerLocation object is created after the WorkerGlobalScope object, this is not problematic as it cannot be observed from script.

WorkerGlobalScope インタフェースを実装するオブジェクトにおいては、 次に挙げるイベントハンドラ(および,それらに対応するイベントハンドライベント型)をイベントハンドラ IDL 属性としてサポートするものとする: The following are the event handlers (and their corresponding event handler event types) that must be supported, as event handler IDL attributes, by objects implementing the WorkerGlobalScope interface:

イベントハンドラ イベントハンドライベント型
onerror error
onlanguagechange languagechange
onoffline offline
ononline online
onrejectionhandled rejectionhandled
onunhandledrejection unhandledrejection
10.2.1.2. 専用 worker と DedicatedWorkerGlobalScope インタフェース
[Global=(Worker,DedicatedWorker),Exposed=DedicatedWorker]
interface DedicatedWorkerGlobalScope : WorkerGlobalScope {
  [Replaceable] readonly attribute DOMString name;

  undefined postMessage(any message, sequence<object> transfer);
  undefined postMessage(any message, optional StructuredSerializeOptions options = {});
  undefined close();

  DedicatedWorkerGlobalScope includes MessageEventTarget;
};

DedicatedWorkerGlobalScope オブジェクトには、 内側ポート が結び付けられる — それは: DedicatedWorkerGlobalScope objects have an associated inside port\

  • MessagePort オブジェクトである。 (a MessagePort).\
  • 当の worker 作成時に設定しておかれるチャネルの一部を成すが,公開されない。 This port is part of a channel that is set up when the worker is created, but it is not exposed.\
  • 当の DedicatedWorkerGlobalScope オブジェクトより先にガーベジ収集されてはならない。 This object must never be garbage collected before the DedicatedWorkerGlobalScope object.
dedicatedWorkerGlobal.name
dedicatedWorkerGlobal名前 — すなわち, new Worker() 構築子に与えた値 — を返す。 主に、 デバッグ時に有用になる。 Returns dedicatedWorkerGlobal's name, i.e. the value given to the Worker constructor. Primarily useful for debugging.
dedicatedWorkerGlobal.postMessage(message, transfer)
dedicatedWorkerGlobal.postMessage(message [, options ])
メッセージをクローンして,それを dedicatedWorkerGlobal に結び付けられた Worker オブジェクトへ伝送する。 [ transfer / [ optionstransfer メンバ ]]に、 クローンせずに転送するオブジェクトのリストを渡せる。 Clones message and transmits it to the Worker object associated with dedicatedWorkerGlobal. transfer can be passed as a list of objects that are to be transferred rather than cloned.
dedicatedWorkerGlobal.close()
dedicatedWorkerGlobal を中止する。 Aborts dedicatedWorkerGlobal.

name 取得子手続きは :RETURN これ°名前 The name getter steps are to return this's name.\

返される値は、 new Worker 構築子を利用して worker に与えた名前を表現する — これは主として、 デバッグ目的に利用される。 Its value represents the name given to the worker using the Worker constructor, used primarily for debugging purposes.

postMessage(message, transfer) メソッド手続きは :RETURN これ°内側ポート上の postMessage メソッド手続き( message, transfer )

postMessage(message, options) メソッド手続きは :RETURN これ°内側ポート上の postMessage メソッド手続き( message, options )

The postMessage(message, transfer) and postMessage(message, options) methods on DedicatedWorkerGlobalScope objects act as if, when invoked, it immediately invoked the respective postMessage(message, transfer) and postMessage(message, options) on the port, with the same arguments, and returned the same return value.

worker を close する アルゴリズムは、 所与の ( worker 大域スコープ ) に対し: To close a worker, given a workerGlobal, run these steps:

  1. worker 大域スコープ関連する agentイベントループタスクキューに追加されたタスクは、 すべて破棄する Discard any tasks that have been added to workerGlobal's relevant agent's event loop's task queues.
  2. worker 大域スコープclose 中か ← true (これにより、 タスクがそれ以上キューされることはなくなる。) Set workerGlobal's closing flag to true. (This prevents any further tasks from being queued.)
close() メソッド手続きは :worker を close する( これ° ) The close() method steps are to close a worker given this.
10.2.1.3. 共用 worker と SharedWorkerGlobalScope インタフェース
[Global=(Worker,SharedWorker),Exposed=SharedWorker]
interface SharedWorkerGlobalScope : WorkerGlobalScope {
  [Replaceable] readonly attribute DOMString name;

  undefined close();

  attribute EventHandler onconnect;
};

SharedWorkerGlobalScope オブジェクトには、 次に挙げるものが結び付けられ, 当のオブジェクトの作成時に worker を走らすアルゴリズムにて初期化される :構築子生成元, 構築子 URL , 資格情報, A SharedWorkerGlobalScope object has an associated constructor origin, constructor url, and credentials. They are initialized when the SharedWorkerGlobalScope object is created, in the run a worker algorithm.

共用 worker は、 その SharedWorkerGlobalScope オブジェクト上の connect イベントを通して,各接続のメッセージポートを受信する。 Shared workers receive message ports through connect events on their SharedWorkerGlobalScope object for each connection.

sharedWorkerGlobal.name
sharedWorkerGlobal名前 — すなわち, new SharedWorker() 構築子に与えた値 — を返す。 同じ名前を再利用すれば、 同じ共用 worker (および SharedWorkerGlobalScope )に複数の SharedWorker オブジェクトを対応させれる。 Returns sharedWorkerGlobal's name, i.e. the value given to the SharedWorker constructor. Multiple SharedWorker objects can correspond to the same shared worker (and SharedWorkerGlobalScope), by reusing the same name.
sharedWorkerGlobal.close()
sharedWorkerGlobal を中止する。 Aborts sharedWorkerGlobal.

name 取得子手続きは :RETURN これ°名前 The name getter steps are to return this's name.\

返される値は、 new SharedWorker() 構築子を利用して worker への参照を得るときに利用できる名前を表現する。 Its value represents the name that can be used to obtain a reference to the worker using the SharedWorker constructor.

close() メソッド手続きは :worker を close する( これ° ) The close() method steps are to close a worker given this.

SharedWorkerGlobalScope インタフェースを実装するオブジェクトにおいては、 次に挙げるイベントハンドラ(および,それらに対応するイベントハンドライベント型)をイベントハンドラ IDL 属性としてサポートするものとする: The following are the event handlers (and their corresponding event handler event types) that must be supported, as event handler IDL attributes, by objects implementing the SharedWorkerGlobalScope interface:

イベントハンドラ イベントハンドライベント型
onconnect connect

10.2.2. イベントループ

worker イベントループタスクキュー内にあり得るタスクは、[ イベント, callback , ネットワーク処理活動 ]に限られる。 これらの worker イベントループは、 worker を走らすアルゴリズムにより作成される。 A worker event loop's task queues only have events, callbacks, and networking activity as tasks. These worker event loops are created by the run a worker algorithm.

WorkerGlobalScope オブジェクトは、 真偽値をとる close 中か を有する: Each WorkerGlobalScope object has a closing flag,\

  • 初期時には false になるものとする。 下の処理モデル節のアルゴリズムにより, true にされ得る。 which must be initially false, but which can get set to true by the algorithms in the processing model section below.
  • true にされたときは、 イベントループタスクキューに追加される それ以降のタスクは,破棄するものとする (キュー内にすでにあるタスクは、 特に指定されない限り,影響されない)。 実質的には、 true になったら,タイマーは発火を止め, 処理待ちにあるすべてのバックグラウンド演算の通知は取り除かれる, 等々が行われることになる。 Once the WorkerGlobalScope's closing flag is set to true, the event loop's task queues must discard any further tasks that would be added to them (tasks already on the queue are unaffected except where otherwise specified). Effectively, once the closing flag is true, timers stop firing, notifications for all pending background operations are dropped, etc.

10.2.3. worker の存続期間

worker は、 メッセージチャネルとそれらの MessagePort オブジェクトを通して,他の worker や window と通信する。 Workers communicate with other workers and with Windows through message channels and their MessagePort objects.

WorkerGlobalScope オブジェクト G は、 ポートリスト を有する — それは: Each WorkerGlobalScope object worker global scope has a list of the worker's ports,\

  • 次を満たす MessagePort オブジェクト P すべてからなる :P は別の MessagePort オブジェクト Q連絡されている ]GP, Q のうち P のみを所有している† ] which consists of all the MessagePort objects that are entangled with another port and that have one (but only one) port owned by worker global scope.\

    【† おそらく,[ P関連する大域オブジェクト G Q関連する大域オブジェクト ]を意味する。 】

  • 専用 worker の事例では 【すなわち, GDedicatedWorkerGlobalScope オブジェクトである】、 暗黙的なポートG内側ポートも含む。 【前項の条件を満たす限り。】 This list includes the implicit MessagePort in the case of dedicated workers.

所与の環境設定群オブジェクト O の下で worker を[ 作成する/得る ]ときに 関連する所有者として追加するもの は、 O により指定される大域オブジェクト G に応じて,次のいずれかになる: Given an environment settings object o when creating or obtaining a worker, the relevant owner to add depends on the type of global object specified by o.\

  • WorkerGlobalScope である(すなわち,入れ子な専用 worker を作成している)場合 :G If o's global object is a WorkerGlobalScope object (i.e., if we are creating a nested dedicated worker), then the relevant owner is that global object.\
  • Window である場合 :G結び付けられた文書 Otherwise, o's global object is a Window object, and the relevant owner is that Window's associated Document.

worker は、 その WorkerGlobalScopeG とするとき:

  • ↓ を満たしている間は、 許可可能permissible )とされる: A worker is said to be a permissible worker if\

    • G所有者集合でない its WorkerGlobalScope's owner set is not empty or:
      • G所有者集合は空であり続けているが、 実装定義な短い制限時間を過ぎていない its owner set has been empty for no more than a short implementation-defined timeout value,
      • GSharedWorkerGlobalScope オブジェクトである(すなわち,worker は共用 worker である) its WorkerGlobalScope object is a SharedWorkerGlobalScope object (i.e., the worker is a shared worker), and
      • UA の あるナビ可能にて作動中な文書は、 まだ完全に読み込まれていない the user agent has a navigable whose active document is not completely loaded.

      注記: 上の定義の 2 番目の項は、 読み込まれている短い間にページが共用 worker に再び繋がろうとしている下でも, 共用 worker が生き残れるようにする。 これを利用すれば,UA は、 利用者が あるサイトの中でページからページへナビゲートするときに, そのサイトが利用している共用 worker を開始し直すコストを避けれるようになる。 The second part of this definition allows a shared worker to survive for a short time while a page is loading, in case that page is going to contact the shared worker again. This can be used by user agents as a way to avoid the cost of restarting a shared worker used by a site when the user is navigating from page to page within that site.

  • 次を満たしている間は、 作動中なため必要active needed )とされる :G所有者集合内に次を満たす[ 文書/worker ]が在る :全部的に作動中作動中なため必要 ]である A worker is said to be an active needed worker if any of its owners are either Document objects that are fully active or active needed workers.
  • ↓ を満たしている間は、 保護され ている( protected )とされる: A worker is said to be a protected worker if\

    • 作動中なため必要である it is an active needed worker\
    • ↓: and either\

      • G 内に】待機中なタイマーがある it has outstanding timers,\
      • G 内に】データベーストランザクションがある[INDEXEDDB] database transactions, or\
      • G 内に】ネットワーク接続がある network connections, or\
      • Gポートリストは空でない its list of the worker's ports is not empty, or\
      • GSharedWorkerGlobalScope オブジェクトである(すなわち,worker は共用 worker である) its WorkerGlobalScope is actually a SharedWorkerGlobalScope object (i.e., the worker is a shared worker).
  • ↓ を満たしている間は、 休止可能suspendable )とされる A worker is said to be a suspendable worker if\

10.2.4. 処理モデル

あるスクリプト用の worker を走らす アルゴリズムは、 所与の :workerWorkerSharedWorker オブジェクト ), URLURL ), 外側設定群環境設定群オブジェクト ), 外側ポートMessagePort オブジェクト ), optionsWorkerOptions 辞書 ) に対し: When a user agent is to run a worker for a script with Worker or SharedWorker object worker, URL url, environment settings object outside settings, MessagePort outside port, and a WorkerOptions dictionary options, it must run the following steps.

  1. 共用か :← ISworkerSharedWorker オブジェクトである ] Let is shared be true if worker is a SharedWorker object, and false otherwise.
  2. 所有者 :← 外側設定群 から与えられる,関連する所有者として追加するもの Let owner be the relevant owner to add given outside settings.
  3. 安全でない worker 作成時刻 :← 安全でない共有される現在の時刻 Let unsafeWorkerCreationTime be the unsafe shared current time.
  4. agent :← 専用/共用 worker agent を得る( 外側設定群, 共用か ) Let agent be the result of obtaining a dedicated/shared worker agent given outside settings and is shared.\

    この手続きの以降は, agent 内で走らすとする Run the rest of these steps in that agent.

  5. realm 実行文脈 :← 次のようにカスタム化する下で, agent 内で新たな realm を作成する大域オブジェクト用には, 共用か に応じて次を作成する :true ならば 新たな SharedWorkerGlobalScope オブジェクト / false ならば 新たな DedicatedWorkerGlobalScope オブジェクト Let realm execution context be the result of creating a new realm given agent and the following customizations: • For the global object, if is shared is true, create a new SharedWorkerGlobalScope object. Otherwise, create a new DedicatedWorkerGlobalScope object.
  6. worker 大域スコープ :← realm 実行文脈大域オブジェクト成分 Let worker global scope be the global object of realm execution context's Realm component.

    注記: これは、 前段で作成した[ SharedWorkerGlobalScopeDedicatedWorkerGlobalScope ]オブジェクトになる。 This is the DedicatedWorkerGlobalScope or SharedWorkerGlobalScope object created in the previous step.

  7. 内側設定群 :← worker の環境設定群オブジェクトを設定しておく( realm 実行環境, 外側設定群, 安全でない worker 作成時刻 ) Set up a worker environment settings object with realm execution context, outside settings, and unsafeWorkerCreationTime, and let inside settings be the result.
  8. worker 大域スコープ名前options[ "name" ] Set worker global scope's name to the value of options's name member.
  9. worker 大域スコープ所有者集合所有者付加する Append owner to worker global scope's owner set.
  10. IF共用か true ] :worker 大域スコープ の :構築子生成元外側設定群生成元, 構築子 URLURL , 種別options[ "type" ], 資格情報options[ "credentials" ] If is shared is true, then: • Set worker global scope's constructor origin to outside settings's origin. • Set worker global scope's constructor url to url. • Set worker global scope's type to the value of options's type member. • Set worker global scope's credentials to the value of options's credentials member.
  11. 行先 :← 共用か に応じて :true ならば "sharedworker" / false ならば "worker" Let destination be "sharedworker" if is shared is true, and "worker" otherwise.
  12. 次に従ってスクリプトを得る — options[ "type" ] に応じて: Obtain script by switching on the value of options's type member:

    • "classic" :worker 用古典スクリプトを fetch する( ↓ ) :URL , 外側設定群, 行先, 内側設定群, 完了時の手続き†, fetch を遂行する"classic" • Fetch a classic worker script given url, outside settings, destination, inside settings, and with onComplete and performFetch as defined below.
    • "module" :モジュール worker スクリプトグラフを fetch する( ↓ ) :URL , 外側設定群, 行先, options[ "credentials" ], 内側設定群, 完了時の手続き†, fetch を遂行する"module" • Fetch a module worker script graph given url, outside settings, destination, the value of the credentials member of options, inside settings, and with onComplete and performFetch as defined below.

    † 上で利用される[ 完了時の手続き, fetch を遂行する ]は、 以下に定義される:

    fetch を遂行する は,fetch フックを遂行するアルゴリズムであり、 所与の ( 要請, トップレベルか, カスタム fetch 応答の処理 ) に対し,次を遂行する: In both cases, let performFetch be the following perform the fetch hook given request, isTopLevel and processCustomFetchResponse:

    1. IFトップレベルか false ]:

      1. 要請fetch する — 次を与える下で :応答の本体を消費する処理カスタム fetch 応答の処理
      2. RETURN
      If isTopLevel is false, fetch request with processResponseConsumeBody set to processCustomFetchResponse, and abort these steps.
    2. 要請予約済みクライアント内側設定群 Set request's reserved client to inside settings.
    3. 要請fetch する — 次を与える下で: Fetch request with\

      • 応答の本体を消費する処理 ← 所与の ( 応答 応答, [ null / 失敗バイト列本体バイト列 ) に対し,次を走らす手続き: processResponseConsumeBody set to the following steps given response response and null, failure, or a byte sequence bodyBytes:

        1. worker 大域スコープURL応答URL Set worker global scope's url to response's url.
        2. worker 大域スコープの施策コンテナを初期化する( worker 大域スコープ, 応答, 内側設定群 ) Initialize worker global scope's policy container given worker global scope, response, and inside settings.
        3. IF大域オブジェクト用に CSP 初期化を走らす( worker 大域スコープ ) 阻止される [CSP] ] :応答ネットワークエラー If the Run CSP initialization for a global object algorithm returns "Blocked" when executed upon worker global scope, set response to a network error. [CSP]
        4. IFworker 大域スコープ埋め込み元施策非同一生成元隔離と互換である ]共用か true ] :agentagent クラスタ非同一生成元隔離モード ← [ "logical""concrete" ] — どちらが選ばれるかは、 実装定義とする If worker global scope's embedder policy's value is compatible with cross-origin isolation and is shared is true, then set agent's agent cluster's cross-origin isolation mode to "logical" or "concrete". The one chosen is implementation-defined.

          これは,本当は当の agent クラスタが作成されるとき設定されるべきだが、 この節を設計し直すことが要求される。 This really ought to be set when the agent cluster is created, which requires a redesign of this section.

        5. IF大域オブジェクトの埋め込み元施策を検査する( worker 大域スコープ, 外側設定群, 応答 ) false ] :応答ネットワークエラー If the result of checking a global object's embedder policy with worker global scope, outside settings, and response is false, then set response to a network error.
        6. IFagentagent クラスタ非同一生成元隔離モード "concrete" ] :worker 大域スコープ非同一生成元能力は隔離されるか ← true Set worker global scope's cross-origin isolated capability to true if agent's agent cluster's cross-origin isolation mode is "concrete".
        7. IF共用か false ]所有者非同一生成元能力は隔離されるか? false ] :worker 大域スコープ非同一生成元能力は隔離されるか ← false If is shared is false and owner's cross-origin isolated capability is false, then set worker global scope's cross-origin isolated capability to false.
        8. IF共用か false ]応答URLスキーム "data" ] :worker 大域スコープ非同一生成元能力は隔離されるか ← false If is shared is false and response's url's scheme is "data", then set worker global scope's cross-origin isolated capability to false.

          注記: これは、 今の所は,保守的な既定である。 worker が一般に — および[ data: URL 【から構築された】worker (その所有者とは非同一生成元になる) ]が特に — 許可施策の文脈において,どう扱われることになるか解明されるまでの間の。 詳細は、 w3c/webappsec-permissions-policy 課題 #207 を見よ。 This is a conservative default for now, while we figure out how workers in general, and data: URL workers in particular (which are cross-origin from their owner), will be treated in the context of permissions policies. See w3c/webappsec-permissions-policy issue #207 for more details.

        9. カスタム fetch 応答の処理( 応答, 本体バイト列 ) Run processCustomFetchResponse with response and bodyBytes.

    完了時の手続き は、 所与の ( スクリプト ) に対し: In both cases, let onComplete given script be the following steps:

    1. IFスクリプト null ]スクリプト再投出用エラー null ]: If script is null or if script's error to rethrow is non-null, then:

      1. 大域タスクをキューする( DOM 操作タスクソース, worker関連する大域オブジェクト, 次の手続き )

        手続きは :イベントを発火する( worker , error )
        Queue a global task on the DOM manipulation task source given worker's relevant global object to fire an event named error at worker.
      2. 内側設定群 用の環境を破棄する手続き() Run the environment discarding steps for inside settings.
      3. RETURN Abort these steps.
    2. workerworker 大域スコープ に結び付ける Associate worker with worker global scope.
    3. 内側ポート :← 新たなオブジェクト( MessagePort, 内側設定群realm ) Let inside port be a new MessagePort object in inside settings's realm.
    4. IF共用か false ]: If is shared is false, then:

      1. 内側ポートメッセージイベントターゲットworker 大域スコープ Set inside port's message event target to worker global scope.
      2. worker 大域スコープ内側ポート内側ポート Set worker global scope's inside port to inside port.
    5. ポートを連絡する( 外側ポート, 内側ポート ) Entangle outside port and inside port.
    6. worker 大域スコープworker 所在オブジェクト ← 新たな WorkerLocation オブジェクト Create a new WorkerLocation object and associate it with worker global scope.
    7. worker の監視を開始する:

      • 孤立 worker は close 中worker が保護されなくなり次第、 許可可能であり続ける間まで, worker 大域スコープclose 中かは true にする Closing orphan workers: Start monitoring the worker such that no sooner than it stops being a protected worker, and no later than it stops being a permissible worker, worker global scope's closing flag is set to true.
      • worker の休止次が満たされるようになったときは、 満たされなくなるまで,worker 内のスクリプトの実行を休止する :worker 大域スコープclose 中か false ][ worker は休止可能である ] Suspending workers: Start monitoring the worker, such that whenever worker global scope's closing flag is false and the worker is a suspendable worker, the user agent suspends execution of script in that worker until such time as either the closing flag switches to true or the worker stops being a suspendable worker.
    8. 内側設定群実行は準備済みか ← true Set inside settings's execution ready flag.
    9. スクリプト に応じて:

      If script is a classic script, then run the classic script script. Otherwise, it is a module script; run the module script script.

      注記: 通例の[ 値を返す, 例外による失敗 ]に加えて,これは、 worker が終了されたときも尚早に中止され得る。 In addition to the usual possibilities of returning a value or failing due to an exception, this could be prematurely aborted by the terminate a worker algorithm defined below.

    10. 外側ポートポートメッセージキューを可能化する Enable outside port's port message queue.
    11. IF共用か false ] :worker の暗黙的なポート内側ポートポートメッセージキューを可能化する If is shared is false, enable the port message queue of the worker's implicit port.
    12. ELSE大域タスクをキューする( DOM 操作タスクソース, worker 大域スコープ, 次の手続き )

      手続きは :イベントを発火する( worker 大域スコープ, connect, MessageEvent ) — 次のように初期化して :data 属性 ← 空文字列, ports 属性 ← 内側ポート のみを包含している新たな凍結配列, source 属性 ← 内側ポート
      If is shared is true, then queue a global task on DOM manipulation task source given worker global scope to fire an event named connect at worker global scope, using MessageEvent, with the data attribute initialized to the empty string, the ports attribute initialized to a new frozen array containing inside port, and the source attribute initialized to inside port.
    13. worker 大域スコープ関連する設定群オブジェクトを,service worker クライアントとして結び付けている ServiceWorkerContainer オブジェクト ]のクライアントメッセージキューを可能化する Enable the client message queue of the ServiceWorkerContainer object whose associated service worker client is worker global scope's relevant settings object.
    14. 内側設定群 により指定される担当のイベントループ ]を,破壊されるまで走らす Event loop: Run the responsible event loop specified by inside settings until it is destroyed.

      注記: イベントループが走らすタスクによる,イベントの取り扱いや callback の実行は、 worker が終了されたときは,尚早に中止され得る。 The handling of events or the execution of callbacks by tasks run by the event loop might get prematurely aborted by the terminate a worker algorithm defined below.

      注記: この段における worker の処理モデルは、 イベントループ処理モデルに述べられるとおり,[ close 中かが true にされた後の,イベントループが破壊される ]まで残り続ける。 The worker processing model remains on this step until the event loop is destroyed, which happens after the closing flag is set to true, as described in the event loop processing model.

    15. worker 大域スコープ作動中なタイマー群が成すマップクリアする Clear the worker global scope's map of active timers.
    16. worker 大域スコープポートリストを成す ( ポート ) に対し :ポート連絡を断つ Disentangle all the ports in the list of the worker's ports.
    17. worker 大域スコープ所有者集合を空にする Empty worker global scope's owner set.

UA が worker を終了させ るときは、 worker のメインループ — すなわち,上で定義した “worker を走らす” 処理モデル — とは並列的に,次の手続きを走らすものとする: When a user agent is to terminate a worker, it must run the following steps in parallel with the worker's main loop (the "run a worker" processing model defined above):

  1. worker 大域スコープ :← 当の worker の WorkerGlobalScope オブジェクト
  2. worker 大域スコープclose 中か ← true Set the worker's WorkerGlobalScope object's closing flag to true.
  3. worker 大域スコープ関連する agentイベントループタスクキューを成す ( タスク タスク ) に対し :タスク を処理することなく,破棄する【当のタスクキューから除去する】 If there are any tasks queued in the WorkerGlobalScope object's relevant agent's event loop's task queues, discard them without processing them.
  4. worker 内で現在走っているスクリプトを中止する Abort the script currently running in the worker.
  5. IFworker 大域スコープDedicatedWorkerGlobalScope オブジェクトである (すなわち,worker は専用 worker である) ] :worker の暗黙的なポートworker 大域スコープ内側ポートポートメッセージキューを空にする If the worker's WorkerGlobalScope object is actually a DedicatedWorkerGlobalScope object (i.e. the worker is a dedicated worker), then empty the port message queue of the port that the worker's implicit port is entangled with.

UA は、 ↓ を満たす worker を終了させてもよい:

User agents may invoke the terminate a worker algorithm when a worker stops being an active needed worker and the worker continues executing even after its closing flag was set to true.

10.2.5. 稼働時のスクリプトエラー

worker のスクリプトにおいて, catch されない稼働時のスクリプトエラーが生じた場合、 それは[ それまでにスクリプトエラーを取り扱う間に生じたもの ]でないならば、 UA は,次を遂行することになる :例外を報告する( 当のエラー, 当の worker の WorkerGlobalScope オブジェクト ) Whenever an uncaught runtime script error occurs in one of the worker's scripts, if the error did not occur while handling a previous script error, the user agent will report it for the worker's WorkerGlobalScope object.

10.2.6. worker の作成法

10.2.6.1. AbstractWorker mixin
interface mixin AbstractWorker {
  attribute EventHandler onerror;
};

AbstractWorker インタフェースを実装するオブジェクトにおいては、 次に挙げるイベントハンドラ(および,それらに対応するイベントハンドライベント型)をイベントハンドラ IDL 属性としてサポートするものとする: The following are the event handlers (and their corresponding event handler event types) that must be supported, as event handler IDL attributes, by objects implementing the AbstractWorker interface:

イベントハンドラ イベントハンドライベント型
onerror error
10.2.6.2. worker 用のスクリプト設定群

worker の環境設定群オブジェクトを設定しておく アルゴリズムは、 所与の ( JavaScript 実行文脈 実行文脈, 環境設定群オブジェクト 外側設定群, 数 安全でない worker 作成時刻 ) に対し: To set up a worker environment settings object, given a JavaScript execution context execution context, an environment settings object outside settings, and a number unsafeWorkerCreationTime:

  1. 継承した生成元 :← 外側設定群生成元 Let inherited origin be outside settings's origin.
  2. realm :← 実行文脈 の Realm 成分の値 Let realm be the value of execution context's Realm component.
  3. worker 大域スコープ :← realm大域オブジェクト Let worker global scope be realm's global object.
  4. 設定群オブジェクト :← 新たな環境設定群オブジェクト — その各種アルゴリズムは、 次に従って定義される: Let settings object be a new environment settings object whose algorithms are defined as follows:

  5. 設定群オブジェクト の :ID ← 新たな一意かつ不透明な文字列, 作成時の URLworker 大域スコープURL , トップレベル作成時の URL ← null , ターゲット閲覧文脈 ← null , 作動中な service worker ← null Set settings object's id to a new unique opaque string, creation URL to worker global scope's url, top-level creation URL to null, target browsing context to null, and active service worker to null.
  6. 設定群オブジェクトトップレベル生成元worker 大域スコープ に応じて :DedicatedWorkerGlobalScope オブジェクトであるならば 外側設定群トップレベル生成元 / 他の場合は 実装定義な値 If worker global scope is a DedicatedWorkerGlobalScope object, then set settings object's top-level origin to outside settings's top-level origin.Otherwise, set settings object's top-level origin to an implementation-defined value.

    これを適正に定義している最新情報は、 クライアント側ストレージ仕切り法を見よ。 See Client-Side Storage Partitioning for the latest on properly defining this.

  7. realm[[HostDefined]] フィールド ← 設定群オブジェクト Set realm's [[HostDefined]] field to settings object.
  8. RETURN 設定群オブジェクト Return settings object.
10.2.6.3. 専用 worker と Worker インタフェース
[Exposed=(Window,DedicatedWorker,SharedWorker)]
interface Worker : EventTarget {
  constructor((TrustedScriptURL or USVString) scriptURL, optional WorkerOptions options = {});

  undefined terminate();

  undefined postMessage(any message, sequence<object> transfer);
  undefined postMessage(any message, optional StructuredSerializeOptions options = {});
};

dictionary WorkerOptions {
  WorkerType type = "classic";
  RequestCredentials credentials = "same-origin"; // †
  DOMString name = "";
};

enum WorkerType { "classic", "module" };

Worker includes AbstractWorker;
Worker includes MessageEventTarget;

注記:† credentials資格情報)は、[ type種別 "module" ]の場合に限り,利用される。 credentials is only used if type is "module"

worker = new Worker(scriptURL [, options ])
新たな Worker オブジェクトを返す。 scriptURL はバックグラウンドで fetch され, 実行され、 新たな大域環境が作成される。 返される worker は、 その大域環境への通信チャネルを表現する。 Returns a new Worker object. scriptURL will be fetched and executed in the background, creating a new global environment for which worker represents the communication channel.\

options を利用すれば: options can be used to\

  • name メンバを介して この大域環境の名前を定義できる — これは主として、 デバッグ目的にある。 define the name of that global environment via the name option, primarily for debugging purposes.\
  • type メンバに "module" を指定すれば、 この新たな大域環境が JavaScript モジュールをサポートすることを確保できる — その場合、 credentials メンバを通して, scriptURL がどう fetch されるかも指定できる。 It can also ensure this new global environment supports JavaScript modules (specify type: "module"), and if that is specified, can also be used to specify how scriptURL is fetched through the credentials option.
worker.terminate()
worker に結び付けられた大域環境を中止する。 Aborts worker's associated global environment.
worker.postMessage(message, transfer)
worker.postMessage(message [, options ])
message をクローンして worker の大域環境へ伝送する。 [ transfer / [ optionstransfer メンバ ]]には,一連のオブジェクトからなるリストを渡すことができ、 それらはクローンされずに転送される。 Clones message and transmits it to worker's global environment. transfer can be passed as a list of objects that are to be transferred rather than cloned.

Worker オブジェクトには、 外側ポート が結び付けられる — それは: Each Worker object has an associated outside port\

  • MessagePort オブジェクトである。 (a MessagePort).\
  • 当の worker 作成時に設定しておかれるチャネルの一部を成すが,公開されない。 This port is part of a channel that is set up when the worker is created, but it is not exposed.\
  • 当の Worker オブジェクトより先にガーベジ収集されてはならない。 This object must never be garbage collected before the Worker object.
terminate() メソッド手続きは :これ°を結び付けている worker 上で worker を終了させThe terminate() method, when invoked, must cause the terminate a worker algorithm to be run on the worker with which the object is associated.

postMessage(message, transfer) メソッド手続きは :RETURN これ°外側ポート上の postMessage メソッド手続き( message, transfer )

postMessage(message, options) メソッド手続きは :RETURN これ°外側ポート上の postMessage メソッド手続き( message, options )

The postMessage(message, transfer) and postMessage(message, options) methods on Worker objects act as if, when invoked, they immediately invoked the respective postMessage(message, transfer) and postMessage(message, options) on this's outside port, with the same arguments, and returned the same return value.

このメソッドの message 引数は有構造データでもよい: The postMessage() method's first argument can be structured data:

worker.postMessage({
   opcode: 'activate',
   device: 1938,
   parameters: [23, 102]
});

new Worker(scriptURL, options) 構築子手続きは: When the Worker(scriptURL, options) constructor is invoked, the user agent must run the following steps:

  1. 準拠するスクリプト URL :← 信用済みな型に準拠する文字列を取得する( ↓ ) :TrustedScriptURL, これ°関連する大域オブジェクト, scriptURL, "Worker constructor", "script" Let compliantScriptURL be the result of invoking the Get Trusted Type compliant string algorithm with TrustedScriptURL, this's relevant global object, scriptURL, "Worker constructor", and "script".
  2. 外側設定群 :← 現在の設定群オブジェクト Let outside settings be the current settings object.
  3. worker URL :← URL を符号化法の下で相対的に構文解析する( 準拠するスクリプト URL , 外側設定群 ) Let worker URL be the result of encoding-parsing a URL given compliantScriptURL, relative to outside settings.

    注記: blob: URL も含め,同一生成元であれば どの URL も利用できる。 data: URL も利用できるが、 作成される worker には不透明な生成元が伴われることになる。 Any same-origin URL (including blob: URLs) can be used. data: URLs can also be used, but they create a worker with an opaque origin.

  4. IFworker URL 失敗 ] :THROW SyntaxError If worker URL is failure, then throw a "SyntaxError" DOMException.
  5. 外側ポート :← 新たなオブジェクト( MessagePort, 外側設定群realm ) Let worker be a new Worker object.Let outside port be a new MessagePort in outside settings's realm.
  6. 外側ポートメッセージイベントターゲットこれ° Set outside port's message event target to worker.
  7. これ°外側ポート外側ポート Set worker's outside port to outside port.
  8. この段は、 並列的に走らす :worker を走らす( ↓ ) :これ°, worker URL , 外側設定群, 外側ポート, options Run this step in parallel: • Run a worker given worker, worker URL, outside settings, outside port, and options.Return worker.
10.2.6.4. 共用 worker と SharedWorker インタフェース
[Exposed=Window]
interface SharedWorker : EventTarget {
  constructor((TrustedScriptURL or USVString) scriptURL, optional (DOMString or WorkerOptions) options = {});

  readonly attribute MessagePort port;
};
SharedWorker includes AbstractWorker;
sharedWorker = new SharedWorker(scriptURL [, name ])
新たな SharedWorker オブジェクトを返す。 scriptURL はバックグラウンドで fetch され, 実行され、 新たな大域環境が作成される。 返される sharedWorker は、 その大域環境への通信チャネルを表現する。 name を利用すれば,その大域環境の名前を定義できる。 Returns a new SharedWorker object. scriptURL will be fetched and executed in the background, creating a new global environment for which sharedWorker represents the communication channel. name can be used to define the name of that global environment.
sharedWorker = new SharedWorker(scriptURL [, options ])
新たな SharedWorker オブジェクトを返す。 scriptURL はバックグラウンドで fetch され, 実行され、 新たな大域環境が作成される。 返される sharedWorker は、 その大域環境への通信チャネルを表現する。 Returns a new SharedWorker object. scriptURL will be fetched and executed in the background, creating a new global environment for which sharedWorker represents the communication channel.\

options を利用すれば: options can be used to\

  • name メンバを介して この大域環境の名前を定義できる。 define the name of that global environment via the name option.\
  • type メンバに "module" を指定すれば、 この新たな大域環境が JavaScript モジュールをサポートすることを確保できる — その場合、 credentials メンバを通して, scriptURL がどう fetch されるかも指定できる。 It can also ensure this new global environment supports JavaScript modules (specify type: "module"), and if that is specified, can also be used to specify how scriptURL is fetched through the credentials option.\

options の[ typecredentials ]いずれかのメンバに既存の共用 worker の[ 種別資格情報 ]と合致しない値を与える下で,共用 worker を構築しようと試みた場合、 返される SharedWorker に向けて error イベントを発火させ,既存の共用 worker には接続されないことに注意。 Note that attempting to construct a shared worker with options whose type or credentials values mismatch an existing shared worker will cause the returned sharedWorker to fire an error event and not connect to the existing shared worker.

sharedWorker.port
sharedWorkerMessagePort オブジェクトを返す。 それを利用して大域環境と通信できる。 Returns sharedWorker's MessagePort object which can be used to communicate with the global environment.

port 取得子手続きは :RETURN これ°の構築子によりあてがわれた値【すなわち, 外側ポート The port attribute must return the value it was assigned by the object's constructor.\

返される値は、 共用 worker と通信するための MessagePort を表現する。 It represents the MessagePort for communicating with the shared worker.

UA には 共用 worker 管理器 が結び付けられる — 初期時は、 次の結果とする :新たな並列キューを開始する() A user agent has an associated shared worker manager which is the result of starting a new parallel queue.

注記: 単純にするため、 各 UA に結び付けられる共用 worker 管理器は 1 個だけとする。 実装は、 生成元ごとに 1 個ずつ利用して,同時並行性を高めることもできる — その相違は、 観測され得ないので。 Each user agent has a single shared worker manager for simplicity. Implementations could use one per origin; that would not be observably different and enables more concurrency.

new SharedWorker(scriptURL, options) 構築子手続きは: When the SharedWorker(scriptURL, options) constructor is invoked:

  1. 準拠するスクリプト URL :← 信用済みな型に準拠する文字列を取得する( ↓ ) :TrustedScriptURL, これ°関連する大域オブジェクト, scriptURL, "SharedWorker constructor", "script" Let compliantScriptURL be the result of invoking the Get Trusted Type compliant string algorithm with TrustedScriptURL, this's relevant global object, scriptURL, "SharedWorker constructor", and "script".
  2. IFoptionsDOMString である ] :options ← 新たな WorkerOptions 辞書 — その :name メンバ ← options の値; 他のメンバ ← 各自の既定値 If options is a DOMString, set options to a new WorkerOptions dictionary whose name member is set to the value of options and whose other members are set to their default values.
  3. 外側設定群 :← 現在の設定群オブジェクト Let outside settings be the current settings object.
  4. URL レコード :← URL を符号化法の下で相対的に構文解析する( 準拠するスクリプト URL , 外側設定群 ) Let urlRecord be the result of encoding-parsing a URL given compliantScriptURL, relative to outside settings.

    注記: blob: URL も含め,同一生成元であれば どの URL も利用できる。 data: URL も利用できるが、 作成される worker には不透明な生成元が伴われることになる。 Any same-origin URL (including blob: URLs) can be used. data: URLs can also be used, but they create a worker with an opaque origin.

  5. IFURL レコード 失敗 ] :THROW SyntaxError If urlRecord is failure, then throw a "SyntaxError" DOMException.
  6. 外側ポート :← 新たなオブジェクト( MessagePort, 外側設定群realm ) Let worker be a new SharedWorker object.Let outside port be a new MessagePort in outside settings's realm.
  7. これ°port 属性 ← 外側ポート Assign outside port to the port attribute of worker.
  8. call 元はセキュアな文脈か :← IS外側設定群セキュアな文脈である ] Let callerIsSecureContext be true if outside settings is a secure context; otherwise, false.
  9. 外側ストレージ key :← 非ストレージ目的用にストレージ key を得る( 外側設定群 ) Let outside storage key be the result of running obtain a storage key for non-storage purposes given outside settings.
  10. 共用 worker 管理器に 次の手続きをエンキューするEnqueue the following steps to the shared worker manager:

    1. worker 大域スコープ :← null Let worker global scope be null.
    2. すべての SharedWorkerGlobalScope オブジェクトからなるリストを成す ( スコープ ) に対し: For each scope in the list of all SharedWorkerGlobalScope objects:

      1. worker ストレージ key :← 非ストレージ目的用にストレージ key を得る( スコープ関連する設定群オブジェクト ) Let worker storage key be the result of running obtain a storage key for non-storage purposes given scope's relevant settings object.
      2. IF↓ ]… If all of the following are true:

        • ( worker ストレージ key , 外側ストレージ key ) は同等なストレージ key である worker storage key equals outside storage key;
        • スコープclose 中か false scope's closing flag is false;
        • ( スコープ構築子 URL , URL レコード ) は同等な URL である scope's constructor url equals urlRecord; and
        • スコープ名前 options[ "name" ] scope's name equals the value of options's name member,

        …ならば: then:

        1. worker 大域スコープスコープ Set worker global scope to scope.
        2. BREAK Break.

      注記: data: URL は、 不透明な生成元が伴われる worker を作成することになる。 構築子生成元, 構築子 URL の両者とも比較されるので,同じ data: URL を利用して ある生成元の中で同じ SharedWorkerGlobalScope オブジェクトを取得できるが、 同一生成元の制約を迂回することはできない。 data: URLs create a worker with an opaque origin. Both the constructor origin and constructor url are compared so the same data: URL can be used within an origin to get to the same SharedWorkerGlobalScope object, but cannot be used to bypass the same origin restriction.

      【 この段には、 反復順序が指定されていない — 条件を満たす スコープ が複数ある場合、 どれが選ばれるかは実装定義になる。 】

    3. IFworker 大域スコープ null ]:

      1. IF[ UA は、[ worker 大域スコープ が表現する worker と[ スクリプトのうち[ その設定群オブジェクト 外側設定群 ]を満たすもの ]との間の通信 ]を許容しないよう環境設定されている ] :worker 大域スコープ ← null If worker global scope is not null, but the user agent has been configured to disallow communication between the worker represented by the worker global scope and the scripts whose settings object is outside settings, then set worker global scope to null.

        注記: 例えば、 次のようなときが該当する :UA は開発モード下にあり, そこでは ある特定のトップレベル辿り可能が 他のすべてのページから隔離されていて、 その開発モード下のスクリプトから[ 通常の閲覧モードで走っている worker ]へ接続することは阻止されている。 For example, a user agent could have a development mode that isolates a particular top-level traversable from all other pages, and scripts in that development mode could be blocked from connecting to shared workers running in the normal browser mode.

      2. ELSE IFworker 大域スコープ種別 options[ "type" ] ]worker 大域スコープ資格情報 options[ "credentials" ] ]:

        1. タスクをキューする( DOM 操作タスクソース?】, 次の手続き )

          手続きは :イベントを発火する( これ°, error )
        2. RETURN
        If worker global scope is not null, then check if worker global scope's type and credentials match the options values. If not, queue a task to fire an event named error and abort these steps.
    4. IFworker 大域スコープ null ]: If worker global scope is not null, then run these subsubsteps:

      1. 設定群オブジェクト :← worker 大域スコープ関連する設定群オブジェクト Let settings object be the relevant settings object for worker global scope.
      2. worker はセキュアな文脈か :← IS設定群オブジェクトセキュアな文脈である ] Let workerIsSecureContext be true if settings object is a secure context; otherwise, false.
      3. IFworker はセキュアな文脈か call 元はセキュアな文脈か ]:

        1. タスクをキューする( DOM 操作タスクソース?】, 次の手続き )

          手続きは :イベントを発火する( これ°, error )
        2. RETURN
        [SECURE-CONTEXTS] If workerIsSecureContext is not callerIsSecureContext, then queue a task to fire an event named error at worker and abort these steps. [SECURE-CONTEXTS]
      4. これ°worker 大域スコープ に結び付ける Associate worker with worker global scope.
      5. 内側ポート :← 新たなオブジェクト( MessagePort, 設定群オブジェクトrealm ) Let inside port be a new MessagePort in settings object's realm.
      6. ポートを連絡する( 外側ポート, 内側ポート ) Entangle outside port and inside port.
      7. タスクをキューする( DOM 操作タスクソース, 次の手続き )

        手続きは :イベントを発火する( worker 大域スコープ, connect, MessageEvent ) — 次のように初期化して :data 属性 ← 空文字列, ports 属性 ← 内側ポート のみを包含している新たな凍結配列, source 属性 ← 内側ポート
        Queue a task, using the DOM manipulation task source, to fire an event named connect at worker global scope, using MessageEvent, with the data attribute initialized to the empty string, the ports attribute initialized to a new frozen array containing only inside port, and the source attribute initialized to inside port.
      8. worker 大域スコープ所有者集合に[ 外側設定群 から与えられる,関連する所有者として追加するもの ]を付加する Append the relevant owner to add given outside settings to worker global scope's owner set.
    5. ELSE次を並列的に走らす :worker を走らす( ↓ ) :これ°, URL レコード, 外側設定群, 外側ポート, options Otherwise, in parallel, run a worker given worker, urlRecord, outside settings, outside port, and options.

    Return worker.

10.3. worker から可用な API

10.3.1. スクリプト/ライブラリの import 法

WorkerGlobalScope オブジェクトの importScripts(...urls) メソッド手続きは: The importScripts(...urls) method steps are:

  1. URL 文字列群 :← « » Let urlStrings be « ».
  2. urls を成す ( URL ) に対し: For each url of urls:

    1. URL 文字列群 に次の結果を付加する信用済みな型に準拠する文字列を取得する( ↓ ) :TrustedScriptURL, これ°関連する大域オブジェクト, URL , "WorkerGlobalScope importScripts", "script" Append the result of invoking the Get Trusted Type compliant string algorithm with TrustedScriptURL, this's relevant global object, url, "WorkerGlobalScope importScripts", and "script" to urlStrings.
  3. スクリプトを worker 大域スコープの中へ import する( これ°, URL 文字列群 ) Import scripts into worker global scope given this and urlStrings.

スクリプトを worker 大域スコープの中へ import する アルゴリズムは、 所与の :WorkerGlobalScope オブジェクト worker 大域スコープ, スカラー値文字列リスト URL 群, fetch フックを遂行するアルゴリズム fetch を遂行する(省略時は ε ) に対し: To import scripts into worker global scope, given a WorkerGlobalScope object worker global scope, a list of scalar value strings urls, and an optional perform the fetch hook performFetch:

  1. IFworker 大域スコープ種別 "module" ] :THROW TypeError If worker global scope's type is "module", throw a TypeError exception.
  2. 設定群オブジェクト :← 現在の設定群オブジェクト Let settings object be the current settings object.
  3. IFURL 群 は空である ] :RETURN If urls is empty, return.
  4. URL レコード群 :← « » Let urlRecords be « ».
  5. URL 群 を成す ( URL 文字列 ) に対し: For each url of urls:

    1. URL レコードURL を符号化法の下で相対的に構文解析する( URL 文字列, 設定群オブジェクト ) Let urlRecord be the result of encoding-parsing a URL given url, relative to settings object.
    2. IFURL レコード 失敗 ] :THROW SyntaxError If urlRecord is failure, then throw a "SyntaxError" DOMException.
    3. URL レコード群URL レコード を付加する Append urlRecord to urlRecords.
  6. URL レコード群 を成す ( URL レコード ) に対し: For each urlRecord of urlRecords:

    1. スクリプト :← worker が import した古典スクリプトを fetch する( URL レコード, 設定群オブジェクト, fetch を遂行する ) (この段は、 例外を投出し得る) Fetch a classic worker-imported script given urlRecord and settings object, passing along performFetch if provided. If this succeeds, let script be the result. Otherwise, rethrow the exception.
    2. 古典スクリプトを走らす( スクリプト, エラーは再投出するか ← true ) Run the classic script script, with the rethrow errors argument set to true.

      注記: スクリプトは、 次のいずれかが生じるまで走らすことになる :普通に返った/ 構文解析に失敗した/ 投出された例外を catch しなかった/ worker が終了されたため,尚早に中止されscript will run until it either returns, fails to parse, fails to catch an exception, or gets prematurely aborted by the terminate a worker algorithm defined above.

      [ スクリプトから例外が投出された / スクリプトは尚早に中止された ]ときは 【普通に返らなかった場合】この手続きすべてを中止した上で、 call 元のスクリプトにて,その[ 例外/中止 ]の処理を継続させる If an exception was thrown or if the script was prematurely aborted, then abort all these steps, letting the exception or aborting continue to be processed by the calling script.

注記: Service Workers [SW] は、 自前の fetch フックを遂行するアルゴリズムを与えて このアルゴリズムを走らす仕様の例である。 Service Workers is an example of a specification that runs this algorithm with its own perform the fetch hook. [SW]

10.3.2. WorkerNavigator インタフェース

WorkerGlobalScope インタフェースの navigator 取得子手続きは、 UA (クライアント)の同一性と状態を表現する, WorkerNavigator インタフェースのインスタンスを返す。 The navigator attribute of the WorkerGlobalScope interface must return an instance of the WorkerNavigator interface, which represents the identity and state of the user agent (the client):
[Exposed=Worker]
interface WorkerNavigator {};
WorkerNavigator includes NavigatorID;
WorkerNavigator includes NavigatorLanguage;
WorkerNavigator includes NavigatorOnLine;
WorkerNavigator includes NavigatorConcurrentHardware;

10.3.3. WorkerLocation インタフェース

[Exposed=Worker]
interface WorkerLocation {
  stringifier readonly attribute USVString href;
  readonly attribute USVString origin;
  readonly attribute USVString protocol;
  readonly attribute USVString host;
  readonly attribute USVString hostname;
  readonly attribute USVString port;
  readonly attribute USVString pathname;
  readonly attribute USVString search;
  readonly attribute USVString hash;
};

WorkerGlobalScope オブジェクトは、 worker 所在オブジェクト を有する — それは、 ある WorkerLocation オブジェクトであり,初期時は ε とする。 A WorkerLocation object has an associated WorkerGlobalScope object (a WorkerGlobalScope object).

【 これらのオブジェクトは、 一対一に対応する。 】【 初期値 ε は、 形式上のものであり,アクセスされ得ない — location の注記を見よ。 】

この節を通して、 URL は,[ worker 所在オブジェクトとして当の WorkerLocation オブジェクトを有している WorkerGlobalScope オブジェクト ]の URL を指すとする。

href 取得子手続きは :RETURN URL を直列化する( URL ) The href getter steps are to return this's WorkerGlobalScope object's url, serialized.
origin 取得子手続きは :RETURN 生成元を直列化する( URL生成元 ) The origin getter steps are to return the serialization of this's WorkerGlobalScope object's url's origin.
protocol 取得子手続きは :RETURN 次を順に連結するURLスキーム, ":" The protocol getter steps are to return this's WorkerGlobalScope object's url's scheme, followed by ":".

host 取得子手続きは:

  1. ホスト :← URLホスト
  2. IFホスト null ] :RETURN 空文字列
  3. ホスト :← ホストを直列化する( ホスト )
  4. ポート :← URLポート
  5. IFポート null ] :RETURN ホスト
  6. ポート整数を直列化する( ポート )
  7. RETURN 次を順に連結するホスト, ":", ポート

The host getter steps are: • Let url be this's WorkerGlobalScope object's url. • If url's host is null, return the empty string. • If url's port is null, return url's host, serialized. • Return url's host, serialized, followed by ":" and url's port, serialized.

hostname 取得子手続きは: The hostname getter steps are:

  1. ホスト :← URLホスト Let host be this's WorkerGlobalScope object's url's host.
  2. IFホスト null ] :RETURN 空文字列 If host is null, return the empty string.
  3. RETURN ホストを直列化する( ホスト ) Return host, serialized.

port 取得子手続きは: The port getter steps are:

  1. ポート :← URLポート Let port be this's WorkerGlobalScope object's url's port.
  2. IFポート null ] :RETURN 空文字列 If port is null, return the empty string.
  3. RETURN 整数を直列化する( ポート ) Return port, serialized.
pathname 取得子手続きは :RETURN URL パスを直列化する( URL ) The pathname getter steps are to return the result of URL path serializing this's WorkerGlobalScope object's url.

search 取得子手続きは: The search getter steps are:

  1. クエリ :← URLクエリ Let query be this's WorkerGlobalScope object's url's query.
  2. IFクエリ { null , 空文字列 } ] :RETURN 空文字列 If query is either null or the empty string, return the empty string.
  3. RETURN 次を順に連結する"?", クエリ Return "?", followed by query.

hash 取得子手続きは: The hash getter steps are:

  1. 素片 :← URL素片 Let fragment be this's WorkerGlobalScope object's url's fragment.
  2. IF素片 { null , 空文字列 } ] :RETURN 空文字列 If fragment is either null or the empty string, return the empty string.
  3. RETURN 次を順に連結する"#", 素片 Return "#", followed by fragment.