]>
Commit | Line | Data |
---|---|---|
9dae56ea A |
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 | ||
ba379fdc A |
26 | #include "BooleanConstructor.h" |
27 | #include "BooleanPrototype.h" | |
14957cd0 | 28 | #include "Error.h" |
ba379fdc A |
29 | #include "ExceptionHelpers.h" |
30 | #include "JSGlobalObject.h" | |
9dae56ea | 31 | #include "JSFunction.h" |
ba379fdc A |
32 | #include "JSNotAnObject.h" |
33 | #include "NumberObject.h" | |
9dae56ea | 34 | #include <wtf/MathExtras.h> |
ba379fdc | 35 | #include <wtf/StringExtras.h> |
9dae56ea A |
36 | |
37 | namespace JSC { | |
38 | ||
39 | static const double D32 = 4294967296.0; | |
40 | ||
41 | // ECMA 9.4 | |
ba379fdc | 42 | double JSValue::toInteger(ExecState* exec) const |
9dae56ea | 43 | { |
ba379fdc A |
44 | if (isInt32()) |
45 | return asInt32(); | |
9dae56ea A |
46 | double d = toNumber(exec); |
47 | return isnan(d) ? 0.0 : trunc(d); | |
48 | } | |
49 | ||
ba379fdc | 50 | double JSValue::toIntegerPreserveNaN(ExecState* exec) const |
9dae56ea | 51 | { |
ba379fdc A |
52 | if (isInt32()) |
53 | return asInt32(); | |
9dae56ea A |
54 | return trunc(toNumber(exec)); |
55 | } | |
56 | ||
14957cd0 | 57 | JSObject* JSValue::toObjectSlowCase(ExecState* exec, JSGlobalObject* globalObject) const |
ba379fdc A |
58 | { |
59 | ASSERT(!isCell()); | |
60 | ||
61 | if (isInt32() || isDouble()) | |
14957cd0 | 62 | return constructNumber(exec, globalObject, asValue()); |
ba379fdc | 63 | if (isTrue() || isFalse()) |
14957cd0 A |
64 | return constructBooleanFromImmediateBoolean(exec, globalObject, asValue()); |
65 | ||
ba379fdc | 66 | ASSERT(isUndefinedOrNull()); |
14957cd0 A |
67 | throwError(exec, createNotAnObjectError(exec, *this)); |
68 | return new (exec) JSNotAnObject(exec); | |
ba379fdc A |
69 | } |
70 | ||
71 | JSObject* JSValue::toThisObjectSlowCase(ExecState* exec) const | |
72 | { | |
73 | ASSERT(!isCell()); | |
74 | ||
75 | if (isInt32() || isDouble()) | |
14957cd0 | 76 | return constructNumber(exec, exec->lexicalGlobalObject(), asValue()); |
ba379fdc | 77 | if (isTrue() || isFalse()) |
14957cd0 | 78 | return constructBooleanFromImmediateBoolean(exec, exec->lexicalGlobalObject(), asValue()); |
ba379fdc A |
79 | ASSERT(isUndefinedOrNull()); |
80 | return exec->globalThisValue(); | |
81 | } | |
82 | ||
83 | JSObject* JSValue::synthesizeObject(ExecState* exec) const | |
84 | { | |
85 | ASSERT(!isCell()); | |
86 | if (isNumber()) | |
14957cd0 | 87 | return constructNumber(exec, exec->lexicalGlobalObject(), asValue()); |
ba379fdc | 88 | if (isBoolean()) |
14957cd0 A |
89 | return constructBooleanFromImmediateBoolean(exec, exec->lexicalGlobalObject(), asValue()); |
90 | ||
91 | ASSERT(isUndefinedOrNull()); | |
92 | throwError(exec, createNotAnObjectError(exec, *this)); | |
93 | return new (exec) JSNotAnObject(exec); | |
ba379fdc A |
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 | ||
14957cd0 A |
104 | ASSERT(isUndefinedOrNull()); |
105 | throwError(exec, createNotAnObjectError(exec, *this)); | |
106 | return new (exec) JSNotAnObject(exec); | |
ba379fdc A |
107 | } |
108 | ||
109 | #ifndef NDEBUG | |
110 | char* JSValue::description() | |
111 | { | |
112 | static const size_t size = 32; | |
113 | static char description[size]; | |
f9bf01c6 A |
114 | |
115 | if (!*this) | |
116 | snprintf(description, size, "<JSValue()>"); | |
117 | else if (isInt32()) | |
ba379fdc A |
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"); | |
14957cd0 | 129 | else if (isUndefined()) |
ba379fdc | 130 | snprintf(description, size, "Undefined"); |
14957cd0 A |
131 | else |
132 | snprintf(description, size, "INVALID"); | |
ba379fdc A |
133 | |
134 | return description; | |
135 | } | |
136 | #endif | |
137 | ||
14957cd0 A |
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) | |
9dae56ea | 146 | { |
14957cd0 A |
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) | |
9dae56ea | 156 | return 0; |
9dae56ea | 157 | |
14957cd0 A |
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; | |
9dae56ea A |
176 | } |
177 | ||
14957cd0 A |
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; | |
9dae56ea A |
181 | } |
182 | ||
ba379fdc A |
183 | NEVER_INLINE double nonInlineNaN() |
184 | { | |
4e4e5a6f A |
185 | #if OS(SYMBIAN) |
186 | return nanval(); | |
187 | #else | |
ba379fdc | 188 | return std::numeric_limits<double>::quiet_NaN(); |
4e4e5a6f | 189 | #endif |
ba379fdc A |
190 | } |
191 | ||
14957cd0 A |
192 | bool JSValue::isValidCallee() |
193 | { | |
194 | return asObject(asObject(asCell())->getAnonymousValue(0))->isGlobalObject(); | |
195 | } | |
196 | ||
9dae56ea | 197 | } // namespace JSC |