1. 10 ウェブワーカー
    1. 10.1 導入
      1. 10.1.1 範囲
      2. 10.1.2
        1. 10.1.2.1 バックグラウンドで計算処理を行うワーカー
        2. 10.1.2.2 JavaScriptモジュールをワーカーとして使用する
        3. 10.1.2.3 共有ワーカーの紹介
        4. 10.1.2.4 共有ワーカーを使用した共有状態
        5. 10.1.2.5 委譲
        6. 10.1.2.6 ライブラリの提供
      3. 10.1.3 チュートリアル
        1. 10.1.3.1 専用ワーカーの作成
        2. 10.1.3.2 専用ワーカーとの通信
        3. 10.1.3.3 共有ワーカー
    2. 10.2 インフラ
      1. 10.2.1 グローバルスコープ
        1. 10.2.1.1 WorkerGlobalScope共通インターフェイス
        2. 10.2.1.2 専用ワーカーおよびDedicatedWorkerGlobalScopeインターフェイス
        3. 10.2.1.3 共有ワーカーおよびSharedWorkerGlobalScopeインターフェイス
      2. 10.2.2 イベントループ
      3. 10.2.3 The worker's lifetime
      4. 10.2.4 Processing model
      5. 10.2.5 ランタイムスクリプトエラー
      6. 10.2.6 ワーカーの作成
        1. 10.2.6.1 AbstractWorkerミックスイン
        2. 10.2.6.2 Script settings for workers
        3. 10.2.6.3 専用ワーカーおよびWorkerインターフェイス
        4. 10.2.6.4 共有ワーカーおよびSharedWorkerインターフェイス
      7. 10.2.7 同時ハードウェア機能
    3. 10.3 ワーカーが使用可能なAPI
      1. 10.3.1 Importing scripts and libraries
      2. 10.3.2 WorkerNavigatorインターフェイス
      3. 10.3.2 WorkerLocationインターフェイス

10 ウェブワーカー

Web_Workers_API

Support in all current engines.

Firefox3.5+Safari4+Chrome2+
Opera10.6+Edge79+
Edge (Legacy)12+Internet Explorer10+
Firefox Android?Safari iOS5+Chrome Android?WebView Android?Samsung Internet?Opera Android11+

Web_Workers_API/Using_web_workers

10.1 導入

10.1.1 範囲

この節は非規範的である。

この仕様は、ユーザインタフェースのスクリプトとは独立して、バックグラウンドでスクリプトを実行するためのAPIを定義する。

これにより、クリックまたはその他のユーザー操作に応答するスクリプトによって中断されない長時間実行スクリプトが可能になり、ページの応答性を維持するために譲歩することなく長時間のタスクを実行できる。

ワーカー(ここではこれらのバックグラウンドスクリプトと呼ぶ)は、比較的重いものであり、大量に使用することは想定されていない。たとえば、4メガピクセルの画像の各ピクセルに対して1つのワーカーを起動するのは不適切である。次節の例では、ワーカーの適切な使用法を示している。

一般に、ワーカーは寿命が長く、起動時のパフォーマンスコストが高く、インスタンスごとのメモリコストが高いと予想される。

10.1.2

この節は非規範的である。

ワーカーにはさまざまな用途がある。次のサブセクションでは、この用途のさまざまな例を示す。

10.1.2.1 バックグラウンドで計算処理を行うワーカー

この節は非規範的である。

ワーカーの最も簡単な用法は、ユーザーインターフェイスを中断することなく、計算コストの高いタスクを実行することである。

この例では、メイン文書がワーカーを生成して(単純に)素数を計算し、最近検出された素数を順を追って表示する。

メインページは次のとおりである:

<!DOCTYPE HTML>
<html lang="en">
 <head>
  <meta charset="utf-8">
  <title>Worker example: One-core computation</title>
 </head>
 <body>
  <p>The highest prime number discovered so far is: <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()コンストラクターの呼び出しは、ワーカーを作成し、そのワーカーを表すWorkerオブジェクトを返す。このオブジェクトは、ワーカーとの通信に使用される。そのオブジェクトのonmessageイベントハンドラーによって、コードはワーカーからメッセージを受け取ることができる。

ワーカー自体は次のとおりである:

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()メソッドは、素数が見つかったときにメッセージをページに送り返すために使用される。

この例をオンラインで見る

10.1.2.2 JavaScriptモジュールをワーカーとして使用する

この節は非規範的である。

これまでの例はすべて、クラシックスクリプトを実行するワーカーを示している。代わりに、ワーカーはモジュールスクリプトを使用してインスタンス化することができる。これには、JavaScript importステートメントを使用して他のモジュールをインポートする機能、デフォルトのstrictモード、ワーカーのグローバルスコープを汚染しないトップレベルの宣言など、通常の利点がある。

importステートメントが使用可能であるため、importScripts()メソッドはモジュールワーカー内で自動的に失敗する。

この例では、メイン文書はワーカーを使用してメインスレッド以外の画像操作を行う。これは、別のモジュールで使用されているフィルターをインポートする。

メインページは次のとおりである:

<!DOCTYPE html>
<html lang="en">
<meta charset="utf-8">
<title>Worker example: image decoding</title>

<p>
  <label>
    Type an image URL to decode
    <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>
    Choose a filter to apply
    <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>

ワーカーファイルは次のようになる:

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をインポートするもの:

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]];

    // 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;
  }
};

この例をオンラインで見る

10.1.2.3 共有ワーカーの紹介

SharedWorker

Support in all current engines.

Firefox29+Safari16+Chrome5+
Opera10.6+Edge79+
Edge (Legacy)?Internet ExplorerNo
Firefox Android33+Safari iOS16+Chrome AndroidNoWebView Android?Samsung Internet4.0–5.0Opera Android11–14

この節は非規範的である。

この節では、Hello Worldの例を使用して共有ワーカーを紹介する。共有ワーカーは、各ワーカーが複数の接続を持つことができるため、わずかに異なるAPIを使用する。

この最初の例では、ワーカーに接続する方法と、ワーカーが接続したときにページにメッセージを送り返す方法を示す。受信したメッセージはログに表示される。

HTMLページは次のとおり:

<!DOCTYPE HTML>
<html lang="en">
<meta charset="utf-8">
<title>Shared workers: demo 1</title>
<pre id="log">Log:</pre>
<script>
  var worker = new SharedWorker('test.js');
  var log = document.getElementById('log');
  worker.port.onmessage = function(e) { // note: not worker.onmessage!
    log.textContent += '\n' + e.data;
  }
</script>

JavaScriptワーカーは次のとおり:

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

この例をオンラインで見る


