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.

refactor Array.from to support iterable objects and mapping functions via iterator protocol

+59 -29
+50 -29
src/ant.c
··· 18181 18181 return mkval(T_BOOL, vtype(args[0]) == T_ARR ? 1 : 0); 18182 18182 } 18183 18183 18184 + typedef struct { 18185 + jsval_t write_target; 18186 + jsval_t result; 18187 + jsval_t mapFn; 18188 + jsoff_t index; 18189 + } array_from_iter_ctx_t; 18190 + 18191 + static iter_action_t array_from_iter_cb(struct js *js, jsval_t value, void *ctx, jsval_t *out) { 18192 + array_from_iter_ctx_t *fctx = (array_from_iter_ctx_t *)ctx; 18193 + jsval_t elem = value; 18194 + 18195 + if (is_callable(fctx->mapFn)) { 18196 + jsval_t call_args[2] = { elem, tov((double)fctx->index) }; 18197 + elem = call_js_with_args(js, fctx->mapFn, call_args, 2); 18198 + if (is_err(elem)) { *out = elem; return ITER_ERROR; } 18199 + } 18200 + 18201 + if (vtype(fctx->write_target) == T_ARR) arr_set(js, fctx->write_target, fctx->index, elem); 18202 + else { 18203 + char idxstr[16]; size_t idxlen = uint_to_str(idxstr, sizeof(idxstr), (unsigned)fctx->index); 18204 + js_setprop(js, fctx->write_target, js_mkstr(js, idxstr, idxlen), elem); 18205 + } 18206 + 18207 + fctx->index++; 18208 + return ITER_CONTINUE; 18209 + } 18210 + 18184 18211 static jsval_t builtin_Array_from(struct js *js, jsval_t *args, int nargs) { 18185 18212 if (nargs == 0) return mkarr(js); 18186 18213 18187 18214 jsval_t src = args[0]; 18188 - jsval_t mapFn = (nargs >= 2 && vtype(args[1]) == T_FUNC) ? args[1] : js_mkundef(); 18215 + jsval_t mapFn = (nargs >= 2 && is_callable(args[1])) ? args[1] : js_mkundef(); 18189 18216 18190 18217 jsval_t ctor = js->this_val; 18191 18218 bool use_ctor = (vtype(ctor) == T_FUNC || vtype(ctor) == T_CFUNC); ··· 18204 18231 jsval_t write_target = result_is_proxy ? proxy_read_target(js, result) : result; 18205 18232 18206 18233 if (vtype(src) == T_STR) { 18234 + array_from_iter_ctx_t ctx = { write_target, result, mapFn, 0 }; 18207 18235 jsoff_t str_len, str_off = vstr(js, src, &str_len); 18208 18236 const char *str_ptr = (const char *)&js->mem[str_off]; 18209 18237 for (jsoff_t i = 0; i < str_len; i++) { 18210 - jsval_t elem = js_mkstr(js, str_ptr + i, 1); 18211 - if (vtype(mapFn) == T_FUNC) { 18212 - jsval_t call_args[2] = { elem, tov((double)i) }; 18213 - elem = call_js_with_args(js, mapFn, call_args, 2); 18214 - if (is_err(elem)) return elem; 18215 - } 18216 - if (vtype(write_target) == T_ARR) arr_set(js, write_target, i, elem); 18217 - else { 18218 - char idxstr[16]; size_t idxlen = uint_to_str(idxstr, sizeof(idxstr), (unsigned)i); 18219 - js_setprop(js, write_target, js_mkstr(js, idxstr, idxlen), elem); 18220 - } 18238 + jsval_t unused; 18239 + iter_action_t act = array_from_iter_cb(js, js_mkstr(js, str_ptr + i, 1), &ctx, &unused); 18240 + if (act == ITER_ERROR) return unused; 18221 18241 } 18222 18242 if (vtype(result) != T_ARR) js_setprop(js, result, js->length_str, tov((double) str_len)); 18223 - } else if (vtype(src) == T_ARR || vtype(src) == T_OBJ) { 18224 - jsoff_t len = get_array_length(js, src); 18225 - for (jsoff_t i = 0; i < len; i++) { 18226 - jsval_t elem = arr_get(js, src, i); 18227 - if (vtype(mapFn) == T_FUNC) { 18228 - jsval_t call_args[2] = { elem, tov((double)i) }; 18229 - elem = call_js_with_args(js, mapFn, call_args, 2); 18230 - if (is_err(elem)) return elem; 18231 - } 18232 - if (vtype(write_target) == T_ARR) arr_set(js, write_target, i, elem); 18233 - else { 18234 - char idxstr[16]; size_t idxlen = uint_to_str(idxstr, sizeof(idxstr), (unsigned)i); 18235 - js_setprop(js, write_target, js_mkstr(js, idxstr, idxlen), elem); 18243 + } else { 18244 + const char *iter_key = get_iterator_sym_key(); 18245 + jsoff_t iter_prop = iter_key ? lkp_proto(js, src, iter_key, strlen(iter_key)) : 0; 18246 + 18247 + if (iter_prop != 0) { 18248 + array_from_iter_ctx_t ctx = { write_target, result, mapFn, 0 }; 18249 + jsval_t iter_result = iter_foreach(js, src, array_from_iter_cb, &ctx); 18250 + if (is_err(iter_result)) return iter_result; 18251 + if (vtype(result) != T_ARR) js_setprop(js, result, js->length_str, tov((double) ctx.index)); 18252 + } else if (vtype(src) == T_ARR || vtype(src) == T_OBJ) { 18253 + array_from_iter_ctx_t ctx = { write_target, result, mapFn, 0 }; 18254 + jsoff_t len = get_array_length(js, src); 18255 + for (jsoff_t i = 0; i < len; i++) { 18256 + jsval_t unused; 18257 + iter_action_t act = array_from_iter_cb(js, arr_get(js, src, i), &ctx, &unused); 18258 + if (act == ITER_ERROR) return unused; 18236 18259 } 18260 + if (vtype(result) != T_ARR) js_setprop(js, result, js->length_str, tov((double) len)); 18237 18261 } 18238 - if (vtype(result) != T_ARR) js_setprop(js, result, js->length_str, tov((double) len)); 18239 18262 } 18240 18263 18241 18264 if (!use_ctor) return mkval(T_ARR, vdata(result)); ··· 18604 18627 if (search_len == 0) return mkval(T_BOOL, 1); 18605 18628 if (start + search_len > str_len) return mkval(T_BOOL, 0); 18606 18629 for (jsoff_t i = start; i <= str_len - search_len; i++) { 18607 - if (memcmp(str_ptr + i, search_ptr, search_len) == 0) { 18608 - return mkval(T_BOOL, 1); 18609 - } 18630 + if (memcmp(str_ptr + i, search_ptr, search_len) == 0) return mkval(T_BOOL, 1); 18610 18631 } 18611 18632 18612 18633 return mkval(T_BOOL, 0);
+9
tests/test_array_from.js
··· 1 + const myArray = ['a', 1, 'a', 2, '1']; 2 + const unique = Array.from(new Set(myArray)); 3 + console.log('Set:', unique); 4 + 5 + const doubled = Array.from(new Set([1, 2, 3]), x => x * 2); 6 + console.log('Set+map:', doubled); 7 + 8 + console.log('Array:', Array.from([10, 20, 30])); 9 + console.log('String:', Array.from("abc"));