Skip to content

Conversation

Pranav2612000
Copy link
Contributor

What does this PR do?

How did you verify your code works?

Ran the following scripts on a debug build to ensure they return the expected output

// Case 1: empty array with extra property
const a = [];
a.field = 1;
console.log(a); // Returns [ field: 1 ]

// Case 2: non-empty array with extra property
const b = [1, 2, 3];
b.field = 1;
console.log(b); // Returns [ 1, 2, 3, field: 1 ]

// Case 3: Empty array
const c = [];
console.log(c); // Returns []

// Case 4: Multiple properties on empty array
const d = [];
d.field1 = 1;
d.field2 = 2;
console.log(d); // Returns [ field1: 1, field2: 2 ]

// Case 5: Multiple properties on non empty array
const e = [1, 2, 3];
e.field1 = 1;
e.field2 = 2;
console.log(e); // Returns [ 1, 2, 3, field1: 1, field2: 2 ]

Copy link
Contributor

coderabbitai bot commented Oct 7, 2025

Walkthrough

Modify console object formatting to include non-indexed properties when printing empty arrays/objects and adjust comma/space emission logic for first and subsequent properties during property iteration.

Changes

Cohort / File(s) Summary
Console formatting logic
src/bun.js/ConsoleObject.zig
- Add handling to iterate non-indexed properties for empty arrays/objects: emit '['/'{', enable quoting, run an iterator over non-indexed properties, conditionally emit a separating space if properties were printed, then close with ']'/'}'.
- Adjust PropertyIterator.forEach comma logic: distinguish ctx.i == 1 (compute should_print_comma based on parent array length) from ctx.i > 1 (emit comma as before), changing when commas/spaces are emitted for first vs subsequent properties.
Console tests (expected output)
test/js/web/console/console-log.expected.txt
- Add expected outputs covering arrays with extra/non-indexed properties (including empty arrays) and multi-property cases to reflect the updated formatting (e.g. [ field_1: "field_1" ], [ 1, 2, 3, field_1: "field_1" ], etc.).
Console tests (test file)
test/js/web/console/console-log.js
- Append new tests that attach custom properties to empty and non-empty arrays to validate that console output now prints non-indexed properties consistently.

Pre-merge checks

✅ Passed checks (4 passed)
Check name Status Explanation
Title Check ✅ Passed The pull request title clearly states the main change of printing custom properties on empty arrays in the console and succinctly highlights the bug fix without extraneous detail, making it easy for reviewers to understand the purpose at a glance.
Linked Issues Check ✅ Passed The changes implement the linked issue requirement by enabling console.log to print custom properties on empty arrays and adding corresponding tests, thus aligning Bun’s behavior with Node.js as specified in issue #22790.
Out of Scope Changes Check ✅ Passed All modifications are confined to the console printing logic and associated tests for custom property rendering on empty arrays, with no unrelated files or features altered beyond the scope of the linked issue.
Description Check ✅ Passed The description follows the repository template by providing both a clear explanation of what the PR does and detailed verification steps with script examples, demonstrating how each case was tested and fulfilling the required sections.

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 4705f34 and 4ab982d.

📒 Files selected for processing (3)
  • src/bun.js/ConsoleObject.zig (2 hunks)
  • test/js/web/console/console-log.expected.txt (1 hunks)
  • test/js/web/console/console-log.js (1 hunks)
🧰 Additional context used
📓 Path-based instructions (9)
test/**

📄 CodeRabbit inference engine (.cursor/rules/writing-tests.mdc)

Place all tests under the test/ directory

Files:

  • test/js/web/console/console-log.expected.txt
  • test/js/web/console/console-log.js
test/js/**

📄 CodeRabbit inference engine (test/CLAUDE.md)

Organize unit tests for specific features under test/js/ by module

Files:

  • test/js/web/console/console-log.expected.txt
  • test/js/web/console/console-log.js
test/js/web/**

📄 CodeRabbit inference engine (CLAUDE.md)

Place Web API tests under test/js/web/

Files:

  • test/js/web/console/console-log.expected.txt
  • test/js/web/console/console-log.js
test/js/**/*.{js,ts}

📄 CodeRabbit inference engine (.cursor/rules/writing-tests.mdc)

Place JavaScript and TypeScript tests under test/js/

Files:

  • test/js/web/console/console-log.js
test/js/web/**/*.{js,ts}

📄 CodeRabbit inference engine (.cursor/rules/writing-tests.mdc)

Place Web API tests under test/js/web/, separated by category

Files:

  • test/js/web/console/console-log.js
