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

#include <type_traits>
#include "AtomList.h"
#include "MainThreadUtils.h"
#include "UnderlyingSourceBinding.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/PrimitiveConversions.h"
#include "mozilla/dom/Promise.h"
#include "mozilla/dom/ReadableByteStreamController.h"
#include "mozilla/dom/ReadableStreamDefaultController.h"
#include "mozilla/dom/ScriptSettings.h"
#include "mozilla/dom/ToJSValue.h"

namespace mozilla::dom {

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


void
ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback& aCallback, OwningReadableStreamDefaultControllerOrReadableByteStreamController& aUnion, const char* aName, uint32_t aFlags)
{
  if (aUnion.IsReadableStreamDefaultController()) {
    ImplCycleCollectionTraverse(aCallback, aUnion.GetAsReadableStreamDefaultController(), "mReadableStreamDefaultController", aFlags);
  } else if (aUnion.IsReadableByteStreamController()) {
    ImplCycleCollectionTraverse(aCallback, aUnion.GetAsReadableByteStreamController(), "mReadableByteStreamController", aFlags);
  }
}


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


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

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







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

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







bool
ReadableStreamDefaultControllerOrReadableByteStreamController::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 = !TrySetToReadableStreamDefaultController(cx, value, tryNext, passedToJSImpl)) || !tryNext ||
           (failed = !TrySetToReadableByteStreamController(cx, value, tryNext, passedToJSImpl)) || !tryNext;
  }
  if (failed) {
    return false;
  }
  if (!done) {
    cx.ThrowErrorMessage<MSG_NOT_IN_UNION>(sourceDescription, "ReadableStreamDefaultController, ReadableByteStreamController");
    return false;
  }
  return true;
}

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


bool
ReadableStreamDefaultControllerOrReadableByteStreamController::ToJSVal(JSContext* cx, JS::Handle<JSObject*> scopeObj, JS::MutableHandle<JS::Value> rval) const
{
  switch (mType) {
    case eUninitialized: {
      return false;
    }
    case eReadableStreamDefaultController: {
      if (!GetOrCreateDOMReflector(cx, mValue.mReadableStreamDefaultController.Value(), rval)) {
        MOZ_ASSERT(JS_IsExceptionPending(cx));
        return false;
      }
      return true;
    }
    case eReadableByteStreamController: {
      if (!GetOrCreateDOMReflector(cx, mValue.mReadableByteStreamController.Value(), rval)) {
        MOZ_ASSERT(JS_IsExceptionPending(cx));
        return false;
      }
      return true;
    }
    default: {
      return false;
    }
  }
}



OwningReadableStreamDefaultControllerOrReadableByteStreamController::OwningReadableStreamDefaultControllerOrReadableByteStreamController(OwningReadableStreamDefaultControllerOrReadableByteStreamController&& aOther)
  : mType(eUninitialized)
{
  switch (aOther.mType) {
    case eUninitialized: {
      MOZ_ASSERT(mType == eUninitialized,
                 "We need to destroy ourselves?");
      break;
    }
    case eReadableStreamDefaultController: {
      mType = eReadableStreamDefaultController;
      mValue.mReadableStreamDefaultController.SetValue(std::move(aOther.mValue.mReadableStreamDefaultController.Value()));
      break;
    }
    case eReadableByteStreamController: {
      mType = eReadableByteStreamController;
      mValue.mReadableByteStreamController.SetValue(std::move(aOther.mValue.mReadableByteStreamController.Value()));
      break;
    }
  }
}



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

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

[[nodiscard]] OwningNonNull<mozilla::dom::ReadableStreamDefaultController>&
OwningReadableStreamDefaultControllerOrReadableByteStreamController::RawSetAsReadableStreamDefaultController()
{
  if (mType == eReadableStreamDefaultController) {
    return mValue.mReadableStreamDefaultController.Value();
  }
  MOZ_ASSERT(mType == eUninitialized);
  mType = eReadableStreamDefaultController;
  return mValue.mReadableStreamDefaultController.SetValue();
}

[[nodiscard]] OwningNonNull<mozilla::dom::ReadableStreamDefaultController>&
OwningReadableStreamDefaultControllerOrReadableByteStreamController::SetAsReadableStreamDefaultController()
{
  if (mType == eReadableStreamDefaultController) {
    return mValue.mReadableStreamDefaultController.Value();
  }
  Uninit();
  mType = eReadableStreamDefaultController;
  return mValue.mReadableStreamDefaultController.SetValue();
}


