@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/src/index.ts ADDED
@@ -0,0 +1,131 @@
1
+ // WHATWG Streams API for GJS
2
+ // Reference: refs/node/lib/internal/webstreams/
3
+ // Copyright (c) Node.js contributors. MIT license.
4
+ // Reimplemented for GJS — pure TypeScript, no native bindings.
5
+ //
6
+ // On Node.js (and any environment with native Web Streams), this module
7
+ // re-exports the native globals for zero overhead.
8
+ // On GJS, it provides a full polyfill and registers globals.
9
+
10
+ import { WritableStream, WritableStreamDefaultWriter, WritableStreamDefaultController } from './writable-stream.js';
11
+ import { ReadableStream, ReadableStreamDefaultReader, ReadableStreamDefaultController } from './readable-stream.js';
12
+ import { TransformStream, TransformStreamDefaultController } from './transform-stream.js';
13
+ import { ByteLengthQueuingStrategy, CountQueuingStrategy } from './queuing-strategies.js';
14
+ import { TextEncoderStream } from './text-encoder-stream.js';
15
+ import { TextDecoderStream } from './text-decoder-stream.js';
16
+
17
+ // Validate that a native stream class produces functional instances.
18
+ // GJS may expose stream constructors that return objects missing core methods
19
+ // (e.g. ReadableStream exists but instances lack getReader()).
20
+ function isNativeStreamUsable(Ctor: unknown, method: string): boolean {
21
+ try {
22
+ if (typeof Ctor !== 'function') return false;
23
+ return typeof (Ctor as any).prototype[method] === 'function';
24
+ } catch {
25
+ return false;
26
+ }
27
+ }
28
+
29
+ // Use native if available and functional (Node.js 18+), polyfill otherwise
30
+ const _ReadableStream = isNativeStreamUsable(globalThis.ReadableStream, 'getReader')
31
+ ? globalThis.ReadableStream
32
+ : ReadableStream;
33
+ const _WritableStream = isNativeStreamUsable(globalThis.WritableStream, 'getWriter')
34
+ ? globalThis.WritableStream
35
+ : WritableStream;
36
+ const _TransformStream = isNativeStreamUsable(globalThis.TransformStream, 'readable')
37
+ ? globalThis.TransformStream
38
+ : TransformStream;
39
+ const _ByteLengthQueuingStrategy = typeof globalThis.ByteLengthQueuingStrategy === 'function'
40
+ ? globalThis.ByteLengthQueuingStrategy
41
+ : ByteLengthQueuingStrategy;
42
+ const _CountQueuingStrategy = typeof globalThis.CountQueuingStrategy === 'function'
43
+ ? globalThis.CountQueuingStrategy
44
+ : CountQueuingStrategy;
45
+ const _TextEncoderStream = typeof globalThis.TextEncoderStream === 'function'
46
+ ? globalThis.TextEncoderStream
47
+ : TextEncoderStream;
48
+ const _TextDecoderStream = typeof globalThis.TextDecoderStream === 'function'
49
+ ? globalThis.TextDecoderStream
50
+ : TextDecoderStream;
51
+
52
+ // Register globals — replace broken native implementations with polyfill
53
+ if (!isNativeStreamUsable(globalThis.ReadableStream, 'getReader')) {
54
+ (globalThis as any).ReadableStream = ReadableStream;
55
+ }
56
+ if (!isNativeStreamUsable(globalThis.WritableStream, 'getWriter')) {
57
+ (globalThis as any).WritableStream = WritableStream;
58
+ }
59
+ if (!isNativeStreamUsable(globalThis.TransformStream, 'readable')) {
60
+ (globalThis as any).TransformStream = TransformStream;
61
+ }
62
+ if (typeof globalThis.ByteLengthQueuingStrategy === 'undefined') {
63
+ (globalThis as any).ByteLengthQueuingStrategy = ByteLengthQueuingStrategy;
64
+ }
65
+ if (typeof globalThis.CountQueuingStrategy === 'undefined') {
66
+ (globalThis as any).CountQueuingStrategy = CountQueuingStrategy;
67
+ }
68
+ if (typeof globalThis.TextEncoderStream === 'undefined') {
69
+ (globalThis as any).TextEncoderStream = TextEncoderStream;
70
+ }
71
+ if (typeof globalThis.TextDecoderStream === 'undefined') {
72
+ (globalThis as any).TextDecoderStream = TextDecoderStream;
73
+ }
74
+
75
+ export {
76
+ _WritableStream as WritableStream,
77
+ _ReadableStream as ReadableStream,
78
+ _TransformStream as TransformStream,
79
+ _ByteLengthQueuingStrategy as ByteLengthQueuingStrategy,
80
+ _CountQueuingStrategy as CountQueuingStrategy,
81
+ _TextEncoderStream as TextEncoderStream,
82
+ _TextDecoderStream as TextDecoderStream,
83
+ };
84
+
85
+ // Re-export class types for direct import
86
+ export { WritableStreamDefaultWriter, WritableStreamDefaultController } from './writable-stream.js';
87
+ export { ReadableStreamDefaultReader, ReadableStreamDefaultController } from './readable-stream.js';
88
+ export { TransformStreamDefaultController } from './transform-stream.js';
89
+
90
+ // Re-export internals needed by other packages
91
+ export {
92
+ isWritableStream,
93
+ isWritableStreamLocked,
94
+ writableStreamAbort,
95
+ writableStreamClose,
96
+ writableStreamCloseQueuedOrInFlight,
97
+ writableStreamDefaultWriterCloseWithErrorPropagation,
98
+ writableStreamDefaultControllerErrorIfNeeded,
99
+ createWritableStream,
100
+ } from './writable-stream.js';
101
+
102
+ export {
103
+ isReadableStream,
104
+ isReadableStreamLocked,
105
+ readableStreamCancel,
106
+ readableStreamClose,
107
+ readableStreamError,
108
+ readableStreamDefaultControllerClose,
109
+ readableStreamDefaultControllerEnqueue,
110
+ readableStreamDefaultControllerError,
111
+ readableStreamDefaultControllerGetDesiredSize,
112
+ readableStreamDefaultControllerCanCloseOrEnqueue,
113
+ readableStreamDefaultControllerHasBackpressure,
114
+ setupReadableStreamDefaultController,
115
+ createReadableStream,
116
+ } from './readable-stream.js';
117
+
118
+ export {
119
+ isTransformStream,
120
+ isTransformStreamDefaultController,
121
+ } from './transform-stream.js';
122
+
123
+ export default {
124
+ WritableStream: _WritableStream,
125
+ ReadableStream: _ReadableStream,
126
+ TransformStream: _TransformStream,
127
+ ByteLengthQueuingStrategy: _ByteLengthQueuingStrategy,
128
+ CountQueuingStrategy: _CountQueuingStrategy,
129
+ TextEncoderStream: _TextEncoderStream,
130
+ TextDecoderStream: _TextDecoderStream,
131
+ };
@@ -0,0 +1,67 @@
1
+ // WHATWG Streams — ByteLengthQueuingStrategy and CountQueuingStrategy
2
+ // Adapted from refs/node/lib/internal/webstreams/queuingstrategies.js
3
+ // Copyright (c) Node.js contributors. MIT license.
4
+
5
+ const byteSizeFunction = Object.defineProperty(
6
+ (chunk: any) => chunk.byteLength,
7
+ 'name',
8
+ { value: 'size' },
9
+ );
10
+
11
+ const countSizeFunction = Object.defineProperty(
12
+ () => 1,
13
+ 'name',
14
+ { value: 'size' },
15
+ );
16
+
17
+ export class ByteLengthQueuingStrategy {
18
+ #highWaterMark: number;
19
+
20
+ constructor(init: { highWaterMark: number }) {
21
+ if (init == null || typeof init !== 'object') {
22
+ throw new TypeError('init must be an object');
23
+ }
24
+ if (init.highWaterMark === undefined) {
25
+ throw new TypeError('init.highWaterMark is required');
26
+ }
27
+ this.#highWaterMark = +init.highWaterMark;
28
+ }
29
+
30
+ get highWaterMark(): number {
31
+ return this.#highWaterMark;
32
+ }
33
+
34
+ get size(): (chunk: any) => number {
35
+ return byteSizeFunction;
36
+ }
37
+
38
+ get [Symbol.toStringTag]() {
39
+ return 'ByteLengthQueuingStrategy';
40
+ }
41
+ }
42
+
43
+ export class CountQueuingStrategy {
44
+ #highWaterMark: number;
45
+
46
+ constructor(init: { highWaterMark: number }) {
47
+ if (init == null || typeof init !== 'object') {
48
+ throw new TypeError('init must be an object');
49
+ }
50
+ if (init.highWaterMark === undefined) {
51
+ throw new TypeError('init.highWaterMark is required');
52
+ }
53
+ this.#highWaterMark = +init.highWaterMark;
54
+ }
55
+
56
+ get highWaterMark(): number {
57
+ return this.#highWaterMark;
58
+ }
59
+
60
+ get size(): (chunk: any) => number {
61
+ return countSizeFunction;
62
+ }
63
+
64
+ get [Symbol.toStringTag]() {
65
+ return 'CountQueuingStrategy';
66
+ }
67
+ }