aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/qml/compiler/qv4codegen.cpp170
-rw-r--r--src/qml/jsruntime/qv4runtime.cpp5
-rw-r--r--tests/auto/qml/ecmascripttests/TestExpectations30
3 files changed, 140 insertions, 65 deletions
diff --git a/src/qml/compiler/qv4codegen.cpp b/src/qml/compiler/qv4codegen.cpp
index b3b522e661..e39bb61688 100644
--- a/src/qml/compiler/qv4codegen.cpp
+++ b/src/qml/compiler/qv4codegen.cpp
@@ -831,53 +831,155 @@ bool Codegen::visit(ArrayPattern *ast)
if (hasError)
return false;
- RegisterScope scope(this);
+ PatternElementList *it = ast->elements;
int argc = 0;
- int args = -1;
- auto push = [this, &argc, &args](AST::ExpressionNode *arg) {
- int temp = bytecodeGenerator->newRegister();
- if (args == -1)
- args = temp;
- if (!arg) {
- auto c = Reference::fromConst(this, Primitive::emptyValue().asReturnedValue());
- (void) c.storeOnStack(temp);
- } else {
- RegisterScope scope(this);
- Reference r = expression(arg);
+ {
+ RegisterScope scope(this);
+
+ int args = -1;
+ auto push = [this, &argc, &args](AST::ExpressionNode *arg) {
+ int temp = bytecodeGenerator->newRegister();
+ if (args == -1)
+ args = temp;
+ if (!arg) {
+ auto c = Reference::fromConst(this, Primitive::emptyValue().asReturnedValue());
+ (void) c.storeOnStack(temp);
+ } else {
+ RegisterScope scope(this);
+ Reference r = expression(arg);
+ if (hasError)
+ return;
+ (void) r.storeOnStack(temp);
+ }
+ ++argc;
+ };
+
+ for (; it; it = it->next) {
+ PatternElement *e = it->element;
+ if (e && e->type == PatternElement::SpreadElement)
+ break;
+ for (Elision *elision = it->elision; elision; elision = elision->next)
+ push(nullptr);
+
+ if (!e)
+ continue;
+
+ push(e->initializer);
if (hasError)
- return;
- (void) r.storeOnStack(temp);
+ return false;
}
- ++argc;
+
+ if (args == -1) {
+ Q_ASSERT(argc == 0);
+ args = 0;
+ }
+
+ Instruction::DefineArray call;
+ call.argc = argc;
+ call.args = Moth::StackSlot::createRegister(args);
+ bytecodeGenerator->addInstruction(call);
+ }
+
+ if (!it) {
+ _expr.setResult(Reference::fromAccumulator(this));
+ return false;
+ }
+ Q_ASSERT(it->element && it->element->type == PatternElement::SpreadElement);
+
+ RegisterScope scope(this);
+ Reference array = Reference::fromStackSlot(this);
+ array.storeConsumeAccumulator();
+ Reference index = Reference::storeConstOnStack(this, Encode(argc));
+
+ auto pushAccumulator = [&]() {
+ Reference slot = Reference::fromSubscript(array, index);
+ slot.storeConsumeAccumulator();
+
+ index.loadInAccumulator();
+ Instruction::Increment inc;
+ bytecodeGenerator->addInstruction(inc);
+ index.storeConsumeAccumulator();
};
- for (PatternElementList *it = ast->elements; it; it = it->next) {
- for (Elision *elision = it->elision; elision; elision = elision->next)
- push(nullptr);
+ while (it) {
+ for (Elision *elision = it->elision; elision; elision = elision->next) {
+ Reference::fromConst(this, Primitive::emptyValue().asReturnedValue()).loadInAccumulator();
+ pushAccumulator();
+ }
- PatternElement *e = it->element;
- if (!e)
+ if (!it->element) {
+ it = it->next;
continue;
- if (e->type == PatternElement::RestElement) {
- throwSyntaxError(it->firstSourceLocation(), QLatin1String("'...' in ArrayLiterals is unimplementd."));
- return false;
}
- push(e->initializer);
- if (hasError)
- return false;
- }
+ // handle spread element
+ if (it->element->type == PatternElement::SpreadElement) {
+ RegisterScope scope(this);
- if (args == -1) {
- Q_ASSERT(argc == 0);
- args = 0;
+ Reference iterator = Reference::fromStackSlot(this);
+ Reference lhsValue = Reference::fromStackSlot(this);
+
+ // There should be a temporal block, so that variables declared in lhs shadow outside vars.
+ // This block should define a temporal dead zone for those variables, which is not yet implemented.
+ {
+ RegisterScope innerScope(this);
+ Reference expr = expression(it->element->initializer);
+ if (hasError)
+ return false;
+
+ expr.loadInAccumulator();
+ Instruction::GetIterator iteratorObjInstr;
+ iteratorObjInstr.iterator = /*ForEachType::Of*/ 1;
+ bytecodeGenerator->addInstruction(iteratorObjInstr);
+ iterator.storeConsumeAccumulator();
+ }
+
+ BytecodeGenerator::Label in = bytecodeGenerator->newLabel();
+ BytecodeGenerator::Label end = bytecodeGenerator->newLabel();
+ BytecodeGenerator::Label done = bytecodeGenerator->newLabel();
+
+ {
+ ControlFlowLoop flow(this, &end, &in, /*requiresUnwind*/ true);
+ bytecodeGenerator->jump().link(in);
+
+ BytecodeGenerator::Label body = bytecodeGenerator->label();
+
+ lhsValue.loadInAccumulator();
+ pushAccumulator();
+
+ in.link();
+ iterator.loadInAccumulator();
+ Instruction::IteratorNext next;
+ next.value = lhsValue.stackSlot();
+ bytecodeGenerator->addInstruction(next);
+ bytecodeGenerator->addJumpInstruction(Instruction::JumpFalse()).link(body);
+ bytecodeGenerator->jump().link(done);
+ }
+
+ end.link();
+
+ Reference iteratorDone = Reference::fromConst(this, Encode(false)).storeOnStack();
+ iterator.loadInAccumulator();
+ Instruction::IteratorClose close;
+ close.done = iteratorDone.stackSlot();
+ bytecodeGenerator->addInstruction(close);
+
+ done.link();
+ } else {
+ RegisterScope innerScope(this);
+ Reference expr = expression(it->element->initializer);
+ if (hasError)
+ return false;
+
+ expr.loadInAccumulator();
+ pushAccumulator();
+ }
+
+ it = it->next;
}
- Instruction::DefineArray call;
- call.argc = argc;
- call.args = Moth::StackSlot::createRegister(args);
- bytecodeGenerator->addInstruction(call);
+ array.loadInAccumulator();
_expr.setResult(Reference::fromAccumulator(this));
return false;
diff --git a/src/qml/jsruntime/qv4runtime.cpp b/src/qml/jsruntime/qv4runtime.cpp
index 73c579f3eb..b879e3fc14 100644
--- a/src/qml/jsruntime/qv4runtime.cpp
+++ b/src/qml/jsruntime/qv4runtime.cpp
@@ -745,7 +745,10 @@ ReturnedValue Runtime::method_getIterator(ExecutionEngine *engine, const Value &
if (!f)
return engine->throwTypeError();
JSCallData cData(scope, 0, nullptr, o);
- return f->call(cData);
+ ScopedObject it(scope, f->call(cData));
+ if (!it)
+ return engine->throwTypeError();
+ return it->asReturnedValue();
}
return engine->newForInIteratorObject(o)->asReturnedValue();
}
diff --git a/tests/auto/qml/ecmascripttests/TestExpectations b/tests/auto/qml/ecmascripttests/TestExpectations
index 33dfb0a750..317ac1735e 100644
--- a/tests/auto/qml/ecmascripttests/TestExpectations
+++ b/tests/auto/qml/ecmascripttests/TestExpectations
@@ -2452,28 +2452,6 @@ language/eval-code/indirect/var-env-global-lex-non-strict.js fails
language/eval-code/indirect/var-env-var-init-global-exstng.js strictFails
language/eval-code/indirect/var-env-var-init-global-new.js strictFails
language/eval-code/indirect/var-env-var-non-strict.js strictFails
-language/expressions/array/spread-err-mult-err-expr-throws.js fails
-language/expressions/array/spread-err-mult-err-iter-get-value.js fails
-language/expressions/array/spread-err-mult-err-itr-get-call.js fails
-language/expressions/array/spread-err-mult-err-itr-get-get.js fails
-language/expressions/array/spread-err-mult-err-itr-step.js fails
-language/expressions/array/spread-err-mult-err-itr-value.js fails
-language/expressions/array/spread-err-mult-err-unresolvable.js fails
-language/expressions/array/spread-err-sngl-err-expr-throws.js fails
-language/expressions/array/spread-err-sngl-err-itr-get-call.js fails
-language/expressions/array/spread-err-sngl-err-itr-get-get.js fails
-language/expressions/array/spread-err-sngl-err-itr-get-value.js fails
-language/expressions/array/spread-err-sngl-err-itr-step.js fails
-language/expressions/array/spread-err-sngl-err-itr-value.js fails
-language/expressions/array/spread-err-sngl-err-unresolvable.js fails
-language/expressions/array/spread-mult-empty.js fails
-language/expressions/array/spread-mult-expr.js fails
-language/expressions/array/spread-mult-iter.js fails
-language/expressions/array/spread-mult-literal.js fails
-language/expressions/array/spread-sngl-empty.js fails
-language/expressions/array/spread-sngl-expr.js fails
-language/expressions/array/spread-sngl-iter.js fails
-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
@@ -3464,8 +3442,6 @@ language/expressions/generators/dstr-obj-ptrn-id-init-fn-name-class.js fails
language/expressions/generators/eval-body-proto-realm.js fails
language/expressions/generators/name.js fails
language/expressions/generators/named-yield-identifier-non-strict.js sloppyFails
-language/expressions/generators/named-yield-spread-arr-multiple.js fails
-language/expressions/generators/named-yield-spread-arr-single.js fails
language/expressions/generators/scope-body-lex-distinct.js sloppyFails
language/expressions/generators/scope-name-var-open-non-strict.js sloppyFails
language/expressions/generators/scope-name-var-open-strict.js strictFails
@@ -3479,8 +3455,6 @@ language/expressions/generators/yield-as-identifier-in-nested-function.js sloppy
language/expressions/generators/yield-as-literal-property-name.js fails
language/expressions/generators/yield-as-property-name.js fails
language/expressions/generators/yield-identifier-non-strict.js sloppyFails
-language/expressions/generators/yield-spread-arr-multiple.js fails
-language/expressions/generators/yield-spread-arr-single.js fails
language/expressions/generators/yield-star-before-newline.js fails
language/expressions/instanceof/prototype-getter-with-object-throws.js fails
language/expressions/instanceof/prototype-getter-with-object.js fails
@@ -3544,8 +3518,6 @@ language/expressions/object/method-definition/fn-name-gen.js fails
language/expressions/object/method-definition/gen-meth-dflt-params-ref-later.js fails
language/expressions/object/method-definition/gen-meth-dflt-params-ref-self.js fails
language/expressions/object/method-definition/gen-yield-identifier-non-strict.js sloppyFails
-language/expressions/object/method-definition/gen-yield-spread-arr-multiple.js fails
-language/expressions/object/method-definition/gen-yield-spread-arr-single.js fails
language/expressions/object/method-definition/generator-name-prop-symbol.js fails
language/expressions/object/method-definition/generator-super-prop-body.js fails
language/expressions/object/method-definition/generator-super-prop-param.js fails
@@ -4902,8 +4874,6 @@ language/statements/generators/yield-as-identifier-in-nested-function.js sloppyF
language/statements/generators/yield-as-literal-property-name.js fails
language/statements/generators/yield-as-property-name.js fails
language/statements/generators/yield-identifier-non-strict.js sloppyFails
-language/statements/generators/yield-spread-arr-multiple.js fails
-language/statements/generators/yield-spread-arr-single.js fails
language/statements/generators/yield-star-before-newline.js fails
language/statements/if/tco-else-body.js strictFails
language/statements/if/tco-if-body.js strictFails