/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtQml module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include "qqmllistmodel_p_p.h"
#include "qqmllistmodelworkeragent_p.h"
#include <private/qqmlopenmetaobject_p.h>
#include <private/qqmljsast_p.h>
#include <private/qqmljsengine_p.h>
#include <private/qjsvalue_p.h>

#include <private/qqmlcustomparser_p.h>
#include <private/qqmlengine_p.h>
#include <private/qqmlnotifier_p.h>

#include <private/qv4object_p.h>
#include <private/qv4dateobject_p.h>
#include <private/qv4objectiterator_p.h>
#include <private/qv4alloca_p.h>
#include <private/qv4lookup_p.h>
#include <private/qv4qmlcontext_p.h>

#include <qqmlcontext.h>
#include <qqmlinfo.h>

#include <QtCore/qdebug.h>
#include <QtCore/qstack.h>
#include <QXmlStreamReader>
#include <QtCore/qdatetime.h>
#include <QScopedValueRollback>

Q_DECLARE_METATYPE(const QV4::CompiledData::Binding*);

QT_BEGIN_NAMESPACE

// Set to 1024 as a debugging aid - easier to distinguish uids from indices of elements/models.
enum { MIN_LISTMODEL_UID = 1024 };

static QAtomicInt uidCounter(MIN_LISTMODEL_UID);

template <typename T>
static bool isMemoryUsed(const char *mem)
{
    for (size_t i=0 ; i < sizeof(T) ; ++i) {
        if (mem[i] != 0)
            return true;
    }

    return false;
}

static QString roleTypeName(ListLayout::Role::DataType t)
{
    static const QString roleTypeNames[] = {
        QStringLiteral("String"), QStringLiteral("Number"), QStringLiteral("Bool"),
        QStringLiteral("List"), QStringLiteral("QObject"), QStringLiteral("VariantMap"),
        QStringLiteral("DateTime"), QStringLiteral("Function")
    };

    if (t > ListLayout::Role::Invalid && t < ListLayout::Role::MaxDataType)
        return roleTypeNames[t];

    return QString();
}

const ListLayout::Role &ListLayout::getRoleOrCreate(const QString &key, Role::DataType type)
{
    QStringHash<Role *>::Node *node = roleHash.findNode(key);
    if (node) {
        const Role &r = *node->value;
        if (type != r.type)
            qmlWarning(nullptr) << QStringLiteral("Can't assign to existing role '%1' of different type [%2 -> %3]").arg(r.name).arg(roleTypeName(type)).arg(roleTypeName(r.type));
        return r;
    }

    return createRole(key, type);
}

const ListLayout::Role &ListLayout::getRoleOrCreate(QV4::String *key, Role::DataType type)
{
    QStringHash<Role *>::Node *node = roleHash.findNode(key);
    if (node) {
        const Role &r = *node->value;
        if (type != r.type)
            qmlWarning(nullptr) << QStringLiteral("Can't assign to existing role '%1' of different type [%2 -> %3]").arg(r.name).arg(roleTypeName(type)).arg(roleTypeName(r.type));
        return r;
    }

    QString qkey = key->toQString();

    return createRole(qkey, type);
}

const ListLayout::Role &ListLayout::createRole(const QString &key, ListLayout::Role::DataType type)
{
    const int dataSizes[] = { sizeof(StringOrTranslation), sizeof(double), sizeof(bool), sizeof(ListModel *), sizeof(QPointer<QObject>), sizeof(QVariantMap), sizeof(QDateTime), sizeof(QJSValue) };
    const int dataAlignments[] = { sizeof(StringOrTranslation), sizeof(double), sizeof(bool), sizeof(ListModel *), sizeof(QObject *), sizeof(QVariantMap), sizeof(QDateTime), sizeof(QJSValue) };

    Role *r = new Role;
    r->name = key;
    r->type = type;

    if (type == Role::List) {
        r->subLayout = new ListLayout;
    } else {
        r->subLayout = nullptr;
    }

    int dataSize = dataSizes[type];
    int dataAlignment = dataAlignments[type];

    int dataOffset = (currentBlockOffset + dataAlignment-1) & ~(dataAlignment-1);
    if (dataOffset + dataSize > ListElement::BLOCK_SIZE) {
        r->blockIndex = ++currentBlock;
        r->blockOffset = 0;
        currentBlockOffset = dataSize;
    } else {
        r->blockIndex = currentBlock;
        r->blockOffset = dataOffset;
        currentBlockOffset = dataOffset + dataSize;
    }

    int roleIndex = roles.count();
    r->index = roleIndex;

    roles.append(r);
    roleHash.insert(key, r);

    return *r;
}

ListLayout::ListLayout(const ListLayout *other) : currentBlock(0), currentBlockOffset(0)
{
    const int otherRolesCount = other->roles.count();
    roles.reserve(otherRolesCount);
    for (int i=0 ; i < otherRolesCount; ++i) {
        Role *role = new Role(other->roles[i]);
        roles.append(role);
        roleHash.insert(role->name, role);
    }
    currentBlockOffset = other->currentBlockOffset;
    currentBlock = other->currentBlock;
}

ListLayout::~ListLayout()
{
    qDeleteAll(roles);
}

void ListLayout::sync(ListLayout *src, ListLayout *target)
{
    int roleOffset = target->roles.count();
    int newRoleCount = src->roles.count() - roleOffset;

    for (int i=0 ; i < newRoleCount ; ++i) {
        Role *role = new Role(src->roles[roleOffset + i]);
        target->roles.append(role);
        target->roleHash.insert(role->name, role);
    }

    target->currentBlockOffset = src->currentBlockOffset;
    target->currentBlock = src->currentBlock;
}

ListLayout::Role::Role(const Role *other)
{
    name = other->name;
    type = other->type;
    blockIndex = other->blockIndex;
    blockOffset = other->blockOffset;
    index = other->index;
    if (other->subLayout)
        subLayout = new ListLayout(other->subLayout);
    else
        subLayout = nullptr;
}

ListLayout::Role::~Role()
{
    delete subLayout;
}

const ListLayout::Role *ListLayout::getRoleOrCreate(const QString &key, const QVariant &data)
{
    Role::DataType type;

    switch (data.userType()) {
        case QMetaType::Double:      type = Role::Number;      break;
        case QMetaType::Int:         type = Role::Number;      break;
        case QMetaType::Bool:        type = Role::Bool;        break;
        case QMetaType::QString:      type = Role::String;      break;
        case QMetaType::QVariantMap:         type = Role::VariantMap;  break;
        case QMetaType::QDateTime:    type = Role::DateTime;    break;
        default:    {
            if (data.userType() == qMetaTypeId<QJSValue>() &&
                data.value<QJSValue>().isCallable()) {
                type = Role::Function;
                break;
            } else if (data.userType() == qMetaTypeId<const QV4::CompiledData::Binding*>()
                       && data.value<const QV4::CompiledData::Binding*>()->isTranslationBinding()) {
                type = Role::String;
                break;
            } else if (data.userType() >= QMetaType::User) {
                type = Role::List;
                break;
            } else {
                type = Role::Invalid;
                break;
            }
        }
    }

    if (type == Role::Invalid) {
        qmlWarning(nullptr) << "Can't create role for unsupported data type";
        return nullptr;
    }

    return &getRoleOrCreate(key, type);
}

const ListLayout::Role *ListLayout::getExistingRole(const QString &key) const
{
    Role *r = nullptr;
    QStringHash<Role *>::Node *node = roleHash.findNode(key);
    if (node)
        r = node->value;
    return r;
}

const ListLayout::Role *ListLayout::getExistingRole(QV4::String *key) const
{
    Role *r = nullptr;
    QStringHash<Role *>::Node *node = roleHash.findNode(key);
    if (node)
        r = node->value;
    return r;
}

StringOrTranslation::StringOrTranslation(const QString &s)
{
    d.setFlag();
    setString(s);
}

StringOrTranslation::StringOrTranslation(const QV4::CompiledData::Binding *binding)
{
    d.setFlag();
    clear();
    d = binding;
}

StringOrTranslation::~StringOrTranslation()
{
    clear();
}

void StringOrTranslation::setString(const QString &s)
{
    d.setFlag();
    clear();
    QStringData *stringData = const_cast<QString &>(s).data_ptr();
    d = stringData;
    if (stringData)
        stringData->ref.ref();
}

void StringOrTranslation::setTranslation(const QV4::CompiledData::Binding *binding)
{
    d.setFlag();
    clear();
    d = binding;
}

QString StringOrTranslation::toString(const QQmlListModel *owner) const
{
    if (d.isNull())
        return QString();
    if (d.isT1()) {
        QStringDataPtr holder = { d.asT1() };
        holder.ptr->ref.ref();
        return QString(holder);
    }
    if (!owner)
        return QString();
    return owner->m_compilationUnit->bindingValueAsString(d.asT2());
}

QString StringOrTranslation::asString() const
{
    if (d.isNull())
        return QString();
    if (!d.isT1())
        return QString();
    QStringDataPtr holder = { d.asT1() };
    holder.ptr->ref.ref();
    return QString(holder);
}

void StringOrTranslation::clear()
{
    if (QStringData *strData = d.isT1() ? d.asT1() : nullptr) {
        if (!strData->ref.deref())
            QStringData::deallocate(strData);
    }
    d = static_cast<QStringData *>(nullptr);
}

QObject *ListModel::getOrCreateModelObject(QQmlListModel *model, int elementIndex)
{
    ListElement *e = elements[elementIndex];
    if (e->m_objectCache == nullptr) {
        void *memory = operator new(sizeof(QObject) + sizeof(QQmlData));
        void *ddataMemory = ((char *)memory) + sizeof(QObject);
        e->m_objectCache = new (memory) QObject;
        QQmlData *ddata = new (ddataMemory) QQmlData;
        ddata->ownMemory = false;
        QObjectPrivate::get(e->m_objectCache)->declarativeData = ddata;
        (void)new ModelNodeMetaObject(e->m_objectCache, model, elementIndex);
    }
    return e->m_objectCache;
}

