aboutsummaryrefslogtreecommitdiffstats
path: root/src/declarative/qml/qdeclarativecompiler.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/declarative/qml/qdeclarativecompiler.cpp')
-rw-r--r--src/declarative/qml/qdeclarativecompiler.cpp1830
1 files changed, 1043 insertions, 787 deletions
diff --git a/src/declarative/qml/qdeclarativecompiler.cpp b/src/declarative/qml/qdeclarativecompiler.cpp
index 7cc8422ddd..79094b7e0e 100644
--- a/src/declarative/qml/qdeclarativecompiler.cpp
+++ b/src/declarative/qml/qdeclarativecompiler.cpp
@@ -41,11 +41,10 @@
#include "private/qdeclarativecompiler_p.h"
-#include "private/qdeclarativeparser_p.h"
-#include "private/qdeclarativescriptparser_p.h"
#include "qdeclarativepropertyvaluesource.h"
#include "qdeclarativecomponent.h"
#include "private/qmetaobjectbuilder_p.h"
+#include "private/qfastmetabuilder_p.h"
#include "private/qdeclarativestringconverters_p.h"
#include "private/qdeclarativeengine_p.h"
#include "qdeclarativeengine.h"
@@ -61,9 +60,9 @@
#include "private/qdeclarativerewrite_p.h"
#include "qdeclarativescriptstring.h"
#include "private/qdeclarativeglobal_p.h"
-#include "private/qdeclarativescriptparser_p.h"
#include "private/qdeclarativebinding_p.h"
#include "private/qdeclarativev4compiler_p.h"
+#include "private/qdeclarativeutils_p.h"
#include <QColor>
#include <QDebug>
@@ -79,14 +78,22 @@ QT_BEGIN_NAMESPACE
DEFINE_BOOL_CONFIG_OPTION(compilerDump, QML_COMPILER_DUMP);
DEFINE_BOOL_CONFIG_OPTION(compilerStatDump, QML_COMPILER_STATS);
-using namespace QDeclarativeParser;
+using namespace QDeclarativeScript;
+using namespace QDeclarativeCompilerTypes;
+
+static QString id_string(QLatin1String("id"));
+static QString on_string(QLatin1String("on"));
+static QString Changed_string(QLatin1String("Changed"));
+static QString Component_string(QLatin1String("Component"));
/*!
Instantiate a new QDeclarativeCompiler.
*/
-QDeclarativeCompiler::QDeclarativeCompiler()
-: output(0), engine(0), unitRoot(0), unit(0)
+QDeclarativeCompiler::QDeclarativeCompiler(QDeclarativePool *pool)
+: pool(pool), output(0), engine(0), unitRoot(0), unit(0), componentStats(0)
{
+ if (compilerStatDump())
+ componentStats = pool->New<ComponentStats>();
}
/*!
@@ -113,9 +120,14 @@ QList<QDeclarativeError> QDeclarativeCompiler::errors() const
Attached property names are those that start with a capital letter.
*/
-bool QDeclarativeCompiler::isAttachedPropertyName(const QByteArray &name)
+bool QDeclarativeCompiler::isAttachedPropertyName(const QString &name)
+{
+ return isAttachedPropertyName(QHashedStringRef(&name));
+}
+
+bool QDeclarativeCompiler::isAttachedPropertyName(const QHashedStringRef &name)
{
- return !name.isEmpty() && name.at(0) >= 'A' && name.at(0) <= 'Z';
+ return !name.isEmpty() && QDeclarativeUtils::isUpper(name.at(0));
}
/*!
@@ -129,15 +141,20 @@ bool QDeclarativeCompiler::isAttachedPropertyName(const QByteArray &name)
character codes in property names, for simplicity and performance reasons
QML only supports letters, numbers and underscores.
*/
-bool QDeclarativeCompiler::isSignalPropertyName(const QByteArray &name)
+bool QDeclarativeCompiler::isSignalPropertyName(const QString &name)
+{
+ return isSignalPropertyName(QStringRef(&name));
+}
+
+bool QDeclarativeCompiler::isSignalPropertyName(const QHashedStringRef &name)
{
if (name.length() < 3) return false;
- if (!name.startsWith("on")) return false;
- int ns = name.size();
+ if (!name.startsWith(on_string)) return false;
+ int ns = name.length();
for (int i = 2; i < ns; ++i) {
- char curr = name.at(i);
- if (curr == '_') continue;
- if (curr >= 'A' && curr <= 'Z') return true;
+ const QChar curr = name.at(i);
+ if (curr.unicode() == '_') continue;
+ if (QDeclarativeUtils::isUpper(curr)) return true;
return false;
}
return false; // consists solely of underscores - invalid.
@@ -155,7 +172,7 @@ bool QDeclarativeCompiler::isSignalPropertyName(const QByteArray &name)
For example:
\code
- COMPILE_EXCEPTION(property, tr("Error for property \"%1\"").arg(QString::fromUtf8(property->name)));
+ COMPILE_EXCEPTION(property, tr("Error for property \"%1\"").arg(property->name));
\endcode
*/
#define COMPILE_EXCEPTION(token, desc) \
@@ -187,27 +204,33 @@ bool QDeclarativeCompiler::isSignalPropertyName(const QByteArray &name)
This test corresponds to action taken by genLiteralAssignment(). Any change
made here, must have a corresponding action in genLiteralAssigment().
*/
-bool QDeclarativeCompiler::testLiteralAssignment(const QMetaProperty &prop,
- QDeclarativeParser::Value *v)
+bool QDeclarativeCompiler::testLiteralAssignment(QDeclarativeScript::Property *prop,
+ QDeclarativeScript::Value *v)
{
- QString string = v->value.asString();
+ const QDeclarativeScript::Variant &value = v->value;
- if (!prop.isWritable())
- COMPILE_EXCEPTION(v, tr("Invalid property assignment: \"%1\" is a read-only property").arg(QString::fromUtf8(prop.name())));
+ if (!prop->core.isWritable())
+ COMPILE_EXCEPTION(v, tr("Invalid property assignment: \"%1\" is a read-only property").arg(prop->name().toString()));
- if (prop.isEnumType()) {
- int value;
- if (prop.isFlagType()) {
- value = prop.enumerator().keysToValue(string.toUtf8().constData());
+ if (prop->core.isEnum()) {
+ QMetaProperty p = prop->parent->metaObject()->property(prop->index);
+ int enumValue;
+ if (p.isFlagType()) {
+ enumValue = p.enumerator().keysToValue(value.asString().toUtf8().constData());
} else
- value = prop.enumerator().keyToValue(string.toUtf8().constData());
- if (value == -1)
+ enumValue = p.enumerator().keyToValue(value.asString().toUtf8().constData());
+
+ if (enumValue == -1)
COMPILE_EXCEPTION(v, tr("Invalid property assignment: unknown enumeration"));
+
+ v->value = QDeclarativeScript::Variant((double)enumValue);
return true;
}
- int type = prop.userType();
+
+ int type = prop->type;
+
switch(type) {
- case -1:
+ case QMetaType::QVariant:
break;
case QVariant::String:
if (!v->value.isString()) COMPILE_EXCEPTION(v, tr("Invalid property assignment: string expected"));
@@ -249,7 +272,7 @@ bool QDeclarativeCompiler::testLiteralAssignment(const QMetaProperty &prop,
case QVariant::Color:
{
bool ok;
- QDeclarativeStringConverters::colorFromString(string, &ok);
+ QDeclarativeStringConverters::colorFromString(value.asString(), &ok);
if (!ok) COMPILE_EXCEPTION(v, tr("Invalid property assignment: color expected"));
}
break;
@@ -257,21 +280,21 @@ bool QDeclarativeCompiler::testLiteralAssignment(const QMetaProperty &prop,
case QVariant::Date:
{
bool ok;
- QDeclarativeStringConverters::dateFromString(string, &ok);
+ QDeclarativeStringConverters::dateFromString(value.asString(), &ok);
if (!ok) COMPILE_EXCEPTION(v, tr("Invalid property assignment: date expected"));
}
break;
case QVariant::Time:
{
bool ok;
- QDeclarativeStringConverters::timeFromString(string, &ok);
+ QDeclarativeStringConverters::timeFromString(value.asString(), &ok);
if (!ok) COMPILE_EXCEPTION(v, tr("Invalid property assignment: time expected"));
}
break;
case QVariant::DateTime:
{
bool ok;
- QDeclarativeStringConverters::dateTimeFromString(string, &ok);
+ QDeclarativeStringConverters::dateTimeFromString(value.asString(), &ok);
if (!ok) COMPILE_EXCEPTION(v, tr("Invalid property assignment: datetime expected"));
}
break;
@@ -280,7 +303,7 @@ bool QDeclarativeCompiler::testLiteralAssignment(const QMetaProperty &prop,
case QVariant::PointF:
{
bool ok;
- QPointF point = QDeclarativeStringConverters::pointFFromString(string, &ok);
+ QPointF point = QDeclarativeStringConverters::pointFFromString(value.asString(), &ok);
if (!ok) COMPILE_EXCEPTION(v, tr("Invalid property assignment: point expected"));
}
break;
@@ -288,7 +311,7 @@ bool QDeclarativeCompiler::testLiteralAssignment(const QMetaProperty &prop,
case QVariant::SizeF:
{
bool ok;
- QSizeF size = QDeclarativeStringConverters::sizeFFromString(string, &ok);
+ QSizeF size = QDeclarativeStringConverters::sizeFFromString(value.asString(), &ok);
if (!ok) COMPILE_EXCEPTION(v, tr("Invalid property assignment: size expected"));
}
break;
@@ -296,7 +319,7 @@ bool QDeclarativeCompiler::testLiteralAssignment(const QMetaProperty &prop,
case QVariant::RectF:
{
bool ok;
- QRectF rect = QDeclarativeStringConverters::rectFFromString(string, &ok);
+ QRectF rect = QDeclarativeStringConverters::rectFFromString(value.asString(), &ok);
if (!ok) COMPILE_EXCEPTION(v, tr("Invalid property assignment: rect expected"));
}
break;
@@ -308,24 +331,22 @@ bool QDeclarativeCompiler::testLiteralAssignment(const QMetaProperty &prop,
case QVariant::Vector3D:
{
bool ok;
- QDeclarativeStringConverters::vector3DFromString(string, &ok);
+ QDeclarativeStringConverters::vector3DFromString(value.asString(), &ok);
if (!ok) COMPILE_EXCEPTION(v, tr("Invalid property assignment: 3D vector expected"));
}
break;
case QVariant::Vector4D:
{
bool ok;
- QDeclarativeStringConverters::vector4DFromString(string, &ok);
+ QDeclarativeStringConverters::vector4DFromString(value.asString(), &ok);
if (!ok) COMPILE_EXCEPTION(v, tr("Invalid property assignment: 4D vector expected"));
}
break;
default:
{
- int t = prop.userType();
- QDeclarativeMetaType::StringConverter converter =
- QDeclarativeMetaType::customStringConverter(t);
+ QDeclarativeMetaType::StringConverter converter = QDeclarativeMetaType::customStringConverter(type);
if (!converter)
- COMPILE_EXCEPTION(v, tr("Invalid property assignment: unsupported type \"%1\"").arg(QString::fromLatin1(QVariant::typeToName(prop.type()))));
+ COMPILE_EXCEPTION(v, tr("Invalid property assignment: unsupported type \"%1\"").arg(QString::fromLatin1(QVariant::typeToName((QVariant::Type)type))));
}
break;
}
@@ -338,140 +359,132 @@ bool QDeclarativeCompiler::testLiteralAssignment(const QMetaProperty &prop,
Any literal assignment that is approved in testLiteralAssignment() must have
a corresponding action in this method.
*/
-void QDeclarativeCompiler::genLiteralAssignment(const QMetaProperty &prop,
- QDeclarativeParser::Value *v)
+void QDeclarativeCompiler::genLiteralAssignment(QDeclarativeScript::Property *prop,
+ QDeclarativeScript::Value *v)
{
QDeclarativeInstruction instr;
- if (prop.isEnumType()) {
- int value;
- if (v->value.isNumber()) {
- // Preresolved enum
- value = (int)v->value.asNumber();
- } else {
- // Must be a string
- if (prop.isFlagType()) {
- value = prop.enumerator().keysToValue(v->value.asString().toUtf8().constData());
- } else
- value = prop.enumerator().keyToValue(v->value.asString().toUtf8().constData());
- }
+
+ if (prop->core.isEnum()) {
+ Q_ASSERT(v->value.isNumber());
+ // Preresolved value
+ int value = (int)v->value.asNumber();
instr.setType(QDeclarativeInstruction::StoreInteger);
- instr.storeInteger.propertyIndex = prop.propertyIndex();
+ instr.storeInteger.propertyIndex = prop->index;
instr.storeInteger.value = value;
output->addInstruction(instr);
return;
}
- QString string = v->value.asString();
-
- int type = prop.userType();
+ int type = prop->type;
switch(type) {
- case -1:
+ case QMetaType::QVariant:
{
if (v->value.isNumber()) {
double n = v->value.asNumber();
if (double(int(n)) == n) {
instr.setType(QDeclarativeInstruction::StoreVariantInteger);
- instr.storeInteger.propertyIndex = prop.propertyIndex();
+ instr.storeInteger.propertyIndex = prop->index;
instr.storeInteger.value = int(n);
} else {
instr.setType(QDeclarativeInstruction::StoreVariantDouble);
- instr.storeDouble.propertyIndex = prop.propertyIndex();
+ instr.storeDouble.propertyIndex = prop->index;
instr.storeDouble.value = n;
}
} else if(v->value.isBoolean()) {
instr.setType(QDeclarativeInstruction::StoreVariantBool);
- instr.storeBool.propertyIndex = prop.propertyIndex();
+ instr.storeBool.propertyIndex = prop->index;
instr.storeBool.value = v->value.asBoolean();
} else {
instr.setType(QDeclarativeInstruction::StoreVariant);
- instr.storeString.propertyIndex = prop.propertyIndex();
- instr.storeString.value = output->indexForString(string);
+ instr.storeString.propertyIndex = prop->index;
+ instr.storeString.value = output->indexForString(v->value.asString());
}
}
break;
case QVariant::String:
{
instr.setType(QDeclarativeInstruction::StoreString);
- instr.storeString.propertyIndex = prop.propertyIndex();
- instr.storeString.value = output->indexForString(string);
+ instr.storeString.propertyIndex = prop->index;
+ instr.storeString.value = output->indexForString(v->value.asString());
}
break;
case QVariant::ByteArray:
{
instr.setType(QDeclarativeInstruction::StoreByteArray);
- instr.storeByteArray.propertyIndex = prop.propertyIndex();
- instr.storeByteArray.value = output->indexForByteArray(string.toLatin1());
+ instr.storeByteArray.propertyIndex = prop->index;
+ instr.storeByteArray.value = output->indexForByteArray(v->value.asString().toLatin1());
}
break;
case QVariant::Url:
{
instr.setType(QDeclarativeInstruction::StoreUrl);
+ QString string = v->value.asString();
QUrl u = string.isEmpty() ? QUrl() : output->url.resolved(QUrl(string));
- instr.storeUrl.propertyIndex = prop.propertyIndex();
+ instr.storeUrl.propertyIndex = prop->index;
instr.storeUrl.value = output->indexForUrl(u);
}
break;
case QVariant::UInt:
{
instr.setType(QDeclarativeInstruction::StoreInteger);
- instr.storeInteger.propertyIndex = prop.propertyIndex();
+ instr.storeInteger.propertyIndex = prop->index;
instr.storeInteger.value = uint(v->value.asNumber());
}
break;
case QVariant::Int:
{
instr.setType(QDeclarativeInstruction::StoreInteger);
- instr.storeInteger.propertyIndex = prop.propertyIndex();
+ instr.storeInteger.propertyIndex = prop->index;
instr.storeInteger.value = int(v->value.asNumber());
}
break;
case QMetaType::Float:
{
instr.setType(QDeclarativeInstruction::StoreFloat);
- instr.storeFloat.propertyIndex = prop.propertyIndex();
+ instr.storeFloat.propertyIndex = prop->index;
instr.storeFloat.value = float(v->value.asNumber());
}
break;
case QVariant::Double:
{
instr.setType(QDeclarativeInstruction::StoreDouble);
- instr.storeDouble.propertyIndex = prop.propertyIndex();
+ instr.storeDouble.propertyIndex = prop->index;
instr.storeDouble.value = v->value.asNumber();
}
break;
case QVariant::Color:
{
- QColor c = QDeclarativeStringConverters::colorFromString(string);
+ QColor c = QDeclarativeStringConverters::colorFromString(v->value.asString());
instr.setType(QDeclarativeInstruction::StoreColor);
- instr.storeColor.propertyIndex = prop.propertyIndex();
+ instr.storeColor.propertyIndex = prop->index;
instr.storeColor.value = c.rgba();
}
break;
#ifndef QT_NO_DATESTRING
case QVariant::Date:
{
- QDate d = QDeclarativeStringConverters::dateFromString(string);
+ QDate d = QDeclarativeStringConverters::dateFromString(v->value.asString());
instr.setType(QDeclarativeInstruction::StoreDate);
- instr.storeDate.propertyIndex = prop.propertyIndex();
+ instr.storeDate.propertyIndex = prop->index;
instr.storeDate.value = d.toJulianDay();
}
break;
case QVariant::Time:
{
- QTime time = QDeclarativeStringConverters::timeFromString(string);
+ QTime time = QDeclarativeStringConverters::timeFromString(v->value.asString());
instr.setType(QDeclarativeInstruction::StoreTime);
- instr.storeTime.propertyIndex = prop.propertyIndex();
+ instr.storeTime.propertyIndex = prop->index;
Q_ASSERT(sizeof(instr.storeTime.time) == sizeof(QTime));
::memcpy(&instr.storeTime.time, &time, sizeof(QTime));
}
break;
case QVariant::DateTime:
{
- QDateTime dateTime = QDeclarativeStringConverters::dateTimeFromString(string);
+ QDateTime dateTime = QDeclarativeStringConverters::dateTimeFromString(v->value.asString());
QTime time = dateTime.time();
instr.setType(QDeclarativeInstruction::StoreDateTime);
- instr.storeDateTime.propertyIndex = prop.propertyIndex();
+ instr.storeDateTime.propertyIndex = prop->index;
instr.storeDateTime.date = dateTime.date().toJulianDay();
Q_ASSERT(sizeof(instr.storeDateTime.time) == sizeof(QTime));
::memcpy(&instr.storeDateTime.time, &time, sizeof(QTime));
@@ -481,9 +494,9 @@ void QDeclarativeCompiler::genLiteralAssignment(const QMetaProperty &prop,
case QVariant::Point:
{
bool ok;
- QPoint point = QDeclarativeStringConverters::pointFFromString(string, &ok).toPoint();
+ QPoint point = QDeclarativeStringConverters::pointFFromString(v->value.asString(), &ok).toPoint();
instr.setType(QDeclarativeInstruction::StorePoint);
- instr.storePoint.propertyIndex = prop.propertyIndex();
+ instr.storePoint.propertyIndex = prop->index;
instr.storePoint.point.xp = point.x();
instr.storePoint.point.yp = point.y();
}
@@ -491,9 +504,9 @@ void QDeclarativeCompiler::genLiteralAssignment(const QMetaProperty &prop,
case QVariant::PointF:
{
bool ok;
- QPointF point = QDeclarativeStringConverters::pointFFromString(string, &ok);
+ QPointF point = QDeclarativeStringConverters::pointFFromString(v->value.asString(), &ok);
instr.setType(QDeclarativeInstruction::StorePointF);
- instr.storePointF.propertyIndex = prop.propertyIndex();
+ instr.storePointF.propertyIndex = prop->index;
instr.storePointF.point.xp = point.x();
instr.storePointF.point.yp = point.y();
}
@@ -501,9 +514,9 @@ void QDeclarativeCompiler::genLiteralAssignment(const QMetaProperty &prop,
case QVariant::Size:
{
bool ok;
- QSize size = QDeclarativeStringConverters::sizeFFromString(string, &ok).toSize();
+ QSize size = QDeclarativeStringConverters::sizeFFromString(v->value.asString(), &ok).toSize();
instr.setType(QDeclarativeInstruction::StoreSize);
- instr.storeSize.propertyIndex = prop.propertyIndex();
+ instr.storeSize.propertyIndex = prop->index;
instr.storeSize.size.wd = size.width();
instr.storeSize.size.ht = size.height();
}
@@ -511,9 +524,9 @@ void QDeclarativeCompiler::genLiteralAssignment(const QMetaProperty &prop,
case QVariant::SizeF:
{
bool ok;
- QSizeF size = QDeclarativeStringConverters::sizeFFromString(string, &ok);
+ QSizeF size = QDeclarativeStringConverters::sizeFFromString(v->value.asString(), &ok);
instr.setType(QDeclarativeInstruction::StoreSizeF);
- instr.storeSizeF.propertyIndex = prop.propertyIndex();
+ instr.storeSizeF.propertyIndex = prop->index;
instr.storeSizeF.size.wd = size.width();
instr.storeSizeF.size.ht = size.height();
}
@@ -521,9 +534,9 @@ void QDeclarativeCompiler::genLiteralAssignment(const QMetaProperty &prop,
case QVariant::Rect:
{
bool ok;
- QRect rect = QDeclarativeStringConverters::rectFFromString(string, &ok).toRect();
+ QRect rect = QDeclarativeStringConverters::rectFFromString(v->value.asString(), &ok).toRect();
instr.setType(QDeclarativeInstruction::StoreRect);
- instr.storeRect.propertyIndex = prop.propertyIndex();
+ instr.storeRect.propertyIndex = prop->index;
instr.storeRect.rect.x1 = rect.left();
instr.storeRect.rect.y1 = rect.top();
instr.storeRect.rect.x2 = rect.right();
@@ -533,9 +546,9 @@ void QDeclarativeCompiler::genLiteralAssignment(const QMetaProperty &prop,
case QVariant::RectF:
{
bool ok;
- QRectF rect = QDeclarativeStringConverters::rectFFromString(string, &ok);
+ QRectF rect = QDeclarativeStringConverters::rectFFromString(v->value.asString(), &ok);
instr.setType(QDeclarativeInstruction::StoreRectF);
- instr.storeRectF.propertyIndex = prop.propertyIndex();
+ instr.storeRectF.propertyIndex = prop->index;
instr.storeRectF.rect.xp = rect.left();
instr.storeRectF.rect.yp = rect.top();
instr.storeRectF.rect.w = rect.width();
@@ -546,16 +559,16 @@ void QDeclarativeCompiler::genLiteralAssignment(const QMetaProperty &prop,
{
bool b = v->value.asBoolean();
instr.setType(QDeclarativeInstruction::StoreBool);
- instr.storeBool.propertyIndex = prop.propertyIndex();
+ instr.storeBool.propertyIndex = prop->index;
instr.storeBool.value = b;
}
break;
case QVariant::Vector3D:
{
bool ok;
- QVector3D vector = QDeclarativeStringConverters::vector3DFromString(string, &ok);
+ QVector3D vector = QDeclarativeStringConverters::vector3DFromString(v->value.asString(), &ok);
instr.setType(QDeclarativeInstruction::StoreVector3D);
- instr.storeVector3D.propertyIndex = prop.propertyIndex();
+ instr.storeVector3D.propertyIndex = prop->index;
instr.storeVector3D.vector.xp = vector.x();
instr.storeVector3D.vector.yp = vector.y();
instr.storeVector3D.vector.zp = vector.z();
@@ -564,9 +577,9 @@ void QDeclarativeCompiler::genLiteralAssignment(const QMetaProperty &prop,
case QVariant::Vector4D:
{
bool ok;
- QVector4D vector = QDeclarativeStringConverters::vector4DFromString(string, &ok);
+ QVector4D vector = QDeclarativeStringConverters::vector4DFromString(v->value.asString(), &ok);
instr.setType(QDeclarativeInstruction::StoreVector4D);
- instr.storeVector4D.propertyIndex = prop.propertyIndex();
+ instr.storeVector4D.propertyIndex = prop->index;
instr.storeVector4D.vector.xp = vector.x();
instr.storeVector4D.vector.yp = vector.y();
instr.storeVector4D.vector.zp = vector.z();
@@ -575,11 +588,10 @@ void QDeclarativeCompiler::genLiteralAssignment(const QMetaProperty &prop,
break;
default:
{
- int t = prop.userType();
instr.setType(QDeclarativeInstruction::AssignCustomType);
- instr.assignCustomType.propertyIndex = prop.propertyIndex();
- instr.assignCustomType.primitive = output->indexForString(string);
- instr.assignCustomType.type = t;
+ instr.assignCustomType.propertyIndex = prop->index;
+ instr.assignCustomType.primitive = output->indexForString(v->value.asString());
+ instr.assignCustomType.type = type;
}
break;
}
@@ -594,7 +606,7 @@ void QDeclarativeCompiler::reset(QDeclarativeCompiledData *data)
data->types.clear();
data->primitives.clear();
data->datas.clear();
- data->bytecode.clear();
+ data->bytecode.resize(0);
}
/*!
@@ -621,13 +633,13 @@ bool QDeclarativeCompiler::compile(QDeclarativeEngine *engine,
// Compile types
const QList<QDeclarativeTypeData::TypeReference> &resolvedTypes = unit->resolvedTypes();
- QList<QDeclarativeScriptParser::TypeReference *> referencedTypes = unit->parser().referencedTypes();
+ QList<QDeclarativeScript::TypeReference *> referencedTypes = unit->parser().referencedTypes();
for (int ii = 0; ii < resolvedTypes.count(); ++ii) {
QDeclarativeCompiledData::TypeReference ref;
const QDeclarativeTypeData::TypeReference &tref = resolvedTypes.at(ii);
- QDeclarativeScriptParser::TypeReference *parserRef = referencedTypes.at(ii);
+ QDeclarativeScript::TypeReference *parserRef = referencedTypes.at(ii);
if (tref.type) {
ref.type = tref.type;
@@ -652,11 +664,11 @@ bool QDeclarativeCompiler::compile(QDeclarativeEngine *engine,
} else if (tref.typeData) {
ref.component = tref.typeData->compiledData();
}
- ref.className = parserRef->name.toUtf8();
+ ref.className = parserRef->name;
out->types << ref;
}
- QDeclarativeParser::Object *root = unit->parser().tree();
+ QDeclarativeScript::Object *root = unit->parser().tree();
Q_ASSERT(root);
this->engine = engine;
@@ -668,15 +680,14 @@ bool QDeclarativeCompiler::compile(QDeclarativeEngine *engine,
if (!isError()) {
if (compilerDump())
out->dumpInstructions();
- if (compilerStatDump())
+ if (componentStats)
dumpStats();
Q_ASSERT(out->rootPropertyCache);
} else {
reset(out);
}
- compileState = ComponentCompileState();
- savedCompileStates.clear();
+ compileState = 0;
output = 0;
this->engine = 0;
this->enginePrivate = 0;
@@ -686,10 +697,13 @@ bool QDeclarativeCompiler::compile(QDeclarativeEngine *engine,
return !isError();
}
-void QDeclarativeCompiler::compileTree(QDeclarativeParser::Object *tree)
+void QDeclarativeCompiler::compileTree(QDeclarativeScript::Object *tree)
{
- compileState.root = tree;
- componentStat.lineNumber = tree->location.start.line;
+ compileState = pool->New<ComponentCompileState>();
+
+ compileState->root = tree;
+ if (componentStats)
+ componentStats->componentStat.lineNumber = tree->location.start.line;
// Build global import scripts
QStringList importedScriptIndexes;
@@ -720,21 +734,21 @@ void QDeclarativeCompiler::compileTree(QDeclarativeParser::Object *tree)
QDeclarativeInstruction init;
init.setType(QDeclarativeInstruction::Init);
- init.init.bindingsSize = compileState.bindings.count();
- init.init.parserStatusSize = compileState.parserStatusCount;
+ init.init.bindingsSize = compileState->bindings.count();
+ init.init.parserStatusSize = compileState->parserStatusCount;
init.init.contextCache = genContextCache();
- if (compileState.compiledBindingData.isEmpty())
+ if (compileState->compiledBindingData.isEmpty())
init.init.compiledBinding = -1;
else
- init.init.compiledBinding = output->indexForByteArray(compileState.compiledBindingData);
+ init.init.compiledBinding = output->indexForByteArray(compileState->compiledBindingData);
output->addInstruction(init);
- if (!compileState.v8BindingProgram.isEmpty()) {
+ if (!compileState->v8BindingProgram.isEmpty()) {
QDeclarativeInstruction bindings;
bindings.setType(QDeclarativeInstruction::InitV8Bindings);
- bindings.initV8Bindings.program = output->indexForString(compileState.v8BindingProgram);
- bindings.initV8Bindings.programIndex = compileState.v8BindingProgramIndex;
- bindings.initV8Bindings.line = compileState.v8BindingProgramLine;
+ bindings.initV8Bindings.program = output->indexForString(compileState->v8BindingProgram);
+ bindings.initV8Bindings.programIndex = compileState->v8BindingProgramIndex;
+ bindings.initV8Bindings.line = compileState->v8BindingProgramLine;
output->addInstruction(bindings);
}
@@ -760,25 +774,27 @@ void QDeclarativeCompiler::compileTree(QDeclarativeParser::Object *tree)
enginePrivate->registerCompositeType(output);
}
-static bool ValuePtrLessThan(const QDeclarativeParser::Value *t1, const QDeclarativeParser::Value *t2)
+static bool QStringList_contains(const QStringList &list, const QHashedStringRef &string)
{
- return t1->location.start.line < t2->location.start.line ||
- (t1->location.start.line == t2->location.start.line &&
- t1->location.start.column < t2->location.start.column);
+ for (int ii = 0; ii < list.count(); ++ii)
+ if (string == list.at(ii))
+ return true;
+
+ return false;
}
-bool QDeclarativeCompiler::buildObject(QDeclarativeParser::Object *obj, const BindingContext &ctxt)
+bool QDeclarativeCompiler::buildObject(QDeclarativeScript::Object *obj, const BindingContext &ctxt)
{
- componentStat.objects++;
+ if (componentStats)
+ componentStats->componentStat.objects++;
Q_ASSERT (obj->type != -1);
const QDeclarativeCompiledData::TypeReference &tr =
output->types.at(obj->type);
obj->metatype = tr.metaObject();
- if (tr.type)
+ if (tr.type)
obj->typeName = tr.type->qmlTypeName();
- obj->className = tr.className;
// This object is a "Component" element
if (tr.type && obj->metatype == &QDeclarativeComponent::staticMetaObject) {
@@ -799,7 +815,7 @@ bool QDeclarativeCompiler::buildObject(QDeclarativeParser::Object *obj, const Bi
Q_ASSERT(type);
obj->parserStatusCast = type->parserStatusCast();
if (obj->parserStatusCast != -1)
- compileState.parserStatusCount++;
+ compileState->parserStatusCount++;
// Check if this is a custom parser type. Custom parser types allow
// assignments to non-existent properties. These assignments are then
@@ -814,8 +830,8 @@ bool QDeclarativeCompiler::buildObject(QDeclarativeParser::Object *obj, const Bi
// 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") {
+ for (Property *prop = obj->properties.first(); prop; prop = obj->properties.next(prop)) {
+ if (prop->name() == id_string) {
COMPILE_CHECK(buildProperty(prop, obj, objCtxt));
break;
}
@@ -825,34 +841,75 @@ bool QDeclarativeCompiler::buildObject(QDeclarativeParser::Object *obj, const Bi
Property *defaultProperty = 0;
Property *skipProperty = 0;
if (obj->defaultProperty) {
- const QMetaObject *metaObject = obj->metaObject();
- Q_ASSERT(metaObject);
- QMetaProperty p = QDeclarativeMetaType::defaultProperty(metaObject);
- if (p.name()) {
- Property *explicitProperty = obj->getProperty(p.name(), false);
- if (explicitProperty && !explicitProperty->value) {
- skipProperty = explicitProperty;
-
- defaultProperty = new Property;
- defaultProperty->parent = obj;
- defaultProperty->isDefault = true;
- defaultProperty->location = obj->defaultProperty->location;
- defaultProperty->listValueRange = obj->defaultProperty->listValueRange;
-
- defaultProperty->values = obj->defaultProperty->values;
- defaultProperty->values += explicitProperty->values;
- foreach(QDeclarativeParser::Value *value, defaultProperty->values)
- value->addref();
- qSort(defaultProperty->values.begin(), defaultProperty->values.end(), ValuePtrLessThan);
+ defaultProperty = obj->defaultProperty;
+
+ Property *explicitProperty = 0;
+
+ const QMetaObject *mo = obj->metatype;
+ int idx = mo->indexOfClassInfo("DefaultProperty");
+ if (idx != -1) {
+ QMetaClassInfo info = mo->classInfo(idx);
+ const char *p = info.value();
+ if (p) {
+ int plen = 0;
+ char ord = 0;
+ while (char c = p[plen++]) { ord |= c; };
+ --plen;
+
+ if (ord & 0x80) {
+ // Utf8 - unoptimal, but seldom hit
+ QString *s = pool->NewString(QString::fromUtf8(p, plen));
+ QHashedStringRef r(*s);
+
+ if (obj->propertiesHashField.test(r.hash())) {
+ for (Property *ep = obj->properties.first(); ep; ep = obj->properties.next(ep)) {
+ if (ep->name() == r) {
+ explicitProperty = ep;
+ break;
+ }
+ }
+ }
+
+ if (!explicitProperty)
+ defaultProperty->setName(r);
- } else {
- defaultProperty = obj->defaultProperty;
- defaultProperty->addref();
+ } else {
+ QHashedCStringRef r(p, plen);
+
+ if (obj->propertiesHashField.test(r.hash())) {
+ for (Property *ep = obj->properties.first(); ep; ep = obj->properties.next(ep)) {
+ if (ep->name() == r) {
+ explicitProperty = ep;
+ break;
+ }
+ }
+ }
+
+ if (!explicitProperty) {
+ // Set the default property name
+ QChar *buffer = pool->NewRawArray<QChar>(r.length());
+ r.writeUtf16(buffer);
+ defaultProperty->setName(QHashedStringRef(buffer, r.length(), r.hash()));
+ }
+ }
}
- } else {
- defaultProperty = obj->defaultProperty;
- defaultProperty->addref();
}
+
+ if (explicitProperty && !explicitProperty->value && !explicitProperty->values.isEmpty()) {
+
+ skipProperty = explicitProperty; // We merge the values into defaultProperty
+
+ // Find the correct insertion point
+ Value *insertPos = 0;
+
+ for (Value *v = defaultProperty->values.first(); v; v = Property::ValueList::next(v)) {
+ if (!(v->location.start < explicitProperty->values.first()->location.start))
+ break;
+ insertPos = v;
+ }
+
+ defaultProperty->values.insertAfter(insertPos, explicitProperty->values);
+ }
}
QDeclarativeCustomParser *cp = 0;
@@ -860,39 +917,38 @@ bool QDeclarativeCompiler::buildObject(QDeclarativeParser::Object *obj, const Bi
cp = output->types.at(obj->type).type->customParser();
// Build all explicit properties specified
- foreach(Property *prop, obj->properties) {
+ for (Property *prop = obj->properties.first(); prop; prop = obj->properties.next(prop)) {
if (prop == skipProperty)
continue;
- if (prop->name == "id")
+ if (prop->name() == id_string)
continue;
bool canDefer = false;
if (isCustomParser) {
- if (doesPropertyExist(prop, obj) &&
+ if (doesPropertyExist(prop, obj) &&
(!(cp->flags() & QDeclarativeCustomParser::AcceptsAttachedProperties) ||
- !isAttachedPropertyName(prop->name))) {
- int ids = compileState.ids.count();
+ !isAttachedPropertyName(prop->name()))) {
+ int ids = compileState->ids.count();
COMPILE_CHECK(buildProperty(prop, obj, objCtxt));
- canDefer = ids == compileState.ids.count();
- } else if (isSignalPropertyName(prop->name) &&
+ canDefer = ids == compileState->ids.count();
+ } else if (isSignalPropertyName(prop->name()) &&
(cp->flags() & QDeclarativeCustomParser::AcceptsSignalHandlers)) {
COMPILE_CHECK(buildSignal(prop,obj,objCtxt));
} else {
customProps << QDeclarativeCustomParserNodePrivate::fromProperty(prop);
}
} else {
- if (isSignalPropertyName(prop->name)) {
+ if (isSignalPropertyName(prop->name())) {
COMPILE_CHECK(buildSignal(prop,obj,objCtxt));
} else {
- int ids = compileState.ids.count();
+ int ids = compileState->ids.count();
COMPILE_CHECK(buildProperty(prop, obj, objCtxt));
- canDefer = ids == compileState.ids.count();
+ canDefer = ids == compileState->ids.count();
}
}
- if (canDefer && !deferredList.isEmpty() &&
- deferredList.contains(QString::fromUtf8(prop->name)))
+ if (canDefer && !deferredList.isEmpty() && QStringList_contains(deferredList, prop->name()))
prop->isDeferred = true;
}
@@ -904,26 +960,22 @@ bool QDeclarativeCompiler::buildObject(QDeclarativeParser::Object *obj, const Bi
bool canDefer = false;
if (isCustomParser) {
if (doesPropertyExist(prop, obj)) {
- int ids = compileState.ids.count();
+ int ids = compileState->ids.count();
COMPILE_CHECK(buildProperty(prop, obj, objCtxt));
- canDefer = ids == compileState.ids.count();
+ canDefer = ids == compileState->ids.count();
} else {
customProps << QDeclarativeCustomParserNodePrivate::fromProperty(prop);
}
} else {
- int ids = compileState.ids.count();
+ int ids = compileState->ids.count();
COMPILE_CHECK(buildProperty(prop, obj, objCtxt));
- canDefer = ids == compileState.ids.count();
+ canDefer = ids == compileState->ids.count();
}
- if (canDefer && !deferredList.isEmpty() &&
- deferredList.contains(QString::fromUtf8(prop->name)))
+ if (canDefer && !deferredList.isEmpty() && QStringList_contains(deferredList, prop->name()))
prop->isDeferred = true;
}
- if (defaultProperty)
- defaultProperty->release();
-
// Compile custom parser parts
if (isCustomParser && !customProps.isEmpty()) {
cp->clearErrors();
@@ -941,7 +993,7 @@ bool QDeclarativeCompiler::buildObject(QDeclarativeParser::Object *obj, const Bi
return true;
}
-void QDeclarativeCompiler::genObject(QDeclarativeParser::Object *obj)
+void QDeclarativeCompiler::genObject(QDeclarativeScript::Object *obj)
{
QDeclarativeCompiledData::TypeReference &tr = output->types[obj->type];
if (tr.type && obj->metatype == &QDeclarativeComponent::staticMetaObject) {
@@ -951,7 +1003,7 @@ void QDeclarativeCompiler::genObject(QDeclarativeParser::Object *obj)
// Create the object
if (obj->custom.isEmpty() && output->types.at(obj->type).type &&
- !output->types.at(obj->type).type->isExtendedType() && obj != compileState.root) {
+ !output->types.at(obj->type).type->isExtendedType() && obj != compileState->root) {
QDeclarativeInstruction create;
create.setType(QDeclarativeInstruction::CreateSimpleObject);
@@ -1039,23 +1091,24 @@ void QDeclarativeCompiler::genObject(QDeclarativeParser::Object *obj)
genObjectBody(obj);
}
-void QDeclarativeCompiler::genObjectBody(QDeclarativeParser::Object *obj)
+void QDeclarativeCompiler::genObjectBody(QDeclarativeScript::Object *obj)
{
- typedef QPair<Property *, int> PropPair;
- foreach(const PropPair &prop, obj->scriptStringProperties) {
- const QString &script = prop.first->values.at(0)->value.asScript();
+ for (Property *prop = obj->scriptStringProperties.first(); prop; prop = Object::PropertyList::next(prop)) {
+ Q_ASSERT(prop->scriptStringScope != -1);
+ const QString &script = prop->values.first()->value.asScript();
QDeclarativeInstruction ss;
ss.setType(QDeclarativeInstruction::StoreScriptString);
- ss.storeScriptString.propertyIndex = prop.first->index;
+ ss.storeScriptString.propertyIndex = prop->index;
ss.storeScriptString.value = output->indexForString(script);
- ss.storeScriptString.scope = prop.second;
- ss.storeScriptString.bindingId = rewriteBinding(script, prop.first->name);
- ss.storeScriptString.line = prop.first->location.start.line;
+ ss.storeScriptString.scope = prop->scriptStringScope;
+// ss.storeScriptString.bindingId = rewriteBinding(script, prop->name());
+ ss.storeScriptString.bindingId = rewriteBinding(script, QString()); // XXX
+ ss.storeScriptString.line = prop->location.start.line;
output->addInstruction(ss);
}
bool seenDefer = false;
- foreach(Property *prop, obj->valueProperties) {
+ for (Property *prop = obj->valueProperties.first(); prop; prop = Object::PropertyList::next(prop)) {
if (prop->isDeferred) {
seenDefer = true;
continue;
@@ -1072,13 +1125,13 @@ void QDeclarativeCompiler::genObjectBody(QDeclarativeParser::Object *obj)
QDeclarativeInstruction init;
init.setType(QDeclarativeInstruction::Init);
- init.init.bindingsSize = compileState.bindings.count(); // XXX - bigger than necessary
- init.init.parserStatusSize = compileState.parserStatusCount; // XXX - bigger than necessary
+ init.init.bindingsSize = compileState->bindings.count(); // XXX - bigger than necessary
+ init.init.parserStatusSize = compileState->parserStatusCount; // XXX - bigger than necessary
init.init.contextCache = -1;
init.init.compiledBinding = -1;
output->addInstruction(init);
- foreach(Property *prop, obj->valueProperties) {
+ for (Property *prop = obj->valueProperties.first(); prop; prop = Object::PropertyList::next(prop)) {
if (!prop->isDeferred)
continue;
genValueProperty(prop, obj);
@@ -1091,9 +1144,9 @@ void QDeclarativeCompiler::genObjectBody(QDeclarativeParser::Object *obj)
output->instruction(deferIdx)->defer.deferCount = output->nextInstructionIndex() - nextInstructionIndex;
}
- foreach(Property *prop, obj->signalProperties) {
+ for (Property *prop = obj->signalProperties.first(); prop; prop = Object::PropertyList::next(prop)) {
- QDeclarativeParser::Value *v = prop->values.at(0);
+ QDeclarativeScript::Value *v = prop->values.first();
if (v->type == Value::SignalObject) {
@@ -1102,21 +1155,18 @@ void QDeclarativeCompiler::genObjectBody(QDeclarativeParser::Object *obj)
QDeclarativeInstruction assign;
assign.setType(QDeclarativeInstruction::AssignSignalObject);
assign.assignSignalObject.line = v->location.start.line;
- assign.assignSignalObject.signal =
- output->indexForByteArray(prop->name);
+ assign.assignSignalObject.signal = output->indexForString(prop->name().toString());
output->addInstruction(assign);
} else if (v->type == Value::SignalExpression) {
- BindingContext ctxt = compileState.signalExpressions.value(v);
-
QDeclarativeInstruction store;
store.setType(QDeclarativeInstruction::StoreSignal);
store.storeSignal.signalIndex = prop->index;
store.storeSignal.value =
output->indexForString(v->value.asScript().trimmed());
- store.storeSignal.context = ctxt.stack;
- store.storeSignal.name = output->indexForByteArray(prop->name);
+ store.storeSignal.context = v->signalExpressionContextStack;
+ store.storeSignal.name = output->indexForByteArray(prop->name().toUtf8());
store.storeSignal.line = v->location.start.line;
output->addInstruction(store);
@@ -1124,7 +1174,7 @@ void QDeclarativeCompiler::genObjectBody(QDeclarativeParser::Object *obj)
}
- foreach(Property *prop, obj->attachedProperties) {
+ for (Property *prop = obj->attachedProperties.first(); prop; prop = Object::PropertyList::next(prop)) {
QDeclarativeInstruction fetch;
fetch.setType(QDeclarativeInstruction::FetchAttached);
fetch.fetchAttached.id = prop->index;
@@ -1138,7 +1188,7 @@ void QDeclarativeCompiler::genObjectBody(QDeclarativeParser::Object *obj)
output->addInstruction(pop);
}
- foreach(Property *prop, obj->groupedProperties) {
+ for (Property *prop = obj->groupedProperties.first(); prop; prop = Object::PropertyList::next(prop)) {
QDeclarativeInstruction fetch;
fetch.setType(QDeclarativeInstruction::FetchObject);
fetch.fetch.property = prop->index;
@@ -1161,25 +1211,25 @@ void QDeclarativeCompiler::genObjectBody(QDeclarativeParser::Object *obj)
output->addInstruction(pop);
}
- foreach(Property *prop, obj->valueTypeProperties) {
+ for (Property *prop = obj->valueTypeProperties.first(); prop; prop = Object::PropertyList::next(prop)) {
if (!prop->isAlias)
genValueTypeProperty(obj, prop);
}
- foreach(Property *prop, obj->valueProperties) {
+ for (Property *prop = obj->valueProperties.first(); prop; prop = Object::PropertyList::next(prop)) {
if (prop->isDeferred)
continue;
if (prop->isAlias)
genValueProperty(prop, obj);
}
- foreach(Property *prop, obj->valueTypeProperties) {
+ for (Property *prop = obj->valueTypeProperties.first(); prop; prop = Object::PropertyList::next(prop)) {
if (prop->isAlias)
genValueTypeProperty(obj, prop);
}
}
-void QDeclarativeCompiler::genValueTypeProperty(QDeclarativeParser::Object *obj,QDeclarativeParser::Property *prop)
+void QDeclarativeCompiler::genValueTypeProperty(QDeclarativeScript::Object *obj,QDeclarativeScript::Property *prop)
{
QDeclarativeInstruction fetch;
fetch.setType(QDeclarativeInstruction::FetchValueType);
@@ -1190,7 +1240,7 @@ void QDeclarativeCompiler::genValueTypeProperty(QDeclarativeParser::Object *obj,
if (obj->type == -1 || output->types.at(obj->type).component) {
// We only have to do this if this is a composite type. If it is a builtin
// type it can't possibly already have bindings that need to be cleared.
- foreach(Property *vprop, prop->value->valueProperties) {
+ for (Property *vprop = prop->value->valueProperties.first(); vprop; vprop = Object::PropertyList::next(vprop)) {
if (!vprop->values.isEmpty()) {
Q_ASSERT(vprop->index >= 0 && vprop->index < 32);
fetch.fetchValue.bindingSkipList |= (1 << vprop->index);
@@ -1200,7 +1250,7 @@ void QDeclarativeCompiler::genValueTypeProperty(QDeclarativeParser::Object *obj,
output->addInstruction(fetch);
- foreach(Property *vprop, prop->value->valueProperties) {
+ for (Property *vprop = prop->value->valueProperties.first(); vprop; vprop = Object::PropertyList::next(vprop)) {
genPropertyAssignment(vprop, prop->value, prop);
}
@@ -1212,9 +1262,9 @@ void QDeclarativeCompiler::genValueTypeProperty(QDeclarativeParser::Object *obj,
output->addInstruction(pop);
}
-void QDeclarativeCompiler::genComponent(QDeclarativeParser::Object *obj)
+void QDeclarativeCompiler::genComponent(QDeclarativeScript::Object *obj)
{
- QDeclarativeParser::Object *root = obj->defaultProperty->values.at(0)->object;
+ QDeclarativeScript::Object *root = obj->defaultProperty->values.first()->object;
Q_ASSERT(root);
QDeclarativeInstruction create;
@@ -1225,26 +1275,26 @@ void QDeclarativeCompiler::genComponent(QDeclarativeParser::Object *obj)
int createInstruction = output->addInstruction(create);
int nextInstructionIndex = output->nextInstructionIndex();
- ComponentCompileState oldCompileState = compileState;
+ ComponentCompileState *oldCompileState = compileState;
compileState = componentState(root);
QDeclarativeInstruction init;
init.setType(QDeclarativeInstruction::Init);
- init.init.bindingsSize = compileState.bindings.count();
- init.init.parserStatusSize = compileState.parserStatusCount;
+ init.init.bindingsSize = compileState->bindings.count();
+ init.init.parserStatusSize = compileState->parserStatusCount;
init.init.contextCache = genContextCache();
- if (compileState.compiledBindingData.isEmpty())
+ if (compileState->compiledBindingData.isEmpty())
init.init.compiledBinding = -1;
else
- init.init.compiledBinding = output->indexForByteArray(compileState.compiledBindingData);
+ init.init.compiledBinding = output->indexForByteArray(compileState->compiledBindingData);
output->addInstruction(init);
- if (!compileState.v8BindingProgram.isEmpty()) {
+ if (!compileState->v8BindingProgram.isEmpty()) {
QDeclarativeInstruction bindings;
bindings.setType(QDeclarativeInstruction::InitV8Bindings);
- bindings.initV8Bindings.program = output->indexForString(compileState.v8BindingProgram);
- bindings.initV8Bindings.programIndex = compileState.v8BindingProgramIndex;
- bindings.initV8Bindings.line = compileState.v8BindingProgramLine;
+ bindings.initV8Bindings.program = output->indexForString(compileState->v8BindingProgram);
+ bindings.initV8Bindings.programIndex = compileState->v8BindingProgramIndex;
+ bindings.initV8Bindings.line = compileState->v8BindingProgramLine;
output->addInstruction(bindings);
}
@@ -1277,7 +1327,7 @@ void QDeclarativeCompiler::genComponent(QDeclarativeParser::Object *obj)
}
}
-bool QDeclarativeCompiler::buildComponent(QDeclarativeParser::Object *obj,
+bool QDeclarativeCompiler::buildComponent(QDeclarativeScript::Object *obj,
const BindingContext &ctxt)
{
// The special "Component" element can only have the id property and a
@@ -1285,21 +1335,21 @@ bool QDeclarativeCompiler::buildComponent(QDeclarativeParser::Object *obj,
// 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(*obj->properties.begin(), tr("Component elements may not contain properties other than id"));
+ if (obj->properties.isMany() ||
+ (obj->properties.isOne() && obj->properties.first()->name() != id_string))
+ COMPILE_EXCEPTION(obj->properties.first(), tr("Component elements may not contain properties other than id"));
- if (obj->properties.count())
- idProp = *obj->properties.begin();
+ if (!obj->properties.isEmpty())
+ idProp = obj->properties.first();
if (idProp) {
- if (idProp->value || idProp->values.count() > 1 || idProp->values.at(0)->object)
+ if (idProp->value || idProp->values.isMany() || idProp->values.first()->object)
COMPILE_EXCEPTION(idProp, tr("Invalid component id specification"));
COMPILE_CHECK(checkValidId(idProp->values.first(), idProp->values.first()->primitive()))
QString idVal = idProp->values.first()->primitive();
- if (compileState.ids.contains(idVal))
+ if (compileState->ids.value(idVal))
COMPILE_EXCEPTION(idProp, tr("id is not unique"));
obj->id = idVal;
@@ -1308,8 +1358,8 @@ bool QDeclarativeCompiler::buildComponent(QDeclarativeParser::Object *obj,
// 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)))
+ (obj->defaultProperty->value || obj->defaultProperty->values.isMany() ||
+ (obj->defaultProperty->values.isOne() && !obj->defaultProperty->values.first()->object)))
COMPILE_EXCEPTION(obj, tr("Invalid component body specification"));
if (!obj->dynamicProperties.isEmpty())
@@ -1319,8 +1369,8 @@ bool QDeclarativeCompiler::buildComponent(QDeclarativeParser::Object *obj,
if (!obj->dynamicSlots.isEmpty())
COMPILE_EXCEPTION(obj, tr("Component objects cannot declare new functions."));
- QDeclarativeParser::Object *root = 0;
- if (obj->defaultProperty && obj->defaultProperty->values.count())
+ QDeclarativeScript::Object *root = 0;
+ if (obj->defaultProperty && !obj->defaultProperty->values.isEmpty())
root = obj->defaultProperty->values.first()->object;
if (!root)
@@ -1332,26 +1382,34 @@ bool QDeclarativeCompiler::buildComponent(QDeclarativeParser::Object *obj,
return true;
}
-bool QDeclarativeCompiler::buildComponentFromRoot(QDeclarativeParser::Object *obj,
+bool QDeclarativeCompiler::buildComponentFromRoot(QDeclarativeScript::Object *obj,
const BindingContext &ctxt)
{
- ComponentCompileState oldComponentCompileState = compileState;
- ComponentStat oldComponentStat = componentStat;
+ ComponentCompileState *oldComponentCompileState = compileState;
+ compileState = pool->New<ComponentCompileState>();
+ compileState->root = obj;
+ compileState->nested = true;
+
+ if (componentStats) {
+ ComponentStat oldComponentStat = componentStats->componentStat;
- compileState = ComponentCompileState();
- compileState.root = obj;
- compileState.nested = true;
+ componentStats->componentStat = ComponentStat();
+ componentStats->componentStat.lineNumber = obj->location.start.line;
- componentStat = ComponentStat();
- componentStat.lineNumber = obj->location.start.line;
+ if (obj)
+ COMPILE_CHECK(buildObject(obj, ctxt));
- if (obj)
- COMPILE_CHECK(buildObject(obj, ctxt));
+ COMPILE_CHECK(completeComponentBuild());
- COMPILE_CHECK(completeComponentBuild());
+ componentStats->componentStat = oldComponentStat;
+ } else {
+ if (obj)
+ COMPILE_CHECK(buildObject(obj, ctxt));
+
+ COMPILE_CHECK(completeComponentBuild());
+ }
compileState = oldComponentCompileState;
- componentStat = oldComponentStat;
return true;
}
@@ -1360,15 +1418,15 @@ bool QDeclarativeCompiler::buildComponentFromRoot(QDeclarativeParser::Object *ob
// 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 QDeclarativeCompiler::buildSubObject(QDeclarativeParser::Object *obj, const BindingContext &ctxt)
+bool QDeclarativeCompiler::buildSubObject(QDeclarativeScript::Object *obj, const BindingContext &ctxt)
{
Q_ASSERT(obj->metatype);
Q_ASSERT(!obj->defaultProperty);
Q_ASSERT(ctxt.isSubContext()); // sub-objects must always be in a binding
// sub-context
- foreach(Property *prop, obj->properties) {
- if (isSignalPropertyName(prop->name)) {
+ for (Property *prop = obj->properties.first(); prop; prop = obj->properties.next(prop)) {
+ if (isSignalPropertyName(prop->name())) {
COMPILE_CHECK(buildSignal(prop, obj, ctxt));
} else {
COMPILE_CHECK(buildProperty(prop, obj, ctxt));
@@ -1380,49 +1438,51 @@ bool QDeclarativeCompiler::buildSubObject(QDeclarativeParser::Object *obj, const
int QDeclarativeCompiler::componentTypeRef()
{
- QDeclarativeType *t = QDeclarativeMetaType::qmlType("QtQuick/Component",2,0);
+ QDeclarativeType *t = QDeclarativeMetaType::qmlType(QLatin1String("QtQuick/Component"),2,0);
for (int ii = output->types.count() - 1; ii >= 0; --ii) {
if (output->types.at(ii).type == t)
return ii;
}
QDeclarativeCompiledData::TypeReference ref;
- ref.className = "Component";
+ ref.className = Component_string;
ref.type = t;
output->types << ref;
return output->types.count() - 1;
}
-bool QDeclarativeCompiler::buildSignal(QDeclarativeParser::Property *prop, QDeclarativeParser::Object *obj,
+bool QDeclarativeCompiler::buildSignal(QDeclarativeScript::Property *prop, QDeclarativeScript::Object *obj,
const BindingContext &ctxt)
{
Q_ASSERT(obj->metaObject());
- QByteArray name = prop->name;
- Q_ASSERT(name.startsWith("on"));
- name = name.mid(2);
+ const QHashedStringRef &propName = prop->name();
+
+ Q_ASSERT(propName.startsWith(on_string));
+ QString name = propName.mid(2, -1).toString();
// Note that the property name could start with any alpha or '_' or '$' character,
// so we need to do the lower-casing of the first alpha character.
for (int firstAlphaIndex = 0; firstAlphaIndex < name.size(); ++firstAlphaIndex) {
- if (name[firstAlphaIndex] >= 'A' && name[firstAlphaIndex] <= 'Z') {
- name[firstAlphaIndex] = name[firstAlphaIndex] - 'A' + 'a';
+ if (QDeclarativeUtils::isUpper(name.at(firstAlphaIndex))) {
+ name[firstAlphaIndex] = name.at(firstAlphaIndex).toLower();
break;
}
}
bool notInRevision = false;
- int sigIdx = indexOfSignal(obj, name, &notInRevision);
- if (sigIdx == -1) {
+ QDeclarativePropertyCache::Data *sig = signal(obj, QStringRef(&name), &notInRevision);
+
+ if (sig == 0) {
- if (notInRevision && -1 == indexOfProperty(obj, prop->name, 0)) {
+ if (notInRevision && 0 == property(obj, propName, 0)) {
Q_ASSERT(obj->type != -1);
const QList<QDeclarativeTypeData::TypeReference> &resolvedTypes = unit->resolvedTypes();
const QDeclarativeTypeData::TypeReference &type = resolvedTypes.at(obj->type);
if (type.type) {
- COMPILE_EXCEPTION(prop, tr("\"%1.%2\" is not available in %3 %4.%5.").arg(QString::fromUtf8(obj->className)).arg(QString::fromUtf8(prop->name)).arg(QString::fromUtf8(type.type->module())).arg(type.majorVersion).arg(type.minorVersion));
+ COMPILE_EXCEPTION(prop, tr("\"%1.%2\" is not available in %3 %4.%5.").arg(elementName(obj)).arg(prop->name().toString()).arg(type.type->module()).arg(type.majorVersion).arg(type.minorVersion));
} else {
- COMPILE_EXCEPTION(prop, tr("\"%1.%2\" is not available due to component versioning.").arg(QString::fromUtf8(obj->className)).arg(QString::fromUtf8(prop->name)));
+ COMPILE_EXCEPTION(prop, tr("\"%1.%2\" is not available due to component versioning.").arg(elementName(obj)).arg(prop->name().toString()));
}
}
@@ -1432,26 +1492,28 @@ bool QDeclarativeCompiler::buildSignal(QDeclarativeParser::Property *prop, QDecl
} else {
- if (prop->value || prop->values.count() != 1)
+ if (prop->value || !prop->values.isOne())
COMPILE_EXCEPTION(prop, tr("Incorrectly specified signal assignment"));
- prop->index = sigIdx;
+ prop->index = sig->coreIndex;
+ prop->core = *sig;
+
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;
+ if (prop->values.first()->object) {
+ COMPILE_CHECK(buildObject(prop->values.first()->object, ctxt));
+ prop->values.first()->type = Value::SignalObject;
} else {
- prop->values.at(0)->type = Value::SignalExpression;
+ prop->values.first()->type = Value::SignalExpression;
- if (!prop->values.at(0)->value.isScript())
+ if (!prop->values.first()->value.isScript())
COMPILE_EXCEPTION(prop, tr("Cannot assign a value to a signal (expecting a script to be run)"));
- QString script = prop->values.at(0)->value.asScript().trimmed();
+ QString script = prop->values.first()->value.asScript().trimmed();
if (script.isEmpty())
COMPILE_EXCEPTION(prop, tr("Empty signal assignment"));
- compileState.signalExpressions.insert(prop->values.at(0), ctxt);
+ prop->values.first()->signalExpressionContextStack = ctxt.stack;
}
}
@@ -1462,37 +1524,28 @@ bool QDeclarativeCompiler::buildSignal(QDeclarativeParser::Property *prop, QDecl
/*!
Returns true if (value) property \a prop exists on obj, false otherwise.
*/
-bool QDeclarativeCompiler::doesPropertyExist(QDeclarativeParser::Property *prop,
- QDeclarativeParser::Object *obj)
+bool QDeclarativeCompiler::doesPropertyExist(QDeclarativeScript::Property *prop,
+ QDeclarativeScript::Object *obj)
{
- if(isAttachedPropertyName(prop->name) || prop->name == "id")
+ if (prop->name().isEmpty())
+ return false;
+ if(isAttachedPropertyName(prop->name()) || prop->name() == id_string)
return true;
- const QMetaObject *mo = obj->metaObject();
- if (mo) {
- if (prop->isDefault) {
- QMetaProperty p = QDeclarativeMetaType::defaultProperty(mo);
- return p.name() != 0;
- } else {
- int idx = indexOfProperty(obj, prop->name);
- return idx != -1 && mo->property(idx).isScriptable();
- }
- }
-
- return false;
+ return property(obj, prop->name()) != 0;
}
-bool QDeclarativeCompiler::buildProperty(QDeclarativeParser::Property *prop,
- QDeclarativeParser::Object *obj,
- const BindingContext &ctxt)
+bool QDeclarativeCompiler::buildProperty(QDeclarativeScript::Property *prop,
+ QDeclarativeScript::Object *obj,
+ const BindingContext &ctxt)
{
- if (prop->isEmpty())
+ if (prop->isEmpty())
COMPILE_EXCEPTION(prop, tr("Empty property assignment"));
const QMetaObject *metaObject = obj->metaObject();
Q_ASSERT(metaObject);
- if (isAttachedPropertyName(prop->name)) {
+ if (isAttachedPropertyName(prop->name())) {
// Setup attached property data
if (ctxt.isSubContext()) {
@@ -1504,7 +1557,7 @@ bool QDeclarativeCompiler::buildProperty(QDeclarativeParser::Property *prop,
QDeclarativeType *type = 0;
QDeclarativeImportedNamespace *typeNamespace = 0;
- unit->imports().resolveType(prop->name, &type, 0, 0, 0, &typeNamespace);
+ unit->imports().resolveType(prop->name().toString(), &type, 0, 0, 0, &typeNamespace);
if (typeNamespace) {
COMPILE_CHECK(buildPropertyInNamespace(typeNamespace, prop, obj,
@@ -1522,44 +1575,35 @@ bool QDeclarativeCompiler::buildProperty(QDeclarativeParser::Property *prop,
prop->value->metatype = type->attachedPropertiesType();
} else {
// Setup regular property data
- QMetaProperty p;
-
- if (prop->isDefault) {
- p = QDeclarativeMetaType::defaultProperty(metaObject);
+ bool notInRevision = false;
+ QDeclarativePropertyCache::Data *d =
+ prop->name().isEmpty()?0:property(obj, prop->name(), &notInRevision);
- if (p.name()) {
- prop->index = p.propertyIndex();
- prop->name = p.name();
- }
-
- } else {
- bool notInRevision = false;
- prop->index = indexOfProperty(obj, prop->name, &notInRevision);
- if (prop->index == -1 && notInRevision) {
- const QList<QDeclarativeTypeData::TypeReference> &resolvedTypes = unit->resolvedTypes();
- const QDeclarativeTypeData::TypeReference &type = resolvedTypes.at(obj->type);
- if (type.type) {
- COMPILE_EXCEPTION(prop, tr("\"%1.%2\" is not available in %3 %4.%5.").arg(QString::fromUtf8(obj->className)).arg(QString::fromUtf8(prop->name)).arg(QString::fromUtf8(type.type->module())).arg(type.majorVersion).arg(type.minorVersion));
- } else {
- COMPILE_EXCEPTION(prop, tr("\"%1.%2\" is not available due to component versioning.").arg(QString::fromUtf8(obj->className)).arg(QString::fromUtf8(prop->name)));
- }
- }
-
- if (prop->index != -1) {
- p = metaObject->property(prop->index);
- Q_ASSERT(p.name());
-
- if (!p.isScriptable()) {
- prop->index = -1;
- p = QMetaProperty();
- }
+ if (d == 0 && notInRevision) {
+ const QList<QDeclarativeTypeData::TypeReference> &resolvedTypes = unit->resolvedTypes();
+ const QDeclarativeTypeData::TypeReference &type = resolvedTypes.at(obj->type);
+ if (type.type) {
+ COMPILE_EXCEPTION(prop, tr("\"%1.%2\" is not available in %3 %4.%5.").arg(elementName(obj)).arg(prop->name().toString()).arg(type.type->module()).arg(type.majorVersion).arg(type.minorVersion));
+ } else {
+ COMPILE_EXCEPTION(prop, tr("\"%1.%2\" is not available due to component versioning.").arg(elementName(obj)).arg(prop->name().toString()));
}
+ } else if (d) {
+ prop->index = d->coreIndex;
+ prop->core = *d;
+ } else if (prop->isDefault) {
+ QMetaProperty p = QDeclarativeMetaType::defaultProperty(metaObject);
+ QDeclarativePropertyCache::Data defaultPropertyData;
+ defaultPropertyData.load(p, engine);
+ if (p.name())
+ prop->setName(p.name());
+ prop->core = defaultPropertyData;
+ prop->index = prop->core.coreIndex;
}
// We can't error here as the "id" property does not require a
// successful index resolution
- if (p.name())
- prop->type = p.userType();
+ if (prop->index != -1)
+ prop->type = prop->core.propType;
// Check if this is an alias
if (prop->index != -1 &&
@@ -1576,17 +1620,17 @@ bool QDeclarativeCompiler::buildProperty(QDeclarativeParser::Property *prop,
prop->parent->setBindingBit(prop->index);
}
- if (!prop->isDefault && prop->name == "id" && !ctxt.isSubContext()) {
+ if (!prop->isDefault && prop->name() == id_string && !ctxt.isSubContext()) {
// The magic "id" behavior 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())
+ prop->values.first()->value.isString())
COMPILE_CHECK(buildPropertyAssignment(prop, obj, ctxt));
- } else if (isAttachedPropertyName(prop->name)) {
+ } else if (isAttachedPropertyName(prop->name())) {
COMPILE_CHECK(buildAttachedProperty(prop, obj, ctxt));
@@ -1595,14 +1639,14 @@ bool QDeclarativeCompiler::buildProperty(QDeclarativeParser::Property *prop,
if (prop->isDefault) {
COMPILE_EXCEPTION(prop->values.first(), tr("Cannot assign to non-existent default property"));
} else {
- COMPILE_EXCEPTION(prop, tr("Cannot assign to non-existent property \"%1\"").arg(QString::fromUtf8(prop->name)));
+ COMPILE_EXCEPTION(prop, tr("Cannot assign to non-existent property \"%1\"").arg(prop->name().toString()));
}
} else if (prop->value) {
COMPILE_CHECK(buildGroupedProperty(prop, obj, ctxt));
- } else if (enginePrivate->isList(prop->type)) {
+ } else if (prop->core.isQList()) {
COMPILE_CHECK(buildListProperty(prop, obj, ctxt));
@@ -1620,22 +1664,22 @@ bool QDeclarativeCompiler::buildProperty(QDeclarativeParser::Property *prop,
}
bool QDeclarativeCompiler::buildPropertyInNamespace(QDeclarativeImportedNamespace *ns,
- QDeclarativeParser::Property *nsProp,
- QDeclarativeParser::Object *obj,
+ QDeclarativeScript::Property *nsProp,
+ QDeclarativeScript::Object *obj,
const BindingContext &ctxt)
{
if (!nsProp->value)
COMPILE_EXCEPTION(nsProp, tr("Invalid use of namespace"));
- foreach (Property *prop, nsProp->value->properties) {
+ for (Property *prop = nsProp->value->properties.first(); prop; prop = nsProp->value->properties.next(prop)) {
- if (!isAttachedPropertyName(prop->name))
+ if (!isAttachedPropertyName(prop->name()))
COMPILE_EXCEPTION(prop, tr("Not an attached property name"));
// Setup attached property data
QDeclarativeType *type = 0;
- unit->imports().resolveType(ns, prop->name, &type, 0, 0, 0);
+ unit->imports().resolveType(ns, prop->name().toString(), &type, 0, 0, 0);
if (!type || !type->attachedPropertiesType())
COMPILE_EXCEPTION(prop, tr("Non-existent attached object"));
@@ -1653,18 +1697,18 @@ bool QDeclarativeCompiler::buildPropertyInNamespace(QDeclarativeImportedNamespac
return true;
}
-void QDeclarativeCompiler::genValueProperty(QDeclarativeParser::Property *prop,
- QDeclarativeParser::Object *obj)
+void QDeclarativeCompiler::genValueProperty(QDeclarativeScript::Property *prop,
+ QDeclarativeScript::Object *obj)
{
- if (enginePrivate->isList(prop->type)) {
+ if (prop->core.isQList()) {
genListProperty(prop, obj);
} else {
genPropertyAssignment(prop, obj);
}
}
-void QDeclarativeCompiler::genListProperty(QDeclarativeParser::Property *prop,
- QDeclarativeParser::Object *obj)
+void QDeclarativeCompiler::genListProperty(QDeclarativeScript::Property *prop,
+ QDeclarativeScript::Object *obj)
{
int listType = enginePrivate->listType(prop->type);
@@ -1675,8 +1719,7 @@ void QDeclarativeCompiler::genListProperty(QDeclarativeParser::Property *prop,
fetch.fetchQmlList.type = listType;
output->addInstruction(fetch);
- for (int ii = 0; ii < prop->values.count(); ++ii) {
- QDeclarativeParser::Value *v = prop->values.at(ii);
+ for (Value *v = prop->values.first(); v; v = Property::ValueList::next(v)) {
if (v->type == Value::CreatedObject) {
@@ -1705,12 +1748,11 @@ void QDeclarativeCompiler::genListProperty(QDeclarativeParser::Property *prop,
output->addInstruction(pop);
}
-void QDeclarativeCompiler::genPropertyAssignment(QDeclarativeParser::Property *prop,
- QDeclarativeParser::Object *obj,
- QDeclarativeParser::Property *valueTypeProperty)
+void QDeclarativeCompiler::genPropertyAssignment(QDeclarativeScript::Property *prop,
+ QDeclarativeScript::Object *obj,
+ QDeclarativeScript::Property *valueTypeProperty)
{
- for (int ii = 0; ii < prop->values.count(); ++ii) {
- QDeclarativeParser::Value *v = prop->values.at(ii);
+ for (Value *v = prop->values.first(); v; v = Property::ValueList::next(v)) {
Q_ASSERT(v->type == Value::CreatedObject ||
v->type == Value::PropertyBinding ||
@@ -1728,7 +1770,7 @@ void QDeclarativeCompiler::genPropertyAssignment(QDeclarativeParser::Property *p
store.storeObject.propertyIndex = prop->index;
output->addInstruction(store);
- } else if (prop->type == -1) {
+ } else if (prop->type == QMetaType::QVariant) {
QDeclarativeInstruction store;
store.setType(QDeclarativeInstruction::StoreVariantObject);
@@ -1751,16 +1793,13 @@ void QDeclarativeCompiler::genPropertyAssignment(QDeclarativeParser::Property *p
} else if (v->type == Value::Literal) {
- QMetaProperty mp = obj->metaObject()->property(prop->index);
- genLiteralAssignment(mp, v);
+ genLiteralAssignment(prop, v);
}
}
- for (int ii = 0; ii < prop->onValues.count(); ++ii) {
-
- QDeclarativeParser::Value *v = prop->onValues.at(ii);
+ for (Value *v = prop->onValues.first(); v; v = Property::ValueList::next(v)) {
Q_ASSERT(v->type == Value::ValueSource ||
v->type == Value::ValueInterceptor);
@@ -1801,23 +1840,23 @@ void QDeclarativeCompiler::genPropertyAssignment(QDeclarativeParser::Property *p
}
}
-bool QDeclarativeCompiler::buildIdProperty(QDeclarativeParser::Property *prop,
- QDeclarativeParser::Object *obj)
+bool QDeclarativeCompiler::buildIdProperty(QDeclarativeScript::Property *prop,
+ QDeclarativeScript::Object *obj)
{
if (prop->value ||
- prop->values.count() > 1 ||
- prop->values.at(0)->object)
+ prop->values.isMany() ||
+ prop->values.first()->object)
COMPILE_EXCEPTION(prop, tr("Invalid use of id property"));
- QDeclarativeParser::Value *idValue = prop->values.at(0);
+ QDeclarativeScript::Value *idValue = prop->values.first();
QString val = idValue->primitive();
COMPILE_CHECK(checkValidId(idValue, val));
- if (compileState.ids.contains(val))
+ if (compileState->ids.value(val))
COMPILE_EXCEPTION(prop, tr("id is not unique"));
- prop->values.at(0)->type = Value::Id;
+ prop->values.first()->type = Value::Id;
obj->id = val;
addId(val, obj);
@@ -1825,35 +1864,37 @@ bool QDeclarativeCompiler::buildIdProperty(QDeclarativeParser::Property *prop,
return true;
}
-void QDeclarativeCompiler::addId(const QString &id, QDeclarativeParser::Object *obj)
+void QDeclarativeCompiler::addId(const QString &id, QDeclarativeScript::Object *obj)
{
- Q_ASSERT(!compileState.ids.contains(id));
+ Q_ASSERT(!compileState->ids.value(id));
Q_ASSERT(obj->id == id);
- obj->idIndex = compileState.ids.count();
- compileState.ids.insert(id, obj);
- compileState.idIndexes.insert(obj->idIndex, obj);
+ obj->idIndex = compileState->ids.count();
+ compileState->ids.append(obj);
}
-void QDeclarativeCompiler::addBindingReference(const BindingReference &ref)
+void QDeclarativeCompiler::addBindingReference(BindingReference *ref)
{
- Q_ASSERT(ref.value && !compileState.bindings.contains(ref.value));
- compileState.bindings.insert(ref.value, ref);
+ Q_ASSERT(ref->value && !ref->value->bindingReference);
+ ref->value->bindingReference = ref;
+ compileState->bindings.prepend(ref);
}
void QDeclarativeCompiler::saveComponentState()
{
- Q_ASSERT(compileState.root);
- Q_ASSERT(!savedCompileStates.contains(compileState.root));
+ Q_ASSERT(compileState->root);
+ Q_ASSERT(compileState->root->componentCompileState == 0);
+
+ compileState->root->componentCompileState = compileState;
- savedCompileStates.insert(compileState.root, compileState);
- savedComponentStats.append(componentStat);
+ if (componentStats)
+ componentStats->savedComponentStats.append(componentStats->componentStat);
}
-QDeclarativeCompiler::ComponentCompileState
-QDeclarativeCompiler::componentState(QDeclarativeParser::Object *obj)
+QDeclarativeCompilerTypes::ComponentCompileState *
+QDeclarativeCompiler::componentState(QDeclarativeScript::Object *obj)
{
- Q_ASSERT(savedCompileStates.contains(obj));
- return savedCompileStates.value(obj);
+ Q_ASSERT(obj->componentCompileState);
+ return obj->componentCompileState;
}
// Build attached property object. In this example,
@@ -1861,8 +1902,8 @@ QDeclarativeCompiler::componentState(QDeclarativeParser::Object *obj)
// GridView.row: 10
// }
// GridView is an attached property object.
-bool QDeclarativeCompiler::buildAttachedProperty(QDeclarativeParser::Property *prop,
- QDeclarativeParser::Object *obj,
+bool QDeclarativeCompiler::buildAttachedProperty(QDeclarativeScript::Property *prop,
+ QDeclarativeScript::Object *obj,
const BindingContext &ctxt)
{
Q_ASSERT(prop->value);
@@ -1882,32 +1923,33 @@ bool QDeclarativeCompiler::buildAttachedProperty(QDeclarativeParser::Property *p
// font.family: "Helvetica"
// }
// font is a nested property. pointSize and family are not.
-bool QDeclarativeCompiler::buildGroupedProperty(QDeclarativeParser::Property *prop,
- QDeclarativeParser::Object *obj,
+bool QDeclarativeCompiler::buildGroupedProperty(QDeclarativeScript::Property *prop,
+ QDeclarativeScript::Object *obj,
const BindingContext &ctxt)
{
Q_ASSERT(prop->type != 0);
Q_ASSERT(prop->index != -1);
if (QDeclarativeValueTypeFactory::isValueType(prop->type)) {
- if (prop->type >= 0 /* QVariant == -1 */ && enginePrivate->valueTypes[prop->type]) {
+ if (prop->type >= 0 && enginePrivate->valueTypes[prop->type]) {
- if (prop->values.count()) {
- if (prop->values.at(0)->location < prop->value->location) {
+ if (!prop->values.isEmpty()) {
+ if (prop->values.first()->location < prop->value->location) {
COMPILE_EXCEPTION(prop->value, tr( "Property has already been assigned a value"));
} else {
- COMPILE_EXCEPTION(prop->values.at(0), tr( "Property has already been assigned a value"));
+ COMPILE_EXCEPTION(prop->values.first(), tr( "Property has already been assigned a value"));
}
}
if (!obj->metaObject()->property(prop->index).isWritable()) {
- COMPILE_EXCEPTION(prop, tr( "Invalid property assignment: \"%1\" is a read-only property").arg(QString::fromUtf8(prop->name)));
+ COMPILE_EXCEPTION(prop, tr( "Invalid property assignment: \"%1\" is a read-only property").arg(prop->name().toString()));
}
if (prop->isAlias) {
- foreach (Property *vtProp, prop->value->properties)
+ for (Property *vtProp = prop->value->properties.first(); vtProp; vtProp = prop->value->properties.next(vtProp)) {
vtProp->isAlias = true;
+ }
}
COMPILE_CHECK(buildValueTypeProperty(enginePrivate->valueTypes[prop->type],
@@ -1923,8 +1965,8 @@ bool QDeclarativeCompiler::buildGroupedProperty(QDeclarativeParser::Property *pr
if (!prop->value->metatype)
COMPILE_EXCEPTION(prop, tr("Invalid grouped property access"));
- if (prop->values.count())
- COMPILE_EXCEPTION(prop->values.at(0), tr( "Cannot assign a value directly to a grouped property"));
+ if (!prop->values.isEmpty())
+ COMPILE_EXCEPTION(prop->values.first(), tr( "Cannot assign a value directly to a grouped property"));
obj->addGroupedProperty(prop);
@@ -1935,32 +1977,32 @@ bool QDeclarativeCompiler::buildGroupedProperty(QDeclarativeParser::Property *pr
}
bool QDeclarativeCompiler::buildValueTypeProperty(QObject *type,
- QDeclarativeParser::Object *obj,
- QDeclarativeParser::Object *baseObj,
+ QDeclarativeScript::Object *obj,
+ QDeclarativeScript::Object *baseObj,
const BindingContext &ctxt)
{
if (obj->defaultProperty)
COMPILE_EXCEPTION(obj, tr("Invalid property use"));
obj->metatype = type->metaObject();
- foreach (Property *prop, obj->properties) {
- int idx = type->metaObject()->indexOfProperty(prop->name.constData());
- if (idx == -1)
- COMPILE_EXCEPTION(prop, tr("Cannot assign to non-existent property \"%1\"").arg(QString::fromUtf8(prop->name)));
- QMetaProperty p = type->metaObject()->property(idx);
- if (!p.isScriptable())
- COMPILE_EXCEPTION(prop, tr("Cannot assign to non-existent property \"%1\"").arg(QString::fromUtf8(prop->name)));
- prop->index = idx;
- prop->type = p.userType();
+ for (Property *prop = obj->properties.first(); prop; prop = obj->properties.next(prop)) {
+
+ QDeclarativePropertyCache::Data *d = property(obj, prop->name());
+ if (d == 0)
+ COMPILE_EXCEPTION(prop, tr("Cannot assign to non-existent property \"%1\"").arg(prop->name().toString()));
+
+ prop->index = d->coreIndex;
+ prop->type = d->propType;
+ prop->core = *d;
prop->isValueTypeSubProperty = true;
if (prop->value)
COMPILE_EXCEPTION(prop, tr("Property assignment expected"));
- if (prop->values.count() > 1) {
+ if (prop->values.isMany()) {
COMPILE_EXCEPTION(prop, tr("Single property assignment expected"));
- } else if (prop->values.count()) {
- QDeclarativeParser::Value *value = prop->values.at(0);
+ } else if (!prop->values.isEmpty()) {
+ QDeclarativeScript::Value *value = prop->values.first();
if (value->object) {
COMPILE_EXCEPTION(prop, tr("Unexpected object assignment"));
@@ -1969,27 +2011,30 @@ bool QDeclarativeCompiler::buildValueTypeProperty(QObject *type,
//optimization for <Type>.<EnumValue> enum assignments
bool isEnumAssignment = false;
- COMPILE_CHECK(testQualifiedEnumAssignment(p, obj, value, &isEnumAssignment));
+
+ if (prop->core.isEnum())
+ COMPILE_CHECK(testQualifiedEnumAssignment(obj->metatype->property(prop->index), obj,
+ value, &isEnumAssignment));
+
if (isEnumAssignment) {
value->type = Value::Literal;
} else {
- BindingReference reference;
- reference.expression = value->value;
- reference.property = prop;
- reference.value = value;
- reference.bindingContext = ctxt;
- reference.bindingContext.owner++;
+ BindingReference *reference = pool->New<BindingReference>();
+ reference->expression = value->value;
+ reference->property = prop;
+ reference->value = value;
+ reference->bindingContext = ctxt;
+ reference->bindingContext.owner++;
addBindingReference(reference);
value->type = Value::PropertyBinding;
}
} else {
- COMPILE_CHECK(testLiteralAssignment(p, value));
+ COMPILE_CHECK(testLiteralAssignment(prop, value));
value->type = Value::Literal;
}
}
- for (int ii = 0; ii < prop->onValues.count(); ++ii) {
- QDeclarativeParser::Value *v = prop->onValues.at(ii);
+ for (Value *v = prop->onValues.first(); v; v = Property::ValueList::next(v)) {
Q_ASSERT(v->object);
COMPILE_CHECK(buildPropertyOnAssignment(prop, obj, baseObj, v, ctxt));
@@ -2004,11 +2049,11 @@ bool QDeclarativeCompiler::buildValueTypeProperty(QObject *type,
// Build assignments to QML lists. QML lists are properties of type
// QDeclarativeListProperty<T>. List properties can accept a list of
// objects, or a single binding.
-bool QDeclarativeCompiler::buildListProperty(QDeclarativeParser::Property *prop,
- QDeclarativeParser::Object *obj,
+bool QDeclarativeCompiler::buildListProperty(QDeclarativeScript::Property *prop,
+ QDeclarativeScript::Object *obj,
const BindingContext &ctxt)
{
- Q_ASSERT(enginePrivate->isList(prop->type));
+ Q_ASSERT(prop->core.isQList());
int t = prop->type;
@@ -2018,8 +2063,7 @@ bool QDeclarativeCompiler::buildListProperty(QDeclarativeParser::Property *prop,
bool listTypeIsInterface = QDeclarativeMetaType::isInterface(listType);
bool assignedBinding = false;
- for (int ii = 0; ii < prop->values.count(); ++ii) {
- QDeclarativeParser::Value *v = prop->values.at(ii);
+ for (Value *v = prop->values.first(); v; v = Property::ValueList::next(v)) {
if (v->object) {
v->type = Value::CreatedObject;
COMPILE_CHECK(buildObject(v->object, ctxt));
@@ -2048,33 +2092,33 @@ bool QDeclarativeCompiler::buildListProperty(QDeclarativeParser::Property *prop,
}
// Compiles an assignment to a QDeclarativeScriptString property
-bool QDeclarativeCompiler::buildScriptStringProperty(QDeclarativeParser::Property *prop,
- QDeclarativeParser::Object *obj,
+bool QDeclarativeCompiler::buildScriptStringProperty(QDeclarativeScript::Property *prop,
+ QDeclarativeScript::Object *obj,
const BindingContext &ctxt)
{
- if (prop->values.count() > 1)
- COMPILE_EXCEPTION(prop->values.at(1), tr( "Cannot assign multiple values to a script property"));
+ if (prop->values.isMany())
+ COMPILE_EXCEPTION(prop->values.first()->nextValue, tr( "Cannot assign multiple values to a script property"));
- if (prop->values.at(0)->object)
- COMPILE_EXCEPTION(prop->values.at(0), tr( "Invalid property assignment: script expected"));
+ if (prop->values.first()->object)
+ COMPILE_EXCEPTION(prop->values.first(), tr( "Invalid property assignment: script expected"));
- obj->addScriptStringProperty(prop, ctxt.stack);
+ prop->scriptStringScope = ctxt.stack;
+ obj->addScriptStringProperty(prop);
return true;
}
// Compile regular property assignments of the form "property: <value>"
-bool QDeclarativeCompiler::buildPropertyAssignment(QDeclarativeParser::Property *prop,
- QDeclarativeParser::Object *obj,
+bool QDeclarativeCompiler::buildPropertyAssignment(QDeclarativeScript::Property *prop,
+ QDeclarativeScript::Object *obj,
const BindingContext &ctxt)
{
obj->addValueProperty(prop);
- if (prop->values.count() > 1)
- COMPILE_EXCEPTION(prop->values.at(0), tr( "Cannot assign multiple values to a singular property") );
+ if (prop->values.isMany())
+ COMPILE_EXCEPTION(prop->values.first(), tr( "Cannot assign multiple values to a singular property") );
- for (int ii = 0; ii < prop->values.count(); ++ii) {
- QDeclarativeParser::Value *v = prop->values.at(ii);
+ for (Value *v = prop->values.first(); v; v = Property::ValueList::next(v)) {
if (v->object) {
COMPILE_CHECK(buildPropertyObjectAssignment(prop, obj, v, ctxt));
@@ -2086,9 +2130,7 @@ bool QDeclarativeCompiler::buildPropertyAssignment(QDeclarativeParser::Property
}
}
- for (int ii = 0; ii < prop->onValues.count(); ++ii) {
- QDeclarativeParser::Value *v = prop->onValues.at(ii);
-
+ for (Value *v = prop->onValues.first(); v; v = Property::ValueList::next(v)) {
Q_ASSERT(v->object);
COMPILE_CHECK(buildPropertyOnAssignment(prop, obj, obj, v, ctxt));
}
@@ -2097,16 +2139,16 @@ bool QDeclarativeCompiler::buildPropertyAssignment(QDeclarativeParser::Property
}
// Compile assigning a single object instance to a regular property
-bool QDeclarativeCompiler::buildPropertyObjectAssignment(QDeclarativeParser::Property *prop,
- QDeclarativeParser::Object *obj,
- QDeclarativeParser::Value *v,
+bool QDeclarativeCompiler::buildPropertyObjectAssignment(QDeclarativeScript::Property *prop,
+ QDeclarativeScript::Object *obj,
+ QDeclarativeScript::Value *v,
const BindingContext &ctxt)
{
Q_ASSERT(prop->index != -1);
Q_ASSERT(v->object->type != -1);
if (!obj->metaObject()->property(prop->index).isWritable())
- COMPILE_EXCEPTION(v, tr("Invalid property assignment: \"%1\" is a read-only property").arg(QString::fromUtf8(prop->name)));
+ COMPILE_EXCEPTION(v, tr("Invalid property assignment: \"%1\" is a read-only property").arg(prop->name().toString()));
if (QDeclarativeMetaType::isInterface(prop->type)) {
@@ -2115,7 +2157,7 @@ bool QDeclarativeCompiler::buildPropertyObjectAssignment(QDeclarativeParser::Pro
v->type = Value::CreatedObject;
- } else if (prop->type == -1) {
+ } else if (prop->type == QMetaType::QVariant) {
// Assigning an object to a QVariant
COMPILE_CHECK(buildObject(v->object, ctxt));
@@ -2152,13 +2194,13 @@ bool QDeclarativeCompiler::buildPropertyObjectAssignment(QDeclarativeParser::Pro
v->type = Value::CreatedObject;
} else if (propertyMetaObject == &QDeclarativeComponent::staticMetaObject) {
// Automatic "Component" insertion
- QDeclarativeParser::Object *root = v->object;
- QDeclarativeParser::Object *component = new QDeclarativeParser::Object;
+ QDeclarativeScript::Object *root = v->object;
+ QDeclarativeScript::Object *component = pool->New<Object>();
component->type = componentTypeRef();
component->typeName = "Qt/Component";
component->metatype = &QDeclarativeComponent::staticMetaObject;
component->location = root->location;
- QDeclarativeParser::Value *componentValue = new QDeclarativeParser::Value;
+ QDeclarativeScript::Value *componentValue = pool->New<Value>();
componentValue->object = root;
component->getDefaultProperty()->addValue(componentValue);
v->object = component;
@@ -2177,17 +2219,17 @@ bool QDeclarativeCompiler::buildPropertyObjectAssignment(QDeclarativeParser::Pro
// Item {
// NumberAnimation on x { }
// }
-bool QDeclarativeCompiler::buildPropertyOnAssignment(QDeclarativeParser::Property *prop,
- QDeclarativeParser::Object *obj,
- QDeclarativeParser::Object *baseObj,
- QDeclarativeParser::Value *v,
+bool QDeclarativeCompiler::buildPropertyOnAssignment(QDeclarativeScript::Property *prop,
+ QDeclarativeScript::Object *obj,
+ QDeclarativeScript::Object *baseObj,
+ QDeclarativeScript::Value *v,
const BindingContext &ctxt)
{
Q_ASSERT(prop->index != -1);
Q_ASSERT(v->object->type != -1);
if (!obj->metaObject()->property(prop->index).isWritable())
- COMPILE_EXCEPTION(v, tr("Invalid property assignment: \"%1\" is a read-only property").arg(QString::fromUtf8(prop->name)));
+ COMPILE_EXCEPTION(v, tr("Invalid property assignment: \"%1\" is a read-only property").arg(prop->name().toString()));
// Normally buildObject() will set this up, but we need the static
@@ -2214,28 +2256,31 @@ bool QDeclarativeCompiler::buildPropertyOnAssignment(QDeclarativeParser::Propert
buildDynamicMeta(baseObj, ForceCreation);
v->type = isPropertyValue ? Value::ValueSource : Value::ValueInterceptor;
} else {
- COMPILE_EXCEPTION(v, tr("\"%1\" cannot operate on \"%2\"").arg(QString::fromUtf8(v->object->typeName)).arg(QString::fromUtf8(prop->name.constData())));
+ COMPILE_EXCEPTION(v, tr("\"%1\" cannot operate on \"%2\"").arg(QString::fromUtf8(v->object->typeName)).arg(prop->name().toString()));
}
return true;
}
// Compile assigning a literal or binding to a regular property
-bool QDeclarativeCompiler::buildPropertyLiteralAssignment(QDeclarativeParser::Property *prop,
- QDeclarativeParser::Object *obj,
- QDeclarativeParser::Value *v,
- const BindingContext &ctxt)
+bool QDeclarativeCompiler::buildPropertyLiteralAssignment(QDeclarativeScript::Property *prop,
+ QDeclarativeScript::Object *obj,
+ QDeclarativeScript::Value *v,
+ const BindingContext &ctxt)
{
Q_ASSERT(prop->index != -1);
if (v->value.isScript()) {
//optimization for <Type>.<EnumValue> enum assignments
- bool isEnumAssignment = false;
- COMPILE_CHECK(testQualifiedEnumAssignment(obj->metaObject()->property(prop->index), obj, v, &isEnumAssignment));
- if (isEnumAssignment) {
- v->type = Value::Literal;
- return true;
+ if (prop->core.isEnum()) {
+ bool isEnumAssignment = false;
+ COMPILE_CHECK(testQualifiedEnumAssignment(obj->metaObject()->property(prop->index), obj,
+ v, &isEnumAssignment));
+ if (isEnumAssignment) {
+ v->type = Value::Literal;
+ return true;
+ }
}
COMPILE_CHECK(buildBinding(v, prop, ctxt));
@@ -2244,7 +2289,7 @@ bool QDeclarativeCompiler::buildPropertyLiteralAssignment(QDeclarativeParser::Pr
} else {
- COMPILE_CHECK(testLiteralAssignment(obj->metaObject()->property(prop->index), v));
+ COMPILE_CHECK(testLiteralAssignment(prop, v));
v->type = Value::Literal;
}
@@ -2253,9 +2298,9 @@ bool QDeclarativeCompiler::buildPropertyLiteralAssignment(QDeclarativeParser::Pr
}
bool QDeclarativeCompiler::testQualifiedEnumAssignment(const QMetaProperty &prop,
- QDeclarativeParser::Object *obj,
- QDeclarativeParser::Value *v,
- bool *isAssignment)
+ QDeclarativeScript::Object *obj,
+ QDeclarativeScript::Value *v,
+ bool *isAssignment)
{
*isAssignment = false;
if (!prop.isEnumType())
@@ -2265,7 +2310,7 @@ bool QDeclarativeCompiler::testQualifiedEnumAssignment(const QMetaProperty &prop
COMPILE_EXCEPTION(v, tr("Invalid property assignment: \"%1\" is a read-only property").arg(QString::fromUtf8(prop.name())));
QString string = v->value.asString();
- if (!string.at(0).isUpper())
+ if (!QDeclarativeUtils::isUpper(string.at(0)))
return true;
QStringList parts = string.split(QLatin1Char('.'));
@@ -2274,7 +2319,7 @@ bool QDeclarativeCompiler::testQualifiedEnumAssignment(const QMetaProperty &prop
QString typeName = parts.at(0);
QDeclarativeType *type = 0;
- unit->imports().resolveType(typeName.toUtf8(), &type, 0, 0, 0, 0);
+ unit->imports().resolveType(typeName, &type, 0, 0, 0, 0);
//handle enums on value types (where obj->typeName is empty)
QByteArray objTypeName = obj->typeName;
@@ -2312,7 +2357,7 @@ bool QDeclarativeCompiler::testQualifiedEnumAssignment(const QMetaProperty &prop
return true;
v->type = Value::Literal;
- v->value = QDeclarativeParser::Variant((double)value);
+ v->value = QDeclarativeScript::Variant((double)value);
*isAssignment = true;
return true;
@@ -2331,7 +2376,7 @@ int QDeclarativeCompiler::evaluateEnum(const QByteArray& script) const
if (dot > 0) {
const QByteArray &scope = script.left(dot);
QDeclarativeType *type = 0;
- unit->imports().resolveType(scope, &type, 0, 0, 0, 0);
+ unit->imports().resolveType(QString::fromUtf8(script.left(dot)), &type, 0, 0, 0, 0);
if (!type && scope != "Qt")
return -1;
const QMetaObject *mo = type ? type->metaObject() : StaticQtMetaObject::get();
@@ -2349,7 +2394,7 @@ int QDeclarativeCompiler::evaluateEnum(const QByteArray& script) const
const QMetaObject *QDeclarativeCompiler::resolveType(const QByteArray& name) const
{
QDeclarativeType *qmltype = 0;
- if (!unit->imports().resolveType(name, &qmltype, 0, 0, 0, 0))
+ if (!unit->imports().resolveType(QString::fromUtf8(name), &qmltype, 0, 0, 0, 0))
return 0;
if (!qmltype)
return 0;
@@ -2358,10 +2403,10 @@ const QMetaObject *QDeclarativeCompiler::resolveType(const QByteArray& name) con
// similar to logic of completeComponentBuild, but also sticks data
// into primitives at the end
-int QDeclarativeCompiler::rewriteBinding(const QString& expression, const QByteArray& name)
+int QDeclarativeCompiler::rewriteBinding(const QString& expression, const QString& name)
{
QDeclarativeRewrite::RewriteBinding rewriteBinding;
- rewriteBinding.setName('$' + name.mid(name.lastIndexOf('.') + 1));
+ rewriteBinding.setName(QLatin1Char('$') + name.mid(name.lastIndexOf('.') + 1));
QString rewrite = rewriteBinding(expression, 0, 0);
@@ -2369,16 +2414,20 @@ int QDeclarativeCompiler::rewriteBinding(const QString& expression, const QByteA
}
// Ensures that the dynamic meta specification on obj is valid
-bool QDeclarativeCompiler::checkDynamicMeta(QDeclarativeParser::Object *obj)
+bool QDeclarativeCompiler::checkDynamicMeta(QDeclarativeScript::Object *obj)
{
- QSet<QByteArray> propNames;
- QSet<QByteArray> methodNames;
bool seenDefaultProperty = false;
+ // We use a coarse grain, 31 bit hash to check if there are duplicates.
+ // Calculating the hash for the names is not a waste as we have to test
+ // them against the illegalNames set anyway.
+ QHashField propNames;
+ QHashField methodNames;
+
// Check properties
- for (int ii = 0; ii < obj->dynamicProperties.count(); ++ii) {
- const QDeclarativeParser::Object::DynamicProperty &prop =
- obj->dynamicProperties.at(ii);
+ int dpCount = obj->dynamicProperties.count();
+ for (Object::DynamicProperty *p = obj->dynamicProperties.first(); p; p = obj->dynamicProperties.next(p)) {
+ const QDeclarativeScript::Object::DynamicProperty &prop = *p;
if (prop.isDefaultProperty) {
if (seenDefaultProperty)
@@ -2386,60 +2435,75 @@ bool QDeclarativeCompiler::checkDynamicMeta(QDeclarativeParser::Object *obj)
seenDefaultProperty = true;
}
- if (propNames.contains(prop.name))
- COMPILE_EXCEPTION(&prop, tr("Duplicate property name"));
+ if (propNames.testAndSet(prop.name.hash())) {
+ for (Object::DynamicProperty *p2 = obj->dynamicProperties.first(); p2 != p;
+ p2 = obj->dynamicProperties.next(p2)) {
+ if (p2->name == prop.name)
+ COMPILE_EXCEPTION(&prop, tr("Duplicate property name"));
+ }
+ }
- QString propName = QString::fromUtf8(prop.name);
- if (propName.at(0).isUpper())
+ if (QDeclarativeUtils::isUpper(prop.name.at(0)))
COMPILE_EXCEPTION(&prop, tr("Property names cannot begin with an upper case letter"));
- if (enginePrivate->v8engine()->illegalNames().contains(propName))
+ if (enginePrivate->v8engine()->illegalNames().contains(prop.name))
COMPILE_EXCEPTION(&prop, tr("Illegal property name"));
-
- propNames.insert(prop.name);
}
- for (int ii = 0; ii < obj->dynamicSignals.count(); ++ii) {
- const QDeclarativeParser::Object::DynamicSignal &currSig = obj->dynamicSignals.at(ii);
- QByteArray name = currSig.name;
- if (methodNames.contains(name))
- COMPILE_EXCEPTION(&currSig, tr("Duplicate signal name"));
- QString nameStr = QString::fromUtf8(name);
- if (nameStr.at(0).isUpper())
+ for (Object::DynamicSignal *s = obj->dynamicSignals.first(); s; s = obj->dynamicSignals.next(s)) {
+ const QDeclarativeScript::Object::DynamicSignal &currSig = *s;
+
+ if (methodNames.testAndSet(currSig.name.hash())) {
+ for (Object::DynamicSignal *s2 = obj->dynamicSignals.first(); s2 != s;
+ s2 = obj->dynamicSignals.next(s2)) {
+ if (s2->name == currSig.name)
+ COMPILE_EXCEPTION(&currSig, tr("Duplicate signal name"));
+ }
+ }
+
+ if (currSig.name.at(0).isUpper())
COMPILE_EXCEPTION(&currSig, tr("Signal names cannot begin with an upper case letter"));
- if (enginePrivate->v8engine()->illegalNames().contains(nameStr))
+ if (enginePrivate->v8engine()->illegalNames().contains(currSig.name))
COMPILE_EXCEPTION(&currSig, tr("Illegal signal name"));
- methodNames.insert(name);
- }
- for (int ii = 0; ii < obj->dynamicSlots.count(); ++ii) {
- const QDeclarativeParser::Object::DynamicSlot &currSlot = obj->dynamicSlots.at(ii);
- QByteArray name = currSlot.name;
- if (methodNames.contains(name))
- COMPILE_EXCEPTION(&currSlot, tr("Duplicate method name"));
- QString nameStr = QString::fromUtf8(name);
- if (nameStr.at(0).isUpper())
+ }
+
+ for (Object::DynamicSlot *s = obj->dynamicSlots.first(); s; s = obj->dynamicSlots.next(s)) {
+ const QDeclarativeScript::Object::DynamicSlot &currSlot = *s;
+
+ if (methodNames.testAndSet(currSlot.name.hash())) {
+ for (Object::DynamicSignal *s2 = obj->dynamicSignals.first(); s2;
+ s2 = obj->dynamicSignals.next(s2)) {
+ if (s2->name == currSlot.name)
+ COMPILE_EXCEPTION(&currSlot, tr("Duplicate method name"));
+ }
+ for (Object::DynamicSlot *s2 = obj->dynamicSlots.first(); s2 != s;
+ s2 = obj->dynamicSlots.next(s2)) {
+ if (s2->name == currSlot.name)
+ COMPILE_EXCEPTION(&currSlot, tr("Duplicate method name"));
+ }
+ }
+
+ if (currSlot.name.at(0).isUpper())
COMPILE_EXCEPTION(&currSlot, tr("Method names cannot begin with an upper case letter"));
- if (enginePrivate->v8engine()->illegalNames().contains(nameStr))
+ if (enginePrivate->v8engine()->illegalNames().contains(currSlot.name))
COMPILE_EXCEPTION(&currSlot, tr("Illegal method name"));
- methodNames.insert(name);
}
return true;
}
-bool QDeclarativeCompiler::mergeDynamicMetaProperties(QDeclarativeParser::Object *obj)
+bool QDeclarativeCompiler::mergeDynamicMetaProperties(QDeclarativeScript::Object *obj)
{
- for (int ii = 0; ii < obj->dynamicProperties.count(); ++ii) {
- const Object::DynamicProperty &p = obj->dynamicProperties.at(ii);
+ for (Object::DynamicProperty *p = obj->dynamicProperties.first(); p; p = obj->dynamicProperties.next(p)) {
- if (!p.defaultValue || p.type == Object::DynamicProperty::Alias)
+ if (!p->defaultValue || p->type == Object::DynamicProperty::Alias)
continue;
Property *property = 0;
- if (p.isDefaultProperty) {
+ if (p->isDefaultProperty) {
property = obj->getDefaultProperty();
} else {
- property = obj->getProperty(p.name);
+ property = obj->getProperty(p->name);
if (!property->values.isEmpty())
COMPILE_EXCEPTION(property, tr("Property value set multiple times"));
}
@@ -2447,18 +2511,14 @@ bool QDeclarativeCompiler::mergeDynamicMetaProperties(QDeclarativeParser::Object
if (property->value)
COMPILE_EXCEPTION(property, tr("Invalid property nesting"));
- for (int ii = 0; ii < p.defaultValue->values.count(); ++ii) {
- QDeclarativeParser::Value *v = p.defaultValue->values.at(ii);
- v->addref();
- property->values.append(v);
- }
+ property->values.append(p->defaultValue->values);
}
return true;
}
Q_GLOBAL_STATIC(QAtomicInt, classIndexCounter)
-bool QDeclarativeCompiler::buildDynamicMeta(QDeclarativeParser::Object *obj, DynamicMetaMode mode)
+bool QDeclarativeCompiler::buildDynamicMeta(QDeclarativeScript::Object *obj, DynamicMetaMode mode)
{
Q_ASSERT(obj);
Q_ASSERT(obj->metatype);
@@ -2469,61 +2529,121 @@ bool QDeclarativeCompiler::buildDynamicMeta(QDeclarativeParser::Object *obj, Dyn
obj->dynamicSlots.isEmpty())
return true;
- QByteArray dynamicData(sizeof(QDeclarativeVMEMetaData), (char)0);
+ bool resolveAlias = (mode == ResolveAliases);
+
+ const Object::DynamicProperty *defaultProperty = 0;
+ int aliasCount = 0;
+
+ for (Object::DynamicProperty *p = obj->dynamicProperties.first(); p; p = obj->dynamicProperties.next(p)) {
+
+ if (p->type == Object::DynamicProperty::Alias)
+ aliasCount++;
+
+ if (p->isDefaultProperty &&
+ (resolveAlias || p->type != Object::DynamicProperty::Alias))
+ defaultProperty = p;
+
+ if (!resolveAlias) {
+ // No point doing this for both the alias and non alias cases
+ QDeclarativePropertyCache::Data *d = property(obj, p->name);
+ if (d && d->isFinal())
+ COMPILE_EXCEPTION(p, tr("Cannot override FINAL property"));
+ }
+ }
+
+ bool buildData = resolveAlias || aliasCount == 0;
+
+ QByteArray dynamicData;
+ if (buildData) {
+ typedef QDeclarativeVMEMetaData VMD;
+
+ dynamicData = QByteArray(sizeof(QDeclarativeVMEMetaData) +
+ (obj->dynamicProperties.count() - aliasCount) * sizeof(VMD::PropertyData) +
+ obj->dynamicSlots.count() * sizeof(VMD::MethodData) +
+ aliasCount * sizeof(VMD::AliasData), 0);
+ }
+
+ int uniqueClassId = classIndexCounter()->fetchAndAddRelaxed(1);
QByteArray newClassName = obj->metatype->className();
newClassName.append("_QML_");
- int idx = classIndexCounter()->fetchAndAddRelaxed(1);
- newClassName.append(QByteArray::number(idx));
- if (compileState.root == obj && !compileState.nested) {
+ newClassName.append(QByteArray::number(uniqueClassId));
+
+ if (compileState->root == obj && !compileState->nested) {
QString path = output->url.path();
int lastSlash = path.lastIndexOf(QLatin1Char('/'));
if (lastSlash > -1) {
QString nameBase = path.mid(lastSlash + 1, path.length()-lastSlash-5);
- if (!nameBase.isEmpty() && nameBase.at(0).isUpper())
- newClassName = nameBase.toUtf8() + "_QMLTYPE_" + QByteArray::number(idx);
+ if (!nameBase.isEmpty() && QDeclarativeUtils::isUpper(nameBase.at(0)))
+ newClassName = nameBase.toUtf8() + "_QMLTYPE_" + QByteArray::number(uniqueClassId);
}
}
- QMetaObjectBuilder builder;
- builder.setClassName(newClassName);
- builder.setFlags(QMetaObjectBuilder::DynamicMetaObject);
+ QFastMetaBuilder builder;
+ QFastMetaBuilder::StringRef classNameRef = builder.init(newClassName.length(),
+ obj->dynamicProperties.count() - (resolveAlias?0:aliasCount),
+ obj->dynamicSlots.count(),
+ obj->dynamicSignals.count() + obj->dynamicProperties.count(),
+ defaultProperty?1:0);
+
+ struct TypeData {
+ Object::DynamicProperty::Type dtype;
+ int metaType;
+ const char *cppType;
+ } builtinTypes[] = {
+ { Object::DynamicProperty::Variant, 0, "QVariant" },
+ { Object::DynamicProperty::Int, QMetaType::Int, "int" },
+ { Object::DynamicProperty::Bool, QMetaType::Bool, "bool" },
+ { Object::DynamicProperty::Real, QMetaType::Double, "double" },
+ { Object::DynamicProperty::String, QMetaType::QString, "QString" },
+ { Object::DynamicProperty::Url, QMetaType::QUrl, "QUrl" },
+ { Object::DynamicProperty::Color, QMetaType::QColor, "QColor" },
+ { Object::DynamicProperty::Time, QMetaType::QTime, "QTime" },
+ { Object::DynamicProperty::Date, QMetaType::QDate, "QDate" },
+ { Object::DynamicProperty::DateTime, QMetaType::QDateTime, "QDateTime" },
+ };
+ static const int builtinTypeCount = sizeof(builtinTypes) / sizeof(TypeData);
+ QFastMetaBuilder::StringRef typeRefs[builtinTypeCount];
+
+ // Reserve dynamic properties
+ if (obj->dynamicProperties.count()) {
+ typedef QDeclarativeVMEMetaData VMD;
+
+ int effectivePropertyIndex = 0;
+ for (Object::DynamicProperty *p = obj->dynamicProperties.first(); p; p = obj->dynamicProperties.next(p)) {
+
+ // Reserve space for name
+ p->nameRef = builder.newString(p->name.utf8length());
+
+ int propertyType = 0;
+ bool readonly = false;
+ QFastMetaBuilder::StringRef typeRef;
+
+ if (p->type == Object::DynamicProperty::Alias) {
+ continue;
+ } else if (p->type < builtinTypeCount) {
+ Q_ASSERT(builtinTypes[p->type].dtype == p->type);
+ propertyType = builtinTypes[p->type].metaType;
+ if (typeRefs[p->type].isEmpty())
+ typeRefs[p->type] = builder.newString(strlen(builtinTypes[p->type].cppType));
+ typeRef = typeRefs[p->type];
+ if (p->type == Object::DynamicProperty::Variant)
+ propertyType = -1;
- bool hasAlias = false;
- for (int ii = 0; ii < obj->dynamicProperties.count(); ++ii) {
- const Object::DynamicProperty &p = obj->dynamicProperties.at(ii);
+ } else {
+ Q_ASSERT(p->type == Object::DynamicProperty::CustomList ||
+ p->type == Object::DynamicProperty::Custom);
- int propIdx = obj->metaObject()->indexOfProperty(p.name.constData());
- if (-1 != propIdx) {
- QMetaProperty prop = obj->metaObject()->property(propIdx);
- if (prop.isFinal())
- COMPILE_EXCEPTION(&p, tr("Cannot override FINAL property"));
- }
+ // XXX don't double resolve this in the case of an alias run
- if (p.isDefaultProperty &&
- (p.type != Object::DynamicProperty::Alias ||
- mode == ResolveAliases))
- builder.addClassInfo("DefaultProperty", p.name);
-
- QByteArray type;
- int propertyType = 0;
- bool readonly = false;
- switch(p.type) {
- case Object::DynamicProperty::Alias:
- hasAlias = true;
- continue;
- break;
- case Object::DynamicProperty::CustomList:
- case Object::DynamicProperty::Custom:
- {
QByteArray customTypeName;
QDeclarativeType *qmltype = 0;
- QUrl url;
- if (!unit->imports().resolveType(p.customType, &qmltype, &url, 0, 0, 0))
- COMPILE_EXCEPTION(&p, tr("Invalid property type"));
+ QString url;
+ if (!unit->imports().resolveType(p->customType.toString(), &qmltype, &url, 0, 0, 0))
+ COMPILE_EXCEPTION(p, tr("Invalid property type"));
if (!qmltype) {
- QDeclarativeTypeData *tdata = enginePrivate->typeLoader.get(url);
+ QDeclarativeTypeData *tdata = enginePrivate->typeLoader.get(QUrl(url));
Q_ASSERT(tdata);
Q_ASSERT(tdata->isComplete());
@@ -2535,146 +2655,217 @@ bool QDeclarativeCompiler::buildDynamicMeta(QDeclarativeParser::Object *obj, Dyn
customTypeName = qmltype->typeName();
}
- if (p.type == Object::DynamicProperty::Custom) {
- type = customTypeName + '*';
+ if (p->type == Object::DynamicProperty::Custom) {
+ customTypeName += '*';
propertyType = QMetaType::QObjectStar;
} else {
readonly = true;
- type = "QDeclarativeListProperty<";
- type.append(customTypeName);
- type.append(">");
+ customTypeName = QByteArray("QDeclarativeListProperty<") + customTypeName + QByteArray(">");
propertyType = qMetaTypeId<QDeclarativeListProperty<QObject> >();
}
+
+ p->resolvedCustomTypeName = pool->NewByteArray(customTypeName);
+ p->typeRef = builder.newString(customTypeName.length());
+ typeRef = p->typeRef;
}
- break;
- case Object::DynamicProperty::Variant:
- propertyType = -1;
- type = "QVariant";
- break;
- case Object::DynamicProperty::Int:
- propertyType = QVariant::Int;
- type = "int";
- break;
- case Object::DynamicProperty::Bool:
- propertyType = QVariant::Bool;
- type = "bool";
- break;
- case Object::DynamicProperty::Real:
- propertyType = QVariant::Double;
- type = "double";
- break;
- case Object::DynamicProperty::String:
- propertyType = QVariant::String;
- type = "QString";
- break;
- case Object::DynamicProperty::Url:
- propertyType = QVariant::Url;
- type = "QUrl";
- break;
- case Object::DynamicProperty::Color:
- propertyType = QVariant::Color;
- type = "QColor";
- break;
- case Object::DynamicProperty::Time:
- propertyType = QVariant::Time;
- type = "QTime";
- break;
- case Object::DynamicProperty::Date:
- propertyType = QVariant::Date;
- type = "QDate";
- break;
- case Object::DynamicProperty::DateTime:
- propertyType = QVariant::DateTime;
- type = "QDateTime";
- break;
- }
- ((QDeclarativeVMEMetaData *)dynamicData.data())->propertyCount++;
- QDeclarativeVMEMetaData::PropertyData propertyData = { propertyType };
- dynamicData.append((char *)&propertyData, sizeof(propertyData));
+ if (buildData) {
+ VMD *vmd = (QDeclarativeVMEMetaData *)dynamicData.data();
+ vmd->propertyCount++;
+ (vmd->propertyData() + effectivePropertyIndex)->propertyType = propertyType;
+ }
- builder.addSignal(p.name + "Changed()");
- QMetaPropertyBuilder propBuilder =
- builder.addProperty(p.name, type, builder.methodCount() - 1);
- propBuilder.setWritable(!readonly);
- }
+ if (p->type < builtinTypeCount)
+ builder.setProperty(effectivePropertyIndex, p->nameRef, typeRef, (QMetaType::Type)propertyType,
+ readonly?QFastMetaBuilder::None:QFastMetaBuilder::Writable,
+ effectivePropertyIndex);
+ else
+ builder.setProperty(effectivePropertyIndex, p->nameRef, typeRef,
+ readonly?QFastMetaBuilder::None:QFastMetaBuilder::Writable,
+ effectivePropertyIndex);
- for (int ii = 0; ii < obj->dynamicProperties.count(); ++ii) {
- const Object::DynamicProperty &p = obj->dynamicProperties.at(ii);
+ p->changedSignatureRef = builder.newString(p->name.utf8length() + strlen("Changed()"));
+ builder.setSignal(effectivePropertyIndex, p->changedSignatureRef);
- if (p.type == Object::DynamicProperty::Alias) {
- if (mode == ResolveAliases) {
- ((QDeclarativeVMEMetaData *)dynamicData.data())->aliasCount++;
- COMPILE_CHECK(compileAlias(builder, dynamicData, obj, p));
- } else {
- // Need a fake signal so that the metaobject remains consistent across
- // the resolve and non-resolve alias runs
- builder.addSignal(p.name + "Changed()");
+ effectivePropertyIndex++;
+ }
+
+ if (aliasCount) {
+ int aliasIndex = 0;
+ for (Object::DynamicProperty *p = obj->dynamicProperties.first(); p; p = obj->dynamicProperties.next(p)) {
+ if (p->type == Object::DynamicProperty::Alias) {
+ if (resolveAlias) {
+ Q_ASSERT(buildData);
+ ((QDeclarativeVMEMetaData *)dynamicData.data())->aliasCount++;
+ COMPILE_CHECK(compileAlias(builder, dynamicData, obj, effectivePropertyIndex,
+ aliasIndex, *p));
+ }
+ // Even if we aren't resolving the alias, we need a fake signal so that the
+ // metaobject remains consistent across the resolve and non-resolve alias runs
+ p->changedSignatureRef = builder.newString(p->name.utf8length() + strlen("Changed()"));
+ builder.setSignal(effectivePropertyIndex, p->changedSignatureRef);
+ effectivePropertyIndex++;
+ aliasIndex++;
+ }
}
}
}
- for (int ii = 0; ii < obj->dynamicSignals.count(); ++ii) {
- const Object::DynamicSignal &s = obj->dynamicSignals.at(ii);
- QByteArray sig(s.name + '(');
- for (int jj = 0; jj < s.parameterTypes.count(); ++jj) {
- if (jj) sig.append(',');
- sig.append(s.parameterTypes.at(jj));
- }
- sig.append(')');
- QMetaMethodBuilder b = builder.addSignal(sig);
- b.setParameterNames(s.parameterNames);
- ((QDeclarativeVMEMetaData *)dynamicData.data())->signalCount++;
+ // Reserve default property
+ QFastMetaBuilder::StringRef defPropRef;
+ if (defaultProperty) {
+ defPropRef = builder.newString(strlen("DefaultProperty"));
+ builder.setClassInfo(0, defPropRef, defaultProperty->nameRef);
+ }
+
+ // Reserve dynamic signals
+ int signalIndex = 0;
+ for (Object::DynamicSignal *s = obj->dynamicSignals.first(); s; s = obj->dynamicSignals.next(s)) {
+
+ int paramCount = s->parameterNames.count();
+
+ int signatureSize = s->name.utf8length() + 2 /* paren */;
+ int namesSize = 0;
+ if (paramCount) signatureSize += s->parameterTypesLength() + (paramCount - 1) /* commas */;
+ if (paramCount) namesSize += s->parameterNamesLength() + (paramCount - 1) /* commas */;
+
+ s->signatureRef = builder.newString(signatureSize);
+ if (namesSize) s->parameterNamesRef = builder.newString(namesSize);
+
+ if (buildData)
+ ((QDeclarativeVMEMetaData *)dynamicData.data())->signalCount++;
+
+ builder.setSignal(signalIndex + obj->dynamicProperties.count(), s->signatureRef, s->parameterNamesRef);
+ ++signalIndex;
}
- QStringList funcScripts;
+ // Reserve dynamic slots
+ if (obj->dynamicSlots.count()) {
+
+ // Allocate QVariant string
+ if (typeRefs[0].isEmpty())
+ typeRefs[0] = builder.newString(strlen(builtinTypes[0].cppType));
+
+ typedef QDeclarativeVMEMetaData VMD;
+
+ int methodIndex = 0;
+ for (Object::DynamicSlot *s = obj->dynamicSlots.first(); s; s = obj->dynamicSlots.next(s)) {
+ int paramCount = s->parameterNames.count();
- for (int ii = 0; ii < obj->dynamicSlots.count(); ++ii) {
- Object::DynamicSlot &s = obj->dynamicSlots[ii];
- QByteArray sig(s.name + '(');
- QString funcScript(QLatin1String("(function ") + s.name + QLatin1Char('('));
+ int signatureSize = s->name.utf8length() + 2 /* paren */;
+ int namesSize = 0;
+ if (paramCount) signatureSize += (paramCount * strlen("QVariant") + (paramCount - 1));
+ if (paramCount) namesSize += s->parameterNamesLength() + (paramCount - 1 /* commas */);
- for (int jj = 0; jj < s.parameterNames.count(); ++jj) {
- if (jj) {
- sig.append(',');
- funcScript.append(QLatin1Char(','));
+ s->signatureRef = builder.newString(signatureSize);
+ if (namesSize) s->parameterNamesRef = builder.newString(namesSize);
+
+ builder.setMethod(methodIndex, s->signatureRef, s->parameterNamesRef, typeRefs[0]);
+
+ if (buildData) {
+ QString funcScript;
+ funcScript.reserve(strlen("(function ") + s->name.length() + 1 /* lparen */ +
+ namesSize + 1 /* rparen */ + s->body.length() + 1 /* rparen */);
+ funcScript = QLatin1String("(function ") + s->name.toString() + QLatin1Char('(');
+ for (int jj = 0; jj < paramCount; ++jj) {
+ if (jj) funcScript.append(QLatin1Char(','));
+ funcScript.append(QLatin1String(s->parameterNames.at(jj)));
+ }
+ funcScript += QLatin1Char(')') + s->body + QLatin1Char(')');
+
+ VMD::MethodData methodData = { s->parameterNames.count(), 0,
+ funcScript.length(),
+ s->location.start.line };
+
+ VMD *vmd = (QDeclarativeVMEMetaData *)dynamicData.data();
+ vmd->methodCount++;
+
+ VMD::MethodData &md = *(vmd->methodData() + methodIndex);
+ md = methodData;
+ md.bodyOffset = dynamicData.size();
+
+ dynamicData.append((const char *)funcScript.constData(),
+ (funcScript.length() * sizeof(QChar)));
}
- funcScript.append(QLatin1String(s.parameterNames.at(jj)));
- sig.append("QVariant");
+
+ methodIndex++;
}
- sig.append(')');
- funcScript.append(QLatin1Char(')'));
- funcScript.append(s.body);
- funcScript.append(QLatin1Char(')'));
- funcScripts << funcScript;
+ }
- QMetaMethodBuilder b = builder.addSlot(sig);
- b.setReturnType("QVariant");
- b.setParameterNames(s.parameterNames);
+ // Now allocate used builtin types
+ for (int ii = 0; ii < builtinTypeCount; ++ii) {
+ if (!typeRefs[ii].isEmpty())
+ typeRefs[ii].load(builtinTypes[ii].cppType);
+ }
- ((QDeclarativeVMEMetaData *)dynamicData.data())->methodCount++;
- QDeclarativeVMEMetaData::MethodData methodData =
- { s.parameterNames.count(), 0, funcScript.length(), s.location.start.line };
+ // Now allocate properties
+ for (Object::DynamicProperty *p = obj->dynamicProperties.first(); p; p = obj->dynamicProperties.next(p)) {
- dynamicData.append((char *)&methodData, sizeof(methodData));
- }
+ char *d = p->changedSignatureRef.data();
+ p->name.writeUtf8(d);
+ strcpy(d + p->name.utf8length(), "Changed()");
- for (int ii = 0; ii < obj->dynamicSlots.count(); ++ii) {
- const QString &funcScript = funcScripts.at(ii);
- QDeclarativeVMEMetaData::MethodData *data =
- ((QDeclarativeVMEMetaData *)dynamicData.data())->methodData() + ii;
+ if (p->type == Object::DynamicProperty::Alias && !resolveAlias)
+ continue;
+
+ p->nameRef.load(p->name);
- data->bodyOffset = dynamicData.size();
+ if (p->type >= builtinTypeCount) {
+ Q_ASSERT(p->resolvedCustomTypeName);
+ p->typeRef.load(*p->resolvedCustomTypeName);
+ }
+ }
- dynamicData.append((const char *)funcScript.constData(),
- (funcScript.length() * sizeof(QChar)));
+ // Allocate default property if necessary
+ if (defaultProperty)
+ strcpy(defPropRef.data(), "DefaultProperty");
+
+ // Now allocate signals
+ for (Object::DynamicSignal *s = obj->dynamicSignals.first(); s; s = obj->dynamicSignals.next(s)) {
+
+ char *d = s->signatureRef.data();
+ char *d2 = s->parameterNamesRef.isEmpty()?0:s->parameterNamesRef.data();
+ s->name.writeUtf8(d); d += s->name.utf8length();
+ *d++ = '(';
+
+ for (int jj = 0; jj < s->parameterNames.count(); ++jj) {
+ if (jj != 0) { *d++ = ','; *d2++ = ','; }
+ strcpy(d, s->parameterTypes.at(jj).constData());
+ d += s->parameterTypes.at(jj).length();
+ s->parameterNames.at(jj).writeUtf8(d2);
+ d2 += s->parameterNames.at(jj).utf8length();
+ }
+ *d++ = ')';
+ *d = 0;
+ if (d2) *d2 = 0;
+ }
+
+ // Now allocate methods
+ for (Object::DynamicSlot *s = obj->dynamicSlots.first(); s; s = obj->dynamicSlots.next(s)) {
+ char *d = s->signatureRef.data();
+ char *d2 = s->parameterNamesRef.isEmpty()?0:s->parameterNamesRef.data();
+ s->name.writeUtf8(d); d += s->name.utf8length();
+ *d++ = '(';
+ for (int jj = 0; jj < s->parameterNames.count(); ++jj) {
+ if (jj != 0) { *d++ = ','; *d2++ = ','; }
+ strcpy(d, "QVariant");
+ d += strlen("QVariant");
+ strcpy(d2, s->parameterNames.at(jj).constData());
+ d2 += s->parameterNames.at(jj).length();
+ }
+ *d++ = ')';
+ *d = 0;
+ if (d2) *d2 = 0;
}
- obj->metadata = builder.toRelocatableData();
- builder.fromRelocatableData(&obj->extObject, obj->metatype, obj->metadata);
+ // Now allocate class name
+ classNameRef.load(newClassName);
- if (mode == IgnoreAliases && hasAlias)
- compileState.aliasingObjects << obj;
+ obj->metadata = builder.toData();
+ builder.fromData(&obj->extObject, obj->metatype, obj->metadata);
+
+ if (mode == IgnoreAliases && aliasCount)
+ compileState->aliasingObjects.append(obj);
obj->synthdata = dynamicData;
@@ -2694,23 +2885,23 @@ bool QDeclarativeCompiler::buildDynamicMeta(QDeclarativeParser::Object *obj, Dyn
return true;
}
-bool QDeclarativeCompiler::checkValidId(QDeclarativeParser::Value *v, const QString &val)
+bool QDeclarativeCompiler::checkValidId(QDeclarativeScript::Value *v, const QString &val)
{
if (val.isEmpty())
COMPILE_EXCEPTION(v, tr( "Invalid empty ID"));
- if (val.at(0).isLetter() && !val.at(0).isLower())
+ QChar ch = val.at(0);
+ if (QDeclarativeUtils::isLetter(ch) && !QDeclarativeUtils::isLower(ch))
COMPILE_EXCEPTION(v, tr( "IDs cannot start with an uppercase letter"));
QChar u(QLatin1Char('_'));
- for (int ii = 0; ii < val.count(); ++ii) {
+ if (!QDeclarativeUtils::isLetter(ch) && ch != u)
+ COMPILE_EXCEPTION(v, tr( "IDs must start with a letter or underscore"));
- if (ii == 0 && !val.at(ii).isLetter() && val.at(ii) != u) {
- COMPILE_EXCEPTION(v, tr( "IDs must start with a letter or underscore"));
- } else if (ii != 0 && !val.at(ii).isLetterOrNumber() && val.at(ii) != u) {
+ for (int ii = 1; ii < val.count(); ++ii) {
+ ch = val.at(ii);
+ if (!QDeclarativeUtils::isLetterOrNumber(ch) && ch != u)
COMPILE_EXCEPTION(v, tr( "IDs must contain only letters, numbers, and underscores"));
- }
-
}
if (enginePrivate->v8engine()->illegalNames().contains(val))
@@ -2725,7 +2916,7 @@ static QStringList astNodeToStringList(QDeclarativeJS::AST::Node *node)
{
if (node->kind == QDeclarativeJS::AST::Node::Kind_IdentifierExpression) {
QString name =
- static_cast<QDeclarativeJS::AST::IdentifierExpression *>(node)->name->asString();
+ static_cast<QDeclarativeJS::AST::IdentifierExpression *>(node)->name.toString();
return QStringList() << name;
} else if (node->kind == QDeclarativeJS::AST::Node::Kind_FieldMemberExpression) {
QDeclarativeJS::AST::FieldMemberExpression *expr = static_cast<QDeclarativeJS::AST::FieldMemberExpression *>(node);
@@ -2733,26 +2924,27 @@ static QStringList astNodeToStringList(QDeclarativeJS::AST::Node *node)
QStringList rv = astNodeToStringList(expr->base);
if (rv.isEmpty())
return rv;
- rv.append(expr->name->asString());
+ rv.append(expr->name.toString());
return rv;
}
return QStringList();
}
-bool QDeclarativeCompiler::compileAlias(QMetaObjectBuilder &builder,
+bool QDeclarativeCompiler::compileAlias(QFastMetaBuilder &builder,
QByteArray &data,
- QDeclarativeParser::Object *obj,
- const Object::DynamicProperty &prop)
+ QDeclarativeScript::Object *obj,
+ int propIndex, int aliasIndex,
+ Object::DynamicProperty &prop)
{
if (!prop.defaultValue)
COMPILE_EXCEPTION(obj, tr("No property alias location"));
- if (prop.defaultValue->values.count() != 1 ||
- prop.defaultValue->values.at(0)->object ||
- !prop.defaultValue->values.at(0)->value.isScript())
+ if (!prop.defaultValue->values.isOne() ||
+ prop.defaultValue->values.first()->object ||
+ !prop.defaultValue->values.first()->value.isScript())
COMPILE_EXCEPTION(prop.defaultValue, tr("Invalid alias location"));
- QDeclarativeJS::AST::Node *node = prop.defaultValue->values.at(0)->value.asAST();
+ QDeclarativeJS::AST::Node *node = prop.defaultValue->values.first()->value.asAST();
if (!node)
COMPILE_EXCEPTION(obj, tr("No property alias location")); // ### Can this happen?
@@ -2761,19 +2953,19 @@ bool QDeclarativeCompiler::compileAlias(QMetaObjectBuilder &builder,
if (alias.count() < 1 || alias.count() > 3)
COMPILE_EXCEPTION(prop.defaultValue, tr("Invalid alias reference. An alias reference must be specified as <id>, <id>.<property> or <id>.<value property>.<property>"));
- if (!compileState.ids.contains(alias.at(0)))
+ QDeclarativeScript::Object *idObject = compileState->ids.value(alias.at(0));
+ if (!idObject)
COMPILE_EXCEPTION(prop.defaultValue, tr("Invalid alias reference. Unable to find id \"%1\"").arg(alias.at(0)));
- QDeclarativeParser::Object *idObject = compileState.ids[alias.at(0)];
-
QByteArray typeName;
int propIdx = -1;
int flags = 0;
+ int type = 0;
bool writable = false;
bool resettable = false;
if (alias.count() == 2 || alias.count() == 3) {
- propIdx = indexOfProperty(idObject, alias.at(1).toUtf8());
+ propIdx = indexOfProperty(idObject, alias.at(1));
if (-1 == propIdx) {
COMPILE_EXCEPTION(prop.defaultValue, tr("Invalid alias location"));
@@ -2788,6 +2980,9 @@ bool QDeclarativeCompiler::compileAlias(QMetaObjectBuilder &builder,
writable = aliasProperty.isWritable();
resettable = aliasProperty.isResettable();
+ if (aliasProperty.type() < QVariant::UserType)
+ type = aliasProperty.type();
+
if (alias.count() == 3) {
QDeclarativeValueType *valueType = enginePrivate->valueTypes[aliasProperty.type()];
if (!valueType)
@@ -2802,6 +2997,11 @@ bool QDeclarativeCompiler::compileAlias(QMetaObjectBuilder &builder,
aliasProperty = valueType->metaObject()->property(valueTypeIndex);
propIdx |= (valueTypeIndex << 16);
+
+ // update the property type
+ type = aliasProperty.type();
+ if (type >= QVariant::UserType)
+ type = 0;
}
if (aliasProperty.isEnumType())
@@ -2823,49 +3023,59 @@ bool QDeclarativeCompiler::compileAlias(QMetaObjectBuilder &builder,
if (typeName.endsWith('*'))
flags |= QML_ALIAS_FLAG_PTR;
- data.append((const char *)&idObject->idIndex, sizeof(idObject->idIndex));
- data.append((const char *)&propIdx, sizeof(propIdx));
- data.append((const char *)&flags, sizeof(flags));
+ QDeclarativeVMEMetaData::AliasData aliasData = { idObject->idIndex, propIdx, flags };
+
+ typedef QDeclarativeVMEMetaData VMD;
+ VMD *vmd = (QDeclarativeVMEMetaData *)data.data();
+ *(vmd->aliasData() + aliasIndex) = aliasData;
+
+ prop.nameRef = builder.newString(prop.name.utf8length());
+ prop.resolvedCustomTypeName = pool->NewByteArray(typeName);
+ prop.typeRef = builder.newString(typeName.length());
+
+ int propertyFlags = 0;
+ if (writable)
+ propertyFlags |= QFastMetaBuilder::Writable;
+ if (resettable)
+ propertyFlags |= QFastMetaBuilder::Resettable;
+
+ builder.setProperty(propIndex, prop.nameRef, prop.typeRef, (QMetaType::Type)type,
+ (QFastMetaBuilder::PropertyFlag)propertyFlags,
+ propIndex);
- builder.addSignal(prop.name + "Changed()");
- QMetaPropertyBuilder propBuilder =
- builder.addProperty(prop.name, typeName.constData(), builder.methodCount() - 1);
- propBuilder.setWritable(writable);
- propBuilder.setResettable(resettable);
return true;
}
-bool QDeclarativeCompiler::buildBinding(QDeclarativeParser::Value *value,
- QDeclarativeParser::Property *prop,
- const BindingContext &ctxt)
+bool QDeclarativeCompiler::buildBinding(QDeclarativeScript::Value *value,
+ QDeclarativeScript::Property *prop,
+ const BindingContext &ctxt)
{
Q_ASSERT(prop->index != -1);
Q_ASSERT(prop->parent);
Q_ASSERT(prop->parent->metaObject());
- QMetaProperty mp = prop->parent->metaObject()->property(prop->index);
- if (!mp.isWritable() && !QDeclarativeMetaType::isList(prop->type))
- COMPILE_EXCEPTION(prop, tr("Invalid property assignment: \"%1\" is a read-only property").arg(QString::fromUtf8(prop->name)));
+ if (!prop->core.isWritable() && !prop->core.isQList())
+ COMPILE_EXCEPTION(prop, tr("Invalid property assignment: \"%1\" is a read-only property").arg(prop->name().toString()));
- BindingReference reference;
- reference.expression = value->value;
- reference.property = prop;
- reference.value = value;
- reference.bindingContext = ctxt;
+ BindingReference *reference = pool->New<BindingReference>();
+ reference->expression = value->value;
+ reference->property = prop;
+ reference->value = value;
+ reference->bindingContext = ctxt;
addBindingReference(reference);
return true;
}
-void QDeclarativeCompiler::genBindingAssignment(QDeclarativeParser::Value *binding,
- QDeclarativeParser::Property *prop,
- QDeclarativeParser::Object *obj,
- QDeclarativeParser::Property *valueTypeProperty)
+void QDeclarativeCompiler::genBindingAssignment(QDeclarativeScript::Value *binding,
+ QDeclarativeScript::Property *prop,
+ QDeclarativeScript::Object *obj,
+ QDeclarativeScript::Property *valueTypeProperty)
{
Q_UNUSED(obj);
- Q_ASSERT(compileState.bindings.contains(binding));
+ Q_ASSERT(binding->bindingReference);
- const BindingReference &ref = compileState.bindings.value(binding);
+ const BindingReference &ref = *binding->bindingReference;
if (ref.dataType == BindingReference::V4) {
QDeclarativeInstruction store;
store.setType(QDeclarativeInstruction::StoreV4Binding);
@@ -2921,22 +3131,20 @@ void QDeclarativeCompiler::genBindingAssignment(QDeclarativeParser::Value *bindi
int QDeclarativeCompiler::genContextCache()
{
- if (compileState.ids.count() == 0)
+ if (compileState->ids.count() == 0)
return -1;
QDeclarativeIntegerCache *cache = new QDeclarativeIntegerCache();
-
- for (QHash<QString, QDeclarativeParser::Object *>::ConstIterator iter = compileState.ids.begin();
- iter != compileState.ids.end();
- ++iter)
- cache->add(iter.key(), (*iter)->idIndex);
+ cache->reserve(compileState->ids.count());
+ for (Object *o = compileState->ids.first(); o; o = compileState->ids.next(o))
+ cache->add(o->id, o->idIndex);
output->contextCaches.append(cache);
return output->contextCaches.count() - 1;
}
-int QDeclarativeCompiler::genValueTypeData(QDeclarativeParser::Property *valueTypeProp,
- QDeclarativeParser::Property *prop)
+int QDeclarativeCompiler::genValueTypeData(QDeclarativeScript::Property *valueTypeProp,
+ QDeclarativeScript::Property *prop)
{
typedef QDeclarativePropertyPrivate QDPP;
QByteArray data = QDPP::saveValueType(prop->parent->metaObject(), prop->index,
@@ -2946,7 +3154,7 @@ int QDeclarativeCompiler::genValueTypeData(QDeclarativeParser::Property *valueTy
return output->indexForByteArray(data);
}
-int QDeclarativeCompiler::genPropertyData(QDeclarativeParser::Property *prop)
+int QDeclarativeCompiler::genPropertyData(QDeclarativeScript::Property *prop)
{
typedef QDeclarativePropertyPrivate QDPP;
QByteArray data = QDPP::saveProperty(prop->parent->metaObject(), prop->index, engine);
@@ -2956,27 +3164,25 @@ int QDeclarativeCompiler::genPropertyData(QDeclarativeParser::Property *prop)
bool QDeclarativeCompiler::completeComponentBuild()
{
- componentStat.ids = compileState.ids.count();
+ if (componentStats)
+ componentStats->componentStat.ids = compileState->ids.count();
- for (int ii = 0; ii < compileState.aliasingObjects.count(); ++ii) {
- QDeclarativeParser::Object *aliasObject = compileState.aliasingObjects.at(ii);
+ for (Object *aliasObject = compileState->aliasingObjects.first(); aliasObject;
+ aliasObject = compileState->aliasingObjects.next(aliasObject))
COMPILE_CHECK(buildDynamicMeta(aliasObject, ResolveAliases));
- }
- QDeclarativeV4Compiler::Expression expr;
- expr.component = compileState.root;
- expr.ids = compileState.ids;
+ QDeclarativeV4Compiler::Expression expr(unit->imports());
+ expr.component = compileState->root;
+ expr.ids = &compileState->ids;
expr.importCache = output->importCache;
- expr.imports = unit->imports();
QDeclarativeV4Compiler bindingCompiler;
QList<BindingReference*> sharedBindings;
- for (QHash<QDeclarativeParser::Value*,BindingReference>::Iterator iter = compileState.bindings.begin();
- iter != compileState.bindings.end(); ++iter) {
+ for (BindingReference *b = compileState->bindings.first(); b; b = b->nextReference) {
- BindingReference &binding = *iter;
+ BindingReference &binding = *b;
// ### We don't currently optimize for bindings on alias's - because
// of the solution to QTBUG-13719
@@ -2989,7 +3195,8 @@ bool QDeclarativeCompiler::completeComponentBuild()
if (index != -1) {
binding.dataType = BindingReference::V4;
binding.compiledIndex = index;
- componentStat.optimizedBindings.append(iter.key()->location);
+ if (componentStats)
+ componentStats->componentStat.optimizedBindings.append(b->value->location);
continue;
}
}
@@ -2998,19 +3205,20 @@ bool QDeclarativeCompiler::completeComponentBuild()
QString expression = binding.expression.asScript();
QDeclarativeRewrite::RewriteBinding rewriteBinding;
- rewriteBinding.setName('$'+binding.property->name);
+ rewriteBinding.setName(QLatin1Char('$')+binding.property->name().toString());
bool isSharable = false;
binding.rewrittenExpression = rewriteBinding(binding.expression.asAST(), expression, &isSharable);
if (isSharable && !binding.property->isAlias /* See above re alias */ &&
binding.property->type != qMetaTypeId<QDeclarativeBinding*>()) {
binding.dataType = BindingReference::V8;
- sharedBindings.append(&iter.value());
+ sharedBindings.append(b);
} else {
binding.dataType = BindingReference::QtScript;
}
- componentStat.scriptBindings.append(iter.key()->location);
+ if (componentStats)
+ componentStats->componentStat.scriptBindings.append(b->value->location);
}
if (!sharedBindings.isEmpty()) {
@@ -3029,7 +3237,7 @@ bool QDeclarativeCompiler::completeComponentBuild()
QString functionArray(QLatin1String("["));
for (int ii = 0; ii < sharedBindings.count(); ++ii) {
BindingReference *reference = sharedBindings.at(ii);
- QDeclarativeParser::Value *value = reference->value;
+ QDeclarativeScript::Value *value = reference->value;
const QString &expression = reference->rewrittenExpression;
if (ii != 0) functionArray += QLatin1String(",");
@@ -3044,14 +3252,14 @@ bool QDeclarativeCompiler::completeComponentBuild()
}
functionArray += QLatin1String("]");
- compileState.v8BindingProgram = functionArray;
- compileState.v8BindingProgramLine = startLineNumber;
- compileState.v8BindingProgramIndex = output->v8bindings.count();
+ compileState->v8BindingProgram = functionArray;
+ compileState->v8BindingProgramLine = startLineNumber;
+ compileState->v8BindingProgramIndex = output->v8bindings.count();
output->v8bindings.append(v8::Persistent<v8::Array>());
}
if (bindingCompiler.isValid())
- compileState.compiledBindingData = bindingCompiler.program();
+ compileState->compiledBindingData = bindingCompiler.program();
saveComponentState();
@@ -3060,9 +3268,10 @@ bool QDeclarativeCompiler::completeComponentBuild()
void QDeclarativeCompiler::dumpStats()
{
+ Q_ASSERT(componentStats);
qWarning().nospace() << "QML Document: " << output->url.toString();
- for (int ii = 0; ii < savedComponentStats.count(); ++ii) {
- const ComponentStat &stat = savedComponentStats.at(ii);
+ for (int ii = 0; ii < componentStats->savedComponentStats.count(); ++ii) {
+ const ComponentStat &stat = componentStats->savedComponentStats.at(ii);
qWarning().nospace() << " Component Line " << stat.lineNumber;
qWarning().nospace() << " Total Objects: " << stat.objects;
qWarning().nospace() << " IDs Used: " << stat.ids;
@@ -3111,7 +3320,7 @@ void QDeclarativeCompiler::dumpStats()
Returns true if from can be assigned to a (QObject) property of type
to.
*/
-bool QDeclarativeCompiler::canCoerce(int to, QDeclarativeParser::Object *from)
+bool QDeclarativeCompiler::canCoerce(int to, QDeclarativeScript::Object *from)
{
const QMetaObject *toMo =
enginePrivate->rawMetaObjectForType(to);
@@ -3125,7 +3334,20 @@ bool QDeclarativeCompiler::canCoerce(int to, QDeclarativeParser::Object *from)
return false;
}
-QDeclarativeType *QDeclarativeCompiler::toQmlType(QDeclarativeParser::Object *from)
+/*!
+ Returns the element name, as written in the QML file, for o.
+*/
+QString QDeclarativeCompiler::elementName(QDeclarativeScript::Object *o)
+{
+ Q_ASSERT(o);
+ if (o->type != -1) {
+ return output->types.at(o->type).className;
+ } else {
+ return QString();
+ }
+}
+
+QDeclarativeType *QDeclarativeCompiler::toQmlType(QDeclarativeScript::Object *from)
{
// ### Optimize
const QMetaObject *mo = from->metatype;
@@ -3137,7 +3359,7 @@ QDeclarativeType *QDeclarativeCompiler::toQmlType(QDeclarativeParser::Object *fr
return type;
}
-QStringList QDeclarativeCompiler::deferredProperties(QDeclarativeParser::Object *obj)
+QStringList QDeclarativeCompiler::deferredProperties(QDeclarativeScript::Object *obj)
{
const QMetaObject *mo = obj->metatype;
@@ -3150,74 +3372,108 @@ QStringList QDeclarativeCompiler::deferredProperties(QDeclarativeParser::Object
return rv;
}
-// This code must match the semantics of QDeclarativePropertyPrivate::findSignalByName
-int QDeclarativeCompiler::indexOfSignal(QDeclarativeParser::Object *object, const QByteArray &name,
- bool *notInRevision)
+QDeclarativePropertyCache::Data *
+QDeclarativeCompiler::property(QDeclarativeScript::Object *object, int index)
{
- if (notInRevision) *notInRevision = false;
+ QDeclarativePropertyCache *cache = 0;
+
+ if (object->synthCache)
+ cache = object->synthCache;
+ else if (object->type != -1)
+ cache = output->types[object->type].createPropertyCache(engine);
+ else
+ cache = QDeclarativeEnginePrivate::get(engine)->cache(object->metaObject());
- if (object->synthCache || (object->type != -1 && output->types.at(object->type).propertyCache())) {
- // XXX fromUtf8
- QString strName(QString::fromUtf8(name));
- QDeclarativePropertyCache *cache =
- object->synthCache?object->synthCache:output->types.at(object->type).propertyCache();
+ return cache->property(index);
+}
- QDeclarativePropertyCache::Data *d = cache->property(strName);
- if (notInRevision) *notInRevision = false;
+QDeclarativePropertyCache::Data *
+QDeclarativeCompiler::property(QDeclarativeScript::Object *object, const QHashedStringRef &name, bool *notInRevision)
+{
+ if (notInRevision) *notInRevision = false;
- while (d && !(d->isFunction()))
- d = cache->overrideData(d);
+ QDeclarativePropertyCache *cache = 0;
- if (d && !cache->isAllowedInRevision(d)) {
- if (notInRevision) *notInRevision = true;
- return -1;
- } else if (d) {
- return d->coreIndex;
- }
+ if (object->synthCache)
+ cache = object->synthCache;
+ else if (object->type != -1)
+ cache = output->types[object->type].createPropertyCache(engine);
+ else
+ cache = QDeclarativeEnginePrivate::get(engine)->cache(object->metaObject());
- if (name.endsWith("Changed")) {
- QByteArray propName = name.mid(0, name.length() - 7);
+ QDeclarativePropertyCache::Data *d = cache->property(name);
- int propIndex = indexOfProperty(object, propName, notInRevision);
- if (propIndex != -1) {
- d = cache->property(propIndex);
- return d->notifyIndex;
- }
- }
+ // Find the first property
+ while (d && d->isFunction())
+ d = cache->overrideData(d);
- return -1;
+ if (d && !cache->isAllowedInRevision(d)) {
+ if (notInRevision) *notInRevision = true;
+ return 0;
} else {
- return QDeclarativePropertyPrivate::findSignalByName(object->metaObject(), name).methodIndex();
+ return d;
}
-
}
-int QDeclarativeCompiler::indexOfProperty(QDeclarativeParser::Object *object, const QByteArray &name,
- bool *notInRevision)
+// This code must match the semantics of QDeclarativePropertyPrivate::findSignalByName
+QDeclarativePropertyCache::Data *
+QDeclarativeCompiler::signal(QDeclarativeScript::Object *object, const QHashedStringRef &name, bool *notInRevision)
{
if (notInRevision) *notInRevision = false;
- if (object->synthCache || (object->type != -1 && output->types.at(object->type).propertyCache())) {
- // XXX fromUtf8
- QString strName(QString::fromUtf8(name));
- QDeclarativePropertyCache *cache =
- object->synthCache?object->synthCache:output->types.at(object->type).propertyCache();
+ QDeclarativePropertyCache *cache = 0;
- QDeclarativePropertyCache::Data *d = cache->property(strName);
- // Find the first property
- while (d && d->isFunction())
- d = cache->overrideData(d);
+ if (object->synthCache)
+ cache = object->synthCache;
+ else if (object->type != -1)
+ cache = output->types[object->type].createPropertyCache(engine);
+ else
+ cache = QDeclarativeEnginePrivate::get(engine)->cache(object->metaObject());
- if (d && !cache->isAllowedInRevision(d)) {
- if (notInRevision) *notInRevision = true;
- return -1;
- } else {
- return d?d->coreIndex:-1;
- }
- } else {
- const QMetaObject *mo = object->metaObject();
- return mo->indexOfProperty(name.constData());
+
+ QDeclarativePropertyCache::Data *d = cache->property(name);
+ if (notInRevision) *notInRevision = false;
+
+ while (d && !(d->isFunction()))
+ d = cache->overrideData(d);
+
+ if (d && !cache->isAllowedInRevision(d)) {
+ if (notInRevision) *notInRevision = true;
+ return 0;
+ } else if (d) {
+ return d;
+ }
+
+ if (name.endsWith(Changed_string)) {
+ QHashedStringRef propName = name.mid(0, name.length() - Changed_string.length());
+
+ d = property(object, propName, notInRevision);
+ if (d)
+ return cache->method(d->notifyIndex);
}
+
+ return 0;
+}
+
+// This code must match the semantics of QDeclarativePropertyPrivate::findSignalByName
+int QDeclarativeCompiler::indexOfSignal(QDeclarativeScript::Object *object, const QString &name,
+ bool *notInRevision)
+{
+ QDeclarativePropertyCache::Data *d = signal(object, QStringRef(&name), notInRevision);
+ return d?d->coreIndex:-1;
+}
+
+int QDeclarativeCompiler::indexOfProperty(QDeclarativeScript::Object *object, const QString &name,
+ bool *notInRevision)
+{
+ return indexOfProperty(object, QStringRef(&name), notInRevision);
+}
+
+int QDeclarativeCompiler::indexOfProperty(QDeclarativeScript::Object *object, const QHashedStringRef &name,
+ bool *notInRevision)
+{
+ QDeclarativePropertyCache::Data *d = property(object, name, notInRevision);
+ return d?d->coreIndex:-1;
}
QT_END_NAMESPACE