Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 9 additions & 8 deletions src/adapters/bunny.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { createWaitUntil } from "../_utils.ts";
import type { Server, ServerOptions } from "../types.ts";
import { wrapFetch } from "../_middleware.ts";
import { errorPlugin } from "../_plugins.ts";
Expand All @@ -17,9 +16,13 @@ export const FastResponse: typeof globalThis.Response = Response;
*/
declare namespace Bunny {
export const v1: BunnySDKV1;
export const unstable: BunnySDKUnstable;
type BunnySDKV1 = {
serve: (handler: (request: Request) => MaybePromise<Response>) => void;
};
type BunnySDKUnstable = {
waitUntil(promise: Promise<unknown>): void;
};
}

export function serve(options: ServerOptions): Server {
Expand All @@ -31,8 +34,7 @@ class BunnyServer implements Server {
readonly options: Server["options"];
readonly fetch: (request: Request) => MaybePromise<Response>;
private _started = false;

#wait: ReturnType<typeof createWaitUntil> | undefined;
readonly waitUntil: Server["waitUntil"];

constructor(options: ServerOptions) {
this.options = { ...options, middleware: [...(options.middleware || [])] };
Expand All @@ -41,12 +43,11 @@ class BunnyServer implements Server {
errorPlugin(this);

const fetchHandler = wrapFetch(this);

this.#wait = createWaitUntil();
this.waitUntil = (promise: Promise<unknown>) => Bunny.unstable.waitUntil(promise);

this.fetch = (request: Request) => {
Object.defineProperties(request, {
waitUntil: { value: this.#wait?.waitUntil },
waitUntil: { value: (promise: Promise<unknown>) => Bunny.unstable.waitUntil(promise) },
Comment on lines +46 to +50
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Missing null-safety guard for Bunny.unstable; duplicate lambda.

Two concerns here:

1. No guard for Bunny.unstable (major): Bunny.unstable is accessed without optional chaining. Unlike Bunny.v1, which is guarded by Bunny.v1?.serve inside serve(), Bunny.unstable is never checked. If the runtime doesn't expose this namespace yet (e.g., on an older edge node during a phased rollout, or during local development with manual: true before serve() throws), any call to server.waitUntil() or request.waitUntil() from a request handler will throw TypeError: Cannot read properties of undefined (reading 'waitUntil'). Since the unstable namespace name itself signals it could be removed or absent, defensive access is warranted.

2. Duplicate lambda (optional): The same arrow function is defined twice — once at line 46 for this.waitUntil and again at line 50 for the request property. The fetch handler can simply reuse this.waitUntil.

🛡️ Proposed fix: optional chaining + dedup lambda
-   this.waitUntil = (promise: Promise<unknown>) => Bunny.unstable.waitUntil(promise);
+   this.waitUntil = (promise: Promise<unknown>) => Bunny.unstable?.waitUntil(promise);

    this.fetch = (request: Request) => {
      Object.defineProperties(request, {
-       waitUntil: { value: (promise: Promise<unknown>) => Bunny.unstable.waitUntil(promise) },
+       waitUntil: { value: this.waitUntil },
        runtime: { enumerable: true, value: { name: "bunny" } },
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/adapters/bunny.ts` around lines 46 - 50, Guard accesses to the unstable
namespace and avoid duplicating the lambda: change uses of
Bunny.unstable.waitUntil to use optional chaining (e.g.,
Bunny.unstable?.waitUntil) and make this.waitUntil a safe wrapper that checks
Bunny.unstable before calling it; then reuse this.waitUntil when defining
request.waitUntil inside fetch instead of redefining the arrow function. Update
symbols: Bunny.unstable, this.waitUntil, fetch, and the request.waitUntil
property to perform a no-op or safe call when Bunny.unstable is undefined.

runtime: { enumerable: true, value: { name: "bunny" } },
ip: {
enumerable: true,
Expand Down Expand Up @@ -80,7 +81,7 @@ class BunnyServer implements Server {
return Promise.resolve(this);
}

async close(): Promise<void> {
await this.#wait?.wait();
close(): Promise<void> {
return Promise.resolve();
}
}
Loading