@mcp-b/do-runtime 0.1.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 (52) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/LICENSE +110 -0
  3. package/LICENSE.workerd +176 -0
  4. package/NOTICE +7 -0
  5. package/README.md +282 -0
  6. package/dist/backends/node-sqlite.d.ts +38 -0
  7. package/dist/backends/node-sqlite.js +335 -0
  8. package/dist/backends/node-sqlite.js.map +1 -0
  9. package/dist/backends/sqlite-wasm.d.ts +130 -0
  10. package/dist/backends/sqlite-wasm.js +259 -0
  11. package/dist/backends/sqlite-wasm.js.map +1 -0
  12. package/dist/chunks/sqlite-DFg92Tgt.js +498 -0
  13. package/dist/chunks/sqlite-DFg92Tgt.js.map +1 -0
  14. package/dist/cloudflare-workers.js +351 -0
  15. package/dist/cloudflare-workers.js.map +1 -0
  16. package/dist/conformance/host.d.ts +58 -0
  17. package/dist/conformance.js +18 -0
  18. package/dist/conformance.js.map +1 -0
  19. package/dist/index.js +7184 -0
  20. package/dist/index.js.map +1 -0
  21. package/dist/server/alarm-scheduler.js +513 -0
  22. package/dist/server/alarm-scheduler.js.map +1 -0
  23. package/dist/src/api/actor-state.d.ts +396 -0
  24. package/dist/src/api/actor.d.ts +306 -0
  25. package/dist/src/api/cloudflare-workers.d.ts +259 -0
  26. package/dist/src/api/export-loopback.d.ts +264 -0
  27. package/dist/src/api/global-scope.d.ts +262 -0
  28. package/dist/src/api/http.d.ts +52 -0
  29. package/dist/src/api/sql.d.ts +188 -0
  30. package/dist/src/api/sync-kv.d.ts +51 -0
  31. package/dist/src/api/web-socket.d.ts +93 -0
  32. package/dist/src/api/worker-loader.d.ts +354 -0
  33. package/dist/src/index.d.ts +130 -0
  34. package/dist/src/io/actor-cache.d.ts +203 -0
  35. package/dist/src/io/actor-id.d.ts +74 -0
  36. package/dist/src/io/actor-sqlite.d.ts +298 -0
  37. package/dist/src/io/io-channels.d.ts +191 -0
  38. package/dist/src/io/io-context.d.ts +451 -0
  39. package/dist/src/io/io-gate.d.ts +298 -0
  40. package/dist/src/io/worker-source.d.ts +108 -0
  41. package/dist/src/io/worker.d.ts +88 -0
  42. package/dist/src/server/actor-container.d.ts +525 -0
  43. package/dist/src/server/actor-id-impl.d.ts +118 -0
  44. package/dist/src/server/alarm-scheduler.d.ts +201 -0
  45. package/dist/src/server/facet-deletion.d.ts +156 -0
  46. package/dist/src/server/facet-tree-index.d.ts +94 -0
  47. package/dist/src/server/sha256.d.ts +39 -0
  48. package/dist/src/transport/rpc-session.d.ts +34 -0
  49. package/dist/src/util/sqlite-kv.d.ts +98 -0
  50. package/dist/src/util/sqlite-metadata.d.ts +46 -0
  51. package/dist/src/util/sqlite.d.ts +291 -0
  52. package/package.json +111 -0
