Annotation of html5/workers/Overview.html, revision 1.59

1.1       ihickson    1: <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN">
                      2: <!-- when publishing, change bits marked ZZZ -->
                      3: 
                      4: <html lang=en-US-x-Hixie>
                      5:  <head>
                      6:   <title>Web Workers</title>
                      7:   <link href="http://www.w3.org/StyleSheets/TR/%57%33%43-ED" rel=stylesheet
                      8:   type="text/css">
                      9:   <!-- ZZZ ED vs WD -->
                     10: 
                     11:  <body>
                     12:   <div class=head>
                     13:    <p><a href="http://www.w3.org/"><img alt=W3C height=48
                     14:     src="http://www.w3.org/Icons/w3c_home" width=72></a></p>
                     15: 
1.54      ihickson   16:    <h1>Web Workers</h1>
1.1       ihickson   17: 
                     18:    <h2 class="no-num no-toc" id=an-accompaniment>An accompaniment
                     19:     specification for HTML5</h2>
                     20: 
                     21:    <h2 class="no-num no-toc" id=editors><!-- "W3C Working Draft" --> Editor's
1.54      ihickson   22:     Draft <!--ZZZ-->12 November 2008</h2>
1.1       ihickson   23: 
                     24:    <dl><!-- ZZZ: update the month/day
                     25:     <dt>This Version:</dt>
                     26:     <dd><a href="http://www.w3.org/TR/2008/WD-workers-20080101/">http://www.w3.org/TR/2008/WD-workers-20080101/</a></dd>
1.2       ihickson   27:     <dt>Latest Published Version:</dt>
                     28:     <dd><a href="http://www.w3.org/TR/workers/">http://www.w3.org/TR/workers/</a></dd>
1.1       ihickson   29:  :ZZZ -->
                     30: 
                     31:     <dt>Latest Editor's Draft:
                     32: 
                     33:     <dd><a
                     34:      href="http://dev.w3.org/html5/workers/">http://dev.w3.org/html5/workers/</a></dd>
1.2       ihickson   35:     <!-- ZZZ: add the new version after it has shipped
                     36:     <dt>Previous Versions:</dt>
                     37:     <dd><a href="http://www.w3.org/TR/2008/WD-workers-20080101/">http://www.w3.org/TR/2008/WD-workers-20080101/</a>
                     38:  :ZZZ -->
1.1       ihickson   39: 
                     40:     <dt>Editors:
                     41: 
                     42:     <dd><a href="mailto:ian@hixie.ch">Ian Hickson</a>, Google, Inc.
                     43:    </dl>
                     44: 
                     45:    <p class=copyright><a
                     46:     href="http://www.w3.org/Consortium/Legal/ipr-notice#Copyright">Copyright</a>
                     47:     &#169; 2008 <a href="http://www.w3.org/"><abbr title="World Wide Web
                     48:     Consortium">W3C</abbr></a><sup>&#174;</sup> (<a
                     49:     href="http://www.csail.mit.edu/"><abbr title="Massachusetts Institute of
                     50:     Technology">MIT</abbr></a>, <a href="http://www.ercim.org/"><abbr
                     51:     title="European Research Consortium for Informatics and
                     52:     Mathematics">ERCIM</abbr></a>, <a
                     53:     href="http://www.keio.ac.jp/">Keio</a>), All Rights Reserved. W3C <a
                     54:     href="http://www.w3.org/Consortium/Legal/ipr-notice#Legal_Disclaimer">liability</a>,
                     55:     <a
                     56:     href="http://www.w3.org/Consortium/Legal/ipr-notice#W3C_Trademarks">trademark</a>
                     57:     and <a
                     58:     href="http://www.w3.org/Consortium/Legal/copyright-documents">document
                     59:     use</a> rules apply.</p>
                     60:    <!-- UNDER NO CIRCUMSTANCES IS THE FOLLOWING PARAGRAPH TO BE REMOVED OR EDITED WITHOUT TALKING TO IAN FIRST -->
                     61:    
                     62:    <p class="alt copyright">The <a
                     63:     href="http://www.whatwg.org/specs/web-workers/current-work/">WHATWG
                     64:     version</a> of this specification is available under a more permissive
                     65:     license.</p>
                     66:    <!-- UNDER NO CIRCUMSTANCES IS THE PRECEDING PARAGRAPH TO BE REMOVED OR EDITED WITHOUT TALKING TO IAN FIRST -->
                     67:    </div>
                     68: 
                     69:   <hr>
                     70: 
                     71:   <h2 class="no-num no-toc" id=abstract>Abstract</h2>
                     72: 
                     73:   <p>This specification defines an API that allows Web application authors to
                     74:    spawn background workers running scripts in parallel to their main page.
                     75:    This allows for thread-like operation with message-passing as the
                     76:    coordination mechanism.
                     77: 
                     78:   <h2 class="no-num no-toc" id=status>Status of this document</h2>
                     79:   <!-- intro boilerplate (required) -->
                     80: 
                     81:   <p><em>This section describes the status of this document at the time of
                     82:    its publication. Other documents may supersede this document. A list of
                     83:    current W3C publications and the most recently formally published revision
                     84:    of this technical report can be found in the <a
                     85:    href="http://www.w3.org/TR/">W3C technical reports index</a> at
                     86:    http://www.w3.org/TR/.</em></p>
                     87:   <!-- where to send feedback (required) -->
                     88: 
                     89:   <p>If you wish to make comments regarding this document, please send them
                     90:    to <a
                     91:    href="mailto:public-html-comments@w3.org">public-html-comments@w3.org</a>
                     92:    (<a
                     93:    href="mailto:public-html-comments-request@w3.org?subject=subscribe">subscribe</a>,
                     94:    <a
                     95:    href="http://lists.w3.org/Archives/Public/public-html-comments/">archives</a>)
                     96:    <!-- UNDER NO CIRCUMSTANCES IS THE FOLLOWING SENTENCE TO BE REMOVED OR EDITED WITHOUT TALKING TO IAN FIRST -->
                     97:    or <a href="mailto:whatwg@whatwg.org">whatwg@whatwg.org</a> (<a
                     98:    href="http://lists.whatwg.org/listinfo.cgi/whatwg-whatwg.org">subscribe</a>,
                     99:    <a
                    100:    href="http://lists.whatwg.org/pipermail/whatwg-whatwg.org/">archives</a>).
                    101:    <!-- UNDER NO CIRCUMSTANCES IS THE PRECEDING SENTENCE TO BE REMOVED OR EDITED WITHOUT TALKING TO IAN FIRST -->
                    102:    All feedback is welcome.</p>
                    103:   <!-- stability (required) -->
                    104: 
                    105:   <p>Implementors should be aware that this specification is not stable.
                    106:    <strong>Implementors who are not taking part in the discussions are likely
                    107:    to find the specification changing out from under them in incompatible
                    108:    ways.</strong> Vendors interested in implementing this specification
                    109:    before it eventually reaches the Candidate Recommendation stage should
                    110:    join the aforementioned mailing lists and take part in the discussions.</p>
                    111:   <!-- UNDER NO CIRCUMSTANCES IS THE FOLLOWING PARAGRAPH TO BE REMOVED OR EDITED WITHOUT TALKING TO IAN FIRST -->
                    112:   <!-- version history or list of changes (required) -->
                    113: 
                    114:   <p>The latest stable version of the editor's draft of this specification is
                    115:    always available on <a
                    116:    href="http://dev.w3.org/html5/workers/Overview.html">the W3C CVS
                    117:    server</a> and in the <a href="http://svn.whatwg.org/webworkers/">WHATWG
                    118:    Subversion repository</a>. The latest editor's working copy (which may
                    119:    contain unfinished text in the process of being prepared) is available <a
                    120:    href="http://www.whatwg.org/specs/web-workers/current-work/">on the WHATWG
                    121:    site</a>. Detailed change history can be obtained from the following
                    122:    locations:</p>
                    123:   <!-- UNDER NO CIRCUMSTANCES IS THE PRECEDING PARAGRAPH TO BE REMOVED OR EDITED WITHOUT TALKING TO IAN FIRST -->
                    124:   <!-- UNDER NO CIRCUMSTANCES IS THE FOLLOWING LIST TO BE REMOVED OR EDITED WITHOUT TALKING TO IAN FIRST -->
                    125: 
                    126:   <ul>
                    127:    <li>Twitter messages (non-editorial changes only): <a
                    128:     href="http://twitter.com/WHATWG">http://twitter.com/WHATWG</a>
                    129: 
                    130:    <li>Interactive Web interface: <a
                    131:     href="http://html5.org/tools/web-workers-tracker">http://html5.org/tools/web-workers-tracker</a>
                    132: 
                    133:    <li>Commit-Watchers mailing list: <a
                    134:     href="http://lists.whatwg.org/listinfo.cgi/commit-watchers-whatwg.org">http://lists.whatwg.org/listinfo.cgi/commit-watchers-whatwg.org</a>
                    135: 
                    136:    <li>Subversion interface: <a
                    137:     href="http://svn.whatwg.org/webworkers/">http://svn.whatwg.org/webworkers/</a>
                    138: 
                    139:    <li>CVS log: <a
                    140:     href="http://dev.w3.org/cvsweb/html5/workers/Overview.html">http://dev.w3.org/cvsweb/html5/workers/Overview.html</a>
                    141:   </ul>
                    142:   <!-- UNDER NO CIRCUMSTANCES IS THE PRECEDING LIST TO BE REMOVED OR EDITED WITHOUT TALKING TO IAN FIRST -->
                    143:   <!-- status of document, group responsible (required) -->
                    144: 
                    145:   <p>The W3C <a href="http://www.w3.org/html/wg/">HTML Working Group</a> is
                    146:    the W3C working group responsible for this specification's progress along
1.54      ihickson  147:    the W3C Recommendation track. <!--ZZZ:--> This specification is the 12
                    148:    November 2008 <!--ZZZ "Working Draft"-->Editor's Draft. <!--:ZZZ--></p>
1.1       ihickson  149:   <!-- UNDER NO CIRCUMSTANCES IS THE PRECEDING PARAGRAPH TO BE REMOVED OR EDITED WITHOUT TALKING TO IAN FIRST -->
                    150:   <!-- relationship to other work (required) -->
                    151: 
                    152:   <p>This specification is also being produced by the <a
                    153:    href="http://www.whatwg.org/">WHATWG</a>. The two specifications are
                    154:    identical from the table of contents onwards.</p>
                    155:   <!-- UNDER NO CIRCUMSTANCES IS THE FOLLOWING PARAGRAPH TO BE REMOVED OR EDITED WITHOUT TALKING TO IAN FIRST -->
                    156:   <!-- UNDER NO CIRCUMSTANCES IS THE PRECEDING PARAGRAPH TO BE REMOVED OR EDITED WITHOUT TALKING TO IAN FIRST -->
                    157:   <!-- context and rationale (required) -->
                    158: 
                    159:   <p>This specification is intended to specify a part of the Web platform
                    160:    closely related to HTML5. It is defined in a separate document primarily
                    161:    to ease the cognitive load on reviewers.</p>
                    162:   <!-- UNDER NO CIRCUMSTANCES IS THE FOLLOWING PARAGRAPH TO BE REMOVED OR EDITED WITHOUT TALKING TO IAN FIRST -->
                    163:   <!-- required patent boilerplate -->
                    164: 
                    165:   <p>This document was produced by a group operating under the <a
                    166:    href="http://www.w3.org/Consortium/Patent-Policy-20040205/">5 February
                    167:    2004 W3C Patent Policy</a>. W3C maintains a <a
                    168:    href="http://www.w3.org/2004/01/pp-impl/40318/status"
                    169:    rel=disclosure>public list of any patent disclosures</a> made in
                    170:    connection with the deliverables of the group; that page also includes
                    171:    instructions for disclosing a patent. An individual who has actual
                    172:    knowledge of a patent which the individual believes contains <a
                    173:    href="http://www.w3.org/Consortium/Patent-Policy-20040205/#def-essential">Essential
                    174:    Claim(s)</a> must disclose the information in accordance with <a
                    175:    href="http://www.w3.org/Consortium/Patent-Policy-20040205/#sec-Disclosure">section
                    176:    6 of the W3C Patent Policy</a>.
                    177: 
                    178:   <h2 class="no-num no-toc" id=contents>Table of contents</h2>
                    179:   <!--begin-toc-->
                    180: 
                    181:   <ul class=toc>
                    182:    <li><a href="#introduction"><span class=secno>1. </span>Introduction</a>
                    183:     <ul class=toc>
1.55      ihickson  184:      <li><a href="#scope"><span class=secno>1.1 </span>Scope</a>
                    185: 
                    186:      <li><a href="#tutorial"><span class=secno>1.2 </span>Tutorial</a>
1.29      ihickson  187:       <ul class=toc>
1.55      ihickson  188:        <li><a href="#a-background"><span class=secno>1.2.1 </span>A
1.32      ihickson  189:         background number-crunching worker</a>
1.31      ihickson  190: 
1.55      ihickson  191:        <li><a href="#a-worker"><span class=secno>1.2.2 </span>A worker for
1.31      ihickson  192:         updating a client-side database</a>
1.33      ihickson  193: 
1.55      ihickson  194:        <li><a href="#worker"><span class=secno>1.2.3 </span>Worker used for
1.58      ihickson  195:         background I/O</a>
1.34      ihickson  196: 
1.55      ihickson  197:        <li><a href="#shared"><span class=secno>1.2.4 </span>Shared
1.34      ihickson  198:         workers</a>
                    199: 
1.55      ihickson  200:        <li><a href="#delegation"><span class=secno>1.2.5
1.40      ihickson  201:         </span>Delegation</a>
                    202: 
1.55      ihickson  203:        <li><a href="#providing"><span class=secno>1.2.6 </span>Providing
1.49      ihickson  204:         libraries</a>
1.29      ihickson  205:       </ul>
1.1       ihickson  206: 
1.55      ihickson  207:      <li><a href="#conformance"><span class=secno>1.3 </span>Conformance
1.1       ihickson  208:       requirements</a>
                    209:       <ul class=toc>
1.55      ihickson  210:        <li><a href="#dependencies"><span class=secno>1.3.1
1.1       ihickson  211:         </span>Dependencies</a>
                    212:       </ul>
                    213: 
1.55      ihickson  214:      <li><a href="#terminology"><span class=secno>1.4 </span>Terminology</a>
1.4       ihickson  215:     </ul>
                    216: 
1.12      ihickson  217:    <li><a href="#infrastructure"><span class=secno>2.
                    218:     </span>Infrastructure</a>
1.4       ihickson  219:     <ul class=toc>
1.50      ihickson  220:      <li><a href="#the-global"><span class=secno>2.1 </span>The global
                    221:       scope</a>
                    222:       <ul class=toc>
                    223:        <li><a href="#the-workerglobalscope"><span class=secno>2.1.1
                    224:         </span>The <code>WorkerGlobalScope</code> abstract interface</a>
                    225: 
                    226:        <li><a href="#dedicated"><span class=secno>2.1.2 </span>Dedicated
                    227:         workers and the <code>DedicatedWorkerGlobalScope</code> interface</a>
                    228:         
                    229: 
                    230:        <li><a href="#shared0"><span class=secno>2.1.3 </span>Shared workers
                    231:         and the <code>SharedWorkerGlobalScope</code> inteface</a>
                    232:       </ul>
1.4       ihickson  233: 
1.15      ihickson  234:      <li><a href="#base-urls"><span class=secno>2.2 </span>Base URLs and
                    235:       origins of workers</a>
                    236: 
                    237:      <li><a href="#the-queue"><span class=secno>2.3 </span>The queue of
1.4       ihickson  238:       events</a>
                    239: 
