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

#include "MainThreadUtils.h"
#include "WindowOrWorkerGlobalScopeBinding.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/dom/BindingCallContext.h"
#include "mozilla/dom/NonRefcountedDOMObject.h"
#include "mozilla/dom/TrustedScript.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, OwningFunctionOrTrustedScriptOrString& aUnion, const char* aName, uint32_t aFlags)
{
  if (aUnion.IsFunction()) {
    ImplCycleCollectionTraverse(aCallback, aUnion.GetAsFunction(), "mFunction", aFlags);
  } else if (aUnion.IsTrustedScript()) {
    ImplCycleCollectionTraverse(aCallback, aUnion.GetAsTrustedScript(), "mTrustedScript", aFlags);
  }
}


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


bool
FunctionOrTrustedScriptOrString::TrySetToFunction(BindingCallContext& cx, JS::Handle<JS::Value> value, bool& tryNext, bool passedToJSImpl)
{
  tryNext = false;
  { // scope for memberSlot
    RootedCallback<OwningNonNull<binding_detail::FastFunction>>& memberSlot = RawSetAsFunction(cx);
    if (JS::IsCallable(&value.toObject())) {
    { // scope for tempRoot and tempGlobalRoot if needed
      memberSlot = new binding_detail::FastFunction(&value.toObject(), JS::CurrentGlobalOrNull(cx));
    }
    } else {
      DestroyFunction();
      tryNext = true;
      return true;
    }
  }
  return true;
}

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







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

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







bool
FunctionOrTrustedScriptOrString::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
FunctionOrTrustedScriptOrString::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 = !TrySetToTrustedScript(cx, value, tryNext, passedToJSImpl)) || !tryNext;
    if (!done) {
      done = (failed = !TrySetToFunction(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, "TrustedScript, Function");
    return false;
  }
  return true;
}

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


