#ifndef mozilla_dom_UnionConversions_h__
#define mozilla_dom_UnionConversions_h__

#include "CanvasRenderingContext2DBinding.h"
#include "ElementBinding.h"
#include "EventBinding.h"
#include "HTMLCanvasElementBinding.h"
#include "HTMLElementBinding.h"
#include "HTMLImageElementBinding.h"
#include "HTMLOptGroupElementBinding.h"
#include "HTMLOptionElementBinding.h"
#include "HTMLVideoElementBinding.h"
#include "IDBCursorBinding.h"
#include "IDBIndexBinding.h"
#include "IDBObjectStoreBinding.h"
#include "MessagePortBinding.h"
#include "NodeListBinding.h"
#include "TelephonyCallBinding.h"
#include "TelephonyCallGroupBinding.h"
#include "XPCWrapper.h"
#include "mozilla/dom/PrimitiveConversions.h"
#include "mozilla/dom/UnionTypes.h"
#include "nsDebug.h"

namespace mozilla {
namespace dom {
class BooleanOrObjectArgument
{
  BooleanOrObject& mUnion;

  BooleanOrObjectArgument(const BooleanOrObjectArgument&) MOZ_DELETE;
  void operator=(const BooleanOrObjectArgument) MOZ_DELETE;

public:
  explicit inline BooleanOrObjectArgument(const BooleanOrObject& aUnion)
    : mUnion(const_cast<BooleanOrObject&>(aUnion))
  {
  }

  inline bool
  TrySetToBoolean(JSContext* cx, JS::Handle<JS::Value> value, JS::MutableHandle<JS::Value> pvalue, bool& tryNext)
  {
    tryNext = false;
    { // scope for memberSlot
      bool& memberSlot = SetAsBoolean();
      if (!ValueToPrimitive<bool, eDefault>(cx, value, &memberSlot)) {
        return false;
      }
    }
    return true;
  }

  inline void
  SetToObject(JSContext* cx, JSObject* obj)
  {
    mUnion.mValue.mObject.SetValue(cx, obj);
    mUnion.mType = mUnion.eObject;
  }

private:
  inline bool&
  SetAsBoolean()
  {
    mUnion.mType = mUnion.eBoolean;
    return mUnion.mValue.mBoolean.SetValue();
  }
};

class EventOrStringArgument
{
  EventOrString& mUnion;
  FakeDependentString mStringHolder;

  EventOrStringArgument(const EventOrStringArgument&) MOZ_DELETE;
  void operator=(const EventOrStringArgument) MOZ_DELETE;

public:
  explicit inline EventOrStringArgument(const EventOrString& aUnion)
    : mUnion(const_cast<EventOrString&>(aUnion))
  {
  }

  inline bool
  TrySetToEvent(JSContext* cx, JS::Handle<JS::Value> value, JS::MutableHandle<JS::Value> pvalue, bool& tryNext)
  {
    tryNext = false;
    { // scope for memberSlot
      NonNull<nsDOMEvent>& memberSlot = SetAsEvent();
      {
        nsresult rv = UnwrapObject<prototypes::id::Event, nsDOMEvent>(cx, &value.toObject(), memberSlot);
        if (NS_FAILED(rv)) {
          if (mUnion.mType != mUnion.eUninitialized) {  mUnion.DestroyEvent();}tryNext = true;
          return true;
        }
      }
    }
    return true;
  }

  inline bool
  TrySetToString(JSContext* cx, JS::Handle<JS::Value> value, JS::MutableHandle<JS::Value> pvalue, bool& tryNext)
  {
    tryNext = false;
    { // scope for memberSlot
      NonNull<nsAString>& memberSlot = SetAsString();
      if (!ConvertJSValueToString(cx, value, pvalue, eStringify, eStringify, mStringHolder)) {
        return false;
      }
      memberSlot = &mStringHolder;
    }
    return true;
  }

