@mcp-b/do-runtime 0.3.4 → 0.3.6

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.
@@ -0,0 +1 @@
1
+ export * from "./src/api/cloudflare-workers.js";
package/dist/gate.js CHANGED
@@ -1,54 +1,72 @@
1
- import { c as tryCurrentSlice, n as atCheckpointEnd } from "./chunks/io-context-BV4kxxAv.js";
1
+ import { l as tryCurrentContinuation, r as atCheckpointEnd, u as tryCurrentIoContext } from "./chunks/io-context-RmmjNtwm.js";
2
2
  //#region src/gate.ts
3
- var continuationContext;
4
3
  var TRANSFORMED_AWAIT = Symbol("@mcp-b/do-runtime/transformed-await");
4
+ /**
5
+ * Own the gap between publishing an await result and its `__resumeAwait` call.
6
+ * This is deliberately separate from the current-continuation ambient: a
7
+ * reservation serializes publishers but must never make its actor look current.
8
+ * See §2.3 and decision 8.
9
+ */
10
+ var CURRENT_PUBLICATION = Symbol.for("@mcp-b/do-runtime/current-await-publication");
11
+ var warnedUngatedAwaits = /* @__PURE__ */ new Set();
5
12
  function isThenable(value) {
6
13
  return (typeof value === "object" && value !== null || typeof value === "function") && typeof Reflect.get(value, "then") === "function";
7
14
  }
8
15
  /** Re-enter the actor that owns this transformed await; fail open outside actors. */
9
16
  function __gate(value) {
10
- const context = tryCurrentSlice() ?? continuationContext?.context;
17
+ const context = tryCurrentIoContext();
11
18
  if (!isThenable(value) && context === void 0) return value;
12
19
  if (context === void 0) return value;
13
20
  return resumeWithContext(context, Promise.resolve(value));
14
21
  }
15
22
  /** Capture an actor await without publishing its context before the continuation runs. */
