/*
    This file is part of the WebKit open source project.
    This file has been generated by generate-bindings.pl. DO NOT MODIFY!

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Library General Public
    License as published by the Free Software Foundation; either
    version 2 of the License, or (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Library General Public License for more details.

    You should have received a copy of the GNU Library General Public License
    along with this library; see the file COPYING.LIB.  If not, write to
    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
    Boston, MA 02110-1301, USA.
*/

#include "config.h"

#if ENABLE(DATA_TRANSFER_ITEMS)

#include "JSDataTransferItemList.h"

#include "DataTransferItem.h"
#include "ExceptionCode.h"
#include "JSDOMBinding.h"
#include "JSDOMConvert.h"
#include "JSDataTransferItem.h"
#include "JSFile.h"
#include <runtime/Error.h>
#include <runtime/PropertyNameArray.h>
#include <wtf/GetPtr.h>

using namespace JSC;

namespace WebCore {

// Functions

JSC::EncodedJSValue JSC_HOST_CALL jsDataTransferItemListPrototypeFunctionItem(JSC::ExecState*);
JSC::EncodedJSValue JSC_HOST_CALL jsDataTransferItemListPrototypeFunctionClear(JSC::ExecState*);
JSC::EncodedJSValue JSC_HOST_CALL jsDataTransferItemListPrototypeFunctionAdd(JSC::ExecState*);

// Attributes

JSC::EncodedJSValue jsDataTransferItemListLength(JSC::ExecState*, JSC::EncodedJSValue, JSC::PropertyName);
bool setJSDataTransferItemListConstructor(JSC::ExecState*, JSC::EncodedJSValue, JSC::EncodedJSValue);

class JSDataTransferItemListPrototype : public JSC::JSNonFinalObject {
public:
    typedef JSC::JSNonFinalObject Base;
    static JSDataTransferItemListPrototype* create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure)
    {
        JSDataTransferItemListPrototype* ptr = new (NotNull, JSC::allocateCell<JSDataTransferItemListPrototype>(vm.heap)) JSDataTransferItemListPrototype(vm, globalObject, structure);
        ptr->finishCreation(vm);
        return ptr;
    }

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

private:
    JSDataTransferItemListPrototype(JSC::VM& vm, JSC::JSGlobalObject*, JSC::Structure* structure)
        : JSC::JSNonFinalObject(vm, structure)
    {
    }

    void finishCreation(JSC::VM&);
};

/* Hash table for prototype */

static const HashTableValue JSDataTransferItemListPrototypeTableValues[] =
{
    { "length", ReadOnly | CustomAccessor, NoIntrinsic, { (intptr_t)static_cast<PropertySlot::GetValueFunc>(jsDataTransferItemListLength), (intptr_t) static_cast<PutPropertySlot::PutValueFunc>(0) } },
    { "item", JSC::Function, NoIntrinsic, { (intptr_t)static_cast<NativeFunction>(jsDataTransferItemListPrototypeFunctionItem), (intptr_t) (1) } },
    { "clear", JSC::Function, NoIntrinsic, { (intptr_t)static_cast<NativeFunction>(jsDataTransferItemListPrototypeFunctionClear), (intptr_t) (0) } },
    { "add", JSC::Function, NoIntrinsic, { (intptr_t)static_cast<NativeFunction>(jsDataTransferItemListPrototypeFunctionAdd), (intptr_t) (0) } },
};

const ClassInfo JSDataTransferItemListPrototype::s_info = { "DataTransferItemListPrototype", &Base::s_info, 0, CREATE_METHOD_TABLE(JSDataTransferItemListPrototype) };

void JSDataTransferItemListPrototype::finishCreation(VM& vm)
{
    Base::finishCreation(vm);
    reifyStaticProperties(vm, JSDataTransferItemListPrototypeTableValues, *this);
}

const ClassInfo JSDataTransferItemList::s_info = { "DataTransferItemList", &Base::s_info, 0, CREATE_METHOD_TABLE(JSDataTransferItemList) };

