#ifndef mozilla_dom_UnionTypes_h
#define mozilla_dom_UnionTypes_h

#include "InstallTriggerBinding.h"
#include "MediaStreamTrackBinding.h"
#include "VTTCueBinding.h"
#include "jsfriendapi.h"
#include "mozilla/dom/BindingDeclarations.h"
#include "mozilla/dom/BindingUtils.h"
#include "mozilla/dom/MozMap.h"
#include "mozilla/dom/OwningNonNull.h"
#include "mozilla/dom/TypedArray.h"
#include "mozilla/dom/UnionMember.h"

namespace mozilla {
namespace dom {
class AudioTrack;
class CanvasGradient;
class CanvasPattern;
class Directory;
class Element;
class Event;
class External;
class File;
class HTMLCanvasElement;
class HTMLImageElement;
class HTMLOptGroupElement;
class HTMLOptionElement;
class HTMLVideoElement;
class Headers;
class MessagePortBase;
class NetworkStatsData;
class OwningArrayBufferOrArrayBufferViewOrBlobOrString;
class OwningArrayBufferOrArrayBufferViewOrScalarValueStringOrURLSearchParams;
class OwningArrayBufferViewOrBlobOrStringOrFormData;
class OwningEventOrString;
class OwningExternalOrWindowProxy;
class OwningHTMLElementOrLong;
class OwningHTMLImageElementOrHTMLCanvasElementOrHTMLVideoElement;
class OwningHTMLOptionElementOrHTMLOptGroupElement;
class OwningHeadersOrByteStringSequenceSequenceOrByteStringMozMap;
class OwningIDBObjectStoreOrIDBIndex;
class OwningIDBObjectStoreOrIDBIndexOrIDBCursor;
class OwningLongOrMozSmsMessageOrMozMmsMessage;
class OwningMozSmsMessageOrMozMmsMessage;
class OwningNetworkStatsDataOrPowerStatsData;
class OwningNodeOrHTMLCollection;
class OwningRadioNodeListOrElement;
class OwningRequestOrScalarValueString;
class OwningStringOrBlobOrArrayBufferOrArrayBufferView;
class OwningStringOrCanvasGradientOrCanvasPattern;
class OwningStringOrFileOrDirectory;
class OwningTelephonyCallOrTelephonyCallGroup;
class OwningTextOrElementOrDocument;
class OwningVideoTrackOrAudioTrackOrTextTrack;
class OwningWindowProxyOrMessagePort;
class OwningmozContactOrString;
class PowerStatsData;
class RadioNodeList;
class Request;
class TelephonyCall;
class TelephonyCallGroup;
class Text;
class TextTrack;
class URLSearchParams;
class VideoTrack;
namespace indexedDB {
class IDBCursor;
class IDBIndex;
class IDBObjectStore;
} // namespace indexedDB
class mozContact;
} // namespace dom
} // namespace mozilla
class nsFormData;
class nsGenericHTMLElement;
class nsIDOMMozMmsMessage;
class nsIDOMMozSmsMessage;
class nsIDOMWindow;
class nsIDocument;
class nsIHTMLCollection;
class nsINode;

namespace mozilla {
namespace dom {
void
ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback& aCallback, OwningArrayBufferOrArrayBufferViewOrBlobOrString& aUnion, const char* aName, uint32_t aFlags = 0);

void
ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback& aCallback, OwningArrayBufferOrArrayBufferViewOrScalarValueStringOrURLSearchParams& aUnion, const char* aName, uint32_t aFlags = 0);

void
ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback& aCallback, OwningArrayBufferViewOrBlobOrStringOrFormData& aUnion, const char* aName, uint32_t aFlags = 0);

void
ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback& aCallback, OwningEventOrString& aUnion, const char* aName, uint32_t aFlags = 0);

void
ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback& aCallback, OwningExternalOrWindowProxy& aUnion, const char* aName, uint32_t aFlags = 0);

void
ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback& aCallback, OwningHTMLElementOrLong& aUnion, const char* aName, uint32_t aFlags = 0);

void
ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback& aCallback, OwningHTMLImageElementOrHTMLCanvasElementOrHTMLVideoElement& aUnion, const char* aName, uint32_t aFlags = 0);

void
ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback& aCallback, OwningHTMLOptionElementOrHTMLOptGroupElement& aUnion, const char* aName, uint32_t aFlags = 0);

void
ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback& aCallback, OwningHeadersOrByteStringSequenceSequenceOrByteStringMozMap& aUnion, const char* aName, uint32_t aFlags = 0);

void
ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback& aCallback, OwningIDBObjectStoreOrIDBIndex& aUnion, const char* aName, uint32_t aFlags = 0);

void
ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback& aCallback, OwningIDBObjectStoreOrIDBIndexOrIDBCursor& aUnion, const char* aName, uint32_t aFlags = 0);

void
ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback& aCallback, OwningLongOrMozSmsMessageOrMozMmsMessage& aUnion, const char* aName, uint32_t aFlags = 0);

void
ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback& aCallback, OwningMozSmsMessageOrMozMmsMessage& aUnion, const char* aName, uint32_t aFlags = 0);

void
ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback& aCallback, OwningNetworkStatsDataOrPowerStatsData& aUnion, const char* aName, uint32_t aFlags = 0);

void
ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback& aCallback, OwningNodeOrHTMLCollection& aUnion, const char* aName, uint32_t aFlags = 0);

void
ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback& aCallback, OwningRadioNodeListOrElement& aUnion, const char* aName, uint32_t aFlags = 0);

void
ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback& aCallback, OwningRequestOrScalarValueString& aUnion, const char* aName, uint32_t aFlags = 0);

void
ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback& aCallback, OwningStringOrBlobOrArrayBufferOrArrayBufferView& aUnion, const char* aName, uint32_t aFlags = 0);

void
ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback& aCallback, OwningStringOrCanvasGradientOrCanvasPattern& aUnion, const char* aName, uint32_t aFlags = 0);

void
ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback& aCallback, OwningStringOrFileOrDirectory& aUnion, const char* aName, uint32_t aFlags = 0);

void
ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback& aCallback, OwningTelephonyCallOrTelephonyCallGroup& aUnion, const char* aName, uint32_t aFlags = 0);

void
ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback& aCallback, OwningTextOrElementOrDocument& aUnion, const char* aName, uint32_t aFlags = 0);

void
ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback& aCallback, OwningVideoTrackOrAudioTrackOrTextTrack& aUnion, const char* aName, uint32_t aFlags = 0);

void
ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback& aCallback, OwningWindowProxyOrMessagePort& aUnion, const char* aName, uint32_t aFlags = 0);

void
ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback& aCallback, OwningmozContactOrString& aUnion, const char* aName, uint32_t aFlags = 0);

void
ImplCycleCollectionUnlink(OwningArrayBufferOrArrayBufferViewOrBlobOrString& aUnion);

void
ImplCycleCollectionUnlink(OwningArrayBufferOrArrayBufferViewOrScalarValueStringOrURLSearchParams& aUnion);

void
ImplCycleCollectionUnlink(OwningArrayBufferViewOrBlobOrStringOrFormData& aUnion);

void
ImplCycleCollectionUnlink(OwningEventOrString& aUnion);

void
ImplCycleCollectionUnlink(OwningExternalOrWindowProxy& aUnion);

void
ImplCycleCollectionUnlink(OwningHTMLElementOrLong& aUnion);

void
ImplCycleCollectionUnlink(OwningHTMLImageElementOrHTMLCanvasElementOrHTMLVideoElement& aUnion);

void
ImplCycleCollectionUnlink(OwningHTMLOptionElementOrHTMLOptGroupElement& aUnion);

void
ImplCycleCollectionUnlink(OwningHeadersOrByteStringSequenceSequenceOrByteStringMozMap& aUnion);

void
ImplCycleCollectionUnlink(OwningIDBObjectStoreOrIDBIndex& aUnion);

void
ImplCycleCollectionUnlink(OwningIDBObjectStoreOrIDBIndexOrIDBCursor& aUnion);

void
ImplCycleCollectionUnlink(OwningLongOrMozSmsMessageOrMozMmsMessage& aUnion);

void
ImplCycleCollectionUnlink(OwningMozSmsMessageOrMozMmsMessage& aUnion);

void
ImplCycleCollectionUnlink(OwningNetworkStatsDataOrPowerStatsData& aUnion);

void
ImplCycleCollectionUnlink(OwningNodeOrHTMLCollection& aUnion);

void
ImplCycleCollectionUnlink(OwningRadioNodeListOrElement& aUnion);

void
ImplCycleCollectionUnlink(OwningRequestOrScalarValueString& aUnion);

void
ImplCycleCollectionUnlink(OwningStringOrBlobOrArrayBufferOrArrayBufferView& aUnion);

void
ImplCycleCollectionUnlink(OwningStringOrCanvasGradientOrCanvasPattern& aUnion);

void
ImplCycleCollectionUnlink(OwningStringOrFileOrDirectory& aUnion);

void
ImplCycleCollectionUnlink(OwningTelephonyCallOrTelephonyCallGroup& aUnion);

void
ImplCycleCollectionUnlink(OwningTextOrElementOrDocument& aUnion);

void
ImplCycleCollectionUnlink(OwningVideoTrackOrAudioTrackOrTextTrack& aUnion);

void
ImplCycleCollectionUnlink(OwningWindowProxyOrMessagePort& aUnion);

void
ImplCycleCollectionUnlink(OwningmozContactOrString& aUnion);

class ArrayBufferOrArrayBufferViewOrBlobOrString
{
  friend class ArrayBufferOrArrayBufferViewOrBlobOrStringArgument;
  enum Type
  {
    eUninitialized,
    eArrayBuffer,
    eArrayBufferView,
    eBlob,
    eString
  };

  union Value
  {
    UnionMember<RootedTypedArray<ArrayBuffer> > mArrayBuffer;
    UnionMember<RootedTypedArray<ArrayBufferView> > mArrayBufferView;
    UnionMember<NonNull<mozilla::dom::File> > mBlob;
    UnionMember<binding_detail::FakeString > mString;

  };

  Type mType;
  Value mValue;

  ArrayBufferOrArrayBufferViewOrBlobOrString(const ArrayBufferOrArrayBufferViewOrBlobOrString&) MOZ_DELETE;
  void operator=(const ArrayBufferOrArrayBufferViewOrBlobOrString) MOZ_DELETE;
public:
  explicit inline ArrayBufferOrArrayBufferViewOrBlobOrString()
    : mType(eUninitialized)
  {
  }

  inline ~ArrayBufferOrArrayBufferViewOrBlobOrString()
  {
    Uninit();
  }

  inline RootedTypedArray<ArrayBuffer>&
  RawSetAsArrayBuffer(JSContext* cx)
  {
    if (mType == eArrayBuffer) {
      return mValue.mArrayBuffer.Value();
    }
    MOZ_ASSERT(mType == eUninitialized);
    mType = eArrayBuffer;
    return mValue.mArrayBuffer.SetValue(cx);
  }

  inline RootedTypedArray<ArrayBuffer>&
  SetAsArrayBuffer(JSContext* cx)
  {
    if (mType == eArrayBuffer) {
      return mValue.mArrayBuffer.Value();
    }
    Uninit();
    mType = eArrayBuffer;
    return mValue.mArrayBuffer.SetValue(cx);
  }

  inline bool
  IsArrayBuffer() const
  {
    return mType == eArrayBuffer;
  }

  inline RootedTypedArray<ArrayBuffer>&
  GetAsArrayBuffer()
  {
    MOZ_ASSERT(IsArrayBuffer(), "Wrong type!");
    return mValue.mArrayBuffer.Value();
  }

  inline ArrayBuffer const &
  GetAsArrayBuffer() const
  {
    MOZ_ASSERT(IsArrayBuffer(), "Wrong type!");
    return mValue.mArrayBuffer.Value();
  }

  inline RootedTypedArray<ArrayBufferView>&
  RawSetAsArrayBufferView(JSContext* cx)
  {
    if (mType == eArrayBufferView) {
      return mValue.mArrayBufferView.Value();
    }
    MOZ_ASSERT(mType == eUninitialized);
    mType = eArrayBufferView;
    return mValue.mArrayBufferView.SetValue(cx);
  }

  inline RootedTypedArray<ArrayBufferView>&
  SetAsArrayBufferView(JSContext* cx)
  {
    if (mType == eArrayBufferView) {
      return mValue.mArrayBufferView.Value();
    }
    Uninit();
    mType = eArrayBufferView;
    return mValue.mArrayBufferView.SetValue(cx);
  }

  inline bool
  IsArrayBufferView() const
  {
    return mType == eArrayBufferView;
  }

  inline RootedTypedArray<ArrayBufferView>&
  GetAsArrayBufferView()
  {
    MOZ_ASSERT(IsArrayBufferView(), "Wrong type!");
    return mValue.mArrayBufferView.Value();
  }

  inline ArrayBufferView const &
  GetAsArrayBufferView() const
  {
    MOZ_ASSERT(IsArrayBufferView(), "Wrong type!");
    return mValue.mArrayBufferView.Value();
  }

  inline NonNull<mozilla::dom::File>&
  RawSetAsBlob()
  {
    if (mType == eBlob) {
      return mValue.mBlob.Value();
    }
    MOZ_ASSERT(mType == eUninitialized);
    mType = eBlob;
    return mValue.mBlob.SetValue();
  }

  inline NonNull<mozilla::dom::File>&
  SetAsBlob()
  {
    if (mType == eBlob) {
      return mValue.mBlob.Value();
    }
    Uninit();
    mType = eBlob;
    return mValue.mBlob.SetValue();
  }

  inline bool
  IsBlob() const
  {
    return mType == eBlob;
  }

  inline NonNull<mozilla::dom::File>&
  GetAsBlob()
  {
    MOZ_ASSERT(IsBlob(), "Wrong type!");
    return mValue.mBlob.Value();
  }

  inline mozilla::dom::File&
  GetAsBlob() const
  {
    MOZ_ASSERT(IsBlob(), "Wrong type!");
    return mValue.mBlob.Value();
  }

  inline binding_detail::FakeString&
  RawSetAsString()
  {
    if (mType == eString) {
      return mValue.mString.Value();
    }
    MOZ_ASSERT(mType == eUninitialized);
    mType = eString;
    return mValue.mString.SetValue();
  }

  inline binding_detail::FakeString&
  SetAsString()
  {
    if (mType == eString) {
      return mValue.mString.Value();
    }
    Uninit();
    mType = eString;
    return mValue.mString.SetValue();
  }

  inline bool
  IsString() const
  {
    return mType == eString;
  }

  inline binding_detail::FakeString&
  GetAsString()
  {
    MOZ_ASSERT(IsString(), "Wrong type!");
    return mValue.mString.Value();
  }

  inline const nsAString&
  GetAsString() const
  {
    MOZ_ASSERT(IsString(), "Wrong type!");
    return mValue.mString.Value();
  }

  bool
  ToJSVal(JSContext* cx, JS::Handle<JSObject*> scopeObj, JS::MutableHandle<JS::Value> rval) const;

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

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

  inline void
  DestroyBlob()
  {
    MOZ_ASSERT(IsBlob(), "Wrong type!");
    mValue.mBlob.Destroy();
    mType = eUninitialized;
  }

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

  inline void
  Uninit()
  {
    switch (mType) {
      case eUninitialized: {
        break;
      }
      case eArrayBuffer: {
        DestroyArrayBuffer();
        break;
      }
      case eArrayBufferView: {
        DestroyArrayBufferView();
        break;
      }
      case eBlob: {
        DestroyBlob();
        break;
      }
      case eString: {
        DestroyString();
        break;
      }
    }
  }
};

class ArrayBufferOrArrayBufferViewOrScalarValueStringOrURLSearchParams
{
  friend class ArrayBufferOrArrayBufferViewOrScalarValueStringOrURLSearchParamsArgument;
  enum Type
  {
    eUninitialized,
    eArrayBuffer,
    eArrayBufferView,
    eScalarValueString,
    eURLSearchParams
  };

  union Value
  {
    UnionMember<RootedTypedArray<ArrayBuffer> > mArrayBuffer;
    UnionMember<RootedTypedArray<ArrayBufferView> > mArrayBufferView;
    UnionMember<binding_detail::FakeString > mScalarValueString;
    UnionMember<NonNull<mozilla::dom::URLSearchParams> > mURLSearchParams;

  };

  Type mType;
  Value mValue;

  ArrayBufferOrArrayBufferViewOrScalarValueStringOrURLSearchParams(const ArrayBufferOrArrayBufferViewOrScalarValueStringOrURLSearchParams&) MOZ_DELETE;
  void operator=(const ArrayBufferOrArrayBufferViewOrScalarValueStringOrURLSearchParams) MOZ_DELETE;
public:
  explicit inline ArrayBufferOrArrayBufferViewOrScalarValueStringOrURLSearchParams()
    : mType(eUninitialized)
  {
  }

  inline ~ArrayBufferOrArrayBufferViewOrScalarValueStringOrURLSearchParams()
  {
    Uninit();
  }

  inline RootedTypedArray<ArrayBuffer>&
  RawSetAsArrayBuffer(JSContext* cx)
  {
    if (mType == eArrayBuffer) {
      return mValue.mArrayBuffer.Value();
    }
    MOZ_ASSERT(mType == eUninitialized);
    mType = eArrayBuffer;
    return mValue.mArrayBuffer.SetValue(cx);
  }

  inline RootedTypedArray<ArrayBuffer>&
  SetAsArrayBuffer(JSContext* cx)
  {
    if (mType == eArrayBuffer) {
      return mValue.mArrayBuffer.Value();
    }
    Uninit();
    mType = eArrayBuffer;
    return mValue.mArrayBuffer.SetValue(cx);
  }

  inline bool
  IsArrayBuffer() const
  {
    return mType == eArrayBuffer;
  }

  inline RootedTypedArray<ArrayBuffer>&
  GetAsArrayBuffer()
  {
    MOZ_ASSERT(IsArrayBuffer(), "Wrong type!");
    return mValue.mArrayBuffer.Value();
  }

  inline ArrayBuffer const &
  GetAsArrayBuffer() const
  {
    MOZ_ASSERT(IsArrayBuffer(), "Wrong type!");
    return mValue.mArrayBuffer.Value();
  }

  inline RootedTypedArray<ArrayBufferView>&
  RawSetAsArrayBufferView(JSContext* cx)
  {
    if (mType == eArrayBufferView) {
      return mValue.mArrayBufferView.Value();
    }
    MOZ_ASSERT(mType == eUninitialized);
    mType = eArrayBufferView;
    return mValue.mArrayBufferView.SetValue(cx);
  }

  inline RootedTypedArray<ArrayBufferView>&
  SetAsArrayBufferView(JSContext* cx)
  {
    if (mType == eArrayBufferView) {
      return mValue.mArrayBufferView.Value();
    }
    Uninit();
    mType = eArrayBufferView;
    return mValue.mArrayBufferView.SetValue(cx);
  }

  inline bool
  IsArrayBufferView() const
  {
    return mType == eArrayBufferView;
  }

  inline RootedTypedArray<ArrayBufferView>&
  GetAsArrayBufferView()
  {
    MOZ_ASSERT(IsArrayBufferView(), "Wrong type!");
    return mValue.mArrayBufferView.Value();
  }

  inline ArrayBufferView const &
  GetAsArrayBufferView() const
  {
    MOZ_ASSERT(IsArrayBufferView(), "Wrong type!");
    return mValue.mArrayBufferView.Value();
  }

  inline binding_detail::FakeString&
  RawSetAsScalarValueString()
  {
    if (mType == eScalarValueString) {
      return mValue.mScalarValueString.Value();
    }
    MOZ_ASSERT(mType == eUninitialized);
    mType = eScalarValueString;
    return mValue.mScalarValueString.SetValue();
  }

  inline binding_detail::FakeString&
  SetAsScalarValueString()
  {
    if (mType == eScalarValueString) {
      return mValue.mScalarValueString.Value();
    }
    Uninit();
    mType = eScalarValueString;
    return mValue.mScalarValueString.SetValue();
  }

  inline bool
  IsScalarValueString() const
  {
    return mType == eScalarValueString;
  }

  inline binding_detail::FakeString&
  GetAsScalarValueString()
  {
    MOZ_ASSERT(IsScalarValueString(), "Wrong type!");
    return mValue.mScalarValueString.Value();
  }

  inline const nsAString&
  GetAsScalarValueString() const
  {
    MOZ_ASSERT(IsScalarValueString(), "Wrong type!");
    return mValue.mScalarValueString.Value();
  }

  inline NonNull<mozilla::dom::URLSearchParams>&
  RawSetAsURLSearchParams()
  {
    if (mType == eURLSearchParams) {
      return mValue.mURLSearchParams.Value();
    }
    MOZ_ASSERT(mType == eUninitialized);
    mType = eURLSearchParams;
    return mValue.mURLSearchParams.SetValue();
  }

  inline NonNull<mozilla::dom::URLSearchParams>&
  SetAsURLSearchParams()
  {
    if (mType == eURLSearchParams) {
      return mValue.mURLSearchParams.Value();
    }
    Uninit();
    mType = eURLSearchParams;
    return mValue.mURLSearchParams.SetValue();
  }

  inline bool
  IsURLSearchParams() const
  {
    return mType == eURLSearchParams;
  }

  inline NonNull<mozilla::dom::URLSearchParams>&
  GetAsURLSearchParams()
  {
    MOZ_ASSERT(IsURLSearchParams(), "Wrong type!");
    return mValue.mURLSearchParams.Value();
  }

  inline mozilla::dom::URLSearchParams&
  GetAsURLSearchParams() const
  {
    MOZ_ASSERT(IsURLSearchParams(), "Wrong type!");
    return mValue.mURLSearchParams.Value();
  }

  bool
  ToJSVal(JSContext* cx, JS::Handle<JSObject*> scopeObj, JS::MutableHandle<JS::Value> rval) const;

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

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

  inline void
  DestroyScalarValueString()
  {
    MOZ_ASSERT(IsScalarValueString(), "Wrong type!");
    mValue.mScalarValueString.Destroy();
    mType = eUninitialized;
  }

  inline void
  DestroyURLSearchParams()
  {
    MOZ_ASSERT(IsURLSearchParams(), "Wrong type!");
    mValue.mURLSearchParams.Destroy();
    mType = eUninitialized;
  }

  inline void
  Uninit()
  {
    switch (mType) {
      case eUninitialized: {
        break;
      }
      case eArrayBuffer: {
        DestroyArrayBuffer();
        break;
      }
      case eArrayBufferView: {
        DestroyArrayBufferView();
        break;
      }
      case eScalarValueString: {
        DestroyScalarValueString();
        break;
      }
      case eURLSearchParams: {
        DestroyURLSearchParams();
        break;
      }
    }
  }
};

class ArrayBufferViewOrArrayBuffer
{
  friend class ArrayBufferViewOrArrayBufferArgument;
  enum Type
  {
    eUninitialized,
    eArrayBufferView,
    eArrayBuffer
  };

  union Value
  {
    UnionMember<RootedTypedArray<ArrayBufferView> > mArrayBufferView;
    UnionMember<RootedTypedArray<ArrayBuffer> > mArrayBuffer;

  };

  Type mType;
  Value mValue;

  ArrayBufferViewOrArrayBuffer(const ArrayBufferViewOrArrayBuffer&) MOZ_DELETE;
  void operator=(const ArrayBufferViewOrArrayBuffer) MOZ_DELETE;
public:
  explicit inline ArrayBufferViewOrArrayBuffer()
    : mType(eUninitialized)
  {
  }

  inline ~ArrayBufferViewOrArrayBuffer()
  {
    Uninit();
  }

  inline RootedTypedArray<ArrayBufferView>&
  RawSetAsArrayBufferView(JSContext* cx)
  {
    if (mType == eArrayBufferView) {
      return mValue.mArrayBufferView.Value();
    }
    MOZ_ASSERT(mType == eUninitialized);
    mType = eArrayBufferView;
    return mValue.mArrayBufferView.SetValue(cx);
  }

  inline RootedTypedArray<ArrayBufferView>&
  SetAsArrayBufferView(JSContext* cx)
  {
    if (mType == eArrayBufferView) {
      return mValue.mArrayBufferView.Value();
    }
    Uninit();
    mType = eArrayBufferView;
    return mValue.mArrayBufferView.SetValue(cx);
  }

  inline bool
  IsArrayBufferView() const
  {
    return mType == eArrayBufferView;
  }

  inline RootedTypedArray<ArrayBufferView>&
  GetAsArrayBufferView()
  {
    MOZ_ASSERT(IsArrayBufferView(), "Wrong type!");
    return mValue.mArrayBufferView.Value();
  }

  inline ArrayBufferView const &
  GetAsArrayBufferView() const
  {
    MOZ_ASSERT(IsArrayBufferView(), "Wrong type!");
    return mValue.mArrayBufferView.Value();
  }

  inline RootedTypedArray<ArrayBuffer>&
  RawSetAsArrayBuffer(JSContext* cx)
  {
    if (mType == eArrayBuffer) {
      return mValue.mArrayBuffer.Value();
    }
    MOZ_ASSERT(mType == eUninitialized);
    mType = eArrayBuffer;
    return mValue.mArrayBuffer.SetValue(cx);
  }

  inline RootedTypedArray<ArrayBuffer>&
  SetAsArrayBuffer(JSContext* cx)
  {
    if (mType == eArrayBuffer) {
      return mValue.mArrayBuffer.Value();
    }
    Uninit();
    mType = eArrayBuffer;
    return mValue.mArrayBuffer.SetValue(cx);
  }

  inline bool
  IsArrayBuffer() const
  {
    return mType == eArrayBuffer;
  }

  inline RootedTypedArray<ArrayBuffer>&
  GetAsArrayBuffer()
  {
    MOZ_ASSERT(IsArrayBuffer(), "Wrong type!");
    return mValue.mArrayBuffer.Value();
  }

  inline ArrayBuffer const &
  GetAsArrayBuffer() const
  {
    MOZ_ASSERT(IsArrayBuffer(), "Wrong type!");
    return mValue.mArrayBuffer.Value();
  }

  bool
  ToJSVal(JSContext* cx, JS::Handle<JSObject*> scopeObj, JS::MutableHandle<JS::Value> rval) const;

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

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

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

class ArrayBufferViewOrBlobOrStringOrFormData
{
  friend class ArrayBufferViewOrBlobOrStringOrFormDataArgument;
  enum Type
  {
    eUninitialized,
    eArrayBufferView,
    eBlob,
    eString,
    eFormData
  };

  union Value
  {
    UnionMember<RootedTypedArray<ArrayBufferView> > mArrayBufferView;
    UnionMember<NonNull<mozilla::dom::File> > mBlob;
    UnionMember<binding_detail::FakeString > mString;
    UnionMember<NonNull<nsFormData> > mFormData;

  };

  Type mType;
  Value mValue;

  ArrayBufferViewOrBlobOrStringOrFormData(const ArrayBufferViewOrBlobOrStringOrFormData&) MOZ_DELETE;
  void operator=(const ArrayBufferViewOrBlobOrStringOrFormData) MOZ_DELETE;
public:
  explicit inline ArrayBufferViewOrBlobOrStringOrFormData()
    : mType(eUninitialized)
  {
  }

  inline ~ArrayBufferViewOrBlobOrStringOrFormData()
  {
    Uninit();
  }

  inline RootedTypedArray<ArrayBufferView>&
  RawSetAsArrayBufferView(JSContext* cx)
  {
    if (mType == eArrayBufferView) {
      return mValue.mArrayBufferView.Value();
    }
    MOZ_ASSERT(mType == eUninitialized);
    mType = eArrayBufferView;
    return mValue.mArrayBufferView.SetValue(cx);
  }

  inline RootedTypedArray<ArrayBufferView>&
  SetAsArrayBufferView(JSContext* cx)
  {
    if (mType == eArrayBufferView) {
      return mValue.mArrayBufferView.Value();
    }
    Uninit();
    mType = eArrayBufferView;
    return mValue.mArrayBufferView.SetValue(cx);
  }

  inline bool
  IsArrayBufferView() const
  {
    return mType == eArrayBufferView;
  }

  inline RootedTypedArray<ArrayBufferView>&
  GetAsArrayBufferView()
  {
    MOZ_ASSERT(IsArrayBufferView(), "Wrong type!");
    return mValue.mArrayBufferView.Value();
  }

  inline ArrayBufferView const &
  GetAsArrayBufferView() const
  {
    MOZ_ASSERT(IsArrayBufferView(), "Wrong type!");
    return mValue.mArrayBufferView.Value();
  }

  inline NonNull<mozilla::dom::File>&
  RawSetAsBlob()
  {
    if (mType == eBlob) {
      return mValue.mBlob.Value();
    }
    MOZ_ASSERT(mType == eUninitialized);
    mType = eBlob;
    return mValue.mBlob.SetValue();
  }

  inline NonNull<mozilla::dom::File>&
  SetAsBlob()
  {
    if (mType == eBlob) {
      return mValue.mBlob.Value();
    }
    Uninit();
    mType = eBlob;
    return mValue.mBlob.SetValue();
  }

  inline bool
  IsBlob() const
  {
    return mType == eBlob;
  }

  inline NonNull<mozilla::dom::File>&
  GetAsBlob()
  {
    MOZ_ASSERT(IsBlob(), "Wrong type!");
    return mValue.mBlob.Value();
  }

  inline mozilla::dom::File&
  GetAsBlob() const
  {
    MOZ_ASSERT(IsBlob(), "Wrong type!");
    return mValue.mBlob.Value();
  }

  inline binding_detail::FakeString&
  RawSetAsString()
  {
    if (mType == eString) {
      return mValue.mString.Value();
    }
    MOZ_ASSERT(mType == eUninitialized);
    mType = eString;
    return mValue.mString.SetValue();
  }

  inline binding_detail::FakeString&
  SetAsString()
  {
    if (mType == eString) {
      return mValue.mString.Value();
    }
    Uninit();
    mType = eString;
    return mValue.mString.SetValue();
  }

  inline bool
  IsString() const
  {
    return mType == eString;
  }

  inline binding_detail::FakeString&
  GetAsString()
  {
    MOZ_ASSERT(IsString(), "Wrong type!");
    return mValue.mString.Value();
  }

  inline const nsAString&
  GetAsString() const
  {
    MOZ_ASSERT(IsString(), "Wrong type!");
    return mValue.mString.Value();
  }

  inline NonNull<nsFormData>&
  RawSetAsFormData()
  {
    if (mType == eFormData) {
      return mValue.mFormData.Value();
    }
    MOZ_ASSERT(mType == eUninitialized);
    mType = eFormData;
    return mValue.mFormData.SetValue();
  }

  inline NonNull<nsFormData>&
  SetAsFormData()
  {
    if (mType == eFormData) {
      return mValue.mFormData.Value();
    }
    Uninit();
    mType = eFormData;
    return mValue.mFormData.SetValue();
  }

  inline bool
  IsFormData() const
  {
    return mType == eFormData;
  }

  inline NonNull<nsFormData>&
  GetAsFormData()
  {
    MOZ_ASSERT(IsFormData(), "Wrong type!");
    return mValue.mFormData.Value();
  }

  inline nsFormData&
  GetAsFormData() const
  {
    MOZ_ASSERT(IsFormData(), "Wrong type!");
    return mValue.mFormData.Value();
  }

  bool
  ToJSVal(JSContext* cx, JS::Handle<JSObject*> scopeObj, JS::MutableHandle<JS::Value> rval) const;

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

  inline void
  DestroyBlob()
  {
    MOZ_ASSERT(IsBlob(), "Wrong type!");
    mValue.mBlob.Destroy();
    mType = eUninitialized;
  }

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

  inline void
  DestroyFormData()
  {
    MOZ_ASSERT(IsFormData(), "Wrong type!");
    mValue.mFormData.Destroy();
    mType = eUninitialized;
  }

  inline void
  Uninit()
  {
    switch (mType) {
      case eUninitialized: {
        break;
      }
      case eArrayBufferView: {
        DestroyArrayBufferView();
        break;
      }
      case eBlob: {
        DestroyBlob();
        break;
      }
      case eString: {
        DestroyString();
        break;
      }
      case eFormData: {
        DestroyFormData();
        break;
      }
    }
  }
};

class BooleanOrMediaTrackConstraints
{
  friend class BooleanOrMediaTrackConstraintsArgument;
  enum Type
  {
    eUninitialized,
    eBoolean,
    eMediaTrackConstraints
  };

  union Value
  {
    UnionMember<bool > mBoolean;
    UnionMember<binding_detail::FastMediaTrackConstraints > mMediaTrackConstraints;

  };

  Type mType;
  Value mValue;

  BooleanOrMediaTrackConstraints(const BooleanOrMediaTrackConstraints&) MOZ_DELETE;
  void operator=(const BooleanOrMediaTrackConstraints) MOZ_DELETE;
public:
  explicit inline BooleanOrMediaTrackConstraints()
    : mType(eUninitialized)
  {
  }

  inline ~BooleanOrMediaTrackConstraints()
  {
    Uninit();
  }

  inline bool&
  RawSetAsBoolean()
  {
    if (mType == eBoolean) {
      return mValue.mBoolean.Value();
    }
    MOZ_ASSERT(mType == eUninitialized);
    mType = eBoolean;
    return mValue.mBoolean.SetValue();
  }

  inline bool&
  SetAsBoolean()
  {
    if (mType == eBoolean) {
      return mValue.mBoolean.Value();
    }
    Uninit();
    mType = eBoolean;
    return mValue.mBoolean.SetValue();
  }

  inline bool
  IsBoolean() const
  {
    return mType == eBoolean;
  }

  inline bool&
  GetAsBoolean()
  {
    MOZ_ASSERT(IsBoolean(), "Wrong type!");
    return mValue.mBoolean.Value();
  }

  inline bool
  GetAsBoolean() const
  {
    MOZ_ASSERT(IsBoolean(), "Wrong type!");
    return mValue.mBoolean.Value();
  }

