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

#include "BufferSourceBinding.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/dom/BindingCallContext.h"
#include "mozilla/dom/NonRefcountedDOMObject.h"

namespace mozilla::dom {

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


bool
ArrayBufferViewOrArrayBuffer::TrySetToArrayBufferView(BindingCallContext& cx, JS::Handle<JS::Value> value, bool& tryNext, bool passedToJSImpl)
{
  tryNext = false;
  { // scope for memberSlot
    RootedSpiderMonkeyInterface<ArrayBufferView>& memberSlot = RawSetAsArrayBufferView(cx);
    if (!memberSlot.Init(&value.toObject())) {
      DestroyArrayBufferView();
      tryNext = true;
      return true;
    }
    if (JS::IsArrayBufferViewShared(memberSlot.Obj())) {
      cx.ThrowErrorMessage<MSG_TYPEDARRAY_IS_SHARED>("ArrayBufferView branch of (ArrayBufferView or ArrayBuffer)");
      return false;
    }
    if (JS::IsLargeArrayBufferView(memberSlot.Obj())) {
      cx.ThrowErrorMessage<MSG_TYPEDARRAY_IS_LARGE>("ArrayBufferView branch of (ArrayBufferView or ArrayBuffer)");
      return false;
    }
    if (JS::IsResizableArrayBufferView(memberSlot.Obj())) {
      cx.ThrowErrorMessage<MSG_TYPEDARRAY_IS_RESIZABLE>("ArrayBufferView branch of (ArrayBufferView or ArrayBuffer)");
      return false;
    }
    if (JS::IsImmutableArrayBufferView(memberSlot.Obj())) {
      cx.ThrowErrorMessage<MSG_TYPEDARRAY_IS_IMMUTABLE>("ArrayBufferView branch of (ArrayBufferView or ArrayBuffer)");
      return false;
    }
  }
  return true;
}

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







bool
ArrayBufferViewOrArrayBuffer::TrySetToArrayBuffer(BindingCallContext& cx, JS::Handle<JS::Value> value, bool& tryNext, bool passedToJSImpl)
{
  tryNext = false;
  { // scope for memberSlot
    RootedSpiderMonkeyInterface<ArrayBuffer>& memberSlot = RawSetAsArrayBuffer(cx);
    if (!memberSlot.Init(&value.toObject())) {
      DestroyArrayBuffer();
      tryNext = true;
      return true;
    }
    if (JS::IsSharedArrayBufferObject(memberSlot.Obj())) {
      cx.ThrowErrorMessage<MSG_TYPEDARRAY_IS_SHARED>("ArrayBuffer branch of (ArrayBufferView or ArrayBuffer)");
      return false;
    }
    if (JS::IsLargeArrayBufferMaybeShared(memberSlot.Obj())) {
      cx.ThrowErrorMessage<MSG_TYPEDARRAY_IS_LARGE>("ArrayBuffer branch of (ArrayBufferView or ArrayBuffer)");
      return false;
    }
    if (JS::IsResizableArrayBufferMaybeShared(memberSlot.Obj())) {
      cx.ThrowErrorMessage<MSG_TYPEDARRAY_IS_RESIZABLE>("ArrayBuffer branch of (ArrayBufferView or ArrayBuffer)");
      return false;
    }
    if (JS::IsImmutableArrayBufferMaybeShared(memberSlot.Obj())) {
      cx.ThrowErrorMessage<MSG_TYPEDARRAY_IS_IMMUTABLE>("ArrayBuffer branch of (ArrayBufferView or ArrayBuffer)");
      return false;
    }
  }
  return true;
}

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







bool
ArrayBufferViewOrArrayBuffer::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 = !TrySetToArrayBufferView(cx, value, tryNext, passedToJSImpl)) || !tryNext ||
           (failed = !TrySetToArrayBuffer(cx, value, tryNext, passedToJSImpl)) || !tryNext;
  }
  if (failed) {
    return false;
  }
  if (!done) {
    cx.ThrowErrorMessage<MSG_NOT_IN_UNION>(sourceDescription, "ArrayBufferView, ArrayBuffer");
    return false;
  }
  return true;
}

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


