aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/compiler/qqmlcodegenerator.cpp
diff options
context:
space:
mode:
authorSimon Hausmann <[email protected]>2013-10-25 14:23:39 +0200
committerThe Qt Project <[email protected]>2013-10-31 16:00:58 +0100
commit71338b4b2f01268759f7ac6b3eff5abb17420a7c (patch)
tree9be8f7484e1a70e3d1d52c75f8bcf971448a3d44 /src/qml/compiler/qqmlcodegenerator.cpp
parent76684fd3edcdc8e120c67f82cbd0625bf9bcc0bb (diff)
Resolve member expressions of QObject members
...when the base is a QObject property itself or an ID referenced object. This patch resolves for example the width property in a parent.width expression to be a per-index lookup at run-time. That requires the base ("parent") however to be a final property or come from an object where expected revision is known, i.e. a QML imported object (scope or context). Change-Id: Iaa1f57ace452da5e059c1d4e63b52b316e1a6b08 Reviewed-by: Lars Knoll <[email protected]>
Diffstat (limited to 'src/qml/compiler/qqmlcodegenerator.cpp')
-rw-r--r--src/qml/compiler/qqmlcodegenerator.cpp54
1 files changed, 50 insertions, 4 deletions
diff --git a/src/qml/compiler/qqmlcodegenerator.cpp b/src/qml/compiler/qqmlcodegenerator.cpp
index 7b1984fce0..5fefa61a7a 100644
--- a/src/qml/compiler/qqmlcodegenerator.cpp
+++ b/src/qml/compiler/qqmlcodegenerator.cpp
@@ -1198,8 +1198,9 @@ int QmlUnitGenerator::getStringId(const QString &str) const
return jsUnitGenerator->getStringId(str);
}
-JSCodeGen::JSCodeGen(const QString &fileName, const QString &sourceCode, V4IR::Module *jsModule, Engine *jsEngine, AST::UiProgram *qmlRoot, QQmlTypeNameCache *imports)
+JSCodeGen::JSCodeGen(QQmlEnginePrivate *enginePrivate, const QString &fileName, const QString &sourceCode, V4IR::Module *jsModule, Engine *jsEngine, AST::UiProgram *qmlRoot, QQmlTypeNameCache *imports)
: QQmlJS::Codegen(/*strict mode*/false)
+ , engine(enginePrivate)
, sourceCode(sourceCode)
, jsEngine(jsEngine)
, qmlRoot(qmlRoot)
@@ -1283,14 +1284,16 @@ QVector<int> JSCodeGen::generateJSCodeForFunctionsAndBindings(const QList<AST::N
return runtimeFunctionIndices;
}
-static QQmlPropertyData *lookupQmlCompliantProperty(QQmlPropertyCache *cache, const QString &name, bool *propertyExistsButForceNameLookup)
+static QQmlPropertyData *lookupQmlCompliantProperty(QQmlPropertyCache *cache, const QString &name, bool *propertyExistsButForceNameLookup = 0)
{
- *propertyExistsButForceNameLookup = false;
+ if (propertyExistsButForceNameLookup)
+ *propertyExistsButForceNameLookup = false;
QQmlPropertyData *pd = cache->property(name, /*object*/0, /*context*/0);
// Q_INVOKABLEs can't be FINAL, so we have to look them up at run-time
if (pd && pd->isFunction()) {
- *propertyExistsButForceNameLookup = true;
+ if (propertyExistsButForceNameLookup)
+ *propertyExistsButForceNameLookup = true;
pd = 0;
}
@@ -1300,6 +1303,49 @@ static QQmlPropertyData *lookupQmlCompliantProperty(QQmlPropertyCache *cache, co
return pd;
}
+V4IR::Expr *JSCodeGen::member(V4IR::Expr *base, const QString *name)
+{
+ V4IR::Member *baseAsMember = base->asMember();
+ if (baseAsMember) {
+ QQmlPropertyCache *cache = 0;
+
+ if (baseAsMember->type == V4IR::Member::MemberOfQObject
+ && baseAsMember->property->isQObject()) {
+
+ bool propertySuitable = baseAsMember->property->isFinal();
+
+ if (!propertySuitable) {
+ // Properties of the scope or context object do not need to be final, as we
+ // intend to find the version of a property available at compile time, not at run-time.
+ if (V4IR::Name *baseName = baseAsMember->base->asName())
+ propertySuitable = baseName->builtin == V4IR::Name::builtin_qml_scope_object || baseName->builtin == V4IR::Name::builtin_qml_context_object;
+ }
+
+ // Check if it's suitable for caching
+ if (propertySuitable)
+ cache = engine->propertyCacheForType(baseAsMember->property->propType);
+ } else if (baseAsMember->type == V4IR::Member::MemberByObjectId) {
+ // Similarly, properties of an id referenced object also don't need to be final, because
+ // we intend to find the version of a property available at compile time, not at run-time.
+ foreach (const IdMapping &mapping, _idObjects) {
+ if (baseAsMember->objectId == mapping.idIndex) {
+ cache = mapping.type;
+ break;
+ }
+ }
+ }
+
+ if (cache) {
+ if (QQmlPropertyData *pd = lookupQmlCompliantProperty(cache, *name)) {
+ const unsigned baseTemp = _block->newTemp();
+ move(_block->TEMP(baseTemp), base);
+ return _block->QML_QOBJECT_PROPERTY(_block->TEMP(baseTemp), name, pd);
+ }
+ }
+ }
+ return QQmlJS::Codegen::member(base, name);
+}
+
V4IR::Expr *JSCodeGen::fallbackNameLookup(const QString &name, int line, int col)
{
V4IR::Expr *result = 0;