summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Base/home/anon/js/type-play.js12
-rw-r--r--Libraries/LibJS/AST.cpp12
-rw-r--r--Libraries/LibJS/AST.h2
-rw-r--r--Libraries/LibJS/Parser.cpp8
-rw-r--r--Libraries/LibJS/Value.cpp31
-rw-r--r--Libraries/LibJS/Value.h1
6 files changed, 64 insertions, 2 deletions
diff --git a/Base/home/anon/js/type-play.js b/Base/home/anon/js/type-play.js
new file mode 100644
index 0000000000..038841397c
--- /dev/null
+++ b/Base/home/anon/js/type-play.js
@@ -0,0 +1,12 @@
+const object = {};
+
+print(true == 1);
+print(null == undefined);
+print("12" == 12);
+print(1 + "12");
+print(12 / "12" == true);
+print(2 * "12");
+print(~"24");
+print(~true);
+print(2*2 + "4");
+print(object == "[object Object]");
diff --git a/Libraries/LibJS/AST.cpp b/Libraries/LibJS/AST.cpp
index ad3fc2cf1e..a431c6fdac 100644
--- a/Libraries/LibJS/AST.cpp
+++ b/Libraries/LibJS/AST.cpp
@@ -155,7 +155,11 @@ Value BinaryExpression::execute(Interpreter& interpreter) const
case BinaryOp::TypedEquals:
return typed_eq(lhs_result, rhs_result);
case BinaryOp::TypedInequals:
- return Value(!typed_eq(lhs_result, rhs_result).to_boolean());
+ return Value(!typed_eq(lhs_result, rhs_result).as_bool());
+ case BinaryOp::AbstractEquals:
+ return eq(lhs_result, rhs_result);
+ case BinaryOp::AbstractInequals:
+ return Value(!eq(lhs_result, rhs_result).as_bool());
case BinaryOp::GreaterThan:
return greater_than(lhs_result, rhs_result);
case BinaryOp::GreaterThanEquals:
@@ -247,6 +251,12 @@ void BinaryExpression::dump(int indent) const
case BinaryOp::TypedInequals:
op_string = "!==";
break;
+ case BinaryOp::AbstractEquals:
+ op_string = "==";
+ break;
+ case BinaryOp::AbstractInequals:
+ op_string = "!=";
+ break;
case BinaryOp::GreaterThan:
op_string = ">";
break;
diff --git a/Libraries/LibJS/AST.h b/Libraries/LibJS/AST.h
index 575e501139..596b025984 100644
--- a/Libraries/LibJS/AST.h
+++ b/Libraries/LibJS/AST.h
@@ -248,6 +248,8 @@ enum class BinaryOp {
Slash,
TypedEquals,
TypedInequals,
+ AbstractEquals,
+ AbstractInequals,
GreaterThan,
GreaterThanEquals,
LessThan,
diff --git a/Libraries/LibJS/Parser.cpp b/Libraries/LibJS/Parser.cpp
index 25982cc590..754b251caa 100644
--- a/Libraries/LibJS/Parser.cpp
+++ b/Libraries/LibJS/Parser.cpp
@@ -334,6 +334,12 @@ NonnullOwnPtr<Expression> Parser::parse_secondary_expression(NonnullOwnPtr<Expre
case TokenType::ExclamationMarkEqualsEquals:
consume();
return make<BinaryExpression>(BinaryOp::TypedInequals, move(lhs), parse_expression(min_precedence, associativity));
+ case TokenType::EqualsEquals:
+ consume();
+ return make<BinaryExpression>(BinaryOp::AbstractEquals, move(lhs), parse_expression(min_precedence, associativity));
+ case TokenType::ExclamationMarkEquals:
+ consume();
+ return make<BinaryExpression>(BinaryOp::AbstractInequals, move(lhs), parse_expression(min_precedence, associativity));
case TokenType::ParenOpen:
return parse_call_expression(move(lhs));
case TokenType::Equals:
@@ -543,6 +549,8 @@ bool Parser::match_secondary_expression() const
|| type == TokenType::Equals
|| type == TokenType::EqualsEqualsEquals
|| type == TokenType::ExclamationMarkEqualsEquals
+ || type == TokenType::EqualsEquals
+ || type == TokenType::ExclamationMarkEquals
|| type == TokenType::GreaterThan
|| type == TokenType::GreaterThanEquals
|| type == TokenType::LessThan
diff --git a/Libraries/LibJS/Value.cpp b/Libraries/LibJS/Value.cpp
index b9ba4ede1f..ce84a77f74 100644
--- a/Libraries/LibJS/Value.cpp
+++ b/Libraries/LibJS/Value.cpp
@@ -209,7 +209,7 @@ Value typed_eq(Value lhs, Value rhs)
case Value::Type::Number:
return Value(lhs.as_double() == rhs.as_double());
case Value::Type::String:
- return Value(lhs.as_string() == rhs.as_string());
+ return Value(lhs.as_string()->string() == rhs.as_string()->string());
case Value::Type::Boolean:
return Value(lhs.as_bool() == rhs.as_bool());
case Value::Type::Object:
@@ -219,6 +219,35 @@ Value typed_eq(Value lhs, Value rhs)
ASSERT_NOT_REACHED();
}
+Value eq(Value lhs, Value rhs)
+{
+ if (lhs.type() == rhs.type())
+ return typed_eq(lhs, rhs);
+
+ if ((lhs.is_undefined() || lhs.is_null()) && (rhs.is_undefined() || rhs.is_null()))
+ return Value(true);
+
+ if (lhs.is_object() && rhs.is_boolean())
+ return eq(lhs.as_object()->to_primitive(), rhs.to_number());
+
+ if (lhs.is_boolean() && rhs.is_object())
+ return eq(lhs.to_number(), rhs.as_object()->to_primitive());
+
+ if (lhs.is_object())
+ return eq(lhs.as_object()->to_primitive(), rhs);
+
+ if (rhs.is_object())
+ return eq(lhs, rhs.as_object()->to_primitive());
+
+ if (lhs.is_number() || rhs.is_number())
+ return Value(lhs.to_number().as_double() == rhs.to_number().as_double());
+
+ if ((lhs.is_string() && rhs.is_boolean()) || (lhs.is_string() && rhs.is_boolean()))
+ return Value(lhs.to_number().as_double() == rhs.to_number().as_double());
+
+ return Value(false);
+}
+
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 3f06b73e66..ada26761c6 100644
--- a/Libraries/LibJS/Value.h
+++ b/Libraries/LibJS/Value.h
@@ -174,6 +174,7 @@ Value add(Value lhs, Value rhs);
Value sub(Value lhs, Value rhs);
Value mul(Value lhs, Value rhs);
Value div(Value lhs, Value rhs);
+Value eq(Value lhs, Value rhs);
Value typed_eq(Value lhs, Value rhs);
const LogStream& operator<<(const LogStream&, const Value&);