1.15      ihickson  240:      <li><a href="#the-workers"><span class=secno>2.4 </span>The worker's
1.9       ihickson  241:       ports</a>
                    242: 
1.15      ihickson  243:      <li><a href="#processing"><span class=secno>2.5 </span>Processing
1.4       ihickson  244:       model</a>
1.12      ihickson  245: 
1.15      ihickson  246:      <li><a href="#creating"><span class=secno>2.6 </span>Creating
1.12      ihickson  247:       workers</a>
1.50      ihickson  248:       <ul class=toc>
                    249:        <li><a href="#the-abstractworker"><span class=secno>2.6.1 </span>The
                    250:         <code>AbstractWorker</code> abstract interface</a>
                    251: 
                    252:        <li><a href="#dedicated0"><span class=secno>2.6.2 </span>Dedicated
                    253:         workers and the <code>Worker</code> interface</a>
                    254: 
                    255:        <li><a href="#shared1"><span class=secno>2.6.3 </span>Shared workers
                    256:         and the <code>SharedWorker</code> interface</a>
                    257:       </ul>
1.1       ihickson  258:     </ul>
                    259: 
1.12      ihickson  260:    <li><a href="#apis-available"><span class=secno>3. </span>APIs available
                    261:     to workers</a>
1.26      ihickson  262:     <ul class=toc>
                    263:      <li><a href="#importing"><span class=secno>3.1 </span>Importing scripts
                    264:       and libraries</a>
                    265: 
                    266:      <li><a href="#apis-defined"><span class=secno>3.2 </span>APIs defined in
                    267:       other specifications</a>
                    268: 
                    269:      <li><a href="#interface"><span class=secno>3.3 </span>Interface objects
                    270:       and constructors</a>
1.34      ihickson  271: 
                    272:      <li><a href="#worker0"><span class=secno>3.4 </span>Worker locations</a>
                    273:       
1.26      ihickson  274:     </ul>
1.4       ihickson  275: 
1.1       ihickson  276:    <li class=no-num><a href="#references">References</a>
                    277: 
                    278:    <li class=no-num><a href="#acknowledgements">Acknowledgements</a>
                    279:   </ul>
                    280:   <!--end-toc-->
                    281: 
                    282:   <hr>
                    283: 
                    284:   <h2 id=introduction><span class=secno>1. </span>Introduction</h2>
                    285: 
1.55      ihickson  286:   <h3 id=scope><span class=secno>1.1 </span>Scope</h3>
                    287: 
                    288:   <p><em>This section is non-normative.</em>
                    289: 
                    290:   <p>This specification defines an API for running scripts in the background
                    291:    independently of any user interface scripts.
                    292: 
                    293:   <p>This allows for long-running scripts that are not interrupted by scripts
                    294:    that respond to clicks or other user interactions, and allows long tasks
                    295:    to be executed without yielding to keep the page responsive.
                    296: 
                    297:   <p>Workers (as these background scripts are called herein) are relatively
                    298:    heavy-weight, and are not intended to be used in large numbers. For
                    299:    example, it would be inappropriate to launch one worker for each pixel of
                    300:    a four megapixel image. The examples below show some appropriate uses of
                    301:    workers.
                    302: 
                    303:   <p>Generally, workers are expected to be long-lived, have a high start-up
                    304:    performance cost, and a high per-instance memory cost.
                    305: 
                    306:   <h3 id=tutorial><span class=secno>1.2 </span>Tutorial</h3>
1.1       ihickson  307: 
                    308:   <p><em>This section is non-normative.</em>
                    309: 
1.29      ihickson  310:   <p>There are a variety of uses that workers can be put to. The following
                    311:    subsections show various examples of this use.
                    312: 
1.55      ihickson  313:   <h4 id=a-background><span class=secno>1.2.1 </span>A background
1.32      ihickson  314:    number-crunching worker</h4>
1.29      ihickson  315: 
                    316:   <p><em>This section is non-normative.</em>
                    317: 
                    318:   <p>The simplest use of workers is for performing a computationally
                    319:    expensive task without interrupting the user interface.
                    320: 
1.32      ihickson  321:   <p>In this example, the main document spawns a worker to (na&iuml;vely)
1.29      ihickson  322:    compute prime numbers, and progressively displays the most recently found
                    323:    prime number.
                    324: 
                    325:   <p>The main page is as follows:
                    326: 
                    327:   <pre>&lt;!DOCTYPE HTML>
                    328: &lt;html>
                    329:  &lt;head>
1.40      ihickson  330:   &lt;title>Worker example: One-core computation&lt;/title>
1.29      ihickson  331:  &lt;/head>
                    332:  &lt;body>
                    333:   &lt;p>The highest prime number discovered so far is: &lt;output id="result">&lt;/output>&lt;/p>
                    334:   &lt;script>
1.50      ihickson  335:    var worker = new Worker('worker.js');
                    336:    worker.onmessage = function (event) {
1.54      ihickson  337:      document.getElementById('result').textContent = event.data;
1.29      ihickson  338:    };
                    339:   &lt;/script>
                    340:  &lt;/body>
                    341: &lt;/html></pre>
                    342: 
1.50      ihickson  343:   <p>The <code title=dom-Worker><a href="#worker2">Worker()</a></code>
                    344:    constructor call creates a worker and returns a <code><a
                    345:    href="#worker1">Worker</a></code> object representing that worker, which
                    346:    is used to communicate with the worker. That object's <code
                    347:    title=handler-Worker-onmessage><a href="#onmessage0">onmessage</a></code>
                    348:    event handler attribute allows the code to receive messages from the
                    349:    worker.
1.29      ihickson  350: 
                    351:   <p>The worker itself is as follows:
                    352: 
                    353:   <pre>var n = 1;
                    354: search: while (true) {
                    355:   n += 1;
                    356:   for (var i = 2; i &lt;= Math.sqrt(n); i += 1)
                    357:     if (n % i == 0)
                    358:      continue search;
                    359:   // found a prime!
1.50      ihickson  360:   postMessage(n);
1.29      ihickson  361: }</pre>
                    362: 
                    363:   <p>The bulk of this code is simply an unoptimised search for a prime
                    364:    number. To send a message back to the page, the <code
1.50      ihickson  365:    title=dom-DedicatedWorkerGlobalScope-postMessage><a
                    366:    href="#postmessage">postMessage()</a></code> method is used to post a
1.30      ihickson  367:    message when a prime is found.
1.29      ihickson  368: 
                    369:   <p><a href="http://www.whatwg.org/demos/workers/primes/page.html">View this
                    370:    example online</a>.
1.4       ihickson  371: 
1.55      ihickson  372:   <h4 id=a-worker><span class=secno>1.2.2 </span>A worker for updating a
1.31      ihickson  373:    client-side database</h4>
                    374: 
                    375:   <p><em>This section is non-normative.</em>
                    376: 
                    377:   <p>In this example, the main document spawns a worker whose only task is to
                    378:    listen for notifications from the server, and, when appropriate, either
                    379:    add or remove data from the client-side database.
                    380: 
                    381:   <p>Since no communication occurs between the worker and the main page, the
                    382:    main page can start the worker by just doing:
                    383: 
                    384:   <pre>&lt;script>
1.50      ihickson  385:  new Worker('worker.js');
1.31      ihickson  386: &lt;/script></pre>
                    387: 
                    388:   <p>The worker itself is as follows:
                    389: 
                    390:   <pre>var server = new WebSocket('ws://whatwg.org/database');
1.42      ihickson  391: var database = openDatabase('demobase', '1.0', 'Demo Database', 10240);
1.31      ihickson  392: server.onmessage = function (event) {
                    393:   // data is in the format "command key value"
1.54      ihickson  394:   var data = event.data.split(' ');
1.31      ihickson  395:   switch (data[0]) {
                    396:     case '+':
                    397:      database.transaction(function(tx) {
                    398:        tx.executeSql('INSERT INTO pairs (key, value) VALUES (?, ?)', data[1], data[2]);
                    399:      });
                    400:     case '-':
                    401:      database.transaction(function(tx) {
                    402:        tx.executeSql('DELETE FROM pairs WHERE key=? AND value=?', data[1], data[2]);
                    403:      });
                    404:   }
                    405: };</pre>
                    406: 
                    407:   <p>This connects to the server using the <code>WebSocket</code> mechanism
                    408:    and opens the local database (which, we presume, has been created
1.58      ihickson  409:    earlier). The worker then just listens for messages from the server and
1.31      ihickson  410:    acts on them as appropriate, forever (or until the main page is closed).
                    411: 
                    412:   <p><a
                    413:    href="http://www.whatwg.org/demos/workers/database-updater/page.html">View
                    414:    this example online</a>. (This example will not actually function, since
                    415:    the server does not actually exist and the database is not created by this
                    416:    sample code.)
                    417: 
1.58      ihickson  418:   <h4 id=worker><span class=secno>1.2.3 </span>Worker used for background I/O</h4>
1.33      ihickson  419: 
                    420:   <p><em>This section is non-normative.</em>
                    421: 
                    422:   <p>In this example, the main document uses two workers, one for fetching
                    423:    stock updates for at regular intervals, and one for fetching performing
                    424:    search queries that the user requests.
                    425: 
                    426:   <p>The main page is as follows:
                    427: 
                    428:   <pre>&lt;!DOCTYPE HTML>
                    429: &lt;html>
                    430:  &lt;head>
                    431:   &lt;title>Worker example: Stock ticker&lt;/title>
                    432:   &lt;script>
                    433:    // TICKER
                    434:    var symbol = 'GOOG'; // default symbol to watch
1.50      ihickson  435:    var ticker = new Worker('ticker.js');
1.33      ihickson  436: 
                    437:    // SEARCHER
1.50      ihickson  438:    var searcher = new Worker('searcher.js');
1.33      ihickson  439:    function search(query) {
1.50      ihickson  440:      searcher.postMessage(query);
1.33      ihickson  441:    }
                    442: 
                    443:    // SYMBOL SELECTION UI
                    444:    function select(newSymbol) {
                    445:      symbol = newSymbol;
1.50      ihickson  446:      ticker.postMessage(symbol);
1.33      ihickson  447:    }
                    448:   &lt;/script>
                    449:  &lt;/head>
                    450:  &lt;body>
                    451:   &lt;p>&lt;output id="symbol">&lt;/output> &lt;output id="value">&lt;/output>&lt;/p>
                    452:   &lt;script>
1.50      ihickson  453:    ticker.onmessage = function (event) {
1.54      ihickson  454:      var data = event.data.split(' ');
1.33      ihickson  455:      document.getElementById('symbol').textContent = data[0];
                    456:      document.getElementById('value').textContent = data[1];
                    457:    };
1.50      ihickson  458:    ticker.postMessage(symbol);
1.33      ihickson  459:   &lt;/script>
                    460:   &lt;p>&lt;label>Search: &lt;input type="text" oninput="search(this.value)">&lt;/label>&lt;/p>
                    461:   &lt;ul id="results">&lt;/ul>
                    462:   &lt;script>
1.50      ihickson  463:    searcher.onmessage = function (event) {
1.54      ihickson  464:      var data = event.data.split(' ');
1.33      ihickson  465:      var results = document.getElementById('results');
                    466:      while (results.hasChildNodes()) // clear previous results
                    467:        results.removeChild(results.firstChild);
                    468:      for (var i = 0; i &lt; data.length; i += 1) {
                    469:        // add a list item with a button for each result
                    470:        var li = document.createElement('li');
                    471:        var button = document.createElement('button');
                    472:        button.value = data[i];
                    473:        button.type = 'button';
                    474:        button.onclick = function () { select(this.value); };
                    475:        button.textContent = data[i];
                    476:        li.appendChild(button);
                    477:        results.appendChild(li);
                    478:      }
                    479:    };
                    480:   &lt;/script>
                    481:   &lt;p>(The data in this example is not real. Try searching for "Google" or "Apple".)&lt;/p>
                    482:  &lt;/body>
                    483: &lt;/html></pre>
                    484: 
                    485:   <p>The two workers use a common library for performing the actual network
                    486:    calls. This library is as follows:
                    487: 
                    488:   <pre>function get(url) {
1.50      ihickson  489:   try {
                    490:     var xhr = new XMLHttpRequest();
                    491:     xhr.open('GET', url, false);
                    492:     xhr.send();
                    493:     return xhr.responseText;
                    494:   } catch (e) {
                    495:     return ''; // turn all errors into empty results
                    496:   }
1.33      ihickson  497: }</pre>
                    498: 
                    499:   <p>The stock updater worker is as follows:
                    500: 
1.45      ihickson  501:   <pre>importScripts('io.js');
1.33      ihickson  502: var timer;
                    503: var symbol;
                    504: function update() {
1.50      ihickson  505:   postMessage(symbol + ' ' + get('stock.cgi?' + symbol));
1.33      ihickson  506:   timer = setTimeout(update, 10000);
                    507: }
1.50      ihickson  508: onmessage = function (event) {
1.33      ihickson  509:   if (timer)
                    510:     clearTimeout(timer);
1.54      ihickson  511:   symbol = event.data;
1.33      ihickson  512:   update();
                    513: };</pre>
                    514: 
                    515:   <p>The search query worker is as follows:
                    516: 
1.45      ihickson  517:   <pre>importScripts('io.js');
1.50      ihickson  518: onmessage = function (event) {
1.54      ihickson  519:   postMessage(get('search.cgi?' + event.data));
1.33      ihickson  520: };</pre>
                    521: 
1.36      ihickson  522:   <p><a href="http://www.whatwg.org/demos/workers/stocks/page.html">View this
1.33      ihickson  523:    example online</a>.
                    524: 
1.55      ihickson  525:   <h4 id=shared><span class=secno>1.2.4 </span>Shared workers</h4>
1.34      ihickson  526: 
1.36      ihickson  527:   <p><em>This section is non-normative.</em>
                    528: 
                    529:   <p>In this example, multiple windows (viewers) can be opened that are all
                    530:    viewing the same map. All the windows share the same map information, with
                    531:    a single worker coordinating all the viewers. Each viewer can move around
                    532:    idependently, but if they set any data on the map, all the viewers are
                    533:    updated.
                    534: 
                    535:   <p>The main page isn't interesting, it merely provides a way to open the
                    536:    viewers:
                    537: 
                    538:   <pre>&lt;!DOCTYPE HTML>
                    539: &lt;html>
                    540:  &lt;head>
                    541:   &lt;title>Workers example: Multiviewer&lt;/title>
                    542:   &lt;script>
                    543:    function openViewer() {
                    544:      window.open('viewer.html');
                    545:    }
                    546:   &lt;/script>
                    547:  &lt;/head>
                    548:  &lt;body>
                    549:   &lt;p>&lt;button type=button onclick="openViewer()">Open a new
                    550:   viewer&lt;/button>&lt;/p>
                    551:   &lt;p>Each viewer opens in a new window. You can have as many viewers
                    552:   as you like, they all view the same data.&lt;/p>
                    553:  &lt;/body>
                    554: &lt;/html></pre>
                    555: 
                    556:   <p>The viewer is more involved:
                    557: 
                    558:   <pre>&lt;!DOCTYPE HTML>
                    559: &lt;html>
                    560:  &lt;head>
                    561:   &lt;title>Workers example: Multiviewer viewer&lt;/title>
                    562:   &lt;script>