test/**/*.{js,ts}

📄 CodeRabbit inference engine (.cursor/rules/writing-tests.mdc)

test/**/*.{js,ts}: Write tests in JavaScript or TypeScript using Bun’s Jest-style APIs (test, describe, expect) and run with bun test
Prefer data-driven tests (e.g., test.each) to reduce boilerplate
Use shared utilities from test/harness.ts where applicable

Files:

  • test/js/web/console/console-log.js
**/*.zig

📄 CodeRabbit inference engine (.cursor/rules/javascriptcore-class.mdc)

**/*.zig: Declare the extern C symbol in Zig and export a Zig-friendly alias for use
Wrap the Bun____toJS extern in a Zig method that takes a JSGlobalObject and returns JSC.JSValue

Files:

  • src/bun.js/ConsoleObject.zig
src/bun.js/**/*.zig

📄 CodeRabbit inference engine (.cursor/rules/zig-javascriptcore-classes.mdc)

src/bun.js/**/*.zig: In Zig binding structs, expose generated bindings via pub const js = JSC.Codegen.JS and re-export toJS/fromJS/fromJSDirect
Constructors and prototype methods should return bun.JSError!JSC.JSValue to integrate Zig error handling with JS exceptions
Use parameter name globalObject (not ctx) and accept (*JSC.JSGlobalObject, *JSC.CallFrame) in binding methods/constructors
Implement getters as get(this, globalObject) returning JSC.JSValue and matching the .classes.ts interface
Provide deinit() for resource cleanup and finalize() that calls deinit(); use bun.destroy(this) or appropriate destroy pattern
Access JS call data via CallFrame (argument(i), argumentCount(), thisValue()) and throw errors with globalObject.throw(...)
For properties marked cache: true, use the generated Zig accessors (NameSetCached/GetCached) to work with GC-owned values
In finalize() for objects holding JS references, release them using .deref() before destroy

Files:

  • src/bun.js/ConsoleObject.zig
src/**/*.zig

📄 CodeRabbit inference engine (CLAUDE.md)

In Zig code, manage memory carefully and use defer for cleanup of allocations/resources

src/**/*.zig: Use the # prefix to declare private fields in Zig structs (e.g., struct { #foo: u32 })
Prefer decl literals when initializing values in Zig (e.g., const decl: Decl = .{ .binding = 0, .value = 0 })
Place @import directives at the bottom of Zig files
Use @import("bun") instead of @import("root").bun

When adding debug logs in Zig, create a scoped logger and log via Bun APIs: const log = bun.Output.scoped(.${SCOPE}, .hidden); then log("...", .{})

Files:

  • src/bun.js/ConsoleObject.zig

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between d273f7f and 965b958.

📒 Files selected for processing (1)
  • src/bun.js/ConsoleObject.zig (2 hunks)
🧰 Additional context used
📓 Path-based instructions (3)
src/**/*.zig

📄 CodeRabbit inference engine (.cursor/rules/building-bun.mdc)

Implement debug logs in Zig using const log = bun.Output.scoped(.${SCOPE}, false); and invoking log("...", .{})

In Zig code, manage memory carefully and use defer for cleanup of allocations/resources

src/**/*.zig: In Zig source files, place all @import statements at the bottom of the file
Use @import("bun") instead of @import("root").bun when importing Bun in Zig

Files:

  • src/bun.js/ConsoleObject.zig
**/*.zig

📄 CodeRabbit inference engine (.cursor/rules/javascriptcore-class.mdc)

**/*.zig: Declare the extern C symbol in Zig and export a Zig-friendly alias for use
Wrap the Bun____toJS extern in a Zig method that takes a JSGlobalObject and returns JSC.JSValue

Files:

  • src/bun.js/ConsoleObject.zig
src/bun.js/**/*.zig

📄 CodeRabbit inference engine (.cursor/rules/zig-javascriptcore-classes.mdc)

src/bun.js/**/*.zig: In Zig binding structs, expose generated bindings via pub const js = JSC.Codegen.JS and re-export toJS/fromJS/fromJSDirect
Constructors and prototype methods should return bun.JSError!JSC.JSValue to integrate Zig error handling with JS exceptions
Use parameter name globalObject (not ctx) and accept (*JSC.JSGlobalObject, *JSC.CallFrame) in binding methods/constructors
Implement getters as get(this, globalObject) returning JSC.JSValue and matching the .classes.ts interface
Provide deinit() for resource cleanup and finalize() that calls deinit(); use bun.destroy(this) or appropriate destroy pattern
Access JS call data via CallFrame (argument(i), argumentCount(), thisValue()) and throw errors with globalObject.throw(...)
For properties marked cache: true, use the generated Zig accessors (NameSetCached/GetCached) to work with GC-owned values
In finalize() for objects holding JS references, release them using .deref() before destroy

