コード例 #1
0
void
GetEntryHelper::CompleteOperation(JSObject* aObj)
{
  MOZ_ASSERT(mParts.IsEmpty());

  if (mType == FileSystemDirectoryEntry::eGetFile) {
    RefPtr<File> file;
    if (NS_FAILED(UNWRAP_OBJECT(File, aObj, file))) {
      Error(NS_ERROR_DOM_TYPE_MISMATCH_ERR);
      return;
    }

    RefPtr<FileSystemFileEntry> entry =
      new FileSystemFileEntry(mParentEntry->GetParentObject(), file,
                              mParentEntry, mFileSystem);
    mSuccessCallback->HandleEvent(*entry);
    return;
  }

  MOZ_ASSERT(mType == FileSystemDirectoryEntry::eGetDirectory);

  RefPtr<Directory> directory;
  if (NS_FAILED(UNWRAP_OBJECT(Directory, aObj, directory))) {
    Error(NS_ERROR_DOM_TYPE_MISMATCH_ERR);
    return;
  }

  RefPtr<FileSystemDirectoryEntry> entry =
    new FileSystemDirectoryEntry(mParentEntry->GetParentObject(), directory,
                                 mParentEntry, mFileSystem);
  mSuccessCallback->HandleEvent(*entry);
}
コード例 #2
0
Promise*
WrapperPromiseCallback::GetDependentPromise()
{
  // Per spec, various algorithms like all() and race() are actually implemented
  // in terms of calling then() but passing it the resolve/reject functions that
  // are passed as arguments to function passed to the Promise constructor.
  // That will cause the promise in question to hold on to a
  // WrapperPromiseCallback, but the dependent promise should really be the one
  // whose constructor those functions came from, not the about-to-be-ignored
  // return value of "then".  So try to determine whether we're in that case and
  // if so go ahead and dig the dependent promise out of the function we have.
  JSObject* callable = mCallback->Callable();
  // Unwrap it, in case it's a cross-compartment wrapper.  Our caller here is
  // system, so it's really ok to just go and unwrap.
  callable = js::UncheckedUnwrap(callable);
  if (JS_IsNativeFunction(callable, Promise::JSCallback)) {
    JS::Value promiseVal =
      js::GetFunctionNativeReserved(callable, Promise::SLOT_PROMISE);
    Promise* promise;
    UNWRAP_OBJECT(Promise, &promiseVal.toObject(), promise);
    return promise;
  }

  if (mNextPromise) {
    return mNextPromise;
  }

  Promise* promise;
  if (NS_SUCCEEDED(UNWRAP_OBJECT(Promise, mNextPromiseObj, promise))) {
    return promise;
  }

  // Oh, well.
  return nullptr;
}
コード例 #3
0
bool
StructuredCloneHelper::WriteCallback(JSContext* aCx,
                                     JSStructuredCloneWriter* aWriter,
                                     JS::Handle<JSObject*> aObj)
{
  if (!mSupportsCloning) {
    return false;
  }

  // See if this is a File/Blob object.
  {
    Blob* blob = nullptr;
    if (NS_SUCCEEDED(UNWRAP_OBJECT(Blob, aObj, blob))) {
      BlobImpl* blobImpl = blob->Impl();
      if (JS_WriteUint32Pair(aWriter, SCTAG_DOM_BLOB,
                             mBlobImplArray.Length())) {
        mBlobImplArray.AppendElement(blobImpl);
        return true;
      }

      return false;
    }
  }

  {
    FileList* fileList = nullptr;
    if (NS_SUCCEEDED(UNWRAP_OBJECT(FileList, aObj, fileList))) {
      // A FileList is serialized writing the X number of elements and the offset
      // from mBlobImplArray. The Read will take X elements from mBlobImplArray
      // starting from the offset.
      if (!JS_WriteUint32Pair(aWriter, SCTAG_DOM_FILELIST,
                              fileList->Length()) ||
          !JS_WriteUint32Pair(aWriter, 0,
                              mBlobImplArray.Length())) {
        return false;
      }

      for (uint32_t i = 0; i < fileList->Length(); ++i) {
        mBlobImplArray.AppendElement(fileList->Item(i)->Impl());
      }

      return true;
    }
  }

  // See if this is an ImageBitmap object.
  {
    ImageBitmap* imageBitmap = nullptr;
    if (NS_SUCCEEDED(UNWRAP_OBJECT(ImageBitmap, aObj, imageBitmap))) {
      return ImageBitmap::WriteStructuredClone(aWriter,
                                               GetImages(),
                                               imageBitmap);
    }
  }

  return NS_DOMWriteStructuredClone(aCx, aWriter, aObj, nullptr);
}
コード例 #4
0
static bool
NativeHandlerCallback(JSContext* aCx, unsigned aArgc, JS::Value* aVp)
{
  JS::CallArgs args = CallArgsFromVp(aArgc, aVp);

  JS::Rooted<JS::Value> v(aCx,
                          js::GetFunctionNativeReserved(&args.callee(),
                                                        SLOT_NATIVEHANDLER));
  MOZ_ASSERT(v.isObject());

  PromiseNativeHandler* handler = nullptr;
  if (NS_FAILED(UNWRAP_OBJECT(PromiseNativeHandler, &v.toObject(),
                              handler))) {
    return Throw(aCx, NS_ERROR_UNEXPECTED);
  }

  v = js::GetFunctionNativeReserved(&args.callee(), SLOT_NATIVEHANDLER_TASK);
  NativeHandlerTask task = static_cast<NativeHandlerTask>(v.toInt32());

  if (task == NativeHandlerTask::Resolve) {
    handler->ResolvedCallback(aCx, args.get(0));
  } else {
    MOZ_ASSERT(task == NativeHandlerTask::Reject);
    handler->RejectedCallback(aCx, args.get(0));
  }

  return true;
}
コード例 #5
0
bool
StructuredCloneHelper::WriteTransferCallback(JSContext* aCx,
                                             JS::Handle<JSObject*> aObj,
                                             uint32_t* aTag,
                                             JS::TransferableOwnership* aOwnership,
                                             void** aContent,
                                             uint64_t* aExtraData)
{
  if (!mSupportsTransferring) {
    return false;
  }

  {
    MessagePortBase* port = nullptr;
    nsresult rv = UNWRAP_OBJECT(MessagePort, aObj, port);
    if (NS_SUCCEEDED(rv)) {
      // We use aExtraData to store the index of this new port identifier.
      *aExtraData = mPortIdentifiers.Length();
      MessagePortIdentifier* identifier = mPortIdentifiers.AppendElement();

      if (!port->CloneAndDisentangle(*identifier)) {
        return false;
      }

      *aTag = SCTAG_DOM_MAP_MESSAGEPORT;
      *aOwnership = JS::SCTAG_TMO_CUSTOM;
      *aContent = nullptr;

      return true;
    }
  }

  return false;
}
コード例 #6
0
bool
WriteTransfer(JSContext* aCx, JS::Handle<JSObject*> aObj, void* aClosure,
              uint32_t* aTag, JS::TransferableOwnership* aOwnership,
              void** aContent, uint64_t* aExtraData)
{
  MOZ_ASSERT(aClosure);

  auto* closure = static_cast<StructuredCloneClosureInternal*>(aClosure);

  MessagePortBase* port = nullptr;
  nsresult rv = UNWRAP_OBJECT(MessagePort, aObj, port);
  if (NS_FAILED(rv)) {
    return false;
  }

  if (closure->mTransferredPorts.Contains(port)) {
    // No duplicates.
    return false;
  }

  MessagePortIdentifier identifier;
  if (!port->CloneAndDisentangle(identifier)) {
    return false;
  }

  closure->mClosure.mMessagePortIdentifiers.AppendElement(identifier);
  closure->mTransferredPorts.AppendElement(port);

  *aTag = SCTAG_DOM_MAP_MESSAGEPORT;
  *aOwnership = JS::SCTAG_TMO_CUSTOM;
  *aContent = nullptr;
  *aExtraData = closure->mClosure.mMessagePortIdentifiers.Length() - 1;

  return true;
}
コード例 #7
0
ファイル: MessagePort.cpp プロジェクト: nixiValor/Waterfox
static bool
PostMessageTransferStructuredClone(JSContext* aCx,
                                   JS::Handle<JSObject*> aObj,
                                   void* aClosure,
                                   uint32_t* aTag,
                                   JS::TransferableOwnership* aOwnership,
                                   void** aContent,
                                   uint64_t *aExtraData)
{
  StructuredCloneInfo* scInfo = static_cast<StructuredCloneInfo*>(aClosure);
  NS_ASSERTION(scInfo, "Must have scInfo!");

  MessagePortBase *port = nullptr;
  nsresult rv = UNWRAP_OBJECT(MessagePort, aObj, port);
  if (NS_SUCCEEDED(rv)) {
    nsRefPtr<MessagePortBase> newPort;
    if (scInfo->mPorts.Get(port, getter_AddRefs(newPort))) {
      // No duplicate.
      return false;
    }

    newPort = port->Clone();
    scInfo->mPorts.Put(port, newPort);

    *aTag = SCTAG_DOM_MAP_MESSAGEPORT;
    *aOwnership = JS::SCTAG_TMO_CUSTOM;
    *aContent = newPort;
    *aExtraData = 0;

    return true;
  }

  return false;
}
コード例 #8
0
already_AddRefed<JSWindowActorChild> WindowGlobalChild::GetActor(
    const nsAString& aName, ErrorResult& aRv) {
  // Check if this actor has already been created, and return it if it has.
  if (mWindowActors.Contains(aName)) {
    return do_AddRef(mWindowActors.GetWeak(aName));
  }

  // Otherwise, we want to create a new instance of this actor. Call into the
  // JSWindowActorService to trigger construction.
  RefPtr<JSWindowActorService> actorSvc = JSWindowActorService::GetSingleton();
  if (!actorSvc) {
    return nullptr;
  }

  JS::RootedObject obj(RootingCx());
  actorSvc->ConstructActor(aName, /* aChildSide */ false, mBrowsingContext,
                           &obj, aRv);
  if (aRv.Failed()) {
    return nullptr;
  }

  // Unwrap our actor to a JSWindowActorChild object.
  RefPtr<JSWindowActorChild> actor;
  if (NS_FAILED(UNWRAP_OBJECT(JSWindowActorChild, &obj, actor))) {
    return nullptr;
  }

  MOZ_RELEASE_ASSERT(!actor->Manager(),
                     "mManager was already initialized once!");
  actor->Init(aName, this);
  mWindowActors.Put(aName, actor);
  return actor.forget();
}
コード例 #9
0
static Promise*
UnwrapPromise(JS::Handle<JSObject*> aPromise, ErrorResult& aRv)
{
  Promise* promise;
  if (NS_WARN_IF(NS_FAILED(UNWRAP_OBJECT(Promise, aPromise, promise)))) {
    aRv.ThrowTypeError<MSG_IS_NOT_PROMISE>(NS_LITERAL_STRING("Argument"));
    return nullptr;
  }
  return promise;
}
コード例 #10
0
ファイル: Promise.cpp プロジェクト: paulmadore/luckyde
Promise*
GetPromise(JSContext* aCx, JS::Handle<JSObject*> aFunc)
{
  JS::Value promiseVal = js::GetFunctionNativeReserved(aFunc, SLOT_PROMISE);

  MOZ_ASSERT(promiseVal.isObject());

  Promise* promise;
  UNWRAP_OBJECT(Promise, &promiseVal.toObject(), promise);
  return promise;
}
コード例 #11
0
Promise*
InvokePromiseFuncCallback::GetDependentPromise()
{
  Promise* promise;
  if (NS_SUCCEEDED(UNWRAP_OBJECT(Promise, mNextPromiseObj, promise))) {
    return promise;
  }

  // Oh, well.
  return nullptr;
}
コード例 #12
0
static nsGlobalWindow*
GetWindowFromGlobal(JSObject* aGlobal)
{
  nsGlobalWindow* win;
  if (NS_SUCCEEDED(UNWRAP_OBJECT(Window, aGlobal, win))) {
    return win;
  }
  XPCWrappedNative* wrapper = XPCWrappedNative::Get(aGlobal);
  nsCOMPtr<nsPIDOMWindow> piWin = do_QueryWrappedNative(wrapper);
  MOZ_ASSERT(piWin);
  return static_cast<nsGlobalWindow*>(piWin.get());
}
コード例 #13
0
NS_IMETHODIMP
WebVTTListener::OnRegion(JS::Handle<JS::Value> aRegion, JSContext* aCx)
{
  if (!aRegion.isObject()) {
    return NS_ERROR_FAILURE;
  }

  TextTrackRegion* region;
  nsresult rv = UNWRAP_OBJECT(VTTRegion, &aRegion.toObject(), region);
  NS_ENSURE_SUCCESS(rv, rv);

  mElement->mTrack->AddRegion(*region);

  return NS_OK;
}
コード例 #14
0
NS_IMETHODIMP
WebVTTListener::OnCue(JS::Handle<JS::Value> aCue, JSContext* aCx)
{
  if (!aCue.isObject()) {
    return NS_ERROR_FAILURE;
  }

  TextTrackCue* cue = nullptr;
  nsresult rv = UNWRAP_OBJECT(VTTCue, &aCue.toObject(), cue);
  NS_ENSURE_SUCCESS(rv, rv);

  cue->SetTrackElement(mElement);
  mElement->mTrack->AddCue(*cue);

  return NS_OK;
}
コード例 #15
0
// static
nsresult
IDBKeyRange::FromJSVal(JSContext* aCx,
                       JS::Handle<JS::Value> aVal,
                       IDBKeyRange** aKeyRange)
{
  MOZ_ASSERT_IF(!aCx, aVal.isUndefined());

  RefPtr<IDBKeyRange> keyRange;

  if (aVal.isNullOrUndefined()) {
    // undefined and null returns no IDBKeyRange.
    keyRange.forget(aKeyRange);
    return NS_OK;
  }

  JS::Rooted<JSObject*> obj(aCx, aVal.isObject() ? &aVal.toObject() : nullptr);
  bool isValidKey = aVal.isPrimitive();
  if (!isValidKey) {
    js::ESClass cls;
    if (!js::GetBuiltinClass(aCx, obj, &cls)) {
      return NS_ERROR_UNEXPECTED;
    }
    isValidKey = cls == js::ESClass::Array || cls == js::ESClass::Date;
  }
  if (isValidKey) {
    // A valid key returns an 'only' IDBKeyRange.
    keyRange = new IDBKeyRange(nullptr, false, false, true);

    nsresult rv = GetKeyFromJSVal(aCx, aVal, keyRange->Lower());
    if (NS_FAILED(rv)) {
      return rv;
    }
  }
  else {
    MOZ_ASSERT(aVal.isObject());
    // An object is not permitted unless it's another IDBKeyRange.
    if (NS_FAILED(UNWRAP_OBJECT(IDBKeyRange, obj, keyRange))) {
      return NS_ERROR_DOM_INDEXEDDB_DATA_ERR;
    }
  }

  keyRange.forget(aKeyRange);
  return NS_OK;
}
コード例 #16
0
ファイル: XPathExpression.cpp プロジェクト: bgrins/gecko-dev
already_AddRefed<XPathResult>
XPathExpression::EvaluateWithContext(JSContext* aCx,
                                     nsINode& aContextNode,
                                     uint32_t aContextPosition,
                                     uint32_t aContextSize,
                                     uint16_t aType,
                                     JS::Handle<JSObject*> aInResult,
                                     ErrorResult& aRv)
{
    RefPtr<XPathResult> inResult;
    if (aInResult) {
        nsresult rv = UNWRAP_OBJECT(XPathResult, aInResult, inResult);
        if (NS_FAILED(rv) && rv != NS_ERROR_XPC_BAD_CONVERT_JS) {
            aRv.Throw(rv);
            return nullptr;
        }
    }

    return EvaluateWithContext(aContextNode, aContextPosition, aContextSize,
                               aType, inResult, aRv);
}
コード例 #17
0
void
GetEntryHelper::ContinueRunning(JSObject* aObj)
{
  MOZ_ASSERT(!mParts.IsEmpty());

  RefPtr<Directory> directory;
  if (NS_FAILED(UNWRAP_OBJECT(Directory, aObj, directory))) {
    Error(NS_ERROR_DOM_TYPE_MISMATCH_ERR);
    return;
  }

  RefPtr<FileSystemDirectoryEntry> entry =
    new FileSystemDirectoryEntry(mParentEntry->GetParentObject(), directory,
                                 mParentEntry, mFileSystem);

  // Update the internal values.
  mParentEntry = entry;
  mDirectory = directory;

  Run();
}
コード例 #18
0
ファイル: Navigator.cpp プロジェクト: AOSC-Dev/Pale-Moon
static bool
GetDataStoresStructuredCloneCallbacksWrite(JSContext* aCx,
                                           JSStructuredCloneWriter* aWriter,
                                           JS::Handle<JSObject*> aObj,
                                           void* aClosure)
{
  AssertIsOnMainThread();

  PromiseWorkerProxy* proxy = static_cast<PromiseWorkerProxy*>(aClosure);
  NS_ASSERTION(proxy, "must have proxy!");

  if (!JS_WriteUint32Pair(aWriter, WORKER_DATA_STORES_TAG, 0)) {
    MOZ_ASSERT(false, "cannot write pair for WORKER_DATA_STORES_TAG!");
    return false;
  }

  JS::Rooted<JSObject*> storeObj(aCx, aObj);

  DataStore* store = nullptr;
  nsresult rv = UNWRAP_OBJECT(DataStore, storeObj, store);
  if (NS_FAILED(rv)) {
    MOZ_ASSERT(false, "cannot unwrap the DataStore object!");
    return false;
  }

  // We keep the data store alive here.
  proxy->StoreISupports(store);

  // Construct the nsMainThreadPtrHolder pointing to the data store.
  nsMainThreadPtrHolder<DataStore>* dataStoreholder =
    new nsMainThreadPtrHolder<DataStore>(store);

  // And write the dataStoreholder into the buffer.
  if (!JS_WriteBytes(aWriter, &dataStoreholder, sizeof(dataStoreholder))) {
    MOZ_ASSERT(false, "cannot write bytes for dataStoreholder!");
    return false;
  }

  return true;
}
コード例 #19
0
void
WrapperPromiseCallback::Call(JS::Handle<JS::Value> aValue)
{
  // AutoCxPusher and co. interact with xpconnect, which crashes on
  // workers. On workers we'll get the right context from
  // GetDefaultJSContextForThread(), and since there is only one context, we
  // don't need to push or pop it from the stack.
  JSContext* cx = nsContentUtils::GetDefaultJSContextForThread();

  Maybe<AutoCxPusher> pusher;
  if (NS_IsMainThread()) {
    pusher.construct(cx);
  }

  Maybe<JSAutoCompartment> ac;
  EnterCompartment(ac, cx, aValue);

  ErrorResult rv;

  // If invoking callback threw an exception, run resolver's reject with the
  // thrown exception as argument and the synchronous flag set.
  JS::Rooted<JS::Value> value(cx,
    mCallback->Call(aValue, rv, CallbackObject::eRethrowExceptions));

  rv.WouldReportJSException();

  if (rv.Failed() && rv.IsJSException()) {
    JS::Rooted<JS::Value> value(cx);
    rv.StealJSException(cx, &value);

    Maybe<JSAutoCompartment> ac2;
    EnterCompartment(ac2, cx, value);
    mNextPromise->RejectInternal(cx, value, Promise::SyncTask);
    return;
  }

  // If the return value is the same as the promise itself, throw TypeError.
  if (value.isObject()) {
    JS::Rooted<JSObject*> valueObj(cx, &value.toObject());
    Promise* returnedPromise;
    nsresult r = UNWRAP_OBJECT(Promise, valueObj, returnedPromise);

    if (NS_SUCCEEDED(r) && returnedPromise == mNextPromise) {
      const char* fileName = nullptr;
      uint32_t lineNumber = 0;

      // Try to get some information about the callback to report a sane error,
      // but don't try too hard (only deals with scripted functions).
      JS::Rooted<JSObject*> unwrapped(cx,
        js::CheckedUnwrap(mCallback->Callback()));

      if (unwrapped) {
        JSAutoCompartment ac(cx, unwrapped);
        if (JS_ObjectIsFunction(cx, unwrapped)) {
          JS::Rooted<JS::Value> asValue(cx, JS::ObjectValue(*unwrapped));
          JS::Rooted<JSFunction*> func(cx, JS_ValueToFunction(cx, asValue));

          MOZ_ASSERT(func);
          JSScript* script = JS_GetFunctionScript(cx, func);
          if (script) {
            fileName = JS_GetScriptFilename(cx, script);
            lineNumber = JS_GetScriptBaseLineNumber(cx, script);
          }
        }
      }

      // We're back in aValue's compartment here.
      JS::Rooted<JSString*> stack(cx, JS_GetEmptyString(JS_GetRuntime(cx)));
      JS::Rooted<JSString*> fn(cx, JS_NewStringCopyZ(cx, fileName));
      if (!fn) {
        // Out of memory. Promise will stay unresolved.
        JS_ClearPendingException(cx);
        return;
      }

      JS::Rooted<JSString*> message(cx,
        JS_NewStringCopyZ(cx,
          "then() cannot return same Promise that it resolves."));
      if (!message) {
        // Out of memory. Promise will stay unresolved.
        JS_ClearPendingException(cx);
        return;
      }

      JS::Rooted<JS::Value> typeError(cx);
      if (!JS::CreateTypeError(cx, stack, fn, lineNumber, 0,
                               nullptr, message, &typeError)) {
        // Out of memory. Promise will stay unresolved.
        JS_ClearPendingException(cx);
        return;
      }

      mNextPromise->RejectInternal(cx, typeError, Promise::SyncTask);
      return;
    }
  }

  // Otherwise, run resolver's resolve with value and the synchronous flag
  // set.
  Maybe<JSAutoCompartment> ac2;
  EnterCompartment(ac2, cx, value);
  mNextPromise->ResolveInternal(cx, value, Promise::SyncTask);
}
コード例 #20
0
void
WrapperPromiseCallback::Call(JSContext* aCx,
                             JS::Handle<JS::Value> aValue)
{
  JSAutoCompartment ac(aCx, mGlobal);
  JS::Rooted<JS::Value> value(aCx, aValue);
  if (!JS_WrapValue(aCx, &value)) {
    NS_WARNING("Failed to wrap value into the right compartment.");
    return;
  }

  ErrorResult rv;

  // If invoking callback threw an exception, run resolver's reject with the
  // thrown exception as argument and the synchronous flag set.
  JS::Rooted<JS::Value> retValue(aCx);
  mCallback->Call(value, &retValue, rv, CallbackObject::eRethrowExceptions);

  rv.WouldReportJSException();

  if (rv.Failed() && rv.IsJSException()) {
    JS::Rooted<JS::Value> value(aCx);
    rv.StealJSException(aCx, &value);

    if (!JS_WrapValue(aCx, &value)) {
      NS_WARNING("Failed to wrap value into the right compartment.");
      return;
    }

    mNextPromise->RejectInternal(aCx, value, Promise::SyncTask);
    return;
  }

  // If the return value is the same as the promise itself, throw TypeError.
  if (retValue.isObject()) {
    JS::Rooted<JSObject*> valueObj(aCx, &retValue.toObject());
    Promise* returnedPromise;
    nsresult r = UNWRAP_OBJECT(Promise, valueObj, returnedPromise);

    if (NS_SUCCEEDED(r) && returnedPromise == mNextPromise) {
      const char* fileName = nullptr;
      uint32_t lineNumber = 0;

      // Try to get some information about the callback to report a sane error,
      // but don't try too hard (only deals with scripted functions).
      JS::Rooted<JSObject*> unwrapped(aCx,
        js::CheckedUnwrap(mCallback->Callback()));

      if (unwrapped) {
        JSAutoCompartment ac(aCx, unwrapped);
        if (JS_ObjectIsFunction(aCx, unwrapped)) {
          JS::Rooted<JS::Value> asValue(aCx, JS::ObjectValue(*unwrapped));
          JS::Rooted<JSFunction*> func(aCx, JS_ValueToFunction(aCx, asValue));

          MOZ_ASSERT(func);
          JSScript* script = JS_GetFunctionScript(aCx, func);
          if (script) {
            fileName = JS_GetScriptFilename(script);
            lineNumber = JS_GetScriptBaseLineNumber(aCx, script);
          }
        }
      }

      // We're back in aValue's compartment here.
      JS::Rooted<JSString*> stack(aCx, JS_GetEmptyString(JS_GetRuntime(aCx)));
      JS::Rooted<JSString*> fn(aCx, JS_NewStringCopyZ(aCx, fileName));
      if (!fn) {
        // Out of memory. Promise will stay unresolved.
        JS_ClearPendingException(aCx);
        return;
      }

      JS::Rooted<JSString*> message(aCx,
        JS_NewStringCopyZ(aCx,
          "then() cannot return same Promise that it resolves."));
      if (!message) {
        // Out of memory. Promise will stay unresolved.
        JS_ClearPendingException(aCx);
        return;
      }

      JS::Rooted<JS::Value> typeError(aCx);
      if (!JS::CreateTypeError(aCx, stack, fn, lineNumber, 0,
                               nullptr, message, &typeError)) {
        // Out of memory. Promise will stay unresolved.
        JS_ClearPendingException(aCx);
        return;
      }

      mNextPromise->RejectInternal(aCx, typeError, Promise::SyncTask);
      return;
    }
  }

  // Otherwise, run resolver's resolve with value and the synchronous flag
  // set.
  if (!JS_WrapValue(aCx, &retValue)) {
    NS_WARNING("Failed to wrap value into the right compartment.");
    return;
  }

  mNextPromise->ResolveInternal(aCx, retValue, Promise::SyncTask);
}