/*
 * Copyright (C) 2013-2019 Apple Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
 */

#include "config.h"
#include "JSArrayBufferPrototype.h"

#include "JSArrayBuffer.h"
#include "JSArrayBufferPrototypeInlines.h"
#include "JSCInlines.h"

namespace JSC {

static JSC_DECLARE_HOST_FUNCTION(arrayBufferProtoFuncSlice);
static JSC_DECLARE_HOST_FUNCTION(arrayBufferProtoGetterFuncByteLength);
static JSC_DECLARE_HOST_FUNCTION(sharedArrayBufferProtoFuncSlice);
static JSC_DECLARE_HOST_FUNCTION(sharedArrayBufferProtoGetterFuncByteLength);

std::optional<JSValue> arrayBufferSpeciesConstructorSlow(JSGlobalObject* globalObject, JSArrayBuffer* thisObject, ArrayBufferSharingMode mode)
{
    VM& vm = globalObject->vm();
    auto scope = DECLARE_THROW_SCOPE(vm);

    bool isValid = speciesWatchpointIsValid(vm, thisObject, mode);
    scope.assertNoException();
    if (LIKELY(isValid))
        return std::nullopt;

    JSValue constructor = thisObject->get(globalObject, vm.propertyNames->constructor);
    RETURN_IF_EXCEPTION(scope, std::nullopt);
    if (constructor.isConstructor(vm)) {
        JSObject* constructorObject = jsCast<JSObject*>(constructor);
        JSGlobalObject* globalObjectFromConstructor = constructorObject->globalObject(vm);
        bool isArrayBufferConstructorFromAnotherRealm = globalObject != globalObjectFromConstructor
            && constructorObject == globalObjectFromConstructor->arrayBufferConstructor(mode);
        if (isArrayBufferConstructorFromAnotherRealm)
            return std::nullopt;
    }

    if (constructor.isUndefined())
        return std::nullopt;

    if (!constructor.isObject()) {
        throwTypeError(globalObject, scope, "constructor property should not be null"_s);
        return std::nullopt;
    }

    JSValue species = constructor.get(globalObject, vm.propertyNames->speciesSymbol);
    RETURN_IF_EXCEPTION(scope, std::nullopt);

    return species.isUndefinedOrNull() ? std::nullopt : std::make_optional(species);
}

enum class SpeciesConstructResult : uint8_t {
    FastPath,
    Exception,
    CreatedObject
};

static ALWAYS_INLINE std::pair<SpeciesConstructResult, JSArrayBuffer*> speciesConstructArrayBuffer(JSGlobalObject* globalObject, JSArrayBuffer* thisObject, unsigned length, ArrayBufferSharingMode mode)
{
    // This is optimized way of SpeciesConstruct invoked from {ArrayBuffer,SharedArrayBuffer}.prototype.slice.
    // https://tc39.es/ecma262/#sec-arraybuffer.prototype.slice
    // https://tc39.es/ecma262/#sec-sharedarraybuffer.prototype.slice
    VM& vm = globalObject->vm();
    auto scope = DECLARE_THROW_SCOPE(vm);
    constexpr std::pair<SpeciesConstructResult, JSArrayBuffer*> errorResult { SpeciesConstructResult::Exception, nullptr };
    constexpr std::pair<SpeciesConstructResult, JSArrayBuffer*> fastPathResult { SpeciesConstructResult::FastPath, nullptr };

    // Fast path in the normal case where the user has not set an own constructor and the ArrayBuffer.prototype.constructor is normal.
    // We need prototype check for subclasses of ArrayBuffer, which are ArrayBuffer objects but have a different prototype by default.
    std::optional<JSValue> species = arrayBufferSpeciesConstructor(globalObject, thisObject, mode);
    RETURN_IF_EXCEPTION(scope, errorResult);
    if (!species)
        return fastPathResult;

    // 16. Let new be ? Construct(ctor, « 𝔽(newLen) »).
    MarkedArgumentBuffer args;
    args.append(jsNumber(length));
    ASSERT(!args.hasOverflowed());
    JSObject* newObject = construct(globalObject, species.value(), args, "Species construction did not get a valid constructor");
    RETURN_IF_EXCEPTION(scope, errorResult);

    // 17. Perform ? RequireInternalSlot(new, [[ArrayBufferData]]).
    JSArrayBuffer* result = jsDynamicCast<JSArrayBuffer*>(vm, newObject);
    if (UNLIKELY(!result)) {
        throwTypeError(globalObject, scope, "Species construction does not create ArrayBuffer"_s);
        return errorResult;
    }

    if (mode == ArrayBufferSharingMode::Default) {
        // 18. If IsSharedArrayBuffer(new) is true, throw a TypeError exception.
        if (result->isShared()) {
            throwTypeError(globalObject, scope, "ArrayBuffer.prototype.slice creates SharedArrayBuffer"_s);
            return errorResult;
        }
        // 19. If IsDetachedBuffer(new) is true, throw a TypeError exception.
        if (result->impl()->isDetached()) {
            throwVMTypeError(globalObject, scope, "Created ArrayBuffer is detached"_s);
            return errorResult;
        }
    } else {
        // 17. If IsSharedArrayBuffer(new) is false, throw a TypeError exception.
        if (!result->isShared()) {
            throwTypeError(globalObject, scope, "SharedArrayBuffer.prototype.slice creates non-shared ArrayBuffer"_s);
            return errorResult;
        }
    }

    // 20. If SameValue(new, O) is true, throw a TypeError exception.
    if (result == thisObject) {
        throwVMTypeError(globalObject, scope, "Species construction returns same ArrayBuffer to a receiver"_s);
        return errorResult;
    }

    // 21. If new.[[ArrayBufferByteLength]] < newLen, throw a TypeError exception.
    if (result->impl()->byteLength() < length) {
        throwVMTypeError(globalObject, scope, "Species construction returns ArrayBuffer which byteLength is less than requested"_s);
        return errorResult;
    }

    return { SpeciesConstructResult::CreatedObject, result };
}


static EncodedJSValue arrayBufferSlice(JSGlobalObject* globalObject, JSValue arrayBufferValue, JSValue startValue, JSValue endValue, ArrayBufferSharingMode mode)
{
    // https://tc39.es/ecma262/#sec-arraybuffer.prototype.slice
    // https://tc39.es/ecma262/#sec-sharedarraybuffer.prototype.slice

    VM& vm = globalObject->vm();
    auto scope = DECLARE_THROW_SCOPE(vm);

    // 2. Perform ? RequireInternalSlot(O, [[ArrayBufferData]]).
    // 3. If IsSharedArrayBuffer(O) is true, throw a TypeError exception.
    JSArrayBuffer* thisObject = jsDynamicCast<JSArrayBuffer*>(vm, arrayBufferValue);
    if (!thisObject || (mode != thisObject->impl()->sharingMode()))
        return throwVMTypeError(globalObject, scope, makeString("Receiver must be "_s, mode == ArrayBufferSharingMode::Default ? "ArrayBuffer"_s : "SharedArrayBuffer"_s));

    // 4. If IsDetachedBuffer(O) is true, throw a TypeError exception.
    if (mode == ArrayBufferSharingMode::Default && thisObject->impl()->isDetached())
        return throwVMTypeError(globalObject, scope, "Receiver is detached"_s);

    // 5. Let len be O.[[ArrayBufferByteLength]].
    unsigned byteLength = thisObject->impl()->byteLength();
    unsigned firstIndex = 0;
    double relativeStart = startValue.toIntegerOrInfinity(globalObject);
    RETURN_IF_EXCEPTION(scope, encodedJSValue());
    if (relativeStart < 0)
        firstIndex = static_cast<unsigned>(std::max<double>(byteLength + relativeStart, 0));
    else
        firstIndex = static_cast<unsigned>(std::min<double>(relativeStart, byteLength));
    ASSERT(firstIndex <= byteLength);

    unsigned finalIndex = 0;
    if (!endValue.isUndefined()) {
        double relativeEnd = endValue.toIntegerOrInfinity(globalObject);
        RETURN_IF_EXCEPTION(scope, encodedJSValue());
        if (relativeEnd < 0)
            finalIndex = static_cast<unsigned>(std::max<double>(byteLength + relativeEnd, 0));
        else
            finalIndex = static_cast<unsigned>(std::min<double>(relativeEnd, byteLength));
    } else
        finalIndex = thisObject->impl()->byteLength();
    ASSERT(finalIndex <= byteLength);

    // 14. Let newLen be max(final - first, 0).
    unsigned newLength = (finalIndex >= firstIndex) ? finalIndex - firstIndex : 0;

    // 15. Let ctor be ? SpeciesConstructor(O, %ArrayBuffer%).
    auto speciesResult = speciesConstructArrayBuffer(globalObject, thisObject, newLength, mode);
    // We can only get an exception if we call some user function.
    EXCEPTION_ASSERT(!!scope.exception() == (speciesResult.first == SpeciesConstructResult::Exception));
    if (UNLIKELY(speciesResult.first == SpeciesConstructResult::Exception))
        return { };

    // 23. If IsDetachedBuffer(O) is true, throw a TypeError exception.
    if (mode == ArrayBufferSharingMode::Default && thisObject->impl()->isDetached())
        return throwVMTypeError(globalObject, scope, "Receiver is detached"_s);

    if (LIKELY(speciesResult.first == SpeciesConstructResult::FastPath)) {
        ASSERT(!thisObject->impl()->isDetached());
        auto newBuffer = thisObject->impl()->sliceWithClampedIndex(firstIndex, finalIndex);
        if (!newBuffer)
            return JSValue::encode(throwOutOfMemoryError(globalObject, scope));
        Structure* structure = globalObject->arrayBufferStructure(newBuffer->sharingMode());
        JSArrayBuffer* result = JSArrayBuffer::create(vm, structure, WTFMove(newBuffer));
        return JSValue::encode(result);
    }

    // 24. Let fromBuf be O.[[ArrayBufferData]].
    // 25. Let toBuf be new.[[ArrayBufferData]].
    // 26. Perform CopyDataBlockBytes(toBuf, 0, fromBuf, first, newLen).
    JSArrayBuffer* newObject = speciesResult.second;
    ASSERT(!thisObject->impl()->isDetached());
    ASSERT(!newObject->impl()->isDetached());
    ASSERT(newObject->impl()->byteLength() >= newLength);
    memcpy(newObject->impl()->data(), static_cast<const char*>(thisObject->impl()->data()) + firstIndex, newLength);
    return JSValue::encode(newObject);
}

static EncodedJSValue arrayBufferByteLength(JSGlobalObject* globalObject, JSValue arrayBufferValue, ArrayBufferSharingMode mode)
{
    VM& vm = globalObject->vm();
    auto scope = DECLARE_THROW_SCOPE(vm);

    auto* thisObject = jsDynamicCast<JSArrayBuffer*>(vm, arrayBufferValue);
    if (!thisObject || (mode != thisObject->impl()->sharingMode()))
        return throwVMTypeError(globalObject, scope, makeString("Receiver must be "_s, mode == ArrayBufferSharingMode::Default ? "ArrayBuffer"_s : "SharedArrayBuffer"_s));

    if (mode == ArrayBufferSharingMode::Default && thisObject->impl()->isDetached())
        return JSValue::encode(jsNumber(0));

    return JSValue::encode(jsNumber(thisObject->impl()->byteLength()));
}

JSC_DEFINE_HOST_FUNCTION(arrayBufferProtoFuncSlice, (JSGlobalObject* globalObject, CallFrame* callFrame))
{
    return arrayBufferSlice(globalObject, callFrame->thisValue(), callFrame->argument(0), callFrame->argument(1), ArrayBufferSharingMode::Default);
}

// http://tc39.github.io/ecmascript_sharedmem/shmem.html#sec-get-arraybuffer.prototype.bytelength
JSC_DEFINE_HOST_FUNCTION(arrayBufferProtoGetterFuncByteLength, (JSGlobalObject* globalObject, CallFrame* callFrame))
{
    return arrayBufferByteLength(globalObject, callFrame->thisValue(), ArrayBufferSharingMode::Default);
}

JSC_DEFINE_HOST_FUNCTION(sharedArrayBufferProtoFuncSlice, (JSGlobalObject* globalObject, CallFrame* callFrame))
{
    return arrayBufferSlice(globalObject, callFrame->thisValue(), callFrame->argument(0), callFrame->argument(1), ArrayBufferSharingMode::Shared);
}

// http://tc39.github.io/ecmascript_sharedmem/shmem.html#StructuredData.SharedArrayBuffer.prototype.get_byteLength
JSC_DEFINE_HOST_FUNCTION(sharedArrayBufferProtoGetterFuncByteLength, (JSGlobalObject* globalObject, CallFrame* callFrame))
{
    return arrayBufferByteLength(globalObject, callFrame->thisValue(), ArrayBufferSharingMode::Shared);
}

const ClassInfo JSArrayBufferPrototype::s_info = {
    "ArrayBuffer", &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSArrayBufferPrototype)
};

