diff options
author | Lars Knoll <lars.knoll@qt.io> | 2018-05-14 14:12:33 +0200 |
---|---|---|
committer | Lars Knoll <lars.knoll@qt.io> | 2018-05-14 19:32:42 +0000 |
commit | c4ef0d6e4b5bb7de7b0ab08928d693988a60b25d (patch) | |
tree | 0ff9682886da081c2d8e89becfd90cfb7083540d /src/qml/jsruntime | |
parent | d8eade23bc4fdd7040204f4374ef26975b94ea0a (diff) |
Call iterator.return when required in destructuring assignments
Array destructuring assignments require a call to iterator.return if
the iterator hasn't been exhausted during destructuring.
Change-Id: I39fe4bc01bef6fb2ad3bda92caf6779fbbddc8e2
Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
Diffstat (limited to 'src/qml/jsruntime')
-rw-r--r-- | src/qml/jsruntime/qv4engine.cpp | 1 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4engine_p.h | 2 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4runtime.cpp | 33 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4runtimeapi_p.h | 1 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4vme_moth.cpp | 6 |
5 files changed, 43 insertions, 0 deletions
diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp index 8227fe0184..96855b6155 100644 --- a/src/qml/jsruntime/qv4engine.cpp +++ b/src/qml/jsruntime/qv4engine.cpp @@ -270,6 +270,7 @@ ExecutionEngine::ExecutionEngine(QJSEngine *jsEngine) jsStrings[String_lastIndex] = newIdentifier(QStringLiteral("lastIndex")); jsStrings[String_next] = newIdentifier(QStringLiteral("next")); jsStrings[String_done] = newIdentifier(QStringLiteral("done")); + jsStrings[String_return] = newIdentifier(QStringLiteral("return")); jsSymbols[Symbol_hasInstance] = Symbol::create(this, QStringLiteral("@Symbol.hasInstance")); jsSymbols[Symbol_isConcatSpreadable] = Symbol::create(this, QStringLiteral("@Symbol.isConcatSpreadable")); diff --git a/src/qml/jsruntime/qv4engine_p.h b/src/qml/jsruntime/qv4engine_p.h index 46bf58de07..e90be8e896 100644 --- a/src/qml/jsruntime/qv4engine_p.h +++ b/src/qml/jsruntime/qv4engine_p.h @@ -329,6 +329,7 @@ public: String_lastIndex, String_next, String_done, + String_return, NJSStrings }; @@ -389,6 +390,7 @@ public: String *id_lastIndex() const { return reinterpret_cast<String *>(jsStrings + String_lastIndex); } String *id_next() const { return reinterpret_cast<String *>(jsStrings + String_next); } String *id_done() const { return reinterpret_cast<String *>(jsStrings + String_done); } + String *id_return() const { return reinterpret_cast<String *>(jsStrings + String_return); } Symbol *symbol_hasInstance() const { return reinterpret_cast<Symbol *>(jsSymbols + Symbol_hasInstance); } Symbol *symbol_isConcatSpreadable() const { return reinterpret_cast<Symbol *>(jsSymbols + Symbol_isConcatSpreadable); } diff --git a/src/qml/jsruntime/qv4runtime.cpp b/src/qml/jsruntime/qv4runtime.cpp index 650f5c6735..6eff9c50db 100644 --- a/src/qml/jsruntime/qv4runtime.cpp +++ b/src/qml/jsruntime/qv4runtime.cpp @@ -737,6 +737,39 @@ ReturnedValue Runtime::method_iteratorNext(ExecutionEngine *engine, const Value return Encode(done); } +ReturnedValue Runtime::method_iteratorClose(ExecutionEngine *engine, const Value &iterator, const Value &done) +{ + Q_ASSERT(iterator.isObject()); + Q_ASSERT(done.isBoolean()); + if (done.booleanValue()) + return Encode::undefined(); + + Scope scope(engine); + bool hadException = engine->hasException; + ScopedValue e(scope); + if (hadException) { + e = *engine->exceptionValue; + engine->hasException = false; + } + ScopedFunctionObject f(scope, static_cast<const Object &>(iterator).get(engine->id_return())); + ScopedObject o(scope); + if (f) { + JSCallData cData(scope, 0, nullptr, &iterator); + o = f->call(cData); + } + if (hadException || !f) { + *engine->exceptionValue = e; + engine->hasException = hadException; + return Encode::undefined(); + } + if (engine->hasException) + return Encode::undefined(); + + if (!o) + return engine->throwTypeError(); + return Encode::undefined(); +} + ReturnedValue Runtime::method_destructureRestElement(ExecutionEngine *engine, const Value &iterator) { Q_ASSERT(iterator.isObject()); diff --git a/src/qml/jsruntime/qv4runtimeapi_p.h b/src/qml/jsruntime/qv4runtimeapi_p.h index a22a053cd1..266dc36680 100644 --- a/src/qml/jsruntime/qv4runtimeapi_p.h +++ b/src/qml/jsruntime/qv4runtimeapi_p.h @@ -147,6 +147,7 @@ struct ExceptionCheck<void (*)(QV4::NoThrowEngine *, A, B, C)> { /* for-in, for-of and array destructuring */ \ F(ReturnedValue, getIterator, (ExecutionEngine *engine, const Value &in, int iterator)) \ F(ReturnedValue, iteratorNext, (ExecutionEngine *engine, const Value &iterator, Value *value)) \ + F(ReturnedValue, iteratorClose, (ExecutionEngine *engine, const Value &iterator, const Value &done)) \ F(ReturnedValue, destructureRestElement, (ExecutionEngine *engine, const Value &iterator)) \ \ /* unary operators */ \ diff --git a/src/qml/jsruntime/qv4vme_moth.cpp b/src/qml/jsruntime/qv4vme_moth.cpp index 17ed1ae044..f39fd39a98 100644 --- a/src/qml/jsruntime/qv4vme_moth.cpp +++ b/src/qml/jsruntime/qv4vme_moth.cpp @@ -965,6 +965,12 @@ QV4::ReturnedValue VME::interpret(CppStackFrame &frame, const uchar *code) CHECK_EXCEPTION; MOTH_END_INSTR(IteratorNext) + MOTH_BEGIN_INSTR(IteratorClose) + STORE_ACC(); + acc = Runtime::method_iteratorClose(engine, accumulator, STACK_VALUE(done)); + CHECK_EXCEPTION; + MOTH_END_INSTR(IteratorClose) + MOTH_BEGIN_INSTR(DestructureRestElement) STORE_ACC(); acc = Runtime::method_destructureRestElement(engine, ACC); |