/* THIS FILE IS AUTOGENERATED FROM EventHandler.webidl BY Codegen.py - DO NOT EDIT */

#include <type_traits>
#include "EventHandlerBinding.h"
#include "MainThreadUtils.h"
#include "js/CallAndConstruct.h"
#include "js/Exception.h"
#include "js/MapAndSet.h"
#include "js/Object.h"
#include "js/PropertyAndElement.h"
#include "js/PropertyDescriptor.h"
#include "js/experimental/JitInfo.h"
#include "mozilla/OwningNonNull.h"
#include "mozilla/dom/BindingCallContext.h"
#include "mozilla/dom/BindingUtils.h"
#include "mozilla/dom/Event.h"
#include "mozilla/dom/NonRefcountedDOMObject.h"
#include "mozilla/dom/Nullable.h"
#include "mozilla/dom/PrimitiveConversions.h"

namespace mozilla::dom {

namespace binding_detail {}; // Just to make sure it's known as a namespace
using namespace mozilla::dom::binding_detail;


void
ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback& aCallback, OwningEventOrString& aUnion, const char* aName, uint32_t aFlags)
{
  if (aUnion.IsEvent()) {
    ImplCycleCollectionTraverse(aCallback, aUnion.GetAsEvent(), "mEvent", aFlags);
  }
}


void
ImplCycleCollectionUnlink(OwningEventOrString& aUnion)
{
  aUnion.Uninit();
}


MOZ_CAN_RUN_SCRIPT void
EventHandlerNonNull::Call(BindingCallContext& cx, JS::Handle<JS::Value> aThisVal, Event& event, JS::MutableHandle<JS::Value> aRetVal, ErrorResult& aRv)
{
  JS::Rooted<JS::Value> rval(cx);
  JS::RootedVector<JS::Value> argv(cx);
  if (!argv.resize(1)) {
    // That threw an exception on the JSContext, and our CallSetup will do
    // the right thing with that.
    return;
  }
  unsigned argc = 1;

  do {
    if (!GetOrCreateDOMReflector(cx, event, argv[0])) {
      MOZ_ASSERT(JS_IsExceptionPending(cx));
      aRv.Throw(NS_ERROR_UNEXPECTED);
      return;
    }
    break;
  } while (false);

  JS::Rooted<JS::Value> callable(cx, JS::ObjectValue(*mCallback));
  if (JS::IsCallable(mCallback) && !JS::Call(cx, aThisVal, callable,
                JS::HandleValueArray::subarray(argv, 0, argc), &rval)) {
    aRv.NoteJSContextException(cx);
    return;
  }
  JS::Rooted<JS::Value> rvalDecl(cx);
#ifdef __clang__
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunreachable-code"
#pragma clang diagnostic ignored "-Wunreachable-code-return"
#endif // __clang__
  if ((false) && !CallerSubsumes(rval)) {
    cx.ThrowErrorMessage<MSG_PERMISSION_DENIED_TO_PASS_ARG>("return value of EventHandlerNonNull");
    aRv.Throw(NS_ERROR_UNEXPECTED);
    return;
  }
#ifdef __clang__
#pragma clang diagnostic pop
#endif // __clang__
  rvalDecl = rval;
  aRetVal.set(rvalDecl);
}



bool
EventOrString::TrySetToEvent(BindingCallContext& cx, JS::Handle<JS::Value> value, bool& tryNext, bool passedToJSImpl)
{
  tryNext = false;
  { // scope for memberSlot
    NonNull<mozilla::dom::Event>& memberSlot = RawSetAsEvent();
    {
      // Our JSContext should be in the right global to do unwrapping in.
      nsresult rv = UnwrapObject<prototypes::id::Event, mozilla::dom::Event>(value, memberSlot, cx);
      if (NS_FAILED(rv)) {
        DestroyEvent();
        tryNext = true;
        return true;
      }
    }
  }
  return true;
}

bool
EventOrString::TrySetToEvent(JSContext* cx_, JS::Handle<JS::Value> value, bool& tryNext, bool passedToJSImpl)
{
  BindingCallContext cx(cx_, nullptr);
  return TrySetToEvent(cx, value, tryNext, passedToJSImpl);
}







