diff options
author | Lars Knoll <lars.knoll@qt.io> | 2018-06-05 13:07:50 +0200 |
---|---|---|
committer | Lars Knoll <lars.knoll@qt.io> | 2018-06-21 13:30:44 +0000 |
commit | ce18e987d4ea623c0db6d10f2a97a16b639a234e (patch) | |
tree | 793ce0624f971de8015d5580e6c06d2b1a1b9aab /src/qml/compiler | |
parent | a12da297946b5a6e767b972bc635a3308683b2e5 (diff) |
Fix more issues with destructuring
Fix destructuring targets that are complex lhs expressions.
There are still some failures remaining, but this fixes
another larger chunk of test cases.
Change-Id: Icf08f42d7c70d4e81be5d5d2e27ebe6249d25467
Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
Diffstat (limited to 'src/qml/compiler')
-rw-r--r-- | src/qml/compiler/qv4codegen.cpp | 31 | ||||
-rw-r--r-- | src/qml/compiler/qv4codegen_p.h | 1 |
2 files changed, 27 insertions, 5 deletions
diff --git a/src/qml/compiler/qv4codegen.cpp b/src/qml/compiler/qv4codegen.cpp index 1a47730979..d71d36845b 100644 --- a/src/qml/compiler/qv4codegen.cpp +++ b/src/qml/compiler/qv4codegen.cpp @@ -469,10 +469,27 @@ void Codegen::variableDeclarationList(VariableDeclarationList *ast) } } -void Codegen::initializeAndDestructureBindingElement(AST::PatternElement *e, const Reference &baseRef) +Codegen::Reference Codegen::targetForPatternElement(AST::PatternElement *p) +{ + if (!p->bindingIdentifier.isNull()) + return referenceForName(p->bindingIdentifier, true); + if (!p->bindingTarget || p->destructuringPattern()) + return Codegen::Reference::fromStackSlot(this); + Reference lhs = expression(p->bindingTarget); + if (hasError) + return lhs; + lhs = lhs.asLValue(); + return lhs; +} + +void Codegen::initializeAndDestructureBindingElement(AST::PatternElement *e, const Reference &base) { RegisterScope scope(this); - Reference varToStore = e->bindingIdentifier.isNull() ? Reference::fromStackSlot(this, bytecodeGenerator->newRegister()) : referenceForName(e->bindingIdentifier, true); + Reference baseRef = (base.isAccumulator()) ? base.storeOnStack() : base; + Reference varToStore = targetForPatternElement(e); + if (hasError) + return; + if (e->initializer) { if (!baseRef.isValid()) { // assignment @@ -508,13 +525,17 @@ void Codegen::initializeAndDestructureBindingElement(AST::PatternElement *e, con baseRef.loadInAccumulator(); varToStore.storeConsumeAccumulator(); } + Pattern *p = e->destructuringPattern(); + if (!p) + return; + if (!varToStore.isStackSlot()) varToStore = varToStore.storeOnStack(); if (PatternElementList *l = e->elementList()) { destructureElementList(varToStore, l); } else if (PatternPropertyList *p = e->propertyList()) { destructurePropertyList(varToStore, p); - } else if (e->bindingPattern) { + } else if (e->bindingTarget) { // empty binding pattern. For spec compatibility, try to coerce the argument to an object varToStore.loadInAccumulator(); Instruction::ToObject toObject; @@ -537,7 +558,7 @@ void Codegen::destructurePropertyList(const Codegen::Reference &object, PatternP if (hasError) return; computedName = computedName.storeOnStack(); - property = Reference::fromSubscript(object, computedName); + property = Reference::fromSubscript(object, computedName).asLValue(); } else { QString propertyName = p->name->asString(); property = Reference::fromMember(object, propertyName); @@ -2496,7 +2517,7 @@ int Codegen::defineFunction(const QString &name, AST::Node *ast, bytecodeGenerator->addInstruction(rest); arg.storeConsumeAccumulator(); } else { - if (e->bindingPattern || e->initializer) { + if (e->bindingTarget || e->initializer) { initializeAndDestructureBindingElement(e, arg); if (hasError) break; diff --git a/src/qml/compiler/qv4codegen_p.h b/src/qml/compiler/qv4codegen_p.h index 39309f78ce..713b040ad1 100644 --- a/src/qml/compiler/qv4codegen_p.h +++ b/src/qml/compiler/qv4codegen_p.h @@ -516,6 +516,7 @@ protected: void variableDeclaration(AST::PatternElement *ast); void variableDeclarationList(AST::VariableDeclarationList *ast); + Reference targetForPatternElement(AST::PatternElement *p); void initializeAndDestructureBindingElement(AST::PatternElement *e, const Reference &baseRef = Reference()); void destructurePropertyList(const Reference &object, AST::PatternPropertyList *bindingList); void destructureElementList(const Reference &array, AST::PatternElementList *bindingList); |