Living Standard — Last Updated 18 April 2024
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:
EXAMPLE workers/primes/page.htmlThe 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:
EXAMPLE workers/primes/worker.jsThe 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:
EXAMPLE workers/modules/page.htmlThe worker file is then:
EXAMPLE workers/modules/worker.jsWhich imports the file filters.js:
EXAMPLE workers/modules/filters.jsSupport 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:
EXAMPLE workers/shared/001/test.htmlHere is the JavaScript worker:
EXAMPLE workers/shared/001/test.jsThis 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:
EXAMPLE workers/shared/002/test.htmlHere is the JavaScript worker:
EXAMPLE workers/shared/002/test.jsFinally, 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:
EXAMPLE workers/shared/003/test.htmlHere is the inner HTML page:
EXAMPLE workers/shared/003/inner.htmlHere is the JavaScript worker:
EXAMPLE workers/shared/003/test.jsThis 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:
EXAMPLE workers/multiviewer/page.htmlThe viewer is more involved:
EXAMPLE workers/multiviewer/viewer.htmlThere 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:
EXAMPLE workers/multiviewer/worker.jsConnecting 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:
EXAMPLE workers/multicore/page.htmlThe worker itself is as follows:
EXAMPLE workers/multicore/worker.jsIt 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:
EXAMPLE workers/multicore/core.jsThey 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:
EXAMPLE workers/crypto/libcrypto-v1.jsNote that the crypto functions here are just stubs and don't do real cryptography.
This library could be used as follows:
EXAMPLE workers/crypto/page.htmlA later version of the API, though, might want to offload all the crypto work onto subworkers. This could be done as follows:
EXAMPLE workers/crypto/libcrypto-v2.jsThe little subworkers would then be as follows.
For generating key pairs:
EXAMPLE workers/crypto/libcrypto-v2-generator.jsFor encrypting:
EXAMPLE workers/crypto/libcrypto-v2-encryptor.jsFor decrypting:
EXAMPLE workers/crypto/libcrypto-v2-decryptor.jsNotice 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) { ... };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 backSupport 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 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(ScriptURLString... 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). It is initially
  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. It is initially 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:
| Event handler | Event handler event type | 
|---|---|
| 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();
  attribute EventHandler onmessage;
  attribute EventHandler onmessageerror;
};DedicatedWorkerGlobalScope objects act as if they had an implicit
  MessagePort associated with them. 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.
All messages received by that port must immediately be retargeted at 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.
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
  DedicatedWorkerGlobalScope interface:
| Event handler | Event handler event type | 
|---|---|
| onmessageDedicatedWorkerGlobalScope/message_event Support in all current engines. Firefox3.5+Safari4+Chrome4+ Opera10.6+Edge79+ Edge (Legacy)12+Internet Explorer10+ Firefox Android?Safari iOS5+Chrome Android?WebView Android37+Samsung Internet?Opera Android11.5+ | message | 
| onmessageerrorDedicatedWorkerGlobalScope/messageerror_event Support in all current engines. Firefox57+Safari16.4+Chrome60+ Opera?Edge79+ Edge (Legacy)18Internet ExplorerNo Firefox Android?Safari iOS?Chrome Android?WebView Android?Samsung Internet?Opera Android47+ | messageerror | 
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 an associated constructor origin, constructor
  url, and credentials. 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:
| Event handler | Event handler event type | 
|---|---|
| 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 worker is said to be a permissible worker if its WorkerGlobalScope's
  owner set is not empty or:
WorkerGlobalScope object is a SharedWorkerGlobalScope object
   (i.e., the worker is a shared worker), andThe second part of this definition allows a shared worker to survive for a short time while a page is loading, in case that page is going to contact the shared worker again. This can be used by user agents as a way to avoid the cost of restarting a shared worker used by a site when the user is navigating from page to page within that site.
A worker is said to be an active needed worker if any of its owners are either Document objects that are fully active or
  active needed workers.
A worker is said to be a protected worker if it is an active needed
  worker and either it has outstanding timers, database transactions, or network connections,
  or its list of the worker's ports is not empty, or its WorkerGlobalScope
  is actually a SharedWorkerGlobalScope object (i.e., the worker is a shared
  worker).
A worker is said to be a suspendable worker if it is not an active needed worker but it is a permissible worker.
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.
Set worker global scope's name to the value of options's
   name member.
If is shared is true, then:
Set worker global scope's constructor origin to outside settings's origin.
Set worker global scope's constructor url to url.
Set worker global scope's type to the value of options's
     type member.
Set worker global scope's credentials to the value of
     options's credentials member.
     
Let destination be "sharedworker" if is
   shared is true, and "worker" otherwise.
Obtain script by switching on the value of options's type member:
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.
Associate inside port with worker global scope.
Entangle outside port and inside port.
Create a new WorkerLocation object and associate it with worker global
     scope.
Closing orphan workers: Start monitoring the worker such that no sooner than it stops being a protected worker, and no later than it stops being a permissible worker, worker global scope's closing flag is set to true.
Suspending workers: Start monitoring the worker, such that whenever worker global scope's closing flag is false and the worker is a suspendable worker, the user agent suspends execution of script in that worker until such time as either the closing flag switches to true or the worker stops being a suspendable worker.
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 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 an active needed worker 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 must
   report the error for that script, with the position (line number and column number) where the
  error occurred, using the WorkerGlobalScope object as the target.
For shared workers, if the error is still not handled afterwards, the error may be reported to a developer console.
For dedicated workers, if the error is still not handled afterwards, the user agent must queue a task to run these steps:
Let notHandled be the result of firing an
   event named error at the Worker object
   associated with the worker, using ErrorEvent, with the cancelable attribute initialized to true, the message, filename, lineno, and colno attributes initialized appropriately, and the error attribute initialized to null.
If notHandled is true, then the user agent must act as if the uncaught runtime
   script error had occurred in the global scope that the Worker object is in, thus
   repeating the entire runtime script error reporting process one level up.
If the implicit port connecting the worker to its Worker object has been
  disentangled (i.e. if the parent worker has been terminated), then the user agent must act as if
  the Worker object had no error event handler and as
  if that worker's onerror attribute was
  null, but must otherwise act as described above.
Thus, error reports propagate up to
  the chain of dedicated workers up to the original Document, even if some of the
  workers along this chain have been terminated and garbage collected.
The task source for the task mentioned above is the DOM manipulation task source.
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:
| Event handler | Event handler event type | 
|---|---|
| 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.
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(ScriptURLString scriptURL, optional WorkerOptions options = {});
  undefined terminate();
  undefined postMessage(any message, sequence<object> transfer);
  undefined postMessage(any message, optional StructuredSerializeOptions options = {});
  attribute EventHandler onmessage;
  attribute EventHandler onmessageerror;
};
dictionary WorkerOptions {
  WorkerType type = "classic";
  RequestCredentials credentials = "same-origin"; // credentials is only used if type is "module"
  DOMString name = "";
};
enum WorkerType { "classic", "module" };
Worker includes AbstractWorker;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 be used to define the name of that global environment via the name option, primarily for debugging purposes. It can also ensure this new
   global environment supports JavaScript modules (specify type: "module"),
   and if that is specified, can also be used to specify how scriptURL is fetched through
   the credentials option.
worker.terminate()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.
The terminate()
  method, when invoked, must cause the terminate a worker algorithm to be run on the
  worker with which the object is associated.
Worker objects act as if they had an implicit MessagePort associated
  with them. 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.
All messages received by that port must immediately be retargeted at the Worker
  object.
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 the 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 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 Worker
  interface:
