@gjsify/web-streams 0.3.13 → 0.3.14

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.
@@ -1,7 +1,11 @@
1
- import { ByteLengthQueuingStrategy, CountQueuingStrategy } from "../index.js";
1
+ import { ByteLengthQueuingStrategy as _ByteLengthQueuingStrategy, CountQueuingStrategy as _CountQueuingStrategy } from "../index.js";
2
+
3
+ //#region src/register/queuing.ts
2
4
  if (typeof globalThis.ByteLengthQueuingStrategy === "undefined") {
3
- globalThis.ByteLengthQueuingStrategy = ByteLengthQueuingStrategy;
5
+ globalThis.ByteLengthQueuingStrategy = _ByteLengthQueuingStrategy;
4
6
  }
5
7
  if (typeof globalThis.CountQueuingStrategy === "undefined") {
6
- globalThis.CountQueuingStrategy = CountQueuingStrategy;
8
+ globalThis.CountQueuingStrategy = _CountQueuingStrategy;
7
9
  }
10
+
11
+ //#endregion
@@ -1,12 +1,16 @@
1
- import { ReadableStream } from "../index.js";
1
+ import { ReadableStream as _ReadableStream } from "../index.js";
2
+
3
+ //#region src/register/readable.ts
2
4
  function isNativeStreamUsable(Ctor, method) {
3
- try {
4
- if (typeof Ctor !== "function") return false;
5
- return typeof Ctor.prototype[method] === "function";
6
- } catch {
7
- return false;
8
- }
5
+ try {
6
+ if (typeof Ctor !== "function") return false;
7
+ return typeof Ctor.prototype[method] === "function";
8
+ } catch {
9
+ return false;
10
+ }
9
11
  }
10
12
  if (!isNativeStreamUsable(globalThis.ReadableStream, "getReader")) {
11
- globalThis.ReadableStream = ReadableStream;
13
+ globalThis.ReadableStream = _ReadableStream;
12
14
  }
15
+
16
+ //#endregion
@@ -1,7 +1,11 @@
1
- import { TextEncoderStream, TextDecoderStream } from "../index.js";
1
+ import { TextDecoderStream as _TextDecoderStream, TextEncoderStream as _TextEncoderStream } from "../index.js";
2
+
3
+ //#region src/register/text-streams.ts
2
4
  if (typeof globalThis.TextEncoderStream === "undefined") {
3
- globalThis.TextEncoderStream = TextEncoderStream;
5
+ globalThis.TextEncoderStream = _TextEncoderStream;
4
6
  }
5
7
  if (typeof globalThis.TextDecoderStream === "undefined") {
6
- globalThis.TextDecoderStream = TextDecoderStream;
8
+ globalThis.TextDecoderStream = _TextDecoderStream;
7
9
  }
10
+
11
+ //#endregion
@@ -1,12 +1,16 @@
1
- import { TransformStream } from "../index.js";
1
+ import { TransformStream as _TransformStream } from "../index.js";
2
+
3
+ //#region src/register/transform.ts
2
4
  function isNativeStreamUsable(Ctor, method) {
3
- try {
4
- if (typeof Ctor !== "function") return false;
5
- return typeof Ctor.prototype[method] === "function";
6
- } catch {
7
- return false;
8
- }
5
+ try {
6
+ if (typeof Ctor !== "function") return false;
7
+ return typeof Ctor.prototype[method] === "function";
8
+ } catch {
9
+ return false;
10
+ }
9
11
  }
10
12
  if (!isNativeStreamUsable(globalThis.TransformStream, "readable")) {
11
- globalThis.TransformStream = TransformStream;
13
+ globalThis.TransformStream = _TransformStream;
12
14
  }
15
+
16
+ //#endregion
@@ -1,12 +1,16 @@
1
- import { WritableStream } from "../index.js";
1
+ import { WritableStream as _WritableStream } from "../index.js";
2
+
3
+ //#region src/register/writable.ts
2
4
  function isNativeStreamUsable(Ctor, method) {
3
- try {
4
- if (typeof Ctor !== "function") return false;
5
- return typeof Ctor.prototype[method] === "function";
6
- } catch {
7
- return false;
8
- }
5
+ try {
6
+ if (typeof Ctor !== "function") return false;
7
+ return typeof Ctor.prototype[method] === "function";
8
+ } catch {
9
+ return false;
10
+ }
9
11
  }
