aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSimon Hausmann <simon.hausmann@digia.com>2013-09-12 16:53:32 +0200
committerThe Qt Project <gerrit-noreply@qt-project.org>2013-09-20 14:26:05 +0200
commit3ec5aae38e77d370d1a23efe4b924ee4762a2238 (patch)
treebff7f62c5daa35a2e045d87a0ea882d211d05c4e
parent6042327dee1f8dd912a86be16f4044d259c9b3e4 (diff)
[new compiler] Add support for id properties
Change-Id: Idb4a0ad06f6cbe5d040da075a8f43d067a27ebc4 Reviewed-by: Lars Knoll <lars.knoll@digia.com>
-rw-r--r--src/qml/compiler/qqmlcodegenerator.cpp45
-rw-r--r--src/qml/compiler/qqmlcodegenerator_p.h2
-rw-r--r--src/qml/qml/qqmlcompiler_p.h2
-rw-r--r--src/qml/qml/qqmlcomponent.cpp15
-rw-r--r--src/qml/qml/qqmlobjectcreator.cpp7
-rw-r--r--src/qml/qml/qqmlobjectcreator_p.h4
-rw-r--r--src/qml/qml/qqmltypeloader.cpp8
7 files changed, 80 insertions, 3 deletions
diff --git a/src/qml/compiler/qqmlcodegenerator.cpp b/src/qml/compiler/qqmlcodegenerator.cpp
index b875067620..2bd00f2a1f 100644
--- a/src/qml/compiler/qqmlcodegenerator.cpp
+++ b/src/qml/compiler/qqmlcodegenerator.cpp
@@ -705,6 +705,12 @@ void QQmlCodeGenerator::appendBinding(const AST::SourceLocation &nameLocation, i
{
if (!sanityCheckPropertyName(nameLocation, propertyNameIndex))
return;
+
+ if (stringAt(propertyNameIndex) == QStringLiteral("id")) {
+ setId(value);
+ return;
+ }
+
Binding *binding = New<Binding>();
binding->propertyNameIndex = propertyNameIndex;
setBindingValue(binding, value);
@@ -722,6 +728,45 @@ void QQmlCodeGenerator::appendBinding(const AST::SourceLocation &nameLocation, i
_object->bindings->append(binding);
}
+bool QQmlCodeGenerator::setId(AST::Statement *value)
+{
+ AST::SourceLocation loc = value->firstSourceLocation();
+ QStringRef str;
+
+ if (AST::ExpressionStatement *stmt = AST::cast<AST::ExpressionStatement *>(value))
+ if (AST::StringLiteral *lit = AST::cast<AST::StringLiteral *>(stmt->expression))
+ str = lit->value;
+
+ if (str.isEmpty())
+ str = asStringRef(value);
+
+ if (str.isEmpty())
+ COMPILE_EXCEPTION(loc, tr( "Invalid empty ID"));
+
+ QChar ch = str.at(0);
+ if (ch.isLetter() && !ch.isLower())
+ COMPILE_EXCEPTION(loc, tr( "IDs cannot start with an uppercase letter"));
+
+ QChar u(QLatin1Char('_'));
+ if (!ch.isLetter() && ch != u)
+ COMPILE_EXCEPTION(loc, tr( "IDs must start with a letter or underscore"));
+
+ for (int ii = 1; ii < str.count(); ++ii) {
+ ch = str.at(ii);
+ if (!ch.isLetterOrNumber() && ch != u)
+ COMPILE_EXCEPTION(loc, tr( "IDs must contain only letters, numbers, and underscores"));
+ }
+
+#if 0 // ###
+ if (enginePrivate->v8engine()->illegalNames().contains(str))
+ COMPILE_EXCEPTION(v, tr( "ID illegally masks global JavaScript property"));
+#endif
+
+ _object->idIndex = registerString(str.toString());
+
+ return true;
+}
+
AST::UiQualifiedId *QQmlCodeGenerator::resolveQualifiedId(AST::UiQualifiedId *name, QmlObject **object)
{
*object = _object;
diff --git a/src/qml/compiler/qqmlcodegenerator_p.h b/src/qml/compiler/qqmlcodegenerator_p.h
index 5344dc1535..3e14a32bce 100644
--- a/src/qml/compiler/qqmlcodegenerator_p.h
+++ b/src/qml/compiler/qqmlcodegenerator_p.h
@@ -220,6 +220,8 @@ public:
void appendBinding(const AST::SourceLocation &nameLocation, int propertyNameIndex, AST::Statement *value);
void appendBinding(const AST::SourceLocation &nameLocation, int propertyNameIndex, int objectIndex);
+ bool setId(AST::Statement *value);
+
// resolves qualified name (font.pixelSize for example) and returns the last name along
// with the object any right-hand-side of a binding should apply to.
AST::UiQualifiedId *resolveQualifiedId(AST::UiQualifiedId *name, QmlObject **object);
diff --git a/src/qml/qml/qqmlcompiler_p.h b/src/qml/qml/qqmlcompiler_p.h
index ac304278ab..52d6fe210c 100644
--- a/src/qml/qml/qqmlcompiler_p.h
+++ b/src/qml/qml/qqmlcompiler_p.h
@@ -140,6 +140,8 @@ public:
// --- new compiler
QV4::CompiledData::CompilationUnit *compilationUnit;
QV4::CompiledData::QmlUnit *qmlUnit;
+ // ### sub-context support
+ QHash<int, int> objectIndexToId;
// ---
struct Instruction {
diff --git a/src/qml/qml/qqmlcomponent.cpp b/src/qml/qml/qqmlcomponent.cpp
index 955c940a9d..2063c5bb25 100644
--- a/src/qml/qml/qqmlcomponent.cpp
+++ b/src/qml/qml/qqmlcomponent.cpp
@@ -900,8 +900,21 @@ QQmlComponentPrivate::beginCreate(QQmlContextData *context)
if (cc->compilationUnit && !cc->compilationUnit->engine)
cc->compilationUnit->linkToEngine(v4);
+ // ### sub-contexts
+ QVector<QQmlContextData::ObjectIdMapping> mapping(cc->objectIndexToId.count());
+ for (QHash<int, int>::ConstIterator it = cc->objectIndexToId.constBegin(), end = cc->objectIndexToId.constEnd();
+ it != end; ++it) {
+ const QV4::CompiledData::Object *obj = cc->qmlUnit->objectAt(it.key());
+
+ QQmlContextData::ObjectIdMapping m;
+ m.id = it.value();
+ m.name = cc->qmlUnit->header.stringAt(obj->idIndex);
+ mapping[m.id] = m;
+ }
+ context->setIdPropertyData(mapping);
+
state.creator = new QmlObjectCreator(context, cc->qmlUnit, cc->compilationUnit, cc->resolvedTypes,
- cc->propertyCaches, cc->datas);
+ cc->propertyCaches, cc->datas, cc->objectIndexToId);
rv = state.creator->create();
if (!rv)
state.errors = state.creator->errors;
diff --git a/src/qml/qml/qqmlobjectcreator.cpp b/src/qml/qml/qqmlobjectcreator.cpp
index a92bbeda9e..def5181f2d 100644
--- a/src/qml/qml/qqmlobjectcreator.cpp
+++ b/src/qml/qml/qqmlobjectcreator.cpp
@@ -446,7 +446,7 @@ QmlObjectCreator::QmlObjectCreator(QQmlContextData *contextData, const QV4::Comp
const QV4::CompiledData::CompilationUnit *jsUnit,
const QHash<int, QQmlCompiledData::TypeReference> &resolvedTypes,
const QList<QQmlPropertyCache*> &propertyCaches,
- const QList<QByteArray> &vmeMetaObjectData)
+ const QList<QByteArray> &vmeMetaObjectData, const QHash<int, int> &objectIndexToId)
: engine(contextData->engine)
, unit(qmlUnit)
, jsUnit(jsUnit)
@@ -454,6 +454,7 @@ QmlObjectCreator::QmlObjectCreator(QQmlContextData *contextData, const QV4::Comp
, resolvedTypes(resolvedTypes)
, propertyCaches(propertyCaches)
, vmeMetaObjectData(vmeMetaObjectData)
+ , objectIndexToId(objectIndexToId)
, _qobject(0)
, _compiledObject(0)
, _ddata(0)
@@ -588,6 +589,10 @@ QObject *QmlObjectCreator::create(int index, QObject *parent)
context->addObject(instance);
+ QHash<int, int>::ConstIterator idEntry = objectIndexToId.find(index);
+ if (idEntry != objectIndexToId.constEnd())
+ context->setIdProperty(idEntry.value(), instance);
+
populateInstance(index, instance, cache);
return instance;
diff --git a/src/qml/qml/qqmlobjectcreator_p.h b/src/qml/qml/qqmlobjectcreator_p.h
index 509fda30e7..9891566a00 100644
--- a/src/qml/qml/qqmlobjectcreator_p.h
+++ b/src/qml/qml/qqmlobjectcreator_p.h
@@ -78,7 +78,8 @@ class QmlObjectCreator
Q_DECLARE_TR_FUNCTIONS(QmlObjectCreator)
public:
QmlObjectCreator(QQmlContextData *contextData, const QV4::CompiledData::QmlUnit *qmlUnit, const QV4::CompiledData::CompilationUnit *jsUnit,
- const QHash<int, QQmlCompiledData::TypeReference> &resolvedTypes, const QList<QQmlPropertyCache *> &propertyCaches, const QList<QByteArray> &vmeMetaObjectData);
+ const QHash<int, QQmlCompiledData::TypeReference> &resolvedTypes, const QList<QQmlPropertyCache *> &propertyCaches, const QList<QByteArray> &vmeMetaObjectData,
+ const QHash<int, int> &objectIndexToId);
QObject *create(QObject *parent = 0)
{ return create(unit->indexOfRootObject, parent); }
@@ -109,6 +110,7 @@ private:
const QHash<int, QQmlCompiledData::TypeReference> resolvedTypes;
const QList<QQmlPropertyCache *> propertyCaches;
const QList<QByteArray> vmeMetaObjectData;
+ const QHash<int, int> &objectIndexToId;
QObject *_qobject;
const QV4::CompiledData::Object *_compiledObject;
diff --git a/src/qml/qml/qqmltypeloader.cpp b/src/qml/qml/qqmltypeloader.cpp
index 652018dd4b..db68631bbf 100644
--- a/src/qml/qml/qqmltypeloader.cpp
+++ b/src/qml/qml/qqmltypeloader.cpp
@@ -2234,6 +2234,14 @@ void QQmlTypeData::compile()
m_compiledData->propertyCaches << propertyCache;
}
+ // ### support sub-contexts
+ for (quint32 i = 0; i < qmlUnit->nObjects; ++i) {
+ const QV4::CompiledData::Object *obj = qmlUnit->objectAt(i);
+ const QString &id = qmlUnit->header.stringAt(obj->idIndex);
+ if (!id.isEmpty())
+ m_compiledData->objectIndexToId.insert(i, m_compiledData->objectIndexToId.count());
+ }
+
if (!errors.isEmpty()) {
setError(errors);
m_compiledData->release();