]> git.saurik.com Git - apple/javascriptcore.git/blame_incremental - runtime/PropertyDescriptor.cpp
JavaScriptCore-1097.3.3.tar.gz
[apple/javascriptcore.git] / runtime / PropertyDescriptor.cpp
... / ...
CommitLineData
1/*
2 * Copyright (C) 2009 Apple Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
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.
12 *
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.
24 */
25
26
27#include "config.h"
28
29#include "PropertyDescriptor.h"
30
31#include "GetterSetter.h"
32#include "JSObject.h"
33#include "Operations.h"
34
35namespace JSC {
36unsigned PropertyDescriptor::defaultAttributes = (DontDelete << 1) - 1;
37
38bool PropertyDescriptor::writable() const
39{
40 ASSERT(!isAccessorDescriptor());
41 return !(m_attributes & ReadOnly);
42}
43
44bool PropertyDescriptor::enumerable() const
45{
46 return !(m_attributes & DontEnum);
47}
48
49bool PropertyDescriptor::configurable() const
50{
51 return !(m_attributes & DontDelete);
52}
53
54bool PropertyDescriptor::isDataDescriptor() const
55{
56 return m_value || (m_seenAttributes & WritablePresent);
57}
58
59bool PropertyDescriptor::isGenericDescriptor() const
60{
61 return !isAccessorDescriptor() && !isDataDescriptor();
62}
63
64bool PropertyDescriptor::isAccessorDescriptor() const
65{
66 return m_getter || m_setter;
67}
68
69void PropertyDescriptor::setUndefined()
70{
71 m_value = jsUndefined();
72 m_attributes = ReadOnly | DontDelete | DontEnum;
73}
74
75JSValue PropertyDescriptor::getter() const
76{
77 ASSERT(isAccessorDescriptor());
78 return m_getter;
79}
80
81JSValue PropertyDescriptor::setter() const
82{
83 ASSERT(isAccessorDescriptor());
84 return m_setter;
85}
86
87JSObject* PropertyDescriptor::getterObject() const
88{
89 ASSERT(isAccessorDescriptor() && getterPresent());
90 return m_getter.isObject() ? asObject(m_getter) : 0;
91}
92
93JSObject* PropertyDescriptor::setterObject() const
94{
95 ASSERT(isAccessorDescriptor() && setterPresent());
96 return m_setter.isObject() ? asObject(m_setter) : 0;
97}
98
99void PropertyDescriptor::setDescriptor(JSValue value, unsigned attributes)
100{
101 ASSERT(value);
102 ASSERT(value.isGetterSetter() == !!(attributes & Accessor));
103
104 m_attributes = attributes;
105 if (value.isGetterSetter()) {
106 m_attributes &= ~ReadOnly; // FIXME: we should be able to ASSERT this!
107
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;
112 } else {
113 m_value = value;
114 m_seenAttributes = EnumerablePresent | ConfigurablePresent | WritablePresent;
115 }
116}
117
118void PropertyDescriptor::setAccessorDescriptor(GetterSetter* accessor, unsigned attributes)
119{
120 ASSERT(attributes & Accessor);
121 attributes &= ~ReadOnly; // FIXME: we should be able to ASSERT this!
122
123 m_attributes = attributes;
124 m_getter = accessor->getter() ? accessor->getter() : jsUndefined();
125 m_setter = accessor->setter() ? accessor->setter() : jsUndefined();
126 m_seenAttributes = EnumerablePresent | ConfigurablePresent;
127}
128
129void PropertyDescriptor::setWritable(bool writable)
130{
131 if (writable)
132 m_attributes &= ~ReadOnly;
133 else
134 m_attributes |= ReadOnly;
135 m_seenAttributes |= WritablePresent;
136}
137
138void PropertyDescriptor::setEnumerable(bool enumerable)
139{
140 if (enumerable)
141 m_attributes &= ~DontEnum;
142 else
143 m_attributes |= DontEnum;
144 m_seenAttributes |= EnumerablePresent;
145}
146
147void PropertyDescriptor::setConfigurable(bool configurable)
148{
149 if (configurable)
150 m_attributes &= ~DontDelete;
151 else
152 m_attributes |= DontDelete;
153 m_seenAttributes |= ConfigurablePresent;
154}
155
156void PropertyDescriptor::setSetter(JSValue setter)
157{
158 m_setter = setter;
159 m_attributes |= Accessor;
160 m_attributes &= ~ReadOnly;
161}
162
163void PropertyDescriptor::setGetter(JSValue getter)
164{
165 m_getter = getter;
166 m_attributes |= Accessor;
167 m_attributes &= ~ReadOnly;
168}
169
170// See ES5.1 9.12
171bool sameValue(ExecState* exec, JSValue a, JSValue b)
172{
173 if (!a.isNumber())
174 return JSValue::strictEqual(exec, a, b);
175 if (!b.isNumber())
176 return false;
177 double x = a.asNumber();
178 double y = b.asNumber();
179 if (isnan(x))
180 return isnan(y);
181 return bitwise_cast<uint64_t>(x) == bitwise_cast<uint64_t>(y);
182}
183
184bool PropertyDescriptor::equalTo(ExecState* exec, const PropertyDescriptor& other) const
185{
186 if (!other.m_value == m_value ||
187 !other.m_getter == m_getter ||
188 !other.m_setter == m_setter)
189 return false;
190 return (!m_value || sameValue(exec, other.m_value, m_value))
191 && (!m_getter || JSValue::strictEqual(exec, other.m_getter, m_getter))
192 && (!m_setter || JSValue::strictEqual(exec, other.m_setter, m_setter))
193 && attributesEqual(other);
194}
195
196bool PropertyDescriptor::attributesEqual(const PropertyDescriptor& other) const
197{
198 unsigned mismatch = other.m_attributes ^ m_attributes;
199 unsigned sharedSeen = other.m_seenAttributes & m_seenAttributes;
200 if (sharedSeen & WritablePresent && mismatch & ReadOnly)
201 return false;
202 if (sharedSeen & ConfigurablePresent && mismatch & DontDelete)
203 return false;
204 if (sharedSeen & EnumerablePresent && mismatch & DontEnum)
205 return false;
206 return true;
207}
208
209unsigned PropertyDescriptor::attributesOverridingCurrent(const PropertyDescriptor& current) const
210{
211 unsigned currentAttributes = current.m_attributes;
212 if (isDataDescriptor() && current.isAccessorDescriptor())
213 currentAttributes |= ReadOnly;
214 unsigned overrideMask = 0;
215 if (writablePresent())
216 overrideMask |= ReadOnly;
217 if (enumerablePresent())
218 overrideMask |= DontEnum;
219 if (configurablePresent())
220 overrideMask |= DontDelete;
221 if (isAccessorDescriptor())
222 overrideMask |= Accessor;
223 return (m_attributes & overrideMask) | (currentAttributes & ~overrideMask);
224}
225
226}