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

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

using namespace JSC;

namespace WebCore {

// Functions


// Attributes

JSC::EncodedJSValue jsByteLengthQueuingStrategyConstructor(JSC::ExecState*, JSC::EncodedJSValue, JSC::PropertyName);
bool setJSByteLengthQueuingStrategyConstructor(JSC::ExecState*, JSC::EncodedJSValue, JSC::EncodedJSValue);

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

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

typedef JSBuiltinConstructor<JSByteLengthQueuingStrategy> JSByteLengthQueuingStrategyConstructor;

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

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

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

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

/* Hash table for prototype */

static const HashTableValue JSByteLengthQueuingStrategyPrototypeTableValues[] =
{
    { "constructor", DontEnum, NoIntrinsic, { (intptr_t)static_cast<PropertySlot::GetValueFunc>(jsByteLengthQueuingStrategyConstructor), (intptr_t) static_cast<PutPropertySlot::PutValueFunc>(setJSByteLengthQueuingStrategyConstructor) } },
    { "size", JSC::Builtin, NoIntrinsic, { (intptr_t)static_cast<BuiltinGenerator>(byteLengthQueuingStrategySizeCodeGenerator), (intptr_t) (0) } },
};

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

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

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

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

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

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

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

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

bool setJSByteLengthQueuingStrategyConstructor(ExecState* state, EncodedJSValue thisValue, EncodedJSValue encodedValue)
{
    VM& vm = state->vm();
    auto throwScope = DECLARE_THROW_SCOPE(vm);
    JSValue value = JSValue::decode(encodedValue);
    JSByteLengthQueuingStrategyPrototype* domObject = jsDynamicCast<JSByteLengthQueuingStrategyPrototype*>(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 JSByteLengthQueuingStrategy::getConstructor(VM& vm, const JSGlobalObject* globalObject)
{
    return getDOMConstructor<JSByteLengthQueuingStrategyConstructor>(vm, *jsCast<const JSDOMGlobalObject*>(globalObject));
}

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


}

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