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.

at mir/inline-method 338 lines 10 kB view raw
1#include <stdlib.h> 2#include <string.h> 3 4#include "ant.h" 5#include "errors.h" 6#include "runtime.h" 7#include "internal.h" 8#include "silver/engine.h" 9 10#include "modules/reflect.h" 11#include "modules/symbol.h" 12 13static ant_value_t reflect_get(ant_t *js, ant_value_t *args, int nargs) { 14 if (nargs < 2) return js_mkundef(); 15 16 ant_value_t target = args[0]; 17 ant_value_t key = args[1]; 18 19 if (!is_object_type(target)) return js_mkundef(); 20 21 ant_value_t prop_key = key; 22 if (is_object_type(prop_key)) { 23 prop_key = js_to_primitive(js, prop_key, 1); 24 if (is_err(prop_key)) return prop_key; 25 } 26 27 if (vtype(prop_key) == T_SYMBOL) 28 return js_get_sym(js, target, prop_key); 29 30 if (vtype(prop_key) != T_STR) { 31 prop_key = js_tostring_val(js, prop_key); 32 if (is_err(prop_key)) return prop_key; 33 } 34 35 char *key_str = js_getstr(js, prop_key, NULL); 36 if (!key_str) return js_mkundef(); 37 38 return js_get(js, target, key_str); 39} 40 41static ant_value_t reflect_set(ant_t *js, ant_value_t *args, int nargs) { 42 if (nargs < 3) return js_false; 43 44 ant_value_t target = args[0]; 45 ant_value_t key = args[1]; 46 ant_value_t value = args[2]; 47 48 int t = vtype(target); 49 if (t != T_OBJ && t != T_FUNC) return js_false; 50 51 if (vtype(key) != T_STR) return js_false; 52 53 char *key_str = js_getstr(js, key, NULL); 54 if (!key_str) return js_false; 55 56 js_set(js, target, key_str, value); 57 return js_true; 58} 59 60static ant_value_t reflect_has(ant_t *js, ant_value_t *args, int nargs) { 61 if (nargs < 2) return js_false; 62 63 ant_value_t target = args[0]; 64 ant_value_t key = args[1]; 65 66 int t = vtype(target); 67 if (t != T_OBJ && t != T_FUNC) return js_false; 68 69 if (vtype(key) != T_STR) return js_false; 70 71 size_t key_len; 72 char *key_str = js_getstr(js, key, &key_len); 73 if (!key_str) return js_false; 74 75 ant_offset_t off = lkp_proto(js, target, key_str, key_len); 76 return js_bool(off > 0); 77} 78 79static ant_value_t reflect_delete_property(ant_t *js, ant_value_t *args, int nargs) { 80 if (nargs < 2) return js_false; 81 82 ant_value_t target = args[0]; 83 ant_value_t key = args[1]; 84 85 int t = vtype(target); 86 if (t != T_OBJ && t != T_FUNC) return js_false; 87 88 if (vtype(key) != T_STR) return js_false; 89 90 char *key_str = js_getstr(js, key, NULL); 91 if (!key_str) return js_false; 92 93 ant_value_t del_result = js_delete_prop(js, target, key_str, strlen(key_str)); 94 bool deleted = !is_err(del_result) && js_truthy(js, del_result); 95 return js_bool(deleted); 96} 97 98static ant_value_t reflect_own_keys(ant_t *js, ant_value_t *args, int nargs) { 99 if (nargs < 1) return js_mkarr(js); 100 101 ant_value_t target = args[0]; 102 103 int t = vtype(target); 104 if (t != T_OBJ && t != T_FUNC) { 105 return js_mkerr(js, "Reflect.ownKeys called on non-object"); 106 } 107 108 ant_value_t keys_arr = js_mkarr(js); 109 ant_iter_t iter = js_prop_iter_begin(js, target); 110 const char *key; size_t key_len; ant_value_t value; 111 112 while (js_prop_iter_next(&iter, &key, &key_len, &value)) { 113 js_arr_push(js, keys_arr, js_mkstr(js, key, key_len)); 114 } 115 116 js_prop_iter_end(&iter); 117 return keys_arr; 118} 119 120static ant_value_t reflect_construct(ant_t *js, ant_value_t *args, int nargs) { 121 if (nargs < 2) { 122 return js_mkerr(js, "Reflect.construct requires at least 2 arguments"); 123 } 124 125 ant_value_t target = args[0]; 126 ant_value_t args_arr = args[1]; 127 ant_value_t new_target = (nargs >= 3) ? args[2] : target; 128 129 if (vtype(target) != T_FUNC && vtype(target) != T_CFUNC) { 130 return js_mkerr(js, "Reflect.construct: first argument must be a constructor"); 131 } 132 133 if (vtype(new_target) != T_FUNC && vtype(new_target) != T_CFUNC) { 134 return js_mkerr(js, "Reflect.construct: third argument must be a constructor"); 135 } 136 137 ant_value_t length_val = js_get(js, args_arr, "length"); 138 int arg_count = 0; 139 if (vtype(length_val) == T_NUM) { 140 arg_count = (int)js_getnum(length_val); 141 } 142 143 ant_value_t *call_args = NULL; 144 if (arg_count > 0) { 145 call_args = malloc(arg_count * sizeof(ant_value_t)); 146 if (!call_args) return js_mkerr(js, "Out of memory"); 147 148 for (int i = 0; i < arg_count; i++) { 149 char idx[16]; 150 snprintf(idx, sizeof(idx), "%d", i); 151 call_args[i] = js_get(js, args_arr, idx); 152 } 153 } 154 155 ant_value_t new_obj = js_mkobj(js); 156 ant_value_t proto = js_get(js, new_target, "prototype"); 157 if (vtype(proto) == T_OBJ) js_set_proto_init(new_obj, proto); 158 159 ant_value_t saved_new_target = js->new_target; 160 js->new_target = new_target; 161 162 ant_value_t result = sv_vm_call(js->vm, js, target, new_obj, call_args, arg_count, NULL, true); 163 js->new_target = saved_new_target; 164 165 if (call_args) free(call_args); 166 if (is_object_type(result)) return result; 167 168 return new_obj; 169} 170 171static ant_value_t reflect_apply(ant_t *js, ant_value_t *args, int nargs) { 172 if (nargs < 3) { 173 return js_mkerr(js, "Reflect.apply requires 3 arguments"); 174 } 175 176 ant_value_t target = args[0]; 177 ant_value_t this_arg = args[1]; 178 ant_value_t args_arr = args[2]; 179 180 if (vtype(target) != T_FUNC && vtype(target) != T_CFUNC) { 181 return js_mkerr(js, "Reflect.apply: first argument must be a function"); 182 } 183 184 if (vtype(args_arr) == T_UNDEF || vtype(args_arr) == T_NULL) return js_mkerr_typed( 185 js, JS_ERR_TYPE, 186 "Reflect.apply: third argument must be an array-like object" 187 ); 188 189 ant_value_t result; 190 if (vtype(args_arr) == T_ARR) { 191 ant_value_t *call_args = NULL; 192 int arg_count = extract_array_args(js, args_arr, &call_args); 193 result = sv_vm_call_explicit_this( 194 js->vm, js, target, this_arg, 195 call_args, arg_count 196 ); 197 if (call_args) free(call_args); 198 return result; 199 } 200 201 ant_value_t length_val = js_get(js, args_arr, "length"); 202 int arg_count = 0; 203 if (vtype(length_val) == T_NUM) { 204 arg_count = (int)js_getnum(length_val); 205 } 206 207 ant_value_t *call_args = NULL; 208 if (arg_count > 0) { 209 call_args = malloc(arg_count * sizeof(ant_value_t)); 210 if (!call_args) return js_mkerr(js, "Out of memory"); 211 212 for (int i = 0; i < arg_count; i++) { 213 char idx[16]; 214 snprintf(idx, sizeof(idx), "%d", i); 215 call_args[i] = js_get(js, args_arr, idx); 216 } 217 } 218 219 result = sv_vm_call_explicit_this( 220 js->vm, js, target, this_arg, 221 call_args, arg_count 222 ); 223 224 if (call_args) free(call_args); 225 return result; 226} 227 228static ant_value_t reflect_get_own_property_descriptor(ant_t *js, ant_value_t *args, int nargs) { 229 if (nargs < 2) return js_mkundef(); 230 231 ant_value_t target = args[0]; 232 ant_value_t key = args[1]; 233 234 int t = vtype(target); 235 if (t != T_OBJ && t != T_FUNC) return js_mkundef(); 236 237 if (vtype(key) != T_STR) return js_mkundef(); 238 239 size_t key_len; 240 char *key_str = js_getstr(js, key, &key_len); 241 if (!key_str) return js_mkundef(); 242 243 ant_offset_t off = lkp(js, target, key_str, key_len); 244 if (off <= 0) return js_mkundef(); 245 246 ant_value_t value = js_get(js, target, key_str); 247 ant_value_t desc = js_mkobj(js); 248 js_set(js, desc, "value", value); 249 js_set(js, desc, "writable", js_true); 250 js_set(js, desc, "enumerable", js_true); 251 js_set(js, desc, "configurable", js_true); 252 253 return desc; 254} 255 256static ant_value_t reflect_define_property(ant_t *js, ant_value_t *args, int nargs) { 257 if (nargs < 3) return js_false; 258 return js_define_property(js, args[0], args[1], args[2], true); 259} 260 261static ant_value_t reflect_get_prototype_of(ant_t *js, ant_value_t *args, int nargs) { 262 if (nargs < 1) { 263 return js_mkerr(js, "Reflect.getPrototypeOf requires an argument"); 264 } 265 266 ant_value_t target = args[0]; 267 268 if (!is_object_type(target)) { 269 return js_mkerr(js, "Reflect.getPrototypeOf: argument must be an object"); 270 } 271 272 return js_get_proto(js, target); 273} 274 275static ant_value_t reflect_set_prototype_of(ant_t *js, ant_value_t *args, int nargs) { 276 if (nargs < 2) return js_false; 277 278 ant_value_t target = args[0]; 279 ant_value_t proto = args[1]; 280 281 if (!is_object_type(target)) return js_false; 282 if (!is_object_type(proto) && vtype(proto) != T_NULL) return js_false; 283 if (vtype(proto) != T_NULL && proto_chain_contains(js, proto, target)) return js_false; 284 285 js_set_proto_wb(js, target, proto); 286 287 return js_true; 288} 289 290static ant_value_t reflect_is_extensible(ant_t *js, ant_value_t *args, int nargs) { 291 if (nargs < 1) return js_false; 292 293 ant_value_t target = args[0]; 294 int t = vtype(target); 295 296 if (t != T_OBJ && t != T_FUNC) return js_false; 297 298 ant_object_t *obj = js_obj_ptr(js_as_obj(target)); 299 if (!obj) return js_false; 300 if (obj->frozen || obj->sealed) return js_false; 301 return js_bool(obj->extensible); 302} 303 304static ant_value_t reflect_prevent_extensions(ant_t *js, ant_value_t *args, int nargs) { 305 if (nargs < 1) return js_false; 306 307 ant_value_t target = args[0]; 308 int t = vtype(target); 309 310 if (t != T_OBJ && t != T_FUNC) return js_false; 311 312 ant_object_t *obj = js_obj_ptr(js_as_obj(target)); 313 if (!obj) return js_false; 314 obj->extensible = 0; 315 return js_true; 316} 317 318void init_reflect_module(void) { 319 ant_t *js = rt->js; 320 ant_value_t reflect_obj = js_mkobj(js); 321 322 js_set(js, reflect_obj, "get", js_mkfun(reflect_get)); 323 js_set(js, reflect_obj, "set", js_mkfun(reflect_set)); 324 js_set(js, reflect_obj, "has", js_mkfun(reflect_has)); 325 js_set(js, reflect_obj, "deleteProperty", js_mkfun(reflect_delete_property)); 326 js_set(js, reflect_obj, "ownKeys", js_mkfun(reflect_own_keys)); 327 js_set(js, reflect_obj, "construct", js_mkfun(reflect_construct)); 328 js_set(js, reflect_obj, "apply", js_mkfun(reflect_apply)); 329 js_set(js, reflect_obj, "getOwnPropertyDescriptor", js_mkfun(reflect_get_own_property_descriptor)); 330 js_set(js, reflect_obj, "defineProperty", js_mkfun(reflect_define_property)); 331 js_set(js, reflect_obj, "getPrototypeOf", js_mkfun(reflect_get_prototype_of)); 332 js_set(js, reflect_obj, "setPrototypeOf", js_mkfun(reflect_set_prototype_of)); 333 js_set(js, reflect_obj, "isExtensible", js_mkfun(reflect_is_extensible)); 334 js_set(js, reflect_obj, "preventExtensions", js_mkfun(reflect_prevent_extensions)); 335 336 js_set_sym(js, reflect_obj, get_toStringTag_sym(), js_mkstr(js, "Reflect", 7)); 337 js_set(js, js_glob(js), "Reflect", reflect_obj); 338}