capnweb 0.0.0-e3fa093 → 0.0.0-ee7ca6f
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 +56 -3
- package/dist/index-bun.cjs +3104 -0
- package/dist/index-bun.cjs.map +1 -0
- package/dist/index-bun.d.cts +517 -0
- package/dist/index-bun.d.ts +517 -0
- package/dist/index-bun.js +3084 -0
- package/dist/index-bun.js.map +1 -0
- package/dist/index-workers.cjs +2912 -2555
- package/dist/index-workers.cjs.map +1 -1
- package/dist/index-workers.d.cts +396 -2
- package/dist/index-workers.d.ts +396 -2
- package/dist/index-workers.js +2875 -2528
- package/dist/index-workers.js.map +1 -1
- package/dist/index.cjs +2881 -2534
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +219 -195
- package/dist/index.d.ts +219 -195
- package/dist/index.js +2871 -2527
- package/dist/index.js.map +1 -1
- package/package.json +24 -12
|
@@ -0,0 +1,3104 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
|
+
|
|
3
|
+
//#region src/symbols.ts
|
|
4
|
+
let WORKERS_MODULE_SYMBOL = Symbol("workers-module");
|
|
5
|
+
|
|
6
|
+
//#endregion
|
|
7
|
+
//#region src/core.ts
|
|
8
|
+
if (!Symbol.dispose) Symbol.dispose = Symbol.for("dispose");
|
|
9
|
+
if (!Symbol.asyncDispose) Symbol.asyncDispose = Symbol.for("asyncDispose");
|
|
10
|
+
if (!Promise.withResolvers) Promise.withResolvers = function() {
|
|
11
|
+
let resolve;
|
|
12
|
+
let reject;
|
|
13
|
+
return {
|
|
14
|
+
promise: new Promise((res, rej) => {
|
|
15
|
+
resolve = res;
|
|
16
|
+
reject = rej;
|
|
17
|
+
}),
|
|
18
|
+
resolve,
|
|
19
|
+
reject
|
|
20
|
+
};
|
|
21
|
+
};
|
|
22
|
+
let workersModule = globalThis[WORKERS_MODULE_SYMBOL];
|
|
23
|
+
let RpcTarget$1 = workersModule ? workersModule.RpcTarget : class {};
|
|
24
|
+
const AsyncFunction = (async function() {}).constructor;
|
|
25
|
+
let BUFFER_PROTOTYPE = typeof Buffer !== "undefined" ? Buffer.prototype : void 0;
|
|
26
|
+
function typeForRpc(value) {
|
|
27
|
+
switch (typeof value) {
|
|
28
|
+
case "boolean":
|
|
29
|
+
case "number":
|
|
30
|
+
case "string": return "primitive";
|
|
31
|
+
case "undefined": return "undefined";
|
|
32
|
+
case "object":
|
|
33
|
+
case "function": break;
|
|
34
|
+
case "bigint": return "bigint";
|
|
35
|
+
default: return "unsupported";
|
|
36
|
+
}
|
|
37
|
+
if (value === null) return "primitive";
|
|
38
|
+
let prototype = Object.getPrototypeOf(value);
|
|
39
|
+
switch (prototype) {
|
|
40
|
+
case Object.prototype: return "object";
|
|
41
|
+
case Function.prototype:
|
|
42
|
+
case AsyncFunction.prototype: return "function";
|
|
43
|
+
case Array.prototype: return "array";
|
|
44
|
+
case Date.prototype: return "date";
|
|
45
|
+
case Uint8Array.prototype:
|
|
46
|
+
case BUFFER_PROTOTYPE: return "bytes";
|
|
47
|
+
case WritableStream.prototype: return "writable";
|
|
48
|
+
case ReadableStream.prototype: return "readable";
|
|
49
|
+
case Headers.prototype: return "headers";
|
|
50
|
+
case Request.prototype: return "request";
|
|
51
|
+
case Response.prototype: return "response";
|
|
52
|
+
case Blob.prototype: return "blob";
|
|
53
|
+
case RpcStub$1.prototype: return "stub";
|
|
54
|
+
case RpcPromise$1.prototype: return "rpc-promise";
|
|
55
|
+
default:
|
|
56
|
+
if (workersModule) {
|
|
57
|
+
if (prototype == workersModule.RpcStub.prototype || value instanceof workersModule.ServiceStub) return "rpc-target";
|
|
58
|
+
else if (prototype == workersModule.RpcPromise.prototype || prototype == workersModule.RpcProperty.prototype) return "rpc-thenable";
|
|
59
|
+
}
|
|
60
|
+
if (value instanceof RpcTarget$1) return "rpc-target";
|
|
61
|
+
if (value instanceof Error) return "error";
|
|
62
|
+
return "unsupported";
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
function mapNotLoaded() {
|
|
66
|
+
throw new Error("RPC map() implementation was not loaded.");
|
|
67
|
+
}
|
|
68
|
+
let mapImpl = {
|
|
69
|
+
applyMap: mapNotLoaded,
|
|
70
|
+
sendMap: mapNotLoaded
|
|
71
|
+
};
|
|
72
|
+
function streamNotLoaded() {
|
|
73
|
+
throw new Error("Stream implementation was not loaded.");
|
|
74
|
+
}
|
|
75
|
+
let streamImpl = {
|
|
76
|
+
createWritableStreamHook: streamNotLoaded,
|
|
77
|
+
createWritableStreamFromHook: streamNotLoaded,
|
|
78
|
+
createReadableStreamHook: streamNotLoaded
|
|
79
|
+
};
|
|
80
|
+
var StubHook = class {
|
|
81
|
+
stream(path, args) {
|
|
82
|
+
let pulled = this.call(path, args).pull();
|
|
83
|
+
let promise;
|
|
84
|
+
if (pulled instanceof Promise) promise = pulled.then((p) => {
|
|
85
|
+
p.dispose();
|
|
86
|
+
});
|
|
87
|
+
else {
|
|
88
|
+
pulled.dispose();
|
|
89
|
+
promise = Promise.resolve();
|
|
90
|
+
}
|
|
91
|
+
return { promise };
|
|
92
|
+
}
|
|
93
|
+
};
|
|
94
|
+
var ErrorStubHook = class extends StubHook {
|
|
95
|
+
error;
|
|
96
|
+
constructor(error) {
|
|
97
|
+
super();
|
|
98
|
+
this.error = error;
|
|
99
|
+
}
|
|
100
|
+
call(path, args) {
|
|
101
|
+
return this;
|
|
102
|
+
}
|
|
103
|
+
map(path, captures, instructions) {
|
|
104
|
+
return this;
|
|
105
|
+
}
|
|
106
|
+
get(path) {
|
|
107
|
+
return this;
|
|
108
|
+
}
|
|
109
|
+
dup() {
|
|
110
|
+
return this;
|
|
111
|
+
}
|
|
112
|
+
pull() {
|
|
113
|
+
return Promise.reject(this.error);
|
|
114
|
+
}
|
|
115
|
+
ignoreUnhandledRejections() {}
|
|
116
|
+
dispose() {}
|
|
117
|
+
onBroken(callback) {
|
|
118
|
+
try {
|
|
119
|
+
callback(this.error);
|
|
120
|
+
} catch (err) {
|
|
121
|
+
Promise.resolve(err);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
};
|
|
125
|
+
const DISPOSED_HOOK = new ErrorStubHook(/* @__PURE__ */ new Error("Attempted to use RPC stub after it has been disposed."));
|
|
126
|
+
let doCall = (hook, path, params) => {
|
|
127
|
+
return hook.call(path, params);
|
|
128
|
+
};
|
|
129
|
+
function withCallInterceptor(interceptor, callback) {
|
|
130
|
+
let oldValue = doCall;
|
|
131
|
+
doCall = interceptor;
|
|
132
|
+
try {
|
|
133
|
+
return callback();
|
|
134
|
+
} finally {
|
|
135
|
+
doCall = oldValue;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
let RAW_STUB = Symbol("realStub");
|
|
139
|
+
const PROXY_HANDLERS = {
|
|
140
|
+
apply(target, thisArg, argumentsList) {
|
|
141
|
+
let stub = target.raw;
|
|
142
|
+
return new RpcPromise$1(doCall(stub.hook, stub.pathIfPromise || [], RpcPayload.fromAppParams(argumentsList)), []);
|
|
143
|
+
},
|
|
144
|
+
get(target, prop, receiver) {
|
|
145
|
+
let stub = target.raw;
|
|
146
|
+
if (prop === RAW_STUB) return stub;
|
|
147
|
+
else if (prop in RpcPromise$1.prototype) return stub[prop];
|
|
148
|
+
else if (typeof prop === "string") return new RpcPromise$1(stub.hook, stub.pathIfPromise ? [...stub.pathIfPromise, prop] : [prop]);
|
|
149
|
+
else if (prop === Symbol.dispose && (!stub.pathIfPromise || stub.pathIfPromise.length == 0)) return () => {
|
|
150
|
+
stub.hook.dispose();
|
|
151
|
+
stub.hook = DISPOSED_HOOK;
|
|
152
|
+
};
|
|
153
|
+
else return;
|
|
154
|
+
},
|
|
155
|
+
has(target, prop) {
|
|
156
|
+
let stub = target.raw;
|
|
157
|
+
if (prop === RAW_STUB) return true;
|
|
158
|
+
else if (prop in RpcPromise$1.prototype) return prop in stub;
|
|
159
|
+
else if (typeof prop === "string") return true;
|
|
160
|
+
else if (prop === Symbol.dispose && (!stub.pathIfPromise || stub.pathIfPromise.length == 0)) return true;
|
|
161
|
+
else return false;
|
|
162
|
+
},
|
|
163
|
+
construct(target, args) {
|
|
164
|
+
throw new Error("An RPC stub cannot be used as a constructor.");
|
|
165
|
+
},
|
|
166
|
+
defineProperty(target, property, attributes) {
|
|
167
|
+
throw new Error("Can't define properties on RPC stubs.");
|
|
168
|
+
},
|
|
169
|
+
deleteProperty(target, p) {
|
|
170
|
+
throw new Error("Can't delete properties on RPC stubs.");
|
|
171
|
+
},
|
|
172
|
+
getOwnPropertyDescriptor(target, p) {},
|
|
173
|
+
getPrototypeOf(target) {
|
|
174
|
+
return Object.getPrototypeOf(target.raw);
|
|
175
|
+
},
|
|
176
|
+
isExtensible(target) {
|
|
177
|
+
return false;
|
|
178
|
+
},
|
|
179
|
+
ownKeys(target) {
|
|
180
|
+
return [];
|
|
181
|
+
},
|
|
182
|
+
preventExtensions(target) {
|
|
183
|
+
return true;
|
|
184
|
+
},
|
|
185
|
+
set(target, p, newValue, receiver) {
|
|
186
|
+
throw new Error("Can't assign properties on RPC stubs.");
|
|
187
|
+
},
|
|
188
|
+
setPrototypeOf(target, v) {
|
|
189
|
+
throw new Error("Can't override prototype of RPC stubs.");
|
|
190
|
+
}
|
|
191
|
+
};
|
|
192
|
+
var RpcStub$1 = class RpcStub$1 extends RpcTarget$1 {
|
|
193
|
+
constructor(hook, pathIfPromise) {
|
|
194
|
+
super();
|
|
195
|
+
if (!(hook instanceof StubHook)) {
|
|
196
|
+
let value = hook;
|
|
197
|
+
if (value instanceof RpcTarget$1 || value instanceof Function) hook = TargetStubHook.create(value, void 0);
|
|
198
|
+
else hook = new PayloadStubHook(RpcPayload.fromAppReturn(value));
|
|
199
|
+
if (pathIfPromise) throw new TypeError("RpcStub constructor expected one argument, received two.");
|
|
200
|
+
}
|
|
201
|
+
this.hook = hook;
|
|
202
|
+
this.pathIfPromise = pathIfPromise;
|
|
203
|
+
let func = () => {};
|
|
204
|
+
func.raw = this;
|
|
205
|
+
return new Proxy(func, PROXY_HANDLERS);
|
|
206
|
+
}
|
|
207
|
+
hook;
|
|
208
|
+
pathIfPromise;
|
|
209
|
+
dup() {
|
|
210
|
+
let target = this[RAW_STUB];
|
|
211
|
+
if (target.pathIfPromise) return new RpcStub$1(target.hook.get(target.pathIfPromise));
|
|
212
|
+
else return new RpcStub$1(target.hook.dup());
|
|
213
|
+
}
|
|
214
|
+
onRpcBroken(callback) {
|
|
215
|
+
this[RAW_STUB].hook.onBroken(callback);
|
|
216
|
+
}
|
|
217
|
+
map(func) {
|
|
218
|
+
let { hook, pathIfPromise } = this[RAW_STUB];
|
|
219
|
+
return mapImpl.sendMap(hook, pathIfPromise || [], func);
|
|
220
|
+
}
|
|
221
|
+
toString() {
|
|
222
|
+
return "[object RpcStub]";
|
|
223
|
+
}
|
|
224
|
+
};
|
|
225
|
+
var RpcPromise$1 = class extends RpcStub$1 {
|
|
226
|
+
constructor(hook, pathIfPromise) {
|
|
227
|
+
super(hook, pathIfPromise);
|
|
228
|
+
}
|
|
229
|
+
then(onfulfilled, onrejected) {
|
|
230
|
+
return pullPromise(this).then(...arguments);
|
|
231
|
+
}
|
|
232
|
+
catch(onrejected) {
|
|
233
|
+
return pullPromise(this).catch(...arguments);
|
|
234
|
+
}
|
|
235
|
+
finally(onfinally) {
|
|
236
|
+
return pullPromise(this).finally(...arguments);
|
|
237
|
+
}
|
|
238
|
+
toString() {
|
|
239
|
+
return "[object RpcPromise]";
|
|
240
|
+
}
|
|
241
|
+
};
|
|
242
|
+
function unwrapStubTakingOwnership(stub) {
|
|
243
|
+
let { hook, pathIfPromise } = stub[RAW_STUB];
|
|
244
|
+
if (pathIfPromise && pathIfPromise.length > 0) return hook.get(pathIfPromise);
|
|
245
|
+
else return hook;
|
|
246
|
+
}
|
|
247
|
+
function unwrapStubAndDup(stub) {
|
|
248
|
+
let { hook, pathIfPromise } = stub[RAW_STUB];
|
|
249
|
+
if (pathIfPromise) return hook.get(pathIfPromise);
|
|
250
|
+
else return hook.dup();
|
|
251
|
+
}
|
|
252
|
+
function unwrapStubNoProperties(stub) {
|
|
253
|
+
let { hook, pathIfPromise } = stub[RAW_STUB];
|
|
254
|
+
if (pathIfPromise && pathIfPromise.length > 0) return;
|
|
255
|
+
return hook;
|
|
256
|
+
}
|
|
257
|
+
function unwrapStubOrParent(stub) {
|
|
258
|
+
return stub[RAW_STUB].hook;
|
|
259
|
+
}
|
|
260
|
+
function unwrapStubAndPath(stub) {
|
|
261
|
+
return stub[RAW_STUB];
|
|
262
|
+
}
|
|
263
|
+
async function pullPromise(promise) {
|
|
264
|
+
let { hook, pathIfPromise } = promise[RAW_STUB];
|
|
265
|
+
if (pathIfPromise.length > 0) hook = hook.get(pathIfPromise);
|
|
266
|
+
return (await hook.pull()).deliverResolve();
|
|
267
|
+
}
|
|
268
|
+
var RpcPayload = class RpcPayload {
|
|
269
|
+
value;
|
|
270
|
+
source;
|
|
271
|
+
hooks;
|
|
272
|
+
promises;
|
|
273
|
+
static fromAppParams(value) {
|
|
274
|
+
return new RpcPayload(value, "params");
|
|
275
|
+
}
|
|
276
|
+
static fromAppReturn(value) {
|
|
277
|
+
return new RpcPayload(value, "return");
|
|
278
|
+
}
|
|
279
|
+
static fromArray(array) {
|
|
280
|
+
let hooks = [];
|
|
281
|
+
let promises = [];
|
|
282
|
+
let resultArray = [];
|
|
283
|
+
for (let payload of array) {
|
|
284
|
+
payload.ensureDeepCopied();
|
|
285
|
+
for (let hook of payload.hooks) hooks.push(hook);
|
|
286
|
+
for (let promise of payload.promises) {
|
|
287
|
+
if (promise.parent === payload) promise = {
|
|
288
|
+
parent: resultArray,
|
|
289
|
+
property: resultArray.length,
|
|
290
|
+
promise: promise.promise
|
|
291
|
+
};
|
|
292
|
+
promises.push(promise);
|
|
293
|
+
}
|
|
294
|
+
resultArray.push(payload.value);
|
|
295
|
+
}
|
|
296
|
+
return new RpcPayload(resultArray, "owned", hooks, promises);
|
|
297
|
+
}
|
|
298
|
+
static forEvaluate(hooks, promises) {
|
|
299
|
+
return new RpcPayload(null, "owned", hooks, promises);
|
|
300
|
+
}
|
|
301
|
+
static deepCopyFrom(value, oldParent, owner) {
|
|
302
|
+
let result = new RpcPayload(null, "owned", [], []);
|
|
303
|
+
result.value = result.deepCopy(value, oldParent, "value", result, true, owner);
|
|
304
|
+
return result;
|
|
305
|
+
}
|
|
306
|
+
constructor(value, source, hooks, promises) {
|
|
307
|
+
this.value = value;
|
|
308
|
+
this.source = source;
|
|
309
|
+
this.hooks = hooks;
|
|
310
|
+
this.promises = promises;
|
|
311
|
+
}
|
|
312
|
+
rpcTargets;
|
|
313
|
+
getHookForRpcTarget(target, parent, dupStubs = true) {
|
|
314
|
+
if (this.source === "params") {
|
|
315
|
+
if (dupStubs) {
|
|
316
|
+
let dupable = target;
|
|
317
|
+
if (typeof dupable.dup === "function") target = dupable.dup();
|
|
318
|
+
}
|
|
319
|
+
return TargetStubHook.create(target, parent);
|
|
320
|
+
} else if (this.source === "return") {
|
|
321
|
+
let hook = this.rpcTargets?.get(target);
|
|
322
|
+
if (hook) if (dupStubs) return hook.dup();
|
|
323
|
+
else {
|
|
324
|
+
this.rpcTargets?.delete(target);
|
|
325
|
+
return hook;
|
|
326
|
+
}
|
|
327
|
+
else {
|
|
328
|
+
hook = TargetStubHook.create(target, parent);
|
|
329
|
+
if (dupStubs) {
|
|
330
|
+
if (!this.rpcTargets) this.rpcTargets = /* @__PURE__ */ new Map();
|
|
331
|
+
this.rpcTargets.set(target, hook);
|
|
332
|
+
return hook.dup();
|
|
333
|
+
} else return hook;
|
|
334
|
+
}
|
|
335
|
+
} else throw new Error("owned payload shouldn't contain raw RpcTargets");
|
|
336
|
+
}
|
|
337
|
+
getHookForWritableStream(stream, parent, dupStubs = true) {
|
|
338
|
+
if (this.source === "params") return streamImpl.createWritableStreamHook(stream);
|
|
339
|
+
else if (this.source === "return") {
|
|
340
|
+
let hook = this.rpcTargets?.get(stream);
|
|
341
|
+
if (hook) if (dupStubs) return hook.dup();
|
|
342
|
+
else {
|
|
343
|
+
this.rpcTargets?.delete(stream);
|
|
344
|
+
return hook;
|
|
345
|
+
}
|
|
346
|
+
else {
|
|
347
|
+
hook = streamImpl.createWritableStreamHook(stream);
|
|
348
|
+
if (dupStubs) {
|
|
349
|
+
if (!this.rpcTargets) this.rpcTargets = /* @__PURE__ */ new Map();
|
|
350
|
+
this.rpcTargets.set(stream, hook);
|
|
351
|
+
return hook.dup();
|
|
352
|
+
} else return hook;
|
|
353
|
+
}
|
|
354
|
+
} else throw new Error("owned payload shouldn't contain raw WritableStreams");
|
|
355
|
+
}
|
|
356
|
+
getHookForReadableStream(stream, parent, dupStubs = true) {
|
|
357
|
+
if (this.source === "params") return streamImpl.createReadableStreamHook(stream);
|
|
358
|
+
else if (this.source === "return") {
|
|
359
|
+
let hook = this.rpcTargets?.get(stream);
|
|
360
|
+
if (hook) if (dupStubs) return hook.dup();
|
|
361
|
+
else {
|
|
362
|
+
this.rpcTargets?.delete(stream);
|
|
363
|
+
return hook;
|
|
364
|
+
}
|
|
365
|
+
else {
|
|
366
|
+
hook = streamImpl.createReadableStreamHook(stream);
|
|
367
|
+
if (dupStubs) {
|
|
368
|
+
if (!this.rpcTargets) this.rpcTargets = /* @__PURE__ */ new Map();
|
|
369
|
+
this.rpcTargets.set(stream, hook);
|
|
370
|
+
return hook.dup();
|
|
371
|
+
} else return hook;
|
|
372
|
+
}
|
|
373
|
+
} else throw new Error("owned payload shouldn't contain raw ReadableStreams");
|
|
374
|
+
}
|
|
375
|
+
deepCopy(value, oldParent, property, parent, dupStubs, owner) {
|
|
376
|
+
switch (typeForRpc(value)) {
|
|
377
|
+
case "unsupported": return value;
|
|
378
|
+
case "primitive":
|
|
379
|
+
case "bigint":
|
|
380
|
+
case "date":
|
|
381
|
+
case "bytes":
|
|
382
|
+
case "blob":
|
|
383
|
+
case "error":
|
|
384
|
+
case "undefined": return value;
|
|
385
|
+
case "array": {
|
|
386
|
+
let array = value;
|
|
387
|
+
let len = array.length;
|
|
388
|
+
let result = new Array(len);
|
|
389
|
+
for (let i = 0; i < len; i++) result[i] = this.deepCopy(array[i], array, i, result, dupStubs, owner);
|
|
390
|
+
return result;
|
|
391
|
+
}
|
|
392
|
+
case "object": {
|
|
393
|
+
let result = {};
|
|
394
|
+
let object = value;
|
|
395
|
+
for (let i in object) result[i] = this.deepCopy(object[i], object, i, result, dupStubs, owner);
|
|
396
|
+
return result;
|
|
397
|
+
}
|
|
398
|
+
case "stub":
|
|
399
|
+
case "rpc-promise": {
|
|
400
|
+
let stub = value;
|
|
401
|
+
let hook;
|
|
402
|
+
if (dupStubs) hook = unwrapStubAndDup(stub);
|
|
403
|
+
else hook = unwrapStubTakingOwnership(stub);
|
|
404
|
+
if (stub instanceof RpcPromise$1) {
|
|
405
|
+
let promise = new RpcPromise$1(hook, []);
|
|
406
|
+
this.promises.push({
|
|
407
|
+
parent,
|
|
408
|
+
property,
|
|
409
|
+
promise
|
|
410
|
+
});
|
|
411
|
+
return promise;
|
|
412
|
+
} else {
|
|
413
|
+
this.hooks.push(hook);
|
|
414
|
+
return new RpcStub$1(hook);
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
case "function":
|
|
418
|
+
case "rpc-target": {
|
|
419
|
+
let target = value;
|
|
420
|
+
let hook;
|
|
421
|
+
if (owner) hook = owner.getHookForRpcTarget(target, oldParent, dupStubs);
|
|
422
|
+
else hook = TargetStubHook.create(target, oldParent);
|
|
423
|
+
this.hooks.push(hook);
|
|
424
|
+
return new RpcStub$1(hook);
|
|
425
|
+
}
|
|
426
|
+
case "rpc-thenable": {
|
|
427
|
+
let target = value;
|
|
428
|
+
let promise;
|
|
429
|
+
if (owner) promise = new RpcPromise$1(owner.getHookForRpcTarget(target, oldParent, dupStubs), []);
|
|
430
|
+
else promise = new RpcPromise$1(TargetStubHook.create(target, oldParent), []);
|
|
431
|
+
this.promises.push({
|
|
432
|
+
parent,
|
|
433
|
+
property,
|
|
434
|
+
promise
|
|
435
|
+
});
|
|
436
|
+
return promise;
|
|
437
|
+
}
|
|
438
|
+
case "writable": {
|
|
439
|
+
let stream = value;
|
|
440
|
+
let hook;
|
|
441
|
+
if (owner) hook = owner.getHookForWritableStream(stream, oldParent, dupStubs);
|
|
442
|
+
else hook = streamImpl.createWritableStreamHook(stream);
|
|
443
|
+
this.hooks.push(hook);
|
|
444
|
+
return stream;
|
|
445
|
+
}
|
|
446
|
+
case "readable": {
|
|
447
|
+
let stream = value;
|
|
448
|
+
let hook;
|
|
449
|
+
if (owner) hook = owner.getHookForReadableStream(stream, oldParent, dupStubs);
|
|
450
|
+
else hook = streamImpl.createReadableStreamHook(stream);
|
|
451
|
+
this.hooks.push(hook);
|
|
452
|
+
return stream;
|
|
453
|
+
}
|
|
454
|
+
case "headers": return new Headers(value);
|
|
455
|
+
case "request": {
|
|
456
|
+
let req = value;
|
|
457
|
+
if (req.body) this.deepCopy(req.body, req, "body", req, dupStubs, owner);
|
|
458
|
+
return new Request(req);
|
|
459
|
+
}
|
|
460
|
+
case "response": {
|
|
461
|
+
let resp = value;
|
|
462
|
+
if (resp.body) this.deepCopy(resp.body, resp, "body", resp, dupStubs, owner);
|
|
463
|
+
return new Response(resp.body, resp);
|
|
464
|
+
}
|
|
465
|
+
default: throw new Error("unreachable");
|
|
466
|
+
}
|
|
467
|
+
}
|
|
468
|
+
ensureDeepCopied() {
|
|
469
|
+
if (this.source !== "owned") {
|
|
470
|
+
let dupStubs = this.source === "params";
|
|
471
|
+
this.hooks = [];
|
|
472
|
+
this.promises = [];
|
|
473
|
+
try {
|
|
474
|
+
this.value = this.deepCopy(this.value, void 0, "value", this, dupStubs, this);
|
|
475
|
+
} catch (err) {
|
|
476
|
+
this.hooks = void 0;
|
|
477
|
+
this.promises = void 0;
|
|
478
|
+
throw err;
|
|
479
|
+
}
|
|
480
|
+
this.source = "owned";
|
|
481
|
+
if (this.rpcTargets && this.rpcTargets.size > 0) throw new Error("Not all rpcTargets were accounted for in deep-copy?");
|
|
482
|
+
this.rpcTargets = void 0;
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
deliverTo(parent, property, promises) {
|
|
486
|
+
this.ensureDeepCopied();
|
|
487
|
+
if (this.value instanceof RpcPromise$1) RpcPayload.deliverRpcPromiseTo(this.value, parent, property, promises);
|
|
488
|
+
else {
|
|
489
|
+
parent[property] = this.value;
|
|
490
|
+
for (let record of this.promises) RpcPayload.deliverRpcPromiseTo(record.promise, record.parent, record.property, promises);
|
|
491
|
+
}
|
|
492
|
+
}
|
|
493
|
+
static deliverRpcPromiseTo(promise, parent, property, promises) {
|
|
494
|
+
let hook = unwrapStubNoProperties(promise);
|
|
495
|
+
if (!hook) throw new Error("property promises should have been resolved earlier");
|
|
496
|
+
let inner = hook.pull();
|
|
497
|
+
if (inner instanceof RpcPayload) inner.deliverTo(parent, property, promises);
|
|
498
|
+
else promises.push(inner.then((payload) => {
|
|
499
|
+
let subPromises = [];
|
|
500
|
+
payload.deliverTo(parent, property, subPromises);
|
|
501
|
+
if (subPromises.length > 0) return Promise.all(subPromises);
|
|
502
|
+
}));
|
|
503
|
+
}
|
|
504
|
+
async deliverCall(func, thisArg) {
|
|
505
|
+
try {
|
|
506
|
+
let promises = [];
|
|
507
|
+
this.deliverTo(this, "value", promises);
|
|
508
|
+
if (promises.length > 0) await Promise.all(promises);
|
|
509
|
+
let result = Function.prototype.apply.call(func, thisArg, this.value);
|
|
510
|
+
if (result instanceof RpcPromise$1) return RpcPayload.fromAppReturn(result);
|
|
511
|
+
else return RpcPayload.fromAppReturn(await result);
|
|
512
|
+
} finally {
|
|
513
|
+
this.dispose();
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
async deliverResolve() {
|
|
517
|
+
try {
|
|
518
|
+
let promises = [];
|
|
519
|
+
this.deliverTo(this, "value", promises);
|
|
520
|
+
if (promises.length > 0) await Promise.all(promises);
|
|
521
|
+
let result = this.value;
|
|
522
|
+
if (result instanceof Object) {
|
|
523
|
+
if (!(Symbol.dispose in result)) Object.defineProperty(result, Symbol.dispose, {
|
|
524
|
+
value: () => this.dispose(),
|
|
525
|
+
writable: true,
|
|
526
|
+
enumerable: false,
|
|
527
|
+
configurable: true
|
|
528
|
+
});
|
|
529
|
+
}
|
|
530
|
+
return result;
|
|
531
|
+
} catch (err) {
|
|
532
|
+
this.dispose();
|
|
533
|
+
throw err;
|
|
534
|
+
}
|
|
535
|
+
}
|
|
536
|
+
dispose() {
|
|
537
|
+
if (this.source === "owned") {
|
|
538
|
+
this.hooks.forEach((hook) => hook.dispose());
|
|
539
|
+
this.promises.forEach((promise) => promise.promise[Symbol.dispose]());
|
|
540
|
+
} else if (this.source === "return") {
|
|
541
|
+
this.disposeImpl(this.value, void 0);
|
|
542
|
+
if (this.rpcTargets && this.rpcTargets.size > 0) throw new Error("Not all rpcTargets were accounted for in disposeImpl()?");
|
|
543
|
+
}
|
|
544
|
+
this.source = "owned";
|
|
545
|
+
this.hooks = [];
|
|
546
|
+
this.promises = [];
|
|
547
|
+
}
|
|
548
|
+
disposeImpl(value, parent) {
|
|
549
|
+
switch (typeForRpc(value)) {
|
|
550
|
+
case "unsupported":
|
|
551
|
+
case "primitive":
|
|
552
|
+
case "bigint":
|
|
553
|
+
case "bytes":
|
|
554
|
+
case "blob":
|
|
555
|
+
case "date":
|
|
556
|
+
case "error":
|
|
557
|
+
case "undefined": return;
|
|
558
|
+
case "array": {
|
|
559
|
+
let array = value;
|
|
560
|
+
let len = array.length;
|
|
561
|
+
for (let i = 0; i < len; i++) this.disposeImpl(array[i], array);
|
|
562
|
+
return;
|
|
563
|
+
}
|
|
564
|
+
case "object": {
|
|
565
|
+
let object = value;
|
|
566
|
+
for (let i in object) this.disposeImpl(object[i], object);
|
|
567
|
+
return;
|
|
568
|
+
}
|
|
569
|
+
case "stub":
|
|
570
|
+
case "rpc-promise": {
|
|
571
|
+
let hook = unwrapStubNoProperties(value);
|
|
572
|
+
if (hook) hook.dispose();
|
|
573
|
+
return;
|
|
574
|
+
}
|
|
575
|
+
case "function":
|
|
576
|
+
case "rpc-target": {
|
|
577
|
+
let target = value;
|
|
578
|
+
let hook = this.rpcTargets?.get(target);
|
|
579
|
+
if (hook) {
|
|
580
|
+
hook.dispose();
|
|
581
|
+
this.rpcTargets.delete(target);
|
|
582
|
+
} else disposeRpcTarget(target);
|
|
583
|
+
return;
|
|
584
|
+
}
|
|
585
|
+
case "rpc-thenable": return;
|
|
586
|
+
case "headers": return;
|
|
587
|
+
case "request": {
|
|
588
|
+
let req = value;
|
|
589
|
+
if (req.body) this.disposeImpl(req.body, req);
|
|
590
|
+
return;
|
|
591
|
+
}
|
|
592
|
+
case "response": {
|
|
593
|
+
let resp = value;
|
|
594
|
+
if (resp.body) this.disposeImpl(resp.body, resp);
|
|
595
|
+
return;
|
|
596
|
+
}
|
|
597
|
+
case "writable": {
|
|
598
|
+
let stream = value;
|
|
599
|
+
let hook = this.rpcTargets?.get(stream);
|
|
600
|
+
if (hook) this.rpcTargets.delete(stream);
|
|
601
|
+
else hook = streamImpl.createWritableStreamHook(stream);
|
|
602
|
+
hook.dispose();
|
|
603
|
+
return;
|
|
604
|
+
}
|
|
605
|
+
case "readable": {
|
|
606
|
+
let stream = value;
|
|
607
|
+
let hook = this.rpcTargets?.get(stream);
|
|
608
|
+
if (hook) this.rpcTargets.delete(stream);
|
|
609
|
+
else hook = streamImpl.createReadableStreamHook(stream);
|
|
610
|
+
hook.dispose();
|
|
611
|
+
return;
|
|
612
|
+
}
|
|
613
|
+
default: return;
|
|
614
|
+
}
|
|
615
|
+
}
|
|
616
|
+
ignoreUnhandledRejections() {
|
|
617
|
+
if (this.hooks) {
|
|
618
|
+
this.hooks.forEach((hook) => {
|
|
619
|
+
hook.ignoreUnhandledRejections();
|
|
620
|
+
});
|
|
621
|
+
this.promises.forEach((promise) => unwrapStubOrParent(promise.promise).ignoreUnhandledRejections());
|
|
622
|
+
} else this.ignoreUnhandledRejectionsImpl(this.value);
|
|
623
|
+
}
|
|
624
|
+
ignoreUnhandledRejectionsImpl(value) {
|
|
625
|
+
switch (typeForRpc(value)) {
|
|
626
|
+
case "unsupported":
|
|
627
|
+
case "primitive":
|
|
628
|
+
case "bigint":
|
|
629
|
+
case "bytes":
|
|
630
|
+
case "blob":
|
|
631
|
+
case "date":
|
|
632
|
+
case "error":
|
|
633
|
+
case "undefined":
|
|
634
|
+
case "function":
|
|
635
|
+
case "rpc-target":
|
|
636
|
+
case "writable":
|
|
637
|
+
case "readable":
|
|
638
|
+
case "headers":
|
|
639
|
+
case "request":
|
|
640
|
+
case "response": return;
|
|
641
|
+
case "array": {
|
|
642
|
+
let array = value;
|
|
643
|
+
let len = array.length;
|
|
644
|
+
for (let i = 0; i < len; i++) this.ignoreUnhandledRejectionsImpl(array[i]);
|
|
645
|
+
return;
|
|
646
|
+
}
|
|
647
|
+
case "object": {
|
|
648
|
+
let object = value;
|
|
649
|
+
for (let i in object) this.ignoreUnhandledRejectionsImpl(object[i]);
|
|
650
|
+
return;
|
|
651
|
+
}
|
|
652
|
+
case "stub":
|
|
653
|
+
case "rpc-promise":
|
|
654
|
+
unwrapStubOrParent(value).ignoreUnhandledRejections();
|
|
655
|
+
return;
|
|
656
|
+
case "rpc-thenable":
|
|
657
|
+
value.then((_) => {}, (_) => {});
|
|
658
|
+
return;
|
|
659
|
+
default: return;
|
|
660
|
+
}
|
|
661
|
+
}
|
|
662
|
+
};
|
|
663
|
+
function followPath(value, parent, path, owner) {
|
|
664
|
+
for (let i = 0; i < path.length; i++) {
|
|
665
|
+
parent = value;
|
|
666
|
+
let part = path[i];
|
|
667
|
+
if (part in Object.prototype) {
|
|
668
|
+
value = void 0;
|
|
669
|
+
continue;
|
|
670
|
+
}
|
|
671
|
+
switch (typeForRpc(value)) {
|
|
672
|
+
case "object":
|
|
673
|
+
case "function":
|
|
674
|
+
if (Object.hasOwn(value, part)) value = value[part];
|
|
675
|
+
else value = void 0;
|
|
676
|
+
break;
|
|
677
|
+
case "array":
|
|
678
|
+
if (Number.isInteger(part) && part >= 0) value = value[part];
|
|
679
|
+
else value = void 0;
|
|
680
|
+
break;
|
|
681
|
+
case "rpc-target":
|
|
682
|
+
case "rpc-thenable":
|
|
683
|
+
if (Object.hasOwn(value, part)) throw new TypeError(`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.`);
|
|
684
|
+
else value = value[part];
|
|
685
|
+
owner = null;
|
|
686
|
+
break;
|
|
687
|
+
case "stub":
|
|
688
|
+
case "rpc-promise": {
|
|
689
|
+
let { hook, pathIfPromise } = unwrapStubAndPath(value);
|
|
690
|
+
return {
|
|
691
|
+
hook,
|
|
692
|
+
remainingPath: pathIfPromise ? pathIfPromise.concat(path.slice(i)) : path.slice(i)
|
|
693
|
+
};
|
|
694
|
+
}
|
|
695
|
+
case "writable":
|
|
696
|
+
value = void 0;
|
|
697
|
+
break;
|
|
698
|
+
case "readable":
|
|
699
|
+
value = void 0;
|
|
700
|
+
break;
|
|
701
|
+
case "primitive":
|
|
702
|
+
case "bigint":
|
|
703
|
+
case "bytes":
|
|
704
|
+
case "blob":
|
|
705
|
+
case "date":
|
|
706
|
+
case "error":
|
|
707
|
+
case "headers":
|
|
708
|
+
case "request":
|
|
709
|
+
case "response":
|
|
710
|
+
value = void 0;
|
|
711
|
+
break;
|
|
712
|
+
case "undefined":
|
|
713
|
+
value = value[part];
|
|
714
|
+
break;
|
|
715
|
+
case "unsupported": if (i === 0) throw new TypeError(`RPC stub points at a non-serializable type.`);
|
|
716
|
+
else {
|
|
717
|
+
let prefix = path.slice(0, i).join(".");
|
|
718
|
+
let remainder = path.slice(0, i).join(".");
|
|
719
|
+
throw new TypeError(`'${prefix}' is not a serializable type, so property ${remainder} cannot be accessed.`);
|
|
720
|
+
}
|
|
721
|
+
default: throw new TypeError("unreachable");
|
|
722
|
+
}
|
|
723
|
+
}
|
|
724
|
+
if (value instanceof RpcPromise$1) {
|
|
725
|
+
let { hook, pathIfPromise } = unwrapStubAndPath(value);
|
|
726
|
+
return {
|
|
727
|
+
hook,
|
|
728
|
+
remainingPath: pathIfPromise || []
|
|
729
|
+
};
|
|
730
|
+
}
|
|
731
|
+
return {
|
|
732
|
+
value,
|
|
733
|
+
parent,
|
|
734
|
+
owner
|
|
735
|
+
};
|
|
736
|
+
}
|
|
737
|
+
var ValueStubHook = class extends StubHook {
|
|
738
|
+
call(path, args) {
|
|
739
|
+
try {
|
|
740
|
+
let { value, owner } = this.getValue();
|
|
741
|
+
let followResult = followPath(value, void 0, path, owner);
|
|
742
|
+
if (followResult.hook) return followResult.hook.call(followResult.remainingPath, args);
|
|
743
|
+
if (typeof followResult.value != "function") throw new TypeError(`'${path.join(".")}' is not a function.`);
|
|
744
|
+
return new PromiseStubHook(args.deliverCall(followResult.value, followResult.parent).then((payload) => {
|
|
745
|
+
return new PayloadStubHook(payload);
|
|
746
|
+
}));
|
|
747
|
+
} catch (err) {
|
|
748
|
+
return new ErrorStubHook(err);
|
|
749
|
+
}
|
|
750
|
+
}
|
|
751
|
+
map(path, captures, instructions) {
|
|
752
|
+
try {
|
|
753
|
+
let followResult;
|
|
754
|
+
try {
|
|
755
|
+
let { value, owner } = this.getValue();
|
|
756
|
+
followResult = followPath(value, void 0, path, owner);
|
|
757
|
+
} catch (err) {
|
|
758
|
+
for (let cap of captures) cap.dispose();
|
|
759
|
+
throw err;
|
|
760
|
+
}
|
|
761
|
+
if (followResult.hook) return followResult.hook.map(followResult.remainingPath, captures, instructions);
|
|
762
|
+
return mapImpl.applyMap(followResult.value, followResult.parent, followResult.owner, captures, instructions);
|
|
763
|
+
} catch (err) {
|
|
764
|
+
return new ErrorStubHook(err);
|
|
765
|
+
}
|
|
766
|
+
}
|
|
767
|
+
get(path) {
|
|
768
|
+
try {
|
|
769
|
+
let { value, owner } = this.getValue();
|
|
770
|
+
if (path.length === 0 && owner === null) throw new Error("Can't dup an RpcTarget stub as a promise.");
|
|
771
|
+
let followResult = followPath(value, void 0, path, owner);
|
|
772
|
+
if (followResult.hook) return followResult.hook.get(followResult.remainingPath);
|
|
773
|
+
return new PayloadStubHook(RpcPayload.deepCopyFrom(followResult.value, followResult.parent, followResult.owner));
|
|
774
|
+
} catch (err) {
|
|
775
|
+
return new ErrorStubHook(err);
|
|
776
|
+
}
|
|
777
|
+
}
|
|
778
|
+
};
|
|
779
|
+
var PayloadStubHook = class PayloadStubHook extends ValueStubHook {
|
|
780
|
+
constructor(payload) {
|
|
781
|
+
super();
|
|
782
|
+
this.payload = payload;
|
|
783
|
+
}
|
|
784
|
+
payload;
|
|
785
|
+
getPayload() {
|
|
786
|
+
if (this.payload) return this.payload;
|
|
787
|
+
else throw new Error("Attempted to use an RPC StubHook after it was disposed.");
|
|
788
|
+
}
|
|
789
|
+
getValue() {
|
|
790
|
+
let payload = this.getPayload();
|
|
791
|
+
return {
|
|
792
|
+
value: payload.value,
|
|
793
|
+
owner: payload
|
|
794
|
+
};
|
|
795
|
+
}
|
|
796
|
+
dup() {
|
|
797
|
+
let thisPayload = this.getPayload();
|
|
798
|
+
return new PayloadStubHook(RpcPayload.deepCopyFrom(thisPayload.value, void 0, thisPayload));
|
|
799
|
+
}
|
|
800
|
+
pull() {
|
|
801
|
+
return this.getPayload();
|
|
802
|
+
}
|
|
803
|
+
ignoreUnhandledRejections() {
|
|
804
|
+
if (this.payload) this.payload.ignoreUnhandledRejections();
|
|
805
|
+
}
|
|
806
|
+
dispose() {
|
|
807
|
+
if (this.payload) {
|
|
808
|
+
this.payload.dispose();
|
|
809
|
+
this.payload = void 0;
|
|
810
|
+
}
|
|
811
|
+
}
|
|
812
|
+
onBroken(callback) {
|
|
813
|
+
if (this.payload) {
|
|
814
|
+
if (this.payload.value instanceof RpcStub$1) this.payload.value.onRpcBroken(callback);
|
|
815
|
+
}
|
|
816
|
+
}
|
|
817
|
+
};
|
|
818
|
+
function disposeRpcTarget(target) {
|
|
819
|
+
if (Symbol.dispose in target) try {
|
|
820
|
+
target[Symbol.dispose]();
|
|
821
|
+
} catch (err) {
|
|
822
|
+
Promise.reject(err);
|
|
823
|
+
}
|
|
824
|
+
}
|
|
825
|
+
var TargetStubHook = class TargetStubHook extends ValueStubHook {
|
|
826
|
+
static create(value, parent) {
|
|
827
|
+
if (typeof value !== "function") parent = void 0;
|
|
828
|
+
return new TargetStubHook(value, parent);
|
|
829
|
+
}
|
|
830
|
+
constructor(target, parent, dupFrom) {
|
|
831
|
+
super();
|
|
832
|
+
this.target = target;
|
|
833
|
+
this.parent = parent;
|
|
834
|
+
if (dupFrom) {
|
|
835
|
+
if (dupFrom.refcount) {
|
|
836
|
+
this.refcount = dupFrom.refcount;
|
|
837
|
+
++this.refcount.count;
|
|
838
|
+
}
|
|
839
|
+
} else if (Symbol.dispose in target) this.refcount = { count: 1 };
|
|
840
|
+
}
|
|
841
|
+
target;
|
|
842
|
+
parent;
|
|
843
|
+
refcount;
|
|
844
|
+
getTarget() {
|
|
845
|
+
if (this.target) return this.target;
|
|
846
|
+
else throw new Error("Attempted to use an RPC StubHook after it was disposed.");
|
|
847
|
+
}
|
|
848
|
+
getValue() {
|
|
849
|
+
return {
|
|
850
|
+
value: this.getTarget(),
|
|
851
|
+
owner: null
|
|
852
|
+
};
|
|
853
|
+
}
|
|
854
|
+
dup() {
|
|
855
|
+
return new TargetStubHook(this.getTarget(), this.parent, this);
|
|
856
|
+
}
|
|
857
|
+
pull() {
|
|
858
|
+
let target = this.getTarget();
|
|
859
|
+
if ("then" in target) return Promise.resolve(target).then((resolution) => {
|
|
860
|
+
return RpcPayload.fromAppReturn(resolution);
|
|
861
|
+
});
|
|
862
|
+
else return Promise.reject(/* @__PURE__ */ new Error("Tried to resolve a non-promise stub."));
|
|
863
|
+
}
|
|
864
|
+
ignoreUnhandledRejections() {}
|
|
865
|
+
dispose() {
|
|
866
|
+
if (this.target) {
|
|
867
|
+
if (this.refcount) {
|
|
868
|
+
if (--this.refcount.count == 0) disposeRpcTarget(this.target);
|
|
869
|
+
}
|
|
870
|
+
this.target = void 0;
|
|
871
|
+
}
|
|
872
|
+
}
|
|
873
|
+
onBroken(callback) {}
|
|
874
|
+
};
|
|
875
|
+
var PromiseStubHook = class PromiseStubHook extends StubHook {
|
|
876
|
+
promise;
|
|
877
|
+
resolution;
|
|
878
|
+
constructor(promise) {
|
|
879
|
+
super();
|
|
880
|
+
this.promise = promise.then((res) => {
|
|
881
|
+
this.resolution = res;
|
|
882
|
+
return res;
|
|
883
|
+
});
|
|
884
|
+
}
|
|
885
|
+
call(path, args) {
|
|
886
|
+
args.ensureDeepCopied();
|
|
887
|
+
return new PromiseStubHook(this.promise.then((hook) => hook.call(path, args)));
|
|
888
|
+
}
|
|
889
|
+
stream(path, args) {
|
|
890
|
+
args.ensureDeepCopied();
|
|
891
|
+
return { promise: this.promise.then((hook) => {
|
|
892
|
+
return hook.stream(path, args).promise;
|
|
893
|
+
}) };
|
|
894
|
+
}
|
|
895
|
+
map(path, captures, instructions) {
|
|
896
|
+
return new PromiseStubHook(this.promise.then((hook) => hook.map(path, captures, instructions), (err) => {
|
|
897
|
+
for (let cap of captures) cap.dispose();
|
|
898
|
+
throw err;
|
|
899
|
+
}));
|
|
900
|
+
}
|
|
901
|
+
get(path) {
|
|
902
|
+
return new PromiseStubHook(this.promise.then((hook) => hook.get(path)));
|
|
903
|
+
}
|
|
904
|
+
dup() {
|
|
905
|
+
if (this.resolution) return this.resolution.dup();
|
|
906
|
+
else return new PromiseStubHook(this.promise.then((hook) => hook.dup()));
|
|
907
|
+
}
|
|
908
|
+
pull() {
|
|
909
|
+
if (this.resolution) return this.resolution.pull();
|
|
910
|
+
else return this.promise.then((hook) => hook.pull());
|
|
911
|
+
}
|
|
912
|
+
ignoreUnhandledRejections() {
|
|
913
|
+
if (this.resolution) this.resolution.ignoreUnhandledRejections();
|
|
914
|
+
else this.promise.then((res) => {
|
|
915
|
+
res.ignoreUnhandledRejections();
|
|
916
|
+
}, (err) => {});
|
|
917
|
+
}
|
|
918
|
+
dispose() {
|
|
919
|
+
if (this.resolution) this.resolution.dispose();
|
|
920
|
+
else this.promise.then((hook) => {
|
|
921
|
+
hook.dispose();
|
|
922
|
+
}, (err) => {});
|
|
923
|
+
}
|
|
924
|
+
onBroken(callback) {
|
|
925
|
+
if (this.resolution) this.resolution.onBroken(callback);
|
|
926
|
+
else this.promise.then((hook) => {
|
|
927
|
+
hook.onBroken(callback);
|
|
928
|
+
}, callback);
|
|
929
|
+
}
|
|
930
|
+
};
|
|
931
|
+
|
|
932
|
+
//#endregion
|
|
933
|
+
//#region src/serialize.ts
|
|
934
|
+
const DEFAULT_MAX_DEPTH = 256;
|
|
935
|
+
const DEFAULT_LIMITS = {
|
|
936
|
+
maxBigIntDigits: 16384,
|
|
937
|
+
maxDepth: 256,
|
|
938
|
+
maxMessageSize: 32 * 1024 * 1024
|
|
939
|
+
};
|
|
940
|
+
var NullExporter = class {
|
|
941
|
+
exportStub(stub) {
|
|
942
|
+
throw new Error("Cannot serialize RPC stubs without an RPC session.");
|
|
943
|
+
}
|
|
944
|
+
exportPromise(stub) {
|
|
945
|
+
throw new Error("Cannot serialize RPC stubs without an RPC session.");
|
|
946
|
+
}
|
|
947
|
+
getImport(hook) {}
|
|
948
|
+
unexport(ids) {}
|
|
949
|
+
createPipe(readable) {
|
|
950
|
+
throw new Error("Cannot create pipes without an RPC session.");
|
|
951
|
+
}
|
|
952
|
+
onSendError(error) {}
|
|
953
|
+
};
|
|
954
|
+
const NULL_EXPORTER = new NullExporter();
|
|
955
|
+
async function streamToBlob(stream, type) {
|
|
956
|
+
let b = await new Response(stream).blob();
|
|
957
|
+
return b.type === type ? b : b.slice(0, b.size, type);
|
|
958
|
+
}
|
|
959
|
+
const ERROR_TYPES = {
|
|
960
|
+
__proto__: null,
|
|
961
|
+
Error,
|
|
962
|
+
EvalError,
|
|
963
|
+
RangeError,
|
|
964
|
+
ReferenceError,
|
|
965
|
+
SyntaxError,
|
|
966
|
+
TypeError,
|
|
967
|
+
URIError,
|
|
968
|
+
AggregateError
|
|
969
|
+
};
|
|
970
|
+
var Devaluator = class Devaluator {
|
|
971
|
+
exporter;
|
|
972
|
+
source;
|
|
973
|
+
encodingLevel;
|
|
974
|
+
constructor(exporter, source, encodingLevel) {
|
|
975
|
+
this.exporter = exporter;
|
|
976
|
+
this.source = source;
|
|
977
|
+
this.encodingLevel = encodingLevel;
|
|
978
|
+
}
|
|
979
|
+
static devaluate(value, parent, exporter = NULL_EXPORTER, source, encodingLevel = "string") {
|
|
980
|
+
let devaluator = new Devaluator(exporter, source, encodingLevel);
|
|
981
|
+
try {
|
|
982
|
+
return devaluator.devaluateImpl(value, parent, 0);
|
|
983
|
+
} catch (err) {
|
|
984
|
+
if (devaluator.exports) try {
|
|
985
|
+
exporter.unexport(devaluator.exports);
|
|
986
|
+
} catch (err) {}
|
|
987
|
+
throw err;
|
|
988
|
+
}
|
|
989
|
+
}
|
|
990
|
+
exports;
|
|
991
|
+
devaluateImpl(value, parent, depth) {
|
|
992
|
+
if (depth >= 256) throw new Error("Serialization exceeded maximum allowed depth. (Does the message contain cycles?)");
|
|
993
|
+
switch (typeForRpc(value)) {
|
|
994
|
+
case "unsupported": {
|
|
995
|
+
let msg;
|
|
996
|
+
try {
|
|
997
|
+
msg = `Cannot serialize value: ${value}`;
|
|
998
|
+
} catch (err) {
|
|
999
|
+
msg = "Cannot serialize value: (couldn't stringify value)";
|
|
1000
|
+
}
|
|
1001
|
+
throw new TypeError(msg);
|
|
1002
|
+
}
|
|
1003
|
+
case "primitive": if (typeof value === "number" && !isFinite(value)) {
|
|
1004
|
+
if (this.encodingLevel === "structuredClonable") return value;
|
|
1005
|
+
if (value === Infinity) return ["inf"];
|
|
1006
|
+
else if (value === -Infinity) return ["-inf"];
|
|
1007
|
+
else return ["nan"];
|
|
1008
|
+
} else return value;
|
|
1009
|
+
case "object": {
|
|
1010
|
+
let object = value;
|
|
1011
|
+
let result = {};
|
|
1012
|
+
for (let key in object) result[key] = this.devaluateImpl(object[key], object, depth + 1);
|
|
1013
|
+
return result;
|
|
1014
|
+
}
|
|
1015
|
+
case "array": {
|
|
1016
|
+
let array = value;
|
|
1017
|
+
let len = array.length;
|
|
1018
|
+
let result = new Array(len);
|
|
1019
|
+
for (let i = 0; i < len; i++) result[i] = this.devaluateImpl(array[i], array, depth + 1);
|
|
1020
|
+
return [result];
|
|
1021
|
+
}
|
|
1022
|
+
case "bigint":
|
|
1023
|
+
if (this.encodingLevel === "structuredClonable") return value;
|
|
1024
|
+
return ["bigint", value.toString()];
|
|
1025
|
+
case "date": {
|
|
1026
|
+
if (this.encodingLevel === "structuredClonable") return value;
|
|
1027
|
+
const time = value.getTime();
|
|
1028
|
+
return ["date", Number.isNaN(time) ? null : time];
|
|
1029
|
+
}
|
|
1030
|
+
case "bytes": {
|
|
1031
|
+
let bytes = value;
|
|
1032
|
+
if (this.encodingLevel === "structuredClonable" || this.encodingLevel === "jsonCompatibleWithBytes") return ["bytes", bytes];
|
|
1033
|
+
if (bytes.toBase64) return ["bytes", bytes.toBase64({ omitPadding: true })];
|
|
1034
|
+
let b64;
|
|
1035
|
+
if (typeof Buffer !== "undefined") b64 = (bytes instanceof Buffer ? bytes : Buffer.from(bytes.buffer, bytes.byteOffset, bytes.byteLength)).toString("base64");
|
|
1036
|
+
else {
|
|
1037
|
+
let binary = "";
|
|
1038
|
+
for (let i = 0; i < bytes.length; i++) binary += String.fromCharCode(bytes[i]);
|
|
1039
|
+
b64 = btoa(binary);
|
|
1040
|
+
}
|
|
1041
|
+
return ["bytes", b64.replace(/=+$/, "")];
|
|
1042
|
+
}
|
|
1043
|
+
case "headers": return ["headers", [...value]];
|
|
1044
|
+
case "request": {
|
|
1045
|
+
let req = value;
|
|
1046
|
+
let init = {};
|
|
1047
|
+
if (req.method !== "GET") init.method = req.method;
|
|
1048
|
+
let headers = [...req.headers];
|
|
1049
|
+
if (headers.length > 0) init.headers = headers;
|
|
1050
|
+
if (req.body) {
|
|
1051
|
+
init.body = this.devaluateImpl(req.body, req, depth + 1);
|
|
1052
|
+
init.duplex = req.duplex || "half";
|
|
1053
|
+
} else if (req.body === void 0 && ![
|
|
1054
|
+
"GET",
|
|
1055
|
+
"HEAD",
|
|
1056
|
+
"OPTIONS",
|
|
1057
|
+
"TRACE",
|
|
1058
|
+
"DELETE"
|
|
1059
|
+
].includes(req.method)) {
|
|
1060
|
+
let bodyPromise = req.arrayBuffer();
|
|
1061
|
+
let readable = new ReadableStream({ async start(controller) {
|
|
1062
|
+
try {
|
|
1063
|
+
controller.enqueue(new Uint8Array(await bodyPromise));
|
|
1064
|
+
controller.close();
|
|
1065
|
+
} catch (err) {
|
|
1066
|
+
controller.error(err);
|
|
1067
|
+
}
|
|
1068
|
+
} });
|
|
1069
|
+
let hook = streamImpl.createReadableStreamHook(readable);
|
|
1070
|
+
init.body = ["readable", this.exporter.createPipe(readable, hook)];
|
|
1071
|
+
init.duplex = req.duplex || "half";
|
|
1072
|
+
}
|
|
1073
|
+
if (req.cache && req.cache !== "default") init.cache = req.cache;
|
|
1074
|
+
if (req.redirect !== "follow") init.redirect = req.redirect;
|
|
1075
|
+
if (req.integrity) init.integrity = req.integrity;
|
|
1076
|
+
if (req.mode && req.mode !== "cors") init.mode = req.mode;
|
|
1077
|
+
if (req.credentials && req.credentials !== "same-origin") init.credentials = req.credentials;
|
|
1078
|
+
if (req.referrer && req.referrer !== "about:client") init.referrer = req.referrer;
|
|
1079
|
+
if (req.referrerPolicy) init.referrerPolicy = req.referrerPolicy;
|
|
1080
|
+
if (req.keepalive) init.keepalive = req.keepalive;
|
|
1081
|
+
let cfReq = req;
|
|
1082
|
+
if (cfReq.cf) init.cf = cfReq.cf;
|
|
1083
|
+
if (cfReq.encodeResponseBody && cfReq.encodeResponseBody !== "automatic") init.encodeResponseBody = cfReq.encodeResponseBody;
|
|
1084
|
+
return [
|
|
1085
|
+
"request",
|
|
1086
|
+
req.url,
|
|
1087
|
+
init
|
|
1088
|
+
];
|
|
1089
|
+
}
|
|
1090
|
+
case "response": {
|
|
1091
|
+
let resp = value;
|
|
1092
|
+
let body = this.devaluateImpl(resp.body, resp, depth + 1);
|
|
1093
|
+
let init = {};
|
|
1094
|
+
if (resp.status !== 200) init.status = resp.status;
|
|
1095
|
+
if (resp.statusText) init.statusText = resp.statusText;
|
|
1096
|
+
let headers = [...resp.headers];
|
|
1097
|
+
if (headers.length > 0) init.headers = headers;
|
|
1098
|
+
let cfResp = resp;
|
|
1099
|
+
if (cfResp.cf) init.cf = cfResp.cf;
|
|
1100
|
+
if (cfResp.encodeBody && cfResp.encodeBody !== "automatic") init.encodeBody = cfResp.encodeBody;
|
|
1101
|
+
if (cfResp.webSocket) throw new TypeError("Can't serialize a Response containing a webSocket.");
|
|
1102
|
+
return [
|
|
1103
|
+
"response",
|
|
1104
|
+
body,
|
|
1105
|
+
init
|
|
1106
|
+
];
|
|
1107
|
+
}
|
|
1108
|
+
case "blob": {
|
|
1109
|
+
let blob = value;
|
|
1110
|
+
let readable = blob.stream();
|
|
1111
|
+
let hook = streamImpl.createReadableStreamHook(readable);
|
|
1112
|
+
let importId = this.exporter.createPipe(readable, hook);
|
|
1113
|
+
return [
|
|
1114
|
+
"blob",
|
|
1115
|
+
blob.type,
|
|
1116
|
+
["readable", importId]
|
|
1117
|
+
];
|
|
1118
|
+
}
|
|
1119
|
+
case "error": {
|
|
1120
|
+
let e = value;
|
|
1121
|
+
let rewritten = this.exporter.onSendError(e);
|
|
1122
|
+
if (rewritten) e = rewritten;
|
|
1123
|
+
let anyE = e;
|
|
1124
|
+
let props;
|
|
1125
|
+
let captureProp = (key, val) => {
|
|
1126
|
+
let exportsBefore = this.exports?.length ?? 0;
|
|
1127
|
+
try {
|
|
1128
|
+
let encoded = this.devaluateImpl(val, e, depth + 1);
|
|
1129
|
+
if (!props) props = {};
|
|
1130
|
+
props[key] = encoded;
|
|
1131
|
+
} catch (err) {
|
|
1132
|
+
if (this.exports && this.exports.length > exportsBefore) {
|
|
1133
|
+
let tail = this.exports.splice(exportsBefore);
|
|
1134
|
+
try {
|
|
1135
|
+
this.exporter.unexport(tail);
|
|
1136
|
+
} catch (err2) {}
|
|
1137
|
+
}
|
|
1138
|
+
}
|
|
1139
|
+
};
|
|
1140
|
+
for (let key of Object.keys(e)) {
|
|
1141
|
+
if (key === "name" || key === "message" || key === "stack") continue;
|
|
1142
|
+
captureProp(key, anyE[key]);
|
|
1143
|
+
}
|
|
1144
|
+
if ("cause" in e) captureProp("cause", anyE.cause);
|
|
1145
|
+
if (e instanceof AggregateError) captureProp("errors", e.errors);
|
|
1146
|
+
let result = [
|
|
1147
|
+
"error",
|
|
1148
|
+
e.name,
|
|
1149
|
+
e.message
|
|
1150
|
+
];
|
|
1151
|
+
if (props) {
|
|
1152
|
+
result.push(rewritten && rewritten.stack ? rewritten.stack : null);
|
|
1153
|
+
result.push(props);
|
|
1154
|
+
} else if (rewritten && rewritten.stack) result.push(rewritten.stack);
|
|
1155
|
+
return result;
|
|
1156
|
+
}
|
|
1157
|
+
case "undefined":
|
|
1158
|
+
if (this.encodingLevel === "structuredClonable") return;
|
|
1159
|
+
return ["undefined"];
|
|
1160
|
+
case "stub":
|
|
1161
|
+
case "rpc-promise": {
|
|
1162
|
+
if (!this.source) throw new Error("Can't serialize RPC stubs in this context.");
|
|
1163
|
+
let { hook, pathIfPromise } = unwrapStubAndPath(value);
|
|
1164
|
+
let importId = this.exporter.getImport(hook);
|
|
1165
|
+
if (importId !== void 0) if (pathIfPromise) if (pathIfPromise.length > 0) return [
|
|
1166
|
+
"pipeline",
|
|
1167
|
+
importId,
|
|
1168
|
+
pathIfPromise
|
|
1169
|
+
];
|
|
1170
|
+
else return ["pipeline", importId];
|
|
1171
|
+
else return ["import", importId];
|
|
1172
|
+
if (pathIfPromise) hook = hook.get(pathIfPromise);
|
|
1173
|
+
else hook = hook.dup();
|
|
1174
|
+
return this.devaluateHook(pathIfPromise ? "promise" : "export", hook);
|
|
1175
|
+
}
|
|
1176
|
+
case "function":
|
|
1177
|
+
case "rpc-target": {
|
|
1178
|
+
if (!this.source) throw new Error("Can't serialize RPC stubs in this context.");
|
|
1179
|
+
let hook = this.source.getHookForRpcTarget(value, parent);
|
|
1180
|
+
return this.devaluateHook("export", hook);
|
|
1181
|
+
}
|
|
1182
|
+
case "rpc-thenable": {
|
|
1183
|
+
if (!this.source) throw new Error("Can't serialize RPC stubs in this context.");
|
|
1184
|
+
let hook = this.source.getHookForRpcTarget(value, parent);
|
|
1185
|
+
return this.devaluateHook("promise", hook);
|
|
1186
|
+
}
|
|
1187
|
+
case "writable": {
|
|
1188
|
+
if (!this.source) throw new Error("Can't serialize WritableStream in this context.");
|
|
1189
|
+
let hook = this.source.getHookForWritableStream(value, parent);
|
|
1190
|
+
return this.devaluateHook("writable", hook);
|
|
1191
|
+
}
|
|
1192
|
+
case "readable": {
|
|
1193
|
+
if (!this.source) throw new Error("Can't serialize ReadableStream in this context.");
|
|
1194
|
+
let ws = value;
|
|
1195
|
+
let hook = this.source.getHookForReadableStream(ws, parent);
|
|
1196
|
+
return ["readable", this.exporter.createPipe(ws, hook)];
|
|
1197
|
+
}
|
|
1198
|
+
default: throw new Error("unreachable");
|
|
1199
|
+
}
|
|
1200
|
+
}
|
|
1201
|
+
devaluateHook(type, hook) {
|
|
1202
|
+
if (!this.exports) this.exports = [];
|
|
1203
|
+
let exportId = type === "promise" ? this.exporter.exportPromise(hook) : this.exporter.exportStub(hook);
|
|
1204
|
+
this.exports.push(exportId);
|
|
1205
|
+
return [type, exportId];
|
|
1206
|
+
}
|
|
1207
|
+
};
|
|
1208
|
+
/**
|
|
1209
|
+
* Serialize a value, using Cap'n Web's underlying serialization. This won't be able to serialize
|
|
1210
|
+
* RPC stubs, but it will support basic data types.
|
|
1211
|
+
*/
|
|
1212
|
+
function serialize(value) {
|
|
1213
|
+
return JSON.stringify(Devaluator.devaluate(value));
|
|
1214
|
+
}
|
|
1215
|
+
var NullImporter = class {
|
|
1216
|
+
importStub(idx) {
|
|
1217
|
+
throw new Error("Cannot deserialize RPC stubs without an RPC session.");
|
|
1218
|
+
}
|
|
1219
|
+
importPromise(idx) {
|
|
1220
|
+
throw new Error("Cannot deserialize RPC stubs without an RPC session.");
|
|
1221
|
+
}
|
|
1222
|
+
getExport(idx) {}
|
|
1223
|
+
getPipeReadable(exportId) {
|
|
1224
|
+
throw new Error("Cannot retrieve pipe readable without an RPC session.");
|
|
1225
|
+
}
|
|
1226
|
+
getLimits() {
|
|
1227
|
+
return DEFAULT_LIMITS;
|
|
1228
|
+
}
|
|
1229
|
+
};
|
|
1230
|
+
const NULL_IMPORTER = new NullImporter();
|
|
1231
|
+
function fixBrokenRequestBody(request, body) {
|
|
1232
|
+
return new RpcPromise$1(new PromiseStubHook(new Response(body).arrayBuffer().then((arrayBuffer) => {
|
|
1233
|
+
let bytes = new Uint8Array(arrayBuffer);
|
|
1234
|
+
let result = new Request(request, { body: bytes });
|
|
1235
|
+
return new PayloadStubHook(RpcPayload.fromAppReturn(result));
|
|
1236
|
+
})), []);
|
|
1237
|
+
}
|
|
1238
|
+
function streamToBlobPromise(stream, type) {
|
|
1239
|
+
return new RpcPromise$1(new PromiseStubHook(streamToBlob(stream, type).then((blob) => {
|
|
1240
|
+
return new PayloadStubHook(RpcPayload.fromAppReturn(blob));
|
|
1241
|
+
})), []);
|
|
1242
|
+
}
|
|
1243
|
+
var Evaluator = class Evaluator {
|
|
1244
|
+
importer;
|
|
1245
|
+
encodingLevel;
|
|
1246
|
+
limits;
|
|
1247
|
+
constructor(importer, encodingLevel = "string") {
|
|
1248
|
+
this.importer = importer;
|
|
1249
|
+
this.encodingLevel = encodingLevel;
|
|
1250
|
+
this.limits = importer.getLimits();
|
|
1251
|
+
}
|
|
1252
|
+
hooks = [];
|
|
1253
|
+
promises = [];
|
|
1254
|
+
evaluate(value) {
|
|
1255
|
+
return this.evaluateWithDepth(value, 0);
|
|
1256
|
+
}
|
|
1257
|
+
evaluateWithDepth(value, depth) {
|
|
1258
|
+
let payload = RpcPayload.forEvaluate(this.hooks, this.promises);
|
|
1259
|
+
try {
|
|
1260
|
+
payload.value = this.evaluateImpl(value, payload, "value", depth);
|
|
1261
|
+
return payload;
|
|
1262
|
+
} catch (err) {
|
|
1263
|
+
payload.dispose();
|
|
1264
|
+
throw err;
|
|
1265
|
+
}
|
|
1266
|
+
}
|
|
1267
|
+
evaluateCopy(value) {
|
|
1268
|
+
return this.evaluate(structuredClone(value));
|
|
1269
|
+
}
|
|
1270
|
+
evaluateImpl(value, parent, property, depth) {
|
|
1271
|
+
let maxDepth = this.limits.maxDepth;
|
|
1272
|
+
if (depth >= maxDepth) throw new TypeError(`Deserialization exceeded maximum allowed message depth of ${maxDepth}.`);
|
|
1273
|
+
if (this.encodingLevel === "structuredClonable") {
|
|
1274
|
+
if (value instanceof Date || typeof value === "bigint") return value;
|
|
1275
|
+
}
|
|
1276
|
+
if (value instanceof Array) {
|
|
1277
|
+
if (value.length == 1 && value[0] instanceof Array) {
|
|
1278
|
+
let result = value[0];
|
|
1279
|
+
for (let i = 0; i < result.length; i++) result[i] = this.evaluateImpl(result[i], result, i, depth + 1);
|
|
1280
|
+
return result;
|
|
1281
|
+
} else switch (value[0]) {
|
|
1282
|
+
case "bigint":
|
|
1283
|
+
if (typeof value[1] == "string") {
|
|
1284
|
+
let digits = value[1];
|
|
1285
|
+
let maxBigIntDigits = this.limits.maxBigIntDigits;
|
|
1286
|
+
if (digits.length > maxBigIntDigits) throw new TypeError(`Deserialized bigint exceeds maximum length of ${maxBigIntDigits} digits.`);
|
|
1287
|
+
return BigInt(digits);
|
|
1288
|
+
}
|
|
1289
|
+
break;
|
|
1290
|
+
case "date":
|
|
1291
|
+
if (value[1] === null) return /* @__PURE__ */ new Date(NaN);
|
|
1292
|
+
if (typeof value[1] == "number") return new Date(value[1]);
|
|
1293
|
+
break;
|
|
1294
|
+
case "bytes":
|
|
1295
|
+
if (value[1] instanceof Uint8Array) return value[1];
|
|
1296
|
+
if (typeof value[1] == "string") if (typeof Buffer !== "undefined") return Buffer.from(value[1], "base64");
|
|
1297
|
+
else if (Uint8Array.fromBase64) return Uint8Array.fromBase64(value[1]);
|
|
1298
|
+
else {
|
|
1299
|
+
let bs = atob(value[1]);
|
|
1300
|
+
let len = bs.length;
|
|
1301
|
+
let bytes = new Uint8Array(len);
|
|
1302
|
+
for (let i = 0; i < len; i++) bytes[i] = bs.charCodeAt(i);
|
|
1303
|
+
return bytes;
|
|
1304
|
+
}
|
|
1305
|
+
break;
|
|
1306
|
+
case "error":
|
|
1307
|
+
if (value.length >= 3 && typeof value[1] === "string" && typeof value[2] === "string") {
|
|
1308
|
+
let cls = ERROR_TYPES[value[1]] || Error;
|
|
1309
|
+
let result = cls === AggregateError ? new cls([], value[2]) : new cls(value[2]);
|
|
1310
|
+
if (typeof value[3] === "string") result.stack = value[3];
|
|
1311
|
+
if (value.length >= 5) {
|
|
1312
|
+
let props = value[4];
|
|
1313
|
+
if (!props || typeof props !== "object" || Array.isArray(props)) break;
|
|
1314
|
+
let anyResult = result;
|
|
1315
|
+
let propsObj = props;
|
|
1316
|
+
for (let key of Object.keys(propsObj)) {
|
|
1317
|
+
if (key === "name" || key === "message" || key === "stack") continue;
|
|
1318
|
+
if (key in Object.prototype || key === "toJSON") {
|
|
1319
|
+
this.evaluateImpl(propsObj[key], result, key, depth + 1);
|
|
1320
|
+
continue;
|
|
1321
|
+
}
|
|
1322
|
+
anyResult[key] = this.evaluateImpl(propsObj[key], result, key, depth + 1);
|
|
1323
|
+
}
|
|
1324
|
+
}
|
|
1325
|
+
return result;
|
|
1326
|
+
}
|
|
1327
|
+
break;
|
|
1328
|
+
case "undefined":
|
|
1329
|
+
if (value.length === 1) return;
|
|
1330
|
+
break;
|
|
1331
|
+
case "inf": return Infinity;
|
|
1332
|
+
case "-inf": return -Infinity;
|
|
1333
|
+
case "nan": return NaN;
|
|
1334
|
+
case "headers":
|
|
1335
|
+
if (value.length === 2 && value[1] instanceof Array) return new Headers(value[1]);
|
|
1336
|
+
break;
|
|
1337
|
+
case "request": {
|
|
1338
|
+
if (value.length !== 3 || typeof value[1] !== "string") break;
|
|
1339
|
+
let url = value[1];
|
|
1340
|
+
let init = value[2];
|
|
1341
|
+
if (typeof init !== "object" || init === null) break;
|
|
1342
|
+
if (init.body) {
|
|
1343
|
+
init.body = this.evaluateImpl(init.body, init, "body", depth + 1);
|
|
1344
|
+
if (init.body === null || typeof init.body === "string" || init.body instanceof Uint8Array || init.body instanceof ReadableStream) {} else throw new TypeError("Request body must be of type ReadableStream.");
|
|
1345
|
+
}
|
|
1346
|
+
if (init.signal) {
|
|
1347
|
+
init.signal = this.evaluateImpl(init.signal, init, "signal", depth + 1);
|
|
1348
|
+
if (!(init.signal instanceof AbortSignal)) throw new TypeError("Request siganl must be of type AbortSignal.");
|
|
1349
|
+
}
|
|
1350
|
+
if (init.headers && !(init.headers instanceof Array)) throw new TypeError("Request headers must be serialized as an array of pairs.");
|
|
1351
|
+
let result = new Request(url, init);
|
|
1352
|
+
if (init.body instanceof ReadableStream && result.body === void 0) {
|
|
1353
|
+
let promise = fixBrokenRequestBody(result, init.body);
|
|
1354
|
+
this.promises.push({
|
|
1355
|
+
promise,
|
|
1356
|
+
parent,
|
|
1357
|
+
property
|
|
1358
|
+
});
|
|
1359
|
+
return promise;
|
|
1360
|
+
} else return result;
|
|
1361
|
+
}
|
|
1362
|
+
case "response": {
|
|
1363
|
+
if (value.length !== 3) break;
|
|
1364
|
+
let body = this.evaluateImpl(value[1], parent, property, depth + 1);
|
|
1365
|
+
if (body === null || typeof body === "string" || body instanceof Uint8Array || body instanceof ReadableStream) {} else throw new TypeError("Response body must be of type ReadableStream.");
|
|
1366
|
+
let init = value[2];
|
|
1367
|
+
if (typeof init !== "object" || init === null) break;
|
|
1368
|
+
if (init.webSocket) throw new TypeError("Can't deserialize a Response containing a webSocket.");
|
|
1369
|
+
if (init.headers && !(init.headers instanceof Array)) throw new TypeError("Request headers must be serialized as an array of pairs.");
|
|
1370
|
+
return new Response(body, init);
|
|
1371
|
+
}
|
|
1372
|
+
case "blob": {
|
|
1373
|
+
if (value.length !== 3 || typeof value[1] !== "string") break;
|
|
1374
|
+
let contentType = value[1];
|
|
1375
|
+
let content = this.evaluateImpl(value[2], parent, property, depth + 1);
|
|
1376
|
+
if (!(content instanceof ReadableStream)) throw new TypeError("Blob content must be serialized as a ReadableStream.");
|
|
1377
|
+
let promise = streamToBlobPromise(content, contentType);
|
|
1378
|
+
this.promises.push({
|
|
1379
|
+
promise,
|
|
1380
|
+
parent,
|
|
1381
|
+
property
|
|
1382
|
+
});
|
|
1383
|
+
return promise;
|
|
1384
|
+
}
|
|
1385
|
+
case "import":
|
|
1386
|
+
case "pipeline": {
|
|
1387
|
+
if (value.length < 2 || value.length > 4) break;
|
|
1388
|
+
if (typeof value[1] != "number") break;
|
|
1389
|
+
let hook = this.importer.getExport(value[1]);
|
|
1390
|
+
if (!hook) throw new Error(`no such entry on exports table: ${value[1]}`);
|
|
1391
|
+
let isPromise = value[0] == "pipeline";
|
|
1392
|
+
let addStub = (hook) => {
|
|
1393
|
+
if (isPromise) {
|
|
1394
|
+
let promise = new RpcPromise$1(hook, []);
|
|
1395
|
+
this.promises.push({
|
|
1396
|
+
promise,
|
|
1397
|
+
parent,
|
|
1398
|
+
property
|
|
1399
|
+
});
|
|
1400
|
+
return promise;
|
|
1401
|
+
} else {
|
|
1402
|
+
this.hooks.push(hook);
|
|
1403
|
+
return new RpcPromise$1(hook, []);
|
|
1404
|
+
}
|
|
1405
|
+
};
|
|
1406
|
+
if (value.length == 2) if (isPromise) return addStub(hook.get([]));
|
|
1407
|
+
else return addStub(hook.dup());
|
|
1408
|
+
let path = value[2];
|
|
1409
|
+
if (!(path instanceof Array)) break;
|
|
1410
|
+
if (!path.every((part) => {
|
|
1411
|
+
return typeof part == "string" || typeof part == "number";
|
|
1412
|
+
})) break;
|
|
1413
|
+
if (value.length == 3) return addStub(hook.get(path));
|
|
1414
|
+
let args = value[3];
|
|
1415
|
+
if (!(args instanceof Array)) break;
|
|
1416
|
+
args = new Evaluator(this.importer).evaluateWithDepth([args], depth);
|
|
1417
|
+
return addStub(hook.call(path, args));
|
|
1418
|
+
}
|
|
1419
|
+
case "remap": {
|
|
1420
|
+
if (value.length !== 5 || typeof value[1] !== "number" || !(value[2] instanceof Array) || !(value[3] instanceof Array) || !(value[4] instanceof Array)) break;
|
|
1421
|
+
let hook = this.importer.getExport(value[1]);
|
|
1422
|
+
if (!hook) throw new Error(`no such entry on exports table: ${value[1]}`);
|
|
1423
|
+
let path = value[2];
|
|
1424
|
+
if (!path.every((part) => {
|
|
1425
|
+
return typeof part == "string" || typeof part == "number";
|
|
1426
|
+
})) break;
|
|
1427
|
+
let captures = value[3].map((cap) => {
|
|
1428
|
+
if (!(cap instanceof Array) || cap.length !== 2 || cap[0] !== "import" && cap[0] !== "export" || typeof cap[1] !== "number") throw new TypeError(`unknown map capture: ${JSON.stringify(cap)}`);
|
|
1429
|
+
if (cap[0] === "export") return this.importer.importStub(cap[1]);
|
|
1430
|
+
else {
|
|
1431
|
+
let exp = this.importer.getExport(cap[1]);
|
|
1432
|
+
if (!exp) throw new Error(`no such entry on exports table: ${cap[1]}`);
|
|
1433
|
+
return exp.dup();
|
|
1434
|
+
}
|
|
1435
|
+
});
|
|
1436
|
+
let instructions = value[4];
|
|
1437
|
+
let promise = new RpcPromise$1(hook.map(path, captures, instructions), []);
|
|
1438
|
+
this.promises.push({
|
|
1439
|
+
promise,
|
|
1440
|
+
parent,
|
|
1441
|
+
property
|
|
1442
|
+
});
|
|
1443
|
+
return promise;
|
|
1444
|
+
}
|
|
1445
|
+
case "export":
|
|
1446
|
+
case "promise":
|
|
1447
|
+
if (typeof value[1] == "number") if (value[0] == "promise") {
|
|
1448
|
+
let promise = new RpcPromise$1(this.importer.importPromise(value[1]), []);
|
|
1449
|
+
this.promises.push({
|
|
1450
|
+
parent,
|
|
1451
|
+
property,
|
|
1452
|
+
promise
|
|
1453
|
+
});
|
|
1454
|
+
return promise;
|
|
1455
|
+
} else {
|
|
1456
|
+
let hook = this.importer.importStub(value[1]);
|
|
1457
|
+
this.hooks.push(hook);
|
|
1458
|
+
return new RpcStub$1(hook);
|
|
1459
|
+
}
|
|
1460
|
+
break;
|
|
1461
|
+
case "writable":
|
|
1462
|
+
if (typeof value[1] == "number") {
|
|
1463
|
+
let hook = this.importer.importStub(value[1]);
|
|
1464
|
+
let stream = streamImpl.createWritableStreamFromHook(hook);
|
|
1465
|
+
this.hooks.push(hook);
|
|
1466
|
+
return stream;
|
|
1467
|
+
}
|
|
1468
|
+
break;
|
|
1469
|
+
case "readable":
|
|
1470
|
+
if (typeof value[1] == "number") {
|
|
1471
|
+
let stream = this.importer.getPipeReadable(value[1]);
|
|
1472
|
+
let hook = streamImpl.createReadableStreamHook(stream);
|
|
1473
|
+
this.hooks.push(hook);
|
|
1474
|
+
return stream;
|
|
1475
|
+
}
|
|
1476
|
+
break;
|
|
1477
|
+
}
|
|
1478
|
+
throw new TypeError(`unknown special value: ${JSON.stringify(value)}`);
|
|
1479
|
+
} else if (value instanceof Object) {
|
|
1480
|
+
let result = value;
|
|
1481
|
+
for (let key in result) if (key in Object.prototype || key === "toJSON") {
|
|
1482
|
+
this.evaluateImpl(result[key], result, key, depth + 1);
|
|
1483
|
+
delete result[key];
|
|
1484
|
+
} else result[key] = this.evaluateImpl(result[key], result, key, depth + 1);
|
|
1485
|
+
return result;
|
|
1486
|
+
} else return value;
|
|
1487
|
+
}
|
|
1488
|
+
};
|
|
1489
|
+
/**
|
|
1490
|
+
* Deserialize a value serialized using serialize().
|
|
1491
|
+
*/
|
|
1492
|
+
function deserialize(value) {
|
|
1493
|
+
let payload = new Evaluator(NULL_IMPORTER).evaluate(JSON.parse(value));
|
|
1494
|
+
payload.dispose();
|
|
1495
|
+
return payload.value;
|
|
1496
|
+
}
|
|
1497
|
+
|
|
1498
|
+
//#endregion
|
|
1499
|
+
//#region src/rpc.ts
|
|
1500
|
+
const ESTIMATED_OBJECT_OVERHEAD = 16;
|
|
1501
|
+
const ESTIMATED_ENTRY_OVERHEAD = 8;
|
|
1502
|
+
const ESTIMATED_BINARY_OVERHEAD = 16;
|
|
1503
|
+
const MAX_ESTIMATE_DEPTH = 64;
|
|
1504
|
+
function estimateStringSize(value) {
|
|
1505
|
+
return 2 + value.length * 3;
|
|
1506
|
+
}
|
|
1507
|
+
function estimateEncodedSize(value, seen, depth = 0) {
|
|
1508
|
+
if (depth >= MAX_ESTIMATE_DEPTH) return ESTIMATED_ENTRY_OVERHEAD;
|
|
1509
|
+
switch (typeof value) {
|
|
1510
|
+
case "string": return estimateStringSize(value);
|
|
1511
|
+
case "number": return 16;
|
|
1512
|
+
case "bigint": return 16;
|
|
1513
|
+
case "boolean": return 8;
|
|
1514
|
+
case "undefined": return 16;
|
|
1515
|
+
case "object": {
|
|
1516
|
+
if (value === null) return 8;
|
|
1517
|
+
if (ArrayBuffer.isView(value)) return ESTIMATED_BINARY_OVERHEAD + value.byteLength;
|
|
1518
|
+
if (value instanceof ArrayBuffer) return ESTIMATED_BINARY_OVERHEAD + value.byteLength;
|
|
1519
|
+
if (typeof Blob !== "undefined" && value instanceof Blob) return ESTIMATED_BINARY_OVERHEAD + value.size;
|
|
1520
|
+
if (value instanceof Date) return 16;
|
|
1521
|
+
seen ??= /* @__PURE__ */ new WeakSet();
|
|
1522
|
+
if (seen.has(value)) return ESTIMATED_ENTRY_OVERHEAD;
|
|
1523
|
+
seen.add(value);
|
|
1524
|
+
if (value instanceof Array) {
|
|
1525
|
+
let size = ESTIMATED_OBJECT_OVERHEAD;
|
|
1526
|
+
for (let item of value) size += ESTIMATED_ENTRY_OVERHEAD + estimateEncodedSize(item, seen, depth + 1);
|
|
1527
|
+
return size;
|
|
1528
|
+
}
|
|
1529
|
+
if (value instanceof Error) {
|
|
1530
|
+
let size = ESTIMATED_OBJECT_OVERHEAD + estimateStringSize(value.name) + estimateStringSize(value.message) + estimateStringSize(value.stack ?? "");
|
|
1531
|
+
for (let key of Object.keys(value)) size += ESTIMATED_ENTRY_OVERHEAD + estimateStringSize(key) + estimateEncodedSize(value[key], seen, depth + 1);
|
|
1532
|
+
return size;
|
|
1533
|
+
}
|
|
1534
|
+
let size = ESTIMATED_OBJECT_OVERHEAD;
|
|
1535
|
+
for (let key of Object.keys(value)) size += ESTIMATED_ENTRY_OVERHEAD + estimateStringSize(key) + estimateEncodedSize(value[key], seen, depth + 1);
|
|
1536
|
+
return size;
|
|
1537
|
+
}
|
|
1538
|
+
default: return 16;
|
|
1539
|
+
}
|
|
1540
|
+
}
|
|
1541
|
+
var ImportTableEntry = class {
|
|
1542
|
+
session;
|
|
1543
|
+
importId;
|
|
1544
|
+
constructor(session, importId, pulling) {
|
|
1545
|
+
this.session = session;
|
|
1546
|
+
this.importId = importId;
|
|
1547
|
+
if (pulling) this.activePull = Promise.withResolvers();
|
|
1548
|
+
}
|
|
1549
|
+
localRefcount = 0;
|
|
1550
|
+
remoteRefcount = 1;
|
|
1551
|
+
activePull;
|
|
1552
|
+
resolution;
|
|
1553
|
+
onBrokenRegistrations;
|
|
1554
|
+
resolve(resolution) {
|
|
1555
|
+
if (this.localRefcount == 0) {
|
|
1556
|
+
resolution.dispose();
|
|
1557
|
+
return;
|
|
1558
|
+
}
|
|
1559
|
+
this.resolution = resolution;
|
|
1560
|
+
this.sendRelease();
|
|
1561
|
+
if (this.onBrokenRegistrations) {
|
|
1562
|
+
for (let i of this.onBrokenRegistrations) {
|
|
1563
|
+
let callback = this.session.onBrokenCallbacks[i];
|
|
1564
|
+
let endIndex = this.session.onBrokenCallbacks.length;
|
|
1565
|
+
resolution.onBroken(callback);
|
|
1566
|
+
if (this.session.onBrokenCallbacks[endIndex] === callback) delete this.session.onBrokenCallbacks[endIndex];
|
|
1567
|
+
else delete this.session.onBrokenCallbacks[i];
|
|
1568
|
+
}
|
|
1569
|
+
this.onBrokenRegistrations = void 0;
|
|
1570
|
+
}
|
|
1571
|
+
if (this.activePull) {
|
|
1572
|
+
this.activePull.resolve();
|
|
1573
|
+
this.activePull = void 0;
|
|
1574
|
+
}
|
|
1575
|
+
}
|
|
1576
|
+
async awaitResolution() {
|
|
1577
|
+
if (!this.activePull) {
|
|
1578
|
+
this.session.sendPull(this.importId);
|
|
1579
|
+
this.activePull = Promise.withResolvers();
|
|
1580
|
+
}
|
|
1581
|
+
await this.activePull.promise;
|
|
1582
|
+
return this.resolution.pull();
|
|
1583
|
+
}
|
|
1584
|
+
dispose() {
|
|
1585
|
+
if (this.resolution) this.resolution.dispose();
|
|
1586
|
+
else {
|
|
1587
|
+
this.abort(/* @__PURE__ */ new Error("RPC was canceled because the RpcPromise was disposed."));
|
|
1588
|
+
this.sendRelease();
|
|
1589
|
+
}
|
|
1590
|
+
}
|
|
1591
|
+
abort(error) {
|
|
1592
|
+
if (!this.resolution) {
|
|
1593
|
+
this.resolution = new ErrorStubHook(error);
|
|
1594
|
+
if (this.activePull) {
|
|
1595
|
+
this.activePull.reject(error);
|
|
1596
|
+
this.activePull = void 0;
|
|
1597
|
+
}
|
|
1598
|
+
this.onBrokenRegistrations = void 0;
|
|
1599
|
+
}
|
|
1600
|
+
}
|
|
1601
|
+
onBroken(callback) {
|
|
1602
|
+
if (this.resolution) this.resolution.onBroken(callback);
|
|
1603
|
+
else {
|
|
1604
|
+
let index = this.session.onBrokenCallbacks.length;
|
|
1605
|
+
this.session.onBrokenCallbacks.push(callback);
|
|
1606
|
+
if (!this.onBrokenRegistrations) this.onBrokenRegistrations = [];
|
|
1607
|
+
this.onBrokenRegistrations.push(index);
|
|
1608
|
+
}
|
|
1609
|
+
}
|
|
1610
|
+
sendRelease() {
|
|
1611
|
+
if (this.remoteRefcount > 0) {
|
|
1612
|
+
this.session.sendRelease(this.importId, this.remoteRefcount);
|
|
1613
|
+
this.remoteRefcount = 0;
|
|
1614
|
+
}
|
|
1615
|
+
}
|
|
1616
|
+
};
|
|
1617
|
+
var RpcImportHook = class RpcImportHook extends StubHook {
|
|
1618
|
+
isPromise;
|
|
1619
|
+
entry;
|
|
1620
|
+
constructor(isPromise, entry) {
|
|
1621
|
+
super();
|
|
1622
|
+
this.isPromise = isPromise;
|
|
1623
|
+
++entry.localRefcount;
|
|
1624
|
+
this.entry = entry;
|
|
1625
|
+
}
|
|
1626
|
+
collectPath(path) {
|
|
1627
|
+
return this;
|
|
1628
|
+
}
|
|
1629
|
+
getEntry() {
|
|
1630
|
+
if (this.entry) return this.entry;
|
|
1631
|
+
else throw new Error("This RpcImportHook was already disposed.");
|
|
1632
|
+
}
|
|
1633
|
+
call(path, args) {
|
|
1634
|
+
let entry = this.getEntry();
|
|
1635
|
+
if (entry.resolution) return entry.resolution.call(path, args);
|
|
1636
|
+
else return entry.session.sendCall(entry.importId, path, args);
|
|
1637
|
+
}
|
|
1638
|
+
stream(path, args) {
|
|
1639
|
+
let entry = this.getEntry();
|
|
1640
|
+
if (entry.resolution) return entry.resolution.stream(path, args);
|
|
1641
|
+
else return entry.session.sendStream(entry.importId, path, args);
|
|
1642
|
+
}
|
|
1643
|
+
map(path, captures, instructions) {
|
|
1644
|
+
let entry;
|
|
1645
|
+
try {
|
|
1646
|
+
entry = this.getEntry();
|
|
1647
|
+
} catch (err) {
|
|
1648
|
+
for (let cap of captures) cap.dispose();
|
|
1649
|
+
throw err;
|
|
1650
|
+
}
|
|
1651
|
+
if (entry.resolution) return entry.resolution.map(path, captures, instructions);
|
|
1652
|
+
else return entry.session.sendMap(entry.importId, path, captures, instructions);
|
|
1653
|
+
}
|
|
1654
|
+
get(path) {
|
|
1655
|
+
let entry = this.getEntry();
|
|
1656
|
+
if (entry.resolution) return entry.resolution.get(path);
|
|
1657
|
+
else return entry.session.sendCall(entry.importId, path);
|
|
1658
|
+
}
|
|
1659
|
+
dup() {
|
|
1660
|
+
return new RpcImportHook(false, this.getEntry());
|
|
1661
|
+
}
|
|
1662
|
+
pull() {
|
|
1663
|
+
let entry = this.getEntry();
|
|
1664
|
+
if (!this.isPromise) throw new Error("Can't pull this hook because it's not a promise hook.");
|
|
1665
|
+
if (entry.resolution) return entry.resolution.pull();
|
|
1666
|
+
return entry.awaitResolution();
|
|
1667
|
+
}
|
|
1668
|
+
ignoreUnhandledRejections() {}
|
|
1669
|
+
dispose() {
|
|
1670
|
+
let entry = this.entry;
|
|
1671
|
+
this.entry = void 0;
|
|
1672
|
+
if (entry) {
|
|
1673
|
+
if (--entry.localRefcount === 0) entry.dispose();
|
|
1674
|
+
}
|
|
1675
|
+
}
|
|
1676
|
+
onBroken(callback) {
|
|
1677
|
+
if (this.entry) this.entry.onBroken(callback);
|
|
1678
|
+
}
|
|
1679
|
+
};
|
|
1680
|
+
var RpcMainHook = class extends RpcImportHook {
|
|
1681
|
+
session;
|
|
1682
|
+
constructor(entry) {
|
|
1683
|
+
super(false, entry);
|
|
1684
|
+
this.session = entry.session;
|
|
1685
|
+
}
|
|
1686
|
+
dispose() {
|
|
1687
|
+
if (this.session) {
|
|
1688
|
+
let session = this.session;
|
|
1689
|
+
this.session = void 0;
|
|
1690
|
+
session.shutdown();
|
|
1691
|
+
}
|
|
1692
|
+
}
|
|
1693
|
+
};
|
|
1694
|
+
var RpcSessionImpl = class {
|
|
1695
|
+
transport;
|
|
1696
|
+
options;
|
|
1697
|
+
exports = [];
|
|
1698
|
+
reverseExports = /* @__PURE__ */ new Map();
|
|
1699
|
+
imports = [];
|
|
1700
|
+
abortReason;
|
|
1701
|
+
cancelReadLoop;
|
|
1702
|
+
nextExportId = -1;
|
|
1703
|
+
onBatchDone;
|
|
1704
|
+
pullCount = 0;
|
|
1705
|
+
onBrokenCallbacks = [];
|
|
1706
|
+
encodingLevel;
|
|
1707
|
+
limits;
|
|
1708
|
+
constructor(transport, mainHook, options) {
|
|
1709
|
+
this.transport = transport;
|
|
1710
|
+
this.options = options;
|
|
1711
|
+
let level = "string";
|
|
1712
|
+
if ("encodingLevel" in transport) {
|
|
1713
|
+
let raw = transport.encodingLevel;
|
|
1714
|
+
if (raw !== void 0) {
|
|
1715
|
+
if (raw !== "string" && raw !== "jsonCompatible" && raw !== "jsonCompatibleWithBytes" && raw !== "structuredClonable") throw new TypeError(`Unknown transport encodingLevel: ${String(raw)}`);
|
|
1716
|
+
level = raw;
|
|
1717
|
+
}
|
|
1718
|
+
}
|
|
1719
|
+
this.encodingLevel = level;
|
|
1720
|
+
this.limits = {
|
|
1721
|
+
...DEFAULT_LIMITS,
|
|
1722
|
+
...options.limits
|
|
1723
|
+
};
|
|
1724
|
+
this.exports.push({
|
|
1725
|
+
hook: mainHook,
|
|
1726
|
+
refcount: 1
|
|
1727
|
+
});
|
|
1728
|
+
this.imports.push(new ImportTableEntry(this, 0, false));
|
|
1729
|
+
this.readLoop().catch((err) => this.abort(err));
|
|
1730
|
+
}
|
|
1731
|
+
getMainImport() {
|
|
1732
|
+
return new RpcMainHook(this.imports[0]);
|
|
1733
|
+
}
|
|
1734
|
+
shutdown() {
|
|
1735
|
+
this.abort(/* @__PURE__ */ new Error("RPC session was shut down by disposing the main stub"), false);
|
|
1736
|
+
}
|
|
1737
|
+
exportStub(hook) {
|
|
1738
|
+
if (this.abortReason) throw this.abortReason;
|
|
1739
|
+
let existingExportId = this.reverseExports.get(hook);
|
|
1740
|
+
if (existingExportId !== void 0) {
|
|
1741
|
+
++this.exports[existingExportId].refcount;
|
|
1742
|
+
return existingExportId;
|
|
1743
|
+
} else {
|
|
1744
|
+
let exportId = this.nextExportId--;
|
|
1745
|
+
this.exports[exportId] = {
|
|
1746
|
+
hook,
|
|
1747
|
+
refcount: 1
|
|
1748
|
+
};
|
|
1749
|
+
this.reverseExports.set(hook, exportId);
|
|
1750
|
+
return exportId;
|
|
1751
|
+
}
|
|
1752
|
+
}
|
|
1753
|
+
exportPromise(hook) {
|
|
1754
|
+
if (this.abortReason) throw this.abortReason;
|
|
1755
|
+
let exportId = this.nextExportId--;
|
|
1756
|
+
this.exports[exportId] = {
|
|
1757
|
+
hook,
|
|
1758
|
+
refcount: 1
|
|
1759
|
+
};
|
|
1760
|
+
this.reverseExports.set(hook, exportId);
|
|
1761
|
+
this.ensureResolvingExport(exportId);
|
|
1762
|
+
return exportId;
|
|
1763
|
+
}
|
|
1764
|
+
unexport(ids) {
|
|
1765
|
+
for (let id of ids) this.releaseExport(id, 1);
|
|
1766
|
+
}
|
|
1767
|
+
releaseExport(exportId, refcount) {
|
|
1768
|
+
let entry = this.exports[exportId];
|
|
1769
|
+
if (!entry) throw new Error(`no such export ID: ${exportId}`);
|
|
1770
|
+
if (entry.refcount < refcount) throw new Error(`refcount would go negative: ${entry.refcount} < ${refcount}`);
|
|
1771
|
+
entry.refcount -= refcount;
|
|
1772
|
+
if (entry.refcount === 0) {
|
|
1773
|
+
delete this.exports[exportId];
|
|
1774
|
+
this.reverseExports.delete(entry.hook);
|
|
1775
|
+
entry.hook.dispose();
|
|
1776
|
+
}
|
|
1777
|
+
}
|
|
1778
|
+
onSendError(error) {
|
|
1779
|
+
if (this.options.onSendError) return this.options.onSendError(error);
|
|
1780
|
+
}
|
|
1781
|
+
ensureResolvingExport(exportId) {
|
|
1782
|
+
let exp = this.exports[exportId];
|
|
1783
|
+
if (!exp) throw new Error(`no such export ID: ${exportId}`);
|
|
1784
|
+
if (!exp.pull) {
|
|
1785
|
+
let resolve = async () => {
|
|
1786
|
+
let hook = exp.hook;
|
|
1787
|
+
for (;;) {
|
|
1788
|
+
let payload = await hook.pull();
|
|
1789
|
+
if (payload.value instanceof RpcStub$1) {
|
|
1790
|
+
let { hook: inner, pathIfPromise } = unwrapStubAndPath(payload.value);
|
|
1791
|
+
if (pathIfPromise && pathIfPromise.length == 0) {
|
|
1792
|
+
if (this.getImport(hook) === void 0) {
|
|
1793
|
+
hook = inner;
|
|
1794
|
+
continue;
|
|
1795
|
+
}
|
|
1796
|
+
}
|
|
1797
|
+
}
|
|
1798
|
+
return payload;
|
|
1799
|
+
}
|
|
1800
|
+
};
|
|
1801
|
+
let autoRelease = exp.autoRelease;
|
|
1802
|
+
++this.pullCount;
|
|
1803
|
+
exp.pull = resolve().then((payload) => {
|
|
1804
|
+
let value = Devaluator.devaluate(payload.value, void 0, this, payload, this.encodingLevel);
|
|
1805
|
+
this.send([
|
|
1806
|
+
"resolve",
|
|
1807
|
+
exportId,
|
|
1808
|
+
value
|
|
1809
|
+
]);
|
|
1810
|
+
if (autoRelease) this.releaseExport(exportId, 1);
|
|
1811
|
+
}, (error) => {
|
|
1812
|
+
this.send([
|
|
1813
|
+
"reject",
|
|
1814
|
+
exportId,
|
|
1815
|
+
Devaluator.devaluate(error, void 0, this, void 0, this.encodingLevel)
|
|
1816
|
+
]);
|
|
1817
|
+
if (autoRelease) this.releaseExport(exportId, 1);
|
|
1818
|
+
}).catch((error) => {
|
|
1819
|
+
try {
|
|
1820
|
+
this.send([
|
|
1821
|
+
"reject",
|
|
1822
|
+
exportId,
|
|
1823
|
+
Devaluator.devaluate(error, void 0, this, void 0, this.encodingLevel)
|
|
1824
|
+
]);
|
|
1825
|
+
if (autoRelease) this.releaseExport(exportId, 1);
|
|
1826
|
+
} catch (error2) {
|
|
1827
|
+
this.abort(error2);
|
|
1828
|
+
}
|
|
1829
|
+
}).finally(() => {
|
|
1830
|
+
if (--this.pullCount === 0) {
|
|
1831
|
+
if (this.onBatchDone) this.onBatchDone.resolve();
|
|
1832
|
+
}
|
|
1833
|
+
});
|
|
1834
|
+
}
|
|
1835
|
+
}
|
|
1836
|
+
getImport(hook) {
|
|
1837
|
+
if (hook instanceof RpcImportHook && hook.entry && hook.entry.session === this) return hook.entry.importId;
|
|
1838
|
+
else return;
|
|
1839
|
+
}
|
|
1840
|
+
importStub(idx) {
|
|
1841
|
+
if (this.abortReason) throw this.abortReason;
|
|
1842
|
+
let entry = this.imports[idx];
|
|
1843
|
+
if (!entry) {
|
|
1844
|
+
entry = new ImportTableEntry(this, idx, false);
|
|
1845
|
+
this.imports[idx] = entry;
|
|
1846
|
+
}
|
|
1847
|
+
return new RpcImportHook(false, entry);
|
|
1848
|
+
}
|
|
1849
|
+
importPromise(idx) {
|
|
1850
|
+
if (this.abortReason) throw this.abortReason;
|
|
1851
|
+
if (this.imports[idx]) return new ErrorStubHook(/* @__PURE__ */ new Error("Bug in RPC system: The peer sent a promise reusing an existing export ID."));
|
|
1852
|
+
let entry = new ImportTableEntry(this, idx, true);
|
|
1853
|
+
this.imports[idx] = entry;
|
|
1854
|
+
return new RpcImportHook(true, entry);
|
|
1855
|
+
}
|
|
1856
|
+
getExport(idx) {
|
|
1857
|
+
return this.exports[idx]?.hook;
|
|
1858
|
+
}
|
|
1859
|
+
getPipeReadable(exportId) {
|
|
1860
|
+
let entry = this.exports[exportId];
|
|
1861
|
+
if (!entry || !entry.pipeReadable) throw new Error(`Export ${exportId} is not a pipe or its readable end was already consumed.`);
|
|
1862
|
+
let readable = entry.pipeReadable;
|
|
1863
|
+
entry.pipeReadable = void 0;
|
|
1864
|
+
return readable;
|
|
1865
|
+
}
|
|
1866
|
+
getLimits() {
|
|
1867
|
+
return this.limits;
|
|
1868
|
+
}
|
|
1869
|
+
createPipe(readable, readableHook) {
|
|
1870
|
+
if (this.abortReason) throw this.abortReason;
|
|
1871
|
+
this.send(["pipe"]);
|
|
1872
|
+
let importId = this.imports.length;
|
|
1873
|
+
let entry = new ImportTableEntry(this, importId, false);
|
|
1874
|
+
this.imports.push(entry);
|
|
1875
|
+
let hook = new RpcImportHook(false, entry);
|
|
1876
|
+
let writable = streamImpl.createWritableStreamFromHook(hook);
|
|
1877
|
+
readable.pipeTo(writable).catch(() => {}).finally(() => readableHook.dispose());
|
|
1878
|
+
return importId;
|
|
1879
|
+
}
|
|
1880
|
+
send(msg) {
|
|
1881
|
+
if (this.abortReason !== void 0) return 0;
|
|
1882
|
+
if (this.encodingLevel === "string") {
|
|
1883
|
+
let msgText;
|
|
1884
|
+
try {
|
|
1885
|
+
msgText = JSON.stringify(msg);
|
|
1886
|
+
} catch (err) {
|
|
1887
|
+
try {
|
|
1888
|
+
this.abort(err);
|
|
1889
|
+
} catch (err2) {}
|
|
1890
|
+
throw err;
|
|
1891
|
+
}
|
|
1892
|
+
try {
|
|
1893
|
+
let sent = this.transport.send(msgText);
|
|
1894
|
+
if (sent !== void 0 && typeof sent.catch === "function") sent.catch((err) => this.abort(err, false));
|
|
1895
|
+
} catch (err) {
|
|
1896
|
+
queueMicrotask(() => this.abort(err, false));
|
|
1897
|
+
}
|
|
1898
|
+
return msgText.length;
|
|
1899
|
+
} else try {
|
|
1900
|
+
let size = this.transport.send(msg);
|
|
1901
|
+
if (typeof size === "number") return size;
|
|
1902
|
+
let thenable = size;
|
|
1903
|
+
if (thenable && typeof thenable.then === "function") Promise.resolve(thenable).catch((err) => this.abort(err, false));
|
|
1904
|
+
return;
|
|
1905
|
+
} catch (err) {
|
|
1906
|
+
queueMicrotask(() => this.abort(err, false));
|
|
1907
|
+
return;
|
|
1908
|
+
}
|
|
1909
|
+
}
|
|
1910
|
+
sendCall(id, path, args) {
|
|
1911
|
+
if (this.abortReason) throw this.abortReason;
|
|
1912
|
+
let value = [
|
|
1913
|
+
"pipeline",
|
|
1914
|
+
id,
|
|
1915
|
+
path
|
|
1916
|
+
];
|
|
1917
|
+
if (args) {
|
|
1918
|
+
let devalue = Devaluator.devaluate(args.value, void 0, this, args, this.encodingLevel);
|
|
1919
|
+
value.push(devalue[0]);
|
|
1920
|
+
}
|
|
1921
|
+
this.send(["push", value]);
|
|
1922
|
+
let entry = new ImportTableEntry(this, this.imports.length, false);
|
|
1923
|
+
this.imports.push(entry);
|
|
1924
|
+
return new RpcImportHook(true, entry);
|
|
1925
|
+
}
|
|
1926
|
+
sendStream(id, path, args) {
|
|
1927
|
+
if (this.abortReason) throw this.abortReason;
|
|
1928
|
+
let value = [
|
|
1929
|
+
"pipeline",
|
|
1930
|
+
id,
|
|
1931
|
+
path
|
|
1932
|
+
];
|
|
1933
|
+
let devalue = Devaluator.devaluate(args.value, void 0, this, args, this.encodingLevel);
|
|
1934
|
+
value.push(devalue[0]);
|
|
1935
|
+
let msg = ["stream", value];
|
|
1936
|
+
let size = this.send(msg);
|
|
1937
|
+
if (size === void 0) size = estimateEncodedSize(msg);
|
|
1938
|
+
let importId = this.imports.length;
|
|
1939
|
+
let entry = new ImportTableEntry(this, importId, true);
|
|
1940
|
+
entry.remoteRefcount = 0;
|
|
1941
|
+
entry.localRefcount = 1;
|
|
1942
|
+
this.imports.push(entry);
|
|
1943
|
+
return {
|
|
1944
|
+
promise: entry.awaitResolution().then((p) => {
|
|
1945
|
+
p.dispose();
|
|
1946
|
+
delete this.imports[importId];
|
|
1947
|
+
}, (err) => {
|
|
1948
|
+
delete this.imports[importId];
|
|
1949
|
+
throw err;
|
|
1950
|
+
}),
|
|
1951
|
+
size
|
|
1952
|
+
};
|
|
1953
|
+
}
|
|
1954
|
+
sendMap(id, path, captures, instructions) {
|
|
1955
|
+
if (this.abortReason) {
|
|
1956
|
+
for (let cap of captures) cap.dispose();
|
|
1957
|
+
throw this.abortReason;
|
|
1958
|
+
}
|
|
1959
|
+
let value = [
|
|
1960
|
+
"remap",
|
|
1961
|
+
id,
|
|
1962
|
+
path,
|
|
1963
|
+
captures.map((hook) => {
|
|
1964
|
+
let importId = this.getImport(hook);
|
|
1965
|
+
if (importId !== void 0) return ["import", importId];
|
|
1966
|
+
else return ["export", this.exportStub(hook)];
|
|
1967
|
+
}),
|
|
1968
|
+
instructions
|
|
1969
|
+
];
|
|
1970
|
+
this.send(["push", value]);
|
|
1971
|
+
let entry = new ImportTableEntry(this, this.imports.length, false);
|
|
1972
|
+
this.imports.push(entry);
|
|
1973
|
+
return new RpcImportHook(true, entry);
|
|
1974
|
+
}
|
|
1975
|
+
sendPull(id) {
|
|
1976
|
+
if (this.abortReason) throw this.abortReason;
|
|
1977
|
+
this.send(["pull", id]);
|
|
1978
|
+
}
|
|
1979
|
+
sendRelease(id, remoteRefcount) {
|
|
1980
|
+
if (this.abortReason) return;
|
|
1981
|
+
this.send([
|
|
1982
|
+
"release",
|
|
1983
|
+
id,
|
|
1984
|
+
remoteRefcount
|
|
1985
|
+
]);
|
|
1986
|
+
delete this.imports[id];
|
|
1987
|
+
}
|
|
1988
|
+
abort(error, trySendAbortMessage = true) {
|
|
1989
|
+
if (this.abortReason !== void 0) return;
|
|
1990
|
+
this.cancelReadLoop?.(error);
|
|
1991
|
+
this.cancelReadLoop = void 0;
|
|
1992
|
+
if (trySendAbortMessage) try {
|
|
1993
|
+
let abortMsg = ["abort", Devaluator.devaluate(error, void 0, this, void 0, this.encodingLevel)];
|
|
1994
|
+
if (this.encodingLevel === "string") {
|
|
1995
|
+
let sent = this.transport.send(JSON.stringify(abortMsg));
|
|
1996
|
+
if (sent !== void 0 && typeof sent.catch === "function") sent.catch((err) => {});
|
|
1997
|
+
} else {
|
|
1998
|
+
let result = this.transport.send(abortMsg);
|
|
1999
|
+
if (result && typeof result.then === "function") Promise.resolve(result).catch((err) => {});
|
|
2000
|
+
}
|
|
2001
|
+
} catch (err) {}
|
|
2002
|
+
if (error === void 0) error = "undefined";
|
|
2003
|
+
this.abortReason = error;
|
|
2004
|
+
if (this.onBatchDone) this.onBatchDone.reject(error);
|
|
2005
|
+
if (this.transport.abort) try {
|
|
2006
|
+
this.transport.abort(error);
|
|
2007
|
+
} catch (err) {
|
|
2008
|
+
Promise.resolve(err);
|
|
2009
|
+
}
|
|
2010
|
+
for (let i in this.onBrokenCallbacks) try {
|
|
2011
|
+
this.onBrokenCallbacks[i](error);
|
|
2012
|
+
} catch (err) {
|
|
2013
|
+
Promise.resolve(err);
|
|
2014
|
+
}
|
|
2015
|
+
for (let i in this.imports) this.imports[i].abort(error);
|
|
2016
|
+
for (let i in this.exports) this.exports[i].hook.dispose();
|
|
2017
|
+
}
|
|
2018
|
+
async readLoop() {
|
|
2019
|
+
while (!this.abortReason) {
|
|
2020
|
+
let readCanceled = Promise.withResolvers();
|
|
2021
|
+
this.cancelReadLoop = readCanceled.reject;
|
|
2022
|
+
let raw;
|
|
2023
|
+
try {
|
|
2024
|
+
raw = await Promise.race([this.transport.receive(), readCanceled.promise]);
|
|
2025
|
+
} finally {
|
|
2026
|
+
if (this.cancelReadLoop === readCanceled.reject) this.cancelReadLoop = void 0;
|
|
2027
|
+
}
|
|
2028
|
+
if (this.encodingLevel === "string" && raw.length > this.limits.maxMessageSize) throw new TypeError(`Incoming message exceeds maximum size of ${this.limits.maxMessageSize} UTF-16 code units.`);
|
|
2029
|
+
if (this.abortReason) break;
|
|
2030
|
+
let msg = this.encodingLevel === "string" ? JSON.parse(raw) : raw;
|
|
2031
|
+
if (msg instanceof Array) switch (msg[0]) {
|
|
2032
|
+
case "push":
|
|
2033
|
+
if (msg.length > 1) {
|
|
2034
|
+
let hook = new PayloadStubHook(new Evaluator(this, this.encodingLevel).evaluate(msg[1]));
|
|
2035
|
+
hook.ignoreUnhandledRejections();
|
|
2036
|
+
this.exports.push({
|
|
2037
|
+
hook,
|
|
2038
|
+
refcount: 1
|
|
2039
|
+
});
|
|
2040
|
+
continue;
|
|
2041
|
+
}
|
|
2042
|
+
break;
|
|
2043
|
+
case "stream":
|
|
2044
|
+
if (msg.length > 1) {
|
|
2045
|
+
let hook = new PayloadStubHook(new Evaluator(this, this.encodingLevel).evaluate(msg[1]));
|
|
2046
|
+
hook.ignoreUnhandledRejections();
|
|
2047
|
+
let exportId = this.exports.length;
|
|
2048
|
+
this.exports.push({
|
|
2049
|
+
hook,
|
|
2050
|
+
refcount: 1,
|
|
2051
|
+
autoRelease: true
|
|
2052
|
+
});
|
|
2053
|
+
this.ensureResolvingExport(exportId);
|
|
2054
|
+
continue;
|
|
2055
|
+
}
|
|
2056
|
+
break;
|
|
2057
|
+
case "pipe": {
|
|
2058
|
+
let { readable, writable } = new TransformStream();
|
|
2059
|
+
let hook = streamImpl.createWritableStreamHook(writable);
|
|
2060
|
+
this.exports.push({
|
|
2061
|
+
hook,
|
|
2062
|
+
refcount: 1,
|
|
2063
|
+
pipeReadable: readable
|
|
2064
|
+
});
|
|
2065
|
+
continue;
|
|
2066
|
+
}
|
|
2067
|
+
case "pull": {
|
|
2068
|
+
let exportId = msg[1];
|
|
2069
|
+
if (typeof exportId == "number") {
|
|
2070
|
+
this.ensureResolvingExport(exportId);
|
|
2071
|
+
continue;
|
|
2072
|
+
}
|
|
2073
|
+
break;
|
|
2074
|
+
}
|
|
2075
|
+
case "resolve":
|
|
2076
|
+
case "reject": {
|
|
2077
|
+
let importId = msg[1];
|
|
2078
|
+
if (typeof importId == "number" && msg.length > 2) {
|
|
2079
|
+
let imp = this.imports[importId];
|
|
2080
|
+
if (imp) if (msg[0] == "resolve") imp.resolve(new PayloadStubHook(new Evaluator(this, this.encodingLevel).evaluate(msg[2])));
|
|
2081
|
+
else {
|
|
2082
|
+
let payload = new Evaluator(this, this.encodingLevel).evaluate(msg[2]);
|
|
2083
|
+
payload.dispose();
|
|
2084
|
+
imp.resolve(new ErrorStubHook(payload.value));
|
|
2085
|
+
}
|
|
2086
|
+
else if (msg[0] == "resolve") new Evaluator(this, this.encodingLevel).evaluate(msg[2]).dispose();
|
|
2087
|
+
continue;
|
|
2088
|
+
}
|
|
2089
|
+
break;
|
|
2090
|
+
}
|
|
2091
|
+
case "release": {
|
|
2092
|
+
let exportId = msg[1];
|
|
2093
|
+
let refcount = msg[2];
|
|
2094
|
+
if (typeof exportId == "number" && typeof refcount == "number") {
|
|
2095
|
+
this.releaseExport(exportId, refcount);
|
|
2096
|
+
continue;
|
|
2097
|
+
}
|
|
2098
|
+
break;
|
|
2099
|
+
}
|
|
2100
|
+
case "abort": {
|
|
2101
|
+
let payload = new Evaluator(this, this.encodingLevel).evaluate(msg[1]);
|
|
2102
|
+
payload.dispose();
|
|
2103
|
+
this.abort(payload.value, false);
|
|
2104
|
+
break;
|
|
2105
|
+
}
|
|
2106
|
+
}
|
|
2107
|
+
throw new Error(`bad RPC message: ${JSON.stringify(msg)}`);
|
|
2108
|
+
}
|
|
2109
|
+
}
|
|
2110
|
+
async drain() {
|
|
2111
|
+
if (this.abortReason) throw this.abortReason;
|
|
2112
|
+
if (this.pullCount > 0) {
|
|
2113
|
+
let { promise, resolve, reject } = Promise.withResolvers();
|
|
2114
|
+
this.onBatchDone = {
|
|
2115
|
+
resolve,
|
|
2116
|
+
reject
|
|
2117
|
+
};
|
|
2118
|
+
await promise;
|
|
2119
|
+
}
|
|
2120
|
+
}
|
|
2121
|
+
getStats() {
|
|
2122
|
+
let result = {
|
|
2123
|
+
imports: 0,
|
|
2124
|
+
exports: 0
|
|
2125
|
+
};
|
|
2126
|
+
for (let i in this.imports) ++result.imports;
|
|
2127
|
+
for (let i in this.exports) ++result.exports;
|
|
2128
|
+
return result;
|
|
2129
|
+
}
|
|
2130
|
+
};
|
|
2131
|
+
var RpcSession$1 = class {
|
|
2132
|
+
#session;
|
|
2133
|
+
#mainStub;
|
|
2134
|
+
constructor(transport, localMain, options = {}) {
|
|
2135
|
+
let mainHook;
|
|
2136
|
+
if (localMain) mainHook = new PayloadStubHook(RpcPayload.fromAppReturn(localMain));
|
|
2137
|
+
else mainHook = new ErrorStubHook(/* @__PURE__ */ new Error("This connection has no main object."));
|
|
2138
|
+
this.#session = new RpcSessionImpl(transport, mainHook, options);
|
|
2139
|
+
this.#mainStub = new RpcStub$1(this.#session.getMainImport());
|
|
2140
|
+
}
|
|
2141
|
+
getRemoteMain() {
|
|
2142
|
+
return this.#mainStub;
|
|
2143
|
+
}
|
|
2144
|
+
getStats() {
|
|
2145
|
+
return this.#session.getStats();
|
|
2146
|
+
}
|
|
2147
|
+
drain() {
|
|
2148
|
+
return this.#session.drain();
|
|
2149
|
+
}
|
|
2150
|
+
};
|
|
2151
|
+
|
|
2152
|
+
//#endregion
|
|
2153
|
+
//#region src/websocket.ts
|
|
2154
|
+
/** Close-frame reason max UTF-8 bytes: 125 payload − 2-byte status (RFC 6455 §5.5). */
|
|
2155
|
+
const MAX_CLOSE_REASON_BYTES = 123;
|
|
2156
|
+
function newWebSocketRpcSession$1(webSocket, localMain, options) {
|
|
2157
|
+
if (typeof webSocket === "string") webSocket = new WebSocket(webSocket);
|
|
2158
|
+
return new RpcSession$1(new WebSocketTransport(webSocket), localMain, options).getRemoteMain();
|
|
2159
|
+
}
|
|
2160
|
+
/**
|
|
2161
|
+
* For use in Cloudflare Workers: Construct an HTTP response that starts a WebSocket RPC session
|
|
2162
|
+
* with the given `localMain`.
|
|
2163
|
+
*/
|
|
2164
|
+
function newWorkersWebSocketRpcResponse(request, localMain, options) {
|
|
2165
|
+
if (request.headers.get("Upgrade")?.toLowerCase() !== "websocket") return new Response("This endpoint only accepts WebSocket requests.", { status: 400 });
|
|
2166
|
+
let pair = new WebSocketPair();
|
|
2167
|
+
let server = pair[0];
|
|
2168
|
+
server.accept();
|
|
2169
|
+
newWebSocketRpcSession$1(server, localMain, options);
|
|
2170
|
+
return new Response(null, {
|
|
2171
|
+
status: 101,
|
|
2172
|
+
webSocket: pair[1]
|
|
2173
|
+
});
|
|
2174
|
+
}
|
|
2175
|
+
/**
|
|
2176
|
+
* Generic WebSocket transport. Default `T = string` is backward-compatible and satisfies
|
|
2177
|
+
* `RpcTransport`. Use `T = ArrayBuffer` as a building block for binary transports.
|
|
2178
|
+
*/
|
|
2179
|
+
var WebSocketTransport = class {
|
|
2180
|
+
constructor(webSocket) {
|
|
2181
|
+
this.#webSocket = webSocket;
|
|
2182
|
+
webSocket.binaryType = "arraybuffer";
|
|
2183
|
+
if (webSocket.readyState === WebSocket.CONNECTING) {
|
|
2184
|
+
this.#sendQueue = [];
|
|
2185
|
+
webSocket.addEventListener("open", (event) => {
|
|
2186
|
+
try {
|
|
2187
|
+
for (let message of this.#sendQueue) webSocket.send(message);
|
|
2188
|
+
} catch (err) {
|
|
2189
|
+
this.#receivedError(err);
|
|
2190
|
+
}
|
|
2191
|
+
this.#sendQueue = void 0;
|
|
2192
|
+
});
|
|
2193
|
+
}
|
|
2194
|
+
webSocket.addEventListener("message", (event) => {
|
|
2195
|
+
if (this.#error) {} else if (typeof event.data === "string" || event.data instanceof ArrayBuffer) if (this.#receiveResolver) {
|
|
2196
|
+
this.#receiveResolver(event.data);
|
|
2197
|
+
this.#receiveResolver = void 0;
|
|
2198
|
+
this.#receiveRejecter = void 0;
|
|
2199
|
+
} else this.#receiveQueue.push(event.data);
|
|
2200
|
+
else this.#receivedError(/* @__PURE__ */ new TypeError("Received unexpected message type from WebSocket."));
|
|
2201
|
+
});
|
|
2202
|
+
webSocket.addEventListener("close", (event) => {
|
|
2203
|
+
this.#receivedError(/* @__PURE__ */ new Error(`Peer closed WebSocket: ${event.code} ${event.reason}`));
|
|
2204
|
+
});
|
|
2205
|
+
webSocket.addEventListener("error", (event) => {
|
|
2206
|
+
this.#receivedError(/* @__PURE__ */ new Error(`WebSocket connection failed.`));
|
|
2207
|
+
});
|
|
2208
|
+
}
|
|
2209
|
+
#webSocket;
|
|
2210
|
+
#sendQueue;
|
|
2211
|
+
#receiveResolver;
|
|
2212
|
+
#receiveRejecter;
|
|
2213
|
+
#receiveQueue = [];
|
|
2214
|
+
#error;
|
|
2215
|
+
send(message) {
|
|
2216
|
+
if (this.#sendQueue === void 0) this.#webSocket.send(message);
|
|
2217
|
+
else this.#sendQueue.push(message);
|
|
2218
|
+
}
|
|
2219
|
+
receive() {
|
|
2220
|
+
if (this.#receiveQueue.length > 0) return Promise.resolve(this.#receiveQueue.shift());
|
|
2221
|
+
else if (this.#error) return Promise.reject(this.#error);
|
|
2222
|
+
else return new Promise((resolve, reject) => {
|
|
2223
|
+
this.#receiveResolver = resolve;
|
|
2224
|
+
this.#receiveRejecter = reject;
|
|
2225
|
+
});
|
|
2226
|
+
}
|
|
2227
|
+
abort(reason) {
|
|
2228
|
+
let message;
|
|
2229
|
+
if (reason instanceof Error) message = reason.message;
|
|
2230
|
+
else message = `${reason}`;
|
|
2231
|
+
let reasonBytes = new TextEncoder().encode(message);
|
|
2232
|
+
if (reasonBytes.length > 123) message = new TextDecoder().decode(reasonBytes.subarray(0, 123), { stream: true });
|
|
2233
|
+
this.#webSocket.close(3e3, message);
|
|
2234
|
+
if (!this.#error) this.#error = reason;
|
|
2235
|
+
}
|
|
2236
|
+
#receivedError(reason) {
|
|
2237
|
+
if (!this.#error) {
|
|
2238
|
+
this.#error = reason;
|
|
2239
|
+
if (this.#receiveRejecter) {
|
|
2240
|
+
this.#receiveRejecter(reason);
|
|
2241
|
+
this.#receiveResolver = void 0;
|
|
2242
|
+
this.#receiveRejecter = void 0;
|
|
2243
|
+
}
|
|
2244
|
+
}
|
|
2245
|
+
}
|
|
2246
|
+
};
|
|
2247
|
+
|
|
2248
|
+
//#endregion
|
|
2249
|
+
//#region src/batch.ts
|
|
2250
|
+
var BatchClientTransport = class {
|
|
2251
|
+
constructor(sendBatch) {
|
|
2252
|
+
this.#promise = this.#scheduleBatch(sendBatch);
|
|
2253
|
+
}
|
|
2254
|
+
#promise;
|
|
2255
|
+
#aborted;
|
|
2256
|
+
#batchToSend = [];
|
|
2257
|
+
#batchToReceive = null;
|
|
2258
|
+
send(message) {
|
|
2259
|
+
if (this.#batchToSend !== null) this.#batchToSend.push(message);
|
|
2260
|
+
}
|
|
2261
|
+
async receive() {
|
|
2262
|
+
if (!this.#batchToReceive) await this.#promise;
|
|
2263
|
+
let msg = this.#batchToReceive.shift();
|
|
2264
|
+
if (msg !== void 0) return msg;
|
|
2265
|
+
else throw new Error("Batch RPC request ended.");
|
|
2266
|
+
}
|
|
2267
|
+
abort(reason) {
|
|
2268
|
+
this.#aborted = reason;
|
|
2269
|
+
}
|
|
2270
|
+
async #scheduleBatch(sendBatch) {
|
|
2271
|
+
await new Promise((resolve) => setTimeout(resolve, 0));
|
|
2272
|
+
if (this.#aborted !== void 0) throw this.#aborted;
|
|
2273
|
+
let batch = this.#batchToSend;
|
|
2274
|
+
this.#batchToSend = null;
|
|
2275
|
+
this.#batchToReceive = await sendBatch(batch);
|
|
2276
|
+
}
|
|
2277
|
+
};
|
|
2278
|
+
function newHttpBatchRpcSession$1(urlOrRequest, options) {
|
|
2279
|
+
let sendBatch = async (batch) => {
|
|
2280
|
+
let response = await fetch(urlOrRequest, {
|
|
2281
|
+
method: "POST",
|
|
2282
|
+
body: batch.join("\n")
|
|
2283
|
+
});
|
|
2284
|
+
if (!response.ok) {
|
|
2285
|
+
response.body?.cancel();
|
|
2286
|
+
throw new Error(`RPC request failed: ${response.status} ${response.statusText}`);
|
|
2287
|
+
}
|
|
2288
|
+
let body = await response.text();
|
|
2289
|
+
return body == "" ? [] : body.split("\n");
|
|
2290
|
+
};
|
|
2291
|
+
return new RpcSession$1(new BatchClientTransport(sendBatch), void 0, options).getRemoteMain();
|
|
2292
|
+
}
|
|
2293
|
+
var BatchServerTransport = class {
|
|
2294
|
+
constructor(batch) {
|
|
2295
|
+
this.#batchToReceive = batch;
|
|
2296
|
+
}
|
|
2297
|
+
#batchToSend = [];
|
|
2298
|
+
#batchToReceive;
|
|
2299
|
+
#allReceived = Promise.withResolvers();
|
|
2300
|
+
send(message) {
|
|
2301
|
+
this.#batchToSend.push(message);
|
|
2302
|
+
}
|
|
2303
|
+
async receive() {
|
|
2304
|
+
let msg = this.#batchToReceive.shift();
|
|
2305
|
+
if (msg !== void 0) return msg;
|
|
2306
|
+
else {
|
|
2307
|
+
this.#allReceived.resolve();
|
|
2308
|
+
return new Promise((r) => {});
|
|
2309
|
+
}
|
|
2310
|
+
}
|
|
2311
|
+
abort(reason) {
|
|
2312
|
+
this.#allReceived.reject(reason);
|
|
2313
|
+
}
|
|
2314
|
+
whenAllReceived() {
|
|
2315
|
+
return this.#allReceived.promise;
|
|
2316
|
+
}
|
|
2317
|
+
getResponseBody() {
|
|
2318
|
+
return this.#batchToSend.join("\n");
|
|
2319
|
+
}
|
|
2320
|
+
};
|
|
2321
|
+
/**
|
|
2322
|
+
* Implements the server end of an HTTP batch session, using standard Fetch API types to represent
|
|
2323
|
+
* HTTP requests and responses.
|
|
2324
|
+
*
|
|
2325
|
+
* @param request The request received from the client initiating the session.
|
|
2326
|
+
* @param localMain The main stub or RpcTarget which the server wishes to expose to the client.
|
|
2327
|
+
* @param options Optional RPC session options.
|
|
2328
|
+
* @returns The HTTP response to return to the client. Note that the returned object has mutable
|
|
2329
|
+
* headers, so you can modify them using e.g. `response.headers.set("Foo", "bar")`.
|
|
2330
|
+
*/
|
|
2331
|
+
async function newHttpBatchRpcResponse(request, localMain, options) {
|
|
2332
|
+
if (request.method !== "POST") return new Response("This endpoint only accepts POST requests.", { status: 405 });
|
|
2333
|
+
let body = await request.text();
|
|
2334
|
+
let transport = new BatchServerTransport(body === "" ? [] : body.split("\n"));
|
|
2335
|
+
let rpc = new RpcSession$1(transport, localMain, options);
|
|
2336
|
+
await transport.whenAllReceived();
|
|
2337
|
+
await rpc.drain();
|
|
2338
|
+
return new Response(transport.getResponseBody());
|
|
2339
|
+
}
|
|
2340
|
+
/**
|
|
2341
|
+
* Implements the server end of an HTTP batch session using traditional Node.js HTTP APIs.
|
|
2342
|
+
*
|
|
2343
|
+
* @param request The request received from the client initiating the session.
|
|
2344
|
+
* @param response The response object, to which the response should be written.
|
|
2345
|
+
* @param localMain The main stub or RpcTarget which the server wishes to expose to the client.
|
|
2346
|
+
* @param options Optional RPC session options. You can also pass headers to set on the response.
|
|
2347
|
+
*/
|
|
2348
|
+
async function nodeHttpBatchRpcResponse(request, response, localMain, options) {
|
|
2349
|
+
if (request.method !== "POST") {
|
|
2350
|
+
response.writeHead(405, "This endpoint only accepts POST requests.", options?.headers);
|
|
2351
|
+
response.end();
|
|
2352
|
+
return;
|
|
2353
|
+
}
|
|
2354
|
+
let body = await new Promise((resolve, reject) => {
|
|
2355
|
+
let chunks = [];
|
|
2356
|
+
request.on("data", (chunk) => {
|
|
2357
|
+
chunks.push(chunk);
|
|
2358
|
+
});
|
|
2359
|
+
request.on("end", () => {
|
|
2360
|
+
resolve(Buffer.concat(chunks).toString());
|
|
2361
|
+
});
|
|
2362
|
+
request.on("error", reject);
|
|
2363
|
+
});
|
|
2364
|
+
let transport = new BatchServerTransport(body === "" ? [] : body.split("\n"));
|
|
2365
|
+
let rpc = new RpcSession$1(transport, localMain, options);
|
|
2366
|
+
await transport.whenAllReceived();
|
|
2367
|
+
await rpc.drain();
|
|
2368
|
+
response.writeHead(200, options?.headers);
|
|
2369
|
+
response.end(transport.getResponseBody());
|
|
2370
|
+
}
|
|
2371
|
+
|
|
2372
|
+
//#endregion
|
|
2373
|
+
//#region src/messageport.ts
|
|
2374
|
+
function newMessagePortRpcSession$1(port, localMain, options) {
|
|
2375
|
+
return new RpcSession$1(new MessagePortTransport(port), localMain, options).getRemoteMain();
|
|
2376
|
+
}
|
|
2377
|
+
var MessagePortTransport = class {
|
|
2378
|
+
encodingLevel = "structuredClonable";
|
|
2379
|
+
constructor(port) {
|
|
2380
|
+
this.#port = port;
|
|
2381
|
+
port.start();
|
|
2382
|
+
port.addEventListener("message", (event) => {
|
|
2383
|
+
if (this.#error) {} else if (event.data === null) this.#receivedError(/* @__PURE__ */ new Error("Peer closed MessagePort connection."));
|
|
2384
|
+
else if (this.#receiveResolver) {
|
|
2385
|
+
this.#receiveResolver(event.data);
|
|
2386
|
+
this.#receiveResolver = void 0;
|
|
2387
|
+
this.#receiveRejecter = void 0;
|
|
2388
|
+
} else this.#receiveQueue.push(event.data);
|
|
2389
|
+
});
|
|
2390
|
+
port.addEventListener("messageerror", (event) => {
|
|
2391
|
+
this.#receivedError(/* @__PURE__ */ new Error("MessagePort message error."));
|
|
2392
|
+
});
|
|
2393
|
+
}
|
|
2394
|
+
#port;
|
|
2395
|
+
#receiveResolver;
|
|
2396
|
+
#receiveRejecter;
|
|
2397
|
+
#receiveQueue = [];
|
|
2398
|
+
#error;
|
|
2399
|
+
send(message) {
|
|
2400
|
+
if (this.#error) throw this.#error;
|
|
2401
|
+
this.#port.postMessage(message);
|
|
2402
|
+
}
|
|
2403
|
+
async receive() {
|
|
2404
|
+
if (this.#receiveQueue.length > 0) return this.#receiveQueue.shift();
|
|
2405
|
+
else if (this.#error) throw this.#error;
|
|
2406
|
+
else return new Promise((resolve, reject) => {
|
|
2407
|
+
this.#receiveResolver = resolve;
|
|
2408
|
+
this.#receiveRejecter = reject;
|
|
2409
|
+
});
|
|
2410
|
+
}
|
|
2411
|
+
abort(reason) {
|
|
2412
|
+
try {
|
|
2413
|
+
this.#port.postMessage(null);
|
|
2414
|
+
} catch (err) {}
|
|
2415
|
+
this.#port.close();
|
|
2416
|
+
if (!this.#error) this.#error = reason;
|
|
2417
|
+
}
|
|
2418
|
+
#receivedError(reason) {
|
|
2419
|
+
if (!this.#error) {
|
|
2420
|
+
this.#error = reason;
|
|
2421
|
+
if (this.#receiveRejecter) {
|
|
2422
|
+
this.#receiveRejecter(reason);
|
|
2423
|
+
this.#receiveResolver = void 0;
|
|
2424
|
+
this.#receiveRejecter = void 0;
|
|
2425
|
+
}
|
|
2426
|
+
}
|
|
2427
|
+
}
|
|
2428
|
+
};
|
|
2429
|
+
|
|
2430
|
+
//#endregion
|
|
2431
|
+
//#region src/map.ts
|
|
2432
|
+
let currentMapBuilder;
|
|
2433
|
+
var MapBuilder = class {
|
|
2434
|
+
context;
|
|
2435
|
+
captureMap = /* @__PURE__ */ new Map();
|
|
2436
|
+
instructions = [];
|
|
2437
|
+
constructor(subject, path) {
|
|
2438
|
+
if (currentMapBuilder) this.context = {
|
|
2439
|
+
parent: currentMapBuilder,
|
|
2440
|
+
captures: [],
|
|
2441
|
+
subject: currentMapBuilder.capture(subject),
|
|
2442
|
+
path
|
|
2443
|
+
};
|
|
2444
|
+
else this.context = {
|
|
2445
|
+
parent: void 0,
|
|
2446
|
+
captures: [],
|
|
2447
|
+
subject,
|
|
2448
|
+
path
|
|
2449
|
+
};
|
|
2450
|
+
currentMapBuilder = this;
|
|
2451
|
+
}
|
|
2452
|
+
unregister() {
|
|
2453
|
+
currentMapBuilder = this.context.parent;
|
|
2454
|
+
}
|
|
2455
|
+
makeInput() {
|
|
2456
|
+
return new MapVariableHook(this, 0);
|
|
2457
|
+
}
|
|
2458
|
+
makeOutput(result) {
|
|
2459
|
+
let devalued;
|
|
2460
|
+
try {
|
|
2461
|
+
devalued = Devaluator.devaluate(result.value, void 0, this, result);
|
|
2462
|
+
} finally {
|
|
2463
|
+
result.dispose();
|
|
2464
|
+
}
|
|
2465
|
+
this.instructions.push(devalued);
|
|
2466
|
+
if (this.context.parent) {
|
|
2467
|
+
this.context.parent.instructions.push([
|
|
2468
|
+
"remap",
|
|
2469
|
+
this.context.subject,
|
|
2470
|
+
this.context.path,
|
|
2471
|
+
this.context.captures.map((cap) => ["import", cap]),
|
|
2472
|
+
this.instructions
|
|
2473
|
+
]);
|
|
2474
|
+
return new MapVariableHook(this.context.parent, this.context.parent.instructions.length);
|
|
2475
|
+
} else return this.context.subject.map(this.context.path, this.context.captures, this.instructions);
|
|
2476
|
+
}
|
|
2477
|
+
pushCall(hook, path, params) {
|
|
2478
|
+
let devalued = Devaluator.devaluate(params.value, void 0, this, params);
|
|
2479
|
+
devalued = devalued[0];
|
|
2480
|
+
let subject = this.capture(hook.dup());
|
|
2481
|
+
this.instructions.push([
|
|
2482
|
+
"pipeline",
|
|
2483
|
+
subject,
|
|
2484
|
+
path,
|
|
2485
|
+
devalued
|
|
2486
|
+
]);
|
|
2487
|
+
return new MapVariableHook(this, this.instructions.length);
|
|
2488
|
+
}
|
|
2489
|
+
pushGet(hook, path) {
|
|
2490
|
+
let subject = this.capture(hook.dup());
|
|
2491
|
+
this.instructions.push([
|
|
2492
|
+
"pipeline",
|
|
2493
|
+
subject,
|
|
2494
|
+
path
|
|
2495
|
+
]);
|
|
2496
|
+
return new MapVariableHook(this, this.instructions.length);
|
|
2497
|
+
}
|
|
2498
|
+
capture(hook) {
|
|
2499
|
+
if (hook instanceof MapVariableHook && hook.mapper === this) return hook.idx;
|
|
2500
|
+
let result = this.captureMap.get(hook);
|
|
2501
|
+
if (result === void 0) {
|
|
2502
|
+
if (this.context.parent) {
|
|
2503
|
+
let parentIdx = this.context.parent.capture(hook);
|
|
2504
|
+
this.context.captures.push(parentIdx);
|
|
2505
|
+
} else this.context.captures.push(hook);
|
|
2506
|
+
result = -this.context.captures.length;
|
|
2507
|
+
this.captureMap.set(hook, result);
|
|
2508
|
+
}
|
|
2509
|
+
return result;
|
|
2510
|
+
}
|
|
2511
|
+
exportStub(hook) {
|
|
2512
|
+
throw new Error("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.");
|
|
2513
|
+
}
|
|
2514
|
+
exportPromise(hook) {
|
|
2515
|
+
return this.exportStub(hook);
|
|
2516
|
+
}
|
|
2517
|
+
getImport(hook) {
|
|
2518
|
+
return this.capture(hook);
|
|
2519
|
+
}
|
|
2520
|
+
unexport(ids) {}
|
|
2521
|
+
createPipe(readable) {
|
|
2522
|
+
throw new Error("Cannot send ReadableStream inside a mapper function.");
|
|
2523
|
+
}
|
|
2524
|
+
onSendError(error) {}
|
|
2525
|
+
};
|
|
2526
|
+
mapImpl.sendMap = (hook, path, func) => {
|
|
2527
|
+
let builder = new MapBuilder(hook, path);
|
|
2528
|
+
let result;
|
|
2529
|
+
try {
|
|
2530
|
+
result = RpcPayload.fromAppReturn(withCallInterceptor(builder.pushCall.bind(builder), () => {
|
|
2531
|
+
return func(new RpcPromise$1(builder.makeInput(), []));
|
|
2532
|
+
}));
|
|
2533
|
+
} finally {
|
|
2534
|
+
builder.unregister();
|
|
2535
|
+
}
|
|
2536
|
+
if (result instanceof Promise) {
|
|
2537
|
+
result.catch((err) => {});
|
|
2538
|
+
throw new Error("RPC map() callbacks cannot be async.");
|
|
2539
|
+
}
|
|
2540
|
+
return new RpcPromise$1(builder.makeOutput(result), []);
|
|
2541
|
+
};
|
|
2542
|
+
function throwMapperBuilderUseError() {
|
|
2543
|
+
throw new Error("Attempted to use an abstract placeholder from a mapper function. Please make sure your map function has no side effects.");
|
|
2544
|
+
}
|
|
2545
|
+
var MapVariableHook = class extends StubHook {
|
|
2546
|
+
mapper;
|
|
2547
|
+
idx;
|
|
2548
|
+
constructor(mapper, idx) {
|
|
2549
|
+
super();
|
|
2550
|
+
this.mapper = mapper;
|
|
2551
|
+
this.idx = idx;
|
|
2552
|
+
}
|
|
2553
|
+
dup() {
|
|
2554
|
+
return this;
|
|
2555
|
+
}
|
|
2556
|
+
dispose() {}
|
|
2557
|
+
get(path) {
|
|
2558
|
+
if (path.length == 0) return this;
|
|
2559
|
+
else if (currentMapBuilder) return currentMapBuilder.pushGet(this, path);
|
|
2560
|
+
else throwMapperBuilderUseError();
|
|
2561
|
+
}
|
|
2562
|
+
call(path, args) {
|
|
2563
|
+
throwMapperBuilderUseError();
|
|
2564
|
+
}
|
|
2565
|
+
map(path, captures, instructions) {
|
|
2566
|
+
throwMapperBuilderUseError();
|
|
2567
|
+
}
|
|
2568
|
+
pull() {
|
|
2569
|
+
throwMapperBuilderUseError();
|
|
2570
|
+
}
|
|
2571
|
+
ignoreUnhandledRejections() {}
|
|
2572
|
+
onBroken(callback) {
|
|
2573
|
+
throwMapperBuilderUseError();
|
|
2574
|
+
}
|
|
2575
|
+
};
|
|
2576
|
+
var MapApplicator = class {
|
|
2577
|
+
captures;
|
|
2578
|
+
variables;
|
|
2579
|
+
constructor(captures, input) {
|
|
2580
|
+
this.captures = captures;
|
|
2581
|
+
this.variables = [input];
|
|
2582
|
+
}
|
|
2583
|
+
dispose() {
|
|
2584
|
+
for (let variable of this.variables) variable.dispose();
|
|
2585
|
+
}
|
|
2586
|
+
apply(instructions) {
|
|
2587
|
+
try {
|
|
2588
|
+
if (instructions.length < 1) throw new Error("Invalid empty mapper function.");
|
|
2589
|
+
for (let instruction of instructions.slice(0, -1)) {
|
|
2590
|
+
let payload = new Evaluator(this).evaluateCopy(instruction);
|
|
2591
|
+
if (payload.value instanceof RpcStub$1) {
|
|
2592
|
+
let hook = unwrapStubNoProperties(payload.value);
|
|
2593
|
+
if (hook) {
|
|
2594
|
+
this.variables.push(hook);
|
|
2595
|
+
continue;
|
|
2596
|
+
}
|
|
2597
|
+
}
|
|
2598
|
+
this.variables.push(new PayloadStubHook(payload));
|
|
2599
|
+
}
|
|
2600
|
+
return new Evaluator(this).evaluateCopy(instructions[instructions.length - 1]);
|
|
2601
|
+
} finally {
|
|
2602
|
+
for (let variable of this.variables) variable.dispose();
|
|
2603
|
+
}
|
|
2604
|
+
}
|
|
2605
|
+
importStub(idx) {
|
|
2606
|
+
throw new Error("A mapper function cannot refer to exports.");
|
|
2607
|
+
}
|
|
2608
|
+
importPromise(idx) {
|
|
2609
|
+
return this.importStub(idx);
|
|
2610
|
+
}
|
|
2611
|
+
getExport(idx) {
|
|
2612
|
+
if (idx < 0) return this.captures[-idx - 1];
|
|
2613
|
+
else return this.variables[idx];
|
|
2614
|
+
}
|
|
2615
|
+
getPipeReadable(exportId) {
|
|
2616
|
+
throw new Error("A mapper function cannot use pipe readables.");
|
|
2617
|
+
}
|
|
2618
|
+
getLimits() {
|
|
2619
|
+
return DEFAULT_LIMITS;
|
|
2620
|
+
}
|
|
2621
|
+
};
|
|
2622
|
+
function applyMapToElement(input, parent, owner, captures, instructions) {
|
|
2623
|
+
let mapper = new MapApplicator(captures, new PayloadStubHook(RpcPayload.deepCopyFrom(input, parent, owner)));
|
|
2624
|
+
try {
|
|
2625
|
+
return mapper.apply(instructions);
|
|
2626
|
+
} finally {
|
|
2627
|
+
mapper.dispose();
|
|
2628
|
+
}
|
|
2629
|
+
}
|
|
2630
|
+
mapImpl.applyMap = (input, parent, owner, captures, instructions) => {
|
|
2631
|
+
try {
|
|
2632
|
+
let result;
|
|
2633
|
+
if (input instanceof RpcPromise$1) throw new Error("applyMap() can't be called on RpcPromise");
|
|
2634
|
+
else if (input instanceof Array) {
|
|
2635
|
+
let payloads = [];
|
|
2636
|
+
try {
|
|
2637
|
+
for (let elem of input) payloads.push(applyMapToElement(elem, input, owner, captures, instructions));
|
|
2638
|
+
} catch (err) {
|
|
2639
|
+
for (let payload of payloads) payload.dispose();
|
|
2640
|
+
throw err;
|
|
2641
|
+
}
|
|
2642
|
+
result = RpcPayload.fromArray(payloads);
|
|
2643
|
+
} else if (input === null || input === void 0) result = RpcPayload.fromAppReturn(input);
|
|
2644
|
+
else result = applyMapToElement(input, parent, owner, captures, instructions);
|
|
2645
|
+
return new PayloadStubHook(result);
|
|
2646
|
+
} finally {
|
|
2647
|
+
for (let cap of captures) cap.dispose();
|
|
2648
|
+
}
|
|
2649
|
+
};
|
|
2650
|
+
|
|
2651
|
+
//#endregion
|
|
2652
|
+
//#region src/streams.ts
|
|
2653
|
+
var WritableStreamStubHook = class WritableStreamStubHook extends StubHook {
|
|
2654
|
+
state;
|
|
2655
|
+
static create(stream) {
|
|
2656
|
+
return new WritableStreamStubHook({
|
|
2657
|
+
refcount: 1,
|
|
2658
|
+
writer: stream.getWriter(),
|
|
2659
|
+
closed: false
|
|
2660
|
+
});
|
|
2661
|
+
}
|
|
2662
|
+
constructor(state, dupFrom) {
|
|
2663
|
+
super();
|
|
2664
|
+
this.state = state;
|
|
2665
|
+
if (dupFrom) ++state.refcount;
|
|
2666
|
+
}
|
|
2667
|
+
getState() {
|
|
2668
|
+
if (this.state) return this.state;
|
|
2669
|
+
else throw new Error("Attempted to use a WritableStreamStubHook after it was disposed.");
|
|
2670
|
+
}
|
|
2671
|
+
call(path, args) {
|
|
2672
|
+
try {
|
|
2673
|
+
let state = this.getState();
|
|
2674
|
+
if (path.length !== 1 || typeof path[0] !== "string") throw new Error("WritableStream stub only supports direct method calls");
|
|
2675
|
+
const method = path[0];
|
|
2676
|
+
if (method !== "write" && method !== "close" && method !== "abort") {
|
|
2677
|
+
args.dispose();
|
|
2678
|
+
throw new Error(`Unknown WritableStream method: ${method}`);
|
|
2679
|
+
}
|
|
2680
|
+
if (method === "close" || method === "abort") state.closed = true;
|
|
2681
|
+
let func = state.writer[method];
|
|
2682
|
+
return new PromiseStubHook(args.deliverCall(func, state.writer).then((payload) => new PayloadStubHook(payload)));
|
|
2683
|
+
} catch (err) {
|
|
2684
|
+
return new ErrorStubHook(err);
|
|
2685
|
+
}
|
|
2686
|
+
}
|
|
2687
|
+
map(path, captures, instructions) {
|
|
2688
|
+
for (let cap of captures) cap.dispose();
|
|
2689
|
+
return new ErrorStubHook(/* @__PURE__ */ new Error("Cannot use map() on a WritableStream"));
|
|
2690
|
+
}
|
|
2691
|
+
get(path) {
|
|
2692
|
+
return new ErrorStubHook(/* @__PURE__ */ new Error("Cannot access properties on a WritableStream stub"));
|
|
2693
|
+
}
|
|
2694
|
+
dup() {
|
|
2695
|
+
return new WritableStreamStubHook(this.getState(), this);
|
|
2696
|
+
}
|
|
2697
|
+
pull() {
|
|
2698
|
+
return Promise.reject(/* @__PURE__ */ new Error("Cannot pull a WritableStream stub"));
|
|
2699
|
+
}
|
|
2700
|
+
ignoreUnhandledRejections() {}
|
|
2701
|
+
dispose() {
|
|
2702
|
+
let state = this.state;
|
|
2703
|
+
this.state = void 0;
|
|
2704
|
+
if (state) {
|
|
2705
|
+
if (--state.refcount === 0) {
|
|
2706
|
+
if (!state.closed) state.writer.abort(/* @__PURE__ */ new Error("WritableStream RPC stub was disposed without calling close()")).catch(() => {});
|
|
2707
|
+
state.writer.releaseLock();
|
|
2708
|
+
}
|
|
2709
|
+
}
|
|
2710
|
+
}
|
|
2711
|
+
onBroken(callback) {}
|
|
2712
|
+
};
|
|
2713
|
+
const INITIAL_WINDOW = 256 * 1024;
|
|
2714
|
+
const MAX_WINDOW = 1024 * 1024 * 1024;
|
|
2715
|
+
const MIN_WINDOW = 64 * 1024;
|
|
2716
|
+
const STARTUP_GROWTH_FACTOR = 2;
|
|
2717
|
+
const STEADY_GROWTH_FACTOR = 1.25;
|
|
2718
|
+
const DECAY_FACTOR = .9;
|
|
2719
|
+
const STARTUP_EXIT_ROUNDS = 3;
|
|
2720
|
+
var FlowController = class {
|
|
2721
|
+
now;
|
|
2722
|
+
window = INITIAL_WINDOW;
|
|
2723
|
+
bytesInFlight = 0;
|
|
2724
|
+
inStartupPhase = true;
|
|
2725
|
+
delivered = 0;
|
|
2726
|
+
deliveredTime = 0;
|
|
2727
|
+
firstAckTime = 0;
|
|
2728
|
+
firstAckDelivered = 0;
|
|
2729
|
+
minRtt = Infinity;
|
|
2730
|
+
roundsWithoutIncrease = 0;
|
|
2731
|
+
lastRoundWindow = 0;
|
|
2732
|
+
roundStartTime = 0;
|
|
2733
|
+
constructor(now) {
|
|
2734
|
+
this.now = now;
|
|
2735
|
+
}
|
|
2736
|
+
onSend(size) {
|
|
2737
|
+
this.bytesInFlight += size;
|
|
2738
|
+
let token = {
|
|
2739
|
+
sentTime: this.now(),
|
|
2740
|
+
size,
|
|
2741
|
+
deliveredAtSend: this.delivered,
|
|
2742
|
+
deliveredTimeAtSend: this.deliveredTime,
|
|
2743
|
+
windowAtSend: this.window,
|
|
2744
|
+
windowFullAtSend: this.bytesInFlight >= this.window
|
|
2745
|
+
};
|
|
2746
|
+
return {
|
|
2747
|
+
token,
|
|
2748
|
+
shouldBlock: token.windowFullAtSend
|
|
2749
|
+
};
|
|
2750
|
+
}
|
|
2751
|
+
onError(token) {
|
|
2752
|
+
this.bytesInFlight -= token.size;
|
|
2753
|
+
}
|
|
2754
|
+
onAck(token) {
|
|
2755
|
+
let ackTime = this.now();
|
|
2756
|
+
this.delivered += token.size;
|
|
2757
|
+
this.deliveredTime = ackTime;
|
|
2758
|
+
this.bytesInFlight -= token.size;
|
|
2759
|
+
let rtt = ackTime - token.sentTime;
|
|
2760
|
+
this.minRtt = Math.min(this.minRtt, rtt);
|
|
2761
|
+
if (this.firstAckTime === 0) {
|
|
2762
|
+
this.firstAckTime = ackTime;
|
|
2763
|
+
this.firstAckDelivered = this.delivered;
|
|
2764
|
+
} else {
|
|
2765
|
+
let baseTime;
|
|
2766
|
+
let baseDelivered;
|
|
2767
|
+
if (token.deliveredTimeAtSend === 0) {
|
|
2768
|
+
baseTime = this.firstAckTime;
|
|
2769
|
+
baseDelivered = this.firstAckDelivered;
|
|
2770
|
+
} else {
|
|
2771
|
+
baseTime = token.deliveredTimeAtSend;
|
|
2772
|
+
baseDelivered = token.deliveredAtSend;
|
|
2773
|
+
}
|
|
2774
|
+
let interval = ackTime - baseTime;
|
|
2775
|
+
let bandwidth = (this.delivered - baseDelivered) / interval;
|
|
2776
|
+
let growthFactor = this.inStartupPhase ? STARTUP_GROWTH_FACTOR : STEADY_GROWTH_FACTOR;
|
|
2777
|
+
let newWindow = bandwidth * this.minRtt * growthFactor;
|
|
2778
|
+
newWindow = Math.min(newWindow, token.windowAtSend * growthFactor);
|
|
2779
|
+
if (token.windowFullAtSend) newWindow = Math.max(newWindow, token.windowAtSend * DECAY_FACTOR);
|
|
2780
|
+
else newWindow = Math.max(newWindow, this.window);
|
|
2781
|
+
this.window = Math.max(Math.min(newWindow, MAX_WINDOW), MIN_WINDOW);
|
|
2782
|
+
if (this.inStartupPhase && token.sentTime >= this.roundStartTime) {
|
|
2783
|
+
if (this.window > this.lastRoundWindow * STEADY_GROWTH_FACTOR) this.roundsWithoutIncrease = 0;
|
|
2784
|
+
else if (++this.roundsWithoutIncrease >= STARTUP_EXIT_ROUNDS) this.inStartupPhase = false;
|
|
2785
|
+
this.roundStartTime = ackTime;
|
|
2786
|
+
this.lastRoundWindow = this.window;
|
|
2787
|
+
}
|
|
2788
|
+
}
|
|
2789
|
+
return this.bytesInFlight < this.window;
|
|
2790
|
+
}
|
|
2791
|
+
};
|
|
2792
|
+
function createWritableStreamFromHook(hook) {
|
|
2793
|
+
let pendingError = void 0;
|
|
2794
|
+
let hookDisposed = false;
|
|
2795
|
+
let fc = new FlowController(() => performance.now());
|
|
2796
|
+
let windowResolve;
|
|
2797
|
+
let windowReject;
|
|
2798
|
+
const disposeHook = () => {
|
|
2799
|
+
if (!hookDisposed) {
|
|
2800
|
+
hookDisposed = true;
|
|
2801
|
+
hook.dispose();
|
|
2802
|
+
}
|
|
2803
|
+
};
|
|
2804
|
+
return new WritableStream({
|
|
2805
|
+
write(chunk, controller) {
|
|
2806
|
+
if (pendingError !== void 0) throw pendingError;
|
|
2807
|
+
const payload = RpcPayload.fromAppParams([chunk]);
|
|
2808
|
+
const { promise, size } = hook.stream(["write"], payload);
|
|
2809
|
+
if (size === void 0) return promise.catch((err) => {
|
|
2810
|
+
if (pendingError === void 0) pendingError = err;
|
|
2811
|
+
throw err;
|
|
2812
|
+
});
|
|
2813
|
+
else {
|
|
2814
|
+
let { token, shouldBlock } = fc.onSend(size);
|
|
2815
|
+
promise.then(() => {
|
|
2816
|
+
if (fc.onAck(token) && windowResolve) {
|
|
2817
|
+
windowResolve();
|
|
2818
|
+
windowResolve = void 0;
|
|
2819
|
+
windowReject = void 0;
|
|
2820
|
+
}
|
|
2821
|
+
}, (err) => {
|
|
2822
|
+
fc.onError(token);
|
|
2823
|
+
if (pendingError === void 0) {
|
|
2824
|
+
pendingError = err;
|
|
2825
|
+
controller.error(err);
|
|
2826
|
+
disposeHook();
|
|
2827
|
+
}
|
|
2828
|
+
if (windowReject) {
|
|
2829
|
+
windowReject(err);
|
|
2830
|
+
windowResolve = void 0;
|
|
2831
|
+
windowReject = void 0;
|
|
2832
|
+
}
|
|
2833
|
+
});
|
|
2834
|
+
if (shouldBlock) return new Promise((resolve, reject) => {
|
|
2835
|
+
windowResolve = resolve;
|
|
2836
|
+
windowReject = reject;
|
|
2837
|
+
});
|
|
2838
|
+
}
|
|
2839
|
+
},
|
|
2840
|
+
async close() {
|
|
2841
|
+
if (pendingError !== void 0) {
|
|
2842
|
+
disposeHook();
|
|
2843
|
+
throw pendingError;
|
|
2844
|
+
}
|
|
2845
|
+
const { promise } = hook.stream(["close"], RpcPayload.fromAppParams([]));
|
|
2846
|
+
try {
|
|
2847
|
+
await promise;
|
|
2848
|
+
} catch (err) {
|
|
2849
|
+
throw pendingError ?? err;
|
|
2850
|
+
} finally {
|
|
2851
|
+
disposeHook();
|
|
2852
|
+
}
|
|
2853
|
+
},
|
|
2854
|
+
abort(reason) {
|
|
2855
|
+
if (pendingError !== void 0) return;
|
|
2856
|
+
pendingError = reason ?? /* @__PURE__ */ new Error("WritableStream was aborted");
|
|
2857
|
+
if (windowReject) {
|
|
2858
|
+
windowReject(pendingError);
|
|
2859
|
+
windowResolve = void 0;
|
|
2860
|
+
windowReject = void 0;
|
|
2861
|
+
}
|
|
2862
|
+
const { promise } = hook.stream(["abort"], RpcPayload.fromAppParams([reason]));
|
|
2863
|
+
promise.then(() => disposeHook(), () => disposeHook());
|
|
2864
|
+
}
|
|
2865
|
+
});
|
|
2866
|
+
}
|
|
2867
|
+
var ReadableStreamStubHook = class ReadableStreamStubHook extends StubHook {
|
|
2868
|
+
state;
|
|
2869
|
+
static create(stream) {
|
|
2870
|
+
return new ReadableStreamStubHook({
|
|
2871
|
+
refcount: 1,
|
|
2872
|
+
stream,
|
|
2873
|
+
canceled: false
|
|
2874
|
+
});
|
|
2875
|
+
}
|
|
2876
|
+
constructor(state, dupFrom) {
|
|
2877
|
+
super();
|
|
2878
|
+
this.state = state;
|
|
2879
|
+
if (dupFrom) ++state.refcount;
|
|
2880
|
+
}
|
|
2881
|
+
call(path, args) {
|
|
2882
|
+
args.dispose();
|
|
2883
|
+
return new ErrorStubHook(/* @__PURE__ */ new Error("Cannot call methods on a ReadableStream stub"));
|
|
2884
|
+
}
|
|
2885
|
+
map(path, captures, instructions) {
|
|
2886
|
+
for (let cap of captures) cap.dispose();
|
|
2887
|
+
return new ErrorStubHook(/* @__PURE__ */ new Error("Cannot use map() on a ReadableStream"));
|
|
2888
|
+
}
|
|
2889
|
+
get(path) {
|
|
2890
|
+
return new ErrorStubHook(/* @__PURE__ */ new Error("Cannot access properties on a ReadableStream stub"));
|
|
2891
|
+
}
|
|
2892
|
+
dup() {
|
|
2893
|
+
let state = this.state;
|
|
2894
|
+
if (!state) throw new Error("Attempted to dup a ReadableStreamStubHook after it was disposed.");
|
|
2895
|
+
return new ReadableStreamStubHook(state, this);
|
|
2896
|
+
}
|
|
2897
|
+
pull() {
|
|
2898
|
+
return Promise.reject(/* @__PURE__ */ new Error("Cannot pull a ReadableStream stub"));
|
|
2899
|
+
}
|
|
2900
|
+
ignoreUnhandledRejections() {}
|
|
2901
|
+
dispose() {
|
|
2902
|
+
let state = this.state;
|
|
2903
|
+
this.state = void 0;
|
|
2904
|
+
if (state) {
|
|
2905
|
+
if (--state.refcount === 0) {
|
|
2906
|
+
if (!state.canceled) {
|
|
2907
|
+
state.canceled = true;
|
|
2908
|
+
if (!state.stream.locked) state.stream.cancel(/* @__PURE__ */ new Error("ReadableStream RPC stub was disposed without being consumed")).catch(() => {});
|
|
2909
|
+
}
|
|
2910
|
+
}
|
|
2911
|
+
}
|
|
2912
|
+
}
|
|
2913
|
+
onBroken(callback) {}
|
|
2914
|
+
};
|
|
2915
|
+
streamImpl.createWritableStreamHook = WritableStreamStubHook.create;
|
|
2916
|
+
streamImpl.createWritableStreamFromHook = createWritableStreamFromHook;
|
|
2917
|
+
streamImpl.createReadableStreamHook = ReadableStreamStubHook.create;
|
|
2918
|
+
|
|
2919
|
+
//#endregion
|
|
2920
|
+
//#region src/index.ts
|
|
2921
|
+
const RpcStub = RpcStub$1;
|
|
2922
|
+
const RpcPromise = RpcPromise$1;
|
|
2923
|
+
const RpcSession = RpcSession$1;
|
|
2924
|
+
const RpcTarget = RpcTarget$1;
|
|
2925
|
+
/**
|
|
2926
|
+
* Start a WebSocket session given either an already-open WebSocket or a URL.
|
|
2927
|
+
*
|
|
2928
|
+
* @param webSocket Either the `wss://` URL to connect to, or an already-open WebSocket object to
|
|
2929
|
+
* use.
|
|
2930
|
+
* @param localMain The main RPC interface to expose to the peer. Returns a stub for the main
|
|
2931
|
+
* interface exposed from the peer.
|
|
2932
|
+
*/
|
|
2933
|
+
let newWebSocketRpcSession = newWebSocketRpcSession$1;
|
|
2934
|
+
/**
|
|
2935
|
+
* Initiate an HTTP batch session from the client side.
|
|
2936
|
+
*
|
|
2937
|
+
* The parameters to this method have exactly the same signature as `fetch()`, but the return
|
|
2938
|
+
* value is an RpcStub. You can customize anything about the request except for the method
|
|
2939
|
+
* (it will always be set to POST) and the body (which the RPC system will fill in).
|
|
2940
|
+
*/
|
|
2941
|
+
let newHttpBatchRpcSession = newHttpBatchRpcSession$1;
|
|
2942
|
+
/**
|
|
2943
|
+
* Initiate an RPC session over a MessagePort, which is particularly useful for communicating
|
|
2944
|
+
* between an iframe and its parent frame in a browser context. Each side should call this function
|
|
2945
|
+
* on its own end of the MessageChannel.
|
|
2946
|
+
*/
|
|
2947
|
+
let newMessagePortRpcSession = newMessagePortRpcSession$1;
|
|
2948
|
+
/**
|
|
2949
|
+
* Implements unified handling of HTTP-batch and WebSocket responses for the Cloudflare Workers
|
|
2950
|
+
* Runtime.
|
|
2951
|
+
*
|
|
2952
|
+
* SECURITY WARNING: This function accepts cross-origin requests. If you do not want this, you
|
|
2953
|
+
* should validate the `Origin` header before calling this, or use `newHttpBatchRpcSession()` and
|
|
2954
|
+
* `newWebSocketRpcSession()` directly with appropriate security measures for each type of request.
|
|
2955
|
+
* But if your API uses in-band authorization (i.e. it has an RPC method that takes the user's
|
|
2956
|
+
* credentials as parameters and returns the authorized API), then cross-origin requests should
|
|
2957
|
+
* be safe.
|
|
2958
|
+
*/
|
|
2959
|
+
async function newWorkersRpcResponse(request, localMain, options) {
|
|
2960
|
+
if (request.method === "POST") {
|
|
2961
|
+
let response = await newHttpBatchRpcResponse(request, localMain, options);
|
|
2962
|
+
response.headers.set("Access-Control-Allow-Origin", "*");
|
|
2963
|
+
return response;
|
|
2964
|
+
} else if (request.headers.get("Upgrade")?.toLowerCase() === "websocket") return newWorkersWebSocketRpcResponse(request, localMain, options);
|
|
2965
|
+
else return new Response("This endpoint only accepts POST or WebSocket requests.", { status: 400 });
|
|
2966
|
+
}
|
|
2967
|
+
|
|
2968
|
+
//#endregion
|
|
2969
|
+
//#region src/bun.ts
|
|
2970
|
+
/**
|
|
2971
|
+
* Start an RPC session over a Bun ServerWebSocket.
|
|
2972
|
+
*
|
|
2973
|
+
* Returns both the stub and the transport. The transport must be wired to Bun's
|
|
2974
|
+
* `WebSocketHandler` callbacks (`message`, `close`, `error`) by calling its
|
|
2975
|
+
* `dispatchMessage`, `dispatchClose`, and `dispatchError` methods.
|
|
2976
|
+
*
|
|
2977
|
+
* For a zero-wiring alternative, see `newBunWebSocketRpcHandler`.
|
|
2978
|
+
*/
|
|
2979
|
+
function newBunWebSocketRpcSession$1(ws, localMain, options) {
|
|
2980
|
+
let transport = new BunWebSocketTransport(ws);
|
|
2981
|
+
return {
|
|
2982
|
+
stub: new RpcSession$1(transport, localMain, options).getRemoteMain(),
|
|
2983
|
+
transport
|
|
2984
|
+
};
|
|
2985
|
+
}
|
|
2986
|
+
/**
|
|
2987
|
+
* Create a Bun `WebSocketHandler` object that manages RPC sessions automatically.
|
|
2988
|
+
*
|
|
2989
|
+
* The returned object can be passed directly as the `websocket` option to `Bun.serve()`.
|
|
2990
|
+
* A fresh `localMain` is created for each connection via the `createMain` callback.
|
|
2991
|
+
* The transport is stored on `ws.data.__capnwebTransport`.
|
|
2992
|
+
*
|
|
2993
|
+
* @param createMain Called once per connection to create the main RPC interface for that client.
|
|
2994
|
+
* @param options Optional RPC session options applied to every connection.
|
|
2995
|
+
*/
|
|
2996
|
+
function newBunWebSocketRpcHandler(createMain, options) {
|
|
2997
|
+
return {
|
|
2998
|
+
open(ws) {
|
|
2999
|
+
let transport = new BunWebSocketTransport(ws);
|
|
3000
|
+
ws.data = {
|
|
3001
|
+
__capnwebTransport: transport,
|
|
3002
|
+
__capnwebStub: new RpcSession$1(transport, createMain(), options).getRemoteMain()
|
|
3003
|
+
};
|
|
3004
|
+
},
|
|
3005
|
+
message(ws, message) {
|
|
3006
|
+
ws.data.__capnwebTransport.dispatchMessage(message);
|
|
3007
|
+
},
|
|
3008
|
+
close(ws, code, reason) {
|
|
3009
|
+
ws.data.__capnwebTransport.dispatchClose(code, reason);
|
|
3010
|
+
},
|
|
3011
|
+
error(ws, error) {
|
|
3012
|
+
ws.data.__capnwebTransport.dispatchError(error);
|
|
3013
|
+
}
|
|
3014
|
+
};
|
|
3015
|
+
}
|
|
3016
|
+
var BunWebSocketTransport = class {
|
|
3017
|
+
constructor(ws) {
|
|
3018
|
+
this.#ws = ws;
|
|
3019
|
+
}
|
|
3020
|
+
#ws;
|
|
3021
|
+
#receiveResolver;
|
|
3022
|
+
#receiveRejecter;
|
|
3023
|
+
#receiveQueue = [];
|
|
3024
|
+
#error;
|
|
3025
|
+
async send(message) {
|
|
3026
|
+
this.#ws.send(message);
|
|
3027
|
+
}
|
|
3028
|
+
async receive() {
|
|
3029
|
+
if (this.#receiveQueue.length > 0) return this.#receiveQueue.shift();
|
|
3030
|
+
else if (this.#error) throw this.#error;
|
|
3031
|
+
else return new Promise((resolve, reject) => {
|
|
3032
|
+
this.#receiveResolver = resolve;
|
|
3033
|
+
this.#receiveRejecter = reject;
|
|
3034
|
+
});
|
|
3035
|
+
}
|
|
3036
|
+
abort(reason) {
|
|
3037
|
+
let message;
|
|
3038
|
+
if (reason instanceof Error) message = reason.message;
|
|
3039
|
+
else message = `${reason}`;
|
|
3040
|
+
this.#ws.close(3e3, message);
|
|
3041
|
+
if (!this.#error) this.#error = reason;
|
|
3042
|
+
}
|
|
3043
|
+
dispatchMessage(data) {
|
|
3044
|
+
if (this.#error) return;
|
|
3045
|
+
let strData = typeof data === "string" ? data : data.toString("utf-8");
|
|
3046
|
+
if (this.#receiveResolver) {
|
|
3047
|
+
this.#receiveResolver(strData);
|
|
3048
|
+
this.#receiveResolver = void 0;
|
|
3049
|
+
this.#receiveRejecter = void 0;
|
|
3050
|
+
} else this.#receiveQueue.push(strData);
|
|
3051
|
+
}
|
|
3052
|
+
dispatchClose(code, reason) {
|
|
3053
|
+
this.#receivedError(/* @__PURE__ */ new Error(`Peer closed WebSocket: ${code} ${reason}`));
|
|
3054
|
+
}
|
|
3055
|
+
dispatchError(error) {
|
|
3056
|
+
this.#receivedError(/* @__PURE__ */ new Error(`WebSocket connection failed.`));
|
|
3057
|
+
}
|
|
3058
|
+
#receivedError(reason) {
|
|
3059
|
+
if (!this.#error) {
|
|
3060
|
+
this.#error = reason;
|
|
3061
|
+
if (this.#receiveRejecter) {
|
|
3062
|
+
this.#receiveRejecter(reason);
|
|
3063
|
+
this.#receiveResolver = void 0;
|
|
3064
|
+
this.#receiveRejecter = void 0;
|
|
3065
|
+
}
|
|
3066
|
+
}
|
|
3067
|
+
}
|
|
3068
|
+
};
|
|
3069
|
+
|
|
3070
|
+
//#endregion
|
|
3071
|
+
//#region src/index-bun.ts
|
|
3072
|
+
/**
|
|
3073
|
+
* Start an RPC session over a Bun ServerWebSocket.
|
|
3074
|
+
*
|
|
3075
|
+
* Returns both the RPC stub and the transport. The transport exposes `dispatchMessage`,
|
|
3076
|
+
* `dispatchClose`, and `dispatchError` methods that must be wired to Bun's `WebSocketHandler`
|
|
3077
|
+
* callbacks. For a zero-wiring alternative, use `newBunWebSocketRpcHandler` instead.
|
|
3078
|
+
*
|
|
3079
|
+
* @param ws The Bun ServerWebSocket from the `open` callback.
|
|
3080
|
+
* @param localMain The main RPC interface to expose to the peer.
|
|
3081
|
+
*/
|
|
3082
|
+
let newBunWebSocketRpcSession = newBunWebSocketRpcSession$1;
|
|
3083
|
+
|
|
3084
|
+
//#endregion
|
|
3085
|
+
exports.BunWebSocketTransport = BunWebSocketTransport;
|
|
3086
|
+
exports.DEFAULT_LIMITS = DEFAULT_LIMITS;
|
|
3087
|
+
exports.DEFAULT_MAX_DEPTH = DEFAULT_MAX_DEPTH;
|
|
3088
|
+
exports.RpcPromise = RpcPromise;
|
|
3089
|
+
exports.RpcSession = RpcSession;
|
|
3090
|
+
exports.RpcStub = RpcStub;
|
|
3091
|
+
exports.RpcTarget = RpcTarget;
|
|
3092
|
+
exports.WebSocketTransport = WebSocketTransport;
|
|
3093
|
+
exports.deserialize = deserialize;
|
|
3094
|
+
exports.newBunWebSocketRpcHandler = newBunWebSocketRpcHandler;
|
|
3095
|
+
exports.newBunWebSocketRpcSession = newBunWebSocketRpcSession;
|
|
3096
|
+
exports.newHttpBatchRpcResponse = newHttpBatchRpcResponse;
|
|
3097
|
+
exports.newHttpBatchRpcSession = newHttpBatchRpcSession;
|
|
3098
|
+
exports.newMessagePortRpcSession = newMessagePortRpcSession;
|
|
3099
|
+
exports.newWebSocketRpcSession = newWebSocketRpcSession;
|
|
3100
|
+
exports.newWorkersRpcResponse = newWorkersRpcResponse;
|
|
3101
|
+
exports.newWorkersWebSocketRpcResponse = newWorkersWebSocketRpcResponse;
|
|
3102
|
+
exports.nodeHttpBatchRpcResponse = nodeHttpBatchRpcResponse;
|
|
3103
|
+
exports.serialize = serialize;
|
|
3104
|
+
//# sourceMappingURL=index-bun.cjs.map
|