void
OwningReadableStreamDefaultControllerOrReadableByteStreamController::DestroyReadableStreamDefaultController()
{
  MOZ_RELEASE_ASSERT(IsReadableStreamDefaultController(), "Wrong type!");
  mValue.mReadableStreamDefaultController.Destroy();
  mType = eUninitialized;
}



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

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

[[nodiscard]] OwningNonNull<mozilla::dom::ReadableByteStreamController>&
OwningReadableStreamDefaultControllerOrReadableByteStreamController::RawSetAsReadableByteStreamController()
{
  if (mType == eReadableByteStreamController) {
    return mValue.mReadableByteStreamController.Value();
  }
  MOZ_ASSERT(mType == eUninitialized);
  mType = eReadableByteStreamController;
  return mValue.mReadableByteStreamController.SetValue();
}

[[nodiscard]] OwningNonNull<mozilla::dom::ReadableByteStreamController>&
OwningReadableStreamDefaultControllerOrReadableByteStreamController::SetAsReadableByteStreamController()
{
  if (mType == eReadableByteStreamController) {
    return mValue.mReadableByteStreamController.Value();
  }
  Uninit();
  mType = eReadableByteStreamController;
  return mValue.mReadableByteStreamController.SetValue();
}


void
OwningReadableStreamDefaultControllerOrReadableByteStreamController::DestroyReadableByteStreamController()
{
  MOZ_RELEASE_ASSERT(IsReadableByteStreamController(), "Wrong type!");
  mValue.mReadableByteStreamController.Destroy();
  mType = eUninitialized;
}



bool
OwningReadableStreamDefaultControllerOrReadableByteStreamController::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 = !TrySetToReadableStreamDefaultController(cx, value, tryNext, passedToJSImpl)) || !tryNext ||
           (failed = !TrySetToReadableByteStreamController(cx, value, tryNext, passedToJSImpl)) || !tryNext;
  }
  if (failed) {
    return false;
  }
  if (!done) {
    cx.ThrowErrorMessage<MSG_NOT_IN_UNION>(sourceDescription, "ReadableStreamDefaultController, ReadableByteStreamController");
    return false;
  }
  return true;
}

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

void
OwningReadableStreamDefaultControllerOrReadableByteStreamController::Uninit()
{
  switch (mType) {
    case eUninitialized: {
      break;
    }
    case eReadableStreamDefaultController: {
      DestroyReadableStreamDefaultController();
      break;
    }
    case eReadableByteStreamController: {
      DestroyReadableByteStreamController();
      break;
    }
  }
}

bool
OwningReadableStreamDefaultControllerOrReadableByteStreamController::ToJSVal(JSContext* cx, JS::Handle<JSObject*> scopeObj, JS::MutableHandle<JS::Value> rval) const
{
  switch (mType) {
    case eUninitialized: {
      return false;
    }
    case eReadableStreamDefaultController: {
      if (!GetOrCreateDOMReflector(cx, mValue.mReadableStreamDefaultController.Value(), rval)) {
        MOZ_ASSERT(JS_IsExceptionPending(cx));
        return false;
      }
      return true;
    }
    case eReadableByteStreamController: {
      if (!GetOrCreateDOMReflector(cx, mValue.mReadableByteStreamController.Value(), rval)) {
        MOZ_ASSERT(JS_IsExceptionPending(cx));
        return false;
      }
      return true;
    }
    default: {
      return false;
    }
  }
}

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


OwningReadableStreamDefaultControllerOrReadableByteStreamController&
OwningReadableStreamDefaultControllerOrReadableByteStreamController::operator=(const OwningReadableStreamDefaultControllerOrReadableByteStreamController& aOther)
{
  switch (aOther.mType) {
    case eUninitialized: {
      MOZ_ASSERT(mType == eUninitialized,
                 "We need to destroy ourselves?");
      break;
    }
    case eReadableStreamDefaultController: {
      SetAsReadableStreamDefaultController() = aOther.GetAsReadableStreamDefaultController();
      break;
    }
    case eReadableByteStreamController: {
      SetAsReadableByteStreamController() = aOther.GetAsReadableByteStreamController();
      break;
    }
  }
  return *this;
}



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



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

  // Initialize these in reverse order so that any failure leaves the first one
  // uninitialized.
  if (!atomsCache->type_id.init(cx, "type") ||
      !atomsCache->start_id.init(cx, "start") ||
      !atomsCache->pull_id.init(cx, "pull") ||
      !atomsCache->cancel_id.init(cx, "cancel") ||
      !atomsCache->autoAllocateChunkSize_id.init(cx, "autoAllocateChunkSize")) {
    return false;
  }
  return true;
}