  inline binding_detail::FastMediaTrackConstraints&
  RawSetAsMediaTrackConstraints()
  {
    if (mType == eMediaTrackConstraints) {
      return mValue.mMediaTrackConstraints.Value();
    }
    MOZ_ASSERT(mType == eUninitialized);
    mType = eMediaTrackConstraints;
    return mValue.mMediaTrackConstraints.SetValue();
  }

  inline binding_detail::FastMediaTrackConstraints&
  SetAsMediaTrackConstraints()
  {
    if (mType == eMediaTrackConstraints) {
      return mValue.mMediaTrackConstraints.Value();
    }
    Uninit();
    mType = eMediaTrackConstraints;
    return mValue.mMediaTrackConstraints.SetValue();
  }

  inline bool
  IsMediaTrackConstraints() const
  {
    return mType == eMediaTrackConstraints;
  }

  inline binding_detail::FastMediaTrackConstraints&
  GetAsMediaTrackConstraints()
  {
    MOZ_ASSERT(IsMediaTrackConstraints(), "Wrong type!");
    return mValue.mMediaTrackConstraints.Value();
  }

  inline const MediaTrackConstraints&
  GetAsMediaTrackConstraints() const
  {
    MOZ_ASSERT(IsMediaTrackConstraints(), "Wrong type!");
    return mValue.mMediaTrackConstraints.Value();
  }

  bool
  ToJSVal(JSContext* cx, JS::Handle<JSObject*> scopeObj, JS::MutableHandle<JS::Value> rval) const;

private:
  inline void
  DestroyBoolean()
  {
    MOZ_ASSERT(IsBoolean(), "Wrong type!");
    mValue.mBoolean.Destroy();
    mType = eUninitialized;
  }

  inline void
  DestroyMediaTrackConstraints()
  {
    MOZ_ASSERT(IsMediaTrackConstraints(), "Wrong type!");
    mValue.mMediaTrackConstraints.Destroy();
    mType = eUninitialized;
  }

  inline void
  Uninit()
  {
    switch (mType) {
      case eUninitialized: {
        break;
      }
      case eBoolean: {
        DestroyBoolean();
        break;
      }
      case eMediaTrackConstraints: {
        DestroyMediaTrackConstraints();
        break;
      }
    }
  }
};

class EventOrString
{
  friend class EventOrStringArgument;
  enum Type
  {
    eUninitialized,
    eEvent,
    eString
  };

  union Value
  {
    UnionMember<NonNull<mozilla::dom::Event> > mEvent;
    UnionMember<binding_detail::FakeString > mString;

  };

  Type mType;
  Value mValue;

  EventOrString(const EventOrString&) MOZ_DELETE;
  void operator=(const EventOrString) MOZ_DELETE;
public:
  explicit inline EventOrString()
    : mType(eUninitialized)
  {
  }

  inline ~EventOrString()
  {
    Uninit();
  }

  inline NonNull<mozilla::dom::Event>&
  RawSetAsEvent()
  {
    if (mType == eEvent) {
      return mValue.mEvent.Value();
    }
    MOZ_ASSERT(mType == eUninitialized);
    mType = eEvent;
    return mValue.mEvent.SetValue();
  }

  inline NonNull<mozilla::dom::Event>&
  SetAsEvent()
  {
    if (mType == eEvent) {
      return mValue.mEvent.Value();
    }
    Uninit();
    mType = eEvent;
    return mValue.mEvent.SetValue();
  }

  inline bool
  IsEvent() const
  {
    return mType == eEvent;
  }

  inline NonNull<mozilla::dom::Event>&
  GetAsEvent()
  {
    MOZ_ASSERT(IsEvent(), "Wrong type!");
    return mValue.mEvent.Value();
  }

  inline mozilla::dom::Event&
  GetAsEvent() const
  {
    MOZ_ASSERT(IsEvent(), "Wrong type!");
    return mValue.mEvent.Value();
  }

  inline binding_detail::FakeString&
  RawSetAsString()
  {
    if (mType == eString) {
      return mValue.mString.Value();
    }
    MOZ_ASSERT(mType == eUninitialized);
    mType = eString;
    return mValue.mString.SetValue();
  }

  inline binding_detail::FakeString&
  SetAsString()
  {
    if (mType == eString) {
      return mValue.mString.Value();
    }
    Uninit();
    mType = eString;
    return mValue.mString.SetValue();
  }

  inline bool
  IsString() const
  {
    return mType == eString;
  }

  inline binding_detail::FakeString&
  GetAsString()
  {
    MOZ_ASSERT(IsString(), "Wrong type!");
    return mValue.mString.Value();
  }

  inline const nsAString&
  GetAsString() const
  {
    MOZ_ASSERT(IsString(), "Wrong type!");
    return mValue.mString.Value();
  }

  bool
  ToJSVal(JSContext* cx, JS::Handle<JSObject*> scopeObj, JS::MutableHandle<JS::Value> rval) const;

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

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

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

class ExternalOrWindowProxy
{
  friend class ExternalOrWindowProxyArgument;
  enum Type
  {
    eUninitialized,
    eExternal,
    eWindowProxy
  };

  union Value
  {
    UnionMember<NonNull<mozilla::dom::External> > mExternal;
    UnionMember<nsIDOMWindow* > mWindowProxy;

  };

  Type mType;
  Value mValue;

  ExternalOrWindowProxy(const ExternalOrWindowProxy&) MOZ_DELETE;
  void operator=(const ExternalOrWindowProxy) MOZ_DELETE;
public:
  explicit inline ExternalOrWindowProxy()
    : mType(eUninitialized)
  {
  }

  inline ~ExternalOrWindowProxy()
  {
    Uninit();
  }

  inline NonNull<mozilla::dom::External>&
  RawSetAsExternal()
  {
    if (mType == eExternal) {
      return mValue.mExternal.Value();
    }
    MOZ_ASSERT(mType == eUninitialized);
    mType = eExternal;
    return mValue.mExternal.SetValue();
  }

  inline NonNull<mozilla::dom::External>&
  SetAsExternal()
  {
    if (mType == eExternal) {
      return mValue.mExternal.Value();
    }
    Uninit();
    mType = eExternal;
    return mValue.mExternal.SetValue();
  }

  inline bool
  IsExternal() const
  {
    return mType == eExternal;
  }

  inline NonNull<mozilla::dom::External>&
  GetAsExternal()
  {
    MOZ_ASSERT(IsExternal(), "Wrong type!");
    return mValue.mExternal.Value();
  }

  inline mozilla::dom::External&
  GetAsExternal() const
  {
    MOZ_ASSERT(IsExternal(), "Wrong type!");
    return mValue.mExternal.Value();
  }

  inline nsIDOMWindow*&
  RawSetAsWindowProxy()
  {
    if (mType == eWindowProxy) {
      return mValue.mWindowProxy.Value();
    }
    MOZ_ASSERT(mType == eUninitialized);
    mType = eWindowProxy;
    return mValue.mWindowProxy.SetValue();
  }

  inline nsIDOMWindow*&
  SetAsWindowProxy()
  {
    if (mType == eWindowProxy) {
      return mValue.mWindowProxy.Value();
    }
    Uninit();
    mType = eWindowProxy;
    return mValue.mWindowProxy.SetValue();
  }

  inline bool
  IsWindowProxy() const
  {
    return mType == eWindowProxy;
  }

  inline nsIDOMWindow*&
  GetAsWindowProxy()
  {
    MOZ_ASSERT(IsWindowProxy(), "Wrong type!");
    return mValue.mWindowProxy.Value();
  }

  inline nsIDOMWindow*
  GetAsWindowProxy() const
  {
    MOZ_ASSERT(IsWindowProxy(), "Wrong type!");
    return mValue.mWindowProxy.Value();
  }

  bool
  ToJSVal(JSContext* cx, JS::Handle<JSObject*> scopeObj, JS::MutableHandle<JS::Value> rval) const;

private:
  inline void
  DestroyExternal()
  {
    MOZ_ASSERT(IsExternal(), "Wrong type!");
    mValue.mExternal.Destroy();
    mType = eUninitialized;
  }

  inline void
  DestroyWindowProxy()
  {
    MOZ_ASSERT(IsWindowProxy(), "Wrong type!");
    mValue.mWindowProxy.Destroy();
    mType = eUninitialized;
  }

  inline void
  Uninit()
  {
    switch (mType) {
      case eUninitialized: {
        break;
      }
      case eExternal: {
        DestroyExternal();
        break;
      }
      case eWindowProxy: {
        DestroyWindowProxy();
        break;
      }
    }
  }
};

class HTMLElementOrLong
{
  friend class HTMLElementOrLongArgument;
  enum Type
  {
    eUninitialized,
    eHTMLElement,
    eLong
  };

  union Value
  {
    UnionMember<NonNull<nsGenericHTMLElement> > mHTMLElement;
    UnionMember<int32_t > mLong;

  };

  Type mType;
  Value mValue;

  HTMLElementOrLong(const HTMLElementOrLong&) MOZ_DELETE;
  void operator=(const HTMLElementOrLong) MOZ_DELETE;
public:
  explicit inline HTMLElementOrLong()
    : mType(eUninitialized)
  {
  }

  inline ~HTMLElementOrLong()
  {
    Uninit();
  }

  inline NonNull<nsGenericHTMLElement>&
  RawSetAsHTMLElement()
  {
    if (mType == eHTMLElement) {
      return mValue.mHTMLElement.Value();
    }
    MOZ_ASSERT(mType == eUninitialized);
    mType = eHTMLElement;
    return mValue.mHTMLElement.SetValue();
  }

  inline NonNull<nsGenericHTMLElement>&
  SetAsHTMLElement()
  {
    if (mType == eHTMLElement) {
      return mValue.mHTMLElement.Value();
    }
    Uninit();
    mType = eHTMLElement;
    return mValue.mHTMLElement.SetValue();
  }

  inline bool
  IsHTMLElement() const
  {
    return mType == eHTMLElement;
  }

  inline NonNull<nsGenericHTMLElement>&
  GetAsHTMLElement()
  {
    MOZ_ASSERT(IsHTMLElement(), "Wrong type!");
    return mValue.mHTMLElement.Value();
  }

  inline nsGenericHTMLElement&
  GetAsHTMLElement() const
  {
    MOZ_ASSERT(IsHTMLElement(), "Wrong type!");
    return mValue.mHTMLElement.Value();
  }

  inline int32_t&
  RawSetAsLong()
  {
    if (mType == eLong) {
      return mValue.mLong.Value();
    }
    MOZ_ASSERT(mType == eUninitialized);
    mType = eLong;
    return mValue.mLong.SetValue();
  }

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

  inline bool
  IsLong() const
  {
    return mType == eLong;
  }

  inline int32_t&
  GetAsLong()
  {
    MOZ_ASSERT(IsLong(), "Wrong type!");
    return mValue.mLong.Value();
  }

  inline int32_t
  GetAsLong() const
  {
    MOZ_ASSERT(IsLong(), "Wrong type!");
    return mValue.mLong.Value();
  }

  bool
  ToJSVal(JSContext* cx, JS::Handle<JSObject*> scopeObj, JS::MutableHandle<JS::Value> rval) const;

private:
  inline void
  DestroyHTMLElement()
  {
    MOZ_ASSERT(IsHTMLElement(), "Wrong type!");
    mValue.mHTMLElement.Destroy();
    mType = eUninitialized;
  }

  inline void
  DestroyLong()
  {
    MOZ_ASSERT(IsLong(), "Wrong type!");
    mValue.mLong.Destroy();
    mType = eUninitialized;
  }

  inline void
  Uninit()
  {
    switch (mType) {
      case eUninitialized: {
        break;
      }
      case eHTMLElement: {
        DestroyHTMLElement();
        break;
      }
      case eLong: {
        DestroyLong();
        break;
      }
    }
  }
};

class HTMLImageElementOrHTMLCanvasElementOrHTMLVideoElement
{
  friend class HTMLImageElementOrHTMLCanvasElementOrHTMLVideoElementArgument;
  enum Type
  {
    eUninitialized,
    eHTMLImageElement,
    eHTMLCanvasElement,
    eHTMLVideoElement
  };

  union Value
  {
    UnionMember<NonNull<mozilla::dom::HTMLImageElement> > mHTMLImageElement;
    UnionMember<NonNull<mozilla::dom::HTMLCanvasElement> > mHTMLCanvasElement;
    UnionMember<NonNull<mozilla::dom::HTMLVideoElement> > mHTMLVideoElement;

  };

  Type mType;
  Value mValue;

  HTMLImageElementOrHTMLCanvasElementOrHTMLVideoElement(const HTMLImageElementOrHTMLCanvasElementOrHTMLVideoElement&) MOZ_DELETE;
  void operator=(const HTMLImageElementOrHTMLCanvasElementOrHTMLVideoElement) MOZ_DELETE;
public:
  explicit inline HTMLImageElementOrHTMLCanvasElementOrHTMLVideoElement()
    : mType(eUninitialized)
  {
  }

  inline ~HTMLImageElementOrHTMLCanvasElementOrHTMLVideoElement()
  {
    Uninit();
  }

  inline NonNull<mozilla::dom::HTMLImageElement>&
  RawSetAsHTMLImageElement()
  {
    if (mType == eHTMLImageElement) {
      return mValue.mHTMLImageElement.Value();
    }
    MOZ_ASSERT(mType == eUninitialized);
    mType = eHTMLImageElement;
    return mValue.mHTMLImageElement.SetValue();
  }

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

  inline bool
  IsHTMLImageElement() const
  {
    return mType == eHTMLImageElement;
  }

  inline NonNull<mozilla::dom::HTMLImageElement>&
  GetAsHTMLImageElement()
  {
    MOZ_ASSERT(IsHTMLImageElement(), "Wrong type!");
    return mValue.mHTMLImageElement.Value();
  }

  inline mozilla::dom::HTMLImageElement&
  GetAsHTMLImageElement() const
  {
    MOZ_ASSERT(IsHTMLImageElement(), "Wrong type!");
    return mValue.mHTMLImageElement.Value();
  }

  inline NonNull<mozilla::dom::HTMLCanvasElement>&
  RawSetAsHTMLCanvasElement()
  {
    if (mType == eHTMLCanvasElement) {
      return mValue.mHTMLCanvasElement.Value();
    }
    MOZ_ASSERT(mType == eUninitialized);
    mType = eHTMLCanvasElement;
    return mValue.mHTMLCanvasElement.SetValue();
  }

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

  inline bool
  IsHTMLCanvasElement() const
  {
    return mType == eHTMLCanvasElement;
  }

  inline NonNull<mozilla::dom::HTMLCanvasElement>&
  GetAsHTMLCanvasElement()
  {
    MOZ_ASSERT(IsHTMLCanvasElement(), "Wrong type!");
    return mValue.mHTMLCanvasElement.Value();
  }

  inline mozilla::dom::HTMLCanvasElement&
  GetAsHTMLCanvasElement() const
  {
    MOZ_ASSERT(IsHTMLCanvasElement(), "Wrong type!");
    return mValue.mHTMLCanvasElement.Value();
  }

  inline NonNull<mozilla::dom::HTMLVideoElement>&
  RawSetAsHTMLVideoElement()
  {
    if (mType == eHTMLVideoElement) {
      return mValue.mHTMLVideoElement.Value();
    }
    MOZ_ASSERT(mType == eUninitialized);
    mType = eHTMLVideoElement;
    return mValue.mHTMLVideoElement.SetValue();
  }

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

  inline bool
  IsHTMLVideoElement() const
  {
    return mType == eHTMLVideoElement;
  }

  inline NonNull<mozilla::dom::HTMLVideoElement>&
  GetAsHTMLVideoElement()
  {
    MOZ_ASSERT(IsHTMLVideoElement(), "Wrong type!");
    return mValue.mHTMLVideoElement.Value();
  }

  inline mozilla::dom::HTMLVideoElement&
  GetAsHTMLVideoElement() const
  {
    MOZ_ASSERT(IsHTMLVideoElement(), "Wrong type!");
    return mValue.mHTMLVideoElement.Value();
  }

  bool
  ToJSVal(JSContext* cx, JS::Handle<JSObject*> scopeObj, JS::MutableHandle<JS::Value> rval) const;

private:
  inline void
  DestroyHTMLImageElement()
  {
    MOZ_ASSERT(IsHTMLImageElement(), "Wrong type!");
    mValue.mHTMLImageElement.Destroy();
    mType = eUninitialized;
  }

  inline void
  DestroyHTMLCanvasElement()
  {
    MOZ_ASSERT(IsHTMLCanvasElement(), "Wrong type!");
    mValue.mHTMLCanvasElement.Destroy();
    mType = eUninitialized;
  }

  inline void
  DestroyHTMLVideoElement()
  {
    MOZ_ASSERT(IsHTMLVideoElement(), "Wrong type!");
    mValue.mHTMLVideoElement.Destroy();
    mType = eUninitialized;
  }

  inline void
  Uninit()
  {
    switch (mType) {
      case eUninitialized: {
        break;
      }
      case eHTMLImageElement: {
        DestroyHTMLImageElement();
        break;
      }
      case eHTMLCanvasElement: {
        DestroyHTMLCanvasElement();
        break;
      }
      case eHTMLVideoElement: {
        DestroyHTMLVideoElement();
        break;
      }
    }
  }
};

class HTMLOptionElementOrHTMLOptGroupElement
{
  friend class HTMLOptionElementOrHTMLOptGroupElementArgument;
  enum Type
  {
    eUninitialized,
    eHTMLOptionElement,
    eHTMLOptGroupElement
  };

  union Value
  {
    UnionMember<NonNull<mozilla::dom::HTMLOptionElement> > mHTMLOptionElement;
    UnionMember<NonNull<mozilla::dom::HTMLOptGroupElement> > mHTMLOptGroupElement;

  };

  Type mType;
  Value mValue;

  HTMLOptionElementOrHTMLOptGroupElement(const HTMLOptionElementOrHTMLOptGroupElement&) MOZ_DELETE;
  void operator=(const HTMLOptionElementOrHTMLOptGroupElement) MOZ_DELETE;
public:
  explicit inline HTMLOptionElementOrHTMLOptGroupElement()
    : mType(eUninitialized)
  {
  }

  inline ~HTMLOptionElementOrHTMLOptGroupElement()
  {
    Uninit();
  }

  inline NonNull<mozilla::dom::HTMLOptionElement>&
  RawSetAsHTMLOptionElement()
  {
    if (mType == eHTMLOptionElement) {
      return mValue.mHTMLOptionElement.Value();
    }
    MOZ_ASSERT(mType == eUninitialized);
    mType = eHTMLOptionElement;
    return mValue.mHTMLOptionElement.SetValue();
  }

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

  inline bool
  IsHTMLOptionElement() const
  {
    return mType == eHTMLOptionElement;
  }

  inline NonNull<mozilla::dom::HTMLOptionElement>&
  GetAsHTMLOptionElement()
  {
    MOZ_ASSERT(IsHTMLOptionElement(), "Wrong type!");
    return mValue.mHTMLOptionElement.Value();
  }

  inline mozilla::dom::HTMLOptionElement&
  GetAsHTMLOptionElement() const
  {
    MOZ_ASSERT(IsHTMLOptionElement(), "Wrong type!");
    return mValue.mHTMLOptionElement.Value();
  }

  inline NonNull<mozilla::dom::HTMLOptGroupElement>&
  RawSetAsHTMLOptGroupElement()
  {
    if (mType == eHTMLOptGroupElement) {
      return mValue.mHTMLOptGroupElement.Value();
    }
    MOZ_ASSERT(mType == eUninitialized);
    mType = eHTMLOptGroupElement;
    return mValue.mHTMLOptGroupElement.SetValue();
  }

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

  inline bool
  IsHTMLOptGroupElement() const
  {
    return mType == eHTMLOptGroupElement;
  }

  inline NonNull<mozilla::dom::HTMLOptGroupElement>&
  GetAsHTMLOptGroupElement()
  {
    MOZ_ASSERT(IsHTMLOptGroupElement(), "Wrong type!");
    return mValue.mHTMLOptGroupElement.Value();
  }

  inline mozilla::dom::HTMLOptGroupElement&
  GetAsHTMLOptGroupElement() const
  {
    MOZ_ASSERT(IsHTMLOptGroupElement(), "Wrong type!");
    return mValue.mHTMLOptGroupElement.Value();
  }

  bool
  ToJSVal(JSContext* cx, JS::Handle<JSObject*> scopeObj, JS::MutableHandle<JS::Value> rval) const;

private:
  inline void
  DestroyHTMLOptionElement()
  {
    MOZ_ASSERT(IsHTMLOptionElement(), "Wrong type!");
    mValue.mHTMLOptionElement.Destroy();
    mType = eUninitialized;
  }

  inline void
  DestroyHTMLOptGroupElement()
  {
    MOZ_ASSERT(IsHTMLOptGroupElement(), "Wrong type!");
    mValue.mHTMLOptGroupElement.Destroy();
    mType = eUninitialized;
  }

  inline void
  Uninit()
  {
    switch (mType) {
      case eUninitialized: {
        break;
      }
      case eHTMLOptionElement: {
        DestroyHTMLOptionElement();
        break;
      }
      case eHTMLOptGroupElement: {
        DestroyHTMLOptGroupElement();
        break;
      }
    }
  }
};

class HeadersOrByteStringSequenceSequenceOrByteStringMozMap
{
  friend class HeadersOrByteStringSequenceSequenceOrByteStringMozMapArgument;
  enum Type
  {
    eUninitialized,
    eHeaders,
    eByteStringSequenceSequence,
    eByteStringMozMap
  };

  union Value
  {
    UnionMember<NonNull<mozilla::dom::Headers> > mHeaders;
    UnionMember<binding_detail::AutoSequence<Sequence<nsCString>> > mByteStringSequenceSequence;
    UnionMember<MozMap<nsCString> > mByteStringMozMap;

  };

  Type mType;
  Value mValue;

  HeadersOrByteStringSequenceSequenceOrByteStringMozMap(const HeadersOrByteStringSequenceSequenceOrByteStringMozMap&) MOZ_DELETE;
  void operator=(const HeadersOrByteStringSequenceSequenceOrByteStringMozMap) MOZ_DELETE;
public:
  explicit inline HeadersOrByteStringSequenceSequenceOrByteStringMozMap()
    : mType(eUninitialized)
  {
  }

  inline ~HeadersOrByteStringSequenceSequenceOrByteStringMozMap()
  {
    Uninit();
  }

  inline NonNull<mozilla::dom::Headers>&
  RawSetAsHeaders()
  {
    if (mType == eHeaders) {
      return mValue.mHeaders.Value();
    }
    MOZ_ASSERT(mType == eUninitialized);
    mType = eHeaders;
    return mValue.mHeaders.SetValue();
  }

  inline NonNull<mozilla::dom::Headers>&
  SetAsHeaders()
  {
    if (mType == eHeaders) {
      return mValue.mHeaders.Value();
    }
    Uninit();
    mType = eHeaders;
    return mValue.mHeaders.SetValue();
  }

  inline bool
  IsHeaders() const
  {
    return mType == eHeaders;
  }

  inline NonNull<mozilla::dom::Headers>&
  GetAsHeaders()
  {
    MOZ_ASSERT(IsHeaders(), "Wrong type!");
    return mValue.mHeaders.Value();
  }

  inline mozilla::dom::Headers&
  GetAsHeaders() const
  {
    MOZ_ASSERT(IsHeaders(), "Wrong type!");
    return mValue.mHeaders.Value();
  }

  inline binding_detail::AutoSequence<Sequence<nsCString>>&
  RawSetAsByteStringSequenceSequence()
  {
    if (mType == eByteStringSequenceSequence) {
      return mValue.mByteStringSequenceSequence.Value();
    }
    MOZ_ASSERT(mType == eUninitialized);
    mType = eByteStringSequenceSequence;
    return mValue.mByteStringSequenceSequence.SetValue();
  }

  inline binding_detail::AutoSequence<Sequence<nsCString>>&
  SetAsByteStringSequenceSequence()
  {
    if (mType == eByteStringSequenceSequence) {
      return mValue.mByteStringSequenceSequence.Value();
    }
    Uninit();
    mType = eByteStringSequenceSequence;
    return mValue.mByteStringSequenceSequence.SetValue();
  }

  inline bool
  IsByteStringSequenceSequence() const
  {
    return mType == eByteStringSequenceSequence;
  }

  inline binding_detail::AutoSequence<Sequence<nsCString>>&
  GetAsByteStringSequenceSequence()
  {
    MOZ_ASSERT(IsByteStringSequenceSequence(), "Wrong type!");
    return mValue.mByteStringSequenceSequence.Value();
  }

  inline const Sequence<Sequence<nsCString>>&
  GetAsByteStringSequenceSequence() const
  {
    MOZ_ASSERT(IsByteStringSequenceSequence(), "Wrong type!");
    return mValue.mByteStringSequenceSequence.Value();
  }

  inline MozMap<nsCString>&
  RawSetAsByteStringMozMap()
  {
    if (mType == eByteStringMozMap) {
      return mValue.mByteStringMozMap.Value();
    }
    MOZ_ASSERT(mType == eUninitialized);
    mType = eByteStringMozMap;
    return mValue.mByteStringMozMap.SetValue();
  }

  inline MozMap<nsCString>&
  SetAsByteStringMozMap()
  {
    if (mType == eByteStringMozMap) {
      return mValue.mByteStringMozMap.Value();
    }
    Uninit();
    mType = eByteStringMozMap;
    return mValue.mByteStringMozMap.SetValue();
  }

  inline bool
  IsByteStringMozMap() const
  {
    return mType == eByteStringMozMap;
  }

  inline MozMap<nsCString>&
  GetAsByteStringMozMap()
  {
    MOZ_ASSERT(IsByteStringMozMap(), "Wrong type!");
    return mValue.mByteStringMozMap.Value();
  }

  inline const MozMap<nsCString>&
  GetAsByteStringMozMap() const
  {
    MOZ_ASSERT(IsByteStringMozMap(), "Wrong type!");
    return mValue.mByteStringMozMap.Value();
  }

  bool
  ToJSVal(JSContext* cx, JS::Handle<JSObject*> scopeObj, JS::MutableHandle<JS::Value> rval) const;

private:
  inline void
  DestroyHeaders()
  {
    MOZ_ASSERT(IsHeaders(), "Wrong type!");
    mValue.mHeaders.Destroy();
    mType = eUninitialized;
  }

  inline void
  DestroyByteStringSequenceSequence()
  {
    MOZ_ASSERT(IsByteStringSequenceSequence(), "Wrong type!");
    mValue.mByteStringSequenceSequence.Destroy();
    mType = eUninitialized;
  }

  inline void
  DestroyByteStringMozMap()
  {
    MOZ_ASSERT(IsByteStringMozMap(), "Wrong type!");
    mValue.mByteStringMozMap.Destroy();
    mType = eUninitialized;
  }

  inline void
  Uninit()
  {
    switch (mType) {
      case eUninitialized: {
        break;
      }
      case eHeaders: {
        DestroyHeaders();
        break;
      }
      case eByteStringSequenceSequence: {
        DestroyByteStringSequenceSequence();
        break;
      }
      case eByteStringMozMap: {
        DestroyByteStringMozMap();
        break;
      }
    }
  }
};

class IDBObjectStoreOrIDBIndex
{
  friend class IDBObjectStoreOrIDBIndexArgument;
  enum Type
  {
    eUninitialized,
    eIDBObjectStore,
    eIDBIndex
  };

  union Value
  {
    UnionMember<NonNull<mozilla::dom::indexedDB::IDBObjectStore> > mIDBObjectStore;
    UnionMember<NonNull<mozilla::dom::indexedDB::IDBIndex> > mIDBIndex;

  };

  Type mType;
  Value mValue;

  IDBObjectStoreOrIDBIndex(const IDBObjectStoreOrIDBIndex&) MOZ_DELETE;
  void operator=(const IDBObjectStoreOrIDBIndex) MOZ_DELETE;
public:
  explicit inline IDBObjectStoreOrIDBIndex()
    : mType(eUninitialized)
  {
  }

  inline ~IDBObjectStoreOrIDBIndex()
  {
    Uninit();
  }

  inline NonNull<mozilla::dom::indexedDB::IDBObjectStore>&
  RawSetAsIDBObjectStore()
  {
    if (mType == eIDBObjectStore) {
      return mValue.mIDBObjectStore.Value();
    }
    MOZ_ASSERT(mType == eUninitialized);
    mType = eIDBObjectStore;
    return mValue.mIDBObjectStore.SetValue();
  }

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

  inline bool
  IsIDBObjectStore() const
  {
    return mType == eIDBObjectStore;
  }

  inline NonNull<mozilla::dom::indexedDB::IDBObjectStore>&
  GetAsIDBObjectStore()
  {
    MOZ_ASSERT(IsIDBObjectStore(), "Wrong type!");
    return mValue.mIDBObjectStore.Value();
  }

  inline mozilla::dom::indexedDB::IDBObjectStore&
  GetAsIDBObjectStore() const
  {
    MOZ_ASSERT(IsIDBObjectStore(), "Wrong type!");
    return mValue.mIDBObjectStore.Value();
  }

  inline NonNull<mozilla::dom::indexedDB::IDBIndex>&
  RawSetAsIDBIndex()
  {
    if (mType == eIDBIndex) {
      return mValue.mIDBIndex.Value();
    }
    MOZ_ASSERT(mType == eUninitialized);
    mType = eIDBIndex;
    return mValue.mIDBIndex.SetValue();
  }

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

  inline bool
  IsIDBIndex() const
  {
    return mType == eIDBIndex;
  }

  inline NonNull<mozilla::dom::indexedDB::IDBIndex>&
  GetAsIDBIndex()
  {
    MOZ_ASSERT(IsIDBIndex(), "Wrong type!");
    return mValue.mIDBIndex.Value();
  }

  inline mozilla::dom::indexedDB::IDBIndex&
  GetAsIDBIndex() const
  {
    MOZ_ASSERT(IsIDBIndex(), "Wrong type!");
    return mValue.mIDBIndex.Value();
  }

  bool
  ToJSVal(JSContext* cx, JS::Handle<JSObject*> scopeObj, JS::MutableHandle<JS::Value> rval) const;

private:
  inline void
  DestroyIDBObjectStore()
  {
    MOZ_ASSERT(IsIDBObjectStore(), "Wrong type!");
    mValue.mIDBObjectStore.Destroy();
    mType = eUninitialized;
  }

  inline void
  DestroyIDBIndex()
  {
    MOZ_ASSERT(IsIDBIndex(), "Wrong type!");
    mValue.mIDBIndex.Destroy();
    mType = eUninitialized;
  }

  inline void
  Uninit()
  {
    switch (mType) {
      case eUninitialized: {
        break;
      }
      case eIDBObjectStore: {
        DestroyIDBObjectStore();
        break;
      }
      case eIDBIndex: {
        DestroyIDBIndex();
        break;
      }
    }
  }
};

class IDBObjectStoreOrIDBIndexOrIDBCursor
{
  friend class IDBObjectStoreOrIDBIndexOrIDBCursorArgument;
  enum Type
  {
    eUninitialized,
    eIDBObjectStore,
    eIDBIndex,
    eIDBCursor
  };

  union Value
  {
    UnionMember<NonNull<mozilla::dom::indexedDB::IDBObjectStore> > mIDBObjectStore;
    UnionMember<NonNull<mozilla::dom::indexedDB::IDBIndex> > mIDBIndex;
    UnionMember<NonNull<mozilla::dom::indexedDB::IDBCursor> > mIDBCursor;

  };

  Type mType;
  Value mValue;

  IDBObjectStoreOrIDBIndexOrIDBCursor(const IDBObjectStoreOrIDBIndexOrIDBCursor&) MOZ_DELETE;
  void operator=(const IDBObjectStoreOrIDBIndexOrIDBCursor) MOZ_DELETE;
public:
  explicit inline IDBObjectStoreOrIDBIndexOrIDBCursor()
    : mType(eUninitialized)
  {
  }

  inline ~IDBObjectStoreOrIDBIndexOrIDBCursor()
  {
    Uninit();
  }

  inline NonNull<mozilla::dom::indexedDB::IDBObjectStore>&
  RawSetAsIDBObjectStore()
  {
    if (mType == eIDBObjectStore) {
      return mValue.mIDBObjectStore.Value();
    }
    MOZ_ASSERT(mType == eUninitialized);
    mType = eIDBObjectStore;
    return mValue.mIDBObjectStore.SetValue();
  }

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

  inline bool
  IsIDBObjectStore() const
  {
    return mType == eIDBObjectStore;
  }

  inline NonNull<mozilla::dom::indexedDB::IDBObjectStore>&
  GetAsIDBObjectStore()
  {
    MOZ_ASSERT(IsIDBObjectStore(), "Wrong type!");
    return mValue.mIDBObjectStore.Value();
  }

  inline mozilla::dom::indexedDB::IDBObjectStore&
  GetAsIDBObjectStore() const
  {
    MOZ_ASSERT(IsIDBObjectStore(), "Wrong type!");
    return mValue.mIDBObjectStore.Value();
  }

  inline NonNull<mozilla::dom::indexedDB::IDBIndex>&
  RawSetAsIDBIndex()
  {
    if (mType == eIDBIndex) {
      return mValue.mIDBIndex.Value();
    }
    MOZ_ASSERT(mType == eUninitialized);
    mType = eIDBIndex;
    return mValue.mIDBIndex.SetValue();
  }

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

  inline bool
  IsIDBIndex() const
  {
    return mType == eIDBIndex;
  }

  inline NonNull<mozilla::dom::indexedDB::IDBIndex>&
  GetAsIDBIndex()
  {
    MOZ_ASSERT(IsIDBIndex(), "Wrong type!");
    return mValue.mIDBIndex.Value();
  }

  inline mozilla::dom::indexedDB::IDBIndex&
  GetAsIDBIndex() const
  {
    MOZ_ASSERT(IsIDBIndex(), "Wrong type!");
    return mValue.mIDBIndex.Value();
  }