  inline void
  SetStringData(const nsDependentString::char_type* aData, nsDependentString::size_type aLength)
  {
    mStringHolder.SetData(aData, aLength);
  }

private:
  inline NonNull<nsDOMEvent>&
  SetAsEvent()
  {
    mUnion.mType = mUnion.eEvent;
    return mUnion.mValue.mEvent.SetValue();
  }

  inline NonNull<nsAString>&
  SetAsString()
  {
    mUnion.mType = mUnion.eString;
    return mUnion.mValue.mString.SetValue();
  }
};

class HTMLElementOrLongArgument
{
  HTMLElementOrLong& mUnion;

  HTMLElementOrLongArgument(const HTMLElementOrLongArgument&) MOZ_DELETE;
  void operator=(const HTMLElementOrLongArgument) MOZ_DELETE;

public:
  explicit inline HTMLElementOrLongArgument(const HTMLElementOrLong& aUnion)
    : mUnion(const_cast<HTMLElementOrLong&>(aUnion))
  {
  }

  inline bool
  TrySetToHTMLElement(JSContext* cx, JS::Handle<JS::Value> value, JS::MutableHandle<JS::Value> pvalue, bool& tryNext)
  {
    tryNext = false;
    { // scope for memberSlot
      NonNull<nsGenericHTMLElement>& memberSlot = SetAsHTMLElement();
      {
        nsresult rv = UnwrapObject<prototypes::id::HTMLElement, nsGenericHTMLElement>(cx, &value.toObject(), memberSlot);
        if (NS_FAILED(rv)) {
          if (mUnion.mType != mUnion.eUninitialized) {  mUnion.DestroyHTMLElement();}tryNext = true;
          return true;
        }
      }
    }
    return true;
  }

  inline bool
  TrySetToLong(JSContext* cx, JS::Handle<JS::Value> value, JS::MutableHandle<JS::Value> pvalue, bool& tryNext)
  {
    tryNext = false;
    { // scope for memberSlot
      int32_t& memberSlot = SetAsLong();
      if (!ValueToPrimitive<int32_t, eDefault>(cx, value, &memberSlot)) {
        return false;
      }
    }
    return true;
  }

private:
  inline NonNull<nsGenericHTMLElement>&
  SetAsHTMLElement()
  {
    mUnion.mType = mUnion.eHTMLElement;
    return mUnion.mValue.mHTMLElement.SetValue();
  }

  inline int32_t&
  SetAsLong()
  {
    mUnion.mType = mUnion.eLong;
    return mUnion.mValue.mLong.SetValue();
  }
};

class HTMLImageElementOrHTMLCanvasElementOrHTMLVideoElementArgument
{
  HTMLImageElementOrHTMLCanvasElementOrHTMLVideoElement& mUnion;

  HTMLImageElementOrHTMLCanvasElementOrHTMLVideoElementArgument(const HTMLImageElementOrHTMLCanvasElementOrHTMLVideoElementArgument&) MOZ_DELETE;
  void operator=(const HTMLImageElementOrHTMLCanvasElementOrHTMLVideoElementArgument) MOZ_DELETE;

public:
  explicit inline HTMLImageElementOrHTMLCanvasElementOrHTMLVideoElementArgument(const HTMLImageElementOrHTMLCanvasElementOrHTMLVideoElement& aUnion)
    : mUnion(const_cast<HTMLImageElementOrHTMLCanvasElementOrHTMLVideoElement&>(aUnion))
  {
  }

  inline bool
  TrySetToHTMLImageElement(JSContext* cx, JS::Handle<JS::Value> value, JS::MutableHandle<JS::Value> pvalue, bool& tryNext)
  {
    tryNext = false;
    { // scope for memberSlot
      NonNull<mozilla::dom::HTMLImageElement>& memberSlot = SetAsHTMLImageElement();
      {
        nsresult rv = UnwrapObject<prototypes::id::HTMLImageElement, mozilla::dom::HTMLImageElement>(cx, &value.toObject(), memberSlot);
        if (NS_FAILED(rv)) {
          if (mUnion.mType != mUnion.eUninitialized) {  mUnion.DestroyHTMLImageElement();}tryNext = true;
          return true;
        }
      }
    }
    return true;
  }