1.50      ihickson  563:    var worker = new SharedWorker('worker.js', 'core');
1.36      ihickson  564: 
                    565:    // CONFIGURATION
                    566:    function configure(event) {
1.54      ihickson  567:      if (event.data.substr(0, 4) != 'cfg ') return;
                    568:      var name = event.data.substr(4).split(' ', 1);
1.36      ihickson  569:      // update display to mention our name is name
                    570:      document.getElementsByTagName('h1')[0].textContent += ' ' + name;
                    571:      // no longer need this listener
1.43      ihickson  572:      worker.port.removeEventListener('message', configure, false);
1.36      ihickson  573:    }
1.53      ihickson  574:    worker.port.addEventListener('message', configure, false);
1.36      ihickson  575: 
                    576:    // MAP
                    577:    function paintMap(event) {
1.54      ihickson  578:      if (event.data.substr(0, 4) != 'map ') return;
                    579:      var data = event.data.substr(4).split(',');
1.36      ihickson  580:      // display tiles data[0] .. data[8]
                    581:      var canvas = document.getElementById('map');
                    582:      var context = canvas.getContext('2d');
                    583:      for (var y = 0; y &lt; 3; y += 1) {
                    584:        for (var x = 0; x &lt; 3; x += 1) {
                    585:          var tile = data[y * 3 + x];
                    586:          if (tile == '0')
                    587:            context.fillStyle = 'green';
                    588:          else 
                    589:            context.fillStyle = 'maroon';
                    590:          fillRect(x * 50, y * 50, 50, 50);
                    591:        }
                    592:      }
                    593:    }
1.53      ihickson  594:    worker.port.addEventListener('message', paintMap, false);
1.36      ihickson  595: 
                    596:    // PUBLIC CHAT
                    597:    function updatePublicChat(event) {
1.54      ihickson  598:      if (event.data.substr(0, 4) != 'txt ') return;
                    599:      var name = event.data.substr(4).split(' ', 1);
                    600:      var message = event.data.substr(4 + length(name) + 1);
1.36      ihickson  601:      // display "&lt;name> message" in public chat
                    602:      var dialog = document.getElementById('public');
                    603:      var dt = document.createElement('dt');
                    604:      dt.textContent = name;
                    605:      dialog.appendChild(dt);
                    606:      var dd = document.createElement('dd');
                    607:      dd.textContent = message;
                    608:      dialog.appendChild(dd);
                    609:    }
1.53      ihickson  610:    worker.port.addEventListener('message', updatePublicChat, false);
1.36      ihickson  611: 
                    612:    // PRIVATE CHAT
                    613:    function startPrivateChat(event) {
1.54      ihickson  614:      if (event.data.substr(0, 4) != 'msg ') return;
                    615:      var name = event.data.substr(4).split(' ', 1);
1.36      ihickson  616:      var port = event.port;
                    617:      // display a private chat UI
                    618:      var ul = document.getElementById('private');
                    619:      var li = document.createElement('li');
                    620:      var h3 = document.createElement('h3');
                    621:      h3.textContent = 'Private chat with ' + name;
                    622:      li.appendChild(h3);
                    623:      var dialog = document.createElement('dialog');
                    624:      var addMessage = function(name, message) {
                    625:        var dt = document.createElement('dt');
                    626:        dt.textContent = name;
                    627:        dialog.appendChild(dt);
                    628:        var dd = document.createElement('dd');
                    629:        dd.textContent = message;
                    630:        dialog.appendChild(dd);
                    631:      };
                    632:      port.onmessage = function (event) {
1.54      ihickson  633:        addMessage(name, event.data);
1.36      ihickson  634:      };
                    635:      li.appendChild(dialog);
                    636:      var form = document.createElement('form');
                    637:      var p = document.createElement('p');
                    638:      var input = document.createElement('input');
                    639:      input.size = 50;
                    640:      p.appendChild(input);
                    641:      p.appendChild(document.createTextNode(' '));
                    642:      var button = document.createElement('button');
                    643:      button.textContent = 'Post';
                    644:      p.appendChild(button);
                    645:      form.onsubmit = function () {
                    646:        port.postMessage(input.value);
                    647:        addMessage('me', input.value);
                    648:        input.value = '';
                    649:        return false;
                    650:      };
                    651:      form.appendChild(p);
                    652:      li.appendChild(form);
                    653:    }
1.53      ihickson  654:    worker.port.addEventListener('message', startPrivateChat, false);
1.36      ihickson  655:   &lt;/script>
                    656:  &lt;/head>
1.50      ihickson  657:  &lt;body>
1.36      ihickson  658:   &lt;h1>Viewer&lt;/h1>
                    659:   &lt;h2>Map&lt;/h2>
                    660:   &lt;p>&lt;canvas id="map" height=150 width=150>&lt;/canvas>&lt;/p>
                    661:   &lt;p>
1.53      ihickson  662:    &lt;button type=button onclick="worker.port.postMessage('mov left')">Left&lt;/button>
                    663:    &lt;button type=button onclick="worker.port.postMessage('mov up')">Up&lt;/button>
                    664:    &lt;button type=button onclick="worker.port.postMessage('mov down')">Down&lt;/button>
                    665:    &lt;button type=button onclick="worker.port.postMessage('mov right')">Right&lt;/button>
                    666:    &lt;button type=button onclick="worker.port.postMessage('set 0')">Set 0&lt;/button>
                    667:    &lt;button type=button onclick="worker.port.postMessage('set 1')">Set 1&lt;/button>
1.36      ihickson  668:   &lt;/p>
                    669:   &lt;h2>Public Chat&lt;/h2>
                    670:   &lt;dialog id="public">&lt;/dialog>
1.53      ihickson  671:   &lt;form onsubmit="worker.port.postMessage('txt ' + message.value); message.value = ''; return false;">
1.36      ihickson  672:    &lt;p>
                    673:     &lt;input type="text" name="message" size="50">
                    674:     &lt;button>Post&lt;/button>
                    675:    &lt;/p>
                    676:   &lt;/form>
                    677:   &lt;h2>Private Chat&lt;/h2>
                    678:   &lt;ul id="private">&lt;/ul>
                    679:  &lt;/body>
1.43      ihickson  680: &lt;/html>
                    681: </pre>
1.36      ihickson  682: 
                    683:   <p>There are several key things worth noting about the way the viewer is
                    684:    written.
                    685: 
                    686:   <p><strong>Multiple listeners</strong>. Instead of a single message
                    687:    processing function, the code here attaches multiple event listeners, each
                    688:    one performing a quick check to see if it is relevant for the message. In
                    689:    this example it doesn't make much difference, but if multiple authors
                    690:    wanted to collaborate using a single port to communicate with a worker, it
                    691:    would allow for independent code instead of changes having to all be made
                    692:    to a single event handling function.
                    693: 
                    694:   <p>Registering event listeners in this way also allows you to unregister
                    695:    specific listeners when you are done with them, as is done with the <code
                    696:    title="">configure()</code> method in this example.
                    697: 
                    698:   <p>Finally, the worker:
                    699: 
                    700:   <pre>
                    701: var nextName = 0;
                    702: function getNextName() {
                    703:   // this could use more friendly names
                    704:   // but for now just return a number
                    705:   return nextName++;
                    706: }
                    707: 
                    708: var map = [
                    709:  [0, 0, 0, 0, 0, 0, 0],
                    710:  [1, 1, 0, 1, 0, 1, 1],
                    711:  [0, 1, 0, 1, 0, 0, 0],
                    712:  [0, 1, 0, 1, 0, 1, 1],
                    713:  [0, 0, 0, 1, 0, 0, 0],
                    714:  [1, 0, 0, 1, 1, 1, 1],
                    715:  [1, 1, 0, 1, 1, 0, 1],
                    716: ];
                    717: 
                    718: function wrapX(x) {
                    719:   if (x &lt; 0) return wrapX(x + map[0].length);
                    720:   if (x >= map[0].length) return wrapX(x - map[0].length);
                    721:   return x;
                    722: }
                    723: 
                    724: function wrapY(y) {
                    725:   if (y &lt; 0) return wrapY(y + map.length);
                    726:   if (y >= map[0].length) return wrapY(y - map.length);
                    727:   return y;
                    728: }
                    729: 
1.50      ihickson  730: function sendMapData(callback) {
1.36      ihickson  731:   var data = '';
                    732:   for (var y = viewer.y-1; y &lt;= viewer.y+1; y += 1) {
                    733:     for (var x = viewer.x-1; x &lt;= viewer.x+1; x += 1) {
                    734:       if (data != '')
                    735:         data += ',';
                    736:       data += map[y][x];
                    737:     }
                    738:   }
1.50      ihickson  739:   callback('map ' + data);
1.36      ihickson  740: }
                    741: 
                    742: var viewers = {};
                    743: onconnect = function (event) {
                    744:   event.port._name = getNextName();
                    745:   event.port._data = { port: event.port, x: 0, y: 0, };
                    746:   viewers[event.port._name] = event.port._data;
                    747:   event.port.postMessage('cfg ' + name);
                    748:   event.port.onmessage = getMessage;
1.50      ihickson  749:   sendMapData(event.port.postMessage);
1.36      ihickson  750: };
                    751: 
                    752: function getMessage(event) {
1.54      ihickson  753:   switch (event.data.substr(0, 4)) {
1.36      ihickson  754:     case 'mov ':
1.54      ihickson  755:       var direction = event.data.substr(4);
1.36      ihickson  756:       var dx = 0;
                    757:       var dy = 0;
                    758:       switch (direction) {
                    759:         case 'up': dy = -1; break;
                    760:         case 'down': dy = 1; break;
                    761:         case 'left': dx = -1; break;
                    762:         case 'right': dx = 1; break;
                    763:       }
                    764:       event.target._data.x = wrapX(event.target._data.x + dx);
                    765:       event.target._data.y = wrapY(event.target._data.y + dy);
1.50      ihickson  766:       sendMapData(event.target.postMessage);
1.36      ihickson  767:       break;
                    768:     case 'set ':
1.54      ihickson  769:       var value = event.data.substr(4);
1.36      ihickson  770:       map[event.target._data.y][event.target._data.x] = value;
                    771:       for (var viewer in viewers)
1.50      ihickson  772:         sendMapData(viewers[viewer].port.postMessage);
1.36      ihickson  773:       break;
                    774:     case 'txt ':
                    775:       var name = event.target._name;
1.54      ihickson  776:       var message = event.data.substr(4);
1.36      ihickson  777:       for (var viewer in viewers)
                    778:         viewers[viewer].port.postMessage('txt ' + name + ' ' + message);
                    779:       break;
                    780:     case 'msg ':
                    781:       var party1 = event._data;
1.54      ihickson  782:       var party2 = viewers[event.data.substr(4).split(' ', 1)];
1.36      ihickson  783:       if (party2) {
                    784:         var channel = new MessageChannel();
                    785:         party1.port.postMessage('msg ' + party2.name, channel.port1);
                    786:         party2.port.postMessage('msg ' + party1.name, channel.port2);
                    787:       }
                    788:       break;
                    789:   }
                    790: }</pre>
                    791: 
1.50      ihickson  792:   <p><strong>Connecting to multiple pages</strong>. The script uses the <code
                    793:    title=handler-SharedWorkerGlobalScope-onconnect><a
1.37      ihickson  794:    href="#onconnect">onconnect</a></code> event listener to listen for
                    795:    multiple connections.
1.36      ihickson  796: 
                    797:   <p><strong>Direct channels</strong>. When the worker receives a "msg"
                    798:    message from one viewer naming another viewer, it sets up a direct
                    799:    connection between the two, so that the two viewers can communicate
                    800:    directly without the worker having to proxy all the messages.
                    801: 
                    802:   <p><a href="http://www.whatwg.org/demos/workers/multiviewer/page.html">View
                    803:    this example online</a>.
1.34      ihickson  804: 
1.55      ihickson  805:   <h4 id=delegation><span class=secno>1.2.5 </span>Delegation</h4>
1.34      ihickson  806: 
1.36      ihickson  807:   <p><em>This section is non-normative.</em>
                    808: 
1.40      ihickson  809:   <p>With multicore CPUs becoming prevalent, one way to obtain better
                    810:    performance is to split computationally expensive tasks amongst multiple
                    811:    workers. In this example, a computationally expensive task that is to be
                    812:    performed for every number from 1 to 10,000,000 is farmed out to ten
                    813:    subworkers.
                    814: 
                    815:   <p>The main page is as follows, it just reports the result:
                    816: 
                    817:   <pre>&lt;!DOCTYPE HTML>
                    818: &lt;html>
                    819:  &lt;head>
                    820:   &lt;title>Worker example: One-core computation&lt;/title>
                    821:  &lt;/head>
                    822:  &lt;body>
                    823:   &lt;p>The highest prime number discovered so far is: &lt;output id="result">&lt;/output>&lt;/p>
                    824:   &lt;script>
1.50      ihickson  825:    var worker = new Worker('worker.js');
                    826:    worker.onmessage = function (event) {
1.54      ihickson  827:      document.getElementById('result').textContent = event.data;
1.40      ihickson  828:    };
                    829:   &lt;/script>
                    830:  &lt;/body>
                    831: &lt;/html></pre>
                    832: 
                    833:   <p>The worker itself is as follows:
                    834: 
                    835:   <pre>// settings
                    836: var num_workers = 10;
                    837: var items_per_worker = 1000000;
                    838: 
                    839: // start the workers
                    840: var result = 0;
                    841: var pending_workers = num_workers;
                    842: for (var i = 0; i &lt; num_workers; i += 1) {
1.50      ihickson  843:   var worker = new Worker('core.js');
                    844:   worker.postMessage(i * items_per_worker);
                    845:   worker.postMessage((i+1) * items_per_worker);
                    846:   worker.onmessage = storeResult;
1.40      ihickson  847: }
                    848: 
                    849: // handle the results
                    850: function storeResult(event) {
1.54      ihickson  851:   result += 1*event.data;
1.40      ihickson  852:   pending_workers -= 1;
                    853:   if (pending_workers &lt;= 0)
1.50      ihickson  854:     postMessage(result); // finished!
1.40      ihickson  855: }</pre>
                    856: 
                    857:   <p>It consists of a loop to start the subworkers, and then a handler that
                    858:    waits for all the subworkers to respond.
                    859: 
                    860:   <p>The subworkers are implemented as follows:
                    861: 
                    862:   <pre>var start;
1.41      ihickson  863: onmessage = getStart;
1.40      ihickson  864: function getStart(event) {
1.54      ihickson  865:   start = 1*event.data;
1.40      ihickson  866:   onmessage = getEnd;
                    867: }
                    868: 
                    869: var end;
                    870: function getEnd(event) {
1.54      ihickson  871:   end = 1*event.data;
1.40      ihickson  872:   onmessage = null;
                    873:   do();
                    874: }
                    875: 
                    876: function do() {
                    877:   var result = 0;
                    878:   for (var i = start; i &lt; end; i += 1) {
                    879:     // perform some complex calculation here
                    880:     result += 1;
                    881:   }
1.50      ihickson  882:   postMessage(result);
                    883:   close();
1.40      ihickson  884: }</pre>
                    885: 
                    886:   <p>They receive two numbers in two events, perform the computation for the
                    887:    range of numbers thus specified, and then report the result back to the
                    888:    parent.
                    889: 
                    890:   <p><a href="http://www.whatwg.org/demos/workers/multicore/page.html">View
                    891:    this example online</a>.
