diff options
author | bellard <6490144+bellard@users.noreply.github.com> | 2020-09-06 19:02:03 +0200 |
---|---|---|
committer | bellard <6490144+bellard@users.noreply.github.com> | 2020-09-06 19:02:03 +0200 |
commit | 383e2b06c8af144b5cd729dc7bc4ce2e2613f178 (patch) | |
tree | 77bf320a5bf01cbcd248f9b85a804980bc89f01d /quickjs.c | |
parent | 0e8fffd4de4a10f498f46cd0e99f53da6a523542 (diff) | |
download | quickjs-383e2b06c8af144b5cd729dc7bc4ce2e2613f178.tar.gz quickjs-383e2b06c8af144b5cd729dc7bc4ce2e2613f178.zip |
2020-03-16 release
Diffstat (limited to 'quickjs.c')
-rw-r--r-- | quickjs.c | 204 |
1 files changed, 128 insertions, 76 deletions
@@ -284,6 +284,7 @@ struct JSRuntime { JSNumericOperations bigdecimal_ops; uint32_t operator_count; #endif + void *user_opaque; }; struct JSClass { @@ -1537,6 +1538,16 @@ JSRuntime *JS_NewRuntime2(const JSMallocFunctions *mf, void *opaque) return NULL; } +void *JS_GetRuntimeOpaque(JSRuntime *rt) +{ + return rt->user_opaque; +} + +void JS_SetRuntimeOpaque(JSRuntime *rt, void *opaque) +{ + rt->user_opaque = opaque; +} + /* default memory allocation functions with memory limitation */ static inline size_t js_def_malloc_usable_size(void *ptr) { @@ -2198,26 +2209,6 @@ static inline BOOL is_math_mode(JSContext *ctx) } #endif -JSValue JS_NewInt64(JSContext *ctx, int64_t v) -{ - if (v == (int32_t)v) { - return JS_NewInt32(ctx, v); - } else { - return __JS_NewFloat64(ctx, (double)v); - } -} - -static force_inline JSValue JS_NewUint32(JSContext *ctx, uint32_t val) -{ - JSValue v; - if (val <= 0x7fffffff) { - v = JS_MKVAL(JS_TAG_INT, val); - } else { - v = __JS_NewFloat64(ctx, val); - } - return v; -} - /* JSAtom support */ #define JS_ATOM_TAG_INT (1U << 31) @@ -9794,6 +9785,8 @@ static JSValue js_atof(JSContext *ctx, const char *str, const char **pp, if (*p == '.' && (p > p_start || to_digit((uint8_t)p[1]) < radix)) { is_float = TRUE; p++; + if (*p == sep) + goto fail; while (to_digit((uint8_t)*p) < radix || (*p == sep && to_digit((uint8_t)p[1]) < radix)) p++; @@ -10129,7 +10122,6 @@ static __maybe_unused JSValue JS_ToIntegerFree(JSContext *ctx, JSValue val) ret = JS_NewInt32(ctx, 0); } else { /* convert -0 to +0 */ - /* XXX: should not be done here ? */ d = trunc(d) + 0.0; ret = JS_NewFloat64(ctx, d); } @@ -10385,6 +10377,14 @@ int JS_ToInt64(JSContext *ctx, int64_t *pres, JSValueConst val) return JS_ToInt64Free(ctx, pres, JS_DupValue(ctx, val)); } +int JS_ToInt64Ext(JSContext *ctx, int64_t *pres, JSValueConst val) +{ + if (JS_IsBigInt(ctx, val)) + return JS_ToBigInt64(ctx, pres, val); + else + return JS_ToInt64(ctx, pres, val); +} + /* return (<0, 0) in case of exception */ static int JS_ToInt32Free(JSContext *ctx, int32_t *pres, JSValue val) { @@ -11840,7 +11840,8 @@ static JSValue JS_CompactBigInt(JSContext *ctx, JSValue val) } /* must be kept in sync with JSOverloadableOperatorEnum */ -static const char *js_overloadable_operator_names[JS_OVOP_COUNT] = { +/* XXX: use atoms ? */ +static const char js_overloadable_operator_names[JS_OVOP_COUNT][4] = { "+", "-", "*", @@ -12894,7 +12895,7 @@ static no_inline __exception int js_binary_arith_slow(JSContext *ctx, JSValue *s handle_bigint: if (ctx->rt->bigint_ops.binary_arith(ctx, op, sp - 2, op1, op2)) goto exception; - } else if (tag1 == JS_TAG_FLOAT64 || tag2 == JS_TAG_FLOAT64) { + } else { double dr; /* float64 result */ if (JS_ToFloat64Free(ctx, &d1, op1)) { @@ -13031,7 +13032,11 @@ static no_inline __exception int js_add_slow(JSContext *ctx, JSValue *sp) } else if (tag1 == JS_TAG_BIG_FLOAT || tag2 == JS_TAG_BIG_FLOAT) { if (ctx->rt->bigfloat_ops.binary_arith(ctx, OP_add, sp - 2, op1, op2)) goto exception; - } else if (tag1 == JS_TAG_FLOAT64 || tag2 == JS_TAG_FLOAT64) { + } else if (tag1 == JS_TAG_BIG_INT || tag2 == JS_TAG_BIG_INT) { + handle_bigint: + if (ctx->rt->bigint_ops.binary_arith(ctx, OP_add, sp - 2, op1, op2)) + goto exception; + } else { double d1, d2; /* float64 result */ if (JS_ToFloat64Free(ctx, &d1, op1)) { @@ -13040,10 +13045,9 @@ static no_inline __exception int js_add_slow(JSContext *ctx, JSValue *sp) } if (JS_ToFloat64Free(ctx, &d2, op2)) goto exception; + if (is_math_mode(ctx) && is_safe_integer(d1) && is_safe_integer(d2)) + goto handle_bigint; sp[-2] = __JS_NewFloat64(ctx, d1 + d2); - } else { - if (ctx->rt->bigint_ops.binary_arith(ctx, OP_add, sp - 2, op1, op2)) - goto exception; } return 0; exception: @@ -13642,6 +13646,28 @@ static no_inline int js_mul_pow10(JSContext *ctx, JSValue *sp) #else /* !CONFIG_BIGNUM */ +static JSValue JS_ThrowUnsupportedBigint(JSContext *ctx) +{ + return JS_ThrowTypeError(ctx, "bigint is not supported"); +} + +JSValue JS_NewBigInt64(JSContext *ctx, int64_t v) +{ + return JS_ThrowUnsupportedBigint(ctx); +} + +JSValue JS_NewBigUint64(JSContext *ctx, uint64_t v) +{ + return JS_ThrowUnsupportedBigint(ctx); +} + +int JS_ToBigInt64(JSContext *ctx, int64_t *pres, JSValueConst val) +{ + JS_ThrowUnsupportedBigint(ctx); + *pres = 0; + return -1; +} + static no_inline __exception int js_unary_arith_slow(JSContext *ctx, JSValue *sp, OPCodeEnum op) @@ -16280,22 +16306,6 @@ static JSValue JS_CallInternal(JSContext *ctx, JSValueConst func_obj, } BREAK; - CASE(OP_get_super_ctor): - { - JSValue proto; - proto = JS_DupValue(ctx, JS_GetPrototype(ctx, sp[-1])); - if (JS_IsException(proto)) - goto exception; - if (!JS_IsConstructor(ctx, proto)) { - JS_FreeValue(ctx, proto); - JS_ThrowTypeError(ctx, "not a constructor"); - goto exception; - } - JS_FreeValue(ctx, sp[-1]); - sp[-1] = proto; - } - BREAK; - CASE(OP_get_super): { JSValue proto; @@ -23821,7 +23831,7 @@ static __exception int js_parse_postfix_expr(JSParseState *s, BOOL accept_lparen emit_atom(s, JS_ATOM_this_active_func); emit_u16(s, 0); - emit_op(s, OP_get_super_ctor); + emit_op(s, OP_get_super); emit_op(s, OP_scope_get_var); emit_atom(s, JS_ATOM_new_target); @@ -31993,10 +32003,10 @@ static __exception int js_parse_function_decl2(JSParseState *s, js_parse_expect(s, ')'); goto fail; } - if (s->token.val == ',') { - if (next_token(s)) - goto fail; - } + if (s->token.val == ')') + break; + if (js_parse_expect(s, ',')) + goto fail; } if ((func_type == JS_PARSE_FUNC_GETTER && fd->arg_count != 0) || (func_type == JS_PARSE_FUNC_SETTER && fd->arg_count != 1)) { @@ -34381,6 +34391,10 @@ int JS_SetModuleExportList(JSContext *ctx, JSModuleDef *m, case JS_DEF_PROP_DOUBLE: val = __JS_NewFloat64(ctx, e->u.f64); break; + case JS_DEF_OBJECT: + val = JS_NewObject(ctx); + JS_SetPropertyFunctionList(ctx, val, e->u.prop_list.tab, e->u.prop_list.len); + break; default: abort(); } @@ -37357,7 +37371,8 @@ static int64_t JS_FlattenIntoArray(JSContext *ctx, JSValueConst target, JS_ThrowTypeError(ctx, "Array too long"); goto fail; } - if (JS_SetPropertyInt64(ctx, target, targetIndex, element) < 0) + if (JS_DefinePropertyValueInt64(ctx, target, targetIndex, element, + JS_PROP_C_W_E | JS_PROP_THROW) < 0) return -1; targetIndex++; } @@ -37754,7 +37769,6 @@ static const JSCFunctionListEntry js_array_proto_funcs[] = { JS_CFUNC_DEF("copyWithin", 2, js_array_copyWithin ), JS_CFUNC_MAGIC_DEF("flatMap", 1, js_array_flatten, 1 ), JS_CFUNC_MAGIC_DEF("flat", 0, js_array_flatten, 0 ), - JS_CFUNC_MAGIC_DEF("flatten", 0, js_array_flatten, 0 ), JS_CFUNC_MAGIC_DEF("values", 0, js_create_array_iterator, JS_ITERATOR_KIND_VALUE ), JS_ALIAS_DEF("[Symbol.iterator]", "values" ), JS_CFUNC_MAGIC_DEF("keys", 0, js_create_array_iterator, JS_ITERATOR_KIND_KEY ), @@ -39918,14 +39932,36 @@ static JSValue js_math_hypot(JSContext *ctx, JSValueConst this_val, if (JS_ToFloat64(ctx, &b, argv[1])) return JS_EXCEPTION; r = hypot(a, b); - } else { + } else if (argc == 0) { r = 0; + } else { + double *tab, a_max; + tab = js_malloc(ctx, sizeof(tab[0]) * argc); + if (!tab) + return JS_EXCEPTION; + /* avoid overflow by taking the maximum */ + a_max = 0; for(i = 0; i < argc; i++) { - if (JS_ToFloat64(ctx, &a, argv[i])) + if (JS_ToFloat64(ctx, &a, argv[i])) { + js_free(ctx, tab); return JS_EXCEPTION; - r += a; + } + a = fabs(a); + tab[i] = a; + if (a > a_max) + a_max = a; + } + if (a_max == 0 || !isfinite(a_max)) { + r = a_max; + } else { + r = 0; + for(i = 0; i < argc; i++) { + a = tab[i] / a_max; + r += a * a; + } + r = a_max * sqrt(r); } - r = sqrt(r); + js_free(ctx, tab); } return JS_NewFloat64(ctx, r); } @@ -45234,10 +45270,10 @@ static JSValue js_promise_then_finally_func(JSContext *ctx, JSValueConst this_va } JS_FreeValue(ctx, ret); if (magic == 0) { - then_func = JS_NewCFunctionData(ctx, js_promise_finally_value_thunk, 1, + then_func = JS_NewCFunctionData(ctx, js_promise_finally_value_thunk, 0, 0, 1, argv); } else { - then_func = JS_NewCFunctionData(ctx, js_promise_finally_thrower, 1, + then_func = JS_NewCFunctionData(ctx, js_promise_finally_thrower, 0, 0, 1, argv); } if (JS_IsException(then_func)) { @@ -50037,7 +50073,7 @@ static JSValue js_typed_array_indexOf(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv, int special) { JSObject *p; - int len, tag, is_int, is_big, k, stop, inc, res = -1; + int len, tag, is_int, is_bigint, k, stop, inc, res = -1; int64_t v64; double d; float f; @@ -50080,7 +50116,11 @@ static JSValue js_typed_array_indexOf(JSContext *ctx, JSValueConst this_val, inc = 1; } - is_big = 0; + if (validate_typed_array(ctx, this_val)) + goto exception; + p = JS_VALUE_GET_OBJ(this_val); + + is_bigint = 0; is_int = 0; /* avoid warning */ v64 = 0; /* avoid warning */ tag = JS_VALUE_GET_NORM_TAG(argv[0]); @@ -50095,10 +50135,20 @@ static JSValue js_typed_array_indexOf(JSContext *ctx, JSValueConst this_val, is_int = (v64 == d); } else #ifdef CONFIG_BIGNUM - if (tag == JS_TAG_BIG_INT || tag == JS_TAG_BIG_FLOAT) { - /* will a generic loop for bigint and bigfloat */ - /* XXX: should use the generic loop in math_mode? */ - is_big = 1; + if (tag == JS_TAG_BIG_INT) { + JSBigFloat *p1 = JS_VALUE_GET_PTR(argv[0]); + + if (p->class_id == JS_CLASS_BIG_INT64_ARRAY) { + if (bf_get_int64(&v64, &p1->num, 0) != 0) + goto done; + } else if (p->class_id == JS_CLASS_BIG_UINT64_ARRAY) { + if (bf_get_uint64((uint64_t *)&v64, &p1->num) != 0) + goto done; + } else { + goto done; + } + d = 0; + is_bigint = 1; } else #endif { @@ -50172,7 +50222,7 @@ static JSValue js_typed_array_indexOf(JSContext *ctx, JSValueConst this_val, } break; case JS_CLASS_FLOAT32_ARRAY: - if (is_big) + if (is_bigint) break; if (isnan(d)) { const float *pv = p->u.array.u.float_ptr; @@ -50196,7 +50246,7 @@ static JSValue js_typed_array_indexOf(JSContext *ctx, JSValueConst this_val, } break; case JS_CLASS_FLOAT64_ARRAY: - if (is_big) + if (is_bigint) break; if (isnan(d)) { const double *pv = p->u.array.u.double_ptr; @@ -50221,20 +50271,22 @@ static JSValue js_typed_array_indexOf(JSContext *ctx, JSValueConst this_val, break; #ifdef CONFIG_BIGNUM case JS_CLASS_BIG_INT64_ARRAY: + if (is_bigint || (is_math_mode(ctx) && is_int && + v64 >= -MAX_SAFE_INTEGER && + v64 <= MAX_SAFE_INTEGER)) { + goto scan64; + } + break; case JS_CLASS_BIG_UINT64_ARRAY: - if (is_big || is_strict_mode(ctx)) { - /* generic loop for bignums, argv[0] is a bignum != NaN */ - /* XXX: optimize with explicit values */ + if (is_bigint || (is_math_mode(ctx) && is_int && + v64 >= 0 && v64 <= MAX_SAFE_INTEGER)) { + const uint64_t *pv; + uint64_t v; + scan64: + pv = p->u.array.u.uint64_ptr; + v = v64; for (; k != stop; k += inc) { - JSValue v = JS_GetPropertyUint32(ctx, this_val, k); - int ret; - if (JS_IsException(v)) - goto exception; - ret = js_same_value_zero(ctx, v, argv[0]); - JS_FreeValue(ctx, v); - if (ret) { - if (ret < 0) - goto exception; + if (pv[k] == v) { res = k; break; } |