diff options
author | Lars Knoll <lars.knoll@qt.io> | 2018-05-12 22:54:27 +0200 |
---|---|---|
committer | Lars Knoll <lars.knoll@qt.io> | 2018-05-13 12:55:32 +0000 |
commit | fbca1b7942fc58d5573c6ec95295c2d4472b80ff (patch) | |
tree | 25bc99ba2cc4b4c2742c3b799707415862b840dc /src/qml/compiler | |
parent | 9e379e8fb72305aff1fb6758c23198c8b30829ac (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.cpp | 34 | ||||
-rw-r--r-- | src/qml/compiler/qv4instr_moth.cpp | 1 | ||||
-rw-r--r-- | src/qml/compiler/qv4instr_moth_p.h | 2 |
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) |