Skip to content

Temporal: Make ExactTime::difference() return an InternalDuration#45603

Merged
webkit-commit-queue merged 1 commit into
WebKit:mainfrom
catamorphism:balance-precision-part-3
Aug 22, 2025
Merged

Temporal: Make ExactTime::difference() return an InternalDuration#45603
webkit-commit-queue merged 1 commit into
WebKit:mainfrom
catamorphism:balance-precision-part-3

Conversation

@catamorphism

@catamorphism catamorphism commented May 19, 2025

Copy link
Copy Markdown
Contributor

4927ce2

Temporal: Make ExactTime::difference() return an InternalDuration

https://bugs.webkit.org/show_bug.cgi?id=223166

Reviewed by Keith Miller.

TemporalInstant::difference() now calls ExactTime::difference(),
then converts the result back to a Duration.

This enables some of the tests for TemporalInstant/p/since and
TemporalInstant/p/until that previously failed.

As part of this change, implement ExactTime::round() according to the
spec.

* JSTests/stress/temporal-instant.js:
* JSTests/test262/expectations.yaml:
* Source/JavaScriptCore/runtime/ISO8601.cpp:
(JSC::ISO8601::roundTemporalInstant):
(JSC::ISO8601::validateTemporalRoundingIncrement):
(JSC::ISO8601::ExactTime::round const):
(JSC::ISO8601::roundTimeDurationToIncrement):
(JSC::ISO8601::roundTimeDuration):
(JSC::ISO8601::ExactTime::difference const):
(JSC::ISO8601::absInt128): Deleted.
(JSC::ISO8601::ExactTime::round): Deleted.
* Source/JavaScriptCore/runtime/ISO8601.h:
(JSC::ISO8601::ExactTime::absInt128):
* Source/JavaScriptCore/runtime/TemporalDuration.cpp:
(JSC::TemporalDuration::temporalDurationFromInternal):
* Source/JavaScriptCore/runtime/TemporalDuration.h:
* Source/JavaScriptCore/runtime/TemporalInstant.cpp:
* Source/JavaScriptCore/runtime/TemporalObject.cpp:
(JSC::applyUnsignedRoundingMode):
(JSC::roundNumberToIncrementAsIfPositive):
(JSC::roundNumberToIncrementInt128):
* Source/JavaScriptCore/runtime/TemporalObject.h:
(JSC::lengthInNanoseconds):
(JSC::getUnsignedRoundingMode):

Canonical link: https://commits.webkit.org/299050@main

0622f71

Misc iOS, visionOS, tvOS & watchOS macOS Linux Windows
✅ 🧪 style ✅ 🛠 ios ✅ 🛠 mac ✅ 🛠 wpe ✅ 🛠 win
✅ 🛠 ios-sim ✅ 🛠 mac-AS-debug ✅ 🧪 wpe-wk2 🧪 win-tests
✅ 🧪 webkitperl ✅ 🧪 ios-wk2 ✅ 🧪 api-mac 🧪 api-wpe
✅ 🧪 ios-wk2-wpt ✅ 🧪 mac-wk1 ✅ 🛠 wpe-cairo
✅ 🛠 🧪 jsc ✅ 🧪 api-ios ✅ 🧪 mac-wk2 ✅ 🛠 gtk
✅ 🛠 🧪 jsc-arm64 ✅ 🛠 vision ✅ 🧪 mac-AS-debug-wk2 ✅ 🧪 gtk-wk2
✅ 🛠 vision-sim ✅ 🧪 mac-wk2-stress ✅ 🧪 api-gtk
✅ 🛠 🧪 merge ✅ 🧪 vision-wk2 ✅ 🧪 mac-intel-wk2 🛠 playstation
✅ 🛠 tv ✅ 🛠 mac-safer-cpp ✅ 🛠 jsc-armv7
✅ 🛠 tv-sim ❌ 🧪 jsc-armv7-tests
✅ 🛠 watch
✅ 🛠 watch-sim

@catamorphism catamorphism requested a review from a team as a code owner May 19, 2025 19:51
@catamorphism catamorphism self-assigned this May 19, 2025
@catamorphism catamorphism added the JavaScriptCore For bugs in JavaScriptCore, the JS engine used by WebKit, other than kxmlcore issues. label May 19, 2025
@catamorphism catamorphism force-pushed the balance-precision-part-3 branch from f90e056 to abff2e7 Compare May 19, 2025 19:52
return round(diff, increment, unit, roundingMode);
}
VM& vm = globalObject->vm();
auto scope = DECLARE_THROW_SCOPE(vm);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This is not necessary.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I think it's necessary, because ExactTime::difference() calls roundTimeDuration(), which can throw.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Never mind, I misunderstood. Fixed in b6b5887

return ExactTime { round(m_epochNanoseconds, increment, unit, roundingMode) };
Int128 timeDuration = other.m_epochNanoseconds - m_epochNanoseconds;
timeDuration = roundTimeDuration(globalObject, timeDuration, roundingIncrement, smallestUnit, roundingMode);
RETURN_IF_EXCEPTION(scope, { });

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Not necessary.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I think it is? roundTimeDuration() can throw.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Sorry, fixed in b6b5887