bool
ArrayBufferViewOrArrayBuffer::ToJSVal(JSContext* cx, JS::Handle<JSObject*> scopeObj, JS::MutableHandle<JS::Value> rval) const
{
  switch (mType) {
    case eUninitialized: {
      return false;
    }
    case eArrayBufferView: {
      rval.setObject(*mValue.mArrayBufferView.Value().Obj());
      if (!MaybeWrapNonDOMObjectValue(cx, rval)) {
        return false;
      }
      return true;
    }
    case eArrayBuffer: {
      rval.setObject(*mValue.mArrayBuffer.Value().Obj());
      if (!MaybeWrapNonDOMObjectValue(cx, rval)) {
        return false;
      }
      return true;
    }
    default: {
      return false;
    }
  }
}



OwningArrayBufferViewOrArrayBuffer::OwningArrayBufferViewOrArrayBuffer(OwningArrayBufferViewOrArrayBuffer&& aOther)
  : mType(eUninitialized)
{
  switch (aOther.mType) {
    case eUninitialized: {
      MOZ_ASSERT(mType == eUninitialized,
                 "We need to destroy ourselves?");
      break;
    }
    case eArrayBufferView: {
      mType = eArrayBufferView;
      mValue.mArrayBufferView.SetValue(std::move(aOther.mValue.mArrayBufferView.Value()));
      break;
    }
    case eArrayBuffer: {
      mType = eArrayBuffer;
      mValue.mArrayBuffer.SetValue(std::move(aOther.mValue.mArrayBuffer.Value()));
      break;
    }
  }
}


bool
OwningArrayBufferViewOrArrayBuffer::TrySetToArrayBufferView(BindingCallContext& cx, JS::Handle<JS::Value> value, bool& tryNext, bool passedToJSImpl)
{
  tryNext = false;
  { // scope for memberSlot
    ArrayBufferView& memberSlot = RawSetAsArrayBufferView();
    if (!memberSlot.Init(&value.toObject())) {
      DestroyArrayBufferView();
      tryNext = true;
      return true;
    }
    if (JS::IsArrayBufferViewShared(memberSlot.Obj())) {
      cx.ThrowErrorMessage<MSG_TYPEDARRAY_IS_SHARED>("ArrayBufferView branch of (ArrayBufferView or ArrayBuffer)");
      return false;
    }
    if (JS::IsLargeArrayBufferView(memberSlot.Obj())) {
      cx.ThrowErrorMessage<MSG_TYPEDARRAY_IS_LARGE>("ArrayBufferView branch of (ArrayBufferView or ArrayBuffer)");
      return false;
    }
    if (JS::IsResizableArrayBufferView(memberSlot.Obj())) {
      cx.ThrowErrorMessage<MSG_TYPEDARRAY_IS_RESIZABLE>("ArrayBufferView branch of (ArrayBufferView or ArrayBuffer)");
      return false;
    }
    if (JS::IsImmutableArrayBufferView(memberSlot.Obj())) {
      cx.ThrowErrorMessage<MSG_TYPEDARRAY_IS_IMMUTABLE>("ArrayBufferView branch of (ArrayBufferView or ArrayBuffer)");
      return false;
    }
  }
  return true;
}

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

[[nodiscard]] ArrayBufferView&
OwningArrayBufferViewOrArrayBuffer::RawSetAsArrayBufferView()
{
  if (mType == eArrayBufferView) {
    return mValue.mArrayBufferView.Value();
  }
  MOZ_ASSERT(mType == eUninitialized);
  mType = eArrayBufferView;
  return mValue.mArrayBufferView.SetValue();
}

[[nodiscard]] ArrayBufferView&
OwningArrayBufferViewOrArrayBuffer::SetAsArrayBufferView()
{
  if (mType == eArrayBufferView) {
    return mValue.mArrayBufferView.Value();
  }
  Uninit();
  mType = eArrayBufferView;
  return mValue.mArrayBufferView.SetValue();
}


void
OwningArrayBufferViewOrArrayBuffer::DestroyArrayBufferView()
{
  MOZ_RELEASE_ASSERT(IsArrayBufferView(), "Wrong type!");
  mValue.mArrayBufferView.Destroy();
  mType = eUninitialized;
}



