@ai-ecoverse/slicc-kernel 1.182.0 → 1.183.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.
Files changed (37) hide show
  1. package/README.md +54 -5
  2. package/dist/driver-worker.js +290 -90
  3. package/dist/driver-worker.js.map +4 -4
  4. package/dist/index.js +328 -102
  5. package/dist/index.js.map +4 -4
  6. package/dist/kernel-worker.js +1705 -695
  7. package/dist/kernel-worker.js.map +4 -4
  8. package/dist/node-driver-worker.js +298 -98
  9. package/dist/node-driver-worker.js.map +4 -4
  10. package/dist/node-process-worker.cjs +849 -193
  11. package/dist/node-process-worker.cjs.map +4 -4
  12. package/dist/node-process-worker.js +849 -193
  13. package/dist/node-process-worker.js.map +4 -4
  14. package/dist/node.js +1875 -743
  15. package/dist/node.js.map +4 -4
  16. package/dist/process-worker.js +805 -149
  17. package/dist/process-worker.js.map +4 -4
  18. package/dist/types/client/attach.d.ts +2 -0
  19. package/dist/types/client/protocol.d.ts +1 -0
  20. package/dist/types/client/serve-client.d.ts +1 -0
  21. package/dist/types/devices-relay.d.ts +74 -0
  22. package/dist/types/index.d.ts +14 -0
  23. package/dist/types/kernel/devices.d.ts +155 -0
  24. package/dist/types/kernel/embedder.d.ts +2 -0
  25. package/dist/types/kernel/fd-table.d.ts +3 -1
  26. package/dist/types/kernel/host.d.ts +2 -0
  27. package/dist/types/kernel/process.d.ts +20 -0
  28. package/dist/types/kernel/serial-ioctl.d.ts +73 -0
  29. package/dist/types/launcher.d.ts +4 -0
  30. package/dist/types/node.d.ts +6 -2
  31. package/dist/types/process/js/js-dev.d.ts +24 -0
  32. package/dist/types/process/kernel-streams.d.ts +11 -1
  33. package/dist/types/process/process-pty.d.ts +1 -0
  34. package/dist/types/process/wasi/wasi-fds.d.ts +1 -0
  35. package/dist/types/process/wasi/wasi-termios.d.ts +1 -0
  36. package/dist/types/serve.d.ts +14 -1
  37. package/package.json +2 -2
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
- "sources": ["../src/cdp/port.ts", "../src/embedder-relay.ts", "../src/facade/port.ts", "../src/kernel/pipe.ts", "../src/kernel/embedder.ts", "../src/kernel/net/transport.ts", "../src/kernel/net/ws-queue.ts", "../src/kernel/net/remote-transport.ts", "../src/kernel/signals.ts", "../src/bytes.ts", "../src/client/dial-stream.ts", "../src/client/loopback-fetch.ts", "../src/client/protocol.ts", "../src/client/attach.ts", "../src/mount/protocol.ts", "../src/mount/driver.ts", "../src/mount/host.ts", "../src/process/js/lockdown.ts", "../src/driver-worker.ts"],
4
- "sourcesContent": ["import type { CdpConnection, CdpHook, CdpRequest } from './types.ts';\n\nexport interface CdpPortLike {\n postMessage(message: unknown): void;\n addEventListener(type: 'message', handler: (event: MessageEvent) => void): void;\n start?(): void;\n close(): void;\n}\n\nexport type CdpWire = { open: true } | { error: string } | { m: string } | { close: string | null };\n\nexport interface CdpOpen {\n cdpOpen: CdpRequest & { registration?: number };\n port: CdpPortLike;\n}\n\nexport function serveCdpPort(\n port: CdpPortLike,\n hook: CdpHook,\n request: CdpRequest,\n onDone?: () => void\n): () => void {\n let conn: CdpConnection | undefined;\n let done = false;\n const end = () => {\n done = true;\n port.close();\n onDone?.();\n };\n const finish = (reason: string | null) => {\n if (done) return;\n port.postMessage({ close: reason });\n end();\n };\n port.addEventListener('message', ({ data }: MessageEvent<{ m?: string; close?: true }>) => {\n if (data.m !== undefined) conn?.send(data.m);\n else if (data.close && !done) {\n end();\n conn?.close();\n }\n });\n port.start?.();\n new Promise<CdpConnection>((resolve) => resolve(hook(request))).then(\n (opened) => {\n conn = opened;\n if (done) return opened.close();\n opened.onmessage = (m) => {\n if (!done) port.postMessage({ m });\n };\n opened.onclose = (reason) => finish(reason ?? null);\n port.postMessage({ open: true });\n },\n (e: unknown) => {\n if (done) return;\n port.postMessage({ error: e instanceof Error ? e.message : String(e) });\n end();\n }\n );\n return () => {\n if (done) return;\n conn?.close();\n finish('the CDP host is gone');\n };\n}\n\nexport function portCdpHook(\n ask: (request: CdpRequest, port: CdpPortLike) => void,\n gone?: Promise<unknown>\n): CdpHook {\n return (request) =>\n new Promise((resolve, reject) => {\n const { port1, port2 } = new MessageChannel();\n let closed = false;\n const conn: CdpConnection = {\n send: (m) => {\n if (!closed) port1.postMessage({ m });\n },\n onmessage: null,\n onclose: null,\n close: () => {\n if (closed) return;\n closed = true;\n port1.postMessage({ close: true });\n port1.close();\n },\n };\n port1.addEventListener('message', ({ data }: MessageEvent<CdpWire>) => {\n if ('m' in data) conn.onmessage?.(data.m);\n else if ('open' in data) resolve(conn);\n else if ('error' in data) {\n closed = true;\n port1.close();\n reject(new Error(data.error));\n } else if (!closed) {\n closed = true;\n port1.close();\n conn.onclose?.(data.close ?? undefined);\n }\n });\n port1.start();\n void gone?.then(() => {\n if (closed) return;\n closed = true;\n port1.close();\n reject(new Error('the CDP host is gone'));\n conn.onclose?.('the CDP host is gone');\n });\n ask(request, port2 as unknown as CdpPortLike);\n });\n}\n", "import type {\n 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 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 { 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", "import type { SealedCaller } from '../sealed.ts';\n\nexport const FORBIDDEN_HEADER = 'forbidden-header';\n\nexport type HeaderList = ReadonlyArray<readonly [name: string, value: string]>;\nexport type RealmRedirectPolicy = 'follow' | 'manual' | 'error';\nexport interface RealmTransportRequest {\n url: string;\n method: string;\n headers: HeaderList;\n body?: Uint8Array;\n bodyStream?: AsyncIterable<Uint8Array>;\n redirect?: RealmRedirectPolicy;\n signal: AbortSignal;\n}\nexport interface RealmRedirectHop {\n status: number;\n url: string;\n headers: HeaderList;\n}\nexport interface RealmTransportResponse {\n url?: string;\n redirected?: boolean;\n redirects?: readonly RealmRedirectHop[];\n opaqueRedirect?: true;\n status: number;\n statusText: string;\n headers: HeaderList;\n body: AsyncIterable<Uint8Array>;\n cancel(): Promise<void>;\n}\nexport interface RealmTransportExit {\n kind: 'local' | 'remote' | 'tailnet' | (string & {});\n caps: readonly string[];\n [detail: string]: unknown;\n}\nexport interface RealmTransportTraits {\n manualRedirects: boolean;\n encodedBodies: boolean;\n maxRequestBody: number;\n crossOrigin?: 'cors' | 'any';\n unavailable?: true;\n websocket?: true;\n streamingBodies?: true;\n redirectHops?: true;\n redirectPolicy?: true;\n exit?: RealmTransportExit;\n [trait: string]: unknown;\n}\nexport interface RealmWebSocketRequest {\n url: string;\n protocols: string[];\n headers: HeaderList;\n signal: AbortSignal;\n}\nexport interface RealmWebSocketClose {\n code: number;\n reason: string;\n wasClean?: boolean;\n}\nexport type RealmWebSocketMessage = string | Uint8Array;\nexport interface RealmWebSocket {\n readonly protocol: string;\n readonly buffered: number;\n send(data: RealmWebSocketMessage): void;\n readonly messages: AsyncIterable<RealmWebSocketMessage>;\n close(code?: number, reason?: string): void;\n readonly closed: Promise<RealmWebSocketClose>;\n}\nexport interface RealmTransport {\n readonly traits: RealmTransportTraits;\n fetch(\n request: RealmTransportRequest,\n owner?: number,\n stamp?: SealedCaller\n ): Promise<RealmTransportResponse>;\n websocket?(request: RealmWebSocketRequest): Promise<RealmWebSocket>;\n}\n", "import type { RealmWebSocketClose, RealmWebSocketMessage } from './transport.ts';\n\nexport const INBOUND_LIMIT = 16 * 1024 * 1024;\nexport const MESSAGE_LIMIT = 64 * 1024 * 1024;\nexport const TOO_BIG = 1009;\n\nexport function payloadSize(message: RealmWebSocketMessage): number {\n return typeof message === 'string' ? new TextEncoder().encode(message).length : message.length;\n}\n\nexport class MessageQueue implements AsyncIterable<RealmWebSocketMessage> {\n private readonly items: RealmWebSocketMessage[] = [];\n private readonly limit: number;\n private waiter: (() => void) | undefined;\n private size = 0;\n private ended = false;\n private readonly overflow: () => void;\n private readonly taken: ((n: number) => void) | undefined;\n readonly closed: Promise<RealmWebSocketClose>;\n private settle!: (close: RealmWebSocketClose) => void;\n\n constructor(overflow: () => void, limit = INBOUND_LIMIT, taken?: (n: number) => void) {\n this.overflow = overflow;\n this.limit = limit;\n this.taken = taken;\n this.closed = new Promise((resolve) => {\n this.settle = resolve;\n });\n }\n\n push(message: RealmWebSocketMessage): void {\n if (this.ended) return;\n const size = payloadSize(message);\n const huge = size > MESSAGE_LIMIT;\n if (huge || (this.items.length > 0 && this.size + size > this.limit)) {\n const reason = huge\n ? `a message is over ${MESSAGE_LIMIT} bytes`\n : `over ${this.limit} bytes of messages are waiting`;\n this.end({ code: TOO_BIG, reason });\n this.overflow();\n return;\n }\n this.size += size;\n this.items.push(message);\n this.wake();\n }\n\n end(close: RealmWebSocketClose): void {\n if (this.ended) return;\n this.ended = true;\n this.settle(close);\n this.wake();\n }\n\n private wake(): void {\n const waiter = this.waiter;\n this.waiter = undefined;\n waiter?.();\n }\n\n async *[Symbol.asyncIterator](): AsyncIterator<RealmWebSocketMessage> {\n for (;;) {\n const next = this.items.shift();\n if (next !== undefined) {\n const n = payloadSize(next);\n this.size -= n;\n this.taken?.(n);\n yield next;\n continue;\n }\n if (this.ended) return;\n await new Promise<void>((resolve) => {\n this.waiter = resolve;\n });\n }\n }\n}\n", "import type { SealedCaller } from '../sealed.ts';\nimport {\n FORBIDDEN_HEADER,\n type HeaderList,\n type RealmRedirectHop,\n type RealmRedirectPolicy,\n type RealmTransport,\n type RealmTransportRequest,\n type RealmTransportResponse,\n type RealmTransportTraits,\n type RealmWebSocket,\n type RealmWebSocketMessage,\n type 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' | typeof FORBIDDEN_HEADER;\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' | typeof FORBIDDEN_HEADER | 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 === FORBIDDEN_HEADER ? 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", "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", "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", "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 { TraceEvent } from '../kernel/trace.ts';\nimport type { MountSpec } from '../mount/mount-fs.ts';\n\nexport const PROTOCOL: readonly [number, number] = [1, 17];\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 cwdMissing?: 'create' | 'error';\n user?: string | number;\n env?: Record<string, string>;\n stdin?: Uint8Array;\n pgid?: number;\n tag?: string | readonly string[];\n}\n\nexport interface TerminalRequestOptions {\n cwd?: string;\n cwdMissing?: 'create' | 'error';\n user?: string | number;\n env?: Record<string, string>;\n cols?: number;\n rows?: number;\n tag?: string | readonly string[];\n}\n\nexport interface SudoRunRequestOptions {\n stdout?: string;\n stderr?: string;\n tag?: string | readonly 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: 'trace'; tag: string; limit?: number }\n | { op: 'untrace'; trace: number }\n | { op: 'sudo-run'; replay: unknown; options: SudoRunRequestOptions }\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 interface TraceAck {\n traceAck: number;\n}\n\nexport type ClientMessage = { hello: ClientHello } | ClientRequest | TransportCall | TraceAck;\n\nexport interface WatchEvent {\n watch: number;\n change: WatchChange;\n}\n\nexport interface TraceMessage {\n trace: number;\n events: TraceEvent[];\n dropped?: number;\n}\n\nexport type KernelMessage =\n | { hello: KernelHello }\n | ClientReply\n | WatchEvent\n | TraceMessage\n | 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 { TraceEvent } from '../kernel/trace.ts';\nimport type { MountEntry, MountSpec } from '../mount/mount-fs.ts';\nimport type { SudoReplay } from '../sudo.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 { TraceEvent, TraceExec, TraceExit, TraceFork } from '../kernel/trace.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 cwdMissing?: 'create' | 'error';\n user?: string | number;\n env?: Record<string, string>;\n stdin?: string | Uint8Array;\n group?: 'new';\n pgid?: number;\n tag?: string | readonly 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 SudoRunOptions {\n stdout?: string;\n stderr?: string;\n tag?: string | readonly string[];\n}\n\nexport interface SudoRun {\n readonly pid: number;\n readonly pgid: number;\n readonly ended: Promise<ClientEnded>;\n}\n\nexport interface ClientRunOptions {\n cwd?: string;\n cwdMissing?: 'create' | 'error';\n user?: string | number;\n env?: Record<string, string>;\n stdin?: string | Uint8Array;\n tag?: string | readonly 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 cwdMissing?: 'create' | 'error';\n user?: string | number;\n env?: Record<string, string>;\n cols?: number;\n rows?: number;\n tag?: string | readonly 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 interface TraceBatch {\n events: TraceEvent[];\n dropped: number;\n}\n\nexport interface TraceOptions {\n limit?: number;\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 trace(\n tag: string,\n onEvents: (batch: TraceBatch) => void | Promise<unknown>,\n options?: TraceOptions\n ): Promise<{ close(): void }>;\n sudoRun(request: SudoReplay, options?: SudoRunOptions): Promise<SudoRun>;\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 tracing = new Map<number, (batch: TraceBatch) => unknown>();\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 trace?: number;\n events?: TraceEvent[];\n dropped?: number;\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.trace !== undefined && data.id === undefined) {\n this.traced(data.trace, data.events ?? [], data.dropped ?? 0);\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 traced(trace: number, events: TraceEvent[], dropped: number): void {\n const listener = this.tracing.get(trace);\n if (!listener) return;\n const ack = () => {\n if (this.tracing.has(trace)) this.post({ traceAck: trace });\n };\n let consumed: unknown;\n try {\n consumed = listener({ events, dropped });\n } finally {\n if (typeof (consumed as PromiseLike<unknown> | undefined)?.then === 'function') {\n void Promise.resolve(consumed).then(ack, ack);\n } else {\n ack();\n }\n }\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 traceOn(\n channel: Channel,\n tag: string,\n onEvents: (batch: TraceBatch) => unknown,\n options: TraceOptions\n): Promise<{ close(): void }> {\n if (typeof onEvents !== 'function') throw new TypeError('trace: onEvents must be a function');\n await since(channel, 15, 'trace', async () => {});\n const { id, done } = channel.request({\n op: 'trace',\n tag,\n ...(options.limit !== undefined ? { limit: options.limit } : {}),\n });\n channel.tracing.set(id, onEvents);\n try {\n await done;\n } catch (error) {\n channel.tracing.delete(id);\n throw error;\n }\n return {\n close: () => {\n if (!channel.tracing.delete(id)) return;\n void channel.call({ op: 'untrace', trace: 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 if (Array.isArray(opts.tag)) await since(channel, 15, 'several tags per spawn', async () => {});\n if (opts.cwdMissing === 'error') await since(channel, 14, \"cwdMissing: 'error'\", 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\nasync function sudoRunOn(\n channel: Channel,\n replay: SudoReplay,\n { stdout, stderr, tag }: SudoRunOptions\n): Promise<SudoRun> {\n await since(channel, 16, 'sudoRun', async () => {});\n const started = Promise.withResolvers<number>();\n let endedBy: string | undefined;\n const { done } = channel.request(\n { op: 'sudo-run', replay, options: { stdout, stderr, tag } },\n { started: started.resolve, ended: (signal) => (endedBy = signal) }\n );\n done.catch(started.reject);\n const pid = await started.promise;\n return { pid, pgid: pid, ended: endedOf(done, () => endedBy) };\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 if (Array.isArray(opts.tag)) {\n await since(channel, 15, 'several tags per terminal', async () => {});\n }\n if (opts.cwdMissing === 'error') await since(channel, 14, \"cwdMissing: 'error'\", 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 trace: (tag, onEvents, options = {}) => traceOn(channel, tag, onEvents, options),\n sudoRun: (replay, options = {}) => sudoRunOn(channel, replay, options),\n async close(o = {}) {\n if (channel.failure) return;\n await channel\n .call({ op: 'detach', ...(o.kill ? { kill: true } : {}) })\n .catch(() => undefined);\n channel.end(new KernelGoneError('this client is closed'));\n },\n };\n}\n", "export const DRIVER_PROTOCOL: readonly [number, number] = [1, 3];\n\nexport interface DriverCapabilities {\n readonly?: boolean;\n symlinks?: boolean;\n links?: boolean;\n fifos?: boolean;\n chmod?: boolean;\n owners?: boolean;\n linkTimes?: boolean;\n ranges?: boolean;\n sessions?: boolean;\n listingStats?: boolean;\n caseInsensitive?: boolean;\n normalization?: 'none' | 'nfc' | 'nfd-insensitive';\n maxIo?: number;\n maxFile?: number;\n attrTtl?: number;\n entryTtl?: number;\n}\n\nexport interface DriverAttr {\n kind: 'file' | 'directory' | 'symlink' | 'fifo';\n size: number;\n mtime: number;\n atime?: number;\n mode?: number;\n ino?: number;\n nlink?: number;\n etag?: string;\n uid?: number;\n gid?: number;\n}\n\nexport interface DriverOwner {\n uid?: number;\n gid?: number;\n mode?: number;\n}\n\nexport interface DriverEntry {\n name: string;\n kind: DriverAttr['kind'];\n attr?: DriverAttr;\n}\n\nexport interface DriverStatfs {\n bsize: number;\n blocks: number;\n bfree: number;\n}\n\nexport interface MountRequestInfo {\n source: string;\n options: Record<string, string>;\n}\n\nexport type DriverCall =\n | { op: 'getattr'; path: string }\n | { op: 'readdir'; path: string }\n | ({\n op: 'open';\n path: string;\n write: boolean;\n create: boolean;\n truncate: boolean;\n exclusive: boolean;\n ifMatch?: string;\n } & DriverOwner)\n | { op: 'read'; fh: number; offset: number; size: number }\n | { op: 'write'; fh: number; offset: number; bytes: Uint8Array }\n | { op: 'release'; fh: number }\n | ({ op: 'mkdir'; path: string } & DriverOwner)\n | { op: 'rmdir'; path: string }\n | { op: 'unlink'; path: string }\n | { op: 'rename'; from: string; to: string }\n | { op: 'link'; from: string; to: string }\n | ({ op: 'symlink'; target: string; path: string } & DriverOwner)\n | ({ op: 'mkfifo'; path: string } & DriverOwner)\n | { op: 'readlink'; path: string }\n | {\n op: 'setattr';\n path: string;\n mode?: number;\n mtime?: number;\n atime?: number;\n size?: number;\n uid?: number;\n gid?: number;\n }\n | { op: 'statfs' };\n\nexport type DriverRequest = DriverCall & { id: number };\n\nexport interface DriverReply {\n id: number;\n result?: unknown;\n errno?: string;\n message?: string;\n}\n\nexport interface KernelDriverHello {\n protocol: readonly [number, number];\n mount: MountRequestInfo;\n}\n\nexport interface DriverHello {\n protocol: readonly [number, number];\n capabilities?: DriverCapabilities;\n error?: string;\n errno?: string;\n}\n\nexport type KernelToDriver = { hello: KernelDriverHello } | DriverRequest;\n\nexport type DriverToKernel = { hello: DriverHello } | DriverReply | { invalidate: string[] | true };\n\nexport function driverVersionError(theirs: unknown): string | undefined {\n const major = Array.isArray(theirs) ? theirs[0] : undefined;\n if (major === DRIVER_PROTOCOL[0]) return undefined;\n const named = typeof major === 'number' ? `${major}.x` : 'without a version';\n return `slicc-kernel driver protocol ${named} is not supported: this side speaks ${DRIVER_PROTOCOL.join('.')}`;\n}\n", "import {\n DRIVER_PROTOCOL,\n type DriverAttr,\n type DriverCapabilities,\n type DriverEntry,\n type 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 { attachKernel } from '../client/attach.ts';\nimport type { MessagePortLike } from '../client/protocol.ts';\nimport type { RealmTransportRequest, RealmTransportResponse } from '../kernel/net/transport.ts';\nimport { type FilesystemHandlers, serveFilesystem } from './driver.ts';\nimport { DRIVER_PROTOCOL, type DriverCapabilities } from './protocol.ts';\n\nexport interface DriverStart {\n code: string;\n driver: MessagePortLike;\n client: MessagePortLike;\n}\n\nexport interface DriverEnv {\n fetch(\n request: Omit<RealmTransportRequest, 'signal'> & { signal?: AbortSignal }\n ): Promise<RealmTransportResponse>;\n}\n\nexport type DriverFactory = (\n env: DriverEnv\n) =>\n | Promise<{ handlers: FilesystemHandlers; capabilities?: DriverCapabilities }>\n | { handlers: FilesystemHandlers; capabilities?: DriverCapabilities };\n\nexport async function hostDriver(\n start: DriverStart,\n load: (code: string) => Promise<{ default?: unknown }>\n): Promise<void> {\n try {\n const factory = (await load(start.code)).default;\n if (typeof factory !== 'function') {\n throw new Error('a slicc file system module must export a default function');\n }\n const client = await attachKernel(start.client, { locks: null });\n const made = await (factory as DriverFactory)({ fetch: (request) => client.fetch(request) });\n serveFilesystem(start.driver, made.handlers, made.capabilities ?? {});\n } catch (err) {\n start.driver.postMessage({\n hello: {\n protocol: DRIVER_PROTOCOL,\n error: `the driver did not start: ${err instanceof Error ? err.message : String(err)}`,\n errno: 'EIO',\n },\n });\n }\n}\n", "export const BLOCKED_GLOBALS: readonly string[] = [\n 'XMLHttpRequest',\n 'WebSocketStream',\n 'WebTransport',\n 'EventSource',\n 'indexedDB',\n 'caches',\n 'cookieStore',\n 'SharedWorker',\n 'close',\n 'webkitRequestFileSystem',\n 'webkitRequestFileSystemSync',\n 'webkitResolveLocalFileSystemURL',\n 'webkitResolveLocalFileSystemSyncURL',\n];\n\nexport const BLOCKED_NAVIGATOR: readonly string[] = [\n 'storage',\n 'storageBuckets',\n 'locks',\n 'serviceWorker',\n 'usb',\n 'hid',\n 'serial',\n];\n\nexport const OPEN_SLOTS: readonly string[] = [\n 'fetch',\n 'WebSocket',\n 'BroadcastChannel',\n 'importScripts',\n 'Worker',\n 'postMessage',\n];\n\nfunction chain(target: object): object[] {\n const out: object[] = [];\n for (let at: object | null = target; at && at !== Object.prototype; ) {\n out.push(at);\n at = Object.getPrototypeOf(at);\n }\n return out;\n}\n\nexport function hide(target: object, names: readonly string[]): void {\n for (const name of names) {\n const holders = chain(target);\n for (const holder of holders) Reflect.deleteProperty(holder, name);\n const kept = holders.slice(1).some((holder) => Object.hasOwn(holder, name));\n const defined = Reflect.defineProperty(target, name, {\n value: undefined,\n writable: false,\n enumerable: false,\n configurable: false,\n });\n if (kept || (!defined && Reflect.get(target, name) !== undefined)) {\n throw new Error(`slicc-kernel: cannot withhold ${name} from a JS program`);\n }\n }\n}\n\nexport function vacate(target: object, names: readonly string[]): void {\n for (const name of names) {\n const holders = chain(target);\n for (const holder of holders) Reflect.deleteProperty(holder, name);\n const kept = holders.slice(1).some((holder) => Object.hasOwn(holder, name));\n const opened = Reflect.defineProperty(target, name, {\n value: undefined,\n writable: true,\n enumerable: false,\n configurable: true,\n });\n if (kept || !opened || Reflect.get(target, name) !== undefined) {\n throw new Error(`slicc-kernel: cannot withhold ${name} from a JS program`);\n }\n }\n}\n\nexport function lockdown(scope: object = globalThis): void {\n hide(scope, BLOCKED_GLOBALS);\n vacate(scope, OPEN_SLOTS);\n if ('self' in scope) {\n Reflect.defineProperty(scope, 'self', {\n value: scope,\n writable: true,\n enumerable: false,\n configurable: true,\n });\n }\n const navigator = (scope as { navigator?: unknown }).navigator;\n if (navigator && typeof navigator === 'object') hide(navigator, BLOCKED_NAVIGATOR);\n}\n", "import { type DriverStart, hostDriver } from './mount/host.ts';\nimport { lockdown } from './process/js/lockdown.ts';\n\naddEventListener(\n 'message',\n (event) =>\n void hostDriver((event as MessageEvent<DriverStart>).data, (code) => {\n const url = URL.createObjectURL(new Blob([code], { type: 'text/javascript' }));\n lockdown();\n return import(url);\n }),\n { once: true }\n);\n"],
5
- "mappings": "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",
6
- "names": ["fresh", "fail", "fresh", "encoder", "bytesOf", "done", "refused", "options", "refused", "fresh"]
3
+ "sources": ["../src/cdp/port.ts", "../src/devices-relay.ts", "../src/embedder-relay.ts", "../src/facade/port.ts", "../src/fs/owners.ts", "../src/kernel/pipe.ts", "../src/kernel/embedder.ts", "../src/kernel/serial-ioctl.ts", "../src/kernel/signals.ts", "../src/kernel/tty.ts", "../src/kernel/devices.ts", "../src/kernel/net/transport.ts", "../src/kernel/net/ws-queue.ts", "../src/kernel/net/remote-transport.ts", "../src/bytes.ts", "../src/client/dial-stream.ts", "../src/client/loopback-fetch.ts", "../src/client/protocol.ts", "../src/client/attach.ts", "../src/mount/protocol.ts", "../src/mount/driver.ts", "../src/mount/host.ts", "../src/process/js/lockdown.ts", "../src/driver-worker.ts"],
4
+ "sourcesContent": ["import type { CdpConnection, CdpHook, CdpRequest } from './types.ts';\n\nexport interface CdpPortLike {\n postMessage(message: unknown): void;\n addEventListener(type: 'message', handler: (event: MessageEvent) => void): void;\n start?(): void;\n close(): void;\n}\n\nexport type CdpWire = { open: true } | { error: string } | { m: string } | { close: string | null };\n\nexport interface CdpOpen {\n cdpOpen: CdpRequest & { registration?: number };\n port: CdpPortLike;\n}\n\nexport function serveCdpPort(\n port: CdpPortLike,\n hook: CdpHook,\n request: CdpRequest,\n onDone?: () => void\n): () => void {\n let conn: CdpConnection | undefined;\n let done = false;\n const end = () => {\n done = true;\n port.close();\n onDone?.();\n };\n const finish = (reason: string | null) => {\n if (done) return;\n port.postMessage({ close: reason });\n end();\n };\n port.addEventListener('message', ({ data }: MessageEvent<{ m?: string; close?: true }>) => {\n if (data.m !== undefined) conn?.send(data.m);\n else if (data.close && !done) {\n end();\n conn?.close();\n }\n });\n port.start?.();\n new Promise<CdpConnection>((resolve) => resolve(hook(request))).then(\n (opened) => {\n conn = opened;\n if (done) return opened.close();\n opened.onmessage = (m) => {\n if (!done) port.postMessage({ m });\n };\n opened.onclose = (reason) => finish(reason ?? null);\n port.postMessage({ open: true });\n },\n (e: unknown) => {\n if (done) return;\n port.postMessage({ error: e instanceof Error ? e.message : String(e) });\n end();\n }\n );\n return () => {\n if (done) return;\n conn?.close();\n finish('the CDP host is gone');\n };\n}\n\nexport function portCdpHook(\n ask: (request: CdpRequest, port: CdpPortLike) => void,\n gone?: Promise<unknown>\n): CdpHook {\n return (request) =>\n new Promise((resolve, reject) => {\n const { port1, port2 } = new MessageChannel();\n let closed = false;\n const conn: CdpConnection = {\n send: (m) => {\n if (!closed) port1.postMessage({ m });\n },\n onmessage: null,\n onclose: null,\n close: () => {\n if (closed) return;\n closed = true;\n port1.postMessage({ close: true });\n port1.close();\n },\n };\n port1.addEventListener('message', ({ data }: MessageEvent<CdpWire>) => {\n if ('m' in data) conn.onmessage?.(data.m);\n else if ('open' in data) resolve(conn);\n else if ('error' in data) {\n closed = true;\n port1.close();\n reject(new Error(data.error));\n } else if (!closed) {\n closed = true;\n port1.close();\n conn.onclose?.(data.close ?? undefined);\n }\n });\n port1.start();\n void gone?.then(() => {\n if (closed) return;\n closed = true;\n port1.close();\n reject(new Error('the CDP host is gone'));\n conn.onclose?.('the CDP host is gone');\n });\n ask(request, port2 as unknown as CdpPortLike);\n });\n}\n", "import type { DeviceHook, DeviceStamp, DeviceStreams } from './kernel/devices.ts';\n\nexport interface DevicesPort {\n postMessage(message: unknown, transfer?: Transferable[]): void;\n}\n\ninterface Failure {\n name: string;\n message: string;\n}\n\nexport type DevicesToPage =\n | { id: number; open: { client: number; path: string; flags: number; stamp: DeviceStamp } }\n | { id: number; pull: true }\n | { id: number; write: Uint8Array; seq: number }\n | { id: number; control: { seq: number; op: string; args?: object } }\n | { id: number; cancel: string };\n\nexport type DevicesToKernel =\n | { id: number; opened: true }\n | { id: number; failed: Failure }\n | { id: number; chunk: Uint8Array }\n | { id: number; done: true }\n | { id: number; readError: Failure }\n | { id: number; wrote: number }\n | { id: number; writeError: Failure; seq: number }\n | { id: number; answered: number; value?: unknown }\n | { id: number; refused: number; error: Failure };\n\nfunction quiet(): undefined {\n return undefined;\n}\n\nfunction errorOf(err: unknown): Failure {\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\nfunction raised(failure: Failure): Error {\n return Object.assign(new Error(failure.message), { name: failure.name });\n}\n\nfunction fresh(bytes: Uint8Array): Uint8Array {\n return bytes.byteOffset === 0 && bytes.byteLength === bytes.buffer.byteLength\n ? bytes\n : bytes.slice();\n}\n\ninterface Remote {\n opened: PromiseWithResolvers<void>;\n chunks: Array<Uint8Array | null | Failure>;\n wake: (() => void) | undefined;\n writes: Map<number, PromiseWithResolvers<void>>;\n controls: Map<number, PromiseWithResolvers<unknown>>;\n seq: number;\n}\n\nexport function devicesAsker(port: DevicesPort) {\n const remotes = new Map<number, Remote>();\n let next = 0;\n const post = (message: DevicesToPage, transfer: Transferable[] = []) =>\n port.postMessage({ devices: message }, transfer);\n const push = (remote: Remote, item: Remote['chunks'][number]) => {\n remote.chunks.push(item);\n remote.wake?.();\n };\n const streams = (id: number, remote: Remote): DeviceStreams => ({\n readable: new ReadableStream<Uint8Array>(\n {\n pull: async (controller) => {\n if (remote.chunks.length === 0) {\n post({ id, pull: true });\n await new Promise<void>((resolve) => {\n remote.wake = resolve;\n });\n }\n const item = remote.chunks.shift();\n if (item instanceof Uint8Array) controller.enqueue(item);\n else if (item === null || item === undefined) controller.close();\n else controller.error(raised(item));\n },\n cancel: (reason) => {\n post({ id, cancel: String(reason ?? 'closed') });\n },\n },\n { highWaterMark: 0 }\n ),\n writable: new WritableStream<Uint8Array>({\n write: (chunk) => {\n const seq = ++remote.seq;\n const done = Promise.withResolvers<void>();\n remote.writes.set(seq, done);\n const bytes = fresh(chunk);\n post({ id, write: bytes, seq }, [bytes.buffer as ArrayBuffer]);\n return done.promise;\n },\n abort: (reason) => {\n post({ id, cancel: String(reason ?? 'closed') });\n },\n }),\n control: (op, args) => {\n const seq = ++remote.seq;\n const done = Promise.withResolvers<unknown>();\n remote.controls.set(seq, done);\n post({ id, control: { seq, op, ...(args ? { args } : {}) } });\n if (op === 'close') void done.promise.finally(() => remotes.delete(id)).catch(quiet);\n return done.promise;\n },\n });\n const hookFor = (client: number): DeviceHook => ({\n open: async (request) => {\n const id = ++next;\n const remote: Remote = {\n opened: Promise.withResolvers<void>(),\n chunks: [],\n wake: undefined,\n writes: new Map(),\n controls: new Map(),\n seq: 0,\n };\n remotes.set(id, remote);\n const abort = () => {\n remotes.delete(id);\n post({ id, cancel: 'interrupted' });\n remote.opened.reject(request.signal.reason);\n };\n request.signal.addEventListener('abort', abort, { once: true });\n const { path, flags, stamp } = request;\n post({ id, open: { client, path, flags, stamp } });\n try {\n await remote.opened.promise;\n } finally {\n request.signal.removeEventListener('abort', abort);\n }\n return streams(id, remote);\n },\n });\n const answer = (message: DevicesToKernel): void => {\n const remote = remotes.get(message.id);\n if (!remote) return;\n if ('opened' in message) remote.opened.resolve();\n else if ('failed' in message) {\n remotes.delete(message.id);\n remote.opened.reject(raised(message.failed));\n } else if ('chunk' in message) push(remote, message.chunk);\n else if ('done' in message) push(remote, null);\n else if ('readError' in message) push(remote, message.readError);\n else if ('wrote' in message) {\n remote.writes.get(message.wrote)?.resolve();\n remote.writes.delete(message.wrote);\n } else if ('writeError' in message) {\n remote.writes.get(message.seq)?.reject(raised(message.writeError));\n remote.writes.delete(message.seq);\n } else if ('answered' in message) {\n remote.controls.get(message.answered)?.resolve(message.value);\n remote.controls.delete(message.answered);\n } else {\n remote.controls.get(message.refused)?.reject(raised(message.error));\n remote.controls.delete(message.refused);\n }\n };\n return { hookFor, answer };\n}\n\ninterface Local {\n abort: AbortController;\n closing?: Promise<void>;\n streams?: DeviceStreams;\n reader?: ReadableStreamDefaultReader<Uint8Array>;\n writer?: WritableStreamDefaultWriter<Uint8Array>;\n}\n\nexport function devicesAnswerer(\n port: DevicesPort,\n hookFor: (client: number) => DeviceHook | undefined\n): { handle(data: unknown): boolean } {\n const locals = new Map<number, Local>();\n const post = (message: DevicesToKernel, transfer: Transferable[] = []) =>\n port.postMessage({ devicesReply: message }, transfer);\n const open = async (\n id: number,\n asked: Extract<DevicesToPage, { open: unknown }>['open']\n ): Promise<void> => {\n const local: Local = { abort: new AbortController() };\n locals.set(id, local);\n try {\n const hook = hookFor(asked.client);\n if (!hook)\n throw Object.assign(new Error('this page has no devices hook'), {\n name: 'NotSupportedError',\n });\n const streams = await hook.open({\n path: asked.path,\n flags: asked.flags,\n stamp: asked.stamp,\n signal: local.abort.signal,\n });\n if (!locals.has(id)) {\n await streams?.readable?.cancel('closed').catch(quiet);\n await streams?.writable?.abort('closed').catch(quiet);\n await Promise.resolve(streams?.control?.('close')).catch(quiet);\n return;\n }\n local.streams = streams;\n local.reader = streams.readable.getReader();\n local.writer = streams.writable.getWriter();\n post({ id, opened: true });\n } catch (err) {\n locals.delete(id);\n post({ id, failed: errorOf(err) });\n }\n };\n const pull = async (id: number, local: Local): Promise<void> => {\n try {\n const got = await (local.reader as ReadableStreamDefaultReader<Uint8Array>).read();\n if (got.done) return post({ id, done: true });\n const bytes = fresh(got.value);\n post({ id, chunk: bytes }, [bytes.buffer as ArrayBuffer]);\n } catch (err) {\n post({ id, readError: errorOf(err) });\n }\n };\n const write = async (id: number, local: Local, bytes: Uint8Array, seq: number) => {\n try {\n await (local.writer as WritableStreamDefaultWriter<Uint8Array>).write(bytes);\n post({ id, wrote: seq });\n } catch (err) {\n post({ id, writeError: errorOf(err), seq });\n }\n };\n const control = async (\n id: number,\n local: Local,\n asked: { seq: number; op: string; args?: object }\n ) => {\n try {\n await local.closing;\n const value = await (local.streams as DeviceStreams).control(asked.op, asked.args);\n post({ id, answered: asked.seq, ...(value !== undefined ? { value } : {}) });\n } catch (err) {\n post({ id, refused: asked.seq, error: errorOf(err) });\n }\n if (asked.op === 'close') locals.delete(id);\n };\n const release = async (local: Local, reason: string): Promise<void> => {\n const { reader, writer } = local;\n local.reader = undefined;\n local.writer = undefined;\n await reader?.cancel(reason).catch(quiet);\n reader?.releaseLock();\n await writer?.abort(reason).catch(quiet);\n writer?.releaseLock();\n };\n const cancel = (id: number, local: Local, reason: string): void => {\n local.abort.abort(new DOMException(reason, 'AbortError'));\n if (!local.streams) {\n locals.delete(id);\n return;\n }\n local.closing = Promise.resolve(local.closing).then(() => release(local, reason));\n };\n return {\n handle(data) {\n const message = (data as { devices?: DevicesToPage } | null)?.devices;\n if (!message) return false;\n if ('open' in message) {\n void open(message.id, message.open);\n return true;\n }\n const local = locals.get(message.id);\n if (!local) return true;\n if ('pull' in message) void pull(message.id, local);\n else if ('write' in message) void write(message.id, local, message.write, message.seq);\n else if ('control' in message) void control(message.id, local, message.control);\n else cancel(message.id, local, message.cancel);\n return true;\n },\n };\n}\n\nexport function devicesReplyOf(data: unknown): DevicesToKernel | undefined {\n return (data as { devicesReply?: DevicesToKernel } | null)?.devicesReply;\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", "import type { Cred } from '../kernel/cred.ts';\nimport type { MetaEntry } from './meta.ts';\nimport { fsError, type KernelFs, type NewOwner, type Owner } from './types.ts';\n\nexport const ROOT_OWNER: Readonly<Owner> = Object.freeze({ uid: 0, gid: 0 });\n\nconst S_ISUID = 0o4000;\nconst S_ISGID = 0o2000;\nconst S_IXGRP = 0o010;\n\nexport function ownOf(entry: MetaEntry | undefined): Owner | undefined {\n if (entry?.uid === undefined || entry.gid === undefined) return undefined;\n return { uid: entry.uid, gid: entry.gid };\n}\n\nfunction handedBy(entry: MetaEntry | undefined): Owner | undefined {\n return entry?.heir ? { uid: entry.heir[0], gid: entry.heir[1] } : ownOf(entry);\n}\n\nexport function inherit(entries: ReadonlyArray<MetaEntry | undefined>): Owner {\n for (let i = entries.length - 1; i >= 0; i--) {\n const found = handedBy(entries[i]);\n if (found) return found;\n }\n return { ...ROOT_OWNER };\n}\n\nexport function chain(path: string): string[] {\n const parts = path.split('/').filter(Boolean);\n return ['/', ...parts.map((_, i) => `/${parts.slice(0, i + 1).join('/')}`)];\n}\n\nexport function sameOwner(a: Owner, b: Owner): boolean {\n return a.uid === b.uid && a.gid === b.gid;\n}\n\nexport function ownerOf(cred: Readonly<Cred>, mode?: number): NewOwner {\n return { uid: cred.euid, gid: cred.egid, ...(mode !== undefined ? { mode } : {}) };\n}\n\nexport function inGroup(cred: Readonly<Cred>, gid: number): boolean {\n return cred.egid === gid || cred.groups.includes(gid);\n}\n\nexport function mayChown(\n cred: Readonly<Cred>,\n current: Owner,\n uid: number | undefined,\n gid: number | undefined\n): boolean {\n if (cred.euid === 0) return true;\n const owner = cred.euid === current.uid;\n if (uid !== undefined && !(owner && uid === current.uid)) return false;\n if (gid !== undefined && !(owner && (gid === current.gid || inGroup(cred, gid)))) return false;\n return true;\n}\n\nexport function clearedSetId(mode: number): number {\n const bits = S_ISUID | (mode & S_IXGRP ? S_ISGID : 0);\n return mode & 0o7777 & ~bits;\n}\n\nexport async function chownAs(\n fs: KernelFs,\n cred: Readonly<Cred>,\n path: string,\n change: { uid?: number; gid?: number; follow: boolean }\n): Promise<void> {\n const { uid, gid, follow } = change;\n const st = follow ? await fs.stat(path) : await fs.lstat(path);\n const current = { uid: st.uid ?? 0, gid: st.gid ?? 0 };\n if (!fs.chown || !mayChown(cred, current, uid, gid)) throw fsError('EPERM', path);\n const clear =\n st.isFile && (uid !== undefined || gid !== undefined) ? clearedSetId(st.mode) : undefined;\n await fs.chown(path, {\n ...(uid !== undefined ? { uid } : {}),\n ...(gid !== undefined ? { gid } : {}),\n follow,\n ...(clear !== undefined && clear !== (st.mode & 0o7777) ? { mode: clear } : {}),\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 { 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\nexport function 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\nexport async function interruptible<T>(\n work: Promise<T>,\n signal: AbortSignal | undefined\n): 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", "import type { Termios } from './tty.ts';\n\nexport const IOCTL = {\n TCGETS: 0x5401,\n TCSETS: 0x5402,\n TCSETSW: 0x5403,\n TCSETSF: 0x5404,\n TCSBRK: 0x5409,\n TCFLSH: 0x540b,\n TIOCEXCL: 0x540c,\n TIOCNXCL: 0x540d,\n TIOCSCTTY: 0x540e,\n TIOCGPGRP: 0x540f,\n TIOCSPGRP: 0x5410,\n TIOCOUTQ: 0x5411,\n TIOCGWINSZ: 0x5413,\n TIOCSWINSZ: 0x5414,\n TIOCMGET: 0x5415,\n TIOCMBIS: 0x5416,\n TIOCMBIC: 0x5417,\n TIOCMSET: 0x5418,\n FIONREAD: 0x541b,\n TIOCNOTTY: 0x5422,\n TCSBRKP: 0x5425,\n TIOCSBRK: 0x5427,\n TIOCCBRK: 0x5428,\n TCGETS2: 0x802c542a,\n TCSETS2: 0x402c542b,\n TCSETSW2: 0x402c542c,\n TCSETSF2: 0x402c542d,\n} as const;\n\nexport const FILE_IOCTLS: ReadonlySet<number> = new Set([0x5421, 0x5450, 0x5451, 0x5452]);\n\nexport const TERMIOS_GETS: ReadonlySet<number> = new Set([IOCTL.TCGETS, IOCTL.TCGETS2]);\n\nexport const TERMIOS_SETS: ReadonlySet<number> = new Set([\n IOCTL.TCSETS,\n IOCTL.TCSETSW,\n IOCTL.TCSETSF,\n IOCTL.TCSETS2,\n IOCTL.TCSETSW2,\n IOCTL.TCSETSF2,\n]);\n\nexport const INT_OUT: ReadonlySet<number> = new Set([\n IOCTL.TIOCMGET,\n IOCTL.FIONREAD,\n IOCTL.TIOCOUTQ,\n]);\n\nexport const INT_IN: ReadonlySet<number> = new Set([\n IOCTL.TIOCMBIS,\n IOCTL.TIOCMBIC,\n IOCTL.TIOCMSET,\n]);\n\nexport const INT_ARG: ReadonlySet<number> = new Set([IOCTL.TCSBRK, IOCTL.TCSBRKP, IOCTL.TCFLSH]);\n\nexport const TIOCM = {\n DTR: 0x002,\n RTS: 0x004,\n CTS: 0x020,\n CD: 0x040,\n RI: 0x080,\n DSR: 0x100,\n} as const;\n\nexport interface SerialTermios extends Termios {\n c_ispeed?: number;\n c_ospeed?: number;\n}\n\nexport interface SerialSettings {\n baudRate: number;\n dataBits: number;\n parity: 'none' | 'even' | 'odd';\n stopBits: 1 | 2;\n flowControl: 'none' | 'hardware';\n}\n\nexport const CBAUD = 0o10017;\nexport const BOTHER = 0o10000;\nconst IBSHIFT = 16;\nconst CSIZE = 0o60;\nconst CSTOPB = 0o100;\nconst PARENB = 0o400;\nconst PARODD = 0o1000;\nconst CRTSCTS = 0x80000000;\n\nconst SPEEDS: readonly number[] = [\n 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800, 9600, 19200, 38400,\n];\nconst FAST: readonly number[] = [\n 0, 57600, 115200, 230400, 460800, 500000, 576000, 921600, 1000000, 1152000, 1500000, 2000000,\n 2500000, 3000000, 3500000, 4000000,\n];\n\nexport function speedOf(code: number): number | undefined {\n if (code === BOTHER) return undefined;\n return code & BOTHER ? FAST[code & 0o17] : SPEEDS[code & 0o17];\n}\n\nexport function codeOf(speed: number): number {\n const low = SPEEDS.indexOf(speed);\n if (low >= 0) return low;\n const high = FAST.indexOf(speed);\n return high > 0 ? BOTHER | high : BOTHER;\n}\n\nexport function speedsOf(\n termios: SerialTermios,\n current: { ispeed: number; ospeed: number },\n extended: boolean\n): { ispeed: number; ospeed: number } {\n const out = termios.c_cflag & CBAUD;\n const ospeed =\n speedOf(out) ?? (extended ? (termios.c_ospeed ?? current.ospeed) >>> 0 : current.ospeed);\n const inCode = (termios.c_cflag >>> IBSHIFT) & CBAUD;\n if (inCode === 0) return { ispeed: ospeed, ospeed };\n const ispeed =\n speedOf(inCode) ?? (extended ? (termios.c_ispeed ?? current.ispeed) >>> 0 : current.ispeed);\n return { ispeed, ospeed };\n}\n\nexport function settingsOf(cflag: number, baudRate: number): SerialSettings {\n return {\n baudRate,\n dataBits: 5 + ((cflag & CSIZE) >> 4),\n parity: cflag & PARENB ? (cflag & PARODD ? 'odd' : 'even') : 'none',\n stopBits: cflag & CSTOPB ? 2 : 1,\n flowControl: cflag & CRTSCTS ? 'hardware' : 'none',\n };\n}\n\nexport function sameSettings(a: SerialSettings, b: SerialSettings): boolean {\n return (\n a.baudRate === b.baudRate &&\n a.dataBits === b.dataBits &&\n a.parity === b.parity &&\n a.stopBits === b.stopBits &&\n a.flowControl === b.flowControl\n );\n}\n\nexport const SERIAL_CFLAG = 0o15 | 0o60 | 0o200 | 0o2000 | 0o4000;\nexport const SERIAL_LFLAG = 0o20 | 0o40 | 0o1000 | 0o4000;\nexport const SERIAL_OFLAG = 0o4;\n\nconst NCCS = 32;\nconst NCCS2 = 19;\nconst C_LINE = 16;\nconst C_CC = 17;\n\nfunction readFlags(view: DataView, at: number, ncc: number): SerialTermios {\n const cCc = new Array<number>(NCCS).fill(0);\n for (let i = 0; i < ncc; i++) cCc[i] = view.getUint8(at + C_CC + i);\n return {\n c_iflag: view.getUint32(at, true),\n c_oflag: view.getUint32(at + 4, true),\n c_cflag: view.getUint32(at + 8, true),\n c_lflag: view.getUint32(at + 12, true),\n c_cc: cCc,\n };\n}\n\nfunction writeFlags(view: DataView, at: number, t: SerialTermios, ncc: number): void {\n view.setUint32(at, t.c_iflag >>> 0, true);\n view.setUint32(at + 4, t.c_oflag >>> 0, true);\n view.setUint32(at + 8, t.c_cflag >>> 0, true);\n view.setUint32(at + 12, t.c_lflag >>> 0, true);\n view.setUint8(at + C_LINE, 0);\n for (let i = 0; i < ncc; i++) view.setUint8(at + C_CC + i, t.c_cc[i] ?? 0);\n}\n\nexport function ioctlArg(view: DataView, request: number, arg: number): unknown {\n if (TERMIOS_SETS.has(request)) {\n if (request > 0xffff) {\n const t = readFlags(view, arg, NCCS2);\n return {\n ...t,\n c_ispeed: view.getUint32(arg + 36, true),\n c_ospeed: view.getUint32(arg + 40, true),\n };\n }\n return readFlags(view, arg, NCCS);\n }\n if (INT_IN.has(request)) return view.getInt32(arg, true);\n if (INT_ARG.has(request)) return arg | 0;\n if (request === IOCTL.TIOCSWINSZ)\n return { rows: view.getUint16(arg, true), cols: view.getUint16(arg + 2, true) };\n return undefined;\n}\n\nexport function ioctlResult(view: DataView, request: number, arg: number, result: unknown): void {\n if (TERMIOS_GETS.has(request)) {\n const t = result as SerialTermios;\n if (request === IOCTL.TCGETS2) {\n writeFlags(view, arg, t, NCCS2);\n view.setUint32(arg + 36, (t.c_ispeed ?? 0) >>> 0, true);\n view.setUint32(arg + 40, (t.c_ospeed ?? 0) >>> 0, true);\n } else {\n writeFlags(view, arg, t, NCCS);\n view.setUint32(arg + 52, t.c_cflag & CBAUD, true);\n view.setUint32(arg + 56, t.c_cflag & CBAUD, true);\n }\n } else if (INT_OUT.has(request)) view.setInt32(arg, Number(result) | 0, true);\n else if (request === IOCTL.TIOCGWINSZ) {\n const size = result as { rows: number; cols: number };\n view.setUint16(arg, size.rows, true);\n view.setUint16(arg + 2, size.cols, true);\n view.setUint32(arg + 4, 0, true);\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 type { Perm } from '../fs/types.ts';\nimport { KernelError, OpenFile, type PollState } from './fd-table.ts';\nimport { SIG } from './signals.ts';\n\nexport interface Termios {\n c_iflag: number;\n c_oflag: number;\n c_cflag: number;\n c_lflag: number;\n c_cc: number[];\n}\n\nexport interface TtyScreen {\n write(bytes: Uint8Array): void;\n}\n\nconst ICRNL = 0o400;\nconst IUTF8 = 0o40000;\nconst OPOST = 0o1;\nconst ONLCR = 0o4;\nconst ISIG = 0o1;\nconst ICANON = 0o2;\nconst ECHO = 0o10;\nconst ECHOE = 0o20;\nconst ECHOCTL = 0o1000;\nconst NOFLSH = 0o200;\nconst IEXTEN = 0o100000;\nconst VINTR = 0;\nconst VQUIT = 1;\nconst VERASE = 2;\nconst VKILL = 3;\nconst VEOF = 4;\nconst VSUSP = 10;\nconst VWERASE = 14;\n\nexport function defaultTermios(): Termios {\n const cCc = new Array<number>(32).fill(0);\n Object.assign(cCc, { [VINTR]: 0x03, [VQUIT]: 0x1c, [VERASE]: 0x7f, [VKILL]: 0x15 });\n Object.assign(cCc, { [VEOF]: 0x04, 6: 1, 8: 0x11, 9: 0x13, [VSUSP]: 0x1a });\n Object.assign(cCc, { 12: 0x12, 13: 0x0f, [VWERASE]: 0x17, 15: 0x16 });\n return {\n c_iflag: ICRNL | 0o2000 | 0o20000 | IUTF8,\n c_oflag: OPOST | ONLCR,\n c_cflag: 0o17 | 0o60 | 0o200,\n c_lflag: ISIG | ICANON | ECHO | ECHOE | 0o40 | ECHOCTL | 0o4000 | IEXTEN,\n c_cc: cCc,\n };\n}\n\nconst encoder = new TextEncoder();\n\nfunction isContinuation(byte: number): boolean {\n return (byte & 0xc0) === 0x80;\n}\n\nexport class KernelTty {\n private termios = defaultTermios();\n private cols = 80;\n private rows = 24;\n\n private readable: Array<Uint8Array | null> = [];\n\n private line: number[] = [];\n private waiters: Array<() => void> = [];\n\n private hungUp = false;\n\n name?: string;\n\n owner?: Perm;\n\n onRead?: () => void;\n\n private readers = 0;\n\n private readonly screen: TtyScreen;\n\n private readonly signal: (sig: number) => void;\n\n constructor(\n screen: TtyScreen,\n\n signal: (sig: number) => void\n ) {\n this.screen = screen;\n\n this.signal = signal;\n }\n\n receive(bytes: Uint8Array): void {\n const { c_iflag, c_lflag } = this.termios;\n if (!(c_iflag & ICRNL) && !(c_lflag & (ISIG | ICANON | ECHO))) {\n if (bytes.length > 0) this.readable.push(bytes.slice());\n } else for (const byte of bytes) this.key(byte);\n this.wake();\n }\n\n resize(cols: number, rows: number): void {\n if (cols === this.cols && rows === this.rows) return;\n this.setSize(cols, rows);\n this.signal(SIG.WINCH);\n }\n\n hangup(): void {\n this.hungUp = true;\n this.wake();\n }\n\n signalHangup(): void {\n this.signal(SIG.HUP);\n }\n\n setSize(cols: number, rows: number): void {\n this.cols = cols;\n this.rows = rows;\n }\n\n tcgets(): Termios {\n return { ...this.termios, c_cc: [...this.termios.c_cc] };\n }\n\n tcsets(termios: Termios, flush = false): void {\n const wasCanonical = this.canonical;\n this.termios = { ...termios, c_cc: [...termios.c_cc] };\n if (flush) {\n this.line = [];\n this.readable = [];\n }\n\n if (wasCanonical && !this.canonical && this.line.length > 0) {\n this.readable.push(Uint8Array.from(this.line));\n this.line = [];\n this.wake();\n }\n }\n\n winsize(): [number, number] {\n return [this.rows, this.cols];\n }\n\n file(): OpenFile {\n return new OpenFile({\n read: (max, signal) => this.read(max, signal),\n write: async (bytes) => {\n if (this.hungUp) throw new KernelError('EIO');\n this.output(bytes);\n return bytes.length;\n },\n poll: (): PollState => ({\n readable: this.readable.length > 0 || this.hungUp,\n writable: true,\n hangup: this.hungUp,\n nread: this.readable.reduce((n, chunk) => n + (chunk?.length ?? 0), 0),\n }),\n changed: (signal) => this.changed(signal),\n close: () => {},\n tty: this,\n });\n }\n\n private get canonical(): boolean {\n return (this.termios.c_lflag & ICANON) !== 0;\n }\n\n private cc(slot: number): number {\n return this.termios.c_cc[slot] ?? 0;\n }\n\n private key(input: number): void {\n const { c_iflag, c_lflag } = this.termios;\n const byte = input === 0x0d && c_iflag & ICRNL ? 0x0a : input;\n if (c_lflag & ISIG && this.signalKey(byte)) return;\n if (!this.canonical) {\n this.readable.push(Uint8Array.of(byte));\n if (c_lflag & ECHO) this.echo(byte);\n return;\n }\n this.edit(byte);\n }\n\n private signalKey(byte: number): boolean {\n const sig =\n byte === this.cc(VINTR)\n ? SIG.INT\n : byte === this.cc(VQUIT)\n ? SIG.QUIT\n : byte === this.cc(VSUSP)\n ? SIG.TSTP\n : 0;\n if (!sig || byte === 0) return false;\n if (this.termios.c_lflag & ECHO) this.echo(byte);\n if (!(this.termios.c_lflag & NOFLSH)) {\n this.line = [];\n this.readable = [];\n }\n this.signal(sig);\n return true;\n }\n\n private edit(byte: number): void {\n const echo = (this.termios.c_lflag & ECHO) !== 0;\n if (byte === this.cc(VERASE) || byte === 0x08) {\n this.rubOut(this.lastCharLength());\n } else if (byte === this.cc(VKILL)) {\n this.rubOut(this.line.length);\n } else if (byte === this.cc(VWERASE)) {\n this.rubOut(this.lastWordLength());\n } else if (byte === this.cc(VEOF)) {\n this.readable.push(this.line.length > 0 ? Uint8Array.from(this.line) : null);\n this.line = [];\n } else if (byte === 0x0a) {\n this.line.push(byte);\n this.readable.push(Uint8Array.from(this.line));\n this.line = [];\n if (echo) this.output(encoder.encode('\\n'));\n } else {\n this.line.push(byte);\n if (echo) this.echo(byte);\n }\n }\n\n private lastWordLength(): number {\n let end = this.line.length;\n while (end > 0 && this.line[end - 1] === 0x20) end--;\n while (end > 0 && this.line[end - 1] !== 0x20) end--;\n return this.line.length - end;\n }\n\n private lastCharLength(): number {\n const { line } = this;\n let n = Math.min(1, line.length);\n if (this.termios.c_iflag & IUTF8) {\n while (n < line.length && isContinuation(line[line.length - n] ?? 0)) n++;\n }\n return n;\n }\n\n private rubOut(n: number): void {\n const dropped = this.line.splice(this.line.length - n, n);\n const utf8 = (this.termios.c_iflag & IUTF8) !== 0;\n const cells = utf8 ? dropped.filter((b) => !isContinuation(b)).length : dropped.length;\n if (cells > 0 && this.termios.c_lflag & ECHO) {\n this.output(encoder.encode('\\b \\b'.repeat(cells)), false);\n }\n }\n\n private echo(byte: number): void {\n if (byte < 0x20 && byte !== 0x0a && byte !== 0x09 && this.termios.c_lflag & ECHOCTL) {\n this.output(Uint8Array.of(0x5e, byte + 0x40), false);\n return;\n }\n this.output(Uint8Array.of(byte));\n }\n\n private output(bytes: Uint8Array, translate = true): void {\n const { c_oflag } = this.termios;\n if (!translate || !(c_oflag & OPOST && c_oflag & ONLCR) || !bytes.includes(0x0a)) {\n this.screen.write(bytes);\n return;\n }\n const out: number[] = [];\n for (const byte of bytes) {\n if (byte === 0x0a) out.push(0x0d);\n out.push(byte);\n }\n this.screen.write(Uint8Array.from(out));\n }\n\n get reading(): boolean {\n return this.readers > 0;\n }\n\n private async read(max: number, signal?: AbortSignal): Promise<Uint8Array> {\n this.onRead?.();\n this.readers++;\n try {\n return await this.take(max, signal);\n } finally {\n this.readers--;\n }\n }\n\n private async take(max: number, signal?: AbortSignal): Promise<Uint8Array> {\n while (this.readable.length === 0) {\n if (this.hungUp) return new Uint8Array(0);\n await this.changed(signal);\n }\n const head = this.readable[0];\n if (head === null) {\n this.readable.shift();\n return new Uint8Array(0);\n }\n if (head === undefined) return new Uint8Array(0);\n\n const chunks: Uint8Array[] = [];\n let n = 0;\n while (this.readable.length > 0 && n < max) {\n const next = this.readable[0];\n if (next === null || next === undefined) break;\n const take = next.subarray(0, max - n);\n chunks.push(take);\n n += take.length;\n if (take.length < next.length) this.readable[0] = next.subarray(take.length);\n else this.readable.shift();\n if (this.canonical) break;\n }\n const out = new Uint8Array(n);\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\n private changed(signal?: AbortSignal): Promise<void> {\n if (signal?.aborted) return Promise.reject(new KernelError('EINTR'));\n return new Promise((resolve, reject) => {\n const onAbort = (): void => {\n this.waiters = this.waiters.filter((w) => w !== waiter);\n reject(new KernelError('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 { permits, R_OK, W_OK } from '../fs/access.ts';\nimport { deny, type Guard } from '../fs/dac.ts';\nimport type { UsersMode } from '../fs/types.ts';\nimport { embedderFailure, interruptible, lineOf } from './embedder.ts';\nimport { KernelError, type OpenAccess, OpenFile, type PollState } from './fd-table.ts';\nimport {\n IOCTL,\n SERIAL_CFLAG,\n SERIAL_LFLAG,\n SERIAL_OFLAG,\n type SerialSettings,\n type SerialTermios,\n sameSettings,\n settingsOf,\n speedsOf,\n TIOCM,\n} from './serial-ioctl.ts';\nimport { defaultTermios, KernelTty, type Termios } from './tty.ts';\n\nexport const DEVICE_NAME = /^tty(USB|ACM)(\\d{1,3})$/;\nexport const BY_ID = '/dev/serial/by-id';\nconst LINK_NAME = /^[A-Za-z0-9._:+@=,-]{1,255}$/;\nconst MAJORS: Readonly<Record<string, number>> = { USB: 188, ACM: 166 };\nconst HIGH_WATER = 64 * 1024;\nconst CLOSING_WAIT_MS = 30_000;\nconst BREAK_MS = 250;\nconst MAX_ID = 4294967294;\nconst DEFAULT_SETTINGS = settingsOf(SERIAL_CFLAG, 9600);\n\nexport interface DeviceSignals {\n clearToSend: boolean;\n dataCarrierDetect: boolean;\n dataSetReady: boolean;\n ringIndicator: boolean;\n}\n\nexport interface DeviceStreams {\n readable: ReadableStream<Uint8Array>;\n writable: WritableStream<Uint8Array>;\n control(op: string, args?: object): unknown;\n}\n\nexport interface DeviceStamp {\n pid: number;\n uid: number;\n gid: number;\n groups: number[];\n users: UsersMode;\n tag?: string;\n tags?: string[];\n}\n\nexport interface DeviceOpenRequest {\n path: string;\n flags: number;\n stamp: DeviceStamp;\n signal: AbortSignal;\n}\n\nexport interface DeviceHook {\n open(request: DeviceOpenRequest): DeviceStreams | Promise<DeviceStreams>;\n}\n\nexport interface DeviceSpec {\n path: string;\n owner?: string | number;\n group?: string | number;\n mode?: number;\n links?: readonly string[];\n}\n\nexport interface DeviceNodeInfo {\n path: string;\n uid: number;\n gid: number;\n mode: number;\n major: number;\n minor: number;\n links: string[];\n atimeMs: number;\n mtimeMs: number;\n ctimeMs: number;\n}\n\nexport interface DeviceMetaChange {\n mode?: number;\n uid?: number;\n gid?: number;\n atimeMs?: number | null;\n mtimeMs?: number | null;\n now?: boolean;\n}\n\nexport interface DeviceLookup {\n userId(name: string): Promise<number | undefined>;\n groupId(name: string): Promise<number | undefined>;\n}\n\ninterface DeviceState {\n termios: Termios;\n ispeed: number;\n ospeed: number;\n}\n\ninterface DeviceNode extends DeviceNodeInfo {\n id: number;\n client: number;\n channel?: DeviceChannel;\n opening: boolean;\n saved?: DeviceState;\n}\n\nexport interface DeviceOpener {\n stamp: DeviceStamp;\n guard?: Guard;\n signal: AbortSignal;\n}\n\nfunction refused(code: 'EINVAL' | 'EEXIST' | 'ENOTSUP', text: string): Error & { code: string } {\n return Object.assign(new Error(`${code}: ${text}`), { code });\n}\n\nfunction invalid(what: string): Error {\n return refused('EINVAL', what);\n}\n\nfunction nodePath(path: unknown): { path: string; major: number; minor: number } {\n if (typeof path !== 'string') throw invalid('path must be a string');\n const name = path.startsWith('/dev/') ? path.slice(5) : path;\n const m = DEVICE_NAME.exec(name);\n const minor = Number(m?.[2]);\n if (!m || minor > 255) throw invalid(`not a serial device name: ${path}`);\n return { path: `/dev/${name}`, major: MAJORS[m[1] as string] as number, minor };\n}\n\nfunction linkPath(link: unknown): string {\n if (typeof link !== 'string') throw invalid('a link must be a string');\n const name = link.startsWith(`${BY_ID}/`) ? link.slice(BY_ID.length + 1) : link;\n if (!LINK_NAME.test(name) || name === '.' || name === '..')\n throw invalid(`not a link name: ${link}`);\n return `${BY_ID}/${name}`;\n}\n\nfunction modeOf(mode: unknown): number {\n if (mode === undefined) return 0o600;\n if (!Number.isInteger(mode) || (mode as number) < 0 || (mode as number) > 0o7777)\n throw invalid('mode must be permission bits');\n return mode as number;\n}\n\nasync function idOf(\n value: string | number | undefined,\n find: (name: string) => Promise<number | undefined>\n): Promise<number> {\n if (value === undefined) return 0;\n if (typeof value === 'number') {\n if (!Number.isInteger(value) || value < 0 || value > MAX_ID) throw invalid(`bad id ${value}`);\n return value;\n }\n const id = typeof value === 'string' ? await find(value) : undefined;\n if (id === undefined) throw invalid(`unknown owner or group ${String(value)}`);\n return id;\n}\n\nfunction quiet(): undefined {\n return undefined;\n}\n\nfunction want(access: OpenAccess): number {\n return access === 'read' ? R_OK : access === 'write' ? W_OK : R_OK | W_OK;\n}\n\nexport function devicesHook(hook: DeviceHook): DeviceHook {\n if (typeof hook?.open !== 'function') throw new TypeError('devices needs open');\n return { open: (request) => hook.open(request) };\n}\n\nfunction checkMeta(\n node: DeviceNode,\n change: DeviceMetaChange,\n uid: number,\n gid: number,\n guard: Guard\n): void {\n const { cred } = guard;\n const owner = cred.euid === 0 || cred.euid === node.uid;\n const member = cred.egid === gid || cred.groups.includes(gid);\n const chown = uid !== node.uid || gid !== node.gid;\n const times = (change.atimeMs ?? change.mtimeMs ?? null) !== null;\n if (change.mode !== undefined && !owner) deny(guard, 'chmod', node.path, 'EPERM');\n if (chown && cred.euid !== 0 && (uid !== node.uid || !owner || !member))\n deny(guard, 'chown', node.path, 'EPERM');\n if (times && !owner && !(change.now && permits(cred, node, W_OK, false)))\n deny(guard, 'utimes', node.path, change.now ? 'EACCES' : 'EPERM');\n}\n\nexport class DeviceNodes {\n private readonly hooks = new Map<number, DeviceHook>();\n private readonly nodes = new Map<string, DeviceNode>();\n private readonly links = new Map<string, DeviceNode>();\n private readonly lookup: DeviceLookup;\n readonly users: UsersMode;\n private next = 0;\n\n constructor(users: UsersMode, lookup: DeviceLookup) {\n this.users = users;\n this.lookup = lookup;\n }\n\n register(client: number, hook: DeviceHook): () => void {\n this.hooks.set(client, hook);\n return () => {\n if (this.hooks.get(client) !== hook) return;\n this.hooks.delete(client);\n for (const node of [...this.nodes.values()]) if (node.client === client) this.drop(node);\n };\n }\n\n async add(spec: DeviceSpec, client: number): Promise<number> {\n if (typeof spec !== 'object' || spec === null) throw invalid('add needs a spec');\n const { path, major, minor } = nodePath(spec.path);\n const mode = modeOf(spec.mode);\n if (spec.links !== undefined && !Array.isArray(spec.links))\n throw invalid('links must be a list');\n const links = (spec.links ?? []).map(linkPath);\n const uid = await idOf(spec.owner, (name) => this.lookup.userId(name));\n const gid = await idOf(spec.group, (name) => this.lookup.groupId(name));\n if (!this.hooks.has(client)) throw refused('ENOTSUP', 'this client has no devices hook');\n if (this.nodes.has(path)) throw refused('EEXIST', `${path} exists`);\n const taken = links.find((l, i) => this.links.has(l) || links.indexOf(l) !== i);\n if (taken !== undefined) throw refused('EEXIST', `${taken} exists`);\n const node: DeviceNode = {\n id: ++this.next,\n client,\n path,\n uid,\n gid,\n mode,\n major,\n minor,\n links,\n opening: false,\n atimeMs: Date.now(),\n mtimeMs: Date.now(),\n ctimeMs: Date.now(),\n };\n this.nodes.set(path, node);\n for (const link of links) this.links.set(link, node);\n return node.id;\n }\n\n remove(id: number): boolean {\n const node = [...this.nodes.values()].find((n) => n.id === id);\n if (!node) return false;\n this.drop(node);\n return true;\n }\n\n private drop(node: DeviceNode): void {\n this.nodes.delete(node.path);\n for (const link of node.links) this.links.delete(link);\n node.channel?.lost(new KernelError('EIO', `${node.path} was removed`));\n }\n\n list(): DeviceNodeInfo[] {\n return [...this.nodes.values()]\n .sort((a, b) => (a.path < b.path ? -1 : 1))\n .map(({ path, uid, gid, mode, major, minor, links, atimeMs, mtimeMs, ctimeMs }) => ({\n path,\n uid,\n gid,\n mode,\n major,\n minor,\n links: [...links],\n atimeMs,\n mtimeMs,\n ctimeMs,\n }));\n }\n\n meta(path: string, change: DeviceMetaChange, guard?: Guard): void {\n const node = this.find(path);\n if (!node) throw new KernelError('ENOENT');\n const uid = change.uid === undefined || change.uid === -1 ? node.uid : change.uid >>> 0;\n const gid = change.gid === undefined || change.gid === -1 ? node.gid : change.gid >>> 0;\n if (guard) checkMeta(node, change, uid, gid, guard);\n const now = Date.now();\n if (change.mode !== undefined) node.mode = change.mode & 0o7777;\n node.uid = uid;\n node.gid = gid;\n const at = (ms: number | null | undefined, kept: number): number =>\n ms === undefined || ms === null ? kept : change.now ? now : ms;\n node.atimeMs = at(change.atimeMs, node.atimeMs);\n node.mtimeMs = at(change.mtimeMs, node.mtimeMs);\n node.ctimeMs = now;\n if (node.channel) node.channel.tty.owner = { uid: node.uid, gid: node.gid, mode: node.mode };\n }\n\n find(path: string): DeviceNode | undefined {\n return this.nodes.get(path) ?? this.links.get(path);\n }\n\n openTty(path: string): KernelTty | undefined {\n return this.nodes.get(path)?.channel?.tty;\n }\n\n async open(path: string, flags: number, opener: DeviceOpener): Promise<OpenFile> {\n const node = this.find(path);\n if (!node) throw new KernelError('ENOENT');\n const access: OpenAccess = (flags & 3) === 0 ? 'read' : (flags & 3) === 1 ? 'write' : 'both';\n if (opener.guard && !permits(opener.guard.cred, node, want(access), false))\n deny(opener.guard, 'open', node.path);\n if (node.channel || node.opening) throw new KernelError('EBUSY');\n const hook = this.hooks.get(node.client) as DeviceHook;\n node.opening = true;\n const asked = Promise.resolve().then(() =>\n hook.open({ path: node.path, flags: flags & 3, stamp: opener.stamp, signal: opener.signal })\n );\n let streams: DeviceStreams;\n try {\n streams = await interruptible(asked, opener.signal);\n } catch (err) {\n if (err instanceof KernelError && err.code === 'EINTR') {\n void asked.then(abandon, quiet).finally(() => (node.opening = false));\n } else node.opening = false;\n throw embedderFailure(err);\n }\n node.opening = false;\n if (!isStreams(streams)) throw new KernelError('EIO', 'the devices hook gave no streams');\n if (this.nodes.get(node.path) !== node) {\n void abandon(streams);\n throw new KernelError('ENOENT');\n }\n const channel = new DeviceChannel(node.path, streams, node.saved, (saved) => {\n node.saved = saved;\n if (node.channel === channel) delete node.channel;\n });\n channel.tty.owner = { uid: node.uid, gid: node.gid, mode: node.mode };\n node.channel = channel;\n try {\n await channel.restore();\n } catch (err) {\n await channel.close();\n throw err;\n }\n return channel.file(access);\n }\n}\n\nfunction isStreams(value: unknown): value is DeviceStreams {\n const s = value as Partial<DeviceStreams> | null;\n return (\n !!s &&\n s.readable instanceof ReadableStream &&\n s.writable instanceof WritableStream &&\n typeof s.control === 'function'\n );\n}\n\nasync function abandon(streams: DeviceStreams): Promise<void> {\n if (!isStreams(streams)) return;\n await streams.readable.cancel('closed').catch(quiet);\n await streams.writable.abort('closed').catch(quiet);\n await Promise.resolve()\n .then(() => streams.control('close'))\n .catch(quiet);\n}\n\nfunction serialTermios(): SerialTermios {\n const base = defaultTermios();\n return {\n c_iflag: 0,\n c_oflag: SERIAL_OFLAG,\n c_cflag: SERIAL_CFLAG,\n c_lflag: SERIAL_LFLAG,\n c_cc: base.c_cc,\n };\n}\n\nfunction sleep(ms: number, signal?: AbortSignal): Promise<void> {\n return interruptible(new Promise<void>((resolve) => setTimeout(resolve, ms)), signal);\n}\n\nexport class DeviceChannel {\n readonly tty: KernelTty;\n readonly path: string;\n private readonly inner: OpenFile;\n private readonly reader: ReadableStreamDefaultReader<Uint8Array>;\n private readonly writer: WritableStreamDefaultWriter<Uint8Array>;\n private readonly streams: DeviceStreams;\n private readonly onClosed: (state: DeviceState) => void;\n private readonly gone = Promise.withResolvers<never>();\n private failure: KernelError | undefined;\n private readonly pending = new Set<Promise<void>>();\n private queued = 0;\n private resume: (() => void) | undefined;\n private waiters: Array<() => void> = [];\n private closed = false;\n ispeed = 9600;\n ospeed = 9600;\n dtr = true;\n rts = true;\n\n constructor(\n path: string,\n streams: DeviceStreams,\n saved: DeviceState | undefined,\n onClosed: (state: DeviceState) => void\n ) {\n this.path = path;\n this.streams = streams;\n this.onClosed = onClosed;\n this.gone.promise.catch(quiet);\n this.tty = new KernelTty({ write: (bytes) => this.send(bytes) }, quiet);\n this.tty.name = path;\n this.tty.setSize(0, 0);\n this.tty.tcsets(saved?.termios ?? serialTermios());\n if (saved) {\n this.ispeed = saved.ispeed;\n this.ospeed = saved.ospeed;\n this.dtr = this.rts = saved.ospeed !== 0;\n }\n this.inner = this.tty.file();\n this.reader = streams.readable.getReader();\n this.writer = streams.writable.getWriter();\n void this.pump();\n }\n\n file(access: OpenAccess): OpenFile {\n return new OpenFile({\n ...(access === 'write' ? {} : { read: (max, signal) => this.read(max, signal) }),\n ...(access === 'read' ? {} : { write: (bytes, signal) => this.write(bytes, signal) }),\n poll: () => this.poll(),\n changed: (signal) => this.changed(signal),\n close: () => this.close(),\n tty: this.tty,\n device: this,\n });\n }\n\n lost(err: KernelError): void {\n if (this.failure) return;\n this.failure = err;\n this.gone.reject(err);\n this.tty.hangup();\n this.wake();\n }\n\n private control(op: string, args?: object): Promise<unknown> {\n return Promise.resolve().then(() => this.streams.control(op, args));\n }\n\n private buffered(): number {\n return this.inner.file.poll?.().nread ?? 0;\n }\n\n private async pump(): Promise<void> {\n for (;;) {\n while (this.buffered() >= HIGH_WATER && !this.closed && !this.failure) {\n await new Promise<void>((resolve) => {\n this.resume = resolve;\n });\n }\n if (this.closed || this.failure) return;\n let got: ReadableStreamReadResult<Uint8Array>;\n try {\n got = await this.reader.read();\n } catch (err) {\n if (!this.closed) this.lost(new KernelError('EIO', lineOf(err)));\n return;\n }\n if (got.done) {\n this.tty.hangup();\n this.wake();\n return;\n }\n this.tty.receive(got.value);\n this.wake();\n }\n }\n\n private send(bytes: Uint8Array): void {\n if (this.closed || this.failure) return;\n const n = bytes.length;\n this.queued += n;\n const sent = this.writer.write(bytes.slice()).catch((err: unknown) => {\n this.lost(new KernelError('EIO', lineOf(err)));\n });\n const tracked = sent.finally(() => {\n this.queued -= n;\n this.pending.delete(tracked);\n this.wake();\n });\n this.pending.add(tracked);\n }\n\n private check(): void {\n if (this.failure) throw this.failure;\n }\n\n private async read(max: number, signal?: AbortSignal): Promise<Uint8Array> {\n this.check();\n const read = this.inner.file.read as NonNullable<OpenFile['file']['read']>;\n const got = await read(max, signal);\n this.resume?.();\n this.resume = undefined;\n if (got.length === 0) this.check();\n return got;\n }\n\n private async ready(signal?: AbortSignal): Promise<void> {\n this.check();\n try {\n await interruptible(Promise.race([this.writer.ready, this.gone.promise]), signal);\n } catch (err) {\n if (err instanceof KernelError) throw err;\n throw new KernelError('EIO', lineOf(err));\n }\n }\n\n private async write(bytes: Uint8Array, signal?: AbortSignal): Promise<number> {\n this.check();\n if (!((this.writer.desiredSize ?? 0) > 0)) await this.ready(signal);\n const write = this.inner.file.write as NonNullable<OpenFile['file']['write']>;\n return write(bytes, signal);\n }\n\n private poll(): PollState {\n if (this.failure)\n return { readable: true, writable: true, hangup: true, error: true, nread: 0 };\n const inner = this.inner.file.poll?.() as PollState;\n const writable = (this.writer.desiredSize ?? 0) > 0;\n return { ...inner, writable };\n }\n\n private changed(signal?: AbortSignal): Promise<void> {\n const mine = new Promise<void>((resolve) => this.waiters.push(resolve));\n const theirs = this.inner.file.changed?.(signal) as Promise<void>;\n return interruptible(Promise.race([mine, theirs]), signal);\n }\n\n private wake(): void {\n const waiters = this.waiters;\n this.waiters = [];\n for (const resolve of waiters) resolve();\n }\n\n async drain(signal?: AbortSignal): Promise<void> {\n while (this.pending.size > 0) {\n this.check();\n await interruptible(\n Promise.race([Promise.all([...this.pending]), this.gone.promise]),\n signal\n );\n }\n this.check();\n }\n\n async restore(): Promise<void> {\n const settings = this.settings();\n if (settings.baudRate === 0)\n return this.signals({ dataTerminalReady: false, requestToSend: false });\n if (sameSettings(settings, DEFAULT_SETTINGS)) return;\n try {\n await this.control('configure', settings);\n } catch (err) {\n throw embedderFailure(err);\n }\n }\n\n settings(): SerialSettings {\n return settingsOf(this.tty.tcgets().c_cflag, this.ospeed);\n }\n\n termios(): SerialTermios {\n return { ...this.tty.tcgets(), c_ispeed: this.ispeed, c_ospeed: this.ospeed };\n }\n\n async setTermios(\n termios: SerialTermios,\n how: { drain?: boolean; flush?: boolean; extended?: boolean },\n signal?: AbortSignal\n ): Promise<void> {\n this.check();\n if (how.drain) await this.drain(signal);\n const before = this.settings();\n const old = { termios: this.tty.tcgets(), ispeed: this.ispeed, ospeed: this.ospeed };\n const speeds = speedsOf(termios, this, how.extended === true);\n this.tty.tcsets(termios, how.flush === true);\n this.ispeed = speeds.ispeed;\n this.ospeed = speeds.ospeed;\n try {\n if (speeds.ospeed === 0) await this.setModem(this.bits() & ~(TIOCM.DTR | TIOCM.RTS));\n else {\n if (!sameSettings(before, this.settings()))\n await this.control('configure', this.settings());\n if (old.ospeed === 0) await this.setModem(this.bits() | TIOCM.DTR | TIOCM.RTS);\n }\n if (how.flush) await this.control('flush', { input: true, output: false });\n } catch (err) {\n this.tty.tcsets(old.termios);\n this.ispeed = old.ispeed;\n this.ospeed = old.ospeed;\n throw embedderFailure(err);\n }\n }\n\n private bits(): number {\n return (this.dtr ? TIOCM.DTR : 0) | (this.rts ? TIOCM.RTS : 0);\n }\n\n async modem(): Promise<number> {\n this.check();\n const s = (await this.control('signals').catch((err: unknown) => {\n throw embedderFailure(err);\n })) as Partial<DeviceSignals> | null;\n return (\n this.bits() |\n (s?.clearToSend ? TIOCM.CTS : 0) |\n (s?.dataSetReady ? TIOCM.DSR : 0) |\n (s?.dataCarrierDetect ? TIOCM.CD : 0) |\n (s?.ringIndicator ? TIOCM.RI : 0)\n );\n }\n\n async setModem(bits: number): Promise<void> {\n this.check();\n const dataTerminalReady = (bits & TIOCM.DTR) !== 0;\n const requestToSend = (bits & TIOCM.RTS) !== 0;\n await this.signals({ dataTerminalReady, requestToSend });\n this.dtr = dataTerminalReady;\n this.rts = requestToSend;\n }\n\n private async signals(args: object): Promise<void> {\n try {\n await this.control('setSignals', args);\n } catch (err) {\n throw embedderFailure(err);\n }\n }\n\n async sendBreak(ms: number, signal?: AbortSignal): Promise<void> {\n await this.drain(signal);\n await this.signals({ break: true });\n try {\n await sleep(ms, signal);\n } finally {\n await this.signals({ break: false });\n }\n }\n\n async flush(input: boolean, output: boolean): Promise<void> {\n this.check();\n if (input) this.tty.tcsets(this.tty.tcgets(), true);\n try {\n await this.control('flush', { input, output });\n } catch (err) {\n throw embedderFailure(err);\n }\n }\n\n async ioctl(request: number, arg: unknown, signal?: AbortSignal): Promise<unknown> {\n this.check();\n switch (request) {\n case IOCTL.TCGETS:\n case IOCTL.TCGETS2:\n return this.termios();\n case IOCTL.TCSETS:\n case IOCTL.TCSETSW:\n case IOCTL.TCSETSF:\n case IOCTL.TCSETS2:\n case IOCTL.TCSETSW2:\n case IOCTL.TCSETSF2: {\n const extended = request > 0xffff;\n const kind = (request & 0xff) - (extended ? 0x2b : 0x02);\n await this.setTermios(\n arg as SerialTermios,\n { drain: kind > 0, flush: kind === 2, extended },\n signal\n );\n return null;\n }\n case IOCTL.TIOCMGET:\n return this.modem();\n case IOCTL.TIOCMSET:\n await this.setModem(Number(arg));\n return null;\n case IOCTL.TIOCMBIS:\n await this.setModem(this.bits() | Number(arg));\n return null;\n case IOCTL.TIOCMBIC:\n await this.setModem(this.bits() & ~Number(arg));\n return null;\n case IOCTL.TIOCSBRK:\n case IOCTL.TIOCCBRK:\n await this.signals({ break: request === IOCTL.TIOCSBRK });\n return null;\n case IOCTL.TCSBRK:\n if (Number(arg) === 0) await this.sendBreak(BREAK_MS, signal);\n else await this.drain(signal);\n return null;\n case IOCTL.TCSBRKP:\n await this.sendBreak(Number(arg) > 0 ? Number(arg) * 100 : BREAK_MS, signal);\n return null;\n case IOCTL.TCFLSH: {\n const queue = Number(arg);\n if (queue < 0 || queue > 2) throw new KernelError('EINVAL');\n await this.flush(queue !== 1, queue !== 0);\n return null;\n }\n case IOCTL.FIONREAD:\n return this.buffered();\n case IOCTL.TIOCOUTQ:\n return this.queued;\n case IOCTL.TIOCEXCL:\n case IOCTL.TIOCNXCL:\n return null;\n case IOCTL.TIOCGWINSZ: {\n const [rows, cols] = this.tty.winsize();\n return { rows, cols };\n }\n case IOCTL.TIOCSWINSZ: {\n const size = arg as { rows: number; cols: number };\n this.tty.setSize(Number(size?.cols) & 0xffff, Number(size?.rows) & 0xffff);\n return null;\n }\n case IOCTL.TIOCSCTTY:\n throw new KernelError('EPERM');\n default:\n throw new KernelError('ENOTTY');\n }\n }\n\n async close(): Promise<void> {\n if (this.closed) return;\n try {\n if (!this.failure) {\n await interruptible(this.drain(), AbortSignal.timeout(CLOSING_WAIT_MS)).catch(quiet);\n }\n this.closed = true;\n this.resume?.();\n this.wake();\n await this.reader.cancel('closed').catch(quiet);\n this.reader.releaseLock();\n await this.writer.abort('closed').catch(quiet);\n this.writer.releaseLock();\n await this.control('close').catch(quiet);\n } finally {\n this.closed = true;\n this.onClosed({ termios: this.tty.tcgets(), ispeed: this.ispeed, ospeed: this.ospeed });\n }\n }\n}\n", "import type { SealedCaller } from '../sealed.ts';\n\nexport const FORBIDDEN_HEADER = 'forbidden-header';\n\nexport type HeaderList = ReadonlyArray<readonly [name: string, value: string]>;\nexport type RealmRedirectPolicy = 'follow' | 'manual' | 'error';\nexport interface RealmTransportRequest {\n url: string;\n method: string;\n headers: HeaderList;\n body?: Uint8Array;\n bodyStream?: AsyncIterable<Uint8Array>;\n redirect?: RealmRedirectPolicy;\n signal: AbortSignal;\n}\nexport interface RealmRedirectHop {\n status: number;\n url: string;\n headers: HeaderList;\n}\nexport interface RealmTransportResponse {\n url?: string;\n redirected?: boolean;\n redirects?: readonly RealmRedirectHop[];\n opaqueRedirect?: true;\n status: number;\n statusText: string;\n headers: HeaderList;\n body: AsyncIterable<Uint8Array>;\n cancel(): Promise<void>;\n}\nexport interface RealmTransportExit {\n kind: 'local' | 'remote' | 'tailnet' | (string & {});\n caps: readonly string[];\n [detail: string]: unknown;\n}\nexport interface RealmTransportTraits {\n manualRedirects: boolean;\n encodedBodies: boolean;\n maxRequestBody: number;\n crossOrigin?: 'cors' | 'any';\n unavailable?: true;\n websocket?: true;\n streamingBodies?: true;\n redirectHops?: true;\n redirectPolicy?: true;\n exit?: RealmTransportExit;\n [trait: string]: unknown;\n}\nexport interface RealmWebSocketRequest {\n url: string;\n protocols: string[];\n headers: HeaderList;\n signal: AbortSignal;\n}\nexport interface RealmWebSocketClose {\n code: number;\n reason: string;\n wasClean?: boolean;\n}\nexport type RealmWebSocketMessage = string | Uint8Array;\nexport interface RealmWebSocket {\n readonly protocol: string;\n readonly buffered: number;\n send(data: RealmWebSocketMessage): void;\n readonly messages: AsyncIterable<RealmWebSocketMessage>;\n close(code?: number, reason?: string): void;\n readonly closed: Promise<RealmWebSocketClose>;\n}\nexport interface RealmTransport {\n readonly traits: RealmTransportTraits;\n fetch(\n request: RealmTransportRequest,\n owner?: number,\n stamp?: SealedCaller\n ): Promise<RealmTransportResponse>;\n websocket?(request: RealmWebSocketRequest): Promise<RealmWebSocket>;\n}\n", "import type { RealmWebSocketClose, RealmWebSocketMessage } from './transport.ts';\n\nexport const INBOUND_LIMIT = 16 * 1024 * 1024;\nexport const MESSAGE_LIMIT = 64 * 1024 * 1024;\nexport const TOO_BIG = 1009;\n\nexport function payloadSize(message: RealmWebSocketMessage): number {\n return typeof message === 'string' ? new TextEncoder().encode(message).length : message.length;\n}\n\nexport class MessageQueue implements AsyncIterable<RealmWebSocketMessage> {\n private readonly items: RealmWebSocketMessage[] = [];\n private readonly limit: number;\n private waiter: (() => void) | undefined;\n private size = 0;\n private ended = false;\n private readonly overflow: () => void;\n private readonly taken: ((n: number) => void) | undefined;\n readonly closed: Promise<RealmWebSocketClose>;\n private settle!: (close: RealmWebSocketClose) => void;\n\n constructor(overflow: () => void, limit = INBOUND_LIMIT, taken?: (n: number) => void) {\n this.overflow = overflow;\n this.limit = limit;\n this.taken = taken;\n this.closed = new Promise((resolve) => {\n this.settle = resolve;\n });\n }\n\n push(message: RealmWebSocketMessage): void {\n if (this.ended) return;\n const size = payloadSize(message);\n const huge = size > MESSAGE_LIMIT;\n if (huge || (this.items.length > 0 && this.size + size > this.limit)) {\n const reason = huge\n ? `a message is over ${MESSAGE_LIMIT} bytes`\n : `over ${this.limit} bytes of messages are waiting`;\n this.end({ code: TOO_BIG, reason });\n this.overflow();\n return;\n }\n this.size += size;\n this.items.push(message);\n this.wake();\n }\n\n end(close: RealmWebSocketClose): void {\n if (this.ended) return;\n this.ended = true;\n this.settle(close);\n this.wake();\n }\n\n private wake(): void {\n const waiter = this.waiter;\n this.waiter = undefined;\n waiter?.();\n }\n\n async *[Symbol.asyncIterator](): AsyncIterator<RealmWebSocketMessage> {\n for (;;) {\n const next = this.items.shift();\n if (next !== undefined) {\n const n = payloadSize(next);\n this.size -= n;\n this.taken?.(n);\n yield next;\n continue;\n }\n if (this.ended) return;\n await new Promise<void>((resolve) => {\n this.waiter = resolve;\n });\n }\n }\n}\n", "import type { SealedCaller } from '../sealed.ts';\nimport {\n FORBIDDEN_HEADER,\n type HeaderList,\n type RealmRedirectHop,\n type RealmRedirectPolicy,\n type RealmTransport,\n type RealmTransportRequest,\n type RealmTransportResponse,\n type RealmTransportTraits,\n type RealmWebSocket,\n type RealmWebSocketMessage,\n type 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' | typeof FORBIDDEN_HEADER;\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' | typeof FORBIDDEN_HEADER | 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 === FORBIDDEN_HEADER ? 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", "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", "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 { TraceEvent } from '../kernel/trace.ts';\nimport type { MountSpec } from '../mount/mount-fs.ts';\n\nexport const PROTOCOL: readonly [number, number] = [1, 18];\n\nexport interface ClientHello {\n protocol: readonly [number, number];\n lock?: string;\n requests?: Record<string, { group?: string; users?: Array<string | number> }>;\n devices?: true;\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 cwdMissing?: 'create' | 'error';\n user?: string | number;\n env?: Record<string, string>;\n stdin?: Uint8Array;\n pgid?: number;\n tag?: string | readonly string[];\n}\n\nexport interface TerminalRequestOptions {\n cwd?: string;\n cwdMissing?: 'create' | 'error';\n user?: string | number;\n env?: Record<string, string>;\n cols?: number;\n rows?: number;\n tag?: string | readonly string[];\n}\n\nexport interface SudoRunRequestOptions {\n stdout?: string;\n stderr?: string;\n tag?: string | readonly 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: 'trace'; tag: string; limit?: number }\n | { op: 'untrace'; trace: number }\n | { op: 'sudo-run'; replay: unknown; options: SudoRunRequestOptions }\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 interface TraceAck {\n traceAck: number;\n}\n\nexport type ClientMessage = { hello: ClientHello } | ClientRequest | TransportCall | TraceAck;\n\nexport interface WatchEvent {\n watch: number;\n change: WatchChange;\n}\n\nexport interface TraceMessage {\n trace: number;\n events: TraceEvent[];\n dropped?: number;\n}\n\nexport type KernelMessage =\n | { hello: KernelHello }\n | ClientReply\n | WatchEvent\n | TraceMessage\n | 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 { devicesAnswerer } from '../devices-relay.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 DeviceHook, devicesHook } from '../kernel/devices.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 { TraceEvent } from '../kernel/trace.ts';\nimport type { MountEntry, MountSpec } from '../mount/mount-fs.ts';\nimport type { SudoReplay } from '../sudo.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 { TraceEvent, TraceExec, TraceExit, TraceFork } from '../kernel/trace.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 devices?: DeviceHook;\n}\n\nexport interface SpawnOptions {\n cwd?: string;\n cwdMissing?: 'create' | 'error';\n user?: string | number;\n env?: Record<string, string>;\n stdin?: string | Uint8Array;\n group?: 'new';\n pgid?: number;\n tag?: string | readonly 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 SudoRunOptions {\n stdout?: string;\n stderr?: string;\n tag?: string | readonly string[];\n}\n\nexport interface SudoRun {\n readonly pid: number;\n readonly pgid: number;\n readonly ended: Promise<ClientEnded>;\n}\n\nexport interface ClientRunOptions {\n cwd?: string;\n cwdMissing?: 'create' | 'error';\n user?: string | number;\n env?: Record<string, string>;\n stdin?: string | Uint8Array;\n tag?: string | readonly 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 cwdMissing?: 'create' | 'error';\n user?: string | number;\n env?: Record<string, string>;\n cols?: number;\n rows?: number;\n tag?: string | readonly 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 interface TraceBatch {\n events: TraceEvent[];\n dropped: number;\n}\n\nexport interface TraceOptions {\n limit?: number;\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 trace(\n tag: string,\n onEvents: (batch: TraceBatch) => void | Promise<unknown>,\n options?: TraceOptions\n ): Promise<{ close(): void }>;\n sudoRun(request: SudoReplay, options?: SudoRunOptions): Promise<SudoRun>;\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 tracing = new Map<number, (batch: TraceBatch) => unknown>();\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 devices: { 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 trace?: number;\n events?: TraceEvent[];\n dropped?: number;\n id?: number;\n }): void {\n if (this.requests?.handle(data)) return;\n if (this.devices?.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.trace !== undefined && data.id === undefined) {\n this.traced(data.trace, data.events ?? [], data.dropped ?? 0);\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 traced(trace: number, events: TraceEvent[], dropped: number): void {\n const listener = this.tracing.get(trace);\n if (!listener) return;\n const ack = () => {\n if (this.tracing.has(trace)) this.post({ traceAck: trace });\n };\n let consumed: unknown;\n try {\n consumed = listener({ events, dropped });\n } finally {\n if (typeof (consumed as PromiseLike<unknown> | undefined)?.then === 'function') {\n void Promise.resolve(consumed).then(ack, ack);\n } else {\n ack();\n }\n }\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 traceOn(\n channel: Channel,\n tag: string,\n onEvents: (batch: TraceBatch) => unknown,\n options: TraceOptions\n): Promise<{ close(): void }> {\n if (typeof onEvents !== 'function') throw new TypeError('trace: onEvents must be a function');\n await since(channel, 15, 'trace', async () => {});\n const { id, done } = channel.request({\n op: 'trace',\n tag,\n ...(options.limit !== undefined ? { limit: options.limit } : {}),\n });\n channel.tracing.set(id, onEvents);\n try {\n await done;\n } catch (error) {\n channel.tracing.delete(id);\n throw error;\n }\n return {\n close: () => {\n if (!channel.tracing.delete(id)) return;\n void channel.call({ op: 'untrace', trace: 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 if (Array.isArray(opts.tag)) await since(channel, 15, 'several tags per spawn', async () => {});\n if (opts.cwdMissing === 'error') await since(channel, 14, \"cwdMissing: 'error'\", 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\nasync function sudoRunOn(\n channel: Channel,\n replay: SudoReplay,\n { stdout, stderr, tag }: SudoRunOptions\n): Promise<SudoRun> {\n await since(channel, 16, 'sudoRun', async () => {});\n const started = Promise.withResolvers<number>();\n let endedBy: string | undefined;\n const { done } = channel.request(\n { op: 'sudo-run', replay, options: { stdout, stderr, tag } },\n { started: started.resolve, ended: (signal) => (endedBy = signal) }\n );\n done.catch(started.reject);\n const pid = await started.promise;\n return { pid, pgid: pid, ended: endedOf(done, () => endedBy) };\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 if (Array.isArray(opts.tag)) {\n await since(channel, 15, 'several tags per terminal', async () => {});\n }\n if (opts.cwdMissing === 'error') await since(channel, 14, \"cwdMissing: 'error'\", 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 devices?: boolean\n): Promise<KernelHello> {\n channel.post({\n hello: {\n protocol: PROTOCOL,\n ...(lock ? { lock } : {}),\n ...(requests ? { requests } : {}),\n ...(devices ? { devices: true } : {}),\n },\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 devices = options.devices ? devicesHook(options.devices) : undefined;\n if (devices) channel.devices = devicesAnswerer(port, () => devices);\n const hello = await greet(\n channel,\n own.name,\n options.timeoutMs ?? 10_000,\n requests ? kindsOf(requests) : undefined,\n devices !== 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 trace: (tag, onEvents, options = {}) => traceOn(channel, tag, onEvents, options),\n sudoRun: (replay, options = {}) => sudoRunOn(channel, replay, options),\n async close(o = {}) {\n if (channel.failure) return;\n await channel\n .call({ op: 'detach', ...(o.kill ? { kill: true } : {}) })\n .catch(() => undefined);\n channel.end(new KernelGoneError('this client is closed'));\n },\n };\n}\n", "export const DRIVER_PROTOCOL: readonly [number, number] = [1, 3];\n\nexport interface DriverCapabilities {\n readonly?: boolean;\n symlinks?: boolean;\n links?: boolean;\n fifos?: boolean;\n chmod?: boolean;\n owners?: boolean;\n linkTimes?: boolean;\n ranges?: boolean;\n sessions?: boolean;\n listingStats?: boolean;\n caseInsensitive?: boolean;\n normalization?: 'none' | 'nfc' | 'nfd-insensitive';\n maxIo?: number;\n maxFile?: number;\n attrTtl?: number;\n entryTtl?: number;\n}\n\nexport interface DriverAttr {\n kind: 'file' | 'directory' | 'symlink' | 'fifo';\n size: number;\n mtime: number;\n atime?: number;\n mode?: number;\n ino?: number;\n nlink?: number;\n etag?: string;\n uid?: number;\n gid?: number;\n}\n\nexport interface DriverOwner {\n uid?: number;\n gid?: number;\n mode?: number;\n}\n\nexport interface DriverEntry {\n name: string;\n kind: DriverAttr['kind'];\n attr?: DriverAttr;\n}\n\nexport interface DriverStatfs {\n bsize: number;\n blocks: number;\n bfree: number;\n}\n\nexport interface MountRequestInfo {\n source: string;\n options: Record<string, string>;\n}\n\nexport type DriverCall =\n | { op: 'getattr'; path: string }\n | { op: 'readdir'; path: string }\n | ({\n op: 'open';\n path: string;\n write: boolean;\n create: boolean;\n truncate: boolean;\n exclusive: boolean;\n ifMatch?: string;\n } & DriverOwner)\n | { op: 'read'; fh: number; offset: number; size: number }\n | { op: 'write'; fh: number; offset: number; bytes: Uint8Array }\n | { op: 'release'; fh: number }\n | ({ op: 'mkdir'; path: string } & DriverOwner)\n | { op: 'rmdir'; path: string }\n | { op: 'unlink'; path: string }\n | { op: 'rename'; from: string; to: string }\n | { op: 'link'; from: string; to: string }\n | ({ op: 'symlink'; target: string; path: string } & DriverOwner)\n | ({ op: 'mkfifo'; path: string } & DriverOwner)\n | { op: 'readlink'; path: string }\n | {\n op: 'setattr';\n path: string;\n mode?: number;\n mtime?: number;\n atime?: number;\n size?: number;\n uid?: number;\n gid?: number;\n }\n | { op: 'statfs' };\n\nexport type DriverRequest = DriverCall & { id: number };\n\nexport interface DriverReply {\n id: number;\n result?: unknown;\n errno?: string;\n message?: string;\n}\n\nexport interface KernelDriverHello {\n protocol: readonly [number, number];\n mount: MountRequestInfo;\n}\n\nexport interface DriverHello {\n protocol: readonly [number, number];\n capabilities?: DriverCapabilities;\n error?: string;\n errno?: string;\n}\n\nexport type KernelToDriver = { hello: KernelDriverHello } | DriverRequest;\n\nexport type DriverToKernel = { hello: DriverHello } | DriverReply | { invalidate: string[] | true };\n\nexport function driverVersionError(theirs: unknown): string | undefined {\n const major = Array.isArray(theirs) ? theirs[0] : undefined;\n if (major === DRIVER_PROTOCOL[0]) return undefined;\n const named = typeof major === 'number' ? `${major}.x` : 'without a version';\n return `slicc-kernel driver protocol ${named} is not supported: this side speaks ${DRIVER_PROTOCOL.join('.')}`;\n}\n", "import {\n DRIVER_PROTOCOL,\n type DriverAttr,\n type DriverCapabilities,\n type DriverEntry,\n type 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 { attachKernel } from '../client/attach.ts';\nimport type { MessagePortLike } from '../client/protocol.ts';\nimport type { RealmTransportRequest, RealmTransportResponse } from '../kernel/net/transport.ts';\nimport { type FilesystemHandlers, serveFilesystem } from './driver.ts';\nimport { DRIVER_PROTOCOL, type DriverCapabilities } from './protocol.ts';\n\nexport interface DriverStart {\n code: string;\n driver: MessagePortLike;\n client: MessagePortLike;\n}\n\nexport interface DriverEnv {\n fetch(\n request: Omit<RealmTransportRequest, 'signal'> & { signal?: AbortSignal }\n ): Promise<RealmTransportResponse>;\n}\n\nexport type DriverFactory = (\n env: DriverEnv\n) =>\n | Promise<{ handlers: FilesystemHandlers; capabilities?: DriverCapabilities }>\n | { handlers: FilesystemHandlers; capabilities?: DriverCapabilities };\n\nexport async function hostDriver(\n start: DriverStart,\n load: (code: string) => Promise<{ default?: unknown }>\n): Promise<void> {\n try {\n const factory = (await load(start.code)).default;\n if (typeof factory !== 'function') {\n throw new Error('a slicc file system module must export a default function');\n }\n const client = await attachKernel(start.client, { locks: null });\n const made = await (factory as DriverFactory)({ fetch: (request) => client.fetch(request) });\n serveFilesystem(start.driver, made.handlers, made.capabilities ?? {});\n } catch (err) {\n start.driver.postMessage({\n hello: {\n protocol: DRIVER_PROTOCOL,\n error: `the driver did not start: ${err instanceof Error ? err.message : String(err)}`,\n errno: 'EIO',\n },\n });\n }\n}\n", "export const BLOCKED_GLOBALS: readonly string[] = [\n 'XMLHttpRequest',\n 'WebSocketStream',\n 'WebTransport',\n 'EventSource',\n 'indexedDB',\n 'caches',\n 'cookieStore',\n 'SharedWorker',\n 'close',\n 'webkitRequestFileSystem',\n 'webkitRequestFileSystemSync',\n 'webkitResolveLocalFileSystemURL',\n 'webkitResolveLocalFileSystemSyncURL',\n];\n\nexport const BLOCKED_NAVIGATOR: readonly string[] = [\n 'storage',\n 'storageBuckets',\n 'locks',\n 'serviceWorker',\n 'usb',\n 'hid',\n 'serial',\n];\n\nexport const OPEN_SLOTS: readonly string[] = [\n 'fetch',\n 'WebSocket',\n 'BroadcastChannel',\n 'importScripts',\n 'Worker',\n 'postMessage',\n];\n\nfunction chain(target: object): object[] {\n const out: object[] = [];\n for (let at: object | null = target; at && at !== Object.prototype; ) {\n out.push(at);\n at = Object.getPrototypeOf(at);\n }\n return out;\n}\n\nexport function hide(target: object, names: readonly string[]): void {\n for (const name of names) {\n const holders = chain(target);\n for (const holder of holders) Reflect.deleteProperty(holder, name);\n const kept = holders.slice(1).some((holder) => Object.hasOwn(holder, name));\n const defined = Reflect.defineProperty(target, name, {\n value: undefined,\n writable: false,\n enumerable: false,\n configurable: false,\n });\n if (kept || (!defined && Reflect.get(target, name) !== undefined)) {\n throw new Error(`slicc-kernel: cannot withhold ${name} from a JS program`);\n }\n }\n}\n\nexport function vacate(target: object, names: readonly string[]): void {\n for (const name of names) {\n const holders = chain(target);\n for (const holder of holders) Reflect.deleteProperty(holder, name);\n const kept = holders.slice(1).some((holder) => Object.hasOwn(holder, name));\n const opened = Reflect.defineProperty(target, name, {\n value: undefined,\n writable: true,\n enumerable: false,\n configurable: true,\n });\n if (kept || !opened || Reflect.get(target, name) !== undefined) {\n throw new Error(`slicc-kernel: cannot withhold ${name} from a JS program`);\n }\n }\n}\n\nexport function lockdown(scope: object = globalThis): void {\n hide(scope, BLOCKED_GLOBALS);\n vacate(scope, OPEN_SLOTS);\n if ('self' in scope) {\n Reflect.defineProperty(scope, 'self', {\n value: scope,\n writable: true,\n enumerable: false,\n configurable: true,\n });\n }\n const navigator = (scope as { navigator?: unknown }).navigator;\n if (navigator && typeof navigator === 'object') hide(navigator, BLOCKED_NAVIGATOR);\n}\n", "import { type DriverStart, hostDriver } from './mount/host.ts';\nimport { lockdown } from './process/js/lockdown.ts';\n\naddEventListener(\n 'message',\n (event) =>\n void hostDriver((event as MessageEvent<DriverStart>).data, (code) => {\n const url = URL.createObjectURL(new Blob([code], { type: 'text/javascript' }));\n lockdown();\n return import(url);\n }),\n { once: true }\n);\n"],
5
+ "mappings": "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",
6
+ "names": ["fresh", "errorOf", "errorOf", "fresh", "quiet", "refused", "fresh", "fail", "fresh", "encoder", "encoder", "bytesOf", "quiet", "done", "refused", "options", "fsError", "refused", "fresh", "chain"]
7
7
  }