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

#include <type_traits>
#include "AtomList.h"
#include "GeometryUtilsBinding.h"
#include "MainThreadUtils.h"
#include "js/CallAndConstruct.h"
#include "js/Exception.h"
#include "js/MapAndSet.h"
#include "js/Object.h"
#include "js/PropertyAndElement.h"
#include "js/PropertyDescriptor.h"
#include "js/experimental/JitInfo.h"
#include "jsapi.h"
#include "mozilla/OwningNonNull.h"
#include "mozilla/dom/BindingCallContext.h"
#include "mozilla/dom/BindingUtils.h"
#include "mozilla/dom/Document.h"
#include "mozilla/dom/Element.h"
#include "mozilla/dom/NonRefcountedDOMObject.h"
#include "mozilla/dom/PrimitiveConversions.h"
#include "mozilla/dom/ScriptSettings.h"
#include "mozilla/dom/SimpleGlobalObject.h"
#include "nsContentUtils.h"
#include "nsTextNode.h"

namespace mozilla {

namespace dom {

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


namespace binding_detail {
constexpr nsLiteralCString EnumStrings<CSSBoxType>::Values[4];
} // namespace binding_detail

bool
ToJSValue(JSContext* aCx, CSSBoxType aArgument, JS::MutableHandle<JS::Value> aValue)
{
  MOZ_ASSERT(uint32_t(aArgument) < std::size(binding_detail::EnumStrings<CSSBoxType>::Values));
  JSString* resultStr =
    JS_NewStringCopyN(aCx, binding_detail::EnumStrings<CSSBoxType>::Values[uint32_t(aArgument)].BeginReading(),
                      binding_detail::EnumStrings<CSSBoxType>::Values[uint32_t(aArgument)].Length());
  if (!resultStr) {
    return false;
  }
  aValue.setString(resultStr);
  return true;
}


void
ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback& aCallback, OwningTextOrElementOrDocument& aUnion, const char* aName, uint32_t aFlags)
{
  if (aUnion.IsText()) {
    ImplCycleCollectionTraverse(aCallback, aUnion.GetAsText(), "mText", aFlags);
  } else if (aUnion.IsElement()) {
    ImplCycleCollectionTraverse(aCallback, aUnion.GetAsElement(), "mElement", aFlags);
  } else if (aUnion.IsDocument()) {
    ImplCycleCollectionTraverse(aCallback, aUnion.GetAsDocument(), "mDocument", aFlags);
  }
}


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



GeometryUtilsOptions::GeometryUtilsOptions()
{
  // Safe to pass a null context if we pass a null value
  Init(nullptr, JS::NullHandleValue);
}




bool
GeometryUtilsOptions::InitIds(JSContext* cx, GeometryUtilsOptionsAtoms* atomsCache)
{
  MOZ_ASSERT(reinterpret_cast<jsid*>(atomsCache)->isVoid());

  // Initialize these in reverse order so that any failure leaves the first one
  // uninitialized.
  if (!atomsCache->flush_id.init(cx, "flush") ||
      !atomsCache->createFramesForSuppressedWhitespace_id.init(cx, "createFramesForSuppressedWhitespace")) {
    return false;
  }
  return true;
}

bool
GeometryUtilsOptions::Init(BindingCallContext& cx, JS::Handle<JS::Value> val, const char* sourceDescription, bool passedToJSImpl)
{
  // Passing a null JSContext is OK only if we're initing from null,
  // Since in that case we will not have to do any property gets
  // Also evaluate isNullOrUndefined in order to avoid false-positive
  // checkers by static analysis tools
  MOZ_ASSERT_IF(!cx, val.isNull() && val.isNullOrUndefined());
  GeometryUtilsOptionsAtoms* atomsCache = nullptr;
  if (cx) {
    atomsCache = GetAtomCache<GeometryUtilsOptionsAtoms>(cx);
    if (reinterpret_cast<jsid*>(atomsCache)->isVoid() &&
        !InitIds(cx, atomsCache)) {
      return false;
    }
  }

  if (!IsConvertibleToDictionary(val)) {
    return cx.ThrowErrorMessage<MSG_CONVERSION_ERROR>(sourceDescription, "dictionary");
  }

  bool isNull = val.isNullOrUndefined();
  // We only need these if !isNull, in which case we have |cx|.
  Maybe<JS::Rooted<JSObject *> > object;
  Maybe<JS::Rooted<JS::Value> > temp;
  if (!isNull) {
    MOZ_ASSERT(cx);
    object.emplace(cx, &val.toObject());
    temp.emplace(cx);
  }
  if (!isNull) {
    if (nsContentUtils::ThreadsafeIsSystemCaller(cx)) {
      if (!JS_GetPropertyById(cx, *object, atomsCache->createFramesForSuppressedWhitespace_id, temp.ptr())) {
        return false;
      }
    } else {
      temp->setUndefined();
    }
  }
  if (!isNull && !temp->isUndefined()) {
    if (!ValueToPrimitive<bool, eDefault>(cx, temp.ref(), "'createFramesForSuppressedWhitespace' member of GeometryUtilsOptions", &mCreateFramesForSuppressedWhitespace)) {
      return false;
    }
  } else {
    mCreateFramesForSuppressedWhitespace = true;
  }
  mIsAnyMemberPresent = true;

  if (!isNull) {
    if (nsContentUtils::ThreadsafeIsSystemCaller(cx)) {
      if (!JS_GetPropertyById(cx, *object, atomsCache->flush_id, temp.ptr())) {
        return false;
      }
    } else {
      temp->setUndefined();
    }
  }
  if (!isNull && !temp->isUndefined()) {
    if (!ValueToPrimitive<bool, eDefault>(cx, temp.ref(), "'flush' member of GeometryUtilsOptions", &mFlush)) {
      return false;
    }
  } else {
    mFlush = true;
  }
  mIsAnyMemberPresent = true;
  return true;
}

bool
GeometryUtilsOptions::Init(JSContext* cx_, JS::Handle<JS::Value> val, const char* sourceDescription, bool passedToJSImpl)
{
  // We don't want to use sourceDescription for our context here;
  // that's not really what it's formatted for.
  BindingCallContext cx(cx_, nullptr);
  return Init(cx, val, sourceDescription, passedToJSImpl);
}

void
GeometryUtilsOptions::TraceDictionary(JSTracer* trc)
{
}

GeometryUtilsOptions&
GeometryUtilsOptions::operator=(const GeometryUtilsOptions& aOther)
{
  DictionaryBase::operator=(aOther);
  mCreateFramesForSuppressedWhitespace = aOther.mCreateFramesForSuppressedWhitespace;
  mFlush = aOther.mFlush;
  return *this;
}


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

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







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

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







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

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







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

