diff --git a/cli/ops/worker_host.rs b/cli/ops/worker_host.rs index ea8e3db56e..479fcceafc 100644 --- a/cli/ops/worker_host.rs +++ b/cli/ops/worker_host.rs @@ -184,6 +184,9 @@ fn op_create_worker( }; let args_name = args.name; let use_deno_namespace = args.use_deno_namespace; + if use_deno_namespace { + state.check_unstable("Worker.deno"); + } let parent_state = state.clone(); let mut state = state.borrow_mut(); let global_state = state.global_state.clone(); diff --git a/cli/tests/039_worker_deno_ns.ts b/cli/tests/039_worker_deno_ns.ts deleted file mode 100644 index 7cb7de7fbd..0000000000 --- a/cli/tests/039_worker_deno_ns.ts +++ /dev/null @@ -1,23 +0,0 @@ -const w1 = new Worker("./039_worker_deno_ns/has_ns.ts", { type: "module" }); -const w2 = new Worker("./039_worker_deno_ns/no_ns.ts", { type: "module" }); -let w1MsgCount = 0; -let w2MsgCount = 0; -w1.onmessage = (msg): void => { - console.log(msg.data); - w1MsgCount++; - if (w1MsgCount === 1) { - w1.postMessage("CONTINUE"); - } else { - w2.postMessage("START"); - } -}; -w2.onmessage = (msg): void => { - console.log(msg.data); - w2MsgCount++; - if (w2MsgCount === 1) { - w2.postMessage("CONTINUE"); - } else { - Deno.exit(0); - } -}; -w1.postMessage("START"); diff --git a/cli/tests/039_worker_deno_ns.ts.out b/cli/tests/039_worker_deno_ns.ts.out deleted file mode 100644 index 9b2f90099c..0000000000 --- a/cli/tests/039_worker_deno_ns.ts.out +++ /dev/null @@ -1,4 +0,0 @@ -has_ns.ts: is window.Deno available: true -[SPAWNED BY has_ns.ts] maybe_ns.ts: is window.Deno available: true -no_ns.ts: is window.Deno available: false -[SPAWNED BY no_ns.ts] maybe_ns.ts: is window.Deno available: false diff --git a/cli/tests/039_worker_deno_ns/has_ns.ts b/cli/tests/039_worker_deno_ns/has_ns.ts deleted file mode 100644 index 8d25071226..0000000000 --- a/cli/tests/039_worker_deno_ns/has_ns.ts +++ /dev/null @@ -1,10 +0,0 @@ -onmessage = (msg): void => { - if (msg.data === "START") { - postMessage("has_ns.ts: is window.Deno available: " + !!window.Deno); - } else { - const worker = new Worker("./maybe_ns.ts"); - worker.onmessage = (msg): void => { - postMessage("[SPAWNED BY has_ns.ts] " + msg.data); - }; - } -}; diff --git a/cli/tests/039_worker_deno_ns/maybe_ns.ts b/cli/tests/039_worker_deno_ns/maybe_ns.ts deleted file mode 100644 index 0bcbd1f973..0000000000 --- a/cli/tests/039_worker_deno_ns/maybe_ns.ts +++ /dev/null @@ -1 +0,0 @@ -postMessage("maybe_ns.ts: is window.Deno available: " + !!window.Deno); diff --git a/cli/tests/039_worker_deno_ns/no_ns.ts b/cli/tests/039_worker_deno_ns/no_ns.ts deleted file mode 100644 index 0489a00a39..0000000000 --- a/cli/tests/039_worker_deno_ns/no_ns.ts +++ /dev/null @@ -1,10 +0,0 @@ -onmessage = (msg): void => { - if (msg.data === "START") { - postMessage("no_ns.ts: is window.Deno available: " + !!window.Deno); - } else { - const worker = new Worker("./maybe_ns.ts"); - worker.onmessage = (msg): void => { - postMessage("[SPAWNED BY no_ns.ts] " + msg.data); - }; - } -}; diff --git a/cli/tests/040_worker_blob.ts b/cli/tests/040_worker_blob.ts deleted file mode 100644 index 1ba4528cf9..0000000000 --- a/cli/tests/040_worker_blob.ts +++ /dev/null @@ -1,6 +0,0 @@ -const b = new Blob(["console.log('code from Blob'); postMessage('DONE')"]); -const blobURL = URL.createObjectURL(b); -const worker = new Worker(blobURL); -worker.onmessage = (): void => { - Deno.exit(0); -}; diff --git a/cli/tests/040_worker_blob.ts.out b/cli/tests/040_worker_blob.ts.out deleted file mode 100644 index f49b8f3d6f..0000000000 --- a/cli/tests/040_worker_blob.ts.out +++ /dev/null @@ -1 +0,0 @@ -code from Blob diff --git a/cli/tests/error_worker_dynamic.ts b/cli/tests/error_worker_dynamic.ts deleted file mode 100644 index 16fadf5733..0000000000 --- a/cli/tests/error_worker_dynamic.ts +++ /dev/null @@ -1,3 +0,0 @@ -const b = new Blob(['throw new Error("hello");']); -const blobURL = URL.createObjectURL(b); -new Worker(blobURL); diff --git a/cli/tests/error_worker_dynamic.ts.out b/cli/tests/error_worker_dynamic.ts.out deleted file mode 100644 index 4bea7b656c..0000000000 --- a/cli/tests/error_worker_dynamic.ts.out +++ /dev/null @@ -1,3 +0,0 @@ -[WILDCARD]error: Uncaught Error: hello -[WILDCARD]__anonymous__:1:7 - at [WILDCARD]__anonymous__:1:7 diff --git a/cli/tests/integration_tests.rs b/cli/tests/integration_tests.rs index bbd4376231..91adb7fe9c 100644 --- a/cli/tests/integration_tests.rs +++ b/cli/tests/integration_tests.rs @@ -985,6 +985,7 @@ fn workers() { .arg("test") .arg("--reload") .arg("--allow-net") + .arg("--unstable") .arg("workers_test.ts") .spawn() .unwrap() @@ -1080,17 +1081,6 @@ itest!(_038_checkjs { output: "038_checkjs.js.out", }); -// TODO(bartlomieju): re-enable -itest_ignore!(_039_worker_deno_ns { - args: "run --reload 039_worker_deno_ns.ts", - output: "039_worker_deno_ns.ts.out", -}); - -itest_ignore!(_040_worker_blob { - args: "run --reload 040_worker_blob.ts", - output: "040_worker_blob.ts.out", -}); - itest!(_041_dyn_import_eval { args: "eval import('./subdir/mod4.js').then(console.log)", output: "041_dyn_import_eval.out", @@ -1471,14 +1461,6 @@ itest!(error_local_static_import_from_remote_js { output: "error_local_static_import_from_remote.js.out", }); -// TODO(bartlomieju) Re-enable -itest_ignore!(error_worker_dynamic { - args: "run --reload error_worker_dynamic.ts", - check_stderr: true, - exit_code: 1, - output: "error_worker_dynamic.ts.out", -}); - itest!(exit_error42 { exit_code: 42, args: "run --reload exit_error42.ts", diff --git a/docs/runtime/workers.md b/docs/runtime/workers.md new file mode 100644 index 0000000000..0418f057e0 --- /dev/null +++ b/docs/runtime/workers.md @@ -0,0 +1,54 @@ +## Workers + +Deno supports +[`Web Worker API`](https://developer.mozilla.org/en-US/docs/Web/API/Worker/Worker). + +Workers can be used to run code on multiple threads. Each instance of `Worker` +is run on a separate thread, dedicated only to that worker. + +Currently Deno supports only `module` type workers; thus it's essential to pass +`type: "module"` option when creating new worker: + +```ts +// Good +new Worker("./worker.js", { type: "module" }); + +// Bad +new Worker("./worker.js"); +new Worker("./worker.js", { type: "classic" }); +``` + +### Using Deno in worker + +**UNSTABLE**: This feature is unstable and requires `--unstable` flag + +By default `Deno` namespace is not available in worker scope. + +To add `Deno` namespace pass `deno: true` option when creating new worker: + +```ts +// main.js +const worker = new Worker("./worker.js", { type: "module", deno: true }); +worker.postMessage({ filename: "./log.txt" }); + +// worker.js +self.onmessage = async (e) => { + const { filename } = e.data; + const text = await Deno.readTextFile(filename); + console.log(text); + self.close(); +}; + +// log.txt +hello world +``` + +```shell +$ deno run --allow-read --unstable main.js +hello world +``` + +When `Deno` namespace is available in worker scope; the worker inherits parent +process permissions (the ones specified using `--allow-*` flags). + +We intend to make permissions configurable for workers. diff --git a/docs/toc.json b/docs/toc.json index a3d8752b93..7956a402a9 100644 --- a/docs/toc.json +++ b/docs/toc.json @@ -18,7 +18,8 @@ "children": { "program_lifecycle": "Program Lifecycle", "compiler_apis": "Compiler APIs", - "unstable": "Unstable APIs" + "unstable": "Unstable APIs", + "workers": "Workers" } }, "linking_to_external_code": {