bool
EventOrString::TrySetToString(JSContext* cx, JS::Handle<JS::Value> value, bool& tryNext, bool passedToJSImpl)
{
  tryNext = false;
  { // scope for memberSlot
    binding_detail::FakeString<char16_t>& memberSlot = RawSetAsString();
    if (!ConvertJSValueToString(cx, value, eStringify, eStringify, memberSlot)) {
      return false;
    }
  }
  return true;
}








bool
EventOrString::Init(BindingCallContext& cx, JS::Handle<JS::Value> value, const char* sourceDescription, bool passedToJSImpl)
{
  MOZ_ASSERT(mType == eUninitialized);

  bool done = false, failed = false, tryNext;
  if (value.isObject()) {
    done = (failed = !TrySetToEvent(cx, value, tryNext, passedToJSImpl)) || !tryNext;
  }
  if (!done) {
    do {
      done = (failed = !TrySetToString(cx, value, tryNext)) || !tryNext;
      break;
    } while (false);
  }
  if (failed) {
    return false;
  }
  if (!done) {
    cx.ThrowErrorMessage<MSG_NOT_IN_UNION>(sourceDescription, "Event");
    return false;
  }
  return true;
}

bool
EventOrString::Init(JSContext* cx_, JS::Handle<JS::Value> value, const char* sourceDescription, bool passedToJSImpl)
{
  BindingCallContext cx(cx_, nullptr);
  return Init(cx, value, sourceDescription, passedToJSImpl);
}


bool
EventOrString::ToJSVal(JSContext* cx, JS::Handle<JSObject*> scopeObj, JS::MutableHandle<JS::Value> rval) const
{
  switch (mType) {
    case eUninitialized: {
      return false;
    }
    case eEvent: {
      if (!GetOrCreateDOMReflector(cx, mValue.mEvent.Value(), rval)) {
        MOZ_ASSERT(JS_IsExceptionPending(cx));
        return false;
      }
      return true;
    }
    case eString: {
      if (!xpc::NonVoidStringToJsval(cx, mValue.mString.Value(), rval)) {
        return false;
      }
      return true;
    }
    default: {
      return false;
    }
  }
}



OwningEventOrString::OwningEventOrString(OwningEventOrString&& aOther)
  : mType(eUninitialized)
{
  switch (aOther.mType) {
    case eUninitialized: {
      MOZ_ASSERT(mType == eUninitialized,
                 "We need to destroy ourselves?");
      break;
    }
    case eEvent: {
      mType = eEvent;
      mValue.mEvent.SetValue(std::move(aOther.mValue.mEvent.Value()));
      break;
    }
    case eString: {
      mType = eString;
      mValue.mString.SetValue(std::move(aOther.mValue.mString.Value()));
      break;
    }
  }
}



bool
OwningEventOrString::TrySetToEvent(BindingCallContext& cx, JS::Handle<JS::Value> value, bool& tryNext, bool passedToJSImpl)
{
  tryNext = false;
  { // scope for memberSlot
    OwningNonNull<mozilla::dom::Event>& memberSlot = RawSetAsEvent();
    static_assert(IsRefcounted<mozilla::dom::Event>::value, "We can only store refcounted classes.");
    {
      // Our JSContext should be in the right global to do unwrapping in.
      nsresult rv = UnwrapObject<prototypes::id::Event, mozilla::dom::Event>(value, memberSlot, cx);
      if (NS_FAILED(rv)) {
        DestroyEvent();
        tryNext = true;
        return true;
      }
    }
  }
  return true;
}

bool
OwningEventOrString::TrySetToEvent(JSContext* cx_, JS::Handle<JS::Value> value, bool& tryNext, bool passedToJSImpl)
{
  BindingCallContext cx(cx_, nullptr);
  return TrySetToEvent(cx, value, tryNext, passedToJSImpl);
}

[[nodiscard]] OwningNonNull<mozilla::dom::Event>&
OwningEventOrString::RawSetAsEvent()
{
  if (mType == eEvent) {
    return mValue.mEvent.Value();
  }
  MOZ_ASSERT(mType == eUninitialized);
  mType = eEvent;
  return mValue.mEvent.SetValue();
}

[[nodiscard]] OwningNonNull<mozilla::dom::Event>&
OwningEventOrString::SetAsEvent()
{
  if (mType == eEvent) {
    return mValue.mEvent.Value();
  }
  Uninit();
  mType = eEvent;
  return mValue.mEvent.SetValue();
}


void
OwningEventOrString::DestroyEvent()
{
  MOZ_RELEASE_ASSERT(IsEvent(), "Wrong type!");
  mValue.mEvent.Destroy();
  mType = eUninitialized;
}



