@ai-ecoverse/slicc-kernel 1.18.0 → 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/README.md +2 -2
- package/dist/driver-worker.js +7 -3
- package/dist/driver-worker.js.map +2 -2
- package/dist/index.js +7 -3
- package/dist/index.js.map +2 -2
- package/dist/kernel-worker.js +81 -11
- package/dist/kernel-worker.js.map +3 -3
- package/dist/node-driver-worker.js +7 -3
- package/dist/node-driver-worker.js.map +2 -2
- package/dist/node.js +87 -13
- package/dist/node.js.map +3 -3
- package/package.json +1 -1
package/dist/index.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/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": ";AAAO,IAAM,eAAe,IAAI,KAAK;AAE9B,SAAS,YAAY,IAAmB;AAC7C,SAAO,OAAO,OAAO,IAAI,MAAM,sCAAsC,EAAE,KAAK,GAAG;AAAA,IAC7E,MAAM;AAAA,EACR,CAAC;AACH;AAEA,eAAsB,WACpB,QACA,IACsC;AACtC,MAAI,EAAE,KAAK,KAAK,KAAK,OAAO,mBAAoB,QAAO,OAAO,KAAK;AACnE,MAAI;AACJ,QAAM,OAAO,IAAI,QAAe,CAAC,GAAG,WAAW;AAC7C,YAAQ,WAAW,MAAM,OAAO,YAAY,EAAE,CAAC,GAAG,EAAE;AAAA,EACtD,CAAC;AACD,MAAI;AACF,WAAO,MAAM,QAAQ,KAAK,CAAC,OAAO,KAAK,GAAG,IAAI,CAAC;AAAA,EACjD,UAAE;AACA,iBAAa,KAAK;AAAA,EACpB;AACF;;;ACGA,IAAM,mBAAmB,KAAK,OAAO;AAErC,SAAS,YAAY,SAA8B;AACjD,QAAM,MAAM,IAAI,QAAQ;AACxB,aAAW,CAAC,MAAM,KAAK,KAAK,SAAS;AACnC,QAAI;AACF,UAAI,OAAO,MAAM,KAAK;AAAA,IACxB,QAAQ;AAAA,IAAC;AAAA,EACX;AACA,SAAO;AACT;AAEA,gBAAgB,OACd,MACA,QAC4B;AAC5B,MAAI,CAAC,KAAM;AACX,QAAM,SAAS,KAAK,UAAU;AAC9B,MAAI;AACF,aACM,OAAO,MAAM,WAAW,QAAQ,MAAM,GAC1C,CAAC,KAAK,MACN,OAAO,MAAM,WAAW,QAAQ,MAAM,GACtC;AACA,UAAI,KAAK,MAAM,aAAa,EAAG,OAAM,KAAK;AAAA,IAC5C;AAAA,EACF,UAAE;AACA,UAAM,OAAO,OAAO,EAAE,MAAM,MAAM,MAAS;AAAA,EAC7C;AACF;AAEO,SAAS,eAAe,UAAiC,CAAC,GAAmB;AAClF,QAAMA,QAAO,QAAQ,SAAS,WAAW,MAAM,KAAK,UAAU;AAC9D,SAAO;AAAA,IACL,QAAQ;AAAA,MACN,iBAAiB;AAAA,MACjB,eAAe;AAAA,MACf,gBAAgB,QAAQ,kBAAkB;AAAA,MAC1C,aAAa;AAAA,IACf;AAAA,IACA,MAAM,MAAM,SAAiE;AAC3E,UAAI;AACJ,UAAI;AACF,mBAAW,MAAMA,MAAK,QAAQ,KAAK;AAAA,UACjC,QAAQ,QAAQ;AAAA,UAChB,SAAS,YAAY,QAAQ,OAAO;AAAA,UACpC,GAAI,QAAQ,OAAO,EAAE,MAAM,QAAQ,KAAiB,IAAI,CAAC;AAAA,UACzD,QAAQ,QAAQ;AAAA,UAChB,UAAU;AAAA,UACV,aAAa;AAAA,UACb,MAAM;AAAA,QACR,CAAC;AAAA,MACH,SAAS,GAAG;AACV,YAAI,QAAQ,OAAO,QAAS,OAAM;AAClC,cAAM,OAAO;AAAA,UACX,IAAI;AAAA,YACF,SAAS,QAAQ,GAAG,gDAAgD,QAAQ,OAAO,KAAK,QAAQ,IAAI,KAAK,EAAE;AAAA,UAC7G;AAAA,UACA,EAAE,QAAQ,IAAI;AAAA,QAChB;AAAA,MACF;AACA,YAAM,UAAmC,CAAC;AAC1C,eAAS,QAAQ,QAAQ,CAAC,OAAO,SAAS;AACxC,gBAAQ,KAAK,CAAC,MAAM,KAAK,CAAC;AAAA,MAC5B,CAAC;AACD,YAAM,OAAO,OAAO,SAAS,MAAM,QAAQ,cAAc,YAAY;AACrE,aAAO;AAAA,QACL,QAAQ,SAAS;AAAA,QACjB,YAAY,SAAS;AAAA,QACrB;AAAA,QACA;AAAA,QACA,QAAQ,YAAY;AAClB,gBAAM,KAAK,OAAO,MAAS;AAC3B,gBAAM,SAAS,MAAM,OAAO,EAAE,MAAM,MAAM,MAAS;AAAA,QACrD;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;AAWO,SAAS,eAAe,MAAqB,WAA4C;AAC9F,QAAM,OAAO,oBAAI,IAGf;AACF,QAAM,OAAO,CAAC,KAAa,MAAe;AACxC,SAAK,OAAO,GAAG;AACf,UAAM,EAAE,QAAQ,KAAK,IAAI;AACzB,SAAK,YAAY;AAAA,MACf,KAAK;AAAA,MACL;AAAA,MACA,SAAS,aAAa,QAAQ,EAAE,UAAU,OAAO,CAAC;AAAA,MAClD,GAAI,OAAO,WAAW,WAAW,EAAE,OAAO,IAAI,CAAC;AAAA,MAC/C,GAAI,OAAO,SAAS,WAAW,EAAE,KAAK,IAAI,CAAC;AAAA,IAC7C,CAAC;AAAA,EACH;AACA,QAAM,QAAQ,OAAO,SAAmD;AACtE,UAAM,QAAQ,IAAI,gBAAgB;AAClC,UAAM,QAAsE,EAAE,MAAM;AACpF,SAAK,IAAI,KAAK,KAAK,KAAK;AACxB,QAAI;AACF,YAAM,WAAW,MAAM,UAAU,MAAM;AAAA,QACrC,KAAK,KAAK;AAAA,QACV,QAAQ,KAAK;AAAA,QACb,SAAS,KAAK;AAAA,QACd,GAAI,KAAK,OAAO,EAAE,MAAM,KAAK,KAAK,IAAI,CAAC;AAAA,QACvC,QAAQ,MAAM;AAAA,MAChB,CAAC;AACD,UAAI,CAAC,KAAK,IAAI,KAAK,GAAG,GAAG;AACvB,cAAM,SAAS,OAAO;AACtB;AAAA,MACF;AACA,WAAK,IAAI,KAAK,KAAK,EAAE,OAAO,MAAM,SAAS,KAAK,OAAO,aAAa,EAAE,GAAG,SAAS,CAAC;AACnF,WAAK,YAAY;AAAA,QACf,KAAK;AAAA,QACL,KAAK,KAAK;AAAA,QACV,QAAQ,SAAS;AAAA,QACjB,YAAY,SAAS;AAAA,QACrB,SAAS,SAAS;AAAA,MACpB,CAAC;AAAA,IACH,SAAS,GAAG;AACV,WAAK,KAAK,KAAK,CAAC;AAAA,IAClB;AAAA,EACF;AACA,QAAM,OAAO,OAAO,QAAgB;AAClC,UAAM,OAAO,KAAK,IAAI,GAAG,GAAG;AAC5B,QAAI,CAAC,KAAM;AACX,QAAI;AACF,YAAM,OAAO,MAAM,KAAK,KAAK;AAC7B,UAAI,KAAK,MAAM;AACb,aAAK,OAAO,GAAG;AACf,aAAK,YAAY,EAAE,KAAK,OAAO,IAAI,CAAC;AAAA,MACtC,OAAO;AACL,cAAM,QAAQ,KAAK,MAAM,MAAM;AAC/B,aAAK,YAAY,EAAE,KAAK,SAAS,KAAK,MAAM,GAAG,CAAC,MAAM,MAAM,CAAC;AAAA,MAC/D;AAAA,IACF,SAAS,GAAG;AACV,WAAK,KAAK,CAAC;AAAA,IACb;AAAA,EACF;AACA,QAAM,OAAO,CAAC,QAAgB;AAC5B,UAAM,QAAQ,KAAK,IAAI,GAAG;AAC1B,SAAK,OAAO,GAAG;AACf,WAAO,MAAM,MAAM;AACnB,SAAK,OAAO,UAAU,OAAO,EAAE,MAAM,MAAM,MAAS;AAAA,EACtD;AACA,SAAO;AAAA,IACL,OAAO,MAAM;AACX,UAAI,KAAK,QAAQ,QAAS,MAAK,MAAM,IAAI;AAAA,eAChC,KAAK,QAAQ,OAAQ,MAAK,KAAK,KAAK,GAAG;AAAA,UAC3C,MAAK,KAAK,GAAG;AAAA,IACpB;AAAA,IACA,QAAQ;AACN,iBAAW,OAAO,CAAC,GAAG,KAAK,KAAK,CAAC,EAAG,MAAK,GAAG;AAAA,IAC9C;AAAA,EACF;AACF;;;AChKO,IAAM,iBAAN,cAA6B,MAAM;AAAA,EAC/B;AAAA,EACA;AAAA,EAET,YAAY,SAAiB,QAAiB,MAAe;AAC3D,UAAM,OAAO;AACb,SAAK,SAAS;AACd,SAAK,OAAO;AAAA,EACd;AACF;AAOO,IAAM,kBAAN,MAAgD;AAAA,EAC5C;AAAA,EAEQ;AAAA,EAEA,UAAU,oBAAI,IAAoB;AAAA,EAE3C,SAAS;AAAA,EAET;AAAA,EAER,YAAY,MAAqB,QAA8B;AAC7D,SAAK,OAAO;AACZ,SAAK,SAAS;AAAA,EAChB;AAAA,EAEA,QAAQ,OAA6B;AACnC,UAAM,SAAS,KAAK,QAAQ,IAAI,MAAM,GAAG;AACzC,QAAI,CAAC,OAAQ;AACb,SAAK,QAAQ,OAAO,MAAM,GAAG;AAC7B,QAAI,MAAM,QAAQ,SAAS;AACzB,aAAO,OAAO,IAAI,eAAe,MAAM,SAAS,MAAM,QAAQ,MAAM,IAAI,CAAC;AAAA,IAC3E,MAAO,QAAO,QAAQ,KAAK;AAAA,EAC7B;AAAA,EAEA,KAAK,OAAoB;AACvB,SAAK,UAAU;AACf,eAAW,UAAU,KAAK,QAAQ,OAAO,EAAG,QAAO,OAAO,KAAK;AAC/D,SAAK,QAAQ,MAAM;AAAA,EACrB;AAAA,EAEQ,IAAI,MAA8C;AACxD,QAAI,KAAK,QAAS,QAAO,QAAQ,OAAO,KAAK,OAAO;AACpD,WAAO,IAAI,QAAQ,CAAC,SAAS,WAAW;AACtC,WAAK,QAAQ,IAAI,KAAK,KAAK,EAAE,SAAS,OAAO,CAAC;AAC9C,WAAK,KAAK,YAAY,IAAI;AAAA,IAC5B,CAAC;AAAA,EACH;AAAA,EAEQ,OAAO,KAAmB;AAChC,UAAM,SAAS,KAAK,QAAQ,IAAI,GAAG;AACnC,SAAK,QAAQ,OAAO,GAAG;AACvB,YAAQ,OAAO,IAAI,eAAe,2BAA2B,CAAC;AAC9D,SAAK,KAAK,YAAY,EAAE,KAAK,UAAU,IAAI,CAAC;AAAA,EAC9C;AAAA,EAEA,MAAM,MAAM,SAAiE;AAC3E,UAAM,MAAM,EAAE,KAAK;AACnB,UAAM,EAAE,OAAO,IAAI;AACnB,WAAO,eAAe;AACtB,QAAI,WAAW;AACf,UAAM,QAAQ,MAAM;AAClB,iBAAW;AACX,WAAK,OAAO,GAAG;AAAA,IACjB;AACA,WAAO,iBAAiB,SAAS,OAAO,EAAE,MAAM,KAAK,CAAC;AACtD,UAAM,SAAS,MAAM;AACnB,UAAI,SAAU;AACd,iBAAW;AACX,aAAO,oBAAoB,SAAS,KAAK;AAAA,IAC3C;AACA,QAAI;AACJ,QAAI;AACF,aAAO,MAAM,KAAK,IAAI;AAAA,QACpB,KAAK;AAAA,QACL;AAAA,QACA,KAAK,QAAQ;AAAA,QACb,QAAQ,QAAQ;AAAA,QAChB,SAAS,QAAQ;AAAA,QACjB,GAAI,QAAQ,OAAO,EAAE,MAAM,QAAQ,KAAK,IAAI,CAAC;AAAA,MAC/C,CAAC;AAAA,IACH,SAAS,GAAG;AACV,aAAO;AACP,YAAM;AAAA,IACR;AACA,UAAM,EAAE,QAAQ,YAAY,QAAQ,IAAI;AACxC,UAAM,OAAO,YAA6C;AACxD,UAAI,SAAU,QAAO;AACrB,YAAM,QAAQ,MAAM,KAAK,IAAI,EAAE,KAAK,QAAQ,IAAI,CAAC,EAAE,MAAM,CAAC,MAAe;AACvE,eAAO;AACP,cAAM;AAAA,MACR,CAAC;AACD,UAAI,MAAM,QAAQ,QAAS,QAAO,MAAM;AACxC,aAAO;AACP,aAAO;AAAA,IACT;AACA,UAAM,SAAS,YAAY;AACzB,UAAI,SAAU;AACd,aAAO;AACP,WAAK,OAAO,GAAG;AAAA,IACjB;AACA,WAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,MAAM;AAAA,QACJ,CAAC,OAAO,aAAa,GAAG,OAAO;AAAA,UAC7B,MAAM,YAAY;AAChB,kBAAM,QAAQ,MAAM,KAAK;AACzB,mBAAO,QAAQ,EAAE,OAAO,OAAO,MAAM,MAAM,IAAI,EAAE,OAAO,QAAW,MAAM,KAAK;AAAA,UAChF;AAAA,UACA,QAAQ,YAAY;AAClB,kBAAM,OAAO;AACb,mBAAO,EAAE,OAAO,QAAW,MAAM,KAAK;AAAA,UACxC;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;;;ACvJO,IAAM,WAAsC,CAAC,GAAG,CAAC;AA4GjD,SAAS,QAAQ,QAAgB,YAAyC;AAC/E,QAAM,QAAS,MAAsD,WAAW;AAChF,SAAO,OAAO,OAAO,YAAY,aAAa,QAAQ;AACxD;AAEO,SAAS,aAAa,QAAqC;AAChE,QAAM,QAAQ,MAAM,QAAQ,MAAM,IAAI,OAAO,CAAC,IAAI;AAClD,MAAI,UAAU,SAAS,CAAC,EAAG,QAAO;AAClC,QAAM,QAAQ,OAAO,UAAU,WAAW,GAAG,KAAK,OAAO;AACzD,SAAO,gCAAgC,KAAK,uCAAuC,SAAS,KAAK,GAAG,CAAC;AACvG;;;ACjGO,IAAM,kBAAN,cAA8B,MAAM;AAAA,EACzC,YAAY,UAAU,wDAAwD;AAC5E,UAAM,OAAO;AACb,SAAK,OAAO;AAAA,EACd;AACF;AAEO,IAAM,kBAAN,cAA8B,MAAM;AAAA,EAChC;AAAA,EAET,YAAY,SAAiB,MAAe;AAC1C,UAAM,OAAO;AACb,SAAK,OAAO;AACZ,SAAK,OAAO;AAAA,EACd;AACF;AAyGA,IAAM,UAAU,IAAI,YAAY;AAChC,IAAM,UAAU,CAAC,SACf,OAAO,SAAS,WAAW,QAAQ,OAAO,IAAI,IAAI;AAEpD,IAAM,cAAc;AAAA,EAClB,iBAAiB;AAAA,EACjB,eAAe;AAAA,EACf,gBAAgB;AAAA,EAChB,aAAa;AACf;AAEA,eAAe,SACb,OAC6C;AAC7C,MAAI,CAAC,MAAO,QAAO,EAAE,UAAU;AAAA,EAAC,EAAE;AAClC,QAAM,OAAO,uBAAuB,OAAO,WAAW,CAAC;AACvD,QAAM,UAAU,QAAQ,cAAoB;AAC5C,QAAM,OAAO,QAAQ,cAAoB;AACzC,OAAK,MAAM,QAAQ,MAAM,MAAM;AAC7B,YAAQ,QAAQ;AAChB,WAAO,KAAK;AAAA,EACd,CAAC;AACD,QAAM,QAAQ;AACd,SAAO,EAAE,MAAM,SAAS,MAAM,KAAK,QAAQ,EAAE;AAC/C;AAEA,SAAS,OAAOC,SAAkC;AAChD,QAAM,MAAM,IAAI,WAAWA,QAAO,OAAO,CAAC,GAAG,MAAM,IAAI,EAAE,QAAQ,CAAC,CAAC;AACnE,MAAI,KAAK;AACT,aAAW,SAASA,SAAQ;AAC1B,QAAI,IAAI,OAAO,EAAE;AACjB,UAAM,MAAM;AAAA,EACd;AACA,SAAO;AACT;AAEA,IAAM,UAAN,MAAc;AAAA,EACH,UAAU,QAAQ,cAA2B;AAAA,EAC7C,QAAQ,QAAQ,cAAqB;AAAA,EAC9C;AAAA,EACA;AAAA,EACiB,UAAU,oBAAI,IAAqB;AAAA,EAC3C,WAAW,oBAAI,IAA2C;AAAA,EACnE,WAAsC;AAAA,EAC9B,SAAS;AAAA,EACA;AAAA,EACA;AAAA,EAEjB,YAAY,MAAuB,SAAqB;AACtD,SAAK,OAAO;AACZ,SAAK,UAAU;AACf,SAAK,QAAQ,QAAQ,MAAM,MAAM,MAAS;AAC1C,SAAK,iBAAiB,WAAW,CAAC,UAAU,KAAK,QAAQ,MAAM,IAAI,CAAC;AACpE,SAAK,iBAAiB,SAAS,MAAM,KAAK,IAAI,IAAI,gBAAgB,CAAC,CAAC;AACpE,SAAK,QAAQ;AAAA,EACf;AAAA,EAEA,KAAK,SAAuB;AAC1B,QAAI,CAAC,KAAK,QAAS,MAAK,KAAK,YAAY,OAAO;AAAA,EAClD;AAAA,EAEA,IAAI,OAAoB;AACtB,QAAI,KAAK,QAAS;AAClB,SAAK,UAAU;AACf,SAAK,QAAQ,OAAO,KAAK;AACzB,SAAK,QAAQ,KAAK,KAAK;AACvB,eAAW,QAAQ,KAAK,QAAQ,OAAO,EAAG,MAAK,OAAO,KAAK;AAC3D,SAAK,QAAQ,MAAM;AACnB,SAAK,QAAQ;AACb,SAAK,KAAK,QAAQ;AAClB,SAAK,MAAM,QAAQ,KAAK;AAAA,EAC1B;AAAA,EAEA,QAAQ,MAAkB,WAAqB,CAAC,GAA2C;AACzF,UAAM,KAAK,EAAE,KAAK;AAClB,UAAM,EAAE,SAAAC,SAAQ,IAAI;AACpB,QAAIA,SAAS,QAAO,EAAE,IAAI,MAAM,QAAQ,OAAOA,QAAO,EAAE;AACxD,UAAM,OAAO,IAAI,QAAQ,CAAC,SAAS,WAAW;AAC5C,WAAK,QAAQ,IAAI,IAAI,EAAE,SAAS,QAAQ,GAAG,SAAS,CAAC;AACrD,WAAK,KAAK,YAAY,EAAE,GAAG,MAAM,GAAG,CAAC;AAAA,IACvC,CAAC;AACD,WAAO,EAAE,IAAI,KAAK;AAAA,EACpB;AAAA,EAEA,KAAK,MAAoC;AACvC,WAAO,KAAK,QAAQ,IAAI,EAAE;AAAA,EAC5B;AAAA,EAEQ,QAAQ,MAMP;AACP,QAAI,KAAK,UAAU,QAAW;AAC5B,WAAK,SAAS,IAAI,KAAK,KAAK,IAAI,KAAK,MAAqB;AAC1D;AAAA,IACF;AACA,QAAI,KAAK,QAAQ,QAAW;AAC1B,WAAK,IAAI,IAAI,gBAAgB,KAAK,GAAG,CAAC;AACtC;AAAA,IACF;AACA,QAAI,KAAK,OAAO;AACd,WAAK,QAAQ,QAAQ,KAAK,KAAK;AAC/B;AAAA,IACF;AACA,QAAI,KAAK,QAAQ,QAAW;AAC1B,WAAK,QAAQ,QAAQ,IAAsB;AAC3C;AAAA,IACF;AACA,UAAM,QAAQ;AACd,UAAM,OAAO,KAAK,QAAQ,IAAI,MAAM,EAAE;AACtC,QAAI,CAAC,KAAM;AACX,QAAI,MAAM,OAAO,QAAW;AAC1B,WAAK,SAAS,MAAM,IAAI,MAAM,KAAmB;AACjD;AAAA,IACF;AACA,QAAI,MAAM,YAAY,QAAW;AAC/B,WAAK,UAAU,MAAM,OAAO;AAC5B;AAAA,IACF;AACA,SAAK,QAAQ,OAAO,MAAM,EAAE;AAC5B,QAAI,MAAM,UAAU,OAAW,MAAK,OAAO,IAAI,gBAAgB,MAAM,OAAO,MAAM,IAAI,CAAC;AAAA,QAClF,MAAK,QAAQ,MAAM,MAAM;AAAA,EAChC;AACF;AAEA,eAAe,QACb,SACA,MACA,MACyB;AACzB,QAAM,EAAE,UAAU,UAAU,OAAO,OAAO,GAAG,GAAG,KAAK,IAAI;AACzD,QAAM,UAAU,QAAQ,cAAsB;AAC9C,QAAM,UAAU,EAAE,GAAG,MAAM,GAAI,UAAU,SAAY,EAAE,OAAO,QAAQ,KAAK,EAAE,IAAI,CAAC,EAAG;AACrF,QAAM,EAAE,KAAK,IAAI,QAAQ;AAAA,IACvB,EAAE,IAAI,SAAS,MAAM,QAAQ;AAAA,IAC7B;AAAA,MACE,QAAQ,CAAC,IAAI,WAAW,OAAO,IAAI,WAAW,YAAY,KAAK;AAAA,MAC/D,SAAS,QAAQ;AAAA,IACnB;AAAA,EACF;AACA,OAAK,MAAM,QAAQ,MAAM;AACzB,QAAM,MAAM,MAAM,QAAQ;AAC1B,SAAO;AAAA,IACL;AAAA,IACA,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,QAAQ,OAAO,OAAO,cACpB,KAAM,MAAM,QAAQ,KAAK,EAAE,IAAI,QAAQ,KAAK,CAAC,KAAK,QAAQ,KAAK,CAAC;AAAA,EACpE;AACF;AAEA,eAAe,MACb,SACA,MACA,MAC0B;AAC1B,QAAM,EAAE,UAAU,UAAU,GAAG,KAAK,IAAI;AACxC,QAAMD,UAAsC,EAAE,GAAG,CAAC,GAAG,GAAG,CAAC,EAAE;AAC3D,QAAM,OAAO,EAAE,GAAG,IAAI,YAAY,GAAG,GAAG,IAAI,YAAY,EAAE;AAC1D,QAAM,MAAM,CAAC,IAAW,OAAgC,CAAC,UAAsB;AAC7E,IAAAA,QAAO,EAAE,EAAE,KAAK,KAAK;AACrB,SAAK,KAAK,EAAE,EAAE,OAAO,OAAO,EAAE,QAAQ,KAAK,CAAC,CAAC;AAAA,EAC/C;AACA,QAAM,QAAQ,MAAM,QAAQ,SAAS,MAAM;AAAA,IACzC,GAAG;AAAA,IACH,UAAU,IAAI,GAAG,QAAQ;AAAA,IACzB,UAAU,IAAI,GAAG,QAAQ;AAAA,EAC3B,CAAC;AACD,QAAM,SAAS,MAAM,MAAM;AAC3B,QAAM,OAAO,CAAC,OAAc,IAAI,YAAY,EAAE,OAAO,OAAOA,QAAO,EAAE,CAAC,CAAC;AACvE,SAAO,EAAE,KAAK,MAAM,KAAK,QAAQ,QAAQ,KAAK,CAAC,GAAG,QAAQ,KAAK,CAAC,EAAE;AACpE;AAEA,eAAe,WACb,SACA,MACA,MACyB;AACzB,QAAM,EAAE,QAAQ,GAAG,QAAQ,IAAI;AAC/B,MAAI,WAAW,UAAU;AACzB,QAAM,UAAwB,CAAC;AAC/B,QAAM,UAAU,QAAQ,cAAsB;AAC9C,QAAM,EAAE,IAAI,KAAK,IAAI,QAAQ;AAAA,IAC3B,EAAE,IAAI,iBAAiB,MAAM,QAAQ;AAAA,IACrC;AAAA,MACE,QAAQ,CAAC,KAAK,UAAW,WAAW,SAAS,KAAK,IAAI,QAAQ,KAAK,KAAK;AAAA,MACxE,SAAS,QAAQ;AAAA,IACnB;AAAA,EACF;AACA,OAAK,MAAM,QAAQ,MAAM;AACzB,QAAM,MAAM,MAAM,QAAQ;AAC1B,QAAME,QAAO,CAAC,WACZ,KAAK,QAAQ,KAAK,EAAE,IAAI,YAAY,UAAU,IAAI,GAAG,OAAO,CAAC,EAAE,MAAM,MAAM,MAAS;AACtF,SAAO;AAAA,IACL;AAAA,IACA,QAAQ;AAAA,IACR,IAAI,SAAS;AACX,aAAO;AAAA,IACT;AAAA,IACA,IAAI,OAAO,MAAM;AACf,iBAAW;AACX,UAAI,KAAM,YAAW,SAAS,QAAQ,OAAO,CAAC,EAAG,MAAK,KAAK;AAAA,IAC7D;AAAA,IACA,OAAO,CAAC,SAASA,MAAK,EAAE,QAAQ,SAAS,OAAO,QAAQ,IAAI,EAAE,CAAC;AAAA,IAC/D,QAAQ,CAAC,MAAM,SAASA,MAAK,EAAE,QAAQ,UAAU,MAAM,KAAK,CAAC;AAAA,IAC7D,QAAQ,CAAC,SAASA,MAAK,EAAE,QAAQ,UAAU,QAAQ,KAAK,CAAC;AAAA,IACzD,OAAO,MAAMA,MAAK,EAAE,QAAQ,QAAQ,CAAC;AAAA,EACvC;AACF;AAEA,SAAS,KAAK,SAA4B;AACxC,QAAM,KAAK,CAAC,WAAqB,SAAoB,QAAQ,KAAK,EAAE,IAAI,MAAM,QAAQ,KAAK,CAAC;AAC5F,QAAM,OAAO,OAAO,WAAqB,SAAoB,KAAM,MAAM,GAAG,QAAQ,GAAG,IAAI;AAC3F,SAAO;AAAA,IACL,UAAU,CAAC,SAAS,GAAG,YAAY,IAAI;AAAA,IACvC,UAAU,OAAO,SAAS,IAAI,YAAY,EAAE,OAAQ,MAAM,GAAG,YAAY,IAAI,CAAgB;AAAA,IAC7F,WAAW,CAAC,MAAM,SAAS,KAAK,aAAa,MAAM,IAAI;AAAA,IACvD,MAAM,CAAC,SAAS,GAAG,QAAQ,IAAI;AAAA,IAC/B,OAAO,CAAC,SAAS,GAAG,SAAS,IAAI;AAAA,IACjC,SAAS,CAAC,SAAS,GAAG,WAAW,IAAI;AAAA,IACrC,OAAO,CAAC,SAAS,KAAK,SAAS,IAAI;AAAA,IACnC,IAAI,CAAC,MAAM,IAAI,CAAC,MAAM,KAAK,MAAM,MAAM,EAAE,UAAU,IAAI;AAAA,IACvD,QAAQ,CAAC,MAAM,OAAO,KAAK,UAAU,MAAM,EAAE;AAAA,IAC7C,UAAU,CAAC,SAAS,GAAG,YAAY,IAAI;AAAA,IACvC,SAAS,CAAC,QAAQ,SAAS,KAAK,WAAW,QAAQ,IAAI;AAAA,IACvD,UAAU,CAAC,SAAS,GAAG,YAAY,IAAI;AAAA,IACvC,QAAQ,CAAC,SAAS,GAAG,UAAU,IAAI;AAAA,IACnC,MAAM,MAAM,OAAO,SAAS,UAAU;AACpC,UAAI,QAAQ,SAAS,CAAC,IAAI,GAAG;AAC3B,cAAM,IAAI;AAAA,UACR,+BAA+B,QAAQ,SAAS,KAAK,GAAG,CAAC;AAAA,UACzD;AAAA,QACF;AAAA,MACF;AACA,YAAM,EAAE,IAAI,MAAAC,MAAK,IAAI,QAAQ,QAAQ;AAAA,QACnC,IAAI;AAAA,QACJ;AAAA,QACA,WAAW,QAAQ,cAAc;AAAA,MACnC,CAAC;AACD,cAAQ,SAAS,IAAI,IAAI,QAAQ;AACjC,UAAI;AACF,cAAMA;AAAA,MACR,SAAS,OAAO;AACd,gBAAQ,SAAS,OAAO,EAAE;AAC1B,cAAM;AAAA,MACR;AACA,aAAO;AAAA,QACL,OAAO,MAAM;AACX,cAAI,CAAC,QAAQ,SAAS,OAAO,EAAE,EAAG;AAClC,eAAK,QAAQ,KAAK,EAAE,IAAI,WAAW,OAAO,GAAG,CAAC,EAAE,MAAM,MAAM,MAAS;AAAA,QACvE;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;AAEA,SAAS,MAAM,SAAkB,OAAe,MAAc,KAA6B;AACzF,MAAI,QAAQ,SAAS,CAAC,IAAI,OAAO;AAC/B,WAAO,QAAQ;AAAA,MACb,IAAI;AAAA,QACF,+BAA+B,QAAQ,SAAS,KAAK,GAAG,CAAC,kBAAkB,IAAI;AAAA,QAC/E;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACA,SAAO,IAAI;AACb;AAEA,eAAe,MACb,SACA,MACA,WACsB;AACtB,UAAQ,KAAK,EAAE,OAAO,EAAE,UAAU,UAAU,GAAI,OAAO,EAAE,KAAK,IAAI,CAAC,EAAG,EAAE,CAAC;AACzE,QAAM,QAAQ;AAAA,IACZ,MACE,QAAQ;AAAA,MACN,IAAI,gBAAgB,gDAAgD,SAAS,KAAK;AAAA,IACpF;AAAA,IACF;AAAA,EACF;AACA,MAAI;AACJ,MAAI;AACF,YAAQ,MAAM,QAAQ,QAAQ;AAAA,EAChC,UAAE;AACA,iBAAa,KAAK;AAAA,EACpB;AACA,QAAM,UAAU,MAAM,SAAS,aAAa,MAAM,QAAQ;AAC1D,MAAI,SAAS;AACX,UAAM,QAAQ,IAAI,MAAM,OAAO;AAC/B,YAAQ,IAAI,KAAK;AACjB,UAAM;AAAA,EACR;AACA,SAAO;AACT;AAEA,eAAsB,aACpB,MACA,UAAyB,CAAC,GACH;AACvB,QAAM,QAAQ,QAAQ,UAAU,OAAO,SAAa,QAAQ,SAAS,QAAQ;AAC7E,QAAM,MAAM,MAAM,SAAS,KAAK;AAChC,QAAM,UAAU,IAAI,QAAQ,MAAM,IAAI,OAAO;AAC7C,QAAM,QAAQ,MAAM,MAAM,SAAS,IAAI,MAAM,QAAQ,aAAa,GAAM;AACxE,UAAQ,WAAW,MAAM;AACzB,MAAI,MAAM,QAAQ,MAAO,MAAK,MAAM,QAAQ,MAAM,MAAM,MAAM,QAAQ,IAAI,IAAI,gBAAgB,CAAC,CAAC;AAChG,QAAM,YAAY,IAAI;AAAA,IACpB,EAAE,aAAa,CAAC,SAAS,QAAQ,KAAK,IAAI,EAAE;AAAA,IAC5C,MAAM,UAAU;AAAA,EAClB;AACA,UAAQ,SAAS;AACjB,SAAO;AAAA,IACL,UAAU,MAAM;AAAA,IAChB;AAAA,IACA,QAAQ,QAAQ,MAAM;AAAA,IACtB,OAAO,CAAC,MAAM,OAAO,CAAC,MAAM,QAAQ,SAAS,MAAM,IAAI;AAAA,IACvD,KAAK,CAAC,MAAM,OAAO,CAAC,MAAM,MAAM,SAAS,MAAM,IAAI;AAAA,IACnD,cAAc,CAAC,MAAM,OAAO,CAAC,MAAM,WAAW,SAAS,MAAM,IAAI;AAAA,IACjE,IAAI,MAAM,QAAQ,KAAK,EAAE,IAAI,KAAK,CAAC;AAAA,IACnC,OAAO,CAAC,SACN,MAAM,SAAS,GAAG,SAAS,MAAM,QAAQ,KAAK,EAAE,IAAI,SAAS,KAAK,CAAC,CAAC;AAAA,IACtE,QAAQ,OAAO,WACb,KAAM,MAAM,MAAM,SAAS,GAAG,UAAU,MAAM,QAAQ,KAAK,EAAE,IAAI,UAAU,OAAO,CAAC,CAAC;AAAA,IACtF,QAAQ,MACN,MAAM,SAAS,GAAG,UAAU,MAAM,QAAQ,KAAK,EAAE,IAAI,SAAS,CAAC,CAAC;AAAA,IAClE,MAAM,OAAO,KAAK,SAAS,cAAc,KAAM,MAAM,QAAQ,KAAK,EAAE,IAAI,QAAQ,KAAK,OAAO,CAAC;AAAA,IAC7F,OAAO,CAAC,QAAQ;AACd,YAAM,EAAE,QAAQ,GAAG,KAAK,IAAI;AAC5B,aAAO,UAAU,MAAM,EAAE,GAAG,MAAM,QAAQ,UAAU,IAAI,gBAAgB,EAAE,OAAO,CAAC;AAAA,IACpF;AAAA,IACA,IAAI,KAAK,OAAO;AAAA,IAChB,MAAM,MAAM,IAAI,CAAC,GAAG;AAClB,UAAI,QAAQ,QAAS;AACrB,YAAM,QACH,KAAK,EAAE,IAAI,UAAU,GAAI,EAAE,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC,EAAG,CAAC,EACxD,MAAM,MAAM,MAAS;AACxB,cAAQ,IAAI,IAAI,gBAAgB,uBAAuB,CAAC;AAAA,IAC1D;AAAA,EACF;AACF;;;ACpcA,IAAM,OAAO;AACb,IAAM,mBAAmB;AACzB,IAAM,WAAW,OAAO;AACxB,IAAMC,oBAAmB,KAAK,OAAO;AACrC,IAAM,cAAc,CAAC,oBAAoB,sBAAsB;AAC/D,IAAM,gBAAgB;AAQtB,IAAM,UAAU,CAAC,SAAiB,SAAS,QACzC,OAAO,OAAO,IAAI,MAAM,gBAAgB,OAAO,EAAE,GAAG,EAAE,OAAO,CAAC;AAEhE,SAAS,WAAW,KAAa,QAAgB,SAA6B;AAC5E,SAAO,KAAK,UAAU,EAAE,KAAK,QAAQ,QAAQ,CAAC,EAAE;AAAA,IAC9C;AAAA,IACA,CAAC,MAAM,MAAM,EAAE,WAAW,CAAC,EAAE,SAAS,EAAE,EAAE,SAAS,GAAG,GAAG,CAAC;AAAA,EAC5D;AACF;AAEA,SAAS,WAAW,SAA4B,OAAwC;AACtF,SAAO,IAAI,QAAQ,EAAE,kBAAkB,QAAQ,KAAK,GAAG,MAAM,CAAC;AAChE;AAEA,SAAS,KAAK,SAA4B;AACxC,SAAO,QAAQ,SAAS,WAAW,MAAM,KAAK,UAAU;AAC1D;AAEA,eAAe,eAAe,UAAqC;AACjE,QAAM,OAAO,MAAM,SAAS,KAAK,EAAE,MAAM,MAAM,EAAE;AACjD,MAAI;AACF,UAAM,SAAS,KAAK,MAAM,IAAI;AAC9B,QAAI,OAAO,OAAO,UAAU,SAAU,QAAO,OAAO;AAAA,EACtD,QAAQ;AAAA,EAAC;AACT,SAAO,QAAQ,SAAS,cAAc,YAAY,SAAS,MAAM;AACnE;AAEA,eAAe,QAAQ,UAAoC;AACzD,SAAO,QAAQ,MAAM,eAAe,QAAQ,GAAG,SAAS,KAAK,MAAM,SAAS,MAAM;AACpF;AAEA,eAAe,WAAW,aAAsE;AAC9F,MAAI,CAAC,YAAa,QAAO;AACzB,aAAW,QAAQ,aAAa;AAC9B,QAAI;AACF,cAAQ,MAAM,YAAY,MAAM,EAAE,KAAK,CAAyB,GAAG;AAAA,IACrE,QAAQ;AAAA,IAAC;AAAA,EACX;AACA,SAAO;AACT;AAEA,SAAS,OAAO,OAAuC;AACrD,QAAM,OAAO;AACb,SACE,CAAC,CAAC,QACF,OAAO,KAAK,WAAW,YACvB,OAAO,KAAK,eAAe,YAC3B,MAAM,QAAQ,KAAK,OAAO,KAC1B,KAAK,QAAQ;AAAA,IACX,CAAC,SACC,MAAM,QAAQ,IAAI,KAClB,KAAK,WAAW,KAChB,OAAO,KAAK,CAAC,MAAM,YACnB,OAAO,KAAK,CAAC,MAAM;AAAA,EACvB;AAEJ;AAEA,SAASC,QAAO,GAAe,GAA2B;AACxD,QAAM,MAAM,IAAI,WAAW,EAAE,aAAa,EAAE,UAAU;AACtD,MAAI,IAAI,CAAC;AACT,MAAI,IAAI,GAAG,EAAE,UAAU;AACvB,SAAO;AACT;AAEA,eAAe,SACb,QACA,QACmD;AACnD,MAAI,SAAqB,IAAI,WAAW,CAAC;AACzC,aAAS;AACP,QAAI,OAAO,cAAc,GAAG;AAC1B,YAAM,SAAS,IAAI,SAAS,OAAO,QAAQ,OAAO,YAAY,CAAC,EAAE,UAAU,CAAC;AAC5E,UAAI,SAAS,SAAU,OAAM,QAAQ,oBAAoB,MAAM,QAAQ;AACvE,UAAI,OAAO,cAAc,IAAI,QAAQ;AACnC,YAAI;AACJ,YAAI;AACF,iBAAO,KAAK,MAAM,IAAI,YAAY,EAAE,OAAO,OAAO,SAAS,GAAG,IAAI,MAAM,CAAC,CAAC;AAAA,QAC5E,QAAQ;AAAA,QAAC;AACT,YAAI,CAAC,OAAO,IAAI,EAAG,OAAM,QAAQ,yBAAyB;AAC1D,eAAO,EAAE,MAAM,MAAM,OAAO,SAAS,IAAI,MAAM,EAAE;AAAA,MACnD;AAAA,IACF;AACA,UAAM,OAAO,MAAM,WAAW,QAAQ,MAAM;AAC5C,QAAI,KAAK,KAAM,OAAM,QAAQ,iCAAiC;AAC9D,aAASA,QAAO,QAAQ,KAAK,KAAK;AAAA,EACpC;AACF;AAEA,gBAAgBC,QACd,MACA,QACA,QAC4B;AAC5B,MAAI;AACF,QAAI,KAAK,aAAa,EAAG,OAAM;AAC/B,aACM,OAAO,MAAM,WAAW,QAAQ,MAAM,GAC1C,CAAC,KAAK,MACN,OAAO,MAAM,WAAW,QAAQ,MAAM,GACtC;AACA,UAAI,KAAK,MAAM,aAAa,EAAG,OAAM,KAAK;AAAA,IAC5C;AAAA,EACF,UAAE;AACA,UAAM,OAAO,OAAO,EAAE,MAAM,MAAM,MAAS;AAAA,EAC7C;AACF;AAEA,eAAsB,gBAAgB,SAA4D;AAChG,QAAM,aAAa,cAAc,KAAK,WAAW,UAAU,YAAY,EAAE;AACzE,QAAM,cAAc,aAChB,SACC,QAAQ,eAAe,WAAW,WAAW;AAClD,MAAK,MAAM,WAAW,WAAW,MAAO,SAAU,QAAO,EAAE,OAAO,UAAU;AAC5E,MAAI;AACJ,MAAI;AACF,eAAW,MAAM,KAAK,OAAO,EAAE,IAAI,IAAI,MAAM,QAAQ,GAAG,GAAG;AAAA,MACzD,QAAQ;AAAA,MACR,SAAS,WAAW,SAAS,EAAE,qBAAqB,IAAI,CAAC;AAAA,MACzD,aAAa;AAAA,MACb,MAAM;AAAA,IACR,CAAC;AAAA,EACH,QAAQ;AACN,UAAM,MAAM,MAAM,WAAW,WAAW;AACxC,QAAI,QAAQ,SAAU,QAAO,EAAE,OAAO,UAAU;AAChD,WAAO;AAAA,MACL,OAAO;AAAA,MACP,YAAY,QAAQ,aAAa,QAAQ,WAAW,MAAM;AAAA,IAC5D;AAAA,EACF;AACA,MAAI,CAAC,SAAS,IAAI;AAChB,WAAO,EAAE,OAAO,WAAW,QAAQ,SAAS,QAAQ,OAAO,MAAM,eAAe,QAAQ,EAAE;AAAA,EAC5F;AACA,QAAM,QAAS,MAAM,SAAS,KAAK,EAAE,MAAM,MAAM,IAAI;AACrD,MACE,CAAC,SACD,OAAO,MAAM,aAAa,YAC1B,MAAM,WAAW,KACjB,OAAO,MAAM,yBAAyB,aACtC,OAAO,MAAM,wBAAwB,UACrC;AACA,WAAO,EAAE,OAAO,eAAe;AAAA,EACjC;AACA,SAAO;AAAA,IACL,OAAO;AAAA,IACP,OAAO;AAAA,MACL,UAAU,MAAM;AAAA,MAChB,sBAAsB,MAAM;AAAA,MAC5B,qBAAqB,MAAM;AAAA,IAC7B;AAAA,EACF;AACF;AAEA,eAAsB,gBACpB,SACiC;AACjC,QAAM,SAAS,MAAM,gBAAgB,OAAO;AAC5C,SAAO,OAAO,UAAU,UAAU,OAAO,QAAQ;AACnD;AAEO,SAAS,oBAAoB,SAAqD;AACvF,QAAM,WAAW,IAAI,IAAI,MAAM,QAAQ,GAAG;AAC1C,SAAO;AAAA,IACL,QAAQ;AAAA,MACN,iBAAiB;AAAA,MACjB,eAAe;AAAA,MACf,gBAAgB,QAAQ,kBAAkBF;AAAA,IAC5C;AAAA,IACA,MAAM,MAAM,SAAiE;AAC3E,UAAI;AACJ,UAAI;AACF,mBAAW,MAAM,KAAK,OAAO,EAAE,UAAU;AAAA,UACvC,QAAQ;AAAA,UACR,SAAS,WAAW,SAAS;AAAA,YAC3B,uBAAuB,WAAW,QAAQ,KAAK,QAAQ,QAAQ,QAAQ,OAAO;AAAA,UAChF,CAAC;AAAA,UACD,GAAI,QAAQ,OAAO,EAAE,MAAM,QAAQ,KAAiB,IAAI,CAAC;AAAA,UACzD,QAAQ,QAAQ;AAAA,UAChB,aAAa;AAAA,UACb,MAAM;AAAA,QACR,CAAC;AAAA,MACH,SAAS,GAAG;AACV,YAAI,QAAQ,OAAO,QAAS,OAAM;AAClC,cAAM,QAAQ,GAAG,SAAS,MAAM,wCAAwC;AAAA,MAC1E;AACA,YAAM,OAAO,SAAS,QAAQ,IAAI,cAAc,KAAK;AACrD,UAAI,SAAS,WAAW,OAAO,CAAC,KAAK,WAAW,gBAAgB,KAAK,CAAC,SAAS,MAAM;AACnF,cAAM,MAAM,QAAQ,QAAQ;AAAA,MAC9B;AACA,YAAM,SAAS,SAAS,KAAK,UAAU;AACvC,YAAM,SAAS,QAAQ,cAAc;AACrC,UAAI;AACJ,UAAI;AACF,iBAAS,MAAM,SAAS,QAAQ,MAAM;AAAA,MACxC,SAAS,GAAG;AACV,cAAM,OAAO,OAAO,EAAE,MAAM,MAAM,MAAS;AAC3C,cAAM;AAAA,MACR;AACA,YAAM,OAAOE,QAAO,OAAO,MAAM,QAAQ,MAAM;AAC/C,aAAO;AAAA,QACL,QAAQ,OAAO,KAAK;AAAA,QACpB,YAAY,OAAO,KAAK;AAAA,QACxB,SAAS,OAAO,KAAK;AAAA,QACrB;AAAA,QACA,QAAQ,YAAY;AAClB,gBAAM,KAAK,OAAO,MAAS;AAC3B,gBAAM,OAAO,OAAO,EAAE,MAAM,MAAM,MAAS;AAAA,QAC7C;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;;;AC5GA,IAAM,YACJ;AAEF,SAAS,SAAS,UAAgD;AAChE,QAAM,UAAU,IAAI,YAAY;AAChC,SAAO,CAAC,UAAsB,WAAW,QAAQ,OAAO,OAAO,EAAE,QAAQ,KAAK,CAAC,CAAC;AAClF;AAEA,eAAsB,aAAa,UAAyB,CAAC,GAAoB;AAC/E,MAAI,CAAC,WAAW,oBAAqB,OAAM,IAAI,MAAM,SAAS;AAC9D,QAAM,MAAM,QAAQ,UAAU,IAAI,IAAI,sBAAsB,YAAY,GAAG;AAC3E,QAAM,SAAS,IAAI,OAAO,KAAK,EAAE,MAAM,UAAU,MAAM,eAAe,CAAC;AACvE,QAAM,UAAU,oBAAI,IAAqB;AACzC,MAAI,SAAS;AACb,MAAIC;AAEJ,QAAM,OAAO,CAAC,UAAiB;AAC7B,IAAAA,WAAU;AACV,YAAQ,MAAM;AACd,eAAWC,SAAQ,QAAQ,OAAO,EAAG,CAAAA,MAAK,OAAO,KAAK;AACtD,YAAQ,MAAM;AAAA,EAChB;AACA,QAAM,YAAY,QAAQ,SAAS;AACnC,QAAM,SAAS,YAAY,eAAe,QAAQ,SAAS,IAAI;AAC/D,iBAAe,OAAO,QAAsE;AAC1F,QAAI,QAAQ;AACV,YAAM,QAAQ,MAAM,OAAO,oBAAoB,EAAE,MAAM,YAAY,CAAC;AACpE,UAAI,UAAU,UAAa,UAAU,UAAW,QAAO;AACvD,YAAM,IAAI,MAAM,2CAA2C;AAAA,IAC7D;AACA,QAAI,CAAC,QAAQ,iBAAkB,OAAM,IAAI,MAAM,mCAAmC;AAClF,WAAO,QAAQ,iBAAiB;AAAA,EAClC;AACA,iBAAe,YAAY,EAAE,IAAI,QAAQ,SAAS,GAAiC;AACjF,QAAI;AACF,UAAI,CAAC,QAAQ,OAAQ,OAAM,IAAI,MAAM,iCAAiC;AACtE,YAAM,QAAQ,MAAM,QAAQ,OAAO,QAAQ,EAAE,SAAS,CAAC;AACvD,aAAO,YAAY,EAAE,aAAa,EAAE,IAAI,MAAM,EAAE,CAAC;AAAA,IACnD,SAAS,KAAK;AACZ,aAAO,YAAY,EAAE,aAAa,EAAE,IAAI,OAAQ,IAAc,WAAW,OAAO,GAAG,EAAE,EAAE,CAAC;AAAA,IAC1F;AAAA,EACF;AACA,iBAAe,OAAO,EAAE,IAAI,IAAI,GAA4D;AAC1F,UAAM,SAAS,QAAQ;AACvB,QAAI,UAAU;AACd,QAAI;AACF,gBAAU,OAAO,WAAW,aAAa,MAAM,OAAO,GAAG,IAAI,WAAW;AAAA,IAC1E,QAAQ;AAAA,IAAC;AACT,WAAO,YAAY,EAAE,cAAc,EAAE,IAAI,QAAQ,EAAE,CAAC;AAAA,EACtD;AACA,QAAM,gBAAgB,CAAC,EAAE,QAAQ,QAAQ,OAAO,MAC9C,QAAQ,iBAAiB;AAAA,IACvB;AAAA,IACA;AAAA,IACA,QAAQ,YACN,KAAM,MAAM,KAAK,EAAE,IAAI,UAAU,QAAQ,QAAQ,QAAQ,MAAM,OAAO,MAAM,EAAE,CAAC;AAAA,EACnF,CAAC;AACH,SAAO;AAAA,IACL;AAAA,IACA,CAAC;AAAA,MACC;AAAA,IACF,MAMM;AACJ,UAAI,SAAS,KAAM,QAAO,QAAQ,OAAO,IAAI;AAC7C,UAAI,iBAAiB,KAAM,QAAO,KAAK,OAAO,KAAK,WAAW;AAC9D,UAAI,YAAY,KAAM,QAAO,cAAc,KAAK,MAAM;AACtD,UAAI,YAAY,KAAM,QAAO,KAAK,YAAY,KAAK,MAAM;AACzD,YAAMA,QAAO,QAAQ,IAAI,KAAK,EAAE;AAChC,UAAI,CAACA,MAAM;AACX,UAAI,KAAK,OAAO,OAAW,QAAOA,MAAK,SAAS,KAAK,IAAI,KAAK,KAAmB;AACjF,UAAI,KAAK,YAAY,OAAW,QAAOA,MAAK,UAAU,KAAK,OAAO;AAClE,cAAQ,OAAO,KAAK,EAAE;AACtB,UAAI,KAAK,UAAU,OAAW,CAAAA,MAAK,OAAO,IAAI,MAAM,KAAK,KAAK,CAAC;AAAA,UAC1D,CAAAA,MAAK,QAAQ,KAAK,MAAM;AAAA,IAC/B;AAAA,EACF;AACA,SAAO,iBAAiB,SAAS,CAAC,UAAU;AAC1C,UAAM,eAAe;AACrB,SAAK,IAAI,MAAM,+BAA+B,MAAM,OAAO,EAAE,CAAC;AAAA,EAChE,CAAC;AAED,WAAS,QACP,KACA,WAAqB,CAAC,GACkB;AACxC,UAAM,KAAK,EAAE;AACb,QAAID,SAAS,QAAO,EAAE,IAAI,MAAM,QAAQ,OAAOA,QAAO,EAAE;AACxD,UAAM,OAAO,IAAI,QAAQ,CAAC,SAAS,WAAW;AAC5C,cAAQ,IAAI,IAAI,EAAE,SAAS,QAAQ,GAAG,SAAS,CAAC;AAChD,aAAO,YAAY,EAAE,GAAG,KAAK,GAAG,CAAC;AAAA,IACnC,CAAC;AACD,WAAO,EAAE,IAAI,KAAK;AAAA,EACpB;AAEA,QAAM,OAAO,CAAC,KAAiB,aAAwB,QAAQ,KAAK,QAAQ,EAAE;AAE9E,iBAAe,aAAa,MAAgB,OAAwB,CAAC,GAAsB;AACzF,UAAM,EAAE,QAAQ,GAAGE,SAAQ,IAAI;AAC/B,QAAI,WAAW,UAAU;AACzB,UAAM,UAAwB,CAAC;AAC/B,UAAM,UAAU,QAAQ,cAAsB;AAC9C,UAAM,EAAE,IAAI,KAAK,IAAI;AAAA,MACnB,EAAE,IAAI,iBAAiB,MAAM,SAAAA,SAAQ;AAAA,MACrC;AAAA,QACE,QAAQ,CAAC,KAAK,UAAW,WAAW,SAAS,KAAK,IAAI,QAAQ,KAAK,KAAK;AAAA,QACxE,SAAS,QAAQ;AAAA,MACnB;AAAA,IACF;AACA,SAAK,MAAM,QAAQ,MAAM;AACzB,UAAM,MAAM,MAAM,QAAQ;AAC1B,UAAMC,QAAO,CAAC,WACZ,KAAK,KAAK,EAAE,IAAI,YAAY,UAAU,IAAI,GAAG,OAAO,CAAC,EAAE,MAAM,MAAM,MAAS;AAC9E,WAAO;AAAA,MACL;AAAA,MACA,QAAQ;AAAA,MACR,IAAI,SAAS;AACX,eAAO;AAAA,MACT;AAAA,MACA,IAAI,OAAO,MAAM;AACf,mBAAW;AACX,YAAI,KAAM,YAAW,SAAS,QAAQ,OAAO,CAAC,EAAG,MAAK,KAAK;AAAA,MAC7D;AAAA,MACA,OAAO,CAAC,SACNA,MAAK;AAAA,QACH,QAAQ;AAAA,QACR,OAAO,OAAO,SAAS,WAAW,IAAI,YAAY,EAAE,OAAO,IAAI,IAAI;AAAA,MACrE,CAAC;AAAA,MACH,QAAQ,CAAC,MAAM,SAASA,MAAK,EAAE,QAAQ,UAAU,MAAM,KAAK,CAAC;AAAA,MAC7D,QAAQ,CAAC,SAASA,MAAK,EAAE,QAAQ,UAAU,QAAQ,KAAK,CAAC;AAAA,MACzD,OAAO,MAAMA,MAAK,EAAE,QAAQ,QAAQ,CAAC;AAAA,IACvC;AAAA,EACF;AAEA,QAAM,KAAK;AAAA,IACT,IAAI;AAAA,IACJ,GAAI,QAAQ,OAAO,EAAE,MAAM,QAAQ,KAAK,IAAI,CAAC;AAAA,IAC7C,GAAI,QAAQ,UAAU,EAAE,SAAS,QAAQ,QAAQ,IAAI,CAAC;AAAA,IACtD,GAAI,QAAQ,MAAM,EAAE,KAAK,QAAQ,IAAI,IAAI,CAAC;AAAA,IAC1C,GAAI,QAAQ,aAAa,SAAY,EAAE,UAAU,QAAQ,SAAS,IAAI,CAAC;AAAA,IACvE,GAAI,QAAQ,UAAU,SAAY,EAAE,OAAO,QAAQ,MAAM,IAAI,CAAC;AAAA,IAC9D,GAAI,YAAY,EAAE,WAAW,UAAU,OAAO,IAAI,CAAC;AAAA,IACnD,GAAI,QAAQ,SAAS,EAAE,QAAQ,KAAK,IAAI,CAAC;AAAA,IACzC,GAAI,QAAQ,kBAAkB,SAC1B;AAAA,MACE,eACE,OAAO,QAAQ,kBAAkB,aAAa,QAAQ,QAAQ;AAAA,IAClE,IACA,CAAC;AAAA,EACP,CAAC;AAED,SAAO;AAAA,IACL,MAAM,IAAI,MAAM,aAAa,CAAC,GAAG;AAC/B,YAAM,EAAE,UAAU,UAAU,OAAO,GAAG,KAAK,IAAI;AAC/C,YAAM,UAAU,EAAE,GAAG,SAAS,QAAQ,GAAG,GAAG,SAAS,QAAQ,EAAE;AAC/D,YAAM,QAAQ,OAAO,UAAU,WAAW,IAAI,YAAY,EAAE,OAAO,KAAK,IAAI;AAC5E,YAAM,SAAU,MAAM;AAAA,QACpB,EAAE,IAAI,OAAO,MAAM,SAAS,EAAE,GAAG,MAAM,GAAI,QAAQ,EAAE,OAAO,MAAM,IAAI,CAAC,EAAG,EAAE;AAAA,QAC5E,EAAE,QAAQ,CAAC,IAAI,UAAU,QAAQ,EAAE,EAAE,KAAK,EAAE;AAAA,MAC9C;AACA,YAAM,UAAU,IAAI,YAAY;AAChC,aAAO;AAAA,QACL,QAAQ,OAAO;AAAA,QACf,QAAQ,QAAQ,OAAO,OAAO,MAAM;AAAA,QACpC,QAAQ,QAAQ,OAAO,OAAO,MAAM;AAAA,MACtC;AAAA,IACF;AAAA,IACA;AAAA,IACA,SAAS,YAAa,MAAM,KAAK,EAAE,IAAI,UAAU,CAAC;AAAA,IAClD,OAAO,OAAO,SAAU,MAAM,KAAK,EAAE,IAAI,SAAS,KAAK,CAAC;AAAA,IACxD,QAAQ,OAAO,WAAW,KAAM,MAAM,KAAK,EAAE,IAAI,UAAU,OAAO,CAAC;AAAA,IACnE,QAAQ,YAAa,MAAM,KAAK,EAAE,IAAI,SAAS,CAAC;AAAA,IAChD,QAAQ,OAAO,QAAQ,WAAW,KAAM,MAAM,KAAK,EAAE,IAAI,UAAU,QAAQ,OAAO,CAAC;AAAA,IACnF,YAAY;AACV,WAAK,IAAI,MAAM,yBAAyB,CAAC;AACzC,aAAO,UAAU;AAAA,IACnB;AAAA,EACF;AACF;",
|
|
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
|
}
|
package/dist/kernel-worker.js
CHANGED
|
@@ -225,7 +225,7 @@ function pinScript(url) {
|
|
|
225
225
|
}
|
|
226
226
|
|
|
227
227
|
// src/client/protocol.ts
|
|
228
|
-
var PROTOCOL = [1,
|
|
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
|
-
|
|
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
|
});
|
|
@@ -5742,6 +5752,48 @@ var VfsNodes = class {
|
|
|
5742
5752
|
}
|
|
5743
5753
|
}
|
|
5744
5754
|
};
|
|
5755
|
+
var MAX_LINKS5 = 40;
|
|
5756
|
+
function parentOf5(path) {
|
|
5757
|
+
return path.slice(0, path.lastIndexOf("/")) || "/";
|
|
5758
|
+
}
|
|
5759
|
+
async function linkOf(fs, path) {
|
|
5760
|
+
return fs.readlink?.(path).catch(() => void 0);
|
|
5761
|
+
}
|
|
5762
|
+
async function realDir(fs, dir) {
|
|
5763
|
+
const queue = dir.split("/").filter(Boolean);
|
|
5764
|
+
let at = "/";
|
|
5765
|
+
let hops = 0;
|
|
5766
|
+
while (queue.length > 0) {
|
|
5767
|
+
const part = queue.shift();
|
|
5768
|
+
if (part === ".") continue;
|
|
5769
|
+
if (part === "..") {
|
|
5770
|
+
at = parentOf5(at);
|
|
5771
|
+
continue;
|
|
5772
|
+
}
|
|
5773
|
+
const next = at === "/" ? `/${part}` : `${at}/${part}`;
|
|
5774
|
+
const link2 = hops < MAX_LINKS5 ? await linkOf(fs, next) : void 0;
|
|
5775
|
+
if (link2 === void 0) {
|
|
5776
|
+
at = next;
|
|
5777
|
+
continue;
|
|
5778
|
+
}
|
|
5779
|
+
hops++;
|
|
5780
|
+
queue.unshift(...link2.split("/").filter(Boolean));
|
|
5781
|
+
if (link2.startsWith("/")) at = "/";
|
|
5782
|
+
}
|
|
5783
|
+
return at;
|
|
5784
|
+
}
|
|
5785
|
+
async function targetDir(fs, path) {
|
|
5786
|
+
let dir = await realDir(fs, parentOf5(path));
|
|
5787
|
+
let name2 = path.slice(path.lastIndexOf("/") + 1);
|
|
5788
|
+
for (let hops = 0; hops < MAX_LINKS5; hops++) {
|
|
5789
|
+
const link2 = await linkOf(fs, dir === "/" ? `/${name2}` : `${dir}/${name2}`);
|
|
5790
|
+
if (link2 === void 0) return dir;
|
|
5791
|
+
const target = link2.startsWith("/") ? link2 : `${dir}/${link2}`;
|
|
5792
|
+
dir = await realDir(fs, parentOf5(target));
|
|
5793
|
+
name2 = target.slice(target.lastIndexOf("/") + 1);
|
|
5794
|
+
}
|
|
5795
|
+
return dir;
|
|
5796
|
+
}
|
|
5745
5797
|
async function refuseReadonly(fs, path, flags, opts = {}) {
|
|
5746
5798
|
const writes = (flags & O_ACCMODE) !== 0 || opts.truncate === true;
|
|
5747
5799
|
if (!writes && !opts.create || !fs.stat) return;
|
|
@@ -5750,10 +5802,9 @@ async function refuseReadonly(fs, path, flags, opts = {}) {
|
|
|
5750
5802
|
if (isMissing(err) || typeof code !== "string") return void 0;
|
|
5751
5803
|
throw err;
|
|
5752
5804
|
});
|
|
5753
|
-
const parent = path.slice(0, path.lastIndexOf("/")) || "/";
|
|
5754
5805
|
const own = await stat(path);
|
|
5755
5806
|
if (own && !writes) return;
|
|
5756
|
-
const st = own ?? await stat(
|
|
5807
|
+
const st = own ?? await stat(await targetDir(fs, path));
|
|
5757
5808
|
if (st?.readonly) throw new KernelError("EROFS");
|
|
5758
5809
|
}
|
|
5759
5810
|
function vfsFile(fs, opts, nodes) {
|
|
@@ -6674,6 +6725,17 @@ var JobTable = class {
|
|
|
6674
6725
|
const parent = this.members.get(this.shown(pid))?.ppid;
|
|
6675
6726
|
return parent === void 0 ? void 0 : this.shown(parent);
|
|
6676
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
|
+
}
|
|
6677
6739
|
pgidOf(pid) {
|
|
6678
6740
|
return this.members.get(pid)?.pgid;
|
|
6679
6741
|
}
|
|
@@ -8041,7 +8103,13 @@ var Launcher = class {
|
|
|
8041
8103
|
}
|
|
8042
8104
|
return this.start({ ...req, program, argv0: target.argv0, args, env });
|
|
8043
8105
|
}
|
|
8106
|
+
groupSession(pgid) {
|
|
8107
|
+
return this.jobs.sessionOf(pgid);
|
|
8108
|
+
}
|
|
8044
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
|
+
}
|
|
8045
8113
|
const pid = this.nextPid++;
|
|
8046
8114
|
const terminal = req.fds.stdioTerminal();
|
|
8047
8115
|
const handle = spawnWasmProcess({
|
|
@@ -8077,6 +8145,7 @@ var Launcher = class {
|
|
|
8077
8145
|
this.processes.set(pid, handle);
|
|
8078
8146
|
this.jobs.add(pid, req.ppid, (sig) => handle.signal(sig), terminal);
|
|
8079
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);
|
|
8080
8149
|
this.described.set(pid, {
|
|
8081
8150
|
argv: [req.argv0, ...req.args],
|
|
8082
8151
|
tty: terminal?.name ?? null,
|
|
@@ -8376,7 +8445,8 @@ var Launcher = class {
|
|
|
8376
8445
|
fds.installAt(0, options.stdin ? bytesSource(options.stdin) : nullFile());
|
|
8377
8446
|
fds.installAt(1, sinkFile(stdout));
|
|
8378
8447
|
fds.installAt(2, sinkFile(stderr));
|
|
8379
|
-
const
|
|
8448
|
+
const group = options.pgid !== void 0 ? { pgid: options.pgid } : {};
|
|
8449
|
+
const handle = await this.launch(planned, { env, cwd, fds, report, ...group });
|
|
8380
8450
|
options.onStarted?.(handle.pid);
|
|
8381
8451
|
const status = await handle.exited;
|
|
8382
8452
|
return { status, stdout: concat5(out), stderr: concat5(err) };
|