Home | History | Annotate | Download | only in runtime
      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 
     38 bool PropertyDescriptor::writable() const
     39 {
     40     ASSERT(!isAccessorDescriptor());
     41     return !(m_attributes & ReadOnly);
     42 }
     43 
     44 bool PropertyDescriptor::enumerable() const
     45 {
     46     return !(m_attributes & DontEnum);
     47 }
     48 
     49 bool PropertyDescriptor::configurable() const
     50 {
     51     return !(m_attributes & DontDelete);
     52 }
     53 
     54 bool PropertyDescriptor::isDataDescriptor() const
     55 {
     56     return m_value || (m_seenAttributes & WritablePresent);
     57 }
     58 
     59 bool PropertyDescriptor::isGenericDescriptor() const
     60 {
     61     return !isAccessorDescriptor() && !isDataDescriptor();
     62 }
     63 
     64 bool PropertyDescriptor::isAccessorDescriptor() const
     65 {
     66     return m_getter || m_setter;
     67 }
     68 
     69 void PropertyDescriptor::setUndefined()
     70 {
     71     m_value = jsUndefined();
     72     m_attributes = ReadOnly | DontDelete | DontEnum;
     73 }
     74 
     75 JSValue PropertyDescriptor::getter() const
     76 {
     77     ASSERT(isAccessorDescriptor());
     78     return m_getter;
     79 }
     80 
     81 JSValue PropertyDescriptor::setter() const
     82 {
     83     ASSERT(isAccessorDescriptor());
     84     return m_setter;
     85 }
     86 
     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 
    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 
    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 
    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 
    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 
    142 void PropertyDescriptor::setSetter(JSValue setter)
    143 {
    144     m_setter = setter;
    145     m_attributes |= Setter;
    146     m_attributes &= ~ReadOnly;
    147 }
    148 
    149 void PropertyDescriptor::setGetter(JSValue getter)
    150 {
    151     m_getter = getter;
    152     m_attributes |= Getter;
    153     m_attributes &= ~ReadOnly;
    154 }
    155 
    156 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 
    168 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 
    181 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