Home | History | Annotate | Download | only in runtime
      1 /*
      2  *  Copyright (C) 1999-2001 Harri Porten (porten (at) kde.org)
      3  *  Copyright (C) 2001 Peter Kelly (pmk (at) post.com)
      4  *  Copyright (C) 2003, 2007, 2008 Apple Inc. All rights reserved.
      5  *
      6  *  This library is free software; you can redistribute it and/or
      7  *  modify it under the terms of the GNU Library General Public
      8  *  License as published by the Free Software Foundation; either
      9  *  version 2 of the License, or (at your option) any later version.
     10  *
     11  *  This library is distributed in the hope that it will be useful,
     12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
     13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     14  *  Library General Public License for more details.
     15  *
     16  *  You should have received a copy of the GNU Library General Public License
     17  *  along with this library; see the file COPYING.LIB.  If not, write to
     18  *  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
     19  *  Boston, MA 02110-1301, USA.
     20  *
     21  */
     22 
     23 #include "config.h"
     24 #include "JSValue.h"
     25 
     26 #include "BooleanConstructor.h"
     27 #include "BooleanPrototype.h"
     28 #include "ExceptionHelpers.h"
     29 #include "JSGlobalObject.h"
     30 #include "JSFunction.h"
     31 #include "JSNotAnObject.h"
     32 #include "NumberObject.h"
     33 #include <wtf/MathExtras.h>
     34 #include <wtf/StringExtras.h>
     35 
     36 namespace JSC {
     37 
     38 static const double D32 = 4294967296.0;
     39 
     40 // ECMA 9.4
     41 double JSValue::toInteger(ExecState* exec) const
     42 {
     43     if (isInt32())
     44         return asInt32();
     45     double d = toNumber(exec);
     46     return isnan(d) ? 0.0 : trunc(d);
     47 }
     48 
     49 double JSValue::toIntegerPreserveNaN(ExecState* exec) const
     50 {
     51     if (isInt32())
     52         return asInt32();
     53     return trunc(toNumber(exec));
     54 }
     55 
     56 JSObject* JSValue::toObjectSlowCase(ExecState* exec) const
     57 {
     58     ASSERT(!isCell());
     59 
     60     if (isInt32() || isDouble())
     61         return constructNumber(exec, asValue());
     62     if (isTrue() || isFalse())
     63         return constructBooleanFromImmediateBoolean(exec, asValue());
     64     ASSERT(isUndefinedOrNull());
     65     JSNotAnObjectErrorStub* exception = createNotAnObjectErrorStub(exec, isNull());
     66     exec->setException(exception);
     67     return new (exec) JSNotAnObject(exec, exception);
     68 }
     69 
     70 JSObject* JSValue::toThisObjectSlowCase(ExecState* exec) const
     71 {
     72     ASSERT(!isCell());
     73 
     74     if (isInt32() || isDouble())
     75         return constructNumber(exec, asValue());
     76     if (isTrue() || isFalse())
     77         return constructBooleanFromImmediateBoolean(exec, asValue());
     78     ASSERT(isUndefinedOrNull());
     79     return exec->globalThisValue();
     80 }
     81 
     82 JSObject* JSValue::synthesizeObject(ExecState* exec) const
     83 {
     84     ASSERT(!isCell());
     85     if (isNumber())
     86         return constructNumber(exec, asValue());
     87     if (isBoolean())
     88         return constructBooleanFromImmediateBoolean(exec, asValue());
     89 
     90     JSNotAnObjectErrorStub* exception = createNotAnObjectErrorStub(exec, isNull());
     91     exec->setException(exception);
     92     return new (exec) JSNotAnObject(exec, exception);
     93 }
     94 
     95 JSObject* JSValue::synthesizePrototype(ExecState* exec) const
     96 {
     97     ASSERT(!isCell());
     98     if (isNumber())
     99         return exec->lexicalGlobalObject()->numberPrototype();
    100     if (isBoolean())
    101         return exec->lexicalGlobalObject()->booleanPrototype();
    102 
    103     JSNotAnObjectErrorStub* exception = createNotAnObjectErrorStub(exec, isNull());
    104     exec->setException(exception);
    105     return new (exec) JSNotAnObject(exec, exception);
    106 }
    107 
    108 #ifndef NDEBUG
    109 char* JSValue::description()
    110 {
    111     static const size_t size = 32;
    112     static char description[size];
    113 
    114     if (!*this)
    115         snprintf(description, size, "<JSValue()>");
    116     else if (isInt32())
    117         snprintf(description, size, "Int32: %d", asInt32());
    118     else if (isDouble())
    119         snprintf(description, size, "Double: %lf", asDouble());
    120     else if (isCell())
    121         snprintf(description, size, "Cell: %p", asCell());
    122     else if (isTrue())
    123         snprintf(description, size, "True");
    124     else if (isFalse())
    125         snprintf(description, size, "False");
    126     else if (isNull())
    127         snprintf(description, size, "Null");
    128     else {
    129         ASSERT(isUndefined());
    130         snprintf(description, size, "Undefined");
    131     }
    132 
    133     return description;
    134 }
    135 #endif
    136 
    137 int32_t toInt32SlowCase(double d, bool& ok)
    138 {
    139     ok = true;
    140 
    141     if (d >= -D32 / 2 && d < D32 / 2)
    142         return static_cast<int32_t>(d);
    143 
    144     if (isnan(d) || isinf(d)) {
    145         ok = false;
    146         return 0;
    147     }
    148 
    149     double d32 = fmod(trunc(d), D32);
    150     if (d32 >= D32 / 2)
    151         d32 -= D32;
    152     else if (d32 < -D32 / 2)
    153         d32 += D32;
    154     return static_cast<int32_t>(d32);
    155 }
    156 
    157 uint32_t toUInt32SlowCase(double d, bool& ok)
    158 {
    159     ok = true;
    160 
    161     if (d >= 0.0 && d < D32)
    162         return static_cast<uint32_t>(d);
    163 
    164     if (isnan(d) || isinf(d)) {
    165         ok = false;
    166         return 0;
    167     }
    168 
    169     double d32 = fmod(trunc(d), D32);
    170     if (d32 < 0)
    171         d32 += D32;
    172     return static_cast<uint32_t>(d32);
    173 }
    174 
    175 NEVER_INLINE double nonInlineNaN()
    176 {
    177 #if OS(SYMBIAN)
    178     return nanval();
    179 #else
    180     return std::numeric_limits<double>::quiet_NaN();
    181 #endif
    182 }
    183 
    184 } // namespace JSC
    185