bool
FunctionOrTrustedScriptOrString::ToJSVal(JSContext* cx, JS::Handle<JSObject*> scopeObj, JS::MutableHandle<JS::Value> rval) const
{
  switch (mType) {
    case eUninitialized: {
      return false;
    }
    case eFunction: {
      rval.setObjectOrNull(GetCallbackFromCallbackObject(cx, mValue.mFunction.Value()));
      if (!MaybeWrapObjectValue(cx, rval)) {
        return false;
      }
      return true;
    }
    case eTrustedScript: {
      if (!WrapNewBindingNonWrapperCachedObject(cx, scopeObj, mValue.mTrustedScript.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;
    }
  }
}



OwningFunctionOrTrustedScriptOrString::OwningFunctionOrTrustedScriptOrString(OwningFunctionOrTrustedScriptOrString&& aOther)
  : mType(eUninitialized)
{
  switch (aOther.mType) {
    case eUninitialized: {
      MOZ_ASSERT(mType == eUninitialized,
                 "We need to destroy ourselves?");
      break;
    }
    case eFunction: {
      mType = eFunction;
      mValue.mFunction.SetValue(std::move(aOther.mValue.mFunction.Value()));
      break;
    }
    case eTrustedScript: {
      mType = eTrustedScript;
      mValue.mTrustedScript.SetValue(std::move(aOther.mValue.mTrustedScript.Value()));
      break;
    }
    case eString: {
      mType = eString;
      mValue.mString.SetValue(std::move(aOther.mValue.mString.Value()));
      break;
    }
  }
}


bool
OwningFunctionOrTrustedScriptOrString::TrySetToFunction(BindingCallContext& cx, JS::Handle<JS::Value> value, bool& tryNext, bool passedToJSImpl)
{
  tryNext = false;
  { // scope for memberSlot
    OwningNonNull<Function>& memberSlot = RawSetAsFunction();
    if (JS::IsCallable(&value.toObject())) {
    { // scope for tempRoot and tempGlobalRoot if needed
      JS::Rooted<JSObject*> tempRoot(cx, &value.toObject());
      JS::Rooted<JSObject*> tempGlobalRoot(cx, JS::CurrentGlobalOrNull(cx));
      memberSlot = new Function(cx, tempRoot, tempGlobalRoot, GetIncumbentGlobal());
    }
    } else {
      DestroyFunction();
      tryNext = true;
      return true;
    }
  }
  return true;
}

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

[[nodiscard]] OwningNonNull<Function>&
OwningFunctionOrTrustedScriptOrString::RawSetAsFunction()
{
  if (mType == eFunction) {
    return mValue.mFunction.Value();
  }
  MOZ_ASSERT(mType == eUninitialized);
  mType = eFunction;
  return mValue.mFunction.SetValue();
}

[[nodiscard]] OwningNonNull<Function>&
OwningFunctionOrTrustedScriptOrString::SetAsFunction()
{
  if (mType == eFunction) {
    return mValue.mFunction.Value();
  }
  Uninit();
  mType = eFunction;
  return mValue.mFunction.SetValue();
}


void
OwningFunctionOrTrustedScriptOrString::DestroyFunction()
{
  MOZ_RELEASE_ASSERT(IsFunction(), "Wrong type!");
  mValue.mFunction.Destroy();
  mType = eUninitialized;
}



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

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

[[nodiscard]] OwningNonNull<mozilla::dom::TrustedScript>&
OwningFunctionOrTrustedScriptOrString::RawSetAsTrustedScript()
{
  if (mType == eTrustedScript) {
    return mValue.mTrustedScript.Value();
  }
  MOZ_ASSERT(mType == eUninitialized);
  mType = eTrustedScript;
  return mValue.mTrustedScript.SetValue();
}

[[nodiscard]] OwningNonNull<mozilla::dom::TrustedScript>&
OwningFunctionOrTrustedScriptOrString::SetAsTrustedScript()
{
  if (mType == eTrustedScript) {
    return mValue.mTrustedScript.Value();
  }
  Uninit();
  mType = eTrustedScript;
  return mValue.mTrustedScript.SetValue();
}


void
OwningFunctionOrTrustedScriptOrString::DestroyTrustedScript()
{
  MOZ_RELEASE_ASSERT(IsTrustedScript(), "Wrong type!");
  mValue.mTrustedScript.Destroy();
  mType = eUninitialized;
}



bool
OwningFunctionOrTrustedScriptOrString::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&
OwningFunctionOrTrustedScriptOrString::RawSetAsString()
{
  if (mType == eString) {
    return mValue.mString.Value();
  }
  MOZ_ASSERT(mType == eUninitialized);
  mType = eString;
  return mValue.mString.SetValue();
}

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



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



bool
OwningFunctionOrTrustedScriptOrString::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 = !TrySetToTrustedScript(cx, value, tryNext, passedToJSImpl)) || !tryNext;
    if (!done) {
      done = (failed = !TrySetToFunction(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, "TrustedScript, Function");
    return false;
  }
  return true;
}

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

void
OwningFunctionOrTrustedScriptOrString::Uninit()
{
  switch (mType) {
    case eUninitialized: {
      break;
    }
    case eFunction: {
      DestroyFunction();
      break;
    }
    case eTrustedScript: {
      DestroyTrustedScript();
      break;
    }
    case eString: {
      DestroyString();
      break;
    }
  }
}

bool
OwningFunctionOrTrustedScriptOrString::ToJSVal(JSContext* cx, JS::Handle<JSObject*> scopeObj, JS::MutableHandle<JS::Value> rval) const
{
  switch (mType) {
    case eUninitialized: {
      return false;
    }
    case eFunction: {
      rval.setObjectOrNull(GetCallbackFromCallbackObject(cx, mValue.mFunction.Value()));
      if (!MaybeWrapObjectValue(cx, rval)) {
        return false;
      }
      return true;
    }
    case eTrustedScript: {
      if (!WrapNewBindingNonWrapperCachedObject(cx, scopeObj, mValue.mTrustedScript.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;
    }
  }
}

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



} // namespace mozilla::dom
