2008-07-02 Geoffrey Garen <ggaren@apple.com>
[WebKit-https.git] / JavaScriptCore / kjs / JSValue.h
1 /*
2  *  Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
3  *  Copyright (C) 2001 Peter Kelly (pmk@post.com)
4  *  Copyright (C) 2003, 2004, 2005, 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 #ifndef JSValue_h
24 #define JSValue_h
25
26 #include "CallData.h"
27 #include "ConstructData.h"
28 #include "ExecState.h"
29 #include "JSImmediate.h"
30 #include "ustring.h"
31 #include <stddef.h> // for size_t
32
33 namespace KJS {
34
35 class ExecState;
36 class Identifier;
37 class JSCell;
38 class JSObject;
39 class JSString;
40 class PropertySlot;
41 struct ClassInfo;
42 struct Instruction;
43
44 /**
45  * JSValue is the base type for all primitives (Undefined, Null, Boolean,
46  * String, Number) and objects in ECMAScript.
47  *
48  * Note: you should never inherit from JSValue as it is for primitive types
49  * only (all of which are provided internally by KJS). Instead, inherit from
50  * JSObject.
51  */
52 class JSValue : Noncopyable {
53     friend class JSCell; // so it can derive from this class
54     friend class Heap; // so it can call asCell()
55     friend class Machine; // so it can call asCell()
56 private:
57     JSValue();
58     virtual ~JSValue();
59
60 public:
61     // Querying the type.
62     JSType type() const;
63     bool isUndefined() const;
64     bool isNull() const;
65     bool isUndefinedOrNull() const;
66     bool isBoolean() const;
67     bool isNumber() const;
68     bool isString() const;
69     bool isObject() const;
70     bool isObject(const ClassInfo*) const; // FIXME: Merge with inherits.
71
72     // Extracting the value.
73     bool getBoolean(bool&) const;
74     bool getBoolean() const; // false if not a boolean
75     bool getNumber(double&) const;
76     double getNumber() const; // NaN if not a number
77     double uncheckedGetNumber() const;
78     bool getString(UString&) const;
79     UString getString() const; // null string if not a string
80     JSObject* getObject(); // NULL if not an object
81     const JSObject* getObject() const; // NULL if not an object
82
83     CallType getCallData(CallData&);
84     ConstructType getConstructData(ConstructData&);
85
86     // Extracting integer values.
87     bool getUInt32(uint32_t&) const;
88     bool getTruncatedInt32(int32_t&) const;
89     bool getTruncatedUInt32(uint32_t&) const;
90     
91     // Basic conversions.
92     JSValue* toPrimitive(ExecState*, JSType preferredType = UnspecifiedType) const;
93     bool getPrimitiveNumber(ExecState*, double& number, JSValue*&);
94
95     bool toBoolean(ExecState*) const;
96
97     // toNumber conversion is expected to be side effect free if an exception has
98     // been set in the ExecState already.
99     double toNumber(ExecState*) const;
100     JSValue* toJSNumber(ExecState*) const; // Fast path for when you expect that the value is an immediate number.
101     UString toString(ExecState*) const;
102     JSObject* toObject(ExecState*) const;
103
104     // Integer conversions.
105     double toInteger(ExecState*) const;
106     double toIntegerPreserveNaN(ExecState*) const;
107     int32_t toInt32(ExecState*) const;
108     int32_t toInt32(ExecState*, bool& ok) const;
109     uint32_t toUInt32(ExecState*) const;
110     uint32_t toUInt32(ExecState*, bool& ok) const;
111
112     // These are identical logic to above, and faster than jsNumber(number)->toInt32(exec)
113     static int32_t toInt32(double);
114     static int32_t toUInt32(double);
115
116     // Floating point conversions.
117     float toFloat(ExecState*) const;
118
119     // Garbage collection.
120     void mark();
121     bool marked() const;
122
123     static int32_t toInt32SlowCase(double, bool& ok);
124     static uint32_t toUInt32SlowCase(double, bool& ok);
125
126     // Object operations, with the toObject operation included.
127     JSValue* get(ExecState*, const Identifier& propertyName) const;
128     JSValue* get(ExecState*, unsigned propertyName) const;
129     void put(ExecState*, const Identifier& propertyName, JSValue*);
130     void put(ExecState*, unsigned propertyName, JSValue*);
131     bool deleteProperty(ExecState*, const Identifier& propertyName);
132     bool deleteProperty(ExecState*, unsigned propertyName);
133
134     JSObject* toThisObject(ExecState*) const;
135     UString toThisString(ExecState*) const;
136     JSString* toThisJSString(ExecState*);
137
138     JSValue* getJSNumber(); // 0 if this is not a JSNumber or number object
139
140 private:
141     bool getPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&);
142     bool getPropertySlot(ExecState*, unsigned propertyName, PropertySlot&);
143     int32_t toInt32SlowCase(ExecState*, bool& ok) const;
144     uint32_t toUInt32SlowCase(ExecState*, bool& ok) const;
145
146     // Implementation details.
147     JSCell* asCell();
148     const JSCell* asCell() const;
149 };
150
151 inline JSValue::JSValue()
152 {
153 }
154
155 inline JSValue::~JSValue()
156 {
157 }
158
159 inline bool JSValue::isUndefined() const
160 {
161     return this == jsUndefined();
162 }
163
164 inline bool JSValue::isNull() const
165 {
166     return this == jsNull();
167 }
168
169 inline bool JSValue::isUndefinedOrNull() const
170 {
171     return JSImmediate::isUndefinedOrNull(this);
172 }
173
174 inline bool JSValue::isBoolean() const
175 {
176     return JSImmediate::isBoolean(this);
177 }
178
179 inline bool JSValue::getBoolean(bool& v) const
180 {
181     if (JSImmediate::isBoolean(this)) {
182         v = JSImmediate::toBoolean(this);
183         return true;
184     }
185     
186     return false;
187 }
188
189 inline bool JSValue::getBoolean() const
190 {
191     return JSImmediate::isBoolean(this) ? JSImmediate::toBoolean(this) : false;
192 }
193
194 ALWAYS_INLINE int32_t JSValue::toInt32(ExecState* exec) const
195 {
196     int32_t i;
197     if (getTruncatedInt32(i))
198         return i;
199     bool ok;
200     return toInt32SlowCase(exec, ok);
201 }
202
203 inline uint32_t JSValue::toUInt32(ExecState* exec) const
204 {
205     uint32_t i;
206     if (getTruncatedUInt32(i))
207         return i;
208     bool ok;
209     return toUInt32SlowCase(exec, ok);
210 }
211
212 inline int32_t JSValue::toInt32(double val)
213 {
214     if (!(val >= -2147483648.0 && val < 2147483648.0)) {
215         bool ignored;
216         return toInt32SlowCase(val, ignored);
217     }
218     return static_cast<int32_t>(val);
219 }
220
221 inline int32_t JSValue::toUInt32(double val)
222 {
223     if (!(val >= 0.0 && val < 4294967296.0)) {
224         bool ignored;
225         return toUInt32SlowCase(val, ignored);
226     }
227     return static_cast<uint32_t>(val);
228 }
229
230 inline int32_t JSValue::toInt32(ExecState* exec, bool& ok) const
231 {
232     int32_t i;
233     if (getTruncatedInt32(i)) {
234         ok = true;
235         return i;
236     }
237     return toInt32SlowCase(exec, ok);
238 }
239
240 inline uint32_t JSValue::toUInt32(ExecState* exec, bool& ok) const
241 {
242     uint32_t i;
243     if (getTruncatedUInt32(i)) {
244         ok = true;
245         return i;
246     }
247     return toUInt32SlowCase(exec, ok);
248 }
249
250 } // namespace KJS
251
252 #endif // JSValue_h