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.

colored printing + cleaner io

+463 -33
+3
include/modules/io.h
··· 1 1 #ifndef IO_H 2 2 #define IO_H 3 3 4 + #include <stdio.h> 5 + 4 6 void init_console_module(void); 7 + void print_value_colored(const char *str, FILE *stream); 5 8 6 9 #endif
+3
maidfile.toml
··· 14 14 15 15 [tasks.debug] 16 16 script = ["maid build -q", "./build/ant -d %{arg.1}"] 17 + 18 + [tasks.install] 19 + script = "bash -c 'which ant && cp ./build/ant \"$(which ant)\" || { mkdir -p ~/.local/bin && cp ./build/ant ~/.local/bin/; }'"
+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.0.8.15') 77 + version_conf.set('ANT_VERSION', '0.0.8.16') 78 78 version_conf.set('ANT_GIT_HASH', git_hash) 79 79 version_conf.set('ANT_BUILD_DATE', build_date) 80 80
+251 -26
src/ant.c
··· 704 704 } 705 705 706 706 #define MAX_STRINGIFY_DEPTH 64 707 + #define MAX_MULTIREF_OBJS 128 708 + 707 709 static jsval_t stringify_stack[MAX_STRINGIFY_DEPTH]; 708 710 static int stringify_depth = 0; 711 + static int stringify_indent = 0; 709 712 710 - static bool is_circular(jsval_t obj) { 713 + static jsval_t multiref_objs[MAX_MULTIREF_OBJS]; 714 + static int multiref_ids[MAX_MULTIREF_OBJS]; 715 + static int multiref_count = 0; 716 + static int multiref_next_id = 0; 717 + 718 + static void scan_refs(struct js *js, jsval_t value); 719 + 720 + static int find_multiref(jsval_t obj) { 721 + for (int i = 0; i < multiref_count; i++) { 722 + if (multiref_objs[i] == obj) return multiref_ids[i]; 723 + } 724 + return 0; 725 + } 726 + 727 + static bool is_on_stack(jsval_t obj) { 711 728 for (int i = 0; i < stringify_depth; i++) { 712 729 if (stringify_stack[i] == obj) return true; 713 730 } 714 731 return false; 715 732 } 716 733 734 + static void mark_multiref(jsval_t obj) { 735 + for (int i = 0; i < multiref_count; i++) { 736 + if (multiref_objs[i] == obj) { 737 + if (multiref_ids[i] == 0) multiref_ids[i] = ++multiref_next_id; 738 + return; 739 + } 740 + } 741 + if (multiref_count < MAX_MULTIREF_OBJS) { 742 + multiref_objs[multiref_count] = obj; 743 + multiref_ids[multiref_count] = 0; 744 + multiref_count++; 745 + } 746 + } 747 + 748 + static void scan_obj_refs(struct js *js, jsval_t obj) { 749 + if (is_on_stack(obj)) { 750 + mark_multiref(obj); 751 + return; 752 + } 753 + mark_multiref(obj); 754 + 755 + if (stringify_depth >= MAX_STRINGIFY_DEPTH) return; 756 + stringify_stack[stringify_depth++] = obj; 757 + 758 + jsoff_t next = loadoff(js, (jsoff_t) vdata(obj)) & ~(3U | CONSTMASK); 759 + while (next < js->brk && next != 0) { 760 + jsoff_t koff = loadoff(js, next + (jsoff_t) sizeof(next)); 761 + jsval_t val = loadval(js, next + (jsoff_t) (sizeof(next) + sizeof(koff))); 762 + scan_refs(js, val); 763 + next = loadoff(js, next) & ~(3U | CONSTMASK); 764 + } 765 + 766 + stringify_depth--; 767 + } 768 + 769 + static void scan_arr_refs(struct js *js, jsval_t obj) { 770 + if (is_on_stack(obj)) { 771 + mark_multiref(obj); 772 + return; 773 + } 774 + mark_multiref(obj); 775 + 776 + if (stringify_depth >= MAX_STRINGIFY_DEPTH) return; 777 + stringify_stack[stringify_depth++] = obj; 778 + 779 + jsoff_t next = loadoff(js, (jsoff_t) vdata(obj)) & ~(3U | CONSTMASK); 780 + while (next < js->brk && next != 0) { 781 + jsoff_t koff = loadoff(js, next + (jsoff_t) sizeof(next)); 782 + jsval_t val = loadval(js, next + (jsoff_t) (sizeof(next) + sizeof(koff))); 783 + scan_refs(js, val); 784 + next = loadoff(js, next) & ~(3U | CONSTMASK); 785 + } 786 + 787 + stringify_depth--; 788 + } 789 + 790 + static void scan_func_refs(struct js *js, jsval_t value) { 791 + jsval_t func_obj = mkval(T_OBJ, vdata(value)); 792 + 793 + if (is_on_stack(func_obj)) { 794 + mark_multiref(func_obj); 795 + return; 796 + } 797 + mark_multiref(func_obj); 798 + 799 + if (stringify_depth >= MAX_STRINGIFY_DEPTH) return; 800 + stringify_stack[stringify_depth++] = func_obj; 801 + 802 + jsoff_t next = loadoff(js, (jsoff_t) vdata(func_obj)) & ~(3U | CONSTMASK); 803 + while (next < js->brk && next != 0) { 804 + jsoff_t koff = loadoff(js, next + (jsoff_t) sizeof(next)); 805 + jsval_t val = loadval(js, next + (jsoff_t) (sizeof(next) + sizeof(koff))); 806 + scan_refs(js, val); 807 + next = loadoff(js, next) & ~(3U | CONSTMASK); 808 + } 809 + 810 + stringify_depth--; 811 + } 812 + 813 + static void scan_refs(struct js *js, jsval_t value) { 814 + switch (vtype(value)) { 815 + case T_OBJ: scan_obj_refs(js, value); break; 816 + case T_ARR: scan_arr_refs(js, value); break; 817 + case T_FUNC: scan_func_refs(js, value); break; 818 + default: break; 819 + } 820 + } 821 + 822 + static int get_circular_ref(jsval_t obj) { 823 + if (is_on_stack(obj)) { 824 + return find_multiref(obj); 825 + } 826 + return 0; 827 + } 828 + 829 + static bool is_circular(jsval_t obj) { 830 + return is_on_stack(obj); 831 + } 832 + 833 + static int get_self_ref(jsval_t obj) { 834 + return find_multiref(obj); 835 + } 836 + 717 837 static void push_stringify(jsval_t obj) { 718 838 if (stringify_depth < MAX_STRINGIFY_DEPTH) { 719 839 stringify_stack[stringify_depth++] = obj; ··· 724 844 if (stringify_depth > 0) stringify_depth--; 725 845 } 726 846 847 + static size_t add_indent(char *buf, size_t len, int level) { 848 + size_t n = 0; 849 + for (int i = 0; i < level * 2 && n < len; i++) { 850 + buf[n++] = ' '; 851 + } 852 + return n; 853 + } 854 + 727 855 static size_t strbigint(struct js *js, jsval_t value, char *buf, size_t len); 728 856 729 857 static size_t strarr(struct js *js, jsval_t obj, char *buf, size_t len) { 730 - if (is_circular(obj)) return cpy(buf, len, "[Circular]", 10); 858 + int ref = get_circular_ref(obj); 859 + if (ref) return (size_t) snprintf(buf, len, "[Circular *%d]", ref); 731 860 732 861 push_stringify(obj); 733 - size_t n = cpy(buf, len, "[", 1); 862 + size_t n = cpy(buf, len, "[ ", 2); 734 863 jsoff_t next = loadoff(js, (jsoff_t) vdata(obj)) & ~(3U | CONSTMASK); 735 864 jsoff_t length = 0; 736 865 jsoff_t scan = next; ··· 749 878 } 750 879 751 880 for (jsoff_t i = 0; i < length; i++) { 752 - if (i > 0) n += cpy(buf + n, len - n, ",", 1); 881 + if (i > 0) n += cpy(buf + n, len - n, ", ", 2); 753 882 char idx[16]; 754 883 snprintf(idx, sizeof(idx), "%u", (unsigned) i); 755 884 ··· 778 907 } 779 908 } 780 909 781 - n += cpy(buf + n, len - n, "]", 1); 910 + n += cpy(buf + n, len - n, " ]", 2); 782 911 pop_stringify(); 783 912 return n; 784 913 } ··· 870 999 return (size_t) snprintf(buf, len, "%s GMT%+03d%02d (%s)", date_part, offset_hours, offset_mins, tz_name); 871 1000 } 872 1001 1002 + static jsoff_t vstr(struct js *js, jsval_t value, jsoff_t *len); 1003 + static size_t strstring(struct js *js, jsval_t value, char *buf, size_t len); 1004 + 1005 + static bool is_valid_identifier(const char *str, jsoff_t slen) { 1006 + if (slen == 0) return false; 1007 + char c = str[0]; 1008 + if (!((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_' || c == '$')) return false; 1009 + for (jsoff_t i = 1; i < slen; i++) { 1010 + c = str[i]; 1011 + if (!((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || c == '_' || c == '$')) return false; 1012 + } 1013 + return true; 1014 + } 1015 + 1016 + static size_t strkey(struct js *js, jsval_t value, char *buf, size_t len) { 1017 + jsoff_t slen, off = vstr(js, value, &slen); 1018 + const char *str = (const char *) &js->mem[off]; 1019 + if (is_valid_identifier(str, slen)) { 1020 + return cpy(buf, len, str, slen); 1021 + } 1022 + return strstring(js, value, buf, len); 1023 + } 1024 + 873 1025 static size_t strobj(struct js *js, jsval_t obj, char *buf, size_t len) { 874 1026 jsoff_t time_off = lkp(js, obj, "__time", 6); 875 1027 if (time_off != 0) return strdate(js, obj, buf, len); 876 1028 877 - if (is_circular(obj)) return cpy(buf, len, "[Circular]", 10); 1029 + int ref = get_circular_ref(obj); 1030 + if (ref) return (size_t) snprintf(buf, len, "[Circular *%d]", ref); 878 1031 879 1032 push_stringify(obj); 880 - size_t n = cpy(buf, len, "{", 1); 1033 + 1034 + size_t n = 0; 1035 + int self_ref = get_self_ref(obj); 1036 + if (self_ref) { 1037 + n += (size_t) snprintf(buf + n, len - n, "<ref *%d> ", self_ref); 1038 + } 1039 + 1040 + jsoff_t tag_off = lkp(js, obj, "@@toStringTag", 13); 1041 + if (tag_off != 0) { 1042 + jsval_t tag_val = resolveprop(js, mkval(T_PROP, tag_off)); 1043 + if (vtype(tag_val) == T_STR) { 1044 + jsoff_t tlen, toff = vstr(js, tag_val, &tlen); 1045 + n += cpy(buf + n, len - n, "Object [", 8); 1046 + n += cpy(buf + n, len - n, (const char *) &js->mem[toff], tlen); 1047 + n += cpy(buf + n, len - n, "] {\n", 4); 1048 + } else { 1049 + n += cpy(buf + n, len - n, "{\n", 2); 1050 + } 1051 + } else { 1052 + n += cpy(buf + n, len - n, "{\n", 2); 1053 + } 1054 + 1055 + stringify_indent++; 881 1056 jsoff_t next = loadoff(js, (jsoff_t) vdata(obj)) & ~(3U | CONSTMASK); 1057 + bool first = true; 882 1058 883 1059 while (next < js->brk && next != 0) { 884 1060 jsoff_t koff = loadoff(js, next + (jsoff_t) sizeof(next)); 885 1061 jsoff_t klen = offtolen(loadoff(js, koff)); 886 1062 const char *key = (char *) &js->mem[koff + sizeof(koff)]; 887 - if (!streq(key, klen, "__proto__", 9)) { 1063 + if (!streq(key, klen, "__proto__", 9) && !streq(key, klen, "@@toStringTag", 13) && !streq(key, klen, "__getter", 8)) { 888 1064 jsval_t val = loadval(js, next + (jsoff_t) (sizeof(next) + sizeof(koff))); 889 - n += cpy(buf + n, len - n, ",", n == 1 ? 0 : 1); 890 - n += tostr(js, mkval(T_STR, koff), buf + n, len - n); 891 - n += cpy(buf + n, len - n, ":", 1); 1065 + if (!first) n += cpy(buf + n, len - n, ",\n", 2); 1066 + first = false; 1067 + n += add_indent(buf + n, len - n, stringify_indent); 1068 + n += strkey(js, mkval(T_STR, koff), buf + n, len - n); 1069 + n += cpy(buf + n, len - n, ": ", 2); 892 1070 n += tostr(js, val, buf + n, len - n); 893 1071 } 894 1072 next = loadoff(js, next) & ~(3U | CONSTMASK); 895 1073 } 896 1074 1075 + stringify_indent--; 1076 + if (!first) n += cpy(buf + n, len - n, "\n", 1); 1077 + n += add_indent(buf + n, len - n, stringify_indent); 897 1078 n += cpy(buf + n, len - n, "}", 1); 898 1079 pop_stringify(); 899 1080 return n; ··· 950 1131 } 951 1132 952 1133 static size_t strfunc_ctor(struct js *js, jsval_t func_obj, char *buf, size_t len) { 953 - if (is_circular(func_obj)) return cpy(buf, len, "[Circular]", 10); 1134 + int ref = get_circular_ref(func_obj); 1135 + if (ref) return (size_t) snprintf(buf, len, "[Circular *%d]", ref); 954 1136 push_stringify(func_obj); 955 1137 956 - size_t n = cpy(buf, len, "{", 1); 1138 + size_t n = cpy(buf, len, "{\n", 2); 1139 + stringify_indent++; 957 1140 bool first = true; 958 1141 959 1142 jsoff_t next = loadoff(js, (jsoff_t) vdata(func_obj)) & ~(3U | CONSTMASK); ··· 964 1147 jsoff_t klen = offtolen(loadoff(js, koff)); 965 1148 const char *kstr = (const char *) &js->mem[koff + sizeof(jsoff_t)]; 966 1149 967 - if (!is_internal_prop(kstr, klen)) { 968 - n += cpy(buf + n, len - n, first ? "" : ",", first ? 0 : 1); 1150 + if (!is_internal_prop(kstr, klen) && !streq(kstr, klen, "name", 4) && !streq(kstr, klen, "@@toStringTag", 13) && !streq(kstr, klen, "__getter", 8)) { 1151 + if (!first) n += cpy(buf + n, len - n, ",\n", 2); 969 1152 first = false; 970 - n += tostr(js, mkval(T_STR, koff), buf + n, len - n); 971 - n += cpy(buf + n, len - n, ":", 1); 1153 + n += add_indent(buf + n, len - n, stringify_indent); 1154 + n += strkey(js, mkval(T_STR, koff), buf + n, len - n); 1155 + n += cpy(buf + n, len - n, ": ", 2); 972 1156 n += tostr(js, val, buf + n, len - n); 973 1157 } 974 1158 next = loadoff(js, next) & ~(3U | CONSTMASK); ··· 986 1170 jsoff_t pklen = offtolen(loadoff(js, pkoff)); 987 1171 const char *pkstr = (const char *) &js->mem[pkoff + sizeof(jsoff_t)]; 988 1172 989 - if (!is_internal_prop(pkstr, pklen)) { 990 - n += cpy(buf + n, len - n, first ? "" : ",", first ? 0 : 1); 1173 + if (!is_internal_prop(pkstr, pklen) && !streq(pkstr, pklen, "name", 4) && !streq(pkstr, pklen, "@@toStringTag", 13) && !streq(pkstr, pklen, "__getter", 8)) { 1174 + if (!first) n += cpy(buf + n, len - n, ",\n", 2); 991 1175 first = false; 992 - n += tostr(js, mkval(T_STR, pkoff), buf + n, len - n); 993 - n += cpy(buf + n, len - n, ":", 1); 1176 + n += add_indent(buf + n, len - n, stringify_indent); 1177 + n += strkey(js, mkval(T_STR, pkoff), buf + n, len - n); 1178 + n += cpy(buf + n, len - n, ": ", 2); 994 1179 n += tostr(js, pval, buf + n, len - n); 995 1180 } 996 1181 proto_next = loadoff(js, proto_next) & ~(3U | CONSTMASK); ··· 998 1183 } 999 1184 } 1000 1185 1186 + stringify_indent--; 1187 + if (!first) n += cpy(buf + n, len - n, "\n", 1); 1188 + n += add_indent(buf + n, len - n, stringify_indent); 1001 1189 n += cpy(buf + n, len - n, "}", 1); 1002 1190 pop_stringify(); 1003 1191 return n; ··· 1007 1195 jsval_t func_obj = mkval(T_OBJ, vdata(value)); 1008 1196 jsoff_t code_off = lkp(js, func_obj, "__code", 6); 1009 1197 1198 + jsoff_t name_off = lkp(js, func_obj, "name", 4); 1199 + const char *name = NULL; 1200 + jsoff_t name_len = 0; 1201 + if (name_off != 0) { 1202 + jsval_t name_val = resolveprop(js, mkval(T_PROP, name_off)); 1203 + if (vtype(name_val) == T_STR) { 1204 + name_len = 0; 1205 + jsoff_t noff = vstr(js, name_val, &name_len); 1206 + name = (const char *) &js->mem[noff]; 1207 + } 1208 + } 1209 + 1010 1210 if (code_off == 0) { 1011 1211 jsoff_t native_off = lkp(js, func_obj, "__native_func", 13); 1012 1212 if (native_off != 0) { 1013 1213 jsval_t native_val = resolveprop(js, mkval(T_PROP, native_off)); 1014 1214 if (vtype(native_val) == T_CFUNC) return strfunc_ctor(js, func_obj, buf, len); 1015 1215 } 1016 - return cpy(buf, len, "function()", 10); 1216 + if (name && name_len > 0) { 1217 + size_t n = cpy(buf, len, "[Function: ", 11); 1218 + n += cpy(buf + n, len - n, name, name_len); 1219 + n += cpy(buf + n, len - n, "]", 1); 1220 + return n; 1221 + } 1222 + return cpy(buf, len, "[Function (anonymous)]", 22); 1017 1223 } 1018 1224 jsval_t code_val = resolveprop(js, mkval(T_PROP, code_off)); 1019 1225 1020 - if (vtype(code_val) != T_STR) return cpy(buf, len, "function()", 10); 1226 + if (vtype(code_val) != T_STR) { 1227 + if (name && name_len > 0) { 1228 + size_t n = cpy(buf, len, "[Function: ", 11); 1229 + n += cpy(buf + n, len - n, name, name_len); 1230 + n += cpy(buf + n, len - n, "]", 1); 1231 + return n; 1232 + } 1233 + return cpy(buf, len, "[Function (anonymous)]", 22); 1234 + } 1021 1235 1022 1236 jsoff_t sn, off = vstr(js, code_val, &sn); 1023 1237 if (sn >= 9 && memcmp(&js->mem[off], "__builtin", 9) == 0) { 1024 1238 return strfunc_ctor(js, func_obj, buf, len); 1025 1239 } 1026 1240 1027 - size_t n = cpy(buf, len, "function", 8); 1028 - return n + cpy(buf + n, len - n, (char *) &js->mem[off], sn); 1241 + if (name && name_len > 0) { 1242 + size_t n = cpy(buf, len, "[Function: ", 11); 1243 + n += cpy(buf + n, len - n, name, name_len); 1244 + n += cpy(buf + n, len - n, "]", 1); 1245 + return n; 1246 + } 1247 + return cpy(buf, len, "[Function (anonymous)]", 22); 1029 1248 } 1030 1249 1031 1250 static void get_line_col(const char *code, jsoff_t pos, int *line, int *col) { ··· 1188 1407 case T_BIGINT: return strbigint(js, value, buf, len); 1189 1408 case T_PROMISE: return strpromise(js, value, buf, len); 1190 1409 case T_FUNC: return strfunc(js, value, buf, len); 1191 - case T_CFUNC: return (size_t) snprintf(buf, len, "\"c_func_0x%lx\"", (unsigned long) vdata(value)); 1410 + case T_CFUNC: return cpy(buf, len, "[Function (native)]", 19); 1192 1411 case T_PROP: return (size_t) snprintf(buf, len, "PROP@%lu", (unsigned long) vdata(value)); 1193 1412 default: return (size_t) snprintf(buf, len, "VTYPE%d", vtype(value)); 1194 1413 } ··· 1201 1420 if (is_err(value)) return js->errmsg; 1202 1421 if (js->brk + sizeof(jsoff_t) >= js->size) return ""; 1203 1422 1423 + multiref_count = 0; 1424 + multiref_next_id = 0; 1204 1425 stringify_depth = 0; 1426 + scan_refs(js, value); 1427 + 1428 + stringify_depth = 0; 1429 + stringify_indent = 0; 1205 1430 len = tostr(js, value, buf, available); 1206 1431 js_mkstr(js, NULL, len); 1207 1432 return buf;
+13 -2
src/main.c
··· 32 32 const char *script = eval->sval[0]; 33 33 size_t len = strlen(script); 34 34 35 - js_set_filename(js, "<eval>"); 35 + js_set_filename(js, "[eval]"); 36 36 js_mkscope(js); 37 37 js_protect_init_memory(js); 38 + 39 + js_set(js, js_glob(js), "__dirname", js_mkstr(js, ".", 1)); 40 + js_set(js, js_glob(js), "__filename", js_mkstr(js, "[eval]", 6)); 38 41 39 42 jsval_t result = js_eval(js, script, len); 40 43 ··· 43 46 js_result = EXIT_FAILURE; 44 47 } else if (print->count > 0) { 45 48 const char *str = js_str(js, result); 46 - if (str && strcmp(str, "undefined") != 0) printf("%s\n", str); 49 + if (str && strcmp(str, "undefined") != 0) { 50 + print_value_colored(str, stdout); 51 + printf("\n"); 52 + } 47 53 } 48 54 49 55 js_run_event_loop(js); ··· 54 60 char *dir = dirname(filename_copy); 55 61 56 62 js_set(js, js_glob(js), "__dirname", js_mkstr(js, dir, strlen(dir))); 63 + js_set(js, js_glob(js), "__filename", js_mkstr(js, filename, strlen(filename))); 64 + 57 65 free(filename_copy); 58 66 59 67 FILE *fp = fopen(filename, "rb"); ··· 155 163 if (gct->count > 0) js_setgct(js, gct->ival[0]); 156 164 157 165 ant_runtime_init(js); 166 + 167 + js_set(js, js_glob(js), "global", js_glob(js)); 168 + js_set(js, js_glob(js), "globalThis", js_glob(js)); 158 169 159 170 init_builtin_module(); 160 171 init_buffer_module();
+160 -3
src/modules/io.c
··· 2 2 #include <stdlib.h> 3 3 #include <string.h> 4 4 #include <stdbool.h> 5 + #include <ctype.h> 5 6 #include <libgen.h> 6 7 7 8 #include "runtime.h" ··· 17 18 #define JSON_BOOL "\x1b[35m" 18 19 #define JSON_NULL "\x1b[90m" 19 20 #define JSON_BRACE "\x1b[37m" 21 + #define JSON_FUNC "\x1b[36m" 22 + #define JSON_TAG "\x1b[34m" 23 + #define JSON_REF "\x1b[90m" 20 24 21 25 static void print_json_colored(const char *json, FILE *stream) { 22 26 bool in_string = false; ··· 106 110 } 107 111 } 108 112 113 + void print_value_colored(const char *str, FILE *stream) { 114 + bool in_string = false; 115 + bool escape_next = false; 116 + bool is_key = true; 117 + int bracket_depth = 0; 118 + 119 + for (const char *p = str; *p; p++) { 120 + if (escape_next) { 121 + fputc(*p, stream); 122 + escape_next = false; 123 + continue; 124 + } 125 + 126 + if (*p == '\\' && in_string) { 127 + fputc(*p, stream); 128 + escape_next = true; 129 + continue; 130 + } 131 + 132 + if (*p == '"') { 133 + if (!in_string) { 134 + fprintf(stream, "%s\"", is_key ? JSON_KEY : JSON_STRING); 135 + in_string = true; 136 + } else { 137 + fprintf(stream, "\"%s", ANSI_RESET); 138 + in_string = false; 139 + } 140 + continue; 141 + } 142 + 143 + if (in_string) { 144 + fputc(*p, stream); 145 + continue; 146 + } 147 + 148 + if (*p == '[' && strncmp(p, "[Function", 9) == 0) { 149 + fprintf(stream, "%s", JSON_FUNC); 150 + while (*p && *p != ']') fputc(*p++, stream); 151 + if (*p == ']') fputc(*p, stream); 152 + fprintf(stream, "%s", ANSI_RESET); 153 + continue; 154 + } 155 + 156 + if (*p == '[' && strncmp(p, "[Circular", 9) == 0) { 157 + fprintf(stream, "%s", JSON_REF); 158 + while (*p && *p != ']') fputc(*p++, stream); 159 + if (*p == ']') fputc(*p, stream); 160 + fprintf(stream, "%s", ANSI_RESET); 161 + continue; 162 + } 163 + 164 + if (*p == '<' && strncmp(p, "<ref", 4) == 0) { 165 + fprintf(stream, "%s", JSON_REF); 166 + while (*p && *p != '>') fputc(*p++, stream); 167 + if (*p == '>') fputc(*p, stream); 168 + fprintf(stream, "%s", ANSI_RESET); 169 + continue; 170 + } 171 + 172 + if (strncmp(p, "Object [", 8) == 0) { 173 + fprintf(stream, "%sObject [", JSON_TAG); 174 + p += 7; 175 + while (*p && *p != ']') fputc(*++p, stream); 176 + fprintf(stream, "%s", ANSI_RESET); 177 + continue; 178 + } 179 + 180 + if (*p == ':') { 181 + fputc(*p, stream); 182 + is_key = false; 183 + continue; 184 + } 185 + 186 + if (*p == ',' || *p == '\n') { 187 + fputc(*p, stream); 188 + is_key = true; 189 + continue; 190 + } 191 + 192 + if (*p == '{' || *p == '[') { 193 + fprintf(stream, "%s%c%s", JSON_BRACE, *p, ANSI_RESET); 194 + bracket_depth++; 195 + is_key = true; 196 + continue; 197 + } 198 + 199 + if (*p == '}' || *p == ']') { 200 + fprintf(stream, "%s%c%s", JSON_BRACE, *p, ANSI_RESET); 201 + bracket_depth--; 202 + continue; 203 + } 204 + 205 + if (strncmp(p, "true", 4) == 0 && !isalnum((unsigned char)p[4]) && p[4] != '_') { 206 + fprintf(stream, "%strue%s", JSON_BOOL, ANSI_RESET); 207 + p += 3; 208 + continue; 209 + } 210 + 211 + if (strncmp(p, "false", 5) == 0 && !isalnum((unsigned char)p[5]) && p[5] != '_') { 212 + fprintf(stream, "%sfalse%s", JSON_BOOL, ANSI_RESET); 213 + p += 4; 214 + continue; 215 + } 216 + 217 + if (strncmp(p, "null", 4) == 0 && !isalnum((unsigned char)p[4]) && p[4] != '_') { 218 + fprintf(stream, "%snull%s", JSON_NULL, ANSI_RESET); 219 + p += 3; 220 + continue; 221 + } 222 + 223 + if (strncmp(p, "undefined", 9) == 0 && !isalnum((unsigned char)p[9]) && p[9] != '_') { 224 + fprintf(stream, "%sundefined%s", JSON_NULL, ANSI_RESET); 225 + p += 8; 226 + continue; 227 + } 228 + 229 + if (strncmp(p, "Infinity", 8) == 0) { 230 + fprintf(stream, "%sInfinity%s", JSON_NUMBER, ANSI_RESET); 231 + p += 7; 232 + continue; 233 + } 234 + 235 + if (strncmp(p, "NaN", 3) == 0 && !isalnum((unsigned char)p[3]) && p[3] != '_') { 236 + fprintf(stream, "%sNaN%s", JSON_NUMBER, ANSI_RESET); 237 + p += 2; 238 + continue; 239 + } 240 + 241 + if ((*p >= '0' && *p <= '9') || (*p == '-' && p[1] >= '0' && p[1] <= '9')) { 242 + fprintf(stream, "%s", JSON_NUMBER); 243 + if (*p == '-') fputc(*p++, stream); 244 + while ((*p >= '0' && *p <= '9') || *p == '.' || *p == 'e' || *p == 'E' || *p == '+' || *p == '-') { 245 + fputc(*p, stream); 246 + if (!((p[1] >= '0' && p[1] <= '9') || p[1] == '.' || p[1] == 'e' || p[1] == 'E' || p[1] == '+' || p[1] == '-')) break; 247 + p++; 248 + } 249 + fprintf(stream, "%s", ANSI_RESET); 250 + continue; 251 + } 252 + 253 + if (is_key && bracket_depth > 0 && (isalpha((unsigned char)*p) || *p == '_' || *p == '$')) { 254 + fprintf(stream, "%s", JSON_KEY); 255 + while (isalnum((unsigned char)*p) || *p == '_' || *p == '$') { 256 + fputc(*p, stream); 257 + if (!(isalnum((unsigned char)p[1]) || p[1] == '_' || p[1] == '$')) break; 258 + p++; 259 + } 260 + fprintf(stream, "%s", ANSI_RESET); 261 + continue; 262 + } 263 + 264 + fputc(*p, stream); 265 + } 266 + } 267 + 109 268 static void console_print(struct js *js, jsval_t *args, int nargs, const char *color, FILE *stream) { 110 269 if (color) fprintf(stream, "%s", color); 111 270 ··· 122 281 if (color) fprintf(stream, "%s", ANSI_RESET); 123 282 print_json_colored(str, stream); 124 283 if (color) fprintf(stream, "%s", color); 125 - } else { 126 - fprintf(stream, "%s", str); 127 - } 284 + } else print_value_colored(str, stdout); 128 285 } 129 286 } 130 287
+27
src/modules/process.c
··· 87 87 return js_mkundef(); 88 88 } 89 89 90 + static jsval_t env_to_object(struct js *js, jsval_t *args, int nargs) { 91 + (void)args; 92 + (void)nargs; 93 + 94 + jsval_t obj = js_mkobj(js); 95 + 96 + for (char **env = environ; *env != NULL; env++) { 97 + char *entry = *env; 98 + char *equals = strchr(entry, '='); 99 + if (equals == NULL) continue; 100 + 101 + size_t key_len = (size_t)(equals - entry); 102 + char *value = equals + 1; 103 + 104 + char *key = malloc(key_len + 1); 105 + if (!key) continue; 106 + memcpy(key, entry, key_len); 107 + key[key_len] = '\0'; 108 + 109 + js_set(js, obj, key, js_mkstr(js, value, strlen(value))); 110 + free(key); 111 + } 112 + 113 + return obj; 114 + } 115 + 90 116 void init_process_module(void) { 91 117 struct js *js = rt->js; 92 118 ··· 127 153 128 154 load_dotenv_file(js, env_obj); 129 155 js_set_getter(js, env_obj, env_getter); 156 + js_set(js, env_obj, "toObject", js_mkfun(env_to_object)); 130 157 131 158 js_set(js, process_obj, "@@toStringTag", js_mkstr(js, "process", 7)); 132 159 js_set(js, js_glob(js), "process", process_obj);
+5 -1
src/repl.c
··· 10 10 #include "repl.h" 11 11 #include "config.h" 12 12 #include "runtime.h" 13 + #include "modules/io.h" 13 14 14 15 #define MAX_HISTORY 100 15 16 #define MAX_LINE_LENGTH 4096 ··· 208 209 history_init(&history); 209 210 210 211 js_set(js, js_glob(js), "__dirname", js_mkstr(js, ".", 1)); 212 + js_set(js, js_glob(js), "__filename", js_mkstr(js, "[repl]", 6)); 213 + 211 214 int prev_ctrl_c_count = 0; 212 215 213 216 while (1) { ··· 325 328 326 329 if (js_type(eval_result) == JS_ERR) fprintf(stderr, "%s\n", js_str(js, eval_result)); else { 327 330 const char *str = js_str(js, eval_result); 328 - printf("%s\n", str); 331 + print_value_colored(str, stdout); 332 + printf("\n"); 329 333 } 330 334 331 335 free(line);