aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorAaron Kennedy <aaron.kennedy@nokia.com>2012-05-24 16:28:54 +0100
committerQt by Nokia <qt-info@nokia.com>2012-06-06 16:51:07 +0200
commita26d7aef3ce61ac0515cf8a324c8badd13bdb017 (patch)
tree1dd22962a7c40df451ae7f9465cf2ca4e4185cb7 /src
parent1fcb3d512c37625e6dfdbd045c755e8d6aca8c57 (diff)
Disallow parent changes for QML created objects
Currently this is protected with a QML_PARENT_TEST environment variable to allow the rest of QtQuick to be updated before it is enforced. Change-Id: I4dd3644cbbce91d67f24c9556637f97eafb00638 Reviewed-by: Kent Hansen <kent.hansen@nokia.com> Reviewed-by: Michael Brasser <michael.brasser@nokia.com>
Diffstat (limited to 'src')
-rw-r--r--src/qml/qml/qqmlcompiler.cpp22
-rw-r--r--src/qml/qml/qqmlcompiler_p.h2
-rw-r--r--src/qml/qml/qqmldata_p.h5
-rw-r--r--src/qml/qml/qqmlengine.cpp17
-rw-r--r--src/qml/qml/qqmlinstruction_p.h4
-rw-r--r--src/qml/qml/qqmlvme.cpp13
6 files changed, 36 insertions, 27 deletions
diff --git a/src/qml/qml/qqmlcompiler.cpp b/src/qml/qml/qqmlcompiler.cpp
index f8625861af..218d719634 100644
--- a/src/qml/qml/qqmlcompiler.cpp
+++ b/src/qml/qml/qqmlcompiler.cpp
@@ -1155,7 +1155,7 @@ bool QQmlCompiler::buildObject(QQmlScript::Object *obj, const BindingContext &ct
return true;
}
-void QQmlCompiler::genObject(QQmlScript::Object *obj)
+void QQmlCompiler::genObject(QQmlScript::Object *obj, bool parentToSuper)
{
QQmlCompiledData::TypeReference &tr = output->types[obj->type];
if (tr.type && obj->metatype->metaObject() == &QQmlComponent::staticMetaObject) {
@@ -1173,6 +1173,7 @@ void QQmlCompiler::genObject(QQmlScript::Object *obj)
create.type = obj->type;
create.line = obj->location.start.line;
create.column = obj->location.start.column;
+ create.parentToSuper = parentToSuper;
output->addInstruction(create);
} else {
@@ -1186,6 +1187,7 @@ void QQmlCompiler::genObject(QQmlScript::Object *obj)
create.data = output->indexForByteArray(obj->custom);
create.type = obj->type;
create.isRoot = (compileState->root == obj);
+ create.parentToSuper = parentToSuper;
output->addInstruction(create);
} else {
Instruction::CreateQMLObject create;
@@ -1975,31 +1977,25 @@ void QQmlCompiler::genPropertyAssignment(QQmlScript::Property *prop,
v->type == Value::ValueInterceptor);
if (v->type == Value::ValueSource) {
- genObject(v->object);
+ genObject(v->object, valueTypeProperty?true:false);
Instruction::StoreValueSource store;
- if (valueTypeProperty) {
+ if (valueTypeProperty)
store.property = genValueTypeData(prop, valueTypeProperty);
- store.owner = 1;
- } else {
+ else
store.property = prop->core;
- store.owner = 0;
- }
QQmlType *valueType = toQmlType(v->object);
store.castValue = valueType->propertyValueSourceCast();
output->addInstruction(store);
} else if (v->type == Value::ValueInterceptor) {
- genObject(v->object);
+ genObject(v->object, valueTypeProperty?true:false);
Instruction::StoreValueInterceptor store;
- if (valueTypeProperty) {
+ if (valueTypeProperty)
store.property = genValueTypeData(prop, valueTypeProperty);
- store.owner = 1;
- } else {
+ else
store.property = prop->core;
- store.owner = 0;
- }
QQmlType *valueType = toQmlType(v->object);
store.castValue = valueType->propertyValueInterceptorCast();
output->addInstruction(store);
diff --git a/src/qml/qml/qqmlcompiler_p.h b/src/qml/qml/qqmlcompiler_p.h
index 2339b6ceea..4b730c2e20 100644
--- a/src/qml/qml/qqmlcompiler_p.h
+++ b/src/qml/qml/qqmlcompiler_p.h
@@ -373,7 +373,7 @@ private:
bool checkValidId(QQmlScript::Value *, const QString &);
- void genObject(QQmlScript::Object *obj);
+ void genObject(QQmlScript::Object *obj, bool parentToSuper = false);
void genObjectBody(QQmlScript::Object *obj);
void genValueTypeProperty(QQmlScript::Object *obj,QQmlScript::Property *);
void genComponent(QQmlScript::Object *obj);
diff --git a/src/qml/qml/qqmldata_p.h b/src/qml/qml/qqmldata_p.h
index eba2f4df6e..879d59722b 100644
--- a/src/qml/qml/qqmldata_p.h
+++ b/src/qml/qml/qqmldata_p.h
@@ -80,7 +80,7 @@ public:
QQmlData()
: ownMemory(true), ownContext(false), indestructible(true), explicitIndestructibleSet(false),
hasTaintedV8Object(false), isQueuedForDeletion(false), rootObjectInCreation(false),
- hasVMEMetaObject(false), notifyList(0), context(0), outerContext(0),
+ hasVMEMetaObject(false), parentFrozen(false), notifyList(0), context(0), outerContext(0),
bindings(0), signalHandlers(0), nextContextObject(0), prevContextObject(0), bindingBitsSize(0), bindingBits(0),
lineNumber(0), columnNumber(0), compiledData(0), deferredIdx(0), v8objectid(0),
propertyCache(0), guards(0), extendedData(0) {
@@ -122,7 +122,8 @@ public:
*/
quint32 rootObjectInCreation:1;
quint32 hasVMEMetaObject:1;
- quint32 dummy:24;
+ quint32 parentFrozen:1;
+ quint32 dummy:23;
struct NotifyList {
quint64 connectionMask;
diff --git a/src/qml/qml/qqmlengine.cpp b/src/qml/qml/qqmlengine.cpp
index 7b4b827409..832f58bcfa 100644
--- a/src/qml/qml/qqmlengine.cpp
+++ b/src/qml/qml/qqmlengine.cpp
@@ -1383,10 +1383,23 @@ void QQmlData::destroyed(QObject *object)
delete this;
}
+DEFINE_BOOL_CONFIG_OPTION(parentTest, QML_PARENT_TEST);
+
void QQmlData::parentChanged(QObject *object, QObject *parent)
{
- Q_UNUSED(object);
- Q_UNUSED(parent);
+ if (parentTest()) {
+ if (parentFrozen && !QObjectPrivate::get(object)->wasDeleted) {
+ QString on;
+ QString pn;
+
+ { QDebug dbg(&on); dbg << object; on = on.left(on.length() - 1); }
+ { QDebug dbg(&pn); dbg << parent; pn = pn.left(pn.length() - 1); }
+
+ qFatal("Object %s has had its parent frozen by QML and cannot be changed.\n"
+ "User code is attempting to change it to %s.\n"
+ "This behavior is NOT supported!", qPrintable(on), qPrintable(pn));
+ }
+ }
}
bool QQmlData::hasBindingBit(int bit) const
diff --git a/src/qml/qml/qqmlinstruction_p.h b/src/qml/qml/qqmlinstruction_p.h
index bd279d66d8..8b7dc383f8 100644
--- a/src/qml/qml/qqmlinstruction_p.h
+++ b/src/qml/qml/qqmlinstruction_p.h
@@ -200,6 +200,7 @@ union QQmlInstruction
ushort column;
ushort line;
bool isRoot;
+ bool parentToSuper;
};
struct instr_createSimple {
QML_INSTR_HEADER
@@ -208,6 +209,7 @@ union QQmlInstruction
int type;
ushort column;
ushort line;
+ bool parentToSuper;
};
struct instr_storeMeta {
QML_INSTR_HEADER
@@ -222,13 +224,11 @@ union QQmlInstruction
struct instr_assignValueSource {
QML_INSTR_HEADER
QQmlPropertyRawData property;
- int owner;
int castValue;
};
struct instr_assignValueInterceptor {
QML_INSTR_HEADER
QQmlPropertyRawData property;
- int owner;
int castValue;
};
struct instr_initV8Bindings {
diff --git a/src/qml/qml/qqmlvme.cpp b/src/qml/qml/qqmlvme.cpp
index bb245198bf..b9924e384c 100644
--- a/src/qml/qml/qqmlvme.cpp
+++ b/src/qml/qml/qqmlvme.cpp
@@ -609,13 +609,14 @@ QObject *QQmlVME::run(QList<QQmlError> *errors,
customParser->setCustomData(o, DATAS.at(instr.data));
}
if (!objects.isEmpty()) {
- QObject *parent = objects.top();
+ QObject *parent = objects.at(objects.count() - 1 - (instr.parentToSuper?1:0));
#if 0 // ### refactor
if (o->isWidgetType() && parent->isWidgetType())
static_cast<QWidget*>(o)->setParent(static_cast<QWidget*>(parent));
else
#endif
QQml_setParent_noEvent(o, parent);
+ ddata->parentFrozen = true;
}
objects.push(o);
QML_END_INSTR(CreateCppObject)
@@ -642,9 +643,10 @@ QObject *QQmlVME::run(QList<QQmlError> *errors,
ddata->prevContextObject = &CTXT->contextObjects;
CTXT->contextObjects = ddata;
- QObject *parent = objects.top();
+ QObject *parent = objects.at(objects.count() - 1 - (instr.parentToSuper?1:0));
QQml_setParent_noEvent(o, parent);
+ ddata->parentFrozen = true;
objects.push(o);
QML_END_INSTR(CreateSimpleObject)
@@ -905,19 +907,16 @@ QObject *QQmlVME::run(QList<QQmlError> *errors,
QML_BEGIN_INSTR(StoreValueSource)
QObject *obj = objects.pop();
QQmlPropertyValueSource *vs = reinterpret_cast<QQmlPropertyValueSource *>(reinterpret_cast<char *>(obj) + instr.castValue);
- QObject *target = objects.at(objects.count() - 1 - instr.owner);
-
- obj->setParent(target);
+ QObject *target = obj->parent();
vs->setTarget(QQmlPropertyPrivate::restore(target, instr.property, CTXT));
QML_END_INSTR(StoreValueSource)
QML_BEGIN_INSTR(StoreValueInterceptor)
QObject *obj = objects.pop();
QQmlPropertyValueInterceptor *vi = reinterpret_cast<QQmlPropertyValueInterceptor *>(reinterpret_cast<char *>(obj) + instr.castValue);
- QObject *target = objects.at(objects.count() - 1 - instr.owner);
+ QObject *target = obj->parent();
QQmlProperty prop =
QQmlPropertyPrivate::restore(target, instr.property, CTXT);
- obj->setParent(target);
vi->setTarget(prop);
QQmlVMEMetaObject *mo = QQmlVMEMetaObject::get(target);
Q_ASSERT(mo);