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.

at mir/inline-method 1073 lines 39 kB view raw
1#include <compat.h> // IWYU pragma: keep 2 3#include <stdio.h> 4#include <stdlib.h> 5#include <string.h> 6#include <stdbool.h> 7#include <ctype.h> 8#include <inttypes.h> 9#include <uv.h> 10 11#include "common.h" 12#include "errors.h" 13#include "output.h" 14#include "internal.h" 15#include "runtime.h" 16#include "gc/roots.h" 17#include "silver/engine.h" 18#include "modules/io.h" 19#include "modules/symbol.h" 20 21bool io_no_color = false; 22 23static ant_value_t g_console_proto = 0; 24static ant_value_t g_console_ctor = 0; 25 26#define JSON_KEY "\x1b[0m" 27#define JSON_STRING "\x1b[32m" 28#define JSON_NUMBER "\x1b[33m" 29#define JSON_BOOL "\x1b[35m" 30#define JSON_NULL "\x1b[90m" 31#define JSON_BRACE "\x1b[37m" 32#define JSON_FUNC "\x1b[36m" 33#define JSON_TAG "\x1b[34m" 34#define JSON_REF "\x1b[90m" 35#define JSON_WHITE "\x1b[97m" 36 37static inline bool io_is_digit_ascii(char c) { 38 return c >= '0' && c <= '9'; 39} 40 41static bool io_print_to_output(const char *str, ant_output_stream_t *out) { 42 if (!io_no_color) { 43 return ant_output_stream_append_cstr(out, str); 44 } 45 46 static void *states[] = {&&normal, &&esc, &&csi, &&done}; 47 const char *p = str; char c; 48 49 goto *states[0]; 50 51 normal: { 52 c = *p++; 53 if (!c) goto *states[3]; 54 if (c == '\x1b') goto *states[1]; 55 if (!ant_output_stream_putc(out, c)) return false; 56 goto *states[0]; 57 } 58 59 esc: { 60 c = *p++; 61 if (!c) goto *states[3]; 62 if (c == '[') goto *states[2]; 63 if (!ant_output_stream_putc(out, '\x1b')) return false; 64 if (!ant_output_stream_putc(out, c)) return false; 65 goto *states[0]; 66 } 67 68 csi: { 69 c = *p++; 70 if (!c) goto *states[3]; 71 if ((c >= '0' && c <= '9') || c == ';') goto *states[2]; 72 if (c != 'm' && !ant_output_stream_putc(out, c)) return false; 73 goto *states[0]; 74 } 75 76 done: return true; 77} 78 79enum char_class { 80 CC_OTHER, CC_NUL, CC_QUOTE, CC_ESCAPE, CC_LBRACE, CC_RBRACE, 81 CC_LBRACK, CC_RBRACK, CC_COLON, CC_COMMA, CC_NEWLINE, 82 CC_DIGIT, CC_MINUS, CC_ALPHA, CC_IDENT, CC_LT, CC_GT 83}; 84 85static const uint8_t char_class_table[256] = { 86 [0] = CC_NUL, 87 ['\n'] = CC_NEWLINE, ['"'] = CC_QUOTE, ['\''] = CC_QUOTE, ['\\'] = CC_ESCAPE, 88 ['{'] = CC_LBRACE, ['}'] = CC_RBRACE, ['['] = CC_LBRACK, [']'] = CC_RBRACK, 89 [':'] = CC_COLON, [','] = CC_COMMA, ['-'] = CC_MINUS, ['<'] = CC_LT, ['>'] = CC_GT, 90 ['_'] = CC_IDENT, ['$'] = CC_IDENT, 91 ['0'] = CC_DIGIT, ['1'] = CC_DIGIT, ['2'] = CC_DIGIT, ['3'] = CC_DIGIT, 92 ['4'] = CC_DIGIT, ['5'] = CC_DIGIT, ['6'] = CC_DIGIT, ['7'] = CC_DIGIT, 93 ['8'] = CC_DIGIT, ['9'] = CC_DIGIT, 94 ['a'] = CC_ALPHA, ['b'] = CC_ALPHA, ['c'] = CC_ALPHA, ['d'] = CC_ALPHA, 95 ['e'] = CC_ALPHA, ['f'] = CC_ALPHA, ['g'] = CC_ALPHA, ['h'] = CC_ALPHA, 96 ['i'] = CC_ALPHA, ['j'] = CC_ALPHA, ['k'] = CC_ALPHA, ['l'] = CC_ALPHA, 97 ['m'] = CC_ALPHA, ['n'] = CC_ALPHA, ['o'] = CC_ALPHA, ['p'] = CC_ALPHA, 98 ['q'] = CC_ALPHA, ['r'] = CC_ALPHA, ['s'] = CC_ALPHA, ['t'] = CC_ALPHA, 99 ['u'] = CC_ALPHA, ['v'] = CC_ALPHA, ['w'] = CC_ALPHA, ['x'] = CC_ALPHA, 100 ['y'] = CC_ALPHA, ['z'] = CC_ALPHA, 101 ['A'] = CC_ALPHA, ['B'] = CC_ALPHA, ['C'] = CC_ALPHA, ['D'] = CC_ALPHA, 102 ['E'] = CC_ALPHA, ['F'] = CC_ALPHA, ['G'] = CC_ALPHA, ['H'] = CC_ALPHA, 103 ['I'] = CC_ALPHA, ['J'] = CC_ALPHA, ['K'] = CC_ALPHA, ['L'] = CC_ALPHA, 104 ['M'] = CC_ALPHA, ['N'] = CC_ALPHA, ['O'] = CC_ALPHA, ['P'] = CC_ALPHA, 105 ['Q'] = CC_ALPHA, ['R'] = CC_ALPHA, ['S'] = CC_ALPHA, ['T'] = CC_ALPHA, 106 ['U'] = CC_ALPHA, ['V'] = CC_ALPHA, ['W'] = CC_ALPHA, ['X'] = CC_ALPHA, 107 ['Y'] = CC_ALPHA, ['Z'] = CC_ALPHA, 108}; 109 110static int io_iso_utc_token_len(const char *p) { 111 int i = 0; 112 113 if (*p == '+' || *p == '-') { 114 i++; 115 for (int d = 0; d < 6; d++, i++) if (!io_is_digit_ascii(p[i])) return 0; 116 } else for (int d = 0; d < 4; d++, i++) if (!io_is_digit_ascii(p[i])) return 0; 117 118 if (p[i++] != '-') return 0; 119 if (!io_is_digit_ascii(p[i++]) || !io_is_digit_ascii(p[i++])) return 0; 120 if (p[i++] != '-') return 0; 121 if (!io_is_digit_ascii(p[i++]) || !io_is_digit_ascii(p[i++])) return 0; 122 if (p[i++] != 'T') return 0; 123 if (!io_is_digit_ascii(p[i++]) || !io_is_digit_ascii(p[i++])) return 0; 124 if (p[i++] != ':') return 0; 125 if (!io_is_digit_ascii(p[i++]) || !io_is_digit_ascii(p[i++])) return 0; 126 if (p[i++] != ':') return 0; 127 if (!io_is_digit_ascii(p[i++]) || !io_is_digit_ascii(p[i++])) return 0; 128 if (p[i++] != '.') return 0; 129 if (!io_is_digit_ascii(p[i++]) || !io_is_digit_ascii(p[i++]) || !io_is_digit_ascii(p[i++])) return 0; 130 if (p[i++] != 'Z') return 0; 131 132 char boundary = p[i]; 133 if ( 134 !(boundary == '\0' 135 || boundary == ' ' 136 || boundary == '\t' 137 || boundary == '\n' 138 || boundary == ',' 139 || boundary == ']' 140 || boundary == '}' 141 || boundary == ')' 142 || boundary == '>') 143 ) return 0; 144 145 return i; 146} 147 148#define KEYWORD(kw, color) \ 149 if (memcmp(p, kw, sizeof(kw) - 1) == 0 && !isalnum((unsigned char)p[sizeof(kw) - 1]) && p[sizeof(kw) - 1] != '_') { \ 150 ant_output_stream_append_cstr(out, color); ant_output_stream_append_cstr(out, kw); ant_output_stream_append_cstr(out, C_RESET); \ 151 p += sizeof(kw) - 1; goto next; \ 152 } 153 154#define EMIT_UNTIL(end_char, color) \ 155 ant_output_stream_append_cstr(out, color); \ 156 while (*p && *p != end_char) ant_output_stream_putc(out, *p++); \ 157 if (*p == end_char) ant_output_stream_putc(out, *p++); \ 158 ant_output_stream_append_cstr(out, C_RESET); goto next; 159 160#define EMIT_TYPE(tag, len, color) \ 161 if (!(is_key && brace_depth > 0) && memcmp(p, tag, len) == 0) { \ 162 ant_output_stream_append_cstr(out, color); ant_output_stream_append_cstr(out, tag); ant_output_stream_append_cstr(out, C_RESET); \ 163 p += len; goto next; \ 164 } 165 166static void print_value_colored_to_output(const char *str, ant_output_stream_t *out) { 167 if (io_no_color) { io_print_to_output(str, out); return; } 168 169 static void *dispatch[] = { 170 [CC_NUL] = &&done, [CC_QUOTE] = &&quote, [CC_ESCAPE] = &&other, 171 [CC_LBRACE] = &&lbrace, [CC_RBRACE] = &&rbrace, 172 [CC_LBRACK] = &&lbrack, [CC_RBRACK] = &&rbrack, 173 [CC_COLON] = &&colon, [CC_COMMA] = &&separator, [CC_NEWLINE] = &&separator, 174 [CC_DIGIT] = &&number, [CC_MINUS] = &&minus, 175 [CC_ALPHA] = &&alpha, [CC_IDENT] = &&ident, [CC_LT] = &&lt, [CC_GT] = &&gt, [CC_OTHER] = &&other 176 }; 177 178 const char *p = str; 179 char string_char = 0; 180 int brace_depth = 0, array_depth = 0; 181 bool is_key = true; 182 183 goto next; 184 185next: 186 goto *dispatch[char_class_table[(unsigned char)*p]]; 187 188done: 189 return; 190 191quote: 192 string_char = *p; 193 ant_output_stream_append_cstr(out, (is_key && brace_depth > 0) ? JSON_KEY : JSON_STRING); 194 ant_output_stream_putc(out, *p++); 195 while (*p) { 196 if (*p == '\\' && p[1]) { ant_output_stream_putc(out, *p++); ant_output_stream_putc(out, *p++); continue; } 197 if (*p == string_char) { ant_output_stream_putc(out, *p++); break; } 198 ant_output_stream_putc(out, *p++); 199 } 200 ant_output_stream_append_cstr(out, C_RESET); 201 goto next; 202 203lbrace: 204 ant_output_stream_append_cstr(out, JSON_BRACE); ant_output_stream_putc(out, *p++); ant_output_stream_append_cstr(out, C_RESET); 205 brace_depth++; is_key = true; goto next; 206 207rbrace: 208 ant_output_stream_append_cstr(out, JSON_BRACE); ant_output_stream_putc(out, *p++); ant_output_stream_append_cstr(out, C_RESET); 209 brace_depth--; is_key = false; goto next; 210 211lbrack: 212 switch (p[1]) { 213 case 'A': if (memcmp(p + 2, "syncFunction", 7) == 0) { EMIT_UNTIL(']', JSON_FUNC) } break; 214 case 'b': if (memcmp(p + 2, "yte", 3) == 0 || memcmp(p + 2, "uffer]", 6) == 0) { EMIT_UNTIL(']', JSON_STRING) } break; 215 case 'F': if (memcmp(p + 2, "unction", 7) == 0) { EMIT_UNTIL(']', JSON_FUNC) } break; 216 case 'n': if (memcmp(p + 2, "ative code", 10) == 0) { EMIT_UNTIL(']', JSON_FUNC) } break; 217 case 'C': if (memcmp(p + 2, "ircular", 7) == 0) { EMIT_UNTIL(']', JSON_REF) } break; 218 case 'G': if (memcmp(p + 2, "etter/Setter]", 13) == 0 || memcmp(p + 2, "etter]", 6) == 0) { EMIT_UNTIL(']', JSON_FUNC) } break; 219 case 'S': if (memcmp(p + 2, "etter]", 6) == 0) { EMIT_UNTIL(']', JSON_FUNC) } break; 220 case 'O': if (memcmp(p + 2, "bject: null prototype]", 22) == 0) { EMIT_UNTIL(']', JSON_TAG) } break; 221 case 'M': if (memcmp(p + 2, "odule]", 6) == 0) { EMIT_UNTIL(']', JSON_TAG) } break; 222 case 'U': if (memcmp(p + 2, "int8Contents]", 13) == 0) { EMIT_UNTIL(']', JSON_FUNC) } break; 223 case 'P': if (memcmp(p + 2, "romise]", 7) == 0) { EMIT_UNTIL(']', JSON_TAG) } break; 224 } 225 ant_output_stream_append_cstr(out, JSON_BRACE); ant_output_stream_putc(out, *p++); ant_output_stream_append_cstr(out, C_RESET); 226 array_depth++; is_key = false; goto next; 227 228rbrack: 229 ant_output_stream_append_cstr(out, JSON_BRACE); ant_output_stream_putc(out, *p++); ant_output_stream_append_cstr(out, C_RESET); 230 array_depth--; is_key = false; goto next; 231 232colon: 233 ant_output_stream_putc(out, *p++); is_key = false; goto next; 234 235separator: 236 ant_output_stream_putc(out, *p++); 237 is_key = (brace_depth > 0 && array_depth == 0); 238 goto next; 239 240number: { 241 int iso_len = io_iso_utc_token_len(p); 242 if (iso_len > 0) { 243 ant_output_stream_append_cstr(out, C_MAGENTA); 244 for (int k = 0; k < iso_len; k++) ant_output_stream_putc(out, *p++); 245 ant_output_stream_append_cstr(out, C_RESET); 246 goto next; 247 } 248 } 249 ant_output_stream_append_cstr(out, JSON_NUMBER); 250 while ((*p >= '0' && *p <= '9') || *p == '.' || *p == 'e' || *p == 'E' || *p == '+' || *p == '-') 251 ant_output_stream_putc(out, *p++); 252 ant_output_stream_append_cstr(out, C_RESET); 253 goto next; 254 255minus: { 256 int iso_len = io_iso_utc_token_len(p); 257 if (iso_len > 0) { 258 ant_output_stream_append_cstr(out, C_MAGENTA); 259 for (int k = 0; k < iso_len; k++) ant_output_stream_putc(out, *p++); 260 ant_output_stream_append_cstr(out, C_RESET); 261 goto next; 262 } 263 } 264 if (memcmp(p + 1, "Infinity", 8) == 0 && !isalnum((unsigned char)p[9]) && p[9] != '_') { 265 ant_output_stream_append_cstr(out, JSON_NUMBER); ant_output_stream_append_cstr(out, "-Infinity"); ant_output_stream_append_cstr(out, C_RESET); 266 p += 9; goto next; 267 } 268 if (p[1] >= '0' && p[1] <= '9') { 269 ant_output_stream_append_cstr(out, JSON_NUMBER); ant_output_stream_putc(out, *p++); 270 while ((*p >= '0' && *p <= '9') || *p == '.' || *p == 'e' || *p == 'E' || *p == '+' || *p == '-') 271 ant_output_stream_putc(out, *p++); 272 ant_output_stream_append_cstr(out, C_RESET); 273 goto next; 274 } 275 ant_output_stream_putc(out, *p++); goto next; 276 277lt: 278 if (memcmp(p, "<ref", 4) == 0) { EMIT_UNTIL('>', JSON_REF) } 279 if (memcmp(p, "<pen", 4) == 0) { is_key = false; EMIT_UNTIL('>', C_CYAN) } 280 if (memcmp(p, "<rej", 4) == 0) { is_key = false; EMIT_UNTIL('>', C_CYAN) } 281 282 if (p[1] == '>' || (isxdigit((unsigned char)p[1]) && isxdigit((unsigned char)p[2]))) { 283 ant_output_stream_append_cstr(out, JSON_BRACE); ant_output_stream_putc(out, *p++); 284 ant_output_stream_append_cstr(out, JSON_WHITE); 285 while (*p && *p != '>') ant_output_stream_putc(out, *p++); 286 ant_output_stream_append_cstr(out, C_RESET); 287 if (*p == '>') { ant_output_stream_append_cstr(out, JSON_BRACE); ant_output_stream_putc(out, *p++); ant_output_stream_append_cstr(out, C_RESET); } 288 goto next; 289 } 290 291 ant_output_stream_append_cstr(out, JSON_BRACE); ant_output_stream_putc(out, *p++); ant_output_stream_append_cstr(out, C_RESET); 292 goto next; 293 294gt: 295 ant_output_stream_append_cstr(out, JSON_BRACE); ant_output_stream_putc(out, *p++); ant_output_stream_append_cstr(out, C_RESET); 296 goto next; 297 298alpha: 299 if (memcmp(p, "Object [", 8) == 0) { EMIT_UNTIL(']', JSON_TAG) } 300 if (memcmp(p, "Symbol(", 7) == 0) { EMIT_UNTIL(')', JSON_STRING) } 301 302 EMIT_TYPE("Map", 3, JSON_STRING) 303 EMIT_TYPE("Set", 3, JSON_STRING) 304 305 KEYWORD("true", JSON_BOOL) 306 KEYWORD("false", JSON_BOOL) 307 KEYWORD("null", JSON_NULL) 308 KEYWORD("undefined", JSON_NULL) 309 KEYWORD("Infinity", JSON_NUMBER) 310 KEYWORD("NaN", JSON_NUMBER) 311 312ident: 313 if (is_key && brace_depth > 0) { 314 ant_output_stream_append_cstr(out, JSON_KEY); 315 while (isalnum((unsigned char)*p) || *p == '_' || *p == '$') ant_output_stream_putc(out, *p++); 316 ant_output_stream_append_cstr(out, C_RESET); 317 goto next; 318 } 319 ant_output_stream_putc(out, *p++); goto next; 320 321other: 322 if (*p == '+') { 323 int iso_len = io_iso_utc_token_len(p); 324 if (iso_len > 0) { 325 ant_output_stream_append_cstr(out, C_MAGENTA); 326 for (int k = 0; k < iso_len; k++) ant_output_stream_putc(out, *p++); 327 ant_output_stream_append_cstr(out, C_RESET); 328 goto next; 329 } 330 } 331 ant_output_stream_putc(out, *p++); goto next; 332} 333 334#undef KEYWORD 335#undef EMIT_UNTIL 336#undef EMIT_TYPE 337 338void print_value_colored(const char *str, FILE *stream) { 339 ant_output_stream_t *out = ant_output_stream(stream); 340 ant_output_stream_begin(out); 341 print_value_colored_to_output(str, out); 342 ant_output_stream_flush(out); 343} 344 345void print_repl_value(ant_t *js, ant_value_t val, FILE *stream) { 346 ant_output_stream_t *out = ant_output_stream(stream); 347 348 if (vtype(val) == T_STR) { 349 char *str = js_getstr(js, val, NULL); 350 ant_output_stream_begin(out); 351 ant_output_stream_append_cstr(out, C(JSON_STRING)); 352 ant_output_stream_putc(out, '\''); 353 ant_output_stream_append_cstr(out, str ? str : ""); 354 ant_output_stream_putc(out, '\''); 355 ant_output_stream_append_cstr(out, C(C_RESET)); 356 ant_output_stream_putc(out, '\n'); 357 ant_output_stream_flush(out); 358 return; 359 } 360 361 if (vtype(val) == T_OBJ && vtype(js_get_slot(val, SLOT_ERR_TYPE)) != T_UNDEF) { 362 const char *stack = get_str_prop(js, val, "stack", 5, NULL); 363 364 if (stack) { 365 ant_output_stream_begin(out); 366 io_print_to_output(stack, out); 367 ant_output_stream_putc(out, '\n'); 368 ant_output_stream_flush(out); 369 return; 370 }} 371 372 char cbuf[512]; 373 js_cstr_t cstr = js_to_cstr(js, val, cbuf, sizeof(cbuf)); 374 375 if (vtype(val) == T_ERR) { 376 ant_output_stream_t *err_out = ant_output_stream(stderr); 377 ant_output_stream_begin(err_out); 378 ant_output_stream_append_cstr(err_out, cstr.ptr); 379 ant_output_stream_putc(err_out, '\n'); 380 ant_output_stream_flush(err_out); 381 } else { 382 ant_output_stream_begin(out); 383 print_value_colored_to_output(cstr.ptr, out); 384 ant_output_stream_putc(out, '\n'); 385 ant_output_stream_flush(out); 386 } 387 388 if (cstr.needs_free) free((void *)cstr.ptr); 389} 390 391static ant_value_t console_call_value( 392 ant_t *js, ant_value_t fn, 393 ant_value_t this_val, 394 ant_value_t *args, int nargs 395) { 396 ant_value_t saved_this = js->this_val; 397 ant_value_t result = js_mkundef(); 398 399 js->this_val = this_val; 400 if (vtype(fn) == T_CFUNC) result = js_as_cfunc(fn)(js, args, nargs); 401 else result = sv_vm_call(js->vm, js, fn, this_val, args, nargs, NULL, false); 402 js->this_val = saved_this; 403 404 return result; 405} 406 407static ant_value_t console_get_process_stream(ant_t *js, const char *name) { 408 ant_value_t process_obj = js_get(js, js_glob(js), "process"); 409 return js_get(js, process_obj, name); 410} 411 412static ant_value_t console_get_effective_this(ant_t *js, ant_value_t this_obj) { 413 if (is_special_object(this_obj)) return this_obj; 414 ant_value_t console_obj = js_get(js, js_glob(js), "console"); 415 if (is_special_object(console_obj)) return console_obj; 416 return this_obj; 417} 418 419static ant_value_t console_get_target_stream(ant_t *js, ant_value_t this_obj, bool use_stderr) { 420 if (is_special_object(this_obj)) { 421 ant_value_t direct = js_get_slot(this_obj, use_stderr ? SLOT_CONSOLE_STDERR : SLOT_CONSOLE_STDOUT); 422 if (is_special_object(direct)) return direct; 423 } 424 return console_get_process_stream(js, use_stderr ? "stderr" : "stdout"); 425} 426 427static bool console_write_to_stream_obj(ant_t *js, ant_value_t stream_obj, const char *data, size_t len) { 428 if (!is_special_object(stream_obj)) return false; 429 430 ant_value_t write_fn = js_get(js, stream_obj, "write"); 431 if (!is_callable(write_fn)) return false; 432 433 ant_value_t argv[1] = { js_mkstr(js, data, len) }; 434 ant_value_t result = console_call_value(js, write_fn, stream_obj, argv, 1); 435 if (is_err(result) || js->thrown_exists) return false; 436 return true; 437} 438 439static bool console_write_string( 440 ant_t *js, ant_value_t this_obj, 441 bool use_stderr, const char *data, size_t len 442) { 443 ant_value_t stream_obj = console_get_target_stream(js, this_obj, use_stderr); 444 if (console_write_to_stream_obj(js, stream_obj, data, len)) return true; 445 446 ant_output_stream_t *out = ant_output_stream(use_stderr ? stderr : stdout); 447 ant_output_stream_begin(out); 448 if (!ant_output_stream_append(out, data, len)) return false; 449 return ant_output_stream_flush(out); 450} 451 452static bool console_output_put_indent(ant_output_stream_t *out, int total) { 453 for (int i = 0; i < total; i++) if (!ant_output_stream_putc(out, ' ')) return false; 454 return true; 455} 456 457static int console_get_group_indentation(ant_t *js, ant_value_t this_obj) { 458 ant_value_t value = is_special_object(this_obj) ? js_get_slot(this_obj, SLOT_CONSOLE_GROUP_INDENT) : js_mkundef(); 459 return vtype(value) == T_NUM ? (int)js_getnum(value) : 2; 460} 461 462static int console_get_group_level(ant_t *js, ant_value_t this_obj) { 463 ant_value_t value = is_special_object(this_obj) ? js_get_slot(this_obj, SLOT_CONSOLE_GROUP_LEVEL) : js_mkundef(); 464 return vtype(value) == T_NUM ? (int)js_getnum(value) : 0; 465} 466 467static void console_set_group_level(ant_t *js, ant_value_t this_obj, int level) { 468 if (!is_special_object(this_obj)) return; 469 if (level < 0) level = 0; 470 js_set_slot(this_obj, SLOT_CONSOLE_GROUP_LEVEL, js_mknum((double)level)); 471} 472 473static ant_value_t console_get_state_map(ant_t *js, ant_value_t this_obj, const char *name) { 474 internal_slot_t slot = SLOT_NONE; 475 476 if (!is_special_object(this_obj)) return js_mkundef(); 477 if (strcmp(name, "counts") == 0) slot = SLOT_CONSOLE_COUNTS; 478 else if (strcmp(name, "timers") == 0) slot = SLOT_CONSOLE_TIMERS; 479 else return js_mkundef(); 480 481 ant_value_t map = js_get_slot(this_obj, slot); 482 if (is_special_object(map)) return map; 483 484 map = js_mkobj(js); 485 js_set_slot_wb(js, this_obj, slot, map); 486 487 return map; 488} 489 490static bool console_write_args_to_stream( 491 ant_t *js, ant_output_stream_t *out, 492 ant_value_t *args, int nargs, bool color_values 493) { 494 for (int i = 0; i < nargs; i++) { 495 if (i && !ant_output_stream_putc(out, ' ')) return false; 496 497 if (vtype(args[i]) == T_OBJ) { 498 const char *stack = get_str_prop(js, args[i], "stack", 5, NULL); 499 if (stack) { 500 if (!io_print_to_output(stack, out)) return false; 501 continue; 502 }} 503 504 char cbuf[512]; 505 js_cstr_t cstr = js_to_cstr(js, args[i], cbuf, sizeof(cbuf)); 506 bool ok = true; 507 508 if (vtype(args[i]) == T_STR) ok = io_print_to_output(cstr.ptr, out); 509 else { 510 bool saved_no_color = io_no_color; 511 io_no_color = saved_no_color || !color_values; 512 if (ok) print_value_colored_to_output(cstr.ptr, out); 513 io_no_color = saved_no_color; 514 } 515 516 if (cstr.needs_free) free((void *)cstr.ptr); 517 if (!ok) return false; 518 } 519 520 return true; 521} 522 523static ant_value_t console_emit_to_output( 524 ant_t *js, ant_value_t this_obj, 525 const char *prefix, ant_value_t *args, 526 int nargs, 527 ant_output_stream_t *out 528) { 529 bool color_values = !io_no_color; 530 531 int group_level = console_get_group_level(js, this_obj); 532 int indent = console_get_group_indentation(js, this_obj); 533 int total_indent = group_level * indent; 534 535 if (!console_output_put_indent(out, total_indent)) goto oom; 536 if (prefix && !ant_output_stream_append_cstr(out, prefix)) goto oom; 537 if (prefix && nargs > 0 && !ant_output_stream_putc(out, ' ')) goto oom; 538 if (!console_write_args_to_stream(js, out, args, nargs, color_values)) goto oom; 539 if (!ant_output_stream_putc(out, '\n')) goto oom; 540 541 return js_mkundef(); 542 oom: return js_mkerr(js, "Out of memory"); 543} 544 545static inline ant_value_t console_emit_with_this( 546 ant_t *js, 547 ant_value_t this_obj, 548 bool use_stderr, const char *prefix, 549 ant_value_t *args, int nargs 550) { 551 this_obj = console_get_effective_this(js, this_obj); 552 ant_output_stream_t out = {0}; 553 ant_output_stream_begin(&out); 554 555 ant_value_t result = console_emit_to_output(js, this_obj, prefix, args, nargs, &out); 556 if (!is_err(result)) console_write_string( 557 js, this_obj, use_stderr, 558 out.buffer.data ? out.buffer.data : "", out.buffer.len 559 ); 560 561 free(out.buffer.data); 562 return result; 563} 564 565ant_value_t console_emit( 566 ant_t *js, 567 bool use_stderr, const char *prefix, 568 ant_value_t *args, int nargs 569) { 570 return console_emit_with_this(js, js_mkundef(), use_stderr, prefix, args, nargs); 571} 572 573ant_value_t console_emit_current( 574 ant_t *js, 575 bool use_stderr, const char *prefix, 576 ant_value_t *args, int nargs 577) { 578 return console_emit_with_this(js, js_getthis(js), use_stderr, prefix, args, nargs); 579} 580 581static void console_write_args_to_output(ant_t *js, ant_output_stream_t *out, ant_value_t *args, int nargs) { 582for (int i = 0; i < nargs; i++) { 583 if (i) ant_output_stream_putc(out, ' '); 584 585 if (vtype(args[i]) == T_OBJ) { 586 const char *stack = get_str_prop(js, args[i], "stack", 5, NULL); 587 if (stack) { 588 io_print_to_output(stack, out); 589 continue; 590 }} 591 592 char cbuf[512]; 593 js_cstr_t cstr = js_to_cstr(js, args[i], cbuf, sizeof(cbuf)); 594 595 if (vtype(args[i]) == T_STR) io_print_to_output(cstr.ptr, out); 596 else print_value_colored_to_output(cstr.ptr, out); 597 598 if (cstr.needs_free) free((void *)cstr.ptr); 599}} 600 601static ant_value_t js_console_log(ant_t *js, ant_value_t *args, int nargs) { 602 return console_emit_current(js, false, NULL, args, nargs); 603} 604 605static ant_value_t js_console_error(ant_t *js, ant_value_t *args, int nargs) { 606 return console_emit_current(js, true, NULL, args, nargs); 607} 608 609static ant_value_t js_console_warn(ant_t *js, ant_value_t *args, int nargs) { 610 return console_emit_current(js, true, NULL, args, nargs); 611} 612 613static ant_value_t js_console_info(ant_t *js, ant_value_t *args, int nargs) { 614 return console_emit_current(js, false, NULL, args, nargs); 615} 616 617static ant_value_t js_console_debug(ant_t *js, ant_value_t *args, int nargs) { 618 return console_emit_current(js, false, NULL, args, nargs); 619} 620 621static ant_value_t js_console_assert(ant_t *js, ant_value_t *args, int nargs) { 622 if (nargs < 1) return js_mkundef(); 623 bool is_truthy = js_truthy(js, args[0]); 624 if (is_truthy) return js_mkundef(); 625 return console_emit_current(js, true, "Assertion failed:", args + 1, nargs - 1); 626} 627 628static ant_value_t js_console_trace(ant_t *js, ant_value_t *args, int nargs) { 629 ant_value_t this_obj = console_get_effective_this(js, js_getthis(js)); 630 console_emit_current(js, true, "Trace:", args, nargs); 631 ant_value_t stack = js_capture_raw_stack(js); 632 if (vtype(stack) == T_STR) { 633 size_t stack_len = 0; 634 const char *stack_str = js_getstr(js, stack, &stack_len); 635 console_write_string(js, this_obj, true, stack_str, stack_len); 636 } else js_print_stack_trace_vm(js, stderr); 637 return js_mkundef(); 638} 639 640static ant_value_t js_console_clear(ant_t *js, ant_value_t *args, int nargs) { 641 ant_value_t this_obj = js_getthis(js); 642 if (!io_no_color) console_write_string(js, this_obj, false, "\033[2J\033[H", 7); 643 return js_mkundef(); 644} 645 646static ant_value_t js_console_time(ant_t *js, ant_value_t *args, int nargs) { 647 ant_value_t this_obj = js_getthis(js); 648 const char *label = "default"; 649 650 if (nargs > 0 && vtype(args[0]) == T_STR) label = js_getstr(js, args[0], NULL); 651 ant_value_t timers = console_get_state_map(js, this_obj, "timers"); 652 if (is_special_object(timers) && vtype(js_get(js, timers, label)) != T_UNDEF) { 653 ant_value_t warn_args[1] = { js_mkstr(js, "Timer already exists", 20) }; 654 return console_emit_current(js, true, NULL, warn_args, 1); 655 } 656 657 js_set(js, timers, label, js_mknum((double)uv_hrtime() / 1e6)); 658 return js_mkundef(); 659} 660 661static ant_value_t js_console_timeEnd(ant_t *js, ant_value_t *args, int nargs) { 662 ant_value_t this_obj = js_getthis(js); 663 const char *label = "default"; 664 665 if (nargs > 0 && vtype(args[0]) == T_STR) label = js_getstr(js, args[0], NULL); 666 ant_value_t timers = console_get_state_map(js, this_obj, "timers"); 667 ant_value_t start = is_special_object(timers) ? js_get(js, timers, label) : js_mkundef(); 668 669 if (vtype(start) != T_NUM) { 670 ant_value_t warn_args[1] = { js_mkstr(js, "Timer does not exist", 19) }; 671 return console_emit_current(js, true, NULL, warn_args, 1); 672 } 673 674 double elapsed = ((double)uv_hrtime() / 1e6) - js_getnum(start); 675 js_delete_prop(js, timers, label, strlen(label)); 676 char buf[256]; 677 678 int len = snprintf(buf, sizeof(buf), "%s: %.3fms", label, elapsed); 679 ant_value_t out_args[1] = { js_mkstr(js, buf, (size_t)(len > 0 ? len : 0)) }; 680 681 return console_emit_current(js, false, NULL, out_args, 1); 682} 683 684static ant_value_t js_console_timeLog(ant_t *js, ant_value_t *args, int nargs) { 685 ant_value_t this_obj = js_getthis(js); 686 const char *label = "default"; 687 int extra_start = 0; 688 689 if (nargs > 0 && vtype(args[0]) == T_STR) { 690 label = js_getstr(js, args[0], NULL); 691 extra_start = 1; 692 } 693 694 ant_value_t timers = console_get_state_map(js, this_obj, "timers"); 695 ant_value_t start = is_special_object(timers) ? js_get(js, timers, label) : js_mkundef(); 696 697 if (vtype(start) != T_NUM) { 698 ant_value_t warn_args[1] = { js_mkstr(js, "Timer does not exist", 19) }; 699 return console_emit_current(js, true, NULL, warn_args, 1); 700 } 701 702 char buf[256]; 703 double elapsed = ((double)uv_hrtime() / 1e6) - js_getnum(start); 704 int len = snprintf(buf, sizeof(buf), "%s: %.3fms", label, elapsed); 705 706 ant_value_t *out_args = malloc((size_t)(nargs - extra_start + 1) * sizeof(ant_value_t)); 707 if (!out_args) return js_mkerr(js, "Out of memory"); 708 709 out_args[0] = js_mkstr(js, buf, (size_t)(len > 0 ? len : 0)); 710 for (int i = extra_start; i < nargs; i++) out_args[i - extra_start + 1] = args[i]; 711 ant_value_t result = console_emit_current(js, false, NULL, out_args, nargs - extra_start + 1); 712 free(out_args); 713 714 return result; 715} 716 717static ant_value_t js_console_count(ant_t *js, ant_value_t *args, int nargs) { 718 ant_value_t this_obj = js_getthis(js); 719 const char *label = "default"; 720 721 if (nargs > 0 && vtype(args[0]) == T_STR) label = js_getstr(js, args[0], NULL); 722 ant_value_t counts = console_get_state_map(js, this_obj, "counts"); 723 ant_value_t current = is_special_object(counts) ? js_get(js, counts, label) : js_mkundef(); 724 725 double next = vtype(current) == T_NUM ? js_getnum(current) + 1 : 1; 726 js_set(js, counts, label, js_mknum(next)); 727 728 char buf[256]; 729 int len = snprintf(buf, sizeof(buf), "%s: %.0f", label, next); 730 ant_value_t out_args[1] = { js_mkstr(js, buf, (size_t)(len > 0 ? len : 0)) }; 731 732 return console_emit_current(js, false, NULL, out_args, 1); 733} 734 735static ant_value_t js_console_countReset(ant_t *js, ant_value_t *args, int nargs) { 736 ant_value_t this_obj = js_getthis(js); 737 const char *label = "default"; 738 if (nargs > 0 && vtype(args[0]) == T_STR) label = js_getstr(js, args[0], NULL); 739 ant_value_t counts = console_get_state_map(js, this_obj, "counts"); 740 js_delete_prop(js, counts, label, strlen(label)); 741 return js_mkundef(); 742} 743 744static ant_value_t js_console_group(ant_t *js, ant_value_t *args, int nargs) { 745 ant_value_t this_obj = js_getthis(js); 746 if (nargs > 0) console_emit_current(js, false, NULL, args, nargs); 747 console_set_group_level(js, this_obj, console_get_group_level(js, this_obj) + 1); 748 return js_mkundef(); 749} 750 751static ant_value_t js_console_group_end(ant_t *js, ant_value_t *args, int nargs) { 752 ant_value_t this_obj = js_getthis(js); 753 console_set_group_level(js, this_obj, console_get_group_level(js, this_obj) - 1); 754 return js_mkundef(); 755} 756 757static ant_value_t js_console_group_collapsed(ant_t *js, ant_value_t *args, int nargs) { 758 return js_console_group(js, args, nargs); 759} 760 761static const char *get_slot_name(internal_slot_t slot) { 762 #define ANT_SLOT_NAME(name) [name] = &#name[5], 763 static const char *slot_names[] = { 764 ANT_INTERNAL_SLOT_LIST(ANT_SLOT_NAME) 765 }; 766 #undef ANT_SLOT_NAME 767 768 if (slot < sizeof(slot_names) / sizeof(slot_names[0]) && slot_names[slot]) { 769 return slot_names[slot]; 770 } 771 772 return "UNKNOWN"; 773} 774 775static const char *get_type_name(int type) { 776 static const char *type_names[] = { 777 [T_OBJ] = "object", 778 [T_STR] = "string", 779 [T_ARR] = "array", 780 [T_FUNC] = "function", 781 [T_CFUNC] = "function", 782 [T_PROMISE] = "Promise", 783 [T_GENERATOR] = "Generator", 784 [T_UNDEF] = "undefined", 785 [T_NULL] = "null", 786 [T_BOOL] = "boolean", 787 [T_NUM] = "number", 788 [T_BIGINT] = "bigint", 789 [T_SYMBOL] = "symbol", 790 [T_ERR] = "error", 791 [T_TYPEDARRAY] = "TypedArray", 792 [T_NTARG] = "ntarg", 793 [T_MAP] = "map", 794 [T_SET] = "set", 795 [T_WEAKMAP] = "weakmap", 796 [T_WEAKSET] = "weakset" 797 }; 798 799 size_t num_types = sizeof(type_names) / sizeof(type_names[0]); 800 if (type < 0 || (size_t)type >= num_types) return "unknown"; 801 802 return type_names[type] ? type_names[type] : "unknown"; 803} 804 805static bool inspect_was_visited(inspect_visited_t *v, uintptr_t off) { 806 for (int i = 0; i < v->count; i++) if (v->visited[i] == off) return true; 807 return false; 808} 809 810static void inspect_print_indent(FILE *stream, int depth) { 811 for (int i = 0; i < depth; i++) fprintf(stream, " "); 812} 813 814static void inspect_mark_visited(inspect_visited_t *v, uintptr_t off) { 815 if (v->count >= v->capacity) { 816 v->capacity = v->capacity ? v->capacity * 2 : 32; 817 v->visited = realloc(v->visited, v->capacity * sizeof(uintptr_t)); 818 } 819 v->visited[v->count++] = off; 820} 821 822void inspect_value(ant_t *js, ant_value_t val, FILE *stream, int depth, inspect_visited_t *visited) { 823 int t = vtype(val); 824 825 if (t == T_UNDEF) { fprintf(stream, "undefined"); return; } 826 if (t == T_NULL) { fprintf(stream, "null"); return; } 827 if (t == T_BOOL) { fprintf(stream, val == js_true ? "true" : "false"); return; } 828 if (t == T_NUM) { fprintf(stream, "%g", js_getnum(val)); return; } 829 if (t == T_ERR) { fprintf(stream, "[Error]"); return; } 830 831 if (t == T_STR) { 832 size_t len; 833 char *str = js_getstr(js, val, &len); 834 fprintf(stream, "\"%.*s\"", (int)len, str ? str : ""); 835 return; 836 } 837 838 if (t == T_SYMBOL) { 839 const char *desc = js_sym_desc(val); 840 fprintf(stream, "Symbol(%s)", desc ? desc : ""); 841 return; 842 } 843 844 if (t == T_OBJ || t == T_FUNC || t == T_PROMISE || t == T_ARR) { 845 if (depth > 10) fprintf(stream, "<%s @%" PRIu64 " ...>", get_type_name(t), (uint64_t)vdata(js_as_obj(val))); 846 else inspect_object(js, val, stream, depth, visited); 847 return; 848 } 849 850 if (t == T_CFUNC) { 851 ant_value_t promoted = js_cfunc_lookup_promoted(js, val); 852 if (vtype(promoted) == T_FUNC) { 853 if (depth > 10) fprintf(stream, "<Function @%" PRIu64 " ...>", (uint64_t)vdata(js_as_obj(promoted))); 854 else inspect_object(js, promoted, stream, depth, visited); 855 return; 856 } 857 858 const ant_cfunc_meta_t *meta = js_as_cfunc_meta(val); 859 const char *name = (meta && meta->name) ? meta->name : NULL; 860 uint32_t length = js_cfunc_length(val); 861 bool has_prototype = meta && (meta->flags & CFUNC_HAS_PROTOTYPE) != 0; 862 863 if (name) fprintf(stream, "[Function: %s]", name); 864 else fprintf(stream, "[Function]"); 865 866 fprintf(stream, " <native ptr 0x%" PRIx64 ", length=%u", (uint64_t)vdata(val), length); 867 if (has_prototype) fprintf(stream, ", prototype"); 868 fprintf(stream, ">"); 869 870 return; 871 } 872 873 fprintf(stream, "<%s rawtype=%d data=%" PRIu64 ">", get_type_name(t), vtype(val), (uint64_t)vdata(val)); 874} 875 876void inspect_object(ant_t *js, ant_value_t obj, FILE *stream, int depth, inspect_visited_t *visited) { 877 int type = vtype(obj); 878 obj = js_as_obj(obj); 879 uintptr_t obj_off = (uintptr_t)vdata(obj); 880 881 if (inspect_was_visited(visited, obj_off)) { 882 fprintf(stream, "[Circular *%llu]", (u64)obj_off); 883 return; 884 } 885 886 inspect_mark_visited(visited, obj_off); 887 fprintf(stream, "<%s @%llu> {\n", type == T_FUNC ? "Function" : (type == T_PROMISE ? "Promise" : "Object"), (u64)obj_off); 888 889 int inner_depth = depth + 1; 890 inspect_print_indent(stream, inner_depth); 891 fprintf(stream, "[[Slots]]: {\n"); 892 893 for (int slot = SLOT_NONE + 1; slot < SLOT_MAX; slot++) { 894 ant_value_t slot_val = js_get_slot(obj, (internal_slot_t)slot); 895 int t = vtype(slot_val); 896 if (t == T_UNDEF) continue; 897 898 inspect_print_indent(stream, inner_depth + 1); 899 fprintf(stream, "[[%s]]: ", get_slot_name((internal_slot_t)slot)); 900 901 switch (slot) { 902 case SLOT_CODE: 903 case SLOT_CFUNC: 904 fprintf(stream, "<native ptr 0x%" PRIx64 ">", (uint64_t)vdata(slot_val)); 905 break; 906 case SLOT_CODE_LEN: 907 fprintf(stream, "%.0f", js_getnum(slot_val)); 908 break; 909 default: 910 if ((t == T_OBJ || t == T_FUNC || t == T_PROMISE) && inspect_was_visited(visited, (uintptr_t)vdata(js_as_obj(slot_val)))) 911 fprintf(stream, "[Circular *%llu]", (u64)vdata(js_as_obj(slot_val))); 912 else if (t == T_OBJ || t == T_FUNC || t == T_PROMISE) 913 fprintf(stream, "<%s @%llu>", get_type_name(t), (u64)vdata(js_as_obj(slot_val))); 914 else 915 inspect_value(js, slot_val, stream, inner_depth + 1, visited); 916 break; 917 } 918 919 fprintf(stream, "\n"); 920 } 921 922 inspect_print_indent(stream, inner_depth); 923 fprintf(stream, "}\n"); 924 925 inspect_print_indent(stream, inner_depth); 926 fprintf(stream, "[[Properties]]: {\n"); 927 928 ant_iter_t iter = js_prop_iter_begin(js, obj); 929 const char *key; 930 size_t key_len; 931 ant_value_t value; 932 933 while (js_prop_iter_next(&iter, &key, &key_len, &value)) { 934 inspect_print_indent(stream, inner_depth + 1); 935 fprintf(stream, "\"%.*s\": ", (int)key_len, key); 936 inspect_value(js, value, stream, inner_depth + 1, visited); 937 fprintf(stream, "\n"); 938 } 939 940 js_prop_iter_end(&iter); 941 inspect_print_indent(stream, inner_depth); 942 fprintf(stream, "}\n"); 943 944 ant_value_t proto = js_get_proto(js, obj); 945 inspect_print_indent(stream, inner_depth); 946 fprintf(stream, "[[Prototype]]: "); 947 if (vtype(proto) == T_NULL) { 948 fprintf(stream, "null\n"); 949 } else { 950 fprintf(stream, "\n"); 951 inspect_print_indent(stream, inner_depth); 952 inspect_value(js, proto, stream, inner_depth, visited); 953 fprintf(stream, "\n"); 954 } 955 956 inspect_print_indent(stream, depth); 957 fprintf(stream, "}"); 958} 959 960static ant_value_t js_console_inspect(ant_t *js, ant_value_t *args, int nargs) { 961 FILE *stream = stdout; 962 inspect_visited_t visited = {0}; 963 964 for (int i = 0; i < nargs; i++) { 965 if (i > 0) fprintf(stream, " "); 966 inspect_value(js, args[i], stream, 0, &visited); 967 } 968 969 fprintf(stream, "\n"); 970 if (visited.visited) free(visited.visited); 971 972 return js_mkundef(); 973} 974 975// TODO: replace stub with real 976static ant_value_t js_console_dir(ant_t *js, ant_value_t *args, int nargs) { 977 return js_console_log(js, args, nargs); 978} 979 980// TODO: replace stub with real 981static ant_value_t js_console_dirxml(ant_t *js, ant_value_t *args, int nargs) { 982 return js_console_log(js, args, nargs); 983} 984 985// TODO: replace stub with real 986static ant_value_t js_console_table(ant_t *js, ant_value_t *args, int nargs) { 987 return js_console_log(js, args, nargs); 988} 989 990static void console_apply_methods(ant_t *js, ant_value_t console_obj) { 991 js_set(js, console_obj, "log", js_mkfun(js_console_log)); 992 js_set(js, console_obj, "error", js_mkfun(js_console_error)); 993 js_set(js, console_obj, "warn", js_mkfun(js_console_warn)); 994 js_set(js, console_obj, "info", js_mkfun(js_console_info)); 995 js_set(js, console_obj, "debug", js_mkfun(js_console_debug)); 996 js_set(js, console_obj, "assert", js_mkfun(js_console_assert)); 997 js_set(js, console_obj, "dir", js_mkfun(js_console_dir)); 998 js_set(js, console_obj, "dirxml", js_mkfun(js_console_dirxml)); 999 js_set(js, console_obj, "table", js_mkfun(js_console_table)); 1000 js_set(js, console_obj, "trace", js_mkfun(js_console_trace)); 1001 js_set(js, console_obj, "count", js_mkfun(js_console_count)); 1002 js_set(js, console_obj, "countReset", js_mkfun(js_console_countReset)); 1003 js_set(js, console_obj, "time", js_mkfun(js_console_time)); 1004 js_set(js, console_obj, "timeLog", js_mkfun(js_console_timeLog)); 1005 js_set(js, console_obj, "timeEnd", js_mkfun(js_console_timeEnd)); 1006 js_set(js, console_obj, "group", js_mkfun(js_console_group)); 1007 js_set(js, console_obj, "groupCollapsed", js_mkfun(js_console_group_collapsed)); 1008 js_set(js, console_obj, "groupEnd", js_mkfun(js_console_group_end)); 1009 js_set(js, console_obj, "clear", js_mkfun(js_console_clear)); 1010 js_set(js, console_obj, "inspect", js_mkfun(js_console_inspect)); 1011} 1012 1013static ant_value_t js_console_constructor(ant_t *js, ant_value_t *args, int nargs) { 1014 ant_value_t proto = js_instance_proto_from_new_target(js, g_console_proto); 1015 ant_value_t console_obj = js_mkobj(js); 1016 js_set_proto_init(console_obj, is_special_object(proto) ? proto : g_console_proto); 1017 1018 ant_value_t stdout_obj = js_mkundef(); 1019 ant_value_t stderr_obj = js_mkundef(); 1020 int group_indentation = 2; 1021 1022 if (nargs >= 1 && is_special_object(args[0]) && nargs == 1) { 1023 ant_value_t options = args[0]; 1024 stdout_obj = js_get(js, options, "stdout"); 1025 stderr_obj = js_get(js, options, "stderr"); 1026 ant_value_t gi = js_get(js, options, "groupIndentation"); 1027 if (vtype(gi) == T_NUM) group_indentation = (int)js_getnum(gi); 1028 } else { 1029 if (nargs >= 1) stdout_obj = args[0]; 1030 if (nargs >= 2) stderr_obj = args[1]; 1031 } 1032 1033 if (vtype(stderr_obj) == T_UNDEF) stderr_obj = stdout_obj; 1034 js_set_slot_wb(js, console_obj, SLOT_CONSOLE_STDOUT, stdout_obj); 1035 js_set_slot_wb(js, console_obj, SLOT_CONSOLE_STDERR, stderr_obj); 1036 js_set_slot_wb(js, console_obj, SLOT_CONSOLE_COUNTS, js_mkobj(js)); 1037 js_set_slot_wb(js, console_obj, SLOT_CONSOLE_TIMERS, js_mkobj(js)); 1038 1039 js_set_slot(console_obj, SLOT_CONSOLE_GROUP_INDENT, js_mknum((double)group_indentation)); 1040 js_set_slot(console_obj, SLOT_CONSOLE_GROUP_LEVEL, js_mknum(0)); 1041 1042 return console_obj; 1043} 1044 1045ant_value_t console_library(ant_t *js) { 1046 if (!g_console_ctor) { 1047 g_console_proto = js_mkobj(js); 1048 console_apply_methods(js, g_console_proto); 1049 js_set_sym(js, g_console_proto, get_toStringTag_sym(), js_mkstr(js, "console", 7)); 1050 g_console_ctor = js_make_ctor(js, js_console_constructor, g_console_proto, "Console", 7); 1051 gc_register_root(&g_console_proto); 1052 gc_register_root(&g_console_ctor); 1053 } 1054 1055 ant_value_t console_obj = js_mkobj(js); 1056 js_set_proto_init(console_obj, g_console_proto); 1057 js_set_slot_wb(js, console_obj, SLOT_CONSOLE_COUNTS, js_mkobj(js)); 1058 js_set_slot_wb(js, console_obj, SLOT_CONSOLE_TIMERS, js_mkobj(js)); 1059 js_set_slot(console_obj, SLOT_CONSOLE_GROUP_INDENT, js_mknum(2)); 1060 js_set_slot(console_obj, SLOT_CONSOLE_GROUP_LEVEL, js_mknum(0)); 1061 1062 js_set(js, console_obj, "Console", g_console_ctor); 1063 js_set(js, console_obj, "default", console_obj); 1064 js_set_sym(js, console_obj, get_toStringTag_sym(), js_mkstr(js, "console", 7)); 1065 1066 return console_obj; 1067} 1068 1069void init_console_module() { 1070 ant_t *js = rt->js; 1071 ant_value_t console_obj = console_library(js); 1072 js_set(js, js_glob(js), "console", console_obj); 1073}