diff options
Diffstat (limited to 'ext/node/polyfills/worker_threads.ts')
-rw-r--r-- | ext/node/polyfills/worker_threads.ts | 65 |
1 files changed, 63 insertions, 2 deletions
diff --git a/ext/node/polyfills/worker_threads.ts b/ext/node/polyfills/worker_threads.ts index 32f9885af..0529383cc 100644 --- a/ext/node/polyfills/worker_threads.ts +++ b/ext/node/polyfills/worker_threads.ts @@ -1,7 +1,7 @@ // Copyright 2018-2023 the Deno authors. All rights reserved. MIT license. // Copyright Joyent and Node contributors. All rights reserved. MIT license. -import { resolve, toFileUrl } from "ext:deno_node/path.ts"; +import { isAbsolute, resolve } from "ext:deno_node/path.ts"; import { notImplemented } from "ext:deno_node/_utils.ts"; import { EventEmitter, once } from "ext:deno_node/events.ts"; import { BroadcastChannel } from "ext:deno_broadcast_channel/01_broadcast_channel.js"; @@ -32,6 +32,67 @@ export interface WorkerOptions { workerData?: unknown; } +const WHITESPACE_ENCODINGS: Record<string, string> = { + "\u0009": "%09", + "\u000A": "%0A", + "\u000B": "%0B", + "\u000C": "%0C", + "\u000D": "%0D", + "\u0020": "%20", +}; + +function encodeWhitespace(string: string): string { + return string.replaceAll(/[\s]/g, (c) => { + return WHITESPACE_ENCODINGS[c] ?? c; + }); +} + +function toFileUrlPosix(path: string): URL { + if (!isAbsolute(path)) { + throw new TypeError("Must be an absolute path."); + } + const url = new URL("file:///"); + url.pathname = encodeWhitespace( + path.replace(/%/g, "%25").replace(/\\/g, "%5C"), + ); + return url; +} + +function toFileUrlWin32(path: string): URL { + if (!isAbsolute(path)) { + throw new TypeError("Must be an absolute path."); + } + const [, hostname, pathname] = path.match( + /^(?:[/\\]{2}([^/\\]+)(?=[/\\](?:[^/\\]|$)))?(.*)/, + )!; + const url = new URL("file:///"); + url.pathname = encodeWhitespace(pathname.replace(/%/g, "%25")); + if (hostname != null && hostname != "localhost") { + url.hostname = hostname; + if (!url.hostname) { + throw new TypeError("Invalid hostname."); + } + } + return url; +} + +/** + * Converts a path string to a file URL. + * + * ```ts + * toFileUrl("/home/foo"); // new URL("file:///home/foo") + * toFileUrl("\\home\\foo"); // new URL("file:///home/foo") + * toFileUrl("C:\\Users\\foo"); // new URL("file:///C:/Users/foo") + * toFileUrl("\\\\127.0.0.1\\home\\foo"); // new URL("file://127.0.0.1/home/foo") + * ``` + * @param path to convert to file URL + */ +function toFileUrl(path: string): URL { + return core.build.os == "windows" + ? toFileUrlWin32(path) + : toFileUrlPosix(path); +} + const kHandle = Symbol("kHandle"); const PRIVATE_WORKER_THREAD_NAME = "$DENO_STD_NODE_WORKER_THREAD"; class _Worker extends EventEmitter { @@ -68,7 +129,7 @@ class _Worker extends EventEmitter { specifier = `data:text/javascript,(async function() {const { createRequire } = await import("node:module");const require = createRequire("${cwdFileUrl}");require("${specifier}");})();`; } else { - specifier = toFileUrl(specifier); + specifier = toFileUrl(specifier as string); } } const handle = this[kHandle] = new Worker( |