You are granted a license to use, reproduce
and create derivative works of this document.

Abstract

This specification defines an API that allows Web application
authors to spawn background workers running scripts in parallel to
their main page. This allows for thread-like operation with
message-passing as the coordination mechanism.

Status of this document

This is a work in progress! This document is
changing on a daily if not hourly basis in response to comments and
as a general part of its development process. Comments are very
welcome, please send them to whatwg@whatwg.org. Thank
you.

The current focus is in developing a first draft proposal.

Implementors should be aware that this specification is not
stable. Implementors who are not taking part in the
discussions are likely to find the specification changing out from
under them in incompatible ways. Vendors interested in
implementing this specification before it eventually reaches the
call for implementations should join the WHATWG mailing list and take part in the
discussions.

This specification is also being produced by the W3C Web Apps WG. The two
specifications are identical from the table of contents onwards.

Table of contents

1.1 Introduction

1.1.1 Scope

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.

1.1.2 Tutorial

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.

1.1.2.1 A background number-crunching worker

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

This connects to the server using the WebSocket
mechanism and opens the local database (which, we presume, has been
created earlier). The worker then just listens for messages from the
server and acts on them as appropriate, forever (or until the main
page is closed).

View
this example online. (This example will not actually function,
since the server does not actually exist and the database is not
created by this sample code.)

1.1.2.3 Worker used for background I/O

This section is non-normative.

In this example, the main document uses two workers, one for
fetching stock updates for at regular intervals, and one for
fetching performing search queries that the user requests.

1.1.2.4 Shared workers

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

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.

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.

1.1.2.5 Delegation

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.

1.1.2.6 Providing libraries

Suppose that a cryptography library is made available that
provides three tasks:

Generate a public/private key pair

Takes a port, on which it will send two messages, first the
public key and then the private key.

Given a plaintext and a public key, return the corresponding cyphertext

Takes a port, to which any number of messages can be sent, the
first giving the public key, and the remainder giving the
plaintext, each of which is encrypted and then sent on that same
channel as the cyphertext. The user can close the port when it is
done encrypting content.

Given a cyphertext and a private key, return the corresponding plaintext

Takes a port, to which any number of messages can be sent, the
first giving the private key, and the remainder giving the
cyphertext, each of which is decrypted and then sent on that same
channel as the plaintext. The user can close the port when it is
done decrypting content.

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.

1.2 Conformance requirements

All diagrams, examples, and notes in this specification are
non-normative, as are all sections explicitly marked non-normative.
Everything else in this specification is normative.

The key words "MUST", "MUST NOT", "REQUIRED", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and
"OPTIONAL" in the normative parts of this document are to be
interpreted as described in RFC2119. For readability, these words do
not appear in all uppercase letters in this specification. [RFC2119]

Requirements phrased in the imperative as part of algorithms
(such as "strip any leading space characters" or "return false and
abort these steps") are to be interpreted with the meaning of the
key word ("must", "should", "may", etc) used in introducing the
algorithm.

Some conformance requirements are phrased as requirements on
attributes, methods or objects. Such requirements are to be
interpreted as requirements on user agents.

Conformance requirements phrased as algorithms or specific steps
may be implemented in any manner, so long as the end result is
equivalent. (In particular, the algorithms defined in this
specification are intended to be easy to follow, and not intended to
be performant.)

The only conformance class defined by this specification is user
agents.

User agents may impose implementation-specific limits on
otherwise unconstrained inputs, e.g. to prevent denial of service
attacks, to guard against running out of memory, or to work around
platform-specific limitations.

1.2.1 Dependencies

This specification relies on several other underlying
specifications.

HTML5

Many fundamental concepts from HTML5 are used by this
specification. [HTML5]

WebIDL

The IDL blocks in this specification use the semantics of the
WebIDL specification. [WEBIDL]

1.3 Terminology

The construction "a Foo object", where
Foo is actually an interface, is sometimes
used instead of the more accurate "an object implementing the
interface Foo".

The term DOM is used to refer to the API set made available to
scripts in Web applications, and does not necessarily imply the
existence of an actual Document object or of any other
Node objects as defined in the DOM Core
specifications. [DOMCORE]

An IDL attribute is said to be getting when its value is
being retrieved (e.g. by author script), and is said to be
setting when a new value is assigned to it.

The term "JavaScript" is used to refer to ECMA262, rather than
the official term ECMAScript, since the term JavaScript is more
widely known. [ECMA262]

1.4 Infrastructure

There are two kinds of workers; dedicated workers, and shared
workers. Dedicated workers, once created, and 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.

The location
attribute must return the WorkerLocation object created
for the WorkerGlobalScope object when the worker was
created. It represents the absolute URL of the script
that was used to initialize the worker, after any redirects.

When a script invokes the close()
method on a WorkerGlobalScope object, the user agent
must run the following steps (atomically):

The postMessage()
method on
DedicatedWorkerGlobalScope objects must act as if, when
invoked, it immediately invoked the
method of the same name on the port, with the same arguments, and
returned the same return value.

Shared workers receive message ports through connect events on
their global object for each connection.

The name
attribute must return the value it was assigned when the
SharedWorkerGlobalScope object was created by the
"run a worker" algorithm. Its value represents the name
that can be used to obtain a reference to the worker using the
SharedWorker constructor.

Each WorkerGlobalScope object also has a closing flag, which must
initially be 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 asynchronous
operations are dropped, etc.

1.4.4 The worker's lifetime

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

Each WorkerGlobalScope also has a list of the
worker's workers. Initially this list is empty; it is
populated when the worker creates or obtains further workers.

Finally, each WorkerGlobalScope also has a list of
the worker's Documents. Initially this list
is empty; it is populated when the worker is created.

Given a script's global objecto
when creating or obtaining a worker, the list of relevant
Document objects to add depends on the type of
o. If o is a
WorkerGlobalScope object (i.e. if we are creating a
nested worker), then the relevant Documents are the
Documents that are in o's own list
of the worker's Documents. Otherwise, o is a Window object, and the relevant
Document is just the Document that is the
active document of the Window object o.

1.4.5 Processing model

When a user agent is to run a worker for a script with
URLurl, a browsing context owner browsing context, an origin owner
origin, and with global scope worker global
scope, it must run the following steps:

Create a completely separate and parallel execution environment
(i.e. a separate thread or process or equivalent construct), and
run the rest of these steps asynchronously in that context.

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.

User agents may invoke the "kill a worker"
processing model on a worker at any time, e.g. in response to user
requests, in response to CPU quota management, or when a worker
stops being an active needed worker if the worker
continues executing even after its closing flag was
set to true.

When a user agent is to terminate a worker it must run
the following steps in parallel with the worker's main loop (the
"run a worker" processing model defined above):