  bool done = false, failed = false, tryNext;
  if (value.isObject()) {
    done = (failed = !TrySetToText(cx, value, tryNext, passedToJSImpl)) || !tryNext ||
           (failed = !TrySetToElement(cx, value, tryNext, passedToJSImpl)) || !tryNext ||
           (failed = !TrySetToDocument(cx, value, tryNext, passedToJSImpl)) || !tryNext;
  }
  if (failed) {
    return false;
  }
  if (!done) {
    cx.ThrowErrorMessage<MSG_NOT_IN_UNION>(sourceDescription, "Text, Element, Document");
    return false;
  }
  return true;
}

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


bool
TextOrElementOrDocument::ToJSVal(JSContext* cx, JS::Handle<JSObject*> scopeObj, JS::MutableHandle<JS::Value> rval) const
{
  switch (mType) {
    case eUninitialized: {
      return false;
    }
    case eText: {
      if (!GetOrCreateDOMReflector(cx, mValue.mText.Value(), rval)) {
        MOZ_ASSERT(JS_IsExceptionPending(cx));
        return false;
      }
      return true;
    }
    case eElement: {
      if (!GetOrCreateDOMReflector(cx, mValue.mElement.Value(), rval)) {
        MOZ_ASSERT(JS_IsExceptionPending(cx));
        return false;
      }
      return true;
    }
    case eDocument: {
      if (!GetOrCreateDOMReflector(cx, mValue.mDocument.Value(), rval)) {
        MOZ_ASSERT(JS_IsExceptionPending(cx));
        return false;
      }
      return true;
    }
    default: {
      return false;
    }
  }
}



OwningTextOrElementOrDocument::OwningTextOrElementOrDocument(OwningTextOrElementOrDocument&& aOther)
  : mType(eUninitialized)
{
  switch (aOther.mType) {
    case eUninitialized: {
      MOZ_ASSERT(mType == eUninitialized,
                 "We need to destroy ourselves?");
      break;
    }
    case eText: {
      mType = eText;
      mValue.mText.SetValue(std::move(aOther.mValue.mText.Value()));
      break;
    }
    case eElement: {
      mType = eElement;
      mValue.mElement.SetValue(std::move(aOther.mValue.mElement.Value()));
      break;
    }
    case eDocument: {
      mType = eDocument;
      mValue.mDocument.SetValue(std::move(aOther.mValue.mDocument.Value()));
      break;
    }
  }
}



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

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

