summaryrefslogtreecommitdiff
path: root/js/src/jsnum.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'js/src/jsnum.cpp')
-rw-r--r--js/src/jsnum.cpp110
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,