63e5d4e86f8c2e44169ceeb26d33f7b1cddb7f9a
[WebKit-https.git] / JavaScriptCore / kjs / JSCell.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 JSCell_h
24 #define JSCell_h
25
26 #include "JSValue.h"
27 #include "collector.h"
28
29 namespace KJS {
30
31 class JSCell : public JSValue {
32     friend class Heap;
33     friend class GetterSetter;
34     friend class JSObject;
35     friend class JSPropertyNameIterator;
36     friend class JSValue;
37     friend class JSNumberCell;
38     friend class JSString;
39 private:
40     JSCell();
41     virtual ~JSCell();
42
43 public:
44     // Querying the type.
45     virtual JSType type() const = 0;
46     bool isNumber() const;
47     bool isString() const;
48     bool isObject() const;
49     bool isObject(const ClassInfo*) const; // FIXME: Merge with inherits.
50
51     // Extracting the value.
52     bool getNumber(double&) const;
53     double getNumber() const; // NaN if not a number
54     bool getString(UString&) const;
55     UString getString() const; // null string if not a string
56     JSObject* getObject(); // NULL if not an object
57     const JSObject* getObject() const; // NULL if not an object
58     
59     virtual CallType getCallData(CallData&);
60     virtual ConstructType getConstructData(ConstructData&);
61
62     // Extracting integer values.
63     virtual bool getUInt32(uint32_t&) const;
64     virtual bool getTruncatedInt32(int32_t&) const;
65     virtual bool getTruncatedUInt32(uint32_t&) const;
66
67     // Basic conversions.
68     virtual JSValue* toPrimitive(ExecState*, JSType preferredType = UnspecifiedType) const = 0;
69     virtual bool getPrimitiveNumber(ExecState*, double& number, JSValue*&) = 0;
70     virtual bool toBoolean(ExecState*) const = 0;
71     virtual double toNumber(ExecState*) const = 0;
72     virtual UString toString(ExecState*) const = 0;
73     virtual JSObject* toObject(ExecState*) const = 0;
74
75     // Garbage collection.
76     void* operator new(size_t, ExecState*);
77     virtual void mark();
78     bool marked() const;
79
80     // Object operations, with the toObject operation included.
81     virtual const ClassInfo* classInfo() const;
82     virtual void put(ExecState*, const Identifier& propertyName, JSValue*);
83     virtual void put(ExecState*, unsigned propertyName, JSValue*);
84     virtual bool deleteProperty(ExecState*, const Identifier& propertyName);
85     virtual bool deleteProperty(ExecState*, unsigned propertyName);
86
87     virtual JSObject* toThisObject(ExecState*) const;
88     virtual UString toThisString(ExecState*) const;
89     virtual JSString* toThisJSString(ExecState*);
90     virtual JSValue* getJSNumber();
91
92 private:
93     // Base implementation, but for non-object classes implements getPropertySlot.
94     virtual bool getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&);
95     virtual bool getOwnPropertySlot(ExecState*, unsigned propertyName, PropertySlot&);
96 };
97
98 inline JSCell::JSCell()
99 {
100 }
101
102 inline JSCell::~JSCell()
103 {
104 }
105
106 inline bool JSCell::isNumber() const
107 {
108     return type() == NumberType;
109 }
110
111 inline bool JSCell::isString() const
112 {
113     return type() == StringType;
114 }
115
116 inline bool JSCell::isObject() const
117 {
118     return type() == ObjectType;
119 }
120
121 inline bool JSCell::marked() const
122 {
123     return Heap::isCellMarked(this);
124 }
125
126 inline void JSCell::mark()
127 {
128     return Heap::markCell(this);
129 }
130
131 ALWAYS_INLINE JSCell* JSValue::asCell()
132 {
133     ASSERT(!JSImmediate::isImmediate(this));
134     return static_cast<JSCell*>(this);
135 }
136
137 ALWAYS_INLINE const JSCell* JSValue::asCell() const
138 {
139     ASSERT(!JSImmediate::isImmediate(this));
140     return static_cast<const JSCell*>(this);
141 }
142
143
144 // --- JSValue inlines ----------------------------
145
146 inline bool JSValue::isNumber() const
147 {
148     return JSImmediate::isNumber(this) || (!JSImmediate::isImmediate(this) && asCell()->isNumber());
149 }
150
151 inline bool JSValue::isString() const
152 {
153     return !JSImmediate::isImmediate(this) && asCell()->isString();
154 }
155
156 inline bool JSValue::isObject() const
157 {
158     return !JSImmediate::isImmediate(this) && asCell()->isObject();
159 }
160
161 inline bool JSValue::getNumber(double& v) const
162 {
163     if (JSImmediate::isImmediate(this)) {
164         v = JSImmediate::toDouble(this);
165         return true;
166     }
167     return asCell()->getNumber(v);
168 }
169
170 inline double JSValue::getNumber() const
171 {
172     return JSImmediate::isImmediate(this) ? JSImmediate::toDouble(this) : asCell()->getNumber();
173 }
174
175 inline bool JSValue::getString(UString& s) const
176 {
177     return !JSImmediate::isImmediate(this) && asCell()->getString(s);
178 }
179
180 inline UString JSValue::getString() const
181 {
182     return JSImmediate::isImmediate(this) ? UString() : asCell()->getString();
183 }
184
185 inline JSObject *JSValue::getObject()
186 {
187     return JSImmediate::isImmediate(this) ? 0 : asCell()->getObject();
188 }
189
190 inline const JSObject *JSValue::getObject() const
191 {
192     return JSImmediate::isImmediate(this) ? 0 : asCell()->getObject();
193 }
194
195 inline CallType JSValue::getCallData(CallData& callData)
196 {
197     return JSImmediate::isImmediate(this) ? CallTypeNone : asCell()->getCallData(callData);
198 }
199
200 inline ConstructType JSValue::getConstructData(ConstructData& constructData)
201 {
202     return JSImmediate::isImmediate(this) ? ConstructTypeNone : asCell()->getConstructData(constructData);
203 }
204
205 ALWAYS_INLINE bool JSValue::getUInt32(uint32_t& v) const
206 {
207     return JSImmediate::isImmediate(this) ? JSImmediate::getUInt32(this, v) : asCell()->getUInt32(v);
208 }
209
210 ALWAYS_INLINE bool JSValue::getTruncatedInt32(int32_t& v) const
211 {
212     return JSImmediate::isImmediate(this) ? JSImmediate::getTruncatedInt32(this, v) : asCell()->getTruncatedInt32(v);
213 }
214
215 inline bool JSValue::getTruncatedUInt32(uint32_t& v) const
216 {
217     return JSImmediate::isImmediate(this) ? JSImmediate::getTruncatedUInt32(this, v) : asCell()->getTruncatedUInt32(v);
218 }
219
220 inline void JSValue::mark()
221 {
222     ASSERT(!JSImmediate::isImmediate(this)); // callers should check !marked() before calling mark()
223     asCell()->mark();
224 }
225
226 inline bool JSValue::marked() const
227 {
228     return JSImmediate::isImmediate(this) || asCell()->marked();
229 }
230
231 inline JSType JSValue::type() const
232 {
233     return JSImmediate::isImmediate(this) ? JSImmediate::type(this) : asCell()->type();
234 }
235
236 inline JSValue* JSValue::toPrimitive(ExecState* exec, JSType preferredType) const
237 {
238     return JSImmediate::isImmediate(this) ? const_cast<JSValue*>(this) : asCell()->toPrimitive(exec, preferredType);
239 }
240
241 inline bool JSValue::getPrimitiveNumber(ExecState* exec, double& number, JSValue*& value)
242 {
243     if (JSImmediate::isImmediate(this)) {
244         number = JSImmediate::toDouble(this);
245         value = this;
246         return true;
247     }
248     return asCell()->getPrimitiveNumber(exec, number, value);
249 }
250
251 inline bool JSValue::toBoolean(ExecState *exec) const
252 {
253     return JSImmediate::isImmediate(this) ? JSImmediate::toBoolean(this) : asCell()->toBoolean(exec);
254 }
255
256 ALWAYS_INLINE double JSValue::toNumber(ExecState *exec) const
257 {
258     return JSImmediate::isImmediate(this) ? JSImmediate::toDouble(this) : asCell()->toNumber(exec);
259 }
260
261 inline UString JSValue::toString(ExecState *exec) const
262 {
263     return JSImmediate::isImmediate(this) ? JSImmediate::toString(this) : asCell()->toString(exec);
264 }
265
266 inline JSObject* JSValue::toObject(ExecState* exec) const
267 {
268     return JSImmediate::isImmediate(this) ? JSImmediate::toObject(this, exec) : asCell()->toObject(exec);
269 }
270
271 inline JSObject* JSValue::toThisObject(ExecState* exec) const
272 {
273     if (UNLIKELY(JSImmediate::isImmediate(this)))
274         return JSImmediate::toObject(this, exec);
275     return asCell()->toThisObject(exec);
276 }
277
278 inline UString JSValue::toThisString(ExecState* exec) const
279 {
280     return JSImmediate::isImmediate(this) ? JSImmediate::toString(this) : asCell()->toThisString(exec);
281 }
282
283 inline JSValue* JSValue::getJSNumber()
284 {
285
286     return JSImmediate::isNumber(this) ? this : (JSImmediate::isImmediate(this) ? 0 : asCell()->getJSNumber());
287 }
288
289 } // namespace KJS
290
291 #endif // JSCell_h