/// Fetched when a client-side error happens. This performs two actions /// - Logs the remapped stack trace to the console. /// - Replies with the remapped stack trace. /// Payload: /// - `u32`: Responding message ID (echoed back) /// - `u32`: Length of message /// - `[n]u8`: Message /// - `u32`: Length of error name /// - `[n]u8`: Error name /// - `u32`: Number of stack frames. For each /// - `u32`: Line number (0 for unavailable) /// - `u32`: Column number (0 for unavailable) /// - `u32`: Length of file name (0 for unavailable) /// - `[n]u8`: File name /// - `u32`: Length of function name (0 for unavailable) /// - `[n]u8`: Function name const ErrorReportRequest = @This(); dev: *DevServer, body: uws.BodyReaderMixin(@This(), "body", runWithBody, finalize), pub fn run(dev: *DevServer, _: *Request, resp: anytype) void { const ctx = bun.new(ErrorReportRequest, .{ .dev = dev, .body = .init(dev.allocator()), }); ctx.dev.server.?.onPendingRequest(); ctx.body.readBody(resp); } pub fn finalize(ctx: *ErrorReportRequest) void { ctx.dev.server.?.onStaticRequestComplete(); bun.destroy(ctx); } pub fn runWithBody(ctx: *ErrorReportRequest, body: []const u8, r: AnyResponse) !void { // .finalize has to be called last, but only in the non-error path. var should_finalize_self = false; defer if (should_finalize_self) ctx.finalize(); var s = std.io.fixedBufferStream(body); const reader = s.reader(); var sfa_general = std.heap.stackFallback(65536, ctx.dev.allocator()); var sfa_sourcemap = std.heap.stackFallback(65536, ctx.dev.allocator()); const temp_alloc = sfa_general.get(); var arena = std.heap.ArenaAllocator.init(temp_alloc); defer arena.deinit(); var source_map_arena = std.heap.ArenaAllocator.init(sfa_sourcemap.get()); defer source_map_arena.deinit(); // Read payload, assemble ZigException const name = try readString32(reader, temp_alloc); defer temp_alloc.free(name); const message = try readString32(reader, temp_alloc); defer temp_alloc.free(message); const browser_url = try readString32(reader, temp_alloc); defer temp_alloc.free(browser_url); var frames: ArrayListUnmanaged(jsc.ZigStackFrame) = .empty; defer frames.deinit(temp_alloc); const stack_count = @min(try reader.readInt(u32, .little), 255); // does not support more than 255 try frames.ensureTotalCapacity(temp_alloc, stack_count); for (0..stack_count) |_| { const line = try reader.readInt(i32, .little); const column = try reader.readInt(i32, .little); const function_name = try readString32(reader, temp_alloc); const file_name = try readString32(reader, temp_alloc); frames.appendAssumeCapacity(.{ .function_name = .init(function_name), .source_url = .init(file_name), .position = if (line > 0) .{ .line = .fromOneBased(line), .column = if (column < 1) .invalid else .fromOneBased(column), .line_start_byte = 0, } else .{ .line = .invalid, .column = .invalid, .line_start_byte = 0, }, .code_type = .None, .is_async = false, .remapped = false, }); } const runtime_name = "Bun HMR Runtime"; const browser_url_origin = bun.jsc.URL.originFromSlice(browser_url) orelse browser_url; // All files that DevServer could provide a source map fit the pattern: // `/_bun/client/