71ee27dc788ee7a936600737eba38c083971a749
[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 private:
56     JSValue();
57     virtual ~JSValue();
58
59 public:
60     // Querying the type.
61     JSType type() const;
62     bool isUndefined() const;
63     bool isNull() const;
64     bool isUndefinedOrNull() const;
65     bool isBoolean() const;
66     bool isNumber() const;
67     bool isString() const;
68     bool isObject() const;
69     bool isObject(const ClassInfo*) const; // FIXME: Merge with inherits.
70
71     // Extracting the value.
72     bool getBoolean(bool&) const;
73     bool getBoolean() const; // false if not a boolean
74     bool getNumber(double&) const;
75     double getNumber() const; // NaN if not a number
76     double uncheckedGetNumber() const;
77     bool getString(UString&) const;
78     UString getString() const; // null string if not a string
79     JSObject* getObject(); // NULL if not an object
80     const JSObject* getObject() const; // NULL if not an object
81
82     CallType getCallData(CallData&);
83     ConstructType getConstructData(ConstructData&);
84
85     // Extracting integer values.
86     bool getUInt32(uint32_t&) const;
87     bool getTruncatedInt32(int32_t&) const;
88     bool getTruncatedUInt32(uint32_t&) const;
89     
90     // Basic conversions.
91     JSValue* toPrimitive(ExecState*, JSType preferredType = UnspecifiedType) const;
92     bool getPrimitiveNumber(ExecState*, double& number, JSValue*&);
93
94     bool toBoolean(ExecState*) const;
95
96     // toNumber conversion is expected to be side effect free if an exception has
97     // been set in the ExecState already.
98     double toNumber(ExecState*) const;
99     JSValue* toJSNumber(ExecState*) const; // Fast path for when you expect that the value is an immediate number.
100     UString toString(ExecState*) const;
101     JSObject* toObject(ExecState*) const;
102
103     // Integer conversions.
104     double toInteger(ExecState*) const;
105     double toIntegerPreserveNaN(ExecState*) const;
106     int32_t toInt32(ExecState*) const;
107     int32_t toInt32(ExecState*, bool& ok) const;
108     uint32_t toUInt32(ExecState*) const;
109     uint32_t toUInt32(ExecState*, bool& ok) const;
110
111     // These are identical logic to above, and faster than jsNumber(number)->toInt32(exec)
112     static int32_t toInt32(double);
113     static int32_t toUInt32(double);
114
115     // Floating point conversions.
116     float toFloat(ExecState*) const;
117
118     // Garbage collection.
119     void mark();
120     bool marked() const;
121
122     static int32_t toInt32SlowCase(double, bool& ok);
123     static uint32_t toUInt32SlowCase(double, bool& ok);
124
125     // Object operations, with the toObject operation included.
126     JSValue* get(ExecState*, const Identifier& propertyName) const;
127     JSValue* get(ExecState*, unsigned propertyName) const;
128     void put(ExecState*, const Identifier& propertyName, JSValue*);
129     void put(ExecState*, unsigned propertyName, JSValue*);
130     bool deleteProperty(ExecState*, const Identifier& propertyName);
131     bool deleteProperty(ExecState*, unsigned propertyName);
132
133     JSObject* toThisObject(ExecState*) const;
134     UString toThisString(ExecState*) const;
135     JSString* toThisJSString(ExecState*);
136
137     JSValue* getJSNumber(); // 0 if this is not a JSNumber or number object
138
139 private:
140     bool getPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&);
141     bool getPropertySlot(ExecState*, unsigned propertyName, PropertySlot&);
142     int32_t toInt32SlowCase(ExecState*, bool& ok) const;
143     uint32_t toUInt32SlowCase(ExecState*, bool& ok) const;
144
145     // Implementation details.
146     JSCell* asCell();
147     const JSCell* asCell() const;
148 };
149
150 inline JSValue::JSValue()
151 {
152 }
153
154 inline JSValue::~JSValue()
155 {
156 }
157
158 inline bool JSValue::isUndefined() const
159 {
160     return this == jsUndefined();
161 }
162
163 inline bool JSValue::isNull() const
164 {
165     return this == jsNull();
166 }
167
168 inline bool JSValue::isUndefinedOrNull() const
169 {
170     return JSImmediate::isUndefinedOrNull(this);
171 }
172
173 inline bool JSValue::isBoolean() const
174 {
175     return JSImmediate::isBoolean(this);
176 }
177
178 inline bool JSValue::getBoolean(bool& v) const
179 {
180     if (JSImmediate::isBoolean(this)) {
181         v = JSImmediate::toBoolean(this);
182         return true;
183     }
184     
185     return false;
186 }
187
188 inline bool JSValue::getBoolean() const
189 {
190     return JSImmediate::isBoolean(this) ? JSImmediate::toBoolean(this) : false;
191 }
192
193 ALWAYS_INLINE int32_t JSValue::toInt32(ExecState* exec) const
194 {
195     int32_t i;
196     if (getTruncatedInt32(i))
197         return i;
198     bool ok;
199     return toInt32SlowCase(exec, ok);
200 }
201
202 inline uint32_t JSValue::toUInt32(ExecState* exec) const
203 {
204     uint32_t i;
205     if (getTruncatedUInt32(i))
206         return i;
207     bool ok;
208     return toUInt32SlowCase(exec, ok);
209 }
210
211 inline int32_t JSValue::toInt32(double val)
212 {
213     if (!(val >= -2147483648.0 && val < 2147483648.0)) {
214         bool ignored;
215         return toInt32SlowCase(val, ignored);
216     }
217     return static_cast<int32_t>(val);
218 }
219
220 inline int32_t JSValue::toUInt32(double val)
221 {
222     if (!(val >= 0.0 && val < 4294967296.0)) {
223         bool ignored;
224         return toUInt32SlowCase(val, ignored);
225     }
226     return static_cast<uint32_t>(val);
227 }
228
229 inline int32_t JSValue::toInt32(ExecState* exec, bool& ok) const
230 {
231     int32_t i;
232     if (getTruncatedInt32(i)) {
233         ok = true;
234         return i;
235     }
236     return toInt32SlowCase(exec, ok);
237 }
238
239 inline uint32_t JSValue::toUInt32(ExecState* exec, bool& ok) const
240 {
241     uint32_t i;
242     if (getTruncatedUInt32(i)) {
243         ok = true;
244         return i;
245     }
246     return toUInt32SlowCase(exec, ok);
247 }
248
249 } // namespace KJS
250
251 #endif // JSValue_h