mirror of
https://github.com/RGBCube/serenity
synced 2025-07-26 02:27:43 +00:00
LibJS: Use switch/case for Value::to_{string{_w/o_side_effects},boolean}
This makes them a bit more compact and improves consistency as to_boolean() and to_number() already use this style as well. Also re-order the types to match the table in the spec document.
This commit is contained in:
parent
9f399f7341
commit
5a983c238b
1 changed files with 61 additions and 82 deletions
|
@ -70,38 +70,32 @@ Accessor& Value::as_accessor()
|
||||||
|
|
||||||
String Value::to_string_without_side_effects() const
|
String Value::to_string_without_side_effects() const
|
||||||
{
|
{
|
||||||
if (is_boolean())
|
switch (m_type) {
|
||||||
return as_bool() ? "true" : "false";
|
case Type::Undefined:
|
||||||
|
|
||||||
if (is_null())
|
|
||||||
return "null";
|
|
||||||
|
|
||||||
if (is_undefined())
|
|
||||||
return "undefined";
|
return "undefined";
|
||||||
|
case Type::Null:
|
||||||
if (is_number()) {
|
return "null";
|
||||||
|
case Type::Boolean:
|
||||||
|
return m_value.as_bool ? "true" : "false";
|
||||||
|
case Type::Number:
|
||||||
if (is_nan())
|
if (is_nan())
|
||||||
return "NaN";
|
return "NaN";
|
||||||
|
|
||||||
if (is_infinity())
|
if (is_infinity())
|
||||||
return as_double() < 0 ? "-Infinity" : "Infinity";
|
return is_negative_infinity() ? "-Infinity" : "Infinity";
|
||||||
|
|
||||||
if (is_integer())
|
if (is_integer())
|
||||||
return String::number(as_i32());
|
return String::number(as_i32());
|
||||||
return String::format("%.4f", as_double());
|
return String::format("%.4f", m_value.as_double);
|
||||||
}
|
case Type::String:
|
||||||
|
|
||||||
if (is_string())
|
|
||||||
return m_value.as_string->string();
|
return m_value.as_string->string();
|
||||||
|
case Type::Symbol:
|
||||||
if (is_symbol())
|
return m_value.as_symbol->to_string();
|
||||||
return as_symbol().to_string();
|
case Type::Object:
|
||||||
|
return String::format("[object %s]", as_object().class_name());
|
||||||
if (is_accessor())
|
case Type::Accessor:
|
||||||
return "<accessor>";
|
return "<accessor>";
|
||||||
|
default:
|
||||||
ASSERT(is_object());
|
ASSERT_NOT_REACHED();
|
||||||
return String::format("[object %s]", as_object().class_name());
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PrimitiveString* Value::to_primitive_string(Interpreter& interpreter)
|
PrimitiveString* Value::to_primitive_string(Interpreter& interpreter)
|
||||||
|
@ -116,60 +110,53 @@ PrimitiveString* Value::to_primitive_string(Interpreter& interpreter)
|
||||||
|
|
||||||
String Value::to_string(Interpreter& interpreter) const
|
String Value::to_string(Interpreter& interpreter) const
|
||||||
{
|
{
|
||||||
if (is_boolean())
|
switch (m_type) {
|
||||||
return as_bool() ? "true" : "false";
|
case Type::Undefined:
|
||||||
|
|
||||||
if (is_null())
|
|
||||||
return "null";
|
|
||||||
|
|
||||||
if (is_undefined())
|
|
||||||
return "undefined";
|
return "undefined";
|
||||||
|
case Type::Null:
|
||||||
if (is_number()) {
|
return "null";
|
||||||
|
case Type::Boolean:
|
||||||
|
return m_value.as_bool ? "true" : "false";
|
||||||
|
case Type::Number:
|
||||||
if (is_nan())
|
if (is_nan())
|
||||||
return "NaN";
|
return "NaN";
|
||||||
|
|
||||||
if (is_infinity())
|
if (is_infinity())
|
||||||
return as_double() < 0 ? "-Infinity" : "Infinity";
|
return is_negative_infinity() ? "-Infinity" : "Infinity";
|
||||||
|
|
||||||
if (is_integer())
|
if (is_integer())
|
||||||
return String::number(as_i32());
|
return String::number(as_i32());
|
||||||
return String::format("%.4f", as_double());
|
return String::format("%.4f", m_value.as_double);
|
||||||
}
|
case Type::String:
|
||||||
|
return m_value.as_string->string();
|
||||||
if (is_symbol()) {
|
case Type::Symbol:
|
||||||
interpreter.throw_exception<TypeError>("Can't convert symbol to string");
|
interpreter.throw_exception<TypeError>("Can't convert symbol to string");
|
||||||
return {};
|
return {};
|
||||||
}
|
case Type::Object: {
|
||||||
|
|
||||||
if (is_object()) {
|
|
||||||
auto primitive_value = as_object().to_primitive(PreferredType::String);
|
auto primitive_value = as_object().to_primitive(PreferredType::String);
|
||||||
if (interpreter.exception())
|
if (interpreter.exception())
|
||||||
return {};
|
return {};
|
||||||
return primitive_value.to_string(interpreter);
|
return primitive_value.to_string(interpreter);
|
||||||
}
|
}
|
||||||
|
default:
|
||||||
ASSERT(is_string());
|
ASSERT_NOT_REACHED();
|
||||||
return m_value.as_string->string();
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Value::to_boolean() const
|
bool Value::to_boolean() const
|
||||||
{
|
{
|
||||||
switch (m_type) {
|
switch (m_type) {
|
||||||
|
case Type::Undefined:
|
||||||
|
case Type::Null:
|
||||||
|
return false;
|
||||||
case Type::Boolean:
|
case Type::Boolean:
|
||||||
return m_value.as_bool;
|
return m_value.as_bool;
|
||||||
case Type::Number:
|
case Type::Number:
|
||||||
if (is_nan()) {
|
if (is_nan())
|
||||||
return false;
|
return false;
|
||||||
}
|
return m_value.as_double != 0;
|
||||||
return !(m_value.as_double == 0 || m_value.as_double == -0);
|
|
||||||
case Type::Null:
|
|
||||||
case Type::Undefined:
|
|
||||||
return false;
|
|
||||||
case Type::String:
|
case Type::String:
|
||||||
return !as_string().string().is_empty();
|
return !m_value.as_string->string().is_empty();
|
||||||
case Type::Object:
|
|
||||||
case Type::Symbol:
|
case Type::Symbol:
|
||||||
|
case Type::Object:
|
||||||
return true;
|
return true;
|
||||||
default:
|
default:
|
||||||
ASSERT_NOT_REACHED();
|
ASSERT_NOT_REACHED();
|
||||||
|
@ -185,37 +172,30 @@ Value Value::to_primitive(Interpreter&, PreferredType preferred_type) const
|
||||||
|
|
||||||
Object* Value::to_object(Interpreter& interpreter) const
|
Object* Value::to_object(Interpreter& interpreter) const
|
||||||
{
|
{
|
||||||
if (is_object())
|
switch (m_type) {
|
||||||
return &const_cast<Object&>(as_object());
|
case Type::Undefined:
|
||||||
|
case Type::Null:
|
||||||
if (is_string())
|
|
||||||
return StringObject::create(interpreter.global_object(), *m_value.as_string);
|
|
||||||
|
|
||||||
if (is_symbol())
|
|
||||||
return SymbolObject::create(interpreter.global_object(), *m_value.as_symbol);
|
|
||||||
|
|
||||||
if (is_number())
|
|
||||||
return NumberObject::create(interpreter.global_object(), m_value.as_double);
|
|
||||||
|
|
||||||
if (is_boolean())
|
|
||||||
return BooleanObject::create(interpreter.global_object(), m_value.as_bool);
|
|
||||||
|
|
||||||
if (is_null() || is_undefined()) {
|
|
||||||
interpreter.throw_exception<TypeError>("ToObject on null or undefined.");
|
interpreter.throw_exception<TypeError>("ToObject on null or undefined.");
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
case Type::Boolean:
|
||||||
|
return BooleanObject::create(interpreter.global_object(), m_value.as_bool);
|
||||||
|
case Type::Number:
|
||||||
|
return NumberObject::create(interpreter.global_object(), m_value.as_double);
|
||||||
|
case Type::String:
|
||||||
|
return StringObject::create(interpreter.global_object(), *m_value.as_string);
|
||||||
|
case Type::Symbol:
|
||||||
|
return SymbolObject::create(interpreter.global_object(), *m_value.as_symbol);
|
||||||
|
case Type::Object:
|
||||||
|
return &const_cast<Object&>(as_object());
|
||||||
|
default:
|
||||||
|
dbg() << "Dying because I can't to_object() on " << *this;
|
||||||
|
ASSERT_NOT_REACHED();
|
||||||
}
|
}
|
||||||
|
|
||||||
dbg() << "Dying because I can't to_object() on " << *this;
|
|
||||||
ASSERT_NOT_REACHED();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Value Value::to_number(Interpreter& interpreter) const
|
Value Value::to_number(Interpreter& interpreter) const
|
||||||
{
|
{
|
||||||
switch (m_type) {
|
switch (m_type) {
|
||||||
case Type::Empty:
|
|
||||||
case Type::Accessor:
|
|
||||||
ASSERT_NOT_REACHED();
|
|
||||||
return {};
|
|
||||||
case Type::Undefined:
|
case Type::Undefined:
|
||||||
return js_nan();
|
return js_nan();
|
||||||
case Type::Null:
|
case Type::Null:
|
||||||
|
@ -241,14 +221,15 @@ Value Value::to_number(Interpreter& interpreter) const
|
||||||
case Type::Symbol:
|
case Type::Symbol:
|
||||||
interpreter.throw_exception<TypeError>("Can't convert symbol to number");
|
interpreter.throw_exception<TypeError>("Can't convert symbol to number");
|
||||||
return {};
|
return {};
|
||||||
case Type::Object:
|
case Type::Object: {
|
||||||
auto primitive = m_value.as_object->to_primitive(PreferredType::Number);
|
auto primitive = m_value.as_object->to_primitive(PreferredType::Number);
|
||||||
if (interpreter.exception())
|
if (interpreter.exception())
|
||||||
return {};
|
return {};
|
||||||
return primitive.to_number(interpreter);
|
return primitive.to_number(interpreter);
|
||||||
}
|
}
|
||||||
|
default:
|
||||||
ASSERT_NOT_REACHED();
|
ASSERT_NOT_REACHED();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
i32 Value::as_i32() const
|
i32 Value::as_i32() const
|
||||||
|
@ -597,8 +578,6 @@ bool same_value_non_numeric(Interpreter&, Value lhs, Value rhs)
|
||||||
ASSERT(lhs.type() == rhs.type());
|
ASSERT(lhs.type() == rhs.type());
|
||||||
|
|
||||||
switch (lhs.type()) {
|
switch (lhs.type()) {
|
||||||
case Value::Type::Empty:
|
|
||||||
ASSERT_NOT_REACHED();
|
|
||||||
case Value::Type::Undefined:
|
case Value::Type::Undefined:
|
||||||
case Value::Type::Null:
|
case Value::Type::Null:
|
||||||
return true;
|
return true;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue