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.

WinterTC global scaffolding

+441 -41
+5
include/errors.h
··· 32 32 void js_set_error_site_from_vm_top(ant_t *js); 33 33 void js_capture_stack(ant_t *js, ant_value_t err_obj); 34 34 35 + void js_get_call_location( 36 + ant_t *js, const char **out_filename, 37 + int *out_line, int *out_col 38 + ); 39 + 35 40 void js_set_error_site_from_bc( 36 41 ant_t *js, sv_func_t *func, 37 42 int bc_offset, const char *filename
+3 -1
include/modules/events.h
··· 3 3 4 4 #include "types.h" 5 5 6 - void init_events_module(void); 7 6 ant_value_t events_library(ant_t *js); 7 + 8 + void init_events_module(void); 9 + void js_dispatch_global_event(ant_t *js, ant_value_t event_obj); 8 10 9 11 #endif
+14
include/modules/globals.h
··· 1 + #ifndef ANT_GLOBALS_MODULE_H 2 + #define ANT_GLOBALS_MODULE_H 3 + 4 + #include "types.h" 5 + 6 + void init_globals_module(void); 7 + 8 + ant_value_t js_structured_clone(ant_t *js, ant_value_t *args, int nargs); 9 + ant_value_t js_report_error(ant_t *js, ant_value_t *args, int nargs); 10 + 11 + bool js_fire_unhandled_rejection(ant_t *js, ant_value_t promise_val, ant_value_t reason); 12 + void js_fire_rejection_handled(ant_t *js, ant_value_t promise_val, ant_value_t reason); 13 + 14 + #endif
+1 -2
package.json
··· 2 2 "name": "ant", 3 3 "type": "module", 4 4 "scripts": { 5 - "spec": "./build/ant examples/spec/run.js", 6 - "wpt": "sh -c './build/ant tools/wpt/runner.js wpt/dom/$1.any.js' --" 5 + "spec": "./build/ant examples/spec/run.js" 7 6 }, 8 7 "dependencies": {}, 9 8 "devDependencies": {}
+5 -1
src/ant.c
··· 60 60 #include "modules/collections.h" 61 61 #include "modules/lmdb.h" 62 62 #include "modules/regex.h" 63 + #include "modules/globals.h" 63 64 64 65 #define D(x) ((double)(x)) 65 66 ··· 10049 10050 gc_write_barrier(js, js_obj_ptr(js_as_obj(p)), onRejected); 10050 10051 10051 10052 if (vtype(onRejected) == T_FUNC || vtype(onRejected) == T_CFUNC) { 10053 + if (pd->unhandled_reported) js_fire_rejection_handled(js, p, pd->value); 10052 10054 pd->has_rejection_handler = true; 10053 10055 pd->unhandled_reported = false; 10054 10056 } ··· 12577 12579 js_destroy(js); exit(1); 12578 12580 } 12579 12581 12580 - print_unhandled_promise_rejection(js, pd->value); 12582 + ant_value_t promise_val = mkval(T_PROMISE, (uintptr_t)obj); 12583 + if (!js_fire_unhandled_rejection(js, promise_val, pd->value)) 12584 + print_unhandled_promise_rejection(js, pd->value); 12581 12585 pd->unhandled_reported = true; 12582 12586 }} 12583 12587
+14
src/errors.c
··· 606 606 js->errsite.valid = (src != NULL && src_len >= 0); 607 607 } 608 608 609 + void js_get_call_location(ant_t *js, const char **out_filename, int *out_line, int *out_col) { 610 + if (!js) return; 611 + if (!js->errsite.valid) js_set_error_site_from_vm_top(js); 612 + 613 + if (out_filename) *out_filename = (js->errsite.valid && js->errsite.filename) ? js->errsite.filename : js->filename; 614 + if (out_line) *out_line = 1; 615 + if (out_col) *out_col = 1; 616 + 617 + if (js->errsite.valid && js->errsite.src) get_line_col( 618 + js->errsite.src, js->errsite.src_len, 619 + js->errsite.off, out_line, out_col 620 + ); 621 + } 622 + 609 623 void js_clear_error_site(ant_t *js) { 610 624 if (!js) return; 611 625 memset(&js->errsite, 0, sizeof(js->errsite));
+2
src/main.c
··· 71 71 #include "modules/assert.h" 72 72 #include "modules/domexception.h" 73 73 #include "modules/abort.h" 74 + #include "modules/globals.h" 74 75 #include "modules/v8.h" 75 76 #include "modules/worker_threads.h" 76 77 ··· 577 578 init_symbol_module(); 578 579 init_timer_module(); 579 580 init_domexception_module(); 581 + init_globals_module(); 580 582 init_abort_module(); 581 583 init_math_module(); 582 584 init_bigint_module();
+53 -37
src/modules/abort.c
··· 58 58 return make_dom_exception(js, "signal timed out", "TimeoutError"); 59 59 } 60 60 61 - void signal_do_abort(ant_t *js, ant_value_t signal_obj, ant_value_t reason) { 61 + static void signal_mark_aborted(ant_t *js, ant_value_t signal_obj, ant_value_t reason) { 62 62 abort_signal_data_t *data = get_signal_data(signal_obj); 63 63 if (!data || data->aborted) return; 64 - 64 + 65 65 data->aborted = true; 66 66 data->fired = true; 67 67 data->reason = reason; 68 + 69 + js_set(js, signal_obj, "aborted", js_true); 70 + js_set(js, signal_obj, "reason", reason); 71 + } 72 + 73 + void signal_do_abort(ant_t *js, ant_value_t signal_obj, ant_value_t reason) { 74 + abort_signal_data_t *data = get_signal_data(signal_obj); 75 + if (!data || data->aborted) return; 68 76 69 - js_set(js, signal_obj, "aborted", js_true); 70 - js_set(js, signal_obj, "reason", reason); 77 + UT_array *queue; utarray_new(queue, &abort_value_icd); 78 + UT_array *to_fire; utarray_new(to_fire, &abort_value_icd); 79 + 80 + utarray_push_back(queue, &signal_obj); 81 + 82 + for (unsigned int qi = 0; qi < utarray_len(queue); qi++) { 83 + ant_value_t *cur = (ant_value_t *)utarray_eltptr(queue, qi); 84 + abort_signal_data_t *d = get_signal_data(*cur); 85 + if (!d || d->aborted) continue; 86 + 87 + d->aborted = true; 88 + d->fired = true; 89 + d->reason = reason; 90 + js_set(js, *cur, "aborted", js_true); 91 + js_set(js, *cur, "reason", reason); 92 + utarray_push_back(to_fire, cur); 93 + 94 + unsigned int nf = utarray_len(d->followers); 95 + for (unsigned int i = 0; i < nf; i++) { 96 + ant_value_t *sig = (ant_value_t *)utarray_eltptr(d->followers, i); 97 + utarray_push_back(queue, sig); 98 + }} 99 + utarray_free(queue); 100 + 101 + for (unsigned int qi = 0; qi < utarray_len(to_fire); qi++) { 102 + ant_value_t *cur = (ant_value_t *)utarray_eltptr(to_fire, qi); 103 + abort_signal_data_t *d = get_signal_data(*cur); 104 + if (!d) continue; 71 105 72 106 ant_value_t event_obj = js_mkobj(js); 73 - js_set(js, event_obj, "type", js_mkstr(js, "abort", 5)); 74 - js_set(js, event_obj, "target", signal_obj); 107 + js_set(js, event_obj, "type", js_mkstr(js, "abort", 5)); 108 + js_set(js, event_obj, "target", *cur); 75 109 ant_value_t call_args[1] = { event_obj }; 76 110 77 - ant_value_t onabort = js_get(js, signal_obj, "onabort"); 111 + ant_value_t onabort = js_get(js, *cur, "onabort"); 78 112 if (vtype(onabort) == T_FUNC) { 79 - sv_vm_call(js->vm, js, onabort, signal_obj, call_args, 1, NULL, false); 113 + sv_vm_call(js->vm, js, onabort, *cur, call_args, 1, NULL, false); 80 114 process_microtasks(js); 81 115 } 82 116 83 - unsigned int n = utarray_len(data->listeners); 117 + unsigned int n = utarray_len(d->listeners); 84 118 for (unsigned int i = 0; i < n;) { 85 - abort_listener_t *entry = (abort_listener_t *)utarray_eltptr(data->listeners, i); 86 - ant_value_t cb = entry->callback; 87 - bool once = entry->once; 88 - 89 - if (once) { 90 - utarray_erase(data->listeners, i, 1); 91 - n--; 92 - } else i++; 93 - 119 + abort_listener_t *entry = (abort_listener_t *)utarray_eltptr(d->listeners, i); 120 + ant_value_t cb = entry->callback; 121 + bool once = entry->once; 122 + if (once) { utarray_erase(d->listeners, i, 1); n--; } else i++; 94 123 if (vtype(cb) != T_FUNC) continue; 95 - sv_vm_call(js->vm, js, cb, signal_obj, call_args, 1, NULL, false); 124 + sv_vm_call(js->vm, js, cb, *cur, call_args, 1, NULL, false); 96 125 process_microtasks(js); 97 - } 98 - 99 - unsigned int nf = utarray_len(data->followers); 100 - for (unsigned int i = 0; i < nf; i++) { 101 - ant_value_t *sig = (ant_value_t *)utarray_eltptr(data->followers, i); 102 - signal_do_abort(js, *sig, reason); 103 - } 126 + }} 127 + utarray_free(to_fire); 104 128 } 105 129 106 130 static ant_value_t make_new_signal(ant_t *js) { ··· 135 159 136 160 abort_signal_data_t *data = get_signal_data(js_getthis(js)); 137 161 if (!data) return js_mkundef(); 138 - 139 - if (data->aborted) { 140 - ant_value_t event_obj = js_mkobj(js); 141 - js_set(js, event_obj, "type", js_mkstr(js, "abort", 5)); 142 - js_set(js, event_obj, "target", js_getthis(js)); 143 - ant_value_t call_args[1] = { event_obj }; 144 - sv_vm_call(js->vm, js, args[1], js_getthis(js), call_args, 1, NULL, false); 145 - return js_mkundef(); 146 - } 162 + if (data->aborted) return js_mkundef(); 147 163 148 164 bool once = false; 149 165 if (nargs >= 3 && vtype(args[2]) == T_OBJ) { ··· 217 233 ant_value_t signal = make_new_signal(js); 218 234 if (is_err(signal)) return signal; 219 235 220 - signal_do_abort(js, signal, reason); 236 + signal_mark_aborted(js, signal, reason); 221 237 return signal; 222 238 } 223 239 ··· 234 250 ant_value_t sig = js_arr_get(js, args[0], i); 235 251 abort_signal_data_t *d = get_signal_data(sig); 236 252 if (d && d->aborted) { 237 - signal_do_abort(js, composite, d->reason); 253 + signal_mark_aborted(js, composite, d->reason); 238 254 return composite; 239 255 }} 240 256
+19
src/modules/events.c
··· 251 251 return dispatch_event_to(js, args, nargs, find_global_event_type(event_type), js_mkundef()); 252 252 } 253 253 254 + void js_dispatch_global_event(ant_t *js, ant_value_t event_obj) { 255 + ant_value_t type_val = js_get(js, event_obj, "type"); 256 + const char *event_type = js_getstr(js, type_val, NULL); 257 + if (!event_type) return; 258 + 259 + EventType *evt = find_global_event_type(event_type); 260 + if (!evt || evt->listener_count == 0) return; 261 + 262 + js_set(js, event_obj, "target", js_glob(js)); 263 + ant_value_t call_args[1] = { event_obj }; 264 + 265 + for (int i = 0; i < evt->listener_count;) { 266 + EventListener *listener = &evt->listeners[i]; 267 + sv_vm_call(js->vm, js, listener->listener, js_mkundef(), call_args, 1, NULL, false); 268 + if (listener->once) remove_listener_at(evt, i); 269 + else i++; 270 + } 271 + } 272 + 254 273 static ant_value_t js_get_event_listeners(ant_t *js, ant_value_t *args, int nargs) { 255 274 EventType *evt, *tmp; 256 275 ant_value_t result = js_mkobj(js);
+316
src/modules/globals.c
··· 1 + #include <string.h> 2 + #include <stdio.h> 3 + #include <stdlib.h> 4 + #include <inttypes.h> 5 + 6 + #include "ant.h" 7 + #include "errors.h" 8 + #include "runtime.h" 9 + #include "internal.h" 10 + #include "descriptors.h" 11 + #include "silver/engine.h" 12 + 13 + #include "modules/buffer.h" 14 + #include "modules/events.h" 15 + #include "modules/collections.h" 16 + #include "modules/domexception.h" 17 + #include "modules/globals.h" 18 + 19 + ant_value_t js_report_error(ant_t *js, ant_value_t *args, int nargs) { 20 + if (nargs < 1) return js_mkerr_typed(js, JS_ERR_TYPE, "reportError requires 1 argument"); 21 + 22 + ant_value_t error = args[0]; 23 + ant_value_t global = js_glob(js); 24 + 25 + const char *msg = ""; 26 + uint8_t et = vtype(error); 27 + 28 + if (et == T_STR) { 29 + msg = js_str(js, error); 30 + } else if (et == T_OBJ) { 31 + const char *m = get_str_prop(js, error, "message", 7, NULL); 32 + if (m && *m) msg = m; 33 + } 34 + 35 + if (!*msg) { 36 + ant_value_t str = js_tostring_val(js, error); 37 + if (vtype(str) == T_STR) { const char *s = js_str(js, str); if (s) msg = s; } 38 + } 39 + 40 + const char *filename = ""; 41 + int lineno = 1, colno = 1; 42 + js_get_call_location(js, &filename, &lineno, &colno); 43 + if (!filename) filename = ""; 44 + 45 + ant_value_t loc = js_get(js, global, "location"); 46 + if (vtype(loc) == T_OBJ) { 47 + const char *href = get_str_prop(js, loc, "href", 4, NULL); 48 + if (href && *href) filename = href; 49 + } 50 + 51 + ant_value_t event = js_mkobj(js); 52 + js_set(js, event, "type", js_mkstr(js, "error", 5)); 53 + js_set(js, event, "message", js_mkstr(js, msg, strlen(msg))); 54 + js_set(js, event, "filename", js_mkstr(js, filename, strlen(filename))); 55 + js_set(js, event, "lineno", js_mknum(lineno)); 56 + js_set(js, event, "colno", js_mknum(colno)); 57 + js_set(js, event, "error", error); 58 + 59 + js_dispatch_global_event(js, event); 60 + ant_value_t handler = js_get(js, global, "onerror"); 61 + 62 + uint8_t ht = vtype(handler); 63 + if (ht == T_FUNC || ht == T_CFUNC) { 64 + ant_value_t msg_str = js_mkstr(js, msg, strlen(msg)); 65 + ant_value_t file_str = js_mkstr(js, filename, strlen(filename)); 66 + ant_value_t call_args[5] = { msg_str, file_str, js_mknum(lineno), js_mknum(colno), error }; 67 + sv_vm_call(js->vm, js, handler, global, call_args, 5, NULL, false); 68 + } 69 + 70 + return js_mkundef(); 71 + } 72 + 73 + bool js_fire_unhandled_rejection(ant_t *js, ant_value_t promise_val, ant_value_t reason) { 74 + ant_value_t global = js_glob(js); 75 + ant_value_t handler = js_get(js, global, "onunhandledrejection"); 76 + 77 + uint8_t ht = vtype(handler); 78 + if (ht != T_FUNC && ht != T_CFUNC) return false; 79 + 80 + ant_value_t event = js_mkobj(js); 81 + js_set(js, event, "type", js_mkstr(js, "unhandledrejection", 18)); 82 + js_set(js, event, "reason", reason); 83 + js_set(js, event, "promise", promise_val); 84 + 85 + ant_value_t call_args[1] = { event }; 86 + sv_vm_call(js->vm, js, handler, global, call_args, 1, NULL, false); 87 + 88 + return true; 89 + } 90 + 91 + void js_fire_rejection_handled(ant_t *js, ant_value_t promise_val, ant_value_t reason) { 92 + ant_value_t global = js_glob(js); 93 + ant_value_t handler = js_get(js, global, "onrejectionhandled"); 94 + 95 + uint8_t ht = vtype(handler); 96 + if (ht != T_FUNC && ht != T_CFUNC) return; 97 + 98 + ant_value_t event = js_mkobj(js); 99 + js_set(js, event, "type", js_mkstr(js, "rejectionhandled", 16)); 100 + js_set(js, event, "reason", reason); 101 + js_set(js, event, "promise", promise_val); 102 + 103 + ant_value_t call_args[1] = { event }; 104 + sv_vm_call(js->vm, js, handler, global, call_args, 1, NULL, false); 105 + } 106 + 107 + static void sc_add_seen(ant_t *js, ant_value_t seen, ant_value_t val, ant_value_t clone) { 108 + char key[24]; 109 + snprintf(key, sizeof(key), "%" PRIxPTR, (uintptr_t)vdata(val)); 110 + js_set(js, seen, key, clone); 111 + } 112 + 113 + static ant_value_t sc_lookup_seen(ant_t *js, ant_value_t seen, ant_value_t val) { 114 + char key[24]; 115 + snprintf(key, sizeof(key), "%" PRIxPTR, (uintptr_t)vdata(val)); 116 + ant_value_t found = js_get(js, seen, key); 117 + return (vtype(found) == T_UNDEF) ? js_mkundef() : found; 118 + } 119 + 120 + static const char *sc_ta_type_name(TypedArrayType type) { 121 + static const char *names[] = { 122 + "Int8Array", "Uint8Array", "Uint8ClampedArray", 123 + "Int16Array", "Uint16Array", 124 + "Int32Array", "Uint32Array", 125 + "Float32Array", "Float64Array", 126 + "BigInt64Array", "BigUint64Array" 127 + }; 128 + int i = (int)type; 129 + if (i < 0 || i > 10) return "Uint8Array"; 130 + return names[i]; 131 + } 132 + 133 + static ant_value_t sc_clone_rec(ant_t *js, ant_value_t val, ant_value_t seen) { 134 + uint8_t t = vtype(val); 135 + 136 + if (t == T_UNDEF || t == T_NULL || t == T_BOOL || t == T_NUM || t == T_BIGINT || t == T_STR) return val; 137 + if (t == T_SYMBOL) return js_throw(js, make_dom_exception(js, "Symbol cannot be serialized", "DataCloneError")); 138 + 139 + if (t == T_TYPEDARRAY) { 140 + ant_value_t existing = sc_lookup_seen(js, seen, val); 141 + if (vtype(existing) != T_UNDEF) return existing; 142 + 143 + TypedArrayData *ta = (TypedArrayData *)js_gettypedarray(val); 144 + if (!ta || !ta->buffer) 145 + return js_throw(js, make_dom_exception(js, "TypedArray could not be cloned", "DataCloneError")); 146 + 147 + ArrayBufferData *new_buf = create_array_buffer_data(ta->byte_length); 148 + if (!new_buf) return js_mkerr(js, "out of memory"); 149 + if (ta->byte_length > 0) memcpy(new_buf->data, ta->buffer->data + ta->byte_offset, ta->byte_length); 150 + 151 + ant_value_t clone = create_typed_array(js, ta->type, new_buf, 0, ta->length, sc_ta_type_name(ta->type)); 152 + sc_add_seen(js, seen, val, clone); 153 + 154 + return clone; 155 + } 156 + 157 + if (t == T_FUNC || t == T_CFUNC || t == T_CLOSURE) 158 + return js_throw(js, make_dom_exception(js, "() => {} could not be cloned", "DataCloneError")); 159 + if (t == T_PROMISE || t == T_GENERATOR) 160 + return js_throw(js, make_dom_exception(js, "Value could not be cloned", "DataCloneError")); 161 + if (!is_object_type(val)) 162 + return js_throw(js, make_dom_exception(js, "Value could not be cloned", "DataCloneError")); 163 + 164 + ant_value_t existing = sc_lookup_seen(js, seen, val); 165 + if (vtype(existing) != T_UNDEF) return existing; 166 + 167 + if (t == T_ARR) { 168 + ant_value_t clone = js_mkarr(js); 169 + sc_add_seen(js, seen, val, clone); 170 + 171 + ant_offset_t len = js_arr_len(js, val); 172 + for (ant_offset_t i = 0; i < len; i++) { 173 + ant_value_t ic = sc_clone_rec(js, js_arr_get(js, val, i), seen); 174 + if (is_err(ic)) return ic; 175 + js_arr_push(js, clone, ic); 176 + } 177 + 178 + return clone; 179 + } 180 + 181 + ant_object_t *obj_ptr = js_obj_ptr(val); 182 + if (!obj_ptr) 183 + return js_throw(js, make_dom_exception(js, "Value could not be cloned", "DataCloneError")); 184 + 185 + if (obj_ptr->type_tag == T_WEAKMAP || obj_ptr->type_tag == T_WEAKSET) 186 + return js_throw(js, make_dom_exception(js, "WeakMap/WeakSet could not be cloned", "DataCloneError")); 187 + 188 + if (obj_ptr->type_tag == T_MAP) { 189 + ant_value_t clone = js_mkobj(js); 190 + js_obj_ptr(clone)->type_tag = T_MAP; 191 + 192 + ant_value_t map_proto = js_get_ctor_proto(js, "Map", 3); 193 + if (is_special_object(map_proto)) js_set_proto_init(clone, map_proto); 194 + 195 + map_entry_t **new_head = ant_calloc(sizeof(map_entry_t *)); 196 + if (!new_head) return js_mkerr(js, "out of memory"); 197 + 198 + *new_head = NULL; 199 + js_set_slot(clone, SLOT_DATA, ANT_PTR(new_head)); 200 + sc_add_seen(js, seen, val, clone); 201 + 202 + map_entry_t **src_head = get_map_from_obj(js, val); 203 + if (src_head && *src_head) { 204 + map_entry_t *e, *tmp; 205 + HASH_ITER(hh, *src_head, e, tmp) { 206 + ant_value_t vc = sc_clone_rec(js, e->value, seen); 207 + if (is_err(vc)) return vc; 208 + 209 + map_entry_t *ne = ant_calloc(sizeof(map_entry_t)); 210 + if (!ne) return js_mkerr(js, "out of memory"); 211 + ne->key = strdup(e->key); 212 + ne->value = vc; 213 + HASH_ADD_STR(*new_head, key, ne); 214 + }} 215 + 216 + return clone; 217 + } 218 + 219 + if (obj_ptr->type_tag == T_SET) { 220 + ant_value_t clone = js_mkobj(js); 221 + js_obj_ptr(clone)->type_tag = T_SET; 222 + 223 + ant_value_t set_proto = js_get_ctor_proto(js, "Set", 3); 224 + if (is_special_object(set_proto)) js_set_proto_init(clone, set_proto); 225 + 226 + set_entry_t **new_head = ant_calloc(sizeof(set_entry_t *)); 227 + if (!new_head) return js_mkerr(js, "out of memory"); 228 + *new_head = NULL; 229 + js_set_slot(clone, SLOT_DATA, ANT_PTR(new_head)); 230 + sc_add_seen(js, seen, val, clone); 231 + 232 + set_entry_t **src_head = get_set_from_obj(js, val); 233 + if (src_head && *src_head) { 234 + set_entry_t *e, *tmp; 235 + HASH_ITER(hh, *src_head, e, tmp) { 236 + ant_value_t vc = sc_clone_rec(js, e->value, seen); 237 + if (is_err(vc)) return vc; 238 + 239 + set_entry_t *ne = ant_calloc(sizeof(set_entry_t)); 240 + if (!ne) return js_mkerr(js, "out of memory"); 241 + ne->key = strdup(e->key); 242 + ne->value = vc; 243 + HASH_ADD_STR(*new_head, key, ne); 244 + }} 245 + 246 + return clone; 247 + } 248 + 249 + if (js_get_slot(val, SLOT_ERROR_BRAND) == js_true) { 250 + ant_value_t clone = js_mkobj(js); 251 + sc_add_seen(js, seen, val, clone); 252 + 253 + const char *msg = get_str_prop(js, val, "message", 7, NULL); 254 + const char *name = get_str_prop(js, val, "name", 4, NULL); 255 + const char *stack = get_str_prop(js, val, "stack", 5, NULL); 256 + 257 + if (msg) js_set(js, clone, "message", js_mkstr(js, msg, strlen(msg))); 258 + if (name) js_set(js, clone, "name", js_mkstr(js, name, strlen(name))); 259 + if (stack) js_set(js, clone, "stack", js_mkstr(js, stack, strlen(stack))); 260 + js_set_slot(clone, SLOT_ERROR_BRAND, js_true); 261 + 262 + ant_value_t err_type = js_get_slot(val, SLOT_ERR_TYPE); 263 + if (vtype(err_type) != T_UNDEF) js_set_slot(clone, SLOT_ERR_TYPE, err_type); 264 + 265 + return clone; 266 + } 267 + 268 + ant_value_t date_proto = js_get_ctor_proto(js, "Date", 4); 269 + if ( 270 + vtype(date_proto) != T_UNDEF 271 + && is_object_type(date_proto) 272 + && js_is_prototype_of(js, date_proto, val) 273 + ) { 274 + ant_value_t clone = js_mkobj(js); 275 + js_set_proto_init(clone, date_proto); 276 + js_set_slot(clone, SLOT_DATA, js_get_slot(val, SLOT_DATA)); 277 + sc_add_seen(js, seen, val, clone); 278 + 279 + return clone; 280 + } 281 + 282 + ant_value_t clone = js_mkobj(js); 283 + sc_add_seen(js, seen, val, clone); 284 + 285 + ant_iter_t iter = js_prop_iter_begin(js, val); 286 + const char *key; 287 + size_t key_len; 288 + ant_value_t pval; 289 + 290 + while (js_prop_iter_next(&iter, &key, &key_len, &pval)) { 291 + ant_value_t pc = sc_clone_rec(js, pval, seen); 292 + if (is_err(pc)) { js_prop_iter_end(&iter); return pc; } 293 + js_set(js, clone, key, pc); 294 + } 295 + 296 + js_prop_iter_end(&iter); 297 + return clone; 298 + } 299 + 300 + ant_value_t js_structured_clone(ant_t *js, ant_value_t *args, int nargs) { 301 + if (nargs < 1) return js_mkundef(); 302 + // TODO: transfer option (args[1]) accepted but not yet implemented 303 + ant_value_t seen = js_mkobj(js); 304 + return sc_clone_rec(js, args[0], seen); 305 + } 306 + 307 + void init_globals_module(void) { 308 + ant_t *js = rt->js; 309 + ant_value_t global = js_glob(js); 310 + 311 + js_set(js, global, "reportError", js_mkfun(js_report_error)); 312 + js_set_descriptor(js, global, "reportError", 11, JS_DESC_W | JS_DESC_C); 313 + 314 + js_set(js, global, "structuredClone", js_mkfun(js_structured_clone)); 315 + js_set_descriptor(js, global, "structuredClone", 15, JS_DESC_W | JS_DESC_C); 316 + }
+9
src/runtime.c
··· 172 172 .pid = (int)ant_getpid(), 173 173 .ls_fp = (ls_p && ls_p->count > 0) ? ls_p->filename[0] : NULL, 174 174 }; 175 + 176 + js_set(js, global, "onerror", js_mknull()); 177 + js_set_descriptor(js, global, "onerror", 7, JS_DESC_W | JS_DESC_C); 178 + 179 + js_set(js, global, "onunhandledrejection", js_mknull()); 180 + js_set_descriptor(js, global, "onunhandledrejection", 20, JS_DESC_W | JS_DESC_C); 181 + 182 + js_set(js, global, "onrejectionhandled", js_mknull()); 183 + js_set_descriptor(js, global, "onrejectionhandled", 18, JS_DESC_W | JS_DESC_C); 175 184 176 185 js_set(js, global, "self", global); 177 186 js_set_descriptor(js, global, "self", 4, JS_DESC_W | JS_DESC_C);