bool ListModel::sync(ListModel *src, ListModel *target)
{
    // Sanity check

    bool hasChanges = false;

    // Build hash of elements <-> uid for each of the lists
    QHash<int, ElementSync> elementHash;
    for (int i = 0; i < target->elements.count(); ++i) {
        ListElement *e = target->elements.at(i);
        int uid = e->getUid();
        ElementSync sync;
        sync.target = e;
        sync.targetIndex = i;
        elementHash.insert(uid, sync);
    }
    for (int i = 0; i < src->elements.count(); ++i) {
        ListElement *e = src->elements.at(i);
        int uid = e->getUid();

        QHash<int, ElementSync>::iterator it = elementHash.find(uid);
        if (it == elementHash.end()) {
            ElementSync sync;
            sync.src = e;
            sync.srcIndex = i;
            elementHash.insert(uid, sync);
        } else {
            ElementSync &sync = it.value();
            sync.src = e;
            sync.srcIndex = i;
        }
    }

    QQmlListModel *targetModel = target->m_modelCache;

    // Get list of elements that are in the target but no longer in the source. These get deleted first.
    int rowsRemoved = 0;
    for (int i = 0 ; i < target->elements.count() ; ++i) {
        ListElement *element = target->elements.at(i);
        ElementSync &s = elementHash.find(element->getUid()).value();
        Q_ASSERT(s.targetIndex >= 0);
        // need to update the targetIndex, to keep it correct after removals
        s.targetIndex -= rowsRemoved;
        if (s.src == nullptr) {
            Q_ASSERT(s.targetIndex == i);
            hasChanges = true;
            if (targetModel)
                targetModel->beginRemoveRows(QModelIndex(), i, i);
            s.target->destroy(target->m_layout);
            target->elements.removeOne(s.target);
            delete s.target;
            if (targetModel)
                targetModel->endRemoveRows();
            ++rowsRemoved;
            --i;
            continue;
        }
    }

    // Sync the layouts
    ListLayout::sync(src->m_layout, target->m_layout);

    // Clear the target list, and append in correct order from the source
    target->elements.clear();
    for (int i = 0; i < src->elements.count(); ++i) {
        ListElement *srcElement = src->elements.at(i);
        ElementSync &s = elementHash.find(srcElement->getUid()).value();
        Q_ASSERT(s.srcIndex >= 0);
        ListElement *targetElement = s.target;
        if (targetElement == nullptr) {
            targetElement = new ListElement(srcElement->getUid());
        }
        s.changedRoles = ListElement::sync(srcElement, src->m_layout, targetElement, target->m_layout);
        target->elements.append(targetElement);
    }

    target->updateCacheIndices();

    // Update values stored in target meta objects
    for (int i=0 ; i < target->elements.count() ; ++i) {
        ListElement *e = target->elements[i];
        if (ModelNodeMetaObject *mo = e->objectCache())
            mo->updateValues();
    }

    // now emit the change notifications required. This can be safely done, as we're only emitting changes, moves and inserts,
    // so the model indices can't be out of bounds
    //
    // to ensure things are kept in the correct order, emit inserts and moves first. This shouls ensure all persistent
    // model indices are updated correctly
    int rowsInserted = 0;
    for (int i = 0 ; i < target->elements.count() ; ++i) {
        ListElement *element = target->elements.at(i);
        ElementSync &s = elementHash.find(element->getUid()).value();
        Q_ASSERT(s.srcIndex >= 0);
        s.srcIndex += rowsInserted;
        if (s.srcIndex != s.targetIndex) {
            if (targetModel) {
                if (s.targetIndex == -1) {
                    targetModel->beginInsertRows(QModelIndex(), i, i);
                    targetModel->endInsertRows();
                } else {
                    targetModel->beginMoveRows(QModelIndex(), i, i, QModelIndex(), s.srcIndex);
                    targetModel->endMoveRows();
                }
            }
            hasChanges = true;
            ++rowsInserted;
        }
        if (s.targetIndex != -1 && !s.changedRoles.isEmpty()) {
            QModelIndex idx = targetModel->createIndex(i, 0);
            if (targetModel)
                targetModel->dataChanged(idx, idx, s.changedRoles);
            hasChanges = true;
        }
    }
    return hasChanges;
}

ListModel::ListModel(ListLayout *layout, QQmlListModel *modelCache) : m_layout(layout), m_modelCache(modelCache)
{
}

void ListModel::destroy()
{
    for (const auto &destroyer : remove(0, elements.count()))
        destroyer();

    m_layout = nullptr;
    if (m_modelCache && m_modelCache->m_primary == false)
        delete m_modelCache;
    m_modelCache = nullptr;
}

int ListModel::appendElement()
{
    int elementIndex = elements.count();
    newElement(elementIndex);
    return elementIndex;
}

void ListModel::insertElement(int index)
{
    newElement(index);
    updateCacheIndices(index);
}

void ListModel::move(int from, int to, int n)
{
    if (from > to) {
        // Only move forwards - flip if backwards moving
        int tfrom = from;
        int tto = to;
        from = tto;
        to = tto+n;
        n = tfrom-tto;
    }

    QPODVector<ListElement *, 4> store;
    for (int i=0 ; i < (to-from) ; ++i)
        store.append(elements[from+n+i]);
    for (int i=0 ; i < n ; ++i)
        store.append(elements[from+i]);
    for (int i=0 ; i < store.count() ; ++i)
        elements[from+i] = store[i];

    updateCacheIndices(from, to + n);
}

void ListModel::newElement(int index)
{
    ListElement *e = new ListElement;
    elements.insert(index, e);
}

void ListModel::updateCacheIndices(int start, int end)
{
    int count = elements.count();

    if (end < 0 || end > count)
        end = count;

    for (int i = start; i < end; ++i) {
        ListElement *e = elements.at(i);
        if (ModelNodeMetaObject *mo = e->objectCache())
            mo->m_elementIndex = i;
    }
}

QVariant ListModel::getProperty(int elementIndex, int roleIndex, const QQmlListModel *owner, QV4::ExecutionEngine *eng)
{
    if (roleIndex >= m_layout->roleCount())
        return QVariant();
    ListElement *e = elements[elementIndex];
    const ListLayout::Role &r = m_layout->getExistingRole(roleIndex);
    return e->getProperty(r, owner, eng);
}

ListModel *ListModel::getListProperty(int elementIndex, const ListLayout::Role &role)
{
    ListElement *e = elements[elementIndex];
    return e->getListProperty(role);
}

void ListModel::set(int elementIndex, QV4::Object *object, QVector<int> *roles)
{
    ListElement *e = elements[elementIndex];

    QV4::ExecutionEngine *v4 = object->engine();
    QV4::Scope scope(v4);
    QV4::ScopedObject o(scope);

    QV4::ObjectIterator it(scope, object, QV4::ObjectIterator::EnumerableOnly);
    QV4::ScopedString propertyName(scope);
    QV4::ScopedValue propertyValue(scope);
    while (1) {
        propertyName = it.nextPropertyNameAsString(propertyValue);
        if (!propertyName)
            break;

        // Check if this key exists yet
        int roleIndex = -1;

        // Add the value now
        if (const QV4::String *s = propertyValue->as<QV4::String>()) {
            const ListLayout::Role &r = m_layout->getRoleOrCreate(propertyName, ListLayout::Role::String);
            roleIndex = e->setStringProperty(r, s->toQString());
        } else if (propertyValue->isNumber()) {
            const ListLayout::Role &r = m_layout->getRoleOrCreate(propertyName, ListLayout::Role::Number);
            roleIndex = e->setDoubleProperty(r, propertyValue->asDouble());
        } else if (QV4::ArrayObject *a = propertyValue->as<QV4::ArrayObject>()) {
            const ListLayout::Role &r = m_layout->getRoleOrCreate(propertyName, ListLayout::Role::List);
            ListModel *subModel = new ListModel(r.subLayout, nullptr);

            int arrayLength = a->getLength();
            for (int j=0 ; j < arrayLength ; ++j) {
                o = a->get(j);
                subModel->append(o);
            }

            roleIndex = e->setListProperty(r, subModel);
        } else if (propertyValue->isBoolean()) {
            const ListLayout::Role &r = m_layout->getRoleOrCreate(propertyName, ListLayout::Role::Bool);
            roleIndex = e->setBoolProperty(r, propertyValue->booleanValue());
        } else if (QV4::DateObject *dd = propertyValue->as<QV4::DateObject>()) {
            const ListLayout::Role &r = m_layout->getRoleOrCreate(propertyName, ListLayout::Role::DateTime);
            QDateTime dt = dd->toQDateTime();
            roleIndex = e->setDateTimeProperty(r, dt);
        } else if (QV4::FunctionObject *f = propertyValue->as<QV4::FunctionObject>()) {
            const ListLayout::Role &r = m_layout->getRoleOrCreate(propertyName, ListLayout::Role::Function);
            QV4::ScopedFunctionObject func(scope, f);
            QJSValue jsv;
            QJSValuePrivate::setValue(&jsv, v4, func);
            roleIndex = e->setFunctionProperty(r, jsv);
        } else if (QV4::Object *o = propertyValue->as<QV4::Object>()) {
            if (QV4::QObjectWrapper *wrapper = o->as<QV4::QObjectWrapper>()) {
                QObject *o = wrapper->object();
                const ListLayout::Role &role = m_layout->getRoleOrCreate(propertyName, ListLayout::Role::QObject);
                if (role.type == ListLayout::Role::QObject)
                    roleIndex = e->setQObjectProperty(role, o);
            } else {
                const ListLayout::Role &role = m_layout->getRoleOrCreate(propertyName, ListLayout::Role::VariantMap);
                if (role.type == ListLayout::Role::VariantMap) {
                    QV4::ScopedObject obj(scope, o);
                    roleIndex = e->setVariantMapProperty(role, obj);
                }
            }
        } else if (propertyValue->isNullOrUndefined()) {
            const ListLayout::Role *r = m_layout->getExistingRole(propertyName);
            if (r)
                e->clearProperty(*r);
        }

        if (roleIndex != -1)
            roles->append(roleIndex);
    }

    if (ModelNodeMetaObject *mo = e->objectCache())
        mo->updateValues(*roles);
}

void ListModel::set(int elementIndex, QV4::Object *object, ListModel::SetElement reason)
{
    if (!object)
        return;

    ListElement *e = elements[elementIndex];

    QV4::ExecutionEngine *v4 = object->engine();
    QV4::Scope scope(v4);

    QV4::ObjectIterator it(scope, object, QV4::ObjectIterator::EnumerableOnly);
    QV4::ScopedString propertyName(scope);
    QV4::ScopedValue propertyValue(scope);
    QV4::ScopedObject o(scope);
    while (1) {
        propertyName = it.nextPropertyNameAsString(propertyValue);
        if (!propertyName)
            break;

        // Add the value now
        if (QV4::String *s = propertyValue->stringValue()) {
            const ListLayout::Role &r = m_layout->getRoleOrCreate(propertyName, ListLayout::Role::String);
            if (r.type == ListLayout::Role::String)
                e->setStringPropertyFast(r, s->toQString());
        } else if (propertyValue->isNumber()) {
            const ListLayout::Role &r = m_layout->getRoleOrCreate(propertyName, ListLayout::Role::Number);
            if (r.type == ListLayout::Role::Number) {
                e->setDoublePropertyFast(r, propertyValue->asDouble());
            }
        } else if (QV4::ArrayObject *a = propertyValue->as<QV4::ArrayObject>()) {
            const ListLayout::Role &r = m_layout->getRoleOrCreate(propertyName, ListLayout::Role::List);
            if (r.type == ListLayout::Role::List) {
                ListModel *subModel = new ListModel(r.subLayout, nullptr);

                int arrayLength = a->getLength();
                for (int j=0 ; j < arrayLength ; ++j) {
                    o = a->get(j);
                    subModel->append(o);
                }

                e->setListPropertyFast(r, subModel);
            }
        } else if (propertyValue->isBoolean()) {
            const ListLayout::Role &r = m_layout->getRoleOrCreate(propertyName, ListLayout::Role::Bool);
            if (r.type == ListLayout::Role::Bool) {
                e->setBoolPropertyFast(r, propertyValue->booleanValue());
            }
        } else if (QV4::DateObject *date = propertyValue->as<QV4::DateObject>()) {
            const ListLayout::Role &r = m_layout->getRoleOrCreate(propertyName, ListLayout::Role::DateTime);
            if (r.type == ListLayout::Role::DateTime) {
                QDateTime dt = date->toQDateTime();
                e->setDateTimePropertyFast(r, dt);
            }
        } else if (QV4::Object *o = propertyValue->as<QV4::Object>()) {
            if (QV4::QObjectWrapper *wrapper = o->as<QV4::QObjectWrapper>()) {
                QObject *o = wrapper->object();
                const ListLayout::Role &r = m_layout->getRoleOrCreate(propertyName, ListLayout::Role::QObject);
                if (r.type == ListLayout::Role::QObject)
                    e->setQObjectPropertyFast(r, o);
            } else {
                const ListLayout::Role &role = m_layout->getRoleOrCreate(propertyName, ListLayout::Role::VariantMap);
                if (role.type == ListLayout::Role::VariantMap)
                    e->setVariantMapFast(role, o);
            }
        } else if (propertyValue->isNullOrUndefined()) {
            if (reason == SetElement::WasJustInserted) {
                QQmlError err;
                auto memberName = propertyName->toString(m_modelCache->engine())->toQString();
                err.setDescription(QString::fromLatin1("%1 is %2. Adding an object with a %2 member does not create a role for it.").arg(memberName, propertyValue->isNull() ? QLatin1String("null") : QLatin1String("undefined")));
                qmlWarning(nullptr, err);
            } else {
                const ListLayout::Role *r = m_layout->getExistingRole(propertyName);
                if (r)
                    e->clearProperty(*r);
            }
        }
    }
}

