diff --git a/scripts/core/engine.js b/scripts/core/engine.js index 07b13a99..8f69554c 100644 --- a/scripts/core/engine.js +++ b/scripts/core/engine.js @@ -129,7 +129,9 @@ function bare_load(file) { var res_cache = {} function console_rec(category, priority, line, file, msg) { - return `[${prosperon.id.substring(0,6)}] ${file}:${line}: [${category} ${priority}]: ${msg}\n` + var now = time.now() + + return `[${prosperon.id.substring(0,6)}] [${time.text(now, "mb d yyyy h:nn:ss")}] ${file}:${line}: [${category} ${priority}]: ${msg}\n` } io.mkdir('.prosperon') @@ -276,6 +278,7 @@ globalThis.use = function use(file) { } globalThis.json = use('json') +var time = use('time') function parse_file(content, file) { if (!content) return {} @@ -668,6 +671,7 @@ $_.start = function(cb, prg, arg) "spawn", "--overling", host.port, "--id", id, + "--overlingid", prosperon.id ] if (prg) @@ -675,6 +679,8 @@ $_.start = function(cb, prg, arg) if (arg) argv = argv.concat(cmd.encode(arg)) + + underlings.add(id) os.createprocess(argv) } @@ -690,8 +696,11 @@ $_.stop = function(actor) { if (!actor) destroyself() + + if (!underlings.has(actor.id)) + throw new Error('Can only call stop on an underling or self.') - actor_send(actor, {type:"stop"}) + actor_send(actor, {type:"stop", id: prosperon.id}) } $_.stop[prosperon.DOC] = `The stop function stops an underling.` @@ -718,11 +727,12 @@ var couplings = new Set() $_.couple = function(actor) { + console.log(`coupled to ${actor.id}`) couplings.add(actor.id) } $_.couple[prosperon.DOC] = `causes this actor to stop when another actor stops.` -// Shuffles the message to the actor with whatever means available +// Shuffsles the message to the actor with whatever means available function actor_send(actor, message) { if (typeof message !== 'object') @@ -733,11 +743,18 @@ function actor_send(actor, message) return } - console.log(`Getting peer for ${actor.id}`) var peer = peers[actor.id] - if (!peer) throw new Error(`Could not send message to actor.`) - console.log(`sending message ${json.encode(message)} to ${json.encode(actor)}`) - peer.send(message) + if (peer) { + peer.send(message) + return + } + + try { + os.mailbox_push(actor.id, message) + } catch(e) { + } + + throw new Error (`Unable to send message to actor ${json.encode(actor)}`) } // Map of reply IDs to functions @@ -763,14 +780,13 @@ $_.send = function(actor, message, reply) console.log(`replycc and reply are ${actor[REPLYCC]} and ${actor[REPLY]}`) actor.id = actor[REPLYCC] send.return = actor[REPLY] - } else if (peers[actor.id]) { - } else - throw new Error(`Could not send message to actor.`) + } if (reply) { var id = util.guid() replies[id] = reply send.reply = id + send.id = prosperon.id } actor_send(actor, send) @@ -786,6 +802,9 @@ if (!prosperon.args.id) prosperon.id = util.guid() else prosperon.id = prosperon.args.id; + +if (prosperon.args.overlingid) + overling = { id: prosperon.args.overlingid } // now can start the mailbox os.mailbox_start(prosperon.id); @@ -800,72 +819,81 @@ var unneeded_timer = $_.delay($_.stop, ar) function destroyself() { - console.log('got the message to destroy') + if (overling) + actor_send(overling, { type: "stopped" , id: prosperon.id}) + + host.flush() os.exit(0) } function handle_actor_disconnect(id) { + var greeter = greeters[id] + if (greeter) { + greeter({ + type: "stopped" + }) + // Greeter can now be removed + delete greeters[id] + } + + console.log(`actor ${id} disconnected`) + if (couplings.has(id)) $_.stop() delete peers[id] - delete greeters[id] } -function handle_message(e) -{ - console.log(`handling message ${json.encode(e)}`) - switch (e.data.type) { - case "user": - if (e.data.return) { - console.log(`Message has a return address.`) - var fn = replies[e.data.return] - if (!fn) - throw new Error(`Could not find return function for message ${e.data.return}`) +/* + msg format is: + id: id of the actor that sent the message + reply: reply id for a response +*/ - fn(e.data) - delete replies[e.data.return] +function handle_message(msg) +{ + switch (msg.type) { + case "user": + if (msg.return) { + console.log(`Message has a return address.`) + var fn = replies[msg.return] + if (!fn) + throw new Error(`Could not find return function for message ${msg.return}`) + + fn(msg) + delete replies[msg.return] return } if (receive_fn) { - if (e.data.reply) { - // Doing this here because there is no way for an actor to reply to the message if it doesn't get it in the first place - e.data.data[REPLYCC] = peer2id.get(e.peer) - e.data.data[REPLY] = e.data.reply - console.log(`set replycc and reply to ${e.data.data[REPLYCC]} and ${e.data.data[REPLY]}`) + if (msg.reply) { + msg.data[REPLY] = msg.reply + msg.data[REPLYCC] = msg.id } - receive_fn(e.data.data) + receive_fn(msg.data) } break - case "greet": - peers[e.data.id] = e.peer; - peer2id.set(e.peer, e.data.id); - console.log(`Registered a peer with ${e.data.id}`) - var greeter = greeters[e.data.id] - if (!greeter) return; //throw new Error(`No greeter registered for greet message id ${e.data.id}`) - greeter({ - type: "actor_started", - actor: { id: e.data.id } - }) - break - case "stop": + if (msg.id !== overling.id) + throw new Error(`Got a message from an actor ${msg.id} to stop, that was not our overling (${overling.id}).`); destroyself() break case "contact": - if (pppfn) pppfn(e.data.data) + if (pppfn) pppfn(msg.data) + break + + case "stopped": + handle_actor_disconnect(msg.id) break } } function handle_connect(e) { - console.log(`message arrived at ${host.address}:${host.port} from somebody ... ${e.peer.address}:${e.peer.port}`) var contact = peer2contact.get(e.peer) if (contact) { // We have successfully made contact. now send the request. @@ -878,19 +906,11 @@ function handle_connect(e) } // For a local greet - e.peer.send({ - type:"greet", - id: prosperon.id - }) + e.peer.send({ id: prosperon.id }) } var hang = 0.001 while (1) { - os.waitevent(e => { - unneeded_timer() - unneeded_timer = $_.delay(unneeded_fn, unneeded_time) - }, hang) - host.service(e => { unneeded_timer() switch(e.type) { @@ -899,14 +919,24 @@ while (1) { break; case "receive": - handle_message(e) + if (e.data.id && !peers[e.data.id]) { + // we can hook them up + peers[e.data.id] = e.peer + peer2id.set(e.peer, e.data.id) + // first time they've been seen; if it has a system callback, run it now + var greeter = greeters[e.data.id] + if (greeter) + greeter({ + type: "actor_started", + actor: { id: e.data.id } + }) + } + handle_message(e.data) break; case "disconnect": var id = peer2id.get(e.peer) - greeters[id]({ - type: "actor_stopped" - }); + if (!id) throw new Error('A peer disconnected but we had no ID associated with it.') handle_actor_disconnect(id); break; } @@ -915,6 +945,10 @@ while (1) { if (portal) portal.service(portal_fn, hang) + + os.mailbox_service(prosperon.id, handle_message) } + + })() diff --git a/scripts/modules/time.js b/scripts/modules/time.js index 7dab82a5..4b7c24ff 100644 --- a/scripts/modules/time.js +++ b/scripts/modules/time.js @@ -187,7 +187,7 @@ time.text = function(num, fmt = this.fmt, zone) { fmt = fmt.replaceAll("h", rec.hour); fmt = fmt.replaceAll("nn", rec.minute.toString().padStart(2, "0")); fmt = fmt.replaceAll("n", rec.minute); - fmt = fmt.replaceAll("ss", rec.second.toString().padStart(2, "0")); + fmt = fmt.replaceAll("ss", rec.second.toFixed(2).padStart(2, "0")); fmt = fmt.replaceAll("s", rec.second); fmt = fmt.replaceAll("z", zone >= 0 ? "+" + zone : zone); fmt = fmt.replaceAll(/mm[^bB]/g, rec.month + 1); diff --git a/source/jsffi.c b/source/jsffi.c index 1397c371..f6671312 100644 --- a/source/jsffi.c +++ b/source/jsffi.c @@ -28,6 +28,14 @@ #include "cgltf.h" #include "physfs.h" + +#include "qjs_dmon.h" +#include "qjs_nota.h" +#include "qjs_wota.h" +#include "qjs_enet.h" +#include "qjs_soloud.h" +#include "qjs_qr.h" + void gui_input(SDL_Event *e); #ifdef _WIN32 @@ -57,6 +65,9 @@ typedef struct rtree rtree; #include #include +#define JS_SetProperty(js, tar, str, val) JS_SetPropertyStr(js, tar, #str, val) +#define JS_GetProperty(js, tar, atom) JS_GetPropertyStr(js, tar, #atom) + int randombytes(void *buf, size_t n); static Uint32 timer_cb_event; @@ -127,101 +138,6 @@ double genRand(MTRand* rand) { return((double)genRandLong(rand) / (uint32_t)0xffffffff); } - -static JSAtom width_atom; -static JSAtom height_atom; -static JSAtom l_atom; -static JSAtom r_atom; -static JSAtom t_atom; -static JSAtom b_atom; -static JSAtom x_atom; -static JSAtom y_atom; -static JSAtom anchor_x_atom; -static JSAtom anchor_y_atom; -static JSAtom pos_atom; -static JSAtom uv_atom; -static JSAtom color_atom; -static JSAtom indices_atom; -static JSAtom vertices_atom; -static JSAtom dst_atom; -static JSAtom src_atom; -static JSAtom count_atom; -static JSAtom num_indices_atom; -static JSAtom transform_atom; -static JSAtom image_atom; -static JSAtom layer_atom; -static JSAtom texture_atom; -static JSAtom parent_atom; - -// GPU ATOMS -static JSAtom cw_atom; -static JSAtom ccw_atom; -static JSAtom zero_atom; -static JSAtom one_atom; -static JSAtom add_atom; -static JSAtom sub_atom; -static JSAtom rev_sub_atom; -static JSAtom min_atom; -static JSAtom max_atom; -static JSAtom none_atom; -static JSAtom norm_atom; -static JSAtom front_atom; -static JSAtom back_atom; -static JSAtom never_atom; -static JSAtom less_atom; -static JSAtom equal_atom; -static JSAtom less_equal_atom; -static JSAtom greater_atom; -static JSAtom not_equal_atom; -static JSAtom greater_equal_atom; -static JSAtom always_atom; -static JSAtom keep_atom; -static JSAtom zero_stencil_atom; -static JSAtom replace_atom; -static JSAtom incr_clamp_atom; -static JSAtom decr_clamp_atom; -static JSAtom invert_atom; -static JSAtom incr_wrap_atom; -static JSAtom decr_wrap_atom; -static JSAtom point_atom; -static JSAtom line_atom; -static JSAtom linestrip_atom; -static JSAtom triangle_atom; -static JSAtom trianglestrip_atom; -static JSAtom src_color_atom; -static JSAtom one_minus_src_color_atom; -static JSAtom dst_color_atom; -static JSAtom one_minus_dst_color_atom; -static JSAtom src_alpha_atom; -static JSAtom one_minus_src_alpha_atom; -static JSAtom dst_alpha_atom; -static JSAtom one_minus_dst_alpha_atom; -static JSAtom constant_color_atom; -static JSAtom one_minus_constant_color_atom; -static JSAtom src_alpha_saturate_atom; -static JSAtom none_cull_atom; -static JSAtom front_cull_atom; -static JSAtom back_cull_atom; - -// For sampler filtering: -static JSAtom nearest_atom; -static JSAtom linear_atom; - -// For sampler mipmap modes: -static JSAtom mipmap_nearest_atom; -static JSAtom mipmap_linear_atom; - -// For sampler address modes: -static JSAtom repeat_atom; -static JSAtom mirror_atom; -static JSAtom clamp_edge_atom; -static JSAtom clamp_border_atom; - -static JSAtom vertex_atom; -static JSAtom index_atom; -static JSAtom indirect_atom; -static JSAtom rect_atom; - typedef struct texture_vertex { float x, y, z; float u, v; @@ -312,24 +228,20 @@ double js_getnum_str(JSContext *js, JSValue v, const char *str) return ret; } -double js_getnum(JSContext *js, JSValue v, JSAtom prop) -{ - JSValue val = JS_GetProperty(js,v,prop); - double ret = js2number(js,val); - JS_FreeValue(js,val); - return ret; -} - #define JS_GETPROP(JS, TARGET, VALUE, PROP, TYPE) {\ JSValue __##PROP##__v = JS_GetPropertyStr(JS,VALUE,#PROP); \ TARGET = js2##TYPE(JS, __##PROP##__v); \ JS_FreeValue(JS,__##PROP##__v); }\ #define JS_GETATOM(JS, TARGET, VALUE, ATOM, TYPE) {\ -JSValue __##PROP##__v = JS_GetProperty(JS,VALUE,ATOM); \ +JSValue __##PROP##__v = JS_GetPropertyStr(JS,VALUE,#ATOM); \ TARGET = js2##TYPE(JS, __##PROP##__v); \ JS_FreeValue(JS,__##PROP##__v); }\ +#define JS_SetProperty(js, target, atom, val) JS_SetPropertyStr(js, target, #atom, val) + +#define JS_SETATOM(JS, TARGET, ATOM, VALUE, TYPE) JS_SetProperty(JS, TARGET, #ATOM, TYPE##2js(JS, VALUE)); + int JS_GETBOOL(JSContext *js, JSValue v, const char *prop) { JSValue __v = JS_GetPropertyStr(js,v,prop); @@ -338,9 +250,9 @@ int JS_GETBOOL(JSContext *js, JSValue v, const char *prop) return r; } -JSValue js_getproperty(JSContext *js, JSValue v, JSAtom atom) +JSValue js_getproperty(JSContext *js, JSValue v, const char *prop) { - JSValue ret = JS_GetProperty(js, v, atom); + JSValue ret = JS_GetPropertyStr(js, v, prop); JS_FreeValue(js,ret); return ret; } @@ -390,7 +302,7 @@ typedef struct { static BufferCheckResult get_or_extend_buffer( JSContext *js, JSValue old_mesh, - JSAtom prop, + const char *prop, size_t needed_size, int type, int elements_per_item, @@ -1088,10 +1000,10 @@ typedef struct lrtb lrtb; lrtb js2lrtb(JSContext *js, JSValue v) { lrtb ret = {0}; - JS_GETATOM(js,ret.l,v,l_atom,number) - JS_GETATOM(js,ret.r,v,r_atom,number) - JS_GETATOM(js,ret.b,v,b_atom,number) - JS_GETATOM(js,ret.t,v,t_atom,number) + JS_GETATOM(js,ret.l,v,l,number) + JS_GETATOM(js,ret.r,v,r,number) + JS_GETATOM(js,ret.b,v,b,number) + JS_GETATOM(js,ret.t,v,t,number) return ret; } @@ -1203,8 +1115,8 @@ void SDL_Texture_free(JSRuntime *rt, SDL_Texture *t){ } QJSCLASS(SDL_Texture, - JS_SetProperty(js, j, width_atom, number2js(js,n->w)); - JS_SetProperty(js,j,height_atom,number2js(js,n->h)); + JS_SetPropertyStr(js, j, "width", number2js(js,n->w)); + JS_SetPropertyStr(js,j,"height",number2js(js,n->h)); ) QJSCLASS(SDL_Surface, @@ -1481,12 +1393,13 @@ JSValue vecarr2js(JSContext *js,HMM_Vec2 *points, int n) { rect js2rect(JSContext *js,JSValue v) { if (JS_IsUndefined(v)) return (rect){0,0,1,1}; rect rect; - JS_GETATOM(js,rect.x,v,x_atom,number) - JS_GETATOM(js,rect.y,v,y_atom,number) - JS_GETATOM(js,rect.w,v,width_atom,number) - JS_GETATOM(js,rect.h,v,height_atom,number) - float anchor_x = js_getnum(js,v, anchor_x_atom); - float anchor_y = js_getnum(js,v, anchor_y_atom); + JS_GETATOM(js,rect.x,v,x,number) + JS_GETATOM(js,rect.y,v,y,number) + JS_GETATOM(js,rect.w,v,width,number) + JS_GETATOM(js,rect.h,v,height,number) + float anchor_x, anchor_y; + JS_GETATOM(js, anchor_x, v, anchor_x, number) + JS_GETATOM(js, anchor_y, v, anchor_y, number) rect.y -= anchor_y*rect.h; rect.x -= anchor_x*rect.w; @@ -1517,10 +1430,10 @@ HMM_Vec2 transform_point(SDL_Renderer *ren, HMM_Vec2 in, HMM_Mat3 *t) JSValue rect2js(JSContext *js,rect rect) { JSValue obj = JS_NewObject(js); - JS_SetProperty(js, obj, x_atom, number2js(js,rect.x)); - JS_SetProperty(js, obj, y_atom, number2js(js,rect.y)); - JS_SetProperty(js, obj, width_atom, number2js(js,rect.w)); - JS_SetProperty(js, obj, height_atom, number2js(js,rect.h)); + JS_SETATOM(js, obj, x, rect.x, number); + JS_SETATOM(js, obj, y, rect.y, number); + JS_SETATOM(js, obj, width, rect.w, number); + JS_SETATOM(js, obj, height, rect.h, number); return obj; } @@ -1660,12 +1573,12 @@ JSValue quadbuffers_to_mesh(JSContext *js, struct quad_buffers buffers) JSValue jsidx = make_quad_indices_buffer(js, quads); JSValue ret = JS_NewObject(js); - JS_SetProperty(js, ret, pos_atom, jspos); - JS_SetProperty(js, ret, uv_atom, jsuv); - JS_SetProperty(js, ret, color_atom, jscolor); - JS_SetProperty(js, ret, indices_atom, jsidx); - JS_SetProperty(js, ret, vertices_atom, number2js(js, buffers.verts)); - JS_SetProperty(js,ret,num_indices_atom, number2js(js,count)); + JS_SetProperty(js, ret, pos, jspos); + JS_SetProperty(js, ret, uv, jsuv); + JS_SetProperty(js, ret, color, jscolor); + JS_SetProperty(js, ret, indices, jsidx); + JS_SetProperty(js, ret, vertices, number2js(js, buffers.verts)); + JS_SetProperty(js,ret,num_indices, number2js(js,count)); return ret; } @@ -1693,12 +1606,12 @@ JSValue quads_to_mesh(JSContext *js, text_vert *buffer) JSValue jsidx = make_quad_indices_buffer(js, quads); JSValue ret = JS_NewObject(js); - JS_SetProperty(js, ret, pos_atom, jspos); - JS_SetProperty(js, ret, uv_atom, jsuv); - JS_SetProperty(js, ret, color_atom, jscolor); - JS_SetProperty(js, ret, indices_atom, jsidx); - JS_SetProperty(js, ret, vertices_atom, number2js(js, verts)); - JS_SetProperty(js,ret,num_indices_atom, number2js(js,count)); + JS_SetProperty(js, ret, pos, jspos); + JS_SetProperty(js, ret, uv, jsuv); + JS_SetProperty(js, ret, color, jscolor); + JS_SetProperty(js, ret, indices, jsidx); + JS_SetProperty(js, ret, vertices, number2js(js, verts)); + JS_SetProperty(js,ret,num_indices, number2js(js,count)); return ret; } @@ -2561,6 +2474,9 @@ JS_FreeValue(js,v); \ } \ JSC_CCALL(os_engine_start, + if (global_window) + return JS_ThrowReferenceError(js, "The engine was already started."); + JSValue p = argv[0]; JS_SDL_PROP(js, p, SDL_PROP_APP_METADATA_NAME_STRING, name) JS_SDL_PROP(js, p, SDL_PROP_APP_METADATA_VERSION_STRING, version) @@ -2576,7 +2492,7 @@ JSC_CCALL(os_engine_start, const char *title; JS_GETPROP(js,title,argv[0],title,cstring) - SDL_Window *new = SDL_CreateWindow(title, js2number(js, js_getproperty(js,argv[0], width_atom)), js2number(js,js_getproperty(js,argv[0], height_atom)), SDL_WINDOW_RESIZABLE); + SDL_Window *new = SDL_CreateWindow(title, js2number(js, js_getproperty(js,argv[0], "width")), js2number(js,js_getproperty(js,argv[0], "height")), SDL_WINDOW_RESIZABLE); JS_FreeCString(js,title); @@ -2587,150 +2503,144 @@ JSC_CCALL(os_engine_start, return SDL_Window2js(js,new); ) -typedef struct { - SDL_EventType key; - JSAtom value; -} SDL_EventTypePair; +static JSAtom event_type_to_atom(JSContext *js, Uint32 event_type) { + switch(event_type) { + // Application events + case SDL_EVENT_QUIT: return JS_NewAtom(js, "quit"); + case SDL_EVENT_TERMINATING: return JS_NewAtom(js, "terminating"); + case SDL_EVENT_LOW_MEMORY: return JS_NewAtom(js, "low_memory"); + case SDL_EVENT_WILL_ENTER_BACKGROUND: return JS_NewAtom(js, "will_enter_background"); + case SDL_EVENT_DID_ENTER_BACKGROUND: return JS_NewAtom(js, "did_enter_background"); + case SDL_EVENT_WILL_ENTER_FOREGROUND: return JS_NewAtom(js, "will_enter_foreground"); + case SDL_EVENT_DID_ENTER_FOREGROUND: return JS_NewAtom(js, "did_enter_foreground"); + case SDL_EVENT_LOCALE_CHANGED: return JS_NewAtom(js, "locale_changed"); + case SDL_EVENT_SYSTEM_THEME_CHANGED: return JS_NewAtom(js, "system_theme_changed"); -struct {SDL_EventType key; JSAtom value; } *event_hash = NULL; + // Display events + case SDL_EVENT_DISPLAY_ORIENTATION: return JS_NewAtom(js, "display_orientation"); + case SDL_EVENT_DISPLAY_ADDED: return JS_NewAtom(js, "display_added"); + case SDL_EVENT_DISPLAY_REMOVED: return JS_NewAtom(js, "display_removed"); + case SDL_EVENT_DISPLAY_MOVED: return JS_NewAtom(js, "display_moved"); + case SDL_EVENT_DISPLAY_DESKTOP_MODE_CHANGED: return JS_NewAtom(js, "display_desktop_mode_changed"); + case SDL_EVENT_DISPLAY_CURRENT_MODE_CHANGED: return JS_NewAtom(js, "display_current_mode_changed"); + case SDL_EVENT_DISPLAY_CONTENT_SCALE_CHANGED: return JS_NewAtom(js, "display_content_scale_changed"); -void fill_event_atoms(JSContext *js) -{ - if (event_hash != NULL) return; + // Window events + case SDL_EVENT_WINDOW_SHOWN: return JS_NewAtom(js, "window_shown"); + case SDL_EVENT_WINDOW_HIDDEN: return JS_NewAtom(js, "window_hidden"); + case SDL_EVENT_WINDOW_EXPOSED: return JS_NewAtom(js, "window_exposed"); + case SDL_EVENT_WINDOW_MOVED: return JS_NewAtom(js, "window_moved"); + case SDL_EVENT_WINDOW_RESIZED: return JS_NewAtom(js, "window_resized"); + case SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED: return JS_NewAtom(js, "window_pixel_size_changed"); + case SDL_EVENT_WINDOW_METAL_VIEW_RESIZED: return JS_NewAtom(js, "window_metal_view_resized"); + case SDL_EVENT_WINDOW_MINIMIZED: return JS_NewAtom(js, "window_minimized"); + case SDL_EVENT_WINDOW_MAXIMIZED: return JS_NewAtom(js, "window_maximized"); + case SDL_EVENT_WINDOW_RESTORED: return JS_NewAtom(js, "window_restored"); + case SDL_EVENT_WINDOW_MOUSE_ENTER: return JS_NewAtom(js, "window_mouse_enter"); + case SDL_EVENT_WINDOW_MOUSE_LEAVE: return JS_NewAtom(js, "window_mouse_leave"); + case SDL_EVENT_WINDOW_FOCUS_GAINED: return JS_NewAtom(js, "window_focus_gained"); + case SDL_EVENT_WINDOW_FOCUS_LOST: return JS_NewAtom(js, "window_focus_lost"); + case SDL_EVENT_WINDOW_CLOSE_REQUESTED: return JS_NewAtom(js, "window_close_requested"); + case SDL_EVENT_WINDOW_HIT_TEST: return JS_NewAtom(js, "window_hit_test"); + case SDL_EVENT_WINDOW_ICCPROF_CHANGED: return JS_NewAtom(js, "window_iccprof_changed"); + case SDL_EVENT_WINDOW_DISPLAY_CHANGED: return JS_NewAtom(js, "window_display_changed"); + case SDL_EVENT_WINDOW_DISPLAY_SCALE_CHANGED: return JS_NewAtom(js, "window_display_scale_changed"); + case SDL_EVENT_WINDOW_SAFE_AREA_CHANGED: return JS_NewAtom(js, "window_safe_area_changed"); + case SDL_EVENT_WINDOW_OCCLUDED: return JS_NewAtom(js, "window_occluded"); + case SDL_EVENT_WINDOW_ENTER_FULLSCREEN: return JS_NewAtom(js, "window_enter_fullscreen"); + case SDL_EVENT_WINDOW_LEAVE_FULLSCREEN: return JS_NewAtom(js, "window_leave_fullscreen"); + case SDL_EVENT_WINDOW_DESTROYED: return JS_NewAtom(js, "window_destroyed"); + case SDL_EVENT_WINDOW_HDR_STATE_CHANGED: return JS_NewAtom(js, "window_hdr_state_changed"); - // Application events - hmput(event_hash, SDL_EVENT_QUIT, JS_NewAtom(js, "quit")); - hmput(event_hash, SDL_EVENT_TERMINATING, JS_NewAtom(js, "terminating")); - hmput(event_hash, SDL_EVENT_LOW_MEMORY, JS_NewAtom(js, "low_memory")); - hmput(event_hash, SDL_EVENT_WILL_ENTER_BACKGROUND, JS_NewAtom(js, "will_enter_background")); - hmput(event_hash, SDL_EVENT_DID_ENTER_BACKGROUND, JS_NewAtom(js, "did_enter_background")); - hmput(event_hash, SDL_EVENT_WILL_ENTER_FOREGROUND, JS_NewAtom(js, "will_enter_foreground")); - hmput(event_hash, SDL_EVENT_DID_ENTER_FOREGROUND, JS_NewAtom(js, "did_enter_foreground")); - hmput(event_hash, SDL_EVENT_LOCALE_CHANGED, JS_NewAtom(js, "locale_changed")); - hmput(event_hash, SDL_EVENT_SYSTEM_THEME_CHANGED, JS_NewAtom(js, "system_theme_changed")); + // Keyboard events + case SDL_EVENT_KEY_DOWN: return JS_NewAtom(js, "key_down"); + case SDL_EVENT_KEY_UP: return JS_NewAtom(js, "key_up"); + case SDL_EVENT_TEXT_EDITING: return JS_NewAtom(js, "text_editing"); + case SDL_EVENT_TEXT_INPUT: return JS_NewAtom(js, "text_input"); + case SDL_EVENT_KEYMAP_CHANGED: return JS_NewAtom(js, "keymap_changed"); + case SDL_EVENT_KEYBOARD_ADDED: return JS_NewAtom(js, "keyboard_added"); + case SDL_EVENT_KEYBOARD_REMOVED: return JS_NewAtom(js, "keyboard_removed"); + case SDL_EVENT_TEXT_EDITING_CANDIDATES: return JS_NewAtom(js, "text_editing_candidates"); - // Display events - hmput(event_hash, SDL_EVENT_DISPLAY_ORIENTATION, JS_NewAtom(js, "display_orientation")); - hmput(event_hash, SDL_EVENT_DISPLAY_ADDED, JS_NewAtom(js, "display_added")); - hmput(event_hash, SDL_EVENT_DISPLAY_REMOVED, JS_NewAtom(js, "display_removed")); - hmput(event_hash, SDL_EVENT_DISPLAY_MOVED, JS_NewAtom(js, "display_moved")); - hmput(event_hash, SDL_EVENT_DISPLAY_DESKTOP_MODE_CHANGED, JS_NewAtom(js, "display_desktop_mode_changed")); - hmput(event_hash, SDL_EVENT_DISPLAY_CURRENT_MODE_CHANGED, JS_NewAtom(js, "display_current_mode_changed")); - hmput(event_hash, SDL_EVENT_DISPLAY_CONTENT_SCALE_CHANGED, JS_NewAtom(js, "display_content_scale_changed")); + // Mouse events + case SDL_EVENT_MOUSE_MOTION: return JS_NewAtom(js, "mouse_motion"); + case SDL_EVENT_MOUSE_BUTTON_DOWN: return JS_NewAtom(js, "mouse_button_down"); + case SDL_EVENT_MOUSE_BUTTON_UP: return JS_NewAtom(js, "mouse_button_up"); + case SDL_EVENT_MOUSE_WHEEL: return JS_NewAtom(js, "mouse_wheel"); + case SDL_EVENT_MOUSE_ADDED: return JS_NewAtom(js, "mouse_added"); + case SDL_EVENT_MOUSE_REMOVED: return JS_NewAtom(js, "mouse_removed"); - // Window events - hmput(event_hash, SDL_EVENT_WINDOW_SHOWN, JS_NewAtom(js, "window_shown")); - hmput(event_hash, SDL_EVENT_WINDOW_HIDDEN, JS_NewAtom(js, "window_hidden")); - hmput(event_hash, SDL_EVENT_WINDOW_EXPOSED, JS_NewAtom(js, "window_exposed")); - hmput(event_hash, SDL_EVENT_WINDOW_MOVED, JS_NewAtom(js, "window_moved")); - hmput(event_hash, SDL_EVENT_WINDOW_RESIZED, JS_NewAtom(js, "window_resized")); - hmput(event_hash, SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED, JS_NewAtom(js, "window_pixel_size_changed")); - hmput(event_hash, SDL_EVENT_WINDOW_METAL_VIEW_RESIZED, JS_NewAtom(js, "window_metal_view_resized")); - hmput(event_hash, SDL_EVENT_WINDOW_MINIMIZED, JS_NewAtom(js, "window_minimized")); - hmput(event_hash, SDL_EVENT_WINDOW_MAXIMIZED, JS_NewAtom(js, "window_maximized")); - hmput(event_hash, SDL_EVENT_WINDOW_RESTORED, JS_NewAtom(js, "window_restored")); - hmput(event_hash, SDL_EVENT_WINDOW_MOUSE_ENTER, JS_NewAtom(js, "window_mouse_enter")); - hmput(event_hash, SDL_EVENT_WINDOW_MOUSE_LEAVE, JS_NewAtom(js, "window_mouse_leave")); - hmput(event_hash, SDL_EVENT_WINDOW_FOCUS_GAINED, JS_NewAtom(js, "window_focus_gained")); - hmput(event_hash, SDL_EVENT_WINDOW_FOCUS_LOST, JS_NewAtom(js, "window_focus_lost")); - hmput(event_hash, SDL_EVENT_WINDOW_CLOSE_REQUESTED, JS_NewAtom(js, "window_close_requested")); - hmput(event_hash, SDL_EVENT_WINDOW_HIT_TEST, JS_NewAtom(js, "window_hit_test")); - hmput(event_hash, SDL_EVENT_WINDOW_ICCPROF_CHANGED, JS_NewAtom(js, "window_iccprof_changed")); - hmput(event_hash, SDL_EVENT_WINDOW_DISPLAY_CHANGED, JS_NewAtom(js, "window_display_changed")); - hmput(event_hash, SDL_EVENT_WINDOW_DISPLAY_SCALE_CHANGED, JS_NewAtom(js, "window_display_scale_changed")); - hmput(event_hash, SDL_EVENT_WINDOW_SAFE_AREA_CHANGED, JS_NewAtom(js, "window_safe_area_changed")); - hmput(event_hash, SDL_EVENT_WINDOW_OCCLUDED, JS_NewAtom(js, "window_occluded")); - hmput(event_hash, SDL_EVENT_WINDOW_ENTER_FULLSCREEN, JS_NewAtom(js, "window_enter_fullscreen")); - hmput(event_hash, SDL_EVENT_WINDOW_LEAVE_FULLSCREEN, JS_NewAtom(js, "window_leave_fullscreen")); - hmput(event_hash, SDL_EVENT_WINDOW_DESTROYED, JS_NewAtom(js, "window_destroyed")); - hmput(event_hash, SDL_EVENT_WINDOW_HDR_STATE_CHANGED, JS_NewAtom(js, "window_hdr_state_changed")); + // Joystick events + case SDL_EVENT_JOYSTICK_AXIS_MOTION: return JS_NewAtom(js, "joystick_axis_motion"); + case SDL_EVENT_JOYSTICK_BALL_MOTION: return JS_NewAtom(js, "joystick_ball_motion"); + case SDL_EVENT_JOYSTICK_HAT_MOTION: return JS_NewAtom(js, "joystick_hat_motion"); + case SDL_EVENT_JOYSTICK_BUTTON_DOWN: return JS_NewAtom(js, "joystick_button_down"); + case SDL_EVENT_JOYSTICK_BUTTON_UP: return JS_NewAtom(js, "joystick_button_up"); + case SDL_EVENT_JOYSTICK_ADDED: return JS_NewAtom(js, "joystick_added"); + case SDL_EVENT_JOYSTICK_REMOVED: return JS_NewAtom(js, "joystick_removed"); + case SDL_EVENT_JOYSTICK_BATTERY_UPDATED: return JS_NewAtom(js, "joystick_battery_updated"); + case SDL_EVENT_JOYSTICK_UPDATE_COMPLETE: return JS_NewAtom(js, "joystick_update_complete"); - // Keyboard events - hmput(event_hash, SDL_EVENT_KEY_DOWN, JS_NewAtom(js, "key_down")); - hmput(event_hash, SDL_EVENT_KEY_UP, JS_NewAtom(js, "key_up")); - hmput(event_hash, SDL_EVENT_TEXT_EDITING, JS_NewAtom(js, "text_editing")); - hmput(event_hash, SDL_EVENT_TEXT_INPUT, JS_NewAtom(js, "text_input")); - hmput(event_hash, SDL_EVENT_KEYMAP_CHANGED, JS_NewAtom(js, "keymap_changed")); - hmput(event_hash, SDL_EVENT_KEYBOARD_ADDED, JS_NewAtom(js, "keyboard_added")); - hmput(event_hash, SDL_EVENT_KEYBOARD_REMOVED, JS_NewAtom(js, "keyboard_removed")); - hmput(event_hash, SDL_EVENT_TEXT_EDITING_CANDIDATES, JS_NewAtom(js, "text_editing_candidates")); + // Gamepad events + case SDL_EVENT_GAMEPAD_AXIS_MOTION: return JS_NewAtom(js, "gamepad_axis_motion"); + case SDL_EVENT_GAMEPAD_BUTTON_DOWN: return JS_NewAtom(js, "gamepad_button_down"); + case SDL_EVENT_GAMEPAD_BUTTON_UP: return JS_NewAtom(js, "gamepad_button_up"); + case SDL_EVENT_GAMEPAD_ADDED: return JS_NewAtom(js, "gamepad_added"); + case SDL_EVENT_GAMEPAD_REMOVED: return JS_NewAtom(js, "gamepad_removed"); + case SDL_EVENT_GAMEPAD_REMAPPED: return JS_NewAtom(js, "gamepad_remapped"); + case SDL_EVENT_GAMEPAD_TOUCHPAD_DOWN: return JS_NewAtom(js, "gamepad_touchpad_down"); + case SDL_EVENT_GAMEPAD_TOUCHPAD_MOTION: return JS_NewAtom(js, "gamepad_touchpad_motion"); + case SDL_EVENT_GAMEPAD_TOUCHPAD_UP: return JS_NewAtom(js, "gamepad_touchpad_up"); + case SDL_EVENT_GAMEPAD_SENSOR_UPDATE: return JS_NewAtom(js, "gamepad_sensor_update"); + case SDL_EVENT_GAMEPAD_UPDATE_COMPLETE: return JS_NewAtom(js, "gamepad_update_complete"); + case SDL_EVENT_GAMEPAD_STEAM_HANDLE_UPDATED: return JS_NewAtom(js, "gamepad_steam_handle_updated"); - // Mouse events - hmput(event_hash, SDL_EVENT_MOUSE_MOTION, JS_NewAtom(js, "mouse_motion")); - hmput(event_hash, SDL_EVENT_MOUSE_BUTTON_DOWN, JS_NewAtom(js, "mouse_button_down")); - hmput(event_hash, SDL_EVENT_MOUSE_BUTTON_UP, JS_NewAtom(js, "mouse_button_up")); - hmput(event_hash, SDL_EVENT_MOUSE_WHEEL, JS_NewAtom(js, "mouse_wheel")); - hmput(event_hash, SDL_EVENT_MOUSE_ADDED, JS_NewAtom(js, "mouse_added")); - hmput(event_hash, SDL_EVENT_MOUSE_REMOVED, JS_NewAtom(js, "mouse_removed")); + // Touch events + case SDL_EVENT_FINGER_DOWN: return JS_NewAtom(js, "finger_down"); + case SDL_EVENT_FINGER_UP: return JS_NewAtom(js, "finger_up"); + case SDL_EVENT_FINGER_MOTION: return JS_NewAtom(js, "finger_motion"); - // Joystick events - hmput(event_hash, SDL_EVENT_JOYSTICK_AXIS_MOTION, JS_NewAtom(js, "joystick_axis_motion")); - hmput(event_hash, SDL_EVENT_JOYSTICK_BALL_MOTION, JS_NewAtom(js, "joystick_ball_motion")); - hmput(event_hash, SDL_EVENT_JOYSTICK_HAT_MOTION, JS_NewAtom(js, "joystick_hat_motion")); - hmput(event_hash, SDL_EVENT_JOYSTICK_BUTTON_DOWN, JS_NewAtom(js, "joystick_button_down")); - hmput(event_hash, SDL_EVENT_JOYSTICK_BUTTON_UP, JS_NewAtom(js, "joystick_button_up")); - hmput(event_hash, SDL_EVENT_JOYSTICK_ADDED, JS_NewAtom(js, "joystick_added")); - hmput(event_hash, SDL_EVENT_JOYSTICK_REMOVED, JS_NewAtom(js, "joystick_removed")); - hmput(event_hash, SDL_EVENT_JOYSTICK_BATTERY_UPDATED, JS_NewAtom(js, "joystick_battery_updated")); - hmput(event_hash, SDL_EVENT_JOYSTICK_UPDATE_COMPLETE, JS_NewAtom(js, "joystick_update_complete")); + // Clipboard events + case SDL_EVENT_CLIPBOARD_UPDATE: return JS_NewAtom(js, "clipboard_update"); - // Gamepad events - hmput(event_hash, SDL_EVENT_GAMEPAD_AXIS_MOTION, JS_NewAtom(js, "gamepad_axis_motion")); - hmput(event_hash, SDL_EVENT_GAMEPAD_BUTTON_DOWN, JS_NewAtom(js, "gamepad_button_down")); - hmput(event_hash, SDL_EVENT_GAMEPAD_BUTTON_UP, JS_NewAtom(js, "gamepad_button_up")); - hmput(event_hash, SDL_EVENT_GAMEPAD_ADDED, JS_NewAtom(js, "gamepad_added")); - hmput(event_hash, SDL_EVENT_GAMEPAD_REMOVED, JS_NewAtom(js, "gamepad_removed")); - hmput(event_hash, SDL_EVENT_GAMEPAD_REMAPPED, JS_NewAtom(js, "gamepad_remapped")); - hmput(event_hash, SDL_EVENT_GAMEPAD_TOUCHPAD_DOWN, JS_NewAtom(js, "gamepad_touchpad_down")); - hmput(event_hash, SDL_EVENT_GAMEPAD_TOUCHPAD_MOTION, JS_NewAtom(js, "gamepad_touchpad_motion")); - hmput(event_hash, SDL_EVENT_GAMEPAD_TOUCHPAD_UP, JS_NewAtom(js, "gamepad_touchpad_up")); - hmput(event_hash, SDL_EVENT_GAMEPAD_SENSOR_UPDATE, JS_NewAtom(js, "gamepad_sensor_update")); - hmput(event_hash, SDL_EVENT_GAMEPAD_UPDATE_COMPLETE, JS_NewAtom(js, "gamepad_update_complete")); - hmput(event_hash, SDL_EVENT_GAMEPAD_STEAM_HANDLE_UPDATED, JS_NewAtom(js, "gamepad_steam_handle_updated")); + // Drag and drop events + case SDL_EVENT_DROP_FILE: return JS_NewAtom(js, "drop_file"); + case SDL_EVENT_DROP_TEXT: return JS_NewAtom(js, "drop_text"); + case SDL_EVENT_DROP_BEGIN: return JS_NewAtom(js, "drop_begin"); + case SDL_EVENT_DROP_COMPLETE: return JS_NewAtom(js, "drop_complete"); + case SDL_EVENT_DROP_POSITION: return JS_NewAtom(js, "drop_position"); - // Touch events - hmput(event_hash, SDL_EVENT_FINGER_DOWN, JS_NewAtom(js, "finger_down")); - hmput(event_hash, SDL_EVENT_FINGER_UP, JS_NewAtom(js, "finger_up")); - hmput(event_hash, SDL_EVENT_FINGER_MOTION, JS_NewAtom(js, "finger_motion")); + // Audio device events + case SDL_EVENT_AUDIO_DEVICE_ADDED: return JS_NewAtom(js, "audio_device_added"); + case SDL_EVENT_AUDIO_DEVICE_REMOVED: return JS_NewAtom(js, "audio_device_removed"); + case SDL_EVENT_AUDIO_DEVICE_FORMAT_CHANGED: return JS_NewAtom(js, "audio_device_format_changed"); - // Clipboard events - hmput(event_hash, SDL_EVENT_CLIPBOARD_UPDATE, JS_NewAtom(js, "clipboard_update")); + // Sensor events + case SDL_EVENT_SENSOR_UPDATE: return JS_NewAtom(js, "sensor_update"); - // Drag and drop events - hmput(event_hash, SDL_EVENT_DROP_FILE, JS_NewAtom(js, "drop_file")); - hmput(event_hash, SDL_EVENT_DROP_TEXT, JS_NewAtom(js, "drop_text")); - hmput(event_hash, SDL_EVENT_DROP_BEGIN, JS_NewAtom(js, "drop_begin")); - hmput(event_hash, SDL_EVENT_DROP_COMPLETE, JS_NewAtom(js, "drop_complete")); - hmput(event_hash, SDL_EVENT_DROP_POSITION, JS_NewAtom(js, "drop_position")); + // Pen events + case SDL_EVENT_PEN_PROXIMITY_IN: return JS_NewAtom(js, "pen_proximity_in"); + case SDL_EVENT_PEN_PROXIMITY_OUT: return JS_NewAtom(js, "pen_proximity_out"); + case SDL_EVENT_PEN_DOWN: return JS_NewAtom(js, "pen_down"); + case SDL_EVENT_PEN_UP: return JS_NewAtom(js, "pen_up"); + case SDL_EVENT_PEN_BUTTON_DOWN: return JS_NewAtom(js, "pen_button_down"); + case SDL_EVENT_PEN_BUTTON_UP: return JS_NewAtom(js, "pen_button_up"); + case SDL_EVENT_PEN_MOTION: return JS_NewAtom(js, "pen_motion"); + case SDL_EVENT_PEN_AXIS: return JS_NewAtom(js, "pen_axis"); - // Audio device events - hmput(event_hash, SDL_EVENT_AUDIO_DEVICE_ADDED, JS_NewAtom(js, "audio_device_added")); - hmput(event_hash, SDL_EVENT_AUDIO_DEVICE_REMOVED, JS_NewAtom(js, "audio_device_removed")); - hmput(event_hash, SDL_EVENT_AUDIO_DEVICE_FORMAT_CHANGED, JS_NewAtom(js, "audio_device_format_changed")); + // Camera events + case SDL_EVENT_CAMERA_DEVICE_ADDED: return JS_NewAtom(js, "camera_device_added"); + case SDL_EVENT_CAMERA_DEVICE_REMOVED: return JS_NewAtom(js, "camera_device_removed"); + case SDL_EVENT_CAMERA_DEVICE_APPROVED: return JS_NewAtom(js, "camera_device_approved"); + case SDL_EVENT_CAMERA_DEVICE_DENIED: return JS_NewAtom(js, "camera_device_denied"); - // Sensor events - hmput(event_hash, SDL_EVENT_SENSOR_UPDATE, JS_NewAtom(js, "sensor_update")); + // Render events + case SDL_EVENT_RENDER_TARGETS_RESET: return JS_NewAtom(js, "render_targets_reset"); + case SDL_EVENT_RENDER_DEVICE_RESET: return JS_NewAtom(js, "render_device_reset"); + case SDL_EVENT_RENDER_DEVICE_LOST: return JS_NewAtom(js, "render_device_lost"); - // Pen events - hmput(event_hash, SDL_EVENT_PEN_PROXIMITY_IN, JS_NewAtom(js, "pen_proximity_in")); - hmput(event_hash, SDL_EVENT_PEN_PROXIMITY_OUT, JS_NewAtom(js, "pen_proximity_out")); - hmput(event_hash, SDL_EVENT_PEN_DOWN, JS_NewAtom(js, "pen_down")); - hmput(event_hash, SDL_EVENT_PEN_UP, JS_NewAtom(js, "pen_up")); - hmput(event_hash, SDL_EVENT_PEN_BUTTON_DOWN, JS_NewAtom(js, "pen_button_down")); - hmput(event_hash, SDL_EVENT_PEN_BUTTON_UP, JS_NewAtom(js, "pen_button_up")); - hmput(event_hash, SDL_EVENT_PEN_MOTION, JS_NewAtom(js, "pen_motion")); - hmput(event_hash, SDL_EVENT_PEN_AXIS, JS_NewAtom(js, "pen_axis")); - - // Camera events - hmput(event_hash, SDL_EVENT_CAMERA_DEVICE_ADDED, JS_NewAtom(js, "camera_device_added")); - hmput(event_hash, SDL_EVENT_CAMERA_DEVICE_REMOVED, JS_NewAtom(js, "camera_device_removed")); - hmput(event_hash, SDL_EVENT_CAMERA_DEVICE_APPROVED, JS_NewAtom(js, "camera_device_approved")); - hmput(event_hash, SDL_EVENT_CAMERA_DEVICE_DENIED, JS_NewAtom(js, "camera_device_denied")); - - // Render events - hmput(event_hash, SDL_EVENT_RENDER_TARGETS_RESET, JS_NewAtom(js, "render_targets_reset")); - hmput(event_hash, SDL_EVENT_RENDER_DEVICE_RESET, JS_NewAtom(js, "render_device_reset")); - hmput(event_hash, SDL_EVENT_RENDER_DEVICE_LOST, JS_NewAtom(js, "render_device_lost")); + default: return JS_NewAtom(js, "unknown"); + } } static JSAtom mouse2atom(JSContext *js, int mouse) @@ -2772,7 +2682,7 @@ static JSValue js_keymod(JSContext *js) static JSValue event2js(JSContext *js, SDL_Event event) { JSValue e = JS_NewObject(js); - JS_SetPropertyStr(js, e, "type", JS_AtomToString(js,hmget(event_hash, event.type))); + JS_SetPropertyStr(js, e, "type", JS_AtomToString(js, event_type_to_atom(js, event.type))); JS_SetPropertyStr(js,e,"timestamp", number2js(js,event.common.timestamp)); switch(event.type) { @@ -3029,6 +2939,8 @@ SDL_GPUShaderFormat js2SDL_GPUShaderFormat(JSContext *js, JSValue v) } JSC_CCALL(SDL_Window_make_gpu, + if (global_gpu) + return JS_ThrowReferenceError(js, "A gpu has already been created somewhere."); const char *name = JS_ToCString(js,argv[1]); SDL_PropertiesID props = SDL_CreateProperties(); SDL_SetStringProperty(props, SDL_PROP_GPU_DEVICE_CREATE_NAME_STRING, name); @@ -3208,8 +3120,8 @@ JSC_CCALL(renderer_load_texture, SDL_Texture *tex = SDL_CreateTextureFromSurface(r,surf); if (!tex) return JS_ThrowReferenceError(js, "Could not create texture from surface: %s", SDL_GetError()); ret = SDL_Texture2js(js,tex); - JS_SetProperty(js,ret,width_atom, number2js(js,tex->w)); - JS_SetProperty(js,ret,height_atom, number2js(js,tex->h)); + JS_SetProperty(js,ret,width, number2js(js,tex->w)); + JS_SetProperty(js,ret,height, number2js(js,tex->h)); ) JSC_CCALL(SDL_Renderer_fillrect, @@ -3530,10 +3442,10 @@ JSC_CCALL(renderer_make_sprite_mesh, for (int i = 0; i < quads; i++) { JSValue sub = JS_GetPropertyUint32(js,sprites,i); - JSValue jstransform = JS_GetProperty(js,sub,transform_atom); + JSValue jstransform = JS_GetProperty(js,sub,transform); - JSValue jssrc = JS_GetProperty(js,sub,src_atom); - JSValue jscolor = JS_GetProperty(js,sub,color_atom); + JSValue jssrc = JS_GetProperty(js,sub,src); + JSValue jscolor = JS_GetProperty(js,sub,color); HMM_Vec4 color; rect src; @@ -3568,12 +3480,12 @@ JSC_CCALL(renderer_make_sprite_mesh, } ret = JS_NewObject(js); - JS_SetProperty(js, ret, pos_atom, make_gpu_buffer(js, posdata, sizeof(*posdata) * verts, JS_TYPED_ARRAY_FLOAT32, 2, 0,0)); - JS_SetProperty(js, ret, uv_atom, make_gpu_buffer(js, uvdata, sizeof(*uvdata) * verts, JS_TYPED_ARRAY_FLOAT32, 2, 0,0)); - JS_SetProperty(js, ret, color_atom, make_gpu_buffer(js, colordata, sizeof(*colordata) * verts, JS_TYPED_ARRAY_FLOAT32, 4, 0,0)); - JS_SetProperty(js, ret, indices_atom, make_quad_indices_buffer(js, quads)); - JS_SetProperty(js, ret, vertices_atom, number2js(js, verts)); - JS_SetProperty(js, ret, count_atom, number2js(js, count)); + JS_SetProperty(js, ret, pos, make_gpu_buffer(js, posdata, sizeof(*posdata) * verts, JS_TYPED_ARRAY_FLOAT32, 2, 0,0)); + JS_SetProperty(js, ret, uv, make_gpu_buffer(js, uvdata, sizeof(*uvdata) * verts, JS_TYPED_ARRAY_FLOAT32, 2, 0,0)); + JS_SetProperty(js, ret, color, make_gpu_buffer(js, colordata, sizeof(*colordata) * verts, JS_TYPED_ARRAY_FLOAT32, 4, 0,0)); + JS_SetProperty(js, ret, indices, make_quad_indices_buffer(js, quads)); + JS_SetProperty(js, ret, vertices, number2js(js, verts)); + JS_SetProperty(js, ret, count, number2js(js, count)); ) @@ -3873,8 +3785,8 @@ if (compress) { } ret = SDL_GPUTexture2js(js, tex); - JS_SetProperty(js, ret, width_atom, number2js(js, surf->w)); - JS_SetProperty(js, ret, height_atom, number2js(js, surf->h)); + JS_SetProperty(js, ret, width, number2js(js, surf->w)); + JS_SetProperty(js, ret, height, number2js(js, surf->h)); JS_SetPropertyStr(js,ret,"dim", vec22js(js,(HMM_Vec2){surf->w,surf->h})); if (dofree) SDL_DestroySurface(surf); @@ -4262,18 +4174,18 @@ JSC_CCALL(gpu_sort_sprite, JSValue b = argv[1]; int alayer, blayer; - JS_GETATOM(js,alayer,a,layer_atom,number) - JS_GETATOM(js,blayer,b,layer_atom,number) + JS_GETATOM(js,alayer,a,layer,number) + JS_GETATOM(js,blayer,b,layer,number) if (alayer != blayer) return number2js(js,alayer - blayer); rect ar, br; - JS_GETATOM(js,ar,a,rect_atom,rect) - JS_GETATOM(js,br,b,rect_atom,rect) + JS_GETATOM(js,ar,a,rect,rect) + JS_GETATOM(js,br,b,rect,rect) if (ar.y != br.y) return number2js(js,br.y-ar.y); JSValue aimg,bimg; - aimg = JS_GetProperty(js,a,image_atom); - bimg = JS_GetProperty(js,b,image_atom); + aimg = JS_GetProperty(js,a,image); + bimg = JS_GetProperty(js,b,image); JS_FreeValue(js,aimg); JS_FreeValue(js,bimg); if (!JS_SameValue(js,aimg,bimg)) return number2js(js,JS_VALUE_GET_PTR(aimg) < JS_VALUE_GET_PTR(bimg) ? -1 : 1); @@ -4307,13 +4219,13 @@ JSC_CCALL(gpu_make_sprite_queue, } else { sprite sp = {0}; - JS_GETATOM(js,sp.affine, sub, rect_atom, rect) - JS_GETATOM(js,sp.color,sub,color_atom,color) - JS_GETATOM(js,sp.layer,sub,layer_atom,number) - JS_GETATOM(js,sp.uv,sub,src_atom,rect) - sp.image = JS_GetProperty(js,sub,image_atom); + JS_GETATOM(js,sp.affine, sub, rect, rect) + JS_GETATOM(js,sp.color,sub,color,color) + JS_GETATOM(js,sp.layer,sub,layer,number) + JS_GETATOM(js,sp.uv,sub,src,rect) + sp.image = JS_GetProperty(js,sub,image); - JS_GETATOM(js,sp.tex,sp.image,texture_atom,SDL_GPUTexture) + JS_GETATOM(js,sp.tex,sp.image,texture,SDL_GPUTexture) arrput(sprites,sp); } JS_FreeValue(js, sub); @@ -4408,9 +4320,9 @@ JSC_CCALL(gpu_make_sprite_mesh, transform *tr; rect src; HMM_Vec4 color; - JS_GETATOM(js,src,sub,src_atom,rect) - JS_GETATOM(js,color,sub,color_atom,color) - JS_GETATOM(js,tr,sub,transform_atom,transform) + JS_GETATOM(js,src,sub,src,rect) + JS_GETATOM(js,color,sub,color,color) + JS_GETATOM(js,tr,sub,transform,transform) JS_FreeValue(js,sub); size_t base = i*4; @@ -4420,7 +4332,7 @@ JSC_CCALL(gpu_make_sprite_mesh, posdata[base+j] = HMM_MulM3V3(trmat, base_quad[j]).xy; } else { rect dst; - JS_GETATOM(js,dst,sub,rect_atom,rect); + JS_GETATOM(js,dst,sub,rect,rect); posdata[base+0] = (HMM_Vec2){dst.x,dst.y}; posdata[base + 1] = (HMM_Vec2){ dst.x+dst.w, dst.y }; posdata[base + 2] = (HMM_Vec2){ dst.x, dst.y+dst.h }; @@ -4448,9 +4360,9 @@ JSC_CCALL(gpu_make_sprite_mesh, size_t uv_size = sizeof(*uvdata)*verts; size_t color_size = sizeof(*colordata)*verts; - BufferCheckResult pos_chk = get_or_extend_buffer(js, old_mesh, pos_atom, pos_size, JS_TYPED_ARRAY_FLOAT32, 2, 1, 0); - BufferCheckResult uv_chk = get_or_extend_buffer(js, old_mesh, uv_atom, uv_size, JS_TYPED_ARRAY_FLOAT32, 2, 1, 0); - BufferCheckResult color_chk = get_or_extend_buffer(js, old_mesh, color_atom, color_size, JS_TYPED_ARRAY_FLOAT32, 4, 1, 0); + BufferCheckResult pos_chk = get_or_extend_buffer(js, old_mesh, "pos", pos_size, JS_TYPED_ARRAY_FLOAT32, 2, 1, 0); + BufferCheckResult uv_chk = get_or_extend_buffer(js, old_mesh, "uv", uv_size, JS_TYPED_ARRAY_FLOAT32, 2, 1, 0); + BufferCheckResult color_chk = get_or_extend_buffer(js, old_mesh, "color", color_size, JS_TYPED_ARRAY_FLOAT32, 4, 1, 0); int need_new_all = pos_chk.need_new || uv_chk.need_new || color_chk.need_new; @@ -4462,13 +4374,13 @@ JSC_CCALL(gpu_make_sprite_mesh, JSValue new_uv = make_gpu_buffer(js, uvdata, uv_size, JS_TYPED_ARRAY_FLOAT32, 2, 1,0); JSValue new_color = make_gpu_buffer(js, colordata, color_size, JS_TYPED_ARRAY_FLOAT32, 0, 1,0); - JS_SetProperty(js, ret, pos_atom, new_pos); - JS_SetProperty(js, ret, uv_atom, new_uv); - JS_SetProperty(js, ret, color_atom, new_color); + JS_SetProperty(js, ret, pos, new_pos); + JS_SetProperty(js, ret, uv, new_uv); + JS_SetProperty(js, ret, color, new_color); // Indices JSValue indices = make_quad_indices_buffer(js, quads); - JS_SetProperty(js, ret, indices_atom, indices); + JS_SetProperty(js, ret, indices, indices); } else { // Reuse the old buffers // Just copy data into existing buffers via their pointers @@ -4477,17 +4389,17 @@ JSC_CCALL(gpu_make_sprite_mesh, memcpy(color_chk.ptr, colordata, color_size); // Duplicate old references since we're returning a new object - JS_SetProperty(js, ret, pos_atom, JS_DupValue(js, pos_chk.val)); - JS_SetProperty(js, ret, uv_atom, JS_DupValue(js, uv_chk.val)); - JS_SetProperty(js, ret, color_atom, JS_DupValue(js, color_chk.val)); + JS_SetProperty(js, ret, pos, JS_DupValue(js, pos_chk.val)); + JS_SetProperty(js, ret, uv, JS_DupValue(js, uv_chk.val)); + JS_SetProperty(js, ret, color, JS_DupValue(js, color_chk.val)); // Indices can remain the same if they were also large enough. If using a shared global index buffer: JSValue indices = make_quad_indices_buffer(js, quads); - JS_SetProperty(js, ret, indices_atom, indices); + JS_SetProperty(js, ret, indices, indices); } - JS_SetProperty(js, ret, vertices_atom, number2js(js, verts)); - JS_SetProperty(js, ret, count_atom, number2js(js, count)); + JS_SetProperty(js, ret, vertices, number2js(js, verts)); + JS_SetProperty(js, ret, count, number2js(js, count)); JS_SetPropertyStr(js,ret,"num_indices", number2js(js,count)); // Free temporary CPU arrays @@ -4533,14 +4445,14 @@ JSC_CCALL(gpu_make_quad, JSValue uv = make_gpu_buffer(js, uvdata, sizeof(*uvdata)*verts, JS_TYPED_ARRAY_FLOAT32, 2, 1,0); JSValue color = make_gpu_buffer(js, colordata, sizeof(*colordata)*verts, JS_TYPED_ARRAY_FLOAT32, 0, 1,0); - JS_SetProperty(js, ret, pos_atom, pos); - JS_SetProperty(js, ret, uv_atom, uv); - JS_SetProperty(js, ret, color_atom, color); + JS_SetProperty(js, ret, pos, pos); + JS_SetProperty(js, ret, uv, uv); + JS_SetProperty(js, ret, color, color); JSValue indices = make_quad_indices_buffer(js, quads); - JS_SetProperty(js, ret, indices_atom, indices); + JS_SetProperty(js, ret, indices, indices); - JS_SetProperty(js, ret, vertices_atom, number2js(js, verts)); - JS_SetProperty(js, ret, count_atom, number2js(js, count)); + JS_SetProperty(js, ret, vertices, number2js(js, verts)); + JS_SetProperty(js, ret, count, number2js(js, count)); JS_SetPropertyStr(js,ret,"num_indices", number2js(js,count)); // Free temporary CPU arrays @@ -5079,8 +4991,8 @@ JSC_CCALL(gpu_slice9, JSC_CCALL(gpu_tile, HMM_Vec2 size; JSValue jstex = argv[0]; - JS_GETATOM(js,size.x,jstex,width_atom,number) - JS_GETATOM(js, size.y, jstex, height_atom, number) + JS_GETATOM(js,size.x,jstex,width,number) + JS_GETATOM(js, size.y, jstex, height, number) rect src_pixels = js2rect(js, argv[1]); // 'src' as pixel dimensions rect dst = js2rect(js, argv[2]); // 'dst' as screen coords @@ -5721,8 +5633,8 @@ JSC_CCALL(input_mousestate, float x,y; SDL_MouseButtonFlags flags = SDL_GetMouseState(&x,&y); JSValue m = JS_NewObject(js); - JS_SetProperty(js,m,x_atom, number2js(js,x)); - JS_SetProperty(js,m,y_atom,number2js(js,y)); + JS_SetProperty(js,m,x, number2js(js,x)); + JS_SetProperty(js,m,y,number2js(js,y)); if (flags & SDL_BUTTON_LMASK) JS_SetPropertyStr(js, m, "left", JS_NewBool(js, 1)); @@ -6527,6 +6439,31 @@ JSC_CCALL(os_memstate, 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_mallinfo, @@ -6977,7 +6914,7 @@ JSC_CCALL(os_cull_sprites, for (int i = 0; i < len; i++) { JSValue sub = JS_GetPropertyUint32(js,sprites,i); transform *t; - JS_GETATOM(js,t,sub,transform_atom,transform) + JS_GETATOM(js,t,sub,transform,transform) rect sprite = transform2rect(t); if (SDL_HasRectIntersectionFloat(&sprite, &camera_rect)) { @@ -6998,15 +6935,15 @@ JSC_CCALL(os_rects_to_sprites, ret = JS_NewArray(js); JSValue image = argv[0]; - JSValue jstex = JS_GetProperty(js,image,texture_atom); + JSValue jstex = JS_GetProperty(js,image,texture); double w, h = 0; - JS_GETATOM(js,w,jstex,width_atom,number) - JS_GETATOM(js,h,jstex,height_atom,number) + JS_GETATOM(js,w,jstex,width,number) + JS_GETATOM(js,h,jstex,height,number) SDL_GPUTexture *tex = js2SDL_GPUTexture(js,jstex); JS_FreeValue(js,jstex); JSValue rects = argv[1]; rect uv; - JS_GETATOM(js,uv,image,rect_atom,rect) + JS_GETATOM(js,uv,image,rect,rect) ret = JS_NewArray(js); int n = js_arrlen(js,rects); @@ -7155,25 +7092,54 @@ JSC_CCALL(os_createprocess, return JS_ThrowReferenceError(js, "Unable to create process: %s\n", SDL_GetError()); ) -int create_new_runtime(void *data) +typedef struct { + int argc; + char **argv; +} cmdargs; + +int create_new_runtime(cmdargs *data) { - + script_startup(data->argc, data->argv); } JSC_CCALL(os_createthread, - SDL_Thread *thread = SDL_CreateThread(create_new_runtime, "newrt", NULL); + cmdargs cmd; + cmd.argc = JS_ArrayLength(js,argv[0]); + cmd.argv = (char **)calloc(cmd.argc, sizeof(char *)); + // Convert JS array elements to C strings + for (int i = 0; i < cmd.argc; i++) { + JSValue val = JS_GetPropertyUint32(js, argv[0], i); + if (JS_IsException(val)) { + free(cmd.argv); + return val; + } + + const char *str = JS_ToCString(js, val); + if (!str) { + free(cmd.argv); + JS_FreeValue(js, val); + return JS_ThrowInternalError(js, "Could not convert argument to string"); + } + + cmd.argv[i] = strdup(str); // Make a copy of the string + JS_FreeCString(js, str); + JS_FreeValue(js, val); + } + SDL_Thread *thread = SDL_CreateThread(create_new_runtime, "newrt", &cmd); + if (!thread) return JS_ThrowInternalError(js, "Could not create a new thread: %s", SDL_GetError()) ) typedef struct mailbox { - SDL_mutex *mutex; + SDL_Mutex *mutex; void **messages; } mailbox; static struct { char *key; mailbox value; } *mailboxes = NULL; +static SDL_Mutex *mailboxes_mutex = NULL; JSC_CCALL(os_mailbox_push, if (argc < 2) return JS_ThrowInternalError(js, "Need an actor and an array buffer."); - char *id = JS_GetCString(js,argv[0]); + char *id = JS_ToCString(js,argv[0]); void *nota = value2nota(js, argv[1]); int mailbox_index = shgeti(mailboxes, id); @@ -7192,7 +7158,7 @@ JSC_CCALL(os_mailbox_push, ) JSC_CCALL(os_mailbox_service, // grab all from our mailbox and - char *id = JS_GetCString(js,argv[0]); + char *id = JS_ToCString(js,argv[0]); JSValue fn = JS_DupValue(js,argv[1]); int mb_index = shgeti(mailboxes, id); @@ -7226,57 +7192,82 @@ JSC_CCALL(os_mailbox_service, // grab all from our mailbox and arrfree(temp); JS_FreeCString(js,id); - JS_FreeCString(js,fn); + JS_FreeValue(js,fn); ) JSC_CCALL(os_mailbox_start, - char *id = JS_GetCString(js,argv[0]); + char *id = JS_ToCString(js,argv[0]); void **letters = NULL; mailbox mb; mb.mutex = SDL_CreateMutex(); mb.messages = NULL; + if (!mailboxes_mutex) + mailboxes_mutex = SDL_CreateMutex(); + + SDL_LockMutex(mailboxes_mutex); shput(mailboxes, id, mb); + SDL_UnlockMutex(mailboxes_mutex); JS_FreeCString(js,id); ) -struct { SDL_TimerID key; JSValue *value; } *timer_hash = NULL; +static SDL_TLSID timer_hash_tls = {0}; +typedef struct { SDL_TimerID key; JSValue *value; } TimerEntry; -Uint64 os_timer_cb(JSValue *fn, SDL_TimerID id, Uint64 delay) -{ - SDL_UserEvent event; - SDL_zero(event); - event.type = timer_cb_event; - event.data1 = fn; - SDL_PushEvent(&event); - hmdel(timer_hash, id); - return 0; +TimerEntry *get_timer_hash(void) { + return (TimerEntry *)SDL_GetTLS(&timer_hash_tls); +} + +Uint64 os_timer_cb(JSValue *fn, SDL_TimerID id, Uint64 delay) { + SDL_UserEvent event; + SDL_zero(event); + event.type = timer_cb_event; + event.data1 = fn; + SDL_PushEvent(&event); + + TimerEntry *timer_hash = get_timer_hash(); + hmdel(timer_hash, id); // Remove from hash table after pushing event + + return 0; // Returning 0 ensures the timer doesn’t repeat } JSC_CCALL(os_addtimer, - JSValue *fn = malloc(sizeof(*fn)); - *fn = JS_DupValue(js,argv[0]); - double secs; - JS_ToFloat64(js, &secs, argv[1]); + JSValue *fn = malloc(sizeof(*fn)); + *fn = JS_DupValue(js, argv[0]); + double secs; + JS_ToFloat64(js, &secs, argv[1]); - SDL_TimerID id = SDL_AddTimerNS(secs*1000000000.0f, os_timer_cb, fn); + SDL_TimerID id = SDL_AddTimerNS(secs * 1000000000.0f, os_timer_cb, fn); + if (!id) { + JS_FreeValue(js, *fn); + free(fn); + return JS_ThrowInternalError(js, "Failed to add timer: %s", SDL_GetError()); + } - hmput(timer_hash, id, fn); + TimerEntry *timer_hash = get_timer_hash(); + hmput(timer_hash, id, fn); - return JS_NewUint32(js,id); + return JS_NewUint32(js, id); ) JSC_CCALL(os_removetimer, - SDL_TimerID id; - JS_ToUint32(js,&id, argv[0]); - int rm = SDL_RemoveTimer(id); - if (!rm) return JS_ThrowReferenceError(js,"Could not remove timer id %u: %s\n", id, SDL_GetError()); - JSValue *fn = hmget(timer_hash, id); - if (fn != -1) { - JS_FreeValue(js, *fn); - free(fn); - hmdel(timer_hash, id); - } + SDL_TimerID id; + JS_ToUint32(js, &id, argv[0]); + int rm = SDL_RemoveTimer(id); + if (!rm) { + return JS_ThrowReferenceError(js, "Could not remove timer id %u: %s\n", id, SDL_GetError()); + } + + TimerEntry *timer_hash = get_timer_hash(); + int index = hmgeti(timer_hash, id); + if (index != -1) { + JSValue *fn = timer_hash[index].value; + JS_FreeValue(js, *fn); + free(fn); + hmdel(timer_hash, id); + } + + return JS_UNDEFINED; ) JSC_CCALL(os_waitevent, @@ -7340,6 +7331,11 @@ static const JSCFunctionListEntry js_os_funcs[] = { MIST_FUNC_DEF(os, addtimer, 2), MIST_FUNC_DEF(os, removetimer, 1), MIST_FUNC_DEF(os, waitevent, 2), + + MIST_FUNC_DEF(os, mailbox_push, 2), + MIST_FUNC_DEF(os, mailbox_service, 2), + MIST_FUNC_DEF(os, mailbox_start, 1), + MIST_FUNC_DEF(os, createthread, 0), }; JSC_CCALL(js_dump_class, return js_get_object_class_distribution(js)) @@ -7489,7 +7485,7 @@ JSC_CCALL(rtree_add, rtree *tree = js2rtree(js,self); JSValue v = argv[0]; rect r; - JS_GETATOM(js,r,v,rect_atom,rect) + JS_GETATOM(js,r,v,rect,rect) NUMTYPE min[3]; NUMTYPE max[3]; min[0] = r.x; @@ -7519,7 +7515,7 @@ JSC_CCALL(rtree_delete, rtree *tree = js2rtree(js,self); JSValue v = argv[0]; rect r; - JS_GETATOM(js,r,v,rect_atom,rect) + JS_GETATOM(js,r,v,rect,rect) NUMTYPE min[3]; NUMTYPE max[3]; min[0] = r.x; @@ -7671,8 +7667,8 @@ JSC_CCALL(sprite_set_image, sp->image = JS_DupValue(js,argv[0]); if (JS_IsUndefined(sp->image)) return JS_UNDEFINED; JSValue img = sp->image; - JS_GETATOM(js, sp->uv, img, rect_atom, rect) - JS_GETATOM(js, sp->tex, img, texture_atom, SDL_GPUTexture); + JS_GETATOM(js, sp->uv, img, rect, rect) + JS_GETATOM(js, sp->tex, img, texture, SDL_GPUTexture); ) static const JSCFunctionListEntry js_sprite_funcs[] = { @@ -7960,13 +7956,6 @@ MISTUSE(crypto) JSValue js_imgui_use(JSContext *js); -#include "qjs_dmon.h" -#include "qjs_nota.h" -#include "qjs_wota.h" -#include "qjs_enet.h" -#include "qjs_soloud.h" -#include "qjs_qr.h" - #define MISTLINE(NAME) (ModuleEntry){#NAME, js_##NAME##_use} void ffi_setup() @@ -8064,98 +8053,6 @@ void ffi_load(JSContext *js, int argc, char **argv) { JS_FreeValue(js,jsnumber); JS_FreeValue(js,number_proto); - x_atom = JS_NewAtom(js,"x"); - y_atom = JS_NewAtom(js,"y"); - width_atom = JS_NewAtom(js,"width"); - height_atom = JS_NewAtom(js,"height"); - anchor_x_atom = JS_NewAtom(js, "anchor_x"); - anchor_y_atom = JS_NewAtom(js,"anchor_y"); - src_atom = JS_NewAtom(js,"src"); - pos_atom = JS_NewAtom(js, "pos"); - uv_atom = JS_NewAtom(js, "uv"); - color_atom = JS_NewAtom(js, "color"); - indices_atom = JS_NewAtom(js, "indices"); - vertices_atom = JS_NewAtom(js, "vertices"); - dst_atom = JS_NewAtom(js, "dst"); - count_atom = JS_NewAtom(js, "count"); - transform_atom = JS_NewAtom(js,"transform"); - image_atom = JS_NewAtom(js,"image"); - layer_atom = JS_NewAtom(js,"layer"); - texture_atom = JS_NewAtom(js, "texture"); - - cw_atom = JS_NewAtom(js,"cw"); - ccw_atom = JS_NewAtom(js,"ccw"); - zero_atom = JS_NewAtom(js, "zero"); - one_atom = JS_NewAtom(js, "one"); - add_atom = JS_NewAtom(js, "add"); - sub_atom = JS_NewAtom(js, "sub"); - rev_sub_atom = JS_NewAtom(js, "rev_sub"); - min_atom = JS_NewAtom(js, "min"); - max_atom = JS_NewAtom(js, "max"); - none_atom = JS_NewAtom(js, "none"); - front_atom = JS_NewAtom(js, "front"); - back_atom = JS_NewAtom(js, "back"); - never_atom = JS_NewAtom(js, "never"); - less_atom = JS_NewAtom(js, "less"); - equal_atom = JS_NewAtom(js, "equal"); - less_equal_atom = JS_NewAtom(js, "less_equal"); - greater_atom = JS_NewAtom(js, "greater"); - not_equal_atom = JS_NewAtom(js, "not_equal"); - greater_equal_atom = JS_NewAtom(js, "greater_equal"); - always_atom = JS_NewAtom(js, "always"); - keep_atom = JS_NewAtom(js, "keep"); - zero_stencil_atom = JS_NewAtom(js, "zero"); - replace_atom = JS_NewAtom(js, "replace"); - incr_clamp_atom = JS_NewAtom(js, "incr_clamp"); - decr_clamp_atom = JS_NewAtom(js, "decr_clamp"); - invert_atom = JS_NewAtom(js, "invert"); - incr_wrap_atom = JS_NewAtom(js, "incr_wrap"); - decr_wrap_atom = JS_NewAtom(js, "decr_wrap"); - point_atom = JS_NewAtom(js, "point"); - line_atom = JS_NewAtom(js, "line"); - linestrip_atom = JS_NewAtom(js, "linestrip"); - triangle_atom = JS_NewAtom(js, "triangle"); - trianglestrip_atom = JS_NewAtom(js, "trianglestrip"); - src_color_atom = JS_NewAtom(js, "src_color"); - one_minus_src_color_atom = JS_NewAtom(js, "one_minus_src_color"); - dst_color_atom = JS_NewAtom(js, "dst_color"); - one_minus_dst_color_atom = JS_NewAtom(js, "one_minus_dst_color"); - src_alpha_atom = JS_NewAtom(js, "src_alpha"); - one_minus_src_alpha_atom = JS_NewAtom(js, "one_minus_src_alpha"); - dst_alpha_atom = JS_NewAtom(js, "dst_alpha"); - one_minus_dst_alpha_atom = JS_NewAtom(js, "one_minus_dst_alpha"); - constant_color_atom = JS_NewAtom(js, "constant_color"); - one_minus_constant_color_atom = JS_NewAtom(js, "one_minus_constant_color"); - src_alpha_saturate_atom = JS_NewAtom(js, "src_alpha_saturate"); - none_cull_atom = JS_NewAtom(js, "none"); - front_cull_atom = JS_NewAtom(js, "front"); - back_cull_atom = JS_NewAtom(js, "back"); - norm_atom = JS_NewAtom(js,"norm"); - - nearest_atom = JS_NewAtom(js, "nearest"); - linear_atom = JS_NewAtom(js, "linear"); - - mipmap_nearest_atom = JS_NewAtom(js, "nearest"); // For mipmap mode "nearest" - mipmap_linear_atom = JS_NewAtom(js, "linear"); // For mipmap mode "linear" - - repeat_atom = JS_NewAtom(js, "repeat"); - mirror_atom = JS_NewAtom(js, "mirror"); - clamp_edge_atom = JS_NewAtom(js, "clamp_edge"); - clamp_border_atom = JS_NewAtom(js, "clamp_border"); - vertex_atom = JS_NewAtom(js, "vertex"); - index_atom = JS_NewAtom(js, "index"); - indirect_atom = JS_NewAtom(js, "indirect"); - num_indices_atom = JS_NewAtom(js,"num_indices"); - parent_atom = JS_NewAtom(js,"parent"); - rect_atom = JS_NewAtom(js,"rect"); - - l_atom = JS_NewAtom(js,"l"); - r_atom = JS_NewAtom(js,"r"); - b_atom = JS_NewAtom(js,"b"); - t_atom = JS_NewAtom(js,"t"); - - fill_event_atoms(js); - signal(SIGINT, signal_handler); signal(SIGTERM, signal_handler); signal(SIGSEGV, signal_handler); @@ -8179,6 +8076,9 @@ void ffi_load(JSContext *js, int argc, char **argv) { cycle_fn = JS_UNDEFINED; JS_FreeValue(js,globalThis); + + TimerEntry *timer_hash = NULL; // Initially empty hash table + SDL_SetTLS(&timer_hash_tls, timer_hash, NULL); // arrfree from stb_ds.h frees the array SDL_Init(SDL_INIT_EVENTS); } diff --git a/source/qjs_nota.c b/source/qjs_nota.c index 911d41b4..a212e21c 100755 --- a/source/qjs_nota.c +++ b/source/qjs_nota.c @@ -240,7 +240,7 @@ void *value2nota(JSContext *ctx, JSValue v) nota_buffer_init(&enc->nb, 128); - nota_encode_value(enc, argv[0]); + nota_encode_value(enc, v); if (enc->cycle) { JS_FreeValue(ctx, enc->visitedStack); diff --git a/source/script.c b/source/script.c index 99558cb8..e1070361 100644 --- a/source/script.c +++ b/source/script.c @@ -27,7 +27,7 @@ SDL_TLSID js_id = {0}; #define ENGINE "scripts/core/engine.js" -#define JS_EVAL_FLAGS JS_EVAL_FLAG_STRICT +#define JS_EVAL_FLAGS JS_EVAL_FLAG_STRICT #ifdef TRACY_ENABLE #include