bool response_promise_then_handler(JSContext *cx, HandleObject event, HandleValue extra,
                                   CallArgs args) {
  // Step 10.1
  // Note: the `then` handler is only invoked after all Promise resolution has
  // happened. (Even if there were multiple Promises to unwrap first.) That
  // means that at this point we're guaranteed to have the final value instead
  // of a Promise wrapping it, so either the value is a Response, or we have to
  // bail.
  if (!Response::is_instance(args.get(0))) {
    JS_ReportErrorUTF8(cx, "FetchEvent#respondWith must be called with a Response "
                           "object or a Promise resolving to a Response object as "
                           "the first argument");
    RootedObject rejection(cx, PromiseRejectedWithPendingError(cx));
    if (!rejection)
      return false;
    args.rval().setObject(*rejection);
    return respondWithError(cx, event);
  }

  // Step 10.2 (very roughly: the way we handle responses and their bodies is
  // very different.)
  RootedObject response_obj(cx, &args[0].toObject());

  // Ensure that all headers are stored client-side, so we retain access to them
  // after sending the response off.
  if (Response::is_upstream(response_obj)) {
    RootedObject headers(cx);
    headers = RequestOrResponse::headers<Headers::Mode::ProxyToResponse>(cx, response_obj);
    if (!Headers::delazify(cx, headers))
      return false;
  }

  bool streaming = false;
  if (!RequestOrResponse::maybe_stream_body(cx, response_obj, &streaming)) {
    return false;
  }

  set_state(event, streaming ? State::responseStreaming : State::responseDone);
  return start_response(cx, response_obj, streaming);
}
bool response_promise_then_handler(JSContext *cx, HandleObject event, HandleValue extra,
                                   CallArgs args) {
   
   
   
   
   
   
  if (!Response::is_instance(args.get(0))) {
    JS_ReportErrorUTF8(cx, "FetchEvent#respondWith must be called with a Response "
                           "object or a Promise resolving to a Response object as "
                           "the first argument");
    RootedObject rejection(cx, PromiseRejectedWithPendingError(cx));
    if (!rejection)
      return false;
    args.rval().setObject(*rejection);
    return respondWithError(cx, event);
  }

   
   
  RootedObject response_obj(cx, &args[0].toObject());

   
   
  if (Response::is_upstream(response_obj)) {
    RootedObject headers(cx);
    headers = RequestOrResponse::headers<Headers::Mode::ProxyToResponse>(cx, response_obj);
    if (!Headers::delazify(cx, headers))
      return false;
  }

  bool streaming = false;
  if (!RequestOrResponse::maybe_stream_body(cx, response_obj, &streaming)) {
    return false;
  }

  set_state(event, streaming ? State::responseStreaming : State::responseDone);
  return start_response(cx, response_obj, streaming);
}