diff options
author | Simon Hausmann <simon.hausmann@digia.com> | 2013-12-10 15:25:22 +0100 |
---|---|---|
committer | The Qt Project <gerrit-noreply@qt-project.org> | 2013-12-10 15:46:09 +0100 |
commit | 29b6d2e45c7434fccf2e6878630e62d5dcce38db (patch) | |
tree | d2d0ad7639c9863c00cdd8558d9663bea813c3f3 /src/qml/qml | |
parent | fb72bb3cf27d1f94760709aaab82e3524ae936f4 (diff) |
Fix broken Maroon game / regression in PropertyChanges {} element
Commit 0aadcf8077840068eb182269e9ed9c31ad12f45e that pre-compiles the
expressions in PropertyChanges {} introduced a regression in where the
evaluation context was incorrect and thus bindings would not be able to
access the correct properties. For example
PropertyChanges {
target: someObject
y: height / 2
}
Here height should be looked up in the context of "someObject", not of the
PropertyChanges element.
This patch introduces an auto-test that verifies that the lookup context is
correct and fixes the bug by disabling accelerated compile time property
lookups for binding expressions that are requested from a custom parser.
Change-Id: I5cb607d07211b453ddfc9928ccbf5f9ecec85575
Reviewed-by: Lars Knoll <lars.knoll@digia.com>
Diffstat (limited to 'src/qml/qml')
-rw-r--r-- | src/qml/qml/qqmlcompiler.cpp | 14 | ||||
-rw-r--r-- | src/qml/qml/qqmlcompiler_p.h | 9 | ||||
-rw-r--r-- | src/qml/qml/qqmltypeloader.cpp | 3 |
3 files changed, 16 insertions, 10 deletions
diff --git a/src/qml/qml/qqmlcompiler.cpp b/src/qml/qml/qqmlcompiler.cpp index 2b925b24ec..1e5f6bfa34 100644 --- a/src/qml/qml/qqmlcompiler.cpp +++ b/src/qml/qml/qqmlcompiler.cpp @@ -62,7 +62,6 @@ #include "qqmlglobal_p.h" #include "qqmlbinding_p.h" #include "qqmlabstracturlinterceptor_p.h" -#include "qqmlcodegenerator_p.h" #include <QDebug> #include <QPointF> @@ -2707,6 +2706,10 @@ int QQmlCompiler::bindingIdentifier(const QString &name, const Variant &value, c reference->value = 0; reference->bindingContext = ctxt; reference->bindingContext.owner++; + // Unfortunately this is required for example for PropertyChanges where the bindings + // will be executed in the dynamic scope of the target, so we can't resolve any lookups + // at run-time. + reference->disableLookupAcceleration = true; const int id = output->customParserBindings.count(); output->customParserBindings.append(0); // Filled in later. @@ -3684,9 +3687,12 @@ bool QQmlCompiler::completeComponentBuild() } ComponentCompileState::PerObjectCompileData *cd = &compileState->jsCompileData[b->bindingContext.object]; - cd->functionsToCompile.append(node); + QtQml::CompiledFunctionOrExpression f; + f.node = node; + f.name = binding.property->name().toString().prepend(QStringLiteral("expression for ")); + f.disableAcceleratedLookups = binding.disableLookupAcceleration; + cd->functionsToCompile.append(f); binding.compiledIndex = cd->functionsToCompile.count() - 1; - cd->expressionNames.insert(binding.compiledIndex, binding.property->name().toString().prepend(QStringLiteral("expression for "))); if (componentStats && b->value) componentStats->componentStat.scriptBindings.append(b->value->location); @@ -3719,7 +3725,7 @@ bool QQmlCompiler::completeComponentBuild() jsCodeGen.beginObjectScope(scopeObject->metatype); - cd->runtimeFunctionIndices = jsCodeGen.generateJSCodeForFunctionsAndBindings(cd->functionsToCompile, cd->expressionNames); + cd->runtimeFunctionIndices = jsCodeGen.generateJSCodeForFunctionsAndBindings(cd->functionsToCompile); QList<QQmlError> errors = jsCodeGen.errors(); if (!errors.isEmpty()) { exceptions << errors; diff --git a/src/qml/qml/qqmlcompiler_p.h b/src/qml/qml/qqmlcompiler_p.h index 75f404a7d5..516f6653ca 100644 --- a/src/qml/qml/qqmlcompiler_p.h +++ b/src/qml/qml/qqmlcompiler_p.h @@ -62,6 +62,7 @@ #include "qqmlpropertycache_p.h" #include "qqmltypenamecache_p.h" #include "qqmltypeloader_p.h" +#include <private/qqmlcodegenerator_p.h> #include "private/qv4identifier_p.h" #include <private/qqmljsastfwd_p.h> @@ -231,14 +232,15 @@ namespace QQmlCompilerTypes { struct JSBindingReference : public QQmlPool::Class, public BindingReference { - JSBindingReference() : nextReference(0) {} + JSBindingReference() : disableLookupAcceleration(false), nextReference(0) {} QQmlScript::Variant expression; QQmlScript::Property *property; QQmlScript::Value *value; int compiledIndex : 16; - int customParserBindingsIndex : 16; + int customParserBindingsIndex : 15; + int disableLookupAcceleration: 1; BindingContext bindingContext; @@ -319,10 +321,9 @@ namespace QQmlCompilerTypes { QList<CompiledMetaMethod> compiledMetaMethods; struct PerObjectCompileData { - QList<QQmlJS::AST::Node*> functionsToCompile; + QList<QtQml::CompiledFunctionOrExpression> functionsToCompile; QVector<int> runtimeFunctionIndices; QVector<CompiledMetaMethod> compiledMetaMethods; - QHash<int, QString> expressionNames; }; QHash<QQmlScript::Object *, PerObjectCompileData> jsCompileData; }; diff --git a/src/qml/qml/qqmltypeloader.cpp b/src/qml/qml/qqmltypeloader.cpp index 7d377af0f8..c9694da0df 100644 --- a/src/qml/qml/qqmltypeloader.cpp +++ b/src/qml/qml/qqmltypeloader.cpp @@ -2372,8 +2372,7 @@ void QQmlTypeData::compile() // Compile JS binding expressions and signal handlers JSCodeGen jsCodeGen(finalUrlString(), parsedQML->code, &parsedQML->jsModule, &parsedQML->jsParserEngine, parsedQML->program, m_compiledData->importCache); - QHash<int, QString> expressionNames; // ### TODO - const QVector<int> runtimeFunctionIndices = jsCodeGen.generateJSCodeForFunctionsAndBindings(parsedQML->functions, expressionNames); + const QVector<int> runtimeFunctionIndices = jsCodeGen.generateJSCodeForFunctionsAndBindings(parsedQML->functions); QV4::ExecutionEngine *v4 = QV8Engine::getV4(m_typeLoader->engine()); |