  inline bool
  TrySetToHTMLCanvasElement(JSContext* cx, JS::Handle<JS::Value> value, JS::MutableHandle<JS::Value> pvalue, bool& tryNext)
  {
    tryNext = false;
    { // scope for memberSlot
      NonNull<mozilla::dom::HTMLCanvasElement>& memberSlot = SetAsHTMLCanvasElement();
      {
        nsresult rv = UnwrapObject<prototypes::id::HTMLCanvasElement, mozilla::dom::HTMLCanvasElement>(cx, &value.toObject(), memberSlot);
        if (NS_FAILED(rv)) {
          if (mUnion.mType != mUnion.eUninitialized) {  mUnion.DestroyHTMLCanvasElement();}tryNext = true;
          return true;
        }
      }
    }
    return true;
  }

  inline bool
  TrySetToHTMLVideoElement(JSContext* cx, JS::Handle<JS::Value> value, JS::MutableHandle<JS::Value> pvalue, bool& tryNext)
  {
    tryNext = false;
    { // scope for memberSlot
      NonNull<mozilla::dom::HTMLVideoElement>& memberSlot = SetAsHTMLVideoElement();
      {
        nsresult rv = UnwrapObject<prototypes::id::HTMLVideoElement, mozilla::dom::HTMLVideoElement>(cx, &value.toObject(), memberSlot);
        if (NS_FAILED(rv)) {
          if (mUnion.mType != mUnion.eUninitialized) {  mUnion.DestroyHTMLVideoElement();}tryNext = true;
          return true;
        }
      }
    }
    return true;
  }

private:
  inline NonNull<mozilla::dom::HTMLImageElement>&
  SetAsHTMLImageElement()
  {
    mUnion.mType = mUnion.eHTMLImageElement;
    return mUnion.mValue.mHTMLImageElement.SetValue();
  }

  inline NonNull<mozilla::dom::HTMLCanvasElement>&
  SetAsHTMLCanvasElement()
  {
    mUnion.mType = mUnion.eHTMLCanvasElement;
    return mUnion.mValue.mHTMLCanvasElement.SetValue();
  }

  inline NonNull<mozilla::dom::HTMLVideoElement>&
  SetAsHTMLVideoElement()
  {
    mUnion.mType = mUnion.eHTMLVideoElement;
    return mUnion.mValue.mHTMLVideoElement.SetValue();
  }
};

class HTMLOptionElementOrHTMLOptGroupElementArgument
{
  HTMLOptionElementOrHTMLOptGroupElement& mUnion;

  HTMLOptionElementOrHTMLOptGroupElementArgument(const HTMLOptionElementOrHTMLOptGroupElementArgument&) MOZ_DELETE;
  void operator=(const HTMLOptionElementOrHTMLOptGroupElementArgument) MOZ_DELETE;

public:
  explicit inline HTMLOptionElementOrHTMLOptGroupElementArgument(const HTMLOptionElementOrHTMLOptGroupElement& aUnion)
    : mUnion(const_cast<HTMLOptionElementOrHTMLOptGroupElement&>(aUnion))
  {
  }

  inline bool
  TrySetToHTMLOptionElement(JSContext* cx, JS::Handle<JS::Value> value, JS::MutableHandle<JS::Value> pvalue, bool& tryNext)
  {
    tryNext = false;
    { // scope for memberSlot
      NonNull<mozilla::dom::HTMLOptionElement>& memberSlot = SetAsHTMLOptionElement();
      {
        nsresult rv = UnwrapObject<prototypes::id::HTMLOptionElement, mozilla::dom::HTMLOptionElement>(cx, &value.toObject(), memberSlot);
        if (NS_FAILED(rv)) {
          if (mUnion.mType != mUnion.eUninitialized) {  mUnion.DestroyHTMLOptionElement();}tryNext = true;
          return true;
        }
      }
    }
    return true;
  }

