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 BuiltinOrFunctionOrAccessorOrLazyProperty = Builtin | Function | Accessor | CellProperty | ClassStructure | PropertyCallback, // helper only used by static hashtables
54 BuiltinOrFunctionOrAccessorOrLazyPropertyOrConstant = Builtin | Function | Accessor | CellProperty | ClassStructure | PropertyCallback | ConstantInteger // helper only used by static hashtables
57 enum CacheabilityType : uint8_t {
62 inline unsigned attributesForStructure(unsigned attributes)
64 // The attributes that are used just for the static hashtable are at bit 8 and higher.
65 return static_cast<uint8_t>(attributes);
69 enum PropertyType : uint8_t {
77 enum class InternalMethodType : uint8_t {
78 Get, // [[Get]] internal method in the spec.
79 HasProperty, // [[HasProperty]] internal method in the spec.
80 GetOwnProperty, // [[GetOwnProperty]] internal method in the spec.
81 VMInquiry, // Our VM is just poking around. When this is the InternalMethodType, getOwnPropertySlot is not allowed to do user observable actions.
84 explicit PropertySlot(const JSValue thisValue, InternalMethodType internalMethodType)
85 : m_offset(invalidOffset)
86 , m_thisValue(thisValue)
88 , m_watchpointSet(nullptr)
89 , m_cacheability(CachingAllowed)
90 , m_propertyType(TypeUnset)
91 , m_internalMethodType(internalMethodType)
92 , m_isTaintedByProxy(false)
96 typedef EncodedJSValue (*GetValueFunc)(ExecState*, EncodedJSValue thisValue, PropertyName);
98 JSValue getValue(ExecState*, PropertyName) const;
99 JSValue getValue(ExecState*, unsigned propertyName) const;
100 JSValue getPureResult() const;
102 bool isCacheable() const { return m_cacheability == CachingAllowed && m_offset != invalidOffset; }
103 bool isUnset() const { return m_propertyType == TypeUnset; }
104 bool isValue() const { return m_propertyType == TypeValue; }
105 bool isAccessor() const { return m_propertyType == TypeGetter; }
106 bool isCustom() const { return m_propertyType == TypeCustom; }
107 bool isCacheableValue() const { return isCacheable() && isValue(); }
108 bool isCacheableGetter() const { return isCacheable() && isAccessor(); }
109 bool isCacheableCustom() const { return isCacheable() && isCustom(); }
110 void setIsTaintedByProxy() { m_isTaintedByProxy = true; }
111 bool isTaintedByProxy() const { return m_isTaintedByProxy; }
113 InternalMethodType internalMethodType() const { return m_internalMethodType; }
115 void disableCaching()
117 m_cacheability = CachingDisallowed;
120 unsigned attributes() const { return m_attributes; }
122 PropertyOffset cachedOffset() const
124 ASSERT(isCacheable());
128 GetterSetter* getterSetter() const
130 ASSERT(isAccessor());
131 return m_data.getter.getterSetter;
134 GetValueFunc customGetter() const
136 ASSERT(isCacheableCustom());
137 return m_data.custom.getValue;
140 JSObject* slotBase() const
145 WatchpointSet* watchpointSet() const
147 return m_watchpointSet;
150 void setValue(JSObject* slotBase, unsigned attributes, JSValue value)
152 ASSERT(attributes == attributesForStructure(attributes));
154 m_data.value = JSValue::encode(value);
155 m_attributes = attributes;
158 m_slotBase = slotBase;
159 m_propertyType = TypeValue;
160 m_offset = invalidOffset;
163 void setValue(JSObject* slotBase, unsigned attributes, JSValue value, PropertyOffset offset)
165 ASSERT(attributes == attributesForStructure(attributes));
168 m_data.value = JSValue::encode(value);
169 m_attributes = attributes;
172 m_slotBase = slotBase;
173 m_propertyType = TypeValue;
177 void setValue(JSString*, unsigned attributes, JSValue value)
179 ASSERT(attributes == attributesForStructure(attributes));
182 m_data.value = JSValue::encode(value);
183 m_attributes = attributes;
186 m_propertyType = TypeValue;
187 m_offset = invalidOffset;
190 void setCustom(JSObject* slotBase, unsigned attributes, GetValueFunc getValue)
192 ASSERT(attributes == attributesForStructure(attributes));
195 m_data.custom.getValue = getValue;
196 m_attributes = attributes;
199 m_slotBase = slotBase;
200 m_propertyType = TypeCustom;
201 m_offset = invalidOffset;
204 void setCacheableCustom(JSObject* slotBase, unsigned attributes, GetValueFunc getValue)
206 ASSERT(attributes == attributesForStructure(attributes));
209 m_data.custom.getValue = getValue;
210 m_attributes = attributes;
213 m_slotBase = slotBase;
214 m_propertyType = TypeCustom;
215 m_offset = !invalidOffset;
218 void setGetterSlot(JSObject* slotBase, unsigned attributes, GetterSetter* getterSetter)
220 ASSERT(attributes == attributesForStructure(attributes));
222 ASSERT(getterSetter);
223 m_data.getter.getterSetter = getterSetter;
224 m_attributes = attributes;
227 m_slotBase = slotBase;
228 m_propertyType = TypeGetter;
229 m_offset = invalidOffset;
232 void setCacheableGetterSlot(JSObject* slotBase, unsigned attributes, GetterSetter* getterSetter, PropertyOffset offset)
234 ASSERT(attributes == attributesForStructure(attributes));
236 ASSERT(getterSetter);
237 m_data.getter.getterSetter = getterSetter;
238 m_attributes = attributes;
241 m_slotBase = slotBase;
242 m_propertyType = TypeGetter;
246 void setThisValue(JSValue thisValue)
248 m_thisValue = thisValue;
253 m_data.value = JSValue::encode(jsUndefined());
254 m_attributes = ReadOnly | DontDelete | DontEnum;
257 m_propertyType = TypeValue;
258 m_offset = invalidOffset;
261 void setWatchpointSet(WatchpointSet& set)
263 m_watchpointSet = &set;
267 JS_EXPORT_PRIVATE JSValue functionGetter(ExecState*) const;
268 JS_EXPORT_PRIVATE JSValue customGetter(ExecState*, PropertyName) const;
270 unsigned m_attributes;
272 EncodedJSValue value;
274 GetterSetter* getterSetter;
277 GetValueFunc getValue;
281 PropertyOffset m_offset;
283 JSObject* m_slotBase;
284 WatchpointSet* m_watchpointSet;
285 CacheabilityType m_cacheability;
286 PropertyType m_propertyType;
287 InternalMethodType m_internalMethodType;
288 bool m_isTaintedByProxy;
291 ALWAYS_INLINE JSValue PropertySlot::getValue(ExecState* exec, PropertyName propertyName) const
293 if (m_propertyType == TypeValue)
294 return JSValue::decode(m_data.value);
295 if (m_propertyType == TypeGetter)
296 return functionGetter(exec);
297 return customGetter(exec, propertyName);
300 ALWAYS_INLINE JSValue PropertySlot::getValue(ExecState* exec, unsigned propertyName) const
302 if (m_propertyType == TypeValue)
303 return JSValue::decode(m_data.value);
304 if (m_propertyType == TypeGetter)
305 return functionGetter(exec);
306 return customGetter(exec, Identifier::from(exec, propertyName));
311 #endif // PropertySlot_h