mirror of
				https://github.com/RGBCube/serenity
				synced 2025-10-31 04:32:44 +00:00 
			
		
		
		
	LibJS: Change internal slots of Duration to store mathematical values
This is a normative change in the Temporal spec.
See: 1f3fba8
			
			
This commit is contained in:
		
							parent
							
								
									cc8f5151d7
								
							
						
					
					
						commit
						b751f80166
					
				
					 4 changed files with 128 additions and 110 deletions
				
			
		|  | @ -174,9 +174,9 @@ JS_DEFINE_NATIVE_FUNCTION(CalendarPrototype::date_add) | |||
|     // 7. Let overflow be ? ToTemporalOverflow(options).
 | ||||
|     auto overflow = TRY(to_temporal_overflow(global_object, options)); | ||||
| 
 | ||||
|     // 8. Let balanceResult be ! BalanceDuration(duration.[[Days]], duration.[[Hours]], duration.[[Minutes]], duration.[[Seconds]], duration.[[Milliseconds]], duration.[[Microseconds]], duration.[[Nanoseconds]], "day").
 | ||||
|     // 8. Let balanceResult be ? BalanceDuration(duration.[[Days]], duration.[[Hours]], duration.[[Minutes]], duration.[[Seconds]], duration.[[Milliseconds]], duration.[[Microseconds]], duration.[[Nanoseconds]], "day").
 | ||||
|     // FIXME: Narrowing conversion from 'double' to 'i64'
 | ||||
|     auto balance_result = MUST(balance_duration(global_object, duration->days(), duration->hours(), duration->minutes(), duration->seconds(), duration->milliseconds(), duration->microseconds(), Crypto::SignedBigInteger::create_from(duration->nanoseconds()), "day"sv)); | ||||
|     auto balance_result = TRY(balance_duration(global_object, duration->days(), duration->hours(), duration->minutes(), duration->seconds(), duration->milliseconds(), duration->microseconds(), Crypto::SignedBigInteger::create_from(duration->nanoseconds()), "day"sv)); | ||||
| 
 | ||||
|     // 9. Let result be ? AddISODate(date.[[ISOYear]], date.[[ISOMonth]], date.[[ISODay]], duration.[[Years]], duration.[[Months]], duration.[[Weeks]], balanceResult.[[Days]], overflow).
 | ||||
