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

#include "JSReadableStreamDefaultController.h"

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

using namespace JSC;

namespace WebCore {

// Functions


// Attributes

JSC::EncodedJSValue jsReadableStreamDefaultControllerConstructor(JSC::ExecState*, JSC::EncodedJSValue, JSC::PropertyName);
bool setJSReadableStreamDefaultControllerConstructor(JSC::ExecState*, JSC::EncodedJSValue, JSC::EncodedJSValue);

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

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

typedef JSDOMConstructor<JSReadableStreamDefaultController> JSReadableStreamDefaultControllerConstructor;

template<> JSC::EncodedJSValue JSC_HOST_CALL JSReadableStreamDefaultControllerConstructor::construct(JSC::ExecState* exec)
{
    ASSERT(exec);
    return constructJSReadableStreamDefaultController(*exec);
}

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

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

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

/* Hash table for prototype */

static const HashTableValue JSReadableStreamDefaultControllerPrototypeTableValues[] =
{
    { "constructor", DontEnum, NoIntrinsic, { (intptr_t)static_cast<PropertySlot::GetValueFunc>(jsReadableStreamDefaultControllerConstructor), (intptr_t) static_cast<PutPropertySlot::PutValueFunc>(setJSReadableStreamDefaultControllerConstructor) } },
    { "desiredSize", DontEnum | ReadOnly | Accessor | Builtin, NoIntrinsic, { (intptr_t)static_cast<BuiltinGenerator>(readableStreamDefaultControllerDesiredSizeCodeGenerator), (intptr_t) (0) } },
    { "enqueue", DontEnum | JSC::Builtin, NoIntrinsic, { (intptr_t)static_cast<BuiltinGenerator>(readableStreamDefaultControllerEnqueueCodeGenerator), (intptr_t) (0) } },
    { "close", DontEnum | JSC::Builtin, NoIntrinsic, { (intptr_t)static_cast<BuiltinGenerator>(readableStreamDefaultControllerCloseCodeGenerator), (intptr_t) (0) } },
    { "error", DontEnum | JSC::Builtin, NoIntrinsic, { (intptr_t)static_cast<BuiltinGenerator>(readableStreamDefaultControllerErrorCodeGenerator), (intptr_t) (0) } },
};

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

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

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

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

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

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

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

EncodedJSValue jsReadableStreamDefaultControllerConstructor(ExecState* state, EncodedJSValue thisValue, PropertyName)
{
    VM& vm = state->vm();
    auto throwScope = DECLARE_THROW_SCOPE(vm);
    JSReadableStreamDefaultControllerPrototype* domObject = jsDynamicCast<JSReadableStreamDefaultControllerPrototype*>(JSValue::decode(thisValue));
    if (UNLIKELY(!domObject))
        return throwVMTypeError(state, throwScope);
    JSValue constructor = JSReadableStreamDefaultControllerConstructor::create(state->vm(), JSReadableStreamDefaultControllerConstructor::createStructure(state->vm(), *domObject->globalObject(), domObject->globalObject()->objectPrototype()), *jsCast<JSDOMGlobalObject*>(domObject->globalObject()));
    // Shadowing constructor property to ensure reusing the same constructor object
    domObject->putDirect(state->vm(), state->propertyNames().constructor, constructor, DontEnum | ReadOnly);
    return JSValue::encode(constructor);
}

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


}

#endif // ENABLE(READABLE_STREAM_API)
