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 message capacity management and formatting improvements

+186 -86
+186 -86
src/ant.c
··· 1288 1288 return srclen; 1289 1289 } 1290 1290 1291 - #define REMAIN(n, len) ((n) >= (len) ? 0 : (len) - (n)) 1292 - 1293 1291 static inline size_t uint_to_str(char *buf, size_t bufsize, uint64_t val) { 1294 1292 if (bufsize == 0) return 0; 1295 1293 if (val == 0) { ··· 2446 2444 *line_start_col = (int)(pos - line_start) + 1; 2447 2445 } 2448 2446 2449 - static void format_error_stack(struct js *js, size_t *n, int line, int col, bool include_source_line, const char *error_line, int error_col) { 2447 + static bool ensure_errmsg_capacity(struct js *js, size_t needed) { 2448 + if (js->errmsg_size == 0) js->errmsg_size = 4096; 2449 + 2450 2450 if (!js->errmsg) { 2451 - js->errmsg_size = 4096; 2452 2451 js->errmsg = (char *)malloc(js->errmsg_size); 2453 - if (!js->errmsg) return; 2452 + if (!js->errmsg) return false; 2453 + js->errmsg[0] = '\0'; 2454 + } 2455 + 2456 + if (needed <= js->errmsg_size) return true; 2457 + 2458 + size_t new_size = js->errmsg_size; 2459 + while (new_size < needed) { 2460 + size_t next = new_size * 2; 2461 + if (next < new_size) return false; 2462 + new_size = next; 2454 2463 } 2464 + 2465 + char *next_buf = (char *)realloc(js->errmsg, new_size); 2466 + if (!next_buf) return false; 2467 + js->errmsg = next_buf; 2468 + js->errmsg_size = new_size; 2469 + return true; 2470 + } 2471 + 2472 + __attribute__((format(printf, 3, 4))) 2473 + static size_t append_errmsg_fmt(struct js *js, size_t used, const char *fmt, ...) { 2474 + for (;;) { 2475 + if (!ensure_errmsg_capacity(js, used + 1)) return used; 2476 + 2477 + size_t remaining = js->errmsg_size - used; 2478 + va_list ap; 2479 + va_start(ap, fmt); 2480 + int written = vsnprintf(js->errmsg + used, remaining, fmt, ap); 2481 + va_end(ap); 2482 + 2483 + if (written < 0) return used; 2484 + if ((size_t)written < remaining) return used + (size_t)written; 2485 + 2486 + if (!ensure_errmsg_capacity(js, used + (size_t)written + 1)) { 2487 + return js->errmsg_size ? js->errmsg_size - 1 : used; 2488 + } 2489 + } 2490 + } 2491 + 2492 + #define ERR_FMT "\x1b[31m%.*s\x1b[0m: \x1b[1m%.*s\x1b[0m" 2493 + #define ERR_NAME_ONLY "\x1b[31m%.*s\x1b[0m" 2494 + 2495 + static inline size_t remaining_capacity(size_t used, size_t total) { 2496 + return used >= total ? 0 : total - used; 2497 + } 2498 + 2499 + static size_t append_error_header(struct js *js, size_t used, int line) { 2500 + if (js->filename) return append_errmsg_fmt(js, used, "%s:%d\n", js->filename, line); 2501 + return append_errmsg_fmt(js, used, "<eval>:%d\n", line); 2502 + } 2503 + 2504 + static const char *get_str_prop(struct js *js, jsval_t obj, const char *key, jsoff_t klen, jsoff_t *out_len) { 2505 + jsoff_t off = lkp(js, obj, key, klen); 2506 + if (off <= 0) return NULL; 2507 + jsval_t v = resolveprop(js, mkval(T_PROP, off)); 2508 + if (vtype(v) != T_STR) return NULL; 2509 + return (const char *)&js->mem[vstr(js, v, out_len)]; 2510 + } 2511 + 2512 + static size_t append_error_value(struct js *js, size_t used, jsval_t value) { 2513 + const char *name = "Error"; 2514 + const char *msg = NULL; 2515 + 2516 + jsoff_t name_len = 5; 2517 + jsoff_t msg_len = 0; 2518 + 2519 + static const void *type_dispatch[] = { 2520 + [T_STR] = &&l_type_str, 2521 + [T_OBJ] = &&l_type_obj, 2522 + [T_FUNC] = &&l_type_default, 2523 + [T_ARR] = &&l_type_default, 2524 + [T_PROMISE] = &&l_type_default, 2525 + [T_GENERATOR] = &&l_type_default, 2526 + [T_PROP] = &&l_type_default, 2527 + [T_BIGINT] = &&l_type_default, 2528 + [T_NUM] = &&l_type_default, 2529 + [T_BOOL] = &&l_type_default, 2530 + [T_SYMBOL] = &&l_type_default, 2531 + [T_CFUNC] = &&l_type_default, 2532 + [T_FFI] = &&l_type_default, 2533 + [T_TYPEDARRAY] = &&l_type_default, 2534 + [T_CODEREF] = &&l_type_default, 2535 + [T_PROPREF] = &&l_type_default, 2536 + [T_ERR] = &&l_type_default, 2537 + [T_UNDEF] = &&l_type_default, 2538 + [T_NULL] = &&l_type_default, 2539 + }; 2540 + 2541 + uint8_t t = vtype(value); 2542 + if (t < sizeof(type_dispatch) / sizeof(type_dispatch[0]) && type_dispatch[t]) { 2543 + goto *type_dispatch[t]; 2544 + } 2545 + goto l_type_default; 2546 + 2547 + l_type_str: 2548 + msg = (const char *)&js->mem[vstr(js, value, &msg_len)]; 2549 + goto l_type_done; 2550 + 2551 + l_type_obj: 2552 + name = get_str_prop(js, value, "name", 4, &name_len); 2553 + if (!name) { 2554 + name = "Error"; 2555 + name_len = 5; 2556 + } 2557 + msg = get_str_prop(js, value, "message", 7, &msg_len); 2558 + goto l_type_done; 2559 + 2560 + l_type_default: 2561 + msg = js_str(js, value); 2562 + msg_len = msg ? (jsoff_t)strlen(msg) : 0; 2563 + goto l_type_done; 2564 + 2565 + l_type_done: 2566 + 2567 + static const void *dispatch[] = { &&l_with_msg, &&l_name_only }; 2568 + int key = msg ? 0 : 1; 2569 + goto *dispatch[key]; 2570 + 2571 + l_with_msg: 2572 + return append_errmsg_fmt(js, used, 2573 + ERR_FMT, 2574 + (int)name_len, name, (int)msg_len, msg 2575 + ); 2576 + 2577 + l_name_only: 2578 + return append_errmsg_fmt(js, used, 2579 + ERR_NAME_ONLY, 2580 + (int)name_len, name 2581 + ); 2582 + } 2583 + 2584 + static void append_error_caret(struct js *js, size_t *n, int error_col) { 2585 + if (!ensure_errmsg_capacity(js, *n + (size_t)error_col + 2)) return; 2586 + if (*n >= js->errmsg_size - 1) return; 2587 + 2588 + size_t remaining = js->errmsg_size - *n; 2589 + for (int i = 1; i < error_col && remaining > 1; i++) { 2590 + js->errmsg[(*n)++] = ' '; 2591 + remaining--; 2592 + } 2593 + if (remaining > 1) { 2594 + js->errmsg[(*n)++] = '^'; 2595 + } 2596 + js->errmsg[*n] = '\0'; 2597 + } 2598 + 2599 + static void format_error_stack(struct js *js, size_t *n, int line, int col, bool include_source_line, const char *error_line, int error_col) { 2600 + if (!ensure_errmsg_capacity(js, *n + 1)) return; 2455 2601 2456 2602 const char *dim = "\x1b[90m"; 2457 2603 const char *reset = "\x1b[0m"; 2458 - size_t remaining; 2459 2604 2460 2605 if (include_source_line && error_line && *n < js->errmsg_size) { 2461 - remaining = js->errmsg_size - *n; 2462 - *n += (size_t) snprintf(js->errmsg + *n, remaining, "\n%s\n", error_line); 2463 - 2464 - if (*n < js->errmsg_size - 1) { 2465 - remaining = js->errmsg_size - *n; 2466 - for (int i = 1; i < error_col && remaining > 1; i++) { 2467 - js->errmsg[(*n)++] = ' '; 2468 - remaining--; 2469 - } 2470 - if (remaining > 1) { 2471 - js->errmsg[(*n)++] = '^'; 2472 - } 2473 - js->errmsg[*n] = '\0'; 2474 - } 2606 + *n = append_errmsg_fmt(js, *n, "\n%s\n", error_line); 2607 + append_error_caret(js, n, error_col); 2475 2608 } 2476 2609 2477 - remaining = js->errmsg_size - *n; 2610 + size_t remaining = remaining_capacity(*n, js->errmsg_size); 2478 2611 if (remaining > 20) { 2479 2612 const char *file = js->filename ? js->filename : "<eval>"; 2480 2613 ··· 2489 2622 int fline = frame->line > 0 ? frame->line : 1; 2490 2623 int fcol = frame->col > 0 ? frame->col : 1; 2491 2624 2492 - *n += (size_t) snprintf(js->errmsg + *n, remaining, "\n at %s %s(%s:%d:%d)%s", fname, dim, ffile, fline, fcol, reset); 2493 - remaining = js->errmsg_size - *n; 2625 + *n = append_errmsg_fmt(js, *n, 2626 + "\n at %s %s(%s:%d:%d)%s", 2627 + fname, dim, ffile, fline, fcol, reset 2628 + ); 2629 + remaining = remaining_capacity(*n, js->errmsg_size); 2494 2630 } 2495 2631 2496 2632 if (global_call_stack.depth > 0 && remaining > 60) { 2497 - *n += (size_t) snprintf(js->errmsg + *n, remaining, "\n at Object.<anonymous> %s(%s:1:1)%s", dim, file, reset); 2498 - remaining = js->errmsg_size - *n; 2633 + *n = append_errmsg_fmt(js, *n, 2634 + "\n at Object.<anonymous> %s(%s:1:1)%s", 2635 + dim, file, reset 2636 + ); 2637 + remaining = remaining_capacity(*n, js->errmsg_size); 2499 2638 } 2500 2639 2501 2640 if (global_call_stack.depth == 0 && remaining > 20) { 2502 - *n += (size_t) snprintf(js->errmsg + *n, remaining, "\n at %s%s:%d:%d%s", dim, file, line, col, reset); 2503 - remaining = js->errmsg_size - *n; 2641 + *n = append_errmsg_fmt(js, *n, 2642 + "\n at %s%s:%d:%d%s", 2643 + dim, file, line, col, reset 2644 + ); 2645 + remaining = remaining_capacity(*n, js->errmsg_size); 2504 2646 } 2505 2647 2506 2648 if (remaining > 60 && js->filename && strcmp(js->filename, "[eval]") != 0) { 2507 - *n += (size_t) snprintf(js->errmsg + *n, remaining, "\n at Module.executeUserEntryPoint [as runMain] %s(ant:internal/modules/run_main:149:5)%s", dim, reset); 2508 - remaining = js->errmsg_size - *n; 2649 + *n = append_errmsg_fmt(js, *n, 2650 + "\n at Module.executeUserEntryPoint [as runMain] %s(ant:internal/modules/run_main:149:5)%s", 2651 + dim, reset 2652 + ); 2653 + remaining = remaining_capacity(*n, js->errmsg_size); 2509 2654 } 2510 2655 2511 2656 if (remaining > 40 && js->filename && strcmp(js->filename, "[eval]") != 0) { 2512 - *n += (size_t) snprintf(js->errmsg + *n, remaining, "\n at %sant:internal/call:21728:23%s", dim, reset); 2657 + *n = append_errmsg_fmt(js, *n, 2658 + "\n at %sant:internal/call:21728:23%s", 2659 + dim, reset 2660 + ); 2513 2661 } 2514 2662 } 2515 2663 ··· 2579 2727 js->thrown_value = err_obj; 2580 2728 2581 2729 size_t n = 0; 2582 - if (js->filename) { 2583 - n = (size_t) snprintf(js->errmsg, js->errmsg_size, "%s:%d\n", js->filename, line); 2584 - } else { 2585 - n = (size_t) snprintf(js->errmsg, js->errmsg_size, "<eval>:%d\n", line); 2586 - } 2730 + n = append_error_header(js, 0, line); 2587 2731 2588 - size_t remaining = js->errmsg_size - n; 2589 - if (remaining > 1) { 2590 - n += (size_t) snprintf(js->errmsg + n, remaining, "\x1b[31m%s\x1b[0m: \x1b[1m%s\x1b[0m", err_name, error_msg); 2591 - } 2732 + if (n < js->errmsg_size - 1) n = append_errmsg_fmt( 2733 + js, n, 2734 + "\x1b[31m%s\x1b[0m: \x1b[1m%s\x1b[0m", 2735 + err_name, error_msg 2736 + ); 2592 2737 2593 2738 if (!no_stack) { 2594 2739 format_error_stack(js, &n, line, col, true, error_line, error_col); ··· 2613 2758 } 2614 2759 2615 2760 size_t n = 0; 2616 - if (js->filename) { 2617 - n = (size_t) snprintf(js->errmsg, js->errmsg_size, "%s:%d\n", js->filename, line); 2618 - } else { 2619 - n = (size_t) snprintf(js->errmsg, js->errmsg_size, "<eval>:%d\n", line); 2620 - } 2621 2761 2622 - size_t remaining = js->errmsg_size - n; 2623 - if (vtype(value) == T_STR) { 2624 - jsoff_t slen, off = vstr(js, value, &slen); 2625 - n += (size_t) snprintf(js->errmsg + n, remaining, "\x1b[31mError\x1b[0m: \x1b[1m%.*s\x1b[0m", (int)slen, (char *)&js->mem[off]); 2626 - } else if (vtype(value) == T_OBJ) { 2627 - jsoff_t name_off = lkp(js, value, "name", 4); 2628 - jsoff_t msg_off = lkp(js, value, "message", 7); 2629 - 2630 - const char *name_str = NULL; 2631 - const char *msg_str = NULL; 2632 - jsoff_t name_len = 0, msg_len = 0; 2633 - 2634 - if (name_off > 0) { 2635 - jsval_t name_val = resolveprop(js, mkval(T_PROP, name_off)); 2636 - if (vtype(name_val) == T_STR) { 2637 - jsoff_t off = vstr(js, name_val, &name_len); 2638 - name_str = (const char *)&js->mem[off]; 2639 - } 2640 - } 2641 - 2642 - if (msg_off > 0) { 2643 - jsval_t msg_val = resolveprop(js, mkval(T_PROP, msg_off)); 2644 - if (vtype(msg_val) == T_STR) { 2645 - jsoff_t off = vstr(js, msg_val, &msg_len); 2646 - msg_str = (const char *)&js->mem[off]; 2647 - } 2648 - } 2649 - 2650 - if (name_str && msg_str) { 2651 - n += (size_t) snprintf(js->errmsg + n, remaining, "\x1b[31m%.*s\x1b[0m: \x1b[1m%.*s\x1b[0m", (int)name_len, name_str, (int)msg_len, msg_str); 2652 - } else if (name_str) { 2653 - n += (size_t) snprintf(js->errmsg + n, remaining, "\x1b[31m%.*s\x1b[0m", (int)name_len, name_str); 2654 - } else if (msg_str) { 2655 - n += (size_t) snprintf(js->errmsg + n, remaining, "\x1b[31mError\x1b[0m: \x1b[1m%.*s\x1b[0m", (int)msg_len, msg_str); 2656 - } else { 2657 - const char *str = js_str(js, value); 2658 - n += (size_t) snprintf(js->errmsg + n, remaining, "\x1b[31mError\x1b[0m: \x1b[1m%s\x1b[0m", str); 2659 - } 2660 - } else { 2661 - const char *str = js_str(js, value); 2662 - n += (size_t) snprintf(js->errmsg + n, remaining, "\x1b[31mError\x1b[0m: \x1b[1m%s\x1b[0m", str); 2663 - } 2762 + n = append_error_header(js, 0, line); 2763 + n = append_error_value(js, n, value); 2664 2764 2665 2765 format_error_stack(js, &n, line, col, true, error_line, error_col); 2666 2766