mirror of
https://github.com/RGBCube/serenity
synced 2025-07-26 08:37:45 +00:00
LibJS: Add spec comments to is_less_than()
This commit is contained in:
parent
f1d8a64510
commit
14e5003ece
1 changed files with 48 additions and 2 deletions
|
@ -2311,14 +2311,24 @@ ThrowCompletionOr<TriState> is_less_than(VM& vm, Value lhs, Value rhs, bool left
|
||||||
Value x_primitive;
|
Value x_primitive;
|
||||||
Value y_primitive;
|
Value y_primitive;
|
||||||
|
|
||||||
|
// 1. If the LeftFirst flag is true, then
|
||||||
if (left_first) {
|
if (left_first) {
|
||||||
|
// a. Let px be ? ToPrimitive(x, number).
|
||||||
x_primitive = TRY(lhs.to_primitive(vm, Value::PreferredType::Number));
|
x_primitive = TRY(lhs.to_primitive(vm, Value::PreferredType::Number));
|
||||||
|
|
||||||
|
// b. Let py be ? ToPrimitive(y, number).
|
||||||
y_primitive = TRY(rhs.to_primitive(vm, Value::PreferredType::Number));
|
y_primitive = TRY(rhs.to_primitive(vm, Value::PreferredType::Number));
|
||||||
} else {
|
} else {
|
||||||
|
// a. NOTE: The order of evaluation needs to be reversed to preserve left to right evaluation.
|
||||||
|
|
||||||
|
// b. Let py be ? ToPrimitive(y, number).
|
||||||
y_primitive = TRY(lhs.to_primitive(vm, Value::PreferredType::Number));
|
y_primitive = TRY(lhs.to_primitive(vm, Value::PreferredType::Number));
|
||||||
|
|
||||||
|
// c. Let px be ? ToPrimitive(x, number).
|
||||||
x_primitive = TRY(rhs.to_primitive(vm, Value::PreferredType::Number));
|
x_primitive = TRY(rhs.to_primitive(vm, Value::PreferredType::Number));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 3. If px is a String and py is a String, then
|
||||||
if (x_primitive.is_string() && y_primitive.is_string()) {
|
if (x_primitive.is_string() && y_primitive.is_string()) {
|
||||||
auto x_string = x_primitive.as_string().deprecated_string();
|
auto x_string = x_primitive.as_string().deprecated_string();
|
||||||
auto y_string = y_primitive.as_string().deprecated_string();
|
auto y_string = y_primitive.as_string().deprecated_string();
|
||||||
|
@ -2326,71 +2336,107 @@ ThrowCompletionOr<TriState> is_less_than(VM& vm, Value lhs, Value rhs, bool left
|
||||||
Utf8View x_code_points { x_string };
|
Utf8View x_code_points { x_string };
|
||||||
Utf8View y_code_points { y_string };
|
Utf8View y_code_points { y_string };
|
||||||
|
|
||||||
|
// a. Let lx be the length of px.
|
||||||
|
// b. Let ly be the length of py.
|
||||||
|
// c. For each integer i such that 0 ≤ i < min(lx, ly), in ascending order, do
|
||||||
for (auto k = x_code_points.begin(), l = y_code_points.begin();
|
for (auto k = x_code_points.begin(), l = y_code_points.begin();
|
||||||
k != x_code_points.end() && l != y_code_points.end();
|
k != x_code_points.end() && l != y_code_points.end();
|
||||||
++k, ++l) {
|
++k, ++l) {
|
||||||
|
// i. Let cx be the integer that is the numeric value of the code unit at index i within px.
|
||||||
|
// ii. Let cy be the integer that is the numeric value of the code unit at index i within py.
|
||||||
if (*k != *l) {
|
if (*k != *l) {
|
||||||
|
// iii. If cx < cy, return true.
|
||||||
if (*k < *l) {
|
if (*k < *l) {
|
||||||
return TriState::True;
|
return TriState::True;
|
||||||
} else {
|
}
|
||||||
|
// iv. If cx > cy, return false.
|
||||||
|
else {
|
||||||
return TriState::False;
|
return TriState::False;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// d. If lx < ly, return true. Otherwise, return false.
|
||||||
return x_code_points.length() < y_code_points.length()
|
return x_code_points.length() < y_code_points.length()
|
||||||
? TriState::True
|
? TriState::True
|
||||||
: TriState::False;
|
: TriState::False;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 4. Else,
|
||||||
|
// a. If px is a BigInt and py is a String, then
|
||||||
if (x_primitive.is_bigint() && y_primitive.is_string()) {
|
if (x_primitive.is_bigint() && y_primitive.is_string()) {
|
||||||
|
// i. Let ny be StringToBigInt(py).
|
||||||
auto y_bigint = string_to_bigint(vm, y_primitive.as_string().deprecated_string());
|
auto y_bigint = string_to_bigint(vm, y_primitive.as_string().deprecated_string());
|
||||||
|
|
||||||
|
// ii. If ny is undefined, return undefined.
|
||||||
if (!y_bigint.has_value())
|
if (!y_bigint.has_value())
|
||||||
return TriState::Unknown;
|
return TriState::Unknown;
|
||||||
|
|
||||||
|
// iii. Return BigInt::lessThan(px, ny).
|
||||||
if (x_primitive.as_bigint().big_integer() < (*y_bigint)->big_integer())
|
if (x_primitive.as_bigint().big_integer() < (*y_bigint)->big_integer())
|
||||||
return TriState::True;
|
return TriState::True;
|
||||||
return TriState::False;
|
return TriState::False;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// b. If px is a String and py is a BigInt, then
|
||||||
if (x_primitive.is_string() && y_primitive.is_bigint()) {
|
if (x_primitive.is_string() && y_primitive.is_bigint()) {
|
||||||
|
// i. Let nx be StringToBigInt(px).
|
||||||
auto x_bigint = string_to_bigint(vm, x_primitive.as_string().deprecated_string());
|
auto x_bigint = string_to_bigint(vm, x_primitive.as_string().deprecated_string());
|
||||||
|
|
||||||
|
// ii. If nx is undefined, return undefined.
|
||||||
if (!x_bigint.has_value())
|
if (!x_bigint.has_value())
|
||||||
return TriState::Unknown;
|
return TriState::Unknown;
|
||||||
|
|
||||||
|
// iii. Return BigInt::lessThan(nx, py).
|
||||||
if ((*x_bigint)->big_integer() < y_primitive.as_bigint().big_integer())
|
if ((*x_bigint)->big_integer() < y_primitive.as_bigint().big_integer())
|
||||||
return TriState::True;
|
return TriState::True;
|
||||||
return TriState::False;
|
return TriState::False;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// c. NOTE: Because px and py are primitive values, evaluation order is not important.
|
||||||
|
|
||||||
|
// d. Let nx be ? ToNumeric(px).
|
||||||
auto x_numeric = TRY(x_primitive.to_numeric(vm));
|
auto x_numeric = TRY(x_primitive.to_numeric(vm));
|
||||||
|
|
||||||
|
// e. Let ny be ? ToNumeric(py).
|
||||||
auto y_numeric = TRY(y_primitive.to_numeric(vm));
|
auto y_numeric = TRY(y_primitive.to_numeric(vm));
|
||||||
|
|
||||||
|
// h. If nx or ny is NaN, return undefined.
|
||||||
if (x_numeric.is_nan() || y_numeric.is_nan())
|
if (x_numeric.is_nan() || y_numeric.is_nan())
|
||||||
return TriState::Unknown;
|
return TriState::Unknown;
|
||||||
|
|
||||||
|
// i. If nx is -∞𝔽 or ny is +∞𝔽, return true.
|
||||||
if (x_numeric.is_positive_infinity() || y_numeric.is_negative_infinity())
|
if (x_numeric.is_positive_infinity() || y_numeric.is_negative_infinity())
|
||||||
return TriState::False;
|
return TriState::False;
|
||||||
|
|
||||||
|
// j. If nx is +∞𝔽 or ny is -∞𝔽, return false.
|
||||||
if (x_numeric.is_negative_infinity() || y_numeric.is_positive_infinity())
|
if (x_numeric.is_negative_infinity() || y_numeric.is_positive_infinity())
|
||||||
return TriState::True;
|
return TriState::True;
|
||||||
|
|
||||||
|
// f. If Type(nx) is the same as Type(ny), then
|
||||||
|
|
||||||
|
// i. If nx is a Number, then
|
||||||
if (x_numeric.is_number() && y_numeric.is_number()) {
|
if (x_numeric.is_number() && y_numeric.is_number()) {
|
||||||
|
// 1. Return Number::lessThan(nx, ny).
|
||||||
if (x_numeric.as_double() < y_numeric.as_double())
|
if (x_numeric.as_double() < y_numeric.as_double())
|
||||||
return TriState::True;
|
return TriState::True;
|
||||||
else
|
else
|
||||||
return TriState::False;
|
return TriState::False;
|
||||||
}
|
}
|
||||||
|
// ii. Else,
|
||||||
if (x_numeric.is_bigint() && y_numeric.is_bigint()) {
|
if (x_numeric.is_bigint() && y_numeric.is_bigint()) {
|
||||||
|
// 1. Assert: nx is a BigInt.
|
||||||
|
// 2. Return BigInt::lessThan(nx, ny).
|
||||||
if (x_numeric.as_bigint().big_integer() < y_numeric.as_bigint().big_integer())
|
if (x_numeric.as_bigint().big_integer() < y_numeric.as_bigint().big_integer())
|
||||||
return TriState::True;
|
return TriState::True;
|
||||||
else
|
else
|
||||||
return TriState::False;
|
return TriState::False;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// g. Assert: nx is a BigInt and ny is a Number, or nx is a Number and ny is a BigInt.
|
||||||
VERIFY((x_numeric.is_number() && y_numeric.is_bigint()) || (x_numeric.is_bigint() && y_numeric.is_number()));
|
VERIFY((x_numeric.is_number() && y_numeric.is_bigint()) || (x_numeric.is_bigint() && y_numeric.is_number()));
|
||||||
|
|
||||||
|
// k. If ℝ(nx) < ℝ(ny), return true; otherwise return false.
|
||||||
bool x_lower_than_y;
|
bool x_lower_than_y;
|
||||||
VERIFY(!x_numeric.is_nan() && !y_numeric.is_nan());
|
VERIFY(!x_numeric.is_nan() && !y_numeric.is_nan());
|
||||||
if (x_numeric.is_number()) {
|
if (x_numeric.is_number()) {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue