aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/qml/jsruntime/qv4qobjectwrapper.cpp2
-rw-r--r--src/qml/qml/qqmlvaluetype.cpp47
-rw-r--r--src/qml/qml/qqmlvaluetype_p.h26
-rw-r--r--src/qml/qml/qqmlvaluetypewrapper.cpp200
-rw-r--r--src/qml/qml/qqmlvaluetypewrapper_p.h9
-rw-r--r--src/qml/qml/v8/qv8engine_p.h1
6 files changed, 138 insertions, 147 deletions
diff --git a/src/qml/jsruntime/qv4qobjectwrapper.cpp b/src/qml/jsruntime/qv4qobjectwrapper.cpp
index 7acd588b22..1af82ff25f 100644
--- a/src/qml/jsruntime/qv4qobjectwrapper.cpp
+++ b/src/qml/jsruntime/qv4qobjectwrapper.cpp
@@ -1842,7 +1842,7 @@ ReturnedValue QObjectMethod::callInternal(CallData *callData)
if (!wrapper)
return Encode::undefined();
- object = QQmlObjectOrGadget(d()->propertyCache.data(), wrapper->d()->type->gadget());
+ object = QQmlObjectOrGadget(d()->propertyCache.data(), wrapper->d()->gadget());
}
QQmlPropertyData method;
diff --git a/src/qml/qml/qqmlvaluetype.cpp b/src/qml/qml/qqmlvaluetype.cpp
index 20f3027e4c..e22e0f8fdc 100644
--- a/src/qml/qml/qqmlvaluetype.cpp
+++ b/src/qml/qml/qqmlvaluetype.cpp
@@ -192,24 +192,16 @@ QQmlValueType::~QQmlValueType()
void QQmlValueType::read(QObject *obj, int idx)
{
- readProperty(obj, idx, gadgetPtr);
-}
-
-void QQmlValueType::readVariantValue(QObject *obj, int idx, QVariant *into)
-{
- // important: must not change the userType of the variant
- readProperty(obj, idx, into);
+ void *a[] = { gadgetPtr, 0 };
+ QMetaObject::metacall(obj, QMetaObject::ReadProperty, idx, a);
}
void QQmlValueType::write(QObject *obj, int idx, QQmlPropertyPrivate::WriteFlags flags)
{
Q_ASSERT(gadgetPtr);
- writeProperty(obj, idx, flags, gadgetPtr);
-}
-
-void QQmlValueType::writeVariantValue(QObject *obj, int idx, QQmlPropertyPrivate::WriteFlags flags, QVariant *from)
-{
- writeProperty(obj, idx, flags, from);
+ int status = -1;
+ void *a[] = { gadgetPtr, 0, &status, &flags };
+ QMetaObject::metacall(obj, QMetaObject::WriteProperty, idx, a);
}
QVariant QQmlValueType::value()
@@ -225,35 +217,6 @@ void QQmlValueType::setValue(const QVariant &value)
QMetaType::construct(typeId, gadgetPtr, value.constData());
}
-bool QQmlValueType::isEqual(const QVariant &other) const
-{
- Q_ASSERT(gadgetPtr);
- return QVariant(typeId, gadgetPtr) == other;
-}
-
-QString QQmlValueType::toString() const
-{
- const QMetaObject *mo = metaObject();
- const int toStringIndex = mo->indexOfMethod("toString()");
- if (toStringIndex != -1) {
- QString result;
- void *args[] = { &result, 0 };
- _metaObject->d.static_metacall(reinterpret_cast<QObject*>(gadgetPtr), QMetaObject::InvokeMetaMethod, toStringIndex, args);
- return result;
- }
- QString result = QString::fromUtf8(QMetaType::typeName(typeId));
- result += QLatin1Char('(');
- const int propCount = mo->propertyCount();
- for (int i = 0; i < propCount; ++i) {
- QVariant value = mo->property(i).read(this);
- result += value.toString();
- if (i < propCount - 1)
- result += QStringLiteral(", ");
- }
- result += QLatin1Char(')');
- return result;
-}
-
QAbstractDynamicMetaObject *QQmlValueType::toDynamicMetaObject(QObject *)
{
return this;
diff --git a/src/qml/qml/qqmlvaluetype_p.h b/src/qml/qml/qqmlvaluetype_p.h
index cd9e51957d..5c411f0e57 100644
--- a/src/qml/qml/qqmlvaluetype_p.h
+++ b/src/qml/qml/qqmlvaluetype_p.h
@@ -63,42 +63,16 @@ public:
QQmlValueType(int userType, const QMetaObject *metaObject);
~QQmlValueType();
void read(QObject *, int);
- void readVariantValue(QObject *, int, QVariant *);
void write(QObject *, int, QQmlPropertyPrivate::WriteFlags flags);
- void writeVariantValue(QObject *, int, QQmlPropertyPrivate::WriteFlags, QVariant *);
QVariant value();
void setValue(const QVariant &);
- QString toString() const;
- bool isEqual(const QVariant &value) const;
-
- void *gadget() const { return gadgetPtr; }
-
- inline int userType() const
- {
- return typeId;
-
- }
// ---- dynamic meta object data interface
virtual QAbstractDynamicMetaObject *toDynamicMetaObject(QObject *);
virtual void objectDestroyed(QObject *);
virtual int metaCall(QObject *obj, QMetaObject::Call type, int _id, void **argv);
// ----
-protected:
- inline void readProperty(QObject *obj, int idx, void *p)
- {
- void *a[] = { p, 0 };
- QMetaObject::metacall(obj, QMetaObject::ReadProperty, idx, a);
- }
-
- inline void writeProperty(QObject *obj, int idx, QQmlPropertyPrivate::WriteFlags flags, void *p)
- {
- int status = -1;
- void *a[] = { p, 0, &status, &flags };
- QMetaObject::metacall(obj, QMetaObject::WriteProperty, idx, a);
- }
-
private:
const QMetaObject *_metaObject;
int typeId;
diff --git a/src/qml/qml/qqmlvaluetypewrapper.cpp b/src/qml/qml/qqmlvaluetypewrapper.cpp
index 8de5df9792..8ed1169ec7 100644
--- a/src/qml/qml/qqmlvaluetypewrapper.cpp
+++ b/src/qml/qml/qqmlvaluetypewrapper.cpp
@@ -79,10 +79,31 @@ using namespace QV4;
Heap::QQmlValueTypeWrapper::QQmlValueTypeWrapper(ExecutionEngine *engine)
: Heap::Object(engine)
+ , gadgetPtr(0)
{
setVTable(QV4::QQmlValueTypeWrapper::staticVTable());
}
+Heap::QQmlValueTypeWrapper::~QQmlValueTypeWrapper()
+{
+ if (gadgetPtr)
+ QMetaType::destroy(metaType, gadgetPtr);
+}
+
+void Heap::QQmlValueTypeWrapper::setValue(const QVariant &value) const
+{
+ Q_ASSERT(metaType == value.userType());
+ QMetaType::destruct(metaType, gadgetPtr);
+ QMetaType::construct(metaType, gadgetPtr, value.constData());
+}
+
+QVariant Heap::QQmlValueTypeWrapper::toVariant() const
+{
+ Q_ASSERT(gadgetPtr);
+ return QVariant(metaType, gadgetPtr);
+}
+
+
Heap::QQmlValueTypeReference::QQmlValueTypeReference(ExecutionEngine *engine)
: Heap::QQmlValueTypeWrapper(engine)
{
@@ -99,33 +120,39 @@ bool QQmlValueTypeReference::readReferenceValue() const
if (writebackProperty.userType() == QMetaType::QVariant) {
// variant-containing-value-type reference
QVariant variantReferenceValue;
- d()->type->readVariantValue(d()->object, d()->property, &variantReferenceValue);
+
+ void *a[] = { &variantReferenceValue, 0 };
+ QMetaObject::metacall(d()->object, QMetaObject::ReadProperty, d()->property, a);
+
int variantReferenceType = variantReferenceValue.userType();
- if (variantReferenceType != d()->type->userType()) {
+ if (variantReferenceType != d()->metaType) {
// This is a stale VariantReference. That is, the variant has been
// overwritten with a different type in the meantime.
// We need to modify this reference to the updated value type, if
// possible, or return false if it is not a value type.
if (QQmlValueTypeFactory::isValueType(variantReferenceType)) {
- QQmlValueType *vt = 0;
QQmlPropertyCache *cache = 0;
- if (const QMetaObject *mo = QQmlValueTypeFactory::metaObjectForMetaType(variantReferenceType)) {
- vt = new QQmlValueType(variantReferenceType, mo);
+ if (const QMetaObject *mo = QQmlValueTypeFactory::metaObjectForMetaType(variantReferenceType))
cache = QQmlEnginePrivate::get(engine())->cache(mo);
- }
- d()->type.reset(vt);
+ if (d()->gadgetPtr)
+ QMetaType::destroy(d()->metaType, d()->gadgetPtr);
+ d()->gadgetPtr = 0;
d()->propertyCache = cache;
- if (!d()->type) {
+ d()->metaType = variantReferenceType;
+ if (cache) {
+ d()->gadgetPtr = QMetaType::create(d()->metaType);
+ } else {
return false;
}
} else {
return false;
}
}
- d()->type->setValue(variantReferenceValue);
+ d()->setValue(variantReferenceValue);
} else {
// value-type reference
- d()->type->read(d()->object, d()->property);
+ void *args[] = { d()->gadget(), 0 };
+ QMetaObject::metacall(d()->object, QMetaObject::ReadProperty, d()->property, args);
}
return true;
}
@@ -149,8 +176,10 @@ ReturnedValue QQmlValueTypeWrapper::create(ExecutionEngine *engine, QObject *obj
Scoped<QQmlValueTypeReference> r(scope, engine->memoryManager->alloc<QQmlValueTypeReference>(engine));
ScopedObject proto(scope, engine->qmlExtensions()->valueTypeWrapperPrototype);
r->setPrototype(proto);
- r->d()->type.reset(new QQmlValueType(typeId, metaObject)); r->d()->object = object; r->d()->property = property;
+ r->d()->object = object; r->d()->property = property;
r->d()->propertyCache = QQmlEnginePrivate::get(engine)->cache(metaObject);
+ r->d()->metaType = typeId;
+ r->d()->gadgetPtr = QMetaType::create(r->d()->metaType);
return r->asReturnedValue();
}
@@ -162,8 +191,10 @@ ReturnedValue QQmlValueTypeWrapper::create(ExecutionEngine *engine, const QVaria
Scoped<QQmlValueTypeWrapper> r(scope, engine->memoryManager->alloc<QQmlValueTypeWrapper>(engine));
ScopedObject proto(scope, engine->qmlExtensions()->valueTypeWrapperPrototype);
r->setPrototype(proto);
- r->d()->type.reset(new QQmlValueType(typeId, metaObject)); r->d()->type->setValue(value);
r->d()->propertyCache = QQmlEnginePrivate::get(engine)->cache(metaObject);
+ r->d()->metaType = typeId;
+ r->d()->gadgetPtr = QMetaType::create(r->d()->metaType);
+ r->d()->setValue(value);
return r->asReturnedValue();
}
@@ -172,7 +203,7 @@ QVariant QQmlValueTypeWrapper::toVariant() const
if (const QQmlValueTypeReference *ref = as<const QQmlValueTypeReference>())
if (!ref->readReferenceValue())
return QVariant();
- return d()->type->value();
+ return d()->toVariant();
}
void QQmlValueTypeWrapper::destroy(Heap::Base *that)
@@ -209,9 +240,7 @@ bool QQmlValueTypeWrapper::isEqual(const QVariant& value)
if (QQmlValueTypeReference *ref = as<QQmlValueTypeReference>())
if (!ref->readReferenceValue())
return false;
- if (d()->type->isEqual(value))
- return true;
- return (value == d()->type->value());
+ return (value == d()->toVariant());
}
ReturnedValue QQmlValueTypeWrapper::method_toString(CallContext *ctx)
@@ -226,7 +255,19 @@ ReturnedValue QQmlValueTypeWrapper::method_toString(CallContext *ctx)
if (QQmlValueTypeReference *ref = w->as<QQmlValueTypeReference>())
if (!ref->readReferenceValue())
return Encode::undefined();
- return Encode(ctx->engine()->newString(w->d()->type->toString()));
+
+ QString result = QString::fromUtf8(QMetaType::typeName(w->d()->metaType));
+ result += QLatin1Char('(');
+ const QMetaObject *mo = w->d()->propertyCache->metaObject();
+ const int propCount = mo->propertyCount();
+ for (int i = 0; i < propCount; ++i) {
+ QVariant value = mo->property(i).readOnGadget(w->d()->gadget());
+ result += value.toString();
+ if (i < propCount - 1)
+ result += QStringLiteral(", ");
+ }
+ result += QLatin1Char(')');
+ return Encode(ctx->engine()->newString(result));
}
ReturnedValue QQmlValueTypeWrapper::get(Managed *m, String *name, bool *hasProperty)
@@ -235,10 +276,6 @@ ReturnedValue QQmlValueTypeWrapper::get(Managed *m, String *name, bool *hasPrope
QQmlValueTypeWrapper *r = static_cast<QQmlValueTypeWrapper *>(m);
QV4::ExecutionEngine *v4 = m->engine();
- // ### Remove this once we can do proper this calls.
- if (name == v4->id_toString)
- return Object::get(m, name, hasProperty);
-
// Note: readReferenceValue() can change the reference->type.
if (QQmlValueTypeReference *reference = r->as<QQmlValueTypeReference>()) {
if (!reference->readReferenceValue())
@@ -263,10 +300,13 @@ ReturnedValue QQmlValueTypeWrapper::get(Managed *m, String *name, bool *hasPrope
if (result->propType == metatype) { \
cpptype v; \
void *args[] = { &v, 0 }; \
- QMetaObject::metacall(r->d()->type.data(), QMetaObject::ReadProperty, result->coreIndex, args); \
+ metaObject->d.static_metacall(reinterpret_cast<QObject*>(gadget), QMetaObject::ReadProperty, result->coreIndex, args); \
return QV4::Encode(constructor(v)); \
}
+ const QMetaObject *metaObject = r->d()->propertyCache->metaObject();
+ void *gadget = r->d()->gadget();
+
// These four types are the most common used by the value type wrappers
VALUE_TYPE_LOAD(QMetaType::QReal, qreal, qreal);
VALUE_TYPE_LOAD(QMetaType::Int, int, int);
@@ -275,7 +315,7 @@ ReturnedValue QQmlValueTypeWrapper::get(Managed *m, String *name, bool *hasPrope
QVariant v(result->propType, (void *)0);
void *args[] = { v.data(), 0 };
- QMetaObject::metacall(r->d()->type.data(), QMetaObject::ReadProperty, result->coreIndex, args);
+ metaObject->d.static_metacall(reinterpret_cast<QObject*>(gadget), QMetaObject::ReadProperty, result->coreIndex, args);
return v4->v8Engine->fromVariant(v);
#undef VALUE_TYPE_ACCESSOR
}
@@ -289,80 +329,90 @@ void QQmlValueTypeWrapper::put(Managed *m, String *name, const ValueRef value)
return;
Scoped<QQmlValueTypeWrapper> r(scope, static_cast<QQmlValueTypeWrapper *>(m));
+ Scoped<QQmlValueTypeReference> reference(scope, m->d());
- QByteArray propName = name->toQString().toUtf8();
- if (QQmlValueTypeReference *reference = r->as<QQmlValueTypeReference>()) {
+ int writeBackPropertyType = -1;
+
+ if (reference) {
QMetaProperty writebackProperty = reference->d()->object->metaObject()->property(reference->d()->property);
if (!writebackProperty.isWritable() || !reference->readReferenceValue())
return;
- // we lookup the index after readReferenceValue() since it can change the reference->type.
- int index = r->d()->type->metaObject()->indexOfProperty(propName.constData());
- if (index == -1)
+ writeBackPropertyType = writebackProperty.userType();
+ }
+
+ const QMetaObject *metaObject = r->d()->propertyCache->metaObject();
+ const QQmlPropertyData *pd = r->d()->propertyCache->property(name, 0, 0);
+ if (!pd)
+ return;
+ QMetaProperty property = metaObject->property(pd->coreIndex);
+ Q_ASSERT(property.isValid());
+
+ QQmlBinding *newBinding = 0;
+
+ QV4::ScopedFunctionObject f(scope, value);
+ if (reference && f) {
+ if (!f->bindingKeyFlag()) {
+ // assigning a JS function to a non-var-property is not allowed.
+ QString error = QStringLiteral("Cannot assign JavaScript function to value-type property");
+ Scoped<String> e(scope, v4->newString(error));
+ v4->throwError(e);
return;
- QMetaProperty p = r->d()->type->metaObject()->property(index);
-
- QQmlBinding *newBinding = 0;
-
- QV4::ScopedFunctionObject f(scope, value);
- if (f) {
- if (!f->bindingKeyFlag()) {
- // assigning a JS function to a non-var-property is not allowed.
- QString error = QStringLiteral("Cannot assign JavaScript function to value-type property");
- Scoped<String> e(scope, v4->newString(error));
- v4->throwError(e);
- return;
- }
+ }
- QQmlContextData *context = QmlContextWrapper::callingContext(v4);
+ QQmlContextData *context = QmlContextWrapper::callingContext(v4);
- QQmlPropertyData cacheData;
- cacheData.setFlags(QQmlPropertyData::IsWritable |
- QQmlPropertyData::IsValueTypeVirtual);
- cacheData.propType = reference->d()->object->metaObject()->property(reference->d()->property).userType();
- cacheData.coreIndex = reference->d()->property;
- cacheData.valueTypeFlags = 0;
- cacheData.valueTypeCoreIndex = index;
- cacheData.valueTypePropType = p.userType();
+ QQmlPropertyData cacheData;
+ cacheData.setFlags(QQmlPropertyData::IsWritable |
+ QQmlPropertyData::IsValueTypeVirtual);
+ cacheData.propType = writeBackPropertyType;
+ cacheData.coreIndex = reference->d()->property;
+ cacheData.valueTypeFlags = 0;
+ cacheData.valueTypeCoreIndex = pd->coreIndex;
+ cacheData.valueTypePropType = property.userType();
- QV4::Scoped<QQmlBindingFunction> bindingFunction(scope, f);
- bindingFunction->initBindingLocation();
+ QV4::Scoped<QQmlBindingFunction> bindingFunction(scope, f);
+ bindingFunction->initBindingLocation();
- newBinding = new QQmlBinding(value, reference->d()->object, context);
- newBinding->setTarget(reference->d()->object, cacheData, context);
- }
+ newBinding = new QQmlBinding(value, reference->d()->object, context);
+ newBinding->setTarget(reference->d()->object, cacheData, context);
+ }
+ if (reference) {
QQmlAbstractBinding *oldBinding =
- QQmlPropertyPrivate::setBinding(reference->d()->object, reference->d()->property, index, newBinding);
+ QQmlPropertyPrivate::setBinding(reference->d()->object, reference->d()->property, pd->coreIndex, newBinding);
if (oldBinding)
oldBinding->destroy();
+ }
- if (!f) {
- QVariant v = v4->v8Engine->toVariant(value, -1);
+ if (newBinding)
+ return;
- if (p.isEnumType() && (QMetaType::Type)v.type() == QMetaType::Double)
- v = v.toInt();
+ QVariant v = v4->v8Engine->toVariant(value, property.userType());
- p.write(reference->d()->type.data(), v);
+ if (property.isEnumType() && (QMetaType::Type)v.type() == QMetaType::Double)
+ v = v.toInt();
- if (writebackProperty.userType() == QMetaType::QVariant) {
- QVariant variantReferenceValue = r->d()->type->value();
- reference->d()->type->writeVariantValue(reference->d()->object, reference->d()->property, 0, &variantReferenceValue);
- } else {
- reference->d()->type->write(reference->d()->object, reference->d()->property, 0);
- }
- }
+ void *gadget = r->d()->gadget();
+ property.writeOnGadget(gadget, v);
- } else {
- int index = r->d()->type->metaObject()->indexOfProperty(propName.constData());
- if (index == -1)
- return;
- QVariant v = v4->v8Engine->toVariant(value, -1);
+ if (reference) {
+ if (writeBackPropertyType == QMetaType::QVariant) {
+ QVariant variantReferenceValue = r->d()->toVariant();
- QMetaProperty p = r->d()->type->metaObject()->property(index);
- p.write(r->d()->type.data(), v);
+ int flags = 0;
+ int status = -1;
+ void *a[] = { &variantReferenceValue, 0, &status, &flags };
+ QMetaObject::metacall(reference->d()->object, QMetaObject::WriteProperty, reference->d()->property, a);
+
+ } else {
+ int flags = 0;
+ int status = -1;
+ void *a[] = { r->d()->gadget(), 0, &status, &flags };
+ QMetaObject::metacall(reference->d()->object, QMetaObject::WriteProperty, reference->d()->property, a);
+ }
}
}
diff --git a/src/qml/qml/qqmlvaluetypewrapper_p.h b/src/qml/qml/qqmlvaluetypewrapper_p.h
index 24031800cd..ad883266bd 100644
--- a/src/qml/qml/qqmlvaluetypewrapper_p.h
+++ b/src/qml/qml/qqmlvaluetypewrapper_p.h
@@ -53,7 +53,6 @@
QT_BEGIN_NAMESPACE
-class QQmlValueType;
class QV8Engine;
namespace QV4 {
@@ -62,8 +61,14 @@ namespace Heap {
struct QQmlValueTypeWrapper : Object {
QQmlValueTypeWrapper(ExecutionEngine *engine);
+ ~QQmlValueTypeWrapper();
mutable QQmlRefPointer<QQmlPropertyCache> propertyCache;
- mutable QScopedPointer<QQmlValueType> type;
+ mutable void *gadgetPtr;
+ mutable int metaType;
+
+ void setValue(const QVariant &value) const;
+ QVariant toVariant() const;
+ void *gadget() const { return gadgetPtr; }
};
}
diff --git a/src/qml/qml/v8/qv8engine_p.h b/src/qml/qml/v8/qv8engine_p.h
index 4a6737a131..18b59f0157 100644
--- a/src/qml/qml/v8/qv8engine_p.h
+++ b/src/qml/qml/v8/qv8engine_p.h
@@ -158,7 +158,6 @@ private:
class QObject;
class QQmlEngine;
-class QQmlValueType;
class QNetworkAccessManager;
class QQmlContextData;