summaryrefslogtreecommitdiff
path: root/cli/tests/workers
diff options
context:
space:
mode:
authorSteven Guerrero <stephenguerrero43@gmail.com>2021-01-06 15:31:16 -0500
committerGitHub <noreply@github.com>2021-01-06 21:31:16 +0100
commitadc2f08c178f51b3ddd5f1c2e3d7f5603424521e (patch)
tree99d61fca9bfdad4e427f9d2d6d1719f69d09c96a /cli/tests/workers
parent2e18fcebcc2ee931ee952ac2fe2175d6ec7acf69 (diff)
feat: Add configurable permissions for Workers (#8215)
This commit adds new option to "Worker" Web API that allows to configure permissions. New "Worker.deno.permissions" option can be used to define limited permissions to the worker thread by either: - inherit set of parent thread permissions - use limited subset of parent thread permissions - revoke all permissions (full sandbox) In order to achieve this functionality "CliModuleLoader" was modified to accept "initial permissions", which are used for top module loading (ie. uses parent thread permission set to load top level module of a worker).
Diffstat (limited to 'cli/tests/workers')
-rw-r--r--cli/tests/workers/bench_worker.ts21
-rw-r--r--cli/tests/workers/busy_worker.js8
-rw-r--r--cli/tests/workers/deno_worker.ts7
-rw-r--r--cli/tests/workers/event_worker.js7
-rw-r--r--cli/tests/workers/event_worker_scope.js43
-rw-r--r--cli/tests/workers/fetching_worker.js6
-rw-r--r--cli/tests/workers/immediately_close_worker.js1
-rw-r--r--cli/tests/workers/nested_worker.js18
-rw-r--r--cli/tests/workers/no_permissions_worker.js17
-rw-r--r--cli/tests/workers/non_deno_worker.js7
-rw-r--r--cli/tests/workers/parent_read_check_granular_worker.js43
-rw-r--r--cli/tests/workers/parent_read_check_worker.js27
-rw-r--r--cli/tests/workers/racy_worker.js21
-rw-r--r--cli/tests/workers/read_check_granular_worker.js13
-rw-r--r--cli/tests/workers/read_check_worker.js7
-rw-r--r--cli/tests/workers/sibling_worker.js4
-rw-r--r--cli/tests/workers/test_worker.js19
-rw-r--r--cli/tests/workers/test_worker.ts8
-rw-r--r--cli/tests/workers/throwing_worker.js2
-rw-r--r--cli/tests/workers/worker_crypto.js3
-rw-r--r--cli/tests/workers/worker_globals.ts10
-rw-r--r--cli/tests/workers/worker_unstable.ts5
22 files changed, 297 insertions, 0 deletions
diff --git a/cli/tests/workers/bench_worker.ts b/cli/tests/workers/bench_worker.ts
new file mode 100644
index 000000000..7e85eed03
--- /dev/null
+++ b/cli/tests/workers/bench_worker.ts
@@ -0,0 +1,21 @@
+onmessage = function (e): void {
+ const { cmdId, action, data } = e.data;
+ switch (action) {
+ case 0: // Static response
+ postMessage({
+ cmdId,
+ data: "HTTP/1.1 200 OK\r\nContent-Length: 12\r\n\r\nHello World\n",
+ });
+ break;
+ case 1: // Respond with request data
+ postMessage({ cmdId, data });
+ break;
+ case 2: // Ping
+ postMessage({ cmdId });
+ break;
+ case 3: // Close
+ postMessage({ cmdId: 3 });
+ close();
+ break;
+ }
+};
diff --git a/cli/tests/workers/busy_worker.js b/cli/tests/workers/busy_worker.js
new file mode 100644
index 000000000..7deba0321
--- /dev/null
+++ b/cli/tests/workers/busy_worker.js
@@ -0,0 +1,8 @@
+self.onmessage = function (_evt) {
+ // infinite loop
+ for (let i = 0; true; i++) {
+ if (i % 1000 == 0) {
+ postMessage(i);
+ }
+ }
+};
diff --git a/cli/tests/workers/deno_worker.ts b/cli/tests/workers/deno_worker.ts
new file mode 100644
index 000000000..6a57c47f0
--- /dev/null
+++ b/cli/tests/workers/deno_worker.ts
@@ -0,0 +1,7 @@
+onmessage = function (e): void {
+ if (typeof self.Deno === "undefined") {
+ throw new Error("Deno namespace not available in worker");
+ }
+
+ postMessage(e.data);
+};
diff --git a/cli/tests/workers/event_worker.js b/cli/tests/workers/event_worker.js
new file mode 100644
index 000000000..849b6026c
--- /dev/null
+++ b/cli/tests/workers/event_worker.js
@@ -0,0 +1,7 @@
+onmessage = function (e) {
+ if (e.data === "boom") {
+ throw new Error("boom error!");
+ }
+
+ postMessage(e.data);
+};
diff --git a/cli/tests/workers/event_worker_scope.js b/cli/tests/workers/event_worker_scope.js
new file mode 100644
index 000000000..0381801a8
--- /dev/null
+++ b/cli/tests/workers/event_worker_scope.js
@@ -0,0 +1,43 @@
+let messageHandlersCalled = 0;
+let errorHandlersCalled = 0;
+
+onmessage = function (e) {
+ if (e.data === "boom") {
+ throw new Error("boom error!");
+ }
+ messageHandlersCalled++;
+};
+
+self.addEventListener("message", (_e) => {
+ messageHandlersCalled++;
+});
+
+self.addEventListener("message", (_e) => {
+ messageHandlersCalled++;
+});
+
+self.addEventListener("message", (_e) => {
+ messageHandlersCalled++;
+
+ postMessage({
+ messageHandlersCalled,
+ errorHandlersCalled,
+ });
+});
+
+onerror = function (_e) {
+ errorHandlersCalled++;
+};
+
+self.addEventListener("error", (_e) => {
+ errorHandlersCalled++;
+});
+
+self.addEventListener("error", (_e) => {
+ errorHandlersCalled++;
+});
+
+self.addEventListener("error", (e) => {
+ errorHandlersCalled++;
+ e.preventDefault();
+});
diff --git a/cli/tests/workers/fetching_worker.js b/cli/tests/workers/fetching_worker.js
new file mode 100644
index 000000000..e1bcdf911
--- /dev/null
+++ b/cli/tests/workers/fetching_worker.js
@@ -0,0 +1,6 @@
+const r = await fetch(
+ "http://localhost:4545/cli/tests/workers/fetching_worker.js",
+);
+await r.text();
+postMessage("Done!");
+close();
diff --git a/cli/tests/workers/immediately_close_worker.js b/cli/tests/workers/immediately_close_worker.js
new file mode 100644
index 000000000..8fd27343a
--- /dev/null
+++ b/cli/tests/workers/immediately_close_worker.js
@@ -0,0 +1 @@
+self.close();
diff --git a/cli/tests/workers/nested_worker.js b/cli/tests/workers/nested_worker.js
new file mode 100644
index 000000000..4b51b8763
--- /dev/null
+++ b/cli/tests/workers/nested_worker.js
@@ -0,0 +1,18 @@
+// Specifier should be resolved relative to current file
+const jsWorker = new Worker(
+ new URL("sibling_worker.js", import.meta.url).href,
+ { type: "module", name: "sibling" },
+);
+
+jsWorker.onerror = (_e) => {
+ postMessage({ type: "error" });
+};
+
+jsWorker.onmessage = (e) => {
+ postMessage({ type: "msg", text: e });
+ close();
+};
+
+onmessage = function (e) {
+ jsWorker.postMessage(e.data);
+};
diff --git a/cli/tests/workers/no_permissions_worker.js b/cli/tests/workers/no_permissions_worker.js
new file mode 100644
index 000000000..8a4f79d57
--- /dev/null
+++ b/cli/tests/workers/no_permissions_worker.js
@@ -0,0 +1,17 @@
+self.onmessage = async () => {
+ const hrtime = await Deno.permissions.query({ name: "hrtime" });
+ const net = await Deno.permissions.query({ name: "net" });
+ const plugin = await Deno.permissions.query({ name: "plugin" });
+ const read = await Deno.permissions.query({ name: "read" });
+ const run = await Deno.permissions.query({ name: "run" });
+ const write = await Deno.permissions.query({ name: "write" });
+ self.postMessage(
+ hrtime.state === "denied" &&
+ net.state === "denied" &&
+ plugin.state === "denied" &&
+ read.state === "denied" &&
+ run.state === "denied" &&
+ write.state === "denied",
+ );
+ self.close();
+};
diff --git a/cli/tests/workers/non_deno_worker.js b/cli/tests/workers/non_deno_worker.js
new file mode 100644
index 000000000..773721560
--- /dev/null
+++ b/cli/tests/workers/non_deno_worker.js
@@ -0,0 +1,7 @@
+onmessage = function (e) {
+ if (typeof self.Deno !== "undefined") {
+ throw new Error("Deno namespace unexpectedly available in worker");
+ }
+
+ postMessage(e.data);
+};
diff --git a/cli/tests/workers/parent_read_check_granular_worker.js b/cli/tests/workers/parent_read_check_granular_worker.js
new file mode 100644
index 000000000..1a7182e17
--- /dev/null
+++ b/cli/tests/workers/parent_read_check_granular_worker.js
@@ -0,0 +1,43 @@
+import { fromFileUrl } from "../../../std/path/mod.ts";
+
+const worker = new Worker(
+ new URL("./read_check_granular_worker.js", import.meta.url).href,
+ {
+ type: "module",
+ deno: {
+ namespace: true,
+ permissions: {
+ read: [],
+ },
+ },
+ },
+);
+
+let received = 0;
+const messages = [];
+
+worker.onmessage = ({ data: childResponse }) => {
+ received++;
+ postMessage({
+ childHasPermission: childResponse.hasPermission,
+ index: childResponse.index,
+ parentHasPermission: messages[childResponse.index],
+ });
+ if (received === messages.length) {
+ worker.terminate();
+ }
+};
+
+onmessage = async ({ data }) => {
+ const { state } = await Deno.permissions.query({
+ name: "read",
+ path: fromFileUrl(new URL(data.route, import.meta.url)),
+ });
+
+ messages[data.index] = state === "granted";
+
+ worker.postMessage({
+ index: data.index,
+ route: data.route,
+ });
+};
diff --git a/cli/tests/workers/parent_read_check_worker.js b/cli/tests/workers/parent_read_check_worker.js
new file mode 100644
index 000000000..ec92cca3f
--- /dev/null
+++ b/cli/tests/workers/parent_read_check_worker.js
@@ -0,0 +1,27 @@
+onmessage = async () => {
+ const { state } = await Deno.permissions.query({
+ name: "read",
+ });
+
+ const worker = new Worker(
+ new URL("./read_check_worker.js", import.meta.url).href,
+ {
+ type: "module",
+ deno: {
+ namespace: true,
+ permissions: {
+ read: false,
+ },
+ },
+ },
+ );
+
+ worker.onmessage = ({ data: childHasPermission }) => {
+ postMessage({
+ parentHasPermission: state === "granted",
+ childHasPermission,
+ });
+ close();
+ };
+ worker.postMessage(null);
+};
diff --git a/cli/tests/workers/racy_worker.js b/cli/tests/workers/racy_worker.js
new file mode 100644
index 000000000..83756b791
--- /dev/null
+++ b/cli/tests/workers/racy_worker.js
@@ -0,0 +1,21 @@
+// See issue for details
+// https://github.com/denoland/deno/issues/4080
+//
+// After first call to `postMessage() this worker schedules
+// [close(), postMessage()] ops on the same turn of microtask queue
+// (because message is rather big).
+// Only single `postMessage()` call should make it
+// to host, ie. after calling `close()` no more code should be run.
+
+setTimeout(() => {
+ close();
+}, 50);
+
+while (true) {
+ await new Promise((done) => {
+ setTimeout(() => {
+ postMessage({ buf: new Array(999999) });
+ done();
+ });
+ });
+}
diff --git a/cli/tests/workers/read_check_granular_worker.js b/cli/tests/workers/read_check_granular_worker.js
new file mode 100644
index 000000000..4eddb7a75
--- /dev/null
+++ b/cli/tests/workers/read_check_granular_worker.js
@@ -0,0 +1,13 @@
+import { fromFileUrl } from "../../../std/path/mod.ts";
+
+onmessage = async ({ data }) => {
+ const { state } = await Deno.permissions.query({
+ name: "read",
+ path: fromFileUrl(new URL(data.route, import.meta.url)),
+ });
+
+ postMessage({
+ hasPermission: state === "granted",
+ index: data.index,
+ });
+};
diff --git a/cli/tests/workers/read_check_worker.js b/cli/tests/workers/read_check_worker.js
new file mode 100644
index 000000000..2ad01bf5b
--- /dev/null
+++ b/cli/tests/workers/read_check_worker.js
@@ -0,0 +1,7 @@
+onmessage = async () => {
+ const { state } = await Deno.permissions.query({
+ name: "read",
+ });
+ postMessage(state === "granted");
+ close();
+};
diff --git a/cli/tests/workers/sibling_worker.js b/cli/tests/workers/sibling_worker.js
new file mode 100644
index 000000000..99707e5d6
--- /dev/null
+++ b/cli/tests/workers/sibling_worker.js
@@ -0,0 +1,4 @@
+onmessage = (e) => {
+ postMessage(e.data);
+ close();
+};
diff --git a/cli/tests/workers/test_worker.js b/cli/tests/workers/test_worker.js
new file mode 100644
index 000000000..4260975a6
--- /dev/null
+++ b/cli/tests/workers/test_worker.js
@@ -0,0 +1,19 @@
+let thrown = false;
+
+if (self.name !== "") {
+ throw Error(`Bad worker name: ${self.name}, expected empty string.`);
+}
+
+onmessage = function (e) {
+ if (thrown === false) {
+ thrown = true;
+ throw new SyntaxError("[test error]");
+ }
+
+ postMessage(e.data);
+ close();
+};
+
+onerror = function () {
+ return false;
+};
diff --git a/cli/tests/workers/test_worker.ts b/cli/tests/workers/test_worker.ts
new file mode 100644
index 000000000..ca79dcfe4
--- /dev/null
+++ b/cli/tests/workers/test_worker.ts
@@ -0,0 +1,8 @@
+if (self.name !== "tsWorker") {
+ throw Error(`Invalid worker name: ${self.name}, expected tsWorker`);
+}
+
+onmessage = function (e): void {
+ postMessage(e.data);
+ close();
+};
diff --git a/cli/tests/workers/throwing_worker.js b/cli/tests/workers/throwing_worker.js
new file mode 100644
index 000000000..56ee4ff88
--- /dev/null
+++ b/cli/tests/workers/throwing_worker.js
@@ -0,0 +1,2 @@
+// This worker just throws error when it's being executed
+throw Error("Thrown error");
diff --git a/cli/tests/workers/worker_crypto.js b/cli/tests/workers/worker_crypto.js
new file mode 100644
index 000000000..a86340005
--- /dev/null
+++ b/cli/tests/workers/worker_crypto.js
@@ -0,0 +1,3 @@
+onmessage = function () {
+ postMessage(!!self.crypto);
+};
diff --git a/cli/tests/workers/worker_globals.ts b/cli/tests/workers/worker_globals.ts
new file mode 100644
index 000000000..a9e7efd85
--- /dev/null
+++ b/cli/tests/workers/worker_globals.ts
@@ -0,0 +1,10 @@
+onmessage = function (): void {
+ postMessage(
+ [
+ self instanceof DedicatedWorkerGlobalScope,
+ self instanceof WorkerGlobalScope,
+ self instanceof EventTarget,
+ ].join(", "),
+ );
+ close();
+};
diff --git a/cli/tests/workers/worker_unstable.ts b/cli/tests/workers/worker_unstable.ts
new file mode 100644
index 000000000..a5b5f7ba2
--- /dev/null
+++ b/cli/tests/workers/worker_unstable.ts
@@ -0,0 +1,5 @@
+console.log(Deno.permissions.query);
+console.log(Deno.emit);
+self.onmessage = () => {
+ self.close();
+};