/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtQml module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include "qv4typedarray_p.h"
#include "qv4arrayiterator_p.h"
#include "qv4arraybuffer_p.h"
#include "qv4string_p.h"
#include "qv4jscall_p.h"
#include "qv4symbol_p.h"
#include "qv4runtime_p.h"
#include <QtCore/qatomic.h>

#include <cmath>

using namespace QV4;

DEFINE_OBJECT_VTABLE(IntrinsicTypedArrayCtor);
DEFINE_OBJECT_VTABLE(IntrinsicTypedArrayPrototype);
DEFINE_OBJECT_VTABLE(TypedArrayCtor);
DEFINE_OBJECT_VTABLE(TypedArrayPrototype);
DEFINE_OBJECT_VTABLE(TypedArray);

Q_STATIC_ASSERT((int)ExecutionEngine::NTypedArrayTypes == (int)NTypedArrayTypes);

static inline int toInt32(Value v)
{
    Q_ASSERT(v.isNumber());
    if (v.isInteger())
        return v.integerValue();
    return Double::toInt32(v.doubleValue());
}

static inline double toDouble(Value v)
{
    Q_ASSERT(v.isNumber());
    if (v.isInteger())
        return v.integerValue();
    return v.doubleValue();
}

struct ClampedUInt8 {
    quint8 c;
};

template <typename T>
ReturnedValue typeToValue(T t) {
    return Encode(t);
}

template <>
ReturnedValue typeToValue(ClampedUInt8 t) {
    return Encode(t.c);
}

template <typename T>
T valueToType(Value value)
{
    Q_ASSERT(value.isNumber());
    int n = toInt32(value);
    return static_cast<T>(n);
}

template <>
ClampedUInt8 valueToType(Value value)
{
    Q_ASSERT(value.isNumber());
    if (value.isInteger())
        return { static_cast<quint8>(qBound(0, value.integerValue(), 255)) };
    Q_ASSERT(value.isDouble());
    double d = value.doubleValue();
    // ### is there a way to optimise this?
    if (d <= 0 || std::isnan(d))
        return { 0 };
    if (d >= 255)
        return { 255 };
    double f = std::floor(d);
    if (f + 0.5 < d)
        return { (quint8)(f + 1) };
    if (d < f + 0.5)
        return { (quint8)(f) };
    if (int(f) % 2)
        // odd number
        return { (quint8)(f + 1) };
    return { (quint8)(f) };
}

template <>
float valueToType(Value value)
{
    Q_ASSERT(value.isNumber());
    double d = toDouble(value);
    return static_cast<float>(d);
}

template <>
double valueToType(Value value)
{
    Q_ASSERT(value.isNumber());
    return toDouble(value);
}

template <typename T>
ReturnedValue read(const char *data) {
    return typeToValue(*reinterpret_cast<const T *>(data));
}
template <typename T>
void write(char *data, Value value)
{
    *reinterpret_cast<T *>(data) = valueToType<T>(value);
}

template <typename T>
ReturnedValue atomicAdd(char *data, Value v)
{
    T value = valueToType<T>(v);
    typename QAtomicOps<T>::Type *mem = reinterpret_cast<typename QAtomicOps<T>::Type *>(data);
    value = QAtomicOps<T>::fetchAndAddOrdered(*mem, value);
    return typeToValue(value);
}

template <typename T>
ReturnedValue atomicAnd(char *data, Value v)
{
    T value = valueToType<T>(v);
    typename QAtomicOps<T>::Type *mem = reinterpret_cast<typename QAtomicOps<T>::Type *>(data);
    value = QAtomicOps<T>::fetchAndAndOrdered(*mem, value);
    return typeToValue(value);
}

template <typename T>
ReturnedValue atomicExchange(char *data, Value v)
{
    T value = valueToType<T>(v);
    typename QAtomicOps<T>::Type *mem = reinterpret_cast<typename QAtomicOps<T>::Type *>(data);
    value = QAtomicOps<T>::fetchAndStoreOrdered(*mem, value);
    return typeToValue(value);
}

template <typename T>
ReturnedValue atomicOr(char *data, Value v)
{
    T value = valueToType<T>(v);
    typename QAtomicOps<T>::Type *mem = reinterpret_cast<typename QAtomicOps<T>::Type *>(data);
    value = QAtomicOps<T>::fetchAndOrOrdered(*mem, value);
    return typeToValue(value);
}

template <typename T>
ReturnedValue atomicSub(char *data, Value v)
{
    T value = valueToType<T>(v);
    typename QAtomicOps<T>::Type *mem = reinterpret_cast<typename QAtomicOps<T>::Type *>(data);
    value = QAtomicOps<T>::fetchAndSubOrdered(*mem, value);
    return typeToValue(value);
}

template <typename T>
ReturnedValue atomicXor(char *data, Value v)
{
    T value = valueToType<T>(v);
    typename QAtomicOps<T>::Type *mem = reinterpret_cast<typename QAtomicOps<T>::Type *>(data);
    value = QAtomicOps<T>::fetchAndXorOrdered(*mem, value);
    return typeToValue(value);
}

template <typename T>
ReturnedValue atomicCompareExchange(char *data, Value expected, Value v)
{
    T value = valueToType<T>(v);
    T exp = valueToType<T>(expected);
    typename QAtomicOps<T>::Type *mem = reinterpret_cast<typename QAtomicOps<T>::Type *>(data);
    T old;
    QAtomicOps<T>::testAndSetOrdered(*mem, exp, value, &old);
    return typeToValue(old);
}

template <typename T>
ReturnedValue atomicLoad(char *data)
{
    typename QAtomicOps<T>::Type *mem = reinterpret_cast<typename QAtomicOps<T>::Type *>(data);
    T val = QAtomicOps<T>::loadRelaxed(*mem);
    return typeToValue(val);
}

template <typename T>
ReturnedValue atomicStore(char *data, Value v)
{
    T value = valueToType<T>(v);
    typename QAtomicOps<T>::Type *mem = reinterpret_cast<typename QAtomicOps<T>::Type *>(data);
    QAtomicOps<T>::storeRelaxed(*mem, value);
    return typeToValue(value);
}


template<typename T>
constexpr TypedArrayOperations TypedArrayOperations::create(const char *name)
{
    return { sizeof(T),
             name,
             ::read<T>,
             ::write<T>,
             { nullptr, nullptr, nullptr, nullptr, nullptr, nullptr },
             nullptr,
             nullptr,
             nullptr
    };
}

template<typename T>
constexpr TypedArrayOperations TypedArrayOperations::createWithAtomics(const char *name)
{
    return { sizeof(T),
             name,
             ::read<T>,
             ::write<T>,
             { ::atomicAdd<T>, ::atomicAnd<T>, ::atomicExchange<T>, ::atomicOr<T>, ::atomicSub<T>, ::atomicXor<T> },
             ::atomicCompareExchange<T>,
             ::atomicLoad<T>,
             ::atomicStore<T>
    };
}

const TypedArrayOperations operations[NTypedArrayTypes] = {
#ifdef Q_ATOMIC_INT8_IS_SUPPORTED
    TypedArrayOperations::createWithAtomics<qint8>("Int8Array"),
    TypedArrayOperations::createWithAtomics<quint8>("Uint8Array"),
#else
    TypedArrayOperations::create<qint8>("Int8Array"),
    TypedArrayOperations::create<quint8>("Uint8Array"),
#endif
    TypedArrayOperations::createWithAtomics<qint16>("Int16Array"),
    TypedArrayOperations::createWithAtomics<quint16>("Uint16Array"),
    TypedArrayOperations::createWithAtomics<qint32>("Int32Array"),
    TypedArrayOperations::createWithAtomics<quint32>("Uint32Array"),
    TypedArrayOperations::create<ClampedUInt8>("Uint8ClampedArray"),
    TypedArrayOperations::create<float>("Float32Array"),
    TypedArrayOperations::create<double>("Float64Array")
};


void Heap::TypedArrayCtor::init(QV4::ExecutionContext *scope, TypedArray::Type t)
{
    Heap::FunctionObject::init(scope, QLatin1String(operations[t].name));
    type = t;
}

