diff --git a/include/ant.h b/include/ant.h index 4fd7463..2e676da 100644 --- a/include/ant.h +++ b/include/ant.h @@ -54,6 +54,12 @@ jsval_t js_call(struct js *js, jsval_t func, jsval_t *args, int nargs); void js_set(struct js *, jsval_t, const char *, jsval_t); void js_merge_obj(struct js *, jsval_t dst, jsval_t src); +jsval_t js_setprop(struct js *, jsval_t obj, jsval_t key, jsval_t val); +void js_set_proto(struct js *, jsval_t obj, jsval_t proto); + +jsval_t js_get_proto(struct js *, jsval_t obj); +jsval_t js_get_ctor_proto(struct js *, const char *name, size_t len); + int js_type(jsval_t val); int js_getbool(jsval_t val); diff --git a/meson.build b/meson.build index deed231..cdb2d37 100644 --- a/meson.build +++ b/meson.build @@ -74,7 +74,7 @@ endif build_date = run_command('date', '+%Y-%m-%d', check: true).stdout().strip() version_conf = configuration_data() -version_conf.set('ANT_VERSION', '0.0.7.34') +version_conf.set('ANT_VERSION', '0.0.7.35') version_conf.set('ANT_GIT_HASH', git_hash) version_conf.set('ANT_BUILD_DATE', build_date) diff --git a/src/ant.c b/src/ant.c index 7144dab..92817d3 100644 --- a/src/ant.c +++ b/src/ant.c @@ -442,11 +442,18 @@ static jsval_t call_js_with_args(struct js *js, jsval_t func, jsval_t *args, int static jsval_t call_js_code_with_args(struct js *js, const char *fn, jsoff_t fnlen, jsval_t closure_scope, jsval_t *args, int nargs); static jsval_t start_async_in_coroutine(struct js *js, const char *code, size_t code_len, jsval_t closure_scope, jsval_t *args, int nargs); +jsval_t js_get_proto(struct js *js, jsval_t obj); +void js_set_proto(struct js *js, jsval_t obj, jsval_t proto); +jsval_t js_setprop(struct js *js, jsval_t obj, jsval_t k, jsval_t v); +static jsoff_t lkp_proto(struct js *js, jsval_t obj, const char *key, size_t len); +jsval_t js_get_ctor_proto(struct js *js, const char *name, size_t len); +static jsval_t get_prototype_for_type(struct js *js, uint8_t type); + +// Backward compat aliases (defined after implementations below) static jsval_t get_proto(struct js *js, jsval_t obj); static void set_proto(struct js *js, jsval_t obj, jsval_t proto); -static jsoff_t lkp_proto(struct js *js, jsval_t obj, const char *key, size_t len); static jsval_t get_ctor_proto(struct js *js, const char *name, size_t len); -static jsval_t get_prototype_for_type(struct js *js, uint8_t type); +static jsval_t setprop(struct js *js, jsval_t obj, jsval_t k, jsval_t v); static void free_coroutine(coroutine_t *coro); static bool has_ready_coroutines(void); @@ -1718,7 +1725,7 @@ static jsval_t mkprop(struct js *js, jsval_t obj, jsval_t k, jsval_t v, bool is_ return mkentity(js, (b & ~(3U | CONSTMASK)) | T_PROP, buf, sizeof(buf)); } -static jsval_t setprop(struct js *js, jsval_t obj, jsval_t k, jsval_t v) { +jsval_t js_setprop(struct js *js, jsval_t obj, jsval_t k, jsval_t v) { jsoff_t koff = (jsoff_t) vdata(k); jsoff_t klen = offtolen(loadoff(js, koff)); const char *key = (char *) &js->mem[koff + sizeof(jsoff_t)]; @@ -1736,6 +1743,10 @@ static jsval_t setprop(struct js *js, jsval_t obj, jsval_t k, jsval_t v) { return mkprop(js, obj, k, v, false); } +static jsval_t setprop(struct js *js, jsval_t obj, jsval_t k, jsval_t v) { + return js_setprop(js, obj, k, v); +} + static inline jsoff_t esize(jsoff_t w) { jsoff_t cleaned = w & ~(GCMASK | CONSTMASK); switch (cleaned & 3U) { @@ -2342,7 +2353,7 @@ static jsoff_t lkp(struct js *js, jsval_t obj, const char *buf, size_t len) { return lkp_inline(js, obj, buf, len); } -static jsval_t get_proto(struct js *js, jsval_t obj) { +jsval_t js_get_proto(struct js *js, jsval_t obj) { uint8_t t = vtype(obj); if (t != T_OBJ && t != T_ARR && t != T_FUNC) return js_mknull(); @@ -2360,7 +2371,11 @@ static jsval_t get_proto(struct js *js, jsval_t obj) { return (vt == T_OBJ || vt == T_ARR || vt == T_FUNC) ? val : js_mknull(); } -static void set_proto(struct js *js, jsval_t obj, jsval_t proto) { +static jsval_t get_proto(struct js *js, jsval_t obj) { + return js_get_proto(js, obj); +} + +void js_set_proto(struct js *js, jsval_t obj, jsval_t proto) { uint8_t t = vtype(obj); if (t != T_OBJ && t != T_ARR && t != T_FUNC) return; @@ -2374,7 +2389,11 @@ static void set_proto(struct js *js, jsval_t obj, jsval_t proto) { } } -static jsval_t get_ctor_proto(struct js *js, const char *name, size_t len) { +static void set_proto(struct js *js, jsval_t obj, jsval_t proto) { + js_set_proto(js, obj, proto); +} + +jsval_t js_get_ctor_proto(struct js *js, const char *name, size_t len) { jsoff_t ctor_off = lkp(js, js->scope, name, len); if (ctor_off == 0 && global_scope_stack) { @@ -2400,6 +2419,10 @@ static jsval_t get_ctor_proto(struct js *js, const char *name, size_t len) { return resolveprop(js, mkval(T_PROP, proto_off)); } +static jsval_t get_ctor_proto(struct js *js, const char *name, size_t len) { + return js_get_ctor_proto(js, name, len); +} + static jsval_t get_prototype_for_type(struct js *js, uint8_t type) { switch (type) { case T_STR: return get_ctor_proto(js, "String", 6); @@ -10560,11 +10583,33 @@ jsval_t js_getthis(struct js *js) { return js->this_val; } jsval_t js_getcurrentfunc(struct js *js) { return js->current_func; } void js_set(struct js *js, jsval_t obj, const char *key, jsval_t val) { + size_t key_len = strlen(key); + if (vtype(obj) == T_OBJ) { - setprop(js, obj, js_mkstr(js, key, strlen(key)), val); + jsoff_t existing = lkp(js, obj, key, key_len); + if (existing > 0) { + if (is_const_prop(js, existing)) { + js_mkerr(js, "assignment to constant"); + return; + } + saveval(js, existing + sizeof(jsoff_t) * 2, val); + } else { + jsval_t key_str = js_mkstr(js, key, key_len); + mkprop(js, obj, key_str, val, false); + } } else if (vtype(obj) == T_FUNC) { jsval_t func_obj = mkval(T_OBJ, vdata(obj)); - setprop(js, func_obj, js_mkstr(js, key, strlen(key)), val); + jsoff_t existing = lkp(js, func_obj, key, key_len); + if (existing > 0) { + if (is_const_prop(js, existing)) { + js_mkerr(js, "assignment to constant"); + return; + } + saveval(js, existing + sizeof(jsoff_t) * 2, val); + } else { + jsval_t key_str = js_mkstr(js, key, key_len); + mkprop(js, func_obj, key_str, val, false); + } } } diff --git a/src/modules/json.c b/src/modules/json.c index 522f291..c1eeeb2 100644 --- a/src/modules/json.c +++ b/src/modules/json.c @@ -200,9 +200,21 @@ jsval_t js_json_stringify(struct js *js, jsval_t *args, int nargs) { void init_json_module() { struct js *js = rt->js; + jsval_t glob = js_glob(js); + + jsval_t object_proto = js_get_ctor_proto(js, "Object", 6); jsval_t json_obj = js_mkobj(js); - js_set(js, js_glob(js), "JSON", json_obj); - js_set(js, json_obj, "parse", js_mkfun(js_json_parse)); - js_set(js, json_obj, "stringify", js_mkfun(js_json_stringify)); + if (js_type(object_proto) == JS_PRIV) { + js_set_proto(js, json_obj, object_proto); + } + + jsval_t parse_key = js_mkstr(js, "parse", 5); + jsval_t stringify_key = js_mkstr(js, "stringify", 9); + + js_setprop(js, json_obj, parse_key, js_mkfun(js_json_parse)); + js_setprop(js, json_obj, stringify_key, js_mkfun(js_json_stringify)); + + jsval_t json_key = js_mkstr(js, "JSON", 4); + js_setprop(js, glob, json_key, json_obj); }