@ai-ecoverse/slicc-kernel 1.37.0 → 1.39.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 CHANGED
@@ -206,6 +206,7 @@ The module's default export (or its `main` export) is called with a context and
206
206
  - `open(path, { read, write, append, create, exclusive, truncate })`, which returns a file with `read(position, length)`, `write(position, bytes)`, `size()`, `truncate(size)`, `sync()` and `close()`. Reads and writes go through the kernel's paged files at those positions, so a large file is never read whole;
207
207
  - `fs`: `stat`, `lstat`, `exists`, `readdir`, `mkdir` (with parents), `rm` (recursive), `unlink`, `rename`, `symlink`, `readlink`, and `readFile`/`writeFile` for small files;
208
208
  - `signals`: `on(signal, handler)` catches a signal (by number or as `'SIGINT'`), `ignore(signal)` ignores it and `reset(signal)` restores its default action. A call blocked in a read or write is restarted after a handler runs; signals without a handler keep their default actions, so an uncaught `SIGINT` ends the program with 130 and `SIGKILL` always does;
209
+ - `sync`: `read`, `write`, `close`, `open` (whose files' methods are synchronous too) and `fs`, made synchronously, for code that cannot `await`, such as a compiled program's file system or a `readFileSync`. A synchronous call holds the worker until the kernel answers, so nothing else of the program runs meanwhile, timers and callbacks included; a signal that arrives during a blocked read or write runs its handler, and the call is then restarted. Descriptors are shared with the rest of the context, so a file opened with `sync.open` can be closed with `close`, and the other way around;
209
210
  - `exit(status)`, which ends the program once its pending writes are done.
210
211
 
211
212
  A program that throws, or leaves an error or a rejected promise unhandled, ends with status 1 and the message on stderr; one whose module cannot be loaded, or exports no function, ends with 126. A write to a pipe whose reader is gone ends the program with 141, unless it ignores or catches `SIGPIPE` (an ignore inherited from its parent counts), in which case the write fails with `EPIPE`. Errors carry a POSIX `code`. Reads and writes of pipes, terminals and sockets go through the kernel's asynchronous operations, so a program blocked reading stdin can still write and handle signals; other calls of one process are made one at a time. A JS program cannot `fork`, and threads it starts itself are not the kernel's.
@@ -225,8 +226,9 @@ await kernel.run(['curl', '-sS', 'https://registry.npmjs.org/@ai-ecoverse/wasm-b
225
226
 
226
227
  - **Sockets**: `AF_INET` stream sockets on `127.x` and `AF_UNIX` sockets are kernel descriptors on one loopback network per kernel, so processes can serve and connect to each other. They survive `dup`, `fork` and `exec` and work with `select` and `poll`, like pipe ends. A bind of an `AF_UNIX` socket creates its path in OPFS. Other addresses are unreachable (`ENETUNREACH`) unless the [uplink](#uplink) routes them: otherwise programs reach the outside world only through the proxy.
227
228
  - **The proxy** listens on `127.0.0.1:3128` from the first connection on. It takes absolute-form `http:` requests and `CONNECT` tunnels, which it terminates with a certificate for the requested host, issued by the kernel's own CA, then hands each request to the transport. Programs start with `http_proxy`, `https_proxy` (and the upper-case names) pointing at it, `no_proxy` covering loopback and the [node name](#node-name), and `SSL_CERT_FILE`, `CURL_CA_BUNDLE` and `GIT_SSL_CAINFO` pointing at the CA bundle in `/etc/ssl/certs/slicc-kernel-ca.pem`; variables in `env` override them. The CA's key never leaves WebCrypto; it is kept in IndexedDB, in `<metadata>-ca`, or in `slicc-kernel-ca` when `metadata` is the default or `false`, so kernels on one origin share one CA whether or not they keep metadata. `ca` names another database, and `ca: false` keeps a CA in memory for the kernel's lifetime. Each kernel adds its CA to the bundle instead of replacing it, so every kernel on the origin stays trusted; the bundle keeps the newest 16.
228
- - **TLS** needs [`@ai-ecoverse/wasm-tls-engine`](https://www.npmjs.com/package/@ai-ecoverse/wasm-tls-engine) installed under `modules`, like a command. Without it, `CONNECT` is answered `501` with the reason.
229
+ - **TLS** needs [`@ai-ecoverse/wasm-tls-engine`](https://www.npmjs.com/package/@ai-ecoverse/wasm-tls-engine) installed under `modules`, like a command. Without it, `CONNECT` to port 443 is answered `501` with the reason. A tunnel to another port is accepted, and what the program sends first decides: plain HTTP is served as `http://host:port`, without TLS, and a TLS handshake is terminated as above, or the tunnel closes when it cannot be.
229
230
  - **The transport** is an object on the page with `traits` (`manualRedirects`, `encodedBodies`, `maxRequestBody`, and `crossOrigin`: `'cors'` or `'any'`) and `fetch(request)`, which answers `{ status, statusText, headers, body, cancel }` with `body` an async iterable of `Uint8Array`. The kernel pulls the body one chunk at a time, so a slow program slows the download. A rejection with a numeric `status` is answered with that status; any other with `502`. `fetchTransport()` is the plain `fetch` of the page, bound by CORS; its `hint` option is appended to the message of a request it could not make, so a program's 502 can name a way around CORS (`registry.npmjs.org` and jsDelivr allow it); an embedder with a way around CORS passes its own. A response body that delivers no data for `bodyIdleMs` (default 5 minutes; `0` or `Infinity` turns it off) fails with `ETIMEDOUT` instead of waiting forever, which matters because Chrome under heavy load can stop handing a page the rest of a body. A slow body that keeps delivering is never cut off.
231
+ - **WebSockets:** a `GET` with `Upgrade: websocket`, in absolute form or inside a tunnel, is bridged to the transport's optional `websocket({ url, protocols, headers, signal })`. It answers `{ protocol, buffered, send(data), messages, close(code, reason), closed }`, with `messages` an async iterable of strings and `Uint8Array`s and `closed` resolving with `{ code, reason }`; a transport that has it says so with `traits.websocket`. The program gets `101 Switching Protocols` with the far end's protocol, then its frames go out as messages and the far end's come back as frames. Pings are answered by the proxy, and close codes pass both ways (a code that may not go on the wire becomes 1000 or 1011). A message over 64 MiB, or more than 16 MiB of payload from the far end waiting for the program, closes with 1009. The proxy stops reading the program while 1 MiB of its messages wait to be sent. A refused connection is `502` with the reason. A transport without WebSockets answers `501` with a message naming the option below, and the kernel logs a warning once, so a program never hangs. `fetchTransport({ webSocket: true })` opens them with the page's `WebSocket` (or pass a constructor); they are off by default because a browser WebSocket carries the user's cookies for the target site, which `fetch` here never sends (`credentials: 'omit'`), so a program could reach a site as the user. A page also cannot send headers on a WebSocket, and an `https:` page cannot open `ws:` to anything but loopback, which is a `502` that says so. `nodeTransport()` has WebSockets on (Node keeps no cookies) and sends the request's headers. The credential-free path for a page is the coming slicc-node relay (`localProxyTransport()`, phase 2 of [#204](https://github.com/ai-ecoverse/slicc-kernel/issues/204)), which has no WebSockets yet.
230
232
  - **`localProxyTransport({ url, key })`** sends every request to a local proxy on loopback, such as [slicc-node](https://github.com/ai-ecoverse/slicc-node) or slicc-swift, which fetches it without CORS. Redirects reach the program unfollowed, with every `Set-Cookie`; bodies arrive decoded. `probeLocalProxy({ url, key })` resolves with the proxy's capabilities, or `null` when it is gone or refuses the key, so a page can fall back to `fetchTransport()`. `checkLocalProxy({ url, key })` says why: it resolves with `{ state }`, which is `ready` (with `probe`), `blocked` (the user denied Chrome's Local Network Access permission, `loopback-network`), `unreachable` (nothing answered; its `permission` is `granted`, `prompt` or `unknown`, and with `prompt` the page cannot tell a dismissed prompt from a proxy that is not running, since Chrome asks only once it has a connection), `refused` (with `status` and `error`, such as a stale key) or `incompatible`. The permission is not consulted when the page itself is on loopback. Both take a `fetch` option, and the transport `maxRequestBody` (default 64 MiB) and `bodyIdleMs` like `fetchTransport`.
231
233
  - **The host machine** is `host.slicc.internal` (`SLICC_HOST_LOOPBACK`), as `host.docker.internal` is in Docker, while `localhost` and `127.0.0.1` stay the kernel's own loopback. The proxy forwards `http(s)://host.slicc.internal:<port>/…` to the transport as `http(s)://127.0.0.1:<port>/…`, so it reaches the real machine's loopback through the local proxy or Node's `fetch` (through the page's own `fetch`, a request needs CORS from that server and Chrome's Local Network Access permission); other loopback addresses are still refused. This is HTTP and HTTPS through the proxy only: `/etc/hosts` and WASIX name resolution give the name `10.0.2.2`, QEMU's address for its host, so a program that connects a socket to it directly fails with `ENETUNREACH` instead of reaching the kernel's loopback.
232
234
  - **Without a transport**, every request is answered `502` with `slicc-kernel: no network transport (createKernel({ network: { transport } }))`.
@@ -418,7 +420,7 @@ Programs mount and unmount with `mount(2)` and `umount2(2)`, so a `mount`/`umoun
418
420
 
419
421
  ### Exec
420
422
 
421
- An exec'd program takes over the pid of the process it replaces, as on Linux: `getpid()` and `$$` in the new image, `/proc`, `ps`, `kill` and the parent's `waitpid` all agree on that pid, and the image's parent pid is the replaced process's. Its own children see that pid as their parent. A file removed or renamed over while programs hold it open keeps its bytes for them, as on Linux: the kernel keeps one copy for all holders, shared by their descriptors (writes through one are seen through the others), and frees it when the last one closes. Signals a program ignores stay ignored in the image it execs and in the children it spawns or forks, as POSIX has it, so `nohup cmd` and `trap '' TERM; exec cmd` keep `cmd` safe from them; caught signals go back to their default. The kernel holds what was handed down, so a new image that sets one of those signals back to the default with `signal(SIG_DFL)` still ignores it, until it installs a handler.
423
+ An exec'd program takes over the pid of the process it replaces, as on Linux: `getpid()` and `$$` in the new image, `/proc`, `ps`, `kill` and the parent's `waitpid` all agree on that pid, and the image's parent pid is the replaced process's. Its own children see that pid as their parent. A file removed or renamed over while programs hold it open keeps its bytes for them, as on Linux: the kernel keeps one copy for all holders, shared by their descriptors (writes through one are seen through the others), and frees it when the last one closes. That holds for files a program opened in its own worker too: every open, read-only ones included, is known to the kernel. When another process removes such a file, or renames another file over it, the kernel does not copy it: as NFS does with its "silly rename", it moves the file into a hidden directory, `.slicc-unlinked/`, at the root of the mount it lives on (or of the root file system), and serves that holder's reads and writes of the old path from there while the path is gone. No file data is held in memory for it. The file is deleted when the last holder closes it or exits, and the directory goes as soon as it is empty. A file created at the path afterwards is the new file for everyone, also for the holder; a holder whose file another process renames (rather than removes) still uses the old path. Listings in the kernel leave `.slicc-unlinked` out, but on an `fsa` or `hostfs` mount it is visible on the real machine while a removed file is held (add `.slicc-unlinked/` to a `.gitignore` there). Each kernel names its entries after itself and holds a Web Lock for that name while it runs; when a mount is set up (and the root at start), the kernel removes the entries whose owner holds no lock, so a tab that died while holding a file leaves nothing behind for long, and entries of other live tabs on the same origin are left alone. Where Web Locks are missing (the Node entry), nothing is swept. Signals a program ignores stay ignored in the image it execs and in the children it spawns or forks, as POSIX has it, so `nohup cmd` and `trap '' TERM; exec cmd` keep `cmd` safe from them; caught signals go back to their default. The kernel holds what was handed down, so a new image that sets one of those signals back to the default with `signal(SIG_DFL)` still ignores it, until it installs a handler.
422
424
 
423
425
  - **Emscripten:** `Module.sliccKernel.execve(file, argv, env, cwd)` runs `file` as this process's new image on its fds 0, 1 and 2, waits for it, and returns its wait status, or a negative errno when it cannot start. `env` and `cwd` may be `null` for this process's own. An exec shim detects it with `typeof Module.sliccKernel.execve === 'function'` and exits with the status it returns, as `execve` never returns on success. Older shims spawn the program and then call `Module.sliccKernel.execWait(pid)`; that works the same way: a new program asks the kernel for its pid before `main`, and the kernel answers once its parent has made its next call, so an image an older shim execs also reports the pid it replaced (the wait starts once the program is loaded; should the parent make no call within 100 ms after that, the kernel answers anyway, and the image may then report its own pid; `launcher.identities` counts the programs that asked and those answered by that timeout).
424
426
  - **WASIX:** `proc_exec` does this by itself.
@@ -43,6 +43,74 @@ function serveCdpPort(port, hook, request, onDone) {
43
43
  };
44
44
  }
45
45
 
46
+ // src/kernel/net/ws-queue.ts
47
+ var INBOUND_LIMIT = 16 * 1024 * 1024;
48
+ var MESSAGE_LIMIT = 64 * 1024 * 1024;
49
+ var TOO_BIG = 1009;
50
+ function payloadSize(message) {
51
+ return typeof message === "string" ? new TextEncoder().encode(message).length : message.length;
52
+ }
53
+ var MessageQueue = class {
54
+ items = [];
55
+ limit;
56
+ waiter;
57
+ size = 0;
58
+ ended = false;
59
+ overflow;
60
+ taken;
61
+ closed;
62
+ settle;
63
+ constructor(overflow, limit = INBOUND_LIMIT, taken) {
64
+ this.overflow = overflow;
65
+ this.limit = limit;
66
+ this.taken = taken;
67
+ this.closed = new Promise((resolve) => {
68
+ this.settle = resolve;
69
+ });
70
+ }
71
+ push(message) {
72
+ if (this.ended) return;
73
+ const size = payloadSize(message);
74
+ const huge = size > MESSAGE_LIMIT;
75
+ if (huge || this.items.length > 0 && this.size + size > this.limit) {
76
+ const reason = huge ? `a message is over ${MESSAGE_LIMIT} bytes` : `over ${this.limit} bytes of messages are waiting`;
77
+ this.end({ code: TOO_BIG, reason });
78
+ this.overflow();
79
+ return;
80
+ }
81
+ this.size += size;
82
+ this.items.push(message);
83
+ this.wake();
84
+ }
85
+ end(close) {
86
+ if (this.ended) return;
87
+ this.ended = true;
88
+ this.settle(close);
89
+ this.wake();
90
+ }
91
+ wake() {
92
+ const waiter = this.waiter;
93
+ this.waiter = void 0;
94
+ waiter?.();
95
+ }
96
+ async *[Symbol.asyncIterator]() {
97
+ for (; ; ) {
98
+ const next = this.items.shift();
99
+ if (next !== void 0) {
100
+ const n = payloadSize(next);
101
+ this.size -= n;
102
+ this.taken?.(n);
103
+ yield next;
104
+ continue;
105
+ }
106
+ if (this.ended) return;
107
+ await new Promise((resolve) => {
108
+ this.waiter = resolve;
109
+ });
110
+ }
111
+ }
112
+ };
113
+
46
114
  // src/kernel/net/remote-transport.ts
47
115
  var TransportError = class extends Error {
48
116
  status;
@@ -58,12 +126,15 @@ var RemoteTransport = class {
58
126
  port;
59
127
  waiting = /* @__PURE__ */ new Map();
60
128
  nextId = 0;
129
+ sockets = /* @__PURE__ */ new Map();
61
130
  failure;
62
131
  constructor(port, traits) {
63
132
  this.port = port;
64
133
  this.traits = traits;
65
134
  }
66
135
  receive(reply) {
136
+ const socket = this.sockets.get(reply.nid);
137
+ if (socket && this.toSocket(reply, socket)) return;
67
138
  const waiter = this.waiting.get(reply.nid);
68
139
  if (!waiter) return;
69
140
  this.waiting.delete(reply.nid);
@@ -71,10 +142,22 @@ var RemoteTransport = class {
71
142
  waiter.reject(new TransportError(reply.message, reply.status, reply.code));
72
143
  } else waiter.resolve(reply);
73
144
  }
145
+ toSocket(reply, socket) {
146
+ if (reply.net === "ws-message") socket.queue.push(reply.data);
147
+ else if (reply.net === "ws-acked") socket.acked(reply.n);
148
+ else if (reply.net === "ws-closed") {
149
+ this.sockets.delete(reply.nid);
150
+ socket.queue.end({ code: reply.code, reason: reply.reason });
151
+ } else return false;
152
+ return true;
153
+ }
74
154
  fail(error) {
75
155
  this.failure = error;
76
156
  for (const waiter of this.waiting.values()) waiter.reject(error);
77
157
  this.waiting.clear();
158
+ for (const socket of this.sockets.values())
159
+ socket.queue.end({ code: 1011, reason: error.message });
160
+ this.sockets.clear();
78
161
  }
79
162
  ask(call) {
80
163
  if (this.failure) return Promise.reject(this.failure);
@@ -153,6 +236,46 @@ var RemoteTransport = class {
153
236
  }
154
237
  };
155
238
  }
239
+ async websocket(request) {
240
+ const nid = ++this.nextId;
241
+ const { signal } = request;
242
+ signal.throwIfAborted();
243
+ const abort = () => this.cancel(nid);
244
+ signal.addEventListener("abort", abort, { once: true });
245
+ let opened;
246
+ try {
247
+ opened = await this.ask({
248
+ net: "ws-open",
249
+ nid,
250
+ url: request.url,
251
+ protocols: request.protocols,
252
+ headers: request.headers
253
+ });
254
+ } finally {
255
+ signal.removeEventListener("abort", abort);
256
+ }
257
+ const close = (code, reason) => this.port.postMessage({ net: "ws-close", nid, code, reason });
258
+ const queue = new MessageQueue(
259
+ () => close(1e3, "a message is too big"),
260
+ Number.POSITIVE_INFINITY,
261
+ (n) => this.port.postMessage({ net: "ws-consumed", nid, n })
262
+ );
263
+ let unacked = 0;
264
+ this.sockets.set(nid, { queue, acked: (n) => void (unacked -= n) });
265
+ return {
266
+ protocol: opened.protocol,
267
+ get buffered() {
268
+ return unacked;
269
+ },
270
+ send: (data) => {
271
+ unacked += payloadSize(data);
272
+ this.port.postMessage({ net: "ws-send", nid, data });
273
+ },
274
+ messages: queue,
275
+ close,
276
+ closed: queue.closed
277
+ };
278
+ }
156
279
  };
157
280
 
158
281
  // src/client/dial-stream.ts
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 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 linkTimes?: boolean;\n ranges?: boolean;\n sessions?: 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": ";AAgBO,SAAS,aACd,MACA,MACA,SACA,QACY;AACZ,MAAI;AACJ,MAAI,OAAO;AACX,QAAM,MAAM,MAAM;AAChB,WAAO;AACP,SAAK,MAAM;AACX,aAAS;AAAA,EACX;AACA,QAAM,SAAS,CAAC,WAA0B;AACxC,QAAI,KAAM;AACV,SAAK,YAAY,EAAE,OAAO,OAAO,CAAC;AAClC,QAAI;AAAA,EACN;AACA,OAAK,iBAAiB,WAAW,CAAC,EAAE,KAAK,MAAkD;AACzF,QAAI,KAAK,MAAM,OAAW,OAAM,KAAK,KAAK,CAAC;AAAA,aAClC,KAAK,SAAS,CAAC,MAAM;AAC5B,UAAI;AACJ,YAAM,MAAM;AAAA,IACd;AAAA,EACF,CAAC;AACD,OAAK,QAAQ;AACb,MAAI,QAAuB,CAAC,YAAY,QAAQ,KAAK,OAAO,CAAC,CAAC,EAAE;AAAA,IAC9D,CAAC,WAAW;AACV,aAAO;AACP,UAAI,KAAM,QAAO,OAAO,MAAM;AAC9B,aAAO,YAAY,CAAC,MAAM;AACxB,YAAI,CAAC,KAAM,MAAK,YAAY,EAAE,EAAE,CAAC;AAAA,MACnC;AACA,aAAO,UAAU,CAAC,WAAW,OAAO,UAAU,IAAI;AAClD,WAAK,YAAY,EAAE,MAAM,KAAK,CAAC;AAAA,IACjC;AAAA,IACA,CAAC,MAAe;AACd,UAAI,KAAM;AACV,WAAK,YAAY,EAAE,OAAO,aAAa,QAAQ,EAAE,UAAU,OAAO,CAAC,EAAE,CAAC;AACtE,UAAI;AAAA,IACN;AAAA,EACF;AACA,SAAO,MAAM;AACX,QAAI,KAAM;AACV,UAAM,MAAM;AACZ,WAAO,sBAAsB;AAAA,EAC/B;AACF;;;ACjCO,IAAM,iBAAN,cAA6B,MAAM;AAAA,EAC/B;AAAA,EACA;AAAA,EAET,YAAY,SAAiB,QAAiB,MAAe;AAC3D,UAAM,OAAO;AACb,SAAK,SAAS;AACd,SAAK,OAAO;AAAA,EACd;AACF;AAOO,IAAM,kBAAN,MAAgD;AAAA,EAC5C;AAAA,EAEQ;AAAA,EAEA,UAAU,oBAAI,IAAoB;AAAA,EAE3C,SAAS;AAAA,EAET;AAAA,EAER,YAAY,MAAqB,QAA8B;AAC7D,SAAK,OAAO;AACZ,SAAK,SAAS;AAAA,EAChB;AAAA,EAEA,QAAQ,OAA6B;AACnC,UAAM,SAAS,KAAK,QAAQ,IAAI,MAAM,GAAG;AACzC,QAAI,CAAC,OAAQ;AACb,SAAK,QAAQ,OAAO,MAAM,GAAG;AAC7B,QAAI,MAAM,QAAQ,SAAS;AACzB,aAAO,OAAO,IAAI,eAAe,MAAM,SAAS,MAAM,QAAQ,MAAM,IAAI,CAAC;AAAA,IAC3E,MAAO,QAAO,QAAQ,KAAK;AAAA,EAC7B;AAAA,EAEA,KAAK,OAAoB;AACvB,SAAK,UAAU;AACf,eAAW,UAAU,KAAK,QAAQ,OAAO,EAAG,QAAO,OAAO,KAAK;AAC/D,SAAK,QAAQ,MAAM;AAAA,EACrB;AAAA,EAEQ,IAAI,MAA8C;AACxD,QAAI,KAAK,QAAS,QAAO,QAAQ,OAAO,KAAK,OAAO;AACpD,WAAO,IAAI,QAAQ,CAAC,SAAS,WAAW;AACtC,WAAK,QAAQ,IAAI,KAAK,KAAK,EAAE,SAAS,OAAO,CAAC;AAC9C,WAAK,KAAK,YAAY,IAAI;AAAA,IAC5B,CAAC;AAAA,EACH;AAAA,EAEQ,OAAO,KAAmB;AAChC,UAAM,SAAS,KAAK,QAAQ,IAAI,GAAG;AACnC,SAAK,QAAQ,OAAO,GAAG;AACvB,YAAQ,OAAO,IAAI,eAAe,2BAA2B,CAAC;AAC9D,SAAK,KAAK,YAAY,EAAE,KAAK,UAAU,IAAI,CAAC;AAAA,EAC9C;AAAA,EAEA,MAAM,MAAM,SAAiE;AAC3E,UAAM,MAAM,EAAE,KAAK;AACnB,UAAM,EAAE,OAAO,IAAI;AACnB,WAAO,eAAe;AACtB,QAAI,WAAW;AACf,UAAM,QAAQ,MAAM;AAClB,iBAAW;AACX,WAAK,OAAO,GAAG;AAAA,IACjB;AACA,WAAO,iBAAiB,SAAS,OAAO,EAAE,MAAM,KAAK,CAAC;AACtD,UAAM,SAAS,MAAM;AACnB,UAAI,SAAU;AACd,iBAAW;AACX,aAAO,oBAAoB,SAAS,KAAK;AAAA,IAC3C;AACA,QAAI;AACJ,QAAI;AACF,aAAO,MAAM,KAAK,IAAI;AAAA,QACpB,KAAK;AAAA,QACL;AAAA,QACA,KAAK,QAAQ;AAAA,QACb,QAAQ,QAAQ;AAAA,QAChB,SAAS,QAAQ;AAAA,QACjB,GAAI,QAAQ,OAAO,EAAE,MAAM,QAAQ,KAAK,IAAI,CAAC;AAAA,MAC/C,CAAC;AAAA,IACH,SAAS,GAAG;AACV,aAAO;AACP,YAAM;AAAA,IACR;AACA,UAAM,EAAE,QAAQ,YAAY,QAAQ,IAAI;AACxC,UAAM,OAAO,YAA6C;AACxD,UAAI,SAAU,QAAO;AACrB,YAAM,QAAQ,MAAM,KAAK,IAAI,EAAE,KAAK,QAAQ,IAAI,CAAC,EAAE,MAAM,CAAC,MAAe;AACvE,eAAO;AACP,cAAM;AAAA,MACR,CAAC;AACD,UAAI,MAAM,QAAQ,QAAS,QAAO,MAAM;AACxC,aAAO;AACP,aAAO;AAAA,IACT;AACA,UAAM,SAAS,YAAY;AACzB,UAAI,SAAU;AACd,aAAO;AACP,WAAK,OAAO,GAAG;AAAA,IACjB;AACA,WAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,MAAM;AAAA,QACJ,CAAC,OAAO,aAAa,GAAG,OAAO;AAAA,UAC7B,MAAM,YAAY;AAChB,kBAAM,QAAQ,MAAM,KAAK;AACzB,mBAAO,QAAQ,EAAE,OAAO,OAAO,MAAM,MAAM,IAAI,EAAE,OAAO,QAAW,MAAM,KAAK;AAAA,UAChF;AAAA,UACA,QAAQ,YAAY;AAClB,kBAAM,OAAO;AACb,mBAAO,EAAE,OAAO,QAAW,MAAM,KAAK;AAAA,UACxC;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;;;ACpIO,SAAS,cAAc,SAA4C;AACxE,QAAM,OAAO,WAAW,KAAK,OAAO,IAAI,CAAC;AACzC,SAAO,OAAO,OAAO,IAAI,MAAM,OAAO,GAAG,OAAO,EAAE,KAAK,IAAI,CAAC,CAAC;AAC/D;AAEO,SAAS,WAAW,MAAkB,SAAkC;AAC7E,MAAI,SAAS;AACb,MAAI;AACJ,QAAM,OAAuE,CAAC;AAC9E,QAAM,WAAW,IAAI,eAA2B;AAAA,IAC9C,MAAM,YAAY;AAChB,eAAS;AAAA,IACX;AAAA,IACA,OAAO;AACL,UAAI,CAAC,OAAQ,MAAK,YAAY,EAAE,MAAM,KAAK,CAAC;AAAA,IAC9C;AAAA,IACA,SAAS;AACP,eAAS;AACT,YAAM;AAAA,IACR;AAAA,EACF,CAAC;AACD,QAAM,SAAS,CAACA,UAAiB;AAC/B,UAAM,aAAa;AACnB,aAAS;AACT,eAAW,OAAO,KAAK,OAAO,CAAC,GAAG;AAChC,UAAIA,MAAM,KAAI,OAAOA,KAAI;AAAA,UACpB,KAAI,QAAQ;AAAA,IACnB;AACA,QAAI,CAAC,WAAY;AACjB,QAAIA,MAAM,YAAW,MAAMA,KAAI;AAAA,QAC1B,YAAW,MAAM;AAAA,EACxB;AACA,WAAS,OAAa;AACpB,QAAI,OAAQ;AACZ,aAAS;AACT,SAAK,MAAM;AACX,cAAU;AAAA,EACZ;AACA,WAAS,QAAc;AACrB,QAAI,CAAC,OAAQ,MAAK,YAAY,EAAE,OAAO,KAAK,CAAC;AAC7C,SAAK;AACL,WAAO;AAAA,EACT;AACA,OAAK,iBAAiB,WAAW,CAAC,EAAE,KAAK,MAAiC;AACxE,QAAI,gBAAgB,WAAY,SAAQ,QAAQ,IAAI;AAAA,aAC3C,SAAS,KAAM,MAAK,MAAM,GAAG,QAAQ;AAAA,aACrC,SAAS,KAAM,QAAO;AAAA,QAC1B,QAAO,cAAc,KAAK,KAAK,CAAC;AAAA,EACvC,CAAC;AACD,OAAK,QAAQ;AACb,QAAM,WAAW,IAAI,eAA2B;AAAA,IAC9C,MAAM,OAAO;AACX,UAAI,OAAQ,OAAM,cAAc,iCAAiC;AACjE,YAAM,OAAO,MAAM,MAAM;AACzB,YAAM,QAAQ,IAAI,QAAc,CAAC,SAAS,WAAW,KAAK,KAAK,EAAE,SAAS,OAAO,CAAC,CAAC;AACnF,WAAK,YAAY,MAAM,CAAC,KAAK,MAAM,CAAC;AACpC,aAAO;AAAA,IACT;AAAA,IACA,QAAQ;AACN,UAAI,CAAC,OAAQ,MAAK,YAAY,EAAE,KAAK,KAAK,CAAC;AAAA,IAC7C;AAAA,IACA,QAAQ;AACN,YAAM;AAAA,IACR;AAAA,EACF,CAAC;AACD,QAAM,OAAO,CAAC,UAAiB;AAC7B,SAAK;AACL,WAAO,KAAK;AAAA,EACd;AACA,SAAO,EAAE,UAAU,UAAU,OAAO,KAAK;AAC3C;;;ACxFA,IAAM,cAAc,oBAAI,IAAI,CAAC,QAAQ,cAAc,kBAAkB,mBAAmB,CAAC;AACzF,IAAM,UAAU,IAAI,YAAY;AAChC,IAAM,SAAS,IAAI,YAAY,QAAQ;AAEvC,IAAM,aAAN,MAAiB;AAAA,EACP,WAAW,IAAI,WAAW,CAAC;AAAA,EAClB;AAAA,EAEjB,YAAY,QAAiD;AAC3D,SAAK,SAAS;AAAA,EAChB;AAAA,EAEA,MAAc,OAAyB;AACrC,UAAM,EAAE,MAAM,MAAM,IAAI,MAAM,KAAK,OAAO,KAAK;AAC/C,QAAI,KAAM,QAAO;AACjB,UAAM,SAAS,IAAI,WAAW,KAAK,SAAS,SAAS,MAAM,MAAM;AACjE,WAAO,IAAI,KAAK,QAAQ;AACxB,WAAO,IAAI,OAAO,KAAK,SAAS,MAAM;AACtC,SAAK,WAAW;AAChB,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,MAAM,QAAiD;AAC3D,UAAM,SAAS,QAAQ,OAAO,MAAM;AACpC,eAAS;AACP,YAAM,KAAK,QAAQ,KAAK,UAAU,MAAM;AACxC,UAAI,MAAM,EAAG,QAAO,KAAK,KAAK,KAAK,OAAO,MAAM;AAChD,UAAI,CAAE,MAAM,KAAK,KAAK,EAAI,QAAO;AAAA,IACnC;AAAA,EACF;AAAA,EAEA,MAAM,KAAK,KAA8C;AACvD,QAAI,KAAK,SAAS,WAAW,KAAK,CAAE,MAAM,KAAK,KAAK,EAAI,QAAO;AAC/D,WAAO,KAAK,KAAK,KAAK,IAAI,KAAK,KAAK,SAAS,MAAM,CAAC;AAAA,EACtD;AAAA,EAEA,MAAM,QAAQ,OAAgD;AAC5D,WAAO,KAAK,SAAS,SAAS,MAAO,KAAI,CAAE,MAAM,KAAK,KAAK,EAAI,QAAO;AACtE,WAAO,KAAK,KAAK,KAAK;AAAA,EACxB;AAAA,EAEQ,KAAK,OAA2B;AACtC,UAAM,MAAM,KAAK,SAAS,MAAM,GAAG,KAAK;AACxC,SAAK,WAAW,KAAK,SAAS,MAAM,KAAK;AACzC,WAAO;AAAA,EACT;AACF;AAEA,SAAS,QAAQ,UAAsB,QAA4B;AACjE,QAAO,UAAS,IAAI,GAAG,IAAI,OAAO,UAAU,SAAS,QAAQ,KAAK;AAChE,aAAS,IAAI,GAAG,IAAI,OAAO,QAAQ,IAAK,KAAI,SAAS,IAAI,CAAC,MAAM,OAAO,CAAC,EAAG,UAAS;AACpF,WAAO;AAAA,EACT;AACA,SAAO;AACT;AAQA,SAAS,UAAU,OAAiC;AAClD,QAAM,CAAC,aAAa,IAAI,GAAG,KAAK,IAAI,OAAO,OAAO,KAAK,EAAE,MAAM,MAAM;AACrE,QAAM,QAAQ,oCAAoC,KAAK,UAAU;AACjE,MAAI,CAAC,MAAO,OAAM,cAAc,qCAAqC,WAAW,MAAM,GAAG,EAAE,CAAC,EAAE;AAC9F,QAAM,UAAmC,CAAC;AAC1C,aAAW,QAAQ,OAAO;AACxB,UAAM,QAAQ,KAAK,QAAQ,GAAG;AAC9B,QAAI,QAAQ,EAAG,SAAQ,KAAK,CAAC,KAAK,MAAM,GAAG,KAAK,EAAE,KAAK,GAAG,KAAK,MAAM,QAAQ,CAAC,EAAE,KAAK,CAAC,CAAC;AAAA,EACzF;AACA,SAAO,EAAE,QAAQ,OAAO,MAAM,CAAC,CAAC,GAAG,YAAY,MAAM,CAAC,KAAK,IAAI,QAAQ;AACzE;AAEA,SAAS,OAAO,MAAoB,MAAkC;AACpE,SAAO,KAAK,QAAQ,KAAK,CAAC,CAAC,GAAG,MAAM,IAAI,YAAY,MAAM,IAAI,IAAI,CAAC;AACrE;AAEA,gBAAgB,QAAQ,QAAgD;AACtE,aAAS;AACP,UAAM,OAAO,MAAM,OAAO,MAAM,MAAM;AACtC,QAAI,CAAC,KAAM,OAAM,cAAc,sCAAsC;AACrE,UAAM,OAAO,OAAO,SAAS,OAAO,OAAO,IAAI,EAAE,KAAK,EAAE,MAAM,GAAG,EAAE,CAAC,KAAK,IAAI,EAAE;AAC/E,QAAI,CAAC,OAAO,SAAS,IAAI,EAAG,OAAM,cAAc,gCAAgC;AAChF,QAAI,SAAS,EAAG;AAChB,UAAM,OAAO,MAAM,OAAO,QAAQ,IAAI;AACtC,QAAI,CAAC,QAAQ,CAAE,MAAM,OAAO,QAAQ,CAAC,EAAI,OAAM,cAAc,6BAA6B;AAC1F,UAAM;AAAA,EACR;AACF;AAEA,gBAAgB,QAAQ,QAAoB,QAA4C;AACtF,MAAI,OAAO;AACX,SAAO,OAAO,GAAG;AACf,UAAM,OAAO,MAAM,OAAO,KAAK,IAAI;AACnC,QAAI,CAAC,KAAM,OAAM,cAAc,8BAA8B;AAC7D,YAAQ,KAAK;AACb,UAAM;AAAA,EACR;AACF;AAEA,gBAAgB,WAAW,QAAgD;AACzE,WAAS,OAAO,MAAM,OAAO,KAAK,KAAK,GAAG,MAAM,OAAO,MAAM,OAAO,KAAK,KAAK,EAAG,OAAM;AACzF;AAEA,SAAS,OAAO,QAAoB,MAAoB,QAAgB;AACtE,MAAI,WAAW,UAAU,KAAK,WAAW,OAAO,KAAK,WAAW,IAAK,QAAO;AAC5E,MAAI,OAAO,MAAM,mBAAmB,GAAG,YAAY,EAAE,SAAS,SAAS,EAAG,QAAO,QAAQ,MAAM;AAC/F,QAAM,SAAS,OAAO,MAAM,gBAAgB;AAC5C,MAAI,WAAW,OAAW,QAAO,WAAW,MAAM;AAClD,QAAM,OAAO,OAAO,MAAM;AAC1B,MAAI,CAAC,QAAQ,KAAK,OAAO,KAAK,CAAC,KAAK,CAAC,OAAO,cAAc,IAAI,GAAG;AAC/D,UAAM,cAAc,uCAAuC,MAAM,EAAE;AAAA,EACrE;AACA,SAAO,QAAQ,QAAQ,IAAI;AAC7B;AAEA,SAAS,OAAO,QAAoC,QAAuB,QAAsB;AAC/F,SAAO,IAAI,eAA2B;AAAA,IACpC,MAAM,YAAY;AAChB,cAAQ,iBAAiB,SAAS,MAAM,WAAW,MAAM,OAAO,MAAM,GAAG,EAAE,MAAM,KAAK,CAAC;AAAA,IACzF;AAAA,IACA,MAAM,KAAK,YAAY;AACrB,UAAI;AACF,cAAM,OAAO,MAAM,OAAO,KAAK;AAC/B,YAAI,KAAK,MAAM;AACb,qBAAW,MAAM;AACjB,iBAAO,MAAM;AAAA,QACf,MAAO,YAAW,QAAQ,KAAK,KAAK;AAAA,MACtC,SAAS,KAAK;AACZ,mBAAW,MAAM,GAAG;AACpB,eAAO,MAAM;AAAA,MACf;AAAA,IACF;AAAA,IACA,SAAS;AACP,aAAO,MAAM;AAAA,IACf;AAAA,EACF,CAAC;AACH;AAEA,eAAe,aAAa,SAAuC;AACjE,QAAM,MAAM,IAAI,IAAI,QAAQ,GAAG;AAC/B,QAAM,OAAO,QAAQ,OAAO,IAAI,WAAW,MAAM,QAAQ,YAAY,CAAC,IAAI;AAC1E,QAAM,QAAQ,CAAC,GAAG,QAAQ,MAAM,IAAI,IAAI,QAAQ,GAAG,IAAI,MAAM,aAAa,SAAS,IAAI,IAAI,EAAE;AAC7F,UAAQ,QAAQ,QAAQ,CAAC,OAAO,SAAS;AACvC,QAAI,CAAC,YAAY,IAAI,IAAI,EAAG,OAAM,KAAK,GAAG,IAAI,KAAK,KAAK,EAAE;AAAA,EAC5D,CAAC;AACD,MAAI,KAAM,OAAM,KAAK,mBAAmB,KAAK,MAAM,EAAE;AACrD,QAAM,KAAK,qBAAqB,IAAI,EAAE;AACtC,QAAM,OAAO,QAAQ,OAAO,MAAM,KAAK,MAAM,CAAC;AAC9C,QAAM,MAAM,IAAI,WAAW,KAAK,UAAU,MAAM,UAAU,EAAE;AAC5D,MAAI,IAAI,IAAI;AACZ,MAAI,KAAM,KAAI,IAAI,MAAM,KAAK,MAAM;AACnC,SAAO;AACT;AAEA,eAAsB,cACpB,MACA,OACA,SACmB;AACnB,UAAQ,QAAQ,eAAe;AAC/B,QAAM,UAAU,iBAAiB,UAAU,QAAQ,IAAI,QAAQ,KAAK;AACpE,QAAM,QAAQ,MAAM,aAAa,OAAO;AACxC,QAAM,SAAS,MAAM,KAAK;AAAA,IACxB,MAAM,QAAQ;AAAA,IACd,GAAI,QAAQ,OAAO,EAAE,MAAM,QAAQ,KAAK,IAAI,CAAC;AAAA,EAC/C,CAAC;AACD,UAAQ,QAAQ,iBAAiB,SAAS,MAAM,OAAO,MAAM,GAAG,EAAE,MAAM,KAAK,CAAC;AAC9E,MAAI;AACF,UAAM,SAAS,OAAO,SAAS,UAAU;AACzC,UAAM,OAAO,MAAM,KAAK;AACxB,WAAO,YAAY;AACnB,UAAM,SAAS,IAAI,WAAW,OAAO,SAAS,UAAU,CAAC;AACzD,QAAI;AACJ,OAAG;AACD,YAAM,MAAM,MAAM,OAAO,MAAM,UAAU;AACzC,UAAI,CAAC,IAAK,OAAM,cAAc,qDAAqD;AACnF,aAAO,UAAU,GAAG;AAAA,IACtB,SAAS,KAAK,UAAU,OAAO,KAAK,SAAS;AAC7C,UAAM,SAAS,OAAO,QAAQ,MAAM,QAAQ,MAAM;AAClD,QAAI,CAAC,OAAQ,QAAO,MAAM;AAC1B,WAAO,IAAI,SAAS,SAAS,OAAO,QAAQ,QAAQ,QAAQ,MAAM,IAAI,MAAM;AAAA,MAC1E,QAAQ,KAAK;AAAA,MACb,YAAY,KAAK;AAAA,MACjB,SAAS,KAAK;AAAA,IAChB,CAAC;AAAA,EACH,SAAS,KAAK;AACZ,WAAO,MAAM;AACb,UAAM;AAAA,EACR;AACF;;;AChMO,IAAM,WAAsC,CAAC,GAAG,CAAC;AAgHjD,SAAS,QAAQ,QAAgB,YAAyC;AAC/E,QAAM,QAAS,MAAsD,WAAW;AAChF,SAAO,OAAO,OAAO,YAAY,aAAa,QAAQ;AACxD;AAEO,SAAS,aAAa,QAAqC;AAChE,QAAM,QAAQ,MAAM,QAAQ,MAAM,IAAI,OAAO,CAAC,IAAI;AAClD,MAAI,UAAU,SAAS,CAAC,EAAG,QAAO;AAClC,QAAM,QAAQ,OAAO,UAAU,WAAW,GAAG,KAAK,OAAO;AACzD,SAAO,gCAAgC,KAAK,uCAAuC,SAAS,KAAK,GAAG,CAAC;AACvG;;;ACjGO,IAAM,kBAAN,cAA8B,MAAM;AAAA,EACzC,YAAY,UAAU,wDAAwD;AAC5E,UAAM,OAAO;AACb,SAAK,OAAO;AAAA,EACd;AACF;AAEO,IAAM,kBAAN,cAA8B,MAAM;AAAA,EAChC;AAAA,EAET,YAAY,SAAiB,MAAe;AAC1C,UAAM,OAAO;AACb,SAAK,OAAO;AACZ,SAAK,OAAO;AAAA,EACd;AACF;AA6GA,IAAMC,WAAU,IAAI,YAAY;AAChC,IAAM,UAAU,CAAC,SACf,OAAO,SAAS,WAAWA,SAAQ,OAAO,IAAI,IAAI;AAEpD,IAAM,cAAc;AAAA,EAClB,iBAAiB;AAAA,EACjB,eAAe;AAAA,EACf,gBAAgB;AAAA,EAChB,aAAa;AACf;AAEA,eAAe,SACb,OAC6C;AAC7C,MAAI,CAAC,MAAO,QAAO,EAAE,UAAU;AAAA,EAAC,EAAE;AAClC,QAAM,OAAO,uBAAuB,OAAO,WAAW,CAAC;AACvD,QAAM,UAAU,QAAQ,cAAoB;AAC5C,QAAM,OAAO,QAAQ,cAAoB;AACzC,OAAK,MAAM,QAAQ,MAAM,MAAM;AAC7B,YAAQ,QAAQ;AAChB,WAAO,KAAK;AAAA,EACd,CAAC;AACD,QAAM,QAAQ;AACd,SAAO,EAAE,MAAM,SAAS,MAAM,KAAK,QAAQ,EAAE;AAC/C;AAEA,SAAS,OAAO,QAAkC;AAChD,QAAM,MAAM,IAAI,WAAW,OAAO,OAAO,CAAC,GAAG,MAAM,IAAI,EAAE,QAAQ,CAAC,CAAC;AACnE,MAAI,KAAK;AACT,aAAW,SAAS,QAAQ;AAC1B,QAAI,IAAI,OAAO,EAAE;AACjB,UAAM,MAAM;AAAA,EACd;AACA,SAAO;AACT;AAEA,IAAM,UAAN,MAAc;AAAA,EACH,UAAU,QAAQ,cAA2B;AAAA,EAC7C,QAAQ,QAAQ,cAAqB;AAAA,EAC9C;AAAA,EACA;AAAA,EACiB,UAAU,oBAAI,IAAqB;AAAA,EAC3C,WAAW,oBAAI,IAA2C;AAAA,EAC1D,WAAW,oBAAI,IAAqB;AAAA,EAC5B,UAAU,oBAAI,IAAgB;AAAA,EAC/C,WAAsC;AAAA,EAC9B,SAAS;AAAA,EACA;AAAA,EACA;AAAA,EAEjB,YAAY,MAAuB,SAAqB;AACtD,SAAK,OAAO;AACZ,SAAK,UAAU;AACf,SAAK,QAAQ,QAAQ,MAAM,MAAM,MAAS;AAC1C,SAAK,iBAAiB,WAAW,CAAC,UAAU,KAAK,QAAQ,MAAM,IAAI,CAAC;AACpE,SAAK,iBAAiB,SAAS,MAAM,KAAK,IAAI,IAAI,gBAAgB,CAAC,CAAC;AACpE,SAAK,QAAQ;AAAA,EACf;AAAA,EAEA,KAAK,SAAuB;AAC1B,QAAI,CAAC,KAAK,QAAS,MAAK,KAAK,YAAY,OAAO;AAAA,EAClD;AAAA,EAEA,IAAI,OAAoB;AACtB,QAAI,KAAK,QAAS;AAClB,SAAK,UAAU;AACf,SAAK,QAAQ,OAAO,KAAK;AACzB,SAAK,QAAQ,KAAK,KAAK;AACvB,eAAW,SAAS,CAAC,GAAG,KAAK,OAAO,EAAG,OAAM;AAC7C,SAAK,QAAQ,MAAM;AACnB,eAAW,QAAQ,KAAK,QAAQ,OAAO,EAAG,MAAK,OAAO,KAAK;AAC3D,SAAK,QAAQ,MAAM;AACnB,SAAK,QAAQ;AACb,SAAK,KAAK,QAAQ;AAClB,SAAK,MAAM,QAAQ,KAAK;AAAA,EAC1B;AAAA,EAEA,QAAQ,MAAkB,WAAqB,CAAC,GAA2C;AACzF,UAAM,KAAK,EAAE,KAAK;AAClB,UAAM,EAAE,QAAQ,IAAI;AACpB,QAAI,QAAS,QAAO,EAAE,IAAI,MAAM,QAAQ,OAAO,OAAO,EAAE;AACxD,UAAM,OAAO,IAAI,QAAQ,CAAC,SAAS,WAAW;AAC5C,WAAK,QAAQ,IAAI,IAAI,EAAE,SAAS,QAAQ,GAAG,SAAS,CAAC;AACrD,WAAK,KAAK,YAAY,EAAE,GAAG,MAAM,GAAG,CAAC;AAAA,IACvC,CAAC;AACD,WAAO,EAAE,IAAI,KAAK;AAAA,EACpB;AAAA,EAEA,KAAK,MAAoC;AACvC,WAAO,KAAK,QAAQ,IAAI,EAAE;AAAA,EAC5B;AAAA,EAEQ,QAAQ,MAQP;AACP,QAAI,KAAK,WAAW,KAAK,MAAM;AAC7B,WAAK,QAAQ,IAAe;AAC5B;AAAA,IACF;AACA,QAAI,KAAK,UAAU,QAAW;AAC5B,WAAK,SAAS,IAAI,KAAK,KAAK,IAAI,KAAK,MAAqB;AAC1D;AAAA,IACF;AACA,QAAI,KAAK,QAAQ,QAAW;AAC1B,WAAK,IAAI,IAAI,gBAAgB,KAAK,GAAG,CAAC;AACtC;AAAA,IACF;AACA,QAAI,KAAK,OAAO;AACd,WAAK,QAAQ,QAAQ,KAAK,KAAK;AAC/B;AAAA,IACF;AACA,QAAI,KAAK,QAAQ,QAAW;AAC1B,WAAK,QAAQ,QAAQ,IAAsB;AAC3C;AAAA,IACF;AACA,UAAM,QAAQ;AACd,UAAM,OAAO,KAAK,QAAQ,IAAI,MAAM,EAAE;AACtC,QAAI,CAAC,KAAM;AACX,QAAI,MAAM,OAAO,QAAW;AAC1B,WAAK,SAAS,MAAM,IAAI,MAAM,KAAmB;AACjD;AAAA,IACF;AACA,QAAI,MAAM,YAAY,QAAW;AAC/B,WAAK,UAAU,MAAM,OAAO;AAC5B;AAAA,IACF;AACA,SAAK,QAAQ,OAAO,MAAM,EAAE;AAC5B,QAAI,MAAM,UAAU,OAAW,MAAK,OAAO,IAAI,gBAAgB,MAAM,OAAO,MAAM,IAAI,CAAC;AAAA,QAClF,MAAK,QAAQ,MAAM,MAAM;AAAA,EAChC;AAAA,EAEQ,QAAQ,EAAE,SAAS,EAAE,cAAc,GAAG,QAAQ,GAAG,KAAK,GAAkB;AAC9E,UAAM,OAAO,iBAAiB,SAAY,SAAY,KAAK,SAAS,IAAI,YAAY;AACpF,QAAI,CAAC,QAAQ,KAAK,SAAS;AACzB,WAAK,YAAY,EAAE,OAAO,mCAAmC,CAAC;AAC9D,WAAK,MAAM;AACX;AAAA,IACF;AACA,UAAM,QAAQ,aAAa,MAAM,MAAM,SAAS,MAAM,KAAK,QAAQ,OAAO,KAAK,CAAC;AAChF,SAAK,QAAQ,IAAI,KAAK;AAAA,EACxB;AACF;AAEA,eAAe,WACb,SACA,MACA,SAC4B;AAC5B,QAAM,MAAM,SAAS,GAAG,eAAe,YAAY;AAAA,EAAC,CAAC;AACrD,QAAM,MAAM;AAAA,IACV,IAAI;AAAA,IACJ,GAAI,QAAQ,UAAU,EAAE,SAAS,QAAQ,QAAQ,IAAI,CAAC;AAAA,EACxD;AACA,QAAM,EAAE,IAAI,KAAK,IAAI,QAAQ,QAAQ,GAAG;AACxC,UAAQ,SAAS,IAAI,IAAI,IAAI;AAC7B,MAAI;AACF,UAAM;AAAA,EACR,SAAS,OAAO;AACd,YAAQ,SAAS,OAAO,EAAE;AAC1B,UAAM;AAAA,EACR;AACA,SAAO;AAAA,IACL,OAAO,MAAM;AACX,UAAI,CAAC,QAAQ,SAAS,OAAO,EAAE,EAAG;AAClC,WAAK,QAAQ,KAAK,EAAE,IAAI,eAAe,cAAc,GAAG,CAAC,EAAE,MAAM,MAAM,MAAS;AAAA,IAClF;AAAA,EACF;AACF;AAEA,eAAe,OAAO,SAAkB,EAAE,MAAM,KAAK,GAAwC;AAC3F,QAAM,MAAM,EAAE,IAAI,QAAiB,MAAM,GAAI,OAAO,EAAE,KAAK,IAAI,CAAC,EAAG;AACnE,SAAO,WAAY,MAAM,MAAM,SAAS,GAAG,QAAQ,MAAM,QAAQ,KAAK,GAAG,CAAC,CAAiB;AAC7F;AAEA,eAAe,QACb,SACA,MACA,MACyB;AACzB,QAAM,EAAE,UAAU,UAAU,OAAO,OAAO,GAAG,GAAG,KAAK,IAAI;AACzD,MAAI,KAAK,SAAS;AAChB,UAAM,MAAM,SAAS,GAAG,8BAA8B,YAAY;AAAA,IAAC,CAAC;AACtE,QAAM,UAAU,QAAQ,cAAsB;AAC9C,QAAM,UAAU,EAAE,GAAG,MAAM,GAAI,UAAU,SAAY,EAAE,OAAO,QAAQ,KAAK,EAAE,IAAI,CAAC,EAAG;AACrF,QAAM,EAAE,KAAK,IAAI,QAAQ;AAAA,IACvB,EAAE,IAAI,SAAS,MAAM,QAAQ;AAAA,IAC7B;AAAA,MACE,QAAQ,CAAC,IAAI,WAAW,OAAO,IAAI,WAAW,YAAY,KAAK;AAAA,MAC/D,SAAS,QAAQ;AAAA,IACnB;AAAA,EACF;AACA,OAAK,MAAM,QAAQ,MAAM;AACzB,QAAM,MAAM,MAAM,QAAQ;AAC1B,QAAM,OAAO,KAAK,QAAQ;AAC1B,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA,QAAQ;AAAA,IACR,QAAQ,OAAO,OAAO,cACpB,KAAM,MAAM,QAAQ,KAAK,EAAE,IAAI,QAAQ,KAAK,CAAC,MAAM,QAAQ,KAAK,CAAC;AAAA,EACrE;AACF;AAEA,eAAe,MACb,SACA,MACA,MAC0B;AAC1B,QAAM,EAAE,UAAU,UAAU,GAAG,KAAK,IAAI;AACxC,QAAM,SAAsC,EAAE,GAAG,CAAC,GAAG,GAAG,CAAC,EAAE;AAC3D,QAAM,OAAO,EAAE,GAAG,IAAI,YAAY,GAAG,GAAG,IAAI,YAAY,EAAE;AAC1D,QAAM,MAAM,CAAC,IAAW,OAAgC,CAAC,UAAsB;AAC7E,WAAO,EAAE,EAAE,KAAK,KAAK;AACrB,SAAK,KAAK,EAAE,EAAE,OAAO,OAAO,EAAE,QAAQ,KAAK,CAAC,CAAC;AAAA,EAC/C;AACA,QAAM,QAAQ,MAAM,QAAQ,SAAS,MAAM;AAAA,IACzC,GAAG;AAAA,IACH,UAAU,IAAI,GAAG,QAAQ;AAAA,IACzB,UAAU,IAAI,GAAG,QAAQ;AAAA,EAC3B,CAAC;AACD,QAAM,SAAS,MAAM,MAAM;AAC3B,QAAM,OAAO,CAAC,OAAc,IAAI,YAAY,EAAE,OAAO,OAAO,OAAO,EAAE,CAAC,CAAC;AACvE,SAAO,EAAE,KAAK,MAAM,KAAK,QAAQ,QAAQ,KAAK,CAAC,GAAG,QAAQ,KAAK,CAAC,EAAE;AACpE;AAEA,eAAe,WACb,SACA,MACA,MACyB;AACzB,QAAM,EAAE,QAAQ,GAAG,QAAQ,IAAI;AAC/B,MAAI,WAAW,UAAU;AACzB,QAAM,UAAwB,CAAC;AAC/B,QAAM,UAAU,QAAQ,cAAsB;AAC9C,QAAM,EAAE,IAAI,KAAK,IAAI,QAAQ;AAAA,IAC3B,EAAE,IAAI,iBAAiB,MAAM,QAAQ;AAAA,IACrC;AAAA,MACE,QAAQ,CAAC,KAAK,UAAW,WAAW,SAAS,KAAK,IAAI,QAAQ,KAAK,KAAK;AAAA,MACxE,SAAS,QAAQ;AAAA,IACnB;AAAA,EACF;AACA,OAAK,MAAM,QAAQ,MAAM;AACzB,QAAM,MAAM,MAAM,QAAQ;AAC1B,QAAM,OAAO,CAAC,WACZ,KAAK,QAAQ,KAAK,EAAE,IAAI,YAAY,UAAU,IAAI,GAAG,OAAO,CAAC,EAAE,MAAM,MAAM,MAAS;AACtF,SAAO;AAAA,IACL;AAAA,IACA,QAAQ;AAAA,IACR,IAAI,SAAS;AACX,aAAO;AAAA,IACT;AAAA,IACA,IAAI,OAAO,MAAM;AACf,iBAAW;AACX,UAAI,KAAM,YAAW,SAAS,QAAQ,OAAO,CAAC,EAAG,MAAK,KAAK;AAAA,IAC7D;AAAA,IACA,OAAO,CAAC,SAAS,KAAK,EAAE,QAAQ,SAAS,OAAO,QAAQ,IAAI,EAAE,CAAC;AAAA,IAC/D,QAAQ,CAAC,MAAM,SAAS,KAAK,EAAE,QAAQ,UAAU,MAAM,KAAK,CAAC;AAAA,IAC7D,QAAQ,CAAC,SAAS,KAAK,EAAE,QAAQ,UAAU,QAAQ,KAAK,CAAC;AAAA,IACzD,OAAO,MAAM,KAAK,EAAE,QAAQ,QAAQ,CAAC;AAAA,EACvC;AACF;AAEA,SAAS,KAAK,SAA4B;AACxC,QAAM,KAAK,CAAC,WAAqB,SAAoB,QAAQ,KAAK,EAAE,IAAI,MAAM,QAAQ,KAAK,CAAC;AAC5F,QAAM,OAAO,OAAO,WAAqB,SAAoB,KAAM,MAAM,GAAG,QAAQ,GAAG,IAAI;AAC3F,SAAO;AAAA,IACL,UAAU,CAAC,SAAS,GAAG,YAAY,IAAI;AAAA,IACvC,UAAU,OAAO,SAAS,IAAI,YAAY,EAAE,OAAQ,MAAM,GAAG,YAAY,IAAI,CAAgB;AAAA,IAC7F,WAAW,CAAC,MAAM,SAAS,KAAK,aAAa,MAAM,IAAI;AAAA,IACvD,MAAM,CAAC,SAAS,GAAG,QAAQ,IAAI;AAAA,IAC/B,OAAO,CAAC,SAAS,GAAG,SAAS,IAAI;AAAA,IACjC,SAAS,CAAC,SAAS,GAAG,WAAW,IAAI;AAAA,IACrC,OAAO,CAAC,SAAS,KAAK,SAAS,IAAI;AAAA,IACnC,IAAI,CAAC,MAAM,IAAI,CAAC,MAAM,KAAK,MAAM,MAAM,EAAE,UAAU,IAAI;AAAA,IACvD,QAAQ,CAAC,MAAM,OAAO,KAAK,UAAU,MAAM,EAAE;AAAA,IAC7C,UAAU,CAAC,SAAS,GAAG,YAAY,IAAI;AAAA,IACvC,SAAS,CAAC,QAAQ,SAAS,KAAK,WAAW,QAAQ,IAAI;AAAA,IACvD,UAAU,CAAC,SAAS,GAAG,YAAY,IAAI;AAAA,IACvC,QAAQ,CAAC,SAAS,GAAG,UAAU,IAAI;AAAA,IACnC,MAAM,MAAM,OAAO,SAAS,UAAU;AACpC,UAAI,QAAQ,SAAS,CAAC,IAAI,GAAG;AAC3B,cAAM,IAAI;AAAA,UACR,+BAA+B,QAAQ,SAAS,KAAK,GAAG,CAAC;AAAA,UACzD;AAAA,QACF;AAAA,MACF;AACA,YAAM,EAAE,IAAI,MAAAC,MAAK,IAAI,QAAQ,QAAQ;AAAA,QACnC,IAAI;AAAA,QACJ;AAAA,QACA,WAAW,QAAQ,cAAc;AAAA,MACnC,CAAC;AACD,cAAQ,SAAS,IAAI,IAAI,QAAQ;AACjC,UAAI;AACF,cAAMA;AAAA,MACR,SAAS,OAAO;AACd,gBAAQ,SAAS,OAAO,EAAE;AAC1B,cAAM;AAAA,MACR;AACA,aAAO;AAAA,QACL,OAAO,MAAM;AACX,cAAI,CAAC,QAAQ,SAAS,OAAO,EAAE,EAAG;AAClC,eAAK,QAAQ,KAAK,EAAE,IAAI,WAAW,OAAO,GAAG,CAAC,EAAE,MAAM,MAAM,MAAS;AAAA,QACvE;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;AAEA,SAAS,MAAM,SAAkB,OAAe,MAAc,KAA6B;AACzF,MAAI,QAAQ,SAAS,CAAC,IAAI,OAAO;AAC/B,WAAO,QAAQ;AAAA,MACb,IAAI;AAAA,QACF,+BAA+B,QAAQ,SAAS,KAAK,GAAG,CAAC,kBAAkB,IAAI;AAAA,QAC/E;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACA,SAAO,IAAI;AACb;AAEA,eAAe,MACb,SACA,MACA,WACsB;AACtB,UAAQ,KAAK,EAAE,OAAO,EAAE,UAAU,UAAU,GAAI,OAAO,EAAE,KAAK,IAAI,CAAC,EAAG,EAAE,CAAC;AACzE,QAAM,QAAQ;AAAA,IACZ,MACE,QAAQ;AAAA,MACN,IAAI,gBAAgB,gDAAgD,SAAS,KAAK;AAAA,IACpF;AAAA,IACF;AAAA,EACF;AACA,MAAI;AACJ,MAAI;AACF,YAAQ,MAAM,QAAQ,QAAQ;AAAA,EAChC,UAAE;AACA,iBAAa,KAAK;AAAA,EACpB;AACA,QAAM,UAAU,MAAM,SAAS,aAAa,MAAM,QAAQ;AAC1D,MAAI,SAAS;AACX,UAAM,QAAQ,IAAI,MAAM,OAAO;AAC/B,YAAQ,IAAI,KAAK;AACjB,UAAM;AAAA,EACR;AACA,SAAO;AACT;AAEA,eAAsB,aACpB,MACA,UAAyB,CAAC,GACH;AACvB,QAAM,QAAQ,QAAQ,UAAU,OAAO,SAAa,QAAQ,SAAS,QAAQ;AAC7E,QAAM,MAAM,MAAM,SAAS,KAAK;AAChC,QAAM,UAAU,IAAI,QAAQ,MAAM,IAAI,OAAO;AAC7C,QAAM,QAAQ,MAAM,MAAM,SAAS,IAAI,MAAM,QAAQ,aAAa,GAAM;AACxE,UAAQ,WAAW,MAAM;AACzB,MAAI,MAAM,QAAQ,MAAO,MAAK,MAAM,QAAQ,MAAM,MAAM,MAAM,QAAQ,IAAI,IAAI,gBAAgB,CAAC,CAAC;AAChG,QAAM,YAAY,IAAI;AAAA,IACpB,EAAE,aAAa,CAAC,SAAS,QAAQ,KAAK,IAAI,EAAE;AAAA,IAC5C,MAAM,UAAU;AAAA,EAClB;AACA,UAAQ,SAAS;AACjB,SAAO;AAAA,IACL,UAAU,MAAM;AAAA,IAChB;AAAA,IACA,QAAQ,QAAQ,MAAM;AAAA,IACtB,OAAO,CAAC,MAAM,OAAO,CAAC,MAAM,QAAQ,SAAS,MAAM,IAAI;AAAA,IACvD,KAAK,CAAC,MAAM,OAAO,CAAC,MAAM,MAAM,SAAS,MAAM,IAAI;AAAA,IACnD,cAAc,CAAC,MAAM,OAAO,CAAC,MAAM,WAAW,SAAS,MAAM,IAAI;AAAA,IACjE,IAAI,MAAM,QAAQ,KAAK,EAAE,IAAI,KAAK,CAAC;AAAA,IACnC,OAAO,CAAC,SACN,MAAM,SAAS,GAAG,SAAS,MAAM,QAAQ,KAAK,EAAE,IAAI,SAAS,KAAK,CAAC,CAAC;AAAA,IACtE,QAAQ,OAAO,WACb,KAAM,MAAM,MAAM,SAAS,GAAG,UAAU,MAAM,QAAQ,KAAK,EAAE,IAAI,UAAU,OAAO,CAAC,CAAC;AAAA,IACtF,QAAQ,MACN,MAAM,SAAS,GAAG,UAAU,MAAM,QAAQ,KAAK,EAAE,IAAI,SAAS,CAAC,CAAC;AAAA,IAClE,MAAM,OAAO,KAAK,SAAS,cAAc,KAAM,MAAM,QAAQ,KAAK,EAAE,IAAI,QAAQ,KAAK,OAAO,CAAC;AAAA,IAC7F,OAAO,CAAC,QAAQ;AACd,YAAM,EAAE,QAAQ,GAAG,KAAK,IAAI;AAC5B,aAAO,UAAU,MAAM,EAAE,GAAG,MAAM,QAAQ,UAAU,IAAI,gBAAgB,EAAE,OAAO,CAAC;AAAA,IACpF;AAAA,IACA,MAAM,CAACC,aAAY,OAAO,SAASA,QAAO;AAAA,IAC1C,eAAe,CAAC,OAAOA,aAAY,cAAc,CAAC,MAAM,OAAO,SAAS,CAAC,GAAG,OAAOA,QAAO;AAAA,IAC1F,IAAI,KAAK,OAAO;AAAA,IAChB,UAAU,CAAC,MAAMA,WAAU,CAAC,MAAM,WAAW,SAAS,MAAMA,QAAO;AAAA,IACnE,MAAM,MAAM,IAAI,CAAC,GAAG;AAClB,UAAI,QAAQ,QAAS;AACrB,YAAM,QACH,KAAK,EAAE,IAAI,UAAU,GAAI,EAAE,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC,EAAG,CAAC,EACxD,MAAM,MAAM,MAAS;AACxB,cAAQ,IAAI,IAAI,gBAAgB,uBAAuB,CAAC;AAAA,IAC1D;AAAA,EACF;AACF;;;AC1iBO,IAAM,kBAA6C,CAAC,GAAG,CAAC;AA6FxD,SAAS,mBAAmB,QAAqC;AACtE,QAAM,QAAQ,MAAM,QAAQ,MAAM,IAAI,OAAO,CAAC,IAAI;AAClD,MAAI,UAAU,gBAAgB,CAAC,EAAG,QAAO;AACzC,QAAM,QAAQ,OAAO,UAAU,WAAW,GAAG,KAAK,OAAO;AACzD,SAAO,gCAAgC,KAAK,uCAAuC,gBAAgB,KAAK,GAAG,CAAC;AAC9G;;;ACxCO,SAAS,QAAQ,MAAc,UAAU,MAAgC;AAC9E,SAAO,OAAO,OAAO,IAAI,MAAM,OAAO,GAAG,EAAE,KAAK,CAAC;AACnD;AAEA,eAAe,SAAS,GAAuB,KAAsC;AACnF,UAAQ,IAAI,IAAI;AAAA,IACd,KAAK;AACH,aAAO,EAAE,QAAQ,IAAI,IAAI;AAAA,IAC3B,KAAK;AACH,aAAO,EAAE,QAAQ,IAAI,IAAI;AAAA,IAC3B,KAAK;AACH,aAAO,EAAE,KAAK,IAAI,MAAM;AAAA,QACtB,OAAO,IAAI;AAAA,QACX,QAAQ,IAAI;AAAA,QACZ,UAAU,IAAI;AAAA,QACd,WAAW,IAAI;AAAA,QACf,GAAI,IAAI,YAAY,SAAY,EAAE,SAAS,IAAI,QAAQ,IAAI,CAAC;AAAA,MAC9D,CAAC;AAAA,IACH,KAAK;AACH,aAAO,EAAE,KAAK,IAAI,IAAI,IAAI,QAAQ,IAAI,IAAI;AAAA,IAC5C,KAAK;AACH,aAAO,EAAE,MAAM,IAAI,IAAI,IAAI,QAAQ,IAAI,KAAK;AAAA,IAC9C,KAAK;AACH,aAAO,EAAE,QAAQ,IAAI,EAAE;AAAA,IACzB,KAAK;AACH,aAAO,EAAE,MAAM,IAAI,IAAI;AAAA,IACzB,KAAK;AACH,aAAO,EAAE,MAAM,IAAI,IAAI;AAAA,IACzB,KAAK;AACH,aAAO,EAAE,OAAO,IAAI,IAAI;AAAA,IAC1B,KAAK;AACH,aAAO,EAAE,OAAO,IAAI,MAAM,IAAI,EAAE;AAAA,IAClC,KAAK;AACH,UAAI,CAAC,EAAE,QAAS,OAAM,QAAQ,SAAS,kCAAkC;AACzE,aAAO,EAAE,QAAQ,IAAI,QAAQ,IAAI,IAAI;AAAA,IACvC,KAAK;AACH,UAAI,CAAC,EAAE,SAAU,OAAM,QAAQ,UAAU,GAAG,IAAI,IAAI,mBAAmB;AACvE,aAAO,EAAE,SAAS,IAAI,IAAI;AAAA,IAC5B,KAAK;AACH,aAAO,EAAE,UAAU,IAAI,MAAM;AAAA,QAC3B,GAAI,IAAI,SAAS,SAAY,EAAE,MAAM,IAAI,KAAK,IAAI,CAAC;AAAA,QACnD,GAAI,IAAI,UAAU,SAAY,EAAE,OAAO,IAAI,MAAM,IAAI,CAAC;AAAA,QACtD,GAAI,IAAI,SAAS,SAAY,EAAE,MAAM,IAAI,KAAK,IAAI,CAAC;AAAA,MACrD,CAAC;AAAA,IACH,KAAK;AACH,aAAO,EAAE,SAAS,KAAK;AAAA,IACzB;AACE,YAAM,QAAQ,UAAU,qBAAsB,IAAuB,EAAE,EAAE;AAAA,EAC7E;AACF;AAEO,SAAS,gBACd,MACA,UACA,eAAmC,CAAC,GACpC,UAA+B,CAAC,GACd;AAClB,MAAI,OAAO;AACX,QAAM,QAAQ,CAAC,SAAiB,WAA2B,CAAC,MAC1D,KAAK,YAAY,SAAS,QAAQ;AACpC,iBAAe,MAAM,SAA2C;AAC9D,UAAM,UAAU,mBAAmB,QAAQ,QAAQ;AACnD,QAAI,SAAS;AACX,YAAM,EAAE,OAAO,EAAE,UAAU,iBAAiB,OAAO,SAAS,OAAO,SAAS,EAAE,CAAC;AAC/E;AAAA,IACF;AACA,QAAI;AACF,YAAM,UAAU,MAAM,SAAS,QAAQ,QAAQ,KAAK;AACpD,aAAO;AACP,YAAM;AAAA,QACJ,OAAO,EAAE,UAAU,iBAAiB,cAAc,EAAE,GAAG,cAAc,GAAG,QAAQ,EAAE;AAAA,MACpF,CAAC;AAAA,IACH,SAAS,KAAK;AACZ,YAAM,OAAQ,KAA4B;AAC1C,YAAM;AAAA,QACJ,OAAO;AAAA,UACL,UAAU;AAAA,UACV,OAAO,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAAA,UACtD,OAAO,OAAO,SAAS,WAAW,OAAO;AAAA,QAC3C;AAAA,MACF,CAAC;AAAA,IACH;AAAA,EACF;AACA,OAAK,iBAAiB,WAAW,CAAC,UAAU;AAC1C,UAAM,OAAO,MAAM;AACnB,QAAI,KAAK,OAAO;AACd,WAAK,MAAM,KAAK,KAAK;AACrB;AAAA,IACF;AACA,QAAI,CAAC,KAAM;AACX,aAAS,UAAU,IAAI,EAAE;AAAA,MACvB,CAAC,WAAW;AACV,YAAI,kBAAkB,YAAY;AAChC,gBAAM,QAAQ,OAAO,eAAe,KAAK,OAAO,eAAe,OAAO,OAAO;AAC7E,gBAAM,QAAQ,QAAQ,SAAS,QAAQ,SAAS,OAAO,MAAM;AAC7D,gBAAM,EAAE,IAAI,KAAK,IAAI,QAAQ,MAAM,GAAG,CAAC,MAAM,MAAM,CAAC;AAAA,QACtD,MAAO,OAAM,EAAE,IAAI,KAAK,IAAI,QAAQ,UAAU,KAAK,CAAC;AAAA,MACtD;AAAA,MACA,CAAC,QAAiB;AAChB,cAAM,OAAQ,KAA4B;AAC1C,cAAM;AAAA,UACJ,IAAI,KAAK;AAAA,UACT,OAAO,OAAO,SAAS,WAAW,OAAO;AAAA,UACzC,SAAS,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAAA,QAC1D,CAAC;AAAA,MACH;AAAA,IACF;AAAA,EACF,CAAC;AACD,OAAK,QAAQ;AACb,SAAO,EAAE,YAAY,CAAC,UAAU,MAAM,EAAE,YAAY,MAAM,CAAC,EAAE;AAC/D;;;AChJA,eAAsB,WACpB,OACA,MACe;AACf,MAAI;AACF,UAAM,WAAW,MAAM,KAAK,MAAM,IAAI,GAAG;AACzC,QAAI,OAAO,YAAY,YAAY;AACjC,YAAM,IAAI,MAAM,2DAA2D;AAAA,IAC7E;AACA,UAAM,SAAS,MAAM,aAAa,MAAM,QAAQ,EAAE,OAAO,KAAK,CAAC;AAC/D,UAAM,OAAO,MAAO,QAA0B,EAAE,OAAO,CAAC,YAAY,OAAO,MAAM,OAAO,EAAE,CAAC;AAC3F,oBAAgB,MAAM,QAAQ,KAAK,UAAU,KAAK,gBAAgB,CAAC,CAAC;AAAA,EACtE,SAAS,KAAK;AACZ,UAAM,OAAO,YAAY;AAAA,MACvB,OAAO;AAAA,QACL,UAAU;AAAA,QACV,OAAO,6BAA6B,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAAA,QACpF,OAAO;AAAA,MACT;AAAA,IACF,CAAC;AAAA,EACH;AACF;;;AC3CA;AAAA,EACE;AAAA,EACA,CAAC,UACC,KAAK;AAAA,IACF,MAAoC;AAAA,IACrC,CAAC,SAAS,OAAO,IAAI,gBAAgB,IAAI,KAAK,CAAC,IAAI,GAAG,EAAE,MAAM,kBAAkB,CAAC,CAAC;AAAA,EACpF;AAAA,EACF,EAAE,MAAM,KAAK;AACf;",
3
+ "sources": ["../src/cdp/port.ts", "../src/kernel/net/ws-queue.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 { RealmWebSocketClose, RealmWebSocketMessage } from './transport.ts';\n\nexport const INBOUND_LIMIT = 16 * 1024 * 1024;\nexport const MESSAGE_LIMIT = 64 * 1024 * 1024;\nexport const TOO_BIG = 1009;\n\nexport function payloadSize(message: RealmWebSocketMessage): number {\n return typeof message === 'string' ? new TextEncoder().encode(message).length : message.length;\n}\n\nexport class MessageQueue implements AsyncIterable<RealmWebSocketMessage> {\n private readonly items: RealmWebSocketMessage[] = [];\n private readonly limit: number;\n private waiter: (() => void) | undefined;\n private size = 0;\n private ended = false;\n private readonly overflow: () => void;\n private readonly taken: ((n: number) => void) | undefined;\n readonly closed: Promise<RealmWebSocketClose>;\n private settle!: (close: RealmWebSocketClose) => void;\n\n constructor(overflow: () => void, limit = INBOUND_LIMIT, taken?: (n: number) => void) {\n this.overflow = overflow;\n this.limit = limit;\n this.taken = taken;\n this.closed = new Promise((resolve) => {\n this.settle = resolve;\n });\n }\n\n push(message: RealmWebSocketMessage): void {\n if (this.ended) return;\n const size = payloadSize(message);\n const huge = size > MESSAGE_LIMIT;\n if (huge || (this.items.length > 0 && this.size + size > this.limit)) {\n const reason = huge\n ? `a message is over ${MESSAGE_LIMIT} bytes`\n : `over ${this.limit} bytes of messages are waiting`;\n this.end({ code: TOO_BIG, reason });\n this.overflow();\n return;\n }\n this.size += size;\n this.items.push(message);\n this.wake();\n }\n\n end(close: RealmWebSocketClose): void {\n if (this.ended) return;\n this.ended = true;\n this.settle(close);\n this.wake();\n }\n\n private wake(): void {\n const waiter = this.waiter;\n this.waiter = undefined;\n waiter?.();\n }\n\n async *[Symbol.asyncIterator](): AsyncIterator<RealmWebSocketMessage> {\n for (;;) {\n const next = this.items.shift();\n if (next !== undefined) {\n const n = payloadSize(next);\n this.size -= n;\n this.taken?.(n);\n yield next;\n continue;\n }\n if (this.ended) return;\n await new Promise<void>((resolve) => {\n this.waiter = resolve;\n });\n }\n }\n}\n", "import type {\n HeaderList,\n RealmTransport,\n RealmTransportRequest,\n RealmTransportResponse,\n RealmTransportTraits,\n RealmWebSocket,\n RealmWebSocketMessage,\n RealmWebSocketRequest,\n} from './transport.ts';\nimport { MessageQueue, payloadSize } from './ws-queue.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 | { net: 'ws-open'; nid: number; url: string; protocols: string[]; headers: HeaderList }\n | { net: 'ws-send'; nid: number; data: RealmWebSocketMessage }\n | { net: 'ws-close'; nid: number; code?: number; reason?: string }\n | { net: 'ws-consumed'; nid: number; n: 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 | { net: 'ws-opened'; nid: number; protocol: string }\n | { net: 'ws-message'; nid: number; data: RealmWebSocketMessage }\n | { net: 'ws-acked'; nid: number; n: number }\n | { net: 'ws-closed'; nid: number; code: number; reason: 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 readonly sockets = new Map<number, { queue: MessageQueue; acked(n: number): void }>();\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 socket = this.sockets.get(reply.nid);\n if (socket && this.toSocket(reply, socket)) return;\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 private toSocket(\n reply: TransportReply,\n socket: { queue: MessageQueue; acked(n: number): void }\n ): boolean {\n if (reply.net === 'ws-message') socket.queue.push(reply.data);\n else if (reply.net === 'ws-acked') socket.acked(reply.n);\n else if (reply.net === 'ws-closed') {\n this.sockets.delete(reply.nid);\n socket.queue.end({ code: reply.code, reason: reply.reason });\n } else return false;\n return true;\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 for (const socket of this.sockets.values())\n socket.queue.end({ code: 1011, reason: error.message });\n this.sockets.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 async websocket(request: RealmWebSocketRequest): Promise<RealmWebSocket> {\n const nid = ++this.nextId;\n const { signal } = request;\n signal.throwIfAborted();\n const abort = () => this.cancel(nid);\n signal.addEventListener('abort', abort, { once: true });\n let opened: TransportReply;\n try {\n opened = await this.ask({\n net: 'ws-open',\n nid,\n url: request.url,\n protocols: request.protocols,\n headers: request.headers,\n });\n } finally {\n signal.removeEventListener('abort', abort);\n }\n const close = (code?: number, reason?: string) =>\n this.port.postMessage({ net: 'ws-close', nid, code, reason });\n const queue = new MessageQueue(\n () => close(1000, 'a message is too big'),\n Number.POSITIVE_INFINITY,\n (n) => this.port.postMessage({ net: 'ws-consumed', nid, n })\n );\n let unacked = 0;\n this.sockets.set(nid, { queue, acked: (n) => void (unacked -= n) });\n return {\n protocol: (opened as Extract<TransportReply, { net: 'ws-opened' }>).protocol,\n get buffered() {\n return unacked;\n },\n send: (data) => {\n unacked += payloadSize(data);\n this.port.postMessage({ net: 'ws-send', nid, data });\n },\n messages: queue,\n close,\n closed: queue.closed,\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 sessions?: 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
  }