ReturnedValue TypedArrayCtor::virtualCallAsConstructor(const FunctionObject *f, const Value *argv, int argc, const Value *newTarget)
{
    Scope scope(f->engine());
    const TypedArrayCtor *that = static_cast<const TypedArrayCtor *>(f);

    auto updateProto = [=](Scope &scope, Scoped<TypedArray> &a) {
        if (newTarget->heapObject() != f->heapObject() && newTarget->isFunctionObject()) {
            const FunctionObject *nt = static_cast<const FunctionObject *>(newTarget);
            ScopedObject o(scope, nt->protoProperty());
            if (o)
                a->setPrototypeOf(o);
        }
    };

    if (!argc || !argv[0].isObject()) {
        // ECMA 6 22.2.1.1
        qint64 l = argc ? argv[0].toIndex() : 0;
        if (scope.engine->hasException)
            return Encode::undefined();
        // ### lift UINT_MAX restriction
        if (l < 0 || l > UINT_MAX)
            return scope.engine->throwRangeError(QLatin1String("Index out of range."));
        uint len = (uint)l;
        if (l != len)
            scope.engine->throwRangeError(QStringLiteral("Non integer length for typed array."));
        uint byteLength = len * operations[that->d()->type].bytesPerElement;
        Scoped<ArrayBuffer> buffer(scope, scope.engine->newArrayBuffer(byteLength));
        if (scope.engine->hasException)
            return Encode::undefined();

        Scoped<TypedArray> array(scope, TypedArray::create(scope.engine, that->d()->type));
        array->d()->buffer.set(scope.engine, buffer->d());
        array->d()->byteLength = byteLength;
        array->d()->byteOffset = 0;

        updateProto(scope, array);
        return array.asReturnedValue();
    }
    Scoped<TypedArray> typedArray(scope, argc ? argv[0] : Value::undefinedValue());
    if (!!typedArray) {
        // ECMA 6 22.2.1.2
        Scoped<ArrayBuffer> buffer(scope, typedArray->d()->buffer);
        if (!buffer || buffer->isDetachedBuffer())
            return scope.engine->throwTypeError();
        uint srcElementSize = typedArray->d()->type->bytesPerElement;
        uint destElementSize = operations[that->d()->type].bytesPerElement;
        uint byteLength = typedArray->d()->byteLength;
        uint destByteLength = byteLength*destElementSize/srcElementSize;

        Scoped<ArrayBuffer> newBuffer(scope, scope.engine->newArrayBuffer(destByteLength));
        if (scope.engine->hasException)
            return Encode::undefined();

        Scoped<TypedArray> array(scope, TypedArray::create(scope.engine, that->d()->type));
        array->d()->buffer.set(scope.engine, newBuffer->d());
        array->d()->byteLength = destByteLength;
        array->d()->byteOffset = 0;

        const char *src = buffer->d()->data->data() + typedArray->d()->byteOffset;
        char *dest = newBuffer->d()->data->data();

        // check if src and new type have the same size. In that case we can simply memcpy the data
        if (srcElementSize == destElementSize) {
            memcpy(dest, src, byteLength);
        } else {
            // not same size, we need to loop
            uint l = typedArray->length();
            TypedArrayOperations::Read read = typedArray->d()->type->read;
            TypedArrayOperations::Write write =array->d()->type->write;
            for (uint i = 0; i < l; ++i) {
                Value val;
                val.setRawValue(read(src + i*srcElementSize));
                write(dest + i*destElementSize, val);
            }
        }

        updateProto(scope, array);
        return array.asReturnedValue();
    }
    Scoped<ArrayBuffer> buffer(scope, argc ? argv[0] : Value::undefinedValue());
    if (!!buffer) {
        // ECMA 6 22.2.1.4

        double dbyteOffset = argc > 1 ? argv[1].toInteger() : 0;

        if (buffer->isDetachedBuffer())
            return scope.engine->throwTypeError();

        uint byteOffset = (uint)dbyteOffset;
        uint elementSize = operations[that->d()->type].bytesPerElement;
        if (dbyteOffset < 0 || (byteOffset % elementSize) || dbyteOffset > buffer->byteLength())
            return scope.engine->throwRangeError(QStringLiteral("new TypedArray: invalid byteOffset"));

        uint byteLength;
        if (argc < 3 || argv[2].isUndefined()) {
            byteLength = buffer->byteLength() - byteOffset;
            if (buffer->byteLength() < byteOffset || byteLength % elementSize)
                return scope.engine->throwRangeError(QStringLiteral("new TypedArray: invalid length"));
        } else {
            double l = qBound(0., argv[2].toInteger(), (double)UINT_MAX);
            if (scope.engine->hasException)
                return Encode::undefined();
            if (buffer->isDetachedBuffer())
                return scope.engine->throwTypeError();
            l *= elementSize;
            if (buffer->byteLength() - byteOffset < l)
                return scope.engine->throwRangeError(QStringLiteral("new TypedArray: invalid length"));
            byteLength = (uint)l;
        }

        Scoped<TypedArray> array(scope, TypedArray::create(scope.engine, that->d()->type));
        array->d()->buffer.set(scope.engine, buffer->d());
        array->d()->byteLength = byteLength;
        array->d()->byteOffset = byteOffset;

        updateProto(scope, array);
        return array.asReturnedValue();
    }

    // ECMA 6 22.2.1.3

    ScopedObject o(scope, argc ? argv[0] : Value::undefinedValue());
    uint l = (uint) qBound(0., ScopedValue(scope, o->get(scope.engine->id_length()))->toInteger(), (double)UINT_MAX);
    if (scope.engine->hasException)
        return scope.engine->throwTypeError();

    uint elementSize = operations[that->d()->type].bytesPerElement;
    size_t bufferSize;
    if (mul_overflow(size_t(l), size_t(elementSize), &bufferSize))
        return scope.engine->throwRangeError(QLatin1String("new TypedArray: invalid length"));
    Scoped<ArrayBuffer> newBuffer(scope, scope.engine->newArrayBuffer(bufferSize));
    if (scope.engine->hasException)
        return Encode::undefined();

    Scoped<TypedArray> array(scope, TypedArray::create(scope.engine, that->d()->type));
    array->d()->buffer.set(scope.engine, newBuffer->d());
    array->d()->byteLength = l * elementSize;
    array->d()->byteOffset = 0;

    uint idx = 0;
    char *b = newBuffer->d()->data->data();
    ScopedValue val(scope);
    while (idx < l) {
        val = o->get(idx);
        val = val->convertedToNumber();
        if (scope.engine->hasException)
            return Encode::undefined();
        array->d()->type->write(b, val);
        if (scope.engine->hasException)
            return Encode::undefined();
        ++idx;
        b += elementSize;
    }

    updateProto(scope, array);
    return array.asReturnedValue();
}

ReturnedValue TypedArrayCtor::virtualCall(const FunctionObject *f, const Value *, const Value *, int)
{
    return f->engine()->throwTypeError(QStringLiteral("calling a TypedArray constructor without new is invalid"));
}

void Heap::TypedArray::init(Type t)
{
    Object::init();
    type = operations + static_cast<int>(t);
    arrayType = static_cast<int>(t);
}

Heap::TypedArray *TypedArray::create(ExecutionEngine *e, Heap::TypedArray::Type t)
{
    Scope scope(e);
    Scoped<InternalClass> ic(scope, e->newInternalClass(staticVTable(), e->typedArrayPrototype + static_cast<int>(t)));
    return e->memoryManager->allocObject<TypedArray>(ic->d(), t);
}

ReturnedValue TypedArray::virtualGet(const Managed *m, PropertyKey id, const Value *receiver, bool *hasProperty)
{
    const bool isArrayIndex = id.isArrayIndex();
    if (!isArrayIndex && !id.isCanonicalNumericIndexString())
        return Object::virtualGet(m, id, receiver, hasProperty);

    Scope scope(static_cast<const Object *>(m)->engine());
    Scoped<TypedArray> a(scope, static_cast<const TypedArray *>(m));
    if (a->d()->buffer->isDetachedBuffer())
        return scope.engine->throwTypeError();

    if (!isArrayIndex || id.asArrayIndex() >= a->length()) {
        if (hasProperty)
            *hasProperty = false;
        return Encode::undefined();
    }

    uint bytesPerElement = a->d()->type->bytesPerElement;
    uint byteOffset = a->d()->byteOffset + id.asArrayIndex() * bytesPerElement;
    Q_ASSERT(byteOffset + bytesPerElement <= (uint)a->d()->buffer->byteLength());

    if (hasProperty)
        *hasProperty = true;
    return a->d()->type->read(a->d()->buffer->data->data() + byteOffset);
}

