// os_emscripten.c - OS module for Emscripten (Web) // Provides system information and utilities for the web platform #include "cell.h" #include #include #include #include #include #include #include // cell_ns - nanoseconds since some epoch uint64_t cell_ns(void) { // emscripten_get_now() returns milliseconds with high precision return (uint64_t)(emscripten_get_now() * 1000000.0); } // cell_sleep - sleep for specified seconds void cell_sleep(double seconds) { // Note: This requires ASYNCIFY to work correctly without freezing the browser emscripten_sleep((unsigned int)(seconds * 1000)); } JSC_CCALL(os_now, return number2js(js, cell_ns()); ) JSC_CCALL(os_sleep, double secs = js2number(js, argv[0]); cell_sleep(secs); ) static JSValue js_os_totalmem(JSContext *js, JSValue self, int argc, JSValue *argv) { // Return heap size or a fixed amount? // heap size is technically dynamic in wasm, but we can query it. // For now, let's return the HEAP8.length equivalent via EM_ASM_INT or similar, // or just return a safe default. // Better yet, use mallinfo if available. return JS_NewInt64(js, (int64_t)emscripten_get_heap_size()); } static JSValue js_os_platform(JSContext *js, JSValue self, int argc, JSValue *argv) { return JS_NewString(js, "Emscripten"); } static JSValue js_os_hostname(JSContext *js, JSValue self, int argc, JSValue *argv) { return JS_NewString(js, "browser"); } static JSValue js_os_arch(JSContext *js, JSValue self, int argc, JSValue *argv) { return JS_NewString(js, "wasm"); } static JSValue js_os_freemem(JSContext *js, JSValue self, int argc, JSValue *argv) { struct mallinfo i = mallinfo(); // Approximate free memory based on mallinfo // total heap - used size_t total = emscripten_get_heap_size(); size_t used = i.uordblks; return JS_NewInt64(js, (int64_t)(total - used)); } static JSValue js_os_version(JSContext *js, JSValue self, int argc, JSValue *argv) { // Could return UserAgent, but for now just "web" return JS_NewString(js, "web"); } JSC_CCALL(os_mallinfo, ret = JS_NewObject(js); struct mallinfo i = mallinfo(); // Add fields if needed, similar to os.c // Using macros from os.c if they were visible, but they aren't public. // We'll just define helper locally or expand it. JS_SetPropertyStr(js, ret, "arena", JS_NewInt32(js, i.arena)); JS_SetPropertyStr(js, ret, "ordblks", JS_NewInt32(js, i.ordblks)); JS_SetPropertyStr(js, ret, "uordblks", JS_NewInt32(js, i.uordblks)); JS_SetPropertyStr(js, ret, "fordblks", JS_NewInt32(js, i.fordblks)); ) static JSValue js_os_rusage(JSContext *js, JSValue self, int argc, JSValue *argv) { return JS_NewObject(js); } JSC_SCALL(os_system, // system() not available in browser ret = JS_NewInt32(js, -1); ) JSC_CCALL(os_exit, // Terminate execution emscripten_force_exit(0); ) // dylib functions - assuming static build for now unless side modules are used static JSValue js_os_dylib_open(JSContext *js, JSValue self, int argc, JSValue *argv) { return JS_ThrowInternalError(js, "dylib_open: not supported on Emscripten"); } static JSValue js_os_dylib_symbol(JSContext *js, JSValue self, int argc, JSValue *argv) { return JS_ThrowInternalError(js, "dylib_symbol: not supported on Emscripten"); } static JSValue js_os_dylib_has_symbol(JSContext *js, JSValue self, int argc, JSValue *argv) { return JS_NewBool(js, 0); } JSC_CCALL(os_print, size_t len; const char *str = JS_ToCStringLen(js, &len, argv[0]); printf("%.*s", (int)len, str); JS_FreeCString(js, str); ) static JSValue js_os_load_internal(JSContext *js, JSValue self, int argc, JSValue *argv) { // dlsym with NULL usually works in Emscripten MAIN_MODULE builds, // but for now we assume no dynamic linking. return JS_NULL; } static JSValue js_os_internal_exists(JSContext *js, JSValue self, int argc, JSValue *argv) { return JS_NewBool(js, 0); } void arc4random_buf(void *buf, size_t nbytes); // Random number generation int randombytes(void *buf, size_t n) { // Emscripten implements arc4random_buf using Web Crypto API arc4random_buf(buf, n); return 0; } JSC_CCALL(os_random, return JS_NewFloat64(js, cell_random_fit()); ) JSC_CCALL(os_getenv, const char *name = JS_ToCString(js, argv[0]); if (!name) return JS_EXCEPTION; const char *value = getenv(name); JS_FreeCString(js, name); if (value) ret = JS_NewString(js, value); else ret = JS_NULL; ) static const JSCFunctionListEntry js_os_funcs[] = { MIST_FUNC_DEF(os, platform, 0), MIST_FUNC_DEF(os, arch, 0), MIST_FUNC_DEF(os, totalmem, 0), MIST_FUNC_DEF(os, freemem, 0), MIST_FUNC_DEF(os, hostname, 0), MIST_FUNC_DEF(os, version, 0), MIST_FUNC_DEF(os, now, 0), MIST_FUNC_DEF(os, rusage, 0), MIST_FUNC_DEF(os, mallinfo, 0), MIST_FUNC_DEF(os, system, 1), MIST_FUNC_DEF(os, exit, 0), MIST_FUNC_DEF(os, sleep, 1), MIST_FUNC_DEF(os, dylib_open, 1), MIST_FUNC_DEF(os, dylib_symbol, 2), MIST_FUNC_DEF(os, dylib_has_symbol, 2), MIST_FUNC_DEF(os, load_internal, 1), MIST_FUNC_DEF(os, internal_exists, 1), MIST_FUNC_DEF(os, print, 1), MIST_FUNC_DEF(os, random, 0), MIST_FUNC_DEF(os, getenv, 1), }; JSValue js_os_use(JSContext *js) { JSValue mod = JS_NewObject(js); JS_SetPropertyFunctionList(js, mod, js_os_funcs, countof(js_os_funcs)); return mod; }