From 06ff8a6d2dfe5181befb6e72a357151d5eaa7cd0 Mon Sep 17 00:00:00 2001 From: Claude Bot Date: Mon, 29 Sep 2025 14:51:24 +0000 Subject: [PATCH] Fix util.inspect negative fractional number formatting with numericSeparator MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes #23098 When numericSeparator: true is set, negative fractional numbers between -1 and 0 (like -0.123) were incorrectly formatted as "0..123" instead of "-0.123". The issue was that Math.trunc(-0.123) returns -0, but String(-0) becomes "0", losing the negative sign. Fixed by checking for -0 with Object.is() and explicitly using "-0" as the string representation. Also fixed scientific notation handling to check the original number string instead of the truncated integer string. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- src/js/internal/util/inspect.js | 12 +++++++++--- test/regression/issue/23098.test.ts | 28 ++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+), 3 deletions(-) create mode 100644 test/regression/issue/23098.test.ts diff --git a/src/js/internal/util/inspect.js b/src/js/internal/util/inspect.js index 2a86431c76..d60d600f3a 100644 --- a/src/js/internal/util/inspect.js +++ b/src/js/internal/util/inspect.js @@ -1967,16 +1967,22 @@ function formatNumber(fn, number, numericSeparator) { return fn(`${number}`, "number"); } const integer = MathTrunc(number); - const string = String(integer); + // Handle -0 specially to preserve the negative sign + const string = ObjectIs(integer, -0) ? "-0" : String(integer); if (integer === number) { - if (!NumberIsFinite(number) || StringPrototypeIncludes(string, "e")) { - return fn(string, "number"); + // Check the original number string for scientific notation, not the integer string + if (!NumberIsFinite(number) || StringPrototypeIncludes(String(number), "e")) { + return fn(`${number}`, "number"); } return fn(`${addNumericSeparator(string)}`, "number"); } if (NumberIsNaN(number)) { return fn(string, "number"); } + // Check the original number string for scientific notation before applying separators + if (StringPrototypeIncludes(String(number), "e")) { + return fn(`${number}`, "number"); + } return fn( `${addNumericSeparator(string)}.${addNumericSeparatorEnd(StringPrototypeSlice(String(number), string.length + 1))}`, "number", diff --git a/test/regression/issue/23098.test.ts b/test/regression/issue/23098.test.ts new file mode 100644 index 0000000000..07a15eddef --- /dev/null +++ b/test/regression/issue/23098.test.ts @@ -0,0 +1,28 @@ +import { test, expect } from "bun:test"; +import { inspect } from "node:util"; + +test("util.inspect formats negative fractional numbers correctly with numericSeparator: true (#23098)", () => { + // Test the specific cases from the issue + const values = [0.1234, -0.12, -0.123, -0.1234, -1.234]; + const text = inspect(values, { numericSeparator: true }); + expect(text).toBe("[ 0.123_4, -0.12, -0.123, -0.123_4, -1.234 ]"); + + // Test individual values + expect(inspect(-0.12, { numericSeparator: true })).toBe("-0.12"); + expect(inspect(-0.123, { numericSeparator: true })).toBe("-0.123"); + expect(inspect(-0.1234, { numericSeparator: true })).toBe("-0.123_4"); + expect(inspect(-0.123456789, { numericSeparator: true })).toBe("-0.123_456_789"); + + // Test edge cases + expect(inspect(-0, { numericSeparator: true })).toBe("-0"); + expect(inspect(0, { numericSeparator: true })).toBe("0"); + + // Test scientific notation doesn't get separators + expect(inspect(1.23e-10, { numericSeparator: true })).toBe("1.23e-10"); + expect(inspect(-1.23e-10, { numericSeparator: true })).toBe("-1.23e-10"); + expect(inspect(1.23e10, { numericSeparator: true })).toBe("12_300_000_000"); + expect(inspect(-1.23e10, { numericSeparator: true })).toBe("-12_300_000_000"); + + // Test large negative numbers still work + expect(inspect(-123456789.123456789, { numericSeparator: true })).toBe("-123_456_789.123_456_79"); +}); \ No newline at end of file