JSDataTransferItemList::JSDataTransferItemList(Structure* structure, JSDOMGlobalObject& globalObject, Ref<DataTransferItemList>&& impl)
    : JSDOMWrapper<DataTransferItemList>(structure, globalObject, WTFMove(impl))
{
}

JSObject* JSDataTransferItemList::createPrototype(VM& vm, JSGlobalObject* globalObject)
{
    return JSDataTransferItemListPrototype::create(vm, globalObject, JSDataTransferItemListPrototype::createStructure(vm, globalObject, globalObject->objectPrototype()));
}

JSObject* JSDataTransferItemList::prototype(VM& vm, JSGlobalObject* globalObject)
{
    return getDOMPrototype<JSDataTransferItemList>(vm, globalObject);
}

void JSDataTransferItemList::destroy(JSC::JSCell* cell)
{
    JSDataTransferItemList* thisObject = static_cast<JSDataTransferItemList*>(cell);
    thisObject->JSDataTransferItemList::~JSDataTransferItemList();
}

bool JSDataTransferItemList::getOwnPropertySlot(JSObject* object, ExecState* state, PropertyName propertyName, PropertySlot& slot)
{
    auto* thisObject = jsCast<JSDataTransferItemList*>(object);
    ASSERT_GC_OBJECT_INHERITS(thisObject, info());
    Optional<uint32_t> optionalIndex = parseIndex(propertyName);
    if (optionalIndex && optionalIndex.value() < thisObject->wrapped().length()) {
        unsigned index = optionalIndex.value();
        unsigned attributes = ReadOnly;
        slot.setValue(thisObject, attributes, toJS(state, thisObject->globalObject(), thisObject->wrapped().item(index)));
        return true;
    }
    if (Base::getOwnPropertySlot(thisObject, state, propertyName, slot))
        return true;
    return false;
}

bool JSDataTransferItemList::getOwnPropertySlotByIndex(JSObject* object, ExecState* state, unsigned index, PropertySlot& slot)
{
    auto* thisObject = jsCast<JSDataTransferItemList*>(object);
    ASSERT_GC_OBJECT_INHERITS(thisObject, info());
    if (LIKELY(index < thisObject->wrapped().length())) {
        unsigned attributes = DontDelete | ReadOnly;
        slot.setValue(thisObject, attributes, toJS(state, thisObject->globalObject(), thisObject->wrapped().item(index)));
        return true;
    }
    return Base::getOwnPropertySlotByIndex(thisObject, state, index, slot);
}

EncodedJSValue jsDataTransferItemListLength(ExecState* state, EncodedJSValue thisValue, PropertyName)
{
    VM& vm = state->vm();
    auto throwScope = DECLARE_THROW_SCOPE(vm);
    UNUSED_PARAM(throwScope);
    UNUSED_PARAM(thisValue);
    JSValue decodedThisValue = JSValue::decode(thisValue);
    auto* castedThis = jsDynamicCast<JSDataTransferItemList*>(decodedThisValue);
    if (UNLIKELY(!castedThis)) {
        return throwGetterTypeError(*state, throwScope, "DataTransferItemList", "length");
    }
    auto& impl = castedThis->wrapped();
    JSValue result = jsNumber(impl.length());
    return JSValue::encode(result);
}


bool setJSDataTransferItemListConstructor(ExecState* state, EncodedJSValue thisValue, EncodedJSValue encodedValue)
{
    VM& vm = state->vm();
    auto throwScope = DECLARE_THROW_SCOPE(vm);
    JSValue value = JSValue::decode(encodedValue);
    JSDataTransferItemListPrototype* domObject = jsDynamicCast<JSDataTransferItemListPrototype*>(JSValue::decode(thisValue));
    if (UNLIKELY(!domObject)) {
        throwVMTypeError(state, throwScope);
        return false;
    }
    // Shadowing a built-in constructor
    return domObject->putDirect(state->vm(), state->propertyNames().constructor, value);
}