[[nodiscard]] OwningNonNull<mozilla::dom::Text>&
OwningTextOrElementOrDocument::RawSetAsText()
{
  if (mType == eText) {
    return mValue.mText.Value();
  }
  MOZ_ASSERT(mType == eUninitialized);
  mType = eText;
  return mValue.mText.SetValue();
}

[[nodiscard]] OwningNonNull<mozilla::dom::Text>&
OwningTextOrElementOrDocument::SetAsText()
{
  if (mType == eText) {
    return mValue.mText.Value();
  }
  Uninit();
  mType = eText;
  return mValue.mText.SetValue();
}


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



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

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

[[nodiscard]] OwningNonNull<mozilla::dom::Element>&
OwningTextOrElementOrDocument::RawSetAsElement()
{
  if (mType == eElement) {
    return mValue.mElement.Value();
  }
  MOZ_ASSERT(mType == eUninitialized);
  mType = eElement;
  return mValue.mElement.SetValue();
}

[[nodiscard]] OwningNonNull<mozilla::dom::Element>&
OwningTextOrElementOrDocument::SetAsElement()
{
  if (mType == eElement) {
    return mValue.mElement.Value();
  }
  Uninit();
  mType = eElement;
  return mValue.mElement.SetValue();
}


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



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

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

[[nodiscard]] OwningNonNull<mozilla::dom::Document>&
OwningTextOrElementOrDocument::RawSetAsDocument()
{
  if (mType == eDocument) {
    return mValue.mDocument.Value();
  }
  MOZ_ASSERT(mType == eUninitialized);
  mType = eDocument;
  return mValue.mDocument.SetValue();
}

[[nodiscard]] OwningNonNull<mozilla::dom::Document>&
OwningTextOrElementOrDocument::SetAsDocument()
{
  if (mType == eDocument) {
    return mValue.mDocument.Value();
  }
  Uninit();
  mType = eDocument;
  return mValue.mDocument.SetValue();
}


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



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

  bool done = false, failed = false, tryNext;
  if (value.isObject()) {
    done = (failed = !TrySetToText(cx, value, tryNext, passedToJSImpl)) || !tryNext ||
           (failed = !TrySetToElement(cx, value, tryNext, passedToJSImpl)) || !tryNext ||
           (failed = !TrySetToDocument(cx, value, tryNext, passedToJSImpl)) || !tryNext;
  }
  if (failed) {
    return false;
  }
  if (!done) {
    cx.ThrowErrorMessage<MSG_NOT_IN_UNION>(sourceDescription, "Text, Element, Document");
    return false;
  }
  return true;
}

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

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

bool
OwningTextOrElementOrDocument::ToJSVal(JSContext* cx, JS::Handle<JSObject*> scopeObj, JS::MutableHandle<JS::Value> rval) const
{
  switch (mType) {
    case eUninitialized: {
      return false;
    }
    case eText: {
      if (!GetOrCreateDOMReflector(cx, mValue.mText.Value(), rval)) {
        MOZ_ASSERT(JS_IsExceptionPending(cx));
        return false;
      }
      return true;
    }
    case eElement: {
      if (!GetOrCreateDOMReflector(cx, mValue.mElement.Value(), rval)) {
        MOZ_ASSERT(JS_IsExceptionPending(cx));
        return false;
      }
      return true;
    }
    case eDocument: {
      if (!GetOrCreateDOMReflector(cx, mValue.mDocument.Value(), rval)) {
        MOZ_ASSERT(JS_IsExceptionPending(cx));
        return false;
      }
      return true;
    }
    default: {
      return false;
    }
  }
}

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


OwningTextOrElementOrDocument&
OwningTextOrElementOrDocument::operator=(const OwningTextOrElementOrDocument& aOther)
{
  switch (aOther.mType) {
    case eUninitialized: {
      MOZ_ASSERT(mType == eUninitialized,
                 "We need to destroy ourselves?");
      break;
    }
    case eText: {
      SetAsText() = aOther.GetAsText();
      break;
    }
    case eElement: {
      SetAsElement() = aOther.GetAsElement();
      break;
    }
    case eDocument: {
      SetAsDocument() = aOther.GetAsDocument();
      break;
    }
  }
  return *this;
}



BoxQuadOptions::BoxQuadOptions()
  : GeometryUtilsOptions(FastDictionaryInitializer())
{
  // Safe to pass a null context if we pass a null value
  Init(nullptr, JS::NullHandleValue);
}