  inline NonNull<mozilla::dom::indexedDB::IDBCursor>&
  RawSetAsIDBCursor()
  {
    if (mType == eIDBCursor) {
      return mValue.mIDBCursor.Value();
    }
    MOZ_ASSERT(mType == eUninitialized);
    mType = eIDBCursor;
    return mValue.mIDBCursor.SetValue();
  }

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

  inline bool
  IsIDBCursor() const
  {
    return mType == eIDBCursor;
  }

  inline NonNull<mozilla::dom::indexedDB::IDBCursor>&
  GetAsIDBCursor()
  {
    MOZ_ASSERT(IsIDBCursor(), "Wrong type!");
    return mValue.mIDBCursor.Value();
  }

  inline mozilla::dom::indexedDB::IDBCursor&
  GetAsIDBCursor() const
  {
    MOZ_ASSERT(IsIDBCursor(), "Wrong type!");
    return mValue.mIDBCursor.Value();
  }

  bool
  ToJSVal(JSContext* cx, JS::Handle<JSObject*> scopeObj, JS::MutableHandle<JS::Value> rval) const;

private:
  inline void
  DestroyIDBObjectStore()
  {
    MOZ_ASSERT(IsIDBObjectStore(), "Wrong type!");
    mValue.mIDBObjectStore.Destroy();
    mType = eUninitialized;
  }

  inline void
  DestroyIDBIndex()
  {
    MOZ_ASSERT(IsIDBIndex(), "Wrong type!");
    mValue.mIDBIndex.Destroy();
    mType = eUninitialized;
  }

  inline void
  DestroyIDBCursor()
  {
    MOZ_ASSERT(IsIDBCursor(), "Wrong type!");
    mValue.mIDBCursor.Destroy();
    mType = eUninitialized;
  }

  inline void
  Uninit()
  {
    switch (mType) {
      case eUninitialized: {
        break;
      }
      case eIDBObjectStore: {
        DestroyIDBObjectStore();
        break;
      }
      case eIDBIndex: {
        DestroyIDBIndex();
        break;
      }
      case eIDBCursor: {
        DestroyIDBCursor();
        break;
      }
    }
  }
};

class LongOrAutoKeyword
{
  friend class LongOrAutoKeywordArgument;
  enum Type
  {
    eUninitialized,
    eLong,
    eAutoKeyword
  };

  union Value
  {
    UnionMember<int32_t > mLong;
    UnionMember<AutoKeyword > mAutoKeyword;

  };

  Type mType;
  Value mValue;

  LongOrAutoKeyword(const LongOrAutoKeyword&) MOZ_DELETE;
  void operator=(const LongOrAutoKeyword) MOZ_DELETE;
public:
  explicit inline LongOrAutoKeyword()
    : mType(eUninitialized)
  {
  }

  inline ~LongOrAutoKeyword()
  {
    Uninit();
  }

  inline int32_t&
  RawSetAsLong()
  {
    if (mType == eLong) {
      return mValue.mLong.Value();
    }
    MOZ_ASSERT(mType == eUninitialized);
    mType = eLong;
    return mValue.mLong.SetValue();
  }

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

  inline bool
  IsLong() const
  {
    return mType == eLong;
  }

  inline int32_t&
  GetAsLong()
  {
    MOZ_ASSERT(IsLong(), "Wrong type!");
    return mValue.mLong.Value();
  }

  inline int32_t
  GetAsLong() const
  {
    MOZ_ASSERT(IsLong(), "Wrong type!");
    return mValue.mLong.Value();
  }

  inline AutoKeyword&
  RawSetAsAutoKeyword()
  {
    if (mType == eAutoKeyword) {
      return mValue.mAutoKeyword.Value();
    }
    MOZ_ASSERT(mType == eUninitialized);
    mType = eAutoKeyword;
    return mValue.mAutoKeyword.SetValue();
  }

  inline AutoKeyword&
  SetAsAutoKeyword()
  {
    if (mType == eAutoKeyword) {
      return mValue.mAutoKeyword.Value();
    }
    Uninit();
    mType = eAutoKeyword;
    return mValue.mAutoKeyword.SetValue();
  }

  inline bool
  IsAutoKeyword() const
  {
    return mType == eAutoKeyword;
  }

  inline AutoKeyword&
  GetAsAutoKeyword()
  {
    MOZ_ASSERT(IsAutoKeyword(), "Wrong type!");
    return mValue.mAutoKeyword.Value();
  }

  inline AutoKeyword
  GetAsAutoKeyword() const
  {
    MOZ_ASSERT(IsAutoKeyword(), "Wrong type!");
    return mValue.mAutoKeyword.Value();
  }

  bool
  ToJSVal(JSContext* cx, JS::Handle<JSObject*> scopeObj, JS::MutableHandle<JS::Value> rval) const;

private:
  inline void
  DestroyLong()
  {
    MOZ_ASSERT(IsLong(), "Wrong type!");
    mValue.mLong.Destroy();
    mType = eUninitialized;
  }

  inline void
  DestroyAutoKeyword()
  {
    MOZ_ASSERT(IsAutoKeyword(), "Wrong type!");
    mValue.mAutoKeyword.Destroy();
    mType = eUninitialized;
  }

  inline void
  Uninit()
  {
    switch (mType) {
      case eUninitialized: {
        break;
      }
      case eLong: {
        DestroyLong();
        break;
      }
      case eAutoKeyword: {
        DestroyAutoKeyword();
        break;
      }
    }
  }
};

class LongOrMozSmsMessageOrMozMmsMessage
{
  friend class LongOrMozSmsMessageOrMozMmsMessageArgument;
  enum Type
  {
    eUninitialized,
    eLong,
    eMozSmsMessage,
    eMozMmsMessage
  };

  union Value
  {
    UnionMember<int32_t > mLong;
    UnionMember<nsIDOMMozSmsMessage* > mMozSmsMessage;
    UnionMember<nsIDOMMozMmsMessage* > mMozMmsMessage;

  };

  Type mType;
  Value mValue;

  LongOrMozSmsMessageOrMozMmsMessage(const LongOrMozSmsMessageOrMozMmsMessage&) MOZ_DELETE;
  void operator=(const LongOrMozSmsMessageOrMozMmsMessage) MOZ_DELETE;
public:
  explicit inline LongOrMozSmsMessageOrMozMmsMessage()
    : mType(eUninitialized)
  {
  }

  inline ~LongOrMozSmsMessageOrMozMmsMessage()
  {
    Uninit();
  }

  inline int32_t&
  RawSetAsLong()
  {
    if (mType == eLong) {
      return mValue.mLong.Value();
    }
    MOZ_ASSERT(mType == eUninitialized);
    mType = eLong;
    return mValue.mLong.SetValue();
  }

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

  inline bool
  IsLong() const
  {
    return mType == eLong;
  }

  inline int32_t&
  GetAsLong()
  {
    MOZ_ASSERT(IsLong(), "Wrong type!");
    return mValue.mLong.Value();
  }

  inline int32_t
  GetAsLong() const
  {
    MOZ_ASSERT(IsLong(), "Wrong type!");
    return mValue.mLong.Value();
  }

  inline nsIDOMMozSmsMessage*&
  RawSetAsMozSmsMessage()
  {
    if (mType == eMozSmsMessage) {
      return mValue.mMozSmsMessage.Value();
    }
    MOZ_ASSERT(mType == eUninitialized);
    mType = eMozSmsMessage;
    return mValue.mMozSmsMessage.SetValue();
  }

  inline nsIDOMMozSmsMessage*&
  SetAsMozSmsMessage()
  {
    if (mType == eMozSmsMessage) {
      return mValue.mMozSmsMessage.Value();
    }
    Uninit();
    mType = eMozSmsMessage;
    return mValue.mMozSmsMessage.SetValue();
  }

  inline bool
  IsMozSmsMessage() const
  {
    return mType == eMozSmsMessage;
  }

  inline nsIDOMMozSmsMessage*&
  GetAsMozSmsMessage()
  {
    MOZ_ASSERT(IsMozSmsMessage(), "Wrong type!");
    return mValue.mMozSmsMessage.Value();
  }

  inline nsIDOMMozSmsMessage*
  GetAsMozSmsMessage() const
  {
    MOZ_ASSERT(IsMozSmsMessage(), "Wrong type!");
    return mValue.mMozSmsMessage.Value();
  }

  inline nsIDOMMozMmsMessage*&
  RawSetAsMozMmsMessage()
  {
    if (mType == eMozMmsMessage) {
      return mValue.mMozMmsMessage.Value();
    }
    MOZ_ASSERT(mType == eUninitialized);
    mType = eMozMmsMessage;
    return mValue.mMozMmsMessage.SetValue();
  }

  inline nsIDOMMozMmsMessage*&
  SetAsMozMmsMessage()
  {
    if (mType == eMozMmsMessage) {
      return mValue.mMozMmsMessage.Value();
    }
    Uninit();
    mType = eMozMmsMessage;
    return mValue.mMozMmsMessage.SetValue();
  }

  inline bool
  IsMozMmsMessage() const
  {
    return mType == eMozMmsMessage;
  }

  inline nsIDOMMozMmsMessage*&
  GetAsMozMmsMessage()
  {
    MOZ_ASSERT(IsMozMmsMessage(), "Wrong type!");
    return mValue.mMozMmsMessage.Value();
  }

  inline nsIDOMMozMmsMessage*
  GetAsMozMmsMessage() const
  {
    MOZ_ASSERT(IsMozMmsMessage(), "Wrong type!");
    return mValue.mMozMmsMessage.Value();
  }

  bool
  ToJSVal(JSContext* cx, JS::Handle<JSObject*> scopeObj, JS::MutableHandle<JS::Value> rval) const;

private:
  inline void
  DestroyLong()
  {
    MOZ_ASSERT(IsLong(), "Wrong type!");
    mValue.mLong.Destroy();
    mType = eUninitialized;
  }

  inline void
  DestroyMozSmsMessage()
  {
    MOZ_ASSERT(IsMozSmsMessage(), "Wrong type!");
    mValue.mMozSmsMessage.Destroy();
    mType = eUninitialized;
  }

  inline void
  DestroyMozMmsMessage()
  {
    MOZ_ASSERT(IsMozMmsMessage(), "Wrong type!");
    mValue.mMozMmsMessage.Destroy();
    mType = eUninitialized;
  }

  inline void
  Uninit()
  {
    switch (mType) {
      case eUninitialized: {
        break;
      }
      case eLong: {
        DestroyLong();
        break;
      }
      case eMozSmsMessage: {
        DestroyMozSmsMessage();
        break;
      }
      case eMozMmsMessage: {
        DestroyMozMmsMessage();
        break;
      }
    }
  }
};

class MozSmsMessageOrMozMmsMessage
{
  friend class MozSmsMessageOrMozMmsMessageArgument;
  enum Type
  {
    eUninitialized,
    eMozSmsMessage,
    eMozMmsMessage
  };

  union Value
  {
    UnionMember<nsIDOMMozSmsMessage* > mMozSmsMessage;
    UnionMember<nsIDOMMozMmsMessage* > mMozMmsMessage;

  };

  Type mType;
  Value mValue;

  MozSmsMessageOrMozMmsMessage(const MozSmsMessageOrMozMmsMessage&) MOZ_DELETE;
  void operator=(const MozSmsMessageOrMozMmsMessage) MOZ_DELETE;
public:
  explicit inline MozSmsMessageOrMozMmsMessage()
    : mType(eUninitialized)
  {
  }

  inline ~MozSmsMessageOrMozMmsMessage()
  {
    Uninit();
  }

  inline nsIDOMMozSmsMessage*&
  RawSetAsMozSmsMessage()
  {
    if (mType == eMozSmsMessage) {
      return mValue.mMozSmsMessage.Value();
    }
    MOZ_ASSERT(mType == eUninitialized);
    mType = eMozSmsMessage;
    return mValue.mMozSmsMessage.SetValue();
  }

  inline nsIDOMMozSmsMessage*&
  SetAsMozSmsMessage()
  {
    if (mType == eMozSmsMessage) {
      return mValue.mMozSmsMessage.Value();
    }
    Uninit();
    mType = eMozSmsMessage;
    return mValue.mMozSmsMessage.SetValue();
  }

  inline bool
  IsMozSmsMessage() const
  {
    return mType == eMozSmsMessage;
  }

  inline nsIDOMMozSmsMessage*&
  GetAsMozSmsMessage()
  {
    MOZ_ASSERT(IsMozSmsMessage(), "Wrong type!");
    return mValue.mMozSmsMessage.Value();
  }

  inline nsIDOMMozSmsMessage*
  GetAsMozSmsMessage() const
  {
    MOZ_ASSERT(IsMozSmsMessage(), "Wrong type!");
    return mValue.mMozSmsMessage.Value();
  }

  inline nsIDOMMozMmsMessage*&
  RawSetAsMozMmsMessage()
  {
    if (mType == eMozMmsMessage) {
      return mValue.mMozMmsMessage.Value();
    }
    MOZ_ASSERT(mType == eUninitialized);
    mType = eMozMmsMessage;
    return mValue.mMozMmsMessage.SetValue();
  }

  inline nsIDOMMozMmsMessage*&
  SetAsMozMmsMessage()
  {
    if (mType == eMozMmsMessage) {
      return mValue.mMozMmsMessage.Value();
    }
    Uninit();
    mType = eMozMmsMessage;
    return mValue.mMozMmsMessage.SetValue();
  }

  inline bool
  IsMozMmsMessage() const
  {
    return mType == eMozMmsMessage;
  }

  inline nsIDOMMozMmsMessage*&
  GetAsMozMmsMessage()
  {
    MOZ_ASSERT(IsMozMmsMessage(), "Wrong type!");
    return mValue.mMozMmsMessage.Value();
  }

  inline nsIDOMMozMmsMessage*
  GetAsMozMmsMessage() const
  {
    MOZ_ASSERT(IsMozMmsMessage(), "Wrong type!");
    return mValue.mMozMmsMessage.Value();
  }

  bool
  ToJSVal(JSContext* cx, JS::Handle<JSObject*> scopeObj, JS::MutableHandle<JS::Value> rval) const;

private:
  inline void
  DestroyMozSmsMessage()
  {
    MOZ_ASSERT(IsMozSmsMessage(), "Wrong type!");
    mValue.mMozSmsMessage.Destroy();
    mType = eUninitialized;
  }

  inline void
  DestroyMozMmsMessage()
  {
    MOZ_ASSERT(IsMozMmsMessage(), "Wrong type!");
    mValue.mMozMmsMessage.Destroy();
    mType = eUninitialized;
  }

  inline void
  Uninit()
  {
    switch (mType) {
      case eUninitialized: {
        break;
      }
      case eMozSmsMessage: {
        DestroyMozSmsMessage();
        break;
      }
      case eMozMmsMessage: {
        DestroyMozMmsMessage();
        break;
      }
    }
  }
};

class NetworkStatsDataOrPowerStatsData
{
  friend class NetworkStatsDataOrPowerStatsDataArgument;
  enum Type
  {
    eUninitialized,
    eNetworkStatsData,
    ePowerStatsData
  };

  union Value
  {
    UnionMember<NonNull<mozilla::dom::NetworkStatsData> > mNetworkStatsData;
    UnionMember<NonNull<mozilla::dom::PowerStatsData> > mPowerStatsData;

  };

  Type mType;
  Value mValue;

  NetworkStatsDataOrPowerStatsData(const NetworkStatsDataOrPowerStatsData&) MOZ_DELETE;
  void operator=(const NetworkStatsDataOrPowerStatsData) MOZ_DELETE;
public:
  explicit inline NetworkStatsDataOrPowerStatsData()
    : mType(eUninitialized)
  {
  }

  inline ~NetworkStatsDataOrPowerStatsData()
  {
    Uninit();
  }

  inline NonNull<mozilla::dom::NetworkStatsData>&
  RawSetAsNetworkStatsData()
  {
    if (mType == eNetworkStatsData) {
      return mValue.mNetworkStatsData.Value();
    }
    MOZ_ASSERT(mType == eUninitialized);
    mType = eNetworkStatsData;
    return mValue.mNetworkStatsData.SetValue();
  }

  inline NonNull<mozilla::dom::NetworkStatsData>&
  SetAsNetworkStatsData()
  {
    if (mType == eNetworkStatsData) {
      return mValue.mNetworkStatsData.Value();
    }
    Uninit();
    mType = eNetworkStatsData;
    return mValue.mNetworkStatsData.SetValue();
  }

  inline bool
  IsNetworkStatsData() const
  {
    return mType == eNetworkStatsData;
  }

  inline NonNull<mozilla::dom::NetworkStatsData>&
  GetAsNetworkStatsData()
  {
    MOZ_ASSERT(IsNetworkStatsData(), "Wrong type!");
    return mValue.mNetworkStatsData.Value();
  }

  inline mozilla::dom::NetworkStatsData&
  GetAsNetworkStatsData() const
  {
    MOZ_ASSERT(IsNetworkStatsData(), "Wrong type!");
    return mValue.mNetworkStatsData.Value();
  }

  inline NonNull<mozilla::dom::PowerStatsData>&
  RawSetAsPowerStatsData()
  {
    if (mType == ePowerStatsData) {
      return mValue.mPowerStatsData.Value();
    }
    MOZ_ASSERT(mType == eUninitialized);
    mType = ePowerStatsData;
    return mValue.mPowerStatsData.SetValue();
  }

  inline NonNull<mozilla::dom::PowerStatsData>&
  SetAsPowerStatsData()
  {
    if (mType == ePowerStatsData) {
      return mValue.mPowerStatsData.Value();
    }
    Uninit();
    mType = ePowerStatsData;
    return mValue.mPowerStatsData.SetValue();
  }

  inline bool
  IsPowerStatsData() const
  {
    return mType == ePowerStatsData;
  }

  inline NonNull<mozilla::dom::PowerStatsData>&
  GetAsPowerStatsData()
  {
    MOZ_ASSERT(IsPowerStatsData(), "Wrong type!");
    return mValue.mPowerStatsData.Value();
  }

  inline mozilla::dom::PowerStatsData&
  GetAsPowerStatsData() const
  {
    MOZ_ASSERT(IsPowerStatsData(), "Wrong type!");
    return mValue.mPowerStatsData.Value();
  }

  bool
  ToJSVal(JSContext* cx, JS::Handle<JSObject*> scopeObj, JS::MutableHandle<JS::Value> rval) const;

private:
  inline void
  DestroyNetworkStatsData()
  {
    MOZ_ASSERT(IsNetworkStatsData(), "Wrong type!");
    mValue.mNetworkStatsData.Destroy();
    mType = eUninitialized;
  }

  inline void
  DestroyPowerStatsData()
  {
    MOZ_ASSERT(IsPowerStatsData(), "Wrong type!");
    mValue.mPowerStatsData.Destroy();
    mType = eUninitialized;
  }

  inline void
  Uninit()
  {
    switch (mType) {
      case eUninitialized: {
        break;
      }
      case eNetworkStatsData: {
        DestroyNetworkStatsData();
        break;
      }
      case ePowerStatsData: {
        DestroyPowerStatsData();
        break;
      }
    }
  }
};

class NodeOrHTMLCollection
{
  friend class NodeOrHTMLCollectionArgument;
  enum Type
  {
    eUninitialized,
    eNode,
    eHTMLCollection
  };

  union Value
  {
    UnionMember<NonNull<nsINode> > mNode;
    UnionMember<NonNull<nsIHTMLCollection> > mHTMLCollection;

  };

  Type mType;
  Value mValue;

  NodeOrHTMLCollection(const NodeOrHTMLCollection&) MOZ_DELETE;
  void operator=(const NodeOrHTMLCollection) MOZ_DELETE;
public:
  explicit inline NodeOrHTMLCollection()
    : mType(eUninitialized)
  {
  }

  inline ~NodeOrHTMLCollection()
  {
    Uninit();
  }

  inline NonNull<nsINode>&
  RawSetAsNode()
  {
    if (mType == eNode) {
      return mValue.mNode.Value();
    }
    MOZ_ASSERT(mType == eUninitialized);
    mType = eNode;
    return mValue.mNode.SetValue();
  }

  inline NonNull<nsINode>&
  SetAsNode()
  {
    if (mType == eNode) {
      return mValue.mNode.Value();
    }
    Uninit();
    mType = eNode;
    return mValue.mNode.SetValue();
  }

  inline bool
  IsNode() const
  {
    return mType == eNode;
  }

  inline NonNull<nsINode>&
  GetAsNode()
  {
    MOZ_ASSERT(IsNode(), "Wrong type!");
    return mValue.mNode.Value();
  }

  inline nsINode&
  GetAsNode() const
  {
    MOZ_ASSERT(IsNode(), "Wrong type!");
    return mValue.mNode.Value();
  }

  inline NonNull<nsIHTMLCollection>&
  RawSetAsHTMLCollection()
  {
    if (mType == eHTMLCollection) {
      return mValue.mHTMLCollection.Value();
    }
    MOZ_ASSERT(mType == eUninitialized);
    mType = eHTMLCollection;
    return mValue.mHTMLCollection.SetValue();
  }

  inline NonNull<nsIHTMLCollection>&
  SetAsHTMLCollection()
  {
    if (mType == eHTMLCollection) {
      return mValue.mHTMLCollection.Value();
    }
    Uninit();
    mType = eHTMLCollection;
    return mValue.mHTMLCollection.SetValue();
  }

  inline bool
  IsHTMLCollection() const
  {
    return mType == eHTMLCollection;
  }

  inline NonNull<nsIHTMLCollection>&
  GetAsHTMLCollection()
  {
    MOZ_ASSERT(IsHTMLCollection(), "Wrong type!");
    return mValue.mHTMLCollection.Value();
  }

  inline nsIHTMLCollection&
  GetAsHTMLCollection() const
  {
    MOZ_ASSERT(IsHTMLCollection(), "Wrong type!");
    return mValue.mHTMLCollection.Value();
  }

  bool
  ToJSVal(JSContext* cx, JS::Handle<JSObject*> scopeObj, JS::MutableHandle<JS::Value> rval) const;

private:
  inline void
  DestroyNode()
  {
    MOZ_ASSERT(IsNode(), "Wrong type!");
    mValue.mNode.Destroy();
    mType = eUninitialized;
  }

  inline void
  DestroyHTMLCollection()
  {
    MOZ_ASSERT(IsHTMLCollection(), "Wrong type!");
    mValue.mHTMLCollection.Destroy();
    mType = eUninitialized;
  }

  inline void
  Uninit()
  {
    switch (mType) {
      case eUninitialized: {
        break;
      }
      case eNode: {
        DestroyNode();
        break;
      }
      case eHTMLCollection: {
        DestroyHTMLCollection();
        break;
      }
    }
  }
};

class ObjectOrString
{
  friend class ObjectOrStringArgument;
  enum Type
  {
    eUninitialized,
    eObject,
    eString
  };

  union Value
  {
    UnionMember<JS::Rooted<JSObject*> > mObject;
    UnionMember<binding_detail::FakeString > mString;

  };

  Type mType;
  Value mValue;

  ObjectOrString(const ObjectOrString&) MOZ_DELETE;
  void operator=(const ObjectOrString) MOZ_DELETE;
public:
  explicit inline ObjectOrString()
    : mType(eUninitialized)
  {
  }

  inline ~ObjectOrString()
  {
    Uninit();
  }

  inline bool
  IsObject() const
  {
    return mType == eObject;
  }

  inline JS::Rooted<JSObject*>&
  GetAsObject()
  {
    MOZ_ASSERT(IsObject(), "Wrong type!");
    return mValue.mObject.Value();
  }

  inline JSObject*
  GetAsObject() const
  {
    MOZ_ASSERT(IsObject(), "Wrong type!");
    return mValue.mObject.Value();
  }

  inline binding_detail::FakeString&
  RawSetAsString()
  {
    if (mType == eString) {
      return mValue.mString.Value();
    }
    MOZ_ASSERT(mType == eUninitialized);
    mType = eString;
    return mValue.mString.SetValue();
  }

  inline binding_detail::FakeString&
  SetAsString()
  {
    if (mType == eString) {
      return mValue.mString.Value();
    }
    MOZ_ASSERT(mType != eObject, "This will not play well with Rooted");
    Uninit();
    mType = eString;
    return mValue.mString.SetValue();
  }

  inline bool
  IsString() const
  {
    return mType == eString;
  }

  inline binding_detail::FakeString&
  GetAsString()
  {
    MOZ_ASSERT(IsString(), "Wrong type!");
    return mValue.mString.Value();
  }

  inline const nsAString&
  GetAsString() const
  {
    MOZ_ASSERT(IsString(), "Wrong type!");
    return mValue.mString.Value();
  }

  bool
  ToJSVal(JSContext* cx, JS::Handle<JSObject*> scopeObj, JS::MutableHandle<JS::Value> rval) const;

private:
  inline void
  DestroyObject()
  {
    MOZ_ASSERT(IsObject(), "Wrong type!");
    mValue.mObject.Destroy();
    mType = eUninitialized;
  }

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

  inline void
  Uninit()
  {
    switch (mType) {
      case eUninitialized: {
        break;
      }
      case eObject: {
        DestroyObject();
        break;
      }
      case eString: {
        DestroyString();
        break;
      }
    }
  }
};

class RadioNodeListOrElement
{
  friend class RadioNodeListOrElementArgument;
  enum Type
  {
    eUninitialized,
    eRadioNodeList,
    eElement
  };

  union Value
  {
    UnionMember<NonNull<mozilla::dom::RadioNodeList> > mRadioNodeList;
    UnionMember<NonNull<mozilla::dom::Element> > mElement;

  };

  Type mType;
  Value mValue;

  RadioNodeListOrElement(const RadioNodeListOrElement&) MOZ_DELETE;
  void operator=(const RadioNodeListOrElement) MOZ_DELETE;
public:
  explicit inline RadioNodeListOrElement()
    : mType(eUninitialized)
  {
  }

  inline ~RadioNodeListOrElement()
  {
    Uninit();
  }

  inline NonNull<mozilla::dom::RadioNodeList>&
  RawSetAsRadioNodeList()
  {
    if (mType == eRadioNodeList) {
      return mValue.mRadioNodeList.Value();
    }
    MOZ_ASSERT(mType == eUninitialized);
    mType = eRadioNodeList;
    return mValue.mRadioNodeList.SetValue();
  }

  inline NonNull<mozilla::dom::RadioNodeList>&
  SetAsRadioNodeList()
  {
    if (mType == eRadioNodeList) {
      return mValue.mRadioNodeList.Value();
    }
    Uninit();
    mType = eRadioNodeList;
    return mValue.mRadioNodeList.SetValue();
  }

  inline bool
  IsRadioNodeList() const
  {
    return mType == eRadioNodeList;
  }

  inline NonNull<mozilla::dom::RadioNodeList>&
  GetAsRadioNodeList()
  {
    MOZ_ASSERT(IsRadioNodeList(), "Wrong type!");
    return mValue.mRadioNodeList.Value();
  }

  inline mozilla::dom::RadioNodeList&
  GetAsRadioNodeList() const
  {
    MOZ_ASSERT(IsRadioNodeList(), "Wrong type!");
    return mValue.mRadioNodeList.Value();
  }

  inline NonNull<mozilla::dom::Element>&
  RawSetAsElement()
  {
    if (mType == eElement) {
      return mValue.mElement.Value();
    }
    MOZ_ASSERT(mType == eUninitialized);
    mType = eElement;
    return mValue.mElement.SetValue();
  }

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

  inline bool
  IsElement() const
  {
    return mType == eElement;
  }

  inline NonNull<mozilla::dom::Element>&
  GetAsElement()
  {
    MOZ_ASSERT(IsElement(), "Wrong type!");
    return mValue.mElement.Value();
  }

  inline mozilla::dom::Element&
  GetAsElement() const
  {
    MOZ_ASSERT(IsElement(), "Wrong type!");
    return mValue.mElement.Value();
  }

  bool
  ToJSVal(JSContext* cx, JS::Handle<JSObject*> scopeObj, JS::MutableHandle<JS::Value> rval) const;

private:
  inline void
  DestroyRadioNodeList()
  {
    MOZ_ASSERT(IsRadioNodeList(), "Wrong type!");
    mValue.mRadioNodeList.Destroy();
    mType = eUninitialized;
  }

  inline void
  DestroyElement()
  {
    MOZ_ASSERT(IsElement(), "Wrong type!");
    mValue.mElement.Destroy();
    mType = eUninitialized;
  }

  inline void
  Uninit()
  {
    switch (mType) {
      case eUninitialized: {
        break;
      }
      case eRadioNodeList: {
        DestroyRadioNodeList();
        break;
      }
      case eElement: {
        DestroyElement();
        break;
      }
    }
  }
};

class RequestOrScalarValueString
{
  friend class RequestOrScalarValueStringArgument;
  enum Type
  {
    eUninitialized,
    eRequest,
    eScalarValueString
  };

  union Value
  {
    UnionMember<NonNull<mozilla::dom::Request> > mRequest;
    UnionMember<binding_detail::FakeString > mScalarValueString;

  };

  Type mType;
  Value mValue;

  RequestOrScalarValueString(const RequestOrScalarValueString&) MOZ_DELETE;
  void operator=(const RequestOrScalarValueString) MOZ_DELETE;
public:
  explicit inline RequestOrScalarValueString()
    : mType(eUninitialized)
  {
  }

  inline ~RequestOrScalarValueString()
  {
    Uninit();
  }

  inline NonNull<mozilla::dom::Request>&
  RawSetAsRequest()
  {
    if (mType == eRequest) {
      return mValue.mRequest.Value();
    }
    MOZ_ASSERT(mType == eUninitialized);
    mType = eRequest;
    return mValue.mRequest.SetValue();
  }

  inline NonNull<mozilla::dom::Request>&
  SetAsRequest()
  {
    if (mType == eRequest) {
      return mValue.mRequest.Value();
    }
    Uninit();
    mType = eRequest;
    return mValue.mRequest.SetValue();
  }

  inline bool
  IsRequest() const
  {
    return mType == eRequest;
  }

  inline NonNull<mozilla::dom::Request>&
  GetAsRequest()
  {
    MOZ_ASSERT(IsRequest(), "Wrong type!");
    return mValue.mRequest.Value();
  }

  inline mozilla::dom::Request&
  GetAsRequest() const
  {
    MOZ_ASSERT(IsRequest(), "Wrong type!");
    return mValue.mRequest.Value();
  }

  inline binding_detail::FakeString&
  RawSetAsScalarValueString()
  {
    if (mType == eScalarValueString) {
      return mValue.mScalarValueString.Value();
    }
    MOZ_ASSERT(mType == eUninitialized);
    mType = eScalarValueString;
    return mValue.mScalarValueString.SetValue();
  }

  inline binding_detail::FakeString&
  SetAsScalarValueString()
  {
    if (mType == eScalarValueString) {
      return mValue.mScalarValueString.Value();
    }
    Uninit();
    mType = eScalarValueString;
    return mValue.mScalarValueString.SetValue();
  }

  inline bool
  IsScalarValueString() const
  {
    return mType == eScalarValueString;
  }

  inline binding_detail::FakeString&
  GetAsScalarValueString()
  {
    MOZ_ASSERT(IsScalarValueString(), "Wrong type!");
    return mValue.mScalarValueString.Value();
  }

  inline const nsAString&
  GetAsScalarValueString() const
  {
    MOZ_ASSERT(IsScalarValueString(), "Wrong type!");
    return mValue.mScalarValueString.Value();
  }

  bool
  ToJSVal(JSContext* cx, JS::Handle<JSObject*> scopeObj, JS::MutableHandle<JS::Value> rval) const;

private:
  inline void
  DestroyRequest()
  {
    MOZ_ASSERT(IsRequest(), "Wrong type!");
    mValue.mRequest.Destroy();
    mType = eUninitialized;
  }

  inline void
  DestroyScalarValueString()
  {
    MOZ_ASSERT(IsScalarValueString(), "Wrong type!");
    mValue.mScalarValueString.Destroy();
    mType = eUninitialized;
  }

  inline void
  Uninit()
  {
    switch (mType) {
      case eUninitialized: {
        break;
      }
      case eRequest: {
        DestroyRequest();
        break;
      }
      case eScalarValueString: {
        DestroyScalarValueString();
        break;
      }
    }
  }
};

class StringOrArrayBufferOrArrayBufferView
{
  friend class StringOrArrayBufferOrArrayBufferViewArgument;
  enum Type
  {
    eUninitialized,
    eString,
    eArrayBuffer,
    eArrayBufferView
  };

  union Value
  {
    UnionMember<binding_detail::FakeString > mString;
    UnionMember<RootedTypedArray<ArrayBuffer> > mArrayBuffer;
    UnionMember<RootedTypedArray<ArrayBufferView> > mArrayBufferView;

  };

  Type mType;
  Value mValue;

  StringOrArrayBufferOrArrayBufferView(const StringOrArrayBufferOrArrayBufferView&) MOZ_DELETE;
  void operator=(const StringOrArrayBufferOrArrayBufferView) MOZ_DELETE;
public:
  explicit inline StringOrArrayBufferOrArrayBufferView()
    : mType(eUninitialized)
  {
  }

  inline ~StringOrArrayBufferOrArrayBufferView()
  {
    Uninit();
  }

  inline binding_detail::FakeString&
  RawSetAsString()
  {
    if (mType == eString) {
      return mValue.mString.Value();
    }
    MOZ_ASSERT(mType == eUninitialized);
    mType = eString;
    return mValue.mString.SetValue();
  }

  inline binding_detail::FakeString&
  SetAsString()
  {
    if (mType == eString) {
      return mValue.mString.Value();
    }
    Uninit();
    mType = eString;
    return mValue.mString.SetValue();
  }

  inline bool
  IsString() const
  {
    return mType == eString;
  }

  inline binding_detail::FakeString&
  GetAsString()
  {
    MOZ_ASSERT(IsString(), "Wrong type!");
    return mValue.mString.Value();
  }

