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.

add WritableStream

+1306 -8
+5
include/common.h
··· 66 66 SLOT_RS_CANCEL, 67 67 SLOT_RS_SIZE, 68 68 SLOT_RS_CLOSED, 69 + SLOT_WS_WRITE, 70 + SLOT_WS_CLOSE, 71 + SLOT_WS_ABORT, 72 + SLOT_WS_READY, 73 + SLOT_WS_SIGNAL, 69 74 SLOT_MAX = 255 70 75 } internal_slot_t; 71 76
+1
include/gc/modules.h
··· 22 22 void gc_mark_abort(ant_t *js, gc_mark_fn mark); 23 23 void gc_mark_domexception(ant_t *js, gc_mark_fn mark); 24 24 void gc_mark_readable_streams(ant_t *js, gc_mark_fn mark); 25 + void gc_mark_writable_streams(ant_t *js, gc_mark_fn mark); 25 26 26 27 #endif
+8
include/streams/readable.h
··· 31 31 void init_readable_stream_module(void); 32 32 void gc_mark_readable_streams(ant_t *js, void (*mark)(ant_t *, ant_value_t)); 33 33 34 + rs_stream_t *rs_get_stream(ant_value_t obj); 35 + ant_value_t rs_stream_controller(ant_t *js, ant_value_t stream_obj); 36 + ant_value_t rs_stream_reader(ant_value_t stream_obj); 37 + 38 + void readable_stream_close(ant_t *js, ant_value_t stream_obj); 39 + void readable_stream_error(ant_t *js, ant_value_t stream_obj, ant_value_t e); 40 + ant_value_t readable_stream_cancel(ant_t *js, ant_value_t stream_obj, ant_value_t reason); 41 + 34 42 #endif
+45
include/streams/writable.h
··· 1 + #ifndef STREAMS_WRITABLE_H 2 + #define STREAMS_WRITABLE_H 3 + 4 + #include "types.h" 5 + #include <stdbool.h> 6 + #include <stddef.h> 7 + 8 + typedef enum { 9 + WS_STATE_WRITABLE = 0, 10 + WS_STATE_CLOSED, 11 + WS_STATE_ERRORING, 12 + WS_STATE_ERRORED, 13 + } ws_state_t; 14 + 15 + typedef struct { 16 + double *queue_sizes; 17 + uint32_t queue_sizes_len; 18 + uint32_t queue_sizes_cap; 19 + double queue_total_size; 20 + double strategy_hwm; 21 + bool close_requested; 22 + bool started; 23 + } ws_controller_t; 24 + 25 + typedef struct { 26 + ws_state_t state; 27 + bool backpressure; 28 + bool has_pending_abort; 29 + bool pending_abort_was_already_erroring; 30 + } ws_stream_t; 31 + 32 + void init_writable_stream_module(void); 33 + void gc_mark_writable_streams(ant_t *js, void (*mark)(ant_t *, ant_value_t)); 34 + 35 + ws_stream_t *ws_get_stream(ant_value_t obj); 36 + ant_value_t ws_stream_controller(ant_value_t stream_obj); 37 + ant_value_t ws_stream_writer(ant_value_t stream_obj); 38 + 39 + ant_value_t writable_stream_close(ant_t *js, ant_value_t stream_obj); 40 + ant_value_t writable_stream_abort(ant_t *js, ant_value_t stream_obj, ant_value_t reason); 41 + 42 + bool writable_stream_close_queued_or_in_flight(ant_value_t stream_obj); 43 + void ws_default_controller_error(ant_t *js, ant_value_t ctrl_obj, ant_value_t error); 44 + 45 + #endif
+1
src/gc/objects.c
··· 455 455 gc_mark_abort(js, gc_mark_value); 456 456 gc_mark_domexception(js, gc_mark_value); 457 457 gc_mark_readable_streams(js, gc_mark_value); 458 + gc_mark_writable_streams(js, gc_mark_value); 458 459 459 460 for ( 460 461 ant_object_t *obj = g_pending_promises;
+2
src/main.c
··· 81 81 #include "modules/formdata.h" 82 82 #include "streams/queuing.h" 83 83 #include "streams/readable.h" 84 + #include "streams/writable.h" 84 85 85 86 int js_result = EXIT_SUCCESS; 86 87 typedef int (*cmd_fn)(int argc, char **argv); ··· 599 600 init_collections_module(); 600 601 init_queuing_strategies_module(); 601 602 init_readable_stream_module(); 603 + init_writable_stream_module(); 602 604 init_builtin_module(); 603 605 init_buffer_module(); 604 606 init_fs_module();
+6 -8
src/streams/readable.c
··· 15 15 static ant_value_t g_reader_proto; 16 16 static ant_value_t g_controller_proto; 17 17 18 - static rs_stream_t *rs_get_stream(ant_value_t obj) { 18 + rs_stream_t *rs_get_stream(ant_value_t obj) { 19 19 ant_value_t s = js_get_slot(obj, SLOT_DATA); 20 20 if (vtype(s) != T_NUM) return NULL; 21 21 return (rs_stream_t *)(uintptr_t)(size_t)js_getnum(s); ··· 49 49 }} 50 50 } 51 51 52 - static inline ant_value_t rs_stream_controller(ant_t *js, ant_value_t stream_obj) { 52 + ant_value_t rs_stream_controller(ant_t *js, ant_value_t stream_obj) { 53 53 return js_get_slot(stream_obj, SLOT_ENTRIES); 54 54 } 55 55 56 - static inline ant_value_t rs_stream_reader(ant_value_t stream_obj) { 56 + ant_value_t rs_stream_reader(ant_value_t stream_obj) { 57 57 return js_get_slot(stream_obj, SLOT_CTOR); 58 58 } 59 59 ··· 141 141 } 142 142 143 143 static void rs_default_controller_call_pull_if_needed(ant_t *js, ant_value_t controller_obj); 144 - static void readable_stream_close(ant_t *js, ant_value_t stream_obj); 145 - static void readable_stream_error(ant_t *js, ant_value_t stream_obj, ant_value_t e); 146 144 static bool rs_default_controller_can_close_or_enqueue(rs_controller_t *ctrl, rs_stream_t *stream); 147 145 148 146 static void rs_default_controller_clear_algorithms(ant_value_t ctrl_obj) { ··· 196 194 aobj->u.array.len = 0; 197 195 } 198 196 199 - static void readable_stream_close(ant_t *js, ant_value_t stream_obj) { 197 + void readable_stream_close(ant_t *js, ant_value_t stream_obj) { 200 198 rs_stream_t *stream = rs_get_stream(stream_obj); 201 199 if (!stream) return; 202 200 stream->state = RS_STATE_CLOSED; ··· 217 215 } 218 216 } 219 217 220 - static void readable_stream_error(ant_t *js, ant_value_t stream_obj, ant_value_t e) { 218 + void readable_stream_error(ant_t *js, ant_value_t stream_obj, ant_value_t e) { 221 219 rs_stream_t *stream = rs_get_stream(stream_obj); 222 220 if (!stream || stream->state != RS_STATE_READABLE) return; 223 221 stream->state = RS_STATE_ERRORED; ··· 242 240 return js_mkundef(); 243 241 } 244 242 245 - static ant_value_t readable_stream_cancel(ant_t *js, ant_value_t stream_obj, ant_value_t reason) { 243 + ant_value_t readable_stream_cancel(ant_t *js, ant_value_t stream_obj, ant_value_t reason) { 246 244 rs_stream_t *stream = rs_get_stream(stream_obj); 247 245 if (!stream) return js_mkundef(); 248 246 stream->disturbed = true;
+1238
src/streams/writable.c
··· 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 "descriptors.h" 9 + 10 + #include "silver/engine.h" 11 + #include "modules/symbol.h" 12 + #include "streams/writable.h" 13 + 14 + static ant_value_t g_ws_proto; 15 + static ant_value_t g_writer_proto; 16 + static ant_value_t g_controller_proto; 17 + static ant_value_t g_close_sentinel; 18 + 19 + ws_stream_t *ws_get_stream(ant_value_t obj) { 20 + ant_value_t s = js_get_slot(obj, SLOT_DATA); 21 + if (vtype(s) != T_NUM) return NULL; 22 + return (ws_stream_t *)(uintptr_t)(size_t)js_getnum(s); 23 + } 24 + 25 + static ws_controller_t *ws_get_controller(ant_value_t obj) { 26 + ant_value_t s = js_get_slot(obj, SLOT_DATA); 27 + if (vtype(s) != T_NUM) return NULL; 28 + return (ws_controller_t *)(uintptr_t)(size_t)js_getnum(s); 29 + } 30 + 31 + static void ws_stream_finalize(ant_t *js, ant_object_t *obj) { 32 + if (!obj->extra_slots) return; 33 + ant_extra_slot_t *entries = (ant_extra_slot_t *)obj->extra_slots; 34 + for (uint8_t i = 0; i < obj->extra_count; i++) { 35 + if (entries[i].slot == SLOT_DATA && vtype(entries[i].value) == T_NUM) { 36 + free((ws_stream_t *)(uintptr_t)(size_t)js_getnum(entries[i].value)); 37 + return; 38 + }} 39 + } 40 + 41 + static void ws_controller_finalize(ant_t *js, ant_object_t *obj) { 42 + if (!obj->extra_slots) return; 43 + ant_extra_slot_t *entries = (ant_extra_slot_t *)obj->extra_slots; 44 + for (uint8_t i = 0; i < obj->extra_count; i++) { 45 + if (entries[i].slot == SLOT_DATA && vtype(entries[i].value) == T_NUM) { 46 + ws_controller_t *ctrl = (ws_controller_t *)(uintptr_t)(size_t)js_getnum(entries[i].value); 47 + free(ctrl->queue_sizes); 48 + free(ctrl); 49 + return; 50 + }} 51 + } 52 + 53 + ant_value_t ws_stream_controller(ant_value_t stream_obj) { 54 + return js_get_slot(stream_obj, SLOT_ENTRIES); 55 + } 56 + 57 + ant_value_t ws_stream_writer(ant_value_t stream_obj) { 58 + return js_get_slot(stream_obj, SLOT_CTOR); 59 + } 60 + 61 + static inline ant_value_t ws_stream_stored_error(ant_value_t stream_obj) { 62 + return js_get_slot(stream_obj, SLOT_BUFFER); 63 + } 64 + 65 + static inline ant_value_t ws_stream_write_requests(ant_t *js, ant_value_t stream_obj) { 66 + return js_get_slot(stream_obj, SLOT_SETTLED); 67 + } 68 + 69 + static inline ant_value_t ws_stream_in_flight_write(ant_value_t stream_obj) { 70 + return js_get_slot(stream_obj, SLOT_DEFAULT); 71 + } 72 + 73 + static inline ant_value_t ws_stream_close_request(ant_value_t stream_obj) { 74 + return js_get_slot(stream_obj, SLOT_WS_CLOSE); 75 + } 76 + 77 + static inline ant_value_t ws_stream_in_flight_close(ant_value_t stream_obj) { 78 + return js_get_slot(stream_obj, SLOT_WS_ABORT); 79 + } 80 + 81 + static inline ant_value_t ws_stream_pending_abort_promise(ant_value_t stream_obj) { 82 + return js_get_slot(stream_obj, SLOT_WS_READY); 83 + } 84 + 85 + static inline ant_value_t ws_ctrl_stream(ant_value_t ctrl_obj) { 86 + return js_get_slot(ctrl_obj, SLOT_ENTRIES); 87 + } 88 + 89 + static inline ant_value_t ws_ctrl_write_fn(ant_value_t ctrl_obj) { 90 + return js_get_slot(ctrl_obj, SLOT_WS_WRITE); 91 + } 92 + 93 + static inline ant_value_t ws_ctrl_close_fn(ant_value_t ctrl_obj) { 94 + return js_get_slot(ctrl_obj, SLOT_WS_CLOSE); 95 + } 96 + 97 + static inline ant_value_t ws_ctrl_abort_fn(ant_value_t ctrl_obj) { 98 + return js_get_slot(ctrl_obj, SLOT_WS_ABORT); 99 + } 100 + 101 + static inline ant_value_t ws_ctrl_size_fn(ant_value_t ctrl_obj) { 102 + return js_get_slot(ctrl_obj, SLOT_RS_SIZE); 103 + } 104 + 105 + static inline ant_value_t ws_ctrl_queue(ant_value_t ctrl_obj) { 106 + return js_get_slot(ctrl_obj, SLOT_BUFFER); 107 + } 108 + 109 + static inline ant_value_t ws_ctrl_signal(ant_value_t ctrl_obj) { 110 + return js_get_slot(ctrl_obj, SLOT_WS_SIGNAL); 111 + } 112 + 113 + static inline ant_value_t ws_writer_stream(ant_value_t writer_obj) { 114 + return js_get_slot(writer_obj, SLOT_ENTRIES); 115 + } 116 + 117 + static inline ant_value_t ws_writer_closed(ant_value_t writer_obj) { 118 + return js_get_slot(writer_obj, SLOT_RS_CLOSED); 119 + } 120 + 121 + static inline ant_value_t ws_writer_ready(ant_value_t writer_obj) { 122 + return js_get_slot(writer_obj, SLOT_WS_READY); 123 + } 124 + 125 + static void ws_ctrl_queue_push(ant_t *js, ant_value_t ctrl_obj, ant_value_t value) { 126 + ant_value_t arr = ws_ctrl_queue(ctrl_obj); 127 + if (vtype(arr) == T_ARR) js_arr_push(js, arr, value); 128 + } 129 + 130 + static ant_value_t ws_ctrl_queue_shift(ant_t *js, ant_value_t ctrl_obj) { 131 + ant_value_t arr = ws_ctrl_queue(ctrl_obj); 132 + if (vtype(arr) != T_ARR) return js_mkundef(); 133 + ant_object_t *aobj = js_obj_ptr(arr); 134 + if (aobj->u.array.len == 0) return js_mkundef(); 135 + ant_value_t val = aobj->u.array.data[0]; 136 + uint32_t new_len = aobj->u.array.len - 1; 137 + for (uint32_t i = 0; i < new_len; i++) 138 + aobj->u.array.data[i] = aobj->u.array.data[i + 1]; 139 + aobj->u.array.len = new_len; 140 + return val; 141 + } 142 + 143 + static ant_value_t ws_ctrl_queue_peek(ant_t *js, ant_value_t ctrl_obj) { 144 + ant_value_t arr = ws_ctrl_queue(ctrl_obj); 145 + if (vtype(arr) != T_ARR) return js_mkundef(); 146 + ant_object_t *aobj = js_obj_ptr(arr); 147 + if (aobj->u.array.len == 0) return js_mkundef(); 148 + return aobj->u.array.data[0]; 149 + } 150 + 151 + static bool ws_ctrl_queue_empty(ant_value_t ctrl_obj) { 152 + ant_value_t arr = ws_ctrl_queue(ctrl_obj); 153 + if (vtype(arr) != T_ARR) return true; 154 + ant_object_t *aobj = js_obj_ptr(arr); 155 + return aobj->u.array.len == 0; 156 + } 157 + 158 + static void ws_write_reqs_push(ant_t *js, ant_value_t stream_obj, ant_value_t promise) { 159 + ant_value_t arr = ws_stream_write_requests(js, stream_obj); 160 + if (vtype(arr) == T_ARR) js_arr_push(js, arr, promise); 161 + } 162 + 163 + static ant_value_t ws_write_reqs_shift(ant_t *js, ant_value_t stream_obj) { 164 + ant_value_t arr = ws_stream_write_requests(js, stream_obj); 165 + if (vtype(arr) != T_ARR) return js_mkundef(); 166 + ant_object_t *aobj = js_obj_ptr(arr); 167 + if (aobj->u.array.len == 0) return js_mkundef(); 168 + ant_value_t val = aobj->u.array.data[0]; 169 + uint32_t new_len = aobj->u.array.len - 1; 170 + for (uint32_t i = 0; i < new_len; i++) 171 + aobj->u.array.data[i] = aobj->u.array.data[i + 1]; 172 + aobj->u.array.len = new_len; 173 + return val; 174 + } 175 + 176 + static void ws_default_controller_advance_queue_if_needed(ant_t *js, ant_value_t ctrl_obj); 177 + static void writable_stream_finish_erroring(ant_t *js, ant_value_t stream_obj); 178 + static void writable_stream_start_erroring(ant_t *js, ant_value_t stream_obj, ant_value_t reason); 179 + static void writable_stream_deal_with_rejection(ant_t *js, ant_value_t stream_obj, ant_value_t error); 180 + static void writable_stream_update_backpressure(ant_t *js, ant_value_t stream_obj, bool backpressure); 181 + static ant_value_t js_ws_writer_ctor(ant_t *js, ant_value_t *args, int nargs); 182 + 183 + static void ws_default_controller_clear_algorithms(ant_value_t ctrl_obj) { 184 + js_set_slot(ctrl_obj, SLOT_WS_WRITE, js_mkundef()); 185 + js_set_slot(ctrl_obj, SLOT_WS_CLOSE, js_mkundef()); 186 + js_set_slot(ctrl_obj, SLOT_WS_ABORT, js_mkundef()); 187 + js_set_slot(ctrl_obj, SLOT_RS_SIZE, js_mkundef()); 188 + } 189 + 190 + static double ws_default_controller_get_desired_size(ws_controller_t *ctrl) { 191 + return ctrl->strategy_hwm - ctrl->queue_total_size; 192 + } 193 + 194 + static bool ws_default_controller_get_backpressure(ws_controller_t *ctrl) { 195 + return ws_default_controller_get_desired_size(ctrl) <= 0; 196 + } 197 + 198 + bool writable_stream_close_queued_or_in_flight(ant_value_t stream_obj) { 199 + ant_value_t cr = ws_stream_close_request(stream_obj); 200 + ant_value_t icr = ws_stream_in_flight_close(stream_obj); 201 + return !is_undefined(cr) || !is_undefined(icr); 202 + } 203 + 204 + static bool writable_stream_has_operation_in_flight(ant_value_t stream_obj) { 205 + ant_value_t iw = ws_stream_in_flight_write(stream_obj); 206 + ant_value_t ic = ws_stream_in_flight_close(stream_obj); 207 + return !is_undefined(iw) || !is_undefined(ic); 208 + } 209 + 210 + static void ws_writer_ensure_ready_promise_rejected(ant_t *js, ant_value_t writer_obj, ant_value_t error) { 211 + ant_value_t ready = ws_writer_ready(writer_obj); 212 + if (is_undefined(ready)) { 213 + ready = js_mkpromise(js); 214 + js_set_slot(writer_obj, SLOT_WS_READY, ready); 215 + } 216 + js_reject_promise(js, ready, error); 217 + } 218 + 219 + static void ws_writer_ensure_closed_promise_rejected(ant_t *js, ant_value_t writer_obj, ant_value_t error) { 220 + ant_value_t closed = ws_writer_closed(writer_obj); 221 + if (is_undefined(closed)) { 222 + closed = js_mkpromise(js); 223 + js_set_slot(writer_obj, SLOT_RS_CLOSED, closed); 224 + } 225 + js_reject_promise(js, closed, error); 226 + } 227 + 228 + static void writable_stream_start_erroring(ant_t *js, ant_value_t stream_obj, ant_value_t reason) { 229 + ws_stream_t *stream = ws_get_stream(stream_obj); 230 + if (!stream || stream->state != WS_STATE_WRITABLE) return; 231 + 232 + ant_value_t ctrl_obj = ws_stream_controller(stream_obj); 233 + ws_controller_t *ctrl = ws_get_controller(ctrl_obj); 234 + 235 + stream->state = WS_STATE_ERRORING; 236 + js_set_slot(stream_obj, SLOT_BUFFER, reason); 237 + 238 + ant_value_t writer_obj = ws_stream_writer(stream_obj); 239 + if (is_object_type(writer_obj)) 240 + ws_writer_ensure_ready_promise_rejected(js, writer_obj, reason); 241 + 242 + if (!writable_stream_has_operation_in_flight(stream_obj) && ctrl && ctrl->started) 243 + writable_stream_finish_erroring(js, stream_obj); 244 + } 245 + 246 + static void ws_reject_close_and_closed(ant_t *js, ant_value_t stream_obj) { 247 + ant_value_t stored_error = ws_stream_stored_error(stream_obj); 248 + ant_value_t cr = ws_stream_close_request(stream_obj); 249 + if (!is_undefined(cr)) { 250 + js_reject_promise(js, cr, stored_error); 251 + js_set_slot(stream_obj, SLOT_WS_CLOSE, js_mkundef()); 252 + } 253 + ant_value_t writer_obj = ws_stream_writer(stream_obj); 254 + if (is_object_type(writer_obj)) 255 + ws_writer_ensure_closed_promise_rejected(js, writer_obj, stored_error); 256 + } 257 + 258 + static ant_value_t ws_finish_erroring_abort_resolve(ant_t *js, ant_value_t *args, int nargs) { 259 + ant_value_t wrapper = js_get_slot(js->current_func, SLOT_DATA); 260 + ant_value_t p = js_get_slot(wrapper, SLOT_DATA); 261 + ant_value_t stream_obj = js_get_slot(wrapper, SLOT_ENTRIES); 262 + js_resolve_promise(js, p, js_mkundef()); 263 + ws_reject_close_and_closed(js, stream_obj); 264 + return js_mkundef(); 265 + } 266 + 267 + static ant_value_t ws_finish_erroring_abort_reject(ant_t *js, ant_value_t *args, int nargs) { 268 + ant_value_t wrapper = js_get_slot(js->current_func, SLOT_DATA); 269 + ant_value_t p = js_get_slot(wrapper, SLOT_DATA); 270 + ant_value_t stream_obj = js_get_slot(wrapper, SLOT_ENTRIES); 271 + ant_value_t reason = (nargs > 0) ? args[0] : js_mkundef(); 272 + js_reject_promise(js, p, reason); 273 + ws_reject_close_and_closed(js, stream_obj); 274 + return js_mkundef(); 275 + } 276 + 277 + static void writable_stream_finish_erroring(ant_t *js, ant_value_t stream_obj) { 278 + ws_stream_t *stream = ws_get_stream(stream_obj); 279 + if (!stream || stream->state != WS_STATE_ERRORING) return; 280 + stream->state = WS_STATE_ERRORED; 281 + 282 + ant_value_t ctrl_obj = ws_stream_controller(stream_obj); 283 + ws_controller_t *ctrl = ws_get_controller(ctrl_obj); 284 + if (ctrl) { 285 + ctrl->queue_total_size = 0; 286 + ctrl->queue_sizes_len = 0; 287 + } 288 + 289 + ws_default_controller_clear_algorithms(ctrl_obj); 290 + ant_value_t stored_error = ws_stream_stored_error(stream_obj); 291 + 292 + ant_value_t wr_arr = ws_stream_write_requests(js, stream_obj); 293 + if (vtype(wr_arr) == T_ARR) { 294 + ant_offset_t len = js_arr_len(js, wr_arr); 295 + for (ant_offset_t i = 0; i < len; i++) 296 + js_reject_promise(js, js_arr_get(js, wr_arr, i), stored_error); 297 + ant_object_t *aobj = js_obj_ptr(wr_arr); 298 + aobj->u.array.len = 0; 299 + } 300 + 301 + if (stream->has_pending_abort) { 302 + stream->has_pending_abort = false; 303 + ant_value_t abort_promise = ws_stream_pending_abort_promise(stream_obj); 304 + js_set_slot(stream_obj, SLOT_WS_READY, js_mkundef()); 305 + 306 + if (stream->pending_abort_was_already_erroring) { 307 + js_reject_promise(js, abort_promise, stored_error); 308 + ws_reject_close_and_closed(js, stream_obj); 309 + return; 310 + } 311 + 312 + ant_value_t abort_fn = ws_ctrl_abort_fn(ctrl_obj); 313 + ant_value_t result = js_mkundef(); 314 + if (is_callable(abort_fn)) { 315 + ant_value_t abort_args[1] = { stored_error }; 316 + result = sv_vm_call(js->vm, js, abort_fn, js_mkundef(), abort_args, 1, NULL, false); 317 + } 318 + 319 + if (is_err(result)) { 320 + ant_value_t thrown = js->thrown_value; 321 + js_reject_promise(js, abort_promise, is_object_type(thrown) ? thrown : result); 322 + ws_reject_close_and_closed(js, stream_obj); 323 + } else if (vtype(result) == T_PROMISE) { 324 + ant_value_t wrapper = js_mkobj(js); 325 + js_set_slot(wrapper, SLOT_DATA, abort_promise); 326 + js_set_slot(wrapper, SLOT_ENTRIES, stream_obj); 327 + ant_value_t res_fn = js_heavy_mkfun(js, ws_finish_erroring_abort_resolve, wrapper); 328 + ant_value_t rej_fn = js_heavy_mkfun(js, ws_finish_erroring_abort_reject, wrapper); 329 + ant_value_t then_fn = js_get(js, result, "then"); 330 + if (is_callable(then_fn)) { 331 + ant_value_t then_args[2] = { res_fn, rej_fn }; 332 + sv_vm_call(js->vm, js, then_fn, result, then_args, 2, NULL, false); 333 + } 334 + } else { 335 + js_resolve_promise(js, abort_promise, js_mkundef()); 336 + ws_reject_close_and_closed(js, stream_obj); 337 + } 338 + return; 339 + } 340 + 341 + ws_reject_close_and_closed(js, stream_obj); 342 + } 343 + 344 + static void writable_stream_deal_with_rejection(ant_t *js, ant_value_t stream_obj, ant_value_t error) { 345 + ws_stream_t *stream = ws_get_stream(stream_obj); 346 + if (!stream) return; 347 + if (stream->state == WS_STATE_WRITABLE) { 348 + writable_stream_start_erroring(js, stream_obj, error); 349 + return; 350 + } 351 + writable_stream_finish_erroring(js, stream_obj); 352 + } 353 + 354 + static void writable_stream_update_backpressure(ant_t *js, ant_value_t stream_obj, bool backpressure) { 355 + ws_stream_t *stream = ws_get_stream(stream_obj); 356 + if (!stream) return; 357 + ant_value_t writer_obj = ws_stream_writer(stream_obj); 358 + 359 + if (is_object_type(writer_obj) && stream->backpressure != backpressure) { 360 + if (backpressure) { 361 + js_set_slot(writer_obj, SLOT_WS_READY, js_mkpromise(js)); 362 + } else { 363 + ant_value_t ready = ws_writer_ready(writer_obj); 364 + if (!is_undefined(ready)) js_resolve_promise(js, ready, js_mkundef()); 365 + }} 366 + 367 + stream->backpressure = backpressure; 368 + } 369 + 370 + static void writable_stream_finish_in_flight_write(ant_t *js, ant_value_t stream_obj) { 371 + ant_value_t p = ws_stream_in_flight_write(stream_obj); 372 + if (!is_undefined(p)) js_resolve_promise(js, p, js_mkundef()); 373 + js_set_slot(stream_obj, SLOT_DEFAULT, js_mkundef()); 374 + } 375 + 376 + static void writable_stream_finish_in_flight_write_with_error(ant_t *js, ant_value_t stream_obj, ant_value_t error) { 377 + ant_value_t p = ws_stream_in_flight_write(stream_obj); 378 + if (!is_undefined(p)) js_reject_promise(js, p, error); 379 + js_set_slot(stream_obj, SLOT_DEFAULT, js_mkundef()); 380 + writable_stream_deal_with_rejection(js, stream_obj, error); 381 + } 382 + 383 + static void writable_stream_finish_in_flight_close(ant_t *js, ant_value_t stream_obj) { 384 + ant_value_t p = ws_stream_in_flight_close(stream_obj); 385 + if (!is_undefined(p)) js_resolve_promise(js, p, js_mkundef()); 386 + js_set_slot(stream_obj, SLOT_WS_ABORT, js_mkundef()); 387 + 388 + ws_stream_t *stream = ws_get_stream(stream_obj); 389 + if (!stream) return; 390 + 391 + if (stream->state == WS_STATE_ERRORING) { 392 + js_set_slot(stream_obj, SLOT_BUFFER, js_mkundef()); 393 + if (stream->has_pending_abort) { 394 + ant_value_t ap = ws_stream_pending_abort_promise(stream_obj); 395 + js_resolve_promise(js, ap, js_mkundef()); 396 + stream->has_pending_abort = false; 397 + js_set_slot(stream_obj, SLOT_WS_READY, js_mkundef()); 398 + } 399 + } 400 + stream->state = WS_STATE_CLOSED; 401 + 402 + ant_value_t writer_obj = ws_stream_writer(stream_obj); 403 + if (is_object_type(writer_obj)) { 404 + ant_value_t closed = ws_writer_closed(writer_obj); 405 + if (!is_undefined(closed)) js_resolve_promise(js, closed, js_mkundef()); 406 + } 407 + } 408 + 409 + static void writable_stream_finish_in_flight_close_with_error(ant_t *js, ant_value_t stream_obj, ant_value_t error) { 410 + ant_value_t p = ws_stream_in_flight_close(stream_obj); 411 + if (!is_undefined(p)) js_reject_promise(js, p, error); 412 + js_set_slot(stream_obj, SLOT_WS_ABORT, js_mkundef()); 413 + writable_stream_deal_with_rejection(js, stream_obj, error); 414 + } 415 + 416 + static void writable_stream_mark_first_write_in_flight(ant_t *js, ant_value_t stream_obj) { 417 + ant_value_t wr = ws_write_reqs_shift(js, stream_obj); 418 + js_set_slot(stream_obj, SLOT_DEFAULT, wr); 419 + } 420 + 421 + static void writable_stream_mark_close_in_flight(ant_value_t stream_obj) { 422 + ant_value_t cr = ws_stream_close_request(stream_obj); 423 + js_set_slot(stream_obj, SLOT_WS_ABORT, cr); 424 + js_set_slot(stream_obj, SLOT_WS_CLOSE, js_mkundef()); 425 + } 426 + 427 + static ant_value_t ws_process_write_resolve(ant_t *js, ant_value_t *args, int nargs) { 428 + ant_value_t ctrl_obj = js_get_slot(js->current_func, SLOT_DATA); 429 + ws_controller_t *ctrl = ws_get_controller(ctrl_obj); 430 + if (!ctrl) return js_mkundef(); 431 + 432 + ant_value_t stream_obj = ws_ctrl_stream(ctrl_obj); 433 + writable_stream_finish_in_flight_write(js, stream_obj); 434 + 435 + ws_stream_t *stream = ws_get_stream(stream_obj); 436 + if (!stream) return js_mkundef(); 437 + 438 + ws_ctrl_queue_shift(js, ctrl_obj); 439 + if (ctrl->queue_sizes_len > 0) { 440 + double sz = ctrl->queue_sizes[0]; 441 + ctrl->queue_sizes_len--; 442 + memmove(ctrl->queue_sizes, ctrl->queue_sizes + 1, ctrl->queue_sizes_len * sizeof(double)); 443 + ctrl->queue_total_size -= sz; 444 + if (ctrl->queue_total_size < 0) ctrl->queue_total_size = 0; 445 + } 446 + 447 + if (!writable_stream_close_queued_or_in_flight(stream_obj) && stream->state == WS_STATE_WRITABLE) { 448 + bool bp = ws_default_controller_get_backpressure(ctrl); 449 + writable_stream_update_backpressure(js, stream_obj, bp); 450 + } 451 + 452 + ws_default_controller_advance_queue_if_needed(js, ctrl_obj); 453 + return js_mkundef(); 454 + } 455 + 456 + static ant_value_t ws_process_write_reject(ant_t *js, ant_value_t *args, int nargs) { 457 + ant_value_t ctrl_obj = js_get_slot(js->current_func, SLOT_DATA); 458 + ant_value_t stream_obj = ws_ctrl_stream(ctrl_obj); 459 + ws_stream_t *stream = ws_get_stream(stream_obj); 460 + 461 + ant_value_t reason = (nargs > 0) ? args[0] : js_mkundef(); 462 + 463 + if (stream && stream->state == WS_STATE_WRITABLE) 464 + ws_default_controller_clear_algorithms(ctrl_obj); 465 + 466 + writable_stream_finish_in_flight_write_with_error(js, stream_obj, reason); 467 + return js_mkundef(); 468 + } 469 + 470 + static void ws_default_controller_process_write(ant_t *js, ant_value_t ctrl_obj, ant_value_t chunk) { 471 + ant_value_t stream_obj = ws_ctrl_stream(ctrl_obj); 472 + writable_stream_mark_first_write_in_flight(js, stream_obj); 473 + 474 + ant_value_t write_fn = ws_ctrl_write_fn(ctrl_obj); 475 + ant_value_t result = js_mkundef(); 476 + if (is_callable(write_fn)) { 477 + ant_value_t write_args[2] = { chunk, ctrl_obj }; 478 + result = sv_vm_call(js->vm, js, write_fn, js_mkundef(), write_args, 2, NULL, false); 479 + } 480 + 481 + if (is_err(result)) { 482 + ws_stream_t *stream = ws_get_stream(stream_obj); 483 + ant_value_t thrown = js->thrown_value; 484 + ant_value_t err = is_object_type(thrown) ? thrown : result; 485 + if (stream && stream->state == WS_STATE_WRITABLE) 486 + ws_default_controller_clear_algorithms(ctrl_obj); 487 + writable_stream_finish_in_flight_write_with_error(js, stream_obj, err); 488 + } else if (vtype(result) == T_PROMISE) { 489 + ant_value_t res_fn = js_heavy_mkfun(js, ws_process_write_resolve, ctrl_obj); 490 + ant_value_t rej_fn = js_heavy_mkfun(js, ws_process_write_reject, ctrl_obj); 491 + ant_value_t then_fn = js_get(js, result, "then"); 492 + if (is_callable(then_fn)) { 493 + ant_value_t then_args[2] = { res_fn, rej_fn }; 494 + sv_vm_call(js->vm, js, then_fn, result, then_args, 2, NULL, false); 495 + } 496 + } else { 497 + ant_value_t resolved = js_mkpromise(js); 498 + js_resolve_promise(js, resolved, js_mkundef()); 499 + ant_value_t res_fn = js_heavy_mkfun(js, ws_process_write_resolve, ctrl_obj); 500 + ant_value_t rej_fn = js_heavy_mkfun(js, ws_process_write_reject, ctrl_obj); 501 + ant_value_t then_fn = js_get(js, resolved, "then"); 502 + if (is_callable(then_fn)) { 503 + ant_value_t then_args[2] = { res_fn, rej_fn }; 504 + sv_vm_call(js->vm, js, then_fn, resolved, then_args, 2, NULL, false); 505 + } 506 + } 507 + } 508 + 509 + static ant_value_t ws_process_close_resolve(ant_t *js, ant_value_t *args, int nargs) { 510 + ant_value_t stream_obj = js_get_slot(js->current_func, SLOT_DATA); 511 + writable_stream_finish_in_flight_close(js, stream_obj); 512 + return js_mkundef(); 513 + } 514 + 515 + static ant_value_t ws_process_close_reject(ant_t *js, ant_value_t *args, int nargs) { 516 + ant_value_t stream_obj = js_get_slot(js->current_func, SLOT_DATA); 517 + ant_value_t reason = (nargs > 0) ? args[0] : js_mkundef(); 518 + writable_stream_finish_in_flight_close_with_error(js, stream_obj, reason); 519 + return js_mkundef(); 520 + } 521 + 522 + static void ws_default_controller_process_close(ant_t *js, ant_value_t ctrl_obj) { 523 + ant_value_t stream_obj = ws_ctrl_stream(ctrl_obj); 524 + writable_stream_mark_close_in_flight(stream_obj); 525 + 526 + ws_ctrl_queue_shift(js, ctrl_obj); 527 + ws_controller_t *ctrl = ws_get_controller(ctrl_obj); 528 + if (ctrl && ctrl->queue_sizes_len > 0) { 529 + ctrl->queue_sizes_len--; 530 + memmove(ctrl->queue_sizes, ctrl->queue_sizes + 1, ctrl->queue_sizes_len * sizeof(double)); 531 + } 532 + 533 + ant_value_t close_fn = ws_ctrl_close_fn(ctrl_obj); 534 + ws_default_controller_clear_algorithms(ctrl_obj); 535 + 536 + ant_value_t result = js_mkundef(); 537 + if (is_callable(close_fn)) 538 + result = sv_vm_call(js->vm, js, close_fn, js_mkundef(), NULL, 0, NULL, false); 539 + 540 + if (is_err(result)) { 541 + ant_value_t thrown = js->thrown_value; 542 + ant_value_t err = is_object_type(thrown) ? thrown : result; 543 + writable_stream_finish_in_flight_close_with_error(js, stream_obj, err); 544 + } else if (vtype(result) == T_PROMISE) { 545 + ant_value_t res_fn = js_heavy_mkfun(js, ws_process_close_resolve, stream_obj); 546 + ant_value_t rej_fn = js_heavy_mkfun(js, ws_process_close_reject, stream_obj); 547 + ant_value_t then_fn = js_get(js, result, "then"); 548 + if (is_callable(then_fn)) { 549 + ant_value_t then_args[2] = { res_fn, rej_fn }; 550 + sv_vm_call(js->vm, js, then_fn, result, then_args, 2, NULL, false); 551 + } 552 + } else { 553 + ant_value_t resolved = js_mkpromise(js); 554 + js_resolve_promise(js, resolved, js_mkundef()); 555 + ant_value_t res_fn = js_heavy_mkfun(js, ws_process_close_resolve, stream_obj); 556 + ant_value_t rej_fn = js_heavy_mkfun(js, ws_process_close_reject, stream_obj); 557 + ant_value_t then_fn = js_get(js, resolved, "then"); 558 + if (is_callable(then_fn)) { 559 + ant_value_t then_args[2] = { res_fn, rej_fn }; 560 + sv_vm_call(js->vm, js, then_fn, resolved, then_args, 2, NULL, false); 561 + } 562 + } 563 + } 564 + 565 + static void ws_default_controller_advance_queue_if_needed(ant_t *js, ant_value_t ctrl_obj) { 566 + ws_controller_t *ctrl = ws_get_controller(ctrl_obj); 567 + if (!ctrl || !ctrl->started) return; 568 + 569 + ant_value_t stream_obj = ws_ctrl_stream(ctrl_obj); 570 + ws_stream_t *stream = ws_get_stream(stream_obj); 571 + if (!stream) return; 572 + 573 + if (!is_undefined(ws_stream_in_flight_write(stream_obj))) return; 574 + 575 + if (stream->state == WS_STATE_ERRORING) { 576 + writable_stream_finish_erroring(js, stream_obj); 577 + return; 578 + } 579 + 580 + if (ws_ctrl_queue_empty(ctrl_obj)) return; 581 + ant_value_t value = ws_ctrl_queue_peek(js, ctrl_obj); 582 + 583 + if (value == g_close_sentinel) ws_default_controller_process_close(js, ctrl_obj); 584 + else ws_default_controller_process_write(js, ctrl_obj, value); 585 + } 586 + 587 + static void ws_default_controller_close(ant_t *js, ant_value_t ctrl_obj) { 588 + ws_controller_t *ctrl = ws_get_controller(ctrl_obj); 589 + if (!ctrl) return; 590 + 591 + ws_ctrl_queue_push(js, ctrl_obj, g_close_sentinel); 592 + if (ctrl->queue_sizes_len >= ctrl->queue_sizes_cap) { 593 + uint32_t new_cap = ctrl->queue_sizes_cap ? ctrl->queue_sizes_cap * 2 : 8; 594 + double *ns = realloc(ctrl->queue_sizes, new_cap * sizeof(double)); 595 + if (ns) { ctrl->queue_sizes = ns; ctrl->queue_sizes_cap = new_cap; } 596 + } 597 + if (ctrl->queue_sizes_len < ctrl->queue_sizes_cap) 598 + ctrl->queue_sizes[ctrl->queue_sizes_len++] = 0; 599 + 600 + ws_default_controller_advance_queue_if_needed(js, ctrl_obj); 601 + } 602 + 603 + static void ws_default_controller_write(ant_t *js, ant_value_t ctrl_obj, ant_value_t chunk, double chunk_size) { 604 + ws_controller_t *ctrl = ws_get_controller(ctrl_obj); 605 + if (!ctrl) return; 606 + 607 + ws_ctrl_queue_push(js, ctrl_obj, chunk); 608 + if (ctrl->queue_sizes_len >= ctrl->queue_sizes_cap) { 609 + uint32_t new_cap = ctrl->queue_sizes_cap ? ctrl->queue_sizes_cap * 2 : 8; 610 + double *ns = realloc(ctrl->queue_sizes, new_cap * sizeof(double)); 611 + if (ns) { ctrl->queue_sizes = ns; ctrl->queue_sizes_cap = new_cap; } 612 + } 613 + if (ctrl->queue_sizes_len < ctrl->queue_sizes_cap) 614 + ctrl->queue_sizes[ctrl->queue_sizes_len++] = chunk_size; 615 + ctrl->queue_total_size += chunk_size; 616 + 617 + ant_value_t stream_obj = ws_ctrl_stream(ctrl_obj); 618 + if (!writable_stream_close_queued_or_in_flight(stream_obj)) { 619 + ws_stream_t *stream = ws_get_stream(stream_obj); 620 + if (stream && stream->state == WS_STATE_WRITABLE) { 621 + bool bp = ws_default_controller_get_backpressure(ctrl); 622 + writable_stream_update_backpressure(js, stream_obj, bp); 623 + } 624 + } 625 + 626 + ws_default_controller_advance_queue_if_needed(js, ctrl_obj); 627 + } 628 + 629 + void ws_default_controller_error(ant_t *js, ant_value_t ctrl_obj, ant_value_t error) { 630 + ant_value_t stream_obj = ws_ctrl_stream(ctrl_obj); 631 + ws_stream_t *stream = ws_get_stream(stream_obj); 632 + if (!stream || stream->state != WS_STATE_WRITABLE) return; 633 + ws_default_controller_clear_algorithms(ctrl_obj); 634 + writable_stream_start_erroring(js, stream_obj, error); 635 + } 636 + 637 + ant_value_t writable_stream_close(ant_t *js, ant_value_t stream_obj) { 638 + ws_stream_t *stream = ws_get_stream(stream_obj); 639 + if (!stream) return js_mkundef(); 640 + 641 + if (stream->state == WS_STATE_CLOSED || stream->state == WS_STATE_ERRORED) { 642 + ant_value_t p = js_mkpromise(js); 643 + js_mkerr_typed(js, JS_ERR_TYPE, "Cannot close a stream that is already closed or errored"); 644 + js_reject_promise(js, p, js->thrown_value); 645 + return p; 646 + } 647 + if (writable_stream_close_queued_or_in_flight(stream_obj)) { 648 + ant_value_t p = js_mkpromise(js); 649 + js_mkerr_typed(js, JS_ERR_TYPE, "Cannot close an already-closing stream"); 650 + js_reject_promise(js, p, js->thrown_value); 651 + return p; 652 + } 653 + 654 + ant_value_t promise = js_mkpromise(js); 655 + js_set_slot(stream_obj, SLOT_WS_CLOSE, promise); 656 + 657 + ant_value_t writer_obj = ws_stream_writer(stream_obj); 658 + if (is_object_type(writer_obj) && stream->backpressure && stream->state == WS_STATE_WRITABLE) { 659 + ant_value_t ready = ws_writer_ready(writer_obj); 660 + if (!is_undefined(ready)) js_resolve_promise(js, ready, js_mkundef()); 661 + } 662 + 663 + ant_value_t ctrl_obj = ws_stream_controller(stream_obj); 664 + ws_default_controller_close(js, ctrl_obj); 665 + 666 + return promise; 667 + } 668 + 669 + static ant_value_t ws_abort_resolve(ant_t *js, ant_value_t *args, int nargs) { 670 + ant_value_t wrapper = js_get_slot(js->current_func, SLOT_DATA); 671 + ant_value_t p = js_get_slot(wrapper, SLOT_DATA); 672 + ant_value_t stream_obj = js_get_slot(wrapper, SLOT_ENTRIES); 673 + js_resolve_promise(js, p, js_mkundef()); 674 + 675 + ws_stream_t *stream = ws_get_stream(stream_obj); 676 + if (stream) stream->has_pending_abort = false; 677 + js_set_slot(stream_obj, SLOT_WS_READY, js_mkundef()); 678 + 679 + ant_value_t stored_error = ws_stream_stored_error(stream_obj); 680 + ant_value_t cr = ws_stream_close_request(stream_obj); 681 + if (!is_undefined(cr)) { 682 + js_reject_promise(js, cr, stored_error); 683 + js_set_slot(stream_obj, SLOT_WS_CLOSE, js_mkundef()); 684 + } 685 + ant_value_t writer_obj = ws_stream_writer(stream_obj); 686 + if (is_object_type(writer_obj)) 687 + ws_writer_ensure_closed_promise_rejected(js, writer_obj, stored_error); 688 + 689 + return js_mkundef(); 690 + } 691 + 692 + static ant_value_t ws_abort_reject(ant_t *js, ant_value_t *args, int nargs) { 693 + ant_value_t wrapper = js_get_slot(js->current_func, SLOT_DATA); 694 + ant_value_t p = js_get_slot(wrapper, SLOT_DATA); 695 + ant_value_t stream_obj = js_get_slot(wrapper, SLOT_ENTRIES); 696 + ant_value_t reason = (nargs > 0) ? args[0] : js_mkundef(); 697 + js_reject_promise(js, p, reason); 698 + 699 + ws_stream_t *stream = ws_get_stream(stream_obj); 700 + if (stream) stream->has_pending_abort = false; 701 + js_set_slot(stream_obj, SLOT_WS_READY, js_mkundef()); 702 + 703 + ant_value_t stored_error = ws_stream_stored_error(stream_obj); 704 + ant_value_t cr = ws_stream_close_request(stream_obj); 705 + if (!is_undefined(cr)) { 706 + js_reject_promise(js, cr, stored_error); 707 + js_set_slot(stream_obj, SLOT_WS_CLOSE, js_mkundef()); 708 + } 709 + ant_value_t writer_obj = ws_stream_writer(stream_obj); 710 + if (is_object_type(writer_obj)) 711 + ws_writer_ensure_closed_promise_rejected(js, writer_obj, stored_error); 712 + 713 + return js_mkundef(); 714 + } 715 + 716 + ant_value_t writable_stream_abort(ant_t *js, ant_value_t stream_obj, ant_value_t reason) { 717 + ws_stream_t *stream = ws_get_stream(stream_obj); 718 + if (!stream) return js_mkundef(); 719 + 720 + if (stream->state == WS_STATE_CLOSED || stream->state == WS_STATE_ERRORED) { 721 + ant_value_t p = js_mkpromise(js); 722 + js_resolve_promise(js, p, js_mkundef()); 723 + return p; 724 + } 725 + 726 + if (stream->has_pending_abort) { 727 + return ws_stream_pending_abort_promise(stream_obj); 728 + } 729 + 730 + bool was_already_erroring = (stream->state == WS_STATE_ERRORING); 731 + 732 + ant_value_t promise = js_mkpromise(js); 733 + stream->has_pending_abort = true; 734 + stream->pending_abort_was_already_erroring = was_already_erroring; 735 + js_set_slot(stream_obj, SLOT_WS_READY, promise); 736 + 737 + if (!was_already_erroring) 738 + writable_stream_start_erroring(js, stream_obj, reason); 739 + 740 + return promise; 741 + } 742 + 743 + static ant_value_t ws_writer_write(ant_t *js, ant_value_t writer_obj, ant_value_t chunk) { 744 + ant_value_t stream_obj = ws_writer_stream(writer_obj); 745 + if (!is_object_type(stream_obj)) { 746 + ant_value_t p = js_mkpromise(js); 747 + js_mkerr_typed(js, JS_ERR_TYPE, "Writer has no stream"); 748 + js_reject_promise(js, p, js->thrown_value); 749 + return p; 750 + } 751 + 752 + ws_stream_t *stream = ws_get_stream(stream_obj); 753 + if (!stream) { 754 + ant_value_t p = js_mkpromise(js); 755 + js_mkerr_typed(js, JS_ERR_TYPE, "Invalid WritableStream"); 756 + js_reject_promise(js, p, js->thrown_value); 757 + return p; 758 + } 759 + 760 + ant_value_t ctrl_obj = ws_stream_controller(stream_obj); 761 + double chunk_size = 1; 762 + ant_value_t size_fn = ws_ctrl_size_fn(ctrl_obj); 763 + 764 + if (is_callable(size_fn)) { 765 + ant_value_t size_args[1] = { chunk }; 766 + ant_value_t size_result = sv_vm_call(js->vm, js, size_fn, js_mkundef(), size_args, 1, NULL, false); 767 + if (is_err(size_result)) { 768 + ant_value_t thrown = js->thrown_value; 769 + ant_value_t err = is_object_type(thrown) ? thrown : size_result; 770 + ws_default_controller_error(js, ctrl_obj, err); 771 + ant_value_t p = js_mkpromise(js); 772 + js_reject_promise(js, p, err); 773 + return p; 774 + } 775 + if (vtype(size_result) == T_NUM) chunk_size = js_getnum(size_result); 776 + else chunk_size = js_to_number(js, size_result); 777 + } 778 + 779 + if (chunk_size < 0 || chunk_size != chunk_size || chunk_size == (double)INFINITY) { 780 + js_mkerr_typed(js, JS_ERR_RANGE, 781 + "The return value of a queuing strategy's size function must be a finite, non-NaN, non-negative number"); 782 + ant_value_t err = is_object_type(js->thrown_value) ? js->thrown_value : js_mkundef(); 783 + ws_default_controller_error(js, ctrl_obj, err); 784 + ant_value_t p = js_mkpromise(js); 785 + js_reject_promise(js, p, err); 786 + return p; 787 + } 788 + 789 + ant_value_t p = js_mkpromise(js); 790 + ws_write_reqs_push(js, stream_obj, p); 791 + ws_default_controller_write(js, ctrl_obj, chunk, chunk_size); 792 + 793 + return p; 794 + } 795 + 796 + static ant_value_t ws_start_resolve_handler(ant_t *js, ant_value_t *args, int nargs) { 797 + ant_value_t ctrl_obj = js_get_slot(js->current_func, SLOT_DATA); 798 + ws_controller_t *ctrl = ws_get_controller(ctrl_obj); 799 + if (!ctrl) return js_mkundef(); 800 + ctrl->started = true; 801 + ws_default_controller_advance_queue_if_needed(js, ctrl_obj); 802 + return js_mkundef(); 803 + } 804 + 805 + static ant_value_t ws_start_reject_handler(ant_t *js, ant_value_t *args, int nargs) { 806 + ant_value_t ctrl_obj = js_get_slot(js->current_func, SLOT_DATA); 807 + ws_controller_t *ctrl = ws_get_controller(ctrl_obj); 808 + if (!ctrl) return js_mkundef(); 809 + ctrl->started = true; 810 + ant_value_t stream_obj = ws_ctrl_stream(ctrl_obj); 811 + writable_stream_deal_with_rejection(js, stream_obj, nargs > 0 ? args[0] : js_mkundef()); 812 + return js_mkundef(); 813 + } 814 + 815 + static ant_value_t js_ws_controller_get_signal(ant_t *js, ant_value_t *args, int nargs) { 816 + ant_value_t signal_ctrl = ws_ctrl_signal(js->this_val); 817 + if (!is_object_type(signal_ctrl)) return js_mkundef(); 818 + return js_get(js, signal_ctrl, "signal"); 819 + } 820 + 821 + static ant_value_t js_ws_controller_error(ant_t *js, ant_value_t *args, int nargs) { 822 + ws_controller_t *ctrl = ws_get_controller(js->this_val); 823 + if (!ctrl) return js_mkerr_typed(js, JS_ERR_TYPE, "Invalid WritableStreamDefaultController"); 824 + ant_value_t stream_obj = ws_ctrl_stream(js->this_val); 825 + ws_stream_t *stream = ws_get_stream(stream_obj); 826 + if (!stream || stream->state != WS_STATE_WRITABLE) return js_mkundef(); 827 + ant_value_t e = (nargs > 0) ? args[0] : js_mkundef(); 828 + ws_default_controller_error(js, js->this_val, e); 829 + return js_mkundef(); 830 + } 831 + 832 + static ant_value_t js_ws_writer_get_closed(ant_t *js, ant_value_t *args, int nargs) { 833 + return ws_writer_closed(js->this_val); 834 + } 835 + 836 + static ant_value_t js_ws_writer_get_ready(ant_t *js, ant_value_t *args, int nargs) { 837 + return ws_writer_ready(js->this_val); 838 + } 839 + 840 + static ant_value_t js_ws_writer_get_desired_size(ant_t *js, ant_value_t *args, int nargs) { 841 + ant_value_t stream_obj = ws_writer_stream(js->this_val); 842 + if (!is_object_type(stream_obj)) 843 + return js_mkerr_typed(js, JS_ERR_TYPE, "Writer has no stream"); 844 + ws_stream_t *stream = ws_get_stream(stream_obj); 845 + if (!stream) return js_mknull(); 846 + if (stream->state == WS_STATE_ERRORED || stream->state == WS_STATE_ERRORING) return js_mknull(); 847 + if (stream->state == WS_STATE_CLOSED) return js_mknum(0); 848 + ant_value_t ctrl_obj = ws_stream_controller(stream_obj); 849 + ws_controller_t *ctrl = ws_get_controller(ctrl_obj); 850 + if (!ctrl) return js_mknull(); 851 + return js_mknum(ws_default_controller_get_desired_size(ctrl)); 852 + } 853 + 854 + static ant_value_t js_ws_writer_abort(ant_t *js, ant_value_t *args, int nargs) { 855 + ant_value_t stream_obj = ws_writer_stream(js->this_val); 856 + if (!is_object_type(stream_obj)) { 857 + ant_value_t p = js_mkpromise(js); 858 + js_mkerr_typed(js, JS_ERR_TYPE, "Writer has no stream"); 859 + js_reject_promise(js, p, js->thrown_value); 860 + return p; 861 + } 862 + ant_value_t reason = (nargs > 0) ? args[0] : js_mkundef(); 863 + return writable_stream_abort(js, stream_obj, reason); 864 + } 865 + 866 + static ant_value_t js_ws_writer_close(ant_t *js, ant_value_t *args, int nargs) { 867 + ant_value_t stream_obj = ws_writer_stream(js->this_val); 868 + if (!is_object_type(stream_obj)) { 869 + ant_value_t p = js_mkpromise(js); 870 + js_mkerr_typed(js, JS_ERR_TYPE, "Writer has no stream"); 871 + js_reject_promise(js, p, js->thrown_value); 872 + return p; 873 + } 874 + if (writable_stream_close_queued_or_in_flight(stream_obj)) { 875 + ant_value_t p = js_mkpromise(js); 876 + js_mkerr_typed(js, JS_ERR_TYPE, "Cannot close an already-closing stream"); 877 + js_reject_promise(js, p, js->thrown_value); 878 + return p; 879 + } 880 + return writable_stream_close(js, stream_obj); 881 + } 882 + 883 + static ant_value_t js_ws_writer_release_lock(ant_t *js, ant_value_t *args, int nargs) { 884 + ant_value_t stream_obj = ws_writer_stream(js->this_val); 885 + if (!is_object_type(stream_obj)) return js_mkundef(); 886 + 887 + js_mkerr_typed(js, JS_ERR_TYPE, "Writer was released"); 888 + ant_value_t release_err = js->thrown_value; 889 + 890 + ws_writer_ensure_ready_promise_rejected(js, js->this_val, release_err); 891 + ws_writer_ensure_closed_promise_rejected(js, js->this_val, release_err); 892 + 893 + js_set_slot(stream_obj, SLOT_CTOR, js_mkundef()); 894 + js_set_slot(js->this_val, SLOT_ENTRIES, js_mkundef()); 895 + return js_mkundef(); 896 + } 897 + 898 + static ant_value_t js_ws_writer_write(ant_t *js, ant_value_t *args, int nargs) { 899 + ant_value_t stream_obj = ws_writer_stream(js->this_val); 900 + if (!is_object_type(stream_obj)) { 901 + ant_value_t p = js_mkpromise(js); 902 + js_mkerr_typed(js, JS_ERR_TYPE, "Writer has no stream"); 903 + js_reject_promise(js, p, js->thrown_value); 904 + return p; 905 + } 906 + ant_value_t chunk = (nargs > 0) ? args[0] : js_mkundef(); 907 + return ws_writer_write(js, js->this_val, chunk); 908 + } 909 + 910 + static ant_value_t js_ws_writer_ctor(ant_t *js, ant_value_t *args, int nargs) { 911 + if (vtype(js->new_target) == T_UNDEF) 912 + return js_mkerr_typed(js, JS_ERR_TYPE, "WritableStreamDefaultWriter constructor requires 'new'"); 913 + if (nargs < 1) 914 + return js_mkerr_typed(js, JS_ERR_TYPE, "WritableStreamDefaultWriter requires a stream argument"); 915 + 916 + ant_value_t stream_obj = args[0]; 917 + if (!is_object_type(stream_obj)) 918 + return js_mkerr_typed(js, JS_ERR_TYPE, "WritableStreamDefaultWriter argument must be a WritableStream"); 919 + ws_stream_t *stream = ws_get_stream(stream_obj); 920 + if (!stream) 921 + return js_mkerr_typed(js, JS_ERR_TYPE, "WritableStreamDefaultWriter argument must be a WritableStream"); 922 + if (is_object_type(ws_stream_writer(stream_obj))) 923 + return js_mkerr_typed(js, JS_ERR_TYPE, "WritableStream is already locked to a writer"); 924 + 925 + ant_value_t obj = js_mkobj(js); 926 + ant_value_t proto = js_instance_proto_from_new_target(js, g_writer_proto); 927 + if (is_object_type(proto)) js_set_proto_init(obj, proto); 928 + 929 + ant_value_t closed = js_mkpromise(js); 930 + ant_value_t ready = js_mkpromise(js); 931 + 932 + js_set_slot(obj, SLOT_ENTRIES, stream_obj); 933 + js_set_slot(obj, SLOT_RS_CLOSED, closed); 934 + js_set_slot(obj, SLOT_WS_READY, ready); 935 + js_set_slot(stream_obj, SLOT_CTOR, obj); 936 + 937 + if (stream->state == WS_STATE_WRITABLE) { 938 + if (writable_stream_close_queued_or_in_flight(stream_obj) || !stream->backpressure) js_resolve_promise(js, ready, js_mkundef()); 939 + } else if (stream->state == WS_STATE_ERRORING) { 940 + ant_value_t stored_error = ws_stream_stored_error(stream_obj); 941 + js_reject_promise(js, ready, stored_error); 942 + } else if (stream->state == WS_STATE_CLOSED) { 943 + js_resolve_promise(js, ready, js_mkundef()); 944 + js_resolve_promise(js, closed, js_mkundef()); 945 + } else { 946 + ant_value_t stored_error = ws_stream_stored_error(stream_obj); 947 + js_reject_promise(js, ready, stored_error); 948 + js_reject_promise(js, closed, stored_error); 949 + } 950 + 951 + return obj; 952 + } 953 + 954 + static ant_value_t js_ws_get_locked(ant_t *js, ant_value_t *args, int nargs) { 955 + ws_stream_t *stream = ws_get_stream(js->this_val); 956 + if (!stream) return js_mkerr_typed(js, JS_ERR_TYPE, "Invalid WritableStream"); 957 + return js_bool(is_object_type(ws_stream_writer(js->this_val))); 958 + } 959 + 960 + static ant_value_t js_ws_abort(ant_t *js, ant_value_t *args, int nargs) { 961 + ws_stream_t *stream = ws_get_stream(js->this_val); 962 + if (!stream) return js_mkerr_typed(js, JS_ERR_TYPE, "Invalid WritableStream"); 963 + if (is_object_type(ws_stream_writer(js->this_val))) { 964 + ant_value_t p = js_mkpromise(js); 965 + js_mkerr_typed(js, JS_ERR_TYPE, "Cannot abort a locked WritableStream"); 966 + js_reject_promise(js, p, js->thrown_value); 967 + return p; 968 + } 969 + ant_value_t reason = (nargs > 0) ? args[0] : js_mkundef(); 970 + return writable_stream_abort(js, js->this_val, reason); 971 + } 972 + 973 + static ant_value_t js_ws_close(ant_t *js, ant_value_t *args, int nargs) { 974 + ws_stream_t *stream = ws_get_stream(js->this_val); 975 + if (!stream) return js_mkerr_typed(js, JS_ERR_TYPE, "Invalid WritableStream"); 976 + if (is_object_type(ws_stream_writer(js->this_val))) { 977 + ant_value_t p = js_mkpromise(js); 978 + js_mkerr_typed(js, JS_ERR_TYPE, "Cannot close a locked WritableStream"); 979 + js_reject_promise(js, p, js->thrown_value); 980 + return p; 981 + } 982 + if (writable_stream_close_queued_or_in_flight(js->this_val)) { 983 + ant_value_t p = js_mkpromise(js); 984 + js_mkerr_typed(js, JS_ERR_TYPE, "Cannot close an already-closing stream"); 985 + js_reject_promise(js, p, js->thrown_value); 986 + return p; 987 + } 988 + return writable_stream_close(js, js->this_val); 989 + } 990 + 991 + static ant_value_t js_ws_get_writer(ant_t *js, ant_value_t *args, int nargs) { 992 + ws_stream_t *stream = ws_get_stream(js->this_val); 993 + if (!stream) return js_mkerr_typed(js, JS_ERR_TYPE, "Invalid WritableStream"); 994 + 995 + ant_value_t writer_args[1] = { js->this_val }; 996 + ant_value_t saved_new_target = js->new_target; 997 + js->new_target = g_writer_proto; 998 + ant_value_t writer = js_ws_writer_ctor(js, writer_args, 1); 999 + js->new_target = saved_new_target; 1000 + return writer; 1001 + } 1002 + 1003 + static ant_value_t setup_ws_default_controller( 1004 + ant_t *js, ant_value_t stream_obj, 1005 + ant_value_t write_fn, ant_value_t close_fn, ant_value_t abort_fn, 1006 + ant_value_t size_fn, double hwm 1007 + ) { 1008 + ws_controller_t *ctrl = calloc(1, sizeof(ws_controller_t)); 1009 + if (!ctrl) return js_mkerr(js, "out of memory"); 1010 + ctrl->strategy_hwm = hwm; 1011 + 1012 + ant_value_t ctrl_obj = js_mkobj(js); 1013 + js_set_proto_init(ctrl_obj, g_controller_proto); 1014 + js_set_slot(ctrl_obj, SLOT_DATA, ANT_PTR(ctrl)); 1015 + js_set_slot(ctrl_obj, SLOT_ENTRIES, stream_obj); 1016 + js_set_slot(ctrl_obj, SLOT_WS_WRITE, write_fn); 1017 + js_set_slot(ctrl_obj, SLOT_WS_CLOSE, close_fn); 1018 + js_set_slot(ctrl_obj, SLOT_WS_ABORT, abort_fn); 1019 + js_set_slot(ctrl_obj, SLOT_RS_SIZE, size_fn); 1020 + js_set_slot(ctrl_obj, SLOT_BUFFER, js_mkarr(js)); 1021 + js_set_finalizer(ctrl_obj, ws_controller_finalize); 1022 + 1023 + ant_value_t ac_ctor = js_get(js, js_glob(js), "AbortController"); 1024 + ant_value_t ac = js_mkundef(); 1025 + if (is_callable(ac_ctor)) { 1026 + ant_value_t saved = js->new_target; 1027 + js->new_target = ac_ctor; 1028 + ac = sv_vm_call(js->vm, js, ac_ctor, js_mkundef(), NULL, 0, NULL, false); 1029 + js->new_target = saved; 1030 + if (is_err(ac)) ac = js_mkundef(); 1031 + } 1032 + 1033 + js_set_slot(ctrl_obj, SLOT_WS_SIGNAL, ac); 1034 + js_set_slot(stream_obj, SLOT_ENTRIES, ctrl_obj); 1035 + 1036 + bool backpressure = ws_default_controller_get_backpressure(ctrl); 1037 + writable_stream_update_backpressure(js, stream_obj, backpressure); 1038 + 1039 + return ctrl_obj; 1040 + } 1041 + 1042 + static ant_value_t js_ws_ctor(ant_t *js, ant_value_t *args, int nargs) { 1043 + if (vtype(js->new_target) == T_UNDEF) 1044 + return js_mkerr_typed(js, JS_ERR_TYPE, "WritableStream constructor requires 'new'"); 1045 + 1046 + ant_value_t underlying_sink = js_mkundef(); 1047 + if (nargs > 0 && !is_undefined(args[0])) { 1048 + if (is_null(args[0])) 1049 + return js_mkerr_typed(js, JS_ERR_TYPE, "The underlying sink cannot be null"); 1050 + underlying_sink = args[0]; 1051 + } 1052 + 1053 + if (is_object_type(underlying_sink)) { 1054 + ant_value_t type_val = js_get(js, underlying_sink, "type"); 1055 + if (!is_undefined(type_val)) 1056 + return js_mkerr_typed(js, JS_ERR_RANGE, "Invalid type is specified"); 1057 + } 1058 + 1059 + ant_value_t strategy = js_mkundef(); 1060 + if (nargs > 1 && !is_undefined(args[1]) && !is_null(args[1])) 1061 + strategy = args[1]; 1062 + 1063 + double hwm = 1; 1064 + if (is_object_type(strategy)) { 1065 + ant_value_t hwm_val = js_get(js, strategy, "highWaterMark"); 1066 + if (is_err(hwm_val)) return hwm_val; 1067 + if (!is_undefined(hwm_val)) { 1068 + hwm = js_to_number(js, hwm_val); 1069 + if (hwm != hwm || hwm < 0) return js_mkerr_typed(js, JS_ERR_RANGE, "Invalid highWaterMark"); 1070 + } 1071 + } 1072 + 1073 + ant_value_t size_fn = js_mkundef(); 1074 + if (is_object_type(strategy)) { 1075 + ant_value_t s = js_get(js, strategy, "size"); 1076 + if (is_err(s)) return s; 1077 + if (!is_undefined(s)) { 1078 + if (!is_callable(s)) return js_mkerr_typed(js, JS_ERR_TYPE, "size must be a function"); 1079 + size_fn = s; 1080 + } 1081 + } 1082 + 1083 + ws_stream_t *st = calloc(1, sizeof(ws_stream_t)); 1084 + if (!st) return js_mkerr(js, "out of memory"); 1085 + st->state = WS_STATE_WRITABLE; 1086 + 1087 + ant_value_t obj = js_mkobj(js); 1088 + ant_value_t proto = js_instance_proto_from_new_target(js, g_ws_proto); 1089 + if (is_object_type(proto)) js_set_proto_init(obj, proto); 1090 + js_set_slot(obj, SLOT_DATA, ANT_PTR(st)); 1091 + js_set_slot(obj, SLOT_SETTLED, js_mkarr(js)); 1092 + js_set_finalizer(obj, ws_stream_finalize); 1093 + 1094 + ant_value_t write_fn = js_mkundef(); 1095 + ant_value_t close_fn = js_mkundef(); 1096 + ant_value_t abort_fn = js_mkundef(); 1097 + ant_value_t start_fn = js_mkundef(); 1098 + 1099 + if (is_object_type(underlying_sink)) { 1100 + ant_value_t wv = js_get(js, underlying_sink, "write"); 1101 + if (is_err(wv)) return wv; 1102 + if (!is_undefined(wv)) { 1103 + if (!is_callable(wv)) return js_mkerr_typed(js, JS_ERR_TYPE, "write must be a function"); 1104 + write_fn = wv; 1105 + } 1106 + ant_value_t cv = js_get(js, underlying_sink, "close"); 1107 + if (is_err(cv)) return cv; 1108 + if (!is_undefined(cv)) { 1109 + if (!is_callable(cv)) return js_mkerr_typed(js, JS_ERR_TYPE, "close must be a function"); 1110 + close_fn = cv; 1111 + } 1112 + ant_value_t av = js_get(js, underlying_sink, "abort"); 1113 + if (is_err(av)) return av; 1114 + if (!is_undefined(av)) { 1115 + if (!is_callable(av)) return js_mkerr_typed(js, JS_ERR_TYPE, "abort must be a function"); 1116 + abort_fn = av; 1117 + } 1118 + ant_value_t sv = js_get(js, underlying_sink, "start"); 1119 + if (is_err(sv)) return sv; 1120 + if (!is_undefined(sv)) { 1121 + if (!is_callable(sv)) return js_mkerr_typed(js, JS_ERR_TYPE, "start must be a function"); 1122 + start_fn = sv; 1123 + } 1124 + } 1125 + 1126 + ant_value_t ctrl_obj = setup_ws_default_controller(js, obj, write_fn, close_fn, abort_fn, size_fn, hwm); 1127 + if (is_err(ctrl_obj)) return ctrl_obj; 1128 + 1129 + if (is_callable(start_fn)) { 1130 + ant_value_t start_args[1] = { ctrl_obj }; 1131 + ant_value_t start_result = sv_vm_call(js->vm, js, start_fn, underlying_sink, start_args, 1, NULL, false); 1132 + if (is_err(start_result)) return start_result; 1133 + 1134 + if (vtype(start_result) == T_PROMISE) { 1135 + ant_value_t resolve_fn = js_heavy_mkfun(js, ws_start_resolve_handler, ctrl_obj); 1136 + ant_value_t reject_fn = js_heavy_mkfun(js, ws_start_reject_handler, ctrl_obj); 1137 + ant_value_t then_fn = js_get(js, start_result, "then"); 1138 + if (is_callable(then_fn)) { 1139 + ant_value_t then_args[2] = { resolve_fn, reject_fn }; 1140 + sv_vm_call(js->vm, js, then_fn, start_result, then_args, 2, NULL, false); 1141 + } 1142 + } 1143 + 1144 + if (vtype(start_result) != T_PROMISE) { 1145 + ant_value_t resolved = js_mkpromise(js); 1146 + js_resolve_promise(js, resolved, js_mkundef()); 1147 + ant_value_t res_fn = js_heavy_mkfun(js, ws_start_resolve_handler, ctrl_obj); 1148 + ant_value_t rej_fn = js_heavy_mkfun(js, ws_start_reject_handler, ctrl_obj); 1149 + ant_value_t then_fn = js_get(js, resolved, "then"); 1150 + if (is_callable(then_fn)) { 1151 + ant_value_t then_args[2] = { res_fn, rej_fn }; 1152 + sv_vm_call(js->vm, js, then_fn, resolved, then_args, 2, NULL, false); 1153 + } 1154 + } 1155 + } else { 1156 + ant_value_t resolved = js_mkpromise(js); 1157 + js_resolve_promise(js, resolved, js_mkundef()); 1158 + ant_value_t res_fn = js_heavy_mkfun(js, ws_start_resolve_handler, ctrl_obj); 1159 + ant_value_t rej_fn = js_heavy_mkfun(js, ws_start_reject_handler, ctrl_obj); 1160 + ant_value_t then_fn = js_get(js, resolved, "then"); 1161 + if (is_callable(then_fn)) { 1162 + ant_value_t then_args[2] = { res_fn, rej_fn }; 1163 + sv_vm_call(js->vm, js, then_fn, resolved, then_args, 2, NULL, false); 1164 + } 1165 + } 1166 + 1167 + return obj; 1168 + } 1169 + 1170 + static ant_value_t js_ws_controller_ctor(ant_t *js, ant_value_t *args, int nargs) { 1171 + return js_mkerr_typed(js, JS_ERR_TYPE, "WritableStreamDefaultController cannot be constructed directly"); 1172 + } 1173 + 1174 + void gc_mark_writable_streams(ant_t *js, void (*mark)(ant_t *, ant_value_t)) { 1175 + mark(js, g_ws_proto); 1176 + mark(js, g_writer_proto); 1177 + mark(js, g_controller_proto); 1178 + mark(js, g_close_sentinel); 1179 + } 1180 + 1181 + void init_writable_stream_module(void) { 1182 + ant_t *js = rt->js; 1183 + ant_value_t g = js_glob(js); 1184 + 1185 + g_close_sentinel = js_mkobj(js); 1186 + g_controller_proto = js_mkobj(js); 1187 + 1188 + js_set_getter_desc(js, g_controller_proto, "signal", 6, 1189 + js_mkfun(js_ws_controller_get_signal), JS_DESC_C); 1190 + js_set(js, g_controller_proto, "error", js_mkfun(js_ws_controller_error)); 1191 + js_set_descriptor(js, g_controller_proto, "error", 5, JS_DESC_W | JS_DESC_C); 1192 + js_set_sym(js, g_controller_proto, get_toStringTag_sym(), 1193 + js_mkstr(js, "WritableStreamDefaultController", 31)); 1194 + 1195 + ant_value_t ctrl_ctor = js_make_ctor(js, js_ws_controller_ctor, g_controller_proto, 1196 + "WritableStreamDefaultController", 31); 1197 + js_set(js, g, "WritableStreamDefaultController", ctrl_ctor); 1198 + js_set_descriptor(js, g, "WritableStreamDefaultController", 31, JS_DESC_W | JS_DESC_C); 1199 + 1200 + g_writer_proto = js_mkobj(js); 1201 + js_set_getter_desc(js, g_writer_proto, "closed", 6, 1202 + js_mkfun(js_ws_writer_get_closed), JS_DESC_C); 1203 + js_set_getter_desc(js, g_writer_proto, "desiredSize", 11, 1204 + js_mkfun(js_ws_writer_get_desired_size), JS_DESC_C); 1205 + js_set_getter_desc(js, g_writer_proto, "ready", 5, 1206 + js_mkfun(js_ws_writer_get_ready), JS_DESC_C); 1207 + js_set(js, g_writer_proto, "abort", js_mkfun(js_ws_writer_abort)); 1208 + js_set_descriptor(js, g_writer_proto, "abort", 5, JS_DESC_W | JS_DESC_C); 1209 + js_set(js, g_writer_proto, "close", js_mkfun(js_ws_writer_close)); 1210 + js_set_descriptor(js, g_writer_proto, "close", 5, JS_DESC_W | JS_DESC_C); 1211 + js_set(js, g_writer_proto, "releaseLock", js_mkfun(js_ws_writer_release_lock)); 1212 + js_set_descriptor(js, g_writer_proto, "releaseLock", 11, JS_DESC_W | JS_DESC_C); 1213 + js_set(js, g_writer_proto, "write", js_mkfun(js_ws_writer_write)); 1214 + js_set_descriptor(js, g_writer_proto, "write", 5, JS_DESC_W | JS_DESC_C); 1215 + js_set_sym(js, g_writer_proto, get_toStringTag_sym(), 1216 + js_mkstr(js, "WritableStreamDefaultWriter", 27)); 1217 + 1218 + ant_value_t writer_ctor = js_make_ctor(js, js_ws_writer_ctor, g_writer_proto, 1219 + "WritableStreamDefaultWriter", 27); 1220 + js_set(js, g, "WritableStreamDefaultWriter", writer_ctor); 1221 + js_set_descriptor(js, g, "WritableStreamDefaultWriter", 27, JS_DESC_W | JS_DESC_C); 1222 + 1223 + g_ws_proto = js_mkobj(js); 1224 + js_set_getter_desc(js, g_ws_proto, "locked", 6, 1225 + js_mkfun(js_ws_get_locked), JS_DESC_C); 1226 + js_set(js, g_ws_proto, "abort", js_mkfun(js_ws_abort)); 1227 + js_set_descriptor(js, g_ws_proto, "abort", 5, JS_DESC_W | JS_DESC_C); 1228 + js_set(js, g_ws_proto, "close", js_mkfun(js_ws_close)); 1229 + js_set_descriptor(js, g_ws_proto, "close", 5, JS_DESC_W | JS_DESC_C); 1230 + js_set(js, g_ws_proto, "getWriter", js_mkfun(js_ws_get_writer)); 1231 + js_set_descriptor(js, g_ws_proto, "getWriter", 9, JS_DESC_W | JS_DESC_C); 1232 + js_set_sym(js, g_ws_proto, get_toStringTag_sym(), 1233 + js_mkstr(js, "WritableStream", 14)); 1234 + 1235 + ant_value_t ws_ctor = js_make_ctor(js, js_ws_ctor, g_ws_proto, "WritableStream", 14); 1236 + js_set(js, g, "WritableStream", ws_ctor); 1237 + js_set_descriptor(js, g, "WritableStream", 14, JS_DESC_W | JS_DESC_C); 1238 + }