bool TypedArray::virtualHasProperty(const Managed *m, PropertyKey id)
{
    const bool isArrayIndex = id.isArrayIndex();
    if (!isArrayIndex && !id.isCanonicalNumericIndexString())
        return Object::virtualHasProperty(m, id);

    const TypedArray *a = static_cast<const TypedArray *>(m);
    if (a->d()->buffer->isDetachedBuffer()) {
        a->engine()->throwTypeError();
        return false;
    }
    return isArrayIndex && id.asArrayIndex() < a->length();
}

PropertyAttributes TypedArray::virtualGetOwnProperty(const Managed *m, PropertyKey id, Property *p)
{
    if (!id.isArrayIndex() && !id.isCanonicalNumericIndexString())
        return Object::virtualGetOwnProperty(m, id, p);

    bool hasProperty = false;
    ReturnedValue v = virtualGet(m, id, m, &hasProperty);
    if (p)
        p->value = v;
    return hasProperty ? Attr_NotConfigurable : PropertyAttributes();
}

bool TypedArray::virtualPut(Managed *m, PropertyKey id, const Value &value, Value *receiver)
{
    const bool isArrayIndex = id.isArrayIndex();
    if (!isArrayIndex && !id.isCanonicalNumericIndexString())
        return Object::virtualPut(m, id, value, receiver);

    ExecutionEngine *v4 = static_cast<Object *>(m)->engine();
    if (v4->hasException)
        return false;

    Scope scope(v4);
    Scoped<TypedArray> a(scope, static_cast<TypedArray *>(m));
    if (a->d()->buffer->isDetachedBuffer())
        return scope.engine->throwTypeError();

    if (!isArrayIndex)
        return false;

    const uint index = id.asArrayIndex();
    if (index >= a->length())
        return false;

    uint bytesPerElement = a->d()->type->bytesPerElement;
    uint byteOffset = a->d()->byteOffset + index * bytesPerElement;
    Q_ASSERT(byteOffset + bytesPerElement <= (uint)a->d()->buffer->byteLength());

    Value v = Value::fromReturnedValue(value.convertedToNumber());
    if (scope.hasException() || a->d()->buffer->isDetachedBuffer())
        return scope.engine->throwTypeError();
    a->d()->type->write(a->d()->buffer->data->data() + byteOffset, v);
    return true;
}

bool TypedArray::virtualDefineOwnProperty(Managed *m, PropertyKey id, const Property *p, PropertyAttributes attrs)
{
    if (!id.isArrayIndex()) {
        return !id.isCanonicalNumericIndexString()
                && Object::virtualDefineOwnProperty(m, id, p, attrs);
    }

    const uint index = id.asArrayIndex();
    TypedArray *a = static_cast<TypedArray *>(m);
    if (index >= a->length() || attrs.isAccessor())
        return false;

    if (attrs.hasConfigurable() && attrs.isConfigurable())
        return false;
    if (attrs.hasEnumerable() && !attrs.isEnumerable())
        return false;
    if (attrs.hasWritable() && !attrs.isWritable())
        return false;
    if (!p->value.isEmpty()) {
        ExecutionEngine *engine = a->engine();

        Value v = Value::fromReturnedValue(p->value.convertedToNumber());
        if (engine->hasException || a->d()->buffer->isDetachedBuffer())
            return engine->throwTypeError();
        uint bytesPerElement = a->d()->type->bytesPerElement;
        uint byteOffset = a->d()->byteOffset + index * bytesPerElement;
        Q_ASSERT(byteOffset + bytesPerElement <= (uint)a->d()->buffer->byteLength());
        a->d()->type->write(a->d()->buffer->data->data() + byteOffset, v);
    }
    return true;
}

struct TypedArrayOwnPropertyKeyIterator : ObjectOwnPropertyKeyIterator
{
    ~TypedArrayOwnPropertyKeyIterator() override = default;
    PropertyKey next(const Object *o, Property *pd = nullptr, PropertyAttributes *attrs = nullptr) override;

};

PropertyKey TypedArrayOwnPropertyKeyIterator::next(const Object *o, Property *pd, PropertyAttributes *attrs)
{
    const TypedArray *a = static_cast<const TypedArray *>(o);
    if (arrayIndex < a->length()) {
        if (attrs)
            *attrs = Attr_NotConfigurable;
        PropertyKey id = PropertyKey::fromArrayIndex(arrayIndex);
        if (pd) {
            bool hasProperty = false;
            pd->value = TypedArray::virtualGet(a, id, a, &hasProperty);
        }
        ++arrayIndex;
        return id;
    }

    arrayIndex = UINT_MAX;
    return ObjectOwnPropertyKeyIterator::next(o, pd, attrs);
}

OwnPropertyKeyIterator *TypedArray::virtualOwnPropertyKeys(const Object *m, Value *target)
{
    *target = *m;
    return new TypedArrayOwnPropertyKeyIterator();
}

void TypedArrayPrototype::init(ExecutionEngine *engine, TypedArrayCtor *ctor)
{
    Scope scope(engine);
    ScopedObject o(scope);

    ctor->defineReadonlyConfigurableProperty(engine->id_length(), Value::fromInt32(3));
    ctor->defineReadonlyProperty(engine->id_prototype(), *this);
    ctor->defineReadonlyProperty(QStringLiteral("BYTES_PER_ELEMENT"), Value::fromInt32(operations[static_cast<int>(ctor->d()->type)].bytesPerElement));
    ctor->setPrototypeOf(engine->intrinsicTypedArrayCtor());

    setPrototypeOf(engine->intrinsicTypedArrayPrototype());
    defineDefaultProperty(engine->id_constructor(), (o = ctor));
    defineReadonlyProperty(QStringLiteral("BYTES_PER_ELEMENT"), Value::fromInt32(operations[static_cast<int>(ctor->d()->type)].bytesPerElement));
}

ReturnedValue IntrinsicTypedArrayPrototype::method_get_buffer(const FunctionObject *b, const Value *thisObject, const Value *, int)
{
    ExecutionEngine *v4 = b->engine();
    const TypedArray *v = thisObject->as<TypedArray>();
    if (!v)
        return v4->throwTypeError();

    return v->d()->buffer->asReturnedValue();
}

ReturnedValue IntrinsicTypedArrayPrototype::method_get_byteLength(const FunctionObject *b, const Value *thisObject, const Value *, int)
{
    ExecutionEngine *v4 = b->engine();
    const TypedArray *v = thisObject->as<TypedArray>();
    if (!v)
        return v4->throwTypeError();

    if (v->d()->buffer->isDetachedBuffer())
        return Encode(0);

    return Encode(v->d()->byteLength);
}

ReturnedValue IntrinsicTypedArrayPrototype::method_get_byteOffset(const FunctionObject *b, const Value *thisObject, const Value *, int)
{
    ExecutionEngine *v4 = b->engine();
    const TypedArray *v = thisObject->as<TypedArray>();
    if (!v)
        return v4->throwTypeError();

    if (v->d()->buffer->isDetachedBuffer())
        return Encode(0);

    return Encode(v->d()->byteOffset);
}

ReturnedValue IntrinsicTypedArrayPrototype::method_get_length(const FunctionObject *b, const Value *thisObject, const Value *, int)
{
    ExecutionEngine *v4 = b->engine();
    const TypedArray *v = thisObject->as<TypedArray>();
    if (!v)
        return v4->throwTypeError();

    if (v->d()->buffer->isDetachedBuffer())
        return Encode(0);

    return Encode(v->d()->byteLength/v->d()->type->bytesPerElement);
}

