JavaScriptCore:
[WebKit-https.git] / JavaScriptCore / kjs / PropertySlot.h
1 /*
2  *  Copyright (C) 2005, 2007, 2008 Apple Inc. All rights reserved.
3  *
4  *  This library is free software; you can redistribute it and/or
5  *  modify it under the terms of the GNU Library General Public
6  *  License as published by the Free Software Foundation; either
7  *  version 2 of the License, or (at your option) any later version.
8  *
9  *  This library is distributed in the hope that it will be useful,
10  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  *  Library General Public License for more details.
13  *
14  *  You should have received a copy of the GNU Library General Public License
15  *  along with this library; see the file COPYING.LIB.  If not, write to
16  *  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17  *  Boston, MA 02110-1301, USA.
18  *
19  */
20
21 #ifndef PropertySlot_h
22 #define PropertySlot_h
23
24 #include "Register.h"
25 #include "JSValue.h"
26 #include "identifier.h"
27 #include <wtf/Assertions.h>
28 #include <wtf/NotFound.h>
29
30 namespace KJS {
31
32     class ExecState;
33     class JSObject;
34     struct HashEntry;
35
36 #define KJS_VALUE_SLOT_MARKER 0
37 #define KJS_REGISTER_SLOT_MARKER reinterpret_cast<GetValueFunc>(1)
38
39     class PropertySlot {
40     public:
41         PropertySlot()
42             : m_offset(WTF::notFound)
43         {
44             clearBase();
45             clearValue();
46         }
47
48         explicit PropertySlot(JSValue* base)
49             : m_slotBase(base)
50             , m_offset(WTF::notFound)
51         {
52             clearValue();
53         }
54
55         typedef JSValue* (*GetValueFunc)(ExecState*, const Identifier&, const PropertySlot&);
56
57         JSValue* getValue(ExecState* exec, const Identifier& propertyName) const
58         {
59             if (m_getValue == KJS_VALUE_SLOT_MARKER)
60                 return *m_data.valueSlot;
61             if (m_getValue == KJS_REGISTER_SLOT_MARKER)
62                 return (*m_data.registerSlot).jsValue(exec);
63             return m_getValue(exec, propertyName, *this);
64         }
65
66         JSValue* getValue(ExecState* exec, unsigned propertyName) const
67         {
68             if (m_getValue == KJS_VALUE_SLOT_MARKER)
69                 return *m_data.valueSlot;
70             if (m_getValue == KJS_REGISTER_SLOT_MARKER)
71                 return (*m_data.registerSlot).jsValue(exec);
72             return m_getValue(exec, Identifier::from(exec, propertyName), *this);
73         }
74
75         bool isCacheable() const { return m_offset != WTF::notFound; }
76         size_t cachedOffset() const
77         {
78             ASSERT(isCacheable());
79             return m_offset;
80         }
81
82         void putValue(JSValue* value)
83         { 
84             if (m_getValue == KJS_VALUE_SLOT_MARKER) {
85                 *m_data.valueSlot = value;
86                 return;
87             }
88             ASSERT(m_getValue == KJS_REGISTER_SLOT_MARKER);
89             *m_data.registerSlot = value;
90         }
91
92         void setValueSlot(JSValue** valueSlot) 
93         {
94             ASSERT(valueSlot);
95             m_getValue = KJS_VALUE_SLOT_MARKER;
96             clearBase();
97             m_data.valueSlot = valueSlot;
98         }
99         
100         void setValueSlot(JSValue* slotBase, JSValue** valueSlot)
101         {
102             ASSERT(valueSlot);
103             m_getValue = KJS_VALUE_SLOT_MARKER;
104             m_slotBase = slotBase;
105             m_data.valueSlot = valueSlot;
106         }
107         
108         void setValueSlot(JSValue* slotBase, JSValue** valueSlot, size_t offset)
109         {
110             ASSERT(valueSlot);
111             m_getValue = KJS_VALUE_SLOT_MARKER;
112             m_slotBase = slotBase;
113             m_data.valueSlot = valueSlot;
114             m_offset = offset;
115         }
116         
117         void setValue(JSValue* value)
118         {
119             ASSERT(value);
120             m_getValue = KJS_VALUE_SLOT_MARKER;
121             clearBase();
122             m_value = value;
123             m_data.valueSlot = &m_value;
124         }
125
126         void setRegisterSlot(Register* registerSlot)
127         {
128             ASSERT(registerSlot);
129             m_getValue = KJS_REGISTER_SLOT_MARKER;
130             clearBase();
131             m_data.registerSlot = registerSlot;
132         }
133
134         void setStaticEntry(JSValue* slotBase, const HashEntry* staticEntry, GetValueFunc getValue)
135         {
136             ASSERT(slotBase);
137             ASSERT(staticEntry);
138             ASSERT(getValue);
139             m_getValue = getValue;
140             m_slotBase = slotBase;
141             m_data.staticEntry = staticEntry;
142         }
143
144         void setCustom(JSValue* slotBase, GetValueFunc getValue)
145         {
146             ASSERT(slotBase);
147             ASSERT(getValue);
148             m_getValue = getValue;
149             m_slotBase = slotBase;
150         }
151
152         void setCustomIndex(JSValue* slotBase, unsigned index, GetValueFunc getValue)
153         {
154             ASSERT(slotBase);
155             ASSERT(getValue);
156             m_getValue = getValue;
157             m_slotBase = slotBase;
158             m_data.index = index;
159         }
160         
161         void setGetterSlot(JSObject* getterFunc)
162         {
163             ASSERT(getterFunc);
164             m_getValue = functionGetter;
165             m_data.getterFunc = getterFunc;
166         }
167         
168         void setUndefined()
169         {
170             clearBase();
171             setValue(jsUndefined());
172         }
173
174         JSValue* slotBase() const
175         {
176             ASSERT(m_slotBase);
177             return m_slotBase;
178         }
179
180         void setBase(JSValue* base)
181         {
182             ASSERT(m_slotBase);
183             ASSERT(base);
184             m_slotBase = base;
185         }
186
187         void clearBase()
188         {
189 #ifndef NDEBUG
190             m_slotBase = 0;
191 #endif
192         }
193
194         void clearValue()
195         {
196 #ifndef NDEBUG
197             m_value = 0;
198 #endif
199         }
200
201         const HashEntry* staticEntry() const { return m_data.staticEntry; }
202         unsigned index() const { return m_data.index; }
203
204     private:
205         static JSValue* functionGetter(ExecState*, const Identifier&, const PropertySlot&);
206
207         GetValueFunc m_getValue;
208         
209         JSValue* m_slotBase;
210         union {
211             JSObject* getterFunc;
212             JSValue** valueSlot;
213             Register* registerSlot;
214             const HashEntry* staticEntry;
215             unsigned index;
216         } m_data;
217
218         JSValue* m_value;
219
220         size_t m_offset;
221     };
222
223 } // namespace KJS
224
225 #endif // PropertySlot_h