@ai-ecoverse/slicc-kernel 1.29.1 → 1.30.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +28 -5
- package/dist/driver-worker.js.map +2 -2
- package/dist/driver.js.map +2 -2
- package/dist/kernel-worker.js +59 -12
- package/dist/kernel-worker.js.map +3 -3
- package/dist/node-driver-worker.js.map +2 -2
- package/dist/node-process-worker.js +106 -36
- package/dist/node-process-worker.js.map +3 -3
- package/dist/node.js +59 -12
- package/dist/node.js.map +3 -3
- package/dist/process-worker.js +106 -36
- package/dist/process-worker.js.map +3 -3
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -140,15 +140,38 @@ A WASI preview1 or WASIX program (Zig, Rust, Go, wasi-libc or wasix-libc C) has
|
|
|
140
140
|
{ "slicc": { "abi": "wasi", "commands": { "rg": { "wasm": "bin/rg.wasm" }, "rustc": { "script": "bin/rustc" } } } }
|
|
141
141
|
```
|
|
142
142
|
|
|
143
|
-
Entries may also set `argv0`, `args` and `env`, and a package can set `slicc.env` for all of its commands. An entry with `"argv0Path": true` gets the absolute path it was run by as `argv[0]` when that path is a link outside `/bin` and `/usr/bin` to the command, as a venv's `bin/python` is (the `#!` line of a script naming such a link included), so it can find what sits beside that link; other entries keep their `argv0`. In `env`, `${package}` is the package directory, `${cwd}` the process's working directory, and `${NAME}` the caller's `NAME` when the program starts (a default naming an unset variable is left out); a relative path that exists in the package (`lib/python3.14`, `./`) becomes that absolute path. The caller's environment wins over these defaults; a `null` value removes the variable for the command, after the caller's environment is applied (a host-networked program can drop the kernel's proxy settings that way), and a command entry can set a variable its package's `slicc.env` removes. The first package to define a name wins. `sh` runs bash as `sh` unless a package provides its own. The installed commands appear as executables in a virtual `/usr/bin` and `/bin`, so `PATH` lookups, `command -v` and `ls /usr/bin` work without writing anything to OPFS. A process can also run a program by the path of its glue when the `.wasm` sits next to it, a wasm module by its own path (as a WASI program), and a script through its `#!` line (including `#!/usr/bin/env name`). Executing any other file fails with `ENOEXEC`, so bash runs it as a shell script, as POSIX shells do. Commands also come from pnpm's global directory. Every process gets `PNPM_HOME=/home/.local/share/pnpm`, unless the embedder sets its own, and has `$PNPM_HOME/bin` on `PATH`. The kernel scans each of pnpm's global install groups (`$PNPM_HOME/global/*/<group>/node_modules`) after `/node_modules`, which wins when both provide a command. The catalog is re-read whenever anything under either changes, so `pnpm add -g @ai-ecoverse/wasi-ripgrep` makes `rg` work in the same shell, and `pnpm remove -g` removes it again.
|
|
143
|
+
Entries may also set `argv0`, `args` and `env`, and a package can set `slicc.env` for all of its commands. A WASI entry with `"preopenRoot": true` also gets `/` as a preopen (see [WASI programs](#wasi-programs)). An entry with `"argv0Path": true` gets the absolute path it was run by as `argv[0]` when that path is a link outside `/bin` and `/usr/bin` to the command, as a venv's `bin/python` is (the `#!` line of a script naming such a link included), so it can find what sits beside that link; other entries keep their `argv0`. In `env`, `${package}` is the package directory, `${cwd}` the process's working directory, and `${NAME}` the caller's `NAME` when the program starts (a default naming an unset variable is left out); a relative path that exists in the package (`lib/python3.14`, `./`) becomes that absolute path. The caller's environment wins over these defaults; a `null` value removes the variable for the command, after the caller's environment is applied (a host-networked program can drop the kernel's proxy settings that way), and a command entry can set a variable its package's `slicc.env` removes. The first package to define a name wins. `sh` runs bash as `sh` unless a package provides its own. The installed commands appear as executables in a virtual `/usr/bin` and `/bin`, so `PATH` lookups, `command -v` and `ls /usr/bin` work without writing anything to OPFS. A process can also run a program by the path of its glue when the `.wasm` sits next to it, a wasm module by its own path (as a WASI program), and a script through its `#!` line (including `#!/usr/bin/env name`). Executing any other file fails with `ENOEXEC`, so bash runs it as a shell script, as POSIX shells do. Commands also come from pnpm's global directory. Every process gets `PNPM_HOME=/home/.local/share/pnpm`, unless the embedder sets its own, and has `$PNPM_HOME/bin` on `PATH`. The kernel scans each of pnpm's global install groups (`$PNPM_HOME/global/*/<group>/node_modules`) after `/node_modules`, which wins when both provide a command. The catalog is re-read whenever anything under either changes, so `pnpm add -g @ai-ecoverse/wasi-ripgrep` makes `rg` work in the same shell, and `pnpm remove -g` removes it again.
|
|
144
144
|
|
|
145
145
|
### WASI programs
|
|
146
146
|
|
|
147
|
-
A WASI program runs in a process worker of its own like an Emscripten one, against the same kernel: its descriptors, pipes, terminals and job control are the kernel's, and its files are OPFS. Preopens
|
|
147
|
+
A WASI program runs in a process worker of its own like an Emscripten one, against the same kernel: its descriptors, pipes, terminals and job control are the kernel's, and its files are OPFS. **Preopens**, in order:
|
|
148
|
+
1. `.`, the cwd, as fd 3, which Zig's std takes for its cwd;
|
|
149
|
+
2. `/dev` and every top-level directory, plus the virtual `/usr` and `/bin`, sorted by name.
|
|
150
|
+
|
|
151
|
+
Every WASI program sees `/` through the cwd.
|
|
152
|
+
|
|
153
|
+
**`preopenRoot`.** A command whose manifest entry sets `"preopenRoot": true` gets two more preopens after those:
|
|
154
|
+
3. `/`, the root;
|
|
155
|
+
4. `./`, the cwd again.
|
|
156
|
+
|
|
157
|
+
That's for programs that walk to the root, such as Go's (`GOOS=wasip1`) and esbuild's resolver. The order serves each runtime:
|
|
158
|
+
- **Go** takes its working directory from `PWD`, which every process gets, and resolves absolute paths against the longest matching preopen name. So `os.ReadDir("/")`, `filepath.Abs("../..")` and walking up to the root work. Without `preopenRoot`, nothing is named `/` and they fail with `EBADF`.
|
|
159
|
+
- **wasi-libc** (C, and Rust's `wasm32-wasip1`) reads `.`, `/` and `./` as the same empty prefix, and the last one wins. So the trailing `./` keeps relative paths on the cwd.
|
|
160
|
+
- **Zig** keeps fd 3, and a second `.` would stop it from starting.
|
|
161
|
+
|
|
162
|
+
**Working directory.** wasi-libc's own `getcwd()` stays `/` (Rust's `current_dir()`, `canonicalize(".")`) in either layout, because the C library starts with a working directory of `/` and no runtime can change it. A wasi-libc program that needs its real directory takes it from `PWD` (`set_current_dir($PWD)` at start); relative paths are the cwd either way. WASIX programs ask the kernel for their cwd and get the real one.
|
|
163
|
+
|
|
164
|
+
**Descriptor numbers.** Preopens take consecutive descriptors from 3, since WASI libraries look for them until the first gap:
|
|
165
|
+
- without `preopenRoot`: fds 3 through 3 + *n*, *n* being the number of top-level directories, `/dev`, `/usr` and `/bin` together;
|
|
166
|
+
- with it: two more, through 3 + *n* + 2.
|
|
167
|
+
|
|
168
|
+
A descriptor a program inherits at one of those numbers (from bash's `3<file`, or a `posix_spawn` file action) moves to the first free number above them. One above the range keeps its number. A command that takes descriptors by number from its caller should leave `preopenRoot` off, which keeps the shorter range.
|
|
169
|
+
|
|
170
|
+
On top of preview1 a WASI program gets:
|
|
148
171
|
|
|
149
172
|
- **Threads**: `wasi.thread-spawn` (wasm32-wasip1-threads) and WASIX `thread_spawn_v2` start a worker per thread on the process's shared memory, sized from the module's own import (a 2 GiB maximum when the engine cannot reserve more). The threads share one descriptor table; `exit` or a trap in any thread ends the process. At most 64 threads per process; `SLICC_WASM_THREADS` sets another cap, up to 256.
|
|
150
173
|
- **WASIX** (a module importing `wasix_32v1`): fork and setjmp/longjmp through Asyncify (the module is built with `wasm-opt --asyncify`), exec, `posix_spawn`, `waitpid`, pipes, `dup2`, signal handlers and interval timers, terminal modes, and dynamic linking: a position-independent main module loads side modules with `dlopen` from `LD_LIBRARY_PATH`, its runtime path, `/lib`, `/usr/lib` and `/usr/local/lib`.
|
|
151
|
-
- **Sockets**: the WASIX socket calls (`sock_open`, `bind`, `listen`, `connect`, `accept`, options, local and peer names) are the kernel's loopback sockets, and preview1's `sock_recv` / `sock_send` / `sock_shutdown` work on them and on inherited ones. Writing to a socket whose peer is gone fails with `EPIPE`, through `fd_write` as through `sock_send`, as if `MSG_NOSIGNAL` were set, since a WASI program cannot ignore `SIGPIPE`; a pipe or terminal whose reader is gone still ends the program with status 141. HTTP and HTTPS leave through the realm proxy that `https_proxy` names, as for any other program; `resolve` answers
|
|
174
|
+
- **Sockets**: the WASIX socket calls (`sock_open`, `bind`, `listen`, `connect`, `accept`, options, local and peer names) are the kernel's loopback sockets, and preview1's `sock_recv` / `sock_send` / `sock_shutdown` work on them and on inherited ones. Writing to a socket whose peer is gone fails with `EPIPE`, through `fd_write` as through `sock_send`, as if `MSG_NOSIGNAL` were set, since a WASI program cannot ignore `SIGPIPE`; a pipe or terminal whose reader is gone still ends the program with status 141. HTTP and HTTPS leave through the realm proxy that `https_proxy` names, as for any other program; `resolve` answers `/etc/hosts` names and literal addresses, and the [uplink](#uplink)'s names.
|
|
152
175
|
- **Diagnostics**: a trap ends the program with 134 and its message on stderr; with `SLICC_WASM_BACKTRACE=1` the wasm frames follow, named from the module's name section, or from a sidecar for a module shipped without one (`<module>.names` beside it, or the same path in a `<package>-names` package). `SLICC_WASI_STATS=1` makes a program print its calls, counted and timed, as it ends.
|
|
153
176
|
|
|
154
177
|
### Program imports
|
|
@@ -290,7 +313,7 @@ Directories are renamed with `FileSystemHandle.move()` where available, else by
|
|
|
290
313
|
- An optional `mount({ source, options })` handler validates the source.
|
|
291
314
|
- Errors carry a POSIX `code`.
|
|
292
315
|
- `@ai-ecoverse/slicc-kernel/driver` exports the types and `fsError`.
|
|
293
|
-
- **Capabilities:** `readonly`, `symlinks`, `chmod`, `ranges`, `maxIo` (the largest read or write per message), `maxFile`, `listingStats`, and `attrTtl`/`entryTtl` (in ms, default 1000). `ranges` (driver protocol 1.1) promises that a write lands in the file at once, with no copy of the whole file on `open` or `release`, and that `setattr` takes `size`.
|
|
316
|
+
- **Capabilities:** `readonly`, `symlinks`, `chmod`, `ranges`, `maxIo` (the largest read or write per message), `maxFile`, `listingStats`, `linkTimes`, and `attrTtl`/`entryTtl` (in ms, default 1000). `linkTimes` promises that `setattr` with `mtime` on a symlink sets the link's own time. Without it, setting a link's own times (`touch -h`, `utimensat` with `AT_SYMLINK_NOFOLLOW`) fails with `EOPNOTSUPP` and never reaches the target. tmpfs has it; hostfs does not. Setting times through a link follows it in the kernel, so `setattr` gets the target. `ranges` (driver protocol 1.1) promises that a write lands in the file at once, with no copy of the whole file on `open` or `release`, and that `setattr` takes `size`.
|
|
294
317
|
- **Caching:** the kernel caches attributes and listings for those TTLs, and a driver can push `invalidate` for changes made outside.
|
|
295
318
|
- **File contents:** on a mount with `ranges`, as `tmpfs` is, and on the root file system when it is in OPFS (in a browser with sync access handles) or an in-memory root, a program reads and writes a file in 64 KiB pages: reads come from the driver 1 MiB at a time, and changed pages go back in 1 MiB runs once 8 MiB have changed, at `fsync`, and when the file is closed (from the kernel's own descriptors also 250 ms after a write). A file of any size the mount can hold works, with memory to spare for about one more copy of it. In OPFS a write opens a sync access handle for just that write. Elsewhere (`fsa` mounts, `hostfs` with an older proxy, and a root outside OPFS), file contents are read whole when a program opens a file and written back when it closes it. Both give close-to-open consistency, as NFS has.
|
|
296
319
|
- **Rules on a mount:**
|
|
@@ -376,7 +399,7 @@ OPFS stores names, bytes, sizes and modification times, nothing else. Everything
|
|
|
376
399
|
- mode bits (`chmod`);
|
|
377
400
|
- access and change times, and a modification time set explicitly with `utime` (it holds until the file is written again);
|
|
378
401
|
- inode numbers that stay stable across renames;
|
|
379
|
-
- symbolic links (`symlink`, `readlink`, `lstat`, and following them in paths), which exist only in the sidecar.
|
|
402
|
+
- symbolic links (`symlink`, `readlink`, `lstat`, and following them in paths), which exist only in the sidecar, with their own times: `touch -h`, `lutimes` and `utimensat` with `AT_SYMLINK_NOFOLLOW` set the link's, never the target's.
|
|
380
403
|
|
|
381
404
|
OPFS stays authoritative: an entry is consulted only for a path that exists in OPFS (symlinks only for paths that don't), so files written straight to OPFS, for example by the BIOS installer or a page, get the defaults: directories `0755`, files `0644`, and files under `node_modules/*/bin/` `0755`. A file deleted through the OPFS API disappears at once; its leftover entry is ignored and removed when the next kernel starts. Changes go to OPFS first and then to the sidecar, so a crash in between at worst loses the metadata of that one change. Each change is a read-modify-write inside one IndexedDB transaction, so two kernels (two tabs) on the same origin don't lose each other's updates.
|
|
382
405
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/cdp/port.ts", "../src/kernel/net/remote-transport.ts", "../src/client/dial-stream.ts", "../src/client/loopback-fetch.ts", "../src/client/protocol.ts", "../src/client/attach.ts", "../src/mount/protocol.ts", "../src/mount/driver.ts", "../src/mount/host.ts", "../src/driver-worker.ts"],
|
|
4
|
-
"sourcesContent": ["import type { CdpConnection, CdpHook, CdpRequest } from './types.ts';\n\nexport interface CdpPortLike {\n postMessage(message: unknown): void;\n addEventListener(type: 'message', handler: (event: MessageEvent) => void): void;\n start?(): void;\n close(): void;\n}\n\nexport type CdpWire = { open: true } | { error: string } | { m: string } | { close: string | null };\n\nexport interface CdpOpen {\n cdpOpen: CdpRequest & { registration?: number };\n port: CdpPortLike;\n}\n\nexport function serveCdpPort(\n port: CdpPortLike,\n hook: CdpHook,\n request: CdpRequest,\n onDone?: () => void\n): () => void {\n let conn: CdpConnection | undefined;\n let done = false;\n const end = () => {\n done = true;\n port.close();\n onDone?.();\n };\n const finish = (reason: string | null) => {\n if (done) return;\n port.postMessage({ close: reason });\n end();\n };\n port.addEventListener('message', ({ data }: MessageEvent<{ m?: string; close?: true }>) => {\n if (data.m !== undefined) conn?.send(data.m);\n else if (data.close && !done) {\n end();\n conn?.close();\n }\n });\n port.start?.();\n new Promise<CdpConnection>((resolve) => resolve(hook(request))).then(\n (opened) => {\n conn = opened;\n if (done) return opened.close();\n opened.onmessage = (m) => {\n if (!done) port.postMessage({ m });\n };\n opened.onclose = (reason) => finish(reason ?? null);\n port.postMessage({ open: true });\n },\n (e: unknown) => {\n if (done) return;\n port.postMessage({ error: e instanceof Error ? e.message : String(e) });\n end();\n }\n );\n return () => {\n if (done) return;\n conn?.close();\n finish('the CDP host is gone');\n };\n}\n\nexport function portCdpHook(\n ask: (request: CdpRequest, port: CdpPortLike) => void,\n gone?: Promise<unknown>\n): CdpHook {\n return (request) =>\n new Promise((resolve, reject) => {\n const { port1, port2 } = new MessageChannel();\n let closed = false;\n const conn: CdpConnection = {\n send: (m) => {\n if (!closed) port1.postMessage({ m });\n },\n onmessage: null,\n onclose: null,\n close: () => {\n if (closed) return;\n closed = true;\n port1.postMessage({ close: true });\n port1.close();\n },\n };\n port1.addEventListener('message', ({ data }: MessageEvent<CdpWire>) => {\n if ('m' in data) conn.onmessage?.(data.m);\n else if ('open' in data) resolve(conn);\n else if ('error' in data) {\n closed = true;\n port1.close();\n reject(new Error(data.error));\n } else if (!closed) {\n closed = true;\n port1.close();\n conn.onclose?.(data.close ?? undefined);\n }\n });\n port1.start();\n void gone?.then(() => {\n if (closed) return;\n closed = true;\n port1.close();\n reject(new Error('the CDP host is gone'));\n conn.onclose?.('the CDP host is gone');\n });\n ask(request, port2 as unknown as CdpPortLike);\n });\n}\n", "import type {\n HeaderList,\n RealmTransport,\n RealmTransportRequest,\n RealmTransportResponse,\n RealmTransportTraits,\n} from './transport.ts';\n\nexport type TransportCall =\n | {\n net: 'fetch';\n nid: number;\n url: string;\n method: string;\n headers: HeaderList;\n body?: Uint8Array;\n }\n | { net: 'read'; nid: number }\n | { net: 'cancel'; nid: number };\n\nexport type TransportReply =\n | { net: 'head'; nid: number; status: number; statusText: string; headers: HeaderList }\n | { net: 'chunk'; nid: number; bytes: Uint8Array }\n | { net: 'end'; nid: number }\n | { net: 'error'; nid: number; message: string; status?: number; code?: string };\n\nexport interface TransportPort {\n postMessage(message: TransportCall): void;\n}\n\nexport class TransportError extends Error {\n readonly status: number | undefined;\n readonly code: string | undefined;\n\n constructor(message: string, status?: number, code?: string) {\n super(message);\n this.status = status;\n this.code = code;\n }\n}\n\ninterface Waiter {\n resolve(reply: TransportReply): void;\n reject(error: Error): void;\n}\n\nexport class RemoteTransport implements RealmTransport {\n readonly traits: RealmTransportTraits;\n\n private readonly port: TransportPort;\n\n private readonly waiting = new Map<number, Waiter>();\n\n private nextId = 0;\n\n private failure: Error | undefined;\n\n constructor(port: TransportPort, traits: RealmTransportTraits) {\n this.port = port;\n this.traits = traits;\n }\n\n receive(reply: TransportReply): void {\n const waiter = this.waiting.get(reply.nid);\n if (!waiter) return;\n this.waiting.delete(reply.nid);\n if (reply.net === 'error') {\n waiter.reject(new TransportError(reply.message, reply.status, reply.code));\n } else waiter.resolve(reply);\n }\n\n fail(error: Error): void {\n this.failure = error;\n for (const waiter of this.waiting.values()) waiter.reject(error);\n this.waiting.clear();\n }\n\n private ask(call: TransportCall): Promise<TransportReply> {\n if (this.failure) return Promise.reject(this.failure);\n return new Promise((resolve, reject) => {\n this.waiting.set(call.nid, { resolve, reject });\n this.port.postMessage(call);\n });\n }\n\n private cancel(nid: number): void {\n const waiter = this.waiting.get(nid);\n this.waiting.delete(nid);\n waiter?.reject(new TransportError('the request was cancelled'));\n this.port.postMessage({ net: 'cancel', nid });\n }\n\n async fetch(request: RealmTransportRequest): Promise<RealmTransportResponse> {\n const nid = ++this.nextId;\n const { signal } = request;\n signal.throwIfAborted();\n let finished = false;\n const abort = () => {\n finished = true;\n this.cancel(nid);\n };\n signal.addEventListener('abort', abort, { once: true });\n const finish = () => {\n if (finished) return;\n finished = true;\n signal.removeEventListener('abort', abort);\n };\n let head: TransportReply;\n try {\n head = await this.ask({\n net: 'fetch',\n nid,\n url: request.url,\n method: request.method,\n headers: request.headers,\n ...(request.body ? { body: request.body } : {}),\n });\n } catch (e) {\n finish();\n throw e;\n }\n const { status, statusText, headers } = head as Extract<TransportReply, { net: 'head' }>;\n const read = async (): Promise<Uint8Array | undefined> => {\n if (finished) return undefined;\n const reply = await this.ask({ net: 'read', nid }).catch((e: unknown) => {\n finish();\n throw e;\n });\n if (reply.net === 'chunk') return reply.bytes;\n finish();\n return undefined;\n };\n const cancel = async () => {\n if (finished) return;\n finish();\n this.cancel(nid);\n };\n return {\n status,\n statusText,\n headers,\n cancel,\n body: {\n [Symbol.asyncIterator]: () => ({\n next: async () => {\n const bytes = await read();\n return bytes ? { value: bytes, done: false } : { value: undefined, done: true };\n },\n return: async () => {\n await cancel();\n return { value: undefined, done: true };\n },\n }),\n },\n };\n }\n}\n", "export interface DialledSocket {\n readable: ReadableStream<Uint8Array>;\n writable: WritableStream<Uint8Array>;\n close(): void;\n}\n\nexport interface DialOptions {\n port: number;\n host?: string;\n}\n\ninterface StreamPort {\n postMessage(message: unknown, transfer?: Transferable[]): void;\n addEventListener(type: 'message', handler: (event: MessageEvent) => void): void;\n start?(): void;\n close(): void;\n}\n\ntype DialMessage = Uint8Array | { end: true } | { ack: true } | { error: string };\n\nexport interface DialHandle extends DialledSocket {\n fail(error: Error): void;\n}\n\nexport function errorWithCode(message: string): Error & { code?: string } {\n const code = /^E[A-Z]+/.exec(message)?.[0];\n return Object.assign(new Error(message), code ? { code } : {});\n}\n\nexport function dialStream(port: StreamPort, onClose?: () => void): DialHandle {\n let closed = false;\n let reader: ReadableStreamDefaultController<Uint8Array> | undefined;\n const acks: Array<{ resolve: () => void; reject: (error: Error) => void }> = [];\n const readable = new ReadableStream<Uint8Array>({\n start(controller) {\n reader = controller;\n },\n pull() {\n if (!closed) port.postMessage({ more: true });\n },\n cancel() {\n reader = undefined;\n close();\n },\n });\n const finish = (fail?: Error) => {\n const controller = reader;\n reader = undefined;\n for (const ack of acks.splice(0)) {\n if (fail) ack.reject(fail);\n else ack.resolve();\n }\n if (!controller) return;\n if (fail) controller.error(fail);\n else controller.close();\n };\n function shut(): void {\n if (closed) return;\n closed = true;\n port.close();\n onClose?.();\n }\n function close(): void {\n if (!closed) port.postMessage({ close: true });\n shut();\n finish();\n }\n port.addEventListener('message', ({ data }: MessageEvent<DialMessage>) => {\n if (data instanceof Uint8Array) reader?.enqueue(data);\n else if ('ack' in data) acks.shift()?.resolve();\n else if ('end' in data) finish();\n else finish(errorWithCode(data.error));\n });\n port.start?.();\n const writable = new WritableStream<Uint8Array>({\n write(chunk) {\n if (closed) throw errorWithCode('EPIPE: the connection is closed');\n const copy = chunk.slice();\n const acked = new Promise<void>((resolve, reject) => acks.push({ resolve, reject }));\n port.postMessage(copy, [copy.buffer]);\n return acked;\n },\n close() {\n if (!closed) port.postMessage({ end: true });\n },\n abort() {\n close();\n },\n });\n const fail = (error: Error) => {\n shut();\n finish(error);\n };\n return { readable, writable, close, fail };\n}\n", "import { type DialledSocket, type DialOptions, errorWithCode } from './dial-stream.ts';\n\nexport interface LoopbackFetchOptions extends DialOptions {\n signal?: AbortSignal;\n}\n\nconst OWN_HEADERS = new Set(['host', 'connection', 'content-length', 'transfer-encoding']);\nconst encoder = new TextEncoder();\nconst latin1 = new TextDecoder('latin1');\n\nclass ByteSource {\n private buffered = new Uint8Array(0);\n private readonly reader: ReadableStreamDefaultReader<Uint8Array>;\n\n constructor(reader: ReadableStreamDefaultReader<Uint8Array>) {\n this.reader = reader;\n }\n\n private async more(): Promise<boolean> {\n const { done, value } = await this.reader.read();\n if (done) return false;\n const joined = new Uint8Array(this.buffered.length + value.length);\n joined.set(this.buffered);\n joined.set(value, this.buffered.length);\n this.buffered = joined;\n return true;\n }\n\n async until(marker: string): Promise<Uint8Array | undefined> {\n const needle = encoder.encode(marker);\n for (;;) {\n const at = indexOf(this.buffered, needle);\n if (at >= 0) return this.take(at + needle.length);\n if (!(await this.more())) return undefined;\n }\n }\n\n async some(max: number): Promise<Uint8Array | undefined> {\n if (this.buffered.length === 0 && !(await this.more())) return undefined;\n return this.take(Math.min(max, this.buffered.length));\n }\n\n async exactly(count: number): Promise<Uint8Array | undefined> {\n while (this.buffered.length < count) if (!(await this.more())) return undefined;\n return this.take(count);\n }\n\n private take(count: number): Uint8Array {\n const out = this.buffered.slice(0, count);\n this.buffered = this.buffered.slice(count);\n return out;\n }\n}\n\nfunction indexOf(haystack: Uint8Array, needle: Uint8Array): number {\n outer: for (let i = 0; i + needle.length <= haystack.length; i++) {\n for (let j = 0; j < needle.length; j++) if (haystack[i + j] !== needle[j]) continue outer;\n return i;\n }\n return -1;\n}\n\ninterface ResponseHead {\n status: number;\n statusText: string;\n headers: Array<[string, string]>;\n}\n\nfunction parseHead(bytes: Uint8Array): ResponseHead {\n const [statusLine = '', ...lines] = latin1.decode(bytes).split('\\r\\n');\n const match = /^HTTP\\/1\\.[01] (\\d{3})(?: (.*))?$/.exec(statusLine);\n if (!match) throw errorWithCode(`EPROTO: not an HTTP/1.x response: ${statusLine.slice(0, 80)}`);\n const headers: Array<[string, string]> = [];\n for (const line of lines) {\n const colon = line.indexOf(':');\n if (colon > 0) headers.push([line.slice(0, colon).trim(), line.slice(colon + 1).trim()]);\n }\n return { status: Number(match[1]), statusText: match[2] ?? '', headers };\n}\n\nfunction header(head: ResponseHead, name: string): string | undefined {\n return head.headers.find(([key]) => key.toLowerCase() === name)?.[1];\n}\n\nasync function* chunked(source: ByteSource): AsyncGenerator<Uint8Array> {\n for (;;) {\n const line = await source.until('\\r\\n');\n if (!line) throw errorWithCode('EPROTO: the chunked body ended early');\n const size = Number.parseInt(latin1.decode(line).trim().split(';')[0] ?? '', 16);\n if (!Number.isFinite(size)) throw errorWithCode('EPROTO: a malformed chunk size');\n if (size === 0) return;\n const data = await source.exactly(size);\n if (!data || !(await source.exactly(2))) throw errorWithCode('EPROTO: a chunk ended early');\n yield data;\n }\n}\n\nasync function* counted(source: ByteSource, length: number): AsyncGenerator<Uint8Array> {\n let left = length;\n while (left > 0) {\n const data = await source.some(left);\n if (!data) throw errorWithCode('EPROTO: the body ended early');\n left -= data.length;\n yield data;\n }\n}\n\nasync function* untilClose(source: ByteSource): AsyncGenerator<Uint8Array> {\n for (let data = await source.some(65536); data; data = await source.some(65536)) yield data;\n}\n\nfunction bodyOf(source: ByteSource, head: ResponseHead, method: string) {\n if (method === 'HEAD' || head.status === 204 || head.status === 304) return undefined;\n if (header(head, 'transfer-encoding')?.toLowerCase().includes('chunked')) return chunked(source);\n const length = header(head, 'content-length');\n if (length === undefined) return untilClose(source);\n const size = Number(length);\n if (!/^\\d+$/.test(length.trim()) || !Number.isSafeInteger(size)) {\n throw errorWithCode(`EPROTO: a malformed Content-Length: ${length}`);\n }\n return counted(source, size);\n}\n\nfunction stream(chunks: AsyncGenerator<Uint8Array>, socket: DialledSocket, signal?: AbortSignal) {\n return new ReadableStream<Uint8Array>({\n start(controller) {\n signal?.addEventListener('abort', () => controller.error(signal.reason), { once: true });\n },\n async pull(controller) {\n try {\n const next = await chunks.next();\n if (next.done) {\n controller.close();\n socket.close();\n } else controller.enqueue(next.value);\n } catch (err) {\n controller.error(err);\n socket.close();\n }\n },\n cancel() {\n socket.close();\n },\n });\n}\n\nasync function requestBytes(request: Request): Promise<Uint8Array> {\n const url = new URL(request.url);\n const body = request.body ? new Uint8Array(await request.arrayBuffer()) : undefined;\n const lines = [`${request.method} ${url.pathname}${url.search} HTTP/1.1`, `Host: ${url.host}`];\n request.headers.forEach((value, name) => {\n if (!OWN_HEADERS.has(name)) lines.push(`${name}: ${value}`);\n });\n if (body) lines.push(`Content-Length: ${body.length}`);\n lines.push('Connection: close', '', '');\n const head = encoder.encode(lines.join('\\r\\n'));\n const out = new Uint8Array(head.length + (body?.length ?? 0));\n out.set(head);\n if (body) out.set(body, head.length);\n return out;\n}\n\nexport async function loopbackFetch(\n dial: (options: DialOptions) => Promise<DialledSocket>,\n input: RequestInfo | URL,\n options: LoopbackFetchOptions\n): Promise<Response> {\n options.signal?.throwIfAborted();\n const request = input instanceof Request ? input : new Request(input);\n const bytes = await requestBytes(request);\n const socket = await dial({\n port: options.port,\n ...(options.host ? { host: options.host } : {}),\n });\n options.signal?.addEventListener('abort', () => socket.close(), { once: true });\n try {\n const writer = socket.writable.getWriter();\n await writer.write(bytes);\n writer.releaseLock();\n const source = new ByteSource(socket.readable.getReader());\n let head: ResponseHead;\n do {\n const raw = await source.until('\\r\\n\\r\\n');\n if (!raw) throw errorWithCode('ECONNRESET: the connection closed before a response');\n head = parseHead(raw);\n } while (head.status >= 100 && head.status < 200);\n const chunks = bodyOf(source, head, request.method);\n if (!chunks) socket.close();\n return new Response(chunks ? stream(chunks, socket, options.signal) : null, {\n status: head.status,\n statusText: head.statusText,\n headers: head.headers,\n });\n } catch (err) {\n socket.close();\n throw err;\n }\n}\n", "import type { WatchChange } from '../fs/watch.ts';\nimport type { TransportCall, TransportReply } from '../kernel/net/remote-transport.ts';\nimport type { RealmTransportTraits } from '../kernel/net/transport.ts';\nimport type { MountSpec } from '../mount/mount-fs.ts';\n\nexport const PROTOCOL: readonly [number, number] = [1, 7];\n\nexport interface ClientHello {\n protocol: readonly [number, number];\n lock?: string;\n}\n\nexport interface KernelHello {\n protocol: readonly [number, number];\n lock?: string;\n traits?: RealmTransportTraits;\n error?: string;\n}\n\nexport interface SpawnRequestOptions {\n cwd?: string;\n env?: Record<string, string>;\n stdin?: Uint8Array;\n pgid?: number;\n}\n\nexport interface TerminalRequestOptions {\n cwd?: string;\n env?: Record<string, string>;\n cols?: number;\n rows?: number;\n}\n\nexport type TerminalAction =\n | { action: 'write'; bytes: Uint8Array }\n | { action: 'resize'; cols: number; rows: number }\n | { action: 'signal'; signal: string }\n | { action: 'close' };\n\nexport const FS_METHODS = [\n 'readFile',\n 'writeFile',\n 'stat',\n 'lstat',\n 'readdir',\n 'mkdir',\n 'rm',\n 'rename',\n 'realpath',\n 'symlink',\n 'readlink',\n 'exists',\n] as const;\n\nexport type FsMethod = (typeof FS_METHODS)[number];\n\nexport type ClientCall =\n | { op: 'spawn'; argv: string[]; options: SpawnRequestOptions }\n | { op: 'open-terminal'; argv: string[]; options: TerminalRequestOptions }\n | ({ op: 'terminal'; terminal: number } & TerminalAction)\n | { op: 'kill'; pid: number; signal: string }\n | { op: 'ps' }\n | { op: 'fs'; method: FsMethod; args: unknown[] }\n | { op: 'watch'; paths: string[]; recursive: boolean }\n | { op: 'unwatch'; watch: number }\n | { op: 'mount'; spec: MountSpec }\n | { op: 'umount'; target: string }\n | { op: 'mounts' }\n | { op: 'dial'; port: number; host?: string }\n | { op: 'serve-cdp'; runtime?: string }\n | { op: 'unserve-cdp'; registration: number }\n | { op: 'detach'; kill?: boolean };\n\nexport type ClientRequest = ClientCall & { id: number };\n\nexport interface ClientReply {\n id: number;\n result?: unknown;\n error?: string;\n code?: string;\n fd?: 1 | 2;\n bytes?: Uint8Array;\n started?: number;\n}\n\nexport type ClientMessage = { hello: ClientHello } | ClientRequest | TransportCall;\n\nexport interface WatchEvent {\n watch: number;\n change: WatchChange;\n}\n\nexport type KernelMessage = { hello: KernelHello } | ClientReply | WatchEvent | TransportReply;\n\nexport interface ProcessEntry {\n pid: number;\n ppid: number;\n pgid: number;\n sid: number;\n argv: string[];\n tty: string | null;\n started: number;\n state: 'S' | 'Z';\n memory: number;\n}\n\nexport interface MessagePortLike {\n postMessage(message: unknown, transfer?: Transferable[]): void;\n addEventListener(type: 'message' | 'close', handler: (event: MessageEvent) => void): void;\n start?(): void;\n close?(): void;\n}\n\nexport interface LockManagerLike {\n request(name: string, callback: () => Promise<unknown> | unknown): Promise<unknown>;\n}\n\nexport function locksOf(scope: object = globalThis): LockManagerLike | undefined {\n const locks = (scope as { navigator?: { locks?: LockManagerLike } }).navigator?.locks;\n return typeof locks?.request === 'function' ? locks : undefined;\n}\n\nexport function versionError(theirs: unknown): string | undefined {\n const major = Array.isArray(theirs) ? theirs[0] : undefined;\n if (major === PROTOCOL[0]) return undefined;\n const named = typeof major === 'number' ? `${major}.x` : 'without a version';\n return `slicc-kernel client protocol ${named} is not supported: this side speaks ${PROTOCOL.join('.')}`;\n}\n", "import { type CdpOpen, serveCdpPort } from '../cdp/port.ts';\nimport type { CdpHook } from '../cdp/types.ts';\nimport type { FsStat } from '../fs/types.ts';\nimport type { WatchChange } from '../fs/watch.ts';\nimport { RemoteTransport, type TransportReply } from '../kernel/net/remote-transport.ts';\nimport type {\n RealmTransport,\n RealmTransportRequest,\n RealmTransportResponse,\n} from '../kernel/net/transport.ts';\nimport type { MountEntry, MountSpec } from '../mount/mount-fs.ts';\nimport { type DialledSocket, type DialOptions, dialStream } from './dial-stream.ts';\nimport { type LoopbackFetchOptions, loopbackFetch } from './loopback-fetch.ts';\nimport {\n type ClientCall,\n type ClientReply,\n type FsMethod,\n type KernelHello,\n type LockManagerLike,\n locksOf,\n type MessagePortLike,\n PROTOCOL,\n type ProcessEntry,\n type TerminalAction,\n versionError,\n} from './protocol.ts';\n\nexport type { WatchChange } from '../fs/watch.ts';\nexport type { ProcessEntry } from './protocol.ts';\n\nexport class KernelGoneError extends Error {\n constructor(message = 'the slicc-kernel this client was attached to is gone') {\n super(message);\n this.name = 'KernelGoneError';\n }\n}\n\nexport class KernelCallError extends Error {\n readonly code: string | undefined;\n\n constructor(message: string, code?: string) {\n super(message);\n this.name = 'KernelCallError';\n this.code = code;\n }\n}\n\nexport interface AttachOptions {\n timeoutMs?: number;\n locks?: LockManagerLike | null;\n}\n\nexport interface SpawnOptions {\n cwd?: string;\n env?: Record<string, string>;\n stdin?: string | Uint8Array;\n group?: 'new';\n pgid?: number;\n onStdout?: (bytes: Uint8Array) => void;\n onStderr?: (bytes: Uint8Array) => void;\n}\n\nexport interface SpawnedProcess {\n readonly pid: number;\n readonly pgid: number;\n readonly exited: Promise<number>;\n signal(name?: string): Promise<void>;\n}\n\nexport interface ClientRunOptions {\n cwd?: string;\n env?: Record<string, string>;\n stdin?: string | Uint8Array;\n onStdout?: (text: string) => void;\n onStderr?: (text: string) => void;\n}\n\nexport interface ClientRunResult {\n pid: number;\n status: number;\n stdout: string;\n stderr: string;\n}\n\nexport interface ClientTerminalOptions {\n cwd?: string;\n env?: Record<string, string>;\n cols?: number;\n rows?: number;\n onData?: (bytes: Uint8Array) => void;\n}\n\nexport interface ClientTerminal {\n readonly pid: number;\n readonly exited: Promise<number>;\n onData: ((bytes: Uint8Array) => void) | null;\n write(data: string | Uint8Array): void;\n resize(cols: number, rows: number): void;\n signal(name: string): void;\n close(): void;\n}\n\nexport interface ClientFs {\n readFile(path: string): Promise<Uint8Array>;\n readText(path: string): Promise<string>;\n writeFile(path: string, data: string | Uint8Array): Promise<void>;\n stat(path: string): Promise<FsStat>;\n lstat(path: string): Promise<FsStat>;\n readdir(path: string): Promise<string[]>;\n mkdir(path: string): Promise<void>;\n rm(path: string, options?: { force?: boolean }): Promise<void>;\n rename(from: string, to: string): Promise<void>;\n realpath(path: string): Promise<string>;\n symlink(target: string, path: string): Promise<void>;\n readlink(path: string): Promise<string>;\n exists(path: string): Promise<boolean>;\n watch(\n paths: string[],\n options: { recursive?: boolean },\n onChange: (change: WatchChange) => void\n ): Promise<{ close(): void }>;\n}\n\nexport type ClientFetchRequest = Omit<RealmTransportRequest, 'signal'> & { signal?: AbortSignal };\n\nexport interface KernelClient {\n readonly protocol: readonly [number, number];\n readonly transport: RealmTransport;\n readonly closed: Promise<Error>;\n spawn(argv: string[], options?: SpawnOptions): Promise<SpawnedProcess>;\n run(argv: string[], options?: ClientRunOptions): Promise<ClientRunResult>;\n openTerminal(argv: string[], options?: ClientTerminalOptions): Promise<ClientTerminal>;\n ps(): Promise<ProcessEntry[]>;\n mount(spec: MountSpec): Promise<MountEntry>;\n umount(target: string): Promise<void>;\n mounts(): Promise<MountEntry[]>;\n kill(pid: number, signal?: string): Promise<void>;\n fetch(request: ClientFetchRequest): Promise<RealmTransportResponse>;\n dial(options: DialOptions): Promise<DialledSocket>;\n loopbackFetch(input: RequestInfo | URL, options: LoopbackFetchOptions): Promise<Response>;\n readonly fs: ClientFs;\n serveCdp(hook: CdpHook, options?: { runtime?: string }): Promise<{ close(): void }>;\n close(options?: { kill?: boolean }): Promise<void>;\n}\n\ninterface Pending {\n resolve: (value: unknown) => void;\n reject: (error: Error) => void;\n output?: (fd: 1 | 2, bytes: Uint8Array) => void;\n started?: (pid: number) => void;\n}\n\ntype Handlers = Omit<Pending, 'resolve' | 'reject'>;\n\nconst encoder = new TextEncoder();\nconst bytesOf = (data: string | Uint8Array) =>\n typeof data === 'string' ? encoder.encode(data) : data;\n\nconst UNAVAILABLE = {\n manualRedirects: false,\n encodedBodies: false,\n maxRequestBody: 0,\n unavailable: true,\n} as const;\n\nasync function holdLock(\n locks: LockManagerLike | undefined\n): Promise<{ name?: string; release(): void }> {\n if (!locks) return { release() {} };\n const name = `slicc-kernel-client:${crypto.randomUUID()}`;\n const granted = Promise.withResolvers<void>();\n const held = Promise.withResolvers<void>();\n void locks.request(name, () => {\n granted.resolve();\n return held.promise;\n });\n await granted.promise;\n return { name, release: () => held.resolve() };\n}\n\nfunction concat(chunks: Uint8Array[]): Uint8Array {\n const out = new Uint8Array(chunks.reduce((n, c) => n + c.length, 0));\n let at = 0;\n for (const chunk of chunks) {\n out.set(chunk, at);\n at += chunk.length;\n }\n return out;\n}\n\nclass Channel {\n readonly greeted = Promise.withResolvers<KernelHello>();\n readonly ended = Promise.withResolvers<Error>();\n remote: RemoteTransport | undefined;\n failure: Error | undefined;\n private readonly pending = new Map<number, Pending>();\n readonly watching = new Map<number, (change: WatchChange) => void>();\n readonly cdpHooks = new Map<number, CdpHook>();\n private readonly cdpOpen = new Set<() => void>();\n protocol: readonly [number, number] = PROTOCOL;\n private nextId = 0;\n private readonly port: MessagePortLike;\n private readonly release: () => void;\n\n constructor(port: MessagePortLike, release: () => void) {\n this.port = port;\n this.release = release;\n this.greeted.promise.catch(() => undefined);\n port.addEventListener('message', (event) => this.receive(event.data));\n port.addEventListener('close', () => this.end(new KernelGoneError()));\n port.start?.();\n }\n\n post(message: object): void {\n if (!this.failure) this.port.postMessage(message);\n }\n\n end(error: Error): void {\n if (this.failure) return;\n this.failure = error;\n this.greeted.reject(error);\n this.remote?.fail(error);\n for (const close of [...this.cdpOpen]) close();\n this.cdpOpen.clear();\n for (const call of this.pending.values()) call.reject(error);\n this.pending.clear();\n this.release();\n this.port.close?.();\n this.ended.resolve(error);\n }\n\n request(call: ClientCall, handlers: Handlers = {}): { id: number; done: Promise<unknown> } {\n const id = ++this.nextId;\n const { failure } = this;\n if (failure) return { id, done: Promise.reject(failure) };\n const done = new Promise((resolve, reject) => {\n this.pending.set(id, { resolve, reject, ...handlers });\n this.port.postMessage({ ...call, id });\n });\n return { id, done };\n }\n\n call(call: ClientCall): Promise<unknown> {\n return this.request(call).done;\n }\n\n private receive(data: {\n hello?: KernelHello;\n net?: unknown;\n bye?: string;\n watch?: number;\n change?: WatchChange;\n cdpOpen?: CdpOpen['cdpOpen'];\n port?: CdpOpen['port'];\n }): void {\n if (data.cdpOpen && data.port) {\n this.openCdp(data as CdpOpen);\n return;\n }\n if (data.watch !== undefined) {\n this.watching.get(data.watch)?.(data.change as WatchChange);\n return;\n }\n if (data.bye !== undefined) {\n this.end(new KernelGoneError(data.bye));\n return;\n }\n if (data.hello) {\n this.greeted.resolve(data.hello);\n return;\n }\n if (data.net !== undefined) {\n this.remote?.receive(data as TransportReply);\n return;\n }\n const reply = data as ClientReply;\n const call = this.pending.get(reply.id);\n if (!call) return;\n if (reply.fd !== undefined) {\n call.output?.(reply.fd, reply.bytes as Uint8Array);\n return;\n }\n if (reply.started !== undefined) {\n call.started?.(reply.started);\n return;\n }\n this.pending.delete(reply.id);\n if (reply.error !== undefined) call.reject(new KernelCallError(reply.error, reply.code));\n else call.resolve(reply.result);\n }\n\n private openCdp({ cdpOpen: { registration, ...request }, port }: CdpOpen): void {\n const hook = registration === undefined ? undefined : this.cdpHooks.get(registration);\n if (!hook || this.failure) {\n port.postMessage({ error: 'this client no longer serves CDP' });\n port.close();\n return;\n }\n const close = serveCdpPort(port, hook, request, () => this.cdpOpen.delete(close));\n this.cdpOpen.add(close);\n }\n}\n\nasync function serveCdpOn(\n channel: Channel,\n hook: CdpHook,\n options: { runtime?: string }\n): Promise<{ close(): void }> {\n await since(channel, 5, 'CDP serving', async () => {});\n const req = {\n op: 'serve-cdp' as const,\n ...(options.runtime ? { runtime: options.runtime } : {}),\n };\n const { id, done } = channel.request(req);\n channel.cdpHooks.set(id, hook);\n try {\n await done;\n } catch (error) {\n channel.cdpHooks.delete(id);\n throw error;\n }\n return {\n close: () => {\n if (!channel.cdpHooks.delete(id)) return;\n void channel.call({ op: 'unserve-cdp', registration: id }).catch(() => undefined);\n },\n };\n}\n\nasync function dialOn(channel: Channel, { port, host }: DialOptions): Promise<DialledSocket> {\n const req = { op: 'dial' as const, port, ...(host ? { host } : {}) };\n return dialStream((await since(channel, 4, 'dial', () => channel.call(req))) as MessagePort);\n}\n\nasync function spawnOn(\n channel: Channel,\n argv: string[],\n opts: SpawnOptions\n): Promise<SpawnedProcess> {\n const { onStdout, onStderr, stdin, group: _, ...rest } = opts;\n if (opts.pgid !== undefined)\n await since(channel, 3, 'spawn into a process group', async () => {});\n const started = Promise.withResolvers<number>();\n const options = { ...rest, ...(stdin !== undefined ? { stdin: bytesOf(stdin) } : {}) };\n const { done } = channel.request(\n { op: 'spawn', argv, options },\n {\n output: (fd, bytes) => (fd === 1 ? onStdout : onStderr)?.(bytes),\n started: started.resolve,\n }\n );\n done.catch(started.reject);\n const pid = await started.promise;\n const pgid = opts.pgid ?? pid;\n return {\n pid,\n pgid,\n exited: done as Promise<number>,\n signal: async (name = 'SIGTERM') =>\n void (await channel.call({ op: 'kill', pid: -pgid, signal: name })),\n };\n}\n\nasync function runOn(\n channel: Channel,\n argv: string[],\n opts: ClientRunOptions\n): Promise<ClientRunResult> {\n const { onStdout, onStderr, ...rest } = opts;\n const chunks: Record<1 | 2, Uint8Array[]> = { 1: [], 2: [] };\n const live = { 1: new TextDecoder(), 2: new TextDecoder() };\n const tee = (fd: 1 | 2, on?: (text: string) => void) => (bytes: Uint8Array) => {\n chunks[fd].push(bytes);\n on?.(live[fd].decode(bytes, { stream: true }));\n };\n const child = await spawnOn(channel, argv, {\n ...rest,\n onStdout: tee(1, onStdout),\n onStderr: tee(2, onStderr),\n });\n const status = await child.exited;\n const text = (fd: 1 | 2) => new TextDecoder().decode(concat(chunks[fd]));\n return { pid: child.pid, status, stdout: text(1), stderr: text(2) };\n}\n\nasync function terminalOn(\n channel: Channel,\n argv: string[],\n opts: ClientTerminalOptions\n): Promise<ClientTerminal> {\n const { onData, ...options } = opts;\n let listener = onData ?? null;\n const backlog: Uint8Array[] = [];\n const started = Promise.withResolvers<number>();\n const { id, done } = channel.request(\n { op: 'open-terminal', argv, options },\n {\n output: (_fd, bytes) => (listener ? listener(bytes) : backlog.push(bytes)),\n started: started.resolve,\n }\n );\n done.catch(started.reject);\n const pid = await started.promise;\n const send = (action: TerminalAction) =>\n void channel.call({ op: 'terminal', terminal: id, ...action }).catch(() => undefined);\n return {\n pid,\n exited: done as Promise<number>,\n get onData() {\n return listener;\n },\n set onData(next) {\n listener = next;\n if (next) for (const bytes of backlog.splice(0)) next(bytes);\n },\n write: (data) => send({ action: 'write', bytes: bytesOf(data) }),\n resize: (cols, rows) => send({ action: 'resize', cols, rows }),\n signal: (name) => send({ action: 'signal', signal: name }),\n close: () => send({ action: 'close' }),\n };\n}\n\nfunction fsOn(channel: Channel): ClientFs {\n const fs = (method: FsMethod, ...args: unknown[]) => channel.call({ op: 'fs', method, args });\n const done = async (method: FsMethod, ...args: unknown[]) => void (await fs(method, ...args));\n return {\n readFile: (path) => fs('readFile', path) as Promise<Uint8Array>,\n readText: async (path) => new TextDecoder().decode((await fs('readFile', path)) as Uint8Array),\n writeFile: (path, data) => done('writeFile', path, data),\n stat: (path) => fs('stat', path) as Promise<FsStat>,\n lstat: (path) => fs('lstat', path) as Promise<FsStat>,\n readdir: (path) => fs('readdir', path) as Promise<string[]>,\n mkdir: (path) => done('mkdir', path),\n rm: (path, o = {}) => done('rm', path, o.force === true),\n rename: (from, to) => done('rename', from, to),\n realpath: (path) => fs('realpath', path) as Promise<string>,\n symlink: (target, path) => done('symlink', target, path),\n readlink: (path) => fs('readlink', path) as Promise<string>,\n exists: (path) => fs('exists', path) as Promise<boolean>,\n async watch(paths, options, onChange) {\n if (channel.protocol[1] < 1) {\n throw new KernelCallError(\n `this kernel speaks protocol ${channel.protocol.join('.')}, which has no watch`,\n 'ENOSYS'\n );\n }\n const { id, done } = channel.request({\n op: 'watch',\n paths,\n recursive: options.recursive === true,\n });\n channel.watching.set(id, onChange);\n try {\n await done;\n } catch (error) {\n channel.watching.delete(id);\n throw error;\n }\n return {\n close: () => {\n if (!channel.watching.delete(id)) return;\n void channel.call({ op: 'unwatch', watch: id }).catch(() => undefined);\n },\n };\n },\n };\n}\n\nfunction since(channel: Channel, minor: number, what: string, run: () => Promise<unknown>) {\n if (channel.protocol[1] < minor) {\n return Promise.reject(\n new KernelCallError(\n `this kernel speaks protocol ${channel.protocol.join('.')}, which has no ${what}`,\n 'ENOSYS'\n )\n );\n }\n return run();\n}\n\nasync function greet(\n channel: Channel,\n lock: string | undefined,\n timeoutMs: number\n): Promise<KernelHello> {\n channel.post({ hello: { protocol: PROTOCOL, ...(lock ? { lock } : {}) } });\n const timer = setTimeout(\n () =>\n channel.end(\n new KernelGoneError(`no slicc-kernel answered on this port within ${timeoutMs} ms`)\n ),\n timeoutMs\n );\n let hello: KernelHello;\n try {\n hello = await channel.greeted.promise;\n } finally {\n clearTimeout(timer);\n }\n const refused = hello.error ?? versionError(hello.protocol);\n if (refused) {\n const error = new Error(refused);\n channel.end(error);\n throw error;\n }\n return hello;\n}\n\nexport async function attachKernel(\n port: MessagePortLike,\n options: AttachOptions = {}\n): Promise<KernelClient> {\n const locks = options.locks === null ? undefined : (options.locks ?? locksOf());\n const own = await holdLock(locks);\n const channel = new Channel(port, own.release);\n const hello = await greet(channel, own.name, options.timeoutMs ?? 10_000);\n channel.protocol = hello.protocol;\n if (hello.lock && locks) void locks.request(hello.lock, () => channel.end(new KernelGoneError()));\n const transport = new RemoteTransport(\n { postMessage: (call) => channel.post(call) },\n hello.traits ?? UNAVAILABLE\n );\n channel.remote = transport;\n return {\n protocol: hello.protocol,\n transport,\n closed: channel.ended.promise,\n spawn: (argv, opts = {}) => spawnOn(channel, argv, opts),\n run: (argv, opts = {}) => runOn(channel, argv, opts),\n openTerminal: (argv, opts = {}) => terminalOn(channel, argv, opts),\n ps: () => channel.call({ op: 'ps' }) as Promise<ProcessEntry[]>,\n mount: (spec) =>\n since(channel, 2, 'mount', () => channel.call({ op: 'mount', spec })) as Promise<MountEntry>,\n umount: async (target) =>\n void (await since(channel, 2, 'umount', () => channel.call({ op: 'umount', target }))),\n mounts: () =>\n since(channel, 2, 'mounts', () => channel.call({ op: 'mounts' })) as Promise<MountEntry[]>,\n kill: async (pid, signal = 'SIGTERM') => void (await channel.call({ op: 'kill', pid, signal })),\n fetch: (req) => {\n const { signal, ...rest } = req;\n return transport.fetch({ ...rest, signal: signal ?? new AbortController().signal });\n },\n dial: (options) => dialOn(channel, options),\n loopbackFetch: (input, options) => loopbackFetch((o) => dialOn(channel, o), input, options),\n fs: fsOn(channel),\n serveCdp: (hook, options = {}) => serveCdpOn(channel, hook, options),\n async close(o = {}) {\n if (channel.failure) return;\n await channel\n .call({ op: 'detach', ...(o.kill ? { kill: true } : {}) })\n .catch(() => undefined);\n channel.end(new KernelGoneError('this client is closed'));\n },\n };\n}\n", "export const DRIVER_PROTOCOL: readonly [number, number] = [1, 1];\n\nexport interface DriverCapabilities {\n readonly?: boolean;\n symlinks?: boolean;\n chmod?: boolean;\n ranges?: boolean;\n listingStats?: boolean;\n caseInsensitive?: boolean;\n normalization?: 'none' | 'nfc' | 'nfd-insensitive';\n maxIo?: number;\n maxFile?: number;\n attrTtl?: number;\n entryTtl?: number;\n}\n\nexport interface DriverAttr {\n kind: 'file' | 'directory' | 'symlink';\n size: number;\n mtime: number;\n mode?: number;\n ino?: number;\n etag?: string;\n}\n\nexport interface DriverEntry {\n name: string;\n kind: DriverAttr['kind'];\n attr?: DriverAttr;\n}\n\nexport interface DriverStatfs {\n bsize: number;\n blocks: number;\n bfree: number;\n}\n\nexport interface MountRequestInfo {\n source: string;\n options: Record<string, string>;\n}\n\nexport type DriverCall =\n | { op: 'getattr'; path: string }\n | { op: 'readdir'; path: string }\n | {\n op: 'open';\n path: string;\n write: boolean;\n create: boolean;\n truncate: boolean;\n exclusive: boolean;\n ifMatch?: string;\n }\n | { op: 'read'; fh: number; offset: number; size: number }\n | { op: 'write'; fh: number; offset: number; bytes: Uint8Array }\n | { op: 'release'; fh: number }\n | { op: 'mkdir'; path: string }\n | { op: 'rmdir'; path: string }\n | { op: 'unlink'; path: string }\n | { op: 'rename'; from: string; to: string }\n | { op: 'symlink'; target: string; path: string }\n | { op: 'readlink'; path: string }\n | { op: 'setattr'; path: string; mode?: number; mtime?: number; size?: number }\n | { op: 'statfs' };\n\nexport type DriverRequest = DriverCall & { id: number };\n\nexport interface DriverReply {\n id: number;\n result?: unknown;\n errno?: string;\n message?: string;\n}\n\nexport interface KernelDriverHello {\n protocol: readonly [number, number];\n mount: MountRequestInfo;\n}\n\nexport interface DriverHello {\n protocol: readonly [number, number];\n capabilities?: DriverCapabilities;\n error?: string;\n errno?: string;\n}\n\nexport type KernelToDriver = { hello: KernelDriverHello } | DriverRequest;\n\nexport type DriverToKernel = { hello: DriverHello } | DriverReply | { invalidate: string[] | true };\n\nexport function driverVersionError(theirs: unknown): string | undefined {\n const major = Array.isArray(theirs) ? theirs[0] : undefined;\n if (major === DRIVER_PROTOCOL[0]) return undefined;\n const named = typeof major === 'number' ? `${major}.x` : 'without a version';\n return `slicc-kernel driver protocol ${named} is not supported: this side speaks ${DRIVER_PROTOCOL.join('.')}`;\n}\n", "import {\n DRIVER_PROTOCOL,\n type DriverAttr,\n type DriverCapabilities,\n type DriverEntry,\n type DriverRequest,\n type DriverStatfs,\n driverVersionError,\n type KernelDriverHello,\n type MountRequestInfo,\n} from './protocol.ts';\n\nexport type {\n DriverAttr,\n DriverCapabilities,\n DriverEntry,\n DriverStatfs,\n MountRequestInfo,\n} from './protocol.ts';\n\nexport interface OpenFlags {\n write: boolean;\n create: boolean;\n truncate: boolean;\n exclusive: boolean;\n ifMatch?: string;\n}\n\nexport interface FilesystemHandlers {\n mount?(\n info: MountRequestInfo\n ): Promise<DriverCapabilities | undefined> | DriverCapabilities | undefined;\n getattr(path: string): Promise<DriverAttr>;\n readdir(path: string): Promise<DriverEntry[]>;\n open(path: string, flags: OpenFlags): Promise<number>;\n read(fh: number, offset: number, size: number): Promise<Uint8Array>;\n write(fh: number, offset: number, bytes: Uint8Array): Promise<void>;\n release(fh: number): Promise<void>;\n mkdir(path: string): Promise<void>;\n rmdir(path: string): Promise<void>;\n unlink(path: string): Promise<void>;\n rename(from: string, to: string): Promise<void>;\n symlink?(target: string, path: string): Promise<void>;\n readlink?(path: string): Promise<string>;\n setattr?(path: string, attr: { mode?: number; mtime?: number; size?: number }): Promise<void>;\n statfs?(): Promise<DriverStatfs>;\n}\n\nexport interface DriverPort {\n postMessage(message: unknown, transfer?: Transferable[]): void;\n addEventListener(type: 'message', handler: (event: MessageEvent) => void): void;\n start?(): void;\n}\n\nexport interface ServedFilesystem {\n invalidate(paths: string[] | true): void;\n}\n\nexport function fsError(code: string, message = code): Error & { code: string } {\n return Object.assign(new Error(message), { code });\n}\n\nasync function dispatch(h: FilesystemHandlers, req: DriverRequest): Promise<unknown> {\n switch (req.op) {\n case 'getattr':\n return h.getattr(req.path);\n case 'readdir':\n return h.readdir(req.path);\n case 'open':\n return h.open(req.path, {\n write: req.write,\n create: req.create,\n truncate: req.truncate,\n exclusive: req.exclusive,\n ...(req.ifMatch !== undefined ? { ifMatch: req.ifMatch } : {}),\n });\n case 'read':\n return h.read(req.fh, req.offset, req.size);\n case 'write':\n return h.write(req.fh, req.offset, req.bytes);\n case 'release':\n return h.release(req.fh);\n case 'mkdir':\n return h.mkdir(req.path);\n case 'rmdir':\n return h.rmdir(req.path);\n case 'unlink':\n return h.unlink(req.path);\n case 'rename':\n return h.rename(req.from, req.to);\n case 'symlink':\n if (!h.symlink) throw fsError('EPERM', 'this file system has no symlinks');\n return h.symlink(req.target, req.path);\n case 'readlink':\n if (!h.readlink) throw fsError('EINVAL', `${req.path} is not a symlink`);\n return h.readlink(req.path);\n case 'setattr':\n return h.setattr?.(req.path, {\n ...(req.mode !== undefined ? { mode: req.mode } : {}),\n ...(req.mtime !== undefined ? { mtime: req.mtime } : {}),\n ...(req.size !== undefined ? { size: req.size } : {}),\n });\n case 'statfs':\n return h.statfs?.() ?? null;\n default:\n throw fsError('ENOSYS', `unknown driver op ${(req as { op: string }).op}`);\n }\n}\n\nexport function serveFilesystem(\n port: DriverPort,\n handlers: FilesystemHandlers,\n capabilities: DriverCapabilities = {},\n options: { owned?: boolean } = {}\n): ServedFilesystem {\n let open = false;\n const reply = (message: object, transfer: Transferable[] = []) =>\n port.postMessage(message, transfer);\n async function hello(message: KernelDriverHello): Promise<void> {\n const refused = driverVersionError(message.protocol);\n if (refused) {\n reply({ hello: { protocol: DRIVER_PROTOCOL, error: refused, errno: 'EPROTO' } });\n return;\n }\n try {\n const refined = await handlers.mount?.(message.mount);\n open = true;\n reply({\n hello: { protocol: DRIVER_PROTOCOL, capabilities: { ...capabilities, ...refined } },\n });\n } catch (err) {\n const code = (err as { code?: unknown })?.code;\n reply({\n hello: {\n protocol: DRIVER_PROTOCOL,\n error: err instanceof Error ? err.message : String(err),\n errno: typeof code === 'string' ? code : 'EIO',\n },\n });\n }\n }\n port.addEventListener('message', (event) => {\n const data = event.data as { hello?: KernelDriverHello } & DriverRequest;\n if (data.hello) {\n void hello(data.hello);\n return;\n }\n if (!open) return;\n dispatch(handlers, data).then(\n (result) => {\n if (result instanceof Uint8Array) {\n const whole = result.byteOffset === 0 && result.byteLength === result.buffer.byteLength;\n const bytes = options.owned && whole ? result : result.slice();\n reply({ id: data.id, result: bytes }, [bytes.buffer]);\n } else reply({ id: data.id, result: result ?? null });\n },\n (err: unknown) => {\n const code = (err as { code?: unknown })?.code;\n reply({\n id: data.id,\n errno: typeof code === 'string' ? code : 'EIO',\n message: err instanceof Error ? err.message : String(err),\n });\n }\n );\n });\n port.start?.();\n return { invalidate: (paths) => reply({ invalidate: paths }) };\n}\n", "import { attachKernel } from '../client/attach.ts';\nimport type { MessagePortLike } from '../client/protocol.ts';\nimport type { RealmTransportRequest, RealmTransportResponse } from '../kernel/net/transport.ts';\nimport { type FilesystemHandlers, serveFilesystem } from './driver.ts';\nimport { DRIVER_PROTOCOL, type DriverCapabilities } from './protocol.ts';\n\nexport interface DriverStart {\n code: string;\n driver: MessagePortLike;\n client: MessagePortLike;\n}\n\nexport interface DriverEnv {\n fetch(\n request: Omit<RealmTransportRequest, 'signal'> & { signal?: AbortSignal }\n ): Promise<RealmTransportResponse>;\n}\n\nexport type DriverFactory = (\n env: DriverEnv\n) =>\n | Promise<{ handlers: FilesystemHandlers; capabilities?: DriverCapabilities }>\n | { handlers: FilesystemHandlers; capabilities?: DriverCapabilities };\n\nexport async function hostDriver(\n start: DriverStart,\n load: (code: string) => Promise<{ default?: unknown }>\n): Promise<void> {\n try {\n const factory = (await load(start.code)).default;\n if (typeof factory !== 'function') {\n throw new Error('a slicc file system module must export a default function');\n }\n const client = await attachKernel(start.client, { locks: null });\n const made = await (factory as DriverFactory)({ fetch: (request) => client.fetch(request) });\n serveFilesystem(start.driver, made.handlers, made.capabilities ?? {});\n } catch (err) {\n start.driver.postMessage({\n hello: {\n protocol: DRIVER_PROTOCOL,\n error: `the driver did not start: ${err instanceof Error ? err.message : String(err)}`,\n errno: 'EIO',\n },\n });\n }\n}\n", "import { type DriverStart, hostDriver } from './mount/host.ts';\n\naddEventListener(\n 'message',\n (event) =>\n void hostDriver(\n (event as MessageEvent<DriverStart>).data,\n (code) => import(URL.createObjectURL(new Blob([code], { type: 'text/javascript' })))\n ),\n { once: true }\n);\n"],
|
|
5
|
-
"mappings": "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",
|
|
4
|
+
"sourcesContent": ["import type { CdpConnection, CdpHook, CdpRequest } from './types.ts';\n\nexport interface CdpPortLike {\n postMessage(message: unknown): void;\n addEventListener(type: 'message', handler: (event: MessageEvent) => void): void;\n start?(): void;\n close(): void;\n}\n\nexport type CdpWire = { open: true } | { error: string } | { m: string } | { close: string | null };\n\nexport interface CdpOpen {\n cdpOpen: CdpRequest & { registration?: number };\n port: CdpPortLike;\n}\n\nexport function serveCdpPort(\n port: CdpPortLike,\n hook: CdpHook,\n request: CdpRequest,\n onDone?: () => void\n): () => void {\n let conn: CdpConnection | undefined;\n let done = false;\n const end = () => {\n done = true;\n port.close();\n onDone?.();\n };\n const finish = (reason: string | null) => {\n if (done) return;\n port.postMessage({ close: reason });\n end();\n };\n port.addEventListener('message', ({ data }: MessageEvent<{ m?: string; close?: true }>) => {\n if (data.m !== undefined) conn?.send(data.m);\n else if (data.close && !done) {\n end();\n conn?.close();\n }\n });\n port.start?.();\n new Promise<CdpConnection>((resolve) => resolve(hook(request))).then(\n (opened) => {\n conn = opened;\n if (done) return opened.close();\n opened.onmessage = (m) => {\n if (!done) port.postMessage({ m });\n };\n opened.onclose = (reason) => finish(reason ?? null);\n port.postMessage({ open: true });\n },\n (e: unknown) => {\n if (done) return;\n port.postMessage({ error: e instanceof Error ? e.message : String(e) });\n end();\n }\n );\n return () => {\n if (done) return;\n conn?.close();\n finish('the CDP host is gone');\n };\n}\n\nexport function portCdpHook(\n ask: (request: CdpRequest, port: CdpPortLike) => void,\n gone?: Promise<unknown>\n): CdpHook {\n return (request) =>\n new Promise((resolve, reject) => {\n const { port1, port2 } = new MessageChannel();\n let closed = false;\n const conn: CdpConnection = {\n send: (m) => {\n if (!closed) port1.postMessage({ m });\n },\n onmessage: null,\n onclose: null,\n close: () => {\n if (closed) return;\n closed = true;\n port1.postMessage({ close: true });\n port1.close();\n },\n };\n port1.addEventListener('message', ({ data }: MessageEvent<CdpWire>) => {\n if ('m' in data) conn.onmessage?.(data.m);\n else if ('open' in data) resolve(conn);\n else if ('error' in data) {\n closed = true;\n port1.close();\n reject(new Error(data.error));\n } else if (!closed) {\n closed = true;\n port1.close();\n conn.onclose?.(data.close ?? undefined);\n }\n });\n port1.start();\n void gone?.then(() => {\n if (closed) return;\n closed = true;\n port1.close();\n reject(new Error('the CDP host is gone'));\n conn.onclose?.('the CDP host is gone');\n });\n ask(request, port2 as unknown as CdpPortLike);\n });\n}\n", "import type {\n HeaderList,\n RealmTransport,\n RealmTransportRequest,\n RealmTransportResponse,\n RealmTransportTraits,\n} from './transport.ts';\n\nexport type TransportCall =\n | {\n net: 'fetch';\n nid: number;\n url: string;\n method: string;\n headers: HeaderList;\n body?: Uint8Array;\n }\n | { net: 'read'; nid: number }\n | { net: 'cancel'; nid: number };\n\nexport type TransportReply =\n | { net: 'head'; nid: number; status: number; statusText: string; headers: HeaderList }\n | { net: 'chunk'; nid: number; bytes: Uint8Array }\n | { net: 'end'; nid: number }\n | { net: 'error'; nid: number; message: string; status?: number; code?: string };\n\nexport interface TransportPort {\n postMessage(message: TransportCall): void;\n}\n\nexport class TransportError extends Error {\n readonly status: number | undefined;\n readonly code: string | undefined;\n\n constructor(message: string, status?: number, code?: string) {\n super(message);\n this.status = status;\n this.code = code;\n }\n}\n\ninterface Waiter {\n resolve(reply: TransportReply): void;\n reject(error: Error): void;\n}\n\nexport class RemoteTransport implements RealmTransport {\n readonly traits: RealmTransportTraits;\n\n private readonly port: TransportPort;\n\n private readonly waiting = new Map<number, Waiter>();\n\n private nextId = 0;\n\n private failure: Error | undefined;\n\n constructor(port: TransportPort, traits: RealmTransportTraits) {\n this.port = port;\n this.traits = traits;\n }\n\n receive(reply: TransportReply): void {\n const waiter = this.waiting.get(reply.nid);\n if (!waiter) return;\n this.waiting.delete(reply.nid);\n if (reply.net === 'error') {\n waiter.reject(new TransportError(reply.message, reply.status, reply.code));\n } else waiter.resolve(reply);\n }\n\n fail(error: Error): void {\n this.failure = error;\n for (const waiter of this.waiting.values()) waiter.reject(error);\n this.waiting.clear();\n }\n\n private ask(call: TransportCall): Promise<TransportReply> {\n if (this.failure) return Promise.reject(this.failure);\n return new Promise((resolve, reject) => {\n this.waiting.set(call.nid, { resolve, reject });\n this.port.postMessage(call);\n });\n }\n\n private cancel(nid: number): void {\n const waiter = this.waiting.get(nid);\n this.waiting.delete(nid);\n waiter?.reject(new TransportError('the request was cancelled'));\n this.port.postMessage({ net: 'cancel', nid });\n }\n\n async fetch(request: RealmTransportRequest): Promise<RealmTransportResponse> {\n const nid = ++this.nextId;\n const { signal } = request;\n signal.throwIfAborted();\n let finished = false;\n const abort = () => {\n finished = true;\n this.cancel(nid);\n };\n signal.addEventListener('abort', abort, { once: true });\n const finish = () => {\n if (finished) return;\n finished = true;\n signal.removeEventListener('abort', abort);\n };\n let head: TransportReply;\n try {\n head = await this.ask({\n net: 'fetch',\n nid,\n url: request.url,\n method: request.method,\n headers: request.headers,\n ...(request.body ? { body: request.body } : {}),\n });\n } catch (e) {\n finish();\n throw e;\n }\n const { status, statusText, headers } = head as Extract<TransportReply, { net: 'head' }>;\n const read = async (): Promise<Uint8Array | undefined> => {\n if (finished) return undefined;\n const reply = await this.ask({ net: 'read', nid }).catch((e: unknown) => {\n finish();\n throw e;\n });\n if (reply.net === 'chunk') return reply.bytes;\n finish();\n return undefined;\n };\n const cancel = async () => {\n if (finished) return;\n finish();\n this.cancel(nid);\n };\n return {\n status,\n statusText,\n headers,\n cancel,\n body: {\n [Symbol.asyncIterator]: () => ({\n next: async () => {\n const bytes = await read();\n return bytes ? { value: bytes, done: false } : { value: undefined, done: true };\n },\n return: async () => {\n await cancel();\n return { value: undefined, done: true };\n },\n }),\n },\n };\n }\n}\n", "export interface DialledSocket {\n readable: ReadableStream<Uint8Array>;\n writable: WritableStream<Uint8Array>;\n close(): void;\n}\n\nexport interface DialOptions {\n port: number;\n host?: string;\n}\n\ninterface StreamPort {\n postMessage(message: unknown, transfer?: Transferable[]): void;\n addEventListener(type: 'message', handler: (event: MessageEvent) => void): void;\n start?(): void;\n close(): void;\n}\n\ntype DialMessage = Uint8Array | { end: true } | { ack: true } | { error: string };\n\nexport interface DialHandle extends DialledSocket {\n fail(error: Error): void;\n}\n\nexport function errorWithCode(message: string): Error & { code?: string } {\n const code = /^E[A-Z]+/.exec(message)?.[0];\n return Object.assign(new Error(message), code ? { code } : {});\n}\n\nexport function dialStream(port: StreamPort, onClose?: () => void): DialHandle {\n let closed = false;\n let reader: ReadableStreamDefaultController<Uint8Array> | undefined;\n const acks: Array<{ resolve: () => void; reject: (error: Error) => void }> = [];\n const readable = new ReadableStream<Uint8Array>({\n start(controller) {\n reader = controller;\n },\n pull() {\n if (!closed) port.postMessage({ more: true });\n },\n cancel() {\n reader = undefined;\n close();\n },\n });\n const finish = (fail?: Error) => {\n const controller = reader;\n reader = undefined;\n for (const ack of acks.splice(0)) {\n if (fail) ack.reject(fail);\n else ack.resolve();\n }\n if (!controller) return;\n if (fail) controller.error(fail);\n else controller.close();\n };\n function shut(): void {\n if (closed) return;\n closed = true;\n port.close();\n onClose?.();\n }\n function close(): void {\n if (!closed) port.postMessage({ close: true });\n shut();\n finish();\n }\n port.addEventListener('message', ({ data }: MessageEvent<DialMessage>) => {\n if (data instanceof Uint8Array) reader?.enqueue(data);\n else if ('ack' in data) acks.shift()?.resolve();\n else if ('end' in data) finish();\n else finish(errorWithCode(data.error));\n });\n port.start?.();\n const writable = new WritableStream<Uint8Array>({\n write(chunk) {\n if (closed) throw errorWithCode('EPIPE: the connection is closed');\n const copy = chunk.slice();\n const acked = new Promise<void>((resolve, reject) => acks.push({ resolve, reject }));\n port.postMessage(copy, [copy.buffer]);\n return acked;\n },\n close() {\n if (!closed) port.postMessage({ end: true });\n },\n abort() {\n close();\n },\n });\n const fail = (error: Error) => {\n shut();\n finish(error);\n };\n return { readable, writable, close, fail };\n}\n", "import { type DialledSocket, type DialOptions, errorWithCode } from './dial-stream.ts';\n\nexport interface LoopbackFetchOptions extends DialOptions {\n signal?: AbortSignal;\n}\n\nconst OWN_HEADERS = new Set(['host', 'connection', 'content-length', 'transfer-encoding']);\nconst encoder = new TextEncoder();\nconst latin1 = new TextDecoder('latin1');\n\nclass ByteSource {\n private buffered = new Uint8Array(0);\n private readonly reader: ReadableStreamDefaultReader<Uint8Array>;\n\n constructor(reader: ReadableStreamDefaultReader<Uint8Array>) {\n this.reader = reader;\n }\n\n private async more(): Promise<boolean> {\n const { done, value } = await this.reader.read();\n if (done) return false;\n const joined = new Uint8Array(this.buffered.length + value.length);\n joined.set(this.buffered);\n joined.set(value, this.buffered.length);\n this.buffered = joined;\n return true;\n }\n\n async until(marker: string): Promise<Uint8Array | undefined> {\n const needle = encoder.encode(marker);\n for (;;) {\n const at = indexOf(this.buffered, needle);\n if (at >= 0) return this.take(at + needle.length);\n if (!(await this.more())) return undefined;\n }\n }\n\n async some(max: number): Promise<Uint8Array | undefined> {\n if (this.buffered.length === 0 && !(await this.more())) return undefined;\n return this.take(Math.min(max, this.buffered.length));\n }\n\n async exactly(count: number): Promise<Uint8Array | undefined> {\n while (this.buffered.length < count) if (!(await this.more())) return undefined;\n return this.take(count);\n }\n\n private take(count: number): Uint8Array {\n const out = this.buffered.slice(0, count);\n this.buffered = this.buffered.slice(count);\n return out;\n }\n}\n\nfunction indexOf(haystack: Uint8Array, needle: Uint8Array): number {\n outer: for (let i = 0; i + needle.length <= haystack.length; i++) {\n for (let j = 0; j < needle.length; j++) if (haystack[i + j] !== needle[j]) continue outer;\n return i;\n }\n return -1;\n}\n\ninterface ResponseHead {\n status: number;\n statusText: string;\n headers: Array<[string, string]>;\n}\n\nfunction parseHead(bytes: Uint8Array): ResponseHead {\n const [statusLine = '', ...lines] = latin1.decode(bytes).split('\\r\\n');\n const match = /^HTTP\\/1\\.[01] (\\d{3})(?: (.*))?$/.exec(statusLine);\n if (!match) throw errorWithCode(`EPROTO: not an HTTP/1.x response: ${statusLine.slice(0, 80)}`);\n const headers: Array<[string, string]> = [];\n for (const line of lines) {\n const colon = line.indexOf(':');\n if (colon > 0) headers.push([line.slice(0, colon).trim(), line.slice(colon + 1).trim()]);\n }\n return { status: Number(match[1]), statusText: match[2] ?? '', headers };\n}\n\nfunction header(head: ResponseHead, name: string): string | undefined {\n return head.headers.find(([key]) => key.toLowerCase() === name)?.[1];\n}\n\nasync function* chunked(source: ByteSource): AsyncGenerator<Uint8Array> {\n for (;;) {\n const line = await source.until('\\r\\n');\n if (!line) throw errorWithCode('EPROTO: the chunked body ended early');\n const size = Number.parseInt(latin1.decode(line).trim().split(';')[0] ?? '', 16);\n if (!Number.isFinite(size)) throw errorWithCode('EPROTO: a malformed chunk size');\n if (size === 0) return;\n const data = await source.exactly(size);\n if (!data || !(await source.exactly(2))) throw errorWithCode('EPROTO: a chunk ended early');\n yield data;\n }\n}\n\nasync function* counted(source: ByteSource, length: number): AsyncGenerator<Uint8Array> {\n let left = length;\n while (left > 0) {\n const data = await source.some(left);\n if (!data) throw errorWithCode('EPROTO: the body ended early');\n left -= data.length;\n yield data;\n }\n}\n\nasync function* untilClose(source: ByteSource): AsyncGenerator<Uint8Array> {\n for (let data = await source.some(65536); data; data = await source.some(65536)) yield data;\n}\n\nfunction bodyOf(source: ByteSource, head: ResponseHead, method: string) {\n if (method === 'HEAD' || head.status === 204 || head.status === 304) return undefined;\n if (header(head, 'transfer-encoding')?.toLowerCase().includes('chunked')) return chunked(source);\n const length = header(head, 'content-length');\n if (length === undefined) return untilClose(source);\n const size = Number(length);\n if (!/^\\d+$/.test(length.trim()) || !Number.isSafeInteger(size)) {\n throw errorWithCode(`EPROTO: a malformed Content-Length: ${length}`);\n }\n return counted(source, size);\n}\n\nfunction stream(chunks: AsyncGenerator<Uint8Array>, socket: DialledSocket, signal?: AbortSignal) {\n return new ReadableStream<Uint8Array>({\n start(controller) {\n signal?.addEventListener('abort', () => controller.error(signal.reason), { once: true });\n },\n async pull(controller) {\n try {\n const next = await chunks.next();\n if (next.done) {\n controller.close();\n socket.close();\n } else controller.enqueue(next.value);\n } catch (err) {\n controller.error(err);\n socket.close();\n }\n },\n cancel() {\n socket.close();\n },\n });\n}\n\nasync function requestBytes(request: Request): Promise<Uint8Array> {\n const url = new URL(request.url);\n const body = request.body ? new Uint8Array(await request.arrayBuffer()) : undefined;\n const lines = [`${request.method} ${url.pathname}${url.search} HTTP/1.1`, `Host: ${url.host}`];\n request.headers.forEach((value, name) => {\n if (!OWN_HEADERS.has(name)) lines.push(`${name}: ${value}`);\n });\n if (body) lines.push(`Content-Length: ${body.length}`);\n lines.push('Connection: close', '', '');\n const head = encoder.encode(lines.join('\\r\\n'));\n const out = new Uint8Array(head.length + (body?.length ?? 0));\n out.set(head);\n if (body) out.set(body, head.length);\n return out;\n}\n\nexport async function loopbackFetch(\n dial: (options: DialOptions) => Promise<DialledSocket>,\n input: RequestInfo | URL,\n options: LoopbackFetchOptions\n): Promise<Response> {\n options.signal?.throwIfAborted();\n const request = input instanceof Request ? input : new Request(input);\n const bytes = await requestBytes(request);\n const socket = await dial({\n port: options.port,\n ...(options.host ? { host: options.host } : {}),\n });\n options.signal?.addEventListener('abort', () => socket.close(), { once: true });\n try {\n const writer = socket.writable.getWriter();\n await writer.write(bytes);\n writer.releaseLock();\n const source = new ByteSource(socket.readable.getReader());\n let head: ResponseHead;\n do {\n const raw = await source.until('\\r\\n\\r\\n');\n if (!raw) throw errorWithCode('ECONNRESET: the connection closed before a response');\n head = parseHead(raw);\n } while (head.status >= 100 && head.status < 200);\n const chunks = bodyOf(source, head, request.method);\n if (!chunks) socket.close();\n return new Response(chunks ? stream(chunks, socket, options.signal) : null, {\n status: head.status,\n statusText: head.statusText,\n headers: head.headers,\n });\n } catch (err) {\n socket.close();\n throw err;\n }\n}\n", "import type { WatchChange } from '../fs/watch.ts';\nimport type { TransportCall, TransportReply } from '../kernel/net/remote-transport.ts';\nimport type { RealmTransportTraits } from '../kernel/net/transport.ts';\nimport type { MountSpec } from '../mount/mount-fs.ts';\n\nexport const PROTOCOL: readonly [number, number] = [1, 7];\n\nexport interface ClientHello {\n protocol: readonly [number, number];\n lock?: string;\n}\n\nexport interface KernelHello {\n protocol: readonly [number, number];\n lock?: string;\n traits?: RealmTransportTraits;\n error?: string;\n}\n\nexport interface SpawnRequestOptions {\n cwd?: string;\n env?: Record<string, string>;\n stdin?: Uint8Array;\n pgid?: number;\n}\n\nexport interface TerminalRequestOptions {\n cwd?: string;\n env?: Record<string, string>;\n cols?: number;\n rows?: number;\n}\n\nexport type TerminalAction =\n | { action: 'write'; bytes: Uint8Array }\n | { action: 'resize'; cols: number; rows: number }\n | { action: 'signal'; signal: string }\n | { action: 'close' };\n\nexport const FS_METHODS = [\n 'readFile',\n 'writeFile',\n 'stat',\n 'lstat',\n 'readdir',\n 'mkdir',\n 'rm',\n 'rename',\n 'realpath',\n 'symlink',\n 'readlink',\n 'exists',\n] as const;\n\nexport type FsMethod = (typeof FS_METHODS)[number];\n\nexport type ClientCall =\n | { op: 'spawn'; argv: string[]; options: SpawnRequestOptions }\n | { op: 'open-terminal'; argv: string[]; options: TerminalRequestOptions }\n | ({ op: 'terminal'; terminal: number } & TerminalAction)\n | { op: 'kill'; pid: number; signal: string }\n | { op: 'ps' }\n | { op: 'fs'; method: FsMethod; args: unknown[] }\n | { op: 'watch'; paths: string[]; recursive: boolean }\n | { op: 'unwatch'; watch: number }\n | { op: 'mount'; spec: MountSpec }\n | { op: 'umount'; target: string }\n | { op: 'mounts' }\n | { op: 'dial'; port: number; host?: string }\n | { op: 'serve-cdp'; runtime?: string }\n | { op: 'unserve-cdp'; registration: number }\n | { op: 'detach'; kill?: boolean };\n\nexport type ClientRequest = ClientCall & { id: number };\n\nexport interface ClientReply {\n id: number;\n result?: unknown;\n error?: string;\n code?: string;\n fd?: 1 | 2;\n bytes?: Uint8Array;\n started?: number;\n}\n\nexport type ClientMessage = { hello: ClientHello } | ClientRequest | TransportCall;\n\nexport interface WatchEvent {\n watch: number;\n change: WatchChange;\n}\n\nexport type KernelMessage = { hello: KernelHello } | ClientReply | WatchEvent | TransportReply;\n\nexport interface ProcessEntry {\n pid: number;\n ppid: number;\n pgid: number;\n sid: number;\n argv: string[];\n tty: string | null;\n started: number;\n state: 'S' | 'Z';\n memory: number;\n}\n\nexport interface MessagePortLike {\n postMessage(message: unknown, transfer?: Transferable[]): void;\n addEventListener(type: 'message' | 'close', handler: (event: MessageEvent) => void): void;\n start?(): void;\n close?(): void;\n}\n\nexport interface LockManagerLike {\n request(name: string, callback: () => Promise<unknown> | unknown): Promise<unknown>;\n}\n\nexport function locksOf(scope: object = globalThis): LockManagerLike | undefined {\n const locks = (scope as { navigator?: { locks?: LockManagerLike } }).navigator?.locks;\n return typeof locks?.request === 'function' ? locks : undefined;\n}\n\nexport function versionError(theirs: unknown): string | undefined {\n const major = Array.isArray(theirs) ? theirs[0] : undefined;\n if (major === PROTOCOL[0]) return undefined;\n const named = typeof major === 'number' ? `${major}.x` : 'without a version';\n return `slicc-kernel client protocol ${named} is not supported: this side speaks ${PROTOCOL.join('.')}`;\n}\n", "import { type CdpOpen, serveCdpPort } from '../cdp/port.ts';\nimport type { CdpHook } from '../cdp/types.ts';\nimport type { FsStat } from '../fs/types.ts';\nimport type { WatchChange } from '../fs/watch.ts';\nimport { RemoteTransport, type TransportReply } from '../kernel/net/remote-transport.ts';\nimport type {\n RealmTransport,\n RealmTransportRequest,\n RealmTransportResponse,\n} from '../kernel/net/transport.ts';\nimport type { MountEntry, MountSpec } from '../mount/mount-fs.ts';\nimport { type DialledSocket, type DialOptions, dialStream } from './dial-stream.ts';\nimport { type LoopbackFetchOptions, loopbackFetch } from './loopback-fetch.ts';\nimport {\n type ClientCall,\n type ClientReply,\n type FsMethod,\n type KernelHello,\n type LockManagerLike,\n locksOf,\n type MessagePortLike,\n PROTOCOL,\n type ProcessEntry,\n type TerminalAction,\n versionError,\n} from './protocol.ts';\n\nexport type { WatchChange } from '../fs/watch.ts';\nexport type { ProcessEntry } from './protocol.ts';\n\nexport class KernelGoneError extends Error {\n constructor(message = 'the slicc-kernel this client was attached to is gone') {\n super(message);\n this.name = 'KernelGoneError';\n }\n}\n\nexport class KernelCallError extends Error {\n readonly code: string | undefined;\n\n constructor(message: string, code?: string) {\n super(message);\n this.name = 'KernelCallError';\n this.code = code;\n }\n}\n\nexport interface AttachOptions {\n timeoutMs?: number;\n locks?: LockManagerLike | null;\n}\n\nexport interface SpawnOptions {\n cwd?: string;\n env?: Record<string, string>;\n stdin?: string | Uint8Array;\n group?: 'new';\n pgid?: number;\n onStdout?: (bytes: Uint8Array) => void;\n onStderr?: (bytes: Uint8Array) => void;\n}\n\nexport interface SpawnedProcess {\n readonly pid: number;\n readonly pgid: number;\n readonly exited: Promise<number>;\n signal(name?: string): Promise<void>;\n}\n\nexport interface ClientRunOptions {\n cwd?: string;\n env?: Record<string, string>;\n stdin?: string | Uint8Array;\n onStdout?: (text: string) => void;\n onStderr?: (text: string) => void;\n}\n\nexport interface ClientRunResult {\n pid: number;\n status: number;\n stdout: string;\n stderr: string;\n}\n\nexport interface ClientTerminalOptions {\n cwd?: string;\n env?: Record<string, string>;\n cols?: number;\n rows?: number;\n onData?: (bytes: Uint8Array) => void;\n}\n\nexport interface ClientTerminal {\n readonly pid: number;\n readonly exited: Promise<number>;\n onData: ((bytes: Uint8Array) => void) | null;\n write(data: string | Uint8Array): void;\n resize(cols: number, rows: number): void;\n signal(name: string): void;\n close(): void;\n}\n\nexport interface ClientFs {\n readFile(path: string): Promise<Uint8Array>;\n readText(path: string): Promise<string>;\n writeFile(path: string, data: string | Uint8Array): Promise<void>;\n stat(path: string): Promise<FsStat>;\n lstat(path: string): Promise<FsStat>;\n readdir(path: string): Promise<string[]>;\n mkdir(path: string): Promise<void>;\n rm(path: string, options?: { force?: boolean }): Promise<void>;\n rename(from: string, to: string): Promise<void>;\n realpath(path: string): Promise<string>;\n symlink(target: string, path: string): Promise<void>;\n readlink(path: string): Promise<string>;\n exists(path: string): Promise<boolean>;\n watch(\n paths: string[],\n options: { recursive?: boolean },\n onChange: (change: WatchChange) => void\n ): Promise<{ close(): void }>;\n}\n\nexport type ClientFetchRequest = Omit<RealmTransportRequest, 'signal'> & { signal?: AbortSignal };\n\nexport interface KernelClient {\n readonly protocol: readonly [number, number];\n readonly transport: RealmTransport;\n readonly closed: Promise<Error>;\n spawn(argv: string[], options?: SpawnOptions): Promise<SpawnedProcess>;\n run(argv: string[], options?: ClientRunOptions): Promise<ClientRunResult>;\n openTerminal(argv: string[], options?: ClientTerminalOptions): Promise<ClientTerminal>;\n ps(): Promise<ProcessEntry[]>;\n mount(spec: MountSpec): Promise<MountEntry>;\n umount(target: string): Promise<void>;\n mounts(): Promise<MountEntry[]>;\n kill(pid: number, signal?: string): Promise<void>;\n fetch(request: ClientFetchRequest): Promise<RealmTransportResponse>;\n dial(options: DialOptions): Promise<DialledSocket>;\n loopbackFetch(input: RequestInfo | URL, options: LoopbackFetchOptions): Promise<Response>;\n readonly fs: ClientFs;\n serveCdp(hook: CdpHook, options?: { runtime?: string }): Promise<{ close(): void }>;\n close(options?: { kill?: boolean }): Promise<void>;\n}\n\ninterface Pending {\n resolve: (value: unknown) => void;\n reject: (error: Error) => void;\n output?: (fd: 1 | 2, bytes: Uint8Array) => void;\n started?: (pid: number) => void;\n}\n\ntype Handlers = Omit<Pending, 'resolve' | 'reject'>;\n\nconst encoder = new TextEncoder();\nconst bytesOf = (data: string | Uint8Array) =>\n typeof data === 'string' ? encoder.encode(data) : data;\n\nconst UNAVAILABLE = {\n manualRedirects: false,\n encodedBodies: false,\n maxRequestBody: 0,\n unavailable: true,\n} as const;\n\nasync function holdLock(\n locks: LockManagerLike | undefined\n): Promise<{ name?: string; release(): void }> {\n if (!locks) return { release() {} };\n const name = `slicc-kernel-client:${crypto.randomUUID()}`;\n const granted = Promise.withResolvers<void>();\n const held = Promise.withResolvers<void>();\n void locks.request(name, () => {\n granted.resolve();\n return held.promise;\n });\n await granted.promise;\n return { name, release: () => held.resolve() };\n}\n\nfunction concat(chunks: Uint8Array[]): Uint8Array {\n const out = new Uint8Array(chunks.reduce((n, c) => n + c.length, 0));\n let at = 0;\n for (const chunk of chunks) {\n out.set(chunk, at);\n at += chunk.length;\n }\n return out;\n}\n\nclass Channel {\n readonly greeted = Promise.withResolvers<KernelHello>();\n readonly ended = Promise.withResolvers<Error>();\n remote: RemoteTransport | undefined;\n failure: Error | undefined;\n private readonly pending = new Map<number, Pending>();\n readonly watching = new Map<number, (change: WatchChange) => void>();\n readonly cdpHooks = new Map<number, CdpHook>();\n private readonly cdpOpen = new Set<() => void>();\n protocol: readonly [number, number] = PROTOCOL;\n private nextId = 0;\n private readonly port: MessagePortLike;\n private readonly release: () => void;\n\n constructor(port: MessagePortLike, release: () => void) {\n this.port = port;\n this.release = release;\n this.greeted.promise.catch(() => undefined);\n port.addEventListener('message', (event) => this.receive(event.data));\n port.addEventListener('close', () => this.end(new KernelGoneError()));\n port.start?.();\n }\n\n post(message: object): void {\n if (!this.failure) this.port.postMessage(message);\n }\n\n end(error: Error): void {\n if (this.failure) return;\n this.failure = error;\n this.greeted.reject(error);\n this.remote?.fail(error);\n for (const close of [...this.cdpOpen]) close();\n this.cdpOpen.clear();\n for (const call of this.pending.values()) call.reject(error);\n this.pending.clear();\n this.release();\n this.port.close?.();\n this.ended.resolve(error);\n }\n\n request(call: ClientCall, handlers: Handlers = {}): { id: number; done: Promise<unknown> } {\n const id = ++this.nextId;\n const { failure } = this;\n if (failure) return { id, done: Promise.reject(failure) };\n const done = new Promise((resolve, reject) => {\n this.pending.set(id, { resolve, reject, ...handlers });\n this.port.postMessage({ ...call, id });\n });\n return { id, done };\n }\n\n call(call: ClientCall): Promise<unknown> {\n return this.request(call).done;\n }\n\n private receive(data: {\n hello?: KernelHello;\n net?: unknown;\n bye?: string;\n watch?: number;\n change?: WatchChange;\n cdpOpen?: CdpOpen['cdpOpen'];\n port?: CdpOpen['port'];\n }): void {\n if (data.cdpOpen && data.port) {\n this.openCdp(data as CdpOpen);\n return;\n }\n if (data.watch !== undefined) {\n this.watching.get(data.watch)?.(data.change as WatchChange);\n return;\n }\n if (data.bye !== undefined) {\n this.end(new KernelGoneError(data.bye));\n return;\n }\n if (data.hello) {\n this.greeted.resolve(data.hello);\n return;\n }\n if (data.net !== undefined) {\n this.remote?.receive(data as TransportReply);\n return;\n }\n const reply = data as ClientReply;\n const call = this.pending.get(reply.id);\n if (!call) return;\n if (reply.fd !== undefined) {\n call.output?.(reply.fd, reply.bytes as Uint8Array);\n return;\n }\n if (reply.started !== undefined) {\n call.started?.(reply.started);\n return;\n }\n this.pending.delete(reply.id);\n if (reply.error !== undefined) call.reject(new KernelCallError(reply.error, reply.code));\n else call.resolve(reply.result);\n }\n\n private openCdp({ cdpOpen: { registration, ...request }, port }: CdpOpen): void {\n const hook = registration === undefined ? undefined : this.cdpHooks.get(registration);\n if (!hook || this.failure) {\n port.postMessage({ error: 'this client no longer serves CDP' });\n port.close();\n return;\n }\n const close = serveCdpPort(port, hook, request, () => this.cdpOpen.delete(close));\n this.cdpOpen.add(close);\n }\n}\n\nasync function serveCdpOn(\n channel: Channel,\n hook: CdpHook,\n options: { runtime?: string }\n): Promise<{ close(): void }> {\n await since(channel, 5, 'CDP serving', async () => {});\n const req = {\n op: 'serve-cdp' as const,\n ...(options.runtime ? { runtime: options.runtime } : {}),\n };\n const { id, done } = channel.request(req);\n channel.cdpHooks.set(id, hook);\n try {\n await done;\n } catch (error) {\n channel.cdpHooks.delete(id);\n throw error;\n }\n return {\n close: () => {\n if (!channel.cdpHooks.delete(id)) return;\n void channel.call({ op: 'unserve-cdp', registration: id }).catch(() => undefined);\n },\n };\n}\n\nasync function dialOn(channel: Channel, { port, host }: DialOptions): Promise<DialledSocket> {\n const req = { op: 'dial' as const, port, ...(host ? { host } : {}) };\n return dialStream((await since(channel, 4, 'dial', () => channel.call(req))) as MessagePort);\n}\n\nasync function spawnOn(\n channel: Channel,\n argv: string[],\n opts: SpawnOptions\n): Promise<SpawnedProcess> {\n const { onStdout, onStderr, stdin, group: _, ...rest } = opts;\n if (opts.pgid !== undefined)\n await since(channel, 3, 'spawn into a process group', async () => {});\n const started = Promise.withResolvers<number>();\n const options = { ...rest, ...(stdin !== undefined ? { stdin: bytesOf(stdin) } : {}) };\n const { done } = channel.request(\n { op: 'spawn', argv, options },\n {\n output: (fd, bytes) => (fd === 1 ? onStdout : onStderr)?.(bytes),\n started: started.resolve,\n }\n );\n done.catch(started.reject);\n const pid = await started.promise;\n const pgid = opts.pgid ?? pid;\n return {\n pid,\n pgid,\n exited: done as Promise<number>,\n signal: async (name = 'SIGTERM') =>\n void (await channel.call({ op: 'kill', pid: -pgid, signal: name })),\n };\n}\n\nasync function runOn(\n channel: Channel,\n argv: string[],\n opts: ClientRunOptions\n): Promise<ClientRunResult> {\n const { onStdout, onStderr, ...rest } = opts;\n const chunks: Record<1 | 2, Uint8Array[]> = { 1: [], 2: [] };\n const live = { 1: new TextDecoder(), 2: new TextDecoder() };\n const tee = (fd: 1 | 2, on?: (text: string) => void) => (bytes: Uint8Array) => {\n chunks[fd].push(bytes);\n on?.(live[fd].decode(bytes, { stream: true }));\n };\n const child = await spawnOn(channel, argv, {\n ...rest,\n onStdout: tee(1, onStdout),\n onStderr: tee(2, onStderr),\n });\n const status = await child.exited;\n const text = (fd: 1 | 2) => new TextDecoder().decode(concat(chunks[fd]));\n return { pid: child.pid, status, stdout: text(1), stderr: text(2) };\n}\n\nasync function terminalOn(\n channel: Channel,\n argv: string[],\n opts: ClientTerminalOptions\n): Promise<ClientTerminal> {\n const { onData, ...options } = opts;\n let listener = onData ?? null;\n const backlog: Uint8Array[] = [];\n const started = Promise.withResolvers<number>();\n const { id, done } = channel.request(\n { op: 'open-terminal', argv, options },\n {\n output: (_fd, bytes) => (listener ? listener(bytes) : backlog.push(bytes)),\n started: started.resolve,\n }\n );\n done.catch(started.reject);\n const pid = await started.promise;\n const send = (action: TerminalAction) =>\n void channel.call({ op: 'terminal', terminal: id, ...action }).catch(() => undefined);\n return {\n pid,\n exited: done as Promise<number>,\n get onData() {\n return listener;\n },\n set onData(next) {\n listener = next;\n if (next) for (const bytes of backlog.splice(0)) next(bytes);\n },\n write: (data) => send({ action: 'write', bytes: bytesOf(data) }),\n resize: (cols, rows) => send({ action: 'resize', cols, rows }),\n signal: (name) => send({ action: 'signal', signal: name }),\n close: () => send({ action: 'close' }),\n };\n}\n\nfunction fsOn(channel: Channel): ClientFs {\n const fs = (method: FsMethod, ...args: unknown[]) => channel.call({ op: 'fs', method, args });\n const done = async (method: FsMethod, ...args: unknown[]) => void (await fs(method, ...args));\n return {\n readFile: (path) => fs('readFile', path) as Promise<Uint8Array>,\n readText: async (path) => new TextDecoder().decode((await fs('readFile', path)) as Uint8Array),\n writeFile: (path, data) => done('writeFile', path, data),\n stat: (path) => fs('stat', path) as Promise<FsStat>,\n lstat: (path) => fs('lstat', path) as Promise<FsStat>,\n readdir: (path) => fs('readdir', path) as Promise<string[]>,\n mkdir: (path) => done('mkdir', path),\n rm: (path, o = {}) => done('rm', path, o.force === true),\n rename: (from, to) => done('rename', from, to),\n realpath: (path) => fs('realpath', path) as Promise<string>,\n symlink: (target, path) => done('symlink', target, path),\n readlink: (path) => fs('readlink', path) as Promise<string>,\n exists: (path) => fs('exists', path) as Promise<boolean>,\n async watch(paths, options, onChange) {\n if (channel.protocol[1] < 1) {\n throw new KernelCallError(\n `this kernel speaks protocol ${channel.protocol.join('.')}, which has no watch`,\n 'ENOSYS'\n );\n }\n const { id, done } = channel.request({\n op: 'watch',\n paths,\n recursive: options.recursive === true,\n });\n channel.watching.set(id, onChange);\n try {\n await done;\n } catch (error) {\n channel.watching.delete(id);\n throw error;\n }\n return {\n close: () => {\n if (!channel.watching.delete(id)) return;\n void channel.call({ op: 'unwatch', watch: id }).catch(() => undefined);\n },\n };\n },\n };\n}\n\nfunction since(channel: Channel, minor: number, what: string, run: () => Promise<unknown>) {\n if (channel.protocol[1] < minor) {\n return Promise.reject(\n new KernelCallError(\n `this kernel speaks protocol ${channel.protocol.join('.')}, which has no ${what}`,\n 'ENOSYS'\n )\n );\n }\n return run();\n}\n\nasync function greet(\n channel: Channel,\n lock: string | undefined,\n timeoutMs: number\n): Promise<KernelHello> {\n channel.post({ hello: { protocol: PROTOCOL, ...(lock ? { lock } : {}) } });\n const timer = setTimeout(\n () =>\n channel.end(\n new KernelGoneError(`no slicc-kernel answered on this port within ${timeoutMs} ms`)\n ),\n timeoutMs\n );\n let hello: KernelHello;\n try {\n hello = await channel.greeted.promise;\n } finally {\n clearTimeout(timer);\n }\n const refused = hello.error ?? versionError(hello.protocol);\n if (refused) {\n const error = new Error(refused);\n channel.end(error);\n throw error;\n }\n return hello;\n}\n\nexport async function attachKernel(\n port: MessagePortLike,\n options: AttachOptions = {}\n): Promise<KernelClient> {\n const locks = options.locks === null ? undefined : (options.locks ?? locksOf());\n const own = await holdLock(locks);\n const channel = new Channel(port, own.release);\n const hello = await greet(channel, own.name, options.timeoutMs ?? 10_000);\n channel.protocol = hello.protocol;\n if (hello.lock && locks) void locks.request(hello.lock, () => channel.end(new KernelGoneError()));\n const transport = new RemoteTransport(\n { postMessage: (call) => channel.post(call) },\n hello.traits ?? UNAVAILABLE\n );\n channel.remote = transport;\n return {\n protocol: hello.protocol,\n transport,\n closed: channel.ended.promise,\n spawn: (argv, opts = {}) => spawnOn(channel, argv, opts),\n run: (argv, opts = {}) => runOn(channel, argv, opts),\n openTerminal: (argv, opts = {}) => terminalOn(channel, argv, opts),\n ps: () => channel.call({ op: 'ps' }) as Promise<ProcessEntry[]>,\n mount: (spec) =>\n since(channel, 2, 'mount', () => channel.call({ op: 'mount', spec })) as Promise<MountEntry>,\n umount: async (target) =>\n void (await since(channel, 2, 'umount', () => channel.call({ op: 'umount', target }))),\n mounts: () =>\n since(channel, 2, 'mounts', () => channel.call({ op: 'mounts' })) as Promise<MountEntry[]>,\n kill: async (pid, signal = 'SIGTERM') => void (await channel.call({ op: 'kill', pid, signal })),\n fetch: (req) => {\n const { signal, ...rest } = req;\n return transport.fetch({ ...rest, signal: signal ?? new AbortController().signal });\n },\n dial: (options) => dialOn(channel, options),\n loopbackFetch: (input, options) => loopbackFetch((o) => dialOn(channel, o), input, options),\n fs: fsOn(channel),\n serveCdp: (hook, options = {}) => serveCdpOn(channel, hook, options),\n async close(o = {}) {\n if (channel.failure) return;\n await channel\n .call({ op: 'detach', ...(o.kill ? { kill: true } : {}) })\n .catch(() => undefined);\n channel.end(new KernelGoneError('this client is closed'));\n },\n };\n}\n", "export const DRIVER_PROTOCOL: readonly [number, number] = [1, 1];\n\nexport interface DriverCapabilities {\n readonly?: boolean;\n symlinks?: boolean;\n chmod?: boolean;\n linkTimes?: boolean;\n ranges?: boolean;\n listingStats?: boolean;\n caseInsensitive?: boolean;\n normalization?: 'none' | 'nfc' | 'nfd-insensitive';\n maxIo?: number;\n maxFile?: number;\n attrTtl?: number;\n entryTtl?: number;\n}\n\nexport interface DriverAttr {\n kind: 'file' | 'directory' | 'symlink';\n size: number;\n mtime: number;\n mode?: number;\n ino?: number;\n etag?: string;\n}\n\nexport interface DriverEntry {\n name: string;\n kind: DriverAttr['kind'];\n attr?: DriverAttr;\n}\n\nexport interface DriverStatfs {\n bsize: number;\n blocks: number;\n bfree: number;\n}\n\nexport interface MountRequestInfo {\n source: string;\n options: Record<string, string>;\n}\n\nexport type DriverCall =\n | { op: 'getattr'; path: string }\n | { op: 'readdir'; path: string }\n | {\n op: 'open';\n path: string;\n write: boolean;\n create: boolean;\n truncate: boolean;\n exclusive: boolean;\n ifMatch?: string;\n }\n | { op: 'read'; fh: number; offset: number; size: number }\n | { op: 'write'; fh: number; offset: number; bytes: Uint8Array }\n | { op: 'release'; fh: number }\n | { op: 'mkdir'; path: string }\n | { op: 'rmdir'; path: string }\n | { op: 'unlink'; path: string }\n | { op: 'rename'; from: string; to: string }\n | { op: 'symlink'; target: string; path: string }\n | { op: 'readlink'; path: string }\n | { op: 'setattr'; path: string; mode?: number; mtime?: number; size?: number }\n | { op: 'statfs' };\n\nexport type DriverRequest = DriverCall & { id: number };\n\nexport interface DriverReply {\n id: number;\n result?: unknown;\n errno?: string;\n message?: string;\n}\n\nexport interface KernelDriverHello {\n protocol: readonly [number, number];\n mount: MountRequestInfo;\n}\n\nexport interface DriverHello {\n protocol: readonly [number, number];\n capabilities?: DriverCapabilities;\n error?: string;\n errno?: string;\n}\n\nexport type KernelToDriver = { hello: KernelDriverHello } | DriverRequest;\n\nexport type DriverToKernel = { hello: DriverHello } | DriverReply | { invalidate: string[] | true };\n\nexport function driverVersionError(theirs: unknown): string | undefined {\n const major = Array.isArray(theirs) ? theirs[0] : undefined;\n if (major === DRIVER_PROTOCOL[0]) return undefined;\n const named = typeof major === 'number' ? `${major}.x` : 'without a version';\n return `slicc-kernel driver protocol ${named} is not supported: this side speaks ${DRIVER_PROTOCOL.join('.')}`;\n}\n", "import {\n DRIVER_PROTOCOL,\n type DriverAttr,\n type DriverCapabilities,\n type DriverEntry,\n type DriverRequest,\n type DriverStatfs,\n driverVersionError,\n type KernelDriverHello,\n type MountRequestInfo,\n} from './protocol.ts';\n\nexport type {\n DriverAttr,\n DriverCapabilities,\n DriverEntry,\n DriverStatfs,\n MountRequestInfo,\n} from './protocol.ts';\n\nexport interface OpenFlags {\n write: boolean;\n create: boolean;\n truncate: boolean;\n exclusive: boolean;\n ifMatch?: string;\n}\n\nexport interface FilesystemHandlers {\n mount?(\n info: MountRequestInfo\n ): Promise<DriverCapabilities | undefined> | DriverCapabilities | undefined;\n getattr(path: string): Promise<DriverAttr>;\n readdir(path: string): Promise<DriverEntry[]>;\n open(path: string, flags: OpenFlags): Promise<number>;\n read(fh: number, offset: number, size: number): Promise<Uint8Array>;\n write(fh: number, offset: number, bytes: Uint8Array): Promise<void>;\n release(fh: number): Promise<void>;\n mkdir(path: string): Promise<void>;\n rmdir(path: string): Promise<void>;\n unlink(path: string): Promise<void>;\n rename(from: string, to: string): Promise<void>;\n symlink?(target: string, path: string): Promise<void>;\n readlink?(path: string): Promise<string>;\n setattr?(path: string, attr: { mode?: number; mtime?: number; size?: number }): Promise<void>;\n statfs?(): Promise<DriverStatfs>;\n}\n\nexport interface DriverPort {\n postMessage(message: unknown, transfer?: Transferable[]): void;\n addEventListener(type: 'message', handler: (event: MessageEvent) => void): void;\n start?(): void;\n}\n\nexport interface ServedFilesystem {\n invalidate(paths: string[] | true): void;\n}\n\nexport function fsError(code: string, message = code): Error & { code: string } {\n return Object.assign(new Error(message), { code });\n}\n\nasync function dispatch(h: FilesystemHandlers, req: DriverRequest): Promise<unknown> {\n switch (req.op) {\n case 'getattr':\n return h.getattr(req.path);\n case 'readdir':\n return h.readdir(req.path);\n case 'open':\n return h.open(req.path, {\n write: req.write,\n create: req.create,\n truncate: req.truncate,\n exclusive: req.exclusive,\n ...(req.ifMatch !== undefined ? { ifMatch: req.ifMatch } : {}),\n });\n case 'read':\n return h.read(req.fh, req.offset, req.size);\n case 'write':\n return h.write(req.fh, req.offset, req.bytes);\n case 'release':\n return h.release(req.fh);\n case 'mkdir':\n return h.mkdir(req.path);\n case 'rmdir':\n return h.rmdir(req.path);\n case 'unlink':\n return h.unlink(req.path);\n case 'rename':\n return h.rename(req.from, req.to);\n case 'symlink':\n if (!h.symlink) throw fsError('EPERM', 'this file system has no symlinks');\n return h.symlink(req.target, req.path);\n case 'readlink':\n if (!h.readlink) throw fsError('EINVAL', `${req.path} is not a symlink`);\n return h.readlink(req.path);\n case 'setattr':\n return h.setattr?.(req.path, {\n ...(req.mode !== undefined ? { mode: req.mode } : {}),\n ...(req.mtime !== undefined ? { mtime: req.mtime } : {}),\n ...(req.size !== undefined ? { size: req.size } : {}),\n });\n case 'statfs':\n return h.statfs?.() ?? null;\n default:\n throw fsError('ENOSYS', `unknown driver op ${(req as { op: string }).op}`);\n }\n}\n\nexport function serveFilesystem(\n port: DriverPort,\n handlers: FilesystemHandlers,\n capabilities: DriverCapabilities = {},\n options: { owned?: boolean } = {}\n): ServedFilesystem {\n let open = false;\n const reply = (message: object, transfer: Transferable[] = []) =>\n port.postMessage(message, transfer);\n async function hello(message: KernelDriverHello): Promise<void> {\n const refused = driverVersionError(message.protocol);\n if (refused) {\n reply({ hello: { protocol: DRIVER_PROTOCOL, error: refused, errno: 'EPROTO' } });\n return;\n }\n try {\n const refined = await handlers.mount?.(message.mount);\n open = true;\n reply({\n hello: { protocol: DRIVER_PROTOCOL, capabilities: { ...capabilities, ...refined } },\n });\n } catch (err) {\n const code = (err as { code?: unknown })?.code;\n reply({\n hello: {\n protocol: DRIVER_PROTOCOL,\n error: err instanceof Error ? err.message : String(err),\n errno: typeof code === 'string' ? code : 'EIO',\n },\n });\n }\n }\n port.addEventListener('message', (event) => {\n const data = event.data as { hello?: KernelDriverHello } & DriverRequest;\n if (data.hello) {\n void hello(data.hello);\n return;\n }\n if (!open) return;\n dispatch(handlers, data).then(\n (result) => {\n if (result instanceof Uint8Array) {\n const whole = result.byteOffset === 0 && result.byteLength === result.buffer.byteLength;\n const bytes = options.owned && whole ? result : result.slice();\n reply({ id: data.id, result: bytes }, [bytes.buffer]);\n } else reply({ id: data.id, result: result ?? null });\n },\n (err: unknown) => {\n const code = (err as { code?: unknown })?.code;\n reply({\n id: data.id,\n errno: typeof code === 'string' ? code : 'EIO',\n message: err instanceof Error ? err.message : String(err),\n });\n }\n );\n });\n port.start?.();\n return { invalidate: (paths) => reply({ invalidate: paths }) };\n}\n", "import { attachKernel } from '../client/attach.ts';\nimport type { MessagePortLike } from '../client/protocol.ts';\nimport type { RealmTransportRequest, RealmTransportResponse } from '../kernel/net/transport.ts';\nimport { type FilesystemHandlers, serveFilesystem } from './driver.ts';\nimport { DRIVER_PROTOCOL, type DriverCapabilities } from './protocol.ts';\n\nexport interface DriverStart {\n code: string;\n driver: MessagePortLike;\n client: MessagePortLike;\n}\n\nexport interface DriverEnv {\n fetch(\n request: Omit<RealmTransportRequest, 'signal'> & { signal?: AbortSignal }\n ): Promise<RealmTransportResponse>;\n}\n\nexport type DriverFactory = (\n env: DriverEnv\n) =>\n | Promise<{ handlers: FilesystemHandlers; capabilities?: DriverCapabilities }>\n | { handlers: FilesystemHandlers; capabilities?: DriverCapabilities };\n\nexport async function hostDriver(\n start: DriverStart,\n load: (code: string) => Promise<{ default?: unknown }>\n): Promise<void> {\n try {\n const factory = (await load(start.code)).default;\n if (typeof factory !== 'function') {\n throw new Error('a slicc file system module must export a default function');\n }\n const client = await attachKernel(start.client, { locks: null });\n const made = await (factory as DriverFactory)({ fetch: (request) => client.fetch(request) });\n serveFilesystem(start.driver, made.handlers, made.capabilities ?? {});\n } catch (err) {\n start.driver.postMessage({\n hello: {\n protocol: DRIVER_PROTOCOL,\n error: `the driver did not start: ${err instanceof Error ? err.message : String(err)}`,\n errno: 'EIO',\n },\n });\n }\n}\n", "import { type DriverStart, hostDriver } from './mount/host.ts';\n\naddEventListener(\n 'message',\n (event) =>\n void hostDriver(\n (event as MessageEvent<DriverStart>).data,\n (code) => import(URL.createObjectURL(new Blob([code], { type: 'text/javascript' })))\n ),\n { once: true }\n);\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["fail", "encoder", "done", "options"]
|
|
7
7
|
}
|
package/dist/driver.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/mount/protocol.ts", "../src/mount/driver.ts"],
|
|
4
|
-
"sourcesContent": ["export const DRIVER_PROTOCOL: readonly [number, number] = [1, 1];\n\nexport interface DriverCapabilities {\n readonly?: boolean;\n symlinks?: boolean;\n chmod?: boolean;\n ranges?: boolean;\n listingStats?: boolean;\n caseInsensitive?: boolean;\n normalization?: 'none' | 'nfc' | 'nfd-insensitive';\n maxIo?: number;\n maxFile?: number;\n attrTtl?: number;\n entryTtl?: number;\n}\n\nexport interface DriverAttr {\n kind: 'file' | 'directory' | 'symlink';\n size: number;\n mtime: number;\n mode?: number;\n ino?: number;\n etag?: string;\n}\n\nexport interface DriverEntry {\n name: string;\n kind: DriverAttr['kind'];\n attr?: DriverAttr;\n}\n\nexport interface DriverStatfs {\n bsize: number;\n blocks: number;\n bfree: number;\n}\n\nexport interface MountRequestInfo {\n source: string;\n options: Record<string, string>;\n}\n\nexport type DriverCall =\n | { op: 'getattr'; path: string }\n | { op: 'readdir'; path: string }\n | {\n op: 'open';\n path: string;\n write: boolean;\n create: boolean;\n truncate: boolean;\n exclusive: boolean;\n ifMatch?: string;\n }\n | { op: 'read'; fh: number; offset: number; size: number }\n | { op: 'write'; fh: number; offset: number; bytes: Uint8Array }\n | { op: 'release'; fh: number }\n | { op: 'mkdir'; path: string }\n | { op: 'rmdir'; path: string }\n | { op: 'unlink'; path: string }\n | { op: 'rename'; from: string; to: string }\n | { op: 'symlink'; target: string; path: string }\n | { op: 'readlink'; path: string }\n | { op: 'setattr'; path: string; mode?: number; mtime?: number; size?: number }\n | { op: 'statfs' };\n\nexport type DriverRequest = DriverCall & { id: number };\n\nexport interface DriverReply {\n id: number;\n result?: unknown;\n errno?: string;\n message?: string;\n}\n\nexport interface KernelDriverHello {\n protocol: readonly [number, number];\n mount: MountRequestInfo;\n}\n\nexport interface DriverHello {\n protocol: readonly [number, number];\n capabilities?: DriverCapabilities;\n error?: string;\n errno?: string;\n}\n\nexport type KernelToDriver = { hello: KernelDriverHello } | DriverRequest;\n\nexport type DriverToKernel = { hello: DriverHello } | DriverReply | { invalidate: string[] | true };\n\nexport function driverVersionError(theirs: unknown): string | undefined {\n const major = Array.isArray(theirs) ? theirs[0] : undefined;\n if (major === DRIVER_PROTOCOL[0]) return undefined;\n const named = typeof major === 'number' ? `${major}.x` : 'without a version';\n return `slicc-kernel driver protocol ${named} is not supported: this side speaks ${DRIVER_PROTOCOL.join('.')}`;\n}\n", "import {\n DRIVER_PROTOCOL,\n type DriverAttr,\n type DriverCapabilities,\n type DriverEntry,\n type DriverRequest,\n type DriverStatfs,\n driverVersionError,\n type KernelDriverHello,\n type MountRequestInfo,\n} from './protocol.ts';\n\nexport type {\n DriverAttr,\n DriverCapabilities,\n DriverEntry,\n DriverStatfs,\n MountRequestInfo,\n} from './protocol.ts';\n\nexport interface OpenFlags {\n write: boolean;\n create: boolean;\n truncate: boolean;\n exclusive: boolean;\n ifMatch?: string;\n}\n\nexport interface FilesystemHandlers {\n mount?(\n info: MountRequestInfo\n ): Promise<DriverCapabilities | undefined> | DriverCapabilities | undefined;\n getattr(path: string): Promise<DriverAttr>;\n readdir(path: string): Promise<DriverEntry[]>;\n open(path: string, flags: OpenFlags): Promise<number>;\n read(fh: number, offset: number, size: number): Promise<Uint8Array>;\n write(fh: number, offset: number, bytes: Uint8Array): Promise<void>;\n release(fh: number): Promise<void>;\n mkdir(path: string): Promise<void>;\n rmdir(path: string): Promise<void>;\n unlink(path: string): Promise<void>;\n rename(from: string, to: string): Promise<void>;\n symlink?(target: string, path: string): Promise<void>;\n readlink?(path: string): Promise<string>;\n setattr?(path: string, attr: { mode?: number; mtime?: number; size?: number }): Promise<void>;\n statfs?(): Promise<DriverStatfs>;\n}\n\nexport interface DriverPort {\n postMessage(message: unknown, transfer?: Transferable[]): void;\n addEventListener(type: 'message', handler: (event: MessageEvent) => void): void;\n start?(): void;\n}\n\nexport interface ServedFilesystem {\n invalidate(paths: string[] | true): void;\n}\n\nexport function fsError(code: string, message = code): Error & { code: string } {\n return Object.assign(new Error(message), { code });\n}\n\nasync function dispatch(h: FilesystemHandlers, req: DriverRequest): Promise<unknown> {\n switch (req.op) {\n case 'getattr':\n return h.getattr(req.path);\n case 'readdir':\n return h.readdir(req.path);\n case 'open':\n return h.open(req.path, {\n write: req.write,\n create: req.create,\n truncate: req.truncate,\n exclusive: req.exclusive,\n ...(req.ifMatch !== undefined ? { ifMatch: req.ifMatch } : {}),\n });\n case 'read':\n return h.read(req.fh, req.offset, req.size);\n case 'write':\n return h.write(req.fh, req.offset, req.bytes);\n case 'release':\n return h.release(req.fh);\n case 'mkdir':\n return h.mkdir(req.path);\n case 'rmdir':\n return h.rmdir(req.path);\n case 'unlink':\n return h.unlink(req.path);\n case 'rename':\n return h.rename(req.from, req.to);\n case 'symlink':\n if (!h.symlink) throw fsError('EPERM', 'this file system has no symlinks');\n return h.symlink(req.target, req.path);\n case 'readlink':\n if (!h.readlink) throw fsError('EINVAL', `${req.path} is not a symlink`);\n return h.readlink(req.path);\n case 'setattr':\n return h.setattr?.(req.path, {\n ...(req.mode !== undefined ? { mode: req.mode } : {}),\n ...(req.mtime !== undefined ? { mtime: req.mtime } : {}),\n ...(req.size !== undefined ? { size: req.size } : {}),\n });\n case 'statfs':\n return h.statfs?.() ?? null;\n default:\n throw fsError('ENOSYS', `unknown driver op ${(req as { op: string }).op}`);\n }\n}\n\nexport function serveFilesystem(\n port: DriverPort,\n handlers: FilesystemHandlers,\n capabilities: DriverCapabilities = {},\n options: { owned?: boolean } = {}\n): ServedFilesystem {\n let open = false;\n const reply = (message: object, transfer: Transferable[] = []) =>\n port.postMessage(message, transfer);\n async function hello(message: KernelDriverHello): Promise<void> {\n const refused = driverVersionError(message.protocol);\n if (refused) {\n reply({ hello: { protocol: DRIVER_PROTOCOL, error: refused, errno: 'EPROTO' } });\n return;\n }\n try {\n const refined = await handlers.mount?.(message.mount);\n open = true;\n reply({\n hello: { protocol: DRIVER_PROTOCOL, capabilities: { ...capabilities, ...refined } },\n });\n } catch (err) {\n const code = (err as { code?: unknown })?.code;\n reply({\n hello: {\n protocol: DRIVER_PROTOCOL,\n error: err instanceof Error ? err.message : String(err),\n errno: typeof code === 'string' ? code : 'EIO',\n },\n });\n }\n }\n port.addEventListener('message', (event) => {\n const data = event.data as { hello?: KernelDriverHello } & DriverRequest;\n if (data.hello) {\n void hello(data.hello);\n return;\n }\n if (!open) return;\n dispatch(handlers, data).then(\n (result) => {\n if (result instanceof Uint8Array) {\n const whole = result.byteOffset === 0 && result.byteLength === result.buffer.byteLength;\n const bytes = options.owned && whole ? result : result.slice();\n reply({ id: data.id, result: bytes }, [bytes.buffer]);\n } else reply({ id: data.id, result: result ?? null });\n },\n (err: unknown) => {\n const code = (err as { code?: unknown })?.code;\n reply({\n id: data.id,\n errno: typeof code === 'string' ? code : 'EIO',\n message: err instanceof Error ? err.message : String(err),\n });\n }\n );\n });\n port.start?.();\n return { invalidate: (paths) => reply({ invalidate: paths }) };\n}\n"],
|
|
5
|
-
"mappings": ";AAAO,IAAM,kBAA6C,CAAC,GAAG,CAAC;
|
|
4
|
+
"sourcesContent": ["export const DRIVER_PROTOCOL: readonly [number, number] = [1, 1];\n\nexport interface DriverCapabilities {\n readonly?: boolean;\n symlinks?: boolean;\n chmod?: boolean;\n linkTimes?: boolean;\n ranges?: boolean;\n listingStats?: boolean;\n caseInsensitive?: boolean;\n normalization?: 'none' | 'nfc' | 'nfd-insensitive';\n maxIo?: number;\n maxFile?: number;\n attrTtl?: number;\n entryTtl?: number;\n}\n\nexport interface DriverAttr {\n kind: 'file' | 'directory' | 'symlink';\n size: number;\n mtime: number;\n mode?: number;\n ino?: number;\n etag?: string;\n}\n\nexport interface DriverEntry {\n name: string;\n kind: DriverAttr['kind'];\n attr?: DriverAttr;\n}\n\nexport interface DriverStatfs {\n bsize: number;\n blocks: number;\n bfree: number;\n}\n\nexport interface MountRequestInfo {\n source: string;\n options: Record<string, string>;\n}\n\nexport type DriverCall =\n | { op: 'getattr'; path: string }\n | { op: 'readdir'; path: string }\n | {\n op: 'open';\n path: string;\n write: boolean;\n create: boolean;\n truncate: boolean;\n exclusive: boolean;\n ifMatch?: string;\n }\n | { op: 'read'; fh: number; offset: number; size: number }\n | { op: 'write'; fh: number; offset: number; bytes: Uint8Array }\n | { op: 'release'; fh: number }\n | { op: 'mkdir'; path: string }\n | { op: 'rmdir'; path: string }\n | { op: 'unlink'; path: string }\n | { op: 'rename'; from: string; to: string }\n | { op: 'symlink'; target: string; path: string }\n | { op: 'readlink'; path: string }\n | { op: 'setattr'; path: string; mode?: number; mtime?: number; size?: number }\n | { op: 'statfs' };\n\nexport type DriverRequest = DriverCall & { id: number };\n\nexport interface DriverReply {\n id: number;\n result?: unknown;\n errno?: string;\n message?: string;\n}\n\nexport interface KernelDriverHello {\n protocol: readonly [number, number];\n mount: MountRequestInfo;\n}\n\nexport interface DriverHello {\n protocol: readonly [number, number];\n capabilities?: DriverCapabilities;\n error?: string;\n errno?: string;\n}\n\nexport type KernelToDriver = { hello: KernelDriverHello } | DriverRequest;\n\nexport type DriverToKernel = { hello: DriverHello } | DriverReply | { invalidate: string[] | true };\n\nexport function driverVersionError(theirs: unknown): string | undefined {\n const major = Array.isArray(theirs) ? theirs[0] : undefined;\n if (major === DRIVER_PROTOCOL[0]) return undefined;\n const named = typeof major === 'number' ? `${major}.x` : 'without a version';\n return `slicc-kernel driver protocol ${named} is not supported: this side speaks ${DRIVER_PROTOCOL.join('.')}`;\n}\n", "import {\n DRIVER_PROTOCOL,\n type DriverAttr,\n type DriverCapabilities,\n type DriverEntry,\n type DriverRequest,\n type DriverStatfs,\n driverVersionError,\n type KernelDriverHello,\n type MountRequestInfo,\n} from './protocol.ts';\n\nexport type {\n DriverAttr,\n DriverCapabilities,\n DriverEntry,\n DriverStatfs,\n MountRequestInfo,\n} from './protocol.ts';\n\nexport interface OpenFlags {\n write: boolean;\n create: boolean;\n truncate: boolean;\n exclusive: boolean;\n ifMatch?: string;\n}\n\nexport interface FilesystemHandlers {\n mount?(\n info: MountRequestInfo\n ): Promise<DriverCapabilities | undefined> | DriverCapabilities | undefined;\n getattr(path: string): Promise<DriverAttr>;\n readdir(path: string): Promise<DriverEntry[]>;\n open(path: string, flags: OpenFlags): Promise<number>;\n read(fh: number, offset: number, size: number): Promise<Uint8Array>;\n write(fh: number, offset: number, bytes: Uint8Array): Promise<void>;\n release(fh: number): Promise<void>;\n mkdir(path: string): Promise<void>;\n rmdir(path: string): Promise<void>;\n unlink(path: string): Promise<void>;\n rename(from: string, to: string): Promise<void>;\n symlink?(target: string, path: string): Promise<void>;\n readlink?(path: string): Promise<string>;\n setattr?(path: string, attr: { mode?: number; mtime?: number; size?: number }): Promise<void>;\n statfs?(): Promise<DriverStatfs>;\n}\n\nexport interface DriverPort {\n postMessage(message: unknown, transfer?: Transferable[]): void;\n addEventListener(type: 'message', handler: (event: MessageEvent) => void): void;\n start?(): void;\n}\n\nexport interface ServedFilesystem {\n invalidate(paths: string[] | true): void;\n}\n\nexport function fsError(code: string, message = code): Error & { code: string } {\n return Object.assign(new Error(message), { code });\n}\n\nasync function dispatch(h: FilesystemHandlers, req: DriverRequest): Promise<unknown> {\n switch (req.op) {\n case 'getattr':\n return h.getattr(req.path);\n case 'readdir':\n return h.readdir(req.path);\n case 'open':\n return h.open(req.path, {\n write: req.write,\n create: req.create,\n truncate: req.truncate,\n exclusive: req.exclusive,\n ...(req.ifMatch !== undefined ? { ifMatch: req.ifMatch } : {}),\n });\n case 'read':\n return h.read(req.fh, req.offset, req.size);\n case 'write':\n return h.write(req.fh, req.offset, req.bytes);\n case 'release':\n return h.release(req.fh);\n case 'mkdir':\n return h.mkdir(req.path);\n case 'rmdir':\n return h.rmdir(req.path);\n case 'unlink':\n return h.unlink(req.path);\n case 'rename':\n return h.rename(req.from, req.to);\n case 'symlink':\n if (!h.symlink) throw fsError('EPERM', 'this file system has no symlinks');\n return h.symlink(req.target, req.path);\n case 'readlink':\n if (!h.readlink) throw fsError('EINVAL', `${req.path} is not a symlink`);\n return h.readlink(req.path);\n case 'setattr':\n return h.setattr?.(req.path, {\n ...(req.mode !== undefined ? { mode: req.mode } : {}),\n ...(req.mtime !== undefined ? { mtime: req.mtime } : {}),\n ...(req.size !== undefined ? { size: req.size } : {}),\n });\n case 'statfs':\n return h.statfs?.() ?? null;\n default:\n throw fsError('ENOSYS', `unknown driver op ${(req as { op: string }).op}`);\n }\n}\n\nexport function serveFilesystem(\n port: DriverPort,\n handlers: FilesystemHandlers,\n capabilities: DriverCapabilities = {},\n options: { owned?: boolean } = {}\n): ServedFilesystem {\n let open = false;\n const reply = (message: object, transfer: Transferable[] = []) =>\n port.postMessage(message, transfer);\n async function hello(message: KernelDriverHello): Promise<void> {\n const refused = driverVersionError(message.protocol);\n if (refused) {\n reply({ hello: { protocol: DRIVER_PROTOCOL, error: refused, errno: 'EPROTO' } });\n return;\n }\n try {\n const refined = await handlers.mount?.(message.mount);\n open = true;\n reply({\n hello: { protocol: DRIVER_PROTOCOL, capabilities: { ...capabilities, ...refined } },\n });\n } catch (err) {\n const code = (err as { code?: unknown })?.code;\n reply({\n hello: {\n protocol: DRIVER_PROTOCOL,\n error: err instanceof Error ? err.message : String(err),\n errno: typeof code === 'string' ? code : 'EIO',\n },\n });\n }\n }\n port.addEventListener('message', (event) => {\n const data = event.data as { hello?: KernelDriverHello } & DriverRequest;\n if (data.hello) {\n void hello(data.hello);\n return;\n }\n if (!open) return;\n dispatch(handlers, data).then(\n (result) => {\n if (result instanceof Uint8Array) {\n const whole = result.byteOffset === 0 && result.byteLength === result.buffer.byteLength;\n const bytes = options.owned && whole ? result : result.slice();\n reply({ id: data.id, result: bytes }, [bytes.buffer]);\n } else reply({ id: data.id, result: result ?? null });\n },\n (err: unknown) => {\n const code = (err as { code?: unknown })?.code;\n reply({\n id: data.id,\n errno: typeof code === 'string' ? code : 'EIO',\n message: err instanceof Error ? err.message : String(err),\n });\n }\n );\n });\n port.start?.();\n return { invalidate: (paths) => reply({ invalidate: paths }) };\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|