bool
OwningEventOrString::TrySetToString(JSContext* cx, JS::Handle<JS::Value> value, bool& tryNext, bool passedToJSImpl)
{
  tryNext = false;
  { // scope for memberSlot
    nsString& memberSlot = RawSetAsString();
    if (!ConvertJSValueToString(cx, value, eStringify, eStringify, memberSlot)) {
      return false;
    }
  }
  return true;
}

[[nodiscard]] nsString&
OwningEventOrString::RawSetAsString()
{
  if (mType == eString) {
    return mValue.mString.Value();
  }
  MOZ_ASSERT(mType == eUninitialized);
  mType = eString;
  return mValue.mString.SetValue();
}

[[nodiscard]] nsString&
OwningEventOrString::SetAsString()
{
  if (mType == eString) {
    return mValue.mString.Value();
  }
  Uninit();
  mType = eString;
  return mValue.mString.SetValue();
}



void
OwningEventOrString::DestroyString()
{
  MOZ_RELEASE_ASSERT(IsString(), "Wrong type!");
  mValue.mString.Destroy();
  mType = eUninitialized;
}



bool
OwningEventOrString::Init(BindingCallContext& cx, JS::Handle<JS::Value> value, const char* sourceDescription, bool passedToJSImpl)
{
  MOZ_ASSERT(mType == eUninitialized);

  bool done = false, failed = false, tryNext;
  if (value.isObject()) {
    done = (failed = !TrySetToEvent(cx, value, tryNext, passedToJSImpl)) || !tryNext;
  }
  if (!done) {
    do {
      done = (failed = !TrySetToString(cx, value, tryNext)) || !tryNext;
      break;
    } while (false);
  }
  if (failed) {
    return false;
  }
  if (!done) {
    cx.ThrowErrorMessage<MSG_NOT_IN_UNION>(sourceDescription, "Event");
    return false;
  }
  return true;
}

bool
OwningEventOrString::Init(JSContext* cx_, JS::Handle<JS::Value> value, const char* sourceDescription, bool passedToJSImpl)
{
  BindingCallContext cx(cx_, nullptr);
  return Init(cx, value, sourceDescription, passedToJSImpl);
}

void
OwningEventOrString::Uninit()
{
  switch (mType) {
    case eUninitialized: {
      break;
    }
    case eEvent: {
      DestroyEvent();
      break;
    }
    case eString: {
      DestroyString();
      break;
    }
  }
}

bool
OwningEventOrString::ToJSVal(JSContext* cx, JS::Handle<JSObject*> scopeObj, JS::MutableHandle<JS::Value> rval) const
{
  switch (mType) {
    case eUninitialized: {
      return false;
    }
    case eEvent: {
      if (!GetOrCreateDOMReflector(cx, mValue.mEvent.Value(), rval)) {
        MOZ_ASSERT(JS_IsExceptionPending(cx));
        return false;
      }
      return true;
    }
    case eString: {
      if (!xpc::NonVoidStringToJsval(cx, mValue.mString.Value(), rval)) {
        return false;
      }
      return true;
    }
    default: {
      return false;
    }
  }
}

OwningEventOrString&
OwningEventOrString::operator=(OwningEventOrString&& aOther)
{
  this->~OwningEventOrString();
  new (this) OwningEventOrString (std::move(aOther));
  return *this;
}


OwningEventOrString&
OwningEventOrString::operator=(const OwningEventOrString& aOther)
{
  switch (aOther.mType) {
    case eUninitialized: {
      MOZ_ASSERT(mType == eUninitialized,
                 "We need to destroy ourselves?");
      break;
    }
    case eEvent: {
      SetAsEvent() = aOther.GetAsEvent();
      break;
    }
    case eString: {
      SetAsString() = aOther.GetAsString();
      break;
    }
  }
  return *this;
}