bool
OwningArrayBufferViewOrArrayBuffer::TrySetToArrayBuffer(BindingCallContext& cx, JS::Handle<JS::Value> value, bool& tryNext, bool passedToJSImpl)
{
  tryNext = false;
  { // scope for memberSlot
    ArrayBuffer& memberSlot = RawSetAsArrayBuffer();
    if (!memberSlot.Init(&value.toObject())) {
      DestroyArrayBuffer();
      tryNext = true;
      return true;
    }
    if (JS::IsSharedArrayBufferObject(memberSlot.Obj())) {
      cx.ThrowErrorMessage<MSG_TYPEDARRAY_IS_SHARED>("ArrayBuffer branch of (ArrayBufferView or ArrayBuffer)");
      return false;
    }
    if (JS::IsLargeArrayBufferMaybeShared(memberSlot.Obj())) {
      cx.ThrowErrorMessage<MSG_TYPEDARRAY_IS_LARGE>("ArrayBuffer branch of (ArrayBufferView or ArrayBuffer)");
      return false;
    }
    if (JS::IsResizableArrayBufferMaybeShared(memberSlot.Obj())) {
      cx.ThrowErrorMessage<MSG_TYPEDARRAY_IS_RESIZABLE>("ArrayBuffer branch of (ArrayBufferView or ArrayBuffer)");
      return false;
    }
    if (JS::IsImmutableArrayBufferMaybeShared(memberSlot.Obj())) {
      cx.ThrowErrorMessage<MSG_TYPEDARRAY_IS_IMMUTABLE>("ArrayBuffer branch of (ArrayBufferView or ArrayBuffer)");
      return false;
    }
  }
  return true;
}

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

[[nodiscard]] ArrayBuffer&
OwningArrayBufferViewOrArrayBuffer::RawSetAsArrayBuffer()
{
  if (mType == eArrayBuffer) {
    return mValue.mArrayBuffer.Value();
  }
  MOZ_ASSERT(mType == eUninitialized);
  mType = eArrayBuffer;
  return mValue.mArrayBuffer.SetValue();
}

[[nodiscard]] ArrayBuffer&
OwningArrayBufferViewOrArrayBuffer::SetAsArrayBuffer()
{
  if (mType == eArrayBuffer) {
    return mValue.mArrayBuffer.Value();
  }
  Uninit();
  mType = eArrayBuffer;
  return mValue.mArrayBuffer.SetValue();
}


void
OwningArrayBufferViewOrArrayBuffer::DestroyArrayBuffer()
{
  MOZ_RELEASE_ASSERT(IsArrayBuffer(), "Wrong type!");
  mValue.mArrayBuffer.Destroy();
  mType = eUninitialized;
}



bool
OwningArrayBufferViewOrArrayBuffer::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 = !TrySetToArrayBufferView(cx, value, tryNext, passedToJSImpl)) || !tryNext ||
           (failed = !TrySetToArrayBuffer(cx, value, tryNext, passedToJSImpl)) || !tryNext;
  }
  if (failed) {
    return false;
  }
  if (!done) {
    cx.ThrowErrorMessage<MSG_NOT_IN_UNION>(sourceDescription, "ArrayBufferView, ArrayBuffer");
    return false;
  }
  return true;
}

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

void
OwningArrayBufferViewOrArrayBuffer::Uninit()
{
  switch (mType) {
    case eUninitialized: {
      break;
    }
    case eArrayBufferView: {
      DestroyArrayBufferView();
      break;
    }
    case eArrayBuffer: {
      DestroyArrayBuffer();
      break;
    }
  }
}

bool
OwningArrayBufferViewOrArrayBuffer::ToJSVal(JSContext* cx, JS::Handle<JSObject*> scopeObj, JS::MutableHandle<JS::Value> rval) const
{
  switch (mType) {
    case eUninitialized: {
      return false;
    }
    case eArrayBufferView: {
      rval.setObject(*mValue.mArrayBufferView.Value().Obj());
      if (!MaybeWrapNonDOMObjectValue(cx, rval)) {
        return false;
      }
      return true;
    }
    case eArrayBuffer: {
      rval.setObject(*mValue.mArrayBuffer.Value().Obj());
      if (!MaybeWrapNonDOMObjectValue(cx, rval)) {
        return false;
      }
      return true;
    }
    default: {
      return false;
    }
  }
}

