@ai-ecoverse/slicc-kernel 1.18.1 → 1.19.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js.map CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/body-idle.ts", "../src/transport.ts", "../src/kernel/net/remote-transport.ts", "../src/client/protocol.ts", "../src/client/attach.ts", "../src/local-proxy-transport.ts", "../src/index.ts"],
4
- "sourcesContent": ["export const BODY_IDLE_MS = 5 * 60 * 1000;\n\nexport function idleFailure(ms: number): Error {\n return Object.assign(new Error(`the response body sent no data for ${ms} ms`), {\n code: 'ETIMEDOUT',\n });\n}\n\nexport async function readWithin<T>(\n reader: ReadableStreamDefaultReader<T>,\n ms: number\n): Promise<ReadableStreamReadResult<T>> {\n if (!(ms > 0 && ms < Number.POSITIVE_INFINITY)) return reader.read();\n let timer: ReturnType<typeof setTimeout> | undefined;\n const idle = new Promise<never>((_, reject) => {\n timer = setTimeout(() => reject(idleFailure(ms)), ms);\n });\n try {\n return await Promise.race([reader.read(), idle]);\n } finally {\n clearTimeout(timer);\n }\n}\n", "import { BODY_IDLE_MS, readWithin } from './body-idle.ts';\nimport type { TransportCall, TransportReply } from './kernel/net/remote-transport.ts';\nimport type {\n HeaderList,\n RealmTransport,\n RealmTransportRequest,\n RealmTransportResponse,\n RealmTransportTraits,\n} from './kernel/net/transport.ts';\n\nexport type {\n HeaderList,\n RealmTransport as NetworkTransport,\n RealmTransportRequest as NetworkRequest,\n RealmTransportResponse as NetworkResponse,\n RealmTransportTraits as NetworkTraits,\n};\n\nexport interface FetchTransportOptions {\n fetch?: typeof globalThis.fetch;\n maxRequestBody?: number;\n hint?: string;\n bodyIdleMs?: number;\n}\n\nconst MAX_REQUEST_BODY = 64 * 1024 * 1024;\n\nfunction joinHeaders(headers: HeaderList): Headers {\n const out = new Headers();\n for (const [name, value] of headers) {\n try {\n out.append(name, value);\n } catch {}\n }\n return out;\n}\n\nasync function* chunks(\n body: ReadableStream<Uint8Array> | null,\n idleMs: number\n): AsyncGenerator<Uint8Array> {\n if (!body) return;\n const reader = body.getReader();\n try {\n for (\n let next = await readWithin(reader, idleMs);\n !next.done;\n next = await readWithin(reader, idleMs)\n ) {\n if (next.value.byteLength > 0) yield next.value;\n }\n } finally {\n await reader.cancel().catch(() => undefined);\n }\n}\n\nexport function fetchTransport(options: FetchTransportOptions = {}): RealmTransport {\n const send = options.fetch ?? globalThis.fetch.bind(globalThis);\n return {\n traits: {\n manualRedirects: false,\n encodedBodies: false,\n maxRequestBody: options.maxRequestBody ?? MAX_REQUEST_BODY,\n crossOrigin: 'cors',\n },\n async fetch(request: RealmTransportRequest): Promise<RealmTransportResponse> {\n let response: Response;\n try {\n response = await send(request.url, {\n method: request.method,\n headers: joinHeaders(request.headers),\n ...(request.body ? { body: request.body as BodyInit } : {}),\n signal: request.signal,\n redirect: 'follow',\n credentials: 'omit',\n mode: 'cors',\n });\n } catch (e) {\n if (request.signal.aborted) throw e;\n throw Object.assign(\n new Error(\n `fetch ${request.url} failed (unreachable, or not allowed by CORS)${options.hint ? `: ${options.hint}` : ''}`\n ),\n { status: 502 }\n );\n }\n const headers: Array<[string, string]> = [];\n response.headers.forEach((value, name) => {\n headers.push([name, value]);\n });\n const body = chunks(response.body, options.bodyIdleMs ?? BODY_IDLE_MS);\n return {\n status: response.status,\n statusText: response.statusText,\n headers,\n body,\n cancel: async () => {\n await body.return(undefined);\n await response.body?.cancel().catch(() => undefined);\n },\n };\n },\n };\n}\n\nexport interface TransportPeer {\n postMessage(message: TransportReply, transfer?: Transferable[]): void;\n}\n\nexport interface TransportServer {\n answer(call: TransportCall): void;\n close(): void;\n}\n\nexport function serveTransport(peer: TransportPeer, transport: RealmTransport): TransportServer {\n const open = new Map<\n number,\n { abort: AbortController; body?: AsyncIterator<Uint8Array>; response?: RealmTransportResponse }\n >();\n const fail = (nid: number, e: unknown) => {\n open.delete(nid);\n const { status, code } = e as { status?: unknown; code?: unknown };\n peer.postMessage({\n net: 'error',\n nid,\n message: e instanceof Error ? e.message : String(e),\n ...(typeof status === 'number' ? { status } : {}),\n ...(typeof code === 'string' ? { code } : {}),\n });\n };\n const start = async (call: Extract<TransportCall, { net: 'fetch' }>) => {\n const abort = new AbortController();\n const entry: { abort: AbortController; body?: AsyncIterator<Uint8Array> } = { abort };\n open.set(call.nid, entry);\n try {\n const response = await transport.fetch({\n url: call.url,\n method: call.method,\n headers: call.headers,\n ...(call.body ? { body: call.body } : {}),\n signal: abort.signal,\n });\n if (!open.has(call.nid)) {\n await response.cancel();\n return;\n }\n open.set(call.nid, { abort, body: response.body[Symbol.asyncIterator](), response });\n peer.postMessage({\n net: 'head',\n nid: call.nid,\n status: response.status,\n statusText: response.statusText,\n headers: response.headers,\n });\n } catch (e) {\n fail(call.nid, e);\n }\n };\n const read = async (nid: number) => {\n const body = open.get(nid)?.body;\n if (!body) return;\n try {\n const next = await body.next();\n if (next.done) {\n open.delete(nid);\n peer.postMessage({ net: 'end', nid });\n } else {\n const bytes = next.value.slice();\n peer.postMessage({ net: 'chunk', nid, bytes }, [bytes.buffer]);\n }\n } catch (e) {\n fail(nid, e);\n }\n };\n const drop = (nid: number) => {\n const entry = open.get(nid);\n open.delete(nid);\n entry?.abort.abort();\n void entry?.response?.cancel().catch(() => undefined);\n };\n return {\n answer(call) {\n if (call.net === 'fetch') void start(call);\n else if (call.net === 'read') void read(call.nid);\n else drop(call.nid);\n },\n close() {\n for (const nid of [...open.keys()]) drop(nid);\n },\n };\n}\n", "import type {\n HeaderList,\n RealmTransport,\n RealmTransportRequest,\n RealmTransportResponse,\n RealmTransportTraits,\n} from './transport.ts';\n\nexport type TransportCall =\n | {\n net: 'fetch';\n nid: number;\n url: string;\n method: string;\n headers: HeaderList;\n body?: Uint8Array;\n }\n | { net: 'read'; nid: number }\n | { net: 'cancel'; nid: number };\n\nexport type TransportReply =\n | { net: 'head'; nid: number; status: number; statusText: string; headers: HeaderList }\n | { net: 'chunk'; nid: number; bytes: Uint8Array }\n | { net: 'end'; nid: number }\n | { net: 'error'; nid: number; message: string; status?: number; code?: string };\n\nexport interface TransportPort {\n postMessage(message: TransportCall): void;\n}\n\nexport class TransportError extends Error {\n readonly status: number | undefined;\n readonly code: string | undefined;\n\n constructor(message: string, status?: number, code?: string) {\n super(message);\n this.status = status;\n this.code = code;\n }\n}\n\ninterface Waiter {\n resolve(reply: TransportReply): void;\n reject(error: Error): void;\n}\n\nexport class RemoteTransport implements RealmTransport {\n readonly traits: RealmTransportTraits;\n\n private readonly port: TransportPort;\n\n private readonly waiting = new Map<number, Waiter>();\n\n private nextId = 0;\n\n private failure: Error | undefined;\n\n constructor(port: TransportPort, traits: RealmTransportTraits) {\n this.port = port;\n this.traits = traits;\n }\n\n receive(reply: TransportReply): void {\n const waiter = this.waiting.get(reply.nid);\n if (!waiter) return;\n this.waiting.delete(reply.nid);\n if (reply.net === 'error') {\n waiter.reject(new TransportError(reply.message, reply.status, reply.code));\n } else waiter.resolve(reply);\n }\n\n fail(error: Error): void {\n this.failure = error;\n for (const waiter of this.waiting.values()) waiter.reject(error);\n this.waiting.clear();\n }\n\n private ask(call: TransportCall): Promise<TransportReply> {\n if (this.failure) return Promise.reject(this.failure);\n return new Promise((resolve, reject) => {\n this.waiting.set(call.nid, { resolve, reject });\n this.port.postMessage(call);\n });\n }\n\n private cancel(nid: number): void {\n const waiter = this.waiting.get(nid);\n this.waiting.delete(nid);\n waiter?.reject(new TransportError('the request was cancelled'));\n this.port.postMessage({ net: 'cancel', nid });\n }\n\n async fetch(request: RealmTransportRequest): Promise<RealmTransportResponse> {\n const nid = ++this.nextId;\n const { signal } = request;\n signal.throwIfAborted();\n let finished = false;\n const abort = () => {\n finished = true;\n this.cancel(nid);\n };\n signal.addEventListener('abort', abort, { once: true });\n const finish = () => {\n if (finished) return;\n finished = true;\n signal.removeEventListener('abort', abort);\n };\n let head: TransportReply;\n try {\n head = await this.ask({\n net: 'fetch',\n nid,\n url: request.url,\n method: request.method,\n headers: request.headers,\n ...(request.body ? { body: request.body } : {}),\n });\n } catch (e) {\n finish();\n throw e;\n }\n const { status, statusText, headers } = head as Extract<TransportReply, { net: 'head' }>;\n const read = async (): Promise<Uint8Array | undefined> => {\n if (finished) return undefined;\n const reply = await this.ask({ net: 'read', nid }).catch((e: unknown) => {\n finish();\n throw e;\n });\n if (reply.net === 'chunk') return reply.bytes;\n finish();\n return undefined;\n };\n const cancel = async () => {\n if (finished) return;\n finish();\n this.cancel(nid);\n };\n return {\n status,\n statusText,\n headers,\n cancel,\n body: {\n [Symbol.asyncIterator]: () => ({\n next: async () => {\n const bytes = await read();\n return bytes ? { value: bytes, done: false } : { value: undefined, done: true };\n },\n return: async () => {\n await cancel();\n return { value: undefined, done: true };\n },\n }),\n },\n };\n }\n}\n", "import type { WatchChange } from '../fs/watch.ts';\nimport type { TransportCall, TransportReply } from '../kernel/net/remote-transport.ts';\nimport type { RealmTransportTraits } from '../kernel/net/transport.ts';\nimport type { MountSpec } from '../mount/mount-fs.ts';\n\nexport const PROTOCOL: readonly [number, number] = [1, 2];\n\nexport interface ClientHello {\n protocol: readonly [number, number];\n lock?: string;\n}\n\nexport interface KernelHello {\n protocol: readonly [number, number];\n lock?: string;\n traits?: RealmTransportTraits;\n error?: string;\n}\n\nexport interface SpawnRequestOptions {\n cwd?: string;\n env?: Record<string, string>;\n stdin?: Uint8Array;\n}\n\nexport interface TerminalRequestOptions {\n cwd?: string;\n env?: Record<string, string>;\n cols?: number;\n rows?: number;\n}\n\nexport type TerminalAction =\n | { action: 'write'; bytes: Uint8Array }\n | { action: 'resize'; cols: number; rows: number }\n | { action: 'signal'; signal: string }\n | { action: 'close' };\n\nexport const FS_METHODS = [\n 'readFile',\n 'writeFile',\n 'stat',\n 'lstat',\n 'readdir',\n 'mkdir',\n 'rm',\n 'rename',\n 'realpath',\n 'symlink',\n 'readlink',\n 'exists',\n] as const;\n\nexport type FsMethod = (typeof FS_METHODS)[number];\n\nexport type ClientCall =\n | { op: 'spawn'; argv: string[]; options: SpawnRequestOptions }\n | { op: 'open-terminal'; argv: string[]; options: TerminalRequestOptions }\n | ({ op: 'terminal'; terminal: number } & TerminalAction)\n | { op: 'kill'; pid: number; signal: string }\n | { op: 'ps' }\n | { op: 'fs'; method: FsMethod; args: unknown[] }\n | { op: 'watch'; paths: string[]; recursive: boolean }\n | { op: 'unwatch'; watch: number }\n | { op: 'mount'; spec: MountSpec }\n | { op: 'umount'; target: string }\n | { op: 'mounts' }\n | { op: 'detach'; kill?: boolean };\n\nexport type ClientRequest = ClientCall & { id: number };\n\nexport interface ClientReply {\n id: number;\n result?: unknown;\n error?: string;\n code?: string;\n fd?: 1 | 2;\n bytes?: Uint8Array;\n started?: number;\n}\n\nexport type ClientMessage = { hello: ClientHello } | ClientRequest | TransportCall;\n\nexport interface WatchEvent {\n watch: number;\n change: WatchChange;\n}\n\nexport type KernelMessage = { hello: KernelHello } | ClientReply | WatchEvent | TransportReply;\n\nexport interface ProcessEntry {\n pid: number;\n ppid: number;\n pgid: number;\n sid: number;\n argv: string[];\n tty: string | null;\n started: number;\n state: 'S' | 'Z';\n memory: number;\n}\n\nexport interface MessagePortLike {\n postMessage(message: unknown, transfer?: Transferable[]): void;\n addEventListener(type: 'message' | 'close', handler: (event: MessageEvent) => void): void;\n start?(): void;\n close?(): void;\n}\n\nexport interface LockManagerLike {\n request(name: string, callback: () => Promise<unknown> | unknown): Promise<unknown>;\n}\n\nexport function locksOf(scope: object = globalThis): LockManagerLike | undefined {\n const locks = (scope as { navigator?: { locks?: LockManagerLike } }).navigator?.locks;\n return typeof locks?.request === 'function' ? locks : undefined;\n}\n\nexport function versionError(theirs: unknown): string | undefined {\n const major = Array.isArray(theirs) ? theirs[0] : undefined;\n if (major === PROTOCOL[0]) return undefined;\n const named = typeof major === 'number' ? `${major}.x` : 'without a version';\n return `slicc-kernel client protocol ${named} is not supported: this side speaks ${PROTOCOL.join('.')}`;\n}\n", "import type { FsStat } from '../fs/types.ts';\nimport type { WatchChange } from '../fs/watch.ts';\nimport { RemoteTransport, type TransportReply } from '../kernel/net/remote-transport.ts';\nimport type {\n RealmTransport,\n RealmTransportRequest,\n RealmTransportResponse,\n} from '../kernel/net/transport.ts';\nimport type { MountEntry, MountSpec } from '../mount/mount-fs.ts';\nimport {\n type ClientCall,\n type ClientReply,\n type FsMethod,\n type KernelHello,\n type LockManagerLike,\n locksOf,\n type MessagePortLike,\n PROTOCOL,\n type ProcessEntry,\n type TerminalAction,\n versionError,\n} from './protocol.ts';\n\nexport type { WatchChange } from '../fs/watch.ts';\nexport type { ProcessEntry } from './protocol.ts';\n\nexport class KernelGoneError extends Error {\n constructor(message = 'the slicc-kernel this client was attached to is gone') {\n super(message);\n this.name = 'KernelGoneError';\n }\n}\n\nexport class KernelCallError extends Error {\n readonly code: string | undefined;\n\n constructor(message: string, code?: string) {\n super(message);\n this.name = 'KernelCallError';\n this.code = code;\n }\n}\n\nexport interface AttachOptions {\n timeoutMs?: number;\n locks?: LockManagerLike | null;\n}\n\nexport interface SpawnOptions {\n cwd?: string;\n env?: Record<string, string>;\n stdin?: string | Uint8Array;\n group?: 'new';\n onStdout?: (bytes: Uint8Array) => void;\n onStderr?: (bytes: Uint8Array) => void;\n}\n\nexport interface SpawnedProcess {\n readonly pid: number;\n readonly pgid: number;\n readonly exited: Promise<number>;\n signal(name?: string): Promise<void>;\n}\n\nexport interface ClientRunOptions {\n cwd?: string;\n env?: Record<string, string>;\n stdin?: string | Uint8Array;\n onStdout?: (text: string) => void;\n onStderr?: (text: string) => void;\n}\n\nexport interface ClientRunResult {\n pid: number;\n status: number;\n stdout: string;\n stderr: string;\n}\n\nexport interface ClientTerminalOptions {\n cwd?: string;\n env?: Record<string, string>;\n cols?: number;\n rows?: number;\n onData?: (bytes: Uint8Array) => void;\n}\n\nexport interface ClientTerminal {\n readonly pid: number;\n readonly exited: Promise<number>;\n onData: ((bytes: Uint8Array) => void) | null;\n write(data: string | Uint8Array): void;\n resize(cols: number, rows: number): void;\n signal(name: string): void;\n close(): void;\n}\n\nexport interface ClientFs {\n readFile(path: string): Promise<Uint8Array>;\n readText(path: string): Promise<string>;\n writeFile(path: string, data: string | Uint8Array): Promise<void>;\n stat(path: string): Promise<FsStat>;\n lstat(path: string): Promise<FsStat>;\n readdir(path: string): Promise<string[]>;\n mkdir(path: string): Promise<void>;\n rm(path: string, options?: { force?: boolean }): Promise<void>;\n rename(from: string, to: string): Promise<void>;\n realpath(path: string): Promise<string>;\n symlink(target: string, path: string): Promise<void>;\n readlink(path: string): Promise<string>;\n exists(path: string): Promise<boolean>;\n watch(\n paths: string[],\n options: { recursive?: boolean },\n onChange: (change: WatchChange) => void\n ): Promise<{ close(): void }>;\n}\n\nexport type ClientFetchRequest = Omit<RealmTransportRequest, 'signal'> & { signal?: AbortSignal };\n\nexport interface KernelClient {\n readonly protocol: readonly [number, number];\n readonly transport: RealmTransport;\n readonly closed: Promise<Error>;\n spawn(argv: string[], options?: SpawnOptions): Promise<SpawnedProcess>;\n run(argv: string[], options?: ClientRunOptions): Promise<ClientRunResult>;\n openTerminal(argv: string[], options?: ClientTerminalOptions): Promise<ClientTerminal>;\n ps(): Promise<ProcessEntry[]>;\n mount(spec: MountSpec): Promise<MountEntry>;\n umount(target: string): Promise<void>;\n mounts(): Promise<MountEntry[]>;\n kill(pid: number, signal?: string): Promise<void>;\n fetch(request: ClientFetchRequest): Promise<RealmTransportResponse>;\n readonly fs: ClientFs;\n close(options?: { kill?: boolean }): Promise<void>;\n}\n\ninterface Pending {\n resolve: (value: unknown) => void;\n reject: (error: Error) => void;\n output?: (fd: 1 | 2, bytes: Uint8Array) => void;\n started?: (pid: number) => void;\n}\n\ntype Handlers = Omit<Pending, 'resolve' | 'reject'>;\n\nconst encoder = new TextEncoder();\nconst bytesOf = (data: string | Uint8Array) =>\n typeof data === 'string' ? encoder.encode(data) : data;\n\nconst UNAVAILABLE = {\n manualRedirects: false,\n encodedBodies: false,\n maxRequestBody: 0,\n unavailable: true,\n} as const;\n\nasync function holdLock(\n locks: LockManagerLike | undefined\n): Promise<{ name?: string; release(): void }> {\n if (!locks) return { release() {} };\n const name = `slicc-kernel-client:${crypto.randomUUID()}`;\n const granted = Promise.withResolvers<void>();\n const held = Promise.withResolvers<void>();\n void locks.request(name, () => {\n granted.resolve();\n return held.promise;\n });\n await granted.promise;\n return { name, release: () => held.resolve() };\n}\n\nfunction concat(chunks: Uint8Array[]): Uint8Array {\n const out = new Uint8Array(chunks.reduce((n, c) => n + c.length, 0));\n let at = 0;\n for (const chunk of chunks) {\n out.set(chunk, at);\n at += chunk.length;\n }\n return out;\n}\n\nclass Channel {\n readonly greeted = Promise.withResolvers<KernelHello>();\n readonly ended = Promise.withResolvers<Error>();\n remote: RemoteTransport | undefined;\n failure: Error | undefined;\n private readonly pending = new Map<number, Pending>();\n readonly watching = new Map<number, (change: WatchChange) => void>();\n 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 call of this.pending.values()) call.reject(error);\n this.pending.clear();\n this.release();\n this.port.close?.();\n this.ended.resolve(error);\n }\n\n request(call: ClientCall, handlers: Handlers = {}): { id: number; done: Promise<unknown> } {\n const id = ++this.nextId;\n const { failure } = this;\n if (failure) return { id, done: Promise.reject(failure) };\n const done = new Promise((resolve, reject) => {\n this.pending.set(id, { resolve, reject, ...handlers });\n this.port.postMessage({ ...call, id });\n });\n return { id, done };\n }\n\n call(call: ClientCall): Promise<unknown> {\n return this.request(call).done;\n }\n\n private receive(data: {\n hello?: KernelHello;\n net?: unknown;\n bye?: string;\n watch?: number;\n change?: WatchChange;\n }): void {\n if (data.watch !== undefined) {\n this.watching.get(data.watch)?.(data.change as WatchChange);\n return;\n }\n if (data.bye !== undefined) {\n this.end(new KernelGoneError(data.bye));\n return;\n }\n if (data.hello) {\n this.greeted.resolve(data.hello);\n return;\n }\n if (data.net !== undefined) {\n this.remote?.receive(data as TransportReply);\n return;\n }\n const reply = data as ClientReply;\n const call = this.pending.get(reply.id);\n if (!call) return;\n if (reply.fd !== undefined) {\n call.output?.(reply.fd, reply.bytes as Uint8Array);\n return;\n }\n if (reply.started !== undefined) {\n call.started?.(reply.started);\n return;\n }\n this.pending.delete(reply.id);\n if (reply.error !== undefined) call.reject(new KernelCallError(reply.error, reply.code));\n else call.resolve(reply.result);\n }\n}\n\nasync function spawnOn(\n channel: Channel,\n argv: string[],\n opts: SpawnOptions\n): Promise<SpawnedProcess> {\n const { onStdout, onStderr, stdin, group: _, ...rest } = opts;\n const started = Promise.withResolvers<number>();\n const options = { ...rest, ...(stdin !== undefined ? { stdin: bytesOf(stdin) } : {}) };\n const { done } = channel.request(\n { op: 'spawn', argv, options },\n {\n output: (fd, bytes) => (fd === 1 ? onStdout : onStderr)?.(bytes),\n started: started.resolve,\n }\n );\n done.catch(started.reject);\n const pid = await started.promise;\n return {\n pid,\n pgid: pid,\n exited: done as Promise<number>,\n signal: async (name = 'SIGTERM') =>\n void (await channel.call({ op: 'kill', pid: -pid, signal: name })),\n };\n}\n\nasync function runOn(\n channel: Channel,\n argv: string[],\n opts: ClientRunOptions\n): Promise<ClientRunResult> {\n const { onStdout, onStderr, ...rest } = opts;\n const chunks: Record<1 | 2, Uint8Array[]> = { 1: [], 2: [] };\n const live = { 1: new TextDecoder(), 2: new TextDecoder() };\n const tee = (fd: 1 | 2, on?: (text: string) => void) => (bytes: Uint8Array) => {\n chunks[fd].push(bytes);\n on?.(live[fd].decode(bytes, { stream: true }));\n };\n const child = await spawnOn(channel, argv, {\n ...rest,\n onStdout: tee(1, onStdout),\n onStderr: tee(2, onStderr),\n });\n const status = await child.exited;\n const text = (fd: 1 | 2) => new TextDecoder().decode(concat(chunks[fd]));\n return { pid: child.pid, status, stdout: text(1), stderr: text(2) };\n}\n\nasync function terminalOn(\n channel: Channel,\n argv: string[],\n opts: ClientTerminalOptions\n): Promise<ClientTerminal> {\n const { onData, ...options } = opts;\n let listener = onData ?? null;\n const backlog: Uint8Array[] = [];\n const started = Promise.withResolvers<number>();\n const { id, done } = channel.request(\n { op: 'open-terminal', argv, options },\n {\n output: (_fd, bytes) => (listener ? listener(bytes) : backlog.push(bytes)),\n started: started.resolve,\n }\n );\n done.catch(started.reject);\n const pid = await started.promise;\n const send = (action: TerminalAction) =>\n void channel.call({ op: 'terminal', terminal: id, ...action }).catch(() => undefined);\n return {\n pid,\n exited: done as Promise<number>,\n get onData() {\n return listener;\n },\n set onData(next) {\n listener = next;\n if (next) for (const bytes of backlog.splice(0)) next(bytes);\n },\n write: (data) => send({ action: 'write', bytes: bytesOf(data) }),\n resize: (cols, rows) => send({ action: 'resize', cols, rows }),\n signal: (name) => send({ action: 'signal', signal: name }),\n close: () => send({ action: 'close' }),\n };\n}\n\nfunction fsOn(channel: Channel): ClientFs {\n const fs = (method: FsMethod, ...args: unknown[]) => channel.call({ op: 'fs', method, args });\n const done = async (method: FsMethod, ...args: unknown[]) => void (await fs(method, ...args));\n return {\n readFile: (path) => fs('readFile', path) as Promise<Uint8Array>,\n readText: async (path) => new TextDecoder().decode((await fs('readFile', path)) as Uint8Array),\n writeFile: (path, data) => done('writeFile', path, data),\n stat: (path) => fs('stat', path) as Promise<FsStat>,\n lstat: (path) => fs('lstat', path) as Promise<FsStat>,\n readdir: (path) => fs('readdir', path) as Promise<string[]>,\n mkdir: (path) => done('mkdir', path),\n rm: (path, o = {}) => done('rm', path, o.force === true),\n rename: (from, to) => done('rename', from, to),\n realpath: (path) => fs('realpath', path) as Promise<string>,\n symlink: (target, path) => done('symlink', target, path),\n readlink: (path) => fs('readlink', path) as Promise<string>,\n exists: (path) => fs('exists', path) as Promise<boolean>,\n async watch(paths, options, onChange) {\n if (channel.protocol[1] < 1) {\n throw new KernelCallError(\n `this kernel speaks protocol ${channel.protocol.join('.')}, which has no watch`,\n 'ENOSYS'\n );\n }\n const { id, done } = channel.request({\n op: 'watch',\n paths,\n recursive: options.recursive === true,\n });\n channel.watching.set(id, onChange);\n try {\n await done;\n } catch (error) {\n channel.watching.delete(id);\n throw error;\n }\n return {\n close: () => {\n if (!channel.watching.delete(id)) return;\n void channel.call({ op: 'unwatch', watch: id }).catch(() => undefined);\n },\n };\n },\n };\n}\n\nfunction since(channel: Channel, minor: number, what: string, run: () => Promise<unknown>) {\n if (channel.protocol[1] < minor) {\n return Promise.reject(\n new KernelCallError(\n `this kernel speaks protocol ${channel.protocol.join('.')}, which has no ${what}`,\n 'ENOSYS'\n )\n );\n }\n return run();\n}\n\nasync function greet(\n channel: Channel,\n lock: string | undefined,\n timeoutMs: number\n): Promise<KernelHello> {\n channel.post({ hello: { protocol: PROTOCOL, ...(lock ? { lock } : {}) } });\n const timer = setTimeout(\n () =>\n channel.end(\n new KernelGoneError(`no slicc-kernel answered on this port within ${timeoutMs} ms`)\n ),\n timeoutMs\n );\n let hello: KernelHello;\n try {\n hello = await channel.greeted.promise;\n } finally {\n clearTimeout(timer);\n }\n const refused = hello.error ?? versionError(hello.protocol);\n if (refused) {\n const error = new Error(refused);\n channel.end(error);\n throw error;\n }\n return hello;\n}\n\nexport async function attachKernel(\n port: MessagePortLike,\n options: AttachOptions = {}\n): Promise<KernelClient> {\n const locks = options.locks === null ? undefined : (options.locks ?? locksOf());\n const own = await holdLock(locks);\n const channel = new Channel(port, own.release);\n const hello = await greet(channel, own.name, options.timeoutMs ?? 10_000);\n channel.protocol = hello.protocol;\n if (hello.lock && locks) void locks.request(hello.lock, () => channel.end(new KernelGoneError()));\n const transport = new RemoteTransport(\n { postMessage: (call) => channel.post(call) },\n hello.traits ?? UNAVAILABLE\n );\n channel.remote = transport;\n return {\n protocol: hello.protocol,\n transport,\n closed: channel.ended.promise,\n spawn: (argv, opts = {}) => spawnOn(channel, argv, opts),\n run: (argv, opts = {}) => runOn(channel, argv, opts),\n openTerminal: (argv, opts = {}) => terminalOn(channel, argv, opts),\n ps: () => channel.call({ op: 'ps' }) as Promise<ProcessEntry[]>,\n mount: (spec) =>\n since(channel, 2, 'mount', () => channel.call({ op: 'mount', spec })) as Promise<MountEntry>,\n umount: async (target) =>\n void (await since(channel, 2, 'umount', () => channel.call({ op: 'umount', target }))),\n mounts: () =>\n since(channel, 2, 'mounts', () => channel.call({ op: 'mounts' })) as Promise<MountEntry[]>,\n kill: async (pid, signal = 'SIGTERM') => void (await channel.call({ op: 'kill', pid, signal })),\n fetch: (req) => {\n const { signal, ...rest } = req;\n return transport.fetch({ ...rest, signal: signal ?? new AbortController().signal });\n },\n fs: fsOn(channel),\n async close(o = {}) {\n if (channel.failure) return;\n await channel\n .call({ op: 'detach', ...(o.kill ? { kill: true } : {}) })\n .catch(() => undefined);\n channel.end(new KernelGoneError('this client is closed'));\n },\n };\n}\n", "import { BODY_IDLE_MS, readWithin } from './body-idle.ts';\nimport type {\n HeaderList,\n RealmTransport,\n RealmTransportRequest,\n RealmTransportResponse,\n} from './kernel/net/transport.ts';\n\nexport interface LocalProxyOptions {\n url: string;\n key: string;\n fetch?: typeof globalThis.fetch;\n}\n\nexport interface LocalProxyCheckOptions extends LocalProxyOptions {\n permissions?: Pick<Permissions, 'query'>;\n}\n\nexport interface LocalProxyTransportOptions extends LocalProxyOptions {\n maxRequestBody?: number;\n bodyIdleMs?: number;\n}\n\nexport interface LocalProxyProbe {\n rawFetch: number;\n requestBodyStreaming: boolean;\n maxRequestBodyBytes: number;\n}\n\nexport type LocalProxyStatus =\n | { state: 'ready'; probe: LocalProxyProbe }\n | { state: 'blocked' }\n | { state: 'unreachable'; permission: 'granted' | 'prompt' | 'unknown' }\n | { state: 'refused'; status: number; error: string }\n | { state: 'incompatible' };\n\nconst PATH = '/api/fetch-proxy';\nconst RAW_CONTENT_TYPE = 'application/vnd.slicc.raw-fetch';\nconst MAX_HEAD = 1024 * 1024;\nconst MAX_REQUEST_BODY = 64 * 1024 * 1024;\nconst PERMISSIONS = ['loopback-network', 'local-network-access'];\nconst LOOPBACK_PAGE = /^(127\\.\\d+\\.\\d+\\.\\d+|localhost|\\[::1\\])$/;\n\ninterface ResponseHead {\n status: number;\n statusText: string;\n headers: Array<[string, string]>;\n}\n\nconst failure = (message: string, status = 502) =>\n Object.assign(new Error(`local proxy: ${message}`), { status });\n\nfunction encodeHead(url: string, method: string, headers: HeaderList): string {\n return JSON.stringify({ url, method, headers }).replace(\n /[\\u007f-\uFFFF]/g,\n (c) => `\\\\u${c.charCodeAt(0).toString(16).padStart(4, '0')}`\n );\n}\n\nfunction hopHeaders(options: LocalProxyOptions, extra: Record<string, string>): Headers {\n return new Headers({ 'X-Bridge-Token': options.key, ...extra });\n}\n\nfunction send(options: LocalProxyOptions) {\n return options.fetch ?? globalThis.fetch.bind(globalThis);\n}\n\nasync function refusalMessage(response: Response): Promise<string> {\n const text = await response.text().catch(() => '');\n try {\n const parsed = JSON.parse(text) as { error?: unknown };\n if (typeof parsed.error === 'string') return parsed.error;\n } catch {}\n return text || response.statusText || `answered ${response.status}`;\n}\n\nasync function refusal(response: Response): Promise<Error> {\n return failure(await refusalMessage(response), response.ok ? 502 : response.status);\n}\n\nasync function permission(permissions: Pick<Permissions, 'query'> | undefined): Promise<string> {\n if (!permissions) return 'unknown';\n for (const name of PERMISSIONS) {\n try {\n return (await permissions.query({ name } as PermissionDescriptor)).state;\n } catch {}\n }\n return 'unknown';\n}\n\nfunction isHead(value: unknown): value is ResponseHead {\n const head = value as Partial<ResponseHead> | null;\n return (\n !!head &&\n typeof head.status === 'number' &&\n typeof head.statusText === 'string' &&\n Array.isArray(head.headers) &&\n head.headers.every(\n (pair) =>\n Array.isArray(pair) &&\n pair.length === 2 &&\n typeof pair[0] === 'string' &&\n typeof pair[1] === 'string'\n )\n );\n}\n\nfunction concat(a: Uint8Array, b: Uint8Array): Uint8Array {\n const out = new Uint8Array(a.byteLength + b.byteLength);\n out.set(a);\n out.set(b, a.byteLength);\n return out;\n}\n\nasync function readHead(\n reader: ReadableStreamDefaultReader<Uint8Array>,\n idleMs: number\n): Promise<{ head: ResponseHead; rest: Uint8Array }> {\n let buffer: Uint8Array = new Uint8Array(0);\n for (;;) {\n if (buffer.byteLength >= 4) {\n const length = new DataView(buffer.buffer, buffer.byteOffset, 4).getUint32(0);\n if (length > MAX_HEAD) throw failure(`response head of ${length} bytes`);\n if (buffer.byteLength >= 4 + length) {\n let head: unknown;\n try {\n head = JSON.parse(new TextDecoder().decode(buffer.subarray(4, 4 + length)));\n } catch {}\n if (!isHead(head)) throw failure('malformed response head');\n return { head, rest: buffer.subarray(4 + length) };\n }\n }\n const next = await readWithin(reader, idleMs);\n if (next.done) throw failure('closed before the response head');\n buffer = concat(buffer, next.value);\n }\n}\n\nasync function* chunks(\n rest: Uint8Array,\n reader: ReadableStreamDefaultReader<Uint8Array>,\n idleMs: number\n): AsyncGenerator<Uint8Array> {\n try {\n if (rest.byteLength > 0) yield rest;\n for (\n let next = await readWithin(reader, idleMs);\n !next.done;\n next = await readWithin(reader, idleMs)\n ) {\n if (next.value.byteLength > 0) yield next.value;\n }\n } finally {\n await reader.cancel().catch(() => undefined);\n }\n}\n\nexport async function checkLocalProxy(options: LocalProxyCheckOptions): Promise<LocalProxyStatus> {\n const onLoopback = LOOPBACK_PAGE.test(globalThis.location?.hostname ?? '');\n const permissions = onLoopback\n ? undefined\n : (options.permissions ?? globalThis.navigator?.permissions);\n if ((await permission(permissions)) === 'denied') return { state: 'blocked' };\n let response: Response;\n try {\n response = await send(options)(new URL(PATH, options.url), {\n method: 'POST',\n headers: hopHeaders(options, { 'X-Slicc-Raw-Probe': '1' }),\n credentials: 'omit',\n mode: 'cors',\n });\n } catch {\n const now = await permission(permissions);\n if (now === 'denied') return { state: 'blocked' };\n return {\n state: 'unreachable',\n permission: now === 'granted' || now === 'prompt' ? now : 'unknown',\n };\n }\n if (!response.ok) {\n return { state: 'refused', status: response.status, error: await refusalMessage(response) };\n }\n const reply = (await response.json().catch(() => null)) as Partial<LocalProxyProbe> | null;\n if (\n !reply ||\n typeof reply.rawFetch !== 'number' ||\n reply.rawFetch < 1 ||\n typeof reply.requestBodyStreaming !== 'boolean' ||\n typeof reply.maxRequestBodyBytes !== 'number'\n ) {\n return { state: 'incompatible' };\n }\n return {\n state: 'ready',\n probe: {\n rawFetch: reply.rawFetch,\n requestBodyStreaming: reply.requestBodyStreaming,\n maxRequestBodyBytes: reply.maxRequestBodyBytes,\n },\n };\n}\n\nexport async function probeLocalProxy(\n options: LocalProxyCheckOptions\n): Promise<LocalProxyProbe | null> {\n const status = await checkLocalProxy(options);\n return status.state === 'ready' ? status.probe : null;\n}\n\nexport function localProxyTransport(options: LocalProxyTransportOptions): RealmTransport {\n const endpoint = new URL(PATH, options.url);\n return {\n traits: {\n manualRedirects: true,\n encodedBodies: false,\n maxRequestBody: options.maxRequestBody ?? MAX_REQUEST_BODY,\n },\n async fetch(request: RealmTransportRequest): Promise<RealmTransportResponse> {\n let response: Response;\n try {\n response = await send(options)(endpoint, {\n method: 'POST',\n headers: hopHeaders(options, {\n 'X-Slicc-Raw-Request': encodeHead(request.url, request.method, request.headers),\n }),\n ...(request.body ? { body: request.body as BodyInit } : {}),\n signal: request.signal,\n credentials: 'omit',\n mode: 'cors',\n });\n } catch (e) {\n if (request.signal.aborted) throw e;\n throw failure(`${endpoint.origin} is unreachable or refuses this origin`);\n }\n const type = response.headers.get('content-type') ?? '';\n if (response.status !== 200 || !type.startsWith(RAW_CONTENT_TYPE) || !response.body) {\n throw await refusal(response);\n }\n const reader = response.body.getReader();\n const idleMs = options.bodyIdleMs ?? BODY_IDLE_MS;\n let framed: { head: ResponseHead; rest: Uint8Array };\n try {\n framed = await readHead(reader, idleMs);\n } catch (e) {\n await reader.cancel().catch(() => undefined);\n throw e;\n }\n const body = chunks(framed.rest, reader, idleMs);\n return {\n status: framed.head.status,\n statusText: framed.head.statusText,\n headers: framed.head.headers,\n body,\n cancel: async () => {\n await body.return(undefined);\n await reader.cancel().catch(() => undefined);\n },\n };\n },\n };\n}\n", "import type { TransportCall } from './kernel/net/remote-transport.ts';\nimport type { PendingMedium } from './launcher.ts';\nimport type { MediumHandle } from './mount/fsa.ts';\nimport type { HostfsGrantHook } from './mount/hostfs.ts';\nimport type { MountEntry, MountSpec } from './mount/mount-fs.ts';\nimport type { ProcessMountPolicy, ProcessMountRequest } from './mount/syscall.ts';\nimport type { KernelCall, TerminalAction } from './serve.ts';\nimport { type NetworkTransport, serveTransport } from './transport.ts';\n\nexport {\n type AttachOptions,\n attachKernel,\n type ClientFetchRequest,\n type ClientFs,\n type ClientRunOptions,\n type ClientRunResult,\n type ClientTerminal,\n type ClientTerminalOptions,\n KernelCallError,\n type KernelClient,\n KernelGoneError,\n type ProcessEntry,\n type SpawnedProcess,\n type SpawnOptions,\n type WatchChange,\n} from './client/attach.ts';\nexport {\n checkLocalProxy,\n type LocalProxyCheckOptions,\n type LocalProxyOptions,\n type LocalProxyProbe,\n type LocalProxyStatus,\n type LocalProxyTransportOptions,\n localProxyTransport,\n probeLocalProxy,\n} from './local-proxy-transport.ts';\nexport type { HostfsGrant, HostfsGrantHook } from './mount/hostfs.ts';\nexport type { MountEntry, MountSpec } from './mount/mount-fs.ts';\nexport type { ProcessMountPolicy, ProcessMountRequest } from './mount/syscall.ts';\nexport {\n type FetchTransportOptions,\n fetchTransport,\n type HeaderList,\n type NetworkRequest,\n type NetworkResponse,\n type NetworkTraits,\n type NetworkTransport,\n} from './transport.ts';\n\nexport interface NetworkOptions {\n transport?: NetworkTransport;\n}\n\nexport interface KernelOptions {\n root?: FileSystemDirectoryHandle;\n modules?: string;\n env?: Record<string, string>;\n metadata?: string | false;\n media?: string | false;\n worker?: string | URL;\n network?: NetworkOptions;\n requestDirectory?: () => Promise<FileSystemDirectoryHandle>;\n onMountPending?: (pending: MountPending) => void;\n hostfs?: HostfsGrantHook;\n processMounts?: ProcessMountPolicy;\n}\n\ninterface HostfsRequest {\n id: number;\n source: string;\n readonly: boolean;\n}\n\nexport interface MountPending {\n target: string;\n source: string;\n insert(): Promise<void>;\n}\n\nexport interface RunOptions {\n cwd?: string;\n env?: Record<string, string>;\n stdin?: string | Uint8Array;\n onStdout?: (text: string) => void;\n onStderr?: (text: string) => void;\n}\n\nexport interface RunResult {\n status: number;\n stdout: string;\n stderr: string;\n}\n\nexport interface Kernel {\n run(argv: string[], options?: RunOptions): Promise<RunResult>;\n openTerminal(argv: string[], options?: TerminalOptions): Promise<Terminal>;\n connect(): Promise<MessagePort>;\n mount(spec: MountSpec): Promise<MountEntry>;\n umount(target: string): Promise<void>;\n mounts(): Promise<MountEntry[]>;\n insert(target: string, handle: FileSystemDirectoryHandle): Promise<void>;\n terminate(): void;\n}\n\nexport interface TerminalOptions {\n cwd?: string;\n env?: Record<string, string>;\n cols?: number;\n rows?: number;\n onData?: (bytes: Uint8Array) => void;\n}\n\nexport type TerminalSignal =\n | 'SIGINT'\n | 'SIGTSTP'\n | 'SIGQUIT'\n | 'SIGHUP'\n | 'SIGTERM'\n | 'SIGKILL'\n | 'SIGCONT';\n\nexport interface Terminal {\n readonly pid: number;\n readonly exited: Promise<number>;\n onData: ((bytes: Uint8Array) => void) | null;\n write(data: string | Uint8Array): void;\n resize(cols: number, rows: number): void;\n signal(name: TerminalSignal): void;\n close(): void;\n}\n\ninterface Reply {\n id: number;\n result?: unknown;\n error?: string;\n fd?: 1 | 2;\n bytes?: Uint8Array;\n started?: number;\n}\n\ninterface Pending {\n resolve: (value: unknown) => void;\n reject: (error: Error) => void;\n output?: (fd: 1 | 2, bytes: Uint8Array) => void;\n started?: (pid: number) => void;\n}\n\ninterface Handlers {\n output?: Pending['output'];\n started?: Pending['started'];\n}\n\nconst ISOLATION =\n 'slicc-kernel needs a cross-origin isolated page (Cross-Origin-Opener-Policy: same-origin and Cross-Origin-Embedder-Policy: require-corp or credentialless)';\n\nfunction streamer(callback: ((text: string) => void) | undefined) {\n const decoder = new TextDecoder();\n return (bytes: Uint8Array) => callback?.(decoder.decode(bytes, { stream: true }));\n}\n\nexport async function createKernel(options: KernelOptions = {}): Promise<Kernel> {\n if (!globalThis.crossOriginIsolated) throw new Error(ISOLATION);\n const url = options.worker ?? new URL('./kernel-worker.js', import.meta.url);\n const worker = new Worker(url, { type: 'module', name: 'slicc-kernel' });\n const pending = new Map<number, Pending>();\n let nextId = 0;\n let failure: Error | undefined;\n\n const fail = (error: Error) => {\n failure = error;\n bridge?.close();\n for (const call of pending.values()) call.reject(error);\n pending.clear();\n };\n const transport = options.network?.transport;\n const bridge = transport ? serveTransport(worker, transport) : undefined;\n async function chosen(handle: MediumHandle | undefined): Promise<FileSystemDirectoryHandle> {\n if (handle) {\n const state = await handle.requestPermission?.({ mode: 'readwrite' });\n if (state === undefined || state === 'granted') return handle;\n throw new Error('permission for the folder was not granted');\n }\n if (!options.requestDirectory) throw new Error('this page cannot ask for a folder');\n return options.requestDirectory();\n }\n async function grantHostfs({ id, source, readonly }: HostfsRequest): Promise<void> {\n try {\n if (!options.hostfs) throw new Error('this page gives no host folders');\n const grant = await options.hostfs(source, { readonly });\n worker.postMessage({ hostfsGrant: { id, grant } });\n } catch (err) {\n worker.postMessage({ hostfsGrant: { id, error: (err as Error).message ?? String(err) } });\n }\n }\n async function policy({ id, req }: { id: number; req: ProcessMountRequest }): Promise<void> {\n const decide = options.processMounts;\n let allowed = false;\n try {\n allowed = typeof decide === 'function' ? await decide(req) : decide !== false;\n } catch {}\n worker.postMessage({ mountAllowed: { id, allowed } });\n }\n const pendingMedium = ({ target, source, handle }: PendingMedium) =>\n options.onMountPending?.({\n target,\n source,\n insert: async () =>\n void (await call({ op: 'insert', target, source, handle: await chosen(handle) })),\n });\n worker.addEventListener(\n 'message',\n ({\n data,\n }: MessageEvent<\n | Reply\n | TransportCall\n | { medium: PendingMedium }\n | { hostfs: HostfsRequest }\n | { mountPolicy: { id: number; req: ProcessMountRequest } }\n >) => {\n if ('net' in data) return bridge?.answer(data);\n if ('mountPolicy' in data) return void policy(data.mountPolicy);\n if ('medium' in data) return pendingMedium(data.medium);\n if ('hostfs' in data) return void grantHostfs(data.hostfs);\n const call = pending.get(data.id);\n if (!call) return;\n if (data.fd !== undefined) return call.output?.(data.fd, data.bytes as Uint8Array);\n if (data.started !== undefined) return call.started?.(data.started);\n pending.delete(data.id);\n if (data.error !== undefined) call.reject(new Error(data.error));\n else call.resolve(data.result);\n }\n );\n worker.addEventListener('error', (event) => {\n event.preventDefault();\n fail(new Error(`slicc-kernel worker failed: ${event.message}`));\n });\n\n function request(\n req: KernelCall,\n handlers: Handlers = {}\n ): { id: number; done: Promise<unknown> } {\n const id = ++nextId;\n if (failure) return { id, done: Promise.reject(failure) };\n const done = new Promise((resolve, reject) => {\n pending.set(id, { resolve, reject, ...handlers });\n worker.postMessage({ ...req, id });\n });\n return { id, done };\n }\n\n const call = (req: KernelCall, handlers?: Handlers) => request(req, handlers).done;\n\n async function openTerminal(argv: string[], opts: TerminalOptions = {}): Promise<Terminal> {\n const { onData, ...options } = opts;\n let listener = onData ?? null;\n const backlog: Uint8Array[] = [];\n const started = Promise.withResolvers<number>();\n const { id, done } = request(\n { op: 'open-terminal', argv, options },\n {\n output: (_fd, bytes) => (listener ? listener(bytes) : backlog.push(bytes)),\n started: started.resolve,\n }\n );\n done.catch(started.reject);\n const pid = await started.promise;\n const send = (action: TerminalAction) =>\n void call({ op: 'terminal', terminal: id, ...action }).catch(() => undefined);\n return {\n pid,\n exited: done as Promise<number>,\n get onData() {\n return listener;\n },\n set onData(next) {\n listener = next;\n if (next) for (const bytes of backlog.splice(0)) next(bytes);\n },\n write: (data) =>\n send({\n action: 'write',\n bytes: typeof data === 'string' ? new TextEncoder().encode(data) : data,\n }),\n resize: (cols, rows) => send({ action: 'resize', cols, rows }),\n signal: (name) => send({ action: 'signal', signal: name }),\n close: () => send({ action: 'close' }),\n };\n }\n\n await call({\n op: 'init',\n ...(options.root ? { root: options.root } : {}),\n ...(options.modules ? { modules: options.modules } : {}),\n ...(options.env ? { env: options.env } : {}),\n ...(options.metadata !== undefined ? { metadata: options.metadata } : {}),\n ...(options.media !== undefined ? { media: options.media } : {}),\n ...(transport ? { transport: transport.traits } : {}),\n ...(options.hostfs ? { hostfs: true } : {}),\n ...(options.processMounts !== undefined\n ? {\n processMounts:\n typeof options.processMounts === 'function' ? 'ask' : options.processMounts,\n }\n : {}),\n });\n\n return {\n async run(argv, runOptions = {}) {\n const { onStdout, onStderr, stdin, ...rest } = runOptions;\n const streams = { 1: streamer(onStdout), 2: streamer(onStderr) };\n const input = typeof stdin === 'string' ? new TextEncoder().encode(stdin) : stdin;\n const result = (await call(\n { op: 'run', argv, options: { ...rest, ...(input ? { stdin: input } : {}) } },\n { output: (fd, bytes) => streams[fd](bytes) }\n )) as { status: number; stdout: Uint8Array; stderr: Uint8Array };\n const decoder = new TextDecoder();\n return {\n status: result.status,\n stdout: decoder.decode(result.stdout),\n stderr: decoder.decode(result.stderr),\n };\n },\n openTerminal,\n connect: async () => (await call({ op: 'connect' })) as MessagePort,\n mount: async (spec) => (await call({ op: 'mount', spec })) as MountEntry,\n umount: async (target) => void (await call({ op: 'umount', target })),\n mounts: async () => (await call({ op: 'mounts' })) as MountEntry[],\n insert: async (target, handle) => void (await call({ op: 'insert', target, handle })),\n terminate() {\n fail(new Error('slicc-kernel terminated'));\n worker.terminate();\n },\n };\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["export const BODY_IDLE_MS = 5 * 60 * 1000;\n\nexport function idleFailure(ms: number): Error {\n return Object.assign(new Error(`the response body sent no data for ${ms} ms`), {\n code: 'ETIMEDOUT',\n });\n}\n\nexport async function readWithin<T>(\n reader: ReadableStreamDefaultReader<T>,\n ms: number\n): Promise<ReadableStreamReadResult<T>> {\n if (!(ms > 0 && ms < Number.POSITIVE_INFINITY)) return reader.read();\n let timer: ReturnType<typeof setTimeout> | undefined;\n const idle = new Promise<never>((_, reject) => {\n timer = setTimeout(() => reject(idleFailure(ms)), ms);\n });\n try {\n return await Promise.race([reader.read(), idle]);\n } finally {\n clearTimeout(timer);\n }\n}\n", "import { BODY_IDLE_MS, readWithin } from './body-idle.ts';\nimport type { TransportCall, TransportReply } from './kernel/net/remote-transport.ts';\nimport type {\n HeaderList,\n RealmTransport,\n RealmTransportRequest,\n RealmTransportResponse,\n RealmTransportTraits,\n} from './kernel/net/transport.ts';\n\nexport type {\n HeaderList,\n RealmTransport as NetworkTransport,\n RealmTransportRequest as NetworkRequest,\n RealmTransportResponse as NetworkResponse,\n RealmTransportTraits as NetworkTraits,\n};\n\nexport interface FetchTransportOptions {\n fetch?: typeof globalThis.fetch;\n maxRequestBody?: number;\n hint?: string;\n bodyIdleMs?: number;\n}\n\nconst MAX_REQUEST_BODY = 64 * 1024 * 1024;\n\nfunction joinHeaders(headers: HeaderList): Headers {\n const out = new Headers();\n for (const [name, value] of headers) {\n try {\n out.append(name, value);\n } catch {}\n }\n return out;\n}\n\nasync function* chunks(\n body: ReadableStream<Uint8Array> | null,\n idleMs: number\n): AsyncGenerator<Uint8Array> {\n if (!body) return;\n const reader = body.getReader();\n try {\n for (\n let next = await readWithin(reader, idleMs);\n !next.done;\n next = await readWithin(reader, idleMs)\n ) {\n if (next.value.byteLength > 0) yield next.value;\n }\n } finally {\n await reader.cancel().catch(() => undefined);\n }\n}\n\nexport function fetchTransport(options: FetchTransportOptions = {}): RealmTransport {\n const send = options.fetch ?? globalThis.fetch.bind(globalThis);\n return {\n traits: {\n manualRedirects: false,\n encodedBodies: false,\n maxRequestBody: options.maxRequestBody ?? MAX_REQUEST_BODY,\n crossOrigin: 'cors',\n },\n async fetch(request: RealmTransportRequest): Promise<RealmTransportResponse> {\n let response: Response;\n try {\n response = await send(request.url, {\n method: request.method,\n headers: joinHeaders(request.headers),\n ...(request.body ? { body: request.body as BodyInit } : {}),\n signal: request.signal,\n redirect: 'follow',\n credentials: 'omit',\n mode: 'cors',\n });\n } catch (e) {\n if (request.signal.aborted) throw e;\n throw Object.assign(\n new Error(\n `fetch ${request.url} failed (unreachable, or not allowed by CORS)${options.hint ? `: ${options.hint}` : ''}`\n ),\n { status: 502 }\n );\n }\n const headers: Array<[string, string]> = [];\n response.headers.forEach((value, name) => {\n headers.push([name, value]);\n });\n const body = chunks(response.body, options.bodyIdleMs ?? BODY_IDLE_MS);\n return {\n status: response.status,\n statusText: response.statusText,\n headers,\n body,\n cancel: async () => {\n await body.return(undefined);\n await response.body?.cancel().catch(() => undefined);\n },\n };\n },\n };\n}\n\nexport interface TransportPeer {\n postMessage(message: TransportReply, transfer?: Transferable[]): void;\n}\n\nexport interface TransportServer {\n answer(call: TransportCall): void;\n close(): void;\n}\n\nexport function serveTransport(peer: TransportPeer, transport: RealmTransport): TransportServer {\n const open = new Map<\n number,\n { abort: AbortController; body?: AsyncIterator<Uint8Array>; response?: RealmTransportResponse }\n >();\n const fail = (nid: number, e: unknown) => {\n open.delete(nid);\n const { status, code } = e as { status?: unknown; code?: unknown };\n peer.postMessage({\n net: 'error',\n nid,\n message: e instanceof Error ? e.message : String(e),\n ...(typeof status === 'number' ? { status } : {}),\n ...(typeof code === 'string' ? { code } : {}),\n });\n };\n const start = async (call: Extract<TransportCall, { net: 'fetch' }>) => {\n const abort = new AbortController();\n const entry: { abort: AbortController; body?: AsyncIterator<Uint8Array> } = { abort };\n open.set(call.nid, entry);\n try {\n const response = await transport.fetch({\n url: call.url,\n method: call.method,\n headers: call.headers,\n ...(call.body ? { body: call.body } : {}),\n signal: abort.signal,\n });\n if (!open.has(call.nid)) {\n await response.cancel();\n return;\n }\n open.set(call.nid, { abort, body: response.body[Symbol.asyncIterator](), response });\n peer.postMessage({\n net: 'head',\n nid: call.nid,\n status: response.status,\n statusText: response.statusText,\n headers: response.headers,\n });\n } catch (e) {\n fail(call.nid, e);\n }\n };\n const read = async (nid: number) => {\n const body = open.get(nid)?.body;\n if (!body) return;\n try {\n const next = await body.next();\n if (next.done) {\n open.delete(nid);\n peer.postMessage({ net: 'end', nid });\n } else {\n const bytes = next.value.slice();\n peer.postMessage({ net: 'chunk', nid, bytes }, [bytes.buffer]);\n }\n } catch (e) {\n fail(nid, e);\n }\n };\n const drop = (nid: number) => {\n const entry = open.get(nid);\n open.delete(nid);\n entry?.abort.abort();\n void entry?.response?.cancel().catch(() => undefined);\n };\n return {\n answer(call) {\n if (call.net === 'fetch') void start(call);\n else if (call.net === 'read') void read(call.nid);\n else drop(call.nid);\n },\n close() {\n for (const nid of [...open.keys()]) drop(nid);\n },\n };\n}\n", "import type {\n HeaderList,\n RealmTransport,\n RealmTransportRequest,\n RealmTransportResponse,\n RealmTransportTraits,\n} from './transport.ts';\n\nexport type TransportCall =\n | {\n net: 'fetch';\n nid: number;\n url: string;\n method: string;\n headers: HeaderList;\n body?: Uint8Array;\n }\n | { net: 'read'; nid: number }\n | { net: 'cancel'; nid: number };\n\nexport type TransportReply =\n | { net: 'head'; nid: number; status: number; statusText: string; headers: HeaderList }\n | { net: 'chunk'; nid: number; bytes: Uint8Array }\n | { net: 'end'; nid: number }\n | { net: 'error'; nid: number; message: string; status?: number; code?: string };\n\nexport interface TransportPort {\n postMessage(message: TransportCall): void;\n}\n\nexport class TransportError extends Error {\n readonly status: number | undefined;\n readonly code: string | undefined;\n\n constructor(message: string, status?: number, code?: string) {\n super(message);\n this.status = status;\n this.code = code;\n }\n}\n\ninterface Waiter {\n resolve(reply: TransportReply): void;\n reject(error: Error): void;\n}\n\nexport class RemoteTransport implements RealmTransport {\n readonly traits: RealmTransportTraits;\n\n private readonly port: TransportPort;\n\n private readonly waiting = new Map<number, Waiter>();\n\n private nextId = 0;\n\n private failure: Error | undefined;\n\n constructor(port: TransportPort, traits: RealmTransportTraits) {\n this.port = port;\n this.traits = traits;\n }\n\n receive(reply: TransportReply): void {\n const waiter = this.waiting.get(reply.nid);\n if (!waiter) return;\n this.waiting.delete(reply.nid);\n if (reply.net === 'error') {\n waiter.reject(new TransportError(reply.message, reply.status, reply.code));\n } else waiter.resolve(reply);\n }\n\n fail(error: Error): void {\n this.failure = error;\n for (const waiter of this.waiting.values()) waiter.reject(error);\n this.waiting.clear();\n }\n\n private ask(call: TransportCall): Promise<TransportReply> {\n if (this.failure) return Promise.reject(this.failure);\n return new Promise((resolve, reject) => {\n this.waiting.set(call.nid, { resolve, reject });\n this.port.postMessage(call);\n });\n }\n\n private cancel(nid: number): void {\n const waiter = this.waiting.get(nid);\n this.waiting.delete(nid);\n waiter?.reject(new TransportError('the request was cancelled'));\n this.port.postMessage({ net: 'cancel', nid });\n }\n\n async fetch(request: RealmTransportRequest): Promise<RealmTransportResponse> {\n const nid = ++this.nextId;\n const { signal } = request;\n signal.throwIfAborted();\n let finished = false;\n const abort = () => {\n finished = true;\n this.cancel(nid);\n };\n signal.addEventListener('abort', abort, { once: true });\n const finish = () => {\n if (finished) return;\n finished = true;\n signal.removeEventListener('abort', abort);\n };\n let head: TransportReply;\n try {\n head = await this.ask({\n net: 'fetch',\n nid,\n url: request.url,\n method: request.method,\n headers: request.headers,\n ...(request.body ? { body: request.body } : {}),\n });\n } catch (e) {\n finish();\n throw e;\n }\n const { status, statusText, headers } = head as Extract<TransportReply, { net: 'head' }>;\n const read = async (): Promise<Uint8Array | undefined> => {\n if (finished) return undefined;\n const reply = await this.ask({ net: 'read', nid }).catch((e: unknown) => {\n finish();\n throw e;\n });\n if (reply.net === 'chunk') return reply.bytes;\n finish();\n return undefined;\n };\n const cancel = async () => {\n if (finished) return;\n finish();\n this.cancel(nid);\n };\n return {\n status,\n statusText,\n headers,\n cancel,\n body: {\n [Symbol.asyncIterator]: () => ({\n next: async () => {\n const bytes = await read();\n return bytes ? { value: bytes, done: false } : { value: undefined, done: true };\n },\n return: async () => {\n await cancel();\n return { value: undefined, done: true };\n },\n }),\n },\n };\n }\n}\n", "import type { WatchChange } from '../fs/watch.ts';\nimport type { TransportCall, TransportReply } from '../kernel/net/remote-transport.ts';\nimport type { RealmTransportTraits } from '../kernel/net/transport.ts';\nimport type { MountSpec } from '../mount/mount-fs.ts';\n\nexport const PROTOCOL: readonly [number, number] = [1, 3];\n\nexport interface ClientHello {\n protocol: readonly [number, number];\n lock?: string;\n}\n\nexport interface KernelHello {\n protocol: readonly [number, number];\n lock?: string;\n traits?: RealmTransportTraits;\n error?: string;\n}\n\nexport interface SpawnRequestOptions {\n cwd?: string;\n env?: Record<string, string>;\n stdin?: Uint8Array;\n pgid?: number;\n}\n\nexport interface TerminalRequestOptions {\n cwd?: string;\n env?: Record<string, string>;\n cols?: number;\n rows?: number;\n}\n\nexport type TerminalAction =\n | { action: 'write'; bytes: Uint8Array }\n | { action: 'resize'; cols: number; rows: number }\n | { action: 'signal'; signal: string }\n | { action: 'close' };\n\nexport const FS_METHODS = [\n 'readFile',\n 'writeFile',\n 'stat',\n 'lstat',\n 'readdir',\n 'mkdir',\n 'rm',\n 'rename',\n 'realpath',\n 'symlink',\n 'readlink',\n 'exists',\n] as const;\n\nexport type FsMethod = (typeof FS_METHODS)[number];\n\nexport type ClientCall =\n | { op: 'spawn'; argv: string[]; options: SpawnRequestOptions }\n | { op: 'open-terminal'; argv: string[]; options: TerminalRequestOptions }\n | ({ op: 'terminal'; terminal: number } & TerminalAction)\n | { op: 'kill'; pid: number; signal: string }\n | { op: 'ps' }\n | { op: 'fs'; method: FsMethod; args: unknown[] }\n | { op: 'watch'; paths: string[]; recursive: boolean }\n | { op: 'unwatch'; watch: number }\n | { op: 'mount'; spec: MountSpec }\n | { op: 'umount'; target: string }\n | { op: 'mounts' }\n | { op: 'detach'; kill?: boolean };\n\nexport type ClientRequest = ClientCall & { id: number };\n\nexport interface ClientReply {\n id: number;\n result?: unknown;\n error?: string;\n code?: string;\n fd?: 1 | 2;\n bytes?: Uint8Array;\n started?: number;\n}\n\nexport type ClientMessage = { hello: ClientHello } | ClientRequest | TransportCall;\n\nexport interface WatchEvent {\n watch: number;\n change: WatchChange;\n}\n\nexport type KernelMessage = { hello: KernelHello } | ClientReply | WatchEvent | TransportReply;\n\nexport interface ProcessEntry {\n pid: number;\n ppid: number;\n pgid: number;\n sid: number;\n argv: string[];\n tty: string | null;\n started: number;\n state: 'S' | 'Z';\n memory: number;\n}\n\nexport interface MessagePortLike {\n postMessage(message: unknown, transfer?: Transferable[]): void;\n addEventListener(type: 'message' | 'close', handler: (event: MessageEvent) => void): void;\n start?(): void;\n close?(): void;\n}\n\nexport interface LockManagerLike {\n request(name: string, callback: () => Promise<unknown> | unknown): Promise<unknown>;\n}\n\nexport function locksOf(scope: object = globalThis): LockManagerLike | undefined {\n const locks = (scope as { navigator?: { locks?: LockManagerLike } }).navigator?.locks;\n return typeof locks?.request === 'function' ? locks : undefined;\n}\n\nexport function versionError(theirs: unknown): string | undefined {\n const major = Array.isArray(theirs) ? theirs[0] : undefined;\n if (major === PROTOCOL[0]) return undefined;\n const named = typeof major === 'number' ? `${major}.x` : 'without a version';\n return `slicc-kernel client protocol ${named} is not supported: this side speaks ${PROTOCOL.join('.')}`;\n}\n", "import type { FsStat } from '../fs/types.ts';\nimport type { WatchChange } from '../fs/watch.ts';\nimport { RemoteTransport, type TransportReply } from '../kernel/net/remote-transport.ts';\nimport type {\n RealmTransport,\n RealmTransportRequest,\n RealmTransportResponse,\n} from '../kernel/net/transport.ts';\nimport type { MountEntry, MountSpec } from '../mount/mount-fs.ts';\nimport {\n type ClientCall,\n type ClientReply,\n type FsMethod,\n type KernelHello,\n type LockManagerLike,\n locksOf,\n type MessagePortLike,\n PROTOCOL,\n type ProcessEntry,\n type TerminalAction,\n versionError,\n} from './protocol.ts';\n\nexport type { WatchChange } from '../fs/watch.ts';\nexport type { ProcessEntry } from './protocol.ts';\n\nexport class KernelGoneError extends Error {\n constructor(message = 'the slicc-kernel this client was attached to is gone') {\n super(message);\n this.name = 'KernelGoneError';\n }\n}\n\nexport class KernelCallError extends Error {\n readonly code: string | undefined;\n\n constructor(message: string, code?: string) {\n super(message);\n this.name = 'KernelCallError';\n this.code = code;\n }\n}\n\nexport interface AttachOptions {\n timeoutMs?: number;\n locks?: LockManagerLike | null;\n}\n\nexport interface SpawnOptions {\n cwd?: string;\n env?: Record<string, string>;\n stdin?: string | Uint8Array;\n group?: 'new';\n pgid?: number;\n onStdout?: (bytes: Uint8Array) => void;\n onStderr?: (bytes: Uint8Array) => void;\n}\n\nexport interface SpawnedProcess {\n readonly pid: number;\n readonly pgid: number;\n readonly exited: Promise<number>;\n signal(name?: string): Promise<void>;\n}\n\nexport interface ClientRunOptions {\n cwd?: string;\n env?: Record<string, string>;\n stdin?: string | Uint8Array;\n onStdout?: (text: string) => void;\n onStderr?: (text: string) => void;\n}\n\nexport interface ClientRunResult {\n pid: number;\n status: number;\n stdout: string;\n stderr: string;\n}\n\nexport interface ClientTerminalOptions {\n cwd?: string;\n env?: Record<string, string>;\n cols?: number;\n rows?: number;\n onData?: (bytes: Uint8Array) => void;\n}\n\nexport interface ClientTerminal {\n readonly pid: number;\n readonly exited: Promise<number>;\n onData: ((bytes: Uint8Array) => void) | null;\n write(data: string | Uint8Array): void;\n resize(cols: number, rows: number): void;\n signal(name: string): void;\n close(): void;\n}\n\nexport interface ClientFs {\n readFile(path: string): Promise<Uint8Array>;\n readText(path: string): Promise<string>;\n writeFile(path: string, data: string | Uint8Array): Promise<void>;\n stat(path: string): Promise<FsStat>;\n lstat(path: string): Promise<FsStat>;\n readdir(path: string): Promise<string[]>;\n mkdir(path: string): Promise<void>;\n rm(path: string, options?: { force?: boolean }): Promise<void>;\n rename(from: string, to: string): Promise<void>;\n realpath(path: string): Promise<string>;\n symlink(target: string, path: string): Promise<void>;\n readlink(path: string): Promise<string>;\n exists(path: string): Promise<boolean>;\n watch(\n paths: string[],\n options: { recursive?: boolean },\n onChange: (change: WatchChange) => void\n ): Promise<{ close(): void }>;\n}\n\nexport type ClientFetchRequest = Omit<RealmTransportRequest, 'signal'> & { signal?: AbortSignal };\n\nexport interface KernelClient {\n readonly protocol: readonly [number, number];\n readonly transport: RealmTransport;\n readonly closed: Promise<Error>;\n spawn(argv: string[], options?: SpawnOptions): Promise<SpawnedProcess>;\n run(argv: string[], options?: ClientRunOptions): Promise<ClientRunResult>;\n openTerminal(argv: string[], options?: ClientTerminalOptions): Promise<ClientTerminal>;\n ps(): Promise<ProcessEntry[]>;\n mount(spec: MountSpec): Promise<MountEntry>;\n umount(target: string): Promise<void>;\n mounts(): Promise<MountEntry[]>;\n kill(pid: number, signal?: string): Promise<void>;\n fetch(request: ClientFetchRequest): Promise<RealmTransportResponse>;\n readonly fs: ClientFs;\n close(options?: { kill?: boolean }): Promise<void>;\n}\n\ninterface Pending {\n resolve: (value: unknown) => void;\n reject: (error: Error) => void;\n output?: (fd: 1 | 2, bytes: Uint8Array) => void;\n started?: (pid: number) => void;\n}\n\ntype Handlers = Omit<Pending, 'resolve' | 'reject'>;\n\nconst encoder = new TextEncoder();\nconst bytesOf = (data: string | Uint8Array) =>\n typeof data === 'string' ? encoder.encode(data) : data;\n\nconst UNAVAILABLE = {\n manualRedirects: false,\n encodedBodies: false,\n maxRequestBody: 0,\n unavailable: true,\n} as const;\n\nasync function holdLock(\n locks: LockManagerLike | undefined\n): Promise<{ name?: string; release(): void }> {\n if (!locks) return { release() {} };\n const name = `slicc-kernel-client:${crypto.randomUUID()}`;\n const granted = Promise.withResolvers<void>();\n const held = Promise.withResolvers<void>();\n void locks.request(name, () => {\n granted.resolve();\n return held.promise;\n });\n await granted.promise;\n return { name, release: () => held.resolve() };\n}\n\nfunction concat(chunks: Uint8Array[]): Uint8Array {\n const out = new Uint8Array(chunks.reduce((n, c) => n + c.length, 0));\n let at = 0;\n for (const chunk of chunks) {\n out.set(chunk, at);\n at += chunk.length;\n }\n return out;\n}\n\nclass Channel {\n readonly greeted = Promise.withResolvers<KernelHello>();\n readonly ended = Promise.withResolvers<Error>();\n remote: RemoteTransport | undefined;\n failure: Error | undefined;\n private readonly pending = new Map<number, Pending>();\n readonly watching = new Map<number, (change: WatchChange) => void>();\n 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 call of this.pending.values()) call.reject(error);\n this.pending.clear();\n this.release();\n this.port.close?.();\n this.ended.resolve(error);\n }\n\n request(call: ClientCall, handlers: Handlers = {}): { id: number; done: Promise<unknown> } {\n const id = ++this.nextId;\n const { failure } = this;\n if (failure) return { id, done: Promise.reject(failure) };\n const done = new Promise((resolve, reject) => {\n this.pending.set(id, { resolve, reject, ...handlers });\n this.port.postMessage({ ...call, id });\n });\n return { id, done };\n }\n\n call(call: ClientCall): Promise<unknown> {\n return this.request(call).done;\n }\n\n private receive(data: {\n hello?: KernelHello;\n net?: unknown;\n bye?: string;\n watch?: number;\n change?: WatchChange;\n }): void {\n if (data.watch !== undefined) {\n this.watching.get(data.watch)?.(data.change as WatchChange);\n return;\n }\n if (data.bye !== undefined) {\n this.end(new KernelGoneError(data.bye));\n return;\n }\n if (data.hello) {\n this.greeted.resolve(data.hello);\n return;\n }\n if (data.net !== undefined) {\n this.remote?.receive(data as TransportReply);\n return;\n }\n const reply = data as ClientReply;\n const call = this.pending.get(reply.id);\n if (!call) return;\n if (reply.fd !== undefined) {\n call.output?.(reply.fd, reply.bytes as Uint8Array);\n return;\n }\n if (reply.started !== undefined) {\n call.started?.(reply.started);\n return;\n }\n this.pending.delete(reply.id);\n if (reply.error !== undefined) call.reject(new KernelCallError(reply.error, reply.code));\n else call.resolve(reply.result);\n }\n}\n\nasync function spawnOn(\n channel: Channel,\n argv: string[],\n opts: SpawnOptions\n): Promise<SpawnedProcess> {\n const { onStdout, onStderr, stdin, group: _, ...rest } = opts;\n if (opts.pgid !== undefined)\n await since(channel, 3, 'spawn into a process group', async () => {});\n const started = Promise.withResolvers<number>();\n const options = { ...rest, ...(stdin !== undefined ? { stdin: bytesOf(stdin) } : {}) };\n const { done } = channel.request(\n { op: 'spawn', argv, options },\n {\n output: (fd, bytes) => (fd === 1 ? onStdout : onStderr)?.(bytes),\n started: started.resolve,\n }\n );\n done.catch(started.reject);\n const pid = await started.promise;\n const pgid = opts.pgid ?? pid;\n return {\n pid,\n pgid,\n exited: done as Promise<number>,\n signal: async (name = 'SIGTERM') =>\n void (await channel.call({ op: 'kill', pid: -pgid, signal: name })),\n };\n}\n\nasync function runOn(\n channel: Channel,\n argv: string[],\n opts: ClientRunOptions\n): Promise<ClientRunResult> {\n const { onStdout, onStderr, ...rest } = opts;\n const chunks: Record<1 | 2, Uint8Array[]> = { 1: [], 2: [] };\n const live = { 1: new TextDecoder(), 2: new TextDecoder() };\n const tee = (fd: 1 | 2, on?: (text: string) => void) => (bytes: Uint8Array) => {\n chunks[fd].push(bytes);\n on?.(live[fd].decode(bytes, { stream: true }));\n };\n const child = await spawnOn(channel, argv, {\n ...rest,\n onStdout: tee(1, onStdout),\n onStderr: tee(2, onStderr),\n });\n const status = await child.exited;\n const text = (fd: 1 | 2) => new TextDecoder().decode(concat(chunks[fd]));\n return { pid: child.pid, status, stdout: text(1), stderr: text(2) };\n}\n\nasync function terminalOn(\n channel: Channel,\n argv: string[],\n opts: ClientTerminalOptions\n): Promise<ClientTerminal> {\n const { onData, ...options } = opts;\n let listener = onData ?? null;\n const backlog: Uint8Array[] = [];\n const started = Promise.withResolvers<number>();\n const { id, done } = channel.request(\n { op: 'open-terminal', argv, options },\n {\n output: (_fd, bytes) => (listener ? listener(bytes) : backlog.push(bytes)),\n started: started.resolve,\n }\n );\n done.catch(started.reject);\n const pid = await started.promise;\n const send = (action: TerminalAction) =>\n void channel.call({ op: 'terminal', terminal: id, ...action }).catch(() => undefined);\n return {\n pid,\n exited: done as Promise<number>,\n get onData() {\n return listener;\n },\n set onData(next) {\n listener = next;\n if (next) for (const bytes of backlog.splice(0)) next(bytes);\n },\n write: (data) => send({ action: 'write', bytes: bytesOf(data) }),\n resize: (cols, rows) => send({ action: 'resize', cols, rows }),\n signal: (name) => send({ action: 'signal', signal: name }),\n close: () => send({ action: 'close' }),\n };\n}\n\nfunction fsOn(channel: Channel): ClientFs {\n const fs = (method: FsMethod, ...args: unknown[]) => channel.call({ op: 'fs', method, args });\n const done = async (method: FsMethod, ...args: unknown[]) => void (await fs(method, ...args));\n return {\n readFile: (path) => fs('readFile', path) as Promise<Uint8Array>,\n readText: async (path) => new TextDecoder().decode((await fs('readFile', path)) as Uint8Array),\n writeFile: (path, data) => done('writeFile', path, data),\n stat: (path) => fs('stat', path) as Promise<FsStat>,\n lstat: (path) => fs('lstat', path) as Promise<FsStat>,\n readdir: (path) => fs('readdir', path) as Promise<string[]>,\n mkdir: (path) => done('mkdir', path),\n rm: (path, o = {}) => done('rm', path, o.force === true),\n rename: (from, to) => done('rename', from, to),\n realpath: (path) => fs('realpath', path) as Promise<string>,\n symlink: (target, path) => done('symlink', target, path),\n readlink: (path) => fs('readlink', path) as Promise<string>,\n exists: (path) => fs('exists', path) as Promise<boolean>,\n async watch(paths, options, onChange) {\n if (channel.protocol[1] < 1) {\n throw new KernelCallError(\n `this kernel speaks protocol ${channel.protocol.join('.')}, which has no watch`,\n 'ENOSYS'\n );\n }\n const { id, done } = channel.request({\n op: 'watch',\n paths,\n recursive: options.recursive === true,\n });\n channel.watching.set(id, onChange);\n try {\n await done;\n } catch (error) {\n channel.watching.delete(id);\n throw error;\n }\n return {\n close: () => {\n if (!channel.watching.delete(id)) return;\n void channel.call({ op: 'unwatch', watch: id }).catch(() => undefined);\n },\n };\n },\n };\n}\n\nfunction since(channel: Channel, minor: number, what: string, run: () => Promise<unknown>) {\n if (channel.protocol[1] < minor) {\n return Promise.reject(\n new KernelCallError(\n `this kernel speaks protocol ${channel.protocol.join('.')}, which has no ${what}`,\n 'ENOSYS'\n )\n );\n }\n return run();\n}\n\nasync function greet(\n channel: Channel,\n lock: string | undefined,\n timeoutMs: number\n): Promise<KernelHello> {\n channel.post({ hello: { protocol: PROTOCOL, ...(lock ? { lock } : {}) } });\n const timer = setTimeout(\n () =>\n channel.end(\n new KernelGoneError(`no slicc-kernel answered on this port within ${timeoutMs} ms`)\n ),\n timeoutMs\n );\n let hello: KernelHello;\n try {\n hello = await channel.greeted.promise;\n } finally {\n clearTimeout(timer);\n }\n const refused = hello.error ?? versionError(hello.protocol);\n if (refused) {\n const error = new Error(refused);\n channel.end(error);\n throw error;\n }\n return hello;\n}\n\nexport async function attachKernel(\n port: MessagePortLike,\n options: AttachOptions = {}\n): Promise<KernelClient> {\n const locks = options.locks === null ? undefined : (options.locks ?? locksOf());\n const own = await holdLock(locks);\n const channel = new Channel(port, own.release);\n const hello = await greet(channel, own.name, options.timeoutMs ?? 10_000);\n channel.protocol = hello.protocol;\n if (hello.lock && locks) void locks.request(hello.lock, () => channel.end(new KernelGoneError()));\n const transport = new RemoteTransport(\n { postMessage: (call) => channel.post(call) },\n hello.traits ?? UNAVAILABLE\n );\n channel.remote = transport;\n return {\n protocol: hello.protocol,\n transport,\n closed: channel.ended.promise,\n spawn: (argv, opts = {}) => spawnOn(channel, argv, opts),\n run: (argv, opts = {}) => runOn(channel, argv, opts),\n openTerminal: (argv, opts = {}) => terminalOn(channel, argv, opts),\n ps: () => channel.call({ op: 'ps' }) as Promise<ProcessEntry[]>,\n mount: (spec) =>\n since(channel, 2, 'mount', () => channel.call({ op: 'mount', spec })) as Promise<MountEntry>,\n umount: async (target) =>\n void (await since(channel, 2, 'umount', () => channel.call({ op: 'umount', target }))),\n mounts: () =>\n since(channel, 2, 'mounts', () => channel.call({ op: 'mounts' })) as Promise<MountEntry[]>,\n kill: async (pid, signal = 'SIGTERM') => void (await channel.call({ op: 'kill', pid, signal })),\n fetch: (req) => {\n const { signal, ...rest } = req;\n return transport.fetch({ ...rest, signal: signal ?? new AbortController().signal });\n },\n fs: fsOn(channel),\n async close(o = {}) {\n if (channel.failure) return;\n await channel\n .call({ op: 'detach', ...(o.kill ? { kill: true } : {}) })\n .catch(() => undefined);\n channel.end(new KernelGoneError('this client is closed'));\n },\n };\n}\n", "import { BODY_IDLE_MS, readWithin } from './body-idle.ts';\nimport type {\n HeaderList,\n RealmTransport,\n RealmTransportRequest,\n RealmTransportResponse,\n} from './kernel/net/transport.ts';\n\nexport interface LocalProxyOptions {\n url: string;\n key: string;\n fetch?: typeof globalThis.fetch;\n}\n\nexport interface LocalProxyCheckOptions extends LocalProxyOptions {\n permissions?: Pick<Permissions, 'query'>;\n}\n\nexport interface LocalProxyTransportOptions extends LocalProxyOptions {\n maxRequestBody?: number;\n bodyIdleMs?: number;\n}\n\nexport interface LocalProxyProbe {\n rawFetch: number;\n requestBodyStreaming: boolean;\n maxRequestBodyBytes: number;\n}\n\nexport type LocalProxyStatus =\n | { state: 'ready'; probe: LocalProxyProbe }\n | { state: 'blocked' }\n | { state: 'unreachable'; permission: 'granted' | 'prompt' | 'unknown' }\n | { state: 'refused'; status: number; error: string }\n | { state: 'incompatible' };\n\nconst PATH = '/api/fetch-proxy';\nconst RAW_CONTENT_TYPE = 'application/vnd.slicc.raw-fetch';\nconst MAX_HEAD = 1024 * 1024;\nconst MAX_REQUEST_BODY = 64 * 1024 * 1024;\nconst PERMISSIONS = ['loopback-network', 'local-network-access'];\nconst LOOPBACK_PAGE = /^(127\\.\\d+\\.\\d+\\.\\d+|localhost|\\[::1\\])$/;\n\ninterface ResponseHead {\n status: number;\n statusText: string;\n headers: Array<[string, string]>;\n}\n\nconst failure = (message: string, status = 502) =>\n Object.assign(new Error(`local proxy: ${message}`), { status });\n\nfunction encodeHead(url: string, method: string, headers: HeaderList): string {\n return JSON.stringify({ url, method, headers }).replace(\n /[\\u007f-\uFFFF]/g,\n (c) => `\\\\u${c.charCodeAt(0).toString(16).padStart(4, '0')}`\n );\n}\n\nfunction hopHeaders(options: LocalProxyOptions, extra: Record<string, string>): Headers {\n return new Headers({ 'X-Bridge-Token': options.key, ...extra });\n}\n\nfunction send(options: LocalProxyOptions) {\n return options.fetch ?? globalThis.fetch.bind(globalThis);\n}\n\nasync function refusalMessage(response: Response): Promise<string> {\n const text = await response.text().catch(() => '');\n try {\n const parsed = JSON.parse(text) as { error?: unknown };\n if (typeof parsed.error === 'string') return parsed.error;\n } catch {}\n return text || response.statusText || `answered ${response.status}`;\n}\n\nasync function refusal(response: Response): Promise<Error> {\n return failure(await refusalMessage(response), response.ok ? 502 : response.status);\n}\n\nasync function permission(permissions: Pick<Permissions, 'query'> | undefined): Promise<string> {\n if (!permissions) return 'unknown';\n for (const name of PERMISSIONS) {\n try {\n return (await permissions.query({ name } as PermissionDescriptor)).state;\n } catch {}\n }\n return 'unknown';\n}\n\nfunction isHead(value: unknown): value is ResponseHead {\n const head = value as Partial<ResponseHead> | null;\n return (\n !!head &&\n typeof head.status === 'number' &&\n typeof head.statusText === 'string' &&\n Array.isArray(head.headers) &&\n head.headers.every(\n (pair) =>\n Array.isArray(pair) &&\n pair.length === 2 &&\n typeof pair[0] === 'string' &&\n typeof pair[1] === 'string'\n )\n );\n}\n\nfunction concat(a: Uint8Array, b: Uint8Array): Uint8Array {\n const out = new Uint8Array(a.byteLength + b.byteLength);\n out.set(a);\n out.set(b, a.byteLength);\n return out;\n}\n\nasync function readHead(\n reader: ReadableStreamDefaultReader<Uint8Array>,\n idleMs: number\n): Promise<{ head: ResponseHead; rest: Uint8Array }> {\n let buffer: Uint8Array = new Uint8Array(0);\n for (;;) {\n if (buffer.byteLength >= 4) {\n const length = new DataView(buffer.buffer, buffer.byteOffset, 4).getUint32(0);\n if (length > MAX_HEAD) throw failure(`response head of ${length} bytes`);\n if (buffer.byteLength >= 4 + length) {\n let head: unknown;\n try {\n head = JSON.parse(new TextDecoder().decode(buffer.subarray(4, 4 + length)));\n } catch {}\n if (!isHead(head)) throw failure('malformed response head');\n return { head, rest: buffer.subarray(4 + length) };\n }\n }\n const next = await readWithin(reader, idleMs);\n if (next.done) throw failure('closed before the response head');\n buffer = concat(buffer, next.value);\n }\n}\n\nasync function* chunks(\n rest: Uint8Array,\n reader: ReadableStreamDefaultReader<Uint8Array>,\n idleMs: number\n): AsyncGenerator<Uint8Array> {\n try {\n if (rest.byteLength > 0) yield rest;\n for (\n let next = await readWithin(reader, idleMs);\n !next.done;\n next = await readWithin(reader, idleMs)\n ) {\n if (next.value.byteLength > 0) yield next.value;\n }\n } finally {\n await reader.cancel().catch(() => undefined);\n }\n}\n\nexport async function checkLocalProxy(options: LocalProxyCheckOptions): Promise<LocalProxyStatus> {\n const onLoopback = LOOPBACK_PAGE.test(globalThis.location?.hostname ?? '');\n const permissions = onLoopback\n ? undefined\n : (options.permissions ?? globalThis.navigator?.permissions);\n if ((await permission(permissions)) === 'denied') return { state: 'blocked' };\n let response: Response;\n try {\n response = await send(options)(new URL(PATH, options.url), {\n method: 'POST',\n headers: hopHeaders(options, { 'X-Slicc-Raw-Probe': '1' }),\n credentials: 'omit',\n mode: 'cors',\n });\n } catch {\n const now = await permission(permissions);\n if (now === 'denied') return { state: 'blocked' };\n return {\n state: 'unreachable',\n permission: now === 'granted' || now === 'prompt' ? now : 'unknown',\n };\n }\n if (!response.ok) {\n return { state: 'refused', status: response.status, error: await refusalMessage(response) };\n }\n const reply = (await response.json().catch(() => null)) as Partial<LocalProxyProbe> | null;\n if (\n !reply ||\n typeof reply.rawFetch !== 'number' ||\n reply.rawFetch < 1 ||\n typeof reply.requestBodyStreaming !== 'boolean' ||\n typeof reply.maxRequestBodyBytes !== 'number'\n ) {\n return { state: 'incompatible' };\n }\n return {\n state: 'ready',\n probe: {\n rawFetch: reply.rawFetch,\n requestBodyStreaming: reply.requestBodyStreaming,\n maxRequestBodyBytes: reply.maxRequestBodyBytes,\n },\n };\n}\n\nexport async function probeLocalProxy(\n options: LocalProxyCheckOptions\n): Promise<LocalProxyProbe | null> {\n const status = await checkLocalProxy(options);\n return status.state === 'ready' ? status.probe : null;\n}\n\nexport function localProxyTransport(options: LocalProxyTransportOptions): RealmTransport {\n const endpoint = new URL(PATH, options.url);\n return {\n traits: {\n manualRedirects: true,\n encodedBodies: false,\n maxRequestBody: options.maxRequestBody ?? MAX_REQUEST_BODY,\n },\n async fetch(request: RealmTransportRequest): Promise<RealmTransportResponse> {\n let response: Response;\n try {\n response = await send(options)(endpoint, {\n method: 'POST',\n headers: hopHeaders(options, {\n 'X-Slicc-Raw-Request': encodeHead(request.url, request.method, request.headers),\n }),\n ...(request.body ? { body: request.body as BodyInit } : {}),\n signal: request.signal,\n credentials: 'omit',\n mode: 'cors',\n });\n } catch (e) {\n if (request.signal.aborted) throw e;\n throw failure(`${endpoint.origin} is unreachable or refuses this origin`);\n }\n const type = response.headers.get('content-type') ?? '';\n if (response.status !== 200 || !type.startsWith(RAW_CONTENT_TYPE) || !response.body) {\n throw await refusal(response);\n }\n const reader = response.body.getReader();\n const idleMs = options.bodyIdleMs ?? BODY_IDLE_MS;\n let framed: { head: ResponseHead; rest: Uint8Array };\n try {\n framed = await readHead(reader, idleMs);\n } catch (e) {\n await reader.cancel().catch(() => undefined);\n throw e;\n }\n const body = chunks(framed.rest, reader, idleMs);\n return {\n status: framed.head.status,\n statusText: framed.head.statusText,\n headers: framed.head.headers,\n body,\n cancel: async () => {\n await body.return(undefined);\n await reader.cancel().catch(() => undefined);\n },\n };\n },\n };\n}\n", "import type { TransportCall } from './kernel/net/remote-transport.ts';\nimport type { PendingMedium } from './launcher.ts';\nimport type { MediumHandle } from './mount/fsa.ts';\nimport type { HostfsGrantHook } from './mount/hostfs.ts';\nimport type { MountEntry, MountSpec } from './mount/mount-fs.ts';\nimport type { ProcessMountPolicy, ProcessMountRequest } from './mount/syscall.ts';\nimport type { KernelCall, TerminalAction } from './serve.ts';\nimport { type NetworkTransport, serveTransport } from './transport.ts';\n\nexport {\n type AttachOptions,\n attachKernel,\n type ClientFetchRequest,\n type ClientFs,\n type ClientRunOptions,\n type ClientRunResult,\n type ClientTerminal,\n type ClientTerminalOptions,\n KernelCallError,\n type KernelClient,\n KernelGoneError,\n type ProcessEntry,\n type SpawnedProcess,\n type SpawnOptions,\n type WatchChange,\n} from './client/attach.ts';\nexport {\n checkLocalProxy,\n type LocalProxyCheckOptions,\n type LocalProxyOptions,\n type LocalProxyProbe,\n type LocalProxyStatus,\n type LocalProxyTransportOptions,\n localProxyTransport,\n probeLocalProxy,\n} from './local-proxy-transport.ts';\nexport type { HostfsGrant, HostfsGrantHook } from './mount/hostfs.ts';\nexport type { MountEntry, MountSpec } from './mount/mount-fs.ts';\nexport type { ProcessMountPolicy, ProcessMountRequest } from './mount/syscall.ts';\nexport {\n type FetchTransportOptions,\n fetchTransport,\n type HeaderList,\n type NetworkRequest,\n type NetworkResponse,\n type NetworkTraits,\n type NetworkTransport,\n} from './transport.ts';\n\nexport interface NetworkOptions {\n transport?: NetworkTransport;\n}\n\nexport interface KernelOptions {\n root?: FileSystemDirectoryHandle;\n modules?: string;\n env?: Record<string, string>;\n metadata?: string | false;\n media?: string | false;\n worker?: string | URL;\n network?: NetworkOptions;\n requestDirectory?: () => Promise<FileSystemDirectoryHandle>;\n onMountPending?: (pending: MountPending) => void;\n hostfs?: HostfsGrantHook;\n processMounts?: ProcessMountPolicy;\n}\n\ninterface HostfsRequest {\n id: number;\n source: string;\n readonly: boolean;\n}\n\nexport interface MountPending {\n target: string;\n source: string;\n insert(): Promise<void>;\n}\n\nexport interface RunOptions {\n cwd?: string;\n env?: Record<string, string>;\n stdin?: string | Uint8Array;\n onStdout?: (text: string) => void;\n onStderr?: (text: string) => void;\n}\n\nexport interface RunResult {\n status: number;\n stdout: string;\n stderr: string;\n}\n\nexport interface Kernel {\n run(argv: string[], options?: RunOptions): Promise<RunResult>;\n openTerminal(argv: string[], options?: TerminalOptions): Promise<Terminal>;\n connect(): Promise<MessagePort>;\n mount(spec: MountSpec): Promise<MountEntry>;\n umount(target: string): Promise<void>;\n mounts(): Promise<MountEntry[]>;\n insert(target: string, handle: FileSystemDirectoryHandle): Promise<void>;\n terminate(): void;\n}\n\nexport interface TerminalOptions {\n cwd?: string;\n env?: Record<string, string>;\n cols?: number;\n rows?: number;\n onData?: (bytes: Uint8Array) => void;\n}\n\nexport type TerminalSignal =\n | 'SIGINT'\n | 'SIGTSTP'\n | 'SIGQUIT'\n | 'SIGHUP'\n | 'SIGTERM'\n | 'SIGKILL'\n | 'SIGCONT';\n\nexport interface Terminal {\n readonly pid: number;\n readonly exited: Promise<number>;\n onData: ((bytes: Uint8Array) => void) | null;\n write(data: string | Uint8Array): void;\n resize(cols: number, rows: number): void;\n signal(name: TerminalSignal): void;\n close(): void;\n}\n\ninterface Reply {\n id: number;\n result?: unknown;\n error?: string;\n fd?: 1 | 2;\n bytes?: Uint8Array;\n started?: number;\n}\n\ninterface Pending {\n resolve: (value: unknown) => void;\n reject: (error: Error) => void;\n output?: (fd: 1 | 2, bytes: Uint8Array) => void;\n started?: (pid: number) => void;\n}\n\ninterface Handlers {\n output?: Pending['output'];\n started?: Pending['started'];\n}\n\nconst ISOLATION =\n 'slicc-kernel needs a cross-origin isolated page (Cross-Origin-Opener-Policy: same-origin and Cross-Origin-Embedder-Policy: require-corp or credentialless)';\n\nfunction streamer(callback: ((text: string) => void) | undefined) {\n const decoder = new TextDecoder();\n return (bytes: Uint8Array) => callback?.(decoder.decode(bytes, { stream: true }));\n}\n\nexport async function createKernel(options: KernelOptions = {}): Promise<Kernel> {\n if (!globalThis.crossOriginIsolated) throw new Error(ISOLATION);\n const url = options.worker ?? new URL('./kernel-worker.js', import.meta.url);\n const worker = new Worker(url, { type: 'module', name: 'slicc-kernel' });\n const pending = new Map<number, Pending>();\n let nextId = 0;\n let failure: Error | undefined;\n\n const fail = (error: Error) => {\n failure = error;\n bridge?.close();\n for (const call of pending.values()) call.reject(error);\n pending.clear();\n };\n const transport = options.network?.transport;\n const bridge = transport ? serveTransport(worker, transport) : undefined;\n async function chosen(handle: MediumHandle | undefined): Promise<FileSystemDirectoryHandle> {\n if (handle) {\n const state = await handle.requestPermission?.({ mode: 'readwrite' });\n if (state === undefined || state === 'granted') return handle;\n throw new Error('permission for the folder was not granted');\n }\n if (!options.requestDirectory) throw new Error('this page cannot ask for a folder');\n return options.requestDirectory();\n }\n async function grantHostfs({ id, source, readonly }: HostfsRequest): Promise<void> {\n try {\n if (!options.hostfs) throw new Error('this page gives no host folders');\n const grant = await options.hostfs(source, { readonly });\n worker.postMessage({ hostfsGrant: { id, grant } });\n } catch (err) {\n worker.postMessage({ hostfsGrant: { id, error: (err as Error).message ?? String(err) } });\n }\n }\n async function policy({ id, req }: { id: number; req: ProcessMountRequest }): Promise<void> {\n const decide = options.processMounts;\n let allowed = false;\n try {\n allowed = typeof decide === 'function' ? await decide(req) : decide !== false;\n } catch {}\n worker.postMessage({ mountAllowed: { id, allowed } });\n }\n const pendingMedium = ({ target, source, handle }: PendingMedium) =>\n options.onMountPending?.({\n target,\n source,\n insert: async () =>\n void (await call({ op: 'insert', target, source, handle: await chosen(handle) })),\n });\n worker.addEventListener(\n 'message',\n ({\n data,\n }: MessageEvent<\n | Reply\n | TransportCall\n | { medium: PendingMedium }\n | { hostfs: HostfsRequest }\n | { mountPolicy: { id: number; req: ProcessMountRequest } }\n >) => {\n if ('net' in data) return bridge?.answer(data);\n if ('mountPolicy' in data) return void policy(data.mountPolicy);\n if ('medium' in data) return pendingMedium(data.medium);\n if ('hostfs' in data) return void grantHostfs(data.hostfs);\n const call = pending.get(data.id);\n if (!call) return;\n if (data.fd !== undefined) return call.output?.(data.fd, data.bytes as Uint8Array);\n if (data.started !== undefined) return call.started?.(data.started);\n pending.delete(data.id);\n if (data.error !== undefined) call.reject(new Error(data.error));\n else call.resolve(data.result);\n }\n );\n worker.addEventListener('error', (event) => {\n event.preventDefault();\n fail(new Error(`slicc-kernel worker failed: ${event.message}`));\n });\n\n function request(\n req: KernelCall,\n handlers: Handlers = {}\n ): { id: number; done: Promise<unknown> } {\n const id = ++nextId;\n if (failure) return { id, done: Promise.reject(failure) };\n const done = new Promise((resolve, reject) => {\n pending.set(id, { resolve, reject, ...handlers });\n worker.postMessage({ ...req, id });\n });\n return { id, done };\n }\n\n const call = (req: KernelCall, handlers?: Handlers) => request(req, handlers).done;\n\n async function openTerminal(argv: string[], opts: TerminalOptions = {}): Promise<Terminal> {\n const { onData, ...options } = opts;\n let listener = onData ?? null;\n const backlog: Uint8Array[] = [];\n const started = Promise.withResolvers<number>();\n const { id, done } = request(\n { op: 'open-terminal', argv, options },\n {\n output: (_fd, bytes) => (listener ? listener(bytes) : backlog.push(bytes)),\n started: started.resolve,\n }\n );\n done.catch(started.reject);\n const pid = await started.promise;\n const send = (action: TerminalAction) =>\n void call({ op: 'terminal', terminal: id, ...action }).catch(() => undefined);\n return {\n pid,\n exited: done as Promise<number>,\n get onData() {\n return listener;\n },\n set onData(next) {\n listener = next;\n if (next) for (const bytes of backlog.splice(0)) next(bytes);\n },\n write: (data) =>\n send({\n action: 'write',\n bytes: typeof data === 'string' ? new TextEncoder().encode(data) : data,\n }),\n resize: (cols, rows) => send({ action: 'resize', cols, rows }),\n signal: (name) => send({ action: 'signal', signal: name }),\n close: () => send({ action: 'close' }),\n };\n }\n\n await call({\n op: 'init',\n ...(options.root ? { root: options.root } : {}),\n ...(options.modules ? { modules: options.modules } : {}),\n ...(options.env ? { env: options.env } : {}),\n ...(options.metadata !== undefined ? { metadata: options.metadata } : {}),\n ...(options.media !== undefined ? { media: options.media } : {}),\n ...(transport ? { transport: transport.traits } : {}),\n ...(options.hostfs ? { hostfs: true } : {}),\n ...(options.processMounts !== undefined\n ? {\n processMounts:\n typeof options.processMounts === 'function' ? 'ask' : options.processMounts,\n }\n : {}),\n });\n\n return {\n async run(argv, runOptions = {}) {\n const { onStdout, onStderr, stdin, ...rest } = runOptions;\n const streams = { 1: streamer(onStdout), 2: streamer(onStderr) };\n const input = typeof stdin === 'string' ? new TextEncoder().encode(stdin) : stdin;\n const result = (await call(\n { op: 'run', argv, options: { ...rest, ...(input ? { stdin: input } : {}) } },\n { output: (fd, bytes) => streams[fd](bytes) }\n )) as { status: number; stdout: Uint8Array; stderr: Uint8Array };\n const decoder = new TextDecoder();\n return {\n status: result.status,\n stdout: decoder.decode(result.stdout),\n stderr: decoder.decode(result.stderr),\n };\n },\n openTerminal,\n connect: async () => (await call({ op: 'connect' })) as MessagePort,\n mount: async (spec) => (await call({ op: 'mount', spec })) as MountEntry,\n umount: async (target) => void (await call({ op: 'umount', target })),\n mounts: async () => (await call({ op: 'mounts' })) as MountEntry[],\n insert: async (target, handle) => void (await call({ op: 'insert', target, handle })),\n terminate() {\n fail(new Error('slicc-kernel terminated'));\n worker.terminate();\n },\n };\n}\n"],
5
+ "mappings": "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",
6
6
  "names": ["send", "chunks", "failure", "send", "done", "MAX_REQUEST_BODY", "concat", "chunks", "failure", "call", "options", "send"]