  inline const nsAString&
  GetAsString() const
  {
    MOZ_ASSERT(IsString(), "Wrong type!");
    return mValue.mString.Value();
  }

  inline RootedTypedArray<ArrayBuffer>&
  RawSetAsArrayBuffer(JSContext* cx)
  {
    if (mType == eArrayBuffer) {
      return mValue.mArrayBuffer.Value();
    }
    MOZ_ASSERT(mType == eUninitialized);
    mType = eArrayBuffer;
    return mValue.mArrayBuffer.SetValue(cx);
  }

  inline RootedTypedArray<ArrayBuffer>&
  SetAsArrayBuffer(JSContext* cx)
  {
    if (mType == eArrayBuffer) {
      return mValue.mArrayBuffer.Value();
    }
    Uninit();
    mType = eArrayBuffer;
    return mValue.mArrayBuffer.SetValue(cx);
  }

  inline bool
  IsArrayBuffer() const
  {
    return mType == eArrayBuffer;
  }

  inline RootedTypedArray<ArrayBuffer>&
  GetAsArrayBuffer()
  {
    MOZ_ASSERT(IsArrayBuffer(), "Wrong type!");
    return mValue.mArrayBuffer.Value();
  }

  inline ArrayBuffer const &
  GetAsArrayBuffer() const
  {
    MOZ_ASSERT(IsArrayBuffer(), "Wrong type!");
    return mValue.mArrayBuffer.Value();
  }

  inline RootedTypedArray<ArrayBufferView>&
  RawSetAsArrayBufferView(JSContext* cx)
  {
    if (mType == eArrayBufferView) {
      return mValue.mArrayBufferView.Value();
    }
    MOZ_ASSERT(mType == eUninitialized);
    mType = eArrayBufferView;
    return mValue.mArrayBufferView.SetValue(cx);
  }

  inline RootedTypedArray<ArrayBufferView>&
  SetAsArrayBufferView(JSContext* cx)
  {
    if (mType == eArrayBufferView) {
      return mValue.mArrayBufferView.Value();
    }
    Uninit();
    mType = eArrayBufferView;
    return mValue.mArrayBufferView.SetValue(cx);
  }

  inline bool
  IsArrayBufferView() const
  {
    return mType == eArrayBufferView;
  }

  inline RootedTypedArray<ArrayBufferView>&
  GetAsArrayBufferView()
  {
    MOZ_ASSERT(IsArrayBufferView(), "Wrong type!");
    return mValue.mArrayBufferView.Value();
  }

  inline ArrayBufferView const &
  GetAsArrayBufferView() const
  {
    MOZ_ASSERT(IsArrayBufferView(), "Wrong type!");
    return mValue.mArrayBufferView.Value();
  }

  bool
  ToJSVal(JSContext* cx, JS::Handle<JSObject*> scopeObj, JS::MutableHandle<JS::Value> rval) const;

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

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

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

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

class StringOrBlobOrArrayBufferOrArrayBufferView
{
  friend class StringOrBlobOrArrayBufferOrArrayBufferViewArgument;
  enum Type
  {
    eUninitialized,
    eString,
    eBlob,
    eArrayBuffer,
    eArrayBufferView
  };

  union Value
  {
    UnionMember<binding_detail::FakeString > mString;
    UnionMember<NonNull<mozilla::dom::File> > mBlob;
    UnionMember<RootedTypedArray<ArrayBuffer> > mArrayBuffer;
    UnionMember<RootedTypedArray<ArrayBufferView> > mArrayBufferView;

  };

  Type mType;
  Value mValue;

  StringOrBlobOrArrayBufferOrArrayBufferView(const StringOrBlobOrArrayBufferOrArrayBufferView&) MOZ_DELETE;
  void operator=(const StringOrBlobOrArrayBufferOrArrayBufferView) MOZ_DELETE;
public:
  explicit inline StringOrBlobOrArrayBufferOrArrayBufferView()
    : mType(eUninitialized)
  {
  }

  inline ~StringOrBlobOrArrayBufferOrArrayBufferView()
  {
    Uninit();
  }

  inline binding_detail::FakeString&
  RawSetAsString()
  {
    if (mType == eString) {
      return mValue.mString.Value();
    }
    MOZ_ASSERT(mType == eUninitialized);
    mType = eString;
    return mValue.mString.SetValue();
  }

  inline binding_detail::FakeString&
  SetAsString()
  {
    if (mType == eString) {
      return mValue.mString.Value();
    }
    Uninit();
    mType = eString;
    return mValue.mString.SetValue();
  }

  inline bool
  IsString() const
  {
    return mType == eString;
  }

  inline binding_detail::FakeString&
  GetAsString()
  {
    MOZ_ASSERT(IsString(), "Wrong type!");
    return mValue.mString.Value();
  }

  inline const nsAString&
  GetAsString() const
  {
    MOZ_ASSERT(IsString(), "Wrong type!");
    return mValue.mString.Value();
  }

  inline NonNull<mozilla::dom::File>&
  RawSetAsBlob()
  {
    if (mType == eBlob) {
      return mValue.mBlob.Value();
    }
    MOZ_ASSERT(mType == eUninitialized);
    mType = eBlob;
    return mValue.mBlob.SetValue();
  }

  inline NonNull<mozilla::dom::File>&
  SetAsBlob()
  {
    if (mType == eBlob) {
      return mValue.mBlob.Value();
    }
    Uninit();
    mType = eBlob;
    return mValue.mBlob.SetValue();
  }

  inline bool
  IsBlob() const
  {
    return mType == eBlob;
  }

  inline NonNull<mozilla::dom::File>&
  GetAsBlob()
  {
    MOZ_ASSERT(IsBlob(), "Wrong type!");
    return mValue.mBlob.Value();
  }

  inline mozilla::dom::File&
  GetAsBlob() const
  {
    MOZ_ASSERT(IsBlob(), "Wrong type!");
    return mValue.mBlob.Value();
  }

  inline RootedTypedArray<ArrayBuffer>&
  RawSetAsArrayBuffer(JSContext* cx)
  {
    if (mType == eArrayBuffer) {
      return mValue.mArrayBuffer.Value();
    }
    MOZ_ASSERT(mType == eUninitialized);
    mType = eArrayBuffer;
    return mValue.mArrayBuffer.SetValue(cx);
  }

  inline RootedTypedArray<ArrayBuffer>&
  SetAsArrayBuffer(JSContext* cx)
  {
    if (mType == eArrayBuffer) {
      return mValue.mArrayBuffer.Value();
    }
    Uninit();
    mType = eArrayBuffer;
    return mValue.mArrayBuffer.SetValue(cx);
  }

  inline bool
  IsArrayBuffer() const
  {
    return mType == eArrayBuffer;
  }

  inline RootedTypedArray<ArrayBuffer>&
  GetAsArrayBuffer()
  {
    MOZ_ASSERT(IsArrayBuffer(), "Wrong type!");
    return mValue.mArrayBuffer.Value();
  }

  inline ArrayBuffer const &
  GetAsArrayBuffer() const
  {
    MOZ_ASSERT(IsArrayBuffer(), "Wrong type!");
    return mValue.mArrayBuffer.Value();
  }

  inline RootedTypedArray<ArrayBufferView>&
  RawSetAsArrayBufferView(JSContext* cx)
  {
    if (mType == eArrayBufferView) {
      return mValue.mArrayBufferView.Value();
    }
    MOZ_ASSERT(mType == eUninitialized);
    mType = eArrayBufferView;
    return mValue.mArrayBufferView.SetValue(cx);
  }

  inline RootedTypedArray<ArrayBufferView>&
  SetAsArrayBufferView(JSContext* cx)
  {
    if (mType == eArrayBufferView) {
      return mValue.mArrayBufferView.Value();
    }
    Uninit();
    mType = eArrayBufferView;
    return mValue.mArrayBufferView.SetValue(cx);
  }

  inline bool
  IsArrayBufferView() const
  {
    return mType == eArrayBufferView;
  }

  inline RootedTypedArray<ArrayBufferView>&
  GetAsArrayBufferView()
  {
    MOZ_ASSERT(IsArrayBufferView(), "Wrong type!");
    return mValue.mArrayBufferView.Value();
  }

  inline ArrayBufferView const &
  GetAsArrayBufferView() const
  {
    MOZ_ASSERT(IsArrayBufferView(), "Wrong type!");
    return mValue.mArrayBufferView.Value();
  }

  bool
  ToJSVal(JSContext* cx, JS::Handle<JSObject*> scopeObj, JS::MutableHandle<JS::Value> rval) const;

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

  inline void
  DestroyBlob()
  {
    MOZ_ASSERT(IsBlob(), "Wrong type!");
    mValue.mBlob.Destroy();
    mType = eUninitialized;
  }

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

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

  inline void
  Uninit()
  {
    switch (mType) {
      case eUninitialized: {
        break;
      }
      case eString: {
        DestroyString();
        break;
      }
      case eBlob: {
        DestroyBlob();
        break;
      }
      case eArrayBuffer: {
        DestroyArrayBuffer();
        break;
      }
      case eArrayBufferView: {
        DestroyArrayBufferView();
        break;
      }
    }
  }
};

class StringOrCanvasGradientOrCanvasPattern
{
  friend class StringOrCanvasGradientOrCanvasPatternArgument;
  enum Type
  {
    eUninitialized,
    eString,
    eCanvasGradient,
    eCanvasPattern
  };

  union Value
  {
    UnionMember<binding_detail::FakeString > mString;
    UnionMember<NonNull<mozilla::dom::CanvasGradient> > mCanvasGradient;
    UnionMember<NonNull<mozilla::dom::CanvasPattern> > mCanvasPattern;

  };

  Type mType;
  Value mValue;

  StringOrCanvasGradientOrCanvasPattern(const StringOrCanvasGradientOrCanvasPattern&) MOZ_DELETE;
  void operator=(const StringOrCanvasGradientOrCanvasPattern) MOZ_DELETE;
public:
  explicit inline StringOrCanvasGradientOrCanvasPattern()
    : mType(eUninitialized)
  {
  }

  inline ~StringOrCanvasGradientOrCanvasPattern()
  {
    Uninit();
  }

  inline binding_detail::FakeString&
  RawSetAsString()
  {
    if (mType == eString) {
      return mValue.mString.Value();
    }
    MOZ_ASSERT(mType == eUninitialized);
    mType = eString;
    return mValue.mString.SetValue();
  }

  inline binding_detail::FakeString&
  SetAsString()
  {
    if (mType == eString) {
      return mValue.mString.Value();
    }
    Uninit();
    mType = eString;
    return mValue.mString.SetValue();
  }

  inline bool
  IsString() const
  {
    return mType == eString;
  }

  inline binding_detail::FakeString&
  GetAsString()
  {
    MOZ_ASSERT(IsString(), "Wrong type!");
    return mValue.mString.Value();
  }

  inline const nsAString&
  GetAsString() const
  {
    MOZ_ASSERT(IsString(), "Wrong type!");
    return mValue.mString.Value();
  }

  inline NonNull<mozilla::dom::CanvasGradient>&
  RawSetAsCanvasGradient()
  {
    if (mType == eCanvasGradient) {
      return mValue.mCanvasGradient.Value();
    }
    MOZ_ASSERT(mType == eUninitialized);
    mType = eCanvasGradient;
    return mValue.mCanvasGradient.SetValue();
  }

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

  inline bool
  IsCanvasGradient() const
  {
    return mType == eCanvasGradient;
  }

  inline NonNull<mozilla::dom::CanvasGradient>&
  GetAsCanvasGradient()
  {
    MOZ_ASSERT(IsCanvasGradient(), "Wrong type!");
    return mValue.mCanvasGradient.Value();
  }

  inline mozilla::dom::CanvasGradient&
  GetAsCanvasGradient() const
  {
    MOZ_ASSERT(IsCanvasGradient(), "Wrong type!");
    return mValue.mCanvasGradient.Value();
  }

  inline NonNull<mozilla::dom::CanvasPattern>&
  RawSetAsCanvasPattern()
  {
    if (mType == eCanvasPattern) {
      return mValue.mCanvasPattern.Value();
    }
    MOZ_ASSERT(mType == eUninitialized);
    mType = eCanvasPattern;
    return mValue.mCanvasPattern.SetValue();
  }

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

  inline bool
  IsCanvasPattern() const
  {
    return mType == eCanvasPattern;
  }

  inline NonNull<mozilla::dom::CanvasPattern>&
  GetAsCanvasPattern()
  {
    MOZ_ASSERT(IsCanvasPattern(), "Wrong type!");
    return mValue.mCanvasPattern.Value();
  }

  inline mozilla::dom::CanvasPattern&
  GetAsCanvasPattern() const
  {
    MOZ_ASSERT(IsCanvasPattern(), "Wrong type!");
    return mValue.mCanvasPattern.Value();
  }

  bool
  ToJSVal(JSContext* cx, JS::Handle<JSObject*> scopeObj, JS::MutableHandle<JS::Value> rval) const;

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

  inline void
  DestroyCanvasGradient()
  {
    MOZ_ASSERT(IsCanvasGradient(), "Wrong type!");
    mValue.mCanvasGradient.Destroy();
    mType = eUninitialized;
  }

  inline void
  DestroyCanvasPattern()
  {
    MOZ_ASSERT(IsCanvasPattern(), "Wrong type!");
    mValue.mCanvasPattern.Destroy();
    mType = eUninitialized;
  }

  inline void
  Uninit()
  {
    switch (mType) {
      case eUninitialized: {
        break;
      }
      case eString: {
        DestroyString();
        break;
      }
      case eCanvasGradient: {
        DestroyCanvasGradient();
        break;
      }
      case eCanvasPattern: {
        DestroyCanvasPattern();
        break;
      }
    }
  }
};

class StringOrFileOrDirectory
{
  friend class StringOrFileOrDirectoryArgument;
  enum Type
  {
    eUninitialized,
    eString,
    eFile,
    eDirectory
  };

  union Value
  {
    UnionMember<binding_detail::FakeString > mString;
    UnionMember<NonNull<mozilla::dom::File> > mFile;
    UnionMember<NonNull<mozilla::dom::Directory> > mDirectory;

  };

  Type mType;
  Value mValue;

  StringOrFileOrDirectory(const StringOrFileOrDirectory&) MOZ_DELETE;
  void operator=(const StringOrFileOrDirectory) MOZ_DELETE;
public:
  explicit inline StringOrFileOrDirectory()
    : mType(eUninitialized)
  {
  }

  inline ~StringOrFileOrDirectory()
  {
    Uninit();
  }

  inline binding_detail::FakeString&
  RawSetAsString()
  {
    if (mType == eString) {
      return mValue.mString.Value();
    }
    MOZ_ASSERT(mType == eUninitialized);
    mType = eString;
    return mValue.mString.SetValue();
  }

  inline binding_detail::FakeString&
  SetAsString()
  {
    if (mType == eString) {
      return mValue.mString.Value();
    }
    Uninit();
    mType = eString;
    return mValue.mString.SetValue();
  }

  inline bool
  IsString() const
  {
    return mType == eString;
  }

  inline binding_detail::FakeString&
  GetAsString()
  {
    MOZ_ASSERT(IsString(), "Wrong type!");
    return mValue.mString.Value();
  }

  inline const nsAString&
  GetAsString() const
  {
    MOZ_ASSERT(IsString(), "Wrong type!");
    return mValue.mString.Value();
  }

  inline NonNull<mozilla::dom::File>&
  RawSetAsFile()
  {
    if (mType == eFile) {
      return mValue.mFile.Value();
    }
    MOZ_ASSERT(mType == eUninitialized);
    mType = eFile;
    return mValue.mFile.SetValue();
  }

  inline NonNull<mozilla::dom::File>&
  SetAsFile()
  {
    if (mType == eFile) {
      return mValue.mFile.Value();
    }
    Uninit();
    mType = eFile;
    return mValue.mFile.SetValue();
  }

  inline bool
  IsFile() const
  {
    return mType == eFile;
  }

  inline NonNull<mozilla::dom::File>&
  GetAsFile()
  {
    MOZ_ASSERT(IsFile(), "Wrong type!");
    return mValue.mFile.Value();
  }

  inline mozilla::dom::File&
  GetAsFile() const
  {
    MOZ_ASSERT(IsFile(), "Wrong type!");
    return mValue.mFile.Value();
  }

  inline NonNull<mozilla::dom::Directory>&
  RawSetAsDirectory()
  {
    if (mType == eDirectory) {
      return mValue.mDirectory.Value();
    }
    MOZ_ASSERT(mType == eUninitialized);
    mType = eDirectory;
    return mValue.mDirectory.SetValue();
  }

  inline NonNull<mozilla::dom::Directory>&
  SetAsDirectory()
  {
    if (mType == eDirectory) {
      return mValue.mDirectory.Value();
    }
    Uninit();
    mType = eDirectory;
    return mValue.mDirectory.SetValue();
  }

  inline bool
  IsDirectory() const
  {
    return mType == eDirectory;
  }

  inline NonNull<mozilla::dom::Directory>&
  GetAsDirectory()
  {
    MOZ_ASSERT(IsDirectory(), "Wrong type!");
    return mValue.mDirectory.Value();
  }

  inline mozilla::dom::Directory&
  GetAsDirectory() const
  {
    MOZ_ASSERT(IsDirectory(), "Wrong type!");
    return mValue.mDirectory.Value();
  }

  bool
  ToJSVal(JSContext* cx, JS::Handle<JSObject*> scopeObj, JS::MutableHandle<JS::Value> rval) const;

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

  inline void
  DestroyFile()
  {
    MOZ_ASSERT(IsFile(), "Wrong type!");
    mValue.mFile.Destroy();
    mType = eUninitialized;
  }

  inline void
  DestroyDirectory()
  {
    MOZ_ASSERT(IsDirectory(), "Wrong type!");
    mValue.mDirectory.Destroy();
    mType = eUninitialized;
  }

  inline void
  Uninit()
  {
    switch (mType) {
      case eUninitialized: {
        break;
      }
      case eString: {
        DestroyString();
        break;
      }
      case eFile: {
        DestroyFile();
        break;
      }
      case eDirectory: {
        DestroyDirectory();
        break;
      }
    }
  }
};

class StringOrInstallTriggerData
{
  friend class StringOrInstallTriggerDataArgument;
  enum Type
  {
    eUninitialized,
    eString,
    eInstallTriggerData
  };

  union Value
  {
    UnionMember<binding_detail::FakeString > mString;
    UnionMember<binding_detail::FastInstallTriggerData > mInstallTriggerData;

  };

  Type mType;
  Value mValue;

  StringOrInstallTriggerData(const StringOrInstallTriggerData&) MOZ_DELETE;
  void operator=(const StringOrInstallTriggerData) MOZ_DELETE;
public:
  explicit inline StringOrInstallTriggerData()
    : mType(eUninitialized)
  {
  }

  inline ~StringOrInstallTriggerData()
  {
    Uninit();
  }

  inline binding_detail::FakeString&
  RawSetAsString()
  {
    if (mType == eString) {
      return mValue.mString.Value();
    }
    MOZ_ASSERT(mType == eUninitialized);
    mType = eString;
    return mValue.mString.SetValue();
  }

  inline binding_detail::FakeString&
  SetAsString()
  {
    if (mType == eString) {
      return mValue.mString.Value();
    }
    Uninit();
    mType = eString;
    return mValue.mString.SetValue();
  }

  inline bool
  IsString() const
  {
    return mType == eString;
  }

  inline binding_detail::FakeString&
  GetAsString()
  {
    MOZ_ASSERT(IsString(), "Wrong type!");
    return mValue.mString.Value();
  }

  inline const nsAString&
  GetAsString() const
  {
    MOZ_ASSERT(IsString(), "Wrong type!");
    return mValue.mString.Value();
  }

  inline binding_detail::FastInstallTriggerData&
  RawSetAsInstallTriggerData()
  {
    if (mType == eInstallTriggerData) {
      return mValue.mInstallTriggerData.Value();
    }
    MOZ_ASSERT(mType == eUninitialized);
    mType = eInstallTriggerData;
    return mValue.mInstallTriggerData.SetValue();
  }

  inline binding_detail::FastInstallTriggerData&
  SetAsInstallTriggerData()
  {
    if (mType == eInstallTriggerData) {
      return mValue.mInstallTriggerData.Value();
    }
    Uninit();
    mType = eInstallTriggerData;
    return mValue.mInstallTriggerData.SetValue();
  }

  inline bool
  IsInstallTriggerData() const
  {
    return mType == eInstallTriggerData;
  }

  inline binding_detail::FastInstallTriggerData&
  GetAsInstallTriggerData()
  {
    MOZ_ASSERT(IsInstallTriggerData(), "Wrong type!");
    return mValue.mInstallTriggerData.Value();
  }

  inline const InstallTriggerData&
  GetAsInstallTriggerData() const
  {
    MOZ_ASSERT(IsInstallTriggerData(), "Wrong type!");
    return mValue.mInstallTriggerData.Value();
  }

  bool
  ToJSVal(JSContext* cx, JS::Handle<JSObject*> scopeObj, JS::MutableHandle<JS::Value> rval) const;

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

  inline void
  DestroyInstallTriggerData()
  {
    MOZ_ASSERT(IsInstallTriggerData(), "Wrong type!");
    mValue.mInstallTriggerData.Destroy();
    mType = eUninitialized;
  }

  inline void
  Uninit()
  {
    switch (mType) {
      case eUninitialized: {
        break;
      }
      case eString: {
        DestroyString();
        break;
      }
      case eInstallTriggerData: {
        DestroyInstallTriggerData();
        break;
      }
    }
  }
};

class StringOrUnsignedLong
{
  friend class StringOrUnsignedLongArgument;
  enum Type
  {
    eUninitialized,
    eString,
    eUnsignedLong
  };

  union Value
  {
    UnionMember<binding_detail::FakeString > mString;
    UnionMember<uint32_t > mUnsignedLong;

  };

  Type mType;
  Value mValue;

  StringOrUnsignedLong(const StringOrUnsignedLong&) MOZ_DELETE;
  void operator=(const StringOrUnsignedLong) MOZ_DELETE;
public:
  explicit inline StringOrUnsignedLong()
    : mType(eUninitialized)
  {
  }

  inline ~StringOrUnsignedLong()
  {
    Uninit();
  }

  inline binding_detail::FakeString&
  RawSetAsString()
  {
    if (mType == eString) {
      return mValue.mString.Value();
    }
    MOZ_ASSERT(mType == eUninitialized);
    mType = eString;
    return mValue.mString.SetValue();
  }

  inline binding_detail::FakeString&
  SetAsString()
  {
    if (mType == eString) {
      return mValue.mString.Value();
    }
    Uninit();
    mType = eString;
    return mValue.mString.SetValue();
  }

  inline bool
  IsString() const
  {
    return mType == eString;
  }

  inline binding_detail::FakeString&
  GetAsString()
  {
    MOZ_ASSERT(IsString(), "Wrong type!");
    return mValue.mString.Value();
  }

  inline const nsAString&
  GetAsString() const
  {
    MOZ_ASSERT(IsString(), "Wrong type!");
    return mValue.mString.Value();
  }

  inline uint32_t&
  RawSetAsUnsignedLong()
  {
    if (mType == eUnsignedLong) {
      return mValue.mUnsignedLong.Value();
    }
    MOZ_ASSERT(mType == eUninitialized);
    mType = eUnsignedLong;
    return mValue.mUnsignedLong.SetValue();
  }

  inline uint32_t&
  SetAsUnsignedLong()
  {
    if (mType == eUnsignedLong) {
      return mValue.mUnsignedLong.Value();
    }
    Uninit();
    mType = eUnsignedLong;
    return mValue.mUnsignedLong.SetValue();
  }

  inline bool
  IsUnsignedLong() const
  {
    return mType == eUnsignedLong;
  }

  inline uint32_t&
  GetAsUnsignedLong()
  {
    MOZ_ASSERT(IsUnsignedLong(), "Wrong type!");
    return mValue.mUnsignedLong.Value();
  }

  inline uint32_t
  GetAsUnsignedLong() const
  {
    MOZ_ASSERT(IsUnsignedLong(), "Wrong type!");
    return mValue.mUnsignedLong.Value();
  }

  bool
  ToJSVal(JSContext* cx, JS::Handle<JSObject*> scopeObj, JS::MutableHandle<JS::Value> rval) const;

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

  inline void
  DestroyUnsignedLong()
  {
    MOZ_ASSERT(IsUnsignedLong(), "Wrong type!");
    mValue.mUnsignedLong.Destroy();
    mType = eUninitialized;
  }

  inline void
  Uninit()
  {
    switch (mType) {
      case eUninitialized: {
        break;
      }
      case eString: {
        DestroyString();
        break;
      }
      case eUnsignedLong: {
        DestroyUnsignedLong();
        break;
      }
    }
  }
};

class TelephonyCallOrTelephonyCallGroup
{
  friend class TelephonyCallOrTelephonyCallGroupArgument;
  enum Type
  {
    eUninitialized,
    eTelephonyCall,
    eTelephonyCallGroup
  };

  union Value
  {
    UnionMember<NonNull<mozilla::dom::TelephonyCall> > mTelephonyCall;
    UnionMember<NonNull<mozilla::dom::TelephonyCallGroup> > mTelephonyCallGroup;

  };

  Type mType;
  Value mValue;

  TelephonyCallOrTelephonyCallGroup(const TelephonyCallOrTelephonyCallGroup&) MOZ_DELETE;
  void operator=(const TelephonyCallOrTelephonyCallGroup) MOZ_DELETE;
public:
  explicit inline TelephonyCallOrTelephonyCallGroup()
    : mType(eUninitialized)
  {
  }

  inline ~TelephonyCallOrTelephonyCallGroup()
  {
    Uninit();
  }

  inline NonNull<mozilla::dom::TelephonyCall>&
  RawSetAsTelephonyCall()
  {
    if (mType == eTelephonyCall) {
      return mValue.mTelephonyCall.Value();
    }
    MOZ_ASSERT(mType == eUninitialized);
    mType = eTelephonyCall;
    return mValue.mTelephonyCall.SetValue();
  }

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

  inline bool
  IsTelephonyCall() const
  {
    return mType == eTelephonyCall;
  }

  inline NonNull<mozilla::dom::TelephonyCall>&
  GetAsTelephonyCall()
  {
    MOZ_ASSERT(IsTelephonyCall(), "Wrong type!");
    return mValue.mTelephonyCall.Value();
  }

  inline mozilla::dom::TelephonyCall&
  GetAsTelephonyCall() const
  {
    MOZ_ASSERT(IsTelephonyCall(), "Wrong type!");
    return mValue.mTelephonyCall.Value();
  }

  inline NonNull<mozilla::dom::TelephonyCallGroup>&
  RawSetAsTelephonyCallGroup()
  {
    if (mType == eTelephonyCallGroup) {
      return mValue.mTelephonyCallGroup.Value();
    }
    MOZ_ASSERT(mType == eUninitialized);
    mType = eTelephonyCallGroup;
    return mValue.mTelephonyCallGroup.SetValue();
  }

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

  inline bool
  IsTelephonyCallGroup() const
  {
    return mType == eTelephonyCallGroup;
  }

  inline NonNull<mozilla::dom::TelephonyCallGroup>&
  GetAsTelephonyCallGroup()
  {
    MOZ_ASSERT(IsTelephonyCallGroup(), "Wrong type!");
    return mValue.mTelephonyCallGroup.Value();
  }

  inline mozilla::dom::TelephonyCallGroup&
  GetAsTelephonyCallGroup() const
  {
    MOZ_ASSERT(IsTelephonyCallGroup(), "Wrong type!");
    return mValue.mTelephonyCallGroup.Value();
  }

  bool
  ToJSVal(JSContext* cx, JS::Handle<JSObject*> scopeObj, JS::MutableHandle<JS::Value> rval) const;

private:
  inline void
  DestroyTelephonyCall()
  {
    MOZ_ASSERT(IsTelephonyCall(), "Wrong type!");
    mValue.mTelephonyCall.Destroy();
    mType = eUninitialized;
  }

  inline void
  DestroyTelephonyCallGroup()
  {
    MOZ_ASSERT(IsTelephonyCallGroup(), "Wrong type!");
    mValue.mTelephonyCallGroup.Destroy();
    mType = eUninitialized;
  }

  inline void
  Uninit()
  {
    switch (mType) {
      case eUninitialized: {
        break;
      }
      case eTelephonyCall: {
        DestroyTelephonyCall();
        break;
      }
      case eTelephonyCallGroup: {
        DestroyTelephonyCallGroup();
        break;
      }
    }
  }
};

class TextOrElementOrDocument
{
  friend class TextOrElementOrDocumentArgument;
  enum Type
  {
    eUninitialized,
    eText,
    eElement,
    eDocument
  };

  union Value
  {
    UnionMember<NonNull<mozilla::dom::Text> > mText;
    UnionMember<NonNull<mozilla::dom::Element> > mElement;
    UnionMember<NonNull<nsIDocument> > mDocument;

  };

  Type mType;
  Value mValue;

  TextOrElementOrDocument(const TextOrElementOrDocument&) MOZ_DELETE;
  void operator=(const TextOrElementOrDocument) MOZ_DELETE;
public:
  explicit inline TextOrElementOrDocument()
    : mType(eUninitialized)
  {
  }

  inline ~TextOrElementOrDocument()
  {
    Uninit();
  }

  inline NonNull<mozilla::dom::Text>&
  RawSetAsText()
  {
    if (mType == eText) {
      return mValue.mText.Value();
    }
    MOZ_ASSERT(mType == eUninitialized);
    mType = eText;
    return mValue.mText.SetValue();
  }

  inline NonNull<mozilla::dom::Text>&
  SetAsText()
  {
    if (mType == eText) {
      return mValue.mText.Value();
    }
    Uninit();
    mType = eText;
    return mValue.mText.SetValue();
  }

  inline bool
  IsText() const
  {
    return mType == eText;
  }

  inline NonNull<mozilla::dom::Text>&
  GetAsText()
  {
    MOZ_ASSERT(IsText(), "Wrong type!");
    return mValue.mText.Value();
  }

  inline mozilla::dom::Text&
  GetAsText() const
  {
    MOZ_ASSERT(IsText(), "Wrong type!");
    return mValue.mText.Value();
  }

  inline NonNull<mozilla::dom::Element>&
  RawSetAsElement()
  {
    if (mType == eElement) {
      return mValue.mElement.Value();
    }
    MOZ_ASSERT(mType == eUninitialized);
    mType = eElement;
    return mValue.mElement.SetValue();
  }

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

  inline bool
  IsElement() const
  {
    return mType == eElement;
  }

  inline NonNull<mozilla::dom::Element>&
  GetAsElement()
  {
    MOZ_ASSERT(IsElement(), "Wrong type!");
    return mValue.mElement.Value();
  }

  inline mozilla::dom::Element&
  GetAsElement() const
  {
    MOZ_ASSERT(IsElement(), "Wrong type!");
    return mValue.mElement.Value();
  }

  inline NonNull<nsIDocument>&
  RawSetAsDocument()
  {
    if (mType == eDocument) {
      return mValue.mDocument.Value();
    }
    MOZ_ASSERT(mType == eUninitialized);
    mType = eDocument;
    return mValue.mDocument.SetValue();
  }

  inline NonNull<nsIDocument>&
  SetAsDocument()
  {
    if (mType == eDocument) {
      return mValue.mDocument.Value();
    }
    Uninit();
    mType = eDocument;
    return mValue.mDocument.SetValue();
  }

  inline bool
  IsDocument() const
  {
    return mType == eDocument;
  }

  inline NonNull<nsIDocument>&
  GetAsDocument()
  {
    MOZ_ASSERT(IsDocument(), "Wrong type!");
    return mValue.mDocument.Value();
  }

  inline nsIDocument&
  GetAsDocument() const
  {
    MOZ_ASSERT(IsDocument(), "Wrong type!");
    return mValue.mDocument.Value();
  }

  bool
  ToJSVal(JSContext* cx, JS::Handle<JSObject*> scopeObj, JS::MutableHandle<JS::Value> rval) const;

private:
  inline void
  DestroyText()
  {
    MOZ_ASSERT(IsText(), "Wrong type!");
    mValue.mText.Destroy();
    mType = eUninitialized;
  }

  inline void
  DestroyElement()
  {
    MOZ_ASSERT(IsElement(), "Wrong type!");
    mValue.mElement.Destroy();
    mType = eUninitialized;
  }

  inline void
  DestroyDocument()
  {
    MOZ_ASSERT(IsDocument(), "Wrong type!");
    mValue.mDocument.Destroy();
    mType = eUninitialized;
  }

  inline void
  Uninit()
  {
    switch (mType) {
      case eUninitialized: {
        break;
      }
      case eText: {
        DestroyText();
        break;
      }
      case eElement: {
        DestroyElement();
        break;
      }
      case eDocument: {
        DestroyDocument();
        break;
      }
    }
  }
};

class UnsignedLongOrString
{
  friend class UnsignedLongOrStringArgument;
  enum Type
  {
    eUninitialized,
    eUnsignedLong,
    eString
  };

  union Value
  {
    UnionMember<uint32_t > mUnsignedLong;
    UnionMember<binding_detail::FakeString > mString;

  };

  Type mType;
  Value mValue;

  UnsignedLongOrString(const UnsignedLongOrString&) MOZ_DELETE;
  void operator=(const UnsignedLongOrString) MOZ_DELETE;
public:
  explicit inline UnsignedLongOrString()
    : mType(eUninitialized)
  {
  }

  inline ~UnsignedLongOrString()
  {
    Uninit();
  }

  inline uint32_t&
  RawSetAsUnsignedLong()
  {
    if (mType == eUnsignedLong) {
      return mValue.mUnsignedLong.Value();
    }
    MOZ_ASSERT(mType == eUninitialized);
    mType = eUnsignedLong;
    return mValue.mUnsignedLong.SetValue();
  }

