/[suikacvs]/markup/html/html5/spec-ja/.workers-spec.en.html
Suika

Contents of /markup/html/html5/spec-ja/.workers-spec.en.html

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.23 - (show annotations) (download) (as text)
Wed Jan 21 06:18:55 2009 UTC (17 years, 5 months ago) by wakaba
Branch: MAIN
Changes since 1.22: +260 -232 lines
File MIME type: text/html
make

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

[email protected]
ViewVC Help
Powered by ViewVC 1.1.24