• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
toInteger(ExecState * exec) const41 double JSValue::toInteger(ExecState* exec) const
42 {
43     if (isInt32())
44         return asInt32();
45     double d = toNumber(exec);
46     return isnan(d) ? 0.0 : trunc(d);
47 }
48 
toIntegerPreserveNaN(ExecState * exec) const49 double JSValue::toIntegerPreserveNaN(ExecState* exec) const
50 {
51     if (isInt32())
52         return asInt32();
53     return trunc(toNumber(exec));
54 }
55 
toObjectSlowCase(ExecState * exec) const56 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());
66     exec->setException(exception);
67     return new (exec) JSNotAnObject(exec, exception);
68 }
69 
toThisObjectSlowCase(ExecState * exec) const70 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 
synthesizeObject(ExecState * exec) const82 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());
91     exec->setException(exception);
92     return new (exec) JSNotAnObject(exec, exception);
93 }
94 
synthesizePrototype(ExecState * exec) const95 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());
104     exec->setException(exception);
105     return new (exec) JSNotAnObject(exec, exception);
106 }
107 
108 #ifndef NDEBUG
description()109 char* JSValue::description()
110 {
111     static const size_t size = 32;
112     static char description[size];
113     if (isInt32())
114         snprintf(description, size, "Int32: %d", asInt32());
115     else if (isDouble())
116         snprintf(description, size, "Double: %lf", asDouble());
117     else if (isCell())
118         snprintf(description, size, "Cell: %p", asCell());
119     else if (isTrue())
120         snprintf(description, size, "True");
121     else if (isFalse())
122         snprintf(description, size, "False");
123     else if (isNull())
124         snprintf(description, size, "Null");
125     else {
126         ASSERT(isUndefined());
127         snprintf(description, size, "Undefined");
128     }
129 
130     return description;
131 }
132 #endif
133 
toInt32SlowCase(double d,bool & ok)134 int32_t toInt32SlowCase(double d, bool& ok)
135 {
136     ok = true;
137 
138     if (d >= -D32 / 2 && d < D32 / 2)
139         return static_cast<int32_t>(d);
140 
141     if (isnan(d) || isinf(d)) {
142         ok = false;
143         return 0;
144     }
145 
146     double d32 = fmod(trunc(d), D32);
147     if (d32 >= D32 / 2)
148         d32 -= D32;
149     else if (d32 < -D32 / 2)
150         d32 += D32;
151     return static_cast<int32_t>(d32);
152 }
153 
toUInt32SlowCase(double d,bool & ok)154 uint32_t toUInt32SlowCase(double d, bool& ok)
155 {
156     ok = true;
157 
158     if (d >= 0.0 && d < D32)
159         return static_cast<uint32_t>(d);
160 
161     if (isnan(d) || isinf(d)) {
162         ok = false;
163         return 0;
164     }
165 
166     double d32 = fmod(trunc(d), D32);
167     if (d32 < 0)
168         d32 += D32;
169     return static_cast<uint32_t>(d32);
170 }
171 
nonInlineNaN()172 NEVER_INLINE double nonInlineNaN()
173 {
174     return std::numeric_limits<double>::quiet_NaN();
175 }
176 
177 } // namespace JSC
178