55void ArrayPrototype::init(ExecutionEngine *engine, Object *ctor)
58 ScopedObject o(scope);
59 ctor->defineReadonlyConfigurableProperty(engine->id_length(), Value::fromInt32(1));
60 ctor->defineReadonlyProperty(engine->id_prototype(), (o =
this));
61 ctor->defineDefaultProperty(QStringLiteral(
"isArray"), method_isArray, 1);
62 ctor->defineDefaultProperty(QStringLiteral(
"of"), method_of, 0);
63 ctor->defineDefaultProperty(QStringLiteral(
"from"), method_from, 1);
64 ctor->addSymbolSpecies();
66 Scoped<InternalClass> ic(scope, engine->classes[EngineBase::Class_Empty]
67 ->changeVTable(QV4::Object::staticVTable()));
68 ScopedObject unscopables(scope, engine->newObject(ic->d()));
69 ScopedString name(scope);
70 defineDefaultProperty(QStringLiteral(
"constructor"), (o = ctor));
71 defineDefaultProperty(engine->id_toString(), method_toString, 0);
72 defineDefaultProperty(engine->id_toLocaleString(), method_toLocaleString, 0);
73 defineDefaultProperty(QStringLiteral(
"concat"), method_concat, 1);
74 name = engine->newIdentifier(QStringLiteral(
"copyWithin"));
75 unscopables->put(name, Value::fromBoolean(
true));
76 defineDefaultProperty(name, method_copyWithin, 2);
77 name = engine->newIdentifier(QStringLiteral(
"entries"));
78 unscopables->put(name, Value::fromBoolean(
true));
79 defineDefaultProperty(name, method_entries, 0);
80 name = engine->newIdentifier(QStringLiteral(
"fill"));
81 unscopables->put(name, Value::fromBoolean(
true));
82 defineDefaultProperty(name, method_fill, 1);
83 name = engine->newIdentifier(QStringLiteral(
"find"));
84 unscopables->put(name, Value::fromBoolean(
true));
85 defineDefaultProperty(name, method_find, 1);
86 name = engine->newIdentifier(QStringLiteral(
"findIndex"));
87 unscopables->put(name, Value::fromBoolean(
true));
88 defineDefaultProperty(name, method_findIndex, 1);
89 name = engine->newIdentifier(QStringLiteral(
"includes"));
90 unscopables->put(name, Value::fromBoolean(
true));
91 defineDefaultProperty(name, method_includes, 1);
92 defineDefaultProperty(QStringLiteral(
"join"), method_join, 1);
93 name = engine->newIdentifier(QStringLiteral(
"keys"));
94 unscopables->put(name, Value::fromBoolean(
true));
95 defineDefaultProperty(name, method_keys, 0);
96 defineDefaultProperty(QStringLiteral(
"pop"), method_pop, 0);
97 defineDefaultProperty(QStringLiteral(
"push"), method_push, 1);
98 defineDefaultProperty(QStringLiteral(
"reverse"), method_reverse, 0);
99 defineDefaultProperty(QStringLiteral(
"shift"), method_shift, 0);
100 defineDefaultProperty(QStringLiteral(
"slice"), method_slice, 2);
101 defineDefaultProperty(QStringLiteral(
"sort"), method_sort, 1);
102 defineDefaultProperty(QStringLiteral(
"splice"), method_splice, 2);
103 defineDefaultProperty(QStringLiteral(
"unshift"), method_unshift, 1);
104 defineDefaultProperty(QStringLiteral(
"indexOf"), method_indexOf, 1);
105 defineDefaultProperty(QStringLiteral(
"lastIndexOf"), method_lastIndexOf, 1);
106 defineDefaultProperty(QStringLiteral(
"every"), method_every, 1);
107 defineDefaultProperty(QStringLiteral(
"some"), method_some, 1);
108 defineDefaultProperty(QStringLiteral(
"forEach"), method_forEach, 1);
109 defineDefaultProperty(QStringLiteral(
"map"), method_map, 1);
110 defineDefaultProperty(QStringLiteral(
"filter"), method_filter, 1);
111 defineDefaultProperty(QStringLiteral(
"reduce"), method_reduce, 1);
112 defineDefaultProperty(QStringLiteral(
"reduceRight"), method_reduceRight, 1);
113 ScopedString valuesString(scope, engine->newIdentifier(QStringLiteral(
"values")));
114 ScopedObject values(scope, FunctionObject::createBuiltinFunction(engine, valuesString, method_values, 0));
115 engine->jsObjects[ExecutionEngine::ArrayProtoValues] = values;
116 unscopables->put(valuesString, Value::fromBoolean(
true));
117 defineDefaultProperty(valuesString, values);
118 defineDefaultProperty(engine->symbol_iterator(), values);
120 defineReadonlyConfigurableProperty(engine->symbol_unscopables(), unscopables);
148ReturnedValue ArrayPrototype::method_from(
const FunctionObject *builtin,
const Value *thisObject,
const Value *argv,
int argc)
150 Scope scope(builtin);
151 ScopedFunctionObject thatCtor(scope, thisObject);
152 ScopedObject itemsObject(scope, argv[0]);
153 bool usingIterator =
false;
157 ScopedValue it(scope, itemsObject->get(scope.engine->symbol_iterator()));
158 if (!it->isNullOrUndefined()) {
159 ScopedFunctionObject itfunc(scope, it);
161 return scope.engine->throwTypeError();
162 usingIterator =
true;
166 ScopedFunctionObject mapfn(scope, Value::undefinedValue());
167 Value *mapArguments =
nullptr;
169 mapfn = ScopedFunctionObject(scope, argv[1]);
171 return scope.engine->throwTypeError(QString::fromLatin1(
"%1 is not a function").arg(argv[1].toQStringNoThrow()));
172 mapArguments = scope.constructUndefined(2);
175 ScopedValue thisArg(scope);
181 ScopedObject a(createObjectFromCtorOrArray(scope, thatCtor,
false, 0));
183 ScopedObject iterator(scope, Runtime::GetIterator::call(scope.engine, itemsObject,
true));
186 return scope.engine->throwTypeError();
190 ScopedValue mappedValue(scope);
191 Value *nextValue = scope.constructUndefined(1);
192 ScopedValue done(scope);
197 if (k > (
static_cast<qint64>(1) << 53) - 1) {
198 ScopedValue error(scope, scope.engine->throwTypeError());
199 return Runtime::IteratorClose::call(scope.engine, iterator);
203 done = Value::fromReturnedValue(Runtime::IteratorNext::call(scope.engine, iterator, nextValue));
205 if (done->toBoolean()) {
206 if (ArrayObject *ao = a->as<ArrayObject>()) {
207 ao->setArrayLengthUnchecked(k);
209 a->set(scope.engine->id_length(), Value::fromDouble(k), QV4::Object::DoThrowOnRejection);
212 return a.asReturnedValue();
216 Q_ASSERT(mapArguments);
217 mapArguments[0] = *nextValue;
218 mapArguments[1] = Value::fromDouble(k);
219 mappedValue = mapfn->call(thisArg, mapArguments, 2);
220 if (scope.hasException())
221 return Runtime::IteratorClose::call(scope.engine, iterator);
223 mappedValue = *nextValue;
226 if (a->getOwnProperty(PropertyKey::fromArrayIndex(k)) == Attr_Invalid) {
227 a->arraySet(k, mappedValue);
230 scope.engine->throwTypeError(QString::fromLatin1(
"Cannot redefine property: %1").arg(k));
233 if (scope.hasException())
234 return Runtime::IteratorClose::call(scope.engine, iterator);
243 ScopedObject arrayLike(scope, argv[0].toObject(scope.engine));
245 return scope.engine->throwTypeError(QString::fromLatin1(
"Cannot convert %1 to object").arg(argv[0].toQStringNoThrow()));
246 qint64 len = arrayLike->getLength();
247 ScopedObject a(createObjectFromCtorOrArray(scope, thatCtor,
true, len));
251 ScopedValue mappedValue(scope, Value::undefinedValue());
252 ScopedValue kValue(scope);
254 kValue = arrayLike->get(k);
258 Q_ASSERT(mapArguments);
259 mapArguments[0] = kValue;
260 mapArguments[1] = Value::fromDouble(k);
261 mappedValue = mapfn->call(thisArg, mapArguments, 2);
264 mappedValue = kValue;
267 if (a->getOwnProperty(PropertyKey::fromArrayIndex(k)) != Attr_Invalid)
268 return scope.engine->throwTypeError(QString::fromLatin1(
"Cannot redefine property: %1").arg(k));
270 a->arraySet(k, mappedValue);
276 if (ArrayObject *ao = a->as<ArrayObject>()) {
277 ao->setArrayLengthUnchecked(k);
279 a->set(scope.engine->id_length(), Value::fromDouble(k), QV4::Object::DoThrowOnRejection);
282 return a.asReturnedValue();
328ReturnedValue ArrayPrototype::method_toLocaleString(
const FunctionObject *b,
const Value *thisObject,
const Value *,
int)
331 ScopedObject instance(scope, thisObject);
333 return scope.engine->throwTypeError();
335 uint len = instance->getLength();
336 const QString separator = QStringLiteral(
",");
340 ScopedValue v(scope);
341 ScopedString s(scope);
343 ScopedPropertyKey tolocaleString(scope, scope.engine->id_toLocaleString()->toPropertyKey());
344 Q_ASSERT(!scope.engine->hasException);
346 for (uint k = 0; k < len; ++k) {
350 v = instance->get(k);
351 if (v->isNullOrUndefined())
354 ScopedObject valueAsObject(scope, v->toObject(scope.engine));
355 Q_ASSERT(valueAsObject);
357 ScopedFunctionObject function(scope, valueAsObject->get(tolocaleString));
359 return scope.engine->throwTypeError();
361 v = function->call(valueAsObject,
nullptr, 0);
362 if (scope.hasException())
363 return Encode::undefined();
365 s = v->toString(scope.engine);
366 if (scope.hasException())
367 return Encode::undefined();
371 return scope.engine->newString(R)->asReturnedValue();
374ReturnedValue ArrayPrototype::method_concat(
const FunctionObject *b,
const Value *that,
const Value *argv,
int argc)
377 ScopedObject thisObject(scope, that->toObject(scope.engine));
381 ScopedArrayObject result(scope, scope.engine->newArrayObject());
383 ScopedArrayObject elt(scope);
384 ScopedObject eltAsObj(scope);
385 ScopedValue entry(scope);
386 for (
int i = -1; i < argc; ++i) {
387 const Value *v = i == -1 ? thisObject.getPointer() : argv + i;
391 uint n = elt->getLength();
392 uint newLen = ArrayData::append(result, elt, n);
393 result->setArrayLengthUnchecked(newLen);
394 }
else if (eltAsObj && eltAsObj->isConcatSpreadable()) {
395 const uint startIndex = result->getLength();
396 const uint len = eltAsObj->getLength();
397 if (scope.hasException())
398 return Encode::undefined();
400 for (uint i = 0; i < len; ++i) {
401 bool hasProperty =
false;
402 entry = eltAsObj->get(i, &hasProperty);
404 if (!result->put(startIndex + i, entry))
405 return scope.engine->throwTypeError();
408 }
else if (eltAsObj && eltAsObj->isArrayLike()) {
409 const uint startIndex = result->getLength();
410 for (
int i = 0, len = eltAsObj->getLength(); i < len; ++i) {
411 entry = eltAsObj->get(i);
413 result->put(startIndex + i, entry);
416 result->arraySet(result->getLength(), *v);
420 return result.asReturnedValue();
423ReturnedValue ArrayPrototype::method_copyWithin(
const FunctionObject *b,
const Value *thisObject,
const Value *argv,
int argc)
426 ScopedObject instance(scope, thisObject->toObject(scope.engine));
430 double len = instance->getLength();
431 double target = argv[0].toInteger();
432 double start = argc > 1 ? argv[1].toInteger() : 0;
435 if (argc > 2 && !argv[2].isUndefined()) {
436 end = argv[2].toInteger();
439 double relativeTarget = target;
440 double relativeStart = start;
441 double relativeEnd = end;
445 if (relativeTarget < 0) {
446 to = std::max(len+relativeTarget, 0.0);
448 to = std::min(relativeTarget, len);
450 if (relativeStart < 0) {
451 from = std::max(len+relativeStart, 0.0);
453 from = std::min(relativeStart, len);
457 if (relativeEnd < 0) {
458 fin = std::max(len+relativeEnd, 0.0);
460 fin = std::min(relativeEnd, len);
462 double count = std::min(fin-from, len-to);
463 double direction = 1;
464 if (from < to && to < from+count) {
466 from = from + count - 1;
471 bool fromPresent =
false;
472 ScopedValue fromVal(scope, instance->get(from, &fromPresent));
475 instance->setIndexed(to, fromVal, QV4::Object::DoThrowOnRejection);
478 bool didDelete = instance->deleteProperty(PropertyKey::fromArrayIndex(to));
481 return scope.engine->throwTypeError();
485 from = from + direction;
490 return instance.asReturnedValue();
573ReturnedValue ArrayPrototype::method_join(
const FunctionObject *functionObject,
574 const Value *thisObject,
const Value *argv,
int argc)
576 Scope scope(functionObject);
578 ScopedObject instance(scope, thisObject->toObject(scope.engine));
581 return Encode(scope.engine->newString());
585 ScopedValue argument(scope, argc ? argv[0] : Value::undefinedValue());
586 const QString separator = argument->isUndefined()
587 ? QStringLiteral(
",")
588 : argument->toQString();
590 ScopedValue scopedLength(scope, instance->get(scope.engine->id_length()));
591 const quint32 genericLength = scopedLength->isUndefined() ? 0 : scopedLength->toUInt32();
593 return Encode(scope.engine->newString());
596 if (
auto *arrayObject = instance->as<ArrayObject>()) {
597 ScopedValue entry(scope);
598 const qint64 arrayLength = arrayObject->getLength();
599 Q_ASSERT(arrayLength >= 0);
600 Q_ASSERT(arrayLength <= std::numeric_limits<quint32>::max());
601 for (quint32 i = 0; i < quint32(arrayLength); ++i) {
605 entry = arrayObject->get(i);
607 if (!entry->isNullOrUndefined())
608 result += entry->toQString();
611 ScopedString name(scope, scope.engine->newString(QStringLiteral(
"0")));
612 ScopedValue value(scope, instance->get(name));
615 if (!value->isNullOrUndefined())
616 result = value->toQString();
618 for (quint32 i = 1; i < genericLength; ++i) {
621 name = Value::fromDouble(i).toString(scope.engine);
622 value = instance->get(name);
625 if (!value->isNullOrUndefined())
626 result += value->toQString();
630 return Encode(scope.engine->newString(result));
633ReturnedValue ArrayPrototype::method_pop(
const FunctionObject *b,
const Value *thisObject,
const Value *,
int)
636 ScopedObject instance(scope, thisObject->toObject(scope.engine));
640 uint len = instance->getLength();
643 if (!instance->isArrayObject())
644 instance->put(scope.engine->id_length(), ScopedValue(scope, Value::fromInt32(0)));
648 ScopedValue result(scope, instance->get(len - 1));
651 if (!instance->deleteProperty(PropertyKey::fromArrayIndex(len - 1)))
652 return scope.engine->throwTypeError();
654 if (instance->isArrayObject())
655 instance->setArrayLength(len - 1);
657 if (!instance->put(scope.engine->id_length(), ScopedValue(scope, Value::fromDouble(len - 1))))
658 return scope.engine->throwTypeError();
660 return result->asReturnedValue();
663ReturnedValue ArrayPrototype::method_push(
const FunctionObject *b,
const Value *thisObject,
const Value *argv,
int argc)
666 ScopedObject instance(scope, thisObject->toObject(scope.engine));
670 instance->arrayCreate();
671 Q_ASSERT(instance->arrayData());
673 qint64 len = instance->getLength();
675 if (len + quint64(argc) >= UINT_MAX) {
678 ScopedString s(scope);
679 for (
int i = 0, ei = argc; i < ei; ++i) {
680 s = Value::fromDouble(l + i).toString(scope.engine);
681 if (!instance->put(s, argv[i]))
682 return scope.engine->throwTypeError();
684 double newLen = l + argc;
685 if (!instance->isArrayObject()) {
686 if (!instance->put(scope.engine->id_length(), ScopedValue(scope, Value::fromDouble(newLen))))
687 return scope.engine->throwTypeError();
689 ScopedString str(scope, scope.engine->newString(QStringLiteral(
"Array.prototype.push: Overflow")));
690 return scope.engine->throwRangeError(str);
692 return Encode(newLen);
697 else if (!instance->protoHasArray() && instance->arrayData()->length() <= len && instance->arrayData()->type == Heap::ArrayData::Simple) {
698 instance->arrayData()->vtable()->putArray(instance, len, argv, argc);
699 len = instance->arrayData()->length();
701 for (
int i = 0, ei = argc; i < ei; ++i) {
702 if (!instance->put(len + i, argv[i]))
703 return scope.engine->throwTypeError();
707 if (instance->isArrayObject())
708 instance->setArrayLengthUnchecked(len);
710 if (!instance->put(scope.engine->id_length(), ScopedValue(scope, Value::fromDouble(len))))
711 return scope.engine->throwTypeError();
714 return Encode(uint(len));
717ReturnedValue ArrayPrototype::method_reverse(
const FunctionObject *b,
const Value *thisObject,
const Value *,
int)
720 ScopedObject instance(scope, thisObject->toObject(scope.engine));
724 qint64 length = instance->getLength();
726 if (length >= UINT_MAX)
727 return scope.engine->throwRangeError(QLatin1String(
"Array.prototype.reverse: Length out of range."));
729 int lo = 0, hi = length - 1;
731 ScopedValue lval(scope);
732 ScopedValue hval(scope);
733 for (; lo < hi; ++lo, --hi) {
734 bool loExists, hiExists;
735 lval = instance->get(lo, &loExists);
736 hval = instance->get(hi, &hiExists);
740 ok = instance->put(lo, hval);
742 ok = instance->deleteProperty(PropertyKey::fromArrayIndex(lo));
745 ok = instance->put(hi, lval);
747 ok = instance->deleteProperty(PropertyKey::fromArrayIndex(hi));
750 return scope.engine->throwTypeError();
752 return instance->asReturnedValue();
755ReturnedValue ArrayPrototype::method_shift(
const FunctionObject *b,
const Value *thisObject,
const Value *,
int)
758 ScopedObject instance(scope, thisObject->toObject(scope.engine));
762 instance->arrayCreate();
763 Q_ASSERT(instance->arrayData());
765 uint len = instance->getLength();
768 if (!instance->isArrayObject())
769 if (!instance->put(scope.engine->id_length(), ScopedValue(scope, Value::fromInt32(0))))
770 return scope.engine->throwTypeError();
774 ScopedValue result(scope);
775 if (!instance->protoHasArray() && !instance->arrayData()->attrs && instance->arrayData()->length() <= len && instance->arrayData()->type != Heap::ArrayData::Custom) {
776 result = instance->arrayData()->vtable()->pop_front(instance);
778 result = instance->get(uint(0));
780 ScopedValue v(scope);
782 for (uint k = 1; k < len; ++k) {
784 v = instance->get(k, &exists);
788 ok = instance->put(k - 1, v);
790 ok = instance->deleteProperty(PropertyKey::fromArrayIndex(k - 1));
792 return scope.engine->throwTypeError();
794 bool ok = instance->deleteProperty(PropertyKey::fromArrayIndex(len - 1));
796 return scope.engine->throwTypeError();
799 if (instance->isArrayObject())
800 instance->setArrayLengthUnchecked(len - 1);
802 bool ok = instance->put(scope.engine->id_length(), ScopedValue(scope, Value::fromDouble(len - 1)));
804 return scope.engine->throwTypeError();
807 return result->asReturnedValue();
851ReturnedValue ArrayPrototype::method_sort(
const FunctionObject *b,
const Value *thisObject,
const Value *argv,
int argc)
857 ScopedValue comparefn(scope, argc ? argv[0] : Value::undefinedValue());
860 if (!comparefn->isUndefined() && !comparefn->isFunctionObject())
861 return scope.engine->throwTypeError(QStringLiteral(
"The provided comparison function is not callable."));
864 ScopedObject instance(scope, thisObject->toObject(scope.engine));
869 uint len = instance->getLength();
871 if (instance->arrayData() && instance->arrayData()->length()) {
872 ArrayData::sort(scope.engine, instance, comparefn, len);
879 Value* sorted = scope.constructUndefined(scope.engine->safeForAllocLength(len));
883 for (uint index = 0; index < len; ++index) {
884 bool hasProperty =
false;
885 auto element = instance->get(index, &hasProperty);
888 sorted[written] = element;
893 std::stable_sort(sorted, sorted + written, ArrayElementLessThan(scope.engine, comparefn));
899 for (uint index = 0; index < written; ++index) {
900 instance->setIndexed(index, sorted[index], QV4::Object::DoThrowOnRejection);
908 while (written < len) {
909 if (!instance->deleteProperty(PropertyKey::fromArrayIndex(written)))
910 return scope.engine->throwTypeError();
916 return thisObject->asReturnedValue();
919ReturnedValue ArrayPrototype::method_splice(
const FunctionObject *b,
const Value *thisObject,
const Value *argv,
int argc)
922 ScopedObject instance(scope, thisObject->toObject(scope.engine));
926 qint64 len = instance->getLength();
928 double rs = (argc ? argv[0] : Value::undefinedValue()).toInteger();
931 start =
static_cast<qint64>(qMax(0., len + rs));
933 start =
static_cast<qint64>(qMin(rs,
static_cast<
double>(len)));
935 qint64 deleteCount = 0;
936 qint64 itemCount = 0;
938 deleteCount = len - start;
939 }
else if (argc > 1){
940 itemCount = argc - 2;
941 double dc = argv[1].toInteger();
942 deleteCount =
static_cast<qint64>(qMin(qMax(dc, 0.),
double(len - start)));
945 if (len + itemCount - deleteCount > UINT_MAX - 1)
946 return scope.engine->throwTypeError();
947 if (deleteCount > UINT_MAX - 1)
948 return scope.engine->throwRangeError(QString::fromLatin1(
"Array length out of range."));
950 ScopedArrayObject newArray(scope, scope.engine->newArrayObject());
951 newArray->arrayReserve(deleteCount);
952 ScopedValue v(scope);
953 for (uint i = 0; i < deleteCount; ++i) {
955 v = instance->get(start + i, &exists);
958 newArray->arrayPut(i, v);
960 newArray->setArrayLengthUnchecked(deleteCount);
963 if (itemCount < deleteCount) {
964 for (uint k = start; k < len - deleteCount; ++k) {
966 v = instance->get(k + deleteCount, &exists);
970 ok = instance->put(k + itemCount, v);
972 ok = instance->deleteProperty(PropertyKey::fromArrayIndex(k + itemCount));
974 return scope.engine->throwTypeError();
976 for (uint k = len; k > len - deleteCount + itemCount; --k) {
977 if (!instance->deleteProperty(PropertyKey::fromArrayIndex(k - 1)))
978 return scope.engine->throwTypeError();
980 }
else if (itemCount > deleteCount) {
981 uint k = len - deleteCount;
984 v = instance->get(k + deleteCount - 1, &exists);
988 ok = instance->put(k + itemCount - 1, v);
990 ok = instance->deleteProperty(PropertyKey::fromArrayIndex(k + itemCount - 1));
992 return scope.engine->throwTypeError();
997 for (uint i = 0; i < itemCount; ++i)
998 instance->put(start + i, argv[i + 2]);
1000 if (!instance->put(scope.engine->id_length(), ScopedValue(scope, Value::fromDouble(len - deleteCount + itemCount))))
1001 return scope.engine->throwTypeError();
1003 return newArray->asReturnedValue();
1006ReturnedValue ArrayPrototype::method_unshift(
const FunctionObject *b,
const Value *thisObject,
const Value *argv,
int argc)
1009 ScopedObject instance(scope, thisObject->toObject(scope.engine));
1013 instance->arrayCreate();
1014 Q_ASSERT(instance->arrayData());
1016 uint len = instance->getLength();
1018 if (!instance->protoHasArray() && !instance->arrayData()->attrs && instance->arrayData()->length() <= len &&
1019 instance->arrayData()->type != Heap::ArrayData::Custom) {
1020 instance->arrayData()->vtable()->push_front(instance, argv, argc);
1022 ScopedValue v(scope);
1023 for (uint k = len; k > 0; --k) {
1025 v = instance->get(k - 1, &exists);
1028 ok = instance->put(k + argc - 1, v);
1030 ok = instance->deleteProperty(PropertyKey::fromArrayIndex(k + argc - 1));
1032 return scope.engine->throwTypeError();
1034 for (
int i = 0, ei = argc; i < ei; ++i) {
1035 bool ok = instance->put(i, argv[i]);
1037 return scope.engine->throwTypeError();
1041 uint newLen = len + argc;
1042 if (instance->isArrayObject())
1043 instance->setArrayLengthUnchecked(newLen);
1045 if (!instance->put(scope.engine->id_length(), ScopedValue(scope, Value::fromDouble(newLen))))
1046 return scope.engine->throwTypeError();
1049 return Encode(newLen);
1091ReturnedValue ArrayPrototype::method_indexOf(
const FunctionObject *b,
const Value *thisObject,
const Value *argv,
int argc)
1094 ScopedObject instance(scope, thisObject->toObject(scope.engine));
1098 uint len = instance->getLength();
1102 ScopedValue searchValue(scope, argc ? argv[0] : Value::undefinedValue());
1106 double f = argv[1].toInteger();
1111 f = qMax(len + f, 0.);
1112 fromIndex = (uint) f;
1115 if (instance->isStringObject()) {
1116 ScopedValue v(scope);
1117 for (uint k = fromIndex; k < len; ++k) {
1119 v = instance->get(k, &exists);
1120 if (exists && RuntimeHelpers::strictEqual(v, searchValue))
1126 ScopedValue value(scope);
1128 if (ArgumentsObject::isNonStrictArgumentsObject(instance) ||
1129 (instance->arrayType() >= Heap::ArrayData::Sparse) || instance->protoHasArray()) {
1131 for (uint i = fromIndex; i < len; ++i) {
1133 value = instance->get(i, &exists);
1135 if (exists && RuntimeHelpers::strictEqual(value, searchValue))
1138 }
else if (!instance->arrayData()) {
1141 Q_ASSERT(instance->arrayType() == Heap::ArrayData::Simple);
1142 Heap::SimpleArrayData *sa = instance->d()->arrayData.cast<Heap::SimpleArrayData>();
1143 if (len > sa->values.size)
1144 len = sa->values.size;
1145 uint idx = fromIndex;
1147 value = sa->data(idx);
1149 if (RuntimeHelpers::strictEqual(value, searchValue))
1246ReturnedValue ArrayPrototype::method_fill(
const FunctionObject *b,
const Value *thisObject,
const Value *argv,
int argc)
1249 ScopedObject instance(scope, thisObject->toObject(scope.engine));
1253 const qsizetype len = instance->getLength();
1256 const qsizetype relativeStart = argc > 1 ? argv[1].toInteger() : 0;
1257 qsizetype relativeEnd = len;
1258 if (argc > 2 && !argv[2].isUndefined())
1259 relativeEnd = argv[2].toInteger();
1264 if (relativeStart < 0) {
1265 if (relativeStart > -len)
1266 k = std::max(len + relativeStart, qsizetype(0));
1268 k = std::min(relativeStart, len);
1272 if (relativeEnd < 0) {
1273 if (relativeEnd > -len)
1274 fin = std::max(len + relativeEnd, qsizetype(0));
1276 fin = std::min(relativeEnd, len);
1280 if (
sizeof(qsizetype) >
sizeof(uint) && fin > qsizetype(std::numeric_limits<uint>::max()))
1281 return scope.engine->throwRangeError(QString::fromLatin1(
"Array length out of range."));
1283 for (; k < fin; ++k)
1284 instance->setIndexed(uint(k), argv[0], QV4::Object::DoThrowOnRejection);
1286 return instance.asReturnedValue();
1289ReturnedValue ArrayPrototype::method_some(
const FunctionObject *b,
const Value *thisObject,
const Value *argv,
int argc)
1292 ScopedObject instance(scope, thisObject->toObject(scope.engine));
1296 uint len = instance->getLength();
1298 if (!argc || !argv->isFunctionObject())
1300 const FunctionObject *callback =
static_cast<
const FunctionObject *>(argv);
1302 ScopedValue that(scope, argc > 1 ? argv[1] : Value::undefinedValue());
1303 ScopedValue result(scope);
1304 Value *arguments = scope.constructUndefined(3);
1306 for (uint k = 0; k < len; ++k) {
1308 arguments[0] = instance->get(k, &exists);
1312 arguments[1] = Value::fromDouble(k);
1313 arguments[2] = instance;
1314 result = callback->call(that, arguments, 3);
1316 if (result->toBoolean())
1317 return Encode(
true);
1319 return Encode(
false);
1351ReturnedValue ArrayPrototype::method_map(
const FunctionObject *b,
const Value *thisObject,
const Value *argv,
int argc)
1354 ScopedObject instance(scope, thisObject->toObject(scope.engine));
1358 qint64 len = instance->getLength();
1360 if (!argc || !argv->isFunctionObject())
1362 const FunctionObject *callback =
static_cast<
const FunctionObject *>(argv);
1364 if (len > UINT_MAX - 1)
1365 return scope.engine->throwRangeError(QString::fromLatin1(
"Array length out of range."));
1367 ScopedArrayObject a(scope, scope.engine->newArrayObject());
1368 a->arrayReserve(len);
1369 a->setArrayLengthUnchecked(len);
1371 ScopedValue v(scope);
1372 ScopedValue mapped(scope);
1373 ScopedValue that(scope, argc > 1 ? argv[1] : Value::undefinedValue());
1374 Value *arguments = scope.constructUndefined(3);
1376 for (uint k = 0; k < len; ++k) {
1378 arguments[0] = instance->get(k, &exists);
1382 arguments[1] = Value::fromDouble(k);
1383 arguments[2] = instance;
1384 mapped = callback->call(that, arguments, 3);
1386 a->arraySet(k, mapped);
1388 return a.asReturnedValue();
1391ReturnedValue ArrayPrototype::method_filter(
const FunctionObject *b,
const Value *thisObject,
const Value *argv,
int argc)
1394 ScopedObject instance(scope, thisObject->toObject(scope.engine));
1398 uint len = instance->getLength();
1400 if (!argc || !argv->isFunctionObject())
1402 const FunctionObject *callback =
static_cast<
const FunctionObject *>(argv);
1404 ScopedArrayObject a(scope, scope.engine->newArrayObject());
1405 a->arrayReserve(len);
1407 ScopedValue selected(scope);
1408 ScopedValue that(scope, argc > 1 ? argv[1] : Value::undefinedValue());
1409 Value *arguments = scope.constructUndefined(3);
1412 for (uint k = 0; k < len; ++k) {
1414 arguments[0] = instance->get(k, &exists);
1418 arguments[1] = Value::fromDouble(k);
1419 arguments[2] = instance;
1420 selected = callback->call(that, arguments, 3);
1422 if (selected->toBoolean()) {
1423 a->arraySet(to, arguments[0]);
1427 return a.asReturnedValue();