diff options
author | Simon Hausmann <simon.hausmann@digia.com> | 2013-11-19 00:31:04 +0100 |
---|---|---|
committer | The Qt Project <gerrit-noreply@qt-project.org> | 2013-11-19 07:57:45 +0100 |
commit | cac9989643d54b15ea0b8e53889336b429e4504d (patch) | |
tree | 35211bbb4829385c2c91d4296b2a9d4e5929030b | |
parent | da31479ee237a40ed03bcaf1352f00d33d1f325c (diff) |
Fix failing assertion when trying to assign to an id referenced QML object
References to id addressed QML objects are member expressions, which are unlike
other member expressions by not being lvalues. Handle this correctly.
Task-Number: QTBUG-34890
Change-Id: Ied6230edbc561128ad36bf0d1a1918185204deec
Reviewed-by: Lars Knoll <lars.knoll@digia.com>
-rw-r--r-- | src/qml/compiler/qqmlcodegenerator.cpp | 1 | ||||
-rw-r--r-- | src/qml/compiler/qv4codegen.cpp | 7 | ||||
-rw-r--r-- | src/qml/compiler/qv4codegen_p.h | 1 | ||||
-rw-r--r-- | src/qml/compiler/qv4jsir_p.h | 2 | ||||
-rw-r--r-- | src/qml/qml/qqmlcompiler.cpp | 5 | ||||
-rw-r--r-- | tests/auto/qml/qqmlecmascript/data/idAsLValue.qml | 7 | ||||
-rw-r--r-- | tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp | 11 |
7 files changed, 30 insertions, 4 deletions
diff --git a/src/qml/compiler/qqmlcodegenerator.cpp b/src/qml/compiler/qqmlcodegenerator.cpp index 2b3cb80acb..c16dd5daea 100644 --- a/src/qml/compiler/qqmlcodegenerator.cpp +++ b/src/qml/compiler/qqmlcodegenerator.cpp @@ -1211,6 +1211,7 @@ JSCodeGen::JSCodeGen(QQmlEnginePrivate *enginePrivate, const QString &fileName, { _module = jsModule; _module->setFileName(fileName); + _fileNameIsUrl = true; } void JSCodeGen::beginContextScope(const JSCodeGen::ObjectIdMapping &objectIds, QQmlPropertyCache *contextObject) diff --git a/src/qml/compiler/qv4codegen.cpp b/src/qml/compiler/qv4codegen.cpp index 68c46f5677..893abc9659 100644 --- a/src/qml/compiler/qv4codegen.cpp +++ b/src/qml/compiler/qv4codegen.cpp @@ -418,6 +418,7 @@ Codegen::Codegen(bool strict) , _labelledStatement(0) , _scopeAndFinally(0) , _strictMode(strict) + , _fileNameIsUrl(false) , hasError(false) { } @@ -1182,7 +1183,7 @@ bool Codegen::visit(BinaryExpression *ast) if (throwSyntaxErrorOnEvalOrArgumentsInStrictMode(left, ast->left->lastSourceLocation())) return false; V4IR::Expr* right = *expression(ast->right); - if (! (left->asTemp() || left->asName() || left->asSubscript() || left->asMember())) { + if (!left->isLValue()) { throwReferenceError(ast->operatorToken, QStringLiteral("left-hand side of assignment operator is not an lvalue")); return false; } @@ -2850,7 +2851,7 @@ void Codegen::throwSyntaxError(const SourceLocation &loc, const QString &detail) hasError = true; QQmlError error; - error.setUrl(QUrl::fromLocalFile(_module->fileName)); + error.setUrl(_fileNameIsUrl ? QUrl(_module->fileName) : QUrl::fromLocalFile(_module->fileName)); error.setDescription(detail); error.setLine(loc.startLine); error.setColumn(loc.startColumn); @@ -2864,7 +2865,7 @@ void Codegen::throwReferenceError(const SourceLocation &loc, const QString &deta hasError = true; QQmlError error; - error.setUrl(QUrl::fromLocalFile(_module->fileName)); + error.setUrl(_fileNameIsUrl ? QUrl(_module->fileName) : QUrl::fromLocalFile(_module->fileName)); error.setDescription(detail); error.setLine(loc.startLine); error.setColumn(loc.startColumn); diff --git a/src/qml/compiler/qv4codegen_p.h b/src/qml/compiler/qv4codegen_p.h index 0bac996349..de22e8904b 100644 --- a/src/qml/compiler/qv4codegen_p.h +++ b/src/qml/compiler/qv4codegen_p.h @@ -460,6 +460,7 @@ protected: QStack<V4IR::BasicBlock *> _exceptionHandlers; bool _strictMode; + bool _fileNameIsUrl; bool hasError; QList<QQmlError> _errors; diff --git a/src/qml/compiler/qv4jsir_p.h b/src/qml/compiler/qv4jsir_p.h index f4b8b15984..9a1bd87a1d 100644 --- a/src/qml/compiler/qv4jsir_p.h +++ b/src/qml/compiler/qv4jsir_p.h @@ -558,7 +558,7 @@ struct Member: Expr { } virtual void accept(ExprVisitor *v) { v->visitMember(this); } - virtual bool isLValue() { return true; } + virtual bool isLValue() { return type != MemberOfQmlContext; } virtual Member *asMember() { return this; } virtual void dump(QTextStream &out) const; diff --git a/src/qml/qml/qqmlcompiler.cpp b/src/qml/qml/qqmlcompiler.cpp index f9dd0b65a3..7b33849e67 100644 --- a/src/qml/qml/qqmlcompiler.cpp +++ b/src/qml/qml/qqmlcompiler.cpp @@ -3682,6 +3682,11 @@ bool QQmlCompiler::completeComponentBuild() jsCodeGen.beginObjectScope(scopeObject->metatype); cd->runtimeFunctionIndices = jsCodeGen.generateJSCodeForFunctionsAndBindings(cd->functionsToCompile, expressionNames); + QList<QQmlError> errors = jsCodeGen.errors(); + if (!errors.isEmpty()) { + exceptions << errors; + return false; + } foreach (const QQmlCompilerTypes::ComponentCompileState::CompiledMetaMethod &cmm, cd->compiledMetaMethods) { typedef QQmlVMEMetaData VMD; diff --git a/tests/auto/qml/qqmlecmascript/data/idAsLValue.qml b/tests/auto/qml/qqmlecmascript/data/idAsLValue.qml new file mode 100644 index 0000000000..1035f844b4 --- /dev/null +++ b/tests/auto/qml/qqmlecmascript/data/idAsLValue.qml @@ -0,0 +1,7 @@ +import QtQml 2.0 +QtObject { + id: root + Component.onCompleted: { + root = "hello" + } +} diff --git a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp index 6af8863de7..6e1e606fb8 100644 --- a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp +++ b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp @@ -317,6 +317,7 @@ private slots: void setPropertyOnInvalid(); void miscTypeTest(); void stackLimits(); + void idsAsLValues(); private: // static void propertyVarWeakRefCallback(v8::Persistent<v8::Value> object, void* parameter); @@ -7466,6 +7467,16 @@ void tst_qqmlecmascript::stackLimits() engine.evaluate(QStringLiteral("function foo() {foo();} try {foo()} catch(e) { }")); } +void tst_qqmlecmascript::idsAsLValues() +{ + QString err = QString(QLatin1String("%1:5 left-hand side of assignment operator is not an lvalue\n")).arg(testFileUrl("idAsLValue.qml").toString()); + QQmlComponent component(&engine, testFileUrl("idAsLValue.qml")); + QTest::ignoreMessage(QtWarningMsg, "QQmlComponent: Component is not ready"); + MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create()); + QVERIFY(!object); + QCOMPARE(component.errorString(), err); +} + QTEST_MAIN(tst_qqmlecmascript) #include "tst_qqmlecmascript.moc" |