unsigned PropertyDescriptor::attributesOverridingCurrent(const PropertyDescriptor& current) const
{
    unsigned currentAttributes = current.m_attributes;
    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);
}
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;
    if (isAccessorDescriptor() && other.isDataDescriptor())
        newAttributes |= ReadOnly;
    return newAttributes;
}
unsigned PropertyDescriptor::attributesOverridingCurrent(const PropertyDescriptor& current) const
{
    unsigned currentAttributes = current.m_attributes;
    if (isDataDescriptor() && current.isAccessorDescriptor())
        currentAttributes |= PropertyAttribute::ReadOnly;
    unsigned overrideMask = 0;
    if (writablePresent())
        overrideMask |= PropertyAttribute::ReadOnly;
    if (enumerablePresent())
        overrideMask |= PropertyAttribute::DontEnum;
    if (configurablePresent())
        overrideMask |= PropertyAttribute::DontDelete;
    if (isAccessorDescriptor())
        overrideMask |= PropertyAttribute::Accessor;
    return (m_attributes & overrideMask) | (currentAttributes & ~overrideMask & ~PropertyAttribute::CustomAccessor);
}
JSValue PropertyDescriptor::setter() const
{
    ASSERT(isAccessorDescriptor());
    return m_setter;
}
bool PropertyDescriptor::isGenericDescriptor() const
{
    return !isAccessorDescriptor() && !isDataDescriptor();
}
bool PropertyDescriptor::writable() const
{
    ASSERT(!isAccessorDescriptor());
    return !(m_attributes & ReadOnly);
}
JSObject* PropertyDescriptor::getterObject() const
{
    ASSERT(isAccessorDescriptor() && getterPresent());
    return m_getter.isObject() ? asObject(m_getter) : 0;
}