@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.
- package/CHANGELOG.md +14 -0
- package/LICENSE +110 -0
- package/LICENSE.workerd +176 -0
- package/NOTICE +7 -0
- package/README.md +282 -0
- package/dist/backends/node-sqlite.d.ts +38 -0
- package/dist/backends/node-sqlite.js +335 -0
- package/dist/backends/node-sqlite.js.map +1 -0
- package/dist/backends/sqlite-wasm.d.ts +130 -0
- package/dist/backends/sqlite-wasm.js +259 -0
- package/dist/backends/sqlite-wasm.js.map +1 -0
- package/dist/chunks/sqlite-DFg92Tgt.js +498 -0
- package/dist/chunks/sqlite-DFg92Tgt.js.map +1 -0
- package/dist/cloudflare-workers.js +351 -0
- package/dist/cloudflare-workers.js.map +1 -0
- package/dist/conformance/host.d.ts +58 -0
- package/dist/conformance.js +18 -0
- package/dist/conformance.js.map +1 -0
- package/dist/index.js +7184 -0
- package/dist/index.js.map +1 -0
- package/dist/server/alarm-scheduler.js +513 -0
- package/dist/server/alarm-scheduler.js.map +1 -0
- package/dist/src/api/actor-state.d.ts +396 -0
- package/dist/src/api/actor.d.ts +306 -0
- package/dist/src/api/cloudflare-workers.d.ts +259 -0
- package/dist/src/api/export-loopback.d.ts +264 -0
- package/dist/src/api/global-scope.d.ts +262 -0
- package/dist/src/api/http.d.ts +52 -0
- package/dist/src/api/sql.d.ts +188 -0
- package/dist/src/api/sync-kv.d.ts +51 -0
- package/dist/src/api/web-socket.d.ts +93 -0
- package/dist/src/api/worker-loader.d.ts +354 -0
- package/dist/src/index.d.ts +130 -0
- package/dist/src/io/actor-cache.d.ts +203 -0
- package/dist/src/io/actor-id.d.ts +74 -0
- package/dist/src/io/actor-sqlite.d.ts +298 -0
- package/dist/src/io/io-channels.d.ts +191 -0
- package/dist/src/io/io-context.d.ts +451 -0
- package/dist/src/io/io-gate.d.ts +298 -0
- package/dist/src/io/worker-source.d.ts +108 -0
- package/dist/src/io/worker.d.ts +88 -0
- package/dist/src/server/actor-container.d.ts +525 -0
- package/dist/src/server/actor-id-impl.d.ts +118 -0
- package/dist/src/server/alarm-scheduler.d.ts +201 -0
- package/dist/src/server/facet-deletion.d.ts +156 -0
- package/dist/src/server/facet-tree-index.d.ts +94 -0
- package/dist/src/server/sha256.d.ts +39 -0
- package/dist/src/transport/rpc-session.d.ts +34 -0
- package/dist/src/util/sqlite-kv.d.ts +98 -0
- package/dist/src/util/sqlite-metadata.d.ts +46 -0
- package/dist/src/util/sqlite.d.ts +291 -0
- package/package.json +111 -0
|
@@ -0,0 +1,354 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ← workerd `src/workerd/api/worker-loader.{h,c++}`
|
|
3
|
+
*
|
|
4
|
+
* The Worker Loader binding: `get(name, getCode)` and `load(code)`, the
|
|
5
|
+
* `WorkerStub` they return, and the two ways a dynamic Worker is reached —
|
|
6
|
+
* `getEntrypoint()` for a `Fetcher` and `getDurableObjectClass()` for a
|
|
7
|
+
* `DurableObjectClass`, which is the single bridge between dynamic Workers and
|
|
8
|
+
* facets. Per §1.11 Code Mode is two features composed: a dynamic Worker for
|
|
9
|
+
* execution and a facet for durable state, because "Dynamically-loaded isolates
|
|
10
|
+
* can't directly have storage" (`server/server.c++:4209`).
|
|
11
|
+
*
|
|
12
|
+
* **The scaffolding this file replaces was a hypothesis, and the C++ wants a
|
|
13
|
+
* different shape.** It declared `IsolateHost.execute({executionId, code,
|
|
14
|
+
* namespaces}, onToolCall)` plus `cancel(executionId)`, with a
|
|
15
|
+
* `SandboxNamespaceDescriptor` of `{provider, name}` and a `SandboxToolDispatch`
|
|
16
|
+
* of `(provider, name, args, toolCallId)`. Not one of those words appears in
|
|
17
|
+
* `worker-loader.{h,c++}` or in `io-channels.h`: providers, tool calls and
|
|
18
|
+
* execution ids are the *consumer's* concepts, and this package may not know
|
|
19
|
+
* about Rook, Think or agents. What upstream actually declares is
|
|
20
|
+
* `IoChannelFactory::loadIsolate(channel, name, fetchSource) ->
|
|
21
|
+
* WorkerStubChannel` (`io/io-channels.h:339-343`), with `getEntrypoint` and
|
|
22
|
+
* `getActorClass` on the channel — a Worker-shaped seam, not an
|
|
23
|
+
* execution-shaped one. The scaffolding had transcribed
|
|
24
|
+
* `OffscreenCodemodeExecutor`, which is decision 15's *subject*, not its result.
|
|
25
|
+
* `ActorPorts.isolates` went with it: a Worker Loader is a binding a host puts in
|
|
26
|
+
* `env`, exactly as `DurableObjectNamespace` and `ctx.exports` already are, not a
|
|
27
|
+
* port the container needs — upstream's own is `Global::WorkerLoader{channel}`
|
|
28
|
+
* compiled into the bindings (`server/workerd-api.c++:748`).
|
|
29
|
+
*
|
|
30
|
+
* **`get()` does not cache; the namespace behind it does.** `WorkerLoader::get`
|
|
31
|
+
* calls `loadIsolate` unconditionally and mints a fresh `WorkerStub` every call
|
|
32
|
+
* (`worker-loader.c++:63-83`). The find-or-create by name lives one layer down, in
|
|
33
|
+
* `Server::WorkerLoaderNamespace::loadIsolate` (`server.c++:4243-4281`), together
|
|
34
|
+
* with the rule that a **null or absent name mints a fresh isolate every time** —
|
|
35
|
+
* which upstream's own `isolateUniqueness` test pins at
|
|
36
|
+
* `api/tests/worker-loader-test.js:527-541`. So what this layer owns is which name
|
|
37
|
+
* reaches the seam: `load(code)` is documented as "Shortcut for `get(null, () =>
|
|
38
|
+
* code)`" and both it and `get(null)` pass none.
|
|
39
|
+
*
|
|
40
|
+
* **What `load()` owns that `get()` does not is *when* the code is validated.**
|
|
41
|
+
* `load()` builds the whole `DynamicWorkerSource` synchronously before it returns
|
|
42
|
+
* (`worker-loader.c++:88`), so a malformed module list throws out of `load()`;
|
|
43
|
+
* `get()` defers everything into the callback, so the same mistake surfaces at the
|
|
44
|
+
* first request on the stub, which is what upstream's tests assert
|
|
45
|
+
* (`worker-loader-test.js:812`, `:829`, `:856`). That eager capture is also a
|
|
46
|
+
* memory-safety fix: `data` and `wasm` bytes are copied out of the caller's buffer
|
|
47
|
+
* at that moment, because a resizable `ArrayBuffer` can be shrunk to zero
|
|
48
|
+
* afterwards (`worker-loader.c++:225-232`, `:242-245`, and
|
|
49
|
+
* `api/tests/worker-loader-rab-test.js`).
|
|
50
|
+
*
|
|
51
|
+
* **`globalOutbound: null` is the default posture, per decision 15, and what it
|
|
52
|
+
* enforces here is one hop further out than on workerd.** Upstream substitutes a
|
|
53
|
+
* `NullGlobalOutboundChannel` whose `startRequest` throws
|
|
54
|
+
* (`server.c++:4306-4331`), so ambient `fetch` inside the loaded Worker fails from
|
|
55
|
+
* inside the isolate. This layer's whole job is the same one upstream's is:
|
|
56
|
+
* collapse the three JS states — omitted, `null`, a `Fetcher` — into the two the
|
|
57
|
+
* source carries, where absent means blocked and omitted means the caller's own
|
|
58
|
+
* outbound. Enforcement belongs to whatever `loadIsolate` returns, because that is
|
|
59
|
+
* the thing with an isolate to deny.
|
|
60
|
+
*
|
|
61
|
+
* **The one thing this file refuses that upstream refuses elsewhere.**
|
|
62
|
+
* `Frankenvalue::fromJs` serializes `props` and `env` inside these methods, and a
|
|
63
|
+
* `ctx.exports` binding that has not been invoked declares no `JSG_SERIALIZABLE`,
|
|
64
|
+
* so it is refused there with a `DataCloneError` — pinned at
|
|
65
|
+
* `api/tests/worker-loader-test.js:104`. `api/export-loopback.ts`'s header records
|
|
66
|
+
* that refusal as not surviving; it survives here, because this is the layer
|
|
67
|
+
* upstream refuses at. See `requireSerializableProps` below.
|
|
68
|
+
*
|
|
69
|
+
* **There are no source or `env` size caps, and an earlier statement of this
|
|
70
|
+
* section's spec said there were** — "64 MiB of module source, 1 MiB of `env`
|
|
71
|
+
* (`worker-loader.c++:15-21`)". Those lines are `WorkerStub::getEntrypoint`'s
|
|
72
|
+
* props-and-limits prologue, and no cap of either size exists anywhere in the
|
|
73
|
+
* open-source runtime: the complete list of refusals in the load path is the ten
|
|
74
|
+
* `JSG_REQUIRE`/`JSG_FAIL_REQUIRE` sites this file ports, and none of them
|
|
75
|
+
* measures a length. Those are Cloudflare's documented *production* limits, which
|
|
76
|
+
* workerd does not reproduce — the same class of thing as `ResourceLimits`, and
|
|
77
|
+
* recorded on it. Nothing here counts bytes.
|
|
78
|
+
*
|
|
79
|
+
* Spec: §1.11, decisions 15 and 16 in
|
|
80
|
+
* docs/decisions.md.
|
|
81
|
+
*/
|
|
82
|
+
import type { CompatibilityDateValidation, DynamicWorkerSource, ResourceLimits, WorkerStubChannel } from "../io/io-channels.js";
|
|
83
|
+
import type { IoContext } from "../io/io-context.js";
|
|
84
|
+
import { DurableObjectClass } from "./actor.js";
|
|
85
|
+
/** ← `JSG_REQUIRE(code.modules.fields.size() > 0, …)` (`worker-loader.c++:175-176`). */
|
|
86
|
+
export declare const NO_MODULES_MESSAGE = "Dynamic Worker code must contain at least one module.";
|
|
87
|
+
/** ← `JSG_FAIL_REQUIRE` at `worker-loader.c++:204-206`. */
|
|
88
|
+
export declare function moduleNameMessage(name: string): string;
|
|
89
|
+
/**
|
|
90
|
+
* ← `JSG_FAIL_REQUIRE` at `worker-loader.c++:197-201`, the `.ts` / `.tsx` / `.jsx`
|
|
91
|
+
* arm. Upstream's is the message above plus the bundler suggestion.
|
|
92
|
+
*/
|
|
93
|
+
export declare function typeScriptModuleNameMessage(name: string): string;
|
|
94
|
+
/** ← `JSG_REQUIRE(fieldCount == 1, …)` (`worker-loader.c++:212-215`). */
|
|
95
|
+
export declare function moduleFieldCountMessage(name: string, fieldCount: number): string;
|
|
96
|
+
/** ← `JSG_FAIL_REQUIRE` at `worker-loader.c++:261-262`. */
|
|
97
|
+
export declare function jsModuleInPythonWorkerMessage(name: string): string;
|
|
98
|
+
/** ← `JSG_FAIL_REQUIRE` at `worker-loader.c++:266-267`. */
|
|
99
|
+
export declare function pythonModuleInJsWorkerMessage(name: string): string;
|
|
100
|
+
/** ← `JSG_REQUIRE` at `worker-loader.c++:152-154`. Upstream's carries no closing period. */
|
|
101
|
+
export declare const STREAMING_TAILS_EXPERIMENTAL_MESSAGE: string;
|
|
102
|
+
/**
|
|
103
|
+
* ← `JSG_REQUIRE_NONNULL(weakIoctx->tryGet(), Error, …)` (`worker-loader.c++:73-74`),
|
|
104
|
+
* the guard the AUTOVULN-CLOUDFLARE-WORKERD-256 fix added.
|
|
105
|
+
*
|
|
106
|
+
* **The precondition differs and the failure mode nearly did too.** Upstream's
|
|
107
|
+
* `IoContext` is per REQUEST, so a stub can outlive the context that made it and
|
|
108
|
+
* the raw `&ioctx` capture was a use-after-free; the WeakRef turns that into this
|
|
109
|
+
* message. Ours is per CONTAINER and outlives every stub it made, so the
|
|
110
|
+
* destroyed case cannot happen — what remains reachable is an **aborted** actor,
|
|
111
|
+
* and for that `IoContext::awaitIo` deliberately leaves its promise unsettled
|
|
112
|
+
* ("`result` is deliberately left unsettled, as upstream leaves it",
|
|
113
|
+
* `io/io-context.ts`). Upstream can afford that because `runAlarm`'s caller and
|
|
114
|
+
* everything else in a torn-down request is being destroyed anyway; a dynamic
|
|
115
|
+
* worker load cannot, because `WorkerStubChannel`'s contract is that a failed
|
|
116
|
+
* load makes every request on the stub **fail** — a load that never settles makes
|
|
117
|
+
* every request on the stub hang instead, which is the failure this repository's
|
|
118
|
+
* own divergence 149 exists to prevent ("a JS promise has to settle, and one that
|
|
119
|
+
* never does is a hang nobody can see"). So the abort is observed explicitly and
|
|
120
|
+
* answered with upstream's own message.
|
|
121
|
+
*/
|
|
122
|
+
export declare const DEAD_LOAD_CONTEXT_MESSAGE = "The request which initiated this dynamic worker load has already completed.";
|
|
123
|
+
/** ← `JSG_REQUIRE(!allowExperimental, …)` (`worker-loader.c++:282-284`). */
|
|
124
|
+
export declare const ALLOW_EXPERIMENTAL_MESSAGE: string;
|
|
125
|
+
/**
|
|
126
|
+
* ← `Serializer::throwDataCloneErrorForObject` (`jsg/ser.c++:175-183`), whose type
|
|
127
|
+
* name is `obj->GetConstructorName()` — the JSG resource type's name, which is the
|
|
128
|
+
* class name here. Pinned for `LoopbackServiceStub` at
|
|
129
|
+
* `api/tests/worker-loader-test.js:104`.
|
|
130
|
+
*/
|
|
131
|
+
export declare function notSerializableMessage(typeName: string): string;
|
|
132
|
+
/** Not something `jsg::asBytes()` would accept for a `kj::Array<const byte>` body. */
|
|
133
|
+
export declare const NOT_BYTES_MESSAGE = "A module's 'data' or 'wasm' body must be an ArrayBuffer or a view over one.";
|
|
134
|
+
/**
|
|
135
|
+
* ← the two arguments `IoChannelFactory::loadIsolate` takes besides the channel
|
|
136
|
+
* number (`io/io-channels.h:339-343`). Upstream: "Use a dynamic Worker loader
|
|
137
|
+
* binding to obtain an Worker by name. If name is null, or if the named Worker
|
|
138
|
+
* doesn't already exist, the callback will be called to fetch the source code from
|
|
139
|
+
* which the Worker should be created."
|
|
140
|
+
*
|
|
141
|
+
* Upstream's own note on the callback, at `worker-loader.c++:90-94`, is the
|
|
142
|
+
* contract an implementation has to honour: "the callback we pass to
|
|
143
|
+
* `loadIsolate()` technically may be called any number of times. Yes, even though
|
|
144
|
+
* we aren't providing an ID. The runtime can actually evict the isolate while a
|
|
145
|
+
* stub still exists, as long as there is no active request on the stub, and then
|
|
146
|
+
* recreate the isolate on the next request."
|
|
147
|
+
*/
|
|
148
|
+
export type LoadIsolateRequest = {
|
|
149
|
+
/**
|
|
150
|
+
* ← `kj::Maybe<kj::String> name`. Absent means the isolate is not cached and a
|
|
151
|
+
* fresh one is minted per call (`server.c++:4264-4281`).
|
|
152
|
+
*/
|
|
153
|
+
readonly name: string | undefined;
|
|
154
|
+
/** ← `kj::Function<kj::Promise<DynamicWorkerSource>()> fetchSource`. */
|
|
155
|
+
fetchSource(): Promise<DynamicWorkerSource>;
|
|
156
|
+
};
|
|
157
|
+
/**
|
|
158
|
+
* ← `IoChannelFactory`'s two dynamic-worker methods, collapsed the way
|
|
159
|
+
* `api/actor.ts` and `api/export-loopback.ts` already collapse theirs: both take a
|
|
160
|
+
* channel *number* upstream and there is no numbered channel table here, so each
|
|
161
|
+
* becomes a factory method taking an object request. Declared beside its one
|
|
162
|
+
* consumer for the same reason `ActorChannelFactory` is.
|
|
163
|
+
*
|
|
164
|
+
* This is the whole substrate seam of §1.11. A host implements it three ways — the
|
|
165
|
+
* offscreen document in the browser, an in-realm module evaluation under Node, and
|
|
166
|
+
* the real `worker_loaders` binding on workerd — and nothing above it has to know
|
|
167
|
+
* which.
|
|
168
|
+
*/
|
|
169
|
+
export interface IsolateChannelFactory {
|
|
170
|
+
/** ← `IoChannelFactory::loadIsolate`. Returns before the Worker has loaded. */
|
|
171
|
+
loadIsolate(request: LoadIsolateRequest): WorkerStubChannel;
|
|
172
|
+
/**
|
|
173
|
+
* ← `getSubrequestChannel(IoContext::NULL_CLIENT_CHANNEL)`
|
|
174
|
+
* (`worker-loader.c++:137-138`, `io/io-context.h:753`) — the calling worker's own
|
|
175
|
+
* global outbound, which a loaded Worker inherits when `globalOutbound` is
|
|
176
|
+
* omitted. Upstream reaches it by channel number 0; with no channel table it is a
|
|
177
|
+
* method on the one factory that needs it.
|
|
178
|
+
*
|
|
179
|
+
* Upstream deliberately does not call `requireAllowsTransfer()` on this one: "if
|
|
180
|
+
* it was the global outbound of the parent, it must be OK to be the global
|
|
181
|
+
* outbound of the child."
|
|
182
|
+
*/
|
|
183
|
+
getNullClientChannel(): Fetcher;
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* ← `WorkerLoader::Module` (`worker-loader.h:62-78`). "Exactly one must be filled
|
|
187
|
+
* in."
|
|
188
|
+
*
|
|
189
|
+
* `data` and `wasm` are `ArrayBuffer | ArrayBufferView` where
|
|
190
|
+
* `@cloudflare/workers-types` declares `ArrayBuffer`, because upstream unwraps
|
|
191
|
+
* them with `jsg::asBytes()`, which accepts either — and upstream's own tests pass
|
|
192
|
+
* a `Uint8Array` to both (`worker-loader-test.js:585`, `:645`). A superset of the
|
|
193
|
+
* pinned types, the same relationship `DurableObjectNamespace.getExisting` has.
|
|
194
|
+
*
|
|
195
|
+
* `serializedJson` is absent: upstream's own comment calls it a HACK for owning
|
|
196
|
+
* the string `Worker::Script::Source` only borrows, and a JS string is owned.
|
|
197
|
+
*/
|
|
198
|
+
export type Module = {
|
|
199
|
+
/** ES module. */
|
|
200
|
+
readonly js?: string;
|
|
201
|
+
/** Common JS module. */
|
|
202
|
+
readonly cjs?: string;
|
|
203
|
+
/** "text blob, imports as a string" */
|
|
204
|
+
readonly text?: string;
|
|
205
|
+
/** "byte blob, imports as ArrayBuffer" */
|
|
206
|
+
readonly data?: ArrayBuffer | ArrayBufferView;
|
|
207
|
+
/** "arbitrary JS value, will be serialized to JSON and then parsed again when imported" */
|
|
208
|
+
readonly json?: unknown;
|
|
209
|
+
/** Python module. */
|
|
210
|
+
readonly py?: string;
|
|
211
|
+
/** "compiled WASM module" */
|
|
212
|
+
readonly wasm?: ArrayBuffer | ArrayBufferView;
|
|
213
|
+
};
|
|
214
|
+
/** ← `WorkerLoader::WorkerCode` (`worker-loader.h:80-120`). */
|
|
215
|
+
export type WorkerCode = {
|
|
216
|
+
readonly compatibilityDate: string;
|
|
217
|
+
readonly compatibilityFlags?: readonly string[];
|
|
218
|
+
readonly allowExperimental?: boolean;
|
|
219
|
+
readonly limits?: ResourceLimits;
|
|
220
|
+
readonly mainModule: string;
|
|
221
|
+
/**
|
|
222
|
+
* "Modules are specified as an object mapping names to content. If the content is
|
|
223
|
+
* just a string, an ES module is assumed. If it's an object, the type of module
|
|
224
|
+
* is determined based on which property is set."
|
|
225
|
+
*/
|
|
226
|
+
readonly modules: Record<string, Module | string>;
|
|
227
|
+
/** "Any RPC-serializable value!" */
|
|
228
|
+
readonly env?: unknown;
|
|
229
|
+
/**
|
|
230
|
+
* "`Fetcher` (e.g. service binding) representing the loaded worker's global
|
|
231
|
+
* outbound. If omitted, inherit the current worker's global outbound. If `null`,
|
|
232
|
+
* block the global outbound (all requests throw errors)."
|
|
233
|
+
*/
|
|
234
|
+
readonly globalOutbound?: Fetcher | null;
|
|
235
|
+
/** "Specify tail workers." */
|
|
236
|
+
readonly tails?: readonly Fetcher[];
|
|
237
|
+
readonly streamingTails?: readonly Fetcher[];
|
|
238
|
+
};
|
|
239
|
+
/** ← `WorkerStub::EntrypointOptions` (`worker-loader.h:22-27`). */
|
|
240
|
+
export type EntrypointOptions = {
|
|
241
|
+
readonly props?: unknown;
|
|
242
|
+
readonly limits?: ResourceLimits;
|
|
243
|
+
};
|
|
244
|
+
/**
|
|
245
|
+
* ← `WorkerStub` (`worker-loader.h:15-50`). "JS stub pointing to a remote Worker
|
|
246
|
+
* loaded using WorkerLoader. This is not a stub for a specific entrypoint, but
|
|
247
|
+
* instead the entire Worker, allowing the caller to call any entrypoint (and
|
|
248
|
+
* specify arbitrary props)."
|
|
249
|
+
*/
|
|
250
|
+
export declare class WorkerStub implements globalThis.WorkerStub {
|
|
251
|
+
#private;
|
|
252
|
+
constructor(channel: WorkerStubChannel);
|
|
253
|
+
/** ← `WorkerStub::getEntrypoint` (`worker-loader.c++:13-36`). */
|
|
254
|
+
getEntrypoint<T extends Rpc.WorkerEntrypointBranded | undefined = undefined>(name?: string | null, options?: EntrypointOptions): Fetcher<T>;
|
|
255
|
+
/**
|
|
256
|
+
* ← `WorkerStub::getDurableObjectClass` (`worker-loader.c++:38-61`).
|
|
257
|
+
*
|
|
258
|
+
* **This is the bridge into facets and it is a real connection, not a named
|
|
259
|
+
* boundary.** The `ActorClassChannel` the channel answers with is the same token
|
|
260
|
+
* `DurableObjectClass.getChannel()` hands to `FacetStartInfo.actorClass`, which
|
|
261
|
+
* `FacetManager.getFacet` hands to `FacetHost.start` — so a class obtained here
|
|
262
|
+
* goes straight into `ctx.facets.get(name, () => ({ class }))` with nothing in
|
|
263
|
+
* between, which is exactly the shape upstream's `FacetTestActor` uses
|
|
264
|
+
* (`worker-loader-test.js:421-433`).
|
|
265
|
+
*/
|
|
266
|
+
getDurableObjectClass<T extends Rpc.DurableObjectBranded | undefined = undefined>(name?: string | null, options?: EntrypointOptions): DurableObjectClass<T>;
|
|
267
|
+
}
|
|
268
|
+
/**
|
|
269
|
+
* The two constructor inputs upstream's `WorkerLoader` resolves from ambients this
|
|
270
|
+
* package does not have.
|
|
271
|
+
*/
|
|
272
|
+
export type WorkerLoaderOptions = {
|
|
273
|
+
/**
|
|
274
|
+
* ← `WorkerLoader`'s second constructor parameter (`worker-loader.h:58`), whose
|
|
275
|
+
* comment is "`compatDateValidation` will differ between workerd vs.
|
|
276
|
+
* production". It is carried onto the `DynamicWorkerSource` rather than consumed
|
|
277
|
+
* here, because the compilation it feeds is a substrate boundary — see
|
|
278
|
+
* `CompatibilityFlagsRequest` in `io/io-channels.ts`.
|
|
279
|
+
*/
|
|
280
|
+
readonly compatDateValidation: CompatibilityDateValidation;
|
|
281
|
+
/**
|
|
282
|
+
* ← `FeatureFlags::get(js).getWorkerdExperimental()` (`worker-loader.c++:281`) —
|
|
283
|
+
* the *calling* worker's `experimental` compatibility flag, which gates
|
|
284
|
+
* `allowExperimental` on the loaded one.
|
|
285
|
+
*
|
|
286
|
+
* Every other compatibility flag this package meets was answered by "a runtime
|
|
287
|
+
* with no deployed history takes the current behaviour" (`api/actor.ts`, and the
|
|
288
|
+
* README row for `deleteAllDeletesAlarm`). That reading does not work here:
|
|
289
|
+
* `experimental` has no default-on date and never turns on by itself, so taking
|
|
290
|
+
* the current behaviour would hard-code `false`, make `allowExperimental: true`
|
|
291
|
+
* always throw, and put `streamingTails` out of reach — the feature subset the
|
|
292
|
+
* README's second paragraph forbids. So the bit moves from an ambient to an
|
|
293
|
+
* explicit input, which is what this package does with every ambient.
|
|
294
|
+
* `compileCompatibilityFlags`'s own parameter for the same bit is named
|
|
295
|
+
* `allowExperimentalFeatures`.
|
|
296
|
+
*/
|
|
297
|
+
readonly allowExperimentalFeatures: boolean;
|
|
298
|
+
};
|
|
299
|
+
/**
|
|
300
|
+
* ← `WorkerLoader` (`worker-loader.h:52-150`). "JS interface for worker loader
|
|
301
|
+
* binding."
|
|
302
|
+
*
|
|
303
|
+
* Takes an `IoContext` where upstream reads `IoContext::current()`, which is the
|
|
304
|
+
* substitution every class in `api/` makes (`DurableObjectFacets`,
|
|
305
|
+
* `DurableObjectStorageOperations`); and an `IsolateChannelFactory` where upstream
|
|
306
|
+
* holds a channel number, which is the substitution every outgoing seam in `api/`
|
|
307
|
+
* makes.
|
|
308
|
+
*/
|
|
309
|
+
export declare class WorkerLoader implements globalThis.WorkerLoader {
|
|
310
|
+
#private;
|
|
311
|
+
constructor(ctx: IoContext, channel: IsolateChannelFactory, options: WorkerLoaderOptions);
|
|
312
|
+
/**
|
|
313
|
+
* ← `WorkerLoader::get` (`worker-loader.c++:63-83`).
|
|
314
|
+
*
|
|
315
|
+
* Nothing is validated here: the code callback is deferred whole into the reentry
|
|
316
|
+
* callback, so every refusal `toDynamicWorkerSource` can make surfaces at the
|
|
317
|
+
* first request on the returned stub instead. That is upstream's own behaviour
|
|
318
|
+
* and its tests depend on it.
|
|
319
|
+
*/
|
|
320
|
+
get(name: string | null | undefined, getCode: () => WorkerCode | Promise<WorkerCode>): WorkerStub;
|
|
321
|
+
/**
|
|
322
|
+
* ← `WorkerLoader::load` (`worker-loader.c++:85-107`). "Shortcut for `get(null,
|
|
323
|
+
* () => code)`."
|
|
324
|
+
*
|
|
325
|
+
* A shortcut with two consequences upstream states outright. The source is built
|
|
326
|
+
* **now**, synchronously, so every refusal below throws from this call rather
|
|
327
|
+
* than from the first request; and `name` is `kj::none`, so the isolate is not
|
|
328
|
+
* cached and a fresh Worker is minted per call.
|
|
329
|
+
*
|
|
330
|
+
* Upstream's clone-per-invocation is absent because a JS source object is
|
|
331
|
+
* immutable and shared safely — see `io/worker-source.ts`'s header. The
|
|
332
|
+
* atomic-refcount wrapper it needs for that ("it may ultimately destroy the
|
|
333
|
+
* `ownContent` in another thread ... Ugh!") goes with it.
|
|
334
|
+
*/
|
|
335
|
+
load(code: WorkerCode): WorkerStub;
|
|
336
|
+
}
|
|
337
|
+
/** `Value` must be assignable to `Declared`; declaring the constraint is the check. */
|
|
338
|
+
type Assignable<Value extends Declared, Declared> = Value;
|
|
339
|
+
/**
|
|
340
|
+
* §2.4's no-cast rule: these reach a consumer as `env` bindings typed by
|
|
341
|
+
* `@cloudflare/workers-types`, so the type system checks the surface rather than a
|
|
342
|
+
* cast doing it. The three struct rows point the other way, because a struct is an
|
|
343
|
+
* argument: what has to hold is that every code a consumer can write against the
|
|
344
|
+
* pinned type is one this file accepts. `Module` is a strict superset by the two
|
|
345
|
+
* byte fields, for the reason its own comment gives.
|
|
346
|
+
*/
|
|
347
|
+
export type PinnedWorkerLoaderTypes = [
|
|
348
|
+
Assignable<WorkerLoader, globalThis.WorkerLoader>,
|
|
349
|
+
Assignable<WorkerStub, globalThis.WorkerStub>,
|
|
350
|
+
Assignable<globalThis.WorkerLoaderWorkerCode, WorkerCode>,
|
|
351
|
+
Assignable<globalThis.WorkerLoaderModule, Module>,
|
|
352
|
+
Assignable<globalThis.WorkerStubEntrypointOptions, EntrypointOptions>
|
|
353
|
+
];
|
|
354
|
+
export {};
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@mcp-b/do-runtime` — the browser implementation of the workerd Durable
|
|
3
|
+
* Object contract. No knowledge of any host application.
|
|
4
|
+
*
|
|
5
|
+
* NO upstream correspondence: this file is the package facade. Everything it
|
|
6
|
+
* re-exports has one.
|
|
7
|
+
*
|
|
8
|
+
* Gates, `IoContext`, storage internals, the facet index, and deletion receipts
|
|
9
|
+
* stay private. Hosts use the `ActorContainer` lifecycle rather than holding a
|
|
10
|
+
* runtime lock or table directly.
|
|
11
|
+
*
|
|
12
|
+
* The `api/` classes are not exported either, for the same reason and one more.
|
|
13
|
+
* `DurableObjectStorage`, `DurableObjectState`, `SqlStorage` and `SyncKvStorage`
|
|
14
|
+
* reach a consumer as `container.state` and its properties, already typed by
|
|
15
|
+
* workers-types; handing out the constructors would let one be built over a
|
|
16
|
+
* gate the container does not own. `FacetManager` is internal for the mirror
|
|
17
|
+
* reason: it is what `server/` implements and `api/` consumes, and the seam a
|
|
18
|
+
* consumer fills is `FacetHost` below it.
|
|
19
|
+
*
|
|
20
|
+
* Refusal messages used by conformance tests are exported so their specified
|
|
21
|
+
* fail-closed behavior cannot drift. `createActorContainer` is asynchronous
|
|
22
|
+
* because `SqlDatabaseProvider.open` is asynchronous; a returned container has
|
|
23
|
+
* usable state and no hidden half-started storage phase.
|
|
24
|
+
*/
|
|
25
|
+
export type { SqlDatabase, SqlDatabaseProvider, SqlDatabaseSnapshot, SqlDatabaseSnapshotProvider, SqlResult, SqlValue, } from "./util/sqlite.js";
|
|
26
|
+
export type { ReadOptions, WriteOptions } from "./io/actor-cache.js";
|
|
27
|
+
export type { AlarmOutlet } from "./io/actor-sqlite.js";
|
|
28
|
+
export type { Timer } from "./io/io-context.js";
|
|
29
|
+
/**
|
|
30
|
+
* The Worker Loader (§1.11, decision 15). Exported where the `api/` classes are
|
|
31
|
+
* not, and for the reason `AlarmScheduler` is: this one is a **binding**, so a
|
|
32
|
+
* host has to construct it and put it in `env` — upstream compiles it from
|
|
33
|
+
* `Global::WorkerLoader{channel}` the same way (`server/workerd-api.c++:748`) —
|
|
34
|
+
* where every other `api/` class reaches a consumer through `container.state`.
|
|
35
|
+
*
|
|
36
|
+
* What a host supplies is `IsolateChannelFactory`, which is the whole substrate
|
|
37
|
+
* seam: `loadIsolate` and the calling worker's own outbound. The scaffolding's
|
|
38
|
+
* `IsolateHost` / `SandboxExecuteRequest` / `SandboxNamespaceDescriptor` /
|
|
39
|
+
* `SandboxToolDispatch` are gone — see `api/worker-loader.ts`'s header for what
|
|
40
|
+
* the C++ wanted instead.
|
|
41
|
+
*/
|
|
42
|
+
export type { EntrypointOptions, IsolateChannelFactory, LoadIsolateRequest, Module, WorkerCode, WorkerLoaderOptions, } from "./api/worker-loader.js";
|
|
43
|
+
export { ALLOW_EXPERIMENTAL_MESSAGE, DEAD_LOAD_CONTEXT_MESSAGE, NO_MODULES_MESSAGE, NOT_BYTES_MESSAGE, STREAMING_TAILS_EXPERIMENTAL_MESSAGE, WorkerLoader, WorkerStub, jsModuleInPythonWorkerMessage, moduleFieldCountMessage, moduleNameMessage, notSerializableMessage, pythonModuleInJsWorkerMessage, typeScriptModuleNameMessage, } from "./api/worker-loader.js";
|
|
44
|
+
export type { ActorClassChannel, CompatibilityDateValidation, CompatibilityFlagsRequest, DynamicWorkerSource, EntrypointRequest, ResourceLimits, WorkerStubChannel, } from "./io/io-channels.js";
|
|
45
|
+
export type { Module as SourceModule, ModuleContent, ModulesSource, WorkerSource, } from "./io/worker-source.js";
|
|
46
|
+
/**
|
|
47
|
+
* The container's own surface. Every one of these is DECLARED in
|
|
48
|
+
* `server/actor-container.ts` rather than here, and re-exported, because
|
|
49
|
+
* TypeScript's project references run the same way workerd's Bazel targets do:
|
|
50
|
+
* `src/` references `src/server/`, so a declaration in this file is one
|
|
51
|
+
* `server/` may not import.
|
|
52
|
+
*/
|
|
53
|
+
export type { ActorContainer, ActorContainerOptions, ActorEntry, ActorPorts, FacetHandle, FacetHost, FacetId, FacetStartRequest, FacetTree, } from "./server/actor-container.js";
|
|
54
|
+
export { createActorContainer, FACET_ALARM_UNIMPLEMENTED_MESSAGE, noFacets, } from "./server/actor-container.js";
|
|
55
|
+
export { ACTOR_CLASS_SERIALIZATION_UNIMPLEMENTED_MESSAGE } from "./api/actor.js";
|
|
56
|
+
/**
|
|
57
|
+
* The `ctx.exports` entries, exported where the rest of `api/` is not — for the
|
|
58
|
+
* reason `WorkerLoader` and `AlarmScheduler` are: a HOST has to construct these.
|
|
59
|
+
*
|
|
60
|
+
* `ActorContainerOptions.exports` is a `Record<string, unknown>` a host fills,
|
|
61
|
+
* and `DurableObjectFacets.get` discriminates its class switch by `instanceof`
|
|
62
|
+
* against exactly these types (`api/actor-state.ts`). So a host that cannot build
|
|
63
|
+
* one cannot register an actor class at all, and every consumer would have to
|
|
64
|
+
* reach into `src/api/` past this facade to do it — which is worse than saying
|
|
65
|
+
* here that these are the two a host is meant to have.
|
|
66
|
+
*
|
|
67
|
+
* They carry no gate and no context: a `LoopbackDurableObjectClass` holds an
|
|
68
|
+
* `ActorClassChannelFactory`, which answers a `className` and nothing else. That
|
|
69
|
+
* is why exporting them cannot reproduce the hazard the rest of `api/` is withheld
|
|
70
|
+
* for — there is no container for one to be built over the wrong one of.
|
|
71
|
+
*/
|
|
72
|
+
export type { LoopbackDurableObjectClassOptions, LoopbackDurableObjectClassValue, ActorClassChannelFactory, } from "./api/export-loopback.js";
|
|
73
|
+
export { asLoopbackDurableObjectClass, LoopbackDurableObjectClass } from "./api/export-loopback.js";
|
|
74
|
+
export { FACET_NAME_MAX_LENGTH, FACET_TREE_MAX_DEPTH, HIBERNATION_UNIMPLEMENTED_MESSAGE, } from "./api/actor-state.js";
|
|
75
|
+
export { PITR_UNIMPLEMENTED_MESSAGE, REPLICATION_UNIMPLEMENTED_MESSAGE } from "./io/actor-cache.js";
|
|
76
|
+
/**
|
|
77
|
+
* The alarm scheduler is exported where the gate is not, and the difference is
|
|
78
|
+
* upstream's own: `AlarmScheduler` is a per-NAMESPACE object a supervisor builds
|
|
79
|
+
* and wires into each actor's storage hooks (`server.c++:2325-2350`,
|
|
80
|
+
* `:3199-3219`), not a per-actor internal. A host has to construct it, because a
|
|
81
|
+
* host is what knows how to resolve an actor id to a container — so it is the
|
|
82
|
+
* implementation a host puts behind `ActorPorts.alarms`, via `hooks(actorId)`,
|
|
83
|
+
* rather than something `createActorContainer` could build for itself.
|
|
84
|
+
*/
|
|
85
|
+
export type { AlarmResult, AlarmSchedulerOptions, AlarmTarget, EventOutcome, GetActorFn, } from "./server/alarm-scheduler.js";
|
|
86
|
+
export { ALARM_RETRY_MAX_TRIES, ALARM_RETRY_START_SECONDS, AlarmScheduler, RETRY_BACKOFF_MAX, RETRY_JITTER_FACTOR, alarmRetryDelayMs, } from "./server/alarm-scheduler.js";
|
|
87
|
+
/**
|
|
88
|
+
* The refusing outlet (`ActorSqlite::Hooks::DEFAULT` upstream) — the
|
|
89
|
+
* `ports.alarms` for a host that schedules nothing, as `noFacets` is its
|
|
90
|
+
* `ports.facets`. A real root actor gets `AlarmScheduler.hooks(id)` instead.
|
|
91
|
+
*/
|
|
92
|
+
export { DEFAULT_ALARM_OUTLET } from "./io/actor-sqlite.js";
|
|
93
|
+
/** The object an `alarm()` handler is called with (`api/global-scope.h:386-412`). */
|
|
94
|
+
export { AlarmInvocationInfo } from "./api/global-scope.js";
|
|
95
|
+
/**
|
|
96
|
+
* The async primitives, which a host INSTALLS rather than constructs.
|
|
97
|
+
*
|
|
98
|
+
* `ActorGlobalScope` is exported as a type only, and `Scheduler` with it: both
|
|
99
|
+
* reach a consumer as `container.globals`, already bound to that container's
|
|
100
|
+
* `IoContext`. Handing out the constructor would let one be built over a context
|
|
101
|
+
* the container does not own, which is the reason `DurableObjectState` and the
|
|
102
|
+
* rest of `api/` are not exported either — and here it would be worse, because
|
|
103
|
+
* the value would look right and gate the wrong actor.
|
|
104
|
+
*
|
|
105
|
+
* The two refusal messages ARE exported, for the reason the substrate-boundary
|
|
106
|
+
* messages above are: they are the specified behaviour, and a message a test
|
|
107
|
+
* re-types by hand is one that drifts.
|
|
108
|
+
*
|
|
109
|
+
* `acceptWebSocket` reaches a consumer as `container.acceptWebSocket` for the
|
|
110
|
+
* same reason, so only its types are here.
|
|
111
|
+
*/
|
|
112
|
+
export type { ActorGlobalScope, ActorGlobalScopeOptions, ActorScopeBindings, FetchPort, Scheduler, SchedulerWaitOptions, } from "./api/global-scope.js";
|
|
113
|
+
export { actorScopeBindings, FOREIGN_SLICE_MESSAGE, installActorScope, NO_GLOBAL_OUTBOUND_MESSAGE, } from "./api/global-scope.js";
|
|
114
|
+
export type { AcceptedWebSocket, RawWebSocket } from "./api/web-socket.js";
|
|
115
|
+
export { ALREADY_ACCEPTED_MESSAGE } from "./api/web-socket.js";
|
|
116
|
+
export { BYOB_READER_UNGATABLE_MESSAGE, gateRequestBody } from "./api/http.js";
|
|
117
|
+
/**
|
|
118
|
+
* The transport, for the same reason the loader binding and the scheduler are
|
|
119
|
+
* here: the hops a host owns are not something `createActorContainer` could
|
|
120
|
+
* construct for it. `newRpcSession` is the door onto capnweb, and a host still
|
|
121
|
+
* needs it — the browser conformance lane's page↔actor session and its
|
|
122
|
+
* actor↔actor routing through the page are both one — because those hops are
|
|
123
|
+
* between SUPERVISED actors, which is a different question from where a facet
|
|
124
|
+
* sits.
|
|
125
|
+
*
|
|
126
|
+
* `newRpcSession` is exported so that going around it is deliberate. It applies
|
|
127
|
+
* decision 18's identity graft immediately before opening each session; see
|
|
128
|
+
* `transport/rpc-session.ts`.
|
|
129
|
+
*/
|
|
130
|
+
export { newRpcSession } from "./transport/rpc-session.js";
|