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.

prepare for pipes

+238 -122
+26
examples/spec/blob.js
··· 105 105 const ft = await f1.text(); 106 106 test('File.text() works', ft, 'content'); 107 107 108 + console.log('\nBlob.stream()\n'); 109 + 110 + { 111 + const blob = new Blob(['hello']); 112 + const stream = blob.stream(); 113 + test('stream() returns ReadableStream', stream instanceof ReadableStream, true); 114 + test('stream is not locked', stream.locked, false); 115 + 116 + const reader = stream.getReader(); 117 + const { value, done } = await reader.read(); 118 + test('stream chunk is Uint8Array', value instanceof Uint8Array, true); 119 + test('stream chunk length', value.length, 5); 120 + test('stream chunk byte 0', value[0], 104); 121 + test('stream chunk byte 4', value[4], 111); 122 + 123 + const end = await reader.read(); 124 + test('stream done after one chunk', end.done, true); 125 + } 126 + 127 + { 128 + const blob = new Blob(); 129 + const reader = blob.stream().getReader(); 130 + const { done } = await reader.read(); 131 + test('empty blob stream closes immediately', done, true); 132 + } 133 + 108 134 console.log('\nSymbol.toStringTag\n'); 109 135 110 136 test('Blob toStringTag', Object.prototype.toString.call(b1), '[object Blob]');
+1
include/gc/modules.h
··· 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 25 void gc_mark_writable_streams(ant_t *js, gc_mark_fn mark); 26 + void gc_mark_pipes(ant_t *js, gc_mark_fn mark); 26 27 27 28 #endif
+20 -1
include/modules/assert.h
··· 1 1 #ifndef ANT_ASSERT_MODULE_H 2 2 #define ANT_ASSERT_MODULE_H 3 3 4 - #include "types.h" 4 + #include "internal.h" 5 + #include "silver/engine.h" 5 6 6 7 ant_value_t assert_library(ant_t *js); 8 + 9 + static inline bool promise_was_rejected(ant_value_t result) { 10 + if (vtype(result) != T_PROMISE) return false; 11 + ant_object_t *obj = js_obj_ptr(js_as_obj(result)); 12 + return obj && obj->promise_state && obj->promise_state->state == 2; 13 + } 14 + 15 + static inline void promise_mark_handled(ant_value_t v) { 16 + if (vtype(v) != T_PROMISE) return; 17 + ant_object_t *obj = js_obj_ptr(js_as_obj(v)); 18 + if (obj && obj->promise_state) obj->promise_state->has_rejection_handler = true; 19 + } 20 + 21 + static inline bool promise_was_fulfilled(ant_value_t result) { 22 + if (vtype(result) != T_PROMISE) return false; 23 + ant_object_t *obj = js_obj_ptr(js_as_obj(result)); 24 + return obj && obj->promise_state && obj->promise_state->state == 1; 25 + } 7 26 8 27 #endif
+16
include/streams/pipes.h
··· 1 + #ifndef STREAMS_PIPES_H 2 + #define STREAMS_PIPES_H 3 + 4 + #include "types.h" 5 + #include <stdbool.h> 6 + 7 + void init_pipes_proto(ant_t *js, ant_value_t rs_proto); 8 + void gc_mark_pipes(ant_t *js, void (*mark)(ant_t *, ant_value_t)); 9 + 10 + ant_value_t readable_stream_pipe_to( 11 + ant_t *js, ant_value_t source, ant_value_t dest, 12 + bool prevent_close, bool prevent_abort, bool prevent_cancel, 13 + ant_value_t signal 14 + ); 15 + 16 + #endif
+29 -2
include/streams/readable.h
··· 28 28 bool disturbed; 29 29 } rs_stream_t; 30 30 31 + extern ant_value_t g_rs_proto; 32 + extern ant_value_t g_reader_proto; 33 + extern ant_value_t g_controller_proto; 34 + 31 35 void init_readable_stream_module(void); 32 36 void gc_mark_readable_streams(ant_t *js, void (*mark)(ant_t *, ant_value_t)); 33 37 34 38 rs_stream_t *rs_get_stream(ant_value_t obj); 39 + rs_controller_t *rs_get_controller(ant_value_t obj); 40 + ant_offset_t rs_ctrl_queue_len(ant_t *js, ant_value_t ctrl_obj); 41 + 42 + ant_value_t rs_ctrl_size(ant_value_t ctrl_obj); 43 + ant_value_t rs_reader_reqs(ant_value_t reader_obj); 44 + ant_value_t rs_stream_error(ant_value_t stream_obj); 45 + ant_value_t rs_stream_reader(ant_value_t stream_obj); 46 + ant_value_t rs_reader_stream(ant_value_t reader_obj); 47 + ant_value_t rs_reader_closed(ant_value_t reader_obj); 48 + 35 49 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); 50 + ant_value_t rs_default_reader_read(ant_t *js, ant_value_t reader_obj); 51 + ant_value_t rs_cancel_reject(ant_t *js, ant_value_t *args, int nargs); 52 + ant_value_t js_rs_reader_ctor(ant_t *js, ant_value_t *args, int nargs); 53 + ant_value_t rs_cancel_resolve(ant_t *js, ant_value_t *args, int nargs); 54 + ant_value_t readable_stream_cancel(ant_t *js, ant_value_t stream_obj, ant_value_t reason); 55 + ant_value_t rs_create_stream(ant_t *js, ant_value_t pull_fn, ant_value_t cancel_fn, double hwm); 56 + ant_value_t rs_create_stream(ant_t *js, ant_value_t pull_fn, ant_value_t cancel_fn, double hwm); 57 + 58 + bool rs_reader_has_reqs(ant_t *js, ant_value_t reader_obj); 59 + bool rs_default_controller_can_close_or_enqueue(rs_controller_t *ctrl, rs_stream_t *stream); 37 60 61 + void rs_default_controller_clear_algorithms(ant_value_t ctrl_obj); 62 + void rs_default_controller_call_pull_if_needed(ant_t *js, ant_value_t controller_obj); 63 + void rs_default_reader_error_read_requests(ant_t *js, ant_value_t reader_obj, ant_value_t e); 64 + void rs_fulfill_read_request(ant_t *js, ant_value_t stream_obj, ant_value_t chunk, bool done); 65 + void rs_ctrl_queue_push(ant_t *js, ant_value_t ctrl_obj, ant_value_t value); 38 66 void readable_stream_close(ant_t *js, ant_value_t stream_obj); 39 67 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 68 42 69 #endif
+5
include/streams/writable.h
··· 33 33 void gc_mark_writable_streams(ant_t *js, void (*mark)(ant_t *, ant_value_t)); 34 34 35 35 ws_stream_t *ws_get_stream(ant_value_t obj); 36 + ws_controller_t *ws_get_controller(ant_value_t obj); 37 + 36 38 ant_value_t ws_stream_controller(ant_value_t stream_obj); 37 39 ant_value_t ws_stream_writer(ant_value_t stream_obj); 40 + 41 + ant_value_t ws_acquire_writer(ant_t *js, ant_value_t stream_obj); 42 + ant_value_t ws_writer_write(ant_t *js, ant_value_t writer_obj, ant_value_t chunk); 38 43 39 44 ant_value_t writable_stream_close(ant_t *js, ant_value_t stream_obj); 40 45 ant_value_t writable_stream_abort(ant_t *js, ant_value_t stream_obj, ant_value_t reason);
+1
src/gc/objects.c
··· 456 456 gc_mark_domexception(js, gc_mark_value); 457 457 gc_mark_readable_streams(js, gc_mark_value); 458 458 gc_mark_writable_streams(js, gc_mark_value); 459 + gc_mark_pipes(js, gc_mark_value); 459 460 460 461 for ( 461 462 ant_object_t *obj = g_pending_promises;
+2 -18
src/modules/assert.c
··· 4 4 #include "ant.h" 5 5 #include "errors.h" 6 6 #include "internal.h" 7 + 8 + #include "modules/assert.h" 7 9 #include "silver/engine.h" 8 10 9 11 static ant_value_t assertion_error(ant_t *js, const char *msg, ant_value_t msg_val) { ··· 188 190 if (is_err(result)) 189 191 return js_mkerr(js, "Got unwanted exception: %s", js_str(js, result)); 190 192 return js_mkundef(); 191 - } 192 - 193 - static bool promise_was_rejected(ant_value_t result) { 194 - if (vtype(result) != T_PROMISE) return false; 195 - ant_object_t *obj = js_obj_ptr(js_as_obj(result)); 196 - return obj && obj->promise_state && obj->promise_state->state == 2; 197 - } 198 - 199 - static void promise_mark_handled(ant_value_t result) { 200 - if (vtype(result) != T_PROMISE) return; 201 - ant_object_t *obj = js_obj_ptr(js_as_obj(result)); 202 - if (obj && obj->promise_state) obj->promise_state->has_rejection_handler = true; 203 - } 204 - 205 - static bool promise_was_fulfilled(ant_value_t result) { 206 - if (vtype(result) != T_PROMISE) return false; 207 - ant_object_t *obj = js_obj_ptr(js_as_obj(result)); 208 - return obj && obj->promise_state && obj->promise_state->state == 1; 209 193 } 210 194 211 195 static ant_value_t assert_rejects(ant_t *js, ant_value_t *args, int nargs) {
+27 -2
src/modules/blob.c
··· 12 12 #include "internal.h" 13 13 #include "descriptors.h" 14 14 15 + #include "silver/engine.h" 15 16 #include "modules/blob.h" 16 17 #include "modules/buffer.h" 17 18 #include "modules/symbol.h" 19 + #include "streams/readable.h" 18 20 19 21 ant_value_t g_blob_proto = 0; 20 22 ant_value_t g_file_proto = 0; ··· 279 281 return result; 280 282 } 281 283 284 + static ant_value_t blob_stream_pull(ant_t *js, ant_value_t *args, int nargs) { 285 + ant_value_t blob_obj = js_get_slot(js->current_func, SLOT_DATA); 286 + blob_data_t *bd = blob_get_data(blob_obj); 287 + ant_value_t controller = (nargs > 0) ? args[0] : js_mkundef(); 288 + 289 + if (bd && bd->size > 0 && bd->data) { 290 + ArrayBufferData *ab = create_array_buffer_data(bd->size); 291 + if (ab) { 292 + memcpy(ab->data, bd->data, bd->size); 293 + ant_value_t chunk = create_typed_array(js, TYPED_ARRAY_UINT8, ab, 0, bd->size, "Uint8Array"); 294 + ant_value_t enqueue_fn = js_get(js, controller, "enqueue"); 295 + if (is_callable(enqueue_fn)) { 296 + ant_value_t enq_args[1] = { chunk }; 297 + sv_vm_call(js->vm, js, enqueue_fn, controller, enq_args, 1, NULL, false); 298 + }} 299 + } 300 + 301 + ant_value_t close_fn = js_get(js, controller, "close"); 302 + if (is_callable(close_fn)) sv_vm_call(js->vm, js, close_fn, controller, NULL, 0, NULL, false); 303 + 304 + return js_mkundef(); 305 + } 306 + 282 307 static ant_value_t js_blob_stream(ant_t *js, ant_value_t *args, int nargs) { 283 - (void)args; (void)nargs; 284 - return js_mkerr_typed(js, JS_ERR_TYPE, "Blob.stream() is not yet implemented"); 308 + ant_value_t pull_fn = js_heavy_mkfun(js, blob_stream_pull, js->this_val); 309 + return rs_create_stream(js, pull_fn, js_mkundef(), 0); 285 310 } 286 311 287 312 static ant_value_t js_blob_ctor(ant_t *js, ant_value_t *args, int nargs) {
+15 -16
src/modules/timer.c
··· 347 347 } 348 348 349 349 void process_immediates(ant_t *js) { 350 - while (timer_state.immediates != NULL) { 351 - immediate_entry_t *entry = timer_state.immediates; 352 - timer_state.immediates = entry->next; 353 - 354 - if (timer_state.immediates == NULL) { 355 - timer_state.immediates_tail = NULL; 356 - } 357 - 358 - if (entry->active) { 359 - ant_value_t args[0]; 360 - sv_vm_call(js->vm, js, entry->callback, js_mkundef(), args, 0, NULL, false); 361 - process_microtasks(js); 362 - } 363 - 364 - free(entry); 350 + while (timer_state.immediates != NULL) { 351 + immediate_entry_t *entry = timer_state.immediates; 352 + timer_state.immediates = entry->next; 353 + 354 + if (timer_state.immediates == NULL) { 355 + timer_state.immediates_tail = NULL; 356 + } 357 + 358 + if (entry->active) { 359 + ant_value_t args[0]; 360 + sv_vm_call(js->vm, js, entry->callback, js_mkundef(), args, 0, NULL, false); 361 + process_microtasks(js); 365 362 } 366 - } 363 + 364 + free(entry); 365 + }} 367 366 368 367 int has_pending_immediates(void) { 369 368 for (
+69 -60
src/streams/readable.c
··· 9 9 10 10 #include "silver/engine.h" 11 11 #include "modules/symbol.h" 12 + #include "modules/assert.h" 12 13 #include "streams/readable.h" 14 + #include "streams/pipes.h" 13 15 14 - static ant_value_t g_rs_proto; 15 - static ant_value_t g_reader_proto; 16 - static ant_value_t g_controller_proto; 16 + ant_value_t g_rs_proto; 17 + ant_value_t g_reader_proto; 18 + ant_value_t g_controller_proto; 17 19 18 20 rs_stream_t *rs_get_stream(ant_value_t obj) { 19 21 ant_value_t s = js_get_slot(obj, SLOT_DATA); ··· 21 23 return (rs_stream_t *)(uintptr_t)(size_t)js_getnum(s); 22 24 } 23 25 24 - static rs_controller_t *rs_get_controller(ant_value_t obj) { 26 + rs_controller_t *rs_get_controller(ant_value_t obj) { 25 27 ant_value_t s = js_get_slot(obj, SLOT_DATA); 26 28 if (vtype(s) != T_NUM) return NULL; 27 29 return (rs_controller_t *)(uintptr_t)(size_t)js_getnum(s); ··· 57 59 return js_get_slot(stream_obj, SLOT_CTOR); 58 60 } 59 61 60 - static inline ant_value_t rs_stream_error(ant_value_t stream_obj) { 62 + ant_value_t rs_stream_error(ant_value_t stream_obj) { 61 63 return js_get_slot(stream_obj, SLOT_BUFFER); 62 64 } 63 65 ··· 73 75 return js_get_slot(ctrl_obj, SLOT_RS_CANCEL); 74 76 } 75 77 76 - static inline ant_value_t rs_ctrl_size(ant_value_t ctrl_obj) { 78 + ant_value_t rs_ctrl_size(ant_value_t ctrl_obj) { 77 79 return js_get_slot(ctrl_obj, SLOT_RS_SIZE); 78 80 } 79 81 ··· 81 83 return js_get_slot(ctrl_obj, SLOT_BUFFER); 82 84 } 83 85 84 - static inline ant_value_t rs_reader_stream(ant_value_t reader_obj) { 86 + ant_value_t rs_reader_stream(ant_value_t reader_obj) { 85 87 return js_get_slot(reader_obj, SLOT_ENTRIES); 86 88 } 87 89 88 - static inline ant_value_t rs_reader_closed(ant_value_t reader_obj) { 90 + ant_value_t rs_reader_closed(ant_value_t reader_obj) { 89 91 return js_get_slot(reader_obj, SLOT_RS_CLOSED); 90 92 } 91 93 92 - static inline ant_value_t rs_reader_reqs(ant_value_t reader_obj) { 94 + ant_value_t rs_reader_reqs(ant_value_t reader_obj) { 93 95 return js_get_slot(reader_obj, SLOT_BUFFER); 94 96 } 95 97 96 - static bool rs_reader_has_reqs(ant_t *js, ant_value_t reader_obj) { 98 + bool rs_reader_has_reqs(ant_t *js, ant_value_t reader_obj) { 97 99 ant_value_t arr = rs_reader_reqs(reader_obj); 98 100 return vtype(arr) == T_ARR && js_arr_len(js, arr) > 0; 99 101 } 100 102 101 - static void rs_ctrl_queue_push(ant_t *js, ant_value_t ctrl_obj, ant_value_t value) { 103 + void rs_ctrl_queue_push(ant_t *js, ant_value_t ctrl_obj, ant_value_t value) { 102 104 ant_value_t arr = rs_ctrl_queue(js, ctrl_obj); 103 105 if (vtype(arr) == T_ARR) js_arr_push(js, arr, value); 104 106 } ··· 116 118 return val; 117 119 } 118 120 119 - static ant_offset_t rs_ctrl_queue_len(ant_t *js, ant_value_t ctrl_obj) { 121 + ant_offset_t rs_ctrl_queue_len(ant_t *js, ant_value_t ctrl_obj) { 120 122 ant_value_t arr = rs_ctrl_queue(js, ctrl_obj); 121 123 if (vtype(arr) != T_ARR) return 0; 122 124 return js_arr_len(js, arr); ··· 140 142 return val; 141 143 } 142 144 143 - static void rs_default_controller_call_pull_if_needed(ant_t *js, ant_value_t controller_obj); 144 - static bool rs_default_controller_can_close_or_enqueue(rs_controller_t *ctrl, rs_stream_t *stream); 145 + void rs_default_controller_call_pull_if_needed(ant_t *js, ant_value_t controller_obj); 146 + bool rs_default_controller_can_close_or_enqueue(rs_controller_t *ctrl, rs_stream_t *stream); 145 147 146 - static void rs_default_controller_clear_algorithms(ant_value_t ctrl_obj) { 148 + void rs_default_controller_clear_algorithms(ant_value_t ctrl_obj) { 147 149 js_set_slot(ctrl_obj, SLOT_RS_PULL, js_mkundef()); 148 150 js_set_slot(ctrl_obj, SLOT_RS_CANCEL, js_mkundef()); 149 151 js_set_slot(ctrl_obj, SLOT_RS_SIZE, js_mkundef()); ··· 168 170 return desired > 0; 169 171 } 170 172 171 - static bool rs_default_controller_can_close_or_enqueue(rs_controller_t *ctrl, rs_stream_t *stream) { 173 + bool rs_default_controller_can_close_or_enqueue(rs_controller_t *ctrl, rs_stream_t *stream) { 172 174 if (!ctrl || !stream) return false; 173 175 if (ctrl->close_requested) return false; 174 176 if (stream->state != RS_STATE_READABLE) return false; 175 177 return true; 176 178 } 177 179 178 - static void rs_fulfill_read_request(ant_t *js, ant_value_t stream_obj, ant_value_t chunk, bool done) { 180 + void rs_fulfill_read_request(ant_t *js, ant_value_t stream_obj, ant_value_t chunk, bool done) { 179 181 ant_value_t reader_obj = rs_stream_reader(stream_obj); 180 182 if (!is_object_type(reader_obj)) return; 181 183 ant_value_t promise = rs_reader_reqs_shift(js, reader_obj); ··· 184 186 js_resolve_promise(js, promise, result); 185 187 } 186 188 187 - static void rs_default_reader_error_read_requests(ant_t *js, ant_value_t reader_obj, ant_value_t e) { 189 + void rs_default_reader_error_read_requests(ant_t *js, ant_value_t reader_obj, ant_value_t e) { 188 190 ant_value_t arr = rs_reader_reqs(reader_obj); 189 191 if (vtype(arr) != T_ARR) return; 190 192 ant_offset_t len = js_arr_len(js, arr); ··· 228 230 } 229 231 } 230 232 231 - static ant_value_t rs_cancel_resolve(ant_t *js, ant_value_t *args, int nargs) { 233 + ant_value_t rs_cancel_resolve(ant_t *js, ant_value_t *args, int nargs) { 232 234 ant_value_t p = js_get_slot(js->current_func, SLOT_DATA); 233 235 js_resolve_promise(js, p, js_mkundef()); 234 236 return js_mkundef(); 235 237 } 236 238 237 - static ant_value_t rs_cancel_reject(ant_t *js, ant_value_t *args, int nargs) { 239 + ant_value_t rs_cancel_reject(ant_t *js, ant_value_t *args, int nargs) { 238 240 ant_value_t p = js_get_slot(js->current_func, SLOT_DATA); 239 241 js_reject_promise(js, p, nargs > 0 ? args[0] : js_mkundef()); 240 242 return js_mkundef(); ··· 308 310 return js_mkundef(); 309 311 } 310 312 311 - static void rs_default_controller_call_pull_if_needed(ant_t *js, ant_value_t controller_obj) { 313 + void rs_default_controller_call_pull_if_needed(ant_t *js, ant_value_t controller_obj) { 312 314 rs_controller_t *ctrl = rs_get_controller(controller_obj); 313 315 if (!ctrl) return; 316 + 314 317 ant_value_t stream_obj = rs_ctrl_stream(controller_obj); 315 318 rs_stream_t *stream = rs_get_stream(stream_obj); 316 319 if (!stream) return; 317 320 318 321 if (!rs_default_controller_should_call_pull(js, ctrl, stream, controller_obj)) return; 319 - 320 322 if (ctrl->pulling) { ctrl->pull_again = true; return; } 321 323 ctrl->pulling = true; 322 324 ··· 352 354 } else ctrl->pulling = false; 353 355 } 354 356 355 - static ant_value_t rs_default_reader_read(ant_t *js, ant_value_t reader_obj) { 357 + ant_value_t rs_default_reader_read(ant_t *js, ant_value_t reader_obj) { 356 358 ant_value_t stream_obj = rs_reader_stream(reader_obj); 357 359 rs_stream_t *stream = rs_get_stream(stream_obj); 358 360 if (!stream) return js_mkerr_typed(js, JS_ERR_TYPE, "Reader has no stream"); ··· 519 521 js_mkerr_typed(js, JS_ERR_TYPE, "Reader was released"); 520 522 ant_value_t release_err = js->thrown_value; 521 523 522 - if (stream->state == RS_STATE_READABLE) 523 - js_reject_promise(js, rs_reader_closed(js->this_val), release_err); 524 + if (stream->state == RS_STATE_READABLE) { 525 + ant_value_t old_closed = rs_reader_closed(js->this_val); 526 + js_reject_promise(js, old_closed, release_err); 527 + promise_mark_handled(old_closed); 528 + } 524 529 525 530 js_reject_promise(js, new_closed, release_err); 531 + promise_mark_handled(new_closed); 526 532 js_set_slot(js->this_val, SLOT_RS_CLOSED, new_closed); 527 533 528 534 js_set_slot(stream_obj, SLOT_CTOR, js_mkundef()); ··· 542 548 return readable_stream_cancel(js, stream_obj, reason); 543 549 } 544 550 545 - static ant_value_t js_rs_reader_ctor(ant_t *js, ant_value_t *args, int nargs) { 551 + ant_value_t js_rs_reader_ctor(ant_t *js, ant_value_t *args, int nargs) { 546 552 if (vtype(js->new_target) == T_UNDEF) 547 553 return js_mkerr_typed(js, JS_ERR_TYPE, "ReadableStreamDefaultReader constructor requires 'new'"); 548 554 if (nargs < 1) return js_mkerr_typed(js, JS_ERR_TYPE, "ReadableStreamDefaultReader requires a stream argument"); ··· 619 625 return reader; 620 626 } 621 627 622 - static ant_value_t js_rs_tee(ant_t *js, ant_value_t *args, int nargs) { 623 - return js_mkerr_typed(js, JS_ERR_TYPE, "ReadableStream.prototype.tee is not yet implemented"); 624 - } 625 - 626 - static ant_value_t js_rs_pipe_through(ant_t *js, ant_value_t *args, int nargs) { 627 - return js_mkerr_typed(js, JS_ERR_TYPE, "ReadableStream.prototype.pipeThrough is not yet implemented"); 628 - } 629 - 630 - static ant_value_t js_rs_pipe_to(ant_t *js, ant_value_t *args, int nargs) { 631 - return js_mkerr_typed(js, JS_ERR_TYPE, "ReadableStream.prototype.pipeTo is not yet implemented"); 632 - } 633 - 634 628 static ant_value_t js_rs_values(ant_t *js, ant_value_t *args, int nargs) { 635 629 return js_mkerr_typed(js, JS_ERR_TYPE, "ReadableStream async iteration is not yet implemented"); 636 630 } ··· 809 803 return obj; 810 804 } 811 805 806 + ant_value_t rs_create_stream(ant_t *js, ant_value_t pull_fn, ant_value_t cancel_fn, double hwm) { 807 + rs_stream_t *st = calloc(1, sizeof(rs_stream_t)); 808 + if (!st) return js_mkerr(js, "out of memory"); 809 + st->state = RS_STATE_READABLE; 810 + 811 + ant_value_t obj = js_mkobj(js); 812 + js_set_proto_init(obj, g_rs_proto); 813 + js_set_slot(obj, SLOT_DATA, ANT_PTR(st)); 814 + js_set_finalizer(obj, rs_stream_finalize); 815 + 816 + ant_value_t ctrl_obj = setup_default_controller(js, obj, pull_fn, cancel_fn, js_mkundef(), hwm); 817 + if (is_err(ctrl_obj)) return ctrl_obj; 818 + 819 + ant_value_t resolved = js_mkpromise(js); 820 + js_resolve_promise(js, resolved, js_mkundef()); 821 + ant_value_t res_fn = js_heavy_mkfun(js, rs_start_resolve_handler, ctrl_obj); 822 + ant_value_t rej_fn = js_heavy_mkfun(js, rs_start_reject_handler, ctrl_obj); 823 + ant_value_t then_fn = js_get(js, resolved, "then"); 824 + 825 + if (is_callable(then_fn)) { 826 + ant_value_t then_args[2] = { res_fn, rej_fn }; 827 + sv_vm_call(js->vm, js, then_fn, resolved, then_args, 2, NULL, false); 828 + } 829 + 830 + return obj; 831 + } 832 + 812 833 static ant_value_t js_rs_controller_ctor(ant_t *js, ant_value_t *args, int nargs) { 813 834 return js_mkerr_typed(js, JS_ERR_TYPE, "ReadableStreamDefaultController cannot be constructed directly"); 814 835 } ··· 824 845 ant_value_t g = js_glob(js); 825 846 826 847 g_controller_proto = js_mkobj(js); 827 - js_set_getter_desc(js, g_controller_proto, "desiredSize", 11, 828 - js_mkfun(js_rs_controller_get_desired_size), JS_DESC_C); 848 + js_set_getter_desc(js, g_controller_proto, "desiredSize", 11, js_mkfun(js_rs_controller_get_desired_size), JS_DESC_C); 829 849 js_set(js, g_controller_proto, "close", js_mkfun(js_rs_controller_close)); 830 850 js_set_descriptor(js, g_controller_proto, "close", 5, JS_DESC_W | JS_DESC_C); 831 851 js_set(js, g_controller_proto, "enqueue", js_mkfun(js_rs_controller_enqueue)); 832 852 js_set_descriptor(js, g_controller_proto, "enqueue", 7, JS_DESC_W | JS_DESC_C); 833 853 js_set(js, g_controller_proto, "error", js_mkfun(js_rs_controller_error)); 834 854 js_set_descriptor(js, g_controller_proto, "error", 5, JS_DESC_W | JS_DESC_C); 835 - js_set_sym(js, g_controller_proto, get_toStringTag_sym(), 836 - js_mkstr(js, "ReadableStreamDefaultController", 31)); 855 + js_set_sym(js, g_controller_proto, get_toStringTag_sym(), js_mkstr(js, "ReadableStreamDefaultController", 31)); 837 856 838 - ant_value_t ctrl_ctor = js_make_ctor(js, js_rs_controller_ctor, g_controller_proto, 839 - "ReadableStreamDefaultController", 31); 857 + ant_value_t ctrl_ctor = js_make_ctor(js, js_rs_controller_ctor, g_controller_proto, "ReadableStreamDefaultController", 31); 840 858 js_set(js, g, "ReadableStreamDefaultController", ctrl_ctor); 841 859 js_set_descriptor(js, g, "ReadableStreamDefaultController", 31, JS_DESC_W | JS_DESC_C); 842 860 843 861 g_reader_proto = js_mkobj(js); 844 - js_set_getter_desc(js, g_reader_proto, "closed", 6, 845 - js_mkfun(js_rs_reader_get_closed), JS_DESC_C); 862 + js_set_getter_desc(js, g_reader_proto, "closed", 6, js_mkfun(js_rs_reader_get_closed), JS_DESC_C); 846 863 js_set(js, g_reader_proto, "read", js_mkfun(js_rs_reader_read)); 847 864 js_set_descriptor(js, g_reader_proto, "read", 4, JS_DESC_W | JS_DESC_C); 848 865 js_set(js, g_reader_proto, "releaseLock", js_mkfun(js_rs_reader_release_lock)); 849 866 js_set_descriptor(js, g_reader_proto, "releaseLock", 11, JS_DESC_W | JS_DESC_C); 850 867 js_set(js, g_reader_proto, "cancel", js_mkfun(js_rs_reader_cancel)); 851 868 js_set_descriptor(js, g_reader_proto, "cancel", 6, JS_DESC_W | JS_DESC_C); 852 - js_set_sym(js, g_reader_proto, get_toStringTag_sym(), 853 - js_mkstr(js, "ReadableStreamDefaultReader", 27)); 869 + js_set_sym(js, g_reader_proto, get_toStringTag_sym(), js_mkstr(js, "ReadableStreamDefaultReader", 27)); 854 870 855 - ant_value_t reader_ctor = js_make_ctor(js, js_rs_reader_ctor, g_reader_proto, 856 - "ReadableStreamDefaultReader", 27); 871 + ant_value_t reader_ctor = js_make_ctor(js, js_rs_reader_ctor, g_reader_proto, "ReadableStreamDefaultReader", 27); 857 872 js_set(js, g, "ReadableStreamDefaultReader", reader_ctor); 858 873 js_set_descriptor(js, g, "ReadableStreamDefaultReader", 27, JS_DESC_W | JS_DESC_C); 859 874 860 875 g_rs_proto = js_mkobj(js); 861 - js_set_getter_desc(js, g_rs_proto, "locked", 6, 862 - js_mkfun(js_rs_get_locked), JS_DESC_C); 876 + js_set_getter_desc(js, g_rs_proto, "locked", 6, js_mkfun(js_rs_get_locked), JS_DESC_C); 863 877 js_set(js, g_rs_proto, "cancel", js_mkfun(js_rs_cancel)); 864 878 js_set_descriptor(js, g_rs_proto, "cancel", 6, JS_DESC_W | JS_DESC_C); 865 879 js_set(js, g_rs_proto, "getReader", js_mkfun(js_rs_get_reader)); 866 880 js_set_descriptor(js, g_rs_proto, "getReader", 9, JS_DESC_W | JS_DESC_C); 867 - js_set(js, g_rs_proto, "tee", js_mkfun(js_rs_tee)); 868 - js_set_descriptor(js, g_rs_proto, "tee", 3, JS_DESC_W | JS_DESC_C); 869 - js_set(js, g_rs_proto, "pipeThrough", js_mkfun(js_rs_pipe_through)); 870 - js_set_descriptor(js, g_rs_proto, "pipeThrough", 11, JS_DESC_W | JS_DESC_C); 871 - js_set(js, g_rs_proto, "pipeTo", js_mkfun(js_rs_pipe_to)); 872 - js_set_descriptor(js, g_rs_proto, "pipeTo", 6, JS_DESC_W | JS_DESC_C); 881 + init_pipes_proto(js, g_rs_proto); 882 + 873 883 js_set(js, g_rs_proto, "values", js_mkfun(js_rs_values)); 874 884 js_set_descriptor(js, g_rs_proto, "values", 6, JS_DESC_W | JS_DESC_C); 875 - js_set_sym(js, g_rs_proto, get_toStringTag_sym(), 876 - js_mkstr(js, "ReadableStream", 14)); 885 + js_set_sym(js, g_rs_proto, get_toStringTag_sym(), js_mkstr(js, "ReadableStream", 14)); 877 886 878 887 ant_value_t rs_ctor = js_make_ctor(js, js_rs_ctor, g_rs_proto, "ReadableStream", 14); 879 888 js_set(js, g, "ReadableStream", rs_ctor);
+27 -23
src/streams/writable.c
··· 9 9 10 10 #include "silver/engine.h" 11 11 #include "modules/symbol.h" 12 + #include "modules/assert.h" 12 13 #include "modules/abort.h" 13 14 #include "streams/writable.h" 14 15 ··· 23 24 return (ws_stream_t *)(uintptr_t)(size_t)js_getnum(s); 24 25 } 25 26 26 - static ws_controller_t *ws_get_controller(ant_value_t obj) { 27 + ws_controller_t *ws_get_controller(ant_value_t obj) { 27 28 ant_value_t s = js_get_slot(obj, SLOT_DATA); 28 29 if (vtype(s) != T_NUM) return NULL; 29 30 return (ws_controller_t *)(uintptr_t)(size_t)js_getnum(s); ··· 238 239 static void ws_writer_ensure_ready_promise_rejected(ant_t *js, ant_value_t writer_obj, ant_value_t error) { 239 240 ant_value_t ready = js_mkpromise(js); 240 241 js_reject_promise(js, ready, error); 242 + promise_mark_handled(ready); 241 243 js_set_slot(writer_obj, SLOT_WS_READY, ready); 242 244 } 243 245 244 246 static void ws_writer_ensure_closed_promise_rejected(ant_t *js, ant_value_t writer_obj, ant_value_t error) { 245 247 ant_value_t closed = js_mkpromise(js); 246 248 js_reject_promise(js, closed, error); 249 + promise_mark_handled(closed); 247 250 js_set_slot(writer_obj, SLOT_RS_CLOSED, closed); 248 251 } 249 252 ··· 755 758 return promise; 756 759 } 757 760 758 - static ant_value_t ws_writer_write(ant_t *js, ant_value_t writer_obj, ant_value_t chunk) { 761 + ant_value_t ws_writer_write(ant_t *js, ant_value_t writer_obj, ant_value_t chunk) { 759 762 ant_value_t stream_obj = ws_writer_stream(writer_obj); 760 763 if (!is_object_type(stream_obj)) { 761 764 ant_value_t p = js_mkpromise(js); ··· 948 951 return ws_writer_write(js, js->this_val, chunk); 949 952 } 950 953 951 - static ant_value_t js_ws_writer_ctor(ant_t *js, ant_value_t *args, int nargs) { 954 + ant_value_t js_ws_writer_ctor(ant_t *js, ant_value_t *args, int nargs) { 952 955 if (vtype(js->new_target) == T_UNDEF) 953 956 return js_mkerr_typed(js, JS_ERR_TYPE, "WritableStreamDefaultWriter constructor requires 'new'"); 954 957 if (nargs < 1) ··· 992 995 return obj; 993 996 } 994 997 998 + ant_value_t ws_acquire_writer(ant_t *js, ant_value_t stream_obj) { 999 + ant_value_t writer_args[1] = { stream_obj }; 1000 + ant_value_t saved = js->new_target; 1001 + 1002 + js->new_target = g_writer_proto; 1003 + ant_value_t writer = js_ws_writer_ctor(js, writer_args, 1); 1004 + js->new_target = saved; 1005 + 1006 + return writer; 1007 + } 1008 + 995 1009 static ant_value_t js_ws_get_locked(ant_t *js, ant_value_t *args, int nargs) { 996 1010 ws_stream_t *stream = ws_get_stream(js->this_val); 997 1011 if (!stream) return js_mkerr_typed(js, JS_ERR_TYPE, "Invalid WritableStream"); ··· 1233 1247 g_close_sentinel = js_mkobj(js); 1234 1248 g_controller_proto = js_mkobj(js); 1235 1249 1236 - js_set_getter_desc(js, g_controller_proto, "signal", 6, 1237 - js_mkfun(js_ws_controller_get_signal), JS_DESC_C); 1250 + js_set_getter_desc(js, g_controller_proto, "signal", 6, js_mkfun(js_ws_controller_get_signal), JS_DESC_C); 1238 1251 js_set(js, g_controller_proto, "error", js_mkfun(js_ws_controller_error)); 1239 1252 js_set_descriptor(js, g_controller_proto, "error", 5, JS_DESC_W | JS_DESC_C); 1240 - js_set_sym(js, g_controller_proto, get_toStringTag_sym(), 1241 - js_mkstr(js, "WritableStreamDefaultController", 31)); 1253 + js_set_sym(js, g_controller_proto, get_toStringTag_sym(), js_mkstr(js, "WritableStreamDefaultController", 31)); 1242 1254 1243 - ant_value_t ctrl_ctor = js_make_ctor(js, js_ws_controller_ctor, g_controller_proto, 1244 - "WritableStreamDefaultController", 31); 1255 + ant_value_t ctrl_ctor = js_make_ctor(js, js_ws_controller_ctor, g_controller_proto, "WritableStreamDefaultController", 31); 1245 1256 js_set(js, g, "WritableStreamDefaultController", ctrl_ctor); 1246 1257 js_set_descriptor(js, g, "WritableStreamDefaultController", 31, JS_DESC_W | JS_DESC_C); 1247 1258 1248 1259 g_writer_proto = js_mkobj(js); 1249 - js_set_getter_desc(js, g_writer_proto, "closed", 6, 1250 - js_mkfun(js_ws_writer_get_closed), JS_DESC_C); 1251 - js_set_getter_desc(js, g_writer_proto, "desiredSize", 11, 1252 - js_mkfun(js_ws_writer_get_desired_size), JS_DESC_C); 1253 - js_set_getter_desc(js, g_writer_proto, "ready", 5, 1254 - js_mkfun(js_ws_writer_get_ready), JS_DESC_C); 1260 + js_set_getter_desc(js, g_writer_proto, "closed", 6, js_mkfun(js_ws_writer_get_closed), JS_DESC_C); 1261 + js_set_getter_desc(js, g_writer_proto, "desiredSize", 11, js_mkfun(js_ws_writer_get_desired_size), JS_DESC_C); 1262 + js_set_getter_desc(js, g_writer_proto, "ready", 5, js_mkfun(js_ws_writer_get_ready), JS_DESC_C); 1255 1263 js_set(js, g_writer_proto, "abort", js_mkfun(js_ws_writer_abort)); 1256 1264 js_set_descriptor(js, g_writer_proto, "abort", 5, JS_DESC_W | JS_DESC_C); 1257 1265 js_set(js, g_writer_proto, "close", js_mkfun(js_ws_writer_close)); ··· 1260 1268 js_set_descriptor(js, g_writer_proto, "releaseLock", 11, JS_DESC_W | JS_DESC_C); 1261 1269 js_set(js, g_writer_proto, "write", js_mkfun(js_ws_writer_write)); 1262 1270 js_set_descriptor(js, g_writer_proto, "write", 5, JS_DESC_W | JS_DESC_C); 1263 - js_set_sym(js, g_writer_proto, get_toStringTag_sym(), 1264 - js_mkstr(js, "WritableStreamDefaultWriter", 27)); 1271 + js_set_sym(js, g_writer_proto, get_toStringTag_sym(), js_mkstr(js, "WritableStreamDefaultWriter", 27)); 1265 1272 1266 - ant_value_t writer_ctor = js_make_ctor(js, js_ws_writer_ctor, g_writer_proto, 1267 - "WritableStreamDefaultWriter", 27); 1273 + ant_value_t writer_ctor = js_make_ctor(js, js_ws_writer_ctor, g_writer_proto, "WritableStreamDefaultWriter", 27); 1268 1274 js_set(js, g, "WritableStreamDefaultWriter", writer_ctor); 1269 1275 js_set_descriptor(js, g, "WritableStreamDefaultWriter", 27, JS_DESC_W | JS_DESC_C); 1270 1276 1271 1277 g_ws_proto = js_mkobj(js); 1272 - js_set_getter_desc(js, g_ws_proto, "locked", 6, 1273 - js_mkfun(js_ws_get_locked), JS_DESC_C); 1278 + js_set_getter_desc(js, g_ws_proto, "locked", 6, js_mkfun(js_ws_get_locked), JS_DESC_C); 1274 1279 js_set(js, g_ws_proto, "abort", js_mkfun(js_ws_abort)); 1275 1280 js_set_descriptor(js, g_ws_proto, "abort", 5, JS_DESC_W | JS_DESC_C); 1276 1281 js_set(js, g_ws_proto, "close", js_mkfun(js_ws_close)); 1277 1282 js_set_descriptor(js, g_ws_proto, "close", 5, JS_DESC_W | JS_DESC_C); 1278 1283 js_set(js, g_ws_proto, "getWriter", js_mkfun(js_ws_get_writer)); 1279 1284 js_set_descriptor(js, g_ws_proto, "getWriter", 9, JS_DESC_W | JS_DESC_C); 1280 - js_set_sym(js, g_ws_proto, get_toStringTag_sym(), 1281 - js_mkstr(js, "WritableStream", 14)); 1285 + js_set_sym(js, g_ws_proto, get_toStringTag_sym(), js_mkstr(js, "WritableStream", 14)); 1282 1286 1283 1287 ant_value_t ws_ctor = js_make_ctor(js, js_ws_ctor, g_ws_proto, "WritableStream", 14); 1284 1288 js_set(js, g, "WritableStream", ws_ctor);