@ccheever/exact-ibex-runtime 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.
Files changed (161) hide show
  1. package/package.json +63 -0
  2. package/src/abort/AbortController.ts +23 -0
  3. package/src/abort/AbortSignal.ts +152 -0
  4. package/src/abort/index.ts +2 -0
  5. package/src/accessibility.ts +12 -0
  6. package/src/arraybuffer-detach.ts +109 -0
  7. package/src/base64/base64.ts +168 -0
  8. package/src/base64/index.ts +1 -0
  9. package/src/blob/Blob.ts +259 -0
  10. package/src/blob/File.ts +59 -0
  11. package/src/blob/FormData.ts +323 -0
  12. package/src/blob/index.ts +3 -0
  13. package/src/bootstrap.ts +1946 -0
  14. package/src/broadcast/BroadcastChannel.ts +280 -0
  15. package/src/broadcast/index.ts +5 -0
  16. package/src/cache/Cache.ts +349 -0
  17. package/src/cache/CacheStorage.ts +89 -0
  18. package/src/cache/index.ts +27 -0
  19. package/src/camera/index.ts +6202 -0
  20. package/src/camera/processor.worker.ts +194 -0
  21. package/src/camera/scene.ts +195 -0
  22. package/src/clipboard/Clipboard.ts +129 -0
  23. package/src/clipboard/ClipboardItem.ts +97 -0
  24. package/src/clipboard/index.ts +6 -0
  25. package/src/clone/index.ts +1 -0
  26. package/src/clone/structuredClone.ts +389 -0
  27. package/src/clone/transferableSymbols.ts +2 -0
  28. package/src/compression/CompressionStream.ts +146 -0
  29. package/src/compression/DecompressionStream.ts +342 -0
  30. package/src/compression/index.ts +4 -0
  31. package/src/console/Console.ts +341 -0
  32. package/src/console/index.ts +2 -0
  33. package/src/core/accessibility-state.ts +263 -0
  34. package/src/core/accessibility.ts +184 -0
  35. package/src/core/agent-state.ts +37 -0
  36. package/src/core/diagnostics-logs.ts +144 -0
  37. package/src/core/host-call-bridge.ts +16 -0
  38. package/src/core/i18n-helpers.ts +189 -0
  39. package/src/core/locale-state.ts +253 -0
  40. package/src/core/locale.ts +95 -0
  41. package/src/crypto/Crypto.ts +2743 -0
  42. package/src/crypto/index.ts +1 -0
  43. package/src/diagnostics/logs.ts +7 -0
  44. package/src/encoding/TextDecoder.ts +1181 -0
  45. package/src/encoding/TextDecoderStream.ts +58 -0
  46. package/src/encoding/TextEncoder.ts +180 -0
  47. package/src/encoding/TextEncoderStream.ts +39 -0
  48. package/src/encoding/index.ts +8 -0
  49. package/src/events/CloseEvent.ts +91 -0
  50. package/src/events/DOMException.ts +409 -0
  51. package/src/events/ErrorEvent.ts +39 -0
  52. package/src/events/Event.ts +151 -0
  53. package/src/events/EventTarget.ts +280 -0
  54. package/src/events/FocusEvent.ts +27 -0
  55. package/src/events/KeyboardEvent.ts +46 -0
  56. package/src/events/MessageEvent.ts +61 -0
  57. package/src/events/ProgressEvent.ts +33 -0
  58. package/src/events/PromiseRejectionEvent.ts +31 -0
  59. package/src/events/index.ts +52 -0
  60. package/src/eventsource/EventSource.ts +371 -0
  61. package/src/eventsource/index.ts +2 -0
  62. package/src/fetch/Headers.ts +642 -0
  63. package/src/fetch/Request.ts +760 -0
  64. package/src/fetch/Response.ts +543 -0
  65. package/src/fetch/body.ts +1256 -0
  66. package/src/fetch/cookie-jar.ts +566 -0
  67. package/src/fetch/demo.ts +207 -0
  68. package/src/fetch/errors.ts +101 -0
  69. package/src/fetch/fetch.ts +2610 -0
  70. package/src/fetch/index.ts +101 -0
  71. package/src/fetch/native-bridge.ts +65 -0
  72. package/src/fetch/types.ts +258 -0
  73. package/src/filereader/FileReader.ts +236 -0
  74. package/src/filereader/index.ts +1 -0
  75. package/src/fs/Dirent.ts +39 -0
  76. package/src/fs/ExactFile.ts +450 -0
  77. package/src/fs/Stats.ts +80 -0
  78. package/src/fs/index.ts +944 -0
  79. package/src/fs/promises.ts +386 -0
  80. package/src/fs/shared.ts +328 -0
  81. package/src/http-server/index.js +697 -0
  82. package/src/http-server/index.ts +27 -0
  83. package/src/identity.generated.ts +14 -0
  84. package/src/index.ts +283 -0
  85. package/src/indexeddb/IDBCursor.ts +188 -0
  86. package/src/indexeddb/IDBDatabase.ts +343 -0
  87. package/src/indexeddb/IDBFactory.ts +269 -0
  88. package/src/indexeddb/IDBIndex.ts +194 -0
  89. package/src/indexeddb/IDBKeyRange.ts +109 -0
  90. package/src/indexeddb/IDBObjectStore.ts +468 -0
  91. package/src/indexeddb/IDBRequest.ts +163 -0
  92. package/src/indexeddb/IDBTransaction.ts +207 -0
  93. package/src/indexeddb/index.ts +34 -0
  94. package/src/indexeddb/utils.ts +52 -0
  95. package/src/inspect/index.ts +1 -0
  96. package/src/inspect/inspect.ts +465 -0
  97. package/src/internal/detect.ts +104 -0
  98. package/src/locale.ts +10 -0
  99. package/src/location/index.ts +1059 -0
  100. package/src/locks/LockManager.ts +460 -0
  101. package/src/locks/index.ts +12 -0
  102. package/src/media/VideoFrame.ts +58 -0
  103. package/src/messaging/MessageChannel.ts +31 -0
  104. package/src/messaging/MessagePort.ts +180 -0
  105. package/src/messaging/index.ts +2 -0
  106. package/src/messaging.ts +247 -0
  107. package/src/native/NativeModules.ts +354 -0
  108. package/src/native/index.ts +1 -0
  109. package/src/navigator/Navigator.ts +351 -0
  110. package/src/navigator/index.ts +1 -0
  111. package/src/node/Buffer.ts +1786 -0
  112. package/src/node/index.ts +4 -0
  113. package/src/node/path.ts +495 -0
  114. package/src/node/process.ts +2528 -0
  115. package/src/performance/Performance.ts +532 -0
  116. package/src/performance/index.ts +21 -0
  117. package/src/polyfills/array.ts +236 -0
  118. package/src/polyfills/arraybuffer.ts +172 -0
  119. package/src/polyfills/groupby.ts +85 -0
  120. package/src/polyfills/index.ts +85 -0
  121. package/src/polyfills/intl.ts +1956 -0
  122. package/src/polyfills/iterator.ts +479 -0
  123. package/src/polyfills/promise.ts +37 -0
  124. package/src/polyfills/set.ts +245 -0
  125. package/src/polyfills/string.ts +85 -0
  126. package/src/polyfills/typedarray.ts +110 -0
  127. package/src/promise-rejection-tracking.ts +464 -0
  128. package/src/react-native/index.ts +388 -0
  129. package/src/runtime-entry.ts +55 -0
  130. package/src/scheduling/AnimationFrame.ts +105 -0
  131. package/src/scheduling/IdleCallback.ts +167 -0
  132. package/src/scheduling/index.ts +13 -0
  133. package/src/security/Capabilities.ts +1146 -0
  134. package/src/security/Permissions.ts +392 -0
  135. package/src/security/capability-bits.generated.ts +63 -0
  136. package/src/security/index.ts +16 -0
  137. package/src/sqlite/Database.ts +456 -0
  138. package/src/sqlite/Statement.ts +206 -0
  139. package/src/sqlite/constants.ts +79 -0
  140. package/src/sqlite/errors.ts +25 -0
  141. package/src/sqlite/index.ts +34 -0
  142. package/src/sqlite/module.js +438 -0
  143. package/src/storage/Storage.ts +291 -0
  144. package/src/storage/StorageManager.ts +91 -0
  145. package/src/storage/index.ts +3 -0
  146. package/src/stream-compat.ts +47 -0
  147. package/src/streams/ReadableStream.ts +4131 -0
  148. package/src/streams/TransformStream.ts +375 -0
  149. package/src/streams/WritableStream.ts +866 -0
  150. package/src/streams/index.ts +41 -0
  151. package/src/timers/Timers.ts +296 -0
  152. package/src/timers/index.ts +11 -0
  153. package/src/url/URL.ts +656 -0
  154. package/src/url/URLPattern.ts +850 -0
  155. package/src/url/URLSearchParams.ts +244 -0
  156. package/src/url/index.ts +9 -0
  157. package/src/websocket/WebSocket.ts +770 -0
  158. package/src/websocket/WebSocketError.ts +52 -0
  159. package/src/websocket/WebSocketStream.ts +628 -0
  160. package/src/websocket/index.ts +7 -0
  161. package/src/window/index.ts +872 -0
