@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,354 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Native Module Interfaces
|
|
3
|
+
*
|
|
4
|
+
* These interfaces define the bridge between JavaScript and native code.
|
|
5
|
+
* The native side (Swift/Rust) must implement these for production use.
|
|
6
|
+
* JavaScript fallbacks exist for testing.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
// =============================================================================
|
|
10
|
+
// Timer Module (MUST BE NATIVE)
|
|
11
|
+
// Native implementation handles event loop integration
|
|
12
|
+
// =============================================================================
|
|
13
|
+
export interface NativeTimerModule {
|
|
14
|
+
setTimeout(callback: () => void, delay: number): number;
|
|
15
|
+
clearTimeout(id: number): void;
|
|
16
|
+
setInterval(callback: () => void, delay: number): number;
|
|
17
|
+
clearInterval(id: number): void;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
// =============================================================================
|
|
21
|
+
// Performance Module (MUST BE NATIVE)
|
|
22
|
+
// Native implementation provides monotonic clock
|
|
23
|
+
// =============================================================================
|
|
24
|
+
export interface NativePerformanceModule {
|
|
25
|
+
/** High-resolution timestamp in milliseconds since timeOrigin */
|
|
26
|
+
now(): number;
|
|
27
|
+
/** Unix timestamp when the runtime started */
|
|
28
|
+
timeOrigin: number;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// =============================================================================
|
|
32
|
+
// Crypto Module (MUST BE NATIVE)
|
|
33
|
+
// Native implementation uses CryptoKit/RustCrypto for security
|
|
34
|
+
// =============================================================================
|
|
35
|
+
export interface NativeCryptoModule {
|
|
36
|
+
/** Fill array with cryptographically secure random bytes */
|
|
37
|
+
getRandomValues(array: Uint8Array): Uint8Array;
|
|
38
|
+
/** Generate a random UUID v4 */
|
|
39
|
+
randomUUID(): string;
|
|
40
|
+
/** SHA-256 hash */
|
|
41
|
+
sha256(data: Uint8Array): Promise<ArrayBuffer>;
|
|
42
|
+
/** SHA-384 hash */
|
|
43
|
+
sha384(data: Uint8Array): Promise<ArrayBuffer>;
|
|
44
|
+
/** SHA-512 hash */
|
|
45
|
+
sha512(data: Uint8Array): Promise<ArrayBuffer>;
|
|
46
|
+
/** SHA-1 hash (legacy, not recommended) */
|
|
47
|
+
sha1(data: Uint8Array): Promise<ArrayBuffer>;
|
|
48
|
+
/** Generic hash digest */
|
|
49
|
+
digest?: (hash: string, data: Uint8Array) => Promise<ArrayBuffer>;
|
|
50
|
+
/** Native HMAC sign helper */
|
|
51
|
+
hmacSign?: (hash: string, key: Uint8Array, data: Uint8Array) => Promise<ArrayBuffer>;
|
|
52
|
+
/** Native HMAC verify helper */
|
|
53
|
+
hmacVerify?: (hash: string, key: Uint8Array, signature: Uint8Array, data: Uint8Array) => Promise<boolean>;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// =============================================================================
|
|
57
|
+
// Encoding Module (SHOULD BE NATIVE for large strings)
|
|
58
|
+
// Native implementation is faster for large payloads
|
|
59
|
+
// =============================================================================
|
|
60
|
+
export interface NativeEncodingModule {
|
|
61
|
+
/** Encode string to UTF-8 bytes */
|
|
62
|
+
encodeUTF8(input: string): Uint8Array;
|
|
63
|
+
/** Decode UTF-8 bytes to string */
|
|
64
|
+
decodeUTF8(input: Uint8Array, fatal?: boolean): string;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// =============================================================================
|
|
68
|
+
// Console Module (Native output)
|
|
69
|
+
// Native handles actual logging to system console/debugger
|
|
70
|
+
// =============================================================================
|
|
71
|
+
export interface NativeConsoleModule {
|
|
72
|
+
log(level: string, message: string): void;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// =============================================================================
|
|
76
|
+
// Fetch Module (MUST BE NATIVE)
|
|
77
|
+
// Native implementation uses URLSession/OkHttp
|
|
78
|
+
// =============================================================================
|
|
79
|
+
export interface NativeFetchModule {
|
|
80
|
+
fetch(
|
|
81
|
+
url: string,
|
|
82
|
+
options: {
|
|
83
|
+
method?: string;
|
|
84
|
+
headers?: Record<string, string>;
|
|
85
|
+
body?: Uint8Array | string;
|
|
86
|
+
signal?: { aborted: boolean };
|
|
87
|
+
}
|
|
88
|
+
): Promise<{
|
|
89
|
+
status: number;
|
|
90
|
+
statusText: string;
|
|
91
|
+
headers: Record<string, string>;
|
|
92
|
+
body: Uint8Array;
|
|
93
|
+
}>;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// =============================================================================
|
|
97
|
+
// WebSocket Module (MUST BE NATIVE)
|
|
98
|
+
// Native implementation uses platform WebSocket
|
|
99
|
+
// =============================================================================
|
|
100
|
+
export interface NativeWebSocketModule {
|
|
101
|
+
create(url: string, protocols?: string[], instance?: any): number; // Returns socket ID
|
|
102
|
+
send(id: number, data: string | Uint8Array): void;
|
|
103
|
+
close(id: number, code?: number, reason?: string): void;
|
|
104
|
+
pause?(id: number): void;
|
|
105
|
+
resume?(id: number): void;
|
|
106
|
+
setFlowControlled?(id: number, enabled: boolean): void;
|
|
107
|
+
// Events are dispatched via callbacks set during creation
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// =============================================================================
|
|
111
|
+
// Storage Module (MUST BE NATIVE - SQLite in Rust kernel)
|
|
112
|
+
// =============================================================================
|
|
113
|
+
export interface NativeStorageModule {
|
|
114
|
+
getItem(key: string): string | null;
|
|
115
|
+
setItem(key: string, value: string): void; // May throw QuotaExceededError
|
|
116
|
+
removeItem(key: string): void;
|
|
117
|
+
clear(): void;
|
|
118
|
+
key(index: number): string | null;
|
|
119
|
+
length(): number;
|
|
120
|
+
estimate?(): { usage: number; quota: number } | Promise<{ usage: number; quota: number }>;
|
|
121
|
+
persist?(): boolean | Promise<boolean>;
|
|
122
|
+
persisted?(): boolean | Promise<boolean>;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// =============================================================================
|
|
126
|
+
// File System Module (MUST BE NATIVE)
|
|
127
|
+
// Sandboxed access to app directories
|
|
128
|
+
// =============================================================================
|
|
129
|
+
export interface NativeFileSystemModule {
|
|
130
|
+
/** Read file as bytes */
|
|
131
|
+
readFile(path: string): Promise<Uint8Array>;
|
|
132
|
+
/** Write bytes to file */
|
|
133
|
+
writeFile(path: string, data: Uint8Array): Promise<void>;
|
|
134
|
+
/** Append bytes to file */
|
|
135
|
+
appendFile(path: string, data: Uint8Array): Promise<void>;
|
|
136
|
+
/** Check if file exists */
|
|
137
|
+
exists(path: string): Promise<boolean>;
|
|
138
|
+
/** Delete file */
|
|
139
|
+
unlink(path: string): Promise<void>;
|
|
140
|
+
/** Get file metadata */
|
|
141
|
+
stat(path: string): Promise<{ size: number; mtime_ms: number; is_dir: boolean; is_file: boolean; mode: number }>;
|
|
142
|
+
/** Get file metadata (no symlink follow) */
|
|
143
|
+
lstat(path: string): Promise<{ size: number; mtime_ms: number; is_dir: boolean; is_file: boolean; is_symlink: boolean; mode: number }>;
|
|
144
|
+
/** List directory entries */
|
|
145
|
+
readdir(path: string): Promise<string[]>;
|
|
146
|
+
/** Create directory */
|
|
147
|
+
mkdir(path: string, options?: { recursive?: boolean }): Promise<void>;
|
|
148
|
+
/** Remove empty directory */
|
|
149
|
+
rmdir(path: string): Promise<void>;
|
|
150
|
+
/** Rename file or directory */
|
|
151
|
+
rename(oldPath: string, newPath: string): Promise<void>;
|
|
152
|
+
/** Copy a file */
|
|
153
|
+
copyFile(src: string, dest: string): Promise<void>;
|
|
154
|
+
/** Check access permissions */
|
|
155
|
+
access(path: string, mode?: number): Promise<void>;
|
|
156
|
+
/** Change file permissions */
|
|
157
|
+
chmod(path: string, mode: number): Promise<void>;
|
|
158
|
+
/** Resolve to canonical absolute path */
|
|
159
|
+
realpath(path: string): Promise<string>;
|
|
160
|
+
/** Create temporary directory */
|
|
161
|
+
mkdtemp(prefix: string): Promise<string>;
|
|
162
|
+
/** Get app documents directory */
|
|
163
|
+
getDocumentsDir(): string;
|
|
164
|
+
/** Get app cache directory */
|
|
165
|
+
getCacheDir(): string;
|
|
166
|
+
/** Get temp directory */
|
|
167
|
+
getTempDir(): string;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
// =============================================================================
|
|
171
|
+
// Global native module registry
|
|
172
|
+
// Native side calls these setters during bootstrap
|
|
173
|
+
// =============================================================================
|
|
174
|
+
|
|
175
|
+
let _timerModule: NativeTimerModule | null = null;
|
|
176
|
+
let _performanceModule: NativePerformanceModule | null = null;
|
|
177
|
+
let _cryptoModule: NativeCryptoModule | null = null;
|
|
178
|
+
let _encodingModule: NativeEncodingModule | null = null;
|
|
179
|
+
let _consoleModule: NativeConsoleModule | null = null;
|
|
180
|
+
let _fetchModule: NativeFetchModule | null = null;
|
|
181
|
+
let _webSocketModule: NativeWebSocketModule | null = null;
|
|
182
|
+
let _storageModule: NativeStorageModule | null = null;
|
|
183
|
+
let _fileSystemModule: NativeFileSystemModule | null = null;
|
|
184
|
+
|
|
185
|
+
export function setNativeTimerModule(module: NativeTimerModule): void {
|
|
186
|
+
_timerModule = module;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
export function getNativeTimerModule(): NativeTimerModule | null {
|
|
190
|
+
return _timerModule;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
export function setNativePerformanceModule(module: NativePerformanceModule): void {
|
|
194
|
+
_performanceModule = module;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
export function getNativePerformanceModule(): NativePerformanceModule | null {
|
|
198
|
+
return _performanceModule;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
export function setNativeCryptoModule(module: NativeCryptoModule): void {
|
|
202
|
+
_cryptoModule = module;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
export function getNativeCryptoModule(): NativeCryptoModule | null {
|
|
206
|
+
return _cryptoModule;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
export function setNativeEncodingModule(module: NativeEncodingModule): void {
|
|
210
|
+
_encodingModule = module;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
export function getNativeEncodingModule(): NativeEncodingModule | null {
|
|
214
|
+
return _encodingModule;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
export function setNativeConsoleModule(module: NativeConsoleModule): void {
|
|
218
|
+
_consoleModule = module;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
export function getNativeConsoleModule(): NativeConsoleModule | null {
|
|
222
|
+
return _consoleModule;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
export function setNativeFetchModule(module: NativeFetchModule): void {
|
|
226
|
+
_fetchModule = module;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
export function getNativeFetchModule(): NativeFetchModule | null {
|
|
230
|
+
return _fetchModule;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
export function setNativeWebSocketModule(module: NativeWebSocketModule): void {
|
|
234
|
+
_webSocketModule = module;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
export function getNativeWebSocketModule(): NativeWebSocketModule | null {
|
|
238
|
+
return _webSocketModule;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
export function setNativeStorageModule(module: NativeStorageModule): void {
|
|
242
|
+
_storageModule = module;
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
export function getNativeStorageModule(): NativeStorageModule | null {
|
|
246
|
+
return _storageModule;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
export function setNativeFileSystemModule(module: NativeFileSystemModule): void {
|
|
250
|
+
_fileSystemModule = module;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
export function getNativeFileSystemModule(): NativeFileSystemModule | null {
|
|
254
|
+
return _fileSystemModule;
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
/**
|
|
258
|
+
* Check if all required native modules are available
|
|
259
|
+
*/
|
|
260
|
+
export function hasRequiredNativeModules(): boolean {
|
|
261
|
+
return (
|
|
262
|
+
_timerModule !== null &&
|
|
263
|
+
_performanceModule !== null &&
|
|
264
|
+
_cryptoModule !== null &&
|
|
265
|
+
_consoleModule !== null
|
|
266
|
+
);
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
/**
|
|
270
|
+
* Get list of missing native modules
|
|
271
|
+
*/
|
|
272
|
+
export function getMissingNativeModules(): string[] {
|
|
273
|
+
const missing: string[] = [];
|
|
274
|
+
if (!_timerModule) missing.push("timer");
|
|
275
|
+
if (!_performanceModule) missing.push("performance");
|
|
276
|
+
if (!_cryptoModule) missing.push("crypto");
|
|
277
|
+
if (!_consoleModule) missing.push("console");
|
|
278
|
+
if (!_fetchModule) missing.push("fetch");
|
|
279
|
+
if (!_storageModule) missing.push("storage");
|
|
280
|
+
return missing;
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
// =============================================================================
|
|
284
|
+
// Scheduling Module (SHOULD BE NATIVE for vsync integration)
|
|
285
|
+
// =============================================================================
|
|
286
|
+
export interface NativeSchedulingModule {
|
|
287
|
+
requestAnimationFrame(callback: () => void): void;
|
|
288
|
+
requestIdleCallback?(callback: (deadline: { didTimeout: boolean; timeRemaining: () => number }) => void, options?: { timeout?: number }): void;
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
let _schedulingModule: NativeSchedulingModule | null = null;
|
|
292
|
+
|
|
293
|
+
export function setNativeSchedulingModule(module: NativeSchedulingModule): void {
|
|
294
|
+
_schedulingModule = module;
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
export function getNativeSchedulingModule(): NativeSchedulingModule | null {
|
|
298
|
+
return _schedulingModule;
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
/**
|
|
302
|
+
* Map of module names to their types for type-safe access
|
|
303
|
+
*/
|
|
304
|
+
export interface NativeModuleMap {
|
|
305
|
+
timer: NativeTimerModule;
|
|
306
|
+
performance: NativePerformanceModule;
|
|
307
|
+
crypto: NativeCryptoModule;
|
|
308
|
+
encoding: NativeEncodingModule;
|
|
309
|
+
console: NativeConsoleModule;
|
|
310
|
+
fetch: NativeFetchModule;
|
|
311
|
+
websocket: NativeWebSocketModule;
|
|
312
|
+
storage: NativeStorageModule;
|
|
313
|
+
filesystem: NativeFileSystemModule;
|
|
314
|
+
scheduling: NativeSchedulingModule;
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
/**
|
|
318
|
+
* Type-safe getter for native modules by name.
|
|
319
|
+
* Returns null if the module is not available.
|
|
320
|
+
*
|
|
321
|
+
* @example
|
|
322
|
+
* const crypto = getNativeModule('crypto');
|
|
323
|
+
* if (crypto) {
|
|
324
|
+
* crypto.getRandomValues(new Uint8Array(16)); // Type-safe!
|
|
325
|
+
* }
|
|
326
|
+
*/
|
|
327
|
+
export function getNativeModule<K extends keyof NativeModuleMap>(
|
|
328
|
+
name: K
|
|
329
|
+
): NativeModuleMap[K] | null {
|
|
330
|
+
switch (name) {
|
|
331
|
+
case 'timer':
|
|
332
|
+
return _timerModule as NativeModuleMap[K] | null;
|
|
333
|
+
case 'performance':
|
|
334
|
+
return _performanceModule as NativeModuleMap[K] | null;
|
|
335
|
+
case 'crypto':
|
|
336
|
+
return _cryptoModule as NativeModuleMap[K] | null;
|
|
337
|
+
case 'encoding':
|
|
338
|
+
return _encodingModule as NativeModuleMap[K] | null;
|
|
339
|
+
case 'console':
|
|
340
|
+
return _consoleModule as NativeModuleMap[K] | null;
|
|
341
|
+
case 'fetch':
|
|
342
|
+
return _fetchModule as NativeModuleMap[K] | null;
|
|
343
|
+
case 'websocket':
|
|
344
|
+
return _webSocketModule as NativeModuleMap[K] | null;
|
|
345
|
+
case 'storage':
|
|
346
|
+
return _storageModule as NativeModuleMap[K] | null;
|
|
347
|
+
case 'filesystem':
|
|
348
|
+
return _fileSystemModule as NativeModuleMap[K] | null;
|
|
349
|
+
case 'scheduling':
|
|
350
|
+
return _schedulingModule as NativeModuleMap[K] | null;
|
|
351
|
+
default:
|
|
352
|
+
return null;
|
|
353
|
+
}
|
|
354
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./NativeModules";
|
|
@@ -0,0 +1,351 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Navigator implementation for Ibex runtime
|
|
3
|
+
*
|
|
4
|
+
* Provides browser-like navigator object with device/platform info.
|
|
5
|
+
* @see https://html.spec.whatwg.org/multipage/system-state.html#the-navigator-object
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { USER_AGENT } from '../identity.generated';
|
|
9
|
+
import { LockManager } from '../locks/LockManager';
|
|
10
|
+
import { Clipboard } from '../clipboard/Clipboard';
|
|
11
|
+
import { StorageManager } from '../storage/StorageManager';
|
|
12
|
+
import { getGeolocation } from '../location';
|
|
13
|
+
import { getExactLocaleSnapshot } from '../locale';
|
|
14
|
+
|
|
15
|
+
function runtimePlatform(): string {
|
|
16
|
+
const g = globalThis as any;
|
|
17
|
+
if (typeof g.__exactPlatform === 'string' && g.__exactPlatform.length > 0) {
|
|
18
|
+
return g.__exactPlatform.toLowerCase();
|
|
19
|
+
}
|
|
20
|
+
if (
|
|
21
|
+
g.process &&
|
|
22
|
+
typeof g.process.platform === 'string' &&
|
|
23
|
+
g.process.platform.length > 0
|
|
24
|
+
) {
|
|
25
|
+
return g.process.platform.toLowerCase();
|
|
26
|
+
}
|
|
27
|
+
return 'ios';
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function platformLabelForNavigator(): string {
|
|
31
|
+
const p = runtimePlatform();
|
|
32
|
+
if (p === 'android') return 'Android';
|
|
33
|
+
if (p === 'web' || p === 'browser') return 'MacIntel';
|
|
34
|
+
if (p === 'macos' || p === 'mac' || p === 'darwin') return 'MacIntel';
|
|
35
|
+
if (p === 'windows' || p === 'win32') return 'Win32';
|
|
36
|
+
if (p === 'linux') return 'Linux x86_64';
|
|
37
|
+
return 'iPhone';
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function platformLabelForAppVersion(): string {
|
|
41
|
+
const p = runtimePlatform();
|
|
42
|
+
if (p === 'android') return 'Android';
|
|
43
|
+
if (p === 'web' || p === 'browser') return 'Macintosh';
|
|
44
|
+
if (p === 'macos' || p === 'mac' || p === 'darwin') return 'Macintosh';
|
|
45
|
+
if (p === 'windows' || p === 'win32') return 'Windows';
|
|
46
|
+
if (p === 'linux') return 'Linux';
|
|
47
|
+
return 'iOS';
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function callNumericHostFunction(name: string): number | null {
|
|
51
|
+
const fn = (globalThis as any)[name];
|
|
52
|
+
if (typeof fn !== 'function') return null;
|
|
53
|
+
try {
|
|
54
|
+
const value = Number(fn());
|
|
55
|
+
return Number.isFinite(value) && value > 0 ? value : null;
|
|
56
|
+
} catch {
|
|
57
|
+
return null;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function approximateDeviceMemory(totalBytes: number | null): number {
|
|
62
|
+
if (totalBytes == null) return 4;
|
|
63
|
+
const gib = totalBytes / (1024 * 1024 * 1024);
|
|
64
|
+
const buckets = [0.25, 0.5, 1, 2, 4, 8];
|
|
65
|
+
let selected = buckets[0];
|
|
66
|
+
for (const bucket of buckets) {
|
|
67
|
+
if (gib >= bucket) {
|
|
68
|
+
selected = bucket;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
return selected;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function readOnlineStatus(): boolean {
|
|
75
|
+
const g = globalThis as any;
|
|
76
|
+
if (typeof g.__exactGetOnlineStatus === 'function') {
|
|
77
|
+
try {
|
|
78
|
+
return g.__exactGetOnlineStatus() !== false;
|
|
79
|
+
} catch {
|
|
80
|
+
return true;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
if (typeof g.__exactGetNetworkInterfaces !== 'function') {
|
|
84
|
+
return true;
|
|
85
|
+
}
|
|
86
|
+
try {
|
|
87
|
+
const interfaces = g.__exactGetNetworkInterfaces();
|
|
88
|
+
if (!interfaces || typeof interfaces !== 'object') {
|
|
89
|
+
return true;
|
|
90
|
+
}
|
|
91
|
+
for (const entries of Object.values(interfaces)) {
|
|
92
|
+
if (!Array.isArray(entries)) continue;
|
|
93
|
+
for (const entry of entries) {
|
|
94
|
+
if (hasUsableNetworkAddress(entry)) {
|
|
95
|
+
return true;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
return false;
|
|
100
|
+
} catch {
|
|
101
|
+
return true;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
function hasUsableNetworkAddress(entry: unknown): boolean {
|
|
106
|
+
if (!entry || typeof entry !== 'object') return false;
|
|
107
|
+
const record = entry as { address?: unknown; internal?: unknown };
|
|
108
|
+
if (record.internal === true || typeof record.address !== 'string') {
|
|
109
|
+
return false;
|
|
110
|
+
}
|
|
111
|
+
return record.address.length > 0 &&
|
|
112
|
+
record.address !== '0.0.0.0' &&
|
|
113
|
+
record.address !== '::';
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Navigator provides information about the runtime environment.
|
|
118
|
+
*/
|
|
119
|
+
export class Navigator {
|
|
120
|
+
readonly __exactNavigator = true;
|
|
121
|
+
|
|
122
|
+
private _locks: LockManager | null = null;
|
|
123
|
+
private _storage: StorageManager | null = null;
|
|
124
|
+
private _clipboard: Clipboard | null = null;
|
|
125
|
+
private _geolocation: Geolocation | null = null;
|
|
126
|
+
/**
|
|
127
|
+
* User agent string identifying the runtime.
|
|
128
|
+
* Format: "Exact/{version} ({platform}; {engine})"
|
|
129
|
+
*/
|
|
130
|
+
get userAgent(): string {
|
|
131
|
+
return USER_AGENT;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* Vendor string (always "Exact" for this runtime).
|
|
136
|
+
*/
|
|
137
|
+
get vendor(): string {
|
|
138
|
+
return 'Exact';
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* Vendor sub-version (empty string).
|
|
143
|
+
*/
|
|
144
|
+
get vendorSub(): string {
|
|
145
|
+
return '';
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* Product name (always "Exact").
|
|
150
|
+
*/
|
|
151
|
+
get product(): string {
|
|
152
|
+
return 'Exact';
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* Product sub-version (empty string).
|
|
157
|
+
*/
|
|
158
|
+
get productSub(): string {
|
|
159
|
+
return '';
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* App name for compatibility (always "Netscape" per spec).
|
|
164
|
+
*/
|
|
165
|
+
get appName(): string {
|
|
166
|
+
return 'Netscape';
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* App code name for compatibility.
|
|
171
|
+
*/
|
|
172
|
+
get appCodeName(): string {
|
|
173
|
+
return 'Mozilla';
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* App version string.
|
|
178
|
+
*/
|
|
179
|
+
get appVersion(): string {
|
|
180
|
+
return `5.0 (${platformLabelForAppVersion()})`;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* Platform identifier.
|
|
185
|
+
* Returns "iPhone", "Android", "MacIntel", etc. depending on the runtime platform.
|
|
186
|
+
*/
|
|
187
|
+
get platform(): string {
|
|
188
|
+
return platformLabelForNavigator();
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
/**
|
|
192
|
+
* Primary language preference.
|
|
193
|
+
* Returns the device's preferred language via native bridge if available.
|
|
194
|
+
*/
|
|
195
|
+
get language(): string {
|
|
196
|
+
const exactLocale = getExactLocaleSnapshot();
|
|
197
|
+
if (exactLocale.tag.length > 0) {
|
|
198
|
+
return exactLocale.tag;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
const g = globalThis as any;
|
|
202
|
+
if (typeof g.__exactLocale === 'string' && g.__exactLocale) {
|
|
203
|
+
return g.__exactLocale;
|
|
204
|
+
}
|
|
205
|
+
if (typeof g.__exactLanguage === 'string' && g.__exactLanguage) {
|
|
206
|
+
return g.__exactLanguage;
|
|
207
|
+
}
|
|
208
|
+
return 'en-US';
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
/**
|
|
212
|
+
* Array of preferred languages.
|
|
213
|
+
*/
|
|
214
|
+
get languages(): readonly string[] {
|
|
215
|
+
const exactLocale = getExactLocaleSnapshot();
|
|
216
|
+
if (exactLocale.tags.length > 0) {
|
|
217
|
+
return exactLocale.tags;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
const lang = this.language;
|
|
221
|
+
const base = lang.includes('-') ? lang.split('-')[0] : lang;
|
|
222
|
+
if (base !== lang) {
|
|
223
|
+
return Object.freeze([lang, base]);
|
|
224
|
+
}
|
|
225
|
+
return Object.freeze([lang]);
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
/**
|
|
229
|
+
* Whether the device is online.
|
|
230
|
+
*/
|
|
231
|
+
get onLine(): boolean {
|
|
232
|
+
// @ref LLP 0008#os-info - Android navigator online status uses native network interface data.
|
|
233
|
+
return readOnlineStatus();
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
/**
|
|
237
|
+
* Number of logical processors available.
|
|
238
|
+
*/
|
|
239
|
+
get hardwareConcurrency(): number {
|
|
240
|
+
// @ref LLP 0008#os-info - Android navigator device hints use native sysconf/sysinfo values.
|
|
241
|
+
const nativeCount = callNumericHostFunction('__exactGetCpuCount');
|
|
242
|
+
return nativeCount == null ? 4 : Math.max(1, Math.floor(nativeCount));
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
/**
|
|
246
|
+
* Maximum touch points supported by the device.
|
|
247
|
+
*/
|
|
248
|
+
get maxTouchPoints(): number {
|
|
249
|
+
// Mobile devices support multi-touch
|
|
250
|
+
return 5;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
/**
|
|
254
|
+
* Whether cookies are enabled.
|
|
255
|
+
* Always returns true in Exact (we support cookies in fetch).
|
|
256
|
+
*/
|
|
257
|
+
get cookieEnabled(): boolean {
|
|
258
|
+
return true;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
/**
|
|
262
|
+
* Whether Java is enabled (always false).
|
|
263
|
+
*/
|
|
264
|
+
javaEnabled(): boolean {
|
|
265
|
+
return false;
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
/**
|
|
269
|
+
* Device memory in GB (approximate).
|
|
270
|
+
* Note: This is a hint, not exact value.
|
|
271
|
+
*/
|
|
272
|
+
get deviceMemory(): number {
|
|
273
|
+
// @ref LLP 0008#os-info - Android navigator device hints use native sysconf/sysinfo values.
|
|
274
|
+
return approximateDeviceMemory(callNumericHostFunction('__exactGetTotalMem'));
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
/**
|
|
278
|
+
* PDF viewer support (always false in native app).
|
|
279
|
+
*/
|
|
280
|
+
get pdfViewerEnabled(): boolean {
|
|
281
|
+
return false;
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
/**
|
|
285
|
+
* Web driver status (always false).
|
|
286
|
+
*/
|
|
287
|
+
get webdriver(): boolean {
|
|
288
|
+
return false;
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
/**
|
|
292
|
+
* Clipboard API for reading and writing clipboard data.
|
|
293
|
+
* @see https://developer.mozilla.org/en-US/docs/Web/API/Navigator/clipboard
|
|
294
|
+
*/
|
|
295
|
+
get clipboard(): Clipboard {
|
|
296
|
+
if (!this._clipboard) {
|
|
297
|
+
this._clipboard = new Clipboard();
|
|
298
|
+
}
|
|
299
|
+
return this._clipboard;
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
/**
|
|
303
|
+
* Geolocation API installed from the runtime location backend.
|
|
304
|
+
*/
|
|
305
|
+
get geolocation(): Geolocation {
|
|
306
|
+
if (!this._geolocation) {
|
|
307
|
+
this._geolocation = getGeolocation();
|
|
308
|
+
}
|
|
309
|
+
return this._geolocation;
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
/**
|
|
313
|
+
* Web Locks API for coordinating concurrent access.
|
|
314
|
+
* @see https://developer.mozilla.org/en-US/docs/Web/API/Navigator/locks
|
|
315
|
+
*/
|
|
316
|
+
get locks(): LockManager {
|
|
317
|
+
if (!this._locks) {
|
|
318
|
+
this._locks = new LockManager();
|
|
319
|
+
}
|
|
320
|
+
return this._locks;
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
/**
|
|
324
|
+
* Storage manager for quota and persistence info.
|
|
325
|
+
* @see https://developer.mozilla.org/en-US/docs/Web/API/Navigator/storage
|
|
326
|
+
*/
|
|
327
|
+
get storage(): StorageManager {
|
|
328
|
+
if (!this._storage) {
|
|
329
|
+
this._storage = new StorageManager();
|
|
330
|
+
}
|
|
331
|
+
return this._storage;
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
get [Symbol.toStringTag](): string {
|
|
335
|
+
return 'Navigator';
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
// Singleton navigator instance
|
|
340
|
+
let _navigator: Navigator | null = null;
|
|
341
|
+
|
|
342
|
+
export function getNavigator(): Navigator {
|
|
343
|
+
if (!_navigator) {
|
|
344
|
+
_navigator = new Navigator();
|
|
345
|
+
}
|
|
346
|
+
return _navigator;
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
export const navigator = getNavigator();
|
|
350
|
+
|
|
351
|
+
export default Navigator;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { Navigator, navigator, getNavigator } from './Navigator';
|