diff options
Diffstat (limited to 'js/src/jsnum.cpp')
-rw-r--r-- | js/src/jsnum.cpp | 110 |
1 files changed, 101 insertions, 9 deletions
diff --git a/js/src/jsnum.cpp b/js/src/jsnum.cpp index 549596e579..fd23e6ccd5 100644 --- a/js/src/jsnum.cpp +++ b/js/src/jsnum.cpp @@ -524,21 +524,30 @@ Number(JSContext* cx, unsigned argc, Value* vp) bool isConstructing = args.isConstructing(); if (args.length() > 0) { - if (!ToNumber(cx, args[0])) + // BigInt proposal section 6.2, steps 2a-c. + if (!ToNumeric(cx, args[0])) return false; - args.rval().set(args[0]); - } else { - args.rval().setInt32(0); + if (args[0].isBigInt()) + args[0].setNumber(BigInt::numberValue(args[0].toBigInt())); + MOZ_ASSERT(args[0].isNumber()); } - if (!isConstructing) + if (!isConstructing) { + if (args.length() > 0) { + args.rval().set(args[0]); + } else { + args.rval().setInt32(0); + } return true; + } RootedObject newTarget(cx, &args.newTarget().toObject()); RootedObject proto(cx); if (!GetPrototypeFromConstructor(cx, newTarget, &proto)) return false; - JSObject* obj = NumberObject::create(cx, args.rval().toNumber(), proto); + + double d = args.length() > 0 ? args[0].toNumber() : 0; + JSObject* obj = NumberObject::create(cx, d, proto); if (!obj) return false; args.rval().setObject(*obj); @@ -1452,9 +1461,19 @@ js::ToNumberSlow(ExclusiveContext* cx, HandleValue v_, double* out) return false; } - MOZ_ASSERT(v.isUndefined()); - *out = GenericNaN(); - return true; + if (v.isUndefined()) { + *out = GenericNaN(); + return true; + } + + MOZ_ASSERT(v.isSymbol() || v.isBigInt()); + if (cx->isJSContext()) { + unsigned errnum = JSMSG_SYMBOL_TO_NUMBER; + if (v.isBigInt()) + errnum = JSMSG_BIGINT_TO_NUMBER; + JS_ReportErrorNumberASCII(cx->asJSContext(), GetErrorMessage, nullptr, errnum); + } + return false; } JS_PUBLIC_API(bool) @@ -1482,6 +1501,29 @@ js::ToInt8Slow(JSContext *cx, const HandleValue v, int8_t *out) return true; } +// BigInt proposal section 3.1.6 +bool +js::ToNumericSlow(ExclusiveContext* cx, MutableHandleValue vp) +{ + MOZ_ASSERT(!vp.isNumeric()); + + // Step 1. + if (!vp.isPrimitive()) { + if (!cx->isJSContext()) + return false; + if (!ToPrimitive(cx->asJSContext(), JSTYPE_NUMBER, vp)) + return false; + } + + // Step 2. + if (vp.isBigInt()) { + return true; + } + + // Step 3. + return ToNumber(cx->asJSContext(), vp); +} + /* * Convert a value to an uint8_t, according to the ToUInt8() function in ES6 * ECMA-262, 7.1.10. Return converted value in *out on success, false on failure. @@ -1573,6 +1615,27 @@ js::ToInt32Slow(JSContext* cx, const HandleValue v, int32_t* out) return true; } +bool +js::ToInt32OrBigIntSlow(JSContext* cx, MutableHandleValue vp) +{ + MOZ_ASSERT(!vp.isInt32()); + if (vp.isDouble()) { + vp.setInt32(ToInt32(vp.toDouble())); + return true; + } + + if (!ToNumeric(cx, vp)) { + return false; + } + + if (vp.isBigInt()) { + return true; + } + + vp.setInt32(ToInt32(vp.toNumber())); + return true; +} + JS_PUBLIC_API(bool) js::ToUint32Slow(JSContext* cx, const HandleValue v, uint32_t* out) { @@ -1706,6 +1769,35 @@ js::ToIntegerIndex(JSContext* cx, JS::HandleValue v, uint64_t* index) return true; } +// ES2017 draft 7.1.17 ToIndex +bool +js::ToIndex(JSContext* cx, JS::HandleValue v, uint64_t* index) +{ + // Step 1. + if (v.isUndefined()) { + *index = 0; + return true; + } + + // Step 2.a. + double integerIndex; + if (!ToInteger(cx, v, &integerIndex)) + return false; + + // Inlined version of ToLength. + // 1. Already an integer. + // 2. Step eliminates < 0, +0 == -0 with SameValueZero. + // 3/4. Limit to <= 2^53-1, so everything above should fail. + if (integerIndex < 0 || integerIndex >= DOUBLE_INTEGRAL_PRECISION_LIMIT) { + JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_BAD_INDEX); + return false; + } + + // Step 3. + *index = uint64_t(integerIndex); + return true; +} + template <typename CharT> bool js_strtod(ExclusiveContext* cx, const CharT* begin, const CharT* end, const CharT** dEnd, |