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.

symbol.iterator support

+161 -102
+1 -1
meson.build
··· 74 74 build_date = run_command('date', '+%Y-%m-%d', check: true).stdout().strip() 75 75 76 76 version_conf = configuration_data() 77 - version_conf.set('ANT_VERSION', '0.1.1.17') 77 + version_conf.set('ANT_VERSION', '0.1.1.18') 78 78 version_conf.set('ANT_GIT_HASH', git_hash) 79 79 version_conf.set('ANT_BUILD_DATE', build_date) 80 80
+160 -101
src/ant.c
··· 24 24 #include "modules/fs.h" 25 25 #include "modules/timer.h" 26 26 #include "modules/fetch.h" 27 + #include "modules/symbol.h" 27 28 28 29 #define MINICORO_IMPL 29 30 #include "minicoro.h" ··· 5121 5122 jsval_t resolved_key = resolveprop(js, key_expr); 5122 5123 if (vtype(resolved_key) == T_STR) { 5123 5124 key = resolved_key; 5125 + } else if (vtype(resolved_key) == T_OBJ && is_symbol(js, resolved_key)) { 5126 + char buf[64]; 5127 + jsoff_t sym_id_off = lkp(js, resolved_key, "__sym_id", 8); 5128 + if (sym_id_off) { 5129 + jsval_t sym_id = loadval(js, sym_id_off + sizeof(jsoff_t) * 2); 5130 + snprintf(buf, sizeof(buf), "__sym_%.0f__", tod(sym_id)); 5131 + } else { 5132 + snprintf(buf, sizeof(buf), "__sym_0__"); 5133 + } 5134 + key = js_mkstr(js, buf, strlen(buf)); 5124 5135 } else { 5125 5136 char buf[64]; 5126 5137 size_t n = tostr(js, resolved_key, buf, sizeof(buf)); ··· 6905 6916 return r; 6906 6917 } 6907 6918 6919 + typedef struct { 6920 + jsoff_t body_start; 6921 + jsoff_t body_end; 6922 + jsoff_t var_name_off; 6923 + jsoff_t var_name_len; 6924 + bool is_const_var; 6925 + uint8_t flags; 6926 + } for_of_ctx_t; 6927 + 6928 + static jsval_t for_of_bind_var(struct js *js, for_of_ctx_t *ctx, jsval_t value) { 6929 + const char *var_name = &js->code[ctx->var_name_off]; 6930 + jsoff_t existing = lkp(js, js->scope, var_name, ctx->var_name_len); 6931 + if (existing > 0) { 6932 + saveval(js, existing + sizeof(jsoff_t) * 2, value); 6933 + return js_mkundef(); 6934 + } 6935 + return mkprop(js, js->scope, js_mkstr(js, var_name, ctx->var_name_len), value, ctx->is_const_var); 6936 + } 6937 + 6938 + static jsval_t for_of_exec_body(struct js *js, for_of_ctx_t *ctx) { 6939 + js->pos = ctx->body_start; 6940 + js->consumed = 1; 6941 + js->flags = (ctx->flags & ~F_NOEXEC) | F_LOOP; 6942 + return js_block_or_stmt(js); 6943 + } 6944 + 6945 + static jsval_t for_of_iter_array(struct js *js, for_of_ctx_t *ctx, jsval_t iterable) { 6946 + jsoff_t next_prop = loadoff(js, (jsoff_t) vdata(iterable)) & ~(3U | CONSTMASK); 6947 + jsoff_t length = 0, scan = next_prop; 6948 + 6949 + while (scan < js->brk && scan != 0) { 6950 + jsoff_t koff = loadoff(js, scan + (jsoff_t) sizeof(scan)); 6951 + jsoff_t klen = offtolen(loadoff(js, koff)); 6952 + const char *key = (char *) &js->mem[koff + sizeof(koff)]; 6953 + if (streq(key, klen, "length", 6)) { 6954 + jsval_t val = loadval(js, scan + (jsoff_t) (sizeof(scan) + sizeof(koff))); 6955 + if (vtype(val) == T_NUM) length = (jsoff_t) tod(val); 6956 + break; 6957 + } 6958 + scan = loadoff(js, scan) & ~(3U | CONSTMASK); 6959 + } 6960 + 6961 + for (jsoff_t i = 0; i < length; i++) { 6962 + char idx[16]; 6963 + snprintf(idx, sizeof(idx), "%u", (unsigned) i); 6964 + jsoff_t idxlen = (jsoff_t) strlen(idx); 6965 + jsoff_t prop = next_prop; 6966 + jsval_t val = js_mkundef(); 6967 + 6968 + while (prop < js->brk && prop != 0) { 6969 + jsoff_t koff = loadoff(js, prop + (jsoff_t) sizeof(prop)); 6970 + jsoff_t klen = offtolen(loadoff(js, koff)); 6971 + const char *key = (char *) &js->mem[koff + sizeof(koff)]; 6972 + if (streq(key, klen, idx, idxlen)) { 6973 + val = loadval(js, prop + (jsoff_t) (sizeof(prop) + sizeof(koff))); 6974 + break; 6975 + } 6976 + prop = loadoff(js, prop) & ~(3U | CONSTMASK); 6977 + } 6978 + 6979 + jsval_t err = for_of_bind_var(js, ctx, val); 6980 + if (is_err(err)) return err; 6981 + 6982 + jsval_t v = for_of_exec_body(js, ctx); 6983 + if (is_err(v)) return v; 6984 + if (js->flags & F_BREAK) break; 6985 + if (js->flags & F_RETURN) return v; 6986 + } 6987 + return js_mkundef(); 6988 + } 6989 + 6990 + static jsval_t for_of_iter_string(struct js *js, for_of_ctx_t *ctx, jsval_t iterable) { 6991 + jsoff_t slen, soff = vstr(js, iterable, &slen); 6992 + const char *str = (char *) &js->mem[soff]; 6993 + 6994 + for (jsoff_t i = 0; i < slen; i++) { 6995 + jsval_t char_str = js_mkstr(js, &str[i], 1); 6996 + 6997 + jsval_t err = for_of_bind_var(js, ctx, char_str); 6998 + if (is_err(err)) return err; 6999 + 7000 + jsval_t v = for_of_exec_body(js, ctx); 7001 + if (is_err(v)) return v; 7002 + if (js->flags & F_BREAK) break; 7003 + if (js->flags & F_RETURN) return v; 7004 + } 7005 + return js_mkundef(); 7006 + } 7007 + 7008 + static jsval_t for_of_iter_object(struct js *js, for_of_ctx_t *ctx, jsval_t iterable) { 7009 + const char *iter_key = get_iterator_sym_key(); 7010 + jsoff_t iter_prop = iter_key ? lkp_proto(js, iterable, iter_key, strlen(iter_key)) : 0; 7011 + if (iter_prop == 0) return js_mkerr(js, "for-of requires iterable"); 7012 + 7013 + js_parse_state_t saved_state; 7014 + JS_SAVE_STATE(js, saved_state); 7015 + uint8_t saved_flags = js->flags; 7016 + 7017 + jsval_t iter_method = loadval(js, iter_prop + sizeof(jsoff_t) * 2); 7018 + push_this(iterable); 7019 + jsval_t iterator = call_js_with_args(js, iter_method, NULL, 0); 7020 + pop_this(); 7021 + JS_RESTORE_STATE(js, saved_state); 7022 + js->flags = saved_flags; 7023 + 7024 + if (is_err(iterator)) return iterator; 7025 + 7026 + while (true) { 7027 + jsoff_t next_off = lkp_proto(js, iterator, "next", 4); 7028 + if (next_off == 0) return js_mkerr(js, "iterator.next is not a function"); 7029 + 7030 + jsval_t next_method = loadval(js, next_off + sizeof(jsoff_t) * 2); 7031 + if (vtype(next_method) != T_FUNC && vtype(next_method) != T_CFUNC) 7032 + return js_mkerr(js, "iterator.next is not a function"); 7033 + 7034 + push_this(iterator); 7035 + jsval_t result = call_js_with_args(js, next_method, NULL, 0); 7036 + pop_this(); 7037 + JS_RESTORE_STATE(js, saved_state); 7038 + js->flags = saved_flags; 7039 + 7040 + if (is_err(result)) return result; 7041 + 7042 + jsoff_t done_off = lkp(js, result, "done", 4); 7043 + jsval_t done_val = done_off ? loadval(js, done_off + sizeof(jsoff_t) * 2) : js_mkundef(); 7044 + if (js_truthy(js, done_val)) break; 7045 + 7046 + jsoff_t value_off = lkp(js, result, "value", 5); 7047 + jsval_t value = value_off ? loadval(js, value_off + sizeof(jsoff_t) * 2) : js_mkundef(); 7048 + 7049 + jsval_t err = for_of_bind_var(js, ctx, value); 7050 + if (is_err(err)) return err; 7051 + 7052 + jsval_t v = for_of_exec_body(js, ctx); 7053 + if (is_err(v)) return v; 7054 + if (js->flags & F_BREAK) break; 7055 + if (js->flags & F_RETURN) return v; 7056 + } 7057 + return js_mkundef(); 7058 + } 7059 + 6908 7060 static jsval_t js_for(struct js *js) { 6909 7061 uint8_t flags = js->flags, exe = !(flags & F_NOEXEC); 6910 7062 jsval_t v, res = js_mkundef(); ··· 7092 7244 if (exe) { 7093 7245 jsval_t iterable = resolveprop(js, iter_expr); 7094 7246 uint8_t itype = vtype(iterable); 7247 + for_of_ctx_t ctx = { body_start, body_end, var_name_off, var_name_len, is_const_var, flags }; 7095 7248 7096 - if (itype == T_ARR) { 7097 - jsoff_t next_prop = loadoff(js, (jsoff_t) vdata(iterable)) & ~(3U | CONSTMASK); 7098 - jsoff_t length = 0; 7099 - jsoff_t scan = next_prop; 7100 - 7101 - while (scan < js->brk && scan != 0) { 7102 - jsoff_t koff = loadoff(js, scan + (jsoff_t) sizeof(scan)); 7103 - jsoff_t klen = offtolen(loadoff(js, koff)); 7104 - const char *key = (char *) &js->mem[koff + sizeof(koff)]; 7105 - 7106 - if (streq(key, klen, "length", 6)) { 7107 - jsval_t val = loadval(js, scan + (jsoff_t) (sizeof(scan) + sizeof(koff))); 7108 - if (vtype(val) == T_NUM) length = (jsoff_t) tod(val); 7109 - break; 7110 - } 7111 - scan = loadoff(js, scan) & ~(3U | CONSTMASK); 7112 - } 7113 - 7114 - for (jsoff_t i = 0; i < length; i++) { 7115 - char idx[16]; 7116 - snprintf(idx, sizeof(idx), "%u", (unsigned) i); 7117 - jsoff_t idxlen = (jsoff_t) strlen(idx); 7118 - jsoff_t prop = next_prop; 7119 - jsval_t val = js_mkundef(); 7120 - 7121 - while (prop < js->brk && prop != 0) { 7122 - jsoff_t koff = loadoff(js, prop + (jsoff_t) sizeof(prop)); 7123 - jsoff_t klen = offtolen(loadoff(js, koff)); 7124 - const char *key = (char *) &js->mem[koff + sizeof(koff)]; 7125 - if (streq(key, klen, idx, idxlen)) { 7126 - val = loadval(js, prop + (jsoff_t) (sizeof(prop) + sizeof(koff))); 7127 - break; 7128 - } 7129 - prop = loadoff(js, prop) & ~(3U | CONSTMASK); 7130 - } 7131 - 7132 - const char *var_name = &js->code[var_name_off]; 7133 - jsoff_t existing = lkp(js, js->scope, var_name, var_name_len); 7134 - if (existing > 0) { 7135 - saveval(js, existing + sizeof(jsoff_t) * 2, val); 7136 - } else { 7137 - jsval_t x = mkprop(js, js->scope, js_mkstr(js, var_name, var_name_len), val, is_const_var); 7138 - if (is_err(x)) { 7139 - res = x; 7140 - goto done; 7141 - } 7142 - } 7143 - 7144 - js->pos = body_start; 7145 - js->consumed = 1; 7146 - js->flags = (flags & ~F_NOEXEC) | F_LOOP; 7147 - v = js_block_or_stmt(js); 7148 - if (is_err(v)) { 7149 - res = v; 7150 - goto done; 7151 - } 7152 - 7153 - if (js->flags & F_BREAK) break; 7154 - if (js->flags & F_RETURN) { 7155 - res = v; 7156 - goto done; 7157 - } 7158 - } 7159 - } else if (itype == T_STR) { 7160 - jsoff_t slen, soff = vstr(js, iterable, &slen); 7161 - const char *str = (char *) &js->mem[soff]; 7162 - 7163 - for (jsoff_t i = 0; i < slen; i++) { 7164 - jsval_t char_str = js_mkstr(js, &str[i], 1); 7165 - 7166 - const char *var_name = &js->code[var_name_off]; 7167 - jsoff_t existing = lkp(js, js->scope, var_name, var_name_len); 7168 - if (existing > 0) { 7169 - saveval(js, existing + sizeof(jsoff_t) * 2, char_str); 7170 - } else { 7171 - jsval_t x = mkprop(js, js->scope, js_mkstr(js, var_name, var_name_len), char_str, is_const_var); 7172 - if (is_err(x)) { 7173 - res = x; 7174 - goto done; 7175 - } 7176 - } 7177 - 7178 - js->pos = body_start; 7179 - js->consumed = 1; 7180 - js->flags = (flags & ~F_NOEXEC) | F_LOOP; 7181 - v = js_block_or_stmt(js); 7182 - if (is_err(v)) { 7183 - res = v; 7184 - goto done; 7185 - } 7186 - 7187 - if (js->flags & F_BREAK) break; 7188 - if (js->flags & F_RETURN) { 7189 - res = v; 7190 - goto done; 7191 - } 7192 - } 7193 - } else { 7194 - res = js_mkerr(js, "for-of requires iterable"); 7195 - goto done; 7196 - } 7249 + if (itype == T_ARR) res = for_of_iter_array(js, &ctx, iterable); 7250 + else if (itype == T_STR) res = for_of_iter_string(js, &ctx, iterable); 7251 + else if (itype == T_OBJ) res = for_of_iter_object(js, &ctx, iterable); 7252 + else res = js_mkerr(js, "for-of requires iterable"); 7253 + 7254 + if (is_err(res)) goto done; 7255 + if (js->flags & F_RETURN) goto done; 7197 7256 } 7198 7257 7199 7258 js->pos = body_end;