Skip to content

fix: accept duck-typed TemporalDuration when Temporal absent from global#574

Merged
fatso83 merged 1 commit into
sinonjs:mainfrom
SimenB:temporal-duck-typed-duration
May 5, 2026
Merged

fix: accept duck-typed TemporalDuration when Temporal absent from global#574
fatso83 merged 1 commit into
sinonjs:mainfrom
SimenB:temporal-duck-typed-duration

Conversation

@SimenB

@SimenB SimenB commented May 5, 2026

Copy link
Copy Markdown
Member

I tried to use the new Temporal stuff in Jest, and hit this 😀

tickValueToMs gated the Duration duck-type check behind isPresent.Temporal, so any object with a .total() method fell through to parseTime() and threw TypeError: str.split is not a function when Temporal was absent from the faked global.

The guard doesn't belong here. Accepting a Duration as input to tick() is purely duck-typed - durationToMs just calls duration.total(...), it has no dependency on the native Temporal global. The isPresent.Temporal guard is correct for faking Temporal.Now.* (which has to construct real Temporal objects as return values), not for accepting input.

Two changes:

  • Remove isPresent.Temporal && from the duck-type check in tickValueToMs
  • Make durationToMs omit relativeTo when NativeTemporal is unavailable — calendar-unit durations will throw from within .total() itself, which is the right place for that error

tick(), tickAsync(), and jump() all go through tickValueToMs so all three get the fix.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Fixes tick()/tickAsync()/jump() handling of Temporal.Duration-like (duck-typed) inputs when Temporal is not available on the faked global, preventing those values from falling through to parseTime() and throwing a confusing str.split is not a function.

Changes:

  • Remove the isPresent.Temporal gate from the duck-type .total() check in tickValueToMs.
  • Update durationToMs to omit relativeTo when NativeTemporal is unavailable.
  • Add a regression test for ticking with a TemporalDuration-shaped object in a Temporal-free global.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

File Description
src/fake-timers-src.js Accept duck-typed durations independent of Temporal presence; make relativeTo conditional on NativeTemporal.
test/fake-timers-test.js Adds a regression test for duck-typed TemporalDuration inputs when Temporal is absent.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread test/fake-timers-test.js
Comment on lines +6641 to +6648
it("tick() accepts a TemporalDuration-shaped object even when Temporal is absent from the global", function () {
const clock = FakeTimers.createClock(0);
// duck-typed Duration: total("millisecond") returns ms, no native Temporal required
const duration = {
total: ({ unit }) => (unit === "millisecond" ? 5000 : 5),
};
clock.tick(duration);
assert.equals(clock.now, 5000);
Comment thread test/fake-timers-test.js

it("tick() accepts a TemporalDuration-shaped object even when Temporal is absent from the global", function () {
const clock = FakeTimers.createClock(0);
// duck-typed Duration: total("millisecond") returns ms, no native Temporal required
@fatso83 fatso83 merged commit 466d18e into sinonjs:main May 5, 2026
17 checks passed
@SimenB SimenB deleted the temporal-duck-typed-duration branch May 5, 2026 22:16
@fatso83

fatso83 commented May 5, 2026

Copy link
Copy Markdown
Contributor

agh, clumsy tired fingers. I was too trigger happy. I saw this might have pending changes. Just re-open and issue a revert on my merge if you need to (if you wanted to address something else)

This is my sign to tuck in. God natt 💤

@SimenB

SimenB commented May 5, 2026

Copy link
Copy Markdown
Member Author

I'll take a look tomorrow. Natta 😀

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.

3 participants