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

#include "ExceptionCode.h"
#include "JSDOMBinding.h"
#include "JSDOMConstructor.h"
#include "JSDOMConvert.h"
#include <runtime/FunctionPrototype.h>
#include <wtf/GetPtr.h>

using namespace JSC;

namespace WebCore {

// Attributes

JSC::EncodedJSValue jsSVGAnimatedEnumerationBaseVal(JSC::ExecState*, JSC::EncodedJSValue, JSC::PropertyName);
bool setJSSVGAnimatedEnumerationBaseVal(JSC::ExecState*, JSC::EncodedJSValue, JSC::EncodedJSValue);
JSC::EncodedJSValue jsSVGAnimatedEnumerationAnimVal(JSC::ExecState*, JSC::EncodedJSValue, JSC::PropertyName);
JSC::EncodedJSValue jsSVGAnimatedEnumerationConstructor(JSC::ExecState*, JSC::EncodedJSValue, JSC::PropertyName);
bool setJSSVGAnimatedEnumerationConstructor(JSC::ExecState*, JSC::EncodedJSValue, JSC::EncodedJSValue);

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

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

typedef JSDOMConstructorNotConstructable<JSSVGAnimatedEnumeration> JSSVGAnimatedEnumerationConstructor;

template<> JSValue JSSVGAnimatedEnumerationConstructor::prototypeForStructure(JSC::VM& vm, const JSDOMGlobalObject& globalObject)
{
    UNUSED_PARAM(vm);
    return globalObject.functionPrototype();
}

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

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

/* Hash table for prototype */

static const HashTableValue JSSVGAnimatedEnumerationPrototypeTableValues[] =
{
    { "constructor", DontEnum, NoIntrinsic, { (intptr_t)static_cast<PropertySlot::GetValueFunc>(jsSVGAnimatedEnumerationConstructor), (intptr_t) static_cast<PutPropertySlot::PutValueFunc>(setJSSVGAnimatedEnumerationConstructor) } },
    { "baseVal", CustomAccessor, NoIntrinsic, { (intptr_t)static_cast<PropertySlot::GetValueFunc>(jsSVGAnimatedEnumerationBaseVal), (intptr_t) static_cast<PutPropertySlot::PutValueFunc>(setJSSVGAnimatedEnumerationBaseVal) } },
    { "animVal", ReadOnly | CustomAccessor, NoIntrinsic, { (intptr_t)static_cast<PropertySlot::GetValueFunc>(jsSVGAnimatedEnumerationAnimVal), (intptr_t) static_cast<PutPropertySlot::PutValueFunc>(0) } },
};

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

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

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

JSSVGAnimatedEnumeration::JSSVGAnimatedEnumeration(Structure* structure, JSDOMGlobalObject& globalObject, Ref<SVGAnimatedEnumeration>&& impl)
    : JSDOMWrapper<SVGAnimatedEnumeration>(structure, globalObject, WTFMove(impl))
{
}

JSObject* JSSVGAnimatedEnumeration::createPrototype(VM& vm, JSGlobalObject* globalObject)
{
    return JSSVGAnimatedEnumerationPrototype::create(vm, globalObject, JSSVGAnimatedEnumerationPrototype::createStructure(vm, globalObject, globalObject->objectPrototype()));
}

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

void JSSVGAnimatedEnumeration::destroy(JSC::JSCell* cell)
{
    JSSVGAnimatedEnumeration* thisObject = static_cast<JSSVGAnimatedEnumeration*>(cell);
    thisObject->JSSVGAnimatedEnumeration::~JSSVGAnimatedEnumeration();
}

EncodedJSValue jsSVGAnimatedEnumerationBaseVal(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<JSSVGAnimatedEnumeration*>(decodedThisValue);
    if (UNLIKELY(!castedThis)) {
        return throwGetterTypeError(*state, throwScope, "SVGAnimatedEnumeration", "baseVal");
    }
    auto& impl = castedThis->wrapped();
    JSValue result = jsNumber(impl.baseVal());
    return JSValue::encode(result);
}


EncodedJSValue jsSVGAnimatedEnumerationAnimVal(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<JSSVGAnimatedEnumeration*>(decodedThisValue);
    if (UNLIKELY(!castedThis)) {
        return throwGetterTypeError(*state, throwScope, "SVGAnimatedEnumeration", "animVal");
    }
    auto& impl = castedThis->wrapped();
    JSValue result = jsNumber(impl.animVal());
    return JSValue::encode(result);
}


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

bool setJSSVGAnimatedEnumerationConstructor(ExecState* state, EncodedJSValue thisValue, EncodedJSValue encodedValue)
{
    VM& vm = state->vm();
    auto throwScope = DECLARE_THROW_SCOPE(vm);
    JSValue value = JSValue::decode(encodedValue);
    JSSVGAnimatedEnumerationPrototype* domObject = jsDynamicCast<JSSVGAnimatedEnumerationPrototype*>(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 setJSSVGAnimatedEnumerationBaseVal(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);
    JSSVGAnimatedEnumeration* castedThis = jsDynamicCast<JSSVGAnimatedEnumeration*>(JSValue::decode(thisValue));
    if (UNLIKELY(!castedThis)) {
        return throwSetterTypeError(*state, throwScope, "SVGAnimatedEnumeration", "baseVal");
    }
    auto& impl = castedThis->wrapped();
    ExceptionCode ec = 0;
    auto nativeValue = convert<uint16_t>(*state, value, NormalConversion);
    RETURN_IF_EXCEPTION(throwScope, false);
    impl.setBaseVal(WTFMove(nativeValue), ec);
    setDOMException(state, throwScope, ec);
    return true;
}


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

bool JSSVGAnimatedEnumerationOwner::isReachableFromOpaqueRoots(JSC::Handle<JSC::Unknown> handle, void*, SlotVisitor& visitor)
{
    UNUSED_PARAM(handle);
    UNUSED_PARAM(visitor);
    return false;
}

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

JSC::JSValue toJSNewlyCreated(JSC::ExecState*, JSDOMGlobalObject* globalObject, Ref<SVGAnimatedEnumeration>&& impl)
{
    return createWrapper<SVGAnimatedEnumeration>(globalObject, WTFMove(impl));
}

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

SVGAnimatedEnumeration* JSSVGAnimatedEnumeration::toWrapped(JSC::JSValue value)
{
    if (auto* wrapper = jsDynamicCast<JSSVGAnimatedEnumeration*>(value))
        return &wrapper->wrapped();
    return nullptr;
}

}
