mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-09-10 02:08:38 +09:00
Issue #1240 - Part 5g - Implement BigInt comparison operators. Implement BigInt support for equality operators. https://bugzilla.mozilla.org/show_bug.cgi?id=1486173 Part 3. Implement BigInt support for relational comparison operators. https://bugzilla.mozilla.org/show_bug.cgi?id=1492669
This commit is contained in:
parent
bbbab3898f
commit
1355043d40
2 changed files with 163 additions and 34 deletions
|
|
@ -31,6 +31,10 @@ EqualGivenSameType(JSContext* cx, JS::HandleValue lval, JS::HandleValue rval, bo
|
|||
*equal = (lval.toDouble() == rval.toDouble());
|
||||
return true;
|
||||
}
|
||||
if (lval.isBigInt()) {
|
||||
*equal = JS::BigInt::equal(lval.toBigInt(), rval.toBigInt());
|
||||
return true;
|
||||
}
|
||||
if (lval.isGCThing()) { // objects or symbols
|
||||
*equal = (lval.toGCThing() == rval.toGCThing());
|
||||
return true;
|
||||
|
|
@ -134,6 +138,22 @@ js::LooselyEqual(JSContext* cx, JS::HandleValue lval, JS::HandleValue rval, bool
|
|||
return js::LooselyEqual(cx, lvalue, rval, result);
|
||||
}
|
||||
|
||||
if (lval.isBigInt()) {
|
||||
RootedBigInt lbi(cx, lval.toBigInt());
|
||||
bool tmpResult;
|
||||
JS_TRY_VAR_OR_RETURN_FALSE(cx, tmpResult, BigInt::looselyEqual(cx, lbi, rval));
|
||||
*result = tmpResult;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (rval.isBigInt()) {
|
||||
RootedBigInt rbi(cx, rval.toBigInt());
|
||||
bool tmpResult;
|
||||
JS_TRY_VAR_OR_RETURN_FALSE(cx, tmpResult, BigInt::looselyEqual(cx, rbi, lval));
|
||||
*result = tmpResult;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Step 12.
|
||||
*result = false;
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -8,6 +8,8 @@
|
|||
|
||||
#include "vm/Interpreter.h"
|
||||
|
||||
#include "mozilla/Maybe.h"
|
||||
|
||||
#include "jscompartment.h"
|
||||
#include "jsnum.h"
|
||||
#include "jsstr.h"
|
||||
|
|
@ -660,51 +662,158 @@ ProcessCallSiteObjOperation(JSContext* cx, RootedObject& cso, RootedObject& raw,
|
|||
return true;
|
||||
}
|
||||
|
||||
#define RELATIONAL_OP(OP) \
|
||||
JS_BEGIN_MACRO \
|
||||
/* Optimize for two int-tagged operands (typical loop control). */ \
|
||||
if (lhs.isInt32() && rhs.isInt32()) { \
|
||||
*res = lhs.toInt32() OP rhs.toInt32(); \
|
||||
} else { \
|
||||
if (!ToPrimitive(cx, JSTYPE_NUMBER, lhs)) \
|
||||
return false; \
|
||||
if (!ToPrimitive(cx, JSTYPE_NUMBER, rhs)) \
|
||||
return false; \
|
||||
if (lhs.isString() && rhs.isString()) { \
|
||||
JSString* l = lhs.toString(); \
|
||||
JSString* r = rhs.toString(); \
|
||||
int32_t result; \
|
||||
if (!CompareStrings(cx, l, r, &result)) \
|
||||
return false; \
|
||||
*res = result OP 0; \
|
||||
} else { \
|
||||
double l, r; \
|
||||
if (!ToNumber(cx, lhs, &l) || !ToNumber(cx, rhs, &r)) \
|
||||
return false; \
|
||||
*res = (l OP r); \
|
||||
} \
|
||||
} \
|
||||
return true; \
|
||||
JS_END_MACRO
|
||||
|
||||
// BigInt proposal 3.2.4 Abstract Relational Comparison
|
||||
// Returns Nothing when at least one operand is a NaN, or when
|
||||
// ToNumeric or StringToBigInt can't interpret a string as a numeric
|
||||
// value. (These cases correspond to a NaN result in the spec.)
|
||||
// Otherwise, return a boolean to indicate whether lhs is less than
|
||||
// rhs. The operands must be primitives; the caller is responsible for
|
||||
// evaluating them in the correct order.
|
||||
static MOZ_ALWAYS_INLINE bool
|
||||
LessThanOperation(JSContext* cx, MutableHandleValue lhs, MutableHandleValue rhs, bool* res) {
|
||||
RELATIONAL_OP(<);
|
||||
LessThanImpl(JSContext* cx, MutableHandleValue lhs, MutableHandleValue rhs,
|
||||
mozilla::Maybe<bool>& res)
|
||||
{
|
||||
// Steps 1 and 2 are performed by the caller.
|
||||
|
||||
// Step 3.
|
||||
if (lhs.isString() && rhs.isString()) {
|
||||
JSString* l = lhs.toString();
|
||||
JSString* r = rhs.toString();
|
||||
int32_t result;
|
||||
if (!CompareStrings(cx, l, r, &result)) {
|
||||
return false;
|
||||
}
|
||||
res = mozilla::Some(result < 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Step 4a.
|
||||
if (lhs.isBigInt() && rhs.isString()) {
|
||||
return BigInt::lessThan(cx, lhs, rhs, res);
|
||||
}
|
||||
// Step 4b.
|
||||
if (lhs.isString() && rhs.isBigInt()) {
|
||||
return BigInt::lessThan(cx, lhs, rhs, res);
|
||||
}
|
||||
|
||||
// Steps 4c and 4d.
|
||||
if (!ToNumeric(cx, lhs) || !ToNumeric(cx, rhs)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Steps 4e-j.
|
||||
if (lhs.isBigInt() || rhs.isBigInt()) {
|
||||
return BigInt::lessThan(cx, lhs, rhs, res);
|
||||
}
|
||||
|
||||
// Step 4e for Number operands.
|
||||
MOZ_ASSERT(lhs.isNumber() && rhs.isNumber());
|
||||
double lhsNum = lhs.toNumber();
|
||||
double rhsNum = rhs.toNumber();
|
||||
|
||||
if (mozilla::IsNaN(lhsNum) || mozilla::IsNaN(rhsNum)) {
|
||||
res = mozilla::Maybe<bool>(mozilla::Nothing());
|
||||
return true;
|
||||
}
|
||||
|
||||
res = mozilla::Some(lhsNum < rhsNum);
|
||||
return true;
|
||||
}
|
||||
|
||||
static MOZ_ALWAYS_INLINE bool
|
||||
LessThanOrEqualOperation(JSContext* cx, MutableHandleValue lhs, MutableHandleValue rhs, bool* res) {
|
||||
RELATIONAL_OP(<=);
|
||||
LessThanOperation(JSContext* cx, MutableHandleValue lhs, MutableHandleValue rhs, bool* res)
|
||||
{
|
||||
if (lhs.isInt32() && rhs.isInt32()) {
|
||||
*res = lhs.toInt32() < rhs.toInt32();
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!ToPrimitive(cx, JSTYPE_NUMBER, lhs)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!ToPrimitive(cx, JSTYPE_NUMBER, rhs)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
mozilla::Maybe<bool> tmpResult;
|
||||
if (!LessThanImpl(cx, lhs, rhs, tmpResult)) {
|
||||
return false;
|
||||
}
|
||||
*res = tmpResult.valueOr(false);
|
||||
return true;
|
||||
}
|
||||
|
||||
static MOZ_ALWAYS_INLINE bool
|
||||
GreaterThanOperation(JSContext* cx, MutableHandleValue lhs, MutableHandleValue rhs, bool* res) {
|
||||
RELATIONAL_OP(>);
|
||||
LessThanOrEqualOperation(JSContext* cx, MutableHandleValue lhs, MutableHandleValue rhs, bool* res)
|
||||
{
|
||||
if (lhs.isInt32() && rhs.isInt32()) {
|
||||
*res = lhs.toInt32() <= rhs.toInt32();
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!ToPrimitive(cx, JSTYPE_NUMBER, lhs)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!ToPrimitive(cx, JSTYPE_NUMBER, rhs)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
mozilla::Maybe<bool> tmpResult;
|
||||
if (!LessThanImpl(cx, rhs, lhs, tmpResult)) {
|
||||
return false;
|
||||
}
|
||||
*res = !tmpResult.valueOr(true);
|
||||
return true;
|
||||
}
|
||||
|
||||
static MOZ_ALWAYS_INLINE bool
|
||||
GreaterThanOrEqualOperation(JSContext* cx, MutableHandleValue lhs, MutableHandleValue rhs, bool* res) {
|
||||
RELATIONAL_OP(>=);
|
||||
GreaterThanOperation(JSContext* cx, MutableHandleValue lhs, MutableHandleValue rhs, bool* res)
|
||||
{
|
||||
if (lhs.isInt32() && rhs.isInt32()) {
|
||||
*res = lhs.toInt32() > rhs.toInt32();
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!ToPrimitive(cx, JSTYPE_NUMBER, lhs)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!ToPrimitive(cx, JSTYPE_NUMBER, rhs)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
mozilla::Maybe<bool> tmpResult;
|
||||
if (!LessThanImpl(cx, rhs, lhs, tmpResult)) {
|
||||
return false;
|
||||
}
|
||||
*res = tmpResult.valueOr(false);
|
||||
return true;
|
||||
}
|
||||
|
||||
static MOZ_ALWAYS_INLINE bool
|
||||
GreaterThanOrEqualOperation(JSContext* cx, MutableHandleValue lhs, MutableHandleValue rhs, bool* res)
|
||||
{
|
||||
if (lhs.isInt32() && rhs.isInt32()) {
|
||||
*res = lhs.toInt32() >= rhs.toInt32();
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!ToPrimitive(cx, JSTYPE_NUMBER, lhs)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!ToPrimitive(cx, JSTYPE_NUMBER, rhs)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
mozilla::Maybe<bool> tmpResult;
|
||||
if (!LessThanImpl(cx, lhs, rhs, tmpResult)) {
|
||||
return false;
|
||||
}
|
||||
*res = !tmpResult.valueOr(true);
|
||||
return true;
|
||||
}
|
||||
|
||||
static MOZ_ALWAYS_INLINE bool
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue