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..809098bc22df --- /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.concurrent("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.concurrent("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.concurrent("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.concurrent("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); +});