| Event handler | Event handler event type | 
|---|---|
| onmessage | message | 
| onmessageerror | messageerror | 
When the Worker(scriptURL,
  options) constructor is invoked, the user agent must run the following
  steps:
Let outside settings be the current settings object.
Let worker URL be the result of encoding-parsing a URL given scriptURL, relative to outside settings.
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 worker URL is failure, then throw a "SyntaxError"
   DOMException.
Let worker be a new Worker object.
Let outside port be a new MessagePort in outside
   settings's realm.
Associate the outside port with worker.
Run this step in parallel:
Run a worker given worker, worker URL, outside settings, outside port, and options.
Return worker.
SharedWorker interfaceSupport in all current engines.
[Exposed=Window]
interface SharedWorker : EventTarget {
  constructor(ScriptURLString 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 be used to define the name of that global environment via the name option. It can also ensure this new global environment supports JavaScript
   modules (specify type: "module"), and if that is specified, can also be
   used to specify how scriptURL is fetched through the credentials option. Note that attempting to construct a shared worker with
   options whose type or credentials values
   mismatch an existing shared worker will cause the returned sharedWorker to fire an
   error event and not connect to the existing shared worker.
sharedWorker.portSupport in all current engines.
Returns sharedWorker's MessagePort object which can be used to
   communicate with the global environment.
The port
  attribute must return the value it was assigned by the object's constructor. It represents the
  MessagePort for communicating with the shared worker.
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.
When the SharedWorker(scriptURL, options)
  constructor is invoked:
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 outside settings be the current settings object.
Let urlRecord be the result of encoding-parsing a URL given scriptURL, relative to outside settings.
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 worker be a new SharedWorker object.
Let outside port be a new MessagePort in outside
   settings's realm.
Assign outside port to the port
   attribute of worker.
Let callerIsSecureContext be true if outside settings is a secure context; otherwise, false.
Let outside storage key be the result of running obtain a storage key for non-storage purposes given outside settings.
Enqueue the following steps to the shared worker manager:
Let worker global scope be null.
For each scope in the list of all
      SharedWorkerGlobalScope objects:
Let worker storage key 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 memberthen:
Set worker global scope 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 worker global scope is not null, but the user agent has been configured to disallow communication between the worker represented by the worker global scope and the scripts whose settings object is outside settings, then set worker global scope to null.
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 worker global scope is not null, then check if worker global
     scope's type and credentials match the
     options values. If not, queue a task to fire an event named error
     and abort these steps.
If worker global scope is not null, then run these subsubsteps:
Let settings object be the relevant settings object for worker global scope.
Let workerIsSecureContext be true if settings object is a secure context; otherwise, false.
If workerIsSecureContext is not callerIsSecureContext, then
       queue a task to fire an event named
       error at worker and abort these steps.
       [SECURE-CONTEXTS]
Associate worker with worker global scope.
Let inside port be a new MessagePort in
       settings object's realm.
Entangle outside port and inside port.
Queue a task, using the DOM manipulation task source, to
       fire an event named connect at worker global scope,
       using MessageEvent, with the data
       attribute initialized to the empty string, the ports attribute initialized to a new frozen
       array containing only inside port, and the source attribute initialized to inside
       port.
Append the relevant owner to add given outside settings to worker global scope's owner set.
Otherwise, in parallel, run a worker given worker, urlRecord, outside settings, outside port, and options.
Return worker.
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 to import scripts into worker global scope given this
  and urls.
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 the rethrow errors argument 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 interfaceSupport in all current engines.
The navigator attribute of the
  WorkerGlobalScope interface must return an instance of the
  WorkerNavigator interface, which represents the identity and state of the user agent
  (the client):
[Exposed=Worker]
interface WorkerNavigator {};
WorkerNavigator includes NavigatorID;
WorkerNavigator includes NavigatorLanguage;
WorkerNavigator includes NavigatorOnLine;
WorkerNavigator includes NavigatorConcurrentHardware;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.