@statewalker/cellb 0.5.2 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (61) hide show
  1. package/README.md +40 -6
  2. package/dist/adapters/ltx-vfs.js +26 -4
  3. package/dist/adapters/ltx-vfs.js.map +1 -1
  4. package/dist/browser.d.ts +4 -0
  5. package/dist/browser.js +2 -0
  6. package/dist/browser.js.map +1 -1
  7. package/dist/bundle.d.ts +2 -0
  8. package/dist/bundle.js +5 -0
  9. package/dist/bundle.js.map +1 -0
  10. package/dist/core/object-host.d.ts +7 -0
  11. package/dist/core/object-host.js +40 -7
  12. package/dist/core/object-host.js.map +1 -1
  13. package/dist/index.d.ts +1 -0
  14. package/dist/index.js +1 -0
  15. package/dist/index.js.map +1 -1
  16. package/dist/ltx/files-rpc.d.ts +30 -0
  17. package/dist/ltx/files-rpc.js +129 -0
  18. package/dist/ltx/files-rpc.js.map +1 -0
  19. package/dist/ltx/ltx-host.d.ts +63 -0
  20. package/dist/ltx/ltx-host.js +46 -0
  21. package/dist/ltx/ltx-host.js.map +1 -0
  22. package/dist/ltx/ltx-page-server.d.ts +42 -1
  23. package/dist/ltx/ltx-page-server.js +101 -21
  24. package/dist/ltx/ltx-page-server.js.map +1 -1
  25. package/dist/ltx/ltx-pages.d.ts +5 -0
  26. package/dist/ltx/ltx-pages.js +32 -3
  27. package/dist/ltx/ltx-pages.js.map +1 -1
  28. package/dist/ltx/ltx-store-worker.js +35 -22
  29. package/dist/ltx/ltx-store-worker.js.map +1 -1
  30. package/dist/node-compat/browser-registry.d.ts +1 -0
  31. package/dist/node-compat/browser-registry.js +5 -0
  32. package/dist/node-compat/browser-registry.js.map +1 -1
  33. package/dist/node-compat/util-guard.d.ts +2 -0
  34. package/dist/node-compat/util-guard.js +14 -0
  35. package/dist/node-compat/util-guard.js.map +1 -0
  36. package/dist/project/browser-host.d.ts +32 -3
  37. package/dist/project/browser-host.js +47 -20
  38. package/dist/project/browser-host.js.map +1 -1
  39. package/dist/project/browser-load.d.ts +16 -4
  40. package/dist/project/browser-load.js +46 -9
  41. package/dist/project/browser-load.js.map +1 -1
  42. package/dist/project/build.js +2 -2
  43. package/dist/project/build.js.map +1 -1
  44. package/dist/project/bundle-compiler.d.ts +31 -0
  45. package/dist/project/bundle-compiler.js +73 -0
  46. package/dist/project/bundle-compiler.js.map +1 -0
  47. package/dist/project/node-project.js +3 -3
  48. package/dist/project/node-project.js.map +1 -1
  49. package/dist/project/site-compiler.d.ts +67 -0
  50. package/dist/project/site-compiler.js +134 -0
  51. package/dist/project/site-compiler.js.map +1 -0
  52. package/dist/project/source-project.d.ts +46 -0
  53. package/dist/project/source-project.js +45 -0
  54. package/dist/project/source-project.js.map +1 -0
  55. package/dist/project/wrangler.d.ts +4 -0
  56. package/dist/project/wrangler.js +7 -1
  57. package/dist/project/wrangler.js.map +1 -1
  58. package/dist/site.d.ts +2 -0
  59. package/dist/site.js +4 -3
  60. package/dist/site.js.map +1 -1
  61. package/package.json +11 -1