1.34      ihickson  892: 
1.55      ihickson  893:   <h4 id=providing><span class=secno>1.2.6 </span>Providing libraries</h4>
1.49      ihickson  894: 
                    895:   <p><em>This section is non-normative.</em>
                    896: 
                    897:   <p>Suppose that a cryptography library is made available that provides
                    898:    three tasks:
                    899: 
                    900:   <dl>
                    901:    <dt>Generate a public/private key pair
                    902: 
                    903:    <dd>Takes a port, on which it will send two messages, first the public key
                    904:     and then the private key.
                    905: 
                    906:    <dt>Given a plaintext and a public key, return the corresponding
                    907:     cyphertext
                    908: 
                    909:    <dd>Takes a port, to which any number of messages can be sent, the first
                    910:     giving the public key, and the remainder giving the plaintext, each of
                    911:     which is encrypted and then sent on that same channel as the cyphertext.
                    912:     The user can close the port when it is done encrypting content.
                    913: 
                    914:    <dt>Given a cyphertext and a private key, return the corresponding
                    915:     plaintext
                    916: 
                    917:    <dd>Takes a port, to which any number of messages can be sent, the first
                    918:     giving the private key, and the remainder giving the cyphertext, each of
                    919:     which is decrypted and then sent on that same channel as the plaintext.
                    920:     The user can close the port when it is done decrypting content.
                    921:   </dl>
                    922: 
                    923:   <p>The library itself is as follows:
                    924: 
                    925:   <pre>function handleMessage(e) {
1.54      ihickson  926:   if (e.data == "genkeys")
1.49      ihickson  927:     genkeys(e.port);
1.54      ihickson  928:   else if (e.data == "encrypt")
1.49      ihickson  929:     encrypt(e.port);
1.54      ihickson  930:   else if (e.data == "decrypt")
1.49      ihickson  931:     decrypt(e.port);
                    932: }
                    933: 
                    934: function genkeys(p) {
                    935:   var keys = _generateKeyPair();
                    936:   p.postMessage(keys[0]);
                    937:   p.postMessage(keys[1]);
                    938: }
                    939: 
                    940: function encrypt(p) {
                    941:   var key, state = 0;
                    942:   p.onmessage = function (e) {
                    943:     if (state == 0) {
1.54      ihickson  944:       key = e.data;
1.49      ihickson  945:       state = 1;
                    946:     } else {
1.54      ihickson  947:       p.postMessage(_encrypt(key, e.data));
1.49      ihickson  948:     }
                    949:   };
                    950: }
                    951: 
                    952: function decrypt(p) {
                    953:   var key, state = 0;
                    954:   p.onmessage = function (e) {
                    955:     if (state == 0) {
1.54      ihickson  956:       key = e.data;
1.49      ihickson  957:       state = 1;
                    958:     } else {
1.54      ihickson  959:       p.postMessage(_decrypt(key, e.data));
1.49      ihickson  960:     }
                    961:   };
                    962: }
                    963: 
1.50      ihickson  964: // support being used as a shared worker as well as a dedicated worker
                    965: if (this.onmessage) // dedicated worker
                    966:   onmessage = handleMessage;
                    967: else // shared worker
                    968:   onconnect = function (e) { e.port.onmessage = handleMessage; }
1.49      ihickson  969: 
                    970: 
                    971: // the "crypto" functions:
                    972: 
                    973: function _generateKeyPair() {
                    974:   return [Math.random(), Math.random()];
                    975: }
                    976: 
                    977: function _encrypt(k, s) {
                    978:   return 'encrypted-' + k + ' ' + s;
                    979: }
                    980: 
                    981: function _decrypt(k, s) {
                    982:   return s.substr(s.indexOf(' ')+1);
                    983: }</pre>
                    984: 
                    985:   <p>Note that the crypto functions here are just stubs and don't do real
                    986:    cryptography.
                    987: 
                    988:   <p>This library could be used as follows:
                    989: 
                    990:   <pre>&lt;!DOCTYPE HTML>
                    991: &lt;html>
                    992:  &lt;head>
                    993:   &lt;title>Worker example: Crypto library&lt;/title>
                    994:   &lt;script>
1.50      ihickson  995:    var crytoLib = new Worker('libcrypto-v1.js'); // or could use 'libcrypto-v2.js'
1.49      ihickson  996:    function getKeys() {
                    997:      var state = 0;
1.50      ihickson  998:      cryptoLib.startConversation("genkeys").onmessage = function (e) {
1.49      ihickson  999:        if (state == 0)
1.54      ihickson 1000:          document.getElementById('public').value = e.data;
1.49      ihickson 1001:        else if (state == 1)
1.54      ihickson 1002:          document.getElementById('private').value = e.data;
1.49      ihickson 1003:        state += 1;
                   1004:      };
                   1005:    }
                   1006:    function enc() {
1.50      ihickson 1007:      var port = cryptoLib.startConversation("encrypt");
                   1008:      port.postMessage(document.getElementById('public').value);
                   1009:      port.postMessage(document.getElementById('input').value);
                   1010:      port.onmessage = function (e) {
1.54      ihickson 1011:        document.getElementById('input').value = e.data;
1.50      ihickson 1012:        port.close();
1.49      ihickson 1013:      };
                   1014:    }
                   1015:    function dec() {
1.50      ihickson 1016:      var port = cryptoLib.startConversation("decrypt");
                   1017:      port.postMessage(document.getElementById('private').value);
                   1018:      port.postMessage(document.getElementById('input').value);
                   1019:      port.onmessage = function (e) {
1.54      ihickson 1020:        document.getElementById('input').value = e.data;
1.50      ihickson 1021:        port.close();
1.49      ihickson 1022:      };
                   1023:    }
                   1024:   &lt;/script>
                   1025:   &lt;style>
                   1026:    textarea { display: block; }
                   1027:   &lt;/style>
                   1028:  &lt;/head>
                   1029:  &lt;body onload="getKeys()">
                   1030:   &lt;fieldset>
                   1031:    &lt;legend>Keys&lt;/legend>
1.50      ihickson 1032:    &lt;p>&lt;label>Public Key: &lt;textarea id="public">&lt;/textarea>&lt;/label>&lt;/p>
                   1033:    &lt;p>&lt;label>Private Key: &lt;textarea id="private">&lt;/textarea>&lt;/label>&lt;/p>
1.49      ihickson 1034:   &lt;/fieldset>
1.50      ihickson 1035:   &lt;p>&lt;label>Input: &lt;textarea id="input">&lt;/textarea>&lt;/label>&lt;/p>
1.49      ihickson 1036:   &lt;p>&lt;button onclick="enc()">Encrypt&lt;/button> &lt;button onclick="dec()">Decrypt&lt;/button>&lt;/p>
                   1037:  &lt;/body>
                   1038: &lt;/html></pre>
                   1039: 
                   1040:   <p>A later version of the API, though, might want to offload all the crypto
                   1041:    work onto subworkers. This could be done as follows:
                   1042: 
                   1043:   <pre>function handleMessage(e) {
1.54      ihickson 1044:   if (e.data == "genkeys")
1.49      ihickson 1045:     genkeys(e.port);
1.54      ihickson 1046:   else if (e.data == "encrypt")
1.49      ihickson 1047:     encrypt(e.port);
1.54      ihickson 1048:   else if (e.data == "decrypt")
1.49      ihickson 1049:     decrypt(e.port);
                   1050: }
                   1051: 
                   1052: function genkeys(p) {
1.50      ihickson 1053:   var generator = new Worker('libcrypto-v2-generator.js');
1.49      ihickson 1054:   generator.postMessage('', p);
                   1055: }
                   1056: 
                   1057: function encrypt(p) {
                   1058:   p.onmessage = function (e) {
1.54      ihickson 1059:     var key = e.data;
1.50      ihickson 1060:     var encryptor = new Worker('libcrypto-v2-encryptor.js');
1.49      ihickson 1061:     encryptor.postMessage(key, p);
                   1062:   };
                   1063: }
                   1064: 
                   1065: function encrypt(p) {
                   1066:   p.onmessage = function (e) {
1.54      ihickson 1067:     var key = e.data;
1.50      ihickson 1068:     var decryptor = new Worker('libcrypto-v2-decryptor.js');
1.49      ihickson 1069:     decryptor.postMessage(key, p);
                   1070:   };
                   1071: }
                   1072: 
1.50      ihickson 1073: // support being used as a shared worker as well as a dedicated worker
                   1074: if (this.onmessage) // dedicated worker
                   1075:   onmessage = handleMessage;
                   1076: else // shared worker
                   1077:   onconnect = function (e) { e.port.onmessage = handleMessage; }
1.49      ihickson 1078: </pre>
                   1079: 
                   1080:   <p>The little subworkers would then be as follows.
                   1081: 
                   1082:   <p>For generating key pairs:
                   1083: 
1.50      ihickson 1084:   <pre>onmessage = function (e) {
                   1085:   var k = _generateKeyPair();
                   1086:   e.port.postMessage(k[0]);
                   1087:   e.port.postMessage(k[1]);
1.49      ihickson 1088:   close();
                   1089: }
1.50      ihickson 1090: 
                   1091: function _generateKeyPair() {
                   1092:   return [Math.random(), Math.random()];
                   1093: }</pre>
1.49      ihickson 1094: 
                   1095:   <p>For encrypting:
                   1096: 
1.50      ihickson 1097:   <pre>onmessage = function (e) {
1.54      ihickson 1098:   var key = e.data;
1.49      ihickson 1099:   e.port.onmessage = function (e) {
1.54      ihickson 1100:     var s = e.data;
1.50      ihickson 1101:     postMessage(_encrypt(key, s));
1.49      ihickson 1102:   }
1.50      ihickson 1103:   e.port.onclose = function (e) {
1.49      ihickson 1104:     close();
                   1105:   }
1.50      ihickson 1106: }
                   1107: 
                   1108: function _encrypt(k, s) {
                   1109:   return 'encrypted-' + k + ' ' + s;
1.49      ihickson 1110: }</pre>
                   1111: 
                   1112:   <p>For decrypting:
                   1113: 
1.50      ihickson 1114:   <pre>onmessage = function (e) {
1.54      ihickson 1115:   var key = e.data;
1.49      ihickson 1116:   e.port.onmessage = function (e) {
1.54      ihickson 1117:     var s = e.data;
1.50      ihickson 1118:     postMessage(_decrypt(key, s));
1.49      ihickson 1119:   }
1.50      ihickson 1120:   e.port.onclose = function (e) {
1.49      ihickson 1121:     close();
                   1122:   }
1.50      ihickson 1123: }
                   1124: 
                   1125: function _decrypt(k, s) {
                   1126:   return s.substr(s.indexOf(' ')+1);
1.49      ihickson 1127: }</pre>
                   1128: 
                   1129:   <p>Notice how the users of the API don't have to even know that this is
                   1130:    happening &mdash; the API hasn't changed; the library can delegate to
                   1131:    subworkers without changing its API, even though it is accepting data
                   1132:    using message channels.
                   1133: 
                   1134:   <p><a href="http://www.whatwg.org/demos/workers/crypto/page.html">View this
                   1135:    example online</a>.
                   1136: 
1.55      ihickson 1137:   <h3 id=conformance><span class=secno>1.3 </span>Conformance requirements</h3>
1.1       ihickson 1138: 
                   1139:   <p>All diagrams, examples, and notes in this specification are
                   1140:    non-normative, as are all sections explicitly marked non-normative.
                   1141:    Everything else in this specification is normative.
                   1142: 
                   1143:   <p>The key words "MUST", "MUST NOT", "REQUIRED", <!--"SHALL", "SHALL
                   1144:   NOT",-->
                   1145:    "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in the
                   1146:    normative parts of this document are to be interpreted as described in
                   1147:    RFC2119. For readability, these words do not appear in all uppercase
                   1148:    letters in this specification. <a href="#refsRFC2119">[RFC2119]</a></p>
                   1149:   <!-- XXX but they should be
                   1150:   marked up -->
                   1151: 
                   1152:   <p>Requirements phrased in the imperative as part of algorithms (such as
                   1153:    "strip any leading space characters" or "return false and abort these
                   1154:    steps") are to be interpreted with the meaning of the key word ("must",
                   1155:    "should", "may", etc) used in introducing the algorithm.
                   1156: 
                   1157:   <p>Some conformance requirements are phrased as requirements on attributes,
                   1158:    methods or objects. Such requirements are to be interpreted as
                   1159:    requirements on user agents.
                   1160: 
                   1161:   <p>Conformance requirements phrased as algorithms or specific steps may be
                   1162:    implemented in any manner, so long as the end result is equivalent. (In
                   1163:    particular, the algorithms defined in this specification are intended to
                   1164:    be easy to follow, and not intended to be performant.)
                   1165: 
                   1166:   <p>The only conformance class defined by this specification is user agents.
                   1167: 
                   1168:   <p>User agents may impose implementation-specific limits on otherwise
                   1169:    unconstrained inputs, e.g. to prevent denial of service attacks, to guard
                   1170:    against running out of memory, or to work around platform-specific
                   1171:    limitations.
                   1172: 
1.55      ihickson 1173:   <h4 id=dependencies><span class=secno>1.3.1 </span>Dependencies</h4>
1.1       ihickson 1174: 
                   1175:   <p>This specification relies on several other underlying specifications.
                   1176: 
                   1177:   <dl>
                   1178:    <dt>HTML5
                   1179: 
                   1180:    <dd>
                   1181:     <p>Many fundamental concepts from HTML5 are used by this specification.
                   1182:      <a href="#refsHTML5">[HTML5]</a></p>
                   1183: 
                   1184:    <dt>ECMAScript
                   1185: 
                   1186:    <dd>
                   1187:     <p>This specification is intended to be used with JavaScript as the
                   1188:      scripting language. <a href="#refsJS">[JS]</a></p>
                   1189: 
                   1190:    <dt>WebIDL
                   1191: 
                   1192:    <dd>
                   1193:     <p>The IDL blocks in this specification use the semantics of the WebIDL
                   1194:      specification. <a href="#refsWebIDL">[WebIDL]</a></p>
                   1195:   </dl>
                   1196: 
1.55      ihickson 1197:   <h3 id=terminology><span class=secno>1.4 </span>Terminology</h3>
1.1       ihickson 1198: 
                   1199:   <p>For simplicity, terms such as <em>shown</em>, <em>displayed</em>, and
                   1200:    <em>visible</em> might sometimes be used when referring to the way a
                   1201:    document is rendered to the user. These terms are not meant to imply a
                   1202:    visual medium; they must be considered to apply to other media in
                   1203:    equivalent ways.
                   1204: 
1.4       ihickson 1205:   <p>The construction "a <code title="">Foo</code> object", where <code
                   1206:    title="">Foo</code> is actually an interface, is sometimes used instead of
                   1207:    the more accurate "an object implementing the interface <code
                   1208:    title="">Foo</code>".
1.1       ihickson 1209: 
                   1210:   <p>The term DOM is used to refer to the API set made available to scripts
                   1211:    in Web applications, and does not necessarily imply the existence of an
                   1212:    actual <code>Document</code> object or of any other <code>Node</code>
                   1213:    objects as defined in the DOM Core specifications. <a
                   1214:    href="#refsDOM3CORE">[DOM3CORE]</a>
                   1215: 
                   1216:   <p>A DOM attribute is said to be <em>getting</em> when its value is being
                   1217:    retrieved (e.g. by author script), and is said to be <em>setting</em> when
                   1218:    a new value is assigned to it.
                   1219: 
                   1220:   <p>If a DOM object is said to be <dfn id=live>live</dfn>, then that means
                   1221:    that any attributes returning that object must always return the same
                   1222:    object (not a new object each time), and the attributes and methods on
                   1223:    that object must operate on the actual underlying data, not a snapshot of
                   1224:    the data.
                   1225: 
1.12      ihickson 1226:   <h2 id=infrastructure><span class=secno>2. </span>Infrastructure</h2>
1.4       ihickson 1227: 
1.50      ihickson 1228:   <p>There are two kinds of workers; dedicated workers, and shared workers.
                   1229:    Dedicated workers, once created, and are linked to their creator; but
                   1230:    message ports can be used to communicate from a dedicated worker to
                   1231:    multple other browsing contexts or workers. Shared workers, on the other
                   1232:    hand, are named, and once created any script running in the same
                   1233:    <span>origin</span> can obtain a reference to that worker and communicate
                   1234:    with it.
                   1235: 
                   1236:   <h3 id=the-global><span class=secno>2.1 </span>The global scope</h3>
                   1237: 
                   1238:   <p>The global scope is the "inside" of a worker.
                   1239: 
                   1240:   <h4 id=the-workerglobalscope><span class=secno>2.1.1 </span>The <code><a
                   1241:    href="#workerglobalscope">WorkerGlobalScope</a></code> abstract interface</h4>
