removed unneeded functions and split out actor specific functions

This commit is contained in:
2025-05-22 17:56:32 -05:00
parent 13c2a0ba0c
commit 698dbd81ae
15 changed files with 155 additions and 222 deletions

View File

@@ -326,11 +326,12 @@ function joinServer() {
}
var os = use('os')
var actor = use('actor')
// Set up IO actor subscription
var ioguy = {
__ACTORDATA__: {
id: os.ioactor()
id: actor.ioactor()
}
};

View File

@@ -147,7 +147,7 @@ sources = []
src += [
'anim.c', 'config.c', 'datastream.c','font.c','HandmadeMath.c','jsffi.c','model.c',
'render.c','simplex.c','spline.c', 'transform.c','prosperon.c', 'wildmatch.c',
'sprite.c', 'rtree.c', 'qjs_nota.c', 'qjs_soloud.c', 'qjs_sdl.c', 'qjs_math.c', 'qjs_geometry.c', 'qjs_transform.c', 'qjs_sprite.c', 'qjs_io.c', 'qjs_os.c',
'sprite.c', 'rtree.c', 'qjs_nota.c', 'qjs_soloud.c', 'qjs_sdl.c', 'qjs_math.c', 'qjs_geometry.c', 'qjs_transform.c', 'qjs_sprite.c', 'qjs_io.c', 'qjs_os.c', 'qjs_actor.c',
'qjs_qr.c', 'qjs_wota.c', 'monocypher.c', 'qjs_blob.c', 'qjs_crypto.c', 'qjs_time.c', 'qjs_http.c', 'qjs_rtree.c', 'qjs_spline.c', 'qjs_js.c', 'qjs_debug.c'
]
# quirc src

View File

