From dc0b091c31046823ea5ee78bdd606183621f7436 Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Tue, 10 Mar 2020 08:46:20 +0100 Subject: [PATCH] LibJS: Implement basic boolean coercion We can't expect the conditionals in "if" and "while" statements to always return a bool, so we need to know how to boolify a JS::Value. --- Libraries/LibJS/AST.cpp | 9 ++++----- Libraries/LibJS/Value.cpp | 19 +++++++++++++++++++ Libraries/LibJS/Value.h | 1 + 3 files changed, 24 insertions(+), 5 deletions(-) diff --git a/Libraries/LibJS/AST.cpp b/Libraries/LibJS/AST.cpp index 00ed1227bf..e1260c1804 100644 --- a/Libraries/LibJS/AST.cpp +++ b/Libraries/LibJS/AST.cpp @@ -70,7 +70,7 @@ Value IfStatement::execute(Interpreter& interpreter) const { auto predicate_result = m_predicate->execute(interpreter); - if (predicate_result.as_bool()) + if (predicate_result.to_boolean()) return interpreter.run(*m_consequent); else return interpreter.run(*m_alternate); @@ -79,7 +79,7 @@ Value IfStatement::execute(Interpreter& interpreter) const Value WhileStatement::execute(Interpreter& interpreter) const { Value last_value = js_undefined(); - while (m_predicate->execute(interpreter).as_bool()) { + while (m_predicate->execute(interpreter).to_boolean()) { last_value = interpreter.run(*m_body); } @@ -213,9 +213,8 @@ Value BinaryExpression::execute(Interpreter& interpreter) const Value LogicalExpression::execute(Interpreter& interpreter) const { - auto lhs_result = m_lhs->execute(interpreter).as_bool(); - - auto rhs_result = m_rhs->execute(interpreter).as_bool(); + auto lhs_result = m_lhs->execute(interpreter).to_boolean(); + auto rhs_result = m_rhs->execute(interpreter).to_boolean(); switch (m_op) { case LogicalOp::And: return Value(lhs_result && rhs_result); diff --git a/Libraries/LibJS/Value.cpp b/Libraries/LibJS/Value.cpp index 54e3185dff..30ce077737 100644 --- a/Libraries/LibJS/Value.cpp +++ b/Libraries/LibJS/Value.cpp @@ -53,6 +53,25 @@ String Value::to_string() const ASSERT_NOT_REACHED(); } +bool Value::to_boolean() const +{ + switch (m_type) { + case Type::Boolean: + return m_value.as_bool; + case Type::Number: + return m_value.as_double == 0 || m_value.as_double == -0; + case Type::Null: + case Type::Undefined: + return false; + case Type::String: + return String(as_string()).is_empty(); + case Type::Object: + return true; + default: + ASSERT_NOT_REACHED(); + } +} + const LogStream& operator<<(const LogStream& stream, const Value& value) { return stream << value.to_string(); diff --git a/Libraries/LibJS/Value.h b/Libraries/LibJS/Value.h index ed00df7d89..ecf0ccc4a6 100644 --- a/Libraries/LibJS/Value.h +++ b/Libraries/LibJS/Value.h @@ -113,6 +113,7 @@ public: } String to_string() const; + bool to_boolean() const; private: Type m_type { Type::Undefined };