Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Editorial: Pass Duration Records rather than individual components #2290

Open
wants to merge 11 commits into
base: main
Choose a base branch
from

Conversation

gibson042
Copy link
Collaborator

Many operations seem to be simplified by dealing with Duration Records rather than individual fields.

And I suspect that even further reform in this direction remains possible.

@gibson042 gibson042 requested a review from ptomato June 12, 2022 23:32
@codecov
Copy link

codecov bot commented Jun 12, 2022

Codecov Report

Merging #2290 (9370ef0) into main (1d42297) will not change coverage.
The diff coverage is n/a.

@@           Coverage Diff           @@
##             main    #2290   +/-   ##
=======================================
  Coverage   91.08%   91.08%           
=======================================
  Files          19       19           
  Lines       10566    10566           
  Branches     1695     1695           
=======================================
  Hits         9624     9624           
  Misses        932      932           
  Partials       10       10           
Flag Coverage Δ
test262 83.94% <ø> (ø)
tests 81.83% <ø> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.


Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 1d42297...9370ef0. Read the comment docs.

1. Return ! CreateDurationRecord(_dateDifference_.[[Years]], _dateDifference_.[[Months]], _dateDifference_.[[Weeks]], _result_.[[Days]], _result_.[[Hours]], _result_.[[Minutes]], _result_.[[Seconds]], _result_.[[Milliseconds]], _result_.[[Microseconds]], _result_.[[Nanoseconds]]).
1. Assert: _relativeTo_ has an [[InitializedTemporalZonedDateTime]] internal slot.
1. Let _timeZone_ be _relativeTo_.[[TimeZone]].
1. Let _calendar_ be _relativeTo_.[[Calendar]].
1. Let _intermediateNs_ be ? AddZonedDateTime(_relativeTo_.[[Nanoseconds]], _timeZone_, _calendar_, _y1_, _mon1_, _w1_, _d1_, _h1_, _min1_, _s1_, _ms1_, _mus1_, _ns1_).
1. Let _endNs_ be ? AddZonedDateTime(_intermediateNs_, _timeZone_, _calendar_, _y2_, _mon2_, _w2_, _d2_, _h2_, _min2_, _s2_, _ms2_, _mus2_, _ns2_).
1. Let _endNs_ be ? AddZonedDateTime(_relativeTo_, _timeZone_, _calendar_, _duration1_.[[Years]] + _duration2_.[[Years]], _duration1_.[[Months]] + _duration2_.[[Months]], _duration1_.[[Weeks]] + _duration2_.[[Weeks]], _duration1_.[[Days]] + _duration2_.[[Days]], _duration1_.[[Hours]] + _duration2_.[[Hours]], _duration1_.[[Minutes]] + _duration2_.[[Minutes]], _duration1_.[[Seconds]] + _duration2_.[[Seconds]], _duration1_.[[Milliseconds]] + _duration2_.[[Milliseconds]], _duration1_.[[Microseconds]] + _duration2_.[[Microseconds]], _duration1_.[[Nanoseconds]] + _duration2_.[[Nanoseconds]]).
Copy link
Contributor

Choose a reason for hiding this comment

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

This change is normative, because it replaces two AddZonedDateTime calls with a single call to AddZonedDateTime. Apart from the obvious normative changes (e.g. fewer observable lookups), will this change result in any other changes, i.e. was there a reason to perform two calls?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Nice catch! I have reverted the normative change and referenced this comment from #2289.

As for whether or not the separate calls make sense, I don't think so. They seem harmless but unnecessary for Temporal.Duration.prototype.{add,subtract}, and undesirable for Temporal.Duration.prototype.round and Temporal.ZonedDateTime.prototype.{since,until}.

spec/duration.html Outdated Show resolved Hide resolved
Comment on lines 1429 to 1424
1. Let _duration1_ be ! CreateDurationRecord(_y1_, _mon1_, _w1_, _d1_, _h1_, _min1_, _s1_, _ms1_, _mus1_).
1. Let _duration2_ be ! CreateDurationRecord(_y2_, _mon2_, _w2_, _d2_, _h2_, _min2_, _s2_, _ms2_, _mus2_).
1. Let _largestUnit1_ be ! DefaultTemporalLargestUnit(_duration1_).
1. Let _largestUnit2_ be ! DefaultTemporalLargestUnit(_duration2_).
Copy link
Collaborator

Choose a reason for hiding this comment

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

Hmm, this is not as obvious as it seems. CreateDurationRecord does a MV → float → MV dance. Are you sure none of these changes are affected?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I corrected this to remain in MV domain with a later commit.

