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.

improve string spread handling for arrays and literals

+99 -99
+99 -99
src/ant.c
··· 3646 3646 return array_alloc_from_ctor_with_length(js, ctor, 0); 3647 3647 } 3648 3648 3649 - static jsval_t array_alloc_like(struct js *js, jsval_t receiver) { 3649 + static inline jsval_t array_alloc_like(struct js *js, jsval_t receiver) { 3650 3650 jsval_t ctor = array_constructor_from_receiver(js, receiver); 3651 3651 if (is_err(ctor)) return ctor; 3652 3652 return array_alloc_from_ctor(js, ctor); ··· 6781 6781 6782 6782 typedef enum { ITER_CONTINUE, ITER_BREAK, ITER_ERROR } iter_action_t; 6783 6783 typedef iter_action_t (*iter_callback_t)(struct js *js, jsval_t value, void *ctx, jsval_t *out); 6784 - 6785 6784 static jsval_t iter_foreach(struct js *js, jsval_t iterable, iter_callback_t cb, void *ctx); 6786 - typedef struct { UT_array *args; } spread_utarray_ctx_t; 6787 6785 6788 - static iter_action_t spread_utarray_iter_cb(struct js *js, jsval_t value, void *ctx, jsval_t *out) { 6789 - spread_utarray_ctx_t *sctx = (spread_utarray_ctx_t *)ctx; 6790 - utarray_push_back(sctx->args, &value); 6791 - return ITER_CONTINUE; 6792 - } 6793 - 6794 - static jsval_t append_spread_to_utarray(struct js *js, UT_array *args, jsval_t spread_value) { 6795 - if (vtype(spread_value) == T_ARR) { 6796 - jsoff_t len = js_arr_len(js, spread_value); 6797 - for (jsoff_t i = 0; i < len; i++) { 6798 - jsval_t elem = arr_get(js, spread_value, i); 6799 - utarray_push_back(args, &elem); 6800 - } return js_mkundef(); 6801 - } 6802 - spread_utarray_ctx_t ctx = { .args = args }; 6803 - return iter_foreach(js, spread_value, spread_utarray_iter_cb, &ctx); 6804 - } 6786 + #define SPREAD_STR_CB 0 6787 + #define SPREAD_STR_UTARRAY 1 6788 + #define SPREAD_STR_DYNARGS 2 6805 6789 6806 6790 typedef struct { 6807 6791 jsval_t **args; 6808 - int *argc; 6809 - int *args_cap; 6792 + int *argc; int *args_cap; 6810 6793 bool *args_on_heap; 6811 6794 } spread_dynargs_ctx_t; 6812 6795 ··· 6823 6806 (*ctx->args)[(*ctx->argc)++] = value; 6824 6807 } 6825 6808 6809 + static jsval_t str_spread_chars(struct js *js, jsval_t str, int flags, void *ctx, iter_callback_t cb) { 6810 + if (is_rope(js, str)) str = rope_flatten(js, str); 6811 + if (is_err(str)) return str; 6812 + jsoff_t len = str_len_fast(js, str); 6813 + for (jsoff_t i = 0; i < len; ) { 6814 + jsoff_t off = vstr(js, str, NULL); 6815 + unsigned char c = (unsigned char)js->mem[off + i]; 6816 + jsoff_t cb_len = 1; 6817 + if (c >= 0x80) { 6818 + int seq = utf8_sequence_length(c); 6819 + cb_len = seq > 0 ? (jsoff_t)seq : 1; 6820 + if (i + cb_len > len) cb_len = len - i; 6821 + } 6822 + jsval_t ch = js_mkstr(js, (char *)&js->mem[off + i], cb_len); 6823 + if (flags == SPREAD_STR_CB) { 6824 + jsval_t out; 6825 + iter_action_t act = cb(js, ch, ctx, &out); 6826 + if (act == ITER_ERROR) return out; 6827 + if (act == ITER_BREAK) break; 6828 + } else if (flags == SPREAD_STR_UTARRAY) { 6829 + utarray_push_back((UT_array *)ctx, &ch); 6830 + } else if (flags == SPREAD_STR_DYNARGS) { 6831 + spread_dynargs_push((spread_dynargs_ctx_t *)ctx, ch); 6832 + } i += cb_len; 6833 + } 6834 + return js_mkundef(); 6835 + } 6836 + 6837 + static iter_action_t spread_utarray_iter_cb(struct js *js, jsval_t value, void *ctx, jsval_t *out) { 6838 + utarray_push_back((UT_array *)ctx, &value); 6839 + return ITER_CONTINUE; 6840 + } 6841 + 6826 6842 static iter_action_t spread_dynargs_iter_cb(struct js *js, jsval_t value, void *ctx, jsval_t *out) { 6827 6843 spread_dynargs_ctx_t *sctx = (spread_dynargs_ctx_t *)ctx; 6828 6844 spread_dynargs_push(sctx, value); 6829 6845 return ITER_CONTINUE; 6830 6846 } 6831 6847 6848 + static jsval_t append_spread_to_utarray(struct js *js, UT_array *args, jsval_t spread_value) { 6849 + if (vtype(spread_value) == T_ARR) { 6850 + jsoff_t len = js_arr_len(js, spread_value); 6851 + for (jsoff_t i = 0; i < len; i++) { 6852 + jsval_t elem = arr_get(js, spread_value, i); 6853 + utarray_push_back(args, &elem); 6854 + } return js_mkundef(); 6855 + } 6856 + if (vtype(spread_value) == T_STR) return str_spread_chars(js, spread_value, SPREAD_STR_UTARRAY, args, NULL); 6857 + return iter_foreach(js, spread_value, spread_utarray_iter_cb, args); 6858 + } 6859 + 6832 6860 static jsval_t append_spread_to_dynargs(struct js *js, spread_dynargs_ctx_t *ctx, jsval_t spread_value) { 6833 6861 if (vtype(spread_value) == T_ARR) { 6834 6862 jsoff_t len = js_arr_len(js, spread_value); 6835 6863 for (jsoff_t i = 0; i < len; i++) spread_dynargs_push(ctx, arr_get(js, spread_value, i)); 6836 6864 return js_mkundef(); 6837 6865 } 6866 + if (vtype(spread_value) == T_STR) return str_spread_chars(js, spread_value, SPREAD_STR_DYNARGS, ctx, NULL); 6838 6867 return iter_foreach(js, spread_value, spread_dynargs_iter_cb, ctx); 6839 6868 } 6840 6869 ··· 9241 9270 return js_mkundef(); 9242 9271 } 9243 9272 if (t == T_STR) { 9244 - jsoff_t len, off = vstr(js, spread_value, &len); 9245 - for (jsoff_t i = 0; i < len; ) { 9246 - unsigned char c = (unsigned char)js->mem[off + i]; 9247 - jsoff_t cb = 1; 9248 - if (c >= 0x80) { 9249 - int seq = utf8_sequence_length(c); 9250 - cb = seq > 0 ? (jsoff_t)seq : 1; 9251 - if (i + cb > len) cb = len - i; 9252 - } 9253 - arr_set(js, arr, *idx, js_mkstr(js, (char *)&js->mem[off + i], cb)); 9254 - (*idx)++; i += cb; 9255 - off = vstr(js, spread_value, &len); 9256 - } 9257 - return js_mkundef(); 9273 + spread_arr_literal_ctx_t ctx = { .arr = arr, .idx = idx }; 9274 + return str_spread_chars(js, spread_value, SPREAD_STR_CB, &ctx, spread_arr_literal_iter_cb); 9258 9275 } 9259 9276 spread_arr_literal_ctx_t ctx = { .arr = arr, .idx = idx }; 9260 9277 return iter_foreach(js, spread_value, spread_arr_literal_iter_cb, &ctx); ··· 15412 15429 if (is_err(flags_val)) return flags_val; 15413 15430 jsval_t exec_val = js_get(js, regexp, "exec"); 15414 15431 if (is_err(exec_val)) return exec_val; 15415 - (void)flags_val; 15416 - (void)exec_val; 15417 15432 15418 15433 jsval_t str = nargs > 0 ? js_tostring_val(js, args[0]) : js_mkstr(js, "", 0); 15419 15434 if (is_err(str)) return str; ··· 17454 17469 obj = resolveprop(js, obj); 17455 17470 uint8_t t = vtype(obj); 17456 17471 17457 - if (is_object_type(obj)) { 17458 - jsval_t check_obj = (t != T_OBJ) ? mkval(T_OBJ, vdata(obj)) : obj; 17459 - const char *tostr_tag_key = get_toStringTag_sym_key(); 17460 - jsoff_t tag_off = lkp(js, check_obj, tostr_tag_key, strlen(tostr_tag_key)); 17461 - if (tag_off == 0) tag_off = lkp_proto(js, check_obj, tostr_tag_key, strlen(tostr_tag_key)); 17472 + const char *tag = NULL; 17473 + jsoff_t tag_len = 0; 17474 + 17475 + const char *tostr_tag_key = get_toStringTag_sym_key(); 17476 + if (tostr_tag_key && tostr_tag_key[0]) { 17477 + jsoff_t tag_off = 0; 17478 + if (is_object_type(obj)) { 17479 + jsval_t check_obj = (t != T_OBJ) ? mkval(T_OBJ, vdata(obj)) : obj; 17480 + tag_off = lkp(js, check_obj, tostr_tag_key, strlen(tostr_tag_key)); 17481 + if (tag_off == 0) tag_off = lkp_proto(js, check_obj, tostr_tag_key, strlen(tostr_tag_key)); 17482 + } else { 17483 + jsval_t proto = get_prototype_for_type(js, t); 17484 + if (is_object_type(proto)) { 17485 + tag_off = lkp(js, proto, tostr_tag_key, strlen(tostr_tag_key)); 17486 + if (tag_off == 0) tag_off = lkp_proto(js, proto, tostr_tag_key, strlen(tostr_tag_key)); 17487 + } 17488 + } 17462 17489 if (tag_off != 0) { 17463 17490 jsval_t tag_val = resolveprop(js, mkval(T_PROP, tag_off)); 17464 17491 if (vtype(tag_val) == T_STR) { 17465 - jsoff_t tag_len, tag_str_off = vstr(js, tag_val, &tag_len); 17466 - const char *tag_str = (const char *)&js->mem[tag_str_off]; 17467 - 17468 - char buf[256]; 17469 - int n = snprintf(buf, sizeof(buf), "[object %.*s]", (int)tag_len, tag_str); 17470 - return js_mkstr(js, buf, n); 17492 + jsoff_t str_off = vstr(js, tag_val, &tag_len); 17493 + tag = (const char *)&js->mem[str_off]; 17471 17494 } 17472 17495 } 17473 17496 } 17474 - 17475 - if (is_object_type(obj) && get_slot(js, obj, SLOT_ERROR_BRAND) == js_true) { 17476 - return js_mkstr(js, "[object Error]", 14); 17477 - } 17478 17497 17479 - // refactor 17480 - if (t == T_STR || t == T_NUM || t == T_BOOL) { 17481 - const char *tostr_tag_key = get_toStringTag_sym_key(); 17482 - jsval_t proto = get_prototype_for_type(js, t); 17483 - if (tostr_tag_key && tostr_tag_key[0] && is_object_type(proto)) { 17484 - jsoff_t tag_off = lkp(js, proto, tostr_tag_key, strlen(tostr_tag_key)); 17485 - if (tag_off == 0) tag_off = lkp_proto(js, proto, tostr_tag_key, strlen(tostr_tag_key)); 17486 - if (tag_off != 0) { 17487 - jsval_t tag_val = resolveprop(js, mkval(T_PROP, tag_off)); 17488 - if (vtype(tag_val) == T_STR) { 17489 - jsoff_t tag_len, tag_str_off = vstr(js, tag_val, &tag_len); 17490 - const char *tag_str = (const char *)&js->mem[tag_str_off]; 17491 - char buf[256]; 17492 - int n = snprintf(buf, sizeof(buf), "[object %.*s]", (int)tag_len, tag_str); 17493 - return js_mkstr(js, buf, n); 17494 - } 17495 - } 17498 + if (!tag) { 17499 + if (is_object_type(obj) && get_slot(js, obj, SLOT_ERROR_BRAND) == js_true) { 17500 + tag = "Error"; tag_len = 5; 17501 + } else switch (t) { 17502 + case T_UNDEF: tag = "Undefined"; tag_len = 9; break; 17503 + case T_NULL: tag = "Null"; tag_len = 4; break; 17504 + case T_BOOL: tag = "Boolean"; tag_len = 7; break; 17505 + case T_NUM: tag = "Number"; tag_len = 6; break; 17506 + case T_STR: tag = "String"; tag_len = 6; break; 17507 + case T_ARR: tag = "Array"; tag_len = 5; break; 17508 + case T_FUNC: tag = "Function"; tag_len = 8; break; 17509 + case T_ERR: tag = "Error"; tag_len = 5; break; 17510 + case T_BIGINT: tag = "BigInt"; tag_len = 6; break; 17511 + case T_PROMISE: tag = "Promise"; tag_len = 7; break; 17512 + case T_OBJ: tag = "Object"; tag_len = 6; break; 17513 + default: tag = "Unknown"; tag_len = 7; break; 17496 17514 } 17497 17515 } 17498 - 17499 - const char *type_name = NULL; 17516 + 17517 + char static_buf[64]; 17518 + string_builder_t sb; 17500 17519 17501 - switch (t) { 17502 - case T_UNDEF: type_name = "Undefined"; break; 17503 - case T_NULL: type_name = "Null"; break; 17504 - case T_BOOL: type_name = "Boolean"; break; 17505 - case T_NUM: type_name = "Number"; break; 17506 - case T_STR: type_name = "String"; break; 17507 - case T_ARR: type_name = "Array"; break; 17508 - case T_FUNC: type_name = "Function"; break; 17509 - case T_ERR: type_name = "Error"; break; 17510 - case T_BIGINT: type_name = "BigInt"; break; 17511 - case T_PROMISE: type_name = "Promise"; break; 17512 - case T_OBJ: type_name = "Object"; break; 17513 - default: type_name = "Unknown"; break; 17514 - } 17520 + string_builder_init(&sb, static_buf, sizeof(static_buf)); 17521 + string_builder_append(&sb, "[object ", 8); 17522 + string_builder_append(&sb, tag, tag_len); 17523 + string_builder_append(&sb, "]", 1); 17515 17524 17516 - char buf[256]; 17517 - int n = snprintf(buf, sizeof(buf), "[object %s]", type_name); 17518 - return js_mkstr(js, buf, n); 17525 + return string_builder_finalize(js, &sb); 17519 17526 } 17520 17527 17521 17528 static jsval_t builtin_object_valueOf(struct js *js, jsval_t *args, int nargs) { 17522 - (void)args; (void)nargs; 17523 17529 return js->this_val; 17524 17530 } 17525 17531 17526 17532 static jsval_t builtin_object_toLocaleString(struct js *js, jsval_t *args, int nargs) { 17527 - (void)args; (void)nargs; 17528 17533 return js_call_toString(js, js->this_val); 17529 17534 } 17530 17535 ··· 19202 19207 19203 19208 if (vtype(src) == T_STR) { 19204 19209 array_from_iter_ctx_t ctx = { write_target, result, mapFn, mapThis, 0 }; 19205 - jsoff_t str_len, str_off = vstr(js, src, &str_len); 19206 - const char *str_ptr = (const char *)&js->mem[str_off]; 19207 - for (jsoff_t i = 0; i < str_len; i++) { 19208 - jsval_t unused; 19209 - iter_action_t act = array_from_iter_cb(js, js_mkstr(js, str_ptr + i, 1), &ctx, &unused); 19210 - if (act == ITER_ERROR) return unused; 19211 - } 19212 - if (vtype(result) != T_ARR) js_setprop(js, result, js->length_str, tov((double) str_len)); 19210 + jsval_t r = str_spread_chars(js, src, SPREAD_STR_CB, &ctx, array_from_iter_cb); 19211 + if (is_err(r)) return r; 19212 + if (vtype(result) != T_ARR) js_setprop(js, result, js->length_str, tov((double) ctx.index)); 19213 19213 } else { 19214 19214 const char *iter_key = get_iterator_sym_key(); 19215 19215 jsoff_t iter_prop = iter_key ? lkp_proto(js, src, iter_key, strlen(iter_key)) : 0;