summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAaron Kennedy <aaron.kennedy@nokia.com>2009-07-14 03:54:55 (GMT)
committerAaron Kennedy <aaron.kennedy@nokia.com>2009-07-15 07:30:16 (GMT)
commit4f7e21dc04ce93531ef68f7694a5e8969448de8b (patch)
treece7e8170b5be6c974420d012a03f620f86cd6d8d
parent9eca9e028884fb82d97e284826faa7965af356bd (diff)
downloadQt-4f7e21dc04ce93531ef68f7694a5e8969448de8b.zip
Qt-4f7e21dc04ce93531ef68f7694a5e8969448de8b.tar.gz
Qt-4f7e21dc04ce93531ef68f7694a5e8969448de8b.tar.bz2
Rework compiler to a two phase analyse/generate approach
-rw-r--r--demos/declarative/flickr/content/Star.qml4
-rw-r--r--src/corelib/kernel/qmetaobjectbuilder.cpp81
-rw-r--r--src/corelib/kernel/qmetaobjectbuilder_p.h2
-rw-r--r--src/declarative/qml/qml.pri1
-rw-r--r--src/declarative/qml/qmlcompiledcomponent.cpp19
-rw-r--r--src/declarative/qml/qmlcompiledcomponent_p.h6
-rw-r--r--src/declarative/qml/qmlcompiler.cpp1728
-rw-r--r--src/declarative/qml/qmlcompiler_p.h117
-rw-r--r--src/declarative/qml/qmlcompositetypemanager.cpp2
-rw-r--r--src/declarative/qml/qmlcontext.cpp9
-rw-r--r--src/declarative/qml/qmldom.cpp1
-rw-r--r--src/declarative/qml/qmlinstruction.cpp29
-rw-r--r--src/declarative/qml/qmlinstruction_p.h20
-rw-r--r--src/declarative/qml/qmlmetaproperty.cpp24
-rw-r--r--src/declarative/qml/qmlparser.cpp44
-rw-r--r--src/declarative/qml/qmlparser_p.h30
-rw-r--r--src/declarative/qml/qmlvme.cpp72
-rw-r--r--src/declarative/qml/qmlvmemetaobject.cpp11
-rw-r--r--src/declarative/qml/qmlvmemetaobject_p.h10
-rw-r--r--tests/auto/declarative/qmlbindengine/testtypes.h22
-rw-r--r--tests/auto/declarative/qmlparser/duplicateIDs.errors.txt2
-rw-r--r--tests/auto/declarative/qmlparser/failingComponent.errors.txt2
-rw-r--r--tests/auto/declarative/qmlparser/fakeDotProperty.errors.txt2
-rw-r--r--tests/auto/declarative/qmlparser/idProperty.txt2
-rw-r--r--tests/auto/declarative/qmlparser/invalidID.2.errors.txt2
-rw-r--r--tests/auto/declarative/qmlparser/invalidID.3.errors.txt2
-rw-r--r--tests/auto/declarative/qmlparser/invalidID.4.errors.txt2
-rw-r--r--tests/auto/declarative/qmlparser/invalidID.errors.txt2
-rw-r--r--tests/auto/declarative/qmlparser/missingSignal.errors.txt2
-rw-r--r--tests/auto/declarative/qmlparser/nonexistantProperty.1.errors.txt2
-rw-r--r--tests/auto/declarative/qmlparser/nonexistantProperty.2.errors.txt2
-rw-r--r--tests/auto/declarative/qmlparser/nonexistantProperty.3.errors.txt2
-rw-r--r--tests/auto/declarative/qmlparser/nonexistantProperty.4.errors.txt2
-rw-r--r--tests/auto/declarative/qmlparser/nonexistantProperty.6.errors.txt2
-rw-r--r--tests/auto/declarative/qmlparser/readOnly.1.errors.txt2
-rw-r--r--tests/auto/declarative/qmlparser/readOnly.2.errors.txt2
-rw-r--r--tests/auto/declarative/qmlparser/tst_qmlparser.cpp8
-rw-r--r--tests/auto/declarative/qmlparser/unsupportedProperty.errors.txt2
-rw-r--r--tests/auto/declarative/qmlparser/wrongType.1.errors.txt2
-rw-r--r--tests/auto/declarative/qmlparser/wrongType.10.errors.txt2
-rw-r--r--tests/auto/declarative/qmlparser/wrongType.11.errors.txt2
-rw-r--r--tests/auto/declarative/qmlparser/wrongType.12.errors.txt2
-rw-r--r--tests/auto/declarative/qmlparser/wrongType.13.errors.txt2
-rw-r--r--tests/auto/declarative/qmlparser/wrongType.14.errors.txt2
-rw-r--r--tests/auto/declarative/qmlparser/wrongType.2.errors.txt2
-rw-r--r--tests/auto/declarative/qmlparser/wrongType.3.errors.txt2
-rw-r--r--tests/auto/declarative/qmlparser/wrongType.4.errors.txt2
-rw-r--r--tests/auto/declarative/qmlparser/wrongType.5.errors.txt2
-rw-r--r--tests/auto/declarative/qmlparser/wrongType.6.errors.txt2
-rw-r--r--tests/auto/declarative/qmlparser/wrongType.7.errors.txt2
-rw-r--r--tests/auto/declarative/qmlparser/wrongType.8.errors.txt2
-rw-r--r--tests/auto/declarative/qmlparser/wrongType.9.errors.txt2
52 files changed, 1252 insertions, 1050 deletions
diff --git a/demos/declarative/flickr/content/Star.qml b/demos/declarative/flickr/content/Star.qml
index 2c2807a..0828bc0 100644
--- a/demos/declarative/flickr/content/Star.qml
+++ b/demos/declarative/flickr/content/Star.qml
@@ -3,8 +3,8 @@ Item {
width: 24
height: 24
- property string rating
- property string on
+ property int rating
+ property bool on
signal clicked
diff --git a/src/corelib/kernel/qmetaobjectbuilder.cpp b/src/corelib/kernel/qmetaobjectbuilder.cpp
index 8775c5c..e6817fe 100644
--- a/src/corelib/kernel/qmetaobjectbuilder.cpp
+++ b/src/corelib/kernel/qmetaobjectbuilder.cpp
@@ -1167,8 +1167,10 @@ static QByteArray buildParameterNames
// Build a QMetaObject in "buf" based on the information in "d".
// If "buf" is null, then return the number of bytes needed to
-// build the QMetaObject.
-static int buildMetaObject(QMetaObjectBuilderPrivate *d, char *buf)
+// build the QMetaObject. Returns -1 if the metaobject if
+// relocatable is set, but the metaobject contains extradata.
+static int buildMetaObject(QMetaObjectBuilderPrivate *d, char *buf,
+ bool relocatable)
{
int size = 0;
int dataIndex;
@@ -1176,18 +1178,23 @@ static int buildMetaObject(QMetaObjectBuilderPrivate *d, char *buf)
int index;
bool hasNotifySignals = false;
+ if (relocatable &&
+ (d->relatedMetaObjects.size() > 0 || d->staticMetacallFunction))
+ return -1;
+
// Create the main QMetaObject structure at the start of the buffer.
QMetaObject *meta = reinterpret_cast<QMetaObject *>(buf);
size += sizeof(QMetaObject);
ALIGN(size, int);
if (buf) {
- meta->d.superdata = d->superClass;
+ if (!relocatable) meta->d.superdata = d->superClass;
meta->d.extradata = 0;
}
// Populate the QMetaObjectPrivate structure.
QMetaObjectPrivate *pmeta
= reinterpret_cast<QMetaObjectPrivate *>(buf + size);
+ int pmetaSize = size;
dataIndex = 13; // Number of fields in the QMetaObjectPrivate.
for (index = 0; index < d->properties.size(); ++index) {
if (d->properties[index].notifySignal != -1) {
@@ -1246,8 +1253,13 @@ static int buildMetaObject(QMetaObjectBuilderPrivate *d, char *buf)
size += dataIndex * sizeof(int);
char *str = reinterpret_cast<char *>(buf + size);
if (buf) {
- meta->d.stringdata = str;
- meta->d.data = reinterpret_cast<uint *>(data);
+ if (relocatable) {
+ meta->d.stringdata = reinterpret_cast<const char *>((intptr_t)size);
+ meta->d.data = reinterpret_cast<uint *>((intptr_t)pmetaSize);
+ } else {
+ meta->d.stringdata = str;
+ meta->d.data = reinterpret_cast<uint *>(data);
+ }
}
// Reset the current data position to just past the QMetaObjectPrivate.
@@ -1422,12 +1434,67 @@ static int buildMetaObject(QMetaObjectBuilderPrivate *d, char *buf)
*/
QMetaObject *QMetaObjectBuilder::toMetaObject() const
{
- int size = buildMetaObject(d, 0);
+ int size = buildMetaObject(d, 0, false);
char *buf = reinterpret_cast<char *>(qMalloc(size));
- buildMetaObject(d, buf);
+ buildMetaObject(d, buf, false);
return reinterpret_cast<QMetaObject *>(buf);
}
+/*
+ \internal
+
+ Converts this meta object builder into relocatable data. This data can
+ be stored, copied and later passed to fromRelocatableData() to create a
+ concrete QMetaObject.
+
+ The data is specific to the architecture on which it was created, but is not
+ specific to the process that created it. Not all meta object builder's can
+ be converted to data in this way. If \a ok is provided, it will be set to
+ true if the conversion succeeds, and false otherwise. If a
+ staticMetacallFunction() or any relatedMetaObject()'s are specified the
+ conversion to relocatable data will fail.
+*/
+QByteArray QMetaObjectBuilder::toRelocatableData(bool *ok) const
+{
+ int size = buildMetaObject(d, 0, true);
+ if (size == -1) {
+ if (ok) *ok = false;
+ return QByteArray();
+ }
+
+ QByteArray data;
+ data.resize(size);
+ char *buf = data.data();
+ buildMetaObject(d, buf, true);
+ if (ok) *ok = true;
+ return data;
+}
+
+/*
+ \internal
+
+ Sets the \a data returned from toRelocatableData() onto a concrete
+ QMetaObject instance, \a output. As the meta object's super class is not
+ saved in the relocatable data, it must be passed as \a superClass.
+*/
+void QMetaObjectBuilder::fromRelocatableData(QMetaObject *output,
+ const QMetaObject *superclass,
+ const QByteArray &data)
+{
+ if (!output)
+ return;
+
+ const char *buf = data.constData();
+ const QMetaObject *dataMo = reinterpret_cast<const QMetaObject *>(buf);
+
+ intptr_t stringdataOffset = (intptr_t)dataMo->d.stringdata;
+ intptr_t dataOffset = (intptr_t)dataMo->d.data;
+
+ output->d.superdata = superclass;
+ output->d.stringdata = buf + stringdataOffset;
+ output->d.data = reinterpret_cast<const uint *>(buf + dataOffset);
+}
+
/*!
\typedef QMetaObjectBuilder::StaticMetacallFunction
diff --git a/src/corelib/kernel/qmetaobjectbuilder_p.h b/src/corelib/kernel/qmetaobjectbuilder_p.h
index 952364a..d503163 100644
--- a/src/corelib/kernel/qmetaobjectbuilder_p.h
+++ b/src/corelib/kernel/qmetaobjectbuilder_p.h
@@ -169,6 +169,8 @@ public:
void setStaticMetacallFunction(QMetaObjectBuilder::StaticMetacallFunction value);
QMetaObject *toMetaObject() const;
+ QByteArray toRelocatableData(bool * = 0) const;
+ static void fromRelocatableData(QMetaObject *, const QMetaObject *, const QByteArray &);
#ifndef QT_NO_DATASTREAM
void serialize(QDataStream& stream) const;
diff --git a/src/declarative/qml/qml.pri b/src/declarative/qml/qml.pri
index f549a5e..d8f0f7f 100644
--- a/src/declarative/qml/qml.pri
+++ b/src/declarative/qml/qml.pri
@@ -12,6 +12,7 @@ SOURCES += qml/qmlparser.cpp \
qml/qmlproxymetaobject.cpp \
qml/qmlvme.cpp \
qml/qmlcompiler.cpp \
+ qml/qmlcompileddata.cpp \
qml/qmlcompiledcomponent.cpp \
qml/qmlboundsignal.cpp \
qml/qmldom.cpp \
diff --git a/src/declarative/qml/qmlcompiledcomponent.cpp b/src/declarative/qml/qmlcompiledcomponent.cpp
index bea736a..6ce89b7 100644
--- a/src/declarative/qml/qmlcompiledcomponent.cpp
+++ b/src/declarative/qml/qmlcompiledcomponent.cpp
@@ -50,7 +50,6 @@ QT_BEGIN_NAMESPACE
DEFINE_BOOL_CONFIG_OPTION(compilerDump, QML_COMPILER_DUMP);
QmlCompiledComponent::QmlCompiledComponent()
-: dumpStatus(NoDump)
{
}
@@ -60,7 +59,6 @@ QmlCompiledComponent::~QmlCompiledComponent()
qFree(synthesizedMetaObjects.at(ii));
}
-
void QmlCompiledComponent::dumpInstructions()
{
if (!compilerDump())
@@ -76,21 +74,4 @@ void QmlCompiledComponent::dumpInstructions()
qWarning() << "-------------------------------------------------------------------------------";
}
-void QmlCompiledComponent::dumpPre()
-{
- if (!(dumpStatus & DumpPre)) {
- dumpInstructions();
- dumpStatus = (DumpStatus)(dumpStatus | DumpPre);
- }
-}
-
-void QmlCompiledComponent::dumpPost()
-{
- if (!(dumpStatus & DumpPost)) {
- dumpInstructions();
- dumpStatus = (DumpStatus)(dumpStatus | DumpPost);
- }
-
-}
-
QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlcompiledcomponent_p.h b/src/declarative/qml/qmlcompiledcomponent_p.h
index 0945892..ddc1124 100644
--- a/src/declarative/qml/qmlcompiledcomponent_p.h
+++ b/src/declarative/qml/qmlcompiledcomponent_p.h
@@ -74,12 +74,8 @@ public:
QmlCompiledComponent();
~QmlCompiledComponent();
- void dumpPre();
- void dumpPost();
-
-private:
- enum DumpStatus { NoDump = 0x00, DumpPre = 0x01, DumpPost = 0x02 } dumpStatus;
void dumpInstructions();
+private:
void dump(QmlInstruction *, int idx = -1);
friend class QmlCompiler;
friend class QmlDomDocument;
diff --git a/src/declarative/qml/qmlcompiler.cpp b/src/declarative/qml/qmlcompiler.cpp
index b04c932..dafc581 100644
--- a/src/declarative/qml/qmlcompiler.cpp
+++ b/src/declarative/qml/qmlcompiler.cpp
@@ -71,90 +71,6 @@ QT_BEGIN_NAMESPACE
using namespace QmlParser;
-int QmlCompiledData::indexForString(const QString &data)
-{
- int idx = primitives.indexOf(data);
- if (idx == -1) {
- idx = primitives.count();
- primitives << data;
- }
- return idx;
-}
-
-int QmlCompiledData::indexForByteArray(const QByteArray &data)
-{
- int idx = datas.indexOf(data);
- if (idx == -1) {
- idx = datas.count();
- datas << data;
- }
- return idx;
-}
-
-int QmlCompiledData::indexForFloat(float *data, int count)
-{
- Q_ASSERT(count > 0);
-
- for (int ii = 0; ii <= floatData.count() - count; ++ii) {
- bool found = true;
- for (int jj = 0; jj < count; ++jj) {
- if (floatData.at(ii + jj) != data[jj]) {
- found = false;
- break;
- }
- }
-
- if (found)
- return ii;
- }
-
- int idx = floatData.count();
- for (int ii = 0; ii < count; ++ii)
- floatData << data[ii];
-
- return idx;
-}
-
-int QmlCompiledData::indexForInt(int *data, int count)
-{
- Q_ASSERT(count > 0);
-
- for (int ii = 0; ii <= intData.count() - count; ++ii) {
- bool found = true;
- for (int jj = 0; jj < count; ++jj) {
- if (intData.at(ii + jj) != data[jj]) {
- found = false;
- break;
- }
- }
-
- if (found)
- return ii;
- }
-
- int idx = intData.count();
- for (int ii = 0; ii < count; ++ii)
- intData << data[ii];
-
- return idx;
-}
-
-int QmlCompiledData::indexForLocation(const QmlParser::Location &l)
-{
- // ### FIXME
- int rv = locations.count();
- locations << l;
- return rv;
-}
-
-int QmlCompiledData::indexForLocation(const QmlParser::LocationSpan &l)
-{
- // ### FIXME
- int rv = locations.count();
- locations << l.start << l.end;
- return rv;
-}
-
QmlCompiler::QmlCompiler()
: output(0)
{
@@ -241,14 +157,13 @@ bool QmlCompiler::isSignalPropertyName(const QByteArray &name)
}
// Compile a simple assignment of v to prop into instr
-bool QmlCompiler::compileStoreInstruction(QmlInstruction &instr,
- const QMetaProperty &prop,
- QmlParser::Value *v)
+bool QmlCompiler::testLiteralAssignment(const QMetaProperty &prop,
+ QmlParser::Value *v)
{
QString string = v->value.asScript();
if (!prop.isWritable())
- COMPILE_EXCEPTION2(v, "Cannot assign literal value to read-only property" << prop.name());
+ COMPILE_EXCEPTION2(v, "Invalid property assignment: read-only property");
if (prop.isEnumType()) {
int value;
@@ -257,12 +172,136 @@ bool QmlCompiler::compileStoreInstruction(QmlInstruction &instr,
} else
value = prop.enumerator().keyToValue(string.toLatin1().constData());
if (value == -1)
- COMPILE_EXCEPTION2(v, "Cannot assign unknown enumeration to property" << prop.name());
+ COMPILE_EXCEPTION2(v, "Invalid property assignment: unknown enumeration");
+ return true;
+ }
+ int type = prop.userType();
+ switch(type) {
+ case -1:
+ break;
+ case QVariant::String:
+ if (!v->value.isString()) COMPILE_EXCEPTION2(v, "Invalid property assignment: string expected");
+ break;
+ case QVariant::Url:
+ if (!v->value.isString()) COMPILE_EXCEPTION2(v, "Invalid property assignment: url expected");
+ break;
+ case QVariant::UInt:
+ {
+ bool ok;
+ string.toUInt(&ok);
+ if (!v->value.isNumber() || !ok) COMPILE_EXCEPTION2(v, "Invalid property assignment: unsigned int expected");
+ }
+ break;
+ case QVariant::Int:
+ {
+ bool ok;
+ string.toInt(&ok);
+ if (!v->value.isNumber() || !ok) COMPILE_EXCEPTION2(v, "Invalid property assignment: int expected");
+ }
+ break;
+ case QMetaType::Float:
+ {
+ bool ok;
+ string.toFloat(&ok);
+ if (!v->value.isNumber() || !ok) COMPILE_EXCEPTION2(v, "Invalid property assignment: float expected");
+ }
+ break;
+ case QVariant::Double:
+ {
+ bool ok;
+ string.toDouble(&ok);
+ if (!v->value.isNumber() || !ok) COMPILE_EXCEPTION2(v, "Invalid property assignment: double expected");
+ }
+ break;
+ case QVariant::Color:
+ {
+ QColor c = QmlStringConverters::colorFromString(string);
+ if (!c.isValid()) COMPILE_EXCEPTION2(v, "Invalid property assignment: color expected");
+ }
+ break;
+ case QVariant::Date:
+ {
+ QDate d = QDate::fromString(string, Qt::ISODate);
+ if (!d.isValid()) COMPILE_EXCEPTION2(v, "Invalid property assignment: date expected");
+ }
+ break;
+ case QVariant::Time:
+ {
+ QTime time = QTime::fromString(string, Qt::ISODate);
+ if (!time.isValid()) COMPILE_EXCEPTION2(v, "Invalid property assignment: time expected");
+ }
+ break;
+ case QVariant::DateTime:
+ {
+ QDateTime dateTime = QDateTime::fromString(string, Qt::ISODate);
+ if (!dateTime.isValid()) COMPILE_EXCEPTION2(v, "Invalid property assignment: datetime expected");
+ }
+ break;
+ case QVariant::Point:
+ case QVariant::PointF:
+ {
+ bool ok;
+ QPointF point = QmlStringConverters::pointFFromString(string, &ok);
+ if (!ok) COMPILE_EXCEPTION2(v, "Invalid property assignment: point expected");
+ }
+ break;
+ case QVariant::Size:
+ case QVariant::SizeF:
+ {
+ bool ok;
+ QSizeF size = QmlStringConverters::sizeFFromString(string, &ok);
+ if (!ok) COMPILE_EXCEPTION2(v, "Invalid property assignment: size expected");
+ }
+ break;
+ case QVariant::Rect:
+ case QVariant::RectF:
+ {
+ bool ok;
+ QRectF rect = QmlStringConverters::rectFFromString(string, &ok);
+ if (!ok) COMPILE_EXCEPTION2(v, "Invalid property assignment: rect expected");
+ }
+ break;
+ case QVariant::Bool:
+ {
+ if (!v->value.isBoolean()) COMPILE_EXCEPTION2(v, "Invalid property assignment: boolean expected");
+ }
+ break;
+ default:
+ {
+ int t = prop.type();
+ if (t == QVariant::UserType)
+ t = prop.userType();
+ QmlMetaType::StringConverter converter =
+ QmlMetaType::customStringConverter(t);
+ if (!converter)
+ COMPILE_EXCEPTION2(v, "Invalid property assignment: unknown type" << prop.type());
+ }
+ break;
+ }
+ return true;
+}
+
+void QmlCompiler::genLiteralAssignment(const QMetaProperty &prop,
+ QmlParser::Value *v)
+{
+ QString string = v->value.asScript();
+
+ QmlInstruction instr;
+ instr.line = v->location.start.line;
+ if (prop.isEnumType()) {
+ int value;
+ if (prop.isFlagType()) {
+ value = prop.enumerator().keysToValue(string.toLatin1().constData());
+ } else
+ value = prop.enumerator().keyToValue(string.toLatin1().constData());
+
instr.type = QmlInstruction::StoreInteger;
instr.storeInteger.propertyIndex = prop.propertyIndex();
instr.storeInteger.value = value;
- return true;
+ output->bytecode << instr;
+ return;
}
+
int type = prop.userType();
switch(type) {
case -1:
@@ -291,51 +330,33 @@ bool QmlCompiler::compileStoreInstruction(QmlInstruction &instr,
{
instr.type = QmlInstruction::StoreInteger;
instr.storeInteger.propertyIndex = prop.propertyIndex();
- bool ok;
- int value = string.toUInt(&ok);
- if (!ok)
- COMPILE_EXCEPTION2(v, "Cannot convert value" << string << "to unsigned integer");
- instr.storeInteger.value = value;
+ instr.storeInteger.value = string.toUInt();
}
break;
case QVariant::Int:
{
instr.type = QmlInstruction::StoreInteger;
instr.storeInteger.propertyIndex = prop.propertyIndex();
- bool ok;
- int value = string.toInt(&ok);
- if (!ok)
- COMPILE_EXCEPTION2(v, "Cannot convert value" << string << "to integer");
- instr.storeInteger.value = value;
+ instr.storeInteger.value = string.toInt();
}
break;
case QMetaType::Float:
{
instr.type = QmlInstruction::StoreFloat;
instr.storeFloat.propertyIndex = prop.propertyIndex();
- bool ok;
- float value = string.toFloat(&ok);
- if (!ok)
- COMPILE_EXCEPTION2(v, "Cannot convert value" << string << "to float number");
- instr.storeFloat.value = value;
+ instr.storeFloat.value = string.toFloat();
}
break;
case QVariant::Double:
{
instr.type = QmlInstruction::StoreDouble;
instr.storeDouble.propertyIndex = prop.propertyIndex();
- bool ok;
- double value = string.toDouble(&ok);
- if (!ok)
- COMPILE_EXCEPTION2(v, "Cannot convert value" << string << "to double number");
- instr.storeDouble.value = value;
+ instr.storeDouble.value = string.toDouble();
}
break;
case QVariant::Color:
{
QColor c = QmlStringConverters::colorFromString(string);
- if (!c.isValid())
- COMPILE_EXCEPTION2(v, "Cannot convert value" << string << "to color");
instr.type = QmlInstruction::StoreColor;
instr.storeColor.propertyIndex = prop.propertyIndex();
instr.storeColor.value = c.rgba();
@@ -344,8 +365,6 @@ bool QmlCompiler::compileStoreInstruction(QmlInstruction &instr,
case QVariant::Date:
{
QDate d = QDate::fromString(string, Qt::ISODate);
- if (!d.isValid())
- COMPILE_EXCEPTION2(v, "Cannot convert value" << string << "to date");
instr.type = QmlInstruction::StoreDate;
instr.storeDate.propertyIndex = prop.propertyIndex();
instr.storeDate.value = d.toJulianDay();
@@ -354,9 +373,8 @@ bool QmlCompiler::compileStoreInstruction(QmlInstruction &instr,
case QVariant::Time:
{
QTime time = QTime::fromString(string, Qt::ISODate);
- if (!time.isValid())
- COMPILE_EXCEPTION2(v, "Cannot convert value" << string << "to time");
- int data[] = { time.hour(), time.minute(), time.second(), time.msec() };
+ int data[] = { time.hour(), time.minute(),
+ time.second(), time.msec() };
int index = output->indexForInt(data, 4);
instr.type = QmlInstruction::StoreTime;
instr.storeTime.propertyIndex = prop.propertyIndex();
@@ -366,8 +384,6 @@ bool QmlCompiler::compileStoreInstruction(QmlInstruction &instr,
case QVariant::DateTime:
{
QDateTime dateTime = QDateTime::fromString(string, Qt::ISODate);
- if (!dateTime.isValid())
- COMPILE_EXCEPTION2(v, "Cannot convert value" << string << "to date and time");
int data[] = { dateTime.date().toJulianDay(),
dateTime.time().hour(),
dateTime.time().minute(),
@@ -382,90 +398,76 @@ bool QmlCompiler::compileStoreInstruction(QmlInstruction &instr,
case QVariant::Point:
case QVariant::PointF:
{
- bool ok;
- QPointF point = QmlStringConverters::pointFFromString(string, &ok);
- if (!ok)
- COMPILE_EXCEPTION2(v, "Cannot convert value" << string << "to point");
- float data[] = { point.x(), point.y() };
- int index = output->indexForFloat(data, 2);
- if (type == QVariant::PointF)
- instr.type = QmlInstruction::StorePointF;
- else
- instr.type = QmlInstruction::StorePoint;
- instr.storeRealPair.propertyIndex = prop.propertyIndex();
- instr.storeRealPair.valueIndex = index;
+ bool ok;
+ QPointF point =
+ QmlStringConverters::pointFFromString(string, &ok);
+ float data[] = { point.x(), point.y() };
+ int index = output->indexForFloat(data, 2);
+ if (type == QVariant::PointF)
+ instr.type = QmlInstruction::StorePointF;
+ else
+ instr.type = QmlInstruction::StorePoint;
+ instr.storeRealPair.propertyIndex = prop.propertyIndex();
+ instr.storeRealPair.valueIndex = index;
}
break;
case QVariant::Size:
case QVariant::SizeF:
{
- bool ok;
- QSizeF size = QmlStringConverters::sizeFFromString(string, &ok);
- if (!ok)
- COMPILE_EXCEPTION2(v, "Cannot convert value" << string << "to size");
- float data[] = { size.width(), size.height() };
- int index = output->indexForFloat(data, 2);
- if (type == QVariant::SizeF)
- instr.type = QmlInstruction::StoreSizeF;
- else
- instr.type = QmlInstruction::StoreSize;
- instr.storeRealPair.propertyIndex = prop.propertyIndex();
- instr.storeRealPair.valueIndex = index;
+ bool ok;
+ QSizeF size = QmlStringConverters::sizeFFromString(string, &ok);
+ float data[] = { size.width(), size.height() };
+ int index = output->indexForFloat(data, 2);
+ if (type == QVariant::SizeF)
+ instr.type = QmlInstruction::StoreSizeF;
+ else
+ instr.type = QmlInstruction::StoreSize;
+ instr.storeRealPair.propertyIndex = prop.propertyIndex();
+ instr.storeRealPair.valueIndex = index;
}
break;
case QVariant::Rect:
case QVariant::RectF:
{
- bool ok;
- QRectF rect = QmlStringConverters::rectFFromString(string, &ok);
- if (!ok)
- COMPILE_EXCEPTION2(v, "Cannot convert value" << string << "to rect");
- float data[] = { rect.x(), rect.y(),
- rect.width(), rect.height() };
- int index = output->indexForFloat(data, 4);
- if (type == QVariant::RectF)
- instr.type = QmlInstruction::StoreRectF;
- else
- instr.type = QmlInstruction::StoreRect;
- instr.storeRect.propertyIndex = prop.propertyIndex();
- instr.storeRect.valueIndex = index;
+ bool ok;
+ QRectF rect = QmlStringConverters::rectFFromString(string, &ok);
+ float data[] = { rect.x(), rect.y(),
+ rect.width(), rect.height() };
+ int index = output->indexForFloat(data, 4);
+ if (type == QVariant::RectF)
+ instr.type = QmlInstruction::StoreRectF;
+ else
+ instr.type = QmlInstruction::StoreRect;
+ instr.storeRect.propertyIndex = prop.propertyIndex();
+ instr.storeRect.valueIndex = index;
}
break;
case QVariant::Bool:
{
- bool ok;
- bool b = QmlStringConverters::boolFromString(string, &ok);
- if (!ok)
- COMPILE_EXCEPTION2(v, "Cannot convert value" << string << "to boolean");
- instr.type = QmlInstruction::StoreBool;
- instr.storeBool.propertyIndex = prop.propertyIndex();
- instr.storeBool.value = b;
+ bool b = v->value.asBoolean();
+ instr.type = QmlInstruction::StoreBool;
+ instr.storeBool.propertyIndex = prop.propertyIndex();
+ instr.storeBool.value = b;
}
break;
default:
{
- int t = prop.type();
- if (t == QVariant::UserType)
- t = prop.userType();
- QmlMetaType::StringConverter converter =
- QmlMetaType::customStringConverter(t);
- if (converter) {
- int index = output->customTypeData.count();
- instr.type = QmlInstruction::AssignCustomType;
- instr.assignCustomType.propertyIndex = prop.propertyIndex();
- instr.assignCustomType.valueIndex = index;
-
- QmlCompiledData::CustomTypeData data;
- data.index = output->indexForString(string);
- data.type = t;
- output->customTypeData << data;
- break;
- }
+ int t = prop.type();
+ if (t == QVariant::UserType)
+ t = prop.userType();
+ int index = output->customTypeData.count();
+ instr.type = QmlInstruction::AssignCustomType;
+ instr.assignCustomType.propertyIndex = prop.propertyIndex();
+ instr.assignCustomType.valueIndex = index;
+
+ QmlCompiledData::CustomTypeData data;
+ data.index = output->indexForString(string);
+ data.type = t;
+ output->customTypeData << data;
}
- COMPILE_EXCEPTION2(v, "Cannot assign to property" << prop.name() << "of unknown type" << prop.type());
break;
}
- return true;
+ output->bytecode << instr;
}
void QmlCompiler::reset(QmlCompiledComponent *cc, bool deleteMemory)
@@ -530,7 +532,7 @@ bool QmlCompiler::compile(QmlEngine *engine,
compileTree(root);
if (!isError()) {
- out->dumpPre();
+ out->dumpInstructions();
} else {
reset(out, true);
}
@@ -544,24 +546,23 @@ void QmlCompiler::compileTree(Object *tree)
{
compileState.root = tree;
+ if (!buildObject(tree, BindingContext()) || !completeComponentBuild())
+ return;
+
QmlInstruction init;
init.type = QmlInstruction::Init;
init.line = 0;
- init.init.dataSize = 0;
- init.init.bindingsSize = 0;
- init.init.parserStatusSize = 0;
+ init.init.bindingsSize = compileState.bindings.count();
+ init.init.parserStatusSize = compileState.parserStatusCount;
output->bytecode << init;
- if (!compileObject(tree, 0)) // Compile failed
- return;
+ genObject(tree);
QmlInstruction def;
init.line = 0;
def.type = QmlInstruction::SetDefault;
output->bytecode << def;
- finalizeComponent(0);
-
if (tree->metatype)
static_cast<QMetaObject &>(output->root) = *tree->metaObject();
else
@@ -569,55 +570,35 @@ void QmlCompiler::compileTree(Object *tree)
}
-bool QmlCompiler::compileObject(Object *obj, const BindingContext &ctxt)
+bool QmlCompiler::buildObject(Object *obj, const BindingContext &ctxt)
{
Q_ASSERT (obj->type != -1);
- const QmlCompiledData::TypeReference &tr = output->types.at(obj->type);
+ const QmlCompiledData::TypeReference &tr =
+ output->types.at(obj->type);
obj->metatype = tr.metaObject();
+
if (tr.component)
obj->url = tr.component->url();
- if (output->types.at(obj->type).className == "Component") {
- COMPILE_CHECK(compileComponent(obj, ctxt));
+ // This object is a "Component" element
+ if (obj->metatype == &QmlComponent::staticMetaObject) {
+ COMPILE_CHECK(buildComponent(obj, ctxt));
return true;
}
+ // Object instantiations reset the binding context
BindingContext objCtxt(obj);
- int createInstrIdx = output->bytecode.count();
- // Create the object
- QmlInstruction create;
- create.type = QmlInstruction::CreateObject;
- create.line = obj->location.start.line;
- create.create.data = -1;
- create.create.type = obj->type;
- output->bytecode << create;
-
- // Create the synthesized meta object
- COMPILE_CHECK(compileDynamicMeta(obj));
+ // Create the synthesized meta object, ignoring aliases
+ COMPILE_CHECK(mergeDynamicMetaProperties(obj));
+ COMPILE_CHECK(buildDynamicMeta(obj, IgnoreAliases));
// Find the native type and check for the QmlParserStatus interface
- // ### Optimize
- const QMetaObject *mo = obj->metatype;
- QmlType *type = 0;
- while (!type && mo) {
- type = QmlMetaType::qmlType(mo);
- mo = mo->superClass();
- }
+ QmlType *type = toQmlType(obj);
Q_ASSERT(type);
- int parserStatusCast = type->parserStatusCast();
-
- // If the type support the QmlParserStatusInterface we need to invoke
- // classBegin()
- if (parserStatusCast != -1) {
- QmlInstruction begin;
- begin.type = QmlInstruction::BeginObject;
- begin.begin.castValue = parserStatusCast;
- begin.line = obj->location.start.line;
- output->bytecode << begin;
-
+ obj->parserStatusCast = type->parserStatusCast();
+ if (obj->parserStatusCast != -1)
compileState.parserStatusCount++;
- }
// Check if this is a custom parser type. Custom parser types allow
// assignments to non-existant properties. These assignments are then
@@ -626,57 +607,72 @@ bool QmlCompiler::compileObject(Object *obj, const BindingContext &ctxt)
output->types.at(obj->type).type->customParser() != 0;
QList<QmlCustomParserProperty> customProps;
- QStringList deferred = deferredProperties(obj);
- QList<Property *> deferredProps;
+ // Fetch the list of deferred properties
+ QStringList deferredList = deferredProperties(obj);
+
+ // Must do id property first. This is to ensure that the id given to any
+ // id reference created matches the order in which the objects are
+ // instantiated
+ foreach(Property *prop, obj->properties) {
+ if (prop->name == "id") {
+ COMPILE_CHECK(buildProperty(prop, obj, objCtxt));
+ break;
+ }
+ }
- // Compile all explicit properties specified
+ // Build all explicit properties specified
foreach(Property *prop, obj->properties) {
+ if (prop->name == "id")
+ continue;
+
+ bool canDefer = false;
if (isCustomParser) {
- // Custom parser types don't support signal properties
if (testProperty(prop, obj)) {
- if (deferred.contains(QString::fromLatin1(prop->name.constData())))
- deferredProps << prop;
- else
- COMPILE_CHECK(compileProperty(prop, obj, objCtxt));
+ int ids = compileState.ids.count();
+ COMPILE_CHECK(buildProperty(prop, obj, objCtxt));
+ canDefer = ids == compileState.ids.count();
} else {
customProps << QmlCustomParserNodePrivate::fromProperty(prop);
}
} else {
- if (isSignalPropertyName(prop->name)) {
- COMPILE_CHECK(compileSignal(prop,obj));
+ if (isSignalPropertyName(prop->name)) {
+ COMPILE_CHECK(buildSignal(prop,obj,objCtxt));
} else {
- if (deferred.contains(QString::fromLatin1(prop->name.constData())))
- deferredProps << prop;
- else
- COMPILE_CHECK(compileProperty(prop, obj, objCtxt));
+ int ids = compileState.ids.count();
+ COMPILE_CHECK(buildProperty(prop, obj, objCtxt));
+ canDefer = ids == compileState.ids.count();
}
}
+ if (canDefer && !deferredList.isEmpty() &&
+ deferredList.contains(prop->name))
+ prop->isDeferred = true;
+
}
- // Compile the default property
+ // Build the default property
if (obj->defaultProperty) {
Property *prop = obj->defaultProperty;
+ bool canDefer = false;
if (isCustomParser) {
if (testProperty(prop, obj)) {
- QMetaProperty p = deferred.isEmpty()?QMetaProperty():QmlMetaType::defaultProperty(obj->metaObject());
- if (deferred.contains(QString::fromLatin1(p.name())))
- deferredProps << prop;
- else
- COMPILE_CHECK(compileProperty(prop, obj, objCtxt));
+ int ids = compileState.ids.count();
+ COMPILE_CHECK(buildProperty(prop, obj, objCtxt));
+ canDefer = ids == compileState.ids.count();
} else {
customProps << QmlCustomParserNodePrivate::fromProperty(prop);
}
} else {
- QMetaProperty p = deferred.isEmpty()?QMetaProperty():QmlMetaType::defaultProperty(obj->metaObject());
- if (deferred.contains(QString::fromLatin1(p.name())))
- deferredProps << prop;
- else
- COMPILE_CHECK(compileProperty(prop, obj, objCtxt));
+ int ids = compileState.ids.count();
+ COMPILE_CHECK(buildProperty(prop, obj, objCtxt));
+ canDefer = ids == compileState.ids.count();
}
+ if (canDefer && !deferredList.isEmpty() &&
+ deferredList.contains(prop->name))
+ prop->isDeferred = true;
}
// Compile custom parser parts
@@ -684,16 +680,83 @@ bool QmlCompiler::compileObject(Object *obj, const BindingContext &ctxt)
// ### Check for failure
bool ok = false;
QmlCustomParser *cp = output->types.at(obj->type).type->customParser();
- QByteArray customData = cp->compile(customProps, &ok);
+ obj->custom = cp->compile(customProps, &ok);
if(!ok)
COMPILE_EXCEPTION("Failure compiling custom type");
- if(!customData.isEmpty())
- output->bytecode[createInstrIdx].create.data =
- output->indexForByteArray(customData);
}
- // Build the deferred block
- if (!deferredProps.isEmpty()) {
+ return true;
+}
+
+void QmlCompiler::genObject(QmlParser::Object *obj)
+{
+ if (obj->metatype == &QmlComponent::staticMetaObject) {
+ genComponent(obj);
+ return;
+ }
+
+ // Create the object
+ QmlInstruction create;
+ create.type = QmlInstruction::CreateObject;
+ create.line = obj->location.start.line;
+ create.create.data = -1;
+ if (!obj->custom.isEmpty())
+ create.create.data = output->indexForByteArray(obj->custom);
+ create.create.type = obj->type;
+ output->bytecode << create;
+
+ // Setup the synthesized meta object if necessary
+ if (!obj->metadata.isEmpty()) {
+ QmlInstruction meta;
+ meta.type = QmlInstruction::StoreMetaObject;
+ meta.line = -1;
+ meta.storeMeta.data = output->indexForByteArray(obj->metadata);
+ meta.storeMeta.aliasData = output->indexForByteArray(obj->synthdata);
+ meta.storeMeta.slotData = -1;
+ output->bytecode << meta;
+ }
+
+ // Set the object id
+ if (!obj->id.isEmpty()) {
+ QmlInstruction id;
+ id.type = QmlInstruction::SetId;
+ id.line = -1;
+ id.setId.value = output->indexForString(obj->id);
+ output->bytecode << id;
+ }
+
+ // Begin the class
+ if (obj->parserStatusCast != -1) {
+ QmlInstruction begin;
+ begin.type = QmlInstruction::BeginObject;
+ begin.begin.castValue = obj->parserStatusCast;
+ begin.line = obj->location.start.line;
+ output->bytecode << begin;
+ }
+
+ genObjectBody(obj);
+
+ // Complete the the class
+ if (obj->parserStatusCast != -1) {
+ QmlInstruction complete;
+ complete.type = QmlInstruction::CompleteObject;
+ complete.complete.castValue = obj->parserStatusCast;
+ complete.line = obj->location.start.line;
+ output->bytecode << complete;
+ }
+}
+
+void QmlCompiler::genObjectBody(QmlParser::Object *obj)
+{
+ bool seenDefer = false;
+ foreach(Property *prop, obj->valueProperties) {
+ if (prop->isDeferred) {
+ seenDefer = true;
+ continue;
+ }
+ genValueProperty(prop, obj);
+ }
+ if (seenDefer) {
QmlInstruction defer;
defer.type = QmlInstruction::Defer;
defer.line = 0;
@@ -701,44 +764,147 @@ bool QmlCompiler::compileObject(Object *obj, const BindingContext &ctxt)
int deferIdx = output->bytecode.count();
output->bytecode << defer;
- // ### This is lame, we should check if individual properties have
- // ids defined within them
- int idCount = compileState.ids.count();
- foreach (Property *prop, deferredProps) {
- COMPILE_CHECK(compileProperty(prop, obj, objCtxt));
+ foreach(Property *prop, obj->valueProperties) {
+ if (!prop->isDeferred)
+ continue;
+ genValueProperty(prop, obj);
}
- if (idCount == compileState.ids.count())
- output->bytecode[deferIdx].defer.deferCount =
- output->bytecode.count() - deferIdx - 1;
+
+ output->bytecode[deferIdx].defer.deferCount =
+ output->bytecode.count() - deferIdx - 1;
}
- // If the type support the QmlParserStatusInterface we need to invoke
- // classComplete()
- if (parserStatusCast != -1) {
- QmlInstruction complete;
- complete.type = QmlInstruction::CompleteObject;
- complete.complete.castValue = parserStatusCast;
- complete.line = obj->location.start.line;
- output->bytecode << complete;
- }
+ foreach(Property *prop, obj->signalProperties) {
- return true;
+ QmlParser::Value *v = prop->values.at(0);
+
+ if (v->type == Value::SignalObject) {
+
+ genObject(v->object);
+
+ QmlInstruction assign;
+ assign.type = QmlInstruction::AssignSignalObject;
+ assign.line = v->location.start.line;
+ assign.assignSignalObject.signal =
+ output->indexForByteArray(prop->name);
+ output->bytecode << assign;
+
+ } else if (v->type == Value::SignalExpression) {
+
+ QmlInstruction store;
+ store.type = QmlInstruction::StoreSignal;
+ store.line = v->location.start.line;
+ store.storeSignal.signalIndex = prop->index;
+ store.storeSignal.value =
+ output->indexForString(v->value.asScript().trimmed());
+ output->bytecode << store;
+
+ }
+
+ }
+
+ foreach(Property *prop, obj->attachedProperties) {
+ QmlInstruction fetch;
+ fetch.type = QmlInstruction::FetchAttached;
+ fetch.line = prop->location.start.line;
+ fetch.fetchAttached.id = prop->index;
+ output->bytecode << fetch;
+
+ genObjectBody(prop->value);
+
+ QmlInstruction pop;
+ pop.type = QmlInstruction::PopFetchedObject;
+ pop.line = prop->location.start.line;
+ output->bytecode << pop;
+ }
+
+ foreach(Property *prop, obj->groupedProperties) {
+ QmlInstruction fetch;
+ fetch.type = QmlInstruction::FetchObject;
+ fetch.fetch.property = prop->index;
+ fetch.line = prop->location.start.line;
+ output->bytecode << fetch;
+
+ genObjectBody(prop->value);
+
+ QmlInstruction pop;
+ pop.type = QmlInstruction::PopFetchedObject;
+ pop.line = prop->location.start.line;
+ output->bytecode << pop;
+ }
+}
+
+void QmlCompiler::genComponent(QmlParser::Object *obj)
+{
+ QmlParser::Object *root = obj->defaultProperty->values.at(0)->object;
+ Q_ASSERT(root);
+
+ QmlInstruction create;
+ create.type = QmlInstruction::CreateComponent;
+ create.line = root->location.start.line;
+ create.createComponent.endLine = root->location.end.line;
+ output->bytecode << create;
+ int count = output->bytecode.count();
+
+ ComponentCompileState oldCompileState = compileState;
+ compileState = componentState(root);
+
+ QmlInstruction init;
+ init.type = QmlInstruction::Init;
+ init.init.bindingsSize = compileState.bindings.count();
+ init.init.parserStatusSize = compileState.parserStatusCount;
+ init.line = obj->location.start.line;
+ output->bytecode << init;
+
+ genObject(root);
+
+ output->bytecode[count - 1].createComponent.count =
+ output->bytecode.count() - count;
+
+ compileState = oldCompileState;
+
+ if (!obj->id.isEmpty()) {
+ QmlInstruction id;
+ id.type = QmlInstruction::SetId;
+ id.line = -1;
+ id.setId.value = output->indexForString(obj->id);;
+ output->bytecode << id;
+ }
}
-bool QmlCompiler::compileComponent(Object *obj, const BindingContext &ctxt)
+bool QmlCompiler::buildComponent(QmlParser::Object *obj,
+ const BindingContext &ctxt)
{
+ // The special "Component" element can only have the id property and a
+ // default property, that actually defines the component's tree
+
+ // Find, check and set the "id" property (if any)
Property *idProp = 0;
if (obj->properties.count() > 1 ||
(obj->properties.count() == 1 && obj->properties.begin().key() != "id"))
COMPILE_EXCEPTION("Invalid component specification");
+
+ if (obj->properties.count())
+ idProp = *obj->properties.begin();
+ if (idProp && (idProp->value || idProp->values.count() > 1 || !isValidId(idProp->values.first()->primitive())))
+ COMPILE_EXCEPTION("Invalid component id specification");
+
+ if (idProp) {
+ QString idVal = idProp->values.first()->primitive().toUtf8();
+
+ if (compileState.ids.contains(idVal))
+ COMPILE_EXCEPTION("id is not unique");
+
+ addId(idVal, obj);
+
+ obj->id = idVal.toUtf8();
+ }
+
+ // Check the Component tree is well formed
if (obj->defaultProperty &&
(obj->defaultProperty->value || obj->defaultProperty->values.count() > 1 ||
(obj->defaultProperty->values.count() == 1 && !obj->defaultProperty->values.first()->object)))
COMPILE_EXCEPTION("Invalid component body specification");
- if (obj->properties.count())
- idProp = *obj->properties.begin();
- if (idProp && (idProp->value || idProp->values.count() > 1))
- COMPILE_EXCEPTION("Invalid component id specification");
Object *root = 0;
if (obj->defaultProperty && obj->defaultProperty->values.count())
@@ -747,84 +913,68 @@ bool QmlCompiler::compileComponent(Object *obj, const BindingContext &ctxt)
if (!root)
COMPILE_EXCEPTION("Cannot create empty component specification");
- COMPILE_CHECK(compileComponentFromRoot(root, ctxt));
-
- if (idProp && idProp->values.count()) {
- QString val = idProp->values.at(0)->primitive();
- if (!isValidId(val))
- COMPILE_EXCEPTION("Invalid id property value");
-
- if (compileState.ids.contains(val))
- COMPILE_EXCEPTION("id is not unique");
-
- IdReference reference;
- reference.id = val;
- reference.object = obj;
- reference.instructionIdx = output->bytecode.count();
- reference.idx = compileState.ids.count();
- compileState.ids.insert(val, reference);
-
- int pref = output->indexForString(val);
- QmlInstruction id;
- id.type = QmlInstruction::SetId;
- id.line = idProp->location.start.line;
- id.setId.value = pref;
- id.setId.save = -1;
-
- output->bytecode << id;
- }
+ // Build the component tree
+ COMPILE_CHECK(buildComponentFromRoot(root, ctxt));
return true;
}
-bool QmlCompiler::compileComponentFromRoot(Object *obj, const BindingContext &ctxt)
+bool QmlCompiler::buildComponentFromRoot(QmlParser::Object *obj,
+ const BindingContext &ctxt)
{
- output->bytecode.push_back(QmlInstruction());
- QmlInstruction &create = output->bytecode.last();
- create.type = QmlInstruction::CreateComponent;
- create.line = obj->location.start.line;
- create.createComponent.endLine = obj->location.end.line;
- int count = output->bytecode.count();
-
- QmlInstruction init;
- init.type = QmlInstruction::Init;
- init.init.dataSize = 0;
- init.init.bindingsSize = 0;
- init.init.parserStatusSize = 0;
- init.line = obj->location.start.line;
- output->bytecode << init;
-
ComponentCompileState oldComponentCompileState = compileState;
compileState = ComponentCompileState();
compileState.root = obj;
+
if (obj)
- COMPILE_CHECK(compileObject(obj, ctxt));
+ COMPILE_CHECK(buildObject(obj, ctxt));
+
+ COMPILE_CHECK(completeComponentBuild());
- COMPILE_CHECK(finalizeComponent(count));
- create.createComponent.count = output->bytecode.count() - count;
compileState = oldComponentCompileState;
+
return true;
}
-bool QmlCompiler::compileFetchedObject(Object *obj, const BindingContext &ctxt)
+
+// Build a sub-object. A sub-object is one that was not created directly by
+// QML - such as a grouped property object, or an attached object. Sub-object's
+// can't have an id, involve a custom parser, have attached properties etc.
+bool QmlCompiler::buildSubObject(Object *obj, const BindingContext &ctxt)
{
Q_ASSERT(obj->metatype);
+ Q_ASSERT(ctxt.isSubContext()); // sub-objects must always be in a binding
+ // sub-context
if (obj->defaultProperty)
- COMPILE_CHECK(compileProperty(obj->defaultProperty, obj, ctxt));
+ COMPILE_CHECK(buildProperty(obj->defaultProperty, obj, ctxt));
foreach(Property *prop, obj->properties) {
if (isSignalPropertyName(prop->name)) {
- COMPILE_CHECK(compileSignal(prop, obj));
+ COMPILE_CHECK(buildSignal(prop, obj, ctxt));
} else {
- COMPILE_CHECK(compileProperty(prop, obj, ctxt));
+ COMPILE_CHECK(buildProperty(prop, obj, ctxt));
}
}
return true;
}
-int QmlCompiler::signalByName(const QMetaObject *mo, const QByteArray &name)
+int QmlCompiler::componentTypeRef()
+{
+ QmlType *t = QmlMetaType::qmlType("Component");
+ for (int ii = output->types.count() - 1; ii >= 0; --ii) {
+ if (output->types.at(ii).type == t)
+ return ii;
+ }
+ QmlCompiledData::TypeReference ref;
+ ref.className = "Component";
+ ref.type = t;
+ output->types << ref;
+ return output->types.count() - 1;
+}
+
+int QmlCompiler::findSignalByName(const QMetaObject *mo, const QByteArray &name)
{
int methods = mo->methodCount();
for (int ii = methods - 1; ii >= 0; --ii) {
@@ -839,15 +989,13 @@ int QmlCompiler::signalByName(const QMetaObject *mo, const QByteArray &name)
return -1;
}
-bool QmlCompiler::compileSignal(Property *prop, Object *obj)
+bool QmlCompiler::buildSignal(QmlParser::Property *prop, QmlParser::Object *obj,
+ const BindingContext &ctxt)
{
Q_ASSERT(obj->metaObject());
- if (prop->values.isEmpty() && !prop->value)
- return true;
-
- if (prop->value || prop->values.count() > 1)
- COMPILE_EXCEPTION("Incorrectly specified signal");
+ if (prop->isEmpty())
+ COMPILE_EXCEPTION2(prop, "Empty property assignment");
QByteArray name = prop->name;
Q_ASSERT(name.startsWith("on"));
@@ -855,47 +1003,26 @@ bool QmlCompiler::compileSignal(Property *prop, Object *obj)
if(name[0] >= 'A' && name[0] <= 'Z')
name[0] = name[0] - 'A' + 'a';
- int sigIdx = signalByName(obj->metaObject(), name);
+ int sigIdx = findSignalByName(obj->metaObject(), name);
if (sigIdx == -1) {
- COMPILE_CHECK(compileProperty(prop, obj, 0));
+ // If the "on<Signal>" name doesn't resolve into a signal, try it as a
+ // property.
+ COMPILE_CHECK(buildProperty(prop, obj, ctxt));
} else {
- if (prop->values.at(0)->object) {
- int pr = output->indexForByteArray(prop->name);
-
- bool rv = compileObject(prop->values.at(0)->object, 0);
+ if (prop->value || prop->values.count() > 1)
+ COMPILE_EXCEPTION("Incorrectly specified signal");
- if (rv) {
- QmlInstruction assign;
- assign.type = QmlInstruction::AssignSignalObject;
- assign.line = prop->values.at(0)->location.start.line;
- assign.assignSignalObject.signal = pr;
-
- output->bytecode << assign;
-
- prop->values.at(0)->type = Value::SignalObject;
- }
-
- return rv;
+ prop->index = sigIdx;
+ obj->addSignalProperty(prop);
+ if (prop->values.at(0)->object) {
+ COMPILE_CHECK(buildObject(prop->values.at(0)->object, ctxt));
+ prop->values.at(0)->type = Value::SignalObject;
} else {
- QString script = prop->values.at(0)->value.asScript().trimmed();
- if (script.isEmpty())
- return true;
-
- int idx = output->indexForString(script);
-
- QmlInstruction store;
- store.line = prop->values.at(0)->location.start.line;
- store.type = QmlInstruction::StoreSignal;
- store.storeSignal.signalIndex = sigIdx;
- store.storeSignal.value = idx;
-
- output->bytecode << store;
-
prop->values.at(0)->type = Value::SignalExpression;
}
}
@@ -903,6 +1030,7 @@ bool QmlCompiler::compileSignal(Property *prop, Object *obj)
return true;
}
+
// Returns true if prop exists on obj, false otherwise
bool QmlCompiler::testProperty(QmlParser::Property *prop,
QmlParser::Object *obj)
@@ -924,9 +1052,11 @@ bool QmlCompiler::testProperty(QmlParser::Property *prop,
return false;
}
-bool QmlCompiler::compileProperty(Property *prop, Object *obj, const BindingContext &ctxt)
+bool QmlCompiler::buildProperty(QmlParser::Property *prop,
+ QmlParser::Object *obj,
+ const BindingContext &ctxt)
{
- if (prop->values.isEmpty() && !prop->value)
+ if (prop->isEmpty())
COMPILE_EXCEPTION2(prop, "Empty property assignment");
const QMetaObject *metaObject = obj->metaObject();
@@ -934,13 +1064,21 @@ bool QmlCompiler::compileProperty(Property *prop, Object *obj, const BindingCont
if (isAttachedPropertyName(prop->name)) {
// Setup attached property data
+
+ if (ctxt.isSubContext()) {
+ // Attached properties cannot be used on sub-objects. Sub-objects
+ // always exist in a binding sub-context, which is what we test
+ // for here.
+ COMPILE_EXCEPTION2(prop, "Attached properties cannot be used here");
+ }
+
QmlType *type = QmlMetaType::qmlType(prop->name);
if (!type || !type->attachedPropertiesType())
COMPILE_EXCEPTION2(prop, "Non-existant attached object");
if (!prop->value)
- COMPILE_EXCEPTION2(prop, "Cannot assign directly to attached object");
+ COMPILE_EXCEPTION2(prop, "Invalid attached object assignment");
prop->value->metatype = type->attachedPropertiesType();
} else {
@@ -976,125 +1114,259 @@ bool QmlCompiler::compileProperty(Property *prop, Object *obj, const BindingCont
}
}
- if (!prop->isDefault && prop->name == "id") {
+ if (!prop->isDefault && prop->name == "id" && !ctxt.isSubContext()) {
- COMPILE_CHECK(compileIdProperty(prop, obj));
+ // The magic "id" behaviour doesn't apply when "id" is resolved as a
+ // default property or to sub-objects (which are always in binding
+ // sub-contexts)
+ COMPILE_CHECK(buildIdProperty(prop, obj));
+ if (prop->type == QVariant::String &&
+ prop->values.at(0)->value.isString())
+ COMPILE_CHECK(buildPropertyAssignment(prop, obj, ctxt));
} else if (isAttachedPropertyName(prop->name)) {
- COMPILE_CHECK(compileAttachedProperty(prop, ctxt));
+ COMPILE_CHECK(buildAttachedProperty(prop, obj, ctxt));
} else if (prop->index == -1) {
if (prop->isDefault) {
- COMPILE_EXCEPTION2(prop, "Cannot assign to non-existant default property");
+ COMPILE_EXCEPTION2(prop->values.first(), "Cannot assign to non-existant default property");
} else {
COMPILE_EXCEPTION2(prop, "Cannot assign to non-existant property" << prop->name);
}
} else if (prop->value) {
- COMPILE_CHECK(compileNestedProperty(prop, ctxt));
+ COMPILE_CHECK(buildGroupedProperty(prop, obj, ctxt));
} else if (QmlMetaType::isQmlList(prop->type) ||
QmlMetaType::isList(prop->type)) {
- COMPILE_CHECK(compileListProperty(prop, obj, ctxt));
+ COMPILE_CHECK(buildListProperty(prop, obj, ctxt));
} else {
- COMPILE_CHECK(compilePropertyAssignment(prop, obj, ctxt));
+ COMPILE_CHECK(buildPropertyAssignment(prop, obj, ctxt));
}
return true;
}
-bool QmlCompiler::compileIdProperty(QmlParser::Property *prop,
- QmlParser::Object *obj)
+void QmlCompiler::genValueProperty(QmlParser::Property *prop,
+ QmlParser::Object *obj)
+{
+ if (QmlMetaType::isQmlList(prop->type) || QmlMetaType::isList(prop->type)) {
+ genListProperty(prop, obj);
+ } else {
+ genPropertyAssignment(prop, obj);
+ }
+}
+
+void QmlCompiler::genListProperty(QmlParser::Property *prop,
+ QmlParser::Object *obj)
+{
+ QmlInstruction::Type fetchType;
+ QmlInstruction::Type storeType;
+ int listType;
+
+ if (QmlMetaType::isQmlList(prop->type)) {
+ fetchType = QmlInstruction::FetchQmlList;
+ storeType = QmlInstruction::StoreObjectQmlList;
+ listType = QmlMetaType::qmlListType(prop->type);
+ } else {
+ fetchType = QmlInstruction::FetchQList;
+ storeType = QmlInstruction::StoreObjectQList;
+ listType = QmlMetaType::listType(prop->type);
+ }
+
+ QmlInstruction fetch;
+ fetch.type = fetchType;
+ fetch.line = prop->location.start.line;
+ fetch.fetchQmlList.property = prop->index;
+ bool listTypeIsInterface = QmlMetaType::isInterface(listType);
+ fetch.fetchQmlList.type = listType;
+ output->bytecode << fetch;
+
+ for (int ii = 0; ii < prop->values.count(); ++ii) {
+ Value *v = prop->values.at(ii);
+
+ if (v->type == Value::CreatedObject) {
+
+ genObject(v->object);
+ if (listTypeIsInterface) {
+ QmlInstruction assign;
+ assign.type = QmlInstruction::AssignObjectList;
+ assign.line = prop->location.start.line;
+ output->bytecode << assign;
+ } else {
+ QmlInstruction store;
+ store.type = storeType;
+ store.line = prop->location.start.line;
+ output->bytecode << store;
+ }
+
+ } else if (v->type == Value::PropertyBinding) {
+
+ genBindingAssignment(v, prop, obj);
+
+ }
+
+ }
+
+ QmlInstruction pop;
+ pop.type = QmlInstruction::PopQList;
+ pop.line = prop->location.start.line;
+ output->bytecode << pop;
+}
+
+void QmlCompiler::genPropertyAssignment(QmlParser::Property *prop,
+ QmlParser::Object *obj)
+{
+ for (int ii = 0; ii < prop->values.count(); ++ii) {
+ QmlParser::Value *v = prop->values.at(ii);
+
+ if (v->type == Value::CreatedObject) {
+
+ genObject(v->object);
+
+ if (QmlMetaType::isInterface(prop->type)) {
+
+ QmlInstruction store;
+ store.type = QmlInstruction::StoreInterface;
+ store.line = v->object->location.start.line;
+ store.storeObject.propertyIndex = prop->index;
+ output->bytecode << store;
+
+ } else if (prop->type == -1) {
+
+ QmlInstruction store;
+ store.type = QmlInstruction::StoreVariantObject;
+ store.line = v->object->location.start.line;
+ store.storeObject.propertyIndex = prop->index;
+ output->bytecode << store;
+
+ } else {
+
+ QmlInstruction store;
+ store.type = QmlInstruction::StoreObject;
+ store.line = v->object->location.start.line;
+ store.storeObject.propertyIndex = prop->index;
+ output->bytecode << store;
+
+ }
+ } else if (v->type == Value::ValueSource) {
+
+ genObject(v->object);
+
+ QmlInstruction store;
+ store.type = QmlInstruction::StoreValueSource;
+ store.line = v->object->location.start.line;
+ store.assignValueSource.property = prop->index;
+ output->bytecode << store;
+
+ } else if (v->type == Value::PropertyBinding) {
+
+ genBindingAssignment(v, prop, obj);
+
+ } else if (v->type == Value::Literal) {
+
+ QMetaProperty mp = obj->metaObject()->property(prop->index);
+ genLiteralAssignment(mp, v);
+
+ }
+
+ }
+}
+
+bool QmlCompiler::buildIdProperty(QmlParser::Property *prop,
+ QmlParser::Object *obj)
{
- if (prop->value)
- COMPILE_EXCEPTION2(prop,"The id property cannot be fetched");
- if (prop->values.count() > 1)
- COMPILE_EXCEPTION2(prop, "The object id may only be set once");
+ if (prop->value ||
+ prop->values.count() > 1 ||
+ prop->values.at(0)->object)
+ COMPILE_EXCEPTION2(prop, "Invalid use of id property");
- if (prop->values.at(0)->object)
- COMPILE_EXCEPTION("Cannot assign an object as an id");
QString val = prop->values.at(0)->primitive();
+
if (!isValidId(val))
- COMPILE_EXCEPTION(val << "is not a valid id");
+ COMPILE_EXCEPTION2(prop, val << "is not a valid object id");
+
if (compileState.ids.contains(val))
- COMPILE_EXCEPTION("id is not unique");
+ COMPILE_EXCEPTION2(prop, "id is not unique");
- int pref = output->indexForString(val);
+ obj->id = val.toUtf8();
- if (prop->type == QVariant::String) {
- QmlInstruction assign;
- assign.type = QmlInstruction::StoreString;
- assign.storeString.propertyIndex = prop->index;
- assign.storeString.value = pref;
- assign.line = prop->values.at(0)->location.start.line;
- output->bytecode << assign;
+ prop->values.at(0)->type = Value::Id;
- prop->values.at(0)->type = Value::Id;
- } else {
- prop->values.at(0)->type = Value::Literal;
- }
+ addId(val, obj);
+ return true;
+}
+
+void QmlCompiler::addId(const QString &id, QmlParser::Object *obj)
+{
IdReference reference;
- reference.id = val;
+ reference.id = id;
reference.object = obj;
- reference.instructionIdx = output->bytecode.count();
reference.idx = compileState.ids.count();
- compileState.ids.insert(val, reference);
+ compileState.ids.insert(id, reference);
+}
- QmlInstruction id;
- id.type = QmlInstruction::SetId;
- id.line = prop->values.at(0)->location.start.line;
- id.setId.value = pref;
- id.setId.save = -1;
- output->bytecode << id;
+void QmlCompiler::addBindingReference(const BindingReference &ref)
+{
+ int id = compileState.bindings.count();
+ compileState.bindings << ref;
+ compileState.bindingMap.insert(ref.value, id);
+}
- obj->id = val.toLatin1();
+void QmlCompiler::saveComponentState()
+{
+ Q_ASSERT(compileState.root);
+ Q_ASSERT(!savedCompileStates.contains(compileState.root));
- return true;
+ savedCompileStates.insert(compileState.root, compileState);
}
-// Compile attached property object. In this example,
+QmlCompiler::ComponentCompileState
+QmlCompiler::componentState(QmlParser::Object *obj)
+{
+ Q_ASSERT(savedCompileStates.contains(obj));
+ return savedCompileStates.value(obj);
+}
+
+// Build attached property object. In this example,
// Text {
// GridView.row: 10
// }
// GridView is an attached property object.
-bool QmlCompiler::compileAttachedProperty(QmlParser::Property *prop,
- const BindingContext &ctxt)
+bool QmlCompiler::buildAttachedProperty(QmlParser::Property *prop,
+ QmlParser::Object *obj,
+ const BindingContext &ctxt)
{
Q_ASSERT(prop->value);
int id = QmlMetaType::attachedPropertiesFuncId(prop->name);
Q_ASSERT(id != -1); // This is checked in compileProperty()
- QmlInstruction fetch;
- fetch.type = QmlInstruction::FetchAttached;
- fetch.line = prop->location.start.line;
- fetch.fetchAttached.id = id;
- output->bytecode << fetch;
-
- COMPILE_CHECK(compileFetchedObject(prop->value, ctxt.incr()));
+ prop->index = id;
+ obj->addAttachedProperty(prop);
- QmlInstruction pop;
- pop.type = QmlInstruction::PopFetchedObject;
- pop.line = prop->location.start.line;
- output->bytecode << pop;
+ COMPILE_CHECK(buildSubObject(prop->value, ctxt.incr()));
return true;
}
-// Compile "nested" properties. In this example:
+
+// Build "grouped" properties. In this example:
// Text {
// font.size: 12
+// font.family: "Helvetica"
// }
-// font is a nested property. size is not.
-bool QmlCompiler::compileNestedProperty(QmlParser::Property *prop,
- const BindingContext &ctxt)
+// font is a nested property. size and family are not.
+bool QmlCompiler::buildGroupedProperty(QmlParser::Property *prop,
+ QmlParser::Object *obj,
+ const BindingContext &ctxt)
{
Q_ASSERT(prop->type != 0);
Q_ASSERT(prop->index != -1);
@@ -1104,132 +1376,90 @@ bool QmlCompiler::compileNestedProperty(QmlParser::Property *prop,
if (!prop->value->metatype)
COMPILE_EXCEPTION2(prop, "Cannot nest non-QObject property" << prop->name);
- QmlInstruction fetch;
- fetch.type = QmlInstruction::FetchObject;
- fetch.fetch.property = prop->index;
- fetch.fetch.isObject = true;
- fetch.line = prop->location.start.line;
- output->bytecode << fetch;
+ obj->addGroupedProperty(prop);
- COMPILE_CHECK(compileFetchedObject(prop->value, ctxt.incr()));
-
- QmlInstruction pop;
- pop.type = QmlInstruction::PopFetchedObject;
- pop.line = prop->location.start.line;
- output->bytecode << pop;
+ COMPILE_CHECK(buildSubObject(prop->value, ctxt.incr()));
return true;
}
-// Compile assignments to QML lists. QML lists are properties of type
+
+// Build assignments to QML lists. QML lists are properties of type
// QList<T *> * and QmlList<T *> *.
//
// QList<T *> * types can accept a list of objects, or a single binding
// QmlList<T *> * types can accept a list of objects
-bool QmlCompiler::compileListProperty(QmlParser::Property *prop,
- QmlParser::Object *obj,
- const BindingContext &ctxt)
+bool QmlCompiler::buildListProperty(QmlParser::Property *prop,
+ QmlParser::Object *obj,
+ const BindingContext &ctxt)
{
Q_ASSERT(QmlMetaType::isList(prop->type) ||
QmlMetaType::isQmlList(prop->type));
int t = prop->type;
+ obj->addValueProperty(prop);
+
if (QmlMetaType::isQmlList(t)) {
- QmlInstruction fetch;
- fetch.line = prop->location.start.line;
- fetch.type = QmlInstruction::FetchQmlList;
- fetch.fetchQmlList.property = prop->index;
int listType = QmlMetaType::qmlListType(t);
bool listTypeIsInterface = QmlMetaType::isInterface(listType);
- fetch.fetchQmlList.type = listType;
- output->bytecode << fetch;
for (int ii = 0; ii < prop->values.count(); ++ii) {
Value *v = prop->values.at(ii);
if (v->object) {
v->type = Value::CreatedObject;
- COMPILE_CHECK(compileObject(v->object, ctxt));
+ COMPILE_CHECK(buildObject(v->object, ctxt));
+ // We check object coercian here. We check interface assignment
+ // at runtime.
if (!listTypeIsInterface) {
- if (canConvert(listType, v->object)) {
- QmlInstruction store;
- store.type = QmlInstruction::StoreObjectQmlList;
- store.line = prop->location.start.line;
- output->bytecode << store;
- } else {
+ if (!canCoerce(listType, v->object)) {
COMPILE_EXCEPTION("Cannot assign object to list");
}
-
- } else {
- QmlInstruction assign;
- assign.type = QmlInstruction::AssignObjectList;
- assign.line = prop->location.start.line;
- output->bytecode << assign;
}
+
} else {
COMPILE_EXCEPTION("Cannot assign primitives to lists");
}
}
- QmlInstruction pop;
- pop.type = QmlInstruction::PopQList;
- pop.line = prop->location.start.line;
- output->bytecode << pop;
} else {
- QmlInstruction fetch;
- fetch.type = QmlInstruction::FetchQList;
- fetch.line = prop->location.start.line;
- fetch.fetchQmlList.property = prop->index;
int listType = QmlMetaType::listType(t);
bool listTypeIsInterface = QmlMetaType::isInterface(listType);
- fetch.fetchQmlList.type = listType;
- output->bytecode << fetch;
bool assignedBinding = false;
for (int ii = 0; ii < prop->values.count(); ++ii) {
Value *v = prop->values.at(ii);
if (v->object) {
v->type = Value::CreatedObject;
- COMPILE_CHECK(compileObject(v->object, ctxt));
+ COMPILE_CHECK(buildObject(v->object, ctxt));
+ // We check object coercian here. We check interface assignment
+ // at runtime.
if (!listTypeIsInterface) {
- if (canConvert(listType, v->object)) {
- QmlInstruction store;
- store.type = QmlInstruction::StoreObjectQList;
- store.line = prop->location.start.line;
- output->bytecode << store;
- } else {
+ if (!canCoerce(listType, v->object)) {
COMPILE_EXCEPTION("Cannot assign object to list");
}
- } else {
- QmlInstruction assign;
- assign.type = QmlInstruction::AssignObjectList;
- assign.line = v->location.start.line;
- output->bytecode << assign;
- }
+ }
+
} else if (v->value.isScript()) {
if (assignedBinding)
COMPILE_EXCEPTION("Can only assign one binding to lists");
assignedBinding = true;
- COMPILE_CHECK(compileBinding(v, prop, ctxt));
+ COMPILE_CHECK(buildBinding(v, prop, ctxt));
v->type = Value::PropertyBinding;
} else {
COMPILE_EXCEPTION("Cannot assign primitives to lists");
}
}
- QmlInstruction pop;
- pop.line = prop->location.start.line;
- pop.type = QmlInstruction::PopQList;
- output->bytecode << pop;
}
return true;
}
-// Compile regular property assignments of the form property: <value>
+// Compile regular property assignments of the form "property: <value>"
//
// ### The following problems exist
//
@@ -1244,19 +1474,21 @@ bool QmlCompiler::compileListProperty(QmlParser::Property *prop,
// }
//
// We allow assignming multiple values to single value properties
-bool QmlCompiler::compilePropertyAssignment(QmlParser::Property *prop,
- QmlParser::Object *obj,
- const BindingContext &ctxt)
+bool QmlCompiler::buildPropertyAssignment(QmlParser::Property *prop,
+ QmlParser::Object *obj,
+ const BindingContext &ctxt)
{
+ obj->addValueProperty(prop);
+
for (int ii = 0; ii < prop->values.count(); ++ii) {
Value *v = prop->values.at(ii);
if (v->object) {
- COMPILE_CHECK(compilePropertyObjectAssignment(prop, v, ctxt));
+ COMPILE_CHECK(buildPropertyObjectAssignment(prop, obj, v, ctxt));
} else {
- COMPILE_CHECK(compilePropertyLiteralAssignment(prop, obj, v, ctxt));
+ COMPILE_CHECK(buildPropertyLiteralAssignment(prop, obj, v, ctxt));
}
}
@@ -1265,9 +1497,10 @@ bool QmlCompiler::compilePropertyAssignment(QmlParser::Property *prop,
}
// Compile assigning a single object instance to a regular property
-bool QmlCompiler::compilePropertyObjectAssignment(QmlParser::Property *prop,
- QmlParser::Value *v,
- const BindingContext &ctxt)
+bool QmlCompiler::buildPropertyObjectAssignment(QmlParser::Property *prop,
+ QmlParser::Object *obj,
+ QmlParser::Value *v,
+ const BindingContext &ctxt)
{
Q_ASSERT(prop->index != -1);
Q_ASSERT(v->object->type != -1);
@@ -1275,30 +1508,18 @@ bool QmlCompiler::compilePropertyObjectAssignment(QmlParser::Property *prop,
if (QmlMetaType::isInterface(prop->type)) {
// Assigning an object to an interface ptr property
- COMPILE_CHECK(compileObject(v->object, ctxt));
-
- QmlInstruction assign;
- assign.type = QmlInstruction::StoreInterface;
- assign.line = v->object->location.start.line;
- assign.storeObject.propertyIndex = prop->index;
- output->bytecode << assign;
+ COMPILE_CHECK(buildObject(v->object, ctxt));
v->type = Value::CreatedObject;
} else if (prop->type == -1) {
// Assigning an object to a QVariant
- COMPILE_CHECK(compileObject(v->object, ctxt));
-
- QmlInstruction assign;
- assign.type = QmlInstruction::StoreVariantObject;
- assign.line = v->object->location.start.line;
- assign.storeObject.propertyIndex = prop->index;
- output->bytecode << assign;
+ COMPILE_CHECK(buildObject(v->object, ctxt));
v->type = Value::CreatedObject;
} else {
- // Normally compileObject() will set this up, but we need the static
+ // Normally buildObject() will set this up, but we need the static
// meta object earlier to test for assignability. It doesn't matter
// that there may still be outstanding synthesized meta object changes
// on this type, as they are not relevant for assignability testing
@@ -1333,39 +1554,29 @@ bool QmlCompiler::compilePropertyObjectAssignment(QmlParser::Property *prop,
if (isAssignable) {
// Simple assignment
- COMPILE_CHECK(compileObject(v->object, ctxt));
-
- QmlInstruction assign;
- assign.type = QmlInstruction::StoreObject;
- assign.line = v->object->location.start.line;
- assign.storeObject.propertyIndex = prop->index;
- output->bytecode << assign;
+ COMPILE_CHECK(buildObject(v->object, ctxt));
v->type = Value::CreatedObject;
} else if (propertyMetaObject == &QmlComponent::staticMetaObject) {
// Automatic "Component" insertion
- COMPILE_CHECK(compileComponentFromRoot(v->object, ctxt));
-
- QmlInstruction assign;
- assign.type = QmlInstruction::StoreObject;
- assign.line = v->object->location.start.line;
- assign.storeObject.propertyIndex = prop->index;
- output->bytecode << assign;
-
- v->type = Value::Component;
+ QmlParser::Object *root = v->object;
+ QmlParser::Object *component = new QmlParser::Object;
+ component->type = componentTypeRef();
+ component->typeName = "Component";
+ component->metatype = &QmlComponent::staticMetaObject;
+ component->location = root->location;
+ QmlParser::Value *componentValue = new QmlParser::Value;
+ componentValue->object = root;
+ component->getDefaultProperty()->addValue(componentValue);
+ v->object = component;
+ COMPILE_CHECK(buildPropertyObjectAssignment(prop, obj, v, ctxt));
} else if (isPropertyValue) {
// Assign as a property value source
- COMPILE_CHECK(compileObject(v->object, ctxt));
-
- QmlInstruction assign;
- assign.type = QmlInstruction::StoreValueSource;
- assign.line = v->object->location.start.line;
- assign.assignValueSource.property = prop->index;
- output->bytecode << assign;
+ COMPILE_CHECK(buildObject(v->object, ctxt));
v->type = Value::ValueSource;
} else {
- COMPILE_EXCEPTION2(v->object, "Unassignable object");
+ COMPILE_EXCEPTION2(v->object, "Cannot assign object to property");
}
}
@@ -1373,25 +1584,22 @@ bool QmlCompiler::compilePropertyObjectAssignment(QmlParser::Property *prop,
}
// Compile assigning a literal or binding to a regular property
-bool QmlCompiler::compilePropertyLiteralAssignment(QmlParser::Property *prop,
- QmlParser::Object *obj,
- QmlParser::Value *v,
- const BindingContext &ctxt)
+bool QmlCompiler::buildPropertyLiteralAssignment(QmlParser::Property *prop,
+ QmlParser::Object *obj,
+ QmlParser::Value *v,
+ const BindingContext &ctxt)
{
Q_ASSERT(prop->index != -1);
if (v->value.isScript()) {
- COMPILE_CHECK(compileBinding(v, prop, ctxt));
+ COMPILE_CHECK(buildBinding(v, prop, ctxt));
v->type = Value::PropertyBinding;
} else {
- QmlInstruction assign;
- assign.line = v->location.start.line;
- COMPILE_CHECK(compileStoreInstruction(assign, obj->metaObject()->property(prop->index), v));
- output->bytecode << assign;
+ COMPILE_CHECK(testLiteralAssignment(obj->metaObject()->property(prop->index), v));
v->type = Value::Literal;
}
@@ -1399,31 +1607,99 @@ bool QmlCompiler::compilePropertyLiteralAssignment(QmlParser::Property *prop,
return true;
}
-bool QmlCompiler::compileDynamicMeta(QmlParser::Object *obj, int preAlias)
+// Ensures that the dynamic meta specification on obj is valid
+bool QmlCompiler::checkDynamicMeta(QmlParser::Object *obj)
+{
+ QSet<QByteArray> propNames;
+ QSet<QByteArray> methodNames;
+ bool seenDefaultProperty = false;
+
+ // Check properties
+ for (int ii = 0; ii < obj->dynamicProperties.count(); ++ii) {
+ const QmlParser::Object::DynamicProperty &prop =
+ obj->dynamicProperties.at(ii);
+
+ if (prop.isDefaultProperty) {
+ if (seenDefaultProperty)
+ COMPILE_EXCEPTION("Duplicate default property");
+ seenDefaultProperty = true;
+ }
+
+ if (propNames.contains(prop.name))
+ COMPILE_EXCEPTION("Duplicate property name");
+
+ propNames.insert(prop.name);
+ }
+
+ for (int ii = 0; ii < obj->dynamicSignals.count(); ++ii) {
+ QByteArray name = obj->dynamicSignals.at(ii).name;
+ if (methodNames.contains(name))
+ COMPILE_EXCEPTION("Duplicate signal name");
+ methodNames.insert(name);
+ }
+ for (int ii = 0; ii < obj->dynamicSlots.count(); ++ii) {
+ QByteArray name = obj->dynamicSlots.at(ii).name;
+ if (methodNames.contains(name))
+ COMPILE_EXCEPTION("Duplicate method name");
+ methodNames.insert(name);
+ }
+
+ return true;
+}
+
+bool QmlCompiler::mergeDynamicMetaProperties(QmlParser::Object *obj)
+{
+ for (int ii = 0; ii < obj->dynamicProperties.count(); ++ii) {
+ const Object::DynamicProperty &p = obj->dynamicProperties.at(ii);
+
+ if (!p.defaultValue || p.type == Object::DynamicProperty::Alias)
+ continue;
+
+ Property *property = 0;
+ if (p.isDefaultProperty)
+ property = obj->getDefaultProperty();
+ else
+ property = obj->getProperty(p.name);
+
+ if (property->value)
+ COMPILE_EXCEPTION2(property, "Invalid property nesting");
+
+ for (int ii = 0; ii < p.defaultValue->values.count(); ++ii) {
+ Value *v = p.defaultValue->values.at(ii);
+ v->addref();
+ property->values.append(v);
+ }
+ }
+ return true;
+}
+
+bool QmlCompiler::buildDynamicMeta(QmlParser::Object *obj, DynamicMetaMode mode)
{
- // ### FIXME - Check that there is only one default property etc.
if (obj->dynamicProperties.isEmpty() &&
obj->dynamicSignals.isEmpty() &&
obj->dynamicSlots.isEmpty())
return true;
+ COMPILE_CHECK(checkDynamicMeta(obj));
+
QByteArray dynamicData(sizeof(QmlVMEMetaData), (char)0);
QMetaObjectBuilder builder;
if (obj->metatype)
- builder.setClassName(QByteArray(obj->metatype->className()) + "QML");
-
+ builder.setClassName(QByteArray(obj->metatype->className()) + "_QML");
builder.setFlags(QMetaObjectBuilder::DynamicMetaObject);
+
bool hasAlias = false;
for (int ii = 0; ii < obj->dynamicProperties.count(); ++ii) {
const Object::DynamicProperty &p = obj->dynamicProperties.at(ii);
if (p.isDefaultProperty &&
- (p.type != Object::DynamicProperty::Alias || preAlias != -1))
+ (p.type != Object::DynamicProperty::Alias ||
+ mode == ResolveAliases))
builder.addClassInfo("DefaultProperty", p.name);
QByteArray type;
- int propertyType;
+ int propertyType = 0;
switch(p.type) {
case Object::DynamicProperty::Alias:
hasAlias = true;
@@ -1471,7 +1747,7 @@ bool QmlCompiler::compileDynamicMeta(QmlParser::Object *obj, int preAlias)
builder.addProperty(p.name, type, ii);
}
- if (preAlias != -1) {
+ if (mode == ResolveAliases) {
for (int ii = 0; ii < obj->dynamicProperties.count(); ++ii) {
const Object::DynamicProperty &p = obj->dynamicProperties.at(ii);
@@ -1495,8 +1771,6 @@ bool QmlCompiler::compileDynamicMeta(QmlParser::Object *obj, int preAlias)
((QmlVMEMetaData *)dynamicData.data())->signalCount++;
}
- int slotStart = obj->dynamicSlots.isEmpty()?-1:output->primitives.count();
-
for (int ii = 0; ii < obj->dynamicSlots.count(); ++ii) {
const Object::DynamicSlot &s = obj->dynamicSlots.at(ii);
QByteArray sig(s.name + "(");
@@ -1509,57 +1783,37 @@ bool QmlCompiler::compileDynamicMeta(QmlParser::Object *obj, int preAlias)
b.setParameterNames(s.parameterNames);
((QmlVMEMetaData *)dynamicData.data())->methodCount++;
- QmlVMEMetaData::MethodData methodData = { s.parameterNames.count() };
- dynamicData.append((char *)&methodData, sizeof(methodData));
+ QmlVMEMetaData::MethodData methodData =
+ { s.parameterNames.count(), 0, s.body.length(), 0 };
- if (preAlias == -1)
- output->primitives << s.body;
+ dynamicData.append((char *)&methodData, sizeof(methodData));
}
- if (obj->metatype)
- builder.setSuperClass(obj->metatype);
-
- obj->extObjectData = builder.toMetaObject();
- static_cast<QMetaObject &>(obj->extObject) = *obj->extObjectData;
-
- if (preAlias != -1) {
- QmlInstruction &store = output->bytecode[preAlias];
-
- store.storeMeta.aliasData = output->indexForByteArray(dynamicData);
- qFree(output->synthesizedMetaObjects.at(store.storeMeta.data));
- output->synthesizedMetaObjects[store.storeMeta.data] = obj->extObjectData;
-
- } else {
- output->synthesizedMetaObjects << obj->extObjectData;
- QmlInstruction store;
- store.type = QmlInstruction::StoreMetaObject;
- store.storeMeta.data = output->synthesizedMetaObjects.count() - 1;
- store.storeMeta.slotData = slotStart;
- store.storeMeta.aliasData = output->indexForByteArray(dynamicData);
- store.line = obj->location.start.line;
- output->bytecode << store;
-
- if (hasAlias) {
- AliasReference alias;
- alias.object = obj;
- alias.instructionIdx = output->bytecode.count() - 1;
- compileState.aliases << alias;
- }
+ for (int ii = 0; ii < obj->dynamicSlots.count(); ++ii) {
+ const Object::DynamicSlot &s = obj->dynamicSlots.at(ii);
+ QmlVMEMetaData::MethodData *data =
+ ((QmlVMEMetaData *)dynamicData.data())->methodData() + ii;
+
+ data->bodyOffset = dynamicData.size();
+
+ dynamicData.append((const char *)s.body.constData(),
+ (s.body.length() * sizeof(QChar)));
}
- for (int ii = 0; ii < obj->dynamicProperties.count(); ++ii) {
- const Object::DynamicProperty &p = obj->dynamicProperties.at(ii);
+ obj->metadata = builder.toRelocatableData();
+ builder.fromRelocatableData(&obj->extObject, obj->metatype, obj->metadata);
- if (p.type == Object::DynamicProperty::Alias)
- continue;
+ // ### Remove me
+ obj->extObjectData = &obj->extObject;
- if (p.defaultValue) {
- p.defaultValue->name = p.name;
- p.defaultValue->isDefault = false;
- COMPILE_CHECK(compileProperty(p.defaultValue, obj, 0));
- }
+ if (mode == IgnoreAliases && hasAlias) {
+ AliasReference alias;
+ alias.object = obj;
+ compileState.aliases << alias;
}
+ obj->synthdata = dynamicData;
+
return true;
}
@@ -1623,9 +1877,9 @@ bool QmlCompiler::compileAlias(QMetaObjectBuilder &builder,
return true;
}
-bool QmlCompiler::compileBinding(QmlParser::Value *value,
- QmlParser::Property *prop,
- const BindingContext &ctxt)
+bool QmlCompiler::buildBinding(QmlParser::Value *value,
+ QmlParser::Property *prop,
+ const BindingContext &ctxt)
{
Q_ASSERT(prop->index);
Q_ASSERT(prop->parent);
@@ -1633,7 +1887,7 @@ bool QmlCompiler::compileBinding(QmlParser::Value *value,
QMetaProperty mp = prop->parent->metaObject()->property(prop->index);
if (!mp.isWritable() && !QmlMetaType::isList(prop->type))
- COMPILE_EXCEPTION2(prop, "Cannot assign binding to read-only property");
+ COMPILE_EXCEPTION2(prop, "Invalid property assignment: read-only property");
BindingReference reference;
reference.expression = value->value;
@@ -1641,185 +1895,104 @@ bool QmlCompiler::compileBinding(QmlParser::Value *value,
reference.value = value;
reference.instructionIdx = output->bytecode.count();
reference.bindingContext = ctxt;
- compileState.bindings << reference;
-
- output->bytecode << QmlInstruction();;
+ addBindingReference(reference);
return true;
}
-#if 0
-
-#include <iostream>
-#ifdef Q_CC_GNU
-#include <cxxabi.h>
-#endif
-
-////////////////////////////////////////////////////////////////////////////////
-// AST Dump
-////////////////////////////////////////////////////////////////////////////////
-class Dump: protected QmlJS::AST::Visitor
-{
- std::ostream &out;
- int depth;
-
-public:
- Dump(std::ostream &out)
- : out(out), depth(-1)
- { }
-
- void operator()(QmlJS::AST::Node *node)
- { QmlJS::AST::Node::acceptChild(node, this); }
-
-protected:
- virtual bool preVisit(QmlJS::AST::Node *node)
- {
- const char *name = typeid(*node).name();
-#ifdef Q_CC_GNU
- name = abi::__cxa_demangle(name, 0, 0, 0) + 17;
-#endif
- std::cout << std::string(++depth, ' ') << name << std::endl;
- return true;
- }
-
- virtual void postVisit(QmlJS::AST::Node *)
- {
- --depth;
- }
-};
-#endif
-
-// Update the init instruction with final data, and optimize some simple
-// bindings
-bool QmlCompiler::finalizeComponent(int patch)
+void QmlCompiler::genBindingAssignment(QmlParser::Value *binding,
+ QmlParser::Property *prop,
+ QmlParser::Object *obj)
{
- for (int ii = 0; ii < compileState.bindings.count(); ++ii) {
- const BindingReference &binding = compileState.bindings.at(ii);
- finalizeBinding(binding);
- }
+ Q_ASSERT(compileState.bindingMap.contains(binding));
- for (int ii = 0; ii < compileState.aliases.count(); ++ii) {
- const AliasReference &alias = compileState.aliases.at(ii);
- COMPILE_CHECK(finalizeAlias(alias));
+ const BindingReference &ref =
+ compileState.bindings.at(compileState.bindingMap.value(binding));
+
+ QMetaProperty mp = obj->metaObject()->property(prop->index);
+
+ QmlInstruction store;
+ int dataRef;
+ if (ref.compiledData.isEmpty()) {
+ dataRef = output->indexForString(ref.expression.asScript());
+ store.type = QmlInstruction::StoreBinding;
+ } else {
+ dataRef = output->indexForByteArray(ref.compiledData);
+ store.type = QmlInstruction::StoreCompiledBinding;
}
- output->bytecode[patch].init.dataSize = compileState.savedObjects;;
- output->bytecode[patch].init.bindingsSize = compileState.bindings.count();
- output->bytecode[patch].init.parserStatusSize =
- compileState.parserStatusCount;
+ store.assignBinding.property = prop->index;
+ store.assignBinding.value = dataRef;
+ store.assignBinding.category = QmlMetaProperty::propertyCategory(mp);
+ store.assignBinding.context = ref.bindingContext.stack;
- return true;
+ output->bytecode << store;
}
-bool QmlCompiler::finalizeAlias(const AliasReference &alias)
+bool QmlCompiler::completeComponentBuild()
{
- COMPILE_CHECK(compileDynamicMeta(alias.object, alias.instructionIdx));
-}
+ saveComponentState();
+
+ for (int ii = 0; ii < compileState.aliases.count(); ++ii) {
+ const AliasReference &alias = compileState.aliases.at(ii);
+ COMPILE_CHECK(buildDynamicMeta(alias.object, ResolveAliases));
+ }
+
-void QmlCompiler::finalizeBinding(const BindingReference &binding)
-{
- QmlBasicScript bs;
QmlBasicScript::Expression expr;
expr.component = compileState.root;
- expr.context = binding.bindingContext.object;
- expr.property = binding.property;
- expr.expression = binding.expression;
- foreach (const IdReference &id, compileState.ids)
+ foreach (const IdReference &id, compileState.ids) {
expr.ids.insert(id.id, qMakePair(id.object, id.idx));
+ }
- bs.compile(expr);
-
- QmlInstruction &instr = output->bytecode[binding.instructionIdx];
- instr.line = binding.value->location.start.line;
-
- // Single load optimization
- if (bs.isValid() && bs.isSingleLoad()) {
-
- QString singleLoadTarget = QLatin1String(bs.singleLoadTarget());
-
- if (singleLoadTarget.at(0).isUpper() &&
- compileState.ids.contains(singleLoadTarget) &&
- QmlMetaType::isObject(binding.property->type)) {
-
- IdReference reference = compileState.ids[singleLoadTarget];
-
- const QMetaObject *idMo = reference.object->metaObject();
- const QMetaObject *storeMo =
- QmlMetaType::rawMetaObjectForType(binding.property->type);
-
- Q_ASSERT(idMo);
- Q_ASSERT(storeMo);
-
- bool canAssign = false;
- while (!canAssign && idMo) {
- if (idMo == storeMo)
- canAssign = true;
- else
- idMo = idMo->superClass();
- }
-
- if (canAssign) {
- int instructionIdx = reference.instructionIdx;
- if (output->bytecode.at(instructionIdx).setId.save == -1) {
- output->bytecode[instructionIdx].setId.save =
- compileState.savedObjects++;
- }
- int saveId = output->bytecode.at(instructionIdx).setId.save;
+ for (int ii = 0; ii < compileState.bindings.count(); ++ii) {
+ BindingReference &binding = compileState.bindings[ii];
- instr.type = QmlInstruction::PushProperty;
- instr.pushProperty.property = binding.property->index;
- QmlInstruction store;
- store.type = QmlInstruction::StoreStackObject;
- store.line = 0;
- store.assignStackObject.property =
- compileState.pushedProperties++;
- store.assignStackObject.object = saveId;
- output->bytecode << store;
- return;
- }
- }
- }
+ QmlBasicScript bs;
+ expr.context = binding.bindingContext.object;
+ expr.property = binding.property;
+ expr.expression = binding.expression;
- // General binding fallback
- int bref;
- if (bs.isValid()) {
- bref = output->indexForByteArray(QByteArray(bs.compileData(), bs.compileDataSize()));
- } else {
- bref = output->indexForString(binding.expression.asScript());
+ bs.compile(expr);
+ if (bs.isValid())
+ binding.compiledData =
+ QByteArray(bs.compileData(), bs.compileDataSize());
}
- instr.assignBinding.context = binding.bindingContext.stack;
-
- if (bs.isValid())
- instr.type = QmlInstruction::StoreCompiledBinding;
- else
- instr.type = QmlInstruction::StoreBinding;
-
- instr.assignBinding.property = binding.property->index;
- instr.assignBinding.value = bref;
- QMetaProperty mp = binding.property->parent->metaObject()->property(binding.property->index);
- instr.assignBinding.category = QmlMetaProperty::propertyCategory(mp);
+ return true;
}
/*!
- Returns true if object can be assigned to a (QObject) property of type
- convertType.
+ Returns true if from can be assigned to a (QObject) property of type
+ to.
*/
-bool QmlCompiler::canConvert(int convertType, QmlParser::Object *object)
+bool QmlCompiler::canCoerce(int to, QmlParser::Object *from)
{
- const QMetaObject *convertTypeMo =
- QmlMetaType::rawMetaObjectForType(convertType);
- const QMetaObject *objectMo = object->metaObject();
+ const QMetaObject *toMo =
+ QmlMetaType::rawMetaObjectForType(to);
+ const QMetaObject *fromMo = from->metaObject();
- while (objectMo) {
- if (objectMo == convertTypeMo)
+ while (fromMo) {
+ if (fromMo == toMo)
return true;
- objectMo = objectMo->superClass();
+ fromMo = fromMo->superClass();
}
return false;
}
+QmlType *QmlCompiler::toQmlType(QmlParser::Object *from)
+{
+ // ### Optimize
+ const QMetaObject *mo = from->metatype;
+ QmlType *type = 0;
+ while (!type && mo) {
+ type = QmlMetaType::qmlType(mo);
+ mo = mo->superClass();
+ }
+ return type;
+}
+
QStringList QmlCompiler::deferredProperties(QmlParser::Object *obj)
{
const QMetaObject *mo = obj->metatype;
@@ -1833,63 +2006,4 @@ QStringList QmlCompiler::deferredProperties(QmlParser::Object *obj)
return rv;
}
-QmlCompiledData::QmlCompiledData()
-{
-}
-
-QmlCompiledData::QmlCompiledData(const QmlCompiledData &other)
-{
- *this = other;
-}
-
-QmlCompiledData::~QmlCompiledData()
-{
- for (int ii = 0; ii < types.count(); ++ii) {
- if (types.at(ii).ref)
- types.at(ii).ref->release();
- }
-}
-
-QmlCompiledData &QmlCompiledData::operator=(const QmlCompiledData &other)
-{
- types = other.types;
- root = other.root;
- primitives = other.primitives;
- floatData = other.floatData;
- intData = other.intData;
- customTypeData = other.customTypeData;
- datas = other.datas;
- synthesizedMetaObjects = other.synthesizedMetaObjects;
- bytecode = other.bytecode;
- return *this;
-}
-
-QObject *QmlCompiledData::TypeReference::createInstance(QmlContext *ctxt) const
-{
- if (type) {
- QObject *rv = type->create();
- if (rv)
- QmlEngine::setContextForObject(rv, ctxt);
- return rv;
- } else {
- Q_ASSERT(component);
- QObject *rv = component->create(ctxt);
- QmlContext *ctxt = qmlContext(rv);
- if(ctxt) {
- static_cast<QmlContextPrivate *>(QObjectPrivate::get(ctxt))->typeName = className;
- }
- return rv;
- }
-}
-
-const QMetaObject *QmlCompiledData::TypeReference::metaObject() const
-{
- if (type) {
- return type->metaObject();
- } else {
- Q_ASSERT(component);
- return &static_cast<QmlComponentPrivate *>(QObjectPrivate::get(component))->cc->root;
- }
-}
-
QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlcompiler_p.h b/src/declarative/qml/qmlcompiler_p.h
index 1c45f57..b97de19 100644
--- a/src/declarative/qml/qmlcompiler_p.h
+++ b/src/declarative/qml/qmlcompiler_p.h
@@ -109,7 +109,10 @@ public:
QList<QmlInstruction> bytecode;
private:
+ QByteArray packData;
friend class QmlCompiler;
+ int pack(const char *, size_t);
+
int indexForString(const QString &);
int indexForByteArray(const QByteArray &);
int indexForFloat(float *, int);
@@ -146,57 +149,79 @@ private:
rv.stack = stack + 1;
return rv;
}
+ bool isSubContext() const { return stack != 0; }
int stack;
QmlParser::Object *object;
};
void compileTree(QmlParser::Object *tree);
- bool compileObject(QmlParser::Object *obj, const BindingContext &);
- bool compileComponent(QmlParser::Object *obj, const BindingContext &);
- bool compileComponentFromRoot(QmlParser::Object *obj, const BindingContext &);
- bool compileFetchedObject(QmlParser::Object *obj, const BindingContext &);
- bool compileSignal(QmlParser::Property *prop, QmlParser::Object *obj);
- bool testProperty(QmlParser::Property *prop, QmlParser::Object *obj);
- int signalByName(const QMetaObject *, const QByteArray &name);
- bool compileProperty(QmlParser::Property *prop, QmlParser::Object *obj, const BindingContext &);
- bool compileIdProperty(QmlParser::Property *prop,
- QmlParser::Object *obj);
- bool compileAttachedProperty(QmlParser::Property *prop,
- const BindingContext &ctxt);
- bool compileNestedProperty(QmlParser::Property *prop,
+
+
+ bool buildObject(QmlParser::Object *obj, const BindingContext &);
+ bool buildComponent(QmlParser::Object *obj, const BindingContext &);
+ bool buildSubObject(QmlParser::Object *obj, const BindingContext &);
+ bool buildSignal(QmlParser::Property *prop, QmlParser::Object *obj,
+ const BindingContext &);
+ bool buildProperty(QmlParser::Property *prop, QmlParser::Object *obj,
+ const BindingContext &);
+ bool buildIdProperty(QmlParser::Property *prop, QmlParser::Object *obj);
+ bool buildAttachedProperty(QmlParser::Property *prop,
+ QmlParser::Object *obj,
const BindingContext &ctxt);
- bool compileListProperty(QmlParser::Property *prop,
- QmlParser::Object *obj,
- const BindingContext &ctxt);
- bool compilePropertyAssignment(QmlParser::Property *prop,
- QmlParser::Object *obj,
- const BindingContext &ctxt);
- bool compilePropertyObjectAssignment(QmlParser::Property *prop,
- QmlParser::Value *value,
- const BindingContext &ctxt);
- bool compilePropertyLiteralAssignment(QmlParser::Property *prop,
- QmlParser::Object *obj,
- QmlParser::Value *value,
- const BindingContext &ctxt);
- bool compileStoreInstruction(QmlInstruction &instr,
- const QMetaProperty &prop,
- QmlParser::Value *value);
-
- bool compileDynamicMeta(QmlParser::Object *obj, int preAlias = -1);
+ bool buildGroupedProperty(QmlParser::Property *prop,
+ QmlParser::Object *obj,
+ const BindingContext &ctxt);
+ bool buildListProperty(QmlParser::Property *prop,
+ QmlParser::Object *obj,
+ const BindingContext &ctxt);
+ bool buildPropertyAssignment(QmlParser::Property *prop,
+ QmlParser::Object *obj,
+ const BindingContext &ctxt);
+ bool buildPropertyObjectAssignment(QmlParser::Property *prop,
+ QmlParser::Object *obj,
+ QmlParser::Value *value,
+ const BindingContext &ctxt);
+ bool buildPropertyLiteralAssignment(QmlParser::Property *prop,
+ QmlParser::Object *obj,
+ QmlParser::Value *value,
+ const BindingContext &ctxt);
+ bool testProperty(QmlParser::Property *prop, QmlParser::Object *obj);
+ bool testLiteralAssignment(const QMetaProperty &prop,
+ QmlParser::Value *value);
+ enum DynamicMetaMode { IgnoreAliases, ResolveAliases };
+ bool mergeDynamicMetaProperties(QmlParser::Object *obj);
+ bool buildDynamicMeta(QmlParser::Object *obj, DynamicMetaMode mode);
+ bool checkDynamicMeta(QmlParser::Object *obj);
+ bool buildBinding(QmlParser::Value *, QmlParser::Property *prop,
+ const BindingContext &ctxt);
+ bool buildComponentFromRoot(QmlParser::Object *obj, const BindingContext &);
bool compileAlias(QMetaObjectBuilder &,
QByteArray &data,
QmlParser::Object *obj,
const QmlParser::Object::DynamicProperty &);
- bool compileBinding(QmlParser::Value *, QmlParser::Property *prop,
- const BindingContext &ctxt);
+ bool completeComponentBuild();
- bool finalizeComponent(int patch);
- struct BindingReference;
- void finalizeBinding(const BindingReference &);
- struct AliasReference;
- bool finalizeAlias(const AliasReference &);
- bool canConvert(int, QmlParser::Object *);
+ void genObject(QmlParser::Object *obj);
+ void genObjectBody(QmlParser::Object *obj);
+ void genComponent(QmlParser::Object *obj);
+ void genValueProperty(QmlParser::Property *prop, QmlParser::Object *obj);
+ void genListProperty(QmlParser::Property *prop, QmlParser::Object *obj);
+ void genPropertyAssignment(QmlParser::Property *prop,
+ QmlParser::Object *obj);
+ void genLiteralAssignment(const QMetaProperty &prop,
+ QmlParser::Value *value);
+ void genBindingAssignment(QmlParser::Value *binding,
+ QmlParser::Property *prop,
+ QmlParser::Object *obj);
+
+
+ int componentTypeRef();
+
+ static int findSignalByName(const QMetaObject *, const QByteArray &name);
+ static bool canCoerce(int to, QmlParser::Object *from);
+ static QmlType *toQmlType(QmlParser::Object *from);
+
QStringList deferredProperties(QmlParser::Object *);
struct IdReference {
@@ -205,6 +230,7 @@ private:
int instructionIdx;
int idx;
};
+ void addId(const QString &, QmlParser::Object *);
struct AliasReference {
QmlParser::Object *object;
@@ -215,28 +241,35 @@ private:
QmlParser::Variant expression;
QmlParser::Property *property;
QmlParser::Value *value;
+ QByteArray compiledData;
int instructionIdx;
BindingContext bindingContext;
};
+ void addBindingReference(const BindingReference &);
struct ComponentCompileState
{
- ComponentCompileState() : parserStatusCount(0), savedObjects(0), pushedProperties(0), root(0) {}
+ ComponentCompileState()
+ : parserStatusCount(0), savedObjects(0),
+ pushedProperties(0), root(0) {}
QHash<QString, IdReference> ids;
int parserStatusCount;
int savedObjects;
int pushedProperties;
QList<BindingReference> bindings;
+ QHash<QmlParser::Value *, int> bindingMap;
QList<AliasReference> aliases;
QmlParser::Object *root;
};
ComponentCompileState compileState;
+ void saveComponentState();
+ ComponentCompileState componentState(QmlParser::Object *);
+ QHash<QmlParser::Object *, ComponentCompileState> savedCompileStates;
+
QList<QmlError> exceptions;
QmlCompiledData *output;
-
};
-
QT_END_NAMESPACE
#endif // QMLCOMPILER_P_H
diff --git a/src/declarative/qml/qmlcompositetypemanager.cpp b/src/declarative/qml/qmlcompositetypemanager.cpp
index ef77803..c7ef765 100644
--- a/src/declarative/qml/qmlcompositetypemanager.cpp
+++ b/src/declarative/qml/qmlcompositetypemanager.cpp
@@ -110,8 +110,6 @@ QmlCompositeTypeData::toCompiledComponent(QmlEngine *engine)
if (!compiler.compile(engine, this, compiledComponent)) {
status = Error;
errors = compiler.errors();
- for(int ii = 0; ii < errors.count(); ++ii)
- errors[ii].setUrl(compiledComponent->url);
compiledComponent->release();
compiledComponent = 0;
}
diff --git a/src/declarative/qml/qmlcontext.cpp b/src/declarative/qml/qmlcontext.cpp
index 0b2742d..c3cee4c 100644
--- a/src/declarative/qml/qmlcontext.cpp
+++ b/src/declarative/qml/qmlcontext.cpp
@@ -73,6 +73,8 @@ void QmlContextPrivate::dump(int depth)
void QmlContextPrivate::destroyed(QObject *obj)
{
+ Q_Q(QmlContext);
+
defaultObjects.removeAll(obj);
QVariant variantObject = QVariant::fromValue(obj);
@@ -84,10 +86,9 @@ void QmlContextPrivate::destroyed(QObject *obj)
}
}
- // ### Work around bug in shutdown
- // for (int ii = 0; ii < notifies.count(); ++ii) {
- // QMetaObject::activate(q, notifies[ii] + notifyIndex, 0);
- // }
+ for (int ii = 0; ii < notifies.count(); ++ii) {
+ QMetaObject::activate(q, notifies[ii] + notifyIndex, 0);
+ }
}
void QmlContextPrivate::init()
diff --git a/src/declarative/qml/qmldom.cpp b/src/declarative/qml/qmldom.cpp
index 648eb36..b5d3c80 100644
--- a/src/declarative/qml/qmldom.cpp
+++ b/src/declarative/qml/qmldom.cpp
@@ -1379,7 +1379,6 @@ QmlDomValue::Type QmlDomValue::type() const
return PropertyBinding;
case QmlParser::Value::ValueSource:
return ValueSource;
- case QmlParser::Value::Component:
case QmlParser::Value::CreatedObject:
return Object;
case QmlParser::Value::SignalObject:
diff --git a/src/declarative/qml/qmlinstruction.cpp b/src/declarative/qml/qmlinstruction.cpp
index 1647a12..863ff9a 100644
--- a/src/declarative/qml/qmlinstruction.cpp
+++ b/src/declarative/qml/qmlinstruction.cpp
@@ -54,13 +54,13 @@ void QmlCompiledComponent::dump(QmlInstruction *instr, int idx)
switch(instr->type) {
case QmlInstruction::Init:
- qWarning() << idx << "\t" << line << "\t" << "INIT\t\t\t" << instr->init.dataSize;
+ qWarning() << idx << "\t" << line << "\t" << "INIT";
break;
case QmlInstruction::CreateObject:
qWarning() << idx << "\t" << line << "\t" << "CREATE\t\t\t" << instr->create.type << "\t\t\t" << types.at(instr->create.type).className;
break;
case QmlInstruction::SetId:
- qWarning() << idx << "\t" << line << "\t" << "SETID\t\t\t" << instr->setId.value << "\t" << instr->setId.save << "\t\t" << primitives.at(instr->setId.value);
+ qWarning() << idx << "\t" << line << "\t" << "SETID\t\t\t" << instr->setId.value << "\t\t\t\t" << primitives.at(instr->setId.value);
break;
case QmlInstruction::SetDefault:
qWarning() << idx << "\t" << line << "\t" << "SET_DEFAULT";
@@ -125,8 +125,11 @@ void QmlCompiledComponent::dump(QmlInstruction *instr, int idx)
case QmlInstruction::StoreObject:
qWarning() << idx << "\t" << line << "\t" << "STORE_OBJECT\t\t" << instr->storeObject.propertyIndex;
break;
- case QmlInstruction::AssignCustomType:
- qWarning() << idx << "\t" << line << "\t" << "ASSIGN_CUSTOMTYPE\t\t" << instr->assignCustomType.propertyIndex << "\t" << instr->assignCustomType.valueIndex;
+ case QmlInstruction::StoreVariantObject:
+ qWarning() << idx << "\t" << line << "\t" << "STORE_VARIANT_OBJECT\t" << instr->storeObject.propertyIndex;
+ break;
+ case QmlInstruction::StoreInterface:
+ qWarning() << idx << "\t" << line << "\t" << "STORE_INTERFACE\t\t" << instr->storeObject.propertyIndex;
break;
case QmlInstruction::StoreSignal:
qWarning() << idx << "\t" << line << "\t" << "STORE_SIGNAL\t\t" << instr->storeSignal.signalIndex << "\t" << instr->storeSignal.value << "\t\t" << primitives.at(instr->storeSignal.value);
@@ -134,6 +137,9 @@ void QmlCompiledComponent::dump(QmlInstruction *instr, int idx)
case QmlInstruction::AssignSignalObject:
qWarning() << idx << "\t" << line << "\t" << "ASSIGN_SIGNAL_OBJECT\t" << instr->assignSignalObject.signal << "\t\t\t" << datas.at(instr->assignSignalObject.signal);
break;
+ case QmlInstruction::AssignCustomType:
+ qWarning() << idx << "\t" << line << "\t" << "ASSIGN_CUSTOMTYPE\t\t" << instr->assignCustomType.propertyIndex << "\t" << instr->assignCustomType.valueIndex;
+ break;
case QmlInstruction::StoreBinding:
qWarning() << idx << "\t" << line << "\t" << "STORE_BINDING\t\t" << instr->assignBinding.property << "\t" << instr->assignBinding.value << "\t\t" << instr->assignBinding.context << primitives.at(instr->assignBinding.value);
break;
@@ -149,6 +155,12 @@ void QmlCompiledComponent::dump(QmlInstruction *instr, int idx)
case QmlInstruction::CompleteObject:
qWarning() << idx << "\t" << line << "\t" << "COMPLETE\t\t" << instr->complete.castValue;
break;
+ case QmlInstruction::StoreObjectQmlList:
+ qWarning() << idx << "\t" << line << "\t" << "STORE_OBJECT_QMLLIST";
+ break;
+ case QmlInstruction::StoreObjectQList:
+ qWarning() << idx << "\t" << line << "\t" << "STORE_OBJECT_QLIST";
+ break;
case QmlInstruction::AssignObjectList:
qWarning() << idx << "\t" << line << "\t" << "ASSIGN_OBJECT_LIST\t";
break;
@@ -170,14 +182,11 @@ void QmlCompiledComponent::dump(QmlInstruction *instr, int idx)
case QmlInstruction::PopQList:
qWarning() << idx << "\t" << line << "\t" << "POP_QLIST";
break;
- case QmlInstruction::PushProperty:
- qWarning() << idx << "\t" << line << "\t" << "PUSH_PROPERTY" << "\t\t" << instr->pushProperty.property;
- break;
- case QmlInstruction::StoreStackObject:
- qWarning() << idx << "\t" << line << "\t" << "STORE_STACK_OBJ" << "\t" << instr->assignStackObject.property << "\t" << instr->assignStackObject.object;
+ case QmlInstruction::Defer:
+ qWarning() << idx << "\t" << line << "\t" << "DEFER" << "\t\t" << instr->defer.deferCount;
break;
default:
- qWarning() << idx << "\t" << line << "\t" << "XXX UNKOWN INSTRUCTION";
+ qWarning() << idx << "\t" << line << "\t" << "XXX UNKOWN INSTRUCTION" << "\t" << instr->type;
break;
}
}
diff --git a/src/declarative/qml/qmlinstruction_p.h b/src/declarative/qml/qmlinstruction_p.h
index 40f9a32..39196a1 100644
--- a/src/declarative/qml/qmlinstruction_p.h
+++ b/src/declarative/qml/qmlinstruction_p.h
@@ -118,8 +118,6 @@ public:
StoreSignal, /* storeSignal */
- // XXX need to handle storing objects in variants
-
//
// Unresolved single assignment
//
@@ -154,14 +152,6 @@ public:
// Deferred creation
//
Defer, /* defer */
-
- //
- // Expression optimizations
- //
- // PushProperty - Save the property for later use
- // StoreStackObject - Assign the stack object (no checks)
- PushProperty, /* pushProperty */
- StoreStackObject /* assignStackObject */
};
QmlInstruction()
: line(0) {}
@@ -170,7 +160,6 @@ public:
unsigned short line;
union {
struct {
- int dataSize;
int bindingsSize;
int parserStatusSize;
} init;
@@ -185,7 +174,6 @@ public:
} storeMeta;
struct {
int value;
- int save;
} setId;
struct {
int property;
@@ -198,7 +186,6 @@ public:
} assignBinding;
struct {
int property;
- bool isObject;
} fetch;
struct {
int property;
@@ -281,13 +268,6 @@ public:
int id;
} fetchAttached;
struct {
- int property;
- } pushProperty;
- struct {
- int property;
- int object;
- } assignStackObject;
- struct {
int deferCount;
} defer;
};
diff --git a/src/declarative/qml/qmlmetaproperty.cpp b/src/declarative/qml/qmlmetaproperty.cpp
index e158adf..6602021 100644
--- a/src/declarative/qml/qmlmetaproperty.cpp
+++ b/src/declarative/qml/qmlmetaproperty.cpp
@@ -663,9 +663,6 @@ void QmlMetaPropertyPrivate::writeValueProperty(const QVariant &value)
return;
}
- if (!value.isValid())
- return;
-
int t = propertyType();
int vt = value.userType();
int category = propertyCategory();
@@ -684,19 +681,22 @@ void QmlMetaPropertyPrivate::writeValueProperty(const QVariant &value)
QObject *o = QmlMetaType::toQObject(value);
- if (!o)
- return;
+ const QMetaObject *valMo = 0;
- const QMetaObject *valMo = o->metaObject();
- const QMetaObject *propMo = QmlMetaType::rawMetaObjectForType(t);
+ if (o) {
+
+ valMo = o->metaObject();
+ const QMetaObject *propMo = QmlMetaType::rawMetaObjectForType(t);
+
+ while (valMo) {
+ if (valMo == propMo)
+ break;
+ valMo = valMo->superClass();
+ }
- while (valMo) {
- if (valMo == propMo)
- break;
- valMo = valMo->superClass();
}
- if (valMo) {
+ if (valMo || !o) {
void *args[] = { &o, 0 };
QMetaObject::metacall(object, QMetaObject::WriteProperty, coreIdx,
diff --git a/src/declarative/qml/qmlparser.cpp b/src/declarative/qml/qmlparser.cpp
index 8daab6a..02f229e 100644
--- a/src/declarative/qml/qmlparser.cpp
+++ b/src/declarative/qml/qmlparser.cpp
@@ -62,7 +62,8 @@ QT_BEGIN_NAMESPACE
using namespace QmlParser;
QmlParser::Object::Object()
-: type(-1), metatype(0), extObjectData(0), defaultProperty(0)
+: type(-1), metatype(0), extObjectData(0), defaultProperty(0),
+ parserStatusCast(-1)
{
}
@@ -71,6 +72,10 @@ QmlParser::Object::~Object()
if (defaultProperty) defaultProperty->release();
foreach(Property *prop, properties)
prop->release();
+ foreach(Property *prop, valueProperties)
+ prop->release();
+ foreach(Property *prop, signalProperties)
+ prop->release();
}
const QMetaObject *Object::metaObject() const
@@ -90,6 +95,30 @@ QmlParser::Property *Object::getDefaultProperty()
return defaultProperty;
}
+void QmlParser::Object::addValueProperty(Property *p)
+{
+ p->addref();
+ valueProperties << p;
+}
+
+void QmlParser::Object::addSignalProperty(Property *p)
+{
+ p->addref();
+ signalProperties << p;
+}
+
+void QmlParser::Object::addAttachedProperty(Property *p)
+{
+ p->addref();
+ attachedProperties << p;
+}
+
+void QmlParser::Object::addGroupedProperty(Property *p)
+{
+ p->addref();
+ groupedProperties << p;
+}
+
Property *QmlParser::Object::getProperty(const QByteArray &name, bool create)
{
if (!properties.contains(name)) {
@@ -160,12 +189,13 @@ void QmlParser::Object::dump(int indent) const
}
QmlParser::Property::Property()
-: parent(0), type(0), index(-1), value(0), isDefault(true)
+: parent(0), type(0), index(-1), value(0), isDefault(true), isDeferred(false)
{
}
QmlParser::Property::Property(const QByteArray &n)
-: parent(0), type(0), index(-1), value(0), name(n), isDefault(false)
+: parent(0), type(0), index(-1), value(0), name(n), isDefault(false),
+ isDeferred(false)
{
}
@@ -187,6 +217,11 @@ void QmlParser::Property::addValue(Value *v)
values << v;
}
+bool QmlParser::Property::isEmpty() const
+{
+ return !value && values.isEmpty();
+}
+
void QmlParser::Property::dump(int indent) const
{
QByteArray ba(indent * 4, ' ');
@@ -232,9 +267,6 @@ void QmlParser::Value::dump(int indent) const
case Value::SignalExpression:
type = "SignalExpression";
break;
- case Value::Component:
- type = "Component";
- break;
case Value::Id:
type = "Id";
break;
diff --git a/src/declarative/qml/qmlparser_p.h b/src/declarative/qml/qmlparser_p.h
index 7550870..d96a43e 100644
--- a/src/declarative/qml/qmlparser_p.h
+++ b/src/declarative/qml/qmlparser_p.h
@@ -110,8 +110,8 @@ namespace QmlParser
virtual ~Object();
// Type of the object. The integer is an index into the
- // QmlCompiledData::types array, or -1 if the object is a fetched
- // object.
+ // QmlCompiledData::types array, or -1 if the object is a property
+ // group.
int type;
// The url of this object if it is an external type. Used by the DOM
QUrl url;
@@ -131,6 +131,8 @@ namespace QmlParser
// this type. Otherwise null
QMetaObject *extObjectData;
QAbstractDynamicMetaObject extObject;
+ QByteArray metadata; // Generated by compiler
+ QByteArray synthdata; // Generated by compiler
Property *getDefaultProperty();
Property *getProperty(const QByteArray &name, bool create=true);
@@ -138,6 +140,22 @@ namespace QmlParser
Property *defaultProperty;
QHash<QByteArray, Property *> properties;
+ // Output of the compilation phase (these properties continue to exist
+ // in either the defaultProperty or properties members too)
+ void addValueProperty(Property *);
+ void addSignalProperty(Property *);
+ void addAttachedProperty(Property *);
+ void addGroupedProperty(Property *);
+ QList<Property *> valueProperties;
+ QList<Property *> signalProperties;
+ QList<Property *> attachedProperties;
+ QList<Property *> groupedProperties;
+
+ // The bytes to cast instances by to get to the QmlParserStatus
+ // interface. -1 indicates the type doesn't support this interface.
+ // Set by the QmlCompiler.
+ int parserStatusCast;
+
LocationSpan location;
struct DynamicProperty {
@@ -242,8 +260,6 @@ namespace QmlParser
SignalObject,
// This is used as a signal expression assignment
SignalExpression,
- // This is used as an implicit component creation
- Component,
// This is used as an id assignment only
Id
};
@@ -281,6 +297,9 @@ namespace QmlParser
// The metaobject index of this property, or -1 if unknown.
int index;
+ // Returns true if this is an empty property - both value and values
+ // are unset.
+ bool isEmpty() const;
// The list of values assigned to this property. Content in values
// and value are mutually exclusive
QList<Value *> values;
@@ -291,6 +310,9 @@ namespace QmlParser
QByteArray name;
// True if this property was accessed as the default property.
bool isDefault;
+ // True if the setting of this property will be deferred. Set by the
+ // QmlCompiler
+ bool isDeferred;
LocationSpan location;
LocationRange listValueRange;
diff --git a/src/declarative/qml/qmlvme.cpp b/src/declarative/qml/qmlvme.cpp
index 2acf1e2..dfb066b 100644
--- a/src/declarative/qml/qmlvme.cpp
+++ b/src/declarative/qml/qmlvme.cpp
@@ -152,7 +152,6 @@ QObject *QmlVME::run(QStack<QObject *> &stack, QmlContext *ctxt, QmlCompiledComp
QStack<ListInstance> qliststack;
QStack<QmlMetaProperty> pushedProperties;
- QObject **savedObjects = 0;
vmeErrors.clear();
@@ -162,12 +161,6 @@ QObject *QmlVME::run(QStack<QObject *> &stack, QmlContext *ctxt, QmlCompiledComp
switch(instr.type) {
case QmlInstruction::Init:
{
- if (instr.init.dataSize) {
- savedObjects = new QObject*[instr.init.dataSize];
- ::memset(savedObjects, 0,
- sizeof(QObject *)*instr.init.dataSize);
- }
-
if (instr.init.bindingsSize)
bindValues = QmlEnginePrivate::SimpleList<QmlBindableValue>(instr.init.bindingsSize);
if (instr.init.parserStatusSize)
@@ -214,9 +207,6 @@ QObject *QmlVME::run(QStack<QObject *> &stack, QmlContext *ctxt, QmlCompiledComp
QmlContext *ctxt =
QmlContext::activeContext();
ctxt->setContextProperty(primitives.at(instr.setId.value), target);
-
- if (instr.setId.save != -1)
- savedObjects[instr.setId.save] = target;
}
break;
@@ -239,7 +229,16 @@ QObject *QmlVME::run(QStack<QObject *> &stack, QmlContext *ctxt, QmlCompiledComp
case QmlInstruction::StoreMetaObject:
{
QObject *target = stack.top();
- new QmlVMEMetaObject(target, synthesizedMetaObjects.at(instr.storeMeta.data), &comp->primitives, instr.storeMeta.slotData, (const QmlVMEMetaData *)datas.at(instr.storeMeta.aliasData).constData(), comp);
+
+ QMetaObject mo;
+ const QByteArray &metadata = datas.at(instr.storeMeta.data);
+ QMetaObjectBuilder::fromRelocatableData(&mo, 0, metadata);
+
+ const QmlVMEMetaData *data = (const QmlVMEMetaData *)datas.at(instr.storeMeta.aliasData).constData();
+
+ (void)new QmlVMEMetaObject(target, &mo, data, comp);
+
+ // new QmlVMEMetaObject(target, synthesizedMetaObjects.at(instr.storeMeta.data), &comp->primitives, instr.storeMeta.slotData, (const QmlVMEMetaData *)datas.at(instr.storeMeta.aliasData).constData(), comp);
}
break;
@@ -545,15 +544,6 @@ QObject *QmlVME::run(QStack<QObject *> &stack, QmlContext *ctxt, QmlCompiledComp
}
break;
- case QmlInstruction::PushProperty:
- {
- QObject *target = stack.top();
- QmlMetaProperty mp(target, instr.pushProperty.property,
- QmlMetaProperty::Object);
- pushedProperties.push(mp);
- }
- break;
-
case QmlInstruction::StoreCompiledBinding:
{
QObject *target = stack.top();
@@ -745,22 +735,12 @@ QObject *QmlVME::run(QStack<QObject *> &stack, QmlContext *ctxt, QmlCompiledComp
QObject *target = stack.top();
QObject *obj = 0;
- if (instr.fetch.isObject) {
- // NOTE: This assumes a cast to QObject does not alter the
- // object pointer
- void *a[1];
- a[0] = &obj;
- QMetaObject::metacall(target, QMetaObject::ReadProperty,
- instr.fetch.property, a);
- } else {
- void *a[1];
- QVariant var;
- a[0] = &var;
- QMetaObject::metacall(target, QMetaObject::ReadProperty,
- instr.fetch.property, a);
- obj = QmlMetaType::toQObject(var);
-
- }
+ // NOTE: This assumes a cast to QObject does not alter the
+ // object pointer
+ void *a[1];
+ a[0] = &obj;
+ QMetaObject::metacall(target, QMetaObject::ReadProperty,
+ instr.fetch.property, a);
if (!obj)
VME_EXCEPTION("Cannot set properties on" << target->metaObject()->property(instr.fetch.property).name() << "as it is null");
@@ -795,21 +775,6 @@ QObject *QmlVME::run(QStack<QObject *> &stack, QmlContext *ctxt, QmlCompiledComp
}
break;
- case QmlInstruction::StoreStackObject:
- {
- const QmlMetaProperty &prop =
- pushedProperties.at(instr.assignStackObject.property);
- QObject *obj = savedObjects[instr.assignStackObject.object];
-
- // NOTE: This assumes a cast to QObject does not alter the
- // object pointer
- void *a[1];
- a[0] = (void *)&obj;
- QMetaObject::metacall(prop.object(), QMetaObject::WriteProperty,
- prop.coreIndex(), a);
- }
- break;
-
default:
qFatal("QmlCompiledComponent: Internal error - unknown instruction %d", instr.type);
break;
@@ -832,11 +797,6 @@ QObject *QmlVME::run(QStack<QObject *> &stack, QmlContext *ctxt, QmlCompiledComp
if (parserStatus.count)
ep->parserStatus << parserStatus;
- comp->dumpPost();
-
- if (savedObjects)
- delete [] savedObjects;
-
if (stack.isEmpty())
return 0;
else
diff --git a/src/declarative/qml/qmlvmemetaobject.cpp b/src/declarative/qml/qmlvmemetaobject.cpp
index 6d14689..33a31a4 100644
--- a/src/declarative/qml/qmlvmemetaobject.cpp
+++ b/src/declarative/qml/qmlvmemetaobject.cpp
@@ -53,12 +53,9 @@ QT_BEGIN_NAMESPACE
QmlVMEMetaObject::QmlVMEMetaObject(QObject *obj,
const QMetaObject *other,
- QList<QString> *strData,
- int slotData,
const QmlVMEMetaData *meta,
QmlRefCount *rc)
-: object(obj), ref(rc), metaData(meta), slotData(strData),
- slotDataIdx(slotData), parent(0)
+: object(obj), ref(rc), metaData(meta), parent(0)
{
if (ref)
ref->addref();
@@ -208,7 +205,11 @@ int QmlVMEMetaObject::metaCall(QMetaObject::Call c, int _id, void **a)
id -= plainSignals;
if (id < metaData->methodCount) {
- QString code = slotData->at(id + slotDataIdx);
+ QmlVMEMetaData::MethodData *data = metaData->methodData() + id;
+ const QChar *body =
+ (const QChar *)(((const char*)metaData) + data->bodyOffset);
+
+ QString code = QString::fromRawData(body, data->bodyLength);
QmlContext *ctxt = qmlContext(object);
if (0 == (metaData->methodData() + id)->parameterCount) {
diff --git a/src/declarative/qml/qmlvmemetaobject_p.h b/src/declarative/qml/qmlvmemetaobject_p.h
index 6421c3f..931d22c 100644
--- a/src/declarative/qml/qmlvmemetaobject_p.h
+++ b/src/declarative/qml/qmlvmemetaobject_p.h
@@ -78,6 +78,9 @@ struct QmlVMEMetaData
struct MethodData {
int parameterCount;
+ int bodyOffset;
+ int bodyLength;
+ int _dummy;
};
PropertyData *propertyData() const {
@@ -89,7 +92,7 @@ struct QmlVMEMetaData
}
MethodData *methodData() const {
- return (MethodData *)(aliasData() + propertyCount);
+ return (MethodData *)(aliasData() + aliasCount);
}
};
@@ -97,7 +100,8 @@ class QmlRefCount;
class QmlVMEMetaObject : public QAbstractDynamicMetaObject
{
public:
- QmlVMEMetaObject(QObject *, const QMetaObject *, QList<QString> *, int slotData, const QmlVMEMetaData *data, QmlRefCount * = 0);
+ QmlVMEMetaObject(QObject *, const QMetaObject *, const QmlVMEMetaData *data,
+ QmlRefCount * = 0);
~QmlVMEMetaObject();
protected:
@@ -114,8 +118,10 @@ private:
QVariant *data;
QBitArray aConnected;
+#if 0
QList<QString> *slotData;
int slotDataIdx;
+#endif
QAbstractDynamicMetaObject *parent;
diff --git a/tests/auto/declarative/qmlbindengine/testtypes.h b/tests/auto/declarative/qmlbindengine/testtypes.h
index df31f7a..f5b309e 100644
--- a/tests/auto/declarative/qmlbindengine/testtypes.h
+++ b/tests/auto/declarative/qmlbindengine/testtypes.h
@@ -8,8 +8,8 @@
class MyQmlObject : public QObject
{
Q_OBJECT
- Q_PROPERTY(bool trueProperty READ trueProperty)
- Q_PROPERTY(bool falseProperty READ falseProperty)
+ Q_PROPERTY(bool trueProperty READ trueProperty CONSTANT)
+ Q_PROPERTY(bool falseProperty READ falseProperty CONSTANT)
Q_PROPERTY(QString stringProperty READ stringProperty WRITE setStringProperty NOTIFY stringChanged)
Q_PROPERTY(QObject *objectProperty READ objectProperty WRITE setObjectProperty NOTIFY objectChanged);
public:
@@ -64,14 +64,14 @@ QML_DECLARE_TYPE(MyQmlObject);
class MyQmlContainer : public QObject
{
Q_OBJECT
- Q_PROPERTY(QList<MyQmlContainer*>* children READ children)
+ Q_PROPERTY(QList<MyQmlObject*>* children READ children)
public:
MyQmlContainer() {}
- QList<MyQmlContainer*> *children() { return &m_children; }
+ QList<MyQmlObject*> *children() { return &m_children; }
private:
- QList<MyQmlContainer*> m_children;
+ QList<MyQmlObject*> m_children;
};
QML_DECLARE_TYPE(MyQmlContainer);
@@ -94,8 +94,8 @@ public:
class MyDefaultObject1 : public QObject
{
Q_OBJECT
- Q_PROPERTY(int horseLegs READ horseLegs);
- Q_PROPERTY(int antLegs READ antLegs);
+ Q_PROPERTY(int horseLegs READ horseLegs CONSTANT);
+ Q_PROPERTY(int antLegs READ antLegs CONSTANT);
public:
int horseLegs() const { return 4; }
int antLegs() const { return 6; }
@@ -104,8 +104,8 @@ public:
class MyDefaultObject2 : public QObject
{
Q_OBJECT
- Q_PROPERTY(int antLegs READ antLegs);
- Q_PROPERTY(int emuLegs READ emuLegs);
+ Q_PROPERTY(int antLegs READ antLegs CONSTANT);
+ Q_PROPERTY(int emuLegs READ emuLegs CONSTANT);
public:
int antLegs() const { return 5; } // Had an accident
int emuLegs() const { return 2; }
@@ -114,8 +114,8 @@ public:
class MyDefaultObject3 : public QObject
{
Q_OBJECT
- Q_PROPERTY(int antLegs READ antLegs);
- Q_PROPERTY(int humanLegs READ humanLegs);
+ Q_PROPERTY(int antLegs READ antLegs CONSTANT);
+ Q_PROPERTY(int humanLegs READ humanLegs CONSTANT);
public:
int antLegs() const { return 7; } // Mutant
int humanLegs() const { return 2; }
diff --git a/tests/auto/declarative/qmlparser/duplicateIDs.errors.txt b/tests/auto/declarative/qmlparser/duplicateIDs.errors.txt
index b03f735..99f4c7c 100644
--- a/tests/auto/declarative/qmlparser/duplicateIDs.errors.txt
+++ b/tests/auto/declarative/qmlparser/duplicateIDs.errors.txt
@@ -1 +1 @@
-3:5:id is not unique
+3:19:id is not unique
diff --git a/tests/auto/declarative/qmlparser/failingComponent.errors.txt b/tests/auto/declarative/qmlparser/failingComponent.errors.txt
index 12fb4e7..a18f2e7 100644
--- a/tests/auto/declarative/qmlparser/failingComponent.errors.txt
+++ b/tests/auto/declarative/qmlparser/failingComponent.errors.txt
@@ -1,2 +1,2 @@
-1:-1:Unable to create type FailingComponent
-2:5:Cannot assign value to non-existant property "a"
+2:5:Cannot assign to non-existant property "a"
diff --git a/tests/auto/declarative/qmlparser/fakeDotProperty.errors.txt b/tests/auto/declarative/qmlparser/fakeDotProperty.errors.txt
index a94b38e..25f22ce 100644
--- a/tests/auto/declarative/qmlparser/fakeDotProperty.errors.txt
+++ b/tests/auto/declarative/qmlparser/fakeDotProperty.errors.txt
@@ -1 +1 @@
-2:11:Cannot assign value to non-existant property "something"
+2:5:Cannot nest non-QObject property "value"
diff --git a/tests/auto/declarative/qmlparser/idProperty.txt b/tests/auto/declarative/qmlparser/idProperty.txt
index 9c7d6fb..c3c2e50 100644
--- a/tests/auto/declarative/qmlparser/idProperty.txt
+++ b/tests/auto/declarative/qmlparser/idProperty.txt
@@ -2,6 +2,6 @@ MyContainer {
property var object : MyObjectId
MyTypeObject {
- id: MyObjectId
+ id: "MyObjectId"
}
}
diff --git a/tests/auto/declarative/qmlparser/invalidID.2.errors.txt b/tests/auto/declarative/qmlparser/invalidID.2.errors.txt
index 6380750..9c54aab 100644
--- a/tests/auto/declarative/qmlparser/invalidID.2.errors.txt
+++ b/tests/auto/declarative/qmlparser/invalidID.2.errors.txt
@@ -1,2 +1,2 @@
-1:1:"" is not a valid id
+2:5:"" is not a valid object id
diff --git a/tests/auto/declarative/qmlparser/invalidID.3.errors.txt b/tests/auto/declarative/qmlparser/invalidID.3.errors.txt
index 05937f0..36cd489 100644
--- a/tests/auto/declarative/qmlparser/invalidID.3.errors.txt
+++ b/tests/auto/declarative/qmlparser/invalidID.3.errors.txt
@@ -1 +1 @@
-2:5:The id property cannot be fetched
+2:5:Invalid use of id property
diff --git a/tests/auto/declarative/qmlparser/invalidID.4.errors.txt b/tests/auto/declarative/qmlparser/invalidID.4.errors.txt
index 50c8960..bb811cf 100644
--- a/tests/auto/declarative/qmlparser/invalidID.4.errors.txt
+++ b/tests/auto/declarative/qmlparser/invalidID.4.errors.txt
@@ -1 +1 @@
-3:5:The object id may only be set once
+3:5:Invalid use of id property
diff --git a/tests/auto/declarative/qmlparser/invalidID.errors.txt b/tests/auto/declarative/qmlparser/invalidID.errors.txt
index eed1869..7cefb7e 100644
--- a/tests/auto/declarative/qmlparser/invalidID.errors.txt
+++ b/tests/auto/declarative/qmlparser/invalidID.errors.txt
@@ -1 +1 @@
-1:1:"1" is not a valid id
+2:5:"1" is not a valid object id
diff --git a/tests/auto/declarative/qmlparser/missingSignal.errors.txt b/tests/auto/declarative/qmlparser/missingSignal.errors.txt
index 5c612cc..bcee331 100644
--- a/tests/auto/declarative/qmlparser/missingSignal.errors.txt
+++ b/tests/auto/declarative/qmlparser/missingSignal.errors.txt
@@ -1 +1 @@
-2:5:Cannot assign binding to non-existant property "onClicked"
+2:5:Cannot assign to non-existant property "onClicked"
diff --git a/tests/auto/declarative/qmlparser/nonexistantProperty.1.errors.txt b/tests/auto/declarative/qmlparser/nonexistantProperty.1.errors.txt
index e8f1a91..6f85946 100644
--- a/tests/auto/declarative/qmlparser/nonexistantProperty.1.errors.txt
+++ b/tests/auto/declarative/qmlparser/nonexistantProperty.1.errors.txt
@@ -1 +1 @@
-1:15:Cannot assign value to non-existant property "something"
+1:15:Cannot assign to non-existant property "something"
diff --git a/tests/auto/declarative/qmlparser/nonexistantProperty.2.errors.txt b/tests/auto/declarative/qmlparser/nonexistantProperty.2.errors.txt
index c154f91..8d6dfb4 100644
--- a/tests/auto/declarative/qmlparser/nonexistantProperty.2.errors.txt
+++ b/tests/auto/declarative/qmlparser/nonexistantProperty.2.errors.txt
@@ -1 +1 @@
-2:5:Cannot assign value to non-existant property "something"
+2:5:Cannot assign to non-existant property "something"
diff --git a/tests/auto/declarative/qmlparser/nonexistantProperty.3.errors.txt b/tests/auto/declarative/qmlparser/nonexistantProperty.3.errors.txt
index a254d7d..8d6dfb4 100644
--- a/tests/auto/declarative/qmlparser/nonexistantProperty.3.errors.txt
+++ b/tests/auto/declarative/qmlparser/nonexistantProperty.3.errors.txt
@@ -1 +1 @@
-2:5:Cannot assign binding to non-existant property "something"
+2:5:Cannot assign to non-existant property "something"
diff --git a/tests/auto/declarative/qmlparser/nonexistantProperty.4.errors.txt b/tests/auto/declarative/qmlparser/nonexistantProperty.4.errors.txt
index a254d7d..8d6dfb4 100644
--- a/tests/auto/declarative/qmlparser/nonexistantProperty.4.errors.txt
+++ b/tests/auto/declarative/qmlparser/nonexistantProperty.4.errors.txt
@@ -1 +1 @@
-2:5:Cannot assign binding to non-existant property "something"
+2:5:Cannot assign to non-existant property "something"
diff --git a/tests/auto/declarative/qmlparser/nonexistantProperty.6.errors.txt b/tests/auto/declarative/qmlparser/nonexistantProperty.6.errors.txt
index 3183b6d..fac833e 100644
--- a/tests/auto/declarative/qmlparser/nonexistantProperty.6.errors.txt
+++ b/tests/auto/declarative/qmlparser/nonexistantProperty.6.errors.txt
@@ -1 +1 @@
-2:-1:Cannot assign to default property
+2:5:Cannot assign to non-existant default property
diff --git a/tests/auto/declarative/qmlparser/readOnly.1.errors.txt b/tests/auto/declarative/qmlparser/readOnly.1.errors.txt
index 89009ce..8608370 100644
--- a/tests/auto/declarative/qmlparser/readOnly.1.errors.txt
+++ b/tests/auto/declarative/qmlparser/readOnly.1.errors.txt
@@ -1 +1 @@
-2:21:Cannot assign value "Hello World" to the read-only property readOnlyString
+2:21:Invalid property assignment: read-only property
diff --git a/tests/auto/declarative/qmlparser/readOnly.2.errors.txt b/tests/auto/declarative/qmlparser/readOnly.2.errors.txt
index ab27946..633d56f 100644
--- a/tests/auto/declarative/qmlparser/readOnly.2.errors.txt
+++ b/tests/auto/declarative/qmlparser/readOnly.2.errors.txt
@@ -1 +1 @@
-2:-1:Cannot assign a binding to read-only property "readOnlyString"
+2:5:Invalid property assignment: read-only property
diff --git a/tests/auto/declarative/qmlparser/tst_qmlparser.cpp b/tests/auto/declarative/qmlparser/tst_qmlparser.cpp
index cdc2a72..7023263 100644
--- a/tests/auto/declarative/qmlparser/tst_qmlparser.cpp
+++ b/tests/auto/declarative/qmlparser/tst_qmlparser.cpp
@@ -98,7 +98,7 @@ void tst_qmlparser::errors_data()
QTest::newRow("nonExistantProperty.3") << "nonexistantProperty.3.txt" << "nonexistantProperty.3.errors.txt" << false;
QTest::newRow("nonExistantProperty.4") << "nonexistantProperty.4.txt" << "nonexistantProperty.4.errors.txt" << false;
QTest::newRow("nonExistantProperty.5") << "nonexistantProperty.5.txt" << "nonexistantProperty.5.errors.txt" << false;
- QTest::newRow("nonExistantProperty.6") << "nonexistantProperty.6.txt" << "nonexistantProperty.6.errors.txt" << true;
+ QTest::newRow("nonExistantProperty.6") << "nonexistantProperty.6.txt" << "nonexistantProperty.6.errors.txt" << false;
QTest::newRow("wrongType (string for int)") << "wrongType.1.txt" << "wrongType.1.errors.txt" << false;
QTest::newRow("wrongType (int for bool)") << "wrongType.2.txt" << "wrongType.2.errors.txt" << false;
@@ -117,7 +117,7 @@ void tst_qmlparser::errors_data()
QTest::newRow("wrongType (int for string)") << "wrongType.14.txt" << "wrongType.14.errors.txt" << false;
QTest::newRow("readOnly.1") << "readOnly.1.txt" << "readOnly.1.errors.txt" << false;
- QTest::newRow("readOnly.2") << "readOnly.2.txt" << "readOnly.2.errors.txt" << true;
+ QTest::newRow("readOnly.2") << "readOnly.2.txt" << "readOnly.2.errors.txt" << false;
QTest::newRow("listAssignment.1") << "listAssignment.1.txt" << "listAssignment.1.errors.txt" << false;
QTest::newRow("listAssignment.2") << "listAssignment.2.txt" << "listAssignment.2.errors.txt" << false;
@@ -344,8 +344,8 @@ void tst_qmlparser::dynamicProperties()
QVERIFY(object != 0);
QCOMPARE(object->property("intProperty"), QVariant(10));
QCOMPARE(object->property("boolProperty"), QVariant(false));
- QCOMPARE(object->property("doubleProperty"), QVariant((float)-10.1));
- QCOMPARE(object->property("realProperty"), QVariant((float)-19.9));
+ QCOMPARE(object->property("doubleProperty"), QVariant(-10.1));
+ QCOMPARE(object->property("realProperty"), QVariant((qreal)-19.9));
QCOMPARE(object->property("stringProperty"), QVariant("Hello World!"));
QCOMPARE(object->property("colorProperty"), QVariant(QColor("red")));
QCOMPARE(object->property("dateProperty"), QVariant(QDate(1945, 9, 2)));
diff --git a/tests/auto/declarative/qmlparser/unsupportedProperty.errors.txt b/tests/auto/declarative/qmlparser/unsupportedProperty.errors.txt
index a067ecb..7ccfc75 100644
--- a/tests/auto/declarative/qmlparser/unsupportedProperty.errors.txt
+++ b/tests/auto/declarative/qmlparser/unsupportedProperty.errors.txt
@@ -1 +1 @@
-2:5:Cannot assign value to property matrix of unknown type
+2:13:Invalid property assignment: unknown type QVariant::QMatrix
diff --git a/tests/auto/declarative/qmlparser/wrongType.1.errors.txt b/tests/auto/declarative/qmlparser/wrongType.1.errors.txt
index 8976ee1..194da94 100644
--- a/tests/auto/declarative/qmlparser/wrongType.1.errors.txt
+++ b/tests/auto/declarative/qmlparser/wrongType.1.errors.txt
@@ -1 +1 @@
-2:12:Cannot assign value "hello" to property value
+2:12:Invalid property assignment: int expected
diff --git a/tests/auto/declarative/qmlparser/wrongType.10.errors.txt b/tests/auto/declarative/qmlparser/wrongType.10.errors.txt
index 562cd6c..f391e2a 100644
--- a/tests/auto/declarative/qmlparser/wrongType.10.errors.txt
+++ b/tests/auto/declarative/qmlparser/wrongType.10.errors.txt
@@ -1 +1 @@
-2:23:Cannot assign value "12" to property dateTimeProperty
+2:23:Invalid property assignment: datetime expected
diff --git a/tests/auto/declarative/qmlparser/wrongType.11.errors.txt b/tests/auto/declarative/qmlparser/wrongType.11.errors.txt
index 24d27d5..9f5ebc9 100644
--- a/tests/auto/declarative/qmlparser/wrongType.11.errors.txt
+++ b/tests/auto/declarative/qmlparser/wrongType.11.errors.txt
@@ -1 +1 @@
-2:20:Cannot assign value "apples" to property pointProperty
+2:20:Invalid property assignment: point expected
diff --git a/tests/auto/declarative/qmlparser/wrongType.12.errors.txt b/tests/auto/declarative/qmlparser/wrongType.12.errors.txt
index b57e70e..4bbb2bf 100644
--- a/tests/auto/declarative/qmlparser/wrongType.12.errors.txt
+++ b/tests/auto/declarative/qmlparser/wrongType.12.errors.txt
@@ -1 +1 @@
-2:19:Cannot assign value "red" to property sizeProperty
+2:19:Invalid property assignment: size expected
diff --git a/tests/auto/declarative/qmlparser/wrongType.13.errors.txt b/tests/auto/declarative/qmlparser/wrongType.13.errors.txt
index 7ff4bf3..194da94 100644
--- a/tests/auto/declarative/qmlparser/wrongType.13.errors.txt
+++ b/tests/auto/declarative/qmlparser/wrongType.13.errors.txt
@@ -1 +1 @@
-2:12:Cannot assign value "12" to property value
+2:12:Invalid property assignment: int expected
diff --git a/tests/auto/declarative/qmlparser/wrongType.14.errors.txt b/tests/auto/declarative/qmlparser/wrongType.14.errors.txt
index ec41e01..f90b8c6 100644
--- a/tests/auto/declarative/qmlparser/wrongType.14.errors.txt
+++ b/tests/auto/declarative/qmlparser/wrongType.14.errors.txt
@@ -1 +1 @@
-2:23:Cannot assign value 10 to property stringProperty
+2:21:Invalid property assignment: string expected
diff --git a/tests/auto/declarative/qmlparser/wrongType.2.errors.txt b/tests/auto/declarative/qmlparser/wrongType.2.errors.txt
index 301d258..4353165 100644
--- a/tests/auto/declarative/qmlparser/wrongType.2.errors.txt
+++ b/tests/auto/declarative/qmlparser/wrongType.2.errors.txt
@@ -1 +1 @@
-2:14:Cannot assign value "5" to property enabled
+2:14:Invalid property assignment: boolean expected
diff --git a/tests/auto/declarative/qmlparser/wrongType.3.errors.txt b/tests/auto/declarative/qmlparser/wrongType.3.errors.txt
index 3afcc2b..87b4eed 100644
--- a/tests/auto/declarative/qmlparser/wrongType.3.errors.txt
+++ b/tests/auto/declarative/qmlparser/wrongType.3.errors.txt
@@ -1 +1 @@
-2:11:Cannot assign value "5,5x10" to property rect
+2:11:Invalid property assignment: rect expected
diff --git a/tests/auto/declarative/qmlparser/wrongType.4.errors.txt b/tests/auto/declarative/qmlparser/wrongType.4.errors.txt
index 6bf88be..57a0744 100644
--- a/tests/auto/declarative/qmlparser/wrongType.4.errors.txt
+++ b/tests/auto/declarative/qmlparser/wrongType.4.errors.txt
@@ -1 +1 @@
-2:19:Cannot assign value "InvalidEnumName" to property enumProperty
+2:19:Invalid property assignment: unknown enumeration
diff --git a/tests/auto/declarative/qmlparser/wrongType.5.errors.txt b/tests/auto/declarative/qmlparser/wrongType.5.errors.txt
index 0e40d84..0023d1d 100644
--- a/tests/auto/declarative/qmlparser/wrongType.5.errors.txt
+++ b/tests/auto/declarative/qmlparser/wrongType.5.errors.txt
@@ -1 +1 @@
-2:19:Cannot assign value "-13" to property uintProperty
+2:19:Invalid property assignment: unsigned int expected
diff --git a/tests/auto/declarative/qmlparser/wrongType.6.errors.txt b/tests/auto/declarative/qmlparser/wrongType.6.errors.txt
index 9692997..06349e7 100644
--- a/tests/auto/declarative/qmlparser/wrongType.6.errors.txt
+++ b/tests/auto/declarative/qmlparser/wrongType.6.errors.txt
@@ -1 +1 @@
-2:19:Cannot assign value "Hello" to property realProperty
+2:19:Invalid property assignment: double expected
diff --git a/tests/auto/declarative/qmlparser/wrongType.7.errors.txt b/tests/auto/declarative/qmlparser/wrongType.7.errors.txt
index f44073a..e053f3b 100644
--- a/tests/auto/declarative/qmlparser/wrongType.7.errors.txt
+++ b/tests/auto/declarative/qmlparser/wrongType.7.errors.txt
@@ -1 +1 @@
-2:20:Cannot assign value "12" to property colorProperty
+2:20:Invalid property assignment: color expected
diff --git a/tests/auto/declarative/qmlparser/wrongType.8.errors.txt b/tests/auto/declarative/qmlparser/wrongType.8.errors.txt
index 8a45ffb..b11f92b 100644
--- a/tests/auto/declarative/qmlparser/wrongType.8.errors.txt
+++ b/tests/auto/declarative/qmlparser/wrongType.8.errors.txt
@@ -1 +1 @@
-2:19:Cannot assign value "12" to property dateProperty
+2:19:Invalid property assignment: date expected
diff --git a/tests/auto/declarative/qmlparser/wrongType.9.errors.txt b/tests/auto/declarative/qmlparser/wrongType.9.errors.txt
index cba3339..419a5ce 100644
--- a/tests/auto/declarative/qmlparser/wrongType.9.errors.txt
+++ b/tests/auto/declarative/qmlparser/wrongType.9.errors.txt
@@ -1 +1 @@
-2:19:Cannot assign value "12" to property timeProperty
+2:19:Invalid property assignment: time expected