Skip to content

Conversation

@Manishearth
Copy link
Contributor

@Manishearth Manishearth commented Nov 25, 2025

Fixes #635

Updates to tc39/proposal-temporal#3172

This passes the test, but it fails other tests. The problem is probably that IncrementRounder isn't written in terms of r1 and r2. @nekevss, I don't understand the full purpose of IncrementRounder being written the way it is: mind having a look?

The new spec text changes how r1 and r2 are computed, and they're passed down to IncrementRounder in the spec but not the code, so I assume that IncrementRounder is recomputing them somehow from the inputs.

I wrote this to not use IncrementRounder. I'm not 100% sure if the implementation is correct when it comes to how it handles mathematical values.

@Manishearth Manishearth requested a review from nekevss November 25, 2025 02:45
@Manishearth Manishearth marked this pull request as draft November 25, 2025 02:45
@Manishearth
Copy link
Contributor Author

This now passes tests, but I'm not entirely sure of the impl

@Manishearth
Copy link
Contributor Author

Manishearth commented Nov 25, 2025

This fails other tests (due to hitting assertions, I think)

=== test262/built-ins/Temporal/PlainDate/prototype/since/roundingincrement ===
--- stdout ---
test/test262/data/test/built-ins/Temporal/PlainDate/prototype/since/roundingincrement.js:15: Error: Temporal error: Internal error: .
  later.since(earlier, { smallestUnit: "years", roundingIncrement: 4, roundingMode: "halfExpand" }),
        ^
Error: Temporal error: Internal error: .
    at PlainDate.since (<anonymous>)
    at test/test262/data/test/built-ins/Temporal/PlainDate/prototype/since/roundingincrement.js:15:9
Command: out/x64.release/d8 --test test/test262/data/harness/sta.js test/test262/data/harness/assert.js test/test262/harness-adapt.js test/test262/data/harness/temporalHelpers.js test/test262/data/test/built-ins/Temporal/PlainDate/prototype/since/roundingincrement.js --random-seed=1623281705 --nohard-abort --ignore-unhandled-promises --harmony-temporal --no-arguments
=== test262/built-ins/Temporal/PlainDate/prototype/since/roundingincrement ===
--- stdout ---
test/test262/data/test/built-ins/Temporal/PlainDate/prototype/since/roundingincrement.js:15: Error: Temporal error: Internal error: .
  later.since(earlier, { smallestUnit: "years", roundingIncrement: 4, roundingMode: "halfExpand" }),
        ^
Error: Temporal error: Internal error: .
    at PlainDate.since (<anonymous>)
    at test/test262/data/test/built-ins/Temporal/PlainDate/prototype/since/roundingincrement.js:15:9
Command: out/x64.release/d8 --test test/test262/data/harness/sta.js test/test262/data/harness/assert.js test/test262/harness-adapt.js test/test262/data/harness/temporalHelpers.js test/test262/data/test/built-ins/Temporal/PlainDate/prototype/since/roundingincrement.js --random-seed=1623281705 --nohard-abort --use-strict --ignore-unhandled-promises --harmony-temporal --no-arguments
=== test262/built-ins/Temporal/PlainYearMonth/prototype/since/roundingincrement-as-expected ===
--- stdout ---
test/test262/data/test/built-ins/Temporal/PlainYearMonth/prototype/since/roundingincrement-as-expected.js:14: Error: Temporal error: Internal error: .
const laterSinceYear = later.since(earlier, { smallestUnit: "years", roundingIncrement: 4, roundingMode: "halfExpand" });
                             ^
Error: Temporal error: Internal error: .
    at PlainYearMonth.since (<anonymous>)
    at test/test262/data/test/built-ins/Temporal/PlainYearMonth/prototype/since/roundingincrement-as-expected.js:14:30