  inline uint32_t&
  SetAsUnsignedLong()
  {
    if (mType == eUnsignedLong) {
      return mValue.mUnsignedLong.Value();
    }
    Uninit();
    mType = eUnsignedLong;
    return mValue.mUnsignedLong.SetValue();
  }

  inline bool
  IsUnsignedLong() const
  {
    return mType == eUnsignedLong;
  }

  inline uint32_t&
  GetAsUnsignedLong()
  {
    MOZ_ASSERT(IsUnsignedLong(), "Wrong type!");
    return mValue.mUnsignedLong.Value();
  }

  inline uint32_t
  GetAsUnsignedLong() const
  {
    MOZ_ASSERT(IsUnsignedLong(), "Wrong type!");
    return mValue.mUnsignedLong.Value();
  }

  inline binding_detail::FakeString&
  RawSetAsString()
  {
    if (mType == eString) {
      return mValue.mString.Value();
    }
    MOZ_ASSERT(mType == eUninitialized);
    mType = eString;
    return mValue.mString.SetValue();
  }

  inline binding_detail::FakeString&
  SetAsString()
  {
    if (mType == eString) {
      return mValue.mString.Value();
    }
    Uninit();
    mType = eString;
    return mValue.mString.SetValue();
  }

  inline bool
  IsString() const
  {
    return mType == eString;
  }

  inline binding_detail::FakeString&
  GetAsString()
  {
    MOZ_ASSERT(IsString(), "Wrong type!");
    return mValue.mString.Value();
  }

  inline const nsAString&
  GetAsString() const
  {
    MOZ_ASSERT(IsString(), "Wrong type!");
    return mValue.mString.Value();
  }

  bool
  ToJSVal(JSContext* cx, JS::Handle<JSObject*> scopeObj, JS::MutableHandle<JS::Value> rval) const;

private:
  inline void
  DestroyUnsignedLong()
  {
    MOZ_ASSERT(IsUnsignedLong(), "Wrong type!");
    mValue.mUnsignedLong.Destroy();
    mType = eUninitialized;
  }

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

  inline void
  Uninit()
  {
    switch (mType) {
      case eUninitialized: {
        break;
      }
      case eUnsignedLong: {
        DestroyUnsignedLong();
        break;
      }
      case eString: {
        DestroyString();
        break;
      }
    }
  }
};

class UnsignedShortOrObject
{
  friend class UnsignedShortOrObjectArgument;
  enum Type
  {
    eUninitialized,
    eUnsignedShort,
    eObject
  };

  union Value
  {
    UnionMember<uint16_t > mUnsignedShort;
    UnionMember<JS::Rooted<JSObject*> > mObject;

  };

  Type mType;
  Value mValue;

  UnsignedShortOrObject(const UnsignedShortOrObject&) MOZ_DELETE;
  void operator=(const UnsignedShortOrObject) MOZ_DELETE;
public:
  explicit inline UnsignedShortOrObject()
    : mType(eUninitialized)
  {
  }

  inline ~UnsignedShortOrObject()
  {
    Uninit();
  }

  inline uint16_t&
  RawSetAsUnsignedShort()
  {
    if (mType == eUnsignedShort) {
      return mValue.mUnsignedShort.Value();
    }
    MOZ_ASSERT(mType == eUninitialized);
    mType = eUnsignedShort;
    return mValue.mUnsignedShort.SetValue();
  }

  inline uint16_t&
  SetAsUnsignedShort()
  {
    if (mType == eUnsignedShort) {
      return mValue.mUnsignedShort.Value();
    }
    MOZ_ASSERT(mType != eObject, "This will not play well with Rooted");
    Uninit();
    mType = eUnsignedShort;
    return mValue.mUnsignedShort.SetValue();
  }

  inline bool
  IsUnsignedShort() const
  {
    return mType == eUnsignedShort;
  }

  inline uint16_t&
  GetAsUnsignedShort()
  {
    MOZ_ASSERT(IsUnsignedShort(), "Wrong type!");
    return mValue.mUnsignedShort.Value();
  }

  inline uint16_t
  GetAsUnsignedShort() const
  {
    MOZ_ASSERT(IsUnsignedShort(), "Wrong type!");
    return mValue.mUnsignedShort.Value();
  }

  inline bool
  IsObject() const
  {
    return mType == eObject;
  }

  inline JS::Rooted<JSObject*>&
  GetAsObject()
  {
    MOZ_ASSERT(IsObject(), "Wrong type!");
    return mValue.mObject.Value();
  }

  inline JSObject*
  GetAsObject() const
  {
    MOZ_ASSERT(IsObject(), "Wrong type!");
    return mValue.mObject.Value();
  }

  bool
  ToJSVal(JSContext* cx, JS::Handle<JSObject*> scopeObj, JS::MutableHandle<JS::Value> rval) const;

private:
  inline void
  DestroyUnsignedShort()
  {
    MOZ_ASSERT(IsUnsignedShort(), "Wrong type!");
    mValue.mUnsignedShort.Destroy();
    mType = eUninitialized;
  }

  inline void
  DestroyObject()
  {
    MOZ_ASSERT(IsObject(), "Wrong type!");
    mValue.mObject.Destroy();
    mType = eUninitialized;
  }

  inline void
  Uninit()
  {
    switch (mType) {
      case eUninitialized: {
        break;
      }
      case eUnsignedShort: {
        DestroyUnsignedShort();
        break;
      }
      case eObject: {
        DestroyObject();
        break;
      }
    }
  }
};

class VideoTrackOrAudioTrackOrTextTrack
{
  friend class VideoTrackOrAudioTrackOrTextTrackArgument;
  enum Type
  {
    eUninitialized,
    eVideoTrack,
    eAudioTrack,
    eTextTrack
  };

  union Value
  {
    UnionMember<NonNull<mozilla::dom::VideoTrack> > mVideoTrack;
    UnionMember<NonNull<mozilla::dom::AudioTrack> > mAudioTrack;
    UnionMember<NonNull<mozilla::dom::TextTrack> > mTextTrack;

  };

  Type mType;
  Value mValue;

  VideoTrackOrAudioTrackOrTextTrack(const VideoTrackOrAudioTrackOrTextTrack&) MOZ_DELETE;
  void operator=(const VideoTrackOrAudioTrackOrTextTrack) MOZ_DELETE;
public:
  explicit inline VideoTrackOrAudioTrackOrTextTrack()
    : mType(eUninitialized)
  {
  }

  inline ~VideoTrackOrAudioTrackOrTextTrack()
  {
    Uninit();
  }

  inline NonNull<mozilla::dom::VideoTrack>&
  RawSetAsVideoTrack()
  {
    if (mType == eVideoTrack) {
      return mValue.mVideoTrack.Value();
    }
    MOZ_ASSERT(mType == eUninitialized);
    mType = eVideoTrack;
    return mValue.mVideoTrack.SetValue();
  }

  inline NonNull<mozilla::dom::VideoTrack>&
  SetAsVideoTrack()
  {
    if (mType == eVideoTrack) {
      return mValue.mVideoTrack.Value();
    }
    Uninit();
    mType = eVideoTrack;
    return mValue.mVideoTrack.SetValue();
  }

  inline bool
  IsVideoTrack() const
  {
    return mType == eVideoTrack;
  }

  inline NonNull<mozilla::dom::VideoTrack>&
  GetAsVideoTrack()
  {
    MOZ_ASSERT(IsVideoTrack(), "Wrong type!");
    return mValue.mVideoTrack.Value();
  }

  inline mozilla::dom::VideoTrack&
  GetAsVideoTrack() const
  {
    MOZ_ASSERT(IsVideoTrack(), "Wrong type!");
    return mValue.mVideoTrack.Value();
  }

  inline NonNull<mozilla::dom::AudioTrack>&
  RawSetAsAudioTrack()
  {
    if (mType == eAudioTrack) {
      return mValue.mAudioTrack.Value();
    }
    MOZ_ASSERT(mType == eUninitialized);
    mType = eAudioTrack;
    return mValue.mAudioTrack.SetValue();
  }

  inline NonNull<mozilla::dom::AudioTrack>&
  SetAsAudioTrack()
  {
    if (mType == eAudioTrack) {
      return mValue.mAudioTrack.Value();
    }
    Uninit();
    mType = eAudioTrack;
    return mValue.mAudioTrack.SetValue();
  }

  inline bool
  IsAudioTrack() const
  {
    return mType == eAudioTrack;
  }

  inline NonNull<mozilla::dom::AudioTrack>&
  GetAsAudioTrack()
  {
    MOZ_ASSERT(IsAudioTrack(), "Wrong type!");
    return mValue.mAudioTrack.Value();
  }

  inline mozilla::dom::AudioTrack&
  GetAsAudioTrack() const
  {
    MOZ_ASSERT(IsAudioTrack(), "Wrong type!");
    return mValue.mAudioTrack.Value();
  }

  inline NonNull<mozilla::dom::TextTrack>&
  RawSetAsTextTrack()
  {
    if (mType == eTextTrack) {
      return mValue.mTextTrack.Value();
    }
    MOZ_ASSERT(mType == eUninitialized);
    mType = eTextTrack;
    return mValue.mTextTrack.SetValue();
  }

  inline NonNull<mozilla::dom::TextTrack>&
  SetAsTextTrack()
  {
    if (mType == eTextTrack) {
      return mValue.mTextTrack.Value();
    }
    Uninit();
    mType = eTextTrack;
    return mValue.mTextTrack.SetValue();
  }

  inline bool
  IsTextTrack() const
  {
    return mType == eTextTrack;
  }

  inline NonNull<mozilla::dom::TextTrack>&
  GetAsTextTrack()
  {
    MOZ_ASSERT(IsTextTrack(), "Wrong type!");
    return mValue.mTextTrack.Value();
  }

  inline mozilla::dom::TextTrack&
  GetAsTextTrack() const
  {
    MOZ_ASSERT(IsTextTrack(), "Wrong type!");
    return mValue.mTextTrack.Value();
  }

  bool
  ToJSVal(JSContext* cx, JS::Handle<JSObject*> scopeObj, JS::MutableHandle<JS::Value> rval) const;

private:
  inline void
  DestroyVideoTrack()
  {
    MOZ_ASSERT(IsVideoTrack(), "Wrong type!");
    mValue.mVideoTrack.Destroy();
    mType = eUninitialized;
  }

  inline void
  DestroyAudioTrack()
  {
    MOZ_ASSERT(IsAudioTrack(), "Wrong type!");
    mValue.mAudioTrack.Destroy();
    mType = eUninitialized;
  }

  inline void
  DestroyTextTrack()
  {
    MOZ_ASSERT(IsTextTrack(), "Wrong type!");
    mValue.mTextTrack.Destroy();
    mType = eUninitialized;
  }

  inline void
  Uninit()
  {
    switch (mType) {
      case eUninitialized: {
        break;
      }
      case eVideoTrack: {
        DestroyVideoTrack();
        break;
      }
      case eAudioTrack: {
        DestroyAudioTrack();
        break;
      }
      case eTextTrack: {
        DestroyTextTrack();
        break;
      }
    }
  }
};

class WindowProxyOrMessagePort
{
  friend class WindowProxyOrMessagePortArgument;
  enum Type
  {
    eUninitialized,
    eWindowProxy,
    eMessagePort
  };

  union Value
  {
    UnionMember<nsIDOMWindow* > mWindowProxy;
    UnionMember<NonNull<mozilla::dom::MessagePortBase> > mMessagePort;

  };

  Type mType;
  Value mValue;

  WindowProxyOrMessagePort(const WindowProxyOrMessagePort&) MOZ_DELETE;
  void operator=(const WindowProxyOrMessagePort) MOZ_DELETE;
public:
  explicit inline WindowProxyOrMessagePort()
    : mType(eUninitialized)
  {
  }

  inline ~WindowProxyOrMessagePort()
  {
    Uninit();
  }

  inline nsIDOMWindow*&
  RawSetAsWindowProxy()
  {
    if (mType == eWindowProxy) {
      return mValue.mWindowProxy.Value();
    }
    MOZ_ASSERT(mType == eUninitialized);
    mType = eWindowProxy;
    return mValue.mWindowProxy.SetValue();
  }

  inline nsIDOMWindow*&
  SetAsWindowProxy()
  {
    if (mType == eWindowProxy) {
      return mValue.mWindowProxy.Value();
    }
    Uninit();
    mType = eWindowProxy;
    return mValue.mWindowProxy.SetValue();
  }

  inline bool
  IsWindowProxy() const
  {
    return mType == eWindowProxy;
  }

  inline nsIDOMWindow*&
  GetAsWindowProxy()
  {
    MOZ_ASSERT(IsWindowProxy(), "Wrong type!");
    return mValue.mWindowProxy.Value();
  }

  inline nsIDOMWindow*
  GetAsWindowProxy() const
  {
    MOZ_ASSERT(IsWindowProxy(), "Wrong type!");
    return mValue.mWindowProxy.Value();
  }

  inline NonNull<mozilla::dom::MessagePortBase>&
  RawSetAsMessagePort()
  {
    if (mType == eMessagePort) {
      return mValue.mMessagePort.Value();
    }
    MOZ_ASSERT(mType == eUninitialized);
    mType = eMessagePort;
    return mValue.mMessagePort.SetValue();
  }

  inline NonNull<mozilla::dom::MessagePortBase>&
  SetAsMessagePort()
  {
    if (mType == eMessagePort) {
      return mValue.mMessagePort.Value();
    }
    Uninit();
    mType = eMessagePort;
    return mValue.mMessagePort.SetValue();
  }

  inline bool
  IsMessagePort() const
  {
    return mType == eMessagePort;
  }

  inline NonNull<mozilla::dom::MessagePortBase>&
  GetAsMessagePort()
  {
    MOZ_ASSERT(IsMessagePort(), "Wrong type!");
    return mValue.mMessagePort.Value();
  }

  inline mozilla::dom::MessagePortBase&
  GetAsMessagePort() const
  {
    MOZ_ASSERT(IsMessagePort(), "Wrong type!");
    return mValue.mMessagePort.Value();
  }

  bool
  ToJSVal(JSContext* cx, JS::Handle<JSObject*> scopeObj, JS::MutableHandle<JS::Value> rval) const;

private:
  inline void
  DestroyWindowProxy()
  {
    MOZ_ASSERT(IsWindowProxy(), "Wrong type!");
    mValue.mWindowProxy.Destroy();
    mType = eUninitialized;
  }

  inline void
  DestroyMessagePort()
  {
    MOZ_ASSERT(IsMessagePort(), "Wrong type!");
    mValue.mMessagePort.Destroy();
    mType = eUninitialized;
  }

  inline void
  Uninit()
  {
    switch (mType) {
      case eUninitialized: {
        break;
      }
      case eWindowProxy: {
        DestroyWindowProxy();
        break;
      }
      case eMessagePort: {
        DestroyMessagePort();
        break;
      }
    }
  }
};

class mozContactOrString
{
  friend class mozContactOrStringArgument;
  enum Type
  {
    eUninitialized,
    emozContact,
    eString
  };

  union Value
  {
    UnionMember<NonNull<mozilla::dom::mozContact> > mmozContact;
    UnionMember<binding_detail::FakeString > mString;

  };

  Type mType;
  Value mValue;

  mozContactOrString(const mozContactOrString&) MOZ_DELETE;
  void operator=(const mozContactOrString) MOZ_DELETE;
public:
  explicit inline mozContactOrString()
    : mType(eUninitialized)
  {
  }

  inline ~mozContactOrString()
  {
    Uninit();
  }

  inline NonNull<mozilla::dom::mozContact>&
  RawSetAsmozContact()
  {
    if (mType == emozContact) {
      return mValue.mmozContact.Value();
    }
    MOZ_ASSERT(mType == eUninitialized);
    mType = emozContact;
    return mValue.mmozContact.SetValue();
  }

  inline NonNull<mozilla::dom::mozContact>&
  SetAsmozContact()
  {
    if (mType == emozContact) {
      return mValue.mmozContact.Value();
    }
    Uninit();
    mType = emozContact;
    return mValue.mmozContact.SetValue();
  }

  inline bool
  IsmozContact() const
  {
    return mType == emozContact;
  }

  inline NonNull<mozilla::dom::mozContact>&
  GetAsmozContact()
  {
    MOZ_ASSERT(IsmozContact(), "Wrong type!");
    return mValue.mmozContact.Value();
  }

  inline mozilla::dom::mozContact&
  GetAsmozContact() const
  {
    MOZ_ASSERT(IsmozContact(), "Wrong type!");
    return mValue.mmozContact.Value();
  }

  inline binding_detail::FakeString&
  RawSetAsString()
  {
    if (mType == eString) {
      return mValue.mString.Value();
    }
    MOZ_ASSERT(mType == eUninitialized);
    mType = eString;
    return mValue.mString.SetValue();
  }

  inline binding_detail::FakeString&
  SetAsString()
  {
    if (mType == eString) {
      return mValue.mString.Value();
    }
    Uninit();
    mType = eString;
    return mValue.mString.SetValue();
  }

  inline bool
  IsString() const
  {
    return mType == eString;
  }

  inline binding_detail::FakeString&
  GetAsString()
  {
    MOZ_ASSERT(IsString(), "Wrong type!");
    return mValue.mString.Value();
  }

  inline const nsAString&
  GetAsString() const
  {
    MOZ_ASSERT(IsString(), "Wrong type!");
    return mValue.mString.Value();
  }

  bool
  ToJSVal(JSContext* cx, JS::Handle<JSObject*> scopeObj, JS::MutableHandle<JS::Value> rval) const;

private:
  inline void
  DestroymozContact()
  {
    MOZ_ASSERT(IsmozContact(), "Wrong type!");
    mValue.mmozContact.Destroy();
    mType = eUninitialized;
  }

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

  inline void
  Uninit()
  {
    switch (mType) {
      case eUninitialized: {
        break;
      }
      case emozContact: {
        DestroymozContact();
        break;
      }
      case eString: {
        DestroyString();
        break;
      }
    }
  }
};

class OwningArrayBufferOrArrayBufferViewOrBlobOrString : public AllOwningUnionBase
{
  friend void ImplCycleCollectionUnlink(OwningArrayBufferOrArrayBufferViewOrBlobOrString& aUnion);
  enum Type
  {
    eUninitialized,
    eArrayBuffer,
    eArrayBufferView,
    eBlob,
    eString
  };

  union Value
  {
    UnionMember<ArrayBuffer > mArrayBuffer;
    UnionMember<ArrayBufferView > mArrayBufferView;
    UnionMember<OwningNonNull<mozilla::dom::File> > mBlob;
    UnionMember<nsString > mString;

  };

  Type mType;
  Value mValue;

  OwningArrayBufferOrArrayBufferViewOrBlobOrString(const OwningArrayBufferOrArrayBufferViewOrBlobOrString&) MOZ_DELETE;
  void operator=(const OwningArrayBufferOrArrayBufferViewOrBlobOrString) MOZ_DELETE;
public:
  explicit inline OwningArrayBufferOrArrayBufferViewOrBlobOrString()
    : mType(eUninitialized)
  {
  }

  inline ~OwningArrayBufferOrArrayBufferViewOrBlobOrString()
  {
    Uninit();
  }

  ArrayBuffer&
  RawSetAsArrayBuffer();

  ArrayBuffer&
  SetAsArrayBuffer();

  bool
  TrySetToArrayBuffer(JSContext* cx, JS::Handle<JS::Value> value, bool& tryNext, bool passedToJSImpl = false);

  inline bool
  IsArrayBuffer() const
  {
    return mType == eArrayBuffer;
  }

  inline ArrayBuffer&
  GetAsArrayBuffer()
  {
    MOZ_ASSERT(IsArrayBuffer(), "Wrong type!");
    return mValue.mArrayBuffer.Value();
  }

  inline ArrayBuffer const &
  GetAsArrayBuffer() const
  {
    MOZ_ASSERT(IsArrayBuffer(), "Wrong type!");
    return mValue.mArrayBuffer.Value();
  }

  ArrayBufferView&
  RawSetAsArrayBufferView();

  ArrayBufferView&
  SetAsArrayBufferView();

  bool
  TrySetToArrayBufferView(JSContext* cx, JS::Handle<JS::Value> value, bool& tryNext, bool passedToJSImpl = false);

  inline bool
  IsArrayBufferView() const
  {
    return mType == eArrayBufferView;
  }

  inline ArrayBufferView&
  GetAsArrayBufferView()
  {
    MOZ_ASSERT(IsArrayBufferView(), "Wrong type!");
    return mValue.mArrayBufferView.Value();
  }

  inline ArrayBufferView const &
  GetAsArrayBufferView() const
  {
    MOZ_ASSERT(IsArrayBufferView(), "Wrong type!");
    return mValue.mArrayBufferView.Value();
  }

  OwningNonNull<mozilla::dom::File>&
  RawSetAsBlob();

  OwningNonNull<mozilla::dom::File>&
  SetAsBlob();

  bool
  TrySetToBlob(JSContext* cx, JS::Handle<JS::Value> value, bool& tryNext, bool passedToJSImpl = false);

  inline bool
  IsBlob() const
  {
    return mType == eBlob;
  }

  inline OwningNonNull<mozilla::dom::File>&
  GetAsBlob()
  {
    MOZ_ASSERT(IsBlob(), "Wrong type!");
    return mValue.mBlob.Value();
  }

  inline OwningNonNull<mozilla::dom::File> const &
  GetAsBlob() const
  {
    MOZ_ASSERT(IsBlob(), "Wrong type!");
    return mValue.mBlob.Value();
  }

  nsString&
  RawSetAsString();

  nsString&
  SetAsString();

  bool
  TrySetToString(JSContext* cx, JS::Handle<JS::Value> value, bool& tryNext, bool passedToJSImpl = false);

  inline void
  SetStringData(const nsString::char_type* aData, nsString::size_type aLength)
  {
    RawSetAsString().Assign(aData, aLength);
  }

  inline bool
  IsString() const
  {
    return mType == eString;
  }

  inline nsString&
  GetAsString()
  {
    MOZ_ASSERT(IsString(), "Wrong type!");
    return mValue.mString.Value();
  }

  inline nsString const &
  GetAsString() const
  {
    MOZ_ASSERT(IsString(), "Wrong type!");
    return mValue.mString.Value();
  }

  bool
  ToJSVal(JSContext* cx, JS::Handle<JSObject*> scopeObj, JS::MutableHandle<JS::Value> rval) const;

  void
  TraceUnion(JSTracer* trc);

private:
  void
  DestroyArrayBuffer();

  void
  DestroyArrayBufferView();

  void
  DestroyBlob();

  void
  DestroyString();

  void
  Uninit();
};

class OwningArrayBufferOrArrayBufferViewOrScalarValueStringOrURLSearchParams : public AllOwningUnionBase
{
  friend void ImplCycleCollectionUnlink(OwningArrayBufferOrArrayBufferViewOrScalarValueStringOrURLSearchParams& aUnion);
  enum Type
  {
    eUninitialized,
    eArrayBuffer,
    eArrayBufferView,
    eScalarValueString,
    eURLSearchParams
  };

  union Value
  {
    UnionMember<ArrayBuffer > mArrayBuffer;
    UnionMember<ArrayBufferView > mArrayBufferView;
    UnionMember<nsString > mScalarValueString;
    UnionMember<OwningNonNull<mozilla::dom::URLSearchParams> > mURLSearchParams;

  };

  Type mType;
  Value mValue;

  OwningArrayBufferOrArrayBufferViewOrScalarValueStringOrURLSearchParams(const OwningArrayBufferOrArrayBufferViewOrScalarValueStringOrURLSearchParams&) MOZ_DELETE;
  void operator=(const OwningArrayBufferOrArrayBufferViewOrScalarValueStringOrURLSearchParams) MOZ_DELETE;
public:
  explicit inline OwningArrayBufferOrArrayBufferViewOrScalarValueStringOrURLSearchParams()
    : mType(eUninitialized)
  {
  }

  inline ~OwningArrayBufferOrArrayBufferViewOrScalarValueStringOrURLSearchParams()
  {
    Uninit();
  }

  ArrayBuffer&
  RawSetAsArrayBuffer();

  ArrayBuffer&
  SetAsArrayBuffer();

  bool
  TrySetToArrayBuffer(JSContext* cx, JS::Handle<JS::Value> value, bool& tryNext, bool passedToJSImpl = false);

  inline bool
  IsArrayBuffer() const
  {
    return mType == eArrayBuffer;
  }

  inline ArrayBuffer&
  GetAsArrayBuffer()
  {
    MOZ_ASSERT(IsArrayBuffer(), "Wrong type!");
    return mValue.mArrayBuffer.Value();
  }

  inline ArrayBuffer const &
  GetAsArrayBuffer() const
  {
    MOZ_ASSERT(IsArrayBuffer(), "Wrong type!");
    return mValue.mArrayBuffer.Value();
  }

  ArrayBufferView&
  RawSetAsArrayBufferView();

  ArrayBufferView&
  SetAsArrayBufferView();

  bool
  TrySetToArrayBufferView(JSContext* cx, JS::Handle<JS::Value> value, bool& tryNext, bool passedToJSImpl = false);

  inline bool
  IsArrayBufferView() const
  {
    return mType == eArrayBufferView;
  }

  inline ArrayBufferView&
  GetAsArrayBufferView()
  {
    MOZ_ASSERT(IsArrayBufferView(), "Wrong type!");
    return mValue.mArrayBufferView.Value();
  }

  inline ArrayBufferView const &
  GetAsArrayBufferView() const
  {
    MOZ_ASSERT(IsArrayBufferView(), "Wrong type!");
    return mValue.mArrayBufferView.Value();
  }

  nsString&
  RawSetAsScalarValueString();

  nsString&
  SetAsScalarValueString();

  bool
  TrySetToScalarValueString(JSContext* cx, JS::Handle<JS::Value> value, bool& tryNext, bool passedToJSImpl = false);

  inline void
  SetStringData(const nsString::char_type* aData, nsString::size_type aLength)
  {
    RawSetAsScalarValueString().Assign(aData, aLength);
  }

  inline bool
  IsScalarValueString() const
  {
    return mType == eScalarValueString;
  }

  inline nsString&
  GetAsScalarValueString()
  {
    MOZ_ASSERT(IsScalarValueString(), "Wrong type!");
    return mValue.mScalarValueString.Value();
  }

  inline nsString const &
  GetAsScalarValueString() const
  {
    MOZ_ASSERT(IsScalarValueString(), "Wrong type!");
    return mValue.mScalarValueString.Value();
  }

  OwningNonNull<mozilla::dom::URLSearchParams>&
  RawSetAsURLSearchParams();

  OwningNonNull<mozilla::dom::URLSearchParams>&
  SetAsURLSearchParams();

  bool
  TrySetToURLSearchParams(JSContext* cx, JS::Handle<JS::Value> value, bool& tryNext, bool passedToJSImpl = false);

  inline bool
  IsURLSearchParams() const
  {
    return mType == eURLSearchParams;
  }

  inline OwningNonNull<mozilla::dom::URLSearchParams>&
  GetAsURLSearchParams()
  {
    MOZ_ASSERT(IsURLSearchParams(), "Wrong type!");
    return mValue.mURLSearchParams.Value();
  }

  inline OwningNonNull<mozilla::dom::URLSearchParams> const &
  GetAsURLSearchParams() const
  {
    MOZ_ASSERT(IsURLSearchParams(), "Wrong type!");
    return mValue.mURLSearchParams.Value();
  }

  bool
  ToJSVal(JSContext* cx, JS::Handle<JSObject*> scopeObj, JS::MutableHandle<JS::Value> rval) const;

  void
  TraceUnion(JSTracer* trc);

private:
  void
  DestroyArrayBuffer();

  void
  DestroyArrayBufferView();

  void
  DestroyScalarValueString();

  void
  DestroyURLSearchParams();

  void
  Uninit();
};

class OwningArrayBufferViewOrArrayBuffer : public AllOwningUnionBase
{
  friend void ImplCycleCollectionUnlink(OwningArrayBufferViewOrArrayBuffer& aUnion);
  enum Type
  {
    eUninitialized,
    eArrayBufferView,
    eArrayBuffer
  };

  union Value
  {
    UnionMember<ArrayBufferView > mArrayBufferView;
    UnionMember<ArrayBuffer > mArrayBuffer;

  };

  Type mType;
  Value mValue;

  OwningArrayBufferViewOrArrayBuffer(const OwningArrayBufferViewOrArrayBuffer&) MOZ_DELETE;
  void operator=(const OwningArrayBufferViewOrArrayBuffer) MOZ_DELETE;
public:
  explicit inline OwningArrayBufferViewOrArrayBuffer()
    : mType(eUninitialized)
  {
  }

  inline ~OwningArrayBufferViewOrArrayBuffer()
  {
    Uninit();
  }

  ArrayBufferView&
  RawSetAsArrayBufferView();

  ArrayBufferView&
  SetAsArrayBufferView();

  bool
  TrySetToArrayBufferView(JSContext* cx, JS::Handle<JS::Value> value, bool& tryNext, bool passedToJSImpl = false);

  inline bool
  IsArrayBufferView() const
  {
    return mType == eArrayBufferView;
  }

  inline ArrayBufferView&
  GetAsArrayBufferView()
  {
    MOZ_ASSERT(IsArrayBufferView(), "Wrong type!");
    return mValue.mArrayBufferView.Value();
  }

  inline ArrayBufferView const &
  GetAsArrayBufferView() const
  {
    MOZ_ASSERT(IsArrayBufferView(), "Wrong type!");
    return mValue.mArrayBufferView.Value();
  }

  ArrayBuffer&
  RawSetAsArrayBuffer();

  ArrayBuffer&
  SetAsArrayBuffer();

  bool
  TrySetToArrayBuffer(JSContext* cx, JS::Handle<JS::Value> value, bool& tryNext, bool passedToJSImpl = false);

  inline bool
  IsArrayBuffer() const
  {
    return mType == eArrayBuffer;
  }

  inline ArrayBuffer&
  GetAsArrayBuffer()
  {
    MOZ_ASSERT(IsArrayBuffer(), "Wrong type!");
    return mValue.mArrayBuffer.Value();
  }

  inline ArrayBuffer const &
  GetAsArrayBuffer() const
  {
    MOZ_ASSERT(IsArrayBuffer(), "Wrong type!");
    return mValue.mArrayBuffer.Value();
  }

  bool
  ToJSVal(JSContext* cx, JS::Handle<JSObject*> scopeObj, JS::MutableHandle<JS::Value> rval) const;

  void
  TraceUnion(JSTracer* trc);

private:
  void
  DestroyArrayBufferView();

  void
  DestroyArrayBuffer();

  void
  Uninit();
};

class OwningArrayBufferViewOrBlobOrStringOrFormData : public AllOwningUnionBase
{
  friend void ImplCycleCollectionUnlink(OwningArrayBufferViewOrBlobOrStringOrFormData& aUnion);
  enum Type
  {
    eUninitialized,
    eArrayBufferView,
    eBlob,
    eString,
    eFormData
  };

  union Value
  {
    UnionMember<ArrayBufferView > mArrayBufferView;
    UnionMember<OwningNonNull<mozilla::dom::File> > mBlob;
    UnionMember<nsString > mString;
    UnionMember<OwningNonNull<nsFormData> > mFormData;

  };

  Type mType;
  Value mValue;

  OwningArrayBufferViewOrBlobOrStringOrFormData(const OwningArrayBufferViewOrBlobOrStringOrFormData&) MOZ_DELETE;
  void operator=(const OwningArrayBufferViewOrBlobOrStringOrFormData) MOZ_DELETE;
public:
  explicit inline OwningArrayBufferViewOrBlobOrStringOrFormData()
    : mType(eUninitialized)
  {
  }

  inline ~OwningArrayBufferViewOrBlobOrStringOrFormData()
  {
    Uninit();
  }

  ArrayBufferView&
  RawSetAsArrayBufferView();

  ArrayBufferView&
  SetAsArrayBufferView();

  bool
  TrySetToArrayBufferView(JSContext* cx, JS::Handle<JS::Value> value, bool& tryNext, bool passedToJSImpl = false);

  inline bool
  IsArrayBufferView() const
  {
    return mType == eArrayBufferView;
  }

  inline ArrayBufferView&
  GetAsArrayBufferView()
  {
    MOZ_ASSERT(IsArrayBufferView(), "Wrong type!");
    return mValue.mArrayBufferView.Value();
  }

  inline ArrayBufferView const &
  GetAsArrayBufferView() const
  {
    MOZ_ASSERT(IsArrayBufferView(), "Wrong type!");
    return mValue.mArrayBufferView.Value();
  }

  OwningNonNull<mozilla::dom::File>&
  RawSetAsBlob();

  OwningNonNull<mozilla::dom::File>&
  SetAsBlob();

  bool
  TrySetToBlob(JSContext* cx, JS::Handle<JS::Value> value, bool& tryNext, bool passedToJSImpl = false);

  inline bool
  IsBlob() const
  {
    return mType == eBlob;
  }

  inline OwningNonNull<mozilla::dom::File>&
  GetAsBlob()
  {
    MOZ_ASSERT(IsBlob(), "Wrong type!");
    return mValue.mBlob.Value();
  }

  inline OwningNonNull<mozilla::dom::File> const &
  GetAsBlob() const
  {
    MOZ_ASSERT(IsBlob(), "Wrong type!");
    return mValue.mBlob.Value();
  }

  nsString&
  RawSetAsString();

  nsString&
  SetAsString();

  bool
  TrySetToString(JSContext* cx, JS::Handle<JS::Value> value, bool& tryNext, bool passedToJSImpl = false);

  inline void
  SetStringData(const nsString::char_type* aData, nsString::size_type aLength)
  {
    RawSetAsString().Assign(aData, aLength);
  }

  inline bool
  IsString() const
  {
    return mType == eString;
  }

  inline nsString&
  GetAsString()
  {
    MOZ_ASSERT(IsString(), "Wrong type!");
    return mValue.mString.Value();
  }