TemporalUnit unit, RoundingMode roundingMode)
{
VM& vm = globalObject->vm();
auto scope = DECLARE_THROW_SCOPE(vm);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Not necessary.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Fixed in b6b5887

auto scope = DECLARE_THROW_SCOPE(vm);

auto divisor = lengthInNanoseconds(unit);
RELEASE_AND_RETURN(scope, roundTimeDurationToIncrement(globalObject, timeDuration,

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Just use return roundTimeDurationToIncrement(...).

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I thought it had to be RELEASE_AND_RETURN(...) because roundTimeDurationToIncrement() can throw?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I'm not sure if this is what @Constellation is referring to, but maybe the tail-call style would just use roundTimeDurationToIncrement's throw scope and creating an outer one wouldn't be necessary, since this is the only thing in the scope that can throw? Just a guess, I don't know off the top of my head if that's accurate.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

@ptomato Ah, that's exactly it. Fixed in b6b5887

@ptomato ptomato left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I'm not a reviewer, but I had some suggestions that will hopefully help the actual review.

Comment on lines +430 to +445

// since() and until()
{
const earlier = Temporal.Instant.from("1976-11-18T15:23:30.123456789Z");
const later = Temporal.Instant.from("2019-10-29T10:46:38.271986102Z");
const diff = later.since(earlier);
shouldBe(diff.nanoseconds, 313);
shouldBe(diff.microseconds, 529);
shouldBe(diff.milliseconds, 148);
shouldBe(diff.seconds, 1355167388);
const diff1 = earlier.until(later);
shouldBe(diff1.nanoseconds, diff.nanoseconds);
shouldBe(diff1.microseconds, diff.microseconds);
shouldBe(diff1.milliseconds, diff.milliseconds);
shouldBe(diff1.seconds, diff.seconds);
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Optional: I think this is probably sufficiently covered by test262 and doesn't need an additional stress test; can't hurt though

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I thought that all changes were supposed to have stress tests, but I agree it does overlap with test262.

Comment thread Source/JavaScriptCore/runtime/ISO8601.cpp Outdated
Comment thread Source/JavaScriptCore/runtime/ISO8601.cpp Outdated
microseconds = microseconds % 1000;
} else if (largestUnit == TemporalUnit::Microsecond) {
microseconds = (Int128) std::trunc(std::fma<double, unsigned, double>(
seconds, 6, std::trunc(((double) nanoseconds) / 1000)));

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I think 6 is probably meant to be 10⁶? If so, this should make more test262 tests pass (and if it doesn't, we should add coverage for this)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Good catch! It turns out the code was correct because seconds is always 0. (I got there from following the code in the polyfill, but in the polyfill time durations are represented with seconds and subseconds separately, and in JSC it's a single nanoseconds value.) But the call to std::fma is unnecessary so I changed it in c719f90 to be similar to the other cases.

if (increment == 1)
return x;

// The following code follows the polyfill rather than the spec, because we don't have float128.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I would suggest rephrasing this comment and the one below not to refer to "the polyfill", it's not clear from context here what is meant.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I added links to the relevant code in the polyfill in 86a28f8 -- hopefully that clarifies?

@webkit-ews-buildbot webkit-ews-buildbot added the merging-blocked Applied to prevent a change from being merged label May 23, 2025
Comment on lines +1718 to +1722
case TemporalUnit::Hour: maximum = (Int128) WTF::hoursPerDay; break;
case TemporalUnit::Minute: maximum = (Int128) (minutesPerHour * WTF::hoursPerDay); break;
case TemporalUnit::Second: maximum = (Int128) (secondsPerMinute * minutesPerHour * WTF::hoursPerDay); break;
case TemporalUnit::Millisecond: maximum = (Int128) msPerDay; break;
case TemporalUnit::Microsecond: maximum = (Int128) msPerDay * 1000; break;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

You shouldn't need the (Int128) and if for some reason it is needed WebKit style would be to static_cast<Int128> rather than C-style cast.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I think the cast was necessary to get it to compile on armv7, but I'll try it without.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Yup, armv7 fails if I remove the casts; I re-added them in the static_cast form.

Comment thread Source/JavaScriptCore/runtime/TemporalObject.h Outdated
Comment thread Source/JavaScriptCore/runtime/TemporalObject.h Outdated
Comment thread Source/JavaScriptCore/runtime/TemporalObject.cpp Outdated
Comment thread Source/JavaScriptCore/runtime/TemporalObject.cpp Outdated
Comment thread Source/JavaScriptCore/runtime/TemporalObject.cpp Outdated
Comment thread Source/JavaScriptCore/runtime/TemporalObject.cpp Outdated
Comment thread Source/JavaScriptCore/runtime/TemporalObject.cpp Outdated
Comment thread Source/JavaScriptCore/runtime/TemporalObject.cpp Outdated

@kmiller68 kmiller68 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

r=me

@ptomato

ptomato commented Aug 18, 2025

Copy link
Copy Markdown
Contributor

The win-tests failure seems pretty squarely unrelated.

Tim's out today, but I'd like to move this forward as much as possible. I'll see if I can dig up the next patch in his series and submit that.

@ptomato ptomato added merge-queue Applied to send a pull request to merge-queue and removed merging-blocked Applied to prevent a change from being merged labels Aug 18, 2025
@webkit-commit-queue

Copy link
Copy Markdown
Collaborator

@ptomato does not have committer permissions according to https://raw.githubusercontent.com/WebKit/WebKit/main/metadata/contributors.json.

If you do have committer permissions, please ensure that your GitHub username is added to contributors.json.

Rejecting 5d20d61df4e4a34ef12020a32641d4ce7927a3f5 from merge queue.

@webkit-commit-queue webkit-commit-queue added merging-blocked Applied to prevent a change from being merged and removed merge-queue Applied to send a pull request to merge-queue labels Aug 18, 2025
@ptomato ptomato added the request-merge-queue Request a pull request to be added to merge-queue once ready label Aug 18, 2025
@ptomato

ptomato commented Aug 18, 2025

Copy link
Copy Markdown
Contributor

(Sorry, wrong label.)

@ptomato ptomato removed the merging-blocked Applied to prevent a change from being merged label Aug 18, 2025
@TingPing TingPing added safe-merge-queue Applied to automatically send a pull-request to merge-queue after passing EWS checks and removed request-merge-queue Request a pull request to be added to merge-queue once ready labels Aug 20, 2025
@fujii fujii removed the safe-merge-queue Applied to automatically send a pull-request to merge-queue after passing EWS checks label Aug 22, 2025
@fujii fujii added the unsafe-merge-queue Applied to send a pull request to merge-queue, but skip building and testing label Aug 22, 2025
@webkit-commit-queue

Copy link
Copy Markdown
Collaborator

This change contains multiple commits which are not squashed together, blocking PR #45603. Please squash the commits to land.

@webkit-commit-queue webkit-commit-queue added merging-blocked Applied to prevent a change from being merged and removed unsafe-merge-queue Applied to send a pull request to merge-queue, but skip building and testing labels Aug 22, 2025
@ptomato ptomato force-pushed the balance-precision-part-3 branch from 5d20d61 to 0622f71 Compare August 22, 2025 01:15
@ptomato

ptomato commented Aug 22, 2025

Copy link
Copy Markdown
Contributor

Rebased and squashed.

@sosukesuzuki sosukesuzuki added merge-queue Applied to send a pull request to merge-queue and removed merging-blocked Applied to prevent a change from being merged labels Aug 22, 2025
https://bugs.webkit.org/show_bug.cgi?id=223166

Reviewed by Keith Miller.

TemporalInstant::difference() now calls ExactTime::difference(),
then converts the result back to a Duration.

This enables some of the tests for TemporalInstant/p/since and
TemporalInstant/p/until that previously failed.

As part of this change, implement ExactTime::round() according to the
spec.

* JSTests/stress/temporal-instant.js:
* JSTests/test262/expectations.yaml:
* Source/JavaScriptCore/runtime/ISO8601.cpp:
(JSC::ISO8601::roundTemporalInstant):
(JSC::ISO8601::validateTemporalRoundingIncrement):
(JSC::ISO8601::ExactTime::round const):
(JSC::ISO8601::roundTimeDurationToIncrement):
(JSC::ISO8601::roundTimeDuration):
(JSC::ISO8601::ExactTime::difference const):
(JSC::ISO8601::absInt128): Deleted.
(JSC::ISO8601::ExactTime::round): Deleted.
* Source/JavaScriptCore/runtime/ISO8601.h:
(JSC::ISO8601::ExactTime::absInt128):
* Source/JavaScriptCore/runtime/TemporalDuration.cpp:
(JSC::TemporalDuration::temporalDurationFromInternal):
* Source/JavaScriptCore/runtime/TemporalDuration.h:
* Source/JavaScriptCore/runtime/TemporalInstant.cpp:
* Source/JavaScriptCore/runtime/TemporalObject.cpp:
(JSC::applyUnsignedRoundingMode):
(JSC::roundNumberToIncrementAsIfPositive):
(JSC::roundNumberToIncrementInt128):
* Source/JavaScriptCore/runtime/TemporalObject.h:
(JSC::lengthInNanoseconds):
(JSC::getUnsignedRoundingMode):

Canonical link: https://commits.webkit.org/299050@main
@webkit-commit-queue

Copy link
Copy Markdown
Collaborator

Committed 299050@main (4927ce2): https://commits.webkit.org/299050@main

Reviewed commits have been landed. Closing PR #45603 and removing active labels.

@webkit-commit-queue webkit-commit-queue merged commit 4927ce2 into WebKit:main Aug 22, 2025
@webkit-commit-queue webkit-commit-queue removed the merge-queue Applied to send a pull request to merge-queue label Aug 22, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

JavaScriptCore For bugs in JavaScriptCore, the JS engine used by WebKit, other than kxmlcore issues.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

10 participants