mirror of
https://github.com/oven-sh/bun
synced 2026-02-10 10:58:56 +00:00
Improve the error message when Bun.serve() is passed a non-Response object (#11562)
Co-authored-by: dave caruso <me@paperdave.net>
This commit is contained in:
@@ -1403,16 +1403,42 @@ fn NewRequestContext(comptime ssl_enabled: bool, comptime debug_mode: bool, comp
|
||||
return JSValue.jsUndefined();
|
||||
}
|
||||
|
||||
fn renderMissingInvalidResponse(ctx: *RequestContext, value: JSC.JSValue) void {
|
||||
var class_name = value.getClassInfoName() orelse bun.String.empty;
|
||||
defer class_name.deref();
|
||||
const globalThis: *JSC.JSGlobalObject = ctx.server.globalThis;
|
||||
|
||||
Output.enableBuffering();
|
||||
var writer = Output.errorWriter();
|
||||
|
||||
if (class_name.eqlComptime("Response")) {
|
||||
Output.errGeneric("Expected a native Response object, but received a polyfilled Response object. Bun.serve() only supports native Response objects.", .{});
|
||||
} else if (!value.isEmpty() and !globalThis.hasException()) {
|
||||
var formatter = JSC.ConsoleObject.Formatter{
|
||||
.globalThis = globalThis,
|
||||
.quote_strings = true,
|
||||
};
|
||||
Output.errGeneric("Expected a Response object, but received '{}'", .{value.toFmt(formatter.globalThis, &formatter)});
|
||||
} else {
|
||||
Output.errGeneric("Expected a Response object", .{});
|
||||
}
|
||||
|
||||
Output.flush();
|
||||
if (!globalThis.hasException()) {
|
||||
JSC.ConsoleObject.writeTrace(@TypeOf(&writer), &writer, globalThis);
|
||||
}
|
||||
Output.flush();
|
||||
ctx.renderMissing();
|
||||
}
|
||||
|
||||
fn handleResolve(ctx: *RequestContext, value: JSC.JSValue) void {
|
||||
if (value.isEmptyOrUndefinedOrNull() or !value.isCell()) {
|
||||
ctx.renderMissing();
|
||||
ctx.renderMissingInvalidResponse(value);
|
||||
return;
|
||||
}
|
||||
|
||||
const response = value.as(JSC.WebCore.Response) orelse {
|
||||
Output.prettyErrorln("Expected a Response object", .{});
|
||||
Output.flush();
|
||||
ctx.renderMissing();
|
||||
ctx.renderMissingInvalidResponse(value);
|
||||
return;
|
||||
};
|
||||
ctx.response_jsvalue = value;
|
||||
@@ -2558,7 +2584,7 @@ fn NewRequestContext(comptime ssl_enabled: bool, comptime debug_mode: bool, comp
|
||||
}
|
||||
|
||||
if (response_value.isEmptyOrUndefinedOrNull()) {
|
||||
ctx.renderMissing();
|
||||
ctx.renderMissingInvalidResponse(response_value);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -2611,11 +2637,11 @@ fn NewRequestContext(comptime ssl_enabled: bool, comptime debug_mode: bool, comp
|
||||
}
|
||||
|
||||
if (fulfilled_value.isEmptyOrUndefinedOrNull()) {
|
||||
ctx.renderMissing();
|
||||
ctx.renderMissingInvalidResponse(fulfilled_value);
|
||||
return;
|
||||
}
|
||||
var response = fulfilled_value.as(JSC.WebCore.Response) orelse {
|
||||
ctx.renderMissing();
|
||||
ctx.renderMissingInvalidResponse(fulfilled_value);
|
||||
return;
|
||||
};
|
||||
|
||||
|
||||
@@ -5600,16 +5600,12 @@ pub const JSValue = enum(JSValueReprInt) {
|
||||
|
||||
extern fn JSC__JSValue__getClassInfoName(value: JSValue, out: *bun.String) bool;
|
||||
|
||||
/// Returned memory is read-only memory of the s_info assigned to a JSCell
|
||||
pub fn getClassInfoName(this: JSValue) ?[]const u8 {
|
||||
var out: bun.String = undefined;
|
||||
/// For native C++ classes extending JSCell, this retrieves s_info's name
|
||||
pub fn getClassInfoName(this: JSValue) ?bun.String {
|
||||
if (!this.isObject()) return null;
|
||||
var out: bun.String = bun.String.empty;
|
||||
if (!JSC__JSValue__getClassInfoName(this, &out)) return null;
|
||||
// we assume the class name is ASCII text
|
||||
const data = out.latin1();
|
||||
if (bun.Environment.allow_assert) {
|
||||
bun.assert(bun.strings.isAllASCII(data));
|
||||
}
|
||||
return data;
|
||||
return out;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -7422,12 +7422,15 @@ pub const Macro = struct {
|
||||
.String => this.coerce(value, .String),
|
||||
.Promise => this.coerce(value, .Promise),
|
||||
else => brk: {
|
||||
var name = value.getClassInfoName() orelse bun.String.init("unknown");
|
||||
defer name.deref();
|
||||
|
||||
this.log.addErrorFmt(
|
||||
this.source,
|
||||
this.caller.loc,
|
||||
this.allocator,
|
||||
"cannot coerce {s} ({s}) to Bun's AST. Please return a simpler type",
|
||||
.{ value.getClassInfoName() orelse "unknown", @tagName(value.jsType()) },
|
||||
"cannot coerce {} ({s}) to Bun's AST. Please return a simpler type",
|
||||
.{ name, @tagName(value.jsType()) },
|
||||
) catch unreachable;
|
||||
break :brk error.MacroFailed;
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user