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.

add error handling for missing tokens in loops

+71 -61
+22 -11
examples/demo/welcome.js
··· 10 10 ['Web Locks', 'Navigator.locks API'], 11 11 ['TypeScript', 'Built-in type stripping via oxc'], 12 12 ['Garbage Collection', 'Mark-copy compacting + Boehm-Demers'], 13 - ['', ''], 14 - ['And more...'] 13 + null, 14 + [null, 'And more...'] 15 15 ]; 16 16 17 17 const widths = [0, 0]; 18 - for (const r of rows) { 19 - if (r[0].length > widths[0]) widths[0] = r[0].length; 20 - if (r[1].length > widths[1]) widths[1] = r[1].length; 21 - } 18 + for (const r of rows) 19 + if (r) { 20 + if ((r[0]?.length || 0) > widths[0]) widths[0] = r[0].length; 21 + if ((r[1]?.length || 0) > widths[1]) widths[1] = r[1].length; 22 + } 23 + 24 + const totalWidth = widths[0] + widths[1] + 3; 25 + const border = (l, m, r) => l + 'โ”€'.repeat(widths[0] + 2) + m + 'โ”€'.repeat(widths[1] + 2) + r; 26 + 27 + console.log(border('โ”Œ', 'โ”ฌ', 'โ”')); 28 + let lastRowSpanned = false; 22 29 23 - const border = '+' + '-'.repeat(widths[0] + 2) + '+' + '-'.repeat(widths[1] + 2) + '+'; 24 - console.log(border); 25 30 for (let i = 0; i < rows.length; i++) { 26 31 const r = rows[i]; 27 - console.log('| ' + r[0].padEnd(widths[0], ' ') + ' | ' + r[1].padEnd(widths[1], ' ') + ' |'); 28 - if (i === 0) console.log(border); 32 + lastRowSpanned = !r || !r[0] || !r[1]; 33 + 34 + if (!r) console.log('โ”‚' + ' '.repeat(totalWidth + 2) + 'โ”‚'); 35 + else if (!r[0]) console.log('โ”‚ ' + r[1].padStart(totalWidth) + ' โ”‚'); 36 + else if (!r[1]) console.log('โ”‚ ' + r[0].padEnd(totalWidth) + ' โ”‚'); 37 + else console.log('โ”‚ ' + r[0].padEnd(widths[0]) + ' โ”‚ ' + r[1].padEnd(widths[1]) + ' โ”‚'); 38 + 39 + if (i === 0) console.log(border('โ”œ', 'โ”ผ', 'โ”ค')); 29 40 } 30 - console.log(border); 41 + console.log(lastRowSpanned ? 'โ””' + 'โ”€'.repeat(totalWidth + 2) + 'โ”˜' : border('โ””', 'โ”ด', 'โ”˜'));
+49 -50
src/ant.c
··· 805 805 return mkval(T_OBJ, loadoff(js, (jsoff_t) (vdata(scope) + sizeof(jsoff_t)))); 806 806 } 807 807 808 - #define CHECKV(_v) \ 809 - if (is_err(_v)) { \ 810 - res = (_v); \ 811 - goto done; \ 812 - } 813 - 814 - #define EXPECT(_tok, _e) \ 815 - if (next(js) != _tok) { \ 816 - _e; \ 808 + #define EXPECT(_tok, ...) \ 809 + if (next(js) != _tok) { \ 810 + __VA_ARGS__; \ 817 811 return js_mkerr_typed(js, JS_ERR_SYNTAX, "parse error"); \ 818 812 } else js->consumed = 1 819 813 820 814 #define EXPECT_IDENT(...) \ 821 - if (!is_valid_param_name(next(js))) { \ 822 - __VA_ARGS__; \ 815 + if (!is_valid_param_name(next(js))) { \ 816 + __VA_ARGS__; \ 823 817 return js_mkerr_typed(js, JS_ERR_SYNTAX, "identifier expected"); \ 824 818 } else js->consumed = 1 825 819 ··· 7945 7939 7946 7940 index++; 7947 7941 if (next(js) == TOK_RBRACKET) break; 7948 - EXPECT(TOK_COMMA, ); 7942 + EXPECT(TOK_COMMA); 7949 7943 } 7950 7944 7951 7945 JS_RESTORE_STATE(js, end_state); ··· 8044 8038 8045 8039 next_elem: 8046 8040 if (next(js) == TOK_RBRACKET) break; 8047 - EXPECT(TOK_COMMA, ); 8041 + EXPECT(TOK_COMMA); 8048 8042 } 8049 8043 8050 - EXPECT(TOK_RBRACKET, ); 8044 + EXPECT(TOK_RBRACKET); 8051 8045 if (exe) { 8052 8046 jsval_t len_key = js_mkstr(js, "length", 6); 8053 8047 jsval_t len_val = tov((double)idx); ··· 8202 8196 8203 8197 spread_next: 8204 8198 if (next(js) == TOK_RBRACE) break; 8205 - EXPECT(TOK_COMMA, ); 8199 + EXPECT(TOK_COMMA); 8206 8200 continue; 8207 8201 } 8208 8202 ··· 8389 8383 } 8390 8384 } 8391 8385 } else { 8392 - EXPECT(TOK_COLON, ); 8386 + EXPECT(TOK_COLON); 8393 8387 jsval_t val = js_expr(js); 8394 8388 if (exe) { 8395 8389 if (is_err(val)) return val; ··· 8403 8397 } 8404 8398 8405 8399 if (next(js) == TOK_RBRACE) break; 8406 - EXPECT(TOK_COMMA, ); 8400 + EXPECT(TOK_COMMA); 8407 8401 } 8408 8402 8409 - EXPECT(TOK_RBRACE, ); 8403 + EXPECT(TOK_RBRACE); 8410 8404 return obj; 8411 8405 } 8412 8406 ··· 9987 9981 if (is_err(ix)) return ix; 9988 9982 9989 9983 if (next(js) == TOK_RBRACE) break; 9990 - EXPECT(TOK_COMMA, ); 9984 + EXPECT(TOK_COMMA); 9991 9985 } 9992 9986 js->consumed = 1; 9993 9987 ··· 10023 10017 obj_destruct_next: 10024 10018 10025 10019 if (next(js) == TOK_RBRACE) break; 10026 - EXPECT(TOK_COMMA, ); 10020 + EXPECT(TOK_COMMA); 10027 10021 } 10028 10022 10029 10023 JS_RESTORE_STATE(js, end_state); ··· 10145 10139 10146 10140 index++; 10147 10141 if (next(js) == TOK_RBRACKET) break; 10148 - EXPECT(TOK_COMMA, ); 10142 + EXPECT(TOK_COMMA); 10149 10143 } 10150 10144 10151 10145 JS_RESTORE_STATE(js, end_state); ··· 10187 10181 uint8_t decl_next = next(js); 10188 10182 bool asi = js->had_newline || decl_next == TOK_EOF || decl_next == TOK_RBRACE; 10189 10183 if (decl_next == TOK_SEMICOLON || asi) break; 10190 - EXPECT(TOK_COMMA, ); 10184 + EXPECT(TOK_COMMA); 10191 10185 } 10192 10186 return js_mkundef(); 10193 10187 } ··· 10254 10248 jsoff_t noff = js->toff, nlen = js->tlen; 10255 10249 char *name = (char *) &js->code[noff]; 10256 10250 js->consumed = 1; 10257 - EXPECT(TOK_LPAREN, ); 10251 + EXPECT(TOK_LPAREN); 10258 10252 jsoff_t pos = js->pos - 1; 10259 10253 int param_count = 0; 10260 10254 if (!parse_func_params(js, &saved_flags, &param_count)) { 10261 10255 js->flags = saved_flags; 10262 10256 return js_mkerr_typed(js, JS_ERR_SYNTAX, "invalid parameters"); 10263 10257 } 10264 - EXPECT(TOK_RPAREN, ); 10265 - EXPECT(TOK_LBRACE, ); 10258 + EXPECT(TOK_RPAREN); 10259 + EXPECT(TOK_LBRACE); 10266 10260 js->consumed = 0; 10267 10261 uint8_t flags = js->flags; 10268 10262 js->flags |= F_NOEXEC; ··· 10325 10319 jsoff_t noff = js->toff, nlen = js->tlen; 10326 10320 char *name = (char *) &js->code[noff]; 10327 10321 js->consumed = 1; 10328 - EXPECT(TOK_LPAREN, ); 10322 + EXPECT(TOK_LPAREN); 10329 10323 jsoff_t pos = js->pos - 1; 10330 10324 if (!parse_func_params(js, NULL, NULL)) { 10331 10325 return js_mkerr_typed(js, JS_ERR_SYNTAX, "invalid parameters"); 10332 10326 } 10333 - EXPECT(TOK_RPAREN, ); 10334 - EXPECT(TOK_LBRACE, ); 10327 + EXPECT(TOK_RPAREN); 10328 + EXPECT(TOK_LBRACE); 10335 10329 js->consumed = 0; 10336 10330 uint8_t flags = js->flags; 10337 10331 js->flags |= F_NOEXEC; ··· 10445 10439 10446 10440 static jsval_t js_if(struct js *js) { 10447 10441 js->consumed = 1; 10448 - EXPECT(TOK_LPAREN, ); 10449 - jsval_t res = js_mkundef(), cond = resolveprop(js, js_expr(js)); 10450 - EXPECT(TOK_RPAREN, ); 10442 + EXPECT(TOK_LPAREN); 10443 + 10444 + jsval_t res = js_mkundef(), cond_expr = js_expr(js); 10445 + if (is_err(cond_expr)) return cond_expr; 10446 + jsval_t cond = resolveprop(js, cond_expr); 10447 + if (is_err(cond)) return cond; 10448 + 10449 + EXPECT(TOK_RPAREN); 10451 10450 10452 10451 bool cond_true = js_truthy(js, cond), exe = !(js->flags & F_NOEXEC); 10453 10452 if (!cond_true) js->flags |= F_NOEXEC; ··· 11892 11891 js->consumed = 1; 11893 11892 } 11894 11893 11895 - EXPECT(TOK_LBRACE, ); 11894 + EXPECT(TOK_LBRACE); 11896 11895 jsoff_t constructor_params_start = 0; 11897 11896 jsoff_t constructor_body_start = 0, constructor_body_end = 0; 11898 11897 uint8_t save_flags = js->flags; ··· 12358 12357 12359 12358 uint8_t var_next = next(js); 12360 12359 if (var_next == TOK_SEMICOLON || var_next == TOK_EOF || var_next == TOK_RBRACE || js->had_newline) break; 12361 - EXPECT(TOK_COMMA, ); 12360 + EXPECT(TOK_COMMA); 12362 12361 } 12363 12362 return js_mkundef(); 12364 12363 } ··· 20583 20582 if (next(js) == TOK_LPAREN) { 20584 20583 js->consumed = 1; 20585 20584 jsval_t spec = js_expr(js); 20586 - EXPECT(TOK_RPAREN, ); 20585 + EXPECT(TOK_RPAREN); 20587 20586 20588 20587 if (vtype(spec) != T_STR) { 20589 20588 return js_mkerr(js, "import() requires string"); ··· 20595 20594 20596 20595 if (next(js) == TOK_MUL) { 20597 20596 js->consumed = 1; 20598 - EXPECT(TOK_AS, ); 20599 - EXPECT(TOK_IDENTIFIER, ); 20597 + EXPECT(TOK_AS); 20598 + EXPECT(TOK_IDENTIFIER); 20600 20599 20601 20600 const char *namespace_name = &js->code[js->toff]; 20602 20601 size_t namespace_len = js->tlen; 20603 20602 js->consumed = 1; 20604 20603 20605 - EXPECT(TOK_FROM, ); 20606 - EXPECT(TOK_STRING, ); 20604 + EXPECT(TOK_FROM); 20605 + EXPECT(TOK_STRING); 20607 20606 20608 20607 jsval_t spec = js_str_literal(js); 20609 20608 jsoff_t spec_len; ··· 20643 20642 if (binding_count < 0) return js_mkerr(js, "Failed to parse named imports"); 20644 20643 } else if (next(js) == TOK_MUL) { 20645 20644 js->consumed = 1; 20646 - EXPECT(TOK_AS, ); 20647 - EXPECT(TOK_IDENTIFIER, ); 20645 + EXPECT(TOK_AS); 20646 + EXPECT(TOK_IDENTIFIER); 20648 20647 bindings[binding_count].import_name = NULL; 20649 20648 bindings[binding_count].import_len = 0; 20650 20649 bindings[binding_count].local_name = &js->code[js->toff]; ··· 20656 20655 } 20657 20656 } 20658 20657 20659 - EXPECT(TOK_FROM, ); 20660 - EXPECT(TOK_STRING, ); 20658 + EXPECT(TOK_FROM); 20659 + EXPECT(TOK_STRING); 20661 20660 20662 20661 jsval_t spec = js_str_literal(js); 20663 20662 jsoff_t spec_len; ··· 20703 20702 int binding_count = esm_parse_named_imports(js, bindings, 64); 20704 20703 if (binding_count < 0) return js_mkerr(js, "Failed to parse named imports"); 20705 20704 20706 - EXPECT(TOK_FROM, ); 20707 - EXPECT(TOK_STRING, ); 20705 + EXPECT(TOK_FROM); 20706 + EXPECT(TOK_STRING); 20708 20707 20709 20708 jsval_t spec = js_str_literal(js); 20710 20709 jsoff_t spec_len; ··· 20766 20765 bool is_const = (next(js) == TOK_CONST); 20767 20766 js->consumed = 1; 20768 20767 20769 - EXPECT(TOK_IDENTIFIER, ); 20768 + EXPECT(TOK_IDENTIFIER); 20770 20769 const char *name = &js->code[js->toff]; 20771 20770 size_t name_len = js->tlen; 20772 20771 js->consumed = 1; ··· 20827 20826 20828 20827 if (next(js) == TOK_AS) { 20829 20828 js->consumed = 1; 20830 - EXPECT(TOK_IDENTIFIER, ); 20829 + EXPECT(TOK_IDENTIFIER); 20831 20830 alias_name = &js->code[js->toff]; 20832 20831 alias_len = js->tlen; 20833 20832 js->consumed = 1; 20834 20833 } 20835 20834 20836 - EXPECT(TOK_FROM, ); 20837 - EXPECT(TOK_STRING, ); 20835 + EXPECT(TOK_FROM); 20836 + EXPECT(TOK_STRING); 20838 20837 20839 20838 jsval_t spec = js_str_literal(js); 20840 20839 jsoff_t spec_len; ··· 20899 20898 if (next(js) == TOK_COMMA) js->consumed = 1; 20900 20899 } 20901 20900 20902 - EXPECT(TOK_RBRACE, ); 20901 + EXPECT(TOK_RBRACE); 20903 20902 20904 20903 if (next(js) == TOK_FROM) { 20905 20904 js->consumed = 1; 20906 - EXPECT(TOK_STRING, ); 20905 + EXPECT(TOK_STRING); 20907 20906 jsval_t spec = js_str_literal(js); 20908 20907 jsoff_t spec_len; 20909 20908 char *spec_str = esm_jsval_to_cstr(js, spec, &spec_len);