aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLars Knoll <lars.knoll@qt.io>2018-06-04 14:59:47 +0200
committerLars Knoll <lars.knoll@qt.io>2018-06-21 13:30:38 +0000
commit77c22af561f49bc6a78010564d33fc86eb831519 (patch)
tree6e4c09c7f833d994c085dba8c08d6e117be6a23b
parent3adc6dcf5ea078c9a365a63fb99f7869fd070cc2 (diff)
Fix handling of elisions in destructuring expressions
We need to iterator over elisions at the end, as those could trigger side effects by calling iterator.next() Change-Id: Ieb5fa3562b6e60fdf179fa228510b2eeaaf9da30 Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
-rw-r--r--src/qml/compiler/qv4codegen.cpp10
-rw-r--r--src/qml/compiler/qv4compilerscanfunctions.cpp4
-rw-r--r--src/qml/parser/qqmljs.g12
-rw-r--r--src/qml/parser/qqmljsast.cpp6
-rw-r--r--src/qml/parser/qqmljsast_p.h9
-rw-r--r--tests/auto/qml/ecmascripttests/TestExpectations24
6 files changed, 17 insertions, 48 deletions
diff --git a/src/qml/compiler/qv4codegen.cpp b/src/qml/compiler/qv4codegen.cpp
index 2aa1cef451..1a47730979 100644
--- a/src/qml/compiler/qv4codegen.cpp
+++ b/src/qml/compiler/qv4codegen.cpp
@@ -595,7 +595,7 @@ void Codegen::destructureElementList(const Codegen::Reference &array, PatternEle
Instruction::IteratorNext next;
next.value = iteratorValue.stackSlot();
bytecodeGenerator->addInstruction(next);
- bool last = !p->next;
+ bool last = !p->next || (!p->next->elision && !p->next->element);
if (last)
iteratorDone.storeConsumeAccumulator();
if (e->type != PatternElement::RestElement) {
@@ -833,6 +833,9 @@ bool Codegen::visit(ArrayPattern *ast)
};
for (PatternElementList *it = ast->elements; it; it = it->next) {
+ for (Elision *elision = it->elision; elision; elision = elision->next)
+ push(nullptr);
+
PatternElement *e = it->element;
if (!e)
continue;
@@ -841,15 +844,10 @@ bool Codegen::visit(ArrayPattern *ast)
return false;
}
- for (Elision *elision = it->elision; elision; elision = elision->next)
- push(nullptr);
-
push(e->initializer);
if (hasError)
return false;
}
- for (Elision *elision = ast->elision; elision; elision = elision->next)
- push(nullptr);
if (args == -1) {
Q_ASSERT(argc == 0);
diff --git a/src/qml/compiler/qv4compilerscanfunctions.cpp b/src/qml/compiler/qv4compilerscanfunctions.cpp
index 9605b72b76..e371280b55 100644
--- a/src/qml/compiler/qv4compilerscanfunctions.cpp
+++ b/src/qml/compiler/qv4compilerscanfunctions.cpp
@@ -184,10 +184,6 @@ bool ScanFunctions::visit(ArrayPattern *ast)
++index;
++index;
}
- if (ast->elision) {
- for (Elision *elision = ast->elision->next; elision; elision = elision->next)
- ++index;
- }
_context->maxNumberOfArguments = qMax(_context->maxNumberOfArguments, index);
return true;
}
diff --git a/src/qml/parser/qqmljs.g b/src/qml/parser/qqmljs.g
index bc38655607..f927473e53 100644
--- a/src/qml/parser/qqmljs.g
+++ b/src/qml/parser/qqmljs.g
@@ -1585,7 +1585,10 @@ RegularExpressionLiteral: T_DIVIDE_EQ;
ArrayLiteral: T_LBRACKET ElisionOpt T_RBRACKET;
/.
case $rule_number: {
- AST::ArrayPattern *node = new (pool) AST::ArrayPattern(sym(2).Elision);
+ AST::PatternElementList *list = nullptr;
+ if (sym(2).Elision)
+ list = (new (pool) AST::PatternElementList(sym(2).Elision, nullptr))->finish();
+ AST::ArrayPattern *node = new (pool) AST::ArrayPattern(list);
node->lbracketToken = loc(1);
node->rbracketToken = loc(3);
sym(1).Node = node;
@@ -1605,7 +1608,12 @@ ArrayLiteral: T_LBRACKET ElementList T_RBRACKET;
ArrayLiteral: T_LBRACKET ElementList T_COMMA ElisionOpt T_RBRACKET;
/.
case $rule_number: {
- AST::ArrayPattern *node = new (pool) AST::ArrayPattern(sym(2).PatternElementList->finish(), sym(4).Elision);
+ auto *list = sym(2).PatternElementList;
+ if (sym(4).Elision) {
+ AST::PatternElementList *l = new (pool) AST::PatternElementList(sym(4).Elision, nullptr);
+ list = list->append(l);
+ }
+ AST::ArrayPattern *node = new (pool) AST::ArrayPattern(list->finish());
node->lbracketToken = loc(1);
node->commaToken = loc(3);
node->rbracketToken = loc(5);
diff --git a/src/qml/parser/qqmljsast.cpp b/src/qml/parser/qqmljsast.cpp
index 814262d98b..b63feb3362 100644
--- a/src/qml/parser/qqmljsast.cpp
+++ b/src/qml/parser/qqmljsast.cpp
@@ -259,10 +259,8 @@ void RegExpLiteral::accept0(Visitor *visitor)
void ArrayPattern::accept0(Visitor *visitor)
{
- if (visitor->visit(this)) {
+ if (visitor->visit(this))
accept(elements, visitor);
- accept(elision, visitor);
- }
visitor->endVisit(this);
}
@@ -358,6 +356,8 @@ bool ArrayPattern::convertLiteralToAssignmentPattern(MemoryPool *pool, SourceLoc
if (parseMode == Binding)
return true;
for (auto *it = elements; it; it = it->next) {
+ if (!it->element)
+ continue;
if (it->element->type == PatternElement::SpreadElement && it->next) {
*errorLocation = it->element->firstSourceLocation();
*errorMessage = QString::fromLatin1("'...' can only appear as last element in a destructuring list.");
diff --git a/src/qml/parser/qqmljsast_p.h b/src/qml/parser/qqmljsast_p.h
index 91d6410132..2d4d5662bd 100644
--- a/src/qml/parser/qqmljsast_p.h
+++ b/src/qml/parser/qqmljsast_p.h
@@ -542,18 +542,10 @@ class QML_PARSER_EXPORT ArrayPattern : public Pattern
public:
QQMLJS_DECLARE_AST_NODE(ArrayPattern)
- ArrayPattern(Elision *e)
- : elision(e)
- { kind = K; }
-
ArrayPattern(PatternElementList *elts)
: elements(elts)
{ kind = K; }
- ArrayPattern(PatternElementList *elts, Elision *e)
- : elements(elts), elision(e)
- { kind = K; }
-
void accept0(Visitor *visitor) override;
SourceLocation firstSourceLocation() const override
@@ -568,7 +560,6 @@ public:
// attributes
PatternElementList *elements = nullptr;
- Elision *elision = nullptr;
SourceLocation lbracketToken;
SourceLocation commaToken;
SourceLocation rbracketToken;
diff --git a/tests/auto/qml/ecmascripttests/TestExpectations b/tests/auto/qml/ecmascripttests/TestExpectations
index c021c1c388..4967ea67d2 100644
--- a/tests/auto/qml/ecmascripttests/TestExpectations
+++ b/tests/auto/qml/ecmascripttests/TestExpectations
@@ -2477,12 +2477,9 @@ language/expressions/array/spread-sngl-literal.js fails
language/expressions/arrow-function/cannot-override-this-with-thisArg.js fails
language/expressions/arrow-function/dflt-params-ref-later.js fails
language/expressions/arrow-function/dflt-params-ref-self.js fails
-language/expressions/arrow-function/dstr-ary-ptrn-elem-ary-elision-init.js fails
language/expressions/arrow-function/dstr-ary-ptrn-elem-ary-rest-init.js fails
language/expressions/arrow-function/dstr-ary-ptrn-elem-ary-rest-iter.js fails
language/expressions/arrow-function/dstr-ary-ptrn-elem-id-init-fn-name-class.js fails
-language/expressions/arrow-function/dstr-ary-ptrn-elision-step-err.js fails
-language/expressions/arrow-function/dstr-ary-ptrn-elision.js fails
language/expressions/arrow-function/dstr-ary-ptrn-rest-ary-elem.js fails
language/expressions/arrow-function/dstr-ary-ptrn-rest-ary-rest.js fails
language/expressions/arrow-function/dstr-ary-ptrn-rest-id-elision.js fails
@@ -2490,12 +2487,9 @@ language/expressions/arrow-function/dstr-ary-ptrn-rest-id-exhausted.js fails
language/expressions/arrow-function/dstr-ary-ptrn-rest-id.js fails
language/expressions/arrow-function/dstr-ary-ptrn-rest-obj-id.js fails
language/expressions/arrow-function/dstr-ary-ptrn-rest-obj-prop-id.js fails
-language/expressions/arrow-function/dstr-dflt-ary-ptrn-elem-ary-elision-init.js fails
language/expressions/arrow-function/dstr-dflt-ary-ptrn-elem-ary-rest-init.js fails
language/expressions/arrow-function/dstr-dflt-ary-ptrn-elem-ary-rest-iter.js fails
language/expressions/arrow-function/dstr-dflt-ary-ptrn-elem-id-init-fn-name-class.js fails
-language/expressions/arrow-function/dstr-dflt-ary-ptrn-elision-step-err.js fails
-language/expressions/arrow-function/dstr-dflt-ary-ptrn-elision.js fails
language/expressions/arrow-function/dstr-dflt-ary-ptrn-rest-ary-elem.js fails
language/expressions/arrow-function/dstr-dflt-ary-ptrn-rest-ary-rest.js fails
language/expressions/arrow-function/dstr-dflt-ary-ptrn-rest-id-elision.js fails
@@ -2550,10 +2544,6 @@ language/expressions/assignment/dstr-array-elem-put-prop-ref-user-err.js fails
language/expressions/assignment/dstr-array-elem-put-prop-ref.js fails
language/expressions/assignment/dstr-array-elem-target-yield-expr.js fails
language/expressions/assignment/dstr-array-elem-target-yield-valid.js sloppyFails
-language/expressions/assignment/dstr-array-elem-trlg-iter-elision-iter-abpt.js fails
-language/expressions/assignment/dstr-array-elem-trlg-iter-elision-iter-nrml-close-err.js fails
-language/expressions/assignment/dstr-array-elem-trlg-iter-elision-iter-nrml-close-skip.js fails
-language/expressions/assignment/dstr-array-elem-trlg-iter-elision-iter-nrml-close.js fails
language/expressions/assignment/dstr-array-elem-trlg-iter-list-rtrn-close-err.js fails
language/expressions/assignment/dstr-array-elem-trlg-iter-list-rtrn-close-null.js fails
language/expressions/assignment/dstr-array-elem-trlg-iter-list-rtrn-close.js fails
@@ -2565,11 +2555,6 @@ language/expressions/assignment/dstr-array-elem-trlg-iter-rest-rtrn-close-null.j
language/expressions/assignment/dstr-array-elem-trlg-iter-rest-rtrn-close.js fails
language/expressions/assignment/dstr-array-elem-trlg-iter-rest-thrw-close-err.js fails
language/expressions/assignment/dstr-array-elem-trlg-iter-rest-thrw-close.js fails
-language/expressions/assignment/dstr-array-elision-iter-abpt.js fails
-language/expressions/assignment/dstr-array-elision-iter-nrml-close-err.js fails
-language/expressions/assignment/dstr-array-elision-iter-nrml-close-skip.js fails
-language/expressions/assignment/dstr-array-elision-iter-nrml-close.js fails
-language/expressions/assignment/dstr-array-iteration.js fails
language/expressions/assignment/dstr-array-rest-after-element.js fails
language/expressions/assignment/dstr-array-rest-after-elision.js fails
language/expressions/assignment/dstr-array-rest-elision.js fails
@@ -4877,10 +4862,6 @@ language/statements/for-of/dstr-array-elem-put-prop-ref-user-err.js fails
language/statements/for-of/dstr-array-elem-put-prop-ref.js fails
language/statements/for-of/dstr-array-elem-target-yield-expr.js fails
language/statements/for-of/dstr-array-elem-target-yield-valid.js sloppyFails
-language/statements/for-of/dstr-array-elem-trlg-iter-elision-iter-abpt.js fails
-language/statements/for-of/dstr-array-elem-trlg-iter-elision-iter-nrml-close-err.js fails
-language/statements/for-of/dstr-array-elem-trlg-iter-elision-iter-nrml-close-skip.js fails
-language/statements/for-of/dstr-array-elem-trlg-iter-elision-iter-nrml-close.js fails
language/statements/for-of/dstr-array-elem-trlg-iter-list-rtrn-close-err.js fails
language/statements/for-of/dstr-array-elem-trlg-iter-list-rtrn-close-null.js fails
language/statements/for-of/dstr-array-elem-trlg-iter-list-rtrn-close.js fails
@@ -4892,11 +4873,6 @@ language/statements/for-of/dstr-array-elem-trlg-iter-rest-rtrn-close-null.js fai
language/statements/for-of/dstr-array-elem-trlg-iter-rest-rtrn-close.js fails
language/statements/for-of/dstr-array-elem-trlg-iter-rest-thrw-close-err.js fails
language/statements/for-of/dstr-array-elem-trlg-iter-rest-thrw-close.js fails
-language/statements/for-of/dstr-array-elision-iter-abpt.js fails
-language/statements/for-of/dstr-array-elision-iter-nrml-close-err.js fails
-language/statements/for-of/dstr-array-elision-iter-nrml-close-skip.js fails
-language/statements/for-of/dstr-array-elision-iter-nrml-close.js fails
-language/statements/for-of/dstr-array-iteration.js fails
language/statements/for-of/dstr-array-rest-after-element.js fails
language/statements/for-of/dstr-array-rest-after-elision.js fails
language/statements/for-of/dstr-array-rest-elision.js fails