/*
    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 "JSRadioNodeList.h"

#include "JSDOMBinding.h"
#include "JSDOMConstructor.h"
#include "JSNode.h"
#include "Node.h"
#include "URL.h"
#include <runtime/JSString.h>
#include <runtime/PropertyNameArray.h>
#include <wtf/GetPtr.h>

using namespace JSC;

namespace WebCore {

// Attributes

JSC::EncodedJSValue jsRadioNodeListValue(JSC::ExecState*, JSC::EncodedJSValue, JSC::PropertyName);
bool setJSRadioNodeListValue(JSC::ExecState*, JSC::EncodedJSValue, JSC::EncodedJSValue);
JSC::EncodedJSValue jsRadioNodeListConstructor(JSC::ExecState*, JSC::EncodedJSValue, JSC::PropertyName);
bool setJSRadioNodeListConstructor(JSC::ExecState*, JSC::EncodedJSValue, JSC::EncodedJSValue);

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

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

typedef JSDOMConstructorNotConstructable<JSRadioNodeList> JSRadioNodeListConstructor;

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

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

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

/* Hash table for prototype */

static const HashTableValue JSRadioNodeListPrototypeTableValues[] =
{
    { "constructor", DontEnum, NoIntrinsic, { (intptr_t)static_cast<PropertySlot::GetValueFunc>(jsRadioNodeListConstructor), (intptr_t) static_cast<PutPropertySlot::PutValueFunc>(setJSRadioNodeListConstructor) } },
    { "value", CustomAccessor, NoIntrinsic, { (intptr_t)static_cast<PropertySlot::GetValueFunc>(jsRadioNodeListValue), (intptr_t) static_cast<PutPropertySlot::PutValueFunc>(setJSRadioNodeListValue) } },
};

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

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

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

JSRadioNodeList::JSRadioNodeList(Structure* structure, JSDOMGlobalObject& globalObject, Ref<RadioNodeList>&& impl)
    : JSNodeList(structure, globalObject, WTFMove(impl))
{
}

JSObject* JSRadioNodeList::createPrototype(VM& vm, JSGlobalObject* globalObject)
{
    return JSRadioNodeListPrototype::create(vm, globalObject, JSRadioNodeListPrototype::createStructure(vm, globalObject, JSNodeList::prototype(vm, globalObject)));
}

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

bool JSRadioNodeList::getOwnPropertySlot(JSObject* object, ExecState* state, PropertyName propertyName, PropertySlot& slot)
{
    auto* thisObject = jsCast<JSRadioNodeList*>(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 JSRadioNodeList::getOwnPropertySlotByIndex(JSObject* object, ExecState* state, unsigned index, PropertySlot& slot)
{
    auto* thisObject = jsCast<JSRadioNodeList*>(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 jsRadioNodeListValue(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<JSRadioNodeList*>(decodedThisValue);
    if (UNLIKELY(!castedThis)) {
        return throwGetterTypeError(*state, throwScope, "RadioNodeList", "value");
    }
    auto& impl = castedThis->wrapped();
    JSValue result = jsStringWithCache(state, impl.value());
    return JSValue::encode(result);
}


EncodedJSValue jsRadioNodeListConstructor(ExecState* state, EncodedJSValue thisValue, PropertyName)
{
    VM& vm = state->vm();
    auto throwScope = DECLARE_THROW_SCOPE(vm);
    JSRadioNodeListPrototype* domObject = jsDynamicCast<JSRadioNodeListPrototype*>(JSValue::decode(thisValue));
    if (UNLIKELY(!domObject))
        return throwVMTypeError(state, throwScope);
    return JSValue::encode(JSRadioNodeList::getConstructor(state->vm(), domObject->globalObject()));
}

bool setJSRadioNodeListConstructor(ExecState* state, EncodedJSValue thisValue, EncodedJSValue encodedValue)
{
    VM& vm = state->vm();
    auto throwScope = DECLARE_THROW_SCOPE(vm);
    JSValue value = JSValue::decode(encodedValue);
    JSRadioNodeListPrototype* domObject = jsDynamicCast<JSRadioNodeListPrototype*>(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);
}

bool setJSRadioNodeListValue(ExecState* state, EncodedJSValue thisValue, EncodedJSValue encodedValue)
{
    VM& vm = state->vm();
    auto throwScope = DECLARE_THROW_SCOPE(vm);
    UNUSED_PARAM(throwScope);
    JSValue value = JSValue::decode(encodedValue);
    UNUSED_PARAM(thisValue);
    JSRadioNodeList* castedThis = jsDynamicCast<JSRadioNodeList*>(JSValue::decode(thisValue));
    if (UNLIKELY(!castedThis)) {
        return throwSetterTypeError(*state, throwScope, "RadioNodeList", "value");
    }
    auto& impl = castedThis->wrapped();
    auto nativeValue = value.toWTFString(state);
    RETURN_IF_EXCEPTION(throwScope, false);
    impl.setValue(WTFMove(nativeValue));
    return true;
}


void JSRadioNodeList::getOwnPropertyNames(JSObject* object, ExecState* state, PropertyNameArray& propertyNames, EnumerationMode mode)
{
    auto* thisObject = jsCast<JSRadioNodeList*>(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);
}

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

#if ENABLE(BINDING_INTEGRITY)
#if PLATFORM(WIN)
#pragma warning(disable: 4483)
extern "C" { extern void (*const __identifier("??_7RadioNodeList@WebCore@@6B@")[])(); }
#else
extern "C" { extern void* _ZTVN7WebCore13RadioNodeListE[]; }
#endif
#endif

JSC::JSValue toJSNewlyCreated(JSC::ExecState*, JSDOMGlobalObject* globalObject, Ref<RadioNodeList>&& impl)
{

#if ENABLE(BINDING_INTEGRITY)
    void* actualVTablePointer = *(reinterpret_cast<void**>(impl.ptr()));
#if PLATFORM(WIN)
    void* expectedVTablePointer = reinterpret_cast<void*>(__identifier("??_7RadioNodeList@WebCore@@6B@"));
#else
    void* expectedVTablePointer = &_ZTVN7WebCore13RadioNodeListE[2];
#if COMPILER(CLANG)
    // If this fails RadioNodeList does not have a vtable, so you need to add the
    // ImplementationLacksVTable attribute to the interface definition
    static_assert(__is_polymorphic(RadioNodeList), "RadioNodeList is not polymorphic");
#endif
#endif
    // If you hit this assertion you either have a use after free bug, or
    // RadioNodeList has subclasses. If RadioNodeList has subclasses that get passed
    // to toJS() we currently require RadioNodeList you to opt out of binding hardening
    // by adding the SkipVTableValidation attribute to the interface IDL definition
    RELEASE_ASSERT(actualVTablePointer == expectedVTablePointer);
#endif
    return createWrapper<RadioNodeList>(globalObject, WTFMove(impl));
}

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


}
