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

#include "JSDOMBinding.h"
#include "JSDOMConstructor.h"
#include <runtime/PropertyNameArray.h>
#include <wtf/GetPtr.h>

using namespace JSC;

namespace WebCore {

// Attributes

JSC::EncodedJSValue jsWebKitCSSFilterValueOperationType(JSC::ExecState*, JSC::EncodedJSValue, JSC::PropertyName);
JSC::EncodedJSValue jsWebKitCSSFilterValueConstructor(JSC::ExecState*, JSC::EncodedJSValue, JSC::PropertyName);
bool setJSWebKitCSSFilterValueConstructor(JSC::ExecState*, JSC::EncodedJSValue, JSC::EncodedJSValue);

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

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

typedef JSDOMConstructorNotConstructable<JSWebKitCSSFilterValue> JSWebKitCSSFilterValueConstructor;

/* Hash table for constructor */

static const HashTableValue JSWebKitCSSFilterValueConstructorTableValues[] =
{
    { "CSS_FILTER_REFERENCE", DontDelete | ReadOnly | ConstantInteger, NoIntrinsic, { (long long)(1) } },
    { "CSS_FILTER_GRAYSCALE", DontDelete | ReadOnly | ConstantInteger, NoIntrinsic, { (long long)(2) } },
    { "CSS_FILTER_SEPIA", DontDelete | ReadOnly | ConstantInteger, NoIntrinsic, { (long long)(3) } },
    { "CSS_FILTER_SATURATE", DontDelete | ReadOnly | ConstantInteger, NoIntrinsic, { (long long)(4) } },
    { "CSS_FILTER_HUE_ROTATE", DontDelete | ReadOnly | ConstantInteger, NoIntrinsic, { (long long)(5) } },
    { "CSS_FILTER_INVERT", DontDelete | ReadOnly | ConstantInteger, NoIntrinsic, { (long long)(6) } },
    { "CSS_FILTER_OPACITY", DontDelete | ReadOnly | ConstantInteger, NoIntrinsic, { (long long)(7) } },
    { "CSS_FILTER_BRIGHTNESS", DontDelete | ReadOnly | ConstantInteger, NoIntrinsic, { (long long)(8) } },
    { "CSS_FILTER_CONTRAST", DontDelete | ReadOnly | ConstantInteger, NoIntrinsic, { (long long)(9) } },
    { "CSS_FILTER_BLUR", DontDelete | ReadOnly | ConstantInteger, NoIntrinsic, { (long long)(10) } },
    { "CSS_FILTER_DROP_SHADOW", DontDelete | ReadOnly | ConstantInteger, NoIntrinsic, { (long long)(11) } },
};

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

template<> void JSWebKitCSSFilterValueConstructor::initializeProperties(VM& vm, JSDOMGlobalObject& globalObject)
{
    putDirect(vm, vm.propertyNames->prototype, JSWebKitCSSFilterValue::prototype(vm, &globalObject), DontDelete | ReadOnly | DontEnum);
    putDirect(vm, vm.propertyNames->name, jsNontrivialString(&vm, String(ASCIILiteral("WebKitCSSFilterValue"))), ReadOnly | DontEnum);
    putDirect(vm, vm.propertyNames->length, jsNumber(0), ReadOnly | DontEnum);
    reifyStaticProperties(vm, JSWebKitCSSFilterValueConstructorTableValues, *this);
}

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

/* Hash table for prototype */

static const HashTableValue JSWebKitCSSFilterValuePrototypeTableValues[] =
{
    { "constructor", DontEnum, NoIntrinsic, { (intptr_t)static_cast<PropertySlot::GetValueFunc>(jsWebKitCSSFilterValueConstructor), (intptr_t) static_cast<PutPropertySlot::PutValueFunc>(setJSWebKitCSSFilterValueConstructor) } },
    { "operationType", ReadOnly | CustomAccessor, NoIntrinsic, { (intptr_t)static_cast<PropertySlot::GetValueFunc>(jsWebKitCSSFilterValueOperationType), (intptr_t) static_cast<PutPropertySlot::PutValueFunc>(0) } },
    { "CSS_FILTER_REFERENCE", DontDelete | ReadOnly | ConstantInteger, NoIntrinsic, { (long long)(1) } },
    { "CSS_FILTER_GRAYSCALE", DontDelete | ReadOnly | ConstantInteger, NoIntrinsic, { (long long)(2) } },
    { "CSS_FILTER_SEPIA", DontDelete | ReadOnly | ConstantInteger, NoIntrinsic, { (long long)(3) } },
    { "CSS_FILTER_SATURATE", DontDelete | ReadOnly | ConstantInteger, NoIntrinsic, { (long long)(4) } },
    { "CSS_FILTER_HUE_ROTATE", DontDelete | ReadOnly | ConstantInteger, NoIntrinsic, { (long long)(5) } },
    { "CSS_FILTER_INVERT", DontDelete | ReadOnly | ConstantInteger, NoIntrinsic, { (long long)(6) } },
    { "CSS_FILTER_OPACITY", DontDelete | ReadOnly | ConstantInteger, NoIntrinsic, { (long long)(7) } },
    { "CSS_FILTER_BRIGHTNESS", DontDelete | ReadOnly | ConstantInteger, NoIntrinsic, { (long long)(8) } },
    { "CSS_FILTER_CONTRAST", DontDelete | ReadOnly | ConstantInteger, NoIntrinsic, { (long long)(9) } },
    { "CSS_FILTER_BLUR", DontDelete | ReadOnly | ConstantInteger, NoIntrinsic, { (long long)(10) } },
    { "CSS_FILTER_DROP_SHADOW", DontDelete | ReadOnly | ConstantInteger, NoIntrinsic, { (long long)(11) } },
};

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

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

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

JSWebKitCSSFilterValue::JSWebKitCSSFilterValue(Structure* structure, JSDOMGlobalObject& globalObject, Ref<WebKitCSSFilterValue>&& impl)
    : JSCSSValueList(structure, globalObject, WTFMove(impl))
{
}

JSObject* JSWebKitCSSFilterValue::createPrototype(VM& vm, JSGlobalObject* globalObject)
{
    return JSWebKitCSSFilterValuePrototype::create(vm, globalObject, JSWebKitCSSFilterValuePrototype::createStructure(vm, globalObject, JSCSSValueList::prototype(vm, globalObject)));
}

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

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


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

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

void JSWebKitCSSFilterValue::getOwnPropertyNames(JSObject* object, ExecState* state, PropertyNameArray& propertyNames, EnumerationMode mode)
{
    auto* thisObject = jsCast<JSWebKitCSSFilterValue*>(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 JSWebKitCSSFilterValue::getConstructor(VM& vm, const JSGlobalObject* globalObject)
{
    return getDOMConstructor<JSWebKitCSSFilterValueConstructor>(vm, *jsCast<const JSDOMGlobalObject*>(globalObject));
}


}
