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.

use libsodium for random

+71 -62
+1 -2
include/modules/bigint.h
··· 21 21 bool bigint_is_negative(ant_t *js, ant_value_t v); 22 22 bool bigint_is_zero(ant_t *js, ant_value_t v); 23 23 24 - 25 24 size_t bigint_digits_len(ant_t *js, ant_value_t v); 26 25 size_t strbigint(ant_t *js, ant_value_t value, char *buf, size_t len); 27 - size_t bigint_compare(ant_t *js, ant_value_t a, ant_value_t b); 26 + int bigint_compare(ant_t *js, ant_value_t a, ant_value_t b); 28 27 29 28 #endif
+4 -2
include/modules/crypto.h
··· 3 3 4 4 #include "types.h" 5 5 6 - void init_crypto_module(); 6 + void init_crypto_module(void); 7 + int ensure_crypto_init(void); 8 + 7 9 ant_value_t crypto_library(ant_t *js); 8 10 9 - #endif 11 + #endif
+1 -1
src/modules/bigint.c
··· 471 471 return js_mkerr_typed(js, JS_ERR_TYPE, "BigInts have no unsigned right shift, use >> instead"); 472 472 } 473 473 474 - size_t bigint_compare(ant_t *js, ant_value_t a, ant_value_t b) { 474 + int bigint_compare(ant_t *js, ant_value_t a, ant_value_t b) { 475 475 bool aneg = bigint_is_negative(js, a); 476 476 bool bneg = bigint_is_negative(js, b); 477 477
+6 -16
src/modules/crypto.c
··· 20 20 #include "modules/buffer.h" 21 21 #include "modules/symbol.h" 22 22 23 - static int ensure_crypto_init(ant_t *js) { 23 + int ensure_crypto_init(void) { 24 24 static int crypto_initialized = 0; 25 25 26 26 if (!crypto_initialized) { ··· 53 53 54 54 // crypto.random() 55 55 static ant_value_t js_crypto_random(ant_t *js, ant_value_t *args, int nargs) { 56 - (void) args; 57 - (void) nargs; 58 - (void) js; 59 - 60 - if (ensure_crypto_init(js) < 0) { 56 + if (ensure_crypto_init() < 0) { 61 57 return js_mkerr(js, "libsodium initialization failed"); 62 58 } 63 59 ··· 71 67 return js_mkerr(js, "randomBytes requires a length argument"); 72 68 } 73 69 74 - if (ensure_crypto_init(js) < 0) { 70 + if (ensure_crypto_init() < 0) { 75 71 return js_mkerr(js, "libsodium initialization failed"); 76 72 } 77 73 ··· 103 99 104 100 // crypto.randomUUID() 105 101 static ant_value_t js_crypto_random_uuid(ant_t *js, ant_value_t *args, int nargs) { 106 - (void) args; 107 - (void) nargs; 108 - 109 - if (ensure_crypto_init(js) < 0) { 102 + if (ensure_crypto_init() < 0) { 110 103 return js_mkerr(js, "libsodium initialization failed"); 111 104 } 112 105 ··· 131 124 132 125 // crypto.randomUUIDv7() 133 126 static ant_value_t js_crypto_random_uuidv7(ant_t *js, ant_value_t *args, int nargs) { 134 - (void) args; 135 - (void) nargs; 136 - 137 - if (ensure_crypto_init(js) < 0) { 127 + if (ensure_crypto_init() < 0) { 138 128 return js_mkerr(js, "libsodium initialization failed"); 139 129 } 140 130 ··· 157 147 return js_mkerr(js, "getRandomValues requires a TypedArray argument"); 158 148 } 159 149 160 - if (ensure_crypto_init(js) < 0) { 150 + if (ensure_crypto_init() < 0) { 161 151 return js_mkerr(js, "libsodium initialization failed"); 162 152 } 163 153
+59 -41
src/modules/math.c
··· 1 - #include <stdlib.h> 2 - #include <time.h> 1 + #include <sodium.h> 2 + #include <float.h> 3 3 4 4 #include "ant.h" 5 + #include "errors.h" 5 6 #include "internal.h" 6 7 #include "runtime.h" 8 + #include "modules/crypto.h" 9 + 10 + #if DBL_MANT_DIG >= 64 11 + #error "Unsupported double mantissa width for Math.random" 12 + #endif 13 + 14 + enum { 15 + MATH_RANDOM_MANTISSA_BITS = DBL_MANT_DIG, 16 + MATH_RANDOM_DISCARD_BITS = 64 - DBL_MANT_DIG, 17 + }; 18 + 19 + static const double math_random_scale = 20 + 1.0 / (double)(UINT64_C(1) << MATH_RANDOM_MANTISSA_BITS); 7 21 8 22 static ant_value_t builtin_Math_abs(ant_t *js, ant_value_t *args, int nargs) { 9 23 double x = (nargs < 1) ? JS_NAN : js_to_number(js, args[0]); ··· 68 82 69 83 static ant_value_t builtin_Math_clz32(ant_t *js, ant_value_t *args, int nargs) { 70 84 if (nargs < 1) return tov(32); 71 - double x = js_to_number(js, args[0]); 72 - if (isnan(x) || isinf(x)) return tov(32); 73 - uint32_t n = (uint32_t)x; 85 + uint32_t n = js_to_uint32(js_to_number(js, args[0])); 74 86 if (n == 0) return tov(32); 75 - int count = 0; 76 - while ((n & 0x80000000U) == 0) { count++; n <<= 1; } 77 - return tov((double)count); 87 + int lz = __builtin_clz(n); 88 + if (sizeof(unsigned int) > sizeof(uint32_t)) { 89 + lz -= (int)((sizeof(unsigned int) - sizeof(uint32_t)) * 8); 90 + } 91 + return tov((double)lz); 78 92 } 79 93 80 94 static ant_value_t builtin_Math_cos(ant_t *js, ant_value_t *args, int nargs) { ··· 115 129 116 130 static ant_value_t builtin_Math_hypot(ant_t *js, ant_value_t *args, int nargs) { 117 131 if (nargs == 0) return tov(0.0); 118 - double sum = 0.0; 132 + double acc = 0.0; 133 + bool saw_nan = false; 119 134 for (int i = 0; i < nargs; i++) { 120 135 double v = js_to_number(js, args[i]); 121 - if (isnan(v)) return tov(JS_NAN); 122 - sum += v * v; 136 + if (isinf(v)) return tov(JS_INF); 137 + if (isnan(v)) { saw_nan = true; continue; } 138 + acc = hypot(acc, v); 123 139 } 124 - return tov(sqrt(sum)); 125 - } 126 - 127 - static int32_t toInt32(double d) { 128 - if (isnan(d) || isinf(d) || d == 0) return 0; 129 - double int_val = trunc(d); 130 - double two32 = (double)(1ULL << 32); 131 - double two31 = (double)(1ULL << 31); 132 - double mod_val = fmod(int_val, two32); 133 - if (mod_val < 0) mod_val += two32; 134 - if (mod_val >= two31) mod_val -= two32; 135 - return (int32_t)mod_val; 140 + if (saw_nan) return tov(JS_NAN); 141 + return tov(acc); 136 142 } 137 143 138 144 static ant_value_t builtin_Math_imul(ant_t *js, ant_value_t *args, int nargs) { 139 145 if (nargs < 2) return tov(0); 140 - int32_t a = toInt32(js_to_number(js, args[0])); 141 - int32_t b = toInt32(js_to_number(js, args[1])); 146 + int32_t a = js_to_int32(js_to_number(js, args[0])); 147 + int32_t b = js_to_int32(js_to_number(js, args[1])); 142 148 return tov((double)((int32_t)((uint32_t)a * (uint32_t)b))); 143 149 } 144 150 ··· 168 174 169 175 static ant_value_t builtin_Math_max(ant_t *js, ant_value_t *args, int nargs) { 170 176 if (nargs == 0) return tov(JS_NEG_INF); 171 - double max_val = JS_NEG_INF; 172 - for (int i = 0; i < nargs; i++) { 177 + double max_val = js_to_number(js, args[0]); 178 + if (isnan(max_val)) return tov(JS_NAN); 179 + for (int i = 1; i < nargs; i++) { 173 180 double v = js_to_number(js, args[i]); 174 181 if (isnan(v)) return tov(JS_NAN); 175 - if (v > max_val) max_val = v; 182 + if (v > max_val) { max_val = v; continue; } 183 + if (v == 0.0 && max_val == 0.0 && !signbit(v) && signbit(max_val)) { 184 + max_val = v; 185 + } 176 186 } 177 187 return tov(max_val); 178 188 } 179 189 180 190 static ant_value_t builtin_Math_min(ant_t *js, ant_value_t *args, int nargs) { 181 191 if (nargs == 0) return tov(JS_INF); 182 - double min_val = JS_INF; 183 - for (int i = 0; i < nargs; i++) { 192 + double min_val = js_to_number(js, args[0]); 193 + if (isnan(min_val)) return tov(JS_NAN); 194 + for (int i = 1; i < nargs; i++) { 184 195 double v = js_to_number(js, args[i]); 185 196 if (isnan(v)) return tov(JS_NAN); 186 - if (v < min_val) min_val = v; 197 + if (v < min_val) { 198 + min_val = v; 199 + continue; 200 + } 201 + if (v == 0.0 202 + && min_val == 0.0 203 + && signbit(v) 204 + && !signbit(min_val) 205 + ) min_val = v; 187 206 } 188 207 return tov(min_val); 189 208 } ··· 195 214 return tov(pow(base, exp)); 196 215 } 197 216 198 - static bool random_seeded = false; 199 - 200 217 static ant_value_t builtin_Math_random(ant_t *js, ant_value_t *args, int nargs) { 201 - (void)js; 202 - (void)args; 203 - (void)nargs; 204 - if (!random_seeded) { 205 - srand((unsigned int)time(NULL)); 206 - random_seeded = true; 218 + if (ensure_crypto_init() < 0) { 219 + return js_mkerr(js, "libsodium initialization failed"); 207 220 } 208 - return tov((double)rand() / ((double)RAND_MAX + 1.0)); 221 + 222 + uint64_t r = 0; randombytes_buf(&r, sizeof(r)); 223 + uint64_t fraction = r >> MATH_RANDOM_DISCARD_BITS; 224 + 225 + return tov((double)fraction * math_random_scale); 209 226 } 210 227 211 228 static ant_value_t builtin_Math_round(ant_t *js, ant_value_t *args, int nargs) { 212 229 double x = (nargs < 1) ? JS_NAN : js_to_number(js, args[0]); 213 - if (isnan(x) || isinf(x)) return tov(x); 230 + if (isnan(x) || isinf(x) || x == 0.0) return tov(x); 231 + if (x < 0.0 && x >= -0.5) return tov(-0.0); 214 232 return tov(floor(x + 0.5)); 215 233 } 216 234