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.

migrate to process module

+1017 -478
+103
examples/spec/process.js
··· 16 16 17 17 test('argv is array', Array.isArray(process.argv), true); 18 18 test('argv has entries', process.argv.length >= 1, true); 19 + test('execArgv is array', Array.isArray(process.execArgv), true); 20 + test('argv0 is string', typeof process.argv0, 'string'); 21 + test('execPath is string', typeof process.execPath, 'string'); 22 + test('ppid is number', typeof process.ppid, 'number'); 23 + test('ppid is positive', process.ppid > 0, true); 19 24 20 25 test('cwd is function', typeof process.cwd, 'function'); 21 26 const cwd = process.cwd(); ··· 113 118 test('supports many listeners', process.listenerCount('manyListeners'), 15); 114 119 process.removeAllListeners('manyListeners'); 115 120 process.setMaxListeners(10); 121 + 122 + test('stdin is object', typeof process.stdin, 'object'); 123 + test('stdin.isTTY is boolean', typeof process.stdin.isTTY, 'boolean'); 124 + test('stdin.setRawMode is function', typeof process.stdin.setRawMode, 'function'); 125 + test('stdin.resume is function', typeof process.stdin.resume, 'function'); 126 + test('stdin.pause is function', typeof process.stdin.pause, 'function'); 127 + test('stdin.on is function', typeof process.stdin.on, 'function'); 128 + test('stdin.removeAllListeners is function', typeof process.stdin.removeAllListeners, 'function'); 129 + 130 + test('stdout is object', typeof process.stdout, 'object'); 131 + test('stdout.isTTY is boolean', typeof process.stdout.isTTY, 'boolean'); 132 + test('stdout.rows is number', typeof process.stdout.rows, 'number'); 133 + test('stdout.columns is number', typeof process.stdout.columns, 'number'); 134 + test('stdout.write is function', typeof process.stdout.write, 'function'); 135 + test('stdout.on is function', typeof process.stdout.on, 'function'); 136 + test('stdout.once is function', typeof process.stdout.once, 'function'); 137 + test('stdout.removeAllListeners is function', typeof process.stdout.removeAllListeners, 'function'); 138 + test('stdout.getWindowSize is function', typeof process.stdout.getWindowSize, 'function'); 139 + 140 + const windowSize = process.stdout.getWindowSize(); 141 + test('getWindowSize returns array', Array.isArray(windowSize), true); 142 + test('getWindowSize has 2 elements', windowSize.length, 2); 143 + test('getWindowSize cols is number', typeof windowSize[0], 'number'); 144 + test('getWindowSize rows is number', typeof windowSize[1], 'number'); 145 + 146 + test('stderr is object', typeof process.stderr, 'object'); 147 + test('stderr.isTTY is boolean', typeof process.stderr.isTTY, 'boolean'); 148 + test('stderr.write is function', typeof process.stderr.write, 'function'); 149 + test('stderr.on is function', typeof process.stderr.on, 'function'); 150 + test('stderr.once is function', typeof process.stderr.once, 'function'); 151 + test('stderr.removeAllListeners is function', typeof process.stderr.removeAllListeners, 'function'); 152 + 153 + test('version is string', typeof process.version, 'string'); 154 + test('version starts with v', process.version.startsWith('v'), true); 155 + 156 + test('versions is object', typeof process.versions, 'object'); 157 + test('versions.ant exists', typeof process.versions.ant, 'string'); 158 + test('versions.uv exists', typeof process.versions.uv, 'string'); 159 + 160 + test('release is object', typeof process.release, 'object'); 161 + test('release.name is string', typeof process.release.name, 'string'); 162 + 163 + test('uptime is function', typeof process.uptime, 'function'); 164 + const uptime = process.uptime(); 165 + test('uptime returns number', typeof uptime, 'number'); 166 + test('uptime is non-negative', uptime >= 0, true); 167 + 168 + test('memoryUsage is function', typeof process.memoryUsage, 'function'); 169 + const mem = process.memoryUsage(); 170 + test('memoryUsage returns object', typeof mem, 'object'); 171 + test('memoryUsage.rss is number', typeof mem.rss, 'number'); 172 + test('memoryUsage.heapTotal is number', typeof mem.heapTotal, 'number'); 173 + test('memoryUsage.heapUsed is number', typeof mem.heapUsed, 'number'); 174 + test('memoryUsage.rss method exists', typeof process.memoryUsage.rss, 'function'); 175 + test('memoryUsage.rss returns number', typeof process.memoryUsage.rss(), 'number'); 176 + 177 + test('cpuUsage is function', typeof process.cpuUsage, 'function'); 178 + const cpu = process.cpuUsage(); 179 + test('cpuUsage returns object', typeof cpu, 'object'); 180 + test('cpuUsage.user is number', typeof cpu.user, 'number'); 181 + test('cpuUsage.system is number', typeof cpu.system, 'number'); 182 + 183 + test('hrtime is function', typeof process.hrtime, 'function'); 184 + const hr = process.hrtime(); 185 + test('hrtime returns array', Array.isArray(hr), true); 186 + test('hrtime has 2 elements', hr.length, 2); 187 + test('hrtime[0] is number', typeof hr[0], 'number'); 188 + test('hrtime[1] is number', typeof hr[1], 'number'); 189 + 190 + test('hrtime.bigint is function', typeof process.hrtime.bigint, 'function'); 191 + const hrBigint = process.hrtime.bigint(); 192 + test('hrtime.bigint returns bigint', typeof hrBigint, 'bigint'); 193 + 194 + test('kill is function', typeof process.kill, 'function'); 195 + test('abort is function', typeof process.abort, 'function'); 196 + test('chdir is function', typeof process.chdir, 'function'); 197 + test('umask is function', typeof process.umask, 'function'); 198 + 199 + const oldMask = process.umask(); 200 + test('umask returns number', typeof oldMask, 'number'); 201 + 202 + if (process.platform !== 'win32') { 203 + test('getuid is function', typeof process.getuid, 'function'); 204 + test('geteuid is function', typeof process.geteuid, 'function'); 205 + test('getgid is function', typeof process.getgid, 'function'); 206 + test('getegid is function', typeof process.getegid, 'function'); 207 + test('getgroups is function', typeof process.getgroups, 'function'); 208 + test('setuid is function', typeof process.setuid, 'function'); 209 + test('setgid is function', typeof process.setgid, 'function'); 210 + test('seteuid is function', typeof process.seteuid, 'function'); 211 + test('setegid is function', typeof process.setegid, 'function'); 212 + test('setgroups is function', typeof process.setgroups, 'function'); 213 + test('initgroups is function', typeof process.initgroups, 'function'); 214 + 215 + test('getuid returns number', typeof process.getuid(), 'number'); 216 + test('getgid returns number', typeof process.getgid(), 'number'); 217 + test('getgroups returns array', Array.isArray(process.getgroups()), true); 218 + } 116 219 117 220 summary();
-2
examples/test262/index.js
··· 1 - import 'readline'; 2 - 3 1 import fs from 'fs'; 4 2 import { join } from 'ant:path'; 5 3
+1
include/ant.h
··· 105 105 jsval_t js_mkarr(ant_t *); 106 106 void js_arr_push(ant_t *, jsval_t arr, jsval_t val); 107 107 jsval_t js_mkstr(ant_t *, const void *, size_t); 108 + jsval_t js_mkbigint(ant_t *, const char *digits, size_t len, bool negative); 108 109 jsval_t js_mksym(ant_t *, const char *desc); 109 110 jsval_t js_mkfun(jsval_t (*fn)(ant_t *, jsval_t *, int)); 110 111 jsval_t js_heavy_mkfun(ant_t *js, jsval_t (*fn)(ant_t *, jsval_t *, int), jsval_t data);
+37 -37
src/ant.c
··· 2790 2790 return mkentity(js, (jsoff_t) ((n << 2) | T_STR), ptr, n); 2791 2791 } 2792 2792 2793 - static jsval_t mkbigint(struct js *js, const char *digits, size_t len, bool negative) { 2793 + jsval_t js_mkbigint(struct js *js, const char *digits, size_t len, bool negative) { 2794 2794 size_t total = len + 2; 2795 2795 jsoff_t ofs = js_alloc(js, total + sizeof(jsoff_t)); 2796 2796 if (ofs == (jsoff_t) ~0) return js_mkerr(js, "oom"); ··· 2938 2938 } 2939 2939 if (!result) return js_mkerr(js, "oom"); 2940 2940 if (rlen == 1 && result[0] == '0') rneg = false; 2941 - jsval_t r = mkbigint(js, result, rlen, rneg); 2941 + jsval_t r = js_mkbigint(js, result, rlen, rneg); 2942 2942 free(result); 2943 2943 return r; 2944 2944 } ··· 2957 2957 } 2958 2958 if (!result) return js_mkerr(js, "oom"); 2959 2959 if (rlen == 1 && result[0] == '0') rneg = false; 2960 - jsval_t r = mkbigint(js, result, rlen, rneg); 2960 + jsval_t r = js_mkbigint(js, result, rlen, rneg); 2961 2961 free(result); 2962 2962 return r; 2963 2963 } ··· 2970 2970 char *result = bigint_mul_abs(ad, alen, bd, blen, &rlen); 2971 2971 if (!result) return js_mkerr(js, "oom"); 2972 2972 bool rneg = (aneg != bneg) && !(rlen == 1 && result[0] == '0'); 2973 - jsval_t r = mkbigint(js, result, rlen, rneg); 2973 + jsval_t r = js_mkbigint(js, result, rlen, rneg); 2974 2974 free(result); 2975 2975 return r; 2976 2976 } ··· 2984 2984 char *result = bigint_div_abs(ad, alen, bd, blen, &rlen, NULL, NULL); 2985 2985 if (!result) return js_mkerr(js, "oom"); 2986 2986 bool rneg = (aneg != bneg) && !(rlen == 1 && result[0] == '0'); 2987 - jsval_t r = mkbigint(js, result, rlen, rneg); 2987 + jsval_t r = js_mkbigint(js, result, rlen, rneg); 2988 2988 free(result); 2989 2989 return r; 2990 2990 } ··· 2999 2999 if (!result) return js_mkerr(js, "oom"); 3000 3000 free(result); 3001 3001 bool rneg = aneg && !(remlen == 1 && rem[0] == '0'); 3002 - jsval_t r = mkbigint(js, rem, remlen, rneg); 3002 + jsval_t r = js_mkbigint(js, rem, remlen, rneg); 3003 3003 free(rem); 3004 3004 return r; 3005 3005 } ··· 3008 3008 size_t len; 3009 3009 const char *digits = bigint_digits(js, a, &len); 3010 3010 bool neg = bigint_IsNegative(js, a); 3011 - if (len == 1 && digits[0] == '0') return mkbigint(js, digits, len, false); 3012 - return mkbigint(js, digits, len, !neg); 3011 + if (len == 1 && digits[0] == '0') return js_mkbigint(js, digits, len, false); 3012 + return js_mkbigint(js, digits, len, !neg); 3013 3013 } 3014 3014 3015 3015 static jsval_t bigint_exp(struct js *js, jsval_t base, jsval_t exp) { 3016 3016 if (bigint_IsNegative(js, exp)) return js_mkerr(js, "Exponent must be positive"); 3017 3017 size_t explen; 3018 3018 const char *expd = bigint_digits(js, exp, &explen); 3019 - if (explen == 1 && expd[0] == '0') return mkbigint(js, "1", 1, false); 3020 - jsval_t result = mkbigint(js, "1", 1, false); 3019 + if (explen == 1 && expd[0] == '0') return js_mkbigint(js, "1", 1, false); 3020 + jsval_t result = js_mkbigint(js, "1", 1, false); 3021 3021 jsval_t b = base; 3022 3022 jsval_t e = exp; 3023 - jsval_t two = mkbigint(js, "2", 1, false); 3023 + jsval_t two = js_mkbigint(js, "2", 1, false); 3024 3024 while (true) { 3025 3025 size_t elen; 3026 3026 const char *ed = bigint_digits(js, e, &elen); ··· 3066 3066 3067 3067 static jsval_t builtin_BigInt(struct js *js, jsval_t *args, int nargs) { 3068 3068 if (vtype(js->new_target) != T_UNDEF) return js_mkerr_typed(js, JS_ERR_TYPE, "BigInt is not a constructor"); 3069 - if (nargs < 1) return mkbigint(js, "0", 1, false); 3069 + if (nargs < 1) return js_mkbigint(js, "0", 1, false); 3070 3070 3071 3071 jsval_t arg = args[0]; 3072 3072 if (vtype(arg) == T_BIGINT) return arg; ··· 3078 3078 if (neg) d = -d; 3079 3079 char buf[64]; 3080 3080 snprintf(buf, sizeof(buf), "%.0f", d); 3081 - return mkbigint(js, buf, strlen(buf), neg); 3081 + return js_mkbigint(js, buf, strlen(buf), neg); 3082 3082 } 3083 3083 if (vtype(arg) == T_STR) { 3084 3084 jsoff_t slen, off = vstr(js, arg, &slen); ··· 3088 3088 if (slen > 0 && str[0] == '-') { neg = true; i++; } 3089 3089 else if (slen > 0 && str[0] == '+') { i++; } 3090 3090 while (i < slen && str[i] == '0') i++; 3091 - if (i >= slen) return mkbigint(js, "0", 1, false); 3091 + if (i >= slen) return js_mkbigint(js, "0", 1, false); 3092 3092 for (size_t j = i; j < slen; j++) { 3093 3093 if (!is_digit(str[j])) return js_mkerr(js, "Cannot convert string to BigInt"); 3094 3094 } 3095 - return mkbigint(js, str + i, slen - i, neg); 3095 + return js_mkbigint(js, str + i, slen - i, neg); 3096 3096 } 3097 3097 if (vtype(arg) == T_BOOL) { 3098 - return mkbigint(js, vdata(arg) ? "1" : "0", 1, false); 3098 + return js_mkbigint(js, vdata(arg) ? "1" : "0", 1, false); 3099 3099 } 3100 3100 return js_mkerr(js, "Cannot convert to BigInt"); 3101 3101 } ··· 7464 7464 if (neg) num_val = -num_val; 7465 7465 char buf[64]; 7466 7466 snprintf(buf, sizeof(buf), "%.0f", num_val); 7467 - eq = bigint_compare(js, bigint_val, mkbigint(js, buf, strlen(buf), neg)) == 0; 7467 + eq = bigint_compare(js, bigint_val, js_mkbigint(js, buf, strlen(buf), neg)) == 0; 7468 7468 } 7469 7469 } else if (lt == T_BOOL) { 7470 7470 return do_op(js, op, tov(vdata(l) ? 1.0 : 0.0), r); ··· 7893 7893 while (len > 1 && start[0] == '0') { start++; len--; } 7894 7894 bool neg = false; 7895 7895 if (len > 0 && start[0] == '-') { neg = true; start++; len--; } 7896 - return mkbigint(js, start, len, neg); 7896 + return js_mkbigint(js, start, len, neg); 7897 7897 } 7898 7898 7899 7899 static jsval_t js_arr_destruct_assign(struct js *js) { ··· 19355 19355 return result; 19356 19356 } 19357 19357 19358 + static const int8_t decode_table[256] = { 19359 + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, 19360 + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, 19361 + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,62,-1,-1,-1,63, 19362 + 52,53,54,55,56,57,58,59,60,61,-1,-1,-1,-1,-1,-1, 19363 + -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14, 19364 + 15,16,17,18,19,20,21,22,23,24,25,-1,-1,-1,-1,-1, 19365 + -1,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40, 19366 + 41,42,43,44,45,46,47,48,49,50,51,-1,-1,-1,-1,-1, 19367 + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, 19368 + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, 19369 + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, 19370 + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, 19371 + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, 19372 + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, 19373 + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, 19374 + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1 19375 + }; 19376 + 19358 19377 static jsval_t builtin_atob(struct js *js, jsval_t *args, int nargs) { 19359 19378 if (nargs < 1) return js_mkerr(js, "atob requires 1 argument"); 19360 19379 ··· 19376 19395 19377 19396 char *out = (char *)ANT_GC_MALLOC(out_len + 1); 19378 19397 if (!out) return js_mkerr(js, "out of memory"); 19379 - 19380 - static const int8_t decode_table[256] = { 19381 - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, 19382 - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, 19383 - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,62,-1,-1,-1,63, 19384 - 52,53,54,55,56,57,58,59,60,61,-1,-1,-1,-1,-1,-1, 19385 - -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14, 19386 - 15,16,17,18,19,20,21,22,23,24,25,-1,-1,-1,-1,-1, 19387 - -1,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40, 19388 - 41,42,43,44,45,46,47,48,49,50,51,-1,-1,-1,-1,-1, 19389 - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, 19390 - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, 19391 - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, 19392 - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, 19393 - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, 19394 - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, 19395 - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, 19396 - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1 19397 - }; 19398 19398 19399 19399 size_t i = 0, j = 0; 19400 19400 while (i < str_len) {
+876 -5
src/modules/process.c
··· 4 4 #include <stdio.h> 5 5 #include <string.h> 6 6 #include <signal.h> 7 + #include <time.h> 7 8 #include <uthash.h> 9 + #include <uv.h> 10 + 11 + #ifdef _WIN32 12 + #include <windows.h> 13 + #include <io.h> 14 + #include <psapi.h> 15 + #define STDIN_FILENO 0 16 + #define STDOUT_FILENO 1 17 + #define STDERR_FILENO 2 18 + #else 19 + #include <termios.h> 20 + #include <unistd.h> 21 + #include <sys/ioctl.h> 22 + #include <sys/time.h> 23 + #include <sys/resource.h> 24 + #include <sys/stat.h> 25 + #include <grp.h> 26 + #include <pwd.h> 27 + #endif 8 28 9 29 #include "ant.h" 30 + #include "config.h" 31 + #include "internal.h" 10 32 #include "runtime.h" 11 33 #include "modules/process.h" 12 34 #include "modules/symbol.h" ··· 31 53 32 54 static int max_listeners = DEFAULT_MAX_LISTENERS; 33 55 static ProcessEventType *process_events = NULL; 56 + 57 + static ProcessEventType *stdin_events = NULL; 58 + static ProcessEventType *stdout_events = NULL; 59 + static ProcessEventType *stderr_events = NULL; 60 + static uv_tty_t stdin_tty; 61 + static uv_signal_t sigwinch_handle; 62 + static bool stdin_tty_initialized = false; 63 + static bool stdin_reading = false; 64 + static bool sigwinch_initialized = false; 65 + static uint64_t process_start_time = 0; 66 + 67 + #ifndef _WIN32 68 + static struct termios stdin_saved_termios; 69 + static bool stdin_raw_mode = false; 70 + #endif 34 71 35 72 #define SIGNAL_LIST \ 36 73 X(SIGHUP) X(SIGINT) X(SIGQUIT) X(SIGILL) X(SIGTRAP) X(SIGABRT) \ ··· 147 184 } 148 185 } 149 186 187 + static ProcessEventType *find_or_create_stdin_event(const char *event_type) { 188 + ProcessEventType *evt = NULL; 189 + HASH_FIND_STR(stdin_events, event_type, evt); 190 + if (evt == NULL) { 191 + evt = malloc(sizeof(ProcessEventType)); 192 + evt->event_type = strdup(event_type); 193 + evt->listener_count = 0; 194 + evt->listener_capacity = INITIAL_LISTENER_CAPACITY; 195 + evt->listeners = malloc(sizeof(ProcessEventListener) * evt->listener_capacity); 196 + HASH_ADD_KEYPTR(hh, stdin_events, evt->event_type, strlen(evt->event_type), evt); 197 + } 198 + return evt; 199 + } 200 + 201 + static ProcessEventType *find_or_create_stdout_event(const char *event_type) { 202 + ProcessEventType *evt = NULL; 203 + HASH_FIND_STR(stdout_events, event_type, evt); 204 + if (evt == NULL) { 205 + evt = malloc(sizeof(ProcessEventType)); 206 + evt->event_type = strdup(event_type); 207 + evt->listener_count = 0; 208 + evt->listener_capacity = INITIAL_LISTENER_CAPACITY; 209 + evt->listeners = malloc(sizeof(ProcessEventListener) * evt->listener_capacity); 210 + HASH_ADD_KEYPTR(hh, stdout_events, evt->event_type, strlen(evt->event_type), evt); 211 + } 212 + return evt; 213 + } 214 + 215 + static void emit_stdio_event(ProcessEventType *events, const char *event_type, jsval_t *args, int nargs) { 216 + if (!rt->js) return; 217 + ProcessEventType *evt = NULL; 218 + HASH_FIND_STR(events, event_type, evt); 219 + if (evt == NULL || evt->listener_count == 0) return; 220 + 221 + int i = 0; 222 + while (i < evt->listener_count) { 223 + ProcessEventListener *listener = &evt->listeners[i]; 224 + js_call(rt->js, listener->listener, args, nargs); 225 + if (listener->once) { 226 + for (int j = i; j < evt->listener_count - 1; j++) { 227 + evt->listeners[j] = evt->listeners[j + 1]; 228 + } 229 + evt->listener_count--; 230 + } else i++; 231 + } 232 + } 233 + 234 + static bool stdin_is_tty(void) { 235 + return uv_guess_handle(STDIN_FILENO) == UV_TTY; 236 + } 237 + 238 + static bool stdout_is_tty(void) { 239 + return uv_guess_handle(STDOUT_FILENO) == UV_TTY; 240 + } 241 + 242 + static bool stderr_is_tty(void) { 243 + return uv_guess_handle(STDERR_FILENO) == UV_TTY; 244 + } 245 + 246 + static void get_tty_size(int fd, int *rows, int *cols) { 247 + int out_rows = 24, out_cols = 80; 248 + #ifndef _WIN32 249 + struct winsize ws; 250 + if (ioctl(fd, TIOCGWINSZ, &ws) == 0) { 251 + if (ws.ws_row > 0) out_rows = ws.ws_row; 252 + if (ws.ws_col > 0) out_cols = ws.ws_col; 253 + } 254 + #else 255 + CONSOLE_SCREEN_BUFFER_INFO csbi; 256 + if (GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi)) { 257 + int width = csbi.srWindow.Right - csbi.srWindow.Left + 1; 258 + int height = csbi.srWindow.Bottom - csbi.srWindow.Top + 1; 259 + if (height > 0) out_rows = height; 260 + if (width > 0) out_cols = width; 261 + } 262 + #endif 263 + if (rows) *rows = out_rows; 264 + if (cols) *cols = out_cols; 265 + } 266 + 267 + #ifndef _WIN32 268 + static bool stdin_set_raw_mode(bool enable) { 269 + if (!stdin_is_tty()) return false; 270 + if (enable) { 271 + if (stdin_raw_mode) return true; 272 + if (tcgetattr(STDIN_FILENO, &stdin_saved_termios) == -1) return false; 273 + struct termios raw = stdin_saved_termios; 274 + raw.c_lflag &= ~(ICANON | ECHO | ISIG); 275 + raw.c_cc[VMIN] = 1; 276 + raw.c_cc[VTIME] = 0; 277 + if (tcsetattr(STDIN_FILENO, TCSANOW, &raw) == -1) return false; 278 + stdin_raw_mode = true; 279 + return true; 280 + } 281 + if (!stdin_raw_mode) return true; 282 + if (tcsetattr(STDIN_FILENO, TCSANOW, &stdin_saved_termios) == -1) return false; 283 + stdin_raw_mode = false; 284 + return true; 285 + } 286 + #else 287 + static bool stdin_set_raw_mode(bool enable) { 288 + (void)enable; 289 + return false; 290 + } 291 + #endif 292 + 293 + static void stdin_alloc_buffer(uv_handle_t *handle, size_t suggested_size, uv_buf_t *buf) { 294 + (void)handle; 295 + buf->base = malloc(suggested_size); 296 + buf->len = suggested_size; 297 + } 298 + 299 + static void on_stdin_read(uv_stream_t *stream, ssize_t nread, const uv_buf_t *buf) { 300 + (void)stream; 301 + if (nread > 0 && rt->js) { 302 + jsval_t data_val = js_mkstr(rt->js, buf->base, (size_t)nread); 303 + emit_stdio_event(stdin_events, "data", &data_val, 1); 304 + } 305 + if (buf->base) free(buf->base); 306 + } 307 + 308 + static void stdin_start_reading(void) { 309 + if (stdin_reading) return; 310 + if (!stdin_tty_initialized) { 311 + uv_loop_t *loop = uv_default_loop(); 312 + if (uv_tty_init(loop, &stdin_tty, STDIN_FILENO, 1) != 0) return; 313 + #ifndef _WIN32 314 + uv_tty_set_mode(&stdin_tty, stdin_raw_mode ? UV_TTY_MODE_RAW : UV_TTY_MODE_NORMAL); 315 + #endif 316 + stdin_tty.data = NULL; 317 + stdin_tty_initialized = true; 318 + } else { 319 + #ifndef _WIN32 320 + uv_tty_set_mode(&stdin_tty, stdin_raw_mode ? UV_TTY_MODE_RAW : UV_TTY_MODE_NORMAL); 321 + #endif 322 + } 323 + stdin_reading = true; 324 + uv_read_start((uv_stream_t *)&stdin_tty, stdin_alloc_buffer, on_stdin_read); 325 + } 326 + 327 + static void stdin_stop_reading(void) { 328 + if (!stdin_reading) return; 329 + uv_read_stop((uv_stream_t *)&stdin_tty); 330 + stdin_reading = false; 331 + } 332 + 333 + #ifndef _WIN32 334 + static void on_sigwinch(uv_signal_t *handle, int signum) { 335 + (void)handle; (void)signum; 336 + if (!rt->js) return; 337 + 338 + jsval_t process_obj = js_get(rt->js, js_glob(rt->js), "process"); 339 + if (js_type(process_obj) != JS_OBJ) return; 340 + 341 + jsval_t stdout_obj = js_get(rt->js, process_obj, "stdout"); 342 + if (js_type(stdout_obj) != JS_OBJ) return; 343 + 344 + int rows = 0, cols = 0; 345 + get_tty_size(STDOUT_FILENO, &rows, &cols); 346 + js_set(rt->js, stdout_obj, "rows", js_mknum(rows)); 347 + js_set(rt->js, stdout_obj, "columns", js_mknum(cols)); 348 + 349 + emit_stdio_event(stdout_events, "resize", NULL, 0); 350 + } 351 + #endif 352 + 353 + static void start_sigwinch_handler(void) { 354 + #ifndef _WIN32 355 + if (sigwinch_initialized) return; 356 + uv_loop_t *loop = uv_default_loop(); 357 + if (uv_signal_init(loop, &sigwinch_handle) != 0) return; 358 + if (uv_signal_start(&sigwinch_handle, on_sigwinch, SIGWINCH) != 0) { 359 + uv_close((uv_handle_t *)&sigwinch_handle, NULL); 360 + return; 361 + } 362 + uv_unref((uv_handle_t *)&sigwinch_handle); 363 + sigwinch_initialized = true; 364 + #endif 365 + } 366 + 367 + static jsval_t js_stdin_set_raw_mode(ant_t *js, jsval_t *args, int nargs) { 368 + bool enable = nargs > 0 ? js_truthy(js, args[0]) : true; 369 + return stdin_set_raw_mode(enable) ? js_mktrue() : js_mkfalse(); 370 + } 371 + 372 + static jsval_t js_stdin_resume(ant_t *js, jsval_t *args, int nargs) { 373 + (void)args; (void)nargs; 374 + stdin_start_reading(); 375 + return js_getthis(js); 376 + } 377 + 378 + static jsval_t js_stdin_pause(ant_t *js, jsval_t *args, int nargs) { 379 + (void)args; (void)nargs; 380 + stdin_stop_reading(); 381 + return js_getthis(js); 382 + } 383 + 384 + static jsval_t js_stdin_on(ant_t *js, jsval_t *args, int nargs) { 385 + jsval_t this_obj = js_getthis(js); 386 + if (nargs < 2) return this_obj; 387 + 388 + char *event = js_getstr(js, args[0], NULL); 389 + if (!event || js_type(args[1]) != JS_FUNC) return this_obj; 390 + 391 + ProcessEventType *evt = find_or_create_stdin_event(event); 392 + if (!ensure_listener_capacity(evt)) return this_obj; 393 + 394 + evt->listeners[evt->listener_count].listener = args[1]; 395 + evt->listeners[evt->listener_count].once = false; 396 + evt->listener_count++; 397 + 398 + if (strcmp(event, "data") == 0) stdin_start_reading(); 399 + 400 + return this_obj; 401 + } 402 + 403 + static jsval_t js_stdin_remove_all_listeners(ant_t *js, jsval_t *args, int nargs) { 404 + jsval_t this_obj = js_getthis(js); 405 + 406 + if (nargs < 1) { 407 + ProcessEventType *evt, *tmp; 408 + HASH_ITER(hh, stdin_events, evt, tmp) { 409 + evt->listener_count = 0; 410 + } 411 + stdin_stop_reading(); 412 + return this_obj; 413 + } 414 + 415 + char *event = js_getstr(js, args[0], NULL); 416 + if (!event) return this_obj; 417 + 418 + ProcessEventType *evt = NULL; 419 + HASH_FIND_STR(stdin_events, event, evt); 420 + if (evt) evt->listener_count = 0; 421 + if (strcmp(event, "data") == 0) stdin_stop_reading(); 422 + 423 + return this_obj; 424 + } 425 + 426 + static jsval_t js_stdout_write(ant_t *js, jsval_t *args, int nargs) { 427 + if (nargs < 1) return js_mkfalse(); 428 + size_t len = 0; 429 + char *data = js_getstr(js, args[0], &len); 430 + if (!data) return js_mkfalse(); 431 + fwrite(data, 1, len, stdout); 432 + fflush(stdout); 433 + return js_mktrue(); 434 + } 435 + 436 + static jsval_t js_stdout_on(ant_t *js, jsval_t *args, int nargs) { 437 + jsval_t this_obj = js_getthis(js); 438 + if (nargs < 2) return this_obj; 439 + 440 + char *event = js_getstr(js, args[0], NULL); 441 + if (!event || js_type(args[1]) != JS_FUNC) return this_obj; 442 + 443 + ProcessEventType *evt = find_or_create_stdout_event(event); 444 + if (!ensure_listener_capacity(evt)) return this_obj; 445 + 446 + evt->listeners[evt->listener_count].listener = args[1]; 447 + evt->listeners[evt->listener_count].once = false; 448 + evt->listener_count++; 449 + 450 + if (strcmp(event, "resize") == 0) start_sigwinch_handler(); 451 + 452 + return this_obj; 453 + } 454 + 455 + static jsval_t js_stdout_once(ant_t *js, jsval_t *args, int nargs) { 456 + jsval_t this_obj = js_getthis(js); 457 + if (nargs < 2) return this_obj; 458 + 459 + char *event = js_getstr(js, args[0], NULL); 460 + if (!event || js_type(args[1]) != JS_FUNC) return this_obj; 461 + 462 + ProcessEventType *evt = find_or_create_stdout_event(event); 463 + if (!ensure_listener_capacity(evt)) return this_obj; 464 + 465 + evt->listeners[evt->listener_count].listener = args[1]; 466 + evt->listeners[evt->listener_count].once = true; 467 + evt->listener_count++; 468 + 469 + if (strcmp(event, "resize") == 0) start_sigwinch_handler(); 470 + 471 + return this_obj; 472 + } 473 + 474 + static jsval_t js_stdout_remove_all_listeners(ant_t *js, jsval_t *args, int nargs) { 475 + jsval_t this_obj = js_getthis(js); 476 + 477 + if (nargs < 1) { 478 + ProcessEventType *evt, *tmp; 479 + HASH_ITER(hh, stdout_events, evt, tmp) { 480 + evt->listener_count = 0; 481 + } 482 + return this_obj; 483 + } 484 + 485 + char *event = js_getstr(js, args[0], NULL); 486 + if (!event) return this_obj; 487 + 488 + ProcessEventType *evt = NULL; 489 + HASH_FIND_STR(stdout_events, event, evt); 490 + if (evt) evt->listener_count = 0; 491 + 492 + return this_obj; 493 + } 494 + 495 + static jsval_t js_stdout_get_window_size(ant_t *js, jsval_t *args, int nargs) { 496 + (void)args; (void)nargs; 497 + int rows = 0, cols = 0; 498 + get_tty_size(STDOUT_FILENO, &rows, &cols); 499 + jsval_t arr = js_mkarr(js); 500 + js_arr_push(js, arr, js_mknum(cols)); 501 + js_arr_push(js, arr, js_mknum(rows)); 502 + return arr; 503 + } 504 + 505 + static jsval_t js_stdout_rows_getter(ant_t *js, jsval_t *args, int nargs) { 506 + (void)args; (void)nargs; 507 + int rows = 0, cols = 0; 508 + get_tty_size(STDOUT_FILENO, &rows, &cols); 509 + return js_mknum(rows); 510 + } 511 + 512 + static jsval_t js_stdout_columns_getter(ant_t *js, jsval_t *args, int nargs) { 513 + (void)args; (void)nargs; 514 + int rows = 0, cols = 0; 515 + get_tty_size(STDOUT_FILENO, &rows, &cols); 516 + return js_mknum(cols); 517 + } 518 + 519 + static ProcessEventType *find_or_create_stderr_event(const char *event_type) { 520 + ProcessEventType *evt = NULL; 521 + HASH_FIND_STR(stderr_events, event_type, evt); 522 + if (evt == NULL) { 523 + evt = malloc(sizeof(ProcessEventType)); 524 + evt->event_type = strdup(event_type); 525 + evt->listener_count = 0; 526 + evt->listener_capacity = INITIAL_LISTENER_CAPACITY; 527 + evt->listeners = malloc(sizeof(ProcessEventListener) * evt->listener_capacity); 528 + HASH_ADD_KEYPTR(hh, stderr_events, evt->event_type, strlen(evt->event_type), evt); 529 + } 530 + return evt; 531 + } 532 + 533 + static jsval_t js_stderr_write(ant_t *js, jsval_t *args, int nargs) { 534 + if (nargs < 1) return js_mkfalse(); 535 + size_t len = 0; 536 + char *data = js_getstr(js, args[0], &len); 537 + if (!data) return js_mkfalse(); 538 + fwrite(data, 1, len, stderr); 539 + fflush(stderr); 540 + return js_mktrue(); 541 + } 542 + 543 + static jsval_t js_stderr_on(ant_t *js, jsval_t *args, int nargs) { 544 + jsval_t this_obj = js_getthis(js); 545 + if (nargs < 2) return this_obj; 546 + 547 + char *event = js_getstr(js, args[0], NULL); 548 + if (!event || js_type(args[1]) != JS_FUNC) return this_obj; 549 + 550 + ProcessEventType *evt = find_or_create_stderr_event(event); 551 + if (!ensure_listener_capacity(evt)) return this_obj; 552 + 553 + evt->listeners[evt->listener_count].listener = args[1]; 554 + evt->listeners[evt->listener_count].once = false; 555 + evt->listener_count++; 556 + 557 + return this_obj; 558 + } 559 + 560 + static jsval_t js_stderr_once(ant_t *js, jsval_t *args, int nargs) { 561 + jsval_t this_obj = js_getthis(js); 562 + if (nargs < 2) return this_obj; 563 + 564 + char *event = js_getstr(js, args[0], NULL); 565 + if (!event || js_type(args[1]) != JS_FUNC) return this_obj; 566 + 567 + ProcessEventType *evt = find_or_create_stderr_event(event); 568 + if (!ensure_listener_capacity(evt)) return this_obj; 569 + 570 + evt->listeners[evt->listener_count].listener = args[1]; 571 + evt->listeners[evt->listener_count].once = true; 572 + evt->listener_count++; 573 + 574 + return this_obj; 575 + } 576 + 577 + static jsval_t js_stderr_remove_all_listeners(ant_t *js, jsval_t *args, int nargs) { 578 + jsval_t this_obj = js_getthis(js); 579 + 580 + if (nargs < 1) { 581 + ProcessEventType *evt, *tmp; 582 + HASH_ITER(hh, stderr_events, evt, tmp) { 583 + evt->listener_count = 0; 584 + } 585 + return this_obj; 586 + } 587 + 588 + char *event = js_getstr(js, args[0], NULL); 589 + if (!event) return this_obj; 590 + 591 + ProcessEventType *evt = NULL; 592 + HASH_FIND_STR(stderr_events, event, evt); 593 + if (evt) evt->listener_count = 0; 594 + 595 + return this_obj; 596 + } 597 + 598 + static jsval_t process_uptime(ant_t *js, jsval_t *args, int nargs) { 599 + (void)args; (void)nargs; 600 + uint64_t now = uv_hrtime(); 601 + double seconds = (double)(now - process_start_time) / 1e9; 602 + return js_mknum(seconds); 603 + } 604 + 605 + static jsval_t process_hrtime(ant_t *js, jsval_t *args, int nargs) { 606 + uint64_t now = uv_hrtime(); 607 + 608 + if (nargs > 0 && js_type(args[0]) == T_ARR) { 609 + jsval_t prev_sec = js_get(js, args[0], "0"); 610 + jsval_t prev_nsec = js_get(js, args[0], "1"); 611 + if (js_type(prev_sec) == JS_NUM && js_type(prev_nsec) == JS_NUM) { 612 + uint64_t prev = (uint64_t)js_getnum(prev_sec) * 1000000000ULL + (uint64_t)js_getnum(prev_nsec); 613 + now = now - prev; 614 + } 615 + } 616 + 617 + jsval_t arr = js_mkarr(js); 618 + 619 + uint64_t secs = now / 1000000000ULL; 620 + uint64_t nsecs = now % 1000000000ULL; 621 + 622 + js_arr_push(js, arr, js_mknum((double)secs)); 623 + js_arr_push(js, arr, js_mknum((double)nsecs)); 624 + 625 + return arr; 626 + } 627 + 628 + static jsval_t process_hrtime_bigint(ant_t *js, jsval_t *args, int nargs) { 629 + (void)args; (void)nargs; 630 + uint64_t now = uv_hrtime(); 631 + char buf[32]; 632 + snprintf(buf, sizeof(buf), "%llu", (unsigned long long)now); 633 + return js_mkbigint(js, buf, strlen(buf), false); 634 + } 635 + 636 + static jsval_t process_memory_usage(ant_t *js, jsval_t *args, int nargs) { 637 + (void)args; (void)nargs; 638 + jsval_t obj = js_mkobj(js); 639 + 640 + size_t rss = 0; 641 + uv_resident_set_memory(&rss); 642 + js_set(js, obj, "rss", js_mknum((double)rss)); 643 + 644 + #ifdef _WIN32 645 + PROCESS_MEMORY_COUNTERS_EX pmc; 646 + if (GetProcessMemoryInfo(GetCurrentProcess(), (PROCESS_MEMORY_COUNTERS*)&pmc, sizeof(pmc))) { 647 + js_set(js, obj, "heapTotal", js_mknum((double)pmc.WorkingSetSize)); 648 + js_set(js, obj, "heapUsed", js_mknum((double)pmc.PrivateUsage)); 649 + } else { 650 + js_set(js, obj, "heapTotal", js_mknum(0)); 651 + js_set(js, obj, "heapUsed", js_mknum(0)); 652 + } 653 + #else 654 + struct rusage usage; 655 + if (getrusage(RUSAGE_SELF, &usage) == 0) { 656 + js_set(js, obj, "heapTotal", js_mknum((double)rss)); 657 + js_set(js, obj, "heapUsed", js_mknum((double)rss)); 658 + } else { 659 + js_set(js, obj, "heapTotal", js_mknum(0)); 660 + js_set(js, obj, "heapUsed", js_mknum(0)); 661 + } 662 + #endif 663 + 664 + js_set(js, obj, "external", js_mknum(0)); 665 + js_set(js, obj, "arrayBuffers", js_mknum(0)); 666 + 667 + return obj; 668 + } 669 + 670 + static jsval_t process_memory_usage_rss(ant_t *js, jsval_t *args, int nargs) { 671 + (void)args; (void)nargs; 672 + size_t rss = 0; 673 + uv_resident_set_memory(&rss); 674 + return js_mknum((double)rss); 675 + } 676 + 677 + static jsval_t process_cpu_usage(ant_t *js, jsval_t *args, int nargs) { 678 + jsval_t obj = js_mkobj(js); 679 + uv_rusage_t rusage; 680 + 681 + if (uv_getrusage(&rusage) == 0) { 682 + int64_t user_usec = rusage.ru_utime.tv_sec * 1000000LL + rusage.ru_utime.tv_usec; 683 + int64_t sys_usec = rusage.ru_stime.tv_sec * 1000000LL + rusage.ru_stime.tv_usec; 684 + 685 + if (nargs > 0 && js_type(args[0]) == JS_OBJ) { 686 + jsval_t prev_user = js_get(js, args[0], "user"); 687 + jsval_t prev_system = js_get(js, args[0], "system"); 688 + if (js_type(prev_user) == JS_NUM) user_usec -= (int64_t)js_getnum(prev_user); 689 + if (js_type(prev_system) == JS_NUM) sys_usec -= (int64_t)js_getnum(prev_system); 690 + } 691 + 692 + js_set(js, obj, "user", js_mknum((double)user_usec)); 693 + js_set(js, obj, "system", js_mknum((double)sys_usec)); 694 + } else { 695 + js_set(js, obj, "user", js_mknum(0)); 696 + js_set(js, obj, "system", js_mknum(0)); 697 + } 698 + 699 + return obj; 700 + } 701 + 702 + static jsval_t process_kill(ant_t *js, jsval_t *args, int nargs) { 703 + if (nargs < 1) return js_mkerr(js, "process.kill requires at least 1 argument"); 704 + if (js_type(args[0]) != JS_NUM) return js_mkerr(js, "pid must be a number"); 705 + 706 + int pid = (int)js_getnum(args[0]); 707 + int sig = SIGTERM; 708 + 709 + if (nargs > 1) { 710 + if (js_type(args[1]) == JS_NUM) { 711 + sig = (int)js_getnum(args[1]); 712 + } else if (js_type(args[1]) == JS_STR) { 713 + char *sig_name = js_getstr(js, args[1], NULL); 714 + if (sig_name) { 715 + int signum = get_signal_number(sig_name); 716 + if (signum > 0) sig = signum; 717 + else return js_mkerr(js, "Unknown signal"); 718 + } 719 + } 720 + } 721 + 722 + int result = uv_kill(pid, sig); 723 + if (result != 0) return js_mkerr(js, "Failed to send signal"); 724 + return js_mktrue(); 725 + } 726 + 727 + static jsval_t process_abort(ant_t *js, jsval_t *args, int nargs) { 728 + (void)js; (void)args; (void)nargs; 729 + abort(); 730 + return js_mkundef(); 731 + } 732 + 733 + static jsval_t process_chdir(ant_t *js, jsval_t *args, int nargs) { 734 + if (nargs < 1) return js_mkerr(js, "process.chdir requires 1 argument"); 735 + 736 + char *dir = js_getstr(js, args[0], NULL); 737 + if (!dir) return js_mkerr(js, "directory must be a string"); 738 + 739 + int result = uv_chdir(dir); 740 + if (result != 0) return js_mkerr(js, "ENOENT: no such file or directory, chdir"); 741 + return js_mkundef(); 742 + } 743 + 744 + static jsval_t process_umask(ant_t *js, jsval_t *args, int nargs) { 745 + #ifdef _WIN32 746 + (void)args; (void)nargs; 747 + return js_mknum(0); 748 + #else 749 + if (nargs > 0 && js_type(args[0]) == JS_NUM) { 750 + int new_mask = (int)js_getnum(args[0]); 751 + int old_mask = umask((mode_t)new_mask); 752 + return js_mknum(old_mask); 753 + } 754 + int cur = umask(0); 755 + umask((mode_t)cur); 756 + return js_mknum(cur); 757 + #endif 758 + } 759 + 760 + #ifndef _WIN32 761 + static jsval_t process_getuid(ant_t *js, jsval_t *args, int nargs) { 762 + (void)args; (void)nargs; 763 + return js_mknum((double)getuid()); 764 + } 765 + 766 + static jsval_t process_geteuid(ant_t *js, jsval_t *args, int nargs) { 767 + (void)args; (void)nargs; 768 + return js_mknum((double)geteuid()); 769 + } 770 + 771 + static jsval_t process_getgid(ant_t *js, jsval_t *args, int nargs) { 772 + (void)args; (void)nargs; 773 + return js_mknum((double)getgid()); 774 + } 775 + 776 + static jsval_t process_getegid(ant_t *js, jsval_t *args, int nargs) { 777 + (void)args; (void)nargs; 778 + return js_mknum((double)getegid()); 779 + } 780 + 781 + static jsval_t process_getgroups(ant_t *js, jsval_t *args, int nargs) { 782 + (void)args; (void)nargs; 783 + int ngroups = getgroups(0, NULL); 784 + if (ngroups < 0) return js_mkarr(js); 785 + 786 + gid_t *groups = malloc(sizeof(gid_t) * (size_t)ngroups); 787 + if (!groups) return js_mkarr(js); 788 + 789 + ngroups = getgroups(ngroups, groups); 790 + jsval_t arr = js_mkarr(js); 791 + for (int i = 0; i < ngroups; i++) { 792 + js_arr_push(js, arr, js_mknum((double)groups[i])); 793 + } 794 + free(groups); 795 + return arr; 796 + } 797 + 798 + static jsval_t process_setuid(ant_t *js, jsval_t *args, int nargs) { 799 + if (nargs < 1) return js_mkerr(js, "process.setuid requires 1 argument"); 800 + 801 + uid_t uid; 802 + if (js_type(args[0]) == JS_NUM) { 803 + uid = (uid_t)js_getnum(args[0]); 804 + } else if (js_type(args[0]) == JS_STR) { 805 + char *name = js_getstr(js, args[0], NULL); 806 + struct passwd *pwd = getpwnam(name); 807 + if (!pwd) return js_mkerr(js, "setuid user not found"); 808 + uid = pwd->pw_uid; 809 + } else { 810 + return js_mkerr(js, "uid must be a number or string"); 811 + } 812 + 813 + if (setuid(uid) != 0) return js_mkerr(js, "setuid failed"); 814 + return js_mkundef(); 815 + } 816 + 817 + static jsval_t process_setgid(ant_t *js, jsval_t *args, int nargs) { 818 + if (nargs < 1) return js_mkerr(js, "process.setgid requires 1 argument"); 819 + 820 + gid_t gid; 821 + if (js_type(args[0]) == JS_NUM) { 822 + gid = (gid_t)js_getnum(args[0]); 823 + } else if (js_type(args[0]) == JS_STR) { 824 + char *name = js_getstr(js, args[0], NULL); 825 + struct group *grp = getgrnam(name); 826 + if (!grp) return js_mkerr(js, "setgid group not found"); 827 + gid = grp->gr_gid; 828 + } else { 829 + return js_mkerr(js, "gid must be a number or string"); 830 + } 831 + 832 + if (setgid(gid) != 0) return js_mkerr(js, "setgid failed"); 833 + return js_mkundef(); 834 + } 835 + 836 + static jsval_t process_seteuid(ant_t *js, jsval_t *args, int nargs) { 837 + if (nargs < 1) return js_mkerr(js, "process.seteuid requires 1 argument"); 838 + 839 + uid_t uid; 840 + if (js_type(args[0]) == JS_NUM) { 841 + uid = (uid_t)js_getnum(args[0]); 842 + } else if (js_type(args[0]) == JS_STR) { 843 + char *name = js_getstr(js, args[0], NULL); 844 + struct passwd *pwd = getpwnam(name); 845 + if (!pwd) return js_mkerr(js, "seteuid user not found"); 846 + uid = pwd->pw_uid; 847 + } else { 848 + return js_mkerr(js, "uid must be a number or string"); 849 + } 850 + 851 + if (seteuid(uid) != 0) return js_mkerr(js, "seteuid failed"); 852 + return js_mkundef(); 853 + } 854 + 855 + static jsval_t process_setegid(ant_t *js, jsval_t *args, int nargs) { 856 + if (nargs < 1) return js_mkerr(js, "process.setegid requires 1 argument"); 857 + 858 + gid_t gid; 859 + if (js_type(args[0]) == JS_NUM) { 860 + gid = (gid_t)js_getnum(args[0]); 861 + } else if (js_type(args[0]) == JS_STR) { 862 + char *name = js_getstr(js, args[0], NULL); 863 + struct group *grp = getgrnam(name); 864 + if (!grp) return js_mkerr(js, "setegid group not found"); 865 + gid = grp->gr_gid; 866 + } else { 867 + return js_mkerr(js, "gid must be a number or string"); 868 + } 869 + 870 + if (setegid(gid) != 0) return js_mkerr(js, "setegid failed"); 871 + return js_mkundef(); 872 + } 873 + 874 + static jsval_t process_setgroups(ant_t *js, jsval_t *args, int nargs) { 875 + if (nargs < 1 || js_type(args[0]) != T_ARR) { 876 + return js_mkerr(js, "process.setgroups requires an array"); 877 + } 878 + 879 + jsval_t len_val = js_get(js, args[0], "length"); 880 + int len = (int)js_getnum(len_val); 881 + 882 + gid_t *groups = malloc(sizeof(gid_t) * (size_t)len); 883 + if (!groups) return js_mkerr(js, "allocation failed"); 884 + 885 + for (int i = 0; i < len; i++) { 886 + char idx[16]; 887 + snprintf(idx, sizeof(idx), "%d", i); 888 + jsval_t val = js_get(js, args[0], idx); 889 + if (js_type(val) == JS_NUM) { 890 + groups[i] = (gid_t)js_getnum(val); 891 + } else if (js_type(val) == JS_STR) { 892 + char *name = js_getstr(js, val, NULL); 893 + struct group *grp = getgrnam(name); 894 + if (!grp) { free(groups); return js_mkerr(js, "group not found"); } 895 + groups[i] = grp->gr_gid; 896 + } else { 897 + free(groups); 898 + return js_mkerr(js, "group id must be number or string"); 899 + } 900 + } 901 + 902 + if (setgroups(len, groups) != 0) { 903 + free(groups); 904 + return js_mkerr(js, "setgroups failed"); 905 + } 906 + free(groups); 907 + return js_mkundef(); 908 + } 909 + 910 + static jsval_t process_initgroups(ant_t *js, jsval_t *args, int nargs) { 911 + if (nargs < 2) return js_mkerr(js, "process.initgroups requires 2 arguments"); 912 + 913 + char *user = js_getstr(js, args[0], NULL); 914 + if (!user) return js_mkerr(js, "user must be a string"); 915 + 916 + gid_t gid; 917 + if (js_type(args[1]) == JS_NUM) { 918 + gid = (gid_t)js_getnum(args[1]); 919 + } else if (js_type(args[1]) == JS_STR) { 920 + char *name = js_getstr(js, args[1], NULL); 921 + struct group *grp = getgrnam(name); 922 + if (!grp) return js_mkerr(js, "group not found"); 923 + gid = grp->gr_gid; 924 + } else { 925 + return js_mkerr(js, "gid must be a number or string"); 926 + } 927 + 928 + if (initgroups(user, gid) != 0) return js_mkerr(js, "initgroups failed"); 929 + return js_mkundef(); 930 + } 931 + #endif 932 + 150 933 static jsval_t env_getter(ant_t *js, jsval_t obj, const char *key, size_t key_len) { 151 934 char *key_str = (char *)malloc(key_len + 1); 152 935 if (!key_str) return js_mkundef(); ··· 400 1183 void init_process_module() { 401 1184 ant_t *js = rt->js; 402 1185 1186 + process_start_time = uv_hrtime(); 1187 + 403 1188 jsval_t process_obj = js_mkobj(js); 404 1189 jsval_t env_obj = js_mkobj(js); 405 1190 jsval_t argv_arr = js_mkarr(js); ··· 419 1204 js_set(js, process_obj, "getMaxListeners", js_mkfun(process_get_max_listeners)); 420 1205 421 1206 js_set(js, process_obj, "pid", js_mknum((double)getpid())); 1207 + js_set(js, process_obj, "ppid", js_mknum((double)getppid())); 1208 + 1209 + char version_str[128]; 1210 + snprintf(version_str, sizeof(version_str), "v%s", ANT_VERSION); 1211 + js_set(js, process_obj, "version", js_mkstr(js, version_str, strlen(version_str))); 1212 + 1213 + jsval_t versions_obj = js_mkobj(js); 1214 + js_set(js, versions_obj, "ant", js_mkstr(js, ANT_VERSION, strlen(ANT_VERSION))); 1215 + char uv_ver[32]; 1216 + snprintf(uv_ver, sizeof(uv_ver), "%d.%d.%d", UV_VERSION_MAJOR, UV_VERSION_MINOR, UV_VERSION_PATCH); 1217 + js_set(js, versions_obj, "uv", js_mkstr(js, uv_ver, strlen(uv_ver))); 1218 + js_set(js, process_obj, "versions", versions_obj); 1219 + 1220 + jsval_t release_obj = js_mkobj(js); 1221 + js_set(js, release_obj, "name", js_mkstr(js, "ant", 3)); 1222 + js_set(js, process_obj, "release", release_obj); 422 1223 423 1224 // process.platform 424 1225 #if defined(__APPLE__) ··· 455 1256 } 456 1257 457 1258 js_set(js, process_obj, "argv", argv_arr); 1259 + js_set(js, process_obj, "execArgv", js_mkarr(js)); 458 1260 js_set(js, process_obj, "cwd", js_mkfun(process_cwd)); 1261 + js_set(js, process_obj, "chdir", js_mkfun(process_chdir)); 1262 + 1263 + js_set(js, process_obj, "argv0", rt->argc > 0 ? js_mkstr(js, rt->argv[0], strlen(rt->argv[0])) : js_mkstr(js, "ant", 3)); 1264 + js_set(js, process_obj, "execPath", rt->argc > 0 ? js_mkstr(js, rt->argv[0], strlen(rt->argv[0])) : js_mkundef()); 1265 + 1266 + js_set(js, process_obj, "uptime", js_mkfun(process_uptime)); 1267 + jsval_t mem_usage_fn = js_heavy_mkfun(js, process_memory_usage, js_mkundef()); 1268 + js_set(js, mem_usage_fn, "rss", js_mkfun(process_memory_usage_rss)); 1269 + js_set(js, process_obj, "memoryUsage", mem_usage_fn); 1270 + js_set(js, process_obj, "cpuUsage", js_mkfun(process_cpu_usage)); 1271 + 1272 + jsval_t hrtime_fn = js_heavy_mkfun(js, process_hrtime, js_mkundef()); 1273 + js_set(js, hrtime_fn, "bigint", js_mkfun(process_hrtime_bigint)); 1274 + js_set(js, process_obj, "hrtime", hrtime_fn); 1275 + 1276 + js_set(js, process_obj, "kill", js_mkfun(process_kill)); 1277 + js_set(js, process_obj, "abort", js_mkfun(process_abort)); 1278 + js_set(js, process_obj, "umask", js_mkfun(process_umask)); 1279 + 1280 + #ifndef _WIN32 1281 + js_set(js, process_obj, "getuid", js_mkfun(process_getuid)); 1282 + js_set(js, process_obj, "geteuid", js_mkfun(process_geteuid)); 1283 + js_set(js, process_obj, "getgid", js_mkfun(process_getgid)); 1284 + js_set(js, process_obj, "getegid", js_mkfun(process_getegid)); 1285 + js_set(js, process_obj, "getgroups", js_mkfun(process_getgroups)); 1286 + js_set(js, process_obj, "setuid", js_mkfun(process_setuid)); 1287 + js_set(js, process_obj, "setgid", js_mkfun(process_setgid)); 1288 + js_set(js, process_obj, "seteuid", js_mkfun(process_seteuid)); 1289 + js_set(js, process_obj, "setegid", js_mkfun(process_setegid)); 1290 + js_set(js, process_obj, "setgroups", js_mkfun(process_setgroups)); 1291 + js_set(js, process_obj, "initgroups", js_mkfun(process_initgroups)); 1292 + #endif 1293 + 1294 + jsval_t stdin_obj = js_mkobj(js); 1295 + js_set(js, stdin_obj, "isTTY", stdin_is_tty() ? js_mktrue() : js_mkfalse()); 1296 + js_set(js, stdin_obj, "setRawMode", js_mkfun(js_stdin_set_raw_mode)); 1297 + js_set(js, stdin_obj, "resume", js_mkfun(js_stdin_resume)); 1298 + js_set(js, stdin_obj, "pause", js_mkfun(js_stdin_pause)); 1299 + js_set(js, stdin_obj, "on", js_mkfun(js_stdin_on)); 1300 + js_set(js, stdin_obj, "removeAllListeners", js_mkfun(js_stdin_remove_all_listeners)); 1301 + js_set(js, process_obj, "stdin", stdin_obj); 1302 + 1303 + jsval_t stdout_obj = js_mkobj(js); 1304 + js_set(js, stdout_obj, "isTTY", stdout_is_tty() ? js_mktrue() : js_mkfalse()); 1305 + js_set(js, stdout_obj, "write", js_mkfun(js_stdout_write)); 1306 + js_set(js, stdout_obj, "on", js_mkfun(js_stdout_on)); 1307 + js_set(js, stdout_obj, "once", js_mkfun(js_stdout_once)); 1308 + js_set(js, stdout_obj, "removeAllListeners", js_mkfun(js_stdout_remove_all_listeners)); 1309 + js_set(js, stdout_obj, "getWindowSize", js_mkfun(js_stdout_get_window_size)); 1310 + js_set_getter_desc(js, stdout_obj, "rows", 4, js_mkfun(js_stdout_rows_getter), JS_DESC_E | JS_DESC_C); 1311 + js_set_getter_desc(js, stdout_obj, "columns", 7, js_mkfun(js_stdout_columns_getter), JS_DESC_E | JS_DESC_C); 1312 + js_set(js, process_obj, "stdout", stdout_obj); 1313 + 1314 + jsval_t stderr_obj = js_mkobj(js); 1315 + js_set(js, stderr_obj, "isTTY", stderr_is_tty() ? js_mktrue() : js_mkfalse()); 1316 + js_set(js, stderr_obj, "write", js_mkfun(js_stderr_write)); 1317 + js_set(js, stderr_obj, "on", js_mkfun(js_stderr_on)); 1318 + js_set(js, stderr_obj, "once", js_mkfun(js_stderr_once)); 1319 + js_set(js, stderr_obj, "removeAllListeners", js_mkfun(js_stderr_remove_all_listeners)); 1320 + js_set(js, process_obj, "stderr", stderr_obj); 459 1321 460 1322 js_set(js, process_obj, get_toStringTag_sym_key(), js_mkstr(js, "process", 7)); 461 1323 js_set(js, js_glob(js), "process", process_obj); 462 1324 } 463 1325 1326 + #define GC_FWD_EVENTS(events) do { \ 1327 + ProcessEventType *evt, *tmp; \ 1328 + HASH_ITER(hh, events, evt, tmp) { \ 1329 + for (int i = 0; i < evt->listener_count; i++) \ 1330 + evt->listeners[i].listener = fwd_val(ctx, evt->listeners[i].listener); \ 1331 + } \ 1332 + } while(0) 1333 + 464 1334 void process_gc_update_roots(GC_FWD_ARGS) { 465 - ProcessEventType *evt, *tmp; 466 - HASH_ITER(hh, process_events, evt, tmp) { 467 - for (int i = 0; i < evt->listener_count; i++) 468 - evt->listeners[i].listener = fwd_val(ctx, evt->listeners[i].listener); 469 - } 1335 + GC_FWD_EVENTS(process_events); 1336 + GC_FWD_EVENTS(stdin_events); 1337 + GC_FWD_EVENTS(stdout_events); 1338 + GC_FWD_EVENTS(stderr_events); 470 1339 } 1340 + 1341 + #undef GC_FWD_EVENTS
-434
src/modules/readline.c
··· 92 92 93 93 static rl_interface_t *interfaces = NULL; 94 94 static uint64_t next_interface_id = 1; 95 - static RLEventType *process_stdin_events = NULL; 96 - static RLEventType *process_stdout_events = NULL; 97 - static uv_tty_t process_tty_in; 98 - static uv_signal_t process_sigwinch; 99 - static bool process_tty_initialized = false; 100 - static bool process_tty_reading = false; 101 - static bool process_sigwinch_initialized = false; 102 - static struct js *process_stdin_js = NULL; 103 - static struct js *process_stdout_js = NULL; 104 95 105 96 static void rl_history_init(rl_history_t *hist, int capacity) { 106 97 hist->capacity = capacity > 0 ? capacity : DEFAULT_HISTORY_SIZE; ··· 213 204 214 205 static void alloc_buffer(uv_handle_t *handle, size_t suggested_size, uv_buf_t *buf); 215 206 static void on_stdin_read(uv_stream_t *stream, ssize_t nread, const uv_buf_t *buf); 216 - static void process_stdout_get_size(int *rows, int *cols); 217 - 218 - static RLEventType *find_or_create_process_event_type(const char *event_type) { 219 - RLEventType *evt = NULL; 220 - HASH_FIND_STR(process_stdin_events, event_type, evt); 221 - 222 - if (evt == NULL) { 223 - evt = malloc(sizeof(RLEventType)); 224 - evt->event_type = strdup(event_type); 225 - evt->listener_count = 0; 226 - HASH_ADD_KEYPTR(hh, process_stdin_events, evt->event_type, strlen(evt->event_type), evt); 227 - } 228 - 229 - return evt; 230 - } 231 - 232 - static void emit_process_event(struct js *js, const char *event_type, jsval_t *args, int nargs) { 233 - RLEventType *evt = NULL; 234 - HASH_FIND_STR(process_stdin_events, event_type, evt); 235 - 236 - if (evt == NULL || evt->listener_count == 0) return; 237 - 238 - int i = 0; 239 - while (i < evt->listener_count) { 240 - RLEventListener *listener = &evt->listeners[i]; 241 - js_call(js, listener->listener, args, nargs); 242 - 243 - if (listener->once) { 244 - for (int j = i; j < evt->listener_count - 1; j++) { 245 - evt->listeners[j] = evt->listeners[j + 1]; 246 - } 247 - evt->listener_count--; 248 - } else i++; 249 - } 250 - } 251 - 252 - static RLEventType *find_or_create_process_stdout_event_type(const char *event_type) { 253 - RLEventType *evt = NULL; 254 - HASH_FIND_STR(process_stdout_events, event_type, evt); 255 - 256 - if (evt == NULL) { 257 - evt = malloc(sizeof(RLEventType)); 258 - evt->event_type = strdup(event_type); 259 - evt->listener_count = 0; 260 - HASH_ADD_KEYPTR(hh, process_stdout_events, evt->event_type, strlen(evt->event_type), evt); 261 - } 262 - 263 - return evt; 264 - } 265 - 266 - static void emit_process_stdout_event(struct js *js, const char *event_type, jsval_t *args, int nargs) { 267 - RLEventType *evt = NULL; 268 - HASH_FIND_STR(process_stdout_events, event_type, evt); 269 - 270 - if (evt == NULL || evt->listener_count == 0) return; 271 - 272 - int i = 0; 273 - while (i < evt->listener_count) { 274 - RLEventListener *listener = &evt->listeners[i]; 275 - js_call(js, listener->listener, args, nargs); 276 - 277 - if (listener->once) { 278 - for (int j = i; j < evt->listener_count - 1; j++) { 279 - evt->listeners[j] = evt->listeners[j + 1]; 280 - } 281 - evt->listener_count--; 282 - } else i++; 283 - } 284 - } 285 - 286 - #ifndef _WIN32 287 - static void on_sigwinch(uv_signal_t *handle, int signum) { 288 - (void)handle; 289 - (void)signum; 290 - 291 - if (!process_stdout_js) return; 292 - 293 - struct js *js = process_stdout_js; 294 - jsval_t process_obj = js_get(js, js_glob(js), "process"); 295 - if (js_type(process_obj) != JS_OBJ) return; 296 - 297 - jsval_t stdout_obj = js_get(js, process_obj, "stdout"); 298 - if (js_type(stdout_obj) != JS_OBJ) return; 299 - 300 - int rows = 0, cols = 0; 301 - process_stdout_get_size(&rows, &cols); 302 - js_set(js, stdout_obj, "rows", js_mknum(rows)); 303 - js_set(js, stdout_obj, "columns", js_mknum(cols)); 304 - 305 - emit_process_stdout_event(js, "resize", NULL, 0); 306 - } 307 - #endif 308 - 309 - static void start_sigwinch_handler(struct js *js) { 310 - #ifndef _WIN32 311 - if (process_sigwinch_initialized) return; 312 - 313 - uv_loop_t *loop = uv_default_loop(); 314 - if (uv_signal_init(loop, &process_sigwinch) != 0) return; 315 - if (uv_signal_start(&process_sigwinch, on_sigwinch, SIGWINCH) != 0) { 316 - uv_close((uv_handle_t *)&process_sigwinch, NULL); 317 - return; 318 - } 319 - uv_unref((uv_handle_t *)&process_sigwinch); 320 - process_sigwinch_initialized = true; 321 - process_stdout_js = js; 322 - #else 323 - (void)js; 324 - #endif 325 - } 326 - 327 - #ifndef _WIN32 328 - static struct termios process_saved_termios; 329 - static bool process_raw_mode = false; 330 - #endif 331 - 332 - static bool process_stdin_is_tty(void) { 333 - return uv_guess_handle(STDIN_FILENO) == UV_TTY; 334 - } 335 - 336 - static bool process_stdout_is_tty(void) { 337 - return uv_guess_handle(STDOUT_FILENO) == UV_TTY; 338 - } 339 - 340 - static void process_stdout_get_size(int *rows, int *cols) { 341 - int out_rows = 24; 342 - int out_cols = 80; 343 - #ifndef _WIN32 344 - struct winsize ws; 345 - if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws) == 0) { 346 - if (ws.ws_row > 0) out_rows = ws.ws_row; 347 - if (ws.ws_col > 0) out_cols = ws.ws_col; 348 - } 349 - #else 350 - CONSOLE_SCREEN_BUFFER_INFO csbi; 351 - if (GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi)) { 352 - int width = csbi.srWindow.Right - csbi.srWindow.Left + 1; 353 - int height = csbi.srWindow.Bottom - csbi.srWindow.Top + 1; 354 - if (height > 0) out_rows = height; 355 - if (width > 0) out_cols = width; 356 - } 357 - #endif 358 - 359 - if (rows) *rows = out_rows; 360 - if (cols) *cols = out_cols; 361 - } 362 - 363 - static void process_stdin_get_size(int *rows, int *cols) { 364 - int out_rows = 24; 365 - int out_cols = 80; 366 - #ifndef _WIN32 367 - struct winsize ws; 368 - if (ioctl(STDIN_FILENO, TIOCGWINSZ, &ws) == 0) { 369 - if (ws.ws_row > 0) out_rows = ws.ws_row; 370 - if (ws.ws_col > 0) out_cols = ws.ws_col; 371 - } 372 - #else 373 - CONSOLE_SCREEN_BUFFER_INFO csbi; 374 - if (GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi)) { 375 - int width = csbi.srWindow.Right - csbi.srWindow.Left + 1; 376 - int height = csbi.srWindow.Bottom - csbi.srWindow.Top + 1; 377 - if (height > 0) out_rows = height; 378 - if (width > 0) out_cols = width; 379 - } 380 - #endif 381 - 382 - if (rows) *rows = out_rows; 383 - if (cols) *cols = out_cols; 384 - } 385 - 386 - #ifndef _WIN32 387 - static bool process_set_raw_mode(bool enable) { 388 - if (!process_stdin_is_tty()) return false; 389 - if (enable) { 390 - if (process_raw_mode) return true; 391 - if (tcgetattr(STDIN_FILENO, &process_saved_termios) == -1) return false; 392 - 393 - struct termios raw = process_saved_termios; 394 - raw.c_lflag &= ~(ICANON | ECHO | ISIG); 395 - raw.c_cc[VMIN] = 1; 396 - raw.c_cc[VTIME] = 0; 397 - 398 - if (tcsetattr(STDIN_FILENO, TCSANOW, &raw) == -1) return false; 399 - process_raw_mode = true; 400 - return true; 401 - } 402 - 403 - if (!process_raw_mode) return true; 404 - if (tcsetattr(STDIN_FILENO, TCSANOW, &process_saved_termios) == -1) return false; 405 - process_raw_mode = false; 406 - return true; 407 - } 408 - #else 409 - static bool process_set_raw_mode(bool enable) { 410 - (void)enable; 411 - return false; 412 - } 413 - #endif 414 - 415 - static jsval_t js_process_stdin_set_raw_mode(struct js *js, jsval_t *args, int nargs) { 416 - bool enable = true; 417 - if (nargs > 0) enable = js_truthy(js, args[0]); 418 - return process_set_raw_mode(enable) ? js_mktrue() : js_mkfalse(); 419 - } 420 - 421 - static jsval_t js_process_stdout_write(struct js *js, jsval_t *args, int nargs) { 422 - if (nargs < 1) return js_mkfalse(); 423 - size_t len = 0; 424 - char *data = js_getstr(js, args[0], &len); 425 - if (!data) return js_mkfalse(); 426 - fwrite(data, 1, len, stdout); 427 - fflush(stdout); 428 - return js_mktrue(); 429 - } 430 - 431 - static void process_stdin_start_reading(void) { 432 - if (process_tty_reading) return; 433 - if (!process_tty_initialized) { 434 - uv_loop_t *loop = uv_default_loop(); 435 - if (uv_tty_init(loop, &process_tty_in, STDIN_FILENO, 1) != 0) return; 436 - uv_tty_set_mode(&process_tty_in, process_raw_mode ? UV_TTY_MODE_RAW : UV_TTY_MODE_NORMAL); 437 - process_tty_in.data = NULL; 438 - process_tty_initialized = true; 439 - } else { 440 - uv_tty_set_mode(&process_tty_in, process_raw_mode ? UV_TTY_MODE_RAW : UV_TTY_MODE_NORMAL); 441 - } 442 - 443 - process_tty_reading = true; 444 - uv_read_start((uv_stream_t *)&process_tty_in, alloc_buffer, on_stdin_read); 445 - } 446 - 447 - static void process_stdin_stop_reading(void) { 448 - if (!process_tty_reading) return; 449 - uv_read_stop((uv_stream_t *)&process_tty_in); 450 - process_tty_reading = false; 451 - } 452 - 453 - static jsval_t js_process_stdin_resume(struct js *js, jsval_t *args, int nargs) { 454 - (void)args; 455 - (void)nargs; 456 - process_stdin_js = js; 457 - process_stdin_start_reading(); 458 - return js_getthis(js); 459 - } 460 - 461 - static jsval_t js_process_stdin_pause(struct js *js, jsval_t *args, int nargs) { 462 - (void)args; 463 - (void)nargs; 464 - process_stdin_stop_reading(); 465 - return js_getthis(js); 466 - } 467 - 468 - static jsval_t js_process_stdin_on(struct js *js, jsval_t *args, int nargs) { 469 - jsval_t this_obj = js_getthis(js); 470 - 471 - if (nargs < 2) return this_obj; 472 - char *event_type = js_getstr(js, args[0], NULL); 473 - if (event_type == NULL) return this_obj; 474 - if (js_type(args[1]) != JS_FUNC) return this_obj; 475 - 476 - RLEventType *evt = find_or_create_process_event_type(event_type); 477 - if (evt->listener_count < MAX_LISTENERS_PER_EVENT) { 478 - evt->listeners[evt->listener_count].listener = args[1]; 479 - evt->listeners[evt->listener_count].once = false; 480 - evt->listener_count++; 481 - } 482 - 483 - if (strcmp(event_type, "data") == 0) { 484 - process_stdin_js = js; 485 - process_stdin_start_reading(); 486 - } 487 - 488 - return this_obj; 489 - } 490 - 491 - static jsval_t js_process_stdin_remove_all_listeners(struct js *js, jsval_t *args, int nargs) { 492 - jsval_t this_obj = js_getthis(js); 493 - if (nargs < 1) { 494 - RLEventType *evt, *tmp; 495 - HASH_ITER(hh, process_stdin_events, evt, tmp) { 496 - evt->listener_count = 0; 497 - } 498 - process_stdin_stop_reading(); 499 - return this_obj; 500 - } 501 - 502 - char *event_type = js_getstr(js, args[0], NULL); 503 - if (!event_type) return this_obj; 504 - RLEventType *evt = NULL; 505 - HASH_FIND_STR(process_stdin_events, event_type, evt); 506 - if (evt != NULL) { 507 - evt->listener_count = 0; 508 - } 509 - if (strcmp(event_type, "data") == 0) { 510 - process_stdin_stop_reading(); 511 - } 512 - return this_obj; 513 - } 514 - 515 - static jsval_t js_process_stdout_on(struct js *js, jsval_t *args, int nargs) { 516 - jsval_t this_obj = js_getthis(js); 517 - 518 - if (nargs < 2) return this_obj; 519 - char *event_type = js_getstr(js, args[0], NULL); 520 - if (event_type == NULL) return this_obj; 521 - if (js_type(args[1]) != JS_FUNC) return this_obj; 522 - 523 - RLEventType *evt = find_or_create_process_stdout_event_type(event_type); 524 - if (evt->listener_count < MAX_LISTENERS_PER_EVENT) { 525 - evt->listeners[evt->listener_count].listener = args[1]; 526 - evt->listeners[evt->listener_count].once = false; 527 - evt->listener_count++; 528 - } 529 - 530 - if (strcmp(event_type, "resize") == 0) { 531 - start_sigwinch_handler(js); 532 - } 533 - 534 - return this_obj; 535 - } 536 - 537 - static jsval_t js_process_stdout_once(struct js *js, jsval_t *args, int nargs) { 538 - jsval_t this_obj = js_getthis(js); 539 - 540 - if (nargs < 2) return this_obj; 541 - char *event_type = js_getstr(js, args[0], NULL); 542 - if (event_type == NULL) return this_obj; 543 - if (js_type(args[1]) != JS_FUNC) return this_obj; 544 - 545 - RLEventType *evt = find_or_create_process_stdout_event_type(event_type); 546 - if (evt->listener_count < MAX_LISTENERS_PER_EVENT) { 547 - evt->listeners[evt->listener_count].listener = args[1]; 548 - evt->listeners[evt->listener_count].once = true; 549 - evt->listener_count++; 550 - } 551 - 552 - if (strcmp(event_type, "resize") == 0) { 553 - start_sigwinch_handler(js); 554 - } 555 - 556 - return this_obj; 557 - } 558 - 559 - static jsval_t js_process_stdout_remove_all_listeners(struct js *js, jsval_t *args, int nargs) { 560 - jsval_t this_obj = js_getthis(js); 561 - if (nargs < 1) { 562 - RLEventType *evt, *tmp; 563 - HASH_ITER(hh, process_stdout_events, evt, tmp) { 564 - evt->listener_count = 0; 565 - } 566 - return this_obj; 567 - } 568 - 569 - char *event_type = js_getstr(js, args[0], NULL); 570 - if (!event_type) return this_obj; 571 - RLEventType *evt = NULL; 572 - HASH_FIND_STR(process_stdout_events, event_type, evt); 573 - if (evt != NULL) { 574 - evt->listener_count = 0; 575 - } 576 - return this_obj; 577 - } 578 - 579 - static jsval_t js_process_stdout_get_window_size(struct js *js, jsval_t *args, int nargs) { 580 - (void)args; 581 - (void)nargs; 582 - 583 - int rows = 0, cols = 0; 584 - process_stdout_get_size(&rows, &cols); 585 - 586 - jsval_t arr = js_mkarr(js); 587 - js_arr_push(js, arr, js_mknum(cols)); 588 - js_arr_push(js, arr, js_mknum(rows)); 589 - return arr; 590 - } 591 - 592 - static void ensure_process_stdio(struct js *js) { 593 - jsval_t process_obj = js_get(js, js_glob(js), "process"); 594 - if (js_type(process_obj) != JS_OBJ) return; 595 - 596 - bool stdin_tty = process_stdin_is_tty(); 597 - bool stdout_tty = process_stdout_is_tty(); 598 - 599 - jsval_t stdin_obj = js_get(js, process_obj, "stdin"); 600 - if (js_type(stdin_obj) != JS_OBJ) { 601 - stdin_obj = js_mkobj(js); 602 - js_set(js, process_obj, "stdin", stdin_obj); 603 - } 604 - int stdin_rows = 0; 605 - int stdin_cols = 0; 606 - process_stdin_get_size(&stdin_rows, &stdin_cols); 607 - js_set(js, stdin_obj, "isTTY", stdin_tty ? js_mktrue() : js_mkfalse()); 608 - js_set(js, stdin_obj, "rows", js_mknum(stdin_rows)); 609 - js_set(js, stdin_obj, "columns", js_mknum(stdin_cols)); 610 - js_set(js, stdin_obj, "setRawMode", js_mkfun(js_process_stdin_set_raw_mode)); 611 - js_set(js, stdin_obj, "resume", js_mkfun(js_process_stdin_resume)); 612 - js_set(js, stdin_obj, "pause", js_mkfun(js_process_stdin_pause)); 613 - js_set(js, stdin_obj, "on", js_mkfun(js_process_stdin_on)); 614 - js_set(js, stdin_obj, "removeAllListeners", js_mkfun(js_process_stdin_remove_all_listeners)); 615 - 616 - jsval_t stdout_obj = js_get(js, process_obj, "stdout"); 617 - if (js_type(stdout_obj) != JS_OBJ) { 618 - stdout_obj = js_mkobj(js); 619 - js_set(js, process_obj, "stdout", stdout_obj); 620 - } 621 - int stdout_rows = 0; 622 - int stdout_cols = 0; 623 - process_stdout_get_size(&stdout_rows, &stdout_cols); 624 - js_set(js, stdout_obj, "isTTY", stdout_tty ? js_mktrue() : js_mkfalse()); 625 - js_set(js, stdout_obj, "rows", js_mknum(stdout_rows)); 626 - js_set(js, stdout_obj, "columns", js_mknum(stdout_cols)); 627 - js_set(js, stdout_obj, "write", js_mkfun(js_process_stdout_write)); 628 - js_set(js, stdout_obj, "on", js_mkfun(js_process_stdout_on)); 629 - js_set(js, stdout_obj, "once", js_mkfun(js_process_stdout_once)); 630 - js_set(js, stdout_obj, "removeAllListeners", js_mkfun(js_process_stdout_remove_all_listeners)); 631 - js_set(js, stdout_obj, "getWindowSize", js_mkfun(js_process_stdout_get_window_size)); 632 - } 633 207 634 208 #ifndef _WIN32 635 209 static void enter_raw_mode(rl_interface_t *iface) { ··· 793 367 struct js *js = rt->js; 794 368 795 369 if (!iface) { 796 - if (nread > 0 && process_stdin_js) { 797 - jsval_t data_val = js_mkstr(process_stdin_js, buf->base, (size_t)nread); 798 - emit_process_event(process_stdin_js, "data", &data_val, 1); 799 - } 800 370 if (buf->base) free(buf->base); 801 371 return; 802 372 } ··· 1634 1204 jsval_t readline_library(struct js *js) { 1635 1205 jsval_t lib = js_mkobj(js); 1636 1206 1637 - ensure_process_stdio(js); 1638 - 1639 1207 js_set(js, lib, "createInterface", js_mkfun(rl_create_interface)); 1640 1208 js_set(js, lib, "clearLine", js_mkfun(rl_clear_line)); 1641 1209 js_set(js, lib, "clearScreenDown", js_mkfun(rl_clear_screen_down)); ··· 1649 1217 1650 1218 jsval_t readline_promises_library(struct js *js) { 1651 1219 jsval_t lib = js_mkobj(js); 1652 - 1653 - ensure_process_stdio(js); 1654 1220 1655 1221 js_set(js, lib, "createInterface", js_mkfun(rl_create_interface_promises)); 1656 1222 js_set(js, lib, "clearLine", js_mkfun(rl_clear_line));