bool
BoxQuadOptions::InitIds(JSContext* cx, BoxQuadOptionsAtoms* atomsCache)
{
  MOZ_ASSERT(reinterpret_cast<jsid*>(atomsCache)->isVoid());

  // Initialize these in reverse order so that any failure leaves the first one
  // uninitialized.
  if (!atomsCache->relativeTo_id.init(cx, "relativeTo") ||
      !atomsCache->ignoreTransforms_id.init(cx, "ignoreTransforms") ||
      !atomsCache->box_id.init(cx, "box")) {
    return false;
  }
  return true;
}

bool
BoxQuadOptions::Init(BindingCallContext& cx, JS::Handle<JS::Value> val, const char* sourceDescription, bool passedToJSImpl)
{
  // Passing a null JSContext is OK only if we're initing from null,
  // Since in that case we will not have to do any property gets
  // Also evaluate isNullOrUndefined in order to avoid false-positive
  // checkers by static analysis tools
  MOZ_ASSERT_IF(!cx, val.isNull() && val.isNullOrUndefined());
  BoxQuadOptionsAtoms* atomsCache = nullptr;
  if (cx) {
    atomsCache = GetAtomCache<BoxQuadOptionsAtoms>(cx);
    if (reinterpret_cast<jsid*>(atomsCache)->isVoid() &&
        !InitIds(cx, atomsCache)) {
      return false;
    }
  }

  // Per spec, we init the parent's members first
  if (!GeometryUtilsOptions::Init(cx, val)) {
    return false;
  }

  bool isNull = val.isNullOrUndefined();
  // We only need these if !isNull, in which case we have |cx|.
  Maybe<JS::Rooted<JSObject *> > object;
  Maybe<JS::Rooted<JS::Value> > temp;
  if (!isNull) {
    MOZ_ASSERT(cx);
    object.emplace(cx, &val.toObject());
    temp.emplace(cx);
  }
  if (!isNull) {
    if (!JS_GetPropertyById(cx, *object, atomsCache->box_id, temp.ptr())) {
      return false;
    }
  }
  if (!isNull && !temp->isUndefined()) {
    {
      int index;
      if (!binding_detail::FindEnumStringIndex<true>(cx, temp.ref(),
                                                                         binding_detail::EnumStrings<CSSBoxType>::Values,
                                                                         "CSSBoxType", "'box' member of BoxQuadOptions",
                                                                         &index)) {
        return false;
      }
      MOZ_ASSERT(index >= 0);
      mBox = static_cast<CSSBoxType>(index);
    }
  } else {
    mBox = CSSBoxType::Border;
  }
  mIsAnyMemberPresent = true;

  if (!isNull) {
    if (nsContentUtils::ThreadsafeIsSystemCaller(cx)) {
      if (!JS_GetPropertyById(cx, *object, atomsCache->ignoreTransforms_id, temp.ptr())) {
        return false;
      }
    } else {
      temp->setUndefined();
    }
  }
  if (!isNull && !temp->isUndefined()) {
    if (!ValueToPrimitive<bool, eDefault>(cx, temp.ref(), "'ignoreTransforms' member of BoxQuadOptions", &mIgnoreTransforms)) {
      return false;
    }
  } else {
    mIgnoreTransforms = false;
  }
  mIsAnyMemberPresent = true;

  if (!isNull) {
    if (!JS_GetPropertyById(cx, *object, atomsCache->relativeTo_id, temp.ptr())) {
      return false;
    }
  }
  if (!isNull && !temp->isUndefined()) {
    mRelativeTo.Construct();
    if (!(mRelativeTo.Value()).Init(cx, temp.ref(), "'relativeTo' member of BoxQuadOptions", passedToJSImpl)) {
      return false;
    }
    mIsAnyMemberPresent = true;
  }
  return true;
}

bool
BoxQuadOptions::Init(JSContext* cx_, JS::Handle<JS::Value> val, const char* sourceDescription, bool passedToJSImpl)
{
  // We don't want to use sourceDescription for our context here;
  // that's not really what it's formatted for.
  BindingCallContext cx(cx_, nullptr);
  return Init(cx, val, sourceDescription, passedToJSImpl);
}

void
BoxQuadOptions::TraceDictionary(JSTracer* trc)
{
  GeometryUtilsOptions::TraceDictionary(trc);
}



BoxQuadOptions&
BoxQuadOptions::operator=(const BoxQuadOptions& aOther)
{
  GeometryUtilsOptions::operator=(aOther);
  mBox = aOther.mBox;
  mIgnoreTransforms = aOther.mIgnoreTransforms;
  mRelativeTo.Reset();
  if (aOther.mRelativeTo.WasPassed()) {
    mRelativeTo.Construct(aOther.mRelativeTo.Value());
  }
  return *this;
}



