From 57b568d1da84a6afc5bd10a9b0bfef45eccf3898 Mon Sep 17 00:00:00 2001 From: lif <1835304752@qq.com> Date: Wed, 17 Dec 2025 23:47:12 +0800 Subject: [PATCH 1/2] fix(console): properly identify Generator and AsyncGenerator in console.log Fixes #18324 When logging generator and async generator objects, Bun was incorrectly displaying them as `{}` instead of showing their type identifier like `AsyncGenerator {}` or `Generator {}`. The issue was that Generator and AsyncGenerator JSTypes were not included in the list of types that should be formatted as Object in the ConsoleObject formatter. Instead, they fell through to the JSON format, which just outputs `{}` for empty objects. Before: ``` async function* asyncGen() { yield 1; } console.log(asyncGen()); // Output: {} ``` After: ``` async function* asyncGen() { yield 1; } console.log(asyncGen()); // Output: AsyncGenerator {} ``` This matches the expected behavior where generators are properly identified by their type name. --- src/bun.js/ConsoleObject.zig | 2 + test/regression/issue/18324.test.ts | 134 ++++++++++++++++++++++++++++ 2 files changed, 136 insertions(+) create mode 100644 test/regression/issue/18324.test.ts diff --git a/src/bun.js/ConsoleObject.zig b/src/bun.js/ConsoleObject.zig index b9a24edf187b..d06810ddca19 100644 --- a/src/bun.js/ConsoleObject.zig +++ b/src/bun.js/ConsoleObject.zig @@ -1338,6 +1338,8 @@ pub const Formatter = struct { .JSArrayIterator, .Iterator, .IteratorHelper, + .Generator, + .AsyncGenerator, .Object, .FinalObject, .ModuleNamespaceObject, diff --git a/test/regression/issue/18324.test.ts b/test/regression/issue/18324.test.ts new file mode 100644 index 000000000000..d372e970a546 --- /dev/null +++ b/test/regression/issue/18324.test.ts @@ -0,0 +1,134 @@ +import { test, expect } from "bun:test"; +import { bunEnv, bunExe } from "harness"; + +// Issue #18324: Async generator function are not properly identified in console.log +// https://github.com/oven-sh/bun/issues/18324 +// +// When logging an async generator, Bun shows `{}` instead of something like +// `Object [AsyncGenerator] {}` (Node.js) or `AsyncGenerator {}`. + +test("console.log should properly identify async generator objects", async () => { + await using proc = Bun.spawn({ + cmd: [ + bunExe(), + "-e", + ` +async function* arrayToIter(requests) { + for (const request of requests) { + yield await Promise.resolve(request); + } +} +console.log(arrayToIter([])); +`, + ], + env: bunEnv, + stdout: "pipe", + stderr: "pipe", + }); + + const [stdout, stderr, exitCode] = await Promise.all([ + proc.stdout.text(), + proc.stderr.text(), + proc.exited, + ]); + + // Should NOT be just `{}` - should contain some identifier for AsyncGenerator + expect(stdout.trim()).not.toBe("{}"); + // Should contain "AsyncGenerator" in the output + expect(stdout).toContain("AsyncGenerator"); + + expect(exitCode).toBe(0); +}); + +test("console.log should properly identify regular generator objects", async () => { + await using proc = Bun.spawn({ + cmd: [ + bunExe(), + "-e", + ` +function* gen() { + yield 1; + yield 2; +} +console.log(gen()); +`, + ], + env: bunEnv, + stdout: "pipe", + stderr: "pipe", + }); + + const [stdout, stderr, exitCode] = await Promise.all([ + proc.stdout.text(), + proc.stderr.text(), + proc.exited, + ]); + + // Should NOT be just `{}` - should contain some identifier for Generator + expect(stdout.trim()).not.toBe("{}"); + // Should contain "Generator" in the output + expect(stdout).toContain("Generator"); + + expect(exitCode).toBe(0); +}); + +test("console.log shows generator state when it has yielded values", async () => { + await using proc = Bun.spawn({ + cmd: [ + bunExe(), + "-e", + ` +async function* asyncGen() { + yield 1; + yield 2; +} +const g = asyncGen(); +await g.next(); // consume first value +console.log(g); +`, + ], + env: bunEnv, + stdout: "pipe", + stderr: "pipe", + }); + + const [stdout, stderr, exitCode] = await Promise.all([ + proc.stdout.text(), + proc.stderr.text(), + proc.exited, + ]); + + // Should contain AsyncGenerator identifier + expect(stdout).toContain("AsyncGenerator"); + + expect(exitCode).toBe(0); +}); + +test("Bun.inspect should properly identify async generator", async () => { + await using proc = Bun.spawn({ + cmd: [ + bunExe(), + "-e", + ` +async function* asyncGen() { + yield 1; +} +console.log(Bun.inspect(asyncGen())); +`, + ], + env: bunEnv, + stdout: "pipe", + stderr: "pipe", + }); + + const [stdout, stderr, exitCode] = await Promise.all([ + proc.stdout.text(), + proc.stderr.text(), + proc.exited, + ]); + + // Should contain AsyncGenerator identifier + expect(stdout).toContain("AsyncGenerator"); + + expect(exitCode).toBe(0); +}); From 87791f710cac9206b8e0d35b968ef318d032b39a Mon Sep 17 00:00:00 2001 From: lif <1835304752@qq.com> Date: Thu, 18 Dec 2025 00:46:32 +0800 Subject: [PATCH 2/2] test: use test.concurrent for parallel execution --- test/regression/issue/18324.test.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/regression/issue/18324.test.ts b/test/regression/issue/18324.test.ts index d372e970a546..809098bc22df 100644 --- a/test/regression/issue/18324.test.ts +++ b/test/regression/issue/18324.test.ts @@ -7,7 +7,7 @@ import { bunEnv, bunExe } from "harness"; // When logging an async generator, Bun shows `{}` instead of something like // `Object [AsyncGenerator] {}` (Node.js) or `AsyncGenerator {}`. -test("console.log should properly identify async generator objects", async () => { +test.concurrent("console.log should properly identify async generator objects", async () => { await using proc = Bun.spawn({ cmd: [ bunExe(), @@ -40,7 +40,7 @@ console.log(arrayToIter([])); expect(exitCode).toBe(0); }); -test("console.log should properly identify regular generator objects", async () => { +test.concurrent("console.log should properly identify regular generator objects", async () => { await using proc = Bun.spawn({ cmd: [ bunExe(), @@ -72,7 +72,7 @@ console.log(gen()); expect(exitCode).toBe(0); }); -test("console.log shows generator state when it has yielded values", async () => { +test.concurrent("console.log shows generator state when it has yielded values", async () => { await using proc = Bun.spawn({ cmd: [ bunExe(), @@ -104,7 +104,7 @@ console.log(g); expect(exitCode).toBe(0); }); -test("Bun.inspect should properly identify async generator", async () => { +test.concurrent("Bun.inspect should properly identify async generator", async () => { await using proc = Bun.spawn({ cmd: [ bunExe(),