Ensure that variant property references keep QObjects alive
[profile/ivi/qtdeclarative.git] / src / qml / qml / qqmlvmemetaobject.cpp
index afcc57e..2434ef0 100644 (file)
@@ -69,7 +69,7 @@ QQmlVMEVariantQObjectPtr::~QQmlVMEVariantQObjectPtr()
 void QQmlVMEVariantQObjectPtr::objectDestroyed(QObject *)
 {
     if (m_target && m_index >= 0)
-        m_target->activate(m_target->object, m_target->methodOffset + m_index, 0);
+        m_target->activate(m_target->object, m_target->methodOffset() + m_index, 0);
 }
 
 void QQmlVMEVariantQObjectPtr::setGuardedValue(QObject *obj, QQmlVMEMetaObject *target, int index)
@@ -100,6 +100,7 @@ public:
     inline const QTime &asQTime();
     inline const QDate &asQDate();
     inline const QDateTime &asQDateTime();
+    inline const QRectF &asQRectF();
     inline const QJSValue &asQJSValue();
 
     inline void setValue(QObject *v, QQmlVMEMetaObject *target, int index);
@@ -112,13 +113,16 @@ public:
     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[6]; // Large enough to hold all types
+    void *data[8]; // Large enough to hold all types
 
     inline void cleanup();
 };
@@ -127,7 +131,7 @@ class QQmlVMEMetaObjectEndpoint : public QQmlNotifierEndpoint
 {
 public:
     QQmlVMEMetaObjectEndpoint();
-    static void vmecallback(QQmlNotifierEndpoint *);
+    static void vmecallback(QQmlNotifierEndpoint *, void **);
     void tryConnect();
 
     QFlagPointer<QQmlVMEMetaObject> metaObject;
@@ -169,6 +173,9 @@ void QQmlVMEVariant::cleanup()
     } 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;
@@ -282,6 +289,14 @@ const QDateTime &QQmlVMEVariant::asQDateTime()
     return *(QDateTime *)(dataPtr());
 }
 
+const QRectF &QQmlVMEVariant::asQRectF()
+{
+    if (type != QMetaType::QRectF)
+        setValue(QRectF());
+
+    return *(QRectF *)(dataPtr());
+}
+
 const QJSValue &QQmlVMEVariant::asQJSValue()
 {
     if (type != qMetaTypeId<QJSValue>())
@@ -393,6 +408,17 @@ void QQmlVMEVariant::setValue(const QDateTime &v)
     }
 }
 
+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>()) {
@@ -409,12 +435,21 @@ 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();
@@ -426,8 +461,8 @@ void QQmlVMEMetaObjectEndpoint::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()) {
@@ -436,60 +471,79 @@ void QQmlVMEMetaObjectEndpoint::tryConnect()
             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();
+
+        hasAssignedMetaObjectData = true;
+    }
 
-    *static_cast<QMetaObject *>(this) = *other;
-    this->d.superdata = obj->metaObject();
+    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;
 
@@ -505,15 +559,15 @@ QQmlVMEMetaObject::~QQmlVMEMetaObject()
 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) {
@@ -537,8 +591,8 @@ int QQmlVMEMetaObject::metaCall(QMetaObject::Call c, int _id, void **a)
         }
     }
     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;
@@ -587,6 +641,9 @@ int QQmlVMEMetaObject::metaCall(QMetaObject::Call c, int _id, void **a)
                         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;
@@ -637,6 +694,10 @@ int QQmlVMEMetaObject::metaCall(QMetaObject::Call c, int _id, void **a)
                             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]), this, id);
@@ -645,10 +706,9 @@ int QQmlVMEMetaObject::metaCall(QMetaObject::Call c, int _id, void **a)
                             writeProperty(id, *reinterpret_cast<QVariant *>(a[0]));
                             break;
                         default:
-                            needActivate = QQml_valueTypeProvider()->writeValueType(t, a[0], data[id].dataPtr(), data[id].dataSize());
-                            if (needActivate) {
-                                data[id].setDataType(t);
-                            }
+                            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;
                         }
                     }
@@ -656,7 +716,7 @@ int QQmlVMEMetaObject::metaCall(QMetaObject::Call c, int _id, void **a)
                 }
 
                 if (c == QMetaObject::WriteProperty && needActivate) {
-                    activate(object, methodOffset + id, 0);
+                    activate(object, methodOffset() + id, 0);
                 }
 
                 return -1;
@@ -725,13 +785,13 @@ int QQmlVMEMetaObject::metaCall(QMetaObject::Call c, int _id, void **a)
 
     } 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;
             }
 
@@ -791,14 +851,19 @@ int QQmlVMEMetaObject::metaCall(QMetaObject::Call c, int _id, void **a)
         }
     }
 
-    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];
 
@@ -871,7 +936,7 @@ void QQmlVMEMetaObject::writeVarProperty(int id, v8::Handle<v8::Value> value)
 
     // 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)
@@ -904,13 +969,13 @@ void QQmlVMEMetaObject::writeProperty(int id, const QVariant &value)
         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), this, id);
+            data[id].setValue(o, this, id);
         } else {
             needActivate = (data[id].dataType() != qMetaTypeId<QVariant>() ||
                             data[id].asQVariant().userType() != value.userType() ||
@@ -919,20 +984,20 @@ void QQmlVMEMetaObject::writeProperty(int id, const QVariant &value)
         }
 
         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)
@@ -949,28 +1014,28 @@ void QQmlVMEMetaObject::list_clear(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;
@@ -978,29 +1043,29 @@ int QQmlVMEMetaObject::vmeMethodLineNumber(int index)
 
 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;
@@ -1008,21 +1073,21 @@ void QQmlVMEMetaObject::setVmeMethod(int index, v8::Persistent<v8::Function> val
 
 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);
 }
 
 bool QQmlVMEMetaObject::ensureVarPropertiesAllocated()
@@ -1067,15 +1132,32 @@ void QQmlVMEMetaObject::GcPrologueCallback(QV8GCCallback::Node *node)
 {
     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;
@@ -1084,7 +1166,7 @@ bool QQmlVMEMetaObject::aliasTarget(int index, QObject **target, int *coreIndex,
     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);
 
@@ -1125,11 +1207,39 @@ void QQmlVMEMetaObject::connectAlias(int aliasId)
 
 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