diff options
author | Erik Verbruggen <erik.verbruggen@qt.io> | 2017-12-12 11:51:04 +0100 |
---|---|---|
committer | Erik Verbruggen <erik.verbruggen@qt.io> | 2017-12-13 08:58:52 +0000 |
commit | 904179cb681e28b248d892e699f5706666a1b4fc (patch) | |
tree | 61bf6c68be99f05d295d1fd304a97fde7a4ca385 /src/qml/compiler/qv4codegen.cpp | |
parent | 93ad68de3a3873cbdc33336520bd0b6443312ec1 (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.cpp | 33 |
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(); |