diff options
author | Liang Qi <liang.qi@theqtcompany.com> | 2015-10-14 15:48:12 +0200 |
---|---|---|
committer | Liang Qi <liang.qi@theqtcompany.com> | 2015-10-14 15:48:12 +0200 |
commit | 7063fefe4b5e866b27001bb9b911fc2f68034e40 (patch) | |
tree | 1ce35139475d83399572a3265414c2da3443a321 /src/qml/qml/qqmlvmemetaobject.cpp | |
parent | f3446071da8357620d0c8593a04e3b4fbba88f21 (diff) | |
parent | 4f3379352a265bab00a7265f85ffc38a9ca4ffe4 (diff) |
Merge remote-tracking branch 'origin/5.6' into dev
Change-Id: I11ea57222ba5aa683b7bfd7735fbc1d2cf86e875
Diffstat (limited to 'src/qml/qml/qqmlvmemetaobject.cpp')
-rw-r--r-- | src/qml/qml/qqmlvmemetaobject.cpp | 169 |
1 files changed, 84 insertions, 85 deletions
diff --git a/src/qml/qml/qqmlvmemetaobject.cpp b/src/qml/qml/qqmlvmemetaobject.cpp index 509bbf7039..b1f2549035 100644 --- a/src/qml/qml/qqmlvmemetaobject.cpp +++ b/src/qml/qml/qqmlvmemetaobject.cpp @@ -63,18 +63,19 @@ QQmlVMEVariantQObjectPtr::~QQmlVMEVariantQObjectPtr() void QQmlVMEVariantQObjectPtr::objectDestroyed(QObject *) { - if (m_target && m_index >= 0) { - if (m_target->propertiesInitialized && !m_target->properties.isUndefined()) { - QV4::ExecutionEngine *v4 = m_target->cache->engine; - if (v4) { - QV4::Scope scope(v4); - QV4::Scoped<QV4::MemberData> sp(scope, m_target->properties.value()); + if (!m_target || QQmlData::wasDeleted(m_target->object)) + return; + + if (m_index >= 0) { + QV4::ExecutionEngine *v4 = m_target->properties.engine(); + if (v4) { + QV4::Scope scope(v4); + QV4::Scoped<QV4::MemberData> sp(scope, m_target->properties.value()); + if (sp) *(sp->data() + m_index) = QV4::Primitive::nullValue(); - } } - if (!QQmlData::wasDeleted(m_target->object)) - m_target->activate(m_target->object, m_target->methodOffset() + m_index, 0); + m_target->activate(m_target->object, m_target->methodOffset() + m_index, 0); } } @@ -147,12 +148,14 @@ QAbstractDynamicMetaObject *QQmlVMEMetaObject::toDynamicMetaObject(QObject *o) QQmlVMEMetaObject::QQmlVMEMetaObject(QObject *obj, QQmlPropertyCache *cache, - const QQmlVMEMetaData *meta, QV4::ExecutionContext *qmlBindingContext, QQmlCompiledData *compiledData) -: object(obj), - ctxt(QQmlData::get(obj, true)->outerContext), cache(cache), metaData(meta), - hasAssignedMetaObjectData(false), aliasEndpoints(0), - propertiesInitialized(false), interceptors(0), methods(0) + const QQmlVMEMetaData *meta) + : object(obj), + ctxt(QQmlData::get(obj, true)->outerContext), cache(cache), metaData(meta), + hasAssignedMetaObjectData(false), aliasEndpoints(0), + interceptors(0), methods(0) { + cache->addref(); + QObjectPrivate *op = QObjectPrivate::get(obj); if (op->metaObject) { @@ -165,8 +168,6 @@ QQmlVMEMetaObject::QQmlVMEMetaObject(QObject *obj, op->metaObject = this; QQmlData::get(obj)->hasVMEMetaObject = true; - aConnected.resize(metaData->aliasCount); - int list_type = qMetaTypeId<QQmlListProperty<QObject> >(); int qobject_type = qMetaTypeId<QObject*>(); int variant_type = qMetaTypeId<QVariant>(); // Need JS wrapper to ensure properties are marked. @@ -177,31 +178,14 @@ QQmlVMEMetaObject::QQmlVMEMetaObject(QObject *obj, // ### Optimize for (int ii = 0; ii < metaData->propertyCount; ++ii) { int t = (metaData->propertyData() + ii)->propertyType; - if (t == list_type) { - listProperties.append(List(methodOffset() + ii, this)); - writeProperty(ii, listProperties.count() - 1); - } else if (!needsJSWrapper && (t == qobject_type || t == variant_type)) { + if (t == qobject_type || t == variant_type) { needsJSWrapper = true; + break; } } if (needsJSWrapper) ensureQObjectWrapper(); - - if (qmlBindingContext && metaData->methodCount) { - methods = new QV4::PersistentValue[metaData->methodCount]; - - QV4::CompiledData::CompilationUnit *compilationUnit = compiledData->compilationUnit; - QV4::Scope scope(cache->engine); - QV4::ScopedObject o(scope); - for (int index = 0; index < metaData->methodCount; ++index) { - QQmlVMEMetaData::MethodData *data = metaData->methodData() + index; - - QV4::Function *runtimeFunction = compilationUnit->runtimeFunctions[data->runtimeFunctionIndex]; - o = QV4::FunctionObject::createScriptFunction(qmlBindingContext, runtimeFunction); - methods[index].set(qmlBindingContext->engine(), o); - } - } } QQmlVMEMetaObject::~QQmlVMEMetaObject() @@ -211,12 +195,21 @@ QQmlVMEMetaObject::~QQmlVMEMetaObject() delete [] methods; qDeleteAll(varObjectGuards); + + cache->release(); } QV4::MemberData *QQmlVMEMetaObject::propertiesAsMemberData() { - if (!ensurePropertiesAllocated()) - return 0; + if (properties.isUndefined()) { + if (properties.valueRef()) + // in some situations, the QObject wrapper (and associated 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, return 0. + return 0; + allocateProperties(); + } return static_cast<QV4::MemberData*>(properties.asManaged()); } @@ -442,6 +435,22 @@ QObject* QQmlVMEMetaObject::readPropertyAsQObject(int id) return wrapper->object(); } +QList<QObject *> *QQmlVMEMetaObject::readPropertyAsList(int id) +{ + QV4::MemberData *md = propertiesAsMemberData(); + if (!md) + return 0; + + QV4::Scope scope(cache->engine); + QV4::Scoped<QV4::VariantObject> v(scope, *(md->data() + id)); + if (!v || (int)v->d()->data.userType() != qMetaTypeId<QList<QObject *> >()) { + QVariant variant(qVariantFromValue(QList<QObject*>())); + v = cache->engine->newVariantObject(variant); + *(md->data() + id) = v; + } + return static_cast<QList<QObject *> *>(v->d()->data.data()); +} + QRectF QQmlVMEMetaObject::readPropertyAsRectF(int id) { QV4::MemberData *md = propertiesAsMemberData(); @@ -601,23 +610,25 @@ int QQmlVMEMetaObject::metaCall(QObject *o, QMetaObject::Call c, int _id, void * break; default: { - QV4::MemberData *md = propertiesAsMemberData(); - if (md) { - QV4::VariantObject *v = (md->data() + id)->as<QV4::VariantObject>(); - if (v) - QQml_valueTypeProvider()->readValueType(v->d()->data, a[0], t); + if (t == qMetaTypeId<QQmlListProperty<QObject> >()) { + QList<QObject *> *list = readPropertyAsList(id); + QQmlListProperty<QObject> *p = static_cast<QQmlListProperty<QObject> *>(a[0]); + *p = QQmlListProperty<QObject>(object, list, + list_append, list_count, list_at, + list_clear); + p->dummy1 = this; + p->dummy2 = reinterpret_cast<void *>(quintptr(methodOffset() + id)); + } else { + QV4::MemberData *md = propertiesAsMemberData(); + if (md) { + QV4::VariantObject *v = (md->data() + id)->as<QV4::VariantObject>(); + if (v) + QQml_valueTypeProvider()->readValueType(v->d()->data, a[0], t); + } } break; } } - if (t == qMetaTypeId<QQmlListProperty<QObject> >()) { - const int listIndex = readPropertyAsInt(id); - const List *list = &listProperties.at(listIndex); - *reinterpret_cast<QQmlListProperty<QObject> *>(a[0]) = - QQmlListProperty<QObject>(object, const_cast<List *>(list), - list_append, list_count, list_at, - list_clear); - } } else if (c == QMetaObject::WriteProperty) { @@ -826,11 +837,11 @@ QV4::ReturnedValue QQmlVMEMetaObject::method(int index) { if (!ctxt || !ctxt->isValid()) { qWarning("QQmlVMEMetaObject: Internal error - attempted to evaluate a function in an invalid context"); - return QV4::Primitive::undefinedValue().asReturnedValue(); + return QV4::Encode::undefined(); } if (!methods) - methods = new QV4::PersistentValue[metaData->methodCount]; + return QV4::Encode::undefined(); return methods[index].value(); } @@ -959,26 +970,28 @@ void QQmlVMEMetaObject::listChanged(int id) void QQmlVMEMetaObject::list_append(QQmlListProperty<QObject> *prop, QObject *o) { - List *list = static_cast<List *>(prop->data); + QList<QObject *> *list = static_cast<QList<QObject *> *>(prop->data); list->append(o); - list->mo->activate(prop->object, list->notifyIndex, 0); + static_cast<QQmlVMEMetaObject *>(prop->dummy1)->activate(prop->object, reinterpret_cast<quintptr>(prop->dummy2), 0); } int QQmlVMEMetaObject::list_count(QQmlListProperty<QObject> *prop) { - return static_cast<List *>(prop->data)->count(); + QList<QObject *> *list = static_cast<QList<QObject *> *>(prop->data); + return list->count(); } QObject *QQmlVMEMetaObject::list_at(QQmlListProperty<QObject> *prop, int index) { - return static_cast<List *>(prop->data)->at(index); + QList<QObject *> *list = static_cast<QList<QObject *> *>(prop->data); + return list->at(index); } void QQmlVMEMetaObject::list_clear(QQmlListProperty<QObject> *prop) { - List *list = static_cast<List *>(prop->data); + QList<QObject *> *list = static_cast<QList<QObject *> *>(prop->data); list->clear(); - list->mo->activate(prop->object, list->notifyIndex, 0); + static_cast<QQmlVMEMetaObject *>(prop->dummy1)->activate(prop->object, reinterpret_cast<quintptr>(prop->dummy2), 0); } void QQmlVMEMetaObject::registerInterceptor(int index, int valueIndex, QQmlPropertyValueInterceptor *interceptor) @@ -1052,19 +1065,6 @@ void QQmlVMEMetaObject::setVMEProperty(int index, const QV4::Value &v) return writeVarProperty(index - propOffset(), v); } -bool QQmlVMEMetaObject::ensurePropertiesAllocated() -{ - if (!propertiesInitialized) - allocateProperties(); - - // 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 !properties.isUndefined(); -} - void QQmlVMEMetaObject::ensureQObjectWrapper() { Q_ASSERT(cache && cache->engine); @@ -1087,12 +1087,12 @@ void QQmlVMEMetaObject::mark(QV4::ExecutionEngine *e) void QQmlVMEMetaObject::allocateProperties() { Q_ASSERT(cache && cache->engine); + Q_ASSERT(!properties.valueRef()); QV4::ExecutionEngine *v4 = cache->engine; QV4::Heap::MemberData *data = QV4::MemberData::allocate(v4, metaData->propertyCount); properties.set(v4, data); for (uint i = 0; i < data->size; ++i) data->data[i] = QV4::Encode::undefined(); - propertiesInitialized = true; } bool QQmlVMEMetaObject::aliasTarget(int index, QObject **target, int *coreIndex, int *valueTypeIndex) const @@ -1127,22 +1127,21 @@ bool QQmlVMEMetaObject::aliasTarget(int index, QObject **target, int *coreIndex, void QQmlVMEMetaObject::connectAlias(int aliasId) { - if (!aConnected.testBit(aliasId)) { - - if (!aliasEndpoints) - aliasEndpoints = new QQmlVMEMetaObjectEndpoint[metaData->aliasCount]; + if (!aliasEndpoints) + aliasEndpoints = new QQmlVMEMetaObjectEndpoint[metaData->aliasCount]; - aConnected.setBit(aliasId); + QQmlVMEMetaData::AliasData *d = metaData->aliasData() + aliasId; - QQmlVMEMetaData::AliasData *d = metaData->aliasData() + aliasId; - - QQmlVMEMetaObjectEndpoint *endpoint = aliasEndpoints + aliasId; - endpoint->metaObject = this; - - endpoint->connect(&ctxt->idValues[d->contextIdx].bindings); - - endpoint->tryConnect(); + QQmlVMEMetaObjectEndpoint *endpoint = aliasEndpoints + aliasId; + if (endpoint->metaObject.data()) { + // already connected + Q_ASSERT(endpoint->metaObject.data() == this); + return; } + + endpoint->metaObject = this; + endpoint->connect(&ctxt->idValues[d->contextIdx].bindings); + endpoint->tryConnect(); } void QQmlVMEMetaObject::connectAliasSignal(int index, bool indexInSignalRange) |