7
7
  }
@@ -225,7 +225,7 @@ function pinScript(url) {
225
225
  }
226
226
 
227
227
  // src/client/protocol.ts
228
- var PROTOCOL = [1, 2];
228
+ var PROTOCOL = [1, 3];
229
229
  var FS_METHODS = [
230
230
  "readFile",
231
231
  "writeFile",
@@ -483,10 +483,22 @@ function signalOf(host) {
483
483
  throw fsError("EINVAL", `this kernel names no signal ${name2}`);
484
484
  });
485
485
  }
486
+ function killGroups(host, pgids) {
487
+ if (pgids.length === 0) return;
488
+ void host.launcher().then((launcher) => {
489
+ for (const pgid of pgids) launcher.kill(-pgid, SIG.KILL);
490
+ });
491
+ }
492
+ function joinable(l, pgid, ours) {
493
+ const sid = l.groupSession(pgid);
494
+ if (sid === void 0) throw fsError("ESRCH", `no process group ${pgid}`);
495
+ if (!ours(sid)) throw fsError("EPERM", `process group ${pgid} is in another session`);
496
+ }
486
497
  function serveClient(port, host) {
487
498
  let state = "new";
488
499
  const terminals = /* @__PURE__ */ new Map();
489
500
  const groups = /* @__PURE__ */ new Set();
501
+ const sessions = /* @__PURE__ */ new Set();
490
502
  const watches = /* @__PURE__ */ new Map();
491
503
  let net;
492
504
  const ended = Promise.withResolvers();
@@ -503,13 +515,8 @@ function serveClient(port, host) {
503
515
  watches.clear();
504
516
  for (const session of terminals.values()) session.close();
505
517
  terminals.clear();
506
- const pids = [...groups];
518
+ if (kill) killGroups(host, [...groups]);
507
519
  groups.clear();
508
- if (kill && pids.length > 0) {
509
- void host.launcher().then((launcher) => {
510
- for (const pid of pids) launcher.kill(-pid, SIG.KILL);
511
- });
512
- }
513
520
  port.close?.();
514
521
  ended.resolve();
515
522
  }
@@ -542,6 +549,7 @@ function serveClient(port, host) {
542
549
  session.close();
543
550
  } else {
544
551
  terminals.set(req.id, session);
552
+ sessions.add(session.pid);
545
553
  reply(req.id, { started: session.pid });
546
554
  }
547
555
  try {
@@ -552,6 +560,7 @@ function serveClient(port, host) {
552
560
  }
553
561
  async function spawn(req, l) {
554
562
  const out = (fd) => (bytes) => reply(req.id, { fd, bytes: bytes.slice() });
563
+ if (req.options.pgid !== void 0) joinable(l, req.options.pgid, (sid) => sessions.has(sid));
555
564
  let leader;
556
565
  const result = await l.run(req.argv, {
557
566
  ...req.options,
@@ -561,7 +570,8 @@ function serveClient(port, host) {
561
570
  onStarted: (pid) => {
562
571
  leader = pid;
563
572
  if (state === "closed") return;
564
- groups.add(pid);
573
+ groups.add(req.options.pgid ?? pid);
574
+ if (req.options.pgid === void 0) sessions.add(pid);
565
575
  reply(req.id, { started: pid });
566
576
  }
567
577
  });
@@ -6715,6 +6725,17 @@ var JobTable = class {
6715
6725
  const parent = this.members.get(this.shown(pid))?.ppid;
6716
6726
  return parent === void 0 ? void 0 : this.shown(parent);
6717
6727
  }
6728
+ sessionOf(pgid) {
6729
+ for (const member of this.members.values()) if (member.pgid === pgid) return member.sid;
6730
+ return void 0;
6731
+ }
6732
+ join(pid, pgid) {
6733
+ const sid = this.sessionOf(pgid);
6734
+ if (sid === void 0) throw new KernelError("ESRCH");
6735
+ const member = this.member(pid);
6736
+ member.pgid = pgid;
6737
+ member.sid = sid;
6738
+ }
6718
6739
  pgidOf(pid) {
6719
6740
  return this.members.get(pid)?.pgid;
6720
6741
  }
@@ -8082,7 +8103,13 @@ var Launcher = class {
8082
8103
  }
8083
8104
  return this.start({ ...req, program, argv0: target.argv0, args, env });
8084
8105
  }
8106
+ groupSession(pgid) {
8107
+ return this.jobs.sessionOf(pgid);
8108
+ }
8085
8109
  start(req) {
8110
+ if (req.pgid !== void 0 && this.jobs.sessionOf(req.pgid) === void 0) {
8111
+ throw fsError("ESRCH", `no process group ${req.pgid}`);
8112
+ }
8086
8113
  const pid = this.nextPid++;
8087
8114
  const terminal = req.fds.stdioTerminal();
8088
8115
  const handle = spawnWasmProcess({
@@ -8118,6 +8145,7 @@ var Launcher = class {
8118
8145
  this.processes.set(pid, handle);
8119
8146
  this.jobs.add(pid, req.ppid, (sig) => handle.signal(sig), terminal);
8120
8147
  if (req.exec && req.ppid !== void 0) this.jobs.exec(req.ppid, pid, true);
8148
+ if (req.pgid !== void 0) this.jobs.join(pid, req.pgid);
8121
8149
  this.described.set(pid, {
8122
8150
  argv: [req.argv0, ...req.args],
8123
8151
  tty: terminal?.name ?? null,
@@ -8417,7 +8445,8 @@ var Launcher = class {
8417
8445
  fds.installAt(0, options.stdin ? bytesSource(options.stdin) : nullFile());
8418
8446
  fds.installAt(1, sinkFile(stdout));
8419
8447
  fds.installAt(2, sinkFile(stderr));
8420
- const handle = await this.launch(planned, { env, cwd, fds, report });
8448
+ const group = options.pgid !== void 0 ? { pgid: options.pgid } : {};
8449
+ const handle = await this.launch(planned, { env, cwd, fds, report, ...group });
8421
8450
  options.onStarted?.(handle.pid);
8422
8451
  const status = await handle.exited;
8423
8452
  return { status, stdout: concat5(out), stderr: concat5(err) };