MIRROR: javascript for ๐Ÿœ's, a tiny runtime with big ambitions
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

reflection

+412 -1
+3
include/ant.h
··· 53 53 jsval_t js_mknum(double); 54 54 55 55 jsval_t js_getthis(struct js *); 56 + void js_setthis(struct js *, jsval_t); 57 + 56 58 jsval_t js_getcurrentfunc(struct js *); 57 59 jsval_t js_get(struct js *, jsval_t, const char *); 58 60 ··· 64 66 jsval_t js_mkerr_typed(struct js *js, js_err_type_t err_type, const char *fmt, ...); 65 67 jsval_t js_mkfun(jsval_t (*fn)(struct js *, jsval_t *, int)); 66 68 jsval_t js_call(struct js *js, jsval_t func, jsval_t *args, int nargs); 69 + jsval_t js_call_with_this(struct js *js, jsval_t func, jsval_t this_val, jsval_t *args, int nargs); 67 70 68 71 void js_set(struct js *, jsval_t, const char *, jsval_t); 69 72 void js_merge_obj(struct js *, jsval_t dst, jsval_t src);
+6
include/modules/reflect.h
··· 1 + #ifndef REFLECT_H 2 + #define REFLECT_H 3 + 4 + void init_reflect_module(void); 5 + 6 + #endif
+1 -1
meson.build
··· 74 74 build_date = run_command('date', '+%Y-%m-%d', check: true).stdout().strip() 75 75 76 76 version_conf = configuration_data() 77 - version_conf.set('ANT_VERSION', '0.1.1.13') 77 + version_conf.set('ANT_VERSION', '0.1.1.14') 78 78 version_conf.set('ANT_GIT_HASH', git_hash) 79 79 version_conf.set('ANT_BUILD_DATE', build_date) 80 80
+76
src/ant.c
··· 15837 15837 jsval_t js_glob(struct js *js) { (void) js; return mkval(T_OBJ, 0); } 15838 15838 jsval_t js_mkfun(jsval_t (*fn)(struct js *, jsval_t *, int)) { return mkval(T_CFUNC, (size_t) (void *) fn); } 15839 15839 jsval_t js_getthis(struct js *js) { return js->this_val; } 15840 + void js_setthis(struct js *js, jsval_t val) { js->this_val = val; } 15840 15841 jsval_t js_getcurrentfunc(struct js *js) { return js->current_func; } 15841 15842 15842 15843 void js_set(struct js *js, jsval_t obj, const char *key, jsval_t val) { ··· 16126 16127 delscope(js); 16127 16128 js->scope = saved_scope; 16128 16129 16130 + return res; 16131 + } 16132 + return js_mkerr(js, "not a function"); 16133 + } 16134 + 16135 + jsval_t js_call_with_this(struct js *js, jsval_t func, jsval_t bound_this, jsval_t *args, int nargs) { 16136 + if (vtype(func) == T_CFUNC) { 16137 + jsval_t (*fn)(struct js *, jsval_t *, int) = (jsval_t(*)(struct js *, jsval_t *, int)) vdata(func); 16138 + return fn(js, args, nargs); 16139 + } else if (vtype(func) == T_FUNC) { 16140 + jsval_t func_obj = mkval(T_OBJ, vdata(func)); 16141 + jsoff_t native_off = lkp(js, func_obj, "__native_func", 13); 16142 + if (native_off != 0) { 16143 + jsval_t native_val = resolveprop(js, mkval(T_PROP, native_off)); 16144 + if (vtype(native_val) == T_CFUNC) { 16145 + jsval_t saved_func = js->current_func; 16146 + jsval_t saved_this = js->this_val; 16147 + js->current_func = func; 16148 + js->this_val = bound_this; 16149 + jsval_t (*fn)(struct js *, jsval_t *, int) = (jsval_t(*)(struct js *, jsval_t *, int)) vdata(native_val); 16150 + jsval_t res = fn(js, args, nargs); 16151 + js->current_func = saved_func; 16152 + js->this_val = saved_this; 16153 + return res; 16154 + } 16155 + } 16156 + jsoff_t code_off = lkp(js, func_obj, "__code", 6); 16157 + if (code_off == 0) return js_mkerr(js, "function has no code"); 16158 + jsval_t code_val = resolveprop(js, mkval(T_PROP, code_off)); 16159 + if (vtype(code_val) != T_STR) return js_mkerr(js, "function code not string"); 16160 + jsoff_t fnlen, fnoff = vstr(js, code_val, &fnlen); 16161 + const char *fn = (const char *) (&js->mem[fnoff]); 16162 + 16163 + jsoff_t fnpos = 1; 16164 + jsval_t saved_scope = js->scope; 16165 + jsoff_t scope_off = lkp(js, func_obj, "__scope", 7); 16166 + if (scope_off != 0) { 16167 + jsval_t closure_scope = resolveprop(js, mkval(T_PROP, scope_off)); 16168 + if (vtype(closure_scope) == T_OBJ) js->scope = closure_scope; 16169 + } 16170 + 16171 + uint8_t saved_flags = js->flags; 16172 + js->flags = 0; 16173 + mkscope(js); 16174 + js->flags = saved_flags; 16175 + int arg_idx = 0; 16176 + 16177 + while (fnpos < fnlen) { 16178 + fnpos = skiptonext(fn, fnlen, fnpos, NULL); 16179 + if (fnpos < fnlen && fn[fnpos] == ')') break; 16180 + jsoff_t identlen = 0; 16181 + uint8_t tok = parseident(&fn[fnpos], fnlen - fnpos, &identlen); 16182 + if (tok != TOK_IDENTIFIER) break; 16183 + jsval_t v = arg_idx < nargs ? args[arg_idx] : js_mkundef(); 16184 + setprop(js, js->scope, js_mkstr(js, &fn[fnpos], identlen), v); 16185 + arg_idx++; 16186 + fnpos = skiptonext(fn, fnlen, fnpos + identlen, NULL); 16187 + if (fnpos < fnlen && fn[fnpos] == ',') fnpos++; 16188 + } 16189 + 16190 + if (fnpos < fnlen && fn[fnpos] == ')') fnpos++; 16191 + fnpos = skiptonext(fn, fnlen, fnpos, NULL); 16192 + if (fnpos < fnlen && fn[fnpos] == '{') fnpos++; 16193 + size_t body_len = fnlen - fnpos - 1; 16194 + 16195 + jsval_t saved_this = js->this_val; 16196 + js->this_val = bound_this; 16197 + 16198 + js->flags = F_CALL; 16199 + jsval_t res = js_eval(js, &fn[fnpos], body_len); 16200 + if (!is_err(res) && !(js->flags & F_RETURN)) res = js_mkundef(); 16201 + 16202 + js->this_val = saved_this; 16203 + delscope(js); 16204 + js->scope = saved_scope; 16129 16205 return res; 16130 16206 } 16131 16207 return js_mkerr(js, "not a function");
+2
src/main.c
··· 32 32 #include "modules/performance.h" 33 33 #include "modules/uri.h" 34 34 #include "modules/url.h" 35 + #include "modules/reflect.h" 35 36 36 37 int js_result = EXIT_SUCCESS; 37 38 ··· 199 200 init_performance_module(); 200 201 init_uri_module(); 201 202 init_url_module(); 203 + init_reflect_module(); 202 204 203 205 ant_register_library(shell_library, "ant:shell", NULL); 204 206 ant_register_library(ffi_library, "ant:ffi", NULL);
+324
src/modules/reflect.c
··· 1 + #include <stdlib.h> 2 + #include <string.h> 3 + 4 + #include "ant.h" 5 + #include "runtime.h" 6 + #include "modules/reflect.h" 7 + 8 + static jsval_t reflect_get(struct js *js, jsval_t *args, int nargs) { 9 + if (nargs < 2) return js_mkundef(); 10 + 11 + jsval_t target = args[0]; 12 + jsval_t key = args[1]; 13 + 14 + int t = js_type(target); 15 + if (t != JS_OBJ && t != JS_FUNC) return js_mkundef(); 16 + 17 + if (js_type(key) != JS_STR) return js_mkundef(); 18 + 19 + char *key_str = js_getstr(js, key, NULL); 20 + if (!key_str) return js_mkundef(); 21 + 22 + return js_get(js, target, key_str); 23 + } 24 + 25 + static jsval_t reflect_set(struct js *js, jsval_t *args, int nargs) { 26 + if (nargs < 3) return js_mkfalse(); 27 + 28 + jsval_t target = args[0]; 29 + jsval_t key = args[1]; 30 + jsval_t value = args[2]; 31 + 32 + int t = js_type(target); 33 + if (t != JS_OBJ && t != JS_FUNC) return js_mkfalse(); 34 + 35 + if (js_type(key) != JS_STR) return js_mkfalse(); 36 + 37 + char *key_str = js_getstr(js, key, NULL); 38 + if (!key_str) return js_mkfalse(); 39 + 40 + js_set(js, target, key_str, value); 41 + return js_mktrue(); 42 + } 43 + 44 + static jsval_t reflect_has(struct js *js, jsval_t *args, int nargs) { 45 + if (nargs < 2) return js_mkfalse(); 46 + 47 + jsval_t target = args[0]; 48 + jsval_t key = args[1]; 49 + 50 + int t = js_type(target); 51 + if (t != JS_OBJ && t != JS_FUNC) return js_mkfalse(); 52 + 53 + if (js_type(key) != JS_STR) return js_mkfalse(); 54 + 55 + char *key_str = js_getstr(js, key, NULL); 56 + if (!key_str) return js_mkfalse(); 57 + 58 + jsval_t val = js_get(js, target, key_str); 59 + return js_type(val) != JS_UNDEF ? js_mktrue() : js_mkfalse(); 60 + } 61 + 62 + static jsval_t reflect_delete_property(struct js *js, jsval_t *args, int nargs) { 63 + if (nargs < 2) return js_mkfalse(); 64 + 65 + jsval_t target = args[0]; 66 + jsval_t key = args[1]; 67 + 68 + int t = js_type(target); 69 + if (t != JS_OBJ && t != JS_FUNC) return js_mkfalse(); 70 + 71 + if (js_type(key) != JS_STR) return js_mkfalse(); 72 + 73 + size_t key_len; 74 + char *key_str = js_getstr(js, key, &key_len); 75 + if (!key_str) return js_mkfalse(); 76 + 77 + jsval_t result = js_setprop(js, target, key, js_mkundef()); 78 + (void)result; 79 + 80 + return js_mktrue(); 81 + } 82 + 83 + static jsval_t reflect_own_keys(struct js *js, jsval_t *args, int nargs) { 84 + if (nargs < 1) return js_mkarr(js); 85 + 86 + jsval_t target = args[0]; 87 + 88 + int t = js_type(target); 89 + if (t != JS_OBJ && t != JS_FUNC) { 90 + return js_mkerr(js, "Reflect.ownKeys called on non-object"); 91 + } 92 + 93 + jsval_t temp_keys[256]; 94 + int count = 0; 95 + 96 + js_prop_iter_t iter = js_prop_iter_begin(js, target); 97 + const char *key; 98 + size_t key_len; 99 + jsval_t value; 100 + 101 + while (js_prop_iter_next(&iter, &key, &key_len, &value) && count < 256) { 102 + if (key_len >= 9 && memcmp(key, "__proto__", 9) == 0) continue; 103 + if (key_len >= 7 && memcmp(key, "__desc_", 7) == 0) continue; 104 + if (key_len >= 2 && key[0] == '_' && key[1] == '_') continue; 105 + 106 + temp_keys[count++] = js_mkstr(js, key, key_len); 107 + } 108 + js_prop_iter_end(&iter); 109 + 110 + jsval_t keys_arr = js_mkarr(js); 111 + for (int i = count - 1; i >= 0; i--) { 112 + js_arr_push(js, keys_arr, temp_keys[i]); 113 + } 114 + 115 + return keys_arr; 116 + } 117 + 118 + static jsval_t reflect_construct(struct js *js, jsval_t *args, int nargs) { 119 + if (nargs < 2) { 120 + return js_mkerr(js, "Reflect.construct requires at least 2 arguments"); 121 + } 122 + 123 + jsval_t target = args[0]; 124 + jsval_t args_arr = args[1]; 125 + 126 + if (js_type(target) != JS_FUNC) { 127 + return js_mkerr(js, "Reflect.construct: first argument must be a constructor"); 128 + } 129 + 130 + jsval_t length_val = js_get(js, args_arr, "length"); 131 + int arg_count = 0; 132 + if (js_type(length_val) == JS_NUM) { 133 + arg_count = (int)js_getnum(length_val); 134 + } 135 + 136 + jsval_t *call_args = NULL; 137 + if (arg_count > 0) { 138 + call_args = malloc(arg_count * sizeof(jsval_t)); 139 + if (!call_args) return js_mkerr(js, "Out of memory"); 140 + 141 + for (int i = 0; i < arg_count; i++) { 142 + char idx[16]; 143 + snprintf(idx, sizeof(idx), "%d", i); 144 + call_args[i] = js_get(js, args_arr, idx); 145 + } 146 + } 147 + 148 + jsval_t new_obj = js_mkobj(js); 149 + jsval_t result = js_call_with_this(js, target, new_obj, call_args, arg_count); 150 + 151 + if (call_args) free(call_args); 152 + 153 + if (js_type(result) == JS_OBJ || js_type(result) == JS_FUNC) { 154 + return result; 155 + } 156 + return new_obj; 157 + } 158 + 159 + static jsval_t reflect_apply(struct js *js, jsval_t *args, int nargs) { 160 + if (nargs < 3) { 161 + return js_mkerr(js, "Reflect.apply requires 3 arguments"); 162 + } 163 + 164 + jsval_t target = args[0]; 165 + jsval_t this_arg = args[1]; 166 + jsval_t args_arr = args[2]; 167 + 168 + if (js_type(target) != JS_FUNC) { 169 + return js_mkerr(js, "Reflect.apply: first argument must be a function"); 170 + } 171 + 172 + jsval_t length_val = js_get(js, args_arr, "length"); 173 + int arg_count = 0; 174 + if (js_type(length_val) == JS_NUM) { 175 + arg_count = (int)js_getnum(length_val); 176 + } 177 + 178 + jsval_t *call_args = NULL; 179 + if (arg_count > 0) { 180 + call_args = malloc(arg_count * sizeof(jsval_t)); 181 + if (!call_args) return js_mkerr(js, "Out of memory"); 182 + 183 + for (int i = 0; i < arg_count; i++) { 184 + char idx[16]; 185 + snprintf(idx, sizeof(idx), "%d", i); 186 + call_args[i] = js_get(js, args_arr, idx); 187 + } 188 + } 189 + 190 + jsval_t result = js_call_with_this(js, target, this_arg, call_args, arg_count); 191 + 192 + if (call_args) free(call_args); 193 + return result; 194 + } 195 + 196 + static jsval_t reflect_get_own_property_descriptor(struct js *js, jsval_t *args, int nargs) { 197 + if (nargs < 2) return js_mkundef(); 198 + 199 + jsval_t target = args[0]; 200 + jsval_t key = args[1]; 201 + 202 + int t = js_type(target); 203 + if (t != JS_OBJ && t != JS_FUNC) return js_mkundef(); 204 + 205 + if (js_type(key) != JS_STR) return js_mkundef(); 206 + 207 + char *key_str = js_getstr(js, key, NULL); 208 + if (!key_str) return js_mkundef(); 209 + 210 + jsval_t value = js_get(js, target, key_str); 211 + if (js_type(value) == JS_UNDEF) return js_mkundef(); 212 + 213 + jsval_t desc = js_mkobj(js); 214 + js_set(js, desc, "value", value); 215 + js_set(js, desc, "writable", js_mktrue()); 216 + js_set(js, desc, "enumerable", js_mktrue()); 217 + js_set(js, desc, "configurable", js_mktrue()); 218 + 219 + return desc; 220 + } 221 + 222 + static jsval_t reflect_define_property(struct js *js, jsval_t *args, int nargs) { 223 + if (nargs < 3) return js_mkfalse(); 224 + 225 + jsval_t target = args[0]; 226 + jsval_t key = args[1]; 227 + jsval_t descriptor = args[2]; 228 + 229 + int t = js_type(target); 230 + if (t != JS_OBJ && t != JS_FUNC) return js_mkfalse(); 231 + 232 + if (js_type(key) != JS_STR) return js_mkfalse(); 233 + if (js_type(descriptor) != JS_OBJ) return js_mkfalse(); 234 + 235 + char *key_str = js_getstr(js, key, NULL); 236 + if (!key_str) return js_mkfalse(); 237 + 238 + jsval_t value = js_get(js, descriptor, "value"); 239 + js_set(js, target, key_str, value); 240 + 241 + return js_mktrue(); 242 + } 243 + 244 + static jsval_t reflect_get_prototype_of(struct js *js, jsval_t *args, int nargs) { 245 + if (nargs < 1) { 246 + return js_mkerr(js, "Reflect.getPrototypeOf requires an argument"); 247 + } 248 + 249 + jsval_t target = args[0]; 250 + int t = js_type(target); 251 + 252 + if (t != JS_OBJ && t != JS_FUNC) { 253 + return js_mkerr(js, "Reflect.getPrototypeOf: argument must be an object"); 254 + } 255 + 256 + return js_get_proto(js, target); 257 + } 258 + 259 + static jsval_t reflect_set_prototype_of(struct js *js, jsval_t *args, int nargs) { 260 + if (nargs < 2) return js_mkfalse(); 261 + 262 + jsval_t target = args[0]; 263 + jsval_t proto = args[1]; 264 + 265 + int t = js_type(target); 266 + if (t != JS_OBJ && t != JS_FUNC) return js_mkfalse(); 267 + 268 + int pt = js_type(proto); 269 + if (pt != JS_OBJ && pt != JS_FUNC && pt != JS_NULL) return js_mkfalse(); 270 + 271 + js_set_proto(js, target, proto); 272 + return js_mktrue(); 273 + } 274 + 275 + static jsval_t reflect_is_extensible(struct js *js, jsval_t *args, int nargs) { 276 + if (nargs < 1) return js_mkfalse(); 277 + 278 + jsval_t target = args[0]; 279 + int t = js_type(target); 280 + 281 + if (t != JS_OBJ && t != JS_FUNC) return js_mkfalse(); 282 + 283 + jsval_t frozen = js_get(js, target, "__frozen__"); 284 + if (js_type(frozen) == JS_TRUE) return js_mkfalse(); 285 + 286 + jsval_t sealed = js_get(js, target, "__sealed__"); 287 + if (js_type(sealed) == JS_TRUE) return js_mkfalse(); 288 + 289 + return js_mktrue(); 290 + } 291 + 292 + static jsval_t reflect_prevent_extensions(struct js *js, jsval_t *args, int nargs) { 293 + if (nargs < 1) return js_mkfalse(); 294 + 295 + jsval_t target = args[0]; 296 + int t = js_type(target); 297 + 298 + if (t != JS_OBJ && t != JS_FUNC) return js_mkfalse(); 299 + 300 + js_set(js, target, "__sealed__", js_mktrue()); 301 + return js_mktrue(); 302 + } 303 + 304 + void init_reflect_module(void) { 305 + struct js *js = rt->js; 306 + jsval_t reflect_obj = js_mkobj(js); 307 + 308 + js_set(js, reflect_obj, "get", js_mkfun(reflect_get)); 309 + js_set(js, reflect_obj, "set", js_mkfun(reflect_set)); 310 + js_set(js, reflect_obj, "has", js_mkfun(reflect_has)); 311 + js_set(js, reflect_obj, "deleteProperty", js_mkfun(reflect_delete_property)); 312 + js_set(js, reflect_obj, "ownKeys", js_mkfun(reflect_own_keys)); 313 + js_set(js, reflect_obj, "construct", js_mkfun(reflect_construct)); 314 + js_set(js, reflect_obj, "apply", js_mkfun(reflect_apply)); 315 + js_set(js, reflect_obj, "getOwnPropertyDescriptor", js_mkfun(reflect_get_own_property_descriptor)); 316 + js_set(js, reflect_obj, "defineProperty", js_mkfun(reflect_define_property)); 317 + js_set(js, reflect_obj, "getPrototypeOf", js_mkfun(reflect_get_prototype_of)); 318 + js_set(js, reflect_obj, "setPrototypeOf", js_mkfun(reflect_set_prototype_of)); 319 + js_set(js, reflect_obj, "isExtensible", js_mkfun(reflect_is_extensible)); 320 + js_set(js, reflect_obj, "preventExtensions", js_mkfun(reflect_prevent_extensions)); 321 + 322 + js_set(js, reflect_obj, "@@toStringTag", js_mkstr(js, "Reflect", 7)); 323 + js_set(js, js_glob(js), "Reflect", reflect_obj); 324 + }