aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/compiler
diff options
context:
space:
mode:
authorLars Knoll <lars.knoll@qt.io>2018-05-12 22:54:27 +0200
committerLars Knoll <lars.knoll@qt.io>2018-05-13 12:55:32 +0000
commitfbca1b7942fc58d5573c6ec95295c2d4472b80ff (patch)
tree25bc99ba2cc4b4c2742c3b799707415862b840dc /src/qml/compiler
parent9e379e8fb72305aff1fb6758c23198c8b30829ac (diff)
Fix array destructuring
Array destructuring should use iterator objects, not integer indexes. Change-Id: I769bb1d63246da6bc45233f7a6e9a8e5ddc53a4d Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
Diffstat (limited to 'src/qml/compiler')
-rw-r--r--src/qml/compiler/qv4codegen.cpp34
-rw-r--r--src/qml/compiler/qv4instr_moth.cpp1
-rw-r--r--src/qml/compiler/qv4instr_moth_p.h2
3 files changed, 28 insertions, 9 deletions
diff --git a/src/qml/compiler/qv4codegen.cpp b/src/qml/compiler/qv4codegen.cpp
index 97b71ddbcc..ffb318168c 100644
--- a/src/qml/compiler/qv4codegen.cpp
+++ b/src/qml/compiler/qv4codegen.cpp
@@ -476,27 +476,44 @@ void Codegen::destructureElementList(const Codegen::Reference &array, PatternEle
{
RegisterScope scope(this);
- int index = 0;
+ Reference iterator = Reference::fromStackSlot(this);
+
+ array.loadInAccumulator();
+ Instruction::GetIterator iteratorObjInstr;
+ iteratorObjInstr.iterator = 1; // ForEachType::Of
+ bytecodeGenerator->addInstruction(iteratorObjInstr);
+ iterator.storeConsumeAccumulator();
+
+ BytecodeGenerator::Label end = bytecodeGenerator->newLabel();
+
for (PatternElementList *p = bindingList; p; p = p->next) {
- for (Elision *elision = p->elision; elision; elision = elision->next)
- ++index;
+ for (Elision *elision = p->elision; elision; elision = elision->next) {
+ iterator.loadInAccumulator();
+ Instruction::IteratorNext next;
+ next.returnUndefinedWhenDone = true;
+ bytecodeGenerator->addInstruction(next);
+ }
RegisterScope scope(this);
- Reference idx = Reference::fromConst(this, Encode(index));
- Reference property = Reference::fromSubscript(array, idx);
+ iterator.loadInAccumulator();
+ Instruction::IteratorNext next;
+ next.returnUndefinedWhenDone = true;
+ bytecodeGenerator->addInstruction(next);
PatternElement *e = p->element;
if (!e)
continue;
if (e->type != PatternElement::RestElement) {
- initializeAndDestructureBindingElement(e, property);
- if (hasError)
+ initializeAndDestructureBindingElement(e, Reference::fromAccumulator(this));
+ if (hasError) {
+ end.link();
return;
+ }
} else {
throwSyntaxError(bindingList->firstSourceLocation(), QString::fromLatin1("Support for rest elements in binding arrays not implemented!"));
}
- ++index;
}
+ end.link();
}
void Codegen::destructurePattern(Pattern *p, const Reference &rhs)
@@ -2666,6 +2683,7 @@ bool Codegen::visit(ForEachStatement *ast)
in.link();
iterator.loadInAccumulator();
Instruction::IteratorNext next;
+ next.returnUndefinedWhenDone = false;
bytecodeGenerator->addInstruction(next);
Instruction::JumpEmpty jump;
BytecodeGenerator::Jump done = bytecodeGenerator->addJumpInstruction(jump);
diff --git a/src/qml/compiler/qv4instr_moth.cpp b/src/qml/compiler/qv4instr_moth.cpp
index 58aa7d7cfd..7446848fb5 100644
--- a/src/qml/compiler/qv4instr_moth.cpp
+++ b/src/qml/compiler/qv4instr_moth.cpp
@@ -434,6 +434,7 @@ void dumpBytecode(const char *code, int len, int nLocals, int nFormals, int /*st
MOTH_END_INSTR(GetIterator)
MOTH_BEGIN_INSTR(IteratorNext)
+ d << returnUndefinedWhenDone;
MOTH_END_INSTR(IteratorNext)
MOTH_BEGIN_INSTR(DeleteMember)
diff --git a/src/qml/compiler/qv4instr_moth_p.h b/src/qml/compiler/qv4instr_moth_p.h
index 301a43a519..de01b808e9 100644
--- a/src/qml/compiler/qv4instr_moth_p.h
+++ b/src/qml/compiler/qv4instr_moth_p.h
@@ -122,7 +122,7 @@ QT_BEGIN_NAMESPACE
#define INSTR_PopScriptContext(op) INSTRUCTION(op, PopScriptContext, 0)
#define INSTR_PopContext(op) INSTRUCTION(op, PopContext, 1, reg)
#define INSTR_GetIterator(op) INSTRUCTION(op, GetIterator, 1, iterator)
-#define INSTR_IteratorNext(op) INSTRUCTION(op, IteratorNext, 0)
+#define INSTR_IteratorNext(op) INSTRUCTION(op, IteratorNext, 1, returnUndefinedWhenDone)
#define INSTR_DeleteMember(op) INSTRUCTION(op, DeleteMember, 2, member, base)
#define INSTR_DeleteSubscript(op) INSTRUCTION(op, DeleteSubscript, 2, base, index)
#define INSTR_DeleteName(op) INSTRUCTION(op, DeleteName, 1, name)