1
Fork 0
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:
Linus Groh 2020-06-04 21:36:52 +01:00 committed by Andreas Kling
parent 9f399f7341
commit 5a983c238b

View file

@ -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;