10
12
  if (!isNativeStreamUsable(globalThis.WritableStream, "getWriter")) {
11
- globalThis.WritableStream = WritableStream;
13
+ globalThis.WritableStream = _WritableStream;
12
14
  }
15
+
16
+ //#endregion
@@ -1,126 +1,141 @@
1
1
  import { TransformStream } from "./transform-stream.js";
2
+
3
+ //#region src/text-decoder-stream.ts
4
+ /** Check if TextDecoder supports the `stream` option */
2
5
  function hasStreamingSupport() {
3
- try {
4
- const td = new TextDecoder();
5
- td.decode(new Uint8Array([195]), { stream: true });
6
- return true;
7
- } catch {
8
- return false;
9
- }
6
+ try {
7
+ const td = new TextDecoder();
8
+ td.decode(new Uint8Array([195]), { stream: true });
9
+ return true;
10
+ } catch {
11
+ return false;
12
+ }
10
13
  }
11
14
  const supportsStreaming = hasStreamingSupport();
15
+ /**
16
+ * For UTF-8 without streaming TextDecoder support:
17
+ * Determine how many bytes at the end of `buf` form an incomplete
18
+ * multi-byte sequence. Returns 0 if the buffer ends on a complete character.
19
+ */
12
20
  function incompleteUtf8Tail(buf) {
13
- const len = buf.length;
14
- if (len === 0) return 0;
15
- for (let i = 1; i <= Math.min(3, len); i++) {
16
- const b = buf[len - i];
17
- if ((b & 128) === 0) {
18
- return 0;
19
- }
20
- if ((b & 192) !== 128) {
21
- let expectedLen;
22
- if ((b & 224) === 192) expectedLen = 2;
23
- else if ((b & 240) === 224) expectedLen = 3;
24
- else if ((b & 248) === 240) expectedLen = 4;
25
- else return 0;
26
- if (i < expectedLen) {
27
- return i;
28
- }
29
- return 0;
30
- }
31
- }
32
- return 0;
33
- }
34
- class TextDecoderStream {
35
- #decoder;
36
- #transform;
37
- constructor(label, options) {
38
- this.#decoder = new TextDecoder(label, options);
39
- if (supportsStreaming) {
40
- this.#transform = new TransformStream({
41
- transform: (chunk, controller) => {
42
- const bytes = toUint8Array(chunk);
43
- const decoded = this.#decoder.decode(bytes, { stream: true });
44
- if (decoded) {
45
- controller.enqueue(decoded);
46
- }
47
- },
48
- flush: (controller) => {
49
- const final = this.#decoder.decode();
50
- if (final) {
51
- controller.enqueue(final);
52
- }
53
- },
54
- cancel: () => {
55
- this.#decoder.decode();
56
- }
57
- });
58
- } else {
59
- let pendingBytes = new Uint8Array(0);
60
- this.#transform = new TransformStream({
61
- transform: (chunk, controller) => {
62
- const incoming = toUint8Array(chunk);
63
- let combined;
64
- if (pendingBytes.length > 0) {
65
- combined = new Uint8Array(pendingBytes.length + incoming.length);
66
- combined.set(pendingBytes, 0);
67
- combined.set(incoming, pendingBytes.length);
68
- } else {
69
- combined = incoming;
70
- }
71
- const tail = incompleteUtf8Tail(combined);
72
- let decodable;
73
- if (tail > 0) {
74
- decodable = combined.slice(0, combined.length - tail);
75
- pendingBytes = combined.slice(combined.length - tail);
76
- } else {
77
- decodable = combined;
78
- pendingBytes = new Uint8Array(0);
79
- }
80
- if (decodable.length > 0) {
81
- const decoded = this.#decoder.decode(decodable);
82
- if (decoded) {
83
- controller.enqueue(decoded);
84
- }
85
- }
86
- },
87
- flush: (controller) => {
88
- if (pendingBytes.length > 0) {
89
- const decoded = this.#decoder.decode(pendingBytes);
90
- if (decoded) {
91
- controller.enqueue(decoded);
92
- }
93
- pendingBytes = new Uint8Array(0);
94
- }
95
- },
96
- cancel: () => {
97
- pendingBytes = new Uint8Array(0);
98
- }
99
- });
100
- }
101
- }
102
- get encoding() {
103
- return this.#decoder.encoding;
104
- }
105
- get fatal() {
106
- return this.#decoder.fatal;
107
- }
108
- get ignoreBOM() {
109
- return this.#decoder.ignoreBOM;
110
- }
111
- get readable() {
112
- return this.#transform.readable;
113
- }
114
- get writable() {
115
- return this.#transform.writable;
116
- }
21
+ const len = buf.length;
22
+ if (len === 0) return 0;
23
+ for (let i = 1; i <= Math.min(3, len); i++) {
24
+ const b = buf[len - i];
25
+ if ((b & 128) === 0) {
26
+ return 0;
27
+ }
28
+ if ((b & 192) !== 128) {
29
+ let expectedLen;
30
+ if ((b & 224) === 192) expectedLen = 2;
31
+ else if ((b & 240) === 224) expectedLen = 3;
32
+ else if ((b & 248) === 240) expectedLen = 4;
33
+ else return 0;
34
+ if (i < expectedLen) {
35
+ return i;
36
+ }
37
+ return 0;
38
+ }
39
+ }
40
+ return 0;
117
41
  }
