diff options
Diffstat (limited to 'runtime/js')
-rw-r--r-- | runtime/js/11_workers.js | 31 | ||||
-rw-r--r-- | runtime/js/99_main.js | 46 |
2 files changed, 66 insertions, 11 deletions
diff --git a/runtime/js/11_workers.js b/runtime/js/11_workers.js index b5a8a9d0c..2f9413119 100644 --- a/runtime/js/11_workers.js +++ b/runtime/js/11_workers.js @@ -7,7 +7,6 @@ ArrayIsArray, ArrayPrototypeMap, Error, - Uint8Array, StringPrototypeStartsWith, String, SymbolIterator, @@ -28,6 +27,7 @@ useDenoNamespace, permissions, name, + workerType, ) { return core.opSync("op_create_worker", { hasSourceCode, @@ -36,6 +36,7 @@ sourceCode, specifier, useDenoNamespace, + workerType, }); } @@ -183,20 +184,12 @@ } } - if (type !== "module") { - throw new Error( - 'Not yet implemented: only "module" type workers are supported', - ); - } - - this.#name = name; - const hasSourceCode = false; - const sourceCode = core.decode(new Uint8Array()); + const workerType = webidl.converters["WorkerType"](type); if ( StringPrototypeStartsWith(specifier, "./") || StringPrototypeStartsWith(specifier, "../") || - StringPrototypeStartsWith(specifier, "/") || type == "classic" + StringPrototypeStartsWith(specifier, "/") || workerType === "classic" ) { const baseUrl = getLocationHref(); if (baseUrl != null) { @@ -204,6 +197,16 @@ } } + this.#name = name; + let hasSourceCode, sourceCode; + if (workerType === "classic") { + hasSourceCode = true; + sourceCode = `importScripts("#");`; + } else { + hasSourceCode = false; + sourceCode = ""; + } + const id = createWorker( specifier, hasSourceCode, @@ -213,6 +216,7 @@ ? null : parsePermissions(workerDenoAttributes.permissions), options?.name, + workerType, ); this.#id = id; this.#pollControl(); @@ -344,6 +348,11 @@ defineEventHandler(Worker.prototype, "message"); defineEventHandler(Worker.prototype, "messageerror"); + webidl.converters["WorkerType"] = webidl.createEnumConverter("WorkerType", [ + "classic", + "module", + ]); + window.__bootstrap.worker = { parsePermissions, Worker, diff --git a/runtime/js/99_main.js b/runtime/js/99_main.js index 6d5599e71..b1f7d1473 100644 --- a/runtime/js/99_main.js +++ b/runtime/js/99_main.js @@ -8,6 +8,7 @@ delete Object.prototype.__proto__; ((window) => { const core = Deno.core; const { + ArrayPrototypeMap, Error, FunctionPrototypeCall, FunctionPrototypeBind, @@ -164,6 +165,44 @@ delete Object.prototype.__proto__; } } + let loadedMainWorkerScript = false; + + function importScripts(...urls) { + if (core.opSync("op_worker_get_type") === "module") { + throw new TypeError("Can't import scripts in a module worker."); + } + + const baseUrl = location.getLocationHref(); + const parsedUrls = ArrayPrototypeMap(urls, (scriptUrl) => { + try { + return new url.URL(scriptUrl, baseUrl ?? undefined).href; + } catch { + throw new domException.DOMException( + "Failed to parse URL.", + "SyntaxError", + ); + } + }); + + // A classic worker's main script has looser MIME type checks than any + // imported scripts, so we use `loadedMainWorkerScript` to distinguish them. + // TODO(andreubotella) Refactor worker creation so the main script isn't + // loaded with `importScripts()`. + const scripts = core.opSync( + "op_worker_sync_fetch", + parsedUrls, + !loadedMainWorkerScript, + ); + loadedMainWorkerScript = true; + + for (const { url, script } of scripts) { + const err = core.evalContext(script, url)[1]; + if (err !== null) { + throw err.thrown; + } + } + } + function opMainModule() { return core.opSync("op_main_module"); } @@ -597,6 +636,13 @@ delete Object.prototype.__proto__; } ObjectDefineProperties(globalThis, workerRuntimeGlobalProperties); ObjectDefineProperties(globalThis, { name: util.readOnly(name) }); + if (runtimeOptions.enableTestingFeaturesFlag) { + ObjectDefineProperty( + globalThis, + "importScripts", + util.writable(importScripts), + ); + } ObjectSetPrototypeOf(globalThis, DedicatedWorkerGlobalScope.prototype); const consoleFromDeno = globalThis.console; |