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

#include <type_traits>
#include "AtomList.h"
#include "MainThreadUtils.h"
#include "UnderlyingSinkBinding.h"
#include "js/CallAndConstruct.h"
#include "js/Exception.h"
#include "js/MapAndSet.h"
#include "js/Object.h"
#include "js/PropertyAndElement.h"
#include "js/PropertyDescriptor.h"
#include "js/experimental/JitInfo.h"
#include "mozilla/OwningNonNull.h"
#include "mozilla/dom/BindingCallContext.h"
#include "mozilla/dom/BindingUtils.h"
#include "mozilla/dom/NonRefcountedDOMObject.h"
#include "mozilla/dom/Promise.h"
#include "mozilla/dom/ScriptSettings.h"
#include "mozilla/dom/ToJSValue.h"
#include "mozilla/dom/WritableStreamDefaultController.h"

namespace mozilla::dom {

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



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



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

  // Initialize these in reverse order so that any failure leaves the first one
  // uninitialized.
  if (!atomsCache->write_id.init(cx, "write") ||
      !atomsCache->type_id.init(cx, "type") ||
      !atomsCache->start_id.init(cx, "start") ||
      !atomsCache->close_id.init(cx, "close") ||
      !atomsCache->abort_id.init(cx, "abort")) {
    return false;
  }
  return true;
}

bool
UnderlyingSink::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());
  UnderlyingSinkAtoms* atomsCache = nullptr;
  if (cx) {
    atomsCache = GetAtomCache<UnderlyingSinkAtoms>(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 (!JS_GetPropertyById(cx, *object, atomsCache->abort_id, temp.ptr())) {
      return false;
    }
  }
  if (!isNull && !temp->isUndefined()) {
    mAbort.Construct();
    if (temp.ref().isObject()) {
      if (JS::IsCallable(&temp.ref().toObject())) {
      { // scope for tempRoot and tempGlobalRoot if needed
        JS::Rooted<JSObject*> tempRoot(cx, &temp.ref().toObject());
        JS::Rooted<JSObject*> tempGlobalRoot(cx, JS::CurrentGlobalOrNull(cx));
        (mAbort.Value()) = new UnderlyingSinkAbortCallback(cx, tempRoot, tempGlobalRoot, GetIncumbentGlobal());
      }
      } else {
        cx.ThrowErrorMessage<MSG_NOT_CALLABLE>("'abort' member of UnderlyingSink");
        return false;
      }
    } else {
      cx.ThrowErrorMessage<MSG_NOT_OBJECT>("'abort' member of UnderlyingSink");
      return false;
    }
    mIsAnyMemberPresent = true;
  }

  if (!isNull) {
    if (!JS_GetPropertyById(cx, *object, atomsCache->close_id, temp.ptr())) {
      return false;
    }
  }
  if (!isNull && !temp->isUndefined()) {
    mClose.Construct();
    if (temp.ref().isObject()) {
      if (JS::IsCallable(&temp.ref().toObject())) {
      { // scope for tempRoot and tempGlobalRoot if needed
        JS::Rooted<JSObject*> tempRoot(cx, &temp.ref().toObject());
        JS::Rooted<JSObject*> tempGlobalRoot(cx, JS::CurrentGlobalOrNull(cx));
        (mClose.Value()) = new UnderlyingSinkCloseCallback(cx, tempRoot, tempGlobalRoot, GetIncumbentGlobal());
      }
      } else {
        cx.ThrowErrorMessage<MSG_NOT_CALLABLE>("'close' member of UnderlyingSink");
        return false;
      }
    } else {
      cx.ThrowErrorMessage<MSG_NOT_OBJECT>("'close' member of UnderlyingSink");
      return false;
    }
    mIsAnyMemberPresent = true;
  }

  if (!isNull) {
    if (!JS_GetPropertyById(cx, *object, atomsCache->start_id, temp.ptr())) {
      return false;
    }
  }
  if (!isNull && !temp->isUndefined()) {
    mStart.Construct();
    if (temp.ref().isObject()) {
      if (JS::IsCallable(&temp.ref().toObject())) {
      { // scope for tempRoot and tempGlobalRoot if needed
        JS::Rooted<JSObject*> tempRoot(cx, &temp.ref().toObject());
        JS::Rooted<JSObject*> tempGlobalRoot(cx, JS::CurrentGlobalOrNull(cx));
        (mStart.Value()) = new UnderlyingSinkStartCallback(cx, tempRoot, tempGlobalRoot, GetIncumbentGlobal());
      }
      } else {
        cx.ThrowErrorMessage<MSG_NOT_CALLABLE>("'start' member of UnderlyingSink");
        return false;
      }
    } else {
      cx.ThrowErrorMessage<MSG_NOT_OBJECT>("'start' member of UnderlyingSink");
      return false;
    }
    mIsAnyMemberPresent = true;
  }

  if (!isNull) {
    if (!JS_GetPropertyById(cx, *object, atomsCache->type_id, temp.ptr())) {
      return false;
    }
  }
  if (!isNull && !temp->isUndefined()) {
#ifdef __clang__
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunreachable-code"
#pragma clang diagnostic ignored "-Wunreachable-code-return"
#endif // __clang__
    if ((passedToJSImpl) && !CallerSubsumes(temp.ref())) {
      cx.ThrowErrorMessage<MSG_PERMISSION_DENIED_TO_PASS_ARG>("'type' member of UnderlyingSink");
      return false;
    }
#ifdef __clang__
#pragma clang diagnostic pop
#endif // __clang__
    mType = temp.ref();
  } else {
    mType = JS::UndefinedValue();
  }
  mIsAnyMemberPresent = true;

  if (!isNull) {
    if (!JS_GetPropertyById(cx, *object, atomsCache->write_id, temp.ptr())) {
      return false;
    }
  }
  if (!isNull && !temp->isUndefined()) {
    mWrite.Construct();
    if (temp.ref().isObject()) {
      if (JS::IsCallable(&temp.ref().toObject())) {
      { // scope for tempRoot and tempGlobalRoot if needed
        JS::Rooted<JSObject*> tempRoot(cx, &temp.ref().toObject());
        JS::Rooted<JSObject*> tempGlobalRoot(cx, JS::CurrentGlobalOrNull(cx));
        (mWrite.Value()) = new UnderlyingSinkWriteCallback(cx, tempRoot, tempGlobalRoot, GetIncumbentGlobal());
      }
      } else {
        cx.ThrowErrorMessage<MSG_NOT_CALLABLE>("'write' member of UnderlyingSink");
        return false;
      }
    } else {
      cx.ThrowErrorMessage<MSG_NOT_OBJECT>("'write' member of UnderlyingSink");
      return false;
    }
    mIsAnyMemberPresent = true;
  }
  return true;
}

