$$PWD/qrecursionwatcher_p.h \
$$PWD/qdeletewatcher_p.h \
$$PWD/qrecyclepool_p.h \
+ $$PWD/qflagpointer_p.h \
SOURCES += \
$$PWD/qintrusivelist.cpp \
--- /dev/null
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QFLAGPOINTER_P_H
+#define QFLAGPOINTER_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtCore/qglobal.h>
+
+QT_BEGIN_NAMESPACE
+
+template<typename T>
+class QFlagPointer {
+public:
+ inline QFlagPointer();
+ inline QFlagPointer(T *);
+ inline QFlagPointer(const QFlagPointer<T> &o);
+
+ inline bool isNull() const;
+
+ inline bool flag() const;
+ inline void setFlag();
+ inline void clearFlag();
+
+ inline bool flag2() const;
+ inline void setFlag2();
+ inline void clearFlag2();
+
+ inline QFlagPointer<T> &operator=(const QFlagPointer &o);
+ inline QFlagPointer<T> &operator=(T *);
+
+ inline T *operator->() const;
+ inline T *operator*() const;
+
+private:
+ intptr_t ptr_value;
+
+ static const intptr_t FlagBit = 0x1;
+ static const intptr_t Flag2Bit = 0x2;
+ static const intptr_t FlagsMask = FlagBit | Flag2Bit;
+};
+
+template<typename T>
+QFlagPointer<T>::QFlagPointer()
+: ptr_value(0)
+{
+}
+
+template<typename T>
+QFlagPointer<T>::QFlagPointer(T *v)
+: ptr_value(intptr_t(v))
+{
+ Q_ASSERT((ptr_value & FlagsMask) == 0);
+}
+
+template<typename T>
+QFlagPointer<T>::QFlagPointer(const QFlagPointer<T> &o)
+: ptr_value(o.ptr_value)
+{
+}
+
+template<typename T>
+bool QFlagPointer<T>::isNull() const
+{
+ return 0 == (ptr_value & (~FlagsMask));
+}
+
+template<typename T>
+bool QFlagPointer<T>::flag() const
+{
+ return ptr_value & FlagBit;
+}
+
+template<typename T>
+void QFlagPointer<T>::setFlag()
+{
+ ptr_value |= FlagBit;
+}
+
+template<typename T>
+void QFlagPointer<T>::clearFlag()
+{
+ ptr_value &= ~FlagBit;
+}
+
+template<typename T>
+bool QFlagPointer<T>::flag2() const
+{
+ return ptr_value & Flag2Bit;
+}
+
+template<typename T>
+void QFlagPointer<T>::setFlag2()
+{
+ ptr_value|= Flag2Bit;
+}
+
+template<typename T>
+void QFlagPointer<T>::clearFlag2()
+{
+ ptr_value &= ~Flag2Bit;
+}
+
+template<typename T>
+QFlagPointer<T> &QFlagPointer<T>::operator=(const QFlagPointer &o)
+{
+ ptr_value = o.ptr_value;
+ return *this;
+}
+
+template<typename T>
+QFlagPointer<T> &QFlagPointer<T>::operator=(T *o)
+{
+ Q_ASSERT((intptr_t(o) & FlagsMask) == 0);
+
+ ptr_value = intptr_t(o) | (ptr_value & FlagsMask);
+ return *this;
+}
+
+template<typename T>
+T *QFlagPointer<T>::operator->() const
+{
+ return (T *)(ptr_value & ~FlagsMask);
+}
+
+template<typename T>
+T *QFlagPointer<T>::operator*() const
+{
+ return (T *)(ptr_value & ~FlagsMask);
+}
+
+QT_END_NAMESPACE
+
+#endif // QFLAGPOINTER_P_H
#include <QtCore/qset.h>
#include <private/qobject_p.h>
-#include "qdeclarativeguard_p.h"
+#include <private/qflagpointer_p.h>
+#include <private/qdeclarativeguard_p.h>
#include <private/qv8_p.h>
+
QT_BEGIN_NAMESPACE
class QV8Bindings;
// id guards
struct ContextGuard : public QDeclarativeGuard<QObject>
{
- ContextGuard() : context(0) {}
- inline ContextGuard &operator=(QObject *obj)
- { QDeclarativeGuard<QObject>::operator=(obj); return *this; }
- virtual void objectDestroyed(QObject *) {
- if (context->contextObject && !QObjectPrivate::get(context->contextObject)->wasDeleted) bindings.notify();
- }
- QDeclarativeContextData *context;
+ inline ContextGuard();
+ inline ContextGuard &operator=(QObject *obj);
+ inline void objectDestroyed(QObject *);
+
+ inline bool wasSet() const;
+
+ QFlagPointer<QDeclarativeContextData> context;
QDeclarativeNotifier bindings;
};
ContextGuard *idValues;
return *this;
}
+QDeclarativeContextData::ContextGuard::ContextGuard()
+: context(0)
+{
+}
+
+QDeclarativeContextData::ContextGuard &QDeclarativeContextData::ContextGuard::operator=(QObject *obj)
+{
+ QDeclarativeGuard<QObject>::operator=(obj);
+ context.setFlag();
+ bindings.notify(); // For alias connections
+ return *this;
+}
+
+void QDeclarativeContextData::ContextGuard::objectDestroyed(QObject *)
+{
+ if (context->contextObject && !QObjectPrivate::get(context->contextObject)->wasDeleted)
+ bindings.notify();
+}
+
+bool QDeclarativeContextData::ContextGuard::wasSet() const
+{
+ return context.flag();
+}
+
QT_END_NAMESPACE
#endif // QDECLARATIVECONTEXT_P_H
inline void cleanup();
};
+class QDeclarativeVMEMetaObjectEndpoint : public QDeclarativeNotifierEndpoint
+{
+public:
+ QDeclarativeVMEMetaObjectEndpoint();
+ static void vmecallback(QDeclarativeNotifierEndpoint *);
+ void tryConnect();
+
+ QFlagPointer<QDeclarativeVMEMetaObject> metaObject;
+};
+
+
QDeclarativeVMEVariant::QDeclarativeVMEVariant()
: type(QVariant::Invalid)
{
}
}
+QDeclarativeVMEMetaObjectEndpoint::QDeclarativeVMEMetaObjectEndpoint()
+{
+ callback = &vmecallback;
+}
+
+void QDeclarativeVMEMetaObjectEndpoint::vmecallback(QDeclarativeNotifierEndpoint *e)
+{
+ QDeclarativeVMEMetaObjectEndpoint *vmee = static_cast<QDeclarativeVMEMetaObjectEndpoint*>(e);
+ vmee->tryConnect();
+}
+
+void QDeclarativeVMEMetaObjectEndpoint::tryConnect()
+{
+ if (metaObject.flag())
+ return;
+
+ int aliasId = this - metaObject->aliasEndpoints;
+
+ QDeclarativeVMEMetaData::AliasData *d = metaObject->metaData->aliasData() + aliasId;
+ if (!d->isObjectAlias()) {
+ QDeclarativeContextData *ctxt = metaObject->ctxt;
+ QObject *target = ctxt->idValues[d->contextIdx].data();
+ if (!target)
+ return;
+
+ QMetaProperty prop = target->metaObject()->property(d->propertyIndex());
+ if (prop.hasNotifySignal()) {
+ int sigIdx = metaObject->methodOffset + aliasId + metaObject->metaData->propertyCount;
+ QDeclarativePropertyPrivate::connect(target, prop.notifySignalIndex(),
+ metaObject->object, sigIdx);
+ }
+ }
+
+ metaObject.setFlag();
+}
+
QDeclarativeVMEMetaObject::QDeclarativeVMEMetaObject(QObject *obj,
const QMetaObject *other,
const QDeclarativeVMEMetaData *meta,
QDeclarativeCompiledData *cdata)
: QV8GCCallback::Node(GcPrologueCallback), object(obj), compiledData(cdata),
ctxt(QDeclarativeData::get(obj, true)->outerContext), metaData(meta), data(0),
- firstVarPropertyIndex(-1), varPropertiesInitialized(false), v8methods(0), parent(0)
+ aliasEndpoints(0), firstVarPropertyIndex(-1), varPropertiesInitialized(false),
+ v8methods(0), parent(0)
{
compiledData->addref();
compiledData->release();
delete parent;
delete [] data;
+ delete [] aliasEndpoints;
for (int ii = 0; v8methods && ii < metaData->methodCount; ++ii) {
qPersistentDispose(v8methods[ii]);
void QDeclarativeVMEMetaObject::connectAlias(int aliasId)
{
if (!aConnected.testBit(aliasId)) {
- aConnected.setBit(aliasId);
- QDeclarativeContext *context = ctxt->asQDeclarativeContext();
- QDeclarativeContextPrivate *ctxtPriv = QDeclarativeContextPrivate::get(context);
+ if (!aliasEndpoints)
+ aliasEndpoints = new QDeclarativeVMEMetaObjectEndpoint[metaData->aliasCount];
+
+ aConnected.setBit(aliasId);
QDeclarativeVMEMetaData::AliasData *d = metaData->aliasData() + aliasId;
- QObject *target = ctxtPriv->data->idValues[d->contextIdx].data();
- if (!target)
- return;
+ QDeclarativeVMEMetaObjectEndpoint *endpoint = aliasEndpoints + aliasId;
+ endpoint->metaObject = this;
- int sigIdx = methodOffset + aliasId + metaData->propertyCount;
- QMetaObject::connect(context, d->contextIdx + ctxtPriv->notifyIndex, object, sigIdx);
+ endpoint->connect(&ctxt->idValues[d->contextIdx].bindings);
- if (!d->isObjectAlias()) {
- QMetaProperty prop = target->metaObject()->property(d->propertyIndex());
- if (prop.hasNotifySignal())
- QDeclarativePropertyPrivate::connect(target, prop.notifySignalIndex(), object, sigIdx);
- }
+ endpoint->tryConnect();
}
}
class QV8QObjectWrapper;
class QDeclarativeVMEVariant;
class QDeclarativeRefCount;
+class QDeclarativeVMEMetaObjectEndpoint;
class Q_AUTOTEST_EXPORT QDeclarativeVMEMetaObject : public QAbstractDynamicMetaObject,
public QV8GCCallback::Node
{
virtual int metaCall(QMetaObject::Call _c, int _id, void **_a);
private:
+ friend class QDeclarativeVMEMetaObjectEndpoint;
+
QObject *object;
QDeclarativeCompiledData *compiledData;
QDeclarativeGuardedContextData ctxt;
int methodOffset;
QDeclarativeVMEVariant *data;
+ QDeclarativeVMEMetaObjectEndpoint *aliasEndpoints;
v8::Persistent<v8::Array> varProperties;
int firstVarPropertyIndex;
--- /dev/null
+import QtQuick 2.0
+
+QtObject {
+ property bool test: false
+
+ property list<QtObject> objects: [
+ QtObject {
+ id: first
+ property alias myAlias: other.myProperty
+ onMyAliasChanged: if (myAlias == 20) test = true
+ },
+ QtObject {
+ id: other
+ property real myProperty
+ }
+ ]
+
+ Component.onCompleted: {
+ other.myProperty = 20;
+ }
+}
+
void sequenceConversionBindings();
void sequenceConversionCopy();
void qtbug_22464();
+ void qtbug_21580();
void bug1();
void bug2();
void dynamicCreationCrash();
delete object;
}
+void tst_qdeclarativeecmascript::qtbug_21580()
+{
+ QDeclarativeComponent component(&engine, TEST_FILE("qtbug_21580.qml"));
+
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+
+ QCOMPARE(object->property("test").toBool(), true);
+
+ delete object;
+}
+
// QTBUG-6781
void tst_qdeclarativeecmascript::bug1()
{