capnweb 0.0.0-b2fcb34 → 0.0.0-c2bb17b
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 +17 -1
- package/dist/index-workers.cjs +3263 -0
- package/dist/index-workers.cjs.map +1 -0
- package/dist/index-workers.d.cts +2 -0
- package/dist/index-workers.d.ts +1 -1
- package/dist/index-workers.js +688 -42
- package/dist/index-workers.js.map +1 -1
- package/dist/index.cjs +3240 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +372 -0
- package/dist/index.d.ts +30 -22
- package/dist/index.js +688 -42
- package/dist/index.js.map +1 -1
- package/package.json +17 -13
package/dist/index-workers.js
CHANGED
|
@@ -1,19 +1,32 @@
|
|
|
1
1
|
import * as cfw from 'cloudflare:workers';
|
|
2
2
|
|
|
3
3
|
// src/symbols.ts
|
|
4
|
-
var WORKERS_MODULE_SYMBOL = Symbol("workers-module");
|
|
4
|
+
var WORKERS_MODULE_SYMBOL = /* @__PURE__ */ Symbol("workers-module");
|
|
5
5
|
globalThis[WORKERS_MODULE_SYMBOL] = cfw;
|
|
6
6
|
|
|
7
7
|
// src/core.ts
|
|
8
8
|
if (!Symbol.dispose) {
|
|
9
|
-
Symbol.dispose = Symbol.for("dispose");
|
|
9
|
+
Symbol.dispose = /* @__PURE__ */ Symbol.for("dispose");
|
|
10
10
|
}
|
|
11
11
|
if (!Symbol.asyncDispose) {
|
|
12
|
-
Symbol.asyncDispose = Symbol.for("asyncDispose");
|
|
12
|
+
Symbol.asyncDispose = /* @__PURE__ */ Symbol.for("asyncDispose");
|
|
13
|
+
}
|
|
14
|
+
if (!Promise.withResolvers) {
|
|
15
|
+
Promise.withResolvers = function() {
|
|
16
|
+
let resolve;
|
|
17
|
+
let reject;
|
|
18
|
+
const promise = new Promise((res, rej) => {
|
|
19
|
+
resolve = res;
|
|
20
|
+
reject = rej;
|
|
21
|
+
});
|
|
22
|
+
return { promise, resolve, reject };
|
|
23
|
+
};
|
|
13
24
|
}
|
|
14
25
|
var workersModule = globalThis[WORKERS_MODULE_SYMBOL];
|
|
15
26
|
var RpcTarget = workersModule ? workersModule.RpcTarget : class {
|
|
16
27
|
};
|
|
28
|
+
var AsyncFunction = (async function() {
|
|
29
|
+
}).constructor;
|
|
17
30
|
function typeForRpc(value) {
|
|
18
31
|
switch (typeof value) {
|
|
19
32
|
case "boolean":
|
|
@@ -38,6 +51,7 @@ function typeForRpc(value) {
|
|
|
38
51
|
case Object.prototype:
|
|
39
52
|
return "object";
|
|
40
53
|
case Function.prototype:
|
|
54
|
+
case AsyncFunction.prototype:
|
|
41
55
|
return "function";
|
|
42
56
|
case Array.prototype:
|
|
43
57
|
return "array";
|
|
@@ -45,6 +59,10 @@ function typeForRpc(value) {
|
|
|
45
59
|
return "date";
|
|
46
60
|
case Uint8Array.prototype:
|
|
47
61
|
return "bytes";
|
|
62
|
+
case WritableStream.prototype:
|
|
63
|
+
return "writable";
|
|
64
|
+
case ReadableStream.prototype:
|
|
65
|
+
return "readable";
|
|
48
66
|
// TODO: All other structured clone types.
|
|
49
67
|
case RpcStub.prototype:
|
|
50
68
|
return "stub";
|
|
@@ -72,7 +90,34 @@ function mapNotLoaded() {
|
|
|
72
90
|
throw new Error("RPC map() implementation was not loaded.");
|
|
73
91
|
}
|
|
74
92
|
var mapImpl = { applyMap: mapNotLoaded, sendMap: mapNotLoaded };
|
|
93
|
+
function streamNotLoaded() {
|
|
94
|
+
throw new Error("Stream implementation was not loaded.");
|
|
95
|
+
}
|
|
96
|
+
var streamImpl = {
|
|
97
|
+
createWritableStreamHook: streamNotLoaded,
|
|
98
|
+
createWritableStreamFromHook: streamNotLoaded,
|
|
99
|
+
createReadableStreamHook: streamNotLoaded
|
|
100
|
+
};
|
|
75
101
|
var StubHook = class {
|
|
102
|
+
// Like call(), but designed for streaming calls (e.g. WritableStream writes). Returns:
|
|
103
|
+
// - promise: A Promise<void> for the completion of the call.
|
|
104
|
+
// - size: If the call was remote, the byte size of the serialized message. For local calls,
|
|
105
|
+
// undefined is returned, indicating the caller should await the promise to serialize writes
|
|
106
|
+
// (no overlapping).
|
|
107
|
+
stream(path, args) {
|
|
108
|
+
let hook = this.call(path, args);
|
|
109
|
+
let pulled = hook.pull();
|
|
110
|
+
let promise;
|
|
111
|
+
if (pulled instanceof Promise) {
|
|
112
|
+
promise = pulled.then((p) => {
|
|
113
|
+
p.dispose();
|
|
114
|
+
});
|
|
115
|
+
} else {
|
|
116
|
+
pulled.dispose();
|
|
117
|
+
promise = Promise.resolve();
|
|
118
|
+
}
|
|
119
|
+
return { promise };
|
|
120
|
+
}
|
|
76
121
|
};
|
|
77
122
|
var ErrorStubHook = class extends StubHook {
|
|
78
123
|
constructor(error) {
|
|
@@ -121,7 +166,7 @@ function withCallInterceptor(interceptor, callback) {
|
|
|
121
166
|
doCall = oldValue;
|
|
122
167
|
}
|
|
123
168
|
}
|
|
124
|
-
var RAW_STUB = Symbol("realStub");
|
|
169
|
+
var RAW_STUB = /* @__PURE__ */ Symbol("realStub");
|
|
125
170
|
var PROXY_HANDLERS = {
|
|
126
171
|
apply(target, thisArg, argumentsList) {
|
|
127
172
|
let stub = target.raw;
|
|
@@ -236,6 +281,9 @@ var RpcStub = class _RpcStub extends RpcTarget {
|
|
|
236
281
|
let { hook, pathIfPromise } = this[RAW_STUB];
|
|
237
282
|
return mapImpl.sendMap(hook, pathIfPromise || [], func);
|
|
238
283
|
}
|
|
284
|
+
toString() {
|
|
285
|
+
return "[object RpcStub]";
|
|
286
|
+
}
|
|
239
287
|
};
|
|
240
288
|
var RpcPromise = class extends RpcStub {
|
|
241
289
|
// TODO: Support passing target value or promise to constructor.
|
|
@@ -251,6 +299,9 @@ var RpcPromise = class extends RpcStub {
|
|
|
251
299
|
finally(onfinally) {
|
|
252
300
|
return pullPromise(this).finally(...arguments);
|
|
253
301
|
}
|
|
302
|
+
toString() {
|
|
303
|
+
return "[object RpcPromise]";
|
|
304
|
+
}
|
|
254
305
|
};
|
|
255
306
|
function unwrapStubTakingOwnership(stub) {
|
|
256
307
|
let { hook, pathIfPromise } = stub[RAW_STUB];
|
|
@@ -291,10 +342,10 @@ async function pullPromise(promise) {
|
|
|
291
342
|
}
|
|
292
343
|
var RpcPayload = class _RpcPayload {
|
|
293
344
|
// Private constructor; use factory functions above to construct.
|
|
294
|
-
constructor(value, source,
|
|
345
|
+
constructor(value, source, hooks, promises) {
|
|
295
346
|
this.value = value;
|
|
296
347
|
this.source = source;
|
|
297
|
-
this.
|
|
348
|
+
this.hooks = hooks;
|
|
298
349
|
this.promises = promises;
|
|
299
350
|
}
|
|
300
351
|
// Create a payload from a value passed as params to an RPC from the app.
|
|
@@ -319,13 +370,13 @@ var RpcPayload = class _RpcPayload {
|
|
|
319
370
|
// stubs is transferred from the inputs to the outputs, hence if the output is disposed, the
|
|
320
371
|
// inputs should not be. (In case of exception, nothing is disposed, though.)
|
|
321
372
|
static fromArray(array) {
|
|
322
|
-
let
|
|
373
|
+
let hooks = [];
|
|
323
374
|
let promises = [];
|
|
324
375
|
let resultArray = [];
|
|
325
376
|
for (let payload of array) {
|
|
326
377
|
payload.ensureDeepCopied();
|
|
327
|
-
for (let
|
|
328
|
-
|
|
378
|
+
for (let hook of payload.hooks) {
|
|
379
|
+
hooks.push(hook);
|
|
329
380
|
}
|
|
330
381
|
for (let promise of payload.promises) {
|
|
331
382
|
if (promise.parent === payload) {
|
|
@@ -339,12 +390,12 @@ var RpcPayload = class _RpcPayload {
|
|
|
339
390
|
}
|
|
340
391
|
resultArray.push(payload.value);
|
|
341
392
|
}
|
|
342
|
-
return new _RpcPayload(resultArray, "owned",
|
|
393
|
+
return new _RpcPayload(resultArray, "owned", hooks, promises);
|
|
343
394
|
}
|
|
344
395
|
// Create a payload from a value parsed off the wire using Evaluator.evaluate().
|
|
345
396
|
//
|
|
346
|
-
// A payload is constructed with a null value and the given
|
|
347
|
-
// is expected to be filled in by the evaluator, and the
|
|
397
|
+
// A payload is constructed with a null value and the given hooks and promises arrays. The value
|
|
398
|
+
// is expected to be filled in by the evaluator, and the hooks and promises arrays are expected
|
|
348
399
|
// to be extended with stubs found during parsing. (This weird usage model is necessary so that
|
|
349
400
|
// if the root value turns out to be a promise, its `parent` in `promises` can be the payload
|
|
350
401
|
// object itself.)
|
|
@@ -352,8 +403,8 @@ var RpcPayload = class _RpcPayload {
|
|
|
352
403
|
// When done, the payload takes ownership of the final value and all the stubs within. It may
|
|
353
404
|
// modify the value in preparation for delivery, and may deliver the value directly to the app
|
|
354
405
|
// without copying.
|
|
355
|
-
static forEvaluate(
|
|
356
|
-
return new _RpcPayload(null, "owned",
|
|
406
|
+
static forEvaluate(hooks, promises) {
|
|
407
|
+
return new _RpcPayload(null, "owned", hooks, promises);
|
|
357
408
|
}
|
|
358
409
|
// Deep-copy the given value, including dup()ing all stubs.
|
|
359
410
|
//
|
|
@@ -375,14 +426,20 @@ var RpcPayload = class _RpcPayload {
|
|
|
375
426
|
return result;
|
|
376
427
|
}
|
|
377
428
|
// For `source === "return"` payloads only, this tracks any StubHooks created around RpcTargets
|
|
378
|
-
// found in the payload at the time that it is serialized (or deep-copied) for
|
|
379
|
-
// can make sure they are not disposed before the pipeline ends.
|
|
429
|
+
// or WritableStreams found in the payload at the time that it is serialized (or deep-copied) for
|
|
430
|
+
// return, so that we can make sure they are not disposed before the pipeline ends.
|
|
380
431
|
//
|
|
381
432
|
// This is initialized on first use.
|
|
382
433
|
rpcTargets;
|
|
383
434
|
// Get the StubHook representing the given RpcTarget found inside this payload.
|
|
384
435
|
getHookForRpcTarget(target, parent, dupStubs = true) {
|
|
385
436
|
if (this.source === "params") {
|
|
437
|
+
if (dupStubs) {
|
|
438
|
+
let dupable = target;
|
|
439
|
+
if (typeof dupable.dup === "function") {
|
|
440
|
+
target = dupable.dup();
|
|
441
|
+
}
|
|
442
|
+
}
|
|
386
443
|
return TargetStubHook.create(target, parent);
|
|
387
444
|
} else if (this.source === "return") {
|
|
388
445
|
let hook = this.rpcTargets?.get(target);
|
|
@@ -409,6 +466,64 @@ var RpcPayload = class _RpcPayload {
|
|
|
409
466
|
throw new Error("owned payload shouldn't contain raw RpcTargets");
|
|
410
467
|
}
|
|
411
468
|
}
|
|
469
|
+
// Get the StubHook representing the given WritableStream found inside this payload.
|
|
470
|
+
getHookForWritableStream(stream, parent, dupStubs = true) {
|
|
471
|
+
if (this.source === "params") {
|
|
472
|
+
return streamImpl.createWritableStreamHook(stream);
|
|
473
|
+
} else if (this.source === "return") {
|
|
474
|
+
let hook = this.rpcTargets?.get(stream);
|
|
475
|
+
if (hook) {
|
|
476
|
+
if (dupStubs) {
|
|
477
|
+
return hook.dup();
|
|
478
|
+
} else {
|
|
479
|
+
this.rpcTargets?.delete(stream);
|
|
480
|
+
return hook;
|
|
481
|
+
}
|
|
482
|
+
} else {
|
|
483
|
+
hook = streamImpl.createWritableStreamHook(stream);
|
|
484
|
+
if (dupStubs) {
|
|
485
|
+
if (!this.rpcTargets) {
|
|
486
|
+
this.rpcTargets = /* @__PURE__ */ new Map();
|
|
487
|
+
}
|
|
488
|
+
this.rpcTargets.set(stream, hook);
|
|
489
|
+
return hook.dup();
|
|
490
|
+
} else {
|
|
491
|
+
return hook;
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
} else {
|
|
495
|
+
throw new Error("owned payload shouldn't contain raw WritableStreams");
|
|
496
|
+
}
|
|
497
|
+
}
|
|
498
|
+
// Get the StubHook representing the given ReadableStream found inside this payload.
|
|
499
|
+
getHookForReadableStream(stream, parent, dupStubs = true) {
|
|
500
|
+
if (this.source === "params") {
|
|
501
|
+
return streamImpl.createReadableStreamHook(stream);
|
|
502
|
+
} else if (this.source === "return") {
|
|
503
|
+
let hook = this.rpcTargets?.get(stream);
|
|
504
|
+
if (hook) {
|
|
505
|
+
if (dupStubs) {
|
|
506
|
+
return hook.dup();
|
|
507
|
+
} else {
|
|
508
|
+
this.rpcTargets?.delete(stream);
|
|
509
|
+
return hook;
|
|
510
|
+
}
|
|
511
|
+
} else {
|
|
512
|
+
hook = streamImpl.createReadableStreamHook(stream);
|
|
513
|
+
if (dupStubs) {
|
|
514
|
+
if (!this.rpcTargets) {
|
|
515
|
+
this.rpcTargets = /* @__PURE__ */ new Map();
|
|
516
|
+
}
|
|
517
|
+
this.rpcTargets.set(stream, hook);
|
|
518
|
+
return hook.dup();
|
|
519
|
+
} else {
|
|
520
|
+
return hook;
|
|
521
|
+
}
|
|
522
|
+
}
|
|
523
|
+
} else {
|
|
524
|
+
throw new Error("owned payload shouldn't contain raw ReadableStreams");
|
|
525
|
+
}
|
|
526
|
+
}
|
|
412
527
|
deepCopy(value, oldParent, property, parent, dupStubs, owner) {
|
|
413
528
|
let kind = typeForRpc(value);
|
|
414
529
|
switch (kind) {
|
|
@@ -452,22 +567,21 @@ var RpcPayload = class _RpcPayload {
|
|
|
452
567
|
this.promises.push({ parent, property, promise });
|
|
453
568
|
return promise;
|
|
454
569
|
} else {
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
return newStub;
|
|
570
|
+
this.hooks.push(hook);
|
|
571
|
+
return new RpcStub(hook);
|
|
458
572
|
}
|
|
459
573
|
}
|
|
460
574
|
case "function":
|
|
461
575
|
case "rpc-target": {
|
|
462
576
|
let target = value;
|
|
463
|
-
let
|
|
577
|
+
let hook;
|
|
464
578
|
if (owner) {
|
|
465
|
-
|
|
579
|
+
hook = owner.getHookForRpcTarget(target, oldParent, dupStubs);
|
|
466
580
|
} else {
|
|
467
|
-
|
|
581
|
+
hook = TargetStubHook.create(target, oldParent);
|
|
468
582
|
}
|
|
469
|
-
this.
|
|
470
|
-
return
|
|
583
|
+
this.hooks.push(hook);
|
|
584
|
+
return new RpcStub(hook);
|
|
471
585
|
}
|
|
472
586
|
case "rpc-thenable": {
|
|
473
587
|
let target = value;
|
|
@@ -480,6 +594,28 @@ var RpcPayload = class _RpcPayload {
|
|
|
480
594
|
this.promises.push({ parent, property, promise });
|
|
481
595
|
return promise;
|
|
482
596
|
}
|
|
597
|
+
case "writable": {
|
|
598
|
+
let stream = value;
|
|
599
|
+
let hook;
|
|
600
|
+
if (owner) {
|
|
601
|
+
hook = owner.getHookForWritableStream(stream, oldParent, dupStubs);
|
|
602
|
+
} else {
|
|
603
|
+
hook = streamImpl.createWritableStreamHook(stream);
|
|
604
|
+
}
|
|
605
|
+
this.hooks.push(hook);
|
|
606
|
+
return stream;
|
|
607
|
+
}
|
|
608
|
+
case "readable": {
|
|
609
|
+
let stream = value;
|
|
610
|
+
let hook;
|
|
611
|
+
if (owner) {
|
|
612
|
+
hook = owner.getHookForReadableStream(stream, oldParent, dupStubs);
|
|
613
|
+
} else {
|
|
614
|
+
hook = streamImpl.createReadableStreamHook(stream);
|
|
615
|
+
}
|
|
616
|
+
this.hooks.push(hook);
|
|
617
|
+
return stream;
|
|
618
|
+
}
|
|
483
619
|
default:
|
|
484
620
|
throw new Error("unreachable");
|
|
485
621
|
}
|
|
@@ -489,12 +625,12 @@ var RpcPayload = class _RpcPayload {
|
|
|
489
625
|
ensureDeepCopied() {
|
|
490
626
|
if (this.source !== "owned") {
|
|
491
627
|
let dupStubs = this.source === "params";
|
|
492
|
-
this.
|
|
628
|
+
this.hooks = [];
|
|
493
629
|
this.promises = [];
|
|
494
630
|
try {
|
|
495
631
|
this.value = this.deepCopy(this.value, void 0, "value", this, dupStubs, this);
|
|
496
632
|
} catch (err) {
|
|
497
|
-
this.
|
|
633
|
+
this.hooks = void 0;
|
|
498
634
|
this.promises = void 0;
|
|
499
635
|
throw err;
|
|
500
636
|
}
|
|
@@ -597,7 +733,7 @@ var RpcPayload = class _RpcPayload {
|
|
|
597
733
|
}
|
|
598
734
|
dispose() {
|
|
599
735
|
if (this.source === "owned") {
|
|
600
|
-
this.
|
|
736
|
+
this.hooks.forEach((hook) => hook.dispose());
|
|
601
737
|
this.promises.forEach((promise) => promise.promise[Symbol.dispose]());
|
|
602
738
|
} else if (this.source === "return") {
|
|
603
739
|
this.disposeImpl(this.value, void 0);
|
|
@@ -606,7 +742,7 @@ var RpcPayload = class _RpcPayload {
|
|
|
606
742
|
}
|
|
607
743
|
} else ;
|
|
608
744
|
this.source = "owned";
|
|
609
|
-
this.
|
|
745
|
+
this.hooks = [];
|
|
610
746
|
this.promises = [];
|
|
611
747
|
}
|
|
612
748
|
// Recursive dispose, called only when `source` is "return".
|
|
@@ -659,6 +795,28 @@ var RpcPayload = class _RpcPayload {
|
|
|
659
795
|
}
|
|
660
796
|
case "rpc-thenable":
|
|
661
797
|
return;
|
|
798
|
+
case "writable": {
|
|
799
|
+
let stream = value;
|
|
800
|
+
let hook = this.rpcTargets?.get(stream);
|
|
801
|
+
if (hook) {
|
|
802
|
+
this.rpcTargets.delete(stream);
|
|
803
|
+
} else {
|
|
804
|
+
hook = streamImpl.createWritableStreamHook(stream);
|
|
805
|
+
}
|
|
806
|
+
hook.dispose();
|
|
807
|
+
return;
|
|
808
|
+
}
|
|
809
|
+
case "readable": {
|
|
810
|
+
let stream = value;
|
|
811
|
+
let hook = this.rpcTargets?.get(stream);
|
|
812
|
+
if (hook) {
|
|
813
|
+
this.rpcTargets.delete(stream);
|
|
814
|
+
} else {
|
|
815
|
+
hook = streamImpl.createReadableStreamHook(stream);
|
|
816
|
+
}
|
|
817
|
+
hook.dispose();
|
|
818
|
+
return;
|
|
819
|
+
}
|
|
662
820
|
default:
|
|
663
821
|
return;
|
|
664
822
|
}
|
|
@@ -667,9 +825,9 @@ var RpcPayload = class _RpcPayload {
|
|
|
667
825
|
// *would* be awaited if this payload were to be delivered. See the similarly-named method of
|
|
668
826
|
// StubHook for explanation.
|
|
669
827
|
ignoreUnhandledRejections() {
|
|
670
|
-
if (this.
|
|
671
|
-
this.
|
|
672
|
-
|
|
828
|
+
if (this.hooks) {
|
|
829
|
+
this.hooks.forEach((hook) => {
|
|
830
|
+
hook.ignoreUnhandledRejections();
|
|
673
831
|
});
|
|
674
832
|
this.promises.forEach(
|
|
675
833
|
(promise) => unwrapStubOrParent(promise.promise).ignoreUnhandledRejections()
|
|
@@ -690,6 +848,8 @@ var RpcPayload = class _RpcPayload {
|
|
|
690
848
|
case "undefined":
|
|
691
849
|
case "function":
|
|
692
850
|
case "rpc-target":
|
|
851
|
+
case "writable":
|
|
852
|
+
case "readable":
|
|
693
853
|
return;
|
|
694
854
|
case "array": {
|
|
695
855
|
let array = value;
|
|
@@ -748,7 +908,9 @@ function followPath(value, parent, path, owner) {
|
|
|
748
908
|
case "rpc-target":
|
|
749
909
|
case "rpc-thenable": {
|
|
750
910
|
if (Object.hasOwn(value, part)) {
|
|
751
|
-
|
|
911
|
+
throw new TypeError(
|
|
912
|
+
`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.`
|
|
913
|
+
);
|
|
752
914
|
} else {
|
|
753
915
|
value = value[part];
|
|
754
916
|
}
|
|
@@ -760,6 +922,12 @@ function followPath(value, parent, path, owner) {
|
|
|
760
922
|
let { hook, pathIfPromise } = unwrapStubAndPath(value);
|
|
761
923
|
return { hook, remainingPath: pathIfPromise ? pathIfPromise.concat(path.slice(i)) : path.slice(i) };
|
|
762
924
|
}
|
|
925
|
+
case "writable":
|
|
926
|
+
value = void 0;
|
|
927
|
+
break;
|
|
928
|
+
case "readable":
|
|
929
|
+
value = void 0;
|
|
930
|
+
break;
|
|
763
931
|
case "primitive":
|
|
764
932
|
case "bigint":
|
|
765
933
|
case "bytes":
|
|
@@ -999,6 +1167,14 @@ var PromiseStubHook = class _PromiseStubHook extends StubHook {
|
|
|
999
1167
|
args.ensureDeepCopied();
|
|
1000
1168
|
return new _PromiseStubHook(this.promise.then((hook) => hook.call(path, args)));
|
|
1001
1169
|
}
|
|
1170
|
+
stream(path, args) {
|
|
1171
|
+
args.ensureDeepCopied();
|
|
1172
|
+
let promise = this.promise.then((hook) => {
|
|
1173
|
+
let result = hook.stream(path, args);
|
|
1174
|
+
return result.promise;
|
|
1175
|
+
});
|
|
1176
|
+
return { promise };
|
|
1177
|
+
}
|
|
1002
1178
|
map(path, captures, instructions) {
|
|
1003
1179
|
return new _PromiseStubHook(this.promise.then(
|
|
1004
1180
|
(hook) => hook.map(path, captures, instructions),
|
|
@@ -1071,6 +1247,9 @@ var NullExporter = class {
|
|
|
1071
1247
|
}
|
|
1072
1248
|
unexport(ids) {
|
|
1073
1249
|
}
|
|
1250
|
+
createPipe(readable) {
|
|
1251
|
+
throw new Error("Cannot create pipes without an RPC session.");
|
|
1252
|
+
}
|
|
1074
1253
|
onSendError(error) {
|
|
1075
1254
|
}
|
|
1076
1255
|
};
|
|
@@ -1132,7 +1311,17 @@ var Devaluator = class _Devaluator {
|
|
|
1132
1311
|
throw new TypeError(msg);
|
|
1133
1312
|
}
|
|
1134
1313
|
case "primitive":
|
|
1135
|
-
|
|
1314
|
+
if (typeof value === "number" && !isFinite(value)) {
|
|
1315
|
+
if (value === Infinity) {
|
|
1316
|
+
return ["inf"];
|
|
1317
|
+
} else if (value === -Infinity) {
|
|
1318
|
+
return ["-inf"];
|
|
1319
|
+
} else {
|
|
1320
|
+
return ["nan"];
|
|
1321
|
+
}
|
|
1322
|
+
} else {
|
|
1323
|
+
return value;
|
|
1324
|
+
}
|
|
1136
1325
|
case "object": {
|
|
1137
1326
|
let object = value;
|
|
1138
1327
|
let result = {};
|
|
@@ -1219,6 +1408,22 @@ var Devaluator = class _Devaluator {
|
|
|
1219
1408
|
let hook = this.source.getHookForRpcTarget(value, parent);
|
|
1220
1409
|
return this.devaluateHook("promise", hook);
|
|
1221
1410
|
}
|
|
1411
|
+
case "writable": {
|
|
1412
|
+
if (!this.source) {
|
|
1413
|
+
throw new Error("Can't serialize WritableStream in this context.");
|
|
1414
|
+
}
|
|
1415
|
+
let hook = this.source.getHookForWritableStream(value, parent);
|
|
1416
|
+
return this.devaluateHook("writable", hook);
|
|
1417
|
+
}
|
|
1418
|
+
case "readable": {
|
|
1419
|
+
if (!this.source) {
|
|
1420
|
+
throw new Error("Can't serialize ReadableStream in this context.");
|
|
1421
|
+
}
|
|
1422
|
+
let ws = value;
|
|
1423
|
+
let hook = this.source.getHookForReadableStream(ws, parent);
|
|
1424
|
+
let importId = this.exporter.createPipe(ws, hook);
|
|
1425
|
+
return ["readable", importId];
|
|
1426
|
+
}
|
|
1222
1427
|
default:
|
|
1223
1428
|
throw new Error("unreachable");
|
|
1224
1429
|
}
|
|
@@ -1243,16 +1448,19 @@ var NullImporter = class {
|
|
|
1243
1448
|
getExport(idx) {
|
|
1244
1449
|
return void 0;
|
|
1245
1450
|
}
|
|
1451
|
+
getPipeReadable(exportId) {
|
|
1452
|
+
throw new Error("Cannot retrieve pipe readable without an RPC session.");
|
|
1453
|
+
}
|
|
1246
1454
|
};
|
|
1247
1455
|
var NULL_IMPORTER = new NullImporter();
|
|
1248
1456
|
var Evaluator = class _Evaluator {
|
|
1249
1457
|
constructor(importer) {
|
|
1250
1458
|
this.importer = importer;
|
|
1251
1459
|
}
|
|
1252
|
-
|
|
1460
|
+
hooks = [];
|
|
1253
1461
|
promises = [];
|
|
1254
1462
|
evaluate(value) {
|
|
1255
|
-
let payload = RpcPayload.forEvaluate(this.
|
|
1463
|
+
let payload = RpcPayload.forEvaluate(this.hooks, this.promises);
|
|
1256
1464
|
try {
|
|
1257
1465
|
payload.value = this.evaluateImpl(value, payload, "value");
|
|
1258
1466
|
return payload;
|
|
@@ -1316,6 +1524,12 @@ var Evaluator = class _Evaluator {
|
|
|
1316
1524
|
return void 0;
|
|
1317
1525
|
}
|
|
1318
1526
|
break;
|
|
1527
|
+
case "inf":
|
|
1528
|
+
return Infinity;
|
|
1529
|
+
case "-inf":
|
|
1530
|
+
return -Infinity;
|
|
1531
|
+
case "nan":
|
|
1532
|
+
return NaN;
|
|
1319
1533
|
case "import":
|
|
1320
1534
|
case "pipeline": {
|
|
1321
1535
|
if (value.length < 2 || value.length > 4) {
|
|
@@ -1335,9 +1549,8 @@ var Evaluator = class _Evaluator {
|
|
|
1335
1549
|
this.promises.push({ promise, parent, property });
|
|
1336
1550
|
return promise;
|
|
1337
1551
|
} else {
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
return stub;
|
|
1552
|
+
this.hooks.push(hook2);
|
|
1553
|
+
return new RpcPromise(hook2, []);
|
|
1341
1554
|
}
|
|
1342
1555
|
};
|
|
1343
1556
|
if (value.length == 2) {
|
|
@@ -1415,12 +1628,27 @@ var Evaluator = class _Evaluator {
|
|
|
1415
1628
|
return promise;
|
|
1416
1629
|
} else {
|
|
1417
1630
|
let hook = this.importer.importStub(value[1]);
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
return stub;
|
|
1631
|
+
this.hooks.push(hook);
|
|
1632
|
+
return new RpcStub(hook);
|
|
1421
1633
|
}
|
|
1422
1634
|
}
|
|
1423
1635
|
break;
|
|
1636
|
+
case "writable":
|
|
1637
|
+
if (typeof value[1] == "number") {
|
|
1638
|
+
let hook = this.importer.importStub(value[1]);
|
|
1639
|
+
let stream = streamImpl.createWritableStreamFromHook(hook);
|
|
1640
|
+
this.hooks.push(hook);
|
|
1641
|
+
return stream;
|
|
1642
|
+
}
|
|
1643
|
+
break;
|
|
1644
|
+
case "readable":
|
|
1645
|
+
if (typeof value[1] == "number") {
|
|
1646
|
+
let stream = this.importer.getPipeReadable(value[1]);
|
|
1647
|
+
let hook = streamImpl.createReadableStreamHook(stream);
|
|
1648
|
+
this.hooks.push(hook);
|
|
1649
|
+
return stream;
|
|
1650
|
+
}
|
|
1651
|
+
break;
|
|
1424
1652
|
}
|
|
1425
1653
|
throw new TypeError(`unknown special value: ${JSON.stringify(value)}`);
|
|
1426
1654
|
} else if (value instanceof Object) {
|
|
@@ -1560,6 +1788,14 @@ var RpcImportHook = class _RpcImportHook extends StubHook {
|
|
|
1560
1788
|
return entry.session.sendCall(entry.importId, path, args);
|
|
1561
1789
|
}
|
|
1562
1790
|
}
|
|
1791
|
+
stream(path, args) {
|
|
1792
|
+
let entry = this.getEntry();
|
|
1793
|
+
if (entry.resolution) {
|
|
1794
|
+
return entry.resolution.stream(path, args);
|
|
1795
|
+
} else {
|
|
1796
|
+
return entry.session.sendStream(entry.importId, path, args);
|
|
1797
|
+
}
|
|
1798
|
+
}
|
|
1563
1799
|
map(path, captures, instructions) {
|
|
1564
1800
|
let entry;
|
|
1565
1801
|
try {
|
|
@@ -1732,19 +1968,23 @@ var RpcSessionImpl = class {
|
|
|
1732
1968
|
return payload;
|
|
1733
1969
|
}
|
|
1734
1970
|
};
|
|
1971
|
+
let autoRelease = exp.autoRelease;
|
|
1735
1972
|
++this.pullCount;
|
|
1736
1973
|
exp.pull = resolve().then(
|
|
1737
1974
|
(payload) => {
|
|
1738
1975
|
let value = Devaluator.devaluate(payload.value, void 0, this, payload);
|
|
1739
1976
|
this.send(["resolve", exportId, value]);
|
|
1977
|
+
if (autoRelease) this.releaseExport(exportId, 1);
|
|
1740
1978
|
},
|
|
1741
1979
|
(error) => {
|
|
1742
1980
|
this.send(["reject", exportId, Devaluator.devaluate(error, void 0, this)]);
|
|
1981
|
+
if (autoRelease) this.releaseExport(exportId, 1);
|
|
1743
1982
|
}
|
|
1744
1983
|
).catch(
|
|
1745
1984
|
(error) => {
|
|
1746
1985
|
try {
|
|
1747
1986
|
this.send(["reject", exportId, Devaluator.devaluate(error, void 0, this)]);
|
|
1987
|
+
if (autoRelease) this.releaseExport(exportId, 1);
|
|
1748
1988
|
} catch (error2) {
|
|
1749
1989
|
this.abort(error2);
|
|
1750
1990
|
}
|
|
@@ -1796,9 +2036,35 @@ var RpcSessionImpl = class {
|
|
|
1796
2036
|
getExport(idx) {
|
|
1797
2037
|
return this.exports[idx]?.hook;
|
|
1798
2038
|
}
|
|
2039
|
+
getPipeReadable(exportId) {
|
|
2040
|
+
let entry = this.exports[exportId];
|
|
2041
|
+
if (!entry || !entry.pipeReadable) {
|
|
2042
|
+
throw new Error(`Export ${exportId} is not a pipe or its readable end was already consumed.`);
|
|
2043
|
+
}
|
|
2044
|
+
let readable = entry.pipeReadable;
|
|
2045
|
+
entry.pipeReadable = void 0;
|
|
2046
|
+
return readable;
|
|
2047
|
+
}
|
|
2048
|
+
createPipe(readable, readableHook) {
|
|
2049
|
+
if (this.abortReason) throw this.abortReason;
|
|
2050
|
+
this.send(["pipe"]);
|
|
2051
|
+
let importId = this.imports.length;
|
|
2052
|
+
let entry = new ImportTableEntry(this, importId, false);
|
|
2053
|
+
this.imports.push(entry);
|
|
2054
|
+
let hook = new RpcImportHook(
|
|
2055
|
+
/*isPromise=*/
|
|
2056
|
+
false,
|
|
2057
|
+
entry
|
|
2058
|
+
);
|
|
2059
|
+
let writable = streamImpl.createWritableStreamFromHook(hook);
|
|
2060
|
+
readable.pipeTo(writable).catch(() => {
|
|
2061
|
+
}).finally(() => readableHook.dispose());
|
|
2062
|
+
return importId;
|
|
2063
|
+
}
|
|
2064
|
+
// Serializes and sends a message. Returns the byte length of the serialized message.
|
|
1799
2065
|
send(msg) {
|
|
1800
2066
|
if (this.abortReason !== void 0) {
|
|
1801
|
-
return;
|
|
2067
|
+
return 0;
|
|
1802
2068
|
}
|
|
1803
2069
|
let msgText;
|
|
1804
2070
|
try {
|
|
@@ -1811,6 +2077,7 @@ var RpcSessionImpl = class {
|
|
|
1811
2077
|
throw err;
|
|
1812
2078
|
}
|
|
1813
2079
|
this.transport.send(msgText).catch((err) => this.abort(err, false));
|
|
2080
|
+
return msgText.length;
|
|
1814
2081
|
}
|
|
1815
2082
|
sendCall(id, path, args) {
|
|
1816
2083
|
if (this.abortReason) throw this.abortReason;
|
|
@@ -1828,6 +2095,34 @@ var RpcSessionImpl = class {
|
|
|
1828
2095
|
entry
|
|
1829
2096
|
);
|
|
1830
2097
|
}
|
|
2098
|
+
sendStream(id, path, args) {
|
|
2099
|
+
if (this.abortReason) throw this.abortReason;
|
|
2100
|
+
let value = ["pipeline", id, path];
|
|
2101
|
+
let devalue = Devaluator.devaluate(args.value, void 0, this, args);
|
|
2102
|
+
value.push(devalue[0]);
|
|
2103
|
+
let size = this.send(["stream", value]);
|
|
2104
|
+
let importId = this.imports.length;
|
|
2105
|
+
let entry = new ImportTableEntry(
|
|
2106
|
+
this,
|
|
2107
|
+
importId,
|
|
2108
|
+
/*pulling=*/
|
|
2109
|
+
true
|
|
2110
|
+
);
|
|
2111
|
+
entry.remoteRefcount = 0;
|
|
2112
|
+
entry.localRefcount = 1;
|
|
2113
|
+
this.imports.push(entry);
|
|
2114
|
+
let promise = entry.awaitResolution().then(
|
|
2115
|
+
(p) => {
|
|
2116
|
+
p.dispose();
|
|
2117
|
+
delete this.imports[importId];
|
|
2118
|
+
},
|
|
2119
|
+
(err) => {
|
|
2120
|
+
delete this.imports[importId];
|
|
2121
|
+
throw err;
|
|
2122
|
+
}
|
|
2123
|
+
);
|
|
2124
|
+
return { promise, size };
|
|
2125
|
+
}
|
|
1831
2126
|
sendMap(id, path, captures, instructions) {
|
|
1832
2127
|
if (this.abortReason) {
|
|
1833
2128
|
for (let cap of captures) {
|
|
@@ -1915,6 +2210,24 @@ var RpcSessionImpl = class {
|
|
|
1915
2210
|
continue;
|
|
1916
2211
|
}
|
|
1917
2212
|
break;
|
|
2213
|
+
case "stream": {
|
|
2214
|
+
if (msg.length > 1) {
|
|
2215
|
+
let payload = new Evaluator(this).evaluate(msg[1]);
|
|
2216
|
+
let hook = new PayloadStubHook(payload);
|
|
2217
|
+
hook.ignoreUnhandledRejections();
|
|
2218
|
+
let exportId = this.exports.length;
|
|
2219
|
+
this.exports.push({ hook, refcount: 1, autoRelease: true });
|
|
2220
|
+
this.ensureResolvingExport(exportId);
|
|
2221
|
+
continue;
|
|
2222
|
+
}
|
|
2223
|
+
break;
|
|
2224
|
+
}
|
|
2225
|
+
case "pipe": {
|
|
2226
|
+
let { readable, writable } = new TransformStream();
|
|
2227
|
+
let hook = streamImpl.createWritableStreamHook(writable);
|
|
2228
|
+
this.exports.push({ hook, refcount: 1, pipeReadable: readable });
|
|
2229
|
+
continue;
|
|
2230
|
+
}
|
|
1918
2231
|
case "pull": {
|
|
1919
2232
|
let exportId = msg[1];
|
|
1920
2233
|
if (typeof exportId == "number") {
|
|
@@ -2410,6 +2723,9 @@ var MapBuilder = class {
|
|
|
2410
2723
|
}
|
|
2411
2724
|
unexport(ids) {
|
|
2412
2725
|
}
|
|
2726
|
+
createPipe(readable) {
|
|
2727
|
+
throw new Error("Cannot send ReadableStream inside a mapper function.");
|
|
2728
|
+
}
|
|
2413
2729
|
onSendError(error) {
|
|
2414
2730
|
}
|
|
2415
2731
|
};
|
|
@@ -2519,6 +2835,9 @@ var MapApplicator = class {
|
|
|
2519
2835
|
return this.variables[idx];
|
|
2520
2836
|
}
|
|
2521
2837
|
}
|
|
2838
|
+
getPipeReadable(exportId) {
|
|
2839
|
+
throw new Error("A mapper function cannot use pipe readables.");
|
|
2840
|
+
}
|
|
2522
2841
|
};
|
|
2523
2842
|
function applyMapToElement(input, parent, owner, captures, instructions) {
|
|
2524
2843
|
let inputHook = new PayloadStubHook(RpcPayload.deepCopyFrom(input, parent, owner));
|
|
@@ -2559,6 +2878,333 @@ mapImpl.applyMap = (input, parent, owner, captures, instructions) => {
|
|
|
2559
2878
|
}
|
|
2560
2879
|
}
|
|
2561
2880
|
};
|
|
2881
|
+
|
|
2882
|
+
// src/streams.ts
|
|
2883
|
+
var WritableStreamStubHook = class _WritableStreamStubHook extends StubHook {
|
|
2884
|
+
state;
|
|
2885
|
+
// undefined when disposed
|
|
2886
|
+
// Creates a new WritableStreamStubHook that is not duplicated from an existing hook.
|
|
2887
|
+
static create(stream) {
|
|
2888
|
+
let writer = stream.getWriter();
|
|
2889
|
+
return new _WritableStreamStubHook({ refcount: 1, writer, closed: false });
|
|
2890
|
+
}
|
|
2891
|
+
constructor(state, dupFrom) {
|
|
2892
|
+
super();
|
|
2893
|
+
this.state = state;
|
|
2894
|
+
if (dupFrom) {
|
|
2895
|
+
++state.refcount;
|
|
2896
|
+
}
|
|
2897
|
+
}
|
|
2898
|
+
getState() {
|
|
2899
|
+
if (this.state) {
|
|
2900
|
+
return this.state;
|
|
2901
|
+
} else {
|
|
2902
|
+
throw new Error("Attempted to use a WritableStreamStubHook after it was disposed.");
|
|
2903
|
+
}
|
|
2904
|
+
}
|
|
2905
|
+
call(path, args) {
|
|
2906
|
+
try {
|
|
2907
|
+
let state = this.getState();
|
|
2908
|
+
if (path.length !== 1 || typeof path[0] !== "string") {
|
|
2909
|
+
throw new Error("WritableStream stub only supports direct method calls");
|
|
2910
|
+
}
|
|
2911
|
+
const method = path[0];
|
|
2912
|
+
if (method !== "write" && method !== "close" && method !== "abort") {
|
|
2913
|
+
args.dispose();
|
|
2914
|
+
throw new Error(`Unknown WritableStream method: ${method}`);
|
|
2915
|
+
}
|
|
2916
|
+
if (method === "close" || method === "abort") {
|
|
2917
|
+
state.closed = true;
|
|
2918
|
+
}
|
|
2919
|
+
let func = state.writer[method];
|
|
2920
|
+
let promise = args.deliverCall(func, state.writer);
|
|
2921
|
+
return new PromiseStubHook(promise.then((payload) => new PayloadStubHook(payload)));
|
|
2922
|
+
} catch (err) {
|
|
2923
|
+
return new ErrorStubHook(err);
|
|
2924
|
+
}
|
|
2925
|
+
}
|
|
2926
|
+
map(path, captures, instructions) {
|
|
2927
|
+
for (let cap of captures) {
|
|
2928
|
+
cap.dispose();
|
|
2929
|
+
}
|
|
2930
|
+
return new ErrorStubHook(new Error("Cannot use map() on a WritableStream"));
|
|
2931
|
+
}
|
|
2932
|
+
get(path) {
|
|
2933
|
+
return new ErrorStubHook(new Error("Cannot access properties on a WritableStream stub"));
|
|
2934
|
+
}
|
|
2935
|
+
dup() {
|
|
2936
|
+
let state = this.getState();
|
|
2937
|
+
return new _WritableStreamStubHook(state, this);
|
|
2938
|
+
}
|
|
2939
|
+
pull() {
|
|
2940
|
+
return Promise.reject(new Error("Cannot pull a WritableStream stub"));
|
|
2941
|
+
}
|
|
2942
|
+
ignoreUnhandledRejections() {
|
|
2943
|
+
}
|
|
2944
|
+
dispose() {
|
|
2945
|
+
let state = this.state;
|
|
2946
|
+
this.state = void 0;
|
|
2947
|
+
if (state) {
|
|
2948
|
+
if (--state.refcount === 0) {
|
|
2949
|
+
if (!state.closed) {
|
|
2950
|
+
state.writer.abort(new Error("WritableStream RPC stub was disposed without calling close()")).catch(() => {
|
|
2951
|
+
});
|
|
2952
|
+
}
|
|
2953
|
+
state.writer.releaseLock();
|
|
2954
|
+
}
|
|
2955
|
+
}
|
|
2956
|
+
}
|
|
2957
|
+
onBroken(callback) {
|
|
2958
|
+
}
|
|
2959
|
+
};
|
|
2960
|
+
var INITIAL_WINDOW = 256 * 1024;
|
|
2961
|
+
var MAX_WINDOW = 1024 * 1024 * 1024;
|
|
2962
|
+
var MIN_WINDOW = 64 * 1024;
|
|
2963
|
+
var STARTUP_GROWTH_FACTOR = 2;
|
|
2964
|
+
var STEADY_GROWTH_FACTOR = 1.25;
|
|
2965
|
+
var DECAY_FACTOR = 0.9;
|
|
2966
|
+
var STARTUP_EXIT_ROUNDS = 3;
|
|
2967
|
+
var FlowController = class {
|
|
2968
|
+
constructor(now) {
|
|
2969
|
+
this.now = now;
|
|
2970
|
+
}
|
|
2971
|
+
// The current window size in bytes. The sender blocks when bytesInFlight >= window.
|
|
2972
|
+
window = INITIAL_WINDOW;
|
|
2973
|
+
// Total bytes currently in flight (sent but not yet acked).
|
|
2974
|
+
bytesInFlight = 0;
|
|
2975
|
+
// Whether we're still in the startup phase.
|
|
2976
|
+
inStartupPhase = true;
|
|
2977
|
+
// ----- BDP estimation state (private) -----
|
|
2978
|
+
// Total bytes acked so far.
|
|
2979
|
+
delivered = 0;
|
|
2980
|
+
// Time of most recent ack.
|
|
2981
|
+
deliveredTime = 0;
|
|
2982
|
+
// Time when the very first ack was received.
|
|
2983
|
+
firstAckTime = 0;
|
|
2984
|
+
firstAckDelivered = 0;
|
|
2985
|
+
// Global minimum RTT observed (milliseconds).
|
|
2986
|
+
minRtt = Infinity;
|
|
2987
|
+
// For startup exit: count of consecutive RTT rounds where the window didn't meaningfully grow.
|
|
2988
|
+
roundsWithoutIncrease = 0;
|
|
2989
|
+
// Window size at the start of the current round, for startup exit detection.
|
|
2990
|
+
lastRoundWindow = 0;
|
|
2991
|
+
// Time when the current round started.
|
|
2992
|
+
roundStartTime = 0;
|
|
2993
|
+
// Called when a write of `size` bytes is about to be sent. Returns a token that must be
|
|
2994
|
+
// passed to onAck() when the ack arrives, and whether the sender should block (window full).
|
|
2995
|
+
onSend(size) {
|
|
2996
|
+
this.bytesInFlight += size;
|
|
2997
|
+
let token = {
|
|
2998
|
+
sentTime: this.now(),
|
|
2999
|
+
size,
|
|
3000
|
+
deliveredAtSend: this.delivered,
|
|
3001
|
+
deliveredTimeAtSend: this.deliveredTime,
|
|
3002
|
+
windowAtSend: this.window,
|
|
3003
|
+
windowFullAtSend: this.bytesInFlight >= this.window
|
|
3004
|
+
};
|
|
3005
|
+
return { token, shouldBlock: token.windowFullAtSend };
|
|
3006
|
+
}
|
|
3007
|
+
// Called when a previously-sent write fails. Restores bytesInFlight without updating
|
|
3008
|
+
// any BDP estimates.
|
|
3009
|
+
onError(token) {
|
|
3010
|
+
this.bytesInFlight -= token.size;
|
|
3011
|
+
}
|
|
3012
|
+
// Called when an ack is received for a previously-sent write. Updates BDP estimates and
|
|
3013
|
+
// the window. Returns whether a blocked sender should now unblock.
|
|
3014
|
+
onAck(token) {
|
|
3015
|
+
let ackTime = this.now();
|
|
3016
|
+
this.delivered += token.size;
|
|
3017
|
+
this.deliveredTime = ackTime;
|
|
3018
|
+
this.bytesInFlight -= token.size;
|
|
3019
|
+
let rtt = ackTime - token.sentTime;
|
|
3020
|
+
this.minRtt = Math.min(this.minRtt, rtt);
|
|
3021
|
+
if (this.firstAckTime === 0) {
|
|
3022
|
+
this.firstAckTime = ackTime;
|
|
3023
|
+
this.firstAckDelivered = this.delivered;
|
|
3024
|
+
} else {
|
|
3025
|
+
let baseTime;
|
|
3026
|
+
let baseDelivered;
|
|
3027
|
+
if (token.deliveredTimeAtSend === 0) {
|
|
3028
|
+
baseTime = this.firstAckTime;
|
|
3029
|
+
baseDelivered = this.firstAckDelivered;
|
|
3030
|
+
} else {
|
|
3031
|
+
baseTime = token.deliveredTimeAtSend;
|
|
3032
|
+
baseDelivered = token.deliveredAtSend;
|
|
3033
|
+
}
|
|
3034
|
+
let interval = ackTime - baseTime;
|
|
3035
|
+
let bytes = this.delivered - baseDelivered;
|
|
3036
|
+
let bandwidth = bytes / interval;
|
|
3037
|
+
let growthFactor = this.inStartupPhase ? STARTUP_GROWTH_FACTOR : STEADY_GROWTH_FACTOR;
|
|
3038
|
+
let newWindow = bandwidth * this.minRtt * growthFactor;
|
|
3039
|
+
newWindow = Math.min(newWindow, token.windowAtSend * growthFactor);
|
|
3040
|
+
if (token.windowFullAtSend) {
|
|
3041
|
+
newWindow = Math.max(newWindow, token.windowAtSend * DECAY_FACTOR);
|
|
3042
|
+
} else {
|
|
3043
|
+
newWindow = Math.max(newWindow, this.window);
|
|
3044
|
+
}
|
|
3045
|
+
this.window = Math.max(Math.min(newWindow, MAX_WINDOW), MIN_WINDOW);
|
|
3046
|
+
if (this.inStartupPhase && token.sentTime >= this.roundStartTime) {
|
|
3047
|
+
if (this.window > this.lastRoundWindow * STEADY_GROWTH_FACTOR) {
|
|
3048
|
+
this.roundsWithoutIncrease = 0;
|
|
3049
|
+
} else {
|
|
3050
|
+
if (++this.roundsWithoutIncrease >= STARTUP_EXIT_ROUNDS) {
|
|
3051
|
+
this.inStartupPhase = false;
|
|
3052
|
+
}
|
|
3053
|
+
}
|
|
3054
|
+
this.roundStartTime = ackTime;
|
|
3055
|
+
this.lastRoundWindow = this.window;
|
|
3056
|
+
}
|
|
3057
|
+
}
|
|
3058
|
+
return this.bytesInFlight < this.window;
|
|
3059
|
+
}
|
|
3060
|
+
};
|
|
3061
|
+
function createWritableStreamFromHook(hook) {
|
|
3062
|
+
let pendingError = void 0;
|
|
3063
|
+
let hookDisposed = false;
|
|
3064
|
+
let fc = new FlowController(() => performance.now());
|
|
3065
|
+
let windowResolve;
|
|
3066
|
+
let windowReject;
|
|
3067
|
+
const disposeHook = () => {
|
|
3068
|
+
if (!hookDisposed) {
|
|
3069
|
+
hookDisposed = true;
|
|
3070
|
+
hook.dispose();
|
|
3071
|
+
}
|
|
3072
|
+
};
|
|
3073
|
+
return new WritableStream({
|
|
3074
|
+
write(chunk, controller) {
|
|
3075
|
+
if (pendingError !== void 0) {
|
|
3076
|
+
throw pendingError;
|
|
3077
|
+
}
|
|
3078
|
+
const payload = RpcPayload.fromAppParams([chunk]);
|
|
3079
|
+
const { promise, size } = hook.stream(["write"], payload);
|
|
3080
|
+
if (size === void 0) {
|
|
3081
|
+
return promise.catch((err) => {
|
|
3082
|
+
if (pendingError === void 0) {
|
|
3083
|
+
pendingError = err;
|
|
3084
|
+
}
|
|
3085
|
+
throw err;
|
|
3086
|
+
});
|
|
3087
|
+
} else {
|
|
3088
|
+
let { token, shouldBlock } = fc.onSend(size);
|
|
3089
|
+
promise.then(() => {
|
|
3090
|
+
let hasCapacity = fc.onAck(token);
|
|
3091
|
+
if (hasCapacity && windowResolve) {
|
|
3092
|
+
windowResolve();
|
|
3093
|
+
windowResolve = void 0;
|
|
3094
|
+
windowReject = void 0;
|
|
3095
|
+
}
|
|
3096
|
+
}, (err) => {
|
|
3097
|
+
fc.onError(token);
|
|
3098
|
+
if (pendingError === void 0) {
|
|
3099
|
+
pendingError = err;
|
|
3100
|
+
controller.error(err);
|
|
3101
|
+
disposeHook();
|
|
3102
|
+
}
|
|
3103
|
+
if (windowReject) {
|
|
3104
|
+
windowReject(err);
|
|
3105
|
+
windowResolve = void 0;
|
|
3106
|
+
windowReject = void 0;
|
|
3107
|
+
}
|
|
3108
|
+
});
|
|
3109
|
+
if (shouldBlock) {
|
|
3110
|
+
return new Promise((resolve, reject) => {
|
|
3111
|
+
windowResolve = resolve;
|
|
3112
|
+
windowReject = reject;
|
|
3113
|
+
});
|
|
3114
|
+
}
|
|
3115
|
+
}
|
|
3116
|
+
},
|
|
3117
|
+
async close() {
|
|
3118
|
+
if (pendingError !== void 0) {
|
|
3119
|
+
disposeHook();
|
|
3120
|
+
throw pendingError;
|
|
3121
|
+
}
|
|
3122
|
+
const { promise } = hook.stream(["close"], RpcPayload.fromAppParams([]));
|
|
3123
|
+
try {
|
|
3124
|
+
await promise;
|
|
3125
|
+
} catch (err) {
|
|
3126
|
+
throw pendingError ?? err;
|
|
3127
|
+
} finally {
|
|
3128
|
+
disposeHook();
|
|
3129
|
+
}
|
|
3130
|
+
},
|
|
3131
|
+
abort(reason) {
|
|
3132
|
+
if (pendingError !== void 0) {
|
|
3133
|
+
return;
|
|
3134
|
+
}
|
|
3135
|
+
pendingError = reason ?? new Error("WritableStream was aborted");
|
|
3136
|
+
if (windowReject) {
|
|
3137
|
+
windowReject(pendingError);
|
|
3138
|
+
windowResolve = void 0;
|
|
3139
|
+
windowReject = void 0;
|
|
3140
|
+
}
|
|
3141
|
+
const { promise } = hook.stream(["abort"], RpcPayload.fromAppParams([reason]));
|
|
3142
|
+
promise.then(() => disposeHook(), () => disposeHook());
|
|
3143
|
+
}
|
|
3144
|
+
});
|
|
3145
|
+
}
|
|
3146
|
+
var ReadableStreamStubHook = class _ReadableStreamStubHook extends StubHook {
|
|
3147
|
+
state;
|
|
3148
|
+
// undefined when disposed
|
|
3149
|
+
// Creates a new ReadableStreamStubHook.
|
|
3150
|
+
static create(stream) {
|
|
3151
|
+
return new _ReadableStreamStubHook({ refcount: 1, stream, canceled: false });
|
|
3152
|
+
}
|
|
3153
|
+
constructor(state, dupFrom) {
|
|
3154
|
+
super();
|
|
3155
|
+
this.state = state;
|
|
3156
|
+
if (dupFrom) {
|
|
3157
|
+
++state.refcount;
|
|
3158
|
+
}
|
|
3159
|
+
}
|
|
3160
|
+
call(path, args) {
|
|
3161
|
+
args.dispose();
|
|
3162
|
+
return new ErrorStubHook(new Error("Cannot call methods on a ReadableStream stub"));
|
|
3163
|
+
}
|
|
3164
|
+
map(path, captures, instructions) {
|
|
3165
|
+
for (let cap of captures) {
|
|
3166
|
+
cap.dispose();
|
|
3167
|
+
}
|
|
3168
|
+
return new ErrorStubHook(new Error("Cannot use map() on a ReadableStream"));
|
|
3169
|
+
}
|
|
3170
|
+
get(path) {
|
|
3171
|
+
return new ErrorStubHook(new Error("Cannot access properties on a ReadableStream stub"));
|
|
3172
|
+
}
|
|
3173
|
+
dup() {
|
|
3174
|
+
let state = this.state;
|
|
3175
|
+
if (!state) {
|
|
3176
|
+
throw new Error("Attempted to dup a ReadableStreamStubHook after it was disposed.");
|
|
3177
|
+
}
|
|
3178
|
+
return new _ReadableStreamStubHook(state, this);
|
|
3179
|
+
}
|
|
3180
|
+
pull() {
|
|
3181
|
+
return Promise.reject(new Error("Cannot pull a ReadableStream stub"));
|
|
3182
|
+
}
|
|
3183
|
+
ignoreUnhandledRejections() {
|
|
3184
|
+
}
|
|
3185
|
+
dispose() {
|
|
3186
|
+
let state = this.state;
|
|
3187
|
+
this.state = void 0;
|
|
3188
|
+
if (state) {
|
|
3189
|
+
if (--state.refcount === 0) {
|
|
3190
|
+
if (!state.canceled) {
|
|
3191
|
+
state.canceled = true;
|
|
3192
|
+
if (!state.stream.locked) {
|
|
3193
|
+
state.stream.cancel(
|
|
3194
|
+
new Error("ReadableStream RPC stub was disposed without being consumed")
|
|
3195
|
+
).catch(() => {
|
|
3196
|
+
});
|
|
3197
|
+
}
|
|
3198
|
+
}
|
|
3199
|
+
}
|
|
3200
|
+
}
|
|
3201
|
+
}
|
|
3202
|
+
onBroken(callback) {
|
|
3203
|
+
}
|
|
3204
|
+
};
|
|
3205
|
+
streamImpl.createWritableStreamHook = WritableStreamStubHook.create;
|
|
3206
|
+
streamImpl.createWritableStreamFromHook = createWritableStreamFromHook;
|
|
3207
|
+
streamImpl.createReadableStreamHook = ReadableStreamStubHook.create;
|
|
2562
3208
|
var RpcStub2 = RpcStub;
|
|
2563
3209
|
var RpcPromise2 = RpcPromise;
|
|
2564
3210
|
var RpcSession2 = RpcSession;
|