  inline bool
  TrySetToHTMLOptGroupElement(JSContext* cx, JS::Handle<JS::Value> value, JS::MutableHandle<JS::Value> pvalue, bool& tryNext)
  {
    tryNext = false;
    { // scope for memberSlot
      NonNull<mozilla::dom::HTMLOptGroupElement>& memberSlot = SetAsHTMLOptGroupElement();
      {
        nsresult rv = UnwrapObject<prototypes::id::HTMLOptGroupElement, mozilla::dom::HTMLOptGroupElement>(cx, &value.toObject(), memberSlot);
        if (NS_FAILED(rv)) {
          if (mUnion.mType != mUnion.eUninitialized) {  mUnion.DestroyHTMLOptGroupElement();}tryNext = true;
          return true;
        }
      }
    }
    return true;
  }

private:
  inline NonNull<mozilla::dom::HTMLOptionElement>&
  SetAsHTMLOptionElement()
  {
    mUnion.mType = mUnion.eHTMLOptionElement;
    return mUnion.mValue.mHTMLOptionElement.SetValue();
  }

  inline NonNull<mozilla::dom::HTMLOptGroupElement>&
  SetAsHTMLOptGroupElement()
  {
    mUnion.mType = mUnion.eHTMLOptGroupElement;
    return mUnion.mValue.mHTMLOptGroupElement.SetValue();
  }
};

class IDBObjectStoreOrIDBIndexArgument
{
  IDBObjectStoreOrIDBIndex& mUnion;

  IDBObjectStoreOrIDBIndexArgument(const IDBObjectStoreOrIDBIndexArgument&) MOZ_DELETE;
  void operator=(const IDBObjectStoreOrIDBIndexArgument) MOZ_DELETE;

public:
  explicit inline IDBObjectStoreOrIDBIndexArgument(const IDBObjectStoreOrIDBIndex& aUnion)
    : mUnion(const_cast<IDBObjectStoreOrIDBIndex&>(aUnion))
  {
  }

  inline bool
  TrySetToIDBObjectStore(JSContext* cx, JS::Handle<JS::Value> value, JS::MutableHandle<JS::Value> pvalue, bool& tryNext)
  {
    tryNext = false;
    { // scope for memberSlot
      NonNull<mozilla::dom::indexedDB::IDBObjectStore>& memberSlot = SetAsIDBObjectStore();
      {
        nsresult rv = UnwrapObject<prototypes::id::IDBObjectStore, mozilla::dom::indexedDB::IDBObjectStore>(cx, &value.toObject(), memberSlot);
        if (NS_FAILED(rv)) {
          if (mUnion.mType != mUnion.eUninitialized) {  mUnion.DestroyIDBObjectStore();}tryNext = true;
          return true;
        }
      }
    }
    return true;
  }

  inline bool
  TrySetToIDBIndex(JSContext* cx, JS::Handle<JS::Value> value, JS::MutableHandle<JS::Value> pvalue, bool& tryNext)
  {
    tryNext = false;
    { // scope for memberSlot
      NonNull<mozilla::dom::indexedDB::IDBIndex>& memberSlot = SetAsIDBIndex();
      {
        nsresult rv = UnwrapObject<prototypes::id::IDBIndex, mozilla::dom::indexedDB::IDBIndex>(cx, &value.toObject(), memberSlot);
        if (NS_FAILED(rv)) {
          if (mUnion.mType != mUnion.eUninitialized) {  mUnion.DestroyIDBIndex();}tryNext = true;
          return true;
        }
      }
    }
    return true;
  }

private:
  inline NonNull<mozilla::dom::indexedDB::IDBObjectStore>&
  SetAsIDBObjectStore()
  {
    mUnion.mType = mUnion.eIDBObjectStore;
    return mUnion.mValue.mIDBObjectStore.SetValue();
  }

