/*
    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"

#if ENABLE(READABLE_STREAM_API) || ENABLE(WRITABLE_STREAM_API)

#include "JSCountQueuingStrategy.h"

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

using namespace JSC;

namespace WebCore {

// Functions


// Attributes

JSC::EncodedJSValue jsCountQueuingStrategyConstructor(JSC::ExecState*, JSC::EncodedJSValue, JSC::PropertyName);
bool setJSCountQueuingStrategyConstructor(JSC::ExecState*, JSC::EncodedJSValue, JSC::EncodedJSValue);

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

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

typedef JSBuiltinConstructor<JSCountQueuingStrategy> JSCountQueuingStrategyConstructor;

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

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

template<> FunctionExecutable* JSCountQueuingStrategyConstructor::initializeExecutable(VM& vm)
{
    return countQueuingStrategyInitializeCountQueuingStrategyCodeGenerator(vm);
}

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

/* Hash table for prototype */

static const HashTableValue JSCountQueuingStrategyPrototypeTableValues[] =
{
    { "constructor", DontEnum, NoIntrinsic, { (intptr_t)static_cast<PropertySlot::GetValueFunc>(jsCountQueuingStrategyConstructor), (intptr_t) static_cast<PutPropertySlot::PutValueFunc>(setJSCountQueuingStrategyConstructor) } },
    { "size", JSC::Builtin, NoIntrinsic, { (intptr_t)static_cast<BuiltinGenerator>(countQueuingStrategySizeCodeGenerator), (intptr_t) (0) } },
};

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

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

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

JSCountQueuingStrategy::JSCountQueuingStrategy(Structure* structure, JSDOMGlobalObject& globalObject)
    : JSDOMObject(structure, globalObject) { }

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

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

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

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

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

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

void JSCountQueuingStrategy::visitChildren(JSCell* cell, SlotVisitor& visitor)
{
    auto* thisObject = jsCast<JSCountQueuingStrategy*>(cell);
    ASSERT_GC_OBJECT_INHERITS(thisObject, info());
    Base::visitChildren(thisObject, visitor);
}


}

#endif // ENABLE(READABLE_STREAM_API) || ENABLE(WRITABLE_STREAM_API)
