summaryrefslogtreecommitdiff
path: root/ext/node/polyfills/worker_threads.ts
diff options
context:
space:
mode:
Diffstat (limited to 'ext/node/polyfills/worker_threads.ts')
-rw-r--r--ext/node/polyfills/worker_threads.ts65
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(