Living Standard — Last Updated 2 May 2026
Support in all current engines.
This section is non-normative.
This specification defines an API for running scripts in the background independently of any user interface scripts.
This allows for long-running scripts that are not interrupted by scripts that respond to clicks or other user interactions, and allows long tasks to be executed without yielding to keep the page responsive.
Workers (as these background scripts are called herein) are relatively heavy-weight, and are not intended to be used in large numbers. For example, it would be inappropriate to launch one worker for each pixel of a four megapixel image. The examples below show some appropriate uses of workers.
Generally, workers are expected to be long-lived, have a high start-up performance cost, and a high per-instance memory cost.
This section is non-normative.
There are a variety of uses that workers can be put to. The following subsections show various examples of this use.
This section is non-normative.
The simplest use of workers is for performing a computationally expensive task without interrupting the user interface.
In this example, the main document spawns a worker to (naïvely) compute prime numbers, and progressively displays the most recently found prime number.
The main page is as follows:
<!DOCTYPE HTML>
< html 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 >
The Worker() constructor call creates a worker and returns a
Worker object representing that worker, which is used to communicate with the worker.
That object's onmessage event handler
allows the code to receive messages from the worker.
The worker itself is as follows:
var n = 1 ;
search: while ( true ) {
n += 1 ;
for ( var i = 2 ; i <= Math. sqrt( n); i += 1 )
if ( n % i == 0 )
continue search;
// found a prime!
postMessage( n);
}
The bulk of this code is simply an unoptimized search for a prime number. The postMessage() method is used to send a
message back to the page when a prime is found.
This section is non-normative.
All of our examples so far show workers that run classic
scripts. Workers can instead be instantiated using module
scripts, which have the usual benefits: the ability to use the JavaScript
import statement to import other modules; strict mode by default; and
top-level declarations not polluting the worker's global scope.
As the import statement is available, the importScripts() method will automatically fail
inside module workers.
In this example, the main document uses a worker to do off-main-thread image manipulation. It imports the filters used from another module.
The main page is as follows:
<!DOCTYPE html>
< 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 is non-normative.
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' );
}
}
This section is non-normative.
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.
This section is non-normative.
With multicore CPUs becoming prevalent, one way to obtain better performance is to split computationally expensive tasks amongst multiple workers. In this example, a computationally expensive task that is to be performed for every number from 1 to 10,000,000 is farmed out to ten subworkers.
The main page is as follows, it just reports the result:
<!DOCTYPE HTML>
< html 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 >
The worker itself is as follows:
// 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!
}
It consists of a loop to start the subworkers, and then a handler that waits for all the subworkers to respond.
The subworkers are implemented as follows:
var start;
onmessage = getStart;
function getStart( event) {
start = 1 * event. data;
onmessage = getEnd;
}
var end;
function getEnd( event) {
end = 1 * event. data;
onmessage = null ;
work();
}
function work() {
var result = 0 ;
for ( var i = start; i < end; i += 1 ) {
// perform some complex calculation here
result += 1 ;
}
postMessage( result);
close();
}
They receive two numbers in two events, perform the computation for the range of numbers thus specified, and then report the result back to the parent.
This section is non-normative.
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.
This section is non-normative.
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" });
This section is non-normative.
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) { ... };
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 To receive a message inside the worker, the You can again also use the In either case, the data is provided in the event object's To send messages back, you again use Support in all current engines. This section is non-normative. 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 Communicating with shared workers is done with explicit Inside the shared worker, new clients of the worker are announced using the 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. Support in all current engines. It is a set, instead of a single owner, to accommodate
A A A The name can have different
semantics for each subclass of A A A A Support in all current engines. Support in all current engines. Support in all current engines. WorkerGlobalScope/importScripts Support in all current engines. The The While the 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
Support in all current engines. WorkerGlobalScope/languagechange_event Support in all current engines. WorkerGlobalScope/offline_event WorkerGlobalScope/online_event Support in all current engines. DedicatedWorkerGlobalScope/name Support in all current engines. Returns dedicatedWorkerGlobal's name, i.e. the value given to the
DedicatedWorkerGlobalScope/postMessage Support in all current engines. Clones message and transmits it to the DedicatedWorkerGlobalScope/close Support in all current engines. Aborts dedicatedWorkerGlobal. The The 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 Support in all current engines. A Shared workers receive message ports through Support in all current engines. Returns sharedWorkerGlobal's name, i.e. the value given to the
Support in all current engines. Aborts sharedWorkerGlobal. The The 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/connect_event Support in all current engines. 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 Once the Workers communicate with other workers and with Each 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 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 If global is not a 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 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 If owner is a Return false. A If global is in extended
lifetime, then return true. For each owner of global's
owner set: If owner is a If owner is a Return false. A If global is not actively needed,
then return false. If global is in extended
lifetime, then return true. If global is a 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. Return false. A If global is in extended
lifetime, then return true. If all of the following are true: global is a 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. Return false. The following relationships hold between these terms: Every Every Every However, the converses do not always hold: A A A If global is actively needed, then
return false. If global is permissible, then return
true. Return 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 Let is shared be true if worker is a 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
Let worker global scope be the global
object of realm execution context's Realm component.
This is the 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[" Set worker global scope's extended lifetime to
options[" Let destination be " Obtain script by switching on options[" In both cases, let performFetch be the following perform the fetch hook given request,
isTopLevel, and processCustomFetchResponse: If isTopLevel is false, fetch
request with processCustomFetchResponse, and abort these steps. Fetch request with 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
" 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 " 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 " 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 " This is a conservative default for now, while we figure out how workers in
general, and 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 Run the environment discarding steps
for inside settings. Abort these steps. Associate worker with worker global scope. Let inside port be a new 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 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 Enable the client message queue of the
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 If there are any tasks queued in the
Abort the script currently running in the
worker. If the worker's 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 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
Support in all current engines. Support in all current engines. Support in all current engines. 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 " 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 " Return 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 Otherwise, set settings object's top-level origin to an
implementation-defined value. Set realm's [[HostDefined]] field to settings object. Return settings object. Support in all current engines. Support in all current engines. Returns a new options can contain the following values: Support in all current engines. Support in all current engines. 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 The The The The Let compliantScriptURL be the result of invoking the get trusted type compliant string algorithm with 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 If workerURL is failure, then throw a " 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. Support in all current engines. Support in all current engines. Returns a new Returns a new options can contain the following values: Note that attempting to construct a shared worker with options
whose Support in all current engines. Returns sharedWorker's 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 The Let compliantScriptURL be the result of invoking the get trusted type compliant string algorithm with If options is a 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 If urlRecord is failure, then throw a " 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
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: then: Set workerGlobalScope to scope. 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[" workerGlobalScope's extended lifetime is not
equal to options[" then: Queue a global task on the DOM manipulation task source
given worker's relevant global object to fire an event named 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 Abort these steps. Associate worker with workerGlobalScope. Let insidePort be a new Entangle outsidePort and insidePort. Queue a global task on the DOM manipulation task source
given workerGlobalScope to fire an event
named 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. Returns the number of logical processors potentially available to the user agent.
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 Let urlStrings be « ». For each url of urls: Append the result of invoking the get trusted type compliant string algorithm with Import scripts into worker global scope given this and
urlStrings. To import scripts into worker global scope, given a
If worker global scope's type is " 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 " 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] Support in all current engines. The Support in all current engines. Support in all current engines. A Support in all current engines. The Support in all current engines. The Support in all current engines. The Support in all current engines. The Let url be this's 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 " Support in all current engines. The Let host be this's If host is null, return the empty string. Return host, serialized. Support in all current engines. The Let port be this's If port is null, return the empty string. Return port, serialized. Support in all current engines. The Support in all current engines. The Let query be this's If query is either null or the empty string, return the empty string. Return " Support in all current engines. The Let fragment be this's If fragment is either null or the empty string, return the empty string. Return "postMessage() method. Structured data can be sent over this
communication channel. To send
workeronmessage event handler IDL attribute is used.onmessage method.data attribute.postMessage(). It supports the
structured data in the same manner.postMessage10.1.3.3 Shared workers
Opera10.6+Edge79+
Edge (Legacy)?Internet ExplorerNo
Firefox Android33+Safari iOS16+Chrome AndroidNoWebView Android?Samsung Internet4.0–5.0Opera Android11–14SharedWorker()
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.MessagePort objects. The
object returned by the SharedWorker() constructor holds a
reference to the port on its port attribute.workerconnect event. The port for the new client is
given by the event object's source attribute.onconnect 10.2 Infrastructure
10.2.1 The global scope
10.2.1.1 The
WorkerGlobalScope common interface
Opera10.6+Edge79+
Edge (Legacy)12+Internet Explorer10+
Firefox Android?Safari iOS5+Chrome Android?WebView Android?Samsung Internet?Opera Android11+[WorkerGlobalScope serves as the base class for specific types of worker global
scope objects, including DedicatedWorkerGlobalScope,
SharedWorkerGlobalScope, and 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.SharedWorkerGlobalScope objects.WorkerGlobalScope object has an associated type ("classic" or "module"). It is set during creation.WorkerGlobalScope object has an associated url (null or a URL). It is initially
null.WorkerGlobalScope object has an associated name (a string). It is set during creation.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
WorkerGlobalScope object has an associated policy container (a policy
container). It is initially a new policy container.WorkerGlobalScope object has an associated embedder policy (an embedder
policy).WorkerGlobalScope object has an associated module map. It is a module map,
initially empty.WorkerGlobalScope object has an associated cross-origin isolated
capability boolean. It is initially false.workerGlobal.self
Opera11.5+Edge79+
Edge (Legacy)12+Internet Explorer10+
Firefox Android34+Safari iOS5+Chrome Android?WebView Android?Samsung Internet?Opera Android?workerGlobal.location
Opera11.5+Edge79+
Edge (Legacy)12+Internet Explorer10+
Firefox Android?Safari iOS5+Chrome Android?WebView Android?Samsung Internet?Opera Android?WorkerLocation object.workerGlobal.navigator
Opera11.5+Edge79+
Edge (Legacy)17+Internet Explorer10+
Firefox Android?Safari iOS5+Chrome Android?WebView Android?Samsung Internet?Opera Android?WorkerNavigator object.workerGlobal.importScripts(...urls)
Opera10.6+Edge79+
Edge (Legacy)12+Internet Explorer10+
Firefox Android?Safari iOS5+Chrome Android?WebView Android?Samsung Internet?Opera Android11+self attribute must return the
WorkerGlobalScope object itself.location attribute must return the
WorkerLocation object whose associated WorkerGlobalScope object is
the WorkerGlobalScope object.WorkerLocation object is created after the
WorkerGlobalScope object, this is not problematic as it cannot be observed from
script.
WorkerGlobalScope interface:Event handler Event handler event type
onerror
Opera11.5+Edge79+
Edge (Legacy)12+Internet Explorer10+
Firefox Android?Safari iOS5+Chrome Android?WebView Android?Samsung Internet?Opera Android? error
onlanguagechange
Opera11.5+Edge79+
Edge (Legacy)?Internet ExplorerNo
Firefox Android?Safari iOS5+Chrome Android?WebView Android37+Samsung Internet?Opera Android? languagechange
onoffline
Opera?EdgeNo
Edge (Legacy)?Internet ExplorerNo
Firefox Android?Safari iOS?Chrome Android?WebView Android?Samsung Internet?Opera Android? offline
ononline
Opera?EdgeNo
Edge (Legacy)?Internet ExplorerNo
Firefox Android?Safari iOS?Chrome Android?WebView Android?Samsung Internet?Opera Android? online
onrejectionhandled rejectionhandled
onunhandledrejection unhandledrejection
10.2.1.2 Dedicated workers and the
DedicatedWorkerGlobalScope interface
Opera10.6+Edge79+
Edge (Legacy)12+Internet Explorer10+
Firefox Android?Safari iOS5+Chrome Android?WebView Android?Samsung Internet?Opera Android11+[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.name
Opera?Edge79+
Edge (Legacy)18Internet ExplorerNo
Firefox Android?Safari iOS?Chrome Android?WebView Android?Samsung Internet?Opera Android?Worker constructor. Primarily useful for debugging.dedicatedWorkerGlobal.postMessage(message [, transfer ])
Opera10.6+Edge79+
Edge (Legacy)12+Internet Explorer10+
Firefox Android?Safari iOS5+Chrome Android?WebView Android?Samsung Internet?Opera Android11+dedicatedWorkerGlobal.postMessage(message [, { transfer } ])Worker object associated
with dedicatedWorkerGlobal. transfer can be passed as a list of objects
that are to be transferred rather than cloned.dedicatedWorkerGlobal.close()
Opera10.6+Edge79+
Edge (Legacy)12+Internet Explorer10+
Firefox Android?Safari iOS5+Chrome Android?WebView Android?Samsung Internet?Opera Android11+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.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.close() method steps are to
close a worker given this.
10.2.1.3 Shared workers and the
SharedWorkerGlobalScope interface
Opera10.6+Edge79+
Edge (Legacy)?Internet ExplorerNo
Firefox Android?Safari iOS16+Chrome Android?WebView Android37+Samsung Internet?Opera Android11+[SharedWorkerGlobalScope object has associated constructor origin (an
origin), constructor
URL (a URL record), and credentials (a credentials mode), and extended lifetime (a boolean).
They are initialized when the SharedWorkerGlobalScope object is created, in the
run a worker algorithm.connect events on their SharedWorkerGlobalScope object for each
connection.sharedWorkerGlobal.name
Opera10.6+Edge79+
Edge (Legacy)?Internet ExplorerNo
Firefox Android?Safari iOS16+Chrome Android?WebView Android?Samsung Internet?Opera Android11+SharedWorker constructor. Multiple SharedWorker objects can correspond
to the same shared worker (and SharedWorkerGlobalScope), by reusing the same
name.sharedWorkerGlobal.close()
Opera10.6+Edge79+
Edge (Legacy)?Internet ExplorerNo
Firefox Android?Safari iOS16+Chrome Android?WebView Android?Samsung Internet?Opera Android11+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.close() method steps are to close a
worker given this.
SharedWorkerGlobalScope interface:Event handler Event handler event type
onconnect
Opera10.6+Edge79+
Edge (Legacy)?Internet ExplorerNo
Firefox Android?Safari iOS16+Chrome Android?WebView Android37+Samsung Internet?Opera Android11+ connect
10.2.2 The event loop
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.WorkerGlobalScope's closing flag is set to true, the event
loop's task queues must discard any
further tasks that would be added to them (tasks already on the
queue are unaffected except where otherwise specified). Effectively, once the closing flag is true, timers stop firing,
notifications for all pending background operations are dropped, etc.10.2.3 The worker's lifetime
Windows through message channels and their MessagePort
objects.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.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.
WorkerGlobalScope global is in extended lifetime if the following algorithm returns true:SharedWorkerGlobalScope, then return
false.Document that is fully active, then
return false.Document and the amount of time that
owner that has been non-fully active is less than the user agent's
extended lifetime shared worker timeout, then return true.WorkerGlobalScope that is in extended lifetime, then return true.WorkerGlobalScope global is actively needed if the following algorithm returns true:Document, and owner is fully
active, then return true.WorkerGlobalScope that is actively needed, then return true.WorkerGlobalScope global is protected if the following algorithm returns true:SharedWorkerGlobalScope, then return true.WorkerGlobalScope global is permissible if the following algorithm returns true:SharedWorkerGlobalScope;WorkerGlobalScope that is in extended lifetime is actively
needed, protected, and permissible.WorkerGlobalScope that is actively
needed or protected is permissible.WorkerGlobalScope that is protected is actively needed.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.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.WorkerGlobalScope global is suspendable if the following algorithm returns true:10.2.4 Processing model
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.SharedWorker
object, and false otherwise.SharedWorkerGlobalScope object. Otherwise, create a new
DedicatedWorkerGlobalScope object.DedicatedWorkerGlobalScope or
SharedWorkerGlobalScope object created in the previous step.credentials"].extendedLifetime"].sharedworker" if is
shared is true, and "worker" otherwise.type"]:classic"module"credentials
member of options, inside settings, and with onComplete and
performFetch as defined below.Blocked" when executed upon worker global scope, set
response to a network error. [CSP]logical" or "concrete". The one chosen is
implementation-defined.concrete".data", then set
worker global scope's cross-origin isolated
capability to false. for more details.error
at worker.MessagePort object in
inside settings's realm.WorkerLocation object and associate it with worker global
scope.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.service worker client is
worker global scope's relevant settings object.
WorkerGlobalScope object's closing flag to true.WorkerGlobalScope object's relevant agent's event loop's task
queues, discard them without processing them.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.10.2.5 Runtime script errors
WorkerGlobalScope object.10.2.6 Creating workers
10.2.6.1 The
AbstractWorker mixinAbstractWorker interface:Event handler Event handler event type
onerror
Opera?Edge79+
Edge (Legacy)17+Internet ExplorerNo
Firefox Android?Safari iOS?Chrome Android?WebView Android?Samsung Internet?Opera Android?
Opera10.6+Edge79+
Edge (Legacy)?Internet ExplorerNo
Firefox Android33+Safari iOS16+Chrome AndroidNoWebView Android?Samsung Internet4.0–5.0Opera Android11–14
Opera10.6+Edge79+
Edge (Legacy)12+Internet Explorer10+
Firefox Android?Safari iOS5+Chrome Android?WebView Android?Samsung Internet?Opera Android11+ error
10.2.6.2 Script settings for workers
data"; otherwise
outside settings's origin.data", then return
true.DedicatedWorkerGlobalScope object,
then set settings object's top-level origin to outside
settings's top-level origin.10.2.6.3 Dedicated workers and the
Worker interface
Opera10.6+Edge79+
Edge (Legacy)12+Internet Explorer10+
Firefox Android?Safari iOS5+Chrome Android?WebView Android?Samsung Internet?Opera Android11+[worker = new Worker(scriptURL [, options ])
Opera10.6+Edge79+
Edge (Legacy)12+Internet Explorer10+
Firefox Android?Safari iOS5+Chrome Android?WebView Android?Samsung Internet?Opera Android11+Worker object. scriptURL will be fetched and executed
in the background, creating a new global environment for which worker represents the
communication channel.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()
Opera10.6+Edge79+
Edge (Legacy)12+Internet Explorer10+
Firefox Android?Safari iOS5+Chrome Android?WebView Android?Samsung Internet?Opera Android11+worker.postMessage(message [, transfer ])
Opera10.6+Edge79+
Edge (Legacy)12+Internet Explorer10+
Firefox Android?Safari iOS5+Chrome Android?WebView Android?Samsung Internet?Opera Android11+worker.postMessage(message [, { transfer } ])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.terminate()
method steps are to terminate a worker given this's worker.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()
method's first argument can be structured data:worker
new Worker(scriptURL,
options) constructor steps are:this's relevant global
object, scriptURL, "Worker constructor", and "script".opaque origin.SyntaxError"
outsidePort be a new MessagePort in
outsideSettings's realm.10.2.6.4 Shared workers and the
SharedWorker interface
Opera10.6+Edge79+
Edge (Legacy)?Internet ExplorerNo
Firefox Android33+Safari iOS16+Chrome AndroidNoWebView Android?Samsung Internet4.0–5.0Opera Android11–14[sharedWorker = new SharedWorker(scriptURL [, name ])
Opera10.6+Edge79+
Edge (Legacy)?Internet ExplorerNo
Firefox Android33+Safari iOS16+Chrome AndroidNoWebView Android?Samsung Internet4.0–5.0Opera Android11–14SharedWorker object. scriptURL will be fetched and
executed in the background, creating a new global environment for which sharedWorker
represents the communication channel. name can be used to define the name of that global environment.sharedWorker = new SharedWorker(scriptURL [, options ])SharedWorker 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.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".extendedLifetime can be
set to request that the newly-created global environment be given extra time to perform its
operations even after all of its owners have disappeared. This
can be useful, for example, for performing asynchronous work after page unload.type, credentials, or extendedLifetime 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.port
Opera10.6+Edge79+
Edge (Legacy)?Internet ExplorerNo
Firefox Android33+Safari iOS16+Chrome AndroidNoWebView Android?Samsung Internet4.0–5.0Opera Android11–14MessagePort object which can be used to
communicate with the global environment.
SharedWorker has a port, a
MessagePort set when the object is created.new
SharedWorker(scriptURL, options) constructor steps are:this's relevant global
object, scriptURL, "SharedWorker constructor", and
"script".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.opaque origin.SyntaxError"
outsidePort be a new MessagePort in
outsideSettings's realm.SharedWorkerGlobalScope objects:name"],opaque origin. Both the constructor origin and
constructor URL are
compared so the same origin to get to the same SharedWorkerGlobalScope object, but cannot
be used to bypass the same origin restriction.credentials"];
orextendedLifetime"],error at worker.error at worker.MessagePort in
insideSettings's realm.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.10.2.7 Concurrent hardware capabilities
self.navigator.hardwareConcurrency
Opera?Edge79+
Edge (Legacy)15+Internet ExplorerNo
Firefox Android?Safari iOS?Chrome Android?WebView Android?Samsung Internet?Opera Android?
Opera?Edge79+
Edge (Legacy)15+Internet ExplorerNo
Firefox Android?Safari iOS?Chrome Android?WebView Android?Samsung Internet?Opera Android?
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.10.3 APIs available to workers
10.3.1 Importing scripts and libraries
importScripts(...urls)
method steps are:this's relevant global
object, url, "WorkerGlobalScope importScripts", and
"script" to urlStrings.WorkerGlobalScope object worker global scope, a list of
scalar value strings urls, and an optional
perform the fetch hook
performFetch:module", throw a
SyntaxError"
Append urlRecord to
urlRecords.10.3.2 The
WorkerNavigator interface
Opera12.1+Edge79+
Edge (Legacy)12+Internet Explorer10+
Firefox Android?Safari iOS5+Chrome Android?WebView Android?Samsung Internet?Opera Android12.1+navigator attribute of the
WorkerGlobalScope interface must return an instance of the
WorkerNavigator interface, which represents the identity and state of the user agent
(the client):[10.3.3 The
WorkerLocation interface
Opera12.1+Edge79+
Edge (Legacy)12+Internet Explorer10+
Firefox Android?Safari iOS5+Chrome Android?WebView Android?Samsung Internet?Opera Android12.1+
Opera15+Edge79+
Edge (Legacy)12+Internet Explorer10+
Firefox Android?Safari iOS5+Chrome Android?WebView Android37+Samsung Internet?Opera Android14+[WorkerLocation object has an associated WorkerGlobalScope object (a
WorkerGlobalScope object).
Opera12.1+Edge79+
Edge (Legacy)12+Internet Explorer10+
Firefox Android?Safari iOS5+Chrome Android?WebView Android?Samsung Internet?Opera Android12.1+href getter steps are to return this's
WorkerGlobalScope
object's url, serialized.
Opera?Edge79+
Edge (Legacy)14+Internet ExplorerNo
Firefox Android?Safari iOS?Chrome Android?WebView Android?Samsung Internet?Opera Android?origin getter steps are to return the serialization of this's WorkerGlobalScope object's
url's origin.
Opera12.1+Edge79+
Edge (Legacy)12+Internet Explorer10+
Firefox Android?Safari iOS5+Chrome Android?WebView Android?Samsung Internet?Opera Android12.1+protocol getter steps are to return
this's WorkerGlobalScope object's
url's scheme, followed by ":".
Opera12.1+Edge79+
Edge (Legacy)12+Internet Explorer10+
Firefox Android?Safari iOS5+Chrome Android?WebView Android?Samsung Internet?Opera Android12.1+host getter steps are:WorkerGlobalScope object's
url.:" and url's port, serialized.
Opera12.1+Edge79+
Edge (Legacy)12+Internet Explorer10+
Firefox Android?Safari iOS5+Chrome Android?WebView Android?Samsung Internet?Opera Android12.1+hostname getter steps are:WorkerGlobalScope object's
url's host.
Opera12.1+Edge79+
Edge (Legacy)12+Internet Explorer10+
Firefox Android?Safari iOS5+Chrome Android?WebView Android?Samsung Internet?Opera Android12.1+port getter steps are:WorkerGlobalScope object's
url's port.
Opera12.1+Edge79+
Edge (Legacy)12+Internet Explorer10+
Firefox Android?Safari iOS5+Chrome Android?WebView Android?Samsung Internet?Opera Android12.1+pathname getter steps are to return the result
of URL path serializing this's WorkerGlobalScope object's
url.
Opera12.1+Edge79+
Edge (Legacy)12+Internet Explorer10+
Firefox Android?Safari iOS5+Chrome Android?WebView Android?Samsung Internet?Opera Android12.1+search getter steps are:WorkerGlobalScope object's
url's query.?", followed by query.
Opera12.1+Edge79+
Edge (Legacy)12+Internet Explorer10+
Firefox Android?Safari iOS5+Chrome Android?WebView Android?Samsung Internet?Opera Android12.1+hash getter steps are:WorkerGlobalScope object's
url's fragment.#", followed by fragment.