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
35 namespace JSC {
36 unsigned PropertyDescriptor::defaultAttributes = (DontDelete << 1) - 1;
37
writable() const38 bool PropertyDescriptor::writable() const
39 {
40 ASSERT(!isAccessorDescriptor());
41 return !(m_attributes & ReadOnly);
42 }
43
enumerable() const44 bool PropertyDescriptor::enumerable() const
45 {
46 return !(m_attributes & DontEnum);
47 }
48
configurable() const49 bool PropertyDescriptor::configurable() const
50 {
51 return !(m_attributes & DontDelete);
52 }
53
isDataDescriptor() const54 bool PropertyDescriptor::isDataDescriptor() const
55 {
56 return m_value || (m_seenAttributes & WritablePresent);
57 }
58
isGenericDescriptor() const59 bool PropertyDescriptor::isGenericDescriptor() const
60 {
61 return !isAccessorDescriptor() && !isDataDescriptor();
62 }
63
isAccessorDescriptor() const64 bool PropertyDescriptor::isAccessorDescriptor() const
65 {
66 return m_getter || m_setter;
67 }
68
setUndefined()69 void PropertyDescriptor::setUndefined()
70 {
71 m_value = jsUndefined();
72 m_attributes = ReadOnly | DontDelete | DontEnum;
73 }
74
getter() const75 JSValue PropertyDescriptor::getter() const
76 {
77 ASSERT(isAccessorDescriptor());
78 return m_getter;
79 }
80
setter() const81 JSValue PropertyDescriptor::setter() const
82 {
83 ASSERT(isAccessorDescriptor());
84 return m_setter;
85 }
86
setDescriptor(JSValue value,unsigned attributes)87 void PropertyDescriptor::setDescriptor(JSValue value, unsigned attributes)
88 {
89 ASSERT(value);
90 m_attributes = attributes;
91 if (attributes & (Getter | Setter)) {
92 GetterSetter* accessor = asGetterSetter(value);
93 m_getter = accessor->getter();
94 m_setter = accessor->setter();
95 ASSERT(m_getter || m_setter);
96 m_seenAttributes = EnumerablePresent | ConfigurablePresent;
97 m_attributes &= ~ReadOnly;
98 } else {
99 m_value = value;
100 m_seenAttributes = EnumerablePresent | ConfigurablePresent | WritablePresent;
101 }
102 }
103
setAccessorDescriptor(JSValue getter,JSValue setter,unsigned attributes)104 void PropertyDescriptor::setAccessorDescriptor(JSValue getter, JSValue setter, unsigned attributes)
105 {
106 ASSERT(attributes & (Getter | Setter));
107 ASSERT(getter || setter);
108 m_attributes = attributes;
109 m_getter = getter;
110 m_setter = setter;
111 m_attributes &= ~ReadOnly;
112 m_seenAttributes = EnumerablePresent | ConfigurablePresent;
113 }
114
setWritable(bool writable)115 void PropertyDescriptor::setWritable(bool writable)
116 {
117 if (writable)
118 m_attributes &= ~ReadOnly;
119 else
120 m_attributes |= ReadOnly;
121 m_seenAttributes |= WritablePresent;
122 }
123
setEnumerable(bool enumerable)124 void PropertyDescriptor::setEnumerable(bool enumerable)
125 {
126 if (enumerable)
127 m_attributes &= ~DontEnum;
128 else
129 m_attributes |= DontEnum;
130 m_seenAttributes |= EnumerablePresent;
131 }
132
setConfigurable(bool configurable)133 void PropertyDescriptor::setConfigurable(bool configurable)
134 {
135 if (configurable)
136 m_attributes &= ~DontDelete;
137 else
138 m_attributes |= DontDelete;
139 m_seenAttributes |= ConfigurablePresent;
140 }
141
setSetter(JSValue setter)142 void PropertyDescriptor::setSetter(JSValue setter)
143 {
144 m_setter = setter;
145 m_attributes |= Setter;
146 m_attributes &= ~ReadOnly;
147 }
148
setGetter(JSValue getter)149 void PropertyDescriptor::setGetter(JSValue getter)
150 {
151 m_getter = getter;
152 m_attributes |= Getter;
153 m_attributes &= ~ReadOnly;
154 }
155
equalTo(ExecState * exec,const PropertyDescriptor & other) const156 bool PropertyDescriptor::equalTo(ExecState* exec, const PropertyDescriptor& other) const
157 {
158 if (!other.m_value == m_value ||
159 !other.m_getter == m_getter ||
160 !other.m_setter == m_setter)
161 return false;
162 return (!m_value || JSValue::strictEqual(exec, other.m_value, m_value)) &&
163 (!m_getter || JSValue::strictEqual(exec, other.m_getter, m_getter)) &&
164 (!m_setter || JSValue::strictEqual(exec, other.m_setter, m_setter)) &&
165 attributesEqual(other);
166 }
167
attributesEqual(const PropertyDescriptor & other) const168 bool PropertyDescriptor::attributesEqual(const PropertyDescriptor& other) const
169 {
170 unsigned mismatch = other.m_attributes ^ m_attributes;
171 unsigned sharedSeen = other.m_seenAttributes & m_seenAttributes;
172 if (sharedSeen & WritablePresent && mismatch & ReadOnly)
173 return false;
174 if (sharedSeen & ConfigurablePresent && mismatch & DontDelete)
175 return false;
176 if (sharedSeen & EnumerablePresent && mismatch & DontEnum)
177 return false;
178 return true;
179 }
180
attributesWithOverride(const PropertyDescriptor & other) const181 unsigned PropertyDescriptor::attributesWithOverride(const PropertyDescriptor& other) const
182 {
183 unsigned mismatch = other.m_attributes ^ m_attributes;
184 unsigned sharedSeen = other.m_seenAttributes & m_seenAttributes;
185 unsigned newAttributes = m_attributes & defaultAttributes;
186 if (sharedSeen & WritablePresent && mismatch & ReadOnly)
187 newAttributes ^= ReadOnly;
188 if (sharedSeen & ConfigurablePresent && mismatch & DontDelete)
189 newAttributes ^= DontDelete;
190 if (sharedSeen & EnumerablePresent && mismatch & DontEnum)
191 newAttributes ^= DontEnum;
192 return newAttributes;
193 }
194
195 }
196