Skip to content

Commit 529c409

Browse files
chrisdavidmillsbsmthdipikabh
authored
Add Worker playground (#322)
* Add Worker playground * fix: Changes following reviewer feedback * feat: Changes following reviewer feedback * Update README.md Co-authored-by: Dipika Bhattacharya <dipika@foss-community.org> --------- Co-authored-by: Brian Smith <brian@smith.berlin> Co-authored-by: Dipika Bhattacharya <dipika@foss-community.org>
1 parent 73a863e commit 529c409

18 files changed

+357
-1
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ Code examples that accompany various MDN DOM and Web API documentation pages.
9393

9494
- The "web-share" directory contains a basic demo to show usage of the [Web Share API](https://developer.mozilla.org/docs/Web/API/Navigator/share). [View the demo live](https://mdn.github.io/dom-examples/web-share/).
9595

96-
- The "web-workers" directory contains a basic web worker to demonstrate how [Web Workers](https://developer.mozilla.org/docs/Web/API/Web_Workers_API) work. [View the demo live](https://mdn.github.io/dom-examples/web-workers/simple-web-worker/).
96+
- The "web-workers" directory contains several demos that show how [Web Workers](https://developer.mozilla.org/docs/Web/API/Web_Workers_API) operate. For example, view the live [simple web worker demo](https://mdn.github.io/dom-examples/web-workers/simple-web-worker/).
9797

9898
- The ["webgl-examples"](webgl-examples/README.md) directory contains a number of WebGL examples that demonstrate the [WebGL API](https://developer.mozilla.org/docs/Web/API/WebGL_API), which is used for 2D and 3D graphics on the web.
9999

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
++++++
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
addEventListener("message", function (evt) {
2+
let { generation, str } = evt.data;
3+
4+
let result;
5+
try {
6+
result = eval(str) + "";
7+
} catch (ex) {
8+
result = "Exception: " + ex;
9+
}
10+
11+
postMessage({
12+
generation,
13+
result,
14+
});
15+
});
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
function msghandler(evt) {
2+
if (evt.data === "throw") {
3+
throw new Error("Throw requested by postMessage()");
4+
}
5+
}
6+
7+
onconnect = function (evt) {
8+
evt.ports[0].onmessage = msghandler;
9+
throw new Error("Throw initiated by connect!");
10+
};
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
onmessage = function (evt) {
2+
if (evt.data.script) {
3+
try {
4+
importScripts(evt.data.script);
5+
if (self.workerMethod) {
6+
workerMethod();
7+
}
8+
} catch (ex) {
9+
let recovered = false;
10+
// Scripts with partial in them should be handled for side-effect.
11+
if (/partial/i.test(evt.data.script)) {
12+
recovered = true;
13+
try {
14+
workerMethod();
15+
} catch (ex2) {
16+
ex = ex2;
17+
}
18+
}
19+
postMessage({
20+
iMsg: evt.data.iMsg,
21+
script: evt.data.script,
22+
errored: true,
23+
recovered,
24+
message: ex.message,
25+
filename: ex.filename || ex.fileName,
26+
stringified: ex + "",
27+
stack: ex.stack + "",
28+
});
29+
return;
30+
}
31+
postMessage({
32+
errored: false,
33+
filname: null,
34+
stack: null,
35+
});
36+
}
37+
};
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
var foo = 1;
2+
fo++;
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
<!doctype html>
2+
<html>
3+
<head>
4+
<meta charset="UTF-8" />
5+
</head>
6+
<body>
7+
<script type="application/javascript">
8+
const crossOrigin = "https://worker-playground-crossorigin.glitch.me";
9+
const syntaxScriptName = "bad-syntax-worker.js";
10+
const idTypoWorkerScriptName = "id-typo-worker.js";
11+
const topLevelThrowScriptName = "top-level-throw.js";
12+
const topLevelPartialScriptName = "top-level-partial.js";
13+
const methodThrowScriptName = "method-throws-worker.js";
14+
15+
function makeRedirectedUrl(scriptName) {
16+
return `${crossOrigin}/redirects/script.js?script=${scriptName}&cookieCheck=true`;
17+
}
18+
19+
const w = new Worker("dynamic-importer.js");
20+
let iMsg = 0;
21+
function sendAndAwait(data) {
22+
data.iMsg = ++iMsg;
23+
return new Promise((resolve) => {
24+
w.addEventListener(
25+
"message",
26+
(evt) => {
27+
resolve(evt.data);
28+
},
29+
{ once: true },
30+
);
31+
w.postMessage(data);
32+
});
33+
}
34+
35+
async function workerDriver() {
36+
let msg;
37+
msg = await sendAndAwait({
38+
script: makeRedirectedUrl(syntaxScriptName),
39+
});
40+
console.log("Syntax error:", msg);
41+
msg = await sendAndAwait({
42+
script: makeRedirectedUrl(idTypoWorkerScriptName),
43+
});
44+
console.log("Id typo error:", msg);
45+
msg = await sendAndAwait({
46+
script: makeRedirectedUrl(topLevelThrowScriptName),
47+
});
48+
console.log("Top level throw error:", msg);
49+
msg = await sendAndAwait({
50+
script: makeRedirectedUrl(topLevelPartialScriptName),
51+
});
52+
console.log("Top level method throw after top-level throw error:", msg);
53+
msg = await sendAndAwait({
54+
script: makeRedirectedUrl(methodThrowScriptName),
55+
});
56+
console.log("Method throw error:", msg);
57+
58+
w.terminate();
59+
}
60+
workerDriver();
61+
</script>
62+
</body>
63+
</html>
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<title>Worker Playground</title>
5+
<meta charset="utf-8" />
6+
<meta name="viewport" content="width=device-width, initial-scale=1" />
7+
<link rel="stylesheet" href="style.css" />
8+
<script src="script.js" defer></script>
9+
</head>
10+
<body>
11+
<h1>Worker Playground!</h1>
12+
13+
<p>
14+
Type your code into the following text area, and the app will
15+
<code>eval()</code> it in a Dedicated Worker, Shared Worker, and Service
16+
Worker, letting you know whether it is supported and what it returns in
17+
those contexts. For example, try <code>XMLHttpRequest</code>,
18+
<code>registration</code>, or <code>location</code>:
19+
</p>
20+
21+
<textarea id="inp" cols="80" rows="10"></textarea>
22+
23+
<h3>Dedicated Worker output:</h3>
24+
<textarea id="dedicated" cols="80" rows="10"></textarea>
25+
<h3>Shared Worker output:</h3>
26+
<textarea id="shared" cols="80" rows="10"></textarea>
27+
<h3>Service Worker output:</h3>
28+
<textarea id="service" cols="80" rows="10"></textarea>
29+
</body>
30+
</html>
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
function workerMethod() {
2+
throw new Error("Hey! Don't call me!");
3+
}
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
var swReg = null;
2+
var useSw = null;
3+
navigator.serviceWorker.register("sw.js").then((reg) => {
4+
swReg = reg;
5+
useSw = reg.active || reg.waiting || reg.installing;
6+
});
7+
8+
var taDedicated = document.getElementById("dedicated");
9+
var dedicatedWorker = new Worker("dedicated.js");
10+
dedicatedWorker.addEventListener("message", function (evt) {
11+
let { result } = evt.data;
12+
taDedicated.value = result;
13+
});
14+
15+
var sharedWorker;
16+
var taShared = document.getElementById("shared");
17+
if ("SharedWorker" in window) {
18+
sharedWorker = new SharedWorker("shared.js");
19+
sharedWorker.port.addEventListener("message", function (evt) {
20+
let { result } = evt.data;
21+
taShared.value = result;
22+
});
23+
sharedWorker.port.start();
24+
} else {
25+
taShared.value = "Not supported by this browser.";
26+
}
27+
28+
var taService = document.getElementById("service");
29+
var serviceWorker;
30+
navigator.serviceWorker.addEventListener("message", function (evt) {
31+
var { result } = evt.data;
32+
taService.value = result;
33+
});
34+
35+
var curGeneration = 1;
36+
function evalInAll(str) {
37+
var payload = {
38+
generation: curGeneration++,
39+
str,
40+
};
41+
42+
dedicatedWorker.postMessage(payload);
43+
if (sharedWorker) {
44+
sharedWorker.port.postMessage(payload);
45+
}
46+
if (useSw) {
47+
useSw.postMessage(payload);
48+
} else {
49+
navigator.serviceWorker.ready.then((reg) => {
50+
reg.active.postMessage(payload);
51+
});
52+
}
53+
}
54+
55+
var taInput = document.getElementById("inp");
56+
taInput.addEventListener("keyup", function (evt) {
57+
evalInAll(taInput.value);
58+
});

0 commit comments

Comments
 (0)