
Instead of passing a GlobalObject everywhere, we will simply pass a VM, from which we can get everything we need: common names, the current realm, symbols, arguments, the heap, and a few other things. In some places we already don't actually need a global object and just do it for consistency - no more `auto& vm = global_object.vm();`! This will eventually automatically fix the "wrong realm" issue we have in some places where we (incorrectly) use the global object from the allocating object, e.g. in call() / construct() implementations. When only ever a VM is passed around, this issue can't happen :^) I've decided to split this change into a series of patches that should keep each commit down do a somewhat manageable size.
105 lines
2.9 KiB
C++
105 lines
2.9 KiB
C++
/*
|
|
* Copyright (c) 2022, Tim Flynn <trflynn89@serenityos.org>
|
|
*
|
|
* SPDX-License-Identifier: BSD-2-Clause
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include <AK/Checked.h>
|
|
#include <AK/Variant.h>
|
|
#include <LibCrypto/BigInt/SignedBigInteger.h>
|
|
#include <LibJS/Runtime/Value.h>
|
|
|
|
namespace JS::Intl {
|
|
|
|
// https://tc39.es/proposal-intl-numberformat-v3/out/numberformat/proposed.html#intl-mathematical-value
|
|
class MathematicalValue {
|
|
public:
|
|
enum class Symbol {
|
|
PositiveInfinity,
|
|
NegativeInfinity,
|
|
NegativeZero,
|
|
NotANumber,
|
|
};
|
|
|
|
MathematicalValue() = default;
|
|
|
|
explicit MathematicalValue(double value)
|
|
: m_value(value_from_number(value))
|
|
{
|
|
}
|
|
|
|
explicit MathematicalValue(Crypto::SignedBigInteger value)
|
|
: m_value(move(value))
|
|
{
|
|
}
|
|
|
|
explicit MathematicalValue(Symbol symbol)
|
|
: m_value(symbol)
|
|
{
|
|
}
|
|
|
|
MathematicalValue(Value value)
|
|
: m_value(value.is_number()
|
|
? value_from_number(value.as_double())
|
|
: ValueType(value.as_bigint().big_integer()))
|
|
{
|
|
}
|
|
|
|
bool is_number() const;
|
|
double as_number() const;
|
|
|
|
bool is_bigint() const;
|
|
Crypto::SignedBigInteger const& as_bigint() const;
|
|
|
|
bool is_mathematical_value() const;
|
|
bool is_positive_infinity() const;
|
|
bool is_negative_infinity() const;
|
|
bool is_negative_zero() const;
|
|
bool is_nan() const;
|
|
|
|
void negate();
|
|
|
|
MathematicalValue plus(Checked<i32> addition) const;
|
|
MathematicalValue plus(MathematicalValue const& addition) const;
|
|
|
|
MathematicalValue minus(Checked<i32> subtraction) const;
|
|
MathematicalValue minus(MathematicalValue const& subtraction) const;
|
|
|
|
MathematicalValue multiplied_by(Checked<i32> multiplier) const;
|
|
MathematicalValue multiplied_by(MathematicalValue const& multiplier) const;
|
|
|
|
MathematicalValue divided_by(Checked<i32> divisor) const;
|
|
MathematicalValue divided_by(MathematicalValue const& divisor) const;
|
|
|
|
MathematicalValue multiplied_by_power(Checked<i32> exponent) const;
|
|
MathematicalValue divided_by_power(Checked<i32> exponent) const;
|
|
|
|
bool modulo_is_zero(Checked<i32> mod) const;
|
|
|
|
int logarithmic_floor() const;
|
|
|
|
bool is_equal_to(MathematicalValue const&) const;
|
|
bool is_less_than(MathematicalValue const&) const;
|
|
|
|
bool is_negative() const;
|
|
bool is_positive() const;
|
|
bool is_zero() const;
|
|
|
|
String to_string() const;
|
|
Value to_value(VM&) const;
|
|
|
|
private:
|
|
using ValueType = Variant<double, Crypto::SignedBigInteger, Symbol>;
|
|
|
|
static ValueType value_from_number(double number);
|
|
|
|
// NOTE: The specific alignment is to avoid an UBSAN error with Clang i686, due to Clang
|
|
// disagreeing with UBSAN on the alignment of doubles. See:
|
|
// https://github.com/llvm/llvm-project/issues/54845
|
|
// https://github.com/SerenityOS/serenity/issues/13614
|
|
alignas(8) ValueType m_value { 0.0 };
|
|
};
|
|
|
|
}
|