2 * Copyright (C) 2005, 2007, 2008, 2015-2016 Apple Inc. All rights reserved.
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.
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.
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.
21 #ifndef PropertySlot_h
22 #define PropertySlot_h
24 #include "JSCJSValue.h"
25 #include "PropertyName.h"
26 #include "PropertyOffset.h"
27 #include <wtf/Assertions.h>
36 // Property attributes
39 ReadOnly = 1 << 1, // property can be only read, not written
40 DontEnum = 1 << 2, // property doesn't appear in (for .. in ..)
41 DontDelete = 1 << 3, // property can't be deleted
42 Accessor = 1 << 4, // property is a getter/setter
43 CustomAccessor = 1 << 5,
45 // Things that are used by static hashtables are not in the attributes byte in PropertyMapEntry.
46 Function = 1 << 8, // property is a function - only used by static hashtables
47 Builtin = 1 << 9, // property is a builtin function - only used by static hashtables
48 ConstantInteger = 1 << 10, // property is a constant integer - only used by static hashtables
49 CellProperty = 1 << 11, // property is a lazy property - only used by static hashtables
50 ClassStructure = 1 << 12, // property is a lazy class structure - only used by static hashtables
51 PropertyCallback = 1 << 13, // property that is a lazy property callback - only used by static hashtables
52 BuiltinOrFunction = Builtin | Function, // helper only used by static hashtables
53 BuiltinOrFunctionOrLazyProperty = Builtin | Function | CellProperty | ClassStructure | PropertyCallback, // helper only used by static hashtables
54 BuiltinOrFunctionOrAccessorOrLazyProperty = Builtin | Function | Accessor | CellProperty | ClassStructure | PropertyCallback, // helper only used by static hashtables
55 BuiltinOrFunctionOrAccessorOrLazyPropertyOrConstant = Builtin | Function | Accessor | CellProperty | ClassStructure | PropertyCallback | ConstantInteger // helper only used by static hashtables
58 enum CacheabilityType : uint8_t {
63 inline unsigned attributesForStructure(unsigned attributes)
65 // The attributes that are used just for the static hashtable are at bit 8 and higher.
66 return static_cast<uint8_t>(attributes);
70 enum PropertyType : uint8_t {
78 enum class InternalMethodType : uint8_t {
79 Get, // [[Get]] internal method in the spec.
80 HasProperty, // [[HasProperty]] internal method in the spec.
81 GetOwnProperty, // [[GetOwnProperty]] internal method in the spec.
82 VMInquiry, // Our VM is just poking around. When this is the InternalMethodType, getOwnPropertySlot is not allowed to do user observable actions.
85 explicit PropertySlot(const JSValue thisValue, InternalMethodType internalMethodType)
86 : m_offset(invalidOffset)
87 , m_thisValue(thisValue)
89 , m_watchpointSet(nullptr)
90 , m_cacheability(CachingAllowed)
91 , m_propertyType(TypeUnset)
92 , m_internalMethodType(internalMethodType)
93 , m_isTaintedByProxy(false)
97 typedef EncodedJSValue (*GetValueFunc)(ExecState*, EncodedJSValue thisValue, PropertyName);
99 JSValue getValue(ExecState*, PropertyName) const;
100 JSValue getValue(ExecState*, unsigned propertyName) const;
101 JSValue getPureResult() const;
103 bool isCacheable() const { return m_cacheability == CachingAllowed && m_offset != invalidOffset; }
104 bool isUnset() const { return m_propertyType == TypeUnset; }
105 bool isValue() const { return m_propertyType == TypeValue; }
106 bool isAccessor() const { return m_propertyType == TypeGetter; }
107 bool isCustom() const { return m_propertyType == TypeCustom; }
108 bool isCacheableValue() const { return isCacheable() && isValue(); }
109 bool isCacheableGetter() const { return isCacheable() && isAccessor(); }
110 bool isCacheableCustom() const { return isCacheable() && isCustom(); }
111 void setIsTaintedByProxy() { m_isTaintedByProxy = true; }
112 bool isTaintedByProxy() const { return m_isTaintedByProxy; }
114 InternalMethodType internalMethodType() const { return m_internalMethodType; }
116 void disableCaching()
118 m_cacheability = CachingDisallowed;
121 unsigned attributes() const { return m_attributes; }
123 PropertyOffset cachedOffset() const
125 ASSERT(isCacheable());
129 GetterSetter* getterSetter() const
131 ASSERT(isAccessor());
132 return m_data.getter.getterSetter;
135 GetValueFunc customGetter() const
137 ASSERT(isCacheableCustom());
138 return m_data.custom.getValue;
141 JSObject* slotBase() const
146 WatchpointSet* watchpointSet() const
148 return m_watchpointSet;
151 void setValue(JSObject* slotBase, unsigned attributes, JSValue value)
153 ASSERT(attributes == attributesForStructure(attributes));
155 m_data.value = JSValue::encode(value);
156 m_attributes = attributes;
159 m_slotBase = slotBase;
160 m_propertyType = TypeValue;
161 m_offset = invalidOffset;
164 void setValue(JSObject* slotBase, unsigned attributes, JSValue value, PropertyOffset offset)
166 ASSERT(attributes == attributesForStructure(attributes));
169 m_data.value = JSValue::encode(value);
170 m_attributes = attributes;
173 m_slotBase = slotBase;
174 m_propertyType = TypeValue;
178 void setValue(JSString*, unsigned attributes, JSValue value)
180 ASSERT(attributes == attributesForStructure(attributes));
183 m_data.value = JSValue::encode(value);
184 m_attributes = attributes;
187 m_propertyType = TypeValue;
188 m_offset = invalidOffset;
191 void setCustom(JSObject* slotBase, unsigned attributes, GetValueFunc getValue)
193 ASSERT(attributes == attributesForStructure(attributes));
196 m_data.custom.getValue = getValue;
197 m_attributes = attributes;
200 m_slotBase = slotBase;
201 m_propertyType = TypeCustom;
202 m_offset = invalidOffset;
205 void setCacheableCustom(JSObject* slotBase, unsigned attributes, GetValueFunc getValue)
207 ASSERT(attributes == attributesForStructure(attributes));
210 m_data.custom.getValue = getValue;
211 m_attributes = attributes;
214 m_slotBase = slotBase;
215 m_propertyType = TypeCustom;
216 m_offset = !invalidOffset;
219 void setGetterSlot(JSObject* slotBase, unsigned attributes, GetterSetter* getterSetter)
221 ASSERT(attributes == attributesForStructure(attributes));
223 ASSERT(getterSetter);
224 m_data.getter.getterSetter = getterSetter;
225 m_attributes = attributes;
228 m_slotBase = slotBase;
229 m_propertyType = TypeGetter;
230 m_offset = invalidOffset;
233 void setCacheableGetterSlot(JSObject* slotBase, unsigned attributes, GetterSetter* getterSetter, PropertyOffset offset)
235 ASSERT(attributes == attributesForStructure(attributes));
237 ASSERT(getterSetter);
238 m_data.getter.getterSetter = getterSetter;
239 m_attributes = attributes;
242 m_slotBase = slotBase;
243 m_propertyType = TypeGetter;
247 void setThisValue(JSValue thisValue)
249 m_thisValue = thisValue;
254 m_data.value = JSValue::encode(jsUndefined());
255 m_attributes = ReadOnly | DontDelete | DontEnum;
258 m_propertyType = TypeValue;
259 m_offset = invalidOffset;
262 void setWatchpointSet(WatchpointSet& set)
264 m_watchpointSet = &set;
268 JS_EXPORT_PRIVATE JSValue functionGetter(ExecState*) const;
269 JS_EXPORT_PRIVATE JSValue customGetter(ExecState*, PropertyName) const;
271 unsigned m_attributes;
273 EncodedJSValue value;
275 GetterSetter* getterSetter;
278 GetValueFunc getValue;
282 PropertyOffset m_offset;
284 JSObject* m_slotBase;
285 WatchpointSet* m_watchpointSet;
286 CacheabilityType m_cacheability;
287 PropertyType m_propertyType;
288 InternalMethodType m_internalMethodType;
289 bool m_isTaintedByProxy;
292 ALWAYS_INLINE JSValue PropertySlot::getValue(ExecState* exec, PropertyName propertyName) const
294 if (m_propertyType == TypeValue)
295 return JSValue::decode(m_data.value);
296 if (m_propertyType == TypeGetter)
297 return functionGetter(exec);
298 return customGetter(exec, propertyName);
301 ALWAYS_INLINE JSValue PropertySlot::getValue(ExecState* exec, unsigned propertyName) const
303 if (m_propertyType == TypeValue)
304 return JSValue::decode(m_data.value);
305 if (m_propertyType == TypeGetter)
306 return functionGetter(exec);
307 return customGetter(exec, Identifier::from(exec, propertyName));
312 #endif // PropertySlot_h