@@ -1184,7 +1176,7 @@ <h1>
<emu-alg>
1. If _relativeTo_ is not present, set _relativeTo_ to *undefined*.
1. If Type(_relativeTo_) is Object and _relativeTo_ has an [[InitializedTemporalZonedDateTime]] internal slot, then
1. Let _endNs_ be ? AddZonedDateTime(_relativeTo_.[[Nanoseconds]], _relativeTo_.[[TimeZone]], _relativeTo_.[[Calendar]], 0, 0, 0, _days_, _hours_, _minutes_, _seconds_, _milliseconds_, _microseconds_, _nanoseconds_).
1. Let _endNs_ be ? AddZonedDateTime(_relativeTo_.[[Nanoseconds]], _relativeTo_.[[TimeZone]], _relativeTo_.[[Calendar]], ! CreateTemporalDurationRecord(0, 0, 0, _days_, _hours_, _minutes_, _seconds_, _milliseconds_, _microseconds_, _nanoseconds_)).
Copy link
Contributor

Choose a reason for hiding this comment

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

Nit: Typo CreateTemporalDurationRecord should be CreateDurationRecord throughout this commit.

CreateDurationRecord is fallible, because days can have a different sign than the time components:

let d = Temporal.Duration.from({
  weeks: 1,
  days: 0,
  hours: 1,
});

let cal = new class extends Temporal.Calendar {
  #dateAdd = 0;
  dateAdd(date, duration, options) {
    if (++this.#dateAdd === 1) {
      duration = "-P1W";
    }
    return super.dateAdd(date, duration, options);
  }
}("iso8601");

let zdt = new Temporal.ZonedDateTime(0n, "UTC", cal);
let r = d.total({
  relativeTo: zdt,
  unit: "days",
});
console.log("rounded result=", r);

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I updated this spot in BalanceDuration where the changes were introducing a risk, but am rather confident that the other invocations are safe. I'm less confident that the use of CreateTemporalDuration within AddZonedDateTime is safe, but that is not changed by this PR.

Copy link
Collaborator

@ptomato ptomato left a comment

Choose a reason for hiding this comment

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

I'm not in favour of this change because I find it makes the rendered spec text less readable in two ways:

  • The sticky highlighting becomes less useful. When auditing the uses of BalanceDuration, for example, I found it a lifesaver to be able to highlight years, months, weeks, days, etc. in different colors. If they become durationFieldsRecord.[[Years]] etc., that's no longer possible.
  • Records with as many fields as Duration Records have are rendered in a kind of jumbled-up way. e.g.
1. Let _record_ be the Record {
    [[Years]]: _foo_,
    [[Months]]: _bar_,
    [[Weeks]]: 0,
  }.

is easy to scan visually in the ecmarkup source, but when rendered it becomes

Let record be the Record { [[Years]]: foo, [[Months]]: bar, [[Weeks]]: 0, ... }.

which in my opinion is much harder to visually scan, and makes it hard to notice discrepancies (whether accidental or intentional) between the way the fields are assigned. (for example, the 0 above)

@gibson042
Copy link
Collaborator Author

I find the current spec to be hard to read precisely because there are so many aliases, especially in operation signatures (cf. tc39/ecmarkup#459 for a relevant consequence). But perhaps there's a compromise position in which the operations deal in Records but those Records theirselves are never constructed manually but rather always through a single (or small handful of) operations that have a distinct parameter for each unit?

And it's also conceivable that spec highlighting should be extended to include [[…]] contents.

@ptomato
Copy link
Collaborator

ptomato commented Jul 4, 2022

Is highlighting of e.g. record.[[Foo]] something that the ecmarkup maintainers would be interested in implementing? I don't think I will have time to do it myself.

@ptomato
Copy link
Collaborator

ptomato commented Jan 5, 2023

@gibson042 Are you planning to continue this PR?

@justingrant
Copy link
Collaborator

Is this PR still moving fwd? Seems like we should either close it or merge it somewhat soon so we can have a clean plate in preparation for Stage 4.

@gibson042
Copy link
Collaborator Author

Yes, and (for my own future reference) @ptomato recommends rebasing on #2519.

@justingrant
Copy link
Collaborator

Is this PR going to move fwd?

@ptomato - do you have an opinion about whether we should continue to do wide-ranging editorial changes like this one, or should pause for a while to give implementers a more stable spec to work on?

@ptomato
Copy link
Collaborator

ptomato commented Jul 24, 2023

I'd prefer we try to get them in quickly after merging the normative changes, and only then stop doing them.

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.

None yet

5 participants