  inline NonNull<mozilla::dom::indexedDB::IDBIndex>&
  SetAsIDBIndex()
  {
    mUnion.mType = mUnion.eIDBIndex;
    return mUnion.mValue.mIDBIndex.SetValue();
  }
};

class IDBObjectStoreOrIDBIndexOrIDBCursorArgument
{
  IDBObjectStoreOrIDBIndexOrIDBCursor& mUnion;

  IDBObjectStoreOrIDBIndexOrIDBCursorArgument(const IDBObjectStoreOrIDBIndexOrIDBCursorArgument&) MOZ_DELETE;
  void operator=(const IDBObjectStoreOrIDBIndexOrIDBCursorArgument) MOZ_DELETE;

public:
  explicit inline IDBObjectStoreOrIDBIndexOrIDBCursorArgument(const IDBObjectStoreOrIDBIndexOrIDBCursor& aUnion)
    : mUnion(const_cast<IDBObjectStoreOrIDBIndexOrIDBCursor&>(aUnion))
  {
  }

  inline bool
  TrySetToIDBObjectStore(JSContext* cx, JS::Handle<JS::Value> value, JS::MutableHandle<JS::Value> pvalue, bool& tryNext)
  {
    tryNext = false;
    { // scope for memberSlot
      NonNull<mozilla::dom::indexedDB::IDBObjectStore>& memberSlot = SetAsIDBObjectStore();
      {
        nsresult rv = UnwrapObject<prototypes::id::IDBObjectStore, mozilla::dom::indexedDB::IDBObjectStore>(cx, &value.toObject(), memberSlot);
        if (NS_FAILED(rv)) {
          if (mUnion.mType != mUnion.eUninitialized) {  mUnion.DestroyIDBObjectStore();}tryNext = true;
          return true;
        }
      }
    }
    return true;
  }

  inline bool
  TrySetToIDBIndex(JSContext* cx, JS::Handle<JS::Value> value, JS::MutableHandle<JS::Value> pvalue, bool& tryNext)
  {
    tryNext = false;
    { // scope for memberSlot
      NonNull<mozilla::dom::indexedDB::IDBIndex>& memberSlot = SetAsIDBIndex();
      {
        nsresult rv = UnwrapObject<prototypes::id::IDBIndex, mozilla::dom::indexedDB::IDBIndex>(cx, &value.toObject(), memberSlot);
        if (NS_FAILED(rv)) {
          if (mUnion.mType != mUnion.eUninitialized) {  mUnion.DestroyIDBIndex();}tryNext = true;
          return true;
        }
      }
    }
    return true;
  }

  inline bool
  TrySetToIDBCursor(JSContext* cx, JS::Handle<JS::Value> value, JS::MutableHandle<JS::Value> pvalue, bool& tryNext)
  {
    tryNext = false;
    { // scope for memberSlot
      NonNull<mozilla::dom::indexedDB::IDBCursor>& memberSlot = SetAsIDBCursor();
      {
        nsresult rv = UnwrapObject<prototypes::id::IDBCursor, mozilla::dom::indexedDB::IDBCursor>(cx, &value.toObject(), memberSlot);
        if (NS_FAILED(rv)) {
          if (mUnion.mType != mUnion.eUninitialized) {  mUnion.DestroyIDBCursor();}tryNext = true;
          return true;
        }
      }
    }
    return true;
  }

private:
  inline NonNull<mozilla::dom::indexedDB::IDBObjectStore>&
  SetAsIDBObjectStore()
  {
    mUnion.mType = mUnion.eIDBObjectStore;
    return mUnion.mValue.mIDBObjectStore.SetValue();
  }