void
OwningArrayBufferViewOrArrayBuffer::TraceUnion(JSTracer* trc)
{
  switch (mType) {
    case eArrayBufferView: {
      mValue.mArrayBufferView.Value().TraceSelf(trc);
      break;
    }
    case eArrayBuffer: {
      mValue.mArrayBuffer.Value().TraceSelf(trc);
      break;
    }
    default: {
    }
  }
}

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



bool
MaybeSharedArrayBufferOrMaybeSharedArrayBufferView::TrySetToArrayBuffer(BindingCallContext& cx, JS::Handle<JS::Value> value, bool& tryNext, bool passedToJSImpl)
{
  tryNext = false;
  { // scope for memberSlot
    RootedSpiderMonkeyInterface<ArrayBuffer>& memberSlot = RawSetAsArrayBuffer(cx);
    if (!memberSlot.Init(&value.toObject())) {
      DestroyArrayBuffer();
      tryNext = true;
      return true;
    }
    if (JS::IsLargeArrayBufferMaybeShared(memberSlot.Obj())) {
      cx.ThrowErrorMessage<MSG_TYPEDARRAY_IS_LARGE>("ArrayBuffer branch of (ArrayBuffer or ArrayBufferView)");
      return false;
    }
    if (JS::IsResizableArrayBufferMaybeShared(memberSlot.Obj())) {
      cx.ThrowErrorMessage<MSG_TYPEDARRAY_IS_RESIZABLE>("ArrayBuffer branch of (ArrayBuffer or ArrayBufferView)");
      return false;
    }
    if (JS::IsImmutableArrayBufferMaybeShared(memberSlot.Obj())) {
      cx.ThrowErrorMessage<MSG_TYPEDARRAY_IS_IMMUTABLE>("ArrayBuffer branch of (ArrayBuffer or ArrayBufferView)");
      return false;
    }
  }
  return true;
}

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







bool
MaybeSharedArrayBufferOrMaybeSharedArrayBufferView::TrySetToArrayBufferView(BindingCallContext& cx, JS::Handle<JS::Value> value, bool& tryNext, bool passedToJSImpl)
{
  tryNext = false;
  { // scope for memberSlot
    RootedSpiderMonkeyInterface<ArrayBufferView>& memberSlot = RawSetAsArrayBufferView(cx);
    if (!memberSlot.Init(&value.toObject())) {
      DestroyArrayBufferView();
      tryNext = true;
      return true;
    }
    if (JS::IsLargeArrayBufferView(memberSlot.Obj())) {
      cx.ThrowErrorMessage<MSG_TYPEDARRAY_IS_LARGE>("ArrayBufferView branch of (ArrayBuffer or ArrayBufferView)");
      return false;
    }
    if (JS::IsResizableArrayBufferView(memberSlot.Obj())) {
      cx.ThrowErrorMessage<MSG_TYPEDARRAY_IS_RESIZABLE>("ArrayBufferView branch of (ArrayBuffer or ArrayBufferView)");
      return false;
    }
    if (JS::IsImmutableArrayBufferView(memberSlot.Obj())) {
      cx.ThrowErrorMessage<MSG_TYPEDARRAY_IS_IMMUTABLE>("ArrayBufferView branch of (ArrayBuffer or ArrayBufferView)");
      return false;
    }
  }
  return true;
}

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







bool
MaybeSharedArrayBufferOrMaybeSharedArrayBufferView::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 = !TrySetToArrayBuffer(cx, value, tryNext, passedToJSImpl)) || !tryNext ||
           (failed = !TrySetToArrayBufferView(cx, value, tryNext, passedToJSImpl)) || !tryNext;
  }
  if (failed) {
    return false;
  }
  if (!done) {
    cx.ThrowErrorMessage<MSG_NOT_IN_UNION>(sourceDescription, "ArrayBuffer, ArrayBufferView");
    return false;
  }
  return true;
}

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


bool
MaybeSharedArrayBufferOrMaybeSharedArrayBufferView::ToJSVal(JSContext* cx, JS::Handle<JSObject*> scopeObj, JS::MutableHandle<JS::Value> rval) const
{
  switch (mType) {
    case eUninitialized: {
      return false;
    }
    case eArrayBuffer: {
      rval.setObject(*mValue.mArrayBuffer.Value().Obj());
      if (!MaybeWrapNonDOMObjectValue(cx, rval)) {
        return false;
      }
      return true;
    }
    case eArrayBufferView: {
      rval.setObject(*mValue.mArrayBufferView.Value().Obj());
      if (!MaybeWrapNonDOMObjectValue(cx, rval)) {
        return false;
      }
      return true;
    }
    default: {
      return false;
    }
  }
}



