Files
cell/source/qjs_actor.c

180 lines
4.7 KiB
C

#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 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);
prosperon_rt *js2actor(JSContext *js, JSValue v)
{
if (!JS_IsObject(v))
return NULL;
/* Check if it has __ACTORDATA__ property */
JSValue actor_data = JS_GetPropertyStr(js, v, "__ACTORDATA__");
if (JS_IsUndefined(actor_data)) {
JS_FreeValue(js, actor_data);
return NULL;
}
/* Get the id from __ACTORDATA__ */
JSValue id_val = JS_GetPropertyStr(js, actor_data, "id");
JS_FreeValue(js, actor_data);
if (JS_IsUndefined(id_val)) {
JS_FreeValue(js, id_val);
return NULL;
}
const char *id = JS_ToCString(js, id_val);
JS_FreeValue(js, id_val);
if (!id)
return NULL;
/* Look up the actor by ID */
prosperon_rt *actor = get_actor((char*)id);
JS_FreeCString(js, id);
return actor;
}
JSValue actor2js(JSContext *js, prosperon_rt *actor)
{
if (!actor)
return JS_NULL;
/* Create the actor object */
JSValue actor_obj = JS_NewObject(js);
if (JS_IsException(actor_obj))
return actor_obj;
/* Create the __ACTORDATA__ object */
JSValue actor_data = JS_NewObject(js);
if (JS_IsException(actor_data)) {
JS_FreeValue(js, actor_obj);
return actor_data;
}
/* Set the id property in __ACTORDATA__ */
JS_SetPropertyStr(js, actor_data, "id", JS_NewString(js, actor->id));
/* TODO: If the actor has network info, we could add address and port here */
/* JS_SetPropertyStr(js, actor_data, "address", JS_NewString(js, actor->address)); */
/* JS_SetPropertyStr(js, actor_data, "port", JS_NewInt32(js, actor->port)); */
/* Set __ACTORDATA__ on the actor object */
JS_SetPropertyStr(js, actor_obj, "__ACTORDATA__", actor_data);
return actor_obj;
}
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, NULL);
)
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;
)
JSC_SCALL(actor_setname,
prosperon_rt *rt = JS_GetContextOpaque(js);
rt->name = strdup(str);
)
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(actor, setname, 1),
};
JSValue js_actor_use(JSContext *js) {
JSValue mod = JS_NewObject(js);
JS_SetPropertyFunctionList(js,mod,js_actor_funcs,countof(js_actor_funcs));
return mod;
}