この2番目の例は最初の例を拡張したもので、2つの点を変更している。1つ目は、イベントハンドラーIDL属性の代わりにaddEventListener()を使用してメッセージを受信すること、2つ目は、メッセージをワーカー送信して、ワーカーに別のメッセージを送信させることである。受信したメッセージは再びログに表示される。

HTMLページは次のとおり:

<!DOCTYPE HTML>
<html lang="en">
<meta charset="utf-8">
<title>Shared workers: demo 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(); // note: need this when using addEventListener
  worker.port.postMessage('ping');
</script>

JavaScriptワーカーは次のとおり:

onconnect = function(e) {
  var port = e.ports[0];
  port.postMessage('Hello World!');
  port.onmessage = function(e) {
    port.postMessage('pong'); // not e.ports[0].postMessage!
    // e.target.postMessage('pong'); would work also
  }
}

この例をオンラインで見る


最後に、この例を拡張して、2つのページが同じワーカーに接続する方法を示す。この場合、2番目のページは最初のページのiframe内にあるだけだが、同じ原則が別のトップレベルのトラバース可能内のまったく別のページにも適用される。

次に外部HTMLページを示す:

<!DOCTYPE HTML>
<html lang="en">
<meta charset="utf-8">
<title>Shared workers: demo 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ページを示す:

<!DOCTYPE HTML>
<html lang="en">
<meta charset="utf-8">
<title>Shared workers: demo 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ワーカーは次のとおり:

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');
  }
}

この例をオンラインで見る

10.1.2.4 共有ワーカーを使用した共有状態

この節は非規範的である。

この例では、すべて同じマップを表示する複数のウィンドウ(ビューアー)を開くことができる。すべてのウィンドウは同じマップ情報を共有し、1つのワーカーがすべてのビューアーを調整する。各ビューアーは独立して移動できるが、マップ上にデータを設定する場合、すべてのビューアーが更新される。

メインページは興味深くはなく、単にビューアーを開く方法を提供しているだけである:

<!DOCTYPE HTML>
<html lang="en">
 <head>
  <meta charset="utf-8">
  <title>Workers example: Multiviewer</title>
  <script>
   function openViewer() {
     window.open('viewer.html');
   }
  </script>
 </head>
 <body>
  <p><button type=button onclick="openViewer()">Open a new
  viewer</button></p>
  <p>Each viewer opens in a new window. You can have as many viewers
  as you like, they all view the same data.</p>
 </body>
</html>

ビューアーはより複雑になる:

<!DOCTYPE HTML>
<html lang="en">
 <head>
  <meta charset="utf-8">
  <title>Workers example: Multiviewer viewer</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];
     // 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(',');
     // 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);
     // 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];
     // 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>

ビューアーの作成方法については、注目に値する重要な点がいくつかある。

複数のリスナー。単一のメッセージ処理関数の代わりに、ここでのコードは複数のイベントリスナーをアタッチし、それぞれがメッセージに関連するかどうかを確認するためのクイックチェックを実行する。この例では大きな違いはないが、複数の著者が単一のポートを使用して共同作業し、ワーカーと通信したい場合、単一のイベント処理関数をすべて変更する代わりに、独立したコードを使用できる。

この方法でイベントリスナーを登録すると、この例のconfigure()メソッドで行ったように、使用後に特定のリスナーの登録を解除することもできる。

最後に、ワーカーは:

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イベントリスナーを使用して、複数の接続をリッスンする。

ダイレクトチャンネル 。ワーカーは、あるビューアーから別のビューアーを指定する"msg"メッセージを受信すると、2つのビューアー間に直接接続を設定し、ワーカーはすべてのメッセージをプロキシすることなく、2つのビューアーが直接通信できるようにする。

この例をオンラインで見る

10.1.2.5 委譲

この節は非規範的である。

マルチコアCPUが普及するにつれて、よりよいパフォーマンスを得る1つの方法は、計算コストの高いタスクを複数のワーカーに分割することである。この例では、1から10,000,000までのすべての数値に対して実行される計算コストの高いタスクが、10のサブワーカーに割り当てられる。

メインページは次のとおりで、結果を報告するだけである:

<!DOCTYPE HTML>
<html lang="en">
 <head>
  <meta charset="utf-8">
  <title>Worker example: Multicore computation</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>

ワーカー自体は次のとおりである:

// settings
var num_workers = 10;
var items_per_worker = 1000000;

// 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!
}

これは、サブワーカーを開始するループと、すべてのサブワーカーが応答するのを待つハンドラーで構成される。

サブワーカーは次のように実装される:

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つの数値を受け取り、指定された数値の範囲に対して計算を実行し、その結果を親に報告する。

この例をオンラインで見る

10.1.2.6 ライブラリの提供

この節は非規範的である。

仮に次の3つのタスクを提供する暗号化ライブラリが利用可能になったとする:

公開鍵と秘密鍵のペアを生成する
最初に公開キー、次に秘密キーの2つのメッセージを送信するポートを取得する。
与えられた平文と、公開鍵に対応する暗号文を返す
任意の数のメッセージを送信できるポートを取得する。最初のポートは公開鍵を提供し、残りのポートは平文を提供する。各メッセージは暗号化され、暗号文と同じチャンネルで送信される。ユーザーは、コンテンツの暗号化が完了したらポートを閉じることができる。
暗号文と秘密鍵が与えられた場合、対応する平文を返す
任意の数のメッセージを送信できるポートを取得する。最初のポートは秘密鍵を提供し、残りのポートは暗号文を提供する。各メッセージは復号化され、プレーンテキストと同じチャンネルで送信される。ユーザーは、コンテンツの復号化が完了したらポートを閉じることができる。

ライブラリ自体は次のとおり:

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));
    }
  };
}

// support being used as a shared worker as well as a dedicated worker
if ('onmessage' in this) // dedicated worker
  onmessage = handleMessage;
else // shared 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);
}

ここでの暗号関数は単なるスタブであり、実際の暗号化を行うものではないことに注意する。

このライブラリは次のように使用できる:

<!DOCTYPE HTML>
<html lang="en">
 <head>
  <meta charset="utf-8">
  <title>Worker example: Crypto library</title>
  <script>
   const cryptoLib = new Worker('libcrypto-v1.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の新しいバージョンでは、すべての暗号化作業をサブワーカーにオフロードしたいかもしれない。これは、次のように実行できる:

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]);
  };
}

// support being used as a shared worker as well as a dedicated worker
if ('onmessage' in this) // dedicated worker
  onmessage = handleMessage;
else // shared worker
  onconnect = function (e) { e.ports[0].onmessage = handleMessage };

小さなサブワーカーは次のようになる。

キーペアを生成する場合:

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()];
}

暗号化の場合:

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;
}

復号化の場合:

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を変更せずにサブワーカーに委任できる。

この例をオンラインで見る

10.1.3 チュートリアル