42
+ /**
43
+ * TextDecoderStream decodes a stream of bytes into strings.
44
+ *
45
+ * Uses TextDecoder with `stream: true` when available (Node.js, browsers).
46
+ * On GJS where `stream` option is not supported, manually buffers incomplete
47
+ * multi-byte UTF-8 sequences across chunks.
48
+ */
49
+ var TextDecoderStream = class {
50
+ #decoder;
51
+ #transform;
52
+ constructor(label, options) {
53
+ this.#decoder = new TextDecoder(label, options);
54
+ if (supportsStreaming) {
55
+ this.#transform = new TransformStream({
56
+ transform: (chunk, controller) => {
57
+ const bytes = toUint8Array(chunk);
58
+ const decoded = this.#decoder.decode(bytes, { stream: true });
59
+ if (decoded) {
60
+ controller.enqueue(decoded);
61
+ }
62
+ },
63
+ flush: (controller) => {
64
+ const final = this.#decoder.decode();
65
+ if (final) {
66
+ controller.enqueue(final);
67
+ }
68
+ },
69
+ cancel: () => {
70
+ this.#decoder.decode();
71
+ }
72
+ });
73
+ } else {
74
+ let pendingBytes = new Uint8Array(0);
75
+ this.#transform = new TransformStream({
76
+ transform: (chunk, controller) => {
77
+ const incoming = toUint8Array(chunk);
78
+ let combined;
79
+ if (pendingBytes.length > 0) {
80
+ combined = new Uint8Array(pendingBytes.length + incoming.length);
81
+ combined.set(pendingBytes, 0);
82
+ combined.set(incoming, pendingBytes.length);
83
+ } else {
84
+ combined = incoming;
85
+ }
86
+ const tail = incompleteUtf8Tail(combined);
87
+ let decodable;
88
+ if (tail > 0) {
89
+ decodable = combined.slice(0, combined.length - tail);
90
+ pendingBytes = combined.slice(combined.length - tail);
91
+ } else {
92
+ decodable = combined;
93
+ pendingBytes = new Uint8Array(0);
94
+ }
95
+ if (decodable.length > 0) {
96
+ const decoded = this.#decoder.decode(decodable);
97
+ if (decoded) {
98
+ controller.enqueue(decoded);
99
+ }
100
+ }
101
+ },
102
+ flush: (controller) => {
103
+ if (pendingBytes.length > 0) {
104
+ const decoded = this.#decoder.decode(pendingBytes);
105
+ if (decoded) {
106
+ controller.enqueue(decoded);
107
+ }
108
+ pendingBytes = new Uint8Array(0);
109
+ }
110
+ },
111
+ cancel: () => {
112
+ pendingBytes = new Uint8Array(0);
113
+ }
114
+ });
115
+ }
116
+ }
117
+ get encoding() {
118
+ return this.#decoder.encoding;
119
+ }
120
+ get fatal() {
121
+ return this.#decoder.fatal;
122
+ }
123
+ get ignoreBOM() {
124
+ return this.#decoder.ignoreBOM;
125
+ }
126
+ get readable() {
127
+ return this.#transform.readable;
128
+ }
129
+ get writable() {
130
+ return this.#transform.writable;
131
+ }
132
+ };
118
133
  function toUint8Array(chunk) {
119
- if (chunk instanceof Uint8Array) return chunk;
120
- if (chunk instanceof ArrayBuffer) return new Uint8Array(chunk);
121
- if (ArrayBuffer.isView(chunk)) return new Uint8Array(chunk.buffer, chunk.byteOffset, chunk.byteLength);
122
- throw new TypeError("chunk must be a BufferSource");
134
+ if (chunk instanceof Uint8Array) return chunk;
135
+ if (chunk instanceof ArrayBuffer) return new Uint8Array(chunk);
136
+ if (ArrayBuffer.isView(chunk)) return new Uint8Array(chunk.buffer, chunk.byteOffset, chunk.byteLength);
137
+ throw new TypeError("chunk must be a BufferSource");
123
138
  }
