Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qv4objectiterator.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3// Qt-Security score:significant
5#include "qv4object_p.h"
8#include <QtQml/private/qv4functionobject_p.h>
9
10using namespace QV4;
11
12void ForInIteratorPrototype::init(ExecutionEngine *)
13{
14 defineDefaultProperty(QStringLiteral("next"), method_next, 0);
15}
16
17PropertyKey ObjectIterator::next(Property *pd, PropertyAttributes *attrs)
18{
19 if (!object || !iterator)
20 return PropertyKey::invalid();
21
22 Scope scope(engine);
23 ScopedPropertyKey key(scope);
24
25 while (1) {
26 key = iterator->next(object, pd, attrs);
27 if (!key->isValid()) {
28 object = nullptr;
29 return key;
30 }
31 if ((!(flags & WithSymbols) && key->isSymbol()) ||
32 ((flags & EnumerableOnly) && !attrs->isEnumerable()))
33 continue;
34 return key;
35 }
36}
37
38ReturnedValue ObjectIterator::nextPropertyName(Value *value)
39{
40 if (!object)
41 return Encode::null();
42
43 PropertyAttributes attrs;
44 Scope scope(engine);
45 ScopedProperty p(scope);
46 ScopedPropertyKey key(scope, next(p, &attrs));
47 if (!key->isValid())
48 return Encode::null();
49
50 *value = object->getValue(p->value, attrs);
51 if (key->isArrayIndex())
52 return Encode(key->asArrayIndex());
53 Q_ASSERT(key->isStringOrSymbol());
54 return key->asStringOrSymbol()->asReturnedValue();
55}
56
57ReturnedValue ObjectIterator::nextPropertyNameAsString(Value *value)
58{
59 if (!object)
60 return Encode::null();
61
62 PropertyAttributes attrs;
63 Scope scope(engine);
64 ScopedProperty p(scope);
65 ScopedPropertyKey key(scope, next(p, &attrs));
66 if (!key->isValid())
67 return Encode::null();
68
69 *value = object->getValue(p->value, attrs);
70
71 return key->toStringOrSymbol(engine)->asReturnedValue();
72}
73
74ReturnedValue ObjectIterator::nextPropertyNameAsString()
75{
76 if (!object)
77 return Encode::null();
78
79 PropertyAttributes attrs;
80 Scope scope(engine);
81 ScopedPropertyKey key(scope, next(nullptr, &attrs));
82 if (!key->isValid())
83 return Encode::null();
84
85 return key->toStringOrSymbol(engine)->asReturnedValue();
86}
87
88
90
91void Heap::ForInIteratorObject::markObjects(Heap::Base *that, MarkStack *markStack)
92{
93 ForInIteratorObject *o = static_cast<ForInIteratorObject *>(that);
94 if (o->object)
95 o->object->mark(markStack);
96 if (o->current)
97 o->current->mark(markStack);
98 if (o->target)
99 o->target->mark(markStack);
100 o->workArea[0].mark(markStack);
101 o->workArea[1].mark(markStack);
102 Object::markObjects(that, markStack);
103}
104
105void Heap::ForInIteratorObject::destroy()
106{
107 delete iterator;
108}
109
110ReturnedValue ForInIteratorPrototype::method_next(const FunctionObject *b, const Value *thisObject, const Value *, int)
111{
112 const ForInIteratorObject *forIn = static_cast<const ForInIteratorObject *>(thisObject);
113 Q_ASSERT(forIn);
114 Scope scope(b);
115
116 ScopedPropertyKey key(scope, forIn->nextProperty());
117 bool done = false;
118 if (!key->isValid())
119 done = true;
120 ScopedStringOrSymbol s(scope, key->toStringOrSymbol(scope.engine));
121 return IteratorPrototype::createIterResultObject(scope.engine, s, done);
122}
123
124
125PropertyKey ForInIteratorObject::nextProperty() const
126{
127 if (!d()->current)
128 return PropertyKey::invalid();
129
130 Scope scope(this);
131 ScopedObject c(scope, d()->current);
132 ScopedObject t(scope, d()->target);
133 ScopedObject o(scope);
134 ScopedProperty p(scope);
135 ScopedPropertyKey key(scope);
136 PropertyAttributes attrs;
137
138 while (1) {
139 while (1) {
140 key = d()->iterator->next(t, p, &attrs);
141 if (!key->isValid())
142 break;
143 if (!attrs.isEnumerable() || key->isSymbol())
144 continue;
145 // check the property is not already defined earlier in the proto chain
146 if (d()->current != d()->object) {
147 o = d()->object;
148 bool shadowed = false;
149 while (o && o->d() != c->heapObject()) {
150 if (o->getOwnProperty(key) != Attr_Invalid) {
151 shadowed = true;
152 break;
153 }
154 o = o->getPrototypeOf();
155 }
156 if (shadowed)
157 continue;
158 }
159 return key;
160 }
161
162 c = c->getPrototypeOf();
163 d()->current.set(scope.engine, c ? c->d() : nullptr);
164 if (!c)
165 break;
166 delete d()->iterator;
167 d()->iterator = c->ownPropertyKeys(t.getRef());
168 d()->target.set(scope.engine, t->d());
169 if (!d()->iterator) {
170 scope.engine->throwTypeError();
171 return PropertyKey::invalid();
172 }
173 }
174 return PropertyKey::invalid();
175}
DEFINE_OBJECT_VTABLE(ForInIteratorObject)