QVector<std::function<void()>> ListModel::remove(int index, int count)
{
    QVector<std::function<void()>> toDestroy;
    auto layout = m_layout;
    for (int i=0 ; i < count ; ++i) {
        auto element = elements[index+i];
        toDestroy.append([element, layout](){
            element->destroy(layout);
            delete element;
        });
    }
    elements.remove(index, count);
    updateCacheIndices(index);
    return toDestroy;
}

void ListModel::insert(int elementIndex, QV4::Object *object)
{
    insertElement(elementIndex);
    set(elementIndex, object, SetElement::WasJustInserted);
}

int ListModel::append(QV4::Object *object)
{
    int elementIndex = appendElement();
    set(elementIndex, object, SetElement::WasJustInserted);
    return elementIndex;
}

int ListModel::setOrCreateProperty(int elementIndex, const QString &key, const QVariant &data)
{
    int roleIndex = -1;

    if (elementIndex >= 0 && elementIndex < elements.count()) {
        ListElement *e = elements[elementIndex];

        const ListLayout::Role *r = m_layout->getRoleOrCreate(key, data);
        if (r) {
            roleIndex = e->setVariantProperty(*r, data);

            ModelNodeMetaObject *cache = e->objectCache();

            if (roleIndex != -1 && cache)
                cache->updateValues(QVector<int>(1, roleIndex));
        }
    }

    return roleIndex;
}

int ListModel::setExistingProperty(int elementIndex, const QString &key, const QV4::Value &data, QV4::ExecutionEngine *eng)
{
    int roleIndex = -1;

    if (elementIndex >= 0 && elementIndex < elements.count()) {
        ListElement *e = elements[elementIndex];
        const ListLayout::Role *r = m_layout->getExistingRole(key);
        if (r)
            roleIndex = e->setJsProperty(*r, data, eng);
    }

    return roleIndex;
}

inline char *ListElement::getPropertyMemory(const ListLayout::Role &role)
{
    ListElement *e = this;
    int blockIndex = 0;
    while (blockIndex < role.blockIndex) {
        if (e->next == nullptr) {
            e->next = new ListElement;
            e->next->uid = uid;
        }
        e = e->next;
        ++blockIndex;
    }

    char *mem = &e->data[role.blockOffset];
    return mem;
}

ModelNodeMetaObject *ListElement::objectCache()
{
    if (!m_objectCache)
        return nullptr;
    return ModelNodeMetaObject::get(m_objectCache);
}

StringOrTranslation *ListElement::getStringProperty(const ListLayout::Role &role)
{
    char *mem = getPropertyMemory(role);
    StringOrTranslation *s = reinterpret_cast<StringOrTranslation *>(mem);
    return s;
}

QObject *ListElement::getQObjectProperty(const ListLayout::Role &role)
{
    char *mem = getPropertyMemory(role);
    QPointer<QObject> *o = reinterpret_cast<QPointer<QObject> *>(mem);
    return o->data();
}

QVariantMap *ListElement::getVariantMapProperty(const ListLayout::Role &role)
{
    QVariantMap *map = nullptr;

    char *mem = getPropertyMemory(role);
    if (isMemoryUsed<QVariantMap>(mem))
        map = reinterpret_cast<QVariantMap *>(mem);

    return map;
}

QDateTime *ListElement::getDateTimeProperty(const ListLayout::Role &role)
{
    QDateTime *dt = nullptr;

    char *mem = getPropertyMemory(role);
    if (isMemoryUsed<QDateTime>(mem))
        dt = reinterpret_cast<QDateTime *>(mem);

    return dt;
}

QJSValue *ListElement::getFunctionProperty(const ListLayout::Role &role)
{
    QJSValue *f = nullptr;

    char *mem = getPropertyMemory(role);
    if (isMemoryUsed<QJSValue>(mem))
        f = reinterpret_cast<QJSValue *>(mem);

    return f;
}

QPointer<QObject> *ListElement::getGuardProperty(const ListLayout::Role &role)
{
    char *mem = getPropertyMemory(role);

    bool existingGuard = false;
    for (size_t i=0 ; i < sizeof(QPointer<QObject>) ; ++i) {
        if (mem[i] != 0) {
            existingGuard = true;
            break;
        }
    }

    QPointer<QObject> *o = nullptr;

    if (existingGuard)
        o = reinterpret_cast<QPointer<QObject> *>(mem);

    return o;
}

ListModel *ListElement::getListProperty(const ListLayout::Role &role)
{
    char *mem = getPropertyMemory(role);
    ListModel **value = reinterpret_cast<ListModel **>(mem);
    return *value;
}

QVariant ListElement::getProperty(const ListLayout::Role &role, const QQmlListModel *owner, QV4::ExecutionEngine *eng)
{
    char *mem = getPropertyMemory(role);

    QVariant data;

    switch (role.type) {
        case ListLayout::Role::Number:
            {
                double *value = reinterpret_cast<double *>(mem);
                data = *value;
            }
            break;
        case ListLayout::Role::String:
            {
                StringOrTranslation *value = reinterpret_cast<StringOrTranslation *>(mem);
                if (value->isSet())
                    data = value->toString(owner);
            }
            break;
        case ListLayout::Role::Bool:
            {
                bool *value = reinterpret_cast<bool *>(mem);
                data = *value;
            }
            break;
        case ListLayout::Role::List:
            {
                ListModel **value = reinterpret_cast<ListModel **>(mem);
                ListModel *model = *value;

                if (model) {
                    if (model->m_modelCache == nullptr) {
                        model->m_modelCache = new QQmlListModel(owner, model, eng);
                        QQmlEngine::setContextForObject(model->m_modelCache, QQmlEngine::contextForObject(owner));
                    }

                    QObject *object = model->m_modelCache;
                    data = QVariant::fromValue(object);
                }
            }
            break;
        case ListLayout::Role::QObject:
            {
                QPointer<QObject> *guard = reinterpret_cast<QPointer<QObject> *>(mem);
                QObject *object = guard->data();
                if (object)
                    data = QVariant::fromValue(object);
            }
            break;
        case ListLayout::Role::VariantMap:
            {
                if (isMemoryUsed<QVariantMap>(mem)) {
                    QVariantMap *map = reinterpret_cast<QVariantMap *>(mem);
                    data = *map;
                }
            }
            break;
        case ListLayout::Role::DateTime:
            {
                if (isMemoryUsed<QDateTime>(mem)) {
                    QDateTime *dt = reinterpret_cast<QDateTime *>(mem);
                    data = *dt;
                }
            }
            break;
        case ListLayout::Role::Function:
            {
                if (isMemoryUsed<QJSValue>(mem)) {
                    QJSValue *func = reinterpret_cast<QJSValue *>(mem);
                    data = QVariant::fromValue(*func);
                }
            }
            break;
        default:
            break;
    }

    return data;
}

int ListElement::setStringProperty(const ListLayout::Role &role, const QString &s)
{
    int roleIndex = -1;

    if (role.type == ListLayout::Role::String) {
        char *mem = getPropertyMemory(role);
        StringOrTranslation *c = reinterpret_cast<StringOrTranslation *>(mem);
        bool changed;
        if (!c->isSet() || c->isTranslation())
            changed = true;
        else
            changed = c->asString().compare(s) != 0;
        c->setString(s);
        if (changed)
            roleIndex = role.index;
    }

    return roleIndex;
}

int ListElement::setDoubleProperty(const ListLayout::Role &role, double d)
{
    int roleIndex = -1;

    if (role.type == ListLayout::Role::Number) {
        char *mem = getPropertyMemory(role);
        double *value = reinterpret_cast<double *>(mem);
        bool changed = *value != d;
        *value = d;
        if (changed)
            roleIndex = role.index;
    }

    return roleIndex;
}

int ListElement::setBoolProperty(const ListLayout::Role &role, bool b)
{
    int roleIndex = -1;

    if (role.type == ListLayout::Role::Bool) {
        char *mem = getPropertyMemory(role);
        bool *value = reinterpret_cast<bool *>(mem);
        bool changed = *value != b;
        *value = b;
        if (changed)
            roleIndex = role.index;
    }

    return roleIndex;
}

int ListElement::setListProperty(const ListLayout::Role &role, ListModel *m)
{
    int roleIndex = -1;

    if (role.type == ListLayout::Role::List) {
        char *mem = getPropertyMemory(role);
        ListModel **value = reinterpret_cast<ListModel **>(mem);
        if (*value && *value != m) {
            (*value)->destroy();
            delete *value;
        }
        *value = m;
        roleIndex = role.index;
    }

    return roleIndex;
}

int ListElement::setQObjectProperty(const ListLayout::Role &role, QObject *o)
{
    int roleIndex = -1;

    if (role.type == ListLayout::Role::QObject) {
        char *mem = getPropertyMemory(role);
        QPointer<QObject> *g = reinterpret_cast<QPointer<QObject> *>(mem);
        bool existingGuard = false;
        for (size_t i=0 ; i < sizeof(QPointer<QObject>) ; ++i) {
            if (mem[i] != 0) {
                existingGuard = true;
                break;
            }
        }
        bool changed;
        if (existingGuard) {
            changed = g->data() != o;
            g->~QPointer();
        } else {
            changed = true;
        }
        new (mem) QPointer<QObject>(o);
        if (changed)
            roleIndex = role.index;
    }

    return roleIndex;
}

int ListElement::setVariantMapProperty(const ListLayout::Role &role, QV4::Object *o)
{
    int roleIndex = -1;

    if (role.type == ListLayout::Role::VariantMap) {
        char *mem = getPropertyMemory(role);
        if (isMemoryUsed<QVariantMap>(mem)) {
            QVariantMap *map = reinterpret_cast<QVariantMap *>(mem);
            map->~QMap();
        }
        new (mem) QVariantMap(o->engine()->variantMapFromJS(o));
        roleIndex = role.index;
    }

    return roleIndex;
}

int ListElement::setVariantMapProperty(const ListLayout::Role &role, QVariantMap *m)
{
    int roleIndex = -1;

    if (role.type == ListLayout::Role::VariantMap) {
        char *mem = getPropertyMemory(role);
        if (isMemoryUsed<QVariantMap>(mem)) {
            QVariantMap *map = reinterpret_cast<QVariantMap *>(mem);
            if (m && map->isSharedWith(*m))
                return roleIndex;
            map->~QMap();
        } else if (!m) {
            return roleIndex;
        }
        if (m)
            new (mem) QVariantMap(*m);
        else
            new (mem) QVariantMap;
        roleIndex = role.index;
    }

    return roleIndex;
}

int ListElement::setDateTimeProperty(const ListLayout::Role &role, const QDateTime &dt)
{
    int roleIndex = -1;

    if (role.type == ListLayout::Role::DateTime) {
        char *mem = getPropertyMemory(role);
        if (isMemoryUsed<QDateTime>(mem)) {
            QDateTime *dt = reinterpret_cast<QDateTime *>(mem);
            dt->~QDateTime();
        }
        new (mem) QDateTime(dt);
        roleIndex = role.index;
    }

    return roleIndex;
}

int ListElement::setFunctionProperty(const ListLayout::Role &role, const QJSValue &f)
{
    int roleIndex = -1;

    if (role.type == ListLayout::Role::Function) {
        char *mem = getPropertyMemory(role);
        if (isMemoryUsed<QJSValue>(mem)) {
            QJSValue *f = reinterpret_cast<QJSValue *>(mem);
            f->~QJSValue();
        }
        new (mem) QJSValue(f);
        roleIndex = role.index;
    }

    return roleIndex;
}