1.4       ihickson 1242: 
                   1243:   <pre
1.26      ihickson 1244:    class=idl>[NoInterfaceObject] interface <dfn id=workerglobalscope>WorkerGlobalScope</dfn> {
                   1245:   readonly attribute <a href="#workerglobalscope">WorkerGlobalScope</a> <a href="#self" title=dom-WorkerGlobalScope-self>self</a>;
1.34      ihickson 1246:   readonly attribute <a href="#workerlocation">WorkerLocation</a> <a href="#location" title=dom-WorkerGlobalScope-location>location</a>;
1.50      ihickson 1247:   // also implements everything on <a href="#workerutils">WorkerUtils</a>
                   1248: 
1.26      ihickson 1249:   void <a href="#close" title=dom-WorkerGlobalScope-close>close</a>();
1.50      ihickson 1250:            attribute <span>EventListener</span> <a href="#onclose" title=handler-WorkerGlobalScope-onclose>onclose</a>;
1.4       ihickson 1251: };</pre>
                   1252: 
1.39      ihickson 1253:   <p>Objects implementing the <code><a
1.50      ihickson 1254:    href="#workerglobalscope">WorkerGlobalScope</a></code> interface it must
                   1255:    also implement the <code>EventTarget</code> interface.
1.39      ihickson 1256: 
1.26      ihickson 1257:   <p>The <dfn id=self
                   1258:    title=dom-WorkerGlobalScope-self><code>self</code></dfn> attribute must
                   1259:    return the <code><a href="#workerglobalscope">WorkerGlobalScope</a></code>
                   1260:    object itself.
1.9       ihickson 1261: 
1.34      ihickson 1262:   <p>The <dfn id=location
                   1263:    title=dom-WorkerGlobalScope-location><code>location</code></dfn> attribute
                   1264:    must return the <code><a href="#workerlocation">WorkerLocation</a></code>
                   1265:    object created for the <code><a
                   1266:    href="#workerglobalscope">WorkerGlobalScope</a></code> object when the
                   1267:    worker was created. It represents the <span>absolute URL</span> of the
                   1268:    script that was used to initialize the worker.
1.26      ihickson 1269: 
1.50      ihickson 1270:   <hr>
                   1271: 
                   1272:   <p>When a script invokes the <dfn id=close
                   1273:    title=dom-WorkerGlobalScope-close><code>close()</code></dfn> method on a
                   1274:    <code><a href="#workerglobalscope">WorkerGlobalScope</a></code> object,
                   1275:    the user agent must run the following steps:
                   1276: 
                   1277:   <ol>
                   1278:    <li>
                   1279:     <p>Create an <code>Event</code> object with the event name <code
                   1280:      title=event-close>close</code>, which does not bubble and is not
                   1281:      cancelable, and add it to the <code><a
                   1282:      href="#workerglobalscope">WorkerGlobalScope</a></code> object's <a
                   1283:      href="#queue">queue of events</a>, targetted at the <code><a
                   1284:      href="#workerglobalscope">WorkerGlobalScope</a></code> object itself.
                   1285: 
                   1286:    <li>
                   1287:     <p>Set the worker's <code><a
                   1288:      href="#workerglobalscope">WorkerGlobalScope</a></code> object's <a
                   1289:      href="#closing" title=dom-WorkerGlobalScope-closing>closing</a> flag to
                   1290:      true.
                   1291: 
                   1292:    <li>
                   1293:     <p>For each <code>MessagePort</code> object that is entangled with
                   1294:      another port and that has one (but only one) port whose owner is the
                   1295:      <code><a href="#workerglobalscope">WorkerGlobalScope</a></code> object
                   1296:      on which the method was invoked (this would include, for instance, the
                   1297:      implicit port in used for dedicated workers), run the following
                   1298:      substeps:</p>
                   1299: 
                   1300:     <ol>
                   1301:      <li>
                   1302:       <p>Unentangle the two ports.
                   1303: 
                   1304:      <li>
                   1305:       <p>At the next available opportunity, after any scripts have finished
                   1306:        executing<!-- XXX queue -->, <span>fire a simple event</span> called
                   1307:        <code title=event-close>close</code> at the other port (the one whose
                   1308:        owner is not the <code><a
                   1309:        href="#workerglobalscope">WorkerGlobalScope</a></code> object on which
                   1310:        the <code title=dom-WorkerGlobalScope-close><a
                   1311:        href="#close">close()</a></code> method was called).
                   1312:     </ol>
                   1313:   </ol>
1.4       ihickson 1314: 
1.9       ihickson 1315:   <p>The following are the <span>event handler DOM attributes</span> that
                   1316:    must be supported by objects implementing the <code><a
1.26      ihickson 1317:    href="#workerglobalscope">WorkerGlobalScope</a></code> interface:
1.9       ihickson 1318: 
                   1319:   <dl>
1.50      ihickson 1320:    <dt><dfn id=onclose
                   1321:     title=handler-WorkerGlobalScope-onclose><code>onclose</code></dfn>
1.9       ihickson 1322: 
                   1323:    <dd>
1.50      ihickson 1324:     <p>Must be invoked whenever a <code title=event-close>close</code> event
                   1325:      is targeted at or bubbles through the <code><a
1.26      ihickson 1326:      href="#workerglobalscope">WorkerGlobalScope</a></code> object.
1.50      ihickson 1327:   </dl>
                   1328: 
                   1329:   <h4 id=dedicated><span class=secno>2.1.2 </span>Dedicated workers and the
                   1330:    <code><a
                   1331:    href="#dedicatedworkerglobalscope">DedicatedWorkerGlobalScope</a></code>
                   1332:    interface</h4>
                   1333: 
                   1334:   <pre
                   1335:    class=idl>[NoInterfaceObject] interface <dfn id=dedicatedworkerglobalscope>DedicatedWorkerGlobalScope</dfn> : <a href="#workerglobalscope">WorkerGlobalScope</a> {
1.51      ihickson 1336:   void <a href="#postmessage" title=dom-DedicatedWorkerGlobalScope-postMessage>postMessage</a>(in DOMString message);
                   1337:   void <a href="#postmessage" title=dom-DedicatedWorkerGlobalScope-postMessage>postMessage</a>(in DOMString message, in <span>MessagePort</span> messagePort);
1.50      ihickson 1338:   <span>MessagePort</span> <a href="#startconversation" title=dom-DedicatedWorkerGlobalScope-startConversation>startConversation</a>(in DOMString message);
                   1339:            attribute <span>EventListener</span> <a href="#onmessage" title=handler-DedicatedWorkerGlobalScope-onmessage>onmessage</a>;
                   1340: };</pre>
1.9       ihickson 1341: 
1.50      ihickson 1342:   <p><code><a
                   1343:    href="#dedicatedworkerglobalscope">DedicatedWorkerGlobalScope</a></code>
                   1344:    objects act as if they had an implicit <code>MessagePort</code> associated
                   1345:    with them. This port is part of a channel that is set up when the worker
                   1346:    is created, but it is not exposed. This object must never be garbage
                   1347:    collected before the <code><a
                   1348:    href="#dedicatedworkerglobalscope">DedicatedWorkerGlobalScope</a></code>
                   1349:    object.
                   1350: 
                   1351:   <p>All messages received by that port must immediately be retargetted at
                   1352:    the <code><a
                   1353:    href="#dedicatedworkerglobalscope">DedicatedWorkerGlobalScope</a></code>
                   1354:    object.
                   1355: 
                   1356:   <p>The <dfn id=postmessage
                   1357:    title=dom-DedicatedWorkerGlobalScope-postMessage><code>postMessage()</code></dfn>
                   1358:    and <dfn id=startconversation
                   1359:    title=dom-DedicatedWorkerGlobalScope-startConversation><code>startConversation()</code></dfn>
                   1360:    methods on <code><a
                   1361:    href="#dedicatedworkerglobalscope">DedicatedWorkerGlobalScope</a></code>
                   1362:    objects must act as if, when invoked, they immediately invoked the method
1.51      ihickson 1363:    of the same name on the port, with the same arguments, and returned the
                   1364:    same return value.
1.50      ihickson 1365: 
                   1366:   <p>The following are the <span>event handler DOM attributes</span> that
                   1367:    must be supported by objects implementing the <code><a
                   1368:    href="#dedicatedworkerglobalscope">DedicatedWorkerGlobalScope</a></code>
                   1369:    interface:
                   1370: 
                   1371:   <dl>
                   1372:    <dt><dfn id=onmessage
                   1373:     title=handler-DedicatedWorkerGlobalScope-onmessage><code>onmessage</code></dfn>
1.9       ihickson 1374: 
                   1375:    <dd>
1.50      ihickson 1376:     <p>Must be invoked whenever a <code
                   1377:      title=event-DedicatedWorkerGlobalScope-message>message</code> event is
                   1378:      targeted at or bubbles through the <code><a
                   1379:      href="#dedicatedworkerglobalscope">DedicatedWorkerGlobalScope</a></code>
                   1380:      object.
1.9       ihickson 1381:   </dl>
                   1382: 
1.50      ihickson 1383:   <h4 id=shared0><span class=secno>2.1.3 </span>Shared workers and the
                   1384:    <code><a
                   1385:    href="#sharedworkerglobalscope">SharedWorkerGlobalScope</a></code>
                   1386:    inteface</h4>
                   1387: 
                   1388:   <pre
                   1389:    class=idl>[NoInterfaceObject] interface <dfn id=sharedworkerglobalscope>SharedWorkerGlobalScope</dfn> : <a href="#workerglobalscope">WorkerGlobalScope</a> {
                   1390:   readonly attribute DOMString <a href="#name" title=dom-SharedWorkerGlobalScope-name>name</a>;
                   1391:            attribute <span>EventListener</span> <a href="#onconnect" title=handler-SharedWorkerGlobalScope-onconnect>onconnect</a>;
                   1392: };</pre>
                   1393: 
                   1394:   <p>Shared workers receive message ports through <code
                   1395:    title=event-WorkerGlobalScope-connect>connect</code> events on their
                   1396:    global object for each connection.
                   1397: 
                   1398:   <p>The <dfn id=name
                   1399:    title=dom-SharedWorkerGlobalScope-name><code>name</code></dfn> attribute
                   1400:    must return the value it was assigned when the <code><a
                   1401:    href="#sharedworkerglobalscope">SharedWorkerGlobalScope</a></code> object
                   1402:    was created by the "<a href="#run-a">run a worker</a>" algorithm. Its
                   1403:    value represents the name that can be used to obtain a reference to the
                   1404:    worker using the <code><a href="#sharedworker">SharedWorker</a></code>
                   1405:    constructor.
                   1406: 
                   1407:   <p>The following are the <span>event handler DOM attributes</span> that
                   1408:    must be supported by objects implementing the <code><a
                   1409:    href="#sharedworkerglobalscope">SharedWorkerGlobalScope</a></code>
                   1410:    interface:
                   1411: 
                   1412:   <dl>
                   1413:    <dt><dfn id=onconnect
                   1414:     title=handler-SharedWorkerGlobalScope-onconnect><code>onconnect</code></dfn>
                   1415: 
                   1416:    <dd>
                   1417:     <p>Must be invoked whenever a <code
                   1418:      title=event-SharedWorkerGlobalScope-connect>connect</code> event is
                   1419:      targeted at or bubbles through the <code><a
                   1420:      href="#sharedworkerglobalscope">SharedWorkerGlobalScope</a></code>
                   1421:      object.
                   1422:   </dl>
1.30      ihickson 1423: 
1.15      ihickson 1424:   <h3 id=base-urls><span class=secno>2.2 </span>Base URLs and origins of
                   1425:    workers</h3>
                   1426: 
                   1427:   <p>The <span>base URL</span> of a <span>URL</span> passed to an API in a
1.34      ihickson 1428:    worker is the <span>absolute URL</span> given that the worker's <code
                   1429:    title=dom-WorkerGlobalScope-location><a
                   1430:    href="#location">location</a></code> attribute represents.
1.15      ihickson 1431: 
1.25      ihickson 1432:   <p>Both the <span>origin</span> and <span>effective script origin</span> of
                   1433:    scripts running in workers are the <span>origin</span> of the
1.34      ihickson 1434:    <span>absolute URL</span> given that the worker's <code
                   1435:    title=dom-WorkerGlobalScope-location><a
                   1436:    href="#location">location</a></code> attribute represents.
1.15      ihickson 1437: 
                   1438:   <h3 id=the-queue><span class=secno>2.3 </span>The queue of events</h3>
1.4       ihickson 1439: 
1.26      ihickson 1440:   <p>Each <code><a href="#workerglobalscope">WorkerGlobalScope</a></code>
                   1441:    object is asssociated with a <dfn id=queue>queue of events</dfn>, which is
                   1442:    initially empty.
1.4       ihickson 1443: 
                   1444:   <p>An event in the queue can be a DOM event or a timeout callback.
                   1445: 
1.8       ihickson 1446:   <p>All asynchronous callbacks and events that would be called or dispatched
                   1447:    in the worker must be added to the worker's queue, with the "<a
                   1448:    href="#run-a">run a worker</a>" processing model below taking care of
                   1449:    actually calling the callbacks or dispatching the events.
                   1450: 
1.50      ihickson 1451:   <p>Each <code><a href="#workerglobalscope">WorkerGlobalScope</a></code>
                   1452:    object also has a <dfn id=closing
                   1453:    title=dom-WorkerGlobalScope-closing>closing</dfn> flag, which must
                   1454:    initially be false, but which can get set to true by the algorithms in the
                   1455:    processing model section below.
                   1456: 
1.26      ihickson 1457:   <p>Once the <code><a
1.50      ihickson 1458:    href="#workerglobalscope">WorkerGlobalScope</a></code>'s <a
                   1459:    href="#closing" title=dom-WorkerGlobalScope-closing>closing</a> flag is
                   1460:    set to true, the queue must discard anything else that would be added to
1.59    ! ihickson 1461:    it (existing already on the queue is unaffected unless otherwise
        !          1462:    specified). Effectively, once the <a href="#closing"
1.50      ihickson 1463:    title=dom-WorkerGlobalScope-closing>closing</a> flag is true, timers stop
                   1464:    firing, notifications for all pending asynchronous operations are dropped,
                   1465:    etc.
1.8       ihickson 1466: 
1.15      ihickson 1467:   <h3 id=the-workers><span class=secno>2.4 </span>The worker's ports</h3>
1.9       ihickson 1468: 
                   1469:   <p>Workers communicate with other workers and with <span title="browsing
                   1470:    context">browsing contexts</span> through <span title="channel
                   1471:    messaging">message channels</span> and their <code>MessagePort</code>
                   1472:    objects.
                   1473: 
1.26      ihickson 1474:   <p>Each <code><a href="#workerglobalscope">WorkerGlobalScope</a></code>
1.50      ihickson 1475:    <var title="">worker global scope</var> has a list of <dfn
                   1476:    id=the-workers0>the worker's ports</dfn>, which consists of all the
                   1477:    <code>MessagePort</code> objects that are entangled with another port and
                   1478:    that have one (but only one) port owned by <var title="">worker global
                   1479:    scope</var>. This list includes all the <code>MessagePort</code> objects
                   1480:    that are in events pending in the <a href="#queue">queue of events</a>, as
                   1481:    well as the implicit <code>MessagePort</code> in the case of <a
                   1482:    href="#dedicatedworkerglobalscope"
                   1483:    title=DedicatedWorkerGlobalScope>dedicated workers</a>.
