void ServerSideBrowserModel::getDirectoryItems(const Dir& dir,
                                               const xmms2::Expected<xmms2::List<xmms2::Dict>>& list)
{
    if (list.isError()) {
        directoryLoadFailed(dir, list.error().toString());
        return;
    }
    
    m_dir = dir;
    m_items.clear();
    
    // Explicitly add .. item
    if (!m_dir.isRootPath()) {
        m_items.emplace_back("..", true);
    }
    
    for (auto it = list->getIterator(); it.isValid(); it.next()) {
        bool ok = false;
        xmms2::Dict dict = it.value(&ok);
        if (NCXMMS2_UNLIKELY(!ok))
            continue;
        
        StringRef path = dict.value<StringRef>("path");
        if (NCXMMS2_UNLIKELY(path.isNull()))
            continue;
        
        if (NCXMMS2_UNLIKELY(path == "." || path == ".."))
            continue;
        
        bool isDir = dict.value<int>("isdir", 0);
        m_items.emplace_back(xmms2::getFileNameFromUrl(xmms2::decodeUrl(path.c_str())), isDir);
    }
    
    std::sort(m_items.begin(), m_items.end());
    
    reset();
    directoryLoaded(m_dir);
}
bool Object::__defineOwnProperty__(ExecutionContext *ctx, uint index, const StringRef member, const Property &p, PropertyAttributes attrs)
{
    // clause 5
    if (attrs.isEmpty())
        return true;

    Property *current;
    PropertyAttributes cattrs;
    if (!member.isNull()) {
        current = propertyAt(index);
        cattrs = internalClass->propertyData[index];
    } else {
        current = arrayData->getProperty(index);
        cattrs = arrayData->attributes(index);
    }

    // clause 6
    if (p.isSubset(attrs, *current, cattrs))
        return true;

    // clause 7
    if (!cattrs.isConfigurable()) {
        if (attrs.isConfigurable())
            goto reject;
        if (attrs.hasEnumerable() && attrs.isEnumerable() != cattrs.isEnumerable())
            goto reject;
    }

    // clause 8
    if (attrs.isGeneric() || current->value.isEmpty())
        goto accept;

    // clause 9
    if (cattrs.isData() != attrs.isData()) {
        // 9a
        if (!cattrs.isConfigurable())
            goto reject;
        if (cattrs.isData()) {
            // 9b
            cattrs.setType(PropertyAttributes::Accessor);
            cattrs.clearWritable();
            if (member.isNull()) {
                // need to convert the array and the slot
                initSparseArray();
                setArrayAttributes(index, cattrs);
                current = arrayData->getProperty(index);
            }
            current->setGetter(0);
            current->setSetter(0);
        } else {
            // 9c
            cattrs.setType(PropertyAttributes::Data);
            cattrs.setWritable(false);
            if (member.isNull()) {
                // need to convert the array and the slot
                setArrayAttributes(index, cattrs);
                current = arrayData->getProperty(index);
            }
            current->value = Primitive::undefinedValue();
        }
    } else if (cattrs.isData() && attrs.isData()) { // clause 10
        if (!cattrs.isConfigurable() && !cattrs.isWritable()) {
            if (attrs.isWritable() || !current->value.sameValue(p.value))
                goto reject;
        }
    } else { // clause 10
        Q_ASSERT(cattrs.isAccessor() && attrs.isAccessor());
        if (!cattrs.isConfigurable()) {
            if (!p.value.isEmpty() && current->value.val != p.value.val)
                goto reject;
            if (!p.set.isEmpty() && current->set.val != p.set.val)
                goto reject;
        }
    }

  accept:

    current->merge(cattrs, p, attrs);
    if (!member.isNull()) {
        InternalClass::changeMember(this, member.getPointer(), cattrs);
    } else {
        setArrayAttributes(index, cattrs);
    }
    if (cattrs.isAccessor())
        hasAccessorProperty = 1;
    return true;
  reject:
    if (ctx->strictMode)
        ctx->throwTypeError();
    return false;
}