bool
UnderlyingSource::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());
  UnderlyingSourceAtoms* atomsCache = nullptr;
  if (cx) {
    atomsCache = GetAtomCache<UnderlyingSourceAtoms>(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->autoAllocateChunkSize_id, temp.ptr())) {
      return false;
    }
  }
  if (!isNull && !temp->isUndefined()) {
    mAutoAllocateChunkSize.Construct();
    if (!ValueToPrimitive<uint64_t, eEnforceRange>(cx, temp.ref(), "'autoAllocateChunkSize' member of UnderlyingSource", &(mAutoAllocateChunkSize.Value()))) {
      return false;
    }
    mIsAnyMemberPresent = true;
  }

  if (!isNull) {
    if (!JS_GetPropertyById(cx, *object, atomsCache->cancel_id, temp.ptr())) {
      return false;
    }
  }
  if (!isNull && !temp->isUndefined()) {
    mCancel.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));
        (mCancel.Value()) = new UnderlyingSourceCancelCallback(cx, tempRoot, tempGlobalRoot, GetIncumbentGlobal());
      }
      } else {
        cx.ThrowErrorMessage<MSG_NOT_CALLABLE>("'cancel' member of UnderlyingSource");
        return false;
      }
    } else {
      cx.ThrowErrorMessage<MSG_NOT_OBJECT>("'cancel' member of UnderlyingSource");
      return false;
    }
    mIsAnyMemberPresent = true;
  }

  if (!isNull) {
    if (!JS_GetPropertyById(cx, *object, atomsCache->pull_id, temp.ptr())) {
      return false;
    }
  }
  if (!isNull && !temp->isUndefined()) {
    mPull.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));
        (mPull.Value()) = new UnderlyingSourcePullCallback(cx, tempRoot, tempGlobalRoot, GetIncumbentGlobal());
      }
      } else {
        cx.ThrowErrorMessage<MSG_NOT_CALLABLE>("'pull' member of UnderlyingSource");
        return false;
      }
    } else {
      cx.ThrowErrorMessage<MSG_NOT_OBJECT>("'pull' member of UnderlyingSource");
      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 UnderlyingSourceStartCallback(cx, tempRoot, tempGlobalRoot, GetIncumbentGlobal());
      }
      } else {
        cx.ThrowErrorMessage<MSG_NOT_CALLABLE>("'start' member of UnderlyingSource");
        return false;
      }
    } else {
      cx.ThrowErrorMessage<MSG_NOT_OBJECT>("'start' member of UnderlyingSource");
      return false;
    }
    mIsAnyMemberPresent = true;
  }

  if (!isNull) {
    if (!JS_GetPropertyById(cx, *object, atomsCache->type_id, temp.ptr())) {
      return false;
    }
  }
  if (!isNull && !temp->isUndefined()) {
    mType.Construct();
    {
      int index;
      if (!binding_detail::FindEnumStringIndex<true>(cx, temp.ref(),
                                                                         binding_detail::EnumStrings<ReadableStreamType>::Values,
                                                                         "ReadableStreamType", "'type' member of UnderlyingSource",
                                                                         &index)) {
        return false;
      }
      MOZ_ASSERT(index >= 0);
      (mType.Value()) = static_cast<ReadableStreamType>(index);
    }
    mIsAnyMemberPresent = true;
  }
  return true;
}

bool
UnderlyingSource::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
UnderlyingSource::TraceDictionary(JSTracer* trc)
{
}




MOZ_CAN_RUN_SCRIPT already_AddRefed<Promise>
UnderlyingSourceCancelCallback::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>
UnderlyingSourcePullCallback::Call(BindingCallContext& cx, JS::Handle<JS::Value> aThisVal, const ReadableStreamDefaultControllerOrReadableByteStreamController& controller, 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 {
    JS::Rooted<JSObject*> callbackObj(cx, CallbackKnownNotGray());
    if (!controller.ToJSVal(cx, callbackObj, 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();
}



MOZ_CAN_RUN_SCRIPT void
UnderlyingSourceStartCallback::Call(BindingCallContext& cx, JS::Handle<JS::Value> aThisVal, const ReadableStreamDefaultControllerOrReadableByteStreamController& 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 {
    JS::Rooted<JSObject*> callbackObj(cx, CallbackKnownNotGray());
    if (!controller.ToJSVal(cx, callbackObj, argv[0])) {
      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 UnderlyingSourceStartCallback");
    aRv.Throw(NS_ERROR_UNEXPECTED);
    return;
  }
#ifdef __clang__
#pragma clang diagnostic pop
#endif // __clang__
  rvalDecl = rval;
  aRetVal.set(rvalDecl);
}



} // namespace mozilla::dom
