diff options
author | Lars Knoll <lars.knoll@qt.io> | 2018-05-14 14:12:33 +0200 |
---|---|---|
committer | Lars Knoll <lars.knoll@qt.io> | 2018-05-14 19:32:42 +0000 |
commit | c4ef0d6e4b5bb7de7b0ab08928d693988a60b25d (patch) | |
tree | 0ff9682886da081c2d8e89becfd90cfb7083540d /src/qml/compiler/qv4codegen.cpp | |
parent | d8eade23bc4fdd7040204f4374ef26975b94ea0a (diff) | |
download | qtdeclarative-c4ef0d6e4b5bb7de7b0ab08928d693988a60b25d.tar.gz |
Call iterator.return when required in destructuring assignments
Array destructuring assignments require a call to iterator.return if
the iterator hasn't been exhausted during destructuring.
Change-Id: I39fe4bc01bef6fb2ad3bda92caf6779fbbddc8e2
Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
Diffstat (limited to 'src/qml/compiler/qv4codegen.cpp')
-rw-r--r-- | src/qml/compiler/qv4codegen.cpp | 34 |
1 files changed, 30 insertions, 4 deletions
diff --git a/src/qml/compiler/qv4codegen.cpp b/src/qml/compiler/qv4codegen.cpp index 99c45d19fa..897f104093 100644 --- a/src/qml/compiler/qv4codegen.cpp +++ b/src/qml/compiler/qv4codegen.cpp @@ -478,6 +478,7 @@ void Codegen::destructureElementList(const Codegen::Reference &array, PatternEle Reference iterator = Reference::fromStackSlot(this); Reference iteratorValue = Reference::fromStackSlot(this); + Reference iteratorDone = Reference::fromStackSlot(this); array.loadInAccumulator(); Instruction::GetIterator iteratorObjInstr; @@ -485,29 +486,42 @@ void Codegen::destructureElementList(const Codegen::Reference &array, PatternEle bytecodeGenerator->addInstruction(iteratorObjInstr); iterator.storeConsumeAccumulator(); + bool hadNext = false; + bool hasRest = false; + BytecodeGenerator::Label end = bytecodeGenerator->newLabel(); for (PatternElementList *p = bindingList; p; p = p->next) { + PatternElement *e = p->element; for (Elision *elision = p->elision; elision; elision = elision->next) { iterator.loadInAccumulator(); Instruction::IteratorNext next; next.value = iteratorValue.stackSlot(); bytecodeGenerator->addInstruction(next); + hadNext = true; + bool last = !elision->next && !e && !p->next; + if (last) + iteratorDone.storeConsumeAccumulator(); } + if (!e) + continue; + + hadNext = true; RegisterScope scope(this); iterator.loadInAccumulator(); - PatternElement *e = p->element; - if (e && e->type == PatternElement::RestElement) { + if (e->type == PatternElement::RestElement) { bytecodeGenerator->addInstruction(Instruction::DestructureRestElement()); initializeAndDestructureBindingElement(e, Reference::fromAccumulator(this)); + hasRest = true; } else { Instruction::IteratorNext next; next.value = iteratorValue.stackSlot(); bytecodeGenerator->addInstruction(next); - if (!e) - continue; + bool last = !p->next; + if (last) + iteratorDone.storeConsumeAccumulator(); if (e->type != PatternElement::RestElement) { initializeAndDestructureBindingElement(e, iteratorValue); if (hasError) { @@ -517,6 +531,18 @@ void Codegen::destructureElementList(const Codegen::Reference &array, PatternEle } } } + + if (!hadNext) { + Reference::storeConstOnStack(this, Encode(false), iteratorDone.stackSlot()); + } + + if (!hasRest) { + iterator.loadInAccumulator(); + Instruction::IteratorClose close; + close.done = iteratorDone.stackSlot(); + bytecodeGenerator->addInstruction(close); + } + end.link(); } |