Living Standard — Last Updated 29 October 2025
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 > 
The worker file is then:
import  *  as  filters from  "./filters.js" ; 
self. onmessage =  e =>  { 
  const  {  imageData,  filter }  =  e. data; 
  filters[ filter]( imageData); 
  self. postMessage( imageData,  [ imageData. data. buffer]); 
}; 
Which imports the file filters.js:
export  function  none()  {} 
export  function  grayscale({  data:  d })  { 
  for  ( let  i =  0 ;  i <  d. length;  i +=  4 )  { 
    const  [ r,  g,  b]  =  [ d[ i],  d[ i +  1 ],  d[ i +  2 ]]; 
    // 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.
この節は非規範的である。
This section introduces shared workers using a Hello World example. Shared workers use slightly different APIs, since each worker can have multiple connections.
This first example shows how you connect to a worker and how a worker can send a message back to the page when it connects to it. Received messages are displayed in a log.
Here is the HTML page:
<!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 > 
Here is the JavaScript worker:
onconnect =  function ( e)  { 
  var  port =  e. ports[ 0 ]; 
  port. postMessage( 'Hello World!' ); 
} 
This second example extends the first one by changing two things: first, messages are received using addEventListener() instead of an event handler IDL attribute, and second, a message is sent to the worker, causing the worker to send another message in return. Received messages are again displayed in a log.
Here is the HTML page:
<!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 > 
Here is the JavaScript worker:
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 
  } 
} 
Finally, the example is extended to show how two pages can connect to the same worker; in this case, the second page is merely in an iframe on the first page, but the same principle would apply to an entirely separate page in a separate top-level traversable.
Here is the outer HTML page:
<!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 > 
Here is the inner HTML page:
<!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 > 
Here is the JavaScript worker:
var  count =  0 ; 
onconnect =  function ( e)  { 
  count +=  1 ; 
  var  port =  e. ports[ 0 ]; 
  port. postMessage( 'Hello World! You are connection #'  +  count); 
  port. onmessage =  function ( e)  { 
    port. postMessage( 'pong' ); 
  } 
} 
この節は非規範的である。
In this example, multiple windows (viewers) can be opened that are all viewing the same map. All the windows share the same map information, with a single worker coordinating all the viewers. Each viewer can move around independently, but if they set any data on the map, all the viewers are updated.
The main page isn't interesting, it merely provides a way to open the viewers:
<!DOCTYPE HTML> 
< html  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 > 
The viewer is more involved:
<!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 > 
There are several key things worth noting about the way the viewer is written.
Multiple listeners. Instead of a single message processing function, the code here attaches multiple event listeners, each one performing a quick check to see if it is relevant for the message. In this example it doesn't make much difference, but if multiple authors wanted to collaborate using a single port to communicate with a worker, it would allow for independent code instead of changes having to all be made to a single event handling function.
Registering event listeners in this way also allows you to unregister specific listeners when you are done with them, as is done with the configure() method in this example.
Finally, the worker:
var  nextName =  0 ; 
function  getNextName()  { 
  // this could use more friendly names 
  // but for now just return a number 
  return  nextName++ ; 
} 
var  map =  [ 
 [ 0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ], 
 [ 1 ,  1 ,  0 ,  1 ,  0 ,  1 ,  1 ], 
 [ 0 ,  1 ,  0 ,  1 ,  0 ,  0 ,  0 ], 
 [ 0 ,  1 ,  0 ,  1 ,  0 ,  1 ,  1 ], 
 [ 0 ,  0 ,  0 ,  1 ,  0 ,  0 ,  0 ], 
 [ 1 ,  0 ,  0 ,  1 ,  1 ,  1 ,  1 ], 
 [ 1 ,  1 ,  0 ,  1 ,  1 ,  0 ,  1 ], 
]; 
function  wrapX( x)  { 
  if  ( x <  0 )  return  wrapX( x +  map[ 0 ]. length); 
  if  ( x >=  map[ 0 ]. length)  return  wrapX( x -  map[ 0 ]. length); 
  return  x; 
} 
function  wrapY( y)  { 
  if  ( y <  0 )  return  wrapY( y +  map. length); 
  if  ( y >=  map[ 0 ]. length)  return  wrapY( y -  map. length); 
  return  y; 
} 
function  wrap( val,  min,  max)  { 
  if  ( val <  min) 
    return  val +  ( max- min) + 1 ; 
  if  ( val >  max) 
    return  val -  ( max- min) - 1 ; 
  return  val; 
} 
function  sendMapData( viewer)  { 
  var  data =  '' ; 
  for  ( var  y =  viewer. y- 1 ;  y <=  viewer. y+ 1 ;  y +=  1 )  { 
    for  ( var  x =  viewer. x- 1 ;  x <=  viewer. x+ 1 ;  x +=  1 )  { 
      if  ( data !=  '' ) 
        data +=  ',' ; 
      data +=  map[ wrap( y,  0 ,  map[ 0 ]. length- 1 )][ wrap( x,  0 ,  map. length- 1 )]; 
    } 
  } 
  viewer. port. postMessage( 'map '  +  data); 
} 
var  viewers =  {}; 
onconnect =  function  ( event)  { 
  var  name =  getNextName(); 
  event. ports[ 0 ]. _data =  {  port:  event. ports[ 0 ],  name:  name,  x:  0 ,  y:  0 ,  }; 
  viewers[ name]  =  event. ports[ 0 ]. _data; 
  event. ports[ 0 ]. postMessage( 'cfg '  +  name); 
  event. ports[ 0 ]. onmessage =  getMessage; 
  sendMapData( event. ports[ 0 ]. _data); 
}; 
function  getMessage( event)  { 
  switch  ( event. data. substr( 0 ,  4 ))  { 
    case  'mov ' : 
      var  direction =  event. data. substr( 4 ); 
      var  dx =  0 ; 
      var  dy =  0 ; 
      switch  ( direction)  { 
        case  'up' :  dy =  - 1 ;  break ; 
        case  'down' :  dy =  1 ;  break ; 
        case  'left' :  dx =  - 1 ;  break ; 
        case  'right' :  dx =  1 ;  break ; 
      } 
      event. target. _data. x =  wrapX( event. target. _data. x +  dx); 
      event. target. _data. y =  wrapY( event. target. _data. y +  dy); 
      sendMapData( event. target. _data); 
      break ; 
    case  'set ' : 
      var  value =  event. data. substr( 4 ); 
      map[ event. target. _data. y][ event. target. _data. x]  =  value; 
      for  ( var  viewer in  viewers) 
        sendMapData( viewers[ viewer]); 
      break ; 
    case  'txt ' : 
      var  name =  event. target. _data. name; 
      var  message =  event. data. substr( 4 ); 
      for  ( var  viewer in  viewers) 
        viewers[ viewer]. port. postMessage( 'txt '  +  name +  ' '  +  message); 
      break ; 
    case  'msg ' : 
      var  party1 =  event. target. _data; 
      var  party2 =  viewers[ event. data. substr( 4 ). split( ' ' ,  1 )[ 0 ]]; 
      if  ( party2)  { 
        var  channel =  new  MessageChannel(); 
        party1. port. postMessage( 'msg '  +  party2. name,  [ channel. port1]); 
        party2. port. postMessage( 'msg '  +  party1. name,  [ channel. port2]); 
      } 
      break ; 
  } 
} 
Connecting to multiple pages. The script uses the onconnect event listener to listen for multiple connections.
Direct channels. When the worker receives a "msg" message from one viewer naming another viewer, it sets up a direct connection between the two, so that the two viewers can communicate directly without the worker having to proxy all the messages.
この節は非規範的である。
マルチコア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つの数値を受け取り、指定された数値の範囲に対して計算を実行し、その結果を親に報告する。
この節は非規範的である。
Suppose that a cryptography library is made available that provides three tasks:
The library itself is as follows:
function  handleMessage( e)  { 
  if  ( e. data ==  "genkeys" ) 
    genkeys( e. ports[ 0 ]); 
  else  if  ( e. data ==  "encrypt" ) 
    encrypt( e. ports[ 0 ]); 
  else  if  ( e. data ==  "decrypt" ) 
    decrypt( e. ports[ 0 ]); 
} 
function  genkeys( p)  { 
  var  keys =  _generateKeyPair(); 
  p. postMessage( keys[ 0 ]); 
  p. postMessage( keys[ 1 ]); 
} 
function  encrypt( p)  { 
  var  key,  state =  0 ; 
  p. onmessage =  function  ( e)  { 
    if  ( state ==  0 )  { 
      key =  e. data; 
      state =  1 ; 
    }  else  { 
      p. postMessage( _encrypt( key,  e. data)); 
    } 
  }; 
} 
function  decrypt( p)  { 
  var  key,  state =  0 ; 
  p. onmessage =  function  ( e)  { 
    if  ( state ==  0 )  { 
      key =  e. data; 
      state =  1 ; 
    }  else  { 
      p. postMessage( _decrypt( key,  e. data)); 
    } 
  }; 
} 
// 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 ); 
} 
Note that the crypto functions here are just stubs and don't do real cryptography.
This library could be used as follows:
<!DOCTYPE HTML> 
< html  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 > 
A later version of the API, though, might want to offload all the crypto work onto subworkers. This could be done as follows:
function  handleMessage( e)  { 
  if  ( e. data ==  "genkeys" ) 
    genkeys( e. ports[ 0 ]); 
  else  if  ( e. data ==  "encrypt" ) 
    encrypt( e. ports[ 0 ]); 
  else  if  ( e. data ==  "decrypt" ) 
    decrypt( e. ports[ 0 ]); 
} 
function  genkeys( p)  { 
  var  generator =  new  Worker( 'libcrypto-v2-generator.js' ); 
  generator. postMessage( '' ,  [ p]); 
} 
function  encrypt( p)  { 
  p. onmessage =  function  ( e)  { 
    var  key =  e. data; 
    var  encryptor =  new  Worker( 'libcrypto-v2-encryptor.js' ); 
    encryptor. postMessage( key,  [ p]); 
  }; 
} 
function  encrypt( p)  { 
  p. onmessage =  function  ( e)  { 
    var  key =  e. data; 
    var  decryptor =  new  Worker( 'libcrypto-v2-decryptor.js' ); 
    decryptor. postMessage( key,  [ p]); 
  }; 
} 
// 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 }; 
The little subworkers would then be as follows.
For generating key pairs:
onmessage =  function  ( e)  { 
  var  k =  _generateKeyPair(); 
  e. ports[ 0 ]. postMessage( k[ 0 ]); 
  e. ports[ 0 ]. postMessage( k[ 1 ]); 
  close(); 
} 
function  _generateKeyPair()  { 
  return  [ Math. random(),  Math. random()]; 
} 
For encrypting:
onmessage =  function  ( e)  { 
  var  key =  e. data; 
  e. ports[ 0 ]. onmessage =  function  ( e)  { 
    var  s =  e. data; 
    postMessage( _encrypt( key,  s)); 
  } 
} 
function  _encrypt( k,  s)  { 
  return  'encrypted-'  +  k +  ' '  +  s; 
} 
For decrypting:
onmessage =  function  ( e)  { 
  var  key =  e. data; 
  e. ports[ 0 ]. onmessage =  function  ( e)  { 
    var  s =  e. data; 
    postMessage( _decrypt( key,  s)); 
  } 
} 
function  _decrypt( k,  s)  { 
  return  s. substr( s. indexOf( ' ' ) + 1 ); 
} 
Notice how the users of the API don't have to even know that this is happening — the API hasn't changed; the library can delegate to subworkers without changing its API, even though it is accepting data using message channels.
この節は非規範的である。
Creating a worker requires a URL to a JavaScript file. The Worker() constructor is invoked with the URL to that file as its only argument; a worker is then created and returned:
var  worker =  new  Worker( 'helper.js' ); If you want your worker script to be interpreted as a module script instead of the default classic script, you need to use a slightly different signature:
var  worker =  new  Worker( 'helper.mjs' ,  {  type:  "module"  }); この節は非規範的である。
Dedicated workers use MessagePort objects behind the scenes, and thus support all the same features, such as sending structured data, transferring binary data, and transferring other ports.
To receive messages from a dedicated worker, use the onmessage event handler IDL attribute on the Worker object:
worker. onmessage =  function  ( event)  {  ...  }; You can also use the addEventListener() method.
The implicit MessagePort used by dedicated workers has its port message queue implicitly enabled when it is created, so there is no equivalent to the MessagePort interface's start() method on the Worker interface.
To send data to a worker, use the postMessage() method. Structured data can be sent over this communication channel. To send ArrayBuffer objects efficiently (by transferring them rather than cloning them), list them in an array in the second argument.
worker. postMessage({ 
  operation:  'find-edges' , 
  input:  buffer,  // an ArrayBuffer object 
  threshold:  0.6 , 
},  [ buffer]); To receive a message inside the worker, the onmessage event handler IDL attribute is used.
onmessage =  function  ( event)  {  ...  }; You can again also use the addEventListener() method.
In either case, the data is provided in the event object's data attribute.
To send messages back, you again use postMessage(). It supports the structured data in the same manner.
postMessage( event. data. input,  [ event. data. input]);  // transfer the buffer back Support in all current engines.
この節は非規範的である。
Shared workers are identified by the URL of the script used to create it, optionally with an explicit name. The name allows multiple instances of a particular shared worker to be started.
Shared workers are scoped by origin. Two different sites using the same names will not collide. However, if a page tries to use the same shared worker name as another page on the same site, but with a different script URL, it will fail.
Creating shared workers is done using the SharedWorker() constructor. This constructor takes the URL to the script to use for its first argument, and the name of the worker, if any, as the second argument.
var  worker =  new  SharedWorker( 'service.js' ); Communicating with shared workers is done with explicit MessagePort objects. The object returned by the SharedWorker() constructor holds a reference to the port on its port attribute.
worker. port. onmessage =  function  ( event)  {  ...  }; 
worker. port. postMessage( 'some message' ); 
worker. port. postMessage({  foo:  'structured' ,  bar:  [ 'data' ,  'also' ,  'possible' ]}); Inside the shared worker, new clients of the worker are announced using the connect event. The port for the new client is given by the event object's source attribute.
onconnect =  function  ( event)  { 
  var  newPort =  event. source; 
  // set up a listener 
  newPort. onmessage =  function  ( event)  {  ...  }; 
  // send a message back to the port 
  newPort. postMessage( 'ready!' );  // can also send structured data, of course 
}; This standard defines two kinds of workers: dedicated workers, and shared workers. Dedicated workers, once created, are linked to their creator, but message ports can be used to communicate from a dedicated worker to multiple other browsing contexts or workers. Shared workers, on the other hand, are named, and once created any script running in the same origin can obtain a reference to that worker and communicate with it. Service Workers defines a third kind. [SW]
The global scope is the "inside" of a worker.
WorkerGlobalScope common interfaceSupport 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 serves as the base class for specific types of worker global scope objects, including DedicatedWorkerGlobalScope, SharedWorkerGlobalScope, and 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 object.workerGlobal.navigatorSupport in all current engines.
WorkerNavigator object.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 interfaceSupport 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 objects have an associated inside port (a MessagePort). This port is part of a channel that is set up when the worker is created, but it is not exposed. This object must never be garbage collected before the DedicatedWorkerGlobalScope object.
dedicatedWorkerGlobal.nameDedicatedWorkerGlobalScope/name
Support in all current engines.
Returns dedicatedWorkerGlobal's name, i.e. the value given to the Worker constructor. Primarily useful for debugging.
dedicatedWorkerGlobal.postMessage(message [, transfer ])DedicatedWorkerGlobalScope/postMessage
Support in all current engines.
dedicatedWorkerGlobal.postMessage(message [, { transfer } ])Clones message and transmits it to the Worker object associated with dedicatedWorkerGlobal. transfer can be passed as a list of objects that are to be transferred rather than cloned.
dedicatedWorkerGlobal.close()DedicatedWorkerGlobalScope/close
Support in all current engines.
Aborts 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 interfaceSupport in all current engines.
[Global =(Worker ,SharedWorker ),Exposed =SharedWorker ]
interface  SharedWorkerGlobalScope  : WorkerGlobalScope  {
  [Replaceable ] readonly  attribute  DOMString  name ;
  undefined  close ();
  attribute  EventHandler  onconnect ;
};A SharedWorkerGlobalScope object has associated constructor origin (an origin), constructor URL (a URL record), and credentials (a credentials mode). They are initialized when the SharedWorkerGlobalScope object is created, in the run a worker algorithm.
Shared workers receive message ports through connect events on their SharedWorkerGlobalScope object for each connection.
sharedWorkerGlobal.nameSupport in all current engines.
Returns sharedWorkerGlobal's name, i.e. the value given to the SharedWorker constructor. Multiple SharedWorker objects can correspond to the same shared worker (and SharedWorkerGlobalScope), by reusing the same name.
sharedWorkerGlobal.close()Support in all current engines.
Aborts 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.
The following are the event handlers (and their corresponding event handler event types) that must be supported, as event handler IDL attributes, by objects implementing the SharedWorkerGlobalScope interface:
| イベントハンドラー | イベントハンドラーイベント型 | 
|---|---|
| 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 | 
A worker event loop's task queues only have events, callbacks, and networking activity as tasks. These worker event loops are created by the run a worker algorithm.
Each WorkerGlobalScope object has a closing flag, which must be initially false, but which can get set to true by the algorithms in the processing model section below.
Once the WorkerGlobalScope's closing flag is set to true, the event loop's task queues must discard any further tasks that would be added to them (tasks already on the queue are unaffected except where otherwise specified). Effectively, once the closing flag is true, timers stop firing, notifications for all pending background operations are dropped, etc.
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 WorkerGlobalScope global is actively needed if the following algorithm returns 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 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 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を返す。
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 get suspended or un-suspended based on whether they are suspendable.
Workers that have been closed, but keep executing, can be terminated at the user agent's discretion, once they stop being actively needed.
Note that every WorkerGlobalScope that is actively needed is protected, and every WorkerGlobalScope that is protected is permissible. (But the converses do not hold.)
An important difference between protected and permissible is that a WorkerGlobalScope is protected only if its transitive set of owners contains at least one fully active Document, whereas a WorkerGlobalScope can be permissible even if all the Documents in its transitive set of owners are in bfcache.
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, then:
Set worker global scope's constructor origin to outside settings's origin.
Set worker global scope's constructor URL to url.
Set worker global scope's credentials to options["credentials"].
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:
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, 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.
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, then:
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.
Whenever an uncaught runtime script error occurs in one of the worker's scripts, if the error did not occur while handling a previous script error, the user agent will report it for the worker's WorkerGlobalScope object.
AbstractWorker mixininterface  mixin  AbstractWorker  {
  attribute  EventHandler  onerror ;
};The following are the event handlers (and their corresponding event handler event types) that must be supported, as event handler IDL attributes, by objects implementing the AbstractWorker interface:
| イベントハンドラー | イベントハンドラーイベント型 | 
|---|---|
| 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 inherited origin be outside settings's origin.
Let realm be the value of execution context's Realm component.
Let worker global scope be realm's global object.
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 a unique opaque origin if worker global scope's url's scheme is "data", and inherited origin otherwise.
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 interfaceSupport 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.
Returns a new Worker object. scriptURL will be fetched and executed in the background, creating a new global environment for which worker represents the communication channel.
options can contain the following values:
name can be used to define the name of that global environment, primarily for debugging purposes.
type can be used to load the new global environment from scriptURL as a JavaScript module, by setting it to the value "module".
credentials can be used to specify how scriptURL is fetched, but only if type is set to "module".
worker.terminate()Support in all current engines.
worker.postMessage(message [, transfer ])Support in all current engines.
worker.postMessage(message [, { transfer } ])Clones message and transmits it to worker's global environment. transfer can be passed as a list of objects that are to be transferred rather than cloned.
Each Worker object has an associated outside port (a MessagePort). This port is part of a channel that is set up when the worker is created, but it is not exposed. 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.
The postMessage() method's first argument can be structured data:
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 interfaceSupport in all current engines.
[Exposed =Window ]
interface  SharedWorker  : EventTarget  {
  constructor ((TrustedScriptURL or  USVString ) scriptURL , optional  (DOMString  or  WorkerOptions ) options  = {});
  readonly  attribute  MessagePort  port ;
};
SharedWorker  includes  AbstractWorker ;sharedWorker = new SharedWorker(scriptURL [, name ])Support in all current engines.
Returns a new SharedWorker object. scriptURL will be fetched and executed in the background, creating a new global environment for which sharedWorker represents the communication channel. name can be used to define the name of that global environment.
sharedWorker = new SharedWorker(scriptURL [, options ])Returns a new SharedWorker object. scriptURL will be fetched and executed in the background, creating a new global environment for which sharedWorker represents the communication channel.
options can contain the following values:
name can be used to define the name of that global environment.
type can be used to load the new global environment from scriptURL as a JavaScript module, by setting it to the value "module".
credentials can be used to specify how scriptURL is fetched, but only if type is set to "module".
Note that attempting to construct a shared worker with options whose type, or credentials values mismatch those of an existing shared worker with the same constructor URL and name, will cause the returned sharedWorker to fire an error event and not connect to the existing shared worker.
sharedWorker.portSupport in all current engines.
Returns sharedWorker's MessagePort object which can be used to communicate with the global environment.
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:
Let workerStorageKey be the result of running obtain a storage key for non-storage purposes given scope's relevant settings object.
If all of the following are true:
name"],then:
Set workerGlobalScope to scope.
data: URLs create a worker with an opaque origin. Both the constructor origin and constructor URL are compared so the same data: URL can be used within an origin to get to the same SharedWorkerGlobalScope object, but cannot be used to bypass the same origin restriction.
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 type is not equal to options["type"]; or
workerGlobalScope's credentials is not equal to options["credentials"]
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.hardwareConcurrencyReturns the number of logical processors potentially available to the user agent.
 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 interfaceSupport 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 ;
};A WorkerLocation object has an associated WorkerGlobalScope object (a WorkerGlobalScope object).
Support in all current engines.
The href getter steps are to return this's WorkerGlobalScope object's url, serialized.
Support in all current engines.
The origin getter steps are to return the serialization of this's WorkerGlobalScope object's url's origin.
Support in all current engines.
The protocol getter steps are to return this's WorkerGlobalScope object's url's scheme, followed by ":".
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.