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.

at type-hints-typescript 1095 lines 42 kB view raw
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 "gc/roots.h" 11#include "silver/engine.h" 12#include "modules/assert.h" 13#include "modules/symbol.h" 14#include "streams/transform.h" 15#include "streams/readable.h" 16#include "streams/writable.h" 17 18ant_value_t g_ts_proto; 19ant_value_t g_ts_ctrl_proto; 20 21static inline bool ts_has_stream_shape(ant_value_t obj) { 22 return vtype(js_get_slot(obj, SLOT_DATA)) == T_NUM 23 && rs_is_stream(js_get_slot(obj, SLOT_ENTRIES)) 24 && ws_is_stream(js_get_slot(obj, SLOT_CTOR)); 25} 26 27static inline bool ts_has_controller_shape(ant_value_t obj) { 28 ant_value_t ts_obj = js_get_slot(obj, SLOT_DATA); 29 return is_object_type(ts_obj) 30 && js_check_brand(ts_obj, BRAND_TRANSFORM_STREAM) 31 && vtype(js_get_slot(ts_obj, SLOT_DATA)) == T_NUM 32 && js_get_slot(ts_obj, SLOT_DEFAULT) == obj; 33} 34 35bool ts_is_controller(ant_value_t obj) { 36 return js_check_brand(obj, BRAND_TRANSFORM_STREAM_CONTROLLER) 37 && ts_has_controller_shape(obj); 38} 39 40bool ts_is_stream(ant_value_t obj) { 41 ant_value_t ctrl_obj = js_get_slot(obj, SLOT_DEFAULT); 42 return js_check_brand(obj, BRAND_TRANSFORM_STREAM) 43 && ts_has_stream_shape(obj) 44 && js_check_brand(ctrl_obj, BRAND_TRANSFORM_STREAM_CONTROLLER) 45 && ts_has_controller_shape(ctrl_obj); 46} 47 48ant_value_t ts_stream_readable(ant_value_t ts_obj) { 49 return js_get_slot(ts_obj, SLOT_ENTRIES); 50} 51 52ant_value_t ts_stream_writable(ant_value_t ts_obj) { 53 return js_get_slot(ts_obj, SLOT_CTOR); 54} 55 56static void ts_ws_finalize(ant_t *js, ant_object_t *obj) { 57 if (!obj->extra_slots) return; 58 ant_extra_slot_t *entries = (ant_extra_slot_t *)obj->extra_slots; 59 for (uint8_t i = 0; i < obj->extra_count; i++) { 60 if (entries[i].slot == SLOT_DATA && vtype(entries[i].value) == T_NUM) { 61 free((ws_stream_t *)(uintptr_t)(size_t)js_getnum(entries[i].value)); 62 return; 63 }} 64} 65 66static void ts_ws_ctrl_finalize(ant_t *js, ant_object_t *obj) { 67 if (!obj->extra_slots) return; 68 ant_extra_slot_t *entries = (ant_extra_slot_t *)obj->extra_slots; 69 for (uint8_t i = 0; i < obj->extra_count; i++) { 70 if (entries[i].slot == SLOT_DATA && vtype(entries[i].value) == T_NUM) { 71 ws_controller_t *ctrl = (ws_controller_t *)(uintptr_t)(size_t)js_getnum(entries[i].value); 72 free(ctrl->queue_sizes); 73 free(ctrl); 74 return; 75 }} 76} 77 78static void ts_rs_finalize(ant_t *js, ant_object_t *obj) { 79 if (!obj->extra_slots) return; 80 ant_extra_slot_t *entries = (ant_extra_slot_t *)obj->extra_slots; 81 for (uint8_t i = 0; i < obj->extra_count; i++) { 82 if (entries[i].slot == SLOT_DATA && vtype(entries[i].value) == T_NUM) { 83 free((rs_stream_t *)(uintptr_t)(size_t)js_getnum(entries[i].value)); 84 return; 85 }} 86} 87 88static void ts_rs_ctrl_finalize(ant_t *js, ant_object_t *obj) { 89 if (!obj->extra_slots) return; 90 ant_extra_slot_t *entries = (ant_extra_slot_t *)obj->extra_slots; 91 for (uint8_t i = 0; i < obj->extra_count; i++) { 92 if (entries[i].slot == SLOT_DATA && vtype(entries[i].value) == T_NUM) { 93 rs_controller_t *ctrl = (rs_controller_t *)(uintptr_t)(size_t)js_getnum(entries[i].value); 94 free(ctrl->queue_sizes); 95 free(ctrl); 96 return; 97 }} 98} 99 100static inline bool ts_get_backpressure(ant_value_t ts_obj) { 101 return js_getnum(js_get_slot(ts_obj, SLOT_DATA)) != 0; 102} 103 104static inline void ts_set_bp_flag(ant_value_t ts_obj, bool bp) { 105 js_set_slot(ts_obj, SLOT_DATA, js_mknum(bp ? 1 : 0)); 106} 107 108static inline ant_value_t ts_readable(ant_value_t ts_obj) { 109 return ts_stream_readable(ts_obj); 110} 111 112static inline ant_value_t ts_writable(ant_value_t ts_obj) { 113 return ts_stream_writable(ts_obj); 114} 115 116static inline ant_value_t ts_bp_promise(ant_value_t ts_obj) { 117 return js_get_slot(ts_obj, SLOT_AUX); 118} 119 120ant_value_t ts_stream_controller(ant_value_t ts_obj) { 121 return js_get_slot(ts_obj, SLOT_DEFAULT); 122} 123 124static inline ant_value_t ts_controller(ant_value_t ts_obj) { 125 return ts_stream_controller(ts_obj); 126} 127 128static inline ant_value_t ts_ctrl_transform_fn(ant_value_t ctrl_obj) { 129 return js_get_slot(ctrl_obj, SLOT_ENTRIES); 130} 131 132static inline ant_value_t ts_ctrl_flush_fn(ant_value_t ctrl_obj) { 133 return js_get_slot(ctrl_obj, SLOT_CTOR); 134} 135 136static inline ant_value_t ts_ctrl_cancel_fn(ant_value_t ctrl_obj) { 137 return js_get_slot(ctrl_obj, SLOT_AUX); 138} 139 140static inline ant_value_t ts_ctrl_transformer(ant_value_t ctrl_obj) { 141 return js_get_slot(ctrl_obj, SLOT_SETTLED); 142} 143 144static inline ant_value_t ts_ctrl_stream(ant_value_t ctrl_obj) { 145 return js_get_slot(ctrl_obj, SLOT_DATA); 146} 147 148static inline ant_value_t ts_ctrl_finish_promise(ant_value_t ctrl_obj) { 149 return js_get_slot(ctrl_obj, SLOT_RS_PULL); 150} 151 152static inline ant_value_t ts_writable_stored_error(ant_value_t ts_obj) { 153 return js_get_slot(ts_writable(ts_obj), SLOT_AUX); 154} 155 156static inline ant_value_t ts_cancel_promise(ant_value_t ts_obj) { 157 return js_get_slot(ts_obj, SLOT_RS_CANCEL); 158} 159 160static inline bool ts_cancel_started_by_abort(ant_value_t ts_obj) { 161 return js_get_slot(ts_obj, SLOT_WS_ABORT) == js_true; 162} 163 164static inline bool ts_is_flushing(ant_value_t ts_obj) { 165 return js_get_slot(ts_obj, SLOT_WS_CLOSE) == js_true; 166} 167 168static inline ant_value_t ts_cancel_settle_error(ant_value_t ts_obj) { 169 return js_get_slot(ts_obj, SLOT_RS_SIZE); 170} 171 172static inline bool ts_cancel_joined_abort(ant_value_t ts_obj) { 173 return js_get_slot(ts_obj, SLOT_WS_WRITE) == js_true; 174} 175 176static inline bool ts_cancel_has_user_handler(ant_value_t ts_obj) { 177 return js_get_slot(ts_obj, SLOT_WS_SIGNAL) == js_true; 178} 179 180static inline void ts_set_flushing(ant_value_t ts_obj, bool flushing) { 181 js_set_slot(ts_obj, SLOT_WS_CLOSE, flushing ? js_true : js_false); 182} 183 184static inline void ts_set_cancel_state(ant_t *js, ant_value_t ts_obj, ant_value_t promise, bool started_by_abort, bool has_user_handler) { 185 js_set_slot_wb(js, ts_obj, SLOT_RS_CANCEL, promise); 186 js_set_slot(ts_obj, SLOT_WS_ABORT, started_by_abort ? js_true : js_false); 187 js_set_slot(ts_obj, SLOT_RS_SIZE, js_mkundef()); 188 js_set_slot(ts_obj, SLOT_WS_WRITE, js_false); 189 js_set_slot(ts_obj, SLOT_WS_SIGNAL, has_user_handler ? js_true : js_false); 190} 191 192static inline void ts_clear_cancel_state(ant_value_t ts_obj, ant_value_t promise) { 193if (ts_cancel_promise(ts_obj) == promise) { 194 js_set_slot(ts_obj, SLOT_RS_CANCEL, js_mkundef()); 195 js_set_slot(ts_obj, SLOT_WS_ABORT, js_false); 196 js_set_slot(ts_obj, SLOT_WS_SIGNAL, js_false); 197}} 198 199static void ts_ctrl_clear_algorithms(ant_value_t ctrl_obj) { 200 js_set_slot(ctrl_obj, SLOT_ENTRIES, js_mkundef()); 201 js_set_slot(ctrl_obj, SLOT_CTOR, js_mkundef()); 202 js_set_slot(ctrl_obj, SLOT_AUX, js_mkundef()); 203} 204 205static ant_value_t ts_take_thrown_or(ant_t *js, ant_value_t fallback) { 206 ant_value_t thrown = js->thrown_exists ? js->thrown_value : js_mkundef(); 207 ant_value_t err = is_object_type(thrown) ? thrown : fallback; 208 js->thrown_exists = false; 209 js->thrown_value = js_mkundef(); 210 js->thrown_stack = js_mkundef(); 211 return err; 212} 213 214static void ts_chain_promise(ant_t *js, ant_value_t val, ant_value_t res_fn, ant_value_t rej_fn) { 215 GC_ROOT_SAVE(root_mark, js); 216 GC_ROOT_PIN(js, val); 217 GC_ROOT_PIN(js, res_fn); 218 GC_ROOT_PIN(js, rej_fn); 219 220 ant_value_t promise = val; 221 GC_ROOT_PIN(js, promise); 222 if (vtype(promise) != T_PROMISE) { 223 promise = js_mkpromise(js); 224 GC_ROOT_PIN(js, promise); 225 js_resolve_promise(js, promise, val); 226 } 227 228 ant_value_t then_result = js_promise_then(js, promise, res_fn, rej_fn); 229 GC_ROOT_PIN(js, then_result); 230 promise_mark_handled(then_result); 231 GC_ROOT_RESTORE(js, root_mark); 232} 233 234static void ts_error(ant_t *js, ant_value_t ts_obj, ant_value_t e) { 235 ant_value_t readable = ts_readable(ts_obj); 236 ant_value_t rs_ctrl = rs_stream_controller(js, readable); 237 rs_controller_t *rc = rs_get_controller(rs_ctrl); 238 if (rc) { 239 rc->queue_total_size = 0; 240 rc->queue_sizes_len = 0; 241 rs_default_controller_clear_algorithms(rs_ctrl); 242 } 243 readable_stream_error(js, readable, e); 244 245 if (ts_get_backpressure(ts_obj)) { 246 ant_value_t bp = ts_bp_promise(ts_obj); 247 if (vtype(bp) == T_PROMISE) js_resolve_promise(js, bp, js_mkundef()); 248 ts_set_bp_flag(ts_obj, false); 249 } 250} 251 252static void ts_error_writable_and_unblock_write(ant_t *js, ant_value_t ts_obj, ant_value_t e) { 253 ant_value_t ctrl_obj = ts_controller(ts_obj); 254 ts_ctrl_clear_algorithms(ctrl_obj); 255 256 ant_value_t writable = ts_writable(ts_obj); 257 ws_stream_t *ws = ws_get_stream(writable); 258 if (ws && ws->state == WS_STATE_WRITABLE) 259 ws_default_controller_error(js, ws_stream_controller(writable), e); 260 261 if (ts_get_backpressure(ts_obj)) { 262 ant_value_t bp = ts_bp_promise(ts_obj); 263 if (vtype(bp) == T_PROMISE) js_resolve_promise(js, bp, js_mkundef()); 264 ts_set_bp_flag(ts_obj, false); 265 } 266} 267 268static void ts_set_backpressure(ant_t *js, ant_value_t ts_obj, bool backpressure) { 269 if (ts_get_backpressure(ts_obj)) { 270 ant_value_t bp = ts_bp_promise(ts_obj); 271 if (vtype(bp) == T_PROMISE) js_resolve_promise(js, bp, js_mkundef()); 272 } 273 ant_value_t new_bp = js_mkpromise(js); 274 js_set_slot_wb(js, ts_obj, SLOT_AUX, new_bp); 275 ts_set_bp_flag(ts_obj, backpressure); 276} 277 278ant_value_t ts_ctrl_enqueue(ant_t *js, ant_value_t ctrl_obj, ant_value_t chunk) { 279 ant_value_t ts_obj = ts_ctrl_stream(ctrl_obj); 280 ant_value_t readable = ts_readable(ts_obj); 281 ant_value_t rs_ctrl = rs_stream_controller(js, readable); 282 rs_stream_t *rs = rs_get_stream(readable); 283 284 if (!rs || rs->state != RS_STATE_READABLE) 285 return js_mkerr_typed(js, JS_ERR_TYPE, "Readable side is not in a readable state"); 286 287 ant_value_t enqueue_result = rs_controller_enqueue(js, rs_ctrl, chunk); 288 if (is_err(enqueue_result)) { 289 ant_value_t err = ts_take_thrown_or(js, enqueue_result); 290 ts_error_writable_and_unblock_write(js, ts_obj, err); 291 return js_throw(js, err); 292 } 293 294 rs_controller_t *rc = rs_get_controller(rs_ctrl); 295 bool bp = rc && ((rc->strategy_hwm - rc->queue_total_size) <= 0); 296 if (bp != ts_get_backpressure(ts_obj)) ts_set_backpressure(js, ts_obj, bp); 297 298 return js_mkundef(); 299} 300 301void ts_ctrl_error(ant_t *js, ant_value_t ctrl_obj, ant_value_t e) { 302 ant_value_t ts_obj = ts_ctrl_stream(ctrl_obj); 303 if (vtype(ts_cancel_promise(ts_obj)) == T_PROMISE && ts_cancel_has_user_handler(ts_obj)) 304 js_set_slot_wb(js, ts_obj, SLOT_RS_SIZE, e); 305 ts_error(js, ts_obj, e); 306 ts_error_writable_and_unblock_write(js, ts_obj, e); 307} 308 309void ts_ctrl_terminate(ant_t *js, ant_value_t ctrl_obj) { 310 ant_value_t ts_obj = ts_ctrl_stream(ctrl_obj); 311 ant_value_t readable = ts_readable(ts_obj); 312 ant_value_t rs_ctrl = rs_stream_controller(js, readable); 313 314 rs_controller_close(js, rs_ctrl); 315 ant_value_t writable = ts_writable(ts_obj); 316 ws_stream_t *ws = ws_get_stream(writable); 317 318 if (ws && ws->state == WS_STATE_WRITABLE) { 319 ant_value_t err = js_make_error_silent(js, JS_ERR_TYPE, "TransformStream readable side terminated"); 320 ts_error_writable_and_unblock_write(js, ts_obj, err); 321 } 322} 323 324static ant_value_t ts_transform_resolve(ant_t *js, ant_value_t *args, int nargs) { 325 ant_value_t p = js_get_slot(js->current_func, SLOT_DATA); 326 js_resolve_promise(js, p, js_mkundef()); 327 return js_mkundef(); 328} 329 330static ant_value_t ts_transform_reject(ant_t *js, ant_value_t *args, int nargs) { 331 ant_value_t wrapper = js_get_slot(js->current_func, SLOT_DATA); 332 ant_value_t p = js_get_slot(wrapper, SLOT_DATA); 333 ant_value_t ts_obj = js_get_slot(wrapper, SLOT_ENTRIES); 334 ant_value_t e = (nargs > 0) ? args[0] : js_mkundef(); 335 ts_error(js, ts_obj, e); 336 js_reject_promise(js, p, e); 337 return js_mkundef(); 338} 339 340static ant_value_t ts_ctrl_perform_transform(ant_t *js, ant_value_t ctrl_obj, ant_value_t chunk) { 341 ant_value_t transform_fn = ts_ctrl_transform_fn(ctrl_obj); 342 ant_value_t ts_obj = ts_ctrl_stream(ctrl_obj); 343 ant_value_t p = js_mkpromise(js); 344 promise_mark_handled(p); 345 346 if (is_callable(transform_fn)) { 347 ant_value_t call_args[2] = { chunk, ctrl_obj }; 348 ant_value_t result = sv_vm_call(js->vm, js, transform_fn, ts_ctrl_transformer(ctrl_obj), call_args, 2, NULL, false); 349 350 if (is_err(result)) { 351 ant_value_t err = ts_take_thrown_or(js, result); 352 ts_error(js, ts_obj, err); 353 js_reject_promise(js, p, err); 354 return p; 355 } 356 357 ant_value_t res_fn = js_heavy_mkfun(js, ts_transform_resolve, p); 358 ant_value_t wrapper = js_mkobj(js); 359 js_set_slot(wrapper, SLOT_DATA, p); 360 js_set_slot(wrapper, SLOT_ENTRIES, ts_obj); 361 362 ant_value_t rej_fn = js_heavy_mkfun(js, ts_transform_reject, wrapper); 363 ts_chain_promise(js, result, res_fn, rej_fn); 364 } else { 365 ant_value_t enqueue_result = ts_ctrl_enqueue(js, ctrl_obj, chunk); 366 if (is_err(enqueue_result)) { 367 ant_value_t err = ts_take_thrown_or(js, enqueue_result); 368 js_reject_promise(js, p, err); 369 return p; 370 } 371 js_resolve_promise(js, p, js_mkundef()); 372 } 373 374 return p; 375} 376 377static ant_value_t ts_cancel_base_resolve(ant_t *js, ant_value_t *args, int nargs) { 378 ant_value_t wrapper = js_get_slot(js->current_func, SLOT_DATA); 379 ant_value_t p = js_get_slot(wrapper, SLOT_DATA); 380 ant_value_t ts_obj = js_get_slot(wrapper, SLOT_ENTRIES); 381 ts_clear_cancel_state(ts_obj, p); 382 js_resolve_promise(js, p, js_mkundef()); 383 return js_mkundef(); 384} 385 386static ant_value_t ts_cancel_base_reject(ant_t *js, ant_value_t *args, int nargs) { 387 ant_value_t wrapper = js_get_slot(js->current_func, SLOT_DATA); 388 ant_value_t p = js_get_slot(wrapper, SLOT_DATA); 389 ant_value_t ts_obj = js_get_slot(wrapper, SLOT_ENTRIES); 390 ant_value_t err = (nargs > 0) ? args[0] : js_mkundef(); 391 ts_clear_cancel_state(ts_obj, p); 392 js_reject_promise(js, p, err); 393 return js_mkundef(); 394} 395 396static ant_value_t ts_run_cancel_algorithm(ant_t *js, ant_value_t ts_obj, ant_value_t cancel_fn, ant_value_t reason, bool started_by_abort) { 397 ant_value_t existing = ts_cancel_promise(ts_obj); 398 if (vtype(existing) == T_PROMISE) return existing; 399 400 ant_value_t p = js_mkpromise(js); 401 promise_mark_handled(p); 402 ts_set_cancel_state(js, ts_obj, p, started_by_abort, is_callable(cancel_fn)); 403 ts_ctrl_clear_algorithms(ts_controller(ts_obj)); 404 405 ant_value_t result = js_mkundef(); 406 if (is_callable(cancel_fn)) { 407 ant_value_t cancel_args[1] = { reason }; 408 result = sv_vm_call(js->vm, js, cancel_fn, ts_ctrl_transformer(ts_controller(ts_obj)), cancel_args, 1, NULL, false); 409 } 410 411 if (is_err(result)) { 412 ant_value_t err = ts_take_thrown_or(js, result); 413 ts_clear_cancel_state(ts_obj, p); 414 js_reject_promise(js, p, err); 415 return p; 416 } 417 418 ant_value_t wrapper = js_mkobj(js); 419 js_set_slot(wrapper, SLOT_DATA, p); 420 js_set_slot(wrapper, SLOT_ENTRIES, ts_obj); 421 422 ant_value_t res_fn = js_heavy_mkfun(js, ts_cancel_base_resolve, wrapper); 423 ant_value_t rej_fn = js_heavy_mkfun(js, ts_cancel_base_reject, wrapper); 424 ts_chain_promise(js, result, res_fn, rej_fn); 425 426 return p; 427} 428 429static ant_value_t ts_source_cancel_resolve(ant_t *js, ant_value_t *args, int nargs) { 430 ant_value_t wrapper = js_get_slot(js->current_func, SLOT_DATA); 431 ant_value_t p = js_get_slot(wrapper, SLOT_DATA); 432 ant_value_t ts_obj = js_get_slot(wrapper, SLOT_ENTRIES); 433 ant_value_t reason = js_get_slot(wrapper, SLOT_AUX); 434 435 ant_value_t readable = ts_readable(ts_obj); 436 rs_stream_t *rs = rs_get_stream(readable); 437 ant_value_t settle_error = ts_cancel_settle_error(ts_obj); 438 if (is_object_type(settle_error)) { 439 js_reject_promise(js, p, settle_error); 440 return js_mkundef(); 441 } 442 if (rs && rs->state == RS_STATE_ERRORED) { 443 js_reject_promise(js, p, rs_stream_error(readable)); 444 return js_mkundef(); 445 } 446 ant_value_t writable = ts_writable(ts_obj); 447 ws_stream_t *ws = ws_get_stream(writable); 448 449 if (ws && ws->state == WS_STATE_WRITABLE) 450 ts_error_writable_and_unblock_write(js, ts_obj, reason); 451 452 js_resolve_promise(js, p, js_mkundef()); 453 return js_mkundef(); 454} 455 456static ant_value_t ts_source_cancel_reject(ant_t *js, ant_value_t *args, int nargs) { 457 ant_value_t wrapper = js_get_slot(js->current_func, SLOT_DATA); 458 ant_value_t p = js_get_slot(wrapper, SLOT_DATA); 459 ant_value_t ts_obj = js_get_slot(wrapper, SLOT_ENTRIES); 460 ant_value_t err = (nargs > 0) ? args[0] : js_mkundef(); 461 ts_error_writable_and_unblock_write(js, ts_obj, err); 462 js_reject_promise(js, p, err); 463 return js_mkundef(); 464} 465 466static ant_value_t ts_abort_cancel_resolve(ant_t *js, ant_value_t *args, int nargs) { 467 ant_value_t wrapper = js_get_slot(js->current_func, SLOT_DATA); 468 ant_value_t p = js_get_slot(wrapper, SLOT_DATA); 469 ant_value_t ts_obj = js_get_slot(wrapper, SLOT_ENTRIES); 470 ant_value_t reason = js_get_slot(wrapper, SLOT_AUX); 471 472 ant_value_t readable = ts_readable(ts_obj); 473 rs_stream_t *rs = rs_get_stream(readable); 474 475 if (rs && rs->state == RS_STATE_ERRORED) { 476 js_reject_promise(js, p, rs_stream_error(readable)); 477 return js_mkundef(); 478 } 479 480 if (ts_cancel_joined_abort(ts_obj)) js_set_slot_wb(js, ts_obj, SLOT_RS_SIZE, reason); 481 ts_error(js, ts_obj, reason); 482 483 if (ts_cancel_joined_abort(ts_obj)) js_reject_promise(js, p, reason); 484 else js_resolve_promise(js, p, js_mkundef()); 485 486 return js_mkundef(); 487} 488 489static ant_value_t ts_abort_cancel_reject(ant_t *js, ant_value_t *args, int nargs) { 490 ant_value_t wrapper = js_get_slot(js->current_func, SLOT_DATA); 491 ant_value_t p = js_get_slot(wrapper, SLOT_DATA); 492 ant_value_t ts_obj = js_get_slot(wrapper, SLOT_ENTRIES); 493 ant_value_t err = (nargs > 0) ? args[0] : js_mkundef(); 494 ts_error(js, ts_obj, err); 495 js_reject_promise(js, p, err); 496 return js_mkundef(); 497} 498 499static ant_value_t ts_close_cancel_resolve(ant_t *js, ant_value_t *args, int nargs) { 500 ant_value_t wrapper = js_get_slot(js->current_func, SLOT_DATA); 501 ant_value_t p = js_get_slot(wrapper, SLOT_DATA); 502 ant_value_t ts_obj = js_get_slot(wrapper, SLOT_ENTRIES); 503 ant_value_t readable = ts_readable(ts_obj); 504 rs_stream_t *rs = rs_get_stream(readable); 505 ant_value_t settle_error = ts_cancel_settle_error(ts_obj); 506 if (is_object_type(settle_error)) { 507 js_reject_promise(js, p, settle_error); 508 return js_mkundef(); 509 } 510 if (rs && rs->state == RS_STATE_ERRORED) { 511 js_reject_promise(js, p, rs_stream_error(readable)); 512 return js_mkundef(); 513 } 514 js_resolve_promise(js, p, js_mkundef()); 515 return js_mkundef(); 516} 517 518static ant_value_t ts_close_cancel_reject(ant_t *js, ant_value_t *args, int nargs) { 519 ant_value_t wrapper = js_get_slot(js->current_func, SLOT_DATA); 520 ant_value_t p = js_get_slot(wrapper, SLOT_DATA); 521 ant_value_t err = (nargs > 0) ? args[0] : js_mkundef(); 522 js_reject_promise(js, p, err); 523 return js_mkundef(); 524} 525 526static ant_value_t ts_sink_write_bp_resolve(ant_t *js, ant_value_t *args, int nargs) { 527 ant_value_t wrapper = js_get_slot(js->current_func, SLOT_DATA); 528 ant_value_t ctrl_obj = js_get_slot(wrapper, SLOT_DATA); 529 ant_value_t chunk = js_get_slot(wrapper, SLOT_ENTRIES); 530 ant_value_t ts_obj = js_get_slot(wrapper, SLOT_CTOR); 531 ws_stream_t *ws = ws_get_stream(ts_writable(ts_obj)); 532 533 if (ws && ws->state == WS_STATE_ERRORING) { 534 ant_value_t err = ts_writable_stored_error(ts_obj); 535 if (!is_object_type(err)) 536 err = js_make_error_silent(js, JS_ERR_TYPE, "WritableStream is in erroring state"); 537 ant_value_t fp = ts_ctrl_finish_promise(ctrl_obj); 538 if (vtype(fp) == T_PROMISE) js_reject_promise(js, fp, err); 539 return js_mkundef(); 540 } 541 542 ant_value_t transform_p = ts_ctrl_perform_transform(js, ctrl_obj, chunk); 543 ant_value_t fp = ts_ctrl_finish_promise(ctrl_obj); 544 if (vtype(fp) == T_PROMISE) { 545 ant_value_t resolve_fn = js_heavy_mkfun(js, ts_transform_resolve, fp); 546 ant_value_t rej_wrapper = js_mkobj(js); 547 js_set_slot(rej_wrapper, SLOT_DATA, fp); 548 js_set_slot(rej_wrapper, SLOT_ENTRIES, ts_obj); 549 ant_value_t reject_fn = js_heavy_mkfun(js, ts_transform_reject, rej_wrapper); 550 ts_chain_promise(js, transform_p, resolve_fn, reject_fn); 551 } 552 return js_mkundef(); 553} 554 555static ant_value_t ts_sink_write(ant_t *js, ant_value_t *args, int nargs) { 556 ant_value_t ts_obj = js_get_slot(js->current_func, SLOT_DATA); 557 ant_value_t chunk = (nargs > 0) ? args[0] : js_mkundef(); 558 ant_value_t ctrl_obj = ts_controller(ts_obj); 559 560 ant_value_t finish_p = js_mkpromise(js); 561 promise_mark_handled(finish_p); 562 js_set_slot_wb(js, ctrl_obj, SLOT_RS_PULL, finish_p); 563 564 if (ts_get_backpressure(ts_obj)) { 565 ant_value_t wrapper = js_mkobj(js); 566 js_set_slot(wrapper, SLOT_DATA, ctrl_obj); 567 js_set_slot(wrapper, SLOT_ENTRIES, chunk); 568 js_set_slot(wrapper, SLOT_CTOR, ts_obj); 569 ant_value_t res_fn = js_heavy_mkfun(js, ts_sink_write_bp_resolve, wrapper); 570 ant_value_t rej_wrapper = js_mkobj(js); 571 js_set_slot(rej_wrapper, SLOT_DATA, finish_p); 572 js_set_slot(rej_wrapper, SLOT_ENTRIES, ts_obj); 573 ant_value_t rej_fn = js_heavy_mkfun(js, ts_transform_reject, rej_wrapper); 574 ant_value_t bp = ts_bp_promise(ts_obj); 575 ts_chain_promise(js, bp, res_fn, rej_fn); 576 } else { 577 ant_value_t transform_p = ts_ctrl_perform_transform(js, ctrl_obj, chunk); 578 ant_value_t resolve_fn = js_heavy_mkfun(js, ts_transform_resolve, finish_p); 579 ant_value_t rej_wrapper = js_mkobj(js); 580 js_set_slot(rej_wrapper, SLOT_DATA, finish_p); 581 js_set_slot(rej_wrapper, SLOT_ENTRIES, ts_obj); 582 ant_value_t reject_fn = js_heavy_mkfun(js, ts_transform_reject, rej_wrapper); 583 ts_chain_promise(js, transform_p, resolve_fn, reject_fn); 584 } 585 586 return finish_p; 587} 588 589static ant_value_t ts_sink_abort(ant_t *js, ant_value_t *args, int nargs) { 590 ant_value_t ts_obj = js_get_slot(js->current_func, SLOT_DATA); 591 ant_value_t ctrl_obj = ts_controller(ts_obj); 592 ant_value_t cancel_fn = ts_ctrl_cancel_fn(ctrl_obj); 593 ant_value_t reason = (nargs > 0) ? args[0] : js_mkundef(); 594 595 bool joined_source_cancel = vtype(ts_cancel_promise(ts_obj)) == T_PROMISE && !ts_cancel_started_by_abort(ts_obj); 596 if (joined_source_cancel && ts_cancel_has_user_handler(ts_obj)) 597 js_set_slot(ts_obj, SLOT_WS_WRITE, js_true); 598 599 ant_value_t p = js_mkpromise(js); 600 ant_value_t base = ts_run_cancel_algorithm(js, ts_obj, cancel_fn, reason, true); 601 ant_value_t wrapper = js_mkobj(js); 602 js_set_slot(wrapper, SLOT_DATA, p); 603 js_set_slot(wrapper, SLOT_ENTRIES, ts_obj); 604 js_set_slot(wrapper, SLOT_AUX, reason); 605 js_set_slot(wrapper, SLOT_CTOR, ts_cancel_started_by_abort(ts_obj) ? js_true : js_false); 606 607 ant_value_t res_fn = js_heavy_mkfun(js, ts_abort_cancel_resolve, wrapper); 608 ant_value_t rej_fn = js_heavy_mkfun(js, ts_abort_cancel_reject, wrapper); 609 ts_chain_promise(js, base, res_fn, rej_fn); 610 611 return p; 612} 613 614static ant_value_t ts_sink_close_resolve(ant_t *js, ant_value_t *args, int nargs) { 615 ant_value_t wrapper = js_get_slot(js->current_func, SLOT_DATA); 616 ant_value_t p = js_get_slot(wrapper, SLOT_DATA); 617 ant_value_t ts_obj = js_get_slot(wrapper, SLOT_ENTRIES); 618 619 ant_value_t readable = ts_readable(ts_obj); 620 rs_stream_t *rs = rs_get_stream(readable); 621 ant_value_t rs_ctrl = rs_stream_controller(js, readable); 622 ts_set_flushing(ts_obj, false); 623 624 if (rs && rs->state == RS_STATE_READABLE) { 625 rs_controller_close(js, rs_ctrl); 626 js_resolve_promise(js, p, js_mkundef()); 627 } else if (rs && rs->state == RS_STATE_CLOSED) { 628 js_resolve_promise(js, p, js_mkundef()); 629 } else if (rs && rs->state == RS_STATE_ERRORED) { 630 js_reject_promise(js, p, rs_stream_error(readable)); 631 } else { 632 js_reject_promise(js, p, js_make_error_silent(js, JS_ERR_TYPE, "TransformStream readable side is not in a readable state")); 633 } 634 635 return js_mkundef(); 636} 637 638static ant_value_t ts_sink_close_reject(ant_t *js, ant_value_t *args, int nargs) { 639 ant_value_t wrapper = js_get_slot(js->current_func, SLOT_DATA); 640 ant_value_t p = js_get_slot(wrapper, SLOT_DATA); 641 ant_value_t ts_obj = js_get_slot(wrapper, SLOT_ENTRIES); 642 ant_value_t e = (nargs > 0) ? args[0] : js_mkundef(); 643 ts_set_flushing(ts_obj, false); 644 ts_error(js, ts_obj, e); 645 js_reject_promise(js, p, e); 646 return js_mkundef(); 647} 648 649static ant_value_t ts_sink_close(ant_t *js, ant_value_t *args, int nargs) { 650 ant_value_t ts_obj = js_get_slot(js->current_func, SLOT_DATA); 651 ant_value_t ctrl_obj = ts_controller(ts_obj); 652 ant_value_t readable = ts_readable(ts_obj); 653 654 ant_value_t flush_fn = ts_ctrl_flush_fn(ctrl_obj); 655 ant_value_t p = js_mkpromise(js); 656 promise_mark_handled(p); 657 658 ant_value_t cancel_p = ts_cancel_promise(ts_obj); 659 if (vtype(cancel_p) == T_PROMISE) { 660 ant_value_t wrapper = js_mkobj(js); 661 js_set_slot(wrapper, SLOT_DATA, p); 662 js_set_slot(wrapper, SLOT_ENTRIES, ts_obj); 663 ant_value_t res_fn = js_heavy_mkfun(js, ts_close_cancel_resolve, wrapper); 664 ant_value_t rej_fn = js_heavy_mkfun(js, ts_close_cancel_reject, wrapper); 665 ts_chain_promise(js, cancel_p, res_fn, rej_fn); 666 return p; 667 } 668 669 ts_ctrl_clear_algorithms(ctrl_obj); 670 ts_set_flushing(ts_obj, true); 671 672 if (is_callable(flush_fn)) { 673 ant_value_t flush_args[1] = { ctrl_obj }; 674 ant_value_t result = sv_vm_call(js->vm, js, flush_fn, ts_ctrl_transformer(ctrl_obj), flush_args, 1, NULL, false); 675 676 if (is_err(result)) { 677 ant_value_t err = ts_take_thrown_or(js, result); 678 ts_error(js, ts_obj, err); 679 ts_set_flushing(ts_obj, false); 680 js_reject_promise(js, p, err); 681 return p; 682 } 683 684 ant_value_t wrapper = js_mkobj(js); 685 js_set_slot(wrapper, SLOT_DATA, p); 686 js_set_slot(wrapper, SLOT_ENTRIES, ts_obj); 687 ant_value_t res_fn = js_heavy_mkfun(js, ts_sink_close_resolve, wrapper); 688 ant_value_t rej_fn = js_heavy_mkfun(js, ts_sink_close_reject, wrapper); 689 690 ts_chain_promise(js, result, res_fn, rej_fn); 691 } else { 692 rs_stream_t *rs = rs_get_stream(readable); 693 if (rs && rs->state == RS_STATE_READABLE) { 694 ant_value_t rs_ctrl = rs_stream_controller(js, readable); 695 rs_controller_t *rc = rs_get_controller(rs_ctrl); 696 if (rc) rc->defer_close = true; 697 rs_controller_close(js, rs_ctrl); 698 if (rc) rc->defer_close = false; 699 } 700 ts_set_flushing(ts_obj, false); 701 js_resolve_promise(js, p, js_mkundef()); 702 } 703 704 return p; 705} 706 707static ant_value_t ts_source_pull_resolve(ant_t *js, ant_value_t *args, int nargs) { 708 ant_value_t p = js_get_slot(js->current_func, SLOT_DATA); 709 js_resolve_promise(js, p, js_mkundef()); 710 return js_mkundef(); 711} 712 713static ant_value_t ts_source_pull(ant_t *js, ant_value_t *args, int nargs) { 714 ant_value_t ts_obj = js_get_slot(js->current_func, SLOT_DATA); 715 716 if (ts_get_backpressure(ts_obj)) { 717 ts_set_backpressure(js, ts_obj, false); 718 ant_value_t p = js_mkpromise(js); 719 js_resolve_promise(js, p, js_mkundef()); 720 return p; 721 } 722 723 ant_value_t p = js_mkpromise(js); 724 js_resolve_promise(js, p, js_mkundef()); 725 return p; 726} 727 728static ant_value_t ts_source_cancel(ant_t *js, ant_value_t *args, int nargs) { 729 ant_value_t ts_obj = js_get_slot(js->current_func, SLOT_DATA); 730 ant_value_t ctrl_obj = ts_controller(ts_obj); 731 ant_value_t cancel_fn = ts_ctrl_cancel_fn(ctrl_obj); 732 ant_value_t reason = (nargs > 0) ? args[0] : js_mkundef(); 733 734 if (ts_is_flushing(ts_obj)) { 735 ant_value_t p = js_mkpromise(js); 736 js_resolve_promise(js, p, js_mkundef()); 737 return p; 738 } 739 740 ant_value_t p = js_mkpromise(js); 741 ant_value_t base = ts_run_cancel_algorithm(js, ts_obj, cancel_fn, reason, false); 742 ant_value_t wrapper = js_mkobj(js); 743 js_set_slot(wrapper, SLOT_DATA, p); 744 js_set_slot(wrapper, SLOT_ENTRIES, ts_obj); 745 js_set_slot(wrapper, SLOT_AUX, reason); 746 js_set_slot(wrapper, SLOT_CTOR, ts_cancel_started_by_abort(ts_obj) ? js_true : js_false); 747 ant_value_t res_fn = js_heavy_mkfun(js, ts_source_cancel_resolve, wrapper); 748 ant_value_t rej_fn = js_heavy_mkfun(js, ts_source_cancel_reject, wrapper); 749 ts_chain_promise(js, base, res_fn, rej_fn); 750 return p; 751} 752 753static ant_value_t js_ts_ctrl_get_desired_size(ant_t *js, ant_value_t *args, int nargs) { 754 ant_value_t ts_obj = ts_ctrl_stream(js->this_val); 755 ant_value_t readable = ts_readable(ts_obj); 756 ant_value_t rs_ctrl = rs_stream_controller(js, readable); 757 rs_controller_t *rc = rs_get_controller(rs_ctrl); 758 rs_stream_t *rs = rs_get_stream(readable); 759 if (!rc || !rs) return js_mknull(); 760 if (rs->state == RS_STATE_ERRORED) return js_mknull(); 761 if (rs->state == RS_STATE_CLOSED) return js_mknum(0); 762 return js_mknum(rc->strategy_hwm - rc->queue_total_size); 763} 764 765static ant_value_t js_ts_ctrl_enqueue(ant_t *js, ant_value_t *args, int nargs) { 766 ant_value_t ts_obj = ts_ctrl_stream(js->this_val); 767 ant_value_t readable = ts_readable(ts_obj); 768 rs_stream_t *rs = rs_get_stream(readable); 769 if (!rs || rs->state != RS_STATE_READABLE) 770 return js_mkerr_typed(js, JS_ERR_TYPE, "Readable side is not in a readable state"); 771 772 ant_value_t chunk = (nargs > 0) ? args[0] : js_mkundef(); 773 return ts_ctrl_enqueue(js, js->this_val, chunk); 774} 775 776static ant_value_t js_ts_ctrl_error(ant_t *js, ant_value_t *args, int nargs) { 777 ant_value_t e = (nargs > 0) ? args[0] : js_mkundef(); 778 ts_ctrl_error(js, js->this_val, e); 779 return js_mkundef(); 780} 781 782static ant_value_t js_ts_ctrl_terminate(ant_t *js, ant_value_t *args, int nargs) { 783 ts_ctrl_terminate(js, js->this_val); 784 return js_mkundef(); 785} 786 787static ant_value_t js_ts_get_readable(ant_t *js, ant_value_t *args, int nargs) { 788 if (!ts_is_stream(js->this_val)) return js_mkerr_typed(js, JS_ERR_TYPE, "Invalid TransformStream"); 789 return ts_readable(js->this_val); 790} 791 792static ant_value_t js_ts_get_writable(ant_t *js, ant_value_t *args, int nargs) { 793 if (!ts_is_stream(js->this_val)) return js_mkerr_typed(js, JS_ERR_TYPE, "Invalid TransformStream"); 794 return ts_writable(js->this_val); 795} 796 797static ant_value_t ts_start_resolve(ant_t *js, ant_value_t *args, int nargs) { 798 ant_value_t ts_obj = js_get_slot(js->current_func, SLOT_DATA); 799 ant_value_t writable = ts_writable(ts_obj); 800 ant_value_t ws_ctrl = ws_stream_controller(writable); 801 ws_controller_t *wc = ws_get_controller(ws_ctrl); 802 if (wc) wc->started = true; 803 ws_default_controller_advance_queue_if_needed(js, ws_ctrl); 804 805 ant_value_t readable = ts_readable(ts_obj); 806 ant_value_t rs_ctrl = rs_stream_controller(js, readable); 807 rs_controller_t *rc = rs_get_controller(rs_ctrl); 808 if (rc) { 809 rc->started = true; 810 rc->pulling = false; 811 rc->pull_again = false; 812 rs_default_controller_call_pull_if_needed(js, rs_ctrl); 813 } 814 815 return js_mkundef(); 816} 817 818static ant_value_t ts_start_reject(ant_t *js, ant_value_t *args, int nargs) { 819 ant_value_t ts_obj = js_get_slot(js->current_func, SLOT_DATA); 820 ant_value_t e = (nargs > 0) ? args[0] : js_mkundef(); 821 822 ant_value_t writable = ts_writable(ts_obj); 823 ant_value_t ws_ctrl = ws_stream_controller(writable); 824 ws_controller_t *wc = ws_get_controller(ws_ctrl); 825 if (wc) wc->started = true; 826 827 ant_value_t readable = ts_readable(ts_obj); 828 ant_value_t rs_ctrl = rs_stream_controller(js, readable); 829 rs_controller_t *rc = rs_get_controller(rs_ctrl); 830 if (rc) rc->started = true; 831 832 readable_stream_error(js, readable, e); 833 834 ws_stream_t *ws = ws_get_stream(writable); 835 if (ws && ws->state == WS_STATE_WRITABLE) 836 ws_default_controller_error(js, ws_ctrl, e); 837 else if (ws && ws->state == WS_STATE_ERRORING) 838 writable_stream_finish_erroring(js, writable); 839 840 return js_mkundef(); 841} 842 843ant_value_t js_ts_ctor(ant_t *js, ant_value_t *args, int nargs) { 844 if (vtype(js->new_target) == T_UNDEF) 845 return js_mkerr_typed(js, JS_ERR_TYPE, "TransformStream constructor requires 'new'"); 846 847 ant_value_t transformer = js_mkundef(); 848 if (nargs > 0 && !is_undefined(args[0])) 849 transformer = args[0]; 850 851 if (is_object_type(transformer)) { 852 ant_value_t rt_val = js_getprop_fallback(js, transformer, "readableType"); 853 if (!is_undefined(rt_val)) 854 return js_mkerr_typed(js, JS_ERR_RANGE, "readableType is not supported"); 855 ant_value_t wt_val = js_getprop_fallback(js, transformer, "writableType"); 856 if (!is_undefined(wt_val)) 857 return js_mkerr_typed(js, JS_ERR_RANGE, "writableType is not supported"); 858 } 859 860 ant_value_t writable_strategy = js_mkundef(); 861 if (nargs > 1 && !is_undefined(args[1]) && !is_null(args[1])) 862 writable_strategy = args[1]; 863 864 ant_value_t readable_strategy = js_mkundef(); 865 if (nargs > 2 && !is_undefined(args[2]) && !is_null(args[2])) 866 readable_strategy = args[2]; 867 868 double writable_hwm = 1; 869 ant_value_t writable_size_fn = js_mkundef(); 870 if (is_object_type(writable_strategy)) { 871 ant_value_t hwm_val = js_getprop_fallback(js, writable_strategy, "highWaterMark"); 872 if (is_err(hwm_val)) return hwm_val; 873 if (!is_undefined(hwm_val)) { 874 writable_hwm = js_to_number(js, hwm_val); 875 if (writable_hwm != writable_hwm || writable_hwm < 0) 876 return js_mkerr_typed(js, JS_ERR_RANGE, "Invalid highWaterMark"); 877 } 878 ant_value_t s = js_getprop_fallback(js, writable_strategy, "size"); 879 if (is_err(s)) return s; 880 if (!is_undefined(s)) { 881 if (!is_callable(s)) return js_mkerr_typed(js, JS_ERR_TYPE, "size must be a function"); 882 writable_size_fn = s; 883 } 884 } 885 886 double readable_hwm = 0; 887 ant_value_t readable_size_fn = js_mkundef(); 888 if (is_object_type(readable_strategy)) { 889 ant_value_t hwm_val = js_getprop_fallback(js, readable_strategy, "highWaterMark"); 890 if (is_err(hwm_val)) return hwm_val; 891 if (!is_undefined(hwm_val)) { 892 readable_hwm = js_to_number(js, hwm_val); 893 if (readable_hwm != readable_hwm || readable_hwm < 0) 894 return js_mkerr_typed(js, JS_ERR_RANGE, "Invalid highWaterMark"); 895 } 896 ant_value_t s = js_getprop_fallback(js, readable_strategy, "size"); 897 if (is_err(s)) return s; 898 if (!is_undefined(s)) { 899 if (!is_callable(s)) return js_mkerr_typed(js, JS_ERR_TYPE, "size must be a function"); 900 readable_size_fn = s; 901 } 902 } 903 904 ant_value_t transform_fn = js_mkundef(); 905 ant_value_t flush_fn = js_mkundef(); 906 ant_value_t cancel_fn = js_mkundef(); 907 ant_value_t start_fn = js_mkundef(); 908 909 if (is_object_type(transformer)) { 910 ant_value_t tv = js_getprop_fallback(js, transformer, "transform"); 911 if (is_err(tv)) return tv; 912 if (!is_undefined(tv)) { 913 if (!is_callable(tv)) return js_mkerr_typed(js, JS_ERR_TYPE, "transform must be a function"); 914 transform_fn = tv; 915 } 916 ant_value_t fv = js_getprop_fallback(js, transformer, "flush"); 917 if (is_err(fv)) return fv; 918 if (!is_undefined(fv)) { 919 if (!is_callable(fv)) return js_mkerr_typed(js, JS_ERR_TYPE, "flush must be a function"); 920 flush_fn = fv; 921 } 922 ant_value_t cv = js_getprop_fallback(js, transformer, "cancel"); 923 if (is_err(cv)) return cv; 924 if (!is_undefined(cv)) { 925 if (!is_callable(cv)) return js_mkerr_typed(js, JS_ERR_TYPE, "cancel must be a function"); 926 cancel_fn = cv; 927 } 928 ant_value_t sv = js_getprop_fallback(js, transformer, "start"); 929 if (is_err(sv)) return sv; 930 if (!is_undefined(sv)) { 931 if (!is_callable(sv)) return js_mkerr_typed(js, JS_ERR_TYPE, "start must be a function"); 932 start_fn = sv; 933 } 934 } 935 936 ant_value_t ts_obj = js_mkobj(js); 937 ant_value_t proto = js_instance_proto_from_new_target(js, g_ts_proto); 938 if (is_object_type(proto)) js_set_proto_init(ts_obj, proto); 939 js_set_slot(ts_obj, SLOT_BRAND, js_mknum(BRAND_TRANSFORM_STREAM)); 940 js_set_slot(ts_obj, SLOT_DATA, js_mknum(0)); 941 942 ant_value_t ctrl_obj = js_mkobj(js); 943 js_set_proto_init(ctrl_obj, g_ts_ctrl_proto); 944 js_set_slot(ctrl_obj, SLOT_BRAND, js_mknum(BRAND_TRANSFORM_STREAM_CONTROLLER)); 945 js_set_slot(ctrl_obj, SLOT_DATA, ts_obj); 946 js_set_slot(ctrl_obj, SLOT_ENTRIES, transform_fn); 947 js_set_slot(ctrl_obj, SLOT_CTOR, flush_fn); 948 js_set_slot(ctrl_obj, SLOT_AUX, cancel_fn); 949 js_set_slot(ctrl_obj, SLOT_SETTLED, transformer); 950 js_set_slot(ctrl_obj, SLOT_RS_PULL, js_mkundef()); 951 js_set_slot(ts_obj, SLOT_DEFAULT, ctrl_obj); 952 js_set_slot(ts_obj, SLOT_RS_CANCEL, js_mkundef()); 953 js_set_slot(ts_obj, SLOT_WS_ABORT, js_false); 954 js_set_slot(ts_obj, SLOT_WS_CLOSE, js_false); 955 js_set_slot(ts_obj, SLOT_RS_SIZE, js_mkundef()); 956 js_set_slot(ts_obj, SLOT_WS_WRITE, js_false); 957 js_set_slot(ts_obj, SLOT_WS_SIGNAL, js_false); 958 959 ant_value_t sink_write = js_heavy_mkfun(js, ts_sink_write, ts_obj); 960 ant_value_t sink_abort = js_heavy_mkfun(js, ts_sink_abort, ts_obj); 961 ant_value_t sink_close = js_heavy_mkfun(js, ts_sink_close, ts_obj); 962 963 ant_value_t source_pull = js_heavy_mkfun(js, ts_source_pull, ts_obj); 964 ant_value_t source_cancel = js_heavy_mkfun(js, ts_source_cancel, ts_obj); 965 966 rs_stream_t *rst = calloc(1, sizeof(rs_stream_t)); 967 if (!rst) return js_mkerr(js, "out of memory"); 968 rst->state = RS_STATE_READABLE; 969 970 ant_value_t rs_obj = js_mkobj(js); 971 js_set_proto_init(rs_obj, g_rs_proto); 972 js_set_slot(rs_obj, SLOT_BRAND, js_mknum(BRAND_READABLE_STREAM)); 973 js_set_slot(rs_obj, SLOT_DATA, ANT_PTR(rst)); 974 js_set_finalizer(rs_obj, ts_rs_finalize); 975 976 rs_controller_t *rcc = calloc(1, sizeof(rs_controller_t)); 977 if (!rcc) { free(rst); return js_mkerr(js, "out of memory"); } 978 rcc->strategy_hwm = readable_hwm; 979 980 ant_value_t rs_ctrl_obj = js_mkobj(js); 981 js_set_proto_init(rs_ctrl_obj, g_controller_proto); 982 js_set_slot(rs_ctrl_obj, SLOT_BRAND, js_mknum(BRAND_READABLE_STREAM_CONTROLLER)); 983 js_set_slot(rs_ctrl_obj, SLOT_DATA, ANT_PTR(rcc)); 984 js_set_slot(rs_ctrl_obj, SLOT_ENTRIES, rs_obj); 985 js_set_slot(rs_ctrl_obj, SLOT_RS_PULL, source_pull); 986 js_set_slot(rs_ctrl_obj, SLOT_RS_CANCEL, source_cancel); 987 js_set_slot(rs_ctrl_obj, SLOT_RS_SIZE, readable_size_fn); 988 js_set_slot(rs_ctrl_obj, SLOT_AUX, js_mkarr(js)); 989 js_set_finalizer(rs_ctrl_obj, ts_rs_ctrl_finalize); 990 js_set_slot(rs_obj, SLOT_ENTRIES, rs_ctrl_obj); 991 992 js_set_slot(ts_obj, SLOT_ENTRIES, rs_obj); 993 994 ws_stream_t *wst = calloc(1, sizeof(ws_stream_t)); 995 if (!wst) return js_mkerr(js, "out of memory"); 996 wst->state = WS_STATE_WRITABLE; 997 998 ant_value_t ws_obj = js_mkobj(js); 999 js_set_proto_init(ws_obj, g_ws_proto); 1000 js_set_slot(ws_obj, SLOT_BRAND, js_mknum(BRAND_WRITABLE_STREAM)); 1001 js_set_slot(ws_obj, SLOT_DATA, ANT_PTR(wst)); 1002 js_set_slot(ws_obj, SLOT_SETTLED, js_mkarr(js)); 1003 js_set_finalizer(ws_obj, ts_ws_finalize); 1004 1005 js_set_slot(ts_obj, SLOT_CTOR, ws_obj); 1006 1007 ant_value_t bp_promise = js_mkpromise(js); 1008 js_set_slot_wb(js, ts_obj, SLOT_AUX, bp_promise); 1009 1010 ts_set_backpressure(js, ts_obj, true); 1011 1012 ws_controller_t *wc = calloc(1, sizeof(ws_controller_t)); 1013 if (!wc) { free(wst); return js_mkerr(js, "out of memory"); } 1014 wc->strategy_hwm = writable_hwm; 1015 1016 ant_value_t ws_ctrl_obj = js_mkobj(js); 1017 js_set_proto_init(ws_ctrl_obj, g_ws_controller_proto); 1018 js_set_slot(ws_ctrl_obj, SLOT_BRAND, js_mknum(BRAND_WRITABLE_STREAM_CONTROLLER)); 1019 js_set_slot(ws_ctrl_obj, SLOT_DATA, ANT_PTR(wc)); 1020 js_set_slot(ws_ctrl_obj, SLOT_ENTRIES, ws_obj); 1021 js_set_slot(ws_ctrl_obj, SLOT_WS_WRITE, sink_write); 1022 js_set_slot(ws_ctrl_obj, SLOT_WS_CLOSE, sink_close); 1023 js_set_slot(ws_ctrl_obj, SLOT_WS_ABORT, sink_abort); 1024 js_set_slot(ws_ctrl_obj, SLOT_RS_SIZE, writable_size_fn); 1025 js_set_slot(ws_ctrl_obj, SLOT_CTOR, js_mkundef()); 1026 js_set_slot(ws_ctrl_obj, SLOT_AUX, js_mkarr(js)); 1027 js_set_finalizer(ws_ctrl_obj, ts_ws_ctrl_finalize); 1028 1029 js_set_slot(ws_obj, SLOT_ENTRIES, ws_ctrl_obj); 1030 1031 if (is_callable(start_fn)) { 1032 ant_value_t start_args[1] = { ctrl_obj }; 1033 ant_value_t start_result = sv_vm_call(js->vm, js, start_fn, transformer, start_args, 1, NULL, false); 1034 if (is_err(start_result)) { return start_result; } 1035 1036 if (vtype(start_result) == T_PROMISE) { 1037 ant_value_t resolve_fn = js_heavy_mkfun(js, ts_start_resolve, ts_obj); 1038 ant_value_t reject_fn = js_heavy_mkfun(js, ts_start_reject, ts_obj); 1039 js_promise_then(js, start_result, resolve_fn, reject_fn); 1040 } 1041 1042 if (vtype(start_result) != T_PROMISE) { 1043 ant_value_t resolved = js_mkpromise(js); 1044 js_resolve_promise(js, resolved, js_mkundef()); 1045 ant_value_t res_fn = js_heavy_mkfun(js, ts_start_resolve, ts_obj); 1046 ant_value_t rej_fn = js_heavy_mkfun(js, ts_start_reject, ts_obj); 1047 js_promise_then(js, resolved, res_fn, rej_fn); 1048 } 1049 } else { 1050 ant_value_t resolved = js_mkpromise(js); 1051 js_resolve_promise(js, resolved, js_mkundef()); 1052 ant_value_t res_fn = js_heavy_mkfun(js, ts_start_resolve, ts_obj); 1053 ant_value_t rej_fn = js_heavy_mkfun(js, ts_start_reject, ts_obj); 1054 js_promise_then(js, resolved, res_fn, rej_fn); 1055 } 1056 1057 return ts_obj; 1058} 1059 1060static ant_value_t js_ts_ctrl_ctor(ant_t *js, ant_value_t *args, int nargs) { 1061 return js_mkerr_typed(js, JS_ERR_TYPE, "TransformStreamDefaultController cannot be constructed directly"); 1062} 1063 1064void init_transform_stream_module(void) { 1065 ant_t *js = rt->js; 1066 ant_value_t g = js_glob(js); 1067 1068 g_ts_ctrl_proto = js_mkobj(js); 1069 js_set_getter_desc(js, g_ts_ctrl_proto, "desiredSize", 11, js_mkfun(js_ts_ctrl_get_desired_size), JS_DESC_C); 1070 js_set(js, g_ts_ctrl_proto, "enqueue", js_mkfun(js_ts_ctrl_enqueue)); 1071 js_set_descriptor(js, g_ts_ctrl_proto, "enqueue", 7, JS_DESC_W | JS_DESC_C); 1072 js_set(js, g_ts_ctrl_proto, "error", js_mkfun(js_ts_ctrl_error)); 1073 js_set_descriptor(js, g_ts_ctrl_proto, "error", 5, JS_DESC_W | JS_DESC_C); 1074 js_set(js, g_ts_ctrl_proto, "terminate", js_mkfun(js_ts_ctrl_terminate)); 1075 js_set_descriptor(js, g_ts_ctrl_proto, "terminate", 9, JS_DESC_W | JS_DESC_C); 1076 js_set_sym(js, g_ts_ctrl_proto, get_toStringTag_sym(), js_mkstr(js, "TransformStreamDefaultController", 32)); 1077 1078 ant_value_t ctrl_ctor = js_make_ctor(js, js_ts_ctrl_ctor, g_ts_ctrl_proto, "TransformStreamDefaultController", 32); 1079 js_set(js, g, "TransformStreamDefaultController", ctrl_ctor); 1080 js_set_descriptor(js, g, "TransformStreamDefaultController", 32, JS_DESC_W | JS_DESC_C); 1081 1082 g_ts_proto = js_mkobj(js); 1083 js_set_getter_desc(js, g_ts_proto, "readable", 8, js_mkfun(js_ts_get_readable), JS_DESC_C); 1084 js_set_getter_desc(js, g_ts_proto, "writable", 8, js_mkfun(js_ts_get_writable), JS_DESC_C); 1085 js_set_sym(js, g_ts_proto, get_toStringTag_sym(), js_mkstr(js, "TransformStream", 15)); 1086 1087 ant_value_t ts_ctor = js_make_ctor(js, js_ts_ctor, g_ts_proto, "TransformStream", 15); 1088 js_set(js, g, "TransformStream", ts_ctor); 1089 js_set_descriptor(js, g, "TransformStream", 15, JS_DESC_W | JS_DESC_C); 1090} 1091 1092void gc_mark_transform_streams(ant_t *js, void (*mark)(ant_t *, ant_value_t)) { 1093 mark(js, g_ts_proto); 1094 mark(js, g_ts_ctrl_proto); 1095}