#include "qqmlpropertyvalueinterceptor_p.h"
#include <private/qv8variantresource_p.h>
+#include <private/qqmlglobal_p.h>
Q_DECLARE_METATYPE(QJSValue);
QT_BEGIN_NAMESPACE
+QQmlVMEVariantQObjectPtr::QQmlVMEVariantQObjectPtr()
+ : QQmlGuard<QObject>(0), m_target(0), m_index(-1)
+{
+}
+
+QQmlVMEVariantQObjectPtr::~QQmlVMEVariantQObjectPtr()
+{
+}
+
+void QQmlVMEVariantQObjectPtr::objectDestroyed(QObject *)
+{
+ if (m_target && m_index >= 0)
+ m_target->activate(m_target->object, m_target->methodOffset() + m_index, 0);
+}
+
+void QQmlVMEVariantQObjectPtr::setGuardedValue(QObject *obj, QQmlVMEMetaObject *target, int index)
+{
+ m_target = target;
+ m_index = index;
+ setObject(obj);
+}
+
class QQmlVMEVariant
{
public:
inline const void *dataPtr() const;
inline void *dataPtr();
inline int dataType() const;
+ inline size_t dataSize() const;
inline QObject *asQObject();
inline const QVariant &asQVariant();
inline double asDouble();
inline const QString &asQString();
inline const QUrl &asQUrl();
- inline const QColor &asQColor();
inline const QTime &asQTime();
inline const QDate &asQDate();
inline const QDateTime &asQDateTime();
+ inline const QRectF &asQRectF();
inline const QJSValue &asQJSValue();
- inline void setValue(QObject *);
+ inline void setValue(QObject *v, QQmlVMEMetaObject *target, int index);
inline void setValue(const QVariant &);
inline void setValue(int);
inline void setValue(bool);
inline void setValue(double);
inline void setValue(const QString &);
inline void setValue(const QUrl &);
- inline void setValue(const QColor &);
inline void setValue(const QTime &);
inline void setValue(const QDate &);
inline void setValue(const QDateTime &);
+ inline void setValue(const QRectF &);
inline void setValue(const QJSValue &);
+
+ inline void setDataType(int t);
+
+ inline void ensureValueType(int);
+
private:
int type;
- void *data[4]; // Large enough to hold all types
+ void *data[8]; // Large enough to hold all types
inline void cleanup();
};
{
public:
QQmlVMEMetaObjectEndpoint();
- static void vmecallback(QQmlNotifierEndpoint *);
+ static void vmecallback(QQmlNotifierEndpoint *, void **);
void tryConnect();
QFlagPointer<QQmlVMEMetaObject> metaObject;
type == QMetaType::Double) {
type = QVariant::Invalid;
} else if (type == QMetaType::QObjectStar) {
- ((QQmlGuard<QObject>*)dataPtr())->~QQmlGuard<QObject>();
+ ((QQmlVMEVariantQObjectPtr*)dataPtr())->~QQmlVMEVariantQObjectPtr();
type = QVariant::Invalid;
} else if (type == QMetaType::QString) {
((QString *)dataPtr())->~QString();
} else if (type == QMetaType::QUrl) {
((QUrl *)dataPtr())->~QUrl();
type = QVariant::Invalid;
- } else if (type == QMetaType::QColor) {
- ((QColor *)dataPtr())->~QColor();
- type = QVariant::Invalid;
} else if (type == QMetaType::QTime) {
((QTime *)dataPtr())->~QTime();
type = QVariant::Invalid;
} else if (type == QMetaType::QDateTime) {
((QDateTime *)dataPtr())->~QDateTime();
type = QVariant::Invalid;
+ } else if (type == QMetaType::QRectF) {
+ ((QRectF *)dataPtr())->~QRectF();
+ type = QVariant::Invalid;
} else if (type == qMetaTypeId<QVariant>()) {
((QVariant *)dataPtr())->~QVariant();
type = QVariant::Invalid;
} else if (type == qMetaTypeId<QJSValue>()) {
((QJSValue *)dataPtr())->~QJSValue();
type = QVariant::Invalid;
+ } else {
+ if (QQml_valueTypeProvider()->destroyValueType(type, dataPtr(), dataSize())) {
+ type = QVariant::Invalid;
+ }
}
-
}
int QQmlVMEVariant::dataType() const
return &data;
}
+size_t QQmlVMEVariant::dataSize() const
+{
+ return sizeof(data);
+}
+
QObject *QQmlVMEVariant::asQObject()
{
- if (type != QMetaType::QObjectStar)
- setValue((QObject *)0);
+ if (type != QMetaType::QObjectStar)
+ setValue((QObject *)0, 0, -1);
return *(QQmlGuard<QObject> *)(dataPtr());
}
return *(QUrl *)(dataPtr());
}
-const QColor &QQmlVMEVariant::asQColor()
-{
- if (type != QMetaType::QColor)
- setValue(QColor());
-
- return *(QColor *)(dataPtr());
-}
-
const QTime &QQmlVMEVariant::asQTime()
{
if (type != QMetaType::QTime)
return *(QDateTime *)(dataPtr());
}
+const QRectF &QQmlVMEVariant::asQRectF()
+{
+ if (type != QMetaType::QRectF)
+ setValue(QRectF());
+
+ return *(QRectF *)(dataPtr());
+}
+
const QJSValue &QQmlVMEVariant::asQJSValue()
{
if (type != qMetaTypeId<QJSValue>())
return *(QJSValue *)(dataPtr());
}
-void QQmlVMEVariant::setValue(QObject *v)
+void QQmlVMEVariant::setValue(QObject *v, QQmlVMEMetaObject *target, int index)
{
if (type != QMetaType::QObjectStar) {
cleanup();
type = QMetaType::QObjectStar;
- new (dataPtr()) QQmlGuard<QObject>();
+ new (dataPtr()) QQmlVMEVariantQObjectPtr;
}
- *(QQmlGuard<QObject>*)(dataPtr()) = v;
+ reinterpret_cast<QQmlVMEVariantQObjectPtr*>(dataPtr())->setGuardedValue(v, target, index);
}
void QQmlVMEVariant::setValue(const QVariant &v)
}
}
-void QQmlVMEVariant::setValue(const QColor &v)
-{
- if (type != QMetaType::QColor) {
- cleanup();
- type = QMetaType::QColor;
- new (dataPtr()) QColor(v);
- } else {
- *(QColor *)(dataPtr()) = v;
- }
-}
-
void QQmlVMEVariant::setValue(const QTime &v)
{
if (type != QMetaType::QTime) {
}
}
+void QQmlVMEVariant::setValue(const QRectF &v)
+{
+ if (type != QMetaType::QRectF) {
+ cleanup();
+ type = QMetaType::QRectF;
+ new (dataPtr()) QRectF(v);
+ } else {
+ *(QRectF *)(dataPtr()) = v;
+ }
+}
+
void QQmlVMEVariant::setValue(const QJSValue &v)
{
if (type != qMetaTypeId<QJSValue>()) {
}
}
+void QQmlVMEVariant::setDataType(int t)
+{
+ type = t;
+}
+
+void QQmlVMEVariant::ensureValueType(int t)
+{
+ if (type != t) {
+ cleanup();
+ type = t;
+ QQml_valueTypeProvider()->initValueType(t, dataPtr(), dataSize());
+ }
+}
+
QQmlVMEMetaObjectEndpoint::QQmlVMEMetaObjectEndpoint()
{
- callback = &vmecallback;
+ setCallback(QQmlNotifierEndpoint::QQmlVMEMetaObjectEndpoint);
}
-void QQmlVMEMetaObjectEndpoint::vmecallback(QQmlNotifierEndpoint *e)
+void QQmlVMEMetaObjectEndpoint_callback(QQmlNotifierEndpoint *e, void **)
{
QQmlVMEMetaObjectEndpoint *vmee = static_cast<QQmlVMEMetaObjectEndpoint*>(e);
vmee->tryConnect();
if (metaObject.flag()) {
// This is actually notify
- int sigIdx = metaObject->methodOffset + aliasId + metaObject->metaData->propertyCount;
- QMetaObject::activate(metaObject->object, sigIdx, 0);
+ int sigIdx = metaObject->methodOffset() + aliasId + metaObject->metaData->propertyCount;
+ metaObject->activate(metaObject->object, sigIdx, 0);
} else {
QQmlVMEMetaData::AliasData *d = metaObject->metaData->aliasData() + aliasId;
if (!d->isObjectAlias()) {
if (!target)
return;
- QMetaProperty prop = target->metaObject()->property(d->propertyIndex());
- if (prop.hasNotifySignal())
- connect(target, prop.notifySignalIndex());
+ if (d->notifySignal != -1)
+ connect(target, d->notifySignal, ctxt->engine);
}
metaObject.setFlag();
}
}
-QQmlVMEMetaObject::QQmlVMEMetaObject(QObject *obj,
- const QMetaObject *other,
- const QQmlVMEMetaData *meta,
- QQmlCompiledData *cdata)
-: QV8GCCallback::Node(GcPrologueCallback), object(obj), compiledData(cdata),
- ctxt(QQmlData::get(obj, true)->outerContext), metaData(meta), data(0),
- aliasEndpoints(0), firstVarPropertyIndex(-1), varPropertiesInitialized(false),
- v8methods(0), parent(0)
+QAbstractDynamicMetaObject *QQmlVMEMetaObject::toDynamicMetaObject(QObject *o)
{
- compiledData->addref();
+ if (!hasAssignedMetaObjectData) {
+ *static_cast<QMetaObject *>(this) = *cache->createMetaObject();
+
+ if (parent.isT1())
+ this->d.superdata = parent.asT1()->toDynamicMetaObject(o);
+ else
+ this->d.superdata = parent.asT2();
- *static_cast<QMetaObject *>(this) = *other;
- this->d.superdata = obj->metaObject();
+ hasAssignedMetaObjectData = true;
+ }
+
+ return this;
+}
+QQmlVMEMetaObject::QQmlVMEMetaObject(QObject *obj,
+ QQmlPropertyCache *cache,
+ const QQmlVMEMetaData *meta)
+: QV8GCCallback::Node(GcPrologueCallback), object(obj),
+ ctxt(QQmlData::get(obj, true)->outerContext), cache(cache), metaData(meta),
+ hasAssignedMetaObjectData(false), data(0), aliasEndpoints(0), firstVarPropertyIndex(-1),
+ varPropertiesInitialized(false), interceptors(0), v8methods(0)
+{
QObjectPrivate *op = QObjectPrivate::get(obj);
- if (op->metaObject)
- parent = static_cast<QAbstractDynamicMetaObject*>(op->metaObject);
- op->metaObject = this;
- propOffset = QAbstractDynamicMetaObject::propertyOffset();
- methodOffset = QAbstractDynamicMetaObject::methodOffset();
+ if (op->metaObject) parent = op->metaObject;
+ else parent = obj->metaObject();
+
+ op->metaObject = this;
+ QQmlData::get(obj)->hasVMEMetaObject = true;
data = new QQmlVMEVariant[metaData->propertyCount - metaData->varPropertyCount];
aConnected.resize(metaData->aliasCount);
int list_type = qMetaTypeId<QQmlListProperty<QObject> >();
+ int qobject_type = qMetaTypeId<QObject*>();
+ int variant_type = qMetaTypeId<QVariant>();
+ bool needsGcCallback = (metaData->varPropertyCount > 0);
// ### Optimize
for (int ii = 0; ii < metaData->propertyCount - metaData->varPropertyCount; ++ii) {
int t = (metaData->propertyData() + ii)->propertyType;
if (t == list_type) {
- listProperties.append(List(methodOffset + ii));
+ listProperties.append(List(methodOffset() + ii, this));
data[ii].setValue(listProperties.count() - 1);
- }
+ } else if (!needsGcCallback && (t == qobject_type || t == variant_type)) {
+ needsGcCallback = true;
+ }
}
firstVarPropertyIndex = metaData->propertyCount - metaData->varPropertyCount;
- if (metaData->varPropertyCount)
+
+ // both var properties and variant properties can keep references to
+ // other QObjects, and var properties can also keep references to
+ // JavaScript objects. If we have any properties, we need to hook
+ // the gc() to ensure that references keep objects alive as needed.
+ if (needsGcCallback) {
QV8GCCallback::addGcCallbackNode(this);
+ }
}
QQmlVMEMetaObject::~QQmlVMEMetaObject()
{
- compiledData->release();
- delete parent;
+ if (parent.isT1()) parent.asT1()->objectDestroyed(object);
delete [] data;
delete [] aliasEndpoints;
int QQmlVMEMetaObject::metaCall(QMetaObject::Call c, int _id, void **a)
{
int id = _id;
- if(c == QMetaObject::WriteProperty) {
- int flags = *reinterpret_cast<int*>(a[3]);
- if (!(flags & QQmlPropertyPrivate::BypassInterceptor)
- && !aInterceptors.isEmpty()
- && aInterceptors.testBit(id)) {
- QPair<int, QQmlPropertyValueInterceptor*> pair = interceptors.value(id);
- int valueIndex = pair.first;
- QQmlPropertyValueInterceptor *vi = pair.second;
- int type = property(id).userType();
+ if (c == QMetaObject::WriteProperty && interceptors &&
+ !(*reinterpret_cast<int*>(a[3]) & QQmlPropertyPrivate::BypassInterceptor)) {
+
+ for (QQmlPropertyValueInterceptor *vi = interceptors; vi; vi = vi->m_next) {
+ if (vi->m_coreIndex != id)
+ continue;
+
+ int valueIndex = vi->m_valueTypeCoreIndex;
+ int type = QQmlData::get(object)->propertyCache->property(id)->propType;
if (type != QVariant::Invalid) {
if (valueIndex != -1) {
}
}
if (c == QMetaObject::ReadProperty || c == QMetaObject::WriteProperty || c == QMetaObject::ResetProperty) {
- if (id >= propOffset) {
- id -= propOffset;
+ if (id >= propOffset()) {
+ id -= propOffset();
if (id < metaData->propertyCount) {
int t = (metaData->propertyData() + id)->propertyType;
case QVariant::Url:
*reinterpret_cast<QUrl *>(a[0]) = data[id].asQUrl();
break;
- case QVariant::Color:
- *reinterpret_cast<QColor *>(a[0]) = data[id].asQColor();
- break;
case QVariant::Date:
*reinterpret_cast<QDate *>(a[0]) = data[id].asQDate();
break;
case QVariant::DateTime:
*reinterpret_cast<QDateTime *>(a[0]) = data[id].asQDateTime();
break;
+ case QVariant::RectF:
+ *reinterpret_cast<QRectF *>(a[0]) = data[id].asQRectF();
+ break;
case QMetaType::QObjectStar:
*reinterpret_cast<QObject **>(a[0]) = data[id].asQObject();
break;
*reinterpret_cast<QVariant *>(a[0]) = readPropertyAsVariant(id);
break;
default:
+ QQml_valueTypeProvider()->readValueType(data[id].dataType(), data[id].dataPtr(), t, a[0]);
break;
}
if (t == qMetaTypeId<QQmlListProperty<QObject> >()) {
needActivate = *reinterpret_cast<QUrl *>(a[0]) != data[id].asQUrl();
data[id].setValue(*reinterpret_cast<QUrl *>(a[0]));
break;
- case QVariant::Color:
- needActivate = *reinterpret_cast<QColor *>(a[0]) != data[id].asQColor();
- data[id].setValue(*reinterpret_cast<QColor *>(a[0]));
- break;
case QVariant::Date:
needActivate = *reinterpret_cast<QDate *>(a[0]) != data[id].asQDate();
data[id].setValue(*reinterpret_cast<QDate *>(a[0]));
needActivate = *reinterpret_cast<QDateTime *>(a[0]) != data[id].asQDateTime();
data[id].setValue(*reinterpret_cast<QDateTime *>(a[0]));
break;
+ case QVariant::RectF:
+ needActivate = *reinterpret_cast<QRectF *>(a[0]) != data[id].asQRectF();
+ data[id].setValue(*reinterpret_cast<QRectF *>(a[0]));
+ break;
case QMetaType::QObjectStar:
needActivate = *reinterpret_cast<QObject **>(a[0]) != data[id].asQObject();
- data[id].setValue(*reinterpret_cast<QObject **>(a[0]));
+ data[id].setValue(*reinterpret_cast<QObject **>(a[0]), this, id);
break;
case QMetaType::QVariant:
writeProperty(id, *reinterpret_cast<QVariant *>(a[0]));
break;
default:
+ data[id].ensureValueType(t);
+ needActivate = !QQml_valueTypeProvider()->equalValueType(t, a[0], data[id].dataPtr());
+ QQml_valueTypeProvider()->writeValueType(t, a[0], data[id].dataPtr(), data[id].dataSize());
break;
}
}
}
if (c == QMetaObject::WriteProperty && needActivate) {
- activate(object, methodOffset + id, 0);
+ activate(object, methodOffset() + id, 0);
}
return -1;
} else if(c == QMetaObject::InvokeMetaMethod) {
- if (id >= methodOffset) {
+ if (id >= methodOffset()) {
- id -= methodOffset;
+ id -= methodOffset();
int plainSignals = metaData->signalCount + metaData->propertyCount +
metaData->aliasCount;
if (id < plainSignals) {
- QMetaObject::activate(object, _id, a);
+ activate(object, _id, a);
return -1;
}
// performance reasons; see QTBUG-24064) and thus compilation will have failed.
QQmlError e;
e.setDescription(QString(QLatin1String("Exception occurred during compilation of function: %1")).
- arg(QLatin1String(QMetaObject::method(_id).signature())));
+ arg(QLatin1String(QMetaObject::method(_id).methodSignature().constData())));
ep->warning(e);
return -1; // The dynamic method with that id is not available.
}
}
}
- if (parent)
- return parent->metaCall(c, _id, a);
+ if (parent.isT1())
+ return parent.asT1()->metaCall(object, c, _id, a);
else
return object->qt_metacall(c, _id, a);
}
v8::Handle<v8::Function> QQmlVMEMetaObject::method(int index)
{
+ if (!ctxt || !ctxt->isValid()) {
+ qWarning("QQmlVMEMetaObject: Internal error - attempted to evaluate a function in an invalid context");
+ return v8::Handle<v8::Function>();
+ }
+
if (!v8methods)
v8methods = new v8::Persistent<v8::Function>[metaData->methodCount];
{
Q_ASSERT(id >= firstVarPropertyIndex);
- ensureVarPropertiesAllocated();
- return varProperties->Get(id - firstVarPropertyIndex);
+ if (ensureVarPropertiesAllocated())
+ return varProperties->Get(id - firstVarPropertyIndex);
+ return v8::Handle<v8::Value>();
}
QVariant QQmlVMEMetaObject::readPropertyAsVariant(int id)
{
if (id >= firstVarPropertyIndex) {
- ensureVarPropertiesAllocated();
- return QQmlEnginePrivate::get(ctxt->engine)->v8engine()->toVariant(varProperties->Get(id - firstVarPropertyIndex), -1);
+ if (ensureVarPropertiesAllocated())
+ return QQmlEnginePrivate::get(ctxt->engine)->v8engine()->toVariant(varProperties->Get(id - firstVarPropertyIndex), -1);
+ return QVariant();
} else {
if (data[id].dataType() == QMetaType::QObjectStar) {
return QVariant::fromValue(data[id].asQObject());
void QQmlVMEMetaObject::writeVarProperty(int id, v8::Handle<v8::Value> value)
{
Q_ASSERT(id >= firstVarPropertyIndex);
- ensureVarPropertiesAllocated();
+ if (!ensureVarPropertiesAllocated())
+ return;
// Importantly, if the current value is a scarce resource, we need to ensure that it
// gets automatically released by the engine if no other references to it exist.
// Write the value and emit change signal as appropriate.
varProperties->Set(id - firstVarPropertyIndex, value);
- activate(object, methodOffset + id, 0);
+ activate(object, methodOffset() + id, 0);
}
void QQmlVMEMetaObject::writeProperty(int id, const QVariant &value)
{
if (id >= firstVarPropertyIndex) {
- ensureVarPropertiesAllocated();
+ if (!ensureVarPropertiesAllocated())
+ return;
// Importantly, if the current value is a scarce resource, we need to ensure that it
// gets automatically released by the engine if no other references to it exist.
QVariant currentValue = readPropertyAsVariant(id);
varProperties->Set(id - firstVarPropertyIndex, newv);
if ((currentValue.userType() != value.userType() || currentValue != value))
- activate(object, methodOffset + id, 0);
+ activate(object, methodOffset() + id, 0);
} else {
bool needActivate = false;
if (value.userType() == QMetaType::QObjectStar) {
- QObject *o = qvariant_cast<QObject *>(value);
+ QObject *o = *(QObject **)value.data();
needActivate = (data[id].dataType() != QMetaType::QObjectStar || data[id].asQObject() != o);
- data[id].setValue(qvariant_cast<QObject *>(value));
+ data[id].setValue(o, this, id);
} else {
needActivate = (data[id].dataType() != qMetaTypeId<QVariant>() ||
data[id].asQVariant().userType() != value.userType() ||
}
if (needActivate)
- activate(object, methodOffset + id, 0);
+ activate(object, methodOffset() + id, 0);
}
}
void QQmlVMEMetaObject::listChanged(int id)
{
- activate(object, methodOffset + id, 0);
+ activate(object, methodOffset() + id, 0);
}
void QQmlVMEMetaObject::list_append(QQmlListProperty<QObject> *prop, QObject *o)
{
List *list = static_cast<List *>(prop->data);
list->append(o);
- QMetaObject::activate(prop->object, list->notifyIndex, 0);
+ list->mo->activate(prop->object, list->notifyIndex, 0);
}
int QQmlVMEMetaObject::list_count(QQmlListProperty<QObject> *prop)
{
List *list = static_cast<List *>(prop->data);
list->clear();
- QMetaObject::activate(prop->object, list->notifyIndex, 0);
+ list->mo->activate(prop->object, list->notifyIndex, 0);
}
void QQmlVMEMetaObject::registerInterceptor(int index, int valueIndex, QQmlPropertyValueInterceptor *interceptor)
{
- if (aInterceptors.isEmpty())
- aInterceptors.resize(propertyCount() + metaData->propertyCount);
- aInterceptors.setBit(index);
- interceptors.insert(index, qMakePair(valueIndex, interceptor));
+ interceptor->m_coreIndex = index;
+ interceptor->m_valueTypeCoreIndex = valueIndex;
+ interceptor->m_next = interceptors;
+ interceptors = interceptor;
}
int QQmlVMEMetaObject::vmeMethodLineNumber(int index)
{
- if (index < methodOffset) {
- Q_ASSERT(parent);
- return static_cast<QQmlVMEMetaObject *>(parent)->vmeMethodLineNumber(index);
+ if (index < methodOffset()) {
+ Q_ASSERT(parent.isT1());
+ return static_cast<QQmlVMEMetaObject *>(parent.asT1())->vmeMethodLineNumber(index);
}
int plainSignals = metaData->signalCount + metaData->propertyCount + metaData->aliasCount;
- Q_ASSERT(index >= (methodOffset + plainSignals) && index < (methodOffset + plainSignals + metaData->methodCount));
+ Q_ASSERT(index >= (methodOffset() + plainSignals) && index < (methodOffset() + plainSignals + metaData->methodCount));
- int rawIndex = index - methodOffset - plainSignals;
+ int rawIndex = index - methodOffset() - plainSignals;
QQmlVMEMetaData::MethodData *data = metaData->methodData() + rawIndex;
return data->lineNumber;
v8::Handle<v8::Function> QQmlVMEMetaObject::vmeMethod(int index)
{
- if (index < methodOffset) {
- Q_ASSERT(parent);
- return static_cast<QQmlVMEMetaObject *>(parent)->vmeMethod(index);
+ if (index < methodOffset()) {
+ Q_ASSERT(parent.isT1());
+ return static_cast<QQmlVMEMetaObject *>(parent.asT1())->vmeMethod(index);
}
int plainSignals = metaData->signalCount + metaData->propertyCount + metaData->aliasCount;
- Q_ASSERT(index >= (methodOffset + plainSignals) && index < (methodOffset + plainSignals + metaData->methodCount));
- return method(index - methodOffset - plainSignals);
+ Q_ASSERT(index >= (methodOffset() + plainSignals) && index < (methodOffset() + plainSignals + metaData->methodCount));
+ return method(index - methodOffset() - plainSignals);
}
// Used by debugger
void QQmlVMEMetaObject::setVmeMethod(int index, v8::Persistent<v8::Function> value)
{
- if (index < methodOffset) {
- Q_ASSERT(parent);
- return static_cast<QQmlVMEMetaObject *>(parent)->setVmeMethod(index, value);
+ if (index < methodOffset()) {
+ Q_ASSERT(parent.isT1());
+ return static_cast<QQmlVMEMetaObject *>(parent.asT1())->setVmeMethod(index, value);
}
int plainSignals = metaData->signalCount + metaData->propertyCount + metaData->aliasCount;
- Q_ASSERT(index >= (methodOffset + plainSignals) && index < (methodOffset + plainSignals + metaData->methodCount));
+ Q_ASSERT(index >= (methodOffset() + plainSignals) && index < (methodOffset() + plainSignals + metaData->methodCount));
if (!v8methods)
v8methods = new v8::Persistent<v8::Function>[metaData->methodCount];
- int methodIndex = index - methodOffset - plainSignals;
+ int methodIndex = index - methodOffset() - plainSignals;
if (!v8methods[methodIndex].IsEmpty())
qPersistentDispose(v8methods[methodIndex]);
v8methods[methodIndex] = value;
v8::Handle<v8::Value> QQmlVMEMetaObject::vmeProperty(int index)
{
- if (index < propOffset) {
- Q_ASSERT(parent);
- return static_cast<QQmlVMEMetaObject *>(parent)->vmeProperty(index);
+ if (index < propOffset()) {
+ Q_ASSERT(parent.isT1());
+ return static_cast<QQmlVMEMetaObject *>(parent.asT1())->vmeProperty(index);
}
- return readVarProperty(index - propOffset);
+ return readVarProperty(index - propOffset());
}
void QQmlVMEMetaObject::setVMEProperty(int index, v8::Handle<v8::Value> v)
{
- if (index < propOffset) {
- Q_ASSERT(parent);
- static_cast<QQmlVMEMetaObject *>(parent)->setVMEProperty(index, v);
+ if (index < propOffset()) {
+ Q_ASSERT(parent.isT1());
+ static_cast<QQmlVMEMetaObject *>(parent.asT1())->setVMEProperty(index, v);
return;
}
- return writeVarProperty(index - propOffset, v);
+ return writeVarProperty(index - propOffset(), v);
}
-void QQmlVMEMetaObject::ensureVarPropertiesAllocated()
+bool QQmlVMEMetaObject::ensureVarPropertiesAllocated()
{
if (!varPropertiesInitialized)
allocateVarPropertiesArray();
+
+ // in some situations, the QObject's v8object (and associated v8 data,
+ // such as the varProperties array) will have been cleaned up, but the
+ // QObject ptr will not yet have been deleted (eg, waiting on deleteLater).
+ // In this situation, the varProperties handle will be (and should remain)
+ // empty.
+ return !varProperties.IsEmpty();
}
// see also: QV8GCCallback::garbageCollectorPrologueCallback()
{
QQmlVMEMetaObject *vmemo = static_cast<QQmlVMEMetaObject*>(node);
Q_ASSERT(vmemo);
- if (!vmemo->varPropertiesInitialized || vmemo->varProperties.IsEmpty() || !vmemo->ctxt || !vmemo->ctxt->engine)
+
+ if (!vmemo->ctxt || !vmemo->ctxt->engine)
return;
QQmlEnginePrivate *ep = QQmlEnginePrivate::get(vmemo->ctxt->engine);
+
+ // add references created by VMEVariant properties
+ int maxDataIdx = vmemo->metaData->propertyCount - vmemo->metaData->varPropertyCount;
+ for (int ii = 0; ii < maxDataIdx; ++ii) { // XXX TODO: optimise?
+ if (vmemo->data[ii].dataType() == QMetaType::QObjectStar) {
+ // possible QObject reference.
+ QObject *ref = vmemo->data[ii].asQObject();
+ if (ref) {
+ ep->v8engine()->addRelationshipForGC(vmemo->object, ref);
+ }
+ }
+ }
+
+ // add references created by var properties
+ if (!vmemo->varPropertiesInitialized || vmemo->varProperties.IsEmpty())
+ return;
ep->v8engine()->addRelationshipForGC(vmemo->object, vmemo->varProperties);
}
bool QQmlVMEMetaObject::aliasTarget(int index, QObject **target, int *coreIndex, int *valueTypeIndex) const
{
- Q_ASSERT(index >= propOffset + metaData->propertyCount);
+ Q_ASSERT(index >= propOffset() + metaData->propertyCount);
*target = 0;
*coreIndex = -1;
if (!ctxt)
return false;
- QQmlVMEMetaData::AliasData *d = metaData->aliasData() + (index - propOffset - metaData->propertyCount);
+ QQmlVMEMetaData::AliasData *d = metaData->aliasData() + (index - propOffset() - metaData->propertyCount);
QQmlContext *context = ctxt->asQQmlContext();
QQmlContextPrivate *ctxtPriv = QQmlContextPrivate::get(context);
void QQmlVMEMetaObject::connectAliasSignal(int index)
{
- int aliasId = (index - methodOffset) - metaData->propertyCount;
+ int aliasId = (index - methodOffset()) - metaData->propertyCount;
if (aliasId < 0 || aliasId >= metaData->aliasCount)
return;
connectAlias(aliasId);
}
+void QQmlVMEMetaObject::activate(QObject *object, int index, void **args)
+{
+ int signalOffset = cache->signalOffset();
+ int methodOffset = cache->methodOffset();
+
+ QMetaObject::activate(object, methodOffset, signalOffset, index - methodOffset, args);
+}
+
+QQmlVMEMetaObject *QQmlVMEMetaObject::getForProperty(QObject *o, int coreIndex)
+{
+ QQmlVMEMetaObject *vme = QQmlVMEMetaObject::get(o);
+ while (vme->propOffset() > coreIndex) {
+ Q_ASSERT(vme->parent.isT1());
+ vme = static_cast<QQmlVMEMetaObject *>(vme->parent.asT1());
+ }
+ return vme;
+}
+
+QQmlVMEMetaObject *QQmlVMEMetaObject::getForMethod(QObject *o, int coreIndex)
+{
+ QQmlVMEMetaObject *vme = QQmlVMEMetaObject::get(o);
+ while (vme->methodOffset() > coreIndex) {
+ Q_ASSERT(vme->parent.isT1());
+ vme = static_cast<QQmlVMEMetaObject *>(vme->parent.asT1());
+ }
+ return vme;
+}
+
QT_END_NAMESPACE