Repository navigation
fix(fs): preserve sub-millisecond precision in stat *Ms properties - #28018
Conversation
The non-BigInt path in `toTimeMS()` was using integer division via `bun.timespec.ms()`, which truncated the nanosecond remainder when converting to milliseconds. This caused `mtimeMs`, `atimeMs`, `ctimeMs`, and `birthtimeMs` to always be whole numbers, whereas Node.js preserves fractional milliseconds (e.g. `1773248895434.0544` vs `1773248895434`). Switch to floating-point arithmetic to preserve sub-millisecond precision. Closes #28017 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
Updated 12:01 PM PT - Mar 11th, 2026
❌ Your commit
🧪 To try this PR locally: bunx bun-pr 28018That installs a local version of the PR into your bun-28018 --bun |
WalkthroughReplaces truncating millisecond computation with a floating-point calculation in Stat.toTimeMS to preserve sub-millisecond precision; adds a regression test that verifies fractional Changes
🚥 Pre-merge checks | ✅ 4✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@test/regression/issue/28017.test.ts`:
- Around line 5-24: Replace the nondeterministic use of import.meta.path with a
deterministic temp file created via harness.tempDir: create a tempDir, write a
test file into it, set known fractional atime/mtime using fs.utimes or
fs.utimesSync (so the timestamps include a fractional millisecond component you
control), then call statSync and await stat on that temp file and assert that
the returned mtimeMs/atimeMs (and other *Ms values if needed) exactly match the
expected fractional values; update the test named "fs.stat *Ms properties
preserve sub-millisecond precision" to remove reliance on import.meta.path and
use the tempDir-created file and controlled utimes instead.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
Run ID: ad912789-03f3-45c5-9c9e-5df1056baa0b
📒 Files selected for processing (2)
src/bun.js/node/Stat.zigtest/regression/issue/28017.test.ts
|
Found 1 issue this PR may fix:
🤖 Generated with Claude Code |
Use tempDir and utimesSync to set known fractional timestamps instead of relying on the filesystem's timestamps of import.meta.path. This makes the test deterministic and verifiable against exact expected values. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@test/regression/issue/28017.test.ts`:
- Around line 26-29: The test currently uses
expect(s.atimeMs).toBeCloseTo(expectedMs, 0) and
expect(s.mtimeMs).toBeCloseTo(expectedMs, 0) which permits ±0.5ms; tighten this
to assert microsecond-level determinism by changing the matcher to use a higher
precision (e.g. toBeCloseTo(expectedMs, 3)) so s.atimeMs and s.mtimeMs are
compared to expectedMs to within 0.001ms (reference symbols: s.atimeMs,
s.mtimeMs, expectedMs, fractionalTime in the test).
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
Run ID: 5319039a-c27a-4fa8-a488-32a39aff6bef
📒 Files selected for processing (1)
test/regression/issue/28017.test.ts
Change toBeCloseTo from precision 0 (±0.5ms) to precision 3 (±0.001ms) since utimes preserves the exact value on this filesystem. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Use a timestamp with 0.5ms fractional part (500 microseconds) and toBeCloseTo precision 1 (±0.05ms) instead of precision 3 (±0.001ms). This ensures the test passes across different filesystem timestamp resolutions (APFS nanosecond vs utimes microsecond precision). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…ven-sh#28018) ## Summary - Fix `fs.stat` truncating sub-millisecond precision from `mtimeMs`, `atimeMs`, `ctimeMs`, and `birthtimeMs` properties - The non-BigInt path in `toTimeMS()` was using `bun.timespec.ms()` which performs integer division, losing the nanosecond remainder - Switch to floating-point arithmetic so fractional milliseconds are preserved, matching Node.js behavior ## Before ``` $ bun mtime-test.js mtimeMs: 1773248895434 ``` ## After ``` $ bun mtime-test.js mtimeMs: 1773248895434.0544 ``` ## Test plan - [x] Added regression test `test/regression/issue/28017.test.ts` that verifies `*Ms` properties have fractional components - [x] Test fails with system bun (`USE_SYSTEM_BUN=1`) and passes with debug build - [x] Existing stat tests (`fs-stats-truncate.test.ts`) still pass Closes oven-sh#28017 Closes oven-sh#21943 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Bot <claude-bot@bun.sh> Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…ven-sh#28018) ## Summary - Fix `fs.stat` truncating sub-millisecond precision from `mtimeMs`, `atimeMs`, `ctimeMs`, and `birthtimeMs` properties - The non-BigInt path in `toTimeMS()` was using `bun.timespec.ms()` which performs integer division, losing the nanosecond remainder - Switch to floating-point arithmetic so fractional milliseconds are preserved, matching Node.js behavior ## Before ``` $ bun mtime-test.js mtimeMs: 1773248895434 ``` ## After ``` $ bun mtime-test.js mtimeMs: 1773248895434.0544 ``` ## Test plan - [x] Added regression test `test/regression/issue/28017.test.ts` that verifies `*Ms` properties have fractional components - [x] Test fails with system bun (`USE_SYSTEM_BUN=1`) and passes with debug build - [x] Existing stat tests (`fs-stats-truncate.test.ts`) still pass Closes oven-sh#28017 Closes oven-sh#21943 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Bot <claude-bot@bun.sh> Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Summary
fs.stattruncating sub-millisecond precision frommtimeMs,atimeMs,ctimeMs, andbirthtimeMspropertiestoTimeMS()was usingbun.timespec.ms()which performs integer division, losing the nanosecond remainderBefore
After
Test plan
test/regression/issue/28017.test.tsthat verifies*Msproperties have fractional componentsUSE_SYSTEM_BUN=1) and passes with debug buildfs-stats-truncate.test.ts) still passCloses #28017
Closes #21943
🤖 Generated with Claude Code