  inline nsString const &
  GetAsString() const
  {
    MOZ_ASSERT(IsString(), "Wrong type!");
    return mValue.mString.Value();
  }

  OwningNonNull<nsFormData>&
  RawSetAsFormData();

  OwningNonNull<nsFormData>&
  SetAsFormData();

  bool
  TrySetToFormData(JSContext* cx, JS::Handle<JS::Value> value, bool& tryNext, bool passedToJSImpl = false);

  inline bool
  IsFormData() const
  {
    return mType == eFormData;
  }

  inline OwningNonNull<nsFormData>&
  GetAsFormData()
  {
    MOZ_ASSERT(IsFormData(), "Wrong type!");
    return mValue.mFormData.Value();
  }

  inline OwningNonNull<nsFormData> const &
  GetAsFormData() const
  {
    MOZ_ASSERT(IsFormData(), "Wrong type!");
    return mValue.mFormData.Value();
  }

  bool
  ToJSVal(JSContext* cx, JS::Handle<JSObject*> scopeObj, JS::MutableHandle<JS::Value> rval) const;

  void
  TraceUnion(JSTracer* trc);

private:
  void
  DestroyArrayBufferView();

  void
  DestroyBlob();

  void
  DestroyString();

  void
  DestroyFormData();

  void
  Uninit();
};

class OwningBooleanOrMediaTrackConstraints : public AllOwningUnionBase
{
  friend void ImplCycleCollectionUnlink(OwningBooleanOrMediaTrackConstraints& aUnion);
  enum Type
  {
    eUninitialized,
    eBoolean,
    eMediaTrackConstraints
  };

  union Value
  {
    UnionMember<bool > mBoolean;
    UnionMember<MediaTrackConstraints > mMediaTrackConstraints;

  };

  Type mType;
  Value mValue;

public:
  explicit inline OwningBooleanOrMediaTrackConstraints()
    : mType(eUninitialized)
  {
  }

  explicit inline OwningBooleanOrMediaTrackConstraints(const OwningBooleanOrMediaTrackConstraints& aOther)
    : mType(eUninitialized)
  {
    *this = aOther;
  }

  inline ~OwningBooleanOrMediaTrackConstraints()
  {
    Uninit();
  }

  bool&
  RawSetAsBoolean();

  bool&
  SetAsBoolean();

  bool
  TrySetToBoolean(JSContext* cx, JS::Handle<JS::Value> value, bool& tryNext, bool passedToJSImpl = false);

  inline bool
  IsBoolean() const
  {
    return mType == eBoolean;
  }

  inline bool&
  GetAsBoolean()
  {
    MOZ_ASSERT(IsBoolean(), "Wrong type!");
    return mValue.mBoolean.Value();
  }

  inline bool const &
  GetAsBoolean() const
  {
    MOZ_ASSERT(IsBoolean(), "Wrong type!");
    return mValue.mBoolean.Value();
  }

  MediaTrackConstraints&
  RawSetAsMediaTrackConstraints();

  MediaTrackConstraints&
  SetAsMediaTrackConstraints();

  bool
  TrySetToMediaTrackConstraints(JSContext* cx, JS::Handle<JS::Value> value, bool& tryNext, bool passedToJSImpl = false);

  inline bool
  IsMediaTrackConstraints() const
  {
    return mType == eMediaTrackConstraints;
  }

  inline MediaTrackConstraints&
  GetAsMediaTrackConstraints()
  {
    MOZ_ASSERT(IsMediaTrackConstraints(), "Wrong type!");
    return mValue.mMediaTrackConstraints.Value();
  }

  inline MediaTrackConstraints const &
  GetAsMediaTrackConstraints() const
  {
    MOZ_ASSERT(IsMediaTrackConstraints(), "Wrong type!");
    return mValue.mMediaTrackConstraints.Value();
  }

  bool
  ToJSVal(JSContext* cx, JS::Handle<JSObject*> scopeObj, JS::MutableHandle<JS::Value> rval) const;

  void
  TraceUnion(JSTracer* trc);

  void
  operator=(const OwningBooleanOrMediaTrackConstraints& aOther);

private:
  void
  DestroyBoolean();

  void
  DestroyMediaTrackConstraints();

  void
  Uninit();
};

class OwningEventOrString : public AllOwningUnionBase
{
  friend void ImplCycleCollectionUnlink(OwningEventOrString& aUnion);
  enum Type
  {
    eUninitialized,
    eEvent,
    eString
  };

  union Value
  {
    UnionMember<OwningNonNull<mozilla::dom::Event> > mEvent;
    UnionMember<nsString > mString;

  };

  Type mType;
  Value mValue;

public:
  explicit inline OwningEventOrString()
    : mType(eUninitialized)
  {
  }

  explicit inline OwningEventOrString(const OwningEventOrString& aOther)
    : mType(eUninitialized)
  {
    *this = aOther;
  }

  inline ~OwningEventOrString()
  {
    Uninit();
  }

  OwningNonNull<mozilla::dom::Event>&
  RawSetAsEvent();

  OwningNonNull<mozilla::dom::Event>&
  SetAsEvent();

  bool
  TrySetToEvent(JSContext* cx, JS::Handle<JS::Value> value, bool& tryNext, bool passedToJSImpl = false);

  inline bool
  IsEvent() const
  {
    return mType == eEvent;
  }

  inline OwningNonNull<mozilla::dom::Event>&
  GetAsEvent()
  {
    MOZ_ASSERT(IsEvent(), "Wrong type!");
    return mValue.mEvent.Value();
  }

  inline OwningNonNull<mozilla::dom::Event> const &
  GetAsEvent() const
  {
    MOZ_ASSERT(IsEvent(), "Wrong type!");
    return mValue.mEvent.Value();
  }

  nsString&
  RawSetAsString();

  nsString&
  SetAsString();

  bool
  TrySetToString(JSContext* cx, JS::Handle<JS::Value> value, bool& tryNext, bool passedToJSImpl = false);

  inline void
  SetStringData(const nsString::char_type* aData, nsString::size_type aLength)
  {
    RawSetAsString().Assign(aData, aLength);
  }

  inline bool
  IsString() const
  {
    return mType == eString;
  }

  inline nsString&
  GetAsString()
  {
    MOZ_ASSERT(IsString(), "Wrong type!");
    return mValue.mString.Value();
  }

  inline nsString const &
  GetAsString() const
  {
    MOZ_ASSERT(IsString(), "Wrong type!");
    return mValue.mString.Value();
  }

  bool
  ToJSVal(JSContext* cx, JS::Handle<JSObject*> scopeObj, JS::MutableHandle<JS::Value> rval) const;

  void
  TraceUnion(JSTracer* trc);

  void
  operator=(const OwningEventOrString& aOther);

private:
  void
  DestroyEvent();

  void
  DestroyString();

  void
  Uninit();
};

class OwningExternalOrWindowProxy : public AllOwningUnionBase
{
  friend void ImplCycleCollectionUnlink(OwningExternalOrWindowProxy& aUnion);
  enum Type
  {
    eUninitialized,
    eExternal,
    eWindowProxy
  };

  union Value
  {
    UnionMember<OwningNonNull<mozilla::dom::External> > mExternal;
    UnionMember<nsRefPtr<nsIDOMWindow> > mWindowProxy;

  };

  Type mType;
  Value mValue;

public:
  explicit inline OwningExternalOrWindowProxy()
    : mType(eUninitialized)
  {
  }

  explicit inline OwningExternalOrWindowProxy(const OwningExternalOrWindowProxy& aOther)
    : mType(eUninitialized)
  {
    *this = aOther;
  }

  inline ~OwningExternalOrWindowProxy()
  {
    Uninit();
  }

  OwningNonNull<mozilla::dom::External>&
  RawSetAsExternal();

  OwningNonNull<mozilla::dom::External>&
  SetAsExternal();

  bool
  TrySetToExternal(JSContext* cx, JS::Handle<JS::Value> value, bool& tryNext, bool passedToJSImpl = false);

  inline bool
  IsExternal() const
  {
    return mType == eExternal;
  }

  inline OwningNonNull<mozilla::dom::External>&
  GetAsExternal()
  {
    MOZ_ASSERT(IsExternal(), "Wrong type!");
    return mValue.mExternal.Value();
  }

  inline OwningNonNull<mozilla::dom::External> const &
  GetAsExternal() const
  {
    MOZ_ASSERT(IsExternal(), "Wrong type!");
    return mValue.mExternal.Value();
  }

  nsRefPtr<nsIDOMWindow>&
  RawSetAsWindowProxy();

  nsRefPtr<nsIDOMWindow>&
  SetAsWindowProxy();

  bool
  TrySetToWindowProxy(JSContext* cx, JS::Handle<JS::Value> value, bool& tryNext, bool passedToJSImpl = false);

  inline bool
  IsWindowProxy() const
  {
    return mType == eWindowProxy;
  }

  inline nsRefPtr<nsIDOMWindow>&
  GetAsWindowProxy()
  {
    MOZ_ASSERT(IsWindowProxy(), "Wrong type!");
    return mValue.mWindowProxy.Value();
  }

  inline nsRefPtr<nsIDOMWindow> const &
  GetAsWindowProxy() const
  {
    MOZ_ASSERT(IsWindowProxy(), "Wrong type!");
    return mValue.mWindowProxy.Value();
  }

  bool
  ToJSVal(JSContext* cx, JS::Handle<JSObject*> scopeObj, JS::MutableHandle<JS::Value> rval) const;

  void
  TraceUnion(JSTracer* trc);

  void
  operator=(const OwningExternalOrWindowProxy& aOther);

private:
  void
  DestroyExternal();

  void
  DestroyWindowProxy();

  void
  Uninit();
};

class OwningHTMLElementOrLong : public AllOwningUnionBase
{
  friend void ImplCycleCollectionUnlink(OwningHTMLElementOrLong& aUnion);
  enum Type
  {
    eUninitialized,
    eHTMLElement,
    eLong
  };

  union Value
  {
    UnionMember<OwningNonNull<nsGenericHTMLElement> > mHTMLElement;
    UnionMember<int32_t > mLong;

  };

  Type mType;
  Value mValue;

public:
  explicit inline OwningHTMLElementOrLong()
    : mType(eUninitialized)
  {
  }

  explicit inline OwningHTMLElementOrLong(const OwningHTMLElementOrLong& aOther)
    : mType(eUninitialized)
  {
    *this = aOther;
  }

  inline ~OwningHTMLElementOrLong()
  {
    Uninit();
  }

  OwningNonNull<nsGenericHTMLElement>&
  RawSetAsHTMLElement();

  OwningNonNull<nsGenericHTMLElement>&
  SetAsHTMLElement();

  bool
  TrySetToHTMLElement(JSContext* cx, JS::Handle<JS::Value> value, bool& tryNext, bool passedToJSImpl = false);

  inline bool
  IsHTMLElement() const
  {
    return mType == eHTMLElement;
  }

  inline OwningNonNull<nsGenericHTMLElement>&
  GetAsHTMLElement()
  {
    MOZ_ASSERT(IsHTMLElement(), "Wrong type!");
    return mValue.mHTMLElement.Value();
  }

  inline OwningNonNull<nsGenericHTMLElement> const &
  GetAsHTMLElement() const
  {
    MOZ_ASSERT(IsHTMLElement(), "Wrong type!");
    return mValue.mHTMLElement.Value();
  }

  int32_t&
  RawSetAsLong();

  int32_t&
  SetAsLong();

  bool
  TrySetToLong(JSContext* cx, JS::Handle<JS::Value> value, bool& tryNext, bool passedToJSImpl = false);

  inline bool
  IsLong() const
  {
    return mType == eLong;
  }

  inline int32_t&
  GetAsLong()
  {
    MOZ_ASSERT(IsLong(), "Wrong type!");
    return mValue.mLong.Value();
  }

  inline int32_t const &
  GetAsLong() const
  {
    MOZ_ASSERT(IsLong(), "Wrong type!");
    return mValue.mLong.Value();
  }

  bool
  ToJSVal(JSContext* cx, JS::Handle<JSObject*> scopeObj, JS::MutableHandle<JS::Value> rval) const;

  void
  TraceUnion(JSTracer* trc);

  void
  operator=(const OwningHTMLElementOrLong& aOther);

private:
  void
  DestroyHTMLElement();

  void
  DestroyLong();

  void
  Uninit();
};

class OwningHTMLImageElementOrHTMLCanvasElementOrHTMLVideoElement : public AllOwningUnionBase
{
  friend void ImplCycleCollectionUnlink(OwningHTMLImageElementOrHTMLCanvasElementOrHTMLVideoElement& aUnion);
  enum Type
  {
    eUninitialized,
    eHTMLImageElement,
    eHTMLCanvasElement,
    eHTMLVideoElement
  };

  union Value
  {
    UnionMember<OwningNonNull<mozilla::dom::HTMLImageElement> > mHTMLImageElement;
    UnionMember<OwningNonNull<mozilla::dom::HTMLCanvasElement> > mHTMLCanvasElement;
    UnionMember<OwningNonNull<mozilla::dom::HTMLVideoElement> > mHTMLVideoElement;

  };

  Type mType;
  Value mValue;

public:
  explicit inline OwningHTMLImageElementOrHTMLCanvasElementOrHTMLVideoElement()
    : mType(eUninitialized)
  {
  }

  explicit inline OwningHTMLImageElementOrHTMLCanvasElementOrHTMLVideoElement(const OwningHTMLImageElementOrHTMLCanvasElementOrHTMLVideoElement& aOther)
    : mType(eUninitialized)
  {
    *this = aOther;
  }

  inline ~OwningHTMLImageElementOrHTMLCanvasElementOrHTMLVideoElement()
  {
    Uninit();
  }

  OwningNonNull<mozilla::dom::HTMLImageElement>&
  RawSetAsHTMLImageElement();

  OwningNonNull<mozilla::dom::HTMLImageElement>&
  SetAsHTMLImageElement();

  bool
  TrySetToHTMLImageElement(JSContext* cx, JS::Handle<JS::Value> value, bool& tryNext, bool passedToJSImpl = false);

  inline bool
  IsHTMLImageElement() const
  {
    return mType == eHTMLImageElement;
  }

  inline OwningNonNull<mozilla::dom::HTMLImageElement>&
  GetAsHTMLImageElement()
  {
    MOZ_ASSERT(IsHTMLImageElement(), "Wrong type!");
    return mValue.mHTMLImageElement.Value();
  }

  inline OwningNonNull<mozilla::dom::HTMLImageElement> const &
  GetAsHTMLImageElement() const
  {
    MOZ_ASSERT(IsHTMLImageElement(), "Wrong type!");
    return mValue.mHTMLImageElement.Value();
  }

  OwningNonNull<mozilla::dom::HTMLCanvasElement>&
  RawSetAsHTMLCanvasElement();

  OwningNonNull<mozilla::dom::HTMLCanvasElement>&
  SetAsHTMLCanvasElement();

  bool
  TrySetToHTMLCanvasElement(JSContext* cx, JS::Handle<JS::Value> value, bool& tryNext, bool passedToJSImpl = false);

  inline bool
  IsHTMLCanvasElement() const
  {
    return mType == eHTMLCanvasElement;
  }

  inline OwningNonNull<mozilla::dom::HTMLCanvasElement>&
  GetAsHTMLCanvasElement()
  {
    MOZ_ASSERT(IsHTMLCanvasElement(), "Wrong type!");
    return mValue.mHTMLCanvasElement.Value();
  }

  inline OwningNonNull<mozilla::dom::HTMLCanvasElement> const &
  GetAsHTMLCanvasElement() const
  {
    MOZ_ASSERT(IsHTMLCanvasElement(), "Wrong type!");
    return mValue.mHTMLCanvasElement.Value();
  }

  OwningNonNull<mozilla::dom::HTMLVideoElement>&
  RawSetAsHTMLVideoElement();

  OwningNonNull<mozilla::dom::HTMLVideoElement>&
  SetAsHTMLVideoElement();

  bool
  TrySetToHTMLVideoElement(JSContext* cx, JS::Handle<JS::Value> value, bool& tryNext, bool passedToJSImpl = false);

  inline bool
  IsHTMLVideoElement() const
  {
    return mType == eHTMLVideoElement;
  }

  inline OwningNonNull<mozilla::dom::HTMLVideoElement>&
  GetAsHTMLVideoElement()
  {
    MOZ_ASSERT(IsHTMLVideoElement(), "Wrong type!");
    return mValue.mHTMLVideoElement.Value();
  }

  inline OwningNonNull<mozilla::dom::HTMLVideoElement> const &
  GetAsHTMLVideoElement() const
  {
    MOZ_ASSERT(IsHTMLVideoElement(), "Wrong type!");
    return mValue.mHTMLVideoElement.Value();
  }

  bool
  ToJSVal(JSContext* cx, JS::Handle<JSObject*> scopeObj, JS::MutableHandle<JS::Value> rval) const;

  void
  TraceUnion(JSTracer* trc);

  void
  operator=(const OwningHTMLImageElementOrHTMLCanvasElementOrHTMLVideoElement& aOther);

private:
  void
  DestroyHTMLImageElement();

  void
  DestroyHTMLCanvasElement();

  void
  DestroyHTMLVideoElement();

  void
  Uninit();
};

class OwningHTMLOptionElementOrHTMLOptGroupElement : public AllOwningUnionBase
{
  friend void ImplCycleCollectionUnlink(OwningHTMLOptionElementOrHTMLOptGroupElement& aUnion);
  enum Type
  {
    eUninitialized,
    eHTMLOptionElement,
    eHTMLOptGroupElement
  };

  union Value
  {
    UnionMember<OwningNonNull<mozilla::dom::HTMLOptionElement> > mHTMLOptionElement;
    UnionMember<OwningNonNull<mozilla::dom::HTMLOptGroupElement> > mHTMLOptGroupElement;

  };

  Type mType;
  Value mValue;

public:
  explicit inline OwningHTMLOptionElementOrHTMLOptGroupElement()
    : mType(eUninitialized)
  {
  }

  explicit inline OwningHTMLOptionElementOrHTMLOptGroupElement(const OwningHTMLOptionElementOrHTMLOptGroupElement& aOther)
    : mType(eUninitialized)
  {
    *this = aOther;
  }

  inline ~OwningHTMLOptionElementOrHTMLOptGroupElement()
  {
    Uninit();
  }

  OwningNonNull<mozilla::dom::HTMLOptionElement>&
  RawSetAsHTMLOptionElement();

  OwningNonNull<mozilla::dom::HTMLOptionElement>&
  SetAsHTMLOptionElement();

  bool
  TrySetToHTMLOptionElement(JSContext* cx, JS::Handle<JS::Value> value, bool& tryNext, bool passedToJSImpl = false);

  inline bool
  IsHTMLOptionElement() const
  {
    return mType == eHTMLOptionElement;
  }

  inline OwningNonNull<mozilla::dom::HTMLOptionElement>&
  GetAsHTMLOptionElement()
  {
    MOZ_ASSERT(IsHTMLOptionElement(), "Wrong type!");
    return mValue.mHTMLOptionElement.Value();
  }

  inline OwningNonNull<mozilla::dom::HTMLOptionElement> const &
  GetAsHTMLOptionElement() const
  {
    MOZ_ASSERT(IsHTMLOptionElement(), "Wrong type!");
    return mValue.mHTMLOptionElement.Value();
  }

  OwningNonNull<mozilla::dom::HTMLOptGroupElement>&
  RawSetAsHTMLOptGroupElement();

  OwningNonNull<mozilla::dom::HTMLOptGroupElement>&
  SetAsHTMLOptGroupElement();

  bool
  TrySetToHTMLOptGroupElement(JSContext* cx, JS::Handle<JS::Value> value, bool& tryNext, bool passedToJSImpl = false);

  inline bool
  IsHTMLOptGroupElement() const
  {
    return mType == eHTMLOptGroupElement;
  }

  inline OwningNonNull<mozilla::dom::HTMLOptGroupElement>&
  GetAsHTMLOptGroupElement()
  {
    MOZ_ASSERT(IsHTMLOptGroupElement(), "Wrong type!");
    return mValue.mHTMLOptGroupElement.Value();
  }

  inline OwningNonNull<mozilla::dom::HTMLOptGroupElement> const &
  GetAsHTMLOptGroupElement() const
  {
    MOZ_ASSERT(IsHTMLOptGroupElement(), "Wrong type!");
    return mValue.mHTMLOptGroupElement.Value();
  }

  bool
  ToJSVal(JSContext* cx, JS::Handle<JSObject*> scopeObj, JS::MutableHandle<JS::Value> rval) const;

  void
  TraceUnion(JSTracer* trc);

  void
  operator=(const OwningHTMLOptionElementOrHTMLOptGroupElement& aOther);

private:
  void
  DestroyHTMLOptionElement();

  void
  DestroyHTMLOptGroupElement();

  void
  Uninit();
};

class OwningHeadersOrByteStringSequenceSequenceOrByteStringMozMap : public AllOwningUnionBase
{
  friend void ImplCycleCollectionUnlink(OwningHeadersOrByteStringSequenceSequenceOrByteStringMozMap& aUnion);
  enum Type
  {
    eUninitialized,
    eHeaders,
    eByteStringSequenceSequence,
    eByteStringMozMap
  };

  union Value
  {
    UnionMember<OwningNonNull<mozilla::dom::Headers> > mHeaders;
    UnionMember<Sequence<Sequence<nsCString>> > mByteStringSequenceSequence;
    UnionMember<MozMap<nsCString> > mByteStringMozMap;

  };

  Type mType;
  Value mValue;

  OwningHeadersOrByteStringSequenceSequenceOrByteStringMozMap(const OwningHeadersOrByteStringSequenceSequenceOrByteStringMozMap&) MOZ_DELETE;
  void operator=(const OwningHeadersOrByteStringSequenceSequenceOrByteStringMozMap) MOZ_DELETE;
public:
  explicit inline OwningHeadersOrByteStringSequenceSequenceOrByteStringMozMap()
    : mType(eUninitialized)
  {
  }

  inline ~OwningHeadersOrByteStringSequenceSequenceOrByteStringMozMap()
  {
    Uninit();
  }

  OwningNonNull<mozilla::dom::Headers>&
  RawSetAsHeaders();

  OwningNonNull<mozilla::dom::Headers>&
  SetAsHeaders();

  bool
  TrySetToHeaders(JSContext* cx, JS::Handle<JS::Value> value, bool& tryNext, bool passedToJSImpl = false);

  inline bool
  IsHeaders() const
  {
    return mType == eHeaders;
  }

  inline OwningNonNull<mozilla::dom::Headers>&
  GetAsHeaders()
  {
    MOZ_ASSERT(IsHeaders(), "Wrong type!");
    return mValue.mHeaders.Value();
  }

  inline OwningNonNull<mozilla::dom::Headers> const &
  GetAsHeaders() const
  {
    MOZ_ASSERT(IsHeaders(), "Wrong type!");
    return mValue.mHeaders.Value();
  }

  Sequence<Sequence<nsCString>>&
  RawSetAsByteStringSequenceSequence();

  Sequence<Sequence<nsCString>>&
  SetAsByteStringSequenceSequence();

  bool
  TrySetToByteStringSequenceSequence(JSContext* cx, JS::Handle<JS::Value> value, bool& tryNext, bool passedToJSImpl = false);

  inline bool
  IsByteStringSequenceSequence() const
  {
    return mType == eByteStringSequenceSequence;
  }

  inline Sequence<Sequence<nsCString>>&
  GetAsByteStringSequenceSequence()
  {
    MOZ_ASSERT(IsByteStringSequenceSequence(), "Wrong type!");
    return mValue.mByteStringSequenceSequence.Value();
  }

  inline Sequence<Sequence<nsCString>> const &
  GetAsByteStringSequenceSequence() const
  {
    MOZ_ASSERT(IsByteStringSequenceSequence(), "Wrong type!");
    return mValue.mByteStringSequenceSequence.Value();
  }

  MozMap<nsCString>&
  RawSetAsByteStringMozMap();

  MozMap<nsCString>&
  SetAsByteStringMozMap();

  bool
  TrySetToByteStringMozMap(JSContext* cx, JS::Handle<JS::Value> value, bool& tryNext, bool passedToJSImpl = false);

  inline bool
  IsByteStringMozMap() const
  {
    return mType == eByteStringMozMap;
  }

  inline MozMap<nsCString>&
  GetAsByteStringMozMap()
  {
    MOZ_ASSERT(IsByteStringMozMap(), "Wrong type!");
    return mValue.mByteStringMozMap.Value();
  }

  inline MozMap<nsCString> const &
  GetAsByteStringMozMap() const
  {
    MOZ_ASSERT(IsByteStringMozMap(), "Wrong type!");
    return mValue.mByteStringMozMap.Value();
  }

  bool
  ToJSVal(JSContext* cx, JS::Handle<JSObject*> scopeObj, JS::MutableHandle<JS::Value> rval) const;

  void
  TraceUnion(JSTracer* trc);

private:
  void
  DestroyHeaders();

  void
  DestroyByteStringSequenceSequence();

  void
  DestroyByteStringMozMap();

  void
  Uninit();
};

class OwningIDBObjectStoreOrIDBIndex : public AllOwningUnionBase
{
  friend void ImplCycleCollectionUnlink(OwningIDBObjectStoreOrIDBIndex& aUnion);
  enum Type
  {
    eUninitialized,
    eIDBObjectStore,
    eIDBIndex
  };

  union Value
  {
    UnionMember<OwningNonNull<mozilla::dom::indexedDB::IDBObjectStore> > mIDBObjectStore;
    UnionMember<OwningNonNull<mozilla::dom::indexedDB::IDBIndex> > mIDBIndex;

  };

  Type mType;
  Value mValue;

public:
  explicit inline OwningIDBObjectStoreOrIDBIndex()
    : mType(eUninitialized)
  {
  }

  explicit inline OwningIDBObjectStoreOrIDBIndex(const OwningIDBObjectStoreOrIDBIndex& aOther)
    : mType(eUninitialized)
  {
    *this = aOther;
  }

  inline ~OwningIDBObjectStoreOrIDBIndex()
  {
    Uninit();
  }

  OwningNonNull<mozilla::dom::indexedDB::IDBObjectStore>&
  RawSetAsIDBObjectStore();

  OwningNonNull<mozilla::dom::indexedDB::IDBObjectStore>&
  SetAsIDBObjectStore();

  bool
  TrySetToIDBObjectStore(JSContext* cx, JS::Handle<JS::Value> value, bool& tryNext, bool passedToJSImpl = false);

  inline bool
  IsIDBObjectStore() const
  {
    return mType == eIDBObjectStore;
  }

  inline OwningNonNull<mozilla::dom::indexedDB::IDBObjectStore>&
  GetAsIDBObjectStore()
  {
    MOZ_ASSERT(IsIDBObjectStore(), "Wrong type!");
    return mValue.mIDBObjectStore.Value();
  }

  inline OwningNonNull<mozilla::dom::indexedDB::IDBObjectStore> const &
  GetAsIDBObjectStore() const
  {
    MOZ_ASSERT(IsIDBObjectStore(), "Wrong type!");
    return mValue.mIDBObjectStore.Value();
  }

  OwningNonNull<mozilla::dom::indexedDB::IDBIndex>&
  RawSetAsIDBIndex();

  OwningNonNull<mozilla::dom::indexedDB::IDBIndex>&
  SetAsIDBIndex();

  bool
  TrySetToIDBIndex(JSContext* cx, JS::Handle<JS::Value> value, bool& tryNext, bool passedToJSImpl = false);

  inline bool
  IsIDBIndex() const
  {
    return mType == eIDBIndex;
  }

  inline OwningNonNull<mozilla::dom::indexedDB::IDBIndex>&
  GetAsIDBIndex()
  {
    MOZ_ASSERT(IsIDBIndex(), "Wrong type!");
    return mValue.mIDBIndex.Value();
  }

  inline OwningNonNull<mozilla::dom::indexedDB::IDBIndex> const &
  GetAsIDBIndex() const
  {
    MOZ_ASSERT(IsIDBIndex(), "Wrong type!");
    return mValue.mIDBIndex.Value();
  }

  bool
  ToJSVal(JSContext* cx, JS::Handle<JSObject*> scopeObj, JS::MutableHandle<JS::Value> rval) const;

  void
  TraceUnion(JSTracer* trc);

  void
  operator=(const OwningIDBObjectStoreOrIDBIndex& aOther);

private:
  void
  DestroyIDBObjectStore();

  void
  DestroyIDBIndex();

  void
  Uninit();
};

class OwningIDBObjectStoreOrIDBIndexOrIDBCursor : public AllOwningUnionBase
{
  friend void ImplCycleCollectionUnlink(OwningIDBObjectStoreOrIDBIndexOrIDBCursor& aUnion);
  enum Type
  {
    eUninitialized,
    eIDBObjectStore,
    eIDBIndex,
    eIDBCursor
  };

  union Value
  {
    UnionMember<OwningNonNull<mozilla::dom::indexedDB::IDBObjectStore> > mIDBObjectStore;
    UnionMember<OwningNonNull<mozilla::dom::indexedDB::IDBIndex> > mIDBIndex;
    UnionMember<OwningNonNull<mozilla::dom::indexedDB::IDBCursor> > mIDBCursor;

  };

  Type mType;
  Value mValue;

public:
  explicit inline OwningIDBObjectStoreOrIDBIndexOrIDBCursor()
    : mType(eUninitialized)
  {
  }

  explicit inline OwningIDBObjectStoreOrIDBIndexOrIDBCursor(const OwningIDBObjectStoreOrIDBIndexOrIDBCursor& aOther)
    : mType(eUninitialized)
  {
    *this = aOther;
  }

  inline ~OwningIDBObjectStoreOrIDBIndexOrIDBCursor()
  {
    Uninit();
  }

  OwningNonNull<mozilla::dom::indexedDB::IDBObjectStore>&
  RawSetAsIDBObjectStore();

  OwningNonNull<mozilla::dom::indexedDB::IDBObjectStore>&
  SetAsIDBObjectStore();

  bool
  TrySetToIDBObjectStore(JSContext* cx, JS::Handle<JS::Value> value, bool& tryNext, bool passedToJSImpl = false);

  inline bool
  IsIDBObjectStore() const
  {
    return mType == eIDBObjectStore;
  }

  inline OwningNonNull<mozilla::dom::indexedDB::IDBObjectStore>&
  GetAsIDBObjectStore()
  {
    MOZ_ASSERT(IsIDBObjectStore(), "Wrong type!");
    return mValue.mIDBObjectStore.Value();
  }

  inline OwningNonNull<mozilla::dom::indexedDB::IDBObjectStore> const &
  GetAsIDBObjectStore() const
  {
    MOZ_ASSERT(IsIDBObjectStore(), "Wrong type!");
    return mValue.mIDBObjectStore.Value();
  }

  OwningNonNull<mozilla::dom::indexedDB::IDBIndex>&
  RawSetAsIDBIndex();

  OwningNonNull<mozilla::dom::indexedDB::IDBIndex>&
  SetAsIDBIndex();

  bool
  TrySetToIDBIndex(JSContext* cx, JS::Handle<JS::Value> value, bool& tryNext, bool passedToJSImpl = false);

  inline bool
  IsIDBIndex() const
  {
    return mType == eIDBIndex;
  }

  inline OwningNonNull<mozilla::dom::indexedDB::IDBIndex>&
  GetAsIDBIndex()
  {
    MOZ_ASSERT(IsIDBIndex(), "Wrong type!");
    return mValue.mIDBIndex.Value();
  }

  inline OwningNonNull<mozilla::dom::indexedDB::IDBIndex> const &
  GetAsIDBIndex() const
  {
    MOZ_ASSERT(IsIDBIndex(), "Wrong type!");
    return mValue.mIDBIndex.Value();
  }

  OwningNonNull<mozilla::dom::indexedDB::IDBCursor>&
  RawSetAsIDBCursor();

  OwningNonNull<mozilla::dom::indexedDB::IDBCursor>&
  SetAsIDBCursor();

  bool
  TrySetToIDBCursor(JSContext* cx, JS::Handle<JS::Value> value, bool& tryNext, bool passedToJSImpl = false);

  inline bool
  IsIDBCursor() const
  {
    return mType == eIDBCursor;
  }

  inline OwningNonNull<mozilla::dom::indexedDB::IDBCursor>&
  GetAsIDBCursor()
  {
    MOZ_ASSERT(IsIDBCursor(), "Wrong type!");
    return mValue.mIDBCursor.Value();
  }

  inline OwningNonNull<mozilla::dom::indexedDB::IDBCursor> const &
  GetAsIDBCursor() const
  {
    MOZ_ASSERT(IsIDBCursor(), "Wrong type!");
    return mValue.mIDBCursor.Value();
  }

  bool
  ToJSVal(JSContext* cx, JS::Handle<JSObject*> scopeObj, JS::MutableHandle<JS::Value> rval) const;

  void
  TraceUnion(JSTracer* trc);

  void
  operator=(const OwningIDBObjectStoreOrIDBIndexOrIDBCursor& aOther);

private:
  void
  DestroyIDBObjectStore();

  void
  DestroyIDBIndex();

  void
  DestroyIDBCursor();

  void
  Uninit();
};

class OwningLongOrAutoKeyword : public AllOwningUnionBase
{
  friend void ImplCycleCollectionUnlink(OwningLongOrAutoKeyword& aUnion);
  enum Type
  {
    eUninitialized,
    eLong,
    eAutoKeyword
  };

  union Value
  {
    UnionMember<int32_t > mLong;
    UnionMember<AutoKeyword > mAutoKeyword;

  };

  Type mType;
  Value mValue;

public:
  explicit inline OwningLongOrAutoKeyword()
    : mType(eUninitialized)
  {
  }

  explicit inline OwningLongOrAutoKeyword(const OwningLongOrAutoKeyword& aOther)
    : mType(eUninitialized)
  {
    *this = aOther;
  }

  inline ~OwningLongOrAutoKeyword()
  {
    Uninit();
  }

