blob: ca4f558a0d38b7f8135b8e1c7e69e53a2fd118a8 [file] [log] [blame]
mjs6f821c82002-03-22 00:31:57 +00001/*
mjs6f821c82002-03-22 00:31:57 +00002 * Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
3 * Copyright (C) 2001 Peter Kelly (pmk@post.com)
fpizlo@apple.com1c4a32c2012-09-17 20:56:39 +00004 * Copyright (C) 2003, 2007, 2008, 2012 Apple Inc. All rights reserved.
mjs6f821c82002-03-22 00:31:57 +00005 *
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
mjscdff33b2006-01-23 21:41:36 +000018 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
ggaren07d4ce62005-07-14 18:27:04 +000019 * Boston, MA 02110-1301, USA.
mjs6f821c82002-03-22 00:31:57 +000020 *
21 */
22
mjsb64c50a2005-10-03 21:13:12 +000023#include "config.h"
mhahnenberg@apple.comc1bc9d32013-01-24 21:39:55 +000024#include "JSCJSValue.h"
darinc13d2ca2005-08-08 04:07:46 +000025
ggaren@apple.com540d71a62009-07-30 20:57:44 +000026#include "BooleanConstructor.h"
27#include "BooleanPrototype.h"
mhahnenberg@apple.comff62ccb2014-06-09 18:53:32 +000028#include "CustomGetterSetter.h"
barraclough@apple.com9c099f92010-06-06 23:34:36 +000029#include "Error.h"
ggaren@apple.com540d71a62009-07-30 20:57:44 +000030#include "ExceptionHelpers.h"
barraclough@apple.comdca6b2e2012-02-29 01:39:15 +000031#include "GetterSetter.h"
commit-queue@webkit.org906a4ec2014-09-09 00:21:24 +000032#include "JSCJSValueInlines.h"
weinig@apple.com860df8c2008-06-29 22:22:32 +000033#include "JSFunction.h"
mhahnenberg@apple.comc1bc9d32013-01-24 21:39:55 +000034#include "JSGlobalObject.h"
ggaren@apple.com540d71a62009-07-30 20:57:44 +000035#include "NumberObject.h"
commit-queue@webkit.org906a4ec2014-09-09 00:21:24 +000036#include "StructureInlines.h"
darin6c5f29d2006-07-05 04:13:32 +000037#include <wtf/MathExtras.h>
ggaren@apple.com540d71a62009-07-30 20:57:44 +000038#include <wtf/StringExtras.h>
mjs6f821c82002-03-22 00:31:57 +000039
cwzwarich@webkit.org3f782f62008-09-08 01:28:33 +000040namespace JSC {
mjs6f821c82002-03-22 00:31:57 +000041
mjs6f821c82002-03-22 00:31:57 +000042// ECMA 9.4
ggaren@apple.comdc067b62009-05-01 22:43:39 +000043double JSValue::toInteger(ExecState* exec) const
mjs6f821c82002-03-22 00:31:57 +000044{
ggaren@apple.com540d71a62009-07-30 20:57:44 +000045 if (isInt32())
46 return asInt32();
darin1622f9e2007-10-26 07:51:25 +000047 double d = toNumber(exec);
zandobersek@gmail.com9182d472013-02-13 23:01:21 +000048 return std::isnan(d) ? 0.0 : trunc(d);
darin1622f9e2007-10-26 07:51:25 +000049}
50
ggaren@apple.comdc067b62009-05-01 22:43:39 +000051double JSValue::toIntegerPreserveNaN(ExecState* exec) const
darin1622f9e2007-10-26 07:51:25 +000052{
ggaren@apple.com540d71a62009-07-30 20:57:44 +000053 if (isInt32())
54 return asInt32();
darin1622f9e2007-10-26 07:51:25 +000055 return trunc(toNumber(exec));
mjs6f821c82002-03-22 00:31:57 +000056}
57
commit-queue@webkit.org1750e1e2015-09-15 17:43:27 +000058double JSValue::toLength(ExecState* exec) const
59{
60 // ECMA 7.1.15
61 // http://www.ecma-international.org/ecma-262/6.0/#sec-tolength
62 double d = toInteger(exec);
63 if (d <= 0)
64 return 0.0;
65 if (std::isinf(d))
66 return 9007199254740991.0; // 2 ** 53 - 1
67 return std::min(d, 9007199254740991.0);
68}
69
barraclough@apple.com06585102011-07-22 05:34:08 +000070double JSValue::toNumberSlowCase(ExecState* exec) const
71{
72 ASSERT(!isInt32() && !isDouble());
73 if (isCell())
74 return asCell()->toNumber(exec);
75 if (isTrue())
76 return 1.0;
fpizlo@apple.combeef4522014-04-16 22:44:00 +000077 return isUndefined() ? PNaN : 0; // null and false both convert to 0.
barraclough@apple.com06585102011-07-22 05:34:08 +000078}
79
oliver@apple.com3b6dc572011-03-28 23:39:16 +000080JSObject* JSValue::toObjectSlowCase(ExecState* exec, JSGlobalObject* globalObject) const
ggaren@apple.com540d71a62009-07-30 20:57:44 +000081{
82 ASSERT(!isCell());
83
84 if (isInt32() || isDouble())
oliver@apple.com3b6dc572011-03-28 23:39:16 +000085 return constructNumber(exec, globalObject, asValue());
ggaren@apple.com540d71a62009-07-30 20:57:44 +000086 if (isTrue() || isFalse())
oliver@apple.com3b6dc572011-03-28 23:39:16 +000087 return constructBooleanFromImmediateBoolean(exec, globalObject, asValue());
barraclough@apple.com8da6d972010-11-16 21:11:26 +000088
ggaren@apple.com540d71a62009-07-30 20:57:44 +000089 ASSERT(isUndefinedOrNull());
akling@apple.com3d286862013-10-08 03:29:05 +000090 VM& vm = exec->vm();
91 vm.throwException(exec, createNotAnObjectError(exec, *this));
mark.lam@apple.com5088f6b2016-03-08 20:57:25 +000092 return nullptr;
ggaren@apple.com540d71a62009-07-30 20:57:44 +000093}
94
oliver@apple.come2fe4ce2013-07-25 03:59:41 +000095JSValue JSValue::toThisSlowCase(ExecState* exec, ECMAMode ecmaMode) const
ggaren@apple.com540d71a62009-07-30 20:57:44 +000096{
97 ASSERT(!isCell());
98
oliver@apple.come2fe4ce2013-07-25 03:59:41 +000099 if (ecmaMode == StrictMode)
100 return *this;
101
ggaren@apple.com540d71a62009-07-30 20:57:44 +0000102 if (isInt32() || isDouble())
oliver@apple.com3b6dc572011-03-28 23:39:16 +0000103 return constructNumber(exec, exec->lexicalGlobalObject(), asValue());
ggaren@apple.com540d71a62009-07-30 20:57:44 +0000104 if (isTrue() || isFalse())
oliver@apple.com3b6dc572011-03-28 23:39:16 +0000105 return constructBooleanFromImmediateBoolean(exec, exec->lexicalGlobalObject(), asValue());
ggaren@apple.com540d71a62009-07-30 20:57:44 +0000106 ASSERT(isUndefinedOrNull());
107 return exec->globalThisValue();
108}
109
ggaren@apple.com540d71a62009-07-30 20:57:44 +0000110JSObject* JSValue::synthesizePrototype(ExecState* exec) const
111{
barraclough@apple.comdca6b2e2012-02-29 01:39:15 +0000112 if (isCell()) {
utatane.tea@gmail.com947fa4e2015-01-31 01:23:56 +0000113 if (isString())
114 return exec->lexicalGlobalObject()->stringPrototype();
115 ASSERT(isSymbol());
116 return exec->lexicalGlobalObject()->symbolPrototype();
barraclough@apple.comdca6b2e2012-02-29 01:39:15 +0000117 }
118
ggaren@apple.com540d71a62009-07-30 20:57:44 +0000119 if (isNumber())
120 return exec->lexicalGlobalObject()->numberPrototype();
121 if (isBoolean())
122 return exec->lexicalGlobalObject()->booleanPrototype();
123
barraclough@apple.com8da6d972010-11-16 21:11:26 +0000124 ASSERT(isUndefinedOrNull());
akling@apple.com3d286862013-10-08 03:29:05 +0000125 VM& vm = exec->vm();
126 vm.throwException(exec, createNotAnObjectError(exec, *this));
mark.lam@apple.com5088f6b2016-03-08 20:57:25 +0000127 return nullptr;
ggaren@apple.com540d71a62009-07-30 20:57:44 +0000128}
129
barraclough@apple.comdca6b2e2012-02-29 01:39:15 +0000130// ECMA 8.7.2
utatane.tea@gmail.com78b50c62016-03-11 17:28:46 +0000131bool JSValue::putToPrimitive(ExecState* exec, PropertyName propertyName, JSValue value, PutPropertySlot& slot)
barraclough@apple.comdca6b2e2012-02-29 01:39:15 +0000132{
ggaren@apple.com9a9a4b52013-04-18 19:32:17 +0000133 VM& vm = exec->vm();
barraclough@apple.comdca6b2e2012-02-29 01:39:15 +0000134
utatane.tea@gmail.com78b50c62016-03-11 17:28:46 +0000135 if (Optional<uint32_t> index = parseIndex(propertyName))
136 return putToPrimitiveByIndex(exec, index.value(), value, slot.isStrictMode());
fpizlo@apple.com1c4a32c2012-09-17 20:56:39 +0000137
barraclough@apple.comdca6b2e2012-02-29 01:39:15 +0000138 // Check if there are any setters or getters in the prototype chain
139 JSObject* obj = synthesizePrototype(exec);
mark.lam@apple.com5088f6b2016-03-08 20:57:25 +0000140 if (UNLIKELY(!obj))
utatane.tea@gmail.com78b50c62016-03-11 17:28:46 +0000141 return false;
barraclough@apple.comdca6b2e2012-02-29 01:39:15 +0000142 JSValue prototype;
143 if (propertyName != exec->propertyNames().underscoreProto) {
144 for (; !obj->structure()->hasReadOnlyOrGetterSetterPropertiesExcludingProto(); obj = asObject(prototype)) {
sbarati@apple.comfa857522016-03-07 01:00:33 +0000145 prototype = obj->getPrototypeDirect();
barraclough@apple.comdca6b2e2012-02-29 01:39:15 +0000146 if (prototype.isNull()) {
147 if (slot.isStrictMode())
148 throwTypeError(exec, StrictModeReadonlyPropertyWriteError);
utatane.tea@gmail.com78b50c62016-03-11 17:28:46 +0000149 return false;
barraclough@apple.comdca6b2e2012-02-29 01:39:15 +0000150 }
151 }
152 }
153
154 for (; ; obj = asObject(prototype)) {
155 unsigned attributes;
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +0000156 PropertyOffset offset = obj->structure()->get(vm, propertyName, attributes);
fpizlo@apple.comd68b1f82012-07-05 22:55:51 +0000157 if (offset != invalidOffset) {
barraclough@apple.comdca6b2e2012-02-29 01:39:15 +0000158 if (attributes & ReadOnly) {
159 if (slot.isStrictMode())
commit-queue@webkit.org3f922f92013-08-29 00:28:42 +0000160 exec->vm().throwException(exec, createTypeError(exec, StrictModeReadonlyPropertyWriteError));
utatane.tea@gmail.com78b50c62016-03-11 17:28:46 +0000161 return false;
barraclough@apple.comdca6b2e2012-02-29 01:39:15 +0000162 }
163
ggaren@apple.com329c1532013-01-11 21:33:47 +0000164 JSValue gs = obj->getDirect(offset);
utatane.tea@gmail.com78b50c62016-03-11 17:28:46 +0000165 if (gs.isGetterSetter())
166 return callSetter(exec, *this, gs, value, slot.isStrictMode() ? StrictMode : NotStrictMode);
barraclough@apple.comdca6b2e2012-02-29 01:39:15 +0000167
utatane.tea@gmail.com78b50c62016-03-11 17:28:46 +0000168 if (gs.isCustomGetterSetter())
169 return callCustomSetter(exec, gs, attributes & CustomAccessor, obj, slot.thisValue(), value);
mhahnenberg@apple.comff62ccb2014-06-09 18:53:32 +0000170
barraclough@apple.comdca6b2e2012-02-29 01:39:15 +0000171 // If there's an existing property on the object or one of its
172 // prototypes it should be replaced, so break here.
173 break;
174 }
175
sbarati@apple.comfa857522016-03-07 01:00:33 +0000176 prototype = obj->getPrototype(vm, exec);
177 if (vm.exception())
utatane.tea@gmail.com78b50c62016-03-11 17:28:46 +0000178 return false;
barraclough@apple.comdca6b2e2012-02-29 01:39:15 +0000179 if (prototype.isNull())
180 break;
181 }
182
183 if (slot.isStrictMode())
184 throwTypeError(exec, StrictModeReadonlyPropertyWriteError);
utatane.tea@gmail.com78b50c62016-03-11 17:28:46 +0000185 return false;
barraclough@apple.comdca6b2e2012-02-29 01:39:15 +0000186}
187
utatane.tea@gmail.com78b50c62016-03-11 17:28:46 +0000188bool JSValue::putToPrimitiveByIndex(ExecState* exec, unsigned propertyName, JSValue value, bool shouldThrow)
fpizlo@apple.com1c4a32c2012-09-17 20:56:39 +0000189{
190 if (propertyName > MAX_ARRAY_INDEX) {
oliver@apple.com68848412014-01-02 20:56:20 +0000191 PutPropertySlot slot(*this, shouldThrow);
utatane.tea@gmail.com78b50c62016-03-11 17:28:46 +0000192 return putToPrimitive(exec, Identifier::from(exec, propertyName), value, slot);
fpizlo@apple.com1c4a32c2012-09-17 20:56:39 +0000193 }
194
mark.lam@apple.com5088f6b2016-03-08 20:57:25 +0000195 JSObject* prototype = synthesizePrototype(exec);
196 if (UNLIKELY(!prototype)) {
197 ASSERT(exec->hadException());
utatane.tea@gmail.com78b50c62016-03-11 17:28:46 +0000198 return false;
mark.lam@apple.com5088f6b2016-03-08 20:57:25 +0000199 }
utatane.tea@gmail.com78b50c62016-03-11 17:28:46 +0000200 bool putResult = false;
201 if (prototype->attemptToInterceptPutByIndexOnHoleForPrototype(exec, *this, propertyName, value, shouldThrow, putResult))
202 return putResult;
fpizlo@apple.com1c4a32c2012-09-17 20:56:39 +0000203
204 if (shouldThrow)
205 throwTypeError(exec, StrictModeReadonlyPropertyWriteError);
utatane.tea@gmail.com78b50c62016-03-11 17:28:46 +0000206 return false;
fpizlo@apple.com1c4a32c2012-09-17 20:56:39 +0000207}
208
fpizlo@apple.com9fe49132012-12-04 19:29:13 +0000209void JSValue::dump(PrintStream& out) const
ggaren@apple.com540d71a62009-07-30 20:57:44 +0000210{
oliver@apple.com237b1462013-07-25 04:05:36 +0000211 dumpInContext(out, 0);
212}
213
214void JSValue::dumpInContext(PrintStream& out, DumpContext* context) const
215{
fpizlo@apple.comb41e6822014-07-25 20:55:17 +0000216 dumpInContextAssumingStructure(
217 out, context, (!!*this && isCell()) ? asCell()->structure() : nullptr);
218}
219
220void JSValue::dumpInContextAssumingStructure(
221 PrintStream& out, DumpContext* context, Structure* structure) const
222{
ggaren@apple.com53e48d52009-10-02 18:06:49 +0000223 if (!*this)
fpizlo@apple.com9fe49132012-12-04 19:29:13 +0000224 out.print("<JSValue()>");
ggaren@apple.com53e48d52009-10-02 18:06:49 +0000225 else if (isInt32())
fpizlo@apple.com9fe49132012-12-04 19:29:13 +0000226 out.printf("Int32: %d", asInt32());
fpizlo@apple.com746c6d072011-09-07 02:47:51 +0000227 else if (isDouble()) {
228#if USE(JSVALUE64)
fpizlo@apple.com9fe49132012-12-04 19:29:13 +0000229 out.printf("Double: %lld, %lf", (long long)reinterpretDoubleToInt64(asDouble()), asDouble());
fpizlo@apple.com746c6d072011-09-07 02:47:51 +0000230#else
231 union {
232 double asDouble;
233 uint32_t asTwoInt32s[2];
234 } u;
235 u.asDouble = asDouble();
fpizlo@apple.com9fe49132012-12-04 19:29:13 +0000236 out.printf("Double: %08x:%08x, %lf", u.asTwoInt32s[1], u.asTwoInt32s[0], asDouble());
fpizlo@apple.com746c6d072011-09-07 02:47:51 +0000237#endif
fpizlo@apple.com0e9910a2012-10-09 23:39:53 +0000238 } else if (isCell()) {
fpizlo@apple.comb41e6822014-07-25 20:55:17 +0000239 if (structure->classInfo()->isSubClassOf(JSString::info())) {
fpizlo@apple.com3fa6f5d2013-02-09 19:33:00 +0000240 JSString* string = jsCast<JSString*>(asCell());
oliver@apple.comb3e5acb2013-07-25 04:02:53 +0000241 out.print("String");
fpizlo@apple.com3fa6f5d2013-02-09 19:33:00 +0000242 if (string->isRope())
oliver@apple.comb3e5acb2013-07-25 04:02:53 +0000243 out.print(" (rope)");
244 const StringImpl* impl = string->tryGetValueImpl();
245 if (impl) {
246 if (impl->isAtomic())
247 out.print(" (atomic)");
barraclough@apple.com0cde90d2014-03-20 21:05:49 +0000248 if (impl->isAtomic())
oliver@apple.comb3e5acb2013-07-25 04:02:53 +0000249 out.print(" (identifier)");
utatane.tea@gmail.comb6f60b22015-03-31 21:25:14 +0000250 if (impl->isSymbol())
251 out.print(" (symbol)");
oliver@apple.comb3e5acb2013-07-25 04:02:53 +0000252 } else
253 out.print(" (unresolved)");
254 out.print(": ", impl);
fpizlo@apple.comb41e6822014-07-25 20:55:17 +0000255 } else if (structure->classInfo()->isSubClassOf(Structure::info()))
oliver@apple.com237b1462013-07-25 04:05:36 +0000256 out.print("Structure: ", inContext(*jsCast<Structure*>(asCell()), context));
oliver@apple.com880e6c32013-07-25 04:03:25 +0000257 else {
fpizlo@apple.com0520bd42012-12-18 22:32:52 +0000258 out.print("Cell: ", RawPointer(asCell()));
fpizlo@apple.comb41e6822014-07-25 20:55:17 +0000259 out.print(" (", inContext(*structure, context), ")");
fpizlo@apple.com1e89af32012-11-19 02:55:14 +0000260 }
fpizlo@apple.com57399572014-03-05 22:01:57 +0000261#if USE(JSVALUE64)
262 out.print(", ID: ", asCell()->structureID());
263#endif
fpizlo@apple.com0e9910a2012-10-09 23:39:53 +0000264 } else if (isTrue())
fpizlo@apple.com9fe49132012-12-04 19:29:13 +0000265 out.print("True");
ggaren@apple.com540d71a62009-07-30 20:57:44 +0000266 else if (isFalse())
fpizlo@apple.com9fe49132012-12-04 19:29:13 +0000267 out.print("False");
ggaren@apple.com540d71a62009-07-30 20:57:44 +0000268 else if (isNull())
fpizlo@apple.com9fe49132012-12-04 19:29:13 +0000269 out.print("Null");
sfalken@apple.comd5e7ced2010-06-24 18:28:06 +0000270 else if (isUndefined())
fpizlo@apple.com9fe49132012-12-04 19:29:13 +0000271 out.print("Undefined");
sfalken@apple.comd5e7ced2010-06-24 18:28:06 +0000272 else
fpizlo@apple.com9fe49132012-12-04 19:29:13 +0000273 out.print("INVALID");
ggaren@apple.com540d71a62009-07-30 20:57:44 +0000274}
ggaren@apple.com540d71a62009-07-30 20:57:44 +0000275
msaboff@apple.com149f8e12014-06-25 06:45:50 +0000276void JSValue::dumpForBacktrace(PrintStream& out) const
277{
278 if (!*this)
279 out.print("<JSValue()>");
280 else if (isInt32())
281 out.printf("%d", asInt32());
282 else if (isDouble())
283 out.printf("%lf", asDouble());
284 else if (isCell()) {
285 if (asCell()->inherits(JSString::info())) {
286 JSString* string = jsCast<JSString*>(asCell());
287 const StringImpl* impl = string->tryGetValueImpl();
288 if (impl)
289 out.print("\"", impl, "\"");
290 else
291 out.print("(unresolved string)");
292 } else if (asCell()->inherits(Structure::info())) {
293 out.print("Structure[ ", asCell()->structure()->classInfo()->className);
294#if USE(JSVALUE64)
295 out.print(" ID: ", asCell()->structureID());
296#endif
297 out.print("]: ", RawPointer(asCell()));
298 } else {
299 out.print("Cell[", asCell()->structure()->classInfo()->className);
300#if USE(JSVALUE64)
301 out.print(" ID: ", asCell()->structureID());
302#endif
303 out.print("]: ", RawPointer(asCell()));
304 }
305 } else if (isTrue())
306 out.print("True");
307 else if (isFalse())
308 out.print("False");
309 else if (isNull())
310 out.print("Null");
311 else if (isUndefined())
312 out.print("Undefined");
313 else
314 out.print("INVALID");
315}
316
barraclough@apple.come7858b12010-09-20 01:23:33 +0000317// This in the ToInt32 operation is defined in section 9.5 of the ECMA-262 spec.
318// Note that this operation is identical to ToUInt32 other than to interpretation
319// of the resulting bit-pattern (as such this metod is also called to implement
320// ToUInt32).
321//
322// The operation can be descibed as round towards zero, then select the 32 least
323// bits of the resulting value in 2s-complement representation.
324int32_t toInt32(double number)
mjs6f821c82002-03-22 00:31:57 +0000325{
barraclough@apple.come7858b12010-09-20 01:23:33 +0000326 int64_t bits = WTF::bitwise_cast<int64_t>(number);
327 int32_t exp = (static_cast<int32_t>(bits >> 52) & 0x7ff) - 0x3ff;
328
329 // If exponent < 0 there will be no bits to the left of the decimal point
330 // after rounding; if the exponent is > 83 then no bits of precision can be
331 // left in the low 32-bit range of the result (IEEE-754 doubles have 52 bits
332 // of fractional precision).
333 // Note this case handles 0, -0, and all infinte, NaN, & denormal value.
334 if (exp < 0 || exp > 83)
darinc13d2ca2005-08-08 04:07:46 +0000335 return 0;
barraclough@apple.come7858b12010-09-20 01:23:33 +0000336
337 // Select the appropriate 32-bits from the floating point mantissa. If the
338 // exponent is 52 then the bits we need to select are already aligned to the
339 // lowest bits of the 64-bit integer representation of tghe number, no need
340 // to shift. If the exponent is greater than 52 we need to shift the value
341 // left by (exp - 52), if the value is less than 52 we need to shift right
342 // accordingly.
343 int32_t result = (exp > 52)
344 ? static_cast<int32_t>(bits << (exp - 52))
345 : static_cast<int32_t>(bits >> (52 - exp));
346
347 // IEEE-754 double precision values are stored omitting an implicit 1 before
348 // the decimal point; we need to reinsert this now. We may also the shifted
349 // invalid bits into the result that are not a part of the mantissa (the sign
350 // and exponent bits from the floatingpoint representation); mask these out.
351 if (exp < 32) {
352 int32_t missingOne = 1 << exp;
353 result &= missingOne - 1;
354 result += missingOne;
ddkilzer20e0d1b2006-07-11 03:16:41 +0000355 }
mjs6f821c82002-03-22 00:31:57 +0000356
barraclough@apple.come7858b12010-09-20 01:23:33 +0000357 // If the input value was negative (we could test either 'number' or 'bits',
358 // but testing 'bits' is likely faster) invert the result appropriately.
359 return bits < 0 ? -result : result;
darina51d07b2004-02-02 21:23:17 +0000360}
361
oliver@apple.com5dea6152010-05-21 18:19:42 +0000362bool JSValue::isValidCallee()
363{
oliver@apple.com2346a3e2011-09-07 19:40:41 +0000364 return asObject(asCell())->globalObject();
oliver@apple.com5dea6152010-05-21 18:19:42 +0000365}
366
fpizlo@apple.com11673742016-03-03 02:06:18 +0000367JSString* JSValue::toStringSlowCase(ExecState* exec, bool returnEmptyStringOnError) const
ggaren@apple.comfbf6d9a2011-10-19 02:54:29 +0000368{
fpizlo@apple.com11673742016-03-03 02:06:18 +0000369 auto errorValue = [&] () -> JSString* {
370 if (returnEmptyStringOnError)
371 return jsEmptyString(exec);
372 return nullptr;
373 };
374
ggaren@apple.com9a9a4b52013-04-18 19:32:17 +0000375 VM& vm = exec->vm();
ggaren@apple.com64be5e92012-01-24 07:34:10 +0000376 ASSERT(!isString());
darin@apple.com6d8af842015-06-24 02:33:18 +0000377 if (isInt32()) {
378 auto integer = asInt32();
379 if (static_cast<unsigned>(integer) <= 9)
380 return vm.smallStrings.singleCharacterString(integer + '0');
381 return jsNontrivialString(&vm, vm.numericStrings.add(integer));
382 }
ggaren@apple.comfbf6d9a2011-10-19 02:54:29 +0000383 if (isDouble())
ggaren@apple.com9a9a4b52013-04-18 19:32:17 +0000384 return jsString(&vm, vm.numericStrings.add(asDouble()));
ggaren@apple.comfbf6d9a2011-10-19 02:54:29 +0000385 if (isTrue())
ggaren@apple.com9a9a4b52013-04-18 19:32:17 +0000386 return vm.smallStrings.trueString();
ggaren@apple.comfbf6d9a2011-10-19 02:54:29 +0000387 if (isFalse())
ggaren@apple.com9a9a4b52013-04-18 19:32:17 +0000388 return vm.smallStrings.falseString();
ggaren@apple.comfbf6d9a2011-10-19 02:54:29 +0000389 if (isNull())
ggaren@apple.com9a9a4b52013-04-18 19:32:17 +0000390 return vm.smallStrings.nullString();
ggaren@apple.comfbf6d9a2011-10-19 02:54:29 +0000391 if (isUndefined())
ggaren@apple.com9a9a4b52013-04-18 19:32:17 +0000392 return vm.smallStrings.undefinedString();
utatane.tea@gmail.com947fa4e2015-01-31 01:23:56 +0000393 if (isSymbol()) {
utatane.tea@gmail.com5d80e952016-05-04 01:21:38 +0000394 throwTypeError(exec, "Cannot convert a symbol to a string");
fpizlo@apple.com11673742016-03-03 02:06:18 +0000395 return errorValue();
utatane.tea@gmail.com947fa4e2015-01-31 01:23:56 +0000396 }
ggaren@apple.comfbf6d9a2011-10-19 02:54:29 +0000397
398 ASSERT(isCell());
ggaren@apple.com64be5e92012-01-24 07:34:10 +0000399 JSValue value = asCell()->toPrimitive(exec, PreferString);
fpizlo@apple.com11673742016-03-03 02:06:18 +0000400 if (vm.exception())
401 return errorValue();
ggaren@apple.com64be5e92012-01-24 07:34:10 +0000402 ASSERT(!value.isObject());
fpizlo@apple.com11673742016-03-03 02:06:18 +0000403 JSString* result = value.toString(exec);
404 if (vm.exception())
405 return errorValue();
406 return result;
ggaren@apple.comfbf6d9a2011-10-19 02:54:29 +0000407}
408
benjamin@webkit.orgcff06e42012-08-30 21:23:51 +0000409String JSValue::toWTFStringSlowCase(ExecState* exec) const
benjamin@webkit.org8063cc72012-04-06 00:12:25 +0000410{
darin@apple.com6d8af842015-06-24 02:33:18 +0000411 VM& vm = exec->vm();
412 if (isInt32())
413 return vm.numericStrings.add(asInt32());
414 if (isDouble())
415 return vm.numericStrings.add(asDouble());
416 if (isTrue())
417 return vm.propertyNames->trueKeyword.string();
418 if (isFalse())
419 return vm.propertyNames->falseKeyword.string();
420 if (isNull())
421 return vm.propertyNames->nullKeyword.string();
422 if (isUndefined())
423 return vm.propertyNames->undefinedKeyword.string();
424 return toString(exec)->value(exec);
benjamin@webkit.org8063cc72012-04-06 00:12:25 +0000425}
426
cwzwarich@webkit.org3f782f62008-09-08 01:28:33 +0000427} // namespace JSC