1.9       ihickson 1484: 
1.17      ihickson 1485:   <hr>
                   1486: 
1.38      ihickson 1487:   <p>A worker is said to be a <dfn id=permissible>permissible worker</dfn> if
                   1488:    either:
                   1489: 
                   1490:   <ul>
                   1491:    <li>at some point past or present a <code>MessagePort</code> owned by the
                   1492:     worker was entangled with a <code>MessagePort</code> <var
                   1493:     title="">p</var> whose owner is a <code>Window</code> object whose
                   1494:     <span>active document</span> is the <code>Document</code> that was that
                   1495:     <span>browsing context</span>'s <span>active document</span> when <var
                   1496:     title="">p</var> was created, and that <code>Document</code> is
                   1497:     <span>fully active</span>, or
                   1498: 
                   1499:    <li>at some point past or present a <code>MessagePort</code> owned by the
                   1500:     worker was entangled with a <code>MessagePort</code> owned by another
                   1501:     worker that is currently a <a href="#permissible">permissible worker</a>.
                   1502:   </ul>
                   1503: 
                   1504:   <hr>
                   1505: 
                   1506:   <p>A worker is said to be a <dfn id=protected>protected worker</dfn> if
                   1507:    either:
                   1508: 
                   1509:   <ul>
                   1510:    <li>it has outstanding timers, database transactions, or network
                   1511:     connections, and is a <a href="#permissible">permissible worker</a>, or:
                   1512: 
                   1513:    <li>there is a <a href="#protected">protected worker</a> that at some
                   1514:     point past or present owned a <code>MessagePort</code> that was entangled
                   1515:     with a <code>MessagePort</code> owned by this worker.
                   1516:   </ul>
                   1517: 
                   1518:   <hr>
1.17      ihickson 1519: 
1.38      ihickson 1520:   <p>A worker is said to be an <dfn id=active>active needed worker</dfn> if
                   1521:    either:
1.17      ihickson 1522: 
                   1523:   <ul>
1.38      ihickson 1524:    <li>the worker is a <a href="#protected">protected worker</a>, or
                   1525: 
                   1526:    <li>at least one of the <a href="#the-workers0">the worker's ports</a> is
                   1527:     entangled with a <code>MessagePort</code> <var title="">p</var> whose
                   1528:     owner is a <code>Window</code> object whose <span>active document</span>
                   1529:     is the <code>Document</code> that was that <span>browsing
                   1530:     context</span>'s <span>active document</span> when that
                   1531:     <code>MessagePort</code> <var title="">p</var> was created, and that
                   1532:     <code>Document</code> is <span>fully active</span>, or
1.17      ihickson 1533: 
                   1534:    <li>at least one of the <a href="#the-workers0">the worker's ports</a> has
1.26      ihickson 1535:     an entangled <code>MessagePort</code> owned by a <code><a
                   1536:     href="#workerglobalscope">WorkerGlobalScope</a></code> object that is
1.38      ihickson 1537:     itself an <a href="#active">active needed worker</a>.
1.17      ihickson 1538:   </ul>
                   1539: 
                   1540:   <hr>
                   1541: 
1.38      ihickson 1542:   <p>A worker is said to be a <dfn id=suspendable>suspendable worker</dfn> if
                   1543:    it is not an <a href="#active">active needed worker</a> but either:
1.17      ihickson 1544: 
                   1545:   <ul>
1.38      ihickson 1546:    <li>at least one of the <a href="#the-workers0">the worker's ports</a> has
                   1547:     an entangled <code>MessagePort</code> owned by a <code>Window</code>
                   1548:     object, or
1.17      ihickson 1549: 
                   1550:    <li>at least one of the <a href="#the-workers0">the worker's ports</a> has
1.26      ihickson 1551:     an entangled <code>MessagePort</code> owned by a <code><a
                   1552:     href="#workerglobalscope">WorkerGlobalScope</a></code> object that is
1.38      ihickson 1553:     itself a <span>needed worker</span>.
1.17      ihickson 1554:   </ul>
                   1555: 
1.15      ihickson 1556:   <h3 id=processing><span class=secno>2.5 </span>Processing model</h3>
1.4       ihickson 1557: 
1.50      ihickson 1558:   <p>When a user agent is to <dfn id=run-a>run a worker</dfn> for a script
                   1559:    with <span>URL</span> <var title="">url</var>, a browsing context <var
                   1560:    title="">owner browsing context</var>, a <code>Document</code> <var
                   1561:    title="">owner document</var>, and with global scope <var title="">worker
1.52      ihickson 1562:    global scope</var>, it must run the following steps:
1.4       ihickson 1563: 
                   1564:   <ol>
                   1565:    <li>
1.52      ihickson 1566:     <p>Create a completely separate and parallel execution environment (i.e.
                   1567:      a separate thread or process or equivalent construct), and run the rest
                   1568:      of these steps asychronously in that context.</p>
                   1569: 
                   1570:    <li>
1.7       ihickson 1571:     <p>Attempt to <span>fetch</span><!-- XXX --> the resource identified by
                   1572:      <var title="">url</var>.</p>
                   1573: 
1.50      ihickson 1574:     <p>If the attempt fails, then, at the next available opportunity, after
                   1575:      any scripts have finished executing<!-- XXX queue -->, <span>fire a
                   1576:      simple event</span> called <code title=event-error>error</code> at all
                   1577:      <code><a href="#worker1">Worker</a></code> or <code><a
                   1578:      href="#sharedworker">SharedWorker</a></code> objects associated with
                   1579:      <var title="">worker global scope</var>. Abort these steps.</p>
1.7       ihickson 1580: 
                   1581:     <p>If the attempt succeeds, then let <var title="">script</var> be the
                   1582:      resource that was obtained.</p>
                   1583: 
                   1584:     <p class=note>As with <code>script</code> elements, the MIME type of the
                   1585:      script is ignored. Unlike with <code>script</code> elements, there is no
                   1586:      way to override the type. It's always assumed to be JavaScript.</p>
                   1587:     <!-- XXX people will complain about
                   1588:     this. I guess we might want to examine the MIME type... -->
                   1589:     
                   1590: 
                   1591:    <li>
1.34      ihickson 1592:     <p>Create a new <code><a href="#workerlocation">WorkerLocation</a></code>
                   1593:      object for the <code title=dom-WorkerGlobalScope-location><a
1.50      ihickson 1594:      href="#location">location</a></code> attribute of <var title="">worker
                   1595:      global scope</var>, representing <var title="">url</var>.</p>
1.34      ihickson 1596: 
                   1597:    <li>
1.4       ihickson 1598:     <p>Let <var title="">script</var>'s <span>script execution context</span>
1.50      ihickson 1599:      (and thus also <span>global object</span>) be <var title="">worker
                   1600:      global scope</var>.</p>
1.4       ihickson 1601: 
                   1602:    <li>
                   1603:     <p>Let <var title="">script</var>'s <span>script browsing context</span>
                   1604:      be <var title="">owner browsing context</var>.</p>
                   1605: 
                   1606:    <li>
                   1607:     <p>Let <var title="">script</var>'s <span>script document context</span>
                   1608:      be <var title="">owner document</var>.</p>
                   1609: 
                   1610:    <li>
1.50      ihickson 1611:     <p><strong>Closing orphan workers</strong>: Start monitoring the worker
                   1612:      such that as soon as it stops being either an <a href="#active">active
                   1613:      needed worker</a> or a <a href="#suspendable">suspendable worker</a>,
                   1614:      the <var title="">worker global scope</var>'s <a href="#closing"
                   1615:      title=dom-WorkerGlobalScope-closing>closing</a> flag is set to true and
                   1616:      an event named <code title=event-close>close</code>, which uses the
1.44      ihickson 1617:      <code>Event</code> object, which does not bubble, and which is not
1.50      ihickson 1618:      cancelable, is added it to <var title="">worker global scope</var>'s
                   1619:      <code><a href="#workerglobalscope">WorkerGlobalScope</a></code> object's
                   1620:      <a href="#queue">queue of events</a>, targetted at the <var
                   1621:      title="">worker global scope</var> itself.</p>
1.9       ihickson 1622: 
                   1623:    <li>
1.50      ihickson 1624:     <p><strong>Suspending workers</strong>: Start monitoring the worker, such
                   1625:      that whenever the <var title="">worker global scope</var>'s <a
                   1626:      href="#closing" title=dom-WorkerGlobalScope-closing>closing</a> flag is
                   1627:      false and the worker is a <a href="#suspendable">suspendable worker</a>,
                   1628:      the user agent suspends execution of script in that worker until such
                   1629:      time as either the <a href="#closing"
                   1630:      title=dom-WorkerGlobalScope-closing>closing</a> flag switches to true or
                   1631:      the worker stops being a <a href="#suspendable">suspendable worker</a>.</p>
1.7       ihickson 1632: 
                   1633:    <li>
                   1634:     <p>Run <var title="">script</var> until it either returns, fails to catch
                   1635:      an exception, or gets prematurely aborted by the "<a href="#kill-a">kill
1.50      ihickson 1636:      a worker</a>" or "<a href="#terminate">terminate a worker</a>"
                   1637:      algorithms defined below.</p>
1.7       ihickson 1638: 
                   1639:     <p class=note>If the script gets aborted by the "<a href="#kill-a">kill a
                   1640:      worker</a>" algorithm, then that same algorithm will cause there to only
                   1641:      be a single event in the <a href="#queue">queue of events</a> at the
1.50      ihickson 1642:      next step, namely the <code title=message-close>close</code> event. The
                   1643:      "<a href="#terminate">terminate a worker</a>" algorithm removes all the
                   1644:      events.</p>
1.4       ihickson 1645: 
                   1646:    <li>
1.9       ihickson 1647:     <p><i>Event loop</i>: Wait until either there is an event in the <a
1.50      ihickson 1648:      href="#queue">queue of events</a> associated with <var title="">worker
                   1649:      global scope</var> or the <var title="">worker global scope</var>'s <a
                   1650:      href="#closing" title=dom-WorkerGlobalScope-closing>closing</a> flag is
                   1651:      set to true.</p>
1.4       ihickson 1652: 
                   1653:    <li>
                   1654:     <p>Dispatch the oldest event or callback in the <a href="#queue">queue of
1.9       ihickson 1655:      events</a>, if any. The handling of this event or the execution of this
                   1656:      callback might get prematurely aborted by the "<a href="#kill-a">kill a
1.50      ihickson 1657:      worker</a>" or "<a href="#terminate">terminate a worker</a>" algorithms
                   1658:      defined below.</p>
1.4       ihickson 1659: 
                   1660:    <li>
                   1661:     <p>If there are any more events in the <a href="#queue">queue of
1.50      ihickson 1662:      events</a> or if the <var title="">worker global scope</var>'s <a
                   1663:      href="#closing" title=dom-WorkerGlobalScope-closing>closing</a> flag is
                   1664:      set to false, then jump back to the step above labeled <i>event
                   1665:      loop</i>.</p>
1.4       ihickson 1666: 
                   1667:    <li>
                   1668:     <p class=big-issue>timers, intervals, XMLHttpRequests, database
1.28      ihickson 1669:      transactions, etc, must be killed; ports must be unentangled</p>
1.43      ihickson 1670: 
                   1671:    <li>
                   1672:     <p>At the next available opportunity, after any scripts have finished
                   1673:      executing<!-- XXX queue -->, <span>fire a simple event</span> called
1.50      ihickson 1674:      <code title=event-close>close</code> at all <code><a
                   1675:      href="#worker1">Worker</a></code> or <code><a
                   1676:      href="#sharedworker">SharedWorker</a></code> objects associated with
                   1677:      this worker.</p>
1.4       ihickson 1678:   </ol>
                   1679: 
                   1680:   <hr>
                   1681: 
1.50      ihickson 1682:   <p>When a user agent is to <dfn id=kill-a>kill a worker</dfn> it must run
1.4       ihickson 1683:    the following steps in parallel with the worker's main loop (the "<a
                   1684:    href="#run-a">run a worker</a>" processing model defined above):
                   1685: 
                   1686:   <ol>
                   1687:    <li>
                   1688:     <p>Create an <code>Event</code> object with the event name <code
1.50      ihickson 1689:      title=event-close>close</code>, which does not bubble and is not
1.4       ihickson 1690:      cancelable, and add it to the worker's <code><a
1.26      ihickson 1691:      href="#workerglobalscope">WorkerGlobalScope</a></code> object's <a
1.8       ihickson 1692:      href="#queue">queue of events</a>, targetted at the <code><a
1.26      ihickson 1693:      href="#workerglobalscope">WorkerGlobalScope</a></code> object itself.
1.28      ihickson 1694:    </li>
                   1695:    <!-- XXX shouldn't add one if closing is
1.50      ihickson 1696:    already true, assuming close has already been added to the queue
1.28      ihickson 1697:    (?) -->
1.4       ihickson 1698: 
                   1699:    <li>
1.26      ihickson 1700:     <p>Set the worker's <code><a
1.50      ihickson 1701:      href="#workerglobalscope">WorkerGlobalScope</a></code> object's <a
                   1702:      href="#closing" title=dom-WorkerGlobalScope-closing>closing</a> flag to
                   1703:      true.
1.8       ihickson 1704: 
                   1705:    <li>
                   1706:     <p>Wait a user-agent-defined amount of time. If the "<a href="#run-a">run
                   1707:      a worker</a>" processing model defined above immediately starts running
1.50      ihickson 1708:      event listeners registered for the <code title=event-close>close</code>
                   1709:      event, this time should not be zero &mdash; the idea is that the <code
                   1710:      title=event-close>close</code> event can be used to clean up when
                   1711:      shutting down unexpectedly.
1.4       ihickson 1712: 
                   1713:    <li>
                   1714:     <p>If there are any events in the <a href="#queue">queue of events</a>
1.50      ihickson 1715:      other than the <code title=event-close>close</code> event that this
1.4       ihickson 1716:      algorithm just added, discard them without dispatching them.
                   1717: 
                   1718:    <li>
1.50      ihickson 1719:     <p>If the <code title=event-close>close</code> event that this algorithm
                   1720:      just added hasn't yet been dispatched, then abort the script currently
                   1721:      running in the worker.
1.4       ihickson 1722: 
                   1723:    <li>
                   1724:     <p>Wait a user-agent-defined amount of time.
                   1725: 
                   1726:    <li>
                   1727:     <p>Abort the script currently running in the worker (if any script is
                   1728:      running, then it will be a handler for the <code
1.50      ihickson 1729:      title=event-close>close</code> event).
1.4       ihickson 1730:   </ol>
                   1731: 
1.19      ihickson 1732:   <p>User agents may invoke the "<a href="#kill-a">kill a worker</a>"
                   1733:    processing model on a worker at any time, e.g. in response to user
                   1734:    requests, in response to CPU quota management, or when a worker stops
1.38      ihickson 1735:    being an <a href="#active">active needed worker</a> if the worker
1.50      ihickson 1736:    continues executing even after its <a href="#closing"
                   1737:    title=dom-WorkerGlobalScope-closing>closing</a> flag was set to true.
1.19      ihickson 1738: 
1.8       ihickson 1739:   <hr>
                   1740: 
1.50      ihickson 1741:   <p>When a user agent is to <dfn id=terminate>terminate a worker</dfn> it
                   1742:    must run the following steps in parallel with the worker's main loop (the
                   1743:    "<a href="#run-a">run a worker</a>" processing model defined above):
1.8       ihickson 1744: 
                   1745:   <ol>
                   1746:    <li>
