authorgravatar for ian@ianjohnson.devIan Johnson <ian@ianjohnson.dev> 2025-02-15 16:23:33-05:00
committergravatar for ian@ianjohnson.devIan Johnson <ian@ianjohnson.dev> 2025-02-15 17:29:31-05:00
logb745a96d20e8159a68be53478d30c72f8c216dd3
tree39c5534d0e11e4c3da8efb36e0d920d48aadb2b6
parent293603f04029e2b1edf235a80417f3bb9651482f

Autodoc: use browser console log levels and simplify panic

Using the browser's `console.error`, etc. functions instead of `console.log` produces prettier output in the console. Additionally, `console.error` in particular includes a stack trace, which is useful for debugging where the error occurred. Additionally, this commit leverages the enhanced logging to delete the separate `panic` function from the JS code and write it in Zig instead.

2 files changed, 37 insertions(+), 26 deletions(-)

lib/docs/main.js+20-6
...@@ -11,6 +11,11 @@...@@ -11,6 +11,11 @@
11 const CAT_type_type = 9;11 const CAT_type_type = 9;
12 const CAT_type_function = 10;12 const CAT_type_function = 10;
1313
14 const LOG_err = 0;
15 const LOG_warn = 1;
16 const LOG_info = 2;
17 const LOG_debug = 3;
18
14 const domDocTestsCode = document.getElementById("docTestsCode");19 const domDocTestsCode = document.getElementById("docTestsCode");
15 const domFnErrorsAnyError = document.getElementById("fnErrorsAnyError");20 const domFnErrorsAnyError = document.getElementById("fnErrorsAnyError");
16 const domFnProto = document.getElementById("fnProto");21 const domFnProto = document.getElementById("fnProto");
...@@ -84,13 +89,22 @@...@@ -84,13 +89,22 @@
8489
85 WebAssembly.instantiateStreaming(wasm_promise, {90 WebAssembly.instantiateStreaming(wasm_promise, {
86 js: {91 js: {
87 log: function(ptr, len) {92 log: function(level, ptr, len) {
88 const msg = decodeString(ptr, len);93 const msg = decodeString(ptr, len);
89 console.log(msg);94 switch (level) {
90 },95 case LOG_err:
91 panic: function (ptr, len) {96 console.error(msg);
92 const msg = decodeString(ptr, len);97 break;
93 throw new Error("panic: " + msg);98 case LOG_warn:
99 console.warn(msg);
100 break;
101 case LOG_info:
102 console.info(msg);
103 break;
104 case LOG_debug:
105 console.debug(msg);
106 break;
107 }
94 },108 },
95 },109 },
96 }).then(function(obj) {110 }).then(function(obj) {
lib/docs/wasm/main.zig+17-20
...@@ -14,8 +14,15 @@ const missing_feature_url_escape = @import("html_render.zig").missing_feature_ur...@@ -14,8 +14,15 @@ const missing_feature_url_escape = @import("html_render.zig").missing_feature_ur
14const gpa = std.heap.wasm_allocator;14const gpa = std.heap.wasm_allocator;
1515
16const js = struct {16const js = struct {
17 extern "js" fn log(ptr: [*]const u8, len: usize) void;17 /// Keep in sync with the `LOG_` constants in `main.js`.
18 extern "js" fn panic(ptr: [*]const u8, len: usize) noreturn;18 const LogLevel = enum(u8) {
19 err,
20 warn,
21 info,
22 debug,
23 };
24
25 extern "js" fn log(level: LogLevel, ptr: [*]const u8, len: usize) void;
19};26};
2027
21pub const std_options: std.Options = .{28pub const std_options: std.Options = .{
...@@ -36,14 +43,13 @@ fn logFn(...@@ -36,14 +43,13 @@ fn logFn(
36 comptime format: []const u8,43 comptime format: []const u8,
37 args: anytype,44 args: anytype,
38) void {45) void {
39 const level_txt = comptime message_level.asText();46 const prefix = if (scope == .default) "" else @tagName(scope) ++ ": ";
40 const prefix2 = if (scope == .default) ": " else "(" ++ @tagName(scope) ++ "): ";
41 var buf: [500]u8 = undefined;47 var buf: [500]u8 = undefined;
42 const line = std.fmt.bufPrint(&buf, level_txt ++ prefix2 ++ format, args) catch l: {48 const line = std.fmt.bufPrint(&buf, prefix ++ format, args) catch l: {
43 buf[buf.len - 3 ..][0..3].* = "...".*;49 buf[buf.len - 3 ..][0..3].* = "...".*;
44 break :l &buf;50 break :l &buf;
45 };51 };
46 js.log(line.ptr, line.len);52 js.log(@field(js.LogLevel, @tagName(message_level)), line.ptr, line.len);
47}53}
4854
49export fn alloc(n: usize) [*]u8 {55export fn alloc(n: usize) [*]u8 {
...@@ -56,7 +62,7 @@ export fn unpack(tar_ptr: [*]u8, tar_len: usize) void {...@@ -56,7 +62,7 @@ export fn unpack(tar_ptr: [*]u8, tar_len: usize) void {
56 //log.debug("received {d} bytes of tar file", .{tar_bytes.len});62 //log.debug("received {d} bytes of tar file", .{tar_bytes.len});
5763
58 unpackInner(tar_bytes) catch |err| {64 unpackInner(tar_bytes) catch |err| {
59 fatal("unable to unpack tar: {s}", .{@errorName(err)});65 std.debug.panic("unable to unpack tar: {s}", .{@errorName(err)});
60 };66 };
61}67}
6268
...@@ -514,7 +520,7 @@ export fn decl_fn_proto_html(decl_index: Decl.Index, linkify_fn_name: bool) Stri...@@ -514,7 +520,7 @@ export fn decl_fn_proto_html(decl_index: Decl.Index, linkify_fn_name: bool) Stri
514 .collapse_whitespace = true,520 .collapse_whitespace = true,
515 .fn_link = if (linkify_fn_name) decl_index else .none,521 .fn_link = if (linkify_fn_name) decl_index else .none,
516 }) catch |err| {522 }) catch |err| {
517 fatal("unable to render source: {s}", .{@errorName(err)});523 std.debug.panic("unable to render source: {s}", .{@errorName(err)});
518 };524 };
519 return String.init(string_result.items);525 return String.init(string_result.items);
520}526}
...@@ -524,7 +530,7 @@ export fn decl_source_html(decl_index: Decl.Index) String {...@@ -524,7 +530,7 @@ export fn decl_source_html(decl_index: Decl.Index) String {
524530
525 string_result.clearRetainingCapacity();531 string_result.clearRetainingCapacity();
526 fileSourceHtml(decl.file, &string_result, decl.ast_node, .{}) catch |err| {532 fileSourceHtml(decl.file, &string_result, decl.ast_node, .{}) catch |err| {
527 fatal("unable to render source: {s}", .{@errorName(err)});533 std.debug.panic("unable to render source: {s}", .{@errorName(err)});
528 };534 };
529 return String.init(string_result.items);535 return String.init(string_result.items);
530}536}
...@@ -536,7 +542,7 @@ export fn decl_doctest_html(decl_index: Decl.Index) String {...@@ -536,7 +542,7 @@ export fn decl_doctest_html(decl_index: Decl.Index) String {
536542
537 string_result.clearRetainingCapacity();543 string_result.clearRetainingCapacity();
538 fileSourceHtml(decl.file, &string_result, doctest_ast_node, .{}) catch |err| {544 fileSourceHtml(decl.file, &string_result, doctest_ast_node, .{}) catch |err| {
539 fatal("unable to render source: {s}", .{@errorName(err)});545 std.debug.panic("unable to render source: {s}", .{@errorName(err)});
540 };546 };
541 return String.init(string_result.items);547 return String.init(string_result.items);
542}548}
...@@ -740,7 +746,7 @@ export fn decl_type_html(decl_index: Decl.Index) String {...@@ -740,7 +746,7 @@ export fn decl_type_html(decl_index: Decl.Index) String {
740 .skip_comments = true,746 .skip_comments = true,
741 .collapse_whitespace = true,747 .collapse_whitespace = true,
742 }) catch |e| {748 }) catch |e| {
743 fatal("unable to render html: {s}", .{@errorName(e)});749 std.debug.panic("unable to render html: {s}", .{@errorName(e)});
744 };750 };
745 string_result.appendSlice(gpa, "</code>") catch @panic("OOM");751 string_result.appendSlice(gpa, "</code>") catch @panic("OOM");
746 break :t;752 break :t;
...@@ -791,15 +797,6 @@ fn unpackInner(tar_bytes: []u8) !void {...@@ -791,15 +797,6 @@ fn unpackInner(tar_bytes: []u8) !void {
791 }797 }
792}798}
793799
794fn fatal(comptime format: []const u8, args: anytype) noreturn {
795 var buf: [500]u8 = undefined;
796 const line = std.fmt.bufPrint(&buf, format, args) catch l: {
797 buf[buf.len - 3 ..][0..3].* = "...".*;
798 break :l &buf;
799 };
800 js.panic(line.ptr, line.len);
801}
802
803fn ascii_lower(bytes: []u8) void {800fn ascii_lower(bytes: []u8) void {
804 for (bytes) |*b| b.* = std.ascii.toLower(b.*);801 for (bytes) |*b| b.* = std.ascii.toLower(b.*);
805}802}