  int32_t&
  RawSetAsLong();

  int32_t&
  SetAsLong();

  bool
  TrySetToLong(JSContext* cx, JS::Handle<JS::Value> value, bool& tryNext, bool passedToJSImpl = false);

  inline bool
  IsLong() const
  {
    return mType == eLong;
  }

  inline int32_t&
  GetAsLong()
  {
    MOZ_ASSERT(IsLong(), "Wrong type!");
    return mValue.mLong.Value();
  }

  inline int32_t const &
  GetAsLong() const
  {
    MOZ_ASSERT(IsLong(), "Wrong type!");
    return mValue.mLong.Value();
  }

  AutoKeyword&
  RawSetAsAutoKeyword();

  AutoKeyword&
  SetAsAutoKeyword();

  bool
  TrySetToAutoKeyword(JSContext* cx, JS::Handle<JS::Value> value, bool& tryNext, bool passedToJSImpl = false);

  inline bool
  IsAutoKeyword() const
  {
    return mType == eAutoKeyword;
  }

  inline AutoKeyword&
  GetAsAutoKeyword()
  {
    MOZ_ASSERT(IsAutoKeyword(), "Wrong type!");
    return mValue.mAutoKeyword.Value();
  }

  inline AutoKeyword const &
  GetAsAutoKeyword() const
  {
    MOZ_ASSERT(IsAutoKeyword(), "Wrong type!");
    return mValue.mAutoKeyword.Value();
  }

  bool
  ToJSVal(JSContext* cx, JS::Handle<JSObject*> scopeObj, JS::MutableHandle<JS::Value> rval) const;

  void
  TraceUnion(JSTracer* trc);

  void
  operator=(const OwningLongOrAutoKeyword& aOther);

private:
  void
  DestroyLong();

  void
  DestroyAutoKeyword();

  void
  Uninit();
};

class OwningLongOrMozSmsMessageOrMozMmsMessage : public AllOwningUnionBase
{
  friend void ImplCycleCollectionUnlink(OwningLongOrMozSmsMessageOrMozMmsMessage& aUnion);
  enum Type
  {
    eUninitialized,
    eLong,
    eMozSmsMessage,
    eMozMmsMessage
  };

  union Value
  {
    UnionMember<int32_t > mLong;
    UnionMember<nsRefPtr<nsIDOMMozSmsMessage> > mMozSmsMessage;
    UnionMember<nsRefPtr<nsIDOMMozMmsMessage> > mMozMmsMessage;

  };

  Type mType;
  Value mValue;

public:
  explicit inline OwningLongOrMozSmsMessageOrMozMmsMessage()
    : mType(eUninitialized)
  {
  }

  explicit inline OwningLongOrMozSmsMessageOrMozMmsMessage(const OwningLongOrMozSmsMessageOrMozMmsMessage& aOther)
    : mType(eUninitialized)
  {
    *this = aOther;
  }

  inline ~OwningLongOrMozSmsMessageOrMozMmsMessage()
  {
    Uninit();
  }

  int32_t&
  RawSetAsLong();

  int32_t&
  SetAsLong();

  bool
  TrySetToLong(JSContext* cx, JS::Handle<JS::Value> value, bool& tryNext, bool passedToJSImpl = false);

  inline bool
  IsLong() const
  {
    return mType == eLong;
  }

  inline int32_t&
  GetAsLong()
  {
    MOZ_ASSERT(IsLong(), "Wrong type!");
    return mValue.mLong.Value();
  }

  inline int32_t const &
  GetAsLong() const
  {
    MOZ_ASSERT(IsLong(), "Wrong type!");
    return mValue.mLong.Value();
  }

  nsRefPtr<nsIDOMMozSmsMessage>&
  RawSetAsMozSmsMessage();

  nsRefPtr<nsIDOMMozSmsMessage>&
  SetAsMozSmsMessage();

  bool
  TrySetToMozSmsMessage(JSContext* cx, JS::Handle<JS::Value> value, bool& tryNext, bool passedToJSImpl = false);

  inline bool
  IsMozSmsMessage() const
  {
    return mType == eMozSmsMessage;
  }

  inline nsRefPtr<nsIDOMMozSmsMessage>&
  GetAsMozSmsMessage()
  {
    MOZ_ASSERT(IsMozSmsMessage(), "Wrong type!");
    return mValue.mMozSmsMessage.Value();
  }

  inline nsRefPtr<nsIDOMMozSmsMessage> const &
  GetAsMozSmsMessage() const
  {
    MOZ_ASSERT(IsMozSmsMessage(), "Wrong type!");
    return mValue.mMozSmsMessage.Value();
  }

  nsRefPtr<nsIDOMMozMmsMessage>&
  RawSetAsMozMmsMessage();

  nsRefPtr<nsIDOMMozMmsMessage>&
  SetAsMozMmsMessage();

  bool
  TrySetToMozMmsMessage(JSContext* cx, JS::Handle<JS::Value> value, bool& tryNext, bool passedToJSImpl = false);

  inline bool
  IsMozMmsMessage() const
  {
    return mType == eMozMmsMessage;
  }

  inline nsRefPtr<nsIDOMMozMmsMessage>&
  GetAsMozMmsMessage()
  {
    MOZ_ASSERT(IsMozMmsMessage(), "Wrong type!");
    return mValue.mMozMmsMessage.Value();
  }

  inline nsRefPtr<nsIDOMMozMmsMessage> const &
  GetAsMozMmsMessage() const
  {
    MOZ_ASSERT(IsMozMmsMessage(), "Wrong type!");
    return mValue.mMozMmsMessage.Value();
  }

  bool
  ToJSVal(JSContext* cx, JS::Handle<JSObject*> scopeObj, JS::MutableHandle<JS::Value> rval) const;

  void
  TraceUnion(JSTracer* trc);

  void
  operator=(const OwningLongOrMozSmsMessageOrMozMmsMessage& aOther);

private:
  void
  DestroyLong();

  void
  DestroyMozSmsMessage();

  void
  DestroyMozMmsMessage();

  void
  Uninit();
};

class OwningMozSmsMessageOrMozMmsMessage : public AllOwningUnionBase
{
  friend void ImplCycleCollectionUnlink(OwningMozSmsMessageOrMozMmsMessage& aUnion);
  enum Type
  {
    eUninitialized,
    eMozSmsMessage,
    eMozMmsMessage
  };

  union Value
  {
    UnionMember<nsRefPtr<nsIDOMMozSmsMessage> > mMozSmsMessage;
    UnionMember<nsRefPtr<nsIDOMMozMmsMessage> > mMozMmsMessage;

  };

  Type mType;
  Value mValue;

public:
  explicit inline OwningMozSmsMessageOrMozMmsMessage()
    : mType(eUninitialized)
  {
  }

  explicit inline OwningMozSmsMessageOrMozMmsMessage(const OwningMozSmsMessageOrMozMmsMessage& aOther)
    : mType(eUninitialized)
  {
    *this = aOther;
  }

  inline ~OwningMozSmsMessageOrMozMmsMessage()
  {
    Uninit();
  }

  nsRefPtr<nsIDOMMozSmsMessage>&
  RawSetAsMozSmsMessage();

  nsRefPtr<nsIDOMMozSmsMessage>&
  SetAsMozSmsMessage();

  bool
  TrySetToMozSmsMessage(JSContext* cx, JS::Handle<JS::Value> value, bool& tryNext, bool passedToJSImpl = false);

  inline bool
  IsMozSmsMessage() const
  {
    return mType == eMozSmsMessage;
  }

  inline nsRefPtr<nsIDOMMozSmsMessage>&
  GetAsMozSmsMessage()
  {
    MOZ_ASSERT(IsMozSmsMessage(), "Wrong type!");
    return mValue.mMozSmsMessage.Value();
  }

  inline nsRefPtr<nsIDOMMozSmsMessage> const &
  GetAsMozSmsMessage() const
  {
    MOZ_ASSERT(IsMozSmsMessage(), "Wrong type!");
    return mValue.mMozSmsMessage.Value();
  }

  nsRefPtr<nsIDOMMozMmsMessage>&
  RawSetAsMozMmsMessage();

  nsRefPtr<nsIDOMMozMmsMessage>&
  SetAsMozMmsMessage();

  bool
  TrySetToMozMmsMessage(JSContext* cx, JS::Handle<JS::Value> value, bool& tryNext, bool passedToJSImpl = false);

  inline bool
  IsMozMmsMessage() const
  {
    return mType == eMozMmsMessage;
  }

  inline nsRefPtr<nsIDOMMozMmsMessage>&
  GetAsMozMmsMessage()
  {
    MOZ_ASSERT(IsMozMmsMessage(), "Wrong type!");
    return mValue.mMozMmsMessage.Value();
  }

  inline nsRefPtr<nsIDOMMozMmsMessage> const &
  GetAsMozMmsMessage() const
  {
    MOZ_ASSERT(IsMozMmsMessage(), "Wrong type!");
    return mValue.mMozMmsMessage.Value();
  }

  bool
  ToJSVal(JSContext* cx, JS::Handle<JSObject*> scopeObj, JS::MutableHandle<JS::Value> rval) const;

  void
  TraceUnion(JSTracer* trc);

  void
  operator=(const OwningMozSmsMessageOrMozMmsMessage& aOther);

private:
  void
  DestroyMozSmsMessage();

  void
  DestroyMozMmsMessage();

  void
  Uninit();
};

class OwningNetworkStatsDataOrPowerStatsData : public AllOwningUnionBase
{
  friend void ImplCycleCollectionUnlink(OwningNetworkStatsDataOrPowerStatsData& aUnion);
  enum Type
  {
    eUninitialized,
    eNetworkStatsData,
    ePowerStatsData
  };

  union Value
  {
    UnionMember<OwningNonNull<mozilla::dom::NetworkStatsData> > mNetworkStatsData;
    UnionMember<OwningNonNull<mozilla::dom::PowerStatsData> > mPowerStatsData;

  };

  Type mType;
  Value mValue;

public:
  explicit inline OwningNetworkStatsDataOrPowerStatsData()
    : mType(eUninitialized)
  {
  }

  explicit inline OwningNetworkStatsDataOrPowerStatsData(const OwningNetworkStatsDataOrPowerStatsData& aOther)
    : mType(eUninitialized)
  {
    *this = aOther;
  }

  inline ~OwningNetworkStatsDataOrPowerStatsData()
  {
    Uninit();
  }

  OwningNonNull<mozilla::dom::NetworkStatsData>&
  RawSetAsNetworkStatsData();

  OwningNonNull<mozilla::dom::NetworkStatsData>&
  SetAsNetworkStatsData();

  bool
  TrySetToNetworkStatsData(JSContext* cx, JS::Handle<JS::Value> value, bool& tryNext, bool passedToJSImpl = false);

  inline bool
  IsNetworkStatsData() const
  {
    return mType == eNetworkStatsData;
  }

  inline OwningNonNull<mozilla::dom::NetworkStatsData>&
  GetAsNetworkStatsData()
  {
    MOZ_ASSERT(IsNetworkStatsData(), "Wrong type!");
    return mValue.mNetworkStatsData.Value();
  }

  inline OwningNonNull<mozilla::dom::NetworkStatsData> const &
  GetAsNetworkStatsData() const
  {
    MOZ_ASSERT(IsNetworkStatsData(), "Wrong type!");
    return mValue.mNetworkStatsData.Value();
  }

  OwningNonNull<mozilla::dom::PowerStatsData>&
  RawSetAsPowerStatsData();

  OwningNonNull<mozilla::dom::PowerStatsData>&
  SetAsPowerStatsData();

  bool
  TrySetToPowerStatsData(JSContext* cx, JS::Handle<JS::Value> value, bool& tryNext, bool passedToJSImpl = false);

  inline bool
  IsPowerStatsData() const
  {
    return mType == ePowerStatsData;
  }

  inline OwningNonNull<mozilla::dom::PowerStatsData>&
  GetAsPowerStatsData()
  {
    MOZ_ASSERT(IsPowerStatsData(), "Wrong type!");
    return mValue.mPowerStatsData.Value();
  }

  inline OwningNonNull<mozilla::dom::PowerStatsData> const &
  GetAsPowerStatsData() const
  {
    MOZ_ASSERT(IsPowerStatsData(), "Wrong type!");
    return mValue.mPowerStatsData.Value();
  }

  bool
  ToJSVal(JSContext* cx, JS::Handle<JSObject*> scopeObj, JS::MutableHandle<JS::Value> rval) const;

  void
  TraceUnion(JSTracer* trc);

  void
  operator=(const OwningNetworkStatsDataOrPowerStatsData& aOther);

private:
  void
  DestroyNetworkStatsData();

  void
  DestroyPowerStatsData();

  void
  Uninit();
};

class OwningNodeOrHTMLCollection : public AllOwningUnionBase
{
  friend void ImplCycleCollectionUnlink(OwningNodeOrHTMLCollection& aUnion);
  enum Type
  {
    eUninitialized,
    eNode,
    eHTMLCollection
  };

  union Value
  {
    UnionMember<OwningNonNull<nsINode> > mNode;
    UnionMember<OwningNonNull<nsIHTMLCollection> > mHTMLCollection;

  };

  Type mType;
  Value mValue;

public:
  explicit inline OwningNodeOrHTMLCollection()
    : mType(eUninitialized)
  {
  }

  explicit inline OwningNodeOrHTMLCollection(const OwningNodeOrHTMLCollection& aOther)
    : mType(eUninitialized)
  {
    *this = aOther;
  }

  inline ~OwningNodeOrHTMLCollection()
  {
    Uninit();
  }

  OwningNonNull<nsINode>&
  RawSetAsNode();

  OwningNonNull<nsINode>&
  SetAsNode();

  bool
  TrySetToNode(JSContext* cx, JS::Handle<JS::Value> value, bool& tryNext, bool passedToJSImpl = false);

  inline bool
  IsNode() const
  {
    return mType == eNode;
  }

  inline OwningNonNull<nsINode>&
  GetAsNode()
  {
    MOZ_ASSERT(IsNode(), "Wrong type!");
    return mValue.mNode.Value();
  }

  inline OwningNonNull<nsINode> const &
  GetAsNode() const
  {
    MOZ_ASSERT(IsNode(), "Wrong type!");
    return mValue.mNode.Value();
  }

  OwningNonNull<nsIHTMLCollection>&
  RawSetAsHTMLCollection();

  OwningNonNull<nsIHTMLCollection>&
  SetAsHTMLCollection();

  bool
  TrySetToHTMLCollection(JSContext* cx, JS::Handle<JS::Value> value, bool& tryNext, bool passedToJSImpl = false);

  inline bool
  IsHTMLCollection() const
  {
    return mType == eHTMLCollection;
  }

  inline OwningNonNull<nsIHTMLCollection>&
  GetAsHTMLCollection()
  {
    MOZ_ASSERT(IsHTMLCollection(), "Wrong type!");
    return mValue.mHTMLCollection.Value();
  }

  inline OwningNonNull<nsIHTMLCollection> const &
  GetAsHTMLCollection() const
  {
    MOZ_ASSERT(IsHTMLCollection(), "Wrong type!");
    return mValue.mHTMLCollection.Value();
  }

  bool
  ToJSVal(JSContext* cx, JS::Handle<JSObject*> scopeObj, JS::MutableHandle<JS::Value> rval) const;

  void
  TraceUnion(JSTracer* trc);

  void
  operator=(const OwningNodeOrHTMLCollection& aOther);

private:
  void
  DestroyNode();

  void
  DestroyHTMLCollection();

  void
  Uninit();
};

class OwningObjectOrString : public AllOwningUnionBase
{
  friend void ImplCycleCollectionUnlink(OwningObjectOrString& aUnion);
  enum Type
  {
    eUninitialized,
    eObject,
    eString
  };

  union Value
  {
    UnionMember<JSObject* > mObject;
    UnionMember<nsString > mString;

  };

  Type mType;
  Value mValue;

  OwningObjectOrString(const OwningObjectOrString&) MOZ_DELETE;
  void operator=(const OwningObjectOrString) MOZ_DELETE;
public:
  explicit inline OwningObjectOrString()
    : mType(eUninitialized)
  {
  }

  inline ~OwningObjectOrString()
  {
    Uninit();
  }

  JSObject*&
  RawSetAsObject();

  JSObject*&
  SetAsObject();

  inline bool
  SetToObject(JSContext* cx, JSObject* obj, bool passedToJSImpl = false)
  {
    MOZ_ASSERT(mType == eUninitialized);
    mValue.mObject.SetValue(obj);
    mType = eObject;
    if (passedToJSImpl && !CallerSubsumes(obj)) {
      ThrowErrorMessage(cx, MSG_PERMISSION_DENIED_TO_PASS_ARG, "%s");
      return false;
    }
    return true;
  }

  inline bool
  IsObject() const
  {
    return mType == eObject;
  }

  inline JSObject*&
  GetAsObject()
  {
    MOZ_ASSERT(IsObject(), "Wrong type!");
    return mValue.mObject.Value();
  }

  inline JSObject* const &
  GetAsObject() const
  {
    MOZ_ASSERT(IsObject(), "Wrong type!");
    return mValue.mObject.Value();
  }

  nsString&
  RawSetAsString();

  nsString&
  SetAsString();

  bool
  TrySetToString(JSContext* cx, JS::Handle<JS::Value> value, bool& tryNext, bool passedToJSImpl = false);

  inline void
  SetStringData(const nsString::char_type* aData, nsString::size_type aLength)
  {
    RawSetAsString().Assign(aData, aLength);
  }

  inline bool
  IsString() const
  {
    return mType == eString;
  }

  inline nsString&
  GetAsString()
  {
    MOZ_ASSERT(IsString(), "Wrong type!");
    return mValue.mString.Value();
  }

  inline nsString const &
  GetAsString() const
  {
    MOZ_ASSERT(IsString(), "Wrong type!");
    return mValue.mString.Value();
  }

  bool
  ToJSVal(JSContext* cx, JS::Handle<JSObject*> scopeObj, JS::MutableHandle<JS::Value> rval) const;

  void
  TraceUnion(JSTracer* trc);

private:
  void
  DestroyObject();

  void
  DestroyString();

  void
  Uninit();
};

class OwningRadioNodeListOrElement : public AllOwningUnionBase
{
  friend void ImplCycleCollectionUnlink(OwningRadioNodeListOrElement& aUnion);
  enum Type
  {
    eUninitialized,
    eRadioNodeList,
    eElement
  };

  union Value
  {
    UnionMember<OwningNonNull<mozilla::dom::RadioNodeList> > mRadioNodeList;
    UnionMember<OwningNonNull<mozilla::dom::Element> > mElement;

  };

  Type mType;
  Value mValue;

public:
  explicit inline OwningRadioNodeListOrElement()
    : mType(eUninitialized)
  {
  }

  explicit inline OwningRadioNodeListOrElement(const OwningRadioNodeListOrElement& aOther)
    : mType(eUninitialized)
  {
    *this = aOther;
  }

  inline ~OwningRadioNodeListOrElement()
  {
    Uninit();
  }

  OwningNonNull<mozilla::dom::RadioNodeList>&
  RawSetAsRadioNodeList();

  OwningNonNull<mozilla::dom::RadioNodeList>&
  SetAsRadioNodeList();

  bool
  TrySetToRadioNodeList(JSContext* cx, JS::Handle<JS::Value> value, bool& tryNext, bool passedToJSImpl = false);

  inline bool
  IsRadioNodeList() const
  {
    return mType == eRadioNodeList;
  }

  inline OwningNonNull<mozilla::dom::RadioNodeList>&
  GetAsRadioNodeList()
  {
    MOZ_ASSERT(IsRadioNodeList(), "Wrong type!");
    return mValue.mRadioNodeList.Value();
  }

  inline OwningNonNull<mozilla::dom::RadioNodeList> const &
  GetAsRadioNodeList() const
  {
    MOZ_ASSERT(IsRadioNodeList(), "Wrong type!");
    return mValue.mRadioNodeList.Value();
  }

  OwningNonNull<mozilla::dom::Element>&
  RawSetAsElement();

  OwningNonNull<mozilla::dom::Element>&
  SetAsElement();

  bool
  TrySetToElement(JSContext* cx, JS::Handle<JS::Value> value, bool& tryNext, bool passedToJSImpl = false);

  inline bool
  IsElement() const
  {
    return mType == eElement;
  }

  inline OwningNonNull<mozilla::dom::Element>&
  GetAsElement()
  {
    MOZ_ASSERT(IsElement(), "Wrong type!");
    return mValue.mElement.Value();
  }

  inline OwningNonNull<mozilla::dom::Element> const &
  GetAsElement() const
  {
    MOZ_ASSERT(IsElement(), "Wrong type!");
    return mValue.mElement.Value();
  }

  bool
  ToJSVal(JSContext* cx, JS::Handle<JSObject*> scopeObj, JS::MutableHandle<JS::Value> rval) const;

  void
  TraceUnion(JSTracer* trc);

  void
  operator=(const OwningRadioNodeListOrElement& aOther);

private:
  void
  DestroyRadioNodeList();

  void
  DestroyElement();

  void
  Uninit();
};

class OwningRequestOrScalarValueString : public AllOwningUnionBase
{
  friend void ImplCycleCollectionUnlink(OwningRequestOrScalarValueString& aUnion);
  enum Type
  {
    eUninitialized,
    eRequest,
    eScalarValueString
  };

  union Value
  {
    UnionMember<OwningNonNull<mozilla::dom::Request> > mRequest;
    UnionMember<nsString > mScalarValueString;

  };

  Type mType;
  Value mValue;

public:
  explicit inline OwningRequestOrScalarValueString()
    : mType(eUninitialized)
  {
  }

  explicit inline OwningRequestOrScalarValueString(const OwningRequestOrScalarValueString& aOther)
    : mType(eUninitialized)
  {
    *this = aOther;
  }

  inline ~OwningRequestOrScalarValueString()
  {
    Uninit();
  }

  OwningNonNull<mozilla::dom::Request>&
  RawSetAsRequest();

  OwningNonNull<mozilla::dom::Request>&
  SetAsRequest();

  bool
  TrySetToRequest(JSContext* cx, JS::Handle<JS::Value> value, bool& tryNext, bool passedToJSImpl = false);

  inline bool
  IsRequest() const
  {
    return mType == eRequest;
  }

  inline OwningNonNull<mozilla::dom::Request>&
  GetAsRequest()
  {
    MOZ_ASSERT(IsRequest(), "Wrong type!");
    return mValue.mRequest.Value();
  }

  inline OwningNonNull<mozilla::dom::Request> const &
  GetAsRequest() const
  {
    MOZ_ASSERT(IsRequest(), "Wrong type!");
    return mValue.mRequest.Value();
  }

  nsString&
  RawSetAsScalarValueString();

  nsString&
  SetAsScalarValueString();

  bool
  TrySetToScalarValueString(JSContext* cx, JS::Handle<JS::Value> value, bool& tryNext, bool passedToJSImpl = false);

  inline void
  SetStringData(const nsString::char_type* aData, nsString::size_type aLength)
  {
    RawSetAsScalarValueString().Assign(aData, aLength);
  }

  inline bool
  IsScalarValueString() const
  {
    return mType == eScalarValueString;
  }

  inline nsString&
  GetAsScalarValueString()
  {
    MOZ_ASSERT(IsScalarValueString(), "Wrong type!");
    return mValue.mScalarValueString.Value();
  }

  inline nsString const &
  GetAsScalarValueString() const
  {
    MOZ_ASSERT(IsScalarValueString(), "Wrong type!");
    return mValue.mScalarValueString.Value();
  }

  bool
  ToJSVal(JSContext* cx, JS::Handle<JSObject*> scopeObj, JS::MutableHandle<JS::Value> rval) const;

  void
  TraceUnion(JSTracer* trc);

  void
  operator=(const OwningRequestOrScalarValueString& aOther);

private:
  void
  DestroyRequest();

  void
  DestroyScalarValueString();

  void
  Uninit();
};

class OwningStringOrArrayBufferOrArrayBufferView : public AllOwningUnionBase
{
  friend void ImplCycleCollectionUnlink(OwningStringOrArrayBufferOrArrayBufferView& aUnion);
  enum Type
  {
    eUninitialized,
    eString,
    eArrayBuffer,
    eArrayBufferView
  };

  union Value
  {
    UnionMember<nsString > mString;
    UnionMember<ArrayBuffer > mArrayBuffer;
    UnionMember<ArrayBufferView > mArrayBufferView;

  };

  Type mType;
  Value mValue;

  OwningStringOrArrayBufferOrArrayBufferView(const OwningStringOrArrayBufferOrArrayBufferView&) MOZ_DELETE;
  void operator=(const OwningStringOrArrayBufferOrArrayBufferView) MOZ_DELETE;
public:
  explicit inline OwningStringOrArrayBufferOrArrayBufferView()
    : mType(eUninitialized)
  {
  }

  inline ~OwningStringOrArrayBufferOrArrayBufferView()
  {
    Uninit();
  }

  nsString&
  RawSetAsString();

  nsString&
  SetAsString();

  bool
  TrySetToString(JSContext* cx, JS::Handle<JS::Value> value, bool& tryNext, bool passedToJSImpl = false);

  inline void
  SetStringData(const nsString::char_type* aData, nsString::size_type aLength)
  {
    RawSetAsString().Assign(aData, aLength);
  }

  inline bool
  IsString() const
  {
    return mType == eString;
  }

  inline nsString&
  GetAsString()
  {
    MOZ_ASSERT(IsString(), "Wrong type!");
    return mValue.mString.Value();
  }

  inline nsString const &
  GetAsString() const
  {
    MOZ_ASSERT(IsString(), "Wrong type!");
    return mValue.mString.Value();
  }

  ArrayBuffer&
  RawSetAsArrayBuffer();

  ArrayBuffer&
  SetAsArrayBuffer();

  bool
  TrySetToArrayBuffer(JSContext* cx, JS::Handle<JS::Value> value, bool& tryNext, bool passedToJSImpl = false);

  inline bool
  IsArrayBuffer() const
  {
    return mType == eArrayBuffer;
  }

  inline ArrayBuffer&
  GetAsArrayBuffer()
  {
    MOZ_ASSERT(IsArrayBuffer(), "Wrong type!");
    return mValue.mArrayBuffer.Value();
  }

  inline ArrayBuffer const &
  GetAsArrayBuffer() const
  {
    MOZ_ASSERT(IsArrayBuffer(), "Wrong type!");
    return mValue.mArrayBuffer.Value();
  }

  ArrayBufferView&
  RawSetAsArrayBufferView();

  ArrayBufferView&
  SetAsArrayBufferView();

  bool
  TrySetToArrayBufferView(JSContext* cx, JS::Handle<JS::Value> value, bool& tryNext, bool passedToJSImpl = false);

  inline bool
  IsArrayBufferView() const
  {
    return mType == eArrayBufferView;
  }

  inline ArrayBufferView&
  GetAsArrayBufferView()
  {
    MOZ_ASSERT(IsArrayBufferView(), "Wrong type!");
    return mValue.mArrayBufferView.Value();
  }

  inline ArrayBufferView const &
  GetAsArrayBufferView() const
  {
    MOZ_ASSERT(IsArrayBufferView(), "Wrong type!");
    return mValue.mArrayBufferView.Value();
  }

  bool
  ToJSVal(JSContext* cx, JS::Handle<JSObject*> scopeObj, JS::MutableHandle<JS::Value> rval) const;

  void
  TraceUnion(JSTracer* trc);

private:
  void
  DestroyString();

  void
  DestroyArrayBuffer();

  void
  DestroyArrayBufferView();

  void
  Uninit();
};

class OwningStringOrBlobOrArrayBufferOrArrayBufferView : public AllOwningUnionBase
{
  friend void ImplCycleCollectionUnlink(OwningStringOrBlobOrArrayBufferOrArrayBufferView& aUnion);
  enum Type
  {
    eUninitialized,
    eString,
    eBlob,
    eArrayBuffer,
    eArrayBufferView
  };

  union Value
  {
    UnionMember<nsString > mString;
    UnionMember<OwningNonNull<mozilla::dom::File> > mBlob;
    UnionMember<ArrayBuffer > mArrayBuffer;
    UnionMember<ArrayBufferView > mArrayBufferView;

  };

  Type mType;
  Value mValue;

  OwningStringOrBlobOrArrayBufferOrArrayBufferView(const OwningStringOrBlobOrArrayBufferOrArrayBufferView&) MOZ_DELETE;
  void operator=(const OwningStringOrBlobOrArrayBufferOrArrayBufferView) MOZ_DELETE;
public:
  explicit inline OwningStringOrBlobOrArrayBufferOrArrayBufferView()
    : mType(eUninitialized)
  {
  }

  inline ~OwningStringOrBlobOrArrayBufferOrArrayBufferView()
  {
    Uninit();
  }

  nsString&
  RawSetAsString();

  nsString&
  SetAsString();

  bool
  TrySetToString(JSContext* cx, JS::Handle<JS::Value> value, bool& tryNext, bool passedToJSImpl = false);

  inline void
  SetStringData(const nsString::char_type* aData, nsString::size_type aLength)
  {
    RawSetAsString().Assign(aData, aLength);
  }

  inline bool
  IsString() const
  {
    return mType == eString;
  }

  inline nsString&
  GetAsString()
  {
    MOZ_ASSERT(IsString(), "Wrong type!");
    return mValue.mString.Value();
  }

  inline nsString const &
  GetAsString() const
  {
    MOZ_ASSERT(IsString(), "Wrong type!");
    return mValue.mString.Value();
  }

  OwningNonNull<mozilla::dom::File>&
  RawSetAsBlob();

  OwningNonNull<mozilla::dom::File>&
  SetAsBlob();

  bool
  TrySetToBlob(JSContext* cx, JS::Handle<JS::Value> value, bool& tryNext, bool passedToJSImpl = false);

  inline bool
  IsBlob() const
  {
    return mType == eBlob;
  }

  inline OwningNonNull<mozilla::dom::File>&
  GetAsBlob()
  {
    MOZ_ASSERT(IsBlob(), "Wrong type!");
    return mValue.mBlob.Value();
  }

  inline OwningNonNull<mozilla::dom::File> const &
  GetAsBlob() const
  {
    MOZ_ASSERT(IsBlob(), "Wrong type!");
    return mValue.mBlob.Value();
  }

  ArrayBuffer&
  RawSetAsArrayBuffer();

  ArrayBuffer&
  SetAsArrayBuffer();

  bool
  TrySetToArrayBuffer(JSContext* cx, JS::Handle<JS::Value> value, bool& tryNext, bool passedToJSImpl = false);

  inline bool
  IsArrayBuffer() const
  {
    return mType == eArrayBuffer;
  }

  inline ArrayBuffer&
  GetAsArrayBuffer()
  {
    MOZ_ASSERT(IsArrayBuffer(), "Wrong type!");
    return mValue.mArrayBuffer.Value();
  }

  inline ArrayBuffer const &
  GetAsArrayBuffer() const
  {
    MOZ_ASSERT(IsArrayBuffer(), "Wrong type!");
    return mValue.mArrayBuffer.Value();
  }

  ArrayBufferView&
  RawSetAsArrayBufferView();

  ArrayBufferView&
  SetAsArrayBufferView();

  bool
  TrySetToArrayBufferView(JSContext* cx, JS::Handle<JS::Value> value, bool& tryNext, bool passedToJSImpl = false);

  inline bool
  IsArrayBufferView() const
  {
    return mType == eArrayBufferView;
  }

  inline ArrayBufferView&
  GetAsArrayBufferView()
  {
    MOZ_ASSERT(IsArrayBufferView(), "Wrong type!");
    return mValue.mArrayBufferView.Value();
  }

  inline ArrayBufferView const &
  GetAsArrayBufferView() const
  {
    MOZ_ASSERT(IsArrayBufferView(), "Wrong type!");
    return mValue.mArrayBufferView.Value();
  }

  bool
  ToJSVal(JSContext* cx, JS::Handle<JSObject*> scopeObj, JS::MutableHandle<JS::Value> rval) const;

  void
  TraceUnion(JSTracer* trc);

private:
  void
  DestroyString();

  void
  DestroyBlob();

  void
  DestroyArrayBuffer();

  void
  DestroyArrayBufferView();

  void
  Uninit();
};

class OwningStringOrCanvasGradientOrCanvasPattern : public AllOwningUnionBase
{
  friend void ImplCycleCollectionUnlink(OwningStringOrCanvasGradientOrCanvasPattern& aUnion);
  enum Type
  {
    eUninitialized,
    eString,
    eCanvasGradient,
    eCanvasPattern
  };

  union Value
  {
    UnionMember<nsString > mString;
    UnionMember<OwningNonNull<mozilla::dom::CanvasGradient> > mCanvasGradient;
    UnionMember<OwningNonNull<mozilla::dom::CanvasPattern> > mCanvasPattern;

  };

  Type mType;
  Value mValue;

public:
  explicit inline OwningStringOrCanvasGradientOrCanvasPattern()
    : mType(eUninitialized)
  {
  }

  explicit inline OwningStringOrCanvasGradientOrCanvasPattern(const OwningStringOrCanvasGradientOrCanvasPattern& aOther)
    : mType(eUninitialized)
  {
    *this = aOther;
  }

  inline ~OwningStringOrCanvasGradientOrCanvasPattern()
  {
    Uninit();
  }

  nsString&
  RawSetAsString();

  nsString&
  SetAsString();

  bool
  TrySetToString(JSContext* cx, JS::Handle<JS::Value> value, bool& tryNext, bool passedToJSImpl = false);

  inline void
  SetStringData(const nsString::char_type* aData, nsString::size_type aLength)
  {
    RawSetAsString().Assign(aData, aLength);
  }

  inline bool
  IsString() const
  {
    return mType == eString;
  }

  inline nsString&
  GetAsString()
  {
    MOZ_ASSERT(IsString(), "Wrong type!");
    return mValue.mString.Value();
  }