@@ -0,0 +1,389 @@
1
+ // @ts-nocheck
2
+ /**
3
+ * structuredClone implementation for Ibex runtime
4
+ *
5
+ * Implements the HTML structured clone algorithm.
6
+ * @see https://html.spec.whatwg.org/multipage/structured-data.html#structuredclone
7
+ */
8
+
9
+ import { DOMException, createDataCloneError } from '../events/DOMException';
10
+ import { isDetachedArrayBuffer, markDetachedArrayBuffer } from '../arraybuffer-detach';
11
+ import { Blob as ExactBlob } from '../blob/Blob';
12
+ import { File as ExactFile } from '../blob/File';
13
+
14
+ // Lazy imports to break circular dependency:
15
+ // Blob → streams/ReadableStream → clone/structuredClone → Blob
16
+ let _Blob: typeof import('../blob/Blob').Blob | undefined;
17
+ let _File: typeof import('../blob/File').File | undefined;
18
+ function getBlobClasses() {
19
+ if (!_Blob) {
20
+ // Keep constructor lookup lazy so the module does not touch Blob/File until
21
+ // structuredClone actually needs them, while still relying on normal ESM
22
+ // resolution instead of CommonJS `require()` path heuristics.
23
+ _Blob = ExactBlob;
24
+ _File = ExactFile;
25
+ }
26
+ return { Blob: _Blob!, File: _File! };
27
+ }
28
+ import {
29
+ structuredCloneCloneSymbol,
30
+ structuredCloneTransferSymbol,
31
+ } from './transferableSymbols';
32
+
33
+ export interface StructuredSerializeOptions {
34
+ transfer?: Transferable[];
35
+ }
36
+
37
+ // Types that can be transferred (ownership moves, original becomes neutered)
38
+ type Transferable = ArrayBuffer | object;
39
+
40
+ export { isDetachedArrayBuffer, markDetachedArrayBuffer } from '../arraybuffer-detach';
41
+
42
+ /**
43
+ * Creates a deep copy of a value using the structured clone algorithm.
44
+ *
45
+ * Supported types:
46
+ * - Primitives (undefined, null, boolean, number, string, bigint)
47
+ * - Date
48
+ * - RegExp
49
+ * - Array
50
+ * - Object (plain objects)
51
+ * - Map
52
+ * - Set
53
+ * - ArrayBuffer
54
+ * - TypedArrays (Uint8Array, Int32Array, etc.)
55
+ * - DataView
56
+ * - Blob
57
+ * - File
58
+ * - Error (partial - only message and name)
59
+ *
60
+ * NOT supported:
61
+ * - Functions
62
+ * - Symbols (as values - ignored as keys)
63
+ * - DOM nodes
64
+ * - WeakMap, WeakSet, WeakRef
65
+ * - Generators, Promises
66
+ * - SharedArrayBuffer (Hermes limitation)
67
+ */
68
+ export function structuredClone<T>(
69
+ value: T,
70
+ options?: StructuredSerializeOptions
71
+ ): T {
72
+ const transfer = options?.transfer ?? [];
73
+ const transferSet = new Set<object>();
74
+
75
+ for (const transferable of transfer) {
76
+ if (
77
+ !(transferable instanceof ArrayBuffer) &&
78
+ !(
79
+ transferable &&
80
+ typeof transferable === 'object' &&
81
+ structuredCloneTransferSymbol in transferable
82
+ )
83
+ ) {
84
+ throw createDataCloneError(
85
+ 'The object could not be cloned.'
86
+ );
87
+ }
88
+ if (transferable && typeof transferable === 'object') {
89
+ if (transferSet.has(transferable)) {
90
+ throw createDataCloneError('The object could not be cloned.');
91
+ }
92
+ transferSet.add(transferable);
93
+ }
94
+ }
95
+
96
+ // Track already-cloned objects to handle circular references
97
+ const cloneMap = new Map<object, object>();
98
+
99
+ const cloned = cloneInternal(value, cloneMap, transferSet);
100
+
101
+ for (const transferable of transfer) {
102
+ if (transferable instanceof ArrayBuffer) {
103
+ markDetachedArrayBuffer(transferable);
104
+ }
105
+ }
106
+
107
+ return cloned;
108
+ }
109
+
110
+ type ImageDataLike = {
111
+ data: Uint8ClampedArray;
112
+ width: number;
113
+ height: number;
114
+ colorSpace?: string;
115
+ };
116
+
117
+ function getGlobalDOMExceptionConstructor():
118
+ | (new (message?: string, name?: string) => DOMException)
119
+ | undefined {
120
+ return typeof globalThis === 'object' &&
121
+ globalThis !== null &&
122
+ typeof (globalThis as any).DOMException === 'function'
123
+ ? ((globalThis as any).DOMException as new (message?: string, name?: string) => DOMException)
124
+ : undefined;
125
+ }
126
+
127
+ function isDomExceptionInstance(value: object): value is DOMException {
128
+ if (value instanceof DOMException) {
129
+ return true;
130
+ }
131
+ const GlobalDOMException = getGlobalDOMExceptionConstructor();
132
+ return typeof GlobalDOMException === 'function' && value instanceof GlobalDOMException;
133
+ }
134
+
135
+ function getGlobalImageDataConstructor():
136
+ | (new (
137
+ data: Uint8ClampedArray,
138
+ width: number,
139
+ height?: number,
140
+ settings?: { colorSpace?: string }
141
+ ) => ImageDataLike)
142
+ | undefined {
143
+ return typeof globalThis === 'object' &&
144
+ globalThis !== null &&
145
+ typeof (globalThis as any).ImageData === 'function'
146
+ ? ((globalThis as any).ImageData as new (
147
+ data: Uint8ClampedArray,
148
+ width: number,
149
+ height?: number,
150
+ settings?: { colorSpace?: string }
151
+ ) => ImageDataLike)
152
+ : undefined;
153
+ }
154
+
155
+ function isImageDataInstance(value: object): value is ImageDataLike {
156
+ const ImageDataCtor = getGlobalImageDataConstructor();
157
+ return typeof ImageDataCtor === 'function' && value instanceof ImageDataCtor;
158
+ }
159
+
160
+ function cloneInternal<T>(
161
+ value: T,
162
+ cloneMap: Map<object, object>,
163
+ transferSet: Set<object>
164
+ ): T {
165
+ // Handle primitives
166
+ if (value === null || value === undefined) {
167
+ return value;
168
+ }
169
+
170
+ const type = typeof value;
171
+
172
+ if (type === 'boolean' || type === 'number' || type === 'string' || type === 'bigint') {
173
+ return value;
174
+ }
175
+
176
+ if (type === 'symbol') {
177
+ throw createDataCloneError('Symbols cannot be cloned');
178
+ }
179
+
180
+ if (type === 'function') {
181
+ throw createDataCloneError('Functions cannot be cloned');
182
+ }
183
+
184
+ // At this point, value must be an object
185
+ const obj = value as unknown as object;
186
+
187
+ // Check for circular reference
188
+ if (cloneMap.has(obj)) {
189
+ return cloneMap.get(obj) as T;
190
+ }
191
+
192
+ if (transferSet.has(obj)) {
193
+ if (obj instanceof ArrayBuffer) {
194
+ const clone = obj.slice(0);
195
+ cloneMap.set(obj, clone);
196
+ return clone as T;
197
+ }
198
+ if (structuredCloneTransferSymbol in obj) {
199
+ const transferClone = (obj as any)[structuredCloneTransferSymbol]();
200
+ cloneMap.set(obj, transferClone);
201
+ return transferClone as T;
202
+ }
203
+ }
204
+
205
+ if (structuredCloneCloneSymbol in obj) {
206
+ const clone = (obj as any)[structuredCloneCloneSymbol]();
207
+ cloneMap.set(obj, clone);
208
+ return clone as T;
209
+ }
210
+
211
+ if (structuredCloneTransferSymbol in obj) {
212
+ throw createDataCloneError('The object could not be cloned.');
213
+ }
214
+
215
+ // Handle specific object types
216
+ if (obj instanceof Date) {
217
+ const clone = new Date(obj.getTime());
218
+ cloneMap.set(obj, clone);
219
+ return clone as T;
220
+ }
221
+
222
+ if (obj instanceof RegExp) {
223
+ const clone = new RegExp(obj.source, obj.flags);
224
+ cloneMap.set(obj, clone);
225
+ return clone as T;
226
+ }
227
+
228
+ if (isDomExceptionInstance(obj)) {
229
+ const DOMExceptionCtor =
230
+ (typeof (obj as any).constructor === 'function'
231
+ ? ((obj as any).constructor as new (message?: string, name?: string) => DOMException)
232
+ : undefined) ??
233
+ getGlobalDOMExceptionConstructor() ??
234
+ DOMException;
235
+ const clone = new DOMExceptionCtor(obj.message, obj.name);
236
+ if (typeof (obj as any).stack === 'string') {
237
+ (clone as any).stack = (obj as any).stack;
238
+ }
239
+ if ('cause' in obj) {
240
+ (clone as any).cause = cloneInternal((obj as any).cause, cloneMap, transferSet);
241
+ }
242
+ cloneMap.set(obj, clone);
243
+ return clone as T;
244
+ }
245
+
246
+ if (obj instanceof Error) {
247
+ const ErrorConstructor = obj.constructor as ErrorConstructor;
248
+ const clone = new ErrorConstructor(obj.message);
249
+ clone.name = obj.name;
250
+ if (typeof (obj as any).stack === 'string') {
251
+ (clone as any).stack = (obj as any).stack;
252
+ }
253
+ // Optionally copy cause if present
254
+ if ('cause' in obj) {
255
+ (clone as any).cause = cloneInternal((obj as any).cause, cloneMap, transferSet);
256
+ }
257
+ cloneMap.set(obj, clone);
258
+ return clone as T;
259
+ }
260
+
261
+ if (isImageDataInstance(obj)) {
262
+ const ImageDataCtor = getGlobalImageDataConstructor();
263
+ if (!ImageDataCtor) {
264
+ throw createDataCloneError('The object could not be cloned.');
265
+ }
266
+
267
+ const clonedData = cloneInternal(obj.data, cloneMap, transferSet) as Uint8ClampedArray;
268
+ let clone: ImageDataLike;
269
+ try {
270
+ clone = new ImageDataCtor(clonedData, obj.width, obj.height, {
271
+ colorSpace: obj.colorSpace,
272
+ });
273
+ } catch {
274
+ clone = new ImageDataCtor(clonedData, obj.width, obj.height);
275
+ }
276
+ cloneMap.set(obj, clone as object);
277
+ return clone as T;
278
+ }
279
+
280
+ if (obj instanceof ArrayBuffer) {
281
+ // Clone the buffer
282
+ const clone = obj.slice(0);
283
+ cloneMap.set(obj, clone);
284
+ return clone as T;
285
+ }
286
+
287
+ // Handle TypedArrays
288
+ if (ArrayBuffer.isView(obj) && !(obj instanceof DataView)) {
289
+ const TypedArrayConstructor = obj.constructor as new (buffer: ArrayBuffer, byteOffset: number, length: number) => typeof obj;
290
+ const sourceBuffer = obj.buffer as ArrayBuffer;
291
+
292
+ // Clone the buffer portion
293
+ const clonedBuffer = sourceBuffer.slice(obj.byteOffset, obj.byteOffset + obj.byteLength);
294
+ const clone = new TypedArrayConstructor(clonedBuffer, 0, (obj as any).length);
295
+ cloneMap.set(obj, clone);
296
+ return clone as T;
297
+ }
298
+
299
+ if (obj instanceof DataView) {
300
+ const sourceBuffer = obj.buffer as ArrayBuffer;
301
+ // Per spec: clone the entire underlying buffer and preserve byteOffset
302
+ const clonedBuffer = sourceBuffer.slice(0);
303
+ const clone = new DataView(clonedBuffer, obj.byteOffset, obj.byteLength);
304
+ cloneMap.set(obj, clone);
305
+ return clone as T;
306
+ }
307
+
308
+ if (obj instanceof Map) {
309
+ const clone = new Map();
310
+ cloneMap.set(obj, clone);
311
+ for (const [key, val] of obj) {
312
+ // Keys are also cloned
313
+ const clonedKey = cloneInternal(key, cloneMap, transferSet);
314
+ const clonedVal = cloneInternal(val, cloneMap, transferSet);
315
+ clone.set(clonedKey, clonedVal);
316
+ }
317
+ return clone as T;
318
+ }
319
+
320
+ if (obj instanceof Set) {
321
+ const clone = new Set();
322
+ cloneMap.set(obj, clone);
323
+ for (const item of obj) {
324
+ clone.add(cloneInternal(item, cloneMap, transferSet));
325
+ }
326
+ return clone as T;
327
+ }
328
+
329
+ // Blob and File
330
+ const { Blob: BlobClass, File: FileClass } = getBlobClasses();
331
+ if (obj instanceof FileClass) {
332
+ const bytes = (obj as any)._getBytes();
333
+ const clone = new FileClass([bytes], (obj as any).name, {
334
+ type: (obj as any).type,
335
+ lastModified: (obj as any).lastModified,
336
+ });
337
+ cloneMap.set(obj, clone);
338
+ return clone as T;
339
+ }
340
+
341
+ if (obj instanceof BlobClass) {
342
+ const bytes = (obj as any)._getBytes();
343
+ const clone = new BlobClass([bytes], { type: (obj as any).type });
344
+ cloneMap.set(obj, clone);
345
+ return clone as T;
346
+ }
347
+
348
+ // Handle Arrays
349
+ if (Array.isArray(obj)) {
350
+ const clone: any[] = [];
351
+ cloneMap.set(obj, clone);
352
+ for (let i = 0; i < obj.length; i++) {
353
+ clone[i] = cloneInternal(obj[i], cloneMap, transferSet);
354
+ }
355
+ return clone as T;
356
+ }
357
+
358
+ // Handle plain objects
359
+ // Check if it's a plain object (not a class instance with special behavior)
360
+ const proto = Object.getPrototypeOf(obj);
361
+ if (proto === null || proto === Object.prototype) {
362
+ const clone: Record<string, unknown> = {};
363
+ cloneMap.set(obj, clone);
364
+
365
+ // Clone own enumerable string-keyed properties
366
+ for (const key of Object.keys(obj)) {
367
+ clone[key] = cloneInternal((obj as any)[key], cloneMap, transferSet);
368
+ }
369
+
370
+ return clone as T;
371
+ }
372
+
373
+ // Object with unknown prototype - try to clone as plain object with warning
374
+ // This handles objects that are "object-like" but may have custom prototypes
375
+ if (typeof obj === 'object') {
376
+ const clone: Record<string, unknown> = {};
377
+ cloneMap.set(obj, clone);
378
+
379
+ for (const key of Object.keys(obj)) {
380
+ clone[key] = cloneInternal((obj as any)[key], cloneMap, transferSet);
381
+ }
382
+
383
+ return clone as T;
384
+ }
385
+
386
+ throw createDataCloneError(`Object of type ${obj.constructor?.name ?? 'unknown'} cannot be cloned`);
387
+ }
388
+
389
+ export default structuredClone;
@@ -0,0 +1,2 @@
1
+ export const structuredCloneTransferSymbol = Symbol.for("exact.structuredClone.transfer");
2
+ export const structuredCloneCloneSymbol = Symbol.for("exact.structuredClone.clone");
@@ -0,0 +1,146 @@
1
+ /**
2
+ * CompressionStream - Web Compression API
3
+ *
4
+ * Implements the CompressionStream class that compresses data using gzip, deflate, deflate-raw, or brotli.
5
+ * Uses the native __exactDeflateSync bridge for actual compression.
6
+ */
7
+
8
+ const g = globalThis as any;
9
+
10
+ export type CompressionFormat = 'gzip' | 'deflate' | 'deflate-raw' | 'brotli';
11
+
12
+ function isTypeError(error: unknown): error is TypeError {
13
+ return error instanceof TypeError;
14
+ }
15
+
16
+ function toTypeError(error: unknown): TypeError {
17
+ if (error instanceof TypeError) {
18
+ return error;
19
+ }
20
+
21
+ if (error instanceof Error) {
22
+ let message = "TypeError";
23
+ try {
24
+ message = String(error.message);
25
+ } catch (_ignored) {
26
+ message = "TypeError";
27
+ }
28
+ return new TypeError(message);
29
+ }
30
+
31
+ try {
32
+ return new TypeError(String(error));
33
+ } catch (_ignored) {
34
+ return new TypeError("TypeError");
35
+ }
36
+ }
37
+
38
+ export class CompressionStream {
39
+ private _format: CompressionFormat;
40
+ private _readable: ReadableStream<Uint8Array>;
41
+ private _writable: WritableStream<Uint8Array>;
42
+
43
+ constructor(format: CompressionFormat) {
44
+ if (format !== 'gzip' && format !== 'deflate' && format !== 'deflate-raw' && format !== 'brotli') {
45
+ throw new TypeError(`Unsupported compression format: '${format}'`);
46
+ }
47
+ this._format = format;
48
+
49
+ // Native bridge mode: 0 = deflate (zlib header), 1 = gzip, 2 = raw deflate (no header)
50
+ const mode = format === 'gzip' ? 1 : format === 'deflate-raw' ? 2 : 0;
51
+ const compressChunk = (chunk: Uint8Array): Uint8Array => {
52
+ // Convert to Uint8Array if needed
53
+ const input = chunk instanceof Uint8Array ? chunk : new Uint8Array(chunk);
54
+
55
+ if (format === 'brotli') {
56
+ if (typeof g.__exactBrotliCompressSync !== 'function') {
57
+ throw new Error('Native compression bridge (__exactBrotliCompressSync) not available');
58
+ }
59
+ return g.__exactBrotliCompressSync(input);
60
+ }
61
+
62
+ if (typeof g.__exactDeflateSync !== 'function') {
63
+ throw new Error('Native compression bridge (__exactDeflateSync) not available');
64
+ }
65
+ return g.__exactDeflateSync(input, -1, mode);
66
+ };
67
+
68
+ let streamInput = new Uint8Array(0);
69
+ let streamError: TypeError | null = null;
70
+
71
+ const appendInput = (chunk: Uint8Array): void => {
72
+ const next = new Uint8Array(streamInput.length + chunk.length);
73
+ next.set(streamInput, 0);
74
+ next.set(chunk, streamInput.length);
75
+ streamInput = next;
76
+ };
77
+
78
+ let readableController: ReadableStreamDefaultController<Uint8Array> | undefined;
79
+
80
+ const readable = new ReadableStream<Uint8Array>({
81
+ start(controller) {
82
+ readableController = controller;
83
+ },
84
+ cancel() {
85
+ readableController = undefined;
86
+ },
87
+ });
88
+
89
+ const writable = new WritableStream<Uint8Array>({
90
+ write(chunk) {
91
+ if (streamError) {
92
+ throw streamError;
93
+ }
94
+
95
+ if (chunk && chunk.length > 0) {
96
+ appendInput(chunk);
97
+ }
98
+ },
99
+ close() {
100
+ if (streamError) {
101
+ if (readableController) {
102
+ readableController.error(streamError);
103
+ }
104
+ return;
105
+ }
106
+
107
+ try {
108
+ const compressed = compressChunk(streamInput);
109
+ if (readableController && compressed.length > 0) {
110
+ readableController.enqueue(compressed);
111
+ }
112
+ if (readableController) {
113
+ readableController.close();
114
+ }
115
+ } catch (e) {
116
+ streamError = e instanceof TypeError ? e : toTypeError(e);
117
+ if (readableController) {
118
+ readableController.error(streamError);
119
+ }
120
+ throw streamError;
121
+ }
122
+ },
123
+ abort(reason) {
124
+ if (reason instanceof Error) {
125
+ streamError = toTypeError(reason);
126
+ } else {
127
+ streamError = new TypeError(String(reason));
128
+ }
129
+ if (readableController) {
130
+ readableController.error(streamError);
131
+ }
132
+ },
133
+ });
134
+
135
+ this._readable = readable;
136
+ this._writable = writable;
137
+ }
138
+
139
+ get readable(): ReadableStream<Uint8Array> {
140
+ return this._readable;
141
+ }
142
+
143
+ get writable(): WritableStream<Uint8Array> {
144
+ return this._writable;
145
+ }
146
+ }