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

#include "JSChannelMergerNode.h"

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

using namespace JSC;

namespace WebCore {

// Attributes

JSC::EncodedJSValue jsChannelMergerNodeConstructor(JSC::ExecState*, JSC::EncodedJSValue, JSC::PropertyName);
bool setJSChannelMergerNodeConstructor(JSC::ExecState*, JSC::EncodedJSValue, JSC::EncodedJSValue);

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

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

typedef JSDOMConstructorNotConstructable<JSChannelMergerNode> JSChannelMergerNodeConstructor;

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

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

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

/* Hash table for prototype */

static const HashTableValue JSChannelMergerNodePrototypeTableValues[] =
{
    { "constructor", DontEnum, NoIntrinsic, { (intptr_t)static_cast<PropertySlot::GetValueFunc>(jsChannelMergerNodeConstructor), (intptr_t) static_cast<PutPropertySlot::PutValueFunc>(setJSChannelMergerNodeConstructor) } },
};

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

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

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

JSChannelMergerNode::JSChannelMergerNode(Structure* structure, JSDOMGlobalObject& globalObject, Ref<ChannelMergerNode>&& impl)
    : JSAudioNode(structure, globalObject, WTFMove(impl))
{
}

JSObject* JSChannelMergerNode::createPrototype(VM& vm, JSGlobalObject* globalObject)
{
    return JSChannelMergerNodePrototype::create(vm, globalObject, JSChannelMergerNodePrototype::createStructure(vm, globalObject, JSAudioNode::prototype(vm, globalObject)));
}

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

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

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

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

#if ENABLE(BINDING_INTEGRITY)
#if PLATFORM(WIN)
#pragma warning(disable: 4483)
extern "C" { extern void (*const __identifier("??_7ChannelMergerNode@WebCore@@6B@")[])(); }
#else
extern "C" { extern void* _ZTVN7WebCore17ChannelMergerNodeE[]; }
#endif
#endif

JSC::JSValue toJSNewlyCreated(JSC::ExecState*, JSDOMGlobalObject* globalObject, Ref<ChannelMergerNode>&& impl)
{

#if ENABLE(BINDING_INTEGRITY)
    void* actualVTablePointer = *(reinterpret_cast<void**>(impl.ptr()));
#if PLATFORM(WIN)
    void* expectedVTablePointer = reinterpret_cast<void*>(__identifier("??_7ChannelMergerNode@WebCore@@6B@"));
#else
    void* expectedVTablePointer = &_ZTVN7WebCore17ChannelMergerNodeE[2];
#if COMPILER(CLANG)
    // If this fails ChannelMergerNode does not have a vtable, so you need to add the
    // ImplementationLacksVTable attribute to the interface definition
    static_assert(__is_polymorphic(ChannelMergerNode), "ChannelMergerNode is not polymorphic");
#endif
#endif
    // If you hit this assertion you either have a use after free bug, or
    // ChannelMergerNode has subclasses. If ChannelMergerNode has subclasses that get passed
    // to toJS() we currently require ChannelMergerNode you to opt out of binding hardening
    // by adding the SkipVTableValidation attribute to the interface IDL definition
    RELEASE_ASSERT(actualVTablePointer == expectedVTablePointer);
#endif
    return createWrapper<ChannelMergerNode>(globalObject, WTFMove(impl));
}

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


}

#endif // ENABLE(WEB_AUDIO)
