/*
    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"
#include "JSHTMLFormControlsCollection.h"

#include "Element.h"
#include "JSDOMBinding.h"
#include "JSDOMConstructor.h"
#include "JSNode.h"
#include "JSNodeCustom.h"
#include "Node.h"
#include "wtf/text/AtomicString.h"
#include <runtime/Error.h>
#include <runtime/PropertyNameArray.h>
#include <wtf/GetPtr.h>

using namespace JSC;

namespace WebCore {

// Functions

JSC::EncodedJSValue JSC_HOST_CALL jsHTMLFormControlsCollectionPrototypeFunctionNamedItem(JSC::ExecState*);

// Attributes

JSC::EncodedJSValue jsHTMLFormControlsCollectionConstructor(JSC::ExecState*, JSC::EncodedJSValue, JSC::PropertyName);
bool setJSHTMLFormControlsCollectionConstructor(JSC::ExecState*, JSC::EncodedJSValue, JSC::EncodedJSValue);

class JSHTMLFormControlsCollectionPrototype : public JSC::JSNonFinalObject {
public:
    typedef JSC::JSNonFinalObject Base;
    static JSHTMLFormControlsCollectionPrototype* create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure)
    {
        JSHTMLFormControlsCollectionPrototype* ptr = new (NotNull, JSC::allocateCell<JSHTMLFormControlsCollectionPrototype>(vm.heap)) JSHTMLFormControlsCollectionPrototype(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:
    JSHTMLFormControlsCollectionPrototype(JSC::VM& vm, JSC::JSGlobalObject*, JSC::Structure* structure)
        : JSC::JSNonFinalObject(vm, structure)
    {
    }

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

typedef JSDOMConstructorNotConstructable<JSHTMLFormControlsCollection> JSHTMLFormControlsCollectionConstructor;

template<> JSValue JSHTMLFormControlsCollectionConstructor::prototypeForStructure(JSC::VM& vm, const JSDOMGlobalObject& globalObject)
{
    return JSHTMLCollection::getConstructor(vm, &globalObject);
}

template<> void JSHTMLFormControlsCollectionConstructor::initializeProperties(VM& vm, JSDOMGlobalObject& globalObject)
{
    putDirect(vm, vm.propertyNames->prototype, JSHTMLFormControlsCollection::prototype(vm, &globalObject), DontDelete | ReadOnly | DontEnum);
    putDirect(vm, vm.propertyNames->name, jsNontrivialString(&vm, String(ASCIILiteral("HTMLFormControlsCollection"))), ReadOnly | DontEnum);
    putDirect(vm, vm.propertyNames->length, jsNumber(0), ReadOnly | DontEnum);
}

template<> const ClassInfo JSHTMLFormControlsCollectionConstructor::s_info = { "HTMLFormControlsCollection", &Base::s_info, 0, CREATE_METHOD_TABLE(JSHTMLFormControlsCollectionConstructor) };

/* Hash table for prototype */

static const HashTableValue JSHTMLFormControlsCollectionPrototypeTableValues[] =
{
    { "constructor", DontEnum, NoIntrinsic, { (intptr_t)static_cast<PropertySlot::GetValueFunc>(jsHTMLFormControlsCollectionConstructor), (intptr_t) static_cast<PutPropertySlot::PutValueFunc>(setJSHTMLFormControlsCollectionConstructor) } },
    { "namedItem", JSC::Function, NoIntrinsic, { (intptr_t)static_cast<NativeFunction>(jsHTMLFormControlsCollectionPrototypeFunctionNamedItem), (intptr_t) (1) } },
};

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

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

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

JSHTMLFormControlsCollection::JSHTMLFormControlsCollection(Structure* structure, JSDOMGlobalObject& globalObject, Ref<HTMLFormControlsCollection>&& impl)
    : JSHTMLCollection(structure, globalObject, WTFMove(impl))
{
}

JSObject* JSHTMLFormControlsCollection::createPrototype(VM& vm, JSGlobalObject* globalObject)
{
    return JSHTMLFormControlsCollectionPrototype::create(vm, globalObject, JSHTMLFormControlsCollectionPrototype::createStructure(vm, globalObject, JSHTMLCollection::prototype(vm, globalObject)));
}

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