ConvertCoordinateOptions::ConvertCoordinateOptions()
  : GeometryUtilsOptions(FastDictionaryInitializer())
{
  // Safe to pass a null context if we pass a null value
  Init(nullptr, JS::NullHandleValue);
}




bool
ConvertCoordinateOptions::InitIds(JSContext* cx, ConvertCoordinateOptionsAtoms* atomsCache)
{
  MOZ_ASSERT(reinterpret_cast<jsid*>(atomsCache)->isVoid());

  // Initialize these in reverse order so that any failure leaves the first one
  // uninitialized.
  if (!atomsCache->toBox_id.init(cx, "toBox") ||
      !atomsCache->fromBox_id.init(cx, "fromBox")) {
    return false;
  }
  return true;
}

bool
ConvertCoordinateOptions::Init(BindingCallContext& cx, JS::Handle<JS::Value> val, const char* sourceDescription, bool passedToJSImpl)
{
  // Passing a null JSContext is OK only if we're initing from null,
  // Since in that case we will not have to do any property gets
  // Also evaluate isNullOrUndefined in order to avoid false-positive
  // checkers by static analysis tools
  MOZ_ASSERT_IF(!cx, val.isNull() && val.isNullOrUndefined());
  ConvertCoordinateOptionsAtoms* atomsCache = nullptr;
  if (cx) {
    atomsCache = GetAtomCache<ConvertCoordinateOptionsAtoms>(cx);
    if (reinterpret_cast<jsid*>(atomsCache)->isVoid() &&
        !InitIds(cx, atomsCache)) {
      return false;
    }
  }

  // Per spec, we init the parent's members first
  if (!GeometryUtilsOptions::Init(cx, val)) {
    return false;
  }

  bool isNull = val.isNullOrUndefined();
  // We only need these if !isNull, in which case we have |cx|.
  Maybe<JS::Rooted<JSObject *> > object;
  Maybe<JS::Rooted<JS::Value> > temp;
  if (!isNull) {
    MOZ_ASSERT(cx);
    object.emplace(cx, &val.toObject());
    temp.emplace(cx);
  }
  if (!isNull) {
    if (!JS_GetPropertyById(cx, *object, atomsCache->fromBox_id, temp.ptr())) {
      return false;
    }
  }
  if (!isNull && !temp->isUndefined()) {
    {
      int index;
      if (!binding_detail::FindEnumStringIndex<true>(cx, temp.ref(),
                                                                         binding_detail::EnumStrings<CSSBoxType>::Values,
                                                                         "CSSBoxType", "'fromBox' member of ConvertCoordinateOptions",
                                                                         &index)) {
        return false;
      }
      MOZ_ASSERT(index >= 0);
      mFromBox = static_cast<CSSBoxType>(index);
    }
  } else {
    mFromBox = CSSBoxType::Border;
  }
  mIsAnyMemberPresent = true;

  if (!isNull) {
    if (!JS_GetPropertyById(cx, *object, atomsCache->toBox_id, temp.ptr())) {
      return false;
    }
  }
  if (!isNull && !temp->isUndefined()) {
    {
      int index;
      if (!binding_detail::FindEnumStringIndex<true>(cx, temp.ref(),
                                                                         binding_detail::EnumStrings<CSSBoxType>::Values,
                                                                         "CSSBoxType", "'toBox' member of ConvertCoordinateOptions",
                                                                         &index)) {
        return false;
      }
      MOZ_ASSERT(index >= 0);
      mToBox = static_cast<CSSBoxType>(index);
    }
  } else {
    mToBox = CSSBoxType::Border;
  }
  mIsAnyMemberPresent = true;
  return true;
}

bool
ConvertCoordinateOptions::Init(JSContext* cx_, JS::Handle<JS::Value> val, const char* sourceDescription, bool passedToJSImpl)
{
  // We don't want to use sourceDescription for our context here;
  // that's not really what it's formatted for.
  BindingCallContext cx(cx_, nullptr);
  return Init(cx, val, sourceDescription, passedToJSImpl);
}

void
ConvertCoordinateOptions::TraceDictionary(JSTracer* trc)
{
  GeometryUtilsOptions::TraceDictionary(trc);
}

ConvertCoordinateOptions&
ConvertCoordinateOptions::operator=(const ConvertCoordinateOptions& aOther)
{
  GeometryUtilsOptions::operator=(aOther);
  mFromBox = aOther.mFromBox;
  mToBox = aOther.mToBox;
  return *this;
}


} // namespace dom


} // namespace mozilla
