Skip to content

Commit c206693

Browse files
Lubrsilinusg
authored andcommitted
LibJS: Handle +Infinity, -Infinity, +0 and -0 in modulo operator
Fixes 11 test262 cases.
1 parent 3282510 commit c206693

File tree

2 files changed

+47
-0
lines changed

2 files changed

+47
-0
lines changed

Userland/Libraries/LibJS/Runtime/Value.cpp

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1212,11 +1212,36 @@ Value mod(GlobalObject& global_object, Value lhs, Value rhs)
12121212
if (vm.exception())
12131213
return {};
12141214
if (both_number(lhs_numeric, rhs_numeric)) {
1215+
// 6.1.6.1.6 Number::remainder ( n, d ), https://tc39.es/ecma262/#sec-numeric-types-number-remainder
1216+
1217+
// 1. If n is NaN or d is NaN, return NaN.
12151218
if (lhs_numeric.is_nan() || rhs_numeric.is_nan())
12161219
return js_nan();
1220+
1221+
// 2. If n is +∞𝔽 or n is -∞𝔽, return NaN.
1222+
if (lhs_numeric.is_positive_infinity() || lhs_numeric.is_negative_infinity())
1223+
return js_nan();
1224+
1225+
// 3. If d is +∞𝔽 or d is -∞𝔽, return n.
1226+
if (rhs_numeric.is_positive_infinity() || rhs_numeric.is_negative_infinity())
1227+
return lhs_numeric;
1228+
1229+
// 4. If d is +0𝔽 or d is -0𝔽, return NaN.
1230+
if (rhs_numeric.is_positive_zero() || rhs_numeric.is_negative_zero())
1231+
return js_nan();
1232+
1233+
// 5. If n is +0𝔽 or n is -0𝔽, return n.
1234+
if (lhs_numeric.is_positive_zero() || lhs_numeric.is_negative_zero())
1235+
return lhs_numeric;
1236+
1237+
// 6. Assert: n and d are finite and non-zero.
1238+
12171239
auto index = lhs_numeric.as_double();
12181240
auto period = rhs_numeric.as_double();
12191241
auto trunc = (double)(i32)(index / period);
1242+
1243+
// 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).
1244+
// 8. Return 𝔽(r).
12201245
return Value(index - trunc * period);
12211246
}
12221247
if (both_bigint(lhs_numeric, rhs_numeric)) {

Userland/Libraries/LibJS/Tests/operators/modulo-basic.js

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,26 @@ test("basic functionality", () => {
1313
expect(-4 % 2).toBe(-0);
1414
expect(5.5 % 2).toBe(1.5);
1515
expect(NaN % 2).toBeNaN();
16+
expect(2 % NaN).toBeNaN();
17+
expect(NaN % NaN).toBeNaN();
18+
expect(Infinity % 1).toBeNaN();
19+
expect(-Infinity % 1).toBeNaN();
20+
expect(1 % Infinity).toBe(1);
21+
expect(1 % -Infinity).toBe(1);
22+
expect(1 % 0).toBeNaN();
23+
expect(1 % -0).toBeNaN();
24+
expect(0 % 5).toBe(0);
25+
expect(-0 % 5).toBe(-0);
26+
27+
// test262 examples
28+
expect(1 % null).toBeNaN();
29+
expect(null % 1).toBe(0);
30+
expect(true % null).toBeNaN();
31+
expect(null % true).toBe(0);
32+
expect("1" % null).toBeNaN();
33+
expect(null % "1").toBe(0);
34+
expect(null % undefined).toBeNaN();
35+
expect(undefined % null).toBeNaN();
36+
expect(undefined % undefined).toBeNaN();
37+
expect(null % null).toBeNaN();
1638
});

0 commit comments

Comments
 (0)