void JSDataTransferItemList::getOwnPropertyNames(JSObject* object, ExecState* state, PropertyNameArray& propertyNames, EnumerationMode mode)
{
    auto* thisObject = jsCast<JSDataTransferItemList*>(object);
    ASSERT_GC_OBJECT_INHERITS(thisObject, info());
    for (unsigned i = 0, count = thisObject->wrapped().length(); i < count; ++i)
        propertyNames.add(Identifier::from(state, i));
    Base::getOwnPropertyNames(thisObject, state, propertyNames, mode);
}

EncodedJSValue JSC_HOST_CALL jsDataTransferItemListPrototypeFunctionItem(ExecState* state)
{
    VM& vm = state->vm();
    auto throwScope = DECLARE_THROW_SCOPE(vm);
    UNUSED_PARAM(throwScope);
    JSValue thisValue = state->thisValue();
    auto castedThis = jsDynamicCast<JSDataTransferItemList*>(thisValue);
    if (UNLIKELY(!castedThis))
        return throwThisTypeError(*state, throwScope, "DataTransferItemList", "item");
    ASSERT_GC_OBJECT_INHERITS(castedThis, JSDataTransferItemList::info());
    auto& impl = castedThis->wrapped();
    if (UNLIKELY(state->argumentCount() < 1))
        return throwVMError(state, throwScope, createNotEnoughArgumentsError(state));
    auto index = convert<uint32_t>(*state, state->uncheckedArgument(0), NormalConversion);
    RETURN_IF_EXCEPTION(throwScope, encodedJSValue());
    JSValue result = toJS(state, castedThis->globalObject(), impl.item(WTFMove(index)));
    return JSValue::encode(result);
}

EncodedJSValue JSC_HOST_CALL jsDataTransferItemListPrototypeFunctionClear(ExecState* state)
{
    VM& vm = state->vm();
    auto throwScope = DECLARE_THROW_SCOPE(vm);
    UNUSED_PARAM(throwScope);
    JSValue thisValue = state->thisValue();
    auto castedThis = jsDynamicCast<JSDataTransferItemList*>(thisValue);
    if (UNLIKELY(!castedThis))
        return throwThisTypeError(*state, throwScope, "DataTransferItemList", "clear");
    ASSERT_GC_OBJECT_INHERITS(castedThis, JSDataTransferItemList::info());
    auto& impl = castedThis->wrapped();
    impl.clear();
    return JSValue::encode(jsUndefined());
}

static inline EncodedJSValue jsDataTransferItemListPrototypeFunctionAdd1(ExecState* state)
{
    VM& vm = state->vm();
    auto throwScope = DECLARE_THROW_SCOPE(vm);
    UNUSED_PARAM(throwScope);
    JSValue thisValue = state->thisValue();
    auto castedThis = jsDynamicCast<JSDataTransferItemList*>(thisValue);
    if (UNLIKELY(!castedThis))
        return throwThisTypeError(*state, throwScope, "DataTransferItemList", "add");
    ASSERT_GC_OBJECT_INHERITS(castedThis, JSDataTransferItemList::info());
    auto& impl = castedThis->wrapped();
    if (UNLIKELY(state->argumentCount() < 1))
        return throwVMError(state, throwScope, createNotEnoughArgumentsError(state));
    File* file = nullptr;
    if (!state->uncheckedArgument(0).isUndefinedOrNull()) {
        file = JSFile::toWrapped(state->uncheckedArgument(0));
        if (UNLIKELY(!file))
            return throwArgumentTypeError(*state, throwScope, 0, "file", "DataTransferItemList", "add", "File");
    }
    impl.add(WTFMove(file));
    return JSValue::encode(jsUndefined());
}

