@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,465 @@
1
+ /**
2
+ * Object inspection utility (similar to Node's util.inspect, Bun.inspect, Deno.inspect)
3
+ *
4
+ * Pretty-prints objects with colors, depth limiting, and smart formatting.
5
+ */
6
+
7
+ export interface InspectOptions {
8
+ /** Show colors (ANSI escape codes) */
9
+ colors?: boolean;
10
+ /** Maximum depth to traverse */
11
+ depth?: number;
12
+ /** Show hidden (non-enumerable) properties */
13
+ showHidden?: boolean;
14
+ /** Maximum array/object elements to show */
15
+ maxArrayLength?: number;
16
+ /** Maximum string length */
17
+ maxStringLength?: number;
18
+ /** Compact mode (less whitespace) */
19
+ compact?: boolean;
20
+ }
21
+
22
+ const DEFAULT_OPTIONS: Required<InspectOptions> = {
23
+ colors: true,
24
+ depth: 4,
25
+ showHidden: false,
26
+ maxArrayLength: 100,
27
+ maxStringLength: 10000,
28
+ compact: true,
29
+ };
30
+
31
+ // ANSI color codes
32
+ const colors = {
33
+ reset: '\x1b[0m',
34
+ bold: '\x1b[1m',
35
+ dim: '\x1b[2m',
36
+
37
+ // Types
38
+ number: '\x1b[33m', // yellow
39
+ string: '\x1b[32m', // green
40
+ boolean: '\x1b[33m', // yellow
41
+ null: '\x1b[1m', // bold
42
+ undefined: '\x1b[2m', // dim
43
+ symbol: '\x1b[32m', // green
44
+ function: '\x1b[36m', // cyan
45
+
46
+ // Structures
47
+ key: '\x1b[0m', // reset
48
+ special: '\x1b[36m', // cyan (Date, RegExp, etc.)
49
+ bracket: '\x1b[2m', // dim
50
+ };
51
+
52
+ function colorize(text: string, color: string, useColors: boolean): string {
53
+ return useColors ? color + text + colors.reset : text;
54
+ }
55
+
56
+ function inspectPrimitive(value: any, opts: Required<InspectOptions>): string {
57
+ if (value === null) {
58
+ return colorize('null', colors.null, opts.colors);
59
+ }
60
+
61
+ if (value === undefined) {
62
+ return colorize('undefined', colors.undefined, opts.colors);
63
+ }
64
+
65
+ if (typeof value === 'number') {
66
+ return colorize(String(value), colors.number, opts.colors);
67
+ }
68
+
69
+ if (typeof value === 'boolean') {
70
+ return colorize(String(value), colors.boolean, opts.colors);
71
+ }
72
+
73
+ if (typeof value === 'string') {
74
+ const truncated = value.length > opts.maxStringLength
75
+ ? value.slice(0, opts.maxStringLength) + '...'
76
+ : value;
77
+ const escaped = JSON.stringify(truncated);
78
+ return colorize(escaped, colors.string, opts.colors);
79
+ }
80
+
81
+ if (typeof value === 'symbol') {
82
+ return colorize(String(value), colors.symbol, opts.colors);
83
+ }
84
+
85
+ if (typeof value === 'function') {
86
+ const name = value.name || 'anonymous';
87
+ const params = 'a0, a1, a2'; // Simplified - we don't have access to Function.length easily
88
+ return colorize(`[Function: ${name}]`, colors.function, opts.colors);
89
+ }
90
+
91
+ return String(value);
92
+ }
93
+
94
+ function inspectArray(arr: any[], depth: number, opts: Required<InspectOptions>, seen: Set<any>): string {
95
+ if (depth >= opts.depth) {
96
+ return colorize('[Array]', colors.special, opts.colors);
97
+ }
98
+
99
+ const items: string[] = [];
100
+ const limit = Math.min(arr.length, opts.maxArrayLength);
101
+
102
+ for (let i = 0; i < limit; i++) {
103
+ items.push(inspectValue(arr[i], depth + 1, opts, seen));
104
+ }
105
+
106
+ if (arr.length > opts.maxArrayLength) {
107
+ items.push(colorize(`... ${arr.length - opts.maxArrayLength} more items`, colors.dim, opts.colors));
108
+ }
109
+
110
+ const open = colorize('[', colors.bracket, opts.colors);
111
+ const close = colorize(']', colors.bracket, opts.colors);
112
+
113
+ if (opts.compact) {
114
+ return open + ' ' + items.join(', ') + ' ' + close;
115
+ } else {
116
+ return open + '\n ' + items.join(',\n ') + '\n' + close;
117
+ }
118
+ }
119
+
120
+ function indentMultiline(text: string, prefix: string): string {
121
+ return text.replace(/\n/g, `\n${prefix}`);
122
+ }
123
+
124
+ function isURLSearchParamsLike(value: any): boolean {
125
+ return !!value &&
126
+ typeof value === 'object' &&
127
+ typeof value.append === 'function' &&
128
+ typeof value.get === 'function' &&
129
+ typeof value.getAll === 'function' &&
130
+ typeof value.entries === 'function' &&
131
+ typeof value.toString === 'function';
132
+ }
133
+
134
+ function inspectURLSearchParamsLike(value: any): string | null {
135
+ try {
136
+ const groups: Array<{ key: string; values: string[] }> = [];
137
+
138
+ for (const entry of value.entries()) {
139
+ const key = String(entry[0]);
140
+ const entryValue = String(entry[1]);
141
+ const group = groups.find(item => item.key === key);
142
+
143
+ if (group) {
144
+ group.values.push(entryValue);
145
+ } else {
146
+ groups.push({ key, values: [entryValue] });
147
+ }
148
+ }
149
+
150
+ if (groups.length === 0) {
151
+ return 'URLSearchParams {}';
152
+ }
153
+
154
+ const lines = groups.map(group => {
155
+ const renderedValue = group.values.length === 1
156
+ ? JSON.stringify(group.values[0])
157
+ : `[ ${group.values.map(item => JSON.stringify(item)).join(', ')} ]`;
158
+ return ` ${JSON.stringify(group.key)}: ${renderedValue},`;
159
+ });
160
+
161
+ return `URLSearchParams {\n${lines.join('\n')}\n}`;
162
+ } catch {
163
+ return null;
164
+ }
165
+ }
166
+
167
+ function isURLLike(value: any): boolean {
168
+ return !!value &&
169
+ typeof value === 'object' &&
170
+ typeof value.href === 'string' &&
171
+ typeof value.origin === 'string' &&
172
+ typeof value.protocol === 'string' &&
173
+ typeof value.username === 'string' &&
174
+ typeof value.password === 'string' &&
175
+ typeof value.host === 'string' &&
176
+ typeof value.hostname === 'string' &&
177
+ typeof value.port === 'string' &&
178
+ typeof value.pathname === 'string' &&
179
+ typeof value.hash === 'string' &&
180
+ typeof value.search === 'string' &&
181
+ value.searchParams &&
182
+ typeof value.searchParams === 'object' &&
183
+ typeof value.toJSON === 'function' &&
184
+ typeof value.toString === 'function';
185
+ }
186
+
187
+ function inspectURLLike(obj: any, depth: number, opts: Required<InspectOptions>, seen: Set<any>): string {
188
+ const searchParams = indentMultiline(inspectValue(obj.searchParams, depth + 1, opts, seen), ' ');
189
+
190
+ return `URL {
191
+ href: ${JSON.stringify(obj.href)},
192
+ origin: ${JSON.stringify(obj.origin)},
193
+ protocol: ${JSON.stringify(obj.protocol)},
194
+ username: ${JSON.stringify(obj.username)},
195
+ password: ${JSON.stringify(obj.password)},
196
+ host: ${JSON.stringify(obj.host)},
197
+ hostname: ${JSON.stringify(obj.hostname)},
198
+ port: ${JSON.stringify(obj.port)},
199
+ pathname: ${JSON.stringify(obj.pathname)},
200
+ hash: ${JSON.stringify(obj.hash)},
201
+ search: ${JSON.stringify(obj.search)},
202
+ searchParams: ${searchParams},
203
+ toJSON: [Function: toJSON],
204
+ toString: [Function: toString],
205
+ }`;
206
+ }
207
+
208
+ function inspectObject(obj: any, depth: number, opts: Required<InspectOptions>, seen: Set<any>): string {
209
+ if (depth >= opts.depth) {
210
+ return colorize('[Object]', colors.special, opts.colors);
211
+ }
212
+
213
+ // Special cases - use duck typing instead of instanceof for cross-realm compatibility
214
+ if (isURLSearchParamsLike(obj)) {
215
+ const inspected = inspectURLSearchParamsLike(obj);
216
+ if (inspected !== null) {
217
+ return inspected;
218
+ }
219
+ }
220
+
221
+ if (isURLLike(obj)) {
222
+ return inspectURLLike(obj, depth, opts, seen);
223
+ }
224
+
225
+ if (typeof obj.toISOString === 'function' && typeof obj.getMonth === 'function') {
226
+ // Date object
227
+ try {
228
+ return colorize(obj.toISOString(), colors.special, opts.colors);
229
+ } catch {
230
+ return colorize(String(obj), colors.special, opts.colors);
231
+ }
232
+ }
233
+
234
+ if (typeof obj.test === 'function' && typeof obj.exec === 'function' && obj.source !== undefined) {
235
+ // RegExp object
236
+ return colorize(String(obj), colors.special, opts.colors);
237
+ }
238
+
239
+ if (obj.name && obj.message && obj.stack) {
240
+ // Error object
241
+ return colorize(`${obj.name}: ${obj.message}`, colors.special, opts.colors);
242
+ }
243
+
244
+ if (typeof obj.get === 'function' && typeof obj.set === 'function' && typeof obj.has === 'function' && typeof obj.entries === 'function' && obj.size !== undefined) {
245
+ // Map object
246
+ try {
247
+ const entries: string[] = [];
248
+ let count = 0;
249
+ for (const [key, value] of obj.entries()) {
250
+ if (count++ >= opts.maxArrayLength) break;
251
+ entries.push(
252
+ inspectValue(key, depth + 1, opts, seen) + ' => ' +
253
+ inspectValue(value, depth + 1, opts, seen)
254
+ );
255
+ }
256
+ if (obj.size > opts.maxArrayLength) {
257
+ entries.push(colorize(`... ${obj.size - opts.maxArrayLength} more entries`, colors.dim, opts.colors));
258
+ }
259
+ return colorize('Map(', colors.special, opts.colors) + obj.size + ') { ' + entries.join(', ') + ' }';
260
+ } catch {
261
+ // Fall through to regular object handling
262
+ }
263
+ }
264
+
265
+ if (typeof obj.has === 'function' && typeof obj.add === 'function' && typeof obj.values === 'function' && obj.size !== undefined) {
266
+ // Set object
267
+ try {
268
+ const values: string[] = [];
269
+ let count = 0;
270
+ for (const value of obj.values()) {
271
+ if (count++ >= opts.maxArrayLength) break;
272
+ values.push(inspectValue(value, depth + 1, opts, seen));
273
+ }
274
+ if (obj.size > opts.maxArrayLength) {
275
+ values.push(colorize(`... ${obj.size - opts.maxArrayLength} more items`, colors.dim, opts.colors));
276
+ }
277
+ return colorize('Set(', colors.special, opts.colors) + obj.size + ') { ' + values.join(', ') + ' }';
278
+ } catch {
279
+ // Fall through to regular object handling
280
+ }
281
+ }
282
+
283
+ // Module object (check for CommonJS/ES module markers)
284
+ // CommonJS modules often have __esModule or are returned from require()
285
+ if (obj.__esModule || obj.default !== undefined || obj.exports !== undefined) {
286
+ // Show as Module with exported names
287
+ const keys = Object.keys(obj).filter(k => k !== '__esModule');
288
+ if (keys.length === 0) {
289
+ return colorize('Module { }', colors.special, opts.colors);
290
+ } else if (keys.length <= 5) {
291
+ const exports = keys.map(k => colorize(k, colors.key, opts.colors)).join(', ');
292
+ return colorize('Module { ', colors.special, opts.colors) + exports + colorize(' }', colors.special, opts.colors);
293
+ } else {
294
+ const firstFive = keys.slice(0, 5).map(k => colorize(k, colors.key, opts.colors)).join(', ');
295
+ const remaining = keys.length - 5;
296
+ return colorize('Module { ', colors.special, opts.colors) +
297
+ firstFive +
298
+ colorize(`, ...${remaining} more`, colors.dim, opts.colors) +
299
+ colorize(' }', colors.special, opts.colors);
300
+ }
301
+ }
302
+
303
+ // Promise object (check for .then method)
304
+ if (typeof obj.then === 'function' && typeof obj.catch === 'function') {
305
+ try {
306
+ // Try to inspect Hermes promise internals for state
307
+ // _x: 0 = pending, 1 = fulfilled, 2 = rejected
308
+ // _z: resolved/rejected value
309
+ const state = (obj as any)._x;
310
+ const value = (obj as any)._z;
311
+
312
+ // If there's a value (even if state is still technically pending due to microtask queue)
313
+ // show it as fulfilled. This matches Chrome DevTools behavior.
314
+ if (value !== undefined && value !== null && state !== 2) {
315
+ return colorize('Promise { ', colors.special, opts.colors) +
316
+ colorize('<fulfilled>', colors.dim, opts.colors) + ': ' +
317
+ inspectValue(value, depth + 1, opts, seen) +
318
+ colorize(' }', colors.special, opts.colors);
319
+ } else if (state === 2) {
320
+ return colorize('Promise { ', colors.special, opts.colors) +
321
+ colorize('<rejected>', colors.dim, opts.colors) + ': ' +
322
+ inspectValue(value, depth + 1, opts, seen) +
323
+ colorize(' }', colors.special, opts.colors);
324
+ } else {
325
+ // Truly pending (no value yet)
326
+ return colorize('Promise { ', colors.special, opts.colors) +
327
+ colorize('<pending>', colors.dim, opts.colors) +
328
+ colorize(' }', colors.special, opts.colors);
329
+ }
330
+ } catch {
331
+ // Fall back to generic Promise label
332
+ return colorize('Promise { ... }', colors.special, opts.colors);
333
+ }
334
+ }
335
+
336
+ // Regular object
337
+ const keys = opts.showHidden
338
+ ? Object.getOwnPropertyNames(obj)
339
+ : Object.keys(obj);
340
+
341
+ if (keys.length === 0) {
342
+ return '{}';
343
+ }
344
+
345
+ const pairs: string[] = [];
346
+ const limit = Math.min(keys.length, opts.maxArrayLength);
347
+
348
+ for (let i = 0; i < limit; i++) {
349
+ const key = keys[i];
350
+ const needsQuotes = !/^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(key);
351
+ const keyStr = needsQuotes ? JSON.stringify(key) : key;
352
+ const coloredKey = colorize(keyStr, colors.key, opts.colors);
353
+ const value = inspectValue(obj[key], depth + 1, opts, seen);
354
+ pairs.push(coloredKey + ': ' + value);
355
+ }
356
+
357
+ if (keys.length > opts.maxArrayLength) {
358
+ pairs.push(colorize(`... ${keys.length - opts.maxArrayLength} more keys`, colors.dim, opts.colors));
359
+ }
360
+
361
+ const open = colorize('{', colors.bracket, opts.colors);
362
+ const close = colorize('}', colors.bracket, opts.colors);
363
+
364
+ if (opts.compact) {
365
+ return open + ' ' + pairs.join(', ') + ' ' + close;
366
+ } else {
367
+ return open + '\n ' + pairs.join(',\n ') + '\n' + close;
368
+ }
369
+ }
370
+
371
+ function inspectTypedArray(value: { length: number; [index: number]: number; constructor?: { name?: string }; [Symbol.toStringTag]?: string }, depth: number, opts: Required<InspectOptions>): string {
372
+ const isBuffer = value[Symbol.toStringTag] === 'Buffer' || (value.constructor && value.constructor.name === 'Buffer');
373
+ const typeName = isBuffer ? 'Buffer' : (value.constructor?.name || 'TypedArray');
374
+
375
+ if (isBuffer) {
376
+ // Node.js style: <Buffer 23 20 45 78 61 63 74 0a ...>
377
+ const maxBytes = 50;
378
+ const hexParts: string[] = [];
379
+ const limit = Math.min(value.length, maxBytes);
380
+ for (let i = 0; i < limit; i++) {
381
+ hexParts.push(value[i].toString(16).padStart(2, '0'));
382
+ }
383
+ const truncated = value.length > maxBytes
384
+ ? ` ... ${value.length - maxBytes} more bytes`
385
+ : '';
386
+ return colorize(`<Buffer ${hexParts.join(' ')}${truncated}>`, colors.special, opts.colors);
387
+ }
388
+
389
+ // Other TypedArrays: Uint8Array(5) [ 1, 2, 3, 4, 5 ]
390
+ const maxItems = Math.min(value.length, opts.maxArrayLength);
391
+ const items: string[] = [];
392
+ for (let i = 0; i < maxItems; i++) {
393
+ items.push(colorize(String(value[i]), colors.number, opts.colors));
394
+ }
395
+ const truncated = value.length > opts.maxArrayLength
396
+ ? colorize(` ... ${value.length - opts.maxArrayLength} more items`, colors.dim, opts.colors)
397
+ : '';
398
+ return `${typeName}(${value.length}) [ ${items.join(', ')}${truncated} ]`;
399
+ }
400
+
401
+ function inspectValue(value: any, depth: number, opts: Required<InspectOptions>, seen: Set<any>): string {
402
+ const type = typeof value;
403
+
404
+ // Primitives and functions
405
+ if (type !== 'object' || value === null) {
406
+ return inspectPrimitive(value, opts);
407
+ }
408
+
409
+ // Circular reference detection
410
+ if (seen.has(value)) {
411
+ return colorize('[Circular]', colors.special, opts.colors);
412
+ }
413
+ seen.add(value);
414
+
415
+ try {
416
+ // Buffer / TypedArray - show hex bytes like Node.js
417
+ if (ArrayBuffer.isView(value) && !(value instanceof DataView)) {
418
+ return inspectTypedArray(value as any, depth, opts);
419
+ }
420
+
421
+ // Arrays
422
+ if (Array.isArray(value)) {
423
+ return inspectArray(value, depth, opts, seen);
424
+ }
425
+
426
+ // Objects (including special types)
427
+ return inspectObject(value, depth, opts, seen);
428
+ } finally {
429
+ seen.delete(value);
430
+ }
431
+ }
432
+
433
+ /**
434
+ * Inspect a value and return a formatted string representation
435
+ * Similar to Node's util.inspect, Bun.inspect, and Deno.inspect
436
+ */
437
+ export function inspect(value: any, options?: InspectOptions): string {
438
+ const opts: Required<InspectOptions> = {
439
+ ...DEFAULT_OPTIONS,
440
+ ...options,
441
+ };
442
+
443
+ return inspectValue(value, 0, opts, new Set());
444
+ }
445
+
446
+ // Install on the Exact global — defensively: hosts may already provide an
447
+ // `inspect` (possibly as a getter-only accessor), and a convenience install
448
+ // must never hard-fail module evaluation (it broke native agent boot as the
449
+ // follow-on failure behind LLP 0176).
450
+ if (typeof globalThis.Exact !== 'undefined') {
451
+ const exactGlobal = (globalThis as { Exact?: Record<string, unknown> }).Exact!;
452
+ const descriptor = Object.getOwnPropertyDescriptor(exactGlobal, 'inspect');
453
+ if (!descriptor || descriptor.configurable || descriptor.writable) {
454
+ try {
455
+ Object.defineProperty(exactGlobal, 'inspect', {
456
+ value: inspect,
457
+ writable: true,
458
+ configurable: true,
459
+ enumerable: true,
460
+ });
461
+ } catch {
462
+ // The host owns Exact.inspect; keep its implementation.
463
+ }
464
+ }
465
+ }
@@ -0,0 +1,104 @@
1
+ /**
2
+ * Internal detection utilities
3
+ *
4
+ * These are used by modules that need to detect engine/platform
5
+ * WITHOUT importing from bootstrap (to avoid circular dependencies).
6
+ */
7
+
8
+ /**
9
+ * Get the runtime version
10
+ */
11
+ export function getRuntimeVersion(): string {
12
+ return "0.1.0";
13
+ }
14
+
15
+ /**
16
+ * Detect the JavaScript engine at runtime.
17
+ */
18
+ export function detectEngine(): "Hermes" | "JSC" | "V8" | "browser" | "unknown" {
19
+ const g = globalThis as any;
20
+
21
+ // Hermes detection
22
+ if (typeof g.HermesInternal !== "undefined") {
23
+ return "Hermes";
24
+ }
25
+
26
+ // Browser detection (must come before V8 check since Chrome has both)
27
+ if (typeof document !== "undefined" && document.createElement) {
28
+ return "browser";
29
+ }
30
+
31
+ // V8 detection (Node.js or standalone V8)
32
+ if (typeof g.v8debug !== "undefined" || g._v8runtime) {
33
+ return "V8";
34
+ }
35
+
36
+ // JSC detection (JavaScriptCore specific globals)
37
+ if (typeof g.gc === "function" && !g.v8debug) {
38
+ return "JSC";
39
+ }
40
+
41
+ return "unknown";
42
+ }
43
+
44
+ /**
45
+ * Detect the platform at runtime.
46
+ * Note: This must NOT access navigator to avoid circular dependency.
47
+ */
48
+ export function detectPlatform(): string {
49
+ const g = globalThis as any;
50
+
51
+ if (typeof g.__exactPlatform === "string" && g.__exactPlatform.length > 0) {
52
+ return g.__exactPlatform;
53
+ }
54
+
55
+ // Browser/web detection (check for DOM document, not our window shim)
56
+ if (typeof document !== "undefined" && document.createElement) {
57
+ return "web";
58
+ }
59
+
60
+ // If process exists (CLI/Node-like), prefer it unless it's Exact's process shim.
61
+ const hostProcess = g.process;
62
+ if (hostProcess) {
63
+ let isExactProcess = false;
64
+ try {
65
+ const versions = hostProcess.versions;
66
+ isExactProcess = !!(versions && typeof versions === "object" && (typeof versions.ibex === "string" || typeof versions.exact === "string"));
67
+ } catch {
68
+ isExactProcess = false;
69
+ }
70
+ if (!isExactProcess) {
71
+ try {
72
+ const platform = hostProcess.platform;
73
+ if (typeof platform === "string" && platform.length > 0) {
74
+ return platform;
75
+ }
76
+ } catch {
77
+ // Ignore host process platform lookup errors and continue fallback chain.
78
+ }
79
+ }
80
+ }
81
+
82
+ // Check for Hermes-specific platform hints
83
+ if (typeof g.HermesInternal !== "undefined") {
84
+ // Hermes is used in Exact for iOS/Android
85
+ // Default to iOS since that's our primary target
86
+ return "ios";
87
+ }
88
+
89
+ return "unknown";
90
+ }
91
+
92
+ /**
93
+ * Runtime info object with lazy getters
94
+ */
95
+ export const runtimeInfo = {
96
+ name: "Exact",
97
+ version: getRuntimeVersion(),
98
+ get engine() {
99
+ return detectEngine();
100
+ },
101
+ get platform() {
102
+ return detectPlatform();
103
+ },
104
+ };
package/src/locale.ts ADDED
@@ -0,0 +1,10 @@
1
+ export {
2
+ _resetExactLocaleForTests,
3
+ clearExactLocaleOverride,
4
+ getExactLocaleSnapshot,
5
+ installExactLocaleGlobal,
6
+ refreshExactLocale,
7
+ setExactLocaleOverride,
8
+ subscribeExactLocaleChanges,
9
+ type ExactLocaleSnapshot,
10
+ } from './core/locale.js';