]> git.saurik.com Git - apple/javascriptcore.git/blobdiff - runtime/PropertyDescriptor.cpp
JavaScriptCore-7601.1.46.3.tar.gz
[apple/javascriptcore.git] / runtime / PropertyDescriptor.cpp
index 558ae28525d9384082db43af0657baaa904929ec..5722e88da0fab36bcaf185db1c5415618ad7fe54 100644 (file)
 
 #include "GetterSetter.h"
 #include "JSObject.h"
-#include "Operations.h"
+#include "JSCInlines.h"
 
 namespace JSC {
-unsigned PropertyDescriptor::defaultAttributes = (DontDelete << 1) - 1;
+unsigned PropertyDescriptor::defaultAttributes = DontDelete | DontEnum | ReadOnly;
 
 bool PropertyDescriptor::writable() const
 {
@@ -84,32 +84,56 @@ JSValue PropertyDescriptor::setter() const
     return m_setter;
 }
 
+JSObject* PropertyDescriptor::getterObject() const
+{
+    ASSERT(isAccessorDescriptor() && getterPresent());
+    return m_getter.isObject() ? asObject(m_getter) : 0;
+}
+
+JSObject* PropertyDescriptor::setterObject() const
+{
+    ASSERT(isAccessorDescriptor() && setterPresent());
+    return m_setter.isObject() ? asObject(m_setter) : 0;
+}
+
 void PropertyDescriptor::setDescriptor(JSValue value, unsigned attributes)
 {
     ASSERT(value);
+    ASSERT(value.isGetterSetter() == !!(attributes & Accessor));
+
     m_attributes = attributes;
-    if (attributes & (Getter | Setter)) {
+    if (value.isGetterSetter()) {
+        m_attributes &= ~ReadOnly; // FIXME: we should be able to ASSERT this!
+
         GetterSetter* accessor = asGetterSetter(value);
-        m_getter = accessor->getter();
-        m_setter = accessor->setter();
-        ASSERT(m_getter || m_setter);
+        m_getter = !accessor->isGetterNull() ? accessor->getter() : jsUndefined();
+        m_setter = !accessor->isSetterNull() ? accessor->setter() : jsUndefined();
         m_seenAttributes = EnumerablePresent | ConfigurablePresent;
-        m_attributes &= ~ReadOnly;
     } else {
         m_value = value;
         m_seenAttributes = EnumerablePresent | ConfigurablePresent | WritablePresent;
     }
 }
 
-void PropertyDescriptor::setAccessorDescriptor(JSValue getter, JSValue setter, unsigned attributes)
+void PropertyDescriptor::setCustomDescriptor(unsigned attributes)
 {
-    ASSERT(attributes & (Getter | Setter));
-    ASSERT(getter || setter);
-    m_attributes = attributes;
-    m_getter = getter;
-    m_setter = setter;
+    m_attributes = attributes | Accessor | CustomAccessor;
     m_attributes &= ~ReadOnly;
     m_seenAttributes = EnumerablePresent | ConfigurablePresent;
+    setGetter(jsUndefined());
+    setSetter(jsUndefined());
+    m_value = JSValue();
+}
+
+void PropertyDescriptor::setAccessorDescriptor(GetterSetter* accessor, unsigned attributes)
+{
+    ASSERT(attributes & Accessor);
+    attributes &= ~ReadOnly; // FIXME: we should be able to ASSERT this!
+
+    m_attributes = attributes;
+    m_getter = !accessor->isGetterNull() ? accessor->getter() : jsUndefined();
+    m_setter = !accessor->isSetterNull() ? accessor->setter() : jsUndefined();
+    m_seenAttributes = EnumerablePresent | ConfigurablePresent;
 }
 
 void PropertyDescriptor::setWritable(bool writable)
@@ -142,27 +166,43 @@ void PropertyDescriptor::setConfigurable(bool configurable)
 void PropertyDescriptor::setSetter(JSValue setter)
 {
     m_setter = setter;
-    m_attributes |= Setter;
+    m_attributes |= Accessor;
     m_attributes &= ~ReadOnly;
 }
 
 void PropertyDescriptor::setGetter(JSValue getter)
 {
     m_getter = getter;
-    m_attributes |= Getter;
+    m_attributes |= Accessor;
     m_attributes &= ~ReadOnly;
 }
 
+// See ES5.1 9.12
+bool sameValue(ExecState* exec, JSValue a, JSValue b)
+{
+    if (!a.isNumber())
+        return JSValue::strictEqual(exec, a, b);
+    if (!b.isNumber())
+        return false;
+    double x = a.asNumber();
+    double y = b.asNumber();
+    bool xIsNaN = std::isnan(x);
+    bool yIsNaN = std::isnan(y);
+    if (xIsNaN || yIsNaN)
+        return xIsNaN && yIsNaN;
+    return bitwise_cast<uint64_t>(x) == bitwise_cast<uint64_t>(y);
+}
+
 bool PropertyDescriptor::equalTo(ExecState* exec, const PropertyDescriptor& other) const
 {
-    if (!other.m_value == m_value ||
-        !other.m_getter == m_getter ||
-        !other.m_setter == m_setter)
+    if (other.m_value.isEmpty() != m_value.isEmpty()
+        || other.m_getter.isEmpty() != m_getter.isEmpty()
+        || other.m_setter.isEmpty() != m_setter.isEmpty())
         return false;
-    return (!m_value || JSValue::strictEqual(exec, other.m_value, m_value)) && 
-           (!m_getter || JSValue::strictEqual(exec, other.m_getter, m_getter)) && 
-           (!m_setter || JSValue::strictEqual(exec, other.m_setter, m_setter)) &&
-           attributesEqual(other);
+    return (!m_value || sameValue(exec, other.m_value, m_value))
+        && (!m_getter || JSValue::strictEqual(exec, other.m_getter, m_getter))
+        && (!m_setter || JSValue::strictEqual(exec, other.m_setter, m_setter))
+        && attributesEqual(other);
 }
 
 bool PropertyDescriptor::attributesEqual(const PropertyDescriptor& other) const
@@ -178,18 +218,21 @@ bool PropertyDescriptor::attributesEqual(const PropertyDescriptor& other) const
     return true;
 }
 
-unsigned PropertyDescriptor::attributesWithOverride(const PropertyDescriptor& other) const
-{
-    unsigned mismatch = other.m_attributes ^ m_attributes;
-    unsigned sharedSeen = other.m_seenAttributes & m_seenAttributes;
-    unsigned newAttributes = m_attributes & defaultAttributes;
-    if (sharedSeen & WritablePresent && mismatch & ReadOnly)
-        newAttributes ^= ReadOnly;
-    if (sharedSeen & ConfigurablePresent && mismatch & DontDelete)
-        newAttributes ^= DontDelete;
-    if (sharedSeen & EnumerablePresent && mismatch & DontEnum)
-        newAttributes ^= DontEnum;
-    return newAttributes;
+unsigned PropertyDescriptor::attributesOverridingCurrent(const PropertyDescriptor& current) const
+{
+    unsigned currentAttributes = current.m_attributes;
+    if (isDataDescriptor() && current.isAccessorDescriptor())
+        currentAttributes |= ReadOnly;
+    unsigned overrideMask = 0;
+    if (writablePresent())
+        overrideMask |= ReadOnly;
+    if (enumerablePresent())
+        overrideMask |= DontEnum;
+    if (configurablePresent())
+        overrideMask |= DontDelete;
+    if (isAccessorDescriptor())
+        overrideMask |= Accessor;
+    return (m_attributes & overrideMask) | (currentAttributes & ~overrideMask);
 }
 
 }