package/README.md CHANGED
@@ -38,8 +38,9 @@ worker is started that way (checked with a Vite build, see `scripts/pack-check.m
38
38
  |---|---|
39
39
  | `@statewalker/cellb` | the runtime (`createCellRuntime`, `createProjectRuntime`), `DurableObject` and `WorkerEntrypoint`, the ports and `CellStorage`, `celldBucket`, the object stores (`s3ObjectStore`, `memoryObjectStore`, `filesApiObjectStore`), `filesApiLtxLog`, `filesApiChangeLog`, `filesApiBackup`, `wasmMemoryOpener` (in-memory SQLite WASM), links over ports, `CellRouter`, `createShardWorker`, the WebSocket classes, and the errors embedders catch |
40
40
  | `@statewalker/cellb/node` | `loadProject` and `buildProject` (the `cellb build` command), `nodeSqliteOpener`, `sqliteObjectStore` (celld dev's local bucket), `loadNodeProject`, `applyNodeD1Migrations`, and celld's peer protocol (`startCelldPeerServer`, `celldPeers`) |
41
- | `@statewalker/cellb/browser` | `loadProject` (a `cellb build` folder by URL), `browserProjectRuntime`, `startProjectShards`, `joinProjectShards` and `serveProjectShard` (shards in workers and tabs), `installProjectRouter` (the ServiceWorker side), `sahpoolOpener`, `idbObjectStore`, `serviceWorkerConnector` |
42
- | `@statewalker/cellb/site` | `createProjectSite`: a project's sources compiled in the browser and served by an in-browser HTTP server (`browserProjectRuntime({ site })`). Needs the optional peer dependencies `@statewalker/webrun-modules` and `@statewalker/webrun-site-builder`; the site is hosted in a ServiceWorker with `@statewalker/webrun-site-host`, also an optional peer |
41
+ | `@statewalker/cellb/browser` | `loadProject` (a `cellb build` folder by URL, or sources with a compiler), `browserProjectRuntime`, `startProjectShards`, `joinProjectShards` and `serveProjectShard` (shards in workers and tabs), `installProjectRouter` (the ServiceWorker side), `sahpoolOpener`, `idbObjectStore`, `serviceWorkerConnector` |
42
+ | `@statewalker/cellb/site` | `createProjectSite`: a project's sources compiled in the browser and served by an in-browser HTTP server (`browserProjectRuntime({ site })`); `siteCompiler` for `loadProject`, and `siteHostOverPort` / `hostSitesForWorker` to host a worker's site from its page. Needs the optional peer dependencies `@statewalker/webrun-modules`, `@statewalker/webrun-site-builder` and `@statewalker/webrun-site-host` (the ServiceWorker host) |
43
+ | `@statewalker/cellb/bundle` | `bundleCompiler`: a project's sources bundled in the browser for `loadProject`, with webrun-bundler on esbuild-wasm. Needs the optional peer dependency `@statewalker/webrun-bundler`; the caller passes esbuild-wasm, initialized |
43
44
  | `@statewalker/cellb/host-modules` | for bundlers other than cellb's own (webrun-bundler in a browser, say): the sources of `cloudflare:workers`, `node:*` and the Workers globals as cellb's realms provide them (`cellbHostModule`, `CELLS_GLOBALS_MODULE`) |
44
45
  | `@statewalker/cellb/isolate-worker` | the Dedicated Worker that runs a Worker-Loader Worker in a realm of its own (`isolateScript`) |
45
46
 
@@ -87,7 +88,10 @@ manifest that lists the assets, since a static host cannot list a folder. Any st
87
88
  it; Node loads it too.
88
89
 
89
90
  - `source`: Node takes a folder (built or not), a `file:` or `http(s):` URL of a built folder, or
90
- a FilesApi holding either; a browser takes the URL of a built folder or a FilesApi holding one.
91
+ a FilesApi holding either; a browser takes the URL of a built folder or a FilesApi holding one,
92
+ or, with `compile`, a FilesApi holding the sources.
93
+ - `compile` (browser): how a source folder becomes code, below. Without it, a browser loads only
94
+ `cellb build` folders.
91
95
  - `data`: where cells keep their data. On Node, a directory (SQLite files, and the project's files
92
96
  under `<data>/files`); without it, memory. In a browser, an OPFS name: the SQLite pool `<data>`
93
97
  and the files directory `<data>-files` (default: the project's `name`).
@@ -99,6 +103,34 @@ it; Node loads it too.
99
103
 
100
104
  `loadNodeProject` and `browserProjectRuntime`, below, stay as the lower-level calls.
101
105
 
106
+ ### Sources in a browser: `compile`
107
+
108
+ A browser compiles a project's sources (`wrangler.jsonc` and `main` at the root of a FilesApi,
109
+ `package.json`, assets) when `loadProject` is given a compiler. The compilers come from their own
110
+ entry points, so a plain `loadProject` ships neither:
111
+
112
+ ```ts
113
+ // One ES module, bundled by webrun-bundler on esbuild-wasm. npm packages come from the project's
114
+ // node_modules, else the npm registry, at package.json's ranges.
115
+ import * as esbuild from "esbuild-wasm";
116
+ import { bundleCompiler } from "@statewalker/cellb/bundle";
117
+ await esbuild.initialize({ wasmURL });
118
+ const project = await loadProject(files, { data: "app", compile: bundleCompiler({ esbuild }) });
119
+
120
+ // Modules compiled one by one by webrun-modules, served from the page's ServiceWorker (a change
121
+ // recompiles one module). A Dedicated Worker cannot register a ServiceWorker: its page hosts the
122
+ // site, with hostSitesForWorker(worker).
123
+ import { siteCompiler, siteHostOverPort } from "@statewalker/cellb/site";
124
+ const project = await loadProject(files, {
125
+ data: "app",
126
+ compile: siteCompiler({ host: siteHostOverPort(self) }),
127
+ });
128
+ ```
129
+
130
+ Both lower `await` for nodejs_compat as `cellb build` does (AsyncLocalStorage follows
131
+ continuations), and take `cloudflare:workers`, the Workers globals and `node:*` from the runtime.
132
+ A source folder loads from a FilesApi only: a static host cannot list it.
133
+
102
134
  ### A Worker and a Durable Object in Node
103
135
 
104
136
  ```ts
@@ -305,9 +337,11 @@ Queues, Workflows, …) in [docs/services/](docs/services/). What is isolated, a
305
337
  `webrun-http-browser` — the HTTP links over MessagePorts, the WebSocket client and its frames.
306
338
  - Optional peers, for `@statewalker/cellb/site` only: `webrun-modules` (compiles a project's
307
339
  sources in the browser; it brings lightningcss-wasm and @jspm/core, about 30 MB),
308
- `webrun-site-builder` (the in-browser HTTP server), and `webrun-site-host`, which the
309
- embedder's own ServiceWorker code uses to host it (cellb does not import it). Projects that run a
310
- bundle (`{ bundle }`) need none of them, and their builds emit none of their assets.
340
+ `webrun-site-builder` (the in-browser HTTP server), and `webrun-site-host` (hosts it in a
341
+ ServiceWorker: `siteCompiler`, `hostSitesForWorker`). Projects that run a bundle (`{ bundle }`)
342
+ need none of them, and their builds emit none of their assets.
343
+ - Optional peer, for `@statewalker/cellb/bundle` only: `webrun-bundler` (with esbuild-wasm, which
344
+ the caller passes in).
311
345
  - `worker-timers` — unthrottled heartbeat timers on a page's main thread.
312
346
  - `buffer`, `events`, `util`, `assert`, `path-browserify` — `nodejs_compat` in browsers.
313
347
 
