Bläddra i källkod

LibJS: Implement Math.abs()

Andreas Kling 5 år sedan
förälder
incheckning
2d3634d5f5

+ 25 - 0
Libraries/LibJS/Runtime/MathObject.cpp

@@ -26,12 +26,15 @@
 
 
 #include <AK/FlyString.h>
 #include <AK/FlyString.h>
 #include <AK/Function.h>
 #include <AK/Function.h>
+#include <LibJS/Interpreter.h>
+#include <LibJS/Runtime/Array.h>
 #include <LibJS/Runtime/MathObject.h>
 #include <LibJS/Runtime/MathObject.h>
 
 
 namespace JS {
 namespace JS {
 
 
 MathObject::MathObject()
 MathObject::MathObject()
 {
 {
+    put_native_function("abs", abs);
     put_native_function("random", random);
     put_native_function("random", random);
 }
 }
 
 
@@ -39,6 +42,28 @@ MathObject::~MathObject()
 {
 {
 }
 }
 
 
+Value MathObject::abs(Interpreter& interpreter)
+{
+    if (interpreter.call_frame().arguments.is_empty())
+        return js_nan();
+
+    auto argument = interpreter.call_frame().arguments[0];
+
+    if (argument.is_array()) {
+        auto& array = *static_cast<const Array*>(argument.as_object());
+        if (array.length() == 0)
+            return Value(0);
+        if (array.length() > 1)
+            return js_nan();
+        argument = array.elements()[0];
+    }
+
+    auto number = argument.to_number();
+    if (number.is_nan())
+        return js_nan();
+    return Value(number.as_double() >= 0 ? number.as_double() : -number.as_double());
+}
+
 Value MathObject::random(Interpreter&)
 Value MathObject::random(Interpreter&)
 {
 {
 #ifdef __serenity__
 #ifdef __serenity__

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

@@ -38,6 +38,7 @@ public:
 private:
 private:
     virtual const char* class_name() const override { return "MathObject"; }
     virtual const char* class_name() const override { return "MathObject"; }
 
 
+    static Value abs(Interpreter&);
     static Value random(Interpreter&);
     static Value random(Interpreter&);
 };
 };
 
 

+ 4 - 1
Libraries/LibJS/Runtime/Value.cpp

@@ -114,9 +114,12 @@ Value Value::to_number() const
     case Type::Null:
     case Type::Null:
         return Value(0);
         return Value(0);
     case Type::String: {
     case Type::String: {
+        auto& string = as_string()->string();
+        if (string.is_empty())
+            return Value(0);
         bool ok;
         bool ok;
         //FIXME: Parse in a better way
         //FIXME: Parse in a better way
-        auto parsed_int = as_string()->string().to_int(ok);
+        auto parsed_int = string.to_int(ok);
         if (ok)
         if (ok)
             return Value(parsed_int);
             return Value(parsed_int);
 
 

+ 16 - 0
Libraries/LibJS/Tests/Math.abs.js

@@ -0,0 +1,16 @@
+function assert(x) { if (!x) throw 1; }
+
+try {
+    assert(Math.abs('-1') === 1);
+    assert(Math.abs(0 - 2) === 2);
+    assert(Math.abs(null) === 0);
+    assert(Math.abs('') === 0);
+    assert(Math.abs([]) === 0);
+    assert(Math.abs([2]) === 2);
+    assert(isNaN(Math.abs([1, 2])));
+    assert(isNaN(Math.abs({})));
+    assert(isNaN(Math.abs('string')));
+    assert(isNaN(Math.abs()));
+    console.log("PASS");
+} catch {
+}