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