no more js leaking on free
This commit is contained in:
@@ -155,6 +155,11 @@ endif
|
||||
quickjs_opts = []
|
||||
quickjs_opts += 'default_library=static'
|
||||
|
||||
# Enable leak detection for non-release builds
|
||||
if get_option('buildtype') != 'release'
|
||||
quickjs_opts += 'leaks=true'
|
||||
endif
|
||||
|
||||
# Try to find system-installed quickjs first
|
||||
quickjs_dep = dependency('quickjs', static: true, required: false)
|
||||
if not quickjs_dep.found()
|
||||
|
||||
@@ -33,7 +33,7 @@ debug.backtrace_fns[cell.DOC] = `Return an array of functions in the current bac
|
||||
:return: An array of function objects from the call stack.
|
||||
`
|
||||
|
||||
debug.dump_obj[cell.DOC] = `Return a string representation of a given object.
|
||||
debug.dump[cell.DOC] = `Return a string representation of a given object.
|
||||
|
||||
:param obj: The object to dump.
|
||||
:return: A string describing the object's contents.
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
(function engine() {
|
||||
globalThis.cell = prosperon
|
||||
cell.DOC = cell.hidden.DOCSYM
|
||||
var ACTORDATA = cell.hidden.ACTORSYM
|
||||
|
||||
var MOD_EXT = '.cm'
|
||||
var ACTOR_EXT = '.ce'
|
||||
@@ -39,6 +40,8 @@ function console_rec(line, file, msg) {
|
||||
|
||||
var console_mod = cell.hidden.console
|
||||
|
||||
|
||||
|
||||
var logs = {}
|
||||
logs.console = function(msg)
|
||||
{
|
||||
@@ -101,7 +104,7 @@ os.on = function(e)
|
||||
log.console(JSON.stringify(e))
|
||||
log.error(e)
|
||||
|
||||
disrupt()
|
||||
actor_mod.disrupt()
|
||||
}
|
||||
|
||||
var js = use_embed('js')
|
||||
@@ -137,8 +140,6 @@ var fnname = "base"
|
||||
script = `(function ${fnname}() { ${script}; })`
|
||||
js.eval(BASEPATH, script)()
|
||||
|
||||
|
||||
|
||||
var inProgress = {}
|
||||
var loadingStack = []
|
||||
|
||||
@@ -317,8 +318,10 @@ var dying = false
|
||||
|
||||
var HEADER = Symbol()
|
||||
|
||||
function create_actor(__ACTORDATA__ = {id:util.guid()}) {
|
||||
return { __ACTORDATA__ }
|
||||
function create_actor(desc = {id:util.guid()}) {
|
||||
var actor = {}
|
||||
actor[ACTORDATA] = desc
|
||||
return actor
|
||||
}
|
||||
|
||||
var $_ = create_actor()
|
||||
@@ -339,7 +342,7 @@ var receive_fn = undefined
|
||||
var greeters = {}
|
||||
|
||||
function is_actor(actor) {
|
||||
return actor.__ACTORDATA__
|
||||
return actor[ACTORDATA]
|
||||
}
|
||||
|
||||
globalThis.is_actor = is_actor;
|
||||
@@ -368,12 +371,12 @@ function peer_connection(peer) {
|
||||
}
|
||||
|
||||
$_.connection = function(callback, actor, config) {
|
||||
var peer = peers[actor.__ACTORDATA__.id]
|
||||
var peer = peers[actor[ACTORDATA].id]
|
||||
if (peer) {
|
||||
callback(peer_connection(peer))
|
||||
return
|
||||
}
|
||||
if (actor_mod.mailbox_exist(actor.__ACTORDATA__.id)) {
|
||||
if (actor_mod.mailbox_exist(actor[ACTORDATA].id)) {
|
||||
callback({type:"local"})
|
||||
return
|
||||
}
|
||||
@@ -419,15 +422,15 @@ function handle_host(e) {
|
||||
var data = nota.decode(e.data)
|
||||
// log.console(`got message ${json.encode(data)} over the wire`)
|
||||
if (data.replycc && !data.replycc.address) {
|
||||
data.replycc.__ACTORDATA__.address = e.peer.address
|
||||
data.replycc.__ACTORDATA__.port = e.peer.port
|
||||
data.replycc[ACTORDATA].address = e.peer.address
|
||||
data.replycc[ACTORDATA].port = e.peer.port
|
||||
}
|
||||
// Also populate address/port for any actor objects in the message data
|
||||
function populate_actor_addresses(obj) {
|
||||
if (typeof obj !== 'object' || obj === null) return
|
||||
if (obj.__ACTORDATA__ && !obj.__ACTORDATA__.address) {
|
||||
obj.__ACTORDATA__.address = e.peer.address
|
||||
obj.__ACTORDATA__.port = e.peer.port
|
||||
if (obj[ACTORDATA] && !obj[ACTORDATA].address) {
|
||||
obj[ACTORDATA].address = e.peer.address
|
||||
obj[ACTORDATA].port = e.peer.port
|
||||
}
|
||||
for (var key in obj) {
|
||||
if (obj.hasOwnProperty(key)) {
|
||||
@@ -480,7 +483,7 @@ $_.stop = function stop(actor) {
|
||||
}
|
||||
if (!is_actor(actor))
|
||||
throw new Error('Can only call stop on an actor.')
|
||||
if (!underlings.has(actor.__ACTORDATA__.id))
|
||||
if (!underlings.has(actor[ACTORDATA].id))
|
||||
throw new Error('Can only call stop on an underling or self.')
|
||||
|
||||
actor_prep(actor, {type:"stop", id: cell.id})
|
||||
@@ -504,18 +507,10 @@ $_.delay[cell.DOC] = "used to schedule the invocation of a function..."
|
||||
|
||||
var couplings = new Set()
|
||||
$_.couple = function couple(actor) {
|
||||
log.console(`coupled to ${actor.__ACTORDATA__.id}`)
|
||||
couplings.add(actor.__ACTORDATA__.id)
|
||||
couplings.add(actor[ACTORDATA].id)
|
||||
}
|
||||
$_.couple[cell.DOC] = "causes this actor to stop when another actor stops."
|
||||
|
||||
function disrupt()
|
||||
{
|
||||
dying = true
|
||||
if (overling) actor_prep(overling, {type:'disrupt', actor: $_})
|
||||
actor_mod.destroy()
|
||||
}
|
||||
|
||||
function actor_prep(actor, send) {
|
||||
message_queue.push({actor,send});
|
||||
}
|
||||
@@ -529,32 +524,32 @@ function actor_send(actor, message) {
|
||||
if (typeof message !== 'object') throw new Error('Must send an object record.')
|
||||
|
||||
// message to self
|
||||
if (actor.__ACTORDATA__.id === cell.id) {
|
||||
if (actor[ACTORDATA].id === cell.id) {
|
||||
if (receive_fn) receive_fn(message.data)
|
||||
return
|
||||
}
|
||||
|
||||
// message to actor in same flock
|
||||
if (actor.__ACTORDATA__.id && actor_mod.mailbox_exist(actor.__ACTORDATA__.id)) {
|
||||
actor_mod.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) {
|
||||
if (actor.__ACTORDATA__.id)
|
||||
message.target = actor.__ACTORDATA__.id
|
||||
if (actor[ACTORDATA].address) {
|
||||
if (actor[ACTORDATA].id)
|
||||
message.target = actor[ACTORDATA].id
|
||||
else
|
||||
message.type = "contact"
|
||||
|
||||
var peer = peers[actor.__ACTORDATA__.address + ":" + actor.__ACTORDATA__.port]
|
||||
var peer = peers[actor[ACTORDATA].address + ":" + actor[ACTORDATA].port]
|
||||
if (!peer) {
|
||||
if (!portal) {
|
||||
log.console(`creating a contactor ...`)
|
||||
portal = enet.create_host({address:"any"})
|
||||
log.console(`allowing contact to port ${portal.port}`)
|
||||
}
|
||||
log.console(`no peer! connecting to ${actor.__ACTORDATA__.address}:${actor.__ACTORDATA__.port}`)
|
||||
peer = portal.connect(actor.__ACTORDATA__.address, actor.__ACTORDATA__.port)
|
||||
log.console(`no peer! connecting to ${actor[ACTORDATA].address}:${actor[ACTORDATA].port}`)
|
||||
peer = portal.connect(actor[ACTORDATA].address, actor[ACTORDATA].port)
|
||||
peer_queue.set(peer, [message])
|
||||
} else {
|
||||
peer.send(nota.encode(message))
|
||||
@@ -626,7 +621,7 @@ else cell.id = cell.args.id
|
||||
// Make remaining arguments available as global 'args' variable
|
||||
globalThis.args = cell.args.remaining || []
|
||||
|
||||
$_.__ACTORDATA__.id = cell.id
|
||||
$_[ACTORDATA].id = cell.id
|
||||
|
||||
function turn(msg)
|
||||
{
|
||||
@@ -667,8 +662,7 @@ function handle_actor_disconnect(id) {
|
||||
delete greeters[id]
|
||||
}
|
||||
log.console(`actor ${id} disconnected`)
|
||||
if (couplings.has(id)) $_.stop()
|
||||
delete peers[id]
|
||||
if (couplings.has(id)) actor_mod.disrupt() // couplings now disrupts instead of stop
|
||||
}
|
||||
|
||||
function handle_message(msg) {
|
||||
@@ -694,7 +688,7 @@ function handle_message(msg) {
|
||||
if (receive_fn) receive_fn(letter)
|
||||
break
|
||||
case "stop":
|
||||
if (msg.id !== overling.__ACTORDATA__.id)
|
||||
if (msg.id !== overling[ACTORDATA].id)
|
||||
throw new Error(`Got a message from an actor ${msg.id} to stop...`)
|
||||
destroyself()
|
||||
break
|
||||
@@ -710,7 +704,7 @@ function handle_message(msg) {
|
||||
handle_actor_disconnect(msg.id)
|
||||
break
|
||||
case "greet":
|
||||
var greeter = greeters[msg.actor.__ACTORDATA__.id]
|
||||
var greeter = greeters[msg.actor[ACTORDATA].id]
|
||||
if (greeter) greeter(msg)
|
||||
break;
|
||||
default:
|
||||
@@ -751,12 +745,18 @@ var progDir = prog.substring(0, prog.lastIndexOf('/'))
|
||||
if (progDir && progDir !== '.') {
|
||||
io.mount(progDir, "")
|
||||
}
|
||||
|
||||
//log.console($_[ACTORDATA])
|
||||
//log.console(json.encode($_[ACTORDATA]))
|
||||
//actor_mod.testfn($_)
|
||||
var progContent = io.slurp(prog)
|
||||
var prog_script = `(function ${cell.args.program.name()}_start($_, arg) { ${progContent} })`
|
||||
var val = js.eval(cell.args.program, prog_script)($_, )
|
||||
try {
|
||||
var val = js.eval(cell.args.program, prog_script)($_, cell.args.arg)
|
||||
if (val)
|
||||
throw new Error('Program must not return anything');
|
||||
} catch(e) {
|
||||
actor_mod.disrupt()
|
||||
}
|
||||
|
||||
send_messages()
|
||||
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
var io = use("io")
|
||||
|
||||
var test = args[0]
|
||||
var test = arg[0]
|
||||
|
||||
if (test) {
|
||||
log.console(`gonna run ${test}`)
|
||||
throw 1
|
||||
$_.stop()
|
||||
}
|
||||
|
||||
var fs = io.enumerate("tests");
|
||||
var tests = [];
|
||||
var passed = 0;
|
||||
|
||||
220
source/cell.c
220
source/cell.c
@@ -60,8 +60,91 @@ static Uint32 queue_event;
|
||||
static SDL_AtomicInt engine_shutdown;
|
||||
static SDL_Thread **runners = NULL;
|
||||
|
||||
|
||||
void actor_free(cell_rt *actor)
|
||||
{
|
||||
// Delete it out of actors first so it can no longer get messages
|
||||
SDL_LockMutex(actors_mutex);
|
||||
shdel(actors, actor->id);
|
||||
int remaining = shlen(actors);
|
||||
SDL_UnlockMutex(actors_mutex);
|
||||
|
||||
// If in a queue, remove it
|
||||
SDL_LockMutex(queue_mutex);
|
||||
|
||||
for (int i = 0; i < arrlen(ready_queue); i++) {
|
||||
if (ready_queue[i] == actor) {
|
||||
arrdel(ready_queue, i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
SDL_UnlockMutex(queue_mutex);
|
||||
|
||||
// Do not go forward with actor destruction until the actor is completely free
|
||||
SDL_LockMutex(actor->mutex);
|
||||
SDL_LockMutex(actor->msg_mutex);
|
||||
SDL_LockMutex(actor->turn);
|
||||
|
||||
JSContext *js = actor->context;
|
||||
|
||||
JS_FreeValue(js, actor->cycle_fn);
|
||||
JS_FreeValue(js, actor->idx_buffer);
|
||||
JS_FreeValue(js, actor->message_handle);
|
||||
JS_FreeValue(js, actor->on_exception);
|
||||
JS_FreeValue(js, actor->unneeded);
|
||||
JS_FreeAtom(js, actor->doc_sym);
|
||||
JS_FreeAtom(js, actor->actor_sym);
|
||||
|
||||
SDL_RemoveTimer(actor->ar);
|
||||
for (int i = 0; i < arrlen(actor->js_swapchains); i++)
|
||||
JS_FreeValue(js, actor->js_swapchains[i]);
|
||||
|
||||
for (int i = 0; i < hmlen(actor->timers); i++) {
|
||||
SDL_RemoveTimer(actor->timers[i].key);
|
||||
JS_FreeValue(js, actor->timers[i].value);
|
||||
}
|
||||
|
||||
hmfree(actor->timers);
|
||||
arrfree(actor->js_swapchains);
|
||||
arrfree(actor->module_registry);
|
||||
|
||||
for (int i = 0; i < arrlen(actor->messages); i++)
|
||||
free(actor->messages[i]);
|
||||
|
||||
arrfree(actor->messages);
|
||||
|
||||
/* If still present, free each JSValue. */
|
||||
for (int i = 0; i < arrlen(actor->events); i++)
|
||||
JS_FreeValue(js, actor->events[i]);
|
||||
|
||||
arrfree(actor->events);
|
||||
|
||||
JSRuntime *rt = JS_GetRuntime(js);
|
||||
JS_SetInterruptHandler(rt, NULL, NULL);
|
||||
JS_FreeContext(js);
|
||||
JS_FreeRuntime(rt);
|
||||
free(actor->id);
|
||||
|
||||
SDL_UnlockMutex(actor->mutex);
|
||||
SDL_DestroyMutex(actor->mutex);
|
||||
SDL_UnlockMutex(actor->msg_mutex);
|
||||
SDL_DestroyMutex(actor->msg_mutex);
|
||||
SDL_UnlockMutex(actor->turn);
|
||||
SDL_DestroyMutex(actor->turn);
|
||||
|
||||
free(actor);
|
||||
|
||||
if (remaining == 0)
|
||||
exit(0);
|
||||
}
|
||||
|
||||
static Uint32 actor_remove_cb(cell_rt *actor, Uint32 id, Uint32 interval)
|
||||
{
|
||||
if (actor->need_stop) {
|
||||
actor_free(actor);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (JS_IsUndefined(actor->unneeded))
|
||||
actor_free(actor);
|
||||
else {
|
||||
@@ -69,8 +152,7 @@ static Uint32 actor_remove_cb(cell_rt *actor, Uint32 id, Uint32 interval)
|
||||
JSValue ret = JS_Call(actor->context, actor->unneeded, JS_UNDEFINED, 0, NULL);
|
||||
uncaught_exception(actor->context, ret);
|
||||
SDL_UnlockMutex(actor->mutex);
|
||||
|
||||
set_actor_state(actor);
|
||||
actor_free(actor);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -304,8 +386,9 @@ void set_actor_state(cell_rt *actor)
|
||||
{
|
||||
SDL_LockMutex(actor->msg_mutex);
|
||||
if (actor->need_stop) {
|
||||
if (!actor->ar)
|
||||
actor->ar = SDL_AddTimerNS(0, actor_remove_cb, actor);
|
||||
SDL_UnlockMutex(actor->msg_mutex);
|
||||
actor_free(actor);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -346,7 +429,7 @@ void set_actor_state(cell_rt *actor)
|
||||
END:
|
||||
if (actor->state == ACTOR_IDLE && !actor->ar && !has_upcoming) {
|
||||
if (JS_IsUndefined(actor->unneeded))
|
||||
actor->ar = SDL_AddTimerNS(SDL_SECONDS_TO_NS(1), actor_remove_cb, actor);
|
||||
actor->ar = SDL_AddTimerNS(SDL_SECONDS_TO_NS(5), actor_remove_cb, actor);
|
||||
else {
|
||||
if (!isinf(actor->unneeded_secs))
|
||||
actor->ar = SDL_AddTimerNS(SDL_SECONDS_TO_NS(actor->unneeded_secs), actor_remove_cb, actor);
|
||||
@@ -465,80 +548,6 @@ void actor_turn(cell_rt *actor, int greedy)
|
||||
actor_free(actor);
|
||||
}
|
||||
|
||||
void actor_free(cell_rt *actor)
|
||||
{
|
||||
// Delete it out of actors first so it can no longer get messages
|
||||
SDL_LockMutex(actors_mutex);
|
||||
shdel(actors, actor->id);
|
||||
int remaining = shlen(actors);
|
||||
SDL_UnlockMutex(actors_mutex);
|
||||
|
||||
// If in a queue, remove it
|
||||
SDL_LockMutex(queue_mutex);
|
||||
|
||||
for (int i = 0; i < arrlen(ready_queue); i++) {
|
||||
if (ready_queue[i] == actor) {
|
||||
arrdel(ready_queue, i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
SDL_UnlockMutex(queue_mutex);
|
||||
|
||||
// Do not go forward with actor destruction until the actor is completely free
|
||||
SDL_LockMutex(actor->mutex);
|
||||
SDL_LockMutex(actor->msg_mutex);
|
||||
SDL_LockMutex(actor->turn);
|
||||
|
||||
JSContext *js = actor->context;
|
||||
|
||||
JS_FreeValue(js, actor->cycle_fn);
|
||||
JS_FreeValue(js, actor->idx_buffer);
|
||||
JS_FreeValue(js, actor->message_handle);
|
||||
JS_FreeValue(js, actor->on_exception);
|
||||
JS_FreeValue(js, actor->unneeded);
|
||||
|
||||
SDL_RemoveTimer(actor->ar);
|
||||
for (int i = 0; i < arrlen(actor->js_swapchains); i++)
|
||||
JS_FreeValue(js, actor->js_swapchains[i]);
|
||||
|
||||
for (int i = 0; i < hmlen(actor->timers); i++) {
|
||||
SDL_RemoveTimer(actor->timers[i].key);
|
||||
JS_FreeValue(js, actor->timers[i].value);
|
||||
}
|
||||
|
||||
hmfree(actor->timers);
|
||||
arrfree(actor->js_swapchains);
|
||||
arrfree(actor->module_registry);
|
||||
|
||||
for (int i = 0; i < arrlen(actor->messages); i++)
|
||||
free(actor->messages[i]);
|
||||
|
||||
arrfree(actor->messages);
|
||||
|
||||
/* If still present, free each JSValue. */
|
||||
for (int i = 0; i < arrlen(actor->events); i++)
|
||||
JS_FreeValue(js, actor->events[i]);
|
||||
|
||||
arrfree(actor->events);
|
||||
|
||||
JSRuntime *rt = JS_GetRuntime(js);
|
||||
JS_FreeContext(js);
|
||||
JS_FreeRuntime(rt);
|
||||
free(actor->id);
|
||||
|
||||
SDL_UnlockMutex(actor->mutex);
|
||||
SDL_DestroyMutex(actor->mutex);
|
||||
SDL_UnlockMutex(actor->msg_mutex);
|
||||
SDL_DestroyMutex(actor->msg_mutex);
|
||||
SDL_UnlockMutex(actor->turn);
|
||||
SDL_DestroyMutex(actor->turn);
|
||||
|
||||
free(actor);
|
||||
|
||||
if (remaining == 1)
|
||||
exit(0);
|
||||
}
|
||||
|
||||
/* Timer callback adds an event to the queue under evt_mutex. */
|
||||
Uint32 actor_timer_cb(cell_rt *actor, SDL_TimerID id, Uint32 interval)
|
||||
{
|
||||
@@ -668,6 +677,20 @@ void tracy_end_hook(JSContext *js, JSValue fn)
|
||||
___tracy_emit_zone_end(arrpop(stack->arr));
|
||||
}
|
||||
|
||||
void actor_disrupt(cell_rt *crt)
|
||||
{
|
||||
crt->disrupt = 1;
|
||||
crt->need_stop = 1;
|
||||
// actor_free(crt);
|
||||
}
|
||||
|
||||
static int actor_interrupt_cb(JSRuntime *rt, cell_rt *crt)
|
||||
{
|
||||
if (crt->disrupt)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void script_startup(cell_rt *prt, void (*hook)(JSContext*))
|
||||
{
|
||||
JSRuntime *rt;
|
||||
@@ -681,6 +704,7 @@ void script_startup(cell_rt *prt, void (*hook)(JSContext*))
|
||||
#endif
|
||||
|
||||
JSContext *js = JS_NewContextRaw(rt);
|
||||
JS_SetInterruptHandler(rt, actor_interrupt_cb, prt);
|
||||
|
||||
#ifdef TRACY_ENABLE
|
||||
if (tracy_profiling_enabled) {
|
||||
@@ -734,23 +758,7 @@ int uncaught_exception(JSContext *js, JSValue v)
|
||||
}
|
||||
|
||||
JSValue exp = JS_GetException(js);
|
||||
|
||||
if (JS_IsFunction(js, rt->on_exception)) {
|
||||
JSValue ret = JS_Call(js, rt->on_exception, JS_UNDEFINED, 1, &exp);
|
||||
JS_FreeValue(js, ret);
|
||||
} else {
|
||||
const char *msg = JS_ToCString(js, exp);
|
||||
JSValue stack = JS_GetPropertyStr(js, exp, "stack");
|
||||
if (!JS_IsUndefined(stack)) {
|
||||
const char *st = JS_ToCString(js, stack);
|
||||
printf("Unhandled error: %s\n%s\n", msg, st);
|
||||
JS_FreeCString(js,st);
|
||||
JS_FreeValue(js,stack);
|
||||
} else
|
||||
printf("Unhandled exception: %s\n", msg);
|
||||
|
||||
JS_FreeCString(js, msg);
|
||||
}
|
||||
JSValue ret = JS_Call(js, rt->on_exception, JS_UNDEFINED, 1, &exp);
|
||||
JS_FreeValue(js, exp);
|
||||
SDL_UnlockMutex(rt->mutex);
|
||||
return 0;
|
||||
@@ -1490,6 +1498,8 @@ bool event_watch(void *data, SDL_Event *e)
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
// quickjs_set_dumpout(stdout);
|
||||
// quickjs_set_cycleout(stdout);
|
||||
const char *new_cwd = NULL;
|
||||
int profile_enabled = 0;
|
||||
int script_start = 1;
|
||||
@@ -1557,13 +1567,18 @@ int main(int argc, char **argv)
|
||||
|
||||
/* Create the initial actor from the main command line. */
|
||||
/* Adjust argc and argv to skip --profile if present */
|
||||
char **actor_argv = argv + (script_start - 1);
|
||||
int actor_argc = argc - (script_start);
|
||||
char **actor_argv = argv + (script_start);
|
||||
|
||||
WotaBuffer startwota;
|
||||
wota_buffer_init(&startwota, 5);
|
||||
wota_write_record(&startwota, 1);
|
||||
wota_write_record(&startwota, 2);
|
||||
wota_write_text(&startwota, "program");
|
||||
wota_write_text(&startwota, actor_argv[1]); // program name
|
||||
wota_write_text(&startwota, actor_argv[0]); // program name
|
||||
wota_write_text(&startwota, "arg");
|
||||
wota_write_array(&startwota, actor_argc-1);
|
||||
for (int i = 1; i < actor_argc; i++)
|
||||
wota_write_text(&startwota, actor_argv[i]);
|
||||
create_actor(startwota.data,NULL); // this can fall off because the actor takes care of freeing the wota data
|
||||
|
||||
/* Start the thread that pumps ready actors, one per logical core. */
|
||||
@@ -1612,3 +1627,12 @@ int actor_exists(const char *id)
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
|
||||
int JS_ArrayLength(JSContext *js, JSValue a)
|
||||
{
|
||||
JSValue length = JS_GetPropertyStr(js, a, "length");
|
||||
int len;
|
||||
JS_ToInt32(js,&len,length);
|
||||
JS_FreeValue(js,length);
|
||||
return len;
|
||||
}
|
||||
|
||||
@@ -63,10 +63,11 @@ typedef struct cell_rt {
|
||||
int state;
|
||||
Uint32 ar;
|
||||
int need_stop;
|
||||
int disrupt;
|
||||
int main_thread_only;
|
||||
|
||||
JSValue actor_sym;
|
||||
JSValue doc_sym;
|
||||
JSAtom actor_sym;
|
||||
JSAtom doc_sym;
|
||||
|
||||
const char *name; // human friendly name
|
||||
} cell_rt;
|
||||
@@ -76,7 +77,8 @@ extern SDL_TLSID prosperon_id;
|
||||
|
||||
cell_rt *create_actor(void *wota, void (*hook)(JSContext*));
|
||||
const char *register_actor(const char *id, cell_rt *actor, int mainthread);
|
||||
void actor_free(cell_rt *actor);
|
||||
void actor_disrupt(cell_rt *actor);
|
||||
|
||||
const char *send_message(const char *id, void *msg);
|
||||
Uint32 actor_timer_cb(cell_rt *actor, SDL_TimerID id, Uint32 interval);
|
||||
JSValue js_actor_delay(JSContext *js, JSValue self, int argc, JSValue *argv);
|
||||
@@ -89,6 +91,8 @@ int actor_exists(const char *id);
|
||||
cell_rt *get_actor(char *id);
|
||||
void set_actor_state(cell_rt *actor);
|
||||
|
||||
int JS_ArrayLength(JSContext *js, JSValue a);
|
||||
|
||||
int prosperon_mount_core(void);
|
||||
|
||||
// Event watchers for SDL events
|
||||
|
||||
@@ -1624,19 +1624,24 @@ void ffi_load(JSContext *js)
|
||||
JS_SetPropertyStr(js, hidden_fn, "use_dyn", JS_NewCFunction(js, js_os_use_dyn, "use_dyn", 1));
|
||||
JS_SetPropertyStr(js, hidden_fn, "use_embed", JS_NewCFunction(js, js_os_use_embed, "use_embed", 1));
|
||||
|
||||
JS_SetPropertyStr(js, prosp, "hidden", hidden_fn);
|
||||
|
||||
if (rt->init_wota) {
|
||||
JS_SetPropertyStr(js, hidden_fn, "init", wota2value(js, rt->init_wota));
|
||||
// init wota can now be freed
|
||||
free(rt->init_wota);
|
||||
rt->init_wota = NULL;
|
||||
}
|
||||
|
||||
JS_FreeValue(js,globalThis);
|
||||
|
||||
cell_rt *actor = JS_GetContextOpaque(js);
|
||||
actor->actor_sym = JS_NewSymbol(js, "actor symbol", 0);
|
||||
actor->doc_sym = JS_NewSymbol(js, "+documentation+", 0);
|
||||
JS_SetPropertyStr(js, hidden_fn, "ACTORDATA", actor->actor_sym);
|
||||
JS_SetPropertyStr(js, hidden_fn, "DOCSYM", actor->doc_sym);
|
||||
JSValue actorsym = js_newsymbol(js, "actor symbol", 0);
|
||||
actor->actor_sym = JS_ValueToAtom(js, actorsym);
|
||||
JS_SetPropertyStr(js, hidden_fn, "ACTORDATA", JS_DupValue(js,actorsym));
|
||||
JS_FreeValue(js, actorsym);
|
||||
JSValue docsym = js_newsymbol(js, "+documentation+", 0);
|
||||
actor->doc_sym = JS_ValueToAtom(js, docsym);
|
||||
JS_SetPropertyStr(js, hidden_fn, "DOCSYM", JS_DupValue(js,docsym));
|
||||
JS_FreeValue(js,docsym);
|
||||
|
||||
JS_SetPropertyStr(js, prosp, "hidden", hidden_fn);
|
||||
|
||||
JS_FreeValue(js,globalThis);
|
||||
}
|
||||
|
||||
@@ -16,15 +16,15 @@ cell_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__");
|
||||
|
||||
cell_rt *crt = JS_GetContextOpaque(js);
|
||||
JSValue actor_data = JS_GetProperty(js, v, crt->actor_sym);
|
||||
|
||||
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);
|
||||
|
||||
@@ -39,7 +39,6 @@ cell_rt *js2actor(JSContext *js, JSValue v)
|
||||
if (!id)
|
||||
return NULL;
|
||||
|
||||
/* Look up the actor by ID */
|
||||
cell_rt *actor = get_actor((char*)id);
|
||||
JS_FreeCString(js, id);
|
||||
|
||||
@@ -51,27 +50,25 @@ JSValue actor2js(JSContext *js, cell_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);
|
||||
cell_rt *crt = JS_GetContextOpaque(js);
|
||||
|
||||
JS_SetProperty(js, actor_obj, crt->actor_sym, actor_data);
|
||||
|
||||
return actor_obj;
|
||||
}
|
||||
@@ -146,11 +143,21 @@ JSC_CCALL(os_destroy,
|
||||
set_actor_state(rt);
|
||||
)
|
||||
|
||||
JSC_CCALL(actor_disrupt,
|
||||
cell_rt *crt = JS_GetContextOpaque(js);
|
||||
actor_disrupt(crt);
|
||||
)
|
||||
|
||||
JSC_SCALL(actor_setname,
|
||||
cell_rt *rt = JS_GetContextOpaque(js);
|
||||
rt->name = strdup(str);
|
||||
)
|
||||
|
||||
JSC_CCALL(actor_testfn,
|
||||
cell_rt *crt = js2actor(js, argv[0]);
|
||||
printf("actor? %p\n", crt);
|
||||
)
|
||||
|
||||
static const JSCFunctionListEntry js_actor_funcs[] = {
|
||||
MIST_FUNC_DEF(os, createactor, 1),
|
||||
MIST_FUNC_DEF(os, mailbox_push, 2),
|
||||
@@ -160,7 +167,9 @@ static const JSCFunctionListEntry js_actor_funcs[] = {
|
||||
MIST_FUNC_DEF(os, register_actor, 2),
|
||||
MIST_FUNC_DEF(os, unneeded, 2),
|
||||
MIST_FUNC_DEF(os, destroy, 0),
|
||||
MIST_FUNC_DEF(actor, disrupt, 0),
|
||||
MIST_FUNC_DEF(actor, setname, 1),
|
||||
MIST_FUNC_DEF(actor, testfn, 1),
|
||||
};
|
||||
|
||||
JSValue js_actor_use(JSContext *js) {
|
||||
|
||||
@@ -2,15 +2,29 @@
|
||||
#include "qjs_macros.h"
|
||||
#include "jsffi.h"
|
||||
|
||||
// Debug function implementations
|
||||
|
||||
JSC_CCALL(debug_stack_depth, return number2js(js,js_debugger_stack_depth(js)))
|
||||
JSC_CCALL(debug_build_backtrace, return js_debugger_build_backtrace(js,NULL))
|
||||
JSC_CCALL(debug_closure_vars, return js_debugger_closure_variables(js,argv[0]))
|
||||
JSC_CCALL(debug_local_vars, return js_debugger_local_variables(js, js2number(js,argv[0])))
|
||||
JSC_CCALL(debug_fn_info, return js_debugger_fn_info(js, argv[0]))
|
||||
JSC_CCALL(debug_backtrace_fns, return js_debugger_backtrace_fns(js,NULL))
|
||||
JSC_CCALL(debug_dump_obj, return js_dump_value(js, argv[0]))
|
||||
|
||||
#include "blob.h"
|
||||
|
||||
void dump_writer(blob *b, const char *buf, size_t len)
|
||||
{
|
||||
blob_write_bytes(b, buf, len);
|
||||
}
|
||||
|
||||
JSC_CCALL(debug_dump,
|
||||
JSPrintValueOptions opt = {0};
|
||||
opt.show_hidden=1;
|
||||
blob *write = blob_new(8*100);
|
||||
JS_PrintValue(js, dump_writer, write, argv[0], &opt);
|
||||
int bytes = write->bit_length/8;
|
||||
ret = JS_NewStringLen(js, write->data, bytes);
|
||||
blob_destroy(write);
|
||||
)
|
||||
|
||||
static const JSCFunctionListEntry js_debug_funcs[] = {
|
||||
MIST_FUNC_DEF(debug, stack_depth, 0),
|
||||
@@ -19,7 +33,7 @@ static const JSCFunctionListEntry js_debug_funcs[] = {
|
||||
MIST_FUNC_DEF(debug, local_vars, 1),
|
||||
MIST_FUNC_DEF(debug, fn_info, 1),
|
||||
MIST_FUNC_DEF(debug, backtrace_fns,0),
|
||||
MIST_FUNC_DEF(debug, dump_obj, 1),
|
||||
MIST_FUNC_DEF(debug, dump, 1),
|
||||
};
|
||||
|
||||
JSValue js_debug_use(JSContext *js) {
|
||||
|
||||
@@ -542,17 +542,6 @@ JSValue js_enet_use(JSContext *ctx)
|
||||
JS_SetPropertyFunctionList(ctx, peer_proto, js_enet_peer_funcs, countof(js_enet_peer_funcs));
|
||||
JS_SetClassProto(ctx, enet_peer_class_id, peer_proto);
|
||||
|
||||
JSValue global = JS_GetGlobalObject(ctx);
|
||||
JSValue prosp = JS_GetPropertyStr(ctx, global, "prosperon");
|
||||
JSValue c_types = JS_GetPropertyStr(ctx, prosp, "c_types");
|
||||
|
||||
JS_SetPropertyStr(ctx, c_types, "enet_host", JS_DupValue(ctx, host_proto));
|
||||
JS_SetPropertyStr(ctx, c_types, "enet_peer", JS_DupValue(ctx, peer_proto));
|
||||
|
||||
JS_FreeValue(ctx, c_types);
|
||||
JS_FreeValue(ctx, prosp);
|
||||
JS_FreeValue(ctx, global);
|
||||
|
||||
JSValue export_obj = JS_NewObject(ctx);
|
||||
JS_SetPropertyFunctionList(ctx, export_obj, js_enet_funcs, countof(js_enet_funcs));
|
||||
return export_obj;
|
||||
|
||||
@@ -580,7 +580,7 @@ static JSValue js_fetch_start(JSContext *ctx, JSValueConst this_val, int argc, J
|
||||
}
|
||||
|
||||
// Create JS object to represent the connection
|
||||
result = JS_NewObjectClass(ctx, JS_CLASS_OBJECT);
|
||||
result = JS_NewObject(ctx);
|
||||
JS_SetOpaque(result, conn);
|
||||
|
||||
// Add properties
|
||||
|
||||
184
source/qjs_js.c
184
source/qjs_js.c
@@ -1,87 +1,42 @@
|
||||
#include "qjs_js.h"
|
||||
#include "qjs_macros.h"
|
||||
#include "jsffi.h"
|
||||
#include "cell.h"
|
||||
#include <string.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
// Function implementations
|
||||
|
||||
JSC_CCALL(os_dump_atoms,
|
||||
return js_dump_atoms(js);
|
||||
)
|
||||
|
||||
JSC_CCALL(os_dump_shapes,
|
||||
return js_dump_shapes(js);
|
||||
)
|
||||
|
||||
JSC_CCALL(js_dump_class, return js_get_object_class_distribution(js))
|
||||
JSC_CCALL(js_dump_type_overheads, return js_get_object_type_overheads(js))
|
||||
JSC_CCALL(js_dump_objects, return js_dump_objects(js))
|
||||
|
||||
void cycle_hook_call(JSContext *js, JSValue v)
|
||||
{
|
||||
cell_rt *rt = JS_GetContextOpaque(js);
|
||||
JS_FreeValue(js,JS_Call(js, rt->cycle_fn,JS_UNDEFINED,1,&v));
|
||||
}
|
||||
|
||||
JSC_CCALL(js_cycle_hook,
|
||||
if (JS_IsUndefined(argv[0]))
|
||||
js_debug_sethook(js,NULL,JS_HOOK_CYCLE);
|
||||
else {
|
||||
cell_rt *rt = JS_GetContextOpaque(js);
|
||||
JS_FreeValue(js,rt->cycle_fn);
|
||||
rt->cycle_fn = JS_DupValue(js,argv[0]);
|
||||
js_debug_sethook(js,cycle_hook_call, JS_HOOK_CYCLE);
|
||||
}
|
||||
)
|
||||
|
||||
JSC_CCALL(js_stack_info, return js_dump_stack_info(js))
|
||||
|
||||
JSC_CCALL(os_mem, return js_get_memory_usage(js))
|
||||
|
||||
#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_memstate,
|
||||
JSMemoryUsage jsmem;
|
||||
JS_FillMemoryState(JS_GetRuntime(js), &jsmem);
|
||||
ret = JS_NewObject(js);
|
||||
JSJMEMRET(malloc_size)
|
||||
JSJMEMRET(malloc_limit)
|
||||
JSJMEMRET(memory_used_size)
|
||||
JSJMEMRET(gc_threshold)
|
||||
JSJMEMRET(malloc_count)
|
||||
JSJMEMRET(memory_used_count)
|
||||
JSJMEMRET(atom_count)
|
||||
JSJMEMRET(atom_size)
|
||||
JSJMEMRET(str_count)
|
||||
JSJMEMRET(str_size)
|
||||
JSJMEMRET(obj_count)
|
||||
JSJMEMRET(obj_size)
|
||||
JSJMEMRET(prop_count)
|
||||
JSJMEMRET(prop_size)
|
||||
JSJMEMRET(shape_count)
|
||||
JSJMEMRET(shape_size)
|
||||
JSJMEMRET(js_func_count)
|
||||
JSJMEMRET(js_func_size)
|
||||
JSJMEMRET(js_func_code_size)
|
||||
JSJMEMRET(js_func_pc2line_count)
|
||||
JSJMEMRET(js_func_pc2line_size)
|
||||
JSJMEMRET(c_func_count)
|
||||
JSJMEMRET(array_count)
|
||||
JSJMEMRET(fast_array_count)
|
||||
JSJMEMRET(fast_array_elements)
|
||||
JSJMEMRET(binary_object_count)
|
||||
JSJMEMRET(binary_object_size)
|
||||
)
|
||||
|
||||
JSC_CCALL(os_gc, JS_RunGC(JS_GetRuntime(js)) )
|
||||
JSC_CCALL(os_mem_limit, JS_SetMemoryLimit(JS_GetRuntime(js), js2number(js,argv[0])))
|
||||
JSC_CCALL(os_gc_threshold, JS_SetGCThreshold(JS_GetRuntime(js), js2number(js,argv[0])))
|
||||
JSC_CCALL(os_max_stacksize, JS_SetMaxStackSize(JS_GetRuntime(js), js2number(js,argv[0])))
|
||||
|
||||
JSC_CCALL(os_calc_mem,
|
||||
JSMemoryUsage mu;
|
||||
JS_ComputeMemoryUsage(JS_GetRuntime(js),&mu);
|
||||
ret = JS_NewObject(js);
|
||||
JS_SetPropertyStr(js,ret,"malloc_size",number2js(js,mu.malloc_size));
|
||||
JS_SetPropertyStr(js,ret,"malloc_limit",number2js(js,mu.malloc_limit));
|
||||
JS_SetPropertyStr(js,ret,"memory_used_size",number2js(js,mu.memory_used_size));
|
||||
JS_SetPropertyStr(js,ret,"malloc_count",number2js(js,mu.malloc_count));
|
||||
JS_SetPropertyStr(js,ret,"memory_used_count",number2js(js,mu.memory_used_count));
|
||||
JS_SetPropertyStr(js,ret,"atom_count",number2js(js,mu.atom_count));
|
||||
JS_SetPropertyStr(js,ret,"atom_size",number2js(js,mu.atom_size));
|
||||
JS_SetPropertyStr(js,ret,"str_count",number2js(js,mu.str_count));
|
||||
JS_SetPropertyStr(js,ret,"str_size",number2js(js,mu.str_size));
|
||||
JS_SetPropertyStr(js,ret,"obj_count",number2js(js,mu.obj_count));
|
||||
JS_SetPropertyStr(js,ret,"obj_size",number2js(js,mu.obj_size));
|
||||
JS_SetPropertyStr(js,ret,"prop_count",number2js(js,mu.prop_count));
|
||||
JS_SetPropertyStr(js,ret,"prop_size",number2js(js,mu.prop_size));
|
||||
JS_SetPropertyStr(js,ret,"shape_count",number2js(js,mu.shape_count));
|
||||
JS_SetPropertyStr(js,ret,"shape_size",number2js(js,mu.shape_size));
|
||||
JS_SetPropertyStr(js,ret,"js_func_count",number2js(js,mu.js_func_count));
|
||||
JS_SetPropertyStr(js,ret,"js_func_size",number2js(js,mu.js_func_size));
|
||||
JS_SetPropertyStr(js,ret,"js_func_code_size",number2js(js,mu.js_func_code_size));
|
||||
JS_SetPropertyStr(js,ret,"js_func_pc2line_count",number2js(js,mu.js_func_pc2line_count));
|
||||
JS_SetPropertyStr(js,ret,"js_func_pc2line_size",number2js(js,mu.js_func_pc2line_size));
|
||||
JS_SetPropertyStr(js,ret,"c_func_count",number2js(js,mu.c_func_count));
|
||||
JS_SetPropertyStr(js,ret,"array_count",number2js(js,mu.array_count));
|
||||
JS_SetPropertyStr(js,ret,"fast_array_count",number2js(js,mu.fast_array_count));
|
||||
JS_SetPropertyStr(js,ret,"fast_array_elements",number2js(js,mu.fast_array_elements));
|
||||
JS_SetPropertyStr(js,ret,"binary_object_count",number2js(js,mu.binary_object_count));
|
||||
JS_SetPropertyStr(js,ret,"binary_object_size",number2js(js,mu.binary_object_size));
|
||||
)
|
||||
|
||||
JSC_SSCALL(os_eval,
|
||||
ret = JS_Eval(js,str2,strlen(str2),str, JS_EVAL_FLAG_STRICT);
|
||||
@@ -116,86 +71,17 @@ JSC_CCALL(js_compile_unblob,
|
||||
return JS_ReadObject(js, data, size, JS_READ_OBJ_BYTECODE);
|
||||
)
|
||||
|
||||
JSC_CCALL(os_mem_limit, JS_SetMemoryLimit(JS_GetRuntime(js), js2number(js,argv[0])))
|
||||
|
||||
JSC_CCALL(os_gc_threshold, JS_SetGCThreshold(JS_GetRuntime(js), js2number(js,argv[0])))
|
||||
|
||||
JSC_CCALL(os_max_stacksize, JS_SetMaxStackSize(JS_GetRuntime(js), js2number(js,argv[0])))
|
||||
JSC_CCALL(os_rt_info, return JS_GetRTInfo(JS_GetRuntime(js),js))
|
||||
|
||||
JSC_CCALL(os_calc_mem,
|
||||
JSMemoryUsage mu;
|
||||
JS_ComputeMemoryUsage(JS_GetRuntime(js),&mu);
|
||||
ret = JS_NewObject(js);
|
||||
JS_SetPropertyStr(js,ret,"malloc_size",number2js(js,mu.malloc_size));
|
||||
JS_SetPropertyStr(js,ret,"malloc_limit",number2js(js,mu.malloc_limit));
|
||||
JS_SetPropertyStr(js,ret,"memory_used_size",number2js(js,mu.memory_used_size));
|
||||
JS_SetPropertyStr(js,ret,"malloc_count",number2js(js,mu.malloc_count));
|
||||
JS_SetPropertyStr(js,ret,"memory_used_count",number2js(js,mu.memory_used_count));
|
||||
JS_SetPropertyStr(js,ret,"atom_count",number2js(js,mu.atom_count));
|
||||
JS_SetPropertyStr(js,ret,"atom_size",number2js(js,mu.atom_size));
|
||||
JS_SetPropertyStr(js,ret,"str_count",number2js(js,mu.str_count));
|
||||
JS_SetPropertyStr(js,ret,"str_size",number2js(js,mu.str_size));
|
||||
JS_SetPropertyStr(js,ret,"obj_count",number2js(js,mu.obj_count));
|
||||
JS_SetPropertyStr(js,ret,"obj_size",number2js(js,mu.obj_size));
|
||||
JS_SetPropertyStr(js,ret,"prop_count",number2js(js,mu.prop_count));
|
||||
JS_SetPropertyStr(js,ret,"prop_size",number2js(js,mu.prop_size));
|
||||
JS_SetPropertyStr(js,ret,"shape_count",number2js(js,mu.shape_count));
|
||||
JS_SetPropertyStr(js,ret,"shape_size",number2js(js,mu.shape_size));
|
||||
JS_SetPropertyStr(js,ret,"js_func_count",number2js(js,mu.js_func_count));
|
||||
JS_SetPropertyStr(js,ret,"js_func_size",number2js(js,mu.js_func_size));
|
||||
JS_SetPropertyStr(js,ret,"js_func_code_size",number2js(js,mu.js_func_code_size));
|
||||
JS_SetPropertyStr(js,ret,"js_func_pc2line_count",number2js(js,mu.js_func_pc2line_count));
|
||||
JS_SetPropertyStr(js,ret,"js_func_pc2line_size",number2js(js,mu.js_func_pc2line_size));
|
||||
JS_SetPropertyStr(js,ret,"c_func_count",number2js(js,mu.c_func_count));
|
||||
JS_SetPropertyStr(js,ret,"array_count",number2js(js,mu.array_count));
|
||||
JS_SetPropertyStr(js,ret,"fast_array_count",number2js(js,mu.fast_array_count));
|
||||
JS_SetPropertyStr(js,ret,"fast_array_elements",number2js(js,mu.fast_array_elements));
|
||||
JS_SetPropertyStr(js,ret,"binary_object_count",number2js(js,mu.binary_object_count));
|
||||
JS_SetPropertyStr(js,ret,"binary_object_size",number2js(js,mu.binary_object_size));
|
||||
)
|
||||
|
||||
/*
|
||||
JSC_CCALL(os_memstate,
|
||||
#ifdef _WIN32
|
||||
MEMORYSTATUSEX statex;
|
||||
statex.dwLength = sizeof (statex);
|
||||
GlobalMemoryStatusEx (&statex);
|
||||
ret = JS_NewObject(js);
|
||||
JS_SetPropertyStr(js,ret,"load",number2js(js,statex.dwMemoryLoad));
|
||||
JS_SetPropertyStr(js,ret,"physical",number2js(js,statex.ullTotalPhys));
|
||||
JS_SetPropertyStr(js,ret,"availphysical",number2js(js,statex.ullAvailPhys));
|
||||
JS_SetPropertyStr(js,ret,"pagefile",number2js(js,statex.ullTotalPageFile));
|
||||
JS_SetPropertyStr(js,ret,"availpagefile",number2js(js,statex.ullAvailPageFile));
|
||||
JS_SetPropertyStr(js,ret,"virtual",number2js(js,statex.ullTotalVirtual));
|
||||
JS_SetPropertyStr(js,ret,"availvirtual",number2js(js,statex.ullAvailVirtual));
|
||||
JS_SetPropertyStr(js,ret,"availextended",number2js(js,statex.ullAvailExtendedVirtual));
|
||||
#else
|
||||
ret = JS_NewObject(js);
|
||||
#endif
|
||||
)*/
|
||||
|
||||
static const JSCFunctionListEntry js_js_funcs[] = {
|
||||
MIST_FUNC_DEF(js, cycle_hook,1),
|
||||
MIST_FUNC_DEF(os, dump_shapes, 0),
|
||||
MIST_FUNC_DEF(os, dump_atoms,0),
|
||||
MIST_FUNC_DEF(js, dump_class, 0),
|
||||
MIST_FUNC_DEF(js, dump_objects, 0),
|
||||
MIST_FUNC_DEF(js, dump_type_overheads, 0),
|
||||
MIST_FUNC_DEF(js, stack_info, 0),
|
||||
MIST_FUNC_DEF(os, calc_mem, 0),
|
||||
MIST_FUNC_DEF(os, mem, 0),
|
||||
MIST_FUNC_DEF(os, mem_limit, 1),
|
||||
MIST_FUNC_DEF(os, gc_threshold, 1),
|
||||
MIST_FUNC_DEF(os, max_stacksize, 1),
|
||||
MIST_FUNC_DEF(os, memstate, 0),
|
||||
MIST_FUNC_DEF(os, gc, 0),
|
||||
MIST_FUNC_DEF(os, eval, 2),
|
||||
MIST_FUNC_DEF(js, compile, 2),
|
||||
MIST_FUNC_DEF(js, eval_compile, 1),
|
||||
MIST_FUNC_DEF(js, compile_blob, 1),
|
||||
MIST_FUNC_DEF(js, compile_unblob, 1),
|
||||
MIST_FUNC_DEF(os, rt_info, 0),
|
||||
};
|
||||
|
||||
JSValue js_js_use(JSContext *js) {
|
||||
|
||||
@@ -73,16 +73,6 @@ JSValue js_##ID##_set_##ENTRY (JS_SETSIG) { \
|
||||
}\
|
||||
JSValue js_##ID##_get_##ENTRY (JSContext *js, JSValue self) { return JS_DupValue(js, js2##ID (js, self)->ENTRY); } \
|
||||
|
||||
#define JSC_GETSET_GLOBAL(ENTRY, TYPE) \
|
||||
JSValue js_global_set_##ENTRY (JS_SETSIG) { \
|
||||
ENTRY = js2##TYPE (val); \
|
||||
return JS_UNDEFINED; \
|
||||
} \
|
||||
\
|
||||
JSValue js_global_get_##ENTRY (JSContext *js, JSValue self) { \
|
||||
return TYPE##2js(ENTRY); \
|
||||
} \
|
||||
|
||||
#define JSC_GET(ID, ENTRY, TYPE) \
|
||||
JSValue js_##ID##_get_##ENTRY (JSContext *js, JSValue self) { \
|
||||
return TYPE##2js(js,js2##ID (js, self)->ENTRY); } \
|
||||
|
||||
@@ -152,11 +152,6 @@ static const JSCFunctionListEntry js_input_funcs[] = {
|
||||
JSValue js_input_use(JSContext *js) {
|
||||
JSValue mod = JS_NewObject(js);
|
||||
JS_SetPropertyFunctionList(js,mod,js_input_funcs,countof(js_input_funcs));
|
||||
|
||||
// Initialize SDL cursor class (no functions)
|
||||
JSValue c_types = JS_GetPropertyStr(js, JS_GetGlobalObject(js), "c_types");
|
||||
JS_FreeValue(js, c_types);
|
||||
|
||||
return mod;
|
||||
}
|
||||
|
||||
@@ -493,12 +488,7 @@ JSValue js_camera_use(JSContext *js) {
|
||||
SDL_Init(SDL_INIT_CAMERA);
|
||||
JSValue mod = JS_NewObject(js);
|
||||
JS_SetPropertyFunctionList(js,mod,js_camera_funcs,countof(js_camera_funcs));
|
||||
|
||||
// Initialize SDL camera class with functions
|
||||
JSValue c_types = JS_GetPropertyStr(js, JS_GetGlobalObject(js), "c_types");
|
||||
QJSCLASSPREP_FUNCS(SDL_Camera)
|
||||
JS_FreeValue(js, c_types);
|
||||
|
||||
return mod;
|
||||
}
|
||||
|
||||
|
||||
@@ -5,16 +5,8 @@
|
||||
#include <SDL3/SDL_gpu.h>
|
||||
#include <SDL3/SDL_surface.h>
|
||||
#include <string.h>
|
||||
|
||||
// Helper functions from jsffi.c that need to be declared
|
||||
extern JSValue number2js(JSContext *js, double g);
|
||||
extern double js2number(JSContext *js, JSValue v);
|
||||
extern rect js2rect(JSContext *js, JSValue v);
|
||||
extern irect js2irect(JSContext *js, JSValue v);
|
||||
extern colorf js2color(JSContext *js, JSValue v);
|
||||
extern HMM_Vec2 js2vec2(JSContext *js, JSValue v);
|
||||
extern SDL_PixelFormat str2pixelformat(const char *str);
|
||||
extern const char *pixelformat2str(SDL_PixelFormat fmt);
|
||||
#include "qjs_sdl.h"
|
||||
#include "qjs_common.h"
|
||||
|
||||
JSValue pixelformat2js(JSContext *js, SDL_PixelFormat fmt)
|
||||
{
|
||||
|
||||
@@ -1747,8 +1747,9 @@ JSC_CCALL(sdl_createWindowAndRenderer,
|
||||
// Hook function to set up endowments for the video actor
|
||||
static void video_actor_hook(JSContext *js) {
|
||||
// Get prosperon object
|
||||
JSValue prosperon = JS_GetPropertyStr(js, JS_GetGlobalObject(js), "prosperon");
|
||||
JSValue c_types = JS_GetPropertyStr(js, prosperon, "c_types");
|
||||
JSValue global = JS_GetGlobalObject(js);
|
||||
JSValue prosperon = JS_GetPropertyStr(js, global, "prosperon");
|
||||
JS_FreeValue(js,global);
|
||||
|
||||
// Initialize classes
|
||||
QJSCLASSPREP_FUNCS(SDL_Window)
|
||||
@@ -1756,8 +1757,6 @@ static void video_actor_hook(JSContext *js) {
|
||||
QJSCLASSPREP_FUNCS(SDL_Texture)
|
||||
QJSCLASSPREP_NO_FUNCS(SDL_Cursor)
|
||||
|
||||
JS_FreeValue(js, c_types);
|
||||
|
||||
// Create window constructor
|
||||
JSValue window_ctor = JS_NewCFunction2(js, js_window_constructor, "window", 1, JS_CFUNC_constructor, 0);
|
||||
|
||||
|
||||
@@ -7,18 +7,14 @@
|
||||
// qjs -m test_blob.js
|
||||
//
|
||||
|
||||
var tester = arg[0]
|
||||
|
||||
// Attempt to "use" the blob module as if it was installed or compiled in.
|
||||
var Blob = use('blob')
|
||||
|
||||
// If you're testing in an environment without a 'use' loader, you might do
|
||||
// something like importing the compiled C module or linking it differently.
|
||||
|
||||
// (Optional) if you have an 'os' module available for controlling exit codes:
|
||||
var os = undefined;
|
||||
try {
|
||||
os = use('os');
|
||||
} catch (e) {
|
||||
// If there's no 'os' module, ignore
|
||||
}
|
||||
|
||||
// A small tolerance for floating comparisons if needed
|
||||
|
||||
3
tests/couple.ce
Normal file
3
tests/couple.ce
Normal file
@@ -0,0 +1,3 @@
|
||||
$_.start(e => {
|
||||
$_.couple(e.actor)
|
||||
}, "delay")
|
||||
1
tests/disrupt.ce
Normal file
1
tests/disrupt.ce
Normal file
@@ -0,0 +1 @@
|
||||
throw 1
|
||||
1
tests/echo.ce
Normal file
1
tests/echo.ce
Normal file
@@ -0,0 +1 @@
|
||||
|
||||
2
tests/stop.ce
Normal file
2
tests/stop.ce
Normal file
@@ -0,0 +1,2 @@
|
||||
$_.delay($_.stop, 0.1)
|
||||
$_.stop()
|
||||
Reference in New Issue
Block a user