1.50      ihickson 1747:     <p>Set the worker's <code><a
1.26      ihickson 1748:      href="#workerglobalscope">WorkerGlobalScope</a></code> object's <a
1.50      ihickson 1749:      href="#closing" title=dom-WorkerGlobalScope-closing>closing</a> flag to
                   1750:      true.
1.8       ihickson 1751: 
                   1752:    <li>
1.50      ihickson 1753:     <p>If there are any events in the <a href="#queue">queue of events</a>
                   1754:      other than the <code title=event-close>close</code> event that this
                   1755:      algorithm just added, discard them without dispatching them.
1.8       ihickson 1756: 
                   1757:    <li>
1.50      ihickson 1758:     <p>Abort the script currently running in the worker.
1.8       ihickson 1759:   </ol>
                   1760: 
1.15      ihickson 1761:   <h3 id=creating><span class=secno>2.6 </span>Creating workers</h3>
1.5       ihickson 1762: 
1.50      ihickson 1763:   <h4 id=the-abstractworker><span class=secno>2.6.1 </span>The <code><a
                   1764:    href="#abstractworker">AbstractWorker</a></code> abstract interface</h4>
                   1765: 
1.5       ihickson 1766:   <pre
1.50      ihickson 1767:    class=idl>[NoInterfaceObject] interface <dfn id=abstractworker>AbstractWorker</dfn> {
                   1768:            attribute <span>EventListener</span> <a href="#onerror" title=handler-AbstractWorker-onerror>onerror</a>;
                   1769:            attribute <span>EventListener</span> <a href="#onclose0" title=handler-AbstractWorker-onclose>onclose</a>;
                   1770: };</pre>
                   1771: 
                   1772:   <p>The following are the <span>event handler DOM attributes</span> that
                   1773:    must be supported by objects implementing the <code><a
                   1774:    href="#abstractworker">AbstractWorker</a></code> interface:
                   1775: 
                   1776:   <dl>
                   1777:    <dt><dfn id=onerror
                   1778:     title=handler-AbstractWorker-onerror><code>onerror</code></dfn>
                   1779: 
                   1780:    <dd>
                   1781:     <p>Must be invoked whenever an <code title=event-error>error</code> event
                   1782:      is targeted at or bubbles through the <code><a
                   1783:      href="#abstractworker">AbstractWorker</a></code> object.
                   1784: 
                   1785:    <dt><dfn id=onclose0
                   1786:     title=handler-AbstractWorker-onclose><code>onclose</code></dfn>
                   1787: 
                   1788:    <dd>
                   1789:     <p>Must be invoked whenever an <code title=event-close>close</code> event
                   1790:      is targeted at or bubbles through the <code><a
                   1791:      href="#abstractworker">AbstractWorker</a></code> object.
                   1792:   </dl>
1.43      ihickson 1793: 
1.50      ihickson 1794:   <h4 id=dedicated0><span class=secno>2.6.2 </span>Dedicated workers and the
                   1795:    <code><a href="#worker1">Worker</a></code> interface</h4>
1.43      ihickson 1796: 
1.50      ihickson 1797:   <pre class=idl>[NoInterfaceObject,
                   1798:  <a href="#worker2" title=dom-Worker>Constructor</a>(in DOMString scriptURL)]
                   1799: interface <dfn id=worker1>Worker</dfn> : <a href="#abstractworker">AbstractWorker</a> {
1.56      ihickson 1800:   void <a href="#terminate0" title=dom-Worker-terminate>terminate</a>();
1.50      ihickson 1801: 
1.51      ihickson 1802:   void <a href="#postmessage0" title=dom-Worker-postMessage>postMessage</a>(in DOMString message);
                   1803:   void <a href="#postmessage0" title=dom-Worker-postMessage>postMessage</a>(in DOMString message, in <span>MessagePort</span> messagePort);
1.50      ihickson 1804:   <span>MessagePort</span> <a href="#startconversation0" title=dom-Worker-startConversation>startConversation</a>(in DOMString message);
                   1805:            attribute <span>EventListener</span> <a href="#onmessage0" title=handler-Worker-onmessage>onmessage</a>;
1.5       ihickson 1806: };</pre>
                   1807: 
1.56      ihickson 1808:   <p>The <dfn id=terminate0
                   1809:    title=dom-Worker-terminate><code>terminate()</code></dfn> method, when
                   1810:    invoked, must cause the "<a href="#terminate">terminate a worker</a>"
                   1811:    algorithm to be run on the worker with with the object is associated.
1.50      ihickson 1812: 
                   1813:   <p><code><a href="#worker1">Worker</a></code> objects act as if they had an
                   1814:    implicit <code>MessagePort</code> associated with them. This port is part
                   1815:    of a channel that is set up when the worker is created, but it is not
                   1816:    exposed. This object must never be garbage collected before the <code><a
                   1817:    href="#worker1">Worker</a></code> object.
                   1818: 
                   1819:   <p>All messages received by that port must immediately be retargetted at
                   1820:    the <code><a href="#worker1">Worker</a></code> object.
                   1821: 
                   1822:   <p>The <dfn id=postmessage0
                   1823:    title=dom-Worker-postMessage><code>postMessage()</code></dfn> and <dfn
                   1824:    id=startconversation0
                   1825:    title=dom-Worker-startConversation><code>startConversation()</code></dfn>
                   1826:    methods on <code><a href="#worker1">Worker</a></code> objects must act as
                   1827:    if, when invoked, they immediately invoked the method of the same name on
1.51      ihickson 1828:    the port, with the same arguments, and returned the same return value.
1.50      ihickson 1829: 
                   1830:   <p>The following are the <span>event handler DOM attributes</span> that
                   1831:    must be supported by objects implementing the <code><a
                   1832:    href="#worker1">Worker</a></code> interface:
                   1833: 
                   1834:   <dl>
                   1835:    <dt><dfn id=onmessage0
                   1836:     title=handler-Worker-onmessage><code>onmessage</code></dfn>
                   1837: 
                   1838:    <dd>
                   1839:     <p>Must be invoked whenever a <code
                   1840:      title=event-Worker-message>message</code> event is targeted at or
                   1841:      bubbles through the <code><a href="#worker1">Worker</a></code> object.
                   1842:   </dl>
1.5       ihickson 1843: 
1.9       ihickson 1844:   <hr>
                   1845: 
1.50      ihickson 1846:   <p>When the <dfn id=worker2 title=dom-Worker><code>Worker(<var
                   1847:    title="">scriptURL</var>)</code></dfn> constructor is invoked, the user
                   1848:    agent must run the following steps:
1.9       ihickson 1849: 
                   1850:   <ol>
                   1851:    <li>
                   1852:     <p><span title="resolve a url">Resolve</span> the <var
                   1853:      title="">scriptURL</var> argument.
                   1854: 
                   1855:    <li>
                   1856:     <p>If this fails, throw a <code>SYNTAX_ERR</code> exception.
                   1857: 
                   1858:    <li>
                   1859:     <p>If the <span>origin</span> of the resulting <span>absolute URL</span>
                   1860:      is not the <span title="same origin">same</span> as the origin of the
1.50      ihickson 1861:      script that invoked the constructor, then throw a <span>security
1.9       ihickson 1862:      exception</span>.
                   1863: 
                   1864:    <li>
1.50      ihickson 1865:     <p><span>Create a new <code><a
                   1866:      href="#dedicatedworkerglobalscope">DedicatedWorkerGlobalScope</a></code>
                   1867:      object</span>. Let this be the <var title="">worker global scope</var>.
                   1868: 
                   1869:    <li>
                   1870:     <p>Create a new <code><a href="#worker1">Worker</a></code> object,
                   1871:      associated with <var title="">worker global scope</var>. Let this
                   1872:      <code><a href="#worker1">Worker</a></code> object be <var
                   1873:      title="">worker</var>.
1.9       ihickson 1874: 
                   1875:    <li>
1.50      ihickson 1876:     <p><span>Create a <code>MessagePort</code> object</span> owned by the
                   1877:      <span>script execution context</span> of the script that invoked the
                   1878:      method. Let this be the <var title="">outside port</var>.
                   1879: 
                   1880:    <li>
                   1881:     <p>Associate the <var title="">outside port</var> with <var
                   1882:      title="">worker</var>.
                   1883: 
                   1884:    <li>
                   1885:     <p><span>Create a <code>MessagePort</code> object</span> owned by the
                   1886:      <var title="">worker global scope</var>. Let this be the <var
                   1887:      title="">inside port</var>.
                   1888: 
                   1889:    <li>
                   1890:     <p>Associate the <var title="">inside port</var> with <var
                   1891:      title="">worker global scope</var>.
                   1892: 
                   1893:    <li>
                   1894:     <p><span>Entangle</span> <var title="">outside port</var> and <var
                   1895:      title="">inside port</var>.
                   1896: 
                   1897:    <li>
                   1898:     <p>Return <var title="">worker</var>, and run the following steps
                   1899:      asynchronously.
                   1900: 
                   1901:    <li>
                   1902:     <p>Open <var title="">inside port</var>'s <span>port message
                   1903:      queue</span>.
                   1904: 
                   1905:    <li>
1.51      ihickson 1906:     <p>Open <var title="">outside port</var>'s <span>port message
                   1907:      queue</span>.
                   1908: 
                   1909:    <li>
1.52      ihickson 1910:     <p><a href="#run-a">Run a worker</a>, with the <span>script browsing
                   1911:      context</span> of the script that invoked the method as the <var
                   1912:      title="">owner browsing context</var>, with the <span>script document
                   1913:      context</span> of the script that invoked the method as the <var
                   1914:      title="">owner document</var>, and with <var title="">worker global
                   1915:      scope</var> as the global scope.</p>
1.9       ihickson 1916:   </ol>
                   1917: 
1.50      ihickson 1918:   <h4 id=shared1><span class=secno>2.6.3 </span>Shared workers and the
                   1919:    <code><a href="#sharedworker">SharedWorker</a></code> interface</h4>
1.9       ihickson 1920: 
1.50      ihickson 1921:   <pre class=idl>[NoInterfaceObject,
                   1922:  <a href="#sharedworker0" title=dom-SharedWorker>Constructor</a>(in DOMString scriptURL, in DOMString name)]
                   1923: interface <dfn id=sharedworker>SharedWorker</dfn> : <a href="#abstractworker">AbstractWorker</a> {
                   1924:   readonly attribute <code>MessagePort</code> <a href="#port" title=dom-SharedWorker-port>port</a>;
                   1925: };</pre>
                   1926: 
                   1927:   <p>The <dfn id=port title=dom-SharedWorker-port><code>port</code></dfn>
                   1928:    attribute must return the value it was assigned by the object's
                   1929:    constructor. It represents the <code>MessagePort</code> for communicating
                   1930:    with the shared worker.
                   1931: 
                   1932:   <p>When the <dfn id=sharedworker0
                   1933:    title=dom-SharedWorker><code>SharedWorker(<var title="">scriptURL</var>,
                   1934:    <var title="">name</var>)</code></dfn> constructor is invoked, the user
                   1935:    agent must run the following steps:
1.9       ihickson 1936: 
                   1937:   <ol>
                   1938:    <li>
                   1939:     <p><span title="resolve a url">Resolve</span> the <var
                   1940:      title="">scriptURL</var> argument.
1.4       ihickson 1941: 
1.9       ihickson 1942:    <li>
                   1943:     <p>If this fails, throw a <code>SYNTAX_ERR</code> exception.
                   1944: 
                   1945:    <li>
                   1946:     <p>If the <span>origin</span> of the resulting <span>absolute URL</span>
                   1947:      is not the <span title="same origin">same</span> as the origin of the
1.50      ihickson 1948:      script that invoked the constructor, then throw a <span>security
1.9       ihickson 1949:      exception</span>.
                   1950: 
                   1951:    <li>
1.50      ihickson 1952:     <p>Execute the following substeps atomically:</p>
1.9       ihickson 1953: 
                   1954:     <ol>
                   1955:      <li>
1.50      ihickson 1956:       <p>Create a new <code><a href="#sharedworker">SharedWorker</a></code>
                   1957:        object, which will shortly be associated with a <code><a
                   1958:        href="#sharedworkerglobalscope">SharedWorkerGlobalScope</a></code>
                   1959:        object. Let this <code><a href="#sharedworker">SharedWorker</a></code>
                   1960:        object be <var title="">worker</var>.
1.9       ihickson 1961: 
                   1962:      <li>
1.50      ihickson 1963:       <p><span>Create a <code>MessagePort</code> object</span> owned by the
                   1964:        <span>script execution context</span> of the script that invoked the
                   1965:        method. Let this be the <var title="">outside port</var>.
1.9       ihickson 1966: 
                   1967:      <li>
1.50      ihickson 1968:       <p>Assign <var title="">outside port</var> to the <code
                   1969:        title=dom-SharedWorker-port><a href="#port">port</a></code> attribute
                   1970:        of <var title="">worker</var>.
1.43      ihickson 1971: 
                   1972:      <li>
1.50      ihickson 1973:       <p>If there exists a <code><a
                   1974:        href="#sharedworkerglobalscope">SharedWorkerGlobalScope</a></code>
                   1975:        object whose <a href="#closing"
                   1976:        title=dom-WorkerGlobalScope-closing>closing</a> flag is false, whose
                   1977:        <code title=dom-WorkerGlobalScope-name>name</code> attribute is
                   1978:        exactly equal to the <var title="">name</var> argument, and whose
                   1979:        <code title=dom-WorkerGlobalScope-location><a
                   1980:        href="#location">location</a></code> attribute represents an
                   1981:        <span>absolute URL</span> that has the <span>same origin</span> as the
                   1982:        resulting <span>absolute URL</span>, then run these substeps:</p>
                   1983: 
                   1984:       <ol>
                   1985:        <li>
                   1986:         <p>Let <var title="">worker global scope</var> be that <code><a
                   1987:          href="#sharedworkerglobalscope">SharedWorkerGlobalScope</a></code>
                   1988:          object.
                   1989: 
                   1990:        <li>
                   1991:         <p>If <var title="">worker global scope</var>'s <code
                   1992:          title=dom-WorkerGlobalScope-location><a
                   1993:          href="#location">location</a></code> attribute represents an
                   1994:          <span>absolute URL</span> that is not exactly equal to the resulting
                   1995:          <span>absolute URL</span>, then throw a
                   1996:          <code>URL_MISMATCH_ERR</code> exception and abort all these steps.
                   1997:          <span class=big-issue>code 21</span>
                   1998: 
                   1999:        <li>
                   2000:         <p>Associate <var title="">worker</var> with <var title="">worker
                   2001:          global scope</var>.
                   2002: 
                   2003:        <li>
                   2004:         <p><span>Create a <code>MessagePort</code> object</span> owned by the
                   2005:          <var title="">worker global scope</var>. Let this be the <var
                   2006:          title="">inside port</var>.
                   2007: 
                   2008:        <li>
                   2009:         <p><span>Entangle</span> <var title="">outside port</var> and <var
                   2010:          title="">inside port</var>.
                   2011: 
                   2012:        <li>
                   2013:         <p>Return <var title="">worker</var> and perform the next step
                   2014:          asynchronously.
                   2015: 
                   2016:        <li>
                   2017:         <p>Create an event that uses the <code>MessageEvent</code> interface,
                   2018:          with the name <code title=event-connect>connect</code>, which does
                   2019:          not bubble, is cancelable, has no default action, has a <code
                   2020:          title=dom-MessageEvent-data>data</code> attribute whose value is the
                   2021:          empty string and has a <code
                   2022:          title=dom-MessageEvent-messagePort>messagePort</code> attribute
                   2023:          whose value is the newly created port, and add it to <var
                   2024:          title="">worker global scope</var>'s <a href="#queue">queue of
                   2025:          events</a>, targetted at the <var title="">worker global scope</var>
                   2026:          itself.
                   2027: 
                   2028:        <li>
                   2029:         <p>Abort all these steps.
                   2030:       </ol>