10.1.3.1 専用ワーカーの作成

この節は非規範的である。

ワーカーを作成するには、JavaScriptファイルへのURLが必要である。Worker()コンストラクターは、そのファイルへのURLを唯一の引数として呼び出される。次に、ワーカーが作成されて返される:

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

ワーカースクリプトをデフォルトのクラシックスクリプトではなく、モジュールスクリプトとして解釈する場合、少し異なるシグネチャーを使用する必要がある:

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

この節は非規範的である。

専用ワーカーは背後でMessagePortオブジェクトを使用するため、構造化データの送信、バイナリデータの転送、他のポートの転送など、すべての同じ機能をサポートする。

専用ワーカーからメッセージを受信するには、WorkerオブジェクトでonmessageイベントハンドラーIDL属性をする:

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

addEventListener()メソッドを使用することもできる。

専用ワーカーによって使用される暗黙のMessagePortは、作成時にそのポートメッセージキューが暗黙的に有効になるため、WorkerインターフェースにはMessagePortインターフェースのstart()メソッドに相当するものは存在しない。

ワーカーにデータを送信するには、postMessage()メソッドを使用する。構造化データは、この通信チャンネルを介して送信できる。(オブジェクトのクローンを作成するのではなく、オブジェクトを転送することによって、)ArrayBufferオブジェクトを効率的に送信するには、オブジェクトを2番目の引数の配列にリストする。

worker.postMessage({
  operation: 'find-edges',
  input: buffer, // an ArrayBuffer object
  threshold: 0.6,
}, [buffer]);

ワーカー内部でメッセージを受信するには、onmessageイベントハンドラーIDL属性を使用する。

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

この場合も、addEventListener()メソッドを使用できる。

いずれの場合も、データはイベントオブジェクトのdata属性で提供される。

メッセージを送り返すには、やはりpostMessage()を使用する。同じ方法で構造化データをサポートする。

postMessage(event.data.input, [event.data.input]); // transfer the buffer back
10.1.3.3 共有ワーカー

SharedWorker

Support in all current engines.

Firefox29+Safari16+Chrome5+
Opera10.6+Edge79+
Edge (Legacy)?Internet ExplorerNo
Firefox Android33+Safari iOS16+Chrome AndroidNoWebView Android?Samsung Internet4.0–5.0Opera Android11–14

この節は非規範的である。

共有ワーカーは、その作成に使用されたスクリプトのURL、オプションで明示的な名前を使用可能、によって識別される。この名前は、特定の共有ワーカーの複数のインスタンスを開始するのを可能にする。

共有ワーカーの範囲は、生成元である。同じ名前を使用する2つの異なるサイトは衝突しない。しかし、ページが同じサイト上の別のページと同じ共有ワーカー名を使用しようとするが、スクリプトURLが異なる場合、失敗する。

共有ワーカーの作成は、SharedWorker()コンストラクターを使用して行われる。このコンストラクターは、最初の引数として使用するスクリプトへのURLと、存在する場合、2番目の引数としてワーカーの名前を受け取る。

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

共有ワーカーとの通信は、明示的なMessagePortオブジェクトを使用して行われる。SharedWorker()コンストラクターによって返されたオブジェクトは、そのport属性のポートへの参照を保持する。

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

共有ワーカー内では、ワーカーの新しいクライアントがconnectイベントを使用して通知される。新しいクライアントのポートは、イベントオブジェクトのsource属性によって指定される。

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
};

10.2 インフラ

この標準では、専用ワーカーと共有ワーカーの2種類のワーカーが定義されている。専用ワーカーは、作成されると作成者にリンクされるが、メッセージポートは、専用ワーカーから他の複数のブラウジングコンテキストまたはワーカーに通信するために使用できない。一方、共有ワーカーは、名前が付けられ、同じ生成元で実行されるスクリプトが作成されると、そのワーカーへの参照を取得して通信できる。Service Workersは第3の種類を定義する。[SW]

10.2.1 グローバルスコープ

グローバルスコープは、ワーカーの"内部"である。

10.2.1.1 WorkerGlobalScope共通インターフェイス

WorkerGlobalScope

Support in all current engines.

