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.

restructure do_op as computed tables

+231 -259
+1 -1
meson.build
··· 96 96 build_date = run_command('date', '+%Y-%m-%d', check: true).stdout().strip() 97 97 98 98 version_conf = configuration_data() 99 - version_conf.set('ANT_VERSION', '0.3.2.8') 99 + version_conf.set('ANT_VERSION', '0.3.2.9') 100 100 version_conf.set('ANT_GIT_HASH', git_hash) 101 101 version_conf.set('ANT_BUILD_DATE', build_date) 102 102
+230 -258
src/ant.c
··· 767 767 static inline jsoff_t esize(jsoff_t w); 768 768 769 769 static jsval_t js_expr(struct js *js); 770 + static jsval_t js_call_valueOf(struct js *js, jsval_t value); 770 771 static jsval_t js_call_toString(struct js *js, jsval_t value); 771 772 static jsval_t js_eval_slice(struct js *js, jsoff_t off, jsoff_t len); 772 773 static jsval_t js_eval_str(struct js *js, const char *code, jsoff_t len); ··· 2991 2992 if (vtype(arg) == T_BOOL) return vdata(arg) ? 1.0 : 0.0; 2992 2993 if (vtype(arg) == T_NULL) return 0.0; 2993 2994 if (vtype(arg) == T_UNDEF) return NAN; 2995 + 2994 2996 if (vtype(arg) == T_STR) { 2995 - jsoff_t len; 2996 - jsoff_t off = vstr(js, arg, &len); 2997 - const char *str = (char *) &js->mem[off]; 2998 - while (*str == ' ' || *str == '\t' || *str == '\n' || *str == '\r') str++; 2999 - if (*str == '\0') return 0.0; 3000 - char *end; 3001 - double val = strtod(str, &end); 2997 + jsoff_t len, off = vstr(js, arg, &len); 2998 + const char *s = (char *)&js->mem[off], *end; 2999 + while (*s == ' ' || *s == '\t' || *s == '\n' || *s == '\r') s++; 3000 + if (!*s) return 0.0; 3001 + double val = strtod(s, (char **)&end); 3002 3002 while (*end == ' ' || *end == '\t' || *end == '\n' || *end == '\r') end++; 3003 - if (end == str || *end != '\0') return NAN; 3004 - return val; 3003 + return (end == s || *end) ? NAN : val; 3005 3004 } 3006 - if (vtype(arg) == T_ARR || vtype(arg) == T_OBJ) { 3005 + 3006 + if (vtype(arg) == T_OBJ || vtype(arg) == T_ARR) { 3007 + if (vtype(arg) == T_OBJ) { 3008 + jsval_t prim = js_call_valueOf(js, arg); 3009 + uint8_t pt = vtype(prim); 3010 + if (pt != T_OBJ && pt != T_ARR && pt != T_FUNC) return js_to_number(js, prim); 3011 + } 3012 + 3007 3013 jsval_t str_val = js_tostring_val(js, arg); 3008 3014 if (is_err(str_val) || vtype(str_val) != T_STR) return NAN; 3009 3015 return js_to_number(js, str_val); 3010 3016 } 3017 + 3011 3018 return NAN; 3012 3019 } 3013 3020 ··· 5870 5877 } 5871 5878 5872 5879 js->this_val = saved_this; 5873 - 5874 5880 if (vtype(result) == T_STR) return result; 5875 5881 5876 5882 uint8_t rt = vtype(result); ··· 5888 5894 return js_mkstr(js, buf, len); 5889 5895 } 5890 5896 5897 + static jsval_t js_call_valueOf(struct js *js, jsval_t value) { 5898 + jsoff_t off = lkp(js, value, "valueOf", 7); 5899 + if (off == 0) off = lkp_proto(js, value, "valueOf", 7); 5900 + if (off == 0) return value; 5901 + 5902 + jsval_t fn = resolveprop(js, mkval(T_PROP, off)); 5903 + uint8_t ft = vtype(fn); 5904 + if (ft != T_FUNC && ft != T_CFUNC) return value; 5905 + 5906 + jsval_t saved = js->this_val; 5907 + js->this_val = value; 5908 + jsval_t result; 5909 + 5910 + if (ft == T_CFUNC) { 5911 + result = ((jsval_t (*)(struct js *, jsval_t *, int))vdata(fn))(js, NULL, 0); 5912 + } else { 5913 + jsval_t func_obj = mkval(T_OBJ, vdata(fn)); 5914 + jsval_t code_val = get_slot(js, func_obj, SLOT_CODE); 5915 + if (vtype(code_val) != T_STR) { js->this_val = saved; return value; } 5916 + 5917 + jsval_t closure_scope = get_slot(js, func_obj, SLOT_SCOPE); 5918 + if (vtype(closure_scope) == T_UNDEF) closure_scope = js->scope; 5919 + 5920 + jsoff_t fnlen, fnoff = vstr(js, code_val, &fnlen); 5921 + result = call_js(js, (const char *)&js->mem[fnoff], fnlen, closure_scope); 5922 + } 5923 + 5924 + js->this_val = saved; 5925 + return result; 5926 + } 5927 + 5928 + static inline bool strict_eq_values(struct js *js, jsval_t l, jsval_t r) { 5929 + uint8_t t = vtype(l); 5930 + if (t != vtype(r)) return false; 5931 + if (t == T_STR) { 5932 + jsoff_t n1, n2, off1 = vstr(js, l, &n1), off2 = vstr(js, r, &n2); 5933 + return n1 == n2 && memcmp(&js->mem[off1], &js->mem[off2], n1) == 0; 5934 + } 5935 + if (t == T_NUM) return tod(l) == tod(r); 5936 + if (t == T_BIGINT) return bigint_compare(js, l, r) == 0; 5937 + return vdata(l) == vdata(r); 5938 + } 5939 + 5940 + static inline jsval_t coerce_to_str(struct js *js, jsval_t v) { 5941 + if (vtype(v) == T_STR) return v; 5942 + if (vtype(v) == T_ARR) { 5943 + char buf[1024]; 5944 + size_t len = array_to_string(js, v, buf, sizeof(buf)); 5945 + return js_mkstr(js, buf, len); 5946 + } 5947 + return js_tostring_val(js, v); 5948 + } 5949 + 5891 5950 static jsval_t do_op(struct js *js, uint8_t op, jsval_t lhs, jsval_t rhs) { 5892 5951 if (js->flags & F_NOEXEC) return 0; 5893 5952 ··· 5897 5956 5898 5957 if (is_err(l)) return l; 5899 5958 if (is_err(r)) return r; 5959 + 5900 5960 if (is_assign(op) && vtype(lhs) != T_PROP && vtype(lhs) != T_PROPREF) { 5901 5961 if (!(js->flags & F_STRICT) && vtype(lhs) == T_UNDEF) return r; 5902 5962 if (!(js->flags & F_STRICT) && vtype(lhs) == T_CODEREF && op == TOK_ASSIGN) { 5903 - jsoff_t id_off = coderefoff(lhs); 5904 - jsoff_t id_len = codereflen(lhs); 5963 + jsoff_t id_off = coderefoff(lhs), id_len = codereflen(lhs); 5905 5964 jsval_t global_scope = js->scope; 5906 - while (vdata(upper(js, global_scope)) != 0) { 5907 - global_scope = upper(js, global_scope); 5908 - } 5965 + while (vdata(upper(js, global_scope)) != 0) global_scope = upper(js, global_scope); 5909 5966 jsval_t key = js_mkstr(js, &js->code[id_off], id_len); 5910 5967 if (is_err(key)) return key; 5911 5968 jsval_t prop = setprop(js, global_scope, key, r); 5912 - if (is_err(prop)) return prop; 5913 - return r; 5969 + return is_err(prop) ? prop : r; 5914 5970 } 5915 - if ((js->flags & F_STRICT) && vtype(lhs) == T_UNDEF) { 5916 - return js_mkerr_typed(js, JS_ERR_TYPE, "Cannot create property on primitive value"); 5917 - } 5918 - return js_mkerr_typed(js, JS_ERR_SYNTAX, "Invalid left-hand side in assignment"); 5971 + return js_mkerr_typed(js, (js->flags & F_STRICT) && vtype(lhs) == T_UNDEF ? JS_ERR_TYPE : JS_ERR_SYNTAX, 5972 + (js->flags & F_STRICT) && vtype(lhs) == T_UNDEF ? "Cannot create property on primitive value" : "Invalid left-hand side in assignment"); 5919 5973 } 5974 + 5975 + #define L(tok) [tok] = &&L_##tok 5976 + static const void *dispatch[TOK_MAX] = { 5977 + L(TOK_TYPEOF), L(TOK_VOID), L(TOK_INSTANCEOF), L(TOK_IN), 5978 + L(TOK_CALL), L(TOK_BRACKET), L(TOK_ASSIGN), L(TOK_DOT), 5979 + L(TOK_OPTIONAL_CHAIN), L(TOK_POSTINC), L(TOK_POSTDEC), 5980 + L(TOK_NOT), L(TOK_UMINUS), L(TOK_UPLUS), L(TOK_SEQ), 5981 + L(TOK_SNE), L(TOK_EQ), L(TOK_NE), L(TOK_PLUS), 5982 + L(TOK_MINUS), L(TOK_MUL), L(TOK_DIV), L(TOK_REM), 5983 + L(TOK_EXP), L(TOK_LT), L(TOK_LE), L(TOK_GT), L(TOK_GE), 5984 + L(TOK_XOR), L(TOK_AND), L(TOK_OR), L(TOK_TILDA), 5985 + L(TOK_SHL), L(TOK_SHR), L(TOK_ZSHR), 5986 + }; 5987 + #undef L 5988 + 5989 + if (op < TOK_MAX && dispatch[op]) goto *dispatch[op]; 5990 + goto L_default; 5991 + 5992 + L_TOK_TYPEOF: { 5993 + const char *ts = typestr(vtype(r)); 5994 + return js_mkstr(js, ts, strlen(ts)); 5995 + } 5996 + L_TOK_VOID: return js_mkundef(); 5997 + L_TOK_INSTANCEOF: return do_instanceof(js, l, r); 5998 + L_TOK_IN: return do_in(js, l, r); 5999 + L_TOK_CALL: return do_call_op(js, l, r); 6000 + L_TOK_BRACKET: return do_bracket_op(js, l, rhs); 6001 + L_TOK_ASSIGN: return assign(js, lhs, r); 6002 + L_TOK_DOT: return do_dot_op(js, l, r); 6003 + L_TOK_OPTIONAL_CHAIN: return do_optional_chain_op(js, l, r); 6004 + 6005 + L_TOK_POSTINC: 6006 + L_TOK_POSTDEC: { 6007 + if (vtype(lhs) != T_PROP) 6008 + return js_mkerr_typed(js, JS_ERR_SYNTAX, "Invalid left-hand side expression in postfix operation"); 6009 + do_assign_op(js, op == TOK_POSTINC ? TOK_PLUS_ASSIGN : TOK_MINUS_ASSIGN, lhs, tov(1)); 6010 + return l; 6011 + } 6012 + 6013 + L_TOK_NOT: return mkval(T_BOOL, !js_truthy(js, r)); 5920 6014 5921 - switch (op) { 5922 - case TOK_TYPEOF: { 5923 - const char *ts = typestr(vtype(r)); 5924 - return js_mkstr(js, ts, strlen(ts)); 5925 - } 5926 - case TOK_VOID: return js_mkundef(); 5927 - case TOK_INSTANCEOF: return do_instanceof(js, l, r); 5928 - case TOK_IN: return do_in(js, l, r); 5929 - case TOK_CALL: return do_call_op(js, l, r); 5930 - case TOK_BRACKET: return do_bracket_op(js, l, rhs); 5931 - case TOK_ASSIGN: return assign(js, lhs, r); 5932 - case TOK_DOT: return do_dot_op(js, l, r); 5933 - case TOK_OPTIONAL_CHAIN: return do_optional_chain_op(js, l, r); 5934 - case TOK_POSTINC: { 5935 - if (vtype(lhs) != T_PROP) return js_mkerr_typed(js, JS_ERR_SYNTAX, "Invalid left-hand side expression in postfix operation"); 5936 - do_assign_op(js, TOK_PLUS_ASSIGN, lhs, tov(1)); return l; 5937 - } 5938 - case TOK_POSTDEC: { 5939 - if (vtype(lhs) != T_PROP) return js_mkerr_typed(js, JS_ERR_SYNTAX, "Invalid left-hand side expression in postfix operation"); 5940 - do_assign_op(js, TOK_MINUS_ASSIGN, lhs, tov(1)); return l; 5941 - } 5942 - case TOK_NOT: return mkval(T_BOOL, !js_truthy(js, r)); 5943 - case TOK_UMINUS: 5944 - if (vtype(r) == T_BIGINT) return bigint_neg(js, r); 5945 - break; 5946 - case TOK_UPLUS: 5947 - if (vtype(r) == T_BIGINT) return js_mkerr(js, "Cannot convert a BigInt value to a number"); 5948 - break; 5949 - } 5950 - if (is_assign(op)) return do_assign_op(js, op, lhs, r); 5951 - if (op == TOK_SEQ || op == TOK_SNE) { 5952 - bool eq = false; 5953 - if (vtype(l) == vtype(r)) { 5954 - if (vtype(l) == T_STR) { 5955 - jsoff_t n1, off1 = vstr(js, l, &n1); 5956 - jsoff_t n2, off2 = vstr(js, r, &n2); 5957 - eq = n1 == n2 && memcmp(&js->mem[off1], &js->mem[off2], n1) == 0; 5958 - } else if (vtype(l) == T_NUM) { 5959 - eq = tod(l) == tod(r); 5960 - } else if (vtype(l) == T_BOOL) { 5961 - eq = vdata(l) == vdata(r); 5962 - } else if (vtype(l) == T_BIGINT) { 5963 - eq = bigint_compare(js, l, r) == 0; 5964 - } else { 5965 - eq = vdata(l) == vdata(r); 5966 - } 5967 - } 6015 + L_TOK_UMINUS: 6016 + if (vtype(r) == T_BIGINT) return bigint_neg(js, r); 6017 + return tov(-js_to_number(js, r)); 6018 + 6019 + L_TOK_UPLUS: 6020 + if (vtype(r) == T_BIGINT) return js_mkerr(js, "Cannot convert a BigInt value to a number"); 6021 + return tov(js_to_number(js, r)); 6022 + 6023 + L_TOK_TILDA: return tov((double)(~js_to_int32(js_to_number(js, r)))); 6024 + 6025 + L_TOK_SEQ: 6026 + L_TOK_SNE: { 6027 + bool eq = strict_eq_values(js, l, r); 5968 6028 return mkval(T_BOOL, op == TOK_SEQ ? eq : !eq); 5969 6029 } 5970 - if (op == TOK_EQ || op == TOK_NE) { 6030 + 6031 + L_TOK_EQ: 6032 + L_TOK_NE: { 5971 6033 bool eq = false; 5972 - if ((vtype(l) == T_NULL && vtype(r) == T_NULL) || (vtype(l) == T_UNDEF && vtype(r) == T_UNDEF)) { 6034 + uint8_t lt = vtype(l), rt = vtype(r); 6035 + 6036 + if ((lt == T_NULL && rt == T_NULL) || (lt == T_UNDEF && rt == T_UNDEF) || 6037 + (lt == T_UNDEF && rt == T_NULL) || (lt == T_NULL && rt == T_UNDEF)) { 5973 6038 eq = true; 5974 - } else if ((vtype(l) == T_UNDEF && vtype(r) == T_NULL) || (vtype(l) == T_NULL && vtype(r) == T_UNDEF)) { 5975 - eq = true; 5976 - } else if (vtype(l) == T_NULL || vtype(r) == T_NULL || vtype(l) == T_UNDEF || vtype(r) == T_UNDEF) { 6039 + } else if (lt == T_NULL || rt == T_NULL || lt == T_UNDEF || rt == T_UNDEF) { 5977 6040 eq = false; 5978 - } else if (vtype(l) == vtype(r)) { 5979 - if (vtype(l) == T_STR) { 5980 - jsoff_t n1, off1 = vstr(js, l, &n1); 5981 - jsoff_t n2, off2 = vstr(js, r, &n2); 5982 - eq = n1 == n2 && memcmp(&js->mem[off1], &js->mem[off2], n1) == 0; 5983 - } else if (vtype(l) == T_NUM) { 5984 - eq = tod(l) == tod(r); 5985 - } else if (vtype(l) == T_BOOL) { 5986 - eq = vdata(l) == vdata(r); 5987 - } else if (vtype(l) == T_BIGINT) { 5988 - eq = bigint_compare(js, l, r) == 0; 5989 - } else { 5990 - eq = vdata(l) == vdata(r); 5991 - } 5992 - } else if ((vtype(l) == T_BIGINT && vtype(r) == T_NUM) || (vtype(l) == T_NUM && vtype(r) == T_BIGINT)) { 5993 - double num_val = vtype(l) == T_NUM ? tod(l) : tod(r); 5994 - jsval_t bigint_val = vtype(l) == T_BIGINT ? l : r; 6041 + } else if (lt == rt) { 6042 + eq = strict_eq_values(js, l, r); 6043 + } else if ((lt == T_BIGINT && rt == T_NUM) || (lt == T_NUM && rt == T_BIGINT)) { 6044 + double num_val = lt == T_NUM ? tod(l) : tod(r); 6045 + jsval_t bigint_val = lt == T_BIGINT ? l : r; 5995 6046 if (isfinite(num_val) && num_val == trunc(num_val)) { 5996 6047 bool neg = num_val < 0; 5997 6048 if (neg) num_val = -num_val; 5998 6049 char buf[64]; 5999 6050 snprintf(buf, sizeof(buf), "%.0f", num_val); 6000 - jsval_t num_as_bigint = mkbigint(js, buf, strlen(buf), neg); 6001 - eq = bigint_compare(js, bigint_val, num_as_bigint) == 0; 6051 + eq = bigint_compare(js, bigint_val, mkbigint(js, buf, strlen(buf), neg)) == 0; 6002 6052 } 6003 - } else if (vtype(l) == T_BOOL) { 6004 - double lnum = vdata(l) ? 1.0 : 0.0; 6005 - jsval_t result = do_op(js, op, tov(lnum), r); 6006 - return result; 6007 - } else if (vtype(r) == T_BOOL) { 6008 - double rnum = vdata(r) ? 1.0 : 0.0; 6009 - jsval_t result = do_op(js, op, l, tov(rnum)); 6010 - return result; 6011 - } else if ((vtype(l) == T_NUM && vtype(r) == T_STR) || (vtype(l) == T_STR && vtype(r) == T_NUM)) { 6012 - double lnum = js_to_number(js, l); 6013 - double rnum = js_to_number(js, r); 6014 - eq = lnum == rnum; 6015 - } else if (vtype(l) == T_ARR || vtype(l) == T_OBJ) { 6053 + } else if (lt == T_BOOL) { 6054 + return do_op(js, op, tov(vdata(l) ? 1.0 : 0.0), r); 6055 + } else if (rt == T_BOOL) { 6056 + return do_op(js, op, l, tov(vdata(r) ? 1.0 : 0.0)); 6057 + } else if ((lt == T_NUM && rt == T_STR) || (lt == T_STR && rt == T_NUM)) { 6058 + eq = js_to_number(js, l) == js_to_number(js, r); 6059 + } else if (lt == T_ARR || lt == T_OBJ) { 6016 6060 jsval_t l_prim = js_tostring_val(js, l); 6017 6061 if (!is_err(l_prim)) return do_op(js, op, l_prim, r); 6018 - } else if (vtype(r) == T_ARR || vtype(r) == T_OBJ) { 6062 + } else if (rt == T_ARR || rt == T_OBJ) { 6019 6063 jsval_t r_prim = js_tostring_val(js, r); 6020 6064 if (!is_err(r_prim)) return do_op(js, op, l, r_prim); 6021 6065 } 6022 6066 return mkval(T_BOOL, op == TOK_EQ ? eq : !eq); 6023 6067 } 6024 - if (vtype(l) == T_BIGINT || vtype(r) == T_BIGINT) { 6025 - if (vtype(l) != T_BIGINT || vtype(r) != T_BIGINT) { 6068 + 6069 + L_TOK_PLUS: { 6070 + if (vtype(l) == T_BIGINT && vtype(r) == T_BIGINT) return bigint_add(js, l, r); 6071 + if (vtype(l) == T_BIGINT || vtype(r) == T_BIGINT) 6026 6072 return js_mkerr(js, "Cannot mix BigInt value and other types"); 6027 - } 6028 - switch (op) { 6029 - case TOK_PLUS: return bigint_add(js, l, r); 6030 - case TOK_MINUS: return bigint_sub(js, l, r); 6031 - case TOK_MUL: return bigint_mul(js, l, r); 6032 - case TOK_DIV: return bigint_div(js, l, r); 6033 - case TOK_REM: return bigint_mod(js, l, r); 6034 - case TOK_EXP: return bigint_exp(js, l, r); 6035 - case TOK_LT: return mkval(T_BOOL, bigint_compare(js, l, r) < 0); 6036 - case TOK_GT: return mkval(T_BOOL, bigint_compare(js, l, r) > 0); 6037 - case TOK_LE: return mkval(T_BOOL, bigint_compare(js, l, r) <= 0); 6038 - case TOK_GE: return mkval(T_BOOL, bigint_compare(js, l, r) >= 0); 6039 - default: return js_mkerr(js, "Unsupported BigInt operation"); 6040 - } 6041 - } 6042 - 6043 - if (op == TOK_PLUS && (is_non_numeric(l) || is_non_numeric(r))) { 6044 - jsval_t l_str = l, r_str = r; 6045 - 6046 - if (vtype(l) == T_ARR) { 6047 - char buf[1024]; 6048 - size_t len = array_to_string(js, l, buf, sizeof(buf)); 6049 - l_str = js_mkstr(js, buf, len); 6050 - if (is_err(l_str)) return l_str; 6051 - } else if (vtype(l) != T_STR) { 6052 - l_str = js_tostring_val(js, l); 6073 + if (is_non_numeric(l) || is_non_numeric(r) || (vtype(l) == T_STR && vtype(r) == T_STR)) { 6074 + jsval_t l_str = coerce_to_str(js, l); 6053 6075 if (is_err(l_str)) return l_str; 6054 - } 6055 - 6056 - if (vtype(r) == T_ARR) { 6057 - char buf[1024]; 6058 - size_t len = array_to_string(js, r, buf, sizeof(buf)); 6059 - r_str = js_mkstr(js, buf, len); 6076 + jsval_t r_str = coerce_to_str(js, r); 6060 6077 if (is_err(r_str)) return r_str; 6061 - } else if (vtype(r) != T_STR) { 6062 - r_str = js_tostring_val(js, r); 6063 - if (is_err(r_str)) return r_str; 6078 + return do_string_op(js, op, l_str, r_str); 6064 6079 } 6065 - 6066 - return do_string_op(js, op, l_str, r_str); 6080 + return tov(js_to_number(js, l) + js_to_number(js, r)); 6067 6081 } 6068 - if (vtype(l) == T_STR && vtype(r) == T_STR) { 6069 - if (op == TOK_PLUS || op == TOK_LT || op == TOK_LE || op == TOK_GT || op == TOK_GE) { 6070 - return do_string_op(js, op, l, r); 6082 + 6083 + L_TOK_MINUS: 6084 + L_TOK_MUL: 6085 + L_TOK_DIV: 6086 + L_TOK_REM: 6087 + L_TOK_EXP: { 6088 + if (vtype(l) == T_BIGINT && vtype(r) == T_BIGINT) { 6089 + switch (op) { 6090 + case TOK_MINUS: return bigint_sub(js, l, r); 6091 + case TOK_MUL: return bigint_mul(js, l, r); 6092 + case TOK_DIV: return bigint_div(js, l, r); 6093 + case TOK_REM: return bigint_mod(js, l, r); 6094 + case TOK_EXP: return bigint_exp(js, l, r); 6095 + } 6071 6096 } 6072 - } 6073 - 6074 - double a = 0.0, b = 0.0; 6075 - 6076 - if (vtype(l) == T_NUM) { 6077 - a = tod(l); 6078 - } else if (vtype(l) == T_STR) { 6079 - jsoff_t slen, off = vstr(js, l, &slen); 6080 - char *endptr; 6081 - char temp[256]; 6082 - size_t copy_len = slen < sizeof(temp) - 1 ? slen : sizeof(temp) - 1; 6083 - memcpy(temp, &js->mem[off], copy_len); 6084 - temp[copy_len] = '\0'; 6085 - char *p = temp; 6086 - while (*p == ' ' || *p == '\t' || *p == '\n' || *p == '\r') p++; 6087 - if (*p == '\0') { 6088 - a = 0.0; 6089 - } else { 6090 - a = strtod(p, &endptr); 6091 - while (*endptr == ' ' || *endptr == '\t' || *endptr == '\n' || *endptr == '\r') endptr++; 6092 - if (endptr == p || *endptr != '\0') a = NAN; 6097 + if (vtype(l) == T_BIGINT || vtype(r) == T_BIGINT) 6098 + return js_mkerr(js, "Cannot mix BigInt value and other types"); 6099 + double a = js_to_number(js, l), b = js_to_number(js, r); 6100 + switch (op) { 6101 + case TOK_MINUS: return tov(a - b); 6102 + case TOK_MUL: return tov(a * b); 6103 + case TOK_DIV: return tov(a / b); 6104 + case TOK_REM: return tov(a - b * ((double)(long)(a / b))); 6105 + case TOK_EXP: return tov(pow(a, b)); 6093 6106 } 6094 - } else if (vtype(l) == T_BOOL) { 6095 - a = vdata(l) ? 1.0 : 0.0; 6096 - } else if (vtype(l) == T_NULL) { 6097 - a = 0.0; 6098 - } else if (vtype(l) == T_UNDEF) { 6099 - a = NAN; 6100 - } else if (vtype(l) == T_ARR) { 6101 - a = js_to_number(js, l); 6102 - } else if (vtype(l) == T_OBJ) { 6103 - jsoff_t vo_off = lkp_proto(js, l, "valueOf", 7); 6104 - if (vo_off != 0) { 6105 - jsval_t vo_fn = resolveprop(js, mkval(T_PROP, vo_off)); 6106 - if (vtype(vo_fn) == T_FUNC || vtype(vo_fn) == T_CFUNC) { 6107 - jsval_t saved_this = js->this_val; 6108 - js->this_val = l; 6109 - jsval_t prim = call_js_with_args(js, vo_fn, NULL, 0); 6110 - js->this_val = saved_this; 6111 - if (vtype(prim) == T_NUM) a = tod(prim); 6112 - else a = NAN; 6113 - } else a = NAN; 6114 - } else a = NAN; 6115 - } else { 6116 - a = NAN; 6117 6107 } 6118 - 6119 - if (vtype(r) == T_NUM) { 6120 - b = tod(r); 6121 - } else if (vtype(r) == T_STR) { 6122 - jsoff_t slen, off = vstr(js, r, &slen); 6123 - char *endptr; 6124 - char temp[256]; 6125 - size_t copy_len = slen < sizeof(temp) - 1 ? slen : sizeof(temp) - 1; 6126 - memcpy(temp, &js->mem[off], copy_len); 6127 - temp[copy_len] = '\0'; 6128 - char *p = temp; 6129 - while (*p == ' ' || *p == '\t' || *p == '\n' || *p == '\r') p++; 6130 - if (*p == '\0') { 6131 - b = 0.0; 6132 - } else { 6133 - b = strtod(p, &endptr); 6134 - while (*endptr == ' ' || *endptr == '\t' || *endptr == '\n' || *endptr == '\r') endptr++; 6135 - if (endptr == p || *endptr != '\0') b = NAN; 6108 + 6109 + L_TOK_LT: 6110 + L_TOK_LE: 6111 + L_TOK_GT: 6112 + L_TOK_GE: { 6113 + if (vtype(l) == T_BIGINT && vtype(r) == T_BIGINT) { 6114 + int cmp = bigint_compare(js, l, r); 6115 + switch (op) { 6116 + case TOK_LT: return mkval(T_BOOL, cmp < 0); 6117 + case TOK_LE: return mkval(T_BOOL, cmp <= 0); 6118 + case TOK_GT: return mkval(T_BOOL, cmp > 0); 6119 + case TOK_GE: return mkval(T_BOOL, cmp >= 0); 6120 + } 6136 6121 } 6137 - } else if (vtype(r) == T_BOOL) { 6138 - b = vdata(r) ? 1.0 : 0.0; 6139 - } else if (vtype(r) == T_NULL) { 6140 - b = 0.0; 6141 - } else if (vtype(r) == T_UNDEF) { 6142 - b = NAN; 6143 - } else if (vtype(r) == T_ARR) { 6144 - b = js_to_number(js, r); 6145 - } else if (vtype(r) == T_OBJ) { 6146 - jsoff_t vo_off = lkp_proto(js, r, "valueOf", 7); 6147 - if (vo_off != 0) { 6148 - jsval_t vo_fn = resolveprop(js, mkval(T_PROP, vo_off)); 6149 - if (vtype(vo_fn) == T_FUNC || vtype(vo_fn) == T_CFUNC) { 6150 - jsval_t saved_this = js->this_val; 6151 - js->this_val = r; 6152 - jsval_t prim = call_js_with_args(js, vo_fn, NULL, 0); 6153 - js->this_val = saved_this; 6154 - if (vtype(prim) == T_NUM) b = tod(prim); 6155 - else b = NAN; 6156 - } else b = NAN; 6157 - } else b = NAN; 6158 - } else { 6159 - b = NAN; 6122 + if (vtype(l) == T_BIGINT || vtype(r) == T_BIGINT) 6123 + return js_mkerr(js, "Cannot mix BigInt value and other types"); 6124 + if (vtype(l) == T_STR && vtype(r) == T_STR) 6125 + return do_string_op(js, op, l, r); 6126 + double a = js_to_number(js, l), b = js_to_number(js, r); 6127 + switch (op) { 6128 + case TOK_LT: return mkval(T_BOOL, a < b); 6129 + case TOK_LE: return mkval(T_BOOL, a <= b); 6130 + case TOK_GT: return mkval(T_BOOL, a > b); 6131 + case TOK_GE: return mkval(T_BOOL, a >= b); 6132 + } 6160 6133 } 6161 - 6162 - switch (op) { 6163 - case TOK_DIV: return tov(a / b); 6164 - case TOK_REM: return tov(a - b * ((double) (long) (a / b))); 6165 - case TOK_MUL: return tov(a * b); 6166 - case TOK_PLUS: return tov(a + b); 6167 - case TOK_MINUS: return tov(a - b); 6168 - case TOK_EXP: return tov(pow(a, b)); 6169 - case TOK_XOR: return tov((double)(js_to_int32(a) ^ js_to_int32(b))); 6170 - case TOK_AND: return tov((double)(js_to_int32(a) & js_to_int32(b))); 6171 - case TOK_OR: return tov((double)(js_to_int32(a) | js_to_int32(b))); 6172 - case TOK_UMINUS: return tov(-b); 6173 - case TOK_UPLUS: return tov(b); 6174 - case TOK_TILDA: return tov((double)(~js_to_int32(b))); 6175 - case TOK_SHL: return tov((double)(js_to_int32(a) << (js_to_uint32(b) & 0x1f))); 6176 - case TOK_SHR: return tov((double)(js_to_int32(a) >> (js_to_uint32(b) & 0x1f))); 6177 - case TOK_ZSHR: return tov((double)(js_to_uint32(a) >> (js_to_uint32(b) & 0x1f))); 6178 - case TOK_DOT: return do_dot_op(js, l, r); 6179 - case TOK_OPTIONAL_CHAIN: return do_optional_chain_op(js, l, r); 6180 - case TOK_LT: return mkval(T_BOOL, a < b); 6181 - case TOK_LE: return mkval(T_BOOL, a <= b); 6182 - case TOK_GT: return mkval(T_BOOL, a > b); 6183 - case TOK_GE: return mkval(T_BOOL, a >= b); 6184 - default: return js_mkerr(js, "unknown op %d", (int) op); 6134 + 6135 + L_TOK_XOR: 6136 + L_TOK_AND: 6137 + L_TOK_OR: 6138 + L_TOK_SHL: 6139 + L_TOK_SHR: 6140 + L_TOK_ZSHR: { 6141 + if (vtype(l) == T_BIGINT || vtype(r) == T_BIGINT) 6142 + return js_mkerr(js, "Cannot mix BigInt value and other types"); 6143 + int32_t ai = js_to_int32(js_to_number(js, l)); 6144 + uint32_t bi = js_to_uint32(js_to_number(js, r)); 6145 + switch (op) { 6146 + case TOK_XOR: return tov((double)(ai ^ (int32_t)bi)); 6147 + case TOK_AND: return tov((double)(ai & (int32_t)bi)); 6148 + case TOK_OR: return tov((double)(ai | (int32_t)bi)); 6149 + case TOK_SHL: return tov((double)(ai << (bi & 0x1f))); 6150 + case TOK_SHR: return tov((double)(ai >> (bi & 0x1f))); 6151 + case TOK_ZSHR: return tov((double)((uint32_t)ai >> (bi & 0x1f))); 6152 + } 6185 6153 } 6154 + 6155 + L_default: 6156 + if (is_assign(op)) return do_assign_op(js, op, lhs, r); 6157 + return js_mkerr(js, "unknown op %d", (int)op); 6186 6158 } 6187 6159 6188 6160 static jsval_t js_template_literal(struct js *js) {