Repository: honojs/hono
File: src/context.ts (TypeScript)

Code before:
        ) as ReturnType<TextRespond>)
  }

  /**
   * `.json()` can render JSON as `Content-Type:application/json`.
   *
   * @see {@link https://hono.dev/docs/api/context#json}
   *
   * @example
   * ```ts
   * app.get('/api', (c) => {
   *   return c.json({ message: 'Hello!' })
   * })
   * ```
   */
  json: JSONRespond = <
    T extends JSONValue | {} | InvalidJSONValue,
    U extends ContentfulStatusCode = ContentfulStatusCode,
  >(
    object: T,
    arg?: U | ResponseOrInit<U>,
    headers?: HeaderRecord
  ): JSONRespondReturn<T, U> => {
    const jsonString = JSON.stringify(object)
    return (
      !this.#preparedHeaders && !this.#status && !arg && !headers && !this.finalized
        ? new Response(jsonString, {
            headers: { 'Content-Type': 'application/json' },
          })
        : this.#newResponse(jsonString, arg, setDefaultContentType('application/json', headers))
    ) /* eslint-disable @typescript-eslint/no-explicit-any */ as any
  }

  html: HTMLRespond = (
    html: string | Promise<string>,
    arg?: ContentfulStatusCode | ResponseOrInit<ContentfulStatusCode>,
    headers?: HeaderRecord
  ): Response | Promise<Response> => {
    const res = (html: string) =>
      this.#newResponse(html, arg, setDefaultContentType('text/html; charset=UTF-8', headers))
    return typeof html === 'object'
      ? resolveCallback(html, HtmlEscapedCallbackPhase.Stringify, false, {}).then(res)
      : res(html)
  }

  /**
   * `.redirect()` can Redirect, default status code is 302.
   *
   * @see {@link https://hono.dev/docs/api/context#redirect}
   *
   * @example

Review comment (suggestion):
Using a common function reduces the file size slightly. I think the overhead can be ignored.

```diff
diff --git a/src/context.ts b/src/context.ts
index 6b7949b9..eb43dcf4 100644
--- a/src/context.ts
+++ b/src/context.ts
@@ -657,6 +657,10 @@ export class Context<
     headers?: HeaderRecord
   ): ReturnType<BodyRespond> => this.#newResponse(data, arg, headers) as ReturnType<BodyRespond>

+  #shouldFastPath(): boolean {
+    return !this.#preparedHeaders && !this.#status && !this.finalized
+  }
+
   /**
    * `.text()` can render text as `Content-Type:text/plain`.
    *
@@ -674,7 +678,7 @@ export class Context<
     arg?: ContentfulStatusCode | ResponseOrInit,
     headers?: HeaderRecord
   ): ReturnType<TextRespond> => {
-    return !this.#preparedHeaders && !this.#status && !arg && !headers && !this.finalized
+    return this.#shouldFastPath() && !arg && !headers
       ? (new Response(text) as ReturnType<TextRespond>)
       : (this.#newResponse(
           text,
@@ -705,7 +709,7 @@ export class Context<
   ): JSONRespondReturn<T, U> => {
     const jsonString = JSON.stringify(object)
     return (
-      !this.#preparedHeaders && !this.#status && !arg && !headers && !this.finalized
+      this.#shouldFastPath() && !arg && !headers
         ? new Response(jsonString, {
             headers: { 'Content-Type': 'application/json' },
           })
```

Code after:
      : (this.#newResponse(
          text,
          arg,
          setDefaultContentType(TEXT_PLAIN, headers)
        ) as ReturnType<TextRespond>)
  }

  /**
   * `.json()` can render JSON as `Content-Type:application/json`.
   *
   * @see {@link https://hono.dev/docs/api/context#json}
   *
   * @example
   * ```ts
   * app.get('/api', (c) => {
   *   return c.json({ message: 'Hello!' })
   * })
   * ```
   */
  json: JSONRespond = <
    T extends JSONValue | {} | InvalidJSONValue,
    U extends ContentfulStatusCode = ContentfulStatusCode,
  >(
    object: T,
    arg?: U | ResponseOrInit<U>,
    headers?: HeaderRecord
  ): JSONRespondReturn<T, U> => {
    return (
      this.#useFastPath() && !arg && !headers
        ? Response.json(object)
        : this.#newResponse(
            JSON.stringify(object),
            arg,
            setDefaultContentType('application/json', headers)
          )
    ) as JSONRespondReturn<T, U>
  }

  html: HTMLRespond = (
    html: string | Promise<string>,
    arg?: ContentfulStatusCode | ResponseOrInit<ContentfulStatusCode>,
    headers?: HeaderRecord
  ): Response | Promise<Response> => {
    const res = (html: string) =>
      this.#newResponse(html, arg, setDefaultContentType('text/html; charset=UTF-8', headers))
    return typeof html === 'object'
      ? resolveCallback(html, HtmlEscapedCallbackPhase.Stringify, false, {}).then(res)
      : res(html)
  }

  /**