@@ -21,16 +21,38 @@ export function installLtxVfs(sqlite3, channel, opts = {}) {
21
21
  const ctl = new Int32Array(channel.sab, 0, 2);
22
22
  const payload = new Uint8Array(channel.sab, 8);
23
23
  const stats = { reads: 0, cacheHits: 0, storeReads: 0, commits: 0, blockedMs: 0 };
24
+ /**
25
+ * Each request's number: the store tags its answer with it (state word = seq << 2 | state),
26
+ * so the late answer to a request this worker gave up on is not taken for the next one's.
27
+ */
28
+ let seq = 0;
24
29
  /** A request answered synchronously: blocks this worker until the store notifies. */
25
30
  const call = (msg) => {
31
+ seq = (seq % 0x1fffffff) + 1;
26
32
  Atomics.store(ctl, 0, 0);
27
33
  const t = performance.now();
28
- channel.post(msg);
34
+ // `until` (wall clock, which both threads share): a commit the store could only finish
35
+ // near it is not kept, since this worker may already have given up on it.
36
+ channel.post({ ...msg, seq, until: Date.now() + 30_000 });
29
37
  // A store that never answers (a worker that failed to load) must not freeze this worker.
30
- if (Atomics.wait(ctl, 0, 0, 30_000) === "timed-out")
31
- throw new Error(`ltx store: no answer to ${String(msg.op)} in 30 s`);
38
+ const deadline = t + 30_000;
39
+ let word = 0;
40
+ for (;;) {
41
+ const left = deadline - performance.now();
42
+ if (left > 0)
43
+ Atomics.wait(ctl, 0, 0, left);
44
+ word = Atomics.load(ctl, 0);
45
+ // Out of time: unless this request's answer is there now, it is abandoned (the store
46
+ // does not keep a commit past `until`, nor serve a request once a newer one came).
47
+ if (performance.now() >= deadline && word >>> 2 !== seq)
48
+ throw new Error(`ltx store: no answer to ${String(msg.op)} in 30 s`);
49
+ if (word >>> 2 === seq)
50
+ break;
51
+ // An answer to an earlier request (given up on): not this one's; wait on.
52
+ Atomics.compareExchange(ctl, 0, word, 0);
53
+ }
32
54
  stats.blockedMs += performance.now() - t;
33
- if (ctl[0] === 2)
55
+ if ((word & 3) === 2)
34
56
  throw new Error(new TextDecoder().decode(payload.slice(0, ctl[1])));
35
57
  return payload.slice(0, ctl[1]);
36
58
  };
@@ -1 +1 @@
1
- {"version":3,"file":"ltx-vfs.js","sourceRoot":"","sources":["../../src/adapters/ltx-vfs.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * A synchronous SQLite VFS (SQLite WASM, in a worker) over an ASYNCHRONOUS page store in another\n * thread: the database is a cell's LTX files on a FilesApi (src/ltx/ltx-pages.ts, served by\n * ltxPageServer). Reads block on a SharedArrayBuffer (Atomics.wait) while the store reads the\n * page by range; pages are cached here (LRU). Writes stay in this worker until the commit\n * (xSync of the main file), which sends the transaction's pages to the store: one LTX file.\n * The rollback journal lives in memory (journal_mode=MEMORY): only the main file is a file.\n *\n * Needs cross-origin isolation (SharedArrayBuffer). One writer per database.\n */\nconst SQLITE_OK = 0;\nconst SQLITE_IOERR = 10;\nconst SQLITE_IOERR_SHORT_READ = 522;\nconst SQLITE_OPEN_MAIN_DB = 0x100;\n\nexport interface LtxVfsChannel {\n /** Shared control words [state, length] + payload (≥ one page). */\n sab: SharedArrayBuffer;\n /** Posts a request to the store (it answers into `sab`, then notifies). */\n post(msg: unknown): void;\n}\n\nexport interface LtxVfsStats {\n reads: number;\n cacheHits: number;\n storeReads: number;\n commits: number;\n blockedMs: number;\n}\n\nexport function installLtxVfs(\n sqlite3: any,\n channel: LtxVfsChannel,\n opts: { name?: string; cachePages?: number; readAhead?: number } = {},\n): { name: string; stats: LtxVfsStats } {\n const { capi, wasm } = sqlite3;\n const name = opts.name ?? \"ltx\";\n const cacheMax = opts.cachePages ?? 2048;\n // A miss fetches this many consecutive pages at once (SQLite scans walk pages in order).\n const readAhead = Math.max(1, opts.readAhead ?? 16);\n const ctl = new Int32Array(channel.sab, 0, 2);\n const payload = new Uint8Array(channel.sab, 8);\n const stats: LtxVfsStats = { reads: 0, cacheHits: 0, storeReads: 0, commits: 0, blockedMs: 0 };\n\n /** A request answered synchronously: blocks this worker until the store notifies. */\n const call = (msg: Record<string, unknown>): Uint8Array => {\n Atomics.store(ctl, 0, 0);\n const t = performance.now();\n channel.post(msg);\n // A store that never answers (a worker that failed to load) must not freeze this worker.\n if (Atomics.wait(ctl, 0, 0, 30_000) === \"timed-out\")\n throw new Error(`ltx store: no answer to ${String(msg.op)} in 30 s`);\n stats.blockedMs += performance.now() - t;\n if (ctl[0] === 2) throw new Error(new TextDecoder().decode(payload.slice(0, ctl[1])));\n return payload.slice(0, ctl[1]);\n };\n /** One open database (a cell): its size, its page cache, the current transaction's pages. */\n interface Db {\n cell: string;\n pageSize: number;\n pageCount: number;\n cache: Map<number, Uint8Array>; // LRU: insertion order\n dirty: Map<number, Uint8Array>;\n }\n const dbs = new Map<string, Db>();\n const dbOf = (cell: string): Db => {\n let d = dbs.get(cell);\n if (!d) {\n const meta = JSON.parse(new TextDecoder().decode(call({ op: \"meta\", cell }))) as {\n pageSize: number;\n pageCount: number;\n };\n d = {\n cell,\n pageSize: meta.pageSize || 4096,\n pageCount: meta.pageCount,\n cache: new Map(),\n dirty: new Map(),\n };\n dbs.set(cell, d);\n }\n return d;\n };\n const page = (d: Db, pgno: number): Uint8Array => {\n const w = d.dirty.get(pgno);\n if (w) return w;\n stats.reads++;\n const c = d.cache.get(pgno);\n if (c) {\n stats.cacheHits++;\n d.cache.delete(pgno);\n d.cache.set(pgno, c);\n return c;\n }\n stats.storeReads++;\n if (pgno > d.pageCount) return new Uint8Array(d.pageSize);\n const count = Math.min(\n readAhead,\n d.pageCount - pgno + 1,\n Math.floor((channel.sab.byteLength - 8) / d.pageSize),\n );\n const run = call({ op: \"readRun\", cell: d.cell, pgno, count });\n for (let i = 0; i * d.pageSize < run.length; i++) {\n const q = pgno + i;\n if (d.dirty.has(q)) continue;\n d.cache.set(q, run.subarray(i * d.pageSize, (i + 1) * d.pageSize));\n if (d.cache.size > cacheMax) d.cache.delete(d.cache.keys().next().value as number);\n }\n return d.cache.get(pgno) ?? new Uint8Array(d.pageSize);\n };\n\n // Journal and other non-main files: plain memory.\n const memFiles = new Map<string, Uint8Array>();\n const open = new Map<number, { main: boolean; path: string; db?: Db }>();\n\n const io = new capi.sqlite3_io_methods();\n io.$iVersion = 1;\n const vfs = new capi.sqlite3_vfs();\n vfs.$iVersion = 1;\n vfs.$szOsFile = capi.sqlite3_file.structInfo.sizeof;\n vfs.$mxPathname = 512;\n\n sqlite3.vfs.installVfs({\n io: {\n struct: io,\n methods: {\n xClose(pFile: number) {\n const d = open.get(pFile)?.db;\n if (d) dbs.delete(d.cell); // its cache goes with it\n open.delete(pFile);\n return SQLITE_OK;\n },\n xRead(pFile: number, pDest: number, n: number, off: bigint) {\n const f = open.get(pFile);\n const at = Number(off);\n const heap = wasm.heap8u();\n if (!f?.main) {\n const b = memFiles.get(f?.path ?? \"\") ?? new Uint8Array();\n const got = b.subarray(at, at + n);\n heap.set(got, pDest);\n if (got.length < n) {\n heap.fill(0, pDest + got.length, pDest + n);\n return SQLITE_IOERR_SHORT_READ;\n }\n return SQLITE_OK;\n }\n try {\n const d = f.db as Db;\n const { pageSize } = d;\n const size = d.pageCount * pageSize;\n let o = 0;\n while (o < n && at + o < size) {\n const pos = at + o;\n const pgno = Math.floor(pos / pageSize) + 1;\n const inPage = pos % pageSize;\n const take = Math.min(pageSize - inPage, n - o);\n heap.set(page(d, pgno).subarray(inPage, inPage + take), pDest + o);\n o += take;\n }\n if (o < n) {\n heap.fill(0, pDest + o, pDest + n);\n return SQLITE_IOERR_SHORT_READ;\n }\n return SQLITE_OK;\n } catch (err) {\n // SQLite only sees SQLITE_IOERR (and rolls the transaction back): say why.\n console.error(`cellb ltx-vfs: ${(err as Error)?.message ?? err}`);\n return SQLITE_IOERR;\n }\n },\n xWrite(pFile: number, pSrc: number, n: number, off: bigint) {\n const f = open.get(pFile);\n const at = Number(off);\n const src = wasm.heap8u().subarray(pSrc, pSrc + n);\n if (!f?.main) {\n const cur = memFiles.get(f?.path ?? \"\") ?? new Uint8Array();\n const next = cur.length >= at + n ? cur : new Uint8Array(at + n);\n if (next !== cur) next.set(cur);\n next.set(src, at);\n memFiles.set(f?.path ?? \"\", next);\n return SQLITE_OK;\n }\n const d = f.db as Db;\n if (d.pageCount === 0 && at === 0 && n >= 18) {\n const ps = (src[16] << 8) | src[17];\n d.pageSize = ps === 1 ? 65536 : ps;\n }\n const { pageSize } = d;\n for (let o = 0; o < n; ) {\n const pos = at + o;\n const pgno = Math.floor(pos / pageSize) + 1;\n const inPage = pos % pageSize;\n const take = Math.min(pageSize - inPage, n - o);\n let p = d.dirty.get(pgno);\n if (!p) {\n p = take === pageSize ? new Uint8Array(pageSize) : page(d, pgno).slice();\n d.dirty.set(pgno, p);\n }\n p.set(src.subarray(o, o + take), inPage);\n o += take;\n if (pgno > d.pageCount) d.pageCount = pgno;\n }\n return SQLITE_OK;\n },\n xTruncate(pFile: number, size: bigint) {\n const f = open.get(pFile);\n if (!f?.main) {\n memFiles.set(\n f?.path ?? \"\",\n (memFiles.get(f?.path ?? \"\") ?? new Uint8Array()).slice(0, Number(size)),\n );\n return SQLITE_OK;\n }\n const d = f.db as Db;\n d.pageCount = Math.ceil(Number(size) / d.pageSize);\n for (const k of [...d.dirty.keys()]) if (k > d.pageCount) d.dirty.delete(k);\n return SQLITE_OK;\n },\n xSync(pFile: number) {\n const d = open.get(pFile)?.db;\n if (!d || !d.dirty.size) return SQLITE_OK;\n // The commit: this transaction's pages become one LTX file in the store.\n try {\n const pages = [...d.dirty].sort((a, b) => a[0] - b[0]);\n call({\n op: \"commit\",\n cell: d.cell,\n pageSize: d.pageSize,\n pageCount: d.pageCount,\n pages,\n });\n stats.commits++;\n for (const [pgno, p] of pages) d.cache.set(pgno, p);\n d.dirty.clear();\n return SQLITE_OK;\n } catch (err) {\n // SQLite only sees SQLITE_IOERR (and rolls the transaction back): say why.\n console.error(`cellb ltx-vfs: ${(err as Error)?.message ?? err}`);\n return SQLITE_IOERR;\n }\n },\n xFileSize(pFile: number, pOut: number) {\n const f = open.get(pFile);\n const size = f?.db\n ? f.db.pageCount * f.db.pageSize\n : (memFiles.get(f?.path ?? \"\")?.length ?? 0);\n wasm.poke64(pOut, BigInt(size));\n return SQLITE_OK;\n },\n xLock: () => SQLITE_OK,\n xUnlock: () => SQLITE_OK,\n xCheckReservedLock(_p: number, pOut: number) {\n wasm.poke32(pOut, 0);\n return SQLITE_OK;\n },\n xFileControl: () => 12, // SQLITE_NOTFOUND\n xSectorSize: () => 4096,\n xDeviceCharacteristics: () => 0,\n },\n },\n vfs: {\n struct: vfs,\n name,\n methods: {\n xOpen(_pVfs: number, zName: number, pFile: number, flags: number, pOutFlags: number) {\n const path = zName ? wasm.cstrToJs(zName) : `tmp-${pFile}`;\n const main = !!(flags & SQLITE_OPEN_MAIN_DB);\n try {\n open.set(pFile, { main, path, db: main ? dbOf(path) : undefined });\n } catch (err) {\n // SQLite only sees SQLITE_IOERR (and rolls the transaction back): say why.\n console.error(`cellb ltx-vfs: ${(err as Error)?.message ?? err}`);\n return SQLITE_IOERR;\n }\n const f = new capi.sqlite3_file(pFile);\n f.$pMethods = io.pointer;\n f.dispose();\n if (pOutFlags) wasm.poke32(pOutFlags, flags);\n return SQLITE_OK;\n },\n xDelete(_p: number, zName: number) {\n memFiles.delete(wasm.cstrToJs(zName));\n return SQLITE_OK;\n },\n xAccess(_p: number, zName: number, _flags: number, pOut: number) {\n wasm.poke32(pOut, memFiles.has(wasm.cstrToJs(zName)) ? 1 : 0);\n return SQLITE_OK;\n },\n xFullPathname(_p: number, zName: number, nOut: number, pOut: number) {\n wasm.cstrncpy(pOut, zName, nOut);\n return SQLITE_OK;\n },\n xRandomness(_p: number, n: number, pOut: number) {\n crypto.getRandomValues(wasm.heap8u().subarray(pOut, pOut + n));\n return n;\n },\n xSleep: () => SQLITE_OK,\n xCurrentTime(_p: number, pOut: number) {\n wasm.poke64f(pOut, 2440587.5 + Date.now() / 86400000);\n return SQLITE_OK;\n },\n xCurrentTimeInt64(_p: number, pOut: number) {\n wasm.poke64(pOut, BigInt(Math.floor(2440587.5 * 86400000 + Date.now())));\n return SQLITE_OK;\n },\n xGetLastError: () => 0,\n },\n },\n });\n return { name, stats };\n}\n"]}
1
+ {"version":3,"file":"ltx-vfs.js","sourceRoot":"","sources":["../../src/adapters/ltx-vfs.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * A synchronous SQLite VFS (SQLite WASM, in a worker) over an ASYNCHRONOUS page store in another\n * thread: the database is a cell's LTX files on a FilesApi (src/ltx/ltx-pages.ts, served by\n * ltxPageServer). Reads block on a SharedArrayBuffer (Atomics.wait) while the store reads the\n * page by range; pages are cached here (LRU). Writes stay in this worker until the commit\n * (xSync of the main file), which sends the transaction's pages to the store: one LTX file.\n * The rollback journal lives in memory (journal_mode=MEMORY): only the main file is a file.\n *\n * Needs cross-origin isolation (SharedArrayBuffer). One writer per database.\n */\nconst SQLITE_OK = 0;\nconst SQLITE_IOERR = 10;\nconst SQLITE_IOERR_SHORT_READ = 522;\nconst SQLITE_OPEN_MAIN_DB = 0x100;\n\nexport interface LtxVfsChannel {\n /** Shared control words [state, length] + payload (≥ one page). */\n sab: SharedArrayBuffer;\n /** Posts a request to the store (it answers into `sab`, then notifies). */\n post(msg: unknown): void;\n}\n\nexport interface LtxVfsStats {\n reads: number;\n cacheHits: number;\n storeReads: number;\n commits: number;\n blockedMs: number;\n}\n\nexport function installLtxVfs(\n sqlite3: any,\n channel: LtxVfsChannel,\n opts: { name?: string; cachePages?: number; readAhead?: number } = {},\n): { name: string; stats: LtxVfsStats } {\n const { capi, wasm } = sqlite3;\n const name = opts.name ?? \"ltx\";\n const cacheMax = opts.cachePages ?? 2048;\n // A miss fetches this many consecutive pages at once (SQLite scans walk pages in order).\n const readAhead = Math.max(1, opts.readAhead ?? 16);\n const ctl = new Int32Array(channel.sab, 0, 2);\n const payload = new Uint8Array(channel.sab, 8);\n const stats: LtxVfsStats = { reads: 0, cacheHits: 0, storeReads: 0, commits: 0, blockedMs: 0 };\n\n /**\n * Each request's number: the store tags its answer with it (state word = seq << 2 | state),\n * so the late answer to a request this worker gave up on is not taken for the next one's.\n */\n let seq = 0;\n /** A request answered synchronously: blocks this worker until the store notifies. */\n const call = (msg: Record<string, unknown>): Uint8Array => {\n seq = (seq % 0x1fffffff) + 1;\n Atomics.store(ctl, 0, 0);\n const t = performance.now();\n // `until` (wall clock, which both threads share): a commit the store could only finish\n // near it is not kept, since this worker may already have given up on it.\n channel.post({ ...msg, seq, until: Date.now() + 30_000 });\n // A store that never answers (a worker that failed to load) must not freeze this worker.\n const deadline = t + 30_000;\n let word = 0;\n for (;;) {\n const left = deadline - performance.now();\n if (left > 0) Atomics.wait(ctl, 0, 0, left);\n word = Atomics.load(ctl, 0);\n // Out of time: unless this request's answer is there now, it is abandoned (the store\n // does not keep a commit past `until`, nor serve a request once a newer one came).\n if (performance.now() >= deadline && word >>> 2 !== seq)\n throw new Error(`ltx store: no answer to ${String(msg.op)} in 30 s`);\n if (word >>> 2 === seq) break;\n // An answer to an earlier request (given up on): not this one's; wait on.\n Atomics.compareExchange(ctl, 0, word, 0);\n }\n stats.blockedMs += performance.now() - t;\n if ((word & 3) === 2) throw new Error(new TextDecoder().decode(payload.slice(0, ctl[1])));\n return payload.slice(0, ctl[1]);\n };\n /** One open database (a cell): its size, its page cache, the current transaction's pages. */\n interface Db {\n cell: string;\n pageSize: number;\n pageCount: number;\n cache: Map<number, Uint8Array>; // LRU: insertion order\n dirty: Map<number, Uint8Array>;\n }\n const dbs = new Map<string, Db>();\n const dbOf = (cell: string): Db => {\n let d = dbs.get(cell);\n if (!d) {\n const meta = JSON.parse(new TextDecoder().decode(call({ op: \"meta\", cell }))) as {\n pageSize: number;\n pageCount: number;\n };\n d = {\n cell,\n pageSize: meta.pageSize || 4096,\n pageCount: meta.pageCount,\n cache: new Map(),\n dirty: new Map(),\n };\n dbs.set(cell, d);\n }\n return d;\n };\n const page = (d: Db, pgno: number): Uint8Array => {\n const w = d.dirty.get(pgno);\n if (w) return w;\n stats.reads++;\n const c = d.cache.get(pgno);\n if (c) {\n stats.cacheHits++;\n d.cache.delete(pgno);\n d.cache.set(pgno, c);\n return c;\n }\n stats.storeReads++;\n if (pgno > d.pageCount) return new Uint8Array(d.pageSize);\n const count = Math.min(\n readAhead,\n d.pageCount - pgno + 1,\n Math.floor((channel.sab.byteLength - 8) / d.pageSize),\n );\n const run = call({ op: \"readRun\", cell: d.cell, pgno, count });\n for (let i = 0; i * d.pageSize < run.length; i++) {\n const q = pgno + i;\n if (d.dirty.has(q)) continue;\n d.cache.set(q, run.subarray(i * d.pageSize, (i + 1) * d.pageSize));\n if (d.cache.size > cacheMax) d.cache.delete(d.cache.keys().next().value as number);\n }\n return d.cache.get(pgno) ?? new Uint8Array(d.pageSize);\n };\n\n // Journal and other non-main files: plain memory.\n const memFiles = new Map<string, Uint8Array>();\n const open = new Map<number, { main: boolean; path: string; db?: Db }>();\n\n const io = new capi.sqlite3_io_methods();\n io.$iVersion = 1;\n const vfs = new capi.sqlite3_vfs();\n vfs.$iVersion = 1;\n vfs.$szOsFile = capi.sqlite3_file.structInfo.sizeof;\n vfs.$mxPathname = 512;\n\n sqlite3.vfs.installVfs({\n io: {\n struct: io,\n methods: {\n xClose(pFile: number) {\n const d = open.get(pFile)?.db;\n if (d) dbs.delete(d.cell); // its cache goes with it\n open.delete(pFile);\n return SQLITE_OK;\n },\n xRead(pFile: number, pDest: number, n: number, off: bigint) {\n const f = open.get(pFile);\n const at = Number(off);\n const heap = wasm.heap8u();\n if (!f?.main) {\n const b = memFiles.get(f?.path ?? \"\") ?? new Uint8Array();\n const got = b.subarray(at, at + n);\n heap.set(got, pDest);\n if (got.length < n) {\n heap.fill(0, pDest + got.length, pDest + n);\n return SQLITE_IOERR_SHORT_READ;\n }\n return SQLITE_OK;\n }\n try {\n const d = f.db as Db;\n const { pageSize } = d;\n const size = d.pageCount * pageSize;\n let o = 0;\n while (o < n && at + o < size) {\n const pos = at + o;\n const pgno = Math.floor(pos / pageSize) + 1;\n const inPage = pos % pageSize;\n const take = Math.min(pageSize - inPage, n - o);\n heap.set(page(d, pgno).subarray(inPage, inPage + take), pDest + o);\n o += take;\n }\n if (o < n) {\n heap.fill(0, pDest + o, pDest + n);\n return SQLITE_IOERR_SHORT_READ;\n }\n return SQLITE_OK;\n } catch (err) {\n // SQLite only sees SQLITE_IOERR (and rolls the transaction back): say why.\n console.error(`cellb ltx-vfs: ${(err as Error)?.message ?? err}`);\n return SQLITE_IOERR;\n }\n },\n xWrite(pFile: number, pSrc: number, n: number, off: bigint) {\n const f = open.get(pFile);\n const at = Number(off);\n const src = wasm.heap8u().subarray(pSrc, pSrc + n);\n if (!f?.main) {\n const cur = memFiles.get(f?.path ?? \"\") ?? new Uint8Array();\n const next = cur.length >= at + n ? cur : new Uint8Array(at + n);\n if (next !== cur) next.set(cur);\n next.set(src, at);\n memFiles.set(f?.path ?? \"\", next);\n return SQLITE_OK;\n }\n const d = f.db as Db;\n if (d.pageCount === 0 && at === 0 && n >= 18) {\n const ps = (src[16] << 8) | src[17];\n d.pageSize = ps === 1 ? 65536 : ps;\n }\n const { pageSize } = d;\n for (let o = 0; o < n; ) {\n const pos = at + o;\n const pgno = Math.floor(pos / pageSize) + 1;\n const inPage = pos % pageSize;\n const take = Math.min(pageSize - inPage, n - o);\n let p = d.dirty.get(pgno);\n if (!p) {\n p = take === pageSize ? new Uint8Array(pageSize) : page(d, pgno).slice();\n d.dirty.set(pgno, p);\n }\n p.set(src.subarray(o, o + take), inPage);\n o += take;\n if (pgno > d.pageCount) d.pageCount = pgno;\n }\n return SQLITE_OK;\n },\n xTruncate(pFile: number, size: bigint) {\n const f = open.get(pFile);\n if (!f?.main) {\n memFiles.set(\n f?.path ?? \"\",\n (memFiles.get(f?.path ?? \"\") ?? new Uint8Array()).slice(0, Number(size)),\n );\n return SQLITE_OK;\n }\n const d = f.db as Db;\n d.pageCount = Math.ceil(Number(size) / d.pageSize);\n for (const k of [...d.dirty.keys()]) if (k > d.pageCount) d.dirty.delete(k);\n return SQLITE_OK;\n },\n xSync(pFile: number) {\n const d = open.get(pFile)?.db;\n if (!d || !d.dirty.size) return SQLITE_OK;\n // The commit: this transaction's pages become one LTX file in the store.\n try {\n const pages = [...d.dirty].sort((a, b) => a[0] - b[0]);\n call({\n op: \"commit\",\n cell: d.cell,\n pageSize: d.pageSize,\n pageCount: d.pageCount,\n pages,\n });\n stats.commits++;\n for (const [pgno, p] of pages) d.cache.set(pgno, p);\n d.dirty.clear();\n return SQLITE_OK;\n } catch (err) {\n // SQLite only sees SQLITE_IOERR (and rolls the transaction back): say why.\n console.error(`cellb ltx-vfs: ${(err as Error)?.message ?? err}`);\n return SQLITE_IOERR;\n }\n },\n xFileSize(pFile: number, pOut: number) {\n const f = open.get(pFile);\n const size = f?.db\n ? f.db.pageCount * f.db.pageSize\n : (memFiles.get(f?.path ?? \"\")?.length ?? 0);\n wasm.poke64(pOut, BigInt(size));\n return SQLITE_OK;\n },\n xLock: () => SQLITE_OK,\n xUnlock: () => SQLITE_OK,\n xCheckReservedLock(_p: number, pOut: number) {\n wasm.poke32(pOut, 0);\n return SQLITE_OK;\n },\n xFileControl: () => 12, // SQLITE_NOTFOUND\n xSectorSize: () => 4096,\n xDeviceCharacteristics: () => 0,\n },\n },\n vfs: {\n struct: vfs,\n name,\n methods: {\n xOpen(_pVfs: number, zName: number, pFile: number, flags: number, pOutFlags: number) {\n const path = zName ? wasm.cstrToJs(zName) : `tmp-${pFile}`;\n const main = !!(flags & SQLITE_OPEN_MAIN_DB);\n try {\n open.set(pFile, { main, path, db: main ? dbOf(path) : undefined });\n } catch (err) {\n // SQLite only sees SQLITE_IOERR (and rolls the transaction back): say why.\n console.error(`cellb ltx-vfs: ${(err as Error)?.message ?? err}`);\n return SQLITE_IOERR;\n }\n const f = new capi.sqlite3_file(pFile);\n f.$pMethods = io.pointer;\n f.dispose();\n if (pOutFlags) wasm.poke32(pOutFlags, flags);\n return SQLITE_OK;\n },\n xDelete(_p: number, zName: number) {\n memFiles.delete(wasm.cstrToJs(zName));\n return SQLITE_OK;\n },\n xAccess(_p: number, zName: number, _flags: number, pOut: number) {\n wasm.poke32(pOut, memFiles.has(wasm.cstrToJs(zName)) ? 1 : 0);\n return SQLITE_OK;\n },\n xFullPathname(_p: number, zName: number, nOut: number, pOut: number) {\n wasm.cstrncpy(pOut, zName, nOut);\n return SQLITE_OK;\n },\n xRandomness(_p: number, n: number, pOut: number) {\n crypto.getRandomValues(wasm.heap8u().subarray(pOut, pOut + n));\n return n;\n },\n xSleep: () => SQLITE_OK,\n xCurrentTime(_p: number, pOut: number) {\n wasm.poke64f(pOut, 2440587.5 + Date.now() / 86400000);\n return SQLITE_OK;\n },\n xCurrentTimeInt64(_p: number, pOut: number) {\n wasm.poke64(pOut, BigInt(Math.floor(2440587.5 * 86400000 + Date.now())));\n return SQLITE_OK;\n },\n xGetLastError: () => 0,\n },\n },\n });\n return { name, stats };\n}\n"]}
package/dist/browser.d.ts CHANGED
@@ -1,8 +1,12 @@
1
1
  export { sahpoolOpener } from "./adapters/wasm-sqlite.js";
2
2
  export { idbObjectStore } from "./bucket/idb-object-store.js";
3
+ export { type FilesRpcOptions, rpcFilesClient, serveFilesApi } from "./ltx/files-rpc.js";
4
+ export { filesApiPort, type ServeLtxStoreOptions, serveLtxStore } from "./ltx/ltx-host.js";
5
+ export type { LtxStoreFiles } from "./ltx/ltx-page-server.js";
3
6
  export { type BrowserBucket, type BrowserProjectOptions, browserProjectRuntime, } from "./project/browser-host.js";
4
7
  export { type BrowserLoadProjectOptions, loadProject } from "./project/browser-load.js";
5
8
  export { type ProjectShards, serveProjectShard, startProjectShards, } from "./project/browser-shards.js";
6
9
  export { installProjectRouter, joinProjectShards, type ProjectTabs, type ProjectTabsOptions, type ServiceWorkerScope, shardOwner, } from "./project/browser-tabs.js";
7
10
  export type { LoadedProject, LoadProjectOptions, ProjectSource, } from "./project/built-project.js";
11
+ export type { CompiledProject, ProjectCompiler, } from "./project/source-project.js";
8
12
  export { serviceWorkerConnector } from "./ws/sw-connector.js";
package/dist/browser.js CHANGED
@@ -1,5 +1,7 @@
1
1
  export { sahpoolOpener } from "./adapters/wasm-sqlite.js";
2
2
  export { idbObjectStore } from "./bucket/idb-object-store.js";
3
+ export { rpcFilesClient, serveFilesApi } from "./ltx/files-rpc.js";
4
+ export { filesApiPort, serveLtxStore } from "./ltx/ltx-host.js";
3
5
  export { browserProjectRuntime, } from "./project/browser-host.js";
4
6
  export { loadProject } from "./project/browser-load.js";
5
7
  export { serveProjectShard, startProjectShards, } from "./project/browser-shards.js";
@@ -1 +1 @@
1
- {"version":3,"file":"browser.js","sourceRoot":"","sources":["../src/browser.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAC1D,OAAO,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAC9D,OAAO,EAGL,qBAAqB,GACtB,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAkC,WAAW,EAAE,MAAM,2BAA2B,CAAC;AACxF,OAAO,EAEL,iBAAiB,EACjB,kBAAkB,GACnB,MAAM,6BAA6B,CAAC;AACrC,OAAO,EACL,oBAAoB,EACpB,iBAAiB,EAIjB,UAAU,GACX,MAAM,2BAA2B,CAAC;AAMnC,OAAO,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC","sourcesContent":["export { sahpoolOpener } from \"./adapters/wasm-sqlite.js\";\nexport { idbObjectStore } from \"./bucket/idb-object-store.js\";\nexport {\n type BrowserBucket,\n type BrowserProjectOptions,\n browserProjectRuntime,\n} from \"./project/browser-host.js\";\nexport { type BrowserLoadProjectOptions, loadProject } from \"./project/browser-load.js\";\nexport {\n type ProjectShards,\n serveProjectShard,\n startProjectShards,\n} from \"./project/browser-shards.js\";\nexport {\n installProjectRouter,\n joinProjectShards,\n type ProjectTabs,\n type ProjectTabsOptions,\n type ServiceWorkerScope,\n shardOwner,\n} from \"./project/browser-tabs.js\";\nexport type {\n LoadedProject,\n LoadProjectOptions,\n ProjectSource,\n} from \"./project/built-project.js\";\nexport { serviceWorkerConnector } from \"./ws/sw-connector.js\";\n"]}
1
+ {"version":3,"file":"browser.js","sourceRoot":"","sources":["../src/browser.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAC1D,OAAO,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAC9D,OAAO,EAAwB,cAAc,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACzF,OAAO,EAAE,YAAY,EAA6B,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAE3F,OAAO,EAGL,qBAAqB,GACtB,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAkC,WAAW,EAAE,MAAM,2BAA2B,CAAC;AACxF,OAAO,EAEL,iBAAiB,EACjB,kBAAkB,GACnB,MAAM,6BAA6B,CAAC;AACrC,OAAO,EACL,oBAAoB,EACpB,iBAAiB,EAIjB,UAAU,GACX,MAAM,2BAA2B,CAAC;AAUnC,OAAO,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC","sourcesContent":["export { sahpoolOpener } from \"./adapters/wasm-sqlite.js\";\nexport { idbObjectStore } from \"./bucket/idb-object-store.js\";\nexport { type FilesRpcOptions, rpcFilesClient, serveFilesApi } from \"./ltx/files-rpc.js\";\nexport { filesApiPort, type ServeLtxStoreOptions, serveLtxStore } from \"./ltx/ltx-host.js\";\nexport type { LtxStoreFiles } from \"./ltx/ltx-page-server.js\";\nexport {\n type BrowserBucket,\n type BrowserProjectOptions,\n browserProjectRuntime,\n} from \"./project/browser-host.js\";\nexport { type BrowserLoadProjectOptions, loadProject } from \"./project/browser-load.js\";\nexport {\n type ProjectShards,\n serveProjectShard,\n startProjectShards,\n} from \"./project/browser-shards.js\";\nexport {\n installProjectRouter,\n joinProjectShards,\n type ProjectTabs,\n type ProjectTabsOptions,\n type ServiceWorkerScope,\n shardOwner,\n} from \"./project/browser-tabs.js\";\nexport type {\n LoadedProject,\n LoadProjectOptions,\n ProjectSource,\n} from \"./project/built-project.js\";\nexport type {\n CompiledProject,\n ProjectCompiler,\n} from \"./project/source-project.js\";\nexport { serviceWorkerConnector } from \"./ws/sw-connector.js\";\n"]}
@@ -0,0 +1,2 @@
1
+ export { type BundleCompilerOptions, bundleCompiler } from "./project/bundle-compiler.js";
2
+ export type { CompiledProject, ProjectCompiler } from "./project/source-project.js";
package/dist/bundle.js ADDED
@@ -0,0 +1,5 @@
1
+ // @statewalker/cellb/bundle: a project's sources bundled in the browser, for `loadProject`'s
2
+ // `compile`. It needs the optional peer dependency @statewalker/webrun-bundler, and esbuild-wasm,
3
+ // which the caller initializes and passes in (its .wasm URL is the app's to serve).
4
+ export { bundleCompiler } from "./project/bundle-compiler.js";
5
+ //# sourceMappingURL=bundle.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bundle.js","sourceRoot":"","sources":["../src/bundle.ts"],"names":[],"mappings":"AAAA,6FAA6F;AAC7F,kGAAkG;AAClG,oFAAoF;AACpF,OAAO,EAA8B,cAAc,EAAE,MAAM,8BAA8B,CAAC","sourcesContent":["// @statewalker/cellb/bundle: a project's sources bundled in the browser, for `loadProject`'s\n// `compile`. It needs the optional peer dependency @statewalker/webrun-bundler, and esbuild-wasm,\n// which the caller initializes and passes in (its .wasm URL is the app's to serve).\nexport { type BundleCompilerOptions, bundleCompiler } from \"./project/bundle-compiler.js\";\nexport type { CompiledProject, ProjectCompiler } from \"./project/source-project.js\";\n"]}
@@ -7,6 +7,13 @@ import { DurableObjectState } from "./state.js";
7
7
  * The request as the object sees it: its signal also aborts when the host closes (the runtime
8
8
  * shuts down), as on Cloudflare when the client goes away; a long poll or an SSE stream that
9
9
  * waits on it then ends instead of running on into a closed database.
10
+ *
11
+ * The request is not copied: its `signal` becomes a getter that builds the merged signal the
12
+ * first time it is read. Copying a Request and merging two signals cost about 7 µs a request, as
13
+ * much as a small handler's whole turn, and most handlers never read the signal. The request is
14
+ * the caller's own object (`runtime.fetch`) or a stub's fresh copy (a Durable Object's `fetch`);
15
+ * `cf` and the upgrade's `headers` that cellb sets on it stay as they are. A copy the handler
16
+ * makes itself (`new Request(req)`) takes the request's own signal, without the host's.
10
17
  */
11
18
  export declare function closingWith(req: Request, closing: AbortSignal): Request;
12
19
  /** The object's host was closed for good: its storage and events fail with this. */
@@ -11,19 +11,52 @@ import { DurableObjectStorage, SyncKvStorage } from "./storage.js";
11
11
  * The request as the object sees it: its signal also aborts when the host closes (the runtime
12
12
  * shuts down), as on Cloudflare when the client goes away; a long poll or an SSE stream that
13
13
  * waits on it then ends instead of running on into a closed database.
14
+ *
15
+ * The request is not copied: its `signal` becomes a getter that builds the merged signal the
16
+ * first time it is read. Copying a Request and merging two signals cost about 7 µs a request, as
17
+ * much as a small handler's whole turn, and most handlers never read the signal. The request is
18
+ * the caller's own object (`runtime.fetch`) or a stub's fresh copy (a Durable Object's `fetch`);
19
+ * `cf` and the upgrade's `headers` that cellb sets on it stay as they are. A copy the handler
20
+ * makes itself (`new Request(req)`) takes the request's own signal, without the host's.
14
21
  */
15
22
  export function closingWith(req, closing) {
16
23
  if (closing.aborted)
17
24
  return req;
18
- const r = new Request(req, { signal: AbortSignal.any([req.signal, closing]) });
19
- // What cellb set on the request itself (`cf`; `headers` carrying a WebSocket upgrade's
20
- // headers, which a Request would drop) stays as it was.
21
- for (const k of ["cf", "headers"]) {
22
- const d = Object.getOwnPropertyDescriptor(req, k);
25
+ const own = signalOf(req);
26
+ let merged;
27
+ try {
28
+ Object.defineProperty(req, "signal", {
29
+ configurable: true,
30
+ enumerable: false,
31
+ get: () => {
32
+ if (!merged) {
33
+ const before = own();
34
+ merged = before ? AbortSignal.any([before, closing]) : closing;
35
+ }
36
+ return merged;
37
+ },
38
+ });
39
+ return req;
40
+ }
41
+ catch {
42
+ // A request whose `signal` cannot be redefined: a copy with the merged signal, as before.
43
+ const r = new Request(req, { signal: AbortSignal.any([req.signal, closing]) });
44
+ for (const k of ["cf", "headers"]) {
45
+ const d = Object.getOwnPropertyDescriptor(req, k);
46
+ if (d)
47
+ Object.defineProperty(r, k, d);
48
+ }
49
+ return r;
50
+ }
51
+ }
52
+ /** Reads `req.signal` as it is now: a getter set by an earlier `closingWith`, or the Request's own. */
53
+ function signalOf(req) {
54
+ for (let o = req; o; o = Object.getPrototypeOf(o)) {
55
+ const d = Object.getOwnPropertyDescriptor(o, "signal");
23
56
  if (d)
24
- Object.defineProperty(r, k, d);
57
+ return d.get ? () => d.get?.call(req) : () => d.value;
25
58
  }
26
- return r;
59
+ return () => undefined;
27
60
  }
28
61
  /** The object's host was closed for good: its storage and events fail with this. */
29
62
  export class ObjectClosedError extends Error {