@@ -0,0 +1,264 @@
1
+ /**
2
+ * ← workerd `src/workerd/api/export-loopback.{h,c++}`
3
+ *
4
+ * The four types `ctx.exports` is made of. Upstream's own comment on the first
5
+ * says what they all are: "the type of a property of `ctx.exports` which points
6
+ * back at a … entrypoint of this Worker", specialized by *invoking* it.
7
+ *
8
+ * - `LoopbackServiceStub` (`export-loopback.h:18`) — a stateless entrypoint. A
9
+ * `Fetcher` with empty props, callable to get one with props.
10
+ * - `LoopbackDurableObjectClass` (`:116`) — an actor class with **no storage
11
+ * configured**. A `DurableObjectClass`, callable to get a specialized one.
12
+ * - `LoopbackDurableObjectNamespace` (`:155`) — an actor class **with** storage:
13
+ * "we want a binding that behaves *both* like a LoopbackDurableObjectClass
14
+ * *and* like a DurableObjectNamespace binding."
15
+ * - `LoopbackColoLocalActorNamespace` (`:192`) — the same, for a colo-local
16
+ * (ephemeral) namespace binding.
17
+ *
18
+ * The third is why this file blocks `server/`. The vendored consumer reads
19
+ * `ctx.exports[className]` and needs one value to answer both `idFromName`
20
+ * (`vendor/agents/packages/agents/src/index.ts:10829`, `:10855`) and
21
+ * `ctx.facets.get`'s class check (`:10857`) — namespace-shaped and class-shaped
22
+ * at once, which is exactly what `LoopbackDurableObjectNamespace` is for.
23
+ * Upstream's own `api/tests/worker-loader-test.js:449-450` pins the same pair.
24
+ *
25
+ * **`JSG_CALLABLE` becomes a `Proxy` with an `apply` trap.** A JS value can only
26
+ * be invoked if it is a function, and a class instance is not one; the private
27
+ * fields these classes inherit mean the callable cannot simply be a function
28
+ * whose prototype is the instance, because an inherited method would then run
29
+ * with `this` set to the function. So each class keeps its behaviour and an
30
+ * `asLoopback…` function produces the JS-visible value — the same split, for the
31
+ * same reason, that `asDurableObjectStub` already makes for `JSG_INHERIT`.
32
+ * `getPrototypeOf` is what keeps `instanceof` answering, which is how
33
+ * `DurableObjectFacets.get` discriminates the three arms of its class switch.
34
+ *
35
+ * **Two `IoChannelFactory` methods are declared here rather than in
36
+ * `io/io-channels.ts`.** `getSubrequestChannel` and `getActorClass` are what
37
+ * `export-loopback.c++` reaches for, and both take a channel *number* upstream —
38
+ * which this package does not have (`io/io-channels.ts`'s header: there is no
39
+ * numbered channel table). So each collapses into a factory taking an object
40
+ * request, exactly as `api/actor.ts` already does for `IoChannelFactory`'s
41
+ * `getGlobalActor` and `getColoLocalActor`, and each is declared beside its one
42
+ * consumer for the same reason `ActorChannelFactory` is. Section 7 fills them.
43
+ *
44
+ * **Non-serializability survives, and Section 7b is where it is enforced.**
45
+ * Upstream is explicit that `LoopbackServiceStub` is "intentionally NOT
46
+ * serializable, unlike its parent class Fetcher", and
47
+ * `api/tests/worker-loader-test.js:104` asserts the message;
48
+ * `LoopbackDurableObjectClass` likewise declares no `JSG_SERIALIZABLE` where
49
+ * `DurableObjectClass` (`actor.h:389`) does, and neither namespace type declares
50
+ * one either — `JSG_INHERIT` does not carry serializability, which is what the
51
+ * test's own comment says it is checking.
52
+ *
53
+ * An earlier revision of this paragraph said the refusal did not survive, and
54
+ * named `src/transport/` as the layer that would have to make it. Both halves
55
+ * were wrong about *where*: the test reaches the refusal through
56
+ * `worker.getEntrypoint(name, {props})`, and `WorkerStub::getEntrypoint`'s first
57
+ * act is `Frankenvalue::fromJs`, which runs `jsg::Serializer` inside
58
+ * `api/worker-loader.c++`. So `api/worker-loader.ts`'s `requireSerializableProps`
59
+ * refuses all four of these in `props` and in `env`, with upstream's message and
60
+ * a `DataCloneError`. `DurableObjectClass.serialize` remains a separate named
61
+ * substrate boundary that throws for every class, loopback or not.
62
+ *
63
+ * The version half of `LoopbackServiceStub` is present and `Options`, the
64
+ * flag-off form, is not: `FeatureFlags::getEnableVersionApi()` is read as on
65
+ * here, the same current-behaviour reading `api/actor.ts` gives the four
66
+ * compatibility flags it meets. That makes this a superset of
67
+ * `@cloudflare/workers-types` 4.20260702.1, which generated the flag-off
68
+ * signature — the same relationship `DurableObjectNamespace.getExisting` has.
69
+ *
70
+ * Spec: §1.10, §1.11, decisions 14 and 16 in
71
+ * docs/decisions.md.
72
+ */
73
+ import type { ActorIdFactory } from "../io/actor-id.js";
74
+ import type { ActorClassChannel } from "../io/io-channels.js";
75
+ import { ColoLocalActorNamespace, DurableObjectClass, DurableObjectNamespace, type ActorChannelFactory, type ColoLocalActorChannelFactory } from "./actor.js";
76
+ /**
77
+ * ← what JSG's struct unwrapper does with a value that is not an object
78
+ * (`jsg/struct.h:246`). Undefined and null are **not** in that set: a struct
79
+ * whose every field is optional — which both option structs here are — unwraps
80
+ * from either as an empty struct (`jsg/struct.h:236-243`), so `ctx.exports.Foo()`
81
+ * is upstream's own empty-options call and not an error.
82
+ */
83
+ export declare const LOOPBACK_OPTIONS_NOT_AN_OBJECT_MESSAGE = "A ctx.exports binding is invoked with an options object: pass { props }, or nothing at all.";
84
+ /** ← what JSG does unwrapping a `jsg::JsRef<jsg::JsObject>` from a non-object. */
85
+ export declare const LOOPBACK_PROPS_NOT_AN_OBJECT_MESSAGE = "`props` must be an object. Upstream unwraps it as a jsg::JsObject, which refuses anything else.";
86
+ /** ← `IoChannelFactory::VersionRequest` (`io/io-channels.h:123-131`). */
87
+ export type VersionRequest = {
88
+ /** "Request a version within the given cohort." */
89
+ readonly cohort: string | undefined;
90
+ };
91
+ /**
92
+ * ← the two arguments `IoChannelFactory::getSubrequestChannel` takes besides the
93
+ * channel number (`io/io-channels.h:243-245`). Upstream: "`props` and
94
+ * `versionRequest` can only be specified if this is a loopback channel (i.e.
95
+ * from ctx.exports)."
96
+ */
97
+ export type SubrequestChannelRequest = {
98
+ /** ← `kj::Maybe<Frankenvalue> props`. */
99
+ readonly props: unknown;
100
+ readonly version: VersionRequest | undefined;
101
+ };
102
+ /**
103
+ * ← `IoChannelFactory::getSubrequestChannel` composed with the `Fetcher` upstream
104
+ * builds over the `SubrequestChannel` it returns.
105
+ *
106
+ * The composition is `api/actor.ts`'s: a `SubrequestChannel` is only ever driven
107
+ * through `startRequest()` → `WorkerInterface`, which has no port, while the
108
+ * JS-visible product is a `Fetcher` — so the channel and the stub it produces are
109
+ * one object here.
110
+ */
111
+ export interface SubrequestChannelFactory {
112
+ getSubrequestChannel(request: SubrequestChannelRequest): Fetcher;
113
+ }
114
+ /** ← the `props` argument of `IoChannelFactory::getActorClass` (`io/io-channels.h:315`). */
115
+ export type ActorClassRequest = {
116
+ readonly props: unknown;
117
+ };
118
+ /** ← `IoChannelFactory::getActorClass`, which returns the token `io/io-channels.ts` ports. */
119
+ export interface ActorClassChannelFactory {
120
+ getActorClass(request: ActorClassRequest): ActorClassChannel;
121
+ }
122
+ /** ← `LoopbackServiceStub::OptionsWithVersion::Version` (`export-loopback.h:32-36`). */
123
+ export type LoopbackServiceStubVersion = {
124
+ /** `jsg::Optional<kj::Maybe<kj::String>>`: omitted and null are the same request. */
125
+ readonly cohort?: string | null;
126
+ };
127
+ /** ← `LoopbackServiceStub::OptionsWithVersion` (`export-loopback.h:31-42`). */
128
+ export type LoopbackServiceStubOptions = {
129
+ readonly props?: unknown;
130
+ readonly version?: LoopbackServiceStubVersion;
131
+ };
132
+ /** ← `LoopbackDurableObjectClass::Options` (`export-loopback.h:120-124`). */
133
+ export type LoopbackDurableObjectClassOptions = {
134
+ readonly props?: unknown;
135
+ };
136
+ /**
137
+ * ← `LoopbackServiceStub` (`export-loopback.h:18-109`).
138
+ *
139
+ * Upstream is a `Fetcher` on the loopback channel and holds the channel number a
140
+ * second time so `callImpl` can re-specialize it. Here the `Fetcher` is the
141
+ * transport's — `api/http.{h,c++}` is not ported — so the unspecialized stub is
142
+ * what the factory returns for a request with no props and no version, and the
143
+ * factory is the thing held twice over.
144
+ */
145
+ export declare class LoopbackServiceStub {
146
+ #private;
147
+ constructor(channel: SubrequestChannelFactory);
148
+ /** The `Fetcher` upstream inherits from rather than holds, as `DurableObject`'s is. */
149
+ getFetcher(): Fetcher;
150
+ /**
151
+ * ← `LoopbackServiceStub::callImpl` (`export-loopback.c++:11-29`) reached
152
+ * through `callWithVersion` (`export-loopback.h:53-55`), which is the callable
153
+ * when `enableVersionApi` is on. "Create a specialized Fetcher which can be
154
+ * passed over RPC."
155
+ */
156
+ callWithVersion(options: LoopbackServiceStubOptions): Fetcher;
157
+ }
158
+ /**
159
+ * ← `js.alloc<LoopbackServiceStub>(…)` plus `JSG_CALLABLE(callWithVersion)`.
160
+ *
161
+ * The declared type is a superset of `@cloudflare/workers-types`' by exactly the
162
+ * `version` field, for the reason in this module's header.
163
+ */
164
+ export type LoopbackServiceStubValue<T extends Rpc.WorkerEntrypointBranded | undefined = undefined> = Fetcher<T> & ((options?: LoopbackServiceStubOptions) => Fetcher<T>);
165
+ export declare function asLoopbackServiceStub<T extends Rpc.WorkerEntrypointBranded | undefined = undefined>(stub: LoopbackServiceStub): LoopbackServiceStubValue<T>;
166
+ /**
167
+ * ← `LoopbackDurableObjectClass` (`export-loopback.h:116-148`). "Similar to
168
+ * LoopbackServiceStub, but for actor classes … this is used for actor classes
169
+ * that do *not* have any storage configured. If you simply export a class
170
+ * extending `DurableObject` but you don't configure storage for it, it shows up
171
+ * in `ctx.exports` as this type. This can be used to create a Durable Object
172
+ * facet."
173
+ *
174
+ * Upstream's base `DurableObjectClass` holds the channel *number*, and
175
+ * `getChannel(ioctx)` resolves it lazily. There is no numbered arm here, so the
176
+ * unspecialized channel is requested once, in the constructor — which is the same
177
+ * value `getActorClass(channel)` with default props would have produced.
178
+ */
179
+ export declare class LoopbackDurableObjectClass<T extends Rpc.DurableObjectBranded | undefined = undefined> extends DurableObjectClass<T> {
180
+ #private;
181
+ constructor(channel: ActorClassChannelFactory);
182
+ /**
183
+ * ← `LoopbackDurableObjectClass::call` (`export-loopback.c++:31-40`). "Create a
184
+ * specialized DurableObjectClass which can be passed over RPC."
185
+ *
186
+ * The result is a plain `DurableObjectClass`, as `js.alloc<DurableObjectClass>`
187
+ * is: specializing a loopback class does not produce another loopback class.
188
+ */
189
+ call(options: LoopbackDurableObjectClassOptions): DurableObjectClass<T>;
190
+ }
191
+ /** ← `js.alloc<LoopbackDurableObjectClass>(…)` plus `JSG_CALLABLE(call)`. */
192
+ export type LoopbackDurableObjectClassValue<T extends Rpc.DurableObjectBranded | undefined = undefined> = DurableObjectClass<T> & ((options?: LoopbackDurableObjectClassOptions) => DurableObjectClass<T>);
193
+ export declare function asLoopbackDurableObjectClass<T extends Rpc.DurableObjectBranded | undefined = undefined>(actorClass: LoopbackDurableObjectClass<T>): LoopbackDurableObjectClassValue<T>;
194
+ /**
195
+ * ← `LoopbackDurableObjectNamespace` (`export-loopback.h:155-189`).
196
+ *
197
+ * Upstream: "used when the class has storage configured. In this case, we want a
198
+ * binding that behaves *both* like a LoopbackDurableObjectClass *and* like a
199
+ * DurableObjectNamespace binding. Easy enough, we'll inherit
200
+ * DurableObjectNamespace, but also make the binding invokable as a function like
201
+ * LoopbackDurableObjectClass."
202
+ */
203
+ export declare class LoopbackDurableObjectNamespace<T extends Rpc.DurableObjectBranded | undefined = undefined> extends DurableObjectNamespace<T> {
204
+ #private;
205
+ constructor(channel: ActorChannelFactory, idFactory: ActorIdFactory, loopbackClass: LoopbackDurableObjectClass<T>);
206
+ /** ← `getClass()`. "getClass() accessor for use from C++ only." */
207
+ getClass(): LoopbackDurableObjectClass<T>;
208
+ /** ← `call`. "Invoking the binding creates a specialization of the class -- not the namespace." */
209
+ call(options: LoopbackDurableObjectClassOptions): DurableObjectClass<T>;
210
+ }
211
+ /**
212
+ * ← `js.alloc<LoopbackDurableObjectNamespace>(…)` plus `JSG_CALLABLE(call)`.
213
+ *
214
+ * This is the type of a `ctx.exports` entry for a Durable Object class with
215
+ * storage, and the reason it is stated in terms of this package's classes rather
216
+ * than `@cloudflare/workers-types`' `LoopbackDurableObjectNamespace` is that the
217
+ * pinned interface is `interface LoopbackDurableObjectNamespace extends
218
+ * DurableObjectNamespace {}` — no call signature, because that resource type
219
+ * carries no `JSG_TS_OVERRIDE` to generate one from. `Cloudflare.Exports`
220
+ * describes the same value correctly, as `LoopbackDurableObjectClass<T> &
221
+ * DurableObjectNamespace<T>`, and `PinnedLoopbackTypes` below checks against
222
+ * that rather than against the interface.
223
+ *
224
+ * `call` is omitted because `JSG_CALLABLE` registers it as the object's call
225
+ * behaviour rather than as a property: on the value, `.call` is
226
+ * `Function.prototype.call`, which is what `asCallable`'s `get` trap answers.
227
+ */
228
+ export type LoopbackDurableObjectNamespaceValue<T extends Rpc.DurableObjectBranded | undefined = undefined> = Omit<LoopbackDurableObjectNamespace<T>, "call"> & ((options?: LoopbackDurableObjectClassOptions) => DurableObjectClass<T>);
229
+ export declare function asLoopbackDurableObjectNamespace<T extends Rpc.DurableObjectBranded | undefined = undefined>(namespace: LoopbackDurableObjectNamespace<T>): LoopbackDurableObjectNamespaceValue<T>;
230
+ /**
231
+ * ← `LoopbackColoLocalActorNamespace` (`export-loopback.h:192-220`). "Like
232
+ * LoopbackDurableObjectNamespace, but for colo-local (ephemeral) actor
233
+ * namespaces."
234
+ */
235
+ export declare class LoopbackColoLocalActorNamespace extends ColoLocalActorNamespace {
236
+ #private;
237
+ constructor(channel: ColoLocalActorChannelFactory, loopbackClass: LoopbackDurableObjectClass);
238
+ /** ← `getClass()`. "getClass() accessor for use from C++ only." */
239
+ getClass(): LoopbackDurableObjectClass;
240
+ /** ← `call`. "Invoking the binding creates a specialization of the class -- not the namespace." */
241
+ call(options: LoopbackDurableObjectClassOptions): DurableObjectClass;
242
+ }
243
+ /**
244
+ * ← `js.alloc<LoopbackColoLocalActorNamespace>(…)` plus `JSG_CALLABLE(call)`,
245
+ * with `call` omitted for the reason given on the durable namespace above.
246
+ */
247
+ export type LoopbackColoLocalActorNamespaceValue = Omit<LoopbackColoLocalActorNamespace, "call"> & ((options?: LoopbackDurableObjectClassOptions) => DurableObjectClass);
248
+ export declare function asLoopbackColoLocalActorNamespace(namespace: LoopbackColoLocalActorNamespace): LoopbackColoLocalActorNamespaceValue;
249
+ /** `Value` must be assignable to `Declared`; declaring the constraint is the check. */
250
+ type Assignable<Value extends Declared, Declared> = Value;
251
+ /**
252
+ * Checked rather than claimed: every value this module produces satisfies the
253
+ * shape `@cloudflare/workers-types` 4.20260702.1 declares for it. The last two
254
+ * are checked against `Cloudflare.Exports`' own description of a `ctx.exports`
255
+ * entry — `LoopbackForExport<T>` intersected with the namespace — because the
256
+ * two named interfaces there are call-signature-less, per the note above.
257
+ */
258
+ export type PinnedLoopbackTypes = [
259
+ Assignable<LoopbackServiceStubValue, globalThis.LoopbackServiceStub>,
260
+ Assignable<LoopbackDurableObjectClassValue, globalThis.LoopbackDurableObjectClass>,
261
+ Assignable<LoopbackDurableObjectNamespaceValue, globalThis.LoopbackDurableObjectClass & globalThis.DurableObjectNamespace>,
262
+ Assignable<LoopbackColoLocalActorNamespaceValue, globalThis.LoopbackDurableObjectClass & globalThis.ColoLocalActorNamespace>
263
+ ];
264
+ export {};
@@ -0,0 +1,262 @@
1
+ /**
2
+ * ← workerd `src/workerd/api/global-scope.{h,c++}` — the alarm half, and the
3
+ * async-primitive half `ServiceWorkerGlobalScope` exposes to an application.
4
+ *
5
+ * The event surface (`fetch`/`scheduled`/`trace`/`queue` handlers) still has no
6
+ * port: that belongs to layers this package does not have. What is here is the
7
+ * other thing that class is, and the thing a Durable Object actually reaches —
8
+ * `JSG_METHOD(setTimeout)`, `clearTimeout`, `setInterval`, `clearInterval`,
9
+ * `JSG_METHOD(fetch)`, and `JSG_LAZY_INSTANCE_PROPERTY(scheduler, getScheduler)`
10
+ * (`global-scope.h:776-808`). `Scheduler` itself is `api/basics.h:781-797`; it
11
+ * is one class with one method and it lives beside its only exposure rather than
12
+ * in a `api/basics.ts` that would hold nothing else, since everything else in
13
+ * that file — `Event`, `EventTarget`, `AbortController`, `AbortSignal` — the
14
+ * substrate already provides.
15
+ *
16
+ * **Why this file gained a half.** Workerd's globals hold no context: each one
17
+ * reads `IoContext::current()` at call time (`global-scope.c++:944`, `:961`,
18
+ * `:989`, `:1160`), because acquisition is structural and every entry into the
19
+ * isolate has already taken the lock. There is no isolate hook here, so a
20
+ * continuation that resumes from a promise the runtime does not own comes back
21
+ * with an empty invocation stack and its next `ctx.storage` call throws `no
22
+ * input lock available in this context`. Every host-provided async primitive
23
+ * therefore has to gate itself, and this is where they do.
24
+ *
25
+ * The three primitives take three different mechanisms, and flattening them into
26
+ * "wrap it in awaitIo" would be wrong three ways:
27
+ *
28
+ * - **Timers** capture the critical section at the ARMING call and re-enter
29
+ * through `ctx.run(callback, cs)` when they fire. Not `awaitIo`, deliberately
30
+ * — see `TimeoutManager` in `io/io-context.ts` for upstream's own reason.
31
+ * - **`fetch`** is `awaitIo` (`http.c++` has ten of them and zero
32
+ * `awaitIoWithInputLock`), preceded by an output-gate wait so nothing departs
33
+ * ahead of the writes it might reveal (`http.c++:1488`). §1.3.
34
+ * - **WebSocket** is neither: `api/web-socket.ts`, because a socket is a long
35
+ * stream of events rather than one result.
36
+ *
37
+ * **The context is held, not looked up, and that is the whole of the
38
+ * enforcement substitution.** One scope per actor. See `requireOwnSlice` for
39
+ * what happens when a facet reaches a scope that is not its own.
40
+ *
41
+ * Spec: §1.2, §1.3, §1.8 and decisions 1 and 16 in
42
+ * docs/decisions.md.
43
+ */
44
+ import { type IoContext } from "../io/io-context.js";
45
+ /**
46
+ * ← `AlarmInvocationInfo` (`api/global-scope.h:386-412`): "a jsg::Object used to
47
+ * pass alarm invocation info to an alarm handler."
48
+ *
49
+ * `scheduledTime` is already milliseconds here where upstream converts a
50
+ * `kj::Date` to them at construction (`global-scope.h:390`), which is the same
51
+ * unit `@cloudflare/workers-types` declares and the same one `setAlarm` takes.
52
+ */
53
+ export declare class AlarmInvocationInfo implements globalThis.AlarmInvocationInfo {
54
+ readonly scheduledTime: number;
55
+ readonly retryCount: number;
56
+ constructor(scheduledTime: number, retry: number);
57
+ get isRetry(): boolean;
58
+ }
59
+ /**
60
+ * ← `isAlarmFailureUserError` (`api/global-scope.c++:501-515`), whose own
61
+ * comment lists the three arms: "Returns true if an alarm failure should count
62
+ * against the user's retry limit. A failure is user-generated if any of: the
63
+ * exception was explicitly tagged with EXCEPTION_IS_USER_ERROR at construction
64
+ * time (e.g. state.abort(), exceededCpu, exceededMemory, overload queue); the
65
+ * exception originated from user code throwing inside blockConcurrencyWhile,
66
+ * which breaks the input gate as a secondary side-effect; the exception is a
67
+ * plain jsg.* error without broken.* or jsg-internal.* prefixes, meaning the
68
+ * user's handler threw directly."
69
+ *
70
+ * The first two arms port exactly: this package writes both markers itself —
71
+ * `DurableObjectState.abort()` sets the detail, and `IoContext` annotates a
72
+ * broken input gate with upstream's own prefix.
73
+ *
74
+ * **The third arm has no input here, and its default is inverted deliberately.**
75
+ * Upstream reads it off jsg's exception tunnelling: a `jsg.Error:` prefix that
76
+ * is neither `jsg-internal.` nor a Durable Object reset means the user's handler
77
+ * threw. There is no tunnelling in this runtime — an `Error` out of a handler
78
+ * carries no provenance at all — so a plain exception is reported here as NOT a
79
+ * user error, where upstream would report it as one.
80
+ *
81
+ * That inversion is narrower than it sounds, and it is the safe direction. The
82
+ * caller is
83
+ * `shouldRetryCountsAgainstLimits = !isOutputGateBroken() || isUserGeneratedError`
84
+ * (`global-scope.c++:624`), so for an intact actor a handler failure counts
85
+ * whatever this answers; the only case the two readings disagree on is a handler
86
+ * failure that arrives together with a broken output gate. Upstream counts that
87
+ * and eventually abandons the alarm. This does not, so the alarm outlives the
88
+ * actor's reset and is retried after the restart — which is what
89
+ * `!tunneled.isDurableObjectReset` (`:514`) is reaching for on the arm above it
90
+ * and what the product ranking asks for outright. A default of "user error"
91
+ * would abandon exactly the alarms that most need keeping.
92
+ */
93
+ export declare function isAlarmFailureUserError(exception: unknown): boolean;
94
+ /** ← `Scheduler::WaitOptions` (`api/basics.h:775-778`). */
95
+ export type SchedulerWaitOptions = {
96
+ signal?: AbortSignal;
97
+ };
98
+ /**
99
+ * ← `Scheduler` (`api/basics.h:781-797`), whose own comment is: "The scheduler
100
+ * class is an emerging web platform standard API that is meant to be global and
101
+ * provides task scheduling APIs. We currently only implement a subset of the API
102
+ * that is being defined."
103
+ *
104
+ * `wait` is "essentially an awaitable alternative to setTimeout()", and upstream
105
+ * implements it as exactly that — `setTimeoutInternal` onto the same timeout
106
+ * manager (`basics.c++:1007`), which is why it inherits the gating rather than
107
+ * having any of its own.
108
+ */
109
+ export declare class Scheduler {
110
+ #private;
111
+ constructor(scope: ActorGlobalScope);
112
+ /** ← `Scheduler::wait` (`basics.c++:989-1020`). */
113
+ wait(delay: number, options?: SchedulerWaitOptions): Promise<void>;
114
+ /**
115
+ * NO upstream correspondence: `scheduler.yield()` is the Prioritized Task
116
+ * Scheduling API's, which workerd does not implement — `Scheduler` above has
117
+ * exactly one `JSG_METHOD`. It is here because Chrome ships a `scheduler`
118
+ * global in workers that DOES have `yield` and no `wait`, so a scope that
119
+ * replaced Chrome's and dropped `yield` would break page-shaped code that a
120
+ * Durable Object never runs but a shared worker global might. A zero-delay
121
+ * gated timer is the closest honest reading and it keeps the lock property.
122
+ */
123
+ yield(): Promise<void>;
124
+ }
125
+ /**
126
+ * ← `ServiceWorkerGlobalScope`'s `crypto`. The synchronous members are the
127
+ * platform's own; `subtle` is the gated one above.
128
+ */
129
+ declare class GatedCrypto {
130
+ #private;
131
+ readonly subtle: SubtleCrypto;
132
+ constructor(requireOwnSlice: (op: string) => void, ctx: IoContext, crypto: Crypto);
133
+ getRandomValues<T extends ArrayBufferView | null>(array: T): T;
134
+ randomUUID(): `${string}-${string}-${string}-${string}-${string}`;
135
+ }
136
+ /** What the host supplies beneath `ServiceWorkerGlobalScope::fetch`. */
137
+ export type FetchPort = (input: RequestInfo | URL, init?: RequestInit) => Promise<Response>;
138
+ export type ActorGlobalScopeOptions = {
139
+ /** Opaque identity of the external entry whose synchronous body is running. */
140
+ readonly currentExternalEntry?: (() => object | undefined) | undefined;
141
+ /**
142
+ * The `Crypto` the gated one delegates to. Defaults to the realm's own, which
143
+ * is what a host wants: unlike `fetch`, there is no per-actor outbound to
144
+ * route this through — `SubtleCrypto` is pure computation, and the only thing
145
+ * the actor's scope adds is the gate around its promise.
146
+ */
147
+ readonly crypto?: Crypto | undefined;
148
+ /**
149
+ * ← the global outbound `Fetcher` `ServiceWorkerGlobalScope::fetch` resolves
150
+ * (`global-scope.c++:1160`). Absent means this actor has no ambient outbound,
151
+ * which is upstream's `globalOutbound: null` posture (§1.11) — `fetch` then
152
+ * refuses by name rather than reaching a `fetch` this package does not own.
153
+ */
154
+ readonly fetch?: FetchPort | undefined;
155
+ };
156
+ /** Thrown where `globalOutbound` is absent. Asserted rather than skipped, so it cannot drift. */
157
+ export declare const NO_GLOBAL_OUTBOUND_MESSAGE = "fetch(): this actor has no global outbound, so an ambient fetch cannot be gated.";
158
+ /**
159
+ * The message a scope answers with when it is reached from another actor's
160
+ * slice. Exported because the failure it names is the one thing about this layer
161
+ * that cannot be found by reading the calling code — see `requireOwnSlice`.
162
+ */
163
+ export declare const FOREIGN_SLICE_MESSAGE: string;
164
+ /**
165
+ * ← `ServiceWorkerGlobalScope`, the async-primitive half. One per actor.
166
+ *
167
+ * A consumer installs this into whatever scope its actor's code reads —
168
+ * `globalThis` for a class in the worker's own module graph, a module-scoped
169
+ * binding for a class that arrived as a dynamically-loaded Worker source, which
170
+ * is upstream's own arrangement (a dynamic Worker has its own global scope bound
171
+ * to its own context, §1.11).
172
+ */
173
+ export declare class ActorGlobalScope {
174
+ #private;
175
+ readonly scheduler: Scheduler;
176
+ readonly crypto: GatedCrypto;
177
+ constructor(ctx: IoContext, options?: ActorGlobalScopeOptions);
178
+ /** Opaque identity available only during an external entry's synchronous body. */
179
+ get currentExternalEntry(): object | undefined;
180
+ /** Re-enter this actor after a host promise settles. */
181
+ awaitIo<T>(promise: Promise<T>): Promise<T>;
182
+ /** ← `ServiceWorkerGlobalScope::setTimeout` (`global-scope.c++:944-950`). */
183
+ setTimeout(callback: (...args: never[]) => void, msDelay?: number, ...args: unknown[]): number;
184
+ /** ← `ServiceWorkerGlobalScope::clearTimeout` (`global-scope.c++:967-975`). */
185
+ clearTimeout(id?: number | null): void;
186
+ /** ← `ServiceWorkerGlobalScope::setInterval` (`global-scope.c++:959-965`). */
187
+ setInterval(callback: (...args: never[]) => void, msDelay?: number, ...args: unknown[]): number;
188
+ /** ← `ServiceWorkerGlobalScope::clearInterval`, which is `clearTimeout`'s own body. */
189
+ clearInterval(id?: number | null): void;
190
+ /**
191
+ * ← `ServiceWorkerGlobalScope::fetch` (`global-scope.h:703-705`) reaching
192
+ * `fetchImpl` (`http.c++:1740-1760`).
193
+ *
194
+ * Two gates, in upstream's order. The OUTPUT gate first, because an outbound
195
+ * request is exactly the observation §1.1 exists to hold back — "blocks all
196
+ * outgoing messages from an actor that would allow the rest of the world to
197
+ * observe the actor's state" — and `fetchImpl` waits on it before the request
198
+ * departs (`http.c++:1488`, `:1759`). The INPUT gate is released for the
199
+ * duration and re-taken on resumption, which is `awaitIo` and which is what
200
+ * makes an actor awaiting the network stay re-entrant (§1.3).
201
+ */
202
+ fetch(input: RequestInfo | URL, init?: RequestInit): Promise<Response>;
203
+ }
204
+ /**
205
+ * The bound form of `ActorGlobalScope`, which is what a scope object actually
206
+ * holds. Bound, because these are read as free variables — `setTimeout(…)`, not
207
+ * `scope.setTimeout(…)` — so a method that needed its receiver would break the
208
+ * moment it was destructured, which is exactly how a dynamically-loaded Worker
209
+ * source receives them.
210
+ */
211
+ export type ActorScopeBindings = {
212
+ readonly awaitIo: <T>(promise: Promise<T>) => Promise<T>;
213
+ readonly scheduler: {
214
+ wait(delay: number, options?: SchedulerWaitOptions): Promise<void>;
215
+ yield(): Promise<void>;
216
+ };
217
+ readonly setTimeout: (callback: (...args: never[]) => void, msDelay?: number, ...args: unknown[]) => number;
218
+ readonly clearTimeout: (id?: number | null) => void;
219
+ readonly setInterval: (callback: (...args: never[]) => void, msDelay?: number, ...args: unknown[]) => number;
220
+ readonly clearInterval: (id?: number | null) => void;
221
+ readonly fetch: (input: RequestInfo | URL, init?: RequestInit) => Promise<Response>;
222
+ readonly crypto: Crypto;
223
+ readonly currentExternalEntry?: object | undefined;
224
+ };
225
+ /**
226
+ * The capabilities an actor's code reads, bound to one scope.
227
+ *
228
+ * `resolve` is a thunk because the owner may change across root respawns, or a
229
+ * shared realm may select the actor whose synchronous slice is running. It is
230
+ * consulted only when an operation begins; it does not propagate identity
231
+ * across a promise continuation. Actor-owned code should retain its explicit
232
+ * scope instead. A single-actor host simply writes `() => scope`.
233
+ */
234
+ export declare function actorScopeBindings(resolve: () => ActorGlobalScope): ActorScopeBindings;
235
+ /**
236
+ * Write the web-platform bindings onto a scope object — `globalThis` for a class in the worker's
237
+ * own module graph, a plain object a dynamically-loaded source destructures for
238
+ * one that is not.
239
+ *
240
+ * **A host should call this rather than assigning the names itself**, and the
241
+ * reason is the failure it prevents: a host that installs five of the six leaves
242
+ * one primitive ungated, and an ungated primitive that WORKS is invisible until
243
+ * a continuation after it touches storage — possibly never, on the path that
244
+ * matters. The set is the package's, so it can grow without every host growing
245
+ * with it.
246
+ *
247
+ * **It ASSIGNS, and that is not incidental.** Chrome ships a `scheduler` global
248
+ * in dedicated workers — the Prioritized Task Scheduling API, `postTask` and
249
+ * `yield`, no `wait` — so a host writing `??=` silently keeps Chrome's and every
250
+ * timer await fails somewhere else entirely with `scheduler.wait is not a
251
+ * function`. Measured on the browser conformance lane, and the extension meets
252
+ * the same global at cutover.
253
+ *
254
+ * **What a host must do first:** capture whatever raw timers its own substrate
255
+ * needs. Everything BELOW the runtime — a `Timer` port, a transport's own
256
+ * retries — has to keep the platform's, or arming a timeout goes through a
257
+ * timeout. That is not hypothetical: pointing the node lane at these primitives
258
+ * without capturing first produced `RangeError: Maximum call stack size
259
+ * exceeded` on the first row.
260
+ */
261
+ export declare function installActorScope(target: object, resolve: () => ActorGlobalScope): void;
262
+ export {};
@@ -0,0 +1,52 @@
1
+ /**
2
+ * ← workerd `src/workerd/api/http.{h,c++}` — the gating, and nothing else.
3
+ *
4
+ * `http.c++` is 2,400 lines of `Request`, `Response`, `Headers`, `Body`,
5
+ * `Fetcher` and the redirect machine. None of it is ported: the substrate ships
6
+ * all of it, to the same specification, and re-implementing WHATWG Fetch over
7
+ * `fetch` would be the feature-subset failure the porting philosophy describes,
8
+ * with a much larger surface than the eighty lines it saves.
9
+ *
10
+ * What the substrate's copy cannot have is the half that is not in the spec at
11
+ * all: **every asynchronous step of a fetch is an io-context operation**, so on
12
+ * workerd the code after `await res.json()` resumes holding an input lock the
13
+ * same way the code after `await fetch(…)` does. §1.3 is the whole of it —
14
+ * `api/http.c++` contains ten `awaitIo(` calls and zero
15
+ * `awaitIoWithInputLock`, so an outbound request releases the input gate and its
16
+ * continuation re-takes one.
17
+ *
18
+ * A `Response` is where that matters and where it is easiest to miss. `fetch`
19
+ * itself is one `awaitIo` in `api/global-scope.ts`, which is obvious; the body
20
+ * is a SECOND await, arbitrarily later, and a raw `Response` would resolve it
21
+ * from a promise this package does not own. The continuation would come back
22
+ * with an empty invocation stack and the next `ctx.storage` call would throw —
23
+ * divergence 147, arriving from a line that looks like it only parses JSON.
24
+ *
25
+ * Upstream reaches the same place by construction rather than by wrapping: a
26
+ * `Response`'s body is an `IoOwn<ReadableStream>`, and `IoOwn` is precisely "a
27
+ * thing that may only be touched from inside its IoContext"
28
+ * (`io-context.h`'s `IoOwn`/`IoPtr`/`DeleteQueue` block). There is no such
29
+ * ownership here — GC makes a cross-context dereference impossible in the way
30
+ * that block guards against, which is why the package does not port it — so the
31
+ * property it produced has to be produced by the wrapper below.
32
+ *
33
+ * Spec: §1.3 and decision 1 in
34
+ * docs/decisions.md.
35
+ */
36
+ type IoAwaiter = {
37
+ awaitIo<T>(promise: Promise<T>): Promise<T>;
38
+ };
39
+ /** Wrap a host-provided request so consuming or streaming its body resumes gated. */
40
+ export declare function gateRequestBody(ctx: IoAwaiter, request: Request): Request;
41
+ /** Wrap an outbound response so consuming or streaming its body resumes gated. */
42
+ export declare function gateResponseBody(ctx: IoAwaiter, response: Response): Response;
43
+ /**
44
+ * ← the same property one layer down: a body read through `getReader()` is a
45
+ * sequence of awaits, so each `read()` is one.
46
+ *
47
+ * Only the default reader is covered. A BYOB reader is refused rather than
48
+ * passed through ungated — see `BYOB_READER_UNGATABLE_MESSAGE`.
49
+ */
50
+ export declare const BYOB_READER_UNGATABLE_MESSAGE: string;
51
+ export declare function gateReadableStream<T>(ctx: IoAwaiter, stream: ReadableStream<T>): ReadableStream<T>;
52
+ export {};