Firefox3.5+Safari4+Chrome4+
Opera10.6+Edge79+
Edge (Legacy)12+Internet Explorer10+
Firefox Android?Safari iOS5+Chrome Android?WebView Android?Samsung Internet?Opera Android11+
[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は、DedicatedWorkerGlobalScopeSharedWorkerGlobalScopeServiceWorkerGlobalScopeなど、特定のタイプのワーカーグローバルスコープオブジェクトの基本クラスとして機能する。

A WorkerGlobalScope object has an associated owner set (a set of Document and WorkerGlobalScope objects). It is initially empty and populated when the worker is created or obtained.

It is a set, instead of a single owner, to accommodate SharedWorkerGlobalScope objects.

A WorkerGlobalScope object has an associated type ("classic" or "module"). It is set during creation.

A WorkerGlobalScope object has an associated url (null or a URL). 最初はnullである。

A WorkerGlobalScope object has an associated name (a string). It is set during creation.

The name can have different semantics for each subclass of WorkerGlobalScope. For DedicatedWorkerGlobalScope instances, it is simply a developer-supplied name, useful mostly for debugging purposes. For SharedWorkerGlobalScope instances, it allows obtaining a reference to a common shared worker via the SharedWorker() constructor. 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 boolean. 最初はfalseである。

workerGlobal.self

WorkerGlobalScope/self

Support in all current engines.

Firefox3.5+Safari4+Chrome4+
Opera11.5+Edge79+
Edge (Legacy)12+Internet Explorer10+
Firefox Android34+Safari iOS5+Chrome Android?WebView Android?Samsung Internet?Opera Android?
workerGlobalを返す。
workerGlobal.location

WorkerGlobalScope/location

Support in all current engines.

Firefox3.5+Safari4+Chrome4+
Opera11.5+Edge79+
Edge (Legacy)12+Internet Explorer10+
Firefox Android?Safari iOS5+Chrome Android?WebView Android?Samsung Internet?Opera Android?
workerGlobalWorkerLocationオブジェクトを返す。
workerGlobal.navigator

WorkerGlobalScope/navigator

Support in all current engines.

Firefox3.5+Safari4+Chrome4+
Opera11.5+Edge79+
Edge (Legacy)17+Internet Explorer10+
Firefox Android?Safari iOS5+Chrome Android?WebView Android?Samsung Internet?Opera Android?
workerGlobalWorkerNavigatorオブジェクトを返す。
workerGlobal.importScripts(...urls)

WorkerGlobalScope/importScripts

Support in all current engines.

Firefox4+Safari4+Chrome4+
Opera10.6+Edge79+
Edge (Legacy)12+Internet Explorer10+
Firefox Android?Safari iOS5+Chrome Android?WebView Android?Samsung Internet?Opera Android11+
urls内の各URLをフェッチし、渡された順序で1つずつ実行してから返す(または何かがうまくいかなかった場合は投げる)。

The self attribute must return the WorkerGlobalScope object itself.

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.


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

WorkerGlobalScope/error_event

Support in all current engines.

Firefox3.5+Safari4+Chrome4+
Opera11.5+Edge79+
Edge (Legacy)12+Internet Explorer10+
Firefox Android?Safari iOS5+Chrome Android?WebView Android?Samsung Internet?Opera Android?
error
onlanguagechange

WorkerGlobalScope/languagechange_event

Support in all current engines.

Firefox74+Safari4+Chrome4+
Opera11.5+Edge79+
Edge (Legacy)?Internet ExplorerNo
Firefox Android?Safari iOS5+Chrome Android?WebView Android37+Samsung Internet?Opera Android?
languagechange
onoffline

WorkerGlobalScope/offline_event

Firefox29+Safari8+ChromeNo
Opera?EdgeNo
Edge (Legacy)?Internet ExplorerNo
Firefox Android?Safari iOS?Chrome Android?WebView Android?Samsung Internet?Opera Android?
offline
ononline

WorkerGlobalScope/online_event

Firefox29+Safari8+ChromeNo
Opera?EdgeNo
Edge (Legacy)?Internet ExplorerNo
Firefox Android?Safari iOS?Chrome Android?WebView Android?Samsung Internet?Opera Android?
online
onrejectionhandledrejectionhandled
onunhandledrejectionunhandledrejection
10.2.1.2 専用ワーカーおよびDedicatedWorkerGlobalScopeインターフェイス

DedicatedWorkerGlobalScope

Support in all current engines.

Firefox3.5+Safari4+Chrome4+
Opera10.6+Edge79+
Edge (Legacy)12+Internet Explorer10+
Firefox Android?Safari iOS5+Chrome Android?WebView Android?Samsung Internet?Opera Android11+
[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オブジェクトは、内部ポートMessagePort)が関連付けられている。このポートは、ワーカーの作成時に設定されるチャンネルの一部であるが、公開されていない。This object must never be garbage collected before the DedicatedWorkerGlobalScope object.

dedicatedWorkerGlobal.name

DedicatedWorkerGlobalScope/name

Support in all current engines.

Firefox55+Safari12.1+Chrome70+
Opera?Edge79+
Edge (Legacy)18Internet ExplorerNo
Firefox Android?Safari iOS?Chrome Android?WebView Android?Samsung Internet?Opera Android?

dedicatedWorkerGlobal名前、すなわちWorkerコンストラクターに指定された値を返す。主にデバッグに役立つ。

dedicatedWorkerGlobal.postMessage(message [, transfer ])

DedicatedWorkerGlobalScope/postMessage

Support in all current engines.

Firefox3.5+Safari4+Chrome4+
Opera10.6+Edge79+
Edge (Legacy)12+Internet Explorer10+
Firefox Android?Safari iOS5+Chrome Android?WebView Android?Samsung Internet?Opera Android11+
dedicatedWorkerGlobal.postMessage(message [, { transfer } ])

messageをクローンしてdedicatedWorkerGlobalに関連付けられたWorkerオブジェクトに送信する。transferは、クローンではなく転送されるオブジェクトのリストとして渡すことができる。

dedicatedWorkerGlobal.close()

DedicatedWorkerGlobalScope/close

Support in all current engines.

Firefox3.5+Safari4+Chrome4+
Opera10.6+Edge79+
Edge (Legacy)12+Internet Explorer10+
Firefox Android?Safari iOS5+Chrome Android?WebView Android?Samsung Internet?Opera Android11+

dedicatedWorkerGlobalを中止する。

The name getter steps are to return this's name. Its value represents the name given to the worker using the Worker constructor, used primarily for debugging purposes.

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.

To close a worker, given a workerGlobal, run these steps:

  1. Discard any tasks that have been added to workerGlobal's relevant agent's event loop's task queues.

  2. Set workerGlobal's closing flag to true. (This prevents any further tasks from being queued.)

The close() method steps are to close a worker given this.


10.2.1.3 共有ワーカーおよびSharedWorkerGlobalScopeインターフェイス

SharedWorkerGlobalScope

Support in all current engines.

Firefox29+Safari16+Chrome4+
Opera10.6+Edge79+
Edge (Legacy)?Internet ExplorerNo
Firefox Android?Safari iOS16+Chrome Android?WebView Android37+Samsung Internet?Opera Android11+
[Global=(Worker,SharedWorker),Exposed=SharedWorker]
interface SharedWorkerGlobalScope : WorkerGlobalScope {
  [Replaceable] readonly attribute DOMString name;

  undefined close();

  attribute EventHandler onconnect;
};

A SharedWorkerGlobalScope object has associated constructor storage key (a storage key), constructor URL (a URL record), and credentials (a credentials mode), and extended lifetime (a boolean). They are initialized when the SharedWorkerGlobalScope object is created, in the run a worker algorithm.

共有ワーカーは、各接続のSharedWorkerGlobalScopeオブジェクトの connectイベントを通じてメッセージポートを受け取る。

sharedWorkerGlobal.name

SharedWorkerGlobalScope/name

Support in all current engines.

Firefox29+Safari16+Chrome4+
Opera10.6+Edge79+
Edge (Legacy)?Internet ExplorerNo
Firefox Android?Safari iOS16+Chrome Android?WebView Android?Samsung Internet?Opera Android11+

sharedWorkerGlobal名前、すなわちSharedWorkerコンストラクターに指定された値を返す。同じ名前を再利用することによって、複数のSharedWorkerオブジェクトを同じ共有ワーカー(およびSharedWorkerGlobalScope)に対応付けることができる。

sharedWorkerGlobal.close()

SharedWorkerGlobalScope/close

Support in all current engines.

Firefox29+Safari16+Chrome4+
Opera10.6+Edge79+
Edge (Legacy)?Internet ExplorerNo
Firefox Android?Safari iOS16+Chrome Android?WebView Android?Samsung Internet?Opera Android11+

sharedWorkerGlobalを中止する。

The name getter steps are to return this's name. Its value represents the name that can be used to obtain a reference to the worker using the SharedWorker constructor.

The close() method steps are to close a worker given this.


下記は、SharedWorkerGlobalScopeインターフェイスを実装するすべてのオブジェクトによって、イベントハンドラーIDL属性として、サポートされるイベントハンドラー(および対応するイベントハンドラーイベント型)である:

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

SharedWorkerGlobalScope/connect_event

Support in all current engines.

Firefox29+Safari16+Chrome4+
Opera10.6+Edge79+
Edge (Legacy)?Internet ExplorerNo
Firefox Android?Safari iOS16+Chrome Android?WebView Android37+Samsung Internet?Opera Android11+
connect

10.2.2 イベントループ

ワーカーイベントループタスクキューは、タスクとしてイベント、コールバック、およびネットワークアクティビティのみを持つ。These worker event loops are created by the run a worker algorithm.

WorkerGlobalScopeオブジェクトはclosingフラグを持ち、このフラグは最初はfalseでなければならないが、下記の処理モデルのセクションのアルゴリズムによってtrueに設定できる。

WorkerGlobalScopeclosingフラグがtrueに設定されると、イベントループタスクキューは、それ以降に追加されるタスクを破棄しなければならない(キュー上にすでにあるタスクは、特に指定がない限り影響を受けない)。実際には、closingフラグがtrueになると、タイマーの発火が停止し、保留中のすべてのバックグラウンド操作の通知が中断されるなどの動作が行われる。

10.2.3 The worker's lifetime

Workers communicate with other workers and with Windows through message channels and their MessagePort objects.

Each WorkerGlobalScope object worker global scope has a list of the worker's ports, 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. This list includes the implicit MessagePort in the case of dedicated workers.

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. 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. Otherwise, o's global object is a Window object, and the relevant owner is that Window's associated Document.


A user agent has an implementation-defined value, the between-loads shared worker timeout, which is some small amount of time. This represents how long the user agent allows shared workers to survive while a page is loading, in case that page is going to contact the shared worker again. Setting this value to greater than zero lets user agents avoid the cost of restarting a shared worker used by a site when the user is navigating from page to page within that site.

A typical value for the between-loads shared worker timeout might be 5 seconds.

A user agent has an implementation-defined value, the extended lifetime shared worker timeout, which is some amount of time. This represents how long the user agent allows shared workers which the web developer has requested be given an extended lifetime, to survive and perform work after all of their owners have disappeared. User agents should choose a value that is equal to the longest lifetime that a service worker can stay alive without any clients, and must not choose a value that is longer than that amount of time.

A typical value for the extended lifetime shared worker timeout could be anywhere from 10 seconds to 5 minutes, depending on the implementation's individual policies regarding background work being performed by an origin without a user-visible representation.


A WorkerGlobalScope global is in extended lifetime if the following algorithm returns true:

  1. If global is not a SharedWorkerGlobalScope, then return false.

  2. If global's extended lifetime is false, then return false.

  3. If global's owner set is empty, but has been empty for less than the user agent's extended lifetime shared worker timeout, then return true.

  4. For each owner of global's owner set:

    1. If owner is a Document that is fully active, then return false.

      In this case global will be actively needed, but it's not in extended lifetime.

  5. For each owner of global's owner set:

    1. If owner is a Document and the amount of time that owner has been non-fully active is less than the user agent's extended lifetime shared worker timeout, then return true.

    2. If owner is a WorkerGlobalScope that is in extended lifetime, then return true.

  6. falseを返す。

A WorkerGlobalScope global is actively needed if the following algorithm returns true:

  1. If global is in extended lifetime, then return true.

  2. For each owner of global's owner set:

    1. If owner is a Document, and owner is fully active, then return true.

    2. If owner is a WorkerGlobalScope that is actively needed, then return true.

  3. falseを返す。

A WorkerGlobalScope global is protected if the following algorithm returns true:

  1. If global is not actively needed, then return false.

  2. If global is in extended lifetime, then return true.

  3. If global is a SharedWorkerGlobalScope, then return true.

  4. If global's the worker's ports is not empty, then return true.

  5. If global has outstanding timers, database transactions, or network connections, then return true.

  6. falseを返す。

A WorkerGlobalScope global is permissible if the following algorithm returns true:

  1. If global's owner set is not empty, then return true.

  2. If global is in extended lifetime, then return true.

  3. If all of the following are true:

    then return true.

  4. falseを返す。

The following relationships hold between these terms:

However, the converses do not always hold:

The between-loads shared worker timeout only influences the definition of permissible, not protected, and so implementations are not required to keep shared workers alive for that duration. Rather, they are required to close shared workers after the timeout is reached.

In contrast, the extended lifetime shared worker timeout does influence the definition of protected, so implementations are required to keep shared workers alive (and not suspended) for that duration.

A WorkerGlobalScope global is suspendable if the following algorithm returns true:

  1. If global is actively needed, then return false.

  2. If global is permissible, then return true.

  3. falseを返す。

These concepts are used elsewhere in the specification's normative requirements as follows:

10.2.4 Processing model

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. 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. Let unsafeWorkerCreationTime be the unsafe shared current time.

  4. Let agent be the result of obtaining a dedicated/shared worker agent given outside settings and is shared. Run the rest of these steps in that agent.

  5. Let realm execution context be the result of creating a new realm given agent and the following customizations:

  6. Let worker global scope be the global object of realm execution context's Realm component.

    This is the DedicatedWorkerGlobalScope or SharedWorkerGlobalScope object created in the previous step.

  7. Set up a worker environment settings object with realm execution context, outside settings, and unsafeWorkerCreationTime, and let inside settings be the result.

  8. Set worker global scope's name to options["name"].

  9. Append owner to worker global scope's owner set.

  10. If is shared is true:

    1. Set worker global scope's constructor storage key to the result of running obtain a storage key for non-storage purposes given outside settings.

    2. Set worker global scope's constructor URL to url.

    3. Set worker global scope's type to options["type"].

    4. Set worker global scope's credentials to options["credentials"].

    5. Set worker global scope's extended lifetime to options["extendedLifetime"].

  11. Let destination be "sharedworker" if is shared is true, and "worker" otherwise.

  12. Obtain script by switching on options["type"]:

    "classic"
    Fetch a classic worker script given url, outside settings, destination, inside settings, and with onComplete and performFetch as defined below.
    "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.

    In both cases, let performFetch be the following perform the fetch hook given request, isTopLevel, and processCustomFetchResponse:

    1. 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 request with processResponseConsumeBody set to the following steps given response response and null, failure, or a byte sequence bodyBytes:

      1. Set worker global scope's url to response's url.

      2. Set inside settings's creation URL to response's url.

      3. Initialize worker global scope's policy container given worker global scope, response, and inside settings.

      4. 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]

      5. 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.

        This really ought to be set when the agent cluster is created, which requires a redesign of this section.

      6. 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.

      7. Set worker global scope's cross-origin isolated capability to true if agent's agent cluster's cross-origin isolation mode is "concrete".

      8. 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.

      9. 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.

        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.

      10. Run processCustomFetchResponse with response and bodyBytes.

    In both cases, let onComplete given script be the following steps:

    1. If script is null or if script's error to rethrow is non-null:

      1. 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. Abort these steps.

    2. Associate worker with worker global scope.

    3. Let inside port be a new MessagePort object in inside settings's realm.

    4. If is shared is false:

      1. Set inside port's message event target to worker global scope.

      2. Set worker global scope's inside port to inside port.

    5. Entangle outside port and inside port.

    6. Create a new WorkerLocation object and associate it with worker global scope.

    7. Closing orphan workers: Start monitoring worker global scope such that no sooner than it stops being protected, and no later than it stops being permissible, worker global scope's closing flag is set to true.

    8. Suspending workers: Start monitoring worker global scope, such that whenever worker global scope's closing flag is false and it is suspendable, the user agent suspends execution of script in worker global scope until such time as either the closing flag switches to true or worker global scope stops being suspendable.

    9. Set inside settings's execution ready flag.

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

      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.

    11. Enable outside port's port message queue.

    12. If is shared is false, enable the port message queue of the worker's implicit port.

    13. If is shared is true, then queue a global task on the 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.

    14. Enable the client message queue of the ServiceWorkerContainer object whose associated service worker client is worker global scope's relevant settings object.

    15. Event loop: Run the responsible event loop specified by inside settings until it is destroyed.

      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.

      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.

    16. Clear the worker global scope's map of active timers.

    17. Disentangle all the ports in the list of the worker's ports.

    18. Empty worker global scope's owner set.


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. Set the worker's WorkerGlobalScope object's closing flag to true.

  2. If there are any tasks queued in the WorkerGlobalScope object's relevant agent's event loop's task queues, discard them without processing them.

  3. Abort the script currently running in the worker.

  4. 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.

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

