@ai-ecoverse/slicc-kernel 1.174.1 → 1.174.2

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.
@@ -3118,7 +3118,7 @@ var init_version = __esm({
3118
3118
  "src/version.ts"() {
3119
3119
  "use strict";
3120
3120
  init_captured_globals();
3121
- KERNEL_VERSION = true ? "1.174.1" : "0.0.0-dev";
3121
+ KERNEL_VERSION = true ? "1.174.2" : "0.0.0-dev";
3122
3122
  OS_RELEASE = "6.0.0-slicc";
3123
3123
  }
3124
3124
  });
package/dist/testing.js CHANGED
@@ -105,7 +105,8 @@ function answerOf(result) {
105
105
  var NEVER = new Routes(true);
106
106
 
107
107
  // src/cron/clock.ts
108
- function fakeCronClock(start = Date.UTC(2026, 0, 1), utc = true) {
108
+ function fakeCronClock(start = Date.UTC(2026, 0, 1), zone = true) {
109
+ const timeZone = zone === true ? "UTC" : zone === false ? void 0 : zone;
109
110
  let now = start;
110
111
  const sleepers = /* @__PURE__ */ new Set();
111
112
  let idle = [];
@@ -121,7 +122,8 @@ function fakeCronClock(start = Date.UTC(2026, 0, 1), utc = true) {
121
122
  for (const sleeper of [...sleepers]) if (sleeper.until <= now) sleeper.ring();
122
123
  };
123
124
  return {
124
- utc,
125
+ utc: timeZone === "UTC",
126
+ ...timeZone !== void 0 ? { timeZone } : {},
125
127
  now: () => now,
126
128
  get sleepers() {
127
129
  return sleepers.size;
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/kernel/net/loopback-names.ts", "../src/kernel/net/routes.ts", "../src/kernel/net/uplink.ts", "../src/cron/clock.ts", "../src/kernel/net/placeholder-floor.ts", "../src/body-idle.ts", "../src/kernel/net/sealed-fetch.ts", "../src/kernel/test-hooks.ts", "../src/bytes.ts", "../src/sealed-relay.ts", "../src/testing.ts"],
4
- "sourcesContent": ["export const HOST_LOOPBACK = 'host.slicc.internal';\n\nexport const HOST_LOOPBACK_ADDRESS = [10, 0, 2, 2] as const;\n\nexport const PAGE_LOOPBACK = 'kernel.localhost';\n\nexport const PAGE_LOOPBACK_URL = `http://{port}.${PAGE_LOOPBACK}`;\n\nexport function toHostLoopback(href: string): string {\n const url = new URL(href);\n if (url.hostname.replace(/\\.$/, '').toLowerCase() !== HOST_LOOPBACK) return href;\n url.hostname = '127.0.0.1';\n return url.href;\n}\n\nconst LOOPBACK_V4 = /^127\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}$/;\nconst LOOPBACK_V6 = new Set(['::1', '::', '0:0:0:0:0:0:0:1']);\nconst MAPPED_V4 = /^::ffff:7f[0-9a-f]{2}:[0-9a-f]{1,4}$/;\nconst KERNEL_PORT = /^(\\d{1,5})\\.kernel\\.localhost$/;\nconst SCHEMES: Readonly<Record<string, number>> = {\n 'http:': 80,\n 'ws:': 80,\n 'https:': 443,\n 'wss:': 443,\n};\n\nexport function isKernelLoopbackHost(hostname: string): boolean {\n const host = hostname\n .replace(/^\\[(.*)\\]$/, '$1')\n .replace(/\\.$/, '')\n .toLowerCase();\n return (\n host === 'localhost' ||\n host.endsWith('.localhost') ||\n host === '0.0.0.0' ||\n LOOPBACK_V4.test(host) ||\n LOOPBACK_V6.has(host) ||\n MAPPED_V4.test(host)\n );\n}\n\nexport function kernelLoopbackPort(href: string): number | undefined {\n let url: URL;\n try {\n url = new URL(href);\n } catch {\n return undefined;\n }\n const fallback = SCHEMES[url.protocol];\n if (fallback === undefined || !isKernelLoopbackHost(url.hostname)) return undefined;\n const named = KERNEL_PORT.exec(url.hostname.replace(/\\.$/, '').toLowerCase())?.[1];\n const port = Number(named ?? (url.port || fallback));\n return port >= 1 && port <= 65535 ? port : undefined;\n}\n\nexport const DEFAULT_HOSTNAME = 'slicc';\n\nexport const HOSTNAME_ADDRESS = '127.0.1.1';\n\nexport const LIBC_HOSTNAMES: readonly string[] = ['emscripten', 'wasmer.sh'];\n\nconst LABEL = /^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$/i;\n\nfunction reserved(name: string): boolean {\n const lower = name.toLowerCase();\n return (\n lower === 'localhost' ||\n lower.endsWith('.localhost') ||\n lower === HOST_LOOPBACK ||\n lower === 'wasmer.sh' ||\n /^\\d+(\\.\\d+){3}$/.test(lower)\n );\n}\n\nexport function isHostname(name: unknown): name is string {\n if (typeof name !== 'string' || name.length > 253 || reserved(name)) return false;\n return name.split('.').every((l) => LABEL.test(l));\n}\n\nexport function hostnameOf(env: Readonly<Record<string, string>>): string {\n return isHostname(env.HOSTNAME) ? env.HOSTNAME : DEFAULT_HOSTNAME;\n}\n\nexport function initHostname(init: {\n hostname?: string | undefined;\n env: Readonly<Record<string, string>>;\n}): string {\n return isHostname(init.hostname) ? init.hostname : hostnameOf(init.env);\n}\n\nexport function ownNames(hostname: string): string[] {\n return [...new Set([hostname.toLowerCase(), ...LIBC_HOSTNAMES])];\n}\n\nexport function hostsFile(hostname: string = DEFAULT_HOSTNAME): string {\n return [\n '127.0.0.1 localhost localhost.localdomain',\n '::1 localhost ip6-localhost',\n `${HOSTNAME_ADDRESS} ${ownNames(hostname).join(' ')}`,\n `${HOST_LOOPBACK_ADDRESS.join('.')} ${HOST_LOOPBACK}`,\n '',\n ].join('\\n');\n}\n", "import { HOST_LOOPBACK, HOST_LOOPBACK_ADDRESS } from './loopback-names.ts';\n\nexport interface RouteTable {\n prefixes: readonly string[];\n exit: boolean;\n}\n\nexport type Destination = 'loopback' | 'host' | 'reserved' | 'uplink' | 'unreachable';\n\ninterface Prefix {\n v6: boolean;\n bits: bigint;\n length: number;\n}\n\nconst HOST_ADDRESS = HOST_LOOPBACK_ADDRESS.join('.');\n\nexport function ipv4Bytes(text: string): number[] | undefined {\n const parts = text.split('.');\n if (parts.length !== 4 || !parts.every((p) => /^\\d{1,3}$/.test(p))) return undefined;\n const bytes = parts.map(Number);\n return bytes.every((b) => b <= 255) ? bytes : undefined;\n}\n\nexport function ipv6Groups(text: string): number[] | undefined {\n if (!text.includes(':')) return undefined;\n let canonical: string;\n try {\n canonical = new URL(`http://[${text}]/`).hostname.slice(1, -1);\n } catch {\n return undefined;\n }\n const [head, tail] = canonical.split('::');\n const part = (s: string | undefined) =>\n s ? s.split(':').map((h) => Number.parseInt(h, 16)) : [];\n const front = part(head);\n const back = part(tail);\n return tail === undefined\n ? front\n : [...front, ...new Array<number>(8 - front.length - back.length).fill(0), ...back];\n}\n\nfunction toBits(values: number[], width: number): bigint {\n return values.reduce((acc, v) => (acc << BigInt(width)) | BigInt(v), 0n);\n}\n\nfunction addressBits(host: string): { v6: boolean; bits: bigint } | undefined {\n const v4 = ipv4Bytes(host);\n if (v4) return { v6: false, bits: toBits(v4, 8) };\n const v6 = ipv6Groups(host);\n return v6 ? { v6: true, bits: toBits(v6, 16) } : undefined;\n}\n\nfunction parsePrefix(text: string): Prefix | undefined {\n const parts = text.trim().split('/');\n if (parts.length > 2) return undefined;\n const [address = '', size] = parts;\n const parsed = addressBits(address);\n if (!parsed) return undefined;\n const max = parsed.v6 ? 128 : 32;\n const length = size === undefined ? max : /^\\d{1,3}$/.test(size) ? Number(size) : -1;\n if (length < 0 || length > max) return undefined;\n return { ...parsed, length };\n}\n\nfunction within(prefix: Prefix, addr: { v6: boolean; bits: bigint }): boolean {\n if (prefix.v6 !== addr.v6) return false;\n const shift = BigInt((prefix.v6 ? 128 : 32) - prefix.length);\n return addr.bits >> shift === prefix.bits >> shift;\n}\n\nconst RESERVED = [\n '0.0.0.0/8',\n '127.0.0.0/8',\n '169.254.0.0/16',\n '224.0.0.0/4',\n '240.0.0.0/4',\n '::/96',\n '::ffff:0:0/96',\n 'fe80::/10',\n 'ff00::/8',\n].map((p) => parsePrefix(p) as Prefix);\n\nexport class Routes {\n private table: Prefix[] = [];\n private exit = false;\n readonly ipv6: boolean;\n\n constructor(ipv6 = false) {\n this.ipv6 = ipv6;\n }\n\n set(table: RouteTable): void {\n const parsed = (table.prefixes ?? []).map(parsePrefix);\n const bad = (table.prefixes ?? []).find((_, i) => !parsed[i]);\n if (bad !== undefined) throw new Error(`not an address prefix: ${bad}`);\n this.table = parsed as Prefix[];\n this.exit = table.exit === true;\n }\n\n classify(host: string): Destination {\n const name = host.toLowerCase().replace(/\\.$/, '');\n if (name === 'localhost' || name.endsWith('.localhost') || name === '0.0.0.0') {\n return 'loopback';\n }\n if (name === HOST_LOOPBACK || name === HOST_ADDRESS) return 'host';\n const addr = addressBits(name);\n if (!addr) return 'unreachable';\n if (addr.v6 && addr.bits === 1n) return 'loopback';\n if (!addr.v6 && addr.bits >> 24n === 127n) return 'loopback';\n if (RESERVED.some((p) => within(p, addr))) return 'reserved';\n if (addr.v6 && !this.ipv6) return 'unreachable';\n if (this.exit || this.table.some((p) => within(p, addr))) return 'uplink';\n return 'unreachable';\n }\n}\n", "import { Routes, type RouteTable } from './routes.ts';\n\nexport interface UplinkTraits {\n tcp: true;\n udp: boolean;\n ipv6: boolean;\n}\n\nexport type ResolveFamily = 0 | 4 | 6;\n\nexport interface ResolveAnswer {\n addresses: string[];\n ttl?: number;\n}\n\nexport interface UplinkConn {\n readonly localAddr: string;\n readonly remoteAddr: string;\n readonly exit?: string;\n read(): Promise<Uint8Array | null>;\n write(bytes: Uint8Array): Promise<number>;\n closeWrite(): void;\n close(): void;\n}\n\nexport interface UplinkDial {\n network: 'tcp';\n host: string;\n port: number;\n signal: AbortSignal;\n}\n\nexport interface UplinkDatagram {\n bytes: Uint8Array;\n host: string;\n port: number;\n}\n\nexport interface UplinkUnreachable {\n error: string;\n host: string;\n port: number;\n}\n\nexport type UplinkMessage = UplinkDatagram | UplinkUnreachable;\n\nexport interface UplinkUdpOpen {\n family: 4 | 6;\n signal: AbortSignal;\n}\n\nexport interface UplinkUdp {\n readonly localAddr: string;\n send(bytes: Uint8Array, host: string, port: number): Promise<void>;\n readonly messages: AsyncIterable<UplinkMessage>;\n close(): void;\n}\n\nexport interface NetworkUplink {\n readonly traits: UplinkTraits;\n readonly routes?: RouteTable;\n readonly nameserver?: string;\n resolve(\n name: string,\n family: ResolveFamily,\n signal?: AbortSignal\n ): Promise<string[] | ResolveAnswer>;\n dial(req: UplinkDial): Promise<UplinkConn>;\n udp?(req: UplinkUdpOpen): Promise<UplinkUdp>;\n}\n\nexport function carriesUdp(uplink: NetworkUplink): boolean {\n return uplink.traits.udp === true && typeof uplink.udp === 'function';\n}\n\nexport type UplinkCall =\n | { uplink: 'resolve'; uid: number; name: string; family: ResolveFamily }\n | { uplink: 'dial'; uid: number; host: string; port: number }\n | { uplink: 'cancel'; uid: number }\n | { uplink: 'read'; uid: number; cid: number }\n | { uplink: 'write'; uid: number; cid: number; bytes: Uint8Array }\n | { uplink: 'close-write'; cid: number }\n | { uplink: 'close'; cid: number }\n | { uplink: 'udp-open'; uid: number; family: 4 | 6 }\n | { uplink: 'udp-send'; uid: number; cid: number; bytes: Uint8Array; host: string; port: number }\n | { uplink: 'udp-recv'; uid: number; cid: number }\n | { uplink: 'udp-close'; cid: number };\n\nexport type UplinkReply =\n | { uplink: 'resolved'; uid: number; addresses: string[]; ttl?: number }\n | { uplink: 'dialled'; uid: number; cid: number; localAddr: string; remoteAddr: string }\n | { uplink: 'data'; uid: number; bytes: Uint8Array | null }\n | { uplink: 'written'; uid: number; n: number }\n | { uplink: 'udp-opened'; uid: number; cid: number; localAddr: string }\n | { uplink: 'udp-sent'; uid: number }\n | { uplink: 'udp-message'; uid: number; message: UplinkMessage | null }\n | { uplink: 'error'; uid: number; message: string; code?: string };\n\nexport interface UplinkPeer {\n postMessage(message: UplinkReply, transfer?: Transferable[]): void;\n}\n\nexport interface UplinkPort {\n postMessage(message: UplinkCall, transfer?: Transferable[]): void;\n}\n\nexport interface UplinkServer {\n answer(call: UplinkCall): void;\n close(): void;\n}\n\nexport function answerOf(result: string[] | ResolveAnswer): ResolveAnswer {\n const answer = Array.isArray(result) ? { addresses: result } : result;\n const addresses = Array.isArray(answer?.addresses)\n ? answer.addresses.filter((a): a is string => typeof a === 'string')\n : [];\n return {\n addresses,\n ...(typeof answer?.ttl === 'number' && answer.ttl >= 0 ? { ttl: answer.ttl } : {}),\n };\n}\n\nfunction failure(uid: number, e: unknown): UplinkReply {\n const code = (e as { code?: unknown } | null)?.code;\n return {\n uplink: 'error',\n uid,\n message: e instanceof Error ? e.message : String(e),\n ...(typeof code === 'string' ? { code } : {}),\n };\n}\n\nconst NEVER = new Routes(true);\n\nexport function serveUplink(peer: UplinkPeer, uplink: NetworkUplink): UplinkServer {\n const conns = new Map<number, UplinkConn>();\n const pending = new Map<number, AbortController>();\n let nextCid = 0;\n let closed = false;\n const run = (uid: number, work: (signal: AbortSignal) => Promise<UplinkReply | undefined>) => {\n const abort = new AbortController();\n pending.set(uid, abort);\n void work(abort.signal)\n .then(\n (reply) => reply && peer.postMessage(reply, transferOf(reply)),\n (e: unknown) => peer.postMessage(failure(uid, e))\n )\n .finally(() => pending.delete(uid));\n };\n const conn = (cid: number): UplinkConn => {\n const found = conns.get(cid);\n if (!found) throw Object.assign(new Error('no such uplink connection'), { code: 'EBADF' });\n return found;\n };\n const dial = async (call: Extract<UplinkCall, { uplink: 'dial' }>, signal: AbortSignal) => {\n refuseLocal(call.host);\n const { host, port } = call;\n const opened = await uplink.dial({ network: 'tcp', host, port, signal });\n if (signal.aborted || closed) {\n opened.close();\n return undefined;\n }\n const cid = ++nextCid;\n conns.set(cid, opened);\n const { localAddr, remoteAddr } = opened;\n return { uplink: 'dialled' as const, uid: call.uid, cid, localAddr, remoteAddr };\n };\n const drop = (cid: number) => {\n const found = conns.get(cid);\n conns.delete(cid);\n found?.close();\n };\n const udp = new UdpServer(uplink, () => closed);\n return {\n answer(call) {\n switch (call.uplink) {\n case 'resolve':\n return run(call.uid, async (signal) => ({\n uplink: 'resolved',\n uid: call.uid,\n ...answerOf(await uplink.resolve(call.name, call.family, signal)),\n }));\n case 'dial':\n return run(call.uid, (signal) => dial(call, signal));\n case 'cancel':\n return pending.get(call.uid)?.abort();\n case 'read':\n return run(call.uid, async () => ({\n uplink: 'data',\n uid: call.uid,\n bytes: (await conn(call.cid).read())?.slice() ?? null,\n }));\n case 'write':\n return run(call.uid, async () => ({\n uplink: 'written',\n uid: call.uid,\n n: await conn(call.cid).write(call.bytes),\n }));\n case 'close-write':\n return conns.get(call.cid)?.closeWrite();\n case 'close':\n return drop(call.cid);\n case 'udp-close':\n return udp.drop(call.cid);\n default:\n return run(call.uid, (signal) => udp.answer(call, signal));\n }\n },\n close() {\n closed = true;\n for (const abort of pending.values()) abort.abort();\n for (const cid of [...conns.keys()]) drop(cid);\n udp.close();\n },\n };\n}\n\nfunction copied(message: UplinkMessage): UplinkMessage {\n if ('bytes' in message) return { ...message, bytes: message.bytes.slice() };\n return { error: String(message.error), host: message.host, port: message.port };\n}\n\nfunction refuseLocal(host: string): void {\n const kind = NEVER.classify(host);\n if (kind === 'loopback' || kind === 'host' || kind === 'reserved') {\n throw Object.assign(new Error(`the uplink does not carry ${host}`), { code: 'ENETUNREACH' });\n }\n}\n\ntype UdpCall = Extract<UplinkCall, { uplink: 'udp-open' | 'udp-send' | 'udp-recv' }>;\n\nclass UdpServer {\n private readonly sockets = new Map<\n number,\n { udp: UplinkUdp; messages: AsyncIterator<UplinkMessage> }\n >();\n private next = 0;\n private readonly uplink: NetworkUplink;\n private readonly closed: () => boolean;\n\n constructor(uplink: NetworkUplink, closed: () => boolean) {\n this.uplink = uplink;\n this.closed = closed;\n }\n\n private socket(cid: number) {\n const found = this.sockets.get(cid);\n if (!found) throw Object.assign(new Error('no such uplink socket'), { code: 'EBADF' });\n return found;\n }\n\n async answer(call: UdpCall, signal: AbortSignal): Promise<UplinkReply | undefined> {\n if (call.uplink === 'udp-open') {\n if (!this.uplink.udp || this.uplink.traits.udp !== true) {\n throw Object.assign(new Error('the uplink carries no datagrams'), { code: 'ENETUNREACH' });\n }\n const opened = await this.uplink.udp({ family: call.family, signal });\n if (signal.aborted || this.closed()) {\n opened.close();\n return undefined;\n }\n const cid = ++this.next;\n this.sockets.set(cid, { udp: opened, messages: opened.messages[Symbol.asyncIterator]() });\n return { uplink: 'udp-opened', uid: call.uid, cid, localAddr: opened.localAddr };\n }\n if (call.uplink === 'udp-send') {\n refuseLocal(call.host);\n await this.socket(call.cid).udp.send(call.bytes, call.host, call.port);\n return { uplink: 'udp-sent', uid: call.uid };\n }\n const next = await this.socket(call.cid).messages.next();\n const message = next.done ? null : copied(next.value);\n return { uplink: 'udp-message', uid: call.uid, message };\n }\n\n drop(cid: number): void {\n const found = this.sockets.get(cid);\n this.sockets.delete(cid);\n found?.udp.close();\n }\n\n close(): void {\n for (const cid of [...this.sockets.keys()]) this.drop(cid);\n }\n}\n\nfunction transferOf(reply: UplinkReply): Transferable[] | undefined {\n if (reply.uplink === 'udp-message' && reply.message && 'bytes' in reply.message) {\n return [reply.message.bytes.buffer as ArrayBuffer];\n }\n if (reply.uplink !== 'data' || !reply.bytes) return undefined;\n return [reply.bytes.buffer as ArrayBuffer];\n}\n\ntype Answer = Exclude<UplinkReply, { uplink: 'error' }>;\n\nexport class RemoteUplink implements NetworkUplink {\n readonly traits: UplinkTraits;\n readonly routes: RouteTable | undefined;\n readonly nameserver: string | undefined;\n private readonly port: UplinkPort;\n private readonly waiting = new Map<number, PromiseWithResolvers<Answer>>();\n private nextId = 0;\n\n constructor(port: UplinkPort, traits: UplinkTraits, routes?: RouteTable, nameserver?: string) {\n this.port = port;\n this.traits = traits;\n this.routes = routes;\n this.nameserver = nameserver;\n }\n\n receive(reply: UplinkReply): void {\n const waiter = this.waiting.get(reply.uid);\n if (!waiter) return;\n this.waiting.delete(reply.uid);\n if (reply.uplink === 'error') {\n waiter.reject(Object.assign(new Error(reply.message), { code: reply.code }));\n } else waiter.resolve(reply);\n }\n\n private ask<T extends Answer>(\n call: Extract<UplinkCall, { uid: number }>,\n signal?: AbortSignal,\n transfer?: Transferable[]\n ): Promise<T> {\n const waiter = Promise.withResolvers<Answer>();\n this.waiting.set(call.uid, waiter);\n const abort = () => {\n this.waiting.delete(call.uid);\n this.port.postMessage({ uplink: 'cancel', uid: call.uid });\n waiter.reject(signal?.reason);\n };\n signal?.addEventListener('abort', abort, { once: true });\n const settled = () => signal?.removeEventListener('abort', abort);\n waiter.promise.then(settled, settled);\n this.port.postMessage(call, transfer);\n return waiter.promise as Promise<T>;\n }\n\n async resolve(name: string, family: ResolveFamily, signal?: AbortSignal) {\n const reply = await this.ask<Extract<Answer, { uplink: 'resolved' }>>(\n { uplink: 'resolve', uid: ++this.nextId, name, family },\n signal\n );\n return answerOf(reply);\n }\n\n async dial(req: UplinkDial): Promise<UplinkConn> {\n req.signal.throwIfAborted();\n const { host, port } = req;\n const opened = await this.ask<Extract<Answer, { uplink: 'dialled' }>>(\n { uplink: 'dial', uid: ++this.nextId, host, port },\n req.signal\n );\n const { cid, localAddr, remoteAddr } = opened;\n return {\n localAddr,\n remoteAddr,\n read: async () => {\n const got = await this.ask<Extract<Answer, { uplink: 'data' }>>({\n uplink: 'read',\n uid: ++this.nextId,\n cid,\n });\n return got.bytes;\n },\n write: async (bytes) => {\n const copy = bytes.slice();\n const call = { uplink: 'write' as const, uid: ++this.nextId, cid, bytes: copy };\n const done = await this.ask<Extract<Answer, { uplink: 'written' }>>(call, undefined, [\n copy.buffer,\n ]);\n return done.n;\n },\n closeWrite: () => this.port.postMessage({ uplink: 'close-write', cid }),\n close: () => this.port.postMessage({ uplink: 'close', cid }),\n };\n }\n\n async udp(req: UplinkUdpOpen): Promise<UplinkUdp> {\n req.signal.throwIfAborted();\n const opened = await this.ask<Extract<Answer, { uplink: 'udp-opened' }>>(\n { uplink: 'udp-open', uid: ++this.nextId, family: req.family },\n req.signal\n );\n const { cid, localAddr } = opened;\n const recv = () =>\n this.ask<Extract<Answer, { uplink: 'udp-message' }>>({\n uplink: 'udp-recv',\n uid: ++this.nextId,\n cid,\n });\n return {\n localAddr,\n send: async (bytes, host, port) => {\n const copy = bytes.slice();\n const call = {\n uplink: 'udp-send' as const,\n uid: ++this.nextId,\n cid,\n bytes: copy,\n host,\n port,\n };\n await this.ask(call, undefined, [copy.buffer]);\n },\n messages: {\n [Symbol.asyncIterator]: async function* () {\n for (;;) {\n const got = await recv();\n if (!got.message) return;\n yield got.message;\n }\n },\n },\n close: () => this.port.postMessage({ uplink: 'udp-close', cid }),\n };\n }\n}\n", "export interface CronClock {\n now(): number;\n readonly utc?: boolean;\n sleep(until: number, signal: AbortSignal): Promise<void>;\n}\n\nexport const systemCronClock: CronClock = {\n now: () => Date.now(),\n sleep(until, signal) {\n if (signal.aborted) return Promise.resolve();\n return new Promise((resolve) => {\n const done = () => {\n clearTimeout(timer);\n signal.removeEventListener('abort', done);\n resolve();\n };\n const timer = setTimeout(done, Math.max(0, until - Date.now()));\n (timer as { unref?: () => void }).unref?.();\n signal.addEventListener('abort', done, { once: true });\n });\n },\n};\n\nexport interface FakeCronClock extends CronClock {\n set(ms: number): void;\n advance(ms: number): void;\n flush(): Promise<void>;\n readonly sleepers: number;\n}\n\ninterface Sleeper {\n until: number;\n wake: () => void;\n ring: () => void;\n}\n\nexport function fakeCronClock(start = Date.UTC(2026, 0, 1), utc = true): FakeCronClock {\n let now = start;\n const sleepers = new Set<Sleeper>();\n let idle: Array<() => void> = [];\n let awake = 0;\n const settled = () =>\n awake === 0 && sleepers.size > 0 && [...sleepers].every((s) => s.until > now);\n const check = () => {\n if (!settled()) return;\n const waiting = idle;\n idle = [];\n for (const resolve of waiting) resolve();\n };\n const wakeDue = () => {\n for (const sleeper of [...sleepers]) if (sleeper.until <= now) sleeper.ring();\n };\n return {\n utc,\n now: () => now,\n get sleepers() {\n return sleepers.size;\n },\n sleep(until, signal) {\n if (signal.aborted) return Promise.resolve();\n return new Promise((resolve) => {\n const sleeper: Sleeper = {\n until,\n wake: () => {\n sleepers.delete(sleeper);\n signal.removeEventListener('abort', sleeper.wake);\n resolve();\n },\n ring: () => {\n if (!sleepers.has(sleeper)) return;\n awake++;\n sleeper.wake();\n },\n };\n awake = Math.max(0, awake - 1);\n signal.addEventListener('abort', sleeper.wake, { once: true });\n sleepers.add(sleeper);\n if (until <= now) queueMicrotask(sleeper.ring);\n else check();\n });\n },\n set(ms) {\n now = ms;\n for (const sleeper of [...sleepers]) sleeper.ring();\n },\n advance(ms) {\n now += ms;\n wakeDue();\n },\n flush() {\n return new Promise((resolve) => {\n idle.push(resolve);\n queueMicrotask(check);\n });\n },\n };\n}\n", "import type { SealedCaller } from '../sealed.ts';\nimport type {\n HeaderList,\n RealmTransport,\n RealmTransportRequest,\n RealmTransportResponse,\n RealmWebSocketRequest,\n} from './transport.ts';\n\nconst PLACEHOLDER = /fnox_proxy_[0-9a-f]{24}/;\nconst ESCAPE = /%([0-9a-f]{2})/gi;\nconst BASIC = /\\bbasic\\b(.*)/is;\nconst PERCENT_LAYERS = 8;\nconst BASE64_GROUP = 4;\n\nexport const PLACEHOLDER_REFUSED =\n 'refused: this request has a sealed placeholder in its URL, a header or a Basic credential, and nothing fills it, so it was not sent';\n\nexport class PlaceholderRefused extends Error {\n readonly status = 403;\n readonly code = 'EACCES';\n\n constructor(reason = PLACEHOLDER_REFUSED) {\n super(reason);\n }\n}\n\nexport type PlaceholderFill = (\n request: RealmTransportRequest,\n stamp: SealedCaller\n) => Promise<RealmTransportResponse>;\n\nexport interface PlaceholderFloorOptions {\n known?: () => readonly string[];\n fill?: PlaceholderFill;\n}\n\ntype Known = readonly string[];\n\nfunction holds(text: string, known: Known): boolean {\n return PLACEHOLDER.test(text) || known.some((placeholder) => text.includes(placeholder));\n}\n\nfunction carries(text: string, known: Known): boolean {\n let layer = text;\n for (let i = 0; i < PERCENT_LAYERS; i++) {\n if (holds(layer, known)) return true;\n const next = layer.replace(ESCAPE, (_, hex: string) =>\n String.fromCharCode(Number.parseInt(hex, 16))\n );\n if (next === layer) return false;\n layer = next;\n }\n return holds(layer, known);\n}\n\nfunction basicCarries(value: string, known: Known): boolean {\n const credential = BASIC.exec(value)?.[1];\n if (credential === undefined) return false;\n const letters = credential\n .replace(/[^A-Za-z0-9+/_-]/g, '')\n .replaceAll('-', '+')\n .replaceAll('_', '/');\n for (let shift = 0; shift < BASE64_GROUP; shift++) {\n const part = letters.slice(shift);\n const whole = part.length % BASE64_GROUP === 1 ? part.slice(0, -1) : part;\n if (carries(atob(whole), known)) return true;\n }\n return false;\n}\n\nfunction headersCarry(headers: HeaderList, known: Known): boolean {\n return headers.some(\n ([name, value]) =>\n carries(name, known) ||\n carries(name.toLowerCase(), known) ||\n carries(value, known) ||\n basicCarries(value, known)\n );\n}\n\nfunction urlCarries(url: string, known: Known): boolean {\n return carries(url, known) || (URL.canParse(url) && carries(new URL(url).href, known));\n}\n\nfunction detected(request: Pick<RealmTransportRequest, 'url' | 'headers'>, known: Known): boolean {\n return urlCarries(request.url, known) || headersCarry(request.headers, known);\n}\n\nfunction refuseSocket(request: RealmWebSocketRequest, known: Known): void {\n if (detected(request, known) || request.protocols.some((p) => carries(p, known))) {\n throw new PlaceholderRefused();\n }\n}\n\nexport function placeholderFloor(\n inner: RealmTransport,\n { known = () => [], fill }: PlaceholderFloorOptions = {}\n): RealmTransport {\n const open = inner.websocket?.bind(inner);\n return {\n get traits() {\n return inner.traits;\n },\n ...(open\n ? {\n websocket: async (request) => {\n refuseSocket(request, known());\n return open(request);\n },\n }\n : {}),\n async fetch(request, owner, stamp) {\n if (!detected(request, known())) return inner.fetch(request, owner, stamp);\n if (!fill || !stamp) throw new PlaceholderRefused();\n return fill(request, stamp);\n },\n };\n}\n", "export const BODY_IDLE_MS = 5 * 60 * 1000;\n\nexport function idleFailure(ms: number): Error {\n return Object.assign(new Error(`the response body sent no data for ${ms} ms`), {\n code: 'ETIMEDOUT',\n });\n}\n\nexport async function readWithin<T>(\n reader: ReadableStreamDefaultReader<T>,\n ms: number\n): Promise<ReadableStreamReadResult<T>> {\n if (!(ms > 0 && ms < Number.POSITIVE_INFINITY)) return reader.read();\n let timer: ReturnType<typeof setTimeout> | undefined;\n const idle = new Promise<never>((_, reject) => {\n timer = setTimeout(() => reject(idleFailure(ms)), ms);\n });\n try {\n return await Promise.race([reader.read(), idle]);\n } finally {\n clearTimeout(timer);\n }\n}\n", "import { BODY_IDLE_MS } from '../../body-idle.ts';\nimport type { SealedCaller, SealedHook } from '../sealed.ts';\nimport { PlaceholderRefused } from './placeholder-floor.ts';\nimport type { HeaderList, RealmTransportRequest, RealmTransportResponse } from './transport.ts';\n\nexport const SEALED_FETCH_VERSION = 1;\n\nconst UNSAFE_FIELD = /[\\r\\n\\0]/;\n\nexport interface SealedFetchRequest {\n v: 1;\n caller: SealedCaller;\n method: string;\n url: string;\n headers: HeaderList;\n redirect: 'manual';\n body?: Uint8Array;\n bodyStream?: AsyncIterable<Uint8Array>;\n}\n\nexport type SealedFetchHook = (\n req: SealedFetchRequest,\n options: { signal: AbortSignal }\n) => Promise<RealmTransportResponse>;\n\nexport type SealedOption = SealedHook | { request: SealedHook; fetch?: SealedFetchHook };\n\nexport function sealedHooks(option: SealedOption | undefined): {\n request?: SealedHook;\n fetch?: SealedFetchHook;\n} {\n if (!option) return {};\n if (typeof option === 'function') return { request: option };\n const { request, fetch } = option;\n if (typeof request !== 'function' || (fetch !== undefined && typeof fetch !== 'function')) {\n throw new TypeError('sealed takes a function or { request, fetch? }');\n }\n return { request, ...(fetch ? { fetch } : {}) };\n}\n\nfunction headerList(headers: unknown): headers is HeaderList {\n return (\n Array.isArray(headers) &&\n headers.every(\n (field) =>\n Array.isArray(field) &&\n field.length === 2 &&\n field.every((text) => typeof text === 'string' && !UNSAFE_FIELD.test(text))\n )\n );\n}\n\nexport function sealedReplyValid(reply: unknown): reply is RealmTransportResponse {\n if (typeof reply !== 'object' || reply === null) return false;\n const { redirects, redirected, status, statusText, headers, url, body, cancel } =\n reply as Partial<RealmTransportResponse>;\n return (\n redirects === undefined &&\n redirected !== true &&\n Number.isInteger(status) &&\n (status as number) >= 100 &&\n (status as number) <= 599 &&\n typeof statusText === 'string' &&\n !UNSAFE_FIELD.test(statusText) &&\n headerList(headers) &&\n (url === undefined || typeof url === 'string') &&\n typeof body?.[Symbol.asyncIterator] === 'function' &&\n typeof cancel === 'function'\n );\n}\n\nexport function dropSealedReply(reply: unknown): void {\n const { cancel } = (reply ?? {}) as Partial<RealmTransportResponse>;\n if (typeof cancel !== 'function') return;\n void Promise.resolve()\n .then(() => cancel.call(reply))\n .catch(() => undefined);\n}\n\nfunction failed(reason: unknown): PlaceholderRefused {\n const text = reason instanceof Error ? reason.message : String(reason);\n return new PlaceholderRefused(\n `refused: the request with a sealed placeholder was not completed: ${text}`\n );\n}\n\nclass Stall {\n private readonly idle = new AbortController();\n private readonly ms: number;\n private timer: ReturnType<typeof setTimeout> | undefined;\n readonly signal: AbortSignal;\n\n constructor(signals: AbortSignal[], ms: number) {\n this.ms = ms;\n this.signal = AbortSignal.any([...signals, this.idle.signal]);\n }\n\n arm(): void {\n clearTimeout(this.timer);\n this.timer = setTimeout(() => this.idle.abort('timeout'), this.ms);\n (this.timer as { unref?: () => void }).unref?.();\n }\n\n touch(): void {\n if (this.timer !== undefined) this.arm();\n }\n\n rest(): void {\n clearTimeout(this.timer);\n this.timer = undefined;\n }\n}\n\nasync function until<T>(work: Promise<T>, signal: AbortSignal): Promise<T> {\n const stopped = Promise.withResolvers<never>();\n const stop = () => stopped.reject(signal.reason);\n if (signal.aborted) stop();\n else signal.addEventListener('abort', stop, { once: true });\n try {\n return await Promise.race([work, stopped.promise]);\n } finally {\n signal.removeEventListener('abort', stop);\n }\n}\n\nasync function* ticking(\n stream: AsyncIterable<Uint8Array>,\n stall: Stall\n): AsyncGenerator<Uint8Array> {\n for await (const chunk of stream) {\n stall.touch();\n yield chunk;\n }\n}\n\nfunction sealedRequest(\n request: RealmTransportRequest,\n stamp: SealedCaller,\n stall: Stall\n): SealedFetchRequest {\n const { method, url, headers, body, bodyStream } = request;\n return {\n v: 1,\n caller: structuredClone(stamp),\n method,\n url,\n headers: headers.map(([name, value]) => [name, value] as const),\n redirect: 'manual',\n ...(bodyStream ? { bodyStream: ticking(bodyStream, stall) } : body ? { body } : {}),\n };\n}\n\nfunction guarded(reply: RealmTransportResponse, stall: Stall): RealmTransportResponse {\n let finished = false;\n const cancel = async () => {\n stall.signal.removeEventListener('abort', dropped);\n stall.rest();\n if (finished) return;\n finished = true;\n await reply.cancel().catch(() => undefined);\n };\n const dropped = () => void cancel();\n stall.signal.addEventListener('abort', dropped, { once: true });\n const source = reply.body[Symbol.asyncIterator]();\n const body = (async function* () {\n try {\n for (;;) {\n stall.arm();\n const next = await until(source.next(), stall.signal);\n stall.rest();\n if (next.done) {\n finished = true;\n return;\n }\n if (!(next.value instanceof Uint8Array)) throw failed('a body chunk is not bytes');\n if (next.value.byteLength > 0) yield next.value;\n }\n } finally {\n await cancel();\n }\n })();\n return {\n ...(reply.url !== undefined ? { url: reply.url } : {}),\n status: reply.status,\n statusText: reply.statusText,\n headers: reply.headers,\n body,\n cancel,\n };\n}\n\nexport function sealedFetcher(\n hook: SealedFetchHook,\n stop: AbortSignal,\n idleMs = BODY_IDLE_MS\n): (request: RealmTransportRequest, stamp: SealedCaller) => Promise<RealmTransportResponse> {\n return async (request, stamp) => {\n const stall = new Stall([request.signal, stop], idleMs);\n const { signal } = stall;\n if (signal.aborted) throw failed(signal.reason);\n stall.arm();\n const asked = Promise.resolve().then(() => {\n signal.throwIfAborted();\n return hook(sealedRequest(request, stamp, stall), { signal });\n });\n let reply: unknown;\n try {\n reply = await until(asked, signal);\n } catch (e) {\n void asked.then(dropSealedReply, () => undefined);\n throw failed(e);\n } finally {\n stall.rest();\n }\n if (sealedReplyValid(reply)) return guarded(reply, stall);\n dropSealedReply(reply);\n throw failed('the reply is not a scrubbed response');\n };\n}\n", "export interface TestSyscall {\n pid: number;\n op: string;\n}\n\nexport type TestSyscallHook = (call: TestSyscall) => Promise<void> | void;\n\nconst SYSCALL_HOOK = Symbol.for('slicc-kernel.test.syscall');\n\ntype HookHolder = { [SYSCALL_HOOK]?: TestSyscallHook };\n\nexport function testSyscallHook(): TestSyscallHook | undefined {\n return (globalThis as HookHolder)[SYSCALL_HOOK];\n}\n\nexport function setTestSyscallHook(hook: TestSyscallHook | undefined): void {\n const holder = globalThis as HookHolder;\n if (hook) holder[SYSCALL_HOOK] = hook;\n else delete holder[SYSCALL_HOOK];\n}\n", "export function fresh(bytes: Uint8Array, start = 0, end = bytes.length): Uint8Array {\n return new Uint8Array(bytes.subarray(start, end));\n}\n", "import { fresh } from './bytes.ts';\nimport {\n dropSealedReply,\n type SealedFetchHook,\n type SealedFetchRequest,\n sealedReplyValid,\n} from './kernel/net/sealed-fetch.ts';\nimport type { HeaderList, RealmTransportResponse as Response } from './kernel/net/transport.ts';\nimport type { SealedHook, SealedRequest } from './kernel/sealed.ts';\n\nexport interface SealedPort {\n postMessage(message: unknown, transfer?: Transferable[]): void;\n}\n\nexport interface SealedAsk {\n id: number;\n req: SealedRequest;\n}\n\nexport interface SealedReply {\n id: number;\n reply?: object;\n error?: string;\n}\n\nexport interface SealedAbort {\n id: number;\n reason: unknown;\n}\n\ntype WireRequest = Omit<SealedFetchRequest, 'bodyStream'> & { streamed?: true };\n\nexport interface SealedFetchAsk {\n req: WireRequest;\n port: MessagePort;\n}\n\ntype AskerMessage =\n | { t: 'pull' }\n | { t: 'stop' }\n | {\n t: 'head';\n status: number;\n statusText: string;\n headers: HeaderList;\n url?: string;\n }\n | { t: 'chunk'; bytes: Uint8Array }\n | { t: 'end' }\n | { t: 'error'; message: string };\n\ntype AnswererMessage =\n | { t: 'read' }\n | { t: 'cancel'; reason: string }\n | { t: 'chunk'; bytes: Uint8Array }\n | { t: 'end' }\n | { t: 'error'; message: string };\n\nfunction textOf(err: unknown): string {\n return err instanceof Error ? err.message : String(err);\n}\n\nfunction sendBytes(port: MessagePort, bytes: Uint8Array): void {\n const copy = fresh(bytes);\n port.postMessage({ t: 'chunk', bytes: copy }, [copy.buffer as ArrayBuffer]);\n}\n\nfunction askFetch(\n port: SealedPort,\n req: SealedFetchRequest,\n signal: AbortSignal\n): Promise<Response> {\n signal.throwIfAborted();\n const { bodyStream, ...wire } = req;\n const { port1: near, port2: far } = new MessageChannel();\n const upload = bodyStream?.[Symbol.asyncIterator]();\n const head = Promise.withResolvers<Response>();\n let reading: PromiseWithResolvers<IteratorResult<Uint8Array>> | undefined;\n let ended = false;\n\n const end = (failure: Error) => {\n if (ended) return;\n ended = true;\n signal.removeEventListener('abort', abort);\n near.close();\n void upload?.return?.().catch(() => undefined);\n head.reject(failure);\n reading?.reject(failure);\n reading = undefined;\n };\n const abort = () => {\n near.postMessage({ t: 'cancel', reason: String(signal.reason) } satisfies AnswererMessage);\n end(new Error(String(signal.reason)));\n };\n const pull = async () => {\n try {\n const next = await (upload as AsyncIterator<Uint8Array>).next();\n if (ended) return;\n if (next.done) near.postMessage({ t: 'end' } satisfies AnswererMessage);\n else sendBytes(near, next.value);\n } catch (err) {\n if (!ended) near.postMessage({ t: 'error', message: textOf(err) });\n }\n };\n const respond = (message: Extract<AskerMessage, { t: 'head' }>) => {\n const { status, statusText, headers, url } = message;\n const body: AsyncIterable<Uint8Array> = {\n [Symbol.asyncIterator]: () => ({\n next: () => {\n if (ended) return Promise.resolve({ value: undefined, done: true });\n reading = Promise.withResolvers();\n near.postMessage({ t: 'read' } satisfies AnswererMessage);\n return reading.promise;\n },\n return: async () => {\n await cancel();\n return { value: undefined, done: true };\n },\n }),\n };\n const cancel = async () => {\n if (ended) return;\n near.postMessage({ t: 'cancel', reason: 'cancelled' } satisfies AnswererMessage);\n end(new Error('the request was cancelled'));\n };\n head.resolve({\n ...(url !== undefined ? { url } : {}),\n status,\n statusText,\n headers,\n body,\n cancel,\n });\n };\n near.addEventListener('message', ({ data }: MessageEvent<AskerMessage>) => {\n if (data.t === 'pull') void pull();\n else if (data.t === 'stop') void upload?.return?.().catch(() => undefined);\n else if (data.t === 'head') respond(data);\n else if (data.t === 'chunk') {\n reading?.resolve({ value: data.bytes, done: false });\n reading = undefined;\n } else if (data.t === 'end') {\n reading?.resolve({ value: undefined, done: true });\n reading = undefined;\n end(new Error('the response ended'));\n } else end(new Error(data.message));\n });\n near.addEventListener('close', () => end(new Error('the sealed fetch relay closed')));\n near.start();\n signal.addEventListener('abort', abort, { once: true });\n const ask: SealedFetchAsk = {\n req: { ...wire, ...(upload ? { streamed: true } : {}) },\n port: far,\n };\n port.postMessage({ sealedFetch: ask }, [far]);\n return head.promise;\n}\n\ninterface FetchAnswer {\n close(reason: unknown): void;\n}\n\nfunction uploadOf(far: MessagePort): {\n stream: AsyncIterable<Uint8Array>;\n answer(message: Extract<AnswererMessage, { t: 'chunk' | 'end' | 'error' }>): void;\n fail(reason: Error): void;\n} {\n let waiting: PromiseWithResolvers<IteratorResult<Uint8Array>> | undefined;\n let failure: Error | undefined;\n const next = () => {\n if (failure) return Promise.reject(failure);\n waiting = Promise.withResolvers();\n far.postMessage({ t: 'pull' } satisfies AskerMessage);\n return waiting.promise;\n };\n return {\n stream: {\n [Symbol.asyncIterator]: () => ({\n next,\n return: async () => {\n far.postMessage({ t: 'stop' } satisfies AskerMessage);\n return { value: undefined, done: true };\n },\n }),\n },\n answer(message) {\n if (message.t === 'chunk') waiting?.resolve({ value: message.bytes, done: false });\n else if (message.t === 'end') waiting?.resolve({ value: undefined, done: true });\n else {\n failure = new Error(message.message);\n waiting?.reject(failure);\n }\n waiting = undefined;\n },\n fail(reason) {\n failure = reason;\n waiting?.reject(reason);\n waiting = undefined;\n },\n };\n}\n\nfunction answerFetch(\n hook: SealedFetchHook | undefined,\n { req, port: far }: SealedFetchAsk,\n live: Set<FetchAnswer>\n): void {\n const control = new AbortController();\n const { streamed, ...fields } = req;\n const upload = uploadOf(far);\n let source: AsyncIterator<Uint8Array> | undefined;\n let reply: Response | undefined;\n let closed = false;\n\n const settle = () => {\n closed = true;\n live.delete(answer);\n upload.fail(new Error('the request ended'));\n };\n const answer: FetchAnswer = {\n close(reason) {\n if (closed) return;\n settle();\n control.abort(reason);\n dropSealedReply(reply);\n far.close();\n },\n };\n const finish = (message: AskerMessage) => {\n if (closed) return;\n settle();\n far.postMessage(message);\n };\n const failWith = (err: unknown) => {\n dropSealedReply(reply);\n finish({ t: 'error', message: textOf(err) });\n };\n const read = async () => {\n try {\n const next = await (source as AsyncIterator<Uint8Array>).next();\n if (closed) return;\n if (next.done) finish({ t: 'end' });\n else if (next.value instanceof Uint8Array) sendBytes(far, next.value);\n else failWith('a body chunk is not bytes');\n } catch (err) {\n failWith(err);\n }\n };\n const ask = async () => {\n try {\n if (!hook) throw new Error('no vault is connected');\n const request: SealedFetchRequest = {\n ...fields,\n ...(streamed ? { bodyStream: upload.stream } : {}),\n };\n const answered: unknown = await hook(request, { signal: control.signal });\n if (!sealedReplyValid(answered)) {\n dropSealedReply(answered);\n throw new Error('the reply is not a scrubbed response');\n }\n if (closed) return dropSealedReply(answered);\n reply = answered;\n source = answered.body[Symbol.asyncIterator]();\n const { status, statusText, headers, url } = answered;\n far.postMessage({\n t: 'head',\n status,\n statusText,\n headers,\n ...(url !== undefined ? { url } : {}),\n } satisfies AskerMessage);\n } catch (err) {\n failWith(err);\n }\n };\n far.addEventListener('message', ({ data }: MessageEvent<AnswererMessage>) => {\n if (data.t === 'read') void read();\n else if (data.t === 'cancel') answer.close(data.reason);\n else upload.answer(data);\n });\n far.addEventListener('close', () => answer.close('withdrawn'));\n far.start();\n live.add(answer);\n void ask();\n}\n\nexport function sealedAsker(port: SealedPort): {\n hook: SealedHook;\n fetch: SealedFetchHook;\n answer(reply: SealedReply): void;\n} {\n const asks = new Map<number, PromiseWithResolvers<object>>();\n let next = 0;\n const hook: SealedHook = (req, { signal }) => {\n const id = ++next;\n const waiting = Promise.withResolvers<object>();\n asks.set(id, waiting);\n const abort = () => {\n if (!asks.delete(id)) return;\n port.postMessage({ sealedAbort: { id, reason: signal.reason } });\n waiting.reject(new Error(String(signal.reason)));\n };\n signal.addEventListener('abort', abort, { once: true });\n port.postMessage({ sealedAsk: { id, req } });\n return waiting.promise.finally(() => signal.removeEventListener('abort', abort));\n };\n const answer = ({ id, reply, error }: SealedReply) => {\n const waiting = asks.get(id);\n if (!waiting) return;\n asks.delete(id);\n if (reply) waiting.resolve(reply);\n else waiting.reject(new Error(error ?? 'no reply'));\n };\n return { hook, fetch: (req, { signal }) => askFetch(port, req, signal), answer };\n}\n\nexport interface SealedAnswerer {\n handle(data: unknown): boolean;\n close(): void;\n}\n\nexport function sealedAnswerer(\n port: SealedPort,\n hook: SealedHook | undefined,\n fetchHook?: SealedFetchHook\n): SealedAnswerer {\n const asked = new Map<number, AbortController>();\n const fetches = new Set<FetchAnswer>();\n const ask = async ({ id, req }: SealedAsk): Promise<void> => {\n const control = new AbortController();\n asked.set(id, control);\n try {\n if (!hook) throw new Error('no vault is connected');\n const reply = await hook(req, { signal: control.signal });\n port.postMessage({ sealedReply: { id, reply } });\n } catch (err) {\n const error = err instanceof Error ? err.message : String(err);\n port.postMessage({ sealedReply: { id, error } });\n } finally {\n asked.delete(id);\n }\n };\n const abort = ({ id, reason }: SealedAbort): void => {\n asked.get(id)?.abort(reason);\n asked.delete(id);\n };\n return {\n handle(data) {\n const message = data as {\n sealedAsk?: SealedAsk;\n sealedAbort?: SealedAbort;\n sealedFetch?: SealedFetchAsk;\n } | null;\n if (message?.sealedAsk) void ask(message.sealedAsk);\n else if (message?.sealedAbort) abort(message.sealedAbort);\n else if (message?.sealedFetch) answerFetch(fetchHook, message.sealedFetch, fetches);\n else return false;\n return true;\n },\n close() {\n for (const control of asked.values()) control.abort('withdrawn');\n asked.clear();\n for (const answer of [...fetches]) answer.close('withdrawn');\n },\n };\n}\n", "import type { RouteTable } from './kernel/net/routes.ts';\nimport {\n answerOf,\n type NetworkUplink,\n type ResolveAnswer,\n type ResolveFamily,\n type UplinkConn,\n type UplinkDatagram,\n type UplinkDial,\n type UplinkMessage,\n type UplinkUdp,\n type UplinkUdpOpen,\n type UplinkUnreachable,\n} from './kernel/net/uplink.ts';\n\nexport { type CronClock, type FakeCronClock, fakeCronClock } from './cron/clock.ts';\nexport { placeholderFloor } from './kernel/net/placeholder-floor.ts';\nexport { sealedFetcher } from './kernel/net/sealed-fetch.ts';\nexport {\n setTestSyscallHook,\n type TestSyscall,\n type TestSyscallHook,\n} from './kernel/test-hooks.ts';\nexport { sealedAnswerer, sealedAsker } from './sealed-relay.ts';\nexport type {\n NetworkUplink,\n ResolveAnswer,\n ResolveFamily,\n RouteTable,\n UplinkConn,\n UplinkDatagram,\n UplinkDial,\n UplinkMessage,\n UplinkUdp,\n UplinkUdpOpen,\n UplinkUnreachable,\n};\n\nexport type FakeDatagramPeer = (\n bytes: Uint8Array\n) => Uint8Array | readonly Uint8Array[] | { error: string } | undefined;\n\nexport interface FakePeerSocket {\n read(): Promise<Uint8Array | null>;\n write(bytes: Uint8Array): void;\n end(): void;\n reset(code?: string): void;\n readonly buffered: number;\n drained(): Promise<void>;\n readonly closed: Promise<void>;\n}\n\nexport type FakePeer = ((socket: FakePeerSocket) => void) | { error: string } | { hang: true };\n\nexport interface FakeUplinkOptions {\n names?: Readonly<Record<string, string[] | ResolveAnswer>>;\n routes?: RouteTable;\n ipv6?: boolean;\n exit?: string;\n peers?: Readonly<Record<string, FakePeer>>;\n datagrams?: Readonly<Record<string, FakeDatagramPeer>>;\n address?: string;\n nameserver?: string;\n}\n\nexport interface FakeUplink extends NetworkUplink {\n readonly asked: Array<{ name: string; family: ResolveFamily }>;\n readonly dialled: Array<{ host: string; port: number }>;\n readonly sent: Array<{ host: string; port: number; bytes: Uint8Array }>;\n udp(req: UplinkUdpOpen): Promise<UplinkUdp>;\n}\n\nconst failure = (code: string, message: string) => Object.assign(new Error(message), { code });\n\nclass Stream {\n private readonly queue: Array<{\n bytes: Uint8Array;\n taken: () => void;\n lost: (error: Error) => void;\n }> = [];\n private ended = false;\n private broken: Error | undefined;\n private waiters: Array<() => void> = [];\n size = 0;\n\n private wake(): void {\n const waiters = this.waiters;\n this.waiters = [];\n for (const wake of waiters) wake();\n }\n\n push(bytes: Uint8Array): Promise<void> {\n if (this.broken) return Promise.reject(this.broken);\n if (this.ended) return Promise.reject(failure('EPIPE', 'the stream is closed'));\n return new Promise((taken, lost) => {\n this.queue.push({ bytes: bytes.slice(), taken, lost });\n this.size += bytes.length;\n this.wake();\n });\n }\n\n end(): void {\n this.ended = true;\n this.wake();\n }\n\n fail(error: Error): void {\n this.broken = error;\n for (const pending of this.queue.splice(0)) pending.lost(error);\n this.size = 0;\n this.wake();\n }\n\n async read(): Promise<Uint8Array | null> {\n while (this.queue.length === 0 && !this.ended && !this.broken) {\n await new Promise<void>((resolve) => this.waiters.push(resolve));\n }\n if (this.broken) throw this.broken;\n const next = this.queue.shift();\n if (!next) return null;\n this.size -= next.bytes.length;\n next.taken();\n this.wake();\n return next.bytes;\n }\n\n async drained(): Promise<void> {\n while (this.size > 0) await new Promise<void>((resolve) => this.waiters.push(resolve));\n }\n}\n\nfunction named(host: string, port: number): string {\n return `${host.includes(':') ? `[${host}]` : host}:${port}`;\n}\n\nclass Inbox {\n private readonly queue: UplinkMessage[] = [];\n private ended = false;\n private wake: (() => void) | undefined;\n\n push(message: UplinkMessage): void {\n if (this.ended) return;\n this.queue.push(message);\n this.wake?.();\n }\n\n end(): void {\n this.ended = true;\n this.wake?.();\n }\n\n async *[Symbol.asyncIterator](): AsyncGenerator<UplinkMessage> {\n for (;;) {\n const next = this.queue.shift();\n if (next) yield next;\n else if (this.ended) return;\n else await new Promise<void>((resolve) => (this.wake = resolve));\n }\n }\n}\n\nfunction fakeUdp(\n options: FakeUplinkOptions,\n sent: FakeUplink['sent'],\n local: string\n): Promise<UplinkUdp> {\n const inbox = new Inbox();\n return Promise.resolve({\n localAddr: local,\n messages: inbox,\n send: async (bytes, host, port) => {\n sent.push({ host, port, bytes: bytes.slice() });\n const answer = options.datagrams?.[named(host, port)]?.(bytes.slice());\n if (!answer) return;\n if ('error' in answer) {\n inbox.push({ error: answer.error, host, port });\n return;\n }\n const replies = answer instanceof Uint8Array ? [answer] : answer;\n for (const reply of replies) inbox.push({ bytes: reply.slice(), host, port });\n },\n close: () => inbox.end(),\n });\n}\n\nfunction hang(signal: AbortSignal): Promise<never> {\n return new Promise((_, reject) => {\n signal.addEventListener('abort', () => reject(failure('ECONNABORTED', 'dial aborted')), {\n once: true,\n });\n });\n}\n\nexport function fakeUplink(options: FakeUplinkOptions = {}): FakeUplink {\n const asked: FakeUplink['asked'] = [];\n const dialled: FakeUplink['dialled'] = [];\n const sent: FakeUplink['sent'] = [];\n let nextPort = 40000;\n return {\n traits: { tcp: true, udp: options.datagrams !== undefined, ipv6: options.ipv6 === true },\n ...(options.routes ? { routes: options.routes } : {}),\n ...(options.nameserver ? { nameserver: options.nameserver } : {}),\n asked,\n dialled,\n sent,\n udp: () => fakeUdp(options, sent, named(options.address ?? '100.100.100.100', nextPort++)),\n resolve: async (name, family) => {\n asked.push({ name, family });\n return answerOf(options.names?.[name] ?? []);\n },\n dial: async ({ host, port, signal }) => {\n dialled.push({ host, port });\n const peer = options.peers?.[named(host, port)];\n if (!peer) throw failure('ECONNREFUSED', `nothing listens on ${named(host, port)}`);\n if ('error' in peer) throw failure(peer.error, `${named(host, port)}: ${peer.error}`);\n if ('hang' in peer) return hang(signal);\n const up = new Stream();\n const down = new Stream();\n const closed = Promise.withResolvers<void>();\n peer({\n read: () => up.read(),\n write: (bytes) => void down.push(bytes).catch(() => undefined),\n end: () => down.end(),\n reset: (code = 'ECONNRESET') => {\n const error = failure(code, `the peer reset the connection (${code})`);\n up.fail(error);\n down.fail(error);\n },\n get buffered() {\n return down.size;\n },\n drained: () => down.drained(),\n closed: closed.promise,\n });\n return {\n localAddr: named(options.address ?? '100.100.100.100', nextPort++),\n remoteAddr: named(host, port),\n ...(options.exit === undefined ? {} : { exit: options.exit }),\n read: () => down.read(),\n write: async (bytes) => {\n await up.push(bytes);\n return bytes.length;\n },\n closeWrite: () => up.end(),\n close: () => {\n up.end();\n down.end();\n closed.resolve();\n },\n };\n },\n };\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["export const HOST_LOOPBACK = 'host.slicc.internal';\n\nexport const HOST_LOOPBACK_ADDRESS = [10, 0, 2, 2] as const;\n\nexport const PAGE_LOOPBACK = 'kernel.localhost';\n\nexport const PAGE_LOOPBACK_URL = `http://{port}.${PAGE_LOOPBACK}`;\n\nexport function toHostLoopback(href: string): string {\n const url = new URL(href);\n if (url.hostname.replace(/\\.$/, '').toLowerCase() !== HOST_LOOPBACK) return href;\n url.hostname = '127.0.0.1';\n return url.href;\n}\n\nconst LOOPBACK_V4 = /^127\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}$/;\nconst LOOPBACK_V6 = new Set(['::1', '::', '0:0:0:0:0:0:0:1']);\nconst MAPPED_V4 = /^::ffff:7f[0-9a-f]{2}:[0-9a-f]{1,4}$/;\nconst KERNEL_PORT = /^(\\d{1,5})\\.kernel\\.localhost$/;\nconst SCHEMES: Readonly<Record<string, number>> = {\n 'http:': 80,\n 'ws:': 80,\n 'https:': 443,\n 'wss:': 443,\n};\n\nexport function isKernelLoopbackHost(hostname: string): boolean {\n const host = hostname\n .replace(/^\\[(.*)\\]$/, '$1')\n .replace(/\\.$/, '')\n .toLowerCase();\n return (\n host === 'localhost' ||\n host.endsWith('.localhost') ||\n host === '0.0.0.0' ||\n LOOPBACK_V4.test(host) ||\n LOOPBACK_V6.has(host) ||\n MAPPED_V4.test(host)\n );\n}\n\nexport function kernelLoopbackPort(href: string): number | undefined {\n let url: URL;\n try {\n url = new URL(href);\n } catch {\n return undefined;\n }\n const fallback = SCHEMES[url.protocol];\n if (fallback === undefined || !isKernelLoopbackHost(url.hostname)) return undefined;\n const named = KERNEL_PORT.exec(url.hostname.replace(/\\.$/, '').toLowerCase())?.[1];\n const port = Number(named ?? (url.port || fallback));\n return port >= 1 && port <= 65535 ? port : undefined;\n}\n\nexport const DEFAULT_HOSTNAME = 'slicc';\n\nexport const HOSTNAME_ADDRESS = '127.0.1.1';\n\nexport const LIBC_HOSTNAMES: readonly string[] = ['emscripten', 'wasmer.sh'];\n\nconst LABEL = /^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$/i;\n\nfunction reserved(name: string): boolean {\n const lower = name.toLowerCase();\n return (\n lower === 'localhost' ||\n lower.endsWith('.localhost') ||\n lower === HOST_LOOPBACK ||\n lower === 'wasmer.sh' ||\n /^\\d+(\\.\\d+){3}$/.test(lower)\n );\n}\n\nexport function isHostname(name: unknown): name is string {\n if (typeof name !== 'string' || name.length > 253 || reserved(name)) return false;\n return name.split('.').every((l) => LABEL.test(l));\n}\n\nexport function hostnameOf(env: Readonly<Record<string, string>>): string {\n return isHostname(env.HOSTNAME) ? env.HOSTNAME : DEFAULT_HOSTNAME;\n}\n\nexport function initHostname(init: {\n hostname?: string | undefined;\n env: Readonly<Record<string, string>>;\n}): string {\n return isHostname(init.hostname) ? init.hostname : hostnameOf(init.env);\n}\n\nexport function ownNames(hostname: string): string[] {\n return [...new Set([hostname.toLowerCase(), ...LIBC_HOSTNAMES])];\n}\n\nexport function hostsFile(hostname: string = DEFAULT_HOSTNAME): string {\n return [\n '127.0.0.1 localhost localhost.localdomain',\n '::1 localhost ip6-localhost',\n `${HOSTNAME_ADDRESS} ${ownNames(hostname).join(' ')}`,\n `${HOST_LOOPBACK_ADDRESS.join('.')} ${HOST_LOOPBACK}`,\n '',\n ].join('\\n');\n}\n", "import { HOST_LOOPBACK, HOST_LOOPBACK_ADDRESS } from './loopback-names.ts';\n\nexport interface RouteTable {\n prefixes: readonly string[];\n exit: boolean;\n}\n\nexport type Destination = 'loopback' | 'host' | 'reserved' | 'uplink' | 'unreachable';\n\ninterface Prefix {\n v6: boolean;\n bits: bigint;\n length: number;\n}\n\nconst HOST_ADDRESS = HOST_LOOPBACK_ADDRESS.join('.');\n\nexport function ipv4Bytes(text: string): number[] | undefined {\n const parts = text.split('.');\n if (parts.length !== 4 || !parts.every((p) => /^\\d{1,3}$/.test(p))) return undefined;\n const bytes = parts.map(Number);\n return bytes.every((b) => b <= 255) ? bytes : undefined;\n}\n\nexport function ipv6Groups(text: string): number[] | undefined {\n if (!text.includes(':')) return undefined;\n let canonical: string;\n try {\n canonical = new URL(`http://[${text}]/`).hostname.slice(1, -1);\n } catch {\n return undefined;\n }\n const [head, tail] = canonical.split('::');\n const part = (s: string | undefined) =>\n s ? s.split(':').map((h) => Number.parseInt(h, 16)) : [];\n const front = part(head);\n const back = part(tail);\n return tail === undefined\n ? front\n : [...front, ...new Array<number>(8 - front.length - back.length).fill(0), ...back];\n}\n\nfunction toBits(values: number[], width: number): bigint {\n return values.reduce((acc, v) => (acc << BigInt(width)) | BigInt(v), 0n);\n}\n\nfunction addressBits(host: string): { v6: boolean; bits: bigint } | undefined {\n const v4 = ipv4Bytes(host);\n if (v4) return { v6: false, bits: toBits(v4, 8) };\n const v6 = ipv6Groups(host);\n return v6 ? { v6: true, bits: toBits(v6, 16) } : undefined;\n}\n\nfunction parsePrefix(text: string): Prefix | undefined {\n const parts = text.trim().split('/');\n if (parts.length > 2) return undefined;\n const [address = '', size] = parts;\n const parsed = addressBits(address);\n if (!parsed) return undefined;\n const max = parsed.v6 ? 128 : 32;\n const length = size === undefined ? max : /^\\d{1,3}$/.test(size) ? Number(size) : -1;\n if (length < 0 || length > max) return undefined;\n return { ...parsed, length };\n}\n\nfunction within(prefix: Prefix, addr: { v6: boolean; bits: bigint }): boolean {\n if (prefix.v6 !== addr.v6) return false;\n const shift = BigInt((prefix.v6 ? 128 : 32) - prefix.length);\n return addr.bits >> shift === prefix.bits >> shift;\n}\n\nconst RESERVED = [\n '0.0.0.0/8',\n '127.0.0.0/8',\n '169.254.0.0/16',\n '224.0.0.0/4',\n '240.0.0.0/4',\n '::/96',\n '::ffff:0:0/96',\n 'fe80::/10',\n 'ff00::/8',\n].map((p) => parsePrefix(p) as Prefix);\n\nexport class Routes {\n private table: Prefix[] = [];\n private exit = false;\n readonly ipv6: boolean;\n\n constructor(ipv6 = false) {\n this.ipv6 = ipv6;\n }\n\n set(table: RouteTable): void {\n const parsed = (table.prefixes ?? []).map(parsePrefix);\n const bad = (table.prefixes ?? []).find((_, i) => !parsed[i]);\n if (bad !== undefined) throw new Error(`not an address prefix: ${bad}`);\n this.table = parsed as Prefix[];\n this.exit = table.exit === true;\n }\n\n classify(host: string): Destination {\n const name = host.toLowerCase().replace(/\\.$/, '');\n if (name === 'localhost' || name.endsWith('.localhost') || name === '0.0.0.0') {\n return 'loopback';\n }\n if (name === HOST_LOOPBACK || name === HOST_ADDRESS) return 'host';\n const addr = addressBits(name);\n if (!addr) return 'unreachable';\n if (addr.v6 && addr.bits === 1n) return 'loopback';\n if (!addr.v6 && addr.bits >> 24n === 127n) return 'loopback';\n if (RESERVED.some((p) => within(p, addr))) return 'reserved';\n if (addr.v6 && !this.ipv6) return 'unreachable';\n if (this.exit || this.table.some((p) => within(p, addr))) return 'uplink';\n return 'unreachable';\n }\n}\n", "import { Routes, type RouteTable } from './routes.ts';\n\nexport interface UplinkTraits {\n tcp: true;\n udp: boolean;\n ipv6: boolean;\n}\n\nexport type ResolveFamily = 0 | 4 | 6;\n\nexport interface ResolveAnswer {\n addresses: string[];\n ttl?: number;\n}\n\nexport interface UplinkConn {\n readonly localAddr: string;\n readonly remoteAddr: string;\n readonly exit?: string;\n read(): Promise<Uint8Array | null>;\n write(bytes: Uint8Array): Promise<number>;\n closeWrite(): void;\n close(): void;\n}\n\nexport interface UplinkDial {\n network: 'tcp';\n host: string;\n port: number;\n signal: AbortSignal;\n}\n\nexport interface UplinkDatagram {\n bytes: Uint8Array;\n host: string;\n port: number;\n}\n\nexport interface UplinkUnreachable {\n error: string;\n host: string;\n port: number;\n}\n\nexport type UplinkMessage = UplinkDatagram | UplinkUnreachable;\n\nexport interface UplinkUdpOpen {\n family: 4 | 6;\n signal: AbortSignal;\n}\n\nexport interface UplinkUdp {\n readonly localAddr: string;\n send(bytes: Uint8Array, host: string, port: number): Promise<void>;\n readonly messages: AsyncIterable<UplinkMessage>;\n close(): void;\n}\n\nexport interface NetworkUplink {\n readonly traits: UplinkTraits;\n readonly routes?: RouteTable;\n readonly nameserver?: string;\n resolve(\n name: string,\n family: ResolveFamily,\n signal?: AbortSignal\n ): Promise<string[] | ResolveAnswer>;\n dial(req: UplinkDial): Promise<UplinkConn>;\n udp?(req: UplinkUdpOpen): Promise<UplinkUdp>;\n}\n\nexport function carriesUdp(uplink: NetworkUplink): boolean {\n return uplink.traits.udp === true && typeof uplink.udp === 'function';\n}\n\nexport type UplinkCall =\n | { uplink: 'resolve'; uid: number; name: string; family: ResolveFamily }\n | { uplink: 'dial'; uid: number; host: string; port: number }\n | { uplink: 'cancel'; uid: number }\n | { uplink: 'read'; uid: number; cid: number }\n | { uplink: 'write'; uid: number; cid: number; bytes: Uint8Array }\n | { uplink: 'close-write'; cid: number }\n | { uplink: 'close'; cid: number }\n | { uplink: 'udp-open'; uid: number; family: 4 | 6 }\n | { uplink: 'udp-send'; uid: number; cid: number; bytes: Uint8Array; host: string; port: number }\n | { uplink: 'udp-recv'; uid: number; cid: number }\n | { uplink: 'udp-close'; cid: number };\n\nexport type UplinkReply =\n | { uplink: 'resolved'; uid: number; addresses: string[]; ttl?: number }\n | { uplink: 'dialled'; uid: number; cid: number; localAddr: string; remoteAddr: string }\n | { uplink: 'data'; uid: number; bytes: Uint8Array | null }\n | { uplink: 'written'; uid: number; n: number }\n | { uplink: 'udp-opened'; uid: number; cid: number; localAddr: string }\n | { uplink: 'udp-sent'; uid: number }\n | { uplink: 'udp-message'; uid: number; message: UplinkMessage | null }\n | { uplink: 'error'; uid: number; message: string; code?: string };\n\nexport interface UplinkPeer {\n postMessage(message: UplinkReply, transfer?: Transferable[]): void;\n}\n\nexport interface UplinkPort {\n postMessage(message: UplinkCall, transfer?: Transferable[]): void;\n}\n\nexport interface UplinkServer {\n answer(call: UplinkCall): void;\n close(): void;\n}\n\nexport function answerOf(result: string[] | ResolveAnswer): ResolveAnswer {\n const answer = Array.isArray(result) ? { addresses: result } : result;\n const addresses = Array.isArray(answer?.addresses)\n ? answer.addresses.filter((a): a is string => typeof a === 'string')\n : [];\n return {\n addresses,\n ...(typeof answer?.ttl === 'number' && answer.ttl >= 0 ? { ttl: answer.ttl } : {}),\n };\n}\n\nfunction failure(uid: number, e: unknown): UplinkReply {\n const code = (e as { code?: unknown } | null)?.code;\n return {\n uplink: 'error',\n uid,\n message: e instanceof Error ? e.message : String(e),\n ...(typeof code === 'string' ? { code } : {}),\n };\n}\n\nconst NEVER = new Routes(true);\n\nexport function serveUplink(peer: UplinkPeer, uplink: NetworkUplink): UplinkServer {\n const conns = new Map<number, UplinkConn>();\n const pending = new Map<number, AbortController>();\n let nextCid = 0;\n let closed = false;\n const run = (uid: number, work: (signal: AbortSignal) => Promise<UplinkReply | undefined>) => {\n const abort = new AbortController();\n pending.set(uid, abort);\n void work(abort.signal)\n .then(\n (reply) => reply && peer.postMessage(reply, transferOf(reply)),\n (e: unknown) => peer.postMessage(failure(uid, e))\n )\n .finally(() => pending.delete(uid));\n };\n const conn = (cid: number): UplinkConn => {\n const found = conns.get(cid);\n if (!found) throw Object.assign(new Error('no such uplink connection'), { code: 'EBADF' });\n return found;\n };\n const dial = async (call: Extract<UplinkCall, { uplink: 'dial' }>, signal: AbortSignal) => {\n refuseLocal(call.host);\n const { host, port } = call;\n const opened = await uplink.dial({ network: 'tcp', host, port, signal });\n if (signal.aborted || closed) {\n opened.close();\n return undefined;\n }\n const cid = ++nextCid;\n conns.set(cid, opened);\n const { localAddr, remoteAddr } = opened;\n return { uplink: 'dialled' as const, uid: call.uid, cid, localAddr, remoteAddr };\n };\n const drop = (cid: number) => {\n const found = conns.get(cid);\n conns.delete(cid);\n found?.close();\n };\n const udp = new UdpServer(uplink, () => closed);\n return {\n answer(call) {\n switch (call.uplink) {\n case 'resolve':\n return run(call.uid, async (signal) => ({\n uplink: 'resolved',\n uid: call.uid,\n ...answerOf(await uplink.resolve(call.name, call.family, signal)),\n }));\n case 'dial':\n return run(call.uid, (signal) => dial(call, signal));\n case 'cancel':\n return pending.get(call.uid)?.abort();\n case 'read':\n return run(call.uid, async () => ({\n uplink: 'data',\n uid: call.uid,\n bytes: (await conn(call.cid).read())?.slice() ?? null,\n }));\n case 'write':\n return run(call.uid, async () => ({\n uplink: 'written',\n uid: call.uid,\n n: await conn(call.cid).write(call.bytes),\n }));\n case 'close-write':\n return conns.get(call.cid)?.closeWrite();\n case 'close':\n return drop(call.cid);\n case 'udp-close':\n return udp.drop(call.cid);\n default:\n return run(call.uid, (signal) => udp.answer(call, signal));\n }\n },\n close() {\n closed = true;\n for (const abort of pending.values()) abort.abort();\n for (const cid of [...conns.keys()]) drop(cid);\n udp.close();\n },\n };\n}\n\nfunction copied(message: UplinkMessage): UplinkMessage {\n if ('bytes' in message) return { ...message, bytes: message.bytes.slice() };\n return { error: String(message.error), host: message.host, port: message.port };\n}\n\nfunction refuseLocal(host: string): void {\n const kind = NEVER.classify(host);\n if (kind === 'loopback' || kind === 'host' || kind === 'reserved') {\n throw Object.assign(new Error(`the uplink does not carry ${host}`), { code: 'ENETUNREACH' });\n }\n}\n\ntype UdpCall = Extract<UplinkCall, { uplink: 'udp-open' | 'udp-send' | 'udp-recv' }>;\n\nclass UdpServer {\n private readonly sockets = new Map<\n number,\n { udp: UplinkUdp; messages: AsyncIterator<UplinkMessage> }\n >();\n private next = 0;\n private readonly uplink: NetworkUplink;\n private readonly closed: () => boolean;\n\n constructor(uplink: NetworkUplink, closed: () => boolean) {\n this.uplink = uplink;\n this.closed = closed;\n }\n\n private socket(cid: number) {\n const found = this.sockets.get(cid);\n if (!found) throw Object.assign(new Error('no such uplink socket'), { code: 'EBADF' });\n return found;\n }\n\n async answer(call: UdpCall, signal: AbortSignal): Promise<UplinkReply | undefined> {\n if (call.uplink === 'udp-open') {\n if (!this.uplink.udp || this.uplink.traits.udp !== true) {\n throw Object.assign(new Error('the uplink carries no datagrams'), { code: 'ENETUNREACH' });\n }\n const opened = await this.uplink.udp({ family: call.family, signal });\n if (signal.aborted || this.closed()) {\n opened.close();\n return undefined;\n }\n const cid = ++this.next;\n this.sockets.set(cid, { udp: opened, messages: opened.messages[Symbol.asyncIterator]() });\n return { uplink: 'udp-opened', uid: call.uid, cid, localAddr: opened.localAddr };\n }\n if (call.uplink === 'udp-send') {\n refuseLocal(call.host);\n await this.socket(call.cid).udp.send(call.bytes, call.host, call.port);\n return { uplink: 'udp-sent', uid: call.uid };\n }\n const next = await this.socket(call.cid).messages.next();\n const message = next.done ? null : copied(next.value);\n return { uplink: 'udp-message', uid: call.uid, message };\n }\n\n drop(cid: number): void {\n const found = this.sockets.get(cid);\n this.sockets.delete(cid);\n found?.udp.close();\n }\n\n close(): void {\n for (const cid of [...this.sockets.keys()]) this.drop(cid);\n }\n}\n\nfunction transferOf(reply: UplinkReply): Transferable[] | undefined {\n if (reply.uplink === 'udp-message' && reply.message && 'bytes' in reply.message) {\n return [reply.message.bytes.buffer as ArrayBuffer];\n }\n if (reply.uplink !== 'data' || !reply.bytes) return undefined;\n return [reply.bytes.buffer as ArrayBuffer];\n}\n\ntype Answer = Exclude<UplinkReply, { uplink: 'error' }>;\n\nexport class RemoteUplink implements NetworkUplink {\n readonly traits: UplinkTraits;\n readonly routes: RouteTable | undefined;\n readonly nameserver: string | undefined;\n private readonly port: UplinkPort;\n private readonly waiting = new Map<number, PromiseWithResolvers<Answer>>();\n private nextId = 0;\n\n constructor(port: UplinkPort, traits: UplinkTraits, routes?: RouteTable, nameserver?: string) {\n this.port = port;\n this.traits = traits;\n this.routes = routes;\n this.nameserver = nameserver;\n }\n\n receive(reply: UplinkReply): void {\n const waiter = this.waiting.get(reply.uid);\n if (!waiter) return;\n this.waiting.delete(reply.uid);\n if (reply.uplink === 'error') {\n waiter.reject(Object.assign(new Error(reply.message), { code: reply.code }));\n } else waiter.resolve(reply);\n }\n\n private ask<T extends Answer>(\n call: Extract<UplinkCall, { uid: number }>,\n signal?: AbortSignal,\n transfer?: Transferable[]\n ): Promise<T> {\n const waiter = Promise.withResolvers<Answer>();\n this.waiting.set(call.uid, waiter);\n const abort = () => {\n this.waiting.delete(call.uid);\n this.port.postMessage({ uplink: 'cancel', uid: call.uid });\n waiter.reject(signal?.reason);\n };\n signal?.addEventListener('abort', abort, { once: true });\n const settled = () => signal?.removeEventListener('abort', abort);\n waiter.promise.then(settled, settled);\n this.port.postMessage(call, transfer);\n return waiter.promise as Promise<T>;\n }\n\n async resolve(name: string, family: ResolveFamily, signal?: AbortSignal) {\n const reply = await this.ask<Extract<Answer, { uplink: 'resolved' }>>(\n { uplink: 'resolve', uid: ++this.nextId, name, family },\n signal\n );\n return answerOf(reply);\n }\n\n async dial(req: UplinkDial): Promise<UplinkConn> {\n req.signal.throwIfAborted();\n const { host, port } = req;\n const opened = await this.ask<Extract<Answer, { uplink: 'dialled' }>>(\n { uplink: 'dial', uid: ++this.nextId, host, port },\n req.signal\n );\n const { cid, localAddr, remoteAddr } = opened;\n return {\n localAddr,\n remoteAddr,\n read: async () => {\n const got = await this.ask<Extract<Answer, { uplink: 'data' }>>({\n uplink: 'read',\n uid: ++this.nextId,\n cid,\n });\n return got.bytes;\n },\n write: async (bytes) => {\n const copy = bytes.slice();\n const call = { uplink: 'write' as const, uid: ++this.nextId, cid, bytes: copy };\n const done = await this.ask<Extract<Answer, { uplink: 'written' }>>(call, undefined, [\n copy.buffer,\n ]);\n return done.n;\n },\n closeWrite: () => this.port.postMessage({ uplink: 'close-write', cid }),\n close: () => this.port.postMessage({ uplink: 'close', cid }),\n };\n }\n\n async udp(req: UplinkUdpOpen): Promise<UplinkUdp> {\n req.signal.throwIfAborted();\n const opened = await this.ask<Extract<Answer, { uplink: 'udp-opened' }>>(\n { uplink: 'udp-open', uid: ++this.nextId, family: req.family },\n req.signal\n );\n const { cid, localAddr } = opened;\n const recv = () =>\n this.ask<Extract<Answer, { uplink: 'udp-message' }>>({\n uplink: 'udp-recv',\n uid: ++this.nextId,\n cid,\n });\n return {\n localAddr,\n send: async (bytes, host, port) => {\n const copy = bytes.slice();\n const call = {\n uplink: 'udp-send' as const,\n uid: ++this.nextId,\n cid,\n bytes: copy,\n host,\n port,\n };\n await this.ask(call, undefined, [copy.buffer]);\n },\n messages: {\n [Symbol.asyncIterator]: async function* () {\n for (;;) {\n const got = await recv();\n if (!got.message) return;\n yield got.message;\n }\n },\n },\n close: () => this.port.postMessage({ uplink: 'udp-close', cid }),\n };\n }\n}\n", "export interface CronClock {\n now(): number;\n readonly utc?: boolean;\n readonly timeZone?: string;\n sleep(until: number, signal: AbortSignal): Promise<void>;\n}\n\nexport function clockZone(clock: CronClock | undefined): string | undefined {\n return clock?.timeZone ?? (clock?.utc === true ? 'UTC' : undefined);\n}\n\nexport const systemCronClock: CronClock = {\n now: () => Date.now(),\n sleep(until, signal) {\n if (signal.aborted) return Promise.resolve();\n return new Promise((resolve) => {\n const done = () => {\n clearTimeout(timer);\n signal.removeEventListener('abort', done);\n resolve();\n };\n const timer = setTimeout(done, Math.max(0, until - Date.now()));\n (timer as { unref?: () => void }).unref?.();\n signal.addEventListener('abort', done, { once: true });\n });\n },\n};\n\nexport interface FakeCronClock extends CronClock {\n set(ms: number): void;\n advance(ms: number): void;\n flush(): Promise<void>;\n readonly sleepers: number;\n}\n\ninterface Sleeper {\n until: number;\n wake: () => void;\n ring: () => void;\n}\n\nexport function fakeCronClock(\n start = Date.UTC(2026, 0, 1),\n zone: boolean | string = true\n): FakeCronClock {\n const timeZone = zone === true ? 'UTC' : zone === false ? undefined : zone;\n let now = start;\n const sleepers = new Set<Sleeper>();\n let idle: Array<() => void> = [];\n let awake = 0;\n const settled = () =>\n awake === 0 && sleepers.size > 0 && [...sleepers].every((s) => s.until > now);\n const check = () => {\n if (!settled()) return;\n const waiting = idle;\n idle = [];\n for (const resolve of waiting) resolve();\n };\n const wakeDue = () => {\n for (const sleeper of [...sleepers]) if (sleeper.until <= now) sleeper.ring();\n };\n return {\n utc: timeZone === 'UTC',\n ...(timeZone !== undefined ? { timeZone } : {}),\n now: () => now,\n get sleepers() {\n return sleepers.size;\n },\n sleep(until, signal) {\n if (signal.aborted) return Promise.resolve();\n return new Promise((resolve) => {\n const sleeper: Sleeper = {\n until,\n wake: () => {\n sleepers.delete(sleeper);\n signal.removeEventListener('abort', sleeper.wake);\n resolve();\n },\n ring: () => {\n if (!sleepers.has(sleeper)) return;\n awake++;\n sleeper.wake();\n },\n };\n awake = Math.max(0, awake - 1);\n signal.addEventListener('abort', sleeper.wake, { once: true });\n sleepers.add(sleeper);\n if (until <= now) queueMicrotask(sleeper.ring);\n else check();\n });\n },\n set(ms) {\n now = ms;\n for (const sleeper of [...sleepers]) sleeper.ring();\n },\n advance(ms) {\n now += ms;\n wakeDue();\n },\n flush() {\n return new Promise((resolve) => {\n idle.push(resolve);\n queueMicrotask(check);\n });\n },\n };\n}\n", "import type { SealedCaller } from '../sealed.ts';\nimport type {\n HeaderList,\n RealmTransport,\n RealmTransportRequest,\n RealmTransportResponse,\n RealmWebSocketRequest,\n} from './transport.ts';\n\nconst PLACEHOLDER = /fnox_proxy_[0-9a-f]{24}/;\nconst ESCAPE = /%([0-9a-f]{2})/gi;\nconst BASIC = /\\bbasic\\b(.*)/is;\nconst PERCENT_LAYERS = 8;\nconst BASE64_GROUP = 4;\n\nexport const PLACEHOLDER_REFUSED =\n 'refused: this request has a sealed placeholder in its URL, a header or a Basic credential, and nothing fills it, so it was not sent';\n\nexport class PlaceholderRefused extends Error {\n readonly status = 403;\n readonly code = 'EACCES';\n\n constructor(reason = PLACEHOLDER_REFUSED) {\n super(reason);\n }\n}\n\nexport type PlaceholderFill = (\n request: RealmTransportRequest,\n stamp: SealedCaller\n) => Promise<RealmTransportResponse>;\n\nexport interface PlaceholderFloorOptions {\n known?: () => readonly string[];\n fill?: PlaceholderFill;\n}\n\ntype Known = readonly string[];\n\nfunction holds(text: string, known: Known): boolean {\n return PLACEHOLDER.test(text) || known.some((placeholder) => text.includes(placeholder));\n}\n\nfunction carries(text: string, known: Known): boolean {\n let layer = text;\n for (let i = 0; i < PERCENT_LAYERS; i++) {\n if (holds(layer, known)) return true;\n const next = layer.replace(ESCAPE, (_, hex: string) =>\n String.fromCharCode(Number.parseInt(hex, 16))\n );\n if (next === layer) return false;\n layer = next;\n }\n return holds(layer, known);\n}\n\nfunction basicCarries(value: string, known: Known): boolean {\n const credential = BASIC.exec(value)?.[1];\n if (credential === undefined) return false;\n const letters = credential\n .replace(/[^A-Za-z0-9+/_-]/g, '')\n .replaceAll('-', '+')\n .replaceAll('_', '/');\n for (let shift = 0; shift < BASE64_GROUP; shift++) {\n const part = letters.slice(shift);\n const whole = part.length % BASE64_GROUP === 1 ? part.slice(0, -1) : part;\n if (carries(atob(whole), known)) return true;\n }\n return false;\n}\n\nfunction headersCarry(headers: HeaderList, known: Known): boolean {\n return headers.some(\n ([name, value]) =>\n carries(name, known) ||\n carries(name.toLowerCase(), known) ||\n carries(value, known) ||\n basicCarries(value, known)\n );\n}\n\nfunction urlCarries(url: string, known: Known): boolean {\n return carries(url, known) || (URL.canParse(url) && carries(new URL(url).href, known));\n}\n\nfunction detected(request: Pick<RealmTransportRequest, 'url' | 'headers'>, known: Known): boolean {\n return urlCarries(request.url, known) || headersCarry(request.headers, known);\n}\n\nfunction refuseSocket(request: RealmWebSocketRequest, known: Known): void {\n if (detected(request, known) || request.protocols.some((p) => carries(p, known))) {\n throw new PlaceholderRefused();\n }\n}\n\nexport function placeholderFloor(\n inner: RealmTransport,\n { known = () => [], fill }: PlaceholderFloorOptions = {}\n): RealmTransport {\n const open = inner.websocket?.bind(inner);\n return {\n get traits() {\n return inner.traits;\n },\n ...(open\n ? {\n websocket: async (request) => {\n refuseSocket(request, known());\n return open(request);\n },\n }\n : {}),\n async fetch(request, owner, stamp) {\n if (!detected(request, known())) return inner.fetch(request, owner, stamp);\n if (!fill || !stamp) throw new PlaceholderRefused();\n return fill(request, stamp);\n },\n };\n}\n", "export const BODY_IDLE_MS = 5 * 60 * 1000;\n\nexport function idleFailure(ms: number): Error {\n return Object.assign(new Error(`the response body sent no data for ${ms} ms`), {\n code: 'ETIMEDOUT',\n });\n}\n\nexport async function readWithin<T>(\n reader: ReadableStreamDefaultReader<T>,\n ms: number\n): Promise<ReadableStreamReadResult<T>> {\n if (!(ms > 0 && ms < Number.POSITIVE_INFINITY)) return reader.read();\n let timer: ReturnType<typeof setTimeout> | undefined;\n const idle = new Promise<never>((_, reject) => {\n timer = setTimeout(() => reject(idleFailure(ms)), ms);\n });\n try {\n return await Promise.race([reader.read(), idle]);\n } finally {\n clearTimeout(timer);\n }\n}\n", "import { BODY_IDLE_MS } from '../../body-idle.ts';\nimport type { SealedCaller, SealedHook } from '../sealed.ts';\nimport { PlaceholderRefused } from './placeholder-floor.ts';\nimport type { HeaderList, RealmTransportRequest, RealmTransportResponse } from './transport.ts';\n\nexport const SEALED_FETCH_VERSION = 1;\n\nconst UNSAFE_FIELD = /[\\r\\n\\0]/;\n\nexport interface SealedFetchRequest {\n v: 1;\n caller: SealedCaller;\n method: string;\n url: string;\n headers: HeaderList;\n redirect: 'manual';\n body?: Uint8Array;\n bodyStream?: AsyncIterable<Uint8Array>;\n}\n\nexport type SealedFetchHook = (\n req: SealedFetchRequest,\n options: { signal: AbortSignal }\n) => Promise<RealmTransportResponse>;\n\nexport type SealedOption = SealedHook | { request: SealedHook; fetch?: SealedFetchHook };\n\nexport function sealedHooks(option: SealedOption | undefined): {\n request?: SealedHook;\n fetch?: SealedFetchHook;\n} {\n if (!option) return {};\n if (typeof option === 'function') return { request: option };\n const { request, fetch } = option;\n if (typeof request !== 'function' || (fetch !== undefined && typeof fetch !== 'function')) {\n throw new TypeError('sealed takes a function or { request, fetch? }');\n }\n return { request, ...(fetch ? { fetch } : {}) };\n}\n\nfunction headerList(headers: unknown): headers is HeaderList {\n return (\n Array.isArray(headers) &&\n headers.every(\n (field) =>\n Array.isArray(field) &&\n field.length === 2 &&\n field.every((text) => typeof text === 'string' && !UNSAFE_FIELD.test(text))\n )\n );\n}\n\nexport function sealedReplyValid(reply: unknown): reply is RealmTransportResponse {\n if (typeof reply !== 'object' || reply === null) return false;\n const { redirects, redirected, status, statusText, headers, url, body, cancel } =\n reply as Partial<RealmTransportResponse>;\n return (\n redirects === undefined &&\n redirected !== true &&\n Number.isInteger(status) &&\n (status as number) >= 100 &&\n (status as number) <= 599 &&\n typeof statusText === 'string' &&\n !UNSAFE_FIELD.test(statusText) &&\n headerList(headers) &&\n (url === undefined || typeof url === 'string') &&\n typeof body?.[Symbol.asyncIterator] === 'function' &&\n typeof cancel === 'function'\n );\n}\n\nexport function dropSealedReply(reply: unknown): void {\n const { cancel } = (reply ?? {}) as Partial<RealmTransportResponse>;\n if (typeof cancel !== 'function') return;\n void Promise.resolve()\n .then(() => cancel.call(reply))\n .catch(() => undefined);\n}\n\nfunction failed(reason: unknown): PlaceholderRefused {\n const text = reason instanceof Error ? reason.message : String(reason);\n return new PlaceholderRefused(\n `refused: the request with a sealed placeholder was not completed: ${text}`\n );\n}\n\nclass Stall {\n private readonly idle = new AbortController();\n private readonly ms: number;\n private timer: ReturnType<typeof setTimeout> | undefined;\n readonly signal: AbortSignal;\n\n constructor(signals: AbortSignal[], ms: number) {\n this.ms = ms;\n this.signal = AbortSignal.any([...signals, this.idle.signal]);\n }\n\n arm(): void {\n clearTimeout(this.timer);\n this.timer = setTimeout(() => this.idle.abort('timeout'), this.ms);\n (this.timer as { unref?: () => void }).unref?.();\n }\n\n touch(): void {\n if (this.timer !== undefined) this.arm();\n }\n\n rest(): void {\n clearTimeout(this.timer);\n this.timer = undefined;\n }\n}\n\nasync function until<T>(work: Promise<T>, signal: AbortSignal): Promise<T> {\n const stopped = Promise.withResolvers<never>();\n const stop = () => stopped.reject(signal.reason);\n if (signal.aborted) stop();\n else signal.addEventListener('abort', stop, { once: true });\n try {\n return await Promise.race([work, stopped.promise]);\n } finally {\n signal.removeEventListener('abort', stop);\n }\n}\n\nasync function* ticking(\n stream: AsyncIterable<Uint8Array>,\n stall: Stall\n): AsyncGenerator<Uint8Array> {\n for await (const chunk of stream) {\n stall.touch();\n yield chunk;\n }\n}\n\nfunction sealedRequest(\n request: RealmTransportRequest,\n stamp: SealedCaller,\n stall: Stall\n): SealedFetchRequest {\n const { method, url, headers, body, bodyStream } = request;\n return {\n v: 1,\n caller: structuredClone(stamp),\n method,\n url,\n headers: headers.map(([name, value]) => [name, value] as const),\n redirect: 'manual',\n ...(bodyStream ? { bodyStream: ticking(bodyStream, stall) } : body ? { body } : {}),\n };\n}\n\nfunction guarded(reply: RealmTransportResponse, stall: Stall): RealmTransportResponse {\n let finished = false;\n const cancel = async () => {\n stall.signal.removeEventListener('abort', dropped);\n stall.rest();\n if (finished) return;\n finished = true;\n await reply.cancel().catch(() => undefined);\n };\n const dropped = () => void cancel();\n stall.signal.addEventListener('abort', dropped, { once: true });\n const source = reply.body[Symbol.asyncIterator]();\n const body = (async function* () {\n try {\n for (;;) {\n stall.arm();\n const next = await until(source.next(), stall.signal);\n stall.rest();\n if (next.done) {\n finished = true;\n return;\n }\n if (!(next.value instanceof Uint8Array)) throw failed('a body chunk is not bytes');\n if (next.value.byteLength > 0) yield next.value;\n }\n } finally {\n await cancel();\n }\n })();\n return {\n ...(reply.url !== undefined ? { url: reply.url } : {}),\n status: reply.status,\n statusText: reply.statusText,\n headers: reply.headers,\n body,\n cancel,\n };\n}\n\nexport function sealedFetcher(\n hook: SealedFetchHook,\n stop: AbortSignal,\n idleMs = BODY_IDLE_MS\n): (request: RealmTransportRequest, stamp: SealedCaller) => Promise<RealmTransportResponse> {\n return async (request, stamp) => {\n const stall = new Stall([request.signal, stop], idleMs);\n const { signal } = stall;\n if (signal.aborted) throw failed(signal.reason);\n stall.arm();\n const asked = Promise.resolve().then(() => {\n signal.throwIfAborted();\n return hook(sealedRequest(request, stamp, stall), { signal });\n });\n let reply: unknown;\n try {\n reply = await until(asked, signal);\n } catch (e) {\n void asked.then(dropSealedReply, () => undefined);\n throw failed(e);\n } finally {\n stall.rest();\n }\n if (sealedReplyValid(reply)) return guarded(reply, stall);\n dropSealedReply(reply);\n throw failed('the reply is not a scrubbed response');\n };\n}\n", "export interface TestSyscall {\n pid: number;\n op: string;\n}\n\nexport type TestSyscallHook = (call: TestSyscall) => Promise<void> | void;\n\nconst SYSCALL_HOOK = Symbol.for('slicc-kernel.test.syscall');\n\ntype HookHolder = { [SYSCALL_HOOK]?: TestSyscallHook };\n\nexport function testSyscallHook(): TestSyscallHook | undefined {\n return (globalThis as HookHolder)[SYSCALL_HOOK];\n}\n\nexport function setTestSyscallHook(hook: TestSyscallHook | undefined): void {\n const holder = globalThis as HookHolder;\n if (hook) holder[SYSCALL_HOOK] = hook;\n else delete holder[SYSCALL_HOOK];\n}\n", "export function fresh(bytes: Uint8Array, start = 0, end = bytes.length): Uint8Array {\n return new Uint8Array(bytes.subarray(start, end));\n}\n", "import { fresh } from './bytes.ts';\nimport {\n dropSealedReply,\n type SealedFetchHook,\n type SealedFetchRequest,\n sealedReplyValid,\n} from './kernel/net/sealed-fetch.ts';\nimport type { HeaderList, RealmTransportResponse as Response } from './kernel/net/transport.ts';\nimport type { SealedHook, SealedRequest } from './kernel/sealed.ts';\n\nexport interface SealedPort {\n postMessage(message: unknown, transfer?: Transferable[]): void;\n}\n\nexport interface SealedAsk {\n id: number;\n req: SealedRequest;\n}\n\nexport interface SealedReply {\n id: number;\n reply?: object;\n error?: string;\n}\n\nexport interface SealedAbort {\n id: number;\n reason: unknown;\n}\n\ntype WireRequest = Omit<SealedFetchRequest, 'bodyStream'> & { streamed?: true };\n\nexport interface SealedFetchAsk {\n req: WireRequest;\n port: MessagePort;\n}\n\ntype AskerMessage =\n | { t: 'pull' }\n | { t: 'stop' }\n | {\n t: 'head';\n status: number;\n statusText: string;\n headers: HeaderList;\n url?: string;\n }\n | { t: 'chunk'; bytes: Uint8Array }\n | { t: 'end' }\n | { t: 'error'; message: string };\n\ntype AnswererMessage =\n | { t: 'read' }\n | { t: 'cancel'; reason: string }\n | { t: 'chunk'; bytes: Uint8Array }\n | { t: 'end' }\n | { t: 'error'; message: string };\n\nfunction textOf(err: unknown): string {\n return err instanceof Error ? err.message : String(err);\n}\n\nfunction sendBytes(port: MessagePort, bytes: Uint8Array): void {\n const copy = fresh(bytes);\n port.postMessage({ t: 'chunk', bytes: copy }, [copy.buffer as ArrayBuffer]);\n}\n\nfunction askFetch(\n port: SealedPort,\n req: SealedFetchRequest,\n signal: AbortSignal\n): Promise<Response> {\n signal.throwIfAborted();\n const { bodyStream, ...wire } = req;\n const { port1: near, port2: far } = new MessageChannel();\n const upload = bodyStream?.[Symbol.asyncIterator]();\n const head = Promise.withResolvers<Response>();\n let reading: PromiseWithResolvers<IteratorResult<Uint8Array>> | undefined;\n let ended = false;\n\n const end = (failure: Error) => {\n if (ended) return;\n ended = true;\n signal.removeEventListener('abort', abort);\n near.close();\n void upload?.return?.().catch(() => undefined);\n head.reject(failure);\n reading?.reject(failure);\n reading = undefined;\n };\n const abort = () => {\n near.postMessage({ t: 'cancel', reason: String(signal.reason) } satisfies AnswererMessage);\n end(new Error(String(signal.reason)));\n };\n const pull = async () => {\n try {\n const next = await (upload as AsyncIterator<Uint8Array>).next();\n if (ended) return;\n if (next.done) near.postMessage({ t: 'end' } satisfies AnswererMessage);\n else sendBytes(near, next.value);\n } catch (err) {\n if (!ended) near.postMessage({ t: 'error', message: textOf(err) });\n }\n };\n const respond = (message: Extract<AskerMessage, { t: 'head' }>) => {\n const { status, statusText, headers, url } = message;\n const body: AsyncIterable<Uint8Array> = {\n [Symbol.asyncIterator]: () => ({\n next: () => {\n if (ended) return Promise.resolve({ value: undefined, done: true });\n reading = Promise.withResolvers();\n near.postMessage({ t: 'read' } satisfies AnswererMessage);\n return reading.promise;\n },\n return: async () => {\n await cancel();\n return { value: undefined, done: true };\n },\n }),\n };\n const cancel = async () => {\n if (ended) return;\n near.postMessage({ t: 'cancel', reason: 'cancelled' } satisfies AnswererMessage);\n end(new Error('the request was cancelled'));\n };\n head.resolve({\n ...(url !== undefined ? { url } : {}),\n status,\n statusText,\n headers,\n body,\n cancel,\n });\n };\n near.addEventListener('message', ({ data }: MessageEvent<AskerMessage>) => {\n if (data.t === 'pull') void pull();\n else if (data.t === 'stop') void upload?.return?.().catch(() => undefined);\n else if (data.t === 'head') respond(data);\n else if (data.t === 'chunk') {\n reading?.resolve({ value: data.bytes, done: false });\n reading = undefined;\n } else if (data.t === 'end') {\n reading?.resolve({ value: undefined, done: true });\n reading = undefined;\n end(new Error('the response ended'));\n } else end(new Error(data.message));\n });\n near.addEventListener('close', () => end(new Error('the sealed fetch relay closed')));\n near.start();\n signal.addEventListener('abort', abort, { once: true });\n const ask: SealedFetchAsk = {\n req: { ...wire, ...(upload ? { streamed: true } : {}) },\n port: far,\n };\n port.postMessage({ sealedFetch: ask }, [far]);\n return head.promise;\n}\n\ninterface FetchAnswer {\n close(reason: unknown): void;\n}\n\nfunction uploadOf(far: MessagePort): {\n stream: AsyncIterable<Uint8Array>;\n answer(message: Extract<AnswererMessage, { t: 'chunk' | 'end' | 'error' }>): void;\n fail(reason: Error): void;\n} {\n let waiting: PromiseWithResolvers<IteratorResult<Uint8Array>> | undefined;\n let failure: Error | undefined;\n const next = () => {\n if (failure) return Promise.reject(failure);\n waiting = Promise.withResolvers();\n far.postMessage({ t: 'pull' } satisfies AskerMessage);\n return waiting.promise;\n };\n return {\n stream: {\n [Symbol.asyncIterator]: () => ({\n next,\n return: async () => {\n far.postMessage({ t: 'stop' } satisfies AskerMessage);\n return { value: undefined, done: true };\n },\n }),\n },\n answer(message) {\n if (message.t === 'chunk') waiting?.resolve({ value: message.bytes, done: false });\n else if (message.t === 'end') waiting?.resolve({ value: undefined, done: true });\n else {\n failure = new Error(message.message);\n waiting?.reject(failure);\n }\n waiting = undefined;\n },\n fail(reason) {\n failure = reason;\n waiting?.reject(reason);\n waiting = undefined;\n },\n };\n}\n\nfunction answerFetch(\n hook: SealedFetchHook | undefined,\n { req, port: far }: SealedFetchAsk,\n live: Set<FetchAnswer>\n): void {\n const control = new AbortController();\n const { streamed, ...fields } = req;\n const upload = uploadOf(far);\n let source: AsyncIterator<Uint8Array> | undefined;\n let reply: Response | undefined;\n let closed = false;\n\n const settle = () => {\n closed = true;\n live.delete(answer);\n upload.fail(new Error('the request ended'));\n };\n const answer: FetchAnswer = {\n close(reason) {\n if (closed) return;\n settle();\n control.abort(reason);\n dropSealedReply(reply);\n far.close();\n },\n };\n const finish = (message: AskerMessage) => {\n if (closed) return;\n settle();\n far.postMessage(message);\n };\n const failWith = (err: unknown) => {\n dropSealedReply(reply);\n finish({ t: 'error', message: textOf(err) });\n };\n const read = async () => {\n try {\n const next = await (source as AsyncIterator<Uint8Array>).next();\n if (closed) return;\n if (next.done) finish({ t: 'end' });\n else if (next.value instanceof Uint8Array) sendBytes(far, next.value);\n else failWith('a body chunk is not bytes');\n } catch (err) {\n failWith(err);\n }\n };\n const ask = async () => {\n try {\n if (!hook) throw new Error('no vault is connected');\n const request: SealedFetchRequest = {\n ...fields,\n ...(streamed ? { bodyStream: upload.stream } : {}),\n };\n const answered: unknown = await hook(request, { signal: control.signal });\n if (!sealedReplyValid(answered)) {\n dropSealedReply(answered);\n throw new Error('the reply is not a scrubbed response');\n }\n if (closed) return dropSealedReply(answered);\n reply = answered;\n source = answered.body[Symbol.asyncIterator]();\n const { status, statusText, headers, url } = answered;\n far.postMessage({\n t: 'head',\n status,\n statusText,\n headers,\n ...(url !== undefined ? { url } : {}),\n } satisfies AskerMessage);\n } catch (err) {\n failWith(err);\n }\n };\n far.addEventListener('message', ({ data }: MessageEvent<AnswererMessage>) => {\n if (data.t === 'read') void read();\n else if (data.t === 'cancel') answer.close(data.reason);\n else upload.answer(data);\n });\n far.addEventListener('close', () => answer.close('withdrawn'));\n far.start();\n live.add(answer);\n void ask();\n}\n\nexport function sealedAsker(port: SealedPort): {\n hook: SealedHook;\n fetch: SealedFetchHook;\n answer(reply: SealedReply): void;\n} {\n const asks = new Map<number, PromiseWithResolvers<object>>();\n let next = 0;\n const hook: SealedHook = (req, { signal }) => {\n const id = ++next;\n const waiting = Promise.withResolvers<object>();\n asks.set(id, waiting);\n const abort = () => {\n if (!asks.delete(id)) return;\n port.postMessage({ sealedAbort: { id, reason: signal.reason } });\n waiting.reject(new Error(String(signal.reason)));\n };\n signal.addEventListener('abort', abort, { once: true });\n port.postMessage({ sealedAsk: { id, req } });\n return waiting.promise.finally(() => signal.removeEventListener('abort', abort));\n };\n const answer = ({ id, reply, error }: SealedReply) => {\n const waiting = asks.get(id);\n if (!waiting) return;\n asks.delete(id);\n if (reply) waiting.resolve(reply);\n else waiting.reject(new Error(error ?? 'no reply'));\n };\n return { hook, fetch: (req, { signal }) => askFetch(port, req, signal), answer };\n}\n\nexport interface SealedAnswerer {\n handle(data: unknown): boolean;\n close(): void;\n}\n\nexport function sealedAnswerer(\n port: SealedPort,\n hook: SealedHook | undefined,\n fetchHook?: SealedFetchHook\n): SealedAnswerer {\n const asked = new Map<number, AbortController>();\n const fetches = new Set<FetchAnswer>();\n const ask = async ({ id, req }: SealedAsk): Promise<void> => {\n const control = new AbortController();\n asked.set(id, control);\n try {\n if (!hook) throw new Error('no vault is connected');\n const reply = await hook(req, { signal: control.signal });\n port.postMessage({ sealedReply: { id, reply } });\n } catch (err) {\n const error = err instanceof Error ? err.message : String(err);\n port.postMessage({ sealedReply: { id, error } });\n } finally {\n asked.delete(id);\n }\n };\n const abort = ({ id, reason }: SealedAbort): void => {\n asked.get(id)?.abort(reason);\n asked.delete(id);\n };\n return {\n handle(data) {\n const message = data as {\n sealedAsk?: SealedAsk;\n sealedAbort?: SealedAbort;\n sealedFetch?: SealedFetchAsk;\n } | null;\n if (message?.sealedAsk) void ask(message.sealedAsk);\n else if (message?.sealedAbort) abort(message.sealedAbort);\n else if (message?.sealedFetch) answerFetch(fetchHook, message.sealedFetch, fetches);\n else return false;\n return true;\n },\n close() {\n for (const control of asked.values()) control.abort('withdrawn');\n asked.clear();\n for (const answer of [...fetches]) answer.close('withdrawn');\n },\n };\n}\n", "import type { RouteTable } from './kernel/net/routes.ts';\nimport {\n answerOf,\n type NetworkUplink,\n type ResolveAnswer,\n type ResolveFamily,\n type UplinkConn,\n type UplinkDatagram,\n type UplinkDial,\n type UplinkMessage,\n type UplinkUdp,\n type UplinkUdpOpen,\n type UplinkUnreachable,\n} from './kernel/net/uplink.ts';\n\nexport { type CronClock, type FakeCronClock, fakeCronClock } from './cron/clock.ts';\nexport { placeholderFloor } from './kernel/net/placeholder-floor.ts';\nexport { sealedFetcher } from './kernel/net/sealed-fetch.ts';\nexport {\n setTestSyscallHook,\n type TestSyscall,\n type TestSyscallHook,\n} from './kernel/test-hooks.ts';\nexport { sealedAnswerer, sealedAsker } from './sealed-relay.ts';\nexport type {\n NetworkUplink,\n ResolveAnswer,\n ResolveFamily,\n RouteTable,\n UplinkConn,\n UplinkDatagram,\n UplinkDial,\n UplinkMessage,\n UplinkUdp,\n UplinkUdpOpen,\n UplinkUnreachable,\n};\n\nexport type FakeDatagramPeer = (\n bytes: Uint8Array\n) => Uint8Array | readonly Uint8Array[] | { error: string } | undefined;\n\nexport interface FakePeerSocket {\n read(): Promise<Uint8Array | null>;\n write(bytes: Uint8Array): void;\n end(): void;\n reset(code?: string): void;\n readonly buffered: number;\n drained(): Promise<void>;\n readonly closed: Promise<void>;\n}\n\nexport type FakePeer = ((socket: FakePeerSocket) => void) | { error: string } | { hang: true };\n\nexport interface FakeUplinkOptions {\n names?: Readonly<Record<string, string[] | ResolveAnswer>>;\n routes?: RouteTable;\n ipv6?: boolean;\n exit?: string;\n peers?: Readonly<Record<string, FakePeer>>;\n datagrams?: Readonly<Record<string, FakeDatagramPeer>>;\n address?: string;\n nameserver?: string;\n}\n\nexport interface FakeUplink extends NetworkUplink {\n readonly asked: Array<{ name: string; family: ResolveFamily }>;\n readonly dialled: Array<{ host: string; port: number }>;\n readonly sent: Array<{ host: string; port: number; bytes: Uint8Array }>;\n udp(req: UplinkUdpOpen): Promise<UplinkUdp>;\n}\n\nconst failure = (code: string, message: string) => Object.assign(new Error(message), { code });\n\nclass Stream {\n private readonly queue: Array<{\n bytes: Uint8Array;\n taken: () => void;\n lost: (error: Error) => void;\n }> = [];\n private ended = false;\n private broken: Error | undefined;\n private waiters: Array<() => void> = [];\n size = 0;\n\n private wake(): void {\n const waiters = this.waiters;\n this.waiters = [];\n for (const wake of waiters) wake();\n }\n\n push(bytes: Uint8Array): Promise<void> {\n if (this.broken) return Promise.reject(this.broken);\n if (this.ended) return Promise.reject(failure('EPIPE', 'the stream is closed'));\n return new Promise((taken, lost) => {\n this.queue.push({ bytes: bytes.slice(), taken, lost });\n this.size += bytes.length;\n this.wake();\n });\n }\n\n end(): void {\n this.ended = true;\n this.wake();\n }\n\n fail(error: Error): void {\n this.broken = error;\n for (const pending of this.queue.splice(0)) pending.lost(error);\n this.size = 0;\n this.wake();\n }\n\n async read(): Promise<Uint8Array | null> {\n while (this.queue.length === 0 && !this.ended && !this.broken) {\n await new Promise<void>((resolve) => this.waiters.push(resolve));\n }\n if (this.broken) throw this.broken;\n const next = this.queue.shift();\n if (!next) return null;\n this.size -= next.bytes.length;\n next.taken();\n this.wake();\n return next.bytes;\n }\n\n async drained(): Promise<void> {\n while (this.size > 0) await new Promise<void>((resolve) => this.waiters.push(resolve));\n }\n}\n\nfunction named(host: string, port: number): string {\n return `${host.includes(':') ? `[${host}]` : host}:${port}`;\n}\n\nclass Inbox {\n private readonly queue: UplinkMessage[] = [];\n private ended = false;\n private wake: (() => void) | undefined;\n\n push(message: UplinkMessage): void {\n if (this.ended) return;\n this.queue.push(message);\n this.wake?.();\n }\n\n end(): void {\n this.ended = true;\n this.wake?.();\n }\n\n async *[Symbol.asyncIterator](): AsyncGenerator<UplinkMessage> {\n for (;;) {\n const next = this.queue.shift();\n if (next) yield next;\n else if (this.ended) return;\n else await new Promise<void>((resolve) => (this.wake = resolve));\n }\n }\n}\n\nfunction fakeUdp(\n options: FakeUplinkOptions,\n sent: FakeUplink['sent'],\n local: string\n): Promise<UplinkUdp> {\n const inbox = new Inbox();\n return Promise.resolve({\n localAddr: local,\n messages: inbox,\n send: async (bytes, host, port) => {\n sent.push({ host, port, bytes: bytes.slice() });\n const answer = options.datagrams?.[named(host, port)]?.(bytes.slice());\n if (!answer) return;\n if ('error' in answer) {\n inbox.push({ error: answer.error, host, port });\n return;\n }\n const replies = answer instanceof Uint8Array ? [answer] : answer;\n for (const reply of replies) inbox.push({ bytes: reply.slice(), host, port });\n },\n close: () => inbox.end(),\n });\n}\n\nfunction hang(signal: AbortSignal): Promise<never> {\n return new Promise((_, reject) => {\n signal.addEventListener('abort', () => reject(failure('ECONNABORTED', 'dial aborted')), {\n once: true,\n });\n });\n}\n\nexport function fakeUplink(options: FakeUplinkOptions = {}): FakeUplink {\n const asked: FakeUplink['asked'] = [];\n const dialled: FakeUplink['dialled'] = [];\n const sent: FakeUplink['sent'] = [];\n let nextPort = 40000;\n return {\n traits: { tcp: true, udp: options.datagrams !== undefined, ipv6: options.ipv6 === true },\n ...(options.routes ? { routes: options.routes } : {}),\n ...(options.nameserver ? { nameserver: options.nameserver } : {}),\n asked,\n dialled,\n sent,\n udp: () => fakeUdp(options, sent, named(options.address ?? '100.100.100.100', nextPort++)),\n resolve: async (name, family) => {\n asked.push({ name, family });\n return answerOf(options.names?.[name] ?? []);\n },\n dial: async ({ host, port, signal }) => {\n dialled.push({ host, port });\n const peer = options.peers?.[named(host, port)];\n if (!peer) throw failure('ECONNREFUSED', `nothing listens on ${named(host, port)}`);\n if ('error' in peer) throw failure(peer.error, `${named(host, port)}: ${peer.error}`);\n if ('hang' in peer) return hang(signal);\n const up = new Stream();\n const down = new Stream();\n const closed = Promise.withResolvers<void>();\n peer({\n read: () => up.read(),\n write: (bytes) => void down.push(bytes).catch(() => undefined),\n end: () => down.end(),\n reset: (code = 'ECONNRESET') => {\n const error = failure(code, `the peer reset the connection (${code})`);\n up.fail(error);\n down.fail(error);\n },\n get buffered() {\n return down.size;\n },\n drained: () => down.drained(),\n closed: closed.promise,\n });\n return {\n localAddr: named(options.address ?? '100.100.100.100', nextPort++),\n remoteAddr: named(host, port),\n ...(options.exit === undefined ? {} : { exit: options.exit }),\n read: () => down.read(),\n write: async (bytes) => {\n await up.push(bytes);\n return bytes.length;\n },\n closeWrite: () => up.end(),\n close: () => {\n up.end();\n down.end();\n closed.resolve();\n },\n };\n },\n };\n}\n"],
5
+ "mappings": "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",
6
6
  "names": ["until", "failure"]
7
7
  }
@@ -1,8 +1,10 @@
1
1
  export interface CronClock {
2
2
  now(): number;
3
3
  readonly utc?: boolean;
4
+ readonly timeZone?: string;
4
5
  sleep(until: number, signal: AbortSignal): Promise<void>;
5
6
  }
7
+ export declare function clockZone(clock: CronClock | undefined): string | undefined;
6
8
  export declare const systemCronClock: CronClock;
7
9
  export interface FakeCronClock extends CronClock {
8
10
  set(ms: number): void;
@@ -10,4 +12,4 @@ export interface FakeCronClock extends CronClock {
10
12
  flush(): Promise<void>;
11
13
  readonly sleepers: number;
12
14
  }
13
- export declare function fakeCronClock(start?: number, utc?: boolean): FakeCronClock;
15
+ export declare function fakeCronClock(start?: number, zone?: boolean | string): FakeCronClock;
@@ -1,4 +1,6 @@
1
+ import { type Zone } from '../time-zone.js';
1
2
  export interface Schedule {
3
+ fixed: boolean;
2
4
  minutes: ReadonlySet<number>;
3
5
  hours: ReadonlySet<number>;
4
6
  days: ReadonlySet<number>;
@@ -16,11 +18,11 @@ export type When = {
16
18
  export declare const MISSED_CAP = 100000;
17
19
  export declare function parseSchedule(expression: string): Schedule;
18
20
  export declare function parseWhen(expression: string): When;
19
- export declare function nextFire(schedule: Schedule, after: number, utc?: boolean): number | null;
21
+ export declare function nextFire(schedule: Schedule, after: number, zone?: Zone): number | null;
20
22
  export interface Missed {
21
23
  count: number;
22
24
  last: number | null;
23
25
  more: boolean;
24
26
  }
25
- export declare function missedFires(schedule: Schedule, from: number, until: number, utc?: boolean, cap?: number): Missed;
26
- export declare function latestFire(schedule: Schedule, from: number, until: number, utc?: boolean): number;
27
+ export declare function missedFires(schedule: Schedule, from: number, until: number, zone?: Zone, cap?: number): Missed;
28
+ export declare function latestFire(schedule: Schedule, from: number, until: number, zone?: Zone): number;
@@ -29,6 +29,7 @@ export interface CronHost {
29
29
  owners: boolean;
30
30
  lock: string;
31
31
  bootId: string;
32
+ timeZone: string;
32
33
  clock?: CronClock;
33
34
  locks?: CronLocks | undefined;
34
35
  ready?: () => Promise<unknown>;
@@ -71,6 +71,7 @@ export interface KernelOptions {
71
71
  cdp?: CdpHook;
72
72
  facades?: FacadeSpecs;
73
73
  hostname?: string;
74
+ timeZone?: string;
74
75
  users?: UsersMode;
75
76
  onDenial?: DenialHook;
76
77
  sealed?: SealedOption;
@@ -1,7 +1,7 @@
1
1
  import { CdpHosts } from './cdp/hosts.js';
2
2
  import type { CdpHook } from './cdp/types.js';
3
3
  import { type Abi, type Command, type CommandVariant } from './commands.js';
4
- import type { CronClock } from './cron/clock.js';
4
+ import { type CronClock } from './cron/clock.js';
5
5
  import { CronService } from './cron/service.js';
6
6
  import { FacadeHosts } from './facade/hosts.js';
7
7
  import type { FacadeSpecs } from './facade/types.js';
@@ -63,6 +63,7 @@ export interface LauncherOptions {
63
63
  uplink?: NetworkUplink;
64
64
  doh?: string | false;
65
65
  hostname?: string;
66
+ timeZone?: string;
66
67
  users?: UsersMode;
67
68
  wasmMemories?: {
68
69
  ceiling?: number;
@@ -223,6 +224,7 @@ export declare class Launcher {
223
224
  readonly routes: Routes;
224
225
  readonly resolver: Resolver;
225
226
  readonly hostname: string;
227
+ readonly timeZone: string;
226
228
  readonly watchers: FsWatchers;
227
229
  private readonly changes;
228
230
  private peerHeldPaths;
@@ -1,6 +1,6 @@
1
1
  import { type MessagePort, type Worker } from 'node:worker_threads';
2
2
  import type { CdpHook } from './cdp/types.js';
3
- import type { CronClock } from './cron/clock.js';
3
+ import { type CronClock } from './cron/clock.js';
4
4
  import type { FacadeSpecs } from './facade/types.js';
5
5
  import type { Attestation, AttestTombstone } from './fs/attest.js';
6
6
  import type { DenialHook } from './fs/dac.js';
@@ -59,6 +59,7 @@ export interface NodeKernelOptions {
59
59
  cdp?: CdpHook;
60
60
  facades?: FacadeSpecs;
61
61
  hostname?: string;
62
+ timeZone?: string;
62
63
  users?: UsersMode;
63
64
  onDenial?: DenialHook;
64
65
  sealed?: SealedOption;
@@ -41,6 +41,7 @@ export interface InitRequest {
41
41
  doh?: string | false;
42
42
  hostfs?: boolean;
43
43
  hostname?: string;
44
+ timeZone?: string;
44
45
  users?: UsersMode;
45
46
  protect?: ProtectInit;
46
47
  denials?: boolean;
@@ -0,0 +1,11 @@
1
+ export declare const MINUTE_MS = 60000;
2
+ export interface Zone {
3
+ readonly name: string;
4
+ offset(at: number): number;
5
+ }
6
+ export declare function canonicalZone(name: unknown): string | undefined;
7
+ export declare function hostTimeZone(): string;
8
+ export declare function systemTimeZone(given: string | undefined, fallback?: string): string;
9
+ export declare const utcZone: Zone;
10
+ export declare function zoneOf(name: string): Zone;
11
+ export declare const MAX_SHIFT_MS: number;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ai-ecoverse/slicc-kernel",
3
- "version": "1.174.1",
3
+ "version": "1.174.2",
4
4
  "description": "SLICC's wasm-realm kernel: run Emscripten programs in the browser against OPFS, with fork, spawn, pipes and waitpid",
5
5
  "type": "module",
6
6
  "license": "Apache-2.0",