Command: out/x64.release/d8 --test test/test262/data/harness/sta.js test/test262/data/harness/assert.js test/test262/harness-adapt.js test/test262/data/harness/temporalHelpers.js test/test262/data/test/built-ins/Temporal/PlainYearMonth/prototype/since/roundingincrement-as-expected.js --random-seed=1623281705 --nohard-abort --ignore-unhandled-promises --harmony-temporal --no-arguments
=== test262/built-ins/Temporal/PlainYearMonth/prototype/since/roundingincrement-wrong-type ===
--- stdout ---
test/test262/data/test/built-ins/Temporal/PlainYearMonth/prototype/since/roundingincrement-wrong-type.js:22: Error: Temporal error: Internal error: .
  (roundingIncrement) => later.since(earlier, { roundingIncrement }),
                               ^
Error: Temporal error: Internal error: .
    at PlainYearMonth.since (<anonymous>)
    at test/test262/data/test/built-ins/Temporal/PlainYearMonth/prototype/since/roundingincrement-wrong-type.js:22:32
    at Object.checkRoundingIncrementOptionWrongType (test/test262/data/harness/temporalHelpers.js:509:26)
    at test/test262/data/test/built-ins/Temporal/PlainYearMonth/prototype/since/roundingincrement-wrong-type.js:21:17
Command: out/x64.release/d8 --test test/test262/data/harness/sta.js test/test262/data/harness/assert.js test/test262/harness-adapt.js test/test262/data/harness/compareArray.js test/test262/data/harness/temporalHelpers.js test/test262/data/test/built-ins/Temporal/PlainYearMonth/prototype/since/roundingincrement-wrong-type.js --random-seed=1623281705 --nohard-abort --ignore-unhandled-promises --harmony-temporal --no-arguments
=== test262/built-ins/Temporal/PlainYearMonth/prototype/since/roundingincrement-as-expected ===
--- stdout ---
test/test262/data/test/built-ins/Temporal/PlainYearMonth/prototype/since/roundingincrement-as-expected.js:14: Error: Temporal error: Internal error: .
const laterSinceYear = later.since(earlier, { smallestUnit: "years", roundingIncrement: 4, roundingMode: "halfExpand" });
                             ^
Error: Temporal error: Internal error: .
    at PlainYearMonth.since (<anonymous>)
    at test/test262/data/test/built-ins/Temporal/PlainYearMonth/prototype/since/roundingincrement-as-expected.js:14:30
Command: out/x64.release/d8 --test test/test262/data/harness/sta.js test/test262/data/harness/assert.js test/test262/harness-adapt.js test/test262/data/harness/temporalHelpers.js test/test262/data/test/built-ins/Temporal/PlainYearMonth/prototype/since/roundingincrement-as-expected.js --random-seed=1623281705 --nohard-abort --use-strict --ignore-unhandled-promises --harmony-temporal --no-arguments
=== test262/built-ins/Temporal/PlainYearMonth/prototype/since/roundingincrement-wrong-type ===
--- stdout ---
test/test262/data/test/built-ins/Temporal/PlainYearMonth/prototype/since/roundingincrement-wrong-type.js:22: Error: Temporal error: Internal error: .
  (roundingIncrement) => later.since(earlier, { roundingIncrement }),
                               ^
Error: Temporal error: Internal error: .
    at PlainYearMonth.since (<anonymous>)
    at test/test262/data/test/built-ins/Temporal/PlainYearMonth/prototype/since/roundingincrement-wrong-type.js:22:32
    at Object.checkRoundingIncrementOptionWrongType (test/test262/data/harness/temporalHelpers.js:509:26)
    at test/test262/data/test/built-ins/Temporal/PlainYearMonth/prototype/since/roundingincrement-wrong-type.js:21:17
Command: out/x64.release/d8 --test test/test262/data/harness/sta.js test/test262/data/harness/assert.js test/test262/harness-adapt.js test/test262/data/harness/compareArray.js test/test262/data/harness/temporalHelpers.js test/test262/data/test/built-ins/Temporal/PlainYearMonth/prototype/since/roundingincrement-wrong-type.js --random-seed=1623281705 --nohard-abort --use-strict --ignore-unhandled-promises --harmony-temporal --no-arguments
=== test262/built-ins/Temporal/ZonedDateTime/prototype/since/roundingincrement-addition-out-of-range ===
--- stdout ---
test/test262/data/harness/assert.js:95: Test262Error: ending bound of 1e8 + 1 days is out of range when added to 1970-01-01 Expected a RangeError but got a Error
      throw new Test262Error(message);
      ^
