diff options
author | Ulf Hermann <ulf.hermann@qt.io> | 2023-09-12 12:16:47 +0200 |
---|---|---|
committer | Ulf Hermann <ulf.hermann@qt.io> | 2023-09-21 10:11:05 +0200 |
commit | a173d50a9e54d2a21a5207f6c66bb54bb8f3a612 (patch) | |
tree | 4b433bf9a693da88dbb7e5d995adbf996dd79b20 /src/qml | |
parent | af24ed58c250cce32e8d2dc12cfc36de79706f92 (diff) |
QmlCompiler: Implement GetIterator and IteratorNext
Each GetIterator generates
* A unique iterator variable that keeps track of the current index
* In the case of for...of a copy of reference to the list being iterated
The result register holds a pointer to the unique iterator so that it
can be loaded and stored without resetting it.
In order to do anything meaningful with iterators (in the tests) we also
need to allow LoadElement with our "optional" types. That is a
conversion of undefined and some other type to QVariant or
QJSPrimitiveValue. This follows the same pattern as the other
"optional"s we already have.
For...of is currently not testable because it requires exception
handlers. The tests will be added once we get exception handlers.
Task-number: QTBUG-116725
Change-Id: I167fe16b983dc34bf86e1840dfcbf2bf682eecc1
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Diffstat (limited to 'src/qml')
-rw-r--r-- | src/qml/jsapi/qjslist.h | 63 |
1 files changed, 63 insertions, 0 deletions
diff --git a/src/qml/jsapi/qjslist.h b/src/qml/jsapi/qjslist.h index aeba3ec4b2..f55d669a41 100644 --- a/src/qml/jsapi/qjslist.h +++ b/src/qml/jsapi/qjslist.h @@ -43,6 +43,17 @@ struct QJSList : private QJSListIndexClamp QJSList(List *list, QJSEngine *engine) : m_list(list), m_engine(engine) {} + Value at(int index) const + { + Q_ASSERT(index >= 0 && index < size()); + return *(m_list->cbegin() + index); + } + + int size() const + { + return int(std::min(m_list->size(), qsizetype(std::numeric_limits<int>::max()))); + } + void resize(int size) { m_list->resize(size); @@ -157,6 +168,17 @@ struct QJSList<QQmlListProperty<QObject>, QObject *> : private QJSListIndexClam QJSList(QQmlListProperty<QObject> *list, QJSEngine *engine) : m_list(list), m_engine(engine) {} + QObject *at(int index) const + { + Q_ASSERT(index >= 0 && index < size()); + return m_list->at(m_list, index); + } + + int size() const + { + return int(std::min(m_list->count(m_list), qsizetype(std::numeric_limits<int>::max()))); + } + void resize(int size) { qsizetype current = m_list->count(m_list); @@ -308,6 +330,47 @@ private: QJSEngine *m_engine = nullptr; }; +struct QJSListForInIterator +{ +public: + using Ptr = QJSListForInIterator *; + template<typename List, typename Value> + void init(const QJSList<List, Value> &list) + { + m_index = 0; + m_size = list.size(); + } + + bool hasNext() const { return m_index < m_size; } + int next() { return m_index++; } + +private: + int m_index; + int m_size; +}; + +// QJSListForInIterator must not require initialization so that we can jump over it with goto. +static_assert(std::is_trivial_v<QJSListForInIterator>); + +struct QJSListForOfIterator +{ +public: + using Ptr = QJSListForOfIterator *; + void init() { m_index = 0; } + + template<typename List, typename Value> + bool hasNext(const QJSList<List, Value> &list) const { return m_index < list.size(); } + + template<typename List, typename Value> + Value next(const QJSList<List, Value> &list) { return list.at(m_index++); } + +private: + int m_index; +}; + +// QJSListForOfIterator must not require initialization so that we can jump over it with goto. +static_assert(std::is_trivial_v<QJSListForOfIterator>); + QT_END_NAMESPACE #endif // QJSLIST_H |