@yume-chan/stream-extra 0.0.20 → 0.0.22
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.json +18 -0
- package/CHANGELOG.md +13 -1
- package/esm/buffered-transform.d.ts.map +1 -1
- package/esm/buffered-transform.js.map +1 -1
- package/esm/buffered.d.ts +0 -2
- package/esm/buffered.d.ts.map +1 -1
- package/esm/buffered.js +28 -21
- package/esm/buffered.js.map +1 -1
- package/esm/concat.d.ts +35 -0
- package/esm/concat.d.ts.map +1 -0
- package/esm/concat.js +128 -0
- package/esm/concat.js.map +1 -0
- package/esm/consumable.d.ts +3 -3
- package/esm/consumable.d.ts.map +1 -1
- package/esm/consumable.js +4 -4
- package/esm/consumable.js.map +1 -1
- package/esm/distribution.d.ts.map +1 -1
- package/esm/distribution.js.map +1 -1
- package/esm/duplex.d.ts +2 -2
- package/esm/duplex.d.ts.map +1 -1
- package/esm/duplex.js +2 -2
- package/esm/duplex.js.map +1 -1
- package/esm/index.d.ts +1 -1
- package/esm/index.d.ts.map +1 -1
- package/esm/index.js +1 -1
- package/esm/index.js.map +1 -1
- package/esm/push-readable.d.ts +1 -0
- package/esm/push-readable.d.ts.map +1 -1
- package/esm/push-readable.js +24 -10
- package/esm/push-readable.js.map +1 -1
- package/esm/split-string.d.ts.map +1 -1
- package/esm/split-string.js.map +1 -1
- package/esm/stream.js +0 -14
- package/esm/stream.js.map +1 -1
- package/esm/struct-deserialize.d.ts.map +1 -1
- package/esm/struct-deserialize.js.map +1 -1
- package/esm/wrap-readable.d.ts +2 -2
- package/esm/wrap-readable.d.ts.map +1 -1
- package/esm/wrap-readable.js +8 -8
- package/esm/wrap-readable.js.map +1 -1
- package/esm/wrap-writable.d.ts.map +1 -1
- package/esm/wrap-writable.js.map +1 -1
- package/package.json +9 -9
- package/src/buffered-transform.ts +4 -4
- package/src/buffered.ts +32 -25
- package/src/concat.ts +160 -0
- package/src/consumable.ts +45 -33
- package/src/decode-utf8.ts +1 -1
- package/src/distribution.ts +5 -5
- package/src/duplex.ts +27 -20
- package/src/index.ts +1 -1
- package/src/pipe-from.ts +1 -1
- package/src/push-readable.ts +33 -17
- package/src/split-string.ts +2 -2
- package/src/stream.ts +0 -13
- package/src/struct-deserialize.ts +2 -2
- package/src/struct-serialize.ts +1 -1
- package/src/wrap-readable.ts +39 -34
- package/src/wrap-writable.ts +5 -5
- package/tsconfig.build.tsbuildinfo +1 -1
- package/esm/gather-string.d.ts +0 -7
- package/esm/gather-string.d.ts.map +0 -1
- package/esm/gather-string.js +0 -16
- package/esm/gather-string.js.map +0 -1
- package/src/gather-string.ts +0 -17
package/esm/push-readable.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { PromiseResolver } from "@yume-chan/async";
|
|
2
2
|
import { AbortController, ReadableStream } from "./stream.js";
|
|
3
3
|
export class PushReadableStream extends ReadableStream {
|
|
4
|
+
#zeroHighWaterMarkAllowEnqueue = false;
|
|
4
5
|
/**
|
|
5
6
|
* Create a new `PushReadableStream` from a source.
|
|
6
7
|
*
|
|
@@ -12,21 +13,28 @@ export class PushReadableStream extends ReadableStream {
|
|
|
12
13
|
let waterMarkLow;
|
|
13
14
|
const abortController = new AbortController();
|
|
14
15
|
super({
|
|
15
|
-
start: (controller) => {
|
|
16
|
+
start: async (controller) => {
|
|
17
|
+
await Promise.resolve();
|
|
16
18
|
const result = source({
|
|
17
19
|
abortSignal: abortController.signal,
|
|
18
|
-
async
|
|
20
|
+
enqueue: async (chunk) => {
|
|
19
21
|
if (abortController.signal.aborted) {
|
|
20
22
|
// If the stream is already cancelled,
|
|
21
23
|
// throw immediately.
|
|
22
|
-
throw
|
|
23
|
-
new Error("Aborted"));
|
|
24
|
+
throw abortController.signal.reason;
|
|
24
25
|
}
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
26
|
+
if (controller.desiredSize === null) {
|
|
27
|
+
// `desiredSize` being `null` means the stream is in error state,
|
|
28
|
+
// `controller.enqueue` will throw an error for us.
|
|
29
|
+
controller.enqueue(chunk);
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
if (this.#zeroHighWaterMarkAllowEnqueue) {
|
|
33
|
+
this.#zeroHighWaterMarkAllowEnqueue = false;
|
|
34
|
+
controller.enqueue(chunk);
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
if (controller.desiredSize <= 0) {
|
|
30
38
|
waterMarkLow = new PromiseResolver();
|
|
31
39
|
await waterMarkLow.promise;
|
|
32
40
|
}
|
|
@@ -55,7 +63,13 @@ export class PushReadableStream extends ReadableStream {
|
|
|
55
63
|
}
|
|
56
64
|
},
|
|
57
65
|
pull: () => {
|
|
58
|
-
waterMarkLow
|
|
66
|
+
if (waterMarkLow) {
|
|
67
|
+
waterMarkLow.resolve();
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
if (strategy?.highWaterMark === 0) {
|
|
71
|
+
this.#zeroHighWaterMarkAllowEnqueue = true;
|
|
72
|
+
}
|
|
59
73
|
},
|
|
60
74
|
cancel: (reason) => {
|
|
61
75
|
abortController.abort(reason);
|
package/esm/push-readable.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"push-readable.js","sourceRoot":"","sources":["../src/push-readable.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAGnD,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAgB9D,MAAM,OAAO,kBAAsB,SAAQ,cAAiB;IACxD;;;;;;OAMG;IACH,YACI,MAAmC,EACnC,QAA6B;QAE7B,IAAI,YAA+C,CAAC;QACpD,MAAM,eAAe,GAAG,IAAI,eAAe,EAAE,CAAC;QAE9C,KAAK,CACD;YACI,KAAK,EAAE,
|
|
1
|
+
{"version":3,"file":"push-readable.js","sourceRoot":"","sources":["../src/push-readable.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAGnD,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAgB9D,MAAM,OAAO,kBAAsB,SAAQ,cAAiB;IACxD,8BAA8B,GAAG,KAAK,CAAC;IAEvC;;;;;;OAMG;IACH,YACI,MAAmC,EACnC,QAA6B;QAE7B,IAAI,YAA+C,CAAC;QACpD,MAAM,eAAe,GAAG,IAAI,eAAe,EAAE,CAAC;QAE9C,KAAK,CACD;YACI,KAAK,EAAE,KAAK,EAAE,UAAU,EAAE,EAAE;gBACxB,MAAM,OAAO,CAAC,OAAO,EAAE,CAAC;gBAExB,MAAM,MAAM,GAAG,MAAM,CAAC;oBAClB,WAAW,EAAE,eAAe,CAAC,MAAM;oBACnC,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE;wBACrB,IAAI,eAAe,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;4BACjC,sCAAsC;4BACtC,qBAAqB;4BACrB,MAAM,eAAe,CAAC,MAAM,CAAC,MAAM,CAAC;wBACxC,CAAC;wBAED,IAAI,UAAU,CAAC,WAAW,KAAK,IAAI,EAAE,CAAC;4BAClC,iEAAiE;4BACjE,mDAAmD;4BACnD,UAAU,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;4BAC1B,OAAO;wBACX,CAAC;wBAED,IAAI,IAAI,CAAC,8BAA8B,EAAE,CAAC;4BACtC,IAAI,CAAC,8BAA8B,GAAG,KAAK,CAAC;4BAC5C,UAAU,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;4BAC1B,OAAO;wBACX,CAAC;wBAED,IAAI,UAAU,CAAC,WAAW,IAAI,CAAC,EAAE,CAAC;4BAC9B,YAAY,GAAG,IAAI,eAAe,EAAQ,CAAC;4BAC3C,MAAM,YAAY,CAAC,OAAO,CAAC;wBAC/B,CAAC;wBAED,+CAA+C;wBAC/C,oCAAoC;wBACpC,UAAU,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;oBAC9B,CAAC;oBACD,KAAK;wBACD,UAAU,CAAC,KAAK,EAAE,CAAC;oBACvB,CAAC;oBACD,KAAK,CAAC,CAAC;wBACH,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;oBACxB,CAAC;iBACJ,CAAC,CAAC;gBAEH,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,EAAE,CAAC;oBAC7B,MAAM,CAAC,IAAI,CACP,GAAG,EAAE;wBACD,IAAI,CAAC;4BACD,UAAU,CAAC,KAAK,EAAE,CAAC;wBACvB,CAAC;wBAAC,OAAO,CAAC,EAAE,CAAC;4BACT,4BAA4B;wBAChC,CAAC;oBACL,CAAC,EACD,CAAC,CAAC,EAAE,EAAE;wBACF,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;oBACxB,CAAC,CACJ,CAAC;gBACN,CAAC;YACL,CAAC;YACD,IAAI,EAAE,GAAG,EAAE;gBACP,IAAI,YAAY,EAAE,CAAC;oBACf,YAAY,CAAC,OAAO,EAAE,CAAC;oBACvB,OAAO;gBACX,CAAC;gBACD,IAAI,QAAQ,EAAE,aAAa,KAAK,CAAC,EAAE,CAAC;oBAChC,IAAI,CAAC,8BAA8B,GAAG,IAAI,CAAC;gBAC/C,CAAC;YACL,CAAC;YACD,MAAM,EAAE,CAAC,MAAM,EAAE,EAAE;gBACf,eAAe,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;gBAC9B,YAAY,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;YACjC,CAAC;SACJ,EACD,QAAQ,CACX,CAAC;IACN,CAAC;CACJ"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"split-string.d.ts","sourceRoot":"","sources":["../src/split-string.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAqB9C,qBAAa,iBAAkB,SAAQ,eAAe,CAAC,MAAM,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"split-string.d.ts","sourceRoot":"","sources":["../src/split-string.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAqB9C,qBAAa,iBAAkB,SAAQ,eAAe,CAAC,MAAM,EAAE,MAAM,CAAC;gBACtD,SAAS,EAAE,MAAM;CAShC"}
|
package/esm/split-string.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"split-string.js","sourceRoot":"","sources":["../src/split-string.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAE9C,QAAQ,CAAC,CAAC,KAAK,CACX,KAAa,EACb,SAAiB;IAEjB,IAAI,KAAK,GAAG,CAAC,CAAC;IAEd,OAAO,IAAI,EAAE;
|
|
1
|
+
{"version":3,"file":"split-string.js","sourceRoot":"","sources":["../src/split-string.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAE9C,QAAQ,CAAC,CAAC,KAAK,CACX,KAAa,EACb,SAAiB;IAEjB,IAAI,KAAK,GAAG,CAAC,CAAC;IAEd,OAAO,IAAI,EAAE,CAAC;QACV,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;QAC9C,IAAI,KAAK,KAAK,CAAC,CAAC,EAAE,CAAC;YACf,OAAO;QACX,CAAC;QAED,MAAM,IAAI,GAAG,KAAK,CAAC,SAAS,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;QAC3C,MAAM,IAAI,CAAC;QAEX,KAAK,GAAG,KAAK,GAAG,CAAC,CAAC;IACtB,CAAC;AACL,CAAC;AAED,MAAM,OAAO,iBAAkB,SAAQ,eAA+B;IAClE,YAAY,SAAiB;QACzB,KAAK,CAAC;YACF,SAAS,CAAC,KAAK,EAAE,UAAU;gBACvB,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,KAAK,EAAE,SAAS,CAAC,EAAE,CAAC;oBACzC,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;gBAC7B,CAAC;YACL,CAAC;SACJ,CAAC,CAAC;IACP,CAAC;CACJ"}
|
package/esm/stream.js
CHANGED
|
@@ -6,22 +6,8 @@ export let ReadableStream = ReadableStreamPolyfill;
|
|
|
6
6
|
export let WritableStream = WritableStreamPolyfill;
|
|
7
7
|
export let TransformStream = TransformStreamPolyfill;
|
|
8
8
|
if (GLOBAL.ReadableStream && GLOBAL.WritableStream && GLOBAL.TransformStream) {
|
|
9
|
-
// Use browser native implementation
|
|
10
9
|
ReadableStream = GLOBAL.ReadableStream;
|
|
11
10
|
WritableStream = GLOBAL.WritableStream;
|
|
12
11
|
TransformStream = GLOBAL.TransformStream;
|
|
13
12
|
}
|
|
14
|
-
else {
|
|
15
|
-
// TODO: enable loading Node.js stream implementation when bundler supports Top Level Await
|
|
16
|
-
// try {
|
|
17
|
-
// // Use Node.js native implementation
|
|
18
|
-
// const MODULE_NAME = "node:stream/web";
|
|
19
|
-
// const StreamWeb = (await import(MODULE_NAME)) as GlobalExtension;
|
|
20
|
-
// ReadableStream = StreamWeb.ReadableStream;
|
|
21
|
-
// WritableStream = StreamWeb.WritableStream;
|
|
22
|
-
// TransformStream = StreamWeb.TransformStream;
|
|
23
|
-
// } catch {
|
|
24
|
-
// // ignore
|
|
25
|
-
// }
|
|
26
|
-
}
|
|
27
13
|
//# sourceMappingURL=stream.js.map
|
package/esm/stream.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stream.js","sourceRoot":"","sources":["../src/stream.ts"],"names":[],"mappings":"AACA,OAAO,EACH,cAAc,IAAI,sBAAsB,EACxC,eAAe,IAAI,uBAAuB,EAC1C,cAAc,IAAI,sBAAsB,GAC3C,MAAM,sBAAsB,CAAC;AAC9B,cAAc,sBAAsB,CAAC;AA2BrC,MAAM,MAAM,GAAG,UAAwC,CAAC;AAExD,MAAM,CAAC,MAAM,eAAe,GAAG,MAAM,CAAC,eAAe,CAAC;AAGtD,MAAM,CAAC,IAAI,cAAc,GAAG,sBAAsB,CAAC;AAGnD,MAAM,CAAC,IAAI,cAAc,GAAG,sBAAsB,CAAC;AAGnD,MAAM,CAAC,IAAI,eAAe,GAAG,uBAAuB,CAAC;AAErD,IAAI,MAAM,CAAC,cAAc,IAAI,MAAM,CAAC,cAAc,IAAI,MAAM,CAAC,eAAe,EAAE
|
|
1
|
+
{"version":3,"file":"stream.js","sourceRoot":"","sources":["../src/stream.ts"],"names":[],"mappings":"AACA,OAAO,EACH,cAAc,IAAI,sBAAsB,EACxC,eAAe,IAAI,uBAAuB,EAC1C,cAAc,IAAI,sBAAsB,GAC3C,MAAM,sBAAsB,CAAC;AAC9B,cAAc,sBAAsB,CAAC;AA2BrC,MAAM,MAAM,GAAG,UAAwC,CAAC;AAExD,MAAM,CAAC,MAAM,eAAe,GAAG,MAAM,CAAC,eAAe,CAAC;AAGtD,MAAM,CAAC,IAAI,cAAc,GAAG,sBAAsB,CAAC;AAGnD,MAAM,CAAC,IAAI,cAAc,GAAG,sBAAsB,CAAC;AAGnD,MAAM,CAAC,IAAI,eAAe,GAAG,uBAAuB,CAAC;AAErD,IAAI,MAAM,CAAC,cAAc,IAAI,MAAM,CAAC,cAAc,IAAI,MAAM,CAAC,eAAe,EAAE,CAAC;IAC3E,cAAc,GAAG,MAAM,CAAC,cAAc,CAAC;IACvC,cAAc,GAAG,MAAM,CAAC,cAAc,CAAC;IACvC,eAAe,GAAG,MAAM,CAAC,eAAe,CAAC;AAC7C,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"struct-deserialize.d.ts","sourceRoot":"","sources":["../src/struct-deserialize.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,MAAM,mBAAmB,CAAC;AAC5C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAEzD,OAAO,EAAE,uBAAuB,EAAE,MAAM,yBAAyB,CAAC;AAElE,qBAAa,uBAAuB,CAChC,CAAC,SAAS,MAAM,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CACtC,SAAQ,uBAAuB,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"struct-deserialize.d.ts","sourceRoot":"","sources":["../src/struct-deserialize.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,MAAM,mBAAmB,CAAC;AAC5C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAEzD,OAAO,EAAE,uBAAuB,EAAE,MAAM,yBAAyB,CAAC;AAElE,qBAAa,uBAAuB,CAChC,CAAC,SAAS,MAAM,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CACtC,SAAQ,uBAAuB,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC;gBACrC,MAAM,EAAE,CAAC;CAKxB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"struct-deserialize.js","sourceRoot":"","sources":["../src/struct-deserialize.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,uBAAuB,EAAE,MAAM,yBAAyB,CAAC;AAElE,MAAM,OAAO,uBAEX,SAAQ,uBAA2C;IACjD,
|
|
1
|
+
{"version":3,"file":"struct-deserialize.js","sourceRoot":"","sources":["../src/struct-deserialize.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,uBAAuB,EAAE,MAAM,yBAAyB,CAAC;AAElE,MAAM,OAAO,uBAEX,SAAQ,uBAA2C;IACjD,YAAY,MAAS;QACjB,KAAK,CAAC,CAAC,MAAM,EAAE,EAAE;YACb,OAAO,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;QACtC,CAAC,CAAC,CAAC;IACP,CAAC;CACJ"}
|
package/esm/wrap-readable.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { ValueOrPromise } from "@yume-chan/struct";
|
|
2
|
-
import type { ReadableStreamDefaultController } from "./stream.js";
|
|
2
|
+
import type { QueuingStrategy, ReadableStreamDefaultController } from "./stream.js";
|
|
3
3
|
import { ReadableStream } from "./stream.js";
|
|
4
4
|
export type WrapReadableStreamStart<T> = (controller: ReadableStreamDefaultController<T>) => ValueOrPromise<ReadableStream<T>>;
|
|
5
5
|
export interface ReadableStreamWrapper<T> {
|
|
@@ -17,6 +17,6 @@ export interface ReadableStreamWrapper<T> {
|
|
|
17
17
|
export declare class WrapReadableStream<T> extends ReadableStream<T> {
|
|
18
18
|
#private;
|
|
19
19
|
readable: ReadableStream<T>;
|
|
20
|
-
constructor(wrapper: ReadableStream<T> | WrapReadableStreamStart<T> | ReadableStreamWrapper<T>);
|
|
20
|
+
constructor(wrapper: ReadableStream<T> | WrapReadableStreamStart<T> | ReadableStreamWrapper<T>, strategy?: QueuingStrategy<T>);
|
|
21
21
|
}
|
|
22
22
|
//# sourceMappingURL=wrap-readable.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"wrap-readable.d.ts","sourceRoot":"","sources":["../src/wrap-readable.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAExD,OAAO,KAAK,EACR,+BAA+B,EAElC,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAE7C,MAAM,MAAM,uBAAuB,CAAC,CAAC,IAAI,CACrC,UAAU,EAAE,+BAA+B,CAAC,CAAC,CAAC,KAC7C,cAAc,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,CAAC;AAEvC,MAAM,WAAW,qBAAqB,CAAC,CAAC;IACpC,KAAK,EAAE,uBAAuB,CAAC,CAAC,CAAC,CAAC;IAClC,MAAM,CAAC,CAAC,MAAM,CAAC,EAAE,OAAO,GAAG,cAAc,CAAC,IAAI,CAAC,CAAC;IAChD,KAAK,CAAC,IAAI,cAAc,CAAC,IAAI,CAAC,CAAC;CAClC;AAoBD;;;;;;GAMG;AACH,qBAAa,kBAAkB,CAAC,CAAC,CAAE,SAAQ,cAAc,CAAC,CAAC,CAAC;;
|
|
1
|
+
{"version":3,"file":"wrap-readable.d.ts","sourceRoot":"","sources":["../src/wrap-readable.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAExD,OAAO,KAAK,EACR,eAAe,EACf,+BAA+B,EAElC,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAE7C,MAAM,MAAM,uBAAuB,CAAC,CAAC,IAAI,CACrC,UAAU,EAAE,+BAA+B,CAAC,CAAC,CAAC,KAC7C,cAAc,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,CAAC;AAEvC,MAAM,WAAW,qBAAqB,CAAC,CAAC;IACpC,KAAK,EAAE,uBAAuB,CAAC,CAAC,CAAC,CAAC;IAClC,MAAM,CAAC,CAAC,MAAM,CAAC,EAAE,OAAO,GAAG,cAAc,CAAC,IAAI,CAAC,CAAC;IAChD,KAAK,CAAC,IAAI,cAAc,CAAC,IAAI,CAAC,CAAC;CAClC;AAoBD;;;;;;GAMG;AACH,qBAAa,kBAAkB,CAAC,CAAC,CAAE,SAAQ,cAAc,CAAC,CAAC,CAAC;;IACxD,QAAQ,EAAG,cAAc,CAAC,CAAC,CAAC,CAAC;gBAKzB,OAAO,EACD,cAAc,CAAC,CAAC,CAAC,GACjB,uBAAuB,CAAC,CAAC,CAAC,GAC1B,qBAAqB,CAAC,CAAC,CAAC,EAC9B,QAAQ,CAAC,EAAE,eAAe,CAAC,CAAC,CAAC;CAsCpC"}
|
package/esm/wrap-readable.js
CHANGED
|
@@ -22,7 +22,7 @@ function getWrappedReadableStream(wrapper, controller) {
|
|
|
22
22
|
export class WrapReadableStream extends ReadableStream {
|
|
23
23
|
readable;
|
|
24
24
|
#reader;
|
|
25
|
-
constructor(wrapper) {
|
|
25
|
+
constructor(wrapper, strategy) {
|
|
26
26
|
super({
|
|
27
27
|
start: async (controller) => {
|
|
28
28
|
// `start` is invoked before `ReadableStream`'s constructor finish,
|
|
@@ -33,12 +33,6 @@ export class WrapReadableStream extends ReadableStream {
|
|
|
33
33
|
this.readable = await getWrappedReadableStream(wrapper, controller);
|
|
34
34
|
this.#reader = this.readable.getReader();
|
|
35
35
|
},
|
|
36
|
-
cancel: async (reason) => {
|
|
37
|
-
await this.#reader.cancel(reason);
|
|
38
|
-
if ("cancel" in wrapper) {
|
|
39
|
-
await wrapper.cancel?.(reason);
|
|
40
|
-
}
|
|
41
|
-
},
|
|
42
36
|
pull: async (controller) => {
|
|
43
37
|
const result = await this.#reader.read();
|
|
44
38
|
if (result.done) {
|
|
@@ -51,7 +45,13 @@ export class WrapReadableStream extends ReadableStream {
|
|
|
51
45
|
controller.enqueue(result.value);
|
|
52
46
|
}
|
|
53
47
|
},
|
|
54
|
-
|
|
48
|
+
cancel: async (reason) => {
|
|
49
|
+
await this.#reader.cancel(reason);
|
|
50
|
+
if ("cancel" in wrapper) {
|
|
51
|
+
await wrapper.cancel?.(reason);
|
|
52
|
+
}
|
|
53
|
+
},
|
|
54
|
+
}, strategy);
|
|
55
55
|
}
|
|
56
56
|
}
|
|
57
57
|
//# sourceMappingURL=wrap-readable.js.map
|
package/esm/wrap-readable.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"wrap-readable.js","sourceRoot":"","sources":["../src/wrap-readable.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"wrap-readable.js","sourceRoot":"","sources":["../src/wrap-readable.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAY7C,SAAS,wBAAwB,CAC7B,OAG8B,EAC9B,UAA8C;IAE9C,IAAI,OAAO,IAAI,OAAO,EAAE,CAAC;QACrB,OAAO,OAAO,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;IACrC,CAAC;SAAM,IAAI,OAAO,OAAO,KAAK,UAAU,EAAE,CAAC;QACvC,OAAO,OAAO,CAAC,UAAU,CAAC,CAAC;IAC/B,CAAC;SAAM,CAAC;QACJ,gDAAgD;QAChD,wEAAwE;QACxE,OAAO,OAAO,CAAC;IACnB,CAAC;AACL,CAAC;AAED;;;;;;GAMG;AACH,MAAM,OAAO,kBAAsB,SAAQ,cAAiB;IACxD,QAAQ,CAAqB;IAE7B,OAAO,CAAkC;IAEzC,YACI,OAG8B,EAC9B,QAA6B;QAE7B,KAAK,CACD;YACI,KAAK,EAAE,KAAK,EAAE,UAAU,EAAE,EAAE;gBACxB,mEAAmE;gBACnE,uCAAuC;gBACvC,gHAAgH;gBAChH,mCAAmC;gBACnC,MAAM,OAAO,CAAC,OAAO,EAAE,CAAC;gBAExB,IAAI,CAAC,QAAQ,GAAG,MAAM,wBAAwB,CAC1C,OAAO,EACP,UAAU,CACb,CAAC;gBACF,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,SAAS,EAAE,CAAC;YAC7C,CAAC;YACD,IAAI,EAAE,KAAK,EAAE,UAAU,EAAE,EAAE;gBACvB,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;gBACzC,IAAI,MAAM,CAAC,IAAI,EAAE,CAAC;oBACd,UAAU,CAAC,KAAK,EAAE,CAAC;oBACnB,IAAI,OAAO,IAAI,OAAO,EAAE,CAAC;wBACrB,MAAM,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC;oBAC5B,CAAC;gBACL,CAAC;qBAAM,CAAC;oBACJ,UAAU,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;gBACrC,CAAC;YACL,CAAC;YACD,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE;gBACrB,MAAM,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;gBAClC,IAAI,QAAQ,IAAI,OAAO,EAAE,CAAC;oBACtB,MAAM,OAAO,CAAC,MAAM,EAAE,CAAC,MAAM,CAAC,CAAC;gBACnC,CAAC;YACL,CAAC;SACJ,EACD,QAAQ,CACX,CAAC;IACN,CAAC;CACJ"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"wrap-writable.d.ts","sourceRoot":"","sources":["../src/wrap-writable.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAExD,OAAO,KAAK,EAAE,eAAe,EAA+B,MAAM,aAAa,CAAC;AAChF,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAE7C,MAAM,MAAM,uBAAuB,CAAC,CAAC,IAAI,MAAM,cAAc,CACzD,cAAc,CAAC,CAAC,CAAC,CACpB,CAAC;AAEF,MAAM,WAAW,qBAAqB,CAAC,CAAC;IACpC,KAAK,EAAE,uBAAuB,CAAC,CAAC,CAAC,CAAC;IAClC,KAAK,CAAC,IAAI,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAClC;AAmBD,qBAAa,kBAAkB,CAAC,CAAC,CAAE,SAAQ,cAAc,CAAC,CAAC,CAAC;;
|
|
1
|
+
{"version":3,"file":"wrap-writable.d.ts","sourceRoot":"","sources":["../src/wrap-writable.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAExD,OAAO,KAAK,EAAE,eAAe,EAA+B,MAAM,aAAa,CAAC;AAChF,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAE7C,MAAM,MAAM,uBAAuB,CAAC,CAAC,IAAI,MAAM,cAAc,CACzD,cAAc,CAAC,CAAC,CAAC,CACpB,CAAC;AAEF,MAAM,WAAW,qBAAqB,CAAC,CAAC;IACpC,KAAK,EAAE,uBAAuB,CAAC,CAAC,CAAC,CAAC;IAClC,KAAK,CAAC,IAAI,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAClC;AAmBD,qBAAa,kBAAkB,CAAC,CAAC,CAAE,SAAQ,cAAc,CAAC,CAAC,CAAC;;IACxD,QAAQ,EAAG,cAAc,CAAC,CAAC,CAAC,CAAC;gBAKzB,OAAO,EACD,cAAc,CAAC,CAAC,CAAC,GACjB,uBAAuB,CAAC,CAAC,CAAC,GAC1B,qBAAqB,CAAC,CAAC,CAAC;IAmClC,kBAAkB,CAAC,CAAC,EAAE,WAAW,EAAE,eAAe,CAAC,CAAC,EAAE,CAAC,CAAC;CAY3D"}
|
package/esm/wrap-writable.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"wrap-writable.js","sourceRoot":"","sources":["../src/wrap-writable.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAW7C,KAAK,UAAU,wBAAwB,CACnC,OAG8B;IAE9B,IAAI,OAAO,IAAI,OAAO,EAAE;
|
|
1
|
+
{"version":3,"file":"wrap-writable.js","sourceRoot":"","sources":["../src/wrap-writable.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAW7C,KAAK,UAAU,wBAAwB,CACnC,OAG8B;IAE9B,IAAI,OAAO,IAAI,OAAO,EAAE,CAAC;QACrB,OAAO,MAAM,OAAO,CAAC,KAAK,EAAE,CAAC;IACjC,CAAC;SAAM,IAAI,OAAO,OAAO,KAAK,UAAU,EAAE,CAAC;QACvC,OAAO,MAAM,OAAO,EAAE,CAAC;IAC3B,CAAC;SAAM,CAAC;QACJ,gDAAgD;QAChD,wEAAwE;QACxE,OAAO,OAAO,CAAC;IACnB,CAAC;AACL,CAAC;AAED,MAAM,OAAO,kBAAsB,SAAQ,cAAiB;IACxD,QAAQ,CAAqB;IAE7B,OAAO,CAAkC;IAEzC,YACI,OAG8B;QAE9B,KAAK,CAAC;YACF,KAAK,EAAE,KAAK,IAAI,EAAE;gBACd,mEAAmE;gBACnE,uCAAuC;gBACvC,gHAAgH;gBAChH,mCAAmC;gBACnC,MAAM,OAAO,CAAC,OAAO,EAAE,CAAC;gBAExB,IAAI,CAAC,QAAQ,GAAG,MAAM,wBAAwB,CAAC,OAAO,CAAC,CAAC;gBACxD,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,SAAS,EAAE,CAAC;YAC7C,CAAC;YACD,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE;gBACnB,MAAM,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;YACpC,CAAC;YACD,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE;gBACpB,MAAM,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;gBACjC,IAAI,OAAO,IAAI,OAAO,EAAE,CAAC;oBACrB,MAAM,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC;gBAC5B,CAAC;YACL,CAAC;YACD,KAAK,EAAE,KAAK,IAAI,EAAE;gBACd,gCAAgC;gBAChC,0EAA0E;gBAC1E,yEAAyE;gBACzE,uCAAuC;gBACvC,MAAM,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;gBAC3B,IAAI,OAAO,IAAI,OAAO,EAAE,CAAC;oBACrB,MAAM,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC;gBAC5B,CAAC;YACL,CAAC;SACJ,CAAC,CAAC;IACP,CAAC;IAED,kBAAkB,CAAI,WAAkC;QACpD,IAAI,OAAsB,CAAC;QAC3B,OAAO,IAAI,kBAAkB,CAAI;YAC7B,KAAK,EAAE,GAAG,EAAE;gBACR,OAAO,GAAG,WAAW,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;gBAC5C,OAAO,WAAW,CAAC,QAAQ,CAAC;YAChC,CAAC;YACD,KAAK,CAAC,KAAK;gBACP,MAAM,OAAO,CAAC;YAClB,CAAC;SACJ,CAAC,CAAC;IACP,CAAC;CACJ"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@yume-chan/stream-extra",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.22",
|
|
4
4
|
"description": "Extensions to Web Streams API",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"stream",
|
|
@@ -26,20 +26,20 @@
|
|
|
26
26
|
"types": "esm/index.d.ts",
|
|
27
27
|
"dependencies": {
|
|
28
28
|
"@yume-chan/async": "^2.2.0",
|
|
29
|
-
"@yume-chan/struct": "^0.0.
|
|
30
|
-
"tslib": "^2.
|
|
29
|
+
"@yume-chan/struct": "^0.0.22",
|
|
30
|
+
"tslib": "^2.6.2",
|
|
31
31
|
"web-streams-polyfill": "^4.0.0-beta.3"
|
|
32
32
|
},
|
|
33
33
|
"devDependencies": {
|
|
34
|
-
"@jest/globals": "^29.
|
|
34
|
+
"@jest/globals": "^29.7.0",
|
|
35
35
|
"@yume-chan/eslint-config": "^1.0.0",
|
|
36
36
|
"@yume-chan/tsconfig": "^1.0.0",
|
|
37
37
|
"cross-env": "^7.0.3",
|
|
38
|
-
"eslint": "^8.
|
|
39
|
-
"jest": "^29.
|
|
40
|
-
"prettier": "^
|
|
41
|
-
"ts-jest": "^29.
|
|
42
|
-
"typescript": "^5.
|
|
38
|
+
"eslint": "^8.55.0",
|
|
39
|
+
"jest": "^29.7.0",
|
|
40
|
+
"prettier": "^3.1.0",
|
|
41
|
+
"ts-jest": "^29.1.1",
|
|
42
|
+
"typescript": "^5.3.2"
|
|
43
43
|
},
|
|
44
44
|
"scripts": {
|
|
45
45
|
"build": "tsc -b tsconfig.build.json",
|
|
@@ -12,17 +12,17 @@ export class BufferedTransformStream<T>
|
|
|
12
12
|
implements ReadableWritablePair<T, Uint8Array>
|
|
13
13
|
{
|
|
14
14
|
#readable: ReadableStream<T>;
|
|
15
|
-
|
|
15
|
+
get readable() {
|
|
16
16
|
return this.#readable;
|
|
17
17
|
}
|
|
18
18
|
|
|
19
19
|
#writable: WritableStream<Uint8Array>;
|
|
20
|
-
|
|
20
|
+
get writable() {
|
|
21
21
|
return this.#writable;
|
|
22
22
|
}
|
|
23
23
|
|
|
24
24
|
constructor(
|
|
25
|
-
transform: (stream: BufferedReadableStream) => ValueOrPromise<T
|
|
25
|
+
transform: (stream: BufferedReadableStream) => ValueOrPromise<T>,
|
|
26
26
|
) {
|
|
27
27
|
// Convert incoming chunks to a `BufferedReadableStream`
|
|
28
28
|
let sourceStreamController!: PushReadableStreamController<Uint8Array>;
|
|
@@ -30,7 +30,7 @@ export class BufferedTransformStream<T>
|
|
|
30
30
|
const buffered = new BufferedReadableStream(
|
|
31
31
|
new PushReadableStream<Uint8Array>((controller) => {
|
|
32
32
|
sourceStreamController = controller;
|
|
33
|
-
})
|
|
33
|
+
}),
|
|
34
34
|
);
|
|
35
35
|
|
|
36
36
|
this.#readable = new ReadableStream<T>({
|
package/src/buffered.ts
CHANGED
|
@@ -14,73 +14,78 @@ export class BufferedReadableStream implements AsyncExactReadable {
|
|
|
14
14
|
#bufferedLength = 0;
|
|
15
15
|
|
|
16
16
|
#position = 0;
|
|
17
|
-
|
|
17
|
+
get position() {
|
|
18
18
|
return this.#position;
|
|
19
19
|
}
|
|
20
20
|
|
|
21
21
|
protected readonly stream: ReadableStream<Uint8Array>;
|
|
22
22
|
protected readonly reader: ReadableStreamDefaultReader<Uint8Array>;
|
|
23
23
|
|
|
24
|
-
|
|
24
|
+
constructor(stream: ReadableStream<Uint8Array>) {
|
|
25
25
|
this.stream = stream;
|
|
26
26
|
this.reader = stream.getReader();
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
-
|
|
29
|
+
async #readSource() {
|
|
30
30
|
const { done, value } = await this.reader.read();
|
|
31
31
|
if (done) {
|
|
32
32
|
throw new ExactReadableEndedError();
|
|
33
33
|
}
|
|
34
|
-
this.#position += value.byteLength;
|
|
35
34
|
return value;
|
|
36
35
|
}
|
|
37
36
|
|
|
38
|
-
|
|
37
|
+
async #readAsync(length: number, initial?: Uint8Array) {
|
|
39
38
|
let result: Uint8Array;
|
|
40
39
|
let index: number;
|
|
41
40
|
|
|
42
41
|
if (initial) {
|
|
43
42
|
result = new Uint8Array(length);
|
|
44
43
|
result.set(initial);
|
|
45
|
-
index = initial.
|
|
46
|
-
length -= initial.
|
|
44
|
+
index = initial.length;
|
|
45
|
+
length -= initial.length;
|
|
47
46
|
} else {
|
|
48
|
-
const array = await this
|
|
49
|
-
if (array.
|
|
47
|
+
const array = await this.#readSource();
|
|
48
|
+
if (array.length === length) {
|
|
49
|
+
this.#position += length;
|
|
50
50
|
return array;
|
|
51
51
|
}
|
|
52
52
|
|
|
53
|
-
if (array.
|
|
53
|
+
if (array.length > length) {
|
|
54
54
|
this.#buffered = array;
|
|
55
55
|
this.#bufferedOffset = length;
|
|
56
|
-
this.#bufferedLength = array.
|
|
56
|
+
this.#bufferedLength = array.length - length;
|
|
57
|
+
this.#position += length;
|
|
57
58
|
return array.subarray(0, length);
|
|
58
59
|
}
|
|
59
60
|
|
|
60
61
|
result = new Uint8Array(length);
|
|
61
62
|
result.set(array);
|
|
62
|
-
index = array.
|
|
63
|
-
length -= array.
|
|
63
|
+
index = array.length;
|
|
64
|
+
length -= array.length;
|
|
65
|
+
this.#position += array.length;
|
|
64
66
|
}
|
|
65
67
|
|
|
66
68
|
while (length > 0) {
|
|
67
|
-
const array = await this
|
|
68
|
-
if (array.
|
|
69
|
+
const array = await this.#readSource();
|
|
70
|
+
if (array.length === length) {
|
|
69
71
|
result.set(array, index);
|
|
72
|
+
this.#position += length;
|
|
70
73
|
return result;
|
|
71
74
|
}
|
|
72
75
|
|
|
73
|
-
if (array.
|
|
76
|
+
if (array.length > length) {
|
|
74
77
|
this.#buffered = array;
|
|
75
78
|
this.#bufferedOffset = length;
|
|
76
|
-
this.#bufferedLength = array.
|
|
79
|
+
this.#bufferedLength = array.length - length;
|
|
77
80
|
result.set(array.subarray(0, length), index);
|
|
81
|
+
this.#position += length;
|
|
78
82
|
return result;
|
|
79
83
|
}
|
|
80
84
|
|
|
81
85
|
result.set(array, index);
|
|
82
|
-
index += array.
|
|
83
|
-
length -= array.
|
|
86
|
+
index += array.length;
|
|
87
|
+
length -= array.length;
|
|
88
|
+
this.#position += array.length;
|
|
84
89
|
}
|
|
85
90
|
|
|
86
91
|
return result;
|
|
@@ -91,7 +96,7 @@ export class BufferedReadableStream implements AsyncExactReadable {
|
|
|
91
96
|
* @param length
|
|
92
97
|
* @returns
|
|
93
98
|
*/
|
|
94
|
-
|
|
99
|
+
readExactly(length: number): Uint8Array | Promise<Uint8Array> {
|
|
95
100
|
// PERF: Add a synchronous path for reading from internal buffer
|
|
96
101
|
if (this.#buffered) {
|
|
97
102
|
const array = this.#buffered;
|
|
@@ -101,16 +106,18 @@ export class BufferedReadableStream implements AsyncExactReadable {
|
|
|
101
106
|
// don't use it until absolutely necessary
|
|
102
107
|
this.#bufferedOffset += length;
|
|
103
108
|
this.#bufferedLength -= length;
|
|
109
|
+
this.#position += length;
|
|
104
110
|
return array.subarray(offset, offset + length);
|
|
105
111
|
}
|
|
106
112
|
|
|
107
113
|
this.#buffered = undefined;
|
|
108
114
|
this.#bufferedLength = 0;
|
|
109
115
|
this.#bufferedOffset = 0;
|
|
110
|
-
|
|
116
|
+
this.#position += array.length - offset;
|
|
117
|
+
return this.#readAsync(length, array.subarray(offset));
|
|
111
118
|
}
|
|
112
119
|
|
|
113
|
-
return this
|
|
120
|
+
return this.#readAsync(length);
|
|
114
121
|
}
|
|
115
122
|
|
|
116
123
|
/**
|
|
@@ -118,7 +125,7 @@ export class BufferedReadableStream implements AsyncExactReadable {
|
|
|
118
125
|
* all data from the wrapped stream.
|
|
119
126
|
* @returns A `ReadableStream`
|
|
120
127
|
*/
|
|
121
|
-
|
|
128
|
+
release(): ReadableStream<Uint8Array> {
|
|
122
129
|
if (this.#bufferedLength > 0) {
|
|
123
130
|
return new PushReadableStream<Uint8Array>(async (controller) => {
|
|
124
131
|
// Put the remaining data back to the stream
|
|
@@ -147,7 +154,7 @@ export class BufferedReadableStream implements AsyncExactReadable {
|
|
|
147
154
|
}
|
|
148
155
|
}
|
|
149
156
|
|
|
150
|
-
|
|
151
|
-
|
|
157
|
+
async cancel(reason?: unknown) {
|
|
158
|
+
await this.reader.cancel(reason);
|
|
152
159
|
}
|
|
153
160
|
}
|
package/src/concat.ts
ADDED
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
import { PromiseResolver } from "@yume-chan/async";
|
|
2
|
+
|
|
3
|
+
import type { ReadableStreamDefaultController } from "./stream.js";
|
|
4
|
+
import { ReadableStream, WritableStream } from "./stream.js";
|
|
5
|
+
|
|
6
|
+
export interface ConcatStringReadableStream
|
|
7
|
+
extends ReadableStream<string>,
|
|
8
|
+
Promise<string> {}
|
|
9
|
+
|
|
10
|
+
// `TransformStream` only calls its `source.flush` method when its `readable` is being read.
|
|
11
|
+
// If the user want to use the `Promise` interface, the `flush` method will never be called,
|
|
12
|
+
// so the `PromiseResolver` will never be resolved.
|
|
13
|
+
// Thus we need to implement our own `TransformStream` using a `WritableStream` and a `ReadableStream`.
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* A `TransformStream` that concatenates strings.
|
|
17
|
+
*
|
|
18
|
+
* Its `readable` is also a `Promise<string>`, so it's possible to `await` it to get the result.
|
|
19
|
+
*
|
|
20
|
+
* ```ts
|
|
21
|
+
* const result: string = await readable.pipeThrough(new ConcatStringStream());
|
|
22
|
+
* ```
|
|
23
|
+
*/
|
|
24
|
+
export class ConcatStringStream {
|
|
25
|
+
// PERF: rope (concat strings) is faster than `[].join('')`
|
|
26
|
+
#result = "";
|
|
27
|
+
|
|
28
|
+
#resolver = new PromiseResolver<string>();
|
|
29
|
+
|
|
30
|
+
#writable = new WritableStream<string>({
|
|
31
|
+
write: (chunk) => {
|
|
32
|
+
this.#result += chunk;
|
|
33
|
+
},
|
|
34
|
+
close: () => {
|
|
35
|
+
this.#resolver.resolve(this.#result);
|
|
36
|
+
this.#readableController.enqueue(this.#result);
|
|
37
|
+
this.#readableController.close();
|
|
38
|
+
},
|
|
39
|
+
abort: (reason) => {
|
|
40
|
+
this.#resolver.reject(reason);
|
|
41
|
+
this.#readableController.error(reason);
|
|
42
|
+
},
|
|
43
|
+
});
|
|
44
|
+
get writable(): WritableStream<string> {
|
|
45
|
+
return this.#writable;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
#readableController!: ReadableStreamDefaultController<string>;
|
|
49
|
+
#readable = new ReadableStream<string>({
|
|
50
|
+
start: (controller) => {
|
|
51
|
+
this.#readableController = controller;
|
|
52
|
+
},
|
|
53
|
+
}) as ConcatStringReadableStream;
|
|
54
|
+
get readable(): ConcatStringReadableStream {
|
|
55
|
+
return this.#readable;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
constructor() {
|
|
59
|
+
void Object.defineProperties(this.#readable, {
|
|
60
|
+
then: {
|
|
61
|
+
get: () =>
|
|
62
|
+
this.#resolver.promise.then.bind(this.#resolver.promise),
|
|
63
|
+
},
|
|
64
|
+
catch: {
|
|
65
|
+
get: () =>
|
|
66
|
+
this.#resolver.promise.catch.bind(this.#resolver.promise),
|
|
67
|
+
},
|
|
68
|
+
finally: {
|
|
69
|
+
get: () =>
|
|
70
|
+
this.#resolver.promise.finally.bind(this.#resolver.promise),
|
|
71
|
+
},
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export interface ConcatBufferReadableStream
|
|
77
|
+
extends ReadableStream<Uint8Array>,
|
|
78
|
+
Promise<Uint8Array> {}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* A `TransformStream` that concatenates `Uint8Array`s.
|
|
82
|
+
*
|
|
83
|
+
* If you want to decode the result as string,
|
|
84
|
+
* prefer `.pipeThrough(new DecodeUtf8Stream()).pipeThrough(new ConcatStringStream())`,
|
|
85
|
+
* than `.pipeThough(new ConcatBufferStream()).pipeThrough(new DecodeUtf8Stream())`,
|
|
86
|
+
* because concatenating strings is faster than concatenating `Uint8Array`s.
|
|
87
|
+
*/
|
|
88
|
+
export class ConcatBufferStream {
|
|
89
|
+
#segments: Uint8Array[] = [];
|
|
90
|
+
|
|
91
|
+
#resolver = new PromiseResolver<Uint8Array>();
|
|
92
|
+
|
|
93
|
+
#writable = new WritableStream<Uint8Array>({
|
|
94
|
+
write: (chunk) => {
|
|
95
|
+
this.#segments.push(chunk);
|
|
96
|
+
},
|
|
97
|
+
close: () => {
|
|
98
|
+
let result: Uint8Array;
|
|
99
|
+
let offset = 0;
|
|
100
|
+
switch (this.#segments.length) {
|
|
101
|
+
case 0:
|
|
102
|
+
result = new Uint8Array(0);
|
|
103
|
+
break;
|
|
104
|
+
case 1:
|
|
105
|
+
result = this.#segments[0]!;
|
|
106
|
+
break;
|
|
107
|
+
default:
|
|
108
|
+
result = new Uint8Array(
|
|
109
|
+
this.#segments.reduce(
|
|
110
|
+
(prev, item) => prev + item.length,
|
|
111
|
+
0,
|
|
112
|
+
),
|
|
113
|
+
);
|
|
114
|
+
for (const segment of this.#segments) {
|
|
115
|
+
result.set(segment, offset);
|
|
116
|
+
offset += segment.length;
|
|
117
|
+
}
|
|
118
|
+
break;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
this.#resolver.resolve(result);
|
|
122
|
+
this.#readableController.enqueue(result);
|
|
123
|
+
this.#readableController.close();
|
|
124
|
+
},
|
|
125
|
+
abort: (reason) => {
|
|
126
|
+
this.#resolver.reject(reason);
|
|
127
|
+
this.#readableController.error(reason);
|
|
128
|
+
},
|
|
129
|
+
});
|
|
130
|
+
get writable(): WritableStream<Uint8Array> {
|
|
131
|
+
return this.#writable;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
#readableController!: ReadableStreamDefaultController<Uint8Array>;
|
|
135
|
+
#readable = new ReadableStream<Uint8Array>({
|
|
136
|
+
start: (controller) => {
|
|
137
|
+
this.#readableController = controller;
|
|
138
|
+
},
|
|
139
|
+
}) as ConcatBufferReadableStream;
|
|
140
|
+
get readable(): ConcatBufferReadableStream {
|
|
141
|
+
return this.#readable;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
constructor() {
|
|
145
|
+
void Object.defineProperties(this.#readable, {
|
|
146
|
+
then: {
|
|
147
|
+
get: () =>
|
|
148
|
+
this.#resolver.promise.then.bind(this.#resolver.promise),
|
|
149
|
+
},
|
|
150
|
+
catch: {
|
|
151
|
+
get: () =>
|
|
152
|
+
this.#resolver.promise.catch.bind(this.#resolver.promise),
|
|
153
|
+
},
|
|
154
|
+
finally: {
|
|
155
|
+
get: () =>
|
|
156
|
+
this.#resolver.promise.finally.bind(this.#resolver.promise),
|
|
157
|
+
},
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
}
|