MOZ_CAN_RUN_SCRIPT void
OnBeforeUnloadEventHandlerNonNull::Call(BindingCallContext& cx, JS::Handle<JS::Value> aThisVal, Event& event, nsString& aRetVal, ErrorResult& aRv)
{
  JS::Rooted<JS::Value> rval(cx);
  JS::RootedVector<JS::Value> argv(cx);
  if (!argv.resize(1)) {
    // That threw an exception on the JSContext, and our CallSetup will do
    // the right thing with that.
    return;
  }
  unsigned argc = 1;

  do {
    if (!GetOrCreateDOMReflector(cx, event, argv[0])) {
      MOZ_ASSERT(JS_IsExceptionPending(cx));
      aRv.Throw(NS_ERROR_UNEXPECTED);
      return;
    }
    break;
  } while (false);

  JS::Rooted<JS::Value> callable(cx, JS::ObjectValue(*mCallback));
  if (JS::IsCallable(mCallback) && !JS::Call(cx, aThisVal, callable,
                JS::HandleValueArray::subarray(argv, 0, argc), &rval)) {
    aRv.NoteJSContextException(cx);
    return;
  }
  binding_detail::FakeString<char16_t> rvalDecl;
  if (!ConvertJSValueToString(cx, rval, eNull, eNull, rvalDecl)) {
    aRv.Throw(NS_ERROR_UNEXPECTED);
    return;
  }
  aRetVal = rvalDecl;
}



MOZ_CAN_RUN_SCRIPT void
OnErrorEventHandlerNonNull::Call(BindingCallContext& cx, JS::Handle<JS::Value> aThisVal, const EventOrString& event, const Optional<nsACString>& source, const Optional<uint32_t>& lineno, const Optional<uint32_t>& column, const Optional<JS::Handle<JS::Value>>& error, JS::MutableHandle<JS::Value> aRetVal, ErrorResult& aRv)
{
  JS::Rooted<JS::Value> rval(cx);
  JS::RootedVector<JS::Value> argv(cx);
  if (!argv.resize(5)) {
    // That threw an exception on the JSContext, and our CallSetup will do
    // the right thing with that.
    return;
  }
  unsigned argc = 5;

  do {
    if (error.WasPassed()) {
      JS::ExposeValueToActiveJS(error.Value());
      argv[4].set(error.Value());
      if (!MaybeWrapValue(cx, argv[4])) {
        aRv.Throw(NS_ERROR_UNEXPECTED);
        return;
      }
      break;
    } else if (argc == 5) {
      // This is our current trailing argument; reduce argc
      --argc;
    } else {
      argv[4].setUndefined();
    }
  } while (false);

  do {
    if (column.WasPassed()) {
      argv[3].setNumber(column.Value());
      break;
    } else if (argc == 4) {
      // This is our current trailing argument; reduce argc
      --argc;
    } else {
      argv[3].setUndefined();
    }
  } while (false);

  do {
    if (lineno.WasPassed()) {
      argv[2].setNumber(lineno.Value());
      break;
    } else if (argc == 3) {
      // This is our current trailing argument; reduce argc
      --argc;
    } else {
      argv[2].setUndefined();
    }
  } while (false);

  do {
    if (source.WasPassed()) {
      if (!NonVoidUTF8StringToJsval(cx, source.Value(), argv[1])) {
        aRv.Throw(NS_ERROR_UNEXPECTED);
        return;
      }
      break;
    } else if (argc == 2) {
      // This is our current trailing argument; reduce argc
      --argc;
    } else {
      argv[1].setUndefined();
    }
  } while (false);

  do {
    JS::Rooted<JSObject*> callbackObj(cx, CallbackKnownNotGray());
    if (!event.ToJSVal(cx, callbackObj, argv[0])) {
      aRv.Throw(NS_ERROR_UNEXPECTED);
      return;
    }
    break;
  } while (false);

  JS::Rooted<JS::Value> callable(cx, JS::ObjectValue(*mCallback));
  if (JS::IsCallable(mCallback) && !JS::Call(cx, aThisVal, callable,
                JS::HandleValueArray::subarray(argv, 0, argc), &rval)) {
    aRv.NoteJSContextException(cx);
    return;
  }
  JS::Rooted<JS::Value> rvalDecl(cx);
#ifdef __clang__
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunreachable-code"
#pragma clang diagnostic ignored "-Wunreachable-code-return"
#endif // __clang__
  if ((false) && !CallerSubsumes(rval)) {
    cx.ThrowErrorMessage<MSG_PERMISSION_DENIED_TO_PASS_ARG>("return value of OnErrorEventHandlerNonNull");
    aRv.Throw(NS_ERROR_UNEXPECTED);
    return;
  }
#ifdef __clang__
#pragma clang diagnostic pop
#endif // __clang__
  rvalDecl = rval;
  aRetVal.set(rvalDecl);
}



} // namespace mozilla::dom
