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