@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.
- package/package.json +63 -0
- package/src/abort/AbortController.ts +23 -0
- package/src/abort/AbortSignal.ts +152 -0
- package/src/abort/index.ts +2 -0
- package/src/accessibility.ts +12 -0
- package/src/arraybuffer-detach.ts +109 -0
- package/src/base64/base64.ts +168 -0
- package/src/base64/index.ts +1 -0
- package/src/blob/Blob.ts +259 -0
- package/src/blob/File.ts +59 -0
- package/src/blob/FormData.ts +323 -0
- package/src/blob/index.ts +3 -0
- package/src/bootstrap.ts +1946 -0
- package/src/broadcast/BroadcastChannel.ts +280 -0
- package/src/broadcast/index.ts +5 -0
- package/src/cache/Cache.ts +349 -0
- package/src/cache/CacheStorage.ts +89 -0
- package/src/cache/index.ts +27 -0
- package/src/camera/index.ts +6202 -0
- package/src/camera/processor.worker.ts +194 -0
- package/src/camera/scene.ts +195 -0
- package/src/clipboard/Clipboard.ts +129 -0
- package/src/clipboard/ClipboardItem.ts +97 -0
- package/src/clipboard/index.ts +6 -0
- package/src/clone/index.ts +1 -0
- package/src/clone/structuredClone.ts +389 -0
- package/src/clone/transferableSymbols.ts +2 -0
- package/src/compression/CompressionStream.ts +146 -0
- package/src/compression/DecompressionStream.ts +342 -0
- package/src/compression/index.ts +4 -0
- package/src/console/Console.ts +341 -0
- package/src/console/index.ts +2 -0
- package/src/core/accessibility-state.ts +263 -0
- package/src/core/accessibility.ts +184 -0
- package/src/core/agent-state.ts +37 -0
- package/src/core/diagnostics-logs.ts +144 -0
- package/src/core/host-call-bridge.ts +16 -0
- package/src/core/i18n-helpers.ts +189 -0
- package/src/core/locale-state.ts +253 -0
- package/src/core/locale.ts +95 -0
- package/src/crypto/Crypto.ts +2743 -0
- package/src/crypto/index.ts +1 -0
- package/src/diagnostics/logs.ts +7 -0
- package/src/encoding/TextDecoder.ts +1181 -0
- package/src/encoding/TextDecoderStream.ts +58 -0
- package/src/encoding/TextEncoder.ts +180 -0
- package/src/encoding/TextEncoderStream.ts +39 -0
- package/src/encoding/index.ts +8 -0
- package/src/events/CloseEvent.ts +91 -0
- package/src/events/DOMException.ts +409 -0
- package/src/events/ErrorEvent.ts +39 -0
- package/src/events/Event.ts +151 -0
- package/src/events/EventTarget.ts +280 -0
- package/src/events/FocusEvent.ts +27 -0
- package/src/events/KeyboardEvent.ts +46 -0
- package/src/events/MessageEvent.ts +61 -0
- package/src/events/ProgressEvent.ts +33 -0
- package/src/events/PromiseRejectionEvent.ts +31 -0
- package/src/events/index.ts +52 -0
- package/src/eventsource/EventSource.ts +371 -0
- package/src/eventsource/index.ts +2 -0
- package/src/fetch/Headers.ts +642 -0
- package/src/fetch/Request.ts +760 -0
- package/src/fetch/Response.ts +543 -0
- package/src/fetch/body.ts +1256 -0
- package/src/fetch/cookie-jar.ts +566 -0
- package/src/fetch/demo.ts +207 -0
- package/src/fetch/errors.ts +101 -0
- package/src/fetch/fetch.ts +2610 -0
- package/src/fetch/index.ts +101 -0
- package/src/fetch/native-bridge.ts +65 -0
- package/src/fetch/types.ts +258 -0
- package/src/filereader/FileReader.ts +236 -0
- package/src/filereader/index.ts +1 -0
- package/src/fs/Dirent.ts +39 -0
- package/src/fs/ExactFile.ts +450 -0
- package/src/fs/Stats.ts +80 -0
- package/src/fs/index.ts +944 -0
- package/src/fs/promises.ts +386 -0
- package/src/fs/shared.ts +328 -0
- package/src/http-server/index.js +697 -0
- package/src/http-server/index.ts +27 -0
- package/src/identity.generated.ts +14 -0
- package/src/index.ts +283 -0
- package/src/indexeddb/IDBCursor.ts +188 -0
- package/src/indexeddb/IDBDatabase.ts +343 -0
- package/src/indexeddb/IDBFactory.ts +269 -0
- package/src/indexeddb/IDBIndex.ts +194 -0
- package/src/indexeddb/IDBKeyRange.ts +109 -0
- package/src/indexeddb/IDBObjectStore.ts +468 -0
- package/src/indexeddb/IDBRequest.ts +163 -0
- package/src/indexeddb/IDBTransaction.ts +207 -0
- package/src/indexeddb/index.ts +34 -0
- package/src/indexeddb/utils.ts +52 -0
- package/src/inspect/index.ts +1 -0
- package/src/inspect/inspect.ts +465 -0
- package/src/internal/detect.ts +104 -0
- package/src/locale.ts +10 -0
- package/src/location/index.ts +1059 -0
- package/src/locks/LockManager.ts +460 -0
- package/src/locks/index.ts +12 -0
- package/src/media/VideoFrame.ts +58 -0
- package/src/messaging/MessageChannel.ts +31 -0
- package/src/messaging/MessagePort.ts +180 -0
- package/src/messaging/index.ts +2 -0
- package/src/messaging.ts +247 -0
- package/src/native/NativeModules.ts +354 -0
- package/src/native/index.ts +1 -0
- package/src/navigator/Navigator.ts +351 -0
- package/src/navigator/index.ts +1 -0
- package/src/node/Buffer.ts +1786 -0
- package/src/node/index.ts +4 -0
- package/src/node/path.ts +495 -0
- package/src/node/process.ts +2528 -0
- package/src/performance/Performance.ts +532 -0
- package/src/performance/index.ts +21 -0
- package/src/polyfills/array.ts +236 -0
- package/src/polyfills/arraybuffer.ts +172 -0
- package/src/polyfills/groupby.ts +85 -0
- package/src/polyfills/index.ts +85 -0
- package/src/polyfills/intl.ts +1956 -0
- package/src/polyfills/iterator.ts +479 -0
- package/src/polyfills/promise.ts +37 -0
- package/src/polyfills/set.ts +245 -0
- package/src/polyfills/string.ts +85 -0
- package/src/polyfills/typedarray.ts +110 -0
- package/src/promise-rejection-tracking.ts +464 -0
- package/src/react-native/index.ts +388 -0
- package/src/runtime-entry.ts +55 -0
- package/src/scheduling/AnimationFrame.ts +105 -0
- package/src/scheduling/IdleCallback.ts +167 -0
- package/src/scheduling/index.ts +13 -0
- package/src/security/Capabilities.ts +1146 -0
- package/src/security/Permissions.ts +392 -0
- package/src/security/capability-bits.generated.ts +63 -0
- package/src/security/index.ts +16 -0
- package/src/sqlite/Database.ts +456 -0
- package/src/sqlite/Statement.ts +206 -0
- package/src/sqlite/constants.ts +79 -0
- package/src/sqlite/errors.ts +25 -0
- package/src/sqlite/index.ts +34 -0
- package/src/sqlite/module.js +438 -0
- package/src/storage/Storage.ts +291 -0
- package/src/storage/StorageManager.ts +91 -0
- package/src/storage/index.ts +3 -0
- package/src/stream-compat.ts +47 -0
- package/src/streams/ReadableStream.ts +4131 -0
- package/src/streams/TransformStream.ts +375 -0
- package/src/streams/WritableStream.ts +866 -0
- package/src/streams/index.ts +41 -0
- package/src/timers/Timers.ts +296 -0
- package/src/timers/index.ts +11 -0
- package/src/url/URL.ts +656 -0
- package/src/url/URLPattern.ts +850 -0
- package/src/url/URLSearchParams.ts +244 -0
- package/src/url/index.ts +9 -0
- package/src/websocket/WebSocket.ts +770 -0
- package/src/websocket/WebSocketError.ts +52 -0
- package/src/websocket/WebSocketStream.ts +628 -0
- package/src/websocket/index.ts +7 -0
- 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;
|