aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar dave caruso <me@paperdave.net> 2023-07-11 12:48:19 -0700
committerGravatar GitHub <noreply@github.com> 2023-07-11 12:48:19 -0700
commit31ab56d36238528c6f44c52a6cbf600744a91f0a (patch)
tree262d70003271800a6c2c7e9c72316ae82d037986
parent4b333b2d3571a106e8a028ce62bf5149954d38f0 (diff)
downloadbun-31ab56d36238528c6f44c52a6cbf600744a91f0a.tar.gz
bun-31ab56d36238528c6f44c52a6cbf600744a91f0a.tar.zst
bun-31ab56d36238528c6f44c52a6cbf600744a91f0a.zip
Fix: console.log with class constructors (#3602)
* Fix console.log with class constructors * oops * fix it * lol * fix test
-rw-r--r--src/bun.js/bindings/bindings.cpp14
-rw-r--r--src/bun.js/bindings/exports.zig37
-rw-r--r--src/bun.js/test/pretty_format.zig42
-rw-r--r--test/js/web/console/console-log.expected.txt8
-rw-r--r--test/js/web/console/console-log.js6
5 files changed, 65 insertions, 42 deletions
diff --git a/src/bun.js/bindings/bindings.cpp b/src/bun.js/bindings/bindings.cpp
index 9f9b20c1e..d311072e4 100644
--- a/src/bun.js/bindings/bindings.cpp
+++ b/src/bun.js/bindings/bindings.cpp
@@ -2775,8 +2775,18 @@ void JSC__JSValue__put(JSC__JSValue JSValue0, JSC__JSGlobalObject* arg1, const Z
bool JSC__JSValue__isClass(JSC__JSValue JSValue0, JSC__JSGlobalObject* arg1)
{
- JSC::JSValue value = JSC::JSValue::decode(JSValue0);
- return value.isConstructor();
+ JSValue value = JSValue::decode(JSValue0);
+ auto callData = getCallData(value);
+
+ switch (callData.type) {
+ case CallData::Type::JS:
+ return callData.js.functionExecutable->isClassConstructorFunction();
+ case CallData::Type::Native:
+ if (callData.native.isBoundFunction)
+ return false;
+ return value.isConstructor();
+ }
+ return false;
}
bool JSC__JSValue__isCell(JSC__JSValue JSValue0) { return JSC::JSValue::decode(JSValue0).isCell(); }
bool JSC__JSValue__isCustomGetterSetter(JSC__JSValue JSValue0)
diff --git a/src/bun.js/bindings/exports.zig b/src/bun.js/bindings/exports.zig
index 73a26e4be..db6de2ef3 100644
--- a/src/bun.js/bindings/exports.zig
+++ b/src/bun.js/bindings/exports.zig
@@ -1417,23 +1417,20 @@ pub const ZigConsoleClient = struct {
// If we check an Object has a method table and it does not
// it will crash
- const callable = js_type != .Object and value.isCallable(globalThis.vm());
-
- if (value.isClass(globalThis) and !callable) {
- return .{
- .tag = .Object,
- .cell = js_type,
- };
- }
+ if (js_type != .Object and value.isCallable(globalThis.vm())) {
+ if (value.isClass(globalThis)) {
+ return .{
+ .tag = .Class,
+ .cell = js_type,
+ };
+ }
- if (callable and js_type == .JSFunction) {
- return .{
- .tag = .Function,
- .cell = js_type,
- };
- } else if (callable and js_type == .InternalFunction) {
return .{
- .tag = .Object,
+ // TODO: we print InternalFunction as Object because we have a lot of
+ // callable namespaces and printing the contents of it is better than [Function: namespace]
+ // ideally, we would print [Function: namespace] { ... } on all functions, internal and js.
+ // what we'll do later is rid of .Function and .Class and handle the prefix in the .Object formatter
+ .tag = if (js_type == .InternalFunction) .Object else .Function,
.cell = js_type,
};
}
@@ -1756,7 +1753,7 @@ pub const ZigConsoleClient = struct {
parent: JSValue,
const enable_ansi_colors = enable_ansi_colors_;
pub fn handleFirstProperty(this: *@This(), globalThis: *JSC.JSGlobalObject, value: JSValue) void {
- if (!value.jsType().isFunction() and !value.isClass(globalThis)) {
+ if (!value.jsType().isFunction()) {
var writer = WrappedWriter(Writer){
.ctx = this.writer,
.failed = false,
@@ -2094,9 +2091,9 @@ pub const ZigConsoleClient = struct {
this.addForNewLine(printable.len);
if (printable.len == 0) {
- writer.print(comptime Output.prettyFmt("[class]", enable_ansi_colors), .{});
+ writer.print(comptime Output.prettyFmt("<cyan>[class]<r>", enable_ansi_colors), .{});
} else {
- writer.print(comptime Output.prettyFmt("[class <cyan>{}<r>]", enable_ansi_colors), .{printable});
+ writer.print(comptime Output.prettyFmt("<cyan>[class {}]<r>", enable_ansi_colors), .{printable});
}
},
.Function => {
@@ -2106,7 +2103,7 @@ pub const ZigConsoleClient = struct {
if (printable.len == 0) {
writer.print(comptime Output.prettyFmt("<cyan>[Function]<r>", enable_ansi_colors), .{});
} else {
- writer.print(comptime Output.prettyFmt("<cyan>[Function<d>:<r> <cyan>{}]<r>", enable_ansi_colors), .{printable});
+ writer.print(comptime Output.prettyFmt("<cyan>[Function: {}]<r>", enable_ansi_colors), .{printable});
}
},
.Getter => {
@@ -2802,7 +2799,7 @@ pub const ZigConsoleClient = struct {
}
if (iter.i == 0) {
- if (value.isClass(this.globalThis) and !value.isCallable(this.globalThis.vm()))
+ if (value.isClass(this.globalThis))
this.printAs(.Class, Writer, writer_, value, jsType, enable_ansi_colors)
else if (value.isCallable(this.globalThis.vm()))
this.printAs(.Function, Writer, writer_, value, jsType, enable_ansi_colors)
diff --git a/src/bun.js/test/pretty_format.zig b/src/bun.js/test/pretty_format.zig
index 4a245c3bb..a6c6aa631 100644
--- a/src/bun.js/test/pretty_format.zig
+++ b/src/bun.js/test/pretty_format.zig
@@ -423,23 +423,20 @@ pub const JestPrettyFormat = struct {
// If we check an Object has a method table and it does not
// it will crash
- const callable = js_type != .Object and value.isCallable(globalThis.vm());
+ if (js_type != .Object and value.isCallable(globalThis.vm())) {
+ if (value.isClass(globalThis)) {
+ return .{
+ .tag = .Class,
+ .cell = js_type,
+ };
+ }
- if (value.isClass(globalThis) and !callable) {
return .{
- .tag = .Object,
- .cell = js_type,
- };
- }
-
- if (callable and js_type == .JSFunction) {
- return .{
- .tag = .Function,
- .cell = js_type,
- };
- } else if (callable and js_type == .InternalFunction) {
- return .{
- .tag = .Object,
+ // TODO: we print InternalFunction as Object because we have a lot of
+ // callable namespaces and printing the contents of it is better than [Function: namespace]
+ // ideally, we would print [Function: namespace] { ... } on all functions, internal and js.
+ // what we'll do later is rid of .Function and .Class and handle the prefix in the .Object formatter
+ .tag = if (js_type == .InternalFunction) .Object else .Function,
.cell = js_type,
};
}
@@ -750,7 +747,7 @@ pub const JestPrettyFormat = struct {
parent: JSValue,
const enable_ansi_colors = enable_ansi_colors_;
pub fn handleFirstProperty(this: *@This(), globalThis: *JSC.JSGlobalObject, value: JSValue) void {
- if (!value.jsType().isFunction() and !value.isClass(globalThis)) {
+ if (!value.jsType().isFunction()) {
var writer = WrappedWriter(Writer){
.ctx = this.writer,
.failed = false,
@@ -1126,13 +1123,20 @@ pub const JestPrettyFormat = struct {
this.addForNewLine(printable.len);
if (printable.len == 0) {
- writer.print(comptime Output.prettyFmt("[class]", enable_ansi_colors), .{});
+ writer.print(comptime Output.prettyFmt("<cyan>[class]<r>", enable_ansi_colors), .{});
} else {
- writer.print(comptime Output.prettyFmt("[class <cyan>{}<r>]", enable_ansi_colors), .{printable});
+ writer.print(comptime Output.prettyFmt("<cyan>[class {}]<r>", enable_ansi_colors), .{printable});
}
},
.Function => {
- writer.writeAll("[Function]");
+ var printable = ZigString.init(&name_buf);
+ value.getNameProperty(this.globalThis, &printable);
+
+ if (printable.len == 0) {
+ writer.print(comptime Output.prettyFmt("<cyan>[Function]<r>", enable_ansi_colors), .{});
+ } else {
+ writer.print(comptime Output.prettyFmt("<cyan>[Function: {}]<r>", enable_ansi_colors), .{printable});
+ }
},
.Array => {
const len = @truncate(u32, value.getLength(this.globalThis));
diff --git a/test/js/web/console/console-log.expected.txt b/test/js/web/console/console-log.expected.txt
index 97191c8be..332322665 100644
--- a/test/js/web/console/console-log.expected.txt
+++ b/test/js/web/console/console-log.expected.txt
@@ -1,4 +1,6 @@
Hello World!
+0
+-0
123
-123
123.567
@@ -7,6 +9,8 @@ true
false
null
undefined
+Infinity
+-Infinity
Symbol(Symbol Description)
2000-06-27T02:24:34.304Z
[ 123, 456, 789 ]
@@ -29,7 +33,9 @@ Symbol(Symbol Description)
}
Promise { <pending> }
[Function]
-[Function: Foo]
+[Function]
+[class Foo]
+[class]
{}
[Function: foooo]
/FooRegex/
diff --git a/test/js/web/console/console-log.js b/test/js/web/console/console-log.js
index e23a3e9cb..4db40aaac 100644
--- a/test/js/web/console/console-log.js
+++ b/test/js/web/console/console-log.js
@@ -1,4 +1,6 @@
console.log("Hello World!");
+console.log(0);
+console.log(-0);
console.log(123);
console.log(-123);
console.log(123.567);
@@ -7,6 +9,8 @@ console.log(true);
console.log(false);
console.log(null);
console.log(undefined);
+console.log(Infinity);
+console.log(-Infinity);
console.log(Symbol("Symbol Description"));
console.log(new Date(Math.pow(2, 34) * 56));
console.log([123, 456, 789]);
@@ -27,7 +31,9 @@ console.log(new Promise(() => {}));
class Foo {}
console.log(() => {});
+console.log(function () {});
console.log(Foo);
+console.log(class {});
console.log(new Foo());
console.log(function foooo() {});