Qt 6.x
The Qt SDK
Loading...
Searching...
No Matches
qv4mapobject.cpp
Go to the documentation of this file.
1// Copyright (C) 2018 Crimson AS <info@crimson.no>
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include "qv4mapobject_p.h"
5#include "qv4mapiterator_p.h"
6#include "qv4estable_p.h"
7#include "qv4symbol_p.h"
8
9using namespace QV4;
10
14
16{
17 Heap::FunctionObject::init(scope, QStringLiteral("WeakMap"));
18}
19
21{
22 Heap::FunctionObject::init(scope, QStringLiteral("Map"));
23}
24
25ReturnedValue WeakMapCtor::construct(const FunctionObject *f, const Value *argv, int argc, const Value *newTarget, bool weakMap)
26{
27 Scope scope(f);
28 Scoped<MapObject> a(scope, scope.engine->memoryManager->allocate<MapObject>());
29 bool protoSet = false;
30 if (newTarget)
31 protoSet = a->setProtoFromNewTarget(newTarget);
32 if (!protoSet && weakMap) {
33 a->setPrototypeOf(scope.engine->weakMapPrototype());
34 scope.engine->memoryManager->registerWeakMap(a->d());
35 }
36 a->d()->isWeakMap = weakMap;
37
38 if (argc > 0) {
39 ScopedValue iterable(scope, argv[0]);
40
41 if (!iterable->isNullOrUndefined()) {
42 ScopedFunctionObject adder(scope, a->get(ScopedString(scope, scope.engine->newString(QString::fromLatin1("set")))));
43 if (!adder)
44 return scope.engine->throwTypeError();
45
46 ScopedObject iter(scope, Runtime::GetIterator::call(scope.engine, iterable, true));
47 if (scope.hasException())
48 return Encode::undefined();
50
52 Value *arguments = scope.alloc(2);
54 forever {
56 if (scope.hasException())
57 break;
58 if (done->toBoolean())
59 return a->asReturnedValue();
60 const Object *o = obj->objectValue();
61 if (!o) {
62 scope.engine->throwTypeError();
63 break;
64 }
65
67 if (scope.hasException())
68 break;
70 if (scope.hasException())
71 break;
72
73 adder->call(a, arguments, 2);
74 if (scope.hasException())
75 break;
76 }
77 ScopedValue falsey(scope, Encode(false));
78 return Runtime::IteratorClose::call(scope.engine, iter, falsey);
79 }
80 }
81 return a->asReturnedValue();
82
83}
84
85ReturnedValue WeakMapCtor::virtualCallAsConstructor(const FunctionObject *f, const Value *argv, int argc, const Value *newTarget)
86{
87 return construct(f, argv, argc, newTarget, true);
88}
89
91{
92 Scope scope(f);
93 return scope.engine->throwTypeError(QString::fromLatin1("(Weak)Map requires new"));
94}
95
96
97ReturnedValue MapCtor::virtualCallAsConstructor(const FunctionObject *f, const Value *argv, int argc, const Value *newTarget)
98{
99 return construct(f, argv, argc, newTarget, false);
100}
101
103{
104 Scope scope(engine);
105 ScopedObject o(scope);
107 ctor->defineReadonlyProperty(engine->id_prototype(), (o = this));
108 defineDefaultProperty(engine->id_constructor(), (o = ctor));
109
110 defineDefaultProperty(QStringLiteral("delete"), method_delete, 1);
111 defineDefaultProperty(QStringLiteral("get"), method_get, 1);
112 defineDefaultProperty(QStringLiteral("has"), method_has, 1);
113 defineDefaultProperty(QStringLiteral("set"), method_set, 2);
114
115 ScopedString val(scope, engine->newString(QLatin1String("WeakMap")));
116 defineReadonlyConfigurableProperty(engine->symbol_toStringTag(), val);
117}
118
119
121{
122 Scope scope(engine);
123 ScopedObject o(scope);
125 ctor->defineReadonlyProperty(engine->id_prototype(), (o = this));
126 ctor->addSymbolSpecies();
127 defineDefaultProperty(engine->id_constructor(), (o = ctor));
128
129 defineDefaultProperty(QStringLiteral("clear"), method_clear, 0);
130 defineDefaultProperty(QStringLiteral("delete"), method_delete, 1);
131 defineDefaultProperty(QStringLiteral("forEach"), method_forEach, 1);
132 defineDefaultProperty(QStringLiteral("get"), method_get, 1);
133 defineDefaultProperty(QStringLiteral("has"), method_has, 1);
134 defineDefaultProperty(QStringLiteral("keys"), method_keys, 0);
135 defineDefaultProperty(QStringLiteral("set"), method_set, 2);
136 defineAccessorProperty(QStringLiteral("size"), method_get_size, nullptr);
137 defineDefaultProperty(QStringLiteral("values"), method_values, 0);
138
139 // Per the spec, the value for entries/@@iterator is the same
140 ScopedString valString(scope, scope.engine->newIdentifier(QStringLiteral("entries")));
142 defineDefaultProperty(QStringLiteral("entries"), entriesFn);
143 defineDefaultProperty(engine->symbol_iterator(), entriesFn);
144
145 ScopedString val(scope, engine->newString(QLatin1String("Map")));
146 defineReadonlyConfigurableProperty(engine->symbol_toStringTag(), val);
147}
148
150{
151 Object::init();
152 esTable = new ESTable();
153}
154
156{
157 delete esTable;
158 esTable = nullptr;
159}
160
162{
163 esTable->removeUnmarkedKeys();
164}
165
167{
168 MapObject *m = static_cast<MapObject *>(that);
169 m->esTable->markObjects(markStack, m->isWeakMap);
170 Object::markObjects(that, markStack);
171}
172
173ReturnedValue WeakMapPrototype::method_delete(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc)
174{
175 Scope scope(b);
176 Scoped<MapObject> that(scope, thisObject);
177 if (!that || !that->d()->isWeakMap)
178 return scope.engine->throwTypeError();
179 if (!argc || !argv[0].isObject())
180 return Encode(false);
181
182 return Encode(that->d()->esTable->remove(argv[0]));
183
184}
185
186ReturnedValue WeakMapPrototype::method_get(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc)
187{
188 Scope scope(b);
189 Scoped<MapObject> that(scope, thisObject);
190 if (!that || !that->d()->isWeakMap)
191 return scope.engine->throwTypeError();
192 if (!argc || !argv[0].isObject())
193 return Encode::undefined();
194
195 return that->d()->esTable->get(argv[0]);
196}
197
198ReturnedValue WeakMapPrototype::method_has(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc)
199{
200 Scope scope(b);
201 Scoped<MapObject> that(scope, thisObject);
202 if (!that || !that->d()->isWeakMap)
203 return scope.engine->throwTypeError();
204 if (!argc || !argv[0].isObject())
205 return Encode(false);
206
207 return Encode(that->d()->esTable->has(argv[0]));
208}
209
210ReturnedValue WeakMapPrototype::method_set(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc)
211{
212 Scope scope(b);
213 Scoped<MapObject> that(scope, thisObject);
214 if ((!that || !that->d()->isWeakMap) ||
215 (!argc || !argv[0].isObject()))
216 return scope.engine->throwTypeError();
217
218 that->d()->esTable->set(argv[0], argc > 1 ? argv[1] : Value::undefinedValue());
219 return that.asReturnedValue();
220}
221
222
223ReturnedValue MapPrototype::method_clear(const FunctionObject *b, const Value *thisObject, const Value *, int)
224{
225 Scope scope(b);
226 Scoped<MapObject> that(scope, thisObject);
227 if (!that || that->d()->isWeakMap)
228 return scope.engine->throwTypeError();
229
230 that->d()->esTable->clear();
231 return Encode::undefined();
232}
233
234ReturnedValue MapPrototype::method_delete(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc)
235{
236 Scope scope(b);
237 Scoped<MapObject> that(scope, thisObject);
238 if (!that || that->d()->isWeakMap)
239 return scope.engine->throwTypeError();
240
241 return Encode(that->d()->esTable->remove(argc ? argv[0] : Value::undefinedValue()));
242}
243
245{
246 Scope scope(b);
247 Scoped<MapObject> that(scope, thisObject);
248 if (!that || that->d()->isWeakMap)
249 return scope.engine->throwTypeError();
250
252 ao->d()->iterationKind = IteratorKind::KeyValueIteratorKind;
253 return ao->asReturnedValue();
254}
255
256ReturnedValue MapPrototype::method_forEach(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc)
257{
258 Scope scope(b);
259 Scoped<MapObject> that(scope, thisObject);
260 if (!that || that->d()->isWeakMap)
261 return scope.engine->throwTypeError();
262
263 ScopedFunctionObject callbackfn(scope, argv[0]);
264 if (!callbackfn)
265 return scope.engine->throwTypeError();
266
267 ScopedValue thisArg(scope, Value::undefinedValue());
268 if (argc > 1)
269 thisArg = ScopedValue(scope, argv[1]);
270
271 Value *arguments = scope.alloc(3);
272 arguments[2] = that;
273 for (uint i = 0; i < that->d()->esTable->size(); ++i) {
274 that->d()->esTable->iterate(i, &arguments[1], &arguments[0]); // fill in key (0), value (1)
275
276 callbackfn->call(thisArg, arguments, 3);
278 }
279 return Encode::undefined();
280}
281
282ReturnedValue MapPrototype::method_get(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc)
283{
284 Scope scope(b);
285 Scoped<MapObject> that(scope, thisObject);
286 if (!that || that->d()->isWeakMap)
287 return scope.engine->throwTypeError();
288
289 return that->d()->esTable->get(argc ? argv[0] : Value::undefinedValue());
290}
291
292ReturnedValue MapPrototype::method_has(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc)
293{
294 Scope scope(b);
295 Scoped<MapObject> that(scope, thisObject);
296 if (!that || that->d()->isWeakMap)
297 return scope.engine->throwTypeError();
298
299 return Encode(that->d()->esTable->has(argc ? argv[0] : Value::undefinedValue()));
300}
301
302ReturnedValue MapPrototype::method_keys(const FunctionObject *b, const Value *thisObject, const Value *, int)
303{
304 Scope scope(b);
305 Scoped<MapObject> that(scope, thisObject);
306 if (!that || that->d()->isWeakMap)
307 return scope.engine->throwTypeError();
308
310 ao->d()->iterationKind = IteratorKind::KeyIteratorKind;
311 return ao->asReturnedValue();
312}
313
314ReturnedValue MapPrototype::method_set(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc)
315{
316 Scope scope(b);
317 Scoped<MapObject> that(scope, thisObject);
318 if (!that || that->d()->isWeakMap)
319 return scope.engine->throwTypeError();
320
321 that->d()->esTable->set(argc ? argv[0] : Value::undefinedValue(), argc > 1 ? argv[1] : Value::undefinedValue());
322 return that.asReturnedValue();
323}
324
326{
327 Scope scope(b);
328 Scoped<MapObject> that(scope, thisObject);
329 if (!that || that->d()->isWeakMap)
330 return scope.engine->throwTypeError();
331
332 return Encode(that->d()->esTable->size());
333}
334
335ReturnedValue MapPrototype::method_values(const FunctionObject *b, const Value *thisObject, const Value *, int)
336{
337 Scope scope(b);
338 Scoped<MapObject> that(scope, thisObject);
339 if (!that || that->d()->isWeakMap)
340 return scope.engine->throwTypeError();
341
343 ao->d()->iterationKind = IteratorKind::ValueIteratorKind;
344 return ao->asReturnedValue();
345}
static QString fromLatin1(QByteArrayView ba)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qstring.cpp:5710
void markObjects(MarkStack *s, bool isWeakMap)
QList< QVariant > arguments
\qmltype Particle \inqmlmodule QtQuick.Particles
quint64 ReturnedValue
@ KeyValueIteratorKind
@ ValueIteratorKind
@ KeyIteratorKind
DBusConnection const char DBusError DBusBusType DBusError return DBusConnection DBusHandleMessageFunction void DBusFreeFunction return DBusConnection return DBusConnection return const char DBusError return DBusConnection DBusMessage dbus_uint32_t return DBusConnection dbus_bool_t DBusConnection DBusAddWatchFunction DBusRemoveWatchFunction DBusWatchToggledFunction void DBusFreeFunction return DBusConnection DBusDispatchStatusFunction void DBusFreeFunction DBusTimeout return DBusTimeout return DBusWatch return DBusWatch unsigned int return DBusError const DBusError return const DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessageIter * iter
#define forever
Definition qforeach.h:78
GLboolean GLboolean GLboolean b
const GLfloat * m
GLboolean GLboolean GLboolean GLboolean a
[7]
GLfloat GLfloat f
GLhandleARB obj
[2]
GLuint GLfloat * val
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
#define QStringLiteral(str)
unsigned int uint
Definition qtypes.h:29
#define CHECK_EXCEPTION()
#define DEFINE_OBJECT_VTABLE(classname)
QJSEngine engine
[0]
static constexpr ReturnedValue undefined()
Heap::Object * newMapIteratorObject(Object *o)
Heap::String * newIdentifier(const QString &text)
ReturnedValue throwTypeError()
static Heap::FunctionObject * createBuiltinFunction(ExecutionEngine *engine, StringOrSymbol *nameOrSymbol, VTable::Call code, int argumentCount)
Heap::ExecutionContext * scope() const
void init(QV4::ExecutionContext *scope)
static void markObjects(Heap::Base *that, MarkStack *markStack)
void init(QV4::ExecutionContext *scope)
static ReturnedValue method_keys(const FunctionObject *, const Value *thisObject, const Value *argv, int argc)
static ReturnedValue method_get(const FunctionObject *, const Value *thisObject, const Value *argv, int argc)
static ReturnedValue method_delete(const FunctionObject *, const Value *thisObject, const Value *argv, int argc)
static ReturnedValue method_set(const FunctionObject *, const Value *thisObject, const Value *argv, int argc)
static ReturnedValue method_values(const FunctionObject *, const Value *thisObject, const Value *argv, int argc)
void init(ExecutionEngine *engine, Object *ctor)
static ReturnedValue method_clear(const FunctionObject *, const Value *thisObject, const Value *argv, int argc)
static ReturnedValue method_entries(const FunctionObject *, const Value *thisObject, const Value *argv, int argc)
static ReturnedValue method_forEach(const FunctionObject *, const Value *thisObject, const Value *argv, int argc)
static ReturnedValue method_get_size(const FunctionObject *, const Value *thisObject, const Value *argv, int argc)
static ReturnedValue method_has(const FunctionObject *, const Value *thisObject, const Value *argv, int argc)
void addSymbolSpecies()
void defineReadonlyConfigurableProperty(const QString &name, const Value &value)
void defineReadonlyProperty(const QString &name, const Value &value)
static PropertyKey fromArrayIndex(uint idx)
static ReturnedValue call(ExecutionEngine *, const Value &, int)
static ReturnedValue call(ExecutionEngine *, const Value &, const Value &)
static ReturnedValue call(ExecutionEngine *, const Value &, Value *)
Value * alloc(qint64 nValues) const =delete
ExecutionEngine * engine
QML_NEARLY_ALWAYS_INLINE ReturnedValue asReturnedValue() const
bool isNullOrUndefined() const
static constexpr VTable::CallAsConstructor virtualCallAsConstructor
static constexpr VTable::Call virtualCall
static constexpr Value fromInt32(int i)
Definition qv4value_p.h:187
static constexpr Value undefinedValue()
Definition qv4value_p.h:191
bool isObject() const
Definition qv4value_p.h:302
static ReturnedValue construct(const FunctionObject *f, const Value *argv, int argc, const Value *, bool weakMap)
static ReturnedValue method_get(const FunctionObject *, const Value *thisObject, const Value *argv, int argc)
static ReturnedValue method_has(const FunctionObject *, const Value *thisObject, const Value *argv, int argc)
static ReturnedValue method_set(const FunctionObject *, const Value *thisObject, const Value *argv, int argc)
static ReturnedValue method_delete(const FunctionObject *, const Value *thisObject, const Value *argv, int argc)
void init(ExecutionEngine *engine, Object *ctor)