Repository navigation
Conversation
A Map row fills only the Key and Values columns. `TablePrinter::print_table` pushed one column per `properties` entry all the same, so each of those columns was empty in every row, and an entry whose conversion throws stopped a table that never uses it. The `properties` columns are now created only when `JSType::is_map()` is false for the data. That test is the one that adds the Key column and that sends a row to the Map branch of `collect_row`. It matches a WeakMap as well as a Map, so a WeakMap with `properties` changes in the same way. This applies to `console.table` and to `Bun.inspect.table`.
|
Reproduced on main (449877f) and on bun 1.4.2: console.table(new Map([["k", 1]]), ["a"]);Column CI status (c3bec93, build #133279) The diff is green. 179 of 181 jobs passed, and no test is red.
Ready for review. |
|
Updated 4:57 PM PT - Oct 26th, 2026
✅ @robobun, your commit c3bec93ff33170d42b7ce6c12fdd6622e06389e0 passed in 🧪 To try this PR locally: bunx bun-pr 47014That installs a local version of the PR into your bun-47014 --bun |
|
No actionable comments were generated in the recent review.
|
| Layer / File(s) | Summary |
|---|---|
Map table columns and output tests src/jsc/ConsoleObject.rs, test/js/bun/console/bun-inspect-table.test.ts |
Map tables no longer add columns from the properties argument. Tests cover Map subclasses, duplicate column names, non-string and Symbol entries, empty Maps and WeakMaps, Maps used as rows, and subprocess output. |
Suggested reviewers: jarred-sumner
Priority:
Merge Risk: 
Minimal · up to c3bec
-
Merge Risk: ⚪ Minimal · up to
c3becNo merge-blocking issue is identified for the Map table column change.
Pre-merge checks: 
4
-
Full details: Description check
-
Explanation
The description explains the problem, implementation, scope, behavior changes, limitations, and verification results. It does not use the template headings exactly, but it provides the required information and is substantially complete.
-
Finishing Touches: 💡 1
-
🛠️ Fix failing CI checks: 💡
-
- Commit to this branch
- Create a new PR
-
- Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts
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.
Comment @coderabbitai help to get the list of available commands.
Problem
console.table(map, properties)andBun.inspect.table(map, properties)print one empty column for eachpropertiesentry.console.table(new Map([["k", 1]]), ["a"])printsKey | a | Valueswithablank.toString, a Symbol) stops the table, although no row uses it.TablePrinter::print_table(src/jsc/ConsoleObject.rs:894) adds a column for each entry. The Map branch ofcollect_row(:731-745) fills onlyKeyandValues.Fix
print_tableadds thepropertiescolumns only in theelseof theJSType::is_map()test that addsKey. A Map now prints the same table with and withoutproperties.is_map()is also true for a WeakMap, so a WeakMap changes in the same way (see Notes).test/js/bun/console/bun-inspect-table.test.ts(9 new tests, 8 fail without the fix). Also the three console test directories.Background
TablePrinteris the native printer behindconsole.table(also thenode:consoleexport) andBun.inspect.table.collect_rowreads one row and fills its cells.Key, andValuesonce the Map has an entry.propertiesrules of Node.js, which Notes lists. They change valid output, and no user reported them.Notes
Origin
There is no user report. A comparison with Node.js v26.3.0 found this. Node prints
KeyandValuesfor a Map withproperties. The loop dates from the firstconsole.table(#7866).Repro
main (449877f) and bun 1.4.2:
This PR:
["Key", "Values"]printedKey | Key | Values | Values.[{ toString() { throw new Error("x") } }]threwError: x.[Symbol()]threwTypeError: Cannot convert a symbol to a string.Record
A review thread on #46986 (comment) asked for three changes to this loop: no conversion for zero rows, no
propertiescolumn for a Map, and none for a Set. The reply left all three out as a change of the column model. This PR reverses that reply for a Map only.propertiescolumn, so each removed cell is blank.propertiescolumns:new Set([{ a: 1 }])with["a"]printsawith the cell1. That stays.The body of #46986 is not edited. A reply on that thread links this PR.
WeakMap
JSType::is_map()(src/jsc/JSType.rs:782) matches a Map and a WeakMap. The guard uses it on purpose. It is the test that addsKey, andcollect_row(:731) uses the same test before it writescolumns[1](:740). The three uses must stay one predicate.Bun.inspect.table(data, properties)console.tablenew WeakMap(),["a"]Key,aKey(index)Object.assign(new WeakMap(), { x: { a: 1 } }),["a"]Key,a,Values. Rowx:undefined, blank,undefinedKey,Values. Rowx:undefined,undefined(index),a. Rowx:1toStringthrowsTypeError(index)onlyNot in this PR
console.table(new WeakMap())prints aKeyheader (Node:(index)only).Object.assign(new WeakMap(), { x: 5 })prints the rowx | undefined | undefined(Node:Valueswith5). With{ x: null }it throwsTypeError: null is not an object(Node:Valueswithnull). These are the same on main and with this PR. The cause isJSType::is_map()itself, whichis_object_empty(src/jsc/JSValue.rs:2788) also uses. A correction changes that predicate and does not edit this guard. No issue tracks this.Keyalone, with or withoutproperties. Node printsKeyandValues.new Map()with["a"]goes fromKey | atoKey.propertiesrules of Node.js: one column for a repeated entry, integer-like names first, no column for zero rows, Set entries underValues. This PR has only the part where every removed cell is blank.Consoleclass (new console.Console(),node:worker_threadsworkers) is a different printer. This PR does not touch it.Open PRs on the same code
propertiesentries whose key is a Symbol #46986 changes the body of the same loop. The two merge without conflict (checked at f5fc979). Both stop the Symbol throw for a Map. If console.table: skippropertiesentries whose key is a Symbol #46986 merges first, the Symbol test here passes without the guard.is_map()for theKeycolumn. There a WeakMap row is an object row, so this guard must follow that row test when the two meet.Measurements (linux x64, release builds of 449877f with and without the change)
.text: 82,164,617 B in both. Strippedbun: 107,730,656 B in both.print_table::<false>: 3,629 B to 3,640 B.print_table::<true>: 3,709 B to 3,704 B.collect_row: 2,981 B in both.propertiesentry for a Map: 1 to 0.test/js/bun/console/,test/js/web/console/andtest/js/node/console/: 122 pass.Tests
console.tablein a child process.Downsides
propertiesprints fewer columns. An entry that throws no longer throws there..textkeeps its size (82,164,617 B).