10.2.5 ランタイムスクリプトエラー

捕捉されなかったランタイムスクリプトエラーがワーカーのスクリプトの1つで発生するたびごとに、そのエラーが以前のスクリプトエラーの処理中に発生したものでなければ、ユーザーエージェントはワーカーのWorkerGlobalScopeオブジェクトに対してそのエラーを報告する

10.2.6 ワーカーの作成

10.2.6.1 AbstractWorkerミックスイン
interface mixin AbstractWorker {
  attribute EventHandler onerror;
};

下記は、AbstractWorkerインターフェイスを実装するすべてのオブジェクトによって、イベントハンドラーIDL属性として、サポートされるイベントハンドラー(および対応するイベントハンドラーイベント型)である:

イベントハンドラーイベントハンドラーイベント型
onerror

ServiceWorker/error_event

Support in all current engines.

Firefox44+Safari11.1+Chrome40+
Opera?Edge79+
Edge (Legacy)17+Internet ExplorerNo
Firefox Android?Safari iOS?Chrome Android?WebView Android?Samsung Internet?Opera Android?

SharedWorker/error_event

Support in all current engines.

Firefox29+Safari16+Chrome5+
Opera10.6+Edge79+
Edge (Legacy)?Internet ExplorerNo
Firefox Android33+Safari iOS16+Chrome AndroidNoWebView Android?Samsung Internet4.0–5.0Opera Android11–14