  inline NonNull<mozilla::dom::indexedDB::IDBIndex>&
  SetAsIDBIndex()
  {
    mUnion.mType = mUnion.eIDBIndex;
    return mUnion.mValue.mIDBIndex.SetValue();
  }

  inline NonNull<mozilla::dom::indexedDB::IDBCursor>&
  SetAsIDBCursor()
  {
    mUnion.mType = mUnion.eIDBCursor;
    return mUnion.mValue.mIDBCursor.SetValue();
  }
};

class NodeListOrElementArgument
{
  NodeListOrElement& mUnion;

  NodeListOrElementArgument(const NodeListOrElementArgument&) MOZ_DELETE;
  void operator=(const NodeListOrElementArgument) MOZ_DELETE;

public:
  explicit inline NodeListOrElementArgument(const NodeListOrElement& aUnion)
    : mUnion(const_cast<NodeListOrElement&>(aUnion))
  {
  }

  inline bool
  TrySetToNodeList(JSContext* cx, JS::Handle<JS::Value> value, JS::MutableHandle<JS::Value> pvalue, bool& tryNext)
  {
    tryNext = false;
    { // scope for memberSlot
      NonNull<nsINodeList>& memberSlot = SetAsNodeList();
      {
        nsresult rv = UnwrapObject<prototypes::id::NodeList, nsINodeList>(cx, &value.toObject(), memberSlot);
        if (NS_FAILED(rv)) {
          if (mUnion.mType != mUnion.eUninitialized) {  mUnion.DestroyNodeList();}tryNext = true;
          return true;
        }
      }
    }
    return true;
  }

  inline bool
  TrySetToElement(JSContext* cx, JS::Handle<JS::Value> value, JS::MutableHandle<JS::Value> pvalue, bool& tryNext)
  {
    tryNext = false;
    { // scope for memberSlot
      NonNull<mozilla::dom::Element>& memberSlot = SetAsElement();
      {
        nsresult rv = UnwrapObject<prototypes::id::Element, mozilla::dom::Element>(cx, &value.toObject(), memberSlot);
        if (NS_FAILED(rv)) {
          if (mUnion.mType != mUnion.eUninitialized) {  mUnion.DestroyElement();}tryNext = true;
          return true;
        }
      }
    }
    return true;
  }

private:
  inline NonNull<nsINodeList>&
  SetAsNodeList()
  {
    mUnion.mType = mUnion.eNodeList;
    return mUnion.mValue.mNodeList.SetValue();
  }

  inline NonNull<mozilla::dom::Element>&
  SetAsElement()
  {
    mUnion.mType = mUnion.eElement;
    return mUnion.mValue.mElement.SetValue();
  }
};

class StringOrCanvasGradientOrCanvasPatternArgument
{
  StringOrCanvasGradientOrCanvasPattern& mUnion;
  FakeDependentString mStringHolder;

  StringOrCanvasGradientOrCanvasPatternArgument(const StringOrCanvasGradientOrCanvasPatternArgument&) MOZ_DELETE;
  void operator=(const StringOrCanvasGradientOrCanvasPatternArgument) MOZ_DELETE;

public:
  explicit inline StringOrCanvasGradientOrCanvasPatternArgument(const StringOrCanvasGradientOrCanvasPattern& aUnion)
    : mUnion(const_cast<StringOrCanvasGradientOrCanvasPattern&>(aUnion))
  {
  }

  inline bool
  TrySetToString(JSContext* cx, JS::Handle<JS::Value> value, JS::MutableHandle<JS::Value> pvalue, bool& tryNext)
  {
    tryNext = false;
    { // scope for memberSlot
      NonNull<nsAString>& memberSlot = SetAsString();
      if (!ConvertJSValueToString(cx, value, pvalue, eStringify, eStringify, mStringHolder)) {
        return false;
      }
      memberSlot = &mStringHolder;
    }
    return true;
  }