int ListElement::setTranslationProperty(const ListLayout::Role &role, const QV4::CompiledData::Binding *b)
{
    int roleIndex = -1;

    if (role.type == ListLayout::Role::String) {
        char *mem = getPropertyMemory(role);
        StringOrTranslation *s = reinterpret_cast<StringOrTranslation *>(mem);
        s->setTranslation(b);
        roleIndex = role.index;
    }

    return roleIndex;
}


void ListElement::setStringPropertyFast(const ListLayout::Role &role, const QString &s)
{
    char *mem = getPropertyMemory(role);
    new (mem) StringOrTranslation(s);
}

void ListElement::setDoublePropertyFast(const ListLayout::Role &role, double d)
{
    char *mem = getPropertyMemory(role);
    double *value = new (mem) double;
    *value = d;
}

void ListElement::setBoolPropertyFast(const ListLayout::Role &role, bool b)
{
    char *mem = getPropertyMemory(role);
    bool *value = new (mem) bool;
    *value = b;
}

void ListElement::setQObjectPropertyFast(const ListLayout::Role &role, QObject *o)
{
    char *mem = getPropertyMemory(role);
    new (mem) QPointer<QObject>(o);
}

void ListElement::setListPropertyFast(const ListLayout::Role &role, ListModel *m)
{
    char *mem = getPropertyMemory(role);
    ListModel **value = new (mem) ListModel *;
    *value = m;
}

void ListElement::setVariantMapFast(const ListLayout::Role &role, QV4::Object *o)
{
    char *mem = getPropertyMemory(role);
    QVariantMap *map = new (mem) QVariantMap;
    *map = o->engine()->variantMapFromJS(o);
}

void ListElement::setDateTimePropertyFast(const ListLayout::Role &role, const QDateTime &dt)
{
    char *mem = getPropertyMemory(role);
    new (mem) QDateTime(dt);
}

void ListElement::setFunctionPropertyFast(const ListLayout::Role &role, const QJSValue &f)
{
    char *mem = getPropertyMemory(role);
    new (mem) QJSValue(f);
}

void ListElement::clearProperty(const ListLayout::Role &role)
{
    switch (role.type) {
    case ListLayout::Role::String:
        setStringProperty(role, QString());
        break;
    case ListLayout::Role::Number:
        setDoubleProperty(role, 0.0);
        break;
    case ListLayout::Role::Bool:
        setBoolProperty(role, false);
        break;
    case ListLayout::Role::List:
        setListProperty(role, nullptr);
        break;
    case ListLayout::Role::QObject:
        setQObjectProperty(role, nullptr);
        break;
    case ListLayout::Role::DateTime:
        setDateTimeProperty(role, QDateTime());
        break;
    case ListLayout::Role::VariantMap:
        setVariantMapProperty(role, (QVariantMap *)nullptr);
        break;
    case ListLayout::Role::Function:
        setFunctionProperty(role, QJSValue());
        break;
    default:
        break;
    }
}

ListElement::ListElement()
{
    m_objectCache = nullptr;
    uid = uidCounter.fetchAndAddOrdered(1);
    next = nullptr;
    memset(data, 0, sizeof(data));
}

ListElement::ListElement(int existingUid)
{
    m_objectCache = nullptr;
    uid = existingUid;
    next = nullptr;
    memset(data, 0, sizeof(data));
}

ListElement::~ListElement()
{
    delete next;
}

QVector<int> ListElement::sync(ListElement *src, ListLayout *srcLayout, ListElement *target, ListLayout *targetLayout)
{
    QVector<int> changedRoles;
    for (int i=0 ; i < srcLayout->roleCount() ; ++i) {
        const ListLayout::Role &srcRole = srcLayout->getExistingRole(i);
        const ListLayout::Role &targetRole = targetLayout->getExistingRole(i);

        int roleIndex = -1;
        switch (srcRole.type) {
            case ListLayout::Role::List:
                {
                    ListModel *srcSubModel = src->getListProperty(srcRole);
                    ListModel *targetSubModel = target->getListProperty(targetRole);

                    if (srcSubModel) {
                        if (targetSubModel == nullptr) {
                            targetSubModel = new ListModel(targetRole.subLayout, nullptr);
                            target->setListPropertyFast(targetRole, targetSubModel);
                        }
                        if (ListModel::sync(srcSubModel, targetSubModel))
                            roleIndex = targetRole.index;
                    }
                }
                break;
            case ListLayout::Role::QObject:
                {
                    QObject *object = src->getQObjectProperty(srcRole);
                    roleIndex = target->setQObjectProperty(targetRole, object);
                }
                break;
            case ListLayout::Role::String:
            case ListLayout::Role::Number:
            case ListLayout::Role::Bool:
            case ListLayout::Role::DateTime:
            case ListLayout::Role::Function:
                {
                    QVariant v = src->getProperty(srcRole, nullptr, nullptr);
                    roleIndex = target->setVariantProperty(targetRole, v);
                }
                break;
            case ListLayout::Role::VariantMap:
                {
                    QVariantMap *map = src->getVariantMapProperty(srcRole);
                    roleIndex = target->setVariantMapProperty(targetRole, map);
                }
                break;
            default:
                break;
        }
        if (roleIndex >= 0)
            changedRoles << roleIndex;
    }

    return changedRoles;
}

void ListElement::destroy(ListLayout *layout)
{
    if (layout) {
        for (int i=0 ; i < layout->roleCount() ; ++i) {
            const ListLayout::Role &r = layout->getExistingRole(i);

            switch (r.type) {
                case ListLayout::Role::String:
                    {
                        StringOrTranslation *string = getStringProperty(r);
                        if (string)
                            string->~StringOrTranslation();
                    }
                    break;
                case ListLayout::Role::List:
                    {
                        ListModel *model = getListProperty(r);
                        if (model) {
                            model->destroy();
                            delete model;
                        }
                    }
                    break;
                case ListLayout::Role::QObject:
                    {
                        QPointer<QObject> *guard = getGuardProperty(r);
                        if (guard)
                            guard->~QPointer();
                    }
                    break;
                case ListLayout::Role::VariantMap:
                    {
                        QVariantMap *map = getVariantMapProperty(r);
                        if (map)
                            map->~QMap();
                    }
                    break;
                case ListLayout::Role::DateTime:
                    {
                        QDateTime *dt = getDateTimeProperty(r);
                        if (dt)
                            dt->~QDateTime();
                    }
                    break;
                case ListLayout::Role::Function:
                    {
                        QJSValue *f = getFunctionProperty(r);
                        if (f)
                            f->~QJSValue();
                    }
                    break;
                default:
                    // other types don't need explicit cleanup.
                    break;
            }
        }

        if (m_objectCache) {
            m_objectCache->~QObject();
            operator delete(m_objectCache);
        }
    }

    if (next)
        next->destroy(nullptr);
    uid = -1;
}

int ListElement::setVariantProperty(const ListLayout::Role &role, const QVariant &d)
{
    int roleIndex = -1;

    switch (role.type) {
        case ListLayout::Role::Number:
            roleIndex = setDoubleProperty(role, d.toDouble());
            break;
        case ListLayout::Role::String:
            if (d.userType() == qMetaTypeId<const QV4::CompiledData::Binding *>())
                roleIndex = setTranslationProperty(role, d.value<const QV4::CompiledData::Binding*>());
            else
                roleIndex = setStringProperty(role, d.toString());
            break;
        case ListLayout::Role::Bool:
            roleIndex = setBoolProperty(role, d.toBool());
            break;
        case ListLayout::Role::List:
            roleIndex = setListProperty(role, d.value<ListModel *>());
            break;
        case ListLayout::Role::VariantMap: {
                QVariantMap map = d.toMap();
                roleIndex = setVariantMapProperty(role, &map);
            }
            break;
        case ListLayout::Role::DateTime:
            roleIndex = setDateTimeProperty(role, d.toDateTime());
            break;
        case ListLayout::Role::Function:
            roleIndex = setFunctionProperty(role, d.value<QJSValue>());
            break;
        default:
            break;
    }

    return roleIndex;
}

int ListElement::setJsProperty(const ListLayout::Role &role, const QV4::Value &d, QV4::ExecutionEngine *eng)
{
    // Check if this key exists yet
    int roleIndex = -1;

    QV4::Scope scope(eng);

    // Add the value now
    if (d.isString()) {
        QString qstr = d.toQString();
        roleIndex = setStringProperty(role, qstr);
    } else if (d.isNumber()) {
        roleIndex = setDoubleProperty(role, d.asDouble());
    } else if (d.as<QV4::ArrayObject>()) {
        QV4::ScopedArrayObject a(scope, d);
        if (role.type == ListLayout::Role::List) {
            QV4::Scope scope(a->engine());
            QV4::ScopedObject o(scope);

            ListModel *subModel = new ListModel(role.subLayout, nullptr);
            int arrayLength = a->getLength();
            for (int j=0 ; j < arrayLength ; ++j) {
                o = a->get(j);
                subModel->append(o);
            }
            roleIndex = setListProperty(role, subModel);
        } else {
            qmlWarning(nullptr) << QStringLiteral("Can't assign to existing role '%1' of different type [%2 -> %3]").arg(role.name).arg(roleTypeName(role.type)).arg(roleTypeName(ListLayout::Role::List));
        }
    } else if (d.isBoolean()) {
        roleIndex = setBoolProperty(role, d.booleanValue());
    } else if (d.as<QV4::DateObject>()) {
        QV4::Scoped<QV4::DateObject> dd(scope, d);
        QDateTime dt = dd->toQDateTime();
        roleIndex = setDateTimeProperty(role, dt);
    } else if (d.as<QV4::FunctionObject>()) {
        QV4::ScopedFunctionObject f(scope, d);
        QJSValue jsv;
        QJSValuePrivate::setValue(&jsv, eng, f);
        roleIndex = setFunctionProperty(role, jsv);
    } else if (d.isObject()) {
        QV4::ScopedObject o(scope, d);
        QV4::QObjectWrapper *wrapper = o->as<QV4::QObjectWrapper>();
        if (role.type == ListLayout::Role::QObject && wrapper) {
            QObject *o = wrapper->object();
            roleIndex = setQObjectProperty(role, o);
        } else if (role.type == ListLayout::Role::VariantMap) {
            roleIndex = setVariantMapProperty(role, o);
        }
    } else if (d.isNullOrUndefined()) {
        clearProperty(role);
    }

    return roleIndex;
}

ModelNodeMetaObject::ModelNodeMetaObject(QObject *object, QQmlListModel *model, int elementIndex)
: QQmlOpenMetaObject(object), m_enabled(false), m_model(model), m_elementIndex(elementIndex), m_initialized(false)
{}

void ModelNodeMetaObject::initialize()
{
    const int roleCount = m_model->m_listModel->roleCount();
    QVector<QByteArray> properties;
    properties.reserve(roleCount);
    for (int i = 0 ; i < roleCount ; ++i) {
        const ListLayout::Role &role = m_model->m_listModel->getExistingRole(i);
        QByteArray name = role.name.toUtf8();
        properties << name;
    }
    type()->createProperties(properties);
    updateValues();
    m_enabled = true;
}

ModelNodeMetaObject::~ModelNodeMetaObject()
{
}

QAbstractDynamicMetaObject *ModelNodeMetaObject::toDynamicMetaObject(QObject *object)
{
    if (!m_initialized) {
        m_initialized = true;
        initialize();
    }
    return QQmlOpenMetaObject::toDynamicMetaObject(object);
}

ModelNodeMetaObject *ModelNodeMetaObject::get(QObject *obj)
{
    QObjectPrivate *op = QObjectPrivate::get(obj);
    return static_cast<ModelNodeMetaObject*>(op->metaObject);
}

