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

#include "AtomicString.h"
#include "JSNode.h"
#include "NamedNodeMap.h"
#include "Node.h"
#include <runtime/Error.h>
#include <runtime/JSNumberCell.h>
#include <runtime/PropertyNameArray.h>
#include <wtf/GetPtr.h>

using namespace JSC;

namespace WebCore {

ASSERT_CLASS_FITS_IN_CELL(JSNamedNodeMap);

/* Hash table */

static const HashTableValue JSNamedNodeMapTableValues[3] =
{
    { "length", DontDelete|ReadOnly, (intptr_t)static_cast<PropertySlot::GetValueFunc>(jsNamedNodeMapLength), (intptr_t)0 },
    { "constructor", DontEnum|ReadOnly, (intptr_t)static_cast<PropertySlot::GetValueFunc>(jsNamedNodeMapConstructor), (intptr_t)0 },
    { 0, 0, 0, 0 }
};

static JSC_CONST_HASHTABLE HashTable JSNamedNodeMapTable =
#if ENABLE(PERFECT_HASH_SIZE)
    { 15, JSNamedNodeMapTableValues, 0 };
#else
    { 5, 3, JSNamedNodeMapTableValues, 0 };
#endif

/* Hash table for constructor */

static const HashTableValue JSNamedNodeMapConstructorTableValues[1] =
{
    { 0, 0, 0, 0 }
};

static JSC_CONST_HASHTABLE HashTable JSNamedNodeMapConstructorTable =
#if ENABLE(PERFECT_HASH_SIZE)
    { 0, JSNamedNodeMapConstructorTableValues, 0 };
#else
    { 1, 0, JSNamedNodeMapConstructorTableValues, 0 };
#endif

class JSNamedNodeMapConstructor : public DOMConstructorObject {
public:
    JSNamedNodeMapConstructor(ExecState* exec, JSDOMGlobalObject* globalObject)
        : DOMConstructorObject(JSNamedNodeMapConstructor::createStructure(globalObject->objectPrototype()), globalObject)
    {
        putDirect(exec->propertyNames().prototype, JSNamedNodeMapPrototype::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 JSNamedNodeMapConstructor::s_info = { "NamedNodeMapConstructor", 0, &JSNamedNodeMapConstructorTable, 0 };

bool JSNamedNodeMapConstructor::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
{
    return getStaticValueSlot<JSNamedNodeMapConstructor, DOMObject>(exec, &JSNamedNodeMapConstructorTable, this, propertyName, slot);
}

bool JSNamedNodeMapConstructor::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
{
    return getStaticValueDescriptor<JSNamedNodeMapConstructor, DOMObject>(exec, &JSNamedNodeMapConstructorTable, this, propertyName, descriptor);
}

/* Hash table for prototype */

static const HashTableValue JSNamedNodeMapPrototypeTableValues[8] =
{
    { "getNamedItem", DontDelete|Function, (intptr_t)static_cast<NativeFunction>(jsNamedNodeMapPrototypeFunctionGetNamedItem), (intptr_t)1 },
    { "setNamedItem", DontDelete|Function, (intptr_t)static_cast<NativeFunction>(jsNamedNodeMapPrototypeFunctionSetNamedItem), (intptr_t)1 },
    { "removeNamedItem", DontDelete|Function, (intptr_t)static_cast<NativeFunction>(jsNamedNodeMapPrototypeFunctionRemoveNamedItem), (intptr_t)1 },
    { "item", DontDelete|Function, (intptr_t)static_cast<NativeFunction>(jsNamedNodeMapPrototypeFunctionItem), (intptr_t)1 },
    { "getNamedItemNS", DontDelete|Function, (intptr_t)static_cast<NativeFunction>(jsNamedNodeMapPrototypeFunctionGetNamedItemNS), (intptr_t)2 },
    { "setNamedItemNS", DontDelete|Function, (intptr_t)static_cast<NativeFunction>(jsNamedNodeMapPrototypeFunctionSetNamedItemNS), (intptr_t)1 },
    { "removeNamedItemNS", DontDelete|Function, (intptr_t)static_cast<NativeFunction>(jsNamedNodeMapPrototypeFunctionRemoveNamedItemNS), (intptr_t)2 },
    { 0, 0, 0, 0 }
};

static JSC_CONST_HASHTABLE HashTable JSNamedNodeMapPrototypeTable =
#if ENABLE(PERFECT_HASH_SIZE)
    { 15, JSNamedNodeMapPrototypeTableValues, 0 };
#else
    { 16, 15, JSNamedNodeMapPrototypeTableValues, 0 };
#endif

const ClassInfo JSNamedNodeMapPrototype::s_info = { "NamedNodeMapPrototype", 0, &JSNamedNodeMapPrototypeTable, 0 };

JSObject* JSNamedNodeMapPrototype::self(ExecState* exec, JSGlobalObject* globalObject)
{
    return getDOMPrototype<JSNamedNodeMap>(exec, globalObject);
}

bool JSNamedNodeMapPrototype::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
{
    return getStaticFunctionSlot<JSObject>(exec, &JSNamedNodeMapPrototypeTable, this, propertyName, slot);
}

bool JSNamedNodeMapPrototype::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
{
    return getStaticFunctionDescriptor<JSObject>(exec, &JSNamedNodeMapPrototypeTable, this, propertyName, descriptor);
}

const ClassInfo JSNamedNodeMap::s_info = { "NamedNodeMap", 0, &JSNamedNodeMapTable, 0 };

JSNamedNodeMap::JSNamedNodeMap(NonNullPassRefPtr<Structure> structure, JSDOMGlobalObject* globalObject, PassRefPtr<NamedNodeMap> impl)
    : DOMObjectWithGlobalPointer(structure, globalObject)
    , m_impl(impl)
{
}

JSNamedNodeMap::~JSNamedNodeMap()
{
    forgetDOMObject(this, impl());
}

JSObject* JSNamedNodeMap::createPrototype(ExecState* exec, JSGlobalObject* globalObject)
{
    return new (exec) JSNamedNodeMapPrototype(JSNamedNodeMapPrototype::createStructure(globalObject->objectPrototype()));
}

bool JSNamedNodeMap::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
{
    JSValue proto = prototype();
    if (proto.isObject() && static_cast<JSObject*>(asObject(proto))->hasProperty(exec, propertyName))
        return false;

    const HashEntry* entry = JSNamedNodeMapTable.entry(exec, propertyName);
    if (entry) {
        slot.setCustom(this, entry->propertyGetter());
        return true;
    }
    bool ok;
    unsigned index = propertyName.toUInt32(&ok, false);
    if (ok && index < static_cast<NamedNodeMap*>(impl())->length()) {
        slot.setCustomIndex(this, index, indexGetter);
        return true;
    }
    if (canGetItemsForName(exec, static_cast<NamedNodeMap*>(impl()), propertyName)) {
        slot.setCustom(this, nameGetter);
        return true;
    }
    return getStaticValueSlot<JSNamedNodeMap, Base>(exec, &JSNamedNodeMapTable, this, propertyName, slot);
}

bool JSNamedNodeMap::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
{
    JSValue proto = prototype();
    if (proto.isObject() && static_cast<JSObject*>(asObject(proto))->hasProperty(exec, propertyName))
        return false;

    const HashEntry* entry = JSNamedNodeMapTable.entry(exec, propertyName);
    if (entry) {
        PropertySlot slot;
        slot.setCustom(this, entry->propertyGetter());
        descriptor.setDescriptor(slot.getValue(exec, propertyName), entry->attributes());
        return true;
    }
    bool ok;
    unsigned index = propertyName.toUInt32(&ok, false);
    if (ok && index < static_cast<NamedNodeMap*>(impl())->length()) {
        PropertySlot slot;
        slot.setCustomIndex(this, index, indexGetter);
        descriptor.setDescriptor(slot.getValue(exec, propertyName), DontDelete | ReadOnly);
        return true;
    }
    if (canGetItemsForName(exec, static_cast<NamedNodeMap*>(impl()), propertyName)) {
        PropertySlot slot;
        slot.setCustom(this, nameGetter);
        descriptor.setDescriptor(slot.getValue(exec, propertyName), ReadOnly | DontDelete | DontEnum);
        return true;
    }
    return getStaticValueDescriptor<JSNamedNodeMap, Base>(exec, &JSNamedNodeMapTable, this, propertyName, descriptor);
}

bool JSNamedNodeMap::getOwnPropertySlot(ExecState* exec, unsigned propertyName, PropertySlot& slot)
{
    if (propertyName < static_cast<NamedNodeMap*>(impl())->length()) {
        slot.setCustomIndex(this, propertyName, indexGetter);
        return true;
    }
    return getOwnPropertySlot(exec, Identifier::from(exec, propertyName), slot);
}

JSValue jsNamedNodeMapLength(ExecState* exec, JSValue slotBase, const Identifier&)
{
    JSNamedNodeMap* castedThis = static_cast<JSNamedNodeMap*>(asObject(slotBase));
    UNUSED_PARAM(exec);
    NamedNodeMap* imp = static_cast<NamedNodeMap*>(castedThis->impl());
    JSValue result = jsNumber(exec, imp->length());
    return result;
}

JSValue jsNamedNodeMapConstructor(ExecState* exec, JSValue slotBase, const Identifier&)
{
    JSNamedNodeMap* domObject = static_cast<JSNamedNodeMap*>(asObject(slotBase));
    return JSNamedNodeMap::getConstructor(exec, domObject->globalObject());
}
void JSNamedNodeMap::getOwnPropertyNames(ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode)
{
    for (unsigned i = 0; i < static_cast<NamedNodeMap*>(impl())->length(); ++i)
        propertyNames.add(Identifier::from(exec, i));
     Base::getOwnPropertyNames(exec, propertyNames, mode);
}

JSValue JSNamedNodeMap::getConstructor(ExecState* exec, JSGlobalObject* globalObject)
{
    return getDOMConstructor<JSNamedNodeMapConstructor>(exec, static_cast<JSDOMGlobalObject*>(globalObject));
}

JSValue JSC_HOST_CALL jsNamedNodeMapPrototypeFunctionGetNamedItem(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
{
    UNUSED_PARAM(args);
    if (!thisValue.inherits(&JSNamedNodeMap::s_info))
        return throwError(exec, TypeError);
    JSNamedNodeMap* castedThisObj = static_cast<JSNamedNodeMap*>(asObject(thisValue));
    NamedNodeMap* imp = static_cast<NamedNodeMap*>(castedThisObj->impl());
    const UString& name = args.at(0).toString(exec);


    JSC::JSValue result = toJS(exec, castedThisObj->globalObject(), WTF::getPtr(imp->getNamedItem(name)));
    return result;
}

JSValue JSC_HOST_CALL jsNamedNodeMapPrototypeFunctionSetNamedItem(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
{
    UNUSED_PARAM(args);
    if (!thisValue.inherits(&JSNamedNodeMap::s_info))
        return throwError(exec, TypeError);
    JSNamedNodeMap* castedThisObj = static_cast<JSNamedNodeMap*>(asObject(thisValue));
    return castedThisObj->setNamedItem(exec, args);
}

JSValue JSC_HOST_CALL jsNamedNodeMapPrototypeFunctionRemoveNamedItem(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
{
    UNUSED_PARAM(args);
    if (!thisValue.inherits(&JSNamedNodeMap::s_info))
        return throwError(exec, TypeError);
    JSNamedNodeMap* castedThisObj = static_cast<JSNamedNodeMap*>(asObject(thisValue));
    NamedNodeMap* imp = static_cast<NamedNodeMap*>(castedThisObj->impl());
    ExceptionCode ec = 0;
    const UString& name = args.at(0).toString(exec);


    JSC::JSValue result = toJS(exec, castedThisObj->globalObject(), WTF::getPtr(imp->removeNamedItem(name, ec)));
    setDOMException(exec, ec);
    return result;
}

JSValue JSC_HOST_CALL jsNamedNodeMapPrototypeFunctionItem(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
{
    UNUSED_PARAM(args);
    if (!thisValue.inherits(&JSNamedNodeMap::s_info))
        return throwError(exec, TypeError);
    JSNamedNodeMap* castedThisObj = static_cast<JSNamedNodeMap*>(asObject(thisValue));
    NamedNodeMap* imp = static_cast<NamedNodeMap*>(castedThisObj->impl());
    unsigned index = args.at(0).toInt32(exec);


    JSC::JSValue result = toJS(exec, castedThisObj->globalObject(), WTF::getPtr(imp->item(index)));
    return result;
}

JSValue JSC_HOST_CALL jsNamedNodeMapPrototypeFunctionGetNamedItemNS(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
{
    UNUSED_PARAM(args);
    if (!thisValue.inherits(&JSNamedNodeMap::s_info))
        return throwError(exec, TypeError);
    JSNamedNodeMap* castedThisObj = static_cast<JSNamedNodeMap*>(asObject(thisValue));
    NamedNodeMap* imp = static_cast<NamedNodeMap*>(castedThisObj->impl());
    const UString& namespaceURI = valueToStringWithNullCheck(exec, args.at(0));
    const UString& localName = args.at(1).toString(exec);


    JSC::JSValue result = toJS(exec, castedThisObj->globalObject(), WTF::getPtr(imp->getNamedItemNS(namespaceURI, localName)));
    return result;
}

JSValue JSC_HOST_CALL jsNamedNodeMapPrototypeFunctionSetNamedItemNS(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
{
    UNUSED_PARAM(args);
    if (!thisValue.inherits(&JSNamedNodeMap::s_info))
        return throwError(exec, TypeError);
    JSNamedNodeMap* castedThisObj = static_cast<JSNamedNodeMap*>(asObject(thisValue));
    return castedThisObj->setNamedItemNS(exec, args);
}

JSValue JSC_HOST_CALL jsNamedNodeMapPrototypeFunctionRemoveNamedItemNS(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
{
    UNUSED_PARAM(args);
    if (!thisValue.inherits(&JSNamedNodeMap::s_info))
        return throwError(exec, TypeError);
    JSNamedNodeMap* castedThisObj = static_cast<JSNamedNodeMap*>(asObject(thisValue));
    NamedNodeMap* imp = static_cast<NamedNodeMap*>(castedThisObj->impl());
    ExceptionCode ec = 0;
    const UString& namespaceURI = valueToStringWithNullCheck(exec, args.at(0));
    const UString& localName = args.at(1).toString(exec);


    JSC::JSValue result = toJS(exec, castedThisObj->globalObject(), WTF::getPtr(imp->removeNamedItemNS(namespaceURI, localName, ec)));
    setDOMException(exec, ec);
    return result;
}


JSValue JSNamedNodeMap::indexGetter(ExecState* exec, JSValue slotBase, unsigned index)
{
    JSNamedNodeMap* thisObj = static_cast<JSNamedNodeMap*>(asObject(slotBase));
    return toJS(exec, thisObj->globalObject(), static_cast<NamedNodeMap*>(thisObj->impl())->item(index));
}
JSC::JSValue toJS(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, NamedNodeMap* object)
{
    return getDOMObjectWrapper<JSNamedNodeMap>(exec, globalObject, object);
}
NamedNodeMap* toNamedNodeMap(JSC::JSValue value)
{
    return value.inherits(&JSNamedNodeMap::s_info) ? static_cast<JSNamedNodeMap*>(asObject(value))->impl() : 0;
}

}