ReturnedValue IntrinsicTypedArrayPrototype::method_copyWithin(const FunctionObject *f, const Value *thisObject, const Value *argv, int argc)
{
    Scope scope(f);
    Scoped<TypedArray> O(scope, thisObject);
    if (!O || O->d()->buffer->isDetachedBuffer())
        return scope.engine->throwTypeError();

    if (!argc)
        return O->asReturnedValue();

    qint64 len = static_cast<uint>(O->length());

    qint64 to = static_cast<qint64>(argv[0].toInteger());
    if (to < 0)
        to = qMax(len + to, 0ll);
    else
        to = qMin(to, len);

    qint64 from = (argc > 1) ? static_cast<qint64>(argv[1].toInteger()) : 0ll;
    if (from < 0)
        from = qMax(len + from, 0ll);
    else
        from = qMin(from, len);

    double fend = argv[2].toInteger();
    if (fend > len)
        fend = len;
    qint64 end = (argc > 2 && !argv[2].isUndefined()) ? static_cast<qint64>(fend) : len;
    if (end < 0)
        end = qMax(len + end, 0ll);
    else
        end = qMin(end, len);

    qint64 count = qMin(end - from, len - to);

    if (count <= 0)
        return O->asReturnedValue();

    if (O->d()->buffer->isDetachedBuffer())
        return scope.engine->throwTypeError();

    if (from != to) {
        int elementSize = O->d()->type->bytesPerElement;
        char *data = O->d()->buffer->data->data() + O->d()->byteOffset;
        memmove(data + to*elementSize, data + from*elementSize, count*elementSize);
    }

    return O->asReturnedValue();
}

ReturnedValue IntrinsicTypedArrayPrototype::method_entries(const FunctionObject *b, const Value *thisObject, const Value *, int)
{
    Scope scope(b);
    Scoped<TypedArray> v(scope, thisObject);
    if (!v || v->d()->buffer->isDetachedBuffer())
        return scope.engine->throwTypeError();

    Scoped<ArrayIteratorObject> ao(scope, scope.engine->newArrayIteratorObject(v));
    ao->d()->iterationKind = IteratorKind::KeyValueIteratorKind;
    return ao->asReturnedValue();
}

ReturnedValue IntrinsicTypedArrayPrototype::method_every(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc)
{
    Scope scope(b);
    Scoped<TypedArray> v(scope, thisObject);
    if (!v || v->d()->buffer->isDetachedBuffer())
        return scope.engine->throwTypeError();

    uint len = v->length();

    if (!argc || !argv->isFunctionObject())
        THROW_TYPE_ERROR();
    const FunctionObject *callback = static_cast<const FunctionObject *>(argv);

    ScopedValue that(scope, argc > 1 ? argv[1] : Value::undefinedValue());
    ScopedValue r(scope);
    Value *arguments = scope.alloc(3);

    const char *data = v->d()->buffer->data->data();
    uint bytesPerElement = v->d()->type->bytesPerElement;
    uint byteOffset = v->d()->byteOffset;

    bool ok = true;
    for (uint k = 0; ok && k < len; ++k) {
        if (v->d()->buffer->isDetachedBuffer())
            return scope.engine->throwTypeError();

        arguments[0] = v->d()->type->read(data + byteOffset + k * bytesPerElement);

        arguments[1] = Value::fromDouble(k);
        arguments[2] = v;
        r = callback->call(that, arguments, 3);
        CHECK_EXCEPTION();
        ok = r->toBoolean();
    }
    return Encode(ok);
}

ReturnedValue IntrinsicTypedArrayPrototype::method_fill(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc)
{
    Scope scope(b);
    Scoped<TypedArray> v(scope, thisObject);
    if (!v || v->d()->buffer->isDetachedBuffer())
        return scope.engine->throwTypeError();

    uint len = v->length();
    double dlen = len;
    double relativeStart = argc > 1 ? argv[1].toInteger() : 0.;
    double relativeEnd = len;
    if (argc > 2 && !argv[2].isUndefined())
        relativeEnd = argv[2].toInteger();

    uint k = 0;
    uint fin = 0;

    if (relativeStart < 0) {
        k = static_cast<uint>(std::max(len+relativeStart, 0.));
    } else {
        k = static_cast<uint>(std::min(relativeStart, dlen));
    }

    if (relativeEnd < 0) {
        fin = static_cast<uint>(std::max(len + relativeEnd, 0.));
    } else {
        fin = static_cast<uint>(std::min(relativeEnd, dlen));
    }

    double val = argc ? argv[0].toNumber() : std::numeric_limits<double>::quiet_NaN();
    Value value = Value::fromDouble(val);
    if (scope.hasException() || v->d()->buffer->isDetachedBuffer())
        return scope.engine->throwTypeError();

    char *data = v->d()->buffer->data->data();
    uint bytesPerElement = v->d()->type->bytesPerElement;
    uint byteOffset = v->d()->byteOffset;

    while (k < fin) {
        v->d()->type->write(data + byteOffset + k * bytesPerElement, value);
        k++;
    }

    return v.asReturnedValue();
}

static TypedArray *typedArraySpeciesCreate(Scope &scope, const TypedArray *instance, uint len)
{
    const FunctionObject *constructor = instance->speciesConstructor(scope, scope.engine->typedArrayCtors + instance->d()->arrayType);
    if (!constructor) {
        scope.engine->throwTypeError();
        return nullptr;
    }

    Value *arguments = scope.alloc(1);
    arguments[0] = Encode(len);
    Scoped<TypedArray> a(scope, constructor->callAsConstructor(arguments, 1));
    if (!a || a->d()->buffer->isDetachedBuffer() || a->length() < len) {
        scope.engine->throwTypeError();
        return nullptr;
    }
    return a;
}

ReturnedValue IntrinsicTypedArrayPrototype::method_filter(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc)
{
    Scope scope(b);
    Scoped<TypedArray> instance(scope, thisObject);
    if (!instance || instance->d()->buffer->isDetachedBuffer())
        return scope.engine->throwTypeError();

    uint len = instance->length();

    if (!argc || !argv->isFunctionObject())
        THROW_TYPE_ERROR();
    const FunctionObject *callback = static_cast<const FunctionObject *>(argv);

    ScopedValue selected(scope);
    ScopedValue that(scope, argc > 1 ? argv[1] : Value::undefinedValue());
    Value *arguments = scope.alloc(3);
    Value *list = arguments;

    uint to = 0;
    for (uint k = 0; k < len; ++k) {
        if (instance->d()->buffer->isDetachedBuffer())
            return scope.engine->throwTypeError();
        bool exists;
        arguments[0] = instance->get(k, &exists);
        if (!exists)
            continue;

        arguments[1] = Value::fromDouble(k);
        arguments[2] = instance;
        selected = callback->call(that, arguments, 3);
        CHECK_EXCEPTION();
        if (selected->toBoolean()) {
            ++arguments;
            scope.alloc(1);
            ++to;
        }
    }

    TypedArray *a = typedArraySpeciesCreate(scope, instance, to);
    if (!a)
        return Encode::undefined();

    for (uint i = 0; i < to; ++i)
        a->put(i, list[i]);

    return a->asReturnedValue();
}

ReturnedValue IntrinsicTypedArrayPrototype::method_find(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc)
{
    Scope scope(b);
    Scoped<TypedArray> v(scope, thisObject);
    if (!v || v->d()->buffer->isDetachedBuffer())
        return scope.engine->throwTypeError();

    uint len = v->length();

    if (!argc || !argv[0].isFunctionObject())
        THROW_TYPE_ERROR();
    const FunctionObject *callback = static_cast<const FunctionObject *>(argv);

    ScopedValue result(scope);
    Value *arguments = scope.alloc(3);

    ScopedValue that(scope, argc > 1 ? argv[1] : Value::undefinedValue());

    for (uint k = 0; k < len; ++k) {
        if (v->d()->buffer->isDetachedBuffer())
            return scope.engine->throwTypeError();
        arguments[0] = v->get(k);
        CHECK_EXCEPTION();

        arguments[1] = Value::fromDouble(k);
        arguments[2] = v;
        result = callback->call(that, arguments, 3);

        CHECK_EXCEPTION();
        if (result->toBoolean())
            return arguments[0].asReturnedValue();
    }

    RETURN_UNDEFINED();
}