Worker/error_event

Support in all current engines.

Firefox3.5+Safari4+Chrome4+
Opera10.6+Edge79+
Edge (Legacy)12+Internet Explorer10+
Firefox Android?Safari iOS5+Chrome Android?WebView Android?Samsung Internet?Opera Android11+
error
10.2.6.2 Script settings for workers

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 realm be the value of execution context's Realm component.

  2. Let worker global scope be realm's global object.

  3. Let origin be a unique opaque origin if worker global scope's url's scheme is "data"; otherwise outside settings's origin.

  4. Let settings object be a new environment settings object whose algorithms are defined as follows:

    The realm execution context

    Return execution context.

    The module map

    Return worker global scope's module map.

    The API base URL

    Return worker global scope's url.

    The origin

    Return origin.

    The has cross-site ancestor
    1. If outside settings's has cross-site ancestor is true, then return true.

    2. If worker global scope's url's scheme is "data", then return true.

    3. falseを返す。

    The policy container

    Return worker global scope's policy container.

    The cross-origin isolated capability

    Return worker global scope's cross-origin isolated capability.

    The time origin

    Return the result of coarsening unsafeWorkerCreationTime with worker global scope's cross-origin isolated capability.

  5. 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. If worker global scope is a DedicatedWorkerGlobalScope object, then set settings object's top-level origin to outside settings's top-level origin.

  7. 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.

  8. Set realm's [[HostDefined]] field to settings object.

  9. Return settings object.

10.2.6.3 専用ワーカーおよびWorkerインターフェイス

Worker

Support in all current engines.

