@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,697 @@
1
+ var g = globalThis;
2
+
3
+ function b64ToBytes(b64) {
4
+ if (!b64) return new Uint8Array(0);
5
+ var chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
6
+ var lookup = {};
7
+ for (var i = 0; i < chars.length; i++) lookup[chars[i]] = i;
8
+ var raw = b64.replace(/[^A-Za-z0-9+/]/g, "");
9
+ var len = raw.length;
10
+ var bytes = new Uint8Array(Math.ceil(len * 3 / 4));
11
+ var j = 0;
12
+ for (var i = 0; i < len; i += 4) {
13
+ var a = lookup[raw[i]] || 0;
14
+ var b = lookup[raw[i+1]] || 0;
15
+ var c = lookup[raw[i+2]] || 0;
16
+ var d = lookup[raw[i+3]] || 0;
17
+ bytes[j++] = (a << 2) | (b >> 4);
18
+ if (i + 2 < len) bytes[j++] = ((b & 15) << 4) | (c >> 2);
19
+ if (i + 3 < len) bytes[j++] = ((c & 3) << 6) | d;
20
+ }
21
+ return bytes.slice(0, j);
22
+ }
23
+
24
+ function toBytes(data) {
25
+ if (!data) return new Uint8Array(0);
26
+ if (data instanceof Uint8Array) return data;
27
+ if (data instanceof ArrayBuffer) return new Uint8Array(data);
28
+ if (typeof data === "string") {
29
+ if (typeof TextEncoder !== "undefined") return new TextEncoder().encode(data);
30
+ var buf = new Uint8Array(data.length * 3), o = 0;
31
+ for (var i = 0; i < data.length; i++) {
32
+ var c = data.charCodeAt(i);
33
+ if (c < 0x80) buf[o++] = c;
34
+ else if (c < 0x800) { buf[o++] = 0xc0|(c>>6); buf[o++] = 0x80|(c&0x3f); }
35
+ else { buf[o++] = 0xe0|(c>>12); buf[o++] = 0x80|((c>>6)&0x3f); buf[o++] = 0x80|(c&0x3f); }
36
+ }
37
+ return buf.slice(0, o);
38
+ }
39
+ return new Uint8Array(0);
40
+ }
41
+
42
+ function responseBodyPayload(data) {
43
+ if (!data) return null;
44
+ if (data instanceof Uint8Array) {
45
+ return {
46
+ buffer: data.buffer,
47
+ byteOffset: data.byteOffset || 0,
48
+ byteLength: data.byteLength || data.length || 0,
49
+ };
50
+ }
51
+ if (data instanceof ArrayBuffer) {
52
+ return {
53
+ buffer: data,
54
+ byteOffset: 0,
55
+ byteLength: data.byteLength || 0,
56
+ };
57
+ }
58
+ return data;
59
+ }
60
+
61
+ function createReadableRequestBody(streamId, requestId) {
62
+ return new ReadableStream({
63
+ pull: function(controller) {
64
+ return new Promise(function(resolve, reject) {
65
+ function poll() {
66
+ if (typeof g.__exactHttpReadBody !== "function") {
67
+ reject(new Error("Request body streaming unavailable"));
68
+ return;
69
+ }
70
+
71
+ var resultJson = g.__exactHttpReadBody(streamId, requestId);
72
+ if (!resultJson) {
73
+ resolve();
74
+ return;
75
+ }
76
+
77
+ var result = JSON.parse(resultJson);
78
+ if (result.error) {
79
+ reject(new Error(result.error));
80
+ return;
81
+ }
82
+
83
+ if (result.done) {
84
+ controller.close();
85
+ resolve();
86
+ return;
87
+ }
88
+
89
+ if (result.chunk) {
90
+ controller.enqueue(b64ToBytes(result.chunk));
91
+ resolve();
92
+ return;
93
+ }
94
+
95
+ setTimeout(poll, 0);
96
+ }
97
+
98
+ poll();
99
+ });
100
+ }
101
+ });
102
+ }
103
+
104
+ var MAX_REQUEST_HEADERS = 128;
105
+ var MAX_REQUEST_HEADER_BYTES = 16 * 1024;
106
+ var MAX_REQUEST_BODY_BYTES = 1024 * 1024;
107
+ var MAX_RESPONSE_BODY_BYTES = 4 * 1024 * 1024;
108
+ var HTTP_OK = 200;
109
+ var HTTP_BAD_REQUEST = 400;
110
+ var HTTP_REQUEST_TIMEOUT = 408;
111
+ var HTTP_REQUEST_ENTITY_TOO_LARGE = 413;
112
+ var HTTP_INTERNAL_SERVER_ERROR = 500;
113
+
114
+ // Fast-path response functions available
115
+ var hasRespondText = typeof g.__exactHttpRespondText === "function";
116
+ var hasRespondJson = typeof g.__exactHttpRespondJson === "function";
117
+ var hasRespondString = typeof g.__exactHttpRespondString === "function";
118
+ var hasPoll = typeof g.__exactHttpPoll === "function";
119
+ var hasDrain = typeof g.__exactHttpDrain === "function";
120
+
121
+ function ensureHttpHostFunctions() {
122
+ if (typeof g.__exactHttpServe === "function") {
123
+ return;
124
+ }
125
+ if (typeof g.__exactEnsureHttp === "function") {
126
+ g.__exactEnsureHttp();
127
+ }
128
+ hasRespondText = typeof g.__exactHttpRespondText === "function";
129
+ hasRespondJson = typeof g.__exactHttpRespondJson === "function";
130
+ hasRespondString = typeof g.__exactHttpRespondString === "function";
131
+ hasPoll = typeof g.__exactHttpPoll === "function";
132
+ hasDrain = typeof g.__exactHttpDrain === "function";
133
+ }
134
+
135
+ // Item 9: Cache common HTTP method strings to reduce allocations
136
+ var METHOD_GET = "GET";
137
+ var METHOD_POST = "POST";
138
+ var METHOD_PUT = "PUT";
139
+ var METHOD_DELETE = "DELETE";
140
+ var METHOD_PATCH = "PATCH";
141
+ var METHOD_HEAD = "HEAD";
142
+ var METHOD_OPTIONS = "OPTIONS";
143
+
144
+ // Item 9: Method string interning cache
145
+ var methodCache = {};
146
+ methodCache[METHOD_GET] = METHOD_GET;
147
+ methodCache[METHOD_POST] = METHOD_POST;
148
+ methodCache[METHOD_PUT] = METHOD_PUT;
149
+ methodCache[METHOD_DELETE] = METHOD_DELETE;
150
+ methodCache[METHOD_PATCH] = METHOD_PATCH;
151
+ methodCache[METHOD_HEAD] = METHOD_HEAD;
152
+ methodCache[METHOD_OPTIONS] = METHOD_OPTIONS;
153
+
154
+ function internMethod(m) {
155
+ return methodCache[m] || m;
156
+ }
157
+
158
+ function clampStatus(status) {
159
+ var n = Number(status);
160
+ if (!isFinite(n) || n < 100 || n > 999) {
161
+ return HTTP_INTERNAL_SERVER_ERROR;
162
+ }
163
+ return Math.floor(n);
164
+ }
165
+
166
+ function stringifyError(error) {
167
+ if (!error) {
168
+ return "";
169
+ }
170
+ if (typeof error.message === "string") {
171
+ return error.message;
172
+ }
173
+ if (typeof error === "string") {
174
+ return error;
175
+ }
176
+ return String(error);
177
+ }
178
+
179
+ function mapRequestErrorStatus(message) {
180
+ var lower = (message || "").toLowerCase();
181
+ if (lower.indexOf("payload too large") !== -1) {
182
+ return HTTP_REQUEST_ENTITY_TOO_LARGE;
183
+ }
184
+ if (lower.indexOf("request timeout") !== -1 || lower.indexOf("timeout") !== -1) {
185
+ return HTTP_REQUEST_TIMEOUT;
186
+ }
187
+ if (lower.indexOf("bad request") !== -1 || lower.indexOf("malformed") !== -1) {
188
+ return HTTP_BAD_REQUEST;
189
+ }
190
+ return HTTP_INTERNAL_SERVER_ERROR;
191
+ }
192
+
193
+ function normalizeHeaders(list) {
194
+ if (!list || !list.length) return {pairs: [], bytes: 0, ok: true};
195
+ var totalBytes = 0;
196
+ var pairs = [];
197
+ for (var i = 0; i < list.length; i++) {
198
+ if (pairs.length >= MAX_REQUEST_HEADERS) {
199
+ return {pairs: pairs, bytes: totalBytes, ok: false};
200
+ }
201
+ var item = list[i];
202
+ if (!item || !item.length || item.length < 2 || item.length > 2) {
203
+ return {pairs: pairs, bytes: totalBytes, ok: false};
204
+ }
205
+ var key = item[0];
206
+ var value = item[1];
207
+ if (typeof key !== "string" || typeof value !== "string") {
208
+ return {pairs: pairs, bytes: totalBytes, ok: false};
209
+ }
210
+ totalBytes += key.length + value.length;
211
+ if (totalBytes > MAX_REQUEST_HEADER_BYTES) {
212
+ return {pairs: pairs, bytes: totalBytes, ok: false};
213
+ }
214
+ pairs.push([key, value]);
215
+ }
216
+ return {pairs: pairs, bytes: totalBytes, ok: true};
217
+ }
218
+
219
+ function serve(options) {
220
+ if (!options || typeof options.fetch !== "function") {
221
+ throw new TypeError("serve() requires a fetch function");
222
+ }
223
+ ensureHttpHostFunctions();
224
+ if (typeof g.__exactHttpServe !== "function") {
225
+ throw new Error("Exact HTTP server bridge is unavailable in this runtime");
226
+ }
227
+ var port = options.port || 0;
228
+ var hostnameProvided = Object.prototype.hasOwnProperty.call(options, "hostname");
229
+ var hostname = hostnameProvided ? options.hostname : "127.0.0.1";
230
+ var fetchFn = options.fetch;
231
+
232
+ var resultJson = g.__exactHttpServe(port, hostname);
233
+ var result = JSON.parse(resultJson);
234
+ if (result.error) {
235
+ throw new Error(result.error);
236
+ }
237
+
238
+ var serverId = result.id;
239
+ var boundPort = result.port;
240
+ var closed = false;
241
+
242
+ // Re-check fast-path availability after serve() init
243
+ hasRespondText = typeof g.__exactHttpRespondText === "function";
244
+ hasRespondJson = typeof g.__exactHttpRespondJson === "function";
245
+ hasRespondString = typeof g.__exactHttpRespondString === "function";
246
+ hasPoll = typeof g.__exactHttpPoll === "function";
247
+ hasDrain = typeof g.__exactHttpDrain === "function";
248
+
249
+ // Pre-compute URL prefix once (avoid per-request string concat)
250
+ var requestHost = !hostnameProvided || hostname === "0.0.0.0" ? "localhost" : hostname;
251
+ var urlPrefix = "http://" + requestHost + ":" + boundPort;
252
+
253
+ function failResponse(requestId, status, message) {
254
+ var body = responseBodyPayload(toBytes(message || ""));
255
+ g.__exactHttpRespond(serverId, requestId, status, null, body);
256
+ }
257
+
258
+ // Concurrent request dispatch
259
+ var waitCount = 0;
260
+ var MAX_CONCURRENT_WAITS = 4;
261
+
262
+ function waitForNextRequest() {
263
+ if (closed) return;
264
+ if (waitCount >= MAX_CONCURRENT_WAITS) return;
265
+
266
+ // Item 6: Synchronous poll fast-path
267
+ // Try to dequeue a request synchronously before falling back to async wait.
268
+ if (hasPoll) {
269
+ var syncJson = g.__exactHttpPoll(serverId);
270
+ if (syncJson) {
271
+ // Got a request synchronously - handle it and keep polling
272
+ handleRequest(syncJson);
273
+ // Use setTimeout(0) to yield back to event loop before next sync poll
274
+ // This prevents starving timers/callbacks during high load
275
+ if (!closed) {
276
+ setTimeout(waitForNextRequest, 0);
277
+ }
278
+ return;
279
+ }
280
+ }
281
+
282
+ // Item 8: Try batch drain before falling back to single async wait
283
+ if (hasDrain) {
284
+ var batchJson = g.__exactHttpDrain(serverId, 16);
285
+ if (batchJson) {
286
+ var batch;
287
+ try {
288
+ batch = JSON.parse(batchJson);
289
+ } catch(e) {
290
+ batch = null;
291
+ }
292
+ if (batch && batch.length > 0) {
293
+ for (var i = 0; i < batch.length; i++) {
294
+ handleRequestObj(batch[i]);
295
+ }
296
+ if (!closed) {
297
+ setTimeout(waitForNextRequest, 0);
298
+ }
299
+ return;
300
+ }
301
+ }
302
+ }
303
+
304
+ if (typeof g.__exactHttpWait !== "function") {
305
+ closed = true;
306
+ throw new Error("Exact HTTP dispatcher unavailable: __exactHttpWait is not defined");
307
+ }
308
+
309
+ waitCount++;
310
+ var waitPromise = g.__exactHttpWait(serverId, 0);
311
+ if (!waitPromise || typeof waitPromise.then !== "function") {
312
+ waitCount--;
313
+ if (!closed) {
314
+ waitForNextRequest();
315
+ }
316
+ return;
317
+ }
318
+
319
+ waitPromise.then(function(reqJson) {
320
+ waitCount--;
321
+ if (closed) return;
322
+
323
+ if (reqJson) {
324
+ handleRequest(reqJson);
325
+ }
326
+
327
+ if (!closed) {
328
+ waitForNextRequest();
329
+ }
330
+ }).catch(function() {
331
+ waitCount--;
332
+ if (!closed) {
333
+ waitForNextRequest();
334
+ }
335
+ });
336
+ }
337
+
338
+ // Item 9: Process a pre-parsed request object (from batch drain)
339
+ function handleRequestObj(req) {
340
+ if (!req || typeof req.method !== "string" || !req.url || typeof req.id !== "number") {
341
+ return;
342
+ }
343
+
344
+ if (req.url.charAt(0) !== "/") {
345
+ failResponse(req.id, HTTP_BAD_REQUEST, "Bad Request: malformed URL");
346
+ return;
347
+ }
348
+
349
+ processRequest(req);
350
+ }
351
+
352
+ function handleRequest(jsonStr) {
353
+ var req;
354
+ try {
355
+ req = JSON.parse(jsonStr);
356
+ } catch(e) {
357
+ return;
358
+ }
359
+
360
+ if (!req || typeof req.method !== "string" || !req.url || typeof req.id !== "number") {
361
+ return;
362
+ }
363
+
364
+ if (req.url.charAt(0) !== "/") {
365
+ failResponse(req.id, HTTP_BAD_REQUEST, "Bad Request: malformed URL");
366
+ return;
367
+ }
368
+
369
+ processRequest(req);
370
+ }
371
+
372
+ // Item 9: Shared request processing logic to avoid duplication
373
+ function processRequest(req) {
374
+ var headerState = normalizeHeaders(req.headers || []);
375
+ if (!headerState.ok) {
376
+ failResponse(req.id, HTTP_BAD_REQUEST, "Bad Request: malformed headers");
377
+ return;
378
+ }
379
+
380
+ // Item 9: Use interned method strings
381
+ var method = internMethod(req.method);
382
+
383
+ var init = {
384
+ method: method,
385
+ headers: headerState.pairs
386
+ };
387
+
388
+ // Item 9: Fast path for GET/HEAD - skip body processing entirely
389
+ if (req.hasBody && method !== METHOD_GET && method !== METHOD_HEAD) {
390
+ if (req.body) {
391
+ init.body = b64ToBytes(req.body);
392
+ } else {
393
+ init.body = createReadableRequestBody(serverId, req.id);
394
+ }
395
+ }
396
+
397
+ var request;
398
+ // Use pre-computed URL prefix
399
+ var url = urlPrefix + req.url;
400
+ try {
401
+ request = new Request(url, init);
402
+ } catch(e) {
403
+ failResponse(req.id, HTTP_BAD_REQUEST, "Bad Request: " + (e && e.message || e));
404
+ return;
405
+ }
406
+
407
+ try {
408
+ var p = fetchFn(request);
409
+ if (p && typeof p.then === "function") {
410
+ p.then(function(response) {
411
+ sendResponse(req.id, response);
412
+ }).catch(function(err) {
413
+ var message = stringifyError(err);
414
+ var status = mapRequestErrorStatus(message);
415
+ if (status === HTTP_INTERNAL_SERVER_ERROR) {
416
+ failResponse(req.id, status, "Internal Server Error: " + message);
417
+ } else {
418
+ failResponse(req.id, status, "Request Error: " + message);
419
+ }
420
+ });
421
+ } else {
422
+ sendResponse(req.id, p);
423
+ }
424
+ } catch(err) {
425
+ var message = stringifyError(err);
426
+ var status = mapRequestErrorStatus(message);
427
+ if (status === HTTP_INTERNAL_SERVER_ERROR) {
428
+ failResponse(req.id, status, "Internal Server Error: " + message);
429
+ } else {
430
+ failResponse(req.id, status, "Request Error: " + message);
431
+ }
432
+ }
433
+ }
434
+
435
+ function sendResponse(requestId, response) {
436
+ if (!response || typeof response !== "object") {
437
+ failResponse(requestId, HTTP_INTERNAL_SERVER_ERROR, "Internal Server Error: malformed response");
438
+ return;
439
+ }
440
+
441
+ var status = HTTP_OK;
442
+ if (response.status !== undefined) {
443
+ status = clampStatus(response.status);
444
+ }
445
+
446
+ // Fast-path for simple text/json responses
447
+ var body = response.body;
448
+ var hasBodyStream = !!(body && typeof body.getReader === "function");
449
+
450
+ if (!hasBodyStream && typeof response.arrayBuffer === "function") {
451
+ var contentType = null;
452
+ var headerCount = 0;
453
+ var hasContentLength = false;
454
+ if (response.headers && typeof response.headers.get === "function") {
455
+ contentType = response.headers.get("content-type");
456
+ if (typeof response.headers.forEach === "function") {
457
+ response.headers.forEach(function(v, k) {
458
+ headerCount++;
459
+ if (k === "content-length") hasContentLength = true;
460
+ });
461
+ }
462
+ }
463
+
464
+ // Use fast text/json path if only content-type (and maybe content-length) headers
465
+ if (contentType && headerCount <= 2) {
466
+ var isText = hasRespondText && contentType.indexOf("text/plain") === 0;
467
+ var isJson = hasRespondJson && (contentType.indexOf("application/json") === 0);
468
+
469
+ if (isText || isJson) {
470
+ response.arrayBuffer().then(function(ab) {
471
+ var bytes = new Uint8Array(ab);
472
+ if (bytes.length > MAX_RESPONSE_BODY_BYTES) {
473
+ failResponse(requestId, HTTP_REQUEST_ENTITY_TOO_LARGE, "Response Too Large");
474
+ return;
475
+ }
476
+ var payload = responseBodyPayload(bytes);
477
+ if (isText) {
478
+ g.__exactHttpRespondText(serverId, requestId, status, payload);
479
+ } else {
480
+ g.__exactHttpRespondJson(serverId, requestId, status, payload);
481
+ }
482
+ }).catch(function(err) {
483
+ failResponse(requestId, HTTP_INTERNAL_SERVER_ERROR, "Internal Server Error: " + (err && err.message || err));
484
+ });
485
+ return;
486
+ }
487
+ }
488
+ }
489
+
490
+ // Item 10: Zero-copy string response path
491
+ // If the response body is a string and we have __exactHttpRespondString,
492
+ // pass it directly without converting to Uint8Array first
493
+ if (hasRespondString && !hasBodyStream && typeof response.text === "function") {
494
+ var ct = null;
495
+ if (response.headers && typeof response.headers.get === "function") {
496
+ ct = response.headers.get("content-type");
497
+ }
498
+ // Use string path for text-based content types
499
+ if (ct && (ct.indexOf("text/") === 0 || ct.indexOf("application/json") === 0 || ct.indexOf("application/xml") === 0)) {
500
+ // Serialize headers once
501
+ var strHeaderPairs = [];
502
+ var strTotalBytes = 0;
503
+ var strHeadersOk = true;
504
+ if (response.headers && typeof response.headers.forEach === "function") {
505
+ try {
506
+ response.headers.forEach(function(value, key) {
507
+ key = String(key);
508
+ value = String(value);
509
+ strHeaderPairs.push([key, value]);
510
+ strTotalBytes += key.length + value.length;
511
+ });
512
+ } catch(e) {
513
+ strHeadersOk = false;
514
+ }
515
+ }
516
+ if (strHeadersOk && strHeaderPairs.length <= MAX_REQUEST_HEADERS && strTotalBytes <= MAX_REQUEST_HEADER_BYTES) {
517
+ var strHeadersJson = JSON.stringify(strHeaderPairs);
518
+ response.text().then(function(text) {
519
+ if (text.length > MAX_RESPONSE_BODY_BYTES) {
520
+ failResponse(requestId, HTTP_REQUEST_ENTITY_TOO_LARGE, "Response Too Large");
521
+ return;
522
+ }
523
+ g.__exactHttpRespondString(serverId, requestId, status, strHeadersJson, text);
524
+ }).catch(function(err) {
525
+ failResponse(requestId, HTTP_INTERNAL_SERVER_ERROR, "Internal Server Error: " + (err && err.message || err));
526
+ });
527
+ return;
528
+ }
529
+ }
530
+ }
531
+
532
+ // Standard path: serialize all headers
533
+ var headerPairs = [];
534
+ if (response.headers) {
535
+ if (typeof response.headers.forEach !== "function") {
536
+ failResponse(requestId, HTTP_INTERNAL_SERVER_ERROR, "Internal Server Error: malformed response headers");
537
+ return;
538
+ }
539
+
540
+ var totalHeaderBytes = 0;
541
+ try {
542
+ response.headers.forEach(function(value, key) {
543
+ key = String(key);
544
+ value = String(value);
545
+ headerPairs.push([key, value]);
546
+ totalHeaderBytes += key.length + value.length;
547
+ });
548
+ } catch (err) {
549
+ failResponse(requestId, HTTP_INTERNAL_SERVER_ERROR, "Internal Server Error: malformed response headers");
550
+ return;
551
+ }
552
+
553
+ if (headerPairs.length > MAX_REQUEST_HEADERS || totalHeaderBytes > MAX_REQUEST_HEADER_BYTES) {
554
+ failResponse(requestId, HTTP_INTERNAL_SERVER_ERROR, "Internal Server Error: response headers too large");
555
+ return;
556
+ }
557
+ }
558
+ var headersJson = JSON.stringify(headerPairs);
559
+
560
+ if (!hasBodyStream && (typeof response.body === "undefined" || response.body === null)) {
561
+ g.__exactHttpRespond(serverId, requestId, status, headersJson, null);
562
+ return;
563
+ }
564
+
565
+ function respondWithBytes(bytes) {
566
+ if (!bytes) {
567
+ g.__exactHttpRespond(serverId, requestId, status, headersJson, null);
568
+ return;
569
+ }
570
+ if (bytes.length > MAX_RESPONSE_BODY_BYTES) {
571
+ failResponse(requestId, HTTP_REQUEST_ENTITY_TOO_LARGE, "Response Too Large");
572
+ return;
573
+ }
574
+ g.__exactHttpRespond(serverId, requestId, status, headersJson, responseBodyPayload(bytes));
575
+ }
576
+
577
+ if (hasBodyStream && typeof g.__exactHttpRespondStream === "function" &&
578
+ typeof g.__exactHttpRespondChunk === "function" &&
579
+ typeof g.__exactHttpRespondEnd === "function") {
580
+ var respondStarted = g.__exactHttpRespondStream(serverId, requestId, status, headersJson);
581
+ if (respondStarted !== 0) {
582
+ failResponse(requestId, HTTP_INTERNAL_SERVER_ERROR, "Internal Server Error: failed to start response");
583
+ return;
584
+ }
585
+
586
+ var streamReader = body.getReader();
587
+ function writeBody() {
588
+ return streamReader.read().then(function(result) {
589
+ if (result.done) {
590
+ g.__exactHttpRespondEnd(serverId, requestId);
591
+ return;
592
+ }
593
+
594
+ var chunk = result.value || new Uint8Array(0);
595
+ var writeResult = g.__exactHttpRespondChunk(serverId, requestId, responseBodyPayload(chunk));
596
+ if (writeResult === 0) {
597
+ return writeBody();
598
+ }
599
+
600
+ if (streamReader.cancel) {
601
+ streamReader.cancel("stream aborted");
602
+ }
603
+ g.__exactHttpRespondEnd(serverId, requestId);
604
+ throw new Error("Failed to write response chunk");
605
+ }).catch(function() {
606
+ g.__exactHttpRespondEnd(serverId, requestId);
607
+ });
608
+ }
609
+
610
+ writeBody();
611
+ return;
612
+ }
613
+
614
+ if (typeof response.arrayBuffer === "function" && !hasBodyStream) {
615
+ response.arrayBuffer().then(function(ab) {
616
+ respondWithBytes(new Uint8Array(ab));
617
+ }).catch(function(err) {
618
+ failResponse(requestId, HTTP_INTERNAL_SERVER_ERROR, "Internal Server Error: " + (err && err.message || err));
619
+ });
620
+ return;
621
+ }
622
+
623
+ if (!hasBodyStream) {
624
+ g.__exactHttpRespond(serverId, requestId, status, headersJson, null);
625
+ return;
626
+ }
627
+
628
+ {
629
+ var chunks = [];
630
+ var totalSize = 0;
631
+ var reader = body.getReader();
632
+ function readBody() {
633
+ return reader.read().then(function(result) {
634
+ if (result.done) {
635
+ var combined = new Uint8Array(totalSize);
636
+ var offset = 0;
637
+ for (var i = 0; i < chunks.length; i++) {
638
+ var chunk = chunks[i];
639
+ combined.set(chunk, offset);
640
+ offset += chunk.length;
641
+ }
642
+ respondWithBytes(combined);
643
+ return;
644
+ }
645
+ var chunk = result.value || new Uint8Array(0);
646
+ totalSize += chunk.length;
647
+ if (totalSize > MAX_RESPONSE_BODY_BYTES) {
648
+ reader.cancel("response too large");
649
+ throw new Error("Response Too Large");
650
+ }
651
+ chunks.push(chunk);
652
+ return readBody();
653
+ });
654
+ }
655
+
656
+ readBody().catch(function(err) {
657
+ failResponse(requestId, HTTP_INTERNAL_SERVER_ERROR, "Internal Server Error: " + (err && err.message || err));
658
+ });
659
+ return;
660
+ }
661
+ }
662
+
663
+ // Start multiple concurrent waiters for better throughput
664
+ waitForNextRequest();
665
+ waitForNextRequest();
666
+ waitForNextRequest();
667
+ waitForNextRequest();
668
+
669
+ var handle = {
670
+ close: function(opts) {
671
+ if (closed) return Promise.resolve();
672
+ closed = true;
673
+ waitCount = 0;
674
+ var force = false;
675
+ if (opts && opts.force) {
676
+ force = !!opts.force;
677
+ }
678
+ g.__exactHttpClose(serverId, force ? 1 : 0);
679
+ return Promise.resolve();
680
+ },
681
+ ref: function() {
682
+ g.__exactHttpSetRef(serverId, 1);
683
+ },
684
+ unref: function() {
685
+ g.__exactHttpSetRef(serverId, 0);
686
+ },
687
+ address: function() {
688
+ var json = g.__exactHttpAddress(serverId);
689
+ if (!json) return null;
690
+ return JSON.parse(json);
691
+ }
692
+ };
693
+
694
+ return Promise.resolve(handle);
695
+ }
696
+
697
+ export { serve };