From ae2b7904b2fd5968472ea69986953ba77671d246 Mon Sep 17 00:00:00 2001 From: Philip Chimento Date: Wed, 28 Oct 2020 15:51:43 -0700 Subject: [PATCH] Generalize DefaultTemporalLargestUnit Per #980 it is a recognized operation to get the correct largestUnit value corresponding with the largest non-zero unit in the duration. Generalize this operation in the spec, in order to use in #857. --- polyfill/lib/duration.mjs | 14 ++++---------- polyfill/lib/ecmascript.mjs | 28 ++++++++++++++++++++++++++++ spec/duration.html | 27 +++++++++++++-------------- 3 files changed, 45 insertions(+), 24 deletions(-) diff --git a/polyfill/lib/duration.mjs b/polyfill/lib/duration.mjs index 8ef0d0c0b2..eaa1f71b60 100644 --- a/polyfill/lib/duration.mjs +++ b/polyfill/lib/duration.mjs @@ -357,8 +357,7 @@ export class Duration { let microseconds = GetSlot(this, MICROSECONDS); let nanoseconds = GetSlot(this, NANOSECONDS); - let defaultLargestUnit = 'nanoseconds'; - for (const [prop, v] of Object.entries({ + let defaultLargestUnit = ES.DefaultTemporalLargestUnit( years, months, weeks, @@ -367,14 +366,9 @@ export class Duration { minutes, seconds, milliseconds, - microseconds - })) { - if (v !== 0) { - defaultLargestUnit = prop; - break; - } - } - + microseconds, + nanoseconds + ); options = ES.NormalizeOptionsObject(options); const smallestUnit = ES.ToSmallestTemporalDurationUnit(options, 'nanoseconds'); defaultLargestUnit = ES.LargerOfTwoTemporalDurationUnits(defaultLargestUnit, smallestUnit); diff --git a/polyfill/lib/ecmascript.mjs b/polyfill/lib/ecmascript.mjs index eec8d5a64c..577c93ece0 100644 --- a/polyfill/lib/ecmascript.mjs +++ b/polyfill/lib/ecmascript.mjs @@ -731,6 +731,34 @@ export const ES = ObjectAssign({}, ES2020, { throw new RangeError(`largestUnit ${largestUnit} cannot be smaller than smallestUnit ${smallestUnit}`); } }, + DefaultTemporalLargestUnit: ( + years, + months, + weeks, + days, + hours, + minutes, + seconds, + milliseconds, + microseconds, + nanoseconds + ) => { + for (const [prop, v] of Object.entries({ + years, + months, + weeks, + days, + hours, + minutes, + seconds, + milliseconds, + microseconds, + nanoseconds + })) { + if (v !== 0) return prop; + } + return 'nanoseconds'; + }, LargerOfTwoTemporalDurationUnits: (unit1, unit2) => { const validUnits = [ 'years', diff --git a/spec/duration.html b/spec/duration.html index 009c5822d6..9539541cee 100644 --- a/spec/duration.html +++ b/spec/duration.html @@ -399,7 +399,7 @@

Temporal.Duration.prototype.round ( _options_ )

1. Perform ? RequireInternalSlot(_duration_, [[InitializedTemporalDuration]]). 1. Set _options_ to ? NormalizeOptionsObject(_options_). 1. Let _smallestUnit_ be ? ToSmallestTemporalDurationUnit(_options_, *"nanoseconds"*). - 1. Let _defaultLargestUnit_ be ! DefaultTemporalLargestUnitForRounding(_duration_). + 1. Let _defaultLargestUnit_ be ! DefaultTemporalLargestUnit(_duration_.[[Years]], _duration_.[[Months]], _duration_.[[Weeks]], _duration_.[[Days]], _duration_.[[Hours]], _duration_.[[Minutes]], _duration_.[[Seconds]], _duration_.[[Milliseconds]], _duration_.[[Microseconds]], _duration_.[[Nanoseconds]]). 1. Set _defaultLargestUnit_ to ! LargerOfTwoTemporalDurationUnits(_defaultLargestUnit_, _smallestUnit_). 1. Let _largestUnit_ be ? ToLargestTemporalUnit(_options_, _defaultLargestUnit_). 1. Perform ? ValidateTemporalUnitRange(_largestUnit_, _smallestUnit_). @@ -682,22 +682,21 @@

ValidateTemporalDuration ( _years_, _months_, _weeks_, _days_, _hours_, _min - -

DefaultTemporalLargestUnitForRounding ( _duration_ )

+ +

DefaultTemporalLargestUnit ( _years_, _months_, _weeks_, _days_, _hours_, _minutes_, _seconds_, _milliseconds_, _microseconds_, _nanoseconds_ )

- The abstract operation DefaultTemporalLargestUnitForRounding implements the logic used in the `Temporal.Duration.prototype.round()` method, where the `largestUnit` option, if not given explicitly, is set to the largest non-zero unit in the input Temporal.Duration. + The abstract operation DefaultTemporalLargestUnit implements the logic used in the `Temporal.Duration.prototype.round()` method and elsewhere, where the `largestUnit` option, if not given explicitly, is set to the largest non-zero unit in the input Temporal.Duration.

- 1. Assert: _duration_ has an [[InitializedTemporalDuration]] internal slot. - 1. If _duration_.[[Years]] is not zero, return *"years"*. - 1. If _duration_.[[Months]] is not zero, return *"months"*. - 1. If _duration_.[[Weeks]] is not zero, return *"weeks"*. - 1. If _duration_.[[Days]] is not zero, return *"days"*. - 1. If _duration_.[[Hours]] is not zero, return *"hours"*. - 1. If _duration_.[[Minutes]] is not zero, return *"minutes"*. - 1. If _duration_.[[Seconds]] is not zero, return *"seconds"*. - 1. If _duration_.[[Milliseconds]] is not zero, return *"milliseconds"*. - 1. If _duration_.[[Microseconds]] is not zero, return *"microseconds"*. + 1. If _years_ is not zero, return *"years"*. + 1. If _months_ is not zero, return *"months"*. + 1. If _weeks_ is not zero, return *"weeks"*. + 1. If _days_ is not zero, return *"days"*. + 1. If _hours_ is not zero, return *"hours"*. + 1. If _minutes_ is not zero, return *"minutes"*. + 1. If _seconds_ is not zero, return *"seconds"*. + 1. If _milliseconds_ is not zero, return *"milliseconds"*. + 1. If _microseconds_ is not zero, return *"microseconds"*. 1. Return *"nanoseconds"*.