JSArrayBufferPrototype::JSArrayBufferPrototype(VM& vm, Structure* structure)
    : Base(vm, structure)
{
}

void JSArrayBufferPrototype::finishCreation(VM& vm, JSGlobalObject* globalObject, ArrayBufferSharingMode sharingMode)
{
    Base::finishCreation(vm);
    
    putDirectWithoutTransition(vm, vm.propertyNames->toStringTagSymbol, jsString(vm, arrayBufferSharingModeName(sharingMode)), PropertyAttribute::DontEnum | PropertyAttribute::ReadOnly);
    if (sharingMode == ArrayBufferSharingMode::Default) {
        JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->slice, arrayBufferProtoFuncSlice, static_cast<unsigned>(PropertyAttribute::DontEnum), 2);
        JSC_NATIVE_GETTER_WITHOUT_TRANSITION(vm.propertyNames->byteLength, arrayBufferProtoGetterFuncByteLength, PropertyAttribute::DontEnum | PropertyAttribute::ReadOnly);
    } else {
        JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->slice, sharedArrayBufferProtoFuncSlice, static_cast<unsigned>(PropertyAttribute::DontEnum), 2);
        JSC_NATIVE_GETTER_WITHOUT_TRANSITION(vm.propertyNames->byteLength, sharedArrayBufferProtoGetterFuncByteLength, PropertyAttribute::DontEnum | PropertyAttribute::ReadOnly);
    }
}

JSArrayBufferPrototype* JSArrayBufferPrototype::create(VM& vm, JSGlobalObject* globalObject, Structure* structure, ArrayBufferSharingMode sharingMode)
{
    JSArrayBufferPrototype* prototype =
        new (NotNull, allocateCell<JSArrayBufferPrototype>(vm.heap))
        JSArrayBufferPrototype(vm, structure);
    prototype->finishCreation(vm, globalObject, sharingMode);
    return prototype;
}

Structure* JSArrayBufferPrototype::createStructure(
    VM& vm, JSGlobalObject* globalObject, JSValue prototype)
{
    return Structure::create(
        vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info());
}

} // namespace JSC

