diff options
author | Lars Knoll <[email protected]> | 2018-09-05 14:56:24 +0200 |
---|---|---|
committer | Lars Knoll <[email protected]> | 2018-09-07 10:31:53 +0000 |
commit | 15bdbd89639c29f88db1798de66066a4a95759c0 (patch) | |
tree | fd06324c900c9eb662f3f64cb1d1f1d45186ecb3 /src/qml/jsruntime/qv4runtime.cpp | |
parent | 06e3ff28bb52500ae45f0c174ff8cd746593855c (diff) |
Fix exception handling while destructuring
When an exception happens during destructuring, IteratorClose
needs to be called, unless the exception happened inside the
IteratorNext call (in that case the iterator is assumed to be
invalid and we shouldn't call close on it).
Implement this, by ensuring that we set the done return variable
of IteratorNext to true whenever IteratorNext throws an exception.
IteratorClose will check the done state and not do anything in that
case.
Change-Id: I73a27f855f2c4d3134b8cc8980e64bf797d03886
Reviewed-by: Simon Hausmann <[email protected]>
Diffstat (limited to 'src/qml/jsruntime/qv4runtime.cpp')
-rw-r--r-- | src/qml/jsruntime/qv4runtime.cpp | 30 |
1 files changed, 20 insertions, 10 deletions
diff --git a/src/qml/jsruntime/qv4runtime.cpp b/src/qml/jsruntime/qv4runtime.cpp index 3a1dabeae3..59fff91e7b 100644 --- a/src/qml/jsruntime/qv4runtime.cpp +++ b/src/qml/jsruntime/qv4runtime.cpp @@ -748,28 +748,38 @@ ReturnedValue Runtime::method_getIterator(ExecutionEngine *engine, const Value & ReturnedValue Runtime::method_iteratorNext(ExecutionEngine *engine, const Value &iterator, Value *value) { + // if we throw an exception from here, return true, not undefined. This is to ensure iteratorDone is set to true + // and the stack unwinding won't close the iterator Q_ASSERT(iterator.isObject()); Scope scope(engine); ScopedFunctionObject f(scope, static_cast<const Object &>(iterator).get(engine->id_next())); - if (!f) - return engine->throwTypeError(); + if (!f) { + engine->throwTypeError(); + return Encode(true); + } JSCallData cData(scope, 0, nullptr, &iterator); ScopedObject o(scope, f->call(cData)); - if (!o) - return engine->throwTypeError(); + if (scope.hasException()) + return Encode(true); + if (!o) { + engine->throwTypeError(); + return Encode(true); + } + ScopedValue d(scope, o->get(engine->id_done())); if (scope.hasException()) - return Encode::undefined(); + return Encode(true); bool done = d->toBoolean(); if (done) { *value = Encode::undefined(); - } else { - *value = o->get(engine->id_value()); - if (scope.hasException()) - return Encode::undefined(); + return Encode(true); } - return Encode(done); + + *value = o->get(engine->id_value()); + if (scope.hasException()) + return Encode(true); + return Encode(false); } ReturnedValue Runtime::method_iteratorClose(ExecutionEngine *engine, const Value &iterator, const Value &done) |