void ModelNodeMetaObject::updateValues()
{
    const int roleCount = m_model->m_listModel->roleCount();
    if (!m_initialized) {
        if (roleCount) {
            Q_ALLOCA_VAR(int, changedRoles, roleCount * sizeof(int));
            for (int i = 0; i < roleCount; ++i)
                changedRoles[i] = i;
            emitDirectNotifies(changedRoles, roleCount);
        }
        return;
    }
    for (int i=0 ; i < roleCount ; ++i) {
        const ListLayout::Role &role = m_model->m_listModel->getExistingRole(i);
        QByteArray name = role.name.toUtf8();
        const QVariant &data = m_model->data(m_elementIndex, i);
        setValue(name, data, role.type == ListLayout::Role::List);
    }
}

void ModelNodeMetaObject::updateValues(const QVector<int> &roles)
{
    if (!m_initialized) {
        emitDirectNotifies(roles.constData(), roles.count());
        return;
    }
    int roleCount = roles.count();
    for (int i=0 ; i < roleCount ; ++i) {
        int roleIndex = roles.at(i);
        const ListLayout::Role &role = m_model->m_listModel->getExistingRole(roleIndex);
        QByteArray name = role.name.toUtf8();
        const QVariant &data = m_model->data(m_elementIndex, roleIndex);
        setValue(name, data, role.type == ListLayout::Role::List);
    }
}

void ModelNodeMetaObject::propertyWritten(int index)
{
    if (!m_enabled)
        return;

    QString propName = QString::fromUtf8(name(index));
    const QVariant value = this->value(index);

    QV4::Scope scope(m_model->engine());
    QV4::ScopedValue v(scope, scope.engine->fromVariant(value));

    int roleIndex = m_model->m_listModel->setExistingProperty(m_elementIndex, propName, v, scope.engine);
    if (roleIndex != -1)
        m_model->emitItemsChanged(m_elementIndex, 1, QVector<int>(1, roleIndex));
}

// Does the emission of the notifiers when we haven't created the meta-object yet
void ModelNodeMetaObject::emitDirectNotifies(const int *changedRoles, int roleCount)
{
    Q_ASSERT(!m_initialized);
    QQmlData *ddata = QQmlData::get(object(), /*create*/false);
    if (!ddata)
        return;
    // There's nothing to emit if we're a list model in a worker thread.
    if (!qmlEngine(m_model))
        return;
    for (int i = 0; i < roleCount; ++i) {
        const int changedRole = changedRoles[i];
        QQmlNotifier::notify(ddata, changedRole);
    }
}

namespace QV4 {

bool ModelObject::virtualPut(Managed *m, PropertyKey id, const Value &value, Value *receiver)
{
    if (!id.isString())
        return Object::virtualPut(m, id, value, receiver);
    QString propName = id.toQString();

    ModelObject *that = static_cast<ModelObject*>(m);

    ExecutionEngine *eng = that->engine();
    const int elementIndex = that->d()->elementIndex();
    int roleIndex = that->d()->m_model->m_listModel->setExistingProperty(elementIndex, propName, value, eng);
    if (roleIndex != -1)
        that->d()->m_model->emitItemsChanged(elementIndex, 1, QVector<int>(1, roleIndex));

    ModelNodeMetaObject *mo = ModelNodeMetaObject::get(that->object());
    if (mo->initialized())
        mo->emitPropertyNotification(propName.toUtf8());
    return true;
}

ReturnedValue ModelObject::virtualGet(const Managed *m, PropertyKey id, const Value *receiver, bool *hasProperty)
{
    if (!id.isString())
        return QObjectWrapper::virtualGet(m, id, receiver, hasProperty);

    const ModelObject *that = static_cast<const ModelObject*>(m);
    Scope scope(that);
    ScopedString name(scope, id.asStringOrSymbol());
    const ListLayout::Role *role = that->d()->m_model->m_listModel->getExistingRole(name);
    if (!role)
        return QObjectWrapper::virtualGet(m, id, receiver, hasProperty);
    if (hasProperty)
        *hasProperty = true;

    if (QQmlEngine *qmlEngine = that->engine()->qmlEngine()) {
        QQmlEnginePrivate *ep = QQmlEnginePrivate::get(qmlEngine);
        if (ep && ep->propertyCapture)
            ep->propertyCapture->captureProperty(that->object(), -1, role->index, /*doNotify=*/ false);
    }

    const int elementIndex = that->d()->elementIndex();
    QVariant value = that->d()->m_model->data(elementIndex, role->index);
    return that->engine()->fromVariant(value);
}

ReturnedValue ModelObject::virtualResolveLookupGetter(const Object *object, ExecutionEngine *engine, Lookup *lookup)
{
    lookup->getter = Lookup::getterFallback;
    return lookup->getter(lookup, engine, *object);
}

struct ModelObjectOwnPropertyKeyIterator : ObjectOwnPropertyKeyIterator
{
    int roleNameIndex = 0;
    ~ModelObjectOwnPropertyKeyIterator() override = default;
    PropertyKey next(const Object *o, Property *pd = nullptr, PropertyAttributes *attrs = nullptr) override;

};

PropertyKey ModelObjectOwnPropertyKeyIterator::next(const Object *o, Property *pd, PropertyAttributes *attrs)
{
    const ModelObject *that = static_cast<const ModelObject *>(o);

    ExecutionEngine *v4 = that->engine();
    if (roleNameIndex < that->listModel()->roleCount()) {
        Scope scope(that->engine());
        const ListLayout::Role &role = that->listModel()->getExistingRole(roleNameIndex);
        ++roleNameIndex;
        ScopedString roleName(scope, v4->newString(role.name));
        if (attrs)
            *attrs = QV4::Attr_Data;
        if (pd) {

            QVariant value = that->d()->m_model->data(that->d()->elementIndex(), role.index);
            if (auto recursiveListModel = qvariant_cast<QQmlListModel*>(value)) {
                auto size = recursiveListModel->count();
                auto array = ScopedArrayObject{scope, v4->newArrayObject(size)};
                for (auto i = 0; i < size; i++) {
                    array->arrayPut(i, QJSValuePrivate::convertedToValue(v4, recursiveListModel->get(i)));
                }
                pd->value = array;
            } else {
                pd->value = v4->fromVariant(value);
            }
        }
        return roleName->toPropertyKey();
    }

    // Fall back to QV4::Object as opposed to QV4::QObjectWrapper otherwise it will add
    // unnecessary entries that relate to the roles used. These just create extra work
    // later on as they will just be ignored.
    return ObjectOwnPropertyKeyIterator::next(o, pd, attrs);
}

OwnPropertyKeyIterator *ModelObject::virtualOwnPropertyKeys(const Object *m, Value *target)
{
    *target = *m;
    return new ModelObjectOwnPropertyKeyIterator;
}

DEFINE_OBJECT_VTABLE(ModelObject);

} // namespace QV4

DynamicRoleModelNode::DynamicRoleModelNode(QQmlListModel *owner, int uid) : m_owner(owner), m_uid(uid), m_meta(new DynamicRoleModelNodeMetaObject(this))
{
    setNodeUpdatesEnabled(true);
}

DynamicRoleModelNode *DynamicRoleModelNode::create(const QVariantMap &obj, QQmlListModel *owner)
{
    DynamicRoleModelNode *object = new DynamicRoleModelNode(owner, uidCounter.fetchAndAddOrdered(1));
    QVector<int> roles;
    object->updateValues(obj, roles);
    return object;
}

QVector<int> DynamicRoleModelNode::sync(DynamicRoleModelNode *src, DynamicRoleModelNode *target)
{
    QVector<int> changedRoles;
    for (int i = 0; i < src->m_meta->count(); ++i) {
        const QByteArray &name = src->m_meta->name(i);
        QVariant value = src->m_meta->value(i);

        QQmlListModel *srcModel = qobject_cast<QQmlListModel *>(value.value<QObject *>());
        QQmlListModel *targetModel = qobject_cast<QQmlListModel *>(target->m_meta->value(i).value<QObject *>());

        bool modelHasChanges = false;
        if (srcModel) {
            if (targetModel == nullptr)
                targetModel = QQmlListModel::createWithOwner(target->m_owner);

            modelHasChanges = QQmlListModel::sync(srcModel, targetModel);

            QObject *targetModelObject = targetModel;
            value = QVariant::fromValue(targetModelObject);
        } else if (targetModel) {
            delete targetModel;
        }

        if (target->setValue(name, value) || modelHasChanges)
            changedRoles << target->m_owner->m_roles.indexOf(QString::fromUtf8(name));
    }
    return changedRoles;
}

void DynamicRoleModelNode::updateValues(const QVariantMap &object, QVector<int> &roles)
{
    for (auto it = object.cbegin(), end = object.cend(); it != end; ++it) {
        const QString &key = it.key();

        int roleIndex = m_owner->m_roles.indexOf(key);
        if (roleIndex == -1) {
            roleIndex = m_owner->m_roles.count();
            m_owner->m_roles.append(key);
        }

        QVariant value = it.value();

        // A JS array/object is translated into a (hierarchical) QQmlListModel,
        // so translate to a variant map/list first with toVariant().
        if (value.userType() == qMetaTypeId<QJSValue>())
            value = value.value<QJSValue>().toVariant();

        if (value.userType() == QMetaType::QVariantList) {
            QQmlListModel *subModel = QQmlListModel::createWithOwner(m_owner);

            QVariantList subArray = value.toList();
            QVariantList::const_iterator subIt = subArray.cbegin();
            QVariantList::const_iterator subEnd = subArray.cend();
            while (subIt != subEnd) {
                const QVariantMap &subObject = subIt->toMap();
                subModel->m_modelObjects.append(DynamicRoleModelNode::create(subObject, subModel));
                ++subIt;
            }

            QObject *subModelObject = subModel;
            value = QVariant::fromValue(subModelObject);
        }

        const QByteArray &keyUtf8 = key.toUtf8();

        QQmlListModel *existingModel = qobject_cast<QQmlListModel *>(m_meta->value(keyUtf8).value<QObject *>());
        delete existingModel;

        if (m_meta->setValue(keyUtf8, value))
            roles << roleIndex;
    }
}

DynamicRoleModelNodeMetaObject::DynamicRoleModelNodeMetaObject(DynamicRoleModelNode *object)
    : QQmlOpenMetaObject(object), m_enabled(false), m_owner(object)
{
}

DynamicRoleModelNodeMetaObject::~DynamicRoleModelNodeMetaObject()
{
    for (int i=0 ; i < count() ; ++i) {
        QQmlListModel *subModel = qobject_cast<QQmlListModel *>(value(i).value<QObject *>());
        delete subModel;
    }
}

void DynamicRoleModelNodeMetaObject::propertyWrite(int index)
{
    if (!m_enabled)
        return;

    QVariant v = value(index);
    QQmlListModel *model = qobject_cast<QQmlListModel *>(v.value<QObject *>());
    delete model;
}

void DynamicRoleModelNodeMetaObject::propertyWritten(int index)
{
    if (!m_enabled)
        return;

    QQmlListModel *parentModel = m_owner->m_owner;

    QVariant v = value(index);

    // A JS array/object is translated into a (hierarchical) QQmlListModel,
    // so translate to a variant map/list first with toVariant().
    if (v.userType() == qMetaTypeId<QJSValue>())
        v= v.value<QJSValue>().toVariant();

    if (v.userType() == QMetaType::QVariantList) {
        QQmlListModel *subModel = QQmlListModel::createWithOwner(parentModel);

        QVariantList subArray = v.toList();
        QVariantList::const_iterator subIt = subArray.cbegin();
        QVariantList::const_iterator subEnd = subArray.cend();
        while (subIt != subEnd) {
            const QVariantMap &subObject = subIt->toMap();
            subModel->m_modelObjects.append(DynamicRoleModelNode::create(subObject, subModel));
            ++subIt;
        }

        QObject *subModelObject = subModel;
        v = QVariant::fromValue(subModelObject);

        setValue(index, v);
    }

    int elementIndex = parentModel->m_modelObjects.indexOf(m_owner);
    if (elementIndex != -1) {
        int roleIndex = parentModel->m_roles.indexOf(QString::fromLatin1(name(index).constData()));
        if (roleIndex != -1)
            parentModel->emitItemsChanged(elementIndex, 1, QVector<int>(1, roleIndex));
    }
}

