mirror of
https://github.com/RGBCube/serenity
synced 2025-07-26 02:17:34 +00:00
LibJS: Throw RangeError on BigInt division/modulo by zero
https://tc39.es/ecma262/#sec-numeric-types-bigint-divide https://tc39.es/ecma262/#sec-numeric-types-bigint-remainder
This commit is contained in:
parent
1d8ab74cbf
commit
11138f5c1f
3 changed files with 30 additions and 8 deletions
|
@ -43,6 +43,7 @@
|
||||||
M(Convert, "Cannot convert {} to {}") \
|
M(Convert, "Cannot convert {} to {}") \
|
||||||
M(ConvertUndefinedToObject, "Cannot convert undefined to object") \
|
M(ConvertUndefinedToObject, "Cannot convert undefined to object") \
|
||||||
M(DescChangeNonConfigurable, "Cannot change attributes of non-configurable property '{}'") \
|
M(DescChangeNonConfigurable, "Cannot change attributes of non-configurable property '{}'") \
|
||||||
|
M(DivisionByZero, "Division by zero") \
|
||||||
M(FunctionArgsNotObject, "Argument array must be an object") \
|
M(FunctionArgsNotObject, "Argument array must be an object") \
|
||||||
M(InOperatorWithObject, "'in' operator must be used on an object") \
|
M(InOperatorWithObject, "'in' operator must be used on an object") \
|
||||||
M(InstanceOfOperatorBadPrototype, "'prototype' property of {} is not an object") \
|
M(InstanceOfOperatorBadPrototype, "'prototype' property of {} is not an object") \
|
||||||
|
|
|
@ -882,27 +882,34 @@ Value mul(GlobalObject& global_object, Value lhs, Value rhs)
|
||||||
|
|
||||||
Value div(GlobalObject& global_object, Value lhs, Value rhs)
|
Value div(GlobalObject& global_object, Value lhs, Value rhs)
|
||||||
{
|
{
|
||||||
|
auto& vm = global_object.vm();
|
||||||
auto lhs_numeric = lhs.to_numeric(global_object.global_object());
|
auto lhs_numeric = lhs.to_numeric(global_object.global_object());
|
||||||
if (global_object.vm().exception())
|
if (vm.exception())
|
||||||
return {};
|
return {};
|
||||||
auto rhs_numeric = rhs.to_numeric(global_object.global_object());
|
auto rhs_numeric = rhs.to_numeric(global_object.global_object());
|
||||||
if (global_object.vm().exception())
|
if (vm.exception())
|
||||||
return {};
|
return {};
|
||||||
if (both_number(lhs_numeric, rhs_numeric))
|
if (both_number(lhs_numeric, rhs_numeric))
|
||||||
return Value(lhs_numeric.as_double() / rhs_numeric.as_double());
|
return Value(lhs_numeric.as_double() / rhs_numeric.as_double());
|
||||||
if (both_bigint(lhs_numeric, rhs_numeric))
|
if (both_bigint(lhs_numeric, rhs_numeric)) {
|
||||||
|
if (rhs_numeric.as_bigint().big_integer() == BIGINT_ZERO) {
|
||||||
|
vm.throw_exception<RangeError>(global_object, ErrorType::DivisionByZero);
|
||||||
|
return {};
|
||||||
|
}
|
||||||
return js_bigint(global_object.heap(), lhs_numeric.as_bigint().big_integer().divided_by(rhs_numeric.as_bigint().big_integer()).quotient);
|
return js_bigint(global_object.heap(), lhs_numeric.as_bigint().big_integer().divided_by(rhs_numeric.as_bigint().big_integer()).quotient);
|
||||||
global_object.vm().throw_exception<TypeError>(global_object.global_object(), ErrorType::BigIntBadOperatorOtherType, "division");
|
}
|
||||||
|
vm.throw_exception<TypeError>(global_object.global_object(), ErrorType::BigIntBadOperatorOtherType, "division");
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
Value mod(GlobalObject& global_object, Value lhs, Value rhs)
|
Value mod(GlobalObject& global_object, Value lhs, Value rhs)
|
||||||
{
|
{
|
||||||
|
auto& vm = global_object.vm();
|
||||||
auto lhs_numeric = lhs.to_numeric(global_object.global_object());
|
auto lhs_numeric = lhs.to_numeric(global_object.global_object());
|
||||||
if (global_object.vm().exception())
|
if (vm.exception())
|
||||||
return {};
|
return {};
|
||||||
auto rhs_numeric = rhs.to_numeric(global_object.global_object());
|
auto rhs_numeric = rhs.to_numeric(global_object.global_object());
|
||||||
if (global_object.vm().exception())
|
if (vm.exception())
|
||||||
return {};
|
return {};
|
||||||
if (both_number(lhs_numeric, rhs_numeric)) {
|
if (both_number(lhs_numeric, rhs_numeric)) {
|
||||||
if (lhs_numeric.is_nan() || rhs_numeric.is_nan())
|
if (lhs_numeric.is_nan() || rhs_numeric.is_nan())
|
||||||
|
@ -912,9 +919,14 @@ Value mod(GlobalObject& global_object, Value lhs, Value rhs)
|
||||||
auto trunc = (double)(i32)(index / period);
|
auto trunc = (double)(i32)(index / period);
|
||||||
return Value(index - trunc * period);
|
return Value(index - trunc * period);
|
||||||
}
|
}
|
||||||
if (both_bigint(lhs_numeric, rhs_numeric))
|
if (both_bigint(lhs_numeric, rhs_numeric)) {
|
||||||
|
if (rhs_numeric.as_bigint().big_integer() == BIGINT_ZERO) {
|
||||||
|
vm.throw_exception<RangeError>(global_object, ErrorType::DivisionByZero);
|
||||||
|
return {};
|
||||||
|
}
|
||||||
return js_bigint(global_object.heap(), lhs_numeric.as_bigint().big_integer().divided_by(rhs_numeric.as_bigint().big_integer()).remainder);
|
return js_bigint(global_object.heap(), lhs_numeric.as_bigint().big_integer().divided_by(rhs_numeric.as_bigint().big_integer()).remainder);
|
||||||
global_object.vm().throw_exception<TypeError>(global_object.global_object(), ErrorType::BigIntBadOperatorOtherType, "modulo");
|
}
|
||||||
|
vm.throw_exception<TypeError>(global_object.global_object(), ErrorType::BigIntBadOperatorOtherType, "modulo");
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -87,4 +87,13 @@ describe("errors", () => {
|
||||||
+123n;
|
+123n;
|
||||||
}).toThrowWithMessage(TypeError, "Cannot convert BigInt to number");
|
}).toThrowWithMessage(TypeError, "Cannot convert BigInt to number");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("division by zero", () => {
|
||||||
|
expect(() => {
|
||||||
|
1n / 0n;
|
||||||
|
}).toThrowWithMessage(RangeError, "Division by zero");
|
||||||
|
expect(() => {
|
||||||
|
1n % 0n;
|
||||||
|
}).toThrowWithMessage(RangeError, "Division by zero");
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue