diff options
-rw-r--r-- | src/qml/compiler/qv4codegen.cpp | 7 | ||||
-rw-r--r-- | tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp | 24 |
2 files changed, 28 insertions, 3 deletions
diff --git a/src/qml/compiler/qv4codegen.cpp b/src/qml/compiler/qv4codegen.cpp index 27aecdd3ed..02274ca793 100644 --- a/src/qml/compiler/qv4codegen.cpp +++ b/src/qml/compiler/qv4codegen.cpp @@ -2448,7 +2448,8 @@ bool Codegen::visit(SwitchStatement *ast) IR::BasicBlock *switchend = _function->newBasicBlock(exceptionHandler()); if (ast->block) { - Result lhs = expression(ast->expression); + int lhs = _block->newTemp(); + move(_block->TEMP(lhs), *expression(ast->expression)); IR::BasicBlock *switchcond = _function->newBasicBlock(exceptionHandler()); _block->JUMP(switchcond); IR::BasicBlock *previousBlock = 0; @@ -2510,7 +2511,7 @@ bool Codegen::visit(SwitchStatement *ast) Result rhs = expression(clause->expression); IR::BasicBlock *iftrue = blockMap[clause]; IR::BasicBlock *iffalse = _function->newBasicBlock(exceptionHandler()); - setLocation(cjump(binop(IR::OpStrictEqual, *lhs, *rhs), iftrue, iffalse), clause->caseToken); + setLocation(cjump(binop(IR::OpStrictEqual, _block->TEMP(lhs), *rhs), iftrue, iffalse), clause->caseToken); _block = iffalse; } @@ -2519,7 +2520,7 @@ bool Codegen::visit(SwitchStatement *ast) Result rhs = expression(clause->expression); IR::BasicBlock *iftrue = blockMap[clause]; IR::BasicBlock *iffalse = _function->newBasicBlock(exceptionHandler()); - setLocation(cjump(binop(IR::OpStrictEqual, *lhs, *rhs), iftrue, iffalse), clause->caseToken); + setLocation(cjump(binop(IR::OpStrictEqual, _block->TEMP(lhs), *rhs), iftrue, iffalse), clause->caseToken); _block = iffalse; } diff --git a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp index 722fd19af6..def04765a0 100644 --- a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp +++ b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp @@ -325,6 +325,7 @@ private slots: void qtbug_39520(); void readUnregisteredQObjectProperty(); void writeUnregisteredQObjectProperty(); + void switchExpression(); private: // static void propertyVarWeakRefCallback(v8::Persistent<v8::Value> object, void* parameter); @@ -7843,6 +7844,29 @@ void tst_qqmlecmascript::writeUnregisteredQObjectProperty() QCOMPARE(root->property("container").value<ObjectContainer*>()->mSetterCalled, true); } +void tst_qqmlecmascript::switchExpression() +{ + // verify that we evaluate the expression inside switch() exactly once + QJSEngine engine; + QJSValue v = engine.evaluate(QString::fromLatin1( + "var num = 0\n" + "var x = 0\n" + "function f() { ++num; return (Math.random() > 0.5) ? 0 : 1; }\n" + "for (var i = 0; i < 1000; ++i) {\n" + " switch (f()) {\n" + " case 0:\n" + " case 1:\n" + " break;\n" + " default:\n" + " ++x;\n" + " }\n" + "}\n" + "(x == 0 && num == 1000) ? true : false\n" + )); + QVERIFY(!v.isError()); + QCOMPARE(v.toBool(), true); +} + QTEST_MAIN(tst_qqmlecmascript) #include "tst_qqmlecmascript.moc" |