ReturnedValue IntrinsicTypedArrayPrototype::method_findIndex(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc)
{
    Scope scope(b);
    Scoped<TypedArray> v(scope, thisObject);
    if (!v || v->d()->buffer->isDetachedBuffer())
        return scope.engine->throwTypeError();

    uint len = v->length();

    if (!argc || !argv[0].isFunctionObject())
        THROW_TYPE_ERROR();
    const FunctionObject *callback = static_cast<const FunctionObject *>(argv);

    ScopedValue result(scope);
    Value *arguments = scope.alloc(3);

    ScopedValue that(scope, argc > 1 ? argv[1] : Value::undefinedValue());

    for (uint k = 0; k < len; ++k) {
        if (v->d()->buffer->isDetachedBuffer())
            return scope.engine->throwTypeError();
        arguments[0] = v->get(k);
        CHECK_EXCEPTION();

        arguments[1] = Value::fromDouble(k);
        arguments[2] = v;
        result = callback->call(that, arguments, 3);

        CHECK_EXCEPTION();
        if (result->toBoolean())
            return Encode(k);
    }

    return Encode(-1);
}

ReturnedValue IntrinsicTypedArrayPrototype::method_forEach(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc)
{
    Scope scope(b);
    Scoped<TypedArray> v(scope, thisObject);
    if (!v || v->d()->buffer->isDetachedBuffer())
        return scope.engine->throwTypeError();

    uint len = v->length();

    if (!argc || !argv->isFunctionObject())
        THROW_TYPE_ERROR();
    const FunctionObject *callback = static_cast<const FunctionObject *>(argv);

    ScopedValue that(scope, argc > 1 ? argv[1] : Value::undefinedValue());
    Value *arguments = scope.alloc(3);

    for (uint k = 0; k < len; ++k) {
        if (v->d()->buffer->isDetachedBuffer())
            return scope.engine->throwTypeError();
        bool exists;
        arguments[0] = v->get(k, &exists);
        if (!exists)
            continue;

        arguments[1] = Value::fromDouble(k);
        arguments[2] = v;
        callback->call(that, arguments, 3);
    }
    RETURN_UNDEFINED();
}


ReturnedValue IntrinsicTypedArrayPrototype::method_includes(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc)
{
    Scope scope(b);
    Scoped<TypedArray> v(scope, thisObject);
    if (!v || v->d()->buffer->isDetachedBuffer())
        return scope.engine->throwTypeError();

    uint len = v->length();
    if (len == 0) {
        return Encode(false);
    }

    double n = 0;
    if (argc > 1 && !argv[1].isUndefined()) {
        n = argv[1].toInteger();
    }

    double k = 0;
    if (n >= 0) {
        k = n;
    } else {
        k = len + n;
        if (k < 0) {
            k = 0;
        }
    }

    while (k < len) {
        ScopedValue val(scope, v->get(k));
        if (val->sameValueZero(argv[0])) {
            return Encode(true);
        }
        k++;
    }

    return Encode(false);
}

ReturnedValue IntrinsicTypedArrayPrototype::method_indexOf(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc)
{
    Scope scope(b);
    Scoped<TypedArray> v(scope, thisObject);
    if (!v || v->d()->buffer->isDetachedBuffer())
        return scope.engine->throwTypeError();

    uint len = v->length();
    if (!len)
        return Encode(-1);

    ScopedValue searchValue(scope, argc ? argv[0] : Value::undefinedValue());
    uint fromIndex = 0;

    if (argc >= 2) {
        double f = argv[1].toInteger();
        CHECK_EXCEPTION();
        if (f >= len)
            return Encode(-1);
        if (f < 0)
            f = qMax(len + f, 0.);
        fromIndex = (uint) f;
    }

    if (v->isStringObject()) {
        ScopedValue value(scope);
        for (uint k = fromIndex; k < len; ++k) {
            bool exists;
            value = v->get(k, &exists);
            if (exists && RuntimeHelpers::strictEqual(value, searchValue))
                return Encode(k);
        }
        return Encode(-1);
    }

    ScopedValue value(scope);

    for (uint i = fromIndex; i < len; ++i) {
        bool exists;
        value = v->get(i, &exists);
        CHECK_EXCEPTION();
        if (exists && RuntimeHelpers::strictEqual(value, searchValue))
            return Encode(i);
    }
    return Encode(-1);
}

ReturnedValue IntrinsicTypedArrayPrototype::method_join(
        const FunctionObject *functionObject, const Value *thisObject, const Value *argv, int argc)
{
    Scope scope(functionObject);
    Scoped<TypedArray> typedArray(scope, thisObject);
    if (!typedArray || typedArray->d()->buffer->isDetachedBuffer())
        return scope.engine->throwTypeError();

    // We cannot optimize the resolution of the argument away if length is 0.
    // It may have side effects.
    ScopedValue argument(scope, argc ? argv[0] : Value::undefinedValue());
    const QString separator = argument->isUndefined()
            ? QStringLiteral(",")
            : argument->toQString();

    const quint32 length = typedArray->length();
    if (!length)
        return Encode(scope.engine->newString());

    QString result;

    ScopedString name(scope, scope.engine->newString(QStringLiteral("0")));
    ScopedValue value(scope, typedArray->get(name));
    if (!value->isNullOrUndefined())
        result = value->toQString();

    for (quint32 i = 1; i < length; ++i) {
        result += separator;

        name = Value::fromDouble(i).toString(scope.engine);
        value = typedArray->get(name);
        CHECK_EXCEPTION();

        if (!value->isNullOrUndefined())
            result += value->toQString();
    }

    return Encode(scope.engine->newString(result));
}

ReturnedValue IntrinsicTypedArrayPrototype::method_keys(const FunctionObject *b, const Value *thisObject, const Value *, int)
{
    Scope scope(b);
    Scoped<TypedArray> v(scope, thisObject);
    if (!v || v->d()->buffer->isDetachedBuffer())
        return scope.engine->throwTypeError();

    Scoped<ArrayIteratorObject> ao(scope, scope.engine->newArrayIteratorObject(v));
    ao->d()->iterationKind = IteratorKind::KeyIteratorKind;
    return ao->asReturnedValue();
}


ReturnedValue IntrinsicTypedArrayPrototype::method_lastIndexOf(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc)
{
    Scope scope(b);
    Scoped<TypedArray> instance(scope, thisObject);
    if (!instance || instance->d()->buffer->isDetachedBuffer())
        return scope.engine->throwTypeError();

    uint len = instance->length();
    if (!len)
        return Encode(-1);

    ScopedValue searchValue(scope);
    uint fromIndex = len;

    if (argc >= 1)
        searchValue = argv[0];
    else
        searchValue = Value::undefinedValue();

    if (argc >= 2) {
        double f = argv[1].toInteger();
        CHECK_EXCEPTION();
        if (f > 0)
            f = qMin(f, (double)(len - 1));
        else if (f < 0) {
            f = len + f;
            if (f < 0)
                return Encode(-1);
        }
        fromIndex = (uint) f + 1;
    }

    ScopedValue value(scope);
    for (uint k = fromIndex; k > 0;) {
        --k;
        bool exists;
        value = instance->get(k, &exists);
        if (exists && RuntimeHelpers::strictEqual(value, searchValue))
            return Encode(k);
    }
    return Encode(-1);
}

ReturnedValue IntrinsicTypedArrayPrototype::method_map(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc)
{
    Scope scope(b);
    Scoped<TypedArray> instance(scope, thisObject);
    if (!instance || instance->d()->buffer->isDetachedBuffer())
        return scope.engine->throwTypeError();

    uint len = instance->length();

    if (!argc || !argv->isFunctionObject())
        THROW_TYPE_ERROR();
    const FunctionObject *callback = static_cast<const FunctionObject *>(argv);

    TypedArray *a = typedArraySpeciesCreate(scope, instance, len);
    if (!a)
        return Encode::undefined();

    ScopedValue v(scope);
    ScopedValue mapped(scope);
    ScopedValue that(scope, argc > 1 ? argv[1] : Value::undefinedValue());
    Value *arguments = scope.alloc(3);

    for (uint k = 0; k < len; ++k) {
        if (instance->d()->buffer->isDetachedBuffer())
            return scope.engine->throwTypeError();
        arguments[0] = instance->get(k);

        arguments[1] = Value::fromDouble(k);
        arguments[2] = instance;
        mapped = callback->call(that, arguments, 3);
        CHECK_EXCEPTION();
        a->put(k, mapped);
    }
    return a->asReturnedValue();
}