OwningMaybeSharedArrayBufferOrMaybeSharedArrayBufferView::OwningMaybeSharedArrayBufferOrMaybeSharedArrayBufferView(OwningMaybeSharedArrayBufferOrMaybeSharedArrayBufferView&& aOther)
  : mType(eUninitialized)
{
  switch (aOther.mType) {
    case eUninitialized: {
      MOZ_ASSERT(mType == eUninitialized,
                 "We need to destroy ourselves?");
      break;
    }
    case eArrayBuffer: {
      mType = eArrayBuffer;
      mValue.mArrayBuffer.SetValue(std::move(aOther.mValue.mArrayBuffer.Value()));
      break;
    }
    case eArrayBufferView: {
      mType = eArrayBufferView;
      mValue.mArrayBufferView.SetValue(std::move(aOther.mValue.mArrayBufferView.Value()));
      break;
    }
  }
}


bool
OwningMaybeSharedArrayBufferOrMaybeSharedArrayBufferView::TrySetToArrayBuffer(BindingCallContext& cx, JS::Handle<JS::Value> value, bool& tryNext, bool passedToJSImpl)
{
  tryNext = false;
  { // scope for memberSlot
    ArrayBuffer& memberSlot = RawSetAsArrayBuffer();
    if (!memberSlot.Init(&value.toObject())) {
      DestroyArrayBuffer();
      tryNext = true;
      return true;
    }
    if (JS::IsLargeArrayBufferMaybeShared(memberSlot.Obj())) {
      cx.ThrowErrorMessage<MSG_TYPEDARRAY_IS_LARGE>("ArrayBuffer branch of (ArrayBuffer or ArrayBufferView)");
      return false;
    }
    if (JS::IsResizableArrayBufferMaybeShared(memberSlot.Obj())) {
      cx.ThrowErrorMessage<MSG_TYPEDARRAY_IS_RESIZABLE>("ArrayBuffer branch of (ArrayBuffer or ArrayBufferView)");
      return false;
    }
    if (JS::IsImmutableArrayBufferMaybeShared(memberSlot.Obj())) {
      cx.ThrowErrorMessage<MSG_TYPEDARRAY_IS_IMMUTABLE>("ArrayBuffer branch of (ArrayBuffer or ArrayBufferView)");
      return false;
    }
  }
  return true;
}

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

[[nodiscard]] ArrayBuffer&
OwningMaybeSharedArrayBufferOrMaybeSharedArrayBufferView::RawSetAsArrayBuffer()
{
  if (mType == eArrayBuffer) {
    return mValue.mArrayBuffer.Value();
  }
  MOZ_ASSERT(mType == eUninitialized);
  mType = eArrayBuffer;
  return mValue.mArrayBuffer.SetValue();
}

[[nodiscard]] ArrayBuffer&
OwningMaybeSharedArrayBufferOrMaybeSharedArrayBufferView::SetAsArrayBuffer()
{
  if (mType == eArrayBuffer) {
    return mValue.mArrayBuffer.Value();
  }
  Uninit();
  mType = eArrayBuffer;
  return mValue.mArrayBuffer.SetValue();
}


void
OwningMaybeSharedArrayBufferOrMaybeSharedArrayBufferView::DestroyArrayBuffer()
{
  MOZ_RELEASE_ASSERT(IsArrayBuffer(), "Wrong type!");
  mValue.mArrayBuffer.Destroy();
  mType = eUninitialized;
}