1.4.6 Runtime script errors

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 using the WorkerGlobalScope object's onerror
attribute.
[HTML5]

For shared workers, if the error is still not handled afterwards, or if
the error occurred while handling a previous script error, the error
may be reported to the user.
[HTML5]

When the user agent is to fire a worker error event at
a Worker object, it must dispatch an event that uses
the ErrorEvent interface, with the name error, that doesn't bubble and is
cancelable, with its message, filename, and lineno attributes set
appropriately. The default action of this event depends on whether
the Worker object is itself in a worker. If it is, and
that worker is also a dedicated worker, then the user agent must
again queue a task to fire a worker error
event at the Worker object associated with
that worker. Otherwise, then the error may be reported
to the user.

The terminate() method,
when invoked, must cause the "terminate a worker"
algorithm to be run on the worker with with 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()
method on Worker objects
must act as if, when invoked, it
immediately invoked the method of the same name on the port, with
the same arguments, and returned the same return value.

Thus, scripts must be external files with the same
scheme as the original page: you can't load a script from a data: URL or javascript:
URL, and a https: page couldn't start workers using
scripts with http: URLs.

Thus, scripts must be external files with the same
scheme as the original page: you can't load a script from a data: URL or javascript:
URL, and a https: page couldn't start workers using
scripts with http: URLs.

Create an event that uses the MessageEvent
interface, with the name connect, which does not bubble, is
not cancelable, has no default action, has a data attribute whose value
is the empty string and has a ports attribute whose
value is an array containing only the newly created port, and
queue a task to dispatch the event at worker global scope.

Create an event that uses the MessageEvent
interface, with the name connect, which does not bubble, is not
cancelable, has no default action, has a data attribute whose value is
the empty string and has a ports attribute whose value
is an array containing only the newly created port, and queue
a task to dispatch the event at worker global
scope.

For each argument in turn, in the order given, starting with
the first one, run these substeps:

Wait for the fetching attempt for the corresponding resource
to complete.

If the fetching attempt failed, throw a
NETWORK_ERR exception and abort all these
steps.

If the attempt succeeds, then convert the script resource to
Unicode by assuming it was encoded as UTF-8, to obtain its source.

Let language be JavaScript.

As with the worker's script, the script here is
always assumed to be JavaScript, regardless of the MIME
type.

Create a script, using source as the script source and language as the scripting language, using the
same global object, browsing context, URL character encoding,
base URL, and script group as the script that was created by the
worker's run a worker algorithm.

Let the newly created script run until it either
returns, fails to parse, fails to catch an exception, or gets
prematurely aborted by the "kill a worker" or
"terminate a worker" algorithms defined above.

If it failed to parse, then throw an ECMAScript
SyntaxError exception and abort all these
steps. [ECMA262]

If an exception was raised or if the script was prematurely
aborted, then abort all these steps, letting the exception or
aborting continue to be processed by the script that called the
importScripts()
method.

1.5.4 Interface objects and constructors

XMLHttpRequest and all interface objects and
constructors defined by the XMLHttpRequest specifications, except
that the document response entity body must always be
null. The XMLHttpRequest base URL is the
script's base URL; the
XMLHttpRequest origin is the script's
origin. [XHR]

These requirements do not override the requirements
defined by the Web IDL specification, in particular concerning the
visibility of interfaces annotated with the [NoInterfaceObject] extended attribute.