From 27c94677dfc66b1bb6da74e76acd105dfbe092a7 Mon Sep 17 00:00:00 2001 From: Tomasz Andrzejak Date: Wed, 24 Jun 2026 10:26:26 +0200 Subject: [PATCH] refactor(p3-shim): migrate preview3-shim package to ts This is based on recent refactor of preview2-shim. --- packages/preview3-shim/.gitignore | 2 ++ packages/preview3-shim/package.json | 29 +++++++++++------ .../{lib/nodejs/cli.js => src/nodejs/cli.ts} | 21 ++++++++---- .../nodejs/clocks.js => src/nodejs/clocks.ts} | 0 .../nodejs/filesystem.ts} | 0 .../nodejs/filesystem/descriptor.ts} | 0 .../nodejs/filesystem/error.ts} | 4 ++- .../nodejs/filesystem/utils.ts} | 0 .../nodejs/finalization.ts} | 4 +-- .../nodejs/future.js => src/nodejs/future.ts} | 0 .../nodejs/http.js => src/nodejs/http.ts} | 0 .../client.js => src/nodejs/http/client.ts} | 4 ++- .../error.js => src/nodejs/http/error.ts} | 6 ++-- .../fields.js => src/nodejs/http/fields.ts} | 0 .../request.js => src/nodejs/http/request.ts} | 4 +-- .../nodejs/http/response.ts} | 2 +- .../server.js => src/nodejs/http/server.ts} | 1 + .../nodejs/index.js => src/nodejs/index.ts} | 0 .../nodejs/random.js => src/nodejs/random.ts} | 0 .../sockets.js => src/nodejs/sockets.ts} | 0 .../nodejs/sockets/address.ts} | 0 .../error.js => src/nodejs/sockets/error.ts} | 8 ++--- .../nodejs/sockets/ip-name-lookup.ts} | 0 .../tcp.js => src/nodejs/sockets/tcp.ts} | 1 + .../udp.js => src/nodejs/sockets/udp.ts} | 0 .../nodejs/stream.js => src/nodejs/stream.ts} | 4 +-- .../nodejs/workers/cli-worker.ts} | 0 .../nodejs/workers/filesystem-worker.ts} | 0 .../nodejs/workers/http-worker.ts} | 10 ++++-- .../nodejs/workers/resource-worker.ts} | 6 ++-- .../nodejs/workers/tcp-worker.ts} | 32 +++++++++---------- .../nodejs/workers/udp-worker.ts} | 12 +++---- packages/preview3-shim/test/nop-worker.js | 2 +- .../test/resource-worker.bench.js | 2 +- .../test/resource-worker.test.js | 2 +- packages/preview3-shim/tsconfig.build.json | 11 +++++++ packages/preview3-shim/tsconfig.json | 21 ++++++++++++ pnpm-lock.yaml | 17 ++++++++-- pnpm-workspace.yaml | 1 + 39 files changed, 141 insertions(+), 65 deletions(-) create mode 100644 packages/preview3-shim/.gitignore rename packages/preview3-shim/{lib/nodejs/cli.js => src/nodejs/cli.ts} (85%) rename packages/preview3-shim/{lib/nodejs/clocks.js => src/nodejs/clocks.ts} (100%) rename packages/preview3-shim/{lib/nodejs/filesystem.js => src/nodejs/filesystem.ts} (100%) rename packages/preview3-shim/{lib/nodejs/filesystem/descriptor.js => src/nodejs/filesystem/descriptor.ts} (100%) rename packages/preview3-shim/{lib/nodejs/filesystem/error.js => src/nodejs/filesystem/error.ts} (95%) rename packages/preview3-shim/{lib/nodejs/filesystem/utils.js => src/nodejs/filesystem/utils.ts} (100%) rename packages/preview3-shim/{lib/nodejs/finalization.js => src/nodejs/finalization.ts} (88%) rename packages/preview3-shim/{lib/nodejs/future.js => src/nodejs/future.ts} (100%) rename packages/preview3-shim/{lib/nodejs/http.js => src/nodejs/http.ts} (100%) rename packages/preview3-shim/{lib/nodejs/http/client.js => src/nodejs/http/client.ts} (97%) rename packages/preview3-shim/{lib/nodejs/http/error.js => src/nodejs/http/error.ts} (92%) rename packages/preview3-shim/{lib/nodejs/http/fields.js => src/nodejs/http/fields.ts} (100%) rename packages/preview3-shim/{lib/nodejs/http/request.js => src/nodejs/http/request.ts} (99%) rename packages/preview3-shim/{lib/nodejs/http/response.js => src/nodejs/http/response.ts} (98%) rename packages/preview3-shim/{lib/nodejs/http/server.js => src/nodejs/http/server.ts} (98%) rename packages/preview3-shim/{lib/nodejs/index.js => src/nodejs/index.ts} (100%) rename packages/preview3-shim/{lib/nodejs/random.js => src/nodejs/random.ts} (100%) rename packages/preview3-shim/{lib/nodejs/sockets.js => src/nodejs/sockets.ts} (100%) rename packages/preview3-shim/{lib/nodejs/sockets/address.js => src/nodejs/sockets/address.ts} (100%) rename packages/preview3-shim/{lib/nodejs/sockets/error.js => src/nodejs/sockets/error.ts} (96%) rename packages/preview3-shim/{lib/nodejs/sockets/ip-name-lookup.js => src/nodejs/sockets/ip-name-lookup.ts} (100%) rename packages/preview3-shim/{lib/nodejs/sockets/tcp.js => src/nodejs/sockets/tcp.ts} (99%) rename packages/preview3-shim/{lib/nodejs/sockets/udp.js => src/nodejs/sockets/udp.ts} (100%) rename packages/preview3-shim/{lib/nodejs/stream.js => src/nodejs/stream.ts} (98%) rename packages/preview3-shim/{lib/nodejs/workers/cli-worker.js => src/nodejs/workers/cli-worker.ts} (100%) rename packages/preview3-shim/{lib/nodejs/workers/filesystem-worker.js => src/nodejs/workers/filesystem-worker.ts} (100%) rename packages/preview3-shim/{lib/nodejs/workers/http-worker.js => src/nodejs/workers/http-worker.ts} (97%) rename packages/preview3-shim/{lib/nodejs/workers/resource-worker.js => src/nodejs/workers/resource-worker.ts} (97%) rename packages/preview3-shim/{lib/nodejs/workers/tcp-worker.js => src/nodejs/workers/tcp-worker.ts} (93%) rename packages/preview3-shim/{lib/nodejs/workers/udp-worker.js => src/nodejs/workers/udp-worker.ts} (94%) create mode 100644 packages/preview3-shim/tsconfig.build.json create mode 100644 packages/preview3-shim/tsconfig.json diff --git a/packages/preview3-shim/.gitignore b/packages/preview3-shim/.gitignore new file mode 100644 index 000000000..d2fcdb5a1 --- /dev/null +++ b/packages/preview3-shim/.gitignore @@ -0,0 +1,2 @@ +# TypeScript build outputs +/dist/ diff --git a/packages/preview3-shim/package.json b/packages/preview3-shim/package.json index 3b41e3628..c477ec64d 100644 --- a/packages/preview3-shim/package.json +++ b/packages/preview3-shim/package.json @@ -23,35 +23,44 @@ }, "files": [ "types", - "lib" + "dist" ], "type": "module", - "types": "./types/index.d.ts", "exports": { ".": { - "types": "./types/index.d.ts", - "node": "./lib/nodejs/index.js" + "types": "./dist/nodejs/index.d.ts", + "node": "./dist/nodejs/index.js" }, "./*": { - "types": "./types/*.d.ts", - "node": "./lib/nodejs/*.js" + "types": "./dist/nodejs/*.d.ts", + "node": "./dist/nodejs/*.js" + }, + "./interfaces/*": { + "types": "./types/interfaces/*.d.ts" } }, "scripts": { - "compile:check": "tsc --noEmit types/index.d.ts", + "build": "tsc --project tsconfig.build.json", + "build:watch": "tsc --watch", + "types:check": "tsc --noEmit", "fmt": "oxfmt", "fmt:check": "oxfmt --check", "lint": "oxlint", "lint:fix": "oxlint --fix", + "pretest": "pnpm run build", "test": "vitest --run", - "bench": "vitest bench --run" + "prebench": "pnpm run build", + "bench": "vitest bench --run", + "prepack": "pnpm run build" }, "dependencies": { - "@bytecodealliance/preview2-shim": "^0.18.1" + "@bytecodealliance/preview2-shim": "^0.19.0" }, "devDependencies": { + "@types/node": "^24.12.4", "globals": "^17.6.0", + "typescript": "catalog:", "vite": "^8.0.16", - "vitest": "^4.1.0" + "vitest": "catalog:" } } diff --git a/packages/preview3-shim/lib/nodejs/cli.js b/packages/preview3-shim/src/nodejs/cli.ts similarity index 85% rename from packages/preview3-shim/lib/nodejs/cli.js rename to packages/preview3-shim/src/nodejs/cli.ts index 262b2d9f4..87b91c69f 100644 --- a/packages/preview3-shim/lib/nodejs/cli.js +++ b/packages/preview3-shim/src/nodejs/cli.ts @@ -5,9 +5,18 @@ import { ResourceWorker } from "./workers/resource-worker.js"; import { StreamReader, readableByteStreamFromReader } from "./stream.js"; import { future } from "./future.js"; -import { environment as environmentV2 } from "@bytecodealliance/preview2-shim/cli"; +import * as cliV2 from "@bytecodealliance/preview2-shim/cli"; -export { +type Preview2NodeCli = typeof cliV2 & { + _appendEnv: (env: Record) => void; + _setTerminalStdin: (terminalStdin: unknown) => void; + _setTerminalStdout: (terminalStdout: unknown) => void; + _setTerminalStderr: (terminalStderr: unknown) => void; +}; + +const nodeCliV2 = cliV2 as Preview2NodeCli; + +export const { _appendEnv, _setEnv, _setArgs, @@ -21,15 +30,15 @@ export { terminalStdin, terminalStdout, terminalStderr, -} from "@bytecodealliance/preview2-shim/cli"; +} = nodeCliV2; // `wasi:cli/environment` renamed `initial-cwd` to `get-initial-cwd` between // p2 and p3. Adapt the p2-shim shape to the p3 WIT member name while // re-exporting the unchanged members. export const environment = { - getEnvironment: environmentV2.getEnvironment, - getArguments: environmentV2.getArguments, - getInitialCwd: environmentV2.initialCwd, + getEnvironment: cliV2.environment.getEnvironment, + getArguments: cliV2.environment.getArguments, + getInitialCwd: cliV2.environment.initialCwd, }; let WORKER = null; diff --git a/packages/preview3-shim/lib/nodejs/clocks.js b/packages/preview3-shim/src/nodejs/clocks.ts similarity index 100% rename from packages/preview3-shim/lib/nodejs/clocks.js rename to packages/preview3-shim/src/nodejs/clocks.ts diff --git a/packages/preview3-shim/lib/nodejs/filesystem.js b/packages/preview3-shim/src/nodejs/filesystem.ts similarity index 100% rename from packages/preview3-shim/lib/nodejs/filesystem.js rename to packages/preview3-shim/src/nodejs/filesystem.ts diff --git a/packages/preview3-shim/lib/nodejs/filesystem/descriptor.js b/packages/preview3-shim/src/nodejs/filesystem/descriptor.ts similarity index 100% rename from packages/preview3-shim/lib/nodejs/filesystem/descriptor.js rename to packages/preview3-shim/src/nodejs/filesystem/descriptor.ts diff --git a/packages/preview3-shim/lib/nodejs/filesystem/error.js b/packages/preview3-shim/src/nodejs/filesystem/error.ts similarity index 95% rename from packages/preview3-shim/lib/nodejs/filesystem/error.js rename to packages/preview3-shim/src/nodejs/filesystem/error.ts index d9d55158b..d3262e6bf 100644 --- a/packages/preview3-shim/lib/nodejs/filesystem/error.js +++ b/packages/preview3-shim/src/nodejs/filesystem/error.ts @@ -56,6 +56,8 @@ function getErrorTag(e) { * Custom error for File operations with JCO compatible payload. */ export class FSError extends Error { + payload; + /** * @param {string} tag – machine‐readable error tag * @param {string} [message] – human‐readable message @@ -63,7 +65,7 @@ export class FSError extends Error { * @param {object} [opts] * @param {Error} [opts.cause] */ - constructor(tag, message, val, opts = {}) { + constructor(tag, message = undefined, val = undefined, opts: { cause?: unknown } = {}) { super(message ?? `Error: ${tag}`, { cause: opts.cause }); this.name = "FSError"; this.payload = val !== undefined ? { tag, val } : { tag }; diff --git a/packages/preview3-shim/lib/nodejs/filesystem/utils.js b/packages/preview3-shim/src/nodejs/filesystem/utils.ts similarity index 100% rename from packages/preview3-shim/lib/nodejs/filesystem/utils.js rename to packages/preview3-shim/src/nodejs/filesystem/utils.ts diff --git a/packages/preview3-shim/lib/nodejs/finalization.js b/packages/preview3-shim/src/nodejs/finalization.ts similarity index 88% rename from packages/preview3-shim/lib/nodejs/finalization.js rename to packages/preview3-shim/src/nodejs/finalization.ts index a685eaa8b..4b0a7db58 100644 --- a/packages/preview3-shim/lib/nodejs/finalization.js +++ b/packages/preview3-shim/src/nodejs/finalization.ts @@ -1,4 +1,4 @@ -let REGISTRY = null; +let REGISTRY: FinalizationRegistry<() => void> | null = null; function getRegistry() { if (!REGISTRY) { @@ -27,7 +27,7 @@ export function registerDispose(resource, parent = null, id, disposeFn) { return finalizer; } -export function earlyDispose(finalizer) { +export function earlyDispose(finalizer: () => void) { getRegistry().unregister(finalizer); finalizer(); } diff --git a/packages/preview3-shim/lib/nodejs/future.js b/packages/preview3-shim/src/nodejs/future.ts similarity index 100% rename from packages/preview3-shim/lib/nodejs/future.js rename to packages/preview3-shim/src/nodejs/future.ts diff --git a/packages/preview3-shim/lib/nodejs/http.js b/packages/preview3-shim/src/nodejs/http.ts similarity index 100% rename from packages/preview3-shim/lib/nodejs/http.js rename to packages/preview3-shim/src/nodejs/http.ts diff --git a/packages/preview3-shim/lib/nodejs/http/client.js b/packages/preview3-shim/src/nodejs/http/client.ts similarity index 97% rename from packages/preview3-shim/lib/nodejs/http/client.js rename to packages/preview3-shim/src/nodejs/http/client.ts index b0fabba65..801436bc1 100644 --- a/packages/preview3-shim/lib/nodejs/http/client.js +++ b/packages/preview3-shim/src/nodejs/http/client.ts @@ -1,3 +1,5 @@ +import { MessageChannel } from "node:worker_threads"; + import { ResourceWorker } from "../workers/resource-worker.js"; import { StreamReader, readableByteStreamFromReader } from "../stream.js"; import { FutureReader, future } from "../future.js"; @@ -63,7 +65,7 @@ export const client = { const { port1: tx, port2: rx } = new MessageChannel(); const { port1: transmitRx, port2: transmitTx } = new MessageChannel(); - const transfer = [rx, transmitTx]; + const transfer = [rx, transmitTx] as any[]; const stream = body ? readableByteStreamFromReader(body, { name: "request body" }) : undefined; if (stream) { transfer.unshift(stream); diff --git a/packages/preview3-shim/lib/nodejs/http/error.js b/packages/preview3-shim/src/nodejs/http/error.ts similarity index 92% rename from packages/preview3-shim/lib/nodejs/http/error.js rename to packages/preview3-shim/src/nodejs/http/error.ts index 079a0ac59..a175f137a 100644 --- a/packages/preview3-shim/lib/nodejs/http/error.js +++ b/packages/preview3-shim/src/nodejs/http/error.ts @@ -4,13 +4,15 @@ * https://bytecodealliance.github.io/jco/wit-type-representations.html#result-considerations-idiomatic-js-errors-for-host-implementations */ export class HttpError extends Error { + payload; + /** * Create a new WASI http error * @param {string} tag - The error tag/type * @param {string} [message] - Human-readable error message * @param {any} [val] - Optional value/data for the error */ - constructor(tag, message, val, opts = {}) { + constructor(tag, message = undefined, val = undefined, opts: { cause?: unknown } = {}) { super(message || `Error: ${tag}`, { cause: opts.cause }); this.name = "HttpError"; this.payload = val !== undefined ? { tag, val } : { tag }; @@ -57,7 +59,7 @@ export class HttpError extends Error { } } -function getFirstError(e) { +function getFirstError(e: any) { if (typeof e !== "object" || e === null) { return e; } diff --git a/packages/preview3-shim/lib/nodejs/http/fields.js b/packages/preview3-shim/src/nodejs/http/fields.ts similarity index 100% rename from packages/preview3-shim/lib/nodejs/http/fields.js rename to packages/preview3-shim/src/nodejs/http/fields.ts diff --git a/packages/preview3-shim/lib/nodejs/http/request.js b/packages/preview3-shim/src/nodejs/http/request.ts similarity index 99% rename from packages/preview3-shim/lib/nodejs/http/request.js rename to packages/preview3-shim/src/nodejs/http/request.ts index 0ff6d0a95..3f37c634a 100644 --- a/packages/preview3-shim/lib/nodejs/http/request.js +++ b/packages/preview3-shim/src/nodejs/http/request.ts @@ -209,7 +209,7 @@ export class Request { * @throws {HttpError} with payload.tag 'invalid-argument' for invalid arguments * */ - static new(headers, contents, trailers, options) { + static new(headers, contents, trailers, options): [Request, FutureReader] { if (options != null && !(options instanceof RequestOptions)) { throw new HttpError("invalid-argument", "options must be RequestOptions"); } @@ -541,7 +541,7 @@ function readOpts(remaining) { ? remaining : BigInt(DEFAULT_BYTE_STREAM_CHUNK_SIZE), ); - const opts = { count }; + const opts: { count: number; rejectLength?: number } = { count }; if (remaining <= BigInt(Number.MAX_SAFE_INTEGER)) { opts.rejectLength = Number(remaining); } diff --git a/packages/preview3-shim/lib/nodejs/http/response.js b/packages/preview3-shim/src/nodejs/http/response.ts similarity index 98% rename from packages/preview3-shim/lib/nodejs/http/response.js rename to packages/preview3-shim/src/nodejs/http/response.ts index e9f7d0613..e8834752e 100644 --- a/packages/preview3-shim/lib/nodejs/http/response.js +++ b/packages/preview3-shim/src/nodejs/http/response.ts @@ -48,7 +48,7 @@ export class Response { * @returns {{ res: Response, future: FutureReader }} * @throws {HttpError} with payload.tag 'invalid-argument' for invalid arguments */ - static new(headers, contents, trailers) { + static new(headers, contents, trailers): [Response, FutureReader] { if (!(headers instanceof Fields)) { throw new HttpError("invalid-argument", "headers must be Fields"); } diff --git a/packages/preview3-shim/lib/nodejs/http/server.js b/packages/preview3-shim/src/nodejs/http/server.ts similarity index 98% rename from packages/preview3-shim/lib/nodejs/http/server.js rename to packages/preview3-shim/src/nodejs/http/server.ts index e811dae93..3ac878537 100644 --- a/packages/preview3-shim/lib/nodejs/http/server.js +++ b/packages/preview3-shim/src/nodejs/http/server.ts @@ -1,4 +1,5 @@ import { EventEmitter } from "node:events"; +import { MessageChannel } from "node:worker_threads"; import { ResourceWorker } from "../workers/resource-worker.js"; import { StreamReader, readableByteStreamFromReader } from "../stream.js"; diff --git a/packages/preview3-shim/lib/nodejs/index.js b/packages/preview3-shim/src/nodejs/index.ts similarity index 100% rename from packages/preview3-shim/lib/nodejs/index.js rename to packages/preview3-shim/src/nodejs/index.ts diff --git a/packages/preview3-shim/lib/nodejs/random.js b/packages/preview3-shim/src/nodejs/random.ts similarity index 100% rename from packages/preview3-shim/lib/nodejs/random.js rename to packages/preview3-shim/src/nodejs/random.ts diff --git a/packages/preview3-shim/lib/nodejs/sockets.js b/packages/preview3-shim/src/nodejs/sockets.ts similarity index 100% rename from packages/preview3-shim/lib/nodejs/sockets.js rename to packages/preview3-shim/src/nodejs/sockets.ts diff --git a/packages/preview3-shim/lib/nodejs/sockets/address.js b/packages/preview3-shim/src/nodejs/sockets/address.ts similarity index 100% rename from packages/preview3-shim/lib/nodejs/sockets/address.js rename to packages/preview3-shim/src/nodejs/sockets/address.ts diff --git a/packages/preview3-shim/lib/nodejs/sockets/error.js b/packages/preview3-shim/src/nodejs/sockets/error.ts similarity index 96% rename from packages/preview3-shim/lib/nodejs/sockets/error.js rename to packages/preview3-shim/src/nodejs/sockets/error.ts index 5d2a8f5a2..3bec26163 100644 --- a/packages/preview3-shim/lib/nodejs/sockets/error.js +++ b/packages/preview3-shim/src/nodejs/sockets/error.ts @@ -68,12 +68,14 @@ export const CODE_MAP = { * https://bytecodealliance.github.io/jco/wit-type-representations.html#result-considerations-idiomatic-js-errors-for-host-implementations */ export class SocketError extends Error { + payload; + /** * @param {string} tag – machine‐readable error tag * @param {string} [message] – human‐readable message * @param {any} [val] – optional extra data */ - constructor(tag, message, val, opts = {}) { + constructor(tag, message = undefined, val = undefined, opts: { cause?: unknown } = {}) { super(message ?? `Error: ${tag}`, { cause: opts.cause }); this.name = "SocketError"; this.payload = val !== undefined ? { tag, val } : { tag }; @@ -88,9 +90,7 @@ export class SocketError extends Error { return err; } - let tag, - message = undefined, - val = undefined; + let tag, message, val; if (typeof err === "number") { tag = CODE_MAP[err] ?? "other"; diff --git a/packages/preview3-shim/lib/nodejs/sockets/ip-name-lookup.js b/packages/preview3-shim/src/nodejs/sockets/ip-name-lookup.ts similarity index 100% rename from packages/preview3-shim/lib/nodejs/sockets/ip-name-lookup.js rename to packages/preview3-shim/src/nodejs/sockets/ip-name-lookup.ts diff --git a/packages/preview3-shim/lib/nodejs/sockets/tcp.js b/packages/preview3-shim/src/nodejs/sockets/tcp.ts similarity index 99% rename from packages/preview3-shim/lib/nodejs/sockets/tcp.js rename to packages/preview3-shim/src/nodejs/sockets/tcp.ts index 7c5ce2282..f3e619065 100644 --- a/packages/preview3-shim/lib/nodejs/sockets/tcp.js +++ b/packages/preview3-shim/src/nodejs/sockets/tcp.ts @@ -93,6 +93,7 @@ export class TcpSocket { hopLimit: 1, receiveBufferSize: 65_536n, sendBufferSize: 65_536n, + listenBacklogSize: 128n, }; /** diff --git a/packages/preview3-shim/lib/nodejs/sockets/udp.js b/packages/preview3-shim/src/nodejs/sockets/udp.ts similarity index 100% rename from packages/preview3-shim/lib/nodejs/sockets/udp.js rename to packages/preview3-shim/src/nodejs/sockets/udp.ts diff --git a/packages/preview3-shim/lib/nodejs/stream.js b/packages/preview3-shim/src/nodejs/stream.ts similarity index 98% rename from packages/preview3-shim/lib/nodejs/stream.js rename to packages/preview3-shim/src/nodejs/stream.ts index eaad33218..90b7eb755 100644 --- a/packages/preview3-shim/lib/nodejs/stream.js +++ b/packages/preview3-shim/src/nodejs/stream.ts @@ -177,7 +177,7 @@ function assertByte(value) { * expect(done).toBeNull(); * */ -export function stream(opts = {}) { +export function stream(opts: { readableHWM?: number; writableHWM?: number } = {}) { const { readableHWM = 64 * 1024, writableHWM = 64 * 1024 } = opts; const transform = new TransformStream( @@ -206,7 +206,7 @@ export class StreamReader { * @param {AsyncIterable|Iterable} source - An async or sync iterable to consume e.g. ReadableStream, async generator, array. * @throws {Error} If the provided source does not implement `[Symbol.asyncIterator]` or `[Symbol.iterator]`. */ - constructor(source, opts = {}) { + constructor(source, opts: { preventCancel?: boolean } = {}) { if ( !source || (typeof source[Symbol.asyncIterator] !== "function" && diff --git a/packages/preview3-shim/lib/nodejs/workers/cli-worker.js b/packages/preview3-shim/src/nodejs/workers/cli-worker.ts similarity index 100% rename from packages/preview3-shim/lib/nodejs/workers/cli-worker.js rename to packages/preview3-shim/src/nodejs/workers/cli-worker.ts diff --git a/packages/preview3-shim/lib/nodejs/workers/filesystem-worker.js b/packages/preview3-shim/src/nodejs/workers/filesystem-worker.ts similarity index 100% rename from packages/preview3-shim/lib/nodejs/workers/filesystem-worker.js rename to packages/preview3-shim/src/nodejs/workers/filesystem-worker.ts diff --git a/packages/preview3-shim/lib/nodejs/workers/http-worker.js b/packages/preview3-shim/src/nodejs/workers/http-worker.ts similarity index 97% rename from packages/preview3-shim/lib/nodejs/workers/http-worker.js rename to packages/preview3-shim/src/nodejs/workers/http-worker.ts index 43d1cf4a8..3ff18b6fa 100644 --- a/packages/preview3-shim/lib/nodejs/workers/http-worker.js +++ b/packages/preview3-shim/src/nodejs/workers/http-worker.ts @@ -1,5 +1,6 @@ import { Readable, Writable, PassThrough } from "node:stream"; import { pipeline } from "stream/promises"; +import { MessageChannel } from "node:worker_threads"; import { createServer } from "node:http"; import { request as httpRequest, Agent as HttpAgent } from "node:http"; @@ -21,6 +22,9 @@ Router() .op("client-request", handleRequest); class Queue { + _items = []; + _resolvers = []; + constructor() { this._items = []; this._resolvers = []; @@ -62,7 +66,7 @@ async function handleHttpServerStart({ port, host }) { await new Promise((resolve, reject) => { server.on("error", reject); - server.listen(port, host, resolve); + server.listen(port, host, () => resolve(undefined)); }); servers.set(serverId, { server, pending, inflight }); @@ -343,7 +347,7 @@ function endRequest(req) { req.once("close", onClose); try { - req.end(() => settle(resolve)); + req.end(() => settle(resolve, undefined)); } catch (err) { settle(reject, err); } @@ -410,7 +414,7 @@ const toObject = (entries) => { const encoder = new TextEncoder(); -const toEntries = (obj) => { +const toEntries = (obj: Record) => { return Object.entries(obj).flatMap(([k, v]) => Array.isArray(v) ? v.map((val) => [k, encoder.encode(val)]) : [[k, encoder.encode(v)]], ); diff --git a/packages/preview3-shim/lib/nodejs/workers/resource-worker.js b/packages/preview3-shim/src/nodejs/workers/resource-worker.ts similarity index 97% rename from packages/preview3-shim/lib/nodejs/workers/resource-worker.js rename to packages/preview3-shim/src/nodejs/workers/resource-worker.ts index 06a59d268..55786857c 100644 --- a/packages/preview3-shim/lib/nodejs/workers/resource-worker.js +++ b/packages/preview3-shim/src/nodejs/workers/resource-worker.ts @@ -144,12 +144,12 @@ export function Router() { }; } -function serializeError(err) { +function serializeError(err: any) { if (!(err instanceof Error)) { return err; } - const serialized = { + const serialized: any = { __resourceWorkerError: true, name: err.name, message: err.message, @@ -167,7 +167,7 @@ function serializeError(err) { return serialized; } -function deserializeError(err) { +function deserializeError(err: any) { if (!err || typeof err !== "object" || err.__resourceWorkerError !== true) { return err; } diff --git a/packages/preview3-shim/lib/nodejs/workers/tcp-worker.js b/packages/preview3-shim/src/nodejs/workers/tcp-worker.ts similarity index 93% rename from packages/preview3-shim/lib/nodejs/workers/tcp-worker.js rename to packages/preview3-shim/src/nodejs/workers/tcp-worker.ts index 6d89ff60c..fb3afda58 100644 --- a/packages/preview3-shim/lib/nodejs/workers/tcp-worker.js +++ b/packages/preview3-shim/src/nodejs/workers/tcp-worker.ts @@ -8,10 +8,10 @@ import { serializeIpAddress, makeIpAddress, ipAddressConflict } from "../sockets import { SocketError } from "../sockets/error.js"; import process from "node:process"; -const { TCP, constants: TCPConstants } = process.binding("tcp_wrap"); +const { TCP, constants: TCPConstants } = (process as any).binding("tcp_wrap"); // Socket instances stored by ID -const sockets = new Map(); +const sockets = new Map(); // Unique IDs for sockets let NEXT_SOCKET_ID = 0n; @@ -69,12 +69,12 @@ async function handleTcpBind({ socketId, localAddress }) { ); if (hasConflict) { - const err = new Error("EADDRINUSE"); + const err = new Error("EADDRINUSE") as NodeJS.ErrnoException; err.code = "EADDRINUSE"; throw err; } - await new Promise((resolve, reject) => { + await new Promise((resolve, reject) => { let code; if (family === "ipv6") { code = handle.bind6(address, port, TCPConstants.UV_TCP_IPV6ONLY); @@ -89,7 +89,7 @@ async function handleTcpBind({ socketId, localAddress }) { } }); - const out = {}; + const out: any = {}; const code = handle.getsockname(out); if (code !== 0) { throw SocketError.from(-code); @@ -107,7 +107,7 @@ async function handleTcpConnect({ socketId, remoteAddress }) { handle: socket.handle, pauseOnCreate: true, allowHalfOpen: true, - })); + } as any)); const onConnect = once(tcp, "connect"); const onError = once(tcp, "error").then(([err]) => { @@ -148,7 +148,7 @@ async function handleTcpListen({ socketId, stream }) { conn.allowHalfOpen = true; const id = NEXT_SOCKET_ID++; sockets.set(id, { - handle: conn._handle, + handle: (conn as any)._handle, family, backlog, tcp: conn, @@ -188,7 +188,7 @@ async function handleTcpReceive({ socketId, stream }) { const { tcp } = socket; try { - await new Promise((resolve, reject) => { + await new Promise((resolve, reject) => { let settled = false; let pending = Promise.resolve(); @@ -197,7 +197,7 @@ async function handleTcpReceive({ socketId, stream }) { tcp.off("end", onEnd); tcp.off("error", onError); }; - const settle = (err) => { + const settle = (err = null) => { if (settled) { return; } @@ -276,11 +276,11 @@ function cleanupDisposedSocket(socketId, socket) { async function handleGetLocalAddress({ socketId }) { const socket = sockets.get(socketId); - const out = {}; + const out: any = {}; const code = socket.handle.getsockname(out); if (code !== 0) { - throw new SocketError.from(-code); + throw SocketError.from(-code); } return makeIpAddress(out.family.toLowerCase(), out.address, out.port); @@ -288,11 +288,11 @@ async function handleGetLocalAddress({ socketId }) { async function handleGetRemoteAddress({ socketId }) { const socket = sockets.get(socketId); - const out = {}; + const out: any = {}; const code = socket.handle.getpeername(out); if (code !== 0) { - throw new SocketError.from(-code); + throw SocketError.from(-code); } return makeIpAddress(out.family.toLowerCase(), out.address, out.port); @@ -309,7 +309,7 @@ async function handleTcpSetKeepAlive({ socketId, keepAliveEnabled, keepAliveIdle const code = socket.handle.setKeepAlive(keepAliveEnabled, time); if (code !== 0) { - throw mapErrorCode(-code); + throw SocketError.from(-code); } } @@ -344,9 +344,9 @@ function handleTcpDispose({ socketId }) { let _recvBufferSize, _sendBufferSize; async function getDefaultBufferSizes() { - var s = new Socket(); + var s: any = new Socket(); s.bind(0); - await new Promise((resolve, reject) => { + await new Promise((resolve, reject) => { s.once("error", reject); s.once("listening", resolve); }); diff --git a/packages/preview3-shim/lib/nodejs/workers/udp-worker.js b/packages/preview3-shim/src/nodejs/workers/udp-worker.ts similarity index 94% rename from packages/preview3-shim/lib/nodejs/workers/udp-worker.js rename to packages/preview3-shim/src/nodejs/workers/udp-worker.ts index 96adf6644..7d472f298 100644 --- a/packages/preview3-shim/lib/nodejs/workers/udp-worker.js +++ b/packages/preview3-shim/src/nodejs/workers/udp-worker.ts @@ -10,7 +10,7 @@ import { import dgram from "node:dgram"; -const sockets = new Map(); +const sockets = new Map(); // Unique IDs for sockets let NEXT_SOCKET_ID = 0n; @@ -38,7 +38,7 @@ Router() function handleCreate({ family }) { const socketId = NEXT_SOCKET_ID++; - const socket = { + const socket: any = { family, connected: null, localAddress: null, @@ -73,7 +73,7 @@ async function handleBind({ socketId, localAddress }) { ); if (hasConflict) { - const err = new Error("EADDRINUSE"); + const err = new Error("EADDRINUSE") as NodeJS.ErrnoException; err.code = "EADDRINUSE"; throw err; } @@ -103,7 +103,7 @@ async function handleConnect({ socketId, remoteAddress }) { if (socket.connected) { const localAddress = preserveLocalAddress ? socket.localAddress : null; - await new Promise((resolve) => socket.udp.close(resolve)); + await new Promise((resolve) => socket.udp.close(resolve)); socket.udp = createSocket(socket); if (localAddress) { await handleBind({ socketId, localAddress }); @@ -115,7 +115,7 @@ async function handleConnect({ socketId, remoteAddress }) { const addr = serializeIpAddress(remoteAddress); const port = remoteAddress.val.port; - await new Promise((resolve, reject) => { + await new Promise((resolve, reject) => { socket.udp.connect(port, addr, (err) => (err ? reject(err) : resolve())); }); const boundAddr = socket.udp.address(); @@ -133,7 +133,7 @@ async function handleSend({ socketId, data, remoteAddress }) { const socket = sockets.get(socketId); const isConnected = socket.connected != null; - await new Promise((resolve, reject) => { + await new Promise((resolve, reject) => { if (isConnected) { socket.udp.send(data, (err) => (err ? reject(err) : resolve())); } else { diff --git a/packages/preview3-shim/test/nop-worker.js b/packages/preview3-shim/test/nop-worker.js index 0f3ef77cf..929eaceee 100644 --- a/packages/preview3-shim/test/nop-worker.js +++ b/packages/preview3-shim/test/nop-worker.js @@ -1,4 +1,4 @@ -import { Router } from "../lib/nodejs/workers/resource-worker.js"; +import { Router } from "../dist/nodejs/workers/resource-worker.js"; Router() .op("nop", () => { diff --git a/packages/preview3-shim/test/resource-worker.bench.js b/packages/preview3-shim/test/resource-worker.bench.js index 724a31628..9c9a5440c 100644 --- a/packages/preview3-shim/test/resource-worker.bench.js +++ b/packages/preview3-shim/test/resource-worker.bench.js @@ -1,5 +1,5 @@ import { describe, bench } from "vitest"; -import { ResourceWorker } from "../lib/nodejs/workers/resource-worker.js"; +import { ResourceWorker } from "../dist/nodejs/workers/resource-worker.js"; const _worker = new ResourceWorker(new URL("./nop-worker.js", import.meta.url)); diff --git a/packages/preview3-shim/test/resource-worker.test.js b/packages/preview3-shim/test/resource-worker.test.js index 3a5f7f416..4673dde64 100644 --- a/packages/preview3-shim/test/resource-worker.test.js +++ b/packages/preview3-shim/test/resource-worker.test.js @@ -1,5 +1,5 @@ import { describe, test, expect } from "vitest"; -import { ResourceWorker } from "../lib/nodejs/workers/resource-worker.js"; +import { ResourceWorker } from "../dist/nodejs/workers/resource-worker.js"; const _worker = new ResourceWorker(new URL("./nop-worker.js", import.meta.url)); diff --git a/packages/preview3-shim/tsconfig.build.json b/packages/preview3-shim/tsconfig.build.json new file mode 100644 index 000000000..5eec24ca9 --- /dev/null +++ b/packages/preview3-shim/tsconfig.build.json @@ -0,0 +1,11 @@ +{ + "extends": "./tsconfig.json", + "exclude": ["test/**/*"], + "compilerOptions": { + "rootDir": "src/", + "declaration": true, + "declarationMap": false, + "sourceMap": false, + "noEmit": false + } +} diff --git a/packages/preview3-shim/tsconfig.json b/packages/preview3-shim/tsconfig.json new file mode 100644 index 000000000..6caac5bee --- /dev/null +++ b/packages/preview3-shim/tsconfig.json @@ -0,0 +1,21 @@ +{ + "include": ["src/**/*"], + "compilerOptions": { + "outDir": "dist", + "target": "ES2022", + "lib": ["ESNext", "DOM"], + "types": ["node"], + "module": "nodenext", + "moduleResolution": "nodenext", + "strict": true, + "noImplicitAny": false, + "strictNullChecks": false, + "useUnknownInCatchVariables": false, + "declaration": true, + "declarationMap": true, + "sourceMap": true, + "esModuleInterop": true, + "skipLibCheck": true, + "noEmit": true + } +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index a0fa12f28..2f7a7f7ed 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -405,17 +405,23 @@ importers: packages/preview3-shim: dependencies: '@bytecodealliance/preview2-shim': - specifier: ^0.18.1 - version: 0.18.1 + specifier: ^0.19.0 + version: 0.19.0 devDependencies: + '@types/node': + specifier: ^24.12.4 + version: 24.12.4 globals: specifier: ^17.6.0 version: 17.6.0 + typescript: + specifier: 'catalog:' + version: 6.0.3 vite: specifier: ^8.0.16 version: 8.0.16(@types/node@24.12.4)(esbuild@0.27.7)(jiti@2.6.1)(terser@5.48.0) vitest: - specifier: ^4.1.0 + specifier: 'catalog:' version: 4.1.6(@types/node@24.12.4)(vite@8.0.16(@types/node@24.12.4)(esbuild@0.27.7)(jiti@2.6.1)(terser@5.48.0)) packages: @@ -473,6 +479,9 @@ packages: '@bytecodealliance/preview2-shim@0.18.1': resolution: {integrity: sha512-8+QEByJTHusG1JkYQNUwOZO0ZvP3zQJD7UVYcyRh8OedKfVls1VuPw/HfSuK0ustslzAkGz7uQCkaBbW+fal9w==} + '@bytecodealliance/preview2-shim@0.19.0': + resolution: {integrity: sha512-OSUlcM62fXLuzYP0DjBn/SwjKMZ/y/2PMXZ8v5cRiiFcroauntlPRl/oCnx0xYjYiqdYvE0PY50VCNutll0xOw==} + '@bytecodealliance/preview3-shim@0.1.2': resolution: {integrity: sha512-5twfO5h6zVkJ2QLxrLR21qyLS3jY35XvY0f+jZV4e9FkI6qa2RdPfNDgC50HYhGCtWmbH4TlN1puIyHfEemSNg==} @@ -3900,6 +3909,8 @@ snapshots: '@bytecodealliance/preview2-shim@0.18.1': {} + '@bytecodealliance/preview2-shim@0.19.0': {} + '@bytecodealliance/preview3-shim@0.1.2': dependencies: '@bytecodealliance/preview2-shim': 0.17.9 diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index ebd7d62b3..86ab30287 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -36,6 +36,7 @@ catalog: minimumReleaseAgeExclude: - '@bytecodealliance/componentize-js@0.21.0' - '@bytecodealliance/jco-transpile@0.3.3' + - '@bytecodealliance/preview2-shim@0.19.0' - '@bytecodealliance/preview3-shim@0.1.2' - '@puppeteer/browsers@3.0.4' - puppeteer-core@25.1.0