Living Standard — Last Updated 11 August 2026
Support in all current engines.
この節は非規範的である。
この仕様は、ユーザインタフェースのスクリプトとは独立して、バックグラウンドでスクリプトを実行するためのAPIを定義する。
これにより、クリックまたはその他のユーザー操作に応答するスクリプトによって中断されない長時間実行スクリプトが可能になり、ページの応答性を維持するために譲歩することなく長時間のタスクを実行できる。
ワーカー(ここではこれらのバックグラウンドスクリプトと呼ぶ)は、比較的重いものであり、大量に使用することは想定されていない。たとえば、4メガピクセルの画像の各ピクセルに対して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()メソッドは、素数が見つかったときにメッセージをページに送り返すために使用される。
この節は非規範的である。
これまでの例はすべて、クラシックスクリプトを実行するワーカーを示している。代わりに、ワーカーはモジュールスクリプトを使用してインスタンス化することができる。これには、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 ;
}
};
Support in all current engines.
この節は非規範的である。
この節では、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' );
}
}
この節は非規範的である。
この例では、すべて同じマップを表示する複数のウィンドウ(ビューアー)を開くことができる。すべてのウィンドウは同じマップ情報を共有し、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つのビューアーが直接通信できるようにする。
この節は非規範的である。
マルチコア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つの数値を受け取り、指定された数値の範囲に対して計算を実行し、その結果を親に報告する。
この節は非規範的である。
仮に次の3つのタスクを提供する暗号化ライブラリが利用可能になったとする:
ライブラリ自体は次のとおり:
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を変更せずにサブワーカーに委任できる。
この節は非規範的である。
ワーカーを作成するには、JavaScriptファイルへのURLが必要である。Worker()コンストラクターは、そのファイルへのURLを唯一の引数として呼び出される。次に、ワーカーが作成されて返される:
var worker = new Worker( 'helper.js' );
ワーカースクリプトをデフォルトのクラシックスクリプトではなく、モジュールスクリプトとして解釈する場合、少し異なるシグネチャーを使用する必要がある:
var worker = new Worker( 'helper.mjs' , { type: "module" });
この節は非規範的である。
専用ワーカーは背後で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
Support in all current engines.
この節は非規範的である。
共有ワーカーは、その作成に使用されたスクリプトの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
};
この標準では、専用ワーカーと共有ワーカーの2種類のワーカーが定義されている。専用ワーカーは、作成されると作成者にリンクされるが、メッセージポートは、専用ワーカーから他の複数のブラウジングコンテキストまたはワーカーに通信するために使用できない。一方、共有ワーカーは、名前が付けられ、同じ生成元で実行されるスクリプトが作成されると、そのワーカーへの参照を取得して通信できる。Service Workersは第3の種類を定義する。[SW]
グローバルスコープは、ワーカーの"内部"である。
WorkerGlobalScope共通インターフェイスSupport in all current engines.
[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は、DedicatedWorkerGlobalScope、SharedWorkerGlobalScope、ServiceWorkerGlobalScopeなど、特定のタイプのワーカーグローバルスコープオブジェクトの基本クラスとして機能する。
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.selfSupport in all current engines.
workerGlobal.locationSupport in all current engines.
WorkerLocationオブジェクトを返す。workerGlobal.navigatorSupport in all current engines.
WorkerNavigatorオブジェクトを返す。workerGlobal.importScripts(...urls)WorkerGlobalScope/importScripts
Support in all current engines.
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:
| イベントハンドラー | イベントハンドラーイベント型 |
|---|---|
onerrorSupport 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 |
onlanguagechangeWorkerGlobalScope/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 |
onofflineWorkerGlobalScope/offline_event Firefox29+Safari8+ChromeNo Opera?EdgeNo Edge (Legacy)?Internet ExplorerNo Firefox Android?Safari iOS?Chrome Android?WebView Android?Samsung Internet?Opera Android? | offline |
ononlineWorkerGlobalScope/online_event Firefox29+Safari8+ChromeNo Opera?EdgeNo Edge (Legacy)?Internet ExplorerNo Firefox Android?Safari iOS?Chrome Android?WebView Android?Samsung Internet?Opera Android? | online |
onrejectionhandled | rejectionhandled |
onunhandledrejection | unhandledrejection |
DedicatedWorkerGlobalScopeインターフェイスSupport in all current engines.
[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.nameDedicatedWorkerGlobalScope/name
Support in all current engines.
dedicatedWorkerGlobalの名前、すなわちWorkerコンストラクターに指定された値を返す。主にデバッグに役立つ。
dedicatedWorkerGlobal.postMessage(message [, transfer ])DedicatedWorkerGlobalScope/postMessage
Support in all current engines.
dedicatedWorkerGlobal.postMessage(message [, { transfer } ])messageをクローンしてdedicatedWorkerGlobalに関連付けられたWorkerオブジェクトに送信する。transferは、クローンではなく転送されるオブジェクトのリストとして渡すことができる。
dedicatedWorkerGlobal.close()DedicatedWorkerGlobalScope/close
Support in all current engines.
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:
Discard any tasks that have been added to workerGlobal's relevant agent's event loop's task queues.
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.
SharedWorkerGlobalScopeインターフェイスSupport in all current engines.
[Global =(Worker ,SharedWorker ),Exposed =SharedWorker ]
interface SharedWorkerGlobalScope : WorkerGlobalScope {
[Replaceable ] readonly attribute DOMString name ;
undefined close ();
attribute EventHandler onconnect ;
};
共有ワーカーは、各接続のSharedWorkerGlobalScopeオブジェクトの connectイベントを通じてメッセージポートを受け取る。
sharedWorkerGlobal.nameSupport in all current engines.
sharedWorkerGlobalの名前、すなわちSharedWorkerコンストラクターに指定された値を返す。同じ名前を再利用することによって、複数のSharedWorkerオブジェクトを同じ共有ワーカー(およびSharedWorkerGlobalScope)に対応付けることができる。
sharedWorkerGlobal.close()Support in all current engines.
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属性として、サポートされるイベントハンドラー(および対応するイベントハンドラーイベント型)である:
| イベントハンドラー | イベントハンドラーイベント型 |
|---|---|
onconnectSharedWorkerGlobalScope/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 |
ワーカーイベントループのタスクキューは、タスクとしてイベント、コールバック、およびネットワークアクティビティのみを持つ。These worker event loops are created by the run a worker algorithm.
各WorkerGlobalScopeオブジェクトはclosingフラグを持ち、このフラグは最初はfalseでなければならないが、下記の処理モデルのセクションのアルゴリズムによってtrueに設定できる。
WorkerGlobalScopeのclosingフラグがtrueに設定されると、イベントループのタスクキューは、それ以降に追加されるタスクを破棄しなければならない(キュー上にすでにあるタスクは、特に指定がない限り影響を受けない)。実際には、closingフラグがtrueになると、タイマーの発火が停止し、保留中のすべてのバックグラウンド操作の通知が中断されるなどの動作が行われる。
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:
If global is not a SharedWorkerGlobalScope, then return false.
If global's extended lifetime is false, then return false.
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.
For each owner of global's owner set:
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.
For each owner of global's owner set:
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.
If owner is a WorkerGlobalScope that is in extended lifetime, then return true.
falseを返す。
A WorkerGlobalScope global is actively needed if the following algorithm returns true:
If global is in extended lifetime, then return true.
For each owner of global's owner set:
If owner is a Document, and owner is fully active, then return true.
If owner is a WorkerGlobalScope that is actively needed, then return true.
falseを返す。
A WorkerGlobalScope global is protected if the following algorithm returns true:
If global is not actively needed, then return false.
If global is in extended lifetime, then return true.
If global is a SharedWorkerGlobalScope, then return true.
If global's the worker's ports is not empty, then return true.
If global has outstanding timers, database transactions, or network connections, then return true.
falseを返す。
A WorkerGlobalScope global is permissible if the following algorithm returns true:
If global is in extended lifetime, then return true.
If all of the following are true:
global is a SharedWorkerGlobalScope;
global's owner set has been empty for no more than the user agent's between-loads shared worker timeout; and
the user agent has a navigable whose active document is not completely loaded,
then return true.
falseを返す。
The following relationships hold between these terms:
Every WorkerGlobalScope that is in extended lifetime is actively needed, protected, and permissible.
Every WorkerGlobalScope that is actively needed or protected is permissible.
Every WorkerGlobalScope that is protected is actively needed.
However, the converses do not always hold:
A WorkerGlobalScope can be actively needed but not protected, if it's a dedicated worker with no outstanding async work that is still performing computation on behalf of a fully active owner, but whose corresponding Worker object has been garbage collected. Because of the garbage collection, the ports collection is empty, so it is no longer protected. However, its event loop has not yet yielded to empty its owner set, so it is still actively needed.
A WorkerGlobalScope can be permissible but not protected or actively needed, if all the Documents in its transitive set of owners are in bfcache, or if it's a SharedWorkerGlobalScope with no current owners being kept alive for the duration of the between-loads shared worker timeout.
A WorkerGlobalScope global is suspendable if the following algorithm returns true:
If global is actively needed, then return false.
If global is permissible, then return true.
falseを返す。
These concepts are used elsewhere in the specification's normative requirements as follows:
Workers get closed as orphans between when they stop being protected and when they stop being permissible.
Workers that have been closed, but keep executing, can be terminated at the user agent's discretion, once they stop being actively needed.
Workers get suspended or un-suspended based on whether they are suspendable.
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:
Let is shared be true if worker is a SharedWorker object, and false otherwise.
Let owner be the relevant owner to add given outside settings.
Let unsafeWorkerCreationTime be the unsafe shared current time.
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.
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.
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.
Set up a worker environment settings object with realm execution context, outside settings, and unsafeWorkerCreationTime, and let inside settings be the result.
If is shared is true:
Set worker global scope's constructor storage key to the result of running obtain a storage key for non-storage purposes given outside settings.
Set worker global scope's constructor URL to url.
Set worker global scope's credentials to options["credentials"].
Set worker global scope's extended lifetime to options["extendedLifetime"].
Let destination be "sharedworker" if is shared is true, and "worker" otherwise.
Obtain script by switching on options["type"]:
classic"module"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:
If isTopLevel is false, fetch request with processResponseConsumeBody set to processCustomFetchResponse, and abort these steps.
Fetch request with processResponseConsumeBody set to the following steps given response response and null, failure, or a byte sequence bodyBytes:
Set inside settings's creation URL to response's url.
Initialize worker global scope's policy container given worker global scope, response, and inside settings.
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]
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.
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.
Set worker global scope's cross-origin isolated capability to true if agent's agent cluster's cross-origin isolation mode is "concrete".
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.
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.
Run processCustomFetchResponse with response and bodyBytes.
In both cases, let onComplete given script be the following steps:
If script is null or if script's error to rethrow is non-null:
Queue a global task on the DOM manipulation task source given worker's relevant global object to fire an event named error at worker.
Run the environment discarding steps for inside settings.
Abort these steps.
Associate worker with worker global scope.
Let inside port be a new MessagePort object in inside settings's realm.
If is shared is false:
Set inside port's message event target to worker global scope.
Set worker global scope's inside port to inside port.
Entangle outside port and inside port.
Create a new WorkerLocation object and associate it with worker global scope.
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.
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.
Set inside settings's execution ready flag.
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.
Enable outside port's port message queue.
If is shared is false, enable the port message queue of the worker's implicit port.
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.
Enable the client message queue of the ServiceWorkerContainer object whose associated service worker client is worker global scope's relevant settings object.
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.
Clear the worker global scope's map of active timers.
Disentangle all the ports in the list of the worker's ports.
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):
Set the worker's WorkerGlobalScope object's closing flag to true.
If there are any tasks queued in the WorkerGlobalScope object's relevant agent's event loop's task queues, discard them without processing them.
Abort the script currently running in the 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.
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.
捕捉されなかったランタイムスクリプトエラーがワーカーのスクリプトの1つで発生するたびごとに、そのエラーが以前のスクリプトエラーの処理中に発生したものでなければ、ユーザーエージェントはワーカーのWorkerGlobalScopeオブジェクトに対してそのエラーを報告する。
AbstractWorkerミックスインinterface mixin AbstractWorker {
attribute EventHandler onerror ;
};
下記は、AbstractWorkerインターフェイスを実装するすべてのオブジェクトによって、イベントハンドラーIDL属性として、サポートされるイベントハンドラー(および対応するイベントハンドラーイベント型)である:
| イベントハンドラー | イベントハンドラーイベント型 |
|---|---|
onerrorSupport 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? 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 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 |
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:
Let realm be the value of execution context's Realm component.
Let worker global scope be realm's global object.
Let origin be a unique opaque origin if worker global scope's url's scheme is "data"; otherwise outside settings's origin.
Let settings object be a new environment settings object whose algorithms are defined as follows:
Return execution context.
Return worker global scope's module map.
Return worker global scope's url.
Return origin.
If outside settings's has cross-site ancestor is true, then return true.
If worker global scope's url's scheme is "data", then return true.
falseを返す。
Return worker global scope's policy container.
Return worker global scope's cross-origin isolated capability.
Return the result of coarsening unsafeWorkerCreationTime with worker global scope's cross-origin isolated capability.
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.
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.
Set realm's [[HostDefined]] field to settings object.
Return settings object.
WorkerインターフェイスSupport in all current engines.
[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 ])Support in all current engines.
新しいWorkerオブジェクトを返す。scriptURLがフェッチされてバックグラウンドで実行され、workerが通信チャンネルを表す新しいグローバル環境が作成される。
optionsには、次の値を含めることができる:
name can be used to define the name of that global environment, primarily for debugging purposes.
typeを使用して、新しいグローバル環境をscriptURLから値"module"に設定することにより、JavaScriptモジュールとしてロードできる。
credentialsを使用してscriptURLの取得方法を指定できるが、typeが"module"に設定されている場合に限られる。
worker.terminate()Support in all current engines.
worker.postMessage(message [, transfer ])Support in all current engines.
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:
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".
Let outsideSettings be this's relevant settings object.
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.
If workerURL is failure, then throw a "SyntaxError" DOMException.
Let outsidePort be a new MessagePort in outsideSettings's realm.
Set outsidePort's message event target to this.
Set this's outside port to outsidePort.
Let worker be this.
Run this step in parallel:
Run a worker given worker, workerURL, outsideSettings, outsidePort, and options.
SharedWorkerインターフェイスSupport in all current engines.
[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 ])Support in all current engines.
新しいSharedWorkerオブジェクトを返す。scriptURLがバックグラウンドでフェッチおよび実行され、sharedWorkerが通信チャンネルを表す新しいグローバル環境が作成される。nameを使用して、そのグローバル環境のnameを定義できる。
sharedWorker = new SharedWorker(scriptURL [, options ])新しいSharedWorkerオブジェクトを返す。scriptURLがバックグラウンドでフェッチおよび実行され、sharedWorkerが通信チャンネルを表す新しいグローバル環境が作成される。
optionsには、次の値を含めることができる:
typeを使用して、新しいグローバル環境をscriptURLから値"module"に設定することにより、JavaScriptモジュールとしてロードできる。
credentialsを使用してscriptURLの取得方法を指定できるが、typeが"module"に設定されている場合に限られる。
extendedLifetimeを設定して、新しく作成されたグローバル環境に、その所有者がすべてなくなった後でさえも、その操作を実行するための追加の時間を与えるように要求できる。これは、たとえば、ページのアンロード後に非同期作業を実行する場合に便利である。
type、credentials、またはextendedLifetimeの値が同じconstructor URLおよびnameの既存の共有ワーカーの値と一致しないoptionsを使用して共有ワーカーを構築しようとすると、戻されたsharedWorkerによってerrorイベントが発火され、既存の共有ワーカーに接続されないことに注意する。
sharedWorker.portSupport in all current engines.
グローバル環境との通信に使用できるsharedWorkerのMessagePortオブジェクトを返す。
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 new SharedWorker(scriptURL, options) constructor steps are:
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".
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.
Let outsideSettings be this's relevant settings object.
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.
If urlRecord is failure, then throw a "SyntaxError" DOMException.
Let outsidePort be a new MessagePort in outsideSettings's realm.
Let callerIsSecureContext be true if outsideSettings is a secure context; otherwise, false.
Let outsideStorageKey be the result of running obtain a storage key for non-storage purposes given outsideSettings.
Let worker be this.
Enqueue the following steps to the shared worker manager:
Let workerGlobalScope be null.
For each scope in the list of all SharedWorkerGlobalScope objects:
If all of the following are true:
name"],then:
Set workerGlobalScope to scope.
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.
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.
If workerGlobalScope is not null, and any of the following are true:
workerGlobalScope's credentials is not equal to options["credentials"]; or
workerGlobalScope's extended lifetime is not equal to options["extendedLifetime"],
then:
Queue a global task on the DOM manipulation task source given worker's relevant global object to fire an event named error at worker.
Abort these steps.
If workerGlobalScope is not null:
Let insideSettings be workerGlobalScope's relevant settings object.
Let workerIsSecureContext be true if insideSettings is a secure context; otherwise, false.
If workerIsSecureContext is not callerIsSecureContext:
Queue a global task on the DOM manipulation task source given worker's relevant global object to fire an event named error at worker.
Abort these steps.
Associate worker with workerGlobalScope.
Let insidePort be a new MessagePort in insideSettings's realm.
Entangle outsidePort and insidePort.
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.
Append the relevant owner to add given outsideSettings to workerGlobalScope's owner set.
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ユーザーエージェントが利用可能な論理プロセッサーの数を返す。
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.
The importScripts(...urls) method steps are:
Let urlStrings be « ».
For each url of urls:
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.
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:
If worker global scope's type is "module", throw a TypeError exception.
Let settings object be the current settings object.
If urls is empty, return.
Let urlRecords be « ».
For each url of urls:
Let urlRecord be the result of encoding-parsing a URL given url, relative to settings object.
If urlRecord is failure, then throw a "SyntaxError" DOMException.
Append urlRecord to urlRecords.
For each urlRecord of urlRecords:
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.
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]
WorkerNavigatorインターフェイスSupport in all current engines.
WorkerGlobalScopeインターフェイスのnavigator属性は、 WorkerNavigatorインターフェイスのインスタンスを返さなければならない。これは、ユーザーエージェント(クライアント)のIDおよび状態を表す:
[Exposed =Worker ]
interface WorkerNavigator {};
WorkerNavigator includes NavigatorID ;
WorkerNavigator includes NavigatorLanguage ;
WorkerNavigator includes NavigatorOnLine ;
WorkerNavigator includes NavigatorConcurrentHardware ;
WorkerLocationインターフェイスSupport in all current engines.
Support in all current engines.
[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オブジェクト)を持つ。
Support in all current engines.
hrefゲッターrステップは、thisのWorkerGlobalScopeオブジェクトのurl、serializedを返す。
Support in all current engines.
originゲッターステップは、thisのWorkerGlobalScopeオブジェクトのurlのoriginのserializationを返す。
Support in all current engines.
protocolゲッターステップは、thisの WorkerGlobalScopeオブジェクトのurlのschemeを返し、その後に":"が続く。
Support in all current engines.
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.
Support in all current engines.
The hostname getter steps are:
Let host be this's WorkerGlobalScope object's url's host.
If host is null, return the empty string.
Return host, serialized.
Support in all current engines.
The port getter steps are:
Let port be this's WorkerGlobalScope object's url's port.
If port is null, return the empty string.
Return port, serialized.
Support in all current engines.
The pathname getter steps are to return the result of URL path serializing this's WorkerGlobalScope object's url.
Support in all current engines.
The search getter steps are:
Let query be this's WorkerGlobalScope object's url's query.
If query is either null or the empty string, return the empty string.
Return "?", followed by query.
Support in all current engines.
The hash getter steps are:
Let fragment be this's WorkerGlobalScope object's url's fragment.
If fragment is either null or the empty string, return the empty string.
Return "#", followed by fragment.