summaryrefslogtreecommitdiff
path: root/Userland/Libraries
diff options
context:
space:
mode:
authorAnonymous <anon@mous.org>2022-02-16 02:14:57 -0800
committerLinus Groh <mail@linusgroh.de>2022-02-16 11:18:41 +0000
commit1e0facb7ee71a8611052b4f87bd36a435d35050a (patch)
tree5d79ed00f44e5d4927a35c373dcc0514ba29bc95 /Userland/Libraries
parent602190f66f7d74bba019b42870d1fc93e5a26a51 (diff)
downloadserenity-1e0facb7ee71a8611052b4f87bd36a435d35050a.zip
LibJS: Implement the Number::remainder AO using fmod
The ECMA verbiage for modulus is the mathematical definition implemented by fmod, so let's just use that rather than trying to reimplement all the edge cases.
Diffstat (limited to 'Userland/Libraries')
-rw-r--r--Userland/Libraries/LibJS/Runtime/Value.cpp35
-rw-r--r--Userland/Libraries/LibJS/Tests/operators/modulo-basic.js1
-rw-r--r--Userland/Libraries/LibJS/Tests/test-common.js3
3 files changed, 9 insertions, 30 deletions
diff --git a/Userland/Libraries/LibJS/Runtime/Value.cpp b/Userland/Libraries/LibJS/Runtime/Value.cpp
index 01f14e2be3..60e59714d4 100644
--- a/Userland/Libraries/LibJS/Runtime/Value.cpp
+++ b/Userland/Libraries/LibJS/Runtime/Value.cpp
@@ -1178,36 +1178,11 @@ ThrowCompletionOr<Value> mod(GlobalObject& global_object, Value lhs, Value rhs)
auto rhs_numeric = TRY(rhs.to_numeric(global_object));
if (both_number(lhs_numeric, rhs_numeric)) {
// 6.1.6.1.6 Number::remainder ( n, d ), https://tc39.es/ecma262/#sec-numeric-types-number-remainder
-
- // 1. If n is NaN or d is NaN, return NaN.
- if (lhs_numeric.is_nan() || rhs_numeric.is_nan())
- return js_nan();
-
- // 2. If n is +∞𝔽 or n is -∞𝔽, return NaN.
- if (lhs_numeric.is_positive_infinity() || lhs_numeric.is_negative_infinity())
- return js_nan();
-
- // 3. If d is +∞𝔽 or d is -∞𝔽, return n.
- if (rhs_numeric.is_positive_infinity() || rhs_numeric.is_negative_infinity())
- return lhs_numeric;
-
- // 4. If d is +0𝔽 or d is -0𝔽, return NaN.
- if (rhs_numeric.is_positive_zero() || rhs_numeric.is_negative_zero())
- return js_nan();
-
- // 5. If n is +0𝔽 or n is -0𝔽, return n.
- if (lhs_numeric.is_positive_zero() || lhs_numeric.is_negative_zero())
- return lhs_numeric;
-
- // 6. Assert: n and d are finite and non-zero.
-
- auto index = lhs_numeric.as_double();
- auto period = rhs_numeric.as_double();
- auto trunc = (double)(i32)(index / period);
-
- // 7. Let r be ℝ(n) - (ℝ(d) × q) where q is an integer that is negative if and only if n and d have opposite sign, and whose magnitude is as large as possible without exceeding the magnitude of ℝ(n) / ℝ(d).
- // 8. Return 𝔽(r).
- return Value(index - trunc * period);
+ // The ECMA specification is describing the mathematical definition of modulus
+ // implemented by fmod.
+ auto n = lhs_numeric.as_double();
+ auto d = rhs_numeric.as_double();
+ return Value(fmod(n, d));
}
if (both_bigint(lhs_numeric, rhs_numeric)) {
if (rhs_numeric.as_bigint().big_integer() == BIGINT_ZERO)
diff --git a/Userland/Libraries/LibJS/Tests/operators/modulo-basic.js b/Userland/Libraries/LibJS/Tests/operators/modulo-basic.js
index c364feaddb..0c30123be9 100644
--- a/Userland/Libraries/LibJS/Tests/operators/modulo-basic.js
+++ b/Userland/Libraries/LibJS/Tests/operators/modulo-basic.js
@@ -23,6 +23,7 @@ test("basic functionality", () => {
expect(1 % -0).toBeNaN();
expect(0 % 5).toBe(0);
expect(-0 % 5).toBe(-0);
+ expect((-1) % -1).toBe(-0);
// test262 examples
expect(1 % null).toBeNaN();
diff --git a/Userland/Libraries/LibJS/Tests/test-common.js b/Userland/Libraries/LibJS/Tests/test-common.js
index 1f9e3af979..b02c9cb287 100644
--- a/Userland/Libraries/LibJS/Tests/test-common.js
+++ b/Userland/Libraries/LibJS/Tests/test-common.js
@@ -53,6 +53,9 @@ class ExpectationError extends Error {
const valueToString = value => {
try {
+ if (value === 0 && 1 / value < 0) {
+ return "-0";
+ }
return String(value);
} catch {
// e.g for objects without a prototype, the above throws.