1.9       ihickson 2031: 
                   2032:      <li>
1.50      ihickson 2033:       <p><span>Create a new <code><a
                   2034:        href="#sharedworkerglobalscope">SharedWorkerGlobalScope</a></code>
                   2035:        object</span>. Let this be the <var title="">worker global
                   2036:        scope</var>.
1.9       ihickson 2037: 
1.50      ihickson 2038:      <li>
                   2039:       <p>Associate <var title="">worker</var> with <var title="">worker
                   2040:        global scope</var>.
1.9       ihickson 2041: 
1.50      ihickson 2042:      <li>
                   2043:       <p>Set the <code title=dom-SharedWorkerGlobalScope-name><a
                   2044:        href="#name">name</a></code> attribute of <var title="">worker global
                   2045:        scope</var> be <var title="">name</var>.
1.9       ihickson 2046: 
1.50      ihickson 2047:      <li>
                   2048:       <p><span>Create a <code>MessagePort</code> object</span> owned by the
                   2049:        <var title="">worker global scope</var>. Let this be the <var
                   2050:        title="">inside port</var>.
1.9       ihickson 2051: 
1.50      ihickson 2052:      <li>
                   2053:       <p><span>Entangle</span> <var title="">outside port</var> and <var
                   2054:        title="">inside port</var>.
                   2055:     </ol>
1.9       ihickson 2056: 
                   2057:    <li>
1.50      ihickson 2058:     <p>Return <var title="">worker</var> and perform the next step
                   2059:      asynchronously.
1.9       ihickson 2060: 
                   2061:    <li>
                   2062:     <p>Create an event that uses the <code>MessageEvent</code> interface,
1.20      ihickson 2063:      with the name <code title=event-connect>connect</code>, which does not
1.9       ihickson 2064:      bubble, is cancelable, has no default action, has a <code
                   2065:      title=dom-MessageEvent-data>data</code> attribute whose value is the
                   2066:      empty string and has a <code
                   2067:      title=dom-MessageEvent-messagePort>messagePort</code> attribute whose
1.50      ihickson 2068:      value is the newly created port, and add it to <var title="">worker
                   2069:      global scope</var>'s <a href="#queue">queue of events</a>, targetted at
                   2070:      the <var title="">worker global scope</var> itself.
1.28      ihickson 2071: 
                   2072:    <li>
1.52      ihickson 2073:     <p><a href="#run-a">Run a worker</a>, with the <span>script browsing
                   2074:      context</span> of the script that invoked the method as the <var
                   2075:      title="">owner browsing context</var>, with the <span>script document
                   2076:      context</span> of the script that invoked the method as the <var
                   2077:      title="">owner document</var>, and with <var title="">worker global
                   2078:      scope</var> as the global scope.</p>
1.9       ihickson 2079:   </ol>
1.7       ihickson 2080: 
1.12      ihickson 2081:   <h2 id=apis-available><span class=secno>3. </span>APIs available to workers</h2>
                   2082: 
1.26      ihickson 2083:   <pre
                   2084:    class=idl>[NoInterfaceObject] interface <dfn id=workerutils>WorkerUtils</dfn> {
1.46      ihickson 2085:   void <a href="#importscripts" title=dom-WorkerGlobalScope-importScripts>importScripts</a>([Variadic] in DOMString urls);
1.26      ihickson 2086:   readonly attribute <span>Storage</span> <a href="#localstorage" title=dom-localStorage>localStorage</a>;
                   2087:   <span>Database</span> <a href="#opendatabase" title=dom-opendatabase>openDatabase</a>(in DOMString name, in DOMString version, in DOMString displayName, in unsigned long estimatedSize);
                   2088:   void <a href="#shownotification" title=dom-showNotification>showNotification</a>(in DOMString title, in DOMString subtitle, in DOMString description);
                   2089:   void <a href="#shownotification" title=dom-showNotification>showNotification</a>(in DOMString title, in DOMString subtitle, in DOMString description, in VoidCallback onclick);
                   2090: };</pre>
1.18      ihickson 2091: 
1.12      ihickson 2092:   <p>Objects that implement the <code><a
1.42      ihickson 2093:    href="#workerglobalscope">WorkerGlobalScope</a></code> interface must also
                   2094:    implement the <code><a href="#workerutils">WorkerUtils</a></code>
                   2095:    interface.
1.12      ihickson 2096: 
1.23      ihickson 2097:   <p class=big-issue>Need to define a sync database API.
                   2098: 
                   2099:   <p class=big-issue>May need to define a browser sniffing API (like
                   2100:    window.navigator).</p>
1.18      ihickson 2101:   <!-- XXX ApplicationCache -->
                   2102:   <!-- XXX a way to set cookies on the URL for the script -->
1.24      ihickson 2103:   <!-- XXX debugging: void log(in DOMString s); // log to console -->
                   2104:   <!-- XXX debugging: onerror -->
1.13      ihickson 2105: 
1.18      ihickson 2106:   <hr>
1.13      ihickson 2107: 
1.18      ihickson 2108:   <p>The DOM APIs (<code>Node</code> objects, <code>Document</code> objects,
                   2109:    etc) are not available to workers in this version of this specification.
1.13      ihickson 2110: 
1.26      ihickson 2111:   <h3 id=importing><span class=secno>3.1 </span>Importing scripts and
                   2112:    libraries</h3>
                   2113: 
1.45      ihickson 2114:   <p>When a script invokes the <dfn id=importscripts
                   2115:    title=dom-WorkerGlobalScope-importScripts><code>importScripts(<var
                   2116:    title="">urls</var>)</code></dfn> method on a <code><a
1.26      ihickson 2117:    href="#workerglobalscope">WorkerGlobalScope</a></code> object, the user
                   2118:    agent must run the following steps:
                   2119: 
                   2120:   <ol>
                   2121:    <li>
1.46      ihickson 2122:     <p>If there are no arguments, return without doing anything. Abort these
                   2123:      steps.
                   2124: 
                   2125:    <li>
1.45      ihickson 2126:     <p><span title="resolve a url">Resolve</span> each argument.
1.26      ihickson 2127: 
                   2128:    <li>
1.45      ihickson 2129:     <p>If any fail, throw a <code>SYNTAX_ERR</code> exception.
                   2130: 
                   2131:    <li>
                   2132:     <p>If any of the resulting <span title="absolute URL">absolute
                   2133:      URLs</span> have an <span>origin</span> that is not the <span
                   2134:      title="same origin">same</span> as the origin of the script that invoked
                   2135:      the method, then throw a <span>security exception</span>.
1.26      ihickson 2136: 
                   2137:    <li>
1.45      ihickson 2138:     <p>Attempt to <span>fetch</span> each resource identified by the
                   2139:      resulting <span title="absolute URLs">absolute URL</span>.</p>
1.26      ihickson 2140: 
                   2141:    <li>
1.45      ihickson 2142:     <p>For each argument in turn, in the order given, starting with the first
                   2143:      one, run these substeps:</p>
1.26      ihickson 2144: 
1.45      ihickson 2145:     <ol>
                   2146:      <li>
                   2147:       <p>Wait for the fetching attempt for the corresponding resource to
                   2148:        complete.</p>
1.26      ihickson 2149: 
1.46      ihickson 2150:       <p>If the fetching attempt failed, throw a <code>NETWORK_ERR</code>
1.48      ihickson 2151:        exception and abort all these steps. <a
                   2152:        href="#refsXHR">[XHR]</a><!-- XXX get DOM Core updated instead
                   2153:       --></p>
1.26      ihickson 2154: 
1.45      ihickson 2155:       <p>If the fetching attempt succeeded, then let <var
                   2156:        title="">script</var> be the resource that was obtained.</p>
1.26      ihickson 2157: 
1.45      ihickson 2158:       <p class=note>As with the worker's script, the script here is always
                   2159:        assumed to be JavaScript, regardless of the MIME type.</p>
                   2160:       <!-- XXX -->
1.26      ihickson 2161: 
1.45      ihickson 2162:      <li>
                   2163:       <p>Let <var title="">script</var>'s <span>script execution
                   2164:        context</span>, <span>script browsing context</span>, and <span>script
                   2165:        document context</span> be the same as for the script that was
                   2166:        executed by the <a href="#run-a">run a worker</a> processing model for
                   2167:        this worker.</p>
1.26      ihickson 2168: 
1.45      ihickson 2169:      <li>
                   2170:       <p>Run <var title="">script</var> until it either returns, fails to
                   2171:        catch an exception, or gets prematurely aborted by the "<a
1.50      ihickson 2172:        href="#kill-a">kill a worker</a>" or "<a href="#terminate">terminate a
                   2173:        worker</a>" algorithms defined above.</p>
1.45      ihickson 2174: 
                   2175:       <p>If an exception was raised or if the script was prematurely aborted,
                   2176:        then abort all these steps, letting the exception or aborting continue
                   2177:        to be processed by the script that called the <code
                   2178:        title=dom-WorkerGlobalScope-importScripts><a
                   2179:        href="#importscripts">importScripts()</a></code> method.</p>
                   2180: 
1.50      ihickson 2181:       <p>If the "<a href="#kill-a">kill a worker</a>" or "<a
1.59    ! ihickson 2182:        href="#terminate">terminate a worker</a>" algorithms abort the script
1.50      ihickson 2183:        then abort all these steps.</p>
1.45      ihickson 2184:     </ol>
1.26      ihickson 2185:   </ol>
                   2186: 
                   2187:   <h3 id=apis-defined><span class=secno>3.2 </span>APIs defined in other
                   2188:    specifications</h3>
                   2189: 
1.27      ihickson 2190:   <p>The <dfn id=localstorage
1.26      ihickson 2191:    title=dom-localStorage><code>localStorage</code></dfn>, <dfn
                   2192:    id=opendatabase title=dom-opendatabase><code>openDatabase()</code></dfn>
                   2193:    must act as defined for the APIs with the same names on the
                   2194:    <code>Window</code> object in the HTML5 specification, with the exception
                   2195:    that where the API would use the <span>origin</span> of the <span>active
                   2196:    document</span> of the <span>browsing context</span> of the
                   2197:    <code>Window</code> object on which the method was supposedly invoked, it
                   2198:    must instead use the <span>origin</span> of the script that invoked the
                   2199:    method. <a href="#refsHTML5">[HTML5]</a>
                   2200: 
                   2201:   <p>The <dfn id=shownotification
                   2202:    title=dom-showNotification><code>showNotification()</code></dfn> methods
                   2203:    must act as defined for the APIs with the same names on the
                   2204:    <code>Window</code> object in the HTML5 specification. <a
                   2205:    href="#refsHTML5">[HTML5]</a>
                   2206: 
                   2207:   <h3 id=interface><span class=secno>3.3 </span>Interface objects and
                   2208:    constructors</h3>
                   2209: 
                   2210:   <p>There must be no interface objects and constructors available in the
                   2211:    global scope of scripts whose <span>script execution context</span> is a
                   2212:    <code><a href="#workerglobalscope">WorkerGlobalScope</a></code> object
                   2213:    except for the following:
                   2214: 
                   2215:   <ul>
                   2216:    <li>
                   2217:     <p><code>XMLHttpRequest</code> and all interface objects and constructors
                   2218:      defined by the XMLHttpRequest specifications, except that the
                   2219:      <span>document response entity body</span> must always be null. <a
                   2220:      href="#refsXHR">[XHR]</a>
                   2221: 
                   2222:    <li>
                   2223:     <p>The <code>WebSocket</code> interface object and constructor.
                   2224: 
                   2225:    <li>
                   2226:     <p>The <code>MessageChannel</code> interface object and constructor.
                   2227:   </ul>
                   2228: 
1.34      ihickson 2229:   <h3 id=worker0><span class=secno>3.4 </span>Worker locations</h3>
                   2230: 
                   2231:   <pre
                   2232:    class=idl>[NoInterfaceObject] interface <dfn id=workerlocation>WorkerLocation</dfn> {
                   2233:   readonly attribute DOMString <a href="#href" title=dom-WorkerLocation-href>href</a>;
                   2234:   readonly attribute DOMString <a href="#protocol" title=dom-WorkerLocation-protocol>protocol</a>;
                   2235:   readonly attribute DOMString <a href="#host" title=dom-WorkerLocation-host>host</a>;
                   2236:   readonly attribute DOMString <a href="#hostname" title=dom-WorkerLocation-hostname>hostname</a>;
1.50      ihickson 2237:   readonly attribute DOMString <a href="#port0" title=dom-WorkerLocation-port>port</a>;
1.34      ihickson 2238:   readonly attribute DOMString <a href="#pathname" title=dom-WorkerLocation-pathname>pathname</a>;
                   2239:   readonly attribute DOMString <a href="#search" title=dom-WorkerLocation-search>search</a>;
                   2240:   readonly attribute DOMString <a href="#hash" title=dom-WorkerLocation-hash>hash</a>;
                   2241: };</pre>
                   2242: 
                   2243:   <p>A <code><a href="#workerlocation">WorkerLocation</a></code> object
                   2244:    represents an <span>absolute URL</span> set at its creation.
                   2245: 
                   2246:   <p>The <dfn id=href title=dom-WorkerLocation-href><code>href</code></dfn>
                   2247:    attribute must return the <span>absolute URL</span> that the object
                   2248:    represents.
                   2249: 
                   2250:   <p>The <code><a href="#workerlocation">WorkerLocation</a></code> interface
                   2251:    also has the complement of <span>URL decomposition attributes</span>, <dfn
                   2252:    id=protocol title=dom-WorkerLocation-protocol><code>protocol</code></dfn>,
                   2253:    <dfn id=host title=dom-WorkerLocation-host><code>host</code></dfn>, <dfn
1.50      ihickson 2254:    id=port0 title=dom-WorkerLocation-port><code>port</code></dfn>, <dfn
1.34      ihickson 2255:    id=hostname title=dom-WorkerLocation-hostname><code>hostname</code></dfn>,
                   2256:    <dfn id=pathname
                   2257:    title=dom-WorkerLocation-pathname><code>pathname</code></dfn>, <dfn
                   2258:    id=search title=dom-WorkerLocation-search><code>search</code></dfn>, and
                   2259:    <dfn id=hash title=dom-WorkerLocation-hash><code>hash</code></dfn>. These
                   2260:    must follow the rules given for URL decomposition attributes, with the
                   2261:    <span title=concept-uda-input>input</span> being the <span>absolute
                   2262:    URL</span> that the object represents (same as the <code
                   2263:    title=dom-WorkerLocation-href><a href="#href">href</a></code> attribute),
                   2264:    and the <span title=concept-uda-setter>common setter action</span> being a
                   2265:    no-op, since the attributes are defined to be readonly. <a
                   2266:    href="#refsHTML5">[HTML5]</a>
                   2267: 
1.1       ihickson 2268:   <h2 class=no-num id=references>References</h2>
                   2269: 
                   2270:   <p class=big-issue>This section will be written in a future
                   2271:    draft.<!--XXX-->
                   2272: 
                   2273:   <h2 class=no-num id=acknowledgements>Acknowledgements</h2>
                   2274:   <!-- ACKS -->
                   2275: 
1.52      ihickson 2276:   <p>Thanks to Aaron Boodman, Jonas Sicking, Justin James, Maciej Stachowiak,
1.57      ihickson 2277:    Michael Nordman, Mike Smith, and Philip Taylor for their useful and
                   2278:    substantial comments.
1.4       ihickson 2279: 
                   2280:   <p>Huge thanks to the whole Gears team, who pioneered this technology and
                   2281:    whose experience has been a huge influence on this specification.

Webmaster