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.

implement base ReadableStream

+1032
+170
examples/spec/streams-readable.js
··· 1 + import { test, testDeep, testThrows, summary } from './helpers.js'; 2 + 3 + console.log('ReadableStream / DefaultController / DefaultReader Tests\n'); 4 + 5 + test('RS typeof', typeof ReadableStream, 'function'); 6 + test('RS toStringTag', Object.prototype.toString.call(new ReadableStream()), '[object ReadableStream]'); 7 + 8 + const rs = new ReadableStream(); 9 + test('RS locked initially false', rs.locked, false); 10 + 11 + testThrows('RS requires new', () => ReadableStream()); 12 + testThrows('RS rejects null source', () => new ReadableStream(null)); 13 + testThrows('RS rejects invalid type', () => new ReadableStream({ type: 'invalid' })); 14 + testThrows('RS rejects null type', () => new ReadableStream({ type: null })); 15 + 16 + const rs2 = new ReadableStream({ type: undefined }); 17 + test('RS accepts undefined type', rs2.locked, false); 18 + 19 + let startCalled = false; 20 + let startController = null; 21 + const rs3 = new ReadableStream({ 22 + start(c) { startCalled = true; startController = c; } 23 + }); 24 + test('start called synchronously', startCalled, true); 25 + test('controller has desiredSize', startController.desiredSize, 1); 26 + test('controller toStringTag', Object.prototype.toString.call(startController), '[object ReadableStreamDefaultController]'); 27 + 28 + testThrows('controller cannot be constructed', () => new ReadableStreamDefaultController()); 29 + 30 + const rs4 = new ReadableStream({ 31 + start(c) { c.enqueue('a'); c.enqueue('b'); c.close(); } 32 + }); 33 + 34 + const reader = rs4.getReader(); 35 + test('locked after getReader', rs4.locked, true); 36 + test('reader toStringTag', Object.prototype.toString.call(reader), '[object ReadableStreamDefaultReader]'); 37 + 38 + testThrows('cannot get second reader', () => rs4.getReader()); 39 + testThrows('getReader rejects unknown mode', () => new ReadableStream().getReader({ mode: 'potato' })); 40 + 41 + async function testReadSequence() { 42 + const r1 = await reader.read(); 43 + test('read 1 value', r1.value, 'a'); 44 + test('read 1 done', r1.done, false); 45 + 46 + const r2 = await reader.read(); 47 + test('read 2 value', r2.value, 'b'); 48 + test('read 2 done', r2.done, false); 49 + 50 + const r3 = await reader.read(); 51 + test('read 3 done', r3.done, true); 52 + test('read 3 value', r3.value, undefined); 53 + } 54 + 55 + async function testClosedPromise() { 56 + const rs = new ReadableStream({ 57 + start(c) { c.close(); } 58 + }); 59 + const reader = rs.getReader(); 60 + await reader.closed; 61 + test('closed resolves on close', true, true); 62 + } 63 + 64 + async function testCancel() { 65 + let cancelReason = null; 66 + const rs = new ReadableStream({ 67 + cancel(reason) { cancelReason = reason; } 68 + }); 69 + await rs.cancel('test reason'); 70 + test('cancel passes reason', cancelReason, 'test reason'); 71 + } 72 + 73 + async function testPullBackpressure() { 74 + let pullCount = 0; 75 + const rs = new ReadableStream({ 76 + pull(c) { 77 + pullCount++; 78 + c.enqueue(pullCount); 79 + } 80 + }, { highWaterMark: 1 }); 81 + 82 + await new Promise(r => setTimeout(r, 50)); 83 + test('pull called once at start', pullCount, 1); 84 + 85 + const reader = rs.getReader(); 86 + const r1 = await reader.read(); 87 + test('pull backpressure value', r1.value, 1); 88 + 89 + await new Promise(r => setTimeout(r, 50)); 90 + test('pull called again after read', pullCount, 2); 91 + } 92 + 93 + async function testReleaseLock() { 94 + const rs = new ReadableStream({ 95 + start(c) { c.enqueue('x'); } 96 + }); 97 + const reader = rs.getReader(); 98 + reader.releaseLock(); 99 + test('locked false after release', rs.locked, false); 100 + 101 + const reader2 = rs.getReader(); 102 + const r = await reader2.read(); 103 + test('new reader can read', r.value, 'x'); 104 + } 105 + 106 + async function testDesiredSize() { 107 + let ctrl; 108 + new ReadableStream({ 109 + start(c) { 110 + ctrl = c; 111 + } 112 + }); 113 + await new Promise(r => setTimeout(r, 0)); 114 + test('desiredSize initially 1', ctrl.desiredSize, 1); 115 + ctrl.enqueue('a'); 116 + test('desiredSize after enqueue', ctrl.desiredSize, 0); 117 + ctrl.close(); 118 + test('desiredSize after close', ctrl.desiredSize, 0); 119 + } 120 + 121 + async function testErrorStream() { 122 + const err = new Error('boom'); 123 + const rs = new ReadableStream({ 124 + start(c) { c.error(err); } 125 + }); 126 + const reader = rs.getReader(); 127 + try { 128 + await reader.read(); 129 + test('errored stream should reject read', false, true); 130 + } catch (e) { 131 + test('errored stream rejects with error', e, err); 132 + } 133 + } 134 + 135 + async function testCustomStrategy() { 136 + const rs = new ReadableStream({ 137 + start(c) { 138 + c.enqueue(new Uint8Array(10)); 139 + c.enqueue(new Uint8Array(20)); 140 + } 141 + }, { 142 + highWaterMark: 64, 143 + size(chunk) { return chunk.byteLength; } 144 + }); 145 + 146 + const reader = rs.getReader(); 147 + const r1 = await reader.read(); 148 + test('custom strategy chunk size', r1.value.byteLength, 10); 149 + } 150 + 151 + async function testSubclass() { 152 + class MyStream extends ReadableStream { 153 + myMethod() { return 42; } 154 + } 155 + const ms = new MyStream({ start(c) { c.close(); } }); 156 + test('subclass instanceof', ms instanceof ReadableStream, true); 157 + test('subclass method', ms.myMethod(), 42); 158 + } 159 + 160 + await testReadSequence(); 161 + await testClosedPromise(); 162 + await testCancel(); 163 + await testPullBackpressure(); 164 + await testReleaseLock(); 165 + await testDesiredSize(); 166 + await testErrorStream(); 167 + await testCustomStrategy(); 168 + await testSubclass(); 169 + 170 + summary();
+4
include/common.h
··· 62 62 SLOT_WT_ENV_STORE, 63 63 SLOT_NAPI_EXTERNAL_ID, 64 64 SLOT_NAPI_WRAP_ID, 65 + SLOT_RS_PULL, 66 + SLOT_RS_CANCEL, 67 + SLOT_RS_SIZE, 68 + SLOT_RS_CLOSED, 65 69 SLOT_MAX = 255 66 70 } internal_slot_t; 67 71
+1
include/gc/modules.h
··· 21 21 void gc_mark_worker_threads(ant_t *js, gc_mark_fn mark); 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 + void gc_mark_readable_streams(ant_t *js, gc_mark_fn mark); 24 25 25 26 #endif
+31
include/streams/readable.h
··· 1 + #ifndef STREAMS_READABLE_H 2 + #define STREAMS_READABLE_H 3 + 4 + #include "types.h" 5 + #include <stdbool.h> 6 + #include <stddef.h> 7 + 8 + typedef enum { 9 + RS_STATE_READABLE = 0, 10 + RS_STATE_CLOSED, 11 + RS_STATE_ERRORED, 12 + } rs_state_t; 13 + 14 + typedef struct { 15 + double queue_total_size; 16 + double strategy_hwm; 17 + bool close_requested; 18 + bool pull_again; 19 + bool pulling; 20 + bool started; 21 + } rs_controller_t; 22 + 23 + typedef struct { 24 + rs_state_t state; 25 + bool disturbed; 26 + } rs_stream_t; 27 + 28 + void init_readable_stream_module(void); 29 + void gc_mark_readable_streams(ant_t *js, void (*mark)(ant_t *, ant_value_t)); 30 + 31 + #endif
+1
src/gc/objects.c
··· 454 454 gc_mark_worker_threads(js, gc_mark_value); 455 455 gc_mark_abort(js, gc_mark_value); 456 456 gc_mark_domexception(js, gc_mark_value); 457 + gc_mark_readable_streams(js, gc_mark_value); 457 458 458 459 for ( 459 460 ant_object_t *obj = g_pending_promises;
+2
src/main.c
··· 80 80 #include "modules/blob.h" 81 81 #include "modules/formdata.h" 82 82 #include "streams/queuing.h" 83 + #include "streams/readable.h" 83 84 84 85 int js_result = EXIT_SUCCESS; 85 86 typedef int (*cmd_fn)(int argc, char **argv); ··· 597 598 init_regex_module(); 598 599 init_collections_module(); 599 600 init_queuing_strategies_module(); 601 + init_readable_stream_module(); 600 602 init_builtin_module(); 601 603 init_buffer_module(); 602 604 init_fs_module();
+823
src/streams/readable.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/readable.h" 13 + 14 + static ant_value_t g_rs_proto; 15 + static ant_value_t g_reader_proto; 16 + static ant_value_t g_controller_proto; 17 + 18 + static rs_stream_t *rs_get_stream(ant_value_t obj) { 19 + ant_value_t s = js_get_slot(obj, SLOT_DATA); 20 + if (vtype(s) != T_NUM) return NULL; 21 + return (rs_stream_t *)(uintptr_t)(size_t)js_getnum(s); 22 + } 23 + 24 + static rs_controller_t *rs_get_controller(ant_value_t obj) { 25 + ant_value_t s = js_get_slot(obj, SLOT_DATA); 26 + if (vtype(s) != T_NUM) return NULL; 27 + return (rs_controller_t *)(uintptr_t)(size_t)js_getnum(s); 28 + } 29 + 30 + static void rs_stream_finalize(ant_t *js, ant_object_t *obj) { 31 + if (!obj->extra_slots) return; 32 + ant_extra_slot_t *entries = (ant_extra_slot_t *)obj->extra_slots; 33 + for (uint8_t i = 0; i < obj->extra_count; i++) { 34 + if (entries[i].slot == SLOT_DATA && vtype(entries[i].value) == T_NUM) { 35 + free((rs_stream_t *)(uintptr_t)(size_t)js_getnum(entries[i].value)); 36 + return; 37 + }} 38 + } 39 + 40 + static void rs_controller_finalize(ant_t *js, ant_object_t *obj) { 41 + if (!obj->extra_slots) return; 42 + ant_extra_slot_t *entries = (ant_extra_slot_t *)obj->extra_slots; 43 + for (uint8_t i = 0; i < obj->extra_count; i++) { 44 + if (entries[i].slot == SLOT_DATA && vtype(entries[i].value) == T_NUM) { 45 + free((rs_controller_t *)(uintptr_t)(size_t)js_getnum(entries[i].value)); 46 + return; 47 + }} 48 + } 49 + 50 + static ant_value_t rs_stream_controller(ant_t *js, ant_value_t stream_obj) { 51 + return js_get_slot(stream_obj, SLOT_ENTRIES); 52 + } 53 + 54 + static ant_value_t rs_stream_reader(ant_value_t stream_obj) { 55 + return js_get_slot(stream_obj, SLOT_CTOR); 56 + } 57 + 58 + static ant_value_t rs_stream_error(ant_value_t stream_obj) { 59 + return js_get_slot(stream_obj, SLOT_BUFFER); 60 + } 61 + 62 + static ant_value_t rs_ctrl_stream(ant_value_t ctrl_obj) { 63 + return js_get_slot(ctrl_obj, SLOT_ENTRIES); 64 + } 65 + 66 + static ant_value_t rs_ctrl_pull(ant_value_t ctrl_obj) { 67 + return js_get_slot(ctrl_obj, SLOT_RS_PULL); 68 + } 69 + 70 + static ant_value_t rs_ctrl_cancel(ant_value_t ctrl_obj) { 71 + return js_get_slot(ctrl_obj, SLOT_RS_CANCEL); 72 + } 73 + 74 + static ant_value_t rs_ctrl_size(ant_value_t ctrl_obj) { 75 + return js_get_slot(ctrl_obj, SLOT_RS_SIZE); 76 + } 77 + 78 + static ant_value_t rs_ctrl_queue(ant_t *js, ant_value_t ctrl_obj) { 79 + return js_get_slot(ctrl_obj, SLOT_BUFFER); 80 + } 81 + 82 + static ant_value_t rs_reader_stream(ant_value_t reader_obj) { 83 + return js_get_slot(reader_obj, SLOT_ENTRIES); 84 + } 85 + 86 + static ant_value_t rs_reader_closed(ant_value_t reader_obj) { 87 + return js_get_slot(reader_obj, SLOT_RS_CLOSED); 88 + } 89 + 90 + static ant_value_t rs_reader_reqs(ant_value_t reader_obj) { 91 + return js_get_slot(reader_obj, SLOT_BUFFER); 92 + } 93 + 94 + static bool rs_reader_has_reqs(ant_t *js, ant_value_t reader_obj) { 95 + ant_value_t arr = rs_reader_reqs(reader_obj); 96 + return vtype(arr) == T_ARR && js_arr_len(js, arr) > 0; 97 + } 98 + 99 + static void rs_ctrl_queue_push(ant_t *js, ant_value_t ctrl_obj, ant_value_t value) { 100 + ant_value_t arr = rs_ctrl_queue(js, ctrl_obj); 101 + if (vtype(arr) == T_ARR) js_arr_push(js, arr, value); 102 + } 103 + 104 + static ant_value_t rs_ctrl_queue_shift(ant_t *js, ant_value_t ctrl_obj) { 105 + ant_value_t arr = rs_ctrl_queue(js, ctrl_obj); 106 + if (vtype(arr) != T_ARR) return js_mkundef(); 107 + ant_object_t *aobj = js_obj_ptr(arr); 108 + if (aobj->u.array.len == 0) return js_mkundef(); 109 + ant_value_t val = aobj->u.array.data[0]; 110 + uint32_t new_len = aobj->u.array.len - 1; 111 + for (uint32_t i = 0; i < new_len; i++) 112 + aobj->u.array.data[i] = aobj->u.array.data[i + 1]; 113 + aobj->u.array.len = new_len; 114 + return val; 115 + } 116 + 117 + static ant_offset_t rs_ctrl_queue_len(ant_t *js, ant_value_t ctrl_obj) { 118 + ant_value_t arr = rs_ctrl_queue(js, ctrl_obj); 119 + if (vtype(arr) != T_ARR) return 0; 120 + return js_arr_len(js, arr); 121 + } 122 + 123 + static void rs_reader_reqs_push(ant_t *js, ant_value_t reader_obj, ant_value_t promise) { 124 + ant_value_t arr = rs_reader_reqs(reader_obj); 125 + if (vtype(arr) == T_ARR) js_arr_push(js, arr, promise); 126 + } 127 + 128 + static ant_value_t rs_reader_reqs_shift(ant_t *js, ant_value_t reader_obj) { 129 + ant_value_t arr = rs_reader_reqs(reader_obj); 130 + if (vtype(arr) != T_ARR) return js_mkundef(); 131 + ant_object_t *aobj = js_obj_ptr(arr); 132 + if (aobj->u.array.len == 0) return js_mkundef(); 133 + ant_value_t val = aobj->u.array.data[0]; 134 + uint32_t new_len = aobj->u.array.len - 1; 135 + for (uint32_t i = 0; i < new_len; i++) 136 + aobj->u.array.data[i] = aobj->u.array.data[i + 1]; 137 + aobj->u.array.len = new_len; 138 + return val; 139 + } 140 + 141 + static void rs_default_controller_call_pull_if_needed(ant_t *js, ant_value_t controller_obj); 142 + static void readable_stream_close(ant_t *js, ant_value_t stream_obj); 143 + static void readable_stream_error(ant_t *js, ant_value_t stream_obj, ant_value_t e); 144 + static bool rs_default_controller_can_close_or_enqueue(rs_controller_t *ctrl, rs_stream_t *stream); 145 + 146 + static void rs_default_controller_clear_algorithms(ant_value_t ctrl_obj) { 147 + js_set_slot(ctrl_obj, SLOT_RS_PULL, js_mkundef()); 148 + js_set_slot(ctrl_obj, SLOT_RS_CANCEL, js_mkundef()); 149 + js_set_slot(ctrl_obj, SLOT_RS_SIZE, js_mkundef()); 150 + } 151 + 152 + static double rs_default_controller_get_desired_size(rs_controller_t *ctrl, rs_stream_t *stream) { 153 + if (!stream) return 0; 154 + if (stream->state == RS_STATE_ERRORED) return -1; 155 + if (stream->state == RS_STATE_CLOSED) return 0; 156 + return ctrl->strategy_hwm - ctrl->queue_total_size; 157 + } 158 + 159 + static bool rs_default_controller_should_call_pull(ant_t *js, rs_controller_t *ctrl, rs_stream_t *stream, ant_value_t ctrl_obj) { 160 + if (!rs_default_controller_can_close_or_enqueue(ctrl, stream)) return false; 161 + if (!ctrl->started) return false; 162 + 163 + ant_value_t stream_obj = rs_ctrl_stream(ctrl_obj); 164 + ant_value_t reader_obj = rs_stream_reader(stream_obj); 165 + if (is_object_type(reader_obj) && rs_reader_has_reqs(js, reader_obj)) return true; 166 + 167 + double desired = rs_default_controller_get_desired_size(ctrl, stream); 168 + return desired > 0; 169 + } 170 + 171 + static bool rs_default_controller_can_close_or_enqueue(rs_controller_t *ctrl, rs_stream_t *stream) { 172 + if (!ctrl || !stream) return false; 173 + if (ctrl->close_requested) return false; 174 + if (stream->state != RS_STATE_READABLE) return false; 175 + return true; 176 + } 177 + 178 + static void rs_fulfill_read_request(ant_t *js, ant_value_t stream_obj, ant_value_t chunk, bool done) { 179 + ant_value_t reader_obj = rs_stream_reader(stream_obj); 180 + if (!is_object_type(reader_obj)) return; 181 + ant_value_t promise = rs_reader_reqs_shift(js, reader_obj); 182 + if (vtype(promise) == T_UNDEF) return; 183 + ant_value_t result = js_iter_result(js, !done, chunk); 184 + js_resolve_promise(js, promise, result); 185 + } 186 + 187 + static void rs_default_reader_error_read_requests(ant_t *js, ant_value_t reader_obj, ant_value_t e) { 188 + ant_value_t arr = rs_reader_reqs(reader_obj); 189 + if (vtype(arr) != T_ARR) return; 190 + ant_offset_t len = js_arr_len(js, arr); 191 + for (ant_offset_t i = 0; i < len; i++) 192 + js_reject_promise(js, js_arr_get(js, arr, i), e); 193 + ant_object_t *aobj = js_obj_ptr(arr); 194 + aobj->u.array.len = 0; 195 + } 196 + 197 + static void readable_stream_close(ant_t *js, ant_value_t stream_obj) { 198 + rs_stream_t *stream = rs_get_stream(stream_obj); 199 + if (!stream) return; 200 + stream->state = RS_STATE_CLOSED; 201 + 202 + ant_value_t reader_obj = rs_stream_reader(stream_obj); 203 + if (is_object_type(reader_obj)) { 204 + ant_value_t arr = rs_reader_reqs(reader_obj); 205 + if (vtype(arr) == T_ARR) { 206 + ant_offset_t len = js_arr_len(js, arr); 207 + for (ant_offset_t i = 0; i < len; i++) { 208 + ant_value_t result = js_iter_result(js, false, js_mkundef()); 209 + js_resolve_promise(js, js_arr_get(js, arr, i), result); 210 + } 211 + ant_object_t *aobj = js_obj_ptr(arr); 212 + aobj->u.array.len = 0; 213 + } 214 + js_resolve_promise(js, rs_reader_closed(reader_obj), js_mkundef()); 215 + } 216 + } 217 + 218 + static void readable_stream_error(ant_t *js, ant_value_t stream_obj, ant_value_t e) { 219 + rs_stream_t *stream = rs_get_stream(stream_obj); 220 + if (!stream) return; 221 + stream->state = RS_STATE_ERRORED; 222 + js_set_slot(stream_obj, SLOT_BUFFER, e); 223 + 224 + ant_value_t reader_obj = rs_stream_reader(stream_obj); 225 + if (is_object_type(reader_obj)) { 226 + js_reject_promise(js, rs_reader_closed(reader_obj), e); 227 + rs_default_reader_error_read_requests(js, reader_obj, e); 228 + } 229 + } 230 + 231 + static ant_value_t readable_stream_cancel(ant_t *js, ant_value_t stream_obj, ant_value_t reason) { 232 + rs_stream_t *stream = rs_get_stream(stream_obj); 233 + if (!stream) return js_mkundef(); 234 + stream->disturbed = true; 235 + 236 + if (stream->state == RS_STATE_CLOSED) { 237 + ant_value_t p = js_mkpromise(js); 238 + js_resolve_promise(js, p, js_mkundef()); 239 + return p; 240 + } 241 + if (stream->state == RS_STATE_ERRORED) { 242 + ant_value_t p = js_mkpromise(js); 243 + js_reject_promise(js, p, rs_stream_error(stream_obj)); 244 + return p; 245 + } 246 + 247 + readable_stream_close(js, stream_obj); 248 + 249 + ant_value_t ctrl_obj = rs_stream_controller(js, stream_obj); 250 + ant_value_t cancel_fn = rs_ctrl_cancel(ctrl_obj); 251 + ant_value_t result = js_mkundef(); 252 + if (is_callable(cancel_fn)) { 253 + ant_value_t args[1] = { reason }; 254 + result = sv_vm_call(js->vm, js, cancel_fn, ctrl_obj, args, 1, NULL, false); 255 + } 256 + rs_default_controller_clear_algorithms(ctrl_obj); 257 + 258 + ant_value_t p = js_mkpromise(js); 259 + if (is_err(result)) 260 + js_reject_promise(js, p, result); 261 + else 262 + js_resolve_promise(js, p, js_mkundef()); 263 + return p; 264 + } 265 + 266 + static ant_value_t rs_pull_resolve_handler(ant_t *js, ant_value_t *args, int nargs) { 267 + ant_value_t ctrl_obj = js_get_slot(js->current_func, SLOT_DATA); 268 + rs_controller_t *ctrl = rs_get_controller(ctrl_obj); 269 + if (!ctrl) return js_mkundef(); 270 + ctrl->pulling = false; 271 + if (ctrl->pull_again) { 272 + ctrl->pull_again = false; 273 + rs_default_controller_call_pull_if_needed(js, ctrl_obj); 274 + } 275 + return js_mkundef(); 276 + } 277 + 278 + static ant_value_t rs_pull_reject_handler(ant_t *js, ant_value_t *args, int nargs) { 279 + ant_value_t ctrl_obj = js_get_slot(js->current_func, SLOT_DATA); 280 + rs_controller_t *ctrl = rs_get_controller(ctrl_obj); 281 + if (!ctrl) return js_mkundef(); 282 + ant_value_t stream_obj = rs_ctrl_stream(ctrl_obj); 283 + rs_stream_t *stream = rs_get_stream(stream_obj); 284 + if (stream && stream->state == RS_STATE_READABLE) 285 + readable_stream_error(js, stream_obj, nargs > 0 ? args[0] : js_mkundef()); 286 + return js_mkundef(); 287 + } 288 + 289 + static void rs_default_controller_call_pull_if_needed(ant_t *js, ant_value_t controller_obj) { 290 + rs_controller_t *ctrl = rs_get_controller(controller_obj); 291 + if (!ctrl) return; 292 + ant_value_t stream_obj = rs_ctrl_stream(controller_obj); 293 + rs_stream_t *stream = rs_get_stream(stream_obj); 294 + if (!stream) return; 295 + 296 + if (!rs_default_controller_should_call_pull(js, ctrl, stream, controller_obj)) return; 297 + 298 + if (ctrl->pulling) { ctrl->pull_again = true; return; } 299 + ctrl->pulling = true; 300 + 301 + ant_value_t pull_fn = rs_ctrl_pull(controller_obj); 302 + if (is_callable(pull_fn)) { 303 + ant_value_t args[1] = { controller_obj }; 304 + ant_value_t result = sv_vm_call(js->vm, js, pull_fn, js_mkundef(), args, 1, NULL, false); 305 + 306 + if (vtype(result) == T_PROMISE) { 307 + ant_value_t resolve_fn = js_heavy_mkfun(js, rs_pull_resolve_handler, controller_obj); 308 + ant_value_t reject_fn = js_heavy_mkfun(js, rs_pull_reject_handler, controller_obj); 309 + ant_value_t then_fn = js_get(js, result, "then"); 310 + if (is_callable(then_fn)) { 311 + ant_value_t then_args[2] = { resolve_fn, reject_fn }; 312 + sv_vm_call(js->vm, js, then_fn, result, then_args, 2, NULL, false); 313 + } 314 + } else if (is_err(result)) { 315 + if (stream->state == RS_STATE_READABLE) { 316 + ant_value_t thrown = js->thrown_value; 317 + readable_stream_error(js, stream_obj, is_object_type(thrown) ? thrown : result); 318 + } 319 + } else { 320 + ant_value_t resolved = js_mkpromise(js); 321 + js_resolve_promise(js, resolved, js_mkundef()); 322 + ant_value_t resolve_fn = js_heavy_mkfun(js, rs_pull_resolve_handler, controller_obj); 323 + ant_value_t reject_fn = js_heavy_mkfun(js, rs_pull_reject_handler, controller_obj); 324 + ant_value_t then_fn = js_get(js, resolved, "then"); 325 + if (is_callable(then_fn)) { 326 + ant_value_t then_args[2] = { resolve_fn, reject_fn }; 327 + sv_vm_call(js->vm, js, then_fn, resolved, then_args, 2, NULL, false); 328 + } 329 + } 330 + } else ctrl->pulling = false; 331 + } 332 + 333 + static ant_value_t rs_default_reader_read(ant_t *js, ant_value_t reader_obj) { 334 + ant_value_t stream_obj = rs_reader_stream(reader_obj); 335 + rs_stream_t *stream = rs_get_stream(stream_obj); 336 + if (!stream) return js_mkerr_typed(js, JS_ERR_TYPE, "Reader has no stream"); 337 + 338 + stream->disturbed = true; 339 + 340 + if (stream->state == RS_STATE_CLOSED) { 341 + ant_value_t p = js_mkpromise(js); 342 + js_resolve_promise(js, p, js_iter_result(js, false, js_mkundef())); 343 + return p; 344 + } 345 + if (stream->state == RS_STATE_ERRORED) { 346 + ant_value_t p = js_mkpromise(js); 347 + js_reject_promise(js, p, rs_stream_error(stream_obj)); 348 + return p; 349 + } 350 + 351 + ant_value_t ctrl_obj = rs_stream_controller(js, stream_obj); 352 + rs_controller_t *ctrl = rs_get_controller(ctrl_obj); 353 + if (ctrl && rs_ctrl_queue_len(js, ctrl_obj) > 0) { 354 + ant_value_t chunk = rs_ctrl_queue_shift(js, ctrl_obj); 355 + ctrl->queue_total_size -= 1; 356 + if (ctrl->queue_total_size < 0) ctrl->queue_total_size = 0; 357 + if (ctrl->close_requested && rs_ctrl_queue_len(js, ctrl_obj) == 0) { 358 + rs_default_controller_clear_algorithms(ctrl_obj); 359 + readable_stream_close(js, stream_obj); 360 + } else { 361 + rs_default_controller_call_pull_if_needed(js, ctrl_obj); 362 + } 363 + ant_value_t p = js_mkpromise(js); 364 + js_resolve_promise(js, p, js_iter_result(js, true, chunk)); 365 + return p; 366 + } 367 + 368 + ant_value_t p = js_mkpromise(js); 369 + rs_reader_reqs_push(js, reader_obj, p); 370 + rs_default_controller_call_pull_if_needed(js, ctrl_obj); 371 + return p; 372 + } 373 + 374 + static ant_value_t js_rs_controller_get_desired_size(ant_t *js, ant_value_t *args, int nargs) { 375 + rs_controller_t *ctrl = rs_get_controller(js->this_val); 376 + if (!ctrl) return js_mkerr_typed(js, JS_ERR_TYPE, "Invalid ReadableStreamDefaultController"); 377 + ant_value_t stream_obj = rs_ctrl_stream(js->this_val); 378 + rs_stream_t *stream = rs_get_stream(stream_obj); 379 + if (!stream || stream->state == RS_STATE_ERRORED) return js_mknull(); 380 + return js_mknum(rs_default_controller_get_desired_size(ctrl, stream)); 381 + } 382 + 383 + static ant_value_t js_rs_controller_close(ant_t *js, ant_value_t *args, int nargs) { 384 + rs_controller_t *ctrl = rs_get_controller(js->this_val); 385 + if (!ctrl) return js_mkerr_typed(js, JS_ERR_TYPE, "Invalid ReadableStreamDefaultController"); 386 + ant_value_t stream_obj = rs_ctrl_stream(js->this_val); 387 + rs_stream_t *stream = rs_get_stream(stream_obj); 388 + if (!rs_default_controller_can_close_or_enqueue(ctrl, stream)) 389 + return js_mkerr_typed(js, JS_ERR_TYPE, "The stream is not in a state that permits close"); 390 + ctrl->close_requested = true; 391 + if (rs_ctrl_queue_len(js, js->this_val) == 0) { 392 + rs_default_controller_clear_algorithms(js->this_val); 393 + readable_stream_close(js, stream_obj); 394 + } 395 + return js_mkundef(); 396 + } 397 + 398 + static ant_value_t js_rs_controller_enqueue(ant_t *js, ant_value_t *args, int nargs) { 399 + rs_controller_t *ctrl = rs_get_controller(js->this_val); 400 + if (!ctrl) return js_mkerr_typed(js, JS_ERR_TYPE, "Invalid ReadableStreamDefaultController"); 401 + ant_value_t stream_obj = rs_ctrl_stream(js->this_val); 402 + rs_stream_t *stream = rs_get_stream(stream_obj); 403 + if (!rs_default_controller_can_close_or_enqueue(ctrl, stream)) 404 + return js_mkerr_typed(js, JS_ERR_TYPE, "The stream is not in a state that permits enqueue"); 405 + 406 + ant_value_t chunk = (nargs > 0) ? args[0] : js_mkundef(); 407 + 408 + ant_value_t reader_obj = rs_stream_reader(stream_obj); 409 + if (is_object_type(reader_obj) && rs_reader_has_reqs(js, reader_obj)) { 410 + rs_fulfill_read_request(js, stream_obj, chunk, false); 411 + rs_default_controller_call_pull_if_needed(js, js->this_val); 412 + return js_mkundef(); 413 + } 414 + 415 + double chunk_size = 1; 416 + ant_value_t size_fn = rs_ctrl_size(js->this_val); 417 + if (is_callable(size_fn)) { 418 + ant_value_t size_args[1] = { chunk }; 419 + ant_value_t size_result = sv_vm_call(js->vm, js, size_fn, js_mkundef(), size_args, 1, NULL, false); 420 + if (is_err(size_result)) { 421 + readable_stream_error(js, stream_obj, size_result); 422 + return size_result; 423 + } 424 + if (vtype(size_result) == T_NUM) chunk_size = js_getnum(size_result); 425 + else chunk_size = js_to_number(js, size_result); 426 + } 427 + 428 + if (chunk_size < 0 || chunk_size != chunk_size || chunk_size == (double)INFINITY) { 429 + ant_value_t err = js_mkerr_typed(js, JS_ERR_RANGE, 430 + "The return value of a queuing strategy's size function must be a finite, non-NaN, non-negative number"); 431 + readable_stream_error(js, stream_obj, err); 432 + return err; 433 + } 434 + 435 + rs_ctrl_queue_push(js, js->this_val, chunk); 436 + ctrl->queue_total_size += chunk_size; 437 + rs_default_controller_call_pull_if_needed(js, js->this_val); 438 + return js_mkundef(); 439 + } 440 + 441 + static ant_value_t js_rs_controller_error(ant_t *js, ant_value_t *args, int nargs) { 442 + rs_controller_t *ctrl = rs_get_controller(js->this_val); 443 + if (!ctrl) return js_mkerr_typed(js, JS_ERR_TYPE, "Invalid ReadableStreamDefaultController"); 444 + ant_value_t stream_obj = rs_ctrl_stream(js->this_val); 445 + rs_stream_t *stream = rs_get_stream(stream_obj); 446 + if (!stream || stream->state != RS_STATE_READABLE) return js_mkundef(); 447 + ant_value_t e = (nargs > 0) ? args[0] : js_mkundef(); 448 + ctrl->queue_total_size = 0; 449 + rs_default_controller_clear_algorithms(js->this_val); 450 + readable_stream_error(js, stream_obj, e); 451 + return js_mkundef(); 452 + } 453 + 454 + static ant_value_t js_rs_reader_get_closed(ant_t *js, ant_value_t *args, int nargs) { 455 + return rs_reader_closed(js->this_val); 456 + } 457 + 458 + static ant_value_t js_rs_reader_read(ant_t *js, ant_value_t *args, int nargs) { 459 + ant_value_t stream_obj = rs_reader_stream(js->this_val); 460 + if (!is_object_type(stream_obj) || !rs_get_stream(stream_obj)) 461 + return js_mkerr_typed(js, JS_ERR_TYPE, "Cannot read from a released reader"); 462 + return rs_default_reader_read(js, js->this_val); 463 + } 464 + 465 + static ant_value_t js_rs_reader_release_lock(ant_t *js, ant_value_t *args, int nargs) { 466 + ant_value_t stream_obj = rs_reader_stream(js->this_val); 467 + if (!is_object_type(stream_obj)) return js_mkundef(); 468 + rs_stream_t *stream = rs_get_stream(stream_obj); 469 + if (!stream) return js_mkundef(); 470 + 471 + if (rs_reader_has_reqs(js, js->this_val)) { 472 + ant_value_t err = js_mkerr_typed(js, JS_ERR_TYPE, "Reader was released"); 473 + rs_default_reader_error_read_requests(js, js->this_val, err); 474 + } 475 + 476 + if (stream->state == RS_STATE_READABLE) { 477 + ant_value_t err = js_mkerr_typed(js, JS_ERR_TYPE, "Reader was released while stream is readable"); 478 + js_reject_promise(js, rs_reader_closed(js->this_val), err); 479 + } 480 + 481 + js_set_slot(stream_obj, SLOT_CTOR, js_mkundef()); 482 + js_set_slot(js->this_val, SLOT_ENTRIES, js_mkundef()); 483 + return js_mkundef(); 484 + } 485 + 486 + static ant_value_t js_rs_reader_cancel(ant_t *js, ant_value_t *args, int nargs) { 487 + ant_value_t stream_obj = rs_reader_stream(js->this_val); 488 + if (!is_object_type(stream_obj)) 489 + return js_mkerr_typed(js, JS_ERR_TYPE, "Cannot cancel a released reader"); 490 + ant_value_t reason = (nargs > 0) ? args[0] : js_mkundef(); 491 + return readable_stream_cancel(js, stream_obj, reason); 492 + } 493 + 494 + static ant_value_t js_rs_reader_ctor(ant_t *js, ant_value_t *args, int nargs) { 495 + if (vtype(js->new_target) == T_UNDEF) 496 + return js_mkerr_typed(js, JS_ERR_TYPE, "ReadableStreamDefaultReader constructor requires 'new'"); 497 + if (nargs < 1) return js_mkerr_typed(js, JS_ERR_TYPE, "ReadableStreamDefaultReader requires a stream argument"); 498 + 499 + ant_value_t stream_obj = args[0]; 500 + if (!is_object_type(stream_obj)) 501 + return js_mkerr_typed(js, JS_ERR_TYPE, "ReadableStreamDefaultReader argument must be a ReadableStream"); 502 + rs_stream_t *stream = rs_get_stream(stream_obj); 503 + if (!stream) return js_mkerr_typed(js, JS_ERR_TYPE, "ReadableStreamDefaultReader argument must be a ReadableStream"); 504 + if (is_object_type(rs_stream_reader(stream_obj))) 505 + return js_mkerr_typed(js, JS_ERR_TYPE, "ReadableStream is already locked to a reader"); 506 + 507 + ant_value_t closed = js_mkpromise(js); 508 + ant_value_t obj = js_mkobj(js); 509 + ant_value_t proto = js_instance_proto_from_new_target(js, g_reader_proto); 510 + if (is_object_type(proto)) js_set_proto_init(obj, proto); 511 + js_set_slot(obj, SLOT_ENTRIES, stream_obj); 512 + js_set_slot(obj, SLOT_RS_CLOSED, closed); 513 + js_set_slot(obj, SLOT_BUFFER, js_mkarr(js)); 514 + js_set_slot(stream_obj, SLOT_CTOR, obj); 515 + 516 + if (stream->state == RS_STATE_CLOSED) 517 + js_resolve_promise(js, closed, js_mkundef()); 518 + else if (stream->state == RS_STATE_ERRORED) 519 + js_reject_promise(js, closed, rs_stream_error(stream_obj)); 520 + 521 + return obj; 522 + } 523 + 524 + static ant_value_t js_rs_get_locked(ant_t *js, ant_value_t *args, int nargs) { 525 + rs_stream_t *stream = rs_get_stream(js->this_val); 526 + if (!stream) return js_mkerr_typed(js, JS_ERR_TYPE, "Invalid ReadableStream"); 527 + return js_bool(is_object_type(rs_stream_reader(js->this_val))); 528 + } 529 + 530 + static ant_value_t js_rs_cancel(ant_t *js, ant_value_t *args, int nargs) { 531 + rs_stream_t *stream = rs_get_stream(js->this_val); 532 + if (!stream) return js_mkerr_typed(js, JS_ERR_TYPE, "Invalid ReadableStream"); 533 + if (is_object_type(rs_stream_reader(js->this_val))) 534 + return js_mkerr_typed(js, JS_ERR_TYPE, "Cannot cancel a locked ReadableStream"); 535 + ant_value_t reason = (nargs > 0) ? args[0] : js_mkundef(); 536 + return readable_stream_cancel(js, js->this_val, reason); 537 + } 538 + 539 + static ant_value_t js_rs_get_reader(ant_t *js, ant_value_t *args, int nargs) { 540 + rs_stream_t *stream = rs_get_stream(js->this_val); 541 + if (!stream) return js_mkerr_typed(js, JS_ERR_TYPE, "Invalid ReadableStream"); 542 + 543 + if (nargs > 0 && is_object_type(args[0])) { 544 + ant_value_t mode = js_get(js, args[0], "mode"); 545 + if (!is_undefined(mode)) { 546 + if (vtype(mode) == T_STR) { 547 + size_t mode_len; 548 + const char *mode_str = js_getstr(js, mode, &mode_len); 549 + if (mode_str && mode_len == 4 && memcmp(mode_str, "byob", 4) == 0) 550 + return js_mkerr_typed(js, JS_ERR_TYPE, "ReadableStreamBYOBReader is not yet implemented"); 551 + } 552 + return js_mkerr_typed(js, JS_ERR_TYPE, "Invalid reader mode"); 553 + } 554 + } 555 + 556 + ant_value_t reader_args[1] = { js->this_val }; 557 + ant_value_t saved_new_target = js->new_target; 558 + js->new_target = g_reader_proto; 559 + ant_value_t reader = js_rs_reader_ctor(js, reader_args, 1); 560 + js->new_target = saved_new_target; 561 + return reader; 562 + } 563 + 564 + static ant_value_t js_rs_tee(ant_t *js, ant_value_t *args, int nargs) { 565 + return js_mkerr_typed(js, JS_ERR_TYPE, "ReadableStream.prototype.tee is not yet implemented"); 566 + } 567 + 568 + static ant_value_t js_rs_pipe_through(ant_t *js, ant_value_t *args, int nargs) { 569 + return js_mkerr_typed(js, JS_ERR_TYPE, "ReadableStream.prototype.pipeThrough is not yet implemented"); 570 + } 571 + 572 + static ant_value_t js_rs_pipe_to(ant_t *js, ant_value_t *args, int nargs) { 573 + return js_mkerr_typed(js, JS_ERR_TYPE, "ReadableStream.prototype.pipeTo is not yet implemented"); 574 + } 575 + 576 + static ant_value_t js_rs_values(ant_t *js, ant_value_t *args, int nargs) { 577 + return js_mkerr_typed(js, JS_ERR_TYPE, "ReadableStream async iteration is not yet implemented"); 578 + } 579 + 580 + static ant_value_t rs_start_resolve_handler(ant_t *js, ant_value_t *args, int nargs) { 581 + ant_value_t ctrl_obj = js_get_slot(js->current_func, SLOT_DATA); 582 + rs_controller_t *ctrl = rs_get_controller(ctrl_obj); 583 + if (!ctrl) return js_mkundef(); 584 + ctrl->started = true; 585 + ctrl->pulling = false; 586 + ctrl->pull_again = false; 587 + rs_default_controller_call_pull_if_needed(js, ctrl_obj); 588 + return js_mkundef(); 589 + } 590 + 591 + static ant_value_t rs_start_reject_handler(ant_t *js, ant_value_t *args, int nargs) { 592 + ant_value_t ctrl_obj = js_get_slot(js->current_func, SLOT_DATA); 593 + rs_controller_t *ctrl = rs_get_controller(ctrl_obj); 594 + if (!ctrl) return js_mkundef(); 595 + ant_value_t stream_obj = rs_ctrl_stream(ctrl_obj); 596 + rs_stream_t *stream = rs_get_stream(stream_obj); 597 + if (stream && stream->state == RS_STATE_READABLE) 598 + readable_stream_error(js, stream_obj, nargs > 0 ? args[0] : js_mkundef()); 599 + return js_mkundef(); 600 + } 601 + 602 + static ant_value_t setup_default_controller( 603 + ant_t *js, ant_value_t stream_obj, 604 + ant_value_t pull_fn, ant_value_t cancel_fn, ant_value_t size_fn, 605 + double hwm 606 + ) { 607 + rs_controller_t *ctrl = calloc(1, sizeof(rs_controller_t)); 608 + if (!ctrl) return js_mkerr(js, "out of memory"); 609 + ctrl->strategy_hwm = hwm; 610 + 611 + ant_value_t ctrl_obj = js_mkobj(js); 612 + js_set_proto_init(ctrl_obj, g_controller_proto); 613 + js_set_slot(ctrl_obj, SLOT_DATA, ANT_PTR(ctrl)); 614 + js_set_slot(ctrl_obj, SLOT_ENTRIES, stream_obj); 615 + js_set_slot(ctrl_obj, SLOT_RS_PULL, pull_fn); 616 + js_set_slot(ctrl_obj, SLOT_RS_CANCEL, cancel_fn); 617 + js_set_slot(ctrl_obj, SLOT_RS_SIZE, size_fn); 618 + js_set_slot(ctrl_obj, SLOT_BUFFER, js_mkarr(js)); 619 + js_set_finalizer(ctrl_obj, rs_controller_finalize); 620 + 621 + js_set_slot(stream_obj, SLOT_ENTRIES, ctrl_obj); 622 + return ctrl_obj; 623 + } 624 + 625 + static ant_value_t js_rs_ctor(ant_t *js, ant_value_t *args, int nargs) { 626 + if (vtype(js->new_target) == T_UNDEF) 627 + return js_mkerr_typed(js, JS_ERR_TYPE, "ReadableStream constructor requires 'new'"); 628 + 629 + ant_value_t underlying_source = js_mkundef(); 630 + if (nargs > 0 && !is_undefined(args[0])) { 631 + if (is_null(args[0])) 632 + return js_mkerr_typed(js, JS_ERR_TYPE, "The underlying source cannot be null"); 633 + underlying_source = args[0]; 634 + } 635 + 636 + if (is_object_type(underlying_source)) { 637 + ant_value_t type_val = js_get(js, underlying_source, "type"); 638 + if (!is_undefined(type_val)) { 639 + ant_value_t coerced = type_val; 640 + if (vtype(type_val) != T_STR) { 641 + coerced = js_tostring_val(js, type_val); 642 + if (is_err(coerced)) return coerced; 643 + } 644 + size_t tlen; 645 + const char *tstr = js_getstr(js, coerced, &tlen); 646 + if (tstr && tlen == 5 && memcmp(tstr, "bytes", 5) == 0) 647 + return js_mkerr_typed(js, JS_ERR_RANGE, "ReadableStream byte sources are not yet implemented"); 648 + return js_mkerr_typed(js, JS_ERR_TYPE, "Invalid type is specified"); 649 + }} 650 + 651 + ant_value_t strategy = js_mkundef(); 652 + if (nargs > 1 && !is_undefined(args[1]) && !is_null(args[1])) 653 + strategy = args[1]; 654 + 655 + double hwm = 1; 656 + if (is_object_type(strategy)) { 657 + ant_value_t hwm_val = js_get(js, strategy, "highWaterMark"); 658 + if (!is_undefined(hwm_val)) { 659 + hwm = js_to_number(js, hwm_val); 660 + if (hwm != hwm || hwm < 0) 661 + return js_mkerr_typed(js, JS_ERR_RANGE, "Invalid highWaterMark"); 662 + } 663 + } 664 + 665 + ant_value_t size_fn = js_mkundef(); 666 + if (is_object_type(strategy)) { 667 + ant_value_t s = js_get(js, strategy, "size"); 668 + if (!is_undefined(s)) { 669 + if (!is_callable(s)) 670 + return js_mkerr_typed(js, JS_ERR_TYPE, "size must be a function"); 671 + size_fn = s; 672 + } 673 + } 674 + 675 + rs_stream_t *st = calloc(1, sizeof(rs_stream_t)); 676 + if (!st) return js_mkerr(js, "out of memory"); 677 + st->state = RS_STATE_READABLE; 678 + 679 + ant_value_t obj = js_mkobj(js); 680 + ant_value_t proto = js_instance_proto_from_new_target(js, g_rs_proto); 681 + if (is_object_type(proto)) js_set_proto_init(obj, proto); 682 + js_set_slot(obj, SLOT_DATA, ANT_PTR(st)); 683 + js_set_finalizer(obj, rs_stream_finalize); 684 + 685 + ant_value_t pull_fn = js_mkundef(); 686 + ant_value_t cancel_fn = js_mkundef(); 687 + ant_value_t start_fn = js_mkundef(); 688 + 689 + if (is_object_type(underlying_source)) { 690 + ant_value_t pv = js_get(js, underlying_source, "pull"); 691 + if (is_err(pv)) return pv; 692 + if (!is_undefined(pv)) { 693 + if (!is_callable(pv)) return js_mkerr_typed(js, JS_ERR_TYPE, "pull must be a function"); 694 + pull_fn = pv; 695 + } 696 + ant_value_t cv = js_get(js, underlying_source, "cancel"); 697 + if (is_err(cv)) return cv; 698 + if (!is_undefined(cv)) { 699 + if (!is_callable(cv)) return js_mkerr_typed(js, JS_ERR_TYPE, "cancel must be a function"); 700 + cancel_fn = cv; 701 + } 702 + ant_value_t sv = js_get(js, underlying_source, "start"); 703 + if (is_err(sv)) return sv; 704 + if (!is_undefined(sv)) { 705 + if (!is_callable(sv)) return js_mkerr_typed(js, JS_ERR_TYPE, "start must be a function"); 706 + start_fn = sv; 707 + } 708 + } 709 + 710 + ant_value_t ctrl_obj = setup_default_controller(js, obj, pull_fn, cancel_fn, size_fn, hwm); 711 + if (is_err(ctrl_obj)) return ctrl_obj; 712 + 713 + if (is_callable(start_fn)) { 714 + ant_value_t start_args[1] = { ctrl_obj }; 715 + ant_value_t start_result = sv_vm_call(js->vm, js, start_fn, underlying_source, start_args, 1, NULL, false); 716 + if (is_err(start_result)) return start_result; 717 + 718 + if (vtype(start_result) == T_PROMISE) { 719 + ant_value_t resolve_fn = js_heavy_mkfun(js, rs_start_resolve_handler, ctrl_obj); 720 + ant_value_t reject_fn = js_heavy_mkfun(js, rs_start_reject_handler, ctrl_obj); 721 + ant_value_t then_fn = js_get(js, start_result, "then"); 722 + if (is_callable(then_fn)) { 723 + ant_value_t then_args[2] = { resolve_fn, reject_fn }; 724 + sv_vm_call(js->vm, js, then_fn, start_result, then_args, 2, NULL, false); 725 + } 726 + } 727 + 728 + if (vtype(start_result) != T_PROMISE) { 729 + ant_value_t resolved = js_mkpromise(js); 730 + js_resolve_promise(js, resolved, js_mkundef()); 731 + ant_value_t res_fn = js_heavy_mkfun(js, rs_start_resolve_handler, ctrl_obj); 732 + ant_value_t rej_fn = js_heavy_mkfun(js, rs_start_reject_handler, ctrl_obj); 733 + ant_value_t then_fn = js_get(js, resolved, "then"); 734 + if (is_callable(then_fn)) { 735 + ant_value_t then_args[2] = { res_fn, rej_fn }; 736 + sv_vm_call(js->vm, js, then_fn, resolved, then_args, 2, NULL, false); 737 + } 738 + } 739 + } else { 740 + ant_value_t resolved = js_mkpromise(js); 741 + js_resolve_promise(js, resolved, js_mkundef()); 742 + ant_value_t res_fn = js_heavy_mkfun(js, rs_start_resolve_handler, ctrl_obj); 743 + ant_value_t rej_fn = js_heavy_mkfun(js, rs_start_reject_handler, ctrl_obj); 744 + ant_value_t then_fn = js_get(js, resolved, "then"); 745 + if (is_callable(then_fn)) { 746 + ant_value_t then_args[2] = { res_fn, rej_fn }; 747 + sv_vm_call(js->vm, js, then_fn, resolved, then_args, 2, NULL, false); 748 + } 749 + } 750 + 751 + return obj; 752 + } 753 + 754 + static ant_value_t js_rs_controller_ctor(ant_t *js, ant_value_t *args, int nargs) { 755 + return js_mkerr_typed(js, JS_ERR_TYPE, "ReadableStreamDefaultController cannot be constructed directly"); 756 + } 757 + 758 + void gc_mark_readable_streams(ant_t *js, void (*mark)(ant_t *, ant_value_t)) { 759 + mark(js, g_rs_proto); 760 + mark(js, g_reader_proto); 761 + mark(js, g_controller_proto); 762 + } 763 + 764 + void init_readable_stream_module(void) { 765 + ant_t *js = rt->js; 766 + ant_value_t g = js_glob(js); 767 + 768 + g_controller_proto = js_mkobj(js); 769 + js_set_getter_desc(js, g_controller_proto, "desiredSize", 11, 770 + js_mkfun(js_rs_controller_get_desired_size), JS_DESC_C); 771 + js_set(js, g_controller_proto, "close", js_mkfun(js_rs_controller_close)); 772 + js_set_descriptor(js, g_controller_proto, "close", 5, JS_DESC_W | JS_DESC_C); 773 + js_set(js, g_controller_proto, "enqueue", js_mkfun(js_rs_controller_enqueue)); 774 + js_set_descriptor(js, g_controller_proto, "enqueue", 7, JS_DESC_W | JS_DESC_C); 775 + js_set(js, g_controller_proto, "error", js_mkfun(js_rs_controller_error)); 776 + js_set_descriptor(js, g_controller_proto, "error", 5, JS_DESC_W | JS_DESC_C); 777 + js_set_sym(js, g_controller_proto, get_toStringTag_sym(), 778 + js_mkstr(js, "ReadableStreamDefaultController", 31)); 779 + 780 + ant_value_t ctrl_ctor = js_make_ctor(js, js_rs_controller_ctor, g_controller_proto, 781 + "ReadableStreamDefaultController", 31); 782 + js_set(js, g, "ReadableStreamDefaultController", ctrl_ctor); 783 + js_set_descriptor(js, g, "ReadableStreamDefaultController", 31, JS_DESC_W | JS_DESC_C); 784 + 785 + g_reader_proto = js_mkobj(js); 786 + js_set_getter_desc(js, g_reader_proto, "closed", 6, 787 + js_mkfun(js_rs_reader_get_closed), JS_DESC_C); 788 + js_set(js, g_reader_proto, "read", js_mkfun(js_rs_reader_read)); 789 + js_set_descriptor(js, g_reader_proto, "read", 4, JS_DESC_W | JS_DESC_C); 790 + js_set(js, g_reader_proto, "releaseLock", js_mkfun(js_rs_reader_release_lock)); 791 + js_set_descriptor(js, g_reader_proto, "releaseLock", 11, JS_DESC_W | JS_DESC_C); 792 + js_set(js, g_reader_proto, "cancel", js_mkfun(js_rs_reader_cancel)); 793 + js_set_descriptor(js, g_reader_proto, "cancel", 6, JS_DESC_W | JS_DESC_C); 794 + js_set_sym(js, g_reader_proto, get_toStringTag_sym(), 795 + js_mkstr(js, "ReadableStreamDefaultReader", 27)); 796 + 797 + ant_value_t reader_ctor = js_make_ctor(js, js_rs_reader_ctor, g_reader_proto, 798 + "ReadableStreamDefaultReader", 27); 799 + js_set(js, g, "ReadableStreamDefaultReader", reader_ctor); 800 + js_set_descriptor(js, g, "ReadableStreamDefaultReader", 27, JS_DESC_W | JS_DESC_C); 801 + 802 + g_rs_proto = js_mkobj(js); 803 + js_set_getter_desc(js, g_rs_proto, "locked", 6, 804 + js_mkfun(js_rs_get_locked), JS_DESC_C); 805 + js_set(js, g_rs_proto, "cancel", js_mkfun(js_rs_cancel)); 806 + js_set_descriptor(js, g_rs_proto, "cancel", 6, JS_DESC_W | JS_DESC_C); 807 + js_set(js, g_rs_proto, "getReader", js_mkfun(js_rs_get_reader)); 808 + js_set_descriptor(js, g_rs_proto, "getReader", 9, JS_DESC_W | JS_DESC_C); 809 + js_set(js, g_rs_proto, "tee", js_mkfun(js_rs_tee)); 810 + js_set_descriptor(js, g_rs_proto, "tee", 3, JS_DESC_W | JS_DESC_C); 811 + js_set(js, g_rs_proto, "pipeThrough", js_mkfun(js_rs_pipe_through)); 812 + js_set_descriptor(js, g_rs_proto, "pipeThrough", 11, JS_DESC_W | JS_DESC_C); 813 + js_set(js, g_rs_proto, "pipeTo", js_mkfun(js_rs_pipe_to)); 814 + js_set_descriptor(js, g_rs_proto, "pipeTo", 6, JS_DESC_W | JS_DESC_C); 815 + js_set(js, g_rs_proto, "values", js_mkfun(js_rs_values)); 816 + js_set_descriptor(js, g_rs_proto, "values", 6, JS_DESC_W | JS_DESC_C); 817 + js_set_sym(js, g_rs_proto, get_toStringTag_sym(), 818 + js_mkstr(js, "ReadableStream", 14)); 819 + 820 + ant_value_t rs_ctor = js_make_ctor(js, js_rs_ctor, g_rs_proto, "ReadableStream", 14); 821 + js_set(js, g, "ReadableStream", rs_ctor); 822 + js_set_descriptor(js, g, "ReadableStream", 14, JS_DESC_W | JS_DESC_C); 823 + }