bool
OwningMaybeSharedArrayBufferOrMaybeSharedArrayBufferView::TrySetToArrayBufferView(BindingCallContext& cx, JS::Handle<JS::Value> value, bool& tryNext, bool passedToJSImpl)
{
  tryNext = false;
  { // scope for memberSlot
    ArrayBufferView& memberSlot = RawSetAsArrayBufferView();
    if (!memberSlot.Init(&value.toObject())) {
      DestroyArrayBufferView();
      tryNext = true;
      return true;
    }
    if (JS::IsLargeArrayBufferView(memberSlot.Obj())) {
      cx.ThrowErrorMessage<MSG_TYPEDARRAY_IS_LARGE>("ArrayBufferView branch of (ArrayBuffer or ArrayBufferView)");
      return false;
    }
    if (JS::IsResizableArrayBufferView(memberSlot.Obj())) {
      cx.ThrowErrorMessage<MSG_TYPEDARRAY_IS_RESIZABLE>("ArrayBufferView branch of (ArrayBuffer or ArrayBufferView)");
      return false;
    }
    if (JS::IsImmutableArrayBufferView(memberSlot.Obj())) {
      cx.ThrowErrorMessage<MSG_TYPEDARRAY_IS_IMMUTABLE>("ArrayBufferView branch of (ArrayBuffer or ArrayBufferView)");
      return false;
    }
  }
  return true;
}

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

[[nodiscard]] ArrayBufferView&
OwningMaybeSharedArrayBufferOrMaybeSharedArrayBufferView::RawSetAsArrayBufferView()
{
  if (mType == eArrayBufferView) {
    return mValue.mArrayBufferView.Value();
  }
  MOZ_ASSERT(mType == eUninitialized);
  mType = eArrayBufferView;
  return mValue.mArrayBufferView.SetValue();
}

[[nodiscard]] ArrayBufferView&
OwningMaybeSharedArrayBufferOrMaybeSharedArrayBufferView::SetAsArrayBufferView()
{
  if (mType == eArrayBufferView) {
    return mValue.mArrayBufferView.Value();
  }
  Uninit();
  mType = eArrayBufferView;
  return mValue.mArrayBufferView.SetValue();
}


void
OwningMaybeSharedArrayBufferOrMaybeSharedArrayBufferView::DestroyArrayBufferView()
{
  MOZ_RELEASE_ASSERT(IsArrayBufferView(), "Wrong type!");
  mValue.mArrayBufferView.Destroy();
  mType = eUninitialized;
}



bool
OwningMaybeSharedArrayBufferOrMaybeSharedArrayBufferView::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 = !TrySetToArrayBuffer(cx, value, tryNext, passedToJSImpl)) || !tryNext ||
           (failed = !TrySetToArrayBufferView(cx, value, tryNext, passedToJSImpl)) || !tryNext;
  }
  if (failed) {
    return false;
  }
  if (!done) {
    cx.ThrowErrorMessage<MSG_NOT_IN_UNION>(sourceDescription, "ArrayBuffer, ArrayBufferView");
    return false;
  }
  return true;
}

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

void
OwningMaybeSharedArrayBufferOrMaybeSharedArrayBufferView::Uninit()
{
  switch (mType) {
    case eUninitialized: {
      break;
    }
    case eArrayBuffer: {
      DestroyArrayBuffer();
      break;
    }
    case eArrayBufferView: {
      DestroyArrayBufferView();
      break;
    }
  }
}

bool
OwningMaybeSharedArrayBufferOrMaybeSharedArrayBufferView::ToJSVal(JSContext* cx, JS::Handle<JSObject*> scopeObj, JS::MutableHandle<JS::Value> rval) const
{
  switch (mType) {
    case eUninitialized: {
      return false;
    }
    case eArrayBuffer: {
      rval.setObject(*mValue.mArrayBuffer.Value().Obj());
      if (!MaybeWrapNonDOMObjectValue(cx, rval)) {
        return false;
      }
      return true;
    }
    case eArrayBufferView: {
      rval.setObject(*mValue.mArrayBufferView.Value().Obj());
      if (!MaybeWrapNonDOMObjectValue(cx, rval)) {
        return false;
      }
      return true;
    }
    default: {
      return false;
    }
  }
}

void
OwningMaybeSharedArrayBufferOrMaybeSharedArrayBufferView::TraceUnion(JSTracer* trc)
{
  switch (mType) {
    case eArrayBuffer: {
      mValue.mArrayBuffer.Value().TraceSelf(trc);
      break;
    }
    case eArrayBufferView: {
      mValue.mArrayBufferView.Value().TraceSelf(trc);
      break;
    }
    default: {
    }
  }
}

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



} // namespace mozilla::dom