Files:

  • src/bun.js/ConsoleObject.zig
🧠 Learnings (1)
📓 Common learnings
Learnt from: CR
PR: oven-sh/bun#0
File: .cursor/rules/zig-javascriptcore-classes.mdc:0-0
Timestamp: 2025-08-30T00:13:36.815Z
Learning: Applies to src/bun.js/**/*.zig : Constructors and prototype methods should return bun.JSError!JSC.JSValue to integrate Zig error handling with JS exceptions

@Pranav2612000 Pranav2612000 force-pushed the bug/print-custom-properties-on-empty-arrays branch 5 times, most recently from ffc01cf to 4705f34 Compare October 9, 2025 03:17
@Pranav2612000
Copy link
Contributor Author

Rebased with main to fix unrelated failures in CI. Can someone please retrigger the builds?

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

📜 Review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between ffc01cf and 4705f34.

📒 Files selected for processing (1)
  • src/bun.js/ConsoleObject.zig (2 hunks)
🧰 Additional context used
📓 Path-based instructions (3)
**/*.zig

📄 CodeRabbit inference engine (.cursor/rules/javascriptcore-class.mdc)

**/*.zig: Declare the extern C symbol in Zig and export a Zig-friendly alias for use
Wrap the Bun____toJS extern in a Zig method that takes a JSGlobalObject and returns JSC.JSValue

Files:

  • src/bun.js/ConsoleObject.zig
src/bun.js/**/*.zig

📄 CodeRabbit inference engine (.cursor/rules/zig-javascriptcore-classes.mdc)

src/bun.js/**/*.zig: In Zig binding structs, expose generated bindings via pub const js = JSC.Codegen.JS and re-export toJS/fromJS/fromJSDirect
Constructors and prototype methods should return bun.JSError!JSC.JSValue to integrate Zig error handling with JS exceptions
Use parameter name globalObject (not ctx) and accept (*JSC.JSGlobalObject, *JSC.CallFrame) in binding methods/constructors
Implement getters as get(this, globalObject) returning JSC.JSValue and matching the .classes.ts interface
Provide deinit() for resource cleanup and finalize() that calls deinit(); use bun.destroy(this) or appropriate destroy pattern
Access JS call data via CallFrame (argument(i), argumentCount(), thisValue()) and throw errors with globalObject.throw(...)
For properties marked cache: true, use the generated Zig accessors (NameSetCached/GetCached) to work with GC-owned values
In finalize() for objects holding JS references, release them using .deref() before destroy

Files:

  • src/bun.js/ConsoleObject.zig
src/**/*.zig

📄 CodeRabbit inference engine (CLAUDE.md)

In Zig code, manage memory carefully and use defer for cleanup of allocations/resources

src/**/*.zig: Use the # prefix to declare private fields in Zig structs (e.g., struct { #foo: u32 })
Prefer decl literals when initializing values in Zig (e.g., const decl: Decl = .{ .binding = 0, .value = 0 })
Place @import directives at the bottom of Zig files
Use @import("bun") instead of @import("root").bun

When adding debug logs in Zig, create a scoped logger and log via Bun APIs: const log = bun.Output.scoped(.${SCOPE}, .hidden); then log("...", .{})

Files:

  • src/bun.js/ConsoleObject.zig
🔇 Additional comments (1)
src/bun.js/ConsoleObject.zig (1)

1925-1937: LGTM! Comma printing logic correctly handles empty arrays while preserving commas for objects.

The three-way branch correctly addresses the past review concern:

  • For empty arrays (length=0): first property at i=1 has no preceding comma → [ field: 1 ]
  • For non-empty arrays (length>0): properties start at i≥len, always print comma → [ 1, 2, 3, field: 1 ]
  • For plain objects: isArray() returns false, so should_print_comma = true{ a: 1, b: 2 }

The use of isArray() with error handling is cleaner than explicit type-switching.

NodeJS prints custom properties on empty arrays. This commit
adds the same support to bun.
Fixes oven-sh#22790
@Pranav2612000 Pranav2612000 force-pushed the bug/print-custom-properties-on-empty-arrays branch from 4705f34 to 4ab982d Compare October 9, 2025 03:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

console.log does not print custom properties on empty arrays (inconsistent with Node.js)
1 participant