]>
git.saurik.com Git - apple/javascriptcore.git/blob - runtime/PropertyDescriptor.cpp
2 * Copyright (C) 2009 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 #include "PropertyDescriptor.h"
31 #include "GetterSetter.h"
33 #include "JSCInlines.h"
36 unsigned PropertyDescriptor::defaultAttributes
= DontDelete
| DontEnum
| ReadOnly
;
38 bool PropertyDescriptor::writable() const
40 ASSERT(!isAccessorDescriptor());
41 return !(m_attributes
& ReadOnly
);
44 bool PropertyDescriptor::enumerable() const
46 return !(m_attributes
& DontEnum
);
49 bool PropertyDescriptor::configurable() const
51 return !(m_attributes
& DontDelete
);
54 bool PropertyDescriptor::isDataDescriptor() const
56 return m_value
|| (m_seenAttributes
& WritablePresent
);
59 bool PropertyDescriptor::isGenericDescriptor() const
61 return !isAccessorDescriptor() && !isDataDescriptor();
64 bool PropertyDescriptor::isAccessorDescriptor() const
66 return m_getter
|| m_setter
;
69 void PropertyDescriptor::setUndefined()
71 m_value
= jsUndefined();
72 m_attributes
= ReadOnly
| DontDelete
| DontEnum
;
75 JSValue
PropertyDescriptor::getter() const
77 ASSERT(isAccessorDescriptor());
81 JSValue
PropertyDescriptor::setter() const
83 ASSERT(isAccessorDescriptor());
87 JSObject
* PropertyDescriptor::getterObject() const
89 ASSERT(isAccessorDescriptor() && getterPresent());
90 return m_getter
.isObject() ? asObject(m_getter
) : 0;
93 JSObject
* PropertyDescriptor::setterObject() const
95 ASSERT(isAccessorDescriptor() && setterPresent());
96 return m_setter
.isObject() ? asObject(m_setter
) : 0;
99 void PropertyDescriptor::setDescriptor(JSValue value
, unsigned attributes
)
102 ASSERT(value
.isGetterSetter() == !!(attributes
& Accessor
));
104 m_attributes
= attributes
;
105 if (value
.isGetterSetter()) {
106 m_attributes
&= ~ReadOnly
; // FIXME: we should be able to ASSERT this!
108 GetterSetter
* accessor
= asGetterSetter(value
);
109 m_getter
= accessor
->getter() ? accessor
->getter() : jsUndefined();
110 m_setter
= accessor
->setter() ? accessor
->setter() : jsUndefined();
111 m_seenAttributes
= EnumerablePresent
| ConfigurablePresent
;
114 m_seenAttributes
= EnumerablePresent
| ConfigurablePresent
| WritablePresent
;
118 void PropertyDescriptor::setCustomDescriptor(unsigned attributes
)
120 m_attributes
= attributes
| Accessor
| CustomAccessor
;
121 m_attributes
&= ~ReadOnly
;
122 m_seenAttributes
= EnumerablePresent
| ConfigurablePresent
;
123 setGetter(jsUndefined());
124 setSetter(jsUndefined());
128 void PropertyDescriptor::setAccessorDescriptor(GetterSetter
* accessor
, unsigned attributes
)
130 ASSERT(attributes
& Accessor
);
131 attributes
&= ~ReadOnly
; // FIXME: we should be able to ASSERT this!
133 m_attributes
= attributes
;
134 m_getter
= accessor
->getter() ? accessor
->getter() : jsUndefined();
135 m_setter
= accessor
->setter() ? accessor
->setter() : jsUndefined();
136 m_seenAttributes
= EnumerablePresent
| ConfigurablePresent
;
139 void PropertyDescriptor::setWritable(bool writable
)
142 m_attributes
&= ~ReadOnly
;
144 m_attributes
|= ReadOnly
;
145 m_seenAttributes
|= WritablePresent
;
148 void PropertyDescriptor::setEnumerable(bool enumerable
)
151 m_attributes
&= ~DontEnum
;
153 m_attributes
|= DontEnum
;
154 m_seenAttributes
|= EnumerablePresent
;
157 void PropertyDescriptor::setConfigurable(bool configurable
)
160 m_attributes
&= ~DontDelete
;
162 m_attributes
|= DontDelete
;
163 m_seenAttributes
|= ConfigurablePresent
;
166 void PropertyDescriptor::setSetter(JSValue setter
)
169 m_attributes
|= Accessor
;
170 m_attributes
&= ~ReadOnly
;
173 void PropertyDescriptor::setGetter(JSValue getter
)
176 m_attributes
|= Accessor
;
177 m_attributes
&= ~ReadOnly
;
181 bool sameValue(ExecState
* exec
, JSValue a
, JSValue b
)
184 return JSValue::strictEqual(exec
, a
, b
);
187 double x
= a
.asNumber();
188 double y
= b
.asNumber();
190 return std::isnan(y
);
191 return bitwise_cast
<uint64_t>(x
) == bitwise_cast
<uint64_t>(y
);
194 bool PropertyDescriptor::equalTo(ExecState
* exec
, const PropertyDescriptor
& other
) const
196 if (other
.m_value
.isEmpty() != m_value
.isEmpty()
197 || other
.m_getter
.isEmpty() != m_getter
.isEmpty()
198 || other
.m_setter
.isEmpty() != m_setter
.isEmpty())
200 return (!m_value
|| sameValue(exec
, other
.m_value
, m_value
))
201 && (!m_getter
|| JSValue::strictEqual(exec
, other
.m_getter
, m_getter
))
202 && (!m_setter
|| JSValue::strictEqual(exec
, other
.m_setter
, m_setter
))
203 && attributesEqual(other
);
206 bool PropertyDescriptor::attributesEqual(const PropertyDescriptor
& other
) const
208 unsigned mismatch
= other
.m_attributes
^ m_attributes
;
209 unsigned sharedSeen
= other
.m_seenAttributes
& m_seenAttributes
;
210 if (sharedSeen
& WritablePresent
&& mismatch
& ReadOnly
)
212 if (sharedSeen
& ConfigurablePresent
&& mismatch
& DontDelete
)
214 if (sharedSeen
& EnumerablePresent
&& mismatch
& DontEnum
)
219 unsigned PropertyDescriptor::attributesOverridingCurrent(const PropertyDescriptor
& current
) const
221 unsigned currentAttributes
= current
.m_attributes
;
222 if (isDataDescriptor() && current
.isAccessorDescriptor())
223 currentAttributes
|= ReadOnly
;
224 unsigned overrideMask
= 0;
225 if (writablePresent())
226 overrideMask
|= ReadOnly
;
227 if (enumerablePresent())
228 overrideMask
|= DontEnum
;
229 if (configurablePresent())
230 overrideMask
|= DontDelete
;
231 if (isAccessorDescriptor())
232 overrideMask
|= Accessor
;
233 return (m_attributes
& overrideMask
) | (currentAttributes
& ~overrideMask
);