static inline EncodedJSValue jsDataTransferItemListPrototypeFunctionAdd2(ExecState* state)
{
    VM& vm = state->vm();
    auto throwScope = DECLARE_THROW_SCOPE(vm);
    UNUSED_PARAM(throwScope);
    JSValue thisValue = state->thisValue();
    auto castedThis = jsDynamicCast<JSDataTransferItemList*>(thisValue);
    if (UNLIKELY(!castedThis))
        return throwThisTypeError(*state, throwScope, "DataTransferItemList", "add");
    ASSERT_GC_OBJECT_INHERITS(castedThis, JSDataTransferItemList::info());
    auto& impl = castedThis->wrapped();
    ExceptionCode ec = 0;
    auto data = state->argument(0).toWTFString(state);
    RETURN_IF_EXCEPTION(throwScope, encodedJSValue());
    auto type = state->argument(1).toWTFString(state);
    RETURN_IF_EXCEPTION(throwScope, encodedJSValue());
    impl.add(WTFMove(data), WTFMove(type), ec);
    setDOMException(state, throwScope, ec);
    return JSValue::encode(jsUndefined());
}

EncodedJSValue JSC_HOST_CALL jsDataTransferItemListPrototypeFunctionAdd(ExecState* state)
{
    VM& vm = state->vm();
    auto throwScope = DECLARE_THROW_SCOPE(vm);
    UNUSED_PARAM(throwScope);
    size_t argsCount = std::min<size_t>(2, state->argumentCount());
    if (argsCount == 0) {
        return jsDataTransferItemListPrototypeFunctionAdd2(state);
    }
    if (argsCount == 1) {
        JSValue distinguishingArg = state->uncheckedArgument(0);
        if (distinguishingArg.isUndefined())
            return jsDataTransferItemListPrototypeFunctionAdd2(state);
        if (distinguishingArg.isUndefinedOrNull())
            return jsDataTransferItemListPrototypeFunctionAdd1(state);
        if (distinguishingArg.isObject() && asObject(distinguishingArg)->inherits(JSFile::info()))
            return jsDataTransferItemListPrototypeFunctionAdd1(state);
        return jsDataTransferItemListPrototypeFunctionAdd2(state);
    }
    if (argsCount == 2) {
        return jsDataTransferItemListPrototypeFunctionAdd2(state);
    }
    return throwVMTypeError(state, throwScope);
}

bool JSDataTransferItemListOwner::isReachableFromOpaqueRoots(JSC::Handle<JSC::Unknown> handle, void*, SlotVisitor& visitor)
{
    UNUSED_PARAM(handle);
    UNUSED_PARAM(visitor);
    return false;
}

void JSDataTransferItemListOwner::finalize(JSC::Handle<JSC::Unknown> handle, void* context)
{
    auto* jsDataTransferItemList = jsCast<JSDataTransferItemList*>(handle.slot()->asCell());
    auto& world = *static_cast<DOMWrapperWorld*>(context);
    uncacheWrapper(world, &jsDataTransferItemList->wrapped(), jsDataTransferItemList);
}

JSC::JSValue toJSNewlyCreated(JSC::ExecState*, JSDOMGlobalObject* globalObject, Ref<DataTransferItemList>&& impl)
{
#if COMPILER(CLANG)
    // If you hit this failure the interface definition has the ImplementationLacksVTable
    // attribute. You should remove that attribute. If the class has subclasses
    // that may be passed through this toJS() function you should use the SkipVTableValidation
    // attribute to DataTransferItemList.
    static_assert(!__is_polymorphic(DataTransferItemList), "DataTransferItemList is polymorphic but the IDL claims it is not");
#endif
    return createWrapper<DataTransferItemList>(globalObject, WTFMove(impl));
}

JSC::JSValue toJS(JSC::ExecState* state, JSDOMGlobalObject* globalObject, DataTransferItemList& impl)
{
    return wrap(state, globalObject, impl);
}

DataTransferItemList* JSDataTransferItemList::toWrapped(JSC::JSValue value)
{
    if (auto* wrapper = jsDynamicCast<JSDataTransferItemList*>(value))
        return &wrapper->wrapped();
    return nullptr;
}

}

#endif // ENABLE(DATA_TRANSFER_ITEMS)