Firefox3.5+Safari4+Chrome2+
Opera10.6+Edge79+
Edge (Legacy)12+Internet Explorer10+
Firefox Android?Safari iOS5+Chrome Android?WebView Android?Samsung Internet?Opera Android11+
[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 {
  DOMString name = "";
  WorkerType type = "classic";
  RequestCredentials credentials = "same-origin"; // credentials is only used if type is "module"
};

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

Worker includes AbstractWorker;
Worker includes MessageEventTarget;
worker = new Worker(scriptURL [, options ])

Worker/Worker

Support in all current engines.

Firefox3.5+Safari4+Chrome4+
Opera10.6+Edge79+
Edge (Legacy)12+Internet Explorer10+
Firefox Android?Safari iOS5+Chrome Android?WebView Android?Samsung Internet?Opera Android11+

新しいWorkerオブジェクトを返す。scriptURLがフェッチされてバックグラウンドで実行され、workerが通信チャンネルを表す新しいグローバル環境が作成される。

optionsには、次の値を含めることができる:

worker.terminate()

Worker/terminate

Support in all current engines.

Firefox3.5+Safari4+Chrome2+
Opera10.6+Edge79+
Edge (Legacy)12+Internet Explorer10+
Firefox Android?Safari iOS5+Chrome Android?WebView Android?Samsung Internet?Opera Android11+
workerの関連付けられたグローバル環境を中止する。
worker.postMessage(message [, transfer ])

Worker/postMessage

Support in all current engines.

Firefox3.5+Safari4+Chrome2+
Opera10.6+Edge79+
Edge (Legacy)12+Internet Explorer10+
Firefox Android?Safari iOS5+Chrome Android?WebView Android?Samsung Internet?Opera Android11+
worker.postMessage(message [, { transfer } ])

messageをクローンし、workerのグローバル環境に送信する。transferは、クローンではなく転送されるオブジェクトのリストとして渡すことができる。

Each Worker object has an associated outside port (a MessagePort). このポートは、ワーカーの作成時に設定されるチャンネルの一部であるが、公開されていない。This object must never be garbage collected before the Worker object.

The terminate() method steps are to terminate a worker given this's worker.

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.

postMessage()メソッドの最初の引数は、構造化データにすることができる:

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

The new Worker(scriptURL, options) constructor steps are:

  1. 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 outsideSettings be this's relevant settings object.

  3. Let workerURL be the result of encoding-parsing a URL given compliantScriptURL, relative to outsideSettings.

    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. If workerURL is failure, then throw a "SyntaxError" DOMException.

  5. Let outsidePort be a new MessagePort in outsideSettings's realm.

  6. Set outsidePort's message event target to this.

  7. Set this's outside port to outsidePort.

  8. Let worker be this.

  9. Run this step in parallel:

    1. Run a worker given worker, workerURL, outsideSettings, outsidePort, and options.

10.2.6.4 共有ワーカーおよびSharedWorkerインターフェイス

SharedWorker

Support in all current engines.

Firefox29+Safari16+Chrome5+
Opera10.6+Edge79+
Edge (Legacy)?Internet ExplorerNo
Firefox Android33+Safari iOS16+Chrome AndroidNoWebView Android?Samsung Internet4.0–5.0Opera Android11–14
[Exposed=Window]
interface SharedWorker : EventTarget {
  constructor((TrustedScriptURL or USVString) scriptURL, optional (DOMString or SharedWorkerOptions) options = {});

  readonly attribute MessagePort port;
};
SharedWorker includes AbstractWorker;

dictionary SharedWorkerOptions : WorkerOptions {
  boolean extendedLifetime = false;
};
sharedWorker = new SharedWorker(scriptURL [, name ])

SharedWorker/SharedWorker

Support in all current engines.

Firefox29+Safari16+Chrome5+
Opera10.6+Edge79+
Edge (Legacy)?Internet ExplorerNo
Firefox Android33+Safari iOS16+Chrome AndroidNoWebView Android?Samsung Internet4.0–5.0Opera Android11–14

新しいSharedWorkerオブジェクトを返す。scriptURLがバックグラウンドでフェッチおよび実行され、sharedWorkerが通信チャンネルを表す新しいグローバル環境が作成される。nameを使用して、そのグローバル環境のnameを定義できる。

sharedWorker = new SharedWorker(scriptURL [, options ])

新しいSharedWorkerオブジェクトを返す。scriptURLがバックグラウンドでフェッチおよび実行され、sharedWorkerが通信チャンネルを表す新しいグローバル環境が作成される。

optionsには、次の値を含めることができる:

typecredentials、またはextendedLifetimeの値が同じconstructor URLおよびnameの既存の共有ワーカーの値と一致しないoptionsを使用して共有ワーカーを構築しようとすると、戻されたsharedWorkerによってerrorイベントが発火され、既存の共有ワーカーに接続されないことに注意する。

sharedWorker.port

SharedWorker/port

Support in all current engines.

Firefox29+Safari16+Chrome5+
Opera10.6+Edge79+
Edge (Legacy)?Internet ExplorerNo
Firefox Android33+Safari iOS16+Chrome AndroidNoWebView Android?Samsung Internet4.0–5.0Opera Android11–14

グローバル環境との通信に使用できるsharedWorkerMessagePortオブジェクトを返す。

A user agent has an associated shared worker manager which is the result of starting a new parallel queue.

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.


Each SharedWorker has a port, a MessagePort set when the object is created.

The port getter steps are to return this's port.

The new SharedWorker(scriptURL, options) constructor steps are:

  1. 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. 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 outsideSettings be this's relevant settings object.

  4. Let urlRecord be the result of encoding-parsing a URL given compliantScriptURL, relative to outsideSettings.

    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. If urlRecord is failure, then throw a "SyntaxError" DOMException.

  6. Let outsidePort be a new MessagePort in outsideSettings's realm.

  7. Set this's port to outsidePort.

  8. Let callerIsSecureContext be true if outsideSettings is a secure context; otherwise, false.

  9. Let outsideStorageKey be the result of running obtain a storage key for non-storage purposes given outsideSettings.

  10. Let worker be this.

  11. Enqueue the following steps to the shared worker manager:

    1. Let workerGlobalScope be null.

    2. For each scope in the list of all SharedWorkerGlobalScope objects:

      1. If all of the following are true:

        then:

        1. Set workerGlobalScope to scope.

        2. Break.

      data: URLs create a worker with an opaque origin, which would prevent such a worker from ever being matched if its own storage key were used. Instead, the constructor storage key (derived from the creating environment) and constructor URL are compared, so the same data: URL can be used within a storage key to get to the same SharedWorkerGlobalScope object, but cannot be used to bypass the storage key restriction.

    3. If workerGlobalScope is not null, but the user agent has been configured to disallow communication between the worker represented by the workerGlobalScope and the scripts whose settings object is outsideSettings, then set workerGlobalScope to null.

      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.

    4. If workerGlobalScope is not null, and any of the following are true:

      then:

      1. 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. Abort these steps.

    5. If workerGlobalScope is not null:

      1. Let insideSettings be workerGlobalScope's relevant settings object.

      2. Let workerIsSecureContext be true if insideSettings is a secure context; otherwise, false.

      3. If workerIsSecureContext is not callerIsSecureContext:

        1. 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. Abort these steps.

      4. Associate worker with workerGlobalScope.

      5. Let insidePort be a new MessagePort in insideSettings's realm.

      6. Entangle outsidePort and insidePort.

      7. Queue a global task on the DOM manipulation task source given workerGlobalScope to fire an event named connect at workerGlobalScope, using MessageEvent, with the data attribute initialized to the empty string, the ports attribute initialized to a new frozen array containing only insidePort, and the source attribute initialized to insidePort.

      8. Append the relevant owner to add given outsideSettings to workerGlobalScope's owner set.

    6. Otherwise, in parallel, run a worker given worker, urlRecord, outsideSettings, outsidePort, and options.

interface mixin NavigatorConcurrentHardware {
  readonly attribute unsigned long long hardwareConcurrency;
};
self.navigator.hardwareConcurrency

Navigator/hardwareConcurrency

Firefox48+Safari10.1–11Chrome37+
Opera?Edge79+
Edge (Legacy)15+Internet ExplorerNo
Firefox Android?Safari iOS?Chrome Android?WebView Android?Samsung Internet?Opera Android?

Navigator/hardwareConcurrency

Firefox48+Safari10.1–11Chrome37+
Opera?Edge79+
Edge (Legacy)15+Internet ExplorerNo
Firefox Android?Safari iOS?Chrome Android?WebView Android?Samsung Internet?Opera Android?

ユーザーエージェントが利用可能な論理プロセッサーの数を返す。

(This is a tracking vector.) The navigator.hardwareConcurrency attribute's getter must return a number between 1 and the number of logical processors potentially available to the user agent. If this cannot be determined, the getter must return 1.

User agents should err toward exposing the number of logical processors available, using lower values only in cases where there are user-agent specific limits in place (such as a limitation on the number of workers that can be created) or when the user agent desires to limit fingerprinting possibilities.

10.3 ワーカーが使用可能なAPI

10.3.1 Importing scripts and libraries

The importScripts(...urls) method steps are:

  1. Let urlStrings be « ».

  2. For each url of urls:

    1. 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. Import scripts into worker global scope given this and urlStrings.

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. If worker global scope's type is "module", throw a TypeError exception.

  2. Let settings object be the current settings object.

  3. If urls is empty, return.

  4. Let urlRecords be « ».

  5. For each url of urls:

    1. Let urlRecord be the result of encoding-parsing a URL given url, relative to settings object.

    2. If urlRecord is failure, then throw a "SyntaxError" DOMException.

    3. Append urlRecord to urlRecords.

  6. For each urlRecord of urlRecords:

    1. 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. Run the classic script script, with rethrow errors set to true.

      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.

      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 is an example of a specification that runs this algorithm with its own perform the fetch hook. [SW]

10.3.2 WorkerNavigatorインターフェイス

WorkerNavigator

Support in all current engines.

Firefox3.5+Safari4+Chrome4+
Opera12.1+Edge79+
Edge (Legacy)12+Internet Explorer10+
Firefox Android?Safari iOS5+Chrome Android?WebView Android?Samsung Internet?Opera Android12.1+

WorkerGlobalScopeインターフェイスのnavigator属性は、 WorkerNavigatorインターフェイスのインスタンスを返さなければならない。これは、ユーザーエージェント(クライアント)のIDおよび状態を表す:

[Exposed=Worker]
interface WorkerNavigator {};
WorkerNavigator includes NavigatorID;
WorkerNavigator includes NavigatorLanguage;
WorkerNavigator includes NavigatorOnLine;
WorkerNavigator includes NavigatorConcurrentHardware;

10.3.3 WorkerLocationインターフェイス

WorkerLocation

Support in all current engines.

Firefox3.5+Safari4+Chrome4+
Opera12.1+Edge79+
Edge (Legacy)12+Internet Explorer10+
Firefox Android?Safari iOS5+Chrome Android?WebView Android?Samsung Internet?Opera Android12.1+

WorkerLocation/toString

Support in all current engines.

Firefox3.5+Safari4+Chrome4+
Opera15+Edge79+
Edge (Legacy)12+Internet Explorer10+
Firefox Android?Safari iOS5+Chrome Android?WebView Android37+Samsung Internet?Opera Android14+
[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;
};

WorkerLocationオブジェクトは、関連付けられたWorkerGlobalScopeオブジェクトWorkerGlobalScopeオブジェクト)を持つ。

