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
qv4arrayobject.cpp
Go to the documentation of this file.
1// Copyright (C) 2018 Crimson AS <info@crimson.no>
2// Copyright (C) 2016 The Qt Company Ltd.
3// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
4
5#include "qv4arrayobject_p.h"
7#include "qv4objectproto_p.h"
9#include "qv4runtime_p.h"
10#include "qv4symbol_p.h"
11#include <QtCore/qscopedvaluerollback.h>
12
13using namespace QV4;
14
16
18{
19 Heap::FunctionObject::init(engine, QStringLiteral("Array"));
20}
21
22ReturnedValue ArrayCtor::virtualCallAsConstructor(const FunctionObject *f, const Value *argv, int argc, const Value *newTarget)
23{
24 ExecutionEngine *v4 = static_cast<const ArrayCtor *>(f)->engine();
25 Scope scope(v4);
27 if (newTarget)
28 a->setProtoFromNewTarget(newTarget);
29 uint len;
30 if (argc == 1 && argv[0].isNumber()) {
31 bool ok;
32 len = argv[0].asArrayLength(&ok);
33
34 if (!ok)
35 return v4->throwRangeError(argv[0]);
36
37 if (len < 0x1000)
38 a->arrayReserve(len);
39 } else {
40 len = argc;
41 a->arrayReserve(len);
42 a->arrayPut(0, argv, len);
43 }
44 a->setArrayLengthUnchecked(len);
45
46 return a.asReturnedValue();
47}
48
49ReturnedValue ArrayCtor::virtualCall(const FunctionObject *f, const Value *, const Value *argv, int argc)
50{
51 return virtualCallAsConstructor(f, argv, argc, f);
52}
53
55{
56 Scope scope(engine);
57 ScopedObject o(scope);
58 ctor->defineReadonlyConfigurableProperty(engine->id_length(), Value::fromInt32(1));
59 ctor->defineReadonlyProperty(engine->id_prototype(), (o = this));
60 ctor->defineDefaultProperty(QStringLiteral("isArray"), method_isArray, 1);
61 ctor->defineDefaultProperty(QStringLiteral("of"), method_of, 0);
62 ctor->defineDefaultProperty(QStringLiteral("from"), method_from, 1);
63 ctor->addSymbolSpecies();
64
65 Scoped<InternalClass> ic(scope, engine->classes[EngineBase::Class_Empty]
66 ->changeVTable(QV4::Object::staticVTable()));
67 ScopedObject unscopables(scope, engine->newObject(ic->d()));
68 ScopedString name(scope);
69 defineDefaultProperty(QStringLiteral("constructor"), (o = ctor));
70 defineDefaultProperty(engine->id_toString(), method_toString, 0);
71 defineDefaultProperty(engine->id_toLocaleString(), method_toLocaleString, 0);
72 defineDefaultProperty(QStringLiteral("concat"), method_concat, 1);
73 name = engine->newIdentifier(QStringLiteral("copyWithin"));
74 unscopables->put(name, Value::fromBoolean(true));
75 defineDefaultProperty(name, method_copyWithin, 2);
76 name = engine->newIdentifier(QStringLiteral("entries"));
77 unscopables->put(name, Value::fromBoolean(true));
78 defineDefaultProperty(name, method_entries, 0);
79 name = engine->newIdentifier(QStringLiteral("fill"));
80 unscopables->put(name, Value::fromBoolean(true));
81 defineDefaultProperty(name, method_fill, 1);
82 name = engine->newIdentifier(QStringLiteral("find"));
83 unscopables->put(name, Value::fromBoolean(true));
84 defineDefaultProperty(name, method_find, 1);
85 name = engine->newIdentifier(QStringLiteral("findIndex"));
86 unscopables->put(name, Value::fromBoolean(true));
87 defineDefaultProperty(name, method_findIndex, 1);
88 name = engine->newIdentifier(QStringLiteral("includes"));
89 unscopables->put(name, Value::fromBoolean(true));
90 defineDefaultProperty(name, method_includes, 1);
91 defineDefaultProperty(QStringLiteral("join"), method_join, 1);
92 name = engine->newIdentifier(QStringLiteral("keys"));
93 unscopables->put(name, Value::fromBoolean(true));
94 defineDefaultProperty(name, method_keys, 0);
95 defineDefaultProperty(QStringLiteral("pop"), method_pop, 0);
96 defineDefaultProperty(QStringLiteral("push"), method_push, 1);
97 defineDefaultProperty(QStringLiteral("reverse"), method_reverse, 0);
98 defineDefaultProperty(QStringLiteral("shift"), method_shift, 0);
99 defineDefaultProperty(QStringLiteral("slice"), method_slice, 2);
100 defineDefaultProperty(QStringLiteral("sort"), method_sort, 1);
101 defineDefaultProperty(QStringLiteral("splice"), method_splice, 2);
102 defineDefaultProperty(QStringLiteral("unshift"), method_unshift, 1);
103 defineDefaultProperty(QStringLiteral("indexOf"), method_indexOf, 1);
104 defineDefaultProperty(QStringLiteral("lastIndexOf"), method_lastIndexOf, 1);
105 defineDefaultProperty(QStringLiteral("every"), method_every, 1);
106 defineDefaultProperty(QStringLiteral("some"), method_some, 1);
107 defineDefaultProperty(QStringLiteral("forEach"), method_forEach, 1);
108 defineDefaultProperty(QStringLiteral("map"), method_map, 1);
109 defineDefaultProperty(QStringLiteral("filter"), method_filter, 1);
110 defineDefaultProperty(QStringLiteral("reduce"), method_reduce, 1);
111 defineDefaultProperty(QStringLiteral("reduceRight"), method_reduceRight, 1);
112 ScopedString valuesString(scope, engine->newIdentifier(QStringLiteral("values")));
113 ScopedObject values(scope, FunctionObject::createBuiltinFunction(engine, valuesString, method_values, 0));
115 unscopables->put(valuesString, Value::fromBoolean(true));
116 defineDefaultProperty(valuesString, values);
117 defineDefaultProperty(engine->symbol_iterator(), values);
118
119 defineReadonlyConfigurableProperty(engine->symbol_unscopables(), unscopables);
120}
121
123{
124 if (!argc || !argv->objectValue())
125 return Encode(false);
126 return Encode(argv->objectValue()->isArray());
127}
128
130{
132
133 if (ctor && ctor->isConstructor()) {
134 // this isn't completely kosher. for instance:
135 // Array.from.call(Object, []).constructor == Object
136 // is expected by the tests, but naturally, we get Number.
139 a = ctor->callAsConstructor(argument, useLen ? 1 : 0);
140 } else {
141 a = scope.engine->newArrayObject(len);
142 }
143
144 return a;
145}
146
147ReturnedValue ArrayPrototype::method_from(const FunctionObject *builtin, const Value *thisObject, const Value *argv, int argc)
148{
149 Scope scope(builtin);
150 ScopedFunctionObject thatCtor(scope, thisObject);
151 ScopedObject itemsObject(scope, argv[0]);
152 bool usingIterator = false;
153
154 if (itemsObject) {
155 // If the object claims to support iterators, then let's try use them.
156 ScopedValue it(scope, itemsObject->get(scope.engine->symbol_iterator()));
157 if (!it->isNullOrUndefined()) {
158 ScopedFunctionObject itfunc(scope, it);
159 if (!itfunc)
160 return scope.engine->throwTypeError();
161 usingIterator = true;
162 }
163 }
164
166 Value *mapArguments = nullptr;
167 if (argc > 1) {
168 mapfn = ScopedFunctionObject(scope, argv[1]);
169 if (!mapfn)
170 return scope.engine->throwTypeError(QString::fromLatin1("%1 is not a function").arg(argv[1].toQStringNoThrow()));
171 mapArguments = scope.alloc(2);
172 }
173
174 ScopedValue thisArg(scope);
175 if (argc > 2)
176 thisArg = argv[2];
177
178 if (usingIterator) {
179 // Item iteration supported, so let's go ahead and try use that.
180 ScopedObject a(createObjectFromCtorOrArray(scope, thatCtor, false, 0));
182 ScopedObject iterator(scope, Runtime::GetIterator::call(scope.engine, itemsObject, true));
183 CHECK_EXCEPTION(); // symbol_iterator threw; whoops.
184 if (!iterator) {
185 return scope.engine->throwTypeError(); // symbol_iterator wasn't an object.
186 }
187
188 qint64 k = 0;
189 ScopedValue mappedValue(scope);
190 Value *nextValue = scope.alloc(1);
191 ScopedValue done(scope);
192
193 // The loop below pulls out all the properties using the iterator, and
194 // sets them into the created array.
195 forever {
196 if (k > (static_cast<qint64>(1) << 53) - 1) {
197 ScopedValue error(scope, scope.engine->throwTypeError());
198 return Runtime::IteratorClose::call(scope.engine, iterator);
199 }
200
201 // Retrieve the next value. If the iteration ends, we're done here.
204 if (done->toBoolean()) {
205 if (ArrayObject *ao = a->as<ArrayObject>()) {
206 ao->setArrayLengthUnchecked(k);
207 } else {
210 }
211 return a.asReturnedValue();
212 }
213
214 if (mapfn) {
215 Q_ASSERT(mapArguments); // if mapfn is set, we always setup mapArguments with scope.alloc
216 mapArguments[0] = *nextValue;
217 mapArguments[1] = Value::fromDouble(k);
218 mappedValue = mapfn->call(thisArg, mapArguments, 2);
219 if (scope.hasException())
220 return Runtime::IteratorClose::call(scope.engine, iterator);
221 } else {
222 mappedValue = *nextValue;
223 }
224
225 if (a->getOwnProperty(PropertyKey::fromArrayIndex(k)) == Attr_Invalid) {
226 a->arraySet(k, mappedValue);
227 } else {
228 // Don't return: we need to close the iterator.
229 scope.engine->throwTypeError(QString::fromLatin1("Cannot redefine property: %1").arg(k));
230 }
231
232 if (scope.hasException())
233 return Runtime::IteratorClose::call(scope.engine, iterator);
234
235 k++;
236 }
237
238 // the return is hidden up in the loop above, when iteration finishes.
239 } else {
240 // Array-like fallback. We request properties by index, and set them on
241 // the return object.
242 ScopedObject arrayLike(scope, argv[0].toObject(scope.engine));
243 if (!arrayLike)
244 return scope.engine->throwTypeError(QString::fromLatin1("Cannot convert %1 to object").arg(argv[0].toQStringNoThrow()));
245 qint64 len = arrayLike->getLength();
246 ScopedObject a(createObjectFromCtorOrArray(scope, thatCtor, true, len));
248
249 qint64 k = 0;
250 ScopedValue mappedValue(scope, Value::undefinedValue());
251 ScopedValue kValue(scope);
252 while (k < len) {
253 kValue = arrayLike->get(k);
255
256 if (mapfn) {
257 Q_ASSERT(mapArguments); // if mapfn is set, we always setup mapArguments with scope.alloc
258 mapArguments[0] = kValue;
259 mapArguments[1] = Value::fromDouble(k);
260 mappedValue = mapfn->call(thisArg, mapArguments, 2);
262 } else {
263 mappedValue = kValue;
264 }
265
266 if (a->getOwnProperty(PropertyKey::fromArrayIndex(k)) != Attr_Invalid)
267 return scope.engine->throwTypeError(QString::fromLatin1("Cannot redefine property: %1").arg(k));
268
269 a->arraySet(k, mappedValue);
271
272 k++;
273 }
274
275 if (ArrayObject *ao = a->as<ArrayObject>()) {
276 ao->setArrayLengthUnchecked(k);
277 } else {
280 }
281 return a.asReturnedValue();
282 }
283
284}
285
286ReturnedValue ArrayPrototype::method_of(const FunctionObject *builtin, const Value *thisObject, const Value *argv, int argc)
287{
288 Scope scope(builtin);
289 ScopedFunctionObject that(scope, thisObject);
290 ScopedObject a(createObjectFromCtorOrArray(scope, that, true, argc));
292
293 int k = 0;
294 while (k < argc) {
295 if (a->getOwnProperty(PropertyKey::fromArrayIndex(k)) != Attr_Invalid) {
296 return scope.engine->throwTypeError(QString::fromLatin1("Cannot redefine property: %1").arg(k));
297 }
298 a->arraySet(k, argv[k]);
300
301 k++;
302 }
303
304 // ArrayObject updates its own length, and will throw if we try touch it.
305 if (!a->as<ArrayObject>()) {
308 }
309
310 return a.asReturnedValue();
311}
312
313ReturnedValue ArrayPrototype::method_toString(const FunctionObject *builtin, const Value *thisObject, const Value *argv, int argc)
314{
315 Scope scope(builtin);
316 ScopedObject that(scope, thisObject->toObject(scope.engine));
317 if (scope.hasException())
318 return QV4::Encode::undefined();
319
320 ScopedString string(scope, scope.engine->newString(QStringLiteral("join")));
321 ScopedFunctionObject f(scope, that->get(string));
322 if (f)
323 return checkedResult(scope.engine, f->call(that, argv, argc));
324 return ObjectPrototype::method_toString(builtin, that, argv, argc);
325}
326
328{
329 Scope scope(b);
330 ScopedObject instance(scope, thisObject);
331 if (!instance)
332 return scope.engine->throwTypeError();
333
334 uint len = instance->getLength();
335 const QString separator = QStringLiteral(",");
336
337 QString R;
338
339 ScopedValue v(scope);
340 ScopedString s(scope);
341
342 ScopedPropertyKey tolocaleString(scope, scope.engine->id_toLocaleString()->toPropertyKey());
344
345 for (uint k = 0; k < len; ++k) {
346 if (k)
347 R += separator;
348
349 v = instance->get(k);
350 if (v->isNullOrUndefined())
351 continue;
352
353 ScopedObject valueAsObject(scope, v->toObject(scope.engine));
354 Q_ASSERT(valueAsObject); // null and undefined handled above
355
356 ScopedFunctionObject function(scope, valueAsObject->get(tolocaleString));
357 if (!function)
358 return scope.engine->throwTypeError();
359
360 v = function->call(valueAsObject, nullptr, 0);
361 if (scope.hasException())
362 return Encode::undefined();
363
364 s = v->toString(scope.engine);
365 if (scope.hasException())
366 return Encode::undefined();
367
368 R += s->toQString();
369 }
370 return scope.engine->newString(R)->asReturnedValue();
371}
372
373ReturnedValue ArrayPrototype::method_concat(const FunctionObject *b, const Value *that, const Value *argv, int argc)
374{
375 Scope scope(b);
376 ScopedObject thisObject(scope, that->toObject(scope.engine));
377 if (!thisObject)
379
381
382 ScopedArrayObject elt(scope);
383 ScopedObject eltAsObj(scope);
384 ScopedValue entry(scope);
385 for (int i = -1; i < argc; ++i) {
386 const Value *v = i == -1 ? thisObject.getPointer() : argv + i;
387 eltAsObj = *v;
388 elt = *v;
389 if (elt) {
390 uint n = elt->getLength();
391 uint newLen = ArrayData::append(result, elt, n);
392 result->setArrayLengthUnchecked(newLen);
393 } else if (eltAsObj && eltAsObj->isConcatSpreadable()) {
394 const uint startIndex = result->getLength();
395 const uint len = eltAsObj->getLength();
396 if (scope.hasException())
397 return Encode::undefined();
398
399 for (uint i = 0; i < len; ++i) {
400 bool hasProperty = false;
401 entry = eltAsObj->get(i, &hasProperty);
402 if (hasProperty) {
403 if (!result->put(startIndex + i, entry))
404 return scope.engine->throwTypeError();
405 }
406 }
407 } else if (eltAsObj && eltAsObj->isArrayLike()) {
408 const uint startIndex = result->getLength();
409 for (int i = 0, len = eltAsObj->getLength(); i < len; ++i) {
410 entry = eltAsObj->get(i);
411 // spec says not to throw if this fails
412 result->put(startIndex + i, entry);
413 }
414 } else {
415 result->arraySet(result->getLength(), *v);
416 }
417 }
418
419 return result.asReturnedValue();
420}
421
422ReturnedValue ArrayPrototype::method_copyWithin(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc)
423{
424 Scope scope(b);
425 ScopedObject instance(scope, thisObject->toObject(scope.engine));
426 if (!instance)
428
429 double len = instance->getLength();
430 double target = argv[0].toInteger();
431 double start = argc > 1 ? argv[1].toInteger() : 0;
432 double end = len;
433
434 if (argc > 2 && !argv[2].isUndefined()) {
435 end = argv[2].toInteger();
436 }
437
438 double relativeTarget = target;
439 double relativeStart = start;
440 double relativeEnd = end;
441 double from = 0;
442 double to = 0;
443
444 if (relativeTarget < 0) {
445 to = std::max(len+relativeTarget, 0.0);
446 } else {
447 to = std::min(relativeTarget, len);
448 }
449 if (relativeStart < 0) {
450 from = std::max(len+relativeStart, 0.0);
451 } else {
452 from = std::min(relativeStart, len);
453 }
454
455 double fin = 0;
456 if (relativeEnd < 0) {
457 fin = std::max(len+relativeEnd, 0.0);
458 } else {
459 fin = std::min(relativeEnd, len);
460 }
461 double count = std::min(fin-from, len-to);
462 double direction = 1;
463 if (from < to && to < from+count) {
464 direction = -1;
465 from = from + count - 1;
466 to = to + count - 1;
467 }
468
469 while (count > 0) {
470 bool fromPresent = false;
471 ScopedValue fromVal(scope, instance->get(from, &fromPresent));
472
473 if (fromPresent) {
474 instance->setIndexed(to, fromVal, QV4::Object::DoThrowOnRejection);
476 } else {
477 bool didDelete = instance->deleteProperty(PropertyKey::fromArrayIndex(to));
479 if (!didDelete) {
480 return scope.engine->throwTypeError();
481 }
482 }
483
484 from = from + direction;
485 to = to + direction;
486 count = count - 1;
487 }
488
489 return instance.asReturnedValue();
490}
491
493{
494 Scope scope(b);
495 ScopedObject O(scope, thisObject->toObject(scope.engine));
496 if (!O)
498
499 Scoped<ArrayIteratorObject> ao(scope, scope.engine->newArrayIteratorObject(O));
500 ao->d()->iterationKind = IteratorKind::KeyValueIteratorKind;
501 return ao->asReturnedValue();
502}
503
504ReturnedValue ArrayPrototype::method_find(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc)
505{
506 Scope scope(b);
507 ScopedObject instance(scope, thisObject->toObject(scope.engine));
508 if (!instance)
510
511 uint len = instance->getLength();
512
513 if (!argc || !argv[0].isFunctionObject())
515 const FunctionObject *callback = static_cast<const FunctionObject *>(argv);
516
517 ScopedValue result(scope);
518 Value *arguments = scope.alloc(3);
519
520 ScopedValue that(scope, argc > 1 ? argv[1] : Value::undefinedValue());
521
522 for (uint k = 0; k < len; ++k) {
523 arguments[0] = instance->get(k);
525
527 arguments[2] = instance;
528 result = callback->call(that, arguments, 3);
529
531 if (result->toBoolean())
532 return arguments[0].asReturnedValue();
533 }
534
536}
537
538ReturnedValue ArrayPrototype::method_findIndex(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc)
539{
540 Scope scope(b);
541 ScopedObject instance(scope, thisObject->toObject(scope.engine));
542 if (!instance)
544
545 uint len = instance->getLength();
546
547 if (!argc || !argv[0].isFunctionObject())
549 const FunctionObject *callback = static_cast<const FunctionObject *>(argv);
550
551 ScopedValue result(scope);
552 Value *arguments = scope.alloc(3);
553
554 ScopedValue that(scope, argc > 1 ? argv[1] : Value::undefinedValue());
555
556 for (uint k = 0; k < len; ++k) {
557 arguments[0] = instance->get(k);
559
561 arguments[2] = instance;
562 result = callback->call(that, arguments, 3);
563
565 if (result->toBoolean())
566 return Encode(k);
567 }
568
569 return Encode(-1);
570}
571
573 const Value *thisObject, const Value *argv, int argc)
574{
575 Scope scope(functionObject);
576 ScopedObject instance(scope, thisObject->toObject(scope.engine));
577
578 if (!instance)
579 return Encode(scope.engine->newString());
580
581 // We cannot optimize the resolution of the argument away in case of length == 0
582 // It may have side effects.
583 ScopedValue argument(scope, argc ? argv[0] : Value::undefinedValue());
584 const QString separator = argument->isUndefined()
585 ? QStringLiteral(",")
586 : argument->toQString();
587
588 ScopedValue scopedLength(scope, instance->get(scope.engine->id_length()));
589 const quint32 genericLength = scopedLength->isUndefined() ? 0 : scopedLength->toUInt32();
590 if (!genericLength)
591 return Encode(scope.engine->newString());
592
594 if (auto *arrayObject = instance->as<ArrayObject>()) {
595 ScopedValue entry(scope);
596 const qint64 arrayLength = arrayObject->getLength();
597 Q_ASSERT(arrayLength >= 0);
598 Q_ASSERT(arrayLength <= std::numeric_limits<quint32>::max());
599 for (quint32 i = 0; i < quint32(arrayLength); ++i) {
600 if (i)
601 result += separator;
602
603 entry = arrayObject->get(i);
605 if (!entry->isNullOrUndefined())
606 result += entry->toQString();
607 }
608 } else {
609 ScopedString name(scope, scope.engine->newString(QStringLiteral("0")));
610 ScopedValue value(scope, instance->get(name));
612
613 if (!value->isNullOrUndefined())
614 result = value->toQString();
615
616 for (quint32 i = 1; i < genericLength; ++i) {
617 result += separator;
618
619 name = Value::fromDouble(i).toString(scope.engine);
620 value = instance->get(name);
622
623 if (!value->isNullOrUndefined())
624 result += value->toQString();
625 }
626 }
627
628 return Encode(scope.engine->newString(result));
629}
630
631ReturnedValue ArrayPrototype::method_pop(const FunctionObject *b, const Value *thisObject, const Value *, int)
632{
633 Scope scope(b);
634 ScopedObject instance(scope, thisObject->toObject(scope.engine));
635 if (!instance)
637
638 uint len = instance->getLength();
639
640 if (!len) {
641 if (!instance->isArrayObject())
642 instance->put(scope.engine->id_length(), ScopedValue(scope, Value::fromInt32(0)));
644 }
645
646 ScopedValue result(scope, instance->get(len - 1));
648
650 return scope.engine->throwTypeError();
651
652 if (instance->isArrayObject())
653 instance->setArrayLength(len - 1);
654 else {
655 if (!instance->put(scope.engine->id_length(), ScopedValue(scope, Value::fromDouble(len - 1))))
656 return scope.engine->throwTypeError();
657 }
658 return result->asReturnedValue();
659}
660
661ReturnedValue ArrayPrototype::method_push(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc)
662{
663 Scope scope(b);
664 ScopedObject instance(scope, thisObject->toObject(scope.engine));
665 if (!instance)
667
668 instance->arrayCreate();
669 Q_ASSERT(instance->arrayData());
670
671 qint64 len = instance->getLength();
672
673 if (len + quint64(argc) >= UINT_MAX) {
674 // ughh... this goes beyond UINT_MAX
675 double l = len;
676 ScopedString s(scope);
677 for (int i = 0, ei = argc; i < ei; ++i) {
678 s = Value::fromDouble(l + i).toString(scope.engine);
679 if (!instance->put(s, argv[i]))
680 return scope.engine->throwTypeError();
681 }
682 double newLen = l + argc;
683 if (!instance->isArrayObject()) {
684 if (!instance->put(scope.engine->id_length(), ScopedValue(scope, Value::fromDouble(newLen))))
685 return scope.engine->throwTypeError();
686 } else {
687 ScopedString str(scope, scope.engine->newString(QStringLiteral("Array.prototype.push: Overflow")));
688 return scope.engine->throwRangeError(str);
689 }
690 return Encode(newLen);
691 }
692
693 if (!argc)
694 ;
695 else if (!instance->protoHasArray() && instance->arrayData()->length() <= len && instance->arrayData()->type == Heap::ArrayData::Simple) {
696 instance->arrayData()->vtable()->putArray(instance, len, argv, argc);
697 len = instance->arrayData()->length();
698 } else {
699 for (int i = 0, ei = argc; i < ei; ++i) {
700 if (!instance->put(len + i, argv[i]))
701 return scope.engine->throwTypeError();
702 }
703 len += argc;
704 }
705 if (instance->isArrayObject())
706 instance->setArrayLengthUnchecked(len);
707 else {
708 if (!instance->put(scope.engine->id_length(), ScopedValue(scope, Value::fromDouble(len))))
709 return scope.engine->throwTypeError();
710 }
711
712 return Encode(uint(len));
713}
714
716{
717 Scope scope(b);
718 ScopedObject instance(scope, thisObject->toObject(scope.engine));
719 if (!instance)
721
722 qint64 length = instance->getLength();
723 // ### FIXME
724 if (length >= UINT_MAX)
725 return scope.engine->throwRangeError(QLatin1String("Array.prototype.reverse: Length out of range."));
726
727 int lo = 0, hi = length - 1;
728
729 ScopedValue lval(scope);
730 ScopedValue hval(scope);
731 for (; lo < hi; ++lo, --hi) {
732 bool loExists, hiExists;
733 lval = instance->get(lo, &loExists);
734 hval = instance->get(hi, &hiExists);
736 bool ok;
737 if (hiExists)
738 ok = instance->put(lo, hval);
739 else
741 if (ok) {
742 if (loExists)
743 ok = instance->put(hi, lval);
744 else
746 }
747 if (!ok)
748 return scope.engine->throwTypeError();
749 }
750 return instance->asReturnedValue();
751}
752
754{
755 Scope scope(b);
756 ScopedObject instance(scope, thisObject->toObject(scope.engine));
757 if (!instance)
759
760 instance->arrayCreate();
761 Q_ASSERT(instance->arrayData());
762
763 uint len = instance->getLength();
764
765 if (!len) {
766 if (!instance->isArrayObject())
767 if (!instance->put(scope.engine->id_length(), ScopedValue(scope, Value::fromInt32(0))))
768 return scope.engine->throwTypeError();
770 }
771
772 ScopedValue result(scope);
773 if (!instance->protoHasArray() && !instance->arrayData()->attrs && instance->arrayData()->length() <= len && instance->arrayData()->type != Heap::ArrayData::Custom) {
774 result = instance->arrayData()->vtable()->pop_front(instance);
775 } else {
776 result = instance->get(uint(0));
778 ScopedValue v(scope);
779 // do it the slow way
780 for (uint k = 1; k < len; ++k) {
781 bool exists;
782 v = instance->get(k, &exists);
784 bool ok;
785 if (exists)
786 ok = instance->put(k - 1, v);
787 else
789 if (!ok)
790 return scope.engine->throwTypeError();
791 }
792 bool ok = instance->deleteProperty(PropertyKey::fromArrayIndex(len - 1));
793 if (!ok)
794 return scope.engine->throwTypeError();
795 }
796
797 if (instance->isArrayObject())
798 instance->setArrayLengthUnchecked(len - 1);
799 else {
800 bool ok = instance->put(scope.engine->id_length(), ScopedValue(scope, Value::fromDouble(len - 1)));
801 if (!ok)
802 return scope.engine->throwTypeError();
803 }
804
805 return result->asReturnedValue();
806}
807
808ReturnedValue ArrayPrototype::method_slice(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc)
809{
810 Scope scope(b);
811 ScopedObject o(scope, thisObject->toObject(scope.engine));
812 if (!o)
814
816 uint len = o->getLength();
817 double s = (argc ? argv[0] : Value::undefinedValue()).toInteger();
818 uint start;
819 if (s < 0)
820 start = (uint)qMax(len + s, 0.);
821 else if (s > len)
822 start = len;
823 else
824 start = (uint) s;
825 uint end = len;
826 if (argc > 1 && !argv[1].isUndefined()) {
827 double e = argv[1].toInteger();
828 if (e < 0)
829 end = (uint)qMax(len + e, 0.);
830 else if (e > len)
831 end = len;
832 else
833 end = (uint) e;
834 }
835
836 ScopedValue v(scope);
837 uint n = 0;
838 for (uint i = start; i < end; ++i) {
839 bool exists;
840 v = o->get(i, &exists);
842 if (exists)
843 result->arraySet(n, v);
844 ++n;
845 }
846 return result->asReturnedValue();
847}
848
849ReturnedValue ArrayPrototype::method_sort(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc)
850{
851 Scope scope(b);
852 ScopedObject instance(scope, thisObject->toObject(scope.engine));
853 if (!instance)
855
856 uint len = instance->getLength();
857
858 ScopedValue comparefn(scope, argc ? argv[0] : Value::undefinedValue());
859 ArrayData::sort(scope.engine, instance, comparefn, len);
860 return thisObject->asReturnedValue();
861}
862
863ReturnedValue ArrayPrototype::method_splice(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc)
864{
865 Scope scope(b);
866 ScopedObject instance(scope, thisObject->toObject(scope.engine));
867 if (!instance)
869
870 qint64 len = instance->getLength();
871
872 double rs = (argc ? argv[0] : Value::undefinedValue()).toInteger();
874 if (rs < 0)
875 start = static_cast<qint64>(qMax(0., len + rs));
876 else
877 start = static_cast<qint64>(qMin(rs, static_cast<double>(len)));
878
879 qint64 deleteCount = 0;
880 qint64 itemCount = 0;
881 if (argc == 1) {
882 deleteCount = len - start;
883 } else if (argc > 1){
884 itemCount = argc - 2;
885 double dc = argv[1].toInteger();
886 deleteCount = static_cast<qint64>(qMin(qMax(dc, 0.), double(len - start)));
887 }
888
889 if (len + itemCount - deleteCount > /*(static_cast<qint64>(1) << 53) - 1*/ UINT_MAX - 1)
890 return scope.engine->throwTypeError();
891 if (deleteCount > /*(static_cast<qint64>(1) << 53) - 1*/ UINT_MAX - 1)
892 return scope.engine->throwRangeError(QString::fromLatin1("Array length out of range."));
893
894 ScopedArrayObject newArray(scope, scope.engine->newArrayObject());
895 newArray->arrayReserve(deleteCount);
896 ScopedValue v(scope);
897 for (uint i = 0; i < deleteCount; ++i) {
898 bool exists;
899 v = instance->get(start + i, &exists);
901 if (exists)
902 newArray->arrayPut(i, v);
903 }
904 newArray->setArrayLengthUnchecked(deleteCount);
905
906
907 if (itemCount < deleteCount) {
908 for (uint k = start; k < len - deleteCount; ++k) {
909 bool exists;
910 v = instance->get(k + deleteCount, &exists);
912 bool ok;
913 if (exists)
914 ok = instance->put(k + itemCount, v);
915 else
916 ok = instance->deleteProperty(PropertyKey::fromArrayIndex(k + itemCount));
917 if (!ok)
918 return scope.engine->throwTypeError();
919 }
920 for (uint k = len; k > len - deleteCount + itemCount; --k) {
921 if (!instance->deleteProperty(PropertyKey::fromArrayIndex(k - 1)))
922 return scope.engine->throwTypeError();
923 }
924 } else if (itemCount > deleteCount) {
925 uint k = len - deleteCount;
926 while (k > start) {
927 bool exists;
928 v = instance->get(k + deleteCount - 1, &exists);
930 bool ok;
931 if (exists)
932 ok = instance->put(k + itemCount - 1, v);
933 else
934 ok = instance->deleteProperty(PropertyKey::fromArrayIndex(k + itemCount - 1));
935 if (!ok)
936 return scope.engine->throwTypeError();
937 --k;
938 }
939 }
940
941 for (uint i = 0; i < itemCount; ++i)
942 instance->put(start + i, argv[i + 2]);
943
944 if (!instance->put(scope.engine->id_length(), ScopedValue(scope, Value::fromDouble(len - deleteCount + itemCount))))
945 return scope.engine->throwTypeError();
946
947 return newArray->asReturnedValue();
948}
949
950ReturnedValue ArrayPrototype::method_unshift(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc)
951{
952 Scope scope(b);
953 ScopedObject instance(scope, thisObject->toObject(scope.engine));
954 if (!instance)
956
957 instance->arrayCreate();
958 Q_ASSERT(instance->arrayData());
959
960 uint len = instance->getLength();
961
962 if (!instance->protoHasArray() && !instance->arrayData()->attrs && instance->arrayData()->length() <= len &&
963 instance->arrayData()->type != Heap::ArrayData::Custom) {
964 instance->arrayData()->vtable()->push_front(instance, argv, argc);
965 } else {
966 ScopedValue v(scope);
967 for (uint k = len; k > 0; --k) {
968 bool exists;
969 v = instance->get(k - 1, &exists);
970 bool ok;
971 if (exists)
972 ok = instance->put(k + argc - 1, v);
973 else
974 ok = instance->deleteProperty(PropertyKey::fromArrayIndex(k + argc - 1));
975 if (!ok)
976 return scope.engine->throwTypeError();
977 }
978 for (int i = 0, ei = argc; i < ei; ++i) {
979 bool ok = instance->put(i, argv[i]);
980 if (!ok)
981 return scope.engine->throwTypeError();
982 }
983 }
984
985 uint newLen = len + argc;
986 if (instance->isArrayObject())
987 instance->setArrayLengthUnchecked(newLen);
988 else {
989 if (!instance->put(scope.engine->id_length(), ScopedValue(scope, Value::fromDouble(newLen))))
990 return scope.engine->throwTypeError();
991 }
992
993 return Encode(newLen);
994}
995
996ReturnedValue ArrayPrototype::method_includes(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc)
997{
998 Scope scope(b);
999 ScopedObject instance(scope, thisObject->toObject(scope.engine));
1000 if (!instance)
1002
1003 qint64 len = instance->getLength();
1004 if (len == 0) {
1005 return Encode(false);
1006 }
1007
1008 double n = 0;
1009 if (argc > 1 && !argv[1].isUndefined()) {
1010 n = argv[1].toInteger();
1011 }
1012
1013 double k = 0;
1014 if (n >= 0) {
1015 k = n;
1016 } else {
1017 k = len + n;
1018 if (k < 0) {
1019 k = 0;
1020 }
1021 }
1022
1023 ScopedValue val(scope);
1024 while (k < len) {
1025 val = instance->get(k);
1026 if (val->sameValueZero(argv[0])) {
1027 return Encode(true);
1028 }
1029 k++;
1030 }
1031
1032 return Encode(false);
1033}
1034
1035ReturnedValue ArrayPrototype::method_indexOf(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc)
1036{
1037 Scope scope(b);
1038 ScopedObject instance(scope, thisObject->toObject(scope.engine));
1039 if (!instance)
1041
1042 uint len = instance->getLength();
1043 if (!len)
1044 return Encode(-1);
1045
1046 ScopedValue searchValue(scope, argc ? argv[0] : Value::undefinedValue());
1047 uint fromIndex = 0;
1048
1049 if (argc >= 2) {
1050 double f = argv[1].toInteger();
1052 if (f >= len)
1053 return Encode(-1);
1054 if (f < 0)
1055 f = qMax(len + f, 0.);
1056 fromIndex = (uint) f;
1057 }
1058
1059 if (instance->isStringObject()) {
1060 ScopedValue v(scope);
1061 for (uint k = fromIndex; k < len; ++k) {
1062 bool exists;
1063 v = instance->get(k, &exists);
1064 if (exists && RuntimeHelpers::strictEqual(v, searchValue))
1065 return Encode(k);
1066 }
1067 return Encode(-1);
1068 }
1069
1070 ScopedValue value(scope);
1071
1073 (instance->arrayType() >= Heap::ArrayData::Sparse) || instance->protoHasArray()) {
1074 // lets be safe and slow
1075 for (uint i = fromIndex; i < len; ++i) {
1076 bool exists;
1077 value = instance->get(i, &exists);
1079 if (exists && RuntimeHelpers::strictEqual(value, searchValue))
1080 return Encode(i);
1081 }
1082 } else if (!instance->arrayData()) {
1083 return Encode(-1);
1084 } else {
1085 Q_ASSERT(instance->arrayType() == Heap::ArrayData::Simple);
1086 Heap::SimpleArrayData *sa = instance->d()->arrayData.cast<Heap::SimpleArrayData>();
1087 if (len > sa->values.size)
1088 len = sa->values.size;
1089 uint idx = fromIndex;
1090 while (idx < len) {
1091 value = sa->data(idx);
1093 if (RuntimeHelpers::strictEqual(value, searchValue))
1094 return Encode(idx);
1095 ++idx;
1096 }
1097 }
1098 return Encode(-1);
1099}
1100
1102{
1103 Scope scope(f);
1104 ScopedObject O(scope, thisObject->toObject(scope.engine));
1105 if (!O)
1107
1108 Scoped<ArrayIteratorObject> ao(scope, scope.engine->newArrayIteratorObject(O));
1109 ao->d()->iterationKind = IteratorKind::KeyIteratorKind;
1110 return ao->asReturnedValue();
1111}
1112
1113ReturnedValue ArrayPrototype::method_lastIndexOf(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc)
1114{
1115 Scope scope(b);
1116 ScopedObject instance(scope, thisObject->toObject(scope.engine));
1117 if (!instance)
1119
1120 uint len = instance->getLength();
1121 if (!len)
1122 return Encode(-1);
1123
1124 ScopedValue searchValue(scope);
1125 uint fromIndex = len;
1126
1127 if (argc >= 1)
1128 searchValue = argv[0];
1129 else
1130 searchValue = Value::undefinedValue();
1131
1132 if (argc >= 2) {
1133 double f = argv[1].toInteger();
1135 if (f > 0)
1136 f = qMin(f, (double)(len - 1));
1137 else if (f < 0) {
1138 f = len + f;
1139 if (f < 0)
1140 return Encode(-1);
1141 }
1142 fromIndex = (uint) f + 1;
1143 }
1144
1145 ScopedValue v(scope);
1146 for (uint k = fromIndex; k > 0;) {
1147 --k;
1148 bool exists;
1149 v = instance->get(k, &exists);
1151 if (exists && RuntimeHelpers::strictEqual(v, searchValue))
1152 return Encode(k);
1153 }
1154 return Encode(-1);
1155}
1156
1157ReturnedValue ArrayPrototype::method_every(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc)
1158{
1159 Scope scope(b);
1160 ScopedObject instance(scope, thisObject->toObject(scope.engine));
1161 if (!instance)
1163
1164 uint len = instance->getLength();
1165
1166 if (!argc || !argv->isFunctionObject())
1168 const FunctionObject *callback = static_cast<const FunctionObject *>(argv);
1169
1170 ScopedValue that(scope, argc > 1 ? argv[1] : Value::undefinedValue());
1171 ScopedValue r(scope);
1172 Value *arguments = scope.alloc(3);
1173
1174 bool ok = true;
1175 for (uint k = 0; ok && k < len; ++k) {
1176 bool exists;
1177 arguments[0] = instance->get(k, &exists);
1178 if (!exists)
1179 continue;
1180
1182 arguments[2] = instance;
1183 r = callback->call(that, arguments, 3);
1185 ok = r->toBoolean();
1186 }
1187 return Encode(ok);
1188}
1189
1190ReturnedValue ArrayPrototype::method_fill(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc)
1191{
1192 Scope scope(b);
1193 ScopedObject instance(scope, thisObject->toObject(scope.engine));
1194 if (!instance)
1196
1197 const qsizetype len = instance->getLength();
1198 Q_ASSERT(len >= 0);
1199
1200 const qsizetype relativeStart = argc > 1 ? argv[1].toInteger() : 0;
1201 qsizetype relativeEnd = len;
1202 if (argc > 2 && !argv[2].isUndefined())
1203 relativeEnd = argv[2].toInteger();
1204
1205 qsizetype k = 0;
1206 qsizetype fin = 0;
1207
1208 if (relativeStart < 0) {
1209 if (relativeStart > -len)
1210 k = std::max(len + relativeStart, qsizetype(0));
1211 } else {
1212 k = std::min(relativeStart, len);
1213 }
1214 Q_ASSERT(k >= 0);
1215
1216 if (relativeEnd < 0) {
1217 if (relativeEnd > -len)
1218 fin = std::max(len + relativeEnd, qsizetype(0));
1219 } else {
1220 fin = std::min(relativeEnd, len);
1221 }
1222 Q_ASSERT(fin >= 0);
1223
1224 if (sizeof(qsizetype) > sizeof(uint) && fin > qsizetype(std::numeric_limits<uint>::max()))
1225 return scope.engine->throwRangeError(QString::fromLatin1("Array length out of range."));
1226
1227 for (; k < fin; ++k)
1228 instance->setIndexed(uint(k), argv[0], QV4::Object::DoThrowOnRejection);
1229
1230 return instance.asReturnedValue();
1231}
1232
1233ReturnedValue ArrayPrototype::method_some(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc)
1234{
1235 Scope scope(b);
1236 ScopedObject instance(scope, thisObject->toObject(scope.engine));
1237 if (!instance)
1239
1240 uint len = instance->getLength();
1241
1242 if (!argc || !argv->isFunctionObject())
1244 const FunctionObject *callback = static_cast<const FunctionObject *>(argv);
1245
1246 ScopedValue that(scope, argc > 1 ? argv[1] : Value::undefinedValue());
1247 ScopedValue result(scope);
1248 Value *arguments = scope.alloc(3);
1249
1250 for (uint k = 0; k < len; ++k) {
1251 bool exists;
1252 arguments[0] = instance->get(k, &exists);
1253 if (!exists)
1254 continue;
1255
1257 arguments[2] = instance;
1258 result = callback->call(that, arguments, 3);
1260 if (result->toBoolean())
1261 return Encode(true);
1262 }
1263 return Encode(false);
1264}
1265
1266ReturnedValue ArrayPrototype::method_forEach(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc)
1267{
1268 Scope scope(b);
1269 ScopedObject instance(scope, thisObject->toObject(scope.engine));
1270 if (!instance)
1272
1273 uint len = instance->getLength();
1274
1275 if (!argc || !argv->isFunctionObject())
1277 const FunctionObject *callback = static_cast<const FunctionObject *>(argv);
1278
1279 ScopedValue that(scope, argc > 1 ? argv[1] : Value::undefinedValue());
1280 Value *arguments = scope.alloc(3);
1281
1282 for (uint k = 0; k < len; ++k) {
1283 bool exists;
1284 arguments[0] = instance->get(k, &exists);
1285 if (!exists)
1286 continue;
1287
1289 arguments[2] = instance;
1290 callback->call(that, arguments, 3);
1291 }
1293}
1294
1295ReturnedValue ArrayPrototype::method_map(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc)
1296{
1297 Scope scope(b);
1298 ScopedObject instance(scope, thisObject->toObject(scope.engine));
1299 if (!instance)
1301
1302 qint64 len = instance->getLength();
1303
1304 if (!argc || !argv->isFunctionObject())
1306 const FunctionObject *callback = static_cast<const FunctionObject *>(argv);
1307
1308 if (len > UINT_MAX - 1)
1309 return scope.engine->throwRangeError(QString::fromLatin1("Array length out of range."));
1310
1311 ScopedArrayObject a(scope, scope.engine->newArrayObject());
1312 a->arrayReserve(len);
1313 a->setArrayLengthUnchecked(len);
1314
1315 ScopedValue v(scope);
1316 ScopedValue mapped(scope);
1317 ScopedValue that(scope, argc > 1 ? argv[1] : Value::undefinedValue());
1318 Value *arguments = scope.alloc(3);
1319
1320 for (uint k = 0; k < len; ++k) {
1321 bool exists;
1322 arguments[0] = instance->get(k, &exists);
1323 if (!exists)
1324 continue;
1325
1327 arguments[2] = instance;
1328 mapped = callback->call(that, arguments, 3);
1330 a->arraySet(k, mapped);
1331 }
1332 return a.asReturnedValue();
1333}
1334
1335ReturnedValue ArrayPrototype::method_filter(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc)
1336{
1337 Scope scope(b);
1338 ScopedObject instance(scope, thisObject->toObject(scope.engine));
1339 if (!instance)
1341
1342 uint len = instance->getLength();
1343
1344 if (!argc || !argv->isFunctionObject())
1346 const FunctionObject *callback = static_cast<const FunctionObject *>(argv);
1347
1348 ScopedArrayObject a(scope, scope.engine->newArrayObject());
1349 a->arrayReserve(len);
1350
1351 ScopedValue selected(scope);
1352 ScopedValue that(scope, argc > 1 ? argv[1] : Value::undefinedValue());
1353 Value *arguments = scope.alloc(3);
1354
1355 uint to = 0;
1356 for (uint k = 0; k < len; ++k) {
1357 bool exists;
1358 arguments[0] = instance->get(k, &exists);
1359 if (!exists)
1360 continue;
1361
1363 arguments[2] = instance;
1364 selected = callback->call(that, arguments, 3);
1366 if (selected->toBoolean()) {
1367 a->arraySet(to, arguments[0]);
1368 ++to;
1369 }
1370 }
1371 return a.asReturnedValue();
1372}
1373
1374ReturnedValue ArrayPrototype::method_reduce(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc)
1375{
1376 Scope scope(b);
1377 ScopedObject instance(scope, thisObject->toObject(scope.engine));
1378 if (!instance)
1380
1381 uint len = instance->getLength();
1382
1383 if (!argc || !argv->isFunctionObject())
1385 const FunctionObject *callback = static_cast<const FunctionObject *>(argv);
1386
1387 uint k = 0;
1388 ScopedValue acc(scope);
1389 ScopedValue v(scope);
1390
1391 if (argc > 1) {
1392 acc = argv[1];
1393 } else {
1394 bool kPresent = false;
1395 while (k < len && !kPresent) {
1396 v = instance->get(k, &kPresent);
1397 if (kPresent)
1398 acc = v;
1399 ++k;
1400 }
1401 if (!kPresent)
1403 }
1404
1405 Value *arguments = scope.alloc(4);
1406
1407 while (k < len) {
1408 bool kPresent;
1409 v = instance->get(k, &kPresent);
1410 if (kPresent) {
1411 arguments[0] = acc;
1412 arguments[1] = v;
1414 arguments[3] = instance;
1415 acc = callback->call(nullptr, arguments, 4);
1417 }
1418 ++k;
1419 }
1420 return acc->asReturnedValue();
1421}
1422
1423ReturnedValue ArrayPrototype::method_reduceRight(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc)
1424{
1425 Scope scope(b);
1426 ScopedObject instance(scope, thisObject->toObject(scope.engine));
1427 if (!instance)
1429
1430 uint len = instance->getLength();
1431
1432 if (!argc || !argv->isFunctionObject())
1434 const FunctionObject *callback = static_cast<const FunctionObject *>(argv);
1435
1436 if (len == 0) {
1437 if (argc == 1)
1439 return argv[1].asReturnedValue();
1440 }
1441
1442 uint k = len;
1443 ScopedValue acc(scope);
1444 ScopedValue v(scope);
1445 if (argc > 1) {
1446 acc = argv[1];
1447 } else {
1448 bool kPresent = false;
1449 while (k > 0 && !kPresent) {
1450 v = instance->get(k - 1, &kPresent);
1451 if (kPresent)
1452 acc = v;
1453 --k;
1454 }
1455 if (!kPresent)
1457 }
1458
1459 Value *arguments = scope.alloc(4);
1460
1461 while (k > 0) {
1462 bool kPresent;
1463 v = instance->get(k - 1, &kPresent);
1464 if (kPresent) {
1465 arguments[0] = acc;
1466 arguments[1] = v;
1467 arguments[2] = Value::fromDouble(k - 1);
1468 arguments[3] = instance;
1469 acc = callback->call(nullptr, arguments, 4);
1471 }
1472 --k;
1473 }
1474 return acc->asReturnedValue();
1475}
1476
1478{
1479 Scope scope(b);
1480 ScopedObject O(scope, thisObject->toObject(scope.engine));
1481 if (!O)
1483
1484 Scoped<ArrayIteratorObject> ao(scope, scope.engine->newArrayIteratorObject(O));
1485 ao->d()->iterationKind = IteratorKind::ValueIteratorKind;
1486 return ao->asReturnedValue();
1487}
1488
1490{
1491 return thisObject->asReturnedValue();
1492}
1493
QJSValue newObject()
Creates a JavaScript object of class Object.
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:129
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
QString str
[2]
QSet< QString >::iterator it
QList< QVariant > arguments
direction
Scoped< FunctionObject > ScopedFunctionObject
quint64 ReturnedValue
@ KeyValueIteratorKind
@ ValueIteratorKind
@ KeyIteratorKind
ReturnedValue checkedResult(QV4::ExecutionEngine *v4, ReturnedValue result)
Scoped< String > ScopedString
@ Attr_Invalid
static int arrayLength(const QString &rawType)
Definition provider.cpp:52
DBusConnection const char DBusError DBusBusType DBusError return DBusConnection DBusHandleMessageFunction function
DBusConnection const char DBusError * error
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
#define forever
Definition qforeach.h:78
constexpr const T & qMin(const T &a, const T &b)
Definition qminmax.h:40
constexpr const T & qMax(const T &a, const T &b)
Definition qminmax.h:42
GLenum GLsizei GLsizei GLint * values
[15]
GLboolean GLboolean GLboolean b
GLsizei const GLfloat * v
[13]
GLboolean GLboolean GLboolean GLboolean a
[7]
GLboolean r
[2]
GLuint GLuint end
GLenum GLuint GLenum GLsizei length
GLenum GLenum GLsizei count
GLfloat GLfloat f
GLenum target
GLuint start
GLuint name
GLfloat n
GLdouble s
[6]
Definition qopenglext.h:235
GLuint GLfloat * val
GLuint entry
GLuint64EXT * result
[6]
GLenum GLsizei len
GLsizei const GLchar *const * string
[0]
Definition qopenglext.h:694
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
SSL_CTX int void * arg
QLatin1StringView QLatin1String
Definition qstringfwd.h:31
#define QStringLiteral(str)
unsigned int quint32
Definition qtypes.h:50
unsigned long long quint64
Definition qtypes.h:61
ptrdiff_t qsizetype
Definition qtypes.h:165
unsigned int uint
Definition qtypes.h:34
long long qint64
Definition qtypes.h:60
static ScopedObject createObjectFromCtorOrArray(Scope &scope, ScopedFunctionObject ctor, bool useLen, int len)
#define THROW_TYPE_ERROR()
#define CHECK_EXCEPTION()
#define RETURN_UNDEFINED()
#define DEFINE_OBJECT_VTABLE(classname)
QDBusArgument argument
QJSEngine engine
[0]
static bool isNonStrictArgumentsObject(Managed *m)
static void sort(ExecutionEngine *engine, Object *thisObject, const Value &comparefn, uint dataLen)
static uint append(Object *obj, ArrayObject *otherObj, uint n)
static ReturnedValue method_lastIndexOf(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_from(const FunctionObject *, const Value *thisObject, const Value *argv, int argc)
static ReturnedValue method_isArray(const FunctionObject *, const Value *thisObject, const Value *argv, int argc)
static ReturnedValue method_includes(const FunctionObject *, const Value *thisObject, const Value *argv, int argc)
static ReturnedValue method_reduceRight(const FunctionObject *, const Value *thisObject, const Value *argv, int argc)
static ReturnedValue method_shift(const FunctionObject *, const Value *thisObject, const Value *argv, int argc)
static ReturnedValue method_indexOf(const FunctionObject *, const Value *thisObject, const Value *argv, int argc)
static ReturnedValue method_find(const FunctionObject *, const Value *thisObject, const Value *argv, int argc)
static ReturnedValue method_of(const FunctionObject *, const Value *thisObject, const Value *argv, int argc)
static ReturnedValue method_reduce(const FunctionObject *, const Value *thisObject, const Value *argv, int argc)
static ReturnedValue method_reverse(const FunctionObject *, const Value *thisObject, const Value *argv, int argc)
static ReturnedValue method_toLocaleString(const FunctionObject *, const Value *thisObject, const Value *argv, int argc)
static ReturnedValue method_toString(const FunctionObject *, const Value *thisObject, const Value *argv, int argc)
static ReturnedValue method_get_species(const FunctionObject *, const Value *thisObject, const Value *argv, int argc)
static ReturnedValue method_findIndex(const FunctionObject *, const Value *thisObject, const Value *argv, int argc)
static ReturnedValue method_slice(const FunctionObject *, const Value *thisObject, const Value *argv, int argc)
static ReturnedValue method_every(const FunctionObject *, const Value *thisObject, const Value *argv, int argc)
static ReturnedValue method_concat(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_entries(const FunctionObject *, const Value *thisObject, const Value *argv, int argc)
static ReturnedValue method_copyWithin(const FunctionObject *, const Value *thisObject, const Value *argv, int argc)
static ReturnedValue method_filter(const FunctionObject *, const Value *thisObject, const Value *argv, int argc)
static ReturnedValue method_unshift(const FunctionObject *, const Value *thisObject, const Value *argv, int argc)
static ReturnedValue method_some(const FunctionObject *, const Value *thisObject, const Value *argv, int argc)
static ReturnedValue method_push(const FunctionObject *, const Value *thisObject, const Value *argv, int argc)
static ReturnedValue method_join(const FunctionObject *, const Value *thisObject, const Value *argv, int argc)
static ReturnedValue method_pop(const FunctionObject *, const Value *thisObject, const Value *argv, int argc)
static ReturnedValue method_sort(const FunctionObject *, const Value *thisObject, const Value *argv, int argc)
static ReturnedValue method_fill(const FunctionObject *, const Value *thisObject, const Value *argv, int argc)
static ReturnedValue method_map(const FunctionObject *, const Value *thisObject, const Value *argv, int argc)
static ReturnedValue method_keys(const FunctionObject *, const Value *thisObject, const Value *argv, int argc)
static ReturnedValue method_splice(const FunctionObject *, const Value *thisObject, const Value *argv, int argc)
static constexpr ReturnedValue undefined()
Symbol * symbol_iterator() const
ReturnedValue throwRangeError(const Value &value)
String * id_length() const
String * id_toLocaleString() const
Heap::String * newString(char16_t c)
Heap::ArrayObject * newArrayObject(int count=0)
Heap::Object * newArrayIteratorObject(Object *o)
ReturnedValue throwTypeError()
static Heap::FunctionObject * createBuiltinFunction(ExecutionEngine *engine, StringOrSymbol *nameOrSymbol, VTable::Call code, int argumentCount)
ReturnedValue call(const Value *thisObject, const Value *argv, int argc) const
void init(QV4::ExecutionEngine *engine)
ReturnedValue asReturnedValue() const
Definition qv4value_p.h:342
bool isStringObject() const
bool isArrayObject() const
ExecutionEngine * engine() const
static ReturnedValue method_toString(const FunctionObject *, const Value *thisObject, const Value *argv, int argc)
bool setArrayLength(uint newLen)
bool deleteProperty(PropertyKey id)
bool protoHasArray()
qint64 getLength() const
bool isArray() const
void arrayCreate()
Heap::ArrayData * arrayData() const
bool setIndexed(uint idx, const Value &v, ThrowOnFailure shouldThrow)
ArrayData::Type arrayType() const
bool put(StringOrSymbol *name, const Value &v, Value *receiver=nullptr)
void setArrayLengthUnchecked(uint l)
ReturnedValue get(StringOrSymbol *name, bool *hasProperty=nullptr, const Value *receiver=nullptr) const
static PropertyKey fromArrayIndex(uint idx)
static Bool strictEqual(const Value &x, const Value &y)
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
QML_NEARLY_ALWAYS_INLINE ReturnedValue asReturnedValue() const
bool isNumber() const
constexpr ReturnedValue asReturnedValue() const
static constexpr VTable::CallAsConstructor virtualCallAsConstructor
static constexpr VTable::Call virtualCall
static constexpr Value fromInt32(int i)
Definition qv4value_p.h:187
bool isFunctionObject() const
Definition qv4value_p.h:309
bool toBoolean() const
Definition qv4value_p.h:97
static constexpr Value fromBoolean(bool b)
Definition qv4value_p.h:183
static constexpr Value undefinedValue()
Definition qv4value_p.h:191
static Value fromDouble(double d)
Definition qv4value_p.h:199
uint asArrayLength(bool *ok) const
Definition qv4value.cpp:275
QML_NEARLY_ALWAYS_INLINE Object * objectValue() const
Definition qv4value_p.h:70
static constexpr Value fromReturnedValue(ReturnedValue val)
Definition qv4value_p.h:165
const T * as() const
Definition qv4value_p.h:132
double toInteger() const
Definition qv4value_p.h:394
Heap::Object * toObject(ExecutionEngine *e) const
Definition qv4value_p.h:122