Переглянути джерело

LibJS: Adding two values should convert them to primitives first

Andreas Kling 5 роки тому
батько
коміт
fa30355194

+ 13 - 3
Libraries/LibJS/Runtime/Value.cpp

@@ -100,6 +100,13 @@ bool Value::to_boolean() const
     }
 }
 
+Value Value::to_primitive(Interpreter&) const
+{
+    if (is_object())
+        return as_object().to_primitive();
+    return *this;
+}
+
 Object* Value::to_object(Heap& heap) const
 {
     if (is_object())
@@ -256,10 +263,13 @@ Value right_shift(Interpreter&, Value lhs, Value rhs)
 
 Value add(Interpreter& interpreter, Value lhs, Value rhs)
 {
-    if (lhs.is_string() || rhs.is_string())
-        return js_string(interpreter.heap(), String::format("%s%s", lhs.to_string().characters(), rhs.to_string().characters()));
+    auto lhs_primitive = lhs.to_primitive(interpreter);
+    auto rhs_primitive = rhs.to_primitive(interpreter);
+
+    if (lhs_primitive.is_string() || rhs_primitive.is_string())
+        return js_string(interpreter.heap(), String::format("%s%s", lhs_primitive.to_string().characters(), rhs_primitive.to_string().characters()));
 
-    return Value(lhs.to_number().as_double() + rhs.to_number().as_double());
+    return Value(lhs_primitive.to_number().as_double() + rhs_primitive.to_number().as_double());
 }
 
 Value sub(Interpreter&, Value lhs, Value rhs)

+ 1 - 0
Libraries/LibJS/Runtime/Value.h

@@ -147,6 +147,7 @@ public:
     Value to_number() const;
     i32 to_i32() const;
     double to_double() const;
+    Value to_primitive(Interpreter&) const;
 
     Object* to_object(Heap&) const;
 

+ 12 - 0
Libraries/LibJS/Tests/add-values-to-primitive.js

@@ -0,0 +1,12 @@
+load("test-common.js");
+
+try {
+    // Note that these will give different results in the REPL due to parsing behavior.
+    assert([] + [] === "");
+    assert([] + {} === "[object Object]");
+    assert({} + {} === "[object Object][object Object]");
+    assert({} + [] === "[object Object]");
+    console.log("PASS");
+} catch (e) {
+    console.log("FAIL: " + e);
+}