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
4#include "qqmllistwrapper_p.h"
5
6#include <QtQml/qqmlinfo.h>
7
8#include <private/qqmllist_p.h>
9
10#include <private/qv4arrayiterator_p.h>
11#include <private/qv4arrayobject_p.h>
12#include <private/qv4functionobject_p.h>
13#include <private/qv4objectiterator_p.h>
14#include <private/qv4objectproto_p.h>
15#include <private/qv4qobjectwrapper_p.h>
16#include <private/qv4symbol_p.h>
17
18QT_BEGIN_NAMESPACE
19
20using namespace QV4;
21using namespace Qt::StringLiterals;
22
23DEFINE_OBJECT_VTABLE(QmlListWrapper);
24
25void Heap::QmlListWrapper::init()
26{
27 Object::init();
28 object.init();
29 QV4::Scope scope(internalClass->engine);
30 QV4::ScopedObject o(scope, this);
31 o->setArrayType(Heap::ArrayData::Custom);
32}
33
34void Heap::QmlListWrapper::destroy()
35{
36 object.destroy();
37 Object::destroy();
38}
39
40ReturnedValue QmlListWrapper::create(ExecutionEngine *engine, QObject *object, int propId, QMetaType propType)
41{
42 if (!object || propId == -1)
43 return Encode::null();
44
45 Scope scope(engine);
46
47 Scoped<QmlListWrapper> r(scope, engine->memoryManager->allocate<QmlListWrapper>());
48 r->d()->object = object;
49 r->d()->propertyType = propType.iface();
50 void *args[] = { &r->d()->property(), nullptr };
51 QMetaObject::metacall(object, QMetaObject::ReadProperty, propId, args);
52 return r.asReturnedValue();
53}
54
55ReturnedValue QmlListWrapper::create(ExecutionEngine *engine, const QQmlListProperty<QObject> &prop, QMetaType propType)
56{
57 Scope scope(engine);
58
59 Scoped<QmlListWrapper> r(scope, engine->memoryManager->allocate<QmlListWrapper>());
60 r->d()->object = prop.object;
61 r->d()->property() = prop;
62 r->d()->propertyType = propType.iface();
63 return r.asReturnedValue();
64}
65
66QVariant QmlListWrapper::toVariant() const
67{
68 if (!d()->object)
69 return QVariant();
70
71 return QVariant::fromValue(value: toListReference());
72}
73
74QQmlListReference QmlListWrapper::toListReference() const
75{
76 Heap::QmlListWrapper *wrapper = d();
77 return QQmlListReferencePrivate::init(wrapper->property(), QMetaType(wrapper->propertyType));
78}
79
80
81ReturnedValue QmlListWrapper::virtualGet(const Managed *m, PropertyKey id, const Value *receiver, bool *hasProperty)
82{
83 Q_ASSERT(m->as<QmlListWrapper>());
84 const QmlListWrapper *w = static_cast<const QmlListWrapper *>(m);
85 QV4::ExecutionEngine *v4 = w->engine();
86
87 if (id.isArrayIndex()) {
88 uint index = id.asArrayIndex();
89 quint32 count = w->d()->property().count ? w->d()->property().count(&w->d()->property()) : 0;
90 if (index < count && w->d()->property().at) {
91 if (hasProperty)
92 *hasProperty = true;
93 return QV4::QObjectWrapper::wrap(engine: v4, object: w->d()->property().at(&w->d()->property(), index));
94 }
95
96 if (hasProperty)
97 *hasProperty = false;
98 return Value::undefinedValue().asReturnedValue();
99 }
100
101 return Object::virtualGet(m, id, receiver, hasProperty);
102}
103
104qint64 QmlListWrapper::virtualGetLength(const Managed *m)
105{
106 Q_ASSERT(m->as<QmlListWrapper>());
107 const QmlListWrapper *w = static_cast<const QmlListWrapper *>(m);
108 return w->toListReference().size();
109}
110
111bool QmlListWrapper::virtualPut(Managed *m, PropertyKey id, const Value &value, Value *receiver)
112{
113 Q_ASSERT(m->as<QmlListWrapper>());
114
115 const auto *w = static_cast<const QmlListWrapper *>(m);
116 QV4::ExecutionEngine *v4 = w->engine();
117
118 QQmlListProperty<QObject> *prop = &(w->d()->property());
119
120 if (id.isArrayIndex()) {
121 if (!prop->count || !prop->replace)
122 return false;
123
124 const uint index = id.asArrayIndex();
125 const int count = prop->count(prop);
126 if (count < 0 || index >= uint(count))
127 return false;
128
129 if (value.isNull()) {
130 prop->replace(prop, index, nullptr);
131 return true;
132 }
133
134 QV4::Scope scope(v4);
135 QV4::ScopedObject so(scope, value.toObject(e: scope.engine));
136 if (auto *wrapper = so->as<QV4::QObjectWrapper>()) {
137 prop->replace(prop, index, wrapper->object());
138 return true;
139 }
140
141 return false;
142 }
143
144 return Object::virtualPut(m, id, value, receiver);
145}
146
147struct QmlListWrapperOwnPropertyKeyIterator : ObjectOwnPropertyKeyIterator
148{
149 ~QmlListWrapperOwnPropertyKeyIterator() override = default;
150 PropertyKey next(const Object *o, Property *pd = nullptr, PropertyAttributes *attrs = nullptr) override;
151
152};
153
154PropertyKey QmlListWrapperOwnPropertyKeyIterator::next(const Object *o, Property *pd, PropertyAttributes *attrs)
155{
156 const QmlListWrapper *w = static_cast<const QmlListWrapper *>(o);
157
158 quint32 count = w->d()->property().count ? w->d()->property().count(&w->d()->property()) : 0;
159 if (arrayIndex < count) {
160 uint index = arrayIndex;
161 ++arrayIndex;
162 if (attrs)
163 *attrs = QV4::Attr_Data;
164 if (pd)
165 pd->value = QV4::QObjectWrapper::wrap(engine: w->engine(), object: w->d()->property().at(&w->d()->property(), index));
166 return PropertyKey::fromArrayIndex(idx: index);
167 } else if (memberIndex == 0) {
168 ++memberIndex;
169 return o->engine()->id_length()->propertyKey();
170 }
171
172 // You cannot add any own properties via the regular JavaScript interfaces.
173 return PropertyKey::invalid();
174}
175
176OwnPropertyKeyIterator *QmlListWrapper::virtualOwnPropertyKeys(const Object *m, Value *target)
177{
178 *target = *m;
179 return new QmlListWrapperOwnPropertyKeyIterator;
180}
181
182void PropertyListPrototype::init()
183{
184 defineDefaultProperty(QStringLiteral("pop"), code: method_pop, argumentCount: 0);
185 defineDefaultProperty(QStringLiteral("push"), code: method_push, argumentCount: 1);
186 defineDefaultProperty(QStringLiteral("shift"), code: method_shift, argumentCount: 0);
187 defineDefaultProperty(QStringLiteral("splice"), code: method_splice, argumentCount: 2);
188 defineDefaultProperty(QStringLiteral("unshift"), code: method_unshift, argumentCount: 1);
189 defineDefaultProperty(QStringLiteral("indexOf"), code: method_indexOf, argumentCount: 1);
190 defineDefaultProperty(QStringLiteral("lastIndexOf"), code: method_lastIndexOf, argumentCount: 1);
191 defineDefaultProperty(QStringLiteral("sort"), code: method_sort, argumentCount: 1);
192 defineAccessorProperty(QStringLiteral("length"), getter: method_get_length, setter: method_set_length);
193}
194
195ReturnedValue PropertyListPrototype::method_pop(const FunctionObject *b, const Value *thisObject, const Value *, int)
196{
197 Scope scope(b);
198 ScopedObject instance(scope, thisObject->toObject(e: scope.engine));
199 if (!instance)
200 RETURN_UNDEFINED();
201
202 QmlListWrapper *w = instance->as<QmlListWrapper>();
203 if (!w)
204 RETURN_UNDEFINED();
205
206 QQmlListProperty<QObject> *property = &w->d()->property();
207
208 if (!property->count)
209 return scope.engine->throwTypeError(message: u"List doesn't define a Count function"_s);
210 const qsizetype len = property->count(property);
211 if (!len)
212 RETURN_UNDEFINED();
213
214 if (!property->at)
215 return scope.engine->throwTypeError(message: u"List doesn't define an At function"_s);
216 ScopedValue result(
217 scope, QV4::QObjectWrapper::wrap(engine: scope.engine, object: property->at(property, len - 1)));
218
219 if (!property->removeLast)
220 return scope.engine->throwTypeError(message: u"List doesn't define a RemoveLast function"_s);
221 property->removeLast(property);
222
223 return result->asReturnedValue();
224}
225
226ReturnedValue PropertyListPrototype::method_push(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc)
227{
228 Scope scope(b);
229 ScopedObject instance(scope, thisObject->toObject(e: scope.engine));
230 if (!instance)
231 RETURN_UNDEFINED();
232 QmlListWrapper *w = instance->as<QmlListWrapper>();
233 if (!w)
234 RETURN_UNDEFINED();
235
236 QQmlListProperty<QObject> *property = &w->d()->property();
237 if (!property->append)
238 return scope.engine->throwTypeError(message: u"List doesn't define an Append function"_s);
239 if (!property->count)
240 return scope.engine->throwTypeError(message: u"List doesn't define a Count function"_s);
241
242 for (int i = 0; i < argc; ++i) {
243 const Value &arg = argv[i];
244 if (!arg.isNull() && !arg.as<QObjectWrapper>())
245 THROW_TYPE_ERROR();
246 }
247
248 const qsizetype length = property->count(property);
249 if (!qIsAtMostUintLimit(length, limit: std::numeric_limits<uint>::max() - argc))
250 return scope.engine->throwRangeError(message: QString::fromLatin1(ba: "List length out of range."));
251
252 for (int i = 0; i < argc; ++i) {
253 if (argv[i].isNull())
254 property->append(property, nullptr);
255 else
256 property->append(property, argv[i].as<QV4::QObjectWrapper>()->object());
257 }
258
259 const auto actualLength = property->count(property);
260 if (actualLength != length + argc)
261 qmlWarning(me: property->object) << "List didn't append all objects";
262
263 return Encode(uint(actualLength));
264}
265
266ReturnedValue PropertyListPrototype::method_shift(const FunctionObject *b, const Value *thisObject, const Value *, int)
267{
268 Scope scope(b);
269 ScopedObject instance(scope, thisObject->toObject(e: scope.engine));
270 if (!instance)
271 RETURN_UNDEFINED();
272 QmlListWrapper *w = instance->as<QmlListWrapper>();
273 if (!w)
274 RETURN_UNDEFINED();
275
276 QQmlListProperty<QObject> *property = &w->d()->property();
277
278 if (!property->count)
279 return scope.engine->throwTypeError(message: u"List doesn't define a Count function"_s);
280 const qsizetype len = property->count(property);
281 if (!len)
282 RETURN_UNDEFINED();
283
284 if (!property->at)
285 return scope.engine->throwTypeError(message: u"List doesn't define an At function"_s);
286 ScopedValue result(scope, QV4::QObjectWrapper::wrap(engine: scope.engine, object: property->at(property, 0)));
287
288 if (!property->replace)
289 return scope.engine->throwTypeError(message: u"List doesn't define a Replace function"_s);
290 if (!property->removeLast)
291 return scope.engine->throwTypeError(message: u"List doesn't define a RemoveLast function"_s);
292
293 for (qsizetype i = 1; i < len; ++i)
294 property->replace(property, i - 1, property->at(property, i));
295 property->removeLast(property);
296
297 return result->asReturnedValue();
298}
299
300ReturnedValue PropertyListPrototype::method_splice(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc)
301{
302 Scope scope(b);
303 ScopedObject instance(scope, thisObject->toObject(e: scope.engine));
304 if (!instance)
305 RETURN_UNDEFINED();
306 QmlListWrapper *w = instance->as<QmlListWrapper>();
307 if (!w)
308 RETURN_UNDEFINED();
309
310 QQmlListProperty<QObject> *property = &w->d()->property();
311
312 if (!property->count)
313 return scope.engine->throwTypeError(message: u"List doesn't define a Count function"_s);
314 const qsizetype len = property->count(property);
315
316 const double rs = (argc ? argv[0] : Value::undefinedValue()).toInteger();
317 qsizetype start;
318 if (rs < 0)
319 start = static_cast<qsizetype>(qMax(a: 0., b: len + rs));
320 else
321 start = static_cast<qsizetype>(qMin(a: rs, b: static_cast<double>(len)));
322
323 qsizetype deleteCount = 0;
324 qsizetype itemCount = 0;
325 if (argc == 1) {
326 deleteCount = len - start;
327 } else if (argc > 1){
328 itemCount = argc - 2;
329 double dc = argv[1].toInteger();
330 deleteCount = static_cast<qsizetype>(qMin(a: qMax(a: dc, b: 0.), b: double(len - start)));
331 }
332
333 if (itemCount > deleteCount
334 && len > std::numeric_limits<qsizetype>::max() - itemCount + deleteCount) {
335 return scope.engine->throwTypeError();
336 }
337
338 if (!qIsAtMostUintLimit(length: deleteCount, limit: std::numeric_limits<uint>::max() - 1))
339 return scope.engine->throwRangeError(message: QString::fromLatin1(ba: "List length out of range."));
340
341 if (!property->at)
342 return scope.engine->throwTypeError(message: u"List doesn't define an At function"_s);
343
344 for (qsizetype i = 0; i < itemCount; ++i) {
345 const auto arg = argv[i + 2];
346 if (!arg.isNull() && !arg.as<QObjectWrapper>())
347 THROW_TYPE_ERROR();
348 }
349
350 ScopedArrayObject newArray(scope, scope.engine->newArrayObject());
351 newArray->arrayReserve(n: deleteCount);
352 ScopedValue v(scope);
353 for (qsizetype i = 0; i < deleteCount; ++i) {
354 newArray->arrayPut(
355 index: i, value: QObjectWrapper::wrap(engine: scope.engine, object: property->at(property, start + i)));
356 }
357 newArray->setArrayLengthUnchecked(deleteCount);
358
359 if (!property->replace)
360 return scope.engine->throwTypeError(message: u"List doesn't define a Replace function"_s);
361 if (!property->removeLast)
362 return scope.engine->throwTypeError(message: u"List doesn't define a RemoveLast function"_s);
363 if (!property->append)
364 return scope.engine->throwTypeError(message: u"List doesn't define an Append function"_s);
365
366 if (itemCount < deleteCount) {
367 for (qsizetype k = start; k < len - deleteCount; ++k)
368 property->replace(property, k + itemCount, property->at(property, k + deleteCount));
369 for (qsizetype k = len; k > len - deleteCount + itemCount; --k)
370 property->removeLast(property);
371 } else if (itemCount > deleteCount) {
372 for (qsizetype k = 0; k < itemCount - deleteCount; ++k)
373 property->append(property, nullptr);
374 for (qsizetype k = len - deleteCount; k > start; --k) {
375 property->replace(
376 property, k + itemCount - 1, property->at(property, k + deleteCount - 1));
377 }
378 }
379
380 for (qsizetype i = 0; i < itemCount; ++i) {
381 const auto arg = argv[i + 2];
382 if (arg.isNull())
383 property->replace(property, start + i, nullptr);
384 else
385 property->replace(property, start + i, arg.as<QObjectWrapper>()->object());
386 }
387
388 return newArray->asReturnedValue();
389}
390
391ReturnedValue PropertyListPrototype::method_unshift(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc)
392{
393 Scope scope(b);
394 ScopedObject instance(scope, thisObject->toObject(e: scope.engine));
395 if (!instance)
396 RETURN_UNDEFINED();
397
398 QmlListWrapper *w = instance->as<QmlListWrapper>();
399 if (!w)
400 RETURN_UNDEFINED();
401
402 QQmlListProperty<QObject> *property = &w->d()->property();
403
404 if (!property->count)
405 return scope.engine->throwTypeError(message: u"List doesn't define a Count function"_s);
406 const qsizetype len = property->count(property);
407
408 if (std::numeric_limits<qsizetype>::max() - len < argc || !qIsAtMostUintLimit(length: len + argc))
409 return scope.engine->throwRangeError(message: QString::fromLatin1(ba: "List length out of range."));
410
411 if (!property->append)
412 return scope.engine->throwTypeError(message: u"List doesn't define an Append function"_s);
413 if (!property->replace)
414 return scope.engine->throwTypeError(message: u"List doesn't define a Replace function"_s);
415
416 for (int i = 0; i < argc; ++i) {
417 const auto arg = argv[i];
418 if (!arg.isNull() && !arg.as<QObjectWrapper>())
419 THROW_TYPE_ERROR();
420 }
421
422 for (int i = 0; i < argc; ++i)
423 property->append(property, nullptr);
424 if (property->count(property) != argc + len)
425 return scope.engine->throwTypeError(message: u"List doesn't append null objects"_s);
426
427 for (qsizetype k = len; k > 0; --k)
428 property->replace(property, k + argc - 1, property->at(property, k - 1));
429
430 for (int i = 0; i < argc; ++i) {
431 const auto *wrapper = argv[i].as<QObjectWrapper>();
432 property->replace(property, i, wrapper ? wrapper->object() : nullptr);
433 }
434
435 return Encode(uint(len + argc));
436}
437
438template<typename Iterate>
439ReturnedValue firstOrLastIndexOf(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc, Iterate iterate)
440{
441 Scope scope(b);
442
443 // Undefined cannot be encoded as QObject*. In particular it's not nullptr.
444 if (argc == 0)
445 THROW_TYPE_ERROR();
446
447 QObject *searchValue;
448 if (argv[0].isNull()) {
449 searchValue = nullptr;
450 } else {
451 Scoped<QObjectWrapper> wrapper(scope, argv[0]);
452 if (wrapper)
453 searchValue = wrapper->object();
454 else
455 THROW_TYPE_ERROR();
456 }
457
458 ScopedObject instance(scope, thisObject->toObject(e: scope.engine));
459 if (!instance)
460 RETURN_UNDEFINED();
461
462 QmlListWrapper *w = instance->as<QmlListWrapper>();
463 if (!w)
464 RETURN_UNDEFINED();
465
466 QQmlListProperty<QObject> *property = &w->d()->property();
467
468 if (!property->count)
469 return scope.engine->throwTypeError(message: u"List doesn't define a Count function"_s);
470 const qsizetype len = property->count(property);
471 if (!len)
472 return Encode(-1);
473
474
475 return iterate(scope.engine, property, len, searchValue);
476}
477
478ReturnedValue PropertyListPrototype::method_indexOf(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc)
479{
480 return firstOrLastIndexOf(
481 b, thisObject, argv, argc,
482 iterate: [argc, argv](ExecutionEngine *engine, QQmlListProperty<QObject> *property,
483 qsizetype len, QObject *searchValue) -> ReturnedValue {
484 qsizetype fromIndex = 0;
485 if (argc >= 2) {
486 double f = argv[1].toInteger();
487 if (hasExceptionOrIsInterrupted(engine))
488 return Encode::undefined();
489 if (f >= len)
490 return Encode(-1);
491 if (f < 0)
492 f = qMax(a: len + f, b: 0.);
493 fromIndex = qsizetype(f);
494 }
495
496 for (qsizetype i = fromIndex; i < len; ++i) {
497 if (property->at(property, i) == searchValue) {
498 if (qIsAtMostUintLimit(length: i))
499 return Encode(uint(i));
500 return engine->throwRangeError(message: QString::fromLatin1(ba: "List length out of range."));
501 }
502 }
503
504 return Encode(-1);
505 });
506}
507
508ReturnedValue PropertyListPrototype::method_lastIndexOf(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc)
509{
510 return firstOrLastIndexOf(
511 b, thisObject, argv, argc,
512 iterate: [argc, argv](ExecutionEngine *engine, QQmlListProperty<QObject> *property,
513 qsizetype len, QObject *searchValue) -> ReturnedValue {
514 qsizetype fromIndex = len - 1;
515 if (argc >= 2) {
516 double f = argv[1].toInteger();
517 if (hasExceptionOrIsInterrupted(engine))
518 return Encode::undefined();
519 if (f > 0)
520 f = qMin(a: f, b: (double)(len - 1));
521 else if (f < 0) {
522 f = len + f;
523 if (f < 0)
524 return Encode(-1);
525 }
526 fromIndex = qsizetype(f);
527 }
528
529 for (qsizetype i = fromIndex; i >= 0; --i) {
530 if (property->at(property, i) == searchValue) {
531 if (qIsAtMostUintLimit(length: i))
532 return Encode(uint(i));
533 return engine->throwRangeError(message: QString::fromLatin1(ba: "List length out of range."));
534 }
535 }
536
537 return Encode(-1);
538 });
539}
540
541ReturnedValue PropertyListPrototype::method_sort(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc)
542{
543 Scope scope(b);
544 ScopedObject instance(scope, thisObject->toObject(e: scope.engine));
545 if (!instance)
546 RETURN_UNDEFINED();
547
548 QmlListWrapper *w = instance->as<QmlListWrapper>();
549 if (!w)
550 RETURN_UNDEFINED();
551
552 QQmlListProperty<QObject> *property = &w->d()->property();
553
554 if (!property->count)
555 return scope.engine->throwTypeError(message: u"List doesn't define a Count function"_s);
556 if (property->count(property) == 0)
557 return thisObject->asReturnedValue();
558 if (!property->at)
559 return scope.engine->throwTypeError(message: u"List doesn't define an At function"_s);
560 if (!property->replace)
561 return scope.engine->throwTypeError(message: u"List doesn't define a Replace function"_s);
562
563 ScopedValue comparefn(scope, argc ? argv[0] : Value::undefinedValue());
564 if (!comparefn->isUndefined() && !comparefn->isFunctionObject())
565 THROW_TYPE_ERROR();
566
567 const ArrayElementLessThan lessThan(scope.engine, comparefn);
568 sortHelper(start: begin(list&: *property), end: end(list&: *property), lessThan: [&](QObject *a, QObject *b) {
569 Scoped<QObjectWrapper> o1(scope, QObjectWrapper::wrap(engine: scope.engine, object: a));
570 Scoped<QObjectWrapper> o2(scope, QObjectWrapper::wrap(engine: scope.engine, object: b));
571 return lessThan(o1, o2);
572 });
573
574 return thisObject->asReturnedValue();
575}
576
577ReturnedValue PropertyListPrototype::method_get_length(const FunctionObject *b, const Value *thisObject, const Value *, int)
578{
579 Scope scope(b);
580 ScopedObject instance(scope, thisObject->toObject(e: scope.engine));
581 if (!instance)
582 RETURN_UNDEFINED();
583
584 const QmlListWrapper *w = instance->as<QmlListWrapper>();
585 if (!w)
586 RETURN_UNDEFINED();
587
588 QQmlListProperty<QObject> *property = &w->d()->property();
589 if (!property->count)
590 return scope.engine->throwTypeError(message: u"List doesn't define a Count function"_s);
591
592 qsizetype count = property->count(property);
593 if (qIsAtMostUintLimit(length: count))
594 return Encode(uint(count));
595
596 return scope.engine->throwRangeError(message: QString::fromLatin1(ba: "List length out of range."));
597}
598
599ReturnedValue PropertyListPrototype::method_set_length(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc)
600{
601 QV4::Scope scope(b);
602 ScopedObject instance(scope, thisObject->toObject(e: scope.engine));
603 if (!instance)
604 RETURN_UNDEFINED();
605
606 const QmlListWrapper *w = instance->as<QmlListWrapper>();
607 if (!w)
608 RETURN_UNDEFINED();
609
610 QQmlListProperty<QObject> *property = &w->d()->property();
611
612 bool ok = false;
613 const uint newLength = argc ? argv[0].asArrayLength(ok: &ok) : 0;
614 if (!ok)
615 return scope.engine->throwRangeError(message: QString::fromLatin1(ba: "Invalid list length."));
616
617 if (newLength == 0 && property->clear) {
618 property->clear(property);
619 return true;
620 }
621
622 if (!property->count)
623 return scope.engine->throwTypeError(message: u"List doesn't define a Count function"_s);
624
625 qsizetype count = property->count(property);
626 if (!qIsAtMostUintLimit(length: count))
627 return scope.engine->throwRangeError(message: QString::fromLatin1(ba: "List length out of range."));
628
629 if (newLength < uint(count)) {
630 if (!property->removeLast)
631 return scope.engine->throwTypeError(message: u"List doesn't define a RemoveLast function"_s);
632
633 for (uint i = count; i > newLength; --i)
634 property->removeLast(property);
635
636 return true;
637 }
638
639 if (!property->append)
640 return scope.engine->throwTypeError(message: u"List doesn't define an Append function"_s);
641
642 for (uint i = count; i < newLength; ++i)
643 property->append(property, nullptr);
644
645 count = property->count(property);
646 if (!qIsAtMostUintLimit(length: count))
647 return scope.engine->throwRangeError(message: QString::fromLatin1(ba: "List length out of range."));
648
649 if (uint(count) != newLength)
650 return scope.engine->throwTypeError(message: u"List doesn't append null objects"_s);
651
652 return true;
653
654}
655
656QT_END_NAMESPACE
657

source code of qtdeclarative/src/qml/qml/qqmllistwrapper.cpp