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 js_decl

+137 -235
+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.0.35') 77 + version_conf.set('ANT_VERSION', '0.1.0.36') 78 78 version_conf.set('ANT_GIT_HASH', git_hash) 79 79 version_conf.set('ANT_BUILD_DATE', build_date) 80 80
+135 -233
src/ant.c
··· 335 335 static bool is_err(jsval_t v) { return vtype(v) == T_ERR; } 336 336 static bool is_unary(uint8_t tok) { return (tok >= TOK_POSTINC && tok <= TOK_UMINUS) || tok == TOK_NOT || tok == TOK_TILDA || tok == TOK_TYPEOF || tok == TOK_VOID; } 337 337 static bool is_assign(uint8_t tok) { return (tok >= TOK_ASSIGN && tok <= TOK_OR_ASSIGN); } 338 + 339 + typedef struct { 340 + const char *code; 341 + jsoff_t clen, pos; 342 + uint8_t tok, consumed; 343 + } js_parse_state_t; 344 + 345 + #define JS_SAVE_STATE(js, state) do { \ 346 + (state).code = (js)->code; \ 347 + (state).clen = (js)->clen; \ 348 + (state).pos = (js)->pos; \ 349 + (state).tok = (js)->tok; \ 350 + (state).consumed = (js)->consumed; \ 351 + } while(0) 352 + 353 + #define JS_RESTORE_STATE(js, state) do { \ 354 + (js)->code = (state).code; \ 355 + (js)->clen = (state).clen; \ 356 + (js)->pos = (state).pos; \ 357 + (js)->tok = (state).tok; \ 358 + (js)->consumed = (state).consumed; \ 359 + } while(0) 338 360 static void saveoff(struct js *js, jsoff_t off, jsoff_t val) { memcpy(&js->mem[off], &val, sizeof(val)); } 339 361 static void saveval(struct js *js, jsoff_t off, jsval_t val) { memcpy(&js->mem[off], &val, sizeof(val)); } 340 362 static jsoff_t loadoff(struct js *js, jsoff_t off) { jsoff_t v = 0; assert(js->brk <= js->size); memcpy(&v, &js->mem[off], sizeof(v)); return v; } ··· 353 375 354 376 static inline jsoff_t esize(jsoff_t w); 355 377 static jsval_t js_expr(struct js *js); 378 + static jsval_t js_eval_slice(struct js *js, jsoff_t off, jsoff_t len); 379 + static jsval_t js_eval_str(struct js *js, const char *code, jsoff_t len); 356 380 static jsval_t js_stmt(struct js *js); 357 381 static jsval_t js_assignment(struct js *js); 358 382 static jsval_t js_arrow_func(struct js *js, jsoff_t params_start, jsoff_t params_end, bool is_async); ··· 3861 3885 if (argi < argc) { 3862 3886 v = args[argi++]; 3863 3887 } else if (default_len > 0) { 3864 - const char *saved_code = js->code; 3865 - jsoff_t saved_clen = js->clen, saved_pos = js->pos; 3866 - js->code = &fn[default_start]; 3867 - js->clen = default_len; 3868 - js->pos = 0; 3869 - js->consumed = 1; 3870 - v = js_expr(js); 3871 - js->code = saved_code; 3872 - js->clen = saved_clen; 3873 - js->pos = saved_pos; 3888 + v = js_eval_str(js, &fn[default_start], default_len); 3874 3889 } else { 3875 3890 v = js_mkundef(); 3876 3891 } ··· 4023 4038 if (arg_idx < nargs) { 4024 4039 v = args[arg_idx]; 4025 4040 } else if (default_len > 0) { 4026 - const char *saved_code = js->code; 4027 - jsoff_t saved_clen = js->clen, saved_pos = js->pos; 4028 - uint8_t saved_consumed = js->consumed; 4029 - js->code = &fn[default_start]; 4030 - js->clen = default_len; 4031 - js->pos = 0; 4032 - js->consumed = 1; 4033 - v = js_expr(js); 4034 - js->code = saved_code; 4035 - js->clen = saved_clen; 4036 - js->pos = saved_pos; 4037 - js->consumed = saved_consumed; 4041 + v = js_eval_str(js, &fn[default_start], default_len); 4038 4042 } else { 4039 4043 v = js_mkundef(); 4040 4044 } ··· 4255 4259 4256 4260 jsval_t field_val = js_mkundef(); 4257 4261 if (init_start > 0 && init_end > init_start) { 4258 - jsoff_t init_len = init_end - init_start; 4259 - const char *init_code = &source[init_start]; 4260 - 4261 - const char *saved_code = js->code; 4262 - jsoff_t saved_clen = js->clen; 4263 - jsoff_t saved_pos = js->pos; 4264 - uint8_t saved_tok = js->tok; 4265 - uint8_t saved_consumed = js->consumed; 4266 - 4267 - js->code = init_code; 4268 - js->clen = init_len; 4269 - js->pos = 0; 4270 - js->consumed = 1; 4271 - 4272 - field_val = js_expr(js); 4262 + field_val = js_eval_str(js, &source[init_start], init_end - init_start); 4273 4263 field_val = resolveprop(js, field_val); 4274 - 4275 - js->code = saved_code; 4276 - js->clen = saved_clen; 4277 - js->pos = saved_pos; 4278 - js->tok = saved_tok; 4279 - js->consumed = saved_consumed; 4280 4264 } 4281 4265 4282 4266 jsval_t set_res = setprop(js, target_this, fname, field_val); ··· 4555 4539 4556 4540 if (brace_count != 0) return js_mkerr_typed(js, JS_ERR_SYNTAX, "unclosed ${"); 4557 4541 4558 - const char *saved_code = js->code; 4559 - jsoff_t saved_clen = js->clen; 4560 - jsoff_t saved_pos = js->pos; 4561 - uint8_t saved_tok = js->tok; 4562 - uint8_t saved_consumed = js->consumed; 4563 - 4564 - js->code = (const char *)&in[expr_start]; 4565 - js->clen = n - expr_start; 4566 - js->pos = 0; 4567 - js->consumed = 1; 4568 - 4569 - jsval_t expr_result = js_expr(js); 4570 - 4571 - js->code = saved_code; 4572 - js->clen = saved_clen; 4573 - js->pos = saved_pos; 4574 - js->tok = saved_tok; 4575 - js->consumed = saved_consumed; 4576 - 4542 + jsval_t expr_result = js_eval_str(js, (const char *)&in[expr_start], n - expr_start); 4577 4543 if (is_err(expr_result)) return expr_result; 4578 4544 expr_result = resolveprop(js, expr_result); 4579 4545 ··· 4617 4583 static jsval_t js_tagged_template(struct js *js, jsval_t tag_func) { 4618 4584 if (js->flags & F_NOEXEC) return js_mkundef(); 4619 4585 4620 - const char *saved_code = js->code; 4621 - jsoff_t saved_clen = js->clen, saved_pos = js->pos; 4622 - uint8_t saved_tok = js->tok; 4586 + js_parse_state_t saved; 4587 + JS_SAVE_STATE(js, saved); 4623 4588 4624 4589 uint8_t *in = (uint8_t *) &js->code[js->toff]; 4625 4590 size_t template_len = js->tlen; ··· 4666 4631 } 4667 4632 if (brace_count != 0) return js_mkerr_typed(js, JS_ERR_SYNTAX, "unclosed ${"); 4668 4633 4669 - const char *saved_code = js->code; 4670 - jsoff_t saved_clen = js->clen, saved_pos = js->pos; 4671 - uint8_t saved_tok = js->tok, saved_consumed = js->consumed; 4672 - 4673 - js->code = (const char *)&in[expr_start]; 4674 - js->clen = n - expr_start; 4675 - js->pos = 0; 4676 - js->consumed = 1; 4677 - 4678 - jsval_t expr_result = resolveprop(js, js_expr(js)); 4679 - 4680 - js->code = saved_code; 4681 - js->clen = saved_clen; 4682 - js->pos = saved_pos; 4683 - js->tok = saved_tok; 4684 - js->consumed = saved_consumed; 4685 - 4634 + jsval_t expr_result = js_eval_str(js, (const char *)&in[expr_start], n - expr_start); 4686 4635 if (is_err(expr_result)) return expr_result; 4636 + expr_result = resolveprop(js, expr_result); 4687 4637 values[value_count++] = expr_result; 4688 4638 n++; 4689 4639 } ··· 4706 4656 uint8_t saved_flags = js->flags; 4707 4657 jsval_t result = call_js_with_args(js, tag_func, args, 1 + value_count); 4708 4658 4709 - js->code = saved_code; 4710 - js->clen = saved_clen; 4711 - js->pos = saved_pos; 4712 - js->tok = saved_tok; 4659 + JS_RESTORE_STATE(js, saved); 4713 4660 js->flags = saved_flags; 4714 4661 js->consumed = 1; 4715 4662 ··· 5767 5714 (void)builtin_promise_then(js, then_args, 2); 5768 5715 js->this_val = saved_this; 5769 5716 5717 + js_parse_state_t saved; 5718 + JS_SAVE_STATE(js, saved); 5770 5719 uint8_t saved_flags = js->flags; 5771 - const char *saved_code = js->code; 5772 - jsoff_t saved_clen = js->clen; 5773 - jsoff_t saved_pos = js->pos; 5774 - uint8_t saved_tok = js->tok; 5775 - uint8_t saved_consumed = js->consumed; 5776 5720 5777 5721 mco_result mco_res = mco_yield(current_mco); 5722 + 5723 + JS_RESTORE_STATE(js, saved); 5778 5724 js->flags = saved_flags; 5779 - js->code = saved_code; 5780 - js->clen = saved_clen; 5781 - js->pos = saved_pos; 5782 - js->tok = saved_tok; 5783 - js->consumed = saved_consumed; 5784 5725 5785 5726 if (mco_res != MCO_SUCCESS) { 5786 5727 return js_mkerr(js, "failed to yield coroutine"); ··· 6065 6006 if (next(js) == TOK_LBRACE) { 6066 6007 js->consumed = 1; 6067 6008 6068 - typedef struct { 6069 - jsoff_t src_off; 6070 - jsoff_t src_len; 6071 - jsoff_t var_off; 6072 - jsoff_t var_len; 6073 - jsoff_t default_off; 6074 - jsoff_t default_len; 6075 - } DestructProp; 6076 - DestructProp props[32]; 6077 - int prop_count = 0; 6009 + js_parse_state_t pattern_state; 6010 + JS_SAVE_STATE(js, pattern_state); 6011 + 6012 + int depth = 1; 6013 + while (depth > 0 && next(js) != TOK_EOF) { 6014 + if (js->tok == TOK_LBRACE) depth++; 6015 + else if (js->tok == TOK_RBRACE) depth--; 6016 + if (depth > 0) js->consumed = 1; 6017 + } 6018 + js->consumed = 1; 6019 + 6020 + if (next(js) != TOK_ASSIGN) { 6021 + return js_mkerr_typed(js, JS_ERR_SYNTAX, "destructuring requires assignment"); 6022 + } 6023 + js->consumed = 1; 6024 + 6025 + jsval_t v = js_expr(js); 6026 + if (is_err(v)) return v; 6027 + 6028 + jsval_t obj = js_mkundef(); 6029 + if (exe) { 6030 + obj = resolveprop(js, v); 6031 + if (vtype(obj) != T_OBJ && vtype(obj) != T_ARR) { 6032 + return js_mkerr(js, "cannot destructure non-object"); 6033 + } 6034 + } 6035 + 6036 + js_parse_state_t end_state; 6037 + JS_SAVE_STATE(js, end_state); 6038 + JS_RESTORE_STATE(js, pattern_state); 6078 6039 6079 - while (next(js) != TOK_RBRACE && next(js) != TOK_EOF && prop_count < 32) { 6040 + while (next(js) != TOK_RBRACE && next(js) != TOK_EOF) { 6080 6041 EXPECT(TOK_IDENTIFIER, ); 6081 - props[prop_count].src_off = js->toff; 6082 - props[prop_count].src_len = js->tlen; 6083 - props[prop_count].var_off = js->toff; 6084 - props[prop_count].var_len = js->tlen; 6085 - props[prop_count].default_off = 0; 6086 - props[prop_count].default_len = 0; 6042 + jsoff_t src_off = js->toff, src_len = js->tlen; 6043 + jsoff_t var_off = src_off, var_len = src_len; 6087 6044 js->consumed = 1; 6088 6045 6089 6046 if (next(js) == TOK_COLON) { 6090 6047 js->consumed = 1; 6091 6048 EXPECT(TOK_IDENTIFIER, ); 6092 - props[prop_count].var_off = js->toff; 6093 - props[prop_count].var_len = js->tlen; 6049 + var_off = js->toff; 6050 + var_len = js->tlen; 6094 6051 js->consumed = 1; 6095 6052 } 6096 6053 6054 + jsoff_t default_off = 0, default_len = 0; 6097 6055 if (next(js) == TOK_ASSIGN) { 6098 6056 js->consumed = 1; 6099 - props[prop_count].default_off = js->pos; 6100 - uint8_t saved_flags = js->flags; 6057 + default_off = js->pos; 6058 + uint8_t sf = js->flags; 6101 6059 js->flags |= F_NOEXEC; 6102 - jsval_t default_expr = js_expr(js); 6103 - js->flags = saved_flags; 6104 - if (is_err(default_expr)) return default_expr; 6105 - props[prop_count].default_len = js->pos - props[prop_count].default_off; 6060 + jsval_t r = js_expr(js); 6061 + js->flags = sf; 6062 + if (is_err(r)) return r; 6063 + default_len = js->pos - default_off; 6106 6064 } 6107 6065 6108 - prop_count++; 6109 - 6110 - if (next(js) == TOK_RBRACE) break; 6111 - EXPECT(TOK_COMMA, ); 6112 - } 6113 - 6114 - EXPECT(TOK_RBRACE, ); 6115 - 6116 - jsval_t v = js_mkundef(); 6117 - if (next(js) == TOK_ASSIGN) { 6118 - js->consumed = 1; 6119 - v = js_expr(js); 6120 - if (is_err(v)) return v; 6121 - } else { 6122 - return js_mkerr_typed(js, JS_ERR_SYNTAX, "destructuring requires assignment"); 6123 - } 6124 - 6125 - if (exe) { 6126 - jsval_t obj = resolveprop(js, v); 6127 - if (vtype(obj) != T_OBJ && vtype(obj) != T_ARR) { 6128 - return js_mkerr(js, "cannot destructure non-object"); 6129 - } 6130 - 6131 - for (int i = 0; i < prop_count; i++) { 6132 - const char *var_name = &js->code[props[i].var_off]; 6133 - jsoff_t var_len = props[i].var_len; 6134 - 6135 - const char *src_name = &js->code[props[i].src_off]; 6136 - jsoff_t src_len = props[i].src_len; 6137 - 6066 + if (exe) { 6067 + const char *var_name = &js->code[var_off]; 6138 6068 if (lkp(js, js->scope, var_name, var_len) > 0) { 6139 - return js_mkerr(js, "'%.*s' already declared", (int) var_len, var_name); 6069 + return js_mkerr(js, "'%.*s' already declared", (int)var_len, var_name); 6140 6070 } 6141 6071 6142 - jsoff_t prop_off = lkp(js, obj, src_name, src_len); 6143 - jsval_t prop_val = js_mkundef(); 6072 + jsoff_t prop_off = lkp(js, obj, &js->code[src_off], src_len); 6073 + jsval_t prop_val = prop_off > 0 ? resolveprop(js, mkval(T_PROP, prop_off)) : js_mkundef(); 6144 6074 6145 - if (prop_off > 0) { 6146 - prop_val = resolveprop(js, mkval(T_PROP, prop_off)); 6147 - } 6148 - 6149 - if (vtype(prop_val) == T_UNDEF && props[i].default_len > 0) { 6150 - const char *saved_code = js->code; 6151 - jsoff_t saved_clen = js->clen, saved_pos = js->pos; 6152 - uint8_t saved_tok = js->tok, saved_consumed = js->consumed; 6153 - 6154 - js->code = &js->code[props[i].default_off - (js->code - saved_code)]; 6155 - js->clen = props[i].default_len; 6156 - js->pos = 0; 6157 - js->consumed = 1; 6158 - 6159 - prop_val = js_expr(js); 6160 - 6161 - js->code = saved_code; 6162 - js->clen = saved_clen; 6163 - js->pos = saved_pos; 6164 - js->tok = saved_tok; 6165 - js->consumed = saved_consumed; 6166 - 6075 + if (vtype(prop_val) == T_UNDEF && default_len > 0) { 6076 + prop_val = js_eval_slice(js, default_off, default_len); 6167 6077 if (is_err(prop_val)) return prop_val; 6168 6078 prop_val = resolveprop(js, prop_val); 6169 6079 } ··· 6171 6081 jsval_t x = mkprop(js, js->scope, js_mkstr(js, var_name, var_len), prop_val, is_const); 6172 6082 if (is_err(x)) return x; 6173 6083 } 6084 + 6085 + if (next(js) == TOK_RBRACE) break; 6086 + EXPECT(TOK_COMMA, ); 6174 6087 } 6088 + 6089 + JS_RESTORE_STATE(js, end_state); 6175 6090 } else { 6176 6091 EXPECT(TOK_IDENTIFIER, ); 6177 6092 js->consumed = 0; ··· 6210 6125 6211 6126 static jsval_t js_expr(struct js *js) { 6212 6127 return js_assignment(js); 6128 + } 6129 + 6130 + static jsval_t js_eval_slice(struct js *js, jsoff_t off, jsoff_t len) { 6131 + js_parse_state_t saved; 6132 + JS_SAVE_STATE(js, saved); 6133 + 6134 + js->code = saved.code + off; 6135 + js->clen = len; 6136 + js->pos = 0; 6137 + js->consumed = 1; 6138 + 6139 + jsval_t result = js_expr(js); 6140 + 6141 + JS_RESTORE_STATE(js, saved); 6142 + return result; 6143 + } 6144 + 6145 + static jsval_t js_eval_str(struct js *js, const char *code, jsoff_t len) { 6146 + js_parse_state_t saved; 6147 + JS_SAVE_STATE(js, saved); 6148 + 6149 + js->code = code; 6150 + js->clen = len; 6151 + js->pos = 0; 6152 + js->consumed = 1; 6153 + 6154 + jsval_t result = js_expr(js); 6155 + 6156 + JS_RESTORE_STATE(js, saved); 6157 + return result; 6213 6158 } 6214 6159 6215 6160 static jsval_t js_let(struct js *js) { ··· 7832 7777 if (methods[i].is_field) { 7833 7778 jsval_t field_val = js_mkundef(); 7834 7779 if (methods[i].field_start > 0 && methods[i].field_end > methods[i].field_start) { 7835 - const char *saved_code = js->code; 7836 - jsoff_t saved_clen = js->clen; 7837 - jsoff_t saved_pos = js->pos; 7838 - uint8_t saved_tok = js->tok; 7839 - uint8_t saved_consumed = js->consumed; 7840 - jsoff_t saved_toff = js->toff; 7841 - jsoff_t saved_tlen = js->tlen; 7842 - 7843 - jsoff_t field_len = methods[i].field_end - methods[i].field_start; 7844 - js->code = &saved_code[methods[i].field_start]; 7845 - js->clen = field_len; 7846 - js->pos = 0; 7847 - js->consumed = 1; 7848 - 7849 - field_val = js_expr(js); 7780 + field_val = js_eval_slice(js, methods[i].field_start, methods[i].field_end - methods[i].field_start); 7850 7781 field_val = resolveprop(js, field_val); 7851 - 7852 - js->code = saved_code; 7853 - js->clen = saved_clen; 7854 - js->pos = saved_pos; 7855 - js->tok = saved_tok; 7856 - js->consumed = saved_consumed; 7857 - js->toff = saved_toff; 7858 - js->tlen = saved_tlen; 7859 7782 } 7860 7783 jsval_t set_res = setprop(js, func_obj, member_name, field_val); 7861 7784 if (is_err(set_res)) return set_res; ··· 8181 8104 jsoff_t code_len, code_off = vstr(js, code_arg, &code_len); 8182 8105 const char *code_str = (const char *)&js->mem[code_off]; 8183 8106 8184 - const char *saved_code = js->code; 8185 - jsoff_t saved_clen = js->clen; 8186 - jsoff_t saved_pos = js->pos; 8187 - uint8_t saved_tok = js->tok; 8188 - uint8_t saved_consumed = js->consumed; 8107 + js_parse_state_t saved; 8108 + JS_SAVE_STATE(js, saved); 8189 8109 uint8_t saved_flags = js->flags; 8190 8110 8191 8111 jsval_t result = js_eval(js, code_str, code_len); 8192 8112 8193 - js->code = saved_code; 8194 - js->clen = saved_clen; 8195 - js->pos = saved_pos; 8196 - js->tok = saved_tok; 8197 - js->consumed = saved_consumed; 8113 + JS_RESTORE_STATE(js, saved); 8198 8114 js->flags = saved_flags; 8199 8115 8200 8116 return result; ··· 13466 13382 } 13467 13383 } 13468 13384 13469 - const char *saved_code = js->code; 13470 - jsoff_t saved_clen = js->clen; 13471 - jsoff_t saved_pos = js->pos; 13385 + js_parse_state_t saved; 13386 + JS_SAVE_STATE(js, saved); 13472 13387 13473 13388 ns = esm_load_module(js, mod); 13474 13389 13475 - js->code = saved_code; 13476 - js->clen = saved_clen; 13477 - js->pos = saved_pos; 13390 + JS_RESTORE_STATE(js, saved); 13478 13391 13479 13392 free(resolved_path); 13480 13393 } ··· 13520 13433 } 13521 13434 } 13522 13435 13523 - const char *saved_code = js->code; 13524 - jsoff_t saved_clen = js->clen; 13525 - jsoff_t saved_pos = js->pos; 13436 + js_parse_state_t saved; 13437 + JS_SAVE_STATE(js, saved); 13526 13438 13527 13439 ns = esm_load_module(js, mod); 13528 13440 13529 - js->code = saved_code; 13530 - js->clen = saved_clen; 13531 - js->pos = saved_pos; 13441 + JS_RESTORE_STATE(js, saved); 13532 13442 13533 13443 free(resolved_path); 13534 13444 } ··· 13610 13520 } 13611 13521 } 13612 13522 13613 - const char *saved_code = js->code; 13614 - jsoff_t saved_clen = js->clen; 13615 - jsoff_t saved_pos = js->pos; 13616 - uint8_t saved_tok = js->tok; 13617 - uint8_t saved_consumed = js->consumed; 13618 - jsoff_t saved_toff = js->toff; 13619 - jsoff_t saved_tlen = js->tlen; 13523 + js_parse_state_t saved; 13524 + JS_SAVE_STATE(js, saved); 13525 + jsoff_t saved_toff = js->toff, saved_tlen = js->tlen; 13620 13526 jsval_t saved_scope = js->scope; 13621 13527 13622 13528 ns = esm_load_module(js, mod); 13623 13529 13624 - js->code = saved_code; 13625 - js->clen = saved_clen; 13626 - js->pos = saved_pos; 13627 - js->tok = saved_tok; 13628 - js->consumed = saved_consumed; 13530 + JS_RESTORE_STATE(js, saved); 13629 13531 js->toff = saved_toff; 13630 13532 js->tlen = saved_tlen; 13631 13533 js->scope = saved_scope;
+1 -1
tests/fetch.cjs
··· 19 19 }); 20 20 21 21 const { json, headers } = response.json(); 22 - console.log(`${json}\n${headers}`); 22 + console.log(`${JSON.stringify(json)}\n${JSON.stringify(headers)}`); 23 23 } 24 24 25 25 void Promise.all([test_get(), test_post(), test_json()]);