@@ -22,6 +22,7 @@ prosperon.dispatch = function(type, data) {
}
var os = use_embed('os')
var actor_mod = use_embed('actor')
var tracy = use_embed('tracy')
os.trace = true;
@@ -676,7 +677,7 @@ $_.connection = function(callback, actor, config) {
callback(peer_connection(peer))
return
}
if (os.mailbox_exist(actor.__ACTORDATA__.id)) {
if (actor_mod.mailbox_exist(actor.__ACTORDATA__.id)) {
callback({type:"local"})
return
}
@@ -769,7 +770,7 @@ $_.start = function(cb, prg, arg) {
if (prg) argv = argv.concat(['--program', prg])
if (arg) argv = argv.concat(cmd.encode(arg))
underlings.add(id)
os.createactor(argv)
actor_mod.createactor(argv)
}
$_.start[prosperon.DOC] = "The start function creates a new actor..."
@@ -788,13 +789,13 @@ $_.stop = function(actor) {
$_.stop[prosperon.DOC] = "The stop function stops an underling."
$_.unneeded = function(fn, seconds) {
os.unneeded(fn, seconds)
actor_mod.unneeded(fn, seconds)
}
$_.unneeded[prosperon.DOC] = "registers a function that is called when the actor..."
$_.delay = function(fn, seconds) {
var id = os.delay(fn, seconds)
return function() { os.removetimer(id) }
var id = actor_mod.delay(fn, seconds)
return function() { actor_mod.removetimer(id) }
}
$_.delay[prosperon.DOC] = "used to schedule the invocation of a function..."
@@ -817,8 +818,8 @@ function actor_send(actor, message) {
if (receive_fn) receive_fn(message.data)
return
}
if (actor.__ACTORDATA__.id && os.mailbox_exist(actor.__ACTORDATA__.id)) {
os.mailbox_push(actor.__ACTORDATA__.id, message)
if (actor.__ACTORDATA__.id && actor_mod.mailbox_exist(actor.__ACTORDATA__.id)) {
actor_mod.mailbox_push(actor.__ACTORDATA__.id, message)
return
}
if (actor.__ACTORDATA__.address) {
@@ -900,7 +901,7 @@ else prosperon.id = prosperon.args.id
$_.__ACTORDATA__.id = prosperon.id
os.register_actor(prosperon.id, function(msg) {
actor_mod.register_actor(prosperon.id, function(msg) {
try {
handle_message(msg)
send_messages()
@@ -931,7 +932,7 @@ function destroyself() {
for (var i of underlings)
$_.stop(create_actor({id:i}))
os.destroy()
actor_mod.destroy()
}
function handle_actor_disconnect(id) {
@@ -948,7 +949,7 @@ function handle_actor_disconnect(id) {
function handle_message(msg) {
if (msg.target) {
if (msg.target !== prosperon.id) {
os.mailbox_push(msg.target, msg)
actor_mod.mailbox_push(msg.target, msg)
return
}
}

View File

@@ -7,21 +7,13 @@ os.freemem[prosperon.DOC] = "Return the amount of free system RAM in bytes, if k
os.hostname[prosperon.DOC] = "Return the system's hostname, or an empty string if not available."
os.version[prosperon.DOC] = "Return the OS or kernel version string, if the platform provides it."
os.kill[prosperon.DOC] = "Send a signal (e.g., 'SIGINT', 'SIGTERM', etc.) to the current process."
os.exit[prosperon.DOC] = "Exit the application with the specified exit code."
os.now[prosperon.DOC] = "Return current time (in seconds as a float) with high resolution."
os.openurl[prosperon.DOC] = "Open the provided URL in the default web browser, if possible."
os.sleep[prosperon.DOC] = "Block execution for the specified number of seconds."
os.battery_pct[prosperon.DOC] = "Return the battery level (percentage) or negative if unknown."
os.battery_voltage[prosperon.DOC] = "Return the current battery voltage in volts, if available."
os.battery_seconds[prosperon.DOC] = "Return the estimated remaining battery time in seconds, or negative if unknown."
os.power_state[prosperon.DOC] = "Return a string describing power status: 'on battery', 'charging', 'charged', etc."
os.on[prosperon.DOC] = "Register a global callback for certain engine-wide or system-level events."
os.rusage[prosperon.DOC] = "Return resource usage stats for this process, if the platform supports it."
os.mallinfo[prosperon.DOC] = "Return detailed memory allocation info (arena size, free blocks, etc.) on some platforms."
os.env[prosperon.DOC] = "Fetch the value of a given environment variable, or undefined if it doesn't exist."
os.system[prosperon.DOC] = "Execute a shell command using the system() call. Returns the command's exit code."
return os

View File

@@ -1,4 +1,4 @@
var ex = {}
var ex = this
ex[prosperon.DOC] = `
A set of utilities for iterating over a hierarchy of actor-like objects, as well
as managing tag-based lookups. Objects are assumed to have a "objects" property,

View File

@@ -43,6 +43,7 @@
#include "qjs_io.h"
#include "qjs_sdl_gpu.h"
#include "qjs_os.h"
#include "qjs_actor.h"
#include "qjs_rtree.h"
#include "qjs_spline.h"
#include "qjs_js.h"
@@ -1905,11 +1906,6 @@ JSC_CCALL(os_guid,
return JS_NewString(js,guid_str);
)
JSC_SCALL(os_openurl,
if (!SDL_OpenURL(str))
ret = JS_ThrowReferenceError(js, "unable to open url %s: %s\n", str, SDL_GetError());
)
JSC_SCALL(console_print,
printf("%s", str);
)
@@ -1957,12 +1953,6 @@ static const JSCFunctionListEntry js_font_funcs[] = {
MIST_FUNC_DEF(font, text_size, 3),
};
JSValue js_os_sys(JSContext *js, JSValue self, int argc, JSValue *argv)
{
return JS_NewString(js, SDL_GetPlatform());
}
// input: (encoded image data of jpg, png, bmp, tiff)
JSC_CCALL(os_make_texture,
size_t len;
@@ -2850,6 +2840,7 @@ void ffi_load(JSContext *js)
arrput(rt->module_registry, ((ModuleEntry){"io", js_io_use}));
arrput(rt->module_registry, ((ModuleEntry){"os", js_os_use}));
arrput(rt->module_registry, ((ModuleEntry){"actor", js_actor_use}));
arrput(rt->module_registry, ((ModuleEntry){"input", js_input_use}));
arrput(rt->module_registry, MISTLINE(time));
arrput(rt->module_registry, ((ModuleEntry){"math", js_math_use}));
@@ -2894,13 +2885,6 @@ void ffi_load(JSContext *js)
QJSCLASSPREP_FUNCS(SDL_Window)
QJSCLASSPREP_FUNCS(SDL_Surface)
QJSCLASSPREP_FUNCS(SDL_Texture)
// Initialize extracted modules which handle their own class registrations
js_input_use(js); // Handles input
js_camera_use(js); // Handles camera
js_sdl_audio_use(js); // Handles SDL_AudioStream and other SDL classes
// js_sdl_gpu_use(js); // Handles all GPU classes
js_io_use(js); // Handles PHYSFS_File
QJSCLASSPREP_FUNCS(renderer_ctx)
QJSCLASSPREP_FUNCS(font);

115
source/qjs_actor.c Normal file
View File

@@ -0,0 +1,115 @@
#include "qjs_actor.h"
#include "jsffi.h"
#include "qjs_macros.h"
#include "qjs_wota.h"
#include "prosperon.h"
#include <SDL3/SDL.h>
#include <stdlib.h>
#include <string.h>
// External variables
extern prosperon_rt *io_actor;
// External function declarations
JSValue js_actor_delay(JSContext *js, JSValue self, int argc, JSValue *argv);
JSValue js_actor_removetimer(JSContext *js, JSValue self, int argc, JSValue *argv);
JSValue js_os_ioactor(JSContext *js, JSValue self, int argc, JSValue *argv);
JSC_CCALL(os_createactor,
int margc = JS_ArrayLength(js, argv[0]);
char **margv = malloc(margc*sizeof(char*));
for (int i = 0; i < margc; i++) {
JSValue val = JS_GetPropertyUint32(js, argv[0], i);
const char *cstr = JS_ToCString(js,val);
margv[i] = strdup(cstr);
JS_FreeCString(js,cstr);
JS_FreeValue(js,val);
}
create_actor(margc, margv);
)
JSC_CCALL(os_mailbox_push,
if (argc < 2) return JS_ThrowInternalError(js, "Need an actor and a message");
if (!JS_IsObject(argv[1])) return JS_ThrowInternalError(js, "Object to push must be an object.");
const char *id = JS_ToCString(js, argv[0]);
int exist = actor_exists(id);
JS_FreeCString(js,id);
if (!exist)
return JS_ThrowInternalError(js, "No mailbox found for given ID");
void *data = value2wota(js, argv[1], JS_UNDEFINED);
const char *err = send_message(id, data);
if (err) {
free(data);
return JS_ThrowInternalError(js, "Could not send message: %s", err);
}
)
JSC_CCALL(os_register_actor,
prosperon_rt *rt = JS_GetContextOpaque(js);
const char *id = JS_ToCString(js, argv[0]);
const char *err = register_actor(id, rt, JS_ToBool(js, argv[2]));
if (err) return JS_ThrowInternalError(js, "Could not register actor: %s", err);
rt->message_handle = JS_DupValue(js, argv[1]);
rt->context = js;
JS_FreeCString(js, id);
)
JSC_CCALL(os_mailbox_exist,
const char *id = JS_ToCString(js, argv[0]);
int exist = actor_exists(id);
JS_FreeCString(js, id);
return JS_NewBool(js, exist);
)
JSC_CCALL(os_unneeded,
prosperon_rt *actor = JS_GetContextOpaque(js);
SDL_LockMutex(actor->msg_mutex);
JS_FreeValue(js, actor->unneeded);
if (!JS_IsFunction(js, argv[0])) {
actor->unneeded = JS_UNDEFINED;
goto END;
}
actor->unneeded = JS_DupValue(js, argv[0]);
JS_ToFloat64(js, &actor->unneeded_secs, argv[1]);
END:
if (actor->ar) {
SDL_RemoveTimer(actor->ar);
actor->ar = 0;
}
set_actor_state(actor);
SDL_UnlockMutex(actor->msg_mutex);
)
JSC_CCALL(os_destroy,
prosperon_rt *rt = JS_GetContextOpaque(js);
rt->need_stop = 1;
)
static const JSCFunctionListEntry js_actor_funcs[] = {
MIST_FUNC_DEF(os, createactor, 1),
MIST_FUNC_DEF(os, mailbox_push, 2),
MIST_FUNC_DEF(os, mailbox_exist, 1),
MIST_FUNC_DEF(actor, delay, 2),
MIST_FUNC_DEF(actor, removetimer, 1),
MIST_FUNC_DEF(os, register_actor, 2),
MIST_FUNC_DEF(os, unneeded, 2),
MIST_FUNC_DEF(os, destroy, 0),
MIST_FUNC_DEF(os, ioactor, 0),
};
JSValue js_actor_use(JSContext *js) {
JSValue mod = JS_NewObject(js);
JS_SetPropertyFunctionList(js,mod,js_actor_funcs,countof(js_actor_funcs));
return mod;
}

8
source/qjs_actor.h Normal file
View File

@@ -0,0 +1,8 @@
#ifndef QJS_ACTOR_H
#define QJS_ACTOR_H
#include <quickjs.h>
JSValue js_actor_use(JSContext *js);
#endif

View File

@@ -374,9 +374,9 @@ static const JSCFunctionListEntry js_PHYSFS_File_funcs[] = {
};
JSValue js_io_use(JSContext *js) {
QJSCLASSPREP_FUNCS(PHYSFS_File);
JSValue mod = JS_NewObject(js);
JS_SetPropertyFunctionList(js,mod,js_io_funcs,countof(js_io_funcs));
return mod;
}
// Note: PHYSFS_File class functions are registered via QJSCLASSPREP_FUNCS(PHYSFS_File) in main FFI loading

View File

@@ -28,62 +28,24 @@
// External variables
extern int trace;
extern prosperon_rt *io_actor;
// External function declarations
extern JSClassID js_transform_id;
JSValue transform2js(JSContext *js, transform *t);
transform *js2transform(JSContext *js, JSValue v);
// OS FUNCTIONS
JSC_SCALL(os_openurl,
if (SDL_OpenURL(str) < 0)
ret = JS_ThrowInternalError(js, "%s", SDL_GetError());
)
JSC_SCALL(os_env,
char *env = getenv(str);
if (env) ret = JS_NewString(js,env);
)
JSC_CCALL(os_exit, exit(js2number(js,argv[0]));)
JSC_CCALL(os_now, return number2js(js, (double)SDL_GetTicksNS()/1000000000.0))
JSC_SCALL(os_system, ret = number2js(js,system(str)); )
JSC_SCALL(os_kill,
pid_t pid = js2number(js,argv[0]);
if (kill(pid, SIGTERM) < 0)
ret = JS_ThrowReferenceError(js,"could not kill process");
)
JSC_CCALL(os_sleep,
double secs = js2number(js,argv[0]);
int ms = secs*1000;
SDL_Delay(ms);
)
JSC_CCALL(os_battery_pct,
int pct;
SDL_PowerState state = SDL_GetPowerInfo(&pct, NULL);
return number2js(js,pct);
)
JSC_CCALL(os_battery_voltage,
return number2js(js,0);
)
JSC_CCALL(os_battery_seconds,
int secs;
SDL_PowerState state = SDL_GetPowerInfo(NULL, &secs);
return number2js(js, secs);
)
JSC_CCALL(os_power_state,
int pct, secs;
SDL_PowerState state = SDL_GetPowerInfo(&pct, &secs);
SDL_PowerState state = SDL_GetPowerInfo(&secs, &pct);
const char *statestr = "unknown";
switch(state) {
case SDL_POWERSTATE_ON_BATTERY: statestr = "battery"; break;
@@ -113,7 +75,6 @@ JSC_CCALL(os_hostname,
#endif
)
JSC_CCALL(os_arch,
#if defined(__x86_64__) || defined(_M_X64)
return JS_NewString(js,"x64");
@@ -269,108 +230,7 @@ JSC_CCALL(os_rusage,
return ret;
)
JSC_CCALL(os_createprocess,
int ac = JS_ArrayLength(js,argv[0]);
const char *args[ac+1];
for (int i = 0; i < ac; i++) {
JSValue astr = JS_GetPropertyUint32(js,argv[0],i);
args[i] = JS_ToCString(js,astr);
JS_FreeValue(js,astr);
}
args[ac] = NULL;
SDL_Process *actor = SDL_CreateProcess(args, 0);
for (int i = 0; i < ac; i++)
JS_FreeCString(js,args[i]);
if (!actor)
return JS_ThrowReferenceError(js, "Unable to create process: %s\n", SDL_GetError());
)
JSC_CCALL(os_createactor,
int margc = JS_ArrayLength(js, argv[0]);
char **margv = malloc(margc*sizeof(char*));
for (int i = 0; i < margc; i++) {
JSValue val = JS_GetPropertyUint32(js, argv[0], i);
const char *cstr = JS_ToCString(js,val);
margv[i] = strdup(cstr);
JS_FreeCString(js,cstr);
JS_FreeValue(js,val);
}
create_actor(margc, margv);
)
JSC_CCALL(os_mailbox_push,
if (argc < 2) return JS_ThrowInternalError(js, "Need an actor and a message");
if (!JS_IsObject(argv[1])) return JS_ThrowInternalError(js, "Object to push must be an object.");
const char *id = JS_ToCString(js, argv[0]);
int exist = actor_exists(id);
JS_FreeCString(js,id);
if (!exist)
return JS_ThrowInternalError(js, "No mailbox found for given ID");
void *data = value2wota(js, argv[1], JS_UNDEFINED);
const char *err = send_message(id, data);
if (err) {
free(data);
return JS_ThrowInternalError(js, "Could not send message: %s", err);
}
)
JSC_CCALL(os_register_actor,
prosperon_rt *rt = JS_GetContextOpaque(js);
const char *id = JS_ToCString(js, argv[0]);
const char *err = register_actor(id, rt, JS_ToBool(js, argv[2]));
if (err) return JS_ThrowInternalError(js, "Could not register actor: %s", err);
rt->message_handle = JS_DupValue(js, argv[1]);
rt->context = js;
JS_FreeCString(js, id);
)
JSC_CCALL(os_mailbox_exist,
const char *id = JS_ToCString(js, argv[0]);
int exist = actor_exists(id);
JS_FreeCString(js, id);
return JS_NewBool(js, exist);
)
JSC_CCALL(os_unneeded,
prosperon_rt *actor = JS_GetContextOpaque(js);
SDL_LockMutex(actor->msg_mutex);
JS_FreeValue(js, actor->unneeded);
if (!JS_IsFunction(js, argv[0])) {
actor->unneeded = JS_UNDEFINED;
goto END;
}
actor->unneeded = JS_DupValue(js, argv[0]);
JS_ToFloat64(js, &actor->unneeded_secs, argv[1]);
END:
if (actor->ar) {
SDL_RemoveTimer(actor->ar);
actor->ar = 0;
}
set_actor_state(actor);
SDL_UnlockMutex(actor->msg_mutex);
)
JSC_CCALL(os_destroy,
prosperon_rt *rt = JS_GetContextOpaque(js);
rt->need_stop = 1;
)
static const JSCFunctionListEntry js_os_funcs[] = {
MIST_FUNC_DEF(os, platform, 0),
MIST_FUNC_DEF(os, arch, 0),
MIST_FUNC_DEF(os, totalmem, 0),
@@ -378,39 +238,12 @@ static const JSCFunctionListEntry js_os_funcs[] = {
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, kill, 1),
MIST_FUNC_DEF(os, exit, 1),
MIST_FUNC_DEF(os, now, 0),
MIST_FUNC_DEF(os, openurl, 1),
MIST_FUNC_DEF(os, sleep, 1),
MIST_FUNC_DEF(os, battery_pct, 0),
MIST_FUNC_DEF(os, battery_voltage, 0),
MIST_FUNC_DEF(os, battery_seconds, 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),
// dangerous ones that need disabled for shipping
MIST_FUNC_DEF(os, env, 1),
MIST_FUNC_DEF(os, system, 1),
MIST_FUNC_DEF(os, createprocess, 0),
MIST_FUNC_DEF(os, createactor, 1),
MIST_FUNC_DEF(os, mailbox_push, 2),
MIST_FUNC_DEF(os, mailbox_exist, 1),
MIST_FUNC_DEF(actor, delay, 2),
MIST_FUNC_DEF(actor, removetimer, 1),
MIST_FUNC_DEF(os, register_actor, 2),
MIST_FUNC_DEF(os, unneeded, 2),
MIST_FUNC_DEF(os, destroy, 0),
MIST_FUNC_DEF(os, ioactor, 0),
};
JSValue js_os_use(JSContext *js) {

View File

@@ -158,7 +158,6 @@ static const JSCFunctionListEntry js_camera_funcs[] = {
MIST_FUNC_DEF(camera, position, 1),
};
static const JSCFunctionListEntry js_SDL_Camera_funcs[] =
{
// MIST_FUNC_DEF(camera, frame, 0),
@@ -470,6 +469,8 @@ static const JSCFunctionListEntry js_SDL_AudioStream_funcs[] = {
};
JSValue js_sdl_audio_use(JSContext *js) {
QJSCLASSPREP_FUNCS(SDL_AudioStream)
JSValue mod = JS_NewObject(js);
JS_SetPropertyFunctionList(js,mod,js_sdl_audio_funcs,countof(js_sdl_audio_funcs));
return mod;

View File

@@ -171,7 +171,7 @@ function pollTests() {
}
// Sleep a bit to avoid pegging the CPU (requires a C function or std.sleep)
os.sleep(0.01);
// TODO: Implement!
}
}

View File

@@ -1,13 +1,9 @@
// Creates a portal and a separate actor to contact
var os = use('os')
//os.createprocess(["./prosperon", "tests/portal.js"])
var children = []
os.createprocess(["./prosperon", "tests/portal.js"])
$_.delay(_ => {
os.createprocess(["./prosperon", "tests/contact.js"])
$_.stop()
//$_.delay(_ => {
// os.createprocess(["./prosperon", "tests/contact.js"])
// $_.stop()
// $_.delay($_.stop, 0.1)
}, 0.2)
//}, 0.2)

View File

@@ -1,6 +1,7 @@
// bunnymark
var render = use('render')
var os = use('os')
var actor = use('actor')
var transform = use('transform')
var dim = [500,500]
render.initialize({
@@ -32,7 +33,7 @@ var dt = 0
var img = "alcinaqr"
var ioguy = {
__ACTORDATA__: { id: os.ioactor() }
__ACTORDATA__: { id: actor.ioactor() }
}
var io = use('io')

View File

@@ -37,9 +37,10 @@ loop()
$_.delay($_.stop, 3)
var os = use('os')
var actor = use('actor')
var ioguy = {
__ACTORDATA__: {
id: os.ioactor()
id: actor.ioactor()
}
}