WorkerLocation/href

Support in all current engines.

Firefox3.5+Safari4+Chrome4+
Opera12.1+Edge79+
Edge (Legacy)12+Internet Explorer10+
Firefox Android?Safari iOS5+Chrome Android?WebView Android?Samsung Internet?Opera Android12.1+

hrefゲッターrステップは、thisWorkerGlobalScopeオブジェクトurlserializedを返す。

WorkerLocation/origin

Support in all current engines.

Firefox29+Safari10+Chrome38+
Opera?Edge79+
Edge (Legacy)14+Internet ExplorerNo
Firefox Android?Safari iOS?Chrome Android?WebView Android?Samsung Internet?Opera Android?

originゲッターステップは、thisWorkerGlobalScopeオブジェクトurloriginserializationを返す。

WorkerLocation/protocol

Support in all current engines.

Firefox3.5+Safari4+Chrome4+
Opera12.1+Edge79+
Edge (Legacy)12+Internet Explorer10+
Firefox Android?Safari iOS5+Chrome Android?WebView Android?Samsung Internet?Opera Android12.1+

protocolゲッターステップは、thisWorkerGlobalScopeオブジェクトurlschemeを返し、その後に":"が続く。

WorkerLocation/host

Support in all current engines.

Firefox3.5+Safari4+Chrome4+
Opera12.1+Edge79+
Edge (Legacy)12+Internet Explorer10+
Firefox Android?Safari iOS5+Chrome Android?WebView Android?Samsung Internet?Opera Android12.1+

The host getter steps are:

  1. Let url be this's WorkerGlobalScope object's url.

  2. If url's host is null, return the empty string.

  3. If url's port is null, return url's host, serialized.

  4. Return url's host, serialized, followed by ":" and url's port, serialized.

WorkerLocation/hostname

Support in all current engines.

Firefox3.5+Safari4+Chrome4+
Opera12.1+Edge79+
Edge (Legacy)12+Internet Explorer10+
Firefox Android?Safari iOS5+Chrome Android?WebView Android?Samsung Internet?Opera Android12.1+

The hostname getter steps are:

  1. Let host be this's WorkerGlobalScope object's url's host.

  2. If host is null, return the empty string.

  3. Return host, serialized.

WorkerLocation/port

Support in all current engines.

Firefox3.5+Safari4+Chrome4+
Opera12.1+Edge79+
Edge (Legacy)12+Internet Explorer10+
Firefox Android?Safari iOS5+Chrome Android?WebView Android?Samsung Internet?Opera Android12.1+

The port getter steps are:

  1. Let port be this's WorkerGlobalScope object's url's port.

  2. If port is null, return the empty string.

  3. Return port, serialized.

WorkerLocation/pathname

Support in all current engines.

Firefox3.5+Safari4+Chrome4+
Opera12.1+Edge79+
Edge (Legacy)12+Internet Explorer10+
Firefox Android?Safari iOS5+Chrome Android?WebView Android?Samsung Internet?Opera Android12.1+

The pathname getter steps are to return the result of URL path serializing this's WorkerGlobalScope object's url.

WorkerLocation/search

Support in all current engines.

Firefox3.5+Safari4+Chrome4+
Opera12.1+Edge79+
Edge (Legacy)12+Internet Explorer10+
Firefox Android?Safari iOS5+Chrome Android?WebView Android?Samsung Internet?Opera Android12.1+

The search getter steps are:

  1. Let query be this's WorkerGlobalScope object's url's query.

  2. If query is either null or the empty string, return the empty string.

  3. Return "?", followed by query.

WorkerLocation/hash

Support in all current engines.

Firefox3.5+Safari4+Chrome4+
Opera12.1+Edge79+
Edge (Legacy)12+Internet Explorer10+
Firefox Android?Safari iOS5+Chrome Android?WebView Android?Samsung Internet?Opera Android12.1+

The hash getter steps are:

  1. Let fragment be this's WorkerGlobalScope object's url's fragment.

  2. If fragment is either null or the empty string, return the empty string.

  3. Return "#", followed by fragment.