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