#include "qjs_os.h" #include "jsffi.h" #include "qjs_macros.h" #include "qjs_common.h" #include "qjs_wota.h" #include "qjs_transform.h" #include "prosperon.h" #include "transform.h" #include #include #include #include #include #include #include #include #include #include #ifdef _WIN32 #include #else #include #include #ifdef __linux__ #include #include #endif #endif JSC_CCALL(os_exit, exit(js2number(js,argv[0]));) JSC_CCALL(os_now, return number2js(js, (double)SDL_GetTicksNS()/1000000000.0)) JSC_CCALL(os_sleep, double secs = js2number(js,argv[0]); int ms = secs*1000; SDL_Delay(ms); ) JSC_CCALL(os_power_state, int pct, secs; SDL_PowerState state = SDL_GetPowerInfo(&secs, &pct); const char *statestr = "unknown"; switch(state) { case SDL_POWERSTATE_ON_BATTERY: statestr = "battery"; break; case SDL_POWERSTATE_NO_BATTERY: statestr = "no battery"; break; case SDL_POWERSTATE_CHARGING: statestr = "charging"; break; case SDL_POWERSTATE_CHARGED: statestr = "charged"; break; } ret = JS_NewObject(js); JS_SetPropertyStr(js,ret,"state",JS_NewString(js,statestr)); JS_SetPropertyStr(js,ret,"percent",number2js(js,pct)); JS_SetPropertyStr(js,ret,"seconds",number2js(js,secs)); ) JSC_CCALL(os_totalmem, return number2js(js, SDL_GetSystemRAM())) JSC_CCALL(os_platform, return JS_NewString(js,SDL_GetPlatform())) static JSValue js_os_hostname(JSContext *js, JSValue self, int argc, JSValue *argv) { JSValue ret = JS_UNDEFINED; #ifdef _WIN32 TCHAR buffer[256] = TEXT(""); DWORD size = sizeof(buffer) / sizeof(TCHAR); GetComputerName(buffer, &size); return JS_NewString(js, buffer); #else struct utsname buffer; if (uname(&buffer) != 0) return JS_ThrowReferenceError(js,"Could not get hostname."); return JS_NewString(js, buffer.nodename); #endif return ret; } static JSValue js_os_arch(JSContext *js, JSValue self, int argc, JSValue *argv) { JSValue ret = JS_UNDEFINED; #if defined(__x86_64__) || defined(_M_X64) return JS_NewString(js,"x64"); #elif defined(__aarch64__) || defined(_M_ARM64) return JS_NewString(js,"arm64"); #elif defined(__arm__) || defined(_M_ARM) return JS_NewString(js,"arm"); #elif defined(__i386__) || defined(_M_IX86) return JS_NewString(js,"ia32"); #elif defined(__loongarch__) || defined(__loongarch32) || defined(__loongarch64) return JS_NewString(js,"loong64"); #elif defined(__mips__) || defined(__mips) || defined(_M_MIPS) // You might want to distinguish mips vs mipsel return JS_NewString(js,"mips"); #elif defined(__ppc64__) || defined(__powerpc64__) || defined(_M_PPC) // You might want to distinguish ppc vs ppc64, big-endian vs little-endian return JS_NewString(js,"ppc64"); #elif defined(__riscv) && __riscv_xlen == 64 return JS_NewString(js,"riscv64"); #elif defined(__s390x__) return JS_NewString(js,"s390x"); #else return JS_NewString(js,"unknown"); #endif return ret; } static JSValue js_os_freemem(JSContext *js, JSValue self, int argc, JSValue *argv) { JSValue ret = JS_UNDEFINED; #ifdef _WIN32 MEMORYSTATUSEX statex; statex.dwLength = sizeof(statex); if (!GlobalMemoryStatusEx(&statex)) return JS_ThrowInternalError(js,"GlobalMemoryStatusEx failed"); return JS_NewInt64(js,(int64_t)statex.ullAvailPhys); #elif defined(__linux__) struct sysinfo info; if (sysinfo(&info) == 0) return JS_NewInt64(js,(int64_t)info.freeram * info.mem_unit); return JS_NewInt64(js,0); #elif defined(__FreeBSD__) || defined(__OpenBSD__) // A very rough fallback using the same sysconf approach // (macOS or *BSD typically need specialized APIs to get free mem accurately) // This is often only "unused" pages, ignoring caches, etc. long pages = sysconf(_SC_AVPHYS_PAGES); long page_size = sysconf(_SC_PAGE_SIZE); if (pages < 0 || page_size < 0) return JS_NewInt64(js,0); return JS_NewInt64(js,(int64_t)pages * (int64_t)page_size); #else // Fallback: unknown return JS_NewInt64(js,0); #endif return ret; } static JSValue js_os_version(JSContext *js, JSValue self, int argc, JSValue *argv) { JSValue ret = JS_UNDEFINED; #ifdef _WIN32 typedef LONG (WINAPI *RtlGetVersionPtr)(PRTL_OSVERSIONINFOW); HMODULE h = GetModuleHandleA("ntdll.dll"); if (h) { RtlGetVersionPtr fx = (RtlGetVersionPtr)GetProcAddress(h, "RtlGetVersion"); if (fx) { RTL_OSVERSIONINFOW ver; memset(&ver, 0, sizeof(ver)); ver.dwOSVersionInfoSize = sizeof(ver); if (!fx(&ver)) { char buf[128]; sprintf(buf, "%u.%u.%u", (unsigned)ver.dwMajorVersion, (unsigned)ver.dwMinorVersion, (unsigned)ver.dwBuildNumber ); return JS_NewString(js, buf); } } } OSVERSIONINFOW wver; memset(&wver, 0, sizeof(wver)); wver.dwOSVersionInfoSize = sizeof(wver); if (GetVersionExW(&wver)) { char buf[128]; sprintf(buf, "%u.%u.%u", (unsigned)wver.dwMajorVersion, (unsigned)wver.dwMinorVersion, (unsigned)wver.dwBuildNumber ); return JS_NewString(js, buf); } return JS_NewString(js, "Windows_Unknown"); #else struct utsname info; if (!uname(&info)) return JS_NewString(js, info.release); return JS_NewString(js, ""); #endif return ret; } JSValue js_os_get_trace(JSContext *js, JSValue self) { return JS_NewBool(js, trace); } JSValue js_os_set_trace(JSContext *js, JSValue self, JSValue value) { trace = JS_ToBool(js, value); return JS_UNDEFINED; } JSC_CCALL(os_on, prosperon_rt *rt = JS_GetContextOpaque(js); JS_FreeValue(js, rt->on_exception); rt->on_exception = JS_DupValue(js,argv[1]); ) JSC_CCALL(os_buffer2string, if (argc < 1) { return JS_ThrowTypeError(js, "buffer2string expects an ArrayBuffer"); } size_t len; uint8_t *buf = JS_GetArrayBuffer(js, &len, argv[0]); if (!buf) { return JS_ThrowTypeError(js, "First argument must be an ArrayBuffer"); } // Create a null-terminated string from the buffer char *str = js_malloc(js, len + 1); if (!str) { return JS_ThrowInternalError(js, "Failed to allocate memory"); } memcpy(str, buf, len); str[len] = '\0'; JSValue result = JS_NewString(js, str); js_free(js, str); return result; ) #define JSOBJ_ADD_FIELD(OBJ, STRUCT, FIELD, TYPE) \ JS_SetPropertyStr(js, OBJ, #FIELD, TYPE##2js(js,STRUCT.FIELD));\ #define JSJMEMRET(FIELD) JSOBJ_ADD_FIELD(ret, jsmem, FIELD, number) JSC_CCALL(os_mallinfo, ret = JS_UNDEFINED; /*struct mallinfo jsmem = mallinfo(); ret = JS_NewObject(js); JSJMEMRET(arena); JSJMEMRET(ordblks); JSJMEMRET(smblks); JSJMEMRET(hblks); JSJMEMRET(hblkhd); JSJMEMRET(usmblks); JSJMEMRET(fsmblks); JSJMEMRET(uordblks); JSJMEMRET(fordblks); JSJMEMRET(keepcost);*/ ) static JSValue js_os_rusage(JSContext *js, JSValue self, int argc, JSValue *argv) { JSValue ret = JS_UNDEFINED; ret = JS_NewObject(js); #ifndef _WIN32 struct rusage jsmem; getrusage(RUSAGE_SELF, &jsmem); JSJMEMRET(ru_maxrss); JSJMEMRET(ru_ixrss); JSJMEMRET(ru_idrss); JSJMEMRET(ru_isrss); JSJMEMRET(ru_minflt); JSJMEMRET(ru_majflt); JSJMEMRET(ru_nswap); JSJMEMRET(ru_inblock); JSJMEMRET(ru_oublock); JSJMEMRET(ru_msgsnd); JSJMEMRET(ru_msgrcv); JSJMEMRET(ru_nsignals); JSJMEMRET(ru_nvcsw); JSJMEMRET(ru_nivcsw); #endif return ret; } 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), JS_CGETSET_DEF("trace", js_os_get_trace, js_os_set_trace), MIST_FUNC_DEF(os, exit, 1), MIST_FUNC_DEF(os, now, 0), MIST_FUNC_DEF(os, power_state, 0), MIST_FUNC_DEF(os, on, 2), MIST_FUNC_DEF(os, rusage, 0), MIST_FUNC_DEF(os, mallinfo, 0), MIST_FUNC_DEF(os, buffer2string, 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; }