/*!
    \qmltype ListModel
    \instantiates QQmlListModel
    \inqmlmodule QtQml.Models
    \ingroup qtquick-models
    \brief Defines a free-form list data source.

    The ListModel is a simple container of ListElement definitions, each
    containing data roles. The contents can be defined dynamically, or
    explicitly in QML.

    The number of elements in the model can be obtained from its \l count property.
    A number of familiar methods are also provided to manipulate the contents of the
    model, including append(), insert(), move(), remove() and set(). These methods
    accept dictionaries as their arguments; these are translated to ListElement objects
    by the model.

    Elements can be manipulated via the model using the setProperty() method, which
    allows the roles of the specified element to be set and changed.

    \section1 Example Usage

    The following example shows a ListModel containing three elements, with the roles
    "name" and "cost".

    \div {class="float-right"}
    \inlineimage listmodel.png
    \enddiv

    \snippet qml/listmodel/listmodel.qml 0

    Roles (properties) in each element must begin with a lower-case letter and
    should be common to all elements in a model. The ListElement documentation
    provides more guidelines for how elements should be defined.

    Since the example model contains an \c id property, it can be referenced
    by views, such as the ListView in this example:

    \snippet qml/listmodel/listmodel-simple.qml 0
    \dots 8
    \snippet qml/listmodel/listmodel-simple.qml 1

    It is possible for roles to contain list data.  In the following example we
    create a list of fruit attributes:

    \snippet qml/listmodel/listmodel-nested.qml model

    The delegate displays all the fruit attributes:

    \div {class="float-right"}
    \inlineimage listmodel-nested.png
    \enddiv

    \snippet qml/listmodel/listmodel-nested.qml delegate

    \section1 Modifying List Models

    The content of a ListModel may be created and modified using the clear(),
    append(), set(), insert() and setProperty() methods.  For example:

    \snippet qml/listmodel/listmodel-modify.qml delegate

    Note that when creating content dynamically the set of available properties
    cannot be changed once set. Whatever properties are first added to the model
    are the only permitted properties in the model.

    \section1 Using Threaded List Models with WorkerScript

    ListModel can be used together with WorkerScript access a list model
    from multiple threads. This is useful if list modifications are
    synchronous and take some time: the list operations can be moved to a
    different thread to avoid blocking of the main GUI thread.

    Here is an example that uses WorkerScript to periodically append the
    current time to a list model:

    \snippet ../../examples/quick/threading/threadedlistmodel/timedisplay.qml 0

    The included file, \tt dataloader.mjs, looks like this:

    \snippet ../../examples/quick/threading/threadedlistmodel/dataloader.mjs 0

    The timer in the main example sends messages to the worker script by calling
    \l WorkerScript::sendMessage(). When this message is received,
    \c WorkerScript.onMessage() is invoked in \c dataloader.mjs,
    which appends the current time to the list model.

    Note the call to sync() from the external thread.
    You must call sync() or else the changes made to the list from that
    thread will not be reflected in the list model in the main thread.

    \sa {qml-data-models}{Data Models}, {Qt Quick Examples - Threading}, {Qt QML}
*/

QQmlListModel::QQmlListModel(QObject *parent)
: QAbstractListModel(parent)
{
    m_mainThread = true;
    m_primary = true;
    m_agent = nullptr;
    m_dynamicRoles = false;

    m_layout = new ListLayout;
    m_listModel = new ListModel(m_layout, this);

    m_engine = nullptr;
}

QQmlListModel::QQmlListModel(const QQmlListModel *owner, ListModel *data, QV4::ExecutionEngine *engine, QObject *parent)
: QAbstractListModel(parent)
{
    m_mainThread = owner->m_mainThread;
    m_primary = false;
    m_agent = owner->m_agent;

    Q_ASSERT(owner->m_dynamicRoles == false);
    m_dynamicRoles = false;
    m_layout = nullptr;
    m_listModel = data;

    m_engine = engine;
    m_compilationUnit = owner->m_compilationUnit;
}

QQmlListModel::QQmlListModel(QQmlListModel *orig, QQmlListModelWorkerAgent *agent)
: QAbstractListModel(agent)
{
    m_mainThread = false;
    m_primary = true;
    m_agent = agent;
    m_dynamicRoles = orig->m_dynamicRoles;

    m_layout = new ListLayout(orig->m_layout);
    m_listModel = new ListModel(m_layout, this);

    if (m_dynamicRoles)
        sync(orig, this);
    else
        ListModel::sync(orig->m_listModel, m_listModel);

    m_engine = nullptr;
    m_compilationUnit = orig->m_compilationUnit;
}

QQmlListModel::~QQmlListModel()
{
    qDeleteAll(m_modelObjects);

    if (m_primary) {
        m_listModel->destroy();
        delete m_listModel;

        if (m_mainThread && m_agent) {
            m_agent->modelDestroyed();
            m_agent->release();
        }
    }

    m_listModel = nullptr;

    delete m_layout;
    m_layout = nullptr;
}

QQmlListModel *QQmlListModel::createWithOwner(QQmlListModel *newOwner)
{
    QQmlListModel *model = new QQmlListModel;

    model->m_mainThread = newOwner->m_mainThread;
    model->m_engine = newOwner->m_engine;
    model->m_agent = newOwner->m_agent;
    model->m_dynamicRoles = newOwner->m_dynamicRoles;

    if (model->m_mainThread && model->m_agent)
        model->m_agent->addref();

    QQmlEngine::setContextForObject(model, QQmlEngine::contextForObject(newOwner));

    return model;
}

QV4::ExecutionEngine *QQmlListModel::engine() const
{
    if (m_engine == nullptr) {
        m_engine  = qmlEngine(this)->handle();
    }

    return m_engine;
}

bool QQmlListModel::sync(QQmlListModel *src, QQmlListModel *target)
{
    Q_ASSERT(src->m_dynamicRoles && target->m_dynamicRoles);

    bool hasChanges = false;

    target->m_roles = src->m_roles;

    // Build hash of elements <-> uid for each of the lists
    QHash<int, ElementSync> elementHash;
    for (int i = 0 ; i < target->m_modelObjects.count(); ++i) {
        DynamicRoleModelNode *e = target->m_modelObjects.at(i);
        int uid = e->getUid();
        ElementSync sync;
        sync.target = e;
        sync.targetIndex = i;
        elementHash.insert(uid, sync);
    }
    for (int i = 0 ; i < src->m_modelObjects.count(); ++i) {
        DynamicRoleModelNode *e = src->m_modelObjects.at(i);
        int uid = e->getUid();

        QHash<int, ElementSync>::iterator it = elementHash.find(uid);
        if (it == elementHash.end()) {
            ElementSync sync;
            sync.src = e;
            sync.srcIndex = i;
            elementHash.insert(uid, sync);
        } else {
            ElementSync &sync = it.value();
            sync.src = e;
            sync.srcIndex = i;
        }
    }

    // Get list of elements that are in the target but no longer in the source. These get deleted first.
    int rowsRemoved = 0;
    for (int i = 0 ; i < target->m_modelObjects.count() ; ++i) {
        DynamicRoleModelNode *element = target->m_modelObjects.at(i);
        ElementSync &s = elementHash.find(element->getUid()).value();
        Q_ASSERT(s.targetIndex >= 0);
        // need to update the targetIndex, to keep it correct after removals
        s.targetIndex -= rowsRemoved;
        if (s.src == nullptr) {
            Q_ASSERT(s.targetIndex == i);
            hasChanges = true;
            target->beginRemoveRows(QModelIndex(), i, i);
            target->m_modelObjects.remove(i, 1);
            target->endRemoveRows();
            delete s.target;
            ++rowsRemoved;
            --i;
            continue;
        }
    }

    // Clear the target list, and append in correct order from the source
    target->m_modelObjects.clear();
    for (int i = 0 ; i < src->m_modelObjects.count() ; ++i) {
        DynamicRoleModelNode *element = src->m_modelObjects.at(i);
        ElementSync &s = elementHash.find(element->getUid()).value();
        Q_ASSERT(s.srcIndex >= 0);
        DynamicRoleModelNode *targetElement = s.target;
        if (targetElement == nullptr) {
            targetElement = new DynamicRoleModelNode(target, element->getUid());
        }
        s.changedRoles = DynamicRoleModelNode::sync(element, targetElement);
        target->m_modelObjects.append(targetElement);
    }

    // now emit the change notifications required. This can be safely done, as we're only emitting changes, moves and inserts,
    // so the model indices can't be out of bounds
    //
    // to ensure things are kept in the correct order, emit inserts and moves first. This shouls ensure all persistent
    // model indices are updated correctly
    int rowsInserted = 0;
    for (int i = 0 ; i < target->m_modelObjects.count() ; ++i) {
        DynamicRoleModelNode *element = target->m_modelObjects.at(i);
        ElementSync &s = elementHash.find(element->getUid()).value();
        Q_ASSERT(s.srcIndex >= 0);
        s.srcIndex += rowsInserted;
        if (s.srcIndex != s.targetIndex) {
            if (s.targetIndex == -1) {
                target->beginInsertRows(QModelIndex(), i, i);
                target->endInsertRows();
            } else {
                target->beginMoveRows(QModelIndex(), i, i, QModelIndex(), s.srcIndex);
                target->endMoveRows();
            }
            hasChanges = true;
            ++rowsInserted;
        }
        if (s.targetIndex != -1 && !s.changedRoles.isEmpty()) {
            QModelIndex idx = target->createIndex(i, 0);
            emit target->dataChanged(idx, idx, s.changedRoles);
            hasChanges = true;
        }
    }
    return hasChanges;
}

void QQmlListModel::emitItemsChanged(int index, int count, const QVector<int> &roles)
{
    if (count <= 0)
        return;

    if (m_mainThread)
        emit dataChanged(createIndex(index, 0), createIndex(index + count - 1, 0), roles);;
}

void QQmlListModel::emitItemsAboutToBeInserted(int index, int count)
{
    Q_ASSERT(index >= 0 && count >= 0);
    if (m_mainThread)
        beginInsertRows(QModelIndex(), index, index + count - 1);
}

void QQmlListModel::emitItemsInserted()
{
    if (m_mainThread) {
        endInsertRows();
        emit countChanged();
    }
}

QQmlListModelWorkerAgent *QQmlListModel::agent()
{
    if (m_agent)
        return m_agent;

    m_agent = new QQmlListModelWorkerAgent(this);
    return m_agent;
}

QModelIndex QQmlListModel::index(int row, int column, const QModelIndex &parent) const
{
    return row >= 0 && row < count() && column == 0 && !parent.isValid()
            ? createIndex(row, column)
            : QModelIndex();
}

int QQmlListModel::rowCount(const QModelIndex &parent) const
{
    return !parent.isValid() ? count() : 0;
}

QVariant QQmlListModel::data(const QModelIndex &index, int role) const
{
    return data(index.row(), role);
}

bool QQmlListModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
    const int row = index.row();
    if (row >= count() || row < 0)
        return false;

    if (m_dynamicRoles) {
        const QByteArray property = m_roles.at(role).toUtf8();
        if (m_modelObjects[row]->setValue(property, value)) {
            emitItemsChanged(row, 1, QVector<int>(1, role));
            return true;
        }
    } else {
        const ListLayout::Role &r = m_listModel->getExistingRole(role);
        const int roleIndex = m_listModel->setOrCreateProperty(row, r.name, value);
        if (roleIndex != -1) {
            emitItemsChanged(row, 1, QVector<int>(1, role));
            return true;
        }
    }

    return false;
}

