[SM91] Update to Spidermonkey 91.1.3 APIs
[0ad.git] / libraries / source / spidermonkey / include-win32-debug / js / PropertyDescriptor.h
blob676b4d1a775247b6e323df263b463321f5f4c98d
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 /* Property descriptors and flags. */
8 #ifndef js_PropertyDescriptor_h
9 #define js_PropertyDescriptor_h
11 #include "mozilla/Assertions.h" // MOZ_ASSERT, MOZ_ASSERT_IF
12 #include "mozilla/EnumSet.h" // mozilla::EnumSet
13 #include "mozilla/Maybe.h" // mozilla::Maybe
15 #include <stdint.h> // uint8_t
17 #include "jstypes.h" // JS_PUBLIC_API
19 #include "js/Class.h" // JS{Getter,Setter}Op
20 #include "js/RootingAPI.h" // JS::Handle, js::{,Mutable}WrappedPtrOperations
21 #include "js/Value.h" // JS::Value
23 struct JS_PUBLIC_API JSContext;
24 class JS_PUBLIC_API JSObject;
25 class JS_PUBLIC_API JSTracer;
27 /* Property attributes, set in JSPropertySpec and passed to API functions.
29 * The data structure in which some of these values are stored only uses a
30 * uint8_t to store the relevant information. Proceed with caution if trying to
31 * reorder or change the the first byte worth of flags.
34 /** The property is visible in for/in loops. */
35 static constexpr uint8_t JSPROP_ENUMERATE = 0x01;
37 /**
38 * The property is non-writable. This flag is only valid for data properties.
40 static constexpr uint8_t JSPROP_READONLY = 0x02;
42 /**
43 * The property is non-configurable: it can't be deleted, and if it's an
44 * accessor descriptor, its getter and setter can't be changed.
46 static constexpr uint8_t JSPROP_PERMANENT = 0x04;
48 /**
49 * Resolve hooks and enumerate hooks must pass this flag when calling
50 * JS_Define* APIs to reify lazily-defined properties.
52 * JSPROP_RESOLVING is used only with property-defining APIs. It tells the
53 * engine to skip the resolve hook when performing the lookup at the beginning
54 * of property definition. This keeps the resolve hook from accidentally
55 * triggering itself: unchecked recursion.
57 * For enumerate hooks, triggering the resolve hook would be merely silly, not
58 * fatal, except in some cases involving non-configurable properties.
60 static constexpr unsigned JSPROP_RESOLVING = 0x08;
62 /* (higher flags are unused; add to JSPROP_FLAGS_MASK if ever defined) */
64 static constexpr unsigned JSPROP_FLAGS_MASK =
65 JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT | JSPROP_RESOLVING;
67 namespace JS {
69 // 6.1.7.1 Property Attributes
70 enum class PropertyAttribute : uint8_t {
71 // The descriptor is [[Configurable]] := true.
72 Configurable,
74 // The descriptor is [[Enumerable]] := true.
75 Enumerable,
77 // The descriptor is [[Writable]] := true. Only valid for data descriptors.
78 Writable
81 class PropertyAttributes : public mozilla::EnumSet<PropertyAttribute> {
82 // Re-use all EnumSet constructors.
83 using mozilla::EnumSet<PropertyAttribute>::EnumSet;
85 public:
86 bool configurable() const {
87 return contains(PropertyAttribute::Configurable);
89 bool enumerable() const { return contains(PropertyAttribute::Enumerable); }
90 bool writable() const { return contains(PropertyAttribute::Writable); }
93 /**
94 * A structure that represents a property on an object, or the absence of a
95 * property. Use {,Mutable}Handle<PropertyDescriptor> to interact with
96 * instances of this structure rather than interacting directly with member
97 * fields.
99 class JS_PUBLIC_API PropertyDescriptor {
100 private:
101 bool hasConfigurable_ : 1;
102 bool configurable_ : 1;
104 bool hasEnumerable_ : 1;
105 bool enumerable_ : 1;
107 bool hasWritable_ : 1;
108 bool writable_ : 1;
110 bool hasValue_ : 1;
111 bool hasGetter_ : 1;
112 bool hasSetter_ : 1;
114 bool resolving_ : 1;
116 JSObject* getter_;
117 JSObject* setter_;
118 Value value_;
120 public:
121 PropertyDescriptor()
122 : hasConfigurable_(false),
123 configurable_(false),
124 hasEnumerable_(false),
125 enumerable_(false),
126 hasWritable_(false),
127 writable_(false),
128 hasValue_(false),
129 hasGetter_(false),
130 hasSetter_(false),
131 resolving_(false),
132 getter_(nullptr),
133 setter_(nullptr),
134 value_(UndefinedValue()) {}
136 void trace(JSTracer* trc);
138 // Construct a new complete DataDescriptor.
139 static PropertyDescriptor Data(const Value& value,
140 PropertyAttributes attributes = {}) {
141 PropertyDescriptor desc;
142 desc.setConfigurable(attributes.configurable());
143 desc.setEnumerable(attributes.enumerable());
144 desc.setWritable(attributes.writable());
145 desc.setValue(value);
146 desc.assertComplete();
147 return desc;
150 // This constructor is only provided for legacy code!
151 static PropertyDescriptor Data(const Value& value, unsigned attrs) {
152 MOZ_ASSERT((attrs & ~(JSPROP_PERMANENT | JSPROP_ENUMERATE |
153 JSPROP_READONLY | JSPROP_RESOLVING)) == 0);
155 PropertyDescriptor desc;
156 desc.setConfigurable(!(attrs & JSPROP_PERMANENT));
157 desc.setEnumerable(attrs & JSPROP_ENUMERATE);
158 desc.setWritable(!(attrs & JSPROP_READONLY));
159 desc.setValue(value);
160 desc.setResolving(attrs & JSPROP_RESOLVING);
161 desc.assertComplete();
162 return desc;
165 // Construct a new complete AccessorDescriptor.
166 // Note: This means JSPROP_GETTER and JSPROP_SETTER are always set.
167 static PropertyDescriptor Accessor(JSObject* getter, JSObject* setter,
168 PropertyAttributes attributes = {}) {
169 MOZ_ASSERT(!attributes.writable());
171 PropertyDescriptor desc;
172 desc.setConfigurable(attributes.configurable());
173 desc.setEnumerable(attributes.enumerable());
174 desc.setGetter(getter);
175 desc.setSetter(setter);
176 desc.assertComplete();
177 return desc;
180 // This constructor is only provided for legacy code!
181 static PropertyDescriptor Accessor(JSObject* getter, JSObject* setter,
182 unsigned attrs) {
183 MOZ_ASSERT((attrs & ~(JSPROP_PERMANENT | JSPROP_ENUMERATE |
184 JSPROP_RESOLVING)) == 0);
186 PropertyDescriptor desc;
187 desc.setConfigurable(!(attrs & JSPROP_PERMANENT));
188 desc.setEnumerable(attrs & JSPROP_ENUMERATE);
189 desc.setGetter(getter);
190 desc.setSetter(setter);
191 desc.setResolving(attrs & JSPROP_RESOLVING);
192 desc.assertComplete();
193 return desc;
196 static PropertyDescriptor Accessor(mozilla::Maybe<JSObject*> getter,
197 mozilla::Maybe<JSObject*> setter,
198 unsigned attrs) {
199 MOZ_ASSERT((attrs & ~(JSPROP_PERMANENT | JSPROP_ENUMERATE |
200 JSPROP_RESOLVING)) == 0);
202 PropertyDescriptor desc;
203 desc.setConfigurable(!(attrs & JSPROP_PERMANENT));
204 desc.setEnumerable(attrs & JSPROP_ENUMERATE);
205 if (getter) {
206 desc.setGetter(*getter);
208 if (setter) {
209 desc.setSetter(*setter);
211 desc.setResolving(attrs & JSPROP_RESOLVING);
212 desc.assertValid();
213 return desc;
216 // Construct a new incomplete empty PropertyDescriptor.
217 // Using the spec syntax this would be { }. Specific fields like [[Value]]
218 // can be added with e.g., setValue.
219 static PropertyDescriptor Empty() {
220 PropertyDescriptor desc;
221 desc.assertValid();
222 MOZ_ASSERT(!desc.hasConfigurable() && !desc.hasEnumerable() &&
223 !desc.hasWritable() && !desc.hasValue() && !desc.hasGetter() &&
224 !desc.hasSetter());
225 return desc;
228 public:
229 bool isAccessorDescriptor() const {
230 MOZ_ASSERT_IF(hasGetter_ || hasSetter_, !isDataDescriptor());
231 return hasGetter_ || hasSetter_;
233 bool isGenericDescriptor() const {
234 return !isAccessorDescriptor() && !isDataDescriptor();
236 bool isDataDescriptor() const {
237 MOZ_ASSERT_IF(hasWritable_ || hasValue_, !isAccessorDescriptor());
238 return hasWritable_ || hasValue_;
241 bool hasConfigurable() const { return hasConfigurable_; }
242 bool configurable() const {
243 MOZ_ASSERT(hasConfigurable());
244 return configurable_;
246 void setConfigurable(bool configurable) {
247 hasConfigurable_ = true;
248 configurable_ = configurable;
251 bool hasEnumerable() const { return hasEnumerable_; }
252 bool enumerable() const {
253 MOZ_ASSERT(hasEnumerable());
254 return enumerable_;
256 void setEnumerable(bool enumerable) {
257 hasEnumerable_ = true;
258 enumerable_ = enumerable;
261 bool hasValue() const { return hasValue_; }
262 Value value() const {
263 MOZ_ASSERT(hasValue());
264 return value_;
266 void setValue(const Value& v) {
267 MOZ_ASSERT(!isAccessorDescriptor());
268 hasValue_ = true;
269 value_ = v;
272 bool hasWritable() const { return hasWritable_; }
273 bool writable() const {
274 MOZ_ASSERT(hasWritable());
275 return writable_;
277 void setWritable(bool writable) {
278 MOZ_ASSERT(!isAccessorDescriptor());
279 hasWritable_ = true;
280 writable_ = writable;
283 bool hasGetter() const { return hasGetter_; }
284 JSObject* getter() const {
285 MOZ_ASSERT(hasGetter());
286 return getter_;
288 void setGetter(JSObject* obj) {
289 MOZ_ASSERT(!isDataDescriptor());
290 hasGetter_ = true;
291 getter_ = obj;
294 bool hasSetter() const { return hasSetter_; }
295 JSObject* setter() const {
296 MOZ_ASSERT(hasSetter());
297 return setter_;
299 void setSetter(JSObject* obj) {
300 MOZ_ASSERT(!isDataDescriptor());
301 hasSetter_ = true;
302 setter_ = obj;
305 // Non-standard flag, which is set when defining properties in a resolve hook.
306 bool resolving() const { return resolving_; }
307 void setResolving(bool resolving) { resolving_ = resolving; }
309 Value* valueDoNotUse() { return &value_; }
310 Value const* valueDoNotUse() const { return &value_; }
311 JSObject** getterDoNotUse() { return &getter_; }
312 JSObject* const* getterDoNotUse() const { return &getter_; }
313 void setGetterDoNotUse(JSObject* obj) { getter_ = obj; }
314 JSObject** setterDoNotUse() { return &setter_; }
315 JSObject* const* setterDoNotUse() const { return &setter_; }
316 void setSetterDoNotUse(JSObject* obj) { setter_ = obj; }
318 void assertValid() const {
319 #ifdef DEBUG
320 if (isAccessorDescriptor()) {
321 MOZ_ASSERT(!hasWritable_);
322 MOZ_ASSERT(!hasValue_);
323 } else {
324 MOZ_ASSERT(isGenericDescriptor() || isDataDescriptor());
325 MOZ_ASSERT(!hasGetter_);
326 MOZ_ASSERT(!hasSetter_);
329 MOZ_ASSERT_IF(!hasConfigurable_, !configurable_);
330 MOZ_ASSERT_IF(!hasEnumerable_, !enumerable_);
331 MOZ_ASSERT_IF(!hasWritable_, !writable_);
332 MOZ_ASSERT_IF(!hasValue_, value_.isUndefined());
333 MOZ_ASSERT_IF(!hasGetter_, !getter_);
334 MOZ_ASSERT_IF(!hasSetter_, !setter_);
336 MOZ_ASSERT_IF(resolving_, !isGenericDescriptor());
337 #endif
340 void assertComplete() const {
341 #ifdef DEBUG
342 assertValid();
343 MOZ_ASSERT(hasConfigurable());
344 MOZ_ASSERT(hasEnumerable());
345 MOZ_ASSERT(!isGenericDescriptor());
346 MOZ_ASSERT_IF(isDataDescriptor(), hasValue() && hasWritable());
347 MOZ_ASSERT_IF(isAccessorDescriptor(), hasGetter() && hasSetter());
348 #endif
352 } // namespace JS
354 namespace js {
356 template <typename Wrapper>
357 class WrappedPtrOperations<JS::PropertyDescriptor, Wrapper> {
358 const JS::PropertyDescriptor& desc() const {
359 return static_cast<const Wrapper*>(this)->get();
362 public:
363 bool isAccessorDescriptor() const { return desc().isAccessorDescriptor(); }
364 bool isGenericDescriptor() const { return desc().isGenericDescriptor(); }
365 bool isDataDescriptor() const { return desc().isDataDescriptor(); }
367 bool hasConfigurable() const { return desc().hasConfigurable(); }
368 bool configurable() const { return desc().configurable(); }
370 bool hasEnumerable() const { return desc().hasEnumerable(); }
371 bool enumerable() const { return desc().enumerable(); }
373 bool hasValue() const { return desc().hasValue(); }
374 JS::Handle<JS::Value> value() const {
375 MOZ_ASSERT(hasValue());
376 return JS::Handle<JS::Value>::fromMarkedLocation(desc().valueDoNotUse());
379 bool hasWritable() const { return desc().hasWritable(); }
380 bool writable() const { return desc().writable(); }
382 bool hasGetter() const { return desc().hasGetter(); }
383 JS::Handle<JSObject*> getter() const {
384 MOZ_ASSERT(hasGetter());
385 return JS::Handle<JSObject*>::fromMarkedLocation(desc().getterDoNotUse());
387 bool hasSetter() const { return desc().hasSetter(); }
388 JS::Handle<JSObject*> setter() const {
389 MOZ_ASSERT(hasSetter());
390 return JS::Handle<JSObject*>::fromMarkedLocation(desc().setterDoNotUse());
393 bool resolving() const { return desc().resolving(); }
395 void assertValid() const { desc().assertValid(); }
396 void assertComplete() const { desc().assertComplete(); }
399 template <typename Wrapper>
400 class MutableWrappedPtrOperations<JS::PropertyDescriptor, Wrapper>
401 : public js::WrappedPtrOperations<JS::PropertyDescriptor, Wrapper> {
402 JS::PropertyDescriptor& desc() { return static_cast<Wrapper*>(this)->get(); }
404 public:
405 JS::MutableHandle<JS::Value> value() {
406 MOZ_ASSERT(desc().hasValue());
407 return JS::MutableHandle<JS::Value>::fromMarkedLocation(
408 desc().valueDoNotUse());
410 void setValue(JS::Handle<JS::Value> v) { desc().setValue(v); }
412 void setConfigurable(bool configurable) {
413 desc().setConfigurable(configurable);
415 void setEnumerable(bool enumerable) { desc().setEnumerable(enumerable); }
416 void setWritable(bool writable) { desc().setWritable(writable); }
418 void setGetter(JSObject* obj) { desc().setGetter(obj); }
419 void setSetter(JSObject* obj) { desc().setSetter(obj); }
421 JS::MutableHandle<JSObject*> getter() {
422 MOZ_ASSERT(desc().hasGetter());
423 return JS::MutableHandle<JSObject*>::fromMarkedLocation(
424 desc().getterDoNotUse());
426 JS::MutableHandle<JSObject*> setter() {
427 MOZ_ASSERT(desc().hasSetter());
428 return JS::MutableHandle<JSObject*>::fromMarkedLocation(
429 desc().setterDoNotUse());
432 void setResolving(bool resolving) { desc().setResolving(resolving); }
435 } // namespace js
437 namespace JS {
439 extern JS_PUBLIC_API bool ObjectToCompletePropertyDescriptor(
440 JSContext* cx, Handle<JSObject*> obj, Handle<Value> descriptor,
441 MutableHandle<PropertyDescriptor> desc);
444 * ES6 draft rev 32 (2015 Feb 2) 6.2.4.4 FromPropertyDescriptor(Desc).
446 * If desc.isNothing(), then vp is set to undefined.
448 extern JS_PUBLIC_API bool FromPropertyDescriptor(
449 JSContext* cx, Handle<mozilla::Maybe<PropertyDescriptor>> desc,
450 MutableHandle<Value> vp);
452 } // namespace JS
454 #endif /* js_PropertyDescriptor_h */