|     auto result = TRY(add_iso_date(global_object, date->iso_year(), date->iso_month(), date->iso_day(), duration->years(), duration->months(), duration->weeks(), balance_result.days, overflow)); | ||||
|  |  | |||
|  | @ -35,6 +35,32 @@ Duration::Duration(double years, double months, double weeks, double days, doubl | |||
|     , m_microseconds(microseconds) | ||||
|     , m_nanoseconds(nanoseconds) | ||||
| { | ||||
|     auto fields = AK::Array { | ||||
|         &Duration::m_years, | ||||
|         &Duration::m_months, | ||||
|         &Duration::m_weeks, | ||||
|         &Duration::m_days, | ||||
|         &Duration::m_hours, | ||||
|         &Duration::m_minutes, | ||||
|         &Duration::m_seconds, | ||||
|         &Duration::m_milliseconds, | ||||
|         &Duration::m_microseconds, | ||||
|         &Duration::m_nanoseconds, | ||||
|     }; | ||||
| 
 | ||||
|     // NOTE: The spec stores these fields as mathematical values. VERIFY() that we have finite,
 | ||||
|     // integral values in them, and normalize any negative zeros caused by floating point math.
 | ||||
|     // This is usually done using ℝ(𝔽(value)) at the call site.
 | ||||
|     for (auto const& field : fields) { | ||||
|         auto& value = this->*field; | ||||
|         VERIFY(isfinite(value)); | ||||
|         // FIXME: test-js contains a small number of cases where a Temporal.Duration is constructed
 | ||||
|         //        with a non-integral double. Eliminate these and VERIFY(trunc(value) == value) instead.
 | ||||
|         if (trunc(value) != value) | ||||
|             value = trunc(value); | ||||
|         else if (bit_cast<u64>(value) == NEGATIVE_ZERO_BITS) | ||||
|             value = 0; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| // NOTE: All of these have two overloads: one that can throw, and one that can't.
 | ||||
|  | @ -47,7 +73,7 @@ DurationRecord create_duration_record(double years, double months, double weeks, | |||
|     // 1. If ! IsValidDuration(years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds) is false, throw a RangeError exception.
 | ||||
|     VERIFY(is_valid_duration(years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds)); | ||||
| 
 | ||||
|     // 2. Return the Record { [[Years]]: years, [[Months]]: months, [[Weeks]]: weeks, [[Days]]: days, [[Hours]]: hours, [[Minutes]]: minutes, [[Seconds]]: seconds, [[Milliseconds]]: milliseconds, [[Microseconds]]: microseconds, [[Nanoseconds]]: nanoseconds }.
 | ||||
|     // 2. Return the Record { [[Years]]: ℝ(𝔽(years)), [[Months]]: ℝ(𝔽(months)), [[Weeks]]: ℝ(𝔽(weeks)), [[Days]]: ℝ(𝔽(days)), [[Hours]]: ℝ(𝔽(hours)), [[Minutes]]: ℝ(𝔽(minutes)), [[Seconds]]: ℝ(𝔽(seconds)), [[Milliseconds]]: ℝ(𝔽(milliseconds)), [[Microseconds]]: ℝ(𝔽(microseconds)), [[Nanoseconds]]: ℝ(𝔽(nanoseconds)) }.
 | ||||
|     return DurationRecord { .years = years, .months = months, .weeks = weeks, .days = days, .hours = hours, .minutes = minutes, .seconds = seconds, .milliseconds = milliseconds, .microseconds = microseconds, .nanoseconds = nanoseconds }; | ||||
| } | ||||
| 
 | ||||
|  | @ -60,7 +86,7 @@ ThrowCompletionOr<DurationRecord> create_duration_record(GlobalObject& global_ob | |||
|     if (!is_valid_duration(years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds)) | ||||
|         return vm.throw_completion<RangeError>(global_object, ErrorType::TemporalInvalidDuration); | ||||
| 
 | ||||
|     // 2. Return the Record { [[Years]]: years, [[Months]]: months, [[Weeks]]: weeks, [[Days]]: days, [[Hours]]: hours, [[Minutes]]: minutes, [[Seconds]]: seconds, [[Milliseconds]]: milliseconds, [[Microseconds]]: microseconds, [[Nanoseconds]]: nanoseconds }.
 | ||||
|     // 2. Return the Record { [[Years]]: ℝ(𝔽(years)), [[Months]]: ℝ(𝔽(months)), [[Weeks]]: ℝ(𝔽(weeks)), [[Days]]: ℝ(𝔽(days)), [[Hours]]: ℝ(𝔽(hours)), [[Minutes]]: ℝ(𝔽(minutes)), [[Seconds]]: ℝ(𝔽(seconds)), [[Milliseconds]]: ℝ(𝔽(milliseconds)), [[Microseconds]]: ℝ(𝔽(microseconds)), [[Nanoseconds]]: ℝ(𝔽(nanoseconds)) }.
 | ||||
|     return DurationRecord { .years = years, .months = months, .weeks = weeks, .days = days, .hours = hours, .minutes = minutes, .seconds = seconds, .milliseconds = milliseconds, .microseconds = microseconds, .nanoseconds = nanoseconds }; | ||||
| } | ||||
| 
 | ||||
|  | @ -70,7 +96,7 @@ DateDurationRecord create_date_duration_record(double years, double months, doub | |||
|     // 1. If ! IsValidDuration(years, months, weeks, days, 0, 0, 0, 0, 0, 0) is false, throw a RangeError exception.
 | ||||
|     VERIFY(is_valid_duration(years, months, weeks, days, 0, 0, 0, 0, 0, 0)); | ||||
| 
 | ||||
|     // 2. Return the Record { [[Years]]: years, [[Months]]: months, [[Weeks]]: weeks, [[Days]]: days, }.
 | ||||
|     // 2. Return the Record { [[Years]]: ℝ(𝔽(years)), [[Months]]: ℝ(𝔽(months)), [[Weeks]]: ℝ(𝔽(weeks)), [[Days]]: ℝ(𝔽(days)) }.
 | ||||
|     return DateDurationRecord { .years = years, .months = months, .weeks = weeks, .days = days }; | ||||
| } | ||||
| 
 | ||||
|  | @ -83,7 +109,7 @@ ThrowCompletionOr<DateDurationRecord> create_date_duration_record(GlobalObject& | |||
|     if (!is_valid_duration(years, months, weeks, days, 0, 0, 0, 0, 0, 0)) | ||||
|         return vm.throw_completion<RangeError>(global_object, ErrorType::TemporalInvalidDuration); | ||||
| 
 | ||||
|     // 2. Return the Record { [[Years]]: years, [[Months]]: months, [[Weeks]]: weeks, [[Days]]: days, }.
 | ||||
|     // 2. Return the Record { [[Years]]: ℝ(𝔽(years)), [[Months]]: ℝ(𝔽(months)), [[Weeks]]: ℝ(𝔽(weeks)), [[Days]]: ℝ(𝔽(days)) }.
 | ||||
|     return DateDurationRecord { .years = years, .months = months, .weeks = weeks, .days = days }; | ||||
| } | ||||
| 
 | ||||
|  | @ -93,7 +119,7 @@ TimeDurationRecord create_time_duration_record(double days, double hours, double | |||
|     // 1. If ! IsValidDuration(0, 0, 0, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds) is false, throw a RangeError exception.
 | ||||
|     VERIFY(is_valid_duration(0, 0, 0, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds)); | ||||
| 
 | ||||
|     // 2. Return the Record { [[Days]]: days, [[Hours]]: hours, [[Minutes]]: minutes, [[Seconds]]: seconds, [[Milliseconds]]: milliseconds, [[Microseconds]]: microseconds, [[Nanoseconds]]: nanoseconds }.
 | ||||
|     // 2. Return the Record { [[Days]]: ℝ(𝔽(days)), [[Hours]]: ℝ(𝔽(hours)), [[Minutes]]: ℝ(𝔽(minutes)), [[Seconds]]: ℝ(𝔽(seconds)), [[Milliseconds]]: ℝ(𝔽(milliseconds)), [[Microseconds]]: ℝ(𝔽(microseconds)), [[Nanoseconds]]: ℝ(𝔽(nanoseconds)) }.
 | ||||
|     return TimeDurationRecord { .days = days, .hours = hours, .minutes = minutes, .seconds = seconds, .milliseconds = milliseconds, .microseconds = microseconds, .nanoseconds = nanoseconds }; | ||||
| } | ||||
| 
 | ||||
|  | @ -106,7 +132,7 @@ ThrowCompletionOr<TimeDurationRecord> create_time_duration_record(GlobalObject& | |||
|     if (!is_valid_duration(0, 0, 0, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds)) | ||||
|         return vm.throw_completion<RangeError>(global_object, ErrorType::TemporalInvalidDuration); | ||||
| 
 | ||||
|     // 2. Return the Record { [[Days]]: days, [[Hours]]: hours, [[Minutes]]: minutes, [[Seconds]]: seconds, [[Milliseconds]]: milliseconds, [[Microseconds]]: microseconds, [[Nanoseconds]]: nanoseconds }.
 | ||||
|     // 2. Return the Record { [[Days]]: ℝ(𝔽(days)), [[Hours]]: ℝ(𝔽(hours)), [[Minutes]]: ℝ(𝔽(minutes)), [[Seconds]]: ℝ(𝔽(seconds)), [[Milliseconds]]: ℝ(𝔽(milliseconds)), [[Microseconds]]: ℝ(𝔽(microseconds)), [[Nanoseconds]]: ℝ(𝔽(nanoseconds)) }.
 | ||||
|     return TimeDurationRecord { .days = days, .hours = hours, .minutes = minutes, .seconds = seconds, .milliseconds = milliseconds, .microseconds = microseconds, .nanoseconds = nanoseconds }; | ||||
| } | ||||
| 
 | ||||
|  | @ -171,11 +197,11 @@ ThrowCompletionOr<DurationRecord> to_temporal_duration_record(GlobalObject& glob | |||
|             // i. Set any to true.
 | ||||
|             any = true; | ||||
| 
 | ||||
|             // ii. Let val be 𝔽(? ToIntegerWithoutRounding(val)).
 | ||||
|             value = Value(TRY(to_integer_without_rounding(global_object, value, ErrorType::TemporalInvalidDurationPropertyValueNonIntegral, property.as_string(), value.to_string_without_side_effects()))); | ||||
|             // ii. Let val be ? ToIntegerWithoutRounding(val).
 | ||||
|             auto value_integer = TRY(to_integer_without_rounding(global_object, value, ErrorType::TemporalInvalidDurationPropertyValueNonIntegral, property.as_string(), value.to_string_without_side_effects())); | ||||
| 
 | ||||
|             // iii. Set result's field whose name is the Field Name value of the current row to val.
 | ||||
|             result.*field = value.as_double(); | ||||
|             result.*field = value_integer; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|  | @ -221,7 +247,7 @@ bool is_valid_duration(double years, double months, double weeks, double days, d | |||
| 
 | ||||
|     // 2. For each value v of « years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds », do
 | ||||
|     for (auto& v : { years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds }) { | ||||
|         // a. If v is not finite, return false.
 | ||||
|         // a. If 𝔽(v) is not finite, return false.
 | ||||
|         if (!isfinite(v)) | ||||
|             return false; | ||||
| 
 | ||||
|  | @ -310,11 +336,11 @@ ThrowCompletionOr<PartialDurationRecord> to_partial_duration(GlobalObject& globa | |||
|             // i. Set any to true.
 | ||||
|             any = true; | ||||
| 
 | ||||
|             // ii. Set value to 𝔽(? ToIntegerWithoutRounding(value)).
 | ||||
|             value = Value(TRY(to_integer_without_rounding(global_object, value, ErrorType::TemporalInvalidDurationPropertyValueNonIntegral, property.as_string(), value.to_string_without_side_effects()))); | ||||
|             // ii. Set value to ? ToIntegerWithoutRounding(value).
 | ||||
|             auto value_integer = TRY(to_integer_without_rounding(global_object, value, ErrorType::TemporalInvalidDurationPropertyValueNonIntegral, property.as_string(), value.to_string_without_side_effects())); | ||||
| 
 | ||||
|             // iii. Set result's field whose name is the Field Name value of the current row to value.
 | ||||
|             result.*field = value.as_double(); | ||||
|             result.*field = value_integer; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|  | @ -342,16 +368,16 @@ ThrowCompletionOr<Duration*> create_temporal_duration(GlobalObject& global_objec | |||
|         new_target = global_object.temporal_duration_constructor(); | ||||
| 
 | ||||
|     // 3. Let object be ? OrdinaryCreateFromConstructor(newTarget, "%Temporal.Duration.prototype%", « [[InitializedTemporalDuration]], [[Years]], [[Months]], [[Weeks]], [[Days]], [[Hours]], [[Minutes]], [[Seconds]], [[Milliseconds]], [[Microseconds]], [[Nanoseconds]] »).
 | ||||
|     // 4. Set object.[[Years]] to years.
 | ||||
|     // 5. Set object.[[Months]] to months.
 | ||||
|     // 6. Set object.[[Weeks]] to weeks.
 | ||||
|     // 7. Set object.[[Days]] to days.
 | ||||
|     // 8. Set object.[[Hours]] to hours.
 | ||||
|     // 9. Set object.[[Minutes]] to minutes.
 | ||||
|     // 10. Set object.[[Seconds]] to seconds.
 | ||||
|     // 11. Set object.[[Milliseconds]] to milliseconds.
 | ||||
|     // 12. Set object.[[Microseconds]] to microseconds.
 | ||||
|     // 13. Set object.[[Nanoseconds]] to nanoseconds.
 | ||||
|     // 4. Set object.[[Years]] to ℝ(𝔽(years)).
 | ||||
|     // 5. Set object.[[Months]] to ℝ(𝔽(months)).
 | ||||
|     // 6. Set object.[[Weeks]] to ℝ(𝔽(weeks)).
 | ||||
|     // 7. Set object.[[Days]] to ℝ(𝔽(days)).
 | ||||
|     // 8. Set object.[[Hours]] to ℝ(𝔽(hours)).
 | ||||
|     // 9. Set object.[[Minutes]] to ℝ(𝔽(minutes)).
 | ||||
|     // 10. Set object.[[Seconds]] to ℝ(𝔽(seconds)).
 | ||||
|     // 11. Set object.[[Milliseconds]] to ℝ(𝔽(milliseconds)).
 | ||||
|     // 12. Set object.[[Microseconds]] to ℝ(𝔽(microseconds)).
 | ||||
|     // 13. Set object.[[Nanoseconds]] to ℝ(𝔽(nanoseconds)).
 | ||||
|     auto* object = TRY(ordinary_create_from_constructor<Duration>(global_object, *new_target, &GlobalObject::temporal_duration_prototype, years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds)); | ||||
| 
 | ||||
|     // 14. Return object.
 | ||||
|  | @ -398,28 +424,27 @@ Crypto::SignedBigInteger total_duration_nanoseconds(double days, double hours, d | |||
| { | ||||
|     VERIFY(offset_shift == trunc(offset_shift)); | ||||
| 
 | ||||
|     // 1. Set nanoseconds to ℝ(nanoseconds).
 | ||||
|     auto result_nanoseconds = nanoseconds; | ||||
| 
 | ||||
|     // TODO: Add a way to create SignedBigIntegers from doubles with full precision and remove this restriction
 | ||||
|     VERIFY(AK::is_within_range<i64>(days) && AK::is_within_range<i64>(hours) && AK::is_within_range<i64>(minutes) && AK::is_within_range<i64>(seconds) && AK::is_within_range<i64>(milliseconds) && AK::is_within_range<i64>(microseconds)); | ||||
| 
 | ||||
|     // 2. If days ≠ 0, then
 | ||||
|     // 1. If days ≠ 0, then
 | ||||
|     if (days != 0) { | ||||
|         // a. Set nanoseconds to nanoseconds - offsetShift.
 | ||||
|         result_nanoseconds = result_nanoseconds.minus(Crypto::SignedBigInteger::create_from(offset_shift)); | ||||
|     } | ||||
|     // 3. Set hours to ℝ(hours) + ℝ(days) × 24.
 | ||||
|     // 2. Set hours to hours + days × 24.
 | ||||
|     auto total_hours = Crypto::SignedBigInteger::create_from(hours).plus(Crypto::SignedBigInteger::create_from(days).multiplied_by(Crypto::UnsignedBigInteger(24))); | ||||
|     // 4. Set minutes to ℝ(minutes) + hours × 60.
 | ||||
|     // 3. Set minutes to minutes + hours × 60.
 | ||||
|     auto total_minutes = Crypto::SignedBigInteger::create_from(minutes).plus(total_hours.multiplied_by(Crypto::UnsignedBigInteger(60))); | ||||
|     // 5. Set seconds to ℝ(seconds) + minutes × 60.
 | ||||
|     // 4. Set seconds to seconds + minutes × 60.
 | ||||
|     auto total_seconds = Crypto::SignedBigInteger::create_from(seconds).plus(total_minutes.multiplied_by(Crypto::UnsignedBigInteger(60))); | ||||
|     // 6. Set milliseconds to ℝ(milliseconds) + seconds × 1000.
 | ||||
|     // 5. Set milliseconds to milliseconds + seconds × 1000.
 | ||||
|     auto total_milliseconds = Crypto::SignedBigInteger::create_from(milliseconds).plus(total_seconds.multiplied_by(Crypto::UnsignedBigInteger(1000))); | ||||
|     // 7. Set microseconds to ℝ(microseconds) + milliseconds × 1000.
 | ||||
|     // 6. Set microseconds to microseconds + milliseconds × 1000.
 | ||||
|     auto total_microseconds = Crypto::SignedBigInteger::create_from(microseconds).plus(total_milliseconds.multiplied_by(Crypto::UnsignedBigInteger(1000))); | ||||
|     // 8. Return nanoseconds + microseconds × 1000.
 | ||||
|     // 7. Return nanoseconds + microseconds × 1000.
 | ||||
|     return result_nanoseconds.plus(total_microseconds.multiplied_by(Crypto::UnsignedBigInteger(1000))); | ||||
| } | ||||
| 
 | ||||
|  | @ -560,7 +585,7 @@ ThrowCompletionOr<TimeDurationRecord> balance_duration(GlobalObject& global_obje | |||
|         // a. Assert: largestUnit is "nanosecond".
 | ||||
|         VERIFY(largest_unit == "nanosecond"sv); | ||||
|     } | ||||
|     // 15. Return ! CreateTimeDurationRecord(days, hours × sign, minutes × sign, seconds × sign, milliseconds × sign, microseconds × sign, nanoseconds × sign).
 | ||||
|     // 15. Return ? CreateTimeDurationRecord(days, hours × sign, minutes × sign, seconds × sign, milliseconds × sign, microseconds × sign, nanoseconds × sign).
 | ||||
|     return create_time_duration_record(days, hours * sign, minutes * sign, seconds * sign, milliseconds * sign, microseconds * sign, result_nanoseconds * sign); | ||||
| } | ||||
| 
 | ||||
|  | @ -976,12 +1001,12 @@ ThrowCompletionOr<DurationRecord> add_duration(GlobalObject& global_object, doub | |||
|             return vm.throw_completion<RangeError>(global_object, ErrorType::TemporalMissingStartingPoint, "year, month or week"); | ||||
|         } | ||||
| 
 | ||||
|         // b. Let result be ! BalanceDuration(d1 + d2, h1 + h2, min1 + min2, s1 + s2, ms1 + ms2, mus1 + mus2, ns1 + ns2, largestUnit).
 | ||||
|         // b. Let result be ? BalanceDuration(d1 + d2, h1 + h2, min1 + min2, s1 + s2, ms1 + ms2, mus1 + mus2, ns1 + ns2, largestUnit).
 | ||||
|         // FIXME: Narrowing conversion from 'double' to 'i64'
 | ||||
|         auto result = MUST(balance_duration(global_object, days1 + days2, hours1 + hours2, minutes1 + minutes2, seconds1 + seconds2, milliseconds1 + milliseconds2, microseconds1 + microseconds2, Crypto::SignedBigInteger::create_from(nanoseconds1 + nanoseconds2), largest_unit)); | ||||
|         auto result = TRY(balance_duration(global_object, days1 + days2, hours1 + hours2, minutes1 + minutes2, seconds1 + seconds2, milliseconds1 + milliseconds2, microseconds1 + microseconds2, Crypto::SignedBigInteger::create_from(nanoseconds1 + nanoseconds2), largest_unit)); | ||||
| 
 | ||||
|         // c. Return ? CreateDurationRecord(0, 0, 0, result.[[Days]], result.[[Hours]], result.[[Minutes]], result.[[Seconds]], result.[[Milliseconds]], result.[[Microseconds]], result.[[Nanoseconds]]).
 | ||||
|         return create_duration_record(global_object, 0, 0, 0, result.days, result.hours, result.minutes, result.seconds, result.milliseconds, result.microseconds, result.nanoseconds); | ||||
|         // c. Return ! CreateDurationRecord(0, 0, 0, result.[[Days]], result.[[Hours]], result.[[Minutes]], result.[[Seconds]], result.[[Milliseconds]], result.[[Microseconds]], result.[[Nanoseconds]]).
 | ||||
|         return MUST(create_duration_record(global_object, 0, 0, 0, result.days, result.hours, result.minutes, result.seconds, result.milliseconds, result.microseconds, result.nanoseconds)); | ||||
|     } | ||||
| 
 | ||||
|     // 5. If relativeTo has an [[InitializedTemporalDate]] internal slot, then
 | ||||
|  | @ -1018,12 +1043,12 @@ ThrowCompletionOr<DurationRecord> add_duration(GlobalObject& global_object, doub | |||
|         // j. Let dateDifference be ? CalendarDateUntil(calendar, relativeTo, end, differenceOptions).
 | ||||
|         auto* date_difference = TRY(calendar_date_until(global_object, calendar, &relative_to, end, *difference_options)); | ||||
| 
 | ||||
|         // k. Let result be ! BalanceDuration(dateDifference.[[Days]], h1 + h2, min1 + min2, s1 + s2, ms1 + ms2, mus1 + mus2, ns1 + ns2, largestUnit).
 | ||||
|         // k. Let result be ? BalanceDuration(dateDifference.[[Days]], h1 + h2, min1 + min2, s1 + s2, ms1 + ms2, mus1 + mus2, ns1 + ns2, largestUnit).
 | ||||
|         // FIXME: Narrowing conversion from 'double' to 'i64'
 | ||||
|         auto result = MUST(balance_duration(global_object, date_difference->days(), hours1 + hours2, minutes1 + minutes2, seconds1 + seconds2, milliseconds1 + milliseconds2, microseconds1 + microseconds2, Crypto::SignedBigInteger::create_from(nanoseconds1 + nanoseconds2), largest_unit)); | ||||
|         auto result = TRY(balance_duration(global_object, date_difference->days(), hours1 + hours2, minutes1 + minutes2, seconds1 + seconds2, milliseconds1 + milliseconds2, microseconds1 + microseconds2, Crypto::SignedBigInteger::create_from(nanoseconds1 + nanoseconds2), largest_unit)); | ||||
| 
 | ||||
|         // l. Return ? CreateDurationRecord(dateDifference.[[Years]], dateDifference.[[Months]], dateDifference.[[Weeks]], result.[[Days]], result.[[Hours]], result.[[Minutes]], result.[[Seconds]], result.[[Milliseconds]], result.[[Microseconds]], result.[[Nanoseconds]]).
 | ||||
|         return create_duration_record(global_object, date_difference->years(), date_difference->months(), date_difference->weeks(), result.days, result.hours, result.minutes, result.seconds, result.milliseconds, result.microseconds, result.nanoseconds); | ||||
|         return MUST(create_duration_record(global_object, date_difference->years(), date_difference->months(), date_difference->weeks(), result.days, result.hours, result.minutes, result.seconds, result.milliseconds, result.microseconds, result.nanoseconds)); | ||||
|     } | ||||
| 
 | ||||
|     // 6. Assert: relativeTo has an [[InitializedTemporalZonedDateTime]] internal slot.
 | ||||
|  | @ -1093,21 +1118,19 @@ ThrowCompletionOr<RoundedDuration> round_duration(GlobalObject& global_object, d | |||
|     // spec is concerned, but the latter is more strictly typed for convenience.
 | ||||
|     PlainDate* relative_to = nullptr; | ||||
| 
 | ||||
|     // 2. Let years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds, and increment each be the mathematical values of themselves.
 | ||||
| 
 | ||||
|     // FIXME: assuming "smallestUnit" as the option name here leads to confusing error messages in some cases:
 | ||||
|     //        > new Temporal.Duration().total({ unit: "month" })
 | ||||
|     //        Uncaught exception: [RangeError] month is not a valid value for option smallestUnit
 | ||||
|     // 3. If unit is "year", "month", or "week", and relativeTo is undefined, then
 | ||||
|     // 2. If unit is "year", "month", or "week", and relativeTo is undefined, then
 | ||||
|     if (unit.is_one_of("year"sv, "month"sv, "week"sv) && !relative_to_object) { | ||||
|         // a. Throw a RangeError exception.
 | ||||
|         return vm.throw_completion<RangeError>(global_object, ErrorType::OptionIsNotValidValue, unit, "smallestUnit"sv); | ||||
|     } | ||||
| 
 | ||||
|     // 4. Let zonedRelativeTo be undefined.
 | ||||
|     // 3. Let zonedRelativeTo be undefined.
 | ||||
|     ZonedDateTime* zoned_relative_to = nullptr; | ||||
| 
 | ||||
|     // 5. If relativeTo is not undefined, then
 | ||||
|     // 4. If relativeTo is not undefined, then
 | ||||
|     if (relative_to_object) { | ||||
|         // a. If relativeTo has an [[InitializedTemporalZonedDateTime]] internal slot, then
 | ||||
|         if (is<ZonedDateTime>(relative_to_object)) { | ||||
|  | @ -1130,10 +1153,10 @@ ThrowCompletionOr<RoundedDuration> round_duration(GlobalObject& global_object, d | |||
|         // c. Let calendar be relativeTo.[[Calendar]].
 | ||||
|         calendar = &relative_to->calendar(); | ||||
|     } | ||||
|     // 6. Else,
 | ||||
|     // 5. Else,
 | ||||
|     //    a. NOTE: calendar will not be used below.
 | ||||
| 
 | ||||
|     // 7. If unit is one of "year", "month", "week", or "day", then
 | ||||
|     // 6. If unit is one of "year", "month", "week", or "day", then
 | ||||
|     if (unit.is_one_of("year"sv, "month"sv, "week"sv, "day"sv)) { | ||||
|         // a. Let nanoseconds be ! TotalDurationNanoseconds(0, hours, minutes, seconds, milliseconds, microseconds, nanoseconds, 0).
 | ||||
|         auto nanoseconds_bigint = total_duration_nanoseconds(0, hours, minutes, seconds, milliseconds, microseconds, Crypto::SignedBigInteger::create_from((i64)nanoseconds), 0); | ||||
|  | @ -1162,16 +1185,16 @@ ThrowCompletionOr<RoundedDuration> round_duration(GlobalObject& global_object, d | |||
|         microseconds = 0; | ||||
|         nanoseconds = 0; | ||||
|     } | ||||
|     // 8. Else,
 | ||||
|     // 7. Else,
 | ||||
|     else { | ||||
|         // a. Let fractionalSeconds be nanoseconds × 10^-9 + microseconds × 10^-6 + milliseconds × 10^-3 + seconds.
 | ||||
|         fractional_seconds = nanoseconds * 0.000000001 + microseconds * 0.000001 + milliseconds * 0.001 + seconds; | ||||
|     } | ||||
| 
 | ||||
|     // 9. Let remainder be undefined.
 | ||||
|     // 8. Let remainder be undefined.
 | ||||
|     double remainder = 0; | ||||
| 
 | ||||
|     // 10. If unit is "year", then
 | ||||
|     // 9. If unit is "year", then
 | ||||
|     if (unit == "year"sv) { | ||||
|         VERIFY(relative_to); | ||||
| 
 | ||||
|  | @ -1261,7 +1284,7 @@ ThrowCompletionOr<RoundedDuration> round_duration(GlobalObject& global_object, d | |||
|         weeks = 0; | ||||
|         days = 0; | ||||
|     } | ||||
|     // 11. Else if unit is "month", then
 | ||||
|     // 10. Else if unit is "month", then
 | ||||
|     else if (unit == "month"sv) { | ||||
|         VERIFY(relative_to); | ||||
| 
 | ||||
|  | @ -1335,7 +1358,7 @@ ThrowCompletionOr<RoundedDuration> round_duration(GlobalObject& global_object, d | |||
|         weeks = 0; | ||||
|         days = 0; | ||||
|     } | ||||
|     // 12. Else if unit is "week", then
 | ||||
|     // 11. Else if unit is "week", then
 | ||||
|     else if (unit == "week"sv) { | ||||
|         VERIFY(relative_to); | ||||
| 
 | ||||
|  | @ -1384,7 +1407,7 @@ ThrowCompletionOr<RoundedDuration> round_duration(GlobalObject& global_object, d | |||
|         // j. Set days to 0.
 | ||||
|         days = 0; | ||||
|     } | ||||
|     // 13. Else if unit is "day", then
 | ||||
|     // 12. Else if unit is "day", then
 | ||||
|     else if (unit == "day"sv) { | ||||
|         // a. Let fractionalDays be days.
 | ||||
|         auto fractional_days = days; | ||||
|  | @ -1395,7 +1418,7 @@ ThrowCompletionOr<RoundedDuration> round_duration(GlobalObject& global_object, d | |||
|         // c. Set remainder to fractionalDays - days.
 | ||||
|         remainder = fractional_days - days; | ||||
|     } | ||||
|     // 14. Else if unit is "hour", then
 | ||||
|     // 13. Else if unit is "hour", then
 | ||||
|     else if (unit == "hour"sv) { | ||||
|         // a. Let fractionalHours be (fractionalSeconds / 60 + minutes) / 60 + hours.
 | ||||
|         auto fractional_hours = (fractional_seconds / 60 + minutes) / 60 + hours; | ||||
|  | @ -1413,7 +1436,7 @@ ThrowCompletionOr<RoundedDuration> round_duration(GlobalObject& global_object, d | |||
|         microseconds = 0; | ||||
|         nanoseconds = 0; | ||||
|     } | ||||
|     // 15. Else if unit is "minute", then
 | ||||
|     // 14. Else if unit is "minute", then
 | ||||
|     else if (unit == "minute"sv) { | ||||
|         // a. Let fractionalMinutes be fractionalSeconds / 60 + minutes.
 | ||||
|         auto fractional_minutes = fractional_seconds / 60 + minutes; | ||||
|  | @ -1430,7 +1453,7 @@ ThrowCompletionOr<RoundedDuration> round_duration(GlobalObject& global_object, d | |||
|         microseconds = 0; | ||||
|         nanoseconds = 0; | ||||
|     } | ||||
|     // 16. Else if unit is "second", then
 | ||||
|     // 15. Else if unit is "second", then
 | ||||
|     else if (unit == "second"sv) { | ||||
|         // a. Set seconds to ! RoundNumberToIncrement(fractionalSeconds, increment, roundingMode).
 | ||||
|         seconds = (double)round_number_to_increment(fractional_seconds, increment, rounding_mode); | ||||
|  | @ -1443,7 +1466,7 @@ ThrowCompletionOr<RoundedDuration> round_duration(GlobalObject& global_object, d | |||
|         microseconds = 0; | ||||
|         nanoseconds = 0; | ||||
|     } | ||||
|     // 17. Else if unit is "millisecond", then
 | ||||
|     // 16. Else if unit is "millisecond", then
 | ||||
|     else if (unit == "millisecond"sv) { | ||||
|         // a. Let fractionalMilliseconds be nanoseconds × 10^-6 + microseconds × 10^-3 + milliseconds.
 | ||||
|         auto fractional_milliseconds = nanoseconds * 0.000001 + microseconds * 0.001 + milliseconds; | ||||
|  | @ -1458,7 +1481,7 @@ ThrowCompletionOr<RoundedDuration> round_duration(GlobalObject& global_object, d | |||
|         microseconds = 0; | ||||
|         nanoseconds = 0; | ||||
|     } | ||||
|     // 18. Else if unit is "microsecond", then
 | ||||
|     // 17. Else if unit is "microsecond", then
 | ||||
|     else if (unit == "microsecond"sv) { | ||||
|         // a. Let fractionalMicroseconds be nanoseconds × 10^-3 + microseconds.
 | ||||
|         auto fractional_microseconds = nanoseconds * 0.001 + microseconds; | ||||
|  | @ -1472,7 +1495,7 @@ ThrowCompletionOr<RoundedDuration> round_duration(GlobalObject& global_object, d | |||
|         // d. Set nanoseconds to 0.
 | ||||
|         nanoseconds = 0; | ||||
|     } | ||||
|     // 19. Else,
 | ||||
|     // 18. Else,
 | ||||
|     else { | ||||
|         // a. Assert: unit is "nanosecond".
 | ||||
|         VERIFY(unit == "nanosecond"sv); | ||||
|  | @ -1487,10 +1510,10 @@ ThrowCompletionOr<RoundedDuration> round_duration(GlobalObject& global_object, d | |||
|         remainder -= nanoseconds; | ||||
|     } | ||||
| 
 | ||||
|     // 20. Let duration be ! CreateDurationRecord(years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds).
 | ||||
|     // 19. Let duration be ! CreateDurationRecord(years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds).
 | ||||
|     auto duration = create_duration_record(years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds); | ||||
| 
 | ||||
|     // 21. Return the Record { [[DurationRecord]]: duration, [[Remainder]]: remainder }.
 | ||||
|     // 20. Return the Record { [[DurationRecord]]: duration, [[Remainder]]: remainder }.
 | ||||
|     return RoundedDuration { .duration_record = duration, .remainder = remainder }; | ||||
| } | ||||
| 
 | ||||
|  | @ -1582,81 +1605,76 @@ String temporal_duration_to_string(double years, double months, double weeks, do | |||
|     if (precision.has<StringView>()) | ||||
|         VERIFY(precision.get<StringView>() == "auto"sv); | ||||
| 
 | ||||
|     // 1. Set seconds to the mathematical value of seconds.
 | ||||
|     // 2. Set milliseconds to the mathematical value of milliseconds.
 | ||||
|     // 3. Set microseconds to the mathematical value of microseconds.
 | ||||
|     // 4. Set nanoseconds to the mathematical value of nanoseconds.
 | ||||
| 
 | ||||
|     // 5. Let sign be ! DurationSign(years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds).
 | ||||
|     // 1. Let sign be ! DurationSign(years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds).
 | ||||
|     auto sign = duration_sign(years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds); | ||||
| 
 | ||||
|     // 6. Set microseconds to microseconds + RoundTowardsZero(nanoseconds / 1000).
 | ||||
|     // 2. Set microseconds to microseconds + RoundTowardsZero(nanoseconds / 1000).
 | ||||
|     microseconds += trunc(nanoseconds / 1000); | ||||
| 
 | ||||
|     // 7. Set nanoseconds to remainder(nanoseconds, 1000).
 | ||||
|     // 3. Set nanoseconds to remainder(nanoseconds, 1000).
 | ||||
|     nanoseconds = fmod(nanoseconds, 1000); | ||||
| 
 | ||||
|     // 8. Set milliseconds to milliseconds + RoundTowardsZero(microseconds / 1000).
 | ||||
|     // 4. Set milliseconds to milliseconds + RoundTowardsZero(microseconds / 1000).
 | ||||
|     milliseconds += trunc(microseconds / 1000); | ||||
| 
 | ||||
|     // 9. Set microseconds to remainder(microseconds, 1000).
 | ||||
|     // 5. Set microseconds to remainder(microseconds, 1000).
 | ||||
|     microseconds = fmod(microseconds, 1000); | ||||
| 
 | ||||
|     // 10. Set seconds to seconds + RoundTowardsZero(milliseconds / 1000).
 | ||||
|     // 6. Set seconds to seconds + RoundTowardsZero(milliseconds / 1000).
 | ||||
|     seconds += trunc(milliseconds / 1000); | ||||
| 
 | ||||
|     // 11. Set milliseconds to remainder(milliseconds, 1000).
 | ||||
|     // 7. Set milliseconds to remainder(milliseconds, 1000).
 | ||||
|     milliseconds = fmod(milliseconds, 1000); | ||||
| 
 | ||||
|     // 12. Let datePart be "".
 | ||||
|     // 8. Let datePart be "".
 | ||||
|     StringBuilder date_part; | ||||
| 
 | ||||
|     // 13. If years is not 0, then
 | ||||
|     // 9. If years is not 0, then
 | ||||
|     if (years != 0) { | ||||
|         // a. Set datePart to the string concatenation of abs(years) formatted as a decimal number and the code unit 0x0059 (LATIN CAPITAL LETTER Y).
 | ||||
|         date_part.appendff("{}", fabs(years)); | ||||
|         date_part.append('Y'); | ||||
|     } | ||||
| 
 | ||||
|     // 14. If months is not 0, then
 | ||||
|     // 10. If months is not 0, then
 | ||||
|     if (months != 0) { | ||||
|         // a. Set datePart to the string concatenation of datePart, abs(months) formatted as a decimal number, and the code unit 0x004D (LATIN CAPITAL LETTER M).
 | ||||
|         date_part.appendff("{}", fabs(months)); | ||||
|         date_part.append('M'); | ||||
|     } | ||||
| 
 | ||||
|     // 15. If weeks is not 0, then
 | ||||
|     // 11. If weeks is not 0, then
 | ||||
|     if (weeks != 0) { | ||||
|         // a. Set datePart to the string concatenation of datePart, abs(weeks) formatted as a decimal number, and the code unit 0x0057 (LATIN CAPITAL LETTER W).
 | ||||
|         date_part.appendff("{}", fabs(weeks)); | ||||
|         date_part.append('W'); | ||||
|     } | ||||
| 
 | ||||
|     // 16. If days is not 0, then
 | ||||
|     // 12. If days is not 0, then
 | ||||
|     if (days != 0) { | ||||
|         // a. Set datePart to the string concatenation of datePart, abs(days) formatted as a decimal number, and the code unit 0x0044 (LATIN CAPITAL LETTER D).
 | ||||
|         date_part.appendff("{}", fabs(days)); | ||||
|         date_part.append('D'); | ||||
|     } | ||||
| 
 | ||||
|     // 17. Let timePart be "".
 | ||||
|     // 13. Let timePart be "".
 | ||||
|     StringBuilder time_part; | ||||
| 
 | ||||
|     // 18. If hours is not 0, then
 | ||||
|     // 14. If hours is not 0, then
 | ||||
|     if (hours != 0) { | ||||
|         // a. Set timePart to the string concatenation of abs(hours) formatted as a decimal number and the code unit 0x0048 (LATIN CAPITAL LETTER H).
 | ||||
|         time_part.appendff("{}", fabs(hours)); | ||||
|         time_part.append('H'); | ||||
|     } | ||||
| 
 | ||||
|     // 19. If minutes is not 0, then
 | ||||
|     // 15. If minutes is not 0, then
 | ||||
|     if (minutes != 0) { | ||||
|         // a. Set timePart to the string concatenation of timePart, abs(minutes) formatted as a decimal number, and the code unit 0x004D (LATIN CAPITAL LETTER M).
 | ||||
|         time_part.appendff("{}", fabs(minutes)); | ||||
|         time_part.append('M'); | ||||
|     } | ||||
| 
 | ||||
|     // 20. If any of seconds, milliseconds, microseconds, and nanoseconds are not 0; or years, months, weeks, days, hours, and minutes are all 0; or precision is not "auto"; then
 | ||||
|     // 16. If any of seconds, milliseconds, microseconds, and nanoseconds are not 0; or years, months, weeks, days, hours, and minutes are all 0; or precision is not "auto"; then
 | ||||
|     if ((seconds != 0 || milliseconds != 0 || microseconds != 0 || nanoseconds != 0) || (years == 0 && months == 0 && weeks == 0 && days == 0 && hours == 0 && minutes == 0) || (!precision.has<StringView>() || precision.get<StringView>() != "auto"sv)) { | ||||
|         // a. Let fraction be abs(milliseconds) × 10^6 + abs(microseconds) × 10^3 + abs(nanoseconds).
 | ||||
|         auto fraction = fabs(milliseconds) * 1'000'000 + fabs(microseconds) * 1'000 + fabs(nanoseconds); | ||||
|  | @ -1699,23 +1717,23 @@ String temporal_duration_to_string(double years, double months, double weeks, do | |||
|         time_part.append('S'); | ||||
|     } | ||||
| 
 | ||||
|     // 21. Let signPart be the code unit 0x002D (HYPHEN-MINUS) if sign < 0, and otherwise the empty String.
 | ||||
|     // 17. Let signPart be the code unit 0x002D (HYPHEN-MINUS) if sign < 0, and otherwise the empty String.
 | ||||
|     auto sign_part = sign < 0 ? "-"sv : ""sv; | ||||
| 
 | ||||
|     // 22. Let result be the string concatenation of signPart, the code unit 0x0050 (LATIN CAPITAL LETTER P) and datePart.
 | ||||
|     // 18. Let result be the string concatenation of signPart, the code unit 0x0050 (LATIN CAPITAL LETTER P) and datePart.
 | ||||
|     StringBuilder result; | ||||
|     result.append(sign_part); | ||||
|     result.append('P'); | ||||
|     result.append(date_part.string_view()); | ||||
| 
 | ||||
|     // 23. If timePart is not "", then
 | ||||
|     // 19. If timePart is not "", then
 | ||||
|     if (!time_part.is_empty()) { | ||||
|         // a. Set result to the string concatenation of result, the code unit 0x0054 (LATIN CAPITAL LETTER T), and timePart.
 | ||||
|         result.append('T'); | ||||
|         result.append(time_part.string_view()); | ||||
|     } | ||||
| 
 | ||||
|     // 24. Return result.
 | ||||
|     // 20. Return result.
 | ||||
|     return result.to_string(); | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -63,7 +63,7 @@ JS_DEFINE_NATIVE_FUNCTION(DurationPrototype::years_getter) | |||
|     // 2. Perform ? RequireInternalSlot(duration, [[InitializedTemporalDuration]]).
 | ||||
|     auto* duration = TRY(typed_this_object(global_object)); | ||||
| 
 | ||||
|     // 3. Return duration.[[Years]].
 | ||||
|     // 3. Return 𝔽(duration.[[Years]]).
 | ||||
|     return Value(duration->years()); | ||||
| } | ||||
| 
 | ||||
|  | @ -74,7 +74,7 @@ JS_DEFINE_NATIVE_FUNCTION(DurationPrototype::months_getter) | |||
|     // 2. Perform ? RequireInternalSlot(duration, [[InitializedTemporalDuration]]).
 | ||||
|     auto* duration = TRY(typed_this_object(global_object)); | ||||
| 
 | ||||
|     // 3. Return duration.[[Months]].
 | ||||
|     // 3. Return 𝔽(duration.[[Months]]).
 | ||||
|     return Value(duration->months()); | ||||
| } | ||||
| 
 | ||||
|  | @ -85,7 +85,7 @@ JS_DEFINE_NATIVE_FUNCTION(DurationPrototype::weeks_getter) | |||
|     // 2. Perform ? RequireInternalSlot(duration, [[InitializedTemporalDuration]]).
 | ||||
|     auto* duration = TRY(typed_this_object(global_object)); | ||||
| 
 | ||||
|     // 3. Return duration.[[Weeks]].
 | ||||
|     // 3. Return 𝔽(duration.[[Weeks]]).
 | ||||
|     return Value(duration->weeks()); | ||||
| } | ||||
| 
 | ||||
|  | @ -96,7 +96,7 @@ JS_DEFINE_NATIVE_FUNCTION(DurationPrototype::days_getter) | |||
|     // 2. Perform ? RequireInternalSlot(duration, [[InitializedTemporalDuration]]).
 | ||||
|     auto* duration = TRY(typed_this_object(global_object)); | ||||
| 
 | ||||
|     // 3. Return duration.[[Days]].
 | ||||
|     // 3. Return 𝔽(duration.[[Days]]).
 | ||||
|     return Value(duration->days()); | ||||
| } | ||||
| 
 | ||||
|  | @ -107,7 +107,7 @@ JS_DEFINE_NATIVE_FUNCTION(DurationPrototype::hours_getter) | |||
|     // 2. Perform ? RequireInternalSlot(duration, [[InitializedTemporalDuration]]).
 | ||||
|     auto* duration = TRY(typed_this_object(global_object)); | ||||
| 
 | ||||
|     // 3. Return duration.[[Hours]].
 | ||||
|     // 3. Return 𝔽(duration.[[Hours]]).
 | ||||
|     return Value(duration->hours()); | ||||
| } | ||||
| 
 | ||||
|  | @ -118,7 +118,7 @@ JS_DEFINE_NATIVE_FUNCTION(DurationPrototype::minutes_getter) | |||
|     // 2. Perform ? RequireInternalSlot(duration, [[InitializedTemporalDuration]]).
 | ||||
|     auto* duration = TRY(typed_this_object(global_object)); | ||||
| 
 | ||||
|     // 3. Return duration.[[Minutes]].
 | ||||
|     // 3. Return 𝔽(duration.[[Minutes]]).
 | ||||
|     return Value(duration->minutes()); | ||||
| } | ||||
| 
 | ||||
|  | @ -129,7 +129,7 @@ JS_DEFINE_NATIVE_FUNCTION(DurationPrototype::seconds_getter) | |||
|     // 2. Perform ? RequireInternalSlot(duration, [[InitializedTemporalDuration]]).
 | ||||
|     auto* duration = TRY(typed_this_object(global_object)); | ||||
| 
 | ||||
|     // 3. Return duration.[[Seconds]].
 | ||||
|     // 3. Return 𝔽(duration.[[Seconds]]).
 | ||||
|     return Value(duration->seconds()); | ||||
| } | ||||
| 
 | ||||
|  | @ -140,7 +140,7 @@ JS_DEFINE_NATIVE_FUNCTION(DurationPrototype::milliseconds_getter) | |||
|     // 2. Perform ? RequireInternalSlot(duration, [[InitializedTemporalDuration]]).
 | ||||
|     auto* duration = TRY(typed_this_object(global_object)); | ||||
| 
 | ||||
|     // 3. Return duration.[[Milliseconds]].
 | ||||
|     // 3. Return 𝔽(duration.[[Milliseconds]]).
 | ||||
|     return Value(duration->milliseconds()); | ||||
| } | ||||
| 
 | ||||
|  | @ -151,7 +151,7 @@ JS_DEFINE_NATIVE_FUNCTION(DurationPrototype::microseconds_getter) | |||
|     // 2. Perform ? RequireInternalSlot(duration, [[InitializedTemporalDuration]]).
 | ||||
|     auto* duration = TRY(typed_this_object(global_object)); | ||||
| 
 | ||||
|     // 3. Return duration.[[Microseconds]].
 | ||||
|     // 3. Return 𝔽(duration.[[Microseconds]]).
 | ||||
|     return Value(duration->microseconds()); | ||||
| } | ||||
| 
 | ||||
|  | @ -162,7 +162,7 @@ JS_DEFINE_NATIVE_FUNCTION(DurationPrototype::nanoseconds_getter) | |||
|     // 2. Perform ? RequireInternalSlot(duration, [[InitializedTemporalDuration]]).
 | ||||
|     auto* duration = TRY(typed_this_object(global_object)); | ||||
| 
 | ||||
|     // 3. Return duration.[[Nanoseconds]].
 | ||||
|     // 3. Return 𝔽(duration.[[Nanoseconds]]).
 | ||||
|     return Value(duration->nanoseconds()); | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -13,9 +13,9 @@ describe("correct behavior", () => { | |||
|         const dateTwo = new Temporal.PlainDate(2022, 12, 25); | ||||
|         const sinceDuration = dateTwo.since(dateOne); | ||||
| 
 | ||||
|         expect(sinceDuration.years).toBe(-0); | ||||
|         expect(sinceDuration.months).toBe(-0); | ||||
|         expect(sinceDuration.weeks).toBe(-0); | ||||
|         expect(sinceDuration.years).toBe(0); | ||||
|         expect(sinceDuration.months).toBe(0); | ||||
|         expect(sinceDuration.weeks).toBe(0); | ||||
|         expect(sinceDuration.days).toBe(406); | ||||
|         expect(sinceDuration.hours).toBe(0); | ||||
|         expect(sinceDuration.minutes).toBe(0); | ||||
|  | @ -30,10 +30,10 @@ describe("correct behavior", () => { | |||
|         const equalDateTwo = new Temporal.PlainDate(1, 1, 1); | ||||
| 
 | ||||
|         const checkResults = result => { | ||||
|             expect(result.years).toBe(-0); | ||||
|             expect(result.months).toBe(-0); | ||||
|             expect(result.weeks).toBe(-0); | ||||
|             expect(result.days).toBe(-0); | ||||
|             expect(result.years).toBe(0); | ||||
|             expect(result.months).toBe(0); | ||||
|             expect(result.weeks).toBe(0); | ||||
|             expect(result.days).toBe(0); | ||||
|             expect(result.hours).toBe(0); | ||||
|             expect(result.minutes).toBe(0); | ||||
|             expect(result.seconds).toBe(0); | ||||
|  | @ -53,9 +53,9 @@ describe("correct behavior", () => { | |||
|         const dateTwo = new Temporal.PlainDate(2022, 12, 25); | ||||
|         const sinceDuration = dateOne.since(dateTwo); | ||||
| 
 | ||||
|         expect(sinceDuration.years).toBe(-0); | ||||
|         expect(sinceDuration.months).toBe(-0); | ||||
|         expect(sinceDuration.weeks).toBe(-0); | ||||
|         expect(sinceDuration.years).toBe(0); | ||||
|         expect(sinceDuration.months).toBe(0); | ||||
|         expect(sinceDuration.weeks).toBe(0); | ||||
|         expect(sinceDuration.days).toBe(-406); | ||||
|         expect(sinceDuration.hours).toBe(0); | ||||
|         expect(sinceDuration.minutes).toBe(0); | ||||
|  | @ -106,9 +106,9 @@ describe("correct behavior", () => { | |||
|         const dateTwo = new Temporal.PlainDate(2022, 12, 25); | ||||
|         const sinceDuration = dateTwo.since("2021-11-14"); | ||||
| 
 | ||||
|         expect(sinceDuration.years).toBe(-0); | ||||
|         expect(sinceDuration.months).toBe(-0); | ||||
|         expect(sinceDuration.weeks).toBe(-0); | ||||
|         expect(sinceDuration.years).toBe(0); | ||||
|         expect(sinceDuration.months).toBe(0); | ||||
|         expect(sinceDuration.weeks).toBe(0); | ||||
|         expect(sinceDuration.days).toBe(406); | ||||
|         expect(sinceDuration.hours).toBe(0); | ||||
|         expect(sinceDuration.minutes).toBe(0); | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Linus Groh
						Linus Groh