QVariant QQmlListModel::data(int index, int role) const
{
    QVariant v;

    if (index >= count() || index < 0)
        return v;

    if (m_dynamicRoles)
        v = m_modelObjects[index]->getValue(m_roles[role]);
    else
        v = m_listModel->getProperty(index, role, this, engine());

    return v;
}

QHash<int, QByteArray> QQmlListModel::roleNames() const
{
    QHash<int, QByteArray> roleNames;

    if (m_dynamicRoles) {
        for (int i = 0 ; i < m_roles.count() ; ++i)
            roleNames.insert(i, m_roles.at(i).toUtf8());
    } else {
        for (int i = 0 ; i < m_listModel->roleCount() ; ++i) {
            const ListLayout::Role &r = m_listModel->getExistingRole(i);
            roleNames.insert(i, r.name.toUtf8());
        }
    }

    return roleNames;
}

/*!
    \qmlproperty bool ListModel::dynamicRoles

    By default, the type of a role is fixed the first time
    the role is used. For example, if you create a role called
    "data" and assign a number to it, you can no longer assign
    a string to the "data" role. However, when the dynamicRoles
    property is enabled, the type of a given role is not fixed
    and can be different between elements.

    The dynamicRoles property must be set before any data is
    added to the ListModel, and must be set from the main
    thread.

    A ListModel that has data statically defined (via the
    ListElement QML syntax) cannot have the dynamicRoles
    property enabled.

    There is a significant performance cost to using a
    ListModel with dynamic roles enabled. The cost varies
    from platform to platform but is typically somewhere
    between 4-6x slower than using static role types.

    Due to the performance cost of using dynamic roles,
    they are disabled by default.
*/
void QQmlListModel::setDynamicRoles(bool enableDynamicRoles)
{
    if (m_mainThread && m_agent == nullptr) {
        if (enableDynamicRoles) {
            if (m_layout->roleCount())
                qmlWarning(this) << tr("unable to enable dynamic roles as this model is not empty");
            else
                m_dynamicRoles = true;
        } else {
            if (m_roles.count()) {
                qmlWarning(this) << tr("unable to enable static roles as this model is not empty");
            } else {
                m_dynamicRoles = false;
            }
        }
    } else {
        qmlWarning(this) << tr("dynamic role setting must be made from the main thread, before any worker scripts are created");
    }
}

/*!
    \qmlproperty int ListModel::count
    The number of data entries in the model.
*/
int QQmlListModel::count() const
{
    return m_dynamicRoles ? m_modelObjects.count() : m_listModel->elementCount();
}

/*!
    \qmlmethod ListModel::clear()

    Deletes all content from the model.

    \sa append(), remove()
*/
void QQmlListModel::clear()
{
    removeElements(0, count());
}

/*!
    \qmlmethod ListModel::remove(int index, int count = 1)

    Deletes the content at \a index from the model.

    \sa clear()
*/
void QQmlListModel::remove(QQmlV4Function *args)
{
    int argLength = args->length();

    if (argLength == 1 || argLength == 2) {
        QV4::Scope scope(args->v4engine());
        int index = QV4::ScopedValue(scope, (*args)[0])->toInt32();
        int removeCount = (argLength == 2 ? QV4::ScopedValue(scope, (*args)[1])->toInt32() : 1);

        if (index < 0 || index+removeCount > count() || removeCount <= 0) {
            qmlWarning(this) << tr("remove: indices [%1 - %2] out of range [0 - %3]").arg(index).arg(index+removeCount).arg(count());
            return;
        }

        removeElements(index, removeCount);
    } else {
        qmlWarning(this) << tr("remove: incorrect number of arguments");
    }
}

void QQmlListModel::removeElements(int index, int removeCount)
{
    Q_ASSERT(index >= 0 && removeCount >= 0);

    if (!removeCount)
        return;

    if (m_mainThread)
        beginRemoveRows(QModelIndex(), index, index + removeCount - 1);

    QVector<std::function<void()>> toDestroy;
    if (m_dynamicRoles) {
        for (int i=0 ; i < removeCount ; ++i) {
            auto modelObject = m_modelObjects[index+i];
            toDestroy.append([modelObject](){
                delete modelObject;
            });
        }
        m_modelObjects.remove(index, removeCount);
    } else {
        toDestroy = m_listModel->remove(index, removeCount);
    }

    if (m_mainThread) {
        endRemoveRows();
        emit countChanged();
    }
    for (const auto &destroyer : toDestroy)
        destroyer();
}

/*!
    \qmlmethod ListModel::insert(int index, jsobject dict)

    Adds a new item to the list model at position \a index, with the
    values in \a dict.

    \code
        fruitModel.insert(2, {"cost": 5.95, "name":"Pizza"})
    \endcode

    The \a index must be to an existing item in the list, or one past
    the end of the list (equivalent to append).

    \sa set(), append()
*/

void QQmlListModel::insert(QQmlV4Function *args)
{
    if (args->length() == 2) {
        QV4::Scope scope(args->v4engine());
        QV4::ScopedValue arg0(scope, (*args)[0]);
        int index = arg0->toInt32();

        if (index < 0 || index > count()) {
            qmlWarning(this) << tr("insert: index %1 out of range").arg(index);
            return;
        }

        QV4::ScopedObject argObject(scope, (*args)[1]);
        QV4::ScopedArrayObject objectArray(scope, (*args)[1]);
        if (objectArray) {
            QV4::ScopedObject argObject(scope);

            int objectArrayLength = objectArray->getLength();
            emitItemsAboutToBeInserted(index, objectArrayLength);
            for (int i=0 ; i < objectArrayLength ; ++i) {
                argObject = objectArray->get(i);

                if (m_dynamicRoles) {
                    m_modelObjects.insert(index+i, DynamicRoleModelNode::create(scope.engine->variantMapFromJS(argObject), this));
                } else {
                    m_listModel->insert(index+i, argObject);
                }
            }
            emitItemsInserted();
        } else if (argObject) {
            emitItemsAboutToBeInserted(index, 1);

            if (m_dynamicRoles) {
                m_modelObjects.insert(index, DynamicRoleModelNode::create(scope.engine->variantMapFromJS(argObject), this));
            } else {
                m_listModel->insert(index, argObject);
            }

            emitItemsInserted();
        } else {
            qmlWarning(this) << tr("insert: value is not an object");
        }
    } else {
        qmlWarning(this) << tr("insert: value is not an object");
    }
}

/*!
    \qmlmethod ListModel::move(int from, int to, int n)

    Moves \a n items \a from one position \a to another.

    The from and to ranges must exist; for example, to move the first 3 items
    to the end of the list:

    \code
        fruitModel.move(0, fruitModel.count - 3, 3)
    \endcode

    \sa append()
*/
void QQmlListModel::move(int from, int to, int n)
{
    if (n == 0 || from == to)
        return;
    if (!canMove(from, to, n)) {
        qmlWarning(this) << tr("move: out of range");
        return;
    }

    if (m_mainThread)
        beginMoveRows(QModelIndex(), from, from + n - 1, QModelIndex(), to > from ? to + n : to);

    if (m_dynamicRoles) {

        int realFrom = from;
        int realTo = to;
        int realN = n;

        if (from > to) {
            // Only move forwards - flip if backwards moving
            int tfrom = from;
            int tto = to;
            realFrom = tto;
            realTo = tto+n;
            realN = tfrom-tto;
        }

        QPODVector<DynamicRoleModelNode *, 4> store;
        for (int i=0 ; i < (realTo-realFrom) ; ++i)
            store.append(m_modelObjects[realFrom+realN+i]);
        for (int i=0 ; i < realN ; ++i)
            store.append(m_modelObjects[realFrom+i]);
        for (int i=0 ; i < store.count() ; ++i)
            m_modelObjects[realFrom+i] = store[i];

    } else {
        m_listModel->move(from, to, n);
    }

    if (m_mainThread)
        endMoveRows();
}

/*!
    \qmlmethod ListModel::append(jsobject dict)

    Adds a new item to the end of the list model, with the
    values in \a dict.

    \code
        fruitModel.append({"cost": 5.95, "name":"Pizza"})
    \endcode

    \sa set(), remove()
*/
void QQmlListModel::append(QQmlV4Function *args)
{
    if (args->length() == 1) {
        QV4::Scope scope(args->v4engine());
        QV4::ScopedObject argObject(scope, (*args)[0]);
        QV4::ScopedArrayObject objectArray(scope, (*args)[0]);

        if (objectArray) {
            QV4::ScopedObject argObject(scope);

            int objectArrayLength = objectArray->getLength();
            if (objectArrayLength > 0) {
                int index = count();
                emitItemsAboutToBeInserted(index, objectArrayLength);

                for (int i=0 ; i < objectArrayLength ; ++i) {
                    argObject = objectArray->get(i);

                    if (m_dynamicRoles) {
                        m_modelObjects.append(DynamicRoleModelNode::create(scope.engine->variantMapFromJS(argObject), this));
                    } else {
                        m_listModel->append(argObject);
                    }
                }

                emitItemsInserted();
            }
        } else if (argObject) {
            int index;

            if (m_dynamicRoles) {
                index = m_modelObjects.count();
                emitItemsAboutToBeInserted(index, 1);
                m_modelObjects.append(DynamicRoleModelNode::create(scope.engine->variantMapFromJS(argObject), this));
            } else {
                index = m_listModel->elementCount();
                emitItemsAboutToBeInserted(index, 1);
                m_listModel->append(argObject);
            }

            emitItemsInserted();
        } else {
            qmlWarning(this) << tr("append: value is not an object");
        }
    } else {
        qmlWarning(this) << tr("append: value is not an object");
    }
}

/*!
    \qmlmethod object ListModel::get(int index)

    Returns the item at \a index in the list model. This allows the item
    data to be accessed or modified from JavaScript:

    \code
    Component.onCompleted: {
        fruitModel.append({"cost": 5.95, "name":"Jackfruit"});
        console.log(fruitModel.get(0).cost);
        fruitModel.get(0).cost = 10.95;
    }
    \endcode

    The \a index must be an element in the list.

    Note that properties of the returned object that are themselves objects
    will also be models, and this get() method is used to access elements:

    \code
        fruitModel.append(..., "attributes":
            [{"name":"spikes","value":"7mm"},
             {"name":"color","value":"green"}]);
        fruitModel.get(0).attributes.get(1).value; // == "green"
    \endcode

    \warning The returned object is not guaranteed to remain valid. It
    should not be used in \l{Property Binding}{property bindings}.

    \sa append()
*/
QJSValue QQmlListModel::get(int index) const
{
    QV4::Scope scope(engine());
    QV4::ScopedValue result(scope, QV4::Value::undefinedValue());

    if (index >= 0 && index < count()) {

        if (m_dynamicRoles) {
            DynamicRoleModelNode *object = m_modelObjects[index];
            result = QV4::QObjectWrapper::wrap(scope.engine, object);
        } else {
            QObject *object = m_listModel->getOrCreateModelObject(const_cast<QQmlListModel *>(this), index);
            QQmlData *ddata = QQmlData::get(object);
            if (ddata->jsWrapper.isNullOrUndefined()) {
                result = scope.engine->memoryManager->allocate<QV4::ModelObject>(object, const_cast<QQmlListModel *>(this));
                // Keep track of the QObjectWrapper in persistent value storage
                ddata->jsWrapper.set(scope.engine, result);
            } else {
                result = ddata->jsWrapper.value();
            }
        }
    }

    return QJSValue(engine(), result->asReturnedValue());
}

