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

#include "Element.h"
#include "ExceptionCode.h"
#include "HTMLOptionElement.h"
#include "JSDOMBinding.h"
#include "JSDOMConstructor.h"
#include "JSDOMConvert.h"
#include "JSHTMLElement.h"
#include "JSHTMLOptionElement.h"
#include "JSNode.h"
#include "JSNodeCustom.h"
#include "Node.h"
#include "wtf/text/AtomicString.h"
#include <runtime/Error.h>
#include <runtime/PropertyNameArray.h>
#include <wtf/GetPtr.h>

using namespace JSC;

namespace WebCore {

// Functions

JSC::EncodedJSValue JSC_HOST_CALL jsHTMLOptionsCollectionPrototypeFunctionItem(JSC::ExecState*);
JSC::EncodedJSValue JSC_HOST_CALL jsHTMLOptionsCollectionPrototypeFunctionNamedItem(JSC::ExecState*);
JSC::EncodedJSValue JSC_HOST_CALL jsHTMLOptionsCollectionPrototypeFunctionAdd(JSC::ExecState*);
JSC::EncodedJSValue JSC_HOST_CALL jsHTMLOptionsCollectionPrototypeFunctionRemove(JSC::ExecState*);

// Attributes

JSC::EncodedJSValue jsHTMLOptionsCollectionSelectedIndex(JSC::ExecState*, JSC::EncodedJSValue, JSC::PropertyName);
bool setJSHTMLOptionsCollectionSelectedIndex(JSC::ExecState*, JSC::EncodedJSValue, JSC::EncodedJSValue);
JSC::EncodedJSValue jsHTMLOptionsCollectionLength(JSC::ExecState*, JSC::EncodedJSValue, JSC::PropertyName);
bool setJSHTMLOptionsCollectionLength(JSC::ExecState*, JSC::EncodedJSValue, JSC::EncodedJSValue);
JSC::EncodedJSValue jsHTMLOptionsCollectionConstructor(JSC::ExecState*, JSC::EncodedJSValue, JSC::PropertyName);
bool setJSHTMLOptionsCollectionConstructor(JSC::ExecState*, JSC::EncodedJSValue, JSC::EncodedJSValue);

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

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

typedef JSDOMConstructorNotConstructable<JSHTMLOptionsCollection> JSHTMLOptionsCollectionConstructor;

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

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

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

/* Hash table for prototype */

static const HashTableValue JSHTMLOptionsCollectionPrototypeTableValues[] =
{
    { "constructor", DontEnum, NoIntrinsic, { (intptr_t)static_cast<PropertySlot::GetValueFunc>(jsHTMLOptionsCollectionConstructor), (intptr_t) static_cast<PutPropertySlot::PutValueFunc>(setJSHTMLOptionsCollectionConstructor) } },
    { "selectedIndex", CustomAccessor, NoIntrinsic, { (intptr_t)static_cast<PropertySlot::GetValueFunc>(jsHTMLOptionsCollectionSelectedIndex), (intptr_t) static_cast<PutPropertySlot::PutValueFunc>(setJSHTMLOptionsCollectionSelectedIndex) } },
    { "length", CustomAccessor, NoIntrinsic, { (intptr_t)static_cast<PropertySlot::GetValueFunc>(jsHTMLOptionsCollectionLength), (intptr_t) static_cast<PutPropertySlot::PutValueFunc>(setJSHTMLOptionsCollectionLength) } },
    { "item", JSC::Function, NoIntrinsic, { (intptr_t)static_cast<NativeFunction>(jsHTMLOptionsCollectionPrototypeFunctionItem), (intptr_t) (1) } },
    { "namedItem", JSC::Function, NoIntrinsic, { (intptr_t)static_cast<NativeFunction>(jsHTMLOptionsCollectionPrototypeFunctionNamedItem), (intptr_t) (1) } },
    { "add", JSC::Function, NoIntrinsic, { (intptr_t)static_cast<NativeFunction>(jsHTMLOptionsCollectionPrototypeFunctionAdd), (intptr_t) (1) } },
    { "remove", JSC::Function, NoIntrinsic, { (intptr_t)static_cast<NativeFunction>(jsHTMLOptionsCollectionPrototypeFunctionRemove), (intptr_t) (1) } },
};

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

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

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

JSHTMLOptionsCollection::JSHTMLOptionsCollection(Structure* structure, JSDOMGlobalObject& globalObject, Ref<HTMLOptionsCollection>&& impl)
    : JSHTMLCollection(structure, globalObject, WTFMove(impl))
{
}

JSObject* JSHTMLOptionsCollection::createPrototype(VM& vm, JSGlobalObject* globalObject)
{
    return JSHTMLOptionsCollectionPrototype::create(vm, globalObject, JSHTMLOptionsCollectionPrototype::createStructure(vm, globalObject, JSHTMLCollection::prototype(vm, globalObject)));
}

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

bool JSHTMLOptionsCollection::getOwnPropertySlot(JSObject* object, ExecState* state, PropertyName propertyName, PropertySlot& slot)
{
    auto* thisObject = jsCast<JSHTMLOptionsCollection*>(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 = 0;
        slot.setValue(thisObject, attributes, toJS(state, thisObject->globalObject(), thisObject->wrapped().item(index)));
        return true;
    }
    if (Base::getOwnPropertySlot(thisObject, state, propertyName, slot))
        return true;
    JSValue proto = thisObject->getPrototypeDirect();
    if (proto.isObject() && jsCast<JSObject*>(proto)->hasProperty(state, propertyName))
        return false;

    if (!optionalIndex && thisObject->classInfo() == info()) {
        JSValue value;
        if (thisObject->nameGetter(state, propertyName, value)) {
            slot.setValue(thisObject, ReadOnly | DontEnum, value);
            return true;
        }
    }
    return false;
}

bool JSHTMLOptionsCollection::getOwnPropertySlotByIndex(JSObject* object, ExecState* state, unsigned index, PropertySlot& slot)
{
    auto* thisObject = jsCast<JSHTMLOptionsCollection*>(object);
    ASSERT_GC_OBJECT_INHERITS(thisObject, info());
    if (LIKELY(index < thisObject->wrapped().length())) {
        unsigned attributes = DontDelete;
        slot.setValue(thisObject, attributes, toJS(state, thisObject->globalObject(), thisObject->wrapped().item(index)));
        return true;
    }
    return Base::getOwnPropertySlotByIndex(thisObject, state, index, slot);
}

EncodedJSValue jsHTMLOptionsCollectionSelectedIndex(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<JSHTMLOptionsCollection*>(decodedThisValue);
    if (UNLIKELY(!castedThis)) {
        return throwGetterTypeError(*state, throwScope, "HTMLOptionsCollection", "selectedIndex");
    }
    auto& impl = castedThis->wrapped();
    JSValue result = jsNumber(impl.selectedIndex());
    return JSValue::encode(result);
}


EncodedJSValue jsHTMLOptionsCollectionLength(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<JSHTMLOptionsCollection*>(decodedThisValue);
    if (UNLIKELY(!castedThis)) {
        return throwGetterTypeError(*state, throwScope, "HTMLOptionsCollection", "length");
    }
    auto& impl = castedThis->wrapped();
    JSValue result = jsNumber(impl.length());
    return JSValue::encode(result);
}


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

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

bool JSHTMLOptionsCollection::put(JSCell* cell, ExecState* state, PropertyName propertyName, JSValue value, PutPropertySlot& slot)
{
    auto* thisObject = jsCast<JSHTMLOptionsCollection*>(cell);
    ASSERT_GC_OBJECT_INHERITS(thisObject, info());
    if (Optional<uint32_t> index = parseIndex(propertyName)) {
        thisObject->indexSetter(state, index.value(), value);
        return true;
    }
    return Base::put(thisObject, state, propertyName, value, slot);
}

bool JSHTMLOptionsCollection::putByIndex(JSCell* cell, ExecState* state, unsigned index, JSValue value, bool shouldThrow)
{
    auto* thisObject = jsCast<JSHTMLOptionsCollection*>(cell);
    ASSERT_GC_OBJECT_INHERITS(thisObject, info());
    if (LIKELY(index <= MAX_ARRAY_INDEX)) {
        thisObject->indexSetter(state, index, value);
        return true;
    }
    return Base::putByIndex(cell, state, index, value, shouldThrow);
}

bool setJSHTMLOptionsCollectionSelectedIndex(ExecState* state, EncodedJSValue thisValue, EncodedJSValue encodedValue)
{
    VM& vm = state->vm();
    auto throwScope = DECLARE_THROW_SCOPE(vm);
    UNUSED_PARAM(throwScope);
    JSValue value = JSValue::decode(encodedValue);
    UNUSED_PARAM(thisValue);
    JSHTMLOptionsCollection* castedThis = jsDynamicCast<JSHTMLOptionsCollection*>(JSValue::decode(thisValue));
    if (UNLIKELY(!castedThis)) {
        return throwSetterTypeError(*state, throwScope, "HTMLOptionsCollection", "selectedIndex");
    }
    auto& impl = castedThis->wrapped();
    auto nativeValue = convert<int32_t>(*state, value, NormalConversion);
    RETURN_IF_EXCEPTION(throwScope, false);
    impl.setSelectedIndex(WTFMove(nativeValue));
    return true;
}


bool setJSHTMLOptionsCollectionLength(ExecState* state, EncodedJSValue thisValue, EncodedJSValue encodedValue)
{
    VM& vm = state->vm();
    auto throwScope = DECLARE_THROW_SCOPE(vm);
    UNUSED_PARAM(throwScope);
    JSValue value = JSValue::decode(encodedValue);
    UNUSED_PARAM(thisValue);
    JSHTMLOptionsCollection* castedThis = jsDynamicCast<JSHTMLOptionsCollection*>(JSValue::decode(thisValue));
    if (UNLIKELY(!castedThis)) {
        return throwSetterTypeError(*state, throwScope, "HTMLOptionsCollection", "length");
    }
    castedThis->setLength(*state, value);
    return true;
}


void JSHTMLOptionsCollection::getOwnPropertyNames(JSObject* object, ExecState* state, PropertyNameArray& propertyNames, EnumerationMode mode)
{
    auto* thisObject = jsCast<JSHTMLOptionsCollection*>(object);
    ASSERT_GC_OBJECT_INHERITS(thisObject, info());
    for (unsigned i = 0, count = thisObject->wrapped().length(); i < count; ++i)
        propertyNames.add(Identifier::from(state, i));
    if (mode.includeDontEnumProperties()) {
        for (auto& propertyName : thisObject->wrapped().supportedPropertyNames())
            propertyNames.add(Identifier::fromString(state, propertyName));
    }
    Base::getOwnPropertyNames(thisObject, state, propertyNames, mode);
}

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

EncodedJSValue JSC_HOST_CALL jsHTMLOptionsCollectionPrototypeFunctionItem(ExecState* state)
{
    VM& vm = state->vm();
    auto throwScope = DECLARE_THROW_SCOPE(vm);
    UNUSED_PARAM(throwScope);
    JSValue thisValue = state->thisValue();
    auto castedThis = jsDynamicCast<JSHTMLOptionsCollection*>(thisValue);
    if (UNLIKELY(!castedThis))
        return throwThisTypeError(*state, throwScope, "HTMLOptionsCollection", "item");
    ASSERT_GC_OBJECT_INHERITS(castedThis, JSHTMLOptionsCollection::info());
    auto& impl = castedThis->wrapped();
    if (UNLIKELY(state->argumentCount() < 1))
        return throwVMError(state, throwScope, createNotEnoughArgumentsError(state));
    auto index = convert<uint32_t>(*state, state->uncheckedArgument(0), NormalConversion);
    RETURN_IF_EXCEPTION(throwScope, encodedJSValue());
    JSValue result = toJS(state, castedThis->globalObject(), impl.item(WTFMove(index)));
    return JSValue::encode(result);
}

EncodedJSValue JSC_HOST_CALL jsHTMLOptionsCollectionPrototypeFunctionNamedItem(ExecState* state)
{
    VM& vm = state->vm();
    auto throwScope = DECLARE_THROW_SCOPE(vm);
    UNUSED_PARAM(throwScope);
    JSValue thisValue = state->thisValue();
    auto castedThis = jsDynamicCast<JSHTMLOptionsCollection*>(thisValue);
    if (UNLIKELY(!castedThis))
        return throwThisTypeError(*state, throwScope, "HTMLOptionsCollection", "namedItem");
    ASSERT_GC_OBJECT_INHERITS(castedThis, JSHTMLOptionsCollection::info());
    auto& impl = castedThis->wrapped();
    if (UNLIKELY(state->argumentCount() < 1))
        return throwVMError(state, throwScope, createNotEnoughArgumentsError(state));
    auto name = state->uncheckedArgument(0).toWTFString(state);
    RETURN_IF_EXCEPTION(throwScope, encodedJSValue());
    JSValue result = toJS(state, castedThis->globalObject(), impl.namedItem(WTFMove(name)));
    return JSValue::encode(result);
}

static inline EncodedJSValue jsHTMLOptionsCollectionPrototypeFunctionAdd1(ExecState* state)
{
    VM& vm = state->vm();
    auto throwScope = DECLARE_THROW_SCOPE(vm);
    UNUSED_PARAM(throwScope);
    JSValue thisValue = state->thisValue();
    auto castedThis = jsDynamicCast<JSHTMLOptionsCollection*>(thisValue);
    if (UNLIKELY(!castedThis))
        return throwThisTypeError(*state, throwScope, "HTMLOptionsCollection", "add");
    ASSERT_GC_OBJECT_INHERITS(castedThis, JSHTMLOptionsCollection::info());
    auto& impl = castedThis->wrapped();
    if (UNLIKELY(state->argumentCount() < 1))
        return throwVMError(state, throwScope, createNotEnoughArgumentsError(state));
    ExceptionCode ec = 0;
    auto element = JSHTMLElement::toWrapped(state->uncheckedArgument(0));
    if (UNLIKELY(!element))
        return throwArgumentTypeError(*state, throwScope, 0, "element", "HTMLOptionsCollection", "add", "HTMLElement");
    HTMLElement* before = nullptr;
    if (!state->argument(1).isUndefinedOrNull()) {
        before = JSHTMLElement::toWrapped(state->uncheckedArgument(1));
        if (UNLIKELY(!before))
            return throwArgumentTypeError(*state, throwScope, 1, "before", "HTMLOptionsCollection", "add", "HTMLElement");
    }
    impl.add(*element, WTFMove(before), ec);
    setDOMException(state, throwScope, ec);
    return JSValue::encode(jsUndefined());
}

static inline EncodedJSValue jsHTMLOptionsCollectionPrototypeFunctionAdd2(ExecState* state)
{
    VM& vm = state->vm();
    auto throwScope = DECLARE_THROW_SCOPE(vm);
    UNUSED_PARAM(throwScope);
    JSValue thisValue = state->thisValue();
    auto castedThis = jsDynamicCast<JSHTMLOptionsCollection*>(thisValue);
    if (UNLIKELY(!castedThis))
        return throwThisTypeError(*state, throwScope, "HTMLOptionsCollection", "add");
    ASSERT_GC_OBJECT_INHERITS(castedThis, JSHTMLOptionsCollection::info());
    auto& impl = castedThis->wrapped();
    if (UNLIKELY(state->argumentCount() < 2))
        return throwVMError(state, throwScope, createNotEnoughArgumentsError(state));
    ExceptionCode ec = 0;
    auto element = JSHTMLElement::toWrapped(state->uncheckedArgument(0));
    if (UNLIKELY(!element))
        return throwArgumentTypeError(*state, throwScope, 0, "element", "HTMLOptionsCollection", "add", "HTMLElement");
    auto index = convert<int32_t>(*state, state->uncheckedArgument(1), NormalConversion);
    RETURN_IF_EXCEPTION(throwScope, encodedJSValue());
    impl.add(*element, WTFMove(index), ec);
    setDOMException(state, throwScope, ec);
    return JSValue::encode(jsUndefined());
}

EncodedJSValue JSC_HOST_CALL jsHTMLOptionsCollectionPrototypeFunctionAdd(ExecState* state)
{
    VM& vm = state->vm();
    auto throwScope = DECLARE_THROW_SCOPE(vm);
    UNUSED_PARAM(throwScope);
    size_t argsCount = std::min<size_t>(2, state->argumentCount());
    if (argsCount == 1) {
        return jsHTMLOptionsCollectionPrototypeFunctionAdd1(state);
    }
    if (argsCount == 2) {
        JSValue distinguishingArg = state->uncheckedArgument(1);
        if (distinguishingArg.isUndefined())
            return jsHTMLOptionsCollectionPrototypeFunctionAdd1(state);
        if (distinguishingArg.isUndefinedOrNull())
            return jsHTMLOptionsCollectionPrototypeFunctionAdd1(state);
        if (distinguishingArg.isObject() && asObject(distinguishingArg)->inherits(JSHTMLElement::info()))
            return jsHTMLOptionsCollectionPrototypeFunctionAdd1(state);
        if (distinguishingArg.isNumber())
            return jsHTMLOptionsCollectionPrototypeFunctionAdd2(state);
        return jsHTMLOptionsCollectionPrototypeFunctionAdd2(state);
    }
    return argsCount < 1 ? throwVMError(state, throwScope, createNotEnoughArgumentsError(state)) : throwVMTypeError(state, throwScope);
}

static inline EncodedJSValue jsHTMLOptionsCollectionPrototypeFunctionRemove1(ExecState* state)
{
    VM& vm = state->vm();
    auto throwScope = DECLARE_THROW_SCOPE(vm);
    UNUSED_PARAM(throwScope);
    JSValue thisValue = state->thisValue();
    auto castedThis = jsDynamicCast<JSHTMLOptionsCollection*>(thisValue);
    if (UNLIKELY(!castedThis))
        return throwThisTypeError(*state, throwScope, "HTMLOptionsCollection", "remove");
    ASSERT_GC_OBJECT_INHERITS(castedThis, JSHTMLOptionsCollection::info());
    auto& impl = castedThis->wrapped();
    if (UNLIKELY(state->argumentCount() < 1))
        return throwVMError(state, throwScope, createNotEnoughArgumentsError(state));
    auto index = convert<int32_t>(*state, state->uncheckedArgument(0), NormalConversion);
    RETURN_IF_EXCEPTION(throwScope, encodedJSValue());
    impl.remove(WTFMove(index));
    return JSValue::encode(jsUndefined());
}

static inline EncodedJSValue jsHTMLOptionsCollectionPrototypeFunctionRemove2(ExecState* state)
{
    VM& vm = state->vm();
    auto throwScope = DECLARE_THROW_SCOPE(vm);
    UNUSED_PARAM(throwScope);
    JSValue thisValue = state->thisValue();
    auto castedThis = jsDynamicCast<JSHTMLOptionsCollection*>(thisValue);
    if (UNLIKELY(!castedThis))
        return throwThisTypeError(*state, throwScope, "HTMLOptionsCollection", "remove");
    ASSERT_GC_OBJECT_INHERITS(castedThis, JSHTMLOptionsCollection::info());
    auto& impl = castedThis->wrapped();
    if (UNLIKELY(state->argumentCount() < 1))
        return throwVMError(state, throwScope, createNotEnoughArgumentsError(state));
    auto option = JSHTMLOptionElement::toWrapped(state->uncheckedArgument(0));
    if (UNLIKELY(!option))
        return throwArgumentTypeError(*state, throwScope, 0, "option", "HTMLOptionsCollection", "remove", "HTMLOptionElement");
    impl.remove(*option);
    return JSValue::encode(jsUndefined());
}

EncodedJSValue JSC_HOST_CALL jsHTMLOptionsCollectionPrototypeFunctionRemove(ExecState* state)
{
    VM& vm = state->vm();
    auto throwScope = DECLARE_THROW_SCOPE(vm);
    UNUSED_PARAM(throwScope);
    size_t argsCount = std::min<size_t>(1, state->argumentCount());
    if (argsCount == 1) {
        JSValue distinguishingArg = state->uncheckedArgument(0);
        if (distinguishingArg.isObject() && asObject(distinguishingArg)->inherits(JSHTMLOptionElement::info()))
            return jsHTMLOptionsCollectionPrototypeFunctionRemove2(state);
        if (distinguishingArg.isNumber())
            return jsHTMLOptionsCollectionPrototypeFunctionRemove1(state);
        return jsHTMLOptionsCollectionPrototypeFunctionRemove1(state);
    }
    return argsCount < 1 ? throwVMError(state, throwScope, createNotEnoughArgumentsError(state)) : throwVMTypeError(state, throwScope);
}

bool JSHTMLOptionsCollectionOwner::isReachableFromOpaqueRoots(JSC::Handle<JSC::Unknown> handle, void*, SlotVisitor& visitor)
{
    auto* jsHTMLOptionsCollection = jsCast<JSHTMLOptionsCollection*>(handle.slot()->asCell());
    void* root = WebCore::root(jsHTMLOptionsCollection->wrapped().ownerNode());
    return visitor.containsOpaqueRoot(root);
}

void JSHTMLOptionsCollectionOwner::finalize(JSC::Handle<JSC::Unknown> handle, void* context)
{
    auto* jsHTMLOptionsCollection = jsCast<JSHTMLOptionsCollection*>(handle.slot()->asCell());
    auto& world = *static_cast<DOMWrapperWorld*>(context);
    uncacheWrapper(world, &jsHTMLOptionsCollection->wrapped(), jsHTMLOptionsCollection);
}

HTMLOptionsCollection* JSHTMLOptionsCollection::toWrapped(JSC::JSValue value)
{
    if (auto* wrapper = jsDynamicCast<JSHTMLOptionsCollection*>(value))
        return &wrapper->wrapped();
    return nullptr;
}

}