124
- export {
125
- TextDecoderStream
126
- };
139
+
140
+ //#endregion
141
+ export { TextDecoderStream };
@@ -1,46 +1,60 @@
1
1
  import { TransformStream } from "./transform-stream.js";
2
- class TextEncoderStream {
3
- #pendingHighSurrogate = null;
4
- #encoder = new TextEncoder();
5
- #transform;
6
- constructor() {
7
- this.#transform = new TransformStream({
8
- transform: (chunk, controller) => {
9
- chunk = String(chunk);
10
- if (chunk === "") {
11
- return;
12
- }
13
- if (this.#pendingHighSurrogate !== null) {
14
- chunk = this.#pendingHighSurrogate + chunk;
15
- }
16
- const lastCodeUnit = chunk.charCodeAt(chunk.length - 1);
17
- if (55296 <= lastCodeUnit && lastCodeUnit <= 56319) {
18
- this.#pendingHighSurrogate = chunk.slice(-1);
19
- chunk = chunk.slice(0, -1);
20
- } else {
21
- this.#pendingHighSurrogate = null;
22
- }
23
- if (chunk) {
24
- controller.enqueue(this.#encoder.encode(chunk));
25
- }
26
- },
27
- flush: (controller) => {
28
- if (this.#pendingHighSurrogate !== null) {
29
- controller.enqueue(new Uint8Array([239, 191, 189]));
30
- }
31
- }
32
- });
33
- }
34
- get encoding() {
35
- return "utf-8";
36
- }
37
- get readable() {
38
- return this.#transform.readable;
39
- }
40
- get writable() {
41
- return this.#transform.writable;
42
- }
43
- }
44
- export {
45
- TextEncoderStream
2
+
3
+ //#region src/text-encoder-stream.ts
4
+ /**
5
+ * TextEncoderStream encodes a stream of strings into UTF-8 encoded bytes.
6
+ *
7
+ * Handles surrogate pairs split across chunks: if the last code unit of a
8
+ * chunk is a high surrogate (0xD800–0xDBFF), it is held until the next chunk.
9
+ * If the stream ends with a pending high surrogate, U+FFFD replacement bytes
10
+ * are emitted.
11
+ */
12
+ var TextEncoderStream = class {
13
+ #pendingHighSurrogate = null;
14
+ #encoder = new TextEncoder();
15
+ #transform;
16
+ constructor() {
17
+ this.#transform = new TransformStream({
18
+ transform: (chunk, controller) => {
19
+ chunk = String(chunk);
20
+ if (chunk === "") {
21
+ return;
22
+ }
23
+ if (this.#pendingHighSurrogate !== null) {
24
+ chunk = this.#pendingHighSurrogate + chunk;
25
+ }
26
+ const lastCodeUnit = chunk.charCodeAt(chunk.length - 1);
27
+ if (55296 <= lastCodeUnit && lastCodeUnit <= 56319) {
28
+ this.#pendingHighSurrogate = chunk.slice(-1);
29
+ chunk = chunk.slice(0, -1);
30
+ } else {
31
+ this.#pendingHighSurrogate = null;
32
+ }
33
+ if (chunk) {
34
+ controller.enqueue(this.#encoder.encode(chunk));
35
+ }
36
+ },
37
+ flush: (controller) => {
38
+ if (this.#pendingHighSurrogate !== null) {
39
+ controller.enqueue(new Uint8Array([
40
+ 239,
41
+ 191,
42
+ 189
43
+ ]));
44
+ }
45
+ }
46
+ });
47
+ }
48
+ get encoding() {
49
+ return "utf-8";
50
+ }
51
+ get readable() {
52
+ return this.#transform.readable;
53
+ }
54
+ get writable() {
55
+ return this.#transform.writable;
56
+ }
46
57
  };
58
+
59
+ //#endregion
60
+ export { TextEncoderStream };