Skip to content

Commit

Permalink
better printing for console.log types (#15404)
Browse files Browse the repository at this point in the history
  • Loading branch information
RiskyMH authored and snoglobe committed Dec 4, 2024
1 parent 3c87910 commit 41590a9
Show file tree
Hide file tree
Showing 3 changed files with 76 additions and 15 deletions.
45 changes: 31 additions & 14 deletions src/bun.js/ConsoleObject.zig
Original file line number Diff line number Diff line change
Expand Up @@ -1228,7 +1228,7 @@ pub const Formatter = struct {
.tag = switch (js_type) {
.ErrorInstance => .Error,
.NumberObject => .Double,
.DerivedArray, JSValue.JSType.Array => .Array,
.DerivedArray, JSValue.JSType.Array, .DirectArguments, .ScopedArguments, .ClonedArguments => .Array,
.DerivedStringObject, JSValue.JSType.String, JSValue.JSType.StringObject => .String,
.RegExpObject => .String,
.Symbol => .Symbol,
Expand Down Expand Up @@ -1921,6 +1921,8 @@ pub const Formatter = struct {
value.getClassName(globalThis, &name_str);
if (!name_str.eqlComptime("Object")) {
return name_str;
} else if (value.getPrototype(globalThis).eqlValue(JSValue.null)) {
return ZigString.static("[Object: null prototype]").*;
}
return null;
}
Expand Down Expand Up @@ -2165,10 +2167,23 @@ pub const Formatter = struct {
value.getClassName(this.globalThis, &printable);
this.addForNewLine(printable.len);

const proto = value.getPrototype(this.globalThis);
var printable_proto = ZigString.init(&name_buf);
proto.getClassName(this.globalThis, &printable_proto);
this.addForNewLine(printable_proto.len);

if (printable.len == 0) {
writer.print(comptime Output.prettyFmt("<cyan>[class (anonymous)]<r>", enable_ansi_colors), .{});
if (printable_proto.isEmpty()) {
writer.print(comptime Output.prettyFmt("<cyan>[class (anonymous)]<r>", enable_ansi_colors), .{});
} else {
writer.print(comptime Output.prettyFmt("<cyan>[class (anonymous) extends {}]<r>", enable_ansi_colors), .{printable_proto});
}
} else {
writer.print(comptime Output.prettyFmt("<cyan>[class {}]<r>", enable_ansi_colors), .{printable});
if (printable_proto.isEmpty()) {
writer.print(comptime Output.prettyFmt("<cyan>[class {}]<r>", enable_ansi_colors), .{printable});
} else {
writer.print(comptime Output.prettyFmt("<cyan>[class {} extends {}]<r>", enable_ansi_colors), .{ printable, printable_proto });
}
}
},
.Function => {
Expand All @@ -2179,7 +2194,7 @@ pub const Formatter = struct {
const func_name = proto.getName(this.globalThis); // "Function" | "AsyncFunction" | "GeneratorFunction" | "AsyncGeneratorFunction"
defer func_name.deref();

if (printable.isEmpty()) {
if (printable.isEmpty() or func_name.eql(printable)) {
if (func_name.isEmpty()) {
writer.print(comptime Output.prettyFmt("<cyan>[Function]<r>", enable_ansi_colors), .{});
} else {
Expand Down Expand Up @@ -2369,16 +2384,18 @@ pub const Formatter = struct {
}
}

const Iterator = PropertyIterator(Writer, enable_ansi_colors);
var iter = Iterator{
.formatter = this,
.writer = writer_,
.always_newline = !this.single_line and (this.always_newline_scope or this.goodTimeForANewLine()),
.single_line = this.single_line,
.parent = value,
.i = i,
};
value.forEachPropertyNonIndexed(this.globalThis, &iter, Iterator.forEach);
if (!jsType.isArguments()) {
const Iterator = PropertyIterator(Writer, enable_ansi_colors);
var iter = Iterator{
.formatter = this,
.writer = writer_,
.always_newline = !this.single_line and (this.always_newline_scope or this.goodTimeForANewLine()),
.single_line = this.single_line,
.parent = value,
.i = i,
};
value.forEachPropertyNonIndexed(this.globalThis, &iter, Iterator.forEach);
}
}

if (!this.single_line and (this.ordered_properties or was_good_time or this.goodTimeForANewLine())) {
Expand Down
7 changes: 7 additions & 0 deletions src/bun.js/bindings/bindings.zig
Original file line number Diff line number Diff line change
Expand Up @@ -3999,6 +3999,13 @@ pub const JSValue = enum(i64) {
else => false,
};
}

pub inline fn isArguments(this: JSType) bool {
return switch (this) {
.DirectArguments, .ClonedArguments, .ScopedArguments => true,
else => false,
};
}
};

pub inline fn cast(ptr: anytype) JSValue {
Expand Down
39 changes: 38 additions & 1 deletion test/js/bun/util/inspect.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -525,13 +525,39 @@ it("Bun.inspect array with non-indexed properties", () => {
});

describe("console.logging function displays async and generator names", async () => {
const cases = [function a() {}, async function b() {}, function* c() {}, async function* d() {}];
const cases = [
function () {},
function a() {},
async function b() {},
function* c() {},
async function* d() {},
async function* () {},
];

const expected_logs = [
"[Function]",
"[Function: a]",
"[AsyncFunction: b]",
"[GeneratorFunction: c]",
"[AsyncGeneratorFunction: d]",
"[AsyncGeneratorFunction]",
];

for (let i = 0; i < cases.length; i++) {
it(expected_logs[i], () => {
expect(Bun.inspect(cases[i])).toBe(expected_logs[i]);
});
}
});
describe("console.logging class displays names and extends", async () => {
class A {}
const cases = [A, class B extends A {}, class extends A {}, class {}];

const expected_logs = [
"[class A]",
"[class B extends A]",
"[class (anonymous) extends A]",
"[class (anonymous)]",
];

for (let i = 0; i < cases.length; i++) {
Expand Down Expand Up @@ -562,3 +588,14 @@ it("console.log on a Blob shows name", () => {
`File (3 bytes) {\n name: "",\n type: "text/plain;charset=utf-8",\n lastModified: ${file.lastModified}\n}`,
);
});

it("console.log on a arguments shows list", () => {
function fn() {
expect(Bun.inspect(arguments)).toBe(`[ 1, [ 1 ], [Function: fn] ]`);
}
fn(1, [1], fn);
});

it("console.log on null prototype", () => {
expect(Bun.inspect(Object.create(null))).toBe("[Object: null prototype] {}");
});

0 comments on commit 41590a9

Please sign in to comment.