Fix isNaN and isFinite
authorLars Knoll <lars.knoll@digia.com>
Wed, 12 Dec 2012 22:43:53 +0000 (23:43 +0100)
committerSimon Hausmann <simon.hausmann@digia.com>
Wed, 12 Dec 2012 15:04:53 +0000 (16:04 +0100)
We need to convert objects to numbers before doing the
check.

Change-Id: Ie25128b6145845a3eb3e0098f5c5fc09f2be6830
Reviewed-by: Simon Hausmann <simon.hausmann@digia.com>
qmljs_objects.cpp
qmljs_value.h

index d7d0365..12269f2 100644 (file)
@@ -670,11 +670,14 @@ IsNaNFunction::IsNaNFunction(ExecutionContext *scope)
     name = scope->engine->newString(QLatin1String("isNaN"));
 }
 
-Value IsNaNFunction::call(ExecutionContext * /*context*/, Value /*thisObject*/, Value *args, int /*argc*/)
+Value IsNaNFunction::call(ExecutionContext *context, Value /*thisObject*/, Value *args, int /*argc*/)
 {
-    // TODO: see if we can generate code for this directly
     const Value &v = args[0];
-    return Value::fromBoolean(v.isDouble() ? std::isnan(v.doubleValue()) : false);
+    if (v.integerCompatible())
+        return Value::fromBoolean(false);
+
+    double d = v.toNumber(context);
+    return Value::fromBoolean(std::isnan(d));
 }
 
 /// isFinite [15.1.2.5]
@@ -684,11 +687,14 @@ IsFiniteFunction::IsFiniteFunction(ExecutionContext *scope)
     name = scope->engine->newString(QLatin1String("isFinite"));
 }
 
-Value IsFiniteFunction::call(ExecutionContext * /*context*/, Value /*thisObject*/, Value *args, int /*argc*/)
+Value IsFiniteFunction::call(ExecutionContext *context, Value /*thisObject*/, Value *args, int /*argc*/)
 {
-    // TODO: see if we can generate code for this directly
     const Value &v = args[0];
-    return Value::fromBoolean(v.isDouble() ? std::isfinite(v.doubleValue()) : true);
+    if (v.integerCompatible())
+        return Value::fromBoolean(true);
+
+    double d = v.toNumber(context);
+    return Value::fromBoolean(std::isfinite(d));
 }
 
 
index 3d29deb..7f095ca 100644 (file)
@@ -205,6 +205,10 @@ struct Value
 
     inline bool isPrimitive() const { return !isObject(); }
 #if CPU(X86_64)
+    inline bool integerCompatible() const {
+        const quint64 mask = quint64(ConvertibleToInt) << 32;
+        return (val & mask) == mask;
+    }
     static inline bool integerCompatible(Value a, Value b) {
         const quint64 mask = quint64(ConvertibleToInt) << 32;
         return ((a.val & b.val) & mask) == mask;
@@ -214,6 +218,9 @@ struct Value
         return ((a.val | b.val) & mask) != mask;
     }
 #else
+    inline bool integerCompatible() const {
+        return (tag & ConvertibleToInt) == ConvertibleToInt;
+    }
     static inline bool integerCompatible(Value a, Value b) {
         return ((a.tag & b.tag) & ConvertibleToInt) == ConvertibleToInt;
     }