bool
UnderlyingSink::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
UnderlyingSink::TraceDictionary(JSTracer* trc)
{
  JS::TraceRoot(trc, &mType, "UnderlyingSink.mType");
}




MOZ_CAN_RUN_SCRIPT already_AddRefed<Promise>
UnderlyingSinkAbortCallback::Call(BindingCallContext& cx, JS::Handle<JS::Value> aThisVal, const Optional<JS::Handle<JS::Value>>& reason, ErrorResult& aRv)
{
  JS::Rooted<JS::Value> rval(cx);
  JS::RootedVector<JS::Value> argv(cx);
  if (!argv.resize(1)) {
    // That threw an exception on the JSContext, and our CallSetup will do
    // the right thing with that.
    return nullptr;
  }
  unsigned argc = 1;

  do {
    if (reason.WasPassed()) {
      JS::ExposeValueToActiveJS(reason.Value());
      argv[0].set(reason.Value());
      if (!MaybeWrapValue(cx, argv[0])) {
        // Convert exception to a rejected promise.
        // See https://heycam.github.io/webidl/#call-a-user-objects-operation
        // step 10 and step 15.5.
        return CreateRejectedPromiseFromThrownException(cx, aRv);
      }
      break;
    } else if (argc == 1) {
      // This is our current trailing argument; reduce argc
      --argc;
    } else {
      argv[0].setUndefined();
    }
  } while (false);

  JS::Rooted<JS::Value> callable(cx, JS::ObjectValue(*mCallback));
  if (!JS::Call(cx, aThisVal, callable,
                JS::HandleValueArray::subarray(argv, 0, argc), &rval)) {
    // Convert exception to a rejected promise.
    // See https://heycam.github.io/webidl/#call-a-user-objects-operation
    // step 12 and step 15.5.
    return CreateRejectedPromiseFromThrownException(cx, aRv);
  }
  RefPtr<Promise> rvalDecl;
  { // Scope for our GlobalObject, FastErrorResult, JSAutoRealm,
    // etc.

    JS::Rooted<JSObject*> globalObj(cx);
    // We basically want our entry global here.  Play it safe
    // and use GetEntryGlobal() to get it, with whatever
    // principal-clamping it ends up doing.
    globalObj = GetEntryGlobal()->GetGlobalJSObject();
    JSAutoRealm ar(cx, globalObj);
    GlobalObject promiseGlobal(cx, globalObj);
    if (promiseGlobal.Failed()) {
      aRv.Throw(NS_ERROR_UNEXPECTED);
      return nullptr;
    }

    JS::Rooted<JS::Value> valueToResolve(cx, rval);
    if (!JS_WrapValue(cx, &valueToResolve)) {
      aRv.Throw(NS_ERROR_UNEXPECTED);
      return nullptr;
    }
    binding_detail::FastErrorResult promiseRv;
    nsCOMPtr<nsIGlobalObject> global =
      do_QueryInterface(promiseGlobal.GetAsSupports());
    if (!global) {
      promiseRv.Throw(NS_ERROR_UNEXPECTED);
      MOZ_ALWAYS_TRUE(promiseRv.MaybeSetPendingException(cx));
      aRv.Throw(NS_ERROR_UNEXPECTED);
      return nullptr;
    }
    rvalDecl = Promise::Resolve(global, cx, valueToResolve,
                                    promiseRv);
    if (promiseRv.MaybeSetPendingException(cx)) {
      aRv.Throw(NS_ERROR_UNEXPECTED);
      return nullptr;
    }
  }
  return rvalDecl.forget();
}