Command: out/x64.release/d8 --test test/test262/data/harness/sta.js test/test262/data/harness/assert.js test/test262/harness-adapt.js test/test262/data/harness/temporalHelpers.js test/test262/data/test/built-ins/Temporal/ZonedDateTime/prototype/since/roundingincrement-addition-out-of-range.js --random-seed=1623281705 --nohard-abort --ignore-unhandled-promises --harmony-temporal --no-arguments
=== test262/built-ins/Temporal/ZonedDateTime/prototype/since/roundingincrement-addition-out-of-range ===
--- stdout ---
test/test262/data/harness/assert.js:95: Test262Error: ending bound of 1e8 + 1 days is out of range when added to 1970-01-01 Expected a RangeError but got a Error
      throw new Test262Error(message);
      ^
Command: out/x64.release/d8 --test test/test262/data/harness/sta.js test/test262/data/harness/assert.js test/test262/harness-adapt.js test/test262/data/harness/temporalHelpers.js test/test262/data/test/built-ins/Temporal/ZonedDateTime/prototype/since/roundingincrement-addition-out-of-range.js --random-seed=1623281705 --nohard-abort --use-strict --ignore-unhandled-promises --harmony-temporal --no-arguments
=== test262/built-ins/Temporal/ZonedDateTime/prototype/until/roundingincrement-addition-out-of-range ===
--- stdout ---
test/test262/data/harness/assert.js:95: Test262Error: ending bound of -1e8 - 1 days is out of range when added to 1970-01-01 Expected a RangeError but got a Error
      throw new Test262Error(message);
      ^
Command: out/x64.release/d8 --test test/test262/data/harness/sta.js test/test262/data/harness/assert.js test/test262/harness-adapt.js test/test262/data/harness/temporalHelpers.js test/test262/data/test/built-ins/Temporal/ZonedDateTime/prototype/until/roundingincrement-addition-out-of-range.js --random-seed=1623281705 --nohard-abort --ignore-unhandled-promises --harmony-temporal --no-arguments
=== test262/built-ins/Temporal/ZonedDateTime/prototype/until/roundingincrement-addition-out-of-range ===
--- stdout ---
test/test262/data/harness/assert.js:95: Test262Error: ending bound of -1e8 - 1 days is out of range when added to 1970-01-01 Expected a RangeError but got a Error
      throw new Test262Error(message);
      ^
Command: out/x64.release/d8 --test test/test262/data/harness/sta.js test/test262/data/harness/assert.js test/test262/harness-adapt.js test/test262/data/harness/temporalHelpers.js test/test262/data/test/built-ins/Temporal/ZonedDateTime/prototype/until/roundingincrement-addition-out-of-range.js --random-seed=1623281705 --nohard-abort --use-strict --ignore-unhandled-promises --harmony-temporal --no-arguments

===

Copy link
Member

@nekevss nekevss left a comment

Choose a reason for hiding this comment

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

Have a couple notes after taking a glance.

Are you still looking into the failures mentioned above?

@Manishearth
Copy link
Contributor Author

Are you still looking into the failures mentioned above?

No, but they should be replicable by copying the tests.

@Manishearth
Copy link
Contributor Author

The failures were due to a missing <=. Fixed.

@Manishearth
Copy link
Contributor Author

And that fixes the crashes. Would still like to see if this can be written without floats, but I don't have time to do that myself.

@Manishearth
Copy link
Contributor Author

Note: I'm not actively working on this right now, and don't really plan to in the near future, if someone wants to figure out how to make the float stuff work.

@nekevss
Copy link
Member

