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

#include "DOMWindow.h"
#include "ExceptionCode.h"
#include "JSDOMBinding.h"
#include "JSDOMConstructor.h"
#include "JSDOMConvert.h"
#include "JSEvent.h"
#include "JSEventListener.h"
#include <runtime/Error.h>
#include <runtime/FunctionPrototype.h>
#include <wtf/GetPtr.h>

using namespace JSC;

namespace WebCore {

template<> Optional<EventTarget::ListenerOptions> convertDictionary<EventTarget::ListenerOptions>(ExecState& state, JSValue value)
{
    VM& vm = state.vm();
    auto throwScope = DECLARE_THROW_SCOPE(vm);
    if (value.isUndefinedOrNull())
        return EventTarget::ListenerOptions { false };
    auto* object = value.getObject();
    if (UNLIKELY(!object || object->type() == RegExpObjectType)) {
        throwTypeError(&state, throwScope);
        return Nullopt;
    }
    auto capture = convertOptional<bool>(state, object->get(&state, Identifier::fromString(&state, "capture")), false);
    return EventTarget::ListenerOptions { WTFMove(capture) };
}

template<> Optional<EventTarget::AddEventListenerOptions> convertDictionary<EventTarget::AddEventListenerOptions>(ExecState& state, JSValue value)
{
    VM& vm = state.vm();
    auto throwScope = DECLARE_THROW_SCOPE(vm);
    if (value.isUndefinedOrNull())
        return EventTarget::AddEventListenerOptions { false, false, false };
    auto* object = value.getObject();
    if (UNLIKELY(!object || object->type() == RegExpObjectType)) {
        throwTypeError(&state, throwScope);
        return Nullopt;
    }
    auto capture = convertOptional<bool>(state, object->get(&state, Identifier::fromString(&state, "capture")), false);
    RETURN_IF_EXCEPTION(throwScope, Nullopt);
    auto passive = convertOptional<bool>(state, object->get(&state, Identifier::fromString(&state, "passive")), false);
    RETURN_IF_EXCEPTION(throwScope, Nullopt);
    auto once = convertOptional<bool>(state, object->get(&state, Identifier::fromString(&state, "once")), false);
    return EventTarget::AddEventListenerOptions { WTFMove(capture), WTFMove(passive), WTFMove(once) };
}

// Functions

JSC::EncodedJSValue JSC_HOST_CALL jsEventTargetPrototypeFunctionAddEventListener(JSC::ExecState*);
JSC::EncodedJSValue JSC_HOST_CALL jsEventTargetPrototypeFunctionRemoveEventListener(JSC::ExecState*);
JSC::EncodedJSValue JSC_HOST_CALL jsEventTargetPrototypeFunctionDispatchEvent(JSC::ExecState*);

// Attributes

JSC::EncodedJSValue jsEventTargetConstructor(JSC::ExecState*, JSC::EncodedJSValue, JSC::PropertyName);
bool setJSEventTargetConstructor(JSC::ExecState*, JSC::EncodedJSValue, JSC::EncodedJSValue);

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

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

typedef JSDOMConstructorNotConstructable<JSEventTarget> JSEventTargetConstructor;

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

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

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

/* Hash table for prototype */

static const HashTableValue JSEventTargetPrototypeTableValues[] =
{
    { "constructor", DontEnum, NoIntrinsic, { (intptr_t)static_cast<PropertySlot::GetValueFunc>(jsEventTargetConstructor), (intptr_t) static_cast<PutPropertySlot::PutValueFunc>(setJSEventTargetConstructor) } },
    { "addEventListener", JSC::Function, NoIntrinsic, { (intptr_t)static_cast<NativeFunction>(jsEventTargetPrototypeFunctionAddEventListener), (intptr_t) (2) } },
    { "removeEventListener", JSC::Function, NoIntrinsic, { (intptr_t)static_cast<NativeFunction>(jsEventTargetPrototypeFunctionRemoveEventListener), (intptr_t) (2) } },
    { "dispatchEvent", JSC::Function, NoIntrinsic, { (intptr_t)static_cast<NativeFunction>(jsEventTargetPrototypeFunctionDispatchEvent), (intptr_t) (1) } },
};

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

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

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

JSEventTarget::JSEventTarget(Structure* structure, JSDOMGlobalObject& globalObject, Ref<EventTarget>&& impl)
    : JSDOMWrapper<EventTarget>(structure, globalObject, WTFMove(impl))
{
}

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

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

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

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

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

static inline EncodedJSValue jsEventTargetPrototypeFunctionAddEventListener1(ExecState* state)
{
    VM& vm = state->vm();
    auto throwScope = DECLARE_THROW_SCOPE(vm);
    UNUSED_PARAM(throwScope);
    JSValue thisValue = state->thisValue();
    auto castedThis = jsEventTargetCast(thisValue.toThis(state, NotStrictMode));
    if (UNLIKELY(!castedThis))
        return throwThisTypeError(*state, throwScope, "EventTarget", "addEventListener");
    auto& impl = castedThis->wrapped();
    if (auto* window = castedThis->wrapped().toDOMWindow()) {
        if (!window->frame() || !BindingSecurity::shouldAllowAccessToDOMWindow(state, *window, ThrowSecurityError))
            return JSValue::encode(jsUndefined());
    }
    if (UNLIKELY(state->argumentCount() < 2))
        return throwVMError(state, throwScope, createNotEnoughArgumentsError(state));
    auto type = state->uncheckedArgument(0).toString(state)->toAtomicString(state);
    RETURN_IF_EXCEPTION(throwScope, encodedJSValue());
    RefPtr<EventListener> listener = nullptr;
    if (!state->uncheckedArgument(1).isUndefinedOrNull()) {
        listener = JSEventListener::create(state->uncheckedArgument(1), *castedThis, false, currentWorld(state));
        if (UNLIKELY(!listener))
            return throwArgumentTypeError(*state, throwScope, 1, "listener", "EventTarget", "addEventListener", "EventListener");
    }
    impl.addEventListenerForBindings(WTFMove(type), WTFMove(listener));
    return JSValue::encode(jsUndefined());
}

static inline EncodedJSValue jsEventTargetPrototypeFunctionAddEventListener2(ExecState* state)
{
    VM& vm = state->vm();
    auto throwScope = DECLARE_THROW_SCOPE(vm);
    UNUSED_PARAM(throwScope);
    JSValue thisValue = state->thisValue();
    auto castedThis = jsEventTargetCast(thisValue.toThis(state, NotStrictMode));
    if (UNLIKELY(!castedThis))
        return throwThisTypeError(*state, throwScope, "EventTarget", "addEventListener");
    auto& impl = castedThis->wrapped();
    if (auto* window = castedThis->wrapped().toDOMWindow()) {
        if (!window->frame() || !BindingSecurity::shouldAllowAccessToDOMWindow(state, *window, ThrowSecurityError))
            return JSValue::encode(jsUndefined());
    }
    if (UNLIKELY(state->argumentCount() < 3))
        return throwVMError(state, throwScope, createNotEnoughArgumentsError(state));
    auto type = state->uncheckedArgument(0).toString(state)->toAtomicString(state);
    RETURN_IF_EXCEPTION(throwScope, encodedJSValue());
    RefPtr<EventListener> listener = nullptr;
    if (!state->uncheckedArgument(1).isUndefinedOrNull()) {
        listener = JSEventListener::create(state->uncheckedArgument(1), *castedThis, false, currentWorld(state));
        if (UNLIKELY(!listener))
            return throwArgumentTypeError(*state, throwScope, 1, "listener", "EventTarget", "addEventListener", "EventListener");
    }
    auto options = convertDictionary<EventTarget::AddEventListenerOptions>(*state, state->uncheckedArgument(2));
    RETURN_IF_EXCEPTION(throwScope, encodedJSValue());
    impl.addEventListenerForBindings(WTFMove(type), WTFMove(listener), options.value());
    return JSValue::encode(jsUndefined());
}

static inline EncodedJSValue jsEventTargetPrototypeFunctionRemoveEventListener1(ExecState* state)
{
    VM& vm = state->vm();
    auto throwScope = DECLARE_THROW_SCOPE(vm);
    UNUSED_PARAM(throwScope);
    JSValue thisValue = state->thisValue();
    auto castedThis = jsEventTargetCast(thisValue.toThis(state, NotStrictMode));
    if (UNLIKELY(!castedThis))
        return throwThisTypeError(*state, throwScope, "EventTarget", "removeEventListener");
    auto& impl = castedThis->wrapped();
    if (auto* window = castedThis->wrapped().toDOMWindow()) {
        if (!window->frame() || !BindingSecurity::shouldAllowAccessToDOMWindow(state, *window, ThrowSecurityError))
            return JSValue::encode(jsUndefined());
    }
    if (UNLIKELY(state->argumentCount() < 2))
        return throwVMError(state, throwScope, createNotEnoughArgumentsError(state));
    auto type = state->uncheckedArgument(0).toString(state)->toAtomicString(state);
    RETURN_IF_EXCEPTION(throwScope, encodedJSValue());
    RefPtr<EventListener> listener = nullptr;
    if (!state->uncheckedArgument(1).isUndefinedOrNull()) {
        listener = JSEventListener::create(state->uncheckedArgument(1), *castedThis, false, currentWorld(state));
        if (UNLIKELY(!listener))
            return throwArgumentTypeError(*state, throwScope, 1, "listener", "EventTarget", "removeEventListener", "EventListener");
    }
    impl.removeEventListenerForBindings(WTFMove(type), WTFMove(listener));
    return JSValue::encode(jsUndefined());
}

static inline EncodedJSValue jsEventTargetPrototypeFunctionRemoveEventListener2(ExecState* state)
{
    VM& vm = state->vm();
    auto throwScope = DECLARE_THROW_SCOPE(vm);
    UNUSED_PARAM(throwScope);
    JSValue thisValue = state->thisValue();
    auto castedThis = jsEventTargetCast(thisValue.toThis(state, NotStrictMode));
    if (UNLIKELY(!castedThis))
        return throwThisTypeError(*state, throwScope, "EventTarget", "removeEventListener");
    auto& impl = castedThis->wrapped();
    if (auto* window = castedThis->wrapped().toDOMWindow()) {
        if (!window->frame() || !BindingSecurity::shouldAllowAccessToDOMWindow(state, *window, ThrowSecurityError))
            return JSValue::encode(jsUndefined());
    }
    if (UNLIKELY(state->argumentCount() < 3))
        return throwVMError(state, throwScope, createNotEnoughArgumentsError(state));
    auto type = state->uncheckedArgument(0).toString(state)->toAtomicString(state);
    RETURN_IF_EXCEPTION(throwScope, encodedJSValue());
    RefPtr<EventListener> listener = nullptr;
    if (!state->uncheckedArgument(1).isUndefinedOrNull()) {
        listener = JSEventListener::create(state->uncheckedArgument(1), *castedThis, false, currentWorld(state));
        if (UNLIKELY(!listener))
            return throwArgumentTypeError(*state, throwScope, 1, "listener", "EventTarget", "removeEventListener", "EventListener");
    }
    auto options = convertDictionary<EventTarget::ListenerOptions>(*state, state->uncheckedArgument(2));
    RETURN_IF_EXCEPTION(throwScope, encodedJSValue());
    impl.removeEventListenerForBindings(WTFMove(type), WTFMove(listener), options.value());
    return JSValue::encode(jsUndefined());
}

static inline EncodedJSValue jsEventTargetPrototypeFunctionAddEventListener3(ExecState* state)
{
    VM& vm = state->vm();
    auto throwScope = DECLARE_THROW_SCOPE(vm);
    UNUSED_PARAM(throwScope);
    JSValue thisValue = state->thisValue();
    auto castedThis = jsEventTargetCast(thisValue.toThis(state, NotStrictMode));
    if (UNLIKELY(!castedThis))
        return throwThisTypeError(*state, throwScope, "EventTarget", "addEventListener");
    auto& impl = castedThis->wrapped();
    if (auto* window = castedThis->wrapped().toDOMWindow()) {
        if (!window->frame() || !BindingSecurity::shouldAllowAccessToDOMWindow(state, *window, ThrowSecurityError))
            return JSValue::encode(jsUndefined());
    }
    if (UNLIKELY(state->argumentCount() < 3))
        return throwVMError(state, throwScope, createNotEnoughArgumentsError(state));
    auto type = state->uncheckedArgument(0).toString(state)->toAtomicString(state);
    RETURN_IF_EXCEPTION(throwScope, encodedJSValue());
    RefPtr<EventListener> listener = nullptr;
    if (!state->uncheckedArgument(1).isUndefinedOrNull()) {
        listener = JSEventListener::create(state->uncheckedArgument(1), *castedThis, false, currentWorld(state));
        if (UNLIKELY(!listener))
            return throwArgumentTypeError(*state, throwScope, 1, "listener", "EventTarget", "addEventListener", "EventListener");
    }
    auto useCapture = state->uncheckedArgument(2).toBoolean(state);
    RETURN_IF_EXCEPTION(throwScope, encodedJSValue());
    impl.addEventListenerForBindings(WTFMove(type), WTFMove(listener), WTFMove(useCapture));
    return JSValue::encode(jsUndefined());
}

EncodedJSValue JSC_HOST_CALL jsEventTargetPrototypeFunctionAddEventListener(ExecState* state)
{
    VM& vm = state->vm();
    auto throwScope = DECLARE_THROW_SCOPE(vm);
    UNUSED_PARAM(throwScope);
    size_t argsCount = std::min<size_t>(3, state->argumentCount());
    if (argsCount == 2) {
        return jsEventTargetPrototypeFunctionAddEventListener1(state);
    }
    if (argsCount == 3) {
        JSValue distinguishingArg = state->uncheckedArgument(2);
        if (distinguishingArg.isUndefinedOrNull())
            return jsEventTargetPrototypeFunctionAddEventListener2(state);
        if (distinguishingArg.isObject() && asObject(distinguishingArg)->type() != RegExpObjectType)
            return jsEventTargetPrototypeFunctionAddEventListener2(state);
        if (distinguishingArg.isBoolean())
            return jsEventTargetPrototypeFunctionAddEventListener3(state);
        return jsEventTargetPrototypeFunctionAddEventListener3(state);
    }
    return argsCount < 2 ? throwVMError(state, throwScope, createNotEnoughArgumentsError(state)) : throwVMTypeError(state, throwScope);
}

static inline EncodedJSValue jsEventTargetPrototypeFunctionRemoveEventListener3(ExecState* state)
{
    VM& vm = state->vm();
    auto throwScope = DECLARE_THROW_SCOPE(vm);
    UNUSED_PARAM(throwScope);
    JSValue thisValue = state->thisValue();
    auto castedThis = jsEventTargetCast(thisValue.toThis(state, NotStrictMode));
    if (UNLIKELY(!castedThis))
        return throwThisTypeError(*state, throwScope, "EventTarget", "removeEventListener");
    auto& impl = castedThis->wrapped();
    if (auto* window = castedThis->wrapped().toDOMWindow()) {
        if (!window->frame() || !BindingSecurity::shouldAllowAccessToDOMWindow(state, *window, ThrowSecurityError))
            return JSValue::encode(jsUndefined());
    }
    if (UNLIKELY(state->argumentCount() < 3))
        return throwVMError(state, throwScope, createNotEnoughArgumentsError(state));
    auto type = state->uncheckedArgument(0).toString(state)->toAtomicString(state);
    RETURN_IF_EXCEPTION(throwScope, encodedJSValue());
    RefPtr<EventListener> listener = nullptr;
    if (!state->uncheckedArgument(1).isUndefinedOrNull()) {
        listener = JSEventListener::create(state->uncheckedArgument(1), *castedThis, false, currentWorld(state));
        if (UNLIKELY(!listener))
            return throwArgumentTypeError(*state, throwScope, 1, "listener", "EventTarget", "removeEventListener", "EventListener");
    }
    auto useCapture = state->uncheckedArgument(2).toBoolean(state);
    RETURN_IF_EXCEPTION(throwScope, encodedJSValue());
    impl.removeEventListenerForBindings(WTFMove(type), WTFMove(listener), WTFMove(useCapture));
    return JSValue::encode(jsUndefined());
}

EncodedJSValue JSC_HOST_CALL jsEventTargetPrototypeFunctionRemoveEventListener(ExecState* state)
{
    VM& vm = state->vm();
    auto throwScope = DECLARE_THROW_SCOPE(vm);
    UNUSED_PARAM(throwScope);
    size_t argsCount = std::min<size_t>(3, state->argumentCount());
    if (argsCount == 2) {
        return jsEventTargetPrototypeFunctionRemoveEventListener1(state);
    }
    if (argsCount == 3) {
        JSValue distinguishingArg = state->uncheckedArgument(2);
        if (distinguishingArg.isUndefinedOrNull())
            return jsEventTargetPrototypeFunctionRemoveEventListener2(state);
        if (distinguishingArg.isObject() && asObject(distinguishingArg)->type() != RegExpObjectType)
            return jsEventTargetPrototypeFunctionRemoveEventListener2(state);
        if (distinguishingArg.isBoolean())
            return jsEventTargetPrototypeFunctionRemoveEventListener3(state);
        return jsEventTargetPrototypeFunctionRemoveEventListener3(state);
    }
    return argsCount < 2 ? throwVMError(state, throwScope, createNotEnoughArgumentsError(state)) : throwVMTypeError(state, throwScope);
}

EncodedJSValue JSC_HOST_CALL jsEventTargetPrototypeFunctionDispatchEvent(ExecState* state)
{
    VM& vm = state->vm();
    auto throwScope = DECLARE_THROW_SCOPE(vm);
    UNUSED_PARAM(throwScope);
    JSValue thisValue = state->thisValue();
    auto castedThis = jsEventTargetCast(thisValue.toThis(state, NotStrictMode));
    if (UNLIKELY(!castedThis))
        return throwThisTypeError(*state, throwScope, "EventTarget", "dispatchEvent");
    auto& impl = castedThis->wrapped();
    if (auto* window = castedThis->wrapped().toDOMWindow()) {
        if (!window->frame() || !BindingSecurity::shouldAllowAccessToDOMWindow(state, *window, ThrowSecurityError))
            return JSValue::encode(jsUndefined());
    }
    if (UNLIKELY(state->argumentCount() < 1))
        return throwVMError(state, throwScope, createNotEnoughArgumentsError(state));
    ExceptionCode ec = 0;
    auto event = JSEvent::toWrapped(state->uncheckedArgument(0));
    if (UNLIKELY(!event))
        return throwArgumentTypeError(*state, throwScope, 0, "event", "EventTarget", "dispatchEvent", "Event");
    JSValue result = jsBoolean(impl.dispatchEventForBindings(*event, ec));

    setDOMException(state, throwScope, ec);
    return JSValue::encode(result);
}

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

bool JSEventTargetOwner::isReachableFromOpaqueRoots(JSC::Handle<JSC::Unknown> handle, void*, SlotVisitor& visitor)
{
    auto* jsEventTarget = jsCast<JSEventTarget*>(handle.slot()->asCell());
    if (jsEventTarget->wrapped().isFiringEventListeners())
        return true;
    UNUSED_PARAM(visitor);
    return false;
}

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


}
