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

#include "CSSMutableStyleDeclaration.h"
#include "CSSStyleDeclaration.h"
#include "JSCSSStyleDeclaration.h"
#include "KURL.h"
#include "WebKitCSSKeyframeRule.h"
#include <runtime/JSString.h>
#include <wtf/GetPtr.h>

using namespace JSC;

namespace WebCore {

ASSERT_CLASS_FITS_IN_CELL(JSWebKitCSSKeyframeRule);

/* Hash table */

static const HashTableValue JSWebKitCSSKeyframeRuleTableValues[4] =
{
    { "keyText", DontDelete, (intptr_t)static_cast<PropertySlot::GetValueFunc>(jsWebKitCSSKeyframeRuleKeyText), (intptr_t)setJSWebKitCSSKeyframeRuleKeyText },
    { "style", DontDelete|ReadOnly, (intptr_t)static_cast<PropertySlot::GetValueFunc>(jsWebKitCSSKeyframeRuleStyle), (intptr_t)0 },
    { "constructor", DontEnum|ReadOnly, (intptr_t)static_cast<PropertySlot::GetValueFunc>(jsWebKitCSSKeyframeRuleConstructor), (intptr_t)0 },
    { 0, 0, 0, 0 }
};

static JSC_CONST_HASHTABLE HashTable JSWebKitCSSKeyframeRuleTable =
#if ENABLE(PERFECT_HASH_SIZE)
    { 15, JSWebKitCSSKeyframeRuleTableValues, 0 };
#else
    { 9, 7, JSWebKitCSSKeyframeRuleTableValues, 0 };
#endif

/* Hash table for constructor */

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

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

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

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

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

/* Hash table for prototype */

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

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

const ClassInfo JSWebKitCSSKeyframeRulePrototype::s_info = { "WebKitCSSKeyframeRulePrototype", 0, &JSWebKitCSSKeyframeRulePrototypeTable, 0 };

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

const ClassInfo JSWebKitCSSKeyframeRule::s_info = { "WebKitCSSKeyframeRule", &JSCSSRule::s_info, &JSWebKitCSSKeyframeRuleTable, 0 };

JSWebKitCSSKeyframeRule::JSWebKitCSSKeyframeRule(NonNullPassRefPtr<Structure> structure, JSDOMGlobalObject* globalObject, PassRefPtr<WebKitCSSKeyframeRule> impl)
    : JSCSSRule(structure, globalObject, impl)
{
}

JSObject* JSWebKitCSSKeyframeRule::createPrototype(ExecState* exec, JSGlobalObject* globalObject)
{
    return new (exec) JSWebKitCSSKeyframeRulePrototype(JSWebKitCSSKeyframeRulePrototype::createStructure(JSCSSRulePrototype::self(exec, globalObject)));
}

bool JSWebKitCSSKeyframeRule::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
{
    return getStaticValueSlot<JSWebKitCSSKeyframeRule, Base>(exec, &JSWebKitCSSKeyframeRuleTable, this, propertyName, slot);
}

bool JSWebKitCSSKeyframeRule::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
{
    return getStaticValueDescriptor<JSWebKitCSSKeyframeRule, Base>(exec, &JSWebKitCSSKeyframeRuleTable, this, propertyName, descriptor);
}

JSValue jsWebKitCSSKeyframeRuleKeyText(ExecState* exec, JSValue slotBase, const Identifier&)
{
    JSWebKitCSSKeyframeRule* castedThis = static_cast<JSWebKitCSSKeyframeRule*>(asObject(slotBase));
    UNUSED_PARAM(exec);
    WebKitCSSKeyframeRule* imp = static_cast<WebKitCSSKeyframeRule*>(castedThis->impl());
    JSValue result = jsString(exec, imp->keyText());
    return result;
}

JSValue jsWebKitCSSKeyframeRuleStyle(ExecState* exec, JSValue slotBase, const Identifier&)
{
    JSWebKitCSSKeyframeRule* castedThis = static_cast<JSWebKitCSSKeyframeRule*>(asObject(slotBase));
    UNUSED_PARAM(exec);
    WebKitCSSKeyframeRule* imp = static_cast<WebKitCSSKeyframeRule*>(castedThis->impl());
    JSValue result = toJS(exec, castedThis->globalObject(), WTF::getPtr(imp->style()));
    return result;
}

JSValue jsWebKitCSSKeyframeRuleConstructor(ExecState* exec, JSValue slotBase, const Identifier&)
{
    JSWebKitCSSKeyframeRule* domObject = static_cast<JSWebKitCSSKeyframeRule*>(asObject(slotBase));
    return JSWebKitCSSKeyframeRule::getConstructor(exec, domObject->globalObject());
}
void JSWebKitCSSKeyframeRule::put(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot)
{
    lookupPut<JSWebKitCSSKeyframeRule, Base>(exec, propertyName, value, &JSWebKitCSSKeyframeRuleTable, this, slot);
}

void setJSWebKitCSSKeyframeRuleKeyText(ExecState* exec, JSObject* thisObject, JSValue value)
{
    JSWebKitCSSKeyframeRule* castedThisObj = static_cast<JSWebKitCSSKeyframeRule*>(thisObject);
    WebKitCSSKeyframeRule* imp = static_cast<WebKitCSSKeyframeRule*>(castedThisObj->impl());
    imp->setKeyText(value.toString(exec));
}

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


}