  inline void
  SetStringData(const nsDependentString::char_type* aData, nsDependentString::size_type aLength)
  {
    mStringHolder.SetData(aData, aLength);
  }

  inline bool
  TrySetToCanvasGradient(JSContext* cx, JS::Handle<JS::Value> value, JS::MutableHandle<JS::Value> pvalue, bool& tryNext)
  {
    tryNext = false;
    { // scope for memberSlot
      NonNull<mozilla::dom::CanvasGradient>& memberSlot = SetAsCanvasGradient();
      {
        nsresult rv = UnwrapObject<prototypes::id::CanvasGradient, mozilla::dom::CanvasGradient>(cx, &value.toObject(), memberSlot);
        if (NS_FAILED(rv)) {
          if (mUnion.mType != mUnion.eUninitialized) {  mUnion.DestroyCanvasGradient();}tryNext = true;
          return true;
        }
      }
    }
    return true;
  }

  inline bool
  TrySetToCanvasPattern(JSContext* cx, JS::Handle<JS::Value> value, JS::MutableHandle<JS::Value> pvalue, bool& tryNext)
  {
    tryNext = false;
    { // scope for memberSlot
      NonNull<mozilla::dom::CanvasPattern>& memberSlot = SetAsCanvasPattern();
      {
        nsresult rv = UnwrapObject<prototypes::id::CanvasPattern, mozilla::dom::CanvasPattern>(cx, &value.toObject(), memberSlot);
        if (NS_FAILED(rv)) {
          if (mUnion.mType != mUnion.eUninitialized) {  mUnion.DestroyCanvasPattern();}tryNext = true;
          return true;
        }
      }
    }
    return true;
  }

private:
  inline NonNull<nsAString>&
  SetAsString()
  {
    mUnion.mType = mUnion.eString;
    return mUnion.mValue.mString.SetValue();
  }

  inline NonNull<mozilla::dom::CanvasGradient>&
  SetAsCanvasGradient()
  {
    mUnion.mType = mUnion.eCanvasGradient;
    return mUnion.mValue.mCanvasGradient.SetValue();
  }

  inline NonNull<mozilla::dom::CanvasPattern>&
  SetAsCanvasPattern()
  {
    mUnion.mType = mUnion.eCanvasPattern;
    return mUnion.mValue.mCanvasPattern.SetValue();
  }
};

class TelephonyCallOrTelephonyCallGroupArgument
{
  TelephonyCallOrTelephonyCallGroup& mUnion;

  TelephonyCallOrTelephonyCallGroupArgument(const TelephonyCallOrTelephonyCallGroupArgument&) MOZ_DELETE;
  void operator=(const TelephonyCallOrTelephonyCallGroupArgument) MOZ_DELETE;

public:
  explicit inline TelephonyCallOrTelephonyCallGroupArgument(const TelephonyCallOrTelephonyCallGroup& aUnion)
    : mUnion(const_cast<TelephonyCallOrTelephonyCallGroup&>(aUnion))
  {
  }

  inline bool
  TrySetToTelephonyCall(JSContext* cx, JS::Handle<JS::Value> value, JS::MutableHandle<JS::Value> pvalue, bool& tryNext)
  {
    tryNext = false;
    { // scope for memberSlot
      NonNull<mozilla::dom::TelephonyCall>& memberSlot = SetAsTelephonyCall();
      {
        nsresult rv = UnwrapObject<prototypes::id::TelephonyCall, mozilla::dom::TelephonyCall>(cx, &value.toObject(), memberSlot);
        if (NS_FAILED(rv)) {
          if (mUnion.mType != mUnion.eUninitialized) {  mUnion.DestroyTelephonyCall();}tryNext = true;
          return true;
        }
      }
    }
    return true;
  }

