summaryrefslogtreecommitdiff
path: root/Userland/Libraries/LibJS
diff options
context:
space:
mode:
authorLuke <luke.wilde@live.co.uk>2021-06-17 00:13:26 +0100
committerLinus Groh <mail@linusgroh.de>2021-06-17 02:20:03 +0100
commit7ff144d533514420a60395e7dc9b41397846d90a (patch)
treec118b38a019ea5ac739e96bf1484941b65e08c98 /Userland/Libraries/LibJS
parent93996eb48e7043fbca5e4dbb31f655d441587867 (diff)
downloadserenity-7ff144d533514420a60395e7dc9b41397846d90a.zip
LibJS: Add a bunch of numeric conversions to Value
Namely: - BigInt64 - BigUint64 - i16 - u16 - i8 - u8 - Clamped u8 These will be used in ArrayBuffer::numeric_to_raw_bytes later.
Diffstat (limited to 'Userland/Libraries/LibJS')
-rw-r--r--Userland/Libraries/LibJS/Runtime/Value.cpp113
-rw-r--r--Userland/Libraries/LibJS/Runtime/Value.h7
2 files changed, 120 insertions, 0 deletions
diff --git a/Userland/Libraries/LibJS/Runtime/Value.cpp b/Userland/Libraries/LibJS/Runtime/Value.cpp
index bff74edc29..ab045e17a9 100644
--- a/Userland/Libraries/LibJS/Runtime/Value.cpp
+++ b/Userland/Libraries/LibJS/Runtime/Value.cpp
@@ -548,6 +548,24 @@ BigInt* Value::to_bigint(GlobalObject& global_object) const
}
}
+// 7.1.15 ToBigInt64 ( argument ), https://tc39.es/ecma262/multipage/abstract-operations.html#sec-tobigint64
+i64 Value::to_bigint_int64(GlobalObject& global_object) const
+{
+ auto* bigint = to_bigint(global_object);
+ if (global_object.vm().exception())
+ return INVALID;
+ return static_cast<i64>(bigint->big_integer().to_u64());
+}
+
+// 7.1.16 ToBigUint64 ( argument ), https://tc39.es/ecma262/multipage/abstract-operations.html#sec-tobiguint64
+u64 Value::to_bigint_uint64(GlobalObject& global_object) const
+{
+ auto* bigint = to_bigint(global_object);
+ if (global_object.vm().exception())
+ return INVALID;
+ return bigint->big_integer().to_u64();
+}
+
// FIXME: These two conversions are wrong for JS, and seem likely to be footguns
i32 Value::as_i32() const
{
@@ -615,6 +633,101 @@ u32 Value::to_u32(GlobalObject& global_object) const
return static_cast<u32>(int32bit);
}
+// 7.1.8 ToInt16 ( argument ), https://tc39.es/ecma262/#sec-toint16
+i16 Value::to_i16(GlobalObject& global_object) const
+{
+ auto number = to_number(global_object);
+ if (global_object.vm().exception())
+ return INVALID;
+ double value = number.as_double();
+ if (!isfinite(value) || value == 0)
+ return 0;
+ auto abs = fabs(value);
+ auto int_val = floor(abs);
+ if (signbit(value))
+ int_val = -int_val;
+ auto remainder = fmod(int_val, 65536.0);
+ auto int16bit = remainder >= 0.0 ? remainder : remainder + 65536.0; // The notation “x modulo y” computes a value k of the same sign as y
+ if (int16bit >= 32768.0)
+ int16bit -= 65536.0;
+ return static_cast<i16>(int16bit);
+}
+
+// 7.1.9 ToUint16 ( argument ), https://tc39.es/ecma262/#sec-touint16
+u16 Value::to_u16(GlobalObject& global_object) const
+{
+ auto number = to_number(global_object);
+ if (global_object.vm().exception())
+ return INVALID;
+ double value = number.as_double();
+ if (!isfinite(value) || value == 0)
+ return 0;
+ auto int_val = floor(fabs(value));
+ if (signbit(value))
+ int_val = -int_val;
+ auto int16bit = fmod(int_val, NumericLimits<u16>::max() + 1.0);
+ return static_cast<u16>(int16bit);
+}
+
+// 7.1.10 ToInt8 ( argument ), https://tc39.es/ecma262/#sec-toint8
+i8 Value::to_i8(GlobalObject& global_object) const
+{
+ auto number = to_number(global_object);
+ if (global_object.vm().exception())
+ return INVALID;
+ double value = number.as_double();
+ if (!isfinite(value) || value == 0)
+ return 0;
+ auto abs = fabs(value);
+ auto int_val = floor(abs);
+ if (signbit(value))
+ int_val = -int_val;
+ auto remainder = fmod(int_val, 256.0);
+ auto int8bit = remainder >= 0.0 ? remainder : remainder + 256.0; // The notation “x modulo y” computes a value k of the same sign as y
+ if (int8bit >= 128.0)
+ int8bit -= 256.0;
+ return static_cast<i8>(int8bit);
+}
+
+// 7.1.11 ToUint8 ( argument ), https://tc39.es/ecma262/#sec-touint8
+u8 Value::to_u8(GlobalObject& global_object) const
+{
+ auto number = to_number(global_object);
+ if (global_object.vm().exception())
+ return INVALID;
+ double value = number.as_double();
+ if (!isfinite(value) || value == 0)
+ return 0;
+ auto int_val = floor(fabs(value));
+ if (signbit(value))
+ int_val = -int_val;
+ auto int8bit = fmod(int_val, NumericLimits<u8>::max() + 1.0);
+ return static_cast<u8>(int8bit);
+}
+
+// 7.1.12 ToUint8Clamp ( argument ), https://tc39.es/ecma262/#sec-touint8clamp
+u8 Value::to_u8_clamp(GlobalObject& global_object) const
+{
+ auto number = to_number(global_object);
+ if (global_object.vm().exception())
+ return INVALID;
+ if (number.is_nan())
+ return 0;
+ double value = number.as_double();
+ if (value <= 0.0)
+ return 0;
+ if (value >= 255.0)
+ return 255;
+ auto int_val = floor(value);
+ if (int_val + 0.5 < value)
+ return static_cast<u8>(int_val + 1.0);
+ if (value < int_val + 0.5)
+ return static_cast<u8>(int_val);
+ if (fmod(int_val, 2.0) == 1.0)
+ return static_cast<u8>(int_val + 1.0);
+ return static_cast<u8>(int_val);
+}
+
// 7.1.20 ToLength ( argument ), https://tc39.es/ecma262/#sec-tolength
size_t Value::to_length(GlobalObject& global_object) const
{
diff --git a/Userland/Libraries/LibJS/Runtime/Value.h b/Userland/Libraries/LibJS/Runtime/Value.h
index 2e861feb99..09eca1530b 100644
--- a/Userland/Libraries/LibJS/Runtime/Value.h
+++ b/Userland/Libraries/LibJS/Runtime/Value.h
@@ -265,6 +265,8 @@ public:
Value to_numeric(GlobalObject&) const;
Value to_number(GlobalObject&) const;
BigInt* to_bigint(GlobalObject&) const;
+ i64 to_bigint_int64(GlobalObject&) const;
+ u64 to_bigint_uint64(GlobalObject&) const;
double to_double(GlobalObject&) const;
StringOrSymbol to_property_key(GlobalObject&) const;
i32 to_i32(GlobalObject& global_object) const
@@ -274,6 +276,11 @@ public:
return to_i32_slow_case(global_object);
}
u32 to_u32(GlobalObject&) const;
+ i16 to_i16(GlobalObject&) const;
+ u16 to_u16(GlobalObject&) const;
+ i8 to_i8(GlobalObject&) const;
+ u8 to_u8(GlobalObject&) const;
+ u8 to_u8_clamp(GlobalObject&) const;
size_t to_length(GlobalObject&) const;
size_t to_index(GlobalObject&) const;
double to_integer_or_infinity(GlobalObject&) const;