ReturnedValue IntrinsicTypedArrayPrototype::method_reduce(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc)
{
    Scope scope(b);
    Scoped<TypedArray> instance(scope, thisObject);
    if (!instance || instance->d()->buffer->isDetachedBuffer())
        return scope.engine->throwTypeError();

    uint len = instance->length();

    if (!argc || !argv->isFunctionObject())
        THROW_TYPE_ERROR();
    const FunctionObject *callback = static_cast<const FunctionObject *>(argv);

    uint k = 0;
    ScopedValue acc(scope);
    ScopedValue v(scope);

    if (argc > 1) {
        acc = argv[1];
    } else {
        bool kPresent = false;
        while (k < len && !kPresent) {
            v = instance->get(k, &kPresent);
            if (kPresent)
                acc = v;
            ++k;
        }
        if (!kPresent)
            THROW_TYPE_ERROR();
    }

    Value *arguments = scope.alloc(4);

    while (k < len) {
        if (instance->d()->buffer->isDetachedBuffer())
            return scope.engine->throwTypeError();
        bool kPresent;
        v = instance->get(k, &kPresent);
        if (kPresent) {
            arguments[0] = acc;
            arguments[1] = v;
            arguments[2] = Value::fromDouble(k);
            arguments[3] = instance;
            acc = callback->call(nullptr, arguments, 4);
            CHECK_EXCEPTION();
        }
        ++k;
    }
    return acc->asReturnedValue();
}

ReturnedValue IntrinsicTypedArrayPrototype::method_reduceRight(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc)
{
    Scope scope(b);
    Scoped<TypedArray> instance(scope, thisObject);
    if (!instance || instance->d()->buffer->isDetachedBuffer())
        return scope.engine->throwTypeError();

    uint len = instance->length();

    if (!argc || !argv->isFunctionObject())
        THROW_TYPE_ERROR();
    const FunctionObject *callback = static_cast<const FunctionObject *>(argv);

    if (len == 0) {
        if (argc == 1)
            THROW_TYPE_ERROR();
        return argv[1].asReturnedValue();
    }

    uint k = len;
    ScopedValue acc(scope);
    ScopedValue v(scope);
    if (argc > 1) {
        acc = argv[1];
    } else {
        bool kPresent = false;
        while (k > 0 && !kPresent) {
            v = instance->get(k - 1, &kPresent);
            if (kPresent)
                acc = v;
            --k;
        }
        if (!kPresent)
            THROW_TYPE_ERROR();
    }

    Value *arguments = scope.alloc(4);

    while (k > 0) {
        if (instance->d()->buffer->isDetachedBuffer())
            return scope.engine->throwTypeError();
        bool kPresent;
        v = instance->get(k - 1, &kPresent);
        if (kPresent) {
            arguments[0] = acc;
            arguments[1] = v;
            arguments[2] = Value::fromDouble(k - 1);
            arguments[3] = instance;
            acc = callback->call(nullptr, arguments, 4);
            CHECK_EXCEPTION();
        }
        --k;
    }
    return acc->asReturnedValue();
}

ReturnedValue IntrinsicTypedArrayPrototype::method_reverse(const FunctionObject *b, const Value *thisObject, const Value *, int)
{
    Scope scope(b);
    Scoped<TypedArray> instance(scope, thisObject);
    if (!instance || instance->d()->buffer->isDetachedBuffer())
        return scope.engine->throwTypeError();

    uint length = instance->length();

    int lo = 0, hi = length - 1;

    ScopedValue lval(scope);
    ScopedValue hval(scope);
    for (; lo < hi; ++lo, --hi) {
        bool loExists, hiExists;
        lval = instance->get(lo, &loExists);
        hval = instance->get(hi, &hiExists);
        Q_ASSERT(hiExists && loExists);
        bool ok;
        ok = instance->put(lo, hval);
        Q_ASSERT(ok);
        ok = instance->put(hi, lval);
        Q_ASSERT(ok);
    }
    return instance->asReturnedValue();
}

ReturnedValue IntrinsicTypedArrayPrototype::method_some(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc)
{
    Scope scope(b);
    Scoped<TypedArray> instance(scope, thisObject);
    if (!instance || instance->d()->buffer->isDetachedBuffer())
        return scope.engine->throwTypeError();

    uint len = instance->length();

    if (!argc || !argv->isFunctionObject())
        THROW_TYPE_ERROR();
    const FunctionObject *callback = static_cast<const FunctionObject *>(argv);

    ScopedValue that(scope, argc > 1 ? argv[1] : Value::undefinedValue());
    ScopedValue result(scope);
    Value *arguments = scope.alloc(3);

    for (uint k = 0; k < len; ++k) {
        if (instance->d()->buffer->isDetachedBuffer())
            return scope.engine->throwTypeError();
        bool exists;
        arguments[0] = instance->get(k, &exists);
        if (!exists)
            continue;

        arguments[1] = Value::fromDouble(k);
        arguments[2] = instance;
        result = callback->call(that, arguments, 3);
        CHECK_EXCEPTION();
        if (result->toBoolean())
            return Encode(true);
    }
    return Encode(false);
}


ReturnedValue IntrinsicTypedArrayPrototype::method_values(const FunctionObject *b, const Value *thisObject, const Value *, int)
{
    Scope scope(b);
    Scoped<TypedArray> v(scope, thisObject);
    if (!v || v->d()->buffer->isDetachedBuffer())
        return scope.engine->throwTypeError();

    Scoped<ArrayIteratorObject> ao(scope, scope.engine->newArrayIteratorObject(v));
    ao->d()->iterationKind = IteratorKind::ValueIteratorKind;
    return ao->asReturnedValue();
}

ReturnedValue IntrinsicTypedArrayPrototype::method_set(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc)
{
    Scope scope(b);
    Scoped<TypedArray> a(scope, *thisObject);
    if (!a)
        return scope.engine->throwTypeError();
    Scoped<ArrayBuffer> buffer(scope, a->d()->buffer);

    double doffset = argc >= 2 ? argv[1].toInteger() : 0;
    if (scope.engine->hasException)
        RETURN_UNDEFINED();
    if (!buffer || buffer->isDetachedBuffer())
        return scope.engine->throwTypeError();

    if (doffset < 0 || doffset >= UINT_MAX)
        RETURN_RESULT(scope.engine->throwRangeError(QStringLiteral("TypedArray.set: out of range")));
    uint offset = (uint)doffset;
    uint elementSize = a->d()->type->bytesPerElement;

    Scoped<TypedArray> srcTypedArray(scope, argv[0]);
    if (!srcTypedArray) {
        // src is a regular object
        ScopedObject o(scope, argv[0].toObject(scope.engine));
        if (scope.engine->hasException || !o)
            return scope.engine->throwTypeError();

        double len = ScopedValue(scope, o->get(scope.engine->id_length()))->toNumber();
        uint l = (uint)len;
        if (scope.engine->hasException || l != len)
            return scope.engine->throwTypeError();

        const uint aLength = a->length();
        if (offset > aLength || l > aLength - offset)
            RETURN_RESULT(scope.engine->throwRangeError(QStringLiteral("TypedArray.set: out of range")));

        uint idx = 0;
        if (buffer->isDetachedBuffer())
            return scope.engine->throwTypeError();
        char *b = buffer->d()->data->data() + a->d()->byteOffset + offset*elementSize;
        ScopedValue val(scope);
        while (idx < l) {
            val = o->get(idx);
            if (scope.hasException())
                return Encode::undefined();
            val = val->convertedToNumber();
            if (scope.hasException() || buffer->isDetachedBuffer())
                return scope.engine->throwTypeError();
            a->d()->type->write(b, val);
            if (scope.engine->hasException)
                RETURN_UNDEFINED();
            ++idx;
            b += elementSize;
        }
        RETURN_UNDEFINED();
    }

    // src is a typed array
    Scoped<ArrayBuffer> srcBuffer(scope, srcTypedArray->d()->buffer);
    if (!srcBuffer || srcBuffer->isDetachedBuffer())
        return scope.engine->throwTypeError();

    uint l = srcTypedArray->length();

    const uint aLength = a->length();
    if (offset > aLength || l > aLength - offset)
        RETURN_RESULT(scope.engine->throwRangeError(QStringLiteral("TypedArray.set: out of range")));

    char *dest = buffer->d()->data->data() + a->d()->byteOffset + offset*elementSize;
    const char *src = srcBuffer->d()->data->data() + srcTypedArray->d()->byteOffset;
    if (srcTypedArray->d()->type == a->d()->type) {
        // same type of typed arrays, use memmove (as srcbuffer and buffer could be the same)
        memmove(dest, src, srcTypedArray->d()->byteLength);
        RETURN_UNDEFINED();
    }

    char *srcCopy = nullptr;
    if (buffer->d() == srcBuffer->d()) {
        // same buffer, need to take a temporary copy, to not run into problems
        srcCopy = new char[srcTypedArray->d()->byteLength];
        memcpy(srcCopy, src, srcTypedArray->d()->byteLength);
        src = srcCopy;
    }

    // typed arrays of different kind, need to manually loop
    uint srcElementSize = srcTypedArray->d()->type->bytesPerElement;
    TypedArrayOperations::Read read = srcTypedArray->d()->type->read;
    TypedArrayOperations::Write write = a->d()->type->write;
    for (uint i = 0; i < l; ++i) {
        Value val;
        val.setRawValue(read(src + i*srcElementSize));
        write(dest + i*elementSize, val);
    }

    if (srcCopy)
        delete [] srcCopy;

    RETURN_UNDEFINED();
}

