mirror of
https://github.com/denoland/deno.git
synced 2025-07-31 00:54:18 +00:00
feat(runtime): support classic workers for internal testing (#11338)
This commit implements classic workers, but only when the `--enable-testing-features-do-not-use` flag is provided. This change is not user facing. Classic workers are used extensively in WPT tests. The classic workers do not support loading from disk, and do not support TypeScript. Co-authored-by: Luca Casonato <hello@lcas.dev>
This commit is contained in:
parent
d1d2388d7f
commit
ddbb7b83f2
15 changed files with 485 additions and 15 deletions
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue