X-Git-Url: https://git.saurik.com/apple/javascriptcore.git/blobdiff_plain/f9bf01c6616d5ddcf65b13b33cedf9e387ff7a63..HEAD:/runtime/PropertyDescriptor.cpp diff --git a/runtime/PropertyDescriptor.cpp b/runtime/PropertyDescriptor.cpp index 558ae28..5722e88 100644 --- a/runtime/PropertyDescriptor.cpp +++ b/runtime/PropertyDescriptor.cpp @@ -30,10 +30,10 @@ #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(x) == bitwise_cast(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); } }