diff options
-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" |