aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/compiler
diff options
context:
space:
mode:
authorLars Knoll <lars.knoll@qt.io>2018-06-05 13:07:50 +0200
committerLars Knoll <lars.knoll@qt.io>2018-06-21 13:30:44 +0000
commitce18e987d4ea623c0db6d10f2a97a16b639a234e (patch)
tree793ce0624f971de8015d5580e6c06d2b1a1b9aab /src/qml/compiler
parenta12da297946b5a6e767b972bc635a3308683b2e5 (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.cpp31
-rw-r--r--src/qml/compiler/qv4codegen_p.h1
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);