@gjsify/web-streams 0.1.0
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 +30 -0
- package/lib/esm/index.js +121 -0
- package/lib/esm/queuing-strategies.js +56 -0
- package/lib/esm/readable-stream.js +1064 -0
- package/lib/esm/text-decoder-stream.js +126 -0
- package/lib/esm/text-encoder-stream.js +46 -0
- package/lib/esm/transform-stream.js +336 -0
- package/lib/esm/util.js +161 -0
- package/lib/esm/writable-stream.js +676 -0
- package/lib/types/index.d.ts +77 -0
- package/lib/types/queuing-strategies.d.ts +18 -0
- package/lib/types/readable-stream.d.ts +61 -0
- package/lib/types/text-decoder-stream.d.ts +16 -0
- package/lib/types/text-encoder-stream.d.ts +15 -0
- package/lib/types/transform-stream.d.ts +21 -0
- package/lib/types/util.d.ts +40 -0
- package/lib/types/writable-stream.d.ts +49 -0
- package/package.json +44 -0
- package/src/index.spec.ts +2043 -0
- package/src/index.ts +131 -0
- package/src/queuing-strategies.ts +67 -0
- package/src/readable-stream.ts +1337 -0
- package/src/test.mts +6 -0
- package/src/text-decoder-stream.ts +183 -0
- package/src/text-encoder-stream.ts +62 -0
- package/src/transform-stream.ts +410 -0
- package/src/util.ts +170 -0
- package/src/writable-stream.ts +773 -0
- package/tsconfig.json +32 -0
- package/tsconfig.tsbuildinfo +1 -0
package/src/util.ts
ADDED
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
// WHATWG Streams — shared utilities
|
|
2
|
+
// Adapted from refs/node/lib/internal/webstreams/util.js
|
|
3
|
+
// Copyright (c) Node.js contributors. MIT license.
|
|
4
|
+
// Modifications: Removed primordials, internalBinding, Node.js error codes
|
|
5
|
+
|
|
6
|
+
export const kState = Symbol('kState');
|
|
7
|
+
export const kType = Symbol('kType');
|
|
8
|
+
|
|
9
|
+
// ---- Brand checking ----
|
|
10
|
+
|
|
11
|
+
export function isBrandCheck(brand: string) {
|
|
12
|
+
return (value: unknown): boolean => {
|
|
13
|
+
return value != null &&
|
|
14
|
+
typeof value === 'object' &&
|
|
15
|
+
(value as Record<symbol, unknown>)[kState] !== undefined &&
|
|
16
|
+
(value as Record<symbol, unknown>)[kType] === brand;
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
// ---- Queue management ----
|
|
21
|
+
|
|
22
|
+
export function dequeueValue(controller: any): any {
|
|
23
|
+
const { value, size } = controller[kState].queue.shift();
|
|
24
|
+
controller[kState].queueTotalSize =
|
|
25
|
+
Math.max(0, controller[kState].queueTotalSize - size);
|
|
26
|
+
return value;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export function resetQueue(controller: any): void {
|
|
30
|
+
controller[kState].queue = [];
|
|
31
|
+
controller[kState].queueTotalSize = 0;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export function peekQueueValue(controller: any): any {
|
|
35
|
+
return controller[kState].queue[0].value;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export function enqueueValueWithSize(controller: any, value: any, size: number): void {
|
|
39
|
+
size = +size;
|
|
40
|
+
if (typeof size !== 'number' || size < 0 || Number.isNaN(size) || size === Infinity) {
|
|
41
|
+
throw new RangeError(`Invalid size: ${size}`);
|
|
42
|
+
}
|
|
43
|
+
controller[kState].queue.push({ value, size });
|
|
44
|
+
controller[kState].queueTotalSize += size;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// ---- Strategy extraction ----
|
|
48
|
+
|
|
49
|
+
export function extractHighWaterMark(value: number | undefined, defaultHWM: number): number {
|
|
50
|
+
if (value === undefined) return defaultHWM;
|
|
51
|
+
value = +value;
|
|
52
|
+
if (typeof value !== 'number' || Number.isNaN(value) || value < 0) {
|
|
53
|
+
throw new RangeError(`Invalid highWaterMark: ${value}`);
|
|
54
|
+
}
|
|
55
|
+
return value;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export function extractSizeAlgorithm(size: ((chunk: any) => number) | undefined): (chunk: any) => number {
|
|
59
|
+
if (size === undefined) return () => 1;
|
|
60
|
+
if (typeof size !== 'function') {
|
|
61
|
+
throw new TypeError('strategy.size must be a function');
|
|
62
|
+
}
|
|
63
|
+
return size;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// ---- Buffer utilities ----
|
|
67
|
+
|
|
68
|
+
export function cloneAsUint8Array(view: ArrayBufferView): Uint8Array {
|
|
69
|
+
const buffer = view.buffer;
|
|
70
|
+
const byteOffset = view.byteOffset;
|
|
71
|
+
const byteLength = view.byteLength;
|
|
72
|
+
return new Uint8Array(buffer.slice(byteOffset, byteOffset + byteLength));
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export function ArrayBufferViewGetBuffer(view: ArrayBufferView): ArrayBuffer {
|
|
76
|
+
return view.buffer as ArrayBuffer;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export function ArrayBufferViewGetByteLength(view: ArrayBufferView): number {
|
|
80
|
+
return view.byteLength;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export function ArrayBufferViewGetByteOffset(view: ArrayBufferView): number {
|
|
84
|
+
return view.byteOffset;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// ---- Promise utilities ----
|
|
88
|
+
|
|
89
|
+
export function setPromiseHandled(promise: Promise<unknown>): void {
|
|
90
|
+
promise.then(() => {}, () => {});
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
export function createPromiseCallback(name: string, fn: Function, thisArg: unknown) {
|
|
94
|
+
if (typeof fn !== 'function') {
|
|
95
|
+
throw new TypeError(`${name} must be a function`);
|
|
96
|
+
}
|
|
97
|
+
// Always return a Promise, even if fn is synchronous
|
|
98
|
+
return async (...args: unknown[]) => fn.call(thisArg, ...args);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// ---- No-op callbacks ----
|
|
102
|
+
|
|
103
|
+
export async function nonOpFlush(): Promise<void> {}
|
|
104
|
+
export function nonOpStart(): void {}
|
|
105
|
+
export async function nonOpPull(): Promise<void> {}
|
|
106
|
+
export async function nonOpCancel(): Promise<void> {}
|
|
107
|
+
export async function nonOpWrite(): Promise<void> {}
|
|
108
|
+
|
|
109
|
+
// ---- Iterator utilities ----
|
|
110
|
+
|
|
111
|
+
const AsyncIteratorPrototype = Object.getPrototypeOf(
|
|
112
|
+
Object.getPrototypeOf(async function* () {}).prototype
|
|
113
|
+
);
|
|
114
|
+
|
|
115
|
+
export const AsyncIterator = {
|
|
116
|
+
__proto__: AsyncIteratorPrototype,
|
|
117
|
+
next: undefined as (() => Promise<IteratorResult<unknown>>) | undefined,
|
|
118
|
+
return: undefined as ((value?: unknown) => Promise<IteratorResult<unknown>>) | undefined,
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
export function createAsyncFromSyncIterator(syncIteratorRecord: { iterator: Iterator<unknown>; nextMethod: Function; done: boolean }) {
|
|
122
|
+
const syncIterable = {
|
|
123
|
+
[Symbol.iterator]: () => syncIteratorRecord.iterator,
|
|
124
|
+
};
|
|
125
|
+
const asyncIterator = (async function* () {
|
|
126
|
+
return yield* syncIterable;
|
|
127
|
+
}());
|
|
128
|
+
const nextMethod = asyncIterator.next;
|
|
129
|
+
return { iterator: asyncIterator, nextMethod, done: false };
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
export function getIterator(obj: Record<string | symbol, unknown>, kind: 'sync' | 'async' = 'sync', method?: Function) {
|
|
133
|
+
if (method === undefined) {
|
|
134
|
+
if (kind === 'async') {
|
|
135
|
+
method = obj[Symbol.asyncIterator] as Function | undefined;
|
|
136
|
+
if (method == null) {
|
|
137
|
+
const syncMethod = obj[Symbol.iterator] as Function | undefined;
|
|
138
|
+
if (syncMethod === undefined) {
|
|
139
|
+
throw new TypeError('Object is not iterable');
|
|
140
|
+
}
|
|
141
|
+
const syncIteratorRecord = getIterator(obj, 'sync', syncMethod);
|
|
142
|
+
return createAsyncFromSyncIterator(syncIteratorRecord);
|
|
143
|
+
}
|
|
144
|
+
} else {
|
|
145
|
+
method = obj[Symbol.iterator] as Function | undefined;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
if (method === undefined) {
|
|
149
|
+
throw new TypeError('Object is not iterable');
|
|
150
|
+
}
|
|
151
|
+
const iterator = method.call(obj);
|
|
152
|
+
if (typeof iterator !== 'object' || iterator === null) {
|
|
153
|
+
throw new TypeError('The iterator method must return an object');
|
|
154
|
+
}
|
|
155
|
+
const nextMethod = iterator.next;
|
|
156
|
+
return { iterator, nextMethod, done: false };
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
export function iteratorNext(iteratorRecord: { iterator: unknown; nextMethod: Function; done: boolean }, value?: unknown) {
|
|
160
|
+
let result;
|
|
161
|
+
if (value === undefined) {
|
|
162
|
+
result = iteratorRecord.nextMethod.call(iteratorRecord.iterator);
|
|
163
|
+
} else {
|
|
164
|
+
result = iteratorRecord.nextMethod.call(iteratorRecord.iterator, value);
|
|
165
|
+
}
|
|
166
|
+
if (typeof result !== 'object' || result === null) {
|
|
167
|
+
throw new TypeError('The iterator.next() method must return an object');
|
|
168
|
+
}
|
|
169
|
+
return result;
|
|
170
|
+
}
|