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.

write barrier for slots in pipes/writable/readable

+106 -57
+23 -20
src/ant.c
··· 11267 11267 return result; 11268 11268 } 11269 11269 11270 + static void js_mark_promise_rejection_handled_chain(ant_t *js, ant_value_t promise) { 11271 + ant_value_t current = promise; 11272 + 11273 + while (vtype(current) == T_PROMISE) { 11274 + ant_promise_state_t *pd = get_promise_data(js, current, false); 11275 + if (!pd) break; 11276 + 11277 + if (pd->unhandled_reported) js_fire_rejection_handled(js, current, pd->value); 11278 + pd->has_rejection_handler = true; 11279 + pd->unhandled_reported = false; 11280 + current = pd->trigger_parent; 11281 + } 11282 + } 11283 + 11270 11284 static inline ant_value_t js_get_thenable_then(ant_t *js, ant_value_t value) { 11271 11285 if (!is_object_type(value)) return js_mkundef(); 11272 11286 return js_getprop_fallback(js, value, "then"); ··· 11294 11308 return result; 11295 11309 } 11296 11310 11297 - if (pd->unhandled_reported) js_fire_rejection_handled(js, promise, pd->value); 11298 - pd->has_rejection_handler = true; 11299 - pd->unhandled_reported = false; 11300 - 11311 + js_mark_promise_rejection_handled_chain(js, promise); 11301 11312 if (pd->state == 0) gc_root_pending_promise(js_obj_ptr(js_as_obj(promise))); 11302 11313 else queue_promise_trigger(js, promise); 11303 11314 ··· 11405 11416 } 11406 11417 11407 11418 gc_write_barrier(js, js_obj_ptr(js_as_obj(val)), p); 11408 - if (src_pd->unhandled_reported) js_fire_rejection_handled(js, val, src_pd->value); 11419 + js_mark_promise_rejection_handled_chain(js, val); 11409 11420 11410 - src_pd->has_rejection_handler = true; 11411 - src_pd->unhandled_reported = false; 11412 - 11413 11421 if (src_pd->state == 0) gc_root_pending_promise(js_obj_ptr(js_as_obj(val))); 11414 11422 else queue_promise_trigger(js, val); 11415 11423 GC_ROOT_RESTORE(js, root_mark); ··· 11666 11674 GC_ROOT_RESTORE(js, root_mark); 11667 11675 return js_mkerr(js, "out of memory"); 11668 11676 } 11669 - 11677 + 11670 11678 gc_write_barrier(js, js_obj_ptr(js_as_obj(p)), nextP); 11671 11679 gc_write_barrier(js, js_obj_ptr(js_as_obj(p)), onFulfilled); 11672 11680 gc_write_barrier(js, js_obj_ptr(js_as_obj(p)), onRejected); 11673 - 11674 - if (vtype(onRejected) == T_FUNC || vtype(onRejected) == T_CFUNC) { 11675 - if (pd->unhandled_reported) js_fire_rejection_handled(js, p, pd->value); 11676 - pd->has_rejection_handler = true; 11677 - pd->unhandled_reported = false; 11678 - } 11679 - 11681 + 11682 + if (vtype(onRejected) == T_FUNC || vtype(onRejected) == T_CFUNC) 11683 + js_mark_promise_rejection_handled_chain(js, p); 11684 + 11680 11685 if (pd->state == 0) 11681 11686 gc_root_pending_promise(js_obj_ptr(p)); 11682 11687 } ··· 12469 12474 12470 12475 ant_promise_state_t *pd = get_promise_data(js, item, false); 12471 12476 if (pd) { 12472 - pd->has_rejection_handler = true; 12473 - pd->unhandled_reported = false; 12474 - 12477 + js_mark_promise_rejection_handled_chain(js, item); 12475 12478 if (pd->state == 1) { 12476 12479 promise_any_try_resolve(js, tracker, pd->value); 12477 12480 GC_ROOT_RESTORE(js, root_mark); ··· 12999 13002 13000 13003 ant_value_t module_ctx = js_get_execution_module_ctx(js); 13001 13004 ant_value_t import_meta = js_get_module_ctx_import_meta(js, module_ctx); 13002 - 13005 + 13003 13006 GC_ROOT_PIN(js, module_ctx); 13004 13007 GC_ROOT_PIN(js, import_meta); 13005 13008
+1 -1
src/silver/glue.c
··· 618 618 619 619 ant_value_t func_obj = mkobj(js, 0); 620 620 closure->func_obj = func_obj; 621 - ant_value_t module_ctx = js_module_eval_active_ctx(js); 621 + ant_value_t module_ctx = sv_get_current_closure_module_ctx(js, mkval(T_FUNC, (uintptr_t)parent_closure)); 622 622 623 623 js_mark_constructor(func_obj, !child->is_arrow && !child->is_method && !child->is_generator); 624 624 js_setprop(js, func_obj, js->length_str, tov((double)child->param_count));
+6 -1
src/silver/ops/coercion.h
··· 58 58 59 59 static inline ant_value_t sv_op_import(sv_vm_t *vm, ant_t *js) { 60 60 ant_value_t specifier = vm->stack[--vm->sp]; 61 - ant_value_t import_fn = js_getprop_fallback(js, js->global, "import"); 61 + ant_value_t import_fn = js_get_module_import_binding(js); 62 + 63 + if (vtype(import_fn) != T_FUNC && vtype(import_fn) != T_CFUNC) 64 + import_fn = js_getprop_fallback(js, js->global, "import"); 65 + 62 66 if (vtype(import_fn) == T_FUNC || vtype(import_fn) == T_CFUNC) { 63 67 ant_value_t result = sv_vm_call(vm, js, import_fn, js->global, &specifier, 1, NULL, false); 64 68 if (!is_err(result)) vm->stack[vm->sp++] = result; 65 69 return result; 66 70 } 71 + 67 72 vm->stack[vm->sp++] = mkval(T_UNDEF, 0); 68 73 return tov(0); 69 74 }
+12 -2
src/silver/ops/upvalues.h
··· 1 1 #ifndef SV_UPVALUES_H 2 2 #define SV_UPVALUES_H 3 3 4 + #include "internal.h" 5 + #include "descriptors.h" 4 6 #include "silver/engine.h" 5 - #include "descriptors.h" 6 7 7 8 static inline ant_value_t sv_setup_function_prototype_with_parent( 8 9 ant_t *js, ant_value_t func_obj, ··· 27 28 js_set_descriptor(js, func_obj, "prototype", 9, JS_DESC_W); 28 29 29 30 return js_mkundef(); 31 + } 32 + 33 + static inline ant_value_t sv_get_current_closure_module_ctx(ant_t *js, ant_value_t parent_func) { 34 + if (vtype(parent_func) == T_FUNC) { 35 + ant_value_t module_ctx = js_get_slot(js_func_obj(parent_func), SLOT_MODULE_CTX); 36 + if (is_object_type(module_ctx)) return module_ctx; 37 + } 38 + 39 + return js_module_eval_active_ctx(js); 30 40 } 31 41 32 42 static inline ant_value_t sv_op_get_upval( ··· 122 132 123 133 ant_value_t func_obj = mkobj(js, 0); 124 134 closure->func_obj = func_obj; 125 - ant_value_t module_ctx = js_module_eval_active_ctx(js); 135 + ant_value_t module_ctx = sv_get_current_closure_module_ctx(js, frame->callee); 126 136 127 137 js_mark_constructor(func_obj, !child->is_arrow && !child->is_method && !child->is_generator); 128 138 js_setprop(js, func_obj, js->length_str, tov((double)child->param_count));
+26 -15
src/streams/pipes.c
··· 5 5 #include "internal.h" 6 6 #include "descriptors.h" 7 7 8 + #include "gc/roots.h" 8 9 #include "silver/engine.h" 9 10 #include "modules/assert.h" 10 11 #include "modules/abort.h" ··· 12 13 #include "streams/readable.h" 13 14 #include "streams/writable.h" 14 15 #include "modules/structured-clone.h" 16 + 17 + typedef struct { 18 + bool settled; 19 + bool shutting_down; 20 + bool in_flight; 21 + bool prevent_close; 22 + bool prevent_abort; 23 + bool prevent_cancel; 24 + } pipe_state_t; 15 25 16 26 static void pipes_chain_promise( 17 27 ant_t *js, ant_value_t value, 18 28 ant_value_t on_resolve, ant_value_t on_reject 19 29 ) { 30 + GC_ROOT_SAVE(root_mark, js); 31 + GC_ROOT_PIN(js, value); 32 + GC_ROOT_PIN(js, on_resolve); 33 + GC_ROOT_PIN(js, on_reject); 34 + 20 35 ant_value_t promise = value; 36 + GC_ROOT_PIN(js, promise); 21 37 if (vtype(promise) != T_PROMISE) { 22 38 promise = js_mkpromise(js); 39 + GC_ROOT_PIN(js, promise); 23 40 js_resolve_promise(js, promise, value); 24 41 } 25 42 26 - js_promise_then(js, promise, on_resolve, on_reject); 43 + ant_value_t then_result = js_promise_then(js, promise, on_resolve, on_reject); 44 + GC_ROOT_PIN(js, then_result); 45 + promise_mark_handled(then_result); 46 + GC_ROOT_RESTORE(js, root_mark); 27 47 } 28 - 29 - typedef struct { 30 - bool settled; 31 - bool shutting_down; 32 - bool in_flight; 33 - bool prevent_close; 34 - bool prevent_abort; 35 - bool prevent_cancel; 36 - } pipe_state_t; 37 48 38 49 static void pipe_state_finalize(ant_t *js, ant_object_t *obj) { 39 50 if (!obj->extra_slots) return; ··· 93 104 94 105 js_reject_promise(js, new_closed, release_err); 95 106 promise_mark_handled(new_closed); 96 - js_set_slot(reader_obj, SLOT_RS_CLOSED, new_closed); 107 + js_set_slot_wb(js, reader_obj, SLOT_RS_CLOSED, new_closed); 97 108 js_set_slot(stream_obj, SLOT_CTOR, js_mkundef()); 98 109 js_set_slot(reader_obj, SLOT_ENTRIES, js_mkundef()); 99 110 } ··· 107 118 108 119 js_reject_promise(js, ready, rel_err); 109 120 promise_mark_handled(ready); 110 - js_set_slot(writer_obj, SLOT_WS_READY, ready); 121 + js_set_slot_wb(js, writer_obj, SLOT_WS_READY, ready); 111 122 112 123 ant_value_t closed = js_mkpromise(js); 113 124 js_reject_promise(js, closed, rel_err); 114 125 promise_mark_handled(closed); 115 - js_set_slot(writer_obj, SLOT_RS_CLOSED, closed); 126 + js_set_slot_wb(js, writer_obj, SLOT_RS_CLOSED, closed); 116 127 js_set_slot(ws_obj, SLOT_CTOR, js_mkundef()); 117 128 js_set_slot(writer_obj, SLOT_ENTRIES, js_mkundef()); 118 129 } ··· 705 716 706 717 if (is_b1) st->canceled1 = true; 707 718 else st->canceled2 = true; 708 - js_set_slot(state, reason_slot, reason); 719 + js_set_slot_wb(js, state, reason_slot, reason); 709 720 710 721 ant_value_t promise = js_mkpromise(js); 711 - js_set_slot(state, promise_slot, promise); 722 + js_set_slot_wb(js, state, promise_slot, promise); 712 723 713 724 if (st->done) { 714 725 js_resolve_promise(js, promise, js_mkundef());
+18 -8
src/streams/transform.c
··· 7 7 #include "internal.h" 8 8 #include "descriptors.h" 9 9 10 + #include "gc/roots.h" 10 11 #include "silver/engine.h" 11 12 #include "modules/assert.h" 12 13 #include "modules/symbol.h" ··· 180 181 js_set_slot(ts_obj, SLOT_WS_CLOSE, flushing ? js_true : js_false); 181 182 } 182 183 183 - static inline void ts_set_cancel_state(ant_value_t ts_obj, ant_value_t promise, bool started_by_abort, bool has_user_handler) { 184 - js_set_slot(ts_obj, SLOT_RS_CANCEL, promise); 184 + static inline void ts_set_cancel_state(ant_t *js, ant_value_t ts_obj, ant_value_t promise, bool started_by_abort, bool has_user_handler) { 185 + js_set_slot_wb(js, ts_obj, SLOT_RS_CANCEL, promise); 185 186 js_set_slot(ts_obj, SLOT_WS_ABORT, started_by_abort ? js_true : js_false); 186 187 js_set_slot(ts_obj, SLOT_RS_SIZE, js_mkundef()); 187 188 js_set_slot(ts_obj, SLOT_WS_WRITE, js_false); ··· 211 212 } 212 213 213 214 static void ts_chain_promise(ant_t *js, ant_value_t val, ant_value_t res_fn, ant_value_t rej_fn) { 215 + GC_ROOT_SAVE(root_mark, js); 216 + GC_ROOT_PIN(js, val); 217 + GC_ROOT_PIN(js, res_fn); 218 + GC_ROOT_PIN(js, rej_fn); 219 + 214 220 ant_value_t promise = val; 221 + GC_ROOT_PIN(js, promise); 215 222 if (vtype(promise) != T_PROMISE) { 216 223 promise = js_mkpromise(js); 224 + GC_ROOT_PIN(js, promise); 217 225 js_resolve_promise(js, promise, val); 218 226 } 219 227 220 228 ant_value_t then_result = js_promise_then(js, promise, res_fn, rej_fn); 229 + GC_ROOT_PIN(js, then_result); 221 230 promise_mark_handled(then_result); 231 + GC_ROOT_RESTORE(js, root_mark); 222 232 } 223 233 224 234 static void ts_error(ant_t *js, ant_value_t ts_obj, ant_value_t e) { ··· 261 271 if (vtype(bp) == T_PROMISE) js_resolve_promise(js, bp, js_mkundef()); 262 272 } 263 273 ant_value_t new_bp = js_mkpromise(js); 264 - js_set_slot(ts_obj, SLOT_AUX, new_bp); 274 + js_set_slot_wb(js, ts_obj, SLOT_AUX, new_bp); 265 275 ts_set_bp_flag(ts_obj, backpressure); 266 276 } 267 277 ··· 291 301 void ts_ctrl_error(ant_t *js, ant_value_t ctrl_obj, ant_value_t e) { 292 302 ant_value_t ts_obj = ts_ctrl_stream(ctrl_obj); 293 303 if (vtype(ts_cancel_promise(ts_obj)) == T_PROMISE && ts_cancel_has_user_handler(ts_obj)) 294 - js_set_slot(ts_obj, SLOT_RS_SIZE, e); 304 + js_set_slot_wb(js, ts_obj, SLOT_RS_SIZE, e); 295 305 ts_error(js, ts_obj, e); 296 306 ts_error_writable_and_unblock_write(js, ts_obj, e); 297 307 } ··· 389 399 390 400 ant_value_t p = js_mkpromise(js); 391 401 promise_mark_handled(p); 392 - ts_set_cancel_state(ts_obj, p, started_by_abort, is_callable(cancel_fn)); 402 + ts_set_cancel_state(js, ts_obj, p, started_by_abort, is_callable(cancel_fn)); 393 403 ts_ctrl_clear_algorithms(ts_controller(ts_obj)); 394 404 395 405 ant_value_t result = js_mkundef(); ··· 467 477 return js_mkundef(); 468 478 } 469 479 470 - if (ts_cancel_joined_abort(ts_obj)) js_set_slot(ts_obj, SLOT_RS_SIZE, reason); 480 + if (ts_cancel_joined_abort(ts_obj)) js_set_slot_wb(js, ts_obj, SLOT_RS_SIZE, reason); 471 481 ts_error(js, ts_obj, reason); 472 482 473 483 if (ts_cancel_joined_abort(ts_obj)) js_reject_promise(js, p, reason); ··· 549 559 550 560 ant_value_t finish_p = js_mkpromise(js); 551 561 promise_mark_handled(finish_p); 552 - js_set_slot(ctrl_obj, SLOT_RS_PULL, finish_p); 562 + js_set_slot_wb(js, ctrl_obj, SLOT_RS_PULL, finish_p); 553 563 554 564 if (ts_get_backpressure(ts_obj)) { 555 565 ant_value_t wrapper = js_mkobj(js); ··· 995 1005 js_set_slot(ts_obj, SLOT_CTOR, ws_obj); 996 1006 997 1007 ant_value_t bp_promise = js_mkpromise(js); 998 - js_set_slot(ts_obj, SLOT_AUX, bp_promise); 1008 + js_set_slot_wb(js, ts_obj, SLOT_AUX, bp_promise); 999 1009 1000 1010 ts_set_backpressure(js, ts_obj, true); 1001 1011
+20 -10
src/streams/writable.c
··· 7 7 #include "internal.h" 8 8 #include "descriptors.h" 9 9 10 + #include "gc/roots.h" 10 11 #include "silver/engine.h" 11 12 #include "modules/symbol.h" 12 13 #include "modules/assert.h" ··· 197 198 } 198 199 199 200 static void ws_chain_promise(ant_t *js, ant_value_t val, ant_value_t res_fn, ant_value_t rej_fn) { 201 + GC_ROOT_SAVE(root_mark, js); 202 + GC_ROOT_PIN(js, val); 203 + GC_ROOT_PIN(js, res_fn); 204 + GC_ROOT_PIN(js, rej_fn); 205 + 200 206 ant_value_t promise = val; 207 + GC_ROOT_PIN(js, promise); 201 208 if (vtype(promise) != T_PROMISE) { 202 209 promise = js_mkpromise(js); 210 + GC_ROOT_PIN(js, promise); 203 211 js_resolve_promise(js, promise, val); 204 212 } 205 213 206 214 ant_value_t then_result = js_promise_then(js, promise, res_fn, rej_fn); 215 + GC_ROOT_PIN(js, then_result); 207 216 promise_mark_handled(then_result); 217 + GC_ROOT_RESTORE(js, root_mark); 208 218 } 209 219 210 220 static void ws_default_controller_clear_algorithms(ant_value_t ctrl_obj) { ··· 238 248 ant_value_t ready = js_mkpromise(js); 239 249 js_reject_promise(js, ready, error); 240 250 promise_mark_handled(ready); 241 - js_set_slot(writer_obj, SLOT_WS_READY, ready); 251 + js_set_slot_wb(js, writer_obj, SLOT_WS_READY, ready); 242 252 } 243 253 244 254 static void ws_writer_replace_closed_promise_rejected(ant_t *js, ant_value_t writer_obj, ant_value_t error) { 245 255 ant_value_t closed = js_mkpromise(js); 246 256 js_reject_promise(js, closed, error); 247 257 promise_mark_handled(closed); 248 - js_set_slot(writer_obj, SLOT_RS_CLOSED, closed); 258 + js_set_slot_wb(js, writer_obj, SLOT_RS_CLOSED, closed); 249 259 } 250 260 251 261 static void ws_writer_reject_ready_promise(ant_t *js, ant_value_t writer_obj, ant_value_t error) { ··· 266 276 ws_controller_t *ctrl = ws_get_controller(ctrl_obj); 267 277 268 278 stream->state = WS_STATE_ERRORING; 269 - js_set_slot(stream_obj, SLOT_AUX, reason); 279 + js_set_slot_wb(js, stream_obj, SLOT_AUX, reason); 270 280 271 281 ant_value_t signal_ac = ws_ctrl_signal(ctrl_obj); 272 282 if (is_object_type(signal_ac)) { ··· 396 406 if (backpressure) { 397 407 ant_value_t ready = js_mkpromise(js); 398 408 promise_mark_handled(ready); 399 - js_set_slot(writer_obj, SLOT_WS_READY, ready); 409 + js_set_slot_wb(js, writer_obj, SLOT_WS_READY, ready); 400 410 } else { 401 411 ant_value_t ready = ws_writer_ready(writer_obj); 402 412 if (!is_undefined(ready)) js_resolve_promise(js, ready, js_mkundef()); ··· 453 463 454 464 static void writable_stream_mark_first_write_in_flight(ant_t *js, ant_value_t stream_obj) { 455 465 ant_value_t wr = ws_write_reqs_shift(js, stream_obj); 456 - js_set_slot(stream_obj, SLOT_DEFAULT, wr); 466 + js_set_slot_wb(js, stream_obj, SLOT_DEFAULT, wr); 457 467 } 458 468 459 - static void writable_stream_mark_close_in_flight(ant_value_t stream_obj) { 469 + static void writable_stream_mark_close_in_flight(ant_t *js, ant_value_t stream_obj) { 460 470 ant_value_t cr = ws_stream_close_request(stream_obj); 461 - js_set_slot(stream_obj, SLOT_WS_ABORT, cr); 471 + js_set_slot_wb(js, stream_obj, SLOT_WS_ABORT, cr); 462 472 js_set_slot(stream_obj, SLOT_WS_CLOSE, js_mkundef()); 463 473 } 464 474 ··· 546 556 547 557 static void ws_default_controller_process_close(ant_t *js, ant_value_t ctrl_obj) { 548 558 ant_value_t stream_obj = ws_ctrl_stream(ctrl_obj); 549 - writable_stream_mark_close_in_flight(stream_obj); 559 + writable_stream_mark_close_in_flight(js, stream_obj); 550 560 551 561 ws_ctrl_queue_shift(js, ctrl_obj); 552 562 ws_controller_t *ctrl = ws_get_controller(ctrl_obj); ··· 664 674 } 665 675 666 676 ant_value_t promise = js_mkpromise(js); 667 - js_set_slot(stream_obj, SLOT_WS_CLOSE, promise); 677 + js_set_slot_wb(js, stream_obj, SLOT_WS_CLOSE, promise); 668 678 669 679 ant_value_t writer_obj = ws_stream_writer(stream_obj); 670 680 if (ws_is_writer(writer_obj) && stream->backpressure && stream->state == WS_STATE_WRITABLE) { ··· 747 757 ant_value_t promise = js_mkpromise(js); 748 758 stream->has_pending_abort = true; 749 759 stream->pending_abort_was_already_erroring = was_already_erroring; 750 - js_set_slot(stream_obj, SLOT_WS_READY, promise); 760 + js_set_slot_wb(js, stream_obj, SLOT_WS_READY, promise); 751 761 752 762 if (!was_already_erroring) 753 763 writable_stream_start_erroring(js, stream_obj, reason);