ReturnedValue IntrinsicTypedArrayPrototype::method_slice(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc)
{
    Scope scope(b);
    Scoped<TypedArray> instance(scope, thisObject);
    if (!instance || instance->d()->buffer->isDetachedBuffer())
        return scope.engine->throwTypeError();

    uint len = instance->length();

    double s = (argc ? argv[0] : Value::undefinedValue()).toInteger();
    uint start;
    if (s < 0)
        start = (uint)qMax(len + s, 0.);
    else if (s > len)
        start = len;
    else
        start = (uint) s;
    uint end = len;
    if (argc > 1 && !argv[1].isUndefined()) {
        double e = argv[1].toInteger();
        if (e < 0)
            end = (uint)qMax(len + e, 0.);
        else if (e > len)
            end = len;
        else
            end = (uint) e;
    }
    uint count = start > end ? 0 : end - start;

    TypedArray *a = typedArraySpeciesCreate(scope, instance, count);
    if (!a)
        return Encode::undefined();

    ScopedValue v(scope);
    uint n = 0;
    for (uint i = start; i < end; ++i) {
        if (instance->d()->buffer->isDetachedBuffer())
            return scope.engine->throwTypeError();
        v = instance->get(i);
        if (a->d()->buffer->isDetachedBuffer())
            return scope.engine->throwTypeError();
        a->put(n, v);
        ++n;
    }
    return a->asReturnedValue();
}

ReturnedValue IntrinsicTypedArrayPrototype::method_subarray(const FunctionObject *builtin, const Value *thisObject, const Value *argv, int argc)
{
    Scope scope(builtin);
    Scoped<TypedArray> a(scope, *thisObject);

    if (!a)
        return scope.engine->throwTypeError();

    Scoped<ArrayBuffer> buffer(scope, a->d()->buffer);
    Q_ASSERT(buffer);

    int len = a->length();
    double b = argc > 0 ? argv[0].toInteger() : 0;
    if (b < 0)
        b = len + b;
    uint begin = (uint)qBound(0., b, (double)len);

    double e = argc < 2 || argv[1].isUndefined() ? len : argv[1].toInteger();
    if (e < 0)
        e = len + e;
    uint end = (uint)qBound(0., e, (double)len);
    if (end < begin)
        end = begin;

    if (scope.engine->hasException)
        RETURN_UNDEFINED();

    int newLen = end - begin;

    ScopedFunctionObject constructor(scope, a->speciesConstructor(scope, scope.engine->typedArrayCtors + a->d()->arrayType));
    if (!constructor)
        return scope.engine->throwTypeError();

    Value *arguments = scope.alloc(3);
    arguments[0] = buffer;
    arguments[1] = Encode(a->d()->byteOffset + begin*a->d()->type->bytesPerElement);
    arguments[2] = Encode(newLen);
    a = constructor->callAsConstructor(arguments, 3);
    if (!a || a->d()->buffer->isDetachedBuffer())
        return scope.engine->throwTypeError();
    return a->asReturnedValue();
}

ReturnedValue IntrinsicTypedArrayPrototype::method_toLocaleString(const FunctionObject *b, const Value *thisObject, const Value *, int)
{
    Scope scope(b);
    Scoped<TypedArray> instance(scope, thisObject);
    if (!instance || instance->d()->buffer->isDetachedBuffer())
        return scope.engine->throwTypeError();

    uint len = instance->length();
    const QString separator = QStringLiteral(",");

    QString R;

    ScopedValue v(scope);
    ScopedString s(scope);

    for (uint k = 0; k < len; ++k) {
        if (instance->d()->buffer->isDetachedBuffer())
            return scope.engine->throwTypeError();
        if (k)
            R += separator;

        v = instance->get(k);
        v = Runtime::CallElement::call(scope.engine, v, *scope.engine->id_toLocaleString(), nullptr, 0);
        s = v->toString(scope.engine);
        if (scope.hasException())
            return Encode::undefined();

        R += s->toQString();
    }
    return scope.engine->newString(R)->asReturnedValue();
}

ReturnedValue IntrinsicTypedArrayPrototype::method_get_toStringTag(const FunctionObject *, const Value *thisObject, const Value *, int)
{
    const TypedArray *a = thisObject->as<TypedArray>();
    if (!a)
        return Encode::undefined();

    return a->engine()->newString(QString::fromLatin1(a->d()->type->name))->asReturnedValue();
}

static bool validateTypedArray(const Object *o)
{
    const TypedArray *a = o->as<TypedArray>();
    if (!a)
        return false;
    if (a->d()->buffer->isDetachedBuffer())
        return false;
    return true;
}

ReturnedValue IntrinsicTypedArrayCtor::method_of(const FunctionObject *f, const Value *thisObject, const Value *argv, int argc)
{
    Scope scope(f);
    int len = argc;
    const Value *items = argv;
    const FunctionObject *C = thisObject->as<FunctionObject>();
    if (!C || !C->isConstructor())
        return scope.engine->throwTypeError();

    Value lenValue = Value::fromInt32(len);
    ScopedObject newObj(scope, C->callAsConstructor(&lenValue, 1));
    if (scope.hasException())
        return Encode::undefined();
    if (!::validateTypedArray(newObj))
        return scope.engine->throwTypeError();
    TypedArray *a = newObj->as<TypedArray>();
    Q_ASSERT(a);
    if (a->length() < static_cast<uint>(len))
        return scope.engine->throwTypeError();

    for (int k = 0; k < len; ++k) {
        newObj->put(PropertyKey::fromArrayIndex(k), items[k]);
    }
    return newObj->asReturnedValue();
}

