mirror of
https://github.com/oven-sh/bun
synced 2026-02-02 15:08:46 +00:00
fix(timers): add _idleStart property to Timeout object (#26021)
## Summary
- Add `_idleStart` property (getter/setter) to the Timeout object
returned by `setTimeout()` and `setInterval()`
- The property returns a monotonic timestamp (in milliseconds)
representing when the timer was created
- This mimics Node.js's behavior where `_idleStart` is the libuv
timestamp at timer creation time
## Test plan
- [x] Verified test fails with `USE_SYSTEM_BUN=1 bun test
test/regression/issue/25639.test.ts`
- [x] Verified test passes with `bun bd test
test/regression/issue/25639.test.ts`
- [x] Manual verification:
```bash
# Bun with fix - _idleStart exists
./build/debug/bun-debug -e "const t = setTimeout(() => {}, 0);
console.log('_idleStart' in t, typeof t._idleStart); clearTimeout(t)"
# Output: true number
# Node.js reference - same behavior
node -e "const t = setTimeout(() => {}, 0); console.log('_idleStart' in
t, typeof t._idleStart); clearTimeout(t)"
# Output: true number
```
Closes #25639
🤖 Generated with [Claude Code](https://claude.com/claude-code)
---------
Co-authored-by: Claude Bot <claude-bot@bun.sh>
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
64
test/regression/issue/25639.test.ts
Normal file
64
test/regression/issue/25639.test.ts
Normal file
@@ -0,0 +1,64 @@
|
||||
import { expect, test } from "bun:test";
|
||||
|
||||
// GitHub Issue #25639: setTimeout Timeout object missing _idleStart property
|
||||
// Next.js 16 uses _idleStart to coordinate timers for Cache Components
|
||||
|
||||
test("setTimeout returns Timeout object with _idleStart property", () => {
|
||||
const timer = setTimeout(() => {}, 100);
|
||||
|
||||
try {
|
||||
// Verify _idleStart exists and is a number
|
||||
expect("_idleStart" in timer).toBe(true);
|
||||
expect(typeof timer._idleStart).toBe("number");
|
||||
|
||||
// _idleStart should be a positive timestamp
|
||||
expect(timer._idleStart).toBeGreaterThan(0);
|
||||
} finally {
|
||||
clearTimeout(timer);
|
||||
}
|
||||
});
|
||||
|
||||
test("setInterval returns Timeout object with _idleStart property", () => {
|
||||
const timer = setInterval(() => {}, 100);
|
||||
|
||||
try {
|
||||
// Verify _idleStart exists and is a number
|
||||
expect("_idleStart" in timer).toBe(true);
|
||||
expect(typeof timer._idleStart).toBe("number");
|
||||
|
||||
// _idleStart should be a positive timestamp
|
||||
expect(timer._idleStart).toBeGreaterThan(0);
|
||||
} finally {
|
||||
clearInterval(timer);
|
||||
}
|
||||
});
|
||||
|
||||
test("_idleStart is writable (Next.js modifies it to coordinate timers)", () => {
|
||||
const timer = setTimeout(() => {}, 100);
|
||||
|
||||
try {
|
||||
const originalIdleStart = timer._idleStart;
|
||||
expect(typeof originalIdleStart).toBe("number");
|
||||
|
||||
// Next.js sets _idleStart to coordinate timers
|
||||
const newIdleStart = originalIdleStart - 100;
|
||||
timer._idleStart = newIdleStart;
|
||||
expect(timer._idleStart).toBe(newIdleStart);
|
||||
} finally {
|
||||
clearTimeout(timer);
|
||||
}
|
||||
});
|
||||
|
||||
test("timers created at different times have different _idleStart values", async () => {
|
||||
const timer1 = setTimeout(() => {}, 100);
|
||||
// Wait a bit to ensure different timestamp
|
||||
await Bun.sleep(10);
|
||||
const timer2 = setTimeout(() => {}, 100);
|
||||
|
||||
try {
|
||||
expect(timer2._idleStart).toBeGreaterThanOrEqual(timer1._idleStart);
|
||||
} finally {
|
||||
clearTimeout(timer1);
|
||||
clearTimeout(timer2);
|
||||
}
|
||||
});
|
||||
Reference in New Issue
Block a user