MOZ_CAN_RUN_SCRIPT already_AddRefed<Promise>
UnderlyingSinkCloseCallback::Call(BindingCallContext& cx, JS::Handle<JS::Value> aThisVal, ErrorResult& aRv)
{
  JS::Rooted<JS::Value> rval(cx);

  JS::Rooted<JS::Value> callable(cx, JS::ObjectValue(*mCallback));
  if (!JS::Call(cx, aThisVal, callable,
                JS::HandleValueArray::empty(), &rval)) {
    // Convert exception to a rejected promise.
    // See https://heycam.github.io/webidl/#call-a-user-objects-operation
    // step 12 and step 15.5.
    return CreateRejectedPromiseFromThrownException(cx, aRv);
  }
  RefPtr<Promise> rvalDecl;
  { // Scope for our GlobalObject, FastErrorResult, JSAutoRealm,
    // etc.

    JS::Rooted<JSObject*> globalObj(cx);
    // We basically want our entry global here.  Play it safe
    // and use GetEntryGlobal() to get it, with whatever
    // principal-clamping it ends up doing.
    globalObj = GetEntryGlobal()->GetGlobalJSObject();
    JSAutoRealm ar(cx, globalObj);
    GlobalObject promiseGlobal(cx, globalObj);
    if (promiseGlobal.Failed()) {
      aRv.Throw(NS_ERROR_UNEXPECTED);
      return nullptr;
    }

    JS::Rooted<JS::Value> valueToResolve(cx, rval);
    if (!JS_WrapValue(cx, &valueToResolve)) {
      aRv.Throw(NS_ERROR_UNEXPECTED);
      return nullptr;
    }
    binding_detail::FastErrorResult promiseRv;
    nsCOMPtr<nsIGlobalObject> global =
      do_QueryInterface(promiseGlobal.GetAsSupports());
    if (!global) {
      promiseRv.Throw(NS_ERROR_UNEXPECTED);
      MOZ_ALWAYS_TRUE(promiseRv.MaybeSetPendingException(cx));
      aRv.Throw(NS_ERROR_UNEXPECTED);
      return nullptr;
    }
    rvalDecl = Promise::Resolve(global, cx, valueToResolve,
                                    promiseRv);
    if (promiseRv.MaybeSetPendingException(cx)) {
      aRv.Throw(NS_ERROR_UNEXPECTED);
      return nullptr;
    }
  }
  return rvalDecl.forget();
}



