Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
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(engine, QStringLiteral("WeakMap"));
18}
19
21{
22 Heap::FunctionObject::init(engine, 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());
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
51 ScopedValue obj(scope);
52 Value *arguments = scope.alloc(2);
53 ScopedValue done(scope);
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 }
78 }
79 }
80 return a->asReturnedValue();
81
82}
83
84ReturnedValue WeakMapCtor::virtualCallAsConstructor(const FunctionObject *f, const Value *argv, int argc, const Value *newTarget)
85{
86 return construct(f, argv, argc, newTarget, true);
87}
88
90{
91 Scope scope(f);
92 return scope.engine->throwTypeError(QString::fromLatin1("(Weak)Map requires new"));
93}
94
95
96ReturnedValue MapCtor::virtualCallAsConstructor(const FunctionObject *f, const Value *argv, int argc, const Value *newTarget)
97{
98 return construct(f, argv, argc, newTarget, false);
99}
100
102{
103 Scope scope(engine);
104 ScopedObject o(scope);
105 ctor->defineReadonlyConfigurableProperty(engine->id_length(), Value::fromInt32(0));
106 ctor->defineReadonlyProperty(engine->id_prototype(), (o = this));
107 defineDefaultProperty(engine->id_constructor(), (o = ctor));
108
109 defineDefaultProperty(QStringLiteral("delete"), method_delete, 1);
110 defineDefaultProperty(QStringLiteral("get"), method_get, 1);
111 defineDefaultProperty(QStringLiteral("has"), method_has, 1);
112 defineDefaultProperty(QStringLiteral("set"), method_set, 2);
113
114 ScopedString val(scope, engine->newString(QLatin1String("WeakMap")));
115 defineReadonlyConfigurableProperty(engine->symbol_toStringTag(), val);
116}
117
118
120{
121 Scope scope(engine);
122 ScopedObject o(scope);
123 ctor->defineReadonlyConfigurableProperty(engine->id_length(), Value::fromInt32(0));
124 ctor->defineReadonlyProperty(engine->id_prototype(), (o = this));
125 ctor->addSymbolSpecies();
126 defineDefaultProperty(engine->id_constructor(), (o = ctor));
127
128 defineDefaultProperty(QStringLiteral("clear"), method_clear, 0);
129 defineDefaultProperty(QStringLiteral("delete"), method_delete, 1);
130 defineDefaultProperty(QStringLiteral("forEach"), method_forEach, 1);
131 defineDefaultProperty(QStringLiteral("get"), method_get, 1);
132 defineDefaultProperty(QStringLiteral("has"), method_has, 1);
133 defineDefaultProperty(QStringLiteral("keys"), method_keys, 0);
134 defineDefaultProperty(QStringLiteral("set"), method_set, 2);
135 defineAccessorProperty(QStringLiteral("size"), method_get_size, nullptr);
136 defineDefaultProperty(QStringLiteral("values"), method_values, 0);
137
138 // Per the spec, the value for entries/@@iterator is the same
139 ScopedString valString(scope, scope.engine->newIdentifier(QStringLiteral("entries")));
141 defineDefaultProperty(QStringLiteral("entries"), entriesFn);
142 defineDefaultProperty(engine->symbol_iterator(), entriesFn);
143
144 ScopedString val(scope, engine->newString(QLatin1String("Map")));
145 defineReadonlyConfigurableProperty(engine->symbol_toStringTag(), val);
146}
147
149{
150 Object::init();
151 esTable = new ESTable();
152}
153
155{
156 delete esTable;
157 esTable = nullptr;
158}
159
161{
162 esTable->removeUnmarkedKeys();
163}
164
166{
167 MapObject *m = static_cast<MapObject *>(that);
168 m->esTable->markObjects(markStack, m->isWeakMap);
169 Object::markObjects(that, markStack);
170}
171
172ReturnedValue WeakMapPrototype::method_delete(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc)
173{
174 Scope scope(b);
175 Scoped<MapObject> that(scope, thisObject);
176 if (!that || !that->d()->isWeakMap)
177 return scope.engine->throwTypeError();
178 if (!argc || !argv[0].isObject())
179 return Encode(false);
180
181 return Encode(that->d()->esTable->remove(argv[0]));
182
183}
184
185ReturnedValue WeakMapPrototype::method_get(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc)
186{
187 Scope scope(b);
188 Scoped<MapObject> that(scope, thisObject);
189 if (!that || !that->d()->isWeakMap)
190 return scope.engine->throwTypeError();
191 if (!argc || !argv[0].isObject())
192 return Encode::undefined();
193
194 return that->d()->esTable->get(argv[0]);
195}
196
197ReturnedValue WeakMapPrototype::method_has(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc)
198{
199 Scope scope(b);
200 Scoped<MapObject> that(scope, thisObject);
201 if (!that || !that->d()->isWeakMap)
202 return scope.engine->throwTypeError();
203 if (!argc || !argv[0].isObject())
204 return Encode(false);
205
206 return Encode(that->d()->esTable->has(argv[0]));
207}
208
209ReturnedValue WeakMapPrototype::method_set(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc)
210{
211 Scope scope(b);
212 Scoped<MapObject> that(scope, thisObject);
213 if ((!that || !that->d()->isWeakMap) ||
214 (!argc || !argv[0].isObject()))
215 return scope.engine->throwTypeError();
216
217 that->d()->esTable->set(argv[0], argc > 1 ? argv[1] : Value::undefinedValue());
218 return that.asReturnedValue();
219}
220
221
222ReturnedValue MapPrototype::method_clear(const FunctionObject *b, const Value *thisObject, const Value *, int)
223{
224 Scope scope(b);
225 Scoped<MapObject> that(scope, thisObject);
226 if (!that || that->d()->isWeakMap)
227 return scope.engine->throwTypeError();
228
229 that->d()->esTable->clear();
230 return Encode::undefined();
231}
232
233ReturnedValue MapPrototype::method_delete(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc)
234{
235 Scope scope(b);
236 Scoped<MapObject> that(scope, thisObject);
237 if (!that || that->d()->isWeakMap)
238 return scope.engine->throwTypeError();
239
240 return Encode(that->d()->esTable->remove(argc ? argv[0] : Value::undefinedValue()));
241}
242
244{
245 Scope scope(b);
246 Scoped<MapObject> that(scope, thisObject);
247 if (!that || that->d()->isWeakMap)
248 return scope.engine->throwTypeError();
249
250 Scoped<MapIteratorObject> ao(scope, scope.engine->newMapIteratorObject(that));
251 ao->d()->iterationKind = IteratorKind::KeyValueIteratorKind;
252 return ao->asReturnedValue();
253}
254
255ReturnedValue MapPrototype::method_forEach(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc)
256{
257 Scope scope(b);
258 Scoped<MapObject> that(scope, thisObject);
259 if (!that || that->d()->isWeakMap)
260 return scope.engine->throwTypeError();
261
262 ScopedFunctionObject callbackfn(scope, argv[0]);
263 if (!callbackfn)
264 return scope.engine->throwTypeError();
265
266 ScopedValue thisArg(scope, Value::undefinedValue());
267 if (argc > 1)
268 thisArg = ScopedValue(scope, argv[1]);
269
270 Value *arguments = scope.alloc(3);
271 arguments[2] = that;
272 for (uint i = 0; i < that->d()->esTable->size(); ++i) {
273 that->d()->esTable->iterate(i, &arguments[1], &arguments[0]); // fill in key (0), value (1)
274
275 callbackfn->call(thisArg, arguments, 3);
277 }
278 return Encode::undefined();
279}
280
281ReturnedValue MapPrototype::method_get(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc)
282{
283 Scope scope(b);
284 Scoped<MapObject> that(scope, thisObject);
285 if (!that || that->d()->isWeakMap)
286 return scope.engine->throwTypeError();
287
288 return that->d()->esTable->get(argc ? argv[0] : Value::undefinedValue());
289}
290
291ReturnedValue MapPrototype::method_has(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc)
292{
293 Scope scope(b);
294 Scoped<MapObject> that(scope, thisObject);
295 if (!that || that->d()->isWeakMap)
296 return scope.engine->throwTypeError();
297
298 return Encode(that->d()->esTable->has(argc ? argv[0] : Value::undefinedValue()));
299}
300
301ReturnedValue MapPrototype::method_keys(const FunctionObject *b, const Value *thisObject, const Value *, int)
302{
303 Scope scope(b);
304 Scoped<MapObject> that(scope, thisObject);
305 if (!that || that->d()->isWeakMap)
306 return scope.engine->throwTypeError();
307
308 Scoped<MapIteratorObject> ao(scope, scope.engine->newMapIteratorObject(that));
309 ao->d()->iterationKind = IteratorKind::KeyIteratorKind;
310 return ao->asReturnedValue();
311}
312
313ReturnedValue MapPrototype::method_set(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc)
314{
315 Scope scope(b);
316 Scoped<MapObject> that(scope, thisObject);
317 if (!that || that->d()->isWeakMap)
318 return scope.engine->throwTypeError();
319
320 that->d()->esTable->set(argc ? argv[0] : Value::undefinedValue(), argc > 1 ? argv[1] : Value::undefinedValue());
321 return that.asReturnedValue();
322}
323
325{
326 Scope scope(b);
327 Scoped<MapObject> that(scope, thisObject);
328 if (!that || that->d()->isWeakMap)
329 return scope.engine->throwTypeError();
330
331 return Encode(that->d()->esTable->size());
332}
333
334ReturnedValue MapPrototype::method_values(const FunctionObject *b, const Value *thisObject, const Value *, int)
335{
336 Scope scope(b);
337 Scoped<MapObject> that(scope, thisObject);
338 if (!that || that->d()->isWeakMap)
339 return scope.engine->throwTypeError();
340
341 Scoped<MapIteratorObject> ao(scope, scope.engine->newMapIteratorObject(that));
342 ao->d()->iterationKind = IteratorKind::ValueIteratorKind;
343 return ao->asReturnedValue();
344}
static QString fromLatin1(QByteArrayView ba)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qstring.cpp:5871
void markObjects(MarkStack *s, bool isWeakMap)
ObjectType::Data * allocate(Args &&... args)
Definition qv4mm_p.h:298
void registerWeakMap(Heap::MapObject *map)
Definition qv4mm.cpp:1389
QList< QVariant > arguments
Scoped< FunctionObject > ScopedFunctionObject
quint64 ReturnedValue
@ KeyValueIteratorKind
@ ValueIteratorKind
@ KeyIteratorKind
Scoped< String > ScopedString
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:34
#define CHECK_EXCEPTION()
#define DEFINE_OBJECT_VTABLE(classname)
QJSEngine engine
[0]
static constexpr ReturnedValue undefined()
MemoryManager * memoryManager
Object * weakMapPrototype() const
Heap::Object * newMapIteratorObject(Object *o)
Heap::String * newString(char16_t c)
Heap::String * newIdentifier(const QString &text)
ReturnedValue throwTypeError()
static Heap::FunctionObject * createBuiltinFunction(ExecutionEngine *engine, StringOrSymbol *nameOrSymbol, VTable::Call code, int argumentCount)
void init(ExecutionEngine *engine)
static void markObjects(Heap::Base *that, MarkStack *markStack)
void init(ExecutionEngine *engine)
ExecutionEngine * engine() const
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)
static PropertyKey fromArrayIndex(uint idx)
static ReturnedValue call(ExecutionEngine *, const Value &, int)
static ReturnedValue call(ExecutionEngine *, const Value &)
static ReturnedValue call(ExecutionEngine *, const Value &, Value *)
Value * alloc(qint64 nValues) const =delete
bool hasException() const
ExecutionEngine * engine
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)