exoagent 0.0.1 → 0.0.2
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/README.md +109 -30
- package/dist/capnweb/index-workers.cjs +2811 -0
- package/dist/capnweb/index-workers.cjs.map +1 -0
- package/dist/capnweb/index-workers.d.cts +2 -0
- package/dist/capnweb/index-workers.d.ts +2 -0
- package/dist/capnweb/index-workers.js +2774 -0
- package/dist/capnweb/index-workers.js.map +1 -0
- package/dist/capnweb/index.cjs +2788 -0
- package/dist/capnweb/index.cjs.map +1 -0
- package/dist/capnweb/index.d.cts +383 -0
- package/dist/capnweb/index.d.ts +383 -0
- package/dist/{code-mode-runtime.mjs → capnweb/index.js} +342 -90
- package/dist/capnweb/index.js.map +1 -0
- package/dist/capnweb-test-helpers.d.ts +25 -0
- package/dist/code-mode-deno.d.ts +13 -0
- package/dist/code-mode-runtime.d.ts +1 -0
- package/dist/code-mode.d.ts +39 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.mjs +97 -3391
- package/dist/rpc-toolset-BnC2BXPq.js +146 -0
- package/dist/rpc-toolset-test-helpers.d.mts +11 -2
- package/dist/rpc-toolset-test-helpers.d.ts +45 -0
- package/dist/rpc-toolset-test-helpers.mjs +12 -1371
- package/dist/rpc-toolset.d.ts +34 -0
- package/dist/sql/builder.d.ts +127 -0
- package/dist/sql/expression.d.ts +69 -0
- package/dist/sql/sql.d.ts +4 -0
- package/dist/sql/test-helpers.d.ts +9 -0
- package/dist/sql.d.ts +2 -0
- package/dist/sql.mjs +553 -0
- package/dist/stream-transport.d.ts +11 -0
- package/dist/tool-wrapper.d.ts +16 -0
- package/package.json +26 -12
- package/dist/index.d.mts +0 -426
package/dist/index.mjs
CHANGED
|
@@ -1,2687 +1,62 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
};
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
return __privateSet(this, extra, x);
|
|
27
|
-
} }, name));
|
|
28
|
-
k ? p && k < 4 && __name(extra, (k > 2 ? "set " : k > 1 ? "get " : "") + name) : __name(target, name);
|
|
29
|
-
for (var i = decorators.length - 1; i >= 0; i--) {
|
|
30
|
-
ctx = __decoratorContext(k, name, done = {}, array[3], extraInitializers);
|
|
31
|
-
if (k) {
|
|
32
|
-
ctx.static = s, ctx.private = p, access = ctx.access = { has: p ? (x) => __privateIn(target, x) : (x) => name in x };
|
|
33
|
-
if (k ^ 3) access.get = p ? (x) => (k ^ 1 ? __privateGet : __privateMethod)(x, target, k ^ 4 ? extra : desc.get) : (x) => x[name];
|
|
34
|
-
if (k > 2) access.set = p ? (x, y) => __privateSet(x, target, y, k ^ 4 ? extra : desc.set) : (x, y) => x[name] = y;
|
|
35
|
-
}
|
|
36
|
-
it = (0, decorators[i])(k ? k < 4 ? p ? extra : desc[key] : k > 4 ? void 0 : { get: desc.get, set: desc.set } : target, ctx), done._ = 1;
|
|
37
|
-
if (k ^ 4 || it === void 0) __expectFn(it) && (k > 4 ? initializers.unshift(it) : k ? p ? extra = it : desc[key] = it : target = it);
|
|
38
|
-
else if (typeof it !== "object" || it === null) __typeError("Object expected");
|
|
39
|
-
else __expectFn(fn = it.get) && (desc.get = fn), __expectFn(fn = it.set) && (desc.set = fn), __expectFn(fn = it.init) && initializers.unshift(fn);
|
|
40
|
-
}
|
|
41
|
-
return k || __decoratorMetadata(array, target), desc && __defProp(target, name, desc), p ? k ^ 4 ? extra : desc : target;
|
|
42
|
-
};
|
|
43
|
-
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
44
|
-
var __accessCheck = (obj, member, msg) => member.has(obj) || __typeError("Cannot " + msg);
|
|
45
|
-
var __privateIn = (member, obj) => Object(obj) !== obj ? __typeError('Cannot use the "in" operator on this value') : member.has(obj);
|
|
46
|
-
var __privateGet = (obj, member, getter) => (__accessCheck(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
|
|
47
|
-
var __privateAdd = (obj, member, value) => member.has(obj) ? __typeError("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
|
|
48
|
-
var __privateSet = (obj, member, value, setter) => (__accessCheck(obj, member, "write to private field"), setter ? setter.call(obj, value) : member.set(obj, value), value);
|
|
49
|
-
var __privateMethod = (obj, member, method) => (__accessCheck(obj, member, "access private method"), method);
|
|
50
|
-
|
|
51
|
-
// src/code-mode-deno.ts
|
|
52
|
-
import { spawn } from "node:child_process";
|
|
53
|
-
import { mkdtemp, rm, writeFile } from "node:fs/promises";
|
|
54
|
-
import { tmpdir } from "node:os";
|
|
55
|
-
import { join } from "node:path";
|
|
56
|
-
import { Readable, Writable } from "node:stream";
|
|
57
|
-
function createDenoSandbox(options = {}) {
|
|
58
|
-
const { args = [], denoPath = "deno" } = options;
|
|
59
|
-
return {
|
|
60
|
-
safeEval: async (code) => {
|
|
61
|
-
const tempDir = await mkdtemp(join(tmpdir(), "exoagent-deno-"));
|
|
62
|
-
const tempFile = join(tempDir, "code.ts");
|
|
63
|
-
await writeFile(tempFile, code, "utf-8");
|
|
64
|
-
const child = spawn(denoPath, ["run", ...args, tempFile], {
|
|
65
|
-
stdio: ["pipe", "pipe", "inherit"]
|
|
66
|
-
});
|
|
67
|
-
return {
|
|
68
|
-
input: Readable.toWeb(child.stdout),
|
|
69
|
-
output: Writable.toWeb(child.stdin),
|
|
70
|
-
wait: () => new Promise((resolve, reject) => {
|
|
71
|
-
child.on("exit", async (code2) => {
|
|
72
|
-
await rm(tempDir, { recursive: true, force: true }).catch(() => {
|
|
73
|
-
});
|
|
74
|
-
code2 === 0 ? resolve() : reject(new Error(`Deno process exited with code ${code2}`));
|
|
75
|
-
});
|
|
76
|
-
child.on("error", async (err) => {
|
|
77
|
-
await rm(tempDir, { recursive: true, force: true }).catch(() => {
|
|
78
|
-
});
|
|
79
|
-
reject(err);
|
|
80
|
-
});
|
|
81
|
-
})
|
|
82
|
-
};
|
|
83
|
-
},
|
|
84
|
-
sandboxContext: `Promise.resolve({
|
|
85
|
-
input: Deno.stdin.readable,
|
|
86
|
-
output: Deno.stdout.writable,
|
|
87
|
-
onSuccess: () => Deno.exit(0),
|
|
88
|
-
onFailure: () => Deno.exit(1)
|
|
89
|
-
})`
|
|
90
|
-
};
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
// src/code-mode.ts
|
|
94
|
-
import { readFileSync } from "node:fs";
|
|
95
|
-
import { fileURLToPath } from "node:url";
|
|
96
|
-
|
|
97
|
-
// packages/capnweb/dist/index.js
|
|
98
|
-
var WORKERS_MODULE_SYMBOL = /* @__PURE__ */ Symbol("workers-module");
|
|
99
|
-
if (!Symbol.dispose) {
|
|
100
|
-
Symbol.dispose = /* @__PURE__ */ Symbol.for("dispose");
|
|
101
|
-
}
|
|
102
|
-
if (!Symbol.asyncDispose) {
|
|
103
|
-
Symbol.asyncDispose = /* @__PURE__ */ Symbol.for("asyncDispose");
|
|
104
|
-
}
|
|
105
|
-
if (!Promise.withResolvers) {
|
|
106
|
-
Promise.withResolvers = function() {
|
|
107
|
-
let resolve;
|
|
108
|
-
let reject;
|
|
109
|
-
const promise = new Promise((res, rej) => {
|
|
110
|
-
resolve = res;
|
|
111
|
-
reject = rej;
|
|
112
|
-
});
|
|
113
|
-
return { promise, resolve, reject };
|
|
114
|
-
};
|
|
115
|
-
}
|
|
116
|
-
var workersModule = globalThis[WORKERS_MODULE_SYMBOL];
|
|
117
|
-
var RpcTarget = workersModule ? workersModule.RpcTarget : class {
|
|
118
|
-
};
|
|
119
|
-
var AsyncFunction = (async function() {
|
|
120
|
-
}).constructor;
|
|
121
|
-
var getGlobalRpcSessionOptions = () => ({});
|
|
122
|
-
var CALLBACK_CLEANUP = /* @__PURE__ */ Symbol("callback-cleanup");
|
|
123
|
-
function typeForRpc(value) {
|
|
124
|
-
switch (typeof value) {
|
|
125
|
-
case "boolean":
|
|
126
|
-
case "number":
|
|
127
|
-
case "string":
|
|
128
|
-
return "primitive";
|
|
129
|
-
case "undefined":
|
|
130
|
-
return "undefined";
|
|
131
|
-
case "object":
|
|
132
|
-
case "function":
|
|
133
|
-
break;
|
|
134
|
-
case "bigint":
|
|
135
|
-
return "bigint";
|
|
136
|
-
default:
|
|
137
|
-
return "unsupported";
|
|
138
|
-
}
|
|
139
|
-
if (value === null) {
|
|
140
|
-
return "primitive";
|
|
141
|
-
}
|
|
142
|
-
let prototype = Object.getPrototypeOf(value);
|
|
143
|
-
switch (prototype) {
|
|
144
|
-
case Object.prototype:
|
|
145
|
-
return "object";
|
|
146
|
-
case Function.prototype:
|
|
147
|
-
case AsyncFunction.prototype:
|
|
148
|
-
return "function";
|
|
149
|
-
case Array.prototype:
|
|
150
|
-
return "array";
|
|
151
|
-
case Date.prototype:
|
|
152
|
-
return "date";
|
|
153
|
-
case Uint8Array.prototype:
|
|
154
|
-
return "bytes";
|
|
155
|
-
// TODO: All other structured clone types.
|
|
156
|
-
case RpcStub.prototype:
|
|
157
|
-
return "stub";
|
|
158
|
-
case RpcPromise.prototype:
|
|
159
|
-
return "rpc-promise";
|
|
160
|
-
// TODO: Promise<T> or thenable
|
|
161
|
-
default:
|
|
162
|
-
if (workersModule) {
|
|
163
|
-
if (prototype == workersModule.RpcStub.prototype || value instanceof workersModule.ServiceStub) {
|
|
164
|
-
return "rpc-target";
|
|
165
|
-
} else if (prototype == workersModule.RpcPromise.prototype || prototype == workersModule.RpcProperty.prototype) {
|
|
166
|
-
return "rpc-thenable";
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
if (value instanceof RpcTarget) {
|
|
170
|
-
return "rpc-target";
|
|
171
|
-
}
|
|
172
|
-
if (value instanceof Error) {
|
|
173
|
-
return "error";
|
|
174
|
-
}
|
|
175
|
-
return "unsupported";
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
|
-
function mapNotLoaded() {
|
|
179
|
-
throw new Error("RPC map() implementation was not loaded.");
|
|
180
|
-
}
|
|
181
|
-
var mapImpl = { applyMap: mapNotLoaded, sendMap: mapNotLoaded, recordCallback: mapNotLoaded };
|
|
182
|
-
var StubHook = class {
|
|
183
|
-
};
|
|
184
|
-
var ErrorStubHook = class extends StubHook {
|
|
185
|
-
constructor(error) {
|
|
186
|
-
super();
|
|
187
|
-
this.error = error;
|
|
188
|
-
}
|
|
189
|
-
call(path, args) {
|
|
190
|
-
return this;
|
|
191
|
-
}
|
|
192
|
-
map(path, captures, instructions) {
|
|
193
|
-
return this;
|
|
194
|
-
}
|
|
195
|
-
get(path) {
|
|
196
|
-
return this;
|
|
197
|
-
}
|
|
198
|
-
dup() {
|
|
199
|
-
return this;
|
|
200
|
-
}
|
|
201
|
-
pull() {
|
|
202
|
-
return Promise.reject(this.error);
|
|
203
|
-
}
|
|
204
|
-
ignoreUnhandledRejections() {
|
|
205
|
-
}
|
|
206
|
-
dispose() {
|
|
207
|
-
}
|
|
208
|
-
onBroken(callback) {
|
|
209
|
-
try {
|
|
210
|
-
callback(this.error);
|
|
211
|
-
} catch (err) {
|
|
212
|
-
Promise.resolve(err);
|
|
213
|
-
}
|
|
214
|
-
}
|
|
215
|
-
};
|
|
216
|
-
var DISPOSED_HOOK = new ErrorStubHook(
|
|
217
|
-
new Error("Attempted to use RPC stub after it has been disposed.")
|
|
218
|
-
);
|
|
219
|
-
var doCall = (hook, path, params) => {
|
|
220
|
-
return hook.call(path, params);
|
|
221
|
-
};
|
|
222
|
-
function withCallInterceptor(interceptor, callback) {
|
|
223
|
-
let oldValue = doCall;
|
|
224
|
-
doCall = interceptor;
|
|
225
|
-
try {
|
|
226
|
-
return callback();
|
|
227
|
-
} finally {
|
|
228
|
-
doCall = oldValue;
|
|
229
|
-
}
|
|
230
|
-
}
|
|
231
|
-
var RAW_STUB = /* @__PURE__ */ Symbol("realStub");
|
|
232
|
-
var PROXY_HANDLERS = {
|
|
233
|
-
apply(target, thisArg, argumentsList) {
|
|
234
|
-
let stub = target.raw;
|
|
235
|
-
return new RpcPromise(doCall(
|
|
236
|
-
stub.hook,
|
|
237
|
-
stub.pathIfPromise || [],
|
|
238
|
-
RpcPayload.fromAppParams(argumentsList)
|
|
239
|
-
), []);
|
|
240
|
-
},
|
|
241
|
-
get(target, prop, receiver) {
|
|
242
|
-
let stub = target.raw;
|
|
243
|
-
if (prop === RAW_STUB) {
|
|
244
|
-
return stub;
|
|
245
|
-
} else if (prop in RpcPromise.prototype) {
|
|
246
|
-
return stub[prop];
|
|
247
|
-
} else if (typeof prop === "string") {
|
|
248
|
-
return new RpcPromise(
|
|
249
|
-
stub.hook,
|
|
250
|
-
stub.pathIfPromise ? [...stub.pathIfPromise, prop] : [prop]
|
|
251
|
-
);
|
|
252
|
-
} else if (prop === Symbol.dispose && (!stub.pathIfPromise || stub.pathIfPromise.length == 0)) {
|
|
253
|
-
return () => {
|
|
254
|
-
stub.hook.dispose();
|
|
255
|
-
stub.hook = DISPOSED_HOOK;
|
|
256
|
-
};
|
|
257
|
-
} else {
|
|
258
|
-
return void 0;
|
|
259
|
-
}
|
|
260
|
-
},
|
|
261
|
-
has(target, prop) {
|
|
262
|
-
let stub = target.raw;
|
|
263
|
-
if (prop === RAW_STUB) {
|
|
264
|
-
return true;
|
|
265
|
-
} else if (prop in RpcPromise.prototype) {
|
|
266
|
-
return prop in stub;
|
|
267
|
-
} else if (typeof prop === "string") {
|
|
268
|
-
return true;
|
|
269
|
-
} else if (prop === Symbol.dispose && (!stub.pathIfPromise || stub.pathIfPromise.length == 0)) {
|
|
270
|
-
return true;
|
|
271
|
-
} else {
|
|
272
|
-
return false;
|
|
273
|
-
}
|
|
274
|
-
},
|
|
275
|
-
construct(target, args) {
|
|
276
|
-
throw new Error("An RPC stub cannot be used as a constructor.");
|
|
277
|
-
},
|
|
278
|
-
defineProperty(target, property, attributes) {
|
|
279
|
-
throw new Error("Can't define properties on RPC stubs.");
|
|
280
|
-
},
|
|
281
|
-
deleteProperty(target, p) {
|
|
282
|
-
throw new Error("Can't delete properties on RPC stubs.");
|
|
283
|
-
},
|
|
284
|
-
getOwnPropertyDescriptor(target, p) {
|
|
285
|
-
return void 0;
|
|
286
|
-
},
|
|
287
|
-
getPrototypeOf(target) {
|
|
288
|
-
return Object.getPrototypeOf(target.raw);
|
|
289
|
-
},
|
|
290
|
-
isExtensible(target) {
|
|
291
|
-
return false;
|
|
292
|
-
},
|
|
293
|
-
ownKeys(target) {
|
|
294
|
-
return [];
|
|
295
|
-
},
|
|
296
|
-
preventExtensions(target) {
|
|
297
|
-
return true;
|
|
298
|
-
},
|
|
299
|
-
set(target, p, newValue, receiver) {
|
|
300
|
-
throw new Error("Can't assign properties on RPC stubs.");
|
|
301
|
-
},
|
|
302
|
-
setPrototypeOf(target, v) {
|
|
303
|
-
throw new Error("Can't override prototype of RPC stubs.");
|
|
304
|
-
}
|
|
305
|
-
};
|
|
306
|
-
var RpcStub = class _RpcStub extends RpcTarget {
|
|
307
|
-
// Although `hook` and `path` are declared `public` here, they are effectively hidden by the
|
|
308
|
-
// proxy.
|
|
309
|
-
constructor(hook, pathIfPromise) {
|
|
310
|
-
super();
|
|
311
|
-
if (!(hook instanceof StubHook)) {
|
|
312
|
-
let value = hook;
|
|
313
|
-
if (value instanceof RpcTarget || value instanceof Function) {
|
|
314
|
-
hook = TargetStubHook.create(value, void 0);
|
|
315
|
-
} else {
|
|
316
|
-
hook = new PayloadStubHook(RpcPayload.fromAppReturn(value));
|
|
317
|
-
}
|
|
318
|
-
if (pathIfPromise) {
|
|
319
|
-
throw new TypeError("RpcStub constructor expected one argument, received two.");
|
|
320
|
-
}
|
|
321
|
-
}
|
|
322
|
-
this.hook = hook;
|
|
323
|
-
this.pathIfPromise = pathIfPromise;
|
|
324
|
-
let func = () => {
|
|
325
|
-
};
|
|
326
|
-
func.raw = this;
|
|
327
|
-
return new Proxy(func, PROXY_HANDLERS);
|
|
328
|
-
}
|
|
329
|
-
hook;
|
|
330
|
-
pathIfPromise;
|
|
331
|
-
dup() {
|
|
332
|
-
let target = this[RAW_STUB];
|
|
333
|
-
if (target.pathIfPromise) {
|
|
334
|
-
return new _RpcStub(target.hook.get(target.pathIfPromise));
|
|
335
|
-
} else {
|
|
336
|
-
return new _RpcStub(target.hook.dup());
|
|
337
|
-
}
|
|
338
|
-
}
|
|
339
|
-
onRpcBroken(callback) {
|
|
340
|
-
this[RAW_STUB].hook.onBroken(callback);
|
|
341
|
-
}
|
|
342
|
-
map(func) {
|
|
343
|
-
let { hook, pathIfPromise } = this[RAW_STUB];
|
|
344
|
-
return mapImpl.sendMap(hook, pathIfPromise || [], func);
|
|
345
|
-
}
|
|
346
|
-
toString() {
|
|
347
|
-
return "[object RpcStub]";
|
|
348
|
-
}
|
|
349
|
-
};
|
|
350
|
-
var RpcPromise = class extends RpcStub {
|
|
351
|
-
// TODO: Support passing target value or promise to constructor.
|
|
352
|
-
constructor(hook, pathIfPromise) {
|
|
353
|
-
super(hook, pathIfPromise);
|
|
354
|
-
}
|
|
355
|
-
then(onfulfilled, onrejected) {
|
|
356
|
-
return pullPromise(this).then(...arguments);
|
|
357
|
-
}
|
|
358
|
-
catch(onrejected) {
|
|
359
|
-
return pullPromise(this).catch(...arguments);
|
|
360
|
-
}
|
|
361
|
-
finally(onfinally) {
|
|
362
|
-
return pullPromise(this).finally(...arguments);
|
|
363
|
-
}
|
|
364
|
-
toString() {
|
|
365
|
-
return "[object RpcPromise]";
|
|
366
|
-
}
|
|
367
|
-
};
|
|
368
|
-
function unwrapStubTakingOwnership(stub) {
|
|
369
|
-
let { hook, pathIfPromise } = stub[RAW_STUB];
|
|
370
|
-
if (pathIfPromise && pathIfPromise.length > 0) {
|
|
371
|
-
return hook.get(pathIfPromise);
|
|
372
|
-
} else {
|
|
373
|
-
return hook;
|
|
374
|
-
}
|
|
375
|
-
}
|
|
376
|
-
function unwrapStubAndDup(stub) {
|
|
377
|
-
let { hook, pathIfPromise } = stub[RAW_STUB];
|
|
378
|
-
if (pathIfPromise) {
|
|
379
|
-
return hook.get(pathIfPromise);
|
|
380
|
-
} else {
|
|
381
|
-
return hook.dup();
|
|
382
|
-
}
|
|
383
|
-
}
|
|
384
|
-
function unwrapStubNoProperties(stub) {
|
|
385
|
-
let { hook, pathIfPromise } = stub[RAW_STUB];
|
|
386
|
-
if (pathIfPromise && pathIfPromise.length > 0) {
|
|
387
|
-
return void 0;
|
|
388
|
-
}
|
|
389
|
-
return hook;
|
|
390
|
-
}
|
|
391
|
-
function unwrapStubOrParent(stub) {
|
|
392
|
-
return stub[RAW_STUB].hook;
|
|
393
|
-
}
|
|
394
|
-
function unwrapStubAndPath(stub) {
|
|
395
|
-
return stub[RAW_STUB];
|
|
396
|
-
}
|
|
397
|
-
async function pullPromise(promise) {
|
|
398
|
-
let { hook, pathIfPromise } = promise[RAW_STUB];
|
|
399
|
-
if (pathIfPromise.length > 0) {
|
|
400
|
-
hook = hook.get(pathIfPromise);
|
|
401
|
-
}
|
|
402
|
-
let payload = await hook.pull();
|
|
403
|
-
return payload.deliverResolve();
|
|
404
|
-
}
|
|
405
|
-
var RpcPayload = class _RpcPayload {
|
|
406
|
-
// Private constructor; use factory functions above to construct.
|
|
407
|
-
constructor(value, source, stubs, promises) {
|
|
408
|
-
this.value = value;
|
|
409
|
-
this.source = source;
|
|
410
|
-
this.stubs = stubs;
|
|
411
|
-
this.promises = promises;
|
|
412
|
-
}
|
|
413
|
-
// Create a payload from a value passed as params to an RPC from the app.
|
|
414
|
-
//
|
|
415
|
-
// The payload does NOT take ownership of any stubs in `value`, and but promises not to modify
|
|
416
|
-
// `value`. If the payload is delivered locally, `value` will be deep-copied first, so as not
|
|
417
|
-
// to have the sender and recipient end up sharing the same mutable object. `value` will not be
|
|
418
|
-
// touched again after the call returns synchronously (returns a promise) -- by that point,
|
|
419
|
-
// the value has either been copied or serialized to the wire.
|
|
420
|
-
static fromAppParams(value) {
|
|
421
|
-
return new _RpcPayload(value, "params");
|
|
422
|
-
}
|
|
423
|
-
// Create a payload from a value return from an RPC implementation by the app.
|
|
424
|
-
//
|
|
425
|
-
// Unlike fromAppParams(), in this case the payload takes ownership of all stubs in `value`, and
|
|
426
|
-
// may hold onto `value` for an arbitrarily long time (e.g. to serve pipelined requests). It
|
|
427
|
-
// will still avoid modifying `value` and will make a deep copy if it is delivered locally.
|
|
428
|
-
static fromAppReturn(value) {
|
|
429
|
-
return new _RpcPayload(value, "return");
|
|
430
|
-
}
|
|
431
|
-
// Combine an array of payloads into a single payload whose value is an array. Ownership of all
|
|
432
|
-
// stubs is transferred from the inputs to the outputs, hence if the output is disposed, the
|
|
433
|
-
// inputs should not be. (In case of exception, nothing is disposed, though.)
|
|
434
|
-
static fromArray(array) {
|
|
435
|
-
let stubs = [];
|
|
436
|
-
let promises = [];
|
|
437
|
-
let resultArray = [];
|
|
438
|
-
for (let payload of array) {
|
|
439
|
-
payload.ensureDeepCopied();
|
|
440
|
-
for (let stub of payload.stubs) {
|
|
441
|
-
stubs.push(stub);
|
|
442
|
-
}
|
|
443
|
-
for (let promise of payload.promises) {
|
|
444
|
-
if (promise.parent === payload) {
|
|
445
|
-
promise = {
|
|
446
|
-
parent: resultArray,
|
|
447
|
-
property: resultArray.length,
|
|
448
|
-
promise: promise.promise
|
|
449
|
-
};
|
|
450
|
-
}
|
|
451
|
-
promises.push(promise);
|
|
452
|
-
}
|
|
453
|
-
resultArray.push(payload.value);
|
|
454
|
-
}
|
|
455
|
-
return new _RpcPayload(resultArray, "owned", stubs, promises);
|
|
456
|
-
}
|
|
457
|
-
// Create a payload from a value parsed off the wire using Evaluator.evaluate().
|
|
458
|
-
//
|
|
459
|
-
// A payload is constructed with a null value and the given stubs and promises arrays. The value
|
|
460
|
-
// is expected to be filled in by the evaluator, and the stubs and promises arrays are expected
|
|
461
|
-
// to be extended with stubs found during parsing. (This weird usage model is necessary so that
|
|
462
|
-
// if the root value turns out to be a promise, its `parent` in `promises` can be the payload
|
|
463
|
-
// object itself.)
|
|
464
|
-
//
|
|
465
|
-
// When done, the payload takes ownership of the final value and all the stubs within. It may
|
|
466
|
-
// modify the value in preparation for delivery, and may deliver the value directly to the app
|
|
467
|
-
// without copying.
|
|
468
|
-
static forEvaluate(stubs, promises) {
|
|
469
|
-
return new _RpcPayload(null, "owned", stubs, promises);
|
|
470
|
-
}
|
|
471
|
-
// Deep-copy the given value, including dup()ing all stubs.
|
|
472
|
-
//
|
|
473
|
-
// If `value` is a function, it should be bound to `oldParent` as its `this`.
|
|
474
|
-
//
|
|
475
|
-
// If deep-copying from a branch of some other RpcPayload, it must be provided, to make sure
|
|
476
|
-
// RpcTargets found within don't get duplicate stubs.
|
|
477
|
-
static deepCopyFrom(value, oldParent, owner) {
|
|
478
|
-
let result = new _RpcPayload(null, "owned", [], []);
|
|
479
|
-
result.value = result.deepCopy(
|
|
480
|
-
value,
|
|
481
|
-
oldParent,
|
|
482
|
-
"value",
|
|
483
|
-
result,
|
|
484
|
-
/*dupStubs=*/
|
|
485
|
-
true,
|
|
486
|
-
owner
|
|
487
|
-
);
|
|
488
|
-
return result;
|
|
489
|
-
}
|
|
490
|
-
// For `source === "return"` payloads only, this tracks any StubHooks created around RpcTargets
|
|
491
|
-
// found in the payload at the time that it is serialized (or deep-copied) for return, so that we
|
|
492
|
-
// can make sure they are not disposed before the pipeline ends.
|
|
493
|
-
//
|
|
494
|
-
// This is initialized on first use.
|
|
495
|
-
rpcTargets;
|
|
496
|
-
// Get the StubHook representing the given RpcTarget found inside this payload.
|
|
497
|
-
getHookForRpcTarget(target, parent, dupStubs = true) {
|
|
498
|
-
if (this.source === "params") {
|
|
499
|
-
if (dupStubs) {
|
|
500
|
-
let dupable = target;
|
|
501
|
-
if (typeof dupable.dup === "function") {
|
|
502
|
-
target = dupable.dup();
|
|
503
|
-
}
|
|
504
|
-
}
|
|
505
|
-
return TargetStubHook.create(target, parent);
|
|
506
|
-
} else if (this.source === "return") {
|
|
507
|
-
let hook = this.rpcTargets?.get(target);
|
|
508
|
-
if (hook) {
|
|
509
|
-
if (dupStubs) {
|
|
510
|
-
return hook.dup();
|
|
511
|
-
} else {
|
|
512
|
-
this.rpcTargets?.delete(target);
|
|
513
|
-
return hook;
|
|
514
|
-
}
|
|
515
|
-
} else {
|
|
516
|
-
hook = TargetStubHook.create(target, parent);
|
|
517
|
-
if (dupStubs) {
|
|
518
|
-
if (!this.rpcTargets) {
|
|
519
|
-
this.rpcTargets = /* @__PURE__ */ new Map();
|
|
520
|
-
}
|
|
521
|
-
this.rpcTargets.set(target, hook);
|
|
522
|
-
return hook.dup();
|
|
523
|
-
} else {
|
|
524
|
-
return hook;
|
|
525
|
-
}
|
|
526
|
-
}
|
|
527
|
-
} else {
|
|
528
|
-
throw new Error("owned payload shouldn't contain raw RpcTargets");
|
|
529
|
-
}
|
|
530
|
-
}
|
|
531
|
-
deepCopy(value, oldParent, property, parent, dupStubs, owner) {
|
|
532
|
-
let kind = typeForRpc(value);
|
|
533
|
-
switch (kind) {
|
|
534
|
-
case "unsupported":
|
|
535
|
-
return value;
|
|
536
|
-
case "primitive":
|
|
537
|
-
case "bigint":
|
|
538
|
-
case "date":
|
|
539
|
-
case "bytes":
|
|
540
|
-
case "error":
|
|
541
|
-
case "undefined":
|
|
542
|
-
return value;
|
|
543
|
-
case "array": {
|
|
544
|
-
let array = value;
|
|
545
|
-
let len = array.length;
|
|
546
|
-
let result = new Array(len);
|
|
547
|
-
for (let i = 0; i < len; i++) {
|
|
548
|
-
result[i] = this.deepCopy(array[i], array, i, result, dupStubs, owner);
|
|
549
|
-
}
|
|
550
|
-
return result;
|
|
551
|
-
}
|
|
552
|
-
case "object": {
|
|
553
|
-
let result = {};
|
|
554
|
-
let object = value;
|
|
555
|
-
for (let i in object) {
|
|
556
|
-
result[i] = this.deepCopy(object[i], object, i, result, dupStubs, owner);
|
|
557
|
-
}
|
|
558
|
-
return result;
|
|
559
|
-
}
|
|
560
|
-
case "stub":
|
|
561
|
-
case "rpc-promise": {
|
|
562
|
-
let stub = value;
|
|
563
|
-
let hook;
|
|
564
|
-
if (dupStubs) {
|
|
565
|
-
hook = unwrapStubAndDup(stub);
|
|
566
|
-
} else {
|
|
567
|
-
hook = unwrapStubTakingOwnership(stub);
|
|
568
|
-
}
|
|
569
|
-
if (stub instanceof RpcPromise) {
|
|
570
|
-
let promise = new RpcPromise(hook, []);
|
|
571
|
-
this.promises.push({ parent, property, promise });
|
|
572
|
-
return promise;
|
|
573
|
-
} else {
|
|
574
|
-
let newStub = new RpcStub(hook);
|
|
575
|
-
this.stubs.push(newStub);
|
|
576
|
-
return newStub;
|
|
577
|
-
}
|
|
578
|
-
}
|
|
579
|
-
case "function":
|
|
580
|
-
if (this.source === "owned" && typeof value === "function" && !(value instanceof RpcTarget)) {
|
|
581
|
-
return value;
|
|
582
|
-
}
|
|
583
|
-
// Fall through to rpc-target handling
|
|
584
|
-
case "rpc-target": {
|
|
585
|
-
let target = value;
|
|
586
|
-
let stub;
|
|
587
|
-
if (owner) {
|
|
588
|
-
stub = new RpcStub(owner.getHookForRpcTarget(target, oldParent, dupStubs));
|
|
589
|
-
} else {
|
|
590
|
-
stub = new RpcStub(TargetStubHook.create(target, oldParent));
|
|
591
|
-
}
|
|
592
|
-
this.stubs.push(stub);
|
|
593
|
-
return stub;
|
|
594
|
-
}
|
|
595
|
-
case "rpc-thenable": {
|
|
596
|
-
let target = value;
|
|
597
|
-
let promise;
|
|
598
|
-
if (owner) {
|
|
599
|
-
promise = new RpcPromise(owner.getHookForRpcTarget(target, oldParent, dupStubs), []);
|
|
600
|
-
} else {
|
|
601
|
-
promise = new RpcPromise(TargetStubHook.create(target, oldParent), []);
|
|
602
|
-
}
|
|
603
|
-
this.promises.push({ parent, property, promise });
|
|
604
|
-
return promise;
|
|
605
|
-
}
|
|
606
|
-
default:
|
|
607
|
-
throw new Error("unreachable");
|
|
608
|
-
}
|
|
609
|
-
}
|
|
610
|
-
// Ensures that if the value originally came from an unowned source, we have replaced it with a
|
|
611
|
-
// deep copy.
|
|
612
|
-
ensureDeepCopied() {
|
|
613
|
-
if (this.source !== "owned") {
|
|
614
|
-
let dupStubs = this.source === "params";
|
|
615
|
-
this.stubs = [];
|
|
616
|
-
this.promises = [];
|
|
617
|
-
try {
|
|
618
|
-
this.value = this.deepCopy(this.value, void 0, "value", this, dupStubs, this);
|
|
619
|
-
} catch (err) {
|
|
620
|
-
this.stubs = void 0;
|
|
621
|
-
this.promises = void 0;
|
|
622
|
-
throw err;
|
|
623
|
-
}
|
|
624
|
-
this.source = "owned";
|
|
625
|
-
if (this.rpcTargets && this.rpcTargets.size > 0) {
|
|
626
|
-
throw new Error("Not all rpcTargets were accounted for in deep-copy?");
|
|
627
|
-
}
|
|
628
|
-
this.rpcTargets = void 0;
|
|
629
|
-
}
|
|
630
|
-
}
|
|
631
|
-
// Resolve all promises in this payload and then assign the final value into `parent[property]`.
|
|
632
|
-
deliverTo(parent, property, promises) {
|
|
633
|
-
const unwrapRpcTargets = (value) => {
|
|
634
|
-
if (value instanceof RpcStub) {
|
|
635
|
-
const { hook, pathIfPromise } = unwrapStubAndPath(value);
|
|
636
|
-
if (pathIfPromise == null && hook instanceof TargetStubHook) {
|
|
637
|
-
const target = hook.getTarget();
|
|
638
|
-
return target;
|
|
639
|
-
}
|
|
640
|
-
}
|
|
641
|
-
return value;
|
|
642
|
-
};
|
|
643
|
-
this.ensureDeepCopied();
|
|
644
|
-
if (this.value instanceof RpcPromise) {
|
|
645
|
-
_RpcPayload.deliverRpcPromiseTo(this.value, parent, property, promises);
|
|
646
|
-
} else {
|
|
647
|
-
const unwrapped = unwrapRpcTargets(this.value);
|
|
648
|
-
parent[property] = unwrapped;
|
|
649
|
-
for (let record of this.promises) {
|
|
650
|
-
_RpcPayload.deliverRpcPromiseTo(record.promise, record.parent, record.property, promises);
|
|
651
|
-
}
|
|
652
|
-
}
|
|
653
|
-
}
|
|
654
|
-
static deliverRpcPromiseTo(promise, parent, property, promises) {
|
|
655
|
-
let hook = unwrapStubNoProperties(promise);
|
|
656
|
-
if (!hook) {
|
|
657
|
-
throw new Error("property promises should have been resolved earlier");
|
|
658
|
-
}
|
|
659
|
-
let inner = hook.pull();
|
|
660
|
-
if (inner instanceof _RpcPayload) {
|
|
661
|
-
inner.deliverTo(parent, property, promises);
|
|
662
|
-
} else {
|
|
663
|
-
promises.push(inner.then((payload) => {
|
|
664
|
-
let subPromises = [];
|
|
665
|
-
payload.deliverTo(parent, property, subPromises);
|
|
666
|
-
if (subPromises.length > 0) {
|
|
667
|
-
return Promise.all(subPromises);
|
|
668
|
-
}
|
|
669
|
-
}));
|
|
670
|
-
}
|
|
671
|
-
}
|
|
672
|
-
// Call the given function with the payload as an argument. The call is made synchronously if
|
|
673
|
-
// possible, in order to maintain e-order. However, if any RpcPromises exist in the payload,
|
|
674
|
-
// they are awaited and substituted before calling the function. The result of the call is
|
|
675
|
-
// wrapped into another payload.
|
|
676
|
-
//
|
|
677
|
-
// The payload is automatically disposed after the call completes. The caller should not call
|
|
678
|
-
// dispose().
|
|
679
|
-
async deliverCall(func, thisArg) {
|
|
680
|
-
try {
|
|
681
|
-
let promises = [];
|
|
682
|
-
this.deliverTo(this, "value", promises);
|
|
683
|
-
if (promises.length > 0) {
|
|
684
|
-
await Promise.all(promises);
|
|
685
|
-
}
|
|
686
|
-
let result = Function.prototype.apply.call(func, thisArg, this.value);
|
|
687
|
-
if (result instanceof RpcPromise) {
|
|
688
|
-
return _RpcPayload.fromAppReturn(result);
|
|
689
|
-
} else {
|
|
690
|
-
return _RpcPayload.fromAppReturn(await result);
|
|
691
|
-
}
|
|
692
|
-
} finally {
|
|
693
|
-
this.dispose();
|
|
694
|
-
}
|
|
695
|
-
}
|
|
696
|
-
// Produce a promise for this payload for return to the application. Any RpcPromises in the
|
|
697
|
-
// payload are awaited and substituted with their results first.
|
|
698
|
-
//
|
|
699
|
-
// The returned object will have a disposer which disposes the payload. The caller should not
|
|
700
|
-
// separately dispose it.
|
|
701
|
-
async deliverResolve() {
|
|
702
|
-
try {
|
|
703
|
-
let promises = [];
|
|
704
|
-
this.deliverTo(this, "value", promises);
|
|
705
|
-
if (promises.length > 0) {
|
|
706
|
-
await Promise.all(promises);
|
|
707
|
-
}
|
|
708
|
-
let result = this.value;
|
|
709
|
-
if (result instanceof Object) {
|
|
710
|
-
if (!(Symbol.dispose in result)) {
|
|
711
|
-
Object.defineProperty(result, Symbol.dispose, {
|
|
712
|
-
// NOTE: Using `this.dispose.bind(this)` here causes Playwright's build of
|
|
713
|
-
// Chromium 140.0.7339.16 to fail when the object is assigned to a `using` variable,
|
|
714
|
-
// with the error:
|
|
715
|
-
// TypeError: Symbol(Symbol.dispose) is not a function
|
|
716
|
-
// I cannot reproduce this problem in Chrome 140.0.7339.127 nor in Node or workerd,
|
|
717
|
-
// so maybe it was a short-lived V8 bug or something. To be safe, though, we use
|
|
718
|
-
// `() => this.dispose()`, which seems to always work.
|
|
719
|
-
value: () => this.dispose(),
|
|
720
|
-
writable: true,
|
|
721
|
-
enumerable: false,
|
|
722
|
-
configurable: true
|
|
723
|
-
});
|
|
724
|
-
}
|
|
725
|
-
}
|
|
726
|
-
return result;
|
|
727
|
-
} catch (err) {
|
|
728
|
-
this.dispose();
|
|
729
|
-
throw err;
|
|
730
|
-
}
|
|
731
|
-
}
|
|
732
|
-
dispose() {
|
|
733
|
-
if (this.source === "owned") {
|
|
734
|
-
this.stubs.forEach((stub) => stub[Symbol.dispose]());
|
|
735
|
-
this.promises.forEach((promise) => promise.promise[Symbol.dispose]());
|
|
736
|
-
} else if (this.source === "return") {
|
|
737
|
-
this.disposeImpl(this.value, void 0);
|
|
738
|
-
if (this.rpcTargets && this.rpcTargets.size > 0) {
|
|
739
|
-
throw new Error("Not all rpcTargets were accounted for in disposeImpl()?");
|
|
740
|
-
}
|
|
741
|
-
} else ;
|
|
742
|
-
this.source = "owned";
|
|
743
|
-
this.stubs = [];
|
|
744
|
-
this.promises = [];
|
|
745
|
-
}
|
|
746
|
-
// Recursive dispose, called only when `source` is "return".
|
|
747
|
-
disposeImpl(value, parent) {
|
|
748
|
-
let kind = typeForRpc(value);
|
|
749
|
-
switch (kind) {
|
|
750
|
-
case "unsupported":
|
|
751
|
-
case "primitive":
|
|
752
|
-
case "bigint":
|
|
753
|
-
case "bytes":
|
|
754
|
-
case "date":
|
|
755
|
-
case "error":
|
|
756
|
-
case "undefined":
|
|
757
|
-
return;
|
|
758
|
-
case "array": {
|
|
759
|
-
let array = value;
|
|
760
|
-
let len = array.length;
|
|
761
|
-
for (let i = 0; i < len; i++) {
|
|
762
|
-
this.disposeImpl(array[i], array);
|
|
763
|
-
}
|
|
764
|
-
return;
|
|
765
|
-
}
|
|
766
|
-
case "object": {
|
|
767
|
-
let object = value;
|
|
768
|
-
for (let i in object) {
|
|
769
|
-
this.disposeImpl(object[i], object);
|
|
770
|
-
}
|
|
771
|
-
return;
|
|
772
|
-
}
|
|
773
|
-
case "stub":
|
|
774
|
-
case "rpc-promise": {
|
|
775
|
-
let stub = value;
|
|
776
|
-
let hook = unwrapStubNoProperties(stub);
|
|
777
|
-
if (hook) {
|
|
778
|
-
hook.dispose();
|
|
779
|
-
}
|
|
780
|
-
return;
|
|
781
|
-
}
|
|
782
|
-
case "function":
|
|
783
|
-
case "rpc-target": {
|
|
784
|
-
let target = value;
|
|
785
|
-
let hook = this.rpcTargets?.get(target);
|
|
786
|
-
if (hook) {
|
|
787
|
-
hook.dispose();
|
|
788
|
-
this.rpcTargets.delete(target);
|
|
789
|
-
} else {
|
|
790
|
-
disposeRpcTarget(target);
|
|
791
|
-
}
|
|
792
|
-
return;
|
|
793
|
-
}
|
|
794
|
-
case "rpc-thenable":
|
|
795
|
-
return;
|
|
796
|
-
default:
|
|
797
|
-
return;
|
|
798
|
-
}
|
|
799
|
-
}
|
|
800
|
-
// Ignore unhandled rejections in all promises in this payload -- that is, all promises that
|
|
801
|
-
// *would* be awaited if this payload were to be delivered. See the similarly-named method of
|
|
802
|
-
// StubHook for explanation.
|
|
803
|
-
ignoreUnhandledRejections() {
|
|
804
|
-
if (this.stubs) {
|
|
805
|
-
this.stubs.forEach((stub) => {
|
|
806
|
-
unwrapStubOrParent(stub).ignoreUnhandledRejections();
|
|
807
|
-
});
|
|
808
|
-
this.promises.forEach(
|
|
809
|
-
(promise) => unwrapStubOrParent(promise.promise).ignoreUnhandledRejections()
|
|
810
|
-
);
|
|
811
|
-
} else {
|
|
812
|
-
this.ignoreUnhandledRejectionsImpl(this.value);
|
|
813
|
-
}
|
|
814
|
-
}
|
|
815
|
-
ignoreUnhandledRejectionsImpl(value) {
|
|
816
|
-
let kind = typeForRpc(value);
|
|
817
|
-
switch (kind) {
|
|
818
|
-
case "unsupported":
|
|
819
|
-
case "primitive":
|
|
820
|
-
case "bigint":
|
|
821
|
-
case "bytes":
|
|
822
|
-
case "date":
|
|
823
|
-
case "error":
|
|
824
|
-
case "undefined":
|
|
825
|
-
case "function":
|
|
826
|
-
case "rpc-target":
|
|
827
|
-
return;
|
|
828
|
-
case "array": {
|
|
829
|
-
let array = value;
|
|
830
|
-
let len = array.length;
|
|
831
|
-
for (let i = 0; i < len; i++) {
|
|
832
|
-
this.ignoreUnhandledRejectionsImpl(array[i]);
|
|
833
|
-
}
|
|
834
|
-
return;
|
|
835
|
-
}
|
|
836
|
-
case "object": {
|
|
837
|
-
let object = value;
|
|
838
|
-
for (let i in object) {
|
|
839
|
-
this.ignoreUnhandledRejectionsImpl(object[i]);
|
|
840
|
-
}
|
|
841
|
-
return;
|
|
842
|
-
}
|
|
843
|
-
case "stub":
|
|
844
|
-
case "rpc-promise":
|
|
845
|
-
unwrapStubOrParent(value).ignoreUnhandledRejections();
|
|
846
|
-
return;
|
|
847
|
-
case "rpc-thenable":
|
|
848
|
-
value.then((_) => {
|
|
849
|
-
}, (_) => {
|
|
850
|
-
});
|
|
851
|
-
return;
|
|
852
|
-
default:
|
|
853
|
-
return;
|
|
854
|
-
}
|
|
855
|
-
}
|
|
856
|
-
};
|
|
857
|
-
function followPath(value, parent, path, owner) {
|
|
858
|
-
for (let i = 0; i < path.length; i++) {
|
|
859
|
-
parent = value;
|
|
860
|
-
let part = path[i];
|
|
861
|
-
if (part in Object.prototype) {
|
|
862
|
-
value = void 0;
|
|
863
|
-
continue;
|
|
864
|
-
}
|
|
865
|
-
let kind = typeForRpc(value);
|
|
866
|
-
switch (kind) {
|
|
867
|
-
case "object":
|
|
868
|
-
case "function":
|
|
869
|
-
if (Object.hasOwn(value, part)) {
|
|
870
|
-
value = value[part];
|
|
871
|
-
} else {
|
|
872
|
-
value = void 0;
|
|
873
|
-
}
|
|
874
|
-
break;
|
|
875
|
-
case "array":
|
|
876
|
-
if (Number.isInteger(part) && part >= 0) {
|
|
877
|
-
value = value[part];
|
|
878
|
-
} else {
|
|
879
|
-
value = void 0;
|
|
880
|
-
}
|
|
881
|
-
break;
|
|
882
|
-
case "rpc-target":
|
|
883
|
-
case "rpc-thenable": {
|
|
884
|
-
if (Object.hasOwn(value, part)) {
|
|
885
|
-
throw new TypeError(
|
|
886
|
-
`Attempted to access property '${part}', which is an instance property of the RpcTarget. To avoid leaking private internals, instance properties cannot be accessed over RPC. If you want to make this property available over RPC, define it as a method or getter on the class, instead of an instance property.`
|
|
887
|
-
);
|
|
888
|
-
} else {
|
|
889
|
-
value = value[part];
|
|
890
|
-
}
|
|
891
|
-
owner = null;
|
|
892
|
-
break;
|
|
893
|
-
}
|
|
894
|
-
case "stub":
|
|
895
|
-
case "rpc-promise": {
|
|
896
|
-
let { hook, pathIfPromise } = unwrapStubAndPath(value);
|
|
897
|
-
return { hook, remainingPath: pathIfPromise ? pathIfPromise.concat(path.slice(i)) : path.slice(i) };
|
|
898
|
-
}
|
|
899
|
-
case "primitive":
|
|
900
|
-
case "bigint":
|
|
901
|
-
case "bytes":
|
|
902
|
-
case "date":
|
|
903
|
-
case "error":
|
|
904
|
-
value = void 0;
|
|
905
|
-
break;
|
|
906
|
-
case "undefined":
|
|
907
|
-
value = value[part];
|
|
908
|
-
break;
|
|
909
|
-
case "unsupported": {
|
|
910
|
-
if (i === 0) {
|
|
911
|
-
throw new TypeError(`RPC stub points at a non-serializable type.`);
|
|
912
|
-
} else {
|
|
913
|
-
let prefix = path.slice(0, i).join(".");
|
|
914
|
-
let remainder = path.slice(0, i).join(".");
|
|
915
|
-
throw new TypeError(
|
|
916
|
-
`'${prefix}' is not a serializable type, so property ${remainder} cannot be accessed.`
|
|
917
|
-
);
|
|
918
|
-
}
|
|
919
|
-
}
|
|
920
|
-
default:
|
|
921
|
-
throw new TypeError("unreachable");
|
|
922
|
-
}
|
|
923
|
-
}
|
|
924
|
-
if (value instanceof RpcPromise) {
|
|
925
|
-
let { hook, pathIfPromise } = unwrapStubAndPath(value);
|
|
926
|
-
return { hook, remainingPath: pathIfPromise || [] };
|
|
927
|
-
}
|
|
928
|
-
return {
|
|
929
|
-
value,
|
|
930
|
-
parent,
|
|
931
|
-
owner
|
|
932
|
-
};
|
|
933
|
-
}
|
|
934
|
-
var ValueStubHook = class extends StubHook {
|
|
935
|
-
call(path, args) {
|
|
936
|
-
try {
|
|
937
|
-
let { value, owner } = this.getValue();
|
|
938
|
-
let followResult = followPath(value, void 0, path, owner);
|
|
939
|
-
if (followResult.hook) {
|
|
940
|
-
return followResult.hook.call(followResult.remainingPath, args);
|
|
941
|
-
}
|
|
942
|
-
if (typeof followResult.value != "function") {
|
|
943
|
-
throw new TypeError(`'${path.join(".")}' is not a function.`);
|
|
944
|
-
}
|
|
945
|
-
let promise = args.deliverCall(followResult.value, followResult.parent);
|
|
946
|
-
return new PromiseStubHook(promise.then((payload) => {
|
|
947
|
-
return new PayloadStubHook(payload);
|
|
948
|
-
}));
|
|
949
|
-
} catch (err) {
|
|
950
|
-
return new ErrorStubHook(err);
|
|
951
|
-
}
|
|
952
|
-
}
|
|
953
|
-
map(path, captures, instructions) {
|
|
954
|
-
try {
|
|
955
|
-
let followResult;
|
|
956
|
-
try {
|
|
957
|
-
let { value, owner } = this.getValue();
|
|
958
|
-
followResult = followPath(value, void 0, path, owner);
|
|
959
|
-
;
|
|
960
|
-
} catch (err) {
|
|
961
|
-
for (let cap of captures) {
|
|
962
|
-
cap.dispose();
|
|
963
|
-
}
|
|
964
|
-
throw err;
|
|
965
|
-
}
|
|
966
|
-
if (followResult.hook) {
|
|
967
|
-
return followResult.hook.map(followResult.remainingPath, captures, instructions);
|
|
968
|
-
}
|
|
969
|
-
return mapImpl.applyMap(
|
|
970
|
-
followResult.value,
|
|
971
|
-
followResult.parent,
|
|
972
|
-
followResult.owner,
|
|
973
|
-
captures,
|
|
974
|
-
instructions
|
|
975
|
-
);
|
|
976
|
-
} catch (err) {
|
|
977
|
-
return new ErrorStubHook(err);
|
|
978
|
-
}
|
|
979
|
-
}
|
|
980
|
-
get(path) {
|
|
981
|
-
try {
|
|
982
|
-
let { value, owner } = this.getValue();
|
|
983
|
-
if (path.length === 0 && owner === null) {
|
|
984
|
-
throw new Error("Can't dup an RpcTarget stub as a promise.");
|
|
985
|
-
}
|
|
986
|
-
let followResult = followPath(value, void 0, path, owner);
|
|
987
|
-
if (followResult.hook) {
|
|
988
|
-
return followResult.hook.get(followResult.remainingPath);
|
|
989
|
-
}
|
|
990
|
-
return new PayloadStubHook(RpcPayload.deepCopyFrom(
|
|
991
|
-
followResult.value,
|
|
992
|
-
followResult.parent,
|
|
993
|
-
followResult.owner
|
|
994
|
-
));
|
|
995
|
-
} catch (err) {
|
|
996
|
-
return new ErrorStubHook(err);
|
|
997
|
-
}
|
|
998
|
-
}
|
|
999
|
-
};
|
|
1000
|
-
var PayloadStubHook = class _PayloadStubHook extends ValueStubHook {
|
|
1001
|
-
constructor(payload) {
|
|
1002
|
-
super();
|
|
1003
|
-
this.payload = payload;
|
|
1004
|
-
}
|
|
1005
|
-
payload;
|
|
1006
|
-
// cleared when disposed
|
|
1007
|
-
getPayload() {
|
|
1008
|
-
if (this.payload) {
|
|
1009
|
-
return this.payload;
|
|
1010
|
-
} else {
|
|
1011
|
-
throw new Error("Attempted to use an RPC StubHook after it was disposed.");
|
|
1012
|
-
}
|
|
1013
|
-
}
|
|
1014
|
-
getValue() {
|
|
1015
|
-
let payload = this.getPayload();
|
|
1016
|
-
return { value: payload.value, owner: payload };
|
|
1017
|
-
}
|
|
1018
|
-
dup() {
|
|
1019
|
-
let thisPayload = this.getPayload();
|
|
1020
|
-
return new _PayloadStubHook(RpcPayload.deepCopyFrom(
|
|
1021
|
-
thisPayload.value,
|
|
1022
|
-
void 0,
|
|
1023
|
-
thisPayload
|
|
1024
|
-
));
|
|
1025
|
-
}
|
|
1026
|
-
pull() {
|
|
1027
|
-
return this.getPayload();
|
|
1028
|
-
}
|
|
1029
|
-
ignoreUnhandledRejections() {
|
|
1030
|
-
if (this.payload) {
|
|
1031
|
-
this.payload.ignoreUnhandledRejections();
|
|
1032
|
-
}
|
|
1033
|
-
}
|
|
1034
|
-
dispose() {
|
|
1035
|
-
if (this.payload) {
|
|
1036
|
-
this.payload.dispose();
|
|
1037
|
-
this.payload = void 0;
|
|
1038
|
-
}
|
|
1039
|
-
}
|
|
1040
|
-
onBroken(callback) {
|
|
1041
|
-
if (this.payload) {
|
|
1042
|
-
if (this.payload.value instanceof RpcStub) {
|
|
1043
|
-
this.payload.value.onRpcBroken(callback);
|
|
1044
|
-
}
|
|
1045
|
-
}
|
|
1046
|
-
}
|
|
1047
|
-
};
|
|
1048
|
-
function disposeRpcTarget(target) {
|
|
1049
|
-
if (Symbol.dispose in target) {
|
|
1050
|
-
try {
|
|
1051
|
-
target[Symbol.dispose]();
|
|
1052
|
-
} catch (err) {
|
|
1053
|
-
Promise.reject(err);
|
|
1054
|
-
}
|
|
1055
|
-
}
|
|
1056
|
-
}
|
|
1057
|
-
var TargetStubHook = class _TargetStubHook extends ValueStubHook {
|
|
1058
|
-
// Constructs a TargetStubHook that is not duplicated from an existing hook.
|
|
1059
|
-
//
|
|
1060
|
-
// If `value` is a function, `parent` is bound as its "this".
|
|
1061
|
-
static create(value, parent) {
|
|
1062
|
-
if (typeof value !== "function") {
|
|
1063
|
-
parent = void 0;
|
|
1064
|
-
}
|
|
1065
|
-
return new _TargetStubHook(value, parent);
|
|
1066
|
-
}
|
|
1067
|
-
constructor(target, parent, dupFrom) {
|
|
1068
|
-
super();
|
|
1069
|
-
this.target = target;
|
|
1070
|
-
this.parent = parent;
|
|
1071
|
-
if (dupFrom) {
|
|
1072
|
-
if (dupFrom.refcount) {
|
|
1073
|
-
this.refcount = dupFrom.refcount;
|
|
1074
|
-
++this.refcount.count;
|
|
1075
|
-
}
|
|
1076
|
-
} else if (Symbol.dispose in target) {
|
|
1077
|
-
this.refcount = { count: 1 };
|
|
1078
|
-
}
|
|
1079
|
-
}
|
|
1080
|
-
target;
|
|
1081
|
-
// cleared when disposed
|
|
1082
|
-
parent;
|
|
1083
|
-
// `this` parameter when calling `target`
|
|
1084
|
-
refcount;
|
|
1085
|
-
// undefined if not needed (because target has no disposer)
|
|
1086
|
-
getTarget() {
|
|
1087
|
-
if (this.target) {
|
|
1088
|
-
return this.target;
|
|
1089
|
-
} else {
|
|
1090
|
-
throw new Error("Attempted to use an RPC StubHook after it was disposed.");
|
|
1091
|
-
}
|
|
1092
|
-
}
|
|
1093
|
-
getValue() {
|
|
1094
|
-
return { value: this.getTarget(), owner: null };
|
|
1095
|
-
}
|
|
1096
|
-
dup() {
|
|
1097
|
-
return new _TargetStubHook(this.getTarget(), this.parent, this);
|
|
1098
|
-
}
|
|
1099
|
-
pull() {
|
|
1100
|
-
let target = this.getTarget();
|
|
1101
|
-
if ("then" in target) {
|
|
1102
|
-
return Promise.resolve(target).then((resolution) => {
|
|
1103
|
-
return RpcPayload.fromAppReturn(resolution);
|
|
1104
|
-
});
|
|
1105
|
-
} else {
|
|
1106
|
-
return Promise.reject(new Error("Tried to resolve a non-promise stub."));
|
|
1107
|
-
}
|
|
1108
|
-
}
|
|
1109
|
-
ignoreUnhandledRejections() {
|
|
1110
|
-
}
|
|
1111
|
-
dispose() {
|
|
1112
|
-
if (this.target) {
|
|
1113
|
-
if (this.refcount) {
|
|
1114
|
-
if (--this.refcount.count == 0) {
|
|
1115
|
-
disposeRpcTarget(this.target);
|
|
1116
|
-
}
|
|
1117
|
-
}
|
|
1118
|
-
this.target = void 0;
|
|
1119
|
-
}
|
|
1120
|
-
}
|
|
1121
|
-
onBroken(callback) {
|
|
1122
|
-
}
|
|
1123
|
-
};
|
|
1124
|
-
var PromiseStubHook = class _PromiseStubHook extends StubHook {
|
|
1125
|
-
promise;
|
|
1126
|
-
resolution;
|
|
1127
|
-
constructor(promise) {
|
|
1128
|
-
super();
|
|
1129
|
-
this.promise = promise.then((res) => {
|
|
1130
|
-
this.resolution = res;
|
|
1131
|
-
return res;
|
|
1132
|
-
});
|
|
1133
|
-
}
|
|
1134
|
-
call(path, args) {
|
|
1135
|
-
args.ensureDeepCopied();
|
|
1136
|
-
return new _PromiseStubHook(this.promise.then((hook) => hook.call(path, args)));
|
|
1137
|
-
}
|
|
1138
|
-
map(path, captures, instructions) {
|
|
1139
|
-
return new _PromiseStubHook(this.promise.then(
|
|
1140
|
-
(hook) => hook.map(path, captures, instructions),
|
|
1141
|
-
(err) => {
|
|
1142
|
-
for (let cap of captures) {
|
|
1143
|
-
cap.dispose();
|
|
1144
|
-
}
|
|
1145
|
-
throw err;
|
|
1146
|
-
}
|
|
1147
|
-
));
|
|
1148
|
-
}
|
|
1149
|
-
get(path) {
|
|
1150
|
-
return new _PromiseStubHook(this.promise.then((hook) => hook.get(path)));
|
|
1151
|
-
}
|
|
1152
|
-
dup() {
|
|
1153
|
-
if (this.resolution) {
|
|
1154
|
-
return this.resolution.dup();
|
|
1155
|
-
} else {
|
|
1156
|
-
return new _PromiseStubHook(this.promise.then((hook) => hook.dup()));
|
|
1157
|
-
}
|
|
1158
|
-
}
|
|
1159
|
-
pull() {
|
|
1160
|
-
if (this.resolution) {
|
|
1161
|
-
return this.resolution.pull();
|
|
1162
|
-
} else {
|
|
1163
|
-
return this.promise.then((hook) => hook.pull());
|
|
1164
|
-
}
|
|
1165
|
-
}
|
|
1166
|
-
ignoreUnhandledRejections() {
|
|
1167
|
-
if (this.resolution) {
|
|
1168
|
-
this.resolution.ignoreUnhandledRejections();
|
|
1169
|
-
} else {
|
|
1170
|
-
this.promise.then((res) => {
|
|
1171
|
-
res.ignoreUnhandledRejections();
|
|
1172
|
-
}, (err) => {
|
|
1173
|
-
});
|
|
1174
|
-
}
|
|
1175
|
-
}
|
|
1176
|
-
dispose() {
|
|
1177
|
-
if (this.resolution) {
|
|
1178
|
-
this.resolution.dispose();
|
|
1179
|
-
} else {
|
|
1180
|
-
this.promise.then((hook) => {
|
|
1181
|
-
hook.dispose();
|
|
1182
|
-
}, (err) => {
|
|
1183
|
-
});
|
|
1184
|
-
}
|
|
1185
|
-
}
|
|
1186
|
-
onBroken(callback) {
|
|
1187
|
-
if (this.resolution) {
|
|
1188
|
-
this.resolution.onBroken(callback);
|
|
1189
|
-
} else {
|
|
1190
|
-
this.promise.then((hook) => {
|
|
1191
|
-
hook.onBroken(callback);
|
|
1192
|
-
}, callback);
|
|
1193
|
-
}
|
|
1194
|
-
}
|
|
1195
|
-
};
|
|
1196
|
-
var currentMapBuilder;
|
|
1197
|
-
var MapBuilder = class {
|
|
1198
|
-
context;
|
|
1199
|
-
captureMap = /* @__PURE__ */ new Map();
|
|
1200
|
-
instructions = [];
|
|
1201
|
-
constructor(subject, path) {
|
|
1202
|
-
if (currentMapBuilder) {
|
|
1203
|
-
this.context = {
|
|
1204
|
-
parent: currentMapBuilder,
|
|
1205
|
-
captures: [],
|
|
1206
|
-
subject: currentMapBuilder.capture(subject),
|
|
1207
|
-
path
|
|
1208
|
-
};
|
|
1209
|
-
} else {
|
|
1210
|
-
this.context = {
|
|
1211
|
-
parent: void 0,
|
|
1212
|
-
captures: [],
|
|
1213
|
-
subject,
|
|
1214
|
-
path
|
|
1215
|
-
};
|
|
1216
|
-
}
|
|
1217
|
-
currentMapBuilder = this;
|
|
1218
|
-
}
|
|
1219
|
-
unregister() {
|
|
1220
|
-
currentMapBuilder = this.context.parent;
|
|
1221
|
-
}
|
|
1222
|
-
makeInput() {
|
|
1223
|
-
return new MapVariableHook(this, 0);
|
|
1224
|
-
}
|
|
1225
|
-
makeOutput(result) {
|
|
1226
|
-
let devalued;
|
|
1227
|
-
try {
|
|
1228
|
-
devalued = Devaluator.devaluate(result.value, void 0, this, result);
|
|
1229
|
-
} finally {
|
|
1230
|
-
result.dispose();
|
|
1231
|
-
}
|
|
1232
|
-
this.instructions.push(devalued);
|
|
1233
|
-
if (this.context.parent) {
|
|
1234
|
-
this.context.parent.instructions.push(
|
|
1235
|
-
[
|
|
1236
|
-
"remap",
|
|
1237
|
-
this.context.subject,
|
|
1238
|
-
this.context.path,
|
|
1239
|
-
this.context.captures.map((cap) => ["import", cap]),
|
|
1240
|
-
this.instructions
|
|
1241
|
-
]
|
|
1242
|
-
);
|
|
1243
|
-
return new MapVariableHook(this.context.parent, this.context.parent.instructions.length);
|
|
1244
|
-
} else {
|
|
1245
|
-
return this.context.subject.map(this.context.path, this.context.captures, this.instructions);
|
|
1246
|
-
}
|
|
1247
|
-
}
|
|
1248
|
-
pushCall(hook, path, params) {
|
|
1249
|
-
let devalued = Devaluator.devaluate(params.value, void 0, this, params);
|
|
1250
|
-
devalued = devalued[0];
|
|
1251
|
-
let subject = this.capture(hook.dup());
|
|
1252
|
-
this.instructions.push(["pipeline", subject, path, devalued]);
|
|
1253
|
-
return new MapVariableHook(this, this.instructions.length);
|
|
1254
|
-
}
|
|
1255
|
-
pushGet(hook, path) {
|
|
1256
|
-
let subject = this.capture(hook.dup());
|
|
1257
|
-
this.instructions.push(["pipeline", subject, path]);
|
|
1258
|
-
return new MapVariableHook(this, this.instructions.length);
|
|
1259
|
-
}
|
|
1260
|
-
capture(hook) {
|
|
1261
|
-
if (hook instanceof MapVariableHook && hook.mapper === this) {
|
|
1262
|
-
return hook.idx;
|
|
1263
|
-
}
|
|
1264
|
-
let result = this.captureMap.get(hook);
|
|
1265
|
-
if (result === void 0) {
|
|
1266
|
-
if (this.context.parent) {
|
|
1267
|
-
let parentIdx = this.context.parent.capture(hook);
|
|
1268
|
-
this.context.captures.push(parentIdx);
|
|
1269
|
-
} else {
|
|
1270
|
-
this.context.captures.push(hook);
|
|
1271
|
-
}
|
|
1272
|
-
result = -this.context.captures.length;
|
|
1273
|
-
this.captureMap.set(hook, result);
|
|
1274
|
-
}
|
|
1275
|
-
return result;
|
|
1276
|
-
}
|
|
1277
|
-
// ---------------------------------------------------------------------------
|
|
1278
|
-
// implements Exporter
|
|
1279
|
-
exportStub(hook) {
|
|
1280
|
-
throw new Error(
|
|
1281
|
-
"Can't construct an RpcTarget or RPC callback inside a mapper function. Try creating a new RpcStub outside the callback first, then using it inside the callback."
|
|
1282
|
-
);
|
|
1283
|
-
}
|
|
1284
|
-
exportPromise(hook) {
|
|
1285
|
-
return this.exportStub(hook);
|
|
1286
|
-
}
|
|
1287
|
-
getImport(hook) {
|
|
1288
|
-
return this.capture(hook);
|
|
1289
|
-
}
|
|
1290
|
-
unexport(ids) {
|
|
1291
|
-
}
|
|
1292
|
-
onSendError(error) {
|
|
1293
|
-
}
|
|
1294
|
-
};
|
|
1295
|
-
mapImpl.sendMap = (hook, path, func) => {
|
|
1296
|
-
let builder = new MapBuilder(hook, path);
|
|
1297
|
-
let result;
|
|
1298
|
-
try {
|
|
1299
|
-
result = RpcPayload.fromAppReturn(withCallInterceptor(builder.pushCall.bind(builder), () => {
|
|
1300
|
-
return func(new RpcPromise(builder.makeInput(), []));
|
|
1301
|
-
}));
|
|
1302
|
-
} finally {
|
|
1303
|
-
builder.unregister();
|
|
1304
|
-
}
|
|
1305
|
-
if (result instanceof Promise) {
|
|
1306
|
-
result.catch((err) => {
|
|
1307
|
-
});
|
|
1308
|
-
throw new Error("RPC map() callbacks cannot be async.");
|
|
1309
|
-
}
|
|
1310
|
-
return new RpcPromise(builder.makeOutput(result), []);
|
|
1311
|
-
};
|
|
1312
|
-
mapImpl.recordCallback = (func) => {
|
|
1313
|
-
const builder = new MapBuilder(new PayloadStubHook(RpcPayload.fromAppParams([])), []);
|
|
1314
|
-
let result;
|
|
1315
|
-
try {
|
|
1316
|
-
result = RpcPayload.fromAppReturn(withCallInterceptor(builder.pushCall.bind(builder), () => {
|
|
1317
|
-
return func(new RpcPromise(builder.makeInput(), []));
|
|
1318
|
-
}));
|
|
1319
|
-
} finally {
|
|
1320
|
-
builder.unregister();
|
|
1321
|
-
}
|
|
1322
|
-
const devaluatedResult = Devaluator.devaluate(result.value, void 0, builder, result);
|
|
1323
|
-
const instructions = [...builder.instructions, devaluatedResult];
|
|
1324
|
-
const context = builder.context;
|
|
1325
|
-
if (context.parent) {
|
|
1326
|
-
return ["callback", context.captures.map((cap) => ["import", cap]), instructions];
|
|
1327
|
-
} else {
|
|
1328
|
-
return ["callback", context.captures, instructions];
|
|
1329
|
-
}
|
|
1330
|
-
};
|
|
1331
|
-
function throwMapperBuilderUseError() {
|
|
1332
|
-
throw new Error(
|
|
1333
|
-
"Attempted to use an abstract placeholder from a mapper function. Please make sure your map function has no side effects."
|
|
1334
|
-
);
|
|
1335
|
-
}
|
|
1336
|
-
var MapVariableHook = class extends StubHook {
|
|
1337
|
-
constructor(mapper, idx) {
|
|
1338
|
-
super();
|
|
1339
|
-
this.mapper = mapper;
|
|
1340
|
-
this.idx = idx;
|
|
1341
|
-
}
|
|
1342
|
-
// We don't have anything we actually need to dispose, so dup() can just return the same hook.
|
|
1343
|
-
dup() {
|
|
1344
|
-
return this;
|
|
1345
|
-
}
|
|
1346
|
-
dispose() {
|
|
1347
|
-
}
|
|
1348
|
-
get(path) {
|
|
1349
|
-
if (path.length == 0) {
|
|
1350
|
-
return this;
|
|
1351
|
-
} else if (currentMapBuilder) {
|
|
1352
|
-
return currentMapBuilder.pushGet(this, path);
|
|
1353
|
-
} else {
|
|
1354
|
-
throwMapperBuilderUseError();
|
|
1355
|
-
}
|
|
1356
|
-
}
|
|
1357
|
-
// Other methods should never be called.
|
|
1358
|
-
call(path, args) {
|
|
1359
|
-
throwMapperBuilderUseError();
|
|
1360
|
-
}
|
|
1361
|
-
map(path, captures, instructions) {
|
|
1362
|
-
throwMapperBuilderUseError();
|
|
1363
|
-
}
|
|
1364
|
-
pull() {
|
|
1365
|
-
throwMapperBuilderUseError();
|
|
1366
|
-
}
|
|
1367
|
-
ignoreUnhandledRejections() {
|
|
1368
|
-
}
|
|
1369
|
-
onBroken(callback) {
|
|
1370
|
-
throwMapperBuilderUseError();
|
|
1371
|
-
}
|
|
1372
|
-
};
|
|
1373
|
-
var MapApplicator = class {
|
|
1374
|
-
constructor(captures, input) {
|
|
1375
|
-
this.captures = captures;
|
|
1376
|
-
this.variables = [input];
|
|
1377
|
-
}
|
|
1378
|
-
variables;
|
|
1379
|
-
dispose() {
|
|
1380
|
-
for (let variable of this.variables) {
|
|
1381
|
-
variable.dispose();
|
|
1382
|
-
}
|
|
1383
|
-
}
|
|
1384
|
-
apply(instructions) {
|
|
1385
|
-
try {
|
|
1386
|
-
if (instructions.length < 1) {
|
|
1387
|
-
throw new Error("Invalid empty mapper function.");
|
|
1388
|
-
}
|
|
1389
|
-
for (let instruction of instructions.slice(0, -1)) {
|
|
1390
|
-
let payload = new Evaluator(this).evaluateCopy(instruction);
|
|
1391
|
-
if (payload.value instanceof RpcStub) {
|
|
1392
|
-
let hook = unwrapStubNoProperties(payload.value);
|
|
1393
|
-
if (hook) {
|
|
1394
|
-
this.variables.push(hook);
|
|
1395
|
-
continue;
|
|
1396
|
-
}
|
|
1397
|
-
}
|
|
1398
|
-
this.variables.push(new PayloadStubHook(payload));
|
|
1399
|
-
}
|
|
1400
|
-
return new Evaluator(this).evaluateCopy(instructions[instructions.length - 1]);
|
|
1401
|
-
} finally {
|
|
1402
|
-
for (let variable of this.variables) {
|
|
1403
|
-
variable.dispose();
|
|
1404
|
-
}
|
|
1405
|
-
}
|
|
1406
|
-
}
|
|
1407
|
-
importStub(idx) {
|
|
1408
|
-
throw new Error("A mapper function cannot refer to exports.");
|
|
1409
|
-
}
|
|
1410
|
-
importPromise(idx) {
|
|
1411
|
-
return this.importStub(idx);
|
|
1412
|
-
}
|
|
1413
|
-
getExport(idx) {
|
|
1414
|
-
if (idx < 0) {
|
|
1415
|
-
return this.captures[-idx - 1];
|
|
1416
|
-
} else {
|
|
1417
|
-
return this.variables[idx];
|
|
1418
|
-
}
|
|
1419
|
-
}
|
|
1420
|
-
};
|
|
1421
|
-
function applyMapToElement(input, parent, owner, captures, instructions) {
|
|
1422
|
-
let inputHook = new PayloadStubHook(RpcPayload.deepCopyFrom(input, parent, owner));
|
|
1423
|
-
let mapper = new MapApplicator(captures, inputHook);
|
|
1424
|
-
try {
|
|
1425
|
-
return mapper.apply(instructions);
|
|
1426
|
-
} finally {
|
|
1427
|
-
mapper.dispose();
|
|
1428
|
-
}
|
|
1429
|
-
}
|
|
1430
|
-
mapImpl.applyMap = (input, parent, owner, captures, instructions) => {
|
|
1431
|
-
try {
|
|
1432
|
-
let result;
|
|
1433
|
-
if (input instanceof RpcPromise) {
|
|
1434
|
-
throw new Error("applyMap() can't be called on RpcPromise");
|
|
1435
|
-
} else if (input instanceof Array) {
|
|
1436
|
-
let payloads = [];
|
|
1437
|
-
try {
|
|
1438
|
-
for (let elem of input) {
|
|
1439
|
-
payloads.push(applyMapToElement(elem, input, owner, captures, instructions));
|
|
1440
|
-
}
|
|
1441
|
-
} catch (err) {
|
|
1442
|
-
for (let payload of payloads) {
|
|
1443
|
-
payload.dispose();
|
|
1444
|
-
}
|
|
1445
|
-
throw err;
|
|
1446
|
-
}
|
|
1447
|
-
result = RpcPayload.fromArray(payloads);
|
|
1448
|
-
} else if (input === null || input === void 0) {
|
|
1449
|
-
result = RpcPayload.fromAppReturn(input);
|
|
1450
|
-
} else {
|
|
1451
|
-
result = applyMapToElement(input, parent, owner, captures, instructions);
|
|
1452
|
-
}
|
|
1453
|
-
return new PayloadStubHook(result);
|
|
1454
|
-
} finally {
|
|
1455
|
-
for (let cap of captures) {
|
|
1456
|
-
cap.dispose();
|
|
1457
|
-
}
|
|
1458
|
-
}
|
|
1459
|
-
};
|
|
1460
|
-
var isExplicitCallback = (arg) => {
|
|
1461
|
-
return typeof arg === "function" && "serializationMode" in arg;
|
|
1462
|
-
};
|
|
1463
|
-
var NullExporter = class {
|
|
1464
|
-
exportStub(stub) {
|
|
1465
|
-
throw new Error("Cannot serialize RPC stubs without an RPC session.");
|
|
1466
|
-
}
|
|
1467
|
-
exportPromise(stub) {
|
|
1468
|
-
throw new Error("Cannot serialize RPC stubs without an RPC session.");
|
|
1469
|
-
}
|
|
1470
|
-
getImport(hook) {
|
|
1471
|
-
return void 0;
|
|
1472
|
-
}
|
|
1473
|
-
unexport(ids) {
|
|
1474
|
-
}
|
|
1475
|
-
onSendError(error) {
|
|
1476
|
-
}
|
|
1477
|
-
};
|
|
1478
|
-
var NULL_EXPORTER = new NullExporter();
|
|
1479
|
-
var ERROR_TYPES = {
|
|
1480
|
-
Error,
|
|
1481
|
-
EvalError,
|
|
1482
|
-
RangeError,
|
|
1483
|
-
ReferenceError,
|
|
1484
|
-
SyntaxError,
|
|
1485
|
-
TypeError,
|
|
1486
|
-
URIError,
|
|
1487
|
-
AggregateError
|
|
1488
|
-
// TODO: DOMError? Others?
|
|
1489
|
-
};
|
|
1490
|
-
var Devaluator = class _Devaluator {
|
|
1491
|
-
constructor(exporter, source) {
|
|
1492
|
-
this.exporter = exporter;
|
|
1493
|
-
this.source = source;
|
|
1494
|
-
}
|
|
1495
|
-
// Devaluate the given value.
|
|
1496
|
-
// * value: The value to devaluate.
|
|
1497
|
-
// * parent: The value's parent object, which would be used as `this` if the value were called
|
|
1498
|
-
// as a function.
|
|
1499
|
-
// * exporter: Callbacks to the RPC session for exporting capabilities found in this message.
|
|
1500
|
-
// * source: The RpcPayload which contains the value, and therefore owns stubs within.
|
|
1501
|
-
//
|
|
1502
|
-
// Returns: The devaluated value, ready to be JSON-serialized.
|
|
1503
|
-
static devaluate(value, parent, exporter = NULL_EXPORTER, source) {
|
|
1504
|
-
let devaluator = new _Devaluator(exporter, source);
|
|
1505
|
-
try {
|
|
1506
|
-
return devaluator.devaluateImpl(value, parent, 0);
|
|
1507
|
-
} catch (err) {
|
|
1508
|
-
if (devaluator.exports) {
|
|
1509
|
-
try {
|
|
1510
|
-
exporter.unexport(devaluator.exports);
|
|
1511
|
-
} catch (err2) {
|
|
1512
|
-
}
|
|
1513
|
-
}
|
|
1514
|
-
throw err;
|
|
1515
|
-
}
|
|
1516
|
-
}
|
|
1517
|
-
exports;
|
|
1518
|
-
devaluateImpl(value, parent, depth) {
|
|
1519
|
-
if (depth >= 64) {
|
|
1520
|
-
throw new Error(
|
|
1521
|
-
"Serialization exceeded maximum allowed depth. (Does the message contain cycles?)"
|
|
1522
|
-
);
|
|
1523
|
-
}
|
|
1524
|
-
let kind = typeForRpc(value);
|
|
1525
|
-
switch (kind) {
|
|
1526
|
-
case "unsupported": {
|
|
1527
|
-
let msg;
|
|
1528
|
-
try {
|
|
1529
|
-
msg = `Cannot serialize value: ${value}`;
|
|
1530
|
-
} catch (err) {
|
|
1531
|
-
msg = "Cannot serialize value: (couldn't stringify value)";
|
|
1532
|
-
}
|
|
1533
|
-
throw new TypeError(msg);
|
|
1534
|
-
}
|
|
1535
|
-
case "primitive":
|
|
1536
|
-
if (typeof value === "number" && !isFinite(value)) {
|
|
1537
|
-
if (value === Infinity) {
|
|
1538
|
-
return ["inf"];
|
|
1539
|
-
} else if (value === -Infinity) {
|
|
1540
|
-
return ["-inf"];
|
|
1541
|
-
} else {
|
|
1542
|
-
return ["nan"];
|
|
1543
|
-
}
|
|
1544
|
-
} else {
|
|
1545
|
-
return value;
|
|
1546
|
-
}
|
|
1547
|
-
case "object": {
|
|
1548
|
-
let object = value;
|
|
1549
|
-
let result = {};
|
|
1550
|
-
for (let key in object) {
|
|
1551
|
-
result[key] = this.devaluateImpl(object[key], object, depth + 1);
|
|
1552
|
-
}
|
|
1553
|
-
return result;
|
|
1554
|
-
}
|
|
1555
|
-
case "array": {
|
|
1556
|
-
let array = value;
|
|
1557
|
-
let len = array.length;
|
|
1558
|
-
let result = new Array(len);
|
|
1559
|
-
for (let i = 0; i < len; i++) {
|
|
1560
|
-
result[i] = this.devaluateImpl(array[i], array, depth + 1);
|
|
1561
|
-
}
|
|
1562
|
-
return [result];
|
|
1563
|
-
}
|
|
1564
|
-
case "bigint":
|
|
1565
|
-
return ["bigint", value.toString()];
|
|
1566
|
-
case "date":
|
|
1567
|
-
return ["date", value.getTime()];
|
|
1568
|
-
case "bytes": {
|
|
1569
|
-
let bytes = value;
|
|
1570
|
-
if (bytes.toBase64) {
|
|
1571
|
-
return ["bytes", bytes.toBase64({ omitPadding: true })];
|
|
1572
|
-
} else {
|
|
1573
|
-
return [
|
|
1574
|
-
"bytes",
|
|
1575
|
-
btoa(String.fromCharCode.apply(null, bytes).replace(/=*$/, ""))
|
|
1576
|
-
];
|
|
1577
|
-
}
|
|
1578
|
-
}
|
|
1579
|
-
case "error": {
|
|
1580
|
-
let e = value;
|
|
1581
|
-
let rewritten = this.exporter.onSendError(e);
|
|
1582
|
-
if (rewritten) {
|
|
1583
|
-
e = rewritten;
|
|
1584
|
-
}
|
|
1585
|
-
let result = ["error", e.name, e.message];
|
|
1586
|
-
if (rewritten && rewritten.stack) {
|
|
1587
|
-
result.push(rewritten.stack);
|
|
1588
|
-
}
|
|
1589
|
-
return result;
|
|
1590
|
-
}
|
|
1591
|
-
case "undefined":
|
|
1592
|
-
return ["undefined"];
|
|
1593
|
-
case "stub":
|
|
1594
|
-
case "rpc-promise": {
|
|
1595
|
-
if (!this.source) {
|
|
1596
|
-
throw new Error("Can't serialize RPC stubs in this context.");
|
|
1597
|
-
}
|
|
1598
|
-
let { hook, pathIfPromise } = unwrapStubAndPath(value);
|
|
1599
|
-
let importId = this.exporter.getImport(hook);
|
|
1600
|
-
if (importId !== void 0) {
|
|
1601
|
-
if (pathIfPromise) {
|
|
1602
|
-
if (pathIfPromise.length > 0) {
|
|
1603
|
-
return ["pipeline", importId, pathIfPromise];
|
|
1604
|
-
} else {
|
|
1605
|
-
return ["pipeline", importId];
|
|
1606
|
-
}
|
|
1607
|
-
} else {
|
|
1608
|
-
return ["import", importId];
|
|
1609
|
-
}
|
|
1610
|
-
}
|
|
1611
|
-
if (pathIfPromise) {
|
|
1612
|
-
hook = hook.get(pathIfPromise);
|
|
1613
|
-
} else {
|
|
1614
|
-
hook = hook.dup();
|
|
1615
|
-
}
|
|
1616
|
-
return this.devaluateHook(pathIfPromise ? "promise" : "export", hook);
|
|
1617
|
-
}
|
|
1618
|
-
case "function":
|
|
1619
|
-
case "rpc-target": {
|
|
1620
|
-
let shouldRecordReplay = false;
|
|
1621
|
-
if (kind === "function") {
|
|
1622
|
-
if (isExplicitCallback(value)) {
|
|
1623
|
-
const explicitMode = value.serializationMode;
|
|
1624
|
-
shouldRecordReplay = explicitMode === "recordReplay";
|
|
1625
|
-
} else {
|
|
1626
|
-
shouldRecordReplay = getGlobalRpcSessionOptions().recordReplayMode === "all";
|
|
1627
|
-
}
|
|
1628
|
-
}
|
|
1629
|
-
if (shouldRecordReplay) {
|
|
1630
|
-
const res = mapImpl.recordCallback(value);
|
|
1631
|
-
const captures = res[1];
|
|
1632
|
-
if (captures.length === 0 || captures[0] instanceof StubHook) {
|
|
1633
|
-
const captureHooks = captures;
|
|
1634
|
-
const serializedCaptures = captureHooks.map((stub) => {
|
|
1635
|
-
const importId = this.exporter.getImport(stub);
|
|
1636
|
-
if (importId !== void 0) {
|
|
1637
|
-
return ["import", importId];
|
|
1638
|
-
} else {
|
|
1639
|
-
return ["export", this.exporter.exportStub(stub)];
|
|
1640
|
-
}
|
|
1641
|
-
});
|
|
1642
|
-
for (const hook2 of captureHooks) {
|
|
1643
|
-
hook2.dispose();
|
|
1644
|
-
}
|
|
1645
|
-
return ["callback", serializedCaptures, res[2]];
|
|
1646
|
-
} else {
|
|
1647
|
-
return res;
|
|
1648
|
-
}
|
|
1649
|
-
}
|
|
1650
|
-
if (!this.source) {
|
|
1651
|
-
throw new Error("Can't serialize RPC stubs in this context.");
|
|
1652
|
-
}
|
|
1653
|
-
let hook = this.source.getHookForRpcTarget(value, parent);
|
|
1654
|
-
return this.devaluateHook("export", hook);
|
|
1655
|
-
}
|
|
1656
|
-
case "rpc-thenable": {
|
|
1657
|
-
if (!this.source) {
|
|
1658
|
-
throw new Error("Can't serialize RPC stubs in this context.");
|
|
1659
|
-
}
|
|
1660
|
-
let hook = this.source.getHookForRpcTarget(value, parent);
|
|
1661
|
-
return this.devaluateHook("promise", hook);
|
|
1662
|
-
}
|
|
1663
|
-
default:
|
|
1664
|
-
throw new Error("unreachable");
|
|
1665
|
-
}
|
|
1666
|
-
}
|
|
1667
|
-
devaluateHook(type, hook) {
|
|
1668
|
-
if (!this.exports) this.exports = [];
|
|
1669
|
-
let exportId = type === "promise" ? this.exporter.exportPromise(hook) : this.exporter.exportStub(hook);
|
|
1670
|
-
this.exports.push(exportId);
|
|
1671
|
-
return [type, exportId];
|
|
1672
|
-
}
|
|
1673
|
-
};
|
|
1674
|
-
var NullImporter = class {
|
|
1675
|
-
importStub(idx) {
|
|
1676
|
-
throw new Error("Cannot deserialize RPC stubs without an RPC session.");
|
|
1677
|
-
}
|
|
1678
|
-
importPromise(idx) {
|
|
1679
|
-
throw new Error("Cannot deserialize RPC stubs without an RPC session.");
|
|
1680
|
-
}
|
|
1681
|
-
getExport(idx) {
|
|
1682
|
-
return void 0;
|
|
1683
|
-
}
|
|
1684
|
-
};
|
|
1685
|
-
var NULL_IMPORTER = new NullImporter();
|
|
1686
|
-
var Evaluator = class _Evaluator {
|
|
1687
|
-
constructor(importer) {
|
|
1688
|
-
this.importer = importer;
|
|
1689
|
-
}
|
|
1690
|
-
stubs = [];
|
|
1691
|
-
promises = [];
|
|
1692
|
-
// Resolve serialized captures to StubHooks. Used by both "callback" and "remap" evaluation.
|
|
1693
|
-
resolveCaptures(capsData) {
|
|
1694
|
-
return capsData.map((cap) => {
|
|
1695
|
-
if (!(cap instanceof Array) || cap.length !== 2 || cap[0] !== "import" && cap[0] !== "export" || typeof cap[1] !== "number") {
|
|
1696
|
-
throw new TypeError(`unknown capture: ${JSON.stringify(cap)}`);
|
|
1697
|
-
}
|
|
1698
|
-
if (cap[0] === "export") {
|
|
1699
|
-
return this.importer.importStub(cap[1]);
|
|
1700
|
-
} else {
|
|
1701
|
-
let exp = this.importer.getExport(cap[1]);
|
|
1702
|
-
if (!exp) {
|
|
1703
|
-
throw new Error(`no such entry on exports table: ${cap[1]}`);
|
|
1704
|
-
}
|
|
1705
|
-
return exp.dup();
|
|
1706
|
-
}
|
|
1707
|
-
});
|
|
1708
|
-
}
|
|
1709
|
-
evaluate(value) {
|
|
1710
|
-
let payload = RpcPayload.forEvaluate(this.stubs, this.promises);
|
|
1711
|
-
try {
|
|
1712
|
-
payload.value = this.evaluateImpl(value, payload, "value");
|
|
1713
|
-
return payload;
|
|
1714
|
-
} catch (err) {
|
|
1715
|
-
payload.dispose();
|
|
1716
|
-
throw err;
|
|
1717
|
-
}
|
|
1718
|
-
}
|
|
1719
|
-
// Evaluate the value without destroying it.
|
|
1720
|
-
evaluateCopy(value) {
|
|
1721
|
-
return this.evaluate(structuredClone(value));
|
|
1722
|
-
}
|
|
1723
|
-
evaluateImpl(value, parent, property) {
|
|
1724
|
-
if (value instanceof Array) {
|
|
1725
|
-
if (value.length == 1 && value[0] instanceof Array) {
|
|
1726
|
-
let result = value[0];
|
|
1727
|
-
for (let i = 0; i < result.length; i++) {
|
|
1728
|
-
result[i] = this.evaluateImpl(result[i], result, i);
|
|
1729
|
-
}
|
|
1730
|
-
return result;
|
|
1731
|
-
} else switch (value[0]) {
|
|
1732
|
-
case "callback": {
|
|
1733
|
-
if (value.length < 3 || !(value[1] instanceof Array) || !(value[2] instanceof Array)) {
|
|
1734
|
-
break;
|
|
1735
|
-
}
|
|
1736
|
-
const captures = this.resolveCaptures(value[1]);
|
|
1737
|
-
const instructions = value[2];
|
|
1738
|
-
const replayFn = (arg) => {
|
|
1739
|
-
const capturesForThisCall = captures.map((c) => c.dup());
|
|
1740
|
-
const inputHook = new PayloadStubHook(RpcPayload.fromAppParams(arg));
|
|
1741
|
-
const applicator = new MapApplicator(capturesForThisCall, inputHook);
|
|
1742
|
-
const disposeInvocation = () => {
|
|
1743
|
-
applicator.dispose();
|
|
1744
|
-
for (const cap of capturesForThisCall) {
|
|
1745
|
-
cap.dispose();
|
|
1746
|
-
}
|
|
1747
|
-
const cleanup = replayFn[CALLBACK_CLEANUP];
|
|
1748
|
-
if (typeof cleanup === "function") {
|
|
1749
|
-
cleanup();
|
|
1750
|
-
}
|
|
1751
|
-
};
|
|
1752
|
-
let resultPayload;
|
|
1753
|
-
try {
|
|
1754
|
-
resultPayload = applicator.apply(instructions);
|
|
1755
|
-
} catch (err) {
|
|
1756
|
-
disposeInvocation();
|
|
1757
|
-
throw err;
|
|
1758
|
-
}
|
|
1759
|
-
return resultPayload.deliverResolve().finally(disposeInvocation);
|
|
1760
|
-
};
|
|
1761
|
-
replayFn[CALLBACK_CLEANUP] = () => {
|
|
1762
|
-
for (const cap of captures) {
|
|
1763
|
-
cap.dispose();
|
|
1764
|
-
}
|
|
1765
|
-
};
|
|
1766
|
-
return replayFn;
|
|
1767
|
-
}
|
|
1768
|
-
case "bigint":
|
|
1769
|
-
if (typeof value[1] == "string") {
|
|
1770
|
-
return BigInt(value[1]);
|
|
1771
|
-
}
|
|
1772
|
-
break;
|
|
1773
|
-
case "date":
|
|
1774
|
-
if (typeof value[1] == "number") {
|
|
1775
|
-
return new Date(value[1]);
|
|
1776
|
-
}
|
|
1777
|
-
break;
|
|
1778
|
-
case "bytes": {
|
|
1779
|
-
let b64 = Uint8Array;
|
|
1780
|
-
if (typeof value[1] == "string") {
|
|
1781
|
-
if (b64.fromBase64) {
|
|
1782
|
-
return b64.fromBase64(value[1]);
|
|
1783
|
-
} else {
|
|
1784
|
-
let bs = atob(value[1]);
|
|
1785
|
-
let len = bs.length;
|
|
1786
|
-
let bytes = new Uint8Array(len);
|
|
1787
|
-
for (let i = 0; i < len; i++) {
|
|
1788
|
-
bytes[i] = bs.charCodeAt(i);
|
|
1789
|
-
}
|
|
1790
|
-
return bytes;
|
|
1791
|
-
}
|
|
1792
|
-
}
|
|
1793
|
-
break;
|
|
1794
|
-
}
|
|
1795
|
-
case "error":
|
|
1796
|
-
if (value.length >= 3 && typeof value[1] === "string" && typeof value[2] === "string") {
|
|
1797
|
-
let cls = ERROR_TYPES[value[1]] || Error;
|
|
1798
|
-
let result = new cls(value[2]);
|
|
1799
|
-
if (typeof value[3] === "string") {
|
|
1800
|
-
result.stack = value[3];
|
|
1801
|
-
}
|
|
1802
|
-
return result;
|
|
1803
|
-
}
|
|
1804
|
-
break;
|
|
1805
|
-
case "undefined":
|
|
1806
|
-
if (value.length === 1) {
|
|
1807
|
-
return void 0;
|
|
1808
|
-
}
|
|
1809
|
-
break;
|
|
1810
|
-
case "inf":
|
|
1811
|
-
return Infinity;
|
|
1812
|
-
case "-inf":
|
|
1813
|
-
return -Infinity;
|
|
1814
|
-
case "nan":
|
|
1815
|
-
return NaN;
|
|
1816
|
-
case "import":
|
|
1817
|
-
case "pipeline": {
|
|
1818
|
-
if (value.length < 2 || value.length > 4) {
|
|
1819
|
-
break;
|
|
1820
|
-
}
|
|
1821
|
-
if (typeof value[1] != "number") {
|
|
1822
|
-
break;
|
|
1823
|
-
}
|
|
1824
|
-
let hook = this.importer.getExport(value[1]);
|
|
1825
|
-
if (!hook) {
|
|
1826
|
-
throw new Error(`no such entry on exports table: ${value[1]}`);
|
|
1827
|
-
}
|
|
1828
|
-
let isPromise = value[0] == "pipeline";
|
|
1829
|
-
let addStub = (hook2) => {
|
|
1830
|
-
const unwrapped = maybeUnwrapStubHook(hook2);
|
|
1831
|
-
if (unwrapped) {
|
|
1832
|
-
hook2.dispose();
|
|
1833
|
-
return unwrapped;
|
|
1834
|
-
}
|
|
1835
|
-
if (isPromise) {
|
|
1836
|
-
let promise = new RpcPromise(hook2, []);
|
|
1837
|
-
this.promises.push({ promise, parent, property });
|
|
1838
|
-
return promise;
|
|
1839
|
-
} else {
|
|
1840
|
-
let stub = new RpcPromise(hook2, []);
|
|
1841
|
-
this.stubs.push(stub);
|
|
1842
|
-
return stub;
|
|
1843
|
-
}
|
|
1844
|
-
};
|
|
1845
|
-
if (value.length == 2) {
|
|
1846
|
-
if (isPromise) {
|
|
1847
|
-
return addStub(hook.get([]));
|
|
1848
|
-
} else {
|
|
1849
|
-
return addStub(hook.dup());
|
|
1850
|
-
}
|
|
1851
|
-
}
|
|
1852
|
-
let path = value[2];
|
|
1853
|
-
if (!(path instanceof Array)) {
|
|
1854
|
-
break;
|
|
1855
|
-
}
|
|
1856
|
-
if (!path.every(
|
|
1857
|
-
(part) => {
|
|
1858
|
-
return typeof part == "string" || typeof part == "number";
|
|
1859
|
-
}
|
|
1860
|
-
)) {
|
|
1861
|
-
break;
|
|
1862
|
-
}
|
|
1863
|
-
if (value.length == 3) {
|
|
1864
|
-
return addStub(hook.get(path));
|
|
1865
|
-
}
|
|
1866
|
-
let args = value[3];
|
|
1867
|
-
if (!(args instanceof Array)) {
|
|
1868
|
-
break;
|
|
1869
|
-
}
|
|
1870
|
-
let subEval = new _Evaluator(this.importer);
|
|
1871
|
-
args = subEval.evaluate([args]);
|
|
1872
|
-
return addStub(hook.call(path, args));
|
|
1873
|
-
}
|
|
1874
|
-
case "remap": {
|
|
1875
|
-
if (value.length !== 5 || typeof value[1] !== "number" || !(value[2] instanceof Array) || !(value[3] instanceof Array) || !(value[4] instanceof Array)) {
|
|
1876
|
-
break;
|
|
1877
|
-
}
|
|
1878
|
-
let hook = this.importer.getExport(value[1]);
|
|
1879
|
-
if (!hook) {
|
|
1880
|
-
throw new Error(`no such entry on exports table: ${value[1]}`);
|
|
1881
|
-
}
|
|
1882
|
-
let path = value[2];
|
|
1883
|
-
if (!path.every(
|
|
1884
|
-
(part) => {
|
|
1885
|
-
return typeof part == "string" || typeof part == "number";
|
|
1886
|
-
}
|
|
1887
|
-
)) {
|
|
1888
|
-
break;
|
|
1889
|
-
}
|
|
1890
|
-
let captures = this.resolveCaptures(value[3]);
|
|
1891
|
-
let instructions = value[4];
|
|
1892
|
-
let resultHook = hook.map(path, captures, instructions);
|
|
1893
|
-
let promise = new RpcPromise(resultHook, []);
|
|
1894
|
-
this.promises.push({ promise, parent, property });
|
|
1895
|
-
return promise;
|
|
1896
|
-
}
|
|
1897
|
-
case "export":
|
|
1898
|
-
case "promise":
|
|
1899
|
-
if (typeof value[1] == "number") {
|
|
1900
|
-
if (value[0] == "promise") {
|
|
1901
|
-
let hook = this.importer.importPromise(value[1]);
|
|
1902
|
-
let promise = new RpcPromise(hook, []);
|
|
1903
|
-
this.promises.push({ parent, property, promise });
|
|
1904
|
-
return promise;
|
|
1905
|
-
} else {
|
|
1906
|
-
let hook = this.importer.importStub(value[1]);
|
|
1907
|
-
let stub = new RpcStub(hook);
|
|
1908
|
-
this.stubs.push(stub);
|
|
1909
|
-
return stub;
|
|
1910
|
-
}
|
|
1911
|
-
}
|
|
1912
|
-
break;
|
|
1913
|
-
}
|
|
1914
|
-
throw new TypeError(`unknown special value: ${JSON.stringify(value)}`);
|
|
1915
|
-
} else if (value instanceof Object) {
|
|
1916
|
-
let result = value;
|
|
1917
|
-
for (let key in result) {
|
|
1918
|
-
if (key in Object.prototype || key === "toJSON") {
|
|
1919
|
-
this.evaluateImpl(result[key], result, key);
|
|
1920
|
-
delete result[key];
|
|
1921
|
-
} else {
|
|
1922
|
-
result[key] = this.evaluateImpl(result[key], result, key);
|
|
1923
|
-
}
|
|
1924
|
-
}
|
|
1925
|
-
return result;
|
|
1926
|
-
} else {
|
|
1927
|
-
return value;
|
|
1928
|
-
}
|
|
1929
|
-
}
|
|
1930
|
-
};
|
|
1931
|
-
var maybeUnwrapStubHook = (hook) => {
|
|
1932
|
-
if (!(hook instanceof PayloadStubHook)) {
|
|
1933
|
-
return void 0;
|
|
1934
|
-
}
|
|
1935
|
-
const payload = hook.getPayload();
|
|
1936
|
-
if (payload.value instanceof RpcStub) {
|
|
1937
|
-
const { hook: innerHook, pathIfPromise } = unwrapStubAndPath(payload.value);
|
|
1938
|
-
if (pathIfPromise == null && innerHook instanceof TargetStubHook) {
|
|
1939
|
-
return innerHook.getTarget();
|
|
1940
|
-
} else {
|
|
1941
|
-
return innerHook;
|
|
1942
|
-
}
|
|
1943
|
-
}
|
|
1944
|
-
return void 0;
|
|
1945
|
-
};
|
|
1946
|
-
var ImportTableEntry = class {
|
|
1947
|
-
constructor(session, importId, pulling) {
|
|
1948
|
-
this.session = session;
|
|
1949
|
-
this.importId = importId;
|
|
1950
|
-
if (pulling) {
|
|
1951
|
-
this.activePull = Promise.withResolvers();
|
|
1952
|
-
}
|
|
1953
|
-
}
|
|
1954
|
-
localRefcount = 0;
|
|
1955
|
-
remoteRefcount = 1;
|
|
1956
|
-
activePull;
|
|
1957
|
-
resolution;
|
|
1958
|
-
// List of integer indexes into session.onBrokenCallbacks which are callbacks registered on
|
|
1959
|
-
// this import. Initialized on first use (so `undefined` is the same as an empty list).
|
|
1960
|
-
onBrokenRegistrations;
|
|
1961
|
-
resolve(resolution) {
|
|
1962
|
-
if (this.localRefcount == 0) {
|
|
1963
|
-
resolution.dispose();
|
|
1964
|
-
return;
|
|
1965
|
-
}
|
|
1966
|
-
this.resolution = resolution;
|
|
1967
|
-
this.sendRelease();
|
|
1968
|
-
if (this.onBrokenRegistrations) {
|
|
1969
|
-
for (let i of this.onBrokenRegistrations) {
|
|
1970
|
-
let callback = this.session.onBrokenCallbacks[i];
|
|
1971
|
-
let endIndex = this.session.onBrokenCallbacks.length;
|
|
1972
|
-
resolution.onBroken(callback);
|
|
1973
|
-
if (this.session.onBrokenCallbacks[endIndex] === callback) {
|
|
1974
|
-
delete this.session.onBrokenCallbacks[endIndex];
|
|
1975
|
-
} else {
|
|
1976
|
-
delete this.session.onBrokenCallbacks[i];
|
|
1977
|
-
}
|
|
1978
|
-
}
|
|
1979
|
-
this.onBrokenRegistrations = void 0;
|
|
1980
|
-
}
|
|
1981
|
-
if (this.activePull) {
|
|
1982
|
-
this.activePull.resolve();
|
|
1983
|
-
this.activePull = void 0;
|
|
1984
|
-
}
|
|
1985
|
-
}
|
|
1986
|
-
async awaitResolution() {
|
|
1987
|
-
if (!this.activePull) {
|
|
1988
|
-
this.session.sendPull(this.importId);
|
|
1989
|
-
this.activePull = Promise.withResolvers();
|
|
1990
|
-
}
|
|
1991
|
-
await this.activePull.promise;
|
|
1992
|
-
return this.resolution.pull();
|
|
1993
|
-
}
|
|
1994
|
-
dispose() {
|
|
1995
|
-
if (this.resolution) {
|
|
1996
|
-
this.resolution.dispose();
|
|
1997
|
-
} else {
|
|
1998
|
-
this.abort(new Error("RPC was canceled because the RpcPromise was disposed."));
|
|
1999
|
-
this.sendRelease();
|
|
2000
|
-
}
|
|
2001
|
-
}
|
|
2002
|
-
abort(error) {
|
|
2003
|
-
if (!this.resolution) {
|
|
2004
|
-
this.resolution = new ErrorStubHook(error);
|
|
2005
|
-
if (this.activePull) {
|
|
2006
|
-
this.activePull.reject(error);
|
|
2007
|
-
this.activePull = void 0;
|
|
2008
|
-
}
|
|
2009
|
-
this.onBrokenRegistrations = void 0;
|
|
2010
|
-
}
|
|
2011
|
-
}
|
|
2012
|
-
onBroken(callback) {
|
|
2013
|
-
if (this.resolution) {
|
|
2014
|
-
this.resolution.onBroken(callback);
|
|
2015
|
-
} else {
|
|
2016
|
-
let index = this.session.onBrokenCallbacks.length;
|
|
2017
|
-
this.session.onBrokenCallbacks.push(callback);
|
|
2018
|
-
if (!this.onBrokenRegistrations) this.onBrokenRegistrations = [];
|
|
2019
|
-
this.onBrokenRegistrations.push(index);
|
|
2020
|
-
}
|
|
2021
|
-
}
|
|
2022
|
-
sendRelease() {
|
|
2023
|
-
if (this.remoteRefcount > 0) {
|
|
2024
|
-
this.session.sendRelease(this.importId, this.remoteRefcount);
|
|
2025
|
-
this.remoteRefcount = 0;
|
|
2026
|
-
}
|
|
2027
|
-
}
|
|
2028
|
-
};
|
|
2029
|
-
var RpcImportHook = class _RpcImportHook extends StubHook {
|
|
2030
|
-
// undefined when we're disposed
|
|
2031
|
-
// `pulling` is true if we already expect that this import is going to be resolved later, and
|
|
2032
|
-
// null if this import is not allowed to be pulled (i.e. it's a stub not a promise).
|
|
2033
|
-
constructor(isPromise, entry) {
|
|
2034
|
-
super();
|
|
2035
|
-
this.isPromise = isPromise;
|
|
2036
|
-
++entry.localRefcount;
|
|
2037
|
-
this.entry = entry;
|
|
2038
|
-
}
|
|
2039
|
-
entry;
|
|
2040
|
-
collectPath(path) {
|
|
2041
|
-
return this;
|
|
2042
|
-
}
|
|
2043
|
-
getEntry() {
|
|
2044
|
-
if (this.entry) {
|
|
2045
|
-
return this.entry;
|
|
2046
|
-
} else {
|
|
2047
|
-
throw new Error("This RpcImportHook was already disposed.");
|
|
2048
|
-
}
|
|
2049
|
-
}
|
|
2050
|
-
// -------------------------------------------------------------------------------------
|
|
2051
|
-
// implements StubHook
|
|
2052
|
-
call(path, args) {
|
|
2053
|
-
let entry = this.getEntry();
|
|
2054
|
-
if (entry.resolution) {
|
|
2055
|
-
return entry.resolution.call(path, args);
|
|
2056
|
-
} else {
|
|
2057
|
-
return entry.session.sendCall(entry.importId, path, args);
|
|
2058
|
-
}
|
|
2059
|
-
}
|
|
2060
|
-
map(path, captures, instructions) {
|
|
2061
|
-
let entry;
|
|
2062
|
-
try {
|
|
2063
|
-
entry = this.getEntry();
|
|
2064
|
-
} catch (err) {
|
|
2065
|
-
for (let cap of captures) {
|
|
2066
|
-
cap.dispose();
|
|
2067
|
-
}
|
|
2068
|
-
throw err;
|
|
2069
|
-
}
|
|
2070
|
-
if (entry.resolution) {
|
|
2071
|
-
return entry.resolution.map(path, captures, instructions);
|
|
2072
|
-
} else {
|
|
2073
|
-
return entry.session.sendMap(entry.importId, path, captures, instructions);
|
|
2074
|
-
}
|
|
2075
|
-
}
|
|
2076
|
-
get(path) {
|
|
2077
|
-
let entry = this.getEntry();
|
|
2078
|
-
if (entry.resolution) {
|
|
2079
|
-
return entry.resolution.get(path);
|
|
2080
|
-
} else {
|
|
2081
|
-
return entry.session.sendCall(entry.importId, path);
|
|
2082
|
-
}
|
|
2083
|
-
}
|
|
2084
|
-
dup() {
|
|
2085
|
-
return new _RpcImportHook(false, this.getEntry());
|
|
2086
|
-
}
|
|
2087
|
-
pull() {
|
|
2088
|
-
let entry = this.getEntry();
|
|
2089
|
-
if (!this.isPromise) {
|
|
2090
|
-
throw new Error("Can't pull this hook because it's not a promise hook.");
|
|
2091
|
-
}
|
|
2092
|
-
if (entry.resolution) {
|
|
2093
|
-
return entry.resolution.pull();
|
|
2094
|
-
}
|
|
2095
|
-
return entry.awaitResolution();
|
|
2096
|
-
}
|
|
2097
|
-
ignoreUnhandledRejections() {
|
|
2098
|
-
}
|
|
2099
|
-
dispose() {
|
|
2100
|
-
let entry = this.entry;
|
|
2101
|
-
this.entry = void 0;
|
|
2102
|
-
if (entry) {
|
|
2103
|
-
if (--entry.localRefcount === 0) {
|
|
2104
|
-
entry.dispose();
|
|
2105
|
-
}
|
|
2106
|
-
}
|
|
2107
|
-
}
|
|
2108
|
-
onBroken(callback) {
|
|
2109
|
-
if (this.entry) {
|
|
2110
|
-
this.entry.onBroken(callback);
|
|
2111
|
-
}
|
|
2112
|
-
}
|
|
2113
|
-
};
|
|
2114
|
-
var RpcMainHook = class extends RpcImportHook {
|
|
2115
|
-
session;
|
|
2116
|
-
constructor(entry) {
|
|
2117
|
-
super(false, entry);
|
|
2118
|
-
this.session = entry.session;
|
|
2119
|
-
}
|
|
2120
|
-
dispose() {
|
|
2121
|
-
if (this.session) {
|
|
2122
|
-
let session = this.session;
|
|
2123
|
-
this.session = void 0;
|
|
2124
|
-
session.shutdown();
|
|
2125
|
-
}
|
|
2126
|
-
}
|
|
2127
|
-
};
|
|
2128
|
-
var RpcSessionImpl = class {
|
|
2129
|
-
constructor(transport, mainHook, options) {
|
|
2130
|
-
this.transport = transport;
|
|
2131
|
-
this.options = options;
|
|
2132
|
-
this.exports.push({ hook: mainHook, refcount: 1 });
|
|
2133
|
-
this.imports.push(new ImportTableEntry(this, 0, false));
|
|
2134
|
-
let rejectFunc;
|
|
2135
|
-
let abortPromise = new Promise((resolve, reject) => {
|
|
2136
|
-
rejectFunc = reject;
|
|
2137
|
-
});
|
|
2138
|
-
this.cancelReadLoop = rejectFunc;
|
|
2139
|
-
this.readLoop(abortPromise).catch((err) => this.abort(err));
|
|
2140
|
-
}
|
|
2141
|
-
exports = [];
|
|
2142
|
-
reverseExports = /* @__PURE__ */ new Map();
|
|
2143
|
-
imports = [];
|
|
2144
|
-
abortReason;
|
|
2145
|
-
cancelReadLoop;
|
|
2146
|
-
// We assign positive numbers to imports we initiate, and negative numbers to exports we
|
|
2147
|
-
// initiate. So the next import ID is just `imports.length`, but the next export ID needs
|
|
2148
|
-
// to be tracked explicitly.
|
|
2149
|
-
nextExportId = -1;
|
|
2150
|
-
// If set, call this when all incoming calls are complete.
|
|
2151
|
-
onBatchDone;
|
|
2152
|
-
// How many promises is our peer expecting us to resolve?
|
|
2153
|
-
pullCount = 0;
|
|
2154
|
-
// Sparse array of onBrokenCallback registrations. Items are strictly appended to the end but
|
|
2155
|
-
// may be deleted from the middle (hence leaving the array sparse).
|
|
2156
|
-
onBrokenCallbacks = [];
|
|
2157
|
-
// Should only be called once immediately after construction.
|
|
2158
|
-
getMainImport() {
|
|
2159
|
-
return new RpcMainHook(this.imports[0]);
|
|
2160
|
-
}
|
|
2161
|
-
shutdown() {
|
|
2162
|
-
this.abort(new Error("RPC session was shut down by disposing the main stub"), false);
|
|
2163
|
-
}
|
|
2164
|
-
exportStub(hook) {
|
|
2165
|
-
if (this.abortReason) throw this.abortReason;
|
|
2166
|
-
let existingExportId = this.reverseExports.get(hook);
|
|
2167
|
-
if (existingExportId !== void 0) {
|
|
2168
|
-
++this.exports[existingExportId].refcount;
|
|
2169
|
-
return existingExportId;
|
|
2170
|
-
} else {
|
|
2171
|
-
let exportId = this.nextExportId--;
|
|
2172
|
-
this.exports[exportId] = { hook, refcount: 1 };
|
|
2173
|
-
this.reverseExports.set(hook, exportId);
|
|
2174
|
-
return exportId;
|
|
2175
|
-
}
|
|
2176
|
-
}
|
|
2177
|
-
exportPromise(hook) {
|
|
2178
|
-
if (this.abortReason) throw this.abortReason;
|
|
2179
|
-
let exportId = this.nextExportId--;
|
|
2180
|
-
this.exports[exportId] = { hook, refcount: 1 };
|
|
2181
|
-
this.reverseExports.set(hook, exportId);
|
|
2182
|
-
this.ensureResolvingExport(exportId);
|
|
2183
|
-
return exportId;
|
|
2184
|
-
}
|
|
2185
|
-
unexport(ids) {
|
|
2186
|
-
for (let id of ids) {
|
|
2187
|
-
this.releaseExport(id, 1);
|
|
2188
|
-
}
|
|
2189
|
-
}
|
|
2190
|
-
releaseExport(exportId, refcount) {
|
|
2191
|
-
let entry = this.exports[exportId];
|
|
2192
|
-
if (!entry) {
|
|
2193
|
-
throw new Error(`no such export ID: ${exportId}`);
|
|
2194
|
-
}
|
|
2195
|
-
if (entry.refcount < refcount) {
|
|
2196
|
-
throw new Error(`refcount would go negative: ${entry.refcount} < ${refcount}`);
|
|
2197
|
-
}
|
|
2198
|
-
entry.refcount -= refcount;
|
|
2199
|
-
if (entry.refcount === 0) {
|
|
2200
|
-
delete this.exports[exportId];
|
|
2201
|
-
this.reverseExports.delete(entry.hook);
|
|
2202
|
-
entry.hook.dispose();
|
|
2203
|
-
}
|
|
2204
|
-
}
|
|
2205
|
-
onSendError(error) {
|
|
2206
|
-
if (this.options.onSendError) {
|
|
2207
|
-
return this.options.onSendError(error);
|
|
2208
|
-
}
|
|
2209
|
-
}
|
|
2210
|
-
ensureResolvingExport(exportId) {
|
|
2211
|
-
let exp = this.exports[exportId];
|
|
2212
|
-
if (!exp) {
|
|
2213
|
-
throw new Error(`no such export ID: ${exportId}`);
|
|
2214
|
-
}
|
|
2215
|
-
if (!exp.pull) {
|
|
2216
|
-
let resolve = async () => {
|
|
2217
|
-
let hook = exp.hook;
|
|
2218
|
-
for (; ; ) {
|
|
2219
|
-
let payload = await hook.pull();
|
|
2220
|
-
if (payload.value instanceof RpcStub) {
|
|
2221
|
-
let { hook: inner, pathIfPromise } = unwrapStubAndPath(payload.value);
|
|
2222
|
-
if (pathIfPromise && pathIfPromise.length == 0) {
|
|
2223
|
-
if (this.getImport(hook) === void 0) {
|
|
2224
|
-
hook = inner;
|
|
2225
|
-
continue;
|
|
2226
|
-
}
|
|
2227
|
-
}
|
|
2228
|
-
}
|
|
2229
|
-
return payload;
|
|
2230
|
-
}
|
|
2231
|
-
};
|
|
2232
|
-
++this.pullCount;
|
|
2233
|
-
exp.pull = resolve().then(
|
|
2234
|
-
(payload) => {
|
|
2235
|
-
let value = Devaluator.devaluate(payload.value, void 0, this, payload);
|
|
2236
|
-
this.send(["resolve", exportId, value]);
|
|
2237
|
-
},
|
|
2238
|
-
(error) => {
|
|
2239
|
-
this.send(["reject", exportId, Devaluator.devaluate(error, void 0, this)]);
|
|
2240
|
-
}
|
|
2241
|
-
).catch(
|
|
2242
|
-
(error) => {
|
|
2243
|
-
try {
|
|
2244
|
-
this.send(["reject", exportId, Devaluator.devaluate(error, void 0, this)]);
|
|
2245
|
-
} catch (error2) {
|
|
2246
|
-
this.abort(error2);
|
|
2247
|
-
}
|
|
2248
|
-
}
|
|
2249
|
-
).finally(() => {
|
|
2250
|
-
if (--this.pullCount === 0) {
|
|
2251
|
-
if (this.onBatchDone) {
|
|
2252
|
-
this.onBatchDone.resolve();
|
|
2253
|
-
}
|
|
2254
|
-
}
|
|
2255
|
-
});
|
|
2256
|
-
}
|
|
2257
|
-
}
|
|
2258
|
-
getImport(hook) {
|
|
2259
|
-
if (hook instanceof RpcImportHook && hook.entry && hook.entry.session === this) {
|
|
2260
|
-
return hook.entry.importId;
|
|
2261
|
-
} else {
|
|
2262
|
-
return void 0;
|
|
2263
|
-
}
|
|
2264
|
-
}
|
|
2265
|
-
importStub(idx) {
|
|
2266
|
-
if (this.abortReason) throw this.abortReason;
|
|
2267
|
-
let entry = this.imports[idx];
|
|
2268
|
-
if (!entry) {
|
|
2269
|
-
entry = new ImportTableEntry(this, idx, false);
|
|
2270
|
-
this.imports[idx] = entry;
|
|
2271
|
-
}
|
|
2272
|
-
return new RpcImportHook(
|
|
2273
|
-
/*isPromise=*/
|
|
2274
|
-
false,
|
|
2275
|
-
entry
|
|
2276
|
-
);
|
|
2277
|
-
}
|
|
2278
|
-
importPromise(idx) {
|
|
2279
|
-
if (this.abortReason) throw this.abortReason;
|
|
2280
|
-
if (this.imports[idx]) {
|
|
2281
|
-
return new ErrorStubHook(new Error(
|
|
2282
|
-
"Bug in RPC system: The peer sent a promise reusing an existing export ID."
|
|
2283
|
-
));
|
|
2284
|
-
}
|
|
2285
|
-
let entry = new ImportTableEntry(this, idx, true);
|
|
2286
|
-
this.imports[idx] = entry;
|
|
2287
|
-
return new RpcImportHook(
|
|
2288
|
-
/*isPromise=*/
|
|
2289
|
-
true,
|
|
2290
|
-
entry
|
|
2291
|
-
);
|
|
2292
|
-
}
|
|
2293
|
-
getExport(idx) {
|
|
2294
|
-
return this.exports[idx]?.hook;
|
|
2295
|
-
}
|
|
2296
|
-
send(msg) {
|
|
2297
|
-
if (this.abortReason !== void 0) {
|
|
2298
|
-
return;
|
|
2299
|
-
}
|
|
2300
|
-
let msgText;
|
|
2301
|
-
try {
|
|
2302
|
-
msgText = JSON.stringify(msg);
|
|
2303
|
-
} catch (err) {
|
|
2304
|
-
try {
|
|
2305
|
-
this.abort(err);
|
|
2306
|
-
} catch (err2) {
|
|
2307
|
-
}
|
|
2308
|
-
throw err;
|
|
2309
|
-
}
|
|
2310
|
-
this.transport.send(msgText).catch((err) => this.abort(err, false));
|
|
2311
|
-
}
|
|
2312
|
-
sendCall(id, path, args) {
|
|
2313
|
-
if (this.abortReason) throw this.abortReason;
|
|
2314
|
-
let value = ["pipeline", id, path];
|
|
2315
|
-
if (args) {
|
|
2316
|
-
let devalue = Devaluator.devaluate(args.value, void 0, this, args);
|
|
2317
|
-
value.push(devalue[0]);
|
|
2318
|
-
}
|
|
2319
|
-
this.send(["push", value]);
|
|
2320
|
-
let entry = new ImportTableEntry(this, this.imports.length, false);
|
|
2321
|
-
this.imports.push(entry);
|
|
2322
|
-
return new RpcImportHook(
|
|
2323
|
-
/*isPromise=*/
|
|
2324
|
-
true,
|
|
2325
|
-
entry
|
|
2326
|
-
);
|
|
2327
|
-
}
|
|
2328
|
-
sendMap(id, path, captures, instructions) {
|
|
2329
|
-
if (this.abortReason) {
|
|
2330
|
-
for (let cap of captures) {
|
|
2331
|
-
cap.dispose();
|
|
2332
|
-
}
|
|
2333
|
-
throw this.abortReason;
|
|
2334
|
-
}
|
|
2335
|
-
let devaluedCaptures = captures.map((hook) => {
|
|
2336
|
-
let importId = this.getImport(hook);
|
|
2337
|
-
if (importId !== void 0) {
|
|
2338
|
-
return ["import", importId];
|
|
2339
|
-
} else {
|
|
2340
|
-
return ["export", this.exportStub(hook)];
|
|
2341
|
-
}
|
|
2342
|
-
});
|
|
2343
|
-
let value = ["remap", id, path, devaluedCaptures, instructions];
|
|
2344
|
-
this.send(["push", value]);
|
|
2345
|
-
let entry = new ImportTableEntry(this, this.imports.length, false);
|
|
2346
|
-
this.imports.push(entry);
|
|
2347
|
-
return new RpcImportHook(
|
|
2348
|
-
/*isPromise=*/
|
|
2349
|
-
true,
|
|
2350
|
-
entry
|
|
2351
|
-
);
|
|
2352
|
-
}
|
|
2353
|
-
sendPull(id) {
|
|
2354
|
-
if (this.abortReason) throw this.abortReason;
|
|
2355
|
-
this.send(["pull", id]);
|
|
2356
|
-
}
|
|
2357
|
-
sendRelease(id, remoteRefcount) {
|
|
2358
|
-
if (this.abortReason) return;
|
|
2359
|
-
this.send(["release", id, remoteRefcount]);
|
|
2360
|
-
delete this.imports[id];
|
|
2361
|
-
}
|
|
2362
|
-
abort(error, trySendAbortMessage = true) {
|
|
2363
|
-
if (this.abortReason !== void 0) return;
|
|
2364
|
-
this.cancelReadLoop(error);
|
|
2365
|
-
if (trySendAbortMessage) {
|
|
2366
|
-
try {
|
|
2367
|
-
this.transport.send(JSON.stringify(["abort", Devaluator.devaluate(error, void 0, this)])).catch((err) => {
|
|
2368
|
-
});
|
|
2369
|
-
} catch (err) {
|
|
2370
|
-
}
|
|
2371
|
-
}
|
|
2372
|
-
if (error === void 0) {
|
|
2373
|
-
error = "undefined";
|
|
2374
|
-
}
|
|
2375
|
-
this.abortReason = error;
|
|
2376
|
-
if (this.onBatchDone) {
|
|
2377
|
-
this.onBatchDone.reject(error);
|
|
2378
|
-
}
|
|
2379
|
-
if (this.transport.abort) {
|
|
2380
|
-
try {
|
|
2381
|
-
this.transport.abort(error);
|
|
2382
|
-
} catch (err) {
|
|
2383
|
-
Promise.resolve(err);
|
|
2384
|
-
}
|
|
2385
|
-
}
|
|
2386
|
-
for (let i in this.onBrokenCallbacks) {
|
|
2387
|
-
try {
|
|
2388
|
-
this.onBrokenCallbacks[i](error);
|
|
2389
|
-
} catch (err) {
|
|
2390
|
-
Promise.resolve(err);
|
|
2391
|
-
}
|
|
2392
|
-
}
|
|
2393
|
-
for (let i in this.imports) {
|
|
2394
|
-
this.imports[i].abort(error);
|
|
2395
|
-
}
|
|
2396
|
-
for (let i in this.exports) {
|
|
2397
|
-
this.exports[i].hook.dispose();
|
|
2398
|
-
}
|
|
2399
|
-
}
|
|
2400
|
-
async readLoop(abortPromise) {
|
|
2401
|
-
while (!this.abortReason) {
|
|
2402
|
-
let msg = JSON.parse(await Promise.race([this.transport.receive(), abortPromise]));
|
|
2403
|
-
if (this.abortReason) break;
|
|
2404
|
-
if (msg instanceof Array) {
|
|
2405
|
-
switch (msg[0]) {
|
|
2406
|
-
case "push":
|
|
2407
|
-
if (msg.length > 1) {
|
|
2408
|
-
let payload = new Evaluator(this).evaluate(msg[1]);
|
|
2409
|
-
let hook = new PayloadStubHook(payload);
|
|
2410
|
-
hook.ignoreUnhandledRejections();
|
|
2411
|
-
this.exports.push({ hook, refcount: 1 });
|
|
2412
|
-
continue;
|
|
2413
|
-
}
|
|
2414
|
-
break;
|
|
2415
|
-
case "pull": {
|
|
2416
|
-
let exportId = msg[1];
|
|
2417
|
-
if (typeof exportId == "number") {
|
|
2418
|
-
this.ensureResolvingExport(exportId);
|
|
2419
|
-
continue;
|
|
2420
|
-
}
|
|
2421
|
-
break;
|
|
2422
|
-
}
|
|
2423
|
-
case "resolve":
|
|
2424
|
-
// ["resolve", ExportId, Expression]
|
|
2425
|
-
case "reject": {
|
|
2426
|
-
let importId = msg[1];
|
|
2427
|
-
if (typeof importId == "number" && msg.length > 2) {
|
|
2428
|
-
let imp = this.imports[importId];
|
|
2429
|
-
if (imp) {
|
|
2430
|
-
if (msg[0] == "resolve") {
|
|
2431
|
-
imp.resolve(new PayloadStubHook(new Evaluator(this).evaluate(msg[2])));
|
|
2432
|
-
} else {
|
|
2433
|
-
let payload = new Evaluator(this).evaluate(msg[2]);
|
|
2434
|
-
payload.dispose();
|
|
2435
|
-
imp.resolve(new ErrorStubHook(payload.value));
|
|
2436
|
-
}
|
|
2437
|
-
} else {
|
|
2438
|
-
if (msg[0] == "resolve") {
|
|
2439
|
-
new Evaluator(this).evaluate(msg[2]).dispose();
|
|
2440
|
-
}
|
|
2441
|
-
}
|
|
2442
|
-
continue;
|
|
2443
|
-
}
|
|
2444
|
-
break;
|
|
2445
|
-
}
|
|
2446
|
-
case "release": {
|
|
2447
|
-
let exportId = msg[1];
|
|
2448
|
-
let refcount = msg[2];
|
|
2449
|
-
if (typeof exportId == "number" && typeof refcount == "number") {
|
|
2450
|
-
this.releaseExport(exportId, refcount);
|
|
2451
|
-
continue;
|
|
2452
|
-
}
|
|
2453
|
-
break;
|
|
2454
|
-
}
|
|
2455
|
-
case "abort": {
|
|
2456
|
-
let payload = new Evaluator(this).evaluate(msg[1]);
|
|
2457
|
-
payload.dispose();
|
|
2458
|
-
this.abort(payload, false);
|
|
2459
|
-
break;
|
|
2460
|
-
}
|
|
2461
|
-
}
|
|
2462
|
-
}
|
|
2463
|
-
throw new Error(`bad RPC message: ${JSON.stringify(msg)}`);
|
|
2464
|
-
}
|
|
2465
|
-
}
|
|
2466
|
-
async drain() {
|
|
2467
|
-
if (this.abortReason) {
|
|
2468
|
-
throw this.abortReason;
|
|
2469
|
-
}
|
|
2470
|
-
if (this.pullCount > 0) {
|
|
2471
|
-
let { promise, resolve, reject } = Promise.withResolvers();
|
|
2472
|
-
this.onBatchDone = { resolve, reject };
|
|
2473
|
-
await promise;
|
|
2474
|
-
}
|
|
2475
|
-
}
|
|
2476
|
-
getStats() {
|
|
2477
|
-
let result = { imports: 0, exports: 0 };
|
|
2478
|
-
for (let i in this.imports) {
|
|
2479
|
-
++result.imports;
|
|
2480
|
-
}
|
|
2481
|
-
for (let i in this.exports) {
|
|
2482
|
-
++result.exports;
|
|
2483
|
-
}
|
|
2484
|
-
return result;
|
|
2485
|
-
}
|
|
2486
|
-
};
|
|
2487
|
-
var RpcSession = class {
|
|
2488
|
-
#session;
|
|
2489
|
-
#mainStub;
|
|
2490
|
-
constructor(transport, localMain, options = {}) {
|
|
2491
|
-
let mainHook;
|
|
2492
|
-
if (localMain) {
|
|
2493
|
-
mainHook = new PayloadStubHook(RpcPayload.fromAppReturn(localMain));
|
|
2494
|
-
} else {
|
|
2495
|
-
mainHook = new ErrorStubHook(new Error("This connection has no main object."));
|
|
2496
|
-
}
|
|
2497
|
-
this.#session = new RpcSessionImpl(transport, mainHook, options);
|
|
2498
|
-
this.#mainStub = new RpcStub(this.#session.getMainImport());
|
|
2499
|
-
}
|
|
2500
|
-
getRemoteMain() {
|
|
2501
|
-
return this.#mainStub;
|
|
2502
|
-
}
|
|
2503
|
-
getStats() {
|
|
2504
|
-
return this.#session.getStats();
|
|
2505
|
-
}
|
|
2506
|
-
drain() {
|
|
2507
|
-
return this.#session.drain();
|
|
2508
|
-
}
|
|
2509
|
-
};
|
|
2510
|
-
function newWebSocketRpcSession(webSocket, localMain, options) {
|
|
2511
|
-
if (typeof webSocket === "string") {
|
|
2512
|
-
webSocket = new WebSocket(webSocket);
|
|
2513
|
-
}
|
|
2514
|
-
let transport = new WebSocketTransport(webSocket);
|
|
2515
|
-
let rpc = new RpcSession(transport, localMain, options);
|
|
2516
|
-
return rpc.getRemoteMain();
|
|
2517
|
-
}
|
|
2518
|
-
function newWorkersWebSocketRpcResponse(request, localMain, options) {
|
|
2519
|
-
if (request.headers.get("Upgrade")?.toLowerCase() !== "websocket") {
|
|
2520
|
-
return new Response("This endpoint only accepts WebSocket requests.", { status: 400 });
|
|
2521
|
-
}
|
|
2522
|
-
let pair = new WebSocketPair();
|
|
2523
|
-
let server = pair[0];
|
|
2524
|
-
server.accept();
|
|
2525
|
-
newWebSocketRpcSession(server, localMain, options);
|
|
2526
|
-
return new Response(null, {
|
|
2527
|
-
status: 101,
|
|
2528
|
-
webSocket: pair[1]
|
|
2529
|
-
});
|
|
2530
|
-
}
|
|
2531
|
-
var WebSocketTransport = class {
|
|
2532
|
-
constructor(webSocket) {
|
|
2533
|
-
this.#webSocket = webSocket;
|
|
2534
|
-
if (webSocket.readyState === WebSocket.CONNECTING) {
|
|
2535
|
-
this.#sendQueue = [];
|
|
2536
|
-
webSocket.addEventListener("open", (event) => {
|
|
2537
|
-
try {
|
|
2538
|
-
for (let message of this.#sendQueue) {
|
|
2539
|
-
webSocket.send(message);
|
|
2540
|
-
}
|
|
2541
|
-
} catch (err) {
|
|
2542
|
-
this.#receivedError(err);
|
|
2543
|
-
}
|
|
2544
|
-
this.#sendQueue = void 0;
|
|
2545
|
-
});
|
|
2546
|
-
}
|
|
2547
|
-
webSocket.addEventListener("message", (event) => {
|
|
2548
|
-
if (this.#error) ;
|
|
2549
|
-
else if (typeof event.data === "string") {
|
|
2550
|
-
if (this.#receiveResolver) {
|
|
2551
|
-
this.#receiveResolver(event.data);
|
|
2552
|
-
this.#receiveResolver = void 0;
|
|
2553
|
-
this.#receiveRejecter = void 0;
|
|
2554
|
-
} else {
|
|
2555
|
-
this.#receiveQueue.push(event.data);
|
|
2556
|
-
}
|
|
2557
|
-
} else {
|
|
2558
|
-
this.#receivedError(new TypeError("Received non-string message from WebSocket."));
|
|
2559
|
-
}
|
|
2560
|
-
});
|
|
2561
|
-
webSocket.addEventListener("close", (event) => {
|
|
2562
|
-
this.#receivedError(new Error(`Peer closed WebSocket: ${event.code} ${event.reason}`));
|
|
2563
|
-
});
|
|
2564
|
-
webSocket.addEventListener("error", (event) => {
|
|
2565
|
-
this.#receivedError(new Error(`WebSocket connection failed.`));
|
|
2566
|
-
});
|
|
2567
|
-
}
|
|
2568
|
-
#webSocket;
|
|
2569
|
-
#sendQueue;
|
|
2570
|
-
// only if not opened yet
|
|
2571
|
-
#receiveResolver;
|
|
2572
|
-
#receiveRejecter;
|
|
2573
|
-
#receiveQueue = [];
|
|
2574
|
-
#error;
|
|
2575
|
-
async send(message) {
|
|
2576
|
-
if (this.#sendQueue === void 0) {
|
|
2577
|
-
this.#webSocket.send(message);
|
|
2578
|
-
} else {
|
|
2579
|
-
this.#sendQueue.push(message);
|
|
2580
|
-
}
|
|
2581
|
-
}
|
|
2582
|
-
async receive() {
|
|
2583
|
-
if (this.#receiveQueue.length > 0) {
|
|
2584
|
-
return this.#receiveQueue.shift();
|
|
2585
|
-
} else if (this.#error) {
|
|
2586
|
-
throw this.#error;
|
|
2587
|
-
} else {
|
|
2588
|
-
return new Promise((resolve, reject) => {
|
|
2589
|
-
this.#receiveResolver = resolve;
|
|
2590
|
-
this.#receiveRejecter = reject;
|
|
2591
|
-
});
|
|
2592
|
-
}
|
|
2593
|
-
}
|
|
2594
|
-
abort(reason) {
|
|
2595
|
-
let message;
|
|
2596
|
-
if (reason instanceof Error) {
|
|
2597
|
-
message = reason.message;
|
|
2598
|
-
} else {
|
|
2599
|
-
message = `${reason}`;
|
|
2600
|
-
}
|
|
2601
|
-
this.#webSocket.close(3e3, message);
|
|
2602
|
-
if (!this.#error) {
|
|
2603
|
-
this.#error = reason;
|
|
2604
|
-
}
|
|
2605
|
-
}
|
|
2606
|
-
#receivedError(reason) {
|
|
2607
|
-
if (!this.#error) {
|
|
2608
|
-
this.#error = reason;
|
|
2609
|
-
if (this.#receiveRejecter) {
|
|
2610
|
-
this.#receiveRejecter(reason);
|
|
2611
|
-
this.#receiveResolver = void 0;
|
|
2612
|
-
this.#receiveRejecter = void 0;
|
|
2613
|
-
}
|
|
2614
|
-
}
|
|
2615
|
-
}
|
|
2616
|
-
};
|
|
2617
|
-
var BatchServerTransport = class {
|
|
2618
|
-
constructor(batch) {
|
|
2619
|
-
this.#batchToReceive = batch;
|
|
2620
|
-
}
|
|
2621
|
-
#batchToSend = [];
|
|
2622
|
-
#batchToReceive;
|
|
2623
|
-
#allReceived = Promise.withResolvers();
|
|
2624
|
-
async send(message) {
|
|
2625
|
-
this.#batchToSend.push(message);
|
|
2626
|
-
}
|
|
2627
|
-
async receive() {
|
|
2628
|
-
let msg = this.#batchToReceive.shift();
|
|
2629
|
-
if (msg !== void 0) {
|
|
2630
|
-
return msg;
|
|
2631
|
-
} else {
|
|
2632
|
-
this.#allReceived.resolve();
|
|
2633
|
-
return new Promise((r) => {
|
|
1
|
+
import { spawn } from "node:child_process";
|
|
2
|
+
import { mkdtemp, writeFile, rm } from "node:fs/promises";
|
|
3
|
+
import { tmpdir } from "node:os";
|
|
4
|
+
import { join } from "node:path";
|
|
5
|
+
import { Writable, Readable } from "node:stream";
|
|
6
|
+
import { RpcTarget, RpcSession } from "capnweb";
|
|
7
|
+
import { z } from "zod";
|
|
8
|
+
import { asSchema } from "ai";
|
|
9
|
+
import camelCase from "camelcase";
|
|
10
|
+
import { validate } from "json-schema";
|
|
11
|
+
import { compile } from "json-schema-to-typescript";
|
|
12
|
+
import invariant from "tiny-invariant";
|
|
13
|
+
import { zodToJsonSchema } from "zod-to-json-schema";
|
|
14
|
+
import { R as RpcToolset } from "./rpc-toolset-BnC2BXPq.js";
|
|
15
|
+
import { t } from "./rpc-toolset-BnC2BXPq.js";
|
|
16
|
+
function createDenoSandbox(options = {}) {
|
|
17
|
+
const { args = [], denoPath = "deno" } = options;
|
|
18
|
+
return {
|
|
19
|
+
kind: "direct",
|
|
20
|
+
safeEval: async (code) => {
|
|
21
|
+
const tempDir = await mkdtemp(join(tmpdir(), "exoagent-deno-"));
|
|
22
|
+
const tempFile = join(tempDir, "code.ts");
|
|
23
|
+
await writeFile(tempFile, code, "utf-8");
|
|
24
|
+
const child = spawn(denoPath, ["run", ...args, tempFile], {
|
|
25
|
+
stdio: ["pipe", "pipe", "inherit"]
|
|
2634
26
|
});
|
|
2635
|
-
|
|
2636
|
-
|
|
2637
|
-
|
|
2638
|
-
|
|
2639
|
-
|
|
2640
|
-
|
|
2641
|
-
|
|
2642
|
-
|
|
2643
|
-
|
|
2644
|
-
|
|
2645
|
-
|
|
2646
|
-
};
|
|
2647
|
-
|
|
2648
|
-
|
|
2649
|
-
|
|
2650
|
-
|
|
2651
|
-
|
|
2652
|
-
|
|
2653
|
-
|
|
2654
|
-
|
|
2655
|
-
|
|
2656
|
-
|
|
2657
|
-
|
|
2658
|
-
}
|
|
2659
|
-
var RpcSession2 = RpcSession;
|
|
2660
|
-
var RpcTarget4 = RpcTarget;
|
|
2661
|
-
var newWebSocketRpcSession2 = newWebSocketRpcSession;
|
|
2662
|
-
async function newWorkersRpcResponse(request, localMain) {
|
|
2663
|
-
if (request.method === "POST") {
|
|
2664
|
-
let response = await newHttpBatchRpcResponse(request, localMain);
|
|
2665
|
-
response.headers.set("Access-Control-Allow-Origin", "*");
|
|
2666
|
-
return response;
|
|
2667
|
-
} else if (request.headers.get("Upgrade")?.toLowerCase() === "websocket") {
|
|
2668
|
-
return newWorkersWebSocketRpcResponse(request, localMain);
|
|
2669
|
-
} else {
|
|
2670
|
-
return new Response("This endpoint only accepts POST or WebSocket requests.", { status: 400 });
|
|
2671
|
-
}
|
|
27
|
+
return {
|
|
28
|
+
input: Readable.toWeb(child.stdout),
|
|
29
|
+
output: Writable.toWeb(child.stdin),
|
|
30
|
+
wait: () => new Promise((resolve, reject) => {
|
|
31
|
+
child.on("exit", async (code2) => {
|
|
32
|
+
await rm(tempDir, { recursive: true, force: true }).catch(() => {
|
|
33
|
+
});
|
|
34
|
+
code2 === 0 ? resolve() : reject(new Error(`Deno process exited with code ${code2}`));
|
|
35
|
+
});
|
|
36
|
+
child.on("error", async (err) => {
|
|
37
|
+
await rm(tempDir, { recursive: true, force: true }).catch(() => {
|
|
38
|
+
});
|
|
39
|
+
reject(err);
|
|
40
|
+
});
|
|
41
|
+
})
|
|
42
|
+
};
|
|
43
|
+
},
|
|
44
|
+
sandboxContext: `Promise.resolve({
|
|
45
|
+
input: Deno.stdin.readable,
|
|
46
|
+
output: Deno.stdout.writable,
|
|
47
|
+
onSuccess: () => Deno.exit(0),
|
|
48
|
+
onFailure: () => Deno.exit(1)
|
|
49
|
+
})`
|
|
50
|
+
};
|
|
2672
51
|
}
|
|
2673
|
-
|
|
2674
|
-
// src/code-mode.ts
|
|
2675
|
-
import { z } from "zod";
|
|
2676
|
-
|
|
2677
|
-
// src/stream-transport.ts
|
|
52
|
+
const runtimeCode = '// packages/capnweb/dist/index.js\nvar WORKERS_MODULE_SYMBOL = /* @__PURE__ */ Symbol("workers-module");\nif (!Symbol.dispose) {\n Symbol.dispose = /* @__PURE__ */ Symbol.for("dispose");\n}\nif (!Symbol.asyncDispose) {\n Symbol.asyncDispose = /* @__PURE__ */ Symbol.for("asyncDispose");\n}\nif (!Promise.withResolvers) {\n Promise.withResolvers = function() {\n let resolve;\n let reject;\n const promise = new Promise((res, rej) => {\n resolve = res;\n reject = rej;\n });\n return { promise, resolve, reject };\n };\n}\nvar workersModule = globalThis[WORKERS_MODULE_SYMBOL];\nvar RpcTarget = workersModule ? workersModule.RpcTarget : class {\n};\nvar AsyncFunction = (async function() {\n}).constructor;\nvar getGlobalRpcSessionOptions = () => ({});\nvar setGlobalRpcSessionOptions = (options) => {\n getGlobalRpcSessionOptions = options;\n};\nvar CALLBACK_CLEANUP = /* @__PURE__ */ Symbol("callback-cleanup");\nfunction typeForRpc(value) {\n switch (typeof value) {\n case "boolean":\n case "number":\n case "string":\n return "primitive";\n case "undefined":\n return "undefined";\n case "object":\n case "function":\n break;\n case "bigint":\n return "bigint";\n default:\n return "unsupported";\n }\n if (value === null) {\n return "primitive";\n }\n let prototype = Object.getPrototypeOf(value);\n switch (prototype) {\n case Object.prototype:\n return "object";\n case Function.prototype:\n case AsyncFunction.prototype:\n return "function";\n case Array.prototype:\n return "array";\n case Date.prototype:\n return "date";\n case Uint8Array.prototype:\n return "bytes";\n // TODO: All other structured clone types.\n case RpcStub.prototype:\n return "stub";\n case RpcPromise.prototype:\n return "rpc-promise";\n // TODO: Promise<T> or thenable\n default:\n if (workersModule) {\n if (prototype == workersModule.RpcStub.prototype || value instanceof workersModule.ServiceStub) {\n return "rpc-target";\n } else if (prototype == workersModule.RpcPromise.prototype || prototype == workersModule.RpcProperty.prototype) {\n return "rpc-thenable";\n }\n }\n if (value instanceof RpcTarget) {\n return "rpc-target";\n }\n if (value instanceof Error) {\n return "error";\n }\n return "unsupported";\n }\n}\nfunction mapNotLoaded() {\n throw new Error("RPC map() implementation was not loaded.");\n}\nvar mapImpl = { applyMap: mapNotLoaded, sendMap: mapNotLoaded, recordCallback: mapNotLoaded };\nvar StubHook = class {\n};\nvar ErrorStubHook = class extends StubHook {\n constructor(error) {\n super();\n this.error = error;\n }\n call(path, args) {\n return this;\n }\n map(path, captures, instructions) {\n return this;\n }\n get(path) {\n return this;\n }\n dup() {\n return this;\n }\n pull() {\n return Promise.reject(this.error);\n }\n ignoreUnhandledRejections() {\n }\n dispose() {\n }\n onBroken(callback) {\n try {\n callback(this.error);\n } catch (err) {\n Promise.resolve(err);\n }\n }\n};\nvar DISPOSED_HOOK = new ErrorStubHook(\n new Error("Attempted to use RPC stub after it has been disposed.")\n);\nvar doCall = (hook, path, params) => {\n return hook.call(path, params);\n};\nfunction withCallInterceptor(interceptor, callback) {\n let oldValue = doCall;\n doCall = interceptor;\n try {\n return callback();\n } finally {\n doCall = oldValue;\n }\n}\nvar RAW_STUB = /* @__PURE__ */ Symbol("realStub");\nvar PROXY_HANDLERS = {\n apply(target, thisArg, argumentsList) {\n let stub = target.raw;\n return new RpcPromise(doCall(\n stub.hook,\n stub.pathIfPromise || [],\n RpcPayload.fromAppParams(argumentsList)\n ), []);\n },\n get(target, prop, receiver) {\n let stub = target.raw;\n if (prop === RAW_STUB) {\n return stub;\n } else if (prop in RpcPromise.prototype) {\n return stub[prop];\n } else if (typeof prop === "string") {\n return new RpcPromise(\n stub.hook,\n stub.pathIfPromise ? [...stub.pathIfPromise, prop] : [prop]\n );\n } else if (prop === Symbol.dispose && (!stub.pathIfPromise || stub.pathIfPromise.length == 0)) {\n return () => {\n stub.hook.dispose();\n stub.hook = DISPOSED_HOOK;\n };\n } else {\n return void 0;\n }\n },\n has(target, prop) {\n let stub = target.raw;\n if (prop === RAW_STUB) {\n return true;\n } else if (prop in RpcPromise.prototype) {\n return prop in stub;\n } else if (typeof prop === "string") {\n return true;\n } else if (prop === Symbol.dispose && (!stub.pathIfPromise || stub.pathIfPromise.length == 0)) {\n return true;\n } else {\n return false;\n }\n },\n construct(target, args) {\n throw new Error("An RPC stub cannot be used as a constructor.");\n },\n defineProperty(target, property, attributes) {\n throw new Error("Can\'t define properties on RPC stubs.");\n },\n deleteProperty(target, p) {\n throw new Error("Can\'t delete properties on RPC stubs.");\n },\n getOwnPropertyDescriptor(target, p) {\n return void 0;\n },\n getPrototypeOf(target) {\n return Object.getPrototypeOf(target.raw);\n },\n isExtensible(target) {\n return false;\n },\n ownKeys(target) {\n return [];\n },\n preventExtensions(target) {\n return true;\n },\n set(target, p, newValue, receiver) {\n throw new Error("Can\'t assign properties on RPC stubs.");\n },\n setPrototypeOf(target, v) {\n throw new Error("Can\'t override prototype of RPC stubs.");\n }\n};\nvar RpcStub = class _RpcStub extends RpcTarget {\n // Although `hook` and `path` are declared `public` here, they are effectively hidden by the\n // proxy.\n constructor(hook, pathIfPromise) {\n super();\n if (!(hook instanceof StubHook)) {\n let value = hook;\n if (value instanceof RpcTarget || value instanceof Function) {\n hook = TargetStubHook.create(value, void 0);\n } else {\n hook = new PayloadStubHook(RpcPayload.fromAppReturn(value));\n }\n if (pathIfPromise) {\n throw new TypeError("RpcStub constructor expected one argument, received two.");\n }\n }\n this.hook = hook;\n this.pathIfPromise = pathIfPromise;\n let func = () => {\n };\n func.raw = this;\n return new Proxy(func, PROXY_HANDLERS);\n }\n hook;\n pathIfPromise;\n dup() {\n let target = this[RAW_STUB];\n if (target.pathIfPromise) {\n return new _RpcStub(target.hook.get(target.pathIfPromise));\n } else {\n return new _RpcStub(target.hook.dup());\n }\n }\n onRpcBroken(callback) {\n this[RAW_STUB].hook.onBroken(callback);\n }\n map(func) {\n let { hook, pathIfPromise } = this[RAW_STUB];\n return mapImpl.sendMap(hook, pathIfPromise || [], func);\n }\n toString() {\n return "[object RpcStub]";\n }\n};\nvar RpcPromise = class extends RpcStub {\n // TODO: Support passing target value or promise to constructor.\n constructor(hook, pathIfPromise) {\n super(hook, pathIfPromise);\n }\n then(onfulfilled, onrejected) {\n return pullPromise(this).then(...arguments);\n }\n catch(onrejected) {\n return pullPromise(this).catch(...arguments);\n }\n finally(onfinally) {\n return pullPromise(this).finally(...arguments);\n }\n toString() {\n return "[object RpcPromise]";\n }\n};\nfunction unwrapStubTakingOwnership(stub) {\n let { hook, pathIfPromise } = stub[RAW_STUB];\n if (pathIfPromise && pathIfPromise.length > 0) {\n return hook.get(pathIfPromise);\n } else {\n return hook;\n }\n}\nfunction unwrapStubAndDup(stub) {\n let { hook, pathIfPromise } = stub[RAW_STUB];\n if (pathIfPromise) {\n return hook.get(pathIfPromise);\n } else {\n return hook.dup();\n }\n}\nfunction unwrapStubNoProperties(stub) {\n let { hook, pathIfPromise } = stub[RAW_STUB];\n if (pathIfPromise && pathIfPromise.length > 0) {\n return void 0;\n }\n return hook;\n}\nfunction unwrapStubOrParent(stub) {\n return stub[RAW_STUB].hook;\n}\nfunction unwrapStubAndPath(stub) {\n return stub[RAW_STUB];\n}\nasync function pullPromise(promise) {\n let { hook, pathIfPromise } = promise[RAW_STUB];\n if (pathIfPromise.length > 0) {\n hook = hook.get(pathIfPromise);\n }\n let payload = await hook.pull();\n return payload.deliverResolve();\n}\nvar RpcPayload = class _RpcPayload {\n // Private constructor; use factory functions above to construct.\n constructor(value, source, stubs, promises) {\n this.value = value;\n this.source = source;\n this.stubs = stubs;\n this.promises = promises;\n }\n // Create a payload from a value passed as params to an RPC from the app.\n //\n // The payload does NOT take ownership of any stubs in `value`, and but promises not to modify\n // `value`. If the payload is delivered locally, `value` will be deep-copied first, so as not\n // to have the sender and recipient end up sharing the same mutable object. `value` will not be\n // touched again after the call returns synchronously (returns a promise) -- by that point,\n // the value has either been copied or serialized to the wire.\n static fromAppParams(value) {\n return new _RpcPayload(value, "params");\n }\n // Create a payload from a value return from an RPC implementation by the app.\n //\n // Unlike fromAppParams(), in this case the payload takes ownership of all stubs in `value`, and\n // may hold onto `value` for an arbitrarily long time (e.g. to serve pipelined requests). It\n // will still avoid modifying `value` and will make a deep copy if it is delivered locally.\n static fromAppReturn(value) {\n return new _RpcPayload(value, "return");\n }\n // Combine an array of payloads into a single payload whose value is an array. Ownership of all\n // stubs is transferred from the inputs to the outputs, hence if the output is disposed, the\n // inputs should not be. (In case of exception, nothing is disposed, though.)\n static fromArray(array) {\n let stubs = [];\n let promises = [];\n let resultArray = [];\n for (let payload of array) {\n payload.ensureDeepCopied();\n for (let stub of payload.stubs) {\n stubs.push(stub);\n }\n for (let promise of payload.promises) {\n if (promise.parent === payload) {\n promise = {\n parent: resultArray,\n property: resultArray.length,\n promise: promise.promise\n };\n }\n promises.push(promise);\n }\n resultArray.push(payload.value);\n }\n return new _RpcPayload(resultArray, "owned", stubs, promises);\n }\n // Create a payload from a value parsed off the wire using Evaluator.evaluate().\n //\n // A payload is constructed with a null value and the given stubs and promises arrays. The value\n // is expected to be filled in by the evaluator, and the stubs and promises arrays are expected\n // to be extended with stubs found during parsing. (This weird usage model is necessary so that\n // if the root value turns out to be a promise, its `parent` in `promises` can be the payload\n // object itself.)\n //\n // When done, the payload takes ownership of the final value and all the stubs within. It may\n // modify the value in preparation for delivery, and may deliver the value directly to the app\n // without copying.\n static forEvaluate(stubs, promises) {\n return new _RpcPayload(null, "owned", stubs, promises);\n }\n // Deep-copy the given value, including dup()ing all stubs.\n //\n // If `value` is a function, it should be bound to `oldParent` as its `this`.\n //\n // If deep-copying from a branch of some other RpcPayload, it must be provided, to make sure\n // RpcTargets found within don\'t get duplicate stubs.\n static deepCopyFrom(value, oldParent, owner) {\n let result = new _RpcPayload(null, "owned", [], []);\n result.value = result.deepCopy(\n value,\n oldParent,\n "value",\n result,\n /*dupStubs=*/\n true,\n owner\n );\n return result;\n }\n // For `source === "return"` payloads only, this tracks any StubHooks created around RpcTargets\n // found in the payload at the time that it is serialized (or deep-copied) for return, so that we\n // can make sure they are not disposed before the pipeline ends.\n //\n // This is initialized on first use.\n rpcTargets;\n // Get the StubHook representing the given RpcTarget found inside this payload.\n getHookForRpcTarget(target, parent, dupStubs = true) {\n if (this.source === "params") {\n if (dupStubs) {\n let dupable = target;\n if (typeof dupable.dup === "function") {\n target = dupable.dup();\n }\n }\n return TargetStubHook.create(target, parent);\n } else if (this.source === "return") {\n let hook = this.rpcTargets?.get(target);\n if (hook) {\n if (dupStubs) {\n return hook.dup();\n } else {\n this.rpcTargets?.delete(target);\n return hook;\n }\n } else {\n hook = TargetStubHook.create(target, parent);\n if (dupStubs) {\n if (!this.rpcTargets) {\n this.rpcTargets = /* @__PURE__ */ new Map();\n }\n this.rpcTargets.set(target, hook);\n return hook.dup();\n } else {\n return hook;\n }\n }\n } else {\n throw new Error("owned payload shouldn\'t contain raw RpcTargets");\n }\n }\n deepCopy(value, oldParent, property, parent, dupStubs, owner) {\n let kind = typeForRpc(value);\n switch (kind) {\n case "unsupported":\n return value;\n case "primitive":\n case "bigint":\n case "date":\n case "bytes":\n case "error":\n case "undefined":\n return value;\n case "array": {\n let array = value;\n let len = array.length;\n let result = new Array(len);\n for (let i = 0; i < len; i++) {\n result[i] = this.deepCopy(array[i], array, i, result, dupStubs, owner);\n }\n return result;\n }\n case "object": {\n let result = {};\n let object = value;\n for (let i in object) {\n result[i] = this.deepCopy(object[i], object, i, result, dupStubs, owner);\n }\n return result;\n }\n case "stub":\n case "rpc-promise": {\n let stub = value;\n let hook;\n if (dupStubs) {\n hook = unwrapStubAndDup(stub);\n } else {\n hook = unwrapStubTakingOwnership(stub);\n }\n if (stub instanceof RpcPromise) {\n let promise = new RpcPromise(hook, []);\n this.promises.push({ parent, property, promise });\n return promise;\n } else {\n let newStub = new RpcStub(hook);\n this.stubs.push(newStub);\n return newStub;\n }\n }\n case "function":\n if (this.source === "owned" && typeof value === "function" && !(value instanceof RpcTarget)) {\n return value;\n }\n // Fall through to rpc-target handling\n case "rpc-target": {\n let target = value;\n let stub;\n if (owner) {\n stub = new RpcStub(owner.getHookForRpcTarget(target, oldParent, dupStubs));\n } else {\n stub = new RpcStub(TargetStubHook.create(target, oldParent));\n }\n this.stubs.push(stub);\n return stub;\n }\n case "rpc-thenable": {\n let target = value;\n let promise;\n if (owner) {\n promise = new RpcPromise(owner.getHookForRpcTarget(target, oldParent, dupStubs), []);\n } else {\n promise = new RpcPromise(TargetStubHook.create(target, oldParent), []);\n }\n this.promises.push({ parent, property, promise });\n return promise;\n }\n default:\n throw new Error("unreachable");\n }\n }\n // Ensures that if the value originally came from an unowned source, we have replaced it with a\n // deep copy.\n ensureDeepCopied() {\n if (this.source !== "owned") {\n let dupStubs = this.source === "params";\n this.stubs = [];\n this.promises = [];\n try {\n this.value = this.deepCopy(this.value, void 0, "value", this, dupStubs, this);\n } catch (err) {\n this.stubs = void 0;\n this.promises = void 0;\n throw err;\n }\n this.source = "owned";\n if (this.rpcTargets && this.rpcTargets.size > 0) {\n throw new Error("Not all rpcTargets were accounted for in deep-copy?");\n }\n this.rpcTargets = void 0;\n }\n }\n // Resolve all promises in this payload and then assign the final value into `parent[property]`.\n deliverTo(parent, property, promises) {\n const unwrapRpcTargets = (value) => {\n if (value instanceof RpcStub) {\n const { hook, pathIfPromise } = unwrapStubAndPath(value);\n if (pathIfPromise == null && hook instanceof TargetStubHook) {\n const target = hook.getTarget();\n return target;\n }\n }\n return value;\n };\n this.ensureDeepCopied();\n if (this.value instanceof RpcPromise) {\n _RpcPayload.deliverRpcPromiseTo(this.value, parent, property, promises);\n } else {\n const unwrapped = unwrapRpcTargets(this.value);\n parent[property] = unwrapped;\n for (let record of this.promises) {\n _RpcPayload.deliverRpcPromiseTo(record.promise, record.parent, record.property, promises);\n }\n }\n }\n static deliverRpcPromiseTo(promise, parent, property, promises) {\n let hook = unwrapStubNoProperties(promise);\n if (!hook) {\n throw new Error("property promises should have been resolved earlier");\n }\n let inner = hook.pull();\n if (inner instanceof _RpcPayload) {\n inner.deliverTo(parent, property, promises);\n } else {\n promises.push(inner.then((payload) => {\n let subPromises = [];\n payload.deliverTo(parent, property, subPromises);\n if (subPromises.length > 0) {\n return Promise.all(subPromises);\n }\n }));\n }\n }\n // Call the given function with the payload as an argument. The call is made synchronously if\n // possible, in order to maintain e-order. However, if any RpcPromises exist in the payload,\n // they are awaited and substituted before calling the function. The result of the call is\n // wrapped into another payload.\n //\n // The payload is automatically disposed after the call completes. The caller should not call\n // dispose().\n async deliverCall(func, thisArg) {\n try {\n let promises = [];\n this.deliverTo(this, "value", promises);\n if (promises.length > 0) {\n await Promise.all(promises);\n }\n let result = Function.prototype.apply.call(func, thisArg, this.value);\n if (result instanceof RpcPromise) {\n return _RpcPayload.fromAppReturn(result);\n } else {\n return _RpcPayload.fromAppReturn(await result);\n }\n } finally {\n this.dispose();\n }\n }\n // Produce a promise for this payload for return to the application. Any RpcPromises in the\n // payload are awaited and substituted with their results first.\n //\n // The returned object will have a disposer which disposes the payload. The caller should not\n // separately dispose it.\n async deliverResolve() {\n try {\n let promises = [];\n this.deliverTo(this, "value", promises);\n if (promises.length > 0) {\n await Promise.all(promises);\n }\n let result = this.value;\n if (result instanceof Object) {\n if (!(Symbol.dispose in result)) {\n Object.defineProperty(result, Symbol.dispose, {\n // NOTE: Using `this.dispose.bind(this)` here causes Playwright\'s build of\n // Chromium 140.0.7339.16 to fail when the object is assigned to a `using` variable,\n // with the error:\n // TypeError: Symbol(Symbol.dispose) is not a function\n // I cannot reproduce this problem in Chrome 140.0.7339.127 nor in Node or workerd,\n // so maybe it was a short-lived V8 bug or something. To be safe, though, we use\n // `() => this.dispose()`, which seems to always work.\n value: () => this.dispose(),\n writable: true,\n enumerable: false,\n configurable: true\n });\n }\n }\n return result;\n } catch (err) {\n this.dispose();\n throw err;\n }\n }\n dispose() {\n if (this.source === "owned") {\n this.stubs.forEach((stub) => stub[Symbol.dispose]());\n this.promises.forEach((promise) => promise.promise[Symbol.dispose]());\n } else if (this.source === "return") {\n this.disposeImpl(this.value, void 0);\n if (this.rpcTargets && this.rpcTargets.size > 0) {\n throw new Error("Not all rpcTargets were accounted for in disposeImpl()?");\n }\n } else ;\n this.source = "owned";\n this.stubs = [];\n this.promises = [];\n }\n // Recursive dispose, called only when `source` is "return".\n disposeImpl(value, parent) {\n let kind = typeForRpc(value);\n switch (kind) {\n case "unsupported":\n case "primitive":\n case "bigint":\n case "bytes":\n case "date":\n case "error":\n case "undefined":\n return;\n case "array": {\n let array = value;\n let len = array.length;\n for (let i = 0; i < len; i++) {\n this.disposeImpl(array[i], array);\n }\n return;\n }\n case "object": {\n let object = value;\n for (let i in object) {\n this.disposeImpl(object[i], object);\n }\n return;\n }\n case "stub":\n case "rpc-promise": {\n let stub = value;\n let hook = unwrapStubNoProperties(stub);\n if (hook) {\n hook.dispose();\n }\n return;\n }\n case "function":\n case "rpc-target": {\n let target = value;\n let hook = this.rpcTargets?.get(target);\n if (hook) {\n hook.dispose();\n this.rpcTargets.delete(target);\n } else {\n disposeRpcTarget(target);\n }\n return;\n }\n case "rpc-thenable":\n return;\n default:\n return;\n }\n }\n // Ignore unhandled rejections in all promises in this payload -- that is, all promises that\n // *would* be awaited if this payload were to be delivered. See the similarly-named method of\n // StubHook for explanation.\n ignoreUnhandledRejections() {\n if (this.stubs) {\n this.stubs.forEach((stub) => {\n unwrapStubOrParent(stub).ignoreUnhandledRejections();\n });\n this.promises.forEach(\n (promise) => unwrapStubOrParent(promise.promise).ignoreUnhandledRejections()\n );\n } else {\n this.ignoreUnhandledRejectionsImpl(this.value);\n }\n }\n ignoreUnhandledRejectionsImpl(value) {\n let kind = typeForRpc(value);\n switch (kind) {\n case "unsupported":\n case "primitive":\n case "bigint":\n case "bytes":\n case "date":\n case "error":\n case "undefined":\n case "function":\n case "rpc-target":\n return;\n case "array": {\n let array = value;\n let len = array.length;\n for (let i = 0; i < len; i++) {\n this.ignoreUnhandledRejectionsImpl(array[i]);\n }\n return;\n }\n case "object": {\n let object = value;\n for (let i in object) {\n this.ignoreUnhandledRejectionsImpl(object[i]);\n }\n return;\n }\n case "stub":\n case "rpc-promise":\n unwrapStubOrParent(value).ignoreUnhandledRejections();\n return;\n case "rpc-thenable":\n value.then((_) => {\n }, (_) => {\n });\n return;\n default:\n return;\n }\n }\n};\nfunction followPath(value, parent, path, owner) {\n for (let i = 0; i < path.length; i++) {\n parent = value;\n let part = path[i];\n if (part in Object.prototype) {\n value = void 0;\n continue;\n }\n let kind = typeForRpc(value);\n switch (kind) {\n case "object":\n case "function":\n if (Object.hasOwn(value, part)) {\n value = value[part];\n } else {\n value = void 0;\n }\n break;\n case "array":\n if (Number.isInteger(part) && part >= 0) {\n value = value[part];\n } else {\n value = void 0;\n }\n break;\n case "rpc-target":\n case "rpc-thenable": {\n if (Object.hasOwn(value, part)) {\n throw new TypeError(\n `Attempted to access property \'${part}\', which is an instance property of the RpcTarget. To avoid leaking private internals, instance properties cannot be accessed over RPC. If you want to make this property available over RPC, define it as a method or getter on the class, instead of an instance property.`\n );\n } else {\n value = value[part];\n }\n owner = null;\n break;\n }\n case "stub":\n case "rpc-promise": {\n let { hook, pathIfPromise } = unwrapStubAndPath(value);\n return { hook, remainingPath: pathIfPromise ? pathIfPromise.concat(path.slice(i)) : path.slice(i) };\n }\n case "primitive":\n case "bigint":\n case "bytes":\n case "date":\n case "error":\n value = void 0;\n break;\n case "undefined":\n value = value[part];\n break;\n case "unsupported": {\n if (i === 0) {\n throw new TypeError(`RPC stub points at a non-serializable type.`);\n } else {\n let prefix = path.slice(0, i).join(".");\n let remainder = path.slice(0, i).join(".");\n throw new TypeError(\n `\'${prefix}\' is not a serializable type, so property ${remainder} cannot be accessed.`\n );\n }\n }\n default:\n throw new TypeError("unreachable");\n }\n }\n if (value instanceof RpcPromise) {\n let { hook, pathIfPromise } = unwrapStubAndPath(value);\n return { hook, remainingPath: pathIfPromise || [] };\n }\n return {\n value,\n parent,\n owner\n };\n}\nvar ValueStubHook = class extends StubHook {\n call(path, args) {\n try {\n let { value, owner } = this.getValue();\n let followResult = followPath(value, void 0, path, owner);\n if (followResult.hook) {\n return followResult.hook.call(followResult.remainingPath, args);\n }\n if (typeof followResult.value != "function") {\n throw new TypeError(`\'${path.join(".")}\' is not a function.`);\n }\n let promise = args.deliverCall(followResult.value, followResult.parent);\n return new PromiseStubHook(promise.then((payload) => {\n return new PayloadStubHook(payload);\n }));\n } catch (err) {\n return new ErrorStubHook(err);\n }\n }\n map(path, captures, instructions) {\n try {\n let followResult;\n try {\n let { value, owner } = this.getValue();\n followResult = followPath(value, void 0, path, owner);\n ;\n } catch (err) {\n for (let cap of captures) {\n cap.dispose();\n }\n throw err;\n }\n if (followResult.hook) {\n return followResult.hook.map(followResult.remainingPath, captures, instructions);\n }\n return mapImpl.applyMap(\n followResult.value,\n followResult.parent,\n followResult.owner,\n captures,\n instructions\n );\n } catch (err) {\n return new ErrorStubHook(err);\n }\n }\n get(path) {\n try {\n let { value, owner } = this.getValue();\n if (path.length === 0 && owner === null) {\n throw new Error("Can\'t dup an RpcTarget stub as a promise.");\n }\n let followResult = followPath(value, void 0, path, owner);\n if (followResult.hook) {\n return followResult.hook.get(followResult.remainingPath);\n }\n return new PayloadStubHook(RpcPayload.deepCopyFrom(\n followResult.value,\n followResult.parent,\n followResult.owner\n ));\n } catch (err) {\n return new ErrorStubHook(err);\n }\n }\n};\nvar PayloadStubHook = class _PayloadStubHook extends ValueStubHook {\n constructor(payload) {\n super();\n this.payload = payload;\n }\n payload;\n // cleared when disposed\n getPayload() {\n if (this.payload) {\n return this.payload;\n } else {\n throw new Error("Attempted to use an RPC StubHook after it was disposed.");\n }\n }\n getValue() {\n let payload = this.getPayload();\n return { value: payload.value, owner: payload };\n }\n dup() {\n let thisPayload = this.getPayload();\n return new _PayloadStubHook(RpcPayload.deepCopyFrom(\n thisPayload.value,\n void 0,\n thisPayload\n ));\n }\n pull() {\n return this.getPayload();\n }\n ignoreUnhandledRejections() {\n if (this.payload) {\n this.payload.ignoreUnhandledRejections();\n }\n }\n dispose() {\n if (this.payload) {\n this.payload.dispose();\n this.payload = void 0;\n }\n }\n onBroken(callback) {\n if (this.payload) {\n if (this.payload.value instanceof RpcStub) {\n this.payload.value.onRpcBroken(callback);\n }\n }\n }\n};\nfunction disposeRpcTarget(target) {\n if (Symbol.dispose in target) {\n try {\n target[Symbol.dispose]();\n } catch (err) {\n Promise.reject(err);\n }\n }\n}\nvar TargetStubHook = class _TargetStubHook extends ValueStubHook {\n // Constructs a TargetStubHook that is not duplicated from an existing hook.\n //\n // If `value` is a function, `parent` is bound as its "this".\n static create(value, parent) {\n if (typeof value !== "function") {\n parent = void 0;\n }\n return new _TargetStubHook(value, parent);\n }\n constructor(target, parent, dupFrom) {\n super();\n this.target = target;\n this.parent = parent;\n if (dupFrom) {\n if (dupFrom.refcount) {\n this.refcount = dupFrom.refcount;\n ++this.refcount.count;\n }\n } else if (Symbol.dispose in target) {\n this.refcount = { count: 1 };\n }\n }\n target;\n // cleared when disposed\n parent;\n // `this` parameter when calling `target`\n refcount;\n // undefined if not needed (because target has no disposer)\n getTarget() {\n if (this.target) {\n return this.target;\n } else {\n throw new Error("Attempted to use an RPC StubHook after it was disposed.");\n }\n }\n getValue() {\n return { value: this.getTarget(), owner: null };\n }\n dup() {\n return new _TargetStubHook(this.getTarget(), this.parent, this);\n }\n pull() {\n let target = this.getTarget();\n if ("then" in target) {\n return Promise.resolve(target).then((resolution) => {\n return RpcPayload.fromAppReturn(resolution);\n });\n } else {\n return Promise.reject(new Error("Tried to resolve a non-promise stub."));\n }\n }\n ignoreUnhandledRejections() {\n }\n dispose() {\n if (this.target) {\n if (this.refcount) {\n if (--this.refcount.count == 0) {\n disposeRpcTarget(this.target);\n }\n }\n this.target = void 0;\n }\n }\n onBroken(callback) {\n }\n};\nvar PromiseStubHook = class _PromiseStubHook extends StubHook {\n promise;\n resolution;\n constructor(promise) {\n super();\n this.promise = promise.then((res) => {\n this.resolution = res;\n return res;\n });\n }\n call(path, args) {\n args.ensureDeepCopied();\n return new _PromiseStubHook(this.promise.then((hook) => hook.call(path, args)));\n }\n map(path, captures, instructions) {\n return new _PromiseStubHook(this.promise.then(\n (hook) => hook.map(path, captures, instructions),\n (err) => {\n for (let cap of captures) {\n cap.dispose();\n }\n throw err;\n }\n ));\n }\n get(path) {\n return new _PromiseStubHook(this.promise.then((hook) => hook.get(path)));\n }\n dup() {\n if (this.resolution) {\n return this.resolution.dup();\n } else {\n return new _PromiseStubHook(this.promise.then((hook) => hook.dup()));\n }\n }\n pull() {\n if (this.resolution) {\n return this.resolution.pull();\n } else {\n return this.promise.then((hook) => hook.pull());\n }\n }\n ignoreUnhandledRejections() {\n if (this.resolution) {\n this.resolution.ignoreUnhandledRejections();\n } else {\n this.promise.then((res) => {\n res.ignoreUnhandledRejections();\n }, (err) => {\n });\n }\n }\n dispose() {\n if (this.resolution) {\n this.resolution.dispose();\n } else {\n this.promise.then((hook) => {\n hook.dispose();\n }, (err) => {\n });\n }\n }\n onBroken(callback) {\n if (this.resolution) {\n this.resolution.onBroken(callback);\n } else {\n this.promise.then((hook) => {\n hook.onBroken(callback);\n }, callback);\n }\n }\n};\nvar currentMapBuilder;\nvar MapBuilder = class {\n context;\n captureMap = /* @__PURE__ */ new Map();\n instructions = [];\n constructor(subject, path) {\n if (currentMapBuilder) {\n this.context = {\n parent: currentMapBuilder,\n captures: [],\n subject: currentMapBuilder.capture(subject),\n path\n };\n } else {\n this.context = {\n parent: void 0,\n captures: [],\n subject,\n path\n };\n }\n currentMapBuilder = this;\n }\n unregister() {\n currentMapBuilder = this.context.parent;\n }\n makeInput() {\n return new MapVariableHook(this, 0);\n }\n makeOutput(result) {\n let devalued;\n try {\n devalued = Devaluator.devaluate(result.value, void 0, this, result);\n } finally {\n result.dispose();\n }\n this.instructions.push(devalued);\n if (this.context.parent) {\n this.context.parent.instructions.push(\n [\n "remap",\n this.context.subject,\n this.context.path,\n this.context.captures.map((cap) => ["import", cap]),\n this.instructions\n ]\n );\n return new MapVariableHook(this.context.parent, this.context.parent.instructions.length);\n } else {\n return this.context.subject.map(this.context.path, this.context.captures, this.instructions);\n }\n }\n pushCall(hook, path, params) {\n let devalued = Devaluator.devaluate(params.value, void 0, this, params);\n devalued = devalued[0];\n let subject = this.capture(hook.dup());\n this.instructions.push(["pipeline", subject, path, devalued]);\n return new MapVariableHook(this, this.instructions.length);\n }\n pushGet(hook, path) {\n let subject = this.capture(hook.dup());\n this.instructions.push(["pipeline", subject, path]);\n return new MapVariableHook(this, this.instructions.length);\n }\n capture(hook) {\n if (hook instanceof MapVariableHook && hook.mapper === this) {\n return hook.idx;\n }\n let result = this.captureMap.get(hook);\n if (result === void 0) {\n if (this.context.parent) {\n let parentIdx = this.context.parent.capture(hook);\n this.context.captures.push(parentIdx);\n } else {\n this.context.captures.push(hook);\n }\n result = -this.context.captures.length;\n this.captureMap.set(hook, result);\n }\n return result;\n }\n // ---------------------------------------------------------------------------\n // implements Exporter\n exportStub(hook) {\n throw new Error(\n "Can\'t construct an RpcTarget or RPC callback inside a mapper function. Try creating a new RpcStub outside the callback first, then using it inside the callback."\n );\n }\n exportPromise(hook) {\n return this.exportStub(hook);\n }\n getImport(hook) {\n return this.capture(hook);\n }\n unexport(ids) {\n }\n onSendError(error) {\n }\n};\nmapImpl.sendMap = (hook, path, func) => {\n let builder = new MapBuilder(hook, path);\n let result;\n try {\n result = RpcPayload.fromAppReturn(withCallInterceptor(builder.pushCall.bind(builder), () => {\n return func(new RpcPromise(builder.makeInput(), []));\n }));\n } finally {\n builder.unregister();\n }\n if (result instanceof Promise) {\n result.catch((err) => {\n });\n throw new Error("RPC map() callbacks cannot be async.");\n }\n return new RpcPromise(builder.makeOutput(result), []);\n};\nmapImpl.recordCallback = (func) => {\n const builder = new MapBuilder(new PayloadStubHook(RpcPayload.fromAppParams([])), []);\n let result;\n try {\n result = RpcPayload.fromAppReturn(withCallInterceptor(builder.pushCall.bind(builder), () => {\n return func(new RpcPromise(builder.makeInput(), []));\n }));\n } finally {\n builder.unregister();\n }\n const devaluatedResult = Devaluator.devaluate(result.value, void 0, builder, result);\n const instructions = [...builder.instructions, devaluatedResult];\n const context = builder.context;\n if (context.parent) {\n return ["callback", context.captures.map((cap) => ["import", cap]), instructions];\n } else {\n return ["callback", context.captures, instructions];\n }\n};\nfunction throwMapperBuilderUseError() {\n throw new Error(\n "Attempted to use an abstract placeholder from a mapper function. Please make sure your map function has no side effects."\n );\n}\nvar MapVariableHook = class extends StubHook {\n constructor(mapper, idx) {\n super();\n this.mapper = mapper;\n this.idx = idx;\n }\n // We don\'t have anything we actually need to dispose, so dup() can just return the same hook.\n dup() {\n return this;\n }\n dispose() {\n }\n get(path) {\n if (path.length == 0) {\n return this;\n } else if (currentMapBuilder) {\n return currentMapBuilder.pushGet(this, path);\n } else {\n throwMapperBuilderUseError();\n }\n }\n // Other methods should never be called.\n call(path, args) {\n throwMapperBuilderUseError();\n }\n map(path, captures, instructions) {\n throwMapperBuilderUseError();\n }\n pull() {\n throwMapperBuilderUseError();\n }\n ignoreUnhandledRejections() {\n }\n onBroken(callback) {\n throwMapperBuilderUseError();\n }\n};\nvar MapApplicator = class {\n constructor(captures, input) {\n this.captures = captures;\n this.variables = [input];\n }\n variables;\n dispose() {\n for (let variable of this.variables) {\n variable.dispose();\n }\n }\n apply(instructions) {\n try {\n if (instructions.length < 1) {\n throw new Error("Invalid empty mapper function.");\n }\n for (let instruction of instructions.slice(0, -1)) {\n let payload = new Evaluator(this).evaluateCopy(instruction);\n if (payload.value instanceof RpcStub) {\n let hook = unwrapStubNoProperties(payload.value);\n if (hook) {\n this.variables.push(hook);\n continue;\n }\n }\n this.variables.push(new PayloadStubHook(payload));\n }\n return new Evaluator(this).evaluateCopy(instructions[instructions.length - 1]);\n } finally {\n for (let variable of this.variables) {\n variable.dispose();\n }\n }\n }\n importStub(idx) {\n throw new Error("A mapper function cannot refer to exports.");\n }\n importPromise(idx) {\n return this.importStub(idx);\n }\n getExport(idx) {\n if (idx < 0) {\n return this.captures[-idx - 1];\n } else {\n return this.variables[idx];\n }\n }\n};\nfunction applyMapToElement(input, parent, owner, captures, instructions) {\n let inputHook = new PayloadStubHook(RpcPayload.deepCopyFrom(input, parent, owner));\n let mapper = new MapApplicator(captures, inputHook);\n try {\n return mapper.apply(instructions);\n } finally {\n mapper.dispose();\n }\n}\nmapImpl.applyMap = (input, parent, owner, captures, instructions) => {\n try {\n let result;\n if (input instanceof RpcPromise) {\n throw new Error("applyMap() can\'t be called on RpcPromise");\n } else if (input instanceof Array) {\n let payloads = [];\n try {\n for (let elem of input) {\n payloads.push(applyMapToElement(elem, input, owner, captures, instructions));\n }\n } catch (err) {\n for (let payload of payloads) {\n payload.dispose();\n }\n throw err;\n }\n result = RpcPayload.fromArray(payloads);\n } else if (input === null || input === void 0) {\n result = RpcPayload.fromAppReturn(input);\n } else {\n result = applyMapToElement(input, parent, owner, captures, instructions);\n }\n return new PayloadStubHook(result);\n } finally {\n for (let cap of captures) {\n cap.dispose();\n }\n }\n};\nvar isExplicitCallback = (arg) => {\n return typeof arg === "function" && "serializationMode" in arg;\n};\nvar NullExporter = class {\n exportStub(stub) {\n throw new Error("Cannot serialize RPC stubs without an RPC session.");\n }\n exportPromise(stub) {\n throw new Error("Cannot serialize RPC stubs without an RPC session.");\n }\n getImport(hook) {\n return void 0;\n }\n unexport(ids) {\n }\n onSendError(error) {\n }\n};\nvar NULL_EXPORTER = new NullExporter();\nvar ERROR_TYPES = {\n Error,\n EvalError,\n RangeError,\n ReferenceError,\n SyntaxError,\n TypeError,\n URIError,\n AggregateError\n // TODO: DOMError? Others?\n};\nvar Devaluator = class _Devaluator {\n constructor(exporter, source) {\n this.exporter = exporter;\n this.source = source;\n }\n // Devaluate the given value.\n // * value: The value to devaluate.\n // * parent: The value\'s parent object, which would be used as `this` if the value were called\n // as a function.\n // * exporter: Callbacks to the RPC session for exporting capabilities found in this message.\n // * source: The RpcPayload which contains the value, and therefore owns stubs within.\n //\n // Returns: The devaluated value, ready to be JSON-serialized.\n static devaluate(value, parent, exporter = NULL_EXPORTER, source) {\n let devaluator = new _Devaluator(exporter, source);\n try {\n return devaluator.devaluateImpl(value, parent, 0);\n } catch (err) {\n if (devaluator.exports) {\n try {\n exporter.unexport(devaluator.exports);\n } catch (err2) {\n }\n }\n throw err;\n }\n }\n exports;\n devaluateImpl(value, parent, depth) {\n if (depth >= 64) {\n throw new Error(\n "Serialization exceeded maximum allowed depth. (Does the message contain cycles?)"\n );\n }\n let kind = typeForRpc(value);\n switch (kind) {\n case "unsupported": {\n let msg;\n try {\n msg = `Cannot serialize value: ${value}`;\n } catch (err) {\n msg = "Cannot serialize value: (couldn\'t stringify value)";\n }\n throw new TypeError(msg);\n }\n case "primitive":\n if (typeof value === "number" && !isFinite(value)) {\n if (value === Infinity) {\n return ["inf"];\n } else if (value === -Infinity) {\n return ["-inf"];\n } else {\n return ["nan"];\n }\n } else {\n return value;\n }\n case "object": {\n let object = value;\n let result = {};\n for (let key in object) {\n result[key] = this.devaluateImpl(object[key], object, depth + 1);\n }\n return result;\n }\n case "array": {\n let array = value;\n let len = array.length;\n let result = new Array(len);\n for (let i = 0; i < len; i++) {\n result[i] = this.devaluateImpl(array[i], array, depth + 1);\n }\n return [result];\n }\n case "bigint":\n return ["bigint", value.toString()];\n case "date":\n return ["date", value.getTime()];\n case "bytes": {\n let bytes = value;\n if (bytes.toBase64) {\n return ["bytes", bytes.toBase64({ omitPadding: true })];\n } else {\n return [\n "bytes",\n btoa(String.fromCharCode.apply(null, bytes).replace(/=*$/, ""))\n ];\n }\n }\n case "error": {\n let e = value;\n let rewritten = this.exporter.onSendError(e);\n if (rewritten) {\n e = rewritten;\n }\n let result = ["error", e.name, e.message];\n if (rewritten && rewritten.stack) {\n result.push(rewritten.stack);\n }\n return result;\n }\n case "undefined":\n return ["undefined"];\n case "stub":\n case "rpc-promise": {\n if (!this.source) {\n throw new Error("Can\'t serialize RPC stubs in this context.");\n }\n let { hook, pathIfPromise } = unwrapStubAndPath(value);\n let importId = this.exporter.getImport(hook);\n if (importId !== void 0) {\n if (pathIfPromise) {\n if (pathIfPromise.length > 0) {\n return ["pipeline", importId, pathIfPromise];\n } else {\n return ["pipeline", importId];\n }\n } else {\n return ["import", importId];\n }\n }\n if (pathIfPromise) {\n hook = hook.get(pathIfPromise);\n } else {\n hook = hook.dup();\n }\n return this.devaluateHook(pathIfPromise ? "promise" : "export", hook);\n }\n case "function":\n case "rpc-target": {\n let shouldRecordReplay = false;\n if (kind === "function") {\n if (isExplicitCallback(value)) {\n const explicitMode = value.serializationMode;\n shouldRecordReplay = explicitMode === "recordReplay";\n } else {\n shouldRecordReplay = getGlobalRpcSessionOptions().recordReplayMode === "all";\n }\n }\n if (shouldRecordReplay) {\n const res = mapImpl.recordCallback(value);\n const captures = res[1];\n if (captures.length === 0 || captures[0] instanceof StubHook) {\n const captureHooks = captures;\n const serializedCaptures = captureHooks.map((stub) => {\n const importId = this.exporter.getImport(stub);\n if (importId !== void 0) {\n return ["import", importId];\n } else {\n return ["export", this.exporter.exportStub(stub)];\n }\n });\n for (const hook2 of captureHooks) {\n hook2.dispose();\n }\n return ["callback", serializedCaptures, res[2]];\n } else {\n return res;\n }\n }\n if (!this.source) {\n throw new Error("Can\'t serialize RPC stubs in this context.");\n }\n let hook = this.source.getHookForRpcTarget(value, parent);\n return this.devaluateHook("export", hook);\n }\n case "rpc-thenable": {\n if (!this.source) {\n throw new Error("Can\'t serialize RPC stubs in this context.");\n }\n let hook = this.source.getHookForRpcTarget(value, parent);\n return this.devaluateHook("promise", hook);\n }\n default:\n throw new Error("unreachable");\n }\n }\n devaluateHook(type, hook) {\n if (!this.exports) this.exports = [];\n let exportId = type === "promise" ? this.exporter.exportPromise(hook) : this.exporter.exportStub(hook);\n this.exports.push(exportId);\n return [type, exportId];\n }\n};\nvar NullImporter = class {\n importStub(idx) {\n throw new Error("Cannot deserialize RPC stubs without an RPC session.");\n }\n importPromise(idx) {\n throw new Error("Cannot deserialize RPC stubs without an RPC session.");\n }\n getExport(idx) {\n return void 0;\n }\n};\nvar NULL_IMPORTER = new NullImporter();\nvar Evaluator = class _Evaluator {\n constructor(importer) {\n this.importer = importer;\n }\n stubs = [];\n promises = [];\n // Resolve serialized captures to StubHooks. Used by both "callback" and "remap" evaluation.\n resolveCaptures(capsData) {\n return capsData.map((cap) => {\n if (!(cap instanceof Array) || cap.length !== 2 || cap[0] !== "import" && cap[0] !== "export" || typeof cap[1] !== "number") {\n throw new TypeError(`unknown capture: ${JSON.stringify(cap)}`);\n }\n if (cap[0] === "export") {\n return this.importer.importStub(cap[1]);\n } else {\n let exp = this.importer.getExport(cap[1]);\n if (!exp) {\n throw new Error(`no such entry on exports table: ${cap[1]}`);\n }\n return exp.dup();\n }\n });\n }\n evaluate(value) {\n let payload = RpcPayload.forEvaluate(this.stubs, this.promises);\n try {\n payload.value = this.evaluateImpl(value, payload, "value");\n return payload;\n } catch (err) {\n payload.dispose();\n throw err;\n }\n }\n // Evaluate the value without destroying it.\n evaluateCopy(value) {\n return this.evaluate(structuredClone(value));\n }\n evaluateImpl(value, parent, property) {\n if (value instanceof Array) {\n if (value.length == 1 && value[0] instanceof Array) {\n let result = value[0];\n for (let i = 0; i < result.length; i++) {\n result[i] = this.evaluateImpl(result[i], result, i);\n }\n return result;\n } else switch (value[0]) {\n case "callback": {\n if (value.length < 3 || !(value[1] instanceof Array) || !(value[2] instanceof Array)) {\n break;\n }\n const captures = this.resolveCaptures(value[1]);\n const instructions = value[2];\n const replayFn = (arg) => {\n const capturesForThisCall = captures.map((c) => c.dup());\n const inputHook = new PayloadStubHook(RpcPayload.fromAppParams(arg));\n const applicator = new MapApplicator(capturesForThisCall, inputHook);\n const disposeInvocation = () => {\n applicator.dispose();\n for (const cap of capturesForThisCall) {\n cap.dispose();\n }\n const cleanup = replayFn[CALLBACK_CLEANUP];\n if (typeof cleanup === "function") {\n cleanup();\n }\n };\n let resultPayload;\n try {\n resultPayload = applicator.apply(instructions);\n } catch (err) {\n disposeInvocation();\n throw err;\n }\n return resultPayload.deliverResolve().finally(disposeInvocation);\n };\n replayFn[CALLBACK_CLEANUP] = () => {\n for (const cap of captures) {\n cap.dispose();\n }\n };\n return replayFn;\n }\n case "bigint":\n if (typeof value[1] == "string") {\n return BigInt(value[1]);\n }\n break;\n case "date":\n if (typeof value[1] == "number") {\n return new Date(value[1]);\n }\n break;\n case "bytes": {\n let b64 = Uint8Array;\n if (typeof value[1] == "string") {\n if (b64.fromBase64) {\n return b64.fromBase64(value[1]);\n } else {\n let bs = atob(value[1]);\n let len = bs.length;\n let bytes = new Uint8Array(len);\n for (let i = 0; i < len; i++) {\n bytes[i] = bs.charCodeAt(i);\n }\n return bytes;\n }\n }\n break;\n }\n case "error":\n if (value.length >= 3 && typeof value[1] === "string" && typeof value[2] === "string") {\n let cls = ERROR_TYPES[value[1]] || Error;\n let result = new cls(value[2]);\n if (typeof value[3] === "string") {\n result.stack = value[3];\n }\n return result;\n }\n break;\n case "undefined":\n if (value.length === 1) {\n return void 0;\n }\n break;\n case "inf":\n return Infinity;\n case "-inf":\n return -Infinity;\n case "nan":\n return NaN;\n case "import":\n case "pipeline": {\n if (value.length < 2 || value.length > 4) {\n break;\n }\n if (typeof value[1] != "number") {\n break;\n }\n let hook = this.importer.getExport(value[1]);\n if (!hook) {\n throw new Error(`no such entry on exports table: ${value[1]}`);\n }\n let isPromise = value[0] == "pipeline";\n let addStub = (hook2) => {\n const unwrapped = maybeUnwrapStubHook(hook2);\n if (unwrapped) {\n hook2.dispose();\n return unwrapped;\n }\n if (isPromise) {\n let promise = new RpcPromise(hook2, []);\n this.promises.push({ promise, parent, property });\n return promise;\n } else {\n let stub = new RpcPromise(hook2, []);\n this.stubs.push(stub);\n return stub;\n }\n };\n if (value.length == 2) {\n if (isPromise) {\n return addStub(hook.get([]));\n } else {\n return addStub(hook.dup());\n }\n }\n let path = value[2];\n if (!(path instanceof Array)) {\n break;\n }\n if (!path.every(\n (part) => {\n return typeof part == "string" || typeof part == "number";\n }\n )) {\n break;\n }\n if (value.length == 3) {\n return addStub(hook.get(path));\n }\n let args = value[3];\n if (!(args instanceof Array)) {\n break;\n }\n let subEval = new _Evaluator(this.importer);\n args = subEval.evaluate([args]);\n return addStub(hook.call(path, args));\n }\n case "remap": {\n if (value.length !== 5 || typeof value[1] !== "number" || !(value[2] instanceof Array) || !(value[3] instanceof Array) || !(value[4] instanceof Array)) {\n break;\n }\n let hook = this.importer.getExport(value[1]);\n if (!hook) {\n throw new Error(`no such entry on exports table: ${value[1]}`);\n }\n let path = value[2];\n if (!path.every(\n (part) => {\n return typeof part == "string" || typeof part == "number";\n }\n )) {\n break;\n }\n let captures = this.resolveCaptures(value[3]);\n let instructions = value[4];\n let resultHook = hook.map(path, captures, instructions);\n let promise = new RpcPromise(resultHook, []);\n this.promises.push({ promise, parent, property });\n return promise;\n }\n case "export":\n case "promise":\n if (typeof value[1] == "number") {\n if (value[0] == "promise") {\n let hook = this.importer.importPromise(value[1]);\n let promise = new RpcPromise(hook, []);\n this.promises.push({ parent, property, promise });\n return promise;\n } else {\n let hook = this.importer.importStub(value[1]);\n let stub = new RpcStub(hook);\n this.stubs.push(stub);\n return stub;\n }\n }\n break;\n }\n throw new TypeError(`unknown special value: ${JSON.stringify(value)}`);\n } else if (value instanceof Object) {\n let result = value;\n for (let key in result) {\n if (key in Object.prototype || key === "toJSON") {\n this.evaluateImpl(result[key], result, key);\n delete result[key];\n } else {\n result[key] = this.evaluateImpl(result[key], result, key);\n }\n }\n return result;\n } else {\n return value;\n }\n }\n};\nvar maybeUnwrapStubHook = (hook) => {\n if (!(hook instanceof PayloadStubHook)) {\n return void 0;\n }\n const payload = hook.getPayload();\n if (payload.value instanceof RpcStub) {\n const { hook: innerHook, pathIfPromise } = unwrapStubAndPath(payload.value);\n if (pathIfPromise == null && innerHook instanceof TargetStubHook) {\n return innerHook.getTarget();\n } else {\n return innerHook;\n }\n }\n return void 0;\n};\nvar ImportTableEntry = class {\n constructor(session, importId, pulling) {\n this.session = session;\n this.importId = importId;\n if (pulling) {\n this.activePull = Promise.withResolvers();\n }\n }\n localRefcount = 0;\n remoteRefcount = 1;\n activePull;\n resolution;\n // List of integer indexes into session.onBrokenCallbacks which are callbacks registered on\n // this import. Initialized on first use (so `undefined` is the same as an empty list).\n onBrokenRegistrations;\n resolve(resolution) {\n if (this.localRefcount == 0) {\n resolution.dispose();\n return;\n }\n this.resolution = resolution;\n this.sendRelease();\n if (this.onBrokenRegistrations) {\n for (let i of this.onBrokenRegistrations) {\n let callback = this.session.onBrokenCallbacks[i];\n let endIndex = this.session.onBrokenCallbacks.length;\n resolution.onBroken(callback);\n if (this.session.onBrokenCallbacks[endIndex] === callback) {\n delete this.session.onBrokenCallbacks[endIndex];\n } else {\n delete this.session.onBrokenCallbacks[i];\n }\n }\n this.onBrokenRegistrations = void 0;\n }\n if (this.activePull) {\n this.activePull.resolve();\n this.activePull = void 0;\n }\n }\n async awaitResolution() {\n if (!this.activePull) {\n this.session.sendPull(this.importId);\n this.activePull = Promise.withResolvers();\n }\n await this.activePull.promise;\n return this.resolution.pull();\n }\n dispose() {\n if (this.resolution) {\n this.resolution.dispose();\n } else {\n this.abort(new Error("RPC was canceled because the RpcPromise was disposed."));\n this.sendRelease();\n }\n }\n abort(error) {\n if (!this.resolution) {\n this.resolution = new ErrorStubHook(error);\n if (this.activePull) {\n this.activePull.reject(error);\n this.activePull = void 0;\n }\n this.onBrokenRegistrations = void 0;\n }\n }\n onBroken(callback) {\n if (this.resolution) {\n this.resolution.onBroken(callback);\n } else {\n let index = this.session.onBrokenCallbacks.length;\n this.session.onBrokenCallbacks.push(callback);\n if (!this.onBrokenRegistrations) this.onBrokenRegistrations = [];\n this.onBrokenRegistrations.push(index);\n }\n }\n sendRelease() {\n if (this.remoteRefcount > 0) {\n this.session.sendRelease(this.importId, this.remoteRefcount);\n this.remoteRefcount = 0;\n }\n }\n};\nvar RpcImportHook = class _RpcImportHook extends StubHook {\n // undefined when we\'re disposed\n // `pulling` is true if we already expect that this import is going to be resolved later, and\n // null if this import is not allowed to be pulled (i.e. it\'s a stub not a promise).\n constructor(isPromise, entry) {\n super();\n this.isPromise = isPromise;\n ++entry.localRefcount;\n this.entry = entry;\n }\n entry;\n collectPath(path) {\n return this;\n }\n getEntry() {\n if (this.entry) {\n return this.entry;\n } else {\n throw new Error("This RpcImportHook was already disposed.");\n }\n }\n // -------------------------------------------------------------------------------------\n // implements StubHook\n call(path, args) {\n let entry = this.getEntry();\n if (entry.resolution) {\n return entry.resolution.call(path, args);\n } else {\n return entry.session.sendCall(entry.importId, path, args);\n }\n }\n map(path, captures, instructions) {\n let entry;\n try {\n entry = this.getEntry();\n } catch (err) {\n for (let cap of captures) {\n cap.dispose();\n }\n throw err;\n }\n if (entry.resolution) {\n return entry.resolution.map(path, captures, instructions);\n } else {\n return entry.session.sendMap(entry.importId, path, captures, instructions);\n }\n }\n get(path) {\n let entry = this.getEntry();\n if (entry.resolution) {\n return entry.resolution.get(path);\n } else {\n return entry.session.sendCall(entry.importId, path);\n }\n }\n dup() {\n return new _RpcImportHook(false, this.getEntry());\n }\n pull() {\n let entry = this.getEntry();\n if (!this.isPromise) {\n throw new Error("Can\'t pull this hook because it\'s not a promise hook.");\n }\n if (entry.resolution) {\n return entry.resolution.pull();\n }\n return entry.awaitResolution();\n }\n ignoreUnhandledRejections() {\n }\n dispose() {\n let entry = this.entry;\n this.entry = void 0;\n if (entry) {\n if (--entry.localRefcount === 0) {\n entry.dispose();\n }\n }\n }\n onBroken(callback) {\n if (this.entry) {\n this.entry.onBroken(callback);\n }\n }\n};\nvar RpcMainHook = class extends RpcImportHook {\n session;\n constructor(entry) {\n super(false, entry);\n this.session = entry.session;\n }\n dispose() {\n if (this.session) {\n let session = this.session;\n this.session = void 0;\n session.shutdown();\n }\n }\n};\nvar RpcSessionImpl = class {\n constructor(transport, mainHook, options) {\n this.transport = transport;\n this.options = options;\n this.exports.push({ hook: mainHook, refcount: 1 });\n this.imports.push(new ImportTableEntry(this, 0, false));\n let rejectFunc;\n let abortPromise = new Promise((resolve, reject) => {\n rejectFunc = reject;\n });\n this.cancelReadLoop = rejectFunc;\n this.readLoop(abortPromise).catch((err) => this.abort(err));\n }\n exports = [];\n reverseExports = /* @__PURE__ */ new Map();\n imports = [];\n abortReason;\n cancelReadLoop;\n // We assign positive numbers to imports we initiate, and negative numbers to exports we\n // initiate. So the next import ID is just `imports.length`, but the next export ID needs\n // to be tracked explicitly.\n nextExportId = -1;\n // If set, call this when all incoming calls are complete.\n onBatchDone;\n // How many promises is our peer expecting us to resolve?\n pullCount = 0;\n // Sparse array of onBrokenCallback registrations. Items are strictly appended to the end but\n // may be deleted from the middle (hence leaving the array sparse).\n onBrokenCallbacks = [];\n // Should only be called once immediately after construction.\n getMainImport() {\n return new RpcMainHook(this.imports[0]);\n }\n shutdown() {\n this.abort(new Error("RPC session was shut down by disposing the main stub"), false);\n }\n exportStub(hook) {\n if (this.abortReason) throw this.abortReason;\n let existingExportId = this.reverseExports.get(hook);\n if (existingExportId !== void 0) {\n ++this.exports[existingExportId].refcount;\n return existingExportId;\n } else {\n let exportId = this.nextExportId--;\n this.exports[exportId] = { hook, refcount: 1 };\n this.reverseExports.set(hook, exportId);\n return exportId;\n }\n }\n exportPromise(hook) {\n if (this.abortReason) throw this.abortReason;\n let exportId = this.nextExportId--;\n this.exports[exportId] = { hook, refcount: 1 };\n this.reverseExports.set(hook, exportId);\n this.ensureResolvingExport(exportId);\n return exportId;\n }\n unexport(ids) {\n for (let id of ids) {\n this.releaseExport(id, 1);\n }\n }\n releaseExport(exportId, refcount) {\n let entry = this.exports[exportId];\n if (!entry) {\n throw new Error(`no such export ID: ${exportId}`);\n }\n if (entry.refcount < refcount) {\n throw new Error(`refcount would go negative: ${entry.refcount} < ${refcount}`);\n }\n entry.refcount -= refcount;\n if (entry.refcount === 0) {\n delete this.exports[exportId];\n this.reverseExports.delete(entry.hook);\n entry.hook.dispose();\n }\n }\n onSendError(error) {\n if (this.options.onSendError) {\n return this.options.onSendError(error);\n }\n }\n ensureResolvingExport(exportId) {\n let exp = this.exports[exportId];\n if (!exp) {\n throw new Error(`no such export ID: ${exportId}`);\n }\n if (!exp.pull) {\n let resolve = async () => {\n let hook = exp.hook;\n for (; ; ) {\n let payload = await hook.pull();\n if (payload.value instanceof RpcStub) {\n let { hook: inner, pathIfPromise } = unwrapStubAndPath(payload.value);\n if (pathIfPromise && pathIfPromise.length == 0) {\n if (this.getImport(hook) === void 0) {\n hook = inner;\n continue;\n }\n }\n }\n return payload;\n }\n };\n ++this.pullCount;\n exp.pull = resolve().then(\n (payload) => {\n let value = Devaluator.devaluate(payload.value, void 0, this, payload);\n this.send(["resolve", exportId, value]);\n },\n (error) => {\n this.send(["reject", exportId, Devaluator.devaluate(error, void 0, this)]);\n }\n ).catch(\n (error) => {\n try {\n this.send(["reject", exportId, Devaluator.devaluate(error, void 0, this)]);\n } catch (error2) {\n this.abort(error2);\n }\n }\n ).finally(() => {\n if (--this.pullCount === 0) {\n if (this.onBatchDone) {\n this.onBatchDone.resolve();\n }\n }\n });\n }\n }\n getImport(hook) {\n if (hook instanceof RpcImportHook && hook.entry && hook.entry.session === this) {\n return hook.entry.importId;\n } else {\n return void 0;\n }\n }\n importStub(idx) {\n if (this.abortReason) throw this.abortReason;\n let entry = this.imports[idx];\n if (!entry) {\n entry = new ImportTableEntry(this, idx, false);\n this.imports[idx] = entry;\n }\n return new RpcImportHook(\n /*isPromise=*/\n false,\n entry\n );\n }\n importPromise(idx) {\n if (this.abortReason) throw this.abortReason;\n if (this.imports[idx]) {\n return new ErrorStubHook(new Error(\n "Bug in RPC system: The peer sent a promise reusing an existing export ID."\n ));\n }\n let entry = new ImportTableEntry(this, idx, true);\n this.imports[idx] = entry;\n return new RpcImportHook(\n /*isPromise=*/\n true,\n entry\n );\n }\n getExport(idx) {\n return this.exports[idx]?.hook;\n }\n send(msg) {\n if (this.abortReason !== void 0) {\n return;\n }\n let msgText;\n try {\n msgText = JSON.stringify(msg);\n } catch (err) {\n try {\n this.abort(err);\n } catch (err2) {\n }\n throw err;\n }\n this.transport.send(msgText).catch((err) => this.abort(err, false));\n }\n sendCall(id, path, args) {\n if (this.abortReason) throw this.abortReason;\n let value = ["pipeline", id, path];\n if (args) {\n let devalue = Devaluator.devaluate(args.value, void 0, this, args);\n value.push(devalue[0]);\n }\n this.send(["push", value]);\n let entry = new ImportTableEntry(this, this.imports.length, false);\n this.imports.push(entry);\n return new RpcImportHook(\n /*isPromise=*/\n true,\n entry\n );\n }\n sendMap(id, path, captures, instructions) {\n if (this.abortReason) {\n for (let cap of captures) {\n cap.dispose();\n }\n throw this.abortReason;\n }\n let devaluedCaptures = captures.map((hook) => {\n let importId = this.getImport(hook);\n if (importId !== void 0) {\n return ["import", importId];\n } else {\n return ["export", this.exportStub(hook)];\n }\n });\n let value = ["remap", id, path, devaluedCaptures, instructions];\n this.send(["push", value]);\n let entry = new ImportTableEntry(this, this.imports.length, false);\n this.imports.push(entry);\n return new RpcImportHook(\n /*isPromise=*/\n true,\n entry\n );\n }\n sendPull(id) {\n if (this.abortReason) throw this.abortReason;\n this.send(["pull", id]);\n }\n sendRelease(id, remoteRefcount) {\n if (this.abortReason) return;\n this.send(["release", id, remoteRefcount]);\n delete this.imports[id];\n }\n abort(error, trySendAbortMessage = true) {\n if (this.abortReason !== void 0) return;\n this.cancelReadLoop(error);\n if (trySendAbortMessage) {\n try {\n this.transport.send(JSON.stringify(["abort", Devaluator.devaluate(error, void 0, this)])).catch((err) => {\n });\n } catch (err) {\n }\n }\n if (error === void 0) {\n error = "undefined";\n }\n this.abortReason = error;\n if (this.onBatchDone) {\n this.onBatchDone.reject(error);\n }\n if (this.transport.abort) {\n try {\n this.transport.abort(error);\n } catch (err) {\n Promise.resolve(err);\n }\n }\n for (let i in this.onBrokenCallbacks) {\n try {\n this.onBrokenCallbacks[i](error);\n } catch (err) {\n Promise.resolve(err);\n }\n }\n for (let i in this.imports) {\n this.imports[i].abort(error);\n }\n for (let i in this.exports) {\n this.exports[i].hook.dispose();\n }\n }\n async readLoop(abortPromise) {\n while (!this.abortReason) {\n let msg = JSON.parse(await Promise.race([this.transport.receive(), abortPromise]));\n if (this.abortReason) break;\n if (msg instanceof Array) {\n switch (msg[0]) {\n case "push":\n if (msg.length > 1) {\n let payload = new Evaluator(this).evaluate(msg[1]);\n let hook = new PayloadStubHook(payload);\n hook.ignoreUnhandledRejections();\n this.exports.push({ hook, refcount: 1 });\n continue;\n }\n break;\n case "pull": {\n let exportId = msg[1];\n if (typeof exportId == "number") {\n this.ensureResolvingExport(exportId);\n continue;\n }\n break;\n }\n case "resolve":\n // ["resolve", ExportId, Expression]\n case "reject": {\n let importId = msg[1];\n if (typeof importId == "number" && msg.length > 2) {\n let imp = this.imports[importId];\n if (imp) {\n if (msg[0] == "resolve") {\n imp.resolve(new PayloadStubHook(new Evaluator(this).evaluate(msg[2])));\n } else {\n let payload = new Evaluator(this).evaluate(msg[2]);\n payload.dispose();\n imp.resolve(new ErrorStubHook(payload.value));\n }\n } else {\n if (msg[0] == "resolve") {\n new Evaluator(this).evaluate(msg[2]).dispose();\n }\n }\n continue;\n }\n break;\n }\n case "release": {\n let exportId = msg[1];\n let refcount = msg[2];\n if (typeof exportId == "number" && typeof refcount == "number") {\n this.releaseExport(exportId, refcount);\n continue;\n }\n break;\n }\n case "abort": {\n let payload = new Evaluator(this).evaluate(msg[1]);\n payload.dispose();\n this.abort(payload, false);\n break;\n }\n }\n }\n throw new Error(`bad RPC message: ${JSON.stringify(msg)}`);\n }\n }\n async drain() {\n if (this.abortReason) {\n throw this.abortReason;\n }\n if (this.pullCount > 0) {\n let { promise, resolve, reject } = Promise.withResolvers();\n this.onBatchDone = { resolve, reject };\n await promise;\n }\n }\n getStats() {\n let result = { imports: 0, exports: 0 };\n for (let i in this.imports) {\n ++result.imports;\n }\n for (let i in this.exports) {\n ++result.exports;\n }\n return result;\n }\n};\nvar RpcSession = class {\n #session;\n #mainStub;\n constructor(transport, localMain, options = {}) {\n let mainHook;\n if (localMain) {\n mainHook = new PayloadStubHook(RpcPayload.fromAppReturn(localMain));\n } else {\n mainHook = new ErrorStubHook(new Error("This connection has no main object."));\n }\n this.#session = new RpcSessionImpl(transport, mainHook, options);\n this.#mainStub = new RpcStub(this.#session.getMainImport());\n }\n getRemoteMain() {\n return this.#mainStub;\n }\n getStats() {\n return this.#session.getStats();\n }\n drain() {\n return this.#session.drain();\n }\n};\nvar RpcSession2 = RpcSession;\n\n// src/stream-transport.ts\nfunction concatBuffers(a, b) {\n const result = new Uint8Array(a.length + b.length);\n result.set(a, 0);\n result.set(b, a.length);\n return result;\n}\nvar BufferedReader = class {\n buffer;\n reader;\n constructor(input) {\n this.buffer = new Uint8Array(0);\n this.reader = input.getReader();\n }\n async read(numberOfBytes) {\n if (numberOfBytes <= 0) {\n throw new Error("numberOfBytes must be positive");\n }\n while (this.buffer.length < numberOfBytes) {\n const result2 = await this.reader.read();\n if (result2.done || result2.value == null) {\n throw new Error("Stream closed");\n }\n this.buffer = concatBuffers(this.buffer, result2.value);\n }\n const result = this.buffer.slice(0, numberOfBytes);\n this.buffer = this.buffer.slice(numberOfBytes);\n return result;\n }\n};\nvar StreamTransport = class {\n constructor(input, output) {\n this.input = input;\n this.output = output;\n this.bufferReader = new BufferedReader(input);\n this.writer = output.getWriter();\n }\n bufferReader;\n writer;\n async send(message) {\n const encoder = new TextEncoder();\n const messageBytes = encoder.encode(message);\n const length = messageBytes.length;\n if (length > 4294967295) {\n throw new Error("Message length exceeds maximum allowed size (4GB)");\n }\n const lengthBytes = new Uint8Array(4);\n const view = new DataView(lengthBytes.buffer);\n view.setUint32(0, length, true);\n const combined = new Uint8Array(4 + length);\n combined.set(lengthBytes, 0);\n combined.set(messageBytes, 4);\n await this.writer.write(combined);\n }\n async receive() {\n const lengthBytes = await this.bufferReader.read(4);\n const lengthBuffer = new Uint8Array(lengthBytes).buffer;\n const length = new DataView(lengthBuffer).getUint32(0, true);\n if (length > 100 * 1024 * 1024) {\n throw new Error("Message length exceeds maximum allowed size");\n }\n if (length === 0) {\n return "";\n }\n const messageBytes = await this.bufferReader.read(length);\n const decoder = new TextDecoder();\n return decoder.decode(messageBytes);\n }\n abort(reason) {\n this.input.cancel(reason).catch(() => {\n });\n this.writer.close().catch(() => {\n });\n }\n};\n\n// src/code-mode-runtime.ts\nsetGlobalRpcSessionOptions(() => ({ recordReplayMode: "all" }));\nasync function run(context) {\n const transport = new StreamTransport(context.input, context.output);\n try {\n const session = new RpcSession2(transport);\n const api = session.getRemoteMain();\n const code = await api.__code__();\n const fn = new Function("api", `return (${code})(api)`);\n const result = await fn(api);\n await api.__return__(result);\n } finally {\n transport.abort("done");\n }\n}\nasync function main() {\n if (!__SANDBOX_CONTEXT_PROMISE__) {\n throw new TypeError("__SANDBOX_CONTEXT_PROMISE__ was not replaced prior to execution.");\n }\n const ctx = await __SANDBOX_CONTEXT_PROMISE__;\n const { input, output, onSuccess, onFailure } = ctx;\n return run({ input, output }).then(() => {\n onSuccess();\n }).catch((err) => {\n console.error("runtime error", err);\n onFailure();\n });\n}\nmain();\n';
|
|
2678
53
|
function concatBuffers(a, b) {
|
|
2679
54
|
const result = new Uint8Array(a.length + b.length);
|
|
2680
55
|
result.set(a, 0);
|
|
2681
56
|
result.set(b, a.length);
|
|
2682
57
|
return result;
|
|
2683
58
|
}
|
|
2684
|
-
|
|
59
|
+
class BufferedReader {
|
|
2685
60
|
buffer;
|
|
2686
61
|
reader;
|
|
2687
62
|
constructor(input) {
|
|
@@ -2703,8 +78,8 @@ var BufferedReader = class {
|
|
|
2703
78
|
this.buffer = this.buffer.slice(numberOfBytes);
|
|
2704
79
|
return result;
|
|
2705
80
|
}
|
|
2706
|
-
}
|
|
2707
|
-
|
|
81
|
+
}
|
|
82
|
+
class StreamTransport {
|
|
2708
83
|
constructor(input, output) {
|
|
2709
84
|
this.input = input;
|
|
2710
85
|
this.output = output;
|
|
@@ -2748,160 +123,8 @@ var StreamTransport = class {
|
|
|
2748
123
|
this.writer.close().catch(() => {
|
|
2749
124
|
});
|
|
2750
125
|
}
|
|
2751
|
-
};
|
|
2752
|
-
|
|
2753
|
-
// src/tool-wrapper.ts
|
|
2754
|
-
import { asSchema } from "ai";
|
|
2755
|
-
import camelCase from "camelcase";
|
|
2756
|
-
import { validate as validate2 } from "json-schema";
|
|
2757
|
-
import { compile as compileJsonSchemaToTs } from "json-schema-to-typescript";
|
|
2758
|
-
import invariant from "tiny-invariant";
|
|
2759
|
-
import { zodToJsonSchema } from "zod-to-json-schema";
|
|
2760
|
-
|
|
2761
|
-
// src/rpc-toolset.ts
|
|
2762
|
-
import { inspect } from "node:util";
|
|
2763
|
-
var validate = (schema, value) => {
|
|
2764
|
-
if ("~standard" in schema) {
|
|
2765
|
-
const validation = schema["~standard"].validate(value);
|
|
2766
|
-
if (validation instanceof Promise) {
|
|
2767
|
-
throw new TypeError(`Validation must be synchronous`);
|
|
2768
|
-
}
|
|
2769
|
-
if (validation.issues) {
|
|
2770
|
-
throw new Error(`Invalid value: ${validation.issues.map((e) => e.message).join(", ")}`);
|
|
2771
|
-
}
|
|
2772
|
-
} else {
|
|
2773
|
-
if (!schema(value)) {
|
|
2774
|
-
throw new Error(`Invalid value: ${inspect(value)} (expected ${schema.name || schema.toString()})`);
|
|
2775
|
-
}
|
|
2776
|
-
}
|
|
2777
|
-
};
|
|
2778
|
-
var toolMetadataKey = /* @__PURE__ */ Symbol("toolMetadata");
|
|
2779
|
-
var setToolMetadata = (target, metadata) => {
|
|
2780
|
-
const meta = target;
|
|
2781
|
-
meta[toolMetadataKey] = {
|
|
2782
|
-
...meta[toolMetadataKey],
|
|
2783
|
-
...metadata
|
|
2784
|
-
};
|
|
2785
|
-
};
|
|
2786
|
-
function toolDef(inputSchema) {
|
|
2787
|
-
return (target, context) => {
|
|
2788
|
-
if (context.kind !== "method") {
|
|
2789
|
-
throw new Error(`Tool decorator can only be used on methods`);
|
|
2790
|
-
}
|
|
2791
|
-
const methodName = String(context.name);
|
|
2792
|
-
const replacementMethod = function(...args) {
|
|
2793
|
-
const expectedArgs = inputSchema ? 1 : 0;
|
|
2794
|
-
if (args.length > expectedArgs) {
|
|
2795
|
-
throw new Error(`Tool ${methodName} got too many arguments: ${args.length} provided (expected ${expectedArgs})`);
|
|
2796
|
-
}
|
|
2797
|
-
if (inputSchema) {
|
|
2798
|
-
const arg = args[0];
|
|
2799
|
-
validate(inputSchema, arg);
|
|
2800
|
-
return target.call(this, arg);
|
|
2801
|
-
} else {
|
|
2802
|
-
return target.call(this);
|
|
2803
|
-
}
|
|
2804
|
-
};
|
|
2805
|
-
setToolMetadata(replacementMethod, { runtimeValidationEnabled: true });
|
|
2806
|
-
return replacementMethod;
|
|
2807
|
-
};
|
|
2808
|
-
}
|
|
2809
|
-
function toolUnsafeNoValidation() {
|
|
2810
|
-
return (target, context) => {
|
|
2811
|
-
if (context.kind !== "method") {
|
|
2812
|
-
throw new Error(`Tool decorator can only be used on methods`);
|
|
2813
|
-
}
|
|
2814
|
-
setToolMetadata(target, { runtimeValidationEnabled: true });
|
|
2815
|
-
return target;
|
|
2816
|
-
};
|
|
2817
|
-
}
|
|
2818
|
-
var callbackMetadataKey = /* @__PURE__ */ Symbol("callbackMetadata");
|
|
2819
|
-
function callbackTool() {
|
|
2820
|
-
return (target, context) => {
|
|
2821
|
-
if (context.kind !== "method") {
|
|
2822
|
-
throw new Error(`Tool decorator can only be used on methods`);
|
|
2823
|
-
}
|
|
2824
|
-
const methodName = String(context.name);
|
|
2825
|
-
const replacementMethod = function(...args) {
|
|
2826
|
-
if (args.length !== 1) {
|
|
2827
|
-
throw new Error(`Tool ${methodName} got too many arguments: ${args.length} provided (expected 1)`);
|
|
2828
|
-
}
|
|
2829
|
-
const callback = args[0];
|
|
2830
|
-
if (typeof callback !== "function") {
|
|
2831
|
-
throw new TypeError(`Callback for tool ${methodName} must be a function`);
|
|
2832
|
-
}
|
|
2833
|
-
const callbackWrapped = (() => {
|
|
2834
|
-
throw new Error(`Callback for tool ${methodName} must be wrapped with \`tool.unwrapCallback\``);
|
|
2835
|
-
});
|
|
2836
|
-
callbackWrapped[callbackMetadataKey] = {
|
|
2837
|
-
callback
|
|
2838
|
-
};
|
|
2839
|
-
return target.call(this, callbackWrapped);
|
|
2840
|
-
};
|
|
2841
|
-
setToolMetadata(replacementMethod, { runtimeValidationEnabled: true });
|
|
2842
|
-
return replacementMethod;
|
|
2843
|
-
};
|
|
2844
126
|
}
|
|
2845
|
-
|
|
2846
|
-
const callback = callbackMetadataKey in toolCallback ? toolCallback[callbackMetadataKey].callback : toolCallback;
|
|
2847
|
-
let isPromise = false;
|
|
2848
|
-
try {
|
|
2849
|
-
const result = callback(arg);
|
|
2850
|
-
if (result instanceof Promise) {
|
|
2851
|
-
isPromise = true;
|
|
2852
|
-
let ret;
|
|
2853
|
-
ret = result.then(async (r) => {
|
|
2854
|
-
validate(returnSchema, r);
|
|
2855
|
-
return then(r);
|
|
2856
|
-
}, opts?.catch);
|
|
2857
|
-
if (opts?.finally) {
|
|
2858
|
-
ret = ret.finally(opts.finally);
|
|
2859
|
-
}
|
|
2860
|
-
return ret;
|
|
2861
|
-
}
|
|
2862
|
-
validate(returnSchema, result);
|
|
2863
|
-
return then(result);
|
|
2864
|
-
} catch (error) {
|
|
2865
|
-
if (opts?.catch) {
|
|
2866
|
-
return opts.catch(error);
|
|
2867
|
-
}
|
|
2868
|
-
throw error;
|
|
2869
|
-
} finally {
|
|
2870
|
-
if (!isPromise) {
|
|
2871
|
-
opts?.finally?.();
|
|
2872
|
-
}
|
|
2873
|
-
}
|
|
2874
|
-
};
|
|
2875
|
-
var tool = toolDef;
|
|
2876
|
-
tool.callback = callbackTool;
|
|
2877
|
-
tool.unwrap = unwrapCallback;
|
|
2878
|
-
tool.unsafeNoValidation = toolUnsafeNoValidation;
|
|
2879
|
-
var RpcToolset = class _RpcToolset extends RpcTarget4 {
|
|
2880
|
-
constructor() {
|
|
2881
|
-
super();
|
|
2882
|
-
let prototype = Object.getPrototypeOf(this);
|
|
2883
|
-
while (prototype !== null && prototype !== _RpcToolset.prototype) {
|
|
2884
|
-
for (const key of Object.getOwnPropertyNames(prototype)) {
|
|
2885
|
-
if (key === "constructor") {
|
|
2886
|
-
continue;
|
|
2887
|
-
}
|
|
2888
|
-
const descriptor = Object.getOwnPropertyDescriptor(prototype, key);
|
|
2889
|
-
const fn = descriptor?.value ?? descriptor?.get;
|
|
2890
|
-
if (!fn || typeof fn !== "function") {
|
|
2891
|
-
throw new Error(`RpcToolset prototype must be methods or getters: ${key} is not`);
|
|
2892
|
-
}
|
|
2893
|
-
const meta = fn;
|
|
2894
|
-
if (!meta[toolMetadataKey]?.runtimeValidationEnabled) {
|
|
2895
|
-
throw new Error(`Prototype method \`${key}\` is not a tool. Did you forget to use the @tool decorator?`);
|
|
2896
|
-
}
|
|
2897
|
-
}
|
|
2898
|
-
prototype = Object.getPrototypeOf(prototype);
|
|
2899
|
-
}
|
|
2900
|
-
}
|
|
2901
|
-
};
|
|
2902
|
-
|
|
2903
|
-
// src/tool-wrapper.ts
|
|
2904
|
-
var extractTypeBody = (interfaceCode) => {
|
|
127
|
+
const extractTypeBody = (interfaceCode) => {
|
|
2905
128
|
const match = interfaceCode.match(/interface \w+ \{([\s\S]*)\}/);
|
|
2906
129
|
if (!match) {
|
|
2907
130
|
return "object";
|
|
@@ -2916,7 +139,7 @@ var extractTypeBody = (interfaceCode) => {
|
|
|
2916
139
|
const formatted = lines.join("; ").replace(/;+/g, ";");
|
|
2917
140
|
return `{ ${formatted} }`;
|
|
2918
141
|
};
|
|
2919
|
-
|
|
142
|
+
const getJsonSchema = (schema) => {
|
|
2920
143
|
if (schema != null && typeof schema === "object" && ("_def" in schema || "parse" in schema && "safeParse" in schema && "shape" in schema)) {
|
|
2921
144
|
try {
|
|
2922
145
|
return zodToJsonSchema(schema);
|
|
@@ -2929,21 +152,21 @@ var getJsonSchema = (schema) => {
|
|
|
2929
152
|
async function* generateToolTypes(tools, name) {
|
|
2930
153
|
yield `class ${name} {`;
|
|
2931
154
|
const toolEntries = Array.isArray(tools) ? tools.map(
|
|
2932
|
-
(
|
|
2933
|
-
|
|
2934
|
-
|
|
155
|
+
(tool, index) => [
|
|
156
|
+
tool.title ?? `tool_${index}`,
|
|
157
|
+
tool
|
|
2935
158
|
]
|
|
2936
159
|
) : Object.entries(tools);
|
|
2937
|
-
for (const [toolName,
|
|
2938
|
-
if (typeof
|
|
2939
|
-
const toolset =
|
|
160
|
+
for (const [toolName, tool] of toolEntries) {
|
|
161
|
+
if (typeof tool === "function") {
|
|
162
|
+
const toolset = tool();
|
|
2940
163
|
yield `// \`RpcToolset\`: ${toolName} (see .d.ts below for methods)`;
|
|
2941
164
|
yield ` ${toolName}: () => RpcPromise<${toolset.constructor.name}>`;
|
|
2942
165
|
continue;
|
|
2943
166
|
}
|
|
2944
|
-
const inputSchema = getJsonSchema(
|
|
2945
|
-
const outputSchema =
|
|
2946
|
-
const inputJsonType = await
|
|
167
|
+
const inputSchema = getJsonSchema(tool.inputSchema);
|
|
168
|
+
const outputSchema = tool.outputSchema ? getJsonSchema(tool.outputSchema) : null;
|
|
169
|
+
const inputJsonType = await compile(
|
|
2947
170
|
inputSchema,
|
|
2948
171
|
`${camelCase(toolName, { pascalCase: true })}Input`,
|
|
2949
172
|
{
|
|
@@ -2951,7 +174,7 @@ async function* generateToolTypes(tools, name) {
|
|
|
2951
174
|
bannerComment: " "
|
|
2952
175
|
}
|
|
2953
176
|
);
|
|
2954
|
-
const outputJsonType = outputSchema ? await
|
|
177
|
+
const outputJsonType = outputSchema ? await compile(
|
|
2955
178
|
outputSchema,
|
|
2956
179
|
`${camelCase(toolName, { pascalCase: true })}Output`,
|
|
2957
180
|
{
|
|
@@ -2961,7 +184,7 @@ async function* generateToolTypes(tools, name) {
|
|
|
2961
184
|
) : null;
|
|
2962
185
|
const inputTypeBody = extractTypeBody(inputJsonType);
|
|
2963
186
|
const outputTypeBody = outputJsonType ? extractTypeBody(outputJsonType) : "object";
|
|
2964
|
-
const description =
|
|
187
|
+
const description = tool.description?.trim() ?? "";
|
|
2965
188
|
const toolDoc = description ? `
|
|
2966
189
|
/**
|
|
2967
190
|
* ${description}
|
|
@@ -2973,8 +196,8 @@ async function* generateToolTypes(tools, name) {
|
|
|
2973
196
|
|
|
2974
197
|
export default ${name};`;
|
|
2975
198
|
}
|
|
2976
|
-
|
|
2977
|
-
class ToolApi extends
|
|
199
|
+
const generateToolApi = (tools, opts) => {
|
|
200
|
+
class ToolApi extends RpcTarget {
|
|
2978
201
|
__return_value__ = null;
|
|
2979
202
|
__raw_code__;
|
|
2980
203
|
constructor(code) {
|
|
@@ -2989,48 +212,36 @@ var generateToolApi = (tools, opts) => {
|
|
|
2989
212
|
}
|
|
2990
213
|
}
|
|
2991
214
|
const toolEntries = Array.isArray(tools) ? tools.map(
|
|
2992
|
-
(
|
|
2993
|
-
|
|
2994
|
-
|
|
215
|
+
(tool, index) => [
|
|
216
|
+
tool.title ?? `tool_${index}`,
|
|
217
|
+
tool
|
|
2995
218
|
]
|
|
2996
219
|
) : Object.entries(tools);
|
|
2997
|
-
for (const [toolName,
|
|
220
|
+
for (const [toolName, tool] of toolEntries) {
|
|
2998
221
|
ToolApi.prototype[toolName] = async function(...args) {
|
|
2999
|
-
if (typeof
|
|
3000
|
-
const toolset =
|
|
222
|
+
if (typeof tool === "function") {
|
|
223
|
+
const toolset = tool();
|
|
3001
224
|
invariant(toolset instanceof RpcToolset, "Tool must return an instance of RpcToolset");
|
|
3002
225
|
return toolset;
|
|
3003
226
|
}
|
|
3004
227
|
if (args.length !== 1) {
|
|
3005
228
|
throw new Error(`Tool ${toolName} only accepts exactly one argument, but ${args.length} were provided`);
|
|
3006
229
|
}
|
|
3007
|
-
const schema = asSchema(
|
|
230
|
+
const schema = asSchema(tool.inputSchema);
|
|
3008
231
|
const jsonSchema = await schema.jsonSchema;
|
|
3009
|
-
const validation =
|
|
232
|
+
const validation = validate(args[0], jsonSchema);
|
|
3010
233
|
if (!validation.valid) {
|
|
3011
234
|
throw new Error(`Invalid arguments for tool ${toolName}: ${validation.errors.map((e) => e.message || e.property).join(", ")}`);
|
|
3012
235
|
}
|
|
3013
|
-
if (!
|
|
236
|
+
if (!tool.execute) {
|
|
3014
237
|
throw new Error(`Tool ${toolName} does not have an execute function`);
|
|
3015
238
|
}
|
|
3016
|
-
return
|
|
239
|
+
return tool.execute(args[0], opts);
|
|
3017
240
|
};
|
|
3018
241
|
}
|
|
3019
242
|
return ToolApi;
|
|
3020
243
|
};
|
|
3021
|
-
|
|
3022
|
-
// src/code-mode.ts
|
|
3023
|
-
var _BUNDLED_RUNTIME_CODE;
|
|
3024
|
-
function getBundledRuntimeCode() {
|
|
3025
|
-
if (_BUNDLED_RUNTIME_CODE === void 0) {
|
|
3026
|
-
_BUNDLED_RUNTIME_CODE = readFileSync(
|
|
3027
|
-
fileURLToPath(new URL("../dist/code-mode-runtime.mjs", import.meta.url)),
|
|
3028
|
-
"utf-8"
|
|
3029
|
-
);
|
|
3030
|
-
}
|
|
3031
|
-
return _BUNDLED_RUNTIME_CODE;
|
|
3032
|
-
}
|
|
3033
|
-
var CodeMode = class {
|
|
244
|
+
class CodeMode {
|
|
3034
245
|
constructor(context) {
|
|
3035
246
|
this.context = context;
|
|
3036
247
|
}
|
|
@@ -3041,8 +252,8 @@ var CodeMode = class {
|
|
|
3041
252
|
}
|
|
3042
253
|
const definitions = typeDefinitions.join("");
|
|
3043
254
|
return {
|
|
3044
|
-
description: `
|
|
3045
|
-
|
|
255
|
+
description: `Execute code using the following API. You MUST call this tool to run any code - never output code directly in your response.
|
|
256
|
+
|
|
3046
257
|
\`\`\`typescript
|
|
3047
258
|
${definitions}
|
|
3048
259
|
|
|
@@ -3053,12 +264,13 @@ var CodeMode = class {
|
|
|
3053
264
|
${dts ? `// .d.ts for the \`RpcToolset\`s:
|
|
3054
265
|
${dts}` : ""}
|
|
3055
266
|
|
|
3056
|
-
|
|
3057
|
-
|
|
3058
|
-
|
|
3059
|
-
|
|
3060
|
-
|
|
3061
|
-
|
|
267
|
+
Provide a valid **javascript** (NOT TypeScript) function taking a single argument of type \`Tools\` and returning
|
|
268
|
+
a value of type \`Promise<Returnable>\`.
|
|
269
|
+
|
|
270
|
+
Example:
|
|
271
|
+
\`\`\`javascript
|
|
272
|
+
(api) => {
|
|
273
|
+
// Call the API here (only vanilla JS is allowed)
|
|
3062
274
|
// The returned result will be passed back into context
|
|
3063
275
|
}
|
|
3064
276
|
\`\`\`
|
|
@@ -3067,531 +279,25 @@ ${dts}` : ""}
|
|
|
3067
279
|
code: z.string()
|
|
3068
280
|
}),
|
|
3069
281
|
execute: async ({ code }, opts) => {
|
|
3070
|
-
const injectedCode = `globalThis.__SANDBOX_CONTEXT_PROMISE__ = ${this.context.sandboxContext};
|
|
3071
|
-
${getBundledRuntimeCode()}`;
|
|
3072
|
-
const { input, output, wait } = await this.context.safeEval(injectedCode);
|
|
3073
282
|
const ToolApi = generateToolApi(tools, opts);
|
|
3074
283
|
const api = new ToolApi(code);
|
|
284
|
+
if (this.context.kind === "rpc") {
|
|
285
|
+
return await this.context.safeEval(code, api);
|
|
286
|
+
}
|
|
287
|
+
const injectedCode = `globalThis.__SANDBOX_CONTEXT_PROMISE__ = ${this.context.sandboxContext};
|
|
288
|
+
${runtimeCode}`;
|
|
289
|
+
const { input, output, wait } = await this.context.safeEval(injectedCode);
|
|
3075
290
|
const transport = new StreamTransport(input, output);
|
|
3076
|
-
|
|
291
|
+
new RpcSession(transport, api);
|
|
3077
292
|
await wait();
|
|
3078
293
|
return api.__return_value__;
|
|
3079
294
|
}
|
|
3080
295
|
};
|
|
3081
296
|
}
|
|
3082
|
-
}
|
|
3083
|
-
|
|
3084
|
-
// src/sql/builder.ts
|
|
3085
|
-
import { Kysely } from "kysely";
|
|
3086
|
-
import invariant2 from "tiny-invariant";
|
|
3087
|
-
import z3 from "zod";
|
|
3088
|
-
|
|
3089
|
-
// src/sql/expression.ts
|
|
3090
|
-
import z2 from "zod";
|
|
3091
|
-
|
|
3092
|
-
// src/sql/sql.ts
|
|
3093
|
-
import { sql as kyselySql } from "kysely";
|
|
3094
|
-
var sql = kyselySql;
|
|
3095
|
-
var buildSql = (parts, separator = kyselySql` `) => {
|
|
3096
|
-
return kyselySql.join(parts.filter((x) => x != null), separator);
|
|
3097
|
-
};
|
|
3098
|
-
|
|
3099
|
-
// src/sql/expression.ts
|
|
3100
|
-
var asSqlExpression = (value) => {
|
|
3101
|
-
return value instanceof SqlExpression ? value : new LiteralExpression(value);
|
|
3102
|
-
};
|
|
3103
|
-
var isSqlExpressionIn = (value) => {
|
|
3104
|
-
return typeof value === "number" || typeof value === "string" || typeof value === "boolean" || value === null || value === void 0 || value instanceof SqlExpression;
|
|
3105
|
-
};
|
|
3106
|
-
var zSqlExpression = z2.custom((val) => val instanceof SqlExpression);
|
|
3107
|
-
var zNumericSqlExpression = z2.union([zSqlExpression, z2.number(), z2.string()]);
|
|
3108
|
-
var zSqlExpressionIn = z2.union([zSqlExpression, z2.number(), z2.string(), z2.boolean(), z2.null()]);
|
|
3109
|
-
var _desc_dec, _asc_dec, ___dec, ___dec2, ___dec3, ___dec4, ___dec5, _NOT_LIKE_dec, _LIKE_dec, ____dec, ____dec2, ___dec6, ____dec3, ___dec7, ____dec4, ___dec8, _isNotNull_dec, _isNull_dec, _not_dec, _and_dec, _or_dec, _a, _init;
|
|
3110
|
-
var SqlExpression = class extends (_a = RpcToolset, _or_dec = [tool(zSqlExpression)], _and_dec = [tool(zSqlExpression)], _not_dec = [tool()], _isNull_dec = [tool()], _isNotNull_dec = [tool()], ___dec8 = [tool(zNumericSqlExpression)], ____dec4 = [tool(zNumericSqlExpression)], ___dec7 = [tool(zNumericSqlExpression)], ____dec3 = [tool(zNumericSqlExpression)], ___dec6 = [tool(zSqlExpressionIn)], ____dec2 = [tool(zSqlExpressionIn)], ____dec = [tool(zSqlExpressionIn)], _LIKE_dec = [tool(z2.union([zSqlExpression, z2.string()]))], _NOT_LIKE_dec = [tool(z2.union([zSqlExpression, z2.string()]))], ___dec5 = [tool(zNumericSqlExpression)], ___dec4 = [tool(zNumericSqlExpression)], ___dec3 = [tool(zNumericSqlExpression)], ___dec2 = [tool(zNumericSqlExpression)], ___dec = [tool(zNumericSqlExpression)], _asc_dec = [tool()], _desc_dec = [tool()], _a) {
|
|
3111
|
-
constructor(precedence = 100) {
|
|
3112
|
-
super();
|
|
3113
|
-
this.precedence = precedence;
|
|
3114
|
-
__runInitializers(_init, 5, this);
|
|
3115
|
-
// `= () => ` to ensure the method is a direct property of the class instance,
|
|
3116
|
-
// not a method of the class prototype
|
|
3117
|
-
__publicField(this, "compile", () => {
|
|
3118
|
-
throw new Error("Not implemented");
|
|
3119
|
-
});
|
|
3120
|
-
}
|
|
3121
|
-
or(expr) {
|
|
3122
|
-
return new BinaryExpression(this, expr, sql`OR`, 1);
|
|
3123
|
-
}
|
|
3124
|
-
and(expr) {
|
|
3125
|
-
return new BinaryExpression(this, expr, sql`AND`, 2);
|
|
3126
|
-
}
|
|
3127
|
-
not() {
|
|
3128
|
-
return new UnaryExpression(this, sql`NOT`, "prefix", 3);
|
|
3129
|
-
}
|
|
3130
|
-
isNull() {
|
|
3131
|
-
return new UnaryExpression(this, sql`IS NULL`, "postfix", 4);
|
|
3132
|
-
}
|
|
3133
|
-
isNotNull() {
|
|
3134
|
-
return new UnaryExpression(this, sql`IS NOT NULL`, "postfix", 4);
|
|
3135
|
-
}
|
|
3136
|
-
"<"(expr) {
|
|
3137
|
-
return new BinaryExpression(this, asSqlExpression(expr), sql`<`, 5);
|
|
3138
|
-
}
|
|
3139
|
-
"<="(expr) {
|
|
3140
|
-
return new BinaryExpression(this, asSqlExpression(expr), sql`<=`, 5);
|
|
3141
|
-
}
|
|
3142
|
-
">"(expr) {
|
|
3143
|
-
return new BinaryExpression(this, asSqlExpression(expr), sql`>`, 5);
|
|
3144
|
-
}
|
|
3145
|
-
">="(expr) {
|
|
3146
|
-
return new BinaryExpression(this, asSqlExpression(expr), sql`>=`, 5);
|
|
3147
|
-
}
|
|
3148
|
-
"="(expr) {
|
|
3149
|
-
return new BinaryExpression(this, asSqlExpression(expr), sql`=`, 5);
|
|
3150
|
-
}
|
|
3151
|
-
"<>"(expr) {
|
|
3152
|
-
return new BinaryExpression(this, asSqlExpression(expr), sql`<>`, 5);
|
|
3153
|
-
}
|
|
3154
|
-
"!="(expr) {
|
|
3155
|
-
return new BinaryExpression(this, asSqlExpression(expr), sql`!=`, 5);
|
|
3156
|
-
}
|
|
3157
|
-
"LIKE"(expr) {
|
|
3158
|
-
return new BinaryExpression(this, asSqlExpression(expr), sql`LIKE`, 6);
|
|
3159
|
-
}
|
|
3160
|
-
"NOT LIKE"(expr) {
|
|
3161
|
-
return new BinaryExpression(this, asSqlExpression(expr), sql`NOT LIKE`, 6);
|
|
3162
|
-
}
|
|
3163
|
-
"+"(expr) {
|
|
3164
|
-
return new BinaryExpression(this, asSqlExpression(expr), sql`+`, 8);
|
|
3165
|
-
}
|
|
3166
|
-
"-"(expr) {
|
|
3167
|
-
return new BinaryExpression(this, asSqlExpression(expr), sql`-`, 8);
|
|
3168
|
-
}
|
|
3169
|
-
"*"(expr) {
|
|
3170
|
-
return new BinaryExpression(this, asSqlExpression(expr), sql`*`, 9);
|
|
3171
|
-
}
|
|
3172
|
-
"/"(expr) {
|
|
3173
|
-
return new BinaryExpression(this, asSqlExpression(expr), sql`/`, 9);
|
|
3174
|
-
}
|
|
3175
|
-
"%"(expr) {
|
|
3176
|
-
return new BinaryExpression(this, asSqlExpression(expr), sql`%`, 9);
|
|
3177
|
-
}
|
|
3178
|
-
asc() {
|
|
3179
|
-
return new OrderByValue(this, sql`ASC`);
|
|
3180
|
-
}
|
|
3181
|
-
desc() {
|
|
3182
|
-
return new OrderByValue(this, sql`DESC`);
|
|
3183
|
-
}
|
|
3184
|
-
};
|
|
3185
|
-
_init = __decoratorStart(_a);
|
|
3186
|
-
__decorateElement(_init, 1, "or", _or_dec, SqlExpression);
|
|
3187
|
-
__decorateElement(_init, 1, "and", _and_dec, SqlExpression);
|
|
3188
|
-
__decorateElement(_init, 1, "not", _not_dec, SqlExpression);
|
|
3189
|
-
__decorateElement(_init, 1, "isNull", _isNull_dec, SqlExpression);
|
|
3190
|
-
__decorateElement(_init, 1, "isNotNull", _isNotNull_dec, SqlExpression);
|
|
3191
|
-
__decorateElement(_init, 1, "<", ___dec8, SqlExpression);
|
|
3192
|
-
__decorateElement(_init, 1, "<=", ____dec4, SqlExpression);
|
|
3193
|
-
__decorateElement(_init, 1, ">", ___dec7, SqlExpression);
|
|
3194
|
-
__decorateElement(_init, 1, ">=", ____dec3, SqlExpression);
|
|
3195
|
-
__decorateElement(_init, 1, "=", ___dec6, SqlExpression);
|
|
3196
|
-
__decorateElement(_init, 1, "<>", ____dec2, SqlExpression);
|
|
3197
|
-
__decorateElement(_init, 1, "!=", ____dec, SqlExpression);
|
|
3198
|
-
__decorateElement(_init, 1, "LIKE", _LIKE_dec, SqlExpression);
|
|
3199
|
-
__decorateElement(_init, 1, "NOT LIKE", _NOT_LIKE_dec, SqlExpression);
|
|
3200
|
-
__decorateElement(_init, 1, "+", ___dec5, SqlExpression);
|
|
3201
|
-
__decorateElement(_init, 1, "-", ___dec4, SqlExpression);
|
|
3202
|
-
__decorateElement(_init, 1, "*", ___dec3, SqlExpression);
|
|
3203
|
-
__decorateElement(_init, 1, "/", ___dec2, SqlExpression);
|
|
3204
|
-
__decorateElement(_init, 1, "%", ___dec, SqlExpression);
|
|
3205
|
-
__decorateElement(_init, 1, "asc", _asc_dec, SqlExpression);
|
|
3206
|
-
__decorateElement(_init, 1, "desc", _desc_dec, SqlExpression);
|
|
3207
|
-
__decoratorMetadata(_init, SqlExpression);
|
|
3208
|
-
var BinaryExpression = class extends SqlExpression {
|
|
3209
|
-
constructor(left, right, operator, precedence) {
|
|
3210
|
-
super(precedence ?? 100);
|
|
3211
|
-
this.left = left;
|
|
3212
|
-
this.right = right;
|
|
3213
|
-
this.operator = operator;
|
|
3214
|
-
}
|
|
3215
|
-
// `= () => ` to ensure the method is a direct property of the class instance,
|
|
3216
|
-
// not a method of the class prototype
|
|
3217
|
-
compile = () => {
|
|
3218
|
-
const leftCompiled = this.left.compile();
|
|
3219
|
-
const rightCompiled = this.right.compile();
|
|
3220
|
-
return buildSql([
|
|
3221
|
-
this.precedence > this.left.precedence ? sql`(${leftCompiled})` : leftCompiled,
|
|
3222
|
-
this.operator,
|
|
3223
|
-
this.precedence > this.right.precedence ? sql`(${rightCompiled})` : rightCompiled
|
|
3224
|
-
]);
|
|
3225
|
-
};
|
|
3226
|
-
};
|
|
3227
|
-
var UnaryExpression = class extends SqlExpression {
|
|
3228
|
-
constructor(operand, operator, placement, precedence) {
|
|
3229
|
-
super(precedence ?? 100);
|
|
3230
|
-
this.operand = operand;
|
|
3231
|
-
this.operator = operator;
|
|
3232
|
-
this.placement = placement;
|
|
3233
|
-
}
|
|
3234
|
-
// `= () => ` to ensure the method is a direct property of the class instance,
|
|
3235
|
-
// not a method of the class prototype
|
|
3236
|
-
compile = () => {
|
|
3237
|
-
const operandCompiled = this.operand.compile();
|
|
3238
|
-
const wrappedOperand = this.precedence > this.operand.precedence ? sql`(${operandCompiled})` : operandCompiled;
|
|
3239
|
-
return this.placement === "postfix" ? buildSql([wrappedOperand, this.operator]) : buildSql([this.operator, wrappedOperand]);
|
|
3240
|
-
};
|
|
3241
|
-
};
|
|
3242
|
-
var ColumnReferenceExpression = class extends SqlExpression {
|
|
3243
|
-
constructor(alias, column) {
|
|
3244
|
-
super();
|
|
3245
|
-
this.alias = alias;
|
|
3246
|
-
this.column = column;
|
|
3247
|
-
}
|
|
3248
|
-
// `= () => ` to ensure the method is a direct property of the class instance,
|
|
3249
|
-
// not a method of the class prototype
|
|
3250
|
-
compile = () => {
|
|
3251
|
-
return sql.ref(`${this.alias}.${this.column}`);
|
|
3252
|
-
};
|
|
3253
|
-
};
|
|
3254
|
-
var UnboundColumnReferenceExpression = class extends ColumnReferenceExpression {
|
|
3255
|
-
constructor(alias, column) {
|
|
3256
|
-
super(alias, column);
|
|
3257
|
-
this.alias = alias;
|
|
3258
|
-
this.column = column;
|
|
3259
|
-
}
|
|
3260
|
-
// `= () => ` to ensure the method is a direct property of the class instance,
|
|
3261
|
-
// not a method of the class prototype
|
|
3262
|
-
compile = () => {
|
|
3263
|
-
throw new Error("Unbound column reference cannot be compiled");
|
|
3264
|
-
};
|
|
3265
|
-
};
|
|
3266
|
-
var LiteralExpression = class extends SqlExpression {
|
|
3267
|
-
constructor(value) {
|
|
3268
|
-
super();
|
|
3269
|
-
this.value = value;
|
|
3270
|
-
}
|
|
3271
|
-
// `= () => ` to ensure the method is a direct property of the class instance,
|
|
3272
|
-
// not a method of the class prototype
|
|
3273
|
-
compile = () => {
|
|
3274
|
-
return sql`${this.value}`;
|
|
3275
|
-
};
|
|
3276
|
-
};
|
|
3277
|
-
var OrderByValue = class {
|
|
3278
|
-
constructor(value, direction) {
|
|
3279
|
-
this.value = value;
|
|
3280
|
-
this.direction = direction;
|
|
3281
|
-
}
|
|
3282
|
-
};
|
|
3283
|
-
|
|
3284
|
-
// src/sql/builder.ts
|
|
3285
|
-
var safeAliasRegex = /^[a-zA-Z_][a-zA-Z0-9_]*$/;
|
|
3286
|
-
var isSafeAlias = (value) => {
|
|
3287
|
-
return safeAliasRegex.test(value) && !(value === "constructor" || value === "prototype" || value === "__proto__") && !(value in Object.prototype) && value !== "toJSON";
|
|
3288
|
-
};
|
|
3289
|
-
var assertSafeAlias = (value) => {
|
|
3290
|
-
if (!isSafeAlias(value)) {
|
|
3291
|
-
throw new Error(`Alias must be a safe alias: "${value}" does not match the regex ${safeAliasRegex.source}`);
|
|
3292
|
-
}
|
|
3293
|
-
};
|
|
3294
|
-
var asRowLike = (value) => {
|
|
3295
|
-
if (value instanceof TableBase) {
|
|
3296
|
-
return value;
|
|
3297
|
-
}
|
|
3298
|
-
return Object.fromEntries(Object.entries(value).map(([key, value2]) => [key, asSqlExpression(value2)]));
|
|
3299
|
-
};
|
|
3300
|
-
var isRowLikeRawIn = (value) => {
|
|
3301
|
-
return typeof value === "object" && value !== null && (Object.getPrototypeOf(value) === Object.prototype || Object.getPrototypeOf(value) === null) && Object.entries(value).every(([key, value2]) => {
|
|
3302
|
-
assertSafeAlias(key);
|
|
3303
|
-
return typeof key === "string" && isSqlExpressionIn(value2);
|
|
3304
|
-
});
|
|
3305
|
-
};
|
|
3306
|
-
var isRowLikeIn = (value) => {
|
|
3307
|
-
return isRowLikeRawIn(value) || value instanceof TableBase;
|
|
3308
|
-
};
|
|
3309
|
-
var rowLikeRawEntries = (value) => {
|
|
3310
|
-
const entries = [];
|
|
3311
|
-
const myKeys = Object.keys(value);
|
|
3312
|
-
const protoKeys = [];
|
|
3313
|
-
if (value instanceof TableBase) {
|
|
3314
|
-
let proto = Object.getPrototypeOf(value);
|
|
3315
|
-
while (proto != null && proto !== TableBase.prototype) {
|
|
3316
|
-
protoKeys.push(...Object.keys(proto));
|
|
3317
|
-
proto = Object.getPrototypeOf(proto);
|
|
3318
|
-
}
|
|
3319
|
-
}
|
|
3320
|
-
for (const key of /* @__PURE__ */ new Set([...myKeys, ...protoKeys])) {
|
|
3321
|
-
const v = value[key];
|
|
3322
|
-
if (v instanceof SqlExpression) {
|
|
3323
|
-
entries.push([key, v]);
|
|
3324
|
-
}
|
|
3325
|
-
}
|
|
3326
|
-
return entries;
|
|
3327
|
-
};
|
|
3328
|
-
var isTableClass = (value) => {
|
|
3329
|
-
return typeof value === "function" && value.prototype instanceof TableBase;
|
|
3330
|
-
};
|
|
3331
|
-
var isFromItem = (value) => {
|
|
3332
|
-
return value instanceof QueryBuilder || isTableClass(value);
|
|
3333
|
-
};
|
|
3334
|
-
var combinePredicates = (...predicates) => {
|
|
3335
|
-
const filtered = predicates.filter((p) => p != null);
|
|
3336
|
-
if (filtered.length === 0) {
|
|
3337
|
-
return void 0;
|
|
3338
|
-
}
|
|
3339
|
-
return filtered.reduce((acc, predicate) => acc.and(predicate));
|
|
3340
|
-
};
|
|
3341
|
-
var namespacedArg = (tables) => {
|
|
3342
|
-
return Object.fromEntries(Object.entries(tables).map(([k, v]) => [k, v.fromItem.toRowLike()]));
|
|
3343
|
-
};
|
|
3344
|
-
var _execute_dec, _join_dec, _offset_dec, _limit_dec, _orderBy_dec, _where_dec, _select_dec, _a2, _db, _limit, _offset, _init2;
|
|
3345
|
-
var _QueryBuilder = class _QueryBuilder extends (_a2 = RpcToolset, _select_dec = [tool.callback()], _where_dec = [tool.callback()], _orderBy_dec = [tool.callback()], _limit_dec = [tool(z3.number().int().nonnegative())], _offset_dec = [tool(z3.number().int().nonnegative())], _join_dec = [tool.unsafeNoValidation()], _execute_dec = [tool()], _a2) {
|
|
3346
|
-
// set only when created directly from a TableClass
|
|
3347
|
-
constructor(params) {
|
|
3348
|
-
super();
|
|
3349
|
-
__runInitializers(_init2, 5, this);
|
|
3350
|
-
__privateAdd(this, _db);
|
|
3351
|
-
__publicField(this, "alias");
|
|
3352
|
-
__publicField(this, "selectRowLike");
|
|
3353
|
-
__publicField(this, "tables");
|
|
3354
|
-
__publicField(this, "whereExpression");
|
|
3355
|
-
__publicField(this, "orderByExpressions");
|
|
3356
|
-
__privateAdd(this, _limit);
|
|
3357
|
-
__privateAdd(this, _offset);
|
|
3358
|
-
__publicField(this, "arg");
|
|
3359
|
-
__publicField(this, "rawTable");
|
|
3360
|
-
// Note, we use `= () => ` to ensure the method is a direct property of the class instance,
|
|
3361
|
-
// not a method of the class prototype
|
|
3362
|
-
__publicField(this, "paramsForCopy", () => {
|
|
3363
|
-
return {
|
|
3364
|
-
alias: this.alias,
|
|
3365
|
-
tables: this.tables,
|
|
3366
|
-
selectRowLike: this.selectRowLike,
|
|
3367
|
-
whereExpression: this.whereExpression,
|
|
3368
|
-
orderByExpressions: this.orderByExpressions,
|
|
3369
|
-
limit: __privateGet(this, _limit),
|
|
3370
|
-
offset: __privateGet(this, _offset),
|
|
3371
|
-
db: __privateGet(this, _db),
|
|
3372
|
-
// `rawTable` is set only when created directly from a TableClass
|
|
3373
|
-
rawTable: void 0
|
|
3374
|
-
};
|
|
3375
|
-
});
|
|
3376
|
-
__publicField(this, "toRowLike", () => {
|
|
3377
|
-
if (this.selectRowLike instanceof TableBase) {
|
|
3378
|
-
const tableClass = this.selectRowLike.constructor;
|
|
3379
|
-
return tableClass.as(this.alias).toRowLike({ remapColumns: true });
|
|
3380
|
-
}
|
|
3381
|
-
return Object.fromEntries(Object.keys(this.selectRowLike).map((key) => [key, new ColumnReferenceExpression(this.alias, key)]));
|
|
3382
|
-
});
|
|
3383
|
-
__publicField(this, "compile", (opts) => {
|
|
3384
|
-
const { tables, selectRowLike, whereExpression, orderByExpressions } = this;
|
|
3385
|
-
const tablesList = Object.entries(tables);
|
|
3386
|
-
const [[_, baseTable], ...rest] = tablesList.filter(([alias, table2]) => {
|
|
3387
|
-
invariant2(table2.fromItem.alias === alias, `Alias mismatch: ${table2.fromItem.alias} !== ${alias}`);
|
|
3388
|
-
return table2.joinType === null;
|
|
3389
|
-
});
|
|
3390
|
-
const joins = tablesList.filter(([, table2]) => table2.joinType !== null);
|
|
3391
|
-
invariant2(baseTable, "Base table not found");
|
|
3392
|
-
invariant2(rest.length === 0, "Implicit joins not supported");
|
|
3393
|
-
invariant2(Object.keys(selectRowLike).length > 0, "select must return a non-empty row");
|
|
3394
|
-
const combinedWhere = combinePredicates(whereExpression, baseTable.fromItem.onExpression);
|
|
3395
|
-
const result = buildSql([
|
|
3396
|
-
sql`SELECT ${buildSql(rowLikeRawEntries(selectRowLike).map(([key, value]) => sql`${value.compile()} as ${sql.ref(key)}`), sql`, `)}`,
|
|
3397
|
-
sql`FROM ${baseTable.fromItem.compile({ isSubquery: true })}`,
|
|
3398
|
-
...joins.map(([, table2]) => buildSql([table2.joinType === "inner" ? sql`JOIN` : table2.joinType === "left" ? sql`LEFT JOIN` : null, table2.isLateral ? sql`LATERAL` : null, table2.fromItem.compile({ isSubquery: true }), table2.on ? sql`ON ${table2.on.compile()}` : null]), sql` `),
|
|
3399
|
-
combinedWhere ? sql`WHERE ${combinedWhere.compile()}` : null,
|
|
3400
|
-
orderByExpressions && orderByExpressions.length > 0 ? sql`ORDER BY ${buildSql(orderByExpressions.map((expr) => buildSql([expr.value.compile(), expr.direction])), sql`, `)}` : null,
|
|
3401
|
-
__privateGet(this, _limit) != null ? sql`LIMIT ${__privateGet(this, _limit)}` : null,
|
|
3402
|
-
__privateGet(this, _offset) != null ? sql`OFFSET ${__privateGet(this, _offset)}` : null
|
|
3403
|
-
]);
|
|
3404
|
-
return opts?.isSubquery ? sql`(${result}) AS ${sql.ref(this.alias)}` : result;
|
|
3405
|
-
});
|
|
3406
|
-
__privateSet(this, _db, params.db);
|
|
3407
|
-
this.alias = params.alias;
|
|
3408
|
-
this.selectRowLike = params.selectRowLike;
|
|
3409
|
-
this.tables = params.tables;
|
|
3410
|
-
this.whereExpression = params.whereExpression;
|
|
3411
|
-
this.orderByExpressions = params.orderByExpressions;
|
|
3412
|
-
this.arg = namespacedArg(params.tables);
|
|
3413
|
-
__privateSet(this, _limit, params.limit);
|
|
3414
|
-
__privateSet(this, _offset, params.offset);
|
|
3415
|
-
this.rawTable = params.rawTable;
|
|
3416
|
-
}
|
|
3417
|
-
select(select) {
|
|
3418
|
-
const selectUnwrapped = tool.unwrap(select, isRowLikeIn);
|
|
3419
|
-
return selectUnwrapped(this.arg, (result) => {
|
|
3420
|
-
return new _QueryBuilder({ ...this.paramsForCopy(), selectRowLike: asRowLike(result) });
|
|
3421
|
-
});
|
|
3422
|
-
}
|
|
3423
|
-
where(where) {
|
|
3424
|
-
const whereUnwrapped = tool.unwrap(where, isSqlExpressionIn);
|
|
3425
|
-
return whereUnwrapped(this.arg, (result) => {
|
|
3426
|
-
return new _QueryBuilder({ ...this.paramsForCopy(), whereExpression: combinePredicates(this.whereExpression, asSqlExpression(result)) });
|
|
3427
|
-
});
|
|
3428
|
-
}
|
|
3429
|
-
orderBy(orderBy) {
|
|
3430
|
-
const orderByUnwrapped = tool.unwrap(orderBy, (arg) => {
|
|
3431
|
-
if (Array.isArray(arg)) {
|
|
3432
|
-
return arg.every((e) => e instanceof SqlExpression || e instanceof OrderByValue);
|
|
3433
|
-
}
|
|
3434
|
-
return arg instanceof SqlExpression || arg instanceof OrderByValue;
|
|
3435
|
-
});
|
|
3436
|
-
return orderByUnwrapped(this.arg, (raw) => {
|
|
3437
|
-
const rawArray = Array.isArray(raw) ? raw : [raw];
|
|
3438
|
-
const exprs = rawArray.map((e) => {
|
|
3439
|
-
invariant2(e instanceof SqlExpression || e instanceof OrderByValue, "orderBy must return a SqlExpression/OrderByValue or an array of SqlExpressions/OrderByValues");
|
|
3440
|
-
return e instanceof SqlExpression ? new OrderByValue(e) : e;
|
|
3441
|
-
});
|
|
3442
|
-
return new _QueryBuilder({ ...this.paramsForCopy(), orderByExpressions: (this.orderByExpressions ?? []).concat(exprs) });
|
|
3443
|
-
});
|
|
3444
|
-
}
|
|
3445
|
-
limit(limit) {
|
|
3446
|
-
invariant2(typeof limit === "number" && limit >= 0, "limit must be greater than or equal to 0");
|
|
3447
|
-
return new _QueryBuilder({ ...this.paramsForCopy(), limit: Math.min(limit, __privateGet(this, _limit) ?? Infinity) });
|
|
3448
|
-
}
|
|
3449
|
-
offset(offset) {
|
|
3450
|
-
invariant2(typeof offset === "number" && offset >= 0, "offset must be greater than or equal to 0");
|
|
3451
|
-
return new _QueryBuilder({ ...this.paramsForCopy(), offset: (__privateGet(this, _offset) ?? 0) + offset });
|
|
3452
|
-
}
|
|
3453
|
-
join(fromItem, on) {
|
|
3454
|
-
const fromItemCallbackRaw = isFromItem(fromItem) ? () => fromItem : fromItem;
|
|
3455
|
-
const fromItemCallback = tool.unwrap(fromItemCallbackRaw, isFromItem);
|
|
3456
|
-
const res = fromItemCallback(this.arg, (fromItemResolved) => {
|
|
3457
|
-
if (fromItemResolved instanceof _QueryBuilder && fromItemResolved.rawTable) {
|
|
3458
|
-
fromItemResolved = fromItemResolved.rawTable;
|
|
3459
|
-
}
|
|
3460
|
-
const alias = fromItemResolved.alias;
|
|
3461
|
-
if (this.tables[alias]) {
|
|
3462
|
-
throw new Error(`Join already exists: ${alias} in ${Object.keys(this.tables)}`);
|
|
3463
|
-
}
|
|
3464
|
-
const arg = {
|
|
3465
|
-
...this.arg,
|
|
3466
|
-
[alias]: fromItemResolved.toRowLike()
|
|
3467
|
-
};
|
|
3468
|
-
const onCallback = tool.unwrap(on ?? (() => void 0), (raw) => raw === void 0 || isSqlExpressionIn(raw));
|
|
3469
|
-
return onCallback(arg, (onRaw) => {
|
|
3470
|
-
const onResolved = combinePredicates(onRaw !== void 0 ? asSqlExpression(onRaw) : void 0, fromItemResolved.onExpression);
|
|
3471
|
-
invariant2(onResolved != null, "Must specify an `on` expression or use `Table.on` to set the on expression");
|
|
3472
|
-
invariant2(onResolved instanceof SqlExpression, "on must return a SqlExpression");
|
|
3473
|
-
const tablesWithAlias = {
|
|
3474
|
-
...this.tables,
|
|
3475
|
-
[alias]: {
|
|
3476
|
-
fromItem: fromItemResolved,
|
|
3477
|
-
on: onResolved,
|
|
3478
|
-
joinType: "inner",
|
|
3479
|
-
// If `fromItem` is a function that returns a QueryBuilder, it is implicitly a lateral join (depends on the other tables)
|
|
3480
|
-
isLateral: !isFromItem(fromItem) && fromItemResolved instanceof _QueryBuilder
|
|
3481
|
-
}
|
|
3482
|
-
};
|
|
3483
|
-
return new _QueryBuilder({ ...this.paramsForCopy(), tables: tablesWithAlias });
|
|
3484
|
-
});
|
|
3485
|
-
});
|
|
3486
|
-
return res;
|
|
3487
|
-
}
|
|
3488
|
-
async execute() {
|
|
3489
|
-
return await __privateGet(this, _db).execute(this.compile());
|
|
3490
|
-
}
|
|
3491
|
-
};
|
|
3492
|
-
_init2 = __decoratorStart(_a2);
|
|
3493
|
-
_db = new WeakMap();
|
|
3494
|
-
_limit = new WeakMap();
|
|
3495
|
-
_offset = new WeakMap();
|
|
3496
|
-
__decorateElement(_init2, 1, "select", _select_dec, _QueryBuilder);
|
|
3497
|
-
__decorateElement(_init2, 1, "where", _where_dec, _QueryBuilder);
|
|
3498
|
-
__decorateElement(_init2, 1, "orderBy", _orderBy_dec, _QueryBuilder);
|
|
3499
|
-
__decorateElement(_init2, 1, "limit", _limit_dec, _QueryBuilder);
|
|
3500
|
-
__decorateElement(_init2, 1, "offset", _offset_dec, _QueryBuilder);
|
|
3501
|
-
__decorateElement(_init2, 1, "join", _join_dec, _QueryBuilder);
|
|
3502
|
-
__decorateElement(_init2, 1, "execute", _execute_dec, _QueryBuilder);
|
|
3503
|
-
__decoratorMetadata(_init2, _QueryBuilder);
|
|
3504
|
-
var QueryBuilder = _QueryBuilder;
|
|
3505
|
-
var TableBase = class extends RpcToolset {
|
|
3506
|
-
opts;
|
|
3507
|
-
// `= () => ` to ensure the method is a direct property of the class instance,
|
|
3508
|
-
// not a method of the class prototype
|
|
3509
|
-
column = function(columnName) {
|
|
3510
|
-
const cls = this.constructor;
|
|
3511
|
-
return new UnboundColumnReferenceExpression(cls.alias ?? cls.tableName, columnName);
|
|
3512
|
-
};
|
|
3513
|
-
};
|
|
3514
|
-
var table = (db, name) => {
|
|
3515
|
-
const { [name]: tableClass } = { [name]: class extends TableBase {
|
|
3516
|
-
static tableName = name;
|
|
3517
|
-
static alias = name;
|
|
3518
|
-
static onExpression;
|
|
3519
|
-
constructor(opts) {
|
|
3520
|
-
super();
|
|
3521
|
-
this.opts = opts;
|
|
3522
|
-
}
|
|
3523
|
-
static from() {
|
|
3524
|
-
const tables = { [this.alias]: { fromItem: this, joinType: null, isLateral: false } };
|
|
3525
|
-
return new QueryBuilder({ db, alias: this.alias, tables, selectRowLike: this.toRowLike(), rawTable: this });
|
|
3526
|
-
}
|
|
3527
|
-
static as(alias) {
|
|
3528
|
-
assertSafeAlias(alias);
|
|
3529
|
-
class Ret extends this {
|
|
3530
|
-
static alias = alias;
|
|
3531
|
-
}
|
|
3532
|
-
return Ret;
|
|
3533
|
-
}
|
|
3534
|
-
static on(on) {
|
|
3535
|
-
const Base = this;
|
|
3536
|
-
return class extends Base {
|
|
3537
|
-
static onExpression = combinePredicates(Base.onExpression, on(Base.toRowLike()));
|
|
3538
|
-
};
|
|
3539
|
-
}
|
|
3540
|
-
// use `function` to bind `this` to the current class instance
|
|
3541
|
-
static toRowLike = function(opts) {
|
|
3542
|
-
const rowLike = new this(opts);
|
|
3543
|
-
for (const key of Object.keys(rowLike)) {
|
|
3544
|
-
const value = rowLike[key];
|
|
3545
|
-
if (value instanceof UnboundColumnReferenceExpression) {
|
|
3546
|
-
const proto = Object.getPrototypeOf(rowLike);
|
|
3547
|
-
const getter = function() {
|
|
3548
|
-
const cls = this.constructor;
|
|
3549
|
-
return new ColumnReferenceExpression(cls.alias ?? cls.tableName, this.opts?.remapColumns ? key : value.column);
|
|
3550
|
-
};
|
|
3551
|
-
setToolMetadata(getter, { runtimeValidationEnabled: true });
|
|
3552
|
-
Object.defineProperty(proto, key, {
|
|
3553
|
-
get: getter,
|
|
3554
|
-
enumerable: true,
|
|
3555
|
-
configurable: true
|
|
3556
|
-
});
|
|
3557
|
-
delete rowLike[key];
|
|
3558
|
-
}
|
|
3559
|
-
}
|
|
3560
|
-
return rowLike;
|
|
3561
|
-
};
|
|
3562
|
-
static compile = function() {
|
|
3563
|
-
return sql`${sql.ref(this.tableName)} AS ${sql.ref(this.alias ?? this.tableName)}`;
|
|
3564
|
-
};
|
|
3565
|
-
} };
|
|
3566
|
-
tableClass;
|
|
3567
|
-
return tableClass;
|
|
3568
|
-
};
|
|
3569
|
-
var Database = class {
|
|
3570
|
-
constructor(dialect, opts) {
|
|
3571
|
-
this.dialect = dialect;
|
|
3572
|
-
this.opts = opts;
|
|
3573
|
-
}
|
|
3574
|
-
kysely;
|
|
3575
|
-
async execute(query) {
|
|
3576
|
-
if (this.kysely == null) {
|
|
3577
|
-
this.kysely = new Kysely({ dialect: this.dialect });
|
|
3578
|
-
}
|
|
3579
|
-
if (this.opts?.logQuery) {
|
|
3580
|
-
this.opts.logQuery(query.compile(this.kysely));
|
|
3581
|
-
}
|
|
3582
|
-
const result = await query.execute(this.kysely);
|
|
3583
|
-
return result.rows;
|
|
3584
|
-
}
|
|
3585
|
-
Table(name) {
|
|
3586
|
-
return table(this, name);
|
|
3587
|
-
}
|
|
3588
|
-
};
|
|
297
|
+
}
|
|
3589
298
|
export {
|
|
3590
299
|
CodeMode,
|
|
3591
|
-
Database,
|
|
3592
300
|
RpcToolset,
|
|
3593
301
|
createDenoSandbox,
|
|
3594
|
-
|
|
3595
|
-
newWorkersRpcResponse,
|
|
3596
|
-
tool
|
|
302
|
+
t as tool
|
|
3597
303
|
};
|