16
- function __gateAwait(value) {
17
- const context = tryCurrentSlice() ?? continuationContext?.context;
18
- if (context === void 0) return value;
23
+ function __gateAwait(value, developmentSource) {
24
+ const context = tryCurrentIoContext();
25
+ if (context === void 0) {
26
+ if (developmentSource !== void 0 && !warnedUngatedAwaits.has(developmentSource)) {
27
+ warnedUngatedAwaits.add(developmentSource);
28
+ console.warn(`do-runtime: transformed await in ${developmentSource} ran without an actor input lock; an earlier await or entry path is not gated`);
29
+ }
30
+ return value;
31
+ }
19
32
  return resumeAwaitWithContext(context, Promise.resolve(value));
20
33
  }
21
34
  /** Restore the captured actor at the first instruction after a transformed await. */
22
35
  function __resumeAwait(value) {
23
36
  if (!isTransformedAwait(value)) return value;
24
- restoreContinuation(value.context);
37
+ clearPublication(value.reservation);
38
+ value.context.restoreContinuation();
25
39
  if (value.outcome.ok) return value.outcome.value;
26
40
  throw value.outcome.exception;
27
41
  }
28
42
  function isTransformedAwait(value) {
29
43
  return Reflect.get(Object(value), TRANSFORMED_AWAIT) === true;
30
44
  }
31
- function restoreContinuation(context) {
32
- const token = {};
33
- continuationContext = {
34
- context,
35
- token
36
- };
37
- atCheckpointEnd(() => {
38
- if (continuationContext?.token === token) continuationContext = void 0;
39
- });
45
+ function currentPublication() {
46
+ return Reflect.get(globalThis, CURRENT_PUBLICATION);
47
+ }
48
+ function reservePublication(context) {
49
+ if (tryCurrentContinuation() !== void 0 || currentPublication() !== void 0) return void 0;
50
+ const reservation = { context };
51
+ Reflect.set(globalThis, CURRENT_PUBLICATION, reservation);
52
+ atCheckpointEnd(() => clearPublication(reservation));
53
+ return reservation;
54
+ }
55
+ function clearPublication(reservation) {
56
+ if (currentPublication() === reservation) Reflect.deleteProperty(globalThis, CURRENT_PUBLICATION);
40
57
  }
41
58
  function publishOutcome(context, promise, finish) {
42
59
  return new Promise((resolve, reject) => {
43
60
  const publish = context.makeTransformReentryCallback((outcome) => {
44
- if (continuationContext !== void 0) {
61
+ const reservation = reservePublication(context);
62
+ if (reservation === void 0) {
45
63
  schedulePublication({
46
64
  publish: () => publish(outcome),
47
65
  reject
48
66
  });
49
67
  return;
50
68
  }
51
- resolve(finish(outcome));
69
+ resolve(finish(outcome, reservation));
52
70
  });
53
71
  promise.then((value) => {
54
72
  schedulePublication({
@@ -70,15 +88,17 @@ function publishOutcome(context, promise, finish) {
70
88
  });
71
89
  }
72
90
  function resumeAwaitWithContext(context, promise) {
73
- return publishOutcome(context, promise, (outcome) => ({
91
+ return publishOutcome(context, promise, (outcome, reservation) => ({
74
92
  [TRANSFORMED_AWAIT]: true,
75
93
  context,
76
- outcome
94
+ outcome,
95
+ reservation
77
96
  }));
78
97
  }
79
98
  function resumeWithContext(context, promise) {
80
- return publishOutcome(context, promise, (outcome) => {
81
- restoreContinuation(context);
99
+ return publishOutcome(context, promise, (outcome, reservation) => {
100
+ clearPublication(reservation);
101
+ context.restoreContinuation();
82
102
  if (outcome.ok) return outcome.value;
83
103
  throw outcome.exception;
84
104
  });
package/dist/gate.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"gate.js","names":[],"sources":["../src/gate.ts"],"sourcesContent":["/* @do-runtime-gated */\n\nimport { atCheckpointEnd, tryCurrentSlice, type IoContext } from \"./io/io-context\";\n\ntype ContinuationContext = {\n readonly context: IoContext;\n readonly token: object;\n};\n\nlet continuationContext: ContinuationContext | undefined;\n\ntype Publication = {\n readonly publish: () => Promise<void>;\n readonly reject: (exception: unknown) => void;\n};\n\ntype Outcome<T> =\n | { readonly ok: true; readonly value: T }\n | { readonly ok: false; readonly exception: unknown };\n\nconst TRANSFORMED_AWAIT = Symbol(\"@mcp-b/do-runtime/transformed-await\");\n\ntype TransformedAwait<T> = {\n readonly [TRANSFORMED_AWAIT]: true;\n readonly context: IoContext;\n readonly outcome: Outcome<T>;\n};\n\nfunction isThenable(value: unknown): value is PromiseLike<unknown> {\n return (\n (typeof value === \"object\" && value !== null) ||\n typeof value === \"function\"\n ) && typeof Reflect.get(value, \"then\") === \"function\";\n}\n\n/** Re-enter the actor that owns this transformed await; fail open outside actors. */\nexport function __gate<T>(value: T): T | Promise<Awaited<T>> {\n const context = tryCurrentSlice() ?? continuationContext?.context;\n if (!isThenable(value) && context === undefined) return value;\n if (context === undefined) return value;\n return resumeWithContext(context, Promise.resolve(value));\n}\n\n/** Capture an actor await without publishing its context before the continuation runs. */\nexport function __gateAwait<T>(value: T): T | Promise<TransformedAwait<Awaited<T>>> {\n const context = tryCurrentSlice() ?? continuationContext?.context;\n if (context === undefined) return value;\n return resumeAwaitWithContext(context, Promise.resolve(value));\n}\n\n/** Restore the captured actor at the first instruction after a transformed await. */\nexport function __resumeAwait<T>(value: T | TransformedAwait<T>): T {\n if (!isTransformedAwait(value)) return value as T;\n\n restoreContinuation(value.context);\n if (value.outcome.ok) return value.outcome.value;\n throw value.outcome.exception;\n}\n\nfunction isTransformedAwait<T>(value: T | TransformedAwait<T>): value is TransformedAwait<T> {\n return Reflect.get(Object(value), TRANSFORMED_AWAIT) === true;\n}\n\nfunction restoreContinuation(context: IoContext): void {\n const token = {};\n continuationContext = { context, token };\n atCheckpointEnd(() => {\n if (continuationContext?.token === token) continuationContext = undefined;\n });\n}\n\nfunction publishOutcome<T, Result>(\n context: IoContext,\n promise: Promise<T>,\n finish: (outcome: Outcome<T>) => Result,\n): Promise<Result> {\n return new Promise<Result>((resolve, reject) => {\n const publish = context.makeTransformReentryCallback((outcome: Outcome<T>) => {\n if (continuationContext !== undefined) {\n schedulePublication({ publish: () => publish(outcome), reject });\n return;\n }\n resolve(finish(outcome));\n });\n void promise.then(\n (value) => {\n schedulePublication({ publish: () => publish({ ok: true, value }), reject });\n },\n (exception: unknown) => {\n schedulePublication({ publish: () => publish({ ok: false, exception }), reject });\n },\n );\n });\n}\n\nfunction resumeAwaitWithContext<T>(\n context: IoContext,\n promise: Promise<T>,\n): Promise<TransformedAwait<T>> {\n return publishOutcome(context, promise, (outcome) => ({\n [TRANSFORMED_AWAIT]: true,\n context,\n outcome,\n }));\n}\n\nfunction resumeWithContext<T>(context: IoContext, promise: Promise<T>): Promise<T> {\n return publishOutcome(context, promise, (outcome) => {\n restoreContinuation(context);\n if (outcome.ok) return outcome.value;\n throw outcome.exception;\n });\n}\n\n/**\n * Resolve one transformed await per task, inside a fresh actor slice. Admission\n * attempts are independent so a blocked actor cannot stall the actor that will\n * unblock it. The task boundary keeps each continuation ambient isolated.\n */\nfunction schedulePublication(publication: Publication): void {\n const channel = new MessageChannel();\n channel.port1.onmessage = () => {\n channel.port1.close();\n channel.port2.close();\n\n void publication.publish().catch((exception: unknown) => {\n publication.reject(exception);\n });\n };\n channel.port2.postMessage(undefined);\n}\n\nfunction iteratorFor<T>(iterable: AsyncIterable<T> | Iterable<T>): AsyncIterator<T> | Iterator<T> {\n const subject = Object(iterable);\n const asyncIterator: unknown = Reflect.get(subject, Symbol.asyncIterator);\n if (typeof asyncIterator === \"function\") return Reflect.apply(asyncIterator, iterable, []);\n const iterator: unknown = Reflect.get(subject, Symbol.iterator);\n if (typeof iterator === \"function\") return Reflect.apply(iterator, iterable, []);\n throw new TypeError(\"value is not async iterable or iterable\");\n}\n\nfunction gatedIterator<T>(iterable: AsyncIterable<T> | Iterable<T>): AsyncIterator<T> {\n const iterator = iteratorFor(iterable);\n\n function invoke(methodName: \"next\" | \"return\" | \"throw\", args: unknown[]): Promise<IteratorResult<T>> {\n const method: unknown = Reflect.get(iterator, methodName);\n if (typeof method === \"function\") {\n return Promise.resolve(__gate(Reflect.apply(method, iterator, args)));\n }\n if (methodName === \"throw\") return Promise.reject(args[0]);\n return Promise.resolve({ done: true, value: args[0] });\n }\n\n return {\n next: (...args: [] | [unknown]) => invoke(\"next\", args),\n return: (value?: unknown) => invoke(\"return\", [value]),\n throw: (exception?: unknown) => invoke(\"throw\", [exception]),\n };\n}\n\n/** Gate every operation used by `for await`, including early return and throw. */\nexport function __gateAsyncIterable<T, IterableType extends AsyncIterable<T> | Iterable<T>>(\n iterable: IterableType,\n): IterableType;\nexport function __gateAsyncIterable<T>(\n iterable: AsyncIterable<T> | Iterable<T>,\n): AsyncIterable<T> | Iterable<T> {\n const wrapper: AsyncIterable<T> = {\n [Symbol.asyncIterator]: () => gatedIterator(iterable),\n };\n if ((typeof iterable !== \"object\" || iterable === null) && typeof iterable !== \"function\") {\n return wrapper;\n }\n return new Proxy(iterable, {\n get(target, property, receiver): unknown {\n if (property === Symbol.asyncIterator) return wrapper[Symbol.asyncIterator];\n return Reflect.get(target, property, receiver);\n },\n });\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"gate.js","names":[],"sources":["../src/gate.ts"],"sourcesContent":["/* @do-runtime-gated */\n\nimport {\n atCheckpointEnd,\n tryCurrentContinuation,\n tryCurrentIoContext,\n type IoContext,\n} from \"./io/io-context\";\n\ntype Publication = {\n readonly publish: () => Promise<void>;\n readonly reject: (exception: unknown) => void;\n};\n\ntype Outcome<T> =\n | { readonly ok: true; readonly value: T }\n | { readonly ok: false; readonly exception: unknown };\n\nconst TRANSFORMED_AWAIT = Symbol(\"@mcp-b/do-runtime/transformed-await\");\n/**\n * Own the gap between publishing an await result and its `__resumeAwait` call.\n * This is deliberately separate from the current-continuation ambient: a\n * reservation serializes publishers but must never make its actor look current.\n * See §2.3 and decision 8.\n */\nconst CURRENT_PUBLICATION = Symbol.for(\"@mcp-b/do-runtime/current-await-publication\");\nconst warnedUngatedAwaits = new Set<string>();\n\ntype PublicationReservation = {\n readonly context: IoContext;\n};\n\ntype TransformedAwait<T> = {\n readonly [TRANSFORMED_AWAIT]: true;\n readonly context: IoContext;\n readonly outcome: Outcome<T>;\n readonly reservation: PublicationReservation;\n};\n\nfunction isThenable(value: unknown): value is PromiseLike<unknown> {\n return (\n (typeof value === \"object\" && value !== null) ||\n typeof value === \"function\"\n ) && typeof Reflect.get(value, \"then\") === \"function\";\n}\n\n/** Re-enter the actor that owns this transformed await; fail open outside actors. */\nexport function __gate<T>(value: T): T | Promise<Awaited<T>> {\n const context = tryCurrentIoContext();\n if (!isThenable(value) && context === undefined) return value;\n if (context === undefined) return value;\n return resumeWithContext(context, Promise.resolve(value));\n}\n\n/** Capture an actor await without publishing its context before the continuation runs. */\nexport function __gateAwait<T>(\n value: T,\n developmentSource?: string,\n): T | Promise<TransformedAwait<Awaited<T>>> {\n const context = tryCurrentIoContext();\n if (context === undefined) {\n if (developmentSource !== undefined && !warnedUngatedAwaits.has(developmentSource)) {\n warnedUngatedAwaits.add(developmentSource);\n console.warn(\n `do-runtime: transformed await in ${developmentSource} ran without an actor input lock; ` +\n \"an earlier await or entry path is not gated\",\n );\n }\n return value;\n }\n return resumeAwaitWithContext(context, Promise.resolve(value));\n}\n\n/** Restore the captured actor at the first instruction after a transformed await. */\nexport function __resumeAwait<T>(value: T | TransformedAwait<T>): T {\n if (!isTransformedAwait(value)) return value as T;\n\n clearPublication(value.reservation);\n value.context.restoreContinuation();\n if (value.outcome.ok) return value.outcome.value;\n throw value.outcome.exception;\n}\n\nfunction isTransformedAwait<T>(value: T | TransformedAwait<T>): value is TransformedAwait<T> {\n return Reflect.get(Object(value), TRANSFORMED_AWAIT) === true;\n}\n\nfunction currentPublication(): PublicationReservation | undefined {\n return Reflect.get(globalThis, CURRENT_PUBLICATION) as PublicationReservation | undefined;\n}\n\nfunction reservePublication(context: IoContext): PublicationReservation | undefined {\n if (tryCurrentContinuation() !== undefined || currentPublication() !== undefined) return undefined;\n const reservation = { context };\n Reflect.set(globalThis, CURRENT_PUBLICATION, reservation);\n atCheckpointEnd(() => clearPublication(reservation));\n return reservation;\n}\n\nfunction clearPublication(reservation: PublicationReservation): void {\n if (currentPublication() === reservation) {\n Reflect.deleteProperty(globalThis, CURRENT_PUBLICATION);\n }\n}\n\nfunction publishOutcome<T, Result>(\n context: IoContext,\n promise: Promise<T>,\n finish: (outcome: Outcome<T>, reservation: PublicationReservation) => Result,\n): Promise<Result> {\n return new Promise<Result>((resolve, reject) => {\n const publish = context.makeTransformReentryCallback((outcome: Outcome<T>) => {\n const reservation = reservePublication(context);\n if (reservation === undefined) {\n schedulePublication({ publish: () => publish(outcome), reject });\n return;\n }\n resolve(finish(outcome, reservation));\n });\n void promise.then(\n (value) => {\n schedulePublication({ publish: () => publish({ ok: true, value }), reject });\n },\n (exception: unknown) => {\n schedulePublication({ publish: () => publish({ ok: false, exception }), reject });\n },\n );\n });\n}\n\nfunction resumeAwaitWithContext<T>(\n context: IoContext,\n promise: Promise<T>,\n): Promise<TransformedAwait<T>> {\n return publishOutcome(context, promise, (outcome, reservation) => ({\n [TRANSFORMED_AWAIT]: true,\n context,\n outcome,\n reservation,\n }));\n}\n\nfunction resumeWithContext<T>(context: IoContext, promise: Promise<T>): Promise<T> {\n return publishOutcome(context, promise, (outcome, reservation) => {\n clearPublication(reservation);\n context.restoreContinuation();\n if (outcome.ok) return outcome.value;\n throw outcome.exception;\n });\n}\n\n/**\n * Resolve one transformed await per task, inside a fresh actor slice. Admission\n * attempts are independent so a blocked actor cannot stall the actor that will\n * unblock it. The task boundary keeps each continuation ambient isolated.\n */\nfunction schedulePublication(publication: Publication): void {\n const channel = new MessageChannel();\n channel.port1.onmessage = () => {\n channel.port1.close();\n channel.port2.close();\n\n void publication.publish().catch((exception: unknown) => {\n publication.reject(exception);\n });\n };\n channel.port2.postMessage(undefined);\n}\n\nfunction iteratorFor<T>(iterable: AsyncIterable<T> | Iterable<T>): AsyncIterator<T> | Iterator<T> {\n const subject = Object(iterable);\n const asyncIterator: unknown = Reflect.get(subject, Symbol.asyncIterator);\n if (typeof asyncIterator === \"function\") return Reflect.apply(asyncIterator, iterable, []);\n const iterator: unknown = Reflect.get(subject, Symbol.iterator);\n if (typeof iterator === \"function\") return Reflect.apply(iterator, iterable, []);\n throw new TypeError(\"value is not async iterable or iterable\");\n}\n\nfunction gatedIterator<T>(iterable: AsyncIterable<T> | Iterable<T>): AsyncIterator<T> {\n const iterator = iteratorFor(iterable);\n\n function invoke(methodName: \"next\" | \"return\" | \"throw\", args: unknown[]): Promise<IteratorResult<T>> {\n const method: unknown = Reflect.get(iterator, methodName);\n if (typeof method === \"function\") {\n return Promise.resolve(__gate(Reflect.apply(method, iterator, args)));\n }\n if (methodName === \"throw\") return Promise.reject(args[0]);\n return Promise.resolve({ done: true, value: args[0] });\n }\n\n return {\n next: (...args: [] | [unknown]) => invoke(\"next\", args),\n return: (value?: unknown) => invoke(\"return\", [value]),\n throw: (exception?: unknown) => invoke(\"throw\", [exception]),\n };\n}\n\n/** Gate every operation used by `for await`, including early return and throw. */\nexport function __gateAsyncIterable<T, IterableType extends AsyncIterable<T> | Iterable<T>>(\n iterable: IterableType,\n): IterableType;\nexport function __gateAsyncIterable<T>(\n iterable: AsyncIterable<T> | Iterable<T>,\n): AsyncIterable<T> | Iterable<T> {\n const wrapper: AsyncIterable<T> = {\n [Symbol.asyncIterator]: () => gatedIterator(iterable),\n };\n if ((typeof iterable !== \"object\" || iterable === null) && typeof iterable !== \"function\") {\n return wrapper;\n }\n return new Proxy(iterable, {\n get(target, property, receiver): unknown {\n if (property === Symbol.asyncIterator) return wrapper[Symbol.asyncIterator];\n return Reflect.get(target, property, receiver);\n },\n });\n}\n"],"mappings":"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"}
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { a as isExceptionFromInputGateBroken, c as tryCurrentSlice, i as hasUserErrorDetail, l as InputGate, n as atCheckpointEnd, o as requireInputLock, r as captureGateStack, s as setUserErrorDetail, t as IoContext, u as OutputGate } from "./chunks/io-context-BV4kxxAv.js";
1
+ import { a as hasUserErrorDetail, c as setUserErrorDetail, d as tryCurrentSlice, f as CanceledError, i as captureGateStack, m as OutputGate, n as IoContext, o as isExceptionFromInputGateBroken, p as InputGate, r as atCheckpointEnd, s as requireInputLock, t as BrokenActorError, u as tryCurrentIoContext } from "./chunks/io-context-RmmjNtwm.js";
2
2
  import { RpcTarget as RpcTarget$1 } from "./cloudflare-workers.js";
3
3
  import { a as getInt64, c as isNull, i as getBlob, o as getText, r as SqliteDatabase, s as hasCurrentSqliteTable } from "./chunks/sqlite-DFg92Tgt.js";
4
4
  import { ALARM_RETRY_MAX_TRIES, ALARM_RETRY_START_SECONDS, AlarmScheduler, RETRY_BACKOFF_MAX, RETRY_JITTER_FACTOR, alarmRetryDelayMs } from "./server/alarm-scheduler.js";
@@ -1366,70 +1366,6 @@ function asRawRow(values) {
1366
1366
  return values;
1367
1367
  }
1368
1368
  //#endregion
1369
- //#region src/api/sync-kv.ts
1370
- var SyncKvStorage = class {
1371
- #ctx;
1372
- #owner;
1373
- constructor(ctx, owner) {
1374
- this.#ctx = ctx;
1375
- this.#owner = owner;
1376
- }
1377
- get(key) {
1378
- requireInputLock(this.#ctx, "kv.get()");
1379
- const value = this.#owner.getSqliteKv().get(key);
1380
- if (value === void 0) return void 0;
1381
- return deserializeValue(key, value);
1382
- }
1383
- /**
1384
- * ← `SyncKvStorage::list`, which reuses `compileListOptions` — "This is public
1385
- * so that SyncKvStorage can reuse it."
1386
- */
1387
- list(options) {
1388
- requireInputLock(this.#ctx, "kv.list()");
1389
- const compiled = compileListOptions(options);
1390
- if (compiled === void 0) return { [Symbol.iterator]: () => emptyIterator() };
1391
- const cursor = this.#owner.getSqliteKv().list(compiled.start, compiled.end, compiled.limit, compiled.reverse ? "REVERSE" : "FORWARD");
1392
- return { [Symbol.iterator]: () => listIterator(cursor) };
1393
- }
1394
- put(key, value) {
1395
- requireInputLock(this.#ctx, "kv.put()");
1396
- this.#owner.getSqliteKv().put(key, serializeValue(key, value));
1397
- }
1398
- delete(key) {
1399
- requireInputLock(this.#ctx, "kv.delete()");
1400
- return this.#owner.getSqliteKv().delete(key);
1401
- }
1402
- };
1403
- /** ← `SyncKvStorage::listNext`, whose cancellation branch is the reason it is not a plain loop. */
1404
- function listIterator(cursor) {
1405
- const iterator = {
1406
- [Symbol.iterator]: () => iterator,
1407
- next: () => {
1408
- const pair = cursor.next();
1409
- if (pair !== void 0) return {
1410
- done: false,
1411
- value: [pair.key, deserializeValue(pair.key, pair.value)]
1412
- };
1413
- if (cursor.wasCanceled()) throw new Error("kv.list() iterator was invalidated because a new call to kv.list() was started. Only one kv.list() iterator can exist at a time.");
1414
- return {
1415
- done: true,
1416
- value: void 0
1417
- };
1418
- }
1419
- };
1420
- return iterator;
1421
- }
1422
- function emptyIterator() {
1423
- const iterator = {
1424
- [Symbol.iterator]: () => iterator,
1425
- next: () => ({
1426
- done: true,
1427
- value: void 0
1428
- })
1429
- };
1430
- return iterator;
1431
- }
1432
- //#endregion
1433
1369
  //#region src/api/actor-state.ts
1434
1370
  /**
1435
1371
  * ← workerd `src/workerd/api/actor-state.{h,c++}`
@@ -1441,8 +1377,8 @@ function emptyIterator() {
1441
1377
  * **`DurableObjectStorage` satisfies workers-types with no cast (§2.4).** That
1442
1378
  * was checked rather than asserted, and two shapes here exist only because it
1443
1379
  * has to: `sql.Cursor` and `sql.Statement` must be constructible with no
1444
- * arguments (see `sql.ts`), and `storage.kv` is required, which is why
1445
- * `api/sync-kv.ts` exists at all. The narrowings that remain are all one thing —
1380
+ * arguments (see `sql.ts`), and `storage.kv` is required. The narrowings that
1381
+ * remain are all one thing —
1446
1382
  * `get<T>` returns the caller's claim about the shape of a value SQLite handed
1447
1383
  * back as bytes, which no check can confirm and which upstream states the same
1448
1384
  * way, as a `jsg::JsRef<jsg::JsValue>` behind a `JSG_TS_OVERRIDE`'d
@@ -1452,8 +1388,7 @@ function emptyIterator() {
1452
1388
  * That is upstream's: a `JSG_REQUIRE` inside a method returning `jsg::Promise`
1453
1389
  * throws into the isolate before the promise exists, so `put(k, undefined)`
1454
1390
  * throws rather than rejecting. The same goes for a value that will not decode,
1455
- * because §1.4 makes the SQLite path take `transformCacheResult`'s value arm and
1456
- * run the decoder synchronously.
1391
+ * because §1.4 makes the SQLite path run the decoder before `Promise.resolve`.
1457
1392
  *
1458
1393
  * **What the input gate does and does not do here.** Every entry point calls
1459
1394
  * `requireInputLock` — see its comment in `io/io-context.ts`, which is the one
@@ -1465,13 +1400,10 @@ function emptyIterator() {
1465
1400
  * section.
1466
1401
  *
1467
1402
  * **Decision 2's branch has one reachable site**, and it is not where upstream's
1468
- * is. `transformCacheResult` branches on `allowConcurrency` because upstream's
1469
- * `ActorCacheOps` returns `kj::OneOf<T, kj::Promise<T>>`; §1.4 measures that the
1470
- * SQLite arm is always the immediate one, so Section 4 collapsed the `OneOf` and
1471
- * the branch has nothing to select between. `transformMaybeBackpressure` keeps
1472
- * it, because `DeleteAllResults.backpressure` is still a promise in
1473
- * `io/actor-cache.ts`. Both helpers are kept under upstream's names so the
1474
- * question "where did `allowConcurrency` go" is answered by reading them.
1403
+ * is. §1.4 measures that SQLite cache operations are immediate, so their
1404
+ * `kj::OneOf<T, kj::Promise<T>>` branch has nothing to select between.
1405
+ * `transformMaybeBackpressure` keeps the branch because
1406
+ * `DeleteAllResults.backpressure` is still a promise in `io/actor-cache.ts`.
1475
1407
  *
1476
1408
  * Not ported, because the substrate has no equivalent: Hibernatable WebSockets,
1477
1409
  * which is the whole reason `DurableObjectState`'s eight WebSocket methods are
@@ -1546,7 +1478,7 @@ var VALUE_CODEC_HEADER = new Uint8Array([
1546
1478
  * The short header keeps the new representation unambiguous while old JSON rows
1547
1479
  * remain readable.
1548
1480
  */
1549
- function serializeValue(_key, value) {
1481
+ function serializeValue(value) {
1550
1482
  const body = textEncoder.encode(JSON.stringify(serialize(value)));
1551
1483
  const encoded = new Uint8Array(VALUE_CODEC_HEADER.byteLength + body.byteLength);
1552
1484
  encoded.set(VALUE_CODEC_HEADER);
@@ -1573,26 +1505,6 @@ function deserializeValue(key, buffer) {
1573
1505
  throw new Error(`actor storage deserialization failed: failed to deserialize stored value; key = ${key}; size = ${buffer.byteLength}`, { cause: exception });
1574
1506
  }
1575
1507
  }
1576
- /** ← `deserializeMaybeV8Value`. */
1577
- function deserializeMaybeValue(key, buffer) {
1578
- return buffer === void 0 ? void 0 : deserializeValue(key, buffer);
1579
- }
1580
- /**
1581
- * ← `transformCacheResult` and `transformCacheResultWithCacheStatus`
1582
- * (`actor-state.c++:49-101`), with the arm that cannot happen removed.
1583
- *
1584
- * Upstream's body is a two-arm switch on `kj::OneOf<T, kj::Promise<T>>`, and the
1585
- * `allowConcurrency` branch lives in the promise arm. §1.4 measures that a
1586
- * SQLite-backed actor returns the immediate arm at every call site, so Section 4
1587
- * collapsed the `OneOf` to `T` and there is no promise left to await — and
1588
- * therefore no gate decision to make. The name is kept so a reader comparing the
1589
- * two files finds the answer here rather than inferring an omission. The
1590
- * `WithCacheStatus` variant differs only in a `cached` flag feeding billing
1591
- * counters that have no port, so the two collapse to one function.
1592
- */
1593
- function transformCacheResult(value, func) {
1594
- return Promise.resolve(func(value));
1595
- }
1596
1508
  /**
1597
1509
  * ← `transformMaybeBackpressure` (`actor-state.c++:103-119`). THIS is decision
1598
1510
  * 2's live site: `DeleteAllResults.backpressure` is still `Promise<void> |
@@ -1611,8 +1523,8 @@ function transformMaybeBackpressure(ctx, options, maybeBackpressure) {
1611
1523
  /**
1612
1524
  * ← `DurableObjectStorageOperations::compileListOptions`
1613
1525
  * (`actor-state.c++:314-417`). Returns undefined if the list operation would
1614
- * provably return no results. Public because `SyncKvStorage` reuses it, exactly
1615
- * as upstream's comment says it must.
1526
+ * provably return no results. `SyncKvStorage` reuses it, exactly as upstream's
1527
+ * comment says it must.
1616
1528
  *
1617
1529
  * Two translations. `startAfter` gains ONE null character where upstream's
1618
1530
  * `kj::String` gains two, because the second of upstream's is the terminator and
@@ -1671,6 +1583,51 @@ function firstKeyAfterPrefix(prefix) {
1671
1583
  return head.slice(0, -1) + String.fromCharCode(head.charCodeAt(head.length - 1) + 1);
1672
1584
  }
1673
1585
  /**
1586
+ * ← workerd `src/workerd/api/sync-kv.{h,c++}`. The synchronous surface lives
1587
+ * beside the asynchronous storage owner because both share the same codec and
1588
+ * list-option compiler over one `SqliteKv`.
1589
+ */
1590
+ var SyncKvStorage = class {
1591
+ #ctx;
1592
+ #kv;
1593
+ constructor(ctx, kv) {
1594
+ this.#ctx = ctx;
1595
+ this.#kv = kv;
1596
+ }
1597
+ get(key) {
1598
+ requireInputLock(this.#ctx, "kv.get()");
1599
+ const value = this.#kv.get(key);
1600
+ if (value === void 0) return void 0;
1601
+ return deserializeValue(key, value);
1602
+ }
1603
+ list(options) {
1604
+ requireInputLock(this.#ctx, "kv.list()");
1605
+ const compiled = compileListOptions(options);
1606
+ if (compiled === void 0) return [];
1607
+ return listIterator(this.#kv.list(compiled.start, compiled.end, compiled.limit, compiled.reverse ? "REVERSE" : "FORWARD"));
1608
+ }
1609
+ put(key, value) {
1610
+ requireInputLock(this.#ctx, "kv.put()");
1611
+ this.#kv.put(key, serializeValue(value));
1612
+ }
1613
+ delete(key) {
1614
+ requireInputLock(this.#ctx, "kv.delete()");
1615
+ return this.#kv.delete(key);
1616
+ }
1617
+ };
1618
+ /** ← `SyncKvStorage::listNext`, whose cancellation branch is the reason it is not a plain loop. */
1619
+ function* listIterator(cursor) {
1620
+ for (;;) {
1621
+ const pair = cursor.next();
1622
+ if (pair !== void 0) {
1623
+ yield [pair.key, deserializeValue(pair.key, pair.value)];
1624
+ continue;
1625
+ }
1626
+ if (cursor.wasCanceled()) throw new Error("kv.list() iterator was invalidated because a new call to kv.list() was started. Only one kv.list() iterator can exist at a time.");
1627
+ return;
1628
+ }
1629
+ }
1630
+ /**
1674
1631
  * ← `DurableObjectStorageOperations`. "Common implementation of
1675
1632
  * DurableObjectStorage and DurableObjectTransaction. This class is designed to
1676
1633
  * be used as a mixin."
@@ -1680,88 +1637,74 @@ var DurableObjectStorageOperations = class {
1680
1637
  constructor(ctx) {
1681
1638
  this.ctx = ctx;
1682
1639
  }
1683
- /** Whether to skip caching and allow concurrency on all operations. */
1684
- useDirectIo() {
1685
- return false;
1686
- }
1687
- /**
1688
- * ← `configureOptions`. Both subclasses answer `useDirectIo()` false, so this
1689
- * is the identity today; it is upstream's hook and the only place the two
1690
- * flags are forced on.
1691
- */
1692
- configureOptions(options) {
1693
- if (!this.useDirectIo()) return options;
1694
- return {
1695
- ...options,
1696
- allowConcurrency: true,
1697
- noCache: true
1698
- };
1699
- }
1700
1640
  get(keyOrKeys, maybeOptions) {
1701
1641
  requireInputLock(this.ctx, OP_GET);
1702
- const options = this.configureOptions({ ...maybeOptions });
1642
+ const options = { ...maybeOptions };
1703
1643
  if (typeof keyOrKeys === "string") return this.#getOne(keyOrKeys, options);
1704
1644
  return this.#getMultiple(keyOrKeys, options);
1705
1645
  }
1706
1646
  getAlarm(maybeOptions) {
1707
1647
  requireInputLock(this.ctx, OP_GET_ALARM);
1708
- const options = this.configureOptions({
1648
+ const options = {
1709
1649
  ...maybeOptions,
1710
1650
  noCache: false
1711
- });
1712
- return transformCacheResult(this.getCache(OP_GET_ALARM).getAlarm(options), (date) => date);
1651
+ };
1652
+ return Promise.resolve(this.getCache(OP_GET_ALARM).getAlarm(options));
1713
1653
  }
1714
1654
  list(maybeOptions) {
1715
1655
  requireInputLock(this.ctx, OP_LIST);
1716
1656
  const compiled = compileListOptions(maybeOptions);
1717
1657
  if (compiled === void 0) return Promise.resolve(/* @__PURE__ */ new Map());
1718
- const options = this.configureOptions({ ...maybeOptions });
1658
+ const options = { ...maybeOptions };
1719
1659
  const cache = this.getCache(OP_LIST);
1720
- return transformCacheResult(compiled.reverse ? cache.listReverse(compiled.start, compiled.end, compiled.limit, options) : cache.list(compiled.start, compiled.end, compiled.limit, options), (rows) => listResultsToMap(rows));
1660
+ const result = compiled.reverse ? cache.listReverse(compiled.start, compiled.end, compiled.limit, options) : cache.list(compiled.start, compiled.end, compiled.limit, options);
1661
+ return Promise.resolve(listResultsToMap(result));
1721
1662
  }
1722
1663
  put(keyOrEntries, valueOrOptions, maybeOptions) {
1723
1664
  requireInputLock(this.ctx, OP_PUT);
1724
1665
  if (typeof keyOrEntries === "string") {
1725
1666
  if (valueOrOptions === void 0) throw new TypeError("put() called with undefined value.");
1726
- return this.#putOne(keyOrEntries, valueOrOptions, this.configureOptions({ ...maybeOptions }));
1667
+ return this.#putOne(keyOrEntries, valueOrOptions, { ...maybeOptions });
1727
1668
  }
1728
- return this.#putMultiple(keyOrEntries, this.configureOptions({ ...valueOrOptions }));
1669
+ return this.#putMultiple(keyOrEntries, { ...valueOrOptions });
1729
1670
  }
1730
1671
  delete(keyOrKeys, maybeOptions) {
1731
1672
  requireInputLock(this.ctx, OP_DELETE);
1732
- const options = this.configureOptions({ ...maybeOptions });
1733
- if (typeof keyOrKeys === "string") return transformCacheResult(this.getCache(OP_DELETE).delete(keyOrKeys, options), (deleted) => deleted);
1734
- return transformCacheResult(this.getCache(OP_DELETE).deleteMultiple(keyOrKeys, options), (count) => count);
1673
+ const options = { ...maybeOptions };
1674
+ if (typeof keyOrKeys === "string") return Promise.resolve(this.getCache(OP_DELETE).delete(keyOrKeys, options));
1675
+ return Promise.resolve(this.getCache(OP_DELETE).deleteMultiple(keyOrKeys, options));
1735
1676
  }
1736
1677
  setAlarm(scheduledTime, maybeOptions) {
1737
1678
  requireInputLock(this.ctx, OP_PUT_ALARM);
1738
1679
  const when = scheduledTime instanceof Date ? scheduledTime.getTime() : scheduledTime;
1739
1680
  if (!(when > 0)) throw new TypeError("setAlarm() cannot be called with an alarm time <= 0");
1740
1681
  this.ctx.getActorOrThrow().assertCanSetAlarm();
1741
- const options = this.configureOptions({
1682
+ const options = {
1742
1683
  ...maybeOptions,
1743
1684
  noCache: false
1744
- });
1685
+ };
1745
1686
  this.getCache(OP_PUT_ALARM).setAlarm(Math.max(when, this.ctx.now()), options);
1746
1687
  return Promise.resolve();
1747
1688
  }
1748
1689
  deleteAlarm(maybeOptions) {
1749
1690
  requireInputLock(this.ctx, OP_DELETE_ALARM);
1750
- const options = this.configureOptions({
1691
+ const options = {
1751
1692
  ...maybeOptions,
1752
1693
  noCache: false
1753
- });
1694
+ };
1754
1695
  this.getCache(OP_DELETE_ALARM).setAlarm(null, options);
1755
1696
  return Promise.resolve();
1756
1697
  }
1757
1698
  #getOne(key, options) {
1758
- return transformCacheResult(this.getCache(OP_GET).get(key, options), (bytes) => deserializeMaybeValue(key, bytes));
1699
+ const value = this.getCache(OP_GET).get(key, options);
1700
+ return Promise.resolve(value === void 0 ? void 0 : deserializeValue(key, value));
1759
1701
  }
1760
1702
  #getMultiple(keys, options) {
1761
- return transformCacheResult(this.getCache(OP_GET).getMultiple(keys, options), (rows) => listResultsToMap(rows));
1703
+ const result = this.getCache(OP_GET).getMultiple(keys, options);
1704
+ return Promise.resolve(listResultsToMap(result));
1762
1705
  }
1763
1706
  #putOne(key, value, options) {
1764
- this.getCache(OP_PUT).put(key, serializeValue(key, value), options);
1707
+ this.getCache(OP_PUT).put(key, serializeValue(value), options);
1765
1708
  return Promise.resolve();
1766
1709
  }
1767
1710
  #putMultiple(entries, options) {
@@ -1770,7 +1713,7 @@ var DurableObjectStorageOperations = class {
1770
1713
  if (value === void 0) continue;
1771
1714
  pairs.push({
1772
1715
  key,
1773
- value: serializeValue(key, value)
1716
+ value: serializeValue(value)
1774
1717
  });
1775
1718
  }
1776
1719
  this.getCache(OP_PUT).putMultiple(pairs, options);
@@ -1799,10 +1742,6 @@ var DurableObjectStorage = class extends DurableObjectStorageOperations {
1799
1742
  getSqliteDb() {
1800
1743
  return this.#cache.getSqliteDatabase();
1801
1744
  }
1802
- /** ← `DurableObjectStorage::getSqliteKv`. */
1803
- getSqliteKv() {
1804
- return this.#cache.getSqliteKv();
1805
- }
1806
1745
  getCache() {
1807
1746
  return this.#cache;
1808
1747
  }
@@ -1813,7 +1752,7 @@ var DurableObjectStorage = class extends DurableObjectStorageOperations {
1813
1752
  }
1814
1753
  /** ← `JSG_LAZY_INSTANCE_PROPERTY(kv, getKv)`. */
1815
1754
  get kv() {
1816
- this.#kv ??= new SyncKvStorage(this.ctx, this);
1755
+ this.#kv ??= new SyncKvStorage(this.ctx, this.#cache.getSqliteKv());
1817
1756
  return this.#kv;
1818
1757
  }
1819
1758
  /**
@@ -1825,7 +1764,7 @@ var DurableObjectStorage = class extends DurableObjectStorageOperations {
1825
1764
  */
1826
1765
  deleteAll(maybeOptions) {
1827
1766
  requireInputLock(this.ctx, "deleteAll()");
1828
- const options = this.configureOptions({ ...maybeOptions });
1767
+ const options = { ...maybeOptions };
1829
1768
  const result = this.#cache.deleteAll(options, { deleteAlarm: true });
1830
1769
  return transformMaybeBackpressure(this.ctx, options, result.backpressure);
1831
1770
  }
@@ -2140,7 +2079,7 @@ var DurableObjectState = class {
2140
2079
  * gated slice.
2141
2080
  */
2142
2081
  blockConcurrencyWhile(callback) {
2143
- return this.#ctx.blockConcurrencyWhile(() => callback());
2082
+ return this.#ctx.blockConcurrencyWhile(callback);
2144
2083
  }
2145
2084
  /**
2146
2085
  * ← `DurableObjectState::abort`. Reset the object, including breaking the
@@ -2490,7 +2429,7 @@ function gateReader(ctx, reader) {
2490
2429
  * "wrap it in awaitIo" would be wrong three ways:
2491
2430
  *
2492
2431
  * - **Timers** capture the critical section at the ARMING call and re-enter
2493
- * through `ctx.run(callback, cs)` when they fire. Not `awaitIo`, deliberately
2432
+ * through `ctx.run(callback, { input: cs })` when they fire. Not `awaitIo`, deliberately
2494
2433
  * — see `TimeoutManager` in `io/io-context.ts` for upstream's own reason.
2495
2434
  * - **`fetch`** is `awaitIo` (`http.c++` has ten of them and zero
2496
2435
  * `awaitIoWithInputLock`), preceded by an output-gate wait so nothing departs
@@ -2996,7 +2935,7 @@ var AcceptedWebSocket = class extends EventTarget {
2996
2935
  this.dispatchEvent(delivered);
2997
2936
  const handler = this[`on${type}`];
2998
2937
  handler?.(delivered);
2999
- }, this.#criticalSection));
2938
+ }, { input: this.#criticalSection }));
3000
2939
  }
3001
2940
  /**
3002
2941
  * ← `WebSocket::send` (`web-socket.c++:~640`), which inserts a
@@ -5662,6 +5601,15 @@ var ActorContainerImpl = class {
5662
5601
  hasCurrent() {
5663
5602
  return this.#ctx.hasCurrent();
5664
5603
  }
5604
+ resolveLoopback(invokeDirect, invokeEntry, caller) {
5605
+ const context = tryCurrentIoContext();
5606
+ if (context === this.#ctx) return invokeDirect();
5607
+ if (context !== void 0) return context.awaitIo(context.waitForOutputLocks().then(invokeEntry));
5608
+ if (caller === void 0) return invokeEntry();
5609
+ if (!caller.hasCurrent()) throw new Error("resolveLoopback() caller has no current input lock");
5610
+ if (caller === this) return invokeDirect();
5611
+ return caller.awaitIo(caller.waitOutputLocks().then(invokeEntry));
5612
+ }
5665
5613
  /**
5666
5614
  * ← `ActorContainer::start` (`server.c++:2854-2957`) as far as the class
5667
5615
  * instance, plus decision 4's boot semantics.
@@ -5688,7 +5636,7 @@ var ActorContainerImpl = class {
5688
5636
  throw exception;
5689
5637
  }
5690
5638
  }
5691
- entry(target) {
5639
+ entry(target, signal) {
5692
5640
  const bound = /* @__PURE__ */ new Map();
5693
5641
  return new Proxy(target, { get: (subject, property) => {
5694
5642
  const value = Reflect.get(subject, property, subject);
@@ -5697,7 +5645,7 @@ var ActorContainerImpl = class {
5697
5645
  if (cached !== void 0) return cached;
5698
5646
  const gated = async (...args) => {
5699
5647
  this.#ctx.noteGateUse(`entry ${String(property)}()`, captureGateStack());
5700
- const result = await this.#ctx.run(() => this.#withExternalEntry(() => value.apply(subject, args)));
5648
+ const result = await this.#ctx.run(() => this.#withExternalEntry(() => value.apply(subject, args)), { signal });
5701
5649
  await this.#ctx.waitForOutputLocks();
5702
5650
  return result;
5703
5651
  };
@@ -5733,8 +5681,8 @@ var ActorContainerImpl = class {
5733
5681
  return callback;
5734
5682
  } });
5735
5683
  }
5736
- run(event) {
5737
- return this.#ctx.run(() => this.#withExternalEntry(event));
5684
+ run(event, signal) {
5685
+ return this.#ctx.run(() => this.#withExternalEntry(event), { signal });
5738
5686
  }
5739
5687
  #withExternalEntry(body) {
5740
5688
  const previous = this.#currentExternalEntry;
@@ -5756,7 +5704,7 @@ var ActorContainerImpl = class {
5756
5704
  *
5757
5705
  * "Alarms enter with no lock and no critical section, so an alarm queues behind
5758
5706
  * any held lock and takes a fresh top-level lock" (§1.8) — which is exactly
5759
- * `ctx.run(func)` with no third argument. The retry ladder and the watchdog are
5707
+ * `ctx.run(func)` with no input option. The retry ladder and the watchdog are
5760
5708
  * `server/alarm-scheduler.ts`'s; what is here is one delivery, and the
5761
5709
  * serialization of one delivery against the next, which is the property
5762
5710
  * `_cf_executingScheduleRowId` upstream depends on.
@@ -5934,6 +5882,6 @@ function newRpcSession(port, localMain) {
5934
5882
  return newMessagePortRpcSession(port, localMain);
5935
5883
  }
5936
5884
  //#endregion
5937
- export { ACTOR_CLASS_SERIALIZATION_UNIMPLEMENTED_MESSAGE, ALARM_RETRY_MAX_TRIES, ALARM_RETRY_START_SECONDS, ALLOW_EXPERIMENTAL_MESSAGE, ALREADY_ACCEPTED_MESSAGE, AlarmInvocationInfo, AlarmScheduler, BYOB_READER_UNGATABLE_MESSAGE, DEAD_LOAD_CONTEXT_MESSAGE, DEFAULT_ALARM_OUTLET, FACET_ALARM_UNIMPLEMENTED_MESSAGE, FACET_NAME_MAX_LENGTH, FACET_TREE_MAX_DEPTH, FOREIGN_SLICE_MESSAGE, HIBERNATION_UNIMPLEMENTED_MESSAGE, LoopbackDurableObjectClass, NOT_BYTES_MESSAGE, NO_GLOBAL_OUTBOUND_MESSAGE, NO_MODULES_MESSAGE, PITR_UNIMPLEMENTED_MESSAGE, REPLICATION_UNIMPLEMENTED_MESSAGE, RETRY_BACKOFF_MAX, RETRY_JITTER_FACTOR, STREAMING_TAILS_EXPERIMENTAL_MESSAGE, WorkerLoader, WorkerStub, actorScopeBindings, alarmRetryDelayMs, asLoopbackDurableObjectClass, createActorContainer, createDurableObjectNamespace, gateRequestBody, installActorScope, jsModuleInPythonWorkerMessage, moduleFieldCountMessage, moduleNameMessage, newRpcSession, noFacets, notSerializableMessage, pythonModuleInJsWorkerMessage, typeScriptModuleNameMessage };
5885
+ export { ACTOR_CLASS_SERIALIZATION_UNIMPLEMENTED_MESSAGE, ALARM_RETRY_MAX_TRIES, ALARM_RETRY_START_SECONDS, ALLOW_EXPERIMENTAL_MESSAGE, ALREADY_ACCEPTED_MESSAGE, AlarmInvocationInfo, AlarmScheduler, BYOB_READER_UNGATABLE_MESSAGE, BrokenActorError, CanceledError, DEAD_LOAD_CONTEXT_MESSAGE, DEFAULT_ALARM_OUTLET, FACET_ALARM_UNIMPLEMENTED_MESSAGE, FACET_NAME_MAX_LENGTH, FACET_TREE_MAX_DEPTH, FOREIGN_SLICE_MESSAGE, HIBERNATION_UNIMPLEMENTED_MESSAGE, LoopbackDurableObjectClass, NOT_BYTES_MESSAGE, NO_GLOBAL_OUTBOUND_MESSAGE, NO_MODULES_MESSAGE, PITR_UNIMPLEMENTED_MESSAGE, REPLICATION_UNIMPLEMENTED_MESSAGE, RETRY_BACKOFF_MAX, RETRY_JITTER_FACTOR, STREAMING_TAILS_EXPERIMENTAL_MESSAGE, WorkerLoader, WorkerStub, actorScopeBindings, alarmRetryDelayMs, asLoopbackDurableObjectClass, createActorContainer, createDurableObjectNamespace, gateRequestBody, installActorScope, jsModuleInPythonWorkerMessage, moduleFieldCountMessage, moduleNameMessage, newRpcSession, noFacets, notSerializableMessage, pythonModuleInJsWorkerMessage, typeScriptModuleNameMessage };
5938
5886
 
5939
5887
  //# sourceMappingURL=index.js.map