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.

string fast path

+142 -19
+6
include/internal.h
··· 548 548 return (ant_flat_string_t *)((char *)str - offsetof(ant_flat_string_t, bytes)); 549 549 } 550 550 551 + static inline ant_flat_string_t *ant_str_flat_ptr(ant_value_t value) { 552 + if (vtype(value) != T_STR) return NULL; 553 + if ((vdata(value) & STR_HEAP_TAG_MASK) != STR_HEAP_TAG_FLAT) return NULL; 554 + return (ant_flat_string_t *)(uintptr_t)vdata(value); 555 + } 556 + 551 557 static inline ant_flat_string_t *large_string_flat_ptr(ant_large_string_alloc_t *alloc) { 552 558 return alloc ? (ant_flat_string_t *)&alloc->len : NULL; 553 559 }
+76 -16
src/ant.c
··· 239 239 if (obj) obj->is_constructor = is_constructor ? 1u : 0u; 240 240 } 241 241 242 - static inline ant_flat_string_t *str_flat_ptr(ant_value_t value) { 243 - if (vtype(value) != T_STR) return NULL; 244 - if ((vdata(value) & STR_HEAP_TAG_MASK) != STR_HEAP_TAG_FLAT) return NULL; 245 - return (ant_flat_string_t *)(uintptr_t)vdata(value); 246 - } 247 - 248 242 static inline ant_extra_slot_t *obj_extra_slots(ant_object_t *obj) { 249 243 return (ant_extra_slot_t *)obj->extra_slots; 250 244 } ··· 564 558 ant_string_builder_t *builder = ant_str_builder_ptr(v); 565 559 return builder ? builder->len : 0; 566 560 } 567 - ant_flat_string_t *flat = str_flat_ptr(v); 561 + ant_flat_string_t *flat = ant_str_flat_ptr(v); 568 562 return flat ? flat->len : 0; 569 563 } 570 564 ··· 1866 1860 1867 1861 static inline ant_offset_t assert_flat_string_len(ant_t *js, ant_value_t value, const char **out_ptr) { 1868 1862 (void)js; 1869 - ant_flat_string_t *flat = str_flat_ptr(value); 1863 + ant_flat_string_t *flat = ant_str_flat_ptr(value); 1870 1864 assert(flat != NULL); 1871 1865 ant_offset_t len = flat->len; 1872 1866 if (out_ptr) *out_ptr = flat->bytes; ··· 2055 2049 return chunk_value; 2056 2050 }} 2057 2051 2058 - ant_flat_string_t *chunk_flat = str_flat_ptr(chunk_value); 2052 + ant_flat_string_t *chunk_flat = ant_str_flat_ptr(chunk_value); 2059 2053 if (!chunk_flat || chunk_flat->len == 0) continue; 2060 2054 memcpy(flat_ptr->bytes + cursor, chunk_flat->bytes, (size_t)chunk_flat->len); 2061 2055 cursor += (size_t)chunk_flat->len; ··· 3116 3110 return (const char *)vdata(code_val); 3117 3111 } 3118 3112 3113 + static inline bool js_is_trim_space(char ch) { 3114 + return ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r'; 3115 + } 3116 + 3117 + static inline bool js_try_parse_ascii_decimal_fast(const char *str, size_t len, double *out) { 3118 + size_t i = 0; 3119 + int sign = 1; 3120 + int int_digits = 0; 3121 + int frac_digits = 0; 3122 + 3123 + double value = 0.0; 3124 + double scale = 1.0; 3125 + bool saw_digit = false; 3126 + 3127 + if (len == 0) return false; 3128 + if (str[i] == '+' || str[i] == '-') { 3129 + sign = (str[i] == '-') ? -1 : 1; 3130 + i++; 3131 + if (i == len) return false; 3132 + } 3133 + 3134 + while (i < len && str[i] >= '0' && str[i] <= '9') { 3135 + if (int_digits >= 18) return false; 3136 + value = value * 10.0 + (double)(str[i] - '0'); 3137 + saw_digit = true; 3138 + int_digits++; i++; 3139 + } 3140 + 3141 + if (i < len && str[i] == '.') { 3142 + i++; 3143 + while (i < len && str[i] >= '0' && str[i] <= '9') { 3144 + if (frac_digits >= 18) return false; 3145 + scale *= 0.1; 3146 + value += (double)(str[i] - '0') * scale; 3147 + saw_digit = true; 3148 + frac_digits++; i++; 3149 + }} 3150 + 3151 + if (!saw_digit || i != len) return false; 3152 + *out = (sign < 0) ? -value : value; 3153 + 3154 + return true; 3155 + } 3156 + 3119 3157 double js_to_number(ant_t *js, ant_value_t arg) { 3120 3158 if (vtype(arg) == T_NULL) return 0.0; 3121 3159 if (vtype(arg) == T_UNDEF) return JS_NAN; ··· 3125 3163 if (vtype(arg) == T_BIGINT) return bigint_to_double(js, arg); 3126 3164 3127 3165 if (vtype(arg) == T_STR) { 3128 - ant_offset_t len, off = vstr(js, arg, &len); 3129 - const char *s = (char *)(uintptr_t)(off), *end; 3130 - while (*s == ' ' || *s == '\t' || *s == '\n' || *s == '\r') s++; 3131 - if (!*s) return 0.0; 3132 - double val = strtod(s, (char **)&end); 3133 - while (*end == ' ' || *end == '\t' || *end == '\n' || *end == '\r') end++; 3134 - return (end == s || *end) ? JS_NAN : val; 3166 + ant_flat_string_t *flat = ant_str_flat_ptr(arg); 3167 + const char *base = NULL; 3168 + const char *s = NULL; 3169 + const char *end = NULL; 3170 + 3171 + if (flat) { 3172 + base = flat->bytes; 3173 + s = base; 3174 + end = base + flat->len; 3175 + } else { 3176 + ant_offset_t len = 0; 3177 + ant_offset_t off = vstr(js, arg, &len); 3178 + base = (const char *)(uintptr_t)off; 3179 + s = base; 3180 + end = base + len; 3181 + } 3182 + 3183 + while (s < end && js_is_trim_space(*s)) s++; 3184 + if (s == end) return 0.0; 3185 + 3186 + double fast_val = 0.0; 3187 + if (js_try_parse_ascii_decimal_fast(s, (size_t)(end - s), &fast_val)) 3188 + return fast_val; 3189 + 3190 + char *parse_end = NULL; 3191 + double val = strtod(s, &parse_end); 3192 + while (parse_end < end && js_is_trim_space(*parse_end)) parse_end++; 3193 + 3194 + return (parse_end == s || parse_end != end) ? JS_NAN : val; 3135 3195 } 3136 3196 3137 3197 if (vtype(arg) == T_OBJ || vtype(arg) == T_ARR) {
+14
src/modules/process.c
··· 803 803 return ant_output_stream_flush(out) ? js_true : js_false; 804 804 } 805 805 806 + static ant_value_t process_write_stream_set_encoding(ant_t *js, ant_value_t *args, int nargs) { 807 + ant_value_t this_obj = js_getthis(js); 808 + ant_value_t encoding = nargs > 0 && vtype(args[0]) != T_UNDEF 809 + ? js_tostring_val(js, args[0]) 810 + : js_mkstr(js, "utf8", 4); 811 + 812 + if (is_err(encoding)) return encoding; 813 + js_set(js, this_obj, "encoding", encoding); 814 + 815 + return this_obj; 816 + } 817 + 806 818 static ant_value_t js_stdout_write(ant_t *js, ant_value_t *args, int nargs) { 807 819 return process_write_stream(js, args, nargs, stdout, STDOUT_FILENO); 808 820 } ··· 1915 1927 1916 1928 ant_value_t stdout_proto = js_mkobj(js); 1917 1929 js_set(js, stdout_proto, "write", js_mkfun(js_stdout_write)); 1930 + js_set(js, stdout_proto, "setEncoding", js_mkfun(process_write_stream_set_encoding)); 1918 1931 js_set(js, stdout_proto, "on", js_mkfun(js_stdout_on)); 1919 1932 js_set(js, stdout_proto, "once", js_mkfun(js_stdout_once)); 1920 1933 js_set(js, stdout_proto, "removeListener", js_mkfun(js_stdout_remove_listener)); ··· 1932 1945 1933 1946 ant_value_t stderr_proto = js_mkobj(js); 1934 1947 js_set(js, stderr_proto, "write", js_mkfun(js_stderr_write)); 1948 + js_set(js, stderr_proto, "setEncoding", js_mkfun(process_write_stream_set_encoding)); 1935 1949 js_set(js, stderr_proto, "on", js_mkfun(js_stderr_on)); 1936 1950 js_set(js, stderr_proto, "once", js_mkfun(js_stderr_once)); 1937 1951 js_set(js, stderr_proto, "removeListener", js_mkfun(js_stderr_remove_listener));
+18 -3
src/silver/glue.c
··· 34 34 35 35 ant_value_t jit_helper_sub(sv_vm_t *vm, ant_t *js, ant_value_t l, ant_value_t r) { 36 36 if (vtype(l) == T_NUM && vtype(r) == T_NUM) return tov(tod(l) - tod(r)); 37 + if ((vtype(l) == T_NUM || vtype(l) == T_STR) && (vtype(r) == T_NUM || vtype(r) == T_STR)) { 38 + double ld = (vtype(l) == T_NUM) ? tod(l) : js_to_number(js, l); 39 + double rd = (vtype(r) == T_NUM) ? tod(r) : js_to_number(js, r); 40 + return tov(ld - rd); 41 + } 37 42 return SV_JIT_BAILOUT; 38 43 } 39 44 ··· 708 713 if (vtype(obj) == T_ARR) 709 714 return tov((double)(uint32_t)js_arr_len(js, obj)); 710 715 if (vtype(obj) == T_STR) { 716 + ant_flat_string_t *flat = ant_str_flat_ptr(obj); 717 + if (flat) { 718 + const char *str_data = flat->bytes; 719 + ant_offset_t byte_len = flat->len; 720 + return tov((double)(uint32_t)( 721 + str_is_ascii(str_data) 722 + ? byte_len 723 + : utf16_strlen(str_data, byte_len) 724 + )); 725 + } 711 726 ant_offset_t byte_len = 0; 712 727 ant_offset_t off = vstr(js, obj, &byte_len); 713 728 const char *str_data = (const char *)(uintptr_t)(off); ··· 819 834 } 820 835 821 836 ant_value_t jit_helper_bor(sv_vm_t *vm, ant_t *js, ant_value_t l, ant_value_t r) { 822 - if (vtype(l) != T_NUM || vtype(r) != T_NUM) return SV_JIT_BAILOUT; 823 - int32_t ai = js_to_int32(tod(l)); 824 - int32_t bi = js_to_int32(tod(r)); 837 + if (!((vtype(l) == T_NUM || vtype(l) == T_STR) && (vtype(r) == T_NUM || vtype(r) == T_STR))) return SV_JIT_BAILOUT; 838 + int32_t ai = js_to_int32((vtype(l) == T_NUM) ? tod(l) : js_to_number(js, l)); 839 + int32_t bi = js_to_int32((vtype(r) == T_NUM) ? tod(r) : js_to_number(js, r)); 825 840 return tov((double)(ai | bi)); 826 841 } 827 842
+12
src/silver/ops/property.h
··· 776 776 } 777 777 778 778 if (vtype(obj) == T_STR) { 779 + ant_flat_string_t *flat = ant_str_flat_ptr(obj); 780 + if (flat) { 781 + const char *str_data = flat->bytes; 782 + ant_offset_t byte_len = flat->len; 783 + vm->stack[vm->sp++] = tov((double)(uint32_t)( 784 + str_is_ascii(str_data) 785 + ? byte_len 786 + : utf16_strlen(str_data, byte_len) 787 + )); 788 + return js_mkundef(); 789 + } 790 + 779 791 ant_offset_t byte_len = 0; 780 792 ant_offset_t off = vstr(js, obj, &byte_len); 781 793 const char *str_data = (const char *)(uintptr_t)(off);
+16
tests/test_process_write_stream_setencoding.cjs
··· 1 + function assert(condition, message) { 2 + if (!condition) throw new Error(message); 3 + } 4 + 5 + for (const [name, stream] of [ 6 + ['stdout', process.stdout], 7 + ['stderr', process.stderr], 8 + ]) { 9 + assert(typeof stream.setEncoding === 'function', `${name}.setEncoding should exist`); 10 + 11 + const returned = stream.setEncoding('utf8'); 12 + assert(returned === stream, `${name}.setEncoding should return the stream`); 13 + assert(stream.encoding === 'utf8', `${name}.encoding should be utf8`); 14 + } 15 + 16 + console.log('process stdout/stderr setEncoding ok');