@gjsify/stream 0.4.0 → 0.4.3

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/readable.ts DELETED
@@ -1,580 +0,0 @@
1
- // Readable stream — pull-based source with flowing/paused modes.
2
- //
3
- // Reference: refs/node/lib/internal/streams/readable.js
4
- // Reimplemented for GJS using @gjsify/events + microtask scheduling.
5
-
6
- import { nextTick } from '@gjsify/utils';
7
- import type { ReadableOptions } from 'node:stream';
8
-
9
- import { Stream_ } from './stream-base.js';
10
- import { getDefaultHighWaterMark } from './internal/state.js';
11
- import type { ErrCallback } from './internal/types.js';
12
- import type { PipeState } from './utils/pipe.js';
13
- import type { Writable_ } from './writable.js';
14
-
15
- /** Internal readable-side state — exposed via `_readableState` for npm-stream consumers. */
16
- export interface ReadableInternalState {
17
- ended: boolean;
18
- endEmitted: boolean;
19
- reading: boolean;
20
- constructed: boolean;
21
- highWaterMark: number;
22
- objectMode: boolean;
23
- pipes: Writable_[];
24
- }
25
-
26
- /** A stored buffer chunk: string, Buffer, Uint8Array, or any value in objectMode. */
27
- type Chunk = unknown;
28
-
29
- /** A chunk that has a `length` (string, Buffer, Uint8Array). */
30
- interface HasLength {
31
- length: number;
32
- }
33
-
34
- function chunkLength(chunk: Chunk): number {
35
- if (chunk == null) return 1;
36
- const v = (chunk as Partial<HasLength>).length;
37
- return typeof v === 'number' ? v : 1;
38
- }
39
-
40
- /** Slice helper that works for Buffer/Uint8Array/string. */
41
- function sliceChunk(chunk: Chunk, start: number, end?: number): Chunk {
42
- if (typeof chunk === 'string') {
43
- return end === undefined ? chunk.slice(start) : chunk.slice(start, end);
44
- }
45
- // Buffer.prototype.slice and Uint8Array.prototype.slice both share this signature.
46
- const slicer = (chunk as { slice?: (s: number, e?: number) => unknown }).slice;
47
- return typeof slicer === 'function' ? slicer.call(chunk, start, end) : chunk;
48
- }
49
-
50
- export class Readable_ extends Stream_ {
51
- readable = true;
52
- readableFlowing: boolean | null = null;
53
- readableLength = 0;
54
- readableHighWaterMark: number;
55
- readableEncoding: string | null;
56
- readableObjectMode: boolean;
57
- readableEnded = false;
58
- readableAborted = false;
59
- destroyed = false;
60
-
61
- /** @internal Tracked pipe destinations for unpipe. */
62
- _pipeDests: PipeState[] = [];
63
-
64
- /** @internal The internal data buffer. */
65
- private _buffer: Chunk[] = [];
66
-
67
- /** @internal Mirrors Node's `_readableState`; exposed for npm-stream consumers. */
68
- _readableState: ReadableInternalState = {
69
- ended: false,
70
- endEmitted: false,
71
- reading: false,
72
- constructed: true,
73
- highWaterMark: 0,
74
- objectMode: false,
75
- pipes: [],
76
- };
77
-
78
- /** @internal The error a `destroy(err)` call stored before the 'error' event fired. */
79
- _err?: Error;
80
-
81
- private _readablePending = false;
82
- private _readImpl: ((this: Readable_, size: number) => void) | undefined;
83
- private _destroyImpl: ((this: Readable_, error: Error | null, cb: ErrCallback) => void) | undefined;
84
- private _constructImpl: ((this: Readable_, cb: ErrCallback) => void) | undefined;
85
-
86
- constructor(opts?: ReadableOptions) {
87
- super(opts);
88
- this.readableHighWaterMark = opts?.highWaterMark ?? getDefaultHighWaterMark(opts?.objectMode ?? false);
89
- this.readableEncoding = opts?.encoding ?? null;
90
- this.readableObjectMode = opts?.objectMode ?? false;
91
- this._readableState.highWaterMark = this.readableHighWaterMark;
92
- this._readableState.objectMode = this.readableObjectMode;
93
- if (opts?.read) this._readImpl = opts.read as unknown as (this: Readable_, size: number) => void;
94
- if (opts?.destroy) this._destroyImpl = opts.destroy as unknown as (this: Readable_, e: Error | null, cb: ErrCallback) => void;
95
- if (opts?.construct) this._constructImpl = opts.construct as unknown as (this: Readable_, cb: ErrCallback) => void;
96
-
97
- // Call _construct if provided via options or overridden by subclass
98
- const hasConstruct = this._constructImpl || this._construct !== Readable_.prototype._construct;
99
- if (hasConstruct) {
100
- this._readableState.constructed = false;
101
- nextTick(() => {
102
- this._construct((err) => {
103
- this._readableState.constructed = true;
104
- if (err) {
105
- this.destroy(err);
106
- } else {
107
- // If data was requested before construct finished, start reading
108
- if (this.readableFlowing === true) {
109
- this._flow();
110
- }
111
- }
112
- });
113
- });
114
- }
115
- }
116
-
117
- _construct(callback: ErrCallback): void {
118
- if (this._constructImpl) {
119
- this._constructImpl.call(this, callback);
120
- } else {
121
- callback();
122
- }
123
- }
124
-
125
- _read(_size: number): void {
126
- if (this._readImpl) {
127
- this._readImpl.call(this, _size);
128
- }
129
- }
130
-
131
- read(size?: number): unknown {
132
- // Don't read until constructed
133
- if (!this._readableState.constructed) return null;
134
-
135
- if (this._buffer.length === 0) {
136
- if (this._readableState.ended) return null;
137
- this._readableState.reading = true;
138
- this._read(size ?? this.readableHighWaterMark);
139
- this._readableState.reading = false;
140
- }
141
-
142
- if (this._buffer.length === 0) return null;
143
-
144
- if (size === 0) return null;
145
-
146
- if (this.readableObjectMode) {
147
- if (size === undefined) {
148
- const chunk = this._buffer.shift();
149
- this.readableLength -= 1;
150
- if (this._readableState.ended && this._buffer.length === 0 && !this._readableState.endEmitted) {
151
- this._emitEnd();
152
- }
153
- return chunk;
154
- }
155
- // In objectMode, size means number of objects
156
- if (size > this.readableLength) return null;
157
- const chunk = this._buffer.shift();
158
- this.readableLength -= 1;
159
- return chunk;
160
- }
161
-
162
- // Byte mode: compute total buffered bytes
163
- if (size !== undefined && size !== null) {
164
- if (size > this.readableLength) return null;
165
- // Partial read: extract exactly `size` bytes from buffer
166
- return this._readBytes(size);
167
- }
168
-
169
- // Read all buffered data
170
- const result = this._buffer.splice(0);
171
- this.readableLength = 0;
172
- if (this._readableState.ended && this._buffer.length === 0 && !this._readableState.endEmitted) {
173
- this._emitEnd();
174
- }
175
- if (result.length === 1) return result[0];
176
- if (result.length === 0) return null;
177
- // Concatenate: strings with join, buffers with Buffer.concat
178
- if (typeof result[0] === 'string') return (result as string[]).join('');
179
- const BufCtor = (globalThis as { Buffer?: { concat?: (parts: unknown[]) => unknown } }).Buffer;
180
- return BufCtor?.concat ? BufCtor.concat(result) : result;
181
- }
182
-
183
- /** @internal Extract exactly `size` bytes from the internal buffer. */
184
- private _readBytes(size: number): unknown {
185
- let collected = 0;
186
- const parts: Chunk[] = [];
187
- while (collected < size && this._buffer.length > 0) {
188
- const chunk = this._buffer[0];
189
- const chunkLen = chunkLength(chunk);
190
- if (collected + chunkLen <= size) {
191
- // Take the whole chunk
192
- parts.push(this._buffer.shift()!);
193
- collected += chunkLen;
194
- this.readableLength -= chunkLen;
195
- } else {
196
- // Split the chunk
197
- const needed = size - collected;
198
- parts.push(sliceChunk(chunk, 0, needed));
199
- this._buffer[0] = sliceChunk(chunk, needed);
200
- this.readableLength -= needed;
201
- collected += needed;
202
- }
203
- }
204
- if (parts.length === 1) return parts[0];
205
- const BufCtor = (globalThis as { Buffer?: { concat?: (parts: unknown[]) => unknown } }).Buffer;
206
- return BufCtor?.concat ? BufCtor.concat(parts) : parts;
207
- }
208
-
209
- push(chunk: unknown, _encoding?: string): boolean {
210
- if (chunk === null) {
211
- this._readableState.ended = true;
212
- this.readableEnded = true;
213
- if (this._buffer.length === 0 && !this._readableState.endEmitted) {
214
- nextTick(() => this._emitEnd());
215
- }
216
- // Emit 'readable' for listeners waiting on EOF with buffered data
217
- this._scheduleReadable();
218
- return false;
219
- }
220
-
221
- // Validate chunk type for non-objectMode streams (Node.js ERR_INVALID_ARG_TYPE).
222
- // Accept string, Buffer, or any ArrayBufferView — the latter covers Uint8Array
223
- // and TypedArrays from any realm (GJS vs host bundle), avoiding cross-realm
224
- // `instanceof Uint8Array` mismatches that would otherwise reject real Buffers.
225
- if (!this.readableObjectMode) {
226
- const isValid = typeof chunk === 'string' || ArrayBuffer.isView(chunk);
227
- if (!isValid) {
228
- const err = Object.assign(
229
- new TypeError(`Invalid non-string/buffer chunk type: ${typeof chunk}`),
230
- { code: 'ERR_INVALID_ARG_TYPE' }
231
- );
232
- nextTick(() => this.emit('error', err));
233
- return false;
234
- }
235
- }
236
-
237
- this._buffer.push(chunk);
238
- this.readableLength += this.readableObjectMode ? 1 : chunkLength(chunk);
239
-
240
- // In flowing mode, schedule draining (unless already flowing)
241
- if (this.readableFlowing && !this._flowing) {
242
- nextTick(() => this._flow());
243
- }
244
-
245
- // In non-flowing mode, emit 'readable' to notify data is available
246
- if (this.readableFlowing !== true) {
247
- this._scheduleReadable();
248
- }
249
-
250
- return this.readableLength < this.readableHighWaterMark;
251
- }
252
-
253
- /** Emit 'end' followed by 'close' (matches Node.js autoDestroy behavior). */
254
- private _emitEnd(): void {
255
- if (this._readableState.endEmitted) return;
256
- this._readableState.endEmitted = true;
257
- this.emit('end');
258
- nextTick(() => this._autoClose());
259
- }
260
-
261
- /** Override in subclasses to suppress automatic 'close' after 'end'. */
262
- protected _autoClose(): void {
263
- this.emit('close');
264
- }
265
-
266
- /** Schedule a single 'readable' event per microtask cycle (deduplicates multiple pushes). */
267
- private _scheduleReadable(): void {
268
- if (this._readablePending || this.listenerCount('readable') === 0) return;
269
- this._readablePending = true;
270
- nextTick(() => {
271
- this._readablePending = false;
272
- if (!this.destroyed) this.emit('readable');
273
- });
274
- }
275
-
276
- on(event: string | symbol, listener: (...args: unknown[]) => void): this {
277
- super.on(event, listener);
278
- // Attaching a 'data' listener switches to flowing mode (like Node.js)
279
- if (event === 'data' && this.readableFlowing !== false) {
280
- this.resume();
281
- }
282
- // Attaching a 'readable' listener: if data is already buffered, schedule event
283
- if (event === 'readable' && (this._buffer.length > 0 || this._readableState.ended)) {
284
- this._scheduleReadable();
285
- }
286
- return this;
287
- }
288
-
289
- unshift(chunk: unknown): void {
290
- this._buffer.unshift(chunk);
291
- this.readableLength += this.readableObjectMode ? 1 : chunkLength(chunk);
292
- }
293
-
294
- setEncoding(encoding: string): this {
295
- this.readableEncoding = encoding;
296
- return this;
297
- }
298
-
299
- pause(): this {
300
- this.readableFlowing = false;
301
- this.emit('pause');
302
- return this;
303
- }
304
-
305
- resume(): this {
306
- if (this.readableFlowing !== true) {
307
- this.readableFlowing = true;
308
- this.emit('resume');
309
- // Start flowing: drain buffered data and call _read
310
- if (this._readableState.constructed) {
311
- this._flow();
312
- }
313
- }
314
- return this;
315
- }
316
-
317
- private _flowing = false;
318
-
319
- private _flow(): void {
320
- if (this.readableFlowing !== true || this._flowing || this.destroyed) return;
321
- if (!this._readableState.constructed) return;
322
- this._flowing = true;
323
-
324
- try {
325
- // Drain buffered data synchronously (like Node.js flow())
326
- while (this._buffer.length > 0 && this.readableFlowing && !this.destroyed) {
327
- let chunk = this._buffer.shift()!;
328
- this.readableLength -= this.readableObjectMode ? 1 : chunkLength(chunk);
329
- // Decode to string when setEncoding was called
330
- if (this.readableEncoding && typeof chunk !== 'string') {
331
- const BufCtor = (globalThis as { Buffer?: { isBuffer?: (v: unknown) => boolean } }).Buffer;
332
- if (BufCtor?.isBuffer && BufCtor.isBuffer(chunk)) {
333
- chunk = (chunk as { toString: (enc: string) => string }).toString(this.readableEncoding);
334
- } else if (chunk instanceof Uint8Array) {
335
- chunk = new TextDecoder(this.readableEncoding).decode(chunk);
336
- }
337
- }
338
- this.emit('data', chunk);
339
- }
340
-
341
- if (this.destroyed) return;
342
-
343
- // If ended and buffer drained, emit end
344
- if (this._readableState.ended && this._buffer.length === 0 && !this._readableState.endEmitted) {
345
- nextTick(() => this._emitEnd());
346
- return;
347
- }
348
-
349
- // Call _read to get more data (may push synchronously)
350
- if (!this._readableState.ended && !this._readableState.reading && !this.destroyed) {
351
- this._readableState.reading = true;
352
- this._read(this.readableHighWaterMark);
353
- this._readableState.reading = false;
354
- }
355
- } finally {
356
- this._flowing = false;
357
- }
358
-
359
- // After _read, if new data was pushed, schedule another flow
360
- if (this._buffer.length > 0 && this.readableFlowing && !this.destroyed) {
361
- nextTick(() => this._flow());
362
- }
363
- }
364
-
365
- isPaused(): boolean {
366
- return this.readableFlowing === false;
367
- }
368
-
369
- unpipe(destination?: Writable_): this {
370
- if (!destination) {
371
- // Remove all piped destinations
372
- for (const state of this._pipeDests) {
373
- state.cleanup();
374
- state.dest.emit('unpipe', this);
375
- }
376
- this._pipeDests = [];
377
- this._readableState.pipes = [];
378
- this.readableFlowing = false;
379
- } else {
380
- const idx = this._pipeDests.findIndex(s => s.dest === destination);
381
- if (idx !== -1) {
382
- const state = this._pipeDests[idx];
383
- state.cleanup();
384
- this._pipeDests.splice(idx, 1);
385
- const pipeIdx = this._readableState.pipes.indexOf(destination);
386
- if (pipeIdx !== -1) this._readableState.pipes.splice(pipeIdx, 1);
387
- destination.emit('unpipe', this);
388
- if (this._pipeDests.length === 0) {
389
- this.readableFlowing = false;
390
- }
391
- }
392
- }
393
- return this;
394
- }
395
-
396
- _destroy(error: Error | null, callback: ErrCallback): void {
397
- if (this._destroyImpl) {
398
- this._destroyImpl.call(this, error, callback);
399
- } else {
400
- callback(error ?? undefined);
401
- }
402
- }
403
-
404
- destroy(error?: Error): this {
405
- if (this.destroyed) return this;
406
- this.destroyed = true;
407
- this.readable = false;
408
- this.readableAborted = !this.readableEnded;
409
- // Store the error so finished() can retrieve it if called after destroy() but before 'error' fires
410
- if (error) this._err = error;
411
-
412
- const cb: ErrCallback = (err) => {
413
- // Emit error and close in separate nextTick calls (matches Node.js behavior)
414
- // so an unhandled error doesn't prevent 'close' from firing
415
- if (err) nextTick(() => this.emit('error', err));
416
- nextTick(() => this.emit('close'));
417
- };
418
-
419
- // Dispatch virtually ONLY when the user overrode _destroy on the instance
420
- // (e.g. tests: `stream._destroy = fn`). Do NOT call a subclass prototype
421
- // _destroy: net.Socket's prototype `_destroy` synchronously cancels in-flight
422
- // Gio I/O and would break tests that call destroy() during pending writes.
423
- // The opts.destroy path still runs via _destroyImpl as before.
424
- if (Object.prototype.hasOwnProperty.call(this, '_destroy')) {
425
- (this as Readable_)._destroy(error ?? null, cb);
426
- } else if (this._destroyImpl) {
427
- this._destroyImpl.call(this, error ?? null, cb);
428
- } else {
429
- cb(error);
430
- }
431
-
432
- return this;
433
- }
434
-
435
- /**
436
- * Converts this Node.js Readable to a Web ReadableStream.
437
- * Used by @hono/node-server to bridge Node.js HTTP → Web Standard Request.
438
- */
439
- static toWeb(nodeReadable: Readable_): ReadableStream<Uint8Array> {
440
- return new ReadableStream({
441
- start(controller) {
442
- nodeReadable.on('data', (chunk: unknown) => {
443
- if (typeof chunk === 'string') {
444
- controller.enqueue(new TextEncoder().encode(chunk));
445
- } else if (chunk instanceof Uint8Array) {
446
- controller.enqueue(chunk);
447
- } else if (chunk && typeof (chunk as Partial<HasLength>).length === 'number') {
448
- controller.enqueue(new Uint8Array(chunk as ArrayLike<number>));
449
- }
450
- });
451
- nodeReadable.on('end', () => {
452
- controller.close();
453
- });
454
- nodeReadable.on('error', (err: Error) => {
455
- controller.error(err);
456
- });
457
- },
458
- cancel() {
459
- nodeReadable.destroy();
460
- },
461
- });
462
- }
463
-
464
- /**
465
- * Creates a Node.js Readable from a Web ReadableStream.
466
- */
467
- static fromWeb(webStream: ReadableStream<Uint8Array>, options?: ReadableOptions): Readable_ {
468
- const reader = webStream.getReader();
469
- return new Readable_({
470
- ...options,
471
- read() {
472
- reader.read().then(
473
- ({ done, value }) => {
474
- if (done) {
475
- this.push(null);
476
- } else {
477
- this.push(value);
478
- }
479
- },
480
- (err) => {
481
- this.destroy(err);
482
- },
483
- );
484
- },
485
- destroy(error, callback) {
486
- reader.cancel(error?.message).then(() => callback(null), callback);
487
- },
488
- });
489
- }
490
-
491
- [Symbol.asyncIterator](): AsyncIterableIterator<unknown> {
492
- const readable = this;
493
- const buffer: unknown[] = [];
494
- let done = false;
495
- let error: Error | null = null;
496
- let waitingResolve: ((value: IteratorResult<unknown>) => void) | null = null;
497
- let waitingReject: ((reason: unknown) => void) | null = null;
498
-
499
- readable.on('data', (chunk: unknown) => {
500
- if (waitingResolve) {
501
- const resolve = waitingResolve;
502
- waitingResolve = null;
503
- waitingReject = null;
504
- resolve({ value: chunk, done: false });
505
- } else {
506
- buffer.push(chunk);
507
- }
508
- });
509
-
510
- readable.on('end', () => {
511
- done = true;
512
- if (waitingResolve) {
513
- const resolve = waitingResolve;
514
- waitingResolve = null;
515
- waitingReject = null;
516
- resolve({ value: undefined, done: true });
517
- }
518
- });
519
-
520
- readable.on('error', (err: Error) => {
521
- error = err;
522
- done = true;
523
- if (waitingReject) {
524
- const reject = waitingReject;
525
- waitingResolve = null;
526
- waitingReject = null;
527
- reject(err);
528
- }
529
- });
530
-
531
- return {
532
- next(): Promise<IteratorResult<unknown>> {
533
- if (error) return Promise.reject(error);
534
- if (buffer.length > 0) return Promise.resolve({ value: buffer.shift(), done: false });
535
- if (done) return Promise.resolve({ value: undefined, done: true });
536
- return new Promise((resolve, reject) => {
537
- waitingResolve = resolve;
538
- waitingReject = reject;
539
- });
540
- },
541
- return(): Promise<IteratorResult<unknown>> {
542
- readable.destroy();
543
- return Promise.resolve({ value: undefined, done: true });
544
- },
545
- [Symbol.asyncIterator]() { return this; }
546
- };
547
- }
548
-
549
- static from(iterable: Iterable<unknown> | AsyncIterable<unknown>, opts?: ReadableOptions): Readable_ {
550
- const readable = new Readable_({
551
- objectMode: true,
552
- ...opts,
553
- read() {}
554
- });
555
-
556
- // Buffer, Uint8Array, and strings should be pushed as a single chunk,
557
- // not iterated element-by-element (matching Node.js Readable.from behavior)
558
- if (typeof iterable === 'string' || ArrayBuffer.isView(iterable)) {
559
- readable.push(iterable);
560
- readable.push(null);
561
- return readable;
562
- }
563
-
564
- (async () => {
565
- try {
566
- for await (const chunk of iterable as AsyncIterable<unknown>) {
567
- if (!readable.push(chunk)) {
568
- // Backpressure — wait for drain
569
- await new Promise<void>(resolve => readable.once('drain', resolve));
570
- }
571
- }
572
- readable.push(null);
573
- } catch (err) {
574
- readable.destroy(err as Error);
575
- }
576
- })();
577
-
578
- return readable;
579
- }
580
- }
@@ -1,28 +0,0 @@
1
- // Ambient module augmentation for spec files only.
2
- //
3
- // White-box tests probe internal stream state (`_readableState`, `_writableState`)
4
- // that exists on real Node.js streams but is not part of `@types/node`. This file
5
- // is included by `tsconfig.spec.json` (not `tsconfig.json`), so the augmented
6
- // shape is visible to specs without leaking into the public package types.
7
-
8
- declare module 'node:stream' {
9
- interface Readable {
10
- _readableState: {
11
- highWaterMark: number;
12
- objectMode: boolean;
13
- pipes: Writable[];
14
- ended?: boolean;
15
- endEmitted?: boolean;
16
- reading?: boolean;
17
- constructed?: boolean;
18
- };
19
- }
20
- interface Writable {
21
- _writableState: {
22
- highWaterMark: number;
23
- objectMode: boolean;
24
- };
25
- }
26
- }
27
-
28
- export {};
@@ -1,37 +0,0 @@
1
- // Base Stream class — shared root of Readable, Writable, Duplex, Transform.
2
- //
3
- // Reference: refs/node/lib/internal/streams/legacy.js (Stream as EventEmitter+pipe)
4
- // Reimplemented for GJS using @gjsify/events.
5
-
6
- import { EventEmitter } from '@gjsify/events';
7
-
8
- import type { StreamOptions } from './internal/types.js';
9
- import type { Writable_ } from './writable.js';
10
-
11
- /**
12
- * Late-bound pipe implementation. Wired by `./utils/pipe.ts` when it loads —
13
- * doing this lazily breaks what would otherwise be a top-level import cycle:
14
- * stream-base → pipe → readable → stream-base.
15
- *
16
- * GJS / esbuild's `__esmMin` wrapper evaluates modules eagerly on first import
17
- * but stops at the cycle boundary, so `Readable_` would be `undefined` at the
18
- * point `Stream_` is declared (`class Readable_ extends Stream_` then fails
19
- * with "class heritage … is not an object or null"). The hook is set after
20
- * both classes finish initializing.
21
- */
22
- let pipeImpl: <T extends Writable_>(source: Stream_, dest: T, opts?: { end?: boolean }) => T;
23
-
24
- /** @internal Wired by ./utils/pipe.js (side-effect import in ./readable.ts). */
25
- export function _setPipeImpl(fn: typeof pipeImpl): void {
26
- pipeImpl = fn;
27
- }
28
-
29
- export class Stream_ extends EventEmitter {
30
- constructor(opts?: StreamOptions) {
31
- super(opts);
32
- }
33
-
34
- pipe<T extends Writable_>(destination: T, options?: { end?: boolean }): T {
35
- return pipeImpl(this, destination, options);
36
- }
37
- }
package/src/test.mts DELETED
@@ -1,26 +0,0 @@
1
- import '@gjsify/node-globals/register/process';
2
- import '@gjsify/node-globals/register/buffer';
3
- import '@gjsify/node-globals/register/timers';
4
- import '@gjsify/node-globals/register/microtask';
5
- import 'abort-controller/register'; // register AbortController/AbortSignal globals on GJS (no-op on Node)
6
- import { run } from '@gjsify/unit';
7
-
8
- import testSuite from './index.spec.js';
9
- import callableTestSuite from './callable.spec.js';
10
- import consumersTestSuite from './consumers/index.spec.js';
11
- import promisesTestSuite from './promises/index.spec.js';
12
- import edgeCasesTestSuite from './edge-cases.spec.js';
13
- import transformTestSuite from './transform.spec.js';
14
- import pipeTestSuite from './pipe.spec.js';
15
- import inheritanceTestSuite from './inheritance.spec.js';
16
-
17
- run({
18
- testSuite,
19
- callableTestSuite,
20
- consumersTestSuite,
21
- promisesTestSuite,
22
- edgeCasesTestSuite,
23
- transformTestSuite,
24
- pipeTestSuite,
25
- inheritanceTestSuite,
26
- });