// Virtual-origin URL shapes (ESM slice brief §Architecture decisions). Every one names // the host page that owns it, so the SW routes it to that page's runtime: // /~/@/vfs/?v=. — transformed ESM source // /~/@/builtin/ — builtin facade module // /~/@/cjs/ — CJS facade module // /~/@/http// — a guest node:http server // The owner rides in the URL because Chromium gives every fetch from a nested worker // (where runtime code runs) an empty clientId, so the requester cannot be traced back // to its page. Single source of truth: the kernel builds these, the host parses them // out of SW relay messages, and the runtime hook returns them — importing from here // keeps the three sites from drifting. export type ModuleKind = "vfs" | "builtin" | "cjs"; /** A host page's id for its whole life: random, short, URL-safe. */ export type HostToken = string & { readonly __hostToken: unique symbol }; export type VirtualPath = | { host: HostToken; kind: ModuleKind; path: string } // path is what the guest sees as req.url (minus the query): "/" + rest, still encoded. | { host: HostToken; kind: "http"; port: number; path: string }; export const VIRTUAL_PREFIX = "/~/"; /** The WebSocket shim the SW serves itself and puts first in every guest app document. */ export const WS_SHIM_PATH = "/~/ws-shim.js"; const TOKEN = /^[0-9a-f]{16}$/; export function parseHostToken(text: string | null | undefined): HostToken | null { return text != null && TOKEN.test(text) ? text as HostToken : null; } export function newHostToken(): HostToken { const bytes = crypto.getRandomValues(new Uint8Array(8)); return Array.from(bytes, (b) => b.toString(16).padStart(2, "0")).join("") as HostToken; } // encodeURIComponent leaves ' unescaped (it is in the unescaped mark set), but these // URLs get spliced INSIDE guest string literals by the kernel transformer, so quote // characters must never survive encoding. decodeURIComponent round-trips %27. const encPath = (path: string): string => encodeURIComponent(path).replace(/'/g, "%27"); export function vfsUrl(host: HostToken, path: string, stat: { ino: number; mtimeMs: number }): string { return `/~/@${host}/vfs/${encPath(path)}?v=${stat.ino}.${stat.mtimeMs}`; } export function builtinUrl(host: HostToken, id: string): string { return `/~/@${host}/builtin/${id}`; } export function cjsUrl(host: HostToken, path: string): string { return `/~/@${host}/cjs/${encPath(path)}`; } export function httpUrl(host: HostToken, port: number): string { return `/~/@${host}/http/${port}/`; } /** Parse the pathname of a /~/ URL into owner, kind and payload. Null for foreign * paths, for a missing owner and for malformed encodings — a malformed URL is a * 404, never a crash. */ export function parseVirtualPath(pathname: string): VirtualPath | null { if (!pathname.startsWith(VIRTUAL_PREFIX + "@")) return null; const [token, kind, ...segments] = pathname.slice(VIRTUAL_PREFIX.length + 1).split("/"); const host = parseHostToken(token); if (!host || kind === undefined || segments.length === 0) return null; const payload = segments.join("/"); if (kind === "vfs" || kind === "cjs") { try { return { host, kind, path: decodeURIComponent(payload) }; } catch { return null; } } if (kind === "builtin") return { host, kind, path: payload }; if (kind === "http") { const portText = segments[0]!; const port = Number(portText); if (segments.length < 2 || !/^\d{1,5}$/.test(portText) || port > 65535) return null; return { host, kind, port, path: "/" + segments.slice(1).join("/") }; } return null; }