@ai-ecoverse/slicc-kernel 1.175.1 → 1.176.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 +5 -4
- package/dist/driver-worker.js +2 -1
- package/dist/driver-worker.js.map +2 -2
- package/dist/index.js +3 -1
- package/dist/index.js.map +2 -2
- package/dist/kernel-worker.js +44 -5
- package/dist/kernel-worker.js.map +2 -2
- package/dist/node-driver-worker.js +2 -1
- package/dist/node-driver-worker.js.map +2 -2
- package/dist/node-process-worker.cjs +1 -1
- package/dist/node-process-worker.js +1 -1
- package/dist/node.js +45 -6
- package/dist/node.js.map +2 -2
- package/dist/process-worker.js +1 -1
- package/dist/types/fs/dac.d.ts +1 -0
- package/dist/types/index.d.ts +3 -2
- package/dist/types/kernel/embedder.d.ts +3 -0
- package/dist/types/serve.d.ts +5 -0
- package/dist/types/users.d.ts +5 -1
- package/package.json +1 -1
package/dist/index.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/cdp/port.ts", "../src/bytes.ts", "../src/client/dial-stream.ts", "../src/client/loopback-fetch.ts", "../src/kernel/pipe.ts", "../src/kernel/clipboard.ts", "../src/clipboard-relay.ts", "../src/embedder-relay.ts", "../src/facade/port.ts", "../src/fs/types.ts", "../src/fs/protect.ts", "../src/fs/integrity.ts", "../src/fs/portable.ts", "../src/integrity-relay.ts", "../src/kernel/embedder.ts", "../src/kernel/net/loopback-names.ts", "../src/body-idle.ts", "../src/kernel/net/sealed-fetch.ts", "../src/kernel/net/routes.ts", "../src/kernel/net/uplink.ts", "../src/kernel/signals.ts", "../src/sealed-relay.ts", "../src/time-zone.ts", "../src/kernel/net/ws-queue.ts", "../src/websocket-transport.ts", "../src/transport.ts", "../src/kernel/net/remote-transport.ts", "../src/client/protocol.ts", "../src/client/attach.ts", "../src/mount/driver.ts", "../src/mount/hostfs.ts", "../src/index.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", "export function fresh(bytes: Uint8Array, start = 0, end = bytes.length): Uint8Array {\n return new Uint8Array(bytes.subarray(start, end));\n}\n", "import { fresh } from '../bytes.ts';\n\nexport 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 = fresh(chunk);\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", "export const PIPE_CAPACITY = 64 * 1024;\n\nexport interface PipeMark {\n readonly at: number;\n readonly count: number;\n drop(): void;\n}\n\nexport class PipeError extends Error {\n readonly code: 'EPIPE' | 'EINTR' | 'EAGAIN';\n\n constructor(code: 'EPIPE' | 'EINTR' | 'EAGAIN') {\n super(code);\n this.code = code;\n }\n}\n\nexport class KernelPipe {\n private chunks: Uint8Array[] = [];\n private size = 0;\n private readers = 0;\n private writers = 0;\n private waiters: Array<() => void> = [];\n private pushed = 0;\n private taken = 0;\n private marks: PipeMark[] = [];\n\n readonly capacity: number;\n\n constructor(capacity: number = PIPE_CAPACITY) {\n this.capacity = capacity;\n }\n\n get buffered(): number {\n return this.size;\n }\n\n get readReady(): boolean {\n return this.size > 0 || this.writers === 0;\n }\n\n get writeReady(): boolean {\n return this.size < this.capacity || this.readers === 0;\n }\n\n get writersGone(): boolean {\n return this.writers === 0;\n }\n\n get readersGone(): boolean {\n return this.readers === 0;\n }\n\n openRead(): void {\n this.readers += 1;\n }\n\n openWrite(): void {\n this.writers += 1;\n }\n\n closeRead(): void {\n if (this.readers > 0) this.readers -= 1;\n if (this.readers === 0) {\n this.chunks = [];\n this.size = 0;\n this.dropMarks(() => true);\n }\n this.wake();\n }\n\n closeWrite(): void {\n if (this.writers > 0) this.writers -= 1;\n this.wake();\n }\n\n async read(max: number, signal?: AbortSignal): Promise<Uint8Array> {\n while (this.size === 0) {\n if (this.writers === 0) return new Uint8Array(0);\n await this.changed(signal);\n }\n const out = this.take(this.bounded(Math.min(max, this.size)));\n this.dropMarks((mark) => mark.at < this.taken);\n this.wake();\n return out;\n }\n\n get inFlight(): number {\n return this.marks.reduce((sum, mark) => sum + mark.count, 0);\n }\n\n async receive(\n max: number,\n nonblock: boolean,\n signal?: AbortSignal\n ): Promise<{ bytes: Uint8Array; marks: PipeMark[] }> {\n while (this.size === 0) {\n if (this.writers === 0) return { bytes: new Uint8Array(0), marks: [] };\n if (nonblock) throw new PipeError('EAGAIN');\n await this.changed(signal);\n }\n const marks = this.marks.filter((mark) => mark.at === this.taken);\n this.marks = this.marks.filter((mark) => mark.at !== this.taken);\n const bytes = this.take(this.bounded(Math.min(max, this.size)));\n this.dropMarks((mark) => mark.at < this.taken);\n this.wake();\n return { bytes, marks };\n }\n\n async writeMarked(\n bytes: Uint8Array,\n mark: (at: number) => PipeMark,\n nonblock: boolean,\n signal?: AbortSignal\n ): Promise<number> {\n while (this.readers > 0 && this.size >= this.capacity) {\n if (nonblock) throw new PipeError('EAGAIN');\n await this.changed(signal);\n }\n if (this.readers === 0) throw new PipeError('EPIPE');\n const before = this.pushed;\n const made = mark(before);\n this.marks.push(made);\n try {\n const n = await this.write(bytes, signal);\n this.orphan(made, before);\n return n;\n } catch (err) {\n this.orphan(made, before);\n throw err;\n }\n }\n\n private orphan(made: PipeMark, before: number): void {\n if (this.pushed !== before) return;\n this.dropMarks((mark) => mark === made);\n }\n\n private bounded(n: number): number {\n const next = this.marks.find((mark) => mark.at > this.taken);\n return next ? Math.min(n, next.at - this.taken) : n;\n }\n\n private dropMarks(gone: (mark: PipeMark) => boolean): void {\n const dropped = this.marks.filter(gone);\n if (dropped.length === 0) return;\n this.marks = this.marks.filter((mark) => !gone(mark));\n for (const mark of dropped) mark.drop();\n }\n\n async peek(max: number, signal?: AbortSignal): Promise<Uint8Array> {\n while (this.size === 0) {\n if (this.writers === 0) return new Uint8Array(0);\n await this.changed(signal);\n }\n const out = new Uint8Array(Math.min(max, this.size));\n let filled = 0;\n for (const chunk of this.chunks) {\n if (filled === out.length) break;\n const count = Math.min(chunk.length, out.length - filled);\n out.set(chunk.subarray(0, count), filled);\n filled += count;\n }\n return out;\n }\n\n async write(bytes: Uint8Array, signal?: AbortSignal): Promise<number> {\n let offset = 0;\n while (offset < bytes.length) {\n if (this.readers === 0) throw new PipeError('EPIPE');\n const room = this.capacity - this.size;\n if (room === 0) {\n try {\n await this.changed(signal);\n } catch (e) {\n if (offset > 0) return offset;\n throw e;\n }\n continue;\n }\n const n = Math.min(room, bytes.length - offset);\n this.chunks.push(bytes.slice(offset, offset + n));\n this.size += n;\n this.pushed += n;\n offset += n;\n this.wake();\n }\n return bytes.length;\n }\n\n private take(n: number): Uint8Array {\n const out = new Uint8Array(n);\n let filled = 0;\n while (filled < n) {\n const head = this.chunks[0];\n const count = Math.min(head.length, n - filled);\n out.set(head.subarray(0, count), filled);\n filled += count;\n if (count === head.length) this.chunks.shift();\n else this.chunks[0] = head.subarray(count);\n }\n this.size -= n;\n this.taken += n;\n return out;\n }\n\n changed(signal?: AbortSignal): Promise<void> {\n if (signal?.aborted) return Promise.reject(new PipeError('EINTR'));\n return new Promise((resolve, reject) => {\n const onAbort = (): void => {\n this.waiters = this.waiters.filter((w) => w !== waiter);\n reject(new PipeError('EINTR'));\n };\n const waiter = (): void => {\n signal?.removeEventListener('abort', onAbort);\n resolve();\n };\n this.waiters.push(waiter);\n signal?.addEventListener('abort', onAbort, { once: true });\n });\n }\n\n private wake(): void {\n const waiters = this.waiters;\n this.waiters = [];\n for (const resolve of waiters) resolve();\n }\n}\n", "import type { UsersMode } from '../fs/types.ts';\nimport { KernelError, type OpenAccess, OpenFile, type PollState } from './fd-table.ts';\n\nexport const CLIPBOARD_PATH = '/dev/clipboard';\nexport const CLIPBOARD_MINOR = 251;\nexport const CLIPBOARD_MAX_BYTES = 1024 * 1024;\nexport const CLIPBOARD_TIMEOUT_MS = 10_000;\n\nexport interface ClipboardStamp {\n pid: number;\n uid: number;\n gid: number;\n users: UsersMode;\n tag?: string;\n tags?: string[];\n}\n\nexport interface ClipboardHook {\n read(stamp: ClipboardStamp): Promise<string>;\n write(text: string, stamp: ClipboardStamp): Promise<void>;\n}\n\nconst encoder = new TextEncoder();\nconst decoder = new TextDecoder('utf-8', { fatal: true });\nconst READY: PollState = { readable: true, writable: true, hangup: false };\n\nfunction lineOf(err: unknown): string {\n const text = err instanceof Error ? err.message : String(err);\n return (text.split('\\n')[0] ?? '').slice(0, 200);\n}\n\nexport function clipboardFailure(err: unknown): KernelError {\n if (err instanceof KernelError) return err;\n const name = (err as { name?: unknown } | null)?.name;\n return new KernelError(name === 'NotAllowedError' ? 'EACCES' : 'EIO', lineOf(err));\n}\n\nfunction joined(chunks: Uint8Array[], size: number): Uint8Array {\n if (chunks.length === 1) return chunks[0] as Uint8Array;\n const out = new Uint8Array(size);\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\nasync function interruptible<T>(work: Promise<T>, signal: AbortSignal | undefined): Promise<T> {\n if (!signal) return work;\n if (signal.aborted) throw new KernelError('EINTR');\n let stop = (): void => {};\n const interrupted = new Promise<never>((_, reject) => {\n stop = () => reject(new KernelError('EINTR'));\n signal.addEventListener('abort', stop, { once: true });\n });\n try {\n return await Promise.race([work, interrupted]);\n } finally {\n signal.removeEventListener('abort', stop);\n }\n}\n\nclass ClipboardChannel {\n stamp: ClipboardStamp;\n readonly access: OpenAccess;\n private readonly broker: ClipboardBroker;\n private snapshot: Promise<Uint8Array> | undefined;\n private taken: Uint8Array | undefined;\n private offset = 0;\n private chunks: Uint8Array[] = [];\n private size = 0;\n private wrote = false;\n private failed = false;\n private aborted = false;\n\n constructor(broker: ClipboardBroker, access: OpenAccess, stamp: ClipboardStamp) {\n this.broker = broker;\n this.access = access;\n this.stamp = stamp;\n }\n\n get unread(): boolean {\n return this.taken === undefined && this.snapshot === undefined;\n }\n\n get settled(): boolean {\n return this.taken !== undefined;\n }\n\n async read(max: number, signal?: AbortSignal): Promise<Uint8Array> {\n if (this.access === 'write') throw new KernelError('EBADF');\n if (!this.taken) {\n if (!this.snapshot) {\n const stamp = this.stamp;\n const asked = this.broker.ask(async (hook) => {\n const text = await hook.read(stamp);\n if (typeof text !== 'string') throw new KernelError('EIO', 'the clipboard gave no text');\n return encoder.encode(text);\n });\n this.snapshot = asked;\n asked.then(\n (bytes) => {\n if (this.snapshot === asked) this.taken = bytes;\n },\n () => {\n if (this.snapshot === asked) this.snapshot = undefined;\n }\n );\n }\n this.taken = await interruptible(this.snapshot, signal);\n }\n const out = this.taken.subarray(this.offset, this.offset + max);\n this.offset += out.length;\n return out;\n }\n\n write(bytes: Uint8Array): number {\n if (this.access === 'read') throw new KernelError('EBADF');\n this.wrote = true;\n if (this.failed) throw new KernelError('EFBIG');\n if (this.size + bytes.length > CLIPBOARD_MAX_BYTES) {\n this.failed = true;\n this.chunks = [];\n this.size = 0;\n throw new KernelError('EFBIG');\n }\n if (bytes.length > 0) this.chunks.push(bytes.slice());\n this.size += bytes.length;\n return bytes.length;\n }\n\n poll(): PollState {\n return READY;\n }\n\n abort(): void {\n this.aborted = true;\n }\n\n async close(): Promise<void> {\n this.snapshot = undefined;\n this.taken = undefined;\n const commits = this.access === 'write' || (this.access === 'both' && this.wrote);\n if (!commits || this.failed || this.aborted) return;\n const bytes = joined(this.chunks, this.size);\n this.chunks = [];\n this.size = 0;\n let text: string;\n try {\n text = decoder.decode(bytes);\n } catch {\n throw new KernelError('EILSEQ', 'the text is not valid UTF-8');\n }\n const stamp = this.stamp;\n await this.broker.ask(async (hook) => {\n await hook.write(text, stamp);\n });\n }\n}\n\nexport class ClipboardBroker {\n readonly hook: ClipboardHook | undefined;\n readonly users: UsersMode;\n readonly timeoutMs: number;\n readonly tagOf: (pid: number) => readonly string[] | undefined;\n\n constructor(\n hook: ClipboardHook | undefined,\n users: UsersMode,\n timeoutMs = CLIPBOARD_TIMEOUT_MS,\n tagOf: (pid: number) => readonly string[] | undefined = () => undefined\n ) {\n this.hook = hook;\n this.users = users;\n this.timeoutMs = timeoutMs;\n this.tagOf = tagOf;\n }\n\n async ask<T>(work: (hook: ClipboardHook) => Promise<T>): Promise<T> {\n const hook = this.hook;\n if (!hook) throw new KernelError('ENOTSUP', 'no clipboard in this embedder');\n let timer: ReturnType<typeof setTimeout> | undefined;\n const late = new Promise<never>((_, reject) => {\n timer = setTimeout(\n () => reject(new KernelError('EIO', 'clipboard timed out')),\n this.timeoutMs\n );\n });\n const asked = Promise.resolve()\n .then(() => work(hook))\n .catch((err: unknown) => {\n throw clipboardFailure(err);\n });\n try {\n return await Promise.race([asked, late]);\n } finally {\n clearTimeout(timer);\n }\n }\n\n open(access: OpenAccess, stamp: ClipboardStamp): OpenFile {\n const channel = new ClipboardChannel(this, access, stamp);\n return new OpenFile({\n read: (max, signal) => channel.read(max, signal),\n write: async (bytes) => channel.write(bytes),\n poll: () => channel.poll(),\n close: () => channel.close(),\n clipboard: channel,\n });\n }\n}\n\nexport type { ClipboardChannel };\n", "import {\n CLIPBOARD_TIMEOUT_MS,\n type ClipboardHook,\n type ClipboardStamp,\n} from './kernel/clipboard.ts';\n\nexport interface ClipboardPort {\n postMessage(message: unknown): void;\n}\n\nexport interface ClipboardAsk {\n id: number;\n op: 'read' | 'write';\n text?: string;\n stamp: ClipboardStamp;\n}\n\nexport interface ClipboardReply {\n id: number;\n text?: string;\n error?: { name: string; message: string };\n}\n\nexport function clipboardAsker(port: ClipboardPort): {\n hook: ClipboardHook;\n answer(reply: ClipboardReply): void;\n} {\n const asks = new Map<number, PromiseWithResolvers<string | undefined>>();\n let next = 0;\n const ask = (op: 'read' | 'write', stamp: ClipboardStamp, text?: string) => {\n const id = ++next;\n const waiting = Promise.withResolvers<string | undefined>();\n asks.set(id, waiting);\n const timer = setTimeout(() => {\n if (asks.delete(id)) waiting.reject(new Error('clipboard timed out'));\n }, CLIPBOARD_TIMEOUT_MS + 1000);\n port.postMessage({ clipboardAsk: { id, op, stamp, ...(text !== undefined ? { text } : {}) } });\n return waiting.promise.finally(() => clearTimeout(timer));\n };\n const hook: ClipboardHook = {\n read: async (stamp) => (await ask('read', stamp)) ?? '',\n write: async (text, stamp) => {\n await ask('write', stamp, text);\n },\n };\n const answer = ({ id, text, error }: ClipboardReply) => {\n const waiting = asks.get(id);\n if (!waiting) return;\n asks.delete(id);\n if (error) waiting.reject(Object.assign(new Error(error.message), { name: error.name }));\n else waiting.resolve(text);\n };\n return { hook, answer };\n}\n\nexport function clipboardAnswerer(\n port: ClipboardPort,\n hook: ClipboardHook | undefined\n): { handle(data: unknown): boolean } {\n const ask = async ({ id, op, text, stamp }: ClipboardAsk): Promise<void> => {\n try {\n if (!hook) throw new Error('no clipboard in this embedder');\n if (op === 'read') {\n const got = await hook.read(stamp);\n if (typeof got !== 'string') throw new Error('the clipboard gave no text');\n port.postMessage({ clipboardReply: { id, text: got } });\n } else {\n await hook.write(text ?? '', stamp);\n port.postMessage({ clipboardReply: { id } });\n }\n } catch (err) {\n const name = (err as { name?: unknown } | null)?.name;\n const message = err instanceof Error ? err.message : String(err);\n port.postMessage({\n clipboardReply: { id, error: { name: typeof name === 'string' ? name : 'Error', message } },\n });\n }\n };\n return {\n handle(data) {\n const message = data as { clipboardAsk?: ClipboardAsk } | null;\n if (!message?.clipboardAsk) return false;\n void ask(message.clipboardAsk);\n return true;\n },\n };\n}\n", "import type {\n EmbedderHook,\n EmbedderKindPolicy,\n EmbedderReply,\n EmbedderStamp,\n} from './kernel/embedder.ts';\n\nexport interface EmbedderPort {\n postMessage(message: unknown, transfer?: Transferable[]): void;\n}\n\ntype Kinds = Readonly<Record<string, EmbedderKindPolicy>>;\n\nexport interface EmbedderAsk {\n id: number;\n client: number;\n kind: string;\n options: Record<string, unknown>;\n stamp: EmbedderStamp;\n}\n\nexport type EmbedderToPage =\n | { ask: EmbedderAsk }\n | { id: number; body: Uint8Array }\n | { id: number; bodyEnd: true }\n | { id: number; pull: true }\n | { id: number; cancel: string };\n\nexport type EmbedderToKernel =\n | { id: number; ready: true }\n | { id: number; chunk: Uint8Array }\n | { id: number; done: true }\n | { id: number; error: { name: string; message: string } }\n | { id: number; progress: string }\n | { id: number; bodyPull: true }\n | { id: number; bodyCancel: true };\n\nfunction fresh(bytes: Uint8Array): Uint8Array {\n return bytes.byteOffset === 0 && bytes.byteLength === bytes.buffer.byteLength\n ? bytes\n : bytes.slice();\n}\n\nfunction errorOf(err: unknown): { name: string; message: string } {\n const name = (err as { name?: unknown } | null)?.name;\n const message = err instanceof Error ? err.message : String(err);\n return { name: typeof name === 'string' ? name : 'Error', message };\n}\n\ninterface Asked {\n ready: PromiseWithResolvers<void>;\n chunks: Array<Uint8Array | null | { name: string; message: string }>;\n wake: (() => void) | undefined;\n body: ReadableStreamDefaultReader<Uint8Array>;\n progress(line: string): void;\n}\n\nexport function embedderAsker(port: EmbedderPort) {\n const asks = new Map<number, Asked>();\n let next = 0;\n const post = (message: EmbedderToPage, transfer: Transferable[] = []) =>\n port.postMessage({ embedder: message }, transfer);\n const push = (asked: Asked, item: Asked['chunks'][number]) => {\n asked.chunks.push(item);\n asked.wake?.();\n };\n const reply = (id: number, asked: Asked) =>\n new ReadableStream<Uint8Array>(\n {\n pull: async (controller) => {\n if (asked.chunks.length === 0) {\n post({ id, pull: true });\n await new Promise<void>((resolve) => {\n asked.wake = resolve;\n });\n }\n const item = asked.chunks.shift();\n if (item instanceof Uint8Array) controller.enqueue(item);\n else if (item === null || item === undefined) {\n asks.delete(id);\n controller.close();\n } else {\n asks.delete(id);\n controller.error(Object.assign(new Error(item.message), { name: item.name }));\n }\n },\n cancel: (reason) => {\n asks.delete(id);\n post({ id, cancel: String(reason ?? 'closed') });\n },\n },\n { highWaterMark: 0 }\n );\n const sendBody = async (id: number, asked: Asked) => {\n const got = await asked.body.read().catch(() => ({ done: true as const, value: undefined }));\n if (got.done) post({ id, bodyEnd: true });\n else {\n const bytes = fresh(got.value);\n post({ id, body: bytes }, [bytes.buffer as ArrayBuffer]);\n }\n };\n const hookFor = (client: number, kinds: Kinds): EmbedderHook => ({\n kinds,\n handle: async (request) => {\n const id = ++next;\n const asked: Asked = {\n ready: Promise.withResolvers<void>(),\n chunks: [],\n wake: undefined,\n body: request.body.getReader(),\n progress: request.progress,\n };\n asks.set(id, asked);\n const cancel = () => {\n asks.delete(id);\n post({\n id,\n cancel: String((request.signal.reason as Error | undefined)?.message ?? 'closed'),\n });\n asked.ready.reject(request.signal.reason);\n push(asked, { name: 'AbortError', message: 'cancelled' });\n };\n request.signal.addEventListener('abort', cancel, { once: true });\n const { kind, options, stamp } = request;\n post({ ask: { id, client, kind, options, stamp } });\n await asked.ready.promise;\n return reply(id, asked);\n },\n });\n const answer = (message: EmbedderToKernel): void => {\n const asked = asks.get(message.id);\n if (!asked) return;\n if ('ready' in message) asked.ready.resolve();\n else if ('chunk' in message) push(asked, message.chunk);\n else if ('done' in message) push(asked, null);\n else if ('error' in message) {\n asked.ready.reject(\n Object.assign(new Error(message.error.message), { name: message.error.name })\n );\n asks.delete(message.id);\n void asked.body.cancel(message.error.message).catch(() => undefined);\n push(asked, message.error);\n } else if ('progress' in message) asked.progress(message.progress);\n else if ('bodyCancel' in message) void asked.body.cancel('the page').catch(() => undefined);\n else void sendBody(message.id, asked);\n };\n return { hookFor, answer };\n}\n\nfunction bytesOf(reply: EmbedderReply): ReadableStream<Uint8Array> {\n if (reply instanceof ReadableStream) return reply;\n const bytes =\n typeof reply === 'string'\n ? new TextEncoder().encode(reply)\n : reply instanceof Uint8Array\n ? reply\n : new Uint8Array(0);\n return new ReadableStream({\n start(controller) {\n if (bytes.length > 0) controller.enqueue(bytes);\n controller.close();\n },\n });\n}\n\ninterface Answering {\n abort: AbortController;\n body: Array<Uint8Array | null>;\n wakeBody: (() => void) | undefined;\n reader?: ReadableStreamDefaultReader<Uint8Array>;\n}\n\nfunction bodyStream(id: number, state: Answering, post: (m: EmbedderToKernel) => void) {\n return new ReadableStream<Uint8Array>(\n {\n pull: async (controller) => {\n if (state.body.length === 0) post({ id, bodyPull: true });\n while (state.body.length === 0 && !state.abort.signal.aborted) {\n await new Promise<void>((resolve) => {\n state.wakeBody = resolve;\n });\n }\n const next = state.body.shift();\n if (next) controller.enqueue(next);\n else controller.close();\n },\n cancel: () => post({ id, bodyCancel: true }),\n },\n { highWaterMark: 0 }\n );\n}\n\nexport function embedderAnswerer(\n port: EmbedderPort,\n hookFor: (client: number) => EmbedderHook | undefined\n): { handle(data: unknown): boolean } {\n const running = new Map<number, Answering>();\n const post = (message: EmbedderToKernel, transfer: Transferable[] = []) =>\n port.postMessage({ embedderReply: message }, transfer);\n const fail = (id: number, err: unknown) => {\n running.delete(id);\n post({ id, error: errorOf(err) });\n };\n const start = async (ask: EmbedderAsk) => {\n const state: Answering = { abort: new AbortController(), body: [], wakeBody: undefined };\n running.set(ask.id, state);\n try {\n const hook = hookFor(ask.client);\n if (!hook || !Object.hasOwn(hook.kinds, ask.kind))\n throw Object.assign(new Error(`this page does not answer ${ask.kind}`), {\n name: 'NotSupportedError',\n });\n const body = bodyStream(ask.id, state, post);\n const reply = await hook.handle({\n kind: ask.kind,\n options: ask.options,\n body,\n stamp: ask.stamp,\n signal: state.abort.signal,\n progress: (line) => post({ id: ask.id, progress: String(line) }),\n });\n if (!(reply instanceof ReadableStream)) post({ id: ask.id, bodyCancel: true });\n state.reader = bytesOf(reply).getReader();\n post({ id: ask.id, ready: true });\n } catch (err) {\n fail(ask.id, err);\n }\n };\n const pull = async (id: number, state: Answering) => {\n try {\n const got = await (state.reader as ReadableStreamDefaultReader<Uint8Array>).read();\n if (got.done) {\n running.delete(id);\n post({ id, done: true });\n return;\n }\n const bytes = fresh(got.value);\n post({ id, chunk: bytes }, [bytes.buffer as ArrayBuffer]);\n } catch (err) {\n fail(id, err);\n }\n };\n const step = (message: Exclude<EmbedderToPage, { ask: EmbedderAsk }>) => {\n const state = running.get(message.id);\n if (!state) return;\n if ('body' in message) state.body.push(message.body);\n else if ('bodyEnd' in message) state.body.push(null);\n else if ('pull' in message) void pull(message.id, state);\n else {\n running.delete(message.id);\n state.abort.abort(new DOMException(message.cancel, 'AbortError'));\n void state.reader?.cancel(message.cancel).catch(() => undefined);\n }\n state.wakeBody?.();\n };\n return {\n handle(data) {\n const message = (data as { embedder?: EmbedderToPage } | null)?.embedder;\n if (!message) return false;\n if ('ask' in message) void start(message.ask);\n else step(message);\n return true;\n },\n };\n}\n\nexport function embedderReplyOf(data: unknown): EmbedderToKernel | undefined {\n return (data as { embedderReply?: EmbedderToKernel } | null)?.embedderReply;\n}\n", "import type { ConnectorStamp } from '../kernel/socket.ts';\nimport type { FacadeConnection, FacadeHook, FacadeOpenRequest } from './types.ts';\n\nexport interface FacadePortLike {\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 FacadeWire = { open: true } | { error: string } | { b: Uint8Array } | { close: true | string };\n\nexport interface FacadeOpen {\n facadeOpen: FacadeOpenRequest & { registration?: number };\n port: FacadePortLike;\n}\n\nexport const FACADE_GONE = 'the facade host is gone';\n\nexport function serveFacadePort(\n port: FacadePortLike,\n hook: FacadeHook,\n { name, stamp }: FacadeOpenRequest,\n onDone?: () => void\n): () => void {\n let conn: FacadeConnection | undefined;\n let done = false;\n const end = () => {\n done = true;\n port.close();\n onDone?.();\n };\n const finish = () => {\n if (done) return;\n port.postMessage({ close: true });\n end();\n };\n port.addEventListener(\n 'message',\n ({ data }: MessageEvent<{ b?: Uint8Array; close?: true | string }>) => {\n if (data.b !== undefined) conn?.send(data.b);\n else if (data.close && !done) {\n end();\n conn?.close(typeof data.close === 'string' ? data.close : undefined);\n }\n }\n );\n port.start?.();\n new Promise<FacadeConnection>((resolve) => resolve(hook(stamp, { name }))).then(\n (opened) => {\n conn = opened;\n if (done) return opened.close();\n opened.onmessage = (bytes) => {\n if (done) return;\n const copy = bytes.slice();\n port.postMessage({ b: copy }, [copy.buffer]);\n };\n opened.onclose = () => finish();\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();\n };\n}\n\nexport function portFacadeHook(\n ask: (request: FacadeOpenRequest, port: FacadePortLike) => void,\n gone?: Promise<unknown>\n): FacadeHook {\n return (stamp: ConnectorStamp, { name }) =>\n new Promise((resolve, reject) => {\n const { port1, port2 } = new MessageChannel();\n let closed = false;\n const shut = () => {\n closed = true;\n port1.close();\n };\n const conn: FacadeConnection = {\n send: (bytes) => {\n if (closed) return;\n const copy = bytes.slice();\n port1.postMessage({ b: copy }, [copy.buffer]);\n },\n onmessage: null,\n onclose: null,\n close: (reason) => {\n if (closed) return;\n port1.postMessage({ close: reason ?? true });\n shut();\n },\n };\n port1.addEventListener('message', ({ data }: MessageEvent<FacadeWire>) => {\n if ('b' in data) conn.onmessage?.(data.b);\n else if ('open' in data) resolve(conn);\n else if ('error' in data) {\n shut();\n reject(new Error(data.error));\n } else if (!closed) {\n shut();\n conn.onclose?.();\n }\n });\n port1.start();\n void gone?.then(() => {\n if (closed) return;\n shut();\n reject(new Error(FACADE_GONE));\n conn.onclose?.(FACADE_GONE);\n });\n ask({ name, stamp }, port2 as unknown as FacadePortLike);\n });\n}\n", "export interface FsStat {\n isFile: boolean;\n isDirectory: boolean;\n isSymbolicLink: boolean;\n isSocket?: boolean;\n isFifo?: boolean;\n size: number;\n mode: number;\n mtime: Date;\n atime: Date;\n ctime: Date;\n ino: number;\n fid?: string;\n nlink?: number;\n dev?: number;\n readonly?: boolean;\n maxFile?: number;\n ranged?: boolean;\n linkable?: boolean;\n version?: string;\n uid?: number;\n gid?: number;\n}\n\nexport type UsersMode = 'off' | 'report' | 'enforce';\n\nexport const DEFAULT_USERS: UsersMode = 'enforce';\n\nexport interface Owner {\n uid: number;\n gid: number;\n}\n\nexport interface Perm {\n uid: number;\n gid: number;\n mode?: number;\n link?: string;\n}\n\nexport interface NewOwner extends Owner {\n mode?: number;\n parents?: number;\n socket?: boolean;\n fifo?: boolean;\n existing?: true;\n}\n\nexport interface CopyOptions {\n exclusive: boolean;\n owner?: NewOwner;\n}\n\nexport interface OwnerChange {\n uid?: number;\n gid?: number;\n follow?: boolean;\n kind?: 'chown' | 'adopt' | 'new';\n mode?: number;\n}\n\nexport interface HeldEntry {\n writeFile: KernelFs['writeFile'];\n direct: boolean;\n}\n\nexport interface Peers {\n joined(): Promise<unknown>;\n crowded(): boolean;\n watch(listener: (crowded: boolean) => void): void;\n fresh?(): void;\n}\n\nexport interface KernelFs {\n resolvePath(base: string, path: string): string;\n exclusive?<T>(path: string, run: (held: HeldEntry) => Promise<T>, follow?: boolean): Promise<T>;\n readFile(path: string): Promise<string>;\n readFileBuffer(path: string): Promise<Uint8Array>;\n writeFile(path: string, content: Uint8Array | string, owner?: NewOwner): Promise<void>;\n exists(path: string): Promise<boolean>;\n stat(path: string): Promise<FsStat>;\n lstat(path: string): Promise<FsStat>;\n readdir(path: string): Promise<string[]>;\n readdirStat(path: string): Promise<Array<[string, FsStat | null]>>;\n mkdir(path: string, options?: { recursive?: boolean; owner?: NewOwner }): Promise<void>;\n rm(\n path: string,\n options?: { recursive?: boolean; force?: boolean; file?: boolean }\n ): Promise<void>;\n rename(from: string, to: string): Promise<void>;\n link(from: string, to: string, follow?: boolean): Promise<void>;\n links?(path: string): boolean;\n symlink(target: string, path: string, owner?: NewOwner): Promise<void>;\n readlink(path: string): Promise<string>;\n realpath?(path: string, follow: boolean): Promise<string>;\n createExclusive?(path: string, owner?: NewOwner): Promise<void>;\n copyFile?(from: string, to: string, options: CopyOptions): Promise<void>;\n readonly rootName?: string;\n chown?(path: string, change: OwnerChange): Promise<void>;\n trackOwners?(): void;\n onPeer?(settle: () => Promise<void>): void;\n heldBy?(held: (dir: string) => readonly string[]): void;\n fileId?(path: string): Promise<string>;\n bindId?(path: string): Promise<string | undefined>;\n remoteChanges?(\n listener: (change: {\n paths: readonly string[];\n trees?: readonly string[];\n moved?: { from: string; to: string };\n content?: true;\n outside?: true;\n }) => void\n ): () => void;\n refresh?(trees: readonly string[]): void;\n peers?(): Peers | undefined;\n crossings?(mounted: (path: string) => boolean): void;\n ancestry?(path: string): Promise<Array<Perm | undefined>>;\n hasOwner?(path: string): Promise<boolean>;\n chmod(path: string, mode: number): Promise<void>;\n append?(path: string, bytes: Uint8Array, options?: PwriteOptions): Promise<number>;\n utimes(path: string, atime: Date, mtime: Date): Promise<void>;\n lutimes?(path: string, atime: Date, mtime: Date): Promise<void>;\n pread?(path: string, offset: number, length: number, version?: string): Promise<Uint8Array>;\n pwrite?(\n path: string,\n offset: number,\n bytes: Uint8Array,\n transfer?: boolean,\n options?: PwriteOptions\n ): Promise<void>;\n truncate?(path: string, size: number): Promise<void>;\n protect?(prefixes: readonly string[], versions?: boolean): void;\n unguarded?(): KernelFs;\n noLinks?(): KernelFs;\n mayChange?(path: string, follow: boolean, whole?: boolean): Promise<void>;\n commandTarget?(path: string): Promise<string | undefined>;\n readVersioned?(path: string, cached?: boolean): Promise<{ bytes: Uint8Array; version: string }>;\n version?(path: string, cached?: boolean): Promise<string>;\n opfsCalls?(): number;\n renameWaits?(): {\n acks: number;\n busy: number;\n waits: number;\n queries: number;\n ackMs: readonly number[];\n };\n opfsOps?(): number;\n metaTransactions?(): { reads: number; writes: number } | undefined;\n fileIdWrites?(): number;\n announceHolds?(\n add: ReadonlyArray<[string, string | undefined]>,\n drop: readonly string[],\n wait: boolean\n ): Promise<void>;\n holdCounts?(): { mine: number; peers: number; sent: number; held: string[] } | undefined;\n peerHolds?(listener: (paths: string[]) => void): void;\n rehold?(from: string, to: string): void;\n peerKeeps?(): PeerKeeps | undefined;\n servePeerKeeps?(\n instance: string,\n handlers: {\n keeping(tab: string, paths: readonly string[]): Promise<void>;\n kept(\n tab: string,\n items: ReadonlyArray<{\n path: string;\n hidden: string | undefined;\n fid: string | undefined;\n }>,\n paths: readonly string[]\n ): Promise<void>;\n left(tab: string): void;\n }\n ): void;\n}\n\nexport interface PeerKeeps {\n shared(): boolean;\n heldWithin(\n path: string\n ): Array<{ tab: string; path: string; fid: string | undefined; instance: string | undefined }>;\n ask(\n to: string,\n body: {\n keeping?: { paths: string[] };\n kept?: {\n items: Array<{\n path: string;\n hidden: string | undefined;\n fid: string | undefined;\n }>;\n paths?: string[];\n };\n },\n cap: number\n ): Promise<boolean>;\n}\n\nexport interface PwriteOptions {\n create?: false;\n alone?: true;\n}\n\nexport type RangedOps = Required<Pick<KernelFs, 'pread' | 'pwrite' | 'truncate'>>;\n\nexport function rangedOps(fs: Partial<RangedOps>): RangedOps | undefined {\n const { pread, pwrite, truncate } = fs;\n if (!pread || !pwrite || !truncate) return undefined;\n return { pread: pread.bind(fs), pwrite: pwrite.bind(fs), truncate: truncate.bind(fs) };\n}\n\nexport async function lutimesOf(\n fs: KernelFs,\n path: string,\n atime: Date,\n mtime: Date\n): Promise<void> {\n if (fs.lutimes) return fs.lutimes(path, atime, mtime);\n if ((await fs.lstat(path)).isSymbolicLink) throw fsError('EOPNOTSUPP', path);\n return fs.utimes(path, atime, mtime);\n}\n\nexport function mayLink(fs: { links?(path: string): boolean }, path: string): boolean {\n return fs.links?.(path) ?? true;\n}\n\nexport function modeOption(mode: unknown): number {\n if (!Number.isInteger(mode) || (mode as number) < 0 || (mode as number) > 0o7777) {\n throw fsError('EINVAL', `not a mode: ${String(mode)}`);\n }\n return mode as number;\n}\n\nexport function fsError(code: string, path: string): Error & { code: string } {\n return Object.assign(new Error(`${code}: ${path}`), { code });\n}\n\nexport function normalizePath(path: string): string {\n const parts: string[] = [];\n for (const part of path.split('/')) {\n if (part === '' || part === '.') continue;\n if (part === '..') parts.pop();\n else parts.push(part);\n }\n return `/${parts.join('/')}`;\n}\n\nexport function resolvePath(base: string, path: string): string {\n return normalizePath(path.startsWith('/') ? path : `${base}/${path}`);\n}\n\nexport function inodeOf(path: string): number {\n let h1 = 0xdeadbeef;\n let h2 = 0x41c6ce57;\n for (let i = 0; i < path.length; i++) {\n const c = path.charCodeAt(i);\n h1 = Math.imul(h1 ^ c, 2654435761);\n h2 = Math.imul(h2 ^ c, 1597334677);\n }\n h1 = Math.imul(h1 ^ (h1 >>> 16), 2246822507) ^ Math.imul(h2 ^ (h2 >>> 13), 3266489909);\n h2 = Math.imul(h2 ^ (h2 >>> 16), 2246822507) ^ Math.imul(h1 ^ (h1 >>> 13), 3266489909);\n return 4294967296 * (2097151 & h2) + (h1 >>> 0) || 1;\n}\n\nexport interface Redirect {\n of: string;\n to: string;\n}\n\nexport function redirected(of: string, to: string): Error {\n return Object.assign(fsError('EXDEV', `${of} leads to the mount at ${to}`), {\n redirect: { of: normalizePath(of), to: normalizePath(to) },\n });\n}\n\nexport function redirectOf(err: unknown): Redirect | undefined {\n return (err as { redirect?: Redirect } | null)?.redirect;\n}\n", "import { type IntegrityOptions, integritySources, integrityUnknown } from './integrity.ts';\nimport {\n type FsStat,\n fsError,\n type HeldEntry,\n type KernelFs,\n normalizePath,\n type PwriteOptions,\n} from './types.ts';\n\nexport interface Protection {\n readonly paths: readonly string[];\n readonly writers?: readonly string[];\n readonly integrity?: IntegrityOptions;\n}\n\nexport interface ProtectInit {\n paths: string[];\n writers?: string[];\n integrity?: { unknown: 'allow' | 'deny'; sources?: readonly string[] };\n}\n\nexport function protectInit(protection: ProtectInit | Protection): ProtectInit {\n const writers = [...writerTags(protection as Protection)];\n const { integrity } = protection;\n return {\n paths: [...protection.paths],\n ...(writers.length > 0 ? { writers } : {}),\n ...(integrity ? { integrity: integrityInit(integrity) } : {}),\n };\n}\n\nfunction integrityInit(integrity: {\n unknown?: string;\n sources?: readonly string[];\n}): NonNullable<ProtectInit['integrity']> {\n const unknown = integrityUnknown(integrity);\n return integrity.sources === undefined\n ? { unknown }\n : { unknown, sources: integritySources(integrity) };\n}\n\nexport function writerTags(protection: Protection | undefined): ReadonlySet<string> {\n const writers = protection?.writers ?? [];\n if (!Array.isArray(writers) || writers.some((tag) => typeof tag !== 'string' || tag === '')) {\n throw new TypeError('protect.writers must be a list of process tags');\n }\n return new Set(writers);\n}\n\nexport function protectedPrefixes(paths: readonly string[]): string[] {\n if (!Array.isArray(paths) || paths.some((p) => typeof p !== 'string' || !p.startsWith('/'))) {\n throw new TypeError('protect.paths must be a list of absolute paths');\n }\n return [...new Set(paths.map((p) => normalizePath(p)))];\n}\n\nfunction within(path: string, prefix: string): boolean {\n return prefix === '/' || path === prefix || path.startsWith(`${prefix}/`);\n}\n\nexport function isProtected(prefixes: readonly string[], path: string): boolean {\n return prefixes.some((prefix) => within(path, prefix));\n}\n\nexport function holdsProtected(prefixes: readonly string[], path: string): boolean {\n return prefixes.some((prefix) => within(prefix, path));\n}\n\nconst MAX_LINKS = 40;\n\nfunction partsOf(path: string): string[] {\n return path.split('/').filter((p) => p !== '' && p !== '.');\n}\n\nfunction missing(err: unknown): boolean {\n const code = (err as { code?: unknown } | null)?.code;\n return code === 'ENOENT' || code === 'ENOTDIR';\n}\n\nasync function resolved(\n fs: KernelFs,\n path: string,\n follow: boolean,\n hops: string[] = []\n): Promise<string> {\n let done: string[] = [];\n let todo = partsOf(path);\n for (let links = 0; todo.length > 0; ) {\n const part = todo.shift() as string;\n if (part === '..') {\n done.pop();\n continue;\n }\n if (todo.length === 0 && !follow) {\n done.push(part);\n break;\n }\n const at = `/${[...done, part].join('/')}`;\n const st = await fs.lstat(at).catch((err: unknown) => {\n if (missing(err)) return undefined;\n throw err;\n });\n if (!st) {\n return normalizePath([...done, part, ...todo].join('/'));\n }\n if (!st.isSymbolicLink) {\n done.push(part);\n continue;\n }\n if (++links > MAX_LINKS) throw fsError('ELOOP', path);\n hops.push(normalizePath([at, ...todo].join('/')));\n const link = await fs.readlink(at);\n if (link.startsWith('/')) done = [];\n todo = [...partsOf(link), ...todo];\n }\n return `/${done.join('/')}`;\n}\n\nexport async function namesOf(fs: KernelFs, path: string): Promise<string[]> {\n const lexical = normalizePath(path);\n const hops: string[] = [];\n await resolved(fs, lexical, true, hops).catch(() => undefined);\n return [lexical, ...hops];\n}\n\nexport class ProtectedFs {\n private readonly prefixes: readonly string[];\n\n constructor(prefixes: readonly string[]) {\n this.prefixes = prefixes;\n }\n\n async check(fs: KernelFs, path: string, follow: boolean, whole = false): Promise<void> {\n const lexical = normalizePath(path);\n const real = await resolved(fs, lexical, follow);\n for (const p of new Set([lexical, real])) {\n if (isProtected(this.prefixes, p) || (whole && holdsProtected(this.prefixes, p))) {\n throw fsError('EROFS', path);\n }\n }\n }\n\n view(fs: KernelFs): KernelFs {\n const check = (path: string, follow: boolean, whole = false) =>\n this.check(fs, path, follow, whole);\n const marked = (path: string, st: FsStat): FsStat =>\n !st.readonly && isProtected(this.prefixes, normalizePath(path))\n ? { ...st, readonly: true }\n : st;\n const own: Partial<KernelFs> = {\n async writeFile(...args: Parameters<KernelFs['writeFile']>) {\n await check(args[0], true);\n return fs.writeFile(...args);\n },\n async mkdir(...args: Parameters<KernelFs['mkdir']>) {\n await check(args[0], false);\n return fs.mkdir(...args);\n },\n async rm(...args: Parameters<KernelFs['rm']>) {\n await check(args[0], false, true);\n return fs.rm(...args);\n },\n async rename(from: string, to: string) {\n await check(from, false, true);\n await check(to, false, true);\n return fs.rename(from, to);\n },\n async link(from: string, to: string, follow?: boolean) {\n await check(from, follow === true);\n await check(to, false);\n return fs.link(from, to, follow);\n },\n async symlink(...args: Parameters<KernelFs['symlink']>) {\n await check(args[1], false);\n return fs.symlink(...args);\n },\n async chmod(path: string, mode: number) {\n await check(path, true);\n return fs.chmod(path, mode);\n },\n async utimes(path: string, atime: Date, mtime: Date) {\n await check(path, true);\n return fs.utimes(path, atime, mtime);\n },\n async mayChange(path: string, follow: boolean, whole = false) {\n await check(path, follow, whole);\n },\n async stat(path: string) {\n return marked(path, await fs.stat(path));\n },\n async lstat(path: string) {\n return marked(path, await fs.lstat(path));\n },\n async readdirStat(path: string) {\n const dir = normalizePath(path);\n return (await fs.readdirStat(path)).map(([name, st]): [string, FsStat | null] => [\n name,\n st && marked(`${dir}/${name}`, st),\n ]);\n },\n ...(fs.copyFile\n ? {\n async copyFile(...args: Parameters<NonNullable<KernelFs['copyFile']>>) {\n await check(args[1], false);\n return fs.copyFile?.(...args);\n },\n }\n : {}),\n ...(fs.createExclusive\n ? {\n async createExclusive(...args: Parameters<NonNullable<KernelFs['createExclusive']>>) {\n await check(args[0], true);\n return fs.createExclusive?.(...args);\n },\n }\n : {}),\n ...(fs.chown\n ? {\n async chown(...args: Parameters<NonNullable<KernelFs['chown']>>) {\n await check(args[0], args[1].follow !== false);\n return fs.chown?.(...args);\n },\n }\n : {}),\n ...(fs.lutimes\n ? {\n async lutimes(path: string, atime: Date, mtime: Date) {\n await check(path, false);\n return fs.lutimes?.(path, atime, mtime);\n },\n }\n : {}),\n ...(fs.pwrite\n ? {\n async pwrite(...args: Parameters<NonNullable<KernelFs['pwrite']>>) {\n await check(args[0], true);\n return fs.pwrite?.(...args);\n },\n }\n : {}),\n ...(fs.append\n ? {\n async append(path: string, bytes: Uint8Array, options?: PwriteOptions) {\n await check(path, true);\n return (fs.append as NonNullable<KernelFs['append']>).call(fs, path, bytes, options);\n },\n }\n : {}),\n ...(fs.truncate\n ? {\n async truncate(path: string, size: number) {\n await check(path, true);\n return fs.truncate?.(path, size);\n },\n }\n : {}),\n ...(fs.exclusive\n ? {\n async exclusive<T>(\n path: string,\n run: (held: HeldEntry) => Promise<T>,\n follow?: boolean\n ): Promise<T> {\n return (fs.exclusive as NonNullable<KernelFs['exclusive']>)(\n path,\n (held) =>\n run({\n ...held,\n writeFile: async (...args: Parameters<KernelFs['writeFile']>) => {\n await check(args[0], true);\n return held.writeFile(...args);\n },\n }),\n follow\n );\n },\n }\n : {}),\n };\n const view: Record<string, unknown> = {};\n for (\n let at: object | null = fs;\n at && at !== Object.prototype;\n at = Object.getPrototypeOf(at)\n ) {\n for (const name of Object.getOwnPropertyNames(at)) {\n if (name === 'constructor' || Object.hasOwn(view, name)) continue;\n const value = (fs as unknown as Record<string, unknown>)[name];\n view[name] = typeof value === 'function' ? value.bind(fs) : value;\n }\n }\n return Object.assign(view, own) as unknown as KernelFs;\n }\n}\n", "import type { DenialHook } from './dac.ts';\nimport { isProtected, namesOf } from './protect.ts';\nimport { fsError, type KernelFs, normalizePath } from './types.ts';\n\nexport type IntegrityLookup = (path: string) => string | undefined | Promise<string | undefined>;\n\nexport interface IntegrityOptions {\n readonly lookup: IntegrityLookup;\n readonly unknown?: 'allow' | 'deny';\n readonly sources?: readonly string[];\n}\n\nexport const SOURCE_SUFFIXES: readonly string[] = [\n '.js',\n '.mjs',\n '.cjs',\n '.json',\n '.py',\n '.pyc',\n '.pth',\n '.zip',\n '.so',\n '.wasm',\n '.sh',\n];\n\nconst EXEC_OPS = { failed: 'exec-integrity', unknown: 'exec-unverified' } as const;\nconst READ_OPS = { failed: 'read-integrity', unknown: 'read-unverified' } as const;\n\ntype Ops = typeof EXEC_OPS | typeof READ_OPS;\n\nexport interface IntegrityCaller {\n pid: number;\n uid: number;\n tag?: string | undefined;\n}\n\ninterface Checked {\n real: string;\n name: string;\n}\n\nexport const KERNEL_CALLER: IntegrityCaller = { pid: 0, uid: 0 };\n\nexport function integrityOptions(options: IntegrityOptions | undefined): void {\n if (options && typeof options.lookup !== 'function') {\n throw new TypeError('protect.integrity.lookup must be a function');\n }\n integrityUnknown(options);\n integritySources(options);\n}\n\nexport function integritySources(options: { sources?: unknown } | undefined): readonly string[] {\n const sources = options?.sources ?? SOURCE_SUFFIXES;\n const suffix = (s: unknown) => typeof s === 'string' && /^\\.[^/]+$/.test(s);\n if (!Array.isArray(sources) || !sources.every(suffix)) {\n throw new TypeError('protect.integrity.sources must be a list of suffixes such as .js');\n }\n return [...sources];\n}\n\nexport function integrityUnknown(options: { unknown?: string } | undefined): 'allow' | 'deny' {\n const unknown = options?.unknown ?? 'allow';\n if (unknown !== 'allow' && unknown !== 'deny') {\n throw new TypeError(\"protect.integrity.unknown must be 'allow' or 'deny'\");\n }\n return unknown;\n}\n\nfunction hex(digest: ArrayBuffer): string {\n return [...new Uint8Array(digest)].map((b) => b.toString(16).padStart(2, '0')).join('');\n}\n\nexport async function sha256(bytes: Uint8Array): Promise<string> {\n return hex(await crypto.subtle.digest('SHA-256', bytes as BufferSource));\n}\n\nexport class Integrity {\n private readonly prefixes: readonly string[];\n private readonly root: KernelFs;\n private readonly lookup: IntegrityLookup;\n private readonly unknown: 'allow' | 'deny';\n private readonly report: DenialHook;\n private readonly unverified = new Set<string>();\n private readonly unread = new Set<string>();\n private readonly sources: readonly string[];\n private readonly passed = new Set<string>();\n private generation = 0;\n\n constructor(\n prefixes: readonly string[],\n root: KernelFs,\n options: IntegrityOptions,\n report: DenialHook\n ) {\n this.prefixes = prefixes;\n this.root = root;\n this.lookup = options.lookup;\n this.unknown = integrityUnknown(options);\n this.sources = integritySources(options);\n this.report = report;\n }\n\n private async real(path: string, asked?: string, known?: string): Promise<Checked | undefined> {\n const at = normalizePath(path);\n const real = known ?? (await this.root.realpath?.(at, true).catch(() => undefined)) ?? at;\n if (isProtected(this.prefixes, real)) return { real, name: real };\n const names = asked === undefined ? [] : await namesOf(this.root, asked);\n if (real !== at) names.push(...(await namesOf(this.root, at)));\n const name = names.findLast((p) => isProtected(this.prefixes, p));\n return name === undefined ? undefined : { real, name };\n }\n\n async key(path: string, asked?: string): Promise<string | undefined> {\n const found = await this.real(path, asked);\n if (found === undefined) return undefined;\n const { real, name } = found;\n if (name !== real) return `${name}\\0${real}\\0`;\n if (!this.root.version) return undefined;\n return `${real}\\0${await this.root.version(real)}`;\n }\n\n async read(\n path: string,\n caller: IntegrityCaller,\n plain: () => Promise<Uint8Array>,\n asked?: string\n ): Promise<Uint8Array> {\n return (await this.readKeyed(path, caller, plain, asked)).bytes;\n }\n\n async readKeyed(\n path: string,\n caller: IntegrityCaller,\n plain: () => Promise<Uint8Array>,\n asked?: string\n ): Promise<{ bytes: Uint8Array; key?: string }> {\n const found = await this.real(path, asked);\n if (found === undefined) return { bytes: await plain() };\n const { real, name } = found;\n const read =\n name !== real\n ? { bytes: await plain(), version: undefined }\n : this.root.readVersioned\n ? await this.root.readVersioned(real)\n : { bytes: await this.root.readFileBuffer(real), version: undefined };\n const { bytes } = read;\n const keyed =\n read.version === undefined ? { bytes } : { bytes, key: `${real}\\0${read.version}` };\n await this.verify(name, bytes, caller, EXEC_OPS);\n return keyed;\n }\n\n get readsChecked(): boolean {\n return this.sources.length > 0;\n }\n\n async readSource(\n path: string,\n caller: IntegrityCaller,\n plain: () => Promise<Uint8Array>\n ): Promise<Uint8Array> {\n const found = await this.source(path);\n return found === undefined ? plain() : this.checked(found, caller, plain);\n }\n\n async openSource(path: string, caller: IntegrityCaller, real?: string): Promise<void> {\n const found = await this.source(path, real);\n if (found === undefined) return;\n if (found.name === found.real && this.root.version) {\n if (this.passed.has(`${found.real}\\0${await this.root.version(found.real, true)}`)) return;\n }\n await this.checked(found, caller, () => this.root.readFileBuffer(found.real));\n }\n\n private async checked(\n found: Checked,\n caller: IntegrityCaller,\n plain: () => Promise<Uint8Array>\n ): Promise<Uint8Array> {\n const { real, name } = found;\n if (name !== real || !this.root.readVersioned) {\n const bytes = await plain();\n await this.verify(name, bytes, caller, READ_OPS);\n return bytes;\n }\n const { bytes, version } = await this.root.readVersioned(real, true);\n await this.pass(`${real}\\0${version}`, () => this.verify(name, bytes, caller, READ_OPS));\n return bytes;\n }\n\n private async pass(key: string, check: () => Promise<void>): Promise<void> {\n if (this.passed.has(key)) return;\n const generation = this.generation;\n await check();\n if (generation === this.generation) this.passed.add(key);\n }\n\n private async source(path: string, known?: string): Promise<Checked | undefined> {\n if (this.sources.length === 0) return undefined;\n const found = await this.real(path, undefined, known);\n if (found === undefined) return undefined;\n const suffixed = (p: string) => this.sources.some((s) => p.endsWith(s));\n if (suffixed(found.real) || suffixed(found.name) || suffixed(normalizePath(path))) return found;\n const st = await this.root.stat(found.real).catch(() => undefined);\n return st?.isFile && ((st.mode ?? 0) & 0o111) !== 0 ? found : undefined;\n }\n\n private async verify(\n name: string,\n bytes: Uint8Array,\n caller: IntegrityCaller,\n ops: Ops\n ): Promise<void> {\n const actual = await sha256(bytes);\n const denial = { pid: caller.pid, uid: caller.uid, path: name, actual };\n const tagged = caller.tag !== undefined ? { tag: caller.tag } : {};\n let expected: string | undefined;\n try {\n expected = await this.expected(name);\n } catch {\n this.say({ ...denial, ...tagged, op: ops.failed, errno: 'EACCES' });\n throw fsError('EACCES', `integrity lookup failed: ${name}`);\n }\n if (expected === actual) return;\n if (expected === undefined && this.unknown === 'allow') {\n const seen = ops === EXEC_OPS ? this.unverified : this.unread;\n if (!seen.has(name)) {\n seen.add(name);\n this.say({ ...denial, ...tagged, op: ops.unknown, errno: 'ENODATA' });\n }\n return;\n }\n const known = expected !== undefined ? { expected } : {};\n this.say({ ...denial, ...tagged, ...known, op: ops.failed, errno: 'EACCES' });\n throw fsError('EACCES', `integrity check failed: ${name}`);\n }\n\n forget(path?: string): void {\n this.generation++;\n for (const seen of [this.unverified, this.unread]) {\n for (const name of [...seen]) {\n if (path === undefined || isProtected([path], name)) seen.delete(name);\n }\n }\n for (const key of [...this.passed]) {\n if (path === undefined || isProtected([path], key.slice(0, key.indexOf('\\0')))) {\n this.passed.delete(key);\n }\n }\n }\n\n private async expected(path: string): Promise<string | undefined> {\n const answer = await this.lookup(path);\n return typeof answer === 'string' ? answer.toLowerCase() : undefined;\n }\n\n private say(event: Parameters<DenialHook>[0]): void {\n try {\n this.report(event);\n } catch {}\n }\n}\n", "export type Portable<T extends FileSystemHandle> = { handle: T } | { path: string[] };\n\ntype Top = () => Promise<FileSystemDirectoryHandle>;\n\nconst privateTop: Top = () => navigator.storage.getDirectory();\n\nexport function clonable(handle: FileSystemHandle): boolean {\n const { port1, port2 } = new MessageChannel();\n try {\n port1.postMessage(handle);\n return true;\n } catch (err) {\n if ((err as { name?: unknown } | null)?.name === 'DataCloneError') return false;\n throw err;\n } finally {\n port1.close();\n port2.close();\n }\n}\n\nexport async function portable<T extends FileSystemHandle>(\n handle: T,\n top: Top = privateTop\n): Promise<Portable<T>> {\n if (clonable(handle)) return { handle };\n const path = await (await top()).resolve(handle);\n if (path === null) {\n throw new Error(\n 'this browser cannot hand a folder to a worker unless it is in the origin private file system'\n );\n }\n return { path };\n}\n\nexport async function directoryAt(\n top: FileSystemDirectoryHandle,\n path: readonly string[]\n): Promise<FileSystemDirectoryHandle> {\n let dir = top;\n for (const name of path) dir = await dir.getDirectoryHandle(name);\n return dir;\n}\n\nexport const samePath = (a: readonly string[], b: readonly string[]): boolean =>\n a.length === b.length && a.every((name, at) => name === b[at]);\n", "import type { IntegrityLookup } from './fs/integrity.ts';\n\nexport interface IntegrityPort {\n postMessage(message: unknown): void;\n}\n\nexport interface IntegrityAsk {\n id: number;\n path: string;\n}\n\nexport interface IntegrityReply {\n id: number;\n hash?: string;\n error?: string;\n}\n\nexport function integrityAsker(port: IntegrityPort): {\n lookup: IntegrityLookup;\n answer(reply: IntegrityReply): void;\n} {\n const asks = new Map<number, PromiseWithResolvers<string | undefined>>();\n let next = 0;\n const lookup: IntegrityLookup = (path) => {\n const id = ++next;\n const waiting = Promise.withResolvers<string | undefined>();\n asks.set(id, waiting);\n port.postMessage({ integrityAsk: { id, path } });\n return waiting.promise;\n };\n const answer = ({ id, hash, error }: IntegrityReply) => {\n const waiting = asks.get(id);\n if (!waiting) return;\n asks.delete(id);\n if (error !== undefined) waiting.reject(new Error(error));\n else waiting.resolve(hash);\n };\n return { lookup, answer };\n}\n\nexport function integrityAnswerer(\n port: IntegrityPort,\n lookup: IntegrityLookup | undefined\n): (data: unknown) => boolean {\n const ask = async ({ id, path }: IntegrityAsk): Promise<void> => {\n try {\n const hash = lookup ? await lookup(path) : undefined;\n port.postMessage({ integrityReply: { id, ...(typeof hash === 'string' ? { hash } : {}) } });\n } catch (err) {\n const error = err instanceof Error ? err.message : String(err);\n port.postMessage({ integrityReply: { id, error } });\n }\n };\n return (data) => {\n const asked = (data as { integrityAsk?: IntegrityAsk } | null)?.integrityAsk;\n if (!asked) return false;\n void ask(asked);\n return true;\n };\n}\n", "import type { UsersMode } from '../fs/types.ts';\nimport { KernelError, type OpenAccess, OpenFile, type PollState } from './fd-table.ts';\n\nexport const EMBEDDER_PATH = '/dev/embedder';\nexport const EMBEDDER_MINOR = 252;\nexport const EMBEDDER_HEADER_MAX = 64 * 1024;\nexport const EMBEDDER_WINDOW = 1024 * 1024;\nexport const EMBEDDER_BUDGET = 256 * 1024 * 1024;\nexport const EMBEDDER_PER_PROCESS = 16;\nexport const EMBEDDER_PROGRESS_PER_SECOND = 4;\n\nconst KIND = /^[a-z][a-z0-9-]*(\\.[a-z0-9-]+)*$/;\nconst NL = 10;\n\nexport interface EmbedderStamp {\n pid: number;\n uid: number;\n gid: number;\n groups: number[];\n users: UsersMode;\n kind: string;\n tag?: string;\n tags?: string[];\n}\n\nexport interface EmbedderKindPolicy {\n group?: string;\n users?: Array<string | number>;\n}\n\nexport type EmbedderReply = ReadableStream<Uint8Array> | Uint8Array | string | undefined | void;\n\nexport interface EmbedderRequest {\n kind: string;\n options: Record<string, unknown>;\n body: ReadableStream<Uint8Array>;\n stamp: EmbedderStamp;\n signal: AbortSignal;\n progress(line: string): void;\n}\n\nexport interface EmbedderHook {\n kinds: Readonly<Record<string, EmbedderKindPolicy>>;\n handle(request: EmbedderRequest): Promise<EmbedderReply>;\n}\n\nexport interface EmbedderCaller {\n pid: number;\n shownPid: number;\n euid: number;\n egid: number;\n groups: number[];\n sessionUid: number;\n client: number;\n tags: readonly string[] | undefined;\n name: string;\n progress(line: string): boolean;\n closing(): AbortSignal;\n}\n\nexport interface EmbedderLookup {\n groupId(name: string): Promise<number | undefined>;\n userId(name: string): Promise<number | undefined>;\n}\n\nconst READY: PollState = { readable: true, writable: true, hangup: false };\n\nfunction lineOf(err: unknown): string {\n const text = err instanceof Error ? err.message : String(err);\n return (text.split('\\n')[0] ?? '').slice(0, 200);\n}\n\nconst ERRNOS: Readonly<Record<string, 'EACCES' | 'ENOTSUP' | 'ENOENT'>> = {\n NotAllowedError: 'EACCES',\n AbortError: 'EACCES',\n NotSupportedError: 'ENOTSUP',\n NotFoundError: 'ENOENT',\n};\n\nexport function embedderFailure(err: unknown): KernelError {\n if (err instanceof KernelError) return err;\n const name = (err as { name?: unknown } | null)?.name;\n return new KernelError(ERRNOS[String(name)] ?? 'EIO', lineOf(err));\n}\n\nfunction headerOf(bytes: Uint8Array): { kind: string; options: Record<string, unknown> } {\n let parsed: unknown;\n try {\n parsed = JSON.parse(new TextDecoder('utf-8', { fatal: true }).decode(bytes));\n } catch {\n throw new KernelError('EINVAL', 'the request header is not JSON');\n }\n if (typeof parsed !== 'object' || parsed === null || Array.isArray(parsed))\n throw new KernelError('EINVAL', 'the request header is not an object');\n const { kind, ...options } = parsed as Record<string, unknown>;\n if (typeof kind !== 'string' || kind.length > 64 || !KIND.test(kind))\n throw new KernelError('EINVAL', 'the request has no valid kind');\n return { kind, options };\n}\n\nfunction joined(a: Uint8Array, b: Uint8Array): Uint8Array {\n const out = new Uint8Array(a.length + b.length);\n out.set(a);\n out.set(b, a.length);\n return out;\n}\n\nfunction aborted(signal: AbortSignal | undefined): Promise<never> | undefined {\n if (!signal) return undefined;\n return new Promise<never>((_, reject) => {\n const stop = () => reject(new KernelError('EINTR'));\n if (signal.aborted) stop();\n else signal.addEventListener('abort', stop, { once: true });\n });\n}\n\nasync function interruptible<T>(work: Promise<T>, signal: AbortSignal | undefined): Promise<T> {\n const stop = aborted(signal);\n if (!stop) return work;\n stop.catch(() => undefined);\n return Promise.race([work, stop]);\n}\n\nclass Budget {\n private used = 0;\n readonly limit: number;\n constructor(limit: number) {\n this.limit = limit;\n }\n take(n: number): boolean {\n if (this.used + n > this.limit) return false;\n this.used += n;\n return true;\n }\n give(n: number): void {\n this.used = Math.max(0, this.used - n);\n }\n}\n\nclass BodyPipe {\n private queue: Uint8Array[] = [];\n private size = 0;\n private ended = false;\n private dropped = false;\n private wake: (() => void) | undefined;\n private room: (() => void) | undefined;\n readonly stream: ReadableStream<Uint8Array>;\n constructor() {\n this.stream = new ReadableStream<Uint8Array>(\n {\n pull: async (controller) => {\n while (this.queue.length === 0 && !this.ended) {\n await new Promise<void>((resolve) => {\n this.wake = resolve;\n });\n }\n const next = this.queue.shift();\n if (next) {\n this.size -= next.length;\n this.room?.();\n controller.enqueue(next);\n } else controller.close();\n },\n cancel: () => this.drop(),\n },\n { highWaterMark: 0 }\n );\n }\n get full(): boolean {\n return this.size >= EMBEDDER_WINDOW;\n }\n drop(): void {\n this.dropped = true;\n this.queue = [];\n this.size = 0;\n this.end();\n }\n push(bytes: Uint8Array): void {\n if (bytes.length === 0 || this.dropped) return;\n this.queue.push(bytes.slice());\n this.size += bytes.length;\n this.wake?.();\n }\n waitRoom(): Promise<void> {\n return new Promise<void>((resolve) => {\n this.room = resolve;\n });\n }\n end(): void {\n this.ended = true;\n this.wake?.();\n this.room?.();\n }\n}\n\nfunction endsWith(\n stream: ReadableStream<Uint8Array>,\n ended: () => void\n): ReadableStream<Uint8Array> {\n const reader = stream.getReader();\n return new ReadableStream<Uint8Array>(\n {\n pull: async (controller) => {\n let got: ReadableStreamReadResult<Uint8Array>;\n try {\n got = await reader.read();\n } catch (err) {\n ended();\n throw err;\n }\n if (!got.done) return controller.enqueue(got.value);\n ended();\n controller.close();\n },\n cancel: (reason) => {\n ended();\n return reader.cancel(reason);\n },\n },\n { highWaterMark: 0 }\n );\n}\n\nfunction replyStream(reply: EmbedderReply): ReadableStream<Uint8Array> {\n if (reply instanceof ReadableStream) return reply;\n const bytes =\n typeof reply === 'string'\n ? new TextEncoder().encode(reply)\n : reply instanceof Uint8Array\n ? reply\n : new Uint8Array(0);\n return new ReadableStream({\n start(controller) {\n if (bytes.length > 0) controller.enqueue(bytes);\n controller.close();\n },\n });\n}\n\nconst HELD_MAX = 16;\n\nclass Throttle {\n private window = 0;\n private count = 0;\n allow(now: number): boolean {\n if (now - this.window >= 1000) {\n this.window = now;\n this.count = 0;\n }\n this.count += 1;\n return this.count <= EMBEDDER_PROGRESS_PER_SECOND;\n }\n}\n\nexport class EmbedderChannel {\n readonly access: OpenAccess;\n readonly owner: number;\n private current: EmbedderCaller;\n private held: string[] = [];\n private readonly broker: EmbedderBroker;\n private header: Uint8Array = new Uint8Array(0);\n private body: BodyPipe | undefined;\n private reply: ReadableStreamDefaultReader<Uint8Array> | undefined;\n private replied: Promise<ReadableStreamDefaultReader<Uint8Array>> | undefined;\n private rest: Uint8Array | undefined;\n private done = false;\n private failure: KernelError | undefined;\n private reported = false;\n private readonly abort = new AbortController();\n private closed = false;\n private readonly throttle = new Throttle();\n\n constructor(broker: EmbedderBroker, access: OpenAccess, caller: EmbedderCaller) {\n this.broker = broker;\n this.access = access;\n this.current = caller;\n this.owner = caller.pid;\n }\n\n get dispatched(): boolean {\n return this.body !== undefined;\n }\n\n get caller(): EmbedderCaller {\n return this.current;\n }\n\n set caller(caller: EmbedderCaller) {\n this.current = caller;\n const held = this.held;\n this.held = [];\n for (const line of held) this.tell(line);\n }\n\n private tell(line: string): void {\n if (!this.current.progress(line) && this.held.length < HELD_MAX) this.held.push(line);\n }\n\n private fail(err: unknown): KernelError {\n this.failure ??= embedderFailure(err);\n return this.failure;\n }\n\n private report(err: unknown): KernelError {\n this.reported = true;\n return this.fail(err);\n }\n\n private async dispatch(bytes: Uint8Array): Promise<void> {\n const { kind, options } = headerOf(bytes);\n const stamp = await this.broker.admit(kind, this.caller);\n const hook = this.broker.hookFor(this.caller.client) as EmbedderHook;\n const body = new BodyPipe();\n this.body = body;\n const prefix = this.caller.name;\n const progress = (line: string) => {\n if (this.throttle.allow(Date.now())) this.tell(`${prefix}: ${lineOf(line)}`);\n };\n const asked = Promise.resolve()\n .then(() =>\n hook.handle({\n kind,\n options,\n body: body.stream,\n stamp,\n signal: this.abort.signal,\n progress,\n })\n )\n .then((reply) => {\n if (!(reply instanceof ReadableStream)) body.drop();\n return endsWith(replyStream(reply), () => body.drop()).getReader();\n });\n this.replied = asked.catch((err: unknown) => {\n body.end();\n throw this.fail(err);\n });\n this.replied.catch(() => undefined);\n }\n\n async write(bytes: Uint8Array, signal?: AbortSignal): Promise<number> {\n if (this.access === 'read') throw new KernelError('EBADF');\n if (this.failure) throw this.report(this.failure);\n if (this.reply || this.done) throw new KernelError('EBADF');\n if (this.body) return this.writeBody(bytes, signal);\n const at = bytes.indexOf(NL);\n const head = at < 0 ? bytes : bytes.subarray(0, at);\n if (this.header.length + head.length > EMBEDDER_HEADER_MAX)\n throw this.report(new KernelError('EINVAL', 'the request header is too long'));\n this.header = joined(this.header, head);\n if (at < 0) return bytes.length;\n try {\n await this.dispatch(this.header);\n } catch (err) {\n throw this.report(err);\n }\n (this.body as BodyPipe | undefined)?.push(bytes.subarray(at + 1));\n return bytes.length;\n }\n\n private async writeBody(bytes: Uint8Array, signal?: AbortSignal): Promise<number> {\n const body = this.body as BodyPipe;\n while (body.full && !this.failure) {\n await interruptible(body.waitRoom(), signal).catch((err: unknown) => {\n this.cancel('interrupted');\n throw err;\n });\n }\n if (this.failure) throw this.report(this.failure);\n body.push(bytes);\n return bytes.length;\n }\n\n private async readerOf(signal?: AbortSignal): Promise<ReadableStreamDefaultReader<Uint8Array>> {\n if (this.reply) return this.reply;\n if (!this.body) {\n try {\n await this.dispatch(this.header);\n } catch (err) {\n throw this.fail(err);\n }\n }\n this.body?.end();\n this.reply = await interruptible(\n this.replied as Promise<ReadableStreamDefaultReader<Uint8Array>>,\n signal\n );\n return this.reply;\n }\n\n async read(max: number, signal?: AbortSignal): Promise<Uint8Array> {\n if (this.access === 'write') throw new KernelError('EBADF');\n if (this.failure) throw this.report(this.failure);\n if (this.done || max <= 0) return new Uint8Array(0);\n try {\n return await this.next(max, signal);\n } catch (err) {\n if (err instanceof KernelError && err.code === 'EINTR') {\n this.cancel('interrupted');\n throw err;\n }\n throw this.report(err);\n }\n }\n\n private async next(max: number, signal?: AbortSignal): Promise<Uint8Array> {\n const reader = await this.readerOf(signal);\n let chunk = this.rest;\n this.rest = undefined;\n if (!chunk) {\n const got = await interruptible(reader.read(), signal);\n if (got.done) {\n this.done = true;\n return new Uint8Array(0);\n }\n chunk = got.value;\n }\n if (chunk.length > max) this.rest = chunk.subarray(max);\n return chunk.subarray(0, max);\n }\n\n poll(): PollState {\n return this.body?.full ? { ...READY, writable: false } : READY;\n }\n\n cancel(reason: 'interrupted' | 'closed'): void {\n if (this.abort.signal.aborted) return;\n this.abort.abort(new DOMException(reason, 'AbortError'));\n this.body?.end();\n void this.reply?.cancel(reason).catch(() => undefined);\n }\n\n async close(): Promise<void> {\n if (this.closed) return;\n const signal = this.caller.closing();\n this.closed = true;\n try {\n if (this.access === 'read') return;\n if (this.failure) {\n if (this.reported) return;\n throw this.report(this.failure);\n }\n if (this.access === 'both' && this.dispatched) return;\n if (!this.dispatched && this.header.length === 0) return;\n await this.drain(signal);\n } finally {\n if (!this.done) this.cancel('closed');\n this.broker.release(this);\n }\n }\n\n private async drain(signal?: AbortSignal): Promise<void> {\n try {\n const reader = await this.readerOf(signal);\n for (;;) {\n const got = await interruptible(reader.read(), signal);\n if (got.done) break;\n }\n this.done = true;\n } catch (err) {\n if (err instanceof KernelError && err.code === 'EINTR') this.cancel('interrupted');\n throw this.fail(err);\n }\n }\n}\n\nexport class EmbedderBroker {\n readonly users: UsersMode;\n private readonly lookup: EmbedderLookup;\n private readonly hooks = new Map<number, EmbedderHook>();\n private readonly budget: Budget;\n private readonly open = new Map<number, Set<EmbedderChannel>>();\n\n readonly tagsOf: (pid: number) => readonly string[] | undefined;\n\n constructor(\n users: UsersMode,\n lookup: EmbedderLookup,\n tagsOf: (pid: number) => readonly string[] | undefined = () => undefined,\n budget = EMBEDDER_BUDGET\n ) {\n this.users = users;\n this.tagsOf = tagsOf;\n this.lookup = lookup;\n this.budget = new Budget(budget);\n }\n\n register(client: number, hook: EmbedderHook | undefined): () => void {\n if (!hook) return () => undefined;\n this.hooks.set(client, hook);\n return () => {\n if (this.hooks.get(client) === hook) this.hooks.delete(client);\n };\n }\n\n hookFor(client: number): EmbedderHook | undefined {\n return this.hooks.get(client);\n }\n\n private async allowed(policy: EmbedderKindPolicy, caller: EmbedderCaller): Promise<boolean> {\n if (caller.euid === 0 || caller.euid === caller.sessionUid) return true;\n if (policy.group !== undefined) {\n const gid = await this.lookup.groupId(policy.group);\n if (gid !== undefined && (caller.egid === gid || caller.groups.includes(gid))) return true;\n }\n for (const user of policy.users ?? []) {\n const uid = typeof user === 'number' ? user : await this.lookup.userId(user);\n if (uid === caller.euid) return true;\n }\n return false;\n }\n\n async admit(kind: string, caller: EmbedderCaller): Promise<EmbedderStamp> {\n const hook = this.hooks.get(caller.client);\n if (!hook) throw new KernelError('ENOTSUP', 'no page answers requests for this session');\n const policy = Object.hasOwn(hook.kinds, kind) ? hook.kinds[kind] : undefined;\n if (!policy) throw new KernelError('ENOTSUP', `this embedder does not answer ${kind}`);\n if (this.users !== 'off' && !(await this.allowed(policy, caller)))\n throw new KernelError('EACCES', `${kind} is not allowed for this user`);\n const tags = caller.tags;\n return {\n pid: caller.shownPid,\n uid: caller.euid,\n gid: caller.egid,\n groups: [...caller.groups],\n users: this.users,\n kind,\n ...(tags?.length ? { tag: tags[0] as string, tags: [...tags] } : {}),\n };\n }\n\n channel(access: OpenAccess, caller: EmbedderCaller): OpenFile {\n const mine = this.open.get(caller.pid) ?? new Set<EmbedderChannel>();\n if (mine.size >= EMBEDDER_PER_PROCESS)\n throw new KernelError('EMFILE', `at most ${EMBEDDER_PER_PROCESS} requests per process`);\n if (!this.budget.take(2 * EMBEDDER_WINDOW))\n throw new KernelError('EAGAIN', 'the embedder request budget is spent');\n const channel = new EmbedderChannel(this, access, caller);\n mine.add(channel);\n this.open.set(caller.pid, mine);\n return new OpenFile({\n read: channel.read.bind(channel),\n write: (bytes, signal) => channel.write(bytes, signal),\n poll: () => channel.poll(),\n close: () => channel.close(),\n embedder: channel,\n });\n }\n\n release(channel: EmbedderChannel): void {\n const mine = this.open.get(channel.owner);\n if (!mine?.delete(channel)) return;\n if (mine.size === 0) this.open.delete(channel.owner);\n this.budget.give(2 * EMBEDDER_WINDOW);\n }\n}\n\nexport function kindsOf(hook: EmbedderHook): Record<string, EmbedderKindPolicy> {\n if (typeof hook?.handle !== 'function' || typeof hook.kinds !== 'object' || !hook.kinds)\n throw new TypeError('requests needs kinds and handle');\n return Object.fromEntries(\n Object.entries(hook.kinds).map(([kind, policy]) => [\n kind,\n {\n ...(policy?.group !== undefined ? { group: String(policy.group) } : {}),\n ...(policy?.users ? { users: [...policy.users] } : {}),\n },\n ])\n );\n}\n", "export const HOST_LOOPBACK = 'host.slicc.internal';\n\nexport const HOST_LOOPBACK_ADDRESS = [10, 0, 2, 2] as const;\n\nexport const PAGE_LOOPBACK = 'kernel.localhost';\n\nexport const PAGE_LOOPBACK_URL = `http://{port}.${PAGE_LOOPBACK}`;\n\nexport function toHostLoopback(href: string): string {\n const url = new URL(href);\n if (url.hostname.replace(/\\.$/, '').toLowerCase() !== HOST_LOOPBACK) return href;\n url.hostname = '127.0.0.1';\n return url.href;\n}\n\nconst LOOPBACK_V4 = /^127\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}$/;\nconst LOOPBACK_V6 = new Set(['::1', '::', '0:0:0:0:0:0:0:1']);\nconst MAPPED_V4 = /^::ffff:7f[0-9a-f]{2}:[0-9a-f]{1,4}$/;\nconst KERNEL_PORT = /^(\\d{1,5})\\.kernel\\.localhost$/;\nconst SCHEMES: Readonly<Record<string, number>> = {\n 'http:': 80,\n 'ws:': 80,\n 'https:': 443,\n 'wss:': 443,\n};\n\nexport function isKernelLoopbackHost(hostname: string): boolean {\n const host = hostname\n .replace(/^\\[(.*)\\]$/, '$1')\n .replace(/\\.$/, '')\n .toLowerCase();\n return (\n host === 'localhost' ||\n host.endsWith('.localhost') ||\n host === '0.0.0.0' ||\n LOOPBACK_V4.test(host) ||\n LOOPBACK_V6.has(host) ||\n MAPPED_V4.test(host)\n );\n}\n\nexport function kernelLoopbackPort(href: string): number | undefined {\n let url: URL;\n try {\n url = new URL(href);\n } catch {\n return undefined;\n }\n const fallback = SCHEMES[url.protocol];\n if (fallback === undefined || !isKernelLoopbackHost(url.hostname)) return undefined;\n const named = KERNEL_PORT.exec(url.hostname.replace(/\\.$/, '').toLowerCase())?.[1];\n const port = Number(named ?? (url.port || fallback));\n return port >= 1 && port <= 65535 ? port : undefined;\n}\n\nexport const DEFAULT_HOSTNAME = 'slicc';\n\nexport const HOSTNAME_ADDRESS = '127.0.1.1';\n\nexport const LIBC_HOSTNAMES: readonly string[] = ['emscripten', 'wasmer.sh'];\n\nconst LABEL = /^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$/i;\n\nfunction reserved(name: string): boolean {\n const lower = name.toLowerCase();\n return (\n lower === 'localhost' ||\n lower.endsWith('.localhost') ||\n lower === HOST_LOOPBACK ||\n lower === 'wasmer.sh' ||\n /^\\d+(\\.\\d+){3}$/.test(lower)\n );\n}\n\nexport function isHostname(name: unknown): name is string {\n if (typeof name !== 'string' || name.length > 253 || reserved(name)) return false;\n return name.split('.').every((l) => LABEL.test(l));\n}\n\nexport function hostnameOf(env: Readonly<Record<string, string>>): string {\n return isHostname(env.HOSTNAME) ? env.HOSTNAME : DEFAULT_HOSTNAME;\n}\n\nexport function initHostname(init: {\n hostname?: string | undefined;\n env: Readonly<Record<string, string>>;\n}): string {\n return isHostname(init.hostname) ? init.hostname : hostnameOf(init.env);\n}\n\nexport function ownNames(hostname: string): string[] {\n return [...new Set([hostname.toLowerCase(), ...LIBC_HOSTNAMES])];\n}\n\nexport function hostsFile(hostname: string = DEFAULT_HOSTNAME): string {\n return [\n '127.0.0.1 localhost localhost.localdomain',\n '::1 localhost ip6-localhost',\n `${HOSTNAME_ADDRESS} ${ownNames(hostname).join(' ')}`,\n `${HOST_LOOPBACK_ADDRESS.join('.')} ${HOST_LOOPBACK}`,\n '',\n ].join('\\n');\n}\n", "export const BODY_IDLE_MS = 5 * 60 * 1000;\n\nexport function idleFailure(ms: number): Error {\n return Object.assign(new Error(`the response body sent no data for ${ms} ms`), {\n code: 'ETIMEDOUT',\n });\n}\n\nexport async function readWithin<T>(\n reader: ReadableStreamDefaultReader<T>,\n ms: number\n): Promise<ReadableStreamReadResult<T>> {\n if (!(ms > 0 && ms < Number.POSITIVE_INFINITY)) return reader.read();\n let timer: ReturnType<typeof setTimeout> | undefined;\n const idle = new Promise<never>((_, reject) => {\n timer = setTimeout(() => reject(idleFailure(ms)), ms);\n });\n try {\n return await Promise.race([reader.read(), idle]);\n } finally {\n clearTimeout(timer);\n }\n}\n", "import { BODY_IDLE_MS } from '../../body-idle.ts';\nimport type { SealedCaller, SealedHook } from '../sealed.ts';\nimport { PlaceholderRefused } from './placeholder-floor.ts';\nimport type { HeaderList, RealmTransportRequest, RealmTransportResponse } from './transport.ts';\n\nexport const SEALED_FETCH_VERSION = 1;\n\nconst UNSAFE_FIELD = /[\\r\\n\\0]/;\n\nexport interface SealedFetchRequest {\n v: 1;\n caller: SealedCaller;\n method: string;\n url: string;\n headers: HeaderList;\n redirect: 'manual';\n body?: Uint8Array;\n bodyStream?: AsyncIterable<Uint8Array>;\n}\n\nexport type SealedFetchHook = (\n req: SealedFetchRequest,\n options: { signal: AbortSignal }\n) => Promise<RealmTransportResponse>;\n\nexport type SealedOption = SealedHook | { request: SealedHook; fetch?: SealedFetchHook };\n\nexport function sealedHooks(option: SealedOption | undefined): {\n request?: SealedHook;\n fetch?: SealedFetchHook;\n} {\n if (!option) return {};\n if (typeof option === 'function') return { request: option };\n const { request, fetch } = option;\n if (typeof request !== 'function' || (fetch !== undefined && typeof fetch !== 'function')) {\n throw new TypeError('sealed takes a function or { request, fetch? }');\n }\n return { request, ...(fetch ? { fetch } : {}) };\n}\n\nfunction headerList(headers: unknown): headers is HeaderList {\n return (\n Array.isArray(headers) &&\n headers.every(\n (field) =>\n Array.isArray(field) &&\n field.length === 2 &&\n field.every((text) => typeof text === 'string' && !UNSAFE_FIELD.test(text))\n )\n );\n}\n\nexport function sealedReplyValid(reply: unknown): reply is RealmTransportResponse {\n if (typeof reply !== 'object' || reply === null) return false;\n const { redirects, redirected, status, statusText, headers, url, body, cancel } =\n reply as Partial<RealmTransportResponse>;\n return (\n redirects === undefined &&\n redirected !== true &&\n Number.isInteger(status) &&\n (status as number) >= 100 &&\n (status as number) <= 599 &&\n typeof statusText === 'string' &&\n !UNSAFE_FIELD.test(statusText) &&\n headerList(headers) &&\n (url === undefined || typeof url === 'string') &&\n typeof body?.[Symbol.asyncIterator] === 'function' &&\n typeof cancel === 'function'\n );\n}\n\nexport function dropSealedReply(reply: unknown): void {\n const { cancel } = (reply ?? {}) as Partial<RealmTransportResponse>;\n if (typeof cancel !== 'function') return;\n void Promise.resolve()\n .then(() => cancel.call(reply))\n .catch(() => undefined);\n}\n\nfunction failed(reason: unknown): PlaceholderRefused {\n const text = reason instanceof Error ? reason.message : String(reason);\n return new PlaceholderRefused(\n `refused: the request with a sealed placeholder was not completed: ${text}`\n );\n}\n\nclass Stall {\n private readonly idle = new AbortController();\n private readonly ms: number;\n private timer: ReturnType<typeof setTimeout> | undefined;\n readonly signal: AbortSignal;\n\n constructor(signals: AbortSignal[], ms: number) {\n this.ms = ms;\n this.signal = AbortSignal.any([...signals, this.idle.signal]);\n }\n\n arm(): void {\n clearTimeout(this.timer);\n this.timer = setTimeout(() => this.idle.abort('timeout'), this.ms);\n (this.timer as { unref?: () => void }).unref?.();\n }\n\n touch(): void {\n if (this.timer !== undefined) this.arm();\n }\n\n rest(): void {\n clearTimeout(this.timer);\n this.timer = undefined;\n }\n}\n\nasync function until<T>(work: Promise<T>, signal: AbortSignal): Promise<T> {\n const stopped = Promise.withResolvers<never>();\n const stop = () => stopped.reject(signal.reason);\n if (signal.aborted) stop();\n else signal.addEventListener('abort', stop, { once: true });\n try {\n return await Promise.race([work, stopped.promise]);\n } finally {\n signal.removeEventListener('abort', stop);\n }\n}\n\nasync function* ticking(\n stream: AsyncIterable<Uint8Array>,\n stall: Stall\n): AsyncGenerator<Uint8Array> {\n for await (const chunk of stream) {\n stall.touch();\n yield chunk;\n }\n}\n\nfunction sealedRequest(\n request: RealmTransportRequest,\n stamp: SealedCaller,\n stall: Stall\n): SealedFetchRequest {\n const { method, url, headers, body, bodyStream } = request;\n return {\n v: 1,\n caller: structuredClone(stamp),\n method,\n url,\n headers: headers.map(([name, value]) => [name, value] as const),\n redirect: 'manual',\n ...(bodyStream ? { bodyStream: ticking(bodyStream, stall) } : body ? { body } : {}),\n };\n}\n\nfunction guarded(reply: RealmTransportResponse, stall: Stall): RealmTransportResponse {\n let finished = false;\n const cancel = async () => {\n stall.signal.removeEventListener('abort', dropped);\n stall.rest();\n if (finished) return;\n finished = true;\n await reply.cancel().catch(() => undefined);\n };\n const dropped = () => void cancel();\n stall.signal.addEventListener('abort', dropped, { once: true });\n const source = reply.body[Symbol.asyncIterator]();\n const body = (async function* () {\n try {\n for (;;) {\n stall.arm();\n const next = await until(source.next(), stall.signal);\n stall.rest();\n if (next.done) {\n finished = true;\n return;\n }\n if (!(next.value instanceof Uint8Array)) throw failed('a body chunk is not bytes');\n if (next.value.byteLength > 0) yield next.value;\n }\n } finally {\n await cancel();\n }\n })();\n return {\n ...(reply.url !== undefined ? { url: reply.url } : {}),\n status: reply.status,\n statusText: reply.statusText,\n headers: reply.headers,\n body,\n cancel,\n };\n}\n\nexport function sealedFetcher(\n hook: SealedFetchHook,\n stop: AbortSignal,\n idleMs = BODY_IDLE_MS\n): (request: RealmTransportRequest, stamp: SealedCaller) => Promise<RealmTransportResponse> {\n return async (request, stamp) => {\n const stall = new Stall([request.signal, stop], idleMs);\n const { signal } = stall;\n if (signal.aborted) throw failed(signal.reason);\n stall.arm();\n const asked = Promise.resolve().then(() => {\n signal.throwIfAborted();\n return hook(sealedRequest(request, stamp, stall), { signal });\n });\n let reply: unknown;\n try {\n reply = await until(asked, signal);\n } catch (e) {\n void asked.then(dropSealedReply, () => undefined);\n throw failed(e);\n } finally {\n stall.rest();\n }\n if (sealedReplyValid(reply)) return guarded(reply, stall);\n dropSealedReply(reply);\n throw failed('the reply is not a scrubbed response');\n };\n}\n", "import { HOST_LOOPBACK, HOST_LOOPBACK_ADDRESS } from './loopback-names.ts';\n\nexport interface RouteTable {\n prefixes: readonly string[];\n exit: boolean;\n}\n\nexport type Destination = 'loopback' | 'host' | 'reserved' | 'uplink' | 'unreachable';\n\ninterface Prefix {\n v6: boolean;\n bits: bigint;\n length: number;\n}\n\nconst HOST_ADDRESS = HOST_LOOPBACK_ADDRESS.join('.');\n\nexport function ipv4Bytes(text: string): number[] | undefined {\n const parts = text.split('.');\n if (parts.length !== 4 || !parts.every((p) => /^\\d{1,3}$/.test(p))) return undefined;\n const bytes = parts.map(Number);\n return bytes.every((b) => b <= 255) ? bytes : undefined;\n}\n\nexport function ipv6Groups(text: string): number[] | undefined {\n if (!text.includes(':')) return undefined;\n let canonical: string;\n try {\n canonical = new URL(`http://[${text}]/`).hostname.slice(1, -1);\n } catch {\n return undefined;\n }\n const [head, tail] = canonical.split('::');\n const part = (s: string | undefined) =>\n s ? s.split(':').map((h) => Number.parseInt(h, 16)) : [];\n const front = part(head);\n const back = part(tail);\n return tail === undefined\n ? front\n : [...front, ...new Array<number>(8 - front.length - back.length).fill(0), ...back];\n}\n\nfunction toBits(values: number[], width: number): bigint {\n return values.reduce((acc, v) => (acc << BigInt(width)) | BigInt(v), 0n);\n}\n\nfunction addressBits(host: string): { v6: boolean; bits: bigint } | undefined {\n const v4 = ipv4Bytes(host);\n if (v4) return { v6: false, bits: toBits(v4, 8) };\n const v6 = ipv6Groups(host);\n return v6 ? { v6: true, bits: toBits(v6, 16) } : undefined;\n}\n\nfunction parsePrefix(text: string): Prefix | undefined {\n const parts = text.trim().split('/');\n if (parts.length > 2) return undefined;\n const [address = '', size] = parts;\n const parsed = addressBits(address);\n if (!parsed) return undefined;\n const max = parsed.v6 ? 128 : 32;\n const length = size === undefined ? max : /^\\d{1,3}$/.test(size) ? Number(size) : -1;\n if (length < 0 || length > max) return undefined;\n return { ...parsed, length };\n}\n\nfunction within(prefix: Prefix, addr: { v6: boolean; bits: bigint }): boolean {\n if (prefix.v6 !== addr.v6) return false;\n const shift = BigInt((prefix.v6 ? 128 : 32) - prefix.length);\n return addr.bits >> shift === prefix.bits >> shift;\n}\n\nconst RESERVED = [\n '0.0.0.0/8',\n '127.0.0.0/8',\n '169.254.0.0/16',\n '224.0.0.0/4',\n '240.0.0.0/4',\n '::/96',\n '::ffff:0:0/96',\n 'fe80::/10',\n 'ff00::/8',\n].map((p) => parsePrefix(p) as Prefix);\n\nexport class Routes {\n private table: Prefix[] = [];\n private exit = false;\n readonly ipv6: boolean;\n\n constructor(ipv6 = false) {\n this.ipv6 = ipv6;\n }\n\n set(table: RouteTable): void {\n const parsed = (table.prefixes ?? []).map(parsePrefix);\n const bad = (table.prefixes ?? []).find((_, i) => !parsed[i]);\n if (bad !== undefined) throw new Error(`not an address prefix: ${bad}`);\n this.table = parsed as Prefix[];\n this.exit = table.exit === true;\n }\n\n classify(host: string): Destination {\n const name = host.toLowerCase().replace(/\\.$/, '');\n if (name === 'localhost' || name.endsWith('.localhost') || name === '0.0.0.0') {\n return 'loopback';\n }\n if (name === HOST_LOOPBACK || name === HOST_ADDRESS) return 'host';\n const addr = addressBits(name);\n if (!addr) return 'unreachable';\n if (addr.v6 && addr.bits === 1n) return 'loopback';\n if (!addr.v6 && addr.bits >> 24n === 127n) return 'loopback';\n if (RESERVED.some((p) => within(p, addr))) return 'reserved';\n if (addr.v6 && !this.ipv6) return 'unreachable';\n if (this.exit || this.table.some((p) => within(p, addr))) return 'uplink';\n return 'unreachable';\n }\n}\n", "import { Routes, type RouteTable } from './routes.ts';\n\nexport interface UplinkTraits {\n tcp: true;\n udp: boolean;\n ipv6: boolean;\n}\n\nexport type ResolveFamily = 0 | 4 | 6;\n\nexport interface ResolveAnswer {\n addresses: string[];\n ttl?: number;\n}\n\nexport interface UplinkConn {\n readonly localAddr: string;\n readonly remoteAddr: string;\n readonly exit?: string;\n read(): Promise<Uint8Array | null>;\n write(bytes: Uint8Array): Promise<number>;\n closeWrite(): void;\n close(): void;\n}\n\nexport interface UplinkDial {\n network: 'tcp';\n host: string;\n port: number;\n signal: AbortSignal;\n}\n\nexport interface UplinkDatagram {\n bytes: Uint8Array;\n host: string;\n port: number;\n}\n\nexport interface UplinkUnreachable {\n error: string;\n host: string;\n port: number;\n}\n\nexport type UplinkMessage = UplinkDatagram | UplinkUnreachable;\n\nexport interface UplinkUdpOpen {\n family: 4 | 6;\n signal: AbortSignal;\n}\n\nexport interface UplinkUdp {\n readonly localAddr: string;\n send(bytes: Uint8Array, host: string, port: number): Promise<void>;\n readonly messages: AsyncIterable<UplinkMessage>;\n close(): void;\n}\n\nexport interface NetworkUplink {\n readonly traits: UplinkTraits;\n readonly routes?: RouteTable;\n readonly nameserver?: string;\n resolve(\n name: string,\n family: ResolveFamily,\n signal?: AbortSignal\n ): Promise<string[] | ResolveAnswer>;\n dial(req: UplinkDial): Promise<UplinkConn>;\n udp?(req: UplinkUdpOpen): Promise<UplinkUdp>;\n}\n\nexport function carriesUdp(uplink: NetworkUplink): boolean {\n return uplink.traits.udp === true && typeof uplink.udp === 'function';\n}\n\nexport type UplinkCall =\n | { uplink: 'resolve'; uid: number; name: string; family: ResolveFamily }\n | { uplink: 'dial'; uid: number; host: string; port: number }\n | { uplink: 'cancel'; uid: number }\n | { uplink: 'read'; uid: number; cid: number }\n | { uplink: 'write'; uid: number; cid: number; bytes: Uint8Array }\n | { uplink: 'close-write'; cid: number }\n | { uplink: 'close'; cid: number }\n | { uplink: 'udp-open'; uid: number; family: 4 | 6 }\n | { uplink: 'udp-send'; uid: number; cid: number; bytes: Uint8Array; host: string; port: number }\n | { uplink: 'udp-recv'; uid: number; cid: number }\n | { uplink: 'udp-close'; cid: number };\n\nexport type UplinkReply =\n | { uplink: 'resolved'; uid: number; addresses: string[]; ttl?: number }\n | { uplink: 'dialled'; uid: number; cid: number; localAddr: string; remoteAddr: string }\n | { uplink: 'data'; uid: number; bytes: Uint8Array | null }\n | { uplink: 'written'; uid: number; n: number }\n | { uplink: 'udp-opened'; uid: number; cid: number; localAddr: string }\n | { uplink: 'udp-sent'; uid: number }\n | { uplink: 'udp-message'; uid: number; message: UplinkMessage | null }\n | { uplink: 'error'; uid: number; message: string; code?: string };\n\nexport interface UplinkPeer {\n postMessage(message: UplinkReply, transfer?: Transferable[]): void;\n}\n\nexport interface UplinkPort {\n postMessage(message: UplinkCall, transfer?: Transferable[]): void;\n}\n\nexport interface UplinkServer {\n answer(call: UplinkCall): void;\n close(): void;\n}\n\nexport function answerOf(result: string[] | ResolveAnswer): ResolveAnswer {\n const answer = Array.isArray(result) ? { addresses: result } : result;\n const addresses = Array.isArray(answer?.addresses)\n ? answer.addresses.filter((a): a is string => typeof a === 'string')\n : [];\n return {\n addresses,\n ...(typeof answer?.ttl === 'number' && answer.ttl >= 0 ? { ttl: answer.ttl } : {}),\n };\n}\n\nfunction failure(uid: number, e: unknown): UplinkReply {\n const code = (e as { code?: unknown } | null)?.code;\n return {\n uplink: 'error',\n uid,\n message: e instanceof Error ? e.message : String(e),\n ...(typeof code === 'string' ? { code } : {}),\n };\n}\n\nconst NEVER = new Routes(true);\n\nexport function serveUplink(peer: UplinkPeer, uplink: NetworkUplink): UplinkServer {\n const conns = new Map<number, UplinkConn>();\n const pending = new Map<number, AbortController>();\n let nextCid = 0;\n let closed = false;\n const run = (uid: number, work: (signal: AbortSignal) => Promise<UplinkReply | undefined>) => {\n const abort = new AbortController();\n pending.set(uid, abort);\n void work(abort.signal)\n .then(\n (reply) => reply && peer.postMessage(reply, transferOf(reply)),\n (e: unknown) => peer.postMessage(failure(uid, e))\n )\n .finally(() => pending.delete(uid));\n };\n const conn = (cid: number): UplinkConn => {\n const found = conns.get(cid);\n if (!found) throw Object.assign(new Error('no such uplink connection'), { code: 'EBADF' });\n return found;\n };\n const dial = async (call: Extract<UplinkCall, { uplink: 'dial' }>, signal: AbortSignal) => {\n refuseLocal(call.host);\n const { host, port } = call;\n const opened = await uplink.dial({ network: 'tcp', host, port, signal });\n if (signal.aborted || closed) {\n opened.close();\n return undefined;\n }\n const cid = ++nextCid;\n conns.set(cid, opened);\n const { localAddr, remoteAddr } = opened;\n return { uplink: 'dialled' as const, uid: call.uid, cid, localAddr, remoteAddr };\n };\n const drop = (cid: number) => {\n const found = conns.get(cid);\n conns.delete(cid);\n found?.close();\n };\n const udp = new UdpServer(uplink, () => closed);\n return {\n answer(call) {\n switch (call.uplink) {\n case 'resolve':\n return run(call.uid, async (signal) => ({\n uplink: 'resolved',\n uid: call.uid,\n ...answerOf(await uplink.resolve(call.name, call.family, signal)),\n }));\n case 'dial':\n return run(call.uid, (signal) => dial(call, signal));\n case 'cancel':\n return pending.get(call.uid)?.abort();\n case 'read':\n return run(call.uid, async () => ({\n uplink: 'data',\n uid: call.uid,\n bytes: (await conn(call.cid).read())?.slice() ?? null,\n }));\n case 'write':\n return run(call.uid, async () => ({\n uplink: 'written',\n uid: call.uid,\n n: await conn(call.cid).write(call.bytes),\n }));\n case 'close-write':\n return conns.get(call.cid)?.closeWrite();\n case 'close':\n return drop(call.cid);\n case 'udp-close':\n return udp.drop(call.cid);\n default:\n return run(call.uid, (signal) => udp.answer(call, signal));\n }\n },\n close() {\n closed = true;\n for (const abort of pending.values()) abort.abort();\n for (const cid of [...conns.keys()]) drop(cid);\n udp.close();\n },\n };\n}\n\nfunction copied(message: UplinkMessage): UplinkMessage {\n if ('bytes' in message) return { ...message, bytes: message.bytes.slice() };\n return { error: String(message.error), host: message.host, port: message.port };\n}\n\nfunction refuseLocal(host: string): void {\n const kind = NEVER.classify(host);\n if (kind === 'loopback' || kind === 'host' || kind === 'reserved') {\n throw Object.assign(new Error(`the uplink does not carry ${host}`), { code: 'ENETUNREACH' });\n }\n}\n\ntype UdpCall = Extract<UplinkCall, { uplink: 'udp-open' | 'udp-send' | 'udp-recv' }>;\n\nclass UdpServer {\n private readonly sockets = new Map<\n number,\n { udp: UplinkUdp; messages: AsyncIterator<UplinkMessage> }\n >();\n private next = 0;\n private readonly uplink: NetworkUplink;\n private readonly closed: () => boolean;\n\n constructor(uplink: NetworkUplink, closed: () => boolean) {\n this.uplink = uplink;\n this.closed = closed;\n }\n\n private socket(cid: number) {\n const found = this.sockets.get(cid);\n if (!found) throw Object.assign(new Error('no such uplink socket'), { code: 'EBADF' });\n return found;\n }\n\n async answer(call: UdpCall, signal: AbortSignal): Promise<UplinkReply | undefined> {\n if (call.uplink === 'udp-open') {\n if (!this.uplink.udp || this.uplink.traits.udp !== true) {\n throw Object.assign(new Error('the uplink carries no datagrams'), { code: 'ENETUNREACH' });\n }\n const opened = await this.uplink.udp({ family: call.family, signal });\n if (signal.aborted || this.closed()) {\n opened.close();\n return undefined;\n }\n const cid = ++this.next;\n this.sockets.set(cid, { udp: opened, messages: opened.messages[Symbol.asyncIterator]() });\n return { uplink: 'udp-opened', uid: call.uid, cid, localAddr: opened.localAddr };\n }\n if (call.uplink === 'udp-send') {\n refuseLocal(call.host);\n await this.socket(call.cid).udp.send(call.bytes, call.host, call.port);\n return { uplink: 'udp-sent', uid: call.uid };\n }\n const next = await this.socket(call.cid).messages.next();\n const message = next.done ? null : copied(next.value);\n return { uplink: 'udp-message', uid: call.uid, message };\n }\n\n drop(cid: number): void {\n const found = this.sockets.get(cid);\n this.sockets.delete(cid);\n found?.udp.close();\n }\n\n close(): void {\n for (const cid of [...this.sockets.keys()]) this.drop(cid);\n }\n}\n\nfunction transferOf(reply: UplinkReply): Transferable[] | undefined {\n if (reply.uplink === 'udp-message' && reply.message && 'bytes' in reply.message) {\n return [reply.message.bytes.buffer as ArrayBuffer];\n }\n if (reply.uplink !== 'data' || !reply.bytes) return undefined;\n return [reply.bytes.buffer as ArrayBuffer];\n}\n\ntype Answer = Exclude<UplinkReply, { uplink: 'error' }>;\n\nexport class RemoteUplink implements NetworkUplink {\n readonly traits: UplinkTraits;\n readonly routes: RouteTable | undefined;\n readonly nameserver: string | undefined;\n private readonly port: UplinkPort;\n private readonly waiting = new Map<number, PromiseWithResolvers<Answer>>();\n private nextId = 0;\n\n constructor(port: UplinkPort, traits: UplinkTraits, routes?: RouteTable, nameserver?: string) {\n this.port = port;\n this.traits = traits;\n this.routes = routes;\n this.nameserver = nameserver;\n }\n\n receive(reply: UplinkReply): void {\n const waiter = this.waiting.get(reply.uid);\n if (!waiter) return;\n this.waiting.delete(reply.uid);\n if (reply.uplink === 'error') {\n waiter.reject(Object.assign(new Error(reply.message), { code: reply.code }));\n } else waiter.resolve(reply);\n }\n\n private ask<T extends Answer>(\n call: Extract<UplinkCall, { uid: number }>,\n signal?: AbortSignal,\n transfer?: Transferable[]\n ): Promise<T> {\n const waiter = Promise.withResolvers<Answer>();\n this.waiting.set(call.uid, waiter);\n const abort = () => {\n this.waiting.delete(call.uid);\n this.port.postMessage({ uplink: 'cancel', uid: call.uid });\n waiter.reject(signal?.reason);\n };\n signal?.addEventListener('abort', abort, { once: true });\n const settled = () => signal?.removeEventListener('abort', abort);\n waiter.promise.then(settled, settled);\n this.port.postMessage(call, transfer);\n return waiter.promise as Promise<T>;\n }\n\n async resolve(name: string, family: ResolveFamily, signal?: AbortSignal) {\n const reply = await this.ask<Extract<Answer, { uplink: 'resolved' }>>(\n { uplink: 'resolve', uid: ++this.nextId, name, family },\n signal\n );\n return answerOf(reply);\n }\n\n async dial(req: UplinkDial): Promise<UplinkConn> {\n req.signal.throwIfAborted();\n const { host, port } = req;\n const opened = await this.ask<Extract<Answer, { uplink: 'dialled' }>>(\n { uplink: 'dial', uid: ++this.nextId, host, port },\n req.signal\n );\n const { cid, localAddr, remoteAddr } = opened;\n return {\n localAddr,\n remoteAddr,\n read: async () => {\n const got = await this.ask<Extract<Answer, { uplink: 'data' }>>({\n uplink: 'read',\n uid: ++this.nextId,\n cid,\n });\n return got.bytes;\n },\n write: async (bytes) => {\n const copy = bytes.slice();\n const call = { uplink: 'write' as const, uid: ++this.nextId, cid, bytes: copy };\n const done = await this.ask<Extract<Answer, { uplink: 'written' }>>(call, undefined, [\n copy.buffer,\n ]);\n return done.n;\n },\n closeWrite: () => this.port.postMessage({ uplink: 'close-write', cid }),\n close: () => this.port.postMessage({ uplink: 'close', cid }),\n };\n }\n\n async udp(req: UplinkUdpOpen): Promise<UplinkUdp> {\n req.signal.throwIfAborted();\n const opened = await this.ask<Extract<Answer, { uplink: 'udp-opened' }>>(\n { uplink: 'udp-open', uid: ++this.nextId, family: req.family },\n req.signal\n );\n const { cid, localAddr } = opened;\n const recv = () =>\n this.ask<Extract<Answer, { uplink: 'udp-message' }>>({\n uplink: 'udp-recv',\n uid: ++this.nextId,\n cid,\n });\n return {\n localAddr,\n send: async (bytes, host, port) => {\n const copy = bytes.slice();\n const call = {\n uplink: 'udp-send' as const,\n uid: ++this.nextId,\n cid,\n bytes: copy,\n host,\n port,\n };\n await this.ask(call, undefined, [copy.buffer]);\n },\n messages: {\n [Symbol.asyncIterator]: async function* () {\n for (;;) {\n const got = await recv();\n if (!got.message) return;\n yield got.message;\n }\n },\n },\n close: () => this.port.postMessage({ uplink: 'udp-close', cid }),\n };\n }\n}\n", "export const SIG = {\n HUP: 1,\n INT: 2,\n QUIT: 3,\n ILL: 4,\n TRAP: 5,\n ABRT: 6,\n BUS: 7,\n FPE: 8,\n KILL: 9,\n USR1: 10,\n SEGV: 11,\n USR2: 12,\n PIPE: 13,\n ALRM: 14,\n TERM: 15,\n STKFLT: 16,\n CHLD: 17,\n CONT: 18,\n STOP: 19,\n TSTP: 20,\n TTIN: 21,\n TTOU: 22,\n URG: 23,\n XCPU: 24,\n XFSZ: 25,\n VTALRM: 26,\n PROF: 27,\n WINCH: 28,\n POLL: 29,\n PWR: 30,\n SYS: 31,\n} as const;\n\nexport type DefaultAction = 'terminate' | 'ignore' | 'stop' | 'continue';\n\nconst IGNORED_BY_DEFAULT: ReadonlySet<number> = new Set([SIG.CHLD, SIG.URG, SIG.WINCH]);\nconst STOPPING: ReadonlySet<number> = new Set([SIG.STOP, SIG.TSTP, SIG.TTIN, SIG.TTOU]);\n\nexport function defaultAction(sig: number): DefaultAction {\n if (sig === SIG.CONT) return 'continue';\n if (STOPPING.has(sig)) return 'stop';\n return IGNORED_BY_DEFAULT.has(sig) ? 'ignore' : 'terminate';\n}\n\nexport function isSignal(sig: number): boolean {\n return Number.isInteger(sig) && sig >= 1 && sig <= 31;\n}\n\nexport function sigbit(sig: number): number {\n return 1 << sig;\n}\n\nexport function signalsIn(mask: number): number[] {\n const out: number[] = [];\n for (let sig = 1; sig <= 31; sig++) if (mask & sigbit(sig)) out.push(sig);\n return out;\n}\n\nexport function signalName(sig: number | undefined): string | undefined {\n const name = Object.entries(SIG).find(([, n]) => n === sig)?.[0];\n return name === undefined ? undefined : `SIG${name}`;\n}\n\nexport function quiet<T>(p: Promise<T>): Promise<T> {\n p.catch(() => undefined);\n return p;\n}\n\nexport function signalField(sig: number | undefined): { signal?: string } {\n const name = signalName(sig);\n return name ? { signal: name } : {};\n}\n\nexport const SIGNAL_BY_NAME: Readonly<\n Record<'SIGINT' | 'SIGTERM' | 'SIGKILL' | 'SIGSTOP' | 'SIGCONT', number>\n> = {\n SIGINT: SIG.INT,\n SIGTERM: SIG.TERM,\n SIGKILL: SIG.KILL,\n SIGSTOP: SIG.STOP,\n SIGCONT: SIG.CONT,\n};\n\nexport interface SigInfo {\n code: number;\n pid: number;\n uid: number;\n status: number;\n}\n\nexport const SI = { USER: 0, QUEUE: -1, TIMER: -2, TKILL: -6, KERNEL: 0x80 } as const;\n\nexport const CLD = { EXITED: 1, KILLED: 2, DUMPED: 3, STOPPED: 5, CONTINUED: 6 } as const;\n\nexport const KERNEL_SIGINFO: Readonly<SigInfo> = Object.freeze({\n code: SI.KERNEL,\n pid: 0,\n uid: 0,\n status: 0,\n});\n", "import { fresh } from './bytes.ts';\nimport {\n dropSealedReply,\n type SealedFetchHook,\n type SealedFetchRequest,\n sealedReplyValid,\n} from './kernel/net/sealed-fetch.ts';\nimport type { HeaderList, RealmTransportResponse as Response } from './kernel/net/transport.ts';\nimport type { SealedHook, SealedRequest } from './kernel/sealed.ts';\n\nexport interface SealedPort {\n postMessage(message: unknown, transfer?: Transferable[]): void;\n}\n\nexport interface SealedAsk {\n id: number;\n req: SealedRequest;\n}\n\nexport interface SealedReply {\n id: number;\n reply?: object;\n error?: string;\n}\n\nexport interface SealedAbort {\n id: number;\n reason: unknown;\n}\n\ntype WireRequest = Omit<SealedFetchRequest, 'bodyStream'> & { streamed?: true };\n\nexport interface SealedFetchAsk {\n req: WireRequest;\n port: MessagePort;\n}\n\ntype AskerMessage =\n | { t: 'pull' }\n | { t: 'stop' }\n | {\n t: 'head';\n status: number;\n statusText: string;\n headers: HeaderList;\n url?: string;\n }\n | { t: 'chunk'; bytes: Uint8Array }\n | { t: 'end' }\n | { t: 'error'; message: string };\n\ntype AnswererMessage =\n | { t: 'read' }\n | { t: 'cancel'; reason: string }\n | { t: 'chunk'; bytes: Uint8Array }\n | { t: 'end' }\n | { t: 'error'; message: string };\n\nfunction textOf(err: unknown): string {\n return err instanceof Error ? err.message : String(err);\n}\n\nfunction sendBytes(port: MessagePort, bytes: Uint8Array): void {\n const copy = fresh(bytes);\n port.postMessage({ t: 'chunk', bytes: copy }, [copy.buffer as ArrayBuffer]);\n}\n\nfunction askFetch(\n port: SealedPort,\n req: SealedFetchRequest,\n signal: AbortSignal\n): Promise<Response> {\n signal.throwIfAborted();\n const { bodyStream, ...wire } = req;\n const { port1: near, port2: far } = new MessageChannel();\n const upload = bodyStream?.[Symbol.asyncIterator]();\n const head = Promise.withResolvers<Response>();\n let reading: PromiseWithResolvers<IteratorResult<Uint8Array>> | undefined;\n let ended = false;\n\n const end = (failure: Error) => {\n if (ended) return;\n ended = true;\n signal.removeEventListener('abort', abort);\n near.close();\n void upload?.return?.().catch(() => undefined);\n head.reject(failure);\n reading?.reject(failure);\n reading = undefined;\n };\n const abort = () => {\n near.postMessage({ t: 'cancel', reason: String(signal.reason) } satisfies AnswererMessage);\n end(new Error(String(signal.reason)));\n };\n const pull = async () => {\n try {\n const next = await (upload as AsyncIterator<Uint8Array>).next();\n if (ended) return;\n if (next.done) near.postMessage({ t: 'end' } satisfies AnswererMessage);\n else sendBytes(near, next.value);\n } catch (err) {\n if (!ended) near.postMessage({ t: 'error', message: textOf(err) });\n }\n };\n const respond = (message: Extract<AskerMessage, { t: 'head' }>) => {\n const { status, statusText, headers, url } = message;\n const body: AsyncIterable<Uint8Array> = {\n [Symbol.asyncIterator]: () => ({\n next: () => {\n if (ended) return Promise.resolve({ value: undefined, done: true });\n reading = Promise.withResolvers();\n near.postMessage({ t: 'read' } satisfies AnswererMessage);\n return reading.promise;\n },\n return: async () => {\n await cancel();\n return { value: undefined, done: true };\n },\n }),\n };\n const cancel = async () => {\n if (ended) return;\n near.postMessage({ t: 'cancel', reason: 'cancelled' } satisfies AnswererMessage);\n end(new Error('the request was cancelled'));\n };\n head.resolve({\n ...(url !== undefined ? { url } : {}),\n status,\n statusText,\n headers,\n body,\n cancel,\n });\n };\n near.addEventListener('message', ({ data }: MessageEvent<AskerMessage>) => {\n if (data.t === 'pull') void pull();\n else if (data.t === 'stop') void upload?.return?.().catch(() => undefined);\n else if (data.t === 'head') respond(data);\n else if (data.t === 'chunk') {\n reading?.resolve({ value: data.bytes, done: false });\n reading = undefined;\n } else if (data.t === 'end') {\n reading?.resolve({ value: undefined, done: true });\n reading = undefined;\n end(new Error('the response ended'));\n } else end(new Error(data.message));\n });\n near.addEventListener('close', () => end(new Error('the sealed fetch relay closed')));\n near.start();\n signal.addEventListener('abort', abort, { once: true });\n const ask: SealedFetchAsk = {\n req: { ...wire, ...(upload ? { streamed: true } : {}) },\n port: far,\n };\n port.postMessage({ sealedFetch: ask }, [far]);\n return head.promise;\n}\n\ninterface FetchAnswer {\n close(reason: unknown): void;\n}\n\nfunction uploadOf(far: MessagePort): {\n stream: AsyncIterable<Uint8Array>;\n answer(message: Extract<AnswererMessage, { t: 'chunk' | 'end' | 'error' }>): void;\n fail(reason: Error): void;\n} {\n let waiting: PromiseWithResolvers<IteratorResult<Uint8Array>> | undefined;\n let failure: Error | undefined;\n const next = () => {\n if (failure) return Promise.reject(failure);\n waiting = Promise.withResolvers();\n far.postMessage({ t: 'pull' } satisfies AskerMessage);\n return waiting.promise;\n };\n return {\n stream: {\n [Symbol.asyncIterator]: () => ({\n next,\n return: async () => {\n far.postMessage({ t: 'stop' } satisfies AskerMessage);\n return { value: undefined, done: true };\n },\n }),\n },\n answer(message) {\n if (message.t === 'chunk') waiting?.resolve({ value: message.bytes, done: false });\n else if (message.t === 'end') waiting?.resolve({ value: undefined, done: true });\n else {\n failure = new Error(message.message);\n waiting?.reject(failure);\n }\n waiting = undefined;\n },\n fail(reason) {\n failure = reason;\n waiting?.reject(reason);\n waiting = undefined;\n },\n };\n}\n\nfunction answerFetch(\n hook: SealedFetchHook | undefined,\n { req, port: far }: SealedFetchAsk,\n live: Set<FetchAnswer>\n): void {\n const control = new AbortController();\n const { streamed, ...fields } = req;\n const upload = uploadOf(far);\n let source: AsyncIterator<Uint8Array> | undefined;\n let reply: Response | undefined;\n let closed = false;\n\n const settle = () => {\n closed = true;\n live.delete(answer);\n upload.fail(new Error('the request ended'));\n };\n const answer: FetchAnswer = {\n close(reason) {\n if (closed) return;\n settle();\n control.abort(reason);\n dropSealedReply(reply);\n far.close();\n },\n };\n const finish = (message: AskerMessage) => {\n if (closed) return;\n settle();\n far.postMessage(message);\n };\n const failWith = (err: unknown) => {\n dropSealedReply(reply);\n finish({ t: 'error', message: textOf(err) });\n };\n const read = async () => {\n try {\n const next = await (source as AsyncIterator<Uint8Array>).next();\n if (closed) return;\n if (next.done) finish({ t: 'end' });\n else if (next.value instanceof Uint8Array) sendBytes(far, next.value);\n else failWith('a body chunk is not bytes');\n } catch (err) {\n failWith(err);\n }\n };\n const ask = async () => {\n try {\n if (!hook) throw new Error('no vault is connected');\n const request: SealedFetchRequest = {\n ...fields,\n ...(streamed ? { bodyStream: upload.stream } : {}),\n };\n const answered: unknown = await hook(request, { signal: control.signal });\n if (!sealedReplyValid(answered)) {\n dropSealedReply(answered);\n throw new Error('the reply is not a scrubbed response');\n }\n if (closed) return dropSealedReply(answered);\n reply = answered;\n source = answered.body[Symbol.asyncIterator]();\n const { status, statusText, headers, url } = answered;\n far.postMessage({\n t: 'head',\n status,\n statusText,\n headers,\n ...(url !== undefined ? { url } : {}),\n } satisfies AskerMessage);\n } catch (err) {\n failWith(err);\n }\n };\n far.addEventListener('message', ({ data }: MessageEvent<AnswererMessage>) => {\n if (data.t === 'read') void read();\n else if (data.t === 'cancel') answer.close(data.reason);\n else upload.answer(data);\n });\n far.addEventListener('close', () => answer.close('withdrawn'));\n far.start();\n live.add(answer);\n void ask();\n}\n\nexport function sealedAsker(port: SealedPort): {\n hook: SealedHook;\n fetch: SealedFetchHook;\n answer(reply: SealedReply): void;\n} {\n const asks = new Map<number, PromiseWithResolvers<object>>();\n let next = 0;\n const hook: SealedHook = (req, { signal }) => {\n const id = ++next;\n const waiting = Promise.withResolvers<object>();\n asks.set(id, waiting);\n const abort = () => {\n if (!asks.delete(id)) return;\n port.postMessage({ sealedAbort: { id, reason: signal.reason } });\n waiting.reject(new Error(String(signal.reason)));\n };\n signal.addEventListener('abort', abort, { once: true });\n port.postMessage({ sealedAsk: { id, req } });\n return waiting.promise.finally(() => signal.removeEventListener('abort', abort));\n };\n const answer = ({ id, reply, error }: SealedReply) => {\n const waiting = asks.get(id);\n if (!waiting) return;\n asks.delete(id);\n if (reply) waiting.resolve(reply);\n else waiting.reject(new Error(error ?? 'no reply'));\n };\n return { hook, fetch: (req, { signal }) => askFetch(port, req, signal), answer };\n}\n\nexport interface SealedAnswerer {\n handle(data: unknown): boolean;\n close(): void;\n}\n\nexport function sealedAnswerer(\n port: SealedPort,\n hook: SealedHook | undefined,\n fetchHook?: SealedFetchHook\n): SealedAnswerer {\n const asked = new Map<number, AbortController>();\n const fetches = new Set<FetchAnswer>();\n const ask = async ({ id, req }: SealedAsk): Promise<void> => {\n const control = new AbortController();\n asked.set(id, control);\n try {\n if (!hook) throw new Error('no vault is connected');\n const reply = await hook(req, { signal: control.signal });\n port.postMessage({ sealedReply: { id, reply } });\n } catch (err) {\n const error = err instanceof Error ? err.message : String(err);\n port.postMessage({ sealedReply: { id, error } });\n } finally {\n asked.delete(id);\n }\n };\n const abort = ({ id, reason }: SealedAbort): void => {\n asked.get(id)?.abort(reason);\n asked.delete(id);\n };\n return {\n handle(data) {\n const message = data as {\n sealedAsk?: SealedAsk;\n sealedAbort?: SealedAbort;\n sealedFetch?: SealedFetchAsk;\n } | null;\n if (message?.sealedAsk) void ask(message.sealedAsk);\n else if (message?.sealedAbort) abort(message.sealedAbort);\n else if (message?.sealedFetch) answerFetch(fetchHook, message.sealedFetch, fetches);\n else return false;\n return true;\n },\n close() {\n for (const control of asked.values()) control.abort('withdrawn');\n asked.clear();\n for (const answer of [...fetches]) answer.close('withdrawn');\n },\n };\n}\n", "export const MINUTE_MS = 60_000;\n\nconst HOUR_MS = 60 * MINUTE_MS;\nconst BUCKET_MS = 15 * MINUTE_MS;\nconst CACHE_MAX = 4096;\nconst ZERO = new Set(['UTC', 'Etc/UTC', 'Etc/GMT', 'GMT', 'Etc/Universal', 'Etc/Zulu']);\n\nexport interface Zone {\n readonly name: string;\n offset(at: number): number;\n}\n\nexport function canonicalZone(name: unknown): string | undefined {\n if (typeof name !== 'string' || name === '' || name.length > 64) return undefined;\n try {\n return new Intl.DateTimeFormat('en-US', { timeZone: name }).resolvedOptions().timeZone;\n } catch {\n return undefined;\n }\n}\n\nexport function hostTimeZone(): string {\n let name: string | undefined;\n try {\n name = new Intl.DateTimeFormat().resolvedOptions().timeZone;\n } catch {\n name = undefined;\n }\n return canonicalZone(name) ?? 'UTC';\n}\n\nexport function systemTimeZone(given: string | undefined, fallback?: string): string {\n if (given !== undefined) {\n const zone = canonicalZone(given);\n if (zone === undefined) throw new Error(`not a time zone: ${String(given)}`);\n return zone;\n }\n return canonicalZone(fallback) ?? hostTimeZone();\n}\n\nexport const utcZone: Zone = { name: 'UTC', offset: () => 0 };\n\nfunction hostZone(name: string): Zone {\n return { name, offset: (at) => -new Date(at).getTimezoneOffset() * MINUTE_MS };\n}\n\nfunction intlZone(name: string): Zone {\n const format = new Intl.DateTimeFormat('en-US', {\n timeZone: name,\n hourCycle: 'h23',\n year: 'numeric',\n month: 'numeric',\n day: 'numeric',\n hour: 'numeric',\n minute: 'numeric',\n second: 'numeric',\n });\n const exact = (at: number): number => {\n const parts: Record<string, number> = {};\n for (const part of format.formatToParts(at)) parts[part.type] = Number(part.value);\n const wall = Date.UTC(\n parts.year as number,\n (parts.month as number) - 1,\n parts.day as number,\n parts.hour as number,\n parts.minute as number,\n parts.second as number\n );\n return wall - Math.floor(at / 1000) * 1000;\n };\n const buckets = new Map<number, number | null>();\n return {\n name,\n offset(at) {\n const bucket = Math.floor(at / BUCKET_MS);\n let known = buckets.get(bucket);\n if (known === undefined) {\n const start = exact(bucket * BUCKET_MS);\n known = start === exact(bucket * BUCKET_MS + BUCKET_MS - MINUTE_MS) ? start : null;\n if (buckets.size >= CACHE_MAX) buckets.clear();\n buckets.set(bucket, known);\n }\n return known ?? exact(at);\n },\n };\n}\n\nconst zones = new Map<string, Zone>();\n\nexport function zoneOf(name: string): Zone {\n if (ZERO.has(name)) return utcZone;\n if (name === hostTimeZone()) return hostZone(name);\n let zone = zones.get(name);\n if (!zone) {\n zone = intlZone(name);\n zones.set(name, zone);\n }\n return zone;\n}\n\nexport const MAX_SHIFT_MS = 3 * HOUR_MS;\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 RealmWebSocket,\n RealmWebSocketMessage,\n RealmWebSocketRequest,\n} from './kernel/net/transport.ts';\nimport { MessageQueue } from './kernel/net/ws-queue.ts';\n\nexport interface WebSocketLike {\n binaryType: string;\n readonly protocol: string;\n readonly bufferedAmount: number;\n send(data: string | ArrayBufferView): void;\n close(code?: number, reason?: string): void;\n addEventListener(type: string, listener: (event: never) => void): void;\n}\n\nexport type WebSocketConstructor = new (url: string, init?: unknown) => WebSocketLike;\n\nconst SENT_HEADERS_DROP = new Set([\n 'host',\n 'connection',\n 'upgrade',\n 'sec-websocket-key',\n 'sec-websocket-version',\n 'sec-websocket-extensions',\n 'sec-websocket-protocol',\n]);\n\nfunction headerRecord(headers: HeaderList): Record<string, string> {\n const out: Record<string, string> = {};\n for (const [name, value] of headers) {\n if (!SENT_HEADERS_DROP.has(name.toLowerCase())) out[name] = value;\n }\n return out;\n}\n\nexport function sendableClose(code?: number): number {\n return code === 1000 || (code !== undefined && code >= 3000 && code <= 4999) ? code : 1000;\n}\n\nfunction blockedReason(url: string, e: unknown): string {\n const name = (e as { name?: unknown } | null)?.name;\n if (name === 'SecurityError' && url.startsWith('ws:')) {\n return `${url}: ws:// is blocked from an https page; use wss://, or link a slicc CLI (npx sliccy@next)`;\n }\n return `${url}: ${e instanceof Error ? e.message : String(e)}`;\n}\n\nfunction unopened(url: string, code: number): Error {\n return Object.assign(new Error(`${url}: the WebSocket closed (${code}) before it opened`), {\n status: 502,\n });\n}\n\nexport function openWebSocket(\n Socket: WebSocketConstructor,\n request: RealmWebSocketRequest,\n withHeaders: boolean\n): Promise<RealmWebSocket> {\n const { url, protocols, signal } = request;\n signal.throwIfAborted();\n let socket: WebSocketLike;\n try {\n socket = withHeaders\n ? new Socket(url, { protocols, headers: headerRecord(request.headers) })\n : new Socket(url, protocols);\n } catch (e) {\n return Promise.reject(Object.assign(new Error(blockedReason(url, e)), { status: 502 }));\n }\n socket.binaryType = 'arraybuffer';\n const queue = new MessageQueue(() => socket.close(1000, 'too many waiting messages'));\n return new Promise((resolve, reject) => {\n let open = false;\n let settled = false;\n const fail = (error: unknown) => {\n if (settled) return;\n settled = true;\n signal.removeEventListener('abort', abort);\n reject(error);\n };\n const abort = () => {\n fail(signal.reason);\n socket.close(1000, 'aborted');\n };\n signal.addEventListener('abort', abort, { once: true });\n socket.addEventListener('open', () => {\n if (settled) return;\n open = true;\n settled = true;\n signal.removeEventListener('abort', abort);\n resolve({\n protocol: socket.protocol,\n get buffered() {\n return socket.bufferedAmount;\n },\n send: (data: RealmWebSocketMessage) => socket.send(data),\n messages: queue,\n close: (code?: number, reason?: string) => socket.close(sendableClose(code), reason),\n closed: queue.closed,\n });\n });\n socket.addEventListener('message', (event: { data: string | ArrayBuffer }) => {\n queue.push(typeof event.data === 'string' ? event.data : new Uint8Array(event.data));\n });\n socket.addEventListener('error', () => {\n if (open || settled) return;\n fail(unopened(url, 1006));\n queue.end({ code: 1006, reason: '' });\n try {\n socket.close();\n } catch {}\n });\n socket.addEventListener(\n 'close',\n (event: { code: number; reason: string; wasClean?: boolean }) => {\n queue.end({ code: event.code, reason: event.reason, wasClean: event.wasClean === true });\n if (open) return;\n fail(unopened(url, event.code));\n }\n );\n });\n}\n", "import { BODY_IDLE_MS, readWithin } from './body-idle.ts';\nimport { fresh } from './bytes.ts';\nimport type { TransportCall, TransportReply } from './kernel/net/remote-transport.ts';\nimport type {\n HeaderList,\n RealmRedirectHop,\n RealmRedirectPolicy,\n RealmTransport,\n RealmTransportExit,\n RealmTransportRequest,\n RealmTransportResponse,\n RealmTransportTraits,\n RealmWebSocket,\n RealmWebSocketRequest,\n} from './kernel/net/transport.ts';\nimport { INBOUND_LIMIT, MESSAGE_LIMIT, payloadSize } from './kernel/net/ws-queue.ts';\nimport { openWebSocket, type WebSocketConstructor } from './websocket-transport.ts';\n\nexport type {\n HeaderList,\n RealmRedirectHop as NetworkRedirectHop,\n RealmRedirectPolicy as NetworkRedirectPolicy,\n RealmTransport as NetworkTransport,\n RealmTransportExit as NetworkExit,\n RealmTransportRequest as NetworkRequest,\n RealmTransportResponse as NetworkResponse,\n RealmTransportTraits as NetworkTraits,\n RealmWebSocket as NetworkWebSocket,\n RealmWebSocketRequest as NetworkWebSocketRequest,\n};\n\nexport interface FetchTransportOptions {\n fetch?: typeof globalThis.fetch;\n maxRequestBody?: number;\n hint?: string;\n bodyIdleMs?: number;\n webSocket?: boolean | WebSocketConstructor;\n webSocketHeaders?: boolean;\n redirect?: 'follow' | 'manual';\n streamingBodies?: boolean;\n}\n\nexport const SEND_BUFFER = 1024 * 1024;\nconst CLOSE_WAIT_MS = 5000;\nconst DNS_CODES = new Set(['ENOTFOUND', 'EAI_AGAIN', 'EAI_NONAME', 'EAI_FAIL', 'ENODATA']);\n\nconst NO_WEBSOCKET =\n 'WebSocket not supported by this transport (fetchTransport needs { webSocket: true })';\n\nconst MAX_REQUEST_BODY = 64 * 1024 * 1024;\n\nfunction joinHeaders(headers: HeaderList): Headers {\n const out = new Headers();\n for (const [name, value] of headers) {\n try {\n out.append(name, value);\n } catch {}\n }\n return out;\n}\n\nasync function* chunks(\n body: ReadableStream<Uint8Array> | null,\n idleMs: number\n): AsyncGenerator<Uint8Array> {\n if (!body) return;\n const reader = body.getReader();\n try {\n for (\n let next = await readWithin(reader, idleMs);\n !next.done;\n next = await readWithin(reader, idleMs)\n ) {\n if (next.value.byteLength > 0) yield next.value;\n }\n } finally {\n await reader.cancel().catch(() => undefined);\n }\n}\n\nfunction sentHeaders(headers: HeaderList, inPage: boolean): Headers {\n const out = joinHeaders(headers);\n if (inPage) out.delete('user-agent');\n return out;\n}\n\nfunction streamOf(body: AsyncIterable<Uint8Array>): ReadableStream<Uint8Array> {\n const it = body[Symbol.asyncIterator]();\n return new ReadableStream<Uint8Array>(\n {\n async pull(controller) {\n const next = await it.next();\n if (next.done) controller.close();\n else controller.enqueue(next.value);\n },\n async cancel(reason) {\n await it.return?.(reason);\n },\n },\n { highWaterMark: 0 }\n );\n}\n\nfunction requestBody(request: RealmTransportRequest): RequestInit {\n if (request.bodyStream) {\n return { body: streamOf(request.bodyStream), duplex: 'half' } as RequestInit;\n }\n return request.body ? { body: request.body as BodyInit } : {};\n}\n\nexport function fetchTransport(options: FetchTransportOptions = {}): RealmTransport {\n const send = options.fetch ?? globalThis.fetch.bind(globalThis);\n const Socket =\n options.webSocket === true\n ? (globalThis as { WebSocket?: WebSocketConstructor }).WebSocket\n : options.webSocket || undefined;\n const headers = options.webSocketHeaders === true;\n const instance = options.redirect ?? 'follow';\n const inPage = !options.fetch && 'location' in globalThis;\n return {\n traits: {\n manualRedirects: instance === 'manual',\n redirectPolicy: true,\n encodedBodies: false,\n maxRequestBody: options.maxRequestBody ?? MAX_REQUEST_BODY,\n crossOrigin: 'cors',\n ...(Socket ? { websocket: true as const } : {}),\n ...(options.streamingBodies ? { streamingBodies: true as const } : {}),\n },\n ...(Socket ? { websocket: (request) => openWebSocket(Socket, request, headers) } : {}),\n async fetch(request: RealmTransportRequest): Promise<RealmTransportResponse> {\n let response: Response;\n try {\n response = await send(request.url, {\n method: request.method,\n headers: sentHeaders(request.headers, inPage),\n ...requestBody(request),\n signal: request.signal,\n redirect: request.redirect ?? instance,\n credentials: 'omit',\n mode: 'cors',\n });\n } catch (e) {\n if (request.signal.aborted) throw e;\n const causeCode = (e as { cause?: { code?: unknown } })?.cause?.code;\n const dns = typeof causeCode === 'string' && DNS_CODES.has(causeCode);\n throw Object.assign(\n new Error(\n `fetch ${request.url} failed (unreachable, or not allowed by CORS)${options.hint ? `: ${options.hint}` : ''}`\n ),\n { status: 502 },\n dns ? { code: causeCode } : {},\n typeof causeCode === 'string' ? {} : { detail: 'transport' }\n );\n }\n const headers: Array<[string, string]> = [];\n response.headers.forEach((value, name) => {\n headers.push([name, value]);\n });\n const body = chunks(response.body, options.bodyIdleMs ?? BODY_IDLE_MS);\n return {\n ...(response.redirected ? { url: response.url, redirected: true } : {}),\n ...(response.type === 'opaqueredirect' ? { opaqueRedirect: true as const } : {}),\n status: response.status,\n statusText: response.statusText,\n headers,\n body,\n cancel: async () => {\n await body.return(undefined);\n await response.body?.cancel().catch(() => undefined);\n },\n };\n },\n };\n}\n\nexport interface TransportPeer {\n postMessage(message: TransportReply, transfer?: Transferable[]): void;\n}\n\nexport interface TransportServer {\n answer(call: TransportCall): void;\n close(): void;\n}\n\ninterface Flow {\n inflight: number;\n closing: boolean;\n dropped: boolean;\n deadline(): void;\n wake?: () => void;\n}\n\nfunction uploadsFor(peer: TransportPeer) {\n const pulls = new Map<number, (call: TransportCall) => void>();\n const of = (nid: number, signal: AbortSignal): AsyncIterable<Uint8Array> => ({\n async *[Symbol.asyncIterator]() {\n for (;;) {\n signal.throwIfAborted();\n const got = await new Promise<TransportCall>((resolve, reject) => {\n const stop = () => reject(signal.reason);\n signal.addEventListener('abort', stop, { once: true });\n pulls.set(nid, (call) => {\n signal.removeEventListener('abort', stop);\n resolve(call);\n });\n peer.postMessage({ net: 'body-pull', nid });\n }).finally(() => pulls.delete(nid));\n if (got.net === 'body-end') return;\n if (got.net === 'body-error') throw new Error(got.message);\n if (got.net === 'body-chunk') yield got.bytes;\n }\n },\n });\n return { of, answer: (call: TransportCall) => pulls.get(call.nid)?.(call) };\n}\n\nfunction headOf(nid: number, response: RealmTransportResponse): TransportReply {\n return {\n net: 'head',\n nid,\n ...(response.url !== undefined ? { url: response.url } : {}),\n ...(response.redirected !== undefined ? { redirected: response.redirected } : {}),\n ...(response.redirects ? { redirects: response.redirects } : {}),\n ...(response.opaqueRedirect ? { opaqueRedirect: true } : {}),\n status: response.status,\n statusText: response.statusText,\n headers: response.headers,\n };\n}\n\nfunction requestOf(\n call: Extract<TransportCall, { net: 'fetch' }>,\n signal: AbortSignal,\n uploads: ReturnType<typeof uploadsFor>\n): RealmTransportRequest {\n const { url, method, headers, streamed, body, redirect, nid } = call;\n return {\n url,\n method,\n headers,\n ...(streamed ? { bodyStream: uploads.of(nid, signal) } : body ? { body } : {}),\n ...(redirect !== undefined ? { redirect } : {}),\n signal,\n };\n}\n\nexport function serveTransport(\n peer: TransportPeer,\n transport: RealmTransport,\n {\n closeWaitMs = CLOSE_WAIT_MS,\n attributed = false,\n }: { closeWaitMs?: number; attributed?: boolean } = {}\n): TransportServer {\n const open = new Map<\n number,\n { abort: AbortController; body?: AsyncIterator<Uint8Array>; response?: RealmTransportResponse }\n >();\n const fail = (nid: number, e: unknown) => {\n open.delete(nid);\n const { status, code, detail } = e as { status?: unknown; code?: unknown; detail?: unknown };\n peer.postMessage({\n net: 'error',\n nid,\n message: e instanceof Error ? e.message : String(e),\n ...(typeof status === 'number' ? { status } : {}),\n ...(typeof code === 'string' ? { code } : {}),\n ...(detail === 'transport' ? { detail } : {}),\n });\n };\n const uploads = uploadsFor(peer);\n const start = async (call: Extract<TransportCall, { net: 'fetch' }>) => {\n const abort = new AbortController();\n const entry: { abort: AbortController; body?: AsyncIterator<Uint8Array> } = { abort };\n open.set(call.nid, entry);\n try {\n const response = await transport.fetch(\n requestOf(call, abort.signal, uploads),\n attributed ? call.owner : undefined,\n attributed ? call.stamp : undefined\n );\n if (!open.has(call.nid)) {\n await response.cancel();\n return;\n }\n open.set(call.nid, { abort, body: response.body[Symbol.asyncIterator](), response });\n peer.postMessage(headOf(call.nid, response));\n } catch (e) {\n fail(call.nid, e);\n }\n };\n const sockets = new Map<number, RealmWebSocket>();\n const credit = new Map<number, Flow>();\n const refill = (nid: number, n: number, closing = false) => {\n const flow = credit.get(nid);\n if (!flow) return;\n flow.inflight -= n;\n if (closing && !flow.closing) {\n flow.closing = true;\n flow.deadline();\n }\n flow.wake?.();\n };\n const openSocket = async (call: Extract<TransportCall, { net: 'ws-open' }>) => {\n const abort = new AbortController();\n open.set(call.nid, { abort });\n try {\n if (!transport.websocket) throw new Error(NO_WEBSOCKET);\n const socket = await transport.websocket({\n url: call.url,\n protocols: call.protocols,\n headers: call.headers,\n signal: abort.signal,\n });\n if (!open.delete(call.nid)) {\n socket.close(1000, 'cancelled');\n return;\n }\n sockets.set(call.nid, socket);\n peer.postMessage({ net: 'ws-opened', nid: call.nid, protocol: socket.protocol });\n void relay(call.nid, socket);\n } catch (e) {\n fail(call.nid, e);\n }\n };\n const relay = async (nid: number, socket: RealmWebSocket) => {\n let ending: { code: number; reason: string };\n let late!: () => void;\n const unanswered = new Promise<'late'>((resolve) => {\n late = () => resolve('late');\n });\n const flow: Flow = {\n inflight: 0,\n closing: false,\n dropped: false,\n deadline: () =>\n AbortSignal.timeout(closeWaitMs).addEventListener('abort', late, { once: true }),\n };\n credit.set(nid, flow);\n const timedOut = { code: 1006, reason: 'the far end did not answer the close' };\n let oversize = false;\n try {\n const messages = socket.messages[Symbol.asyncIterator]();\n for (;;) {\n const next = await Promise.race([messages.next(), unanswered]);\n if (next === 'late' || next.done) break;\n const data = next.value;\n if (flow.dropped) continue;\n if (payloadSize(data) > MESSAGE_LIMIT) {\n oversize = true;\n break;\n }\n if (typeof data === 'string') peer.postMessage({ net: 'ws-message', nid, data });\n else {\n const bytes = fresh(data);\n peer.postMessage({ net: 'ws-message', nid, data: bytes }, [bytes.buffer]);\n }\n flow.inflight += payloadSize(data);\n while (flow.inflight > INBOUND_LIMIT && !flow.closing) {\n await new Promise<void>((resolve) => {\n flow.wake = resolve;\n });\n }\n }\n if (oversize) socket.close(1000, 'a message is too big');\n ending = oversize\n ? { code: 1009, reason: `a message is over ${MESSAGE_LIMIT} bytes` }\n : await Promise.race([socket.closed, unanswered.then(() => timedOut)]);\n } catch (e) {\n socket.close(1000, 'the relay failed');\n ending = { code: 1011, reason: e instanceof Error ? e.message : String(e) };\n }\n sockets.delete(nid);\n credit.delete(nid);\n peer.postMessage({ net: 'ws-closed', nid, ...ending });\n };\n const sendOn = async (call: Extract<TransportCall, { net: 'ws-send' }>) => {\n const socket = sockets.get(call.nid);\n if (!socket) return;\n socket.send(call.data);\n while (socket.buffered > SEND_BUFFER && sockets.has(call.nid)) {\n await new Promise((resolve) => setTimeout(resolve, 10));\n }\n peer.postMessage({ net: 'ws-acked', nid: call.nid, n: payloadSize(call.data) });\n };\n const read = async (nid: number) => {\n const body = open.get(nid)?.body;\n if (!body) return;\n try {\n const next = await body.next();\n if (next.done) {\n open.delete(nid);\n peer.postMessage({ net: 'end', nid });\n } else {\n const bytes = fresh(next.value);\n peer.postMessage({ net: 'chunk', nid, bytes }, [bytes.buffer]);\n }\n } catch (e) {\n fail(nid, e);\n }\n };\n const drop = (nid: number) => {\n sockets.get(nid)?.close(1000, 'cancelled');\n const flow = credit.get(nid);\n if (flow) flow.dropped = true;\n refill(nid, 0, true);\n const entry = open.get(nid);\n open.delete(nid);\n entry?.abort.abort();\n void entry?.response?.cancel().catch(() => undefined);\n };\n return {\n answer(call) {\n if (call.net === 'fetch') void start(call);\n else if (call.net === 'body-chunk' || call.net === 'body-end' || call.net === 'body-error') {\n uploads.answer(call);\n } else if (call.net === 'read') void read(call.nid);\n else if (call.net === 'ws-open') void openSocket(call);\n else if (call.net === 'ws-send') void sendOn(call);\n else if (call.net === 'ws-close') {\n sockets.get(call.nid)?.close(call.code, call.reason);\n refill(call.nid, 0, true);\n } else if (call.net === 'ws-consumed') refill(call.nid, call.n);\n else drop(call.nid);\n },\n close() {\n for (const nid of [...open.keys(), ...sockets.keys()]) drop(nid);\n },\n };\n}\n", "import type { SealedCaller } from '../sealed.ts';\nimport type {\n HeaderList,\n RealmRedirectHop,\n RealmRedirectPolicy,\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 streamed?: true;\n redirect?: RealmRedirectPolicy;\n owner?: number;\n stamp?: SealedCaller;\n }\n | { net: 'body-chunk'; nid: number; bytes: Uint8Array }\n | { net: 'body-end'; nid: number }\n | { net: 'body-error'; nid: number; message: string }\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 | {\n net: 'head';\n nid: number;\n status: number;\n statusText: string;\n headers: HeaderList;\n url?: string;\n redirected?: boolean;\n redirects?: readonly RealmRedirectHop[];\n opaqueRedirect?: true;\n }\n | { net: 'chunk'; nid: number; bytes: Uint8Array }\n | { net: 'body-pull'; nid: number }\n | { net: 'end'; nid: number }\n | {\n net: 'error';\n nid: number;\n message: string;\n status?: number;\n code?: string;\n detail?: 'transport';\n }\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 readonly detail: 'transport' | undefined;\n\n constructor(message: string, status?: number, code?: string, detail?: unknown) {\n super(message);\n this.status = status;\n this.code = code;\n this.detail = detail === 'transport' ? detail : undefined;\n }\n}\n\nexport function unfollowed(redirect?: RealmRedirectPolicy): boolean {\n return redirect !== undefined && redirect !== 'follow';\n}\n\nfunction honors(traits: RealmTransportTraits, redirect?: RealmRedirectPolicy): boolean {\n if (traits.redirectPolicy === true) return true;\n const hops = traits.redirectHops as unknown;\n const raw = traits.manualRedirects === true && (hops === undefined || hops === false);\n return redirect === 'manual' && raw;\n}\n\nfunction refused(message: string): TransportError {\n return new TransportError(message, 502, undefined, 'transport');\n}\n\ninterface Waiter {\n resolve(reply: TransportReply): void;\n reject(error: Error): void;\n}\n\nexport class RemoteTransport implements RealmTransport {\n 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 readonly uploads = new Map<number, AsyncIterator<Uint8Array>>();\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 if (reply.net === 'body-pull') {\n void this.pull(reply.nid);\n return;\n }\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, reply.detail));\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 private async pull(nid: number): Promise<void> {\n const upload = this.uploads.get(nid);\n if (!upload) {\n this.port.postMessage({ net: 'body-error', nid, message: 'the request body is gone' });\n return;\n }\n try {\n const next = await upload.next();\n if (next.done) {\n this.uploads.delete(nid);\n this.port.postMessage({ net: 'body-end', nid });\n } else this.port.postMessage({ net: 'body-chunk', nid, bytes: next.value });\n } catch (e) {\n this.uploads.delete(nid);\n this.port.postMessage({\n net: 'body-error',\n nid,\n message: e instanceof Error ? e.message : String(e),\n });\n }\n }\n\n private dropUpload(nid: number): void {\n const upload = this.uploads.get(nid);\n this.uploads.delete(nid);\n void upload?.return?.().catch(() => undefined);\n }\n\n fail(error: Error): void {\n this.failure = error;\n for (const nid of [...this.uploads.keys()]) this.dropUpload(nid);\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(\n request: RealmTransportRequest,\n owner?: number,\n stamp?: SealedCaller\n ): Promise<RealmTransportResponse> {\n const nid = ++this.nextId;\n const { signal, redirect } = request;\n signal.throwIfAborted();\n if (unfollowed(redirect) && !honors(this.traits, redirect)) {\n throw refused(`this transport cannot honor redirect: ${redirect}`);\n }\n let finished = false;\n const abort = () => {\n finished = true;\n this.dropUpload(nid);\n this.cancel(nid);\n };\n signal.addEventListener('abort', abort, { once: true });\n const finish = () => {\n this.dropUpload(nid);\n if (finished) return;\n finished = true;\n signal.removeEventListener('abort', abort);\n };\n if (request.bodyStream) this.uploads.set(nid, request.bodyStream[Symbol.asyncIterator]());\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.bodyStream\n ? { streamed: true as const }\n : request.body\n ? { body: request.body }\n : {}),\n ...(redirect !== undefined ? { redirect } : {}),\n ...(owner !== undefined ? { owner } : {}),\n ...(stamp ? { stamp } : {}),\n });\n } catch (e) {\n finish();\n throw e;\n }\n const { status, statusText, headers, url, redirected, redirects, opaqueRedirect } =\n 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 if (unfollowed(redirect) && (redirected || redirects?.length)) {\n await cancel();\n throw refused(`this transport followed a redirect despite redirect: ${redirect}`);\n }\n return {\n ...(url !== undefined ? { url } : {}),\n ...(redirected !== undefined ? { redirected } : {}),\n ...(redirects ? { redirects } : {}),\n ...(opaqueRedirect ? { opaqueRedirect } : {}),\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", "import type { UsersMode } from '../fs/types.ts';\nimport 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, 13];\n\nexport interface ClientHello {\n protocol: readonly [number, number];\n lock?: string;\n requests?: Record<string, { group?: string; users?: Array<string | number> }>;\n}\n\nexport interface KernelHello {\n protocol: readonly [number, number];\n lock?: string;\n traits?: RealmTransportTraits;\n users?: UsersMode;\n error?: string;\n}\n\nexport interface SpawnRequestOptions {\n cwd?: string;\n user?: string | number;\n env?: Record<string, string>;\n stdin?: Uint8Array;\n pgid?: number;\n tag?: string;\n}\n\nexport interface TerminalRequestOptions {\n cwd?: string;\n user?: string | number;\n env?: Record<string, string>;\n cols?: number;\n rows?: number;\n tag?: string;\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: 'serve-facade'; name: string }\n | { op: 'unserve-facade'; 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 signal?: string;\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' | 'T' | 'Z';\n memory: number;\n rss?: number;\n utime?: number;\n stime?: number;\n uid?: number;\n gid?: number;\n tag?: string;\n tags?: string[];\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 { embedderAnswerer } from '../embedder-relay.ts';\nimport { type FacadeOpen, serveFacadePort } from '../facade/port.ts';\nimport type { FacadeHook } from '../facade/types.ts';\nimport type { FsStat, UsersMode } from '../fs/types.ts';\nimport type { WatchChange } from '../fs/watch.ts';\nimport { type EmbedderHook, type EmbedderKindPolicy, kindsOf } from '../kernel/embedder.ts';\nimport { RemoteTransport, type TransportReply } from '../kernel/net/remote-transport.ts';\nimport type {\n RealmTransport,\n RealmTransportRequest,\n RealmTransportResponse,\n RealmTransportTraits,\n} from '../kernel/net/transport.ts';\nimport { quiet } from '../kernel/signals.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 requests?: EmbedderHook;\n}\n\nexport interface SpawnOptions {\n cwd?: string;\n user?: string | number;\n env?: Record<string, string>;\n stdin?: string | Uint8Array;\n group?: 'new';\n pgid?: number;\n tag?: string;\n onStdout?: (bytes: Uint8Array) => void;\n onStderr?: (bytes: Uint8Array) => void;\n}\n\nexport interface ClientEnded {\n status: number;\n signal?: string;\n}\n\nexport interface SpawnedProcess {\n readonly pid: number;\n readonly pgid: number;\n readonly exited: Promise<number>;\n readonly ended: Promise<ClientEnded>;\n signal(name?: string): Promise<void>;\n}\n\nexport interface ClientRunOptions {\n cwd?: string;\n user?: string | number;\n env?: Record<string, string>;\n stdin?: string | Uint8Array;\n tag?: string;\n onStdout?: (text: string) => void;\n onStderr?: (text: string) => void;\n}\n\nexport interface ClientRunResult {\n pid: number;\n status: number;\n signal?: string;\n stdout: string;\n stderr: string;\n}\n\nexport interface ClientTerminalOptions {\n cwd?: string;\n user?: string | number;\n env?: Record<string, string>;\n cols?: number;\n rows?: number;\n tag?: string;\n onData?: (bytes: Uint8Array) => void;\n}\n\nexport interface ClientTerminal {\n readonly pid: number;\n readonly exited: Promise<number>;\n readonly ended: Promise<ClientEnded>;\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 users: UsersMode;\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 serveFacade(name: string, hook: FacadeHook): Promise<{ close(): void }>;\n onTraits(listener: (traits: RealmTransportTraits) => void): () => 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 ended?: (signal: string | undefined) => 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\n readonly traitsListeners = new Set<(traits: RealmTransportTraits) => void>();\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 readonly facadeHooks = new Map<number, FacadeHook>();\n private readonly facadeOpen = 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 close of [...this.facadeOpen]) close();\n this.facadeOpen.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 requests: { handle(data: unknown): boolean } | undefined;\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 facadeOpen?: FacadeOpen['facadeOpen'];\n port?: CdpOpen['port'];\n traits?: RealmTransportTraits;\n id?: number;\n }): void {\n if (this.requests?.handle(data)) return;\n if (data.traits && data.id === undefined) {\n if (this.remote) this.remote.traits = data.traits;\n for (const listener of [...this.traitsListeners]) listener(data.traits);\n return;\n }\n if (data.cdpOpen && data.port) {\n this.openCdp(data as CdpOpen);\n return;\n }\n if (data.facadeOpen && data.port) {\n this.openFacade(data as FacadeOpen);\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 call.ended?.(reply.signal);\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 private openFacade({ facadeOpen: { registration, ...request }, port }: FacadeOpen): void {\n const hook = registration === undefined ? undefined : this.facadeHooks.get(registration);\n if (!hook || this.failure) {\n port.postMessage({ error: 'this client no longer serves the facade' });\n port.close();\n return;\n }\n const close = serveFacadePort(port, hook, request, () => this.facadeOpen.delete(close));\n this.facadeOpen.add(close);\n }\n}\n\nasync function serveFacadeOn(\n channel: Channel,\n name: string,\n hook: FacadeHook\n): Promise<{ close(): void }> {\n if (typeof hook !== 'function') throw new TypeError('serveFacade: hook must be a function');\n await since(channel, 11, 'facade serving', async () => {});\n const { id, done } = channel.request({ op: 'serve-facade' as const, name });\n channel.facadeHooks.set(id, hook);\n try {\n await done;\n } catch (error) {\n channel.facadeHooks.delete(id);\n throw error;\n }\n return {\n close: () => {\n if (!channel.facadeHooks.delete(id)) return;\n void channel.call({ op: 'unserve-facade', registration: id }).catch(() => undefined);\n },\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 if (opts.user !== undefined) await since(channel, 8, 'spawn as a user', async () => {});\n if (opts.tag !== undefined) await since(channel, 12, 'a tag per spawn', async () => {});\n const started = Promise.withResolvers<number>();\n let endedBy: string | undefined;\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 ended: (signal) => (endedBy = signal),\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 ended: endedOf(done, () => endedBy),\n signal: async (name = 'SIGTERM') =>\n void (await channel.call({ op: 'kill', pid: -pgid, signal: name })),\n };\n}\n\nfunction endedOf(done: Promise<unknown>, signal: () => string | undefined): Promise<ClientEnded> {\n return quiet(\n done.then((status) => {\n const by = signal();\n return { status: status as number, ...(by ? { signal: by } : {}) };\n })\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, signal } = await child.ended;\n const text = (fd: 1 | 2) => new TextDecoder().decode(concat(chunks[fd]));\n return {\n pid: child.pid,\n status,\n ...(signal ? { signal } : {}),\n stdout: text(1),\n stderr: text(2),\n };\n}\n\nasync function terminalOn(\n channel: Channel,\n argv: string[],\n opts: ClientTerminalOptions\n): Promise<ClientTerminal> {\n const { onData, ...options } = opts;\n if (opts.user !== undefined) await since(channel, 8, 'a terminal as a user', async () => {});\n if (opts.tag !== undefined) await since(channel, 12, 'a tag per terminal', async () => {});\n let listener = onData ?? null;\n const backlog: Uint8Array[] = [];\n const started = Promise.withResolvers<number>();\n let endedBy: string | undefined;\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 ended: (signal) => (endedBy = signal),\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 ended: endedOf(done, () => endedBy),\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 requests?: Record<string, EmbedderKindPolicy>\n): Promise<KernelHello> {\n channel.post({\n hello: { protocol: PROTOCOL, ...(lock ? { lock } : {}), ...(requests ? { requests } : {}) },\n });\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 requests = options.requests;\n if (requests) channel.requests = embedderAnswerer(port, () => requests);\n const hello = await greet(\n channel,\n own.name,\n options.timeoutMs ?? 10_000,\n requests ? kindsOf(requests) : undefined\n );\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 users: hello.users ?? 'off',\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 serveFacade: (name, hook) => serveFacadeOn(channel, name, hook),\n onTraits(listener) {\n channel.traitsListeners.add(listener);\n return () => channel.traitsListeners.delete(listener);\n },\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", "import {\n DRIVER_PROTOCOL,\n type DriverAttr,\n type DriverCapabilities,\n type DriverEntry,\n type DriverOwner,\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 DriverOwner,\n DriverStatfs,\n MountRequestInfo,\n} from './protocol.ts';\n\nimport { fresh } from '../bytes.ts';\n\nexport interface OpenFlags {\n write: boolean;\n create: boolean;\n truncate: boolean;\n exclusive: boolean;\n ifMatch?: string;\n owner?: DriverOwner;\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, owner?: DriverOwner): Promise<void>;\n rmdir(path: string): Promise<void>;\n unlink(path: string): Promise<void>;\n rename(from: string, to: string): Promise<void>;\n link?(from: string, to: string): Promise<void>;\n symlink?(target: string, path: string, owner?: DriverOwner): Promise<void>;\n mkfifo?(path: string, owner?: DriverOwner): Promise<void>;\n readlink?(path: string): Promise<string>;\n setattr?(path: string, attr: DriverSetAttr): Promise<void>;\n statfs?(): Promise<DriverStatfs>;\n}\n\nexport interface DriverSetAttr {\n mode?: number;\n mtime?: number;\n atime?: number;\n size?: number;\n uid?: number;\n gid?: number;\n}\n\nfunction ownerOf(req: DriverOwner): DriverOwner | undefined {\n const owner = {\n ...(req.uid !== undefined ? { uid: req.uid } : {}),\n ...(req.gid !== undefined ? { gid: req.gid } : {}),\n ...(req.mode !== undefined ? { mode: req.mode } : {}),\n };\n return Object.keys(owner).length > 0 ? owner : undefined;\n}\n\nfunction withOwner<T extends object>(base: T, owner: DriverOwner | undefined): T {\n return owner ? { ...base, owner } : base;\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\nconst SET_ATTRS = ['mode', 'mtime', 'atime', 'size', 'uid', 'gid'] as const;\n\nfunction setAttrOf(req: DriverSetAttr): DriverSetAttr {\n const attr: DriverSetAttr = {};\n for (const key of SET_ATTRS) if (req[key] !== undefined) attr[key] = req[key];\n return attr;\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(\n req.path,\n withOwner(\n {\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 ownerOf(req)\n )\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 ownerOf(req) ? h.mkdir(req.path, ownerOf(req)) : 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 'link':\n if (!h.link) throw fsError('EPERM', 'this file system has no hard links');\n return h.link(req.from, req.to);\n case 'mkfifo':\n if (!h.mkfifo) throw fsError('EPERM', 'this file system has no FIFOs');\n return ownerOf(req) ? h.mkfifo(req.path, ownerOf(req)) : h.mkfifo(req.path);\n case 'symlink':\n if (!h.symlink) throw fsError('EPERM', 'this file system has no symlinks');\n return ownerOf(req)\n ? h.symlink(req.target, req.path, ownerOf(req))\n : 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, setAttrOf(req));\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 : fresh(result);\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 { type FilesystemHandlers, fsError, type OpenFlags, serveFilesystem } from './driver.ts';\nimport { type MediumHandlers, mediumSlot } from './medium.ts';\nimport type { MountSpec, OpenedDriver } from './mount-fs.ts';\nimport type { DriverAttr, DriverCapabilities, DriverEntry, DriverStatfs } from './protocol.ts';\n\nexport interface HostfsGrant {\n url: string;\n token: string;\n readonly?: boolean;\n capabilities?: DriverCapabilities;\n}\n\nexport interface HostfsPortGrant {\n port: MessagePort;\n token?: string;\n capabilities?: DriverCapabilities;\n}\n\nexport type HostfsGrantHook = (\n source: string,\n options: { readonly: boolean }\n) => Promise<HostfsGrant | HostfsPortGrant>;\n\nexport type FetchLike = (url: string, init: RequestInit) => Promise<Response>;\n\nexport interface HostfsEvent {\n paths?: string[];\n all?: boolean;\n ping?: number;\n}\n\nexport interface HostfsTransport {\n readonly capabilities: DriverCapabilities;\n readonly token: string;\n readonly maxIo: number;\n readonly gone?: boolean;\n retire?(why: string): void;\n cleanup?(op: string, body: Record<string, unknown>): Promise<unknown>;\n call<T>(op: string, body?: Record<string, unknown>, handle?: boolean): Promise<T>;\n read(fh: number, offset: number, size: number, ifMatch?: string): Promise<Uint8Array>;\n write(fh: number, offset: number, bytes: Uint8Array): Promise<void>;\n watch(\n signal: AbortSignal,\n onEvent: (event: HostfsEvent) => void,\n onOpen?: () => void\n ): Promise<void>;\n}\n\nexport type HostfsConnect = (\n source: string,\n options: { readonly: boolean }\n) => Promise<HostfsTransport>;\n\nexport const HOSTFS_IO = 16 * 1024 * 1024;\n\nconst codeOf = (err: unknown) => (err as { code?: unknown } | null)?.code;\n\nexport const unreachable = (err: unknown) => codeOf(err) === 'ENOTCONN';\n\nfunction rel(path: string): string {\n return path.replace(/^\\/+/, '');\n}\n\nexport class HostfsClient implements HostfsTransport {\n private grant: HostfsGrant;\n private readonly regrant: () => Promise<HostfsGrant>;\n private readonly fetch: FetchLike;\n\n constructor(grant: HostfsGrant, regrant: () => Promise<HostfsGrant>, fetch: FetchLike) {\n this.grant = grant;\n this.regrant = regrant;\n this.fetch = fetch;\n }\n\n get capabilities(): DriverCapabilities {\n return this.grant.capabilities ?? {};\n }\n\n get token(): string {\n return this.grant.token;\n }\n\n get maxIo(): number {\n return this.capabilities.maxIo ?? HOSTFS_IO;\n }\n\n private retired: string | undefined;\n private readonly stop = new AbortController();\n\n get gone(): boolean {\n return this.retired !== undefined;\n }\n\n retire(why: string): void {\n this.retired ??= why;\n this.stop.abort();\n }\n\n private async send(\n path: string,\n init: RequestInit,\n handle = false,\n retried = false,\n cleanup = false\n ): Promise<Response> {\n if (this.retired && !cleanup) throw fsError('ENOTCONN', this.retired);\n const stop = cleanup ? undefined : this.stop.signal;\n const signal =\n init.signal && stop ? AbortSignal.any([init.signal, stop]) : (init.signal ?? stop);\n let response: Response;\n try {\n response = await this.fetch(`${this.grant.url}${path}`, {\n ...init,\n ...(signal ? { signal } : {}),\n credentials: 'omit',\n headers: {\n ...(init.headers as Record<string, string>),\n 'X-Hostfs-Token': this.grant.token,\n },\n });\n } catch (err) {\n throw fsError('ENOTCONN', `the host proxy is unreachable: ${(err as Error).message}`);\n }\n if (response.ok) return response;\n if (response.headers.get('X-Proxy-Error')) {\n await response.body?.cancel();\n if (retried || response.status !== 403) {\n throw fsError('EACCES', `the host proxy refused this folder (${response.status})`);\n }\n this.grant = await this.regrant();\n if (handle)\n throw fsError('ESTALE', 'the folder was granted again, so its open files are gone');\n return this.send(path, init, false, true);\n }\n const errno = response.headers.get('X-Hostfs-Errno') ?? 'EIO';\n const body = (await response.json().catch(() => ({}))) as { message?: unknown };\n throw fsError(errno, typeof body.message === 'string' ? body.message : errno);\n }\n\n async call<T>(op: string, body: Record<string, unknown> = {}, handle = false): Promise<T> {\n const response = await this.send(\n '/api/hostfs',\n {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ op, ...body }),\n },\n handle\n );\n return (await response.json()) as T;\n }\n\n async cleanup(op: string, body: Record<string, unknown>): Promise<unknown> {\n const response = await this.send(\n '/api/hostfs',\n {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ op, ...body }),\n },\n true,\n false,\n true\n );\n return response.json().catch(() => null);\n }\n\n async read(fh: number, offset: number, size: number, ifMatch?: string): Promise<Uint8Array> {\n const response = await this.send(\n '/api/hostfs',\n {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ op: 'read', fh, offset, size, ...(ifMatch ? { ifMatch } : {}) }),\n },\n true\n );\n return new Uint8Array(await response.arrayBuffer());\n }\n\n async write(fh: number, offset: number, bytes: Uint8Array): Promise<void> {\n const response = await this.send(\n '/api/hostfs/write',\n {\n method: 'PUT',\n headers: {\n 'Content-Type': 'application/octet-stream',\n 'X-Hostfs-Request': JSON.stringify({ fh, offset }),\n },\n body: bytes as BodyInit,\n },\n true\n );\n await response.body?.cancel();\n }\n\n async watch(\n signal: AbortSignal,\n onEvent: (event: HostfsEvent) => void,\n onOpen: () => void = () => undefined\n ): Promise<void> {\n const response = await this.send('/api/hostfs/watch', { method: 'POST', signal });\n onOpen();\n const reader = (response.body as ReadableStream<Uint8Array>).getReader();\n const decoder = new TextDecoder();\n let buffered = '';\n try {\n for (;;) {\n const { done, value } = await reader.read();\n if (done) return;\n buffered += decoder.decode(value, { stream: true });\n let end = buffered.indexOf('\\n');\n while (end >= 0) {\n const line = buffered.slice(0, end).trim();\n buffered = buffered.slice(end + 1);\n if (line) onEvent(JSON.parse(line) as HostfsEvent);\n end = buffered.indexOf('\\n');\n }\n }\n } catch (err) {\n if (signal.aborted) return;\n throw fsError('ENOTCONN', `the host proxy's watch broke: ${(err as Error).message}`);\n } finally {\n reader.releaseLock();\n }\n }\n}\n\ninterface Remote {\n client: HostfsTransport;\n token: string;\n fh: number;\n etag: string | undefined;\n restore: Restore | undefined;\n}\n\ntype Restore = { path: string; mode: number; was: DriverAttr };\n\nexport const RESTORE_AGAIN_MS = 30_000;\n\nexport function hostfsHandlers(\n current: () => HostfsTransport,\n againMs = RESTORE_AGAIN_MS\n): MediumHandlers {\n const handles = new Map<number, Remote>();\n let nextFh = 0;\n const fresh = (remote: Remote): Remote => {\n if (remote.client.token === remote.token && !remote.client.gone) return remote;\n throw fsError('ESTALE', 'the folder was granted again, so this open file is gone');\n };\n const live = (fh: number): Remote => {\n const remote = handles.get(fh);\n if (!remote) throw fsError('EBADF', `handle ${fh}`);\n return fresh(remote);\n };\n const call = <T>(op: string, body: Record<string, unknown> = {}) => current().call<T>(op, body);\n const same = (was: DriverAttr, mode: number, seen: DriverAttr | null) =>\n seen?.mode === (mode | 0o200) &&\n (was.ino !== undefined && seen.ino !== undefined\n ? seen.ino === was.ino\n : seen.size === was.size && seen.mtime === was.mtime);\n const settle = (client: HostfsTransport, { was, ...restore }: Restore) =>\n client.call('setattr', restore).catch((err: unknown) => {\n if (!client.gone || !client.cleanup) throw err;\n void client.cleanup('setattr', restore).catch(() => {});\n const timer = setTimeout(async () => {\n const seen = (await client\n .cleanup?.('stat', { path: restore.path })\n .catch(() => null)) as DriverAttr | null;\n if (same(was, restore.mode, seen))\n void client.cleanup?.('setattr', restore).catch(() => {});\n }, againMs) as { unref?: () => void };\n timer.unref?.();\n });\n async function writable(client: HostfsTransport, path: string, flags: OpenFlags) {\n const { ifMatch: _, ...asked } = flags;\n const opening = () =>\n client.call<{ fh: number; attr?: DriverAttr }>('open', { path: rel(path), ...asked });\n try {\n return { opened: await opening(), restore: undefined };\n } catch (err) {\n if (!flags.write || codeOf(err) !== 'EACCES') throw err;\n const was = await client.call<DriverAttr>('stat', { path: rel(path) });\n const mode = was.mode ?? 0;\n if (mode & 0o200) throw err;\n const restore = { path: rel(path), mode, was };\n const opened = await client\n .call('setattr', { path: rel(path), mode: mode | 0o200 })\n .then(opening)\n .catch(async (again: unknown) => {\n await settle(client, restore).catch(() => {});\n throw again;\n });\n return { opened, restore };\n }\n }\n const handlers: MediumHandlers = {\n getattr: async (path) => await call<DriverAttr>('stat', { path: rel(path) }),\n async readdir(path) {\n const { entries } = await call<{ entries: Array<{ name: string; attr: DriverAttr }> }>(\n 'list',\n { path: rel(path) }\n );\n return entries.map(({ name, attr }): DriverEntry => ({ name, kind: attr.kind, attr }));\n },\n async open(path: string, flags: OpenFlags) {\n const client = current();\n const token = client.token;\n const { opened, restore } = await writable(client, path, flags);\n if (flags.ifMatch !== undefined && opened.attr?.etag !== flags.ifMatch) {\n await client.call('release', { fh: opened.fh }, true);\n throw fsError('ESTALE', `${path} changed on the host while it was being read`);\n }\n handles.set(++nextFh, {\n client,\n token,\n fh: opened.fh,\n etag: flags.write ? undefined : opened.attr?.etag,\n restore,\n });\n return nextFh;\n },\n async read(fh, offset, size) {\n const remote = live(fh);\n return remote.client.read(\n remote.fh,\n offset,\n Math.min(size, remote.client.maxIo),\n remote.etag\n );\n },\n async write(fh, offset, bytes) {\n const remote = live(fh);\n const most = remote.client.maxIo;\n for (let at = 0; at < bytes.length; at += most) {\n await remote.client.write(remote.fh, offset + at, bytes.subarray(at, at + most));\n }\n },\n async release(fh) {\n const remote = handles.get(fh);\n if (!remote) throw fsError('EBADF', `handle ${fh}`);\n handles.delete(fh);\n try {\n await fresh(remote).client.call('release', { fh: remote.fh }, true);\n } finally {\n if (remote.restore) await settle(current(), remote.restore);\n }\n },\n mkdir: async (path) => void (await call('mkdir', { path: rel(path) })),\n rmdir: async (path) => void (await call('rmdir', { path: rel(path) })),\n unlink: async (path) => void (await call('unlink', { path: rel(path) })),\n rename: async (from, to) => void (await call('rename', { from: rel(from), to: rel(to) })),\n symlink: async (target, path) => void (await call('symlink', { target, path: rel(path) })),\n readlink: async (path) =>\n (await call<{ target: string }>('readlink', { path: rel(path) })).target,\n async setattr(path, { size, ...change }) {\n if (size !== undefined && !current().capabilities.ranges) await resize(handlers, path, size);\n else if (size !== undefined) change = { ...change, size } as typeof change;\n if (Object.keys(change).length > 0) await call('setattr', { path: rel(path), ...change });\n },\n statfs: () => call<DriverStatfs>('statfs'),\n };\n return handlers;\n}\n\nconst KEEP: OpenFlags = { write: false, create: false, truncate: false, exclusive: false };\n\nasync function resize(h: FilesystemHandlers, path: string, size: number): Promise<void> {\n const was = (await h.getattr(path)).size;\n if (size === was) return;\n const kept: Uint8Array[] = [];\n if (size < was && size > 0) {\n const fh = await h.open(path, KEEP);\n try {\n for (let at = 0; at < size; ) {\n const bytes = await h.read(fh, at, size - at);\n if (bytes.length === 0) break;\n kept.push(bytes);\n at += bytes.length;\n }\n } finally {\n await h.release(fh);\n }\n }\n const fh = await h.open(path, { ...KEEP, write: true, truncate: size < was });\n try {\n if (size > was) await h.write(fh, size - 1, new Uint8Array(1));\n let at = 0;\n for (const bytes of kept) {\n await h.write(fh, at, bytes);\n at += bytes.length;\n }\n } finally {\n await h.release(fh);\n }\n}\n\nexport interface WatchLoop {\n connect(): Promise<HostfsTransport>;\n up(client: HostfsTransport): void;\n event(event: HostfsEvent): void;\n down(): void;\n silenceMs?: number;\n backoffMs?: [number, number];\n connectMs?: number;\n}\n\nfunction sleep(ms: number, signal: AbortSignal): Promise<void> {\n return new Promise((resolve) => {\n const done = () => {\n clearTimeout(timer);\n signal.removeEventListener('abort', done);\n resolve();\n };\n const timer = setTimeout(done, ms);\n signal.addEventListener('abort', done);\n });\n}\n\nexport interface Watching {\n ready: Promise<void>;\n kick(): void;\n}\n\nexport function keepWatching(loop: WatchLoop, signal: AbortSignal): Watching {\n const silenceMs = loop.silenceMs ?? 45_000;\n const [first, most] = loop.backoffMs ?? [1000, 30_000];\n const ready = Promise.withResolvers<void>();\n const capped = setTimeout(ready.resolve, loop.connectMs ?? 15_000);\n const uncap = () => clearTimeout(capped);\n void ready.promise.then(uncap);\n signal.addEventListener('abort', uncap, { once: true });\n let wait = first;\n let up = false;\n let current: AbortController | undefined;\n async function session(): Promise<boolean> {\n const session = new AbortController();\n current = session;\n const stop = () => session.abort();\n signal.addEventListener('abort', stop);\n let timer: ReturnType<typeof setTimeout> | undefined;\n const quiet = () => {\n clearTimeout(timer);\n timer = setTimeout(stop, silenceMs);\n };\n let opened = false;\n try {\n const client = await loop.connect();\n quiet();\n await client.watch(\n session.signal,\n (event) => {\n quiet();\n if (!event.ping) loop.event(event);\n },\n () => {\n quiet();\n opened = true;\n up = true;\n loop.up(client);\n ready.resolve();\n }\n );\n return opened;\n } catch {\n return opened;\n } finally {\n clearTimeout(timer);\n signal.removeEventListener('abort', stop);\n }\n }\n void (async () => {\n while (!signal.aborted) {\n const began = Date.now();\n const opened = await session();\n if (signal.aborted) return;\n if (opened && Date.now() - began >= first) {\n wait = first;\n continue;\n }\n if (!opened && up) {\n up = false;\n loop.down();\n }\n ready.resolve();\n await sleep(wait, signal);\n wait = Math.min(wait * 2, most);\n }\n })();\n return { ready: ready.promise, kick: () => current?.abort() };\n}\n\nexport function invalidation(event: HostfsEvent): string[] | true {\n return event.paths ?? true;\n}\n\nexport interface HostfsTiming {\n silenceMs?: number;\n backoffMs?: [number, number];\n connectMs?: number;\n requestMs?: number;\n callMs?: number;\n beatMs?: number;\n deadMs?: number;\n}\n\nexport const PORT_REQUEST_MS = 60_000;\nexport const HOSTFS_CALL_MS = 20_000;\nexport const PORT_BEAT_MS = 1000;\nexport const PORT_DEAD_MS = 10_000;\nexport const PORT_LINGER_MS = 1000;\n\nexport interface PortLiveness {\n requestMs?: number;\n beatMs?: number;\n deadMs?: number;\n lingerMs?: number;\n}\n\nexport function timed(transport: HostfsTransport, ms: number): HostfsTransport {\n const inflight = new Set<Promise<unknown>>();\n const guard = <T>(\n name: string,\n run: () => Promise<T>,\n late?: (value: T) => void,\n expire?: (running: Promise<T>) => void\n ) =>\n new Promise<T>((resolve, reject) => {\n let expired = false;\n const running = run();\n inflight.add(running);\n const done = () => inflight.delete(running);\n running.then(done, done);\n const timer = setTimeout(() => {\n expired = true;\n const why = `the host folder did not answer ${name} within ${ms} ms`;\n transport.retire?.(why);\n expire?.(running);\n reject(fsError('ENOTCONN', why));\n }, ms);\n running.then(\n (value) => {\n clearTimeout(timer);\n if (expired) late?.(value);\n resolve(value);\n },\n (err) => {\n clearTimeout(timer);\n reject(err);\n }\n );\n });\n const cleanup = async (op: string, body: Record<string, unknown>, skip?: Promise<unknown>) => {\n await Promise.allSettled([...inflight].filter((work) => work !== skip));\n return await transport.cleanup?.(op, body);\n };\n const release = (opened: unknown) => {\n const fh = (opened as { fh?: unknown } | null)?.fh;\n if (typeof fh === 'number') void cleanup('release', { fh }).catch(() => {});\n };\n return {\n get capabilities() {\n return transport.capabilities;\n },\n get token() {\n return transport.token;\n },\n get maxIo() {\n return transport.maxIo;\n },\n get gone() {\n return transport.gone;\n },\n retire: (why) => transport.retire?.(why),\n ...(transport.cleanup ? { cleanup } : {}),\n call: (op, body, handle) =>\n guard(\n op,\n () => transport.call(op, body, handle),\n op === 'open' ? release : undefined,\n op === 'release'\n ? (running) => void cleanup('release', body ?? {}, running).catch(() => {})\n : undefined\n ),\n read: (fh, offset, size, ifMatch) =>\n guard('read', () => transport.read(fh, offset, size, ifMatch)),\n write: (fh, offset, bytes) => guard('write', () => transport.write(fh, offset, bytes)),\n watch: (signal, onEvent, onOpen) => transport.watch(signal, onEvent, onOpen),\n };\n}\nconst PORT_MS_PER_MIB = 1000;\n\nlet nextPortToken = 0;\n\ntype PortReply = {\n id: number;\n pong?: boolean;\n result?: unknown;\n bytes?: Uint8Array;\n event?: HostfsEvent;\n open?: boolean;\n end?: boolean;\n error?: { code?: string; message?: string };\n};\n\nexport class PortTransport implements HostfsTransport {\n readonly capabilities: DriverCapabilities;\n readonly token: string;\n private readonly port: MessagePort;\n private readonly requestMs: number;\n private readonly waiting = new Map<number, (reply: PortReply) => void>();\n private next = 0;\n private dead: string | undefined;\n private readonly beatMs: number;\n private readonly deadMs: number;\n private readonly lingerMs: number;\n private beat: ReturnType<typeof setInterval> | undefined;\n private answers = false;\n private pinged: number | undefined;\n\n constructor(grant: HostfsPortGrant, liveness: PortLiveness = {}) {\n this.port = grant.port;\n this.requestMs = liveness.requestMs ?? PORT_REQUEST_MS;\n this.beatMs = liveness.beatMs ?? PORT_BEAT_MS;\n this.deadMs = liveness.deadMs ?? PORT_DEAD_MS;\n this.lingerMs = liveness.lingerMs ?? PORT_LINGER_MS;\n this.capabilities = grant.capabilities ?? {};\n this.token = grant.token ?? `port-${++nextPortToken}`;\n this.port.addEventListener('message', (event: MessageEvent<PortReply>) => {\n if (event.data?.pong) {\n this.answers = true;\n this.pinged = undefined;\n } else this.waiting.get(event.data?.id)?.(event.data);\n });\n this.port.addEventListener('close', () => this.fail(\"the folder's port closed\"));\n this.port.start();\n }\n\n get maxIo(): number {\n return this.capabilities.maxIo ?? HOSTFS_IO;\n }\n\n get gone(): boolean {\n return this.dead !== undefined;\n }\n\n retire(why: string): void {\n this.fail(why);\n }\n\n private ping(): void {\n if (this.pinged !== undefined) return;\n this.pinged = Date.now();\n try {\n this.port.postMessage({ id: 0, op: 'ping' });\n } catch {}\n }\n\n private watchBeat(): void {\n if (this.beat || this.dead) return;\n this.ping();\n this.beat = setInterval(() => {\n if (this.waiting.size === 0) {\n clearInterval(this.beat);\n this.beat = undefined;\n return;\n }\n if (this.answers && this.pinged !== undefined && Date.now() - this.pinged > this.deadMs) {\n this.fail(\"the folder's port stopped answering\");\n return;\n }\n this.ping();\n }, this.beatMs);\n }\n\n async cleanup(op: string, body: Record<string, unknown>): Promise<void> {\n if (this.closed) throw fsError('ENOTCONN', \"the folder's port is closed\");\n this.port.postMessage({ id: 0, op: 'cleanup', name: op, body });\n }\n\n private closed = false;\n\n fail(why: string): void {\n if (this.dead === undefined) {\n setTimeout(() => {\n try {\n this.port.postMessage({ id: 0, op: 'bye' });\n } catch {}\n this.closed = true;\n this.port.close();\n }, this.lingerMs);\n }\n clearInterval(this.beat);\n this.beat = undefined;\n this.dead ??= why;\n for (const settle of [...this.waiting.values()])\n settle({ id: 0, error: { code: 'ENOTCONN', message: why } });\n }\n\n private ask(\n message: Record<string, unknown>,\n bytes = 0,\n transfer: Transferable[] = []\n ): Promise<PortReply> {\n const id = ++this.next;\n if (this.dead) return Promise.reject(fsError('ENOTCONN', this.dead));\n return new Promise((resolve, reject) => {\n const timer = setTimeout(\n () => {\n this.waiting.delete(id);\n reject(fsError('ETIMEDOUT', \"the folder's port did not answer\"));\n this.fail(\"the folder's port stopped answering\");\n },\n this.requestMs + Math.ceil(bytes / 1_048_576) * PORT_MS_PER_MIB\n );\n this.watchBeat();\n this.waiting.set(id, (reply) => {\n clearTimeout(timer);\n this.waiting.delete(id);\n if (reply.error) reject(fsError(reply.error.code ?? 'EIO', reply.error.message ?? ''));\n else resolve(reply);\n });\n try {\n this.port.postMessage({ id, ...message }, transfer);\n } catch (err) {\n this.fail(`the folder's port is closed: ${(err as Error).message}`);\n }\n });\n }\n\n async call<T>(op: string, body: Record<string, unknown> = {}): Promise<T> {\n return (await this.ask({ op: 'call', name: op, body })).result as T;\n }\n\n async read(fh: number, offset: number, size: number, ifMatch?: string): Promise<Uint8Array> {\n const reply = await this.ask(\n { op: 'read', fh, offset, size, ...(ifMatch ? { ifMatch } : {}) },\n size\n );\n return reply.bytes ?? new Uint8Array(0);\n }\n\n async write(fh: number, offset: number, bytes: Uint8Array): Promise<void> {\n await this.ask({ op: 'write', fh, offset, bytes }, bytes.length);\n }\n\n watch(\n signal: AbortSignal,\n onEvent: (event: HostfsEvent) => void,\n onOpen: () => void = () => undefined\n ): Promise<void> {\n const id = ++this.next;\n if (this.dead) return Promise.reject(fsError('ENOTCONN', this.dead));\n if (signal.aborted) {\n this.fail(\"the folder's watch ended\");\n return Promise.resolve();\n }\n return new Promise<void>((resolve, reject) => {\n const finish = () => {\n this.waiting.delete(id);\n signal.removeEventListener('abort', stop);\n };\n const stop = () => {\n finish();\n try {\n this.port.postMessage({ id, op: 'unwatch' });\n } catch {}\n resolve();\n };\n this.watchBeat();\n this.waiting.set(id, (reply) => {\n if (reply.open) return onOpen();\n if (reply.event) return onEvent(reply.event);\n finish();\n if (reply.error) reject(fsError(reply.error.code ?? 'ENOTCONN', reply.error.message ?? ''));\n else resolve();\n });\n signal.addEventListener('abort', stop, { once: true });\n try {\n this.port.postMessage({ id, op: 'watch' });\n } catch (err) {\n finish();\n reject(fsError('ENOTCONN', `the folder's port is closed: ${(err as Error).message}`));\n }\n }).finally(() => this.fail(\"the folder's watch ended\"));\n }\n}\n\nconst errorOf = (err: unknown) => ({\n code: typeof codeOf(err) === 'string' ? (codeOf(err) as string) : 'EIO',\n message: (err as Error | null)?.message ?? String(err),\n});\n\nexport function serveHostfsPort(port: MessagePort, transport: HostfsTransport): () => void {\n const watches = new Map<number, AbortController>();\n const handles = new Set<number>();\n let stopped = false;\n const closeHandles = () => {\n for (const fh of handles) void transport.call('release', { fh }, true).catch(() => {});\n handles.clear();\n };\n const send = (reply: PortReply, transfer: Transferable[] = []) =>\n port.postMessage(reply, transfer);\n const pending = new Set<Promise<unknown>>();\n const track = <T>(work: Promise<T>) => {\n pending.add(work);\n const done = () => pending.delete(work);\n work.then(done, done);\n return work;\n };\n const answer = async (name: string, body: Record<string, unknown>) => {\n const result = await track(transport.call(name, body));\n const opened = (result as { fh?: unknown } | null)?.fh;\n if (name === 'open' && typeof opened === 'number') handles.add(opened);\n if (name === 'release') handles.delete(body?.fh as number);\n if (stopped) closeHandles();\n return result;\n };\n const listener = async ({\n data,\n }: MessageEvent<Record<string, unknown> & { id: number; op: string }>) => {\n const { id, op } = data;\n if (op === 'ping') return send({ id, pong: true });\n if (op === 'bye') return stop();\n if (op === 'cleanup')\n return void Promise.allSettled([...pending])\n .then(() => answer(data.name as string, data.body as Record<string, unknown>))\n .catch(() => {});\n if (op === 'unwatch') return watches.get(id)?.abort();\n if (op === 'watch') {\n const stop = new AbortController();\n watches.set(id, stop);\n try {\n await transport.watch(\n stop.signal,\n (event) => send({ id, event }),\n () => send({ id, open: true })\n );\n send({ id, end: true });\n } catch (err) {\n send({ id, error: errorOf(err) });\n } finally {\n watches.delete(id);\n }\n return;\n }\n try {\n if (op === 'read') {\n const read = await track(\n transport.read(\n data.fh as number,\n data.offset as number,\n data.size as number,\n data.ifMatch as string | undefined\n )\n );\n const bytes = read.slice();\n return send({ id, bytes }, [bytes.buffer as ArrayBuffer]);\n }\n if (op === 'write') {\n await track(\n transport.write(data.fh as number, data.offset as number, data.bytes as Uint8Array)\n );\n return send({ id });\n }\n if (op !== 'call') throw fsError('EINVAL', `unknown hostfs port op ${op}`);\n send({ id, result: await answer(data.name as string, data.body as Record<string, unknown>) });\n } catch (err) {\n send({ id, error: errorOf(err) });\n }\n };\n const stop = () => {\n stopped = true;\n port.removeEventListener('message', listener as (event: MessageEvent) => void);\n port.removeEventListener('close', stop);\n for (const watch of watches.values()) watch.abort();\n closeHandles();\n port.close();\n };\n port.addEventListener('message', listener as (event: MessageEvent) => void);\n port.addEventListener('close', stop);\n port.start();\n return stop;\n}\n\nexport function grantConnect(\n hook: HostfsGrantHook,\n fetch: FetchLike,\n liveness: PortLiveness = {}\n): HostfsConnect {\n return async (source, options) => {\n const first = await hook(source, options);\n if ('port' in first) return new PortTransport(first, liveness);\n const grant = async () => {\n const again = await hook(source, options);\n if ('port' in again)\n throw fsError('ESTALE', 'the folder moved to a port, so its open files are gone');\n return again;\n };\n return new HostfsClient(first, grant, fetch);\n };\n}\n\nexport async function openHostfs(\n spec: MountSpec,\n connect: HostfsConnect,\n timing: HostfsTiming = {}\n): Promise<OpenedDriver> {\n const readonly = spec.options?.ro !== undefined;\n const { port1, port2 } = new MessageChannel();\n const slot = mediumSlot<HostfsTransport>(\n async (err) => unreachable(err),\n () => watching.kick()\n );\n const stop = new AbortController();\n let active: HostfsTransport | undefined;\n const handlers = hostfsHandlers(() => active as HostfsTransport);\n const ranged = () => ({\n ...(active?.capabilities.ranges === true ? { ranges: true } : {}),\n ...(active ? { maxIo: Math.min(active.maxIo, HOSTFS_IO) } : {}),\n });\n const served = serveFilesystem(\n port2,\n { ...slot.handlers, mount: ranged },\n {\n symlinks: true,\n chmod: true,\n listingStats: true,\n maxIo: HOSTFS_IO,\n ...(readonly ? { readonly: true } : {}),\n }\n );\n const watching = keepWatching(\n {\n connect: () => connect(spec.source, { readonly }),\n up(client) {\n active = timed(client, timing.callMs ?? HOSTFS_CALL_MS);\n slot.insert(client, handlers);\n served.invalidate(true);\n },\n event: (event) => served.invalidate(invalidation(event)),\n down() {\n slot.eject();\n served.invalidate(true);\n },\n ...timing,\n },\n stop.signal\n );\n await watching.ready;\n return {\n port: port1,\n present: slot.present,\n dispose() {\n stop.abort();\n port1.close();\n port2.close();\n },\n };\n}\n", "import { type CdpOpen, serveCdpPort } from './cdp/port.ts';\nimport type { CdpHook } from './cdp/types.ts';\nimport {\n type DialHandle,\n type DialledSocket,\n type DialOptions,\n dialStream,\n errorWithCode,\n} from './client/dial-stream.ts';\nimport { type LoopbackFetchOptions, loopbackFetch } from './client/loopback-fetch.ts';\nimport { clipboardAnswerer } from './clipboard-relay.ts';\nimport { embedderAnswerer } from './embedder-relay.ts';\nimport { type FacadeOpen, serveFacadePort } from './facade/port.ts';\nimport type { FacadeSpecs } from './facade/types.ts';\nimport type { Attestation, AttestOptions, AttestTombstone } from './fs/attest.ts';\nimport type { Denial, DenialHook } from './fs/dac.ts';\nimport { integrityOptions } from './fs/integrity.ts';\nimport { type Portable, portable } from './fs/portable.ts';\nimport { type Protection, protectInit } from './fs/protect.ts';\nimport { DEFAULT_USERS, type UsersMode } from './fs/types.ts';\nimport { integrityAnswerer } from './integrity-relay.ts';\nimport type { ClipboardHook } from './kernel/clipboard.ts';\nimport { type EmbedderHook, kindsOf } from './kernel/embedder.ts';\nimport { isHostname } from './kernel/net/loopback-names.ts';\nimport type { TransportCall } from './kernel/net/remote-transport.ts';\nimport type { RouteTable } from './kernel/net/routes.ts';\nimport { type SealedOption, sealedHooks } from './kernel/net/sealed-fetch.ts';\nimport {\n carriesUdp,\n type NetworkUplink,\n serveUplink,\n type UplinkCall,\n} from './kernel/net/uplink.ts';\nimport { quiet, signalField } from './kernel/signals.ts';\nimport type { PendingMedium } from './launcher.ts';\nimport type { MediumHandle } from './mount/fsa.ts';\nimport type { HostfsGrantHook } from './mount/hostfs.ts';\nimport type { MountEntry, MountSpec } from './mount/mount-fs.ts';\nimport type { ProcessMountPolicy, ProcessMountRequest } from './mount/syscall.ts';\nimport { sealedAnswerer } from './sealed-relay.ts';\nimport type { FileChanged, InitRequest, KernelCall, TerminalAction } from './serve.ts';\nimport type { ApproveHook, SudoRequest } from './sudo.ts';\nimport { systemTimeZone } from './time-zone.ts';\nimport { type NetworkTransport, serveTransport } from './transport.ts';\nimport type { Account, AddUser, Group, RemoveUser } from './users.ts';\n\nexport type { CdpConnection, CdpHook, CdpRequest } from './cdp/types.ts';\nexport {\n type AttachOptions,\n attachKernel,\n type ClientEnded,\n type ClientFetchRequest,\n type ClientFs,\n type ClientRunOptions,\n type ClientRunResult,\n type ClientTerminal,\n type ClientTerminalOptions,\n KernelCallError,\n type KernelClient,\n KernelGoneError,\n type ProcessEntry,\n type SpawnedProcess,\n type SpawnOptions,\n type WatchChange,\n} from './client/attach.ts';\nexport type { DialledSocket, DialOptions } from './client/dial-stream.ts';\nexport type { LoopbackFetchOptions } from './client/loopback-fetch.ts';\nexport type {\n FacadeConnection,\n FacadeHook,\n FacadeInfo,\n FacadeSpec,\n FacadeSpecs,\n} from './facade/types.ts';\nexport type { Attestation, AttestedDir, AttestOptions, AttestTombstone } from './fs/attest.ts';\nexport type { Denial, DenialHook } from './fs/dac.ts';\nexport type { ClipboardHook, ClipboardStamp } from './kernel/clipboard.ts';\nexport type {\n EmbedderHook,\n EmbedderKindPolicy,\n EmbedderReply,\n EmbedderRequest,\n EmbedderStamp,\n} from './kernel/embedder.ts';\nexport type { RouteTable } from './kernel/net/routes.ts';\nexport {\n SEALED_FETCH_VERSION,\n type SealedFetchHook,\n type SealedFetchRequest,\n type SealedOption,\n} from './kernel/net/sealed-fetch.ts';\nexport type {\n NetworkUplink,\n ResolveAnswer,\n ResolveFamily,\n UplinkTraits,\n} from './kernel/net/uplink.ts';\nexport type {\n SealedAbortReason,\n SealedCaller,\n SealedHook,\n SealedRequest,\n SealedRequester,\n} from './kernel/sealed.ts';\nexport type { ConnectorStamp } from './kernel/socket.ts';\nexport type {\n HostfsEvent,\n HostfsGrant,\n HostfsGrantHook,\n HostfsPortGrant,\n HostfsTransport,\n} from './mount/hostfs.ts';\nexport { serveHostfsPort } from './mount/hostfs.ts';\nexport type { MountEntry, MountSpec } from './mount/mount-fs.ts';\nexport type { ProcessMountPolicy, ProcessMountRequest } from './mount/syscall.ts';\nexport type { JsChild, JsExited, JsSpawnOptions, JsStdio } from './process/js/js-children.ts';\nexport type {\n JsCrontabAnswer,\n JsCrontabCall,\n JsFdStatus,\n JsFdType,\n JsFile,\n JsOpenOptions,\n JsProgramContext,\n JsSelected,\n JsSelectSets,\n JsSignal,\n JsSudoAnswer,\n JsVisudoAnswer,\n JsVisudoCall,\n JsWriteOptions,\n} from './process/js/js-context.ts';\nexport type { JsStatFs } from './process/js/js-io.ts';\nexport type {\n JsAddress,\n JsConnection,\n JsConnectOptions,\n JsListener,\n JsListenOptions,\n JsNet,\n JsResolveOptions,\n JsTlsChoice,\n JsTlsCipher,\n JsTlsContext,\n JsTlsContextOptions,\n JsTlsOffer,\n JsTlsOptions,\n JsTlsSelect,\n JsTlsServerSession,\n JsTlsSession,\n} from './process/js/js-net.ts';\nexport type { JsRunOptions, JsRunResult, JsRunStdio } from './process/js/js-run.ts';\nexport type { JsCred, JsSyncContext, JsSyncFile } from './process/js/js-sync.ts';\nexport type { JsThread, JsThreadContext, JsThreadSpawnOptions } from './process/js/js-thread.ts';\nexport type { JsTermios, JsTty, JsTtySize } from './process/js/js-tty.ts';\nexport type {\n JsWebSocket,\n JsWebSocketClose,\n JsWebSocketMessage,\n JsWebSocketOptions,\n} from './process/js/js-websocket.ts';\nexport type { ApproveHook, SudoAnswer, SudoDenial, SudoRequest, SudoStdin } from './sudo.ts';\nexport {\n type FetchTransportOptions,\n fetchTransport,\n type HeaderList,\n type NetworkExit,\n type NetworkRedirectPolicy,\n type NetworkRequest,\n type NetworkResponse,\n type NetworkTraits,\n type NetworkTransport,\n type NetworkWebSocket,\n type NetworkWebSocketRequest,\n} from './transport.ts';\nexport type { Account, AddUser, Group, RemoveUser } from './users.ts';\n\nexport interface NetworkOptions {\n transport?: NetworkTransport;\n uplink?: NetworkUplink;\n doh?: string | false;\n}\n\nexport interface KernelOptions {\n root?: FileSystemDirectoryHandle;\n modules?: string;\n commands?: { append?: readonly string[] };\n env?: Record<string, string>;\n metadata?: string | false;\n media?: string | false;\n ca?: string | false;\n worker?: string | URL;\n network?: NetworkOptions;\n requestDirectory?: () => Promise<FileSystemDirectoryHandle>;\n onMountPending?: (pending: MountPending) => void;\n hostfs?: HostfsGrantHook;\n processMounts?: ProcessMountPolicy;\n cdp?: CdpHook;\n facades?: FacadeSpecs;\n hostname?: string;\n timeZone?: string;\n users?: UsersMode;\n onDenial?: DenialHook;\n sealed?: SealedOption;\n clipboard?: ClipboardHook;\n requests?: EmbedderHook;\n approve?: ApproveHook;\n protect?: Protection;\n}\n\ninterface HostfsRequest {\n id: number;\n source: string;\n readonly: boolean;\n}\n\nexport interface MountPending {\n target: string;\n source: string;\n insert(): Promise<void>;\n}\n\nexport interface RunOptions {\n cwd?: string;\n user?: string | number;\n tag?: string;\n env?: Record<string, string>;\n stdin?: string | Uint8Array;\n onStdout?: (text: string) => void;\n onStderr?: (text: string) => void;\n}\n\nexport interface RunResult {\n status: number;\n signal?: string;\n stdout: string;\n stderr: string;\n}\n\nexport interface ConnectOptions {\n user?: string | number;\n tag?: string;\n requests?: EmbedderHook | 'attach';\n}\n\nexport interface KernelGroups {\n list(): Promise<Group[]>;\n addMember(group: string, user: string): Promise<Group>;\n removeMember(group: string, user: string): Promise<Group>;\n}\n\nexport interface KernelUsers {\n readonly mode: UsersMode;\n add(user: AddUser): Promise<Account>;\n remove(name: string, options?: RemoveUser): Promise<boolean>;\n list(): Promise<Account[]>;\n}\n\nexport interface KernelIntegrity {\n revoke(path?: string): Promise<void>;\n}\n\nexport interface KernelSealed {\n setPlaceholders(list: readonly string[]): Promise<void>;\n}\n\nexport interface Kernel {\n run(argv: string[], options?: RunOptions): Promise<RunResult>;\n openTerminal(argv: string[], options?: TerminalOptions): Promise<Terminal>;\n connect(options?: ConnectOptions): Promise<MessagePort>;\n readonly users: KernelUsers;\n readonly groups: KernelGroups;\n setRoutes(routes: RouteTable): Promise<void>;\n chmod(path: string, mode: number): Promise<void>;\n readonly integrity: KernelIntegrity;\n readonly sealed: KernelSealed;\n updateTransportTraits(): Promise<boolean>;\n dial(options: DialOptions): Promise<DialledSocket>;\n loopbackFetch(input: RequestInfo | URL, options: LoopbackFetchOptions): Promise<Response>;\n mount(spec: MountSpec): Promise<MountEntry>;\n umount(target: string): Promise<void>;\n mounts(): Promise<MountEntry[]>;\n insert(target: string, handle: FileSystemDirectoryHandle): Promise<void>;\n attest(path: string): Promise<Attestation>;\n attest(path: string, options: { absent: 'allow' }): Promise<Attestation | AttestTombstone>;\n watch(paths: string[], onChange: (path: string) => void): Promise<() => void>;\n terminate(): void;\n}\n\nexport interface TerminalOptions {\n cwd?: string;\n user?: string | number;\n tag?: string;\n env?: Record<string, string>;\n cols?: number;\n rows?: number;\n onData?: (bytes: Uint8Array) => void;\n}\n\nexport type TerminalSignal =\n | 'SIGINT'\n | 'SIGTSTP'\n | 'SIGQUIT'\n | 'SIGHUP'\n | 'SIGTERM'\n | 'SIGKILL'\n | 'SIGCONT';\n\nexport interface Ended {\n status: number;\n signal?: string;\n}\n\nexport interface Terminal {\n readonly pid: number;\n readonly exited: Promise<number>;\n readonly ended: Promise<Ended>;\n onData: ((bytes: Uint8Array) => void) | null;\n write(data: string | Uint8Array): void;\n resize(cols: number, rows: number): void;\n signal(name: TerminalSignal): void;\n close(): void;\n}\n\ninterface Reply {\n id: number;\n result?: unknown;\n error?: string;\n code?: string;\n fd?: 1 | 2;\n bytes?: Uint8Array;\n started?: number;\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\ninterface Handlers {\n output?: Pending['output'];\n started?: Pending['started'];\n}\n\nconst ISOLATION =\n 'slicc-kernel needs a cross-origin isolated page (Cross-Origin-Opener-Policy: same-origin and Cross-Origin-Embedder-Policy: require-corp or credentialless)';\n\nfunction streamer(callback: ((text: string) => void) | undefined) {\n const decoder = new TextDecoder();\n return (bytes: Uint8Array) => callback?.(decoder.decode(bytes, { stream: true }));\n}\n\nfunction dialer(call: (req: KernelCall) => Promise<unknown>) {\n const open = new Set<DialHandle>();\n const dial = async ({ port, host }: DialOptions): Promise<DialledSocket> => {\n let reply: unknown;\n try {\n reply = await call({ op: 'dial', port, ...(host ? { host } : {}) });\n } catch (err) {\n throw errorWithCode((err as Error).message);\n }\n const handle = dialStream(reply as MessagePort, () => open.delete(handle));\n open.add(handle);\n return handle;\n };\n const reset = () => {\n for (const handle of [...open]) handle.fail(errorWithCode('ECONNRESET: the kernel is gone'));\n };\n return { dial, reset };\n}\n\nfunction uplinkInit(uplink: NetworkUplink | undefined): Pick<InitRequest, 'uplink'> {\n if (!uplink) return {};\n const traits = { tcp: true, udp: carriesUdp(uplink), ipv6: uplink.traits.ipv6 === true } as const;\n const nameserver = typeof uplink.nameserver === 'string' ? { nameserver: uplink.nameserver } : {};\n return { uplink: { traits, ...(uplink.routes ? { routes: uplink.routes } : {}), ...nameserver } };\n}\n\nfunction rootField(\n at: Portable<FileSystemDirectoryHandle>\n): Pick<InitRequest, 'root' | 'rootPath'> {\n return 'path' in at ? { rootPath: at.path } : { root: at.handle };\n}\n\nasync function insertCall(\n target: string,\n handle: FileSystemDirectoryHandle,\n source?: string\n): Promise<KernelCall> {\n return { op: 'insert', target, source, ...(await portable(handle)) };\n}\n\nasync function initCall(\n options: KernelOptions,\n transport: NetworkTransport | undefined\n): Promise<KernelCall> {\n const hooks = sealedHooks(options.sealed);\n return {\n op: 'init',\n ...(options.root ? rootField(await portable(options.root)) : {}),\n ...(options.modules ? { modules: options.modules } : {}),\n ...(options.commands ? { commands: options.commands } : {}),\n ...(options.env ? { env: options.env } : {}),\n ...(options.metadata !== undefined ? { metadata: options.metadata } : {}),\n ...(options.media !== undefined ? { media: options.media } : {}),\n ...(options.ca !== undefined ? { ca: options.ca } : {}),\n ...(transport ? { transport: transport.traits } : {}),\n ...uplinkInit(options.network?.uplink),\n ...(options.network?.doh !== undefined ? { doh: options.network.doh } : {}),\n ...(options.hostfs ? { hostfs: true } : {}),\n ...(options.cdp ? { cdp: true } : {}),\n ...facadesInit(options.facades),\n ...(options.hostname !== undefined ? { hostname: options.hostname } : {}),\n ...(options.timeZone !== undefined ? { timeZone: options.timeZone } : {}),\n users: options.users === undefined ? DEFAULT_USERS : options.users,\n ...(options.onDenial ? { denials: true } : {}),\n ...(hooks.request ? { sealed: true } : {}),\n ...(hooks.fetch ? { sealedFetch: true } : {}),\n ...(options.clipboard ? { clipboard: true } : {}),\n ...(options.requests ? { requests: kindsOf(options.requests) } : {}),\n ...(options.approve ? { approve: true } : {}),\n ...(options.protect ? { protect: protectInit(options.protect) } : {}),\n ...(options.processMounts !== undefined\n ? {\n processMounts:\n typeof options.processMounts === 'function' ? 'ask' : options.processMounts,\n }\n : {}),\n };\n}\n\ninterface PageHosts {\n cdp: { open(data: CdpOpen): void };\n facades: { open(data: FacadeOpen): void };\n policy(data: { id: number; req: ProcessMountRequest }): Promise<void>;\n medium(medium: PendingMedium): void;\n hostfs(req: HostfsRequest): Promise<void>;\n}\n\nfunction hostedMessage(data: WorkerMessage, on: PageHosts): data is Exclude<WorkerMessage, Reply> {\n if ('cdpOpen' in data) on.cdp.open(data);\n else if ('facadeOpen' in data) on.facades.open(data);\n else if ('mountPolicy' in data) void on.policy(data.mountPolicy);\n else if ('medium' in data) on.medium(data.medium);\n else if ('hostfs' in data) void on.hostfs(data.hostfs);\n else return false;\n return true;\n}\n\nfunction facadesInit(specs: FacadeSpecs | undefined) {\n if (!specs) return {};\n const facades: Record<string, { port: number; hook?: boolean }> = {};\n for (const [name, spec] of Object.entries(specs)) {\n if (spec?.hook !== undefined && typeof spec.hook !== 'function') {\n throw new TypeError(`facades.${name}: hook must be a function`);\n }\n facades[name] = { port: spec?.port, ...(spec?.hook ? { hook: true } : {}) };\n }\n return { facades };\n}\n\nfunction facadeBridge(specs: FacadeSpecs | undefined) {\n const open = new Set<() => void>();\n let closed = false;\n return {\n open({ facadeOpen, port }: FacadeOpen): void {\n const hook = specs?.[facadeOpen.name]?.hook;\n if (!hook || closed) {\n port.postMessage({ error: 'no facade host' });\n port.close();\n return;\n }\n const close = serveFacadePort(port, hook, facadeOpen, () => open.delete(close));\n open.add(close);\n },\n close(): void {\n closed = true;\n for (const close of [...open]) close();\n },\n };\n}\n\nfunction cdpBridge(hook: CdpHook | undefined) {\n const open = new Set<() => void>();\n let closed = false;\n return {\n open({ cdpOpen, port }: CdpOpen): void {\n if (!hook || closed) {\n port.close();\n return;\n }\n const close = serveCdpPort(port, hook, cdpOpen, () => open.delete(close));\n open.add(close);\n },\n close(): void {\n closed = true;\n for (const close of [...open]) close();\n },\n };\n}\n\nfunction failed(message: string, code: string | undefined): Error {\n return Object.assign(new Error(message), code === undefined ? {} : { code });\n}\n\nfunction kernelGroups(call: (req: KernelCall) => Promise<unknown>): KernelGroups {\n const member =\n (op: 'groups-add-member' | 'groups-remove-member') => async (group: string, user: string) =>\n (await call({ op, group, user })) as Group;\n return {\n list: async () => (await call({ op: 'groups-list' })) as Group[],\n addMember: member('groups-add-member'),\n removeMember: member('groups-remove-member'),\n };\n}\n\nfunction accounts(\n call: (req: KernelCall) => Promise<unknown>,\n mode: UsersMode | undefined\n): { users: KernelUsers; groups: KernelGroups } {\n return { users: kernelUsers(call, mode), groups: kernelGroups(call) };\n}\n\nfunction kernelUsers(\n call: (req: KernelCall) => Promise<unknown>,\n mode: UsersMode = DEFAULT_USERS\n): KernelUsers {\n return {\n mode,\n add: async (user) => (await call({ op: 'users-add', user })) as Account,\n remove: async (name, options) =>\n (await call({ op: 'users-remove', name, ...(options ? { options } : {}) })) as boolean,\n list: async () => (await call({ op: 'users-list' })) as Account[],\n };\n}\n\nasync function mountPolicy(\n options: KernelOptions,\n worker: Worker,\n { id, req }: { id: number; req: ProcessMountRequest }\n): Promise<void> {\n const decide = options.processMounts;\n let allowed = false;\n try {\n allowed = typeof decide === 'function' ? await decide(req) : decide !== false;\n } catch {}\n worker.postMessage({ mountAllowed: { id, allowed } });\n}\n\ntype SudoMessage = { sudoAsk: SudoRequest } | { sudoAbort: { id: string; reason: string } };\n\ntype WorkerMessage =\n | Reply\n | TransportCall\n | UplinkCall\n | { medium: PendingMedium }\n | { hostfs: HostfsRequest }\n | { mountPolicy: { id: number; req: ProcessMountRequest } }\n | CdpOpen\n | FacadeOpen\n | { denial: Denial }\n | FileChanged\n | SudoMessage;\n\ntype Requester = (req: KernelCall) => { id: number; done: Promise<unknown> };\n\nfunction fileWatches(request: Requester, call: (req: KernelCall) => Promise<unknown>) {\n const watching = new Map<number, (path: string) => void>();\n return {\n event(data: WorkerMessage): data is FileChanged {\n if (!('fileChanged' in data)) return false;\n watching.get(data.fileChanged.watch)?.(data.fileChanged.path);\n return true;\n },\n async watch(paths: string[], onChange: (path: string) => void): Promise<() => void> {\n const { id, done } = request({ op: 'watch-files', paths });\n watching.set(id, onChange);\n await done.catch((err: unknown) => {\n watching.delete(id);\n throw err;\n });\n return () => {\n if (!watching.delete(id)) return;\n void call({ op: 'unwatch-files', watch: id }).catch(() => undefined);\n };\n },\n };\n}\n\nfunction relayable(answer: unknown): unknown {\n if (typeof answer === 'symbol' || typeof answer === 'function') return 'deny';\n if (typeof answer !== 'object' || answer === null) return answer;\n try {\n const { answer: kind, message } = answer as { answer?: unknown; message?: unknown };\n return kind === 'deny' && typeof message === 'string' ? { answer: kind, message } : 'deny';\n } catch {\n return 'deny';\n }\n}\n\nfunction approver(approve: ApproveHook | undefined, worker: Worker) {\n const asked = new Map<string, AbortController>();\n const handlers = {\n handle(data: WorkerMessage): data is SudoMessage {\n if ('sudoAsk' in data) void handlers.ask(data.sudoAsk);\n else if ('sudoAbort' in data) handlers.abort(data.sudoAbort);\n else return false;\n return true;\n },\n async ask(req: SudoRequest): Promise<void> {\n const control = new AbortController();\n asked.set(req.id, control);\n let answer: unknown = 'deny';\n try {\n answer = await approve?.(req, { signal: control.signal });\n } catch {}\n asked.delete(req.id);\n if (control.signal.aborted) return;\n worker.postMessage({ sudoAnswer: { id: req.id, answer: relayable(answer) } });\n },\n abort({ id, reason }: { id: string; reason: string }): void {\n asked.get(id)?.abort(reason);\n asked.delete(id);\n },\n close(): void {\n for (const control of asked.values()) control.abort('withdrawn');\n asked.clear();\n },\n };\n return handlers;\n}\n\nfunction checkOptions(options: KernelOptions): void {\n if (!globalThis.crossOriginIsolated) throw new Error(ISOLATION);\n if (options.hostname !== undefined && !isHostname(options.hostname)) {\n throw new Error(`not a host name: ${String(options.hostname)}`);\n }\n if (options.timeZone !== undefined) systemTimeZone(options.timeZone);\n if (options.protect) protectInit(options.protect);\n integrityOptions(options.protect?.integrity);\n facadesInit(options.facades);\n sealedHooks(options.sealed);\n}\n\nfunction connector(\n call: (req: KernelCall) => Promise<unknown>,\n bound: Map<number, EmbedderHook>\n): (options?: ConnectOptions) => Promise<MessagePort> {\n return async (connectOptions = {}) => {\n const { requests, ...rest } = connectOptions;\n if (requests === undefined || requests === 'attach')\n return (await call({\n op: 'connect',\n ...rest,\n ...(requests ? { requests } : {}),\n })) as MessagePort;\n const made = (await call({ op: 'connect', ...rest, requests: kindsOf(requests) })) as {\n port: MessagePort;\n client: number;\n };\n bound.set(made.client, requests);\n return made.port;\n };\n}\n\nfunction hookRelays(\n worker: Worker,\n options: KernelOptions,\n bound: Map<number, EmbedderHook>\n): { handle(data: unknown): boolean; close(): void } {\n const hooks = sealedHooks(options.sealed);\n const sealed = sealedAnswerer(worker, hooks.request, hooks.fetch);\n const clipboard = clipboardAnswerer(worker, options.clipboard);\n const integrity = integrityAnswerer(worker, options.protect?.integrity?.lookup);\n const requests = embedderAnswerer(worker, (client) =>\n client === 0 ? options.requests : bound.get(client)\n );\n return {\n handle: (data) =>\n sealed.handle(data) || clipboard.handle(data) || requests.handle(data) || integrity(data),\n close: () => sealed.close(),\n };\n}\n\ninterface RawRun {\n status: number;\n signal?: number;\n stdout: Uint8Array;\n stderr: Uint8Array;\n}\n\nfunction decodedRun(result: RawRun): RunResult {\n const decoder = new TextDecoder();\n return {\n status: result.status,\n ...signalField(result.signal),\n stdout: decoder.decode(result.stdout),\n stderr: decoder.decode(result.stderr),\n };\n}\n\nfunction endedOf(r: unknown): Ended {\n if (typeof r === 'number') return { status: r };\n const { status, signal } = r as { status: number; signal?: number };\n return { status, ...signalField(signal) };\n}\n\nfunction uplinkServer(\n worker: Worker,\n uplink: NetworkUplink | undefined\n): ReturnType<typeof serveUplink> | undefined {\n return uplink ? serveUplink(worker, uplink) : undefined;\n}\n\nfunction traitsUpdater(\n transport: NetworkTransport | undefined,\n call: (req: KernelCall) => Promise<unknown>\n): () => Promise<boolean> {\n return async () => {\n const traits = transport ? { traits: { ...transport.traits } } : {};\n return (await call({ op: 'transport-traits', ...traits })) === true;\n };\n}\n\nfunction transportBridge(\n worker: Worker,\n transport: NetworkTransport | undefined\n): ReturnType<typeof serveTransport> | undefined {\n return transport ? serveTransport(worker, transport, { attributed: true }) : undefined;\n}\n\nfunction pageOnly(call: (req: KernelCall) => Promise<unknown>): Pick<Kernel, 'attest' | 'sealed'> {\n return {\n sealed: {\n setPlaceholders: async (list) => void (await call({ op: 'sealed-placeholders', list })),\n },\n attest: ((path: string, options?: AttestOptions) =>\n call({ op: 'attest', path, ...(options ? { options } : {}) })) as Kernel['attest'],\n };\n}\n\nexport async function createKernel(options: KernelOptions = {}): Promise<Kernel> {\n checkOptions(options);\n const url = options.worker ?? new URL('./kernel-worker.js', import.meta.url);\n const worker = new Worker(url, { type: 'module', name: 'slicc-kernel' });\n const pending = new Map<number, Pending>();\n let nextId = 0;\n let failure: Error | undefined;\n\n const dials = dialer((req) => call(req));\n const files = fileWatches(\n (req) => request(req),\n (req) => call(req)\n );\n const cdp = cdpBridge(options.cdp);\n const facades = facadeBridge(options.facades);\n const bound = new Map<number, EmbedderHook>();\n const sealed = hookRelays(worker, options, bound);\n const approvals = approver(options.approve, worker);\n const fail = (error: Error) => {\n dials.reset();\n cdp.close();\n facades.close();\n sealed.close();\n approvals.close();\n failure = error;\n bridge?.close();\n uplinks?.close();\n for (const call of pending.values()) call.reject(error);\n pending.clear();\n };\n const transport = options.network?.transport;\n const bridge = transportBridge(worker, transport);\n const uplinks = uplinkServer(worker, options.network?.uplink);\n async function chosen(handle: MediumHandle | undefined): Promise<FileSystemDirectoryHandle> {\n if (handle) {\n const state = await handle.requestPermission?.({ mode: 'readwrite' });\n if (state === undefined || state === 'granted') return handle;\n throw new Error('permission for the folder was not granted');\n }\n if (!options.requestDirectory) throw new Error('this page cannot ask for a folder');\n return options.requestDirectory();\n }\n async function grantHostfs({ id, source, readonly }: HostfsRequest): Promise<void> {\n try {\n if (!options.hostfs) throw new Error('this page gives no host folders');\n const grant = await options.hostfs(source, { readonly });\n worker.postMessage({ hostfsGrant: { id, grant } }, 'port' in grant ? [grant.port] : []);\n } catch (err) {\n worker.postMessage({ hostfsGrant: { id, error: (err as Error).message ?? String(err) } });\n }\n }\n const policy = (asked: { id: number; req: ProcessMountRequest }) =>\n mountPolicy(options, worker, asked);\n const pendingMedium = ({ target, source, handle }: PendingMedium) =>\n options.onMountPending?.({\n target,\n source,\n insert: async () => void (await call(await insertCall(target, await chosen(handle), source))),\n });\n const aside = (data: WorkerMessage): data is { denial: Denial } | FileChanged => {\n if (files.event(data)) return true;\n if (!('denial' in data)) return sealed.handle(data);\n options.onDenial?.(data.denial);\n return true;\n };\n const hosts = { cdp, facades, policy, medium: pendingMedium, hostfs: grantHostfs };\n worker.addEventListener('message', ({ data }: MessageEvent<WorkerMessage>) => {\n if (aside(data)) return;\n if (approvals.handle(data)) return;\n if ('net' in data) return bridge?.answer(data);\n if ('uplink' in data) return uplinks?.answer(data);\n if (hostedMessage(data, hosts)) return;\n const call = pending.get(data.id);\n if (!call) return;\n if (data.fd !== undefined) return call.output?.(data.fd, data.bytes as Uint8Array);\n if (data.started !== undefined) return call.started?.(data.started);\n pending.delete(data.id);\n if (data.error !== undefined) call.reject(failed(data.error, data.code));\n else call.resolve(data.result);\n });\n worker.addEventListener('error', (event) => {\n event.preventDefault();\n fail(new Error(`slicc-kernel worker failed: ${event.message}`));\n });\n\n function request(\n req: KernelCall,\n handlers: Handlers = {}\n ): { id: number; done: Promise<unknown> } {\n const id = ++nextId;\n if (failure) return { id, done: Promise.reject(failure) };\n const done = new Promise((resolve, reject) => {\n pending.set(id, { resolve, reject, ...handlers });\n worker.postMessage({ ...req, id });\n });\n return { id, done };\n }\n\n const call = (req: KernelCall, handlers?: Handlers) => request(req, handlers).done;\n\n async function openTerminal(argv: string[], opts: TerminalOptions = {}): Promise<Terminal> {\n const { onData, ...options } = opts;\n let listener = onData ?? null;\n const backlog: Uint8Array[] = [];\n const started = Promise.withResolvers<number>();\n const { id, done } = 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 call({ op: 'terminal', terminal: id, ...action }).catch(() => undefined);\n return {\n pid,\n exited: quiet(done.then((r) => endedOf(r).status)),\n ended: quiet(done.then(endedOf)),\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) =>\n send({\n action: 'write',\n bytes: typeof data === 'string' ? new TextEncoder().encode(data) : data,\n }),\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\n const { dial } = dials;\n\n await call(await initCall(options, transport));\n\n return {\n async run(argv, runOptions = {}) {\n const { onStdout, onStderr, stdin, ...rest } = runOptions;\n const streams = { 1: streamer(onStdout), 2: streamer(onStderr) };\n const input = typeof stdin === 'string' ? new TextEncoder().encode(stdin) : stdin;\n const result = (await call(\n { op: 'run', argv, options: { ...rest, ...(input ? { stdin: input } : {}) } },\n { output: (fd, bytes) => streams[fd](bytes) }\n )) as RawRun;\n return decodedRun(result);\n },\n openTerminal,\n connect: connector(call, bound),\n ...accounts(call, options.users === undefined ? DEFAULT_USERS : options.users),\n setRoutes: async (routes) => void (await call({ op: 'routes', routes })),\n chmod: async (path, mode) => void (await call({ op: 'chmod', path, mode })),\n integrity: {\n revoke: async (path) =>\n void (await call({ op: 'integrity-revoke', ...(path !== undefined ? { path } : {}) })),\n },\n updateTransportTraits: traitsUpdater(transport, call),\n dial,\n loopbackFetch: (input, fetchOptions) => loopbackFetch(dial, input, fetchOptions),\n mount: async (spec) => (await call({ op: 'mount', spec })) as MountEntry,\n umount: async (target) => void (await call({ op: 'umount', target })),\n mounts: async () => (await call({ op: 'mounts' })) as MountEntry[],\n insert: async (target, handle) => void (await call(await insertCall(target, handle))),\n ...pageOnly(call),\n watch: files.watch,\n terminate() {\n fail(new Error('slicc-kernel terminated'));\n worker.terminate();\n },\n };\n}\n"],
|
|
5
|
-
"mappings": "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",
|
|
4
|
+
"sourcesContent": ["import type { CdpConnection, CdpHook, CdpRequest } from './types.ts';\n\nexport interface CdpPortLike {\n postMessage(message: unknown): void;\n addEventListener(type: 'message', handler: (event: MessageEvent) => void): void;\n start?(): void;\n close(): void;\n}\n\nexport type CdpWire = { open: true } | { error: string } | { m: string } | { close: string | null };\n\nexport interface CdpOpen {\n cdpOpen: CdpRequest & { registration?: number };\n port: CdpPortLike;\n}\n\nexport function serveCdpPort(\n port: CdpPortLike,\n hook: CdpHook,\n request: CdpRequest,\n onDone?: () => void\n): () => void {\n let conn: CdpConnection | undefined;\n let done = false;\n const end = () => {\n done = true;\n port.close();\n onDone?.();\n };\n const finish = (reason: string | null) => {\n if (done) return;\n port.postMessage({ close: reason });\n end();\n };\n port.addEventListener('message', ({ data }: MessageEvent<{ m?: string; close?: true }>) => {\n if (data.m !== undefined) conn?.send(data.m);\n else if (data.close && !done) {\n end();\n conn?.close();\n }\n });\n port.start?.();\n new Promise<CdpConnection>((resolve) => resolve(hook(request))).then(\n (opened) => {\n conn = opened;\n if (done) return opened.close();\n opened.onmessage = (m) => {\n if (!done) port.postMessage({ m });\n };\n opened.onclose = (reason) => finish(reason ?? null);\n port.postMessage({ open: true });\n },\n (e: unknown) => {\n if (done) return;\n port.postMessage({ error: e instanceof Error ? e.message : String(e) });\n end();\n }\n );\n return () => {\n if (done) return;\n conn?.close();\n finish('the CDP host is gone');\n };\n}\n\nexport function portCdpHook(\n ask: (request: CdpRequest, port: CdpPortLike) => void,\n gone?: Promise<unknown>\n): CdpHook {\n return (request) =>\n new Promise((resolve, reject) => {\n const { port1, port2 } = new MessageChannel();\n let closed = false;\n const conn: CdpConnection = {\n send: (m) => {\n if (!closed) port1.postMessage({ m });\n },\n onmessage: null,\n onclose: null,\n close: () => {\n if (closed) return;\n closed = true;\n port1.postMessage({ close: true });\n port1.close();\n },\n };\n port1.addEventListener('message', ({ data }: MessageEvent<CdpWire>) => {\n if ('m' in data) conn.onmessage?.(data.m);\n else if ('open' in data) resolve(conn);\n else if ('error' in data) {\n closed = true;\n port1.close();\n reject(new Error(data.error));\n } else if (!closed) {\n closed = true;\n port1.close();\n conn.onclose?.(data.close ?? undefined);\n }\n });\n port1.start();\n void gone?.then(() => {\n if (closed) return;\n closed = true;\n port1.close();\n reject(new Error('the CDP host is gone'));\n conn.onclose?.('the CDP host is gone');\n });\n ask(request, port2 as unknown as CdpPortLike);\n });\n}\n", "export function fresh(bytes: Uint8Array, start = 0, end = bytes.length): Uint8Array {\n return new Uint8Array(bytes.subarray(start, end));\n}\n", "import { fresh } from '../bytes.ts';\n\nexport 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 = fresh(chunk);\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", "export const PIPE_CAPACITY = 64 * 1024;\n\nexport interface PipeMark {\n readonly at: number;\n readonly count: number;\n drop(): void;\n}\n\nexport class PipeError extends Error {\n readonly code: 'EPIPE' | 'EINTR' | 'EAGAIN';\n\n constructor(code: 'EPIPE' | 'EINTR' | 'EAGAIN') {\n super(code);\n this.code = code;\n }\n}\n\nexport class KernelPipe {\n private chunks: Uint8Array[] = [];\n private size = 0;\n private readers = 0;\n private writers = 0;\n private waiters: Array<() => void> = [];\n private pushed = 0;\n private taken = 0;\n private marks: PipeMark[] = [];\n\n readonly capacity: number;\n\n constructor(capacity: number = PIPE_CAPACITY) {\n this.capacity = capacity;\n }\n\n get buffered(): number {\n return this.size;\n }\n\n get readReady(): boolean {\n return this.size > 0 || this.writers === 0;\n }\n\n get writeReady(): boolean {\n return this.size < this.capacity || this.readers === 0;\n }\n\n get writersGone(): boolean {\n return this.writers === 0;\n }\n\n get readersGone(): boolean {\n return this.readers === 0;\n }\n\n openRead(): void {\n this.readers += 1;\n }\n\n openWrite(): void {\n this.writers += 1;\n }\n\n closeRead(): void {\n if (this.readers > 0) this.readers -= 1;\n if (this.readers === 0) {\n this.chunks = [];\n this.size = 0;\n this.dropMarks(() => true);\n }\n this.wake();\n }\n\n closeWrite(): void {\n if (this.writers > 0) this.writers -= 1;\n this.wake();\n }\n\n async read(max: number, signal?: AbortSignal): Promise<Uint8Array> {\n while (this.size === 0) {\n if (this.writers === 0) return new Uint8Array(0);\n await this.changed(signal);\n }\n const out = this.take(this.bounded(Math.min(max, this.size)));\n this.dropMarks((mark) => mark.at < this.taken);\n this.wake();\n return out;\n }\n\n get inFlight(): number {\n return this.marks.reduce((sum, mark) => sum + mark.count, 0);\n }\n\n async receive(\n max: number,\n nonblock: boolean,\n signal?: AbortSignal\n ): Promise<{ bytes: Uint8Array; marks: PipeMark[] }> {\n while (this.size === 0) {\n if (this.writers === 0) return { bytes: new Uint8Array(0), marks: [] };\n if (nonblock) throw new PipeError('EAGAIN');\n await this.changed(signal);\n }\n const marks = this.marks.filter((mark) => mark.at === this.taken);\n this.marks = this.marks.filter((mark) => mark.at !== this.taken);\n const bytes = this.take(this.bounded(Math.min(max, this.size)));\n this.dropMarks((mark) => mark.at < this.taken);\n this.wake();\n return { bytes, marks };\n }\n\n async writeMarked(\n bytes: Uint8Array,\n mark: (at: number) => PipeMark,\n nonblock: boolean,\n signal?: AbortSignal\n ): Promise<number> {\n while (this.readers > 0 && this.size >= this.capacity) {\n if (nonblock) throw new PipeError('EAGAIN');\n await this.changed(signal);\n }\n if (this.readers === 0) throw new PipeError('EPIPE');\n const before = this.pushed;\n const made = mark(before);\n this.marks.push(made);\n try {\n const n = await this.write(bytes, signal);\n this.orphan(made, before);\n return n;\n } catch (err) {\n this.orphan(made, before);\n throw err;\n }\n }\n\n private orphan(made: PipeMark, before: number): void {\n if (this.pushed !== before) return;\n this.dropMarks((mark) => mark === made);\n }\n\n private bounded(n: number): number {\n const next = this.marks.find((mark) => mark.at > this.taken);\n return next ? Math.min(n, next.at - this.taken) : n;\n }\n\n private dropMarks(gone: (mark: PipeMark) => boolean): void {\n const dropped = this.marks.filter(gone);\n if (dropped.length === 0) return;\n this.marks = this.marks.filter((mark) => !gone(mark));\n for (const mark of dropped) mark.drop();\n }\n\n async peek(max: number, signal?: AbortSignal): Promise<Uint8Array> {\n while (this.size === 0) {\n if (this.writers === 0) return new Uint8Array(0);\n await this.changed(signal);\n }\n const out = new Uint8Array(Math.min(max, this.size));\n let filled = 0;\n for (const chunk of this.chunks) {\n if (filled === out.length) break;\n const count = Math.min(chunk.length, out.length - filled);\n out.set(chunk.subarray(0, count), filled);\n filled += count;\n }\n return out;\n }\n\n async write(bytes: Uint8Array, signal?: AbortSignal): Promise<number> {\n let offset = 0;\n while (offset < bytes.length) {\n if (this.readers === 0) throw new PipeError('EPIPE');\n const room = this.capacity - this.size;\n if (room === 0) {\n try {\n await this.changed(signal);\n } catch (e) {\n if (offset > 0) return offset;\n throw e;\n }\n continue;\n }\n const n = Math.min(room, bytes.length - offset);\n this.chunks.push(bytes.slice(offset, offset + n));\n this.size += n;\n this.pushed += n;\n offset += n;\n this.wake();\n }\n return bytes.length;\n }\n\n private take(n: number): Uint8Array {\n const out = new Uint8Array(n);\n let filled = 0;\n while (filled < n) {\n const head = this.chunks[0];\n const count = Math.min(head.length, n - filled);\n out.set(head.subarray(0, count), filled);\n filled += count;\n if (count === head.length) this.chunks.shift();\n else this.chunks[0] = head.subarray(count);\n }\n this.size -= n;\n this.taken += n;\n return out;\n }\n\n changed(signal?: AbortSignal): Promise<void> {\n if (signal?.aborted) return Promise.reject(new PipeError('EINTR'));\n return new Promise((resolve, reject) => {\n const onAbort = (): void => {\n this.waiters = this.waiters.filter((w) => w !== waiter);\n reject(new PipeError('EINTR'));\n };\n const waiter = (): void => {\n signal?.removeEventListener('abort', onAbort);\n resolve();\n };\n this.waiters.push(waiter);\n signal?.addEventListener('abort', onAbort, { once: true });\n });\n }\n\n private wake(): void {\n const waiters = this.waiters;\n this.waiters = [];\n for (const resolve of waiters) resolve();\n }\n}\n", "import type { UsersMode } from '../fs/types.ts';\nimport { KernelError, type OpenAccess, OpenFile, type PollState } from './fd-table.ts';\n\nexport const CLIPBOARD_PATH = '/dev/clipboard';\nexport const CLIPBOARD_MINOR = 251;\nexport const CLIPBOARD_MAX_BYTES = 1024 * 1024;\nexport const CLIPBOARD_TIMEOUT_MS = 10_000;\n\nexport interface ClipboardStamp {\n pid: number;\n uid: number;\n gid: number;\n users: UsersMode;\n tag?: string;\n tags?: string[];\n}\n\nexport interface ClipboardHook {\n read(stamp: ClipboardStamp): Promise<string>;\n write(text: string, stamp: ClipboardStamp): Promise<void>;\n}\n\nconst encoder = new TextEncoder();\nconst decoder = new TextDecoder('utf-8', { fatal: true });\nconst READY: PollState = { readable: true, writable: true, hangup: false };\n\nfunction lineOf(err: unknown): string {\n const text = err instanceof Error ? err.message : String(err);\n return (text.split('\\n')[0] ?? '').slice(0, 200);\n}\n\nexport function clipboardFailure(err: unknown): KernelError {\n if (err instanceof KernelError) return err;\n const name = (err as { name?: unknown } | null)?.name;\n return new KernelError(name === 'NotAllowedError' ? 'EACCES' : 'EIO', lineOf(err));\n}\n\nfunction joined(chunks: Uint8Array[], size: number): Uint8Array {\n if (chunks.length === 1) return chunks[0] as Uint8Array;\n const out = new Uint8Array(size);\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\nasync function interruptible<T>(work: Promise<T>, signal: AbortSignal | undefined): Promise<T> {\n if (!signal) return work;\n if (signal.aborted) throw new KernelError('EINTR');\n let stop = (): void => {};\n const interrupted = new Promise<never>((_, reject) => {\n stop = () => reject(new KernelError('EINTR'));\n signal.addEventListener('abort', stop, { once: true });\n });\n try {\n return await Promise.race([work, interrupted]);\n } finally {\n signal.removeEventListener('abort', stop);\n }\n}\n\nclass ClipboardChannel {\n stamp: ClipboardStamp;\n readonly access: OpenAccess;\n private readonly broker: ClipboardBroker;\n private snapshot: Promise<Uint8Array> | undefined;\n private taken: Uint8Array | undefined;\n private offset = 0;\n private chunks: Uint8Array[] = [];\n private size = 0;\n private wrote = false;\n private failed = false;\n private aborted = false;\n\n constructor(broker: ClipboardBroker, access: OpenAccess, stamp: ClipboardStamp) {\n this.broker = broker;\n this.access = access;\n this.stamp = stamp;\n }\n\n get unread(): boolean {\n return this.taken === undefined && this.snapshot === undefined;\n }\n\n get settled(): boolean {\n return this.taken !== undefined;\n }\n\n async read(max: number, signal?: AbortSignal): Promise<Uint8Array> {\n if (this.access === 'write') throw new KernelError('EBADF');\n if (!this.taken) {\n if (!this.snapshot) {\n const stamp = this.stamp;\n const asked = this.broker.ask(async (hook) => {\n const text = await hook.read(stamp);\n if (typeof text !== 'string') throw new KernelError('EIO', 'the clipboard gave no text');\n return encoder.encode(text);\n });\n this.snapshot = asked;\n asked.then(\n (bytes) => {\n if (this.snapshot === asked) this.taken = bytes;\n },\n () => {\n if (this.snapshot === asked) this.snapshot = undefined;\n }\n );\n }\n this.taken = await interruptible(this.snapshot, signal);\n }\n const out = this.taken.subarray(this.offset, this.offset + max);\n this.offset += out.length;\n return out;\n }\n\n write(bytes: Uint8Array): number {\n if (this.access === 'read') throw new KernelError('EBADF');\n this.wrote = true;\n if (this.failed) throw new KernelError('EFBIG');\n if (this.size + bytes.length > CLIPBOARD_MAX_BYTES) {\n this.failed = true;\n this.chunks = [];\n this.size = 0;\n throw new KernelError('EFBIG');\n }\n if (bytes.length > 0) this.chunks.push(bytes.slice());\n this.size += bytes.length;\n return bytes.length;\n }\n\n poll(): PollState {\n return READY;\n }\n\n abort(): void {\n this.aborted = true;\n }\n\n async close(): Promise<void> {\n this.snapshot = undefined;\n this.taken = undefined;\n const commits = this.access === 'write' || (this.access === 'both' && this.wrote);\n if (!commits || this.failed || this.aborted) return;\n const bytes = joined(this.chunks, this.size);\n this.chunks = [];\n this.size = 0;\n let text: string;\n try {\n text = decoder.decode(bytes);\n } catch {\n throw new KernelError('EILSEQ', 'the text is not valid UTF-8');\n }\n const stamp = this.stamp;\n await this.broker.ask(async (hook) => {\n await hook.write(text, stamp);\n });\n }\n}\n\nexport class ClipboardBroker {\n readonly hook: ClipboardHook | undefined;\n readonly users: UsersMode;\n readonly timeoutMs: number;\n readonly tagOf: (pid: number) => readonly string[] | undefined;\n\n constructor(\n hook: ClipboardHook | undefined,\n users: UsersMode,\n timeoutMs = CLIPBOARD_TIMEOUT_MS,\n tagOf: (pid: number) => readonly string[] | undefined = () => undefined\n ) {\n this.hook = hook;\n this.users = users;\n this.timeoutMs = timeoutMs;\n this.tagOf = tagOf;\n }\n\n async ask<T>(work: (hook: ClipboardHook) => Promise<T>): Promise<T> {\n const hook = this.hook;\n if (!hook) throw new KernelError('ENOTSUP', 'no clipboard in this embedder');\n let timer: ReturnType<typeof setTimeout> | undefined;\n const late = new Promise<never>((_, reject) => {\n timer = setTimeout(\n () => reject(new KernelError('EIO', 'clipboard timed out')),\n this.timeoutMs\n );\n });\n const asked = Promise.resolve()\n .then(() => work(hook))\n .catch((err: unknown) => {\n throw clipboardFailure(err);\n });\n try {\n return await Promise.race([asked, late]);\n } finally {\n clearTimeout(timer);\n }\n }\n\n open(access: OpenAccess, stamp: ClipboardStamp): OpenFile {\n const channel = new ClipboardChannel(this, access, stamp);\n return new OpenFile({\n read: (max, signal) => channel.read(max, signal),\n write: async (bytes) => channel.write(bytes),\n poll: () => channel.poll(),\n close: () => channel.close(),\n clipboard: channel,\n });\n }\n}\n\nexport type { ClipboardChannel };\n", "import {\n CLIPBOARD_TIMEOUT_MS,\n type ClipboardHook,\n type ClipboardStamp,\n} from './kernel/clipboard.ts';\n\nexport interface ClipboardPort {\n postMessage(message: unknown): void;\n}\n\nexport interface ClipboardAsk {\n id: number;\n op: 'read' | 'write';\n text?: string;\n stamp: ClipboardStamp;\n}\n\nexport interface ClipboardReply {\n id: number;\n text?: string;\n error?: { name: string; message: string };\n}\n\nexport function clipboardAsker(port: ClipboardPort): {\n hook: ClipboardHook;\n answer(reply: ClipboardReply): void;\n} {\n const asks = new Map<number, PromiseWithResolvers<string | undefined>>();\n let next = 0;\n const ask = (op: 'read' | 'write', stamp: ClipboardStamp, text?: string) => {\n const id = ++next;\n const waiting = Promise.withResolvers<string | undefined>();\n asks.set(id, waiting);\n const timer = setTimeout(() => {\n if (asks.delete(id)) waiting.reject(new Error('clipboard timed out'));\n }, CLIPBOARD_TIMEOUT_MS + 1000);\n port.postMessage({ clipboardAsk: { id, op, stamp, ...(text !== undefined ? { text } : {}) } });\n return waiting.promise.finally(() => clearTimeout(timer));\n };\n const hook: ClipboardHook = {\n read: async (stamp) => (await ask('read', stamp)) ?? '',\n write: async (text, stamp) => {\n await ask('write', stamp, text);\n },\n };\n const answer = ({ id, text, error }: ClipboardReply) => {\n const waiting = asks.get(id);\n if (!waiting) return;\n asks.delete(id);\n if (error) waiting.reject(Object.assign(new Error(error.message), { name: error.name }));\n else waiting.resolve(text);\n };\n return { hook, answer };\n}\n\nexport function clipboardAnswerer(\n port: ClipboardPort,\n hook: ClipboardHook | undefined\n): { handle(data: unknown): boolean } {\n const ask = async ({ id, op, text, stamp }: ClipboardAsk): Promise<void> => {\n try {\n if (!hook) throw new Error('no clipboard in this embedder');\n if (op === 'read') {\n const got = await hook.read(stamp);\n if (typeof got !== 'string') throw new Error('the clipboard gave no text');\n port.postMessage({ clipboardReply: { id, text: got } });\n } else {\n await hook.write(text ?? '', stamp);\n port.postMessage({ clipboardReply: { id } });\n }\n } catch (err) {\n const name = (err as { name?: unknown } | null)?.name;\n const message = err instanceof Error ? err.message : String(err);\n port.postMessage({\n clipboardReply: { id, error: { name: typeof name === 'string' ? name : 'Error', message } },\n });\n }\n };\n return {\n handle(data) {\n const message = data as { clipboardAsk?: ClipboardAsk } | null;\n if (!message?.clipboardAsk) return false;\n void ask(message.clipboardAsk);\n return true;\n },\n };\n}\n", "import type {\n EmbedderHook,\n EmbedderKindPolicy,\n EmbedderReply,\n EmbedderStamp,\n} from './kernel/embedder.ts';\n\nexport interface EmbedderPort {\n postMessage(message: unknown, transfer?: Transferable[]): void;\n}\n\ntype Kinds = Readonly<Record<string, EmbedderKindPolicy>>;\n\nexport interface EmbedderAsk {\n id: number;\n client: number;\n kind: string;\n options: Record<string, unknown>;\n stamp: EmbedderStamp;\n}\n\nexport type EmbedderToPage =\n | { ask: EmbedderAsk }\n | { id: number; body: Uint8Array }\n | { id: number; bodyEnd: true }\n | { id: number; pull: true }\n | { id: number; cancel: string };\n\nexport type EmbedderToKernel =\n | { id: number; ready: true }\n | { id: number; chunk: Uint8Array }\n | { id: number; done: true }\n | { id: number; error: { name: string; message: string } }\n | { id: number; progress: string }\n | { id: number; bodyPull: true }\n | { id: number; bodyCancel: true };\n\nfunction fresh(bytes: Uint8Array): Uint8Array {\n return bytes.byteOffset === 0 && bytes.byteLength === bytes.buffer.byteLength\n ? bytes\n : bytes.slice();\n}\n\nfunction errorOf(err: unknown): { name: string; message: string } {\n const name = (err as { name?: unknown } | null)?.name;\n const message = err instanceof Error ? err.message : String(err);\n return { name: typeof name === 'string' ? name : 'Error', message };\n}\n\ninterface Asked {\n ready: PromiseWithResolvers<void>;\n chunks: Array<Uint8Array | null | { name: string; message: string }>;\n wake: (() => void) | undefined;\n body: ReadableStreamDefaultReader<Uint8Array>;\n progress(line: string): void;\n}\n\nexport function embedderAsker(port: EmbedderPort) {\n const asks = new Map<number, Asked>();\n let next = 0;\n const post = (message: EmbedderToPage, transfer: Transferable[] = []) =>\n port.postMessage({ embedder: message }, transfer);\n const push = (asked: Asked, item: Asked['chunks'][number]) => {\n asked.chunks.push(item);\n asked.wake?.();\n };\n const reply = (id: number, asked: Asked) =>\n new ReadableStream<Uint8Array>(\n {\n pull: async (controller) => {\n if (asked.chunks.length === 0) {\n post({ id, pull: true });\n await new Promise<void>((resolve) => {\n asked.wake = resolve;\n });\n }\n const item = asked.chunks.shift();\n if (item instanceof Uint8Array) controller.enqueue(item);\n else if (item === null || item === undefined) {\n asks.delete(id);\n controller.close();\n } else {\n asks.delete(id);\n controller.error(Object.assign(new Error(item.message), { name: item.name }));\n }\n },\n cancel: (reason) => {\n asks.delete(id);\n post({ id, cancel: String(reason ?? 'closed') });\n },\n },\n { highWaterMark: 0 }\n );\n const sendBody = async (id: number, asked: Asked) => {\n const got = await asked.body.read().catch(() => ({ done: true as const, value: undefined }));\n if (got.done) post({ id, bodyEnd: true });\n else {\n const bytes = fresh(got.value);\n post({ id, body: bytes }, [bytes.buffer as ArrayBuffer]);\n }\n };\n const hookFor = (client: number, kinds: Kinds): EmbedderHook => ({\n kinds,\n handle: async (request) => {\n const id = ++next;\n const asked: Asked = {\n ready: Promise.withResolvers<void>(),\n chunks: [],\n wake: undefined,\n body: request.body.getReader(),\n progress: request.progress,\n };\n asks.set(id, asked);\n const cancel = () => {\n asks.delete(id);\n post({\n id,\n cancel: String((request.signal.reason as Error | undefined)?.message ?? 'closed'),\n });\n asked.ready.reject(request.signal.reason);\n push(asked, { name: 'AbortError', message: 'cancelled' });\n };\n request.signal.addEventListener('abort', cancel, { once: true });\n const { kind, options, stamp } = request;\n post({ ask: { id, client, kind, options, stamp } });\n await asked.ready.promise;\n return reply(id, asked);\n },\n });\n const answer = (message: EmbedderToKernel): void => {\n const asked = asks.get(message.id);\n if (!asked) return;\n if ('ready' in message) asked.ready.resolve();\n else if ('chunk' in message) push(asked, message.chunk);\n else if ('done' in message) push(asked, null);\n else if ('error' in message) {\n asked.ready.reject(\n Object.assign(new Error(message.error.message), { name: message.error.name })\n );\n asks.delete(message.id);\n void asked.body.cancel(message.error.message).catch(() => undefined);\n push(asked, message.error);\n } else if ('progress' in message) asked.progress(message.progress);\n else if ('bodyCancel' in message) void asked.body.cancel('the page').catch(() => undefined);\n else void sendBody(message.id, asked);\n };\n return { hookFor, answer };\n}\n\nfunction bytesOf(reply: EmbedderReply): ReadableStream<Uint8Array> {\n if (reply instanceof ReadableStream) return reply;\n const bytes =\n typeof reply === 'string'\n ? new TextEncoder().encode(reply)\n : reply instanceof Uint8Array\n ? reply\n : new Uint8Array(0);\n return new ReadableStream({\n start(controller) {\n if (bytes.length > 0) controller.enqueue(bytes);\n controller.close();\n },\n });\n}\n\ninterface Answering {\n abort: AbortController;\n body: Array<Uint8Array | null>;\n wakeBody: (() => void) | undefined;\n reader?: ReadableStreamDefaultReader<Uint8Array>;\n}\n\nfunction bodyStream(id: number, state: Answering, post: (m: EmbedderToKernel) => void) {\n return new ReadableStream<Uint8Array>(\n {\n pull: async (controller) => {\n if (state.body.length === 0) post({ id, bodyPull: true });\n while (state.body.length === 0 && !state.abort.signal.aborted) {\n await new Promise<void>((resolve) => {\n state.wakeBody = resolve;\n });\n }\n const next = state.body.shift();\n if (next) controller.enqueue(next);\n else controller.close();\n },\n cancel: () => post({ id, bodyCancel: true }),\n },\n { highWaterMark: 0 }\n );\n}\n\nexport function embedderAnswerer(\n port: EmbedderPort,\n hookFor: (client: number) => EmbedderHook | undefined\n): { handle(data: unknown): boolean } {\n const running = new Map<number, Answering>();\n const post = (message: EmbedderToKernel, transfer: Transferable[] = []) =>\n port.postMessage({ embedderReply: message }, transfer);\n const fail = (id: number, err: unknown) => {\n running.delete(id);\n post({ id, error: errorOf(err) });\n };\n const start = async (ask: EmbedderAsk) => {\n const state: Answering = { abort: new AbortController(), body: [], wakeBody: undefined };\n running.set(ask.id, state);\n try {\n const hook = hookFor(ask.client);\n if (!hook || !Object.hasOwn(hook.kinds, ask.kind))\n throw Object.assign(new Error(`this page does not answer ${ask.kind}`), {\n name: 'NotSupportedError',\n });\n const body = bodyStream(ask.id, state, post);\n const reply = await hook.handle({\n kind: ask.kind,\n options: ask.options,\n body,\n stamp: ask.stamp,\n signal: state.abort.signal,\n progress: (line) => post({ id: ask.id, progress: String(line) }),\n });\n if (!(reply instanceof ReadableStream)) post({ id: ask.id, bodyCancel: true });\n state.reader = bytesOf(reply).getReader();\n post({ id: ask.id, ready: true });\n } catch (err) {\n fail(ask.id, err);\n }\n };\n const pull = async (id: number, state: Answering) => {\n try {\n const got = await (state.reader as ReadableStreamDefaultReader<Uint8Array>).read();\n if (got.done) {\n running.delete(id);\n post({ id, done: true });\n return;\n }\n const bytes = fresh(got.value);\n post({ id, chunk: bytes }, [bytes.buffer as ArrayBuffer]);\n } catch (err) {\n fail(id, err);\n }\n };\n const step = (message: Exclude<EmbedderToPage, { ask: EmbedderAsk }>) => {\n const state = running.get(message.id);\n if (!state) return;\n if ('body' in message) state.body.push(message.body);\n else if ('bodyEnd' in message) state.body.push(null);\n else if ('pull' in message) void pull(message.id, state);\n else {\n running.delete(message.id);\n state.abort.abort(new DOMException(message.cancel, 'AbortError'));\n void state.reader?.cancel(message.cancel).catch(() => undefined);\n }\n state.wakeBody?.();\n };\n return {\n handle(data) {\n const message = (data as { embedder?: EmbedderToPage } | null)?.embedder;\n if (!message) return false;\n if ('ask' in message) void start(message.ask);\n else step(message);\n return true;\n },\n };\n}\n\nexport function embedderReplyOf(data: unknown): EmbedderToKernel | undefined {\n return (data as { embedderReply?: EmbedderToKernel } | null)?.embedderReply;\n}\n", "import type { ConnectorStamp } from '../kernel/socket.ts';\nimport type { FacadeConnection, FacadeHook, FacadeOpenRequest } from './types.ts';\n\nexport interface FacadePortLike {\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 FacadeWire = { open: true } | { error: string } | { b: Uint8Array } | { close: true | string };\n\nexport interface FacadeOpen {\n facadeOpen: FacadeOpenRequest & { registration?: number };\n port: FacadePortLike;\n}\n\nexport const FACADE_GONE = 'the facade host is gone';\n\nexport function serveFacadePort(\n port: FacadePortLike,\n hook: FacadeHook,\n { name, stamp }: FacadeOpenRequest,\n onDone?: () => void\n): () => void {\n let conn: FacadeConnection | undefined;\n let done = false;\n const end = () => {\n done = true;\n port.close();\n onDone?.();\n };\n const finish = () => {\n if (done) return;\n port.postMessage({ close: true });\n end();\n };\n port.addEventListener(\n 'message',\n ({ data }: MessageEvent<{ b?: Uint8Array; close?: true | string }>) => {\n if (data.b !== undefined) conn?.send(data.b);\n else if (data.close && !done) {\n end();\n conn?.close(typeof data.close === 'string' ? data.close : undefined);\n }\n }\n );\n port.start?.();\n new Promise<FacadeConnection>((resolve) => resolve(hook(stamp, { name }))).then(\n (opened) => {\n conn = opened;\n if (done) return opened.close();\n opened.onmessage = (bytes) => {\n if (done) return;\n const copy = bytes.slice();\n port.postMessage({ b: copy }, [copy.buffer]);\n };\n opened.onclose = () => finish();\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();\n };\n}\n\nexport function portFacadeHook(\n ask: (request: FacadeOpenRequest, port: FacadePortLike) => void,\n gone?: Promise<unknown>\n): FacadeHook {\n return (stamp: ConnectorStamp, { name }) =>\n new Promise((resolve, reject) => {\n const { port1, port2 } = new MessageChannel();\n let closed = false;\n const shut = () => {\n closed = true;\n port1.close();\n };\n const conn: FacadeConnection = {\n send: (bytes) => {\n if (closed) return;\n const copy = bytes.slice();\n port1.postMessage({ b: copy }, [copy.buffer]);\n },\n onmessage: null,\n onclose: null,\n close: (reason) => {\n if (closed) return;\n port1.postMessage({ close: reason ?? true });\n shut();\n },\n };\n port1.addEventListener('message', ({ data }: MessageEvent<FacadeWire>) => {\n if ('b' in data) conn.onmessage?.(data.b);\n else if ('open' in data) resolve(conn);\n else if ('error' in data) {\n shut();\n reject(new Error(data.error));\n } else if (!closed) {\n shut();\n conn.onclose?.();\n }\n });\n port1.start();\n void gone?.then(() => {\n if (closed) return;\n shut();\n reject(new Error(FACADE_GONE));\n conn.onclose?.(FACADE_GONE);\n });\n ask({ name, stamp }, port2 as unknown as FacadePortLike);\n });\n}\n", "export interface FsStat {\n isFile: boolean;\n isDirectory: boolean;\n isSymbolicLink: boolean;\n isSocket?: boolean;\n isFifo?: boolean;\n size: number;\n mode: number;\n mtime: Date;\n atime: Date;\n ctime: Date;\n ino: number;\n fid?: string;\n nlink?: number;\n dev?: number;\n readonly?: boolean;\n maxFile?: number;\n ranged?: boolean;\n linkable?: boolean;\n version?: string;\n uid?: number;\n gid?: number;\n}\n\nexport type UsersMode = 'off' | 'report' | 'enforce';\n\nexport const DEFAULT_USERS: UsersMode = 'enforce';\n\nexport interface Owner {\n uid: number;\n gid: number;\n}\n\nexport interface Perm {\n uid: number;\n gid: number;\n mode?: number;\n link?: string;\n}\n\nexport interface NewOwner extends Owner {\n mode?: number;\n parents?: number;\n socket?: boolean;\n fifo?: boolean;\n existing?: true;\n}\n\nexport interface CopyOptions {\n exclusive: boolean;\n owner?: NewOwner;\n}\n\nexport interface OwnerChange {\n uid?: number;\n gid?: number;\n follow?: boolean;\n kind?: 'chown' | 'adopt' | 'new';\n mode?: number;\n}\n\nexport interface HeldEntry {\n writeFile: KernelFs['writeFile'];\n direct: boolean;\n}\n\nexport interface Peers {\n joined(): Promise<unknown>;\n crowded(): boolean;\n watch(listener: (crowded: boolean) => void): void;\n fresh?(): void;\n}\n\nexport interface KernelFs {\n resolvePath(base: string, path: string): string;\n exclusive?<T>(path: string, run: (held: HeldEntry) => Promise<T>, follow?: boolean): Promise<T>;\n readFile(path: string): Promise<string>;\n readFileBuffer(path: string): Promise<Uint8Array>;\n writeFile(path: string, content: Uint8Array | string, owner?: NewOwner): Promise<void>;\n exists(path: string): Promise<boolean>;\n stat(path: string): Promise<FsStat>;\n lstat(path: string): Promise<FsStat>;\n readdir(path: string): Promise<string[]>;\n readdirStat(path: string): Promise<Array<[string, FsStat | null]>>;\n mkdir(path: string, options?: { recursive?: boolean; owner?: NewOwner }): Promise<void>;\n rm(\n path: string,\n options?: { recursive?: boolean; force?: boolean; file?: boolean }\n ): Promise<void>;\n rename(from: string, to: string): Promise<void>;\n link(from: string, to: string, follow?: boolean): Promise<void>;\n links?(path: string): boolean;\n symlink(target: string, path: string, owner?: NewOwner): Promise<void>;\n readlink(path: string): Promise<string>;\n realpath?(path: string, follow: boolean): Promise<string>;\n createExclusive?(path: string, owner?: NewOwner): Promise<void>;\n copyFile?(from: string, to: string, options: CopyOptions): Promise<void>;\n readonly rootName?: string;\n chown?(path: string, change: OwnerChange): Promise<void>;\n trackOwners?(): void;\n onPeer?(settle: () => Promise<void>): void;\n heldBy?(held: (dir: string) => readonly string[]): void;\n fileId?(path: string): Promise<string>;\n bindId?(path: string): Promise<string | undefined>;\n remoteChanges?(\n listener: (change: {\n paths: readonly string[];\n trees?: readonly string[];\n moved?: { from: string; to: string };\n content?: true;\n outside?: true;\n }) => void\n ): () => void;\n refresh?(trees: readonly string[]): void;\n peers?(): Peers | undefined;\n crossings?(mounted: (path: string) => boolean): void;\n ancestry?(path: string): Promise<Array<Perm | undefined>>;\n hasOwner?(path: string): Promise<boolean>;\n chmod(path: string, mode: number): Promise<void>;\n append?(path: string, bytes: Uint8Array, options?: PwriteOptions): Promise<number>;\n utimes(path: string, atime: Date, mtime: Date): Promise<void>;\n lutimes?(path: string, atime: Date, mtime: Date): Promise<void>;\n pread?(path: string, offset: number, length: number, version?: string): Promise<Uint8Array>;\n pwrite?(\n path: string,\n offset: number,\n bytes: Uint8Array,\n transfer?: boolean,\n options?: PwriteOptions\n ): Promise<void>;\n truncate?(path: string, size: number): Promise<void>;\n protect?(prefixes: readonly string[], versions?: boolean): void;\n unguarded?(): KernelFs;\n noLinks?(): KernelFs;\n mayChange?(path: string, follow: boolean, whole?: boolean): Promise<void>;\n commandTarget?(path: string): Promise<string | undefined>;\n readVersioned?(path: string, cached?: boolean): Promise<{ bytes: Uint8Array; version: string }>;\n version?(path: string, cached?: boolean): Promise<string>;\n opfsCalls?(): number;\n renameWaits?(): {\n acks: number;\n busy: number;\n waits: number;\n queries: number;\n ackMs: readonly number[];\n };\n opfsOps?(): number;\n metaTransactions?(): { reads: number; writes: number } | undefined;\n fileIdWrites?(): number;\n announceHolds?(\n add: ReadonlyArray<[string, string | undefined]>,\n drop: readonly string[],\n wait: boolean\n ): Promise<void>;\n holdCounts?(): { mine: number; peers: number; sent: number; held: string[] } | undefined;\n peerHolds?(listener: (paths: string[]) => void): void;\n rehold?(from: string, to: string): void;\n peerKeeps?(): PeerKeeps | undefined;\n servePeerKeeps?(\n instance: string,\n handlers: {\n keeping(tab: string, paths: readonly string[]): Promise<void>;\n kept(\n tab: string,\n items: ReadonlyArray<{\n path: string;\n hidden: string | undefined;\n fid: string | undefined;\n }>,\n paths: readonly string[]\n ): Promise<void>;\n left(tab: string): void;\n }\n ): void;\n}\n\nexport interface PeerKeeps {\n shared(): boolean;\n heldWithin(\n path: string\n ): Array<{ tab: string; path: string; fid: string | undefined; instance: string | undefined }>;\n ask(\n to: string,\n body: {\n keeping?: { paths: string[] };\n kept?: {\n items: Array<{\n path: string;\n hidden: string | undefined;\n fid: string | undefined;\n }>;\n paths?: string[];\n };\n },\n cap: number\n ): Promise<boolean>;\n}\n\nexport interface PwriteOptions {\n create?: false;\n alone?: true;\n}\n\nexport type RangedOps = Required<Pick<KernelFs, 'pread' | 'pwrite' | 'truncate'>>;\n\nexport function rangedOps(fs: Partial<RangedOps>): RangedOps | undefined {\n const { pread, pwrite, truncate } = fs;\n if (!pread || !pwrite || !truncate) return undefined;\n return { pread: pread.bind(fs), pwrite: pwrite.bind(fs), truncate: truncate.bind(fs) };\n}\n\nexport async function lutimesOf(\n fs: KernelFs,\n path: string,\n atime: Date,\n mtime: Date\n): Promise<void> {\n if (fs.lutimes) return fs.lutimes(path, atime, mtime);\n if ((await fs.lstat(path)).isSymbolicLink) throw fsError('EOPNOTSUPP', path);\n return fs.utimes(path, atime, mtime);\n}\n\nexport function mayLink(fs: { links?(path: string): boolean }, path: string): boolean {\n return fs.links?.(path) ?? true;\n}\n\nexport function modeOption(mode: unknown): number {\n if (!Number.isInteger(mode) || (mode as number) < 0 || (mode as number) > 0o7777) {\n throw fsError('EINVAL', `not a mode: ${String(mode)}`);\n }\n return mode as number;\n}\n\nexport function fsError(code: string, path: string): Error & { code: string } {\n return Object.assign(new Error(`${code}: ${path}`), { code });\n}\n\nexport function normalizePath(path: string): string {\n const parts: string[] = [];\n for (const part of path.split('/')) {\n if (part === '' || part === '.') continue;\n if (part === '..') parts.pop();\n else parts.push(part);\n }\n return `/${parts.join('/')}`;\n}\n\nexport function resolvePath(base: string, path: string): string {\n return normalizePath(path.startsWith('/') ? path : `${base}/${path}`);\n}\n\nexport function inodeOf(path: string): number {\n let h1 = 0xdeadbeef;\n let h2 = 0x41c6ce57;\n for (let i = 0; i < path.length; i++) {\n const c = path.charCodeAt(i);\n h1 = Math.imul(h1 ^ c, 2654435761);\n h2 = Math.imul(h2 ^ c, 1597334677);\n }\n h1 = Math.imul(h1 ^ (h1 >>> 16), 2246822507) ^ Math.imul(h2 ^ (h2 >>> 13), 3266489909);\n h2 = Math.imul(h2 ^ (h2 >>> 16), 2246822507) ^ Math.imul(h1 ^ (h1 >>> 13), 3266489909);\n return 4294967296 * (2097151 & h2) + (h1 >>> 0) || 1;\n}\n\nexport interface Redirect {\n of: string;\n to: string;\n}\n\nexport function redirected(of: string, to: string): Error {\n return Object.assign(fsError('EXDEV', `${of} leads to the mount at ${to}`), {\n redirect: { of: normalizePath(of), to: normalizePath(to) },\n });\n}\n\nexport function redirectOf(err: unknown): Redirect | undefined {\n return (err as { redirect?: Redirect } | null)?.redirect;\n}\n", "import { type IntegrityOptions, integritySources, integrityUnknown } from './integrity.ts';\nimport {\n type FsStat,\n fsError,\n type HeldEntry,\n type KernelFs,\n normalizePath,\n type PwriteOptions,\n} from './types.ts';\n\nexport interface Protection {\n readonly paths: readonly string[];\n readonly writers?: readonly string[];\n readonly integrity?: IntegrityOptions;\n}\n\nexport interface ProtectInit {\n paths: string[];\n writers?: string[];\n integrity?: { unknown: 'allow' | 'deny'; sources?: readonly string[] };\n}\n\nexport function protectInit(protection: ProtectInit | Protection): ProtectInit {\n const writers = [...writerTags(protection as Protection)];\n const { integrity } = protection;\n return {\n paths: [...protection.paths],\n ...(writers.length > 0 ? { writers } : {}),\n ...(integrity ? { integrity: integrityInit(integrity) } : {}),\n };\n}\n\nfunction integrityInit(integrity: {\n unknown?: string;\n sources?: readonly string[];\n}): NonNullable<ProtectInit['integrity']> {\n const unknown = integrityUnknown(integrity);\n return integrity.sources === undefined\n ? { unknown }\n : { unknown, sources: integritySources(integrity) };\n}\n\nexport function writerTags(protection: Protection | undefined): ReadonlySet<string> {\n const writers = protection?.writers ?? [];\n if (!Array.isArray(writers) || writers.some((tag) => typeof tag !== 'string' || tag === '')) {\n throw new TypeError('protect.writers must be a list of process tags');\n }\n return new Set(writers);\n}\n\nexport function protectedPrefixes(paths: readonly string[]): string[] {\n if (!Array.isArray(paths) || paths.some((p) => typeof p !== 'string' || !p.startsWith('/'))) {\n throw new TypeError('protect.paths must be a list of absolute paths');\n }\n return [...new Set(paths.map((p) => normalizePath(p)))];\n}\n\nfunction within(path: string, prefix: string): boolean {\n return prefix === '/' || path === prefix || path.startsWith(`${prefix}/`);\n}\n\nexport function isProtected(prefixes: readonly string[], path: string): boolean {\n return prefixes.some((prefix) => within(path, prefix));\n}\n\nexport function holdsProtected(prefixes: readonly string[], path: string): boolean {\n return prefixes.some((prefix) => within(prefix, path));\n}\n\nconst MAX_LINKS = 40;\n\nfunction partsOf(path: string): string[] {\n return path.split('/').filter((p) => p !== '' && p !== '.');\n}\n\nfunction missing(err: unknown): boolean {\n const code = (err as { code?: unknown } | null)?.code;\n return code === 'ENOENT' || code === 'ENOTDIR';\n}\n\nasync function resolved(\n fs: KernelFs,\n path: string,\n follow: boolean,\n hops: string[] = []\n): Promise<string> {\n let done: string[] = [];\n let todo = partsOf(path);\n for (let links = 0; todo.length > 0; ) {\n const part = todo.shift() as string;\n if (part === '..') {\n done.pop();\n continue;\n }\n if (todo.length === 0 && !follow) {\n done.push(part);\n break;\n }\n const at = `/${[...done, part].join('/')}`;\n const st = await fs.lstat(at).catch((err: unknown) => {\n if (missing(err)) return undefined;\n throw err;\n });\n if (!st) {\n return normalizePath([...done, part, ...todo].join('/'));\n }\n if (!st.isSymbolicLink) {\n done.push(part);\n continue;\n }\n if (++links > MAX_LINKS) throw fsError('ELOOP', path);\n hops.push(normalizePath([at, ...todo].join('/')));\n const link = await fs.readlink(at);\n if (link.startsWith('/')) done = [];\n todo = [...partsOf(link), ...todo];\n }\n return `/${done.join('/')}`;\n}\n\nexport async function namesOf(fs: KernelFs, path: string): Promise<string[]> {\n const lexical = normalizePath(path);\n const hops: string[] = [];\n await resolved(fs, lexical, true, hops).catch(() => undefined);\n return [lexical, ...hops];\n}\n\nexport class ProtectedFs {\n private readonly prefixes: readonly string[];\n\n constructor(prefixes: readonly string[]) {\n this.prefixes = prefixes;\n }\n\n async check(fs: KernelFs, path: string, follow: boolean, whole = false): Promise<void> {\n const lexical = normalizePath(path);\n const real = await resolved(fs, lexical, follow);\n for (const p of new Set([lexical, real])) {\n if (isProtected(this.prefixes, p) || (whole && holdsProtected(this.prefixes, p))) {\n throw fsError('EROFS', path);\n }\n }\n }\n\n view(fs: KernelFs): KernelFs {\n const check = (path: string, follow: boolean, whole = false) =>\n this.check(fs, path, follow, whole);\n const marked = (path: string, st: FsStat): FsStat =>\n !st.readonly && isProtected(this.prefixes, normalizePath(path))\n ? { ...st, readonly: true }\n : st;\n const own: Partial<KernelFs> = {\n async writeFile(...args: Parameters<KernelFs['writeFile']>) {\n await check(args[0], true);\n return fs.writeFile(...args);\n },\n async mkdir(...args: Parameters<KernelFs['mkdir']>) {\n await check(args[0], false);\n return fs.mkdir(...args);\n },\n async rm(...args: Parameters<KernelFs['rm']>) {\n await check(args[0], false, true);\n return fs.rm(...args);\n },\n async rename(from: string, to: string) {\n await check(from, false, true);\n await check(to, false, true);\n return fs.rename(from, to);\n },\n async link(from: string, to: string, follow?: boolean) {\n await check(from, follow === true);\n await check(to, false);\n return fs.link(from, to, follow);\n },\n async symlink(...args: Parameters<KernelFs['symlink']>) {\n await check(args[1], false);\n return fs.symlink(...args);\n },\n async chmod(path: string, mode: number) {\n await check(path, true);\n return fs.chmod(path, mode);\n },\n async utimes(path: string, atime: Date, mtime: Date) {\n await check(path, true);\n return fs.utimes(path, atime, mtime);\n },\n async mayChange(path: string, follow: boolean, whole = false) {\n await check(path, follow, whole);\n },\n async stat(path: string) {\n return marked(path, await fs.stat(path));\n },\n async lstat(path: string) {\n return marked(path, await fs.lstat(path));\n },\n async readdirStat(path: string) {\n const dir = normalizePath(path);\n return (await fs.readdirStat(path)).map(([name, st]): [string, FsStat | null] => [\n name,\n st && marked(`${dir}/${name}`, st),\n ]);\n },\n ...(fs.copyFile\n ? {\n async copyFile(...args: Parameters<NonNullable<KernelFs['copyFile']>>) {\n await check(args[1], false);\n return fs.copyFile?.(...args);\n },\n }\n : {}),\n ...(fs.createExclusive\n ? {\n async createExclusive(...args: Parameters<NonNullable<KernelFs['createExclusive']>>) {\n await check(args[0], true);\n return fs.createExclusive?.(...args);\n },\n }\n : {}),\n ...(fs.chown\n ? {\n async chown(...args: Parameters<NonNullable<KernelFs['chown']>>) {\n await check(args[0], args[1].follow !== false);\n return fs.chown?.(...args);\n },\n }\n : {}),\n ...(fs.lutimes\n ? {\n async lutimes(path: string, atime: Date, mtime: Date) {\n await check(path, false);\n return fs.lutimes?.(path, atime, mtime);\n },\n }\n : {}),\n ...(fs.pwrite\n ? {\n async pwrite(...args: Parameters<NonNullable<KernelFs['pwrite']>>) {\n await check(args[0], true);\n return fs.pwrite?.(...args);\n },\n }\n : {}),\n ...(fs.append\n ? {\n async append(path: string, bytes: Uint8Array, options?: PwriteOptions) {\n await check(path, true);\n return (fs.append as NonNullable<KernelFs['append']>).call(fs, path, bytes, options);\n },\n }\n : {}),\n ...(fs.truncate\n ? {\n async truncate(path: string, size: number) {\n await check(path, true);\n return fs.truncate?.(path, size);\n },\n }\n : {}),\n ...(fs.exclusive\n ? {\n async exclusive<T>(\n path: string,\n run: (held: HeldEntry) => Promise<T>,\n follow?: boolean\n ): Promise<T> {\n return (fs.exclusive as NonNullable<KernelFs['exclusive']>)(\n path,\n (held) =>\n run({\n ...held,\n writeFile: async (...args: Parameters<KernelFs['writeFile']>) => {\n await check(args[0], true);\n return held.writeFile(...args);\n },\n }),\n follow\n );\n },\n }\n : {}),\n };\n const view: Record<string, unknown> = {};\n for (\n let at: object | null = fs;\n at && at !== Object.prototype;\n at = Object.getPrototypeOf(at)\n ) {\n for (const name of Object.getOwnPropertyNames(at)) {\n if (name === 'constructor' || Object.hasOwn(view, name)) continue;\n const value = (fs as unknown as Record<string, unknown>)[name];\n view[name] = typeof value === 'function' ? value.bind(fs) : value;\n }\n }\n return Object.assign(view, own) as unknown as KernelFs;\n }\n}\n", "import type { DenialHook } from './dac.ts';\nimport { isProtected, namesOf } from './protect.ts';\nimport { fsError, type KernelFs, normalizePath } from './types.ts';\n\nexport type IntegrityLookup = (path: string) => string | undefined | Promise<string | undefined>;\n\nexport interface IntegrityOptions {\n readonly lookup: IntegrityLookup;\n readonly unknown?: 'allow' | 'deny';\n readonly sources?: readonly string[];\n}\n\nexport const SOURCE_SUFFIXES: readonly string[] = [\n '.js',\n '.mjs',\n '.cjs',\n '.json',\n '.py',\n '.pyc',\n '.pth',\n '.zip',\n '.so',\n '.wasm',\n '.sh',\n];\n\nconst EXEC_OPS = { failed: 'exec-integrity', unknown: 'exec-unverified' } as const;\nconst READ_OPS = { failed: 'read-integrity', unknown: 'read-unverified' } as const;\n\ntype Ops = typeof EXEC_OPS | typeof READ_OPS;\n\nexport interface IntegrityCaller {\n pid: number;\n uid: number;\n tag?: string | undefined;\n}\n\ninterface Checked {\n real: string;\n name: string;\n}\n\nexport const KERNEL_CALLER: IntegrityCaller = { pid: 0, uid: 0 };\n\nexport function integrityOptions(options: IntegrityOptions | undefined): void {\n if (options && typeof options.lookup !== 'function') {\n throw new TypeError('protect.integrity.lookup must be a function');\n }\n integrityUnknown(options);\n integritySources(options);\n}\n\nexport function integritySources(options: { sources?: unknown } | undefined): readonly string[] {\n const sources = options?.sources ?? SOURCE_SUFFIXES;\n const suffix = (s: unknown) => typeof s === 'string' && /^\\.[^/]+$/.test(s);\n if (!Array.isArray(sources) || !sources.every(suffix)) {\n throw new TypeError('protect.integrity.sources must be a list of suffixes such as .js');\n }\n return [...sources];\n}\n\nexport function integrityUnknown(options: { unknown?: string } | undefined): 'allow' | 'deny' {\n const unknown = options?.unknown ?? 'allow';\n if (unknown !== 'allow' && unknown !== 'deny') {\n throw new TypeError(\"protect.integrity.unknown must be 'allow' or 'deny'\");\n }\n return unknown;\n}\n\nfunction hex(digest: ArrayBuffer): string {\n return [...new Uint8Array(digest)].map((b) => b.toString(16).padStart(2, '0')).join('');\n}\n\nexport async function sha256(bytes: Uint8Array): Promise<string> {\n return hex(await crypto.subtle.digest('SHA-256', bytes as BufferSource));\n}\n\nexport class Integrity {\n private readonly prefixes: readonly string[];\n private readonly root: KernelFs;\n private readonly lookup: IntegrityLookup;\n private readonly unknown: 'allow' | 'deny';\n private readonly report: DenialHook;\n private readonly unverified = new Set<string>();\n private readonly unread = new Set<string>();\n private readonly sources: readonly string[];\n private readonly passed = new Set<string>();\n private generation = 0;\n\n constructor(\n prefixes: readonly string[],\n root: KernelFs,\n options: IntegrityOptions,\n report: DenialHook\n ) {\n this.prefixes = prefixes;\n this.root = root;\n this.lookup = options.lookup;\n this.unknown = integrityUnknown(options);\n this.sources = integritySources(options);\n this.report = report;\n }\n\n private async real(path: string, asked?: string, known?: string): Promise<Checked | undefined> {\n const at = normalizePath(path);\n const real = known ?? (await this.root.realpath?.(at, true).catch(() => undefined)) ?? at;\n if (isProtected(this.prefixes, real)) return { real, name: real };\n const names = asked === undefined ? [] : await namesOf(this.root, asked);\n if (real !== at) names.push(...(await namesOf(this.root, at)));\n const name = names.findLast((p) => isProtected(this.prefixes, p));\n return name === undefined ? undefined : { real, name };\n }\n\n async key(path: string, asked?: string): Promise<string | undefined> {\n const found = await this.real(path, asked);\n if (found === undefined) return undefined;\n const { real, name } = found;\n if (name !== real) return `${name}\\0${real}\\0`;\n if (!this.root.version) return undefined;\n return `${real}\\0${await this.root.version(real)}`;\n }\n\n async read(\n path: string,\n caller: IntegrityCaller,\n plain: () => Promise<Uint8Array>,\n asked?: string\n ): Promise<Uint8Array> {\n return (await this.readKeyed(path, caller, plain, asked)).bytes;\n }\n\n async readKeyed(\n path: string,\n caller: IntegrityCaller,\n plain: () => Promise<Uint8Array>,\n asked?: string\n ): Promise<{ bytes: Uint8Array; key?: string }> {\n const found = await this.real(path, asked);\n if (found === undefined) return { bytes: await plain() };\n const { real, name } = found;\n const read =\n name !== real\n ? { bytes: await plain(), version: undefined }\n : this.root.readVersioned\n ? await this.root.readVersioned(real)\n : { bytes: await this.root.readFileBuffer(real), version: undefined };\n const { bytes } = read;\n const keyed =\n read.version === undefined ? { bytes } : { bytes, key: `${real}\\0${read.version}` };\n await this.verify(name, bytes, caller, EXEC_OPS);\n return keyed;\n }\n\n get readsChecked(): boolean {\n return this.sources.length > 0;\n }\n\n async readSource(\n path: string,\n caller: IntegrityCaller,\n plain: () => Promise<Uint8Array>\n ): Promise<Uint8Array> {\n const found = await this.source(path);\n return found === undefined ? plain() : this.checked(found, caller, plain);\n }\n\n async openSource(path: string, caller: IntegrityCaller, real?: string): Promise<void> {\n const found = await this.source(path, real);\n if (found === undefined) return;\n if (found.name === found.real && this.root.version) {\n if (this.passed.has(`${found.real}\\0${await this.root.version(found.real, true)}`)) return;\n }\n await this.checked(found, caller, () => this.root.readFileBuffer(found.real));\n }\n\n private async checked(\n found: Checked,\n caller: IntegrityCaller,\n plain: () => Promise<Uint8Array>\n ): Promise<Uint8Array> {\n const { real, name } = found;\n if (name !== real || !this.root.readVersioned) {\n const bytes = await plain();\n await this.verify(name, bytes, caller, READ_OPS);\n return bytes;\n }\n const { bytes, version } = await this.root.readVersioned(real, true);\n await this.pass(`${real}\\0${version}`, () => this.verify(name, bytes, caller, READ_OPS));\n return bytes;\n }\n\n private async pass(key: string, check: () => Promise<void>): Promise<void> {\n if (this.passed.has(key)) return;\n const generation = this.generation;\n await check();\n if (generation === this.generation) this.passed.add(key);\n }\n\n private async source(path: string, known?: string): Promise<Checked | undefined> {\n if (this.sources.length === 0) return undefined;\n const found = await this.real(path, undefined, known);\n if (found === undefined) return undefined;\n const suffixed = (p: string) => this.sources.some((s) => p.endsWith(s));\n if (suffixed(found.real) || suffixed(found.name) || suffixed(normalizePath(path))) return found;\n const st = await this.root.stat(found.real).catch(() => undefined);\n return st?.isFile && ((st.mode ?? 0) & 0o111) !== 0 ? found : undefined;\n }\n\n private async verify(\n name: string,\n bytes: Uint8Array,\n caller: IntegrityCaller,\n ops: Ops\n ): Promise<void> {\n const actual = await sha256(bytes);\n const denial = { pid: caller.pid, uid: caller.uid, path: name, actual };\n const tagged = caller.tag !== undefined ? { tag: caller.tag } : {};\n let expected: string | undefined;\n try {\n expected = await this.expected(name);\n } catch {\n this.say({ ...denial, ...tagged, op: ops.failed, errno: 'EACCES' });\n throw fsError('EACCES', `integrity lookup failed: ${name}`);\n }\n if (expected === actual) return;\n if (expected === undefined && this.unknown === 'allow') {\n const seen = ops === EXEC_OPS ? this.unverified : this.unread;\n if (!seen.has(name)) {\n seen.add(name);\n this.say({ ...denial, ...tagged, op: ops.unknown, errno: 'ENODATA' });\n }\n return;\n }\n const known = expected !== undefined ? { expected } : {};\n this.say({ ...denial, ...tagged, ...known, op: ops.failed, errno: 'EACCES' });\n throw fsError('EACCES', `integrity check failed: ${name}`);\n }\n\n forget(path?: string): void {\n this.generation++;\n for (const seen of [this.unverified, this.unread]) {\n for (const name of [...seen]) {\n if (path === undefined || isProtected([path], name)) seen.delete(name);\n }\n }\n for (const key of [...this.passed]) {\n if (path === undefined || isProtected([path], key.slice(0, key.indexOf('\\0')))) {\n this.passed.delete(key);\n }\n }\n }\n\n private async expected(path: string): Promise<string | undefined> {\n const answer = await this.lookup(path);\n return typeof answer === 'string' ? answer.toLowerCase() : undefined;\n }\n\n private say(event: Parameters<DenialHook>[0]): void {\n try {\n this.report(event);\n } catch {}\n }\n}\n", "export type Portable<T extends FileSystemHandle> = { handle: T } | { path: string[] };\n\ntype Top = () => Promise<FileSystemDirectoryHandle>;\n\nconst privateTop: Top = () => navigator.storage.getDirectory();\n\nexport function clonable(handle: FileSystemHandle): boolean {\n const { port1, port2 } = new MessageChannel();\n try {\n port1.postMessage(handle);\n return true;\n } catch (err) {\n if ((err as { name?: unknown } | null)?.name === 'DataCloneError') return false;\n throw err;\n } finally {\n port1.close();\n port2.close();\n }\n}\n\nexport async function portable<T extends FileSystemHandle>(\n handle: T,\n top: Top = privateTop\n): Promise<Portable<T>> {\n if (clonable(handle)) return { handle };\n const path = await (await top()).resolve(handle);\n if (path === null) {\n throw new Error(\n 'this browser cannot hand a folder to a worker unless it is in the origin private file system'\n );\n }\n return { path };\n}\n\nexport async function directoryAt(\n top: FileSystemDirectoryHandle,\n path: readonly string[]\n): Promise<FileSystemDirectoryHandle> {\n let dir = top;\n for (const name of path) dir = await dir.getDirectoryHandle(name);\n return dir;\n}\n\nexport const samePath = (a: readonly string[], b: readonly string[]): boolean =>\n a.length === b.length && a.every((name, at) => name === b[at]);\n", "import type { IntegrityLookup } from './fs/integrity.ts';\n\nexport interface IntegrityPort {\n postMessage(message: unknown): void;\n}\n\nexport interface IntegrityAsk {\n id: number;\n path: string;\n}\n\nexport interface IntegrityReply {\n id: number;\n hash?: string;\n error?: string;\n}\n\nexport function integrityAsker(port: IntegrityPort): {\n lookup: IntegrityLookup;\n answer(reply: IntegrityReply): void;\n} {\n const asks = new Map<number, PromiseWithResolvers<string | undefined>>();\n let next = 0;\n const lookup: IntegrityLookup = (path) => {\n const id = ++next;\n const waiting = Promise.withResolvers<string | undefined>();\n asks.set(id, waiting);\n port.postMessage({ integrityAsk: { id, path } });\n return waiting.promise;\n };\n const answer = ({ id, hash, error }: IntegrityReply) => {\n const waiting = asks.get(id);\n if (!waiting) return;\n asks.delete(id);\n if (error !== undefined) waiting.reject(new Error(error));\n else waiting.resolve(hash);\n };\n return { lookup, answer };\n}\n\nexport function integrityAnswerer(\n port: IntegrityPort,\n lookup: IntegrityLookup | undefined\n): (data: unknown) => boolean {\n const ask = async ({ id, path }: IntegrityAsk): Promise<void> => {\n try {\n const hash = lookup ? await lookup(path) : undefined;\n port.postMessage({ integrityReply: { id, ...(typeof hash === 'string' ? { hash } : {}) } });\n } catch (err) {\n const error = err instanceof Error ? err.message : String(err);\n port.postMessage({ integrityReply: { id, error } });\n }\n };\n return (data) => {\n const asked = (data as { integrityAsk?: IntegrityAsk } | null)?.integrityAsk;\n if (!asked) return false;\n void ask(asked);\n return true;\n };\n}\n", "import type { DenialHook } from '../fs/dac.ts';\nimport type { UsersMode } from '../fs/types.ts';\nimport { KernelError, type OpenAccess, OpenFile, type PollState } from './fd-table.ts';\n\nexport const EMBEDDER_PATH = '/dev/embedder';\nexport const EMBEDDER_MINOR = 252;\nexport const EMBEDDER_HEADER_MAX = 64 * 1024;\nexport const EMBEDDER_WINDOW = 1024 * 1024;\nexport const EMBEDDER_BUDGET = 256 * 1024 * 1024;\nexport const EMBEDDER_PER_PROCESS = 16;\nexport const EMBEDDER_PROGRESS_PER_SECOND = 4;\n\nconst KIND = /^[a-z][a-z0-9-]*(\\.[a-z0-9-]+)*$/;\nconst NL = 10;\n\nexport interface EmbedderStamp {\n pid: number;\n uid: number;\n gid: number;\n groups: number[];\n users: UsersMode;\n kind: string;\n tag?: string;\n tags?: string[];\n}\n\nexport interface EmbedderKindPolicy {\n group?: string;\n users?: Array<string | number>;\n session?: boolean;\n}\n\nexport type EmbedderReply = ReadableStream<Uint8Array> | Uint8Array | string | undefined | void;\n\nexport interface EmbedderRequest {\n kind: string;\n options: Record<string, unknown>;\n body: ReadableStream<Uint8Array>;\n stamp: EmbedderStamp;\n signal: AbortSignal;\n progress(line: string): void;\n}\n\nexport interface EmbedderHook {\n kinds: Readonly<Record<string, EmbedderKindPolicy>>;\n handle(request: EmbedderRequest): Promise<EmbedderReply>;\n}\n\nexport interface EmbedderCaller {\n pid: number;\n shownPid: number;\n euid: number;\n egid: number;\n groups: number[];\n sessionUid: number;\n client: number;\n tags: readonly string[] | undefined;\n name: string;\n progress(line: string): boolean;\n closing(): AbortSignal;\n}\n\nexport interface EmbedderLookup {\n groupId(name: string): Promise<number | undefined>;\n userId(name: string): Promise<number | undefined>;\n}\n\nconst READY: PollState = { readable: true, writable: true, hangup: false };\n\nfunction lineOf(err: unknown): string {\n const text = err instanceof Error ? err.message : String(err);\n return (text.split('\\n')[0] ?? '').slice(0, 200);\n}\n\nconst ERRNOS: Readonly<Record<string, 'EACCES' | 'ENOTSUP' | 'ENOENT'>> = {\n NotAllowedError: 'EACCES',\n AbortError: 'EACCES',\n NotSupportedError: 'ENOTSUP',\n NotFoundError: 'ENOENT',\n};\n\nexport function embedderFailure(err: unknown): KernelError {\n if (err instanceof KernelError) return err;\n const name = (err as { name?: unknown } | null)?.name;\n return new KernelError(ERRNOS[String(name)] ?? 'EIO', lineOf(err));\n}\n\nfunction headerOf(bytes: Uint8Array): { kind: string; options: Record<string, unknown> } {\n let parsed: unknown;\n try {\n parsed = JSON.parse(new TextDecoder('utf-8', { fatal: true }).decode(bytes));\n } catch {\n throw new KernelError('EINVAL', 'the request header is not JSON');\n }\n if (typeof parsed !== 'object' || parsed === null || Array.isArray(parsed))\n throw new KernelError('EINVAL', 'the request header is not an object');\n const { kind, ...options } = parsed as Record<string, unknown>;\n if (typeof kind !== 'string' || kind.length > 64 || !KIND.test(kind))\n throw new KernelError('EINVAL', 'the request has no valid kind');\n return { kind, options };\n}\n\nfunction joined(a: Uint8Array, b: Uint8Array): Uint8Array {\n const out = new Uint8Array(a.length + b.length);\n out.set(a);\n out.set(b, a.length);\n return out;\n}\n\nfunction aborted(signal: AbortSignal | undefined): Promise<never> | undefined {\n if (!signal) return undefined;\n return new Promise<never>((_, reject) => {\n const stop = () => reject(new KernelError('EINTR'));\n if (signal.aborted) stop();\n else signal.addEventListener('abort', stop, { once: true });\n });\n}\n\nasync function interruptible<T>(work: Promise<T>, signal: AbortSignal | undefined): Promise<T> {\n const stop = aborted(signal);\n if (!stop) return work;\n stop.catch(() => undefined);\n return Promise.race([work, stop]);\n}\n\nclass Budget {\n private used = 0;\n readonly limit: number;\n constructor(limit: number) {\n this.limit = limit;\n }\n take(n: number): boolean {\n if (this.used + n > this.limit) return false;\n this.used += n;\n return true;\n }\n give(n: number): void {\n this.used = Math.max(0, this.used - n);\n }\n}\n\nclass BodyPipe {\n private queue: Uint8Array[] = [];\n private size = 0;\n private ended = false;\n private dropped = false;\n private wake: (() => void) | undefined;\n private room: (() => void) | undefined;\n readonly stream: ReadableStream<Uint8Array>;\n constructor() {\n this.stream = new ReadableStream<Uint8Array>(\n {\n pull: async (controller) => {\n while (this.queue.length === 0 && !this.ended) {\n await new Promise<void>((resolve) => {\n this.wake = resolve;\n });\n }\n const next = this.queue.shift();\n if (next) {\n this.size -= next.length;\n this.room?.();\n controller.enqueue(next);\n } else controller.close();\n },\n cancel: () => this.drop(),\n },\n { highWaterMark: 0 }\n );\n }\n get full(): boolean {\n return this.size >= EMBEDDER_WINDOW;\n }\n drop(): void {\n this.dropped = true;\n this.queue = [];\n this.size = 0;\n this.end();\n }\n push(bytes: Uint8Array): void {\n if (bytes.length === 0 || this.dropped) return;\n this.queue.push(bytes.slice());\n this.size += bytes.length;\n this.wake?.();\n }\n waitRoom(): Promise<void> {\n return new Promise<void>((resolve) => {\n this.room = resolve;\n });\n }\n end(): void {\n this.ended = true;\n this.wake?.();\n this.room?.();\n }\n}\n\nfunction endsWith(\n stream: ReadableStream<Uint8Array>,\n ended: () => void\n): ReadableStream<Uint8Array> {\n const reader = stream.getReader();\n return new ReadableStream<Uint8Array>(\n {\n pull: async (controller) => {\n let got: ReadableStreamReadResult<Uint8Array>;\n try {\n got = await reader.read();\n } catch (err) {\n ended();\n throw err;\n }\n if (!got.done) return controller.enqueue(got.value);\n ended();\n controller.close();\n },\n cancel: (reason) => {\n ended();\n return reader.cancel(reason);\n },\n },\n { highWaterMark: 0 }\n );\n}\n\nfunction replyStream(reply: EmbedderReply): ReadableStream<Uint8Array> {\n if (reply instanceof ReadableStream) return reply;\n const bytes =\n typeof reply === 'string'\n ? new TextEncoder().encode(reply)\n : reply instanceof Uint8Array\n ? reply\n : new Uint8Array(0);\n return new ReadableStream({\n start(controller) {\n if (bytes.length > 0) controller.enqueue(bytes);\n controller.close();\n },\n });\n}\n\nconst HELD_MAX = 16;\n\nclass Throttle {\n private window = 0;\n private count = 0;\n allow(now: number): boolean {\n if (now - this.window >= 1000) {\n this.window = now;\n this.count = 0;\n }\n this.count += 1;\n return this.count <= EMBEDDER_PROGRESS_PER_SECOND;\n }\n}\n\nexport class EmbedderChannel {\n readonly access: OpenAccess;\n readonly owner: number;\n private current: EmbedderCaller;\n private held: string[] = [];\n private readonly broker: EmbedderBroker;\n private header: Uint8Array = new Uint8Array(0);\n private body: BodyPipe | undefined;\n private reply: ReadableStreamDefaultReader<Uint8Array> | undefined;\n private replied: Promise<ReadableStreamDefaultReader<Uint8Array>> | undefined;\n private rest: Uint8Array | undefined;\n private done = false;\n private failure: KernelError | undefined;\n private reported = false;\n private readonly abort = new AbortController();\n private closed = false;\n private readonly throttle = new Throttle();\n\n constructor(broker: EmbedderBroker, access: OpenAccess, caller: EmbedderCaller) {\n this.broker = broker;\n this.access = access;\n this.current = caller;\n this.owner = caller.pid;\n }\n\n get dispatched(): boolean {\n return this.body !== undefined;\n }\n\n get caller(): EmbedderCaller {\n return this.current;\n }\n\n set caller(caller: EmbedderCaller) {\n this.current = caller;\n const held = this.held;\n this.held = [];\n for (const line of held) this.tell(line);\n }\n\n private tell(line: string): void {\n if (!this.current.progress(line) && this.held.length < HELD_MAX) this.held.push(line);\n }\n\n private fail(err: unknown): KernelError {\n this.failure ??= embedderFailure(err);\n return this.failure;\n }\n\n private report(err: unknown): KernelError {\n this.reported = true;\n return this.fail(err);\n }\n\n private async dispatch(bytes: Uint8Array): Promise<void> {\n const { kind, options } = headerOf(bytes);\n const stamp = await this.broker.admit(kind, this.caller);\n const hook = this.broker.hookFor(this.caller.client) as EmbedderHook;\n const body = new BodyPipe();\n this.body = body;\n const prefix = this.caller.name;\n const progress = (line: string) => {\n if (this.throttle.allow(Date.now())) this.tell(`${prefix}: ${lineOf(line)}`);\n };\n const asked = Promise.resolve()\n .then(() =>\n hook.handle({\n kind,\n options,\n body: body.stream,\n stamp,\n signal: this.abort.signal,\n progress,\n })\n )\n .then((reply) => {\n if (!(reply instanceof ReadableStream)) body.drop();\n return endsWith(replyStream(reply), () => body.drop()).getReader();\n });\n this.replied = asked.catch((err: unknown) => {\n body.end();\n throw this.fail(err);\n });\n this.replied.catch(() => undefined);\n }\n\n async write(bytes: Uint8Array, signal?: AbortSignal): Promise<number> {\n if (this.access === 'read') throw new KernelError('EBADF');\n if (this.failure) throw this.report(this.failure);\n if (this.reply || this.done) throw new KernelError('EBADF');\n if (this.body) return this.writeBody(bytes, signal);\n const at = bytes.indexOf(NL);\n const head = at < 0 ? bytes : bytes.subarray(0, at);\n if (this.header.length + head.length > EMBEDDER_HEADER_MAX)\n throw this.report(new KernelError('EINVAL', 'the request header is too long'));\n this.header = joined(this.header, head);\n if (at < 0) return bytes.length;\n try {\n await this.dispatch(this.header);\n } catch (err) {\n throw this.report(err);\n }\n (this.body as BodyPipe | undefined)?.push(bytes.subarray(at + 1));\n return bytes.length;\n }\n\n private async writeBody(bytes: Uint8Array, signal?: AbortSignal): Promise<number> {\n const body = this.body as BodyPipe;\n while (body.full && !this.failure) {\n await interruptible(body.waitRoom(), signal).catch((err: unknown) => {\n this.cancel('interrupted');\n throw err;\n });\n }\n if (this.failure) throw this.report(this.failure);\n body.push(bytes);\n return bytes.length;\n }\n\n private async readerOf(signal?: AbortSignal): Promise<ReadableStreamDefaultReader<Uint8Array>> {\n if (this.reply) return this.reply;\n if (!this.body) {\n try {\n await this.dispatch(this.header);\n } catch (err) {\n throw this.fail(err);\n }\n }\n this.body?.end();\n this.reply = await interruptible(\n this.replied as Promise<ReadableStreamDefaultReader<Uint8Array>>,\n signal\n );\n return this.reply;\n }\n\n async read(max: number, signal?: AbortSignal): Promise<Uint8Array> {\n if (this.access === 'write') throw new KernelError('EBADF');\n if (this.failure) throw this.report(this.failure);\n if (this.done || max <= 0) return new Uint8Array(0);\n try {\n return await this.next(max, signal);\n } catch (err) {\n if (err instanceof KernelError && err.code === 'EINTR') {\n this.cancel('interrupted');\n throw err;\n }\n throw this.report(err);\n }\n }\n\n private async next(max: number, signal?: AbortSignal): Promise<Uint8Array> {\n const reader = await this.readerOf(signal);\n let chunk = this.rest;\n this.rest = undefined;\n if (!chunk) {\n const got = await interruptible(reader.read(), signal);\n if (got.done) {\n this.done = true;\n return new Uint8Array(0);\n }\n chunk = got.value;\n }\n if (chunk.length > max) this.rest = chunk.subarray(max);\n return chunk.subarray(0, max);\n }\n\n poll(): PollState {\n return this.body?.full ? { ...READY, writable: false } : READY;\n }\n\n cancel(reason: 'interrupted' | 'closed'): void {\n if (this.abort.signal.aborted) return;\n this.abort.abort(new DOMException(reason, 'AbortError'));\n this.body?.end();\n void this.reply?.cancel(reason).catch(() => undefined);\n }\n\n async close(): Promise<void> {\n if (this.closed) return;\n const signal = this.caller.closing();\n this.closed = true;\n try {\n if (this.access === 'read') return;\n if (this.failure) {\n if (this.reported) return;\n throw this.report(this.failure);\n }\n if (this.access === 'both' && this.dispatched) return;\n if (!this.dispatched && this.header.length === 0) return;\n await this.drain(signal);\n } finally {\n if (!this.done) this.cancel('closed');\n this.broker.release(this);\n }\n }\n\n private async drain(signal?: AbortSignal): Promise<void> {\n try {\n const reader = await this.readerOf(signal);\n for (;;) {\n const got = await interruptible(reader.read(), signal);\n if (got.done) break;\n }\n this.done = true;\n } catch (err) {\n if (err instanceof KernelError && err.code === 'EINTR') this.cancel('interrupted');\n throw this.fail(err);\n }\n }\n}\n\nexport class EmbedderBroker {\n readonly users: UsersMode;\n private readonly lookup: EmbedderLookup;\n private readonly hooks = new Map<number, EmbedderHook>();\n private readonly budget: Budget;\n private readonly open = new Map<number, Set<EmbedderChannel>>();\n\n readonly tagsOf: (pid: number) => readonly string[] | undefined;\n denied: DenialHook | undefined;\n\n constructor(\n users: UsersMode,\n lookup: EmbedderLookup,\n tagsOf: (pid: number) => readonly string[] | undefined = () => undefined,\n budget = EMBEDDER_BUDGET\n ) {\n this.users = users;\n this.tagsOf = tagsOf;\n this.lookup = lookup;\n this.budget = new Budget(budget);\n }\n\n register(client: number, hook: EmbedderHook | undefined): () => void {\n if (!hook) return () => undefined;\n this.hooks.set(client, hook);\n return () => {\n if (this.hooks.get(client) === hook) this.hooks.delete(client);\n };\n }\n\n hookFor(client: number): EmbedderHook | undefined {\n return this.hooks.get(client);\n }\n\n private async allowed(policy: EmbedderKindPolicy, caller: EmbedderCaller): Promise<boolean> {\n if (caller.euid === 0) return true;\n if (policy.session !== false && caller.euid === caller.sessionUid) return true;\n if (policy.group !== undefined) {\n const gid = await this.lookup.groupId(policy.group);\n if (gid !== undefined && (caller.egid === gid || caller.groups.includes(gid))) return true;\n }\n for (const user of policy.users ?? []) {\n const uid = typeof user === 'number' ? user : await this.lookup.userId(user);\n if (uid === caller.euid) return true;\n }\n return false;\n }\n\n async admit(kind: string, caller: EmbedderCaller): Promise<EmbedderStamp> {\n const hook = this.hooks.get(caller.client);\n if (!hook) throw new KernelError('ENOTSUP', 'no page answers requests for this session');\n const policy = Object.hasOwn(hook.kinds, kind) ? hook.kinds[kind] : undefined;\n if (!policy) throw new KernelError('ENOTSUP', `this embedder does not answer ${kind}`);\n const tags = caller.tags;\n if (this.users !== 'off' && !(await this.allowed(policy, caller))) {\n try {\n this.denied?.({\n pid: caller.pid,\n uid: caller.euid,\n op: 'embedder',\n path: EMBEDDER_PATH,\n errno: 'EACCES',\n kind,\n ...(tags?.length ? { tag: tags[0] as string } : {}),\n });\n } catch {}\n throw new KernelError('EACCES', `${kind} is not allowed for this user`);\n }\n return {\n pid: caller.shownPid,\n uid: caller.euid,\n gid: caller.egid,\n groups: [...caller.groups],\n users: this.users,\n kind,\n ...(tags?.length ? { tag: tags[0] as string, tags: [...tags] } : {}),\n };\n }\n\n channel(access: OpenAccess, caller: EmbedderCaller): OpenFile {\n const mine = this.open.get(caller.pid) ?? new Set<EmbedderChannel>();\n if (mine.size >= EMBEDDER_PER_PROCESS)\n throw new KernelError('EMFILE', `at most ${EMBEDDER_PER_PROCESS} requests per process`);\n if (!this.budget.take(2 * EMBEDDER_WINDOW))\n throw new KernelError('EAGAIN', 'the embedder request budget is spent');\n const channel = new EmbedderChannel(this, access, caller);\n mine.add(channel);\n this.open.set(caller.pid, mine);\n return new OpenFile({\n read: channel.read.bind(channel),\n write: (bytes, signal) => channel.write(bytes, signal),\n poll: () => channel.poll(),\n close: () => channel.close(),\n embedder: channel,\n });\n }\n\n release(channel: EmbedderChannel): void {\n const mine = this.open.get(channel.owner);\n if (!mine?.delete(channel)) return;\n if (mine.size === 0) this.open.delete(channel.owner);\n this.budget.give(2 * EMBEDDER_WINDOW);\n }\n}\n\nexport function kindsOf(hook: EmbedderHook): Record<string, EmbedderKindPolicy> {\n if (typeof hook?.handle !== 'function' || typeof hook.kinds !== 'object' || !hook.kinds)\n throw new TypeError('requests needs kinds and handle');\n return Object.fromEntries(\n Object.entries(hook.kinds).map(([kind, policy]) => [\n kind,\n {\n ...(policy?.group !== undefined ? { group: String(policy.group) } : {}),\n ...(policy?.users ? { users: [...policy.users] } : {}),\n ...(policy?.session === false ? { session: false } : {}),\n },\n ])\n );\n}\n", "export const HOST_LOOPBACK = 'host.slicc.internal';\n\nexport const HOST_LOOPBACK_ADDRESS = [10, 0, 2, 2] as const;\n\nexport const PAGE_LOOPBACK = 'kernel.localhost';\n\nexport const PAGE_LOOPBACK_URL = `http://{port}.${PAGE_LOOPBACK}`;\n\nexport function toHostLoopback(href: string): string {\n const url = new URL(href);\n if (url.hostname.replace(/\\.$/, '').toLowerCase() !== HOST_LOOPBACK) return href;\n url.hostname = '127.0.0.1';\n return url.href;\n}\n\nconst LOOPBACK_V4 = /^127\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}$/;\nconst LOOPBACK_V6 = new Set(['::1', '::', '0:0:0:0:0:0:0:1']);\nconst MAPPED_V4 = /^::ffff:7f[0-9a-f]{2}:[0-9a-f]{1,4}$/;\nconst KERNEL_PORT = /^(\\d{1,5})\\.kernel\\.localhost$/;\nconst SCHEMES: Readonly<Record<string, number>> = {\n 'http:': 80,\n 'ws:': 80,\n 'https:': 443,\n 'wss:': 443,\n};\n\nexport function isKernelLoopbackHost(hostname: string): boolean {\n const host = hostname\n .replace(/^\\[(.*)\\]$/, '$1')\n .replace(/\\.$/, '')\n .toLowerCase();\n return (\n host === 'localhost' ||\n host.endsWith('.localhost') ||\n host === '0.0.0.0' ||\n LOOPBACK_V4.test(host) ||\n LOOPBACK_V6.has(host) ||\n MAPPED_V4.test(host)\n );\n}\n\nexport function kernelLoopbackPort(href: string): number | undefined {\n let url: URL;\n try {\n url = new URL(href);\n } catch {\n return undefined;\n }\n const fallback = SCHEMES[url.protocol];\n if (fallback === undefined || !isKernelLoopbackHost(url.hostname)) return undefined;\n const named = KERNEL_PORT.exec(url.hostname.replace(/\\.$/, '').toLowerCase())?.[1];\n const port = Number(named ?? (url.port || fallback));\n return port >= 1 && port <= 65535 ? port : undefined;\n}\n\nexport const DEFAULT_HOSTNAME = 'slicc';\n\nexport const HOSTNAME_ADDRESS = '127.0.1.1';\n\nexport const LIBC_HOSTNAMES: readonly string[] = ['emscripten', 'wasmer.sh'];\n\nconst LABEL = /^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$/i;\n\nfunction reserved(name: string): boolean {\n const lower = name.toLowerCase();\n return (\n lower === 'localhost' ||\n lower.endsWith('.localhost') ||\n lower === HOST_LOOPBACK ||\n lower === 'wasmer.sh' ||\n /^\\d+(\\.\\d+){3}$/.test(lower)\n );\n}\n\nexport function isHostname(name: unknown): name is string {\n if (typeof name !== 'string' || name.length > 253 || reserved(name)) return false;\n return name.split('.').every((l) => LABEL.test(l));\n}\n\nexport function hostnameOf(env: Readonly<Record<string, string>>): string {\n return isHostname(env.HOSTNAME) ? env.HOSTNAME : DEFAULT_HOSTNAME;\n}\n\nexport function initHostname(init: {\n hostname?: string | undefined;\n env: Readonly<Record<string, string>>;\n}): string {\n return isHostname(init.hostname) ? init.hostname : hostnameOf(init.env);\n}\n\nexport function ownNames(hostname: string): string[] {\n return [...new Set([hostname.toLowerCase(), ...LIBC_HOSTNAMES])];\n}\n\nexport function hostsFile(hostname: string = DEFAULT_HOSTNAME): string {\n return [\n '127.0.0.1 localhost localhost.localdomain',\n '::1 localhost ip6-localhost',\n `${HOSTNAME_ADDRESS} ${ownNames(hostname).join(' ')}`,\n `${HOST_LOOPBACK_ADDRESS.join('.')} ${HOST_LOOPBACK}`,\n '',\n ].join('\\n');\n}\n", "export const BODY_IDLE_MS = 5 * 60 * 1000;\n\nexport function idleFailure(ms: number): Error {\n return Object.assign(new Error(`the response body sent no data for ${ms} ms`), {\n code: 'ETIMEDOUT',\n });\n}\n\nexport async function readWithin<T>(\n reader: ReadableStreamDefaultReader<T>,\n ms: number\n): Promise<ReadableStreamReadResult<T>> {\n if (!(ms > 0 && ms < Number.POSITIVE_INFINITY)) return reader.read();\n let timer: ReturnType<typeof setTimeout> | undefined;\n const idle = new Promise<never>((_, reject) => {\n timer = setTimeout(() => reject(idleFailure(ms)), ms);\n });\n try {\n return await Promise.race([reader.read(), idle]);\n } finally {\n clearTimeout(timer);\n }\n}\n", "import { BODY_IDLE_MS } from '../../body-idle.ts';\nimport type { SealedCaller, SealedHook } from '../sealed.ts';\nimport { PlaceholderRefused } from './placeholder-floor.ts';\nimport type { HeaderList, RealmTransportRequest, RealmTransportResponse } from './transport.ts';\n\nexport const SEALED_FETCH_VERSION = 1;\n\nconst UNSAFE_FIELD = /[\\r\\n\\0]/;\n\nexport interface SealedFetchRequest {\n v: 1;\n caller: SealedCaller;\n method: string;\n url: string;\n headers: HeaderList;\n redirect: 'manual';\n body?: Uint8Array;\n bodyStream?: AsyncIterable<Uint8Array>;\n}\n\nexport type SealedFetchHook = (\n req: SealedFetchRequest,\n options: { signal: AbortSignal }\n) => Promise<RealmTransportResponse>;\n\nexport type SealedOption = SealedHook | { request: SealedHook; fetch?: SealedFetchHook };\n\nexport function sealedHooks(option: SealedOption | undefined): {\n request?: SealedHook;\n fetch?: SealedFetchHook;\n} {\n if (!option) return {};\n if (typeof option === 'function') return { request: option };\n const { request, fetch } = option;\n if (typeof request !== 'function' || (fetch !== undefined && typeof fetch !== 'function')) {\n throw new TypeError('sealed takes a function or { request, fetch? }');\n }\n return { request, ...(fetch ? { fetch } : {}) };\n}\n\nfunction headerList(headers: unknown): headers is HeaderList {\n return (\n Array.isArray(headers) &&\n headers.every(\n (field) =>\n Array.isArray(field) &&\n field.length === 2 &&\n field.every((text) => typeof text === 'string' && !UNSAFE_FIELD.test(text))\n )\n );\n}\n\nexport function sealedReplyValid(reply: unknown): reply is RealmTransportResponse {\n if (typeof reply !== 'object' || reply === null) return false;\n const { redirects, redirected, status, statusText, headers, url, body, cancel } =\n reply as Partial<RealmTransportResponse>;\n return (\n redirects === undefined &&\n redirected !== true &&\n Number.isInteger(status) &&\n (status as number) >= 100 &&\n (status as number) <= 599 &&\n typeof statusText === 'string' &&\n !UNSAFE_FIELD.test(statusText) &&\n headerList(headers) &&\n (url === undefined || typeof url === 'string') &&\n typeof body?.[Symbol.asyncIterator] === 'function' &&\n typeof cancel === 'function'\n );\n}\n\nexport function dropSealedReply(reply: unknown): void {\n const { cancel } = (reply ?? {}) as Partial<RealmTransportResponse>;\n if (typeof cancel !== 'function') return;\n void Promise.resolve()\n .then(() => cancel.call(reply))\n .catch(() => undefined);\n}\n\nfunction failed(reason: unknown): PlaceholderRefused {\n const text = reason instanceof Error ? reason.message : String(reason);\n return new PlaceholderRefused(\n `refused: the request with a sealed placeholder was not completed: ${text}`\n );\n}\n\nclass Stall {\n private readonly idle = new AbortController();\n private readonly ms: number;\n private timer: ReturnType<typeof setTimeout> | undefined;\n readonly signal: AbortSignal;\n\n constructor(signals: AbortSignal[], ms: number) {\n this.ms = ms;\n this.signal = AbortSignal.any([...signals, this.idle.signal]);\n }\n\n arm(): void {\n clearTimeout(this.timer);\n this.timer = setTimeout(() => this.idle.abort('timeout'), this.ms);\n (this.timer as { unref?: () => void }).unref?.();\n }\n\n touch(): void {\n if (this.timer !== undefined) this.arm();\n }\n\n rest(): void {\n clearTimeout(this.timer);\n this.timer = undefined;\n }\n}\n\nasync function until<T>(work: Promise<T>, signal: AbortSignal): Promise<T> {\n const stopped = Promise.withResolvers<never>();\n const stop = () => stopped.reject(signal.reason);\n if (signal.aborted) stop();\n else signal.addEventListener('abort', stop, { once: true });\n try {\n return await Promise.race([work, stopped.promise]);\n } finally {\n signal.removeEventListener('abort', stop);\n }\n}\n\nasync function* ticking(\n stream: AsyncIterable<Uint8Array>,\n stall: Stall\n): AsyncGenerator<Uint8Array> {\n for await (const chunk of stream) {\n stall.touch();\n yield chunk;\n }\n}\n\nfunction sealedRequest(\n request: RealmTransportRequest,\n stamp: SealedCaller,\n stall: Stall\n): SealedFetchRequest {\n const { method, url, headers, body, bodyStream } = request;\n return {\n v: 1,\n caller: structuredClone(stamp),\n method,\n url,\n headers: headers.map(([name, value]) => [name, value] as const),\n redirect: 'manual',\n ...(bodyStream ? { bodyStream: ticking(bodyStream, stall) } : body ? { body } : {}),\n };\n}\n\nfunction guarded(reply: RealmTransportResponse, stall: Stall): RealmTransportResponse {\n let finished = false;\n const cancel = async () => {\n stall.signal.removeEventListener('abort', dropped);\n stall.rest();\n if (finished) return;\n finished = true;\n await reply.cancel().catch(() => undefined);\n };\n const dropped = () => void cancel();\n stall.signal.addEventListener('abort', dropped, { once: true });\n const source = reply.body[Symbol.asyncIterator]();\n const body = (async function* () {\n try {\n for (;;) {\n stall.arm();\n const next = await until(source.next(), stall.signal);\n stall.rest();\n if (next.done) {\n finished = true;\n return;\n }\n if (!(next.value instanceof Uint8Array)) throw failed('a body chunk is not bytes');\n if (next.value.byteLength > 0) yield next.value;\n }\n } finally {\n await cancel();\n }\n })();\n return {\n ...(reply.url !== undefined ? { url: reply.url } : {}),\n status: reply.status,\n statusText: reply.statusText,\n headers: reply.headers,\n body,\n cancel,\n };\n}\n\nexport function sealedFetcher(\n hook: SealedFetchHook,\n stop: AbortSignal,\n idleMs = BODY_IDLE_MS\n): (request: RealmTransportRequest, stamp: SealedCaller) => Promise<RealmTransportResponse> {\n return async (request, stamp) => {\n const stall = new Stall([request.signal, stop], idleMs);\n const { signal } = stall;\n if (signal.aborted) throw failed(signal.reason);\n stall.arm();\n const asked = Promise.resolve().then(() => {\n signal.throwIfAborted();\n return hook(sealedRequest(request, stamp, stall), { signal });\n });\n let reply: unknown;\n try {\n reply = await until(asked, signal);\n } catch (e) {\n void asked.then(dropSealedReply, () => undefined);\n throw failed(e);\n } finally {\n stall.rest();\n }\n if (sealedReplyValid(reply)) return guarded(reply, stall);\n dropSealedReply(reply);\n throw failed('the reply is not a scrubbed response');\n };\n}\n", "import { HOST_LOOPBACK, HOST_LOOPBACK_ADDRESS } from './loopback-names.ts';\n\nexport interface RouteTable {\n prefixes: readonly string[];\n exit: boolean;\n}\n\nexport type Destination = 'loopback' | 'host' | 'reserved' | 'uplink' | 'unreachable';\n\ninterface Prefix {\n v6: boolean;\n bits: bigint;\n length: number;\n}\n\nconst HOST_ADDRESS = HOST_LOOPBACK_ADDRESS.join('.');\n\nexport function ipv4Bytes(text: string): number[] | undefined {\n const parts = text.split('.');\n if (parts.length !== 4 || !parts.every((p) => /^\\d{1,3}$/.test(p))) return undefined;\n const bytes = parts.map(Number);\n return bytes.every((b) => b <= 255) ? bytes : undefined;\n}\n\nexport function ipv6Groups(text: string): number[] | undefined {\n if (!text.includes(':')) return undefined;\n let canonical: string;\n try {\n canonical = new URL(`http://[${text}]/`).hostname.slice(1, -1);\n } catch {\n return undefined;\n }\n const [head, tail] = canonical.split('::');\n const part = (s: string | undefined) =>\n s ? s.split(':').map((h) => Number.parseInt(h, 16)) : [];\n const front = part(head);\n const back = part(tail);\n return tail === undefined\n ? front\n : [...front, ...new Array<number>(8 - front.length - back.length).fill(0), ...back];\n}\n\nfunction toBits(values: number[], width: number): bigint {\n return values.reduce((acc, v) => (acc << BigInt(width)) | BigInt(v), 0n);\n}\n\nfunction addressBits(host: string): { v6: boolean; bits: bigint } | undefined {\n const v4 = ipv4Bytes(host);\n if (v4) return { v6: false, bits: toBits(v4, 8) };\n const v6 = ipv6Groups(host);\n return v6 ? { v6: true, bits: toBits(v6, 16) } : undefined;\n}\n\nfunction parsePrefix(text: string): Prefix | undefined {\n const parts = text.trim().split('/');\n if (parts.length > 2) return undefined;\n const [address = '', size] = parts;\n const parsed = addressBits(address);\n if (!parsed) return undefined;\n const max = parsed.v6 ? 128 : 32;\n const length = size === undefined ? max : /^\\d{1,3}$/.test(size) ? Number(size) : -1;\n if (length < 0 || length > max) return undefined;\n return { ...parsed, length };\n}\n\nfunction within(prefix: Prefix, addr: { v6: boolean; bits: bigint }): boolean {\n if (prefix.v6 !== addr.v6) return false;\n const shift = BigInt((prefix.v6 ? 128 : 32) - prefix.length);\n return addr.bits >> shift === prefix.bits >> shift;\n}\n\nconst RESERVED = [\n '0.0.0.0/8',\n '127.0.0.0/8',\n '169.254.0.0/16',\n '224.0.0.0/4',\n '240.0.0.0/4',\n '::/96',\n '::ffff:0:0/96',\n 'fe80::/10',\n 'ff00::/8',\n].map((p) => parsePrefix(p) as Prefix);\n\nexport class Routes {\n private table: Prefix[] = [];\n private exit = false;\n readonly ipv6: boolean;\n\n constructor(ipv6 = false) {\n this.ipv6 = ipv6;\n }\n\n set(table: RouteTable): void {\n const parsed = (table.prefixes ?? []).map(parsePrefix);\n const bad = (table.prefixes ?? []).find((_, i) => !parsed[i]);\n if (bad !== undefined) throw new Error(`not an address prefix: ${bad}`);\n this.table = parsed as Prefix[];\n this.exit = table.exit === true;\n }\n\n classify(host: string): Destination {\n const name = host.toLowerCase().replace(/\\.$/, '');\n if (name === 'localhost' || name.endsWith('.localhost') || name === '0.0.0.0') {\n return 'loopback';\n }\n if (name === HOST_LOOPBACK || name === HOST_ADDRESS) return 'host';\n const addr = addressBits(name);\n if (!addr) return 'unreachable';\n if (addr.v6 && addr.bits === 1n) return 'loopback';\n if (!addr.v6 && addr.bits >> 24n === 127n) return 'loopback';\n if (RESERVED.some((p) => within(p, addr))) return 'reserved';\n if (addr.v6 && !this.ipv6) return 'unreachable';\n if (this.exit || this.table.some((p) => within(p, addr))) return 'uplink';\n return 'unreachable';\n }\n}\n", "import { Routes, type RouteTable } from './routes.ts';\n\nexport interface UplinkTraits {\n tcp: true;\n udp: boolean;\n ipv6: boolean;\n}\n\nexport type ResolveFamily = 0 | 4 | 6;\n\nexport interface ResolveAnswer {\n addresses: string[];\n ttl?: number;\n}\n\nexport interface UplinkConn {\n readonly localAddr: string;\n readonly remoteAddr: string;\n readonly exit?: string;\n read(): Promise<Uint8Array | null>;\n write(bytes: Uint8Array): Promise<number>;\n closeWrite(): void;\n close(): void;\n}\n\nexport interface UplinkDial {\n network: 'tcp';\n host: string;\n port: number;\n signal: AbortSignal;\n}\n\nexport interface UplinkDatagram {\n bytes: Uint8Array;\n host: string;\n port: number;\n}\n\nexport interface UplinkUnreachable {\n error: string;\n host: string;\n port: number;\n}\n\nexport type UplinkMessage = UplinkDatagram | UplinkUnreachable;\n\nexport interface UplinkUdpOpen {\n family: 4 | 6;\n signal: AbortSignal;\n}\n\nexport interface UplinkUdp {\n readonly localAddr: string;\n send(bytes: Uint8Array, host: string, port: number): Promise<void>;\n readonly messages: AsyncIterable<UplinkMessage>;\n close(): void;\n}\n\nexport interface NetworkUplink {\n readonly traits: UplinkTraits;\n readonly routes?: RouteTable;\n readonly nameserver?: string;\n resolve(\n name: string,\n family: ResolveFamily,\n signal?: AbortSignal\n ): Promise<string[] | ResolveAnswer>;\n dial(req: UplinkDial): Promise<UplinkConn>;\n udp?(req: UplinkUdpOpen): Promise<UplinkUdp>;\n}\n\nexport function carriesUdp(uplink: NetworkUplink): boolean {\n return uplink.traits.udp === true && typeof uplink.udp === 'function';\n}\n\nexport type UplinkCall =\n | { uplink: 'resolve'; uid: number; name: string; family: ResolveFamily }\n | { uplink: 'dial'; uid: number; host: string; port: number }\n | { uplink: 'cancel'; uid: number }\n | { uplink: 'read'; uid: number; cid: number }\n | { uplink: 'write'; uid: number; cid: number; bytes: Uint8Array }\n | { uplink: 'close-write'; cid: number }\n | { uplink: 'close'; cid: number }\n | { uplink: 'udp-open'; uid: number; family: 4 | 6 }\n | { uplink: 'udp-send'; uid: number; cid: number; bytes: Uint8Array; host: string; port: number }\n | { uplink: 'udp-recv'; uid: number; cid: number }\n | { uplink: 'udp-close'; cid: number };\n\nexport type UplinkReply =\n | { uplink: 'resolved'; uid: number; addresses: string[]; ttl?: number }\n | { uplink: 'dialled'; uid: number; cid: number; localAddr: string; remoteAddr: string }\n | { uplink: 'data'; uid: number; bytes: Uint8Array | null }\n | { uplink: 'written'; uid: number; n: number }\n | { uplink: 'udp-opened'; uid: number; cid: number; localAddr: string }\n | { uplink: 'udp-sent'; uid: number }\n | { uplink: 'udp-message'; uid: number; message: UplinkMessage | null }\n | { uplink: 'error'; uid: number; message: string; code?: string };\n\nexport interface UplinkPeer {\n postMessage(message: UplinkReply, transfer?: Transferable[]): void;\n}\n\nexport interface UplinkPort {\n postMessage(message: UplinkCall, transfer?: Transferable[]): void;\n}\n\nexport interface UplinkServer {\n answer(call: UplinkCall): void;\n close(): void;\n}\n\nexport function answerOf(result: string[] | ResolveAnswer): ResolveAnswer {\n const answer = Array.isArray(result) ? { addresses: result } : result;\n const addresses = Array.isArray(answer?.addresses)\n ? answer.addresses.filter((a): a is string => typeof a === 'string')\n : [];\n return {\n addresses,\n ...(typeof answer?.ttl === 'number' && answer.ttl >= 0 ? { ttl: answer.ttl } : {}),\n };\n}\n\nfunction failure(uid: number, e: unknown): UplinkReply {\n const code = (e as { code?: unknown } | null)?.code;\n return {\n uplink: 'error',\n uid,\n message: e instanceof Error ? e.message : String(e),\n ...(typeof code === 'string' ? { code } : {}),\n };\n}\n\nconst NEVER = new Routes(true);\n\nexport function serveUplink(peer: UplinkPeer, uplink: NetworkUplink): UplinkServer {\n const conns = new Map<number, UplinkConn>();\n const pending = new Map<number, AbortController>();\n let nextCid = 0;\n let closed = false;\n const run = (uid: number, work: (signal: AbortSignal) => Promise<UplinkReply | undefined>) => {\n const abort = new AbortController();\n pending.set(uid, abort);\n void work(abort.signal)\n .then(\n (reply) => reply && peer.postMessage(reply, transferOf(reply)),\n (e: unknown) => peer.postMessage(failure(uid, e))\n )\n .finally(() => pending.delete(uid));\n };\n const conn = (cid: number): UplinkConn => {\n const found = conns.get(cid);\n if (!found) throw Object.assign(new Error('no such uplink connection'), { code: 'EBADF' });\n return found;\n };\n const dial = async (call: Extract<UplinkCall, { uplink: 'dial' }>, signal: AbortSignal) => {\n refuseLocal(call.host);\n const { host, port } = call;\n const opened = await uplink.dial({ network: 'tcp', host, port, signal });\n if (signal.aborted || closed) {\n opened.close();\n return undefined;\n }\n const cid = ++nextCid;\n conns.set(cid, opened);\n const { localAddr, remoteAddr } = opened;\n return { uplink: 'dialled' as const, uid: call.uid, cid, localAddr, remoteAddr };\n };\n const drop = (cid: number) => {\n const found = conns.get(cid);\n conns.delete(cid);\n found?.close();\n };\n const udp = new UdpServer(uplink, () => closed);\n return {\n answer(call) {\n switch (call.uplink) {\n case 'resolve':\n return run(call.uid, async (signal) => ({\n uplink: 'resolved',\n uid: call.uid,\n ...answerOf(await uplink.resolve(call.name, call.family, signal)),\n }));\n case 'dial':\n return run(call.uid, (signal) => dial(call, signal));\n case 'cancel':\n return pending.get(call.uid)?.abort();\n case 'read':\n return run(call.uid, async () => ({\n uplink: 'data',\n uid: call.uid,\n bytes: (await conn(call.cid).read())?.slice() ?? null,\n }));\n case 'write':\n return run(call.uid, async () => ({\n uplink: 'written',\n uid: call.uid,\n n: await conn(call.cid).write(call.bytes),\n }));\n case 'close-write':\n return conns.get(call.cid)?.closeWrite();\n case 'close':\n return drop(call.cid);\n case 'udp-close':\n return udp.drop(call.cid);\n default:\n return run(call.uid, (signal) => udp.answer(call, signal));\n }\n },\n close() {\n closed = true;\n for (const abort of pending.values()) abort.abort();\n for (const cid of [...conns.keys()]) drop(cid);\n udp.close();\n },\n };\n}\n\nfunction copied(message: UplinkMessage): UplinkMessage {\n if ('bytes' in message) return { ...message, bytes: message.bytes.slice() };\n return { error: String(message.error), host: message.host, port: message.port };\n}\n\nfunction refuseLocal(host: string): void {\n const kind = NEVER.classify(host);\n if (kind === 'loopback' || kind === 'host' || kind === 'reserved') {\n throw Object.assign(new Error(`the uplink does not carry ${host}`), { code: 'ENETUNREACH' });\n }\n}\n\ntype UdpCall = Extract<UplinkCall, { uplink: 'udp-open' | 'udp-send' | 'udp-recv' }>;\n\nclass UdpServer {\n private readonly sockets = new Map<\n number,\n { udp: UplinkUdp; messages: AsyncIterator<UplinkMessage> }\n >();\n private next = 0;\n private readonly uplink: NetworkUplink;\n private readonly closed: () => boolean;\n\n constructor(uplink: NetworkUplink, closed: () => boolean) {\n this.uplink = uplink;\n this.closed = closed;\n }\n\n private socket(cid: number) {\n const found = this.sockets.get(cid);\n if (!found) throw Object.assign(new Error('no such uplink socket'), { code: 'EBADF' });\n return found;\n }\n\n async answer(call: UdpCall, signal: AbortSignal): Promise<UplinkReply | undefined> {\n if (call.uplink === 'udp-open') {\n if (!this.uplink.udp || this.uplink.traits.udp !== true) {\n throw Object.assign(new Error('the uplink carries no datagrams'), { code: 'ENETUNREACH' });\n }\n const opened = await this.uplink.udp({ family: call.family, signal });\n if (signal.aborted || this.closed()) {\n opened.close();\n return undefined;\n }\n const cid = ++this.next;\n this.sockets.set(cid, { udp: opened, messages: opened.messages[Symbol.asyncIterator]() });\n return { uplink: 'udp-opened', uid: call.uid, cid, localAddr: opened.localAddr };\n }\n if (call.uplink === 'udp-send') {\n refuseLocal(call.host);\n await this.socket(call.cid).udp.send(call.bytes, call.host, call.port);\n return { uplink: 'udp-sent', uid: call.uid };\n }\n const next = await this.socket(call.cid).messages.next();\n const message = next.done ? null : copied(next.value);\n return { uplink: 'udp-message', uid: call.uid, message };\n }\n\n drop(cid: number): void {\n const found = this.sockets.get(cid);\n this.sockets.delete(cid);\n found?.udp.close();\n }\n\n close(): void {\n for (const cid of [...this.sockets.keys()]) this.drop(cid);\n }\n}\n\nfunction transferOf(reply: UplinkReply): Transferable[] | undefined {\n if (reply.uplink === 'udp-message' && reply.message && 'bytes' in reply.message) {\n return [reply.message.bytes.buffer as ArrayBuffer];\n }\n if (reply.uplink !== 'data' || !reply.bytes) return undefined;\n return [reply.bytes.buffer as ArrayBuffer];\n}\n\ntype Answer = Exclude<UplinkReply, { uplink: 'error' }>;\n\nexport class RemoteUplink implements NetworkUplink {\n readonly traits: UplinkTraits;\n readonly routes: RouteTable | undefined;\n readonly nameserver: string | undefined;\n private readonly port: UplinkPort;\n private readonly waiting = new Map<number, PromiseWithResolvers<Answer>>();\n private nextId = 0;\n\n constructor(port: UplinkPort, traits: UplinkTraits, routes?: RouteTable, nameserver?: string) {\n this.port = port;\n this.traits = traits;\n this.routes = routes;\n this.nameserver = nameserver;\n }\n\n receive(reply: UplinkReply): void {\n const waiter = this.waiting.get(reply.uid);\n if (!waiter) return;\n this.waiting.delete(reply.uid);\n if (reply.uplink === 'error') {\n waiter.reject(Object.assign(new Error(reply.message), { code: reply.code }));\n } else waiter.resolve(reply);\n }\n\n private ask<T extends Answer>(\n call: Extract<UplinkCall, { uid: number }>,\n signal?: AbortSignal,\n transfer?: Transferable[]\n ): Promise<T> {\n const waiter = Promise.withResolvers<Answer>();\n this.waiting.set(call.uid, waiter);\n const abort = () => {\n this.waiting.delete(call.uid);\n this.port.postMessage({ uplink: 'cancel', uid: call.uid });\n waiter.reject(signal?.reason);\n };\n signal?.addEventListener('abort', abort, { once: true });\n const settled = () => signal?.removeEventListener('abort', abort);\n waiter.promise.then(settled, settled);\n this.port.postMessage(call, transfer);\n return waiter.promise as Promise<T>;\n }\n\n async resolve(name: string, family: ResolveFamily, signal?: AbortSignal) {\n const reply = await this.ask<Extract<Answer, { uplink: 'resolved' }>>(\n { uplink: 'resolve', uid: ++this.nextId, name, family },\n signal\n );\n return answerOf(reply);\n }\n\n async dial(req: UplinkDial): Promise<UplinkConn> {\n req.signal.throwIfAborted();\n const { host, port } = req;\n const opened = await this.ask<Extract<Answer, { uplink: 'dialled' }>>(\n { uplink: 'dial', uid: ++this.nextId, host, port },\n req.signal\n );\n const { cid, localAddr, remoteAddr } = opened;\n return {\n localAddr,\n remoteAddr,\n read: async () => {\n const got = await this.ask<Extract<Answer, { uplink: 'data' }>>({\n uplink: 'read',\n uid: ++this.nextId,\n cid,\n });\n return got.bytes;\n },\n write: async (bytes) => {\n const copy = bytes.slice();\n const call = { uplink: 'write' as const, uid: ++this.nextId, cid, bytes: copy };\n const done = await this.ask<Extract<Answer, { uplink: 'written' }>>(call, undefined, [\n copy.buffer,\n ]);\n return done.n;\n },\n closeWrite: () => this.port.postMessage({ uplink: 'close-write', cid }),\n close: () => this.port.postMessage({ uplink: 'close', cid }),\n };\n }\n\n async udp(req: UplinkUdpOpen): Promise<UplinkUdp> {\n req.signal.throwIfAborted();\n const opened = await this.ask<Extract<Answer, { uplink: 'udp-opened' }>>(\n { uplink: 'udp-open', uid: ++this.nextId, family: req.family },\n req.signal\n );\n const { cid, localAddr } = opened;\n const recv = () =>\n this.ask<Extract<Answer, { uplink: 'udp-message' }>>({\n uplink: 'udp-recv',\n uid: ++this.nextId,\n cid,\n });\n return {\n localAddr,\n send: async (bytes, host, port) => {\n const copy = bytes.slice();\n const call = {\n uplink: 'udp-send' as const,\n uid: ++this.nextId,\n cid,\n bytes: copy,\n host,\n port,\n };\n await this.ask(call, undefined, [copy.buffer]);\n },\n messages: {\n [Symbol.asyncIterator]: async function* () {\n for (;;) {\n const got = await recv();\n if (!got.message) return;\n yield got.message;\n }\n },\n },\n close: () => this.port.postMessage({ uplink: 'udp-close', cid }),\n };\n }\n}\n", "export const SIG = {\n HUP: 1,\n INT: 2,\n QUIT: 3,\n ILL: 4,\n TRAP: 5,\n ABRT: 6,\n BUS: 7,\n FPE: 8,\n KILL: 9,\n USR1: 10,\n SEGV: 11,\n USR2: 12,\n PIPE: 13,\n ALRM: 14,\n TERM: 15,\n STKFLT: 16,\n CHLD: 17,\n CONT: 18,\n STOP: 19,\n TSTP: 20,\n TTIN: 21,\n TTOU: 22,\n URG: 23,\n XCPU: 24,\n XFSZ: 25,\n VTALRM: 26,\n PROF: 27,\n WINCH: 28,\n POLL: 29,\n PWR: 30,\n SYS: 31,\n} as const;\n\nexport type DefaultAction = 'terminate' | 'ignore' | 'stop' | 'continue';\n\nconst IGNORED_BY_DEFAULT: ReadonlySet<number> = new Set([SIG.CHLD, SIG.URG, SIG.WINCH]);\nconst STOPPING: ReadonlySet<number> = new Set([SIG.STOP, SIG.TSTP, SIG.TTIN, SIG.TTOU]);\n\nexport function defaultAction(sig: number): DefaultAction {\n if (sig === SIG.CONT) return 'continue';\n if (STOPPING.has(sig)) return 'stop';\n return IGNORED_BY_DEFAULT.has(sig) ? 'ignore' : 'terminate';\n}\n\nexport function isSignal(sig: number): boolean {\n return Number.isInteger(sig) && sig >= 1 && sig <= 31;\n}\n\nexport function sigbit(sig: number): number {\n return 1 << sig;\n}\n\nexport function signalsIn(mask: number): number[] {\n const out: number[] = [];\n for (let sig = 1; sig <= 31; sig++) if (mask & sigbit(sig)) out.push(sig);\n return out;\n}\n\nexport function signalName(sig: number | undefined): string | undefined {\n const name = Object.entries(SIG).find(([, n]) => n === sig)?.[0];\n return name === undefined ? undefined : `SIG${name}`;\n}\n\nexport function quiet<T>(p: Promise<T>): Promise<T> {\n p.catch(() => undefined);\n return p;\n}\n\nexport function signalField(sig: number | undefined): { signal?: string } {\n const name = signalName(sig);\n return name ? { signal: name } : {};\n}\n\nexport const SIGNAL_BY_NAME: Readonly<\n Record<'SIGINT' | 'SIGTERM' | 'SIGKILL' | 'SIGSTOP' | 'SIGCONT', number>\n> = {\n SIGINT: SIG.INT,\n SIGTERM: SIG.TERM,\n SIGKILL: SIG.KILL,\n SIGSTOP: SIG.STOP,\n SIGCONT: SIG.CONT,\n};\n\nexport interface SigInfo {\n code: number;\n pid: number;\n uid: number;\n status: number;\n}\n\nexport const SI = { USER: 0, QUEUE: -1, TIMER: -2, TKILL: -6, KERNEL: 0x80 } as const;\n\nexport const CLD = { EXITED: 1, KILLED: 2, DUMPED: 3, STOPPED: 5, CONTINUED: 6 } as const;\n\nexport const KERNEL_SIGINFO: Readonly<SigInfo> = Object.freeze({\n code: SI.KERNEL,\n pid: 0,\n uid: 0,\n status: 0,\n});\n", "import { fresh } from './bytes.ts';\nimport {\n dropSealedReply,\n type SealedFetchHook,\n type SealedFetchRequest,\n sealedReplyValid,\n} from './kernel/net/sealed-fetch.ts';\nimport type { HeaderList, RealmTransportResponse as Response } from './kernel/net/transport.ts';\nimport type { SealedHook, SealedRequest } from './kernel/sealed.ts';\n\nexport interface SealedPort {\n postMessage(message: unknown, transfer?: Transferable[]): void;\n}\n\nexport interface SealedAsk {\n id: number;\n req: SealedRequest;\n}\n\nexport interface SealedReply {\n id: number;\n reply?: object;\n error?: string;\n}\n\nexport interface SealedAbort {\n id: number;\n reason: unknown;\n}\n\ntype WireRequest = Omit<SealedFetchRequest, 'bodyStream'> & { streamed?: true };\n\nexport interface SealedFetchAsk {\n req: WireRequest;\n port: MessagePort;\n}\n\ntype AskerMessage =\n | { t: 'pull' }\n | { t: 'stop' }\n | {\n t: 'head';\n status: number;\n statusText: string;\n headers: HeaderList;\n url?: string;\n }\n | { t: 'chunk'; bytes: Uint8Array }\n | { t: 'end' }\n | { t: 'error'; message: string };\n\ntype AnswererMessage =\n | { t: 'read' }\n | { t: 'cancel'; reason: string }\n | { t: 'chunk'; bytes: Uint8Array }\n | { t: 'end' }\n | { t: 'error'; message: string };\n\nfunction textOf(err: unknown): string {\n return err instanceof Error ? err.message : String(err);\n}\n\nfunction sendBytes(port: MessagePort, bytes: Uint8Array): void {\n const copy = fresh(bytes);\n port.postMessage({ t: 'chunk', bytes: copy }, [copy.buffer as ArrayBuffer]);\n}\n\nfunction askFetch(\n port: SealedPort,\n req: SealedFetchRequest,\n signal: AbortSignal\n): Promise<Response> {\n signal.throwIfAborted();\n const { bodyStream, ...wire } = req;\n const { port1: near, port2: far } = new MessageChannel();\n const upload = bodyStream?.[Symbol.asyncIterator]();\n const head = Promise.withResolvers<Response>();\n let reading: PromiseWithResolvers<IteratorResult<Uint8Array>> | undefined;\n let ended = false;\n\n const end = (failure: Error) => {\n if (ended) return;\n ended = true;\n signal.removeEventListener('abort', abort);\n near.close();\n void upload?.return?.().catch(() => undefined);\n head.reject(failure);\n reading?.reject(failure);\n reading = undefined;\n };\n const abort = () => {\n near.postMessage({ t: 'cancel', reason: String(signal.reason) } satisfies AnswererMessage);\n end(new Error(String(signal.reason)));\n };\n const pull = async () => {\n try {\n const next = await (upload as AsyncIterator<Uint8Array>).next();\n if (ended) return;\n if (next.done) near.postMessage({ t: 'end' } satisfies AnswererMessage);\n else sendBytes(near, next.value);\n } catch (err) {\n if (!ended) near.postMessage({ t: 'error', message: textOf(err) });\n }\n };\n const respond = (message: Extract<AskerMessage, { t: 'head' }>) => {\n const { status, statusText, headers, url } = message;\n const body: AsyncIterable<Uint8Array> = {\n [Symbol.asyncIterator]: () => ({\n next: () => {\n if (ended) return Promise.resolve({ value: undefined, done: true });\n reading = Promise.withResolvers();\n near.postMessage({ t: 'read' } satisfies AnswererMessage);\n return reading.promise;\n },\n return: async () => {\n await cancel();\n return { value: undefined, done: true };\n },\n }),\n };\n const cancel = async () => {\n if (ended) return;\n near.postMessage({ t: 'cancel', reason: 'cancelled' } satisfies AnswererMessage);\n end(new Error('the request was cancelled'));\n };\n head.resolve({\n ...(url !== undefined ? { url } : {}),\n status,\n statusText,\n headers,\n body,\n cancel,\n });\n };\n near.addEventListener('message', ({ data }: MessageEvent<AskerMessage>) => {\n if (data.t === 'pull') void pull();\n else if (data.t === 'stop') void upload?.return?.().catch(() => undefined);\n else if (data.t === 'head') respond(data);\n else if (data.t === 'chunk') {\n reading?.resolve({ value: data.bytes, done: false });\n reading = undefined;\n } else if (data.t === 'end') {\n reading?.resolve({ value: undefined, done: true });\n reading = undefined;\n end(new Error('the response ended'));\n } else end(new Error(data.message));\n });\n near.addEventListener('close', () => end(new Error('the sealed fetch relay closed')));\n near.start();\n signal.addEventListener('abort', abort, { once: true });\n const ask: SealedFetchAsk = {\n req: { ...wire, ...(upload ? { streamed: true } : {}) },\n port: far,\n };\n port.postMessage({ sealedFetch: ask }, [far]);\n return head.promise;\n}\n\ninterface FetchAnswer {\n close(reason: unknown): void;\n}\n\nfunction uploadOf(far: MessagePort): {\n stream: AsyncIterable<Uint8Array>;\n answer(message: Extract<AnswererMessage, { t: 'chunk' | 'end' | 'error' }>): void;\n fail(reason: Error): void;\n} {\n let waiting: PromiseWithResolvers<IteratorResult<Uint8Array>> | undefined;\n let failure: Error | undefined;\n const next = () => {\n if (failure) return Promise.reject(failure);\n waiting = Promise.withResolvers();\n far.postMessage({ t: 'pull' } satisfies AskerMessage);\n return waiting.promise;\n };\n return {\n stream: {\n [Symbol.asyncIterator]: () => ({\n next,\n return: async () => {\n far.postMessage({ t: 'stop' } satisfies AskerMessage);\n return { value: undefined, done: true };\n },\n }),\n },\n answer(message) {\n if (message.t === 'chunk') waiting?.resolve({ value: message.bytes, done: false });\n else if (message.t === 'end') waiting?.resolve({ value: undefined, done: true });\n else {\n failure = new Error(message.message);\n waiting?.reject(failure);\n }\n waiting = undefined;\n },\n fail(reason) {\n failure = reason;\n waiting?.reject(reason);\n waiting = undefined;\n },\n };\n}\n\nfunction answerFetch(\n hook: SealedFetchHook | undefined,\n { req, port: far }: SealedFetchAsk,\n live: Set<FetchAnswer>\n): void {\n const control = new AbortController();\n const { streamed, ...fields } = req;\n const upload = uploadOf(far);\n let source: AsyncIterator<Uint8Array> | undefined;\n let reply: Response | undefined;\n let closed = false;\n\n const settle = () => {\n closed = true;\n live.delete(answer);\n upload.fail(new Error('the request ended'));\n };\n const answer: FetchAnswer = {\n close(reason) {\n if (closed) return;\n settle();\n control.abort(reason);\n dropSealedReply(reply);\n far.close();\n },\n };\n const finish = (message: AskerMessage) => {\n if (closed) return;\n settle();\n far.postMessage(message);\n };\n const failWith = (err: unknown) => {\n dropSealedReply(reply);\n finish({ t: 'error', message: textOf(err) });\n };\n const read = async () => {\n try {\n const next = await (source as AsyncIterator<Uint8Array>).next();\n if (closed) return;\n if (next.done) finish({ t: 'end' });\n else if (next.value instanceof Uint8Array) sendBytes(far, next.value);\n else failWith('a body chunk is not bytes');\n } catch (err) {\n failWith(err);\n }\n };\n const ask = async () => {\n try {\n if (!hook) throw new Error('no vault is connected');\n const request: SealedFetchRequest = {\n ...fields,\n ...(streamed ? { bodyStream: upload.stream } : {}),\n };\n const answered: unknown = await hook(request, { signal: control.signal });\n if (!sealedReplyValid(answered)) {\n dropSealedReply(answered);\n throw new Error('the reply is not a scrubbed response');\n }\n if (closed) return dropSealedReply(answered);\n reply = answered;\n source = answered.body[Symbol.asyncIterator]();\n const { status, statusText, headers, url } = answered;\n far.postMessage({\n t: 'head',\n status,\n statusText,\n headers,\n ...(url !== undefined ? { url } : {}),\n } satisfies AskerMessage);\n } catch (err) {\n failWith(err);\n }\n };\n far.addEventListener('message', ({ data }: MessageEvent<AnswererMessage>) => {\n if (data.t === 'read') void read();\n else if (data.t === 'cancel') answer.close(data.reason);\n else upload.answer(data);\n });\n far.addEventListener('close', () => answer.close('withdrawn'));\n far.start();\n live.add(answer);\n void ask();\n}\n\nexport function sealedAsker(port: SealedPort): {\n hook: SealedHook;\n fetch: SealedFetchHook;\n answer(reply: SealedReply): void;\n} {\n const asks = new Map<number, PromiseWithResolvers<object>>();\n let next = 0;\n const hook: SealedHook = (req, { signal }) => {\n const id = ++next;\n const waiting = Promise.withResolvers<object>();\n asks.set(id, waiting);\n const abort = () => {\n if (!asks.delete(id)) return;\n port.postMessage({ sealedAbort: { id, reason: signal.reason } });\n waiting.reject(new Error(String(signal.reason)));\n };\n signal.addEventListener('abort', abort, { once: true });\n port.postMessage({ sealedAsk: { id, req } });\n return waiting.promise.finally(() => signal.removeEventListener('abort', abort));\n };\n const answer = ({ id, reply, error }: SealedReply) => {\n const waiting = asks.get(id);\n if (!waiting) return;\n asks.delete(id);\n if (reply) waiting.resolve(reply);\n else waiting.reject(new Error(error ?? 'no reply'));\n };\n return { hook, fetch: (req, { signal }) => askFetch(port, req, signal), answer };\n}\n\nexport interface SealedAnswerer {\n handle(data: unknown): boolean;\n close(): void;\n}\n\nexport function sealedAnswerer(\n port: SealedPort,\n hook: SealedHook | undefined,\n fetchHook?: SealedFetchHook\n): SealedAnswerer {\n const asked = new Map<number, AbortController>();\n const fetches = new Set<FetchAnswer>();\n const ask = async ({ id, req }: SealedAsk): Promise<void> => {\n const control = new AbortController();\n asked.set(id, control);\n try {\n if (!hook) throw new Error('no vault is connected');\n const reply = await hook(req, { signal: control.signal });\n port.postMessage({ sealedReply: { id, reply } });\n } catch (err) {\n const error = err instanceof Error ? err.message : String(err);\n port.postMessage({ sealedReply: { id, error } });\n } finally {\n asked.delete(id);\n }\n };\n const abort = ({ id, reason }: SealedAbort): void => {\n asked.get(id)?.abort(reason);\n asked.delete(id);\n };\n return {\n handle(data) {\n const message = data as {\n sealedAsk?: SealedAsk;\n sealedAbort?: SealedAbort;\n sealedFetch?: SealedFetchAsk;\n } | null;\n if (message?.sealedAsk) void ask(message.sealedAsk);\n else if (message?.sealedAbort) abort(message.sealedAbort);\n else if (message?.sealedFetch) answerFetch(fetchHook, message.sealedFetch, fetches);\n else return false;\n return true;\n },\n close() {\n for (const control of asked.values()) control.abort('withdrawn');\n asked.clear();\n for (const answer of [...fetches]) answer.close('withdrawn');\n },\n };\n}\n", "export const MINUTE_MS = 60_000;\n\nconst HOUR_MS = 60 * MINUTE_MS;\nconst BUCKET_MS = 15 * MINUTE_MS;\nconst CACHE_MAX = 4096;\nconst ZERO = new Set(['UTC', 'Etc/UTC', 'Etc/GMT', 'GMT', 'Etc/Universal', 'Etc/Zulu']);\n\nexport interface Zone {\n readonly name: string;\n offset(at: number): number;\n}\n\nexport function canonicalZone(name: unknown): string | undefined {\n if (typeof name !== 'string' || name === '' || name.length > 64) return undefined;\n try {\n return new Intl.DateTimeFormat('en-US', { timeZone: name }).resolvedOptions().timeZone;\n } catch {\n return undefined;\n }\n}\n\nexport function hostTimeZone(): string {\n let name: string | undefined;\n try {\n name = new Intl.DateTimeFormat().resolvedOptions().timeZone;\n } catch {\n name = undefined;\n }\n return canonicalZone(name) ?? 'UTC';\n}\n\nexport function systemTimeZone(given: string | undefined, fallback?: string): string {\n if (given !== undefined) {\n const zone = canonicalZone(given);\n if (zone === undefined) throw new Error(`not a time zone: ${String(given)}`);\n return zone;\n }\n return canonicalZone(fallback) ?? hostTimeZone();\n}\n\nexport const utcZone: Zone = { name: 'UTC', offset: () => 0 };\n\nfunction hostZone(name: string): Zone {\n return { name, offset: (at) => -new Date(at).getTimezoneOffset() * MINUTE_MS };\n}\n\nfunction intlZone(name: string): Zone {\n const format = new Intl.DateTimeFormat('en-US', {\n timeZone: name,\n hourCycle: 'h23',\n year: 'numeric',\n month: 'numeric',\n day: 'numeric',\n hour: 'numeric',\n minute: 'numeric',\n second: 'numeric',\n });\n const exact = (at: number): number => {\n const parts: Record<string, number> = {};\n for (const part of format.formatToParts(at)) parts[part.type] = Number(part.value);\n const wall = Date.UTC(\n parts.year as number,\n (parts.month as number) - 1,\n parts.day as number,\n parts.hour as number,\n parts.minute as number,\n parts.second as number\n );\n return wall - Math.floor(at / 1000) * 1000;\n };\n const buckets = new Map<number, number | null>();\n return {\n name,\n offset(at) {\n const bucket = Math.floor(at / BUCKET_MS);\n let known = buckets.get(bucket);\n if (known === undefined) {\n const start = exact(bucket * BUCKET_MS);\n known = start === exact(bucket * BUCKET_MS + BUCKET_MS - MINUTE_MS) ? start : null;\n if (buckets.size >= CACHE_MAX) buckets.clear();\n buckets.set(bucket, known);\n }\n return known ?? exact(at);\n },\n };\n}\n\nconst zones = new Map<string, Zone>();\n\nexport function zoneOf(name: string): Zone {\n if (ZERO.has(name)) return utcZone;\n if (name === hostTimeZone()) return hostZone(name);\n let zone = zones.get(name);\n if (!zone) {\n zone = intlZone(name);\n zones.set(name, zone);\n }\n return zone;\n}\n\nexport const MAX_SHIFT_MS = 3 * HOUR_MS;\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 RealmWebSocket,\n RealmWebSocketMessage,\n RealmWebSocketRequest,\n} from './kernel/net/transport.ts';\nimport { MessageQueue } from './kernel/net/ws-queue.ts';\n\nexport interface WebSocketLike {\n binaryType: string;\n readonly protocol: string;\n readonly bufferedAmount: number;\n send(data: string | ArrayBufferView): void;\n close(code?: number, reason?: string): void;\n addEventListener(type: string, listener: (event: never) => void): void;\n}\n\nexport type WebSocketConstructor = new (url: string, init?: unknown) => WebSocketLike;\n\nconst SENT_HEADERS_DROP = new Set([\n 'host',\n 'connection',\n 'upgrade',\n 'sec-websocket-key',\n 'sec-websocket-version',\n 'sec-websocket-extensions',\n 'sec-websocket-protocol',\n]);\n\nfunction headerRecord(headers: HeaderList): Record<string, string> {\n const out: Record<string, string> = {};\n for (const [name, value] of headers) {\n if (!SENT_HEADERS_DROP.has(name.toLowerCase())) out[name] = value;\n }\n return out;\n}\n\nexport function sendableClose(code?: number): number {\n return code === 1000 || (code !== undefined && code >= 3000 && code <= 4999) ? code : 1000;\n}\n\nfunction blockedReason(url: string, e: unknown): string {\n const name = (e as { name?: unknown } | null)?.name;\n if (name === 'SecurityError' && url.startsWith('ws:')) {\n return `${url}: ws:// is blocked from an https page; use wss://, or link a slicc CLI (npx sliccy@next)`;\n }\n return `${url}: ${e instanceof Error ? e.message : String(e)}`;\n}\n\nfunction unopened(url: string, code: number): Error {\n return Object.assign(new Error(`${url}: the WebSocket closed (${code}) before it opened`), {\n status: 502,\n });\n}\n\nexport function openWebSocket(\n Socket: WebSocketConstructor,\n request: RealmWebSocketRequest,\n withHeaders: boolean\n): Promise<RealmWebSocket> {\n const { url, protocols, signal } = request;\n signal.throwIfAborted();\n let socket: WebSocketLike;\n try {\n socket = withHeaders\n ? new Socket(url, { protocols, headers: headerRecord(request.headers) })\n : new Socket(url, protocols);\n } catch (e) {\n return Promise.reject(Object.assign(new Error(blockedReason(url, e)), { status: 502 }));\n }\n socket.binaryType = 'arraybuffer';\n const queue = new MessageQueue(() => socket.close(1000, 'too many waiting messages'));\n return new Promise((resolve, reject) => {\n let open = false;\n let settled = false;\n const fail = (error: unknown) => {\n if (settled) return;\n settled = true;\n signal.removeEventListener('abort', abort);\n reject(error);\n };\n const abort = () => {\n fail(signal.reason);\n socket.close(1000, 'aborted');\n };\n signal.addEventListener('abort', abort, { once: true });\n socket.addEventListener('open', () => {\n if (settled) return;\n open = true;\n settled = true;\n signal.removeEventListener('abort', abort);\n resolve({\n protocol: socket.protocol,\n get buffered() {\n return socket.bufferedAmount;\n },\n send: (data: RealmWebSocketMessage) => socket.send(data),\n messages: queue,\n close: (code?: number, reason?: string) => socket.close(sendableClose(code), reason),\n closed: queue.closed,\n });\n });\n socket.addEventListener('message', (event: { data: string | ArrayBuffer }) => {\n queue.push(typeof event.data === 'string' ? event.data : new Uint8Array(event.data));\n });\n socket.addEventListener('error', () => {\n if (open || settled) return;\n fail(unopened(url, 1006));\n queue.end({ code: 1006, reason: '' });\n try {\n socket.close();\n } catch {}\n });\n socket.addEventListener(\n 'close',\n (event: { code: number; reason: string; wasClean?: boolean }) => {\n queue.end({ code: event.code, reason: event.reason, wasClean: event.wasClean === true });\n if (open) return;\n fail(unopened(url, event.code));\n }\n );\n });\n}\n", "import { BODY_IDLE_MS, readWithin } from './body-idle.ts';\nimport { fresh } from './bytes.ts';\nimport type { TransportCall, TransportReply } from './kernel/net/remote-transport.ts';\nimport type {\n HeaderList,\n RealmRedirectHop,\n RealmRedirectPolicy,\n RealmTransport,\n RealmTransportExit,\n RealmTransportRequest,\n RealmTransportResponse,\n RealmTransportTraits,\n RealmWebSocket,\n RealmWebSocketRequest,\n} from './kernel/net/transport.ts';\nimport { INBOUND_LIMIT, MESSAGE_LIMIT, payloadSize } from './kernel/net/ws-queue.ts';\nimport { openWebSocket, type WebSocketConstructor } from './websocket-transport.ts';\n\nexport type {\n HeaderList,\n RealmRedirectHop as NetworkRedirectHop,\n RealmRedirectPolicy as NetworkRedirectPolicy,\n RealmTransport as NetworkTransport,\n RealmTransportExit as NetworkExit,\n RealmTransportRequest as NetworkRequest,\n RealmTransportResponse as NetworkResponse,\n RealmTransportTraits as NetworkTraits,\n RealmWebSocket as NetworkWebSocket,\n RealmWebSocketRequest as NetworkWebSocketRequest,\n};\n\nexport interface FetchTransportOptions {\n fetch?: typeof globalThis.fetch;\n maxRequestBody?: number;\n hint?: string;\n bodyIdleMs?: number;\n webSocket?: boolean | WebSocketConstructor;\n webSocketHeaders?: boolean;\n redirect?: 'follow' | 'manual';\n streamingBodies?: boolean;\n}\n\nexport const SEND_BUFFER = 1024 * 1024;\nconst CLOSE_WAIT_MS = 5000;\nconst DNS_CODES = new Set(['ENOTFOUND', 'EAI_AGAIN', 'EAI_NONAME', 'EAI_FAIL', 'ENODATA']);\n\nconst NO_WEBSOCKET =\n 'WebSocket not supported by this transport (fetchTransport needs { webSocket: true })';\n\nconst MAX_REQUEST_BODY = 64 * 1024 * 1024;\n\nfunction joinHeaders(headers: HeaderList): Headers {\n const out = new Headers();\n for (const [name, value] of headers) {\n try {\n out.append(name, value);\n } catch {}\n }\n return out;\n}\n\nasync function* chunks(\n body: ReadableStream<Uint8Array> | null,\n idleMs: number\n): AsyncGenerator<Uint8Array> {\n if (!body) return;\n const reader = body.getReader();\n try {\n for (\n let next = await readWithin(reader, idleMs);\n !next.done;\n next = await readWithin(reader, idleMs)\n ) {\n if (next.value.byteLength > 0) yield next.value;\n }\n } finally {\n await reader.cancel().catch(() => undefined);\n }\n}\n\nfunction sentHeaders(headers: HeaderList, inPage: boolean): Headers {\n const out = joinHeaders(headers);\n if (inPage) out.delete('user-agent');\n return out;\n}\n\nfunction streamOf(body: AsyncIterable<Uint8Array>): ReadableStream<Uint8Array> {\n const it = body[Symbol.asyncIterator]();\n return new ReadableStream<Uint8Array>(\n {\n async pull(controller) {\n const next = await it.next();\n if (next.done) controller.close();\n else controller.enqueue(next.value);\n },\n async cancel(reason) {\n await it.return?.(reason);\n },\n },\n { highWaterMark: 0 }\n );\n}\n\nfunction requestBody(request: RealmTransportRequest): RequestInit {\n if (request.bodyStream) {\n return { body: streamOf(request.bodyStream), duplex: 'half' } as RequestInit;\n }\n return request.body ? { body: request.body as BodyInit } : {};\n}\n\nexport function fetchTransport(options: FetchTransportOptions = {}): RealmTransport {\n const send = options.fetch ?? globalThis.fetch.bind(globalThis);\n const Socket =\n options.webSocket === true\n ? (globalThis as { WebSocket?: WebSocketConstructor }).WebSocket\n : options.webSocket || undefined;\n const headers = options.webSocketHeaders === true;\n const instance = options.redirect ?? 'follow';\n const inPage = !options.fetch && 'location' in globalThis;\n return {\n traits: {\n manualRedirects: instance === 'manual',\n redirectPolicy: true,\n encodedBodies: false,\n maxRequestBody: options.maxRequestBody ?? MAX_REQUEST_BODY,\n crossOrigin: 'cors',\n ...(Socket ? { websocket: true as const } : {}),\n ...(options.streamingBodies ? { streamingBodies: true as const } : {}),\n },\n ...(Socket ? { websocket: (request) => openWebSocket(Socket, request, headers) } : {}),\n async fetch(request: RealmTransportRequest): Promise<RealmTransportResponse> {\n let response: Response;\n try {\n response = await send(request.url, {\n method: request.method,\n headers: sentHeaders(request.headers, inPage),\n ...requestBody(request),\n signal: request.signal,\n redirect: request.redirect ?? instance,\n credentials: 'omit',\n mode: 'cors',\n });\n } catch (e) {\n if (request.signal.aborted) throw e;\n const causeCode = (e as { cause?: { code?: unknown } })?.cause?.code;\n const dns = typeof causeCode === 'string' && DNS_CODES.has(causeCode);\n throw Object.assign(\n new Error(\n `fetch ${request.url} failed (unreachable, or not allowed by CORS)${options.hint ? `: ${options.hint}` : ''}`\n ),\n { status: 502 },\n dns ? { code: causeCode } : {},\n typeof causeCode === 'string' ? {} : { detail: 'transport' }\n );\n }\n const headers: Array<[string, string]> = [];\n response.headers.forEach((value, name) => {\n headers.push([name, value]);\n });\n const body = chunks(response.body, options.bodyIdleMs ?? BODY_IDLE_MS);\n return {\n ...(response.redirected ? { url: response.url, redirected: true } : {}),\n ...(response.type === 'opaqueredirect' ? { opaqueRedirect: true as const } : {}),\n status: response.status,\n statusText: response.statusText,\n headers,\n body,\n cancel: async () => {\n await body.return(undefined);\n await response.body?.cancel().catch(() => undefined);\n },\n };\n },\n };\n}\n\nexport interface TransportPeer {\n postMessage(message: TransportReply, transfer?: Transferable[]): void;\n}\n\nexport interface TransportServer {\n answer(call: TransportCall): void;\n close(): void;\n}\n\ninterface Flow {\n inflight: number;\n closing: boolean;\n dropped: boolean;\n deadline(): void;\n wake?: () => void;\n}\n\nfunction uploadsFor(peer: TransportPeer) {\n const pulls = new Map<number, (call: TransportCall) => void>();\n const of = (nid: number, signal: AbortSignal): AsyncIterable<Uint8Array> => ({\n async *[Symbol.asyncIterator]() {\n for (;;) {\n signal.throwIfAborted();\n const got = await new Promise<TransportCall>((resolve, reject) => {\n const stop = () => reject(signal.reason);\n signal.addEventListener('abort', stop, { once: true });\n pulls.set(nid, (call) => {\n signal.removeEventListener('abort', stop);\n resolve(call);\n });\n peer.postMessage({ net: 'body-pull', nid });\n }).finally(() => pulls.delete(nid));\n if (got.net === 'body-end') return;\n if (got.net === 'body-error') throw new Error(got.message);\n if (got.net === 'body-chunk') yield got.bytes;\n }\n },\n });\n return { of, answer: (call: TransportCall) => pulls.get(call.nid)?.(call) };\n}\n\nfunction headOf(nid: number, response: RealmTransportResponse): TransportReply {\n return {\n net: 'head',\n nid,\n ...(response.url !== undefined ? { url: response.url } : {}),\n ...(response.redirected !== undefined ? { redirected: response.redirected } : {}),\n ...(response.redirects ? { redirects: response.redirects } : {}),\n ...(response.opaqueRedirect ? { opaqueRedirect: true } : {}),\n status: response.status,\n statusText: response.statusText,\n headers: response.headers,\n };\n}\n\nfunction requestOf(\n call: Extract<TransportCall, { net: 'fetch' }>,\n signal: AbortSignal,\n uploads: ReturnType<typeof uploadsFor>\n): RealmTransportRequest {\n const { url, method, headers, streamed, body, redirect, nid } = call;\n return {\n url,\n method,\n headers,\n ...(streamed ? { bodyStream: uploads.of(nid, signal) } : body ? { body } : {}),\n ...(redirect !== undefined ? { redirect } : {}),\n signal,\n };\n}\n\nexport function serveTransport(\n peer: TransportPeer,\n transport: RealmTransport,\n {\n closeWaitMs = CLOSE_WAIT_MS,\n attributed = false,\n }: { closeWaitMs?: number; attributed?: boolean } = {}\n): TransportServer {\n const open = new Map<\n number,\n { abort: AbortController; body?: AsyncIterator<Uint8Array>; response?: RealmTransportResponse }\n >();\n const fail = (nid: number, e: unknown) => {\n open.delete(nid);\n const { status, code, detail } = e as { status?: unknown; code?: unknown; detail?: unknown };\n peer.postMessage({\n net: 'error',\n nid,\n message: e instanceof Error ? e.message : String(e),\n ...(typeof status === 'number' ? { status } : {}),\n ...(typeof code === 'string' ? { code } : {}),\n ...(detail === 'transport' ? { detail } : {}),\n });\n };\n const uploads = uploadsFor(peer);\n const start = async (call: Extract<TransportCall, { net: 'fetch' }>) => {\n const abort = new AbortController();\n const entry: { abort: AbortController; body?: AsyncIterator<Uint8Array> } = { abort };\n open.set(call.nid, entry);\n try {\n const response = await transport.fetch(\n requestOf(call, abort.signal, uploads),\n attributed ? call.owner : undefined,\n attributed ? call.stamp : undefined\n );\n if (!open.has(call.nid)) {\n await response.cancel();\n return;\n }\n open.set(call.nid, { abort, body: response.body[Symbol.asyncIterator](), response });\n peer.postMessage(headOf(call.nid, response));\n } catch (e) {\n fail(call.nid, e);\n }\n };\n const sockets = new Map<number, RealmWebSocket>();\n const credit = new Map<number, Flow>();\n const refill = (nid: number, n: number, closing = false) => {\n const flow = credit.get(nid);\n if (!flow) return;\n flow.inflight -= n;\n if (closing && !flow.closing) {\n flow.closing = true;\n flow.deadline();\n }\n flow.wake?.();\n };\n const openSocket = async (call: Extract<TransportCall, { net: 'ws-open' }>) => {\n const abort = new AbortController();\n open.set(call.nid, { abort });\n try {\n if (!transport.websocket) throw new Error(NO_WEBSOCKET);\n const socket = await transport.websocket({\n url: call.url,\n protocols: call.protocols,\n headers: call.headers,\n signal: abort.signal,\n });\n if (!open.delete(call.nid)) {\n socket.close(1000, 'cancelled');\n return;\n }\n sockets.set(call.nid, socket);\n peer.postMessage({ net: 'ws-opened', nid: call.nid, protocol: socket.protocol });\n void relay(call.nid, socket);\n } catch (e) {\n fail(call.nid, e);\n }\n };\n const relay = async (nid: number, socket: RealmWebSocket) => {\n let ending: { code: number; reason: string };\n let late!: () => void;\n const unanswered = new Promise<'late'>((resolve) => {\n late = () => resolve('late');\n });\n const flow: Flow = {\n inflight: 0,\n closing: false,\n dropped: false,\n deadline: () =>\n AbortSignal.timeout(closeWaitMs).addEventListener('abort', late, { once: true }),\n };\n credit.set(nid, flow);\n const timedOut = { code: 1006, reason: 'the far end did not answer the close' };\n let oversize = false;\n try {\n const messages = socket.messages[Symbol.asyncIterator]();\n for (;;) {\n const next = await Promise.race([messages.next(), unanswered]);\n if (next === 'late' || next.done) break;\n const data = next.value;\n if (flow.dropped) continue;\n if (payloadSize(data) > MESSAGE_LIMIT) {\n oversize = true;\n break;\n }\n if (typeof data === 'string') peer.postMessage({ net: 'ws-message', nid, data });\n else {\n const bytes = fresh(data);\n peer.postMessage({ net: 'ws-message', nid, data: bytes }, [bytes.buffer]);\n }\n flow.inflight += payloadSize(data);\n while (flow.inflight > INBOUND_LIMIT && !flow.closing) {\n await new Promise<void>((resolve) => {\n flow.wake = resolve;\n });\n }\n }\n if (oversize) socket.close(1000, 'a message is too big');\n ending = oversize\n ? { code: 1009, reason: `a message is over ${MESSAGE_LIMIT} bytes` }\n : await Promise.race([socket.closed, unanswered.then(() => timedOut)]);\n } catch (e) {\n socket.close(1000, 'the relay failed');\n ending = { code: 1011, reason: e instanceof Error ? e.message : String(e) };\n }\n sockets.delete(nid);\n credit.delete(nid);\n peer.postMessage({ net: 'ws-closed', nid, ...ending });\n };\n const sendOn = async (call: Extract<TransportCall, { net: 'ws-send' }>) => {\n const socket = sockets.get(call.nid);\n if (!socket) return;\n socket.send(call.data);\n while (socket.buffered > SEND_BUFFER && sockets.has(call.nid)) {\n await new Promise((resolve) => setTimeout(resolve, 10));\n }\n peer.postMessage({ net: 'ws-acked', nid: call.nid, n: payloadSize(call.data) });\n };\n const read = async (nid: number) => {\n const body = open.get(nid)?.body;\n if (!body) return;\n try {\n const next = await body.next();\n if (next.done) {\n open.delete(nid);\n peer.postMessage({ net: 'end', nid });\n } else {\n const bytes = fresh(next.value);\n peer.postMessage({ net: 'chunk', nid, bytes }, [bytes.buffer]);\n }\n } catch (e) {\n fail(nid, e);\n }\n };\n const drop = (nid: number) => {\n sockets.get(nid)?.close(1000, 'cancelled');\n const flow = credit.get(nid);\n if (flow) flow.dropped = true;\n refill(nid, 0, true);\n const entry = open.get(nid);\n open.delete(nid);\n entry?.abort.abort();\n void entry?.response?.cancel().catch(() => undefined);\n };\n return {\n answer(call) {\n if (call.net === 'fetch') void start(call);\n else if (call.net === 'body-chunk' || call.net === 'body-end' || call.net === 'body-error') {\n uploads.answer(call);\n } else if (call.net === 'read') void read(call.nid);\n else if (call.net === 'ws-open') void openSocket(call);\n else if (call.net === 'ws-send') void sendOn(call);\n else if (call.net === 'ws-close') {\n sockets.get(call.nid)?.close(call.code, call.reason);\n refill(call.nid, 0, true);\n } else if (call.net === 'ws-consumed') refill(call.nid, call.n);\n else drop(call.nid);\n },\n close() {\n for (const nid of [...open.keys(), ...sockets.keys()]) drop(nid);\n },\n };\n}\n", "import type { SealedCaller } from '../sealed.ts';\nimport type {\n HeaderList,\n RealmRedirectHop,\n RealmRedirectPolicy,\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 streamed?: true;\n redirect?: RealmRedirectPolicy;\n owner?: number;\n stamp?: SealedCaller;\n }\n | { net: 'body-chunk'; nid: number; bytes: Uint8Array }\n | { net: 'body-end'; nid: number }\n | { net: 'body-error'; nid: number; message: string }\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 | {\n net: 'head';\n nid: number;\n status: number;\n statusText: string;\n headers: HeaderList;\n url?: string;\n redirected?: boolean;\n redirects?: readonly RealmRedirectHop[];\n opaqueRedirect?: true;\n }\n | { net: 'chunk'; nid: number; bytes: Uint8Array }\n | { net: 'body-pull'; nid: number }\n | { net: 'end'; nid: number }\n | {\n net: 'error';\n nid: number;\n message: string;\n status?: number;\n code?: string;\n detail?: 'transport';\n }\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 readonly detail: 'transport' | undefined;\n\n constructor(message: string, status?: number, code?: string, detail?: unknown) {\n super(message);\n this.status = status;\n this.code = code;\n this.detail = detail === 'transport' ? detail : undefined;\n }\n}\n\nexport function unfollowed(redirect?: RealmRedirectPolicy): boolean {\n return redirect !== undefined && redirect !== 'follow';\n}\n\nfunction honors(traits: RealmTransportTraits, redirect?: RealmRedirectPolicy): boolean {\n if (traits.redirectPolicy === true) return true;\n const hops = traits.redirectHops as unknown;\n const raw = traits.manualRedirects === true && (hops === undefined || hops === false);\n return redirect === 'manual' && raw;\n}\n\nfunction refused(message: string): TransportError {\n return new TransportError(message, 502, undefined, 'transport');\n}\n\ninterface Waiter {\n resolve(reply: TransportReply): void;\n reject(error: Error): void;\n}\n\nexport class RemoteTransport implements RealmTransport {\n 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 readonly uploads = new Map<number, AsyncIterator<Uint8Array>>();\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 if (reply.net === 'body-pull') {\n void this.pull(reply.nid);\n return;\n }\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, reply.detail));\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 private async pull(nid: number): Promise<void> {\n const upload = this.uploads.get(nid);\n if (!upload) {\n this.port.postMessage({ net: 'body-error', nid, message: 'the request body is gone' });\n return;\n }\n try {\n const next = await upload.next();\n if (next.done) {\n this.uploads.delete(nid);\n this.port.postMessage({ net: 'body-end', nid });\n } else this.port.postMessage({ net: 'body-chunk', nid, bytes: next.value });\n } catch (e) {\n this.uploads.delete(nid);\n this.port.postMessage({\n net: 'body-error',\n nid,\n message: e instanceof Error ? e.message : String(e),\n });\n }\n }\n\n private dropUpload(nid: number): void {\n const upload = this.uploads.get(nid);\n this.uploads.delete(nid);\n void upload?.return?.().catch(() => undefined);\n }\n\n fail(error: Error): void {\n this.failure = error;\n for (const nid of [...this.uploads.keys()]) this.dropUpload(nid);\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(\n request: RealmTransportRequest,\n owner?: number,\n stamp?: SealedCaller\n ): Promise<RealmTransportResponse> {\n const nid = ++this.nextId;\n const { signal, redirect } = request;\n signal.throwIfAborted();\n if (unfollowed(redirect) && !honors(this.traits, redirect)) {\n throw refused(`this transport cannot honor redirect: ${redirect}`);\n }\n let finished = false;\n const abort = () => {\n finished = true;\n this.dropUpload(nid);\n this.cancel(nid);\n };\n signal.addEventListener('abort', abort, { once: true });\n const finish = () => {\n this.dropUpload(nid);\n if (finished) return;\n finished = true;\n signal.removeEventListener('abort', abort);\n };\n if (request.bodyStream) this.uploads.set(nid, request.bodyStream[Symbol.asyncIterator]());\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.bodyStream\n ? { streamed: true as const }\n : request.body\n ? { body: request.body }\n : {}),\n ...(redirect !== undefined ? { redirect } : {}),\n ...(owner !== undefined ? { owner } : {}),\n ...(stamp ? { stamp } : {}),\n });\n } catch (e) {\n finish();\n throw e;\n }\n const { status, statusText, headers, url, redirected, redirects, opaqueRedirect } =\n 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 if (unfollowed(redirect) && (redirected || redirects?.length)) {\n await cancel();\n throw refused(`this transport followed a redirect despite redirect: ${redirect}`);\n }\n return {\n ...(url !== undefined ? { url } : {}),\n ...(redirected !== undefined ? { redirected } : {}),\n ...(redirects ? { redirects } : {}),\n ...(opaqueRedirect ? { opaqueRedirect } : {}),\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", "import type { UsersMode } from '../fs/types.ts';\nimport 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, 13];\n\nexport interface ClientHello {\n protocol: readonly [number, number];\n lock?: string;\n requests?: Record<string, { group?: string; users?: Array<string | number> }>;\n}\n\nexport interface KernelHello {\n protocol: readonly [number, number];\n lock?: string;\n traits?: RealmTransportTraits;\n users?: UsersMode;\n error?: string;\n}\n\nexport interface SpawnRequestOptions {\n cwd?: string;\n user?: string | number;\n env?: Record<string, string>;\n stdin?: Uint8Array;\n pgid?: number;\n tag?: string;\n}\n\nexport interface TerminalRequestOptions {\n cwd?: string;\n user?: string | number;\n env?: Record<string, string>;\n cols?: number;\n rows?: number;\n tag?: string;\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: 'serve-facade'; name: string }\n | { op: 'unserve-facade'; 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 signal?: string;\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' | 'T' | 'Z';\n memory: number;\n rss?: number;\n utime?: number;\n stime?: number;\n uid?: number;\n gid?: number;\n tag?: string;\n tags?: string[];\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 { embedderAnswerer } from '../embedder-relay.ts';\nimport { type FacadeOpen, serveFacadePort } from '../facade/port.ts';\nimport type { FacadeHook } from '../facade/types.ts';\nimport type { FsStat, UsersMode } from '../fs/types.ts';\nimport type { WatchChange } from '../fs/watch.ts';\nimport { type EmbedderHook, type EmbedderKindPolicy, kindsOf } from '../kernel/embedder.ts';\nimport { RemoteTransport, type TransportReply } from '../kernel/net/remote-transport.ts';\nimport type {\n RealmTransport,\n RealmTransportRequest,\n RealmTransportResponse,\n RealmTransportTraits,\n} from '../kernel/net/transport.ts';\nimport { quiet } from '../kernel/signals.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 requests?: EmbedderHook;\n}\n\nexport interface SpawnOptions {\n cwd?: string;\n user?: string | number;\n env?: Record<string, string>;\n stdin?: string | Uint8Array;\n group?: 'new';\n pgid?: number;\n tag?: string;\n onStdout?: (bytes: Uint8Array) => void;\n onStderr?: (bytes: Uint8Array) => void;\n}\n\nexport interface ClientEnded {\n status: number;\n signal?: string;\n}\n\nexport interface SpawnedProcess {\n readonly pid: number;\n readonly pgid: number;\n readonly exited: Promise<number>;\n readonly ended: Promise<ClientEnded>;\n signal(name?: string): Promise<void>;\n}\n\nexport interface ClientRunOptions {\n cwd?: string;\n user?: string | number;\n env?: Record<string, string>;\n stdin?: string | Uint8Array;\n tag?: string;\n onStdout?: (text: string) => void;\n onStderr?: (text: string) => void;\n}\n\nexport interface ClientRunResult {\n pid: number;\n status: number;\n signal?: string;\n stdout: string;\n stderr: string;\n}\n\nexport interface ClientTerminalOptions {\n cwd?: string;\n user?: string | number;\n env?: Record<string, string>;\n cols?: number;\n rows?: number;\n tag?: string;\n onData?: (bytes: Uint8Array) => void;\n}\n\nexport interface ClientTerminal {\n readonly pid: number;\n readonly exited: Promise<number>;\n readonly ended: Promise<ClientEnded>;\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 users: UsersMode;\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 serveFacade(name: string, hook: FacadeHook): Promise<{ close(): void }>;\n onTraits(listener: (traits: RealmTransportTraits) => void): () => 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 ended?: (signal: string | undefined) => 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\n readonly traitsListeners = new Set<(traits: RealmTransportTraits) => void>();\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 readonly facadeHooks = new Map<number, FacadeHook>();\n private readonly facadeOpen = 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 close of [...this.facadeOpen]) close();\n this.facadeOpen.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 requests: { handle(data: unknown): boolean } | undefined;\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 facadeOpen?: FacadeOpen['facadeOpen'];\n port?: CdpOpen['port'];\n traits?: RealmTransportTraits;\n id?: number;\n }): void {\n if (this.requests?.handle(data)) return;\n if (data.traits && data.id === undefined) {\n if (this.remote) this.remote.traits = data.traits;\n for (const listener of [...this.traitsListeners]) listener(data.traits);\n return;\n }\n if (data.cdpOpen && data.port) {\n this.openCdp(data as CdpOpen);\n return;\n }\n if (data.facadeOpen && data.port) {\n this.openFacade(data as FacadeOpen);\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 call.ended?.(reply.signal);\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 private openFacade({ facadeOpen: { registration, ...request }, port }: FacadeOpen): void {\n const hook = registration === undefined ? undefined : this.facadeHooks.get(registration);\n if (!hook || this.failure) {\n port.postMessage({ error: 'this client no longer serves the facade' });\n port.close();\n return;\n }\n const close = serveFacadePort(port, hook, request, () => this.facadeOpen.delete(close));\n this.facadeOpen.add(close);\n }\n}\n\nasync function serveFacadeOn(\n channel: Channel,\n name: string,\n hook: FacadeHook\n): Promise<{ close(): void }> {\n if (typeof hook !== 'function') throw new TypeError('serveFacade: hook must be a function');\n await since(channel, 11, 'facade serving', async () => {});\n const { id, done } = channel.request({ op: 'serve-facade' as const, name });\n channel.facadeHooks.set(id, hook);\n try {\n await done;\n } catch (error) {\n channel.facadeHooks.delete(id);\n throw error;\n }\n return {\n close: () => {\n if (!channel.facadeHooks.delete(id)) return;\n void channel.call({ op: 'unserve-facade', registration: id }).catch(() => undefined);\n },\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 if (opts.user !== undefined) await since(channel, 8, 'spawn as a user', async () => {});\n if (opts.tag !== undefined) await since(channel, 12, 'a tag per spawn', async () => {});\n const started = Promise.withResolvers<number>();\n let endedBy: string | undefined;\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 ended: (signal) => (endedBy = signal),\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 ended: endedOf(done, () => endedBy),\n signal: async (name = 'SIGTERM') =>\n void (await channel.call({ op: 'kill', pid: -pgid, signal: name })),\n };\n}\n\nfunction endedOf(done: Promise<unknown>, signal: () => string | undefined): Promise<ClientEnded> {\n return quiet(\n done.then((status) => {\n const by = signal();\n return { status: status as number, ...(by ? { signal: by } : {}) };\n })\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, signal } = await child.ended;\n const text = (fd: 1 | 2) => new TextDecoder().decode(concat(chunks[fd]));\n return {\n pid: child.pid,\n status,\n ...(signal ? { signal } : {}),\n stdout: text(1),\n stderr: text(2),\n };\n}\n\nasync function terminalOn(\n channel: Channel,\n argv: string[],\n opts: ClientTerminalOptions\n): Promise<ClientTerminal> {\n const { onData, ...options } = opts;\n if (opts.user !== undefined) await since(channel, 8, 'a terminal as a user', async () => {});\n if (opts.tag !== undefined) await since(channel, 12, 'a tag per terminal', async () => {});\n let listener = onData ?? null;\n const backlog: Uint8Array[] = [];\n const started = Promise.withResolvers<number>();\n let endedBy: string | undefined;\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 ended: (signal) => (endedBy = signal),\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 ended: endedOf(done, () => endedBy),\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 requests?: Record<string, EmbedderKindPolicy>\n): Promise<KernelHello> {\n channel.post({\n hello: { protocol: PROTOCOL, ...(lock ? { lock } : {}), ...(requests ? { requests } : {}) },\n });\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 requests = options.requests;\n if (requests) channel.requests = embedderAnswerer(port, () => requests);\n const hello = await greet(\n channel,\n own.name,\n options.timeoutMs ?? 10_000,\n requests ? kindsOf(requests) : undefined\n );\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 users: hello.users ?? 'off',\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 serveFacade: (name, hook) => serveFacadeOn(channel, name, hook),\n onTraits(listener) {\n channel.traitsListeners.add(listener);\n return () => channel.traitsListeners.delete(listener);\n },\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", "import {\n DRIVER_PROTOCOL,\n type DriverAttr,\n type DriverCapabilities,\n type DriverEntry,\n type DriverOwner,\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 DriverOwner,\n DriverStatfs,\n MountRequestInfo,\n} from './protocol.ts';\n\nimport { fresh } from '../bytes.ts';\n\nexport interface OpenFlags {\n write: boolean;\n create: boolean;\n truncate: boolean;\n exclusive: boolean;\n ifMatch?: string;\n owner?: DriverOwner;\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, owner?: DriverOwner): Promise<void>;\n rmdir(path: string): Promise<void>;\n unlink(path: string): Promise<void>;\n rename(from: string, to: string): Promise<void>;\n link?(from: string, to: string): Promise<void>;\n symlink?(target: string, path: string, owner?: DriverOwner): Promise<void>;\n mkfifo?(path: string, owner?: DriverOwner): Promise<void>;\n readlink?(path: string): Promise<string>;\n setattr?(path: string, attr: DriverSetAttr): Promise<void>;\n statfs?(): Promise<DriverStatfs>;\n}\n\nexport interface DriverSetAttr {\n mode?: number;\n mtime?: number;\n atime?: number;\n size?: number;\n uid?: number;\n gid?: number;\n}\n\nfunction ownerOf(req: DriverOwner): DriverOwner | undefined {\n const owner = {\n ...(req.uid !== undefined ? { uid: req.uid } : {}),\n ...(req.gid !== undefined ? { gid: req.gid } : {}),\n ...(req.mode !== undefined ? { mode: req.mode } : {}),\n };\n return Object.keys(owner).length > 0 ? owner : undefined;\n}\n\nfunction withOwner<T extends object>(base: T, owner: DriverOwner | undefined): T {\n return owner ? { ...base, owner } : base;\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\nconst SET_ATTRS = ['mode', 'mtime', 'atime', 'size', 'uid', 'gid'] as const;\n\nfunction setAttrOf(req: DriverSetAttr): DriverSetAttr {\n const attr: DriverSetAttr = {};\n for (const key of SET_ATTRS) if (req[key] !== undefined) attr[key] = req[key];\n return attr;\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(\n req.path,\n withOwner(\n {\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 ownerOf(req)\n )\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 ownerOf(req) ? h.mkdir(req.path, ownerOf(req)) : 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 'link':\n if (!h.link) throw fsError('EPERM', 'this file system has no hard links');\n return h.link(req.from, req.to);\n case 'mkfifo':\n if (!h.mkfifo) throw fsError('EPERM', 'this file system has no FIFOs');\n return ownerOf(req) ? h.mkfifo(req.path, ownerOf(req)) : h.mkfifo(req.path);\n case 'symlink':\n if (!h.symlink) throw fsError('EPERM', 'this file system has no symlinks');\n return ownerOf(req)\n ? h.symlink(req.target, req.path, ownerOf(req))\n : 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, setAttrOf(req));\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 : fresh(result);\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 { type FilesystemHandlers, fsError, type OpenFlags, serveFilesystem } from './driver.ts';\nimport { type MediumHandlers, mediumSlot } from './medium.ts';\nimport type { MountSpec, OpenedDriver } from './mount-fs.ts';\nimport type { DriverAttr, DriverCapabilities, DriverEntry, DriverStatfs } from './protocol.ts';\n\nexport interface HostfsGrant {\n url: string;\n token: string;\n readonly?: boolean;\n capabilities?: DriverCapabilities;\n}\n\nexport interface HostfsPortGrant {\n port: MessagePort;\n token?: string;\n capabilities?: DriverCapabilities;\n}\n\nexport type HostfsGrantHook = (\n source: string,\n options: { readonly: boolean }\n) => Promise<HostfsGrant | HostfsPortGrant>;\n\nexport type FetchLike = (url: string, init: RequestInit) => Promise<Response>;\n\nexport interface HostfsEvent {\n paths?: string[];\n all?: boolean;\n ping?: number;\n}\n\nexport interface HostfsTransport {\n readonly capabilities: DriverCapabilities;\n readonly token: string;\n readonly maxIo: number;\n readonly gone?: boolean;\n retire?(why: string): void;\n cleanup?(op: string, body: Record<string, unknown>): Promise<unknown>;\n call<T>(op: string, body?: Record<string, unknown>, handle?: boolean): Promise<T>;\n read(fh: number, offset: number, size: number, ifMatch?: string): Promise<Uint8Array>;\n write(fh: number, offset: number, bytes: Uint8Array): Promise<void>;\n watch(\n signal: AbortSignal,\n onEvent: (event: HostfsEvent) => void,\n onOpen?: () => void\n ): Promise<void>;\n}\n\nexport type HostfsConnect = (\n source: string,\n options: { readonly: boolean }\n) => Promise<HostfsTransport>;\n\nexport const HOSTFS_IO = 16 * 1024 * 1024;\n\nconst codeOf = (err: unknown) => (err as { code?: unknown } | null)?.code;\n\nexport const unreachable = (err: unknown) => codeOf(err) === 'ENOTCONN';\n\nfunction rel(path: string): string {\n return path.replace(/^\\/+/, '');\n}\n\nexport class HostfsClient implements HostfsTransport {\n private grant: HostfsGrant;\n private readonly regrant: () => Promise<HostfsGrant>;\n private readonly fetch: FetchLike;\n\n constructor(grant: HostfsGrant, regrant: () => Promise<HostfsGrant>, fetch: FetchLike) {\n this.grant = grant;\n this.regrant = regrant;\n this.fetch = fetch;\n }\n\n get capabilities(): DriverCapabilities {\n return this.grant.capabilities ?? {};\n }\n\n get token(): string {\n return this.grant.token;\n }\n\n get maxIo(): number {\n return this.capabilities.maxIo ?? HOSTFS_IO;\n }\n\n private retired: string | undefined;\n private readonly stop = new AbortController();\n\n get gone(): boolean {\n return this.retired !== undefined;\n }\n\n retire(why: string): void {\n this.retired ??= why;\n this.stop.abort();\n }\n\n private async send(\n path: string,\n init: RequestInit,\n handle = false,\n retried = false,\n cleanup = false\n ): Promise<Response> {\n if (this.retired && !cleanup) throw fsError('ENOTCONN', this.retired);\n const stop = cleanup ? undefined : this.stop.signal;\n const signal =\n init.signal && stop ? AbortSignal.any([init.signal, stop]) : (init.signal ?? stop);\n let response: Response;\n try {\n response = await this.fetch(`${this.grant.url}${path}`, {\n ...init,\n ...(signal ? { signal } : {}),\n credentials: 'omit',\n headers: {\n ...(init.headers as Record<string, string>),\n 'X-Hostfs-Token': this.grant.token,\n },\n });\n } catch (err) {\n throw fsError('ENOTCONN', `the host proxy is unreachable: ${(err as Error).message}`);\n }\n if (response.ok) return response;\n if (response.headers.get('X-Proxy-Error')) {\n await response.body?.cancel();\n if (retried || response.status !== 403) {\n throw fsError('EACCES', `the host proxy refused this folder (${response.status})`);\n }\n this.grant = await this.regrant();\n if (handle)\n throw fsError('ESTALE', 'the folder was granted again, so its open files are gone');\n return this.send(path, init, false, true);\n }\n const errno = response.headers.get('X-Hostfs-Errno') ?? 'EIO';\n const body = (await response.json().catch(() => ({}))) as { message?: unknown };\n throw fsError(errno, typeof body.message === 'string' ? body.message : errno);\n }\n\n async call<T>(op: string, body: Record<string, unknown> = {}, handle = false): Promise<T> {\n const response = await this.send(\n '/api/hostfs',\n {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ op, ...body }),\n },\n handle\n );\n return (await response.json()) as T;\n }\n\n async cleanup(op: string, body: Record<string, unknown>): Promise<unknown> {\n const response = await this.send(\n '/api/hostfs',\n {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ op, ...body }),\n },\n true,\n false,\n true\n );\n return response.json().catch(() => null);\n }\n\n async read(fh: number, offset: number, size: number, ifMatch?: string): Promise<Uint8Array> {\n const response = await this.send(\n '/api/hostfs',\n {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ op: 'read', fh, offset, size, ...(ifMatch ? { ifMatch } : {}) }),\n },\n true\n );\n return new Uint8Array(await response.arrayBuffer());\n }\n\n async write(fh: number, offset: number, bytes: Uint8Array): Promise<void> {\n const response = await this.send(\n '/api/hostfs/write',\n {\n method: 'PUT',\n headers: {\n 'Content-Type': 'application/octet-stream',\n 'X-Hostfs-Request': JSON.stringify({ fh, offset }),\n },\n body: bytes as BodyInit,\n },\n true\n );\n await response.body?.cancel();\n }\n\n async watch(\n signal: AbortSignal,\n onEvent: (event: HostfsEvent) => void,\n onOpen: () => void = () => undefined\n ): Promise<void> {\n const response = await this.send('/api/hostfs/watch', { method: 'POST', signal });\n onOpen();\n const reader = (response.body as ReadableStream<Uint8Array>).getReader();\n const decoder = new TextDecoder();\n let buffered = '';\n try {\n for (;;) {\n const { done, value } = await reader.read();\n if (done) return;\n buffered += decoder.decode(value, { stream: true });\n let end = buffered.indexOf('\\n');\n while (end >= 0) {\n const line = buffered.slice(0, end).trim();\n buffered = buffered.slice(end + 1);\n if (line) onEvent(JSON.parse(line) as HostfsEvent);\n end = buffered.indexOf('\\n');\n }\n }\n } catch (err) {\n if (signal.aborted) return;\n throw fsError('ENOTCONN', `the host proxy's watch broke: ${(err as Error).message}`);\n } finally {\n reader.releaseLock();\n }\n }\n}\n\ninterface Remote {\n client: HostfsTransport;\n token: string;\n fh: number;\n etag: string | undefined;\n restore: Restore | undefined;\n}\n\ntype Restore = { path: string; mode: number; was: DriverAttr };\n\nexport const RESTORE_AGAIN_MS = 30_000;\n\nexport function hostfsHandlers(\n current: () => HostfsTransport,\n againMs = RESTORE_AGAIN_MS\n): MediumHandlers {\n const handles = new Map<number, Remote>();\n let nextFh = 0;\n const fresh = (remote: Remote): Remote => {\n if (remote.client.token === remote.token && !remote.client.gone) return remote;\n throw fsError('ESTALE', 'the folder was granted again, so this open file is gone');\n };\n const live = (fh: number): Remote => {\n const remote = handles.get(fh);\n if (!remote) throw fsError('EBADF', `handle ${fh}`);\n return fresh(remote);\n };\n const call = <T>(op: string, body: Record<string, unknown> = {}) => current().call<T>(op, body);\n const same = (was: DriverAttr, mode: number, seen: DriverAttr | null) =>\n seen?.mode === (mode | 0o200) &&\n (was.ino !== undefined && seen.ino !== undefined\n ? seen.ino === was.ino\n : seen.size === was.size && seen.mtime === was.mtime);\n const settle = (client: HostfsTransport, { was, ...restore }: Restore) =>\n client.call('setattr', restore).catch((err: unknown) => {\n if (!client.gone || !client.cleanup) throw err;\n void client.cleanup('setattr', restore).catch(() => {});\n const timer = setTimeout(async () => {\n const seen = (await client\n .cleanup?.('stat', { path: restore.path })\n .catch(() => null)) as DriverAttr | null;\n if (same(was, restore.mode, seen))\n void client.cleanup?.('setattr', restore).catch(() => {});\n }, againMs) as { unref?: () => void };\n timer.unref?.();\n });\n async function writable(client: HostfsTransport, path: string, flags: OpenFlags) {\n const { ifMatch: _, ...asked } = flags;\n const opening = () =>\n client.call<{ fh: number; attr?: DriverAttr }>('open', { path: rel(path), ...asked });\n try {\n return { opened: await opening(), restore: undefined };\n } catch (err) {\n if (!flags.write || codeOf(err) !== 'EACCES') throw err;\n const was = await client.call<DriverAttr>('stat', { path: rel(path) });\n const mode = was.mode ?? 0;\n if (mode & 0o200) throw err;\n const restore = { path: rel(path), mode, was };\n const opened = await client\n .call('setattr', { path: rel(path), mode: mode | 0o200 })\n .then(opening)\n .catch(async (again: unknown) => {\n await settle(client, restore).catch(() => {});\n throw again;\n });\n return { opened, restore };\n }\n }\n const handlers: MediumHandlers = {\n getattr: async (path) => await call<DriverAttr>('stat', { path: rel(path) }),\n async readdir(path) {\n const { entries } = await call<{ entries: Array<{ name: string; attr: DriverAttr }> }>(\n 'list',\n { path: rel(path) }\n );\n return entries.map(({ name, attr }): DriverEntry => ({ name, kind: attr.kind, attr }));\n },\n async open(path: string, flags: OpenFlags) {\n const client = current();\n const token = client.token;\n const { opened, restore } = await writable(client, path, flags);\n if (flags.ifMatch !== undefined && opened.attr?.etag !== flags.ifMatch) {\n await client.call('release', { fh: opened.fh }, true);\n throw fsError('ESTALE', `${path} changed on the host while it was being read`);\n }\n handles.set(++nextFh, {\n client,\n token,\n fh: opened.fh,\n etag: flags.write ? undefined : opened.attr?.etag,\n restore,\n });\n return nextFh;\n },\n async read(fh, offset, size) {\n const remote = live(fh);\n return remote.client.read(\n remote.fh,\n offset,\n Math.min(size, remote.client.maxIo),\n remote.etag\n );\n },\n async write(fh, offset, bytes) {\n const remote = live(fh);\n const most = remote.client.maxIo;\n for (let at = 0; at < bytes.length; at += most) {\n await remote.client.write(remote.fh, offset + at, bytes.subarray(at, at + most));\n }\n },\n async release(fh) {\n const remote = handles.get(fh);\n if (!remote) throw fsError('EBADF', `handle ${fh}`);\n handles.delete(fh);\n try {\n await fresh(remote).client.call('release', { fh: remote.fh }, true);\n } finally {\n if (remote.restore) await settle(current(), remote.restore);\n }\n },\n mkdir: async (path) => void (await call('mkdir', { path: rel(path) })),\n rmdir: async (path) => void (await call('rmdir', { path: rel(path) })),\n unlink: async (path) => void (await call('unlink', { path: rel(path) })),\n rename: async (from, to) => void (await call('rename', { from: rel(from), to: rel(to) })),\n symlink: async (target, path) => void (await call('symlink', { target, path: rel(path) })),\n readlink: async (path) =>\n (await call<{ target: string }>('readlink', { path: rel(path) })).target,\n async setattr(path, { size, ...change }) {\n if (size !== undefined && !current().capabilities.ranges) await resize(handlers, path, size);\n else if (size !== undefined) change = { ...change, size } as typeof change;\n if (Object.keys(change).length > 0) await call('setattr', { path: rel(path), ...change });\n },\n statfs: () => call<DriverStatfs>('statfs'),\n };\n return handlers;\n}\n\nconst KEEP: OpenFlags = { write: false, create: false, truncate: false, exclusive: false };\n\nasync function resize(h: FilesystemHandlers, path: string, size: number): Promise<void> {\n const was = (await h.getattr(path)).size;\n if (size === was) return;\n const kept: Uint8Array[] = [];\n if (size < was && size > 0) {\n const fh = await h.open(path, KEEP);\n try {\n for (let at = 0; at < size; ) {\n const bytes = await h.read(fh, at, size - at);\n if (bytes.length === 0) break;\n kept.push(bytes);\n at += bytes.length;\n }\n } finally {\n await h.release(fh);\n }\n }\n const fh = await h.open(path, { ...KEEP, write: true, truncate: size < was });\n try {\n if (size > was) await h.write(fh, size - 1, new Uint8Array(1));\n let at = 0;\n for (const bytes of kept) {\n await h.write(fh, at, bytes);\n at += bytes.length;\n }\n } finally {\n await h.release(fh);\n }\n}\n\nexport interface WatchLoop {\n connect(): Promise<HostfsTransport>;\n up(client: HostfsTransport): void;\n event(event: HostfsEvent): void;\n down(): void;\n silenceMs?: number;\n backoffMs?: [number, number];\n connectMs?: number;\n}\n\nfunction sleep(ms: number, signal: AbortSignal): Promise<void> {\n return new Promise((resolve) => {\n const done = () => {\n clearTimeout(timer);\n signal.removeEventListener('abort', done);\n resolve();\n };\n const timer = setTimeout(done, ms);\n signal.addEventListener('abort', done);\n });\n}\n\nexport interface Watching {\n ready: Promise<void>;\n kick(): void;\n}\n\nexport function keepWatching(loop: WatchLoop, signal: AbortSignal): Watching {\n const silenceMs = loop.silenceMs ?? 45_000;\n const [first, most] = loop.backoffMs ?? [1000, 30_000];\n const ready = Promise.withResolvers<void>();\n const capped = setTimeout(ready.resolve, loop.connectMs ?? 15_000);\n const uncap = () => clearTimeout(capped);\n void ready.promise.then(uncap);\n signal.addEventListener('abort', uncap, { once: true });\n let wait = first;\n let up = false;\n let current: AbortController | undefined;\n async function session(): Promise<boolean> {\n const session = new AbortController();\n current = session;\n const stop = () => session.abort();\n signal.addEventListener('abort', stop);\n let timer: ReturnType<typeof setTimeout> | undefined;\n const quiet = () => {\n clearTimeout(timer);\n timer = setTimeout(stop, silenceMs);\n };\n let opened = false;\n try {\n const client = await loop.connect();\n quiet();\n await client.watch(\n session.signal,\n (event) => {\n quiet();\n if (!event.ping) loop.event(event);\n },\n () => {\n quiet();\n opened = true;\n up = true;\n loop.up(client);\n ready.resolve();\n }\n );\n return opened;\n } catch {\n return opened;\n } finally {\n clearTimeout(timer);\n signal.removeEventListener('abort', stop);\n }\n }\n void (async () => {\n while (!signal.aborted) {\n const began = Date.now();\n const opened = await session();\n if (signal.aborted) return;\n if (opened && Date.now() - began >= first) {\n wait = first;\n continue;\n }\n if (!opened && up) {\n up = false;\n loop.down();\n }\n ready.resolve();\n await sleep(wait, signal);\n wait = Math.min(wait * 2, most);\n }\n })();\n return { ready: ready.promise, kick: () => current?.abort() };\n}\n\nexport function invalidation(event: HostfsEvent): string[] | true {\n return event.paths ?? true;\n}\n\nexport interface HostfsTiming {\n silenceMs?: number;\n backoffMs?: [number, number];\n connectMs?: number;\n requestMs?: number;\n callMs?: number;\n beatMs?: number;\n deadMs?: number;\n}\n\nexport const PORT_REQUEST_MS = 60_000;\nexport const HOSTFS_CALL_MS = 20_000;\nexport const PORT_BEAT_MS = 1000;\nexport const PORT_DEAD_MS = 10_000;\nexport const PORT_LINGER_MS = 1000;\n\nexport interface PortLiveness {\n requestMs?: number;\n beatMs?: number;\n deadMs?: number;\n lingerMs?: number;\n}\n\nexport function timed(transport: HostfsTransport, ms: number): HostfsTransport {\n const inflight = new Set<Promise<unknown>>();\n const guard = <T>(\n name: string,\n run: () => Promise<T>,\n late?: (value: T) => void,\n expire?: (running: Promise<T>) => void\n ) =>\n new Promise<T>((resolve, reject) => {\n let expired = false;\n const running = run();\n inflight.add(running);\n const done = () => inflight.delete(running);\n running.then(done, done);\n const timer = setTimeout(() => {\n expired = true;\n const why = `the host folder did not answer ${name} within ${ms} ms`;\n transport.retire?.(why);\n expire?.(running);\n reject(fsError('ENOTCONN', why));\n }, ms);\n running.then(\n (value) => {\n clearTimeout(timer);\n if (expired) late?.(value);\n resolve(value);\n },\n (err) => {\n clearTimeout(timer);\n reject(err);\n }\n );\n });\n const cleanup = async (op: string, body: Record<string, unknown>, skip?: Promise<unknown>) => {\n await Promise.allSettled([...inflight].filter((work) => work !== skip));\n return await transport.cleanup?.(op, body);\n };\n const release = (opened: unknown) => {\n const fh = (opened as { fh?: unknown } | null)?.fh;\n if (typeof fh === 'number') void cleanup('release', { fh }).catch(() => {});\n };\n return {\n get capabilities() {\n return transport.capabilities;\n },\n get token() {\n return transport.token;\n },\n get maxIo() {\n return transport.maxIo;\n },\n get gone() {\n return transport.gone;\n },\n retire: (why) => transport.retire?.(why),\n ...(transport.cleanup ? { cleanup } : {}),\n call: (op, body, handle) =>\n guard(\n op,\n () => transport.call(op, body, handle),\n op === 'open' ? release : undefined,\n op === 'release'\n ? (running) => void cleanup('release', body ?? {}, running).catch(() => {})\n : undefined\n ),\n read: (fh, offset, size, ifMatch) =>\n guard('read', () => transport.read(fh, offset, size, ifMatch)),\n write: (fh, offset, bytes) => guard('write', () => transport.write(fh, offset, bytes)),\n watch: (signal, onEvent, onOpen) => transport.watch(signal, onEvent, onOpen),\n };\n}\nconst PORT_MS_PER_MIB = 1000;\n\nlet nextPortToken = 0;\n\ntype PortReply = {\n id: number;\n pong?: boolean;\n result?: unknown;\n bytes?: Uint8Array;\n event?: HostfsEvent;\n open?: boolean;\n end?: boolean;\n error?: { code?: string; message?: string };\n};\n\nexport class PortTransport implements HostfsTransport {\n readonly capabilities: DriverCapabilities;\n readonly token: string;\n private readonly port: MessagePort;\n private readonly requestMs: number;\n private readonly waiting = new Map<number, (reply: PortReply) => void>();\n private next = 0;\n private dead: string | undefined;\n private readonly beatMs: number;\n private readonly deadMs: number;\n private readonly lingerMs: number;\n private beat: ReturnType<typeof setInterval> | undefined;\n private answers = false;\n private pinged: number | undefined;\n\n constructor(grant: HostfsPortGrant, liveness: PortLiveness = {}) {\n this.port = grant.port;\n this.requestMs = liveness.requestMs ?? PORT_REQUEST_MS;\n this.beatMs = liveness.beatMs ?? PORT_BEAT_MS;\n this.deadMs = liveness.deadMs ?? PORT_DEAD_MS;\n this.lingerMs = liveness.lingerMs ?? PORT_LINGER_MS;\n this.capabilities = grant.capabilities ?? {};\n this.token = grant.token ?? `port-${++nextPortToken}`;\n this.port.addEventListener('message', (event: MessageEvent<PortReply>) => {\n if (event.data?.pong) {\n this.answers = true;\n this.pinged = undefined;\n } else this.waiting.get(event.data?.id)?.(event.data);\n });\n this.port.addEventListener('close', () => this.fail(\"the folder's port closed\"));\n this.port.start();\n }\n\n get maxIo(): number {\n return this.capabilities.maxIo ?? HOSTFS_IO;\n }\n\n get gone(): boolean {\n return this.dead !== undefined;\n }\n\n retire(why: string): void {\n this.fail(why);\n }\n\n private ping(): void {\n if (this.pinged !== undefined) return;\n this.pinged = Date.now();\n try {\n this.port.postMessage({ id: 0, op: 'ping' });\n } catch {}\n }\n\n private watchBeat(): void {\n if (this.beat || this.dead) return;\n this.ping();\n this.beat = setInterval(() => {\n if (this.waiting.size === 0) {\n clearInterval(this.beat);\n this.beat = undefined;\n return;\n }\n if (this.answers && this.pinged !== undefined && Date.now() - this.pinged > this.deadMs) {\n this.fail(\"the folder's port stopped answering\");\n return;\n }\n this.ping();\n }, this.beatMs);\n }\n\n async cleanup(op: string, body: Record<string, unknown>): Promise<void> {\n if (this.closed) throw fsError('ENOTCONN', \"the folder's port is closed\");\n this.port.postMessage({ id: 0, op: 'cleanup', name: op, body });\n }\n\n private closed = false;\n\n fail(why: string): void {\n if (this.dead === undefined) {\n setTimeout(() => {\n try {\n this.port.postMessage({ id: 0, op: 'bye' });\n } catch {}\n this.closed = true;\n this.port.close();\n }, this.lingerMs);\n }\n clearInterval(this.beat);\n this.beat = undefined;\n this.dead ??= why;\n for (const settle of [...this.waiting.values()])\n settle({ id: 0, error: { code: 'ENOTCONN', message: why } });\n }\n\n private ask(\n message: Record<string, unknown>,\n bytes = 0,\n transfer: Transferable[] = []\n ): Promise<PortReply> {\n const id = ++this.next;\n if (this.dead) return Promise.reject(fsError('ENOTCONN', this.dead));\n return new Promise((resolve, reject) => {\n const timer = setTimeout(\n () => {\n this.waiting.delete(id);\n reject(fsError('ETIMEDOUT', \"the folder's port did not answer\"));\n this.fail(\"the folder's port stopped answering\");\n },\n this.requestMs + Math.ceil(bytes / 1_048_576) * PORT_MS_PER_MIB\n );\n this.watchBeat();\n this.waiting.set(id, (reply) => {\n clearTimeout(timer);\n this.waiting.delete(id);\n if (reply.error) reject(fsError(reply.error.code ?? 'EIO', reply.error.message ?? ''));\n else resolve(reply);\n });\n try {\n this.port.postMessage({ id, ...message }, transfer);\n } catch (err) {\n this.fail(`the folder's port is closed: ${(err as Error).message}`);\n }\n });\n }\n\n async call<T>(op: string, body: Record<string, unknown> = {}): Promise<T> {\n return (await this.ask({ op: 'call', name: op, body })).result as T;\n }\n\n async read(fh: number, offset: number, size: number, ifMatch?: string): Promise<Uint8Array> {\n const reply = await this.ask(\n { op: 'read', fh, offset, size, ...(ifMatch ? { ifMatch } : {}) },\n size\n );\n return reply.bytes ?? new Uint8Array(0);\n }\n\n async write(fh: number, offset: number, bytes: Uint8Array): Promise<void> {\n await this.ask({ op: 'write', fh, offset, bytes }, bytes.length);\n }\n\n watch(\n signal: AbortSignal,\n onEvent: (event: HostfsEvent) => void,\n onOpen: () => void = () => undefined\n ): Promise<void> {\n const id = ++this.next;\n if (this.dead) return Promise.reject(fsError('ENOTCONN', this.dead));\n if (signal.aborted) {\n this.fail(\"the folder's watch ended\");\n return Promise.resolve();\n }\n return new Promise<void>((resolve, reject) => {\n const finish = () => {\n this.waiting.delete(id);\n signal.removeEventListener('abort', stop);\n };\n const stop = () => {\n finish();\n try {\n this.port.postMessage({ id, op: 'unwatch' });\n } catch {}\n resolve();\n };\n this.watchBeat();\n this.waiting.set(id, (reply) => {\n if (reply.open) return onOpen();\n if (reply.event) return onEvent(reply.event);\n finish();\n if (reply.error) reject(fsError(reply.error.code ?? 'ENOTCONN', reply.error.message ?? ''));\n else resolve();\n });\n signal.addEventListener('abort', stop, { once: true });\n try {\n this.port.postMessage({ id, op: 'watch' });\n } catch (err) {\n finish();\n reject(fsError('ENOTCONN', `the folder's port is closed: ${(err as Error).message}`));\n }\n }).finally(() => this.fail(\"the folder's watch ended\"));\n }\n}\n\nconst errorOf = (err: unknown) => ({\n code: typeof codeOf(err) === 'string' ? (codeOf(err) as string) : 'EIO',\n message: (err as Error | null)?.message ?? String(err),\n});\n\nexport function serveHostfsPort(port: MessagePort, transport: HostfsTransport): () => void {\n const watches = new Map<number, AbortController>();\n const handles = new Set<number>();\n let stopped = false;\n const closeHandles = () => {\n for (const fh of handles) void transport.call('release', { fh }, true).catch(() => {});\n handles.clear();\n };\n const send = (reply: PortReply, transfer: Transferable[] = []) =>\n port.postMessage(reply, transfer);\n const pending = new Set<Promise<unknown>>();\n const track = <T>(work: Promise<T>) => {\n pending.add(work);\n const done = () => pending.delete(work);\n work.then(done, done);\n return work;\n };\n const answer = async (name: string, body: Record<string, unknown>) => {\n const result = await track(transport.call(name, body));\n const opened = (result as { fh?: unknown } | null)?.fh;\n if (name === 'open' && typeof opened === 'number') handles.add(opened);\n if (name === 'release') handles.delete(body?.fh as number);\n if (stopped) closeHandles();\n return result;\n };\n const listener = async ({\n data,\n }: MessageEvent<Record<string, unknown> & { id: number; op: string }>) => {\n const { id, op } = data;\n if (op === 'ping') return send({ id, pong: true });\n if (op === 'bye') return stop();\n if (op === 'cleanup')\n return void Promise.allSettled([...pending])\n .then(() => answer(data.name as string, data.body as Record<string, unknown>))\n .catch(() => {});\n if (op === 'unwatch') return watches.get(id)?.abort();\n if (op === 'watch') {\n const stop = new AbortController();\n watches.set(id, stop);\n try {\n await transport.watch(\n stop.signal,\n (event) => send({ id, event }),\n () => send({ id, open: true })\n );\n send({ id, end: true });\n } catch (err) {\n send({ id, error: errorOf(err) });\n } finally {\n watches.delete(id);\n }\n return;\n }\n try {\n if (op === 'read') {\n const read = await track(\n transport.read(\n data.fh as number,\n data.offset as number,\n data.size as number,\n data.ifMatch as string | undefined\n )\n );\n const bytes = read.slice();\n return send({ id, bytes }, [bytes.buffer as ArrayBuffer]);\n }\n if (op === 'write') {\n await track(\n transport.write(data.fh as number, data.offset as number, data.bytes as Uint8Array)\n );\n return send({ id });\n }\n if (op !== 'call') throw fsError('EINVAL', `unknown hostfs port op ${op}`);\n send({ id, result: await answer(data.name as string, data.body as Record<string, unknown>) });\n } catch (err) {\n send({ id, error: errorOf(err) });\n }\n };\n const stop = () => {\n stopped = true;\n port.removeEventListener('message', listener as (event: MessageEvent) => void);\n port.removeEventListener('close', stop);\n for (const watch of watches.values()) watch.abort();\n closeHandles();\n port.close();\n };\n port.addEventListener('message', listener as (event: MessageEvent) => void);\n port.addEventListener('close', stop);\n port.start();\n return stop;\n}\n\nexport function grantConnect(\n hook: HostfsGrantHook,\n fetch: FetchLike,\n liveness: PortLiveness = {}\n): HostfsConnect {\n return async (source, options) => {\n const first = await hook(source, options);\n if ('port' in first) return new PortTransport(first, liveness);\n const grant = async () => {\n const again = await hook(source, options);\n if ('port' in again)\n throw fsError('ESTALE', 'the folder moved to a port, so its open files are gone');\n return again;\n };\n return new HostfsClient(first, grant, fetch);\n };\n}\n\nexport async function openHostfs(\n spec: MountSpec,\n connect: HostfsConnect,\n timing: HostfsTiming = {}\n): Promise<OpenedDriver> {\n const readonly = spec.options?.ro !== undefined;\n const { port1, port2 } = new MessageChannel();\n const slot = mediumSlot<HostfsTransport>(\n async (err) => unreachable(err),\n () => watching.kick()\n );\n const stop = new AbortController();\n let active: HostfsTransport | undefined;\n const handlers = hostfsHandlers(() => active as HostfsTransport);\n const ranged = () => ({\n ...(active?.capabilities.ranges === true ? { ranges: true } : {}),\n ...(active ? { maxIo: Math.min(active.maxIo, HOSTFS_IO) } : {}),\n });\n const served = serveFilesystem(\n port2,\n { ...slot.handlers, mount: ranged },\n {\n symlinks: true,\n chmod: true,\n listingStats: true,\n maxIo: HOSTFS_IO,\n ...(readonly ? { readonly: true } : {}),\n }\n );\n const watching = keepWatching(\n {\n connect: () => connect(spec.source, { readonly }),\n up(client) {\n active = timed(client, timing.callMs ?? HOSTFS_CALL_MS);\n slot.insert(client, handlers);\n served.invalidate(true);\n },\n event: (event) => served.invalidate(invalidation(event)),\n down() {\n slot.eject();\n served.invalidate(true);\n },\n ...timing,\n },\n stop.signal\n );\n await watching.ready;\n return {\n port: port1,\n present: slot.present,\n dispose() {\n stop.abort();\n port1.close();\n port2.close();\n },\n };\n}\n", "import { type CdpOpen, serveCdpPort } from './cdp/port.ts';\nimport type { CdpHook } from './cdp/types.ts';\nimport {\n type DialHandle,\n type DialledSocket,\n type DialOptions,\n dialStream,\n errorWithCode,\n} from './client/dial-stream.ts';\nimport { type LoopbackFetchOptions, loopbackFetch } from './client/loopback-fetch.ts';\nimport { clipboardAnswerer } from './clipboard-relay.ts';\nimport { embedderAnswerer } from './embedder-relay.ts';\nimport { type FacadeOpen, serveFacadePort } from './facade/port.ts';\nimport type { FacadeSpecs } from './facade/types.ts';\nimport type { Attestation, AttestOptions, AttestTombstone } from './fs/attest.ts';\nimport type { Denial, DenialHook } from './fs/dac.ts';\nimport { integrityOptions } from './fs/integrity.ts';\nimport { type Portable, portable } from './fs/portable.ts';\nimport { type Protection, protectInit } from './fs/protect.ts';\nimport { DEFAULT_USERS, type UsersMode } from './fs/types.ts';\nimport { integrityAnswerer } from './integrity-relay.ts';\nimport type { ClipboardHook } from './kernel/clipboard.ts';\nimport { type EmbedderHook, kindsOf } from './kernel/embedder.ts';\nimport { isHostname } from './kernel/net/loopback-names.ts';\nimport type { TransportCall } from './kernel/net/remote-transport.ts';\nimport type { RouteTable } from './kernel/net/routes.ts';\nimport { type SealedOption, sealedHooks } from './kernel/net/sealed-fetch.ts';\nimport {\n carriesUdp,\n type NetworkUplink,\n serveUplink,\n type UplinkCall,\n} from './kernel/net/uplink.ts';\nimport { quiet, signalField } from './kernel/signals.ts';\nimport type { PendingMedium } from './launcher.ts';\nimport type { MediumHandle } from './mount/fsa.ts';\nimport type { HostfsGrantHook } from './mount/hostfs.ts';\nimport type { MountEntry, MountSpec } from './mount/mount-fs.ts';\nimport type { ProcessMountPolicy, ProcessMountRequest } from './mount/syscall.ts';\nimport { sealedAnswerer } from './sealed-relay.ts';\nimport type { FileChanged, InitRequest, KernelCall, TerminalAction } from './serve.ts';\nimport type { ApproveHook, SudoRequest } from './sudo.ts';\nimport { systemTimeZone } from './time-zone.ts';\nimport { type NetworkTransport, serveTransport } from './transport.ts';\nimport type { Account, AddGroup, AddUser, Group, RemoveUser } from './users.ts';\n\nexport type { CdpConnection, CdpHook, CdpRequest } from './cdp/types.ts';\nexport {\n type AttachOptions,\n attachKernel,\n type ClientEnded,\n type ClientFetchRequest,\n type ClientFs,\n type ClientRunOptions,\n type ClientRunResult,\n type ClientTerminal,\n type ClientTerminalOptions,\n KernelCallError,\n type KernelClient,\n KernelGoneError,\n type ProcessEntry,\n type SpawnedProcess,\n type SpawnOptions,\n type WatchChange,\n} from './client/attach.ts';\nexport type { DialledSocket, DialOptions } from './client/dial-stream.ts';\nexport type { LoopbackFetchOptions } from './client/loopback-fetch.ts';\nexport type {\n FacadeConnection,\n FacadeHook,\n FacadeInfo,\n FacadeSpec,\n FacadeSpecs,\n} from './facade/types.ts';\nexport type { Attestation, AttestedDir, AttestOptions, AttestTombstone } from './fs/attest.ts';\nexport type { Denial, DenialHook } from './fs/dac.ts';\nexport type { ClipboardHook, ClipboardStamp } from './kernel/clipboard.ts';\nexport type {\n EmbedderHook,\n EmbedderKindPolicy,\n EmbedderReply,\n EmbedderRequest,\n EmbedderStamp,\n} from './kernel/embedder.ts';\nexport type { RouteTable } from './kernel/net/routes.ts';\nexport {\n SEALED_FETCH_VERSION,\n type SealedFetchHook,\n type SealedFetchRequest,\n type SealedOption,\n} from './kernel/net/sealed-fetch.ts';\nexport type {\n NetworkUplink,\n ResolveAnswer,\n ResolveFamily,\n UplinkTraits,\n} from './kernel/net/uplink.ts';\nexport type {\n SealedAbortReason,\n SealedCaller,\n SealedHook,\n SealedRequest,\n SealedRequester,\n} from './kernel/sealed.ts';\nexport type { ConnectorStamp } from './kernel/socket.ts';\nexport type {\n HostfsEvent,\n HostfsGrant,\n HostfsGrantHook,\n HostfsPortGrant,\n HostfsTransport,\n} from './mount/hostfs.ts';\nexport { serveHostfsPort } from './mount/hostfs.ts';\nexport type { MountEntry, MountSpec } from './mount/mount-fs.ts';\nexport type { ProcessMountPolicy, ProcessMountRequest } from './mount/syscall.ts';\nexport type { JsChild, JsExited, JsSpawnOptions, JsStdio } from './process/js/js-children.ts';\nexport type {\n JsCrontabAnswer,\n JsCrontabCall,\n JsFdStatus,\n JsFdType,\n JsFile,\n JsOpenOptions,\n JsProgramContext,\n JsSelected,\n JsSelectSets,\n JsSignal,\n JsSudoAnswer,\n JsVisudoAnswer,\n JsVisudoCall,\n JsWriteOptions,\n} from './process/js/js-context.ts';\nexport type { JsStatFs } from './process/js/js-io.ts';\nexport type {\n JsAddress,\n JsConnection,\n JsConnectOptions,\n JsListener,\n JsListenOptions,\n JsNet,\n JsResolveOptions,\n JsTlsChoice,\n JsTlsCipher,\n JsTlsContext,\n JsTlsContextOptions,\n JsTlsOffer,\n JsTlsOptions,\n JsTlsSelect,\n JsTlsServerSession,\n JsTlsSession,\n} from './process/js/js-net.ts';\nexport type { JsRunOptions, JsRunResult, JsRunStdio } from './process/js/js-run.ts';\nexport type { JsCred, JsSyncContext, JsSyncFile } from './process/js/js-sync.ts';\nexport type { JsThread, JsThreadContext, JsThreadSpawnOptions } from './process/js/js-thread.ts';\nexport type { JsTermios, JsTty, JsTtySize } from './process/js/js-tty.ts';\nexport type {\n JsWebSocket,\n JsWebSocketClose,\n JsWebSocketMessage,\n JsWebSocketOptions,\n} from './process/js/js-websocket.ts';\nexport type { ApproveHook, SudoAnswer, SudoDenial, SudoRequest, SudoStdin } from './sudo.ts';\nexport {\n type FetchTransportOptions,\n fetchTransport,\n type HeaderList,\n type NetworkExit,\n type NetworkRedirectPolicy,\n type NetworkRequest,\n type NetworkResponse,\n type NetworkTraits,\n type NetworkTransport,\n type NetworkWebSocket,\n type NetworkWebSocketRequest,\n} from './transport.ts';\nexport type { Account, AddGroup, AddUser, Group, RemoveUser } from './users.ts';\n\nexport interface NetworkOptions {\n transport?: NetworkTransport;\n uplink?: NetworkUplink;\n doh?: string | false;\n}\n\nexport interface KernelOptions {\n root?: FileSystemDirectoryHandle;\n modules?: string;\n commands?: { append?: readonly string[] };\n env?: Record<string, string>;\n metadata?: string | false;\n media?: string | false;\n ca?: string | false;\n worker?: string | URL;\n network?: NetworkOptions;\n requestDirectory?: () => Promise<FileSystemDirectoryHandle>;\n onMountPending?: (pending: MountPending) => void;\n hostfs?: HostfsGrantHook;\n processMounts?: ProcessMountPolicy;\n cdp?: CdpHook;\n facades?: FacadeSpecs;\n hostname?: string;\n timeZone?: string;\n users?: UsersMode;\n onDenial?: DenialHook;\n sealed?: SealedOption;\n clipboard?: ClipboardHook;\n requests?: EmbedderHook;\n approve?: ApproveHook;\n protect?: Protection;\n}\n\ninterface HostfsRequest {\n id: number;\n source: string;\n readonly: boolean;\n}\n\nexport interface MountPending {\n target: string;\n source: string;\n insert(): Promise<void>;\n}\n\nexport interface RunOptions {\n cwd?: string;\n user?: string | number;\n tag?: string;\n env?: Record<string, string>;\n stdin?: string | Uint8Array;\n onStdout?: (text: string) => void;\n onStderr?: (text: string) => void;\n}\n\nexport interface RunResult {\n status: number;\n signal?: string;\n stdout: string;\n stderr: string;\n}\n\nexport interface ConnectOptions {\n user?: string | number;\n tag?: string;\n requests?: EmbedderHook | 'attach';\n}\n\nexport interface KernelGroups {\n list(): Promise<Group[]>;\n add(name: string, options: AddGroup): Promise<Group>;\n addMember(group: string, user: string): Promise<Group>;\n removeMember(group: string, user: string): Promise<Group>;\n}\n\nexport interface KernelUsers {\n readonly mode: UsersMode;\n add(user: AddUser): Promise<Account>;\n remove(name: string, options?: RemoveUser): Promise<boolean>;\n list(): Promise<Account[]>;\n}\n\nexport interface KernelIntegrity {\n revoke(path?: string): Promise<void>;\n}\n\nexport interface KernelSealed {\n setPlaceholders(list: readonly string[]): Promise<void>;\n}\n\nexport interface Kernel {\n run(argv: string[], options?: RunOptions): Promise<RunResult>;\n openTerminal(argv: string[], options?: TerminalOptions): Promise<Terminal>;\n connect(options?: ConnectOptions): Promise<MessagePort>;\n readonly users: KernelUsers;\n readonly groups: KernelGroups;\n setRoutes(routes: RouteTable): Promise<void>;\n chmod(path: string, mode: number): Promise<void>;\n readonly integrity: KernelIntegrity;\n readonly sealed: KernelSealed;\n updateTransportTraits(): Promise<boolean>;\n dial(options: DialOptions): Promise<DialledSocket>;\n loopbackFetch(input: RequestInfo | URL, options: LoopbackFetchOptions): Promise<Response>;\n mount(spec: MountSpec): Promise<MountEntry>;\n umount(target: string): Promise<void>;\n mounts(): Promise<MountEntry[]>;\n insert(target: string, handle: FileSystemDirectoryHandle): Promise<void>;\n attest(path: string): Promise<Attestation>;\n attest(path: string, options: { absent: 'allow' }): Promise<Attestation | AttestTombstone>;\n watch(paths: string[], onChange: (path: string) => void): Promise<() => void>;\n terminate(): void;\n}\n\nexport interface TerminalOptions {\n cwd?: string;\n user?: string | number;\n tag?: string;\n env?: Record<string, string>;\n cols?: number;\n rows?: number;\n onData?: (bytes: Uint8Array) => void;\n}\n\nexport type TerminalSignal =\n | 'SIGINT'\n | 'SIGTSTP'\n | 'SIGQUIT'\n | 'SIGHUP'\n | 'SIGTERM'\n | 'SIGKILL'\n | 'SIGCONT';\n\nexport interface Ended {\n status: number;\n signal?: string;\n}\n\nexport interface Terminal {\n readonly pid: number;\n readonly exited: Promise<number>;\n readonly ended: Promise<Ended>;\n onData: ((bytes: Uint8Array) => void) | null;\n write(data: string | Uint8Array): void;\n resize(cols: number, rows: number): void;\n signal(name: TerminalSignal): void;\n close(): void;\n}\n\ninterface Reply {\n id: number;\n result?: unknown;\n error?: string;\n code?: string;\n fd?: 1 | 2;\n bytes?: Uint8Array;\n started?: number;\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\ninterface Handlers {\n output?: Pending['output'];\n started?: Pending['started'];\n}\n\nconst ISOLATION =\n 'slicc-kernel needs a cross-origin isolated page (Cross-Origin-Opener-Policy: same-origin and Cross-Origin-Embedder-Policy: require-corp or credentialless)';\n\nfunction streamer(callback: ((text: string) => void) | undefined) {\n const decoder = new TextDecoder();\n return (bytes: Uint8Array) => callback?.(decoder.decode(bytes, { stream: true }));\n}\n\nfunction dialer(call: (req: KernelCall) => Promise<unknown>) {\n const open = new Set<DialHandle>();\n const dial = async ({ port, host }: DialOptions): Promise<DialledSocket> => {\n let reply: unknown;\n try {\n reply = await call({ op: 'dial', port, ...(host ? { host } : {}) });\n } catch (err) {\n throw errorWithCode((err as Error).message);\n }\n const handle = dialStream(reply as MessagePort, () => open.delete(handle));\n open.add(handle);\n return handle;\n };\n const reset = () => {\n for (const handle of [...open]) handle.fail(errorWithCode('ECONNRESET: the kernel is gone'));\n };\n return { dial, reset };\n}\n\nfunction uplinkInit(uplink: NetworkUplink | undefined): Pick<InitRequest, 'uplink'> {\n if (!uplink) return {};\n const traits = { tcp: true, udp: carriesUdp(uplink), ipv6: uplink.traits.ipv6 === true } as const;\n const nameserver = typeof uplink.nameserver === 'string' ? { nameserver: uplink.nameserver } : {};\n return { uplink: { traits, ...(uplink.routes ? { routes: uplink.routes } : {}), ...nameserver } };\n}\n\nfunction rootField(\n at: Portable<FileSystemDirectoryHandle>\n): Pick<InitRequest, 'root' | 'rootPath'> {\n return 'path' in at ? { rootPath: at.path } : { root: at.handle };\n}\n\nasync function insertCall(\n target: string,\n handle: FileSystemDirectoryHandle,\n source?: string\n): Promise<KernelCall> {\n return { op: 'insert', target, source, ...(await portable(handle)) };\n}\n\nasync function initCall(\n options: KernelOptions,\n transport: NetworkTransport | undefined\n): Promise<KernelCall> {\n const hooks = sealedHooks(options.sealed);\n return {\n op: 'init',\n ...(options.root ? rootField(await portable(options.root)) : {}),\n ...(options.modules ? { modules: options.modules } : {}),\n ...(options.commands ? { commands: options.commands } : {}),\n ...(options.env ? { env: options.env } : {}),\n ...(options.metadata !== undefined ? { metadata: options.metadata } : {}),\n ...(options.media !== undefined ? { media: options.media } : {}),\n ...(options.ca !== undefined ? { ca: options.ca } : {}),\n ...(transport ? { transport: transport.traits } : {}),\n ...uplinkInit(options.network?.uplink),\n ...(options.network?.doh !== undefined ? { doh: options.network.doh } : {}),\n ...(options.hostfs ? { hostfs: true } : {}),\n ...(options.cdp ? { cdp: true } : {}),\n ...facadesInit(options.facades),\n ...(options.hostname !== undefined ? { hostname: options.hostname } : {}),\n ...(options.timeZone !== undefined ? { timeZone: options.timeZone } : {}),\n users: options.users === undefined ? DEFAULT_USERS : options.users,\n ...(options.onDenial ? { denials: true } : {}),\n ...(hooks.request ? { sealed: true } : {}),\n ...(hooks.fetch ? { sealedFetch: true } : {}),\n ...(options.clipboard ? { clipboard: true } : {}),\n ...(options.requests ? { requests: kindsOf(options.requests) } : {}),\n ...(options.approve ? { approve: true } : {}),\n ...(options.protect ? { protect: protectInit(options.protect) } : {}),\n ...(options.processMounts !== undefined\n ? {\n processMounts:\n typeof options.processMounts === 'function' ? 'ask' : options.processMounts,\n }\n : {}),\n };\n}\n\ninterface PageHosts {\n cdp: { open(data: CdpOpen): void };\n facades: { open(data: FacadeOpen): void };\n policy(data: { id: number; req: ProcessMountRequest }): Promise<void>;\n medium(medium: PendingMedium): void;\n hostfs(req: HostfsRequest): Promise<void>;\n}\n\nfunction hostedMessage(data: WorkerMessage, on: PageHosts): data is Exclude<WorkerMessage, Reply> {\n if ('cdpOpen' in data) on.cdp.open(data);\n else if ('facadeOpen' in data) on.facades.open(data);\n else if ('mountPolicy' in data) void on.policy(data.mountPolicy);\n else if ('medium' in data) on.medium(data.medium);\n else if ('hostfs' in data) void on.hostfs(data.hostfs);\n else return false;\n return true;\n}\n\nfunction facadesInit(specs: FacadeSpecs | undefined) {\n if (!specs) return {};\n const facades: Record<string, { port: number; hook?: boolean }> = {};\n for (const [name, spec] of Object.entries(specs)) {\n if (spec?.hook !== undefined && typeof spec.hook !== 'function') {\n throw new TypeError(`facades.${name}: hook must be a function`);\n }\n facades[name] = { port: spec?.port, ...(spec?.hook ? { hook: true } : {}) };\n }\n return { facades };\n}\n\nfunction facadeBridge(specs: FacadeSpecs | undefined) {\n const open = new Set<() => void>();\n let closed = false;\n return {\n open({ facadeOpen, port }: FacadeOpen): void {\n const hook = specs?.[facadeOpen.name]?.hook;\n if (!hook || closed) {\n port.postMessage({ error: 'no facade host' });\n port.close();\n return;\n }\n const close = serveFacadePort(port, hook, facadeOpen, () => open.delete(close));\n open.add(close);\n },\n close(): void {\n closed = true;\n for (const close of [...open]) close();\n },\n };\n}\n\nfunction cdpBridge(hook: CdpHook | undefined) {\n const open = new Set<() => void>();\n let closed = false;\n return {\n open({ cdpOpen, port }: CdpOpen): void {\n if (!hook || closed) {\n port.close();\n return;\n }\n const close = serveCdpPort(port, hook, cdpOpen, () => open.delete(close));\n open.add(close);\n },\n close(): void {\n closed = true;\n for (const close of [...open]) close();\n },\n };\n}\n\nfunction failed(message: string, code: string | undefined): Error {\n return Object.assign(new Error(message), code === undefined ? {} : { code });\n}\n\nfunction kernelGroups(call: (req: KernelCall) => Promise<unknown>): KernelGroups {\n const member =\n (op: 'groups-add-member' | 'groups-remove-member') => async (group: string, user: string) =>\n (await call({ op, group, user })) as Group;\n return {\n list: async () => (await call({ op: 'groups-list' })) as Group[],\n add: async (name: string, options: AddGroup) =>\n (await call({ op: 'groups-add', name, gid: options?.gid })) as Group,\n addMember: member('groups-add-member'),\n removeMember: member('groups-remove-member'),\n };\n}\n\nfunction accounts(\n call: (req: KernelCall) => Promise<unknown>,\n mode: UsersMode | undefined\n): { users: KernelUsers; groups: KernelGroups } {\n return { users: kernelUsers(call, mode), groups: kernelGroups(call) };\n}\n\nfunction kernelUsers(\n call: (req: KernelCall) => Promise<unknown>,\n mode: UsersMode = DEFAULT_USERS\n): KernelUsers {\n return {\n mode,\n add: async (user) => (await call({ op: 'users-add', user })) as Account,\n remove: async (name, options) =>\n (await call({ op: 'users-remove', name, ...(options ? { options } : {}) })) as boolean,\n list: async () => (await call({ op: 'users-list' })) as Account[],\n };\n}\n\nasync function mountPolicy(\n options: KernelOptions,\n worker: Worker,\n { id, req }: { id: number; req: ProcessMountRequest }\n): Promise<void> {\n const decide = options.processMounts;\n let allowed = false;\n try {\n allowed = typeof decide === 'function' ? await decide(req) : decide !== false;\n } catch {}\n worker.postMessage({ mountAllowed: { id, allowed } });\n}\n\ntype SudoMessage = { sudoAsk: SudoRequest } | { sudoAbort: { id: string; reason: string } };\n\ntype WorkerMessage =\n | Reply\n | TransportCall\n | UplinkCall\n | { medium: PendingMedium }\n | { hostfs: HostfsRequest }\n | { mountPolicy: { id: number; req: ProcessMountRequest } }\n | CdpOpen\n | FacadeOpen\n | { denial: Denial }\n | FileChanged\n | SudoMessage;\n\ntype Requester = (req: KernelCall) => { id: number; done: Promise<unknown> };\n\nfunction fileWatches(request: Requester, call: (req: KernelCall) => Promise<unknown>) {\n const watching = new Map<number, (path: string) => void>();\n return {\n event(data: WorkerMessage): data is FileChanged {\n if (!('fileChanged' in data)) return false;\n watching.get(data.fileChanged.watch)?.(data.fileChanged.path);\n return true;\n },\n async watch(paths: string[], onChange: (path: string) => void): Promise<() => void> {\n const { id, done } = request({ op: 'watch-files', paths });\n watching.set(id, onChange);\n await done.catch((err: unknown) => {\n watching.delete(id);\n throw err;\n });\n return () => {\n if (!watching.delete(id)) return;\n void call({ op: 'unwatch-files', watch: id }).catch(() => undefined);\n };\n },\n };\n}\n\nfunction relayable(answer: unknown): unknown {\n if (typeof answer === 'symbol' || typeof answer === 'function') return 'deny';\n if (typeof answer !== 'object' || answer === null) return answer;\n try {\n const { answer: kind, message } = answer as { answer?: unknown; message?: unknown };\n return kind === 'deny' && typeof message === 'string' ? { answer: kind, message } : 'deny';\n } catch {\n return 'deny';\n }\n}\n\nfunction approver(approve: ApproveHook | undefined, worker: Worker) {\n const asked = new Map<string, AbortController>();\n const handlers = {\n handle(data: WorkerMessage): data is SudoMessage {\n if ('sudoAsk' in data) void handlers.ask(data.sudoAsk);\n else if ('sudoAbort' in data) handlers.abort(data.sudoAbort);\n else return false;\n return true;\n },\n async ask(req: SudoRequest): Promise<void> {\n const control = new AbortController();\n asked.set(req.id, control);\n let answer: unknown = 'deny';\n try {\n answer = await approve?.(req, { signal: control.signal });\n } catch {}\n asked.delete(req.id);\n if (control.signal.aborted) return;\n worker.postMessage({ sudoAnswer: { id: req.id, answer: relayable(answer) } });\n },\n abort({ id, reason }: { id: string; reason: string }): void {\n asked.get(id)?.abort(reason);\n asked.delete(id);\n },\n close(): void {\n for (const control of asked.values()) control.abort('withdrawn');\n asked.clear();\n },\n };\n return handlers;\n}\n\nfunction checkOptions(options: KernelOptions): void {\n if (!globalThis.crossOriginIsolated) throw new Error(ISOLATION);\n if (options.hostname !== undefined && !isHostname(options.hostname)) {\n throw new Error(`not a host name: ${String(options.hostname)}`);\n }\n if (options.timeZone !== undefined) systemTimeZone(options.timeZone);\n if (options.protect) protectInit(options.protect);\n integrityOptions(options.protect?.integrity);\n facadesInit(options.facades);\n sealedHooks(options.sealed);\n}\n\nfunction connector(\n call: (req: KernelCall) => Promise<unknown>,\n bound: Map<number, EmbedderHook>\n): (options?: ConnectOptions) => Promise<MessagePort> {\n return async (connectOptions = {}) => {\n const { requests, ...rest } = connectOptions;\n if (requests === undefined || requests === 'attach')\n return (await call({\n op: 'connect',\n ...rest,\n ...(requests ? { requests } : {}),\n })) as MessagePort;\n const made = (await call({ op: 'connect', ...rest, requests: kindsOf(requests) })) as {\n port: MessagePort;\n client: number;\n };\n bound.set(made.client, requests);\n return made.port;\n };\n}\n\nfunction hookRelays(\n worker: Worker,\n options: KernelOptions,\n bound: Map<number, EmbedderHook>\n): { handle(data: unknown): boolean; close(): void } {\n const hooks = sealedHooks(options.sealed);\n const sealed = sealedAnswerer(worker, hooks.request, hooks.fetch);\n const clipboard = clipboardAnswerer(worker, options.clipboard);\n const integrity = integrityAnswerer(worker, options.protect?.integrity?.lookup);\n const requests = embedderAnswerer(worker, (client) =>\n client === 0 ? options.requests : bound.get(client)\n );\n return {\n handle: (data) =>\n sealed.handle(data) || clipboard.handle(data) || requests.handle(data) || integrity(data),\n close: () => sealed.close(),\n };\n}\n\ninterface RawRun {\n status: number;\n signal?: number;\n stdout: Uint8Array;\n stderr: Uint8Array;\n}\n\nfunction decodedRun(result: RawRun): RunResult {\n const decoder = new TextDecoder();\n return {\n status: result.status,\n ...signalField(result.signal),\n stdout: decoder.decode(result.stdout),\n stderr: decoder.decode(result.stderr),\n };\n}\n\nfunction endedOf(r: unknown): Ended {\n if (typeof r === 'number') return { status: r };\n const { status, signal } = r as { status: number; signal?: number };\n return { status, ...signalField(signal) };\n}\n\nfunction uplinkServer(\n worker: Worker,\n uplink: NetworkUplink | undefined\n): ReturnType<typeof serveUplink> | undefined {\n return uplink ? serveUplink(worker, uplink) : undefined;\n}\n\nfunction traitsUpdater(\n transport: NetworkTransport | undefined,\n call: (req: KernelCall) => Promise<unknown>\n): () => Promise<boolean> {\n return async () => {\n const traits = transport ? { traits: { ...transport.traits } } : {};\n return (await call({ op: 'transport-traits', ...traits })) === true;\n };\n}\n\nfunction transportBridge(\n worker: Worker,\n transport: NetworkTransport | undefined\n): ReturnType<typeof serveTransport> | undefined {\n return transport ? serveTransport(worker, transport, { attributed: true }) : undefined;\n}\n\nfunction pageOnly(call: (req: KernelCall) => Promise<unknown>): Pick<Kernel, 'attest' | 'sealed'> {\n return {\n sealed: {\n setPlaceholders: async (list) => void (await call({ op: 'sealed-placeholders', list })),\n },\n attest: ((path: string, options?: AttestOptions) =>\n call({ op: 'attest', path, ...(options ? { options } : {}) })) as Kernel['attest'],\n };\n}\n\nexport async function createKernel(options: KernelOptions = {}): Promise<Kernel> {\n checkOptions(options);\n const url = options.worker ?? new URL('./kernel-worker.js', import.meta.url);\n const worker = new Worker(url, { type: 'module', name: 'slicc-kernel' });\n const pending = new Map<number, Pending>();\n let nextId = 0;\n let failure: Error | undefined;\n\n const dials = dialer((req) => call(req));\n const files = fileWatches(\n (req) => request(req),\n (req) => call(req)\n );\n const cdp = cdpBridge(options.cdp);\n const facades = facadeBridge(options.facades);\n const bound = new Map<number, EmbedderHook>();\n const sealed = hookRelays(worker, options, bound);\n const approvals = approver(options.approve, worker);\n const fail = (error: Error) => {\n dials.reset();\n cdp.close();\n facades.close();\n sealed.close();\n approvals.close();\n failure = error;\n bridge?.close();\n uplinks?.close();\n for (const call of pending.values()) call.reject(error);\n pending.clear();\n };\n const transport = options.network?.transport;\n const bridge = transportBridge(worker, transport);\n const uplinks = uplinkServer(worker, options.network?.uplink);\n async function chosen(handle: MediumHandle | undefined): Promise<FileSystemDirectoryHandle> {\n if (handle) {\n const state = await handle.requestPermission?.({ mode: 'readwrite' });\n if (state === undefined || state === 'granted') return handle;\n throw new Error('permission for the folder was not granted');\n }\n if (!options.requestDirectory) throw new Error('this page cannot ask for a folder');\n return options.requestDirectory();\n }\n async function grantHostfs({ id, source, readonly }: HostfsRequest): Promise<void> {\n try {\n if (!options.hostfs) throw new Error('this page gives no host folders');\n const grant = await options.hostfs(source, { readonly });\n worker.postMessage({ hostfsGrant: { id, grant } }, 'port' in grant ? [grant.port] : []);\n } catch (err) {\n worker.postMessage({ hostfsGrant: { id, error: (err as Error).message ?? String(err) } });\n }\n }\n const policy = (asked: { id: number; req: ProcessMountRequest }) =>\n mountPolicy(options, worker, asked);\n const pendingMedium = ({ target, source, handle }: PendingMedium) =>\n options.onMountPending?.({\n target,\n source,\n insert: async () => void (await call(await insertCall(target, await chosen(handle), source))),\n });\n const aside = (data: WorkerMessage): data is { denial: Denial } | FileChanged => {\n if (files.event(data)) return true;\n if (!('denial' in data)) return sealed.handle(data);\n options.onDenial?.(data.denial);\n return true;\n };\n const hosts = { cdp, facades, policy, medium: pendingMedium, hostfs: grantHostfs };\n worker.addEventListener('message', ({ data }: MessageEvent<WorkerMessage>) => {\n if (aside(data)) return;\n if (approvals.handle(data)) return;\n if ('net' in data) return bridge?.answer(data);\n if ('uplink' in data) return uplinks?.answer(data);\n if (hostedMessage(data, hosts)) return;\n const call = pending.get(data.id);\n if (!call) return;\n if (data.fd !== undefined) return call.output?.(data.fd, data.bytes as Uint8Array);\n if (data.started !== undefined) return call.started?.(data.started);\n pending.delete(data.id);\n if (data.error !== undefined) call.reject(failed(data.error, data.code));\n else call.resolve(data.result);\n });\n worker.addEventListener('error', (event) => {\n event.preventDefault();\n fail(new Error(`slicc-kernel worker failed: ${event.message}`));\n });\n\n function request(\n req: KernelCall,\n handlers: Handlers = {}\n ): { id: number; done: Promise<unknown> } {\n const id = ++nextId;\n if (failure) return { id, done: Promise.reject(failure) };\n const done = new Promise((resolve, reject) => {\n pending.set(id, { resolve, reject, ...handlers });\n worker.postMessage({ ...req, id });\n });\n return { id, done };\n }\n\n const call = (req: KernelCall, handlers?: Handlers) => request(req, handlers).done;\n\n async function openTerminal(argv: string[], opts: TerminalOptions = {}): Promise<Terminal> {\n const { onData, ...options } = opts;\n let listener = onData ?? null;\n const backlog: Uint8Array[] = [];\n const started = Promise.withResolvers<number>();\n const { id, done } = 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 call({ op: 'terminal', terminal: id, ...action }).catch(() => undefined);\n return {\n pid,\n exited: quiet(done.then((r) => endedOf(r).status)),\n ended: quiet(done.then(endedOf)),\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) =>\n send({\n action: 'write',\n bytes: typeof data === 'string' ? new TextEncoder().encode(data) : data,\n }),\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\n const { dial } = dials;\n\n await call(await initCall(options, transport));\n\n return {\n async run(argv, runOptions = {}) {\n const { onStdout, onStderr, stdin, ...rest } = runOptions;\n const streams = { 1: streamer(onStdout), 2: streamer(onStderr) };\n const input = typeof stdin === 'string' ? new TextEncoder().encode(stdin) : stdin;\n const result = (await call(\n { op: 'run', argv, options: { ...rest, ...(input ? { stdin: input } : {}) } },\n { output: (fd, bytes) => streams[fd](bytes) }\n )) as RawRun;\n return decodedRun(result);\n },\n openTerminal,\n connect: connector(call, bound),\n ...accounts(call, options.users === undefined ? DEFAULT_USERS : options.users),\n setRoutes: async (routes) => void (await call({ op: 'routes', routes })),\n chmod: async (path, mode) => void (await call({ op: 'chmod', path, mode })),\n integrity: {\n revoke: async (path) =>\n void (await call({ op: 'integrity-revoke', ...(path !== undefined ? { path } : {}) })),\n },\n updateTransportTraits: traitsUpdater(transport, call),\n dial,\n loopbackFetch: (input, fetchOptions) => loopbackFetch(dial, input, fetchOptions),\n mount: async (spec) => (await call({ op: 'mount', spec })) as MountEntry,\n umount: async (target) => void (await call({ op: 'umount', target })),\n mounts: async () => (await call({ op: 'mounts' })) as MountEntry[],\n insert: async (target, handle) => void (await call(await insertCall(target, handle))),\n ...pageOnly(call),\n watch: files.watch,\n terminate() {\n fail(new Error('slicc-kernel terminated'));\n worker.terminate();\n },\n };\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["fail", "chunks", "encoder", "fresh", "fresh", "failure", "headers", "encoder", "bytesOf", "chunks", "failure", "done", "refused", "options", "fsError", "errorOf", "stop", "fsError", "decoder", "endedOf", "failure", "call", "options"]
|
|
7
7
|
}
|