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.
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.
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.
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.
26 #include "BooleanConstructor.h"
27 #include "BooleanPrototype.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>
39 static const double D32 = 4294967296.0;
42 double JSValue::toInteger(ExecState* exec) const
46 double d = toNumber(exec);
47 return isnan(d) ? 0.0 : trunc(d);
50 double JSValue::toIntegerPreserveNaN(ExecState* exec) const
54 return trunc(toNumber(exec));
57 double JSValue::toNumberSlowCase(ExecState* exec) const
59 ASSERT(!isInt32() && !isDouble());
61 return asCell()->toNumber(exec);
64 return isUndefined() ? std::numeric_limits<double>::quiet_NaN() : 0; // null and false both convert to 0.
67 JSObject* JSValue::toObjectSlowCase(ExecState* exec, JSGlobalObject* globalObject) const
71 if (isInt32() || isDouble())
72 return constructNumber(exec, globalObject, asValue());
73 if (isTrue() || isFalse())
74 return constructBooleanFromImmediateBoolean(exec, globalObject, asValue());
76 ASSERT(isUndefinedOrNull());
77 throwError(exec, createNotAnObjectError(exec, *this));
78 return JSNotAnObject::create(exec);
81 JSObject* JSValue::toThisObjectSlowCase(ExecState* exec) const
85 if (isInt32() || isDouble())
86 return constructNumber(exec, exec->lexicalGlobalObject(), asValue());
87 if (isTrue() || isFalse())
88 return constructBooleanFromImmediateBoolean(exec, exec->lexicalGlobalObject(), asValue());
89 ASSERT(isUndefinedOrNull());
90 return exec->globalThisValue();
93 JSObject* JSValue::synthesizeObject(ExecState* exec) const
97 return constructNumber(exec, exec->lexicalGlobalObject(), asValue());
99 return constructBooleanFromImmediateBoolean(exec, exec->lexicalGlobalObject(), asValue());
101 ASSERT(isUndefinedOrNull());
102 throwError(exec, createNotAnObjectError(exec, *this));
103 return JSNotAnObject::create(exec);
106 JSObject* JSValue::synthesizePrototype(ExecState* exec) const
110 return exec->lexicalGlobalObject()->numberPrototype();
112 return exec->lexicalGlobalObject()->booleanPrototype();
114 ASSERT(isUndefinedOrNull());
115 throwError(exec, createNotAnObjectError(exec, *this));
116 return JSNotAnObject::create(exec);
120 char* JSValue::description()
122 static const size_t size = 64;
123 static char description[size];
126 snprintf(description, size, "<JSValue()>");
128 snprintf(description, size, "Int32: %d", asInt32());
129 else if (isDouble()) {
131 snprintf(description, size, "Double: %lf, %lx", asDouble(), reinterpretDoubleToIntptr(asDouble()));
135 uint32_t asTwoInt32s[2];
137 u.asDouble = asDouble();
138 snprintf(description, size, "Double: %lf, %08x:%08x", asDouble(), u.asTwoInt32s[1], u.asTwoInt32s[0]);
141 snprintf(description, size, "Cell: %p", asCell());
143 snprintf(description, size, "True");
145 snprintf(description, size, "False");
147 snprintf(description, size, "Null");
148 else if (isUndefined())
149 snprintf(description, size, "Undefined");
151 snprintf(description, size, "INVALID");
157 // This in the ToInt32 operation is defined in section 9.5 of the ECMA-262 spec.
158 // Note that this operation is identical to ToUInt32 other than to interpretation
159 // of the resulting bit-pattern (as such this metod is also called to implement
162 // The operation can be descibed as round towards zero, then select the 32 least
163 // bits of the resulting value in 2s-complement representation.
164 int32_t toInt32(double number)
166 int64_t bits = WTF::bitwise_cast<int64_t>(number);
167 int32_t exp = (static_cast<int32_t>(bits >> 52) & 0x7ff) - 0x3ff;
169 // If exponent < 0 there will be no bits to the left of the decimal point
170 // after rounding; if the exponent is > 83 then no bits of precision can be
171 // left in the low 32-bit range of the result (IEEE-754 doubles have 52 bits
172 // of fractional precision).
173 // Note this case handles 0, -0, and all infinte, NaN, & denormal value.
174 if (exp < 0 || exp > 83)
177 // Select the appropriate 32-bits from the floating point mantissa. If the
178 // exponent is 52 then the bits we need to select are already aligned to the
179 // lowest bits of the 64-bit integer representation of tghe number, no need
180 // to shift. If the exponent is greater than 52 we need to shift the value
181 // left by (exp - 52), if the value is less than 52 we need to shift right
183 int32_t result = (exp > 52)
184 ? static_cast<int32_t>(bits << (exp - 52))
185 : static_cast<int32_t>(bits >> (52 - exp));
187 // IEEE-754 double precision values are stored omitting an implicit 1 before
188 // the decimal point; we need to reinsert this now. We may also the shifted
189 // invalid bits into the result that are not a part of the mantissa (the sign
190 // and exponent bits from the floatingpoint representation); mask these out.
192 int32_t missingOne = 1 << exp;
193 result &= missingOne - 1;
194 result += missingOne;
197 // If the input value was negative (we could test either 'number' or 'bits',
198 // but testing 'bits' is likely faster) invert the result appropriately.
199 return bits < 0 ? -result : result;
202 bool JSValue::isValidCallee()
204 return asObject(asCell())->globalObject();