  inline nsString const &
  GetAsString() const
  {
    MOZ_ASSERT(IsString(), "Wrong type!");
    return mValue.mString.Value();
  }

  OwningNonNull<mozilla::dom::CanvasGradient>&
  RawSetAsCanvasGradient();

  OwningNonNull<mozilla::dom::CanvasGradient>&
  SetAsCanvasGradient();

  bool
  TrySetToCanvasGradient(JSContext* cx, JS::Handle<JS::Value> value, bool& tryNext, bool passedToJSImpl = false);

  inline bool
  IsCanvasGradient() const
  {
    return mType == eCanvasGradient;
  }

  inline OwningNonNull<mozilla::dom::CanvasGradient>&
  GetAsCanvasGradient()
  {
    MOZ_ASSERT(IsCanvasGradient(), "Wrong type!");
    return mValue.mCanvasGradient.Value();
  }

  inline OwningNonNull<mozilla::dom::CanvasGradient> const &
  GetAsCanvasGradient() const
  {
    MOZ_ASSERT(IsCanvasGradient(), "Wrong type!");
    return mValue.mCanvasGradient.Value();
  }

  OwningNonNull<mozilla::dom::CanvasPattern>&
  RawSetAsCanvasPattern();

  OwningNonNull<mozilla::dom::CanvasPattern>&
  SetAsCanvasPattern();

  bool
  TrySetToCanvasPattern(JSContext* cx, JS::Handle<JS::Value> value, bool& tryNext, bool passedToJSImpl = false);

  inline bool
  IsCanvasPattern() const
  {
    return mType == eCanvasPattern;
  }

  inline OwningNonNull<mozilla::dom::CanvasPattern>&
  GetAsCanvasPattern()
  {
    MOZ_ASSERT(IsCanvasPattern(), "Wrong type!");
    return mValue.mCanvasPattern.Value();
  }

  inline OwningNonNull<mozilla::dom::CanvasPattern> const &
  GetAsCanvasPattern() const
  {
    MOZ_ASSERT(IsCanvasPattern(), "Wrong type!");
    return mValue.mCanvasPattern.Value();
  }

  bool
  ToJSVal(JSContext* cx, JS::Handle<JSObject*> scopeObj, JS::MutableHandle<JS::Value> rval) const;

  void
  TraceUnion(JSTracer* trc);

  void
  operator=(const OwningStringOrCanvasGradientOrCanvasPattern& aOther);

private:
  void
  DestroyString();

  void
  DestroyCanvasGradient();

  void
  DestroyCanvasPattern();

  void
  Uninit();
};

class OwningStringOrFileOrDirectory : public AllOwningUnionBase
{
  friend void ImplCycleCollectionUnlink(OwningStringOrFileOrDirectory& aUnion);
  enum Type
  {
    eUninitialized,
    eString,
    eFile,
    eDirectory
  };

  union Value
  {
    UnionMember<nsString > mString;
    UnionMember<OwningNonNull<mozilla::dom::File> > mFile;
    UnionMember<OwningNonNull<mozilla::dom::Directory> > mDirectory;

  };

  Type mType;
  Value mValue;

public:
  explicit inline OwningStringOrFileOrDirectory()
    : mType(eUninitialized)
  {
  }

  explicit inline OwningStringOrFileOrDirectory(const OwningStringOrFileOrDirectory& aOther)
    : mType(eUninitialized)
  {
    *this = aOther;
  }

  inline ~OwningStringOrFileOrDirectory()
  {
    Uninit();
  }

  nsString&
  RawSetAsString();

  nsString&
  SetAsString();

  bool
  TrySetToString(JSContext* cx, JS::Handle<JS::Value> value, bool& tryNext, bool passedToJSImpl = false);

  inline void
  SetStringData(const nsString::char_type* aData, nsString::size_type aLength)
  {
    RawSetAsString().Assign(aData, aLength);
  }

  inline bool
  IsString() const
  {
    return mType == eString;
  }

  inline nsString&
  GetAsString()
  {
    MOZ_ASSERT(IsString(), "Wrong type!");
    return mValue.mString.Value();
  }

  inline nsString const &
  GetAsString() const
  {
    MOZ_ASSERT(IsString(), "Wrong type!");
    return mValue.mString.Value();
  }

  OwningNonNull<mozilla::dom::File>&
  RawSetAsFile();

  OwningNonNull<mozilla::dom::File>&
  SetAsFile();

  bool
  TrySetToFile(JSContext* cx, JS::Handle<JS::Value> value, bool& tryNext, bool passedToJSImpl = false);

  inline bool
  IsFile() const
  {
    return mType == eFile;
  }

  inline OwningNonNull<mozilla::dom::File>&
  GetAsFile()
  {
    MOZ_ASSERT(IsFile(), "Wrong type!");
    return mValue.mFile.Value();
  }

  inline OwningNonNull<mozilla::dom::File> const &
  GetAsFile() const
  {
    MOZ_ASSERT(IsFile(), "Wrong type!");
    return mValue.mFile.Value();
  }

  OwningNonNull<mozilla::dom::Directory>&
  RawSetAsDirectory();

  OwningNonNull<mozilla::dom::Directory>&
  SetAsDirectory();

  bool
  TrySetToDirectory(JSContext* cx, JS::Handle<JS::Value> value, bool& tryNext, bool passedToJSImpl = false);

  inline bool
  IsDirectory() const
  {
    return mType == eDirectory;
  }

  inline OwningNonNull<mozilla::dom::Directory>&
  GetAsDirectory()
  {
    MOZ_ASSERT(IsDirectory(), "Wrong type!");
    return mValue.mDirectory.Value();
  }

  inline OwningNonNull<mozilla::dom::Directory> const &
  GetAsDirectory() const
  {
    MOZ_ASSERT(IsDirectory(), "Wrong type!");
    return mValue.mDirectory.Value();
  }

  bool
  ToJSVal(JSContext* cx, JS::Handle<JSObject*> scopeObj, JS::MutableHandle<JS::Value> rval) const;

  void
  TraceUnion(JSTracer* trc);

  void
  operator=(const OwningStringOrFileOrDirectory& aOther);

private:
  void
  DestroyString();

  void
  DestroyFile();

  void
  DestroyDirectory();

  void
  Uninit();
};

class OwningStringOrInstallTriggerData : public AllOwningUnionBase
{
  friend void ImplCycleCollectionUnlink(OwningStringOrInstallTriggerData& aUnion);
  enum Type
  {
    eUninitialized,
    eString,
    eInstallTriggerData
  };

  union Value
  {
    UnionMember<nsString > mString;
    UnionMember<InstallTriggerData > mInstallTriggerData;

  };

  Type mType;
  Value mValue;

public:
  explicit inline OwningStringOrInstallTriggerData()
    : mType(eUninitialized)
  {
  }

  explicit inline OwningStringOrInstallTriggerData(const OwningStringOrInstallTriggerData& aOther)
    : mType(eUninitialized)
  {
    *this = aOther;
  }

  inline ~OwningStringOrInstallTriggerData()
  {
    Uninit();
  }

  nsString&
  RawSetAsString();

  nsString&
  SetAsString();

  bool
  TrySetToString(JSContext* cx, JS::Handle<JS::Value> value, bool& tryNext, bool passedToJSImpl = false);

  inline void
  SetStringData(const nsString::char_type* aData, nsString::size_type aLength)
  {
    RawSetAsString().Assign(aData, aLength);
  }

  inline bool
  IsString() const
  {
    return mType == eString;
  }

  inline nsString&
  GetAsString()
  {
    MOZ_ASSERT(IsString(), "Wrong type!");
    return mValue.mString.Value();
  }

  inline nsString const &
  GetAsString() const
  {
    MOZ_ASSERT(IsString(), "Wrong type!");
    return mValue.mString.Value();
  }

  InstallTriggerData&
  RawSetAsInstallTriggerData();

  InstallTriggerData&
  SetAsInstallTriggerData();

  bool
  TrySetToInstallTriggerData(JSContext* cx, JS::Handle<JS::Value> value, bool& tryNext, bool passedToJSImpl = false);

  inline bool
  IsInstallTriggerData() const
  {
    return mType == eInstallTriggerData;
  }

  inline InstallTriggerData&
  GetAsInstallTriggerData()
  {
    MOZ_ASSERT(IsInstallTriggerData(), "Wrong type!");
    return mValue.mInstallTriggerData.Value();
  }

  inline InstallTriggerData const &
  GetAsInstallTriggerData() const
  {
    MOZ_ASSERT(IsInstallTriggerData(), "Wrong type!");
    return mValue.mInstallTriggerData.Value();
  }

  bool
  ToJSVal(JSContext* cx, JS::Handle<JSObject*> scopeObj, JS::MutableHandle<JS::Value> rval) const;

  void
  TraceUnion(JSTracer* trc);

  void
  operator=(const OwningStringOrInstallTriggerData& aOther);

private:
  void
  DestroyString();

  void
  DestroyInstallTriggerData();

  void
  Uninit();
};

class OwningStringOrUnsignedLong : public AllOwningUnionBase
{
  friend void ImplCycleCollectionUnlink(OwningStringOrUnsignedLong& aUnion);
  enum Type
  {
    eUninitialized,
    eString,
    eUnsignedLong
  };

  union Value
  {
    UnionMember<nsString > mString;
    UnionMember<uint32_t > mUnsignedLong;

  };

  Type mType;
  Value mValue;

public:
  explicit inline OwningStringOrUnsignedLong()
    : mType(eUninitialized)
  {
  }

  explicit inline OwningStringOrUnsignedLong(const OwningStringOrUnsignedLong& aOther)
    : mType(eUninitialized)
  {
    *this = aOther;
  }

  inline ~OwningStringOrUnsignedLong()
  {
    Uninit();
  }

  nsString&
  RawSetAsString();

  nsString&
  SetAsString();

  bool
  TrySetToString(JSContext* cx, JS::Handle<JS::Value> value, bool& tryNext, bool passedToJSImpl = false);

  inline void
  SetStringData(const nsString::char_type* aData, nsString::size_type aLength)
  {
    RawSetAsString().Assign(aData, aLength);
  }

  inline bool
  IsString() const
  {
    return mType == eString;
  }

  inline nsString&
  GetAsString()
  {
    MOZ_ASSERT(IsString(), "Wrong type!");
    return mValue.mString.Value();
  }

  inline nsString const &
  GetAsString() const
  {
    MOZ_ASSERT(IsString(), "Wrong type!");
    return mValue.mString.Value();
  }

  uint32_t&
  RawSetAsUnsignedLong();

  uint32_t&
  SetAsUnsignedLong();

  bool
  TrySetToUnsignedLong(JSContext* cx, JS::Handle<JS::Value> value, bool& tryNext, bool passedToJSImpl = false);

  inline bool
  IsUnsignedLong() const
  {
    return mType == eUnsignedLong;
  }

  inline uint32_t&
  GetAsUnsignedLong()
  {
    MOZ_ASSERT(IsUnsignedLong(), "Wrong type!");
    return mValue.mUnsignedLong.Value();
  }

  inline uint32_t const &
  GetAsUnsignedLong() const
  {
    MOZ_ASSERT(IsUnsignedLong(), "Wrong type!");
    return mValue.mUnsignedLong.Value();
  }

  bool
  ToJSVal(JSContext* cx, JS::Handle<JSObject*> scopeObj, JS::MutableHandle<JS::Value> rval) const;

  void
  TraceUnion(JSTracer* trc);

  void
  operator=(const OwningStringOrUnsignedLong& aOther);

private:
  void
  DestroyString();

  void
  DestroyUnsignedLong();

  void
  Uninit();
};

class OwningTelephonyCallOrTelephonyCallGroup : public AllOwningUnionBase
{
  friend void ImplCycleCollectionUnlink(OwningTelephonyCallOrTelephonyCallGroup& aUnion);
  enum Type
  {
    eUninitialized,
    eTelephonyCall,
    eTelephonyCallGroup
  };

  union Value
  {
    UnionMember<OwningNonNull<mozilla::dom::TelephonyCall> > mTelephonyCall;
    UnionMember<OwningNonNull<mozilla::dom::TelephonyCallGroup> > mTelephonyCallGroup;

  };

  Type mType;
  Value mValue;

public:
  explicit inline OwningTelephonyCallOrTelephonyCallGroup()
    : mType(eUninitialized)
  {
  }

  explicit inline OwningTelephonyCallOrTelephonyCallGroup(const OwningTelephonyCallOrTelephonyCallGroup& aOther)
    : mType(eUninitialized)
  {
    *this = aOther;
  }

  inline ~OwningTelephonyCallOrTelephonyCallGroup()
  {
    Uninit();
  }

  OwningNonNull<mozilla::dom::TelephonyCall>&
  RawSetAsTelephonyCall();

  OwningNonNull<mozilla::dom::TelephonyCall>&
  SetAsTelephonyCall();

  bool
  TrySetToTelephonyCall(JSContext* cx, JS::Handle<JS::Value> value, bool& tryNext, bool passedToJSImpl = false);

  inline bool
  IsTelephonyCall() const
  {
    return mType == eTelephonyCall;
  }

  inline OwningNonNull<mozilla::dom::TelephonyCall>&
  GetAsTelephonyCall()
  {
    MOZ_ASSERT(IsTelephonyCall(), "Wrong type!");
    return mValue.mTelephonyCall.Value();
  }

  inline OwningNonNull<mozilla::dom::TelephonyCall> const &
  GetAsTelephonyCall() const
  {
    MOZ_ASSERT(IsTelephonyCall(), "Wrong type!");
    return mValue.mTelephonyCall.Value();
  }

  OwningNonNull<mozilla::dom::TelephonyCallGroup>&
  RawSetAsTelephonyCallGroup();

  OwningNonNull<mozilla::dom::TelephonyCallGroup>&
  SetAsTelephonyCallGroup();

  bool
  TrySetToTelephonyCallGroup(JSContext* cx, JS::Handle<JS::Value> value, bool& tryNext, bool passedToJSImpl = false);

  inline bool
  IsTelephonyCallGroup() const
  {
    return mType == eTelephonyCallGroup;
  }

  inline OwningNonNull<mozilla::dom::TelephonyCallGroup>&
  GetAsTelephonyCallGroup()
  {
    MOZ_ASSERT(IsTelephonyCallGroup(), "Wrong type!");
    return mValue.mTelephonyCallGroup.Value();
  }

  inline OwningNonNull<mozilla::dom::TelephonyCallGroup> const &
  GetAsTelephonyCallGroup() const
  {
    MOZ_ASSERT(IsTelephonyCallGroup(), "Wrong type!");
    return mValue.mTelephonyCallGroup.Value();
  }

  bool
  ToJSVal(JSContext* cx, JS::Handle<JSObject*> scopeObj, JS::MutableHandle<JS::Value> rval) const;

  void
  TraceUnion(JSTracer* trc);

  void
  operator=(const OwningTelephonyCallOrTelephonyCallGroup& aOther);

private:
  void
  DestroyTelephonyCall();

  void
  DestroyTelephonyCallGroup();

  void
  Uninit();
};

class OwningTextOrElementOrDocument : public AllOwningUnionBase
{
  friend void ImplCycleCollectionUnlink(OwningTextOrElementOrDocument& aUnion);
  enum Type
  {
    eUninitialized,
    eText,
    eElement,
    eDocument
  };

  union Value
  {
    UnionMember<OwningNonNull<mozilla::dom::Text> > mText;
    UnionMember<OwningNonNull<mozilla::dom::Element> > mElement;
    UnionMember<OwningNonNull<nsIDocument> > mDocument;

  };

  Type mType;
  Value mValue;

public:
  explicit inline OwningTextOrElementOrDocument()
    : mType(eUninitialized)
  {
  }

  explicit inline OwningTextOrElementOrDocument(const OwningTextOrElementOrDocument& aOther)
    : mType(eUninitialized)
  {
    *this = aOther;
  }

  inline ~OwningTextOrElementOrDocument()
  {
    Uninit();
  }

  OwningNonNull<mozilla::dom::Text>&
  RawSetAsText();

  OwningNonNull<mozilla::dom::Text>&
  SetAsText();

  bool
  TrySetToText(JSContext* cx, JS::Handle<JS::Value> value, bool& tryNext, bool passedToJSImpl = false);

  inline bool
  IsText() const
  {
    return mType == eText;
  }

  inline OwningNonNull<mozilla::dom::Text>&
  GetAsText()
  {
    MOZ_ASSERT(IsText(), "Wrong type!");
    return mValue.mText.Value();
  }

  inline OwningNonNull<mozilla::dom::Text> const &
  GetAsText() const
  {
    MOZ_ASSERT(IsText(), "Wrong type!");
    return mValue.mText.Value();
  }

  OwningNonNull<mozilla::dom::Element>&
  RawSetAsElement();

  OwningNonNull<mozilla::dom::Element>&
  SetAsElement();

  bool
  TrySetToElement(JSContext* cx, JS::Handle<JS::Value> value, bool& tryNext, bool passedToJSImpl = false);

  inline bool
  IsElement() const
  {
    return mType == eElement;
  }

  inline OwningNonNull<mozilla::dom::Element>&
  GetAsElement()
  {
    MOZ_ASSERT(IsElement(), "Wrong type!");
    return mValue.mElement.Value();
  }

  inline OwningNonNull<mozilla::dom::Element> const &
  GetAsElement() const
  {
    MOZ_ASSERT(IsElement(), "Wrong type!");
    return mValue.mElement.Value();
  }

  OwningNonNull<nsIDocument>&
  RawSetAsDocument();

  OwningNonNull<nsIDocument>&
  SetAsDocument();

  bool
  TrySetToDocument(JSContext* cx, JS::Handle<JS::Value> value, bool& tryNext, bool passedToJSImpl = false);

  inline bool
  IsDocument() const
  {
    return mType == eDocument;
  }

  inline OwningNonNull<nsIDocument>&
  GetAsDocument()
  {
    MOZ_ASSERT(IsDocument(), "Wrong type!");
    return mValue.mDocument.Value();
  }

  inline OwningNonNull<nsIDocument> const &
  GetAsDocument() const
  {
    MOZ_ASSERT(IsDocument(), "Wrong type!");
    return mValue.mDocument.Value();
  }

  bool
  ToJSVal(JSContext* cx, JS::Handle<JSObject*> scopeObj, JS::MutableHandle<JS::Value> rval) const;

  void
  TraceUnion(JSTracer* trc);

  void
  operator=(const OwningTextOrElementOrDocument& aOther);

private:
  void
  DestroyText();

  void
  DestroyElement();

  void
  DestroyDocument();

  void
  Uninit();
};

class OwningUnsignedLongOrString : public AllOwningUnionBase
{
  friend void ImplCycleCollectionUnlink(OwningUnsignedLongOrString& aUnion);
  enum Type
  {
    eUninitialized,
    eUnsignedLong,
    eString
  };

  union Value
  {
    UnionMember<uint32_t > mUnsignedLong;
    UnionMember<nsString > mString;

  };

  Type mType;
  Value mValue;

public:
  explicit inline OwningUnsignedLongOrString()
    : mType(eUninitialized)
  {
  }

  explicit inline OwningUnsignedLongOrString(const OwningUnsignedLongOrString& aOther)
    : mType(eUninitialized)
  {
    *this = aOther;
  }

  inline ~OwningUnsignedLongOrString()
  {
    Uninit();
  }

  uint32_t&
  RawSetAsUnsignedLong();

  uint32_t&
  SetAsUnsignedLong();

  bool
  TrySetToUnsignedLong(JSContext* cx, JS::Handle<JS::Value> value, bool& tryNext, bool passedToJSImpl = false);

  inline bool
  IsUnsignedLong() const
  {
    return mType == eUnsignedLong;
  }

  inline uint32_t&
  GetAsUnsignedLong()
  {
    MOZ_ASSERT(IsUnsignedLong(), "Wrong type!");
    return mValue.mUnsignedLong.Value();
  }

  inline uint32_t const &
  GetAsUnsignedLong() const
  {
    MOZ_ASSERT(IsUnsignedLong(), "Wrong type!");
    return mValue.mUnsignedLong.Value();
  }

  nsString&
  RawSetAsString();

  nsString&
  SetAsString();

  bool
  TrySetToString(JSContext* cx, JS::Handle<JS::Value> value, bool& tryNext, bool passedToJSImpl = false);

  inline void
  SetStringData(const nsString::char_type* aData, nsString::size_type aLength)
  {
    RawSetAsString().Assign(aData, aLength);
  }

  inline bool
  IsString() const
  {
    return mType == eString;
  }

  inline nsString&
  GetAsString()
  {
    MOZ_ASSERT(IsString(), "Wrong type!");
    return mValue.mString.Value();
  }

  inline nsString const &
  GetAsString() const
  {
    MOZ_ASSERT(IsString(), "Wrong type!");
    return mValue.mString.Value();
  }

  bool
  ToJSVal(JSContext* cx, JS::Handle<JSObject*> scopeObj, JS::MutableHandle<JS::Value> rval) const;

  void
  TraceUnion(JSTracer* trc);

  void
  operator=(const OwningUnsignedLongOrString& aOther);

private:
  void
  DestroyUnsignedLong();

  void
  DestroyString();

  void
  Uninit();
};

class OwningUnsignedShortOrObject : public AllOwningUnionBase
{
  friend void ImplCycleCollectionUnlink(OwningUnsignedShortOrObject& aUnion);
  enum Type
  {
    eUninitialized,
    eUnsignedShort,
    eObject
  };

  union Value
  {
    UnionMember<uint16_t > mUnsignedShort;
    UnionMember<JSObject* > mObject;

  };

  Type mType;
  Value mValue;

  OwningUnsignedShortOrObject(const OwningUnsignedShortOrObject&) MOZ_DELETE;
  void operator=(const OwningUnsignedShortOrObject) MOZ_DELETE;
public:
  explicit inline OwningUnsignedShortOrObject()
    : mType(eUninitialized)
  {
  }

  inline ~OwningUnsignedShortOrObject()
  {
    Uninit();
  }

  uint16_t&
  RawSetAsUnsignedShort();

  uint16_t&
  SetAsUnsignedShort();

  bool
  TrySetToUnsignedShort(JSContext* cx, JS::Handle<JS::Value> value, bool& tryNext, bool passedToJSImpl = false);

  inline bool
  IsUnsignedShort() const
  {
    return mType == eUnsignedShort;
  }

  inline uint16_t&
  GetAsUnsignedShort()
  {
    MOZ_ASSERT(IsUnsignedShort(), "Wrong type!");
    return mValue.mUnsignedShort.Value();
  }

  inline uint16_t const &
  GetAsUnsignedShort() const
  {
    MOZ_ASSERT(IsUnsignedShort(), "Wrong type!");
    return mValue.mUnsignedShort.Value();
  }

  JSObject*&
  RawSetAsObject();

  JSObject*&
  SetAsObject();

  inline bool
  SetToObject(JSContext* cx, JSObject* obj, bool passedToJSImpl = false)
  {
    MOZ_ASSERT(mType == eUninitialized);
    mValue.mObject.SetValue(obj);
    mType = eObject;
    if (passedToJSImpl && !CallerSubsumes(obj)) {
      ThrowErrorMessage(cx, MSG_PERMISSION_DENIED_TO_PASS_ARG, "%s");
      return false;
    }
    return true;
  }

  inline bool
  IsObject() const
  {
    return mType == eObject;
  }

  inline JSObject*&
  GetAsObject()
  {
    MOZ_ASSERT(IsObject(), "Wrong type!");
    return mValue.mObject.Value();
  }

  inline JSObject* const &
  GetAsObject() const
  {
    MOZ_ASSERT(IsObject(), "Wrong type!");
    return mValue.mObject.Value();
  }

  bool
  ToJSVal(JSContext* cx, JS::Handle<JSObject*> scopeObj, JS::MutableHandle<JS::Value> rval) const;

  void
  TraceUnion(JSTracer* trc);

private:
  void
  DestroyUnsignedShort();

  void
  DestroyObject();

  void
  Uninit();
};

class OwningVideoTrackOrAudioTrackOrTextTrack : public AllOwningUnionBase
{
  friend void ImplCycleCollectionUnlink(OwningVideoTrackOrAudioTrackOrTextTrack& aUnion);
  enum Type
  {
    eUninitialized,
    eVideoTrack,
    eAudioTrack,
    eTextTrack
  };

  union Value
  {
    UnionMember<OwningNonNull<mozilla::dom::VideoTrack> > mVideoTrack;
    UnionMember<OwningNonNull<mozilla::dom::AudioTrack> > mAudioTrack;
    UnionMember<OwningNonNull<mozilla::dom::TextTrack> > mTextTrack;

  };

  Type mType;
  Value mValue;

public:
  explicit inline OwningVideoTrackOrAudioTrackOrTextTrack()
    : mType(eUninitialized)
  {
  }

  explicit inline OwningVideoTrackOrAudioTrackOrTextTrack(const OwningVideoTrackOrAudioTrackOrTextTrack& aOther)
    : mType(eUninitialized)
  {
    *this = aOther;
  }

  inline ~OwningVideoTrackOrAudioTrackOrTextTrack()
  {
    Uninit();
  }

  OwningNonNull<mozilla::dom::VideoTrack>&
  RawSetAsVideoTrack();

  OwningNonNull<mozilla::dom::VideoTrack>&
  SetAsVideoTrack();

  bool
  TrySetToVideoTrack(JSContext* cx, JS::Handle<JS::Value> value, bool& tryNext, bool passedToJSImpl = false);

  inline bool
  IsVideoTrack() const
  {
    return mType == eVideoTrack;
  }

  inline OwningNonNull<mozilla::dom::VideoTrack>&
  GetAsVideoTrack()
  {
    MOZ_ASSERT(IsVideoTrack(), "Wrong type!");
    return mValue.mVideoTrack.Value();
  }

  inline OwningNonNull<mozilla::dom::VideoTrack> const &
  GetAsVideoTrack() const
  {
    MOZ_ASSERT(IsVideoTrack(), "Wrong type!");
    return mValue.mVideoTrack.Value();
  }

  OwningNonNull<mozilla::dom::AudioTrack>&
  RawSetAsAudioTrack();

  OwningNonNull<mozilla::dom::AudioTrack>&
  SetAsAudioTrack();

  bool
  TrySetToAudioTrack(JSContext* cx, JS::Handle<JS::Value> value, bool& tryNext, bool passedToJSImpl = false);

  inline bool
  IsAudioTrack() const
  {
    return mType == eAudioTrack;
  }

  inline OwningNonNull<mozilla::dom::AudioTrack>&
  GetAsAudioTrack()
  {
    MOZ_ASSERT(IsAudioTrack(), "Wrong type!");
    return mValue.mAudioTrack.Value();
  }

  inline OwningNonNull<mozilla::dom::AudioTrack> const &
  GetAsAudioTrack() const
  {
    MOZ_ASSERT(IsAudioTrack(), "Wrong type!");
    return mValue.mAudioTrack.Value();
  }

  OwningNonNull<mozilla::dom::TextTrack>&
  RawSetAsTextTrack();

  OwningNonNull<mozilla::dom::TextTrack>&
  SetAsTextTrack();

  bool
  TrySetToTextTrack(JSContext* cx, JS::Handle<JS::Value> value, bool& tryNext, bool passedToJSImpl = false);

  inline bool
  IsTextTrack() const
  {
    return mType == eTextTrack;
  }

  inline OwningNonNull<mozilla::dom::TextTrack>&
  GetAsTextTrack()
  {
    MOZ_ASSERT(IsTextTrack(), "Wrong type!");
    return mValue.mTextTrack.Value();
  }

  inline OwningNonNull<mozilla::dom::TextTrack> const &
  GetAsTextTrack() const
  {
    MOZ_ASSERT(IsTextTrack(), "Wrong type!");
    return mValue.mTextTrack.Value();
  }

  bool
  ToJSVal(JSContext* cx, JS::Handle<JSObject*> scopeObj, JS::MutableHandle<JS::Value> rval) const;

  void
  TraceUnion(JSTracer* trc);

  void
  operator=(const OwningVideoTrackOrAudioTrackOrTextTrack& aOther);

private:
  void
  DestroyVideoTrack();

  void
  DestroyAudioTrack();

  void
  DestroyTextTrack();

  void
  Uninit();
};

class OwningWindowProxyOrMessagePort : public AllOwningUnionBase
{
  friend void ImplCycleCollectionUnlink(OwningWindowProxyOrMessagePort& aUnion);
  enum Type
  {
    eUninitialized,
    eWindowProxy,
    eMessagePort
  };

  union Value
  {
    UnionMember<nsRefPtr<nsIDOMWindow> > mWindowProxy;
    UnionMember<OwningNonNull<mozilla::dom::MessagePortBase> > mMessagePort;

  };

  Type mType;
  Value mValue;

public:
  explicit inline OwningWindowProxyOrMessagePort()
    : mType(eUninitialized)
  {
  }

  explicit inline OwningWindowProxyOrMessagePort(const OwningWindowProxyOrMessagePort& aOther)
    : mType(eUninitialized)
  {
    *this = aOther;
  }

  inline ~OwningWindowProxyOrMessagePort()
  {
    Uninit();
  }

  nsRefPtr<nsIDOMWindow>&
  RawSetAsWindowProxy();

  nsRefPtr<nsIDOMWindow>&
  SetAsWindowProxy();

  bool
  TrySetToWindowProxy(JSContext* cx, JS::Handle<JS::Value> value, bool& tryNext, bool passedToJSImpl = false);

  inline bool
  IsWindowProxy() const
  {
    return mType == eWindowProxy;
  }

  inline nsRefPtr<nsIDOMWindow>&
  GetAsWindowProxy()
  {
    MOZ_ASSERT(IsWindowProxy(), "Wrong type!");
    return mValue.mWindowProxy.Value();
  }

  inline nsRefPtr<nsIDOMWindow> const &
  GetAsWindowProxy() const
  {
    MOZ_ASSERT(IsWindowProxy(), "Wrong type!");
    return mValue.mWindowProxy.Value();
  }

  OwningNonNull<mozilla::dom::MessagePortBase>&
  RawSetAsMessagePort();

  OwningNonNull<mozilla::dom::MessagePortBase>&
  SetAsMessagePort();

  bool
  TrySetToMessagePort(JSContext* cx, JS::Handle<JS::Value> value, bool& tryNext, bool passedToJSImpl = false);

  inline bool
  IsMessagePort() const
  {
    return mType == eMessagePort;
  }

  inline OwningNonNull<mozilla::dom::MessagePortBase>&
  GetAsMessagePort()
  {
    MOZ_ASSERT(IsMessagePort(), "Wrong type!");
    return mValue.mMessagePort.Value();
  }

  inline OwningNonNull<mozilla::dom::MessagePortBase> const &
  GetAsMessagePort() const
  {
    MOZ_ASSERT(IsMessagePort(), "Wrong type!");
    return mValue.mMessagePort.Value();
  }

  bool
  ToJSVal(JSContext* cx, JS::Handle<JSObject*> scopeObj, JS::MutableHandle<JS::Value> rval) const;

  void
  TraceUnion(JSTracer* trc);

  void
  operator=(const OwningWindowProxyOrMessagePort& aOther);

private:
  void
  DestroyWindowProxy();

  void
  DestroyMessagePort();

  void
  Uninit();
};

class OwningmozContactOrString : public AllOwningUnionBase
{
  friend void ImplCycleCollectionUnlink(OwningmozContactOrString& aUnion);
  enum Type
  {
    eUninitialized,
    emozContact,
    eString
  };

  union Value
  {
    UnionMember<OwningNonNull<mozilla::dom::mozContact> > mmozContact;
    UnionMember<nsString > mString;

  };

  Type mType;
  Value mValue;

public:
  explicit inline OwningmozContactOrString()
    : mType(eUninitialized)
  {
  }

  explicit inline OwningmozContactOrString(const OwningmozContactOrString& aOther)
    : mType(eUninitialized)
  {
    *this = aOther;
  }

  inline ~OwningmozContactOrString()
  {
    Uninit();
  }

  OwningNonNull<mozilla::dom::mozContact>&
  RawSetAsmozContact();

  OwningNonNull<mozilla::dom::mozContact>&
  SetAsmozContact();

  bool
  TrySetTomozContact(JSContext* cx, JS::Handle<JS::Value> value, bool& tryNext, bool passedToJSImpl = false);

  inline bool
  IsmozContact() const
  {
    return mType == emozContact;
  }

  inline OwningNonNull<mozilla::dom::mozContact>&
  GetAsmozContact()
  {
    MOZ_ASSERT(IsmozContact(), "Wrong type!");
    return mValue.mmozContact.Value();
  }

  inline OwningNonNull<mozilla::dom::mozContact> const &
  GetAsmozContact() const
  {
    MOZ_ASSERT(IsmozContact(), "Wrong type!");
    return mValue.mmozContact.Value();
  }

  nsString&
  RawSetAsString();

  nsString&
  SetAsString();

  bool
  TrySetToString(JSContext* cx, JS::Handle<JS::Value> value, bool& tryNext, bool passedToJSImpl = false);

  inline void
  SetStringData(const nsString::char_type* aData, nsString::size_type aLength)
  {
    RawSetAsString().Assign(aData, aLength);
  }

  inline bool
  IsString() const
  {
    return mType == eString;
  }

  inline nsString&
  GetAsString()
  {
    MOZ_ASSERT(IsString(), "Wrong type!");
    return mValue.mString.Value();
  }

  inline nsString const &
  GetAsString() const
  {
    MOZ_ASSERT(IsString(), "Wrong type!");
    return mValue.mString.Value();
  }

  bool
  ToJSVal(JSContext* cx, JS::Handle<JSObject*> scopeObj, JS::MutableHandle<JS::Value> rval) const;

  void
  TraceUnion(JSTracer* trc);

  void
  operator=(const OwningmozContactOrString& aOther);

private:
  void
  DestroymozContact();

  void
  DestroyString();

  void
  Uninit();
};
} // namespace dom
} // namespace mozilla


#endif // mozilla_dom_UnionTypes_h
