diff options
author | Simon Hausmann <[email protected]> | 2013-10-25 14:23:39 +0200 |
---|---|---|
committer | The Qt Project <[email protected]> | 2013-10-31 16:00:58 +0100 |
commit | 71338b4b2f01268759f7ac6b3eff5abb17420a7c (patch) | |
tree | 9be8f7484e1a70e3d1d52c75f8bcf971448a3d44 /src/qml/compiler/qqmlcodegenerator.cpp | |
parent | 76684fd3edcdc8e120c67f82cbd0625bf9bcc0bb (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.cpp | 54 |
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; |