/*!
    \qmlmethod ListModel::set(int index, jsobject dict)

    Changes the item at \a index in the list model with the
    values in \a dict. Properties not appearing in \a dict
    are left unchanged.

    \code
        fruitModel.set(3, {"cost": 5.95, "name":"Pizza"})
    \endcode

    If \a index is equal to count() then a new item is appended to the
    list. Otherwise, \a index must be an element in the list.

    \sa append()
*/
void QQmlListModel::set(int index, const QJSValue &value)
{
    QV4::Scope scope(engine());
    QV4::ScopedObject object(scope, QJSValuePrivate::getValue(&value));

    if (!object) {
        qmlWarning(this) << tr("set: value is not an object");
        return;
    }
    if (index > count() || index < 0) {
        qmlWarning(this) << tr("set: index %1 out of range").arg(index);
        return;
    }


    if (index == count()) {
        emitItemsAboutToBeInserted(index, 1);

        if (m_dynamicRoles) {
            m_modelObjects.append(DynamicRoleModelNode::create(scope.engine->variantMapFromJS(object), this));
        } else {
            m_listModel->insert(index, object);
        }

        emitItemsInserted();
    } else {

        QVector<int> roles;

        if (m_dynamicRoles) {
            m_modelObjects[index]->updateValues(scope.engine->variantMapFromJS(object), roles);
        } else {
            m_listModel->set(index, object, &roles);
        }

        if (roles.count())
            emitItemsChanged(index, 1, roles);
    }
}

/*!
    \qmlmethod ListModel::setProperty(int index, string property, variant value)

    Changes the \a property of the item at \a index in the list model to \a value.

    \code
        fruitModel.setProperty(3, "cost", 5.95)
    \endcode

    The \a index must be an element in the list.

    \sa append()
*/
void QQmlListModel::setProperty(int index, const QString& property, const QVariant& value)
{
    if (count() == 0 || index >= count() || index < 0) {
        qmlWarning(this) << tr("set: index %1 out of range").arg(index);
        return;
    }

    if (m_dynamicRoles) {
        int roleIndex = m_roles.indexOf(property);
        if (roleIndex == -1) {
            roleIndex = m_roles.count();
            m_roles.append(property);
        }
        if (m_modelObjects[index]->setValue(property.toUtf8(), value))
            emitItemsChanged(index, 1, QVector<int>(1, roleIndex));
    } else {
        int roleIndex = m_listModel->setOrCreateProperty(index, property, value);
        if (roleIndex != -1)
            emitItemsChanged(index, 1, QVector<int>(1, roleIndex));
    }
}

/*!
    \qmlmethod ListModel::sync()

    Writes any unsaved changes to the list model after it has been modified
    from a worker script.
*/
void QQmlListModel::sync()
{
    // This is just a dummy method to make it look like sync() exists in
    // ListModel (and not just QQmlListModelWorkerAgent) and to let
    // us document sync().
    qmlWarning(this) << "List sync() can only be called from a WorkerScript";
}

bool QQmlListModelParser::verifyProperty(const QQmlRefPointer<QV4::ExecutableCompilationUnit> &compilationUnit, const QV4::CompiledData::Binding *binding)
{
    if (binding->type >= QV4::CompiledData::Binding::Type_Object) {
        const quint32 targetObjectIndex = binding->value.objectIndex;
        const QV4::CompiledData::Object *target = compilationUnit->objectAt(targetObjectIndex);
        QString objName = compilationUnit->stringAt(target->inheritedTypeNameIndex);
        if (objName != listElementTypeName) {
            const QMetaObject *mo = resolveType(objName);
            if (mo != &QQmlListElement::staticMetaObject) {
                error(target, QQmlListModel::tr("ListElement: cannot contain nested elements"));
                return false;
            }
            listElementTypeName = objName; // cache right name for next time
        }

        if (!compilationUnit->stringAt(target->idNameIndex).isEmpty()) {
            error(target->locationOfIdProperty, QQmlListModel::tr("ListElement: cannot use reserved \"id\" property"));
            return false;
        }

        const QV4::CompiledData::Binding *binding = target->bindingTable();
        for (quint32 i = 0; i < target->nBindings; ++i, ++binding) {
            QString propName = compilationUnit->stringAt(binding->propertyNameIndex);
            if (propName.isEmpty()) {
                error(binding, QQmlListModel::tr("ListElement: cannot contain nested elements"));
                return false;
            }
            if (!verifyProperty(compilationUnit, binding))
                return false;
        }
    } else if (binding->type == QV4::CompiledData::Binding::Type_Script) {
        QString scriptStr = compilationUnit->bindingValueAsScriptString(binding);
        if (!binding->isFunctionExpression() && !definesEmptyList(scriptStr)) {
            QByteArray script = scriptStr.toUtf8();
            bool ok;
            evaluateEnum(script, &ok);
            if (!ok) {
                error(binding, QQmlListModel::tr("ListElement: cannot use script for property value"));
                return false;
            }
        }
    }

    return true;
}

bool QQmlListModelParser::applyProperty(
        const QQmlRefPointer<QV4::ExecutableCompilationUnit> &compilationUnit,
        const QV4::CompiledData::Binding *binding, ListModel *model, int outterElementIndex)
{
    const QString elementName = compilationUnit->stringAt(binding->propertyNameIndex);

    bool roleSet = false;
    if (binding->type >= QV4::CompiledData::Binding::Type_Object) {
        const quint32 targetObjectIndex = binding->value.objectIndex;
        const QV4::CompiledData::Object *target = compilationUnit->objectAt(targetObjectIndex);

        ListModel *subModel = nullptr;
        if (outterElementIndex == -1) {
            subModel = model;
        } else {
            const ListLayout::Role &role = model->getOrCreateListRole(elementName);
            if (role.type == ListLayout::Role::List) {
                subModel = model->getListProperty(outterElementIndex, role);
                if (subModel == nullptr) {
                    subModel = new ListModel(role.subLayout, nullptr);
                    QVariant vModel = QVariant::fromValue(subModel);
                    model->setOrCreateProperty(outterElementIndex, elementName, vModel);
                }
            }
        }

        int elementIndex = subModel ? subModel->appendElement() : -1;

        const QV4::CompiledData::Binding *subBinding = target->bindingTable();
        for (quint32 i = 0; i < target->nBindings; ++i, ++subBinding) {
            roleSet |= applyProperty(compilationUnit, subBinding, subModel, elementIndex);
        }

    } else {
        QVariant value;

        if (binding->isTranslationBinding()) {
            value = QVariant::fromValue<const QV4::CompiledData::Binding*>(binding);
        } else if (binding->evaluatesToString()) {
            value = compilationUnit->bindingValueAsString(binding);
        } else if (binding->type == QV4::CompiledData::Binding::Type_Number) {
            value = compilationUnit->bindingValueAsNumber(binding);
        } else if (binding->type == QV4::CompiledData::Binding::Type_Boolean) {
            value = binding->valueAsBoolean();
        } else if (binding->type == QV4::CompiledData::Binding::Type_Null) {
            value = QVariant::fromValue(nullptr);
        } else if (binding->type == QV4::CompiledData::Binding::Type_Script) {
            QString scriptStr = compilationUnit->bindingValueAsScriptString(binding);
            if (definesEmptyList(scriptStr)) {
                const ListLayout::Role &role = model->getOrCreateListRole(elementName);
                ListModel *emptyModel = new ListModel(role.subLayout, nullptr);
                value = QVariant::fromValue(emptyModel);
            } else if (binding->isFunctionExpression()) {
                QQmlBinding::Identifier id = binding->value.compiledScriptIndex;
                Q_ASSERT(id != QQmlBinding::Invalid);

                auto v4 = compilationUnit->engine;
                QV4::Scope scope(v4);
                // for now we do not provide a context object; data from the ListElement must be passed to the function
                QV4::ScopedContext context(scope, QV4::QmlContext::create(v4->rootContext(), QQmlContextData::get(qmlContext(model->m_modelCache)), nullptr));
                QV4::ScopedFunctionObject function(scope, QV4::FunctionObject::createScriptFunction(context, compilationUnit->runtimeFunctions[id]));

                QJSValue v;
                QV4::ScopedValue result(scope, function->call(v4->globalObject, nullptr, 0));
                if (v4->hasException)
                    v4->catchException();
                else
                    QJSValuePrivate::setValue(&v, v4, result->asReturnedValue());
                value.setValue<QJSValue>(v);
            } else {
                QByteArray script = scriptStr.toUtf8();
                bool ok;
                value = evaluateEnum(script, &ok);
            }
        } else {
            Q_UNREACHABLE();
        }

        model->setOrCreateProperty(outterElementIndex, elementName, value);
        roleSet = true;
    }
    return roleSet;
}

void QQmlListModelParser::verifyBindings(const QQmlRefPointer<QV4::ExecutableCompilationUnit> &compilationUnit, const QList<const QV4::CompiledData::Binding *> &bindings)
{
    listElementTypeName = QString(); // unknown

    for (const QV4::CompiledData::Binding *binding : bindings) {
        QString propName = compilationUnit->stringAt(binding->propertyNameIndex);
        if (!propName.isEmpty()) { // isn't default property
            error(binding, QQmlListModel::tr("ListModel: undefined property '%1'").arg(propName));
            return;
        }
        if (!verifyProperty(compilationUnit, binding))
            return;
    }
}

void QQmlListModelParser::applyBindings(QObject *obj, const QQmlRefPointer<QV4::ExecutableCompilationUnit> &compilationUnit, const QList<const QV4::CompiledData::Binding *> &bindings)
{
    QQmlListModel *rv = static_cast<QQmlListModel *>(obj);

    rv->m_engine = qmlEngine(rv)->handle();
    rv->m_compilationUnit = compilationUnit;

    bool setRoles = false;

    for (const QV4::CompiledData::Binding *binding : bindings) {
        if (binding->type != QV4::CompiledData::Binding::Type_Object)
            continue;
        setRoles |= applyProperty(compilationUnit, binding, rv->m_listModel, /*outter element index*/-1);
    }

    if (setRoles == false)
        qmlWarning(obj) << "All ListElement declarations are empty, no roles can be created unless dynamicRoles is set.";
}

bool QQmlListModelParser::definesEmptyList(const QString &s)
{
    if (s.startsWith(QLatin1Char('[')) && s.endsWith(QLatin1Char(']'))) {
        for (int i=1; i<s.length()-1; i++) {
            if (!s[i].isSpace())
                return false;
        }
        return true;
    }
    return false;
}


/*!
    \qmltype ListElement
    \instantiates QQmlListElement
    \inqmlmodule QtQml.Models
    \brief Defines a data item in a ListModel.
    \ingroup qtquick-models

    List elements are defined inside ListModel definitions, and represent items in a
    list that will be displayed using ListView or \l Repeater items.

    List elements are defined like other QML elements except that they contain
    a collection of \e role definitions instead of properties. Using the same
    syntax as property definitions, roles both define how the data is accessed
    and include the data itself.

    The names used for roles must begin with a lower-case letter and should be
    common to all elements in a given model. Values must be simple constants; either
    strings (quoted and optionally within a call to QT_TR_NOOP), boolean values
    (true, false), numbers, or enumeration values (such as AlignText.AlignHCenter).

    Beginning with Qt 5.11 ListElement also allows assigning a function declaration to
    a role. This allows the definition of ListElements with callable actions.

    \section1 Referencing Roles

    The role names are used by delegates to obtain data from list elements.
    Each role name is accessible in the delegate's scope, and refers to the
    corresponding role in the current element. Where a role name would be
    ambiguous to use, it can be accessed via the \l{ListView::}{model}
    property (e.g., \c{model.cost} instead of \c{cost}).

    \section1 Example Usage

    The following model defines a series of list elements, each of which
    contain "name" and "cost" roles and their associated values.

    \snippet qml/listmodel/listelements.qml model

    The delegate obtains the name and cost for each element by simply referring
    to \c name and \c cost:

    \snippet qml/listmodel/listelements.qml view

    \sa ListModel
*/

QT_END_NAMESPACE

#include "moc_qqmllistmodel_p.cpp"