bool JSHTMLFormControlsCollection::getOwnPropertySlot(JSObject* object, ExecState* state, PropertyName propertyName, PropertySlot& slot)
{
    auto* thisObject = jsCast<JSHTMLFormControlsCollection*>(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;
    JSValue proto = thisObject->getPrototypeDirect();
    if (proto.isObject() && jsCast<JSObject*>(proto)->hasProperty(state, propertyName))
        return false;

    if (!optionalIndex && thisObject->classInfo() == info()) {
        JSValue value;
        if (thisObject->nameGetter(state, propertyName, value)) {
            slot.setValue(thisObject, ReadOnly | DontEnum, value);
            return true;
        }
    }
    return false;
}

bool JSHTMLFormControlsCollection::getOwnPropertySlotByIndex(JSObject* object, ExecState* state, unsigned index, PropertySlot& slot)
{
    auto* thisObject = jsCast<JSHTMLFormControlsCollection*>(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 jsHTMLFormControlsCollectionConstructor(ExecState* state, EncodedJSValue thisValue, PropertyName)
{
    VM& vm = state->vm();
    auto throwScope = DECLARE_THROW_SCOPE(vm);
    JSHTMLFormControlsCollectionPrototype* domObject = jsDynamicCast<JSHTMLFormControlsCollectionPrototype*>(JSValue::decode(thisValue));
    if (UNLIKELY(!domObject))
        return throwVMTypeError(state, throwScope);
    return JSValue::encode(JSHTMLFormControlsCollection::getConstructor(state->vm(), domObject->globalObject()));
}

bool setJSHTMLFormControlsCollectionConstructor(ExecState* state, EncodedJSValue thisValue, EncodedJSValue encodedValue)
{
    VM& vm = state->vm();
    auto throwScope = DECLARE_THROW_SCOPE(vm);
    JSValue value = JSValue::decode(encodedValue);
    JSHTMLFormControlsCollectionPrototype* domObject = jsDynamicCast<JSHTMLFormControlsCollectionPrototype*>(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 JSHTMLFormControlsCollection::getOwnPropertyNames(JSObject* object, ExecState* state, PropertyNameArray& propertyNames, EnumerationMode mode)
{
    auto* thisObject = jsCast<JSHTMLFormControlsCollection*>(object);
    ASSERT_GC_OBJECT_INHERITS(thisObject, info());
    for (unsigned i = 0, count = thisObject->wrapped().length(); i < count; ++i)
        propertyNames.add(Identifier::from(state, i));
    if (mode.includeDontEnumProperties()) {
        for (auto& propertyName : thisObject->wrapped().supportedPropertyNames())
            propertyNames.add(Identifier::fromString(state, propertyName));
    }
    Base::getOwnPropertyNames(thisObject, state, propertyNames, mode);
}

JSValue JSHTMLFormControlsCollection::getConstructor(VM& vm, const JSGlobalObject* globalObject)
{
    return getDOMConstructor<JSHTMLFormControlsCollectionConstructor>(vm, *jsCast<const JSDOMGlobalObject*>(globalObject));
}

EncodedJSValue JSC_HOST_CALL jsHTMLFormControlsCollectionPrototypeFunctionNamedItem(ExecState* state)
{
    VM& vm = state->vm();
    auto throwScope = DECLARE_THROW_SCOPE(vm);
    UNUSED_PARAM(throwScope);
    JSValue thisValue = state->thisValue();
    auto castedThis = jsDynamicCast<JSHTMLFormControlsCollection*>(thisValue);
    if (UNLIKELY(!castedThis))
        return throwThisTypeError(*state, throwScope, "HTMLFormControlsCollection", "namedItem");
    ASSERT_GC_OBJECT_INHERITS(castedThis, JSHTMLFormControlsCollection::info());
    return JSValue::encode(castedThis->namedItem(*state));
}

bool JSHTMLFormControlsCollectionOwner::isReachableFromOpaqueRoots(JSC::Handle<JSC::Unknown> handle, void*, SlotVisitor& visitor)
{
    auto* jsHTMLFormControlsCollection = jsCast<JSHTMLFormControlsCollection*>(handle.slot()->asCell());
    void* root = WebCore::root(jsHTMLFormControlsCollection->wrapped().ownerNode());
    return visitor.containsOpaqueRoot(root);
}

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


}
