aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/compiler/qv4codegen.cpp
diff options
context:
space:
mode:
authorErik Verbruggen <erik.verbruggen@qt.io>2017-12-12 11:51:04 +0100
committerErik Verbruggen <erik.verbruggen@qt.io>2017-12-13 08:58:52 +0000
commit904179cb681e28b248d892e699f5706666a1b4fc (patch)
tree61bf6c68be99f05d295d1fd304a97fde7a4ca385 /src/qml/compiler/qv4codegen.cpp
parent93ad68de3a3873cbdc33336520bd0b6443312ec1 (diff)
Fix iterator assignment for for-in loops
When iterating over an object using an for-in loop, the value for the next iteration should be assigned in the body of the loop. This means that after the loop, the value of the last iteration is still assigned to that variable, not null (which marks the end of the iterable values). Task-number: QTBUG-65104 Change-Id: Icbddbc67723719005120587bcdc63dcdfa52b67f Reviewed-by: Lars Knoll <lars.knoll@qt.io>
Diffstat (limited to 'src/qml/compiler/qv4codegen.cpp')
-rw-r--r--src/qml/compiler/qv4codegen.cpp33
1 files changed, 21 insertions, 12 deletions
diff --git a/src/qml/compiler/qv4codegen.cpp b/src/qml/compiler/qv4codegen.cpp
index 6abcf82f44..ae6557968b 100644
--- a/src/qml/compiler/qv4codegen.cpp
+++ b/src/qml/compiler/qv4codegen.cpp
@@ -2333,7 +2333,8 @@ bool Codegen::visit(ForEachStatement *ast)
RegisterScope scope(this);
- Reference obj = Reference::fromStackSlot(this);
+ Reference nextIterObj = Reference::fromStackSlot(this);
+ Reference iterObj = Reference::fromStackSlot(this);
Reference expr = expression(ast->expression);
if (hasError)
return true;
@@ -2341,7 +2342,9 @@ bool Codegen::visit(ForEachStatement *ast)
expr.loadInAccumulator();
Instruction::ForeachIteratorObject iteratorObjInstr;
bytecodeGenerator->addInstruction(iteratorObjInstr);
- obj.storeConsumeAccumulator();
+ iterObj.storeConsumeAccumulator();
+
+ Reference lhs = expression(ast->initialiser).asLValue();
BytecodeGenerator::Label in = bytecodeGenerator->newLabel();
BytecodeGenerator::Label end = bytecodeGenerator->newLabel();
@@ -2352,20 +2355,21 @@ bool Codegen::visit(ForEachStatement *ast)
BytecodeGenerator::Label body = bytecodeGenerator->label();
+ nextIterObj.loadInAccumulator();
+ lhs.storeConsumeAccumulator();
+
statement(ast->statement);
setJumpOutLocation(bytecodeGenerator, ast->statement, ast->forToken);
in.link();
- Reference lhs = expression(ast->initialiser).asLValue();
-
- obj.loadInAccumulator();
+ iterObj.loadInAccumulator();
Instruction::ForeachNextPropertyName nextPropInstr;
bytecodeGenerator->addInstruction(nextPropInstr);
- lhs = lhs.storeRetainAccumulator().storeOnStack();
+ nextIterObj.storeConsumeAccumulator();
Reference::fromConst(this, QV4::Encode::null()).loadInAccumulator();
- bytecodeGenerator->jumpStrictNotEqual(lhs.stackSlot(), body);
+ bytecodeGenerator->jumpStrictNotEqual(nextIterObj.stackSlot(), body);
end.link();
@@ -2477,7 +2481,8 @@ bool Codegen::visit(LocalForEachStatement *ast)
RegisterScope scope(this);
- Reference obj = Reference::fromStackSlot(this);
+ Reference nextIterObj = Reference::fromStackSlot(this);
+ Reference iterObj = Reference::fromStackSlot(this);
Reference expr = expression(ast->expression);
if (hasError)
return true;
@@ -2487,7 +2492,7 @@ bool Codegen::visit(LocalForEachStatement *ast)
expr.loadInAccumulator();
Instruction::ForeachIteratorObject iteratorObjInstr;
bytecodeGenerator->addInstruction(iteratorObjInstr);
- obj.storeConsumeAccumulator();
+ iterObj.storeConsumeAccumulator();
BytecodeGenerator::Label in = bytecodeGenerator->newLabel();
BytecodeGenerator::Label end = bytecodeGenerator->newLabel();
@@ -2498,18 +2503,22 @@ bool Codegen::visit(LocalForEachStatement *ast)
BytecodeGenerator::Label body = bytecodeGenerator->label();
Reference it = referenceForName(ast->declaration->name.toString(), true).asLValue();
+
+ nextIterObj.loadInAccumulator();
+ it.storeConsumeAccumulator();
+
statement(ast->statement);
setJumpOutLocation(bytecodeGenerator, ast->statement, ast->forToken);
in.link();
- obj.loadInAccumulator();
+ iterObj.loadInAccumulator();
Instruction::ForeachNextPropertyName nextPropInstr;
bytecodeGenerator->addInstruction(nextPropInstr);
- auto lhs = it.storeRetainAccumulator().storeOnStack();
+ nextIterObj.storeConsumeAccumulator();
Reference::fromConst(this, QV4::Encode::null()).loadInAccumulator();
- bytecodeGenerator->jumpStrictNotEqual(lhs.stackSlot(), body);
+ bytecodeGenerator->jumpStrictNotEqual(nextIterObj.stackSlot(), body);
end.link();