ReturnedValue IntrinsicTypedArrayCtor::method_from(const FunctionObject *f, const Value *thisObject, const Value *argv, int argc)
{
    Scope scope(f);
    ScopedObject itemsObject(scope, argv[0]);
    bool usingIterator = false;

    ScopedFunctionObject mapfn(scope, Value::undefinedValue());
    Value *mapArguments = nullptr;
    if (argc > 1) {
        mapfn = ScopedFunctionObject(scope, argv[1]);
        if (!mapfn)
            return scope.engine->throwTypeError(QString::fromLatin1("%1 is not a function").arg(argv[1].toQStringNoThrow()));
        mapArguments = scope.alloc(2);
    }

    // Iterator validity check goes after map function validity has been checked.
    if (itemsObject) {
        // If the object claims to support iterators, then let's try use them.
        ScopedValue it(scope, itemsObject->get(scope.engine->symbol_iterator()));
        CHECK_EXCEPTION();
        if (!it->isNullOrUndefined()) {
            ScopedFunctionObject itfunc(scope, it);
            if (!itfunc)
                return scope.engine->throwTypeError();
            usingIterator = true;
        }
    }

    ScopedValue thisArg(scope);
    if (argc > 2)
        thisArg = argv[2];

    const FunctionObject *C = thisObject->as<FunctionObject>();

    if (usingIterator) {
        // Item iteration supported, so let's go ahead and try use that.
        CHECK_EXCEPTION();

        qint64 iterableLength = 0;
        Value *nextValue = scope.alloc(1);
        ScopedValue done(scope);

        ScopedObject lengthIterator(scope, Runtime::GetIterator::call(scope.engine, itemsObject, true));
        CHECK_EXCEPTION(); // symbol_iterator threw; whoops.
        if (!lengthIterator) {
            return scope.engine->throwTypeError(); // symbol_iterator wasn't an object.
        }

        forever {
            // Here we calculate the length of the iterable range.
            if (iterableLength > (static_cast<qint64>(1) << 53) - 1) {
                ScopedValue falsey(scope, Encode(false));
                ScopedValue error(scope, scope.engine->throwTypeError());
                return Runtime::IteratorClose::call(scope.engine, lengthIterator, falsey);
            }
            // Retrieve the next value. If the iteration ends, we're done here.
            done = Value::fromReturnedValue(Runtime::IteratorNext::call(scope.engine, lengthIterator, nextValue));
            if (scope.engine->hasException)
                return Runtime::IteratorClose::call(scope.engine, lengthIterator, Value::fromBoolean(false));
            if (done->toBoolean()) {
                break;
            }
            iterableLength++;
        }

        // Constructor validity check goes after we have calculated the length, because that calculation can throw
        // errors that are not type errors and at least the tests expect those rather than type errors.
        if (!C || !C->isConstructor())
            return scope.engine->throwTypeError();

        ScopedObject iterator(scope, Runtime::GetIterator::call(scope.engine, itemsObject, true));
        CHECK_EXCEPTION(); // symbol_iterator can throw.
        if (!iterator) {
            return scope.engine->throwTypeError(); // symbol_iterator wasn't an object.
        }

        ScopedObject a(scope, Value::undefinedValue());
        ScopedValue ctorArgument(scope, Value::fromReturnedValue(QV4::Encode(int(iterableLength))));
        a = C->callAsConstructor(ctorArgument, 1);
        CHECK_EXCEPTION();

        // We check exceptions above, and only after doing so, check the array's validity after construction.
        if (!::validateTypedArray(a) || (a->getLength() < iterableLength))
            return scope.engine->throwTypeError();


        // The loop below traverses the iterator, and puts elements into the created array.
        ScopedValue mappedValue(scope, Value::undefinedValue());
        for (qint64 k = 0; k < iterableLength; ++k) {
            done = Value::fromReturnedValue(Runtime::IteratorNext::call(scope.engine, iterator, nextValue));
            if (scope.engine->hasException)
                return Runtime::IteratorClose::call(scope.engine, iterator, Value::fromBoolean(false));

            if (mapfn) {
                mapArguments[0] = *nextValue;
                mapArguments[1] = Value::fromDouble(k);
                mappedValue = mapfn->call(thisArg, mapArguments, 2);
                if (scope.engine->hasException)
                    return Runtime::IteratorClose::call(scope.engine, iterator, Value::fromBoolean(false));
            } else {
                mappedValue = *nextValue;
            }

            a->put(k, mappedValue);
            if (scope.engine->hasException)
                return Runtime::IteratorClose::call(scope.engine, iterator, Value::fromBoolean(false));
        }
        return a.asReturnedValue();
    } else {
        // Array-like fallback. We request elements by index, and put them into the created array.
        ScopedObject arrayLike(scope, argv[0].toObject(scope.engine));
        if (!arrayLike)
            return scope.engine->throwTypeError(QString::fromLatin1("Cannot convert %1 to object").arg(argv[0].toQStringNoThrow()));

        int len = arrayLike->getLength();
        CHECK_EXCEPTION();

        // Getting the length may throw, and must do so before we check the constructor validity.
        if (!C || !C->isConstructor())
            return scope.engine->throwTypeError();

        ScopedObject a(scope, Value::undefinedValue());
        ScopedValue ctorArgument(scope, Value::fromReturnedValue(QV4::Encode(len)));
        a = C->callAsConstructor(ctorArgument, 1);
        CHECK_EXCEPTION();

        // We check exceptions above, and only after doing so, check the array's validity after construction.
        if (!::validateTypedArray(a) || (a->getLength() < len))
            return scope.engine->throwTypeError();

        ScopedValue mappedValue(scope, Value::undefinedValue());
        ScopedValue kValue(scope);
        for (int k = 0; k < len; ++k) {
            kValue = arrayLike->get(k);
            CHECK_EXCEPTION();

            if (mapfn) {
                mapArguments[0] = kValue;
                mapArguments[1] = Value::fromDouble(k);
                mappedValue = mapfn->call(thisArg, mapArguments, 2);
                CHECK_EXCEPTION();
            } else {
                mappedValue = kValue;
            }

            a->put(k, mappedValue);
            CHECK_EXCEPTION();
        }
        return a.asReturnedValue();
    }
}

void IntrinsicTypedArrayPrototype::init(ExecutionEngine *engine, IntrinsicTypedArrayCtor *ctor)
{
    Scope scope(engine);
    ctor->defineReadonlyProperty(engine->id_prototype(), *this);
    ctor->defineReadonlyConfigurableProperty(engine->id_length(), Value::fromInt32(0));
    ScopedString s(scope, engine->newString(QStringLiteral("TypedArray")));
    ctor->defineReadonlyConfigurableProperty(engine->id_name(), s);
    s = scope.engine->newString(QStringLiteral("of"));
    ctor->defineDefaultProperty(s, IntrinsicTypedArrayCtor::method_of);
    s = scope.engine->newString(QStringLiteral("from"));
    ctor->defineDefaultProperty(s, IntrinsicTypedArrayCtor::method_from, 1);
    ctor->addSymbolSpecies();

    defineAccessorProperty(QStringLiteral("buffer"), method_get_buffer, nullptr);
    defineAccessorProperty(QStringLiteral("byteLength"), method_get_byteLength, nullptr);
    defineAccessorProperty(QStringLiteral("byteOffset"), method_get_byteOffset, nullptr);
    defineAccessorProperty(QStringLiteral("length"), method_get_length, nullptr);

    defineDefaultProperty(QStringLiteral("copyWithin"), method_copyWithin, 2);
    defineDefaultProperty(QStringLiteral("entries"), method_entries, 0);
    defineDefaultProperty(QStringLiteral("every"), method_every, 1);
    defineDefaultProperty(QStringLiteral("fill"), method_fill, 1);
    defineDefaultProperty(QStringLiteral("filter"), method_filter, 1);
    defineDefaultProperty(QStringLiteral("find"), method_find, 1);
    defineDefaultProperty(QStringLiteral("findIndex"), method_findIndex, 1);
    defineDefaultProperty(QStringLiteral("forEach"), method_forEach, 1);
    defineDefaultProperty(QStringLiteral("includes"), method_includes, 1);
    defineDefaultProperty(QStringLiteral("indexOf"), method_indexOf, 1);
    defineDefaultProperty(QStringLiteral("join"), method_join, 1);
    defineDefaultProperty(QStringLiteral("keys"), method_keys, 0);
    defineDefaultProperty(QStringLiteral("lastIndexOf"), method_lastIndexOf, 1);
    defineDefaultProperty(QStringLiteral("map"), method_map, 1);
    defineDefaultProperty(QStringLiteral("reduce"), method_reduce, 1);
    defineDefaultProperty(QStringLiteral("reduceRight"), method_reduceRight, 1);
    defineDefaultProperty(QStringLiteral("reverse"), method_reverse, 0);
    defineDefaultProperty(QStringLiteral("some"), method_some, 1);
    defineDefaultProperty(QStringLiteral("set"), method_set, 1);
    defineDefaultProperty(QStringLiteral("slice"), method_slice, 2);
    defineDefaultProperty(QStringLiteral("subarray"), method_subarray, 2);
    defineDefaultProperty(engine->id_toLocaleString(), method_toLocaleString, 0);
    ScopedObject f(scope, engine->arrayPrototype()->get(engine->id_toString()));
    defineDefaultProperty(engine->id_toString(), f);

    ScopedString valuesString(scope, engine->newIdentifier(QStringLiteral("values")));
    ScopedObject values(scope, FunctionObject::createBuiltinFunction(engine, valuesString, method_values, 0));
    defineDefaultProperty(QStringLiteral("values"), values);
    defineDefaultProperty(engine->symbol_iterator(), values);

    defineAccessorProperty(engine->symbol_toStringTag(), method_get_toStringTag, nullptr);
}