nekevss commented Dec 9, 2025

I have some time and can take a look at this now if you're not currently working on it.

@Manishearth
Copy link
Contributor Author

That would be great!

// TODO: Add unit tests specifically for nudge_calendar_unit if possible.
fn nudge_calendar_unit(

fn nudge_calendar_unit_total(
Copy link
Contributor Author

Choose a reason for hiding this comment

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

nit: mention what spec item this is and why it is different

question: why is this different?

Copy link
Member

Choose a reason for hiding this comment

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

If you look at the specification, the return of NudgeToCalendarUnit is a record of (NudgeRecord, Total).

The callers of NudgeToCalendarUnit are RoundRelativeDuration and TotalRelativeDuration, the return type of NudgeRecord and Total correspond with the callers, respectively.

This means that for TotalRelativeDuration, the NudgeRecord is being computed and directly discarded; meanwhile, for RoundRelativeDuration, the value of total must be a f64, because the return type of total is a f64.

Ultimately, the changes separate these out into different codepaths, and therefore we are only computing exactly what we need for round and total

/// <https://tc39.es/proposal-temporal/#sec-temporal-computenudgewindow>
/// `compute_nudge_window` in `temporal_rs` refers to step 1-12 of `NudgeToCalendarUnit`.
///
/// For A.O. `ComputeNudgeWinodw`, see `compute_nudge_window_with_shift`
Copy link
Contributor Author

Choose a reason for hiding this comment

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

issue: this is confusing, let's call this compute_and_adjust_nudge_window or something

Copy link
Member

Choose a reason for hiding this comment

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

That's fair. I can go with that.

@nekevss nekevss marked this pull request as ready for review December 11, 2025 04:32
@nekevss nekevss requested a review from a team December 11, 2025 04:41
@Manishearth
Copy link
Contributor Author

Running this code patched into v8 gives me two (expected) new test successes and one new test failure in built-ins/Temporal/Duration/prototype/total/total-of-each-unit-relativeto


=== test262/built-ins/Temporal/Duration/prototype/round/rounding-window ===
Command: out/x64.release/d8 --test test/test262/data/harness/sta.js test/test262/data/harness/assert.js test/test262/harness-adapt.js test/test262/data/harness/temporalHelpers.js test/test262/data/test/built-ins/Temporal/Duration/prototype/round/rounding-window.js --random-seed=-136350097 --nohard-abort --ignore-unhandled-promises --harmony-temporal --no-arguments
=== test262/built-ins/Temporal/Duration/prototype/round/rounding-window ===
Command: out/x64.release/d8 --test test/test262/data/harness/sta.js test/test262/data/harness/assert.js test/test262/harness-adapt.js test/test262/data/harness/temporalHelpers.js test/test262/data/test/built-ins/Temporal/Duration/prototype/round/rounding-window.js --random-seed=-136350097 --nohard-abort --use-strict --ignore-unhandled-promises --harmony-temporal --no-arguments
=== test262/built-ins/Temporal/Duration/prototype/total/rounding-window ===
Command: out/x64.release/d8 --test test/test262/data/harness/sta.js test/test262/data/harness/assert.js test/test262/harness-adapt.js test/test262/data/test/built-ins/Temporal/Duration/prototype/total/rounding-window.js --random-seed=-136350097 --nohard-abort --ignore-unhandled-promises --harmony-temporal --no-arguments
=== test262/built-ins/Temporal/Duration/prototype/total/total-of-each-unit-relativeto ===
--- stdout ---
test/test262/data/harness/assert.js:49: Test262Error: Duration.total results for months relative to 2000-01-01 Expected SameValue(«66.32941495109206», «66.32941495109208») to be true
  throw new Test262Error(message);
  ^
Command: out/x64.release/d8 --test test/test262/data/harness/sta.js test/test262/data/harness/assert.js test/test262/harness-adapt.js test/test262/data/test/built-ins/Temporal/Duration/prototype/total/total-of-each-unit-relativeto.js --random-seed=-136350097 --nohard-abort --ignore-unhandled-promises --harmony-temporal --no-arguments
=== test262/built-ins/Temporal/Duration/prototype/total/rounding-window ===
Command: out/x64.release/d8 --test test/test262/data/harness/sta.js test/test262/data/harness/assert.js test/test262/harness-adapt.js test/test262/data/test/built-ins/Temporal/Duration/prototype/total/rounding-window.js --random-seed=-136350097 --nohard-abort --use-strict --ignore-unhandled-promises --harmony-temporal --no-arguments
=== test262/built-ins/Temporal/Duration/prototype/total/total-of-each-unit-relativeto ===
--- stdout ---
test/test262/data/harness/assert.js:49: Test262Error: Duration.total results for months relative to 2000-01-01 Expected SameValue(«66.32941495109206», «66.32941495109208») to be true
  throw new Test262Error(message);
  ^
Command: out/x64.release/d8 --test test/test262/data/harness/sta.js test/test262/data/harness/assert.js test/test262/harness-adapt.js test/test262/data/test/built-ins/Temporal/Duration/prototype/total/total-of-each-unit-relativeto.js --random-seed=-136350097 --nohard-abort --use-strict --ignore-unhandled-promises --harmony-temporal --no-arguments

@nekevss
Copy link
Member

nekevss commented Dec 12, 2025

Running this code patched into v8 gives me two (expected) new test successes and one new test failure in built-ins/Temporal/Duration/prototype/total/total-of-each-unit-relativeto


=== test262/built-ins/Temporal/Duration/prototype/round/rounding-window ===
Command: out/x64.release/d8 --test test/test262/data/harness/sta.js test/test262/data/harness/assert.js test/test262/harness-adapt.js test/test262/data/harness/temporalHelpers.js test/test262/data/test/built-ins/Temporal/Duration/prototype/round/rounding-window.js --random-seed=-136350097 --nohard-abort --ignore-unhandled-promises --harmony-temporal --no-arguments
=== test262/built-ins/Temporal/Duration/prototype/round/rounding-window ===
Command: out/x64.release/d8 --test test/test262/data/harness/sta.js test/test262/data/harness/assert.js test/test262/harness-adapt.js test/test262/data/harness/temporalHelpers.js test/test262/data/test/built-ins/Temporal/Duration/prototype/round/rounding-window.js --random-seed=-136350097 --nohard-abort --use-strict --ignore-unhandled-promises --harmony-temporal --no-arguments
=== test262/built-ins/Temporal/Duration/prototype/total/rounding-window ===
Command: out/x64.release/d8 --test test/test262/data/harness/sta.js test/test262/data/harness/assert.js test/test262/harness-adapt.js test/test262/data/test/built-ins/Temporal/Duration/prototype/total/rounding-window.js --random-seed=-136350097 --nohard-abort --ignore-unhandled-promises --harmony-temporal --no-arguments
=== test262/built-ins/Temporal/Duration/prototype/total/total-of-each-unit-relativeto ===
--- stdout ---
test/test262/data/harness/assert.js:49: Test262Error: Duration.total results for months relative to 2000-01-01 Expected SameValue(«66.32941495109206», «66.32941495109208») to be true
  throw new Test262Error(message);
  ^
Command: out/x64.release/d8 --test test/test262/data/harness/sta.js test/test262/data/harness/assert.js test/test262/harness-adapt.js test/test262/data/test/built-ins/Temporal/Duration/prototype/total/total-of-each-unit-relativeto.js --random-seed=-136350097 --nohard-abort --ignore-unhandled-promises --harmony-temporal --no-arguments
=== test262/built-ins/Temporal/Duration/prototype/total/rounding-window ===
Command: out/x64.release/d8 --test test/test262/data/harness/sta.js test/test262/data/harness/assert.js test/test262/harness-adapt.js test/test262/data/test/built-ins/Temporal/Duration/prototype/total/rounding-window.js --random-seed=-136350097 --nohard-abort --use-strict --ignore-unhandled-promises --harmony-temporal --no-arguments
=== test262/built-ins/Temporal/Duration/prototype/total/total-of-each-unit-relativeto ===
--- stdout ---
test/test262/data/harness/assert.js:49: Test262Error: Duration.total results for months relative to 2000-01-01 Expected SameValue(«66.32941495109206», «66.32941495109208») to be true
  throw new Test262Error(message);
  ^
Command: out/x64.release/d8 --test test/test262/data/harness/sta.js test/test262/data/harness/assert.js test/test262/harness-adapt.js test/test262/data/test/built-ins/Temporal/Duration/prototype/total/total-of-each-unit-relativeto.js --random-seed=-136350097 --nohard-abort --use-strict --ignore-unhandled-promises --harmony-temporal --no-arguments

Shoot, confirmed in Boa too. This looks like it may have something to do with f1c2828. But the curious thing is that that fixed the new precision calculations ...

EDIT: Oh, we need to do the full precision calculation.

@nekevss
Copy link
Member

nekevss commented Dec 12, 2025

All tests pass locally on Boa for Duration.

@Manishearth
Copy link
Contributor Author

Also V8

=== test262/built-ins/Temporal/Duration/prototype/round/rounding-window ===
Command: out/x64.release/d8 --test test/test262/data/harness/sta.js test/test262/data/harness/assert.js test/test262/harness-adapt.js test/test262/data/harness/temporalHelpers.js test/test262/data/test/built-ins/Temporal/Duration/prototype/round/rounding-window.js --random-seed=329755706 --nohard-abort --ignore-unhandled-promises --harmony-temporal --no-arguments
=== test262/built-ins/Temporal/Duration/prototype/round/rounding-window ===
Command: out/x64.release/d8 --test test/test262/data/harness/sta.js test/test262/data/harness/assert.js test/test262/harness-adapt.js test/test262/data/harness/temporalHelpers.js test/test262/data/test/built-ins/Temporal/Duration/prototype/round/rounding-window.js --random-seed=329755706 --nohard-abort --use-strict --ignore-unhandled-promises --harmony-temporal --no-arguments
=== test262/built-ins/Temporal/Duration/prototype/total/rounding-window ===
Command: out/x64.release/d8 --test test/test262/data/harness/sta.js test/test262/data/harness/assert.js test/test262/harness-adapt.js test/test262/data/test/built-ins/Temporal/Duration/prototype/total/rounding-window.js --random-seed=329755706 --nohard-abort --ignore-unhandled-promises --harmony-temporal --no-arguments
=== test262/built-ins/Temporal/Duration/prototype/total/rounding-window ===
Command: out/x64.release/d8 --test test/test262/data/harness/sta.js test/test262/data/harness/assert.js test/test262/harness-adapt.js test/test262/data/test/built-ins/Temporal/Duration/prototype/total/rounding-window.js --random-seed=329755706 --nohard-abort --use-strict --ignore-unhandled-promises --harmony-temporal --no-arguments

Copy link
Contributor Author

@Manishearth Manishearth left a comment

Choose a reason for hiding this comment

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

r+

@nekevss nekevss merged commit 8aa66e3 into boa-dev:main Dec 12, 2025
8 checks passed
@Manishearth Manishearth deleted the nudge-window branch December 15, 2025 20:50
ajperel pushed a commit to chromium/chromium that referenced this pull request Dec 16, 2025
Uplift of boa-dev/temporal#647,
boa-dev/temporal#636, unicode-org/icu4x#7321

Change-Id: Icf703e2ae907a6a820b6b1141883ed9ab825874c
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/7261567
Commit-Queue: Manish Goregaokar <manishearth@google.com>
Auto-Submit: Manish Goregaokar <manishearth@google.com>
Reviewed-by: Łukasz Anforowicz <lukasza@chromium.org>
Commit-Queue: Łukasz Anforowicz <lukasza@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1559085}
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.

Implement new Nudge changes

3 participants