/*
    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 "JSHTMLLIElement.h"

#include "HTMLLIElement.h"
#include "KURL.h"
#include <runtime/JSNumberCell.h>
#include <runtime/JSString.h>
#include <wtf/GetPtr.h>

using namespace JSC;

namespace WebCore {

ASSERT_CLASS_FITS_IN_CELL(JSHTMLLIElement);

/* Hash table */

static const HashTableValue JSHTMLLIElementTableValues[4] =
{
    { "type", DontDelete, (intptr_t)static_cast<PropertySlot::GetValueFunc>(jsHTMLLIElementType), (intptr_t)setJSHTMLLIElementType },
    { "value", DontDelete, (intptr_t)static_cast<PropertySlot::GetValueFunc>(jsHTMLLIElementValue), (intptr_t)setJSHTMLLIElementValue },
    { "constructor", DontEnum|ReadOnly, (intptr_t)static_cast<PropertySlot::GetValueFunc>(jsHTMLLIElementConstructor), (intptr_t)0 },
    { 0, 0, 0, 0 }
};

static JSC_CONST_HASHTABLE HashTable JSHTMLLIElementTable =
#if ENABLE(PERFECT_HASH_SIZE)
    { 31, JSHTMLLIElementTableValues, 0 };
#else
    { 9, 7, JSHTMLLIElementTableValues, 0 };
#endif

/* Hash table for constructor */

static const HashTableValue JSHTMLLIElementConstructorTableValues[1] =
{
    { 0, 0, 0, 0 }
};

static JSC_CONST_HASHTABLE HashTable JSHTMLLIElementConstructorTable =
#if ENABLE(PERFECT_HASH_SIZE)
    { 0, JSHTMLLIElementConstructorTableValues, 0 };
#else
    { 1, 0, JSHTMLLIElementConstructorTableValues, 0 };
#endif

class JSHTMLLIElementConstructor : public DOMConstructorObject {
public:
    JSHTMLLIElementConstructor(ExecState* exec, JSDOMGlobalObject* globalObject)
        : DOMConstructorObject(JSHTMLLIElementConstructor::createStructure(globalObject->objectPrototype()), globalObject)
    {
        putDirect(exec->propertyNames().prototype, JSHTMLLIElementPrototype::self(exec, globalObject), None);
    }
    virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&);
    virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&);
    virtual const ClassInfo* classInfo() const { return &s_info; }
    static const ClassInfo s_info;

    static PassRefPtr<Structure> createStructure(JSValue proto) 
    { 
        return Structure::create(proto, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount); 
    }
    
protected:
    static const unsigned StructureFlags = OverridesGetOwnPropertySlot | ImplementsHasInstance | DOMConstructorObject::StructureFlags;
};

const ClassInfo JSHTMLLIElementConstructor::s_info = { "HTMLLIElementConstructor", 0, &JSHTMLLIElementConstructorTable, 0 };

bool JSHTMLLIElementConstructor::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
{
    return getStaticValueSlot<JSHTMLLIElementConstructor, DOMObject>(exec, &JSHTMLLIElementConstructorTable, this, propertyName, slot);
}

bool JSHTMLLIElementConstructor::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
{
    return getStaticValueDescriptor<JSHTMLLIElementConstructor, DOMObject>(exec, &JSHTMLLIElementConstructorTable, this, propertyName, descriptor);
}

/* Hash table for prototype */

static const HashTableValue JSHTMLLIElementPrototypeTableValues[1] =
{
    { 0, 0, 0, 0 }
};

static JSC_CONST_HASHTABLE HashTable JSHTMLLIElementPrototypeTable =
#if ENABLE(PERFECT_HASH_SIZE)
    { 0, JSHTMLLIElementPrototypeTableValues, 0 };
#else
    { 1, 0, JSHTMLLIElementPrototypeTableValues, 0 };
#endif

const ClassInfo JSHTMLLIElementPrototype::s_info = { "HTMLLIElementPrototype", 0, &JSHTMLLIElementPrototypeTable, 0 };

JSObject* JSHTMLLIElementPrototype::self(ExecState* exec, JSGlobalObject* globalObject)
{
    return getDOMPrototype<JSHTMLLIElement>(exec, globalObject);
}

const ClassInfo JSHTMLLIElement::s_info = { "HTMLLIElement", &JSHTMLElement::s_info, &JSHTMLLIElementTable, 0 };

JSHTMLLIElement::JSHTMLLIElement(NonNullPassRefPtr<Structure> structure, JSDOMGlobalObject* globalObject, PassRefPtr<HTMLLIElement> impl)
    : JSHTMLElement(structure, globalObject, impl)
{
}

JSObject* JSHTMLLIElement::createPrototype(ExecState* exec, JSGlobalObject* globalObject)
{
    return new (exec) JSHTMLLIElementPrototype(JSHTMLLIElementPrototype::createStructure(JSHTMLElementPrototype::self(exec, globalObject)));
}

bool JSHTMLLIElement::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
{
    return getStaticValueSlot<JSHTMLLIElement, Base>(exec, &JSHTMLLIElementTable, this, propertyName, slot);
}

bool JSHTMLLIElement::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
{
    return getStaticValueDescriptor<JSHTMLLIElement, Base>(exec, &JSHTMLLIElementTable, this, propertyName, descriptor);
}

JSValue jsHTMLLIElementType(ExecState* exec, JSValue slotBase, const Identifier&)
{
    JSHTMLLIElement* castedThis = static_cast<JSHTMLLIElement*>(asObject(slotBase));
    UNUSED_PARAM(exec);
    HTMLLIElement* imp = static_cast<HTMLLIElement*>(castedThis->impl());
    JSValue result = jsString(exec, imp->type());
    return result;
}

JSValue jsHTMLLIElementValue(ExecState* exec, JSValue slotBase, const Identifier&)
{
    JSHTMLLIElement* castedThis = static_cast<JSHTMLLIElement*>(asObject(slotBase));
    UNUSED_PARAM(exec);
    HTMLLIElement* imp = static_cast<HTMLLIElement*>(castedThis->impl());
    JSValue result = jsNumber(exec, imp->value());
    return result;
}

JSValue jsHTMLLIElementConstructor(ExecState* exec, JSValue slotBase, const Identifier&)
{
    JSHTMLLIElement* domObject = static_cast<JSHTMLLIElement*>(asObject(slotBase));
    return JSHTMLLIElement::getConstructor(exec, domObject->globalObject());
}
void JSHTMLLIElement::put(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot)
{
    lookupPut<JSHTMLLIElement, Base>(exec, propertyName, value, &JSHTMLLIElementTable, this, slot);
}

void setJSHTMLLIElementType(ExecState* exec, JSObject* thisObject, JSValue value)
{
    JSHTMLLIElement* castedThisObj = static_cast<JSHTMLLIElement*>(thisObject);
    HTMLLIElement* imp = static_cast<HTMLLIElement*>(castedThisObj->impl());
    imp->setType(valueToStringWithNullCheck(exec, value));
}

void setJSHTMLLIElementValue(ExecState* exec, JSObject* thisObject, JSValue value)
{
    JSHTMLLIElement* castedThisObj = static_cast<JSHTMLLIElement*>(thisObject);
    HTMLLIElement* imp = static_cast<HTMLLIElement*>(castedThisObj->impl());
    imp->setValue(value.toInt32(exec));
}

JSValue JSHTMLLIElement::getConstructor(ExecState* exec, JSGlobalObject* globalObject)
{
    return getDOMConstructor<JSHTMLLIElementConstructor>(exec, static_cast<JSDOMGlobalObject*>(globalObject));
}


}