  inline bool
  TrySetToTelephonyCallGroup(JSContext* cx, JS::Handle<JS::Value> value, JS::MutableHandle<JS::Value> pvalue, bool& tryNext)
  {
    tryNext = false;
    { // scope for memberSlot
      NonNull<mozilla::dom::TelephonyCallGroup>& memberSlot = SetAsTelephonyCallGroup();
      {
        nsresult rv = UnwrapObject<prototypes::id::TelephonyCallGroup, mozilla::dom::TelephonyCallGroup>(cx, &value.toObject(), memberSlot);
        if (NS_FAILED(rv)) {
          if (mUnion.mType != mUnion.eUninitialized) {  mUnion.DestroyTelephonyCallGroup();}tryNext = true;
          return true;
        }
      }
    }
    return true;
  }

private:
  inline NonNull<mozilla::dom::TelephonyCall>&
  SetAsTelephonyCall()
  {
    mUnion.mType = mUnion.eTelephonyCall;
    return mUnion.mValue.mTelephonyCall.SetValue();
  }

  inline NonNull<mozilla::dom::TelephonyCallGroup>&
  SetAsTelephonyCallGroup()
  {
    mUnion.mType = mUnion.eTelephonyCallGroup;
    return mUnion.mValue.mTelephonyCallGroup.SetValue();
  }
};

class WindowProxyOrMessagePortArgument
{
  WindowProxyOrMessagePort& mUnion;
  nsRefPtr<nsIDOMWindow> mWindowProxyHolder;

  WindowProxyOrMessagePortArgument(const WindowProxyOrMessagePortArgument&) MOZ_DELETE;
  void operator=(const WindowProxyOrMessagePortArgument) MOZ_DELETE;

public:
  explicit inline WindowProxyOrMessagePortArgument(const WindowProxyOrMessagePort& aUnion)
    : mUnion(const_cast<WindowProxyOrMessagePort&>(aUnion))
  {
  }

  inline bool
  TrySetToWindowProxy(JSContext* cx, JS::Handle<JS::Value> value, JS::MutableHandle<JS::Value> pvalue, bool& tryNext)
  {
    tryNext = false;
    { // scope for memberSlot
      nsIDOMWindow*& memberSlot = SetAsWindowProxy();
      JS::Rooted<JS::Value> tmpVal(cx, value);
      nsIDOMWindow* tmp;
      if (NS_FAILED(UnwrapArg<nsIDOMWindow>(cx, value, &tmp, static_cast<nsIDOMWindow**>(getter_AddRefs(mWindowProxyHolder)), &tmpVal))) {
        if (mUnion.mType != mUnion.eUninitialized) {  mUnion.DestroyWindowProxy();}tryNext = true;
        return true;
      }
      MOZ_ASSERT(tmp);
      memberSlot = tmp;
    }
    return true;
  }

  inline bool
  TrySetToMessagePort(JSContext* cx, JS::Handle<JS::Value> value, JS::MutableHandle<JS::Value> pvalue, bool& tryNext)
  {
    tryNext = false;
    { // scope for memberSlot
      NonNull<mozilla::dom::MessagePort>& memberSlot = SetAsMessagePort();
      {
        nsresult rv = UnwrapObject<prototypes::id::MessagePort, mozilla::dom::MessagePort>(cx, &value.toObject(), memberSlot);
        if (NS_FAILED(rv)) {
          if (mUnion.mType != mUnion.eUninitialized) {  mUnion.DestroyMessagePort();}tryNext = true;
          return true;
        }
      }
    }
    return true;
  }

private:
  inline nsIDOMWindow*&
  SetAsWindowProxy()
  {
    mUnion.mType = mUnion.eWindowProxy;
    return mUnion.mValue.mWindowProxy.SetValue();
  }

  inline NonNull<mozilla::dom::MessagePort>&
  SetAsMessagePort()
  {
    mUnion.mType = mUnion.eMessagePort;
    return mUnion.mValue.mMessagePort.SetValue();
  }
};


} // namespace dom
} // namespace mozilla


#endif // mozilla_dom_UnionConversions_h__
