| 1 | /* | 
| 2 |  *  Copyright (C) 1999-2001 Harri Porten (porten@kde.org) | 
| 3 |  *  Copyright (C) 2001 Peter Kelly (pmk@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 std::isnan(x: d) ? 0.0 : trunc(x: d); | 
| 47 | } | 
| 48 |  | 
| 49 | double JSValue::toIntegerPreserveNaN(ExecState* exec) const | 
| 50 | { | 
| 51 |     if (isInt32()) | 
| 52 |         return asInt32(); | 
| 53 |     return trunc(x: 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: 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: 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: 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(s: description, maxlen: size, format: "<JSValue()>" ); | 
| 116 |     else if (isInt32()) | 
| 117 |         snprintf(s: description, maxlen: size, format: "Int32: %d" , asInt32()); | 
| 118 |     else if (isDouble()) | 
| 119 |         snprintf(s: description, maxlen: size, format: "Double: %lf" , asDouble()); | 
| 120 |     else if (isCell()) | 
| 121 |         snprintf(s: description, maxlen: size, format: "Cell: %p" , asCell()); | 
| 122 |     else if (isTrue()) | 
| 123 |         snprintf(s: description, maxlen: size, format: "True" ); | 
| 124 |     else if (isFalse()) | 
| 125 |         snprintf(s: description, maxlen: size, format: "False" ); | 
| 126 |     else if (isNull()) | 
| 127 |         snprintf(s: description, maxlen: size, format: "Null" ); | 
| 128 |     else { | 
| 129 |         ASSERT(isUndefined()); | 
| 130 |         snprintf(s: description, maxlen: size, format: "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 (std::isnan(x: d) || std::isinf(x: d)) { | 
| 145 |         ok = false; | 
| 146 |         return 0; | 
| 147 |     } | 
| 148 |  | 
| 149 |     double d32 = fmod(x: trunc(x: d), y: 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 (std::isnan(x: d) || std::isinf(x: d)) { | 
| 165 |         ok = false; | 
| 166 |         return 0; | 
| 167 |     } | 
| 168 |  | 
| 169 |     double d32 = fmod(x: trunc(x: d), y: 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 |  |