MOZ_CAN_RUN_SCRIPT void
UnderlyingSinkStartCallback::Call(BindingCallContext& cx, JS::Handle<JS::Value> aThisVal, WritableStreamDefaultController& controller, JS::MutableHandle<JS::Value> aRetVal, ErrorResult& aRv)
{
  JS::Rooted<JS::Value> rval(cx);
  JS::RootedVector<JS::Value> argv(cx);
  if (!argv.resize(1)) {
    // That threw an exception on the JSContext, and our CallSetup will do
    // the right thing with that.
    return;
  }
  unsigned argc = 1;

  do {
    if (!GetOrCreateDOMReflector(cx, controller, argv[0])) {
      MOZ_ASSERT(JS_IsExceptionPending(cx));
      aRv.Throw(NS_ERROR_UNEXPECTED);
      return;
    }
    break;
  } while (false);

  JS::Rooted<JS::Value> callable(cx, JS::ObjectValue(*mCallback));
  if (!JS::Call(cx, aThisVal, callable,
                JS::HandleValueArray::subarray(argv, 0, argc), &rval)) {
    aRv.NoteJSContextException(cx);
    return;
  }
  JS::Rooted<JS::Value> rvalDecl(cx);
#ifdef __clang__
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunreachable-code"
#pragma clang diagnostic ignored "-Wunreachable-code-return"
#endif // __clang__
  if ((false) && !CallerSubsumes(rval)) {
    cx.ThrowErrorMessage<MSG_PERMISSION_DENIED_TO_PASS_ARG>("return value of UnderlyingSinkStartCallback");
    aRv.Throw(NS_ERROR_UNEXPECTED);
    return;
  }
#ifdef __clang__
#pragma clang diagnostic pop
#endif // __clang__
  rvalDecl = rval;
  aRetVal.set(rvalDecl);
}



MOZ_CAN_RUN_SCRIPT already_AddRefed<Promise>
UnderlyingSinkWriteCallback::Call(BindingCallContext& cx, JS::Handle<JS::Value> aThisVal, JS::Handle<JS::Value> chunk, WritableStreamDefaultController& controller, ErrorResult& aRv)
{
  JS::Rooted<JS::Value> rval(cx);
  JS::RootedVector<JS::Value> argv(cx);
  if (!argv.resize(2)) {
    // That threw an exception on the JSContext, and our CallSetup will do
    // the right thing with that.
    return nullptr;
  }
  unsigned argc = 2;

  do {
    if (!GetOrCreateDOMReflector(cx, controller, argv[1])) {
      MOZ_ASSERT(JS_IsExceptionPending(cx));
      // Convert exception to a rejected promise.
      // See https://heycam.github.io/webidl/#call-a-user-objects-operation
      // step 10 and step 15.5.
      return CreateRejectedPromiseFromThrownException(cx, aRv);
    }
    break;
  } while (false);

  do {
    JS::ExposeValueToActiveJS(chunk);
    argv[0].set(chunk);
    if (!MaybeWrapValue(cx, argv[0])) {
      // Convert exception to a rejected promise.
      // See https://heycam.github.io/webidl/#call-a-user-objects-operation
      // step 10 and step 15.5.
      return CreateRejectedPromiseFromThrownException(cx, aRv);
    }
    break;
  } while (false);

  JS::Rooted<JS::Value> callable(cx, JS::ObjectValue(*mCallback));
  if (!JS::Call(cx, aThisVal, callable,
                JS::HandleValueArray::subarray(argv, 0, argc), &rval)) {
    // Convert exception to a rejected promise.
    // See https://heycam.github.io/webidl/#call-a-user-objects-operation
    // step 12 and step 15.5.
    return CreateRejectedPromiseFromThrownException(cx, aRv);
  }
  RefPtr<Promise> rvalDecl;
  { // Scope for our GlobalObject, FastErrorResult, JSAutoRealm,
    // etc.

    JS::Rooted<JSObject*> globalObj(cx);
    // We basically want our entry global here.  Play it safe
    // and use GetEntryGlobal() to get it, with whatever
    // principal-clamping it ends up doing.
    globalObj = GetEntryGlobal()->GetGlobalJSObject();
    JSAutoRealm ar(cx, globalObj);
    GlobalObject promiseGlobal(cx, globalObj);
    if (promiseGlobal.Failed()) {
      aRv.Throw(NS_ERROR_UNEXPECTED);
      return nullptr;
    }

    JS::Rooted<JS::Value> valueToResolve(cx, rval);
    if (!JS_WrapValue(cx, &valueToResolve)) {
      aRv.Throw(NS_ERROR_UNEXPECTED);
      return nullptr;
    }
    binding_detail::FastErrorResult promiseRv;
    nsCOMPtr<nsIGlobalObject> global =
      do_QueryInterface(promiseGlobal.GetAsSupports());
    if (!global) {
      promiseRv.Throw(NS_ERROR_UNEXPECTED);
      MOZ_ALWAYS_TRUE(promiseRv.MaybeSetPendingException(cx));
      aRv.Throw(NS_ERROR_UNEXPECTED);
      return nullptr;
    }
    rvalDecl = Promise::Resolve(global, cx, valueToResolve,
                                    promiseRv);
    if (promiseRv.MaybeSetPendingException(cx)) {
      aRv.Throw(NS_ERROR_UNEXPECTED);
      return nullptr;
    }
  }
  return rvalDecl.forget();
}



} // namespace mozilla::dom
