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 "Error.h" 29 #include "ExceptionHelpers.h" 30 #include "JSGlobalObject.h" 31 #include "JSFunction.h" 32 #include "JSNotAnObject.h" 33 #include "NumberObject.h" 34 #include <wtf/MathExtras.h> 35 #include <wtf/StringExtras.h> 36 37 namespace JSC { 38 39 static const double D32 = 4294967296.0; 40 41 // ECMA 9.4 42 double JSValue::toInteger(ExecState* exec) const 43 { 44 if (isInt32()) 45 return asInt32(); 46 double d = toNumber(exec); 47 return isnan(d) ? 0.0 : trunc(d); 48 } 49 50 double JSValue::toIntegerPreserveNaN(ExecState* exec) const 51 { 52 if (isInt32()) 53 return asInt32(); 54 return trunc(toNumber(exec)); 55 } 56 57 JSObject* JSValue::toObjectSlowCase(ExecState* exec, JSGlobalObject* globalObject) const 58 { 59 ASSERT(!isCell()); 60 61 if (isInt32() || isDouble()) 62 return constructNumber(exec, globalObject, asValue()); 63 if (isTrue() || isFalse()) 64 return constructBooleanFromImmediateBoolean(exec, globalObject, asValue()); 65 66 ASSERT(isUndefinedOrNull()); 67 throwError(exec, createNotAnObjectError(exec, *this)); 68 return new (exec) JSNotAnObject(exec); 69 } 70 71 JSObject* JSValue::toThisObjectSlowCase(ExecState* exec) const 72 { 73 ASSERT(!isCell()); 74 75 if (isInt32() || isDouble()) 76 return constructNumber(exec, exec->lexicalGlobalObject(), asValue()); 77 if (isTrue() || isFalse()) 78 return constructBooleanFromImmediateBoolean(exec, exec->lexicalGlobalObject(), asValue()); 79 ASSERT(isUndefinedOrNull()); 80 return exec->globalThisValue(); 81 } 82 83 JSObject* JSValue::synthesizeObject(ExecState* exec) const 84 { 85 ASSERT(!isCell()); 86 if (isNumber()) 87 return constructNumber(exec, exec->lexicalGlobalObject(), asValue()); 88 if (isBoolean()) 89 return constructBooleanFromImmediateBoolean(exec, exec->lexicalGlobalObject(), asValue()); 90 91 ASSERT(isUndefinedOrNull()); 92 throwError(exec, createNotAnObjectError(exec, *this)); 93 return new (exec) JSNotAnObject(exec); 94 } 95 96 JSObject* JSValue::synthesizePrototype(ExecState* exec) const 97 { 98 ASSERT(!isCell()); 99 if (isNumber()) 100 return exec->lexicalGlobalObject()->numberPrototype(); 101 if (isBoolean()) 102 return exec->lexicalGlobalObject()->booleanPrototype(); 103 104 ASSERT(isUndefinedOrNull()); 105 throwError(exec, createNotAnObjectError(exec, *this)); 106 return new (exec) JSNotAnObject(exec); 107 } 108 109 #ifndef NDEBUG 110 char* JSValue::description() 111 { 112 static const size_t size = 32; 113 static char description[size]; 114 115 if (!*this) 116 snprintf(description, size, "<JSValue()>"); 117 else if (isInt32()) 118 snprintf(description, size, "Int32: %d", asInt32()); 119 else if (isDouble()) 120 snprintf(description, size, "Double: %lf", asDouble()); 121 else if (isCell()) 122 snprintf(description, size, "Cell: %p", asCell()); 123 else if (isTrue()) 124 snprintf(description, size, "True"); 125 else if (isFalse()) 126 snprintf(description, size, "False"); 127 else if (isNull()) 128 snprintf(description, size, "Null"); 129 else if (isUndefined()) 130 snprintf(description, size, "Undefined"); 131 else 132 snprintf(description, size, "INVALID"); 133 134 return description; 135 } 136 #endif 137 138 // This in the ToInt32 operation is defined in section 9.5 of the ECMA-262 spec. 139 // Note that this operation is identical to ToUInt32 other than to interpretation 140 // of the resulting bit-pattern (as such this metod is also called to implement 141 // ToUInt32). 142 // 143 // The operation can be descibed as round towards zero, then select the 32 least 144 // bits of the resulting value in 2s-complement representation. 145 int32_t toInt32(double number) 146 { 147 int64_t bits = WTF::bitwise_cast<int64_t>(number); 148 int32_t exp = (static_cast<int32_t>(bits >> 52) & 0x7ff) - 0x3ff; 149 150 // If exponent < 0 there will be no bits to the left of the decimal point 151 // after rounding; if the exponent is > 83 then no bits of precision can be 152 // left in the low 32-bit range of the result (IEEE-754 doubles have 52 bits 153 // of fractional precision). 154 // Note this case handles 0, -0, and all infinte, NaN, & denormal value. 155 if (exp < 0 || exp > 83) 156 return 0; 157 158 // Select the appropriate 32-bits from the floating point mantissa. If the 159 // exponent is 52 then the bits we need to select are already aligned to the 160 // lowest bits of the 64-bit integer representation of tghe number, no need 161 // to shift. If the exponent is greater than 52 we need to shift the value 162 // left by (exp - 52), if the value is less than 52 we need to shift right 163 // accordingly. 164 int32_t result = (exp > 52) 165 ? static_cast<int32_t>(bits << (exp - 52)) 166 : static_cast<int32_t>(bits >> (52 - exp)); 167 168 // IEEE-754 double precision values are stored omitting an implicit 1 before 169 // the decimal point; we need to reinsert this now. We may also the shifted 170 // invalid bits into the result that are not a part of the mantissa (the sign 171 // and exponent bits from the floatingpoint representation); mask these out. 172 if (exp < 32) { 173 int32_t missingOne = 1 << exp; 174 result &= missingOne - 1; 175 result += missingOne; 176 } 177 178 // If the input value was negative (we could test either 'number' or 'bits', 179 // but testing 'bits' is likely faster) invert the result appropriately. 180 return bits < 0 ? -result : result; 181 } 182 183 NEVER_INLINE double nonInlineNaN() 184 { 185 #if OS(SYMBIAN) 186 return nanval(); 187 #else 188 return std::numeric_limits<double>::quiet_NaN(); 189 #endif 190 } 191 192 bool JSValue::isValidCallee() 193 { 194 return asObject(asObject(asCell())->getAnonymousValue(0))->isGlobalObject(); 195 } 196 197 } // namespace JSC 198