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