1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the QtQml module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU Lesser General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU Lesser
19** General Public License version 3 as published by the Free Software
20** Foundation and appearing in the file LICENSE.LGPL3 included in the
21** packaging of this file. Please review the following information to
22** ensure the GNU Lesser General Public License version 3 requirements
23** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24**
25** GNU General Public License Usage
26** Alternatively, this file may be used under the terms of the GNU
27** General Public License version 2.0 or (at your option) the GNU General
28** Public license version 3 or any later version approved by the KDE Free
29** Qt Foundation. The licenses are as published by the Free Software
30** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31** included in the packaging of this file. Please review the following
32** information to ensure the GNU General Public License requirements will
33** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34** https://www.gnu.org/licenses/gpl-3.0.html.
35**
36** $QT_END_LICENSE$
37**
38****************************************************************************/
39
40#include "qjsvalueiterator.h"
41#include "qjsvalueiterator_p.h"
42#include "qjsvalue_p.h"
43#include "private/qv4string_p.h"
44#include "private/qv4object_p.h"
45#include "private/qv4context_p.h"
46
47QT_BEGIN_NAMESPACE
48
49QJSValueIteratorPrivate::QJSValueIteratorPrivate(const QJSValue &v)
50{
51 init(v);
52}
53
54void QJSValueIteratorPrivate::init(const QJSValue &v)
55{
56 engine = nullptr;
57
58 QV4::ExecutionEngine *e = QJSValuePrivate::engine(jsval: &v);
59 if (!e)
60 return;
61 QV4::Object *o = QJSValuePrivate::getValue(jsval: &v)->objectValue();
62 if (!o)
63 return;
64
65 engine = e;
66 object = o;
67 iterator.reset(other: o->ownPropertyKeys(target: object.valueRef()));
68 next();
69}
70
71void QJSValueIteratorPrivate::next()
72{
73 QV4::Object *o = object.as<QV4::Object>();
74 if (!o || !iterator)
75 return;
76
77 QV4::PropertyKey key;
78 while (1) {
79 key = iterator->next(o);
80 if (!key.isSymbol())
81 break;
82 }
83 currentKey = nextKey;
84 nextKey.set(engine, value: key.id());
85}
86
87bool QJSValueIteratorPrivate::isValid() const
88{
89 if (!engine || !iterator)
90 return false;
91 QV4::Value *val = object.valueRef();
92 return (val && val->isObject());
93}
94
95/*!
96 \class QJSValueIterator
97
98 \brief The QJSValueIterator class provides a Java-style iterator for QJSValue.
99
100 \ingroup qtjavascript
101 \inmodule QtQml
102
103
104 The QJSValueIterator constructor takes a QJSValue as
105 argument. After construction, the iterator is located at the very
106 beginning of the sequence of properties. Here's how to iterate over
107 all the properties of a QJSValue:
108
109 \snippet code/src_script_qjsvalueiterator.cpp 0
110
111 The next() advances the iterator. The name() and value()
112 functions return the name and value of the last item that was
113 jumped over.
114
115 Note that QJSValueIterator only iterates over the QJSValue's
116 own properties; i.e. it does not follow the prototype chain. You can
117 use a loop like this to follow the prototype chain:
118
119 \snippet code/src_script_qjsvalueiterator.cpp 1
120
121 \sa QJSValue::property()
122*/
123
124/*!
125 Constructs an iterator for traversing \a object. The iterator is
126 set to be at the front of the sequence of properties (before the
127 first property).
128*/
129QJSValueIterator::QJSValueIterator(const QJSValue& object)
130 : d_ptr(new QJSValueIteratorPrivate(object))
131{
132}
133
134/*!
135 Destroys the iterator.
136*/
137QJSValueIterator::~QJSValueIterator()
138{
139}
140
141/*!
142 Returns true if there is at least one item ahead of the iterator
143 (i.e. the iterator is \e not at the back of the property sequence);
144 otherwise returns false.
145
146 \sa next()
147*/
148bool QJSValueIterator::hasNext() const
149{
150 if (!d_ptr->isValid())
151 return false;
152 return QV4::PropertyKey::fromId(id: d_ptr->nextKey.value()).isValid();
153}
154
155/*!
156 Advances the iterator by one position.
157 Returns true if there was at least one item ahead of the iterator
158 (i.e. the iterator was \e not already at the back of the property sequence);
159 otherwise returns false.
160
161 \sa hasNext(), name()
162*/
163bool QJSValueIterator::next()
164{
165 if (!d_ptr->isValid())
166 return false;
167 d_ptr->next();
168 return QV4::PropertyKey::fromId(id: d_ptr->currentKey.value()).isValid();
169}
170
171/*!
172 Returns the name of the last property that was jumped over using
173 next().
174
175 \sa value()
176*/
177QString QJSValueIterator::name() const
178{
179 if (!d_ptr->isValid())
180 return QString();
181 QV4::Scope scope(d_ptr->engine);
182 QV4::ScopedPropertyKey key(scope, QV4::PropertyKey::fromId(id: d_ptr->currentKey.value()));
183 if (!key->isValid())
184 return QString();
185 Q_ASSERT(!key->isSymbol());
186 return key->toStringOrSymbol(e: d_ptr->engine)->toQString();
187}
188
189
190/*!
191 Returns the value of the last property that was jumped over using
192 next().
193
194 \sa name()
195*/
196QJSValue QJSValueIterator::value() const
197{
198 if (!d_ptr->isValid())
199 return QJSValue();
200 QV4::Scope scope(d_ptr->engine);
201 QV4::ScopedPropertyKey key(scope, QV4::PropertyKey::fromId(id: d_ptr->currentKey.value()));
202 if (!key->isValid())
203 return QJSValue();
204
205 QV4::ScopedObject obj(scope, d_ptr->object.asManaged());
206 QV4::ScopedValue val(scope, obj->get(id: key));
207
208 if (scope.hasException()) {
209 scope.engine->catchException();
210 return QJSValue();
211 }
212 return QJSValue(scope.engine, val->asReturnedValue());
213}
214
215
216/*!
217 Makes the iterator operate on \a object. The iterator is set to be
218 at the front of the sequence of properties (before the first
219 property).
220*/
221QJSValueIterator& QJSValueIterator::operator=(QJSValue& object)
222{
223 d_ptr->init(v: object);
224 return *this;
225}
226
227QT_END_NAMESPACE
228

source code of qtdeclarative/src/qml/jsapi/qjsvalueiterator.cpp