aboutsummaryrefslogtreecommitdiff
path: root/src/javascript
diff options
context:
space:
mode:
authorGravatar Jarred Sumner <jarred@jarredsumner.com> 2022-03-11 00:03:09 -0800
committerGravatar Jarred Sumner <jarred@jarredsumner.com> 2022-03-11 00:03:09 -0800
commit44b0c8153a7092f97c36c5aab82b692f672c3ddf (patch)
tree5554a3e9e69bd689739c77745cb4a4bf87e98fd6 /src/javascript
parentc8f6337f1f9f22b48286c8bed1e47d44f0657cd0 (diff)
downloadbun-44b0c8153a7092f97c36c5aab82b692f672c3ddf.tar.gz
bun-44b0c8153a7092f97c36c5aab82b692f672c3ddf.tar.zst
bun-44b0c8153a7092f97c36c5aab82b692f672c3ddf.zip
Source Maps for client-side errors & columns
Diffstat (limited to 'src/javascript')
-rw-r--r--src/javascript/jsc/bindings/exports.zig122
-rw-r--r--src/javascript/jsc/bindings/headers-handwritten.h2
-rw-r--r--src/javascript/jsc/javascript.zig35
-rw-r--r--src/javascript/jsc/webcore/encoding.zig3
4 files changed, 110 insertions, 52 deletions
diff --git a/src/javascript/jsc/bindings/exports.zig b/src/javascript/jsc/bindings/exports.zig
index 75a7c96be..0a0a045a3 100644
--- a/src/javascript/jsc/bindings/exports.zig
+++ b/src/javascript/jsc/bindings/exports.zig
@@ -389,7 +389,12 @@ pub const ZigStackTrace = extern struct {
frames_ptr: [*c]ZigStackFrame,
frames_len: u8,
- pub fn toAPI(this: *const ZigStackTrace, allocator: std.mem.Allocator) !Api.StackTrace {
+ pub fn toAPI(
+ this: *const ZigStackTrace,
+ allocator: std.mem.Allocator,
+ root_path: string,
+ origin: ?*const ZigURL,
+ ) !Api.StackTrace {
var stack_trace: Api.StackTrace = std.mem.zeroes(Api.StackTrace);
{
var source_lines_iter = this.sourceLineIterator();
@@ -424,7 +429,11 @@ pub const ZigStackTrace = extern struct {
stack_trace.frames = stack_frames;
for (_frames) |frame, i| {
- stack_frames[i] = try frame.toAPI(allocator);
+ stack_frames[i] = try frame.toAPI(
+ root_path,
+ origin,
+ allocator,
+ );
}
}
}
@@ -480,18 +489,24 @@ pub const ZigStackFrame = extern struct {
position: ZigStackFramePosition,
code_type: ZigStackFrameCode,
- pub fn toAPI(this: *const ZigStackFrame, allocator: std.mem.Allocator) !Api.StackFrame {
+ /// This informs formatters whether to display as a blob URL or not
+ remapped: bool = false,
+
+ pub fn toAPI(this: *const ZigStackFrame, root_path: string, origin: ?*const ZigURL, allocator: std.mem.Allocator) !Api.StackFrame {
var frame: Api.StackFrame = std.mem.zeroes(Api.StackFrame);
if (this.function_name.len > 0) {
frame.function_name = try allocator.dupe(u8, this.function_name.slice());
}
if (this.source_url.len > 0) {
- frame.file = try allocator.dupe(u8, this.source_url.slice());
+ frame.file = try std.fmt.allocPrint(allocator, "{any}", .{this.sourceURLFormatter(root_path, origin, true, false)});
}
frame.position.source_offset = this.position.source_offset;
- frame.position.line = this.position.line;
+
+ // For remapped code, we add 1 to the line number
+ frame.position.line = this.position.line + @as(i32, @boolToInt(this.remapped));
+
frame.position.line_start = this.position.line_start;
frame.position.line_stop = this.position.line_stop;
frame.position.column_start = this.position.column_start;
@@ -508,7 +523,8 @@ pub const ZigStackFrame = extern struct {
position: ZigStackFramePosition,
enable_color: bool,
origin: ?*const ZigURL,
-
+ exclude_line_column: bool = false,
+ remapped: bool = false,
root_path: string = "",
pub fn format(this: SourceURLFormatter, comptime _: []const u8, _: std.fmt.FormatOptions, writer: anytype) !void {
if (this.enable_color) {
@@ -516,16 +532,19 @@ pub const ZigStackFrame = extern struct {
}
var source_slice = this.source_url.slice();
- if (this.origin) |origin| {
- try writer.writeAll(origin.displayProtocol());
- try writer.writeAll("://");
- try writer.writeAll(origin.displayHostname());
- try writer.writeAll(":");
- try writer.writeAll(origin.port);
- try writer.writeAll("/blob:");
-
- if (strings.startsWith(source_slice, this.root_path)) {
- source_slice = source_slice[this.root_path.len..];
+
+ if (!this.remapped) {
+ if (this.origin) |origin| {
+ try writer.writeAll(origin.displayProtocol());
+ try writer.writeAll("://");
+ try writer.writeAll(origin.displayHostname());
+ try writer.writeAll(":");
+ try writer.writeAll(origin.port);
+ try writer.writeAll("/blob:");
+
+ if (strings.startsWith(source_slice, this.root_path)) {
+ source_slice = source_slice[this.root_path.len..];
+ }
}
}
@@ -539,30 +558,32 @@ pub const ZigStackFrame = extern struct {
}
}
- if (this.position.line > -1 and this.position.column_start > -1) {
- if (this.enable_color) {
- try std.fmt.format(
- writer,
- // :
- comptime Output.prettyFmt("<d>:<r><yellow>{d}<r><d>:<yellow>{d}<r>", true),
- .{ this.position.line + 1, this.position.column_start },
- );
- } else {
- try std.fmt.format(writer, ":{d}:{d}", .{ this.position.line + 1, this.position.column_start });
- }
- } else if (this.position.line > -1) {
- if (this.enable_color) {
- try std.fmt.format(
- writer,
- comptime Output.prettyFmt("<d>:<r><yellow>{d}<r>", true),
- .{
+ if (!this.exclude_line_column) {
+ if (this.position.line > -1 and this.position.column_start > -1) {
+ if (this.enable_color) {
+ try std.fmt.format(
+ writer,
+ // :
+ comptime Output.prettyFmt("<d>:<r><yellow>{d}<r><d>:<yellow>{d}<r>", true),
+ .{ this.position.line + 1, this.position.column_start },
+ );
+ } else {
+ try std.fmt.format(writer, ":{d}:{d}", .{ this.position.line + 1, this.position.column_start });
+ }
+ } else if (this.position.line > -1) {
+ if (this.enable_color) {
+ try std.fmt.format(
+ writer,
+ comptime Output.prettyFmt("<d>:<r><yellow>{d}<r>", true),
+ .{
+ this.position.line + 1,
+ },
+ );
+ } else {
+ try std.fmt.format(writer, ":{d}", .{
this.position.line + 1,
- },
- );
- } else {
- try std.fmt.format(writer, ":{d}", .{
- this.position.line + 1,
- });
+ });
+ }
}
}
}
@@ -621,8 +642,16 @@ pub const ZigStackFrame = extern struct {
return NameFormatter{ .function_name = this.function_name, .code_type = this.code_type, .enable_color = enable_color };
}
- pub fn sourceURLFormatter(this: *const ZigStackFrame, root_path: string, origin: ?*const ZigURL, comptime enable_color: bool) SourceURLFormatter {
- return SourceURLFormatter{ .source_url = this.source_url, .origin = origin, .root_path = root_path, .position = this.position, .enable_color = enable_color };
+ pub fn sourceURLFormatter(this: *const ZigStackFrame, root_path: string, origin: ?*const ZigURL, exclude_line_column: bool, comptime enable_color: bool) SourceURLFormatter {
+ return SourceURLFormatter{
+ .source_url = this.source_url,
+ .exclude_line_column = exclude_line_column,
+ .origin = origin,
+ .root_path = root_path,
+ .position = this.position,
+ .enable_color = enable_color,
+ .remapped = this.remapped,
+ };
}
};
@@ -670,6 +699,8 @@ pub const ZigException = extern struct {
exception: ?*anyopaque,
+ remapped: bool = false,
+
pub const shim = Shimmer("Zig", "Exception", @This());
pub const name = "ZigException";
pub const namespace = shim.namespace;
@@ -736,7 +767,12 @@ pub const ZigException = extern struct {
return shim.cppFn("fromException", .{exception});
}
- pub fn addToErrorList(this: *ZigException, error_list: *std.ArrayList(Api.JsException)) !void {
+ pub fn addToErrorList(
+ this: *ZigException,
+ error_list: *std.ArrayList(Api.JsException),
+ root_path: string,
+ origin: ?*const ZigURL,
+ ) !void {
const _name: string = @field(this, "name").slice();
const message: string = @field(this, "message").slice();
@@ -757,7 +793,7 @@ pub const ZigException = extern struct {
}
if (this.stack.frames_len > 0) {
- api_exception.stack = try this.stack.toAPI(error_list.allocator);
+ api_exception.stack = try this.stack.toAPI(error_list.allocator, root_path, origin);
is_empty = false;
}
diff --git a/src/javascript/jsc/bindings/headers-handwritten.h b/src/javascript/jsc/bindings/headers-handwritten.h
index 56d5c0773..8e2bafc76 100644
--- a/src/javascript/jsc/bindings/headers-handwritten.h
+++ b/src/javascript/jsc/bindings/headers-handwritten.h
@@ -68,6 +68,7 @@ typedef struct ZigStackFrame {
ZigString source_url;
ZigStackFramePosition position;
ZigStackFrameCode code_type;
+ bool remapped;
} ZigStackFrame;
typedef struct ZigStackTrace {
@@ -90,6 +91,7 @@ typedef struct ZigException {
ZigString message;
ZigStackTrace stack;
void* exception;
+ bool remapped;
} ZigException;
typedef uint8_t JSErrorCode;
diff --git a/src/javascript/jsc/javascript.zig b/src/javascript/jsc/javascript.zig
index 36c8174ad..622364a6c 100644
--- a/src/javascript/jsc/javascript.zig
+++ b/src/javascript/jsc/javascript.zig
@@ -2921,7 +2921,7 @@ pub const VirtualMachine = struct {
}
if (exception_list) |list| {
- zig_exception.addToErrorList(list) catch {};
+ zig_exception.addToErrorList(list, this.bundler.fs.top_level_dir, &this.origin) catch {};
}
}
}
@@ -3067,6 +3067,7 @@ pub const VirtualMachine = struct {
frame.sourceURLFormatter(
dir,
origin,
+ false,
allow_ansi_colors,
),
},
@@ -3081,6 +3082,7 @@ pub const VirtualMachine = struct {
frame.sourceURLFormatter(
dir,
origin,
+ false,
allow_ansi_colors,
),
},
@@ -3095,10 +3097,13 @@ pub const VirtualMachine = struct {
exception: *ZigException,
error_instance: JSValue,
exception_list: ?*ExceptionList,
- ) !void {
+ ) void {
error_instance.toZigException(this.global, exception);
- if (exception_list) |list| {
- try exception.addToErrorList(list);
+ // defer this so that it copies correctly
+ defer {
+ if (exception_list) |list| {
+ exception.addToErrorList(list, this.bundler.fs.top_level_dir, &this.origin) catch unreachable;
+ }
}
var frames: []JSC.ZigStackFrame = exception.stack.frames_ptr[0..exception.stack.frames_len];
@@ -3108,14 +3113,22 @@ pub const VirtualMachine = struct {
if (this.source_mappings.resolveMapping(
top.source_url.slice(),
@maximum(top.position.line, 0),
- @maximum(top.position.column_stop, 0),
+ @maximum(top.position.column_start, 0),
)) |mapping| {
var log = logger.Log.init(default_allocator);
var original_source = _fetch(this.global, top.source_url.slice(), "", &log, true) catch return;
const code = original_source.source_code.slice();
top.position.line = mapping.original.lines;
+ top.position.line_start = mapping.original.lines;
+ top.position.line_stop = mapping.original.lines + 1;
top.position.column_start = mapping.original.columns;
+ top.position.column_stop = mapping.original.columns + 1;
+ exception.remapped = true;
+ top.remapped = true;
+ // This expression range is no longer accurate
top.position.expression_start = mapping.original.columns;
+ top.position.expression_stop = mapping.original.columns + 1;
+
if (strings.getLinesInText(
code,
@intCast(u32, top.position.line),
@@ -3133,6 +3146,13 @@ pub const VirtualMachine = struct {
}
exception.stack.source_lines_len = @intCast(u8, lines_.len);
+
+ top.position.column_stop = @intCast(i32, source_lines[lines_.len - 1].len);
+ top.position.line_stop = top.position.column_stop;
+
+ // This expression range is no longer accurate
+ top.position.expression_start = mapping.original.columns;
+ top.position.expression_stop = top.position.column_stop;
}
}
@@ -3145,6 +3165,7 @@ pub const VirtualMachine = struct {
@maximum(frame.position.column_start, 0),
)) |mapping| {
frame.position.line = mapping.original.lines;
+ frame.remapped = true;
frame.position.column_start = mapping.original.columns;
}
}
@@ -3154,7 +3175,7 @@ pub const VirtualMachine = struct {
pub fn printErrorInstance(this: *VirtualMachine, error_instance: JSValue, exception_list: ?*ExceptionList, comptime Writer: type, writer: Writer, comptime allow_ansi_color: bool) !void {
var exception_holder = ZigException.Holder.init();
var exception = exception_holder.zigException();
- try this.remapZigException(exception, error_instance, exception_list);
+ this.remapZigException(exception, error_instance, exception_list);
this.had_errors = true;
var line_numbers = exception.stack.source_lines_numbers[0..exception.stack.source_lines_len];
@@ -3217,7 +3238,7 @@ pub const VirtualMachine = struct {
writer.writeByteNTimes(' ', pad) catch unreachable;
const top = exception.stack.frames()[0];
var remainder = std.mem.trim(u8, source.text, "\n");
- if (@intCast(usize, top.position.column_stop) > remainder.len) {
+ if (@intCast(usize, top.position.column_stop) > remainder.len or (top.position.column_stop - top.position.column_start) <= 0) {
writer.print(
comptime Output.prettyFmt(
"<r><d>{d} |<r> {s}\n",
diff --git a/src/javascript/jsc/webcore/encoding.zig b/src/javascript/jsc/webcore/encoding.zig
index 79c3125f7..8d9486907 100644
--- a/src/javascript/jsc/webcore/encoding.zig
+++ b/src/javascript/jsc/webcore/encoding.zig
@@ -486,8 +486,7 @@ pub const TextDecoder = struct {
}
}
}
-
- return str.toValueGC(ctx.ptr()).asObjectRef();
+ return str.toValue(ctx.ptr()).asObjectRef();
},
EncodingLabel.@"UTF-16LE" => {