Differential D3143 Diff 14286 ps/trunk/libraries/source/spidermonkey/include-win32-debug/js/PropertyDescriptor.h
Changeset View
Changeset View
Standalone View
Standalone View
ps/trunk/libraries/source/spidermonkey/include-win32-debug/js/PropertyDescriptor.h
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ | |||||
/* This Source Code Form is subject to the terms of the Mozilla Public | |||||
* License, v. 2.0. If a copy of the MPL was not distributed with this | |||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ | |||||
/* Property descriptors and flags. */ | |||||
#ifndef js_PropertyDescriptor_h | |||||
#define js_PropertyDescriptor_h | |||||
#include "mozilla/Assertions.h" // MOZ_ASSERT, MOZ_ASSERT_IF | |||||
#include <stdint.h> // uint8_t | |||||
#include "jstypes.h" // JS_PUBLIC_API | |||||
#include "js/Class.h" // JS{Getter,Setter}Op | |||||
#include "js/RootingAPI.h" // JS::Handle, js::{,Mutable}WrappedPtrOperations | |||||
#include "js/Value.h" // JS::Value | |||||
struct JS_PUBLIC_API JSContext; | |||||
class JS_PUBLIC_API JSObject; | |||||
class JS_PUBLIC_API JSTracer; | |||||
/* Property attributes, set in JSPropertySpec and passed to API functions. | |||||
* | |||||
* The data structure in which some of these values are stored only uses a | |||||
* uint8_t to store the relevant information. Proceed with caution if trying to | |||||
* reorder or change the the first byte worth of flags. | |||||
*/ | |||||
/** The property is visible in for/in loops. */ | |||||
static constexpr uint8_t JSPROP_ENUMERATE = 0x01; | |||||
/** | |||||
* The property is non-writable. This flag is only valid when neither | |||||
* JSPROP_GETTER nor JSPROP_SETTER is set. | |||||
*/ | |||||
static constexpr uint8_t JSPROP_READONLY = 0x02; | |||||
/** | |||||
* The property is non-configurable: it can't be deleted, and if it's an | |||||
* accessor descriptor, its getter and setter can't be changed. | |||||
*/ | |||||
static constexpr uint8_t JSPROP_PERMANENT = 0x04; | |||||
/* (0x08 is unused; add to JSPROP_FLAGS_MASK if ever defined) */ | |||||
/** The property has a getter function. */ | |||||
static constexpr uint8_t JSPROP_GETTER = 0x10; | |||||
/** The property has a setter function. */ | |||||
static constexpr uint8_t JSPROP_SETTER = 0x20; | |||||
/* (0x40 is unused; add to JSPROP_FLAGS_MASK if ever defined) */ | |||||
/** A bit for internal JS engine use only. */ | |||||
static constexpr uint8_t JSPROP_INTERNAL_USE_BIT = 0x80; | |||||
/* (0x1000 is unused; add to JSPROP_FLAGS_MASK if ever defined) */ | |||||
/** | |||||
* Resolve hooks and enumerate hooks must pass this flag when calling | |||||
* JS_Define* APIs to reify lazily-defined properties. | |||||
* | |||||
* JSPROP_RESOLVING is used only with property-defining APIs. It tells the | |||||
* engine to skip the resolve hook when performing the lookup at the beginning | |||||
* of property definition. This keeps the resolve hook from accidentally | |||||
* triggering itself: unchecked recursion. | |||||
* | |||||
* For enumerate hooks, triggering the resolve hook would be merely silly, not | |||||
* fatal, except in some cases involving non-configurable properties. | |||||
*/ | |||||
static constexpr unsigned JSPROP_RESOLVING = 0x2000; | |||||
/** | |||||
* When redefining an existing property, ignore the value of the | |||||
* JSPROP_ENUMERATE flag. This flag is ignored in other situations. | |||||
*/ | |||||
static constexpr unsigned JSPROP_IGNORE_ENUMERATE = 0x4000; | |||||
/** | |||||
* When redefining an existing property, ignore the value of the JSPROP_READONLY | |||||
* flag. This flag is ignored in other situations. | |||||
*/ | |||||
static constexpr unsigned JSPROP_IGNORE_READONLY = 0x8000; | |||||
/** | |||||
* When redefining an existing property, ignore the value of the | |||||
* JSPROP_PERMANENT flag. This flag is ignored in other situations. | |||||
*/ | |||||
static constexpr unsigned JSPROP_IGNORE_PERMANENT = 0x10000; | |||||
/** | |||||
* When redefining an existing property, ignore the Value in the descriptor. | |||||
* This flag is ignored in other situations. | |||||
*/ | |||||
static constexpr unsigned JSPROP_IGNORE_VALUE = 0x20000; | |||||
/* (higher flags are unused; add to JSPROP_FLAGS_MASK if ever defined) */ | |||||
static constexpr unsigned JSPROP_FLAGS_MASK = | |||||
JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT | JSPROP_GETTER | | |||||
JSPROP_SETTER | JSPROP_INTERNAL_USE_BIT | JSPROP_RESOLVING | | |||||
JSPROP_IGNORE_ENUMERATE | JSPROP_IGNORE_READONLY | JSPROP_IGNORE_PERMANENT | | |||||
JSPROP_IGNORE_VALUE; | |||||
namespace JS { | |||||
/** | |||||
* A structure that represents a property on an object, or the absence of a | |||||
* property. Use {,Mutable}Handle<PropertyDescriptor> to interact with | |||||
* instances of this structure rather than interacting directly with member | |||||
* fields. | |||||
*/ | |||||
struct JS_PUBLIC_API PropertyDescriptor { | |||||
JSObject* obj = nullptr; | |||||
unsigned attrs = 0; | |||||
JSGetterOp getter = nullptr; | |||||
JSSetterOp setter = nullptr; | |||||
Value value; | |||||
PropertyDescriptor() = default; | |||||
static void trace(PropertyDescriptor* self, JSTracer* trc) { | |||||
self->trace(trc); | |||||
} | |||||
void trace(JSTracer* trc); | |||||
}; | |||||
} // namespace JS | |||||
namespace js { | |||||
template <typename Wrapper> | |||||
class WrappedPtrOperations<JS::PropertyDescriptor, Wrapper> { | |||||
const JS::PropertyDescriptor& desc() const { | |||||
return static_cast<const Wrapper*>(this)->get(); | |||||
} | |||||
bool has(unsigned bit) const { | |||||
MOZ_ASSERT(bit != 0); | |||||
MOZ_ASSERT((bit & (bit - 1)) == 0); // only a single bit | |||||
return (desc().attrs & bit) != 0; | |||||
} | |||||
bool hasAny(unsigned bits) const { return (desc().attrs & bits) != 0; } | |||||
bool hasAll(unsigned bits) const { return (desc().attrs & bits) == bits; } | |||||
public: | |||||
// Descriptors with JSGetterOp/JSSetterOp are considered data | |||||
// descriptors. It's complicated. | |||||
bool isAccessorDescriptor() const { | |||||
return hasAny(JSPROP_GETTER | JSPROP_SETTER); | |||||
} | |||||
bool isGenericDescriptor() const { | |||||
return (desc().attrs & (JSPROP_GETTER | JSPROP_SETTER | | |||||
JSPROP_IGNORE_READONLY | JSPROP_IGNORE_VALUE)) == | |||||
(JSPROP_IGNORE_READONLY | JSPROP_IGNORE_VALUE); | |||||
} | |||||
bool isDataDescriptor() const { | |||||
return !isAccessorDescriptor() && !isGenericDescriptor(); | |||||
} | |||||
bool hasConfigurable() const { return !has(JSPROP_IGNORE_PERMANENT); } | |||||
bool configurable() const { | |||||
MOZ_ASSERT(hasConfigurable()); | |||||
return !has(JSPROP_PERMANENT); | |||||
} | |||||
bool hasEnumerable() const { return !has(JSPROP_IGNORE_ENUMERATE); } | |||||
bool enumerable() const { | |||||
MOZ_ASSERT(hasEnumerable()); | |||||
return has(JSPROP_ENUMERATE); | |||||
} | |||||
bool hasValue() const { | |||||
return !isAccessorDescriptor() && !has(JSPROP_IGNORE_VALUE); | |||||
} | |||||
JS::HandleValue value() const { | |||||
return JS::Handle<JS::Value>::fromMarkedLocation(&desc().value); | |||||
} | |||||
bool hasWritable() const { | |||||
return !isAccessorDescriptor() && !has(JSPROP_IGNORE_READONLY); | |||||
} | |||||
bool writable() const { | |||||
MOZ_ASSERT(hasWritable()); | |||||
return !has(JSPROP_READONLY); | |||||
} | |||||
bool hasGetterObject() const { return has(JSPROP_GETTER); } | |||||
JS::Handle<JSObject*> getterObject() const { | |||||
MOZ_ASSERT(hasGetterObject()); | |||||
return JS::Handle<JSObject*>::fromMarkedLocation( | |||||
reinterpret_cast<JSObject* const*>(&desc().getter)); | |||||
} | |||||
bool hasSetterObject() const { return has(JSPROP_SETTER); } | |||||
JS::Handle<JSObject*> setterObject() const { | |||||
MOZ_ASSERT(hasSetterObject()); | |||||
return JS::Handle<JSObject*>::fromMarkedLocation( | |||||
reinterpret_cast<JSObject* const*>(&desc().setter)); | |||||
} | |||||
bool hasGetterOrSetter() const { return desc().getter || desc().setter; } | |||||
JS::Handle<JSObject*> object() const { | |||||
return JS::Handle<JSObject*>::fromMarkedLocation(&desc().obj); | |||||
} | |||||
unsigned attributes() const { return desc().attrs; } | |||||
JSGetterOp getter() const { return desc().getter; } | |||||
JSSetterOp setter() const { return desc().setter; } | |||||
void assertValid() const { | |||||
#ifdef DEBUG | |||||
MOZ_ASSERT( | |||||
(attributes() & | |||||
~(JSPROP_ENUMERATE | JSPROP_IGNORE_ENUMERATE | JSPROP_PERMANENT | | |||||
JSPROP_IGNORE_PERMANENT | JSPROP_READONLY | JSPROP_IGNORE_READONLY | | |||||
JSPROP_IGNORE_VALUE | JSPROP_GETTER | JSPROP_SETTER | | |||||
JSPROP_RESOLVING | JSPROP_INTERNAL_USE_BIT)) == 0); | |||||
MOZ_ASSERT(!hasAll(JSPROP_IGNORE_ENUMERATE | JSPROP_ENUMERATE)); | |||||
MOZ_ASSERT(!hasAll(JSPROP_IGNORE_PERMANENT | JSPROP_PERMANENT)); | |||||
if (isAccessorDescriptor()) { | |||||
MOZ_ASSERT(!has(JSPROP_READONLY)); | |||||
MOZ_ASSERT(!has(JSPROP_IGNORE_READONLY)); | |||||
MOZ_ASSERT(!has(JSPROP_IGNORE_VALUE)); | |||||
MOZ_ASSERT(!has(JSPROP_INTERNAL_USE_BIT)); | |||||
MOZ_ASSERT(value().isUndefined()); | |||||
MOZ_ASSERT_IF(!has(JSPROP_GETTER), !getter()); | |||||
MOZ_ASSERT_IF(!has(JSPROP_SETTER), !setter()); | |||||
} else { | |||||
MOZ_ASSERT(!hasAll(JSPROP_IGNORE_READONLY | JSPROP_READONLY)); | |||||
MOZ_ASSERT_IF(has(JSPROP_IGNORE_VALUE), value().isUndefined()); | |||||
} | |||||
MOZ_ASSERT_IF(has(JSPROP_RESOLVING), !has(JSPROP_IGNORE_ENUMERATE)); | |||||
MOZ_ASSERT_IF(has(JSPROP_RESOLVING), !has(JSPROP_IGNORE_PERMANENT)); | |||||
MOZ_ASSERT_IF(has(JSPROP_RESOLVING), !has(JSPROP_IGNORE_READONLY)); | |||||
MOZ_ASSERT_IF(has(JSPROP_RESOLVING), !has(JSPROP_IGNORE_VALUE)); | |||||
#endif | |||||
} | |||||
void assertComplete() const { | |||||
#ifdef DEBUG | |||||
assertValid(); | |||||
MOZ_ASSERT( | |||||
(attributes() & ~(JSPROP_ENUMERATE | JSPROP_PERMANENT | | |||||
JSPROP_READONLY | JSPROP_GETTER | JSPROP_SETTER | | |||||
JSPROP_RESOLVING | JSPROP_INTERNAL_USE_BIT)) == 0); | |||||
MOZ_ASSERT_IF(isAccessorDescriptor(), | |||||
has(JSPROP_GETTER) && has(JSPROP_SETTER)); | |||||
#endif | |||||
} | |||||
void assertCompleteIfFound() const { | |||||
#ifdef DEBUG | |||||
if (object()) { | |||||
assertComplete(); | |||||
} | |||||
#endif | |||||
} | |||||
}; | |||||
template <typename Wrapper> | |||||
class MutableWrappedPtrOperations<JS::PropertyDescriptor, Wrapper> | |||||
: public js::WrappedPtrOperations<JS::PropertyDescriptor, Wrapper> { | |||||
JS::PropertyDescriptor& desc() { return static_cast<Wrapper*>(this)->get(); } | |||||
public: | |||||
void clear() { | |||||
object().set(nullptr); | |||||
setAttributes(0); | |||||
setGetter(nullptr); | |||||
setSetter(nullptr); | |||||
value().setUndefined(); | |||||
} | |||||
void initFields(JS::Handle<JSObject*> obj, JS::Handle<JS::Value> v, | |||||
unsigned attrs, JSGetterOp getterOp, JSSetterOp setterOp) { | |||||
object().set(obj); | |||||
value().set(v); | |||||
setAttributes(attrs); | |||||
setGetter(getterOp); | |||||
setSetter(setterOp); | |||||
} | |||||
void assign(JS::PropertyDescriptor& other) { | |||||
object().set(other.obj); | |||||
setAttributes(other.attrs); | |||||
setGetter(other.getter); | |||||
setSetter(other.setter); | |||||
value().set(other.value); | |||||
} | |||||
void setDataDescriptor(JS::Handle<JS::Value> v, unsigned attrs) { | |||||
MOZ_ASSERT((attrs & ~(JSPROP_ENUMERATE | JSPROP_PERMANENT | | |||||
JSPROP_READONLY | JSPROP_IGNORE_ENUMERATE | | |||||
JSPROP_IGNORE_PERMANENT | JSPROP_IGNORE_READONLY)) == | |||||
0); | |||||
object().set(nullptr); | |||||
setAttributes(attrs); | |||||
setGetter(nullptr); | |||||
setSetter(nullptr); | |||||
value().set(v); | |||||
} | |||||
JS::MutableHandle<JSObject*> object() { | |||||
return JS::MutableHandle<JSObject*>::fromMarkedLocation(&desc().obj); | |||||
} | |||||
unsigned& attributesRef() { return desc().attrs; } | |||||
JSGetterOp& getter() { return desc().getter; } | |||||
JSSetterOp& setter() { return desc().setter; } | |||||
JS::MutableHandle<JS::Value> value() { | |||||
return JS::MutableHandle<JS::Value>::fromMarkedLocation(&desc().value); | |||||
} | |||||
void setValue(JS::Handle<JS::Value> v) { | |||||
MOZ_ASSERT(!(desc().attrs & (JSPROP_GETTER | JSPROP_SETTER))); | |||||
attributesRef() &= ~JSPROP_IGNORE_VALUE; | |||||
value().set(v); | |||||
} | |||||
void setConfigurable(bool configurable) { | |||||
setAttributes( | |||||
(desc().attrs & ~(JSPROP_IGNORE_PERMANENT | JSPROP_PERMANENT)) | | |||||
(configurable ? 0 : JSPROP_PERMANENT)); | |||||
} | |||||
void setEnumerable(bool enumerable) { | |||||
setAttributes( | |||||
(desc().attrs & ~(JSPROP_IGNORE_ENUMERATE | JSPROP_ENUMERATE)) | | |||||
(enumerable ? JSPROP_ENUMERATE : 0)); | |||||
} | |||||
void setWritable(bool writable) { | |||||
MOZ_ASSERT(!(desc().attrs & (JSPROP_GETTER | JSPROP_SETTER))); | |||||
setAttributes((desc().attrs & ~(JSPROP_IGNORE_READONLY | JSPROP_READONLY)) | | |||||
(writable ? 0 : JSPROP_READONLY)); | |||||
} | |||||
void setAttributes(unsigned attrs) { desc().attrs = attrs; } | |||||
void setGetter(JSGetterOp op) { desc().getter = op; } | |||||
void setSetter(JSSetterOp op) { desc().setter = op; } | |||||
void setGetterObject(JSObject* obj) { | |||||
desc().getter = reinterpret_cast<JSGetterOp>(obj); | |||||
desc().attrs &= | |||||
~(JSPROP_IGNORE_VALUE | JSPROP_IGNORE_READONLY | JSPROP_READONLY); | |||||
desc().attrs |= JSPROP_GETTER; | |||||
} | |||||
void setSetterObject(JSObject* obj) { | |||||
desc().setter = reinterpret_cast<JSSetterOp>(obj); | |||||
desc().attrs &= | |||||
~(JSPROP_IGNORE_VALUE | JSPROP_IGNORE_READONLY | JSPROP_READONLY); | |||||
desc().attrs |= JSPROP_SETTER; | |||||
} | |||||
JS::MutableHandle<JSObject*> getterObject() { | |||||
MOZ_ASSERT(this->hasGetterObject()); | |||||
return JS::MutableHandle<JSObject*>::fromMarkedLocation( | |||||
reinterpret_cast<JSObject**>(&desc().getter)); | |||||
} | |||||
JS::MutableHandle<JSObject*> setterObject() { | |||||
MOZ_ASSERT(this->hasSetterObject()); | |||||
return JS::MutableHandle<JSObject*>::fromMarkedLocation( | |||||
reinterpret_cast<JSObject**>(&desc().setter)); | |||||
} | |||||
}; | |||||
} // namespace js | |||||
namespace JS { | |||||
extern JS_PUBLIC_API bool ObjectToCompletePropertyDescriptor( | |||||
JSContext* cx, Handle<JSObject*> obj, Handle<Value> descriptor, | |||||
MutableHandle<PropertyDescriptor> desc); | |||||
/* | |||||
* ES6 draft rev 32 (2015 Feb 2) 6.2.4.4 FromPropertyDescriptor(Desc). | |||||
* | |||||
* If desc.object() is null, then vp is set to undefined. | |||||
*/ | |||||
extern JS_PUBLIC_API bool FromPropertyDescriptor( | |||||
JSContext* cx, Handle<PropertyDescriptor> desc, MutableHandle<Value> vp); | |||||
} // namespace JS | |||||
#endif /* js_PropertyDescriptor_h */ |
Wildfire Games · Phabricator