@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,371 @@
1
+ // @ts-nocheck
2
+ /**
3
+ * EventSource implementation for Ibex runtime
4
+ *
5
+ * Implements the WHATWG EventSource (Server-Sent Events) API.
6
+ * @see https://html.spec.whatwg.org/multipage/server-sent-events.html
7
+ */
8
+
9
+ import { EventTarget } from '../events/EventTarget';
10
+ import { Event } from '../events/Event';
11
+ import { MessageEvent } from '../events/MessageEvent';
12
+ import { requireCapability, Capabilities } from '../security/Capabilities';
13
+
14
+ // EventSource ready states
15
+ const CONNECTING = 0;
16
+ const OPEN = 1;
17
+ const CLOSED = 2;
18
+
19
+ // Default reconnection time in milliseconds
20
+ const DEFAULT_RECONNECT_TIME = 3000;
21
+
22
+ // Maximum reconnection time (cap for exponential backoff)
23
+ const MAX_RECONNECT_TIME = 60000;
24
+
25
+ /**
26
+ * EventSourceInit options for the EventSource constructor.
27
+ */
28
+ export interface EventSourceInit {
29
+ withCredentials?: boolean;
30
+ }
31
+
32
+ /**
33
+ * EventSource provides a persistent connection to a server that sends events
34
+ * in the text/event-stream format. Unlike WebSocket, EventSource is a
35
+ * unidirectional channel (server to client only).
36
+ */
37
+ export class EventSource extends EventTarget {
38
+ // Ready state constants (static)
39
+ static readonly CONNECTING = CONNECTING;
40
+ static readonly OPEN = OPEN;
41
+ static readonly CLOSED = CLOSED;
42
+
43
+ // Ready state constants (instance)
44
+ readonly CONNECTING = CONNECTING;
45
+ readonly OPEN = OPEN;
46
+ readonly CLOSED = CLOSED;
47
+
48
+ // Public properties
49
+ readonly url: string;
50
+ readonly withCredentials: boolean;
51
+
52
+ // Internal state
53
+ #readyState: number = CONNECTING;
54
+ #reconnectionTime: number = DEFAULT_RECONNECT_TIME;
55
+ #lastEventId: string = '';
56
+ #abortController: AbortController | null = null;
57
+ #reconnectTimer: ReturnType<typeof setTimeout> | null = null;
58
+ #consecutiveFailures: number = 0;
59
+
60
+ // Event handler properties
61
+ onopen: ((this: EventSource, ev: Event) => any) | null = null;
62
+ onmessage: ((this: EventSource, ev: MessageEvent) => any) | null = null;
63
+ onerror: ((this: EventSource, ev: Event) => any) | null = null;
64
+
65
+ constructor(url: string | URL, eventSourceInitDict?: EventSourceInit) {
66
+ super();
67
+
68
+ // Check capability before proceeding
69
+ requireCapability(Capabilities.NETWORK_CONNECT);
70
+
71
+ // Normalize URL
72
+ const urlString = url instanceof URL ? url.href : url;
73
+
74
+ // Validate URL
75
+ let parsedUrl: URL;
76
+ try {
77
+ parsedUrl = new URL(urlString);
78
+ } catch {
79
+ throw new DOMException('Invalid URL', 'SyntaxError');
80
+ }
81
+
82
+ this.url = parsedUrl.href;
83
+ this.withCredentials = eventSourceInitDict?.withCredentials ?? false;
84
+
85
+ // Start connection
86
+ this.#connect();
87
+ }
88
+
89
+ get readyState(): number {
90
+ return this.#readyState;
91
+ }
92
+
93
+ /**
94
+ * Close the EventSource connection.
95
+ */
96
+ close(): void {
97
+ if (this.#readyState === CLOSED) {
98
+ return;
99
+ }
100
+
101
+ this.#readyState = CLOSED;
102
+
103
+ // Abort any in-flight fetch
104
+ if (this.#abortController) {
105
+ this.#abortController.abort();
106
+ this.#abortController = null;
107
+ }
108
+
109
+ // Clear any pending reconnect timer
110
+ if (this.#reconnectTimer !== null) {
111
+ clearTimeout(this.#reconnectTimer);
112
+ this.#reconnectTimer = null;
113
+ }
114
+ }
115
+
116
+ /**
117
+ * Initiate the fetch connection to the SSE endpoint.
118
+ */
119
+ #connect(): void {
120
+ if (this.#readyState === CLOSED) {
121
+ return;
122
+ }
123
+
124
+ this.#readyState = CONNECTING;
125
+ this.#abortController = new AbortController();
126
+
127
+ const headers: Record<string, string> = {
128
+ 'Accept': 'text/event-stream',
129
+ 'Cache-Control': 'no-cache',
130
+ };
131
+
132
+ // Send Last-Event-ID on reconnects
133
+ if (this.#lastEventId) {
134
+ headers['Last-Event-ID'] = this.#lastEventId;
135
+ }
136
+
137
+ fetch(this.url, {
138
+ headers,
139
+ signal: this.#abortController.signal,
140
+ cache: 'no-store' as any,
141
+ })
142
+ .then((response) => {
143
+ if (this.#readyState === CLOSED) {
144
+ return;
145
+ }
146
+
147
+ // Check for successful response
148
+ if (!response.ok) {
149
+ this.#failConnection('HTTP error: ' + response.status);
150
+ return;
151
+ }
152
+
153
+ // Check content type
154
+ const contentType = response.headers.get('content-type') || '';
155
+ if (!contentType.includes('text/event-stream')) {
156
+ this.#failConnection('Invalid content type: ' + contentType);
157
+ return;
158
+ }
159
+
160
+ // Connection established
161
+ this.#readyState = OPEN;
162
+ this.#consecutiveFailures = 0;
163
+
164
+ const openEvent = new Event('open');
165
+ if (this.onopen) {
166
+ this.onopen.call(this, openEvent);
167
+ }
168
+ this.dispatchEvent(openEvent);
169
+
170
+ // Read the stream
171
+ this.#readStream(response);
172
+ })
173
+ .catch((error) => {
174
+ if (this.#readyState === CLOSED) {
175
+ return;
176
+ }
177
+
178
+ // AbortError means we called close() or are reconnecting
179
+ if (error && error.name === 'AbortError') {
180
+ return;
181
+ }
182
+
183
+ this.#failConnection(error?.message || 'Connection failed');
184
+ });
185
+ }
186
+
187
+ /**
188
+ * Read the response body as a stream and parse SSE events.
189
+ */
190
+ async #readStream(response: Response): Promise<void> {
191
+ const body = response.body;
192
+ if (!body) {
193
+ this.#failConnection('Response body is null');
194
+ return;
195
+ }
196
+
197
+ const reader = body.getReader();
198
+ const decoder = new TextDecoder();
199
+ let buffer = '';
200
+
201
+ // SSE parser state
202
+ let eventType = '';
203
+ let dataBuffer = '';
204
+ let lastEventId: string | undefined;
205
+
206
+ try {
207
+ while (true) {
208
+ if (this.#readyState === CLOSED) {
209
+ reader.cancel();
210
+ return;
211
+ }
212
+
213
+ const { done, value } = await reader.read();
214
+
215
+ if (done) {
216
+ // Stream ended - attempt reconnect
217
+ if (this.#readyState !== CLOSED) {
218
+ this.#scheduleReconnect();
219
+ }
220
+ return;
221
+ }
222
+
223
+ buffer += decoder.decode(value, { stream: true });
224
+
225
+ // Process complete lines
226
+ let lineEnd: number;
227
+ while ((lineEnd = buffer.indexOf('\n')) !== -1) {
228
+ const line = buffer.substring(0, lineEnd);
229
+ buffer = buffer.substring(lineEnd + 1);
230
+
231
+ // Remove trailing \r if present (handle \r\n line endings)
232
+ const cleanLine = line.endsWith('\r') ? line.slice(0, -1) : line;
233
+
234
+ if (cleanLine === '') {
235
+ // Empty line = dispatch event
236
+ if (dataBuffer !== '') {
237
+ // Remove trailing newline from data buffer
238
+ if (dataBuffer.endsWith('\n')) {
239
+ dataBuffer = dataBuffer.slice(0, -1);
240
+ }
241
+
242
+ const eventName = eventType || 'message';
243
+
244
+ if (lastEventId !== undefined) {
245
+ this.#lastEventId = lastEventId;
246
+ }
247
+
248
+ const messageEvent = new MessageEvent(eventName, {
249
+ data: dataBuffer,
250
+ origin: new URL(this.url).origin,
251
+ lastEventId: this.#lastEventId,
252
+ });
253
+
254
+ // Fire onmessage only for "message" type events
255
+ if (eventName === 'message' && this.onmessage) {
256
+ this.onmessage.call(this, messageEvent);
257
+ }
258
+ this.dispatchEvent(messageEvent);
259
+ }
260
+
261
+ // Reset per-event state
262
+ eventType = '';
263
+ dataBuffer = '';
264
+ lastEventId = undefined;
265
+ } else if (cleanLine.startsWith(':')) {
266
+ // Comment line - ignore
267
+ } else {
268
+ // Parse field
269
+ const colonIndex = cleanLine.indexOf(':');
270
+ let field: string;
271
+ let fieldValue: string;
272
+
273
+ if (colonIndex === -1) {
274
+ // No colon: treat entire line as field name with empty value
275
+ field = cleanLine;
276
+ fieldValue = '';
277
+ } else {
278
+ field = cleanLine.substring(0, colonIndex);
279
+ // Skip optional space after colon
280
+ fieldValue = cleanLine.substring(colonIndex + 1);
281
+ if (fieldValue.startsWith(' ')) {
282
+ fieldValue = fieldValue.substring(1);
283
+ }
284
+ }
285
+
286
+ switch (field) {
287
+ case 'data':
288
+ dataBuffer += fieldValue + '\n';
289
+ break;
290
+ case 'event':
291
+ eventType = fieldValue;
292
+ break;
293
+ case 'id':
294
+ // Per spec: if the field value does not contain U+0000 NULL
295
+ if (!fieldValue.includes('\0')) {
296
+ lastEventId = fieldValue;
297
+ }
298
+ break;
299
+ case 'retry':
300
+ // Only set if the value consists solely of ASCII digits
301
+ if (/^\d+$/.test(fieldValue)) {
302
+ this.#reconnectionTime = parseInt(fieldValue, 10);
303
+ }
304
+ break;
305
+ // Unknown fields are ignored per spec
306
+ }
307
+ }
308
+ }
309
+ }
310
+ } catch (error: any) {
311
+ if (this.#readyState === CLOSED) {
312
+ return;
313
+ }
314
+
315
+ if (error && error.name === 'AbortError') {
316
+ return;
317
+ }
318
+
319
+ // Stream read error - attempt reconnect
320
+ this.#failConnection(error?.message || 'Stream read error');
321
+ }
322
+ }
323
+
324
+ /**
325
+ * Handle a connection failure: fire error event and schedule reconnect.
326
+ */
327
+ #failConnection(message: string): void {
328
+ if (this.#readyState === CLOSED) {
329
+ return;
330
+ }
331
+
332
+ const errorEvent = new Event('error');
333
+ if (this.onerror) {
334
+ this.onerror.call(this, errorEvent);
335
+ }
336
+ this.dispatchEvent(errorEvent);
337
+
338
+ this.#scheduleReconnect();
339
+ }
340
+
341
+ /**
342
+ * Schedule a reconnection attempt with exponential backoff.
343
+ */
344
+ #scheduleReconnect(): void {
345
+ if (this.#readyState === CLOSED) {
346
+ return;
347
+ }
348
+
349
+ this.#readyState = CONNECTING;
350
+ this.#consecutiveFailures++;
351
+
352
+ // Exponential backoff: reconnectionTime * 2^(failures-1), capped at MAX
353
+ const backoff = Math.min(
354
+ this.#reconnectionTime * Math.pow(2, this.#consecutiveFailures - 1),
355
+ MAX_RECONNECT_TIME
356
+ );
357
+
358
+ this.#reconnectTimer = setTimeout(() => {
359
+ this.#reconnectTimer = null;
360
+ if (this.#readyState !== CLOSED) {
361
+ this.#connect();
362
+ }
363
+ }, backoff);
364
+ }
365
+
366
+ get [Symbol.toStringTag](): string {
367
+ return 'EventSource';
368
+ }
369
+ }
370
+
371
+ export default EventSource;
@@ -0,0 +1,2 @@
1
+ export { EventSource } from './EventSource';
2
+ export type { EventSourceInit } from './EventSource';