mirror of
https://github.com/RGBCube/serenity
synced 2025-07-08 17:37:35 +00:00
LibJS: Convert remaining Date AOs using JS::Value as in/output to double
There was an awful lot of JS::Value <-> double conversion going on, even through these AOs only work with number values anyway. They don't need a global object either as they won't allocate or throw, that was simply to pass it to infallible calls of ToIntegerOrInfinity.
This commit is contained in:
parent
b9b3d01bea
commit
f7c9bd0760
10 changed files with 357 additions and 354 deletions
|
@ -300,25 +300,25 @@ double utc_time(double time)
|
|||
}
|
||||
|
||||
// 21.4.1.11 MakeTime ( hour, min, sec, ms ), https://tc39.es/ecma262/#sec-maketime
|
||||
Value make_time(GlobalObject& global_object, Value hour, Value min, Value sec, Value ms)
|
||||
double make_time(double hour, double min, double sec, double ms)
|
||||
{
|
||||
// 1. If hour is not finite or min is not finite or sec is not finite or ms is not finite, return NaN.
|
||||
if (!hour.is_finite_number() || !min.is_finite_number() || !sec.is_finite_number() || !ms.is_finite_number())
|
||||
return js_nan();
|
||||
if (!isfinite(hour) || !isfinite(min) || !isfinite(sec) || !isfinite(ms))
|
||||
return NAN;
|
||||
|
||||
// 2. Let h be 𝔽(! ToIntegerOrInfinity(hour)).
|
||||
auto h = MUST(hour.to_integer_or_infinity(global_object));
|
||||
auto h = to_integer_or_infinity(hour);
|
||||
// 3. Let m be 𝔽(! ToIntegerOrInfinity(min)).
|
||||
auto m = MUST(min.to_integer_or_infinity(global_object));
|
||||
auto m = to_integer_or_infinity(min);
|
||||
// 4. Let s be 𝔽(! ToIntegerOrInfinity(sec)).
|
||||
auto s = MUST(sec.to_integer_or_infinity(global_object));
|
||||
auto s = to_integer_or_infinity(sec);
|
||||
// 5. Let milli be 𝔽(! ToIntegerOrInfinity(ms)).
|
||||
auto milli = MUST(ms.to_integer_or_infinity(global_object));
|
||||
auto milli = to_integer_or_infinity(ms);
|
||||
// 6. Let t be ((h * msPerHour + m * msPerMinute) + s * msPerSecond) + milli, performing the arithmetic according to IEEE 754-2019 rules (that is, as if using the ECMAScript operators * and +).
|
||||
// NOTE: C++ arithmetic abides by IEEE 754 rules
|
||||
auto t = ((h * ms_per_hour + m * ms_per_minute) + s * ms_per_second) + milli;
|
||||
// 7. Return t.
|
||||
return Value(t);
|
||||
return t;
|
||||
}
|
||||
|
||||
// Day(t), https://tc39.es/ecma262/#eqn-Day
|
||||
|
@ -335,69 +335,69 @@ double time_within_day(double time)
|
|||
}
|
||||
|
||||
// 21.4.1.12 MakeDay ( year, month, date ), https://tc39.es/ecma262/#sec-makeday
|
||||
Value make_day(GlobalObject& global_object, Value year, Value month, Value date)
|
||||
double make_day(double year, double month, double date)
|
||||
{
|
||||
// 1. If year is not finite or month is not finite or date is not finite, return NaN.
|
||||
if (!year.is_finite_number() || !month.is_finite_number() || !date.is_finite_number())
|
||||
return js_nan();
|
||||
if (!isfinite(year) || !isfinite(month) || !isfinite(date))
|
||||
return NAN;
|
||||
|
||||
// 2. Let y be 𝔽(! ToIntegerOrInfinity(year)).
|
||||
auto y = MUST(year.to_integer_or_infinity(global_object));
|
||||
auto y = to_integer_or_infinity(year);
|
||||
// 3. Let m be 𝔽(! ToIntegerOrInfinity(month)).
|
||||
auto m = MUST(month.to_integer_or_infinity(global_object));
|
||||
auto m = to_integer_or_infinity(month);
|
||||
// 4. Let dt be 𝔽(! ToIntegerOrInfinity(date)).
|
||||
auto dt = MUST(date.to_integer_or_infinity(global_object));
|
||||
auto dt = to_integer_or_infinity(date);
|
||||
// 5. Let ym be y + 𝔽(floor(ℝ(m) / 12)).
|
||||
auto ym = y + floor(m / 12);
|
||||
// 6. If ym is not finite, return NaN.
|
||||
if (!Value(ym).is_finite_number())
|
||||
return js_nan();
|
||||
if (!isfinite(ym))
|
||||
return NAN;
|
||||
// 7. Let mn be 𝔽(ℝ(m) modulo 12).
|
||||
auto mn = modulo(m, 12);
|
||||
|
||||
// 8. Find a finite time value t such that YearFromTime(t) is ym and MonthFromTime(t) is mn and DateFromTime(t) is 1𝔽; but if this is not possible (because some argument is out of range), return NaN.
|
||||
if (!AK::is_within_range<int>(ym) || !AK::is_within_range<int>(mn + 1))
|
||||
return js_nan();
|
||||
return NAN;
|
||||
|
||||
// FIXME: We are avoiding AK::years_to_days_since_epoch here because it is implemented by looping over
|
||||
// the range [1970, ym), which will spin for any time value with an extremely large year.
|
||||
auto t = time_from_year(ym) + (day_of_year(static_cast<int>(ym), static_cast<int>(mn) + 1, 1) * ms_per_day);
|
||||
|
||||
// 9. Return Day(t) + dt - 1𝔽.
|
||||
return Value(day(static_cast<double>(t)) + dt - 1);
|
||||
return day(static_cast<double>(t)) + dt - 1;
|
||||
}
|
||||
|
||||
// 21.4.1.13 MakeDate ( day, time ), https://tc39.es/ecma262/#sec-makedate
|
||||
Value make_date(Value day, Value time)
|
||||
double make_date(double day, double time)
|
||||
{
|
||||
// 1. If day is not finite or time is not finite, return NaN.
|
||||
if (!day.is_finite_number() || !time.is_finite_number())
|
||||
return js_nan();
|
||||
if (!isfinite(day) || !isfinite(time))
|
||||
return NAN;
|
||||
|
||||
// 2. Let tv be day × msPerDay + time.
|
||||
auto tv = Value(day.as_double() * ms_per_day + time.as_double());
|
||||
auto tv = day * ms_per_day + time;
|
||||
|
||||
// 3. If tv is not finite, return NaN.
|
||||
if (!tv.is_finite_number())
|
||||
return js_nan();
|
||||
if (!isfinite(tv))
|
||||
return NAN;
|
||||
|
||||
// 4. Return tv.
|
||||
return tv;
|
||||
}
|
||||
|
||||
// 21.4.1.14 TimeClip ( time ), https://tc39.es/ecma262/#sec-timeclip
|
||||
Value time_clip(GlobalObject& global_object, Value time)
|
||||
double time_clip(double time)
|
||||
{
|
||||
// 1. If time is not finite, return NaN.
|
||||
if (!time.is_finite_number())
|
||||
return js_nan();
|
||||
if (!isfinite(time))
|
||||
return NAN;
|
||||
|
||||
// 2. If abs(ℝ(time)) > 8.64 × 10^15, return NaN.
|
||||
if (fabs(time.as_double()) > 8.64E15)
|
||||
return js_nan();
|
||||
if (fabs(time) > 8.64E15)
|
||||
return NAN;
|
||||
|
||||
// 3. Return 𝔽(! ToIntegerOrInfinity(time)).
|
||||
return Value(MUST(time.to_integer_or_infinity(global_object)));
|
||||
return to_integer_or_infinity(time);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -63,9 +63,9 @@ double local_time(double time);
|
|||
double utc_time(double time);
|
||||
double day(double);
|
||||
double time_within_day(double);
|
||||
Value make_time(GlobalObject& global_object, Value hour, Value min, Value sec, Value ms);
|
||||
Value make_day(GlobalObject& global_object, Value year, Value month, Value date);
|
||||
Value make_date(Value day, Value time);
|
||||
Value time_clip(GlobalObject& global_object, Value time);
|
||||
double make_time(double hour, double min, double sec, double ms);
|
||||
double make_day(double year, double month, double date);
|
||||
double make_date(double day, double time);
|
||||
double time_clip(double time);
|
||||
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2020, Linus Groh <linusg@serenityos.org>
|
||||
* Copyright (c) 2020-2022, Linus Groh <linusg@serenityos.org>
|
||||
* Copyright (c) 2020, Nico Weber <thakis@chromium.org>
|
||||
* Copyright (c) 2021, Petróczi Zoltán <petroczizoltan@tutanota.com>
|
||||
* Copyright (c) 2022, Tim Flynn <trflynn89@serenityos.org>
|
||||
|
@ -23,7 +23,7 @@
|
|||
namespace JS {
|
||||
|
||||
// 21.4.3.2 Date.parse ( string ), https://tc39.es/ecma262/#sec-date.parse
|
||||
static Value parse_simplified_iso8601(GlobalObject& global_object, String const& iso_8601)
|
||||
static double parse_simplified_iso8601(String const& iso_8601)
|
||||
{
|
||||
// 21.4.1.15 Date Time String Format, https://tc39.es/ecma262/#sec-date-time-string-format
|
||||
GenericLexer lexer(iso_8601);
|
||||
|
@ -126,7 +126,7 @@ static Value parse_simplified_iso8601(GlobalObject& global_object, String const&
|
|||
auto lex_time = [&]() { return lex_hours_minutes(hours, minutes) && (!lexer.consume_specific(':') || lex_seconds_milliseconds()) && lex_timezone(); };
|
||||
|
||||
if (!lex_date() || (lexer.consume_specific('T') && !lex_time()) || !lexer.is_eof()) {
|
||||
return js_nan();
|
||||
return NAN;
|
||||
}
|
||||
|
||||
// We parsed a valid date simplified ISO 8601 string.
|
||||
|
@ -144,22 +144,22 @@ static Value parse_simplified_iso8601(GlobalObject& global_object, String const&
|
|||
else if (timezone == '+')
|
||||
time_ms -= *timezone_hours * 3'600'000 + *timezone_minutes * 60'000;
|
||||
|
||||
return time_clip(global_object, Value(time_ms));
|
||||
return time_clip(time_ms);
|
||||
}
|
||||
|
||||
static Value parse_date_string(GlobalObject& global_object, String const& date_string)
|
||||
static double parse_date_string(String const& date_string)
|
||||
{
|
||||
auto value = parse_simplified_iso8601(global_object, date_string);
|
||||
if (value.is_finite_number())
|
||||
auto value = parse_simplified_iso8601(date_string);
|
||||
if (isfinite(value))
|
||||
return value;
|
||||
|
||||
// Date.parse() is allowed to accept an arbitrary number of implementation-defined formats.
|
||||
// Parse formats of this type: "Wed Apr 17 23:08:53 +0000 2019"
|
||||
auto maybe_datetime = Core::DateTime::parse("%a %b %e %T %z %Y", date_string);
|
||||
if (maybe_datetime.has_value())
|
||||
return Value(1000.0 * maybe_datetime.value().timestamp());
|
||||
return 1000.0 * maybe_datetime->timestamp();
|
||||
|
||||
return js_nan();
|
||||
return NAN;
|
||||
}
|
||||
|
||||
DateConstructor::DateConstructor(GlobalObject& global_object)
|
||||
|
@ -200,20 +200,20 @@ ThrowCompletionOr<Object*> DateConstructor::construct(FunctionObject& new_target
|
|||
auto& vm = this->vm();
|
||||
auto& global_object = this->global_object();
|
||||
|
||||
Value date_value;
|
||||
double date_value;
|
||||
|
||||
// 2. Let numberOfArgs be the number of elements in values.
|
||||
// 3. If numberOfArgs = 0, then
|
||||
if (vm.argument_count() == 0) {
|
||||
// a. Let dv be the time value (UTC) identifying the current time.
|
||||
auto now = AK::Time::now_realtime().to_milliseconds();
|
||||
date_value = Value(static_cast<double>(now));
|
||||
date_value = static_cast<double>(now);
|
||||
}
|
||||
// 4. Else if numberOfArgs = 1, then
|
||||
else if (vm.argument_count() == 1) {
|
||||
// a. Let value be values[0].
|
||||
auto value = vm.argument(0);
|
||||
Value time_value;
|
||||
double time_value;
|
||||
|
||||
// b. If Type(value) is Object and value has a [[DateValue]] internal slot, then
|
||||
if (value.is_object() && is<Date>(value.as_object())) {
|
||||
|
@ -229,28 +229,28 @@ ThrowCompletionOr<Object*> DateConstructor::construct(FunctionObject& new_target
|
|||
if (primitive.is_string()) {
|
||||
// 1. Assert: The next step never returns an abrupt completion because Type(v) is String.
|
||||
// 2. Let tv be the result of parsing v as a date, in exactly the same manner as for the parse method (21.4.3.2).
|
||||
time_value = parse_date_string(global_object, primitive.as_string().string());
|
||||
time_value = parse_date_string(primitive.as_string().string());
|
||||
}
|
||||
// iii. Else,
|
||||
else {
|
||||
// 1. Let tv be ? ToNumber(v).
|
||||
time_value = TRY(primitive.to_number(global_object));
|
||||
time_value = TRY(primitive.to_number(global_object)).as_double();
|
||||
}
|
||||
}
|
||||
|
||||
// d. Let dv be TimeClip(tv).
|
||||
date_value = time_clip(global_object, time_value);
|
||||
date_value = time_clip(time_value);
|
||||
}
|
||||
// 5. Else,
|
||||
else {
|
||||
// a. Assert: numberOfArgs ≥ 2.
|
||||
// b. Let y be ? ToNumber(values[0]).
|
||||
auto year = TRY(vm.argument(0).to_number(global_object));
|
||||
auto year = TRY(vm.argument(0).to_number(global_object)).as_double();
|
||||
// c. Let m be ? ToNumber(values[1]).
|
||||
auto month = TRY(vm.argument(1).to_number(global_object));
|
||||
auto month = TRY(vm.argument(1).to_number(global_object)).as_double();
|
||||
|
||||
auto arg_or = [&vm, &global_object](size_t i, i32 fallback) -> ThrowCompletionOr<Value> {
|
||||
return vm.argument_count() > i ? vm.argument(i).to_number(global_object) : Value(fallback);
|
||||
auto arg_or = [&vm, &global_object](size_t i, double fallback) -> ThrowCompletionOr<double> {
|
||||
return vm.argument_count() > i ? TRY(vm.argument(i).to_number(global_object)).as_double() : fallback;
|
||||
};
|
||||
|
||||
// d. If numberOfArgs > 2, let dt be ? ToNumber(values[2]); else let dt be 1𝔽.
|
||||
|
@ -266,28 +266,28 @@ ThrowCompletionOr<Object*> DateConstructor::construct(FunctionObject& new_target
|
|||
|
||||
// i. If y is NaN, let yr be NaN.
|
||||
// j. Else,
|
||||
if (!year.is_nan()) {
|
||||
if (!isnan(year)) {
|
||||
// i. Let yi be ! ToIntegerOrInfinity(y).
|
||||
auto year_double = MUST(year.to_integer_or_infinity(global_object));
|
||||
auto year_integer = to_integer_or_infinity(year);
|
||||
|
||||
// ii. If 0 ≤ yi ≤ 99, let yr be 1900𝔽 + 𝔽(yi); otherwise, let yr be y.
|
||||
if (0 <= year_double && year_double <= 99)
|
||||
year = Value(1900 + year_double);
|
||||
if (0 <= year_integer && year_integer <= 99)
|
||||
year = 1900 + year_integer;
|
||||
}
|
||||
|
||||
// k. Let finalDate be MakeDate(MakeDay(yr, m, dt), MakeTime(h, min, s, milli)).
|
||||
auto day = make_day(global_object, year, month, date);
|
||||
auto time = make_time(global_object, hours, minutes, seconds, milliseconds);
|
||||
auto day = make_day(year, month, date);
|
||||
auto time = make_time(hours, minutes, seconds, milliseconds);
|
||||
auto final_date = make_date(day, time);
|
||||
|
||||
// l. Let dv be TimeClip(UTC(finalDate)).
|
||||
date_value = time_clip(global_object, Value(utc_time(final_date.as_double())));
|
||||
date_value = time_clip(utc_time(final_date));
|
||||
}
|
||||
|
||||
// 6. Let O be ? OrdinaryCreateFromConstructor(NewTarget, "%Date.prototype%", « [[DateValue]] »).
|
||||
// 7. Set O.[[DateValue]] to dv.
|
||||
// 8. Return O.
|
||||
return TRY(ordinary_create_from_constructor<Date>(global_object, new_target, &GlobalObject::date_prototype, date_value.as_double()));
|
||||
return TRY(ordinary_create_from_constructor<Date>(global_object, new_target, &GlobalObject::date_prototype, date_value));
|
||||
}
|
||||
|
||||
// 21.4.3.1 Date.now ( ), https://tc39.es/ecma262/#sec-date.now
|
||||
|
@ -306,18 +306,18 @@ JS_DEFINE_NATIVE_FUNCTION(DateConstructor::parse)
|
|||
|
||||
auto date_string = TRY(vm.argument(0).to_string(global_object));
|
||||
|
||||
return parse_date_string(global_object, date_string);
|
||||
return Value(parse_date_string(date_string));
|
||||
}
|
||||
|
||||
// 21.4.3.4 Date.UTC ( year [ , month [ , date [ , hours [ , minutes [ , seconds [ , ms ] ] ] ] ] ] ), https://tc39.es/ecma262/#sec-date.utc
|
||||
JS_DEFINE_NATIVE_FUNCTION(DateConstructor::utc)
|
||||
{
|
||||
auto arg_or = [&vm, &global_object](size_t i, i32 fallback) -> ThrowCompletionOr<Value> {
|
||||
return vm.argument_count() > i ? vm.argument(i).to_number(global_object) : Value(fallback);
|
||||
auto arg_or = [&vm, &global_object](size_t i, double fallback) -> ThrowCompletionOr<double> {
|
||||
return vm.argument_count() > i ? TRY(vm.argument(i).to_number(global_object)).as_double() : fallback;
|
||||
};
|
||||
|
||||
// 1. Let y be ? ToNumber(year).
|
||||
auto year = TRY(vm.argument(0).to_number(global_object));
|
||||
auto year = TRY(vm.argument(0).to_number(global_object)).as_double();
|
||||
// 2. If month is present, let m be ? ToNumber(month); else let m be +0𝔽.
|
||||
auto month = TRY(arg_or(1, 0));
|
||||
// 3. If date is present, let dt be ? ToNumber(date); else let dt be 1𝔽.
|
||||
|
@ -333,19 +333,19 @@ JS_DEFINE_NATIVE_FUNCTION(DateConstructor::utc)
|
|||
|
||||
// 8. If y is NaN, let yr be NaN.
|
||||
// 9. Else,
|
||||
if (!year.is_nan()) {
|
||||
if (!isnan(year)) {
|
||||
// a. Let yi be ! ToIntegerOrInfinity(y).
|
||||
auto year_double = MUST(year.to_integer_or_infinity(global_object));
|
||||
auto year_integer = to_integer_or_infinity(year);
|
||||
|
||||
// b. If 0 ≤ yi ≤ 99, let yr be 1900𝔽 + 𝔽(yi); otherwise, let yr be y.
|
||||
if (0 <= year_double && year_double <= 99)
|
||||
year = Value(1900 + year_double);
|
||||
if (0 <= year_integer && year_integer <= 99)
|
||||
year = 1900 + year_integer;
|
||||
}
|
||||
|
||||
// 10. Return TimeClip(MakeDate(MakeDay(yr, m, dt), MakeTime(h, min, s, milli))).
|
||||
auto day = make_day(global_object, year, month, date);
|
||||
auto time = make_time(global_object, hours, minutes, seconds, milliseconds);
|
||||
return time_clip(global_object, make_date(day, time));
|
||||
auto day = make_day(year, month, date);
|
||||
auto time = make_time(hours, minutes, seconds, milliseconds);
|
||||
return Value(time_clip(make_date(day, time)));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2020, Linus Groh <linusg@serenityos.org>
|
||||
* Copyright (c) 2020-2022, Linus Groh <linusg@serenityos.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
@ -71,7 +71,7 @@ private:
|
|||
JS_DECLARE_NATIVE_FUNCTION(symbol_to_primitive);
|
||||
};
|
||||
|
||||
ThrowCompletionOr<Value> this_time_value(GlobalObject& global_object, Value value);
|
||||
ThrowCompletionOr<double> this_time_value(GlobalObject& global_object, Value value);
|
||||
String time_string(double time);
|
||||
String date_string(double time);
|
||||
String time_zone_string(double time);
|
||||
|
|
|
@ -504,15 +504,15 @@ static Optional<StyleAndValue> find_calendar_field(StringView name, Unicode::Cal
|
|||
}
|
||||
|
||||
// 11.5.6 FormatDateTimePattern ( dateTimeFormat, patternParts, x, rangeFormatOptions ), https://tc39.es/ecma402/#sec-formatdatetimepattern
|
||||
ThrowCompletionOr<Vector<PatternPartition>> format_date_time_pattern(GlobalObject& global_object, DateTimeFormat& date_time_format, Vector<PatternPartition> pattern_parts, Value time, Unicode::CalendarPattern const* range_format_options)
|
||||
ThrowCompletionOr<Vector<PatternPartition>> format_date_time_pattern(GlobalObject& global_object, DateTimeFormat& date_time_format, Vector<PatternPartition> pattern_parts, double time, Unicode::CalendarPattern const* range_format_options)
|
||||
{
|
||||
auto& vm = global_object.vm();
|
||||
|
||||
// 1. Let x be TimeClip(x).
|
||||
time = time_clip(global_object, time);
|
||||
time = time_clip(time);
|
||||
|
||||
// 2. If x is NaN, throw a RangeError exception.
|
||||
if (time.is_nan())
|
||||
if (isnan(time))
|
||||
return vm.throw_completion<RangeError>(global_object, ErrorType::IntlInvalidTime);
|
||||
|
||||
// 3. Let locale be dateTimeFormat.[[Locale]].
|
||||
|
@ -567,7 +567,7 @@ ThrowCompletionOr<Vector<PatternPartition>> format_date_time_pattern(GlobalObjec
|
|||
}
|
||||
|
||||
// 13. Let tm be ToLocalTime(x, dateTimeFormat.[[Calendar]], dateTimeFormat.[[TimeZone]]).
|
||||
auto local_time = TRY(to_local_time(global_object, time.as_double(), date_time_format.calendar(), date_time_format.time_zone()));
|
||||
auto local_time = TRY(to_local_time(global_object, time, date_time_format.calendar(), date_time_format.time_zone()));
|
||||
|
||||
// 14. Let result be a new empty List.
|
||||
Vector<PatternPartition> result;
|
||||
|
@ -788,7 +788,7 @@ ThrowCompletionOr<Vector<PatternPartition>> format_date_time_pattern(GlobalObjec
|
|||
}
|
||||
|
||||
// 11.5.7 PartitionDateTimePattern ( dateTimeFormat, x ), https://tc39.es/ecma402/#sec-partitiondatetimepattern
|
||||
ThrowCompletionOr<Vector<PatternPartition>> partition_date_time_pattern(GlobalObject& global_object, DateTimeFormat& date_time_format, Value time)
|
||||
ThrowCompletionOr<Vector<PatternPartition>> partition_date_time_pattern(GlobalObject& global_object, DateTimeFormat& date_time_format, double time)
|
||||
{
|
||||
// 1. Let patternParts be PartitionPattern(dateTimeFormat.[[Pattern]]).
|
||||
auto pattern_parts = partition_pattern(date_time_format.pattern());
|
||||
|
@ -801,7 +801,7 @@ ThrowCompletionOr<Vector<PatternPartition>> partition_date_time_pattern(GlobalOb
|
|||
}
|
||||
|
||||
// 11.5.8 FormatDateTime ( dateTimeFormat, x ), https://tc39.es/ecma402/#sec-formatdatetime
|
||||
ThrowCompletionOr<String> format_date_time(GlobalObject& global_object, DateTimeFormat& date_time_format, Value time)
|
||||
ThrowCompletionOr<String> format_date_time(GlobalObject& global_object, DateTimeFormat& date_time_format, double time)
|
||||
{
|
||||
// 1. Let parts be ? PartitionDateTimePattern(dateTimeFormat, x).
|
||||
auto parts = TRY(partition_date_time_pattern(global_object, date_time_format, time));
|
||||
|
@ -820,7 +820,7 @@ ThrowCompletionOr<String> format_date_time(GlobalObject& global_object, DateTime
|
|||
}
|
||||
|
||||
// 11.5.9 FormatDateTimeToParts ( dateTimeFormat, x ), https://tc39.es/ecma402/#sec-formatdatetimetoparts
|
||||
ThrowCompletionOr<Array*> format_date_time_to_parts(GlobalObject& global_object, DateTimeFormat& date_time_format, Value time)
|
||||
ThrowCompletionOr<Array*> format_date_time_to_parts(GlobalObject& global_object, DateTimeFormat& date_time_format, double time)
|
||||
{
|
||||
auto& vm = global_object.vm();
|
||||
|
||||
|
@ -891,33 +891,33 @@ ThrowCompletionOr<void> for_each_range_pattern_with_source(Unicode::CalendarRang
|
|||
}
|
||||
|
||||
// 11.5.10 PartitionDateTimeRangePattern ( dateTimeFormat, x, y ), https://tc39.es/ecma402/#sec-partitiondatetimerangepattern
|
||||
ThrowCompletionOr<Vector<PatternPartitionWithSource>> partition_date_time_range_pattern(GlobalObject& global_object, DateTimeFormat& date_time_format, Value start, Value end)
|
||||
ThrowCompletionOr<Vector<PatternPartitionWithSource>> partition_date_time_range_pattern(GlobalObject& global_object, DateTimeFormat& date_time_format, double start, double end)
|
||||
{
|
||||
auto& vm = global_object.vm();
|
||||
|
||||
// 1. Let x be TimeClip(x).
|
||||
start = time_clip(global_object, start);
|
||||
start = time_clip(start);
|
||||
|
||||
// 2. If x is NaN, throw a RangeError exception.
|
||||
if (start.is_nan())
|
||||
if (isnan(start))
|
||||
return vm.throw_completion<RangeError>(global_object, ErrorType::IntlInvalidTime);
|
||||
|
||||
// 3. Let y be TimeClip(y).
|
||||
end = time_clip(global_object, end);
|
||||
end = time_clip(end);
|
||||
|
||||
// 4. If y is NaN, throw a RangeError exception.
|
||||
if (end.is_nan())
|
||||
if (isnan(end))
|
||||
return vm.throw_completion<RangeError>(global_object, ErrorType::IntlInvalidTime);
|
||||
|
||||
// 5. If x is greater than y, throw a RangeError exception.
|
||||
if (start.as_double() > end.as_double())
|
||||
if (start > end)
|
||||
return vm.throw_completion<RangeError>(global_object, ErrorType::IntlStartTimeAfterEndTime, start, end);
|
||||
|
||||
// 6. Let tm1 be ToLocalTime(x, dateTimeFormat.[[Calendar]], dateTimeFormat.[[TimeZone]]).
|
||||
auto start_local_time = TRY(to_local_time(global_object, start.as_double(), date_time_format.calendar(), date_time_format.time_zone()));
|
||||
auto start_local_time = TRY(to_local_time(global_object, start, date_time_format.calendar(), date_time_format.time_zone()));
|
||||
|
||||
// 7. Let tm2 be ToLocalTime(y, dateTimeFormat.[[Calendar]], dateTimeFormat.[[TimeZone]]).
|
||||
auto end_local_time = TRY(to_local_time(global_object, end.as_double(), date_time_format.calendar(), date_time_format.time_zone()));
|
||||
auto end_local_time = TRY(to_local_time(global_object, end, date_time_format.calendar(), date_time_format.time_zone()));
|
||||
|
||||
// 8. Let rangePatterns be dateTimeFormat.[[RangePatterns]].
|
||||
auto range_patterns = date_time_format.range_patterns();
|
||||
|
@ -1121,7 +1121,7 @@ ThrowCompletionOr<Vector<PatternPartitionWithSource>> partition_date_time_range_
|
|||
}
|
||||
|
||||
// 11.5.11 FormatDateTimeRange ( dateTimeFormat, x, y ), https://tc39.es/ecma402/#sec-formatdatetimerange
|
||||
ThrowCompletionOr<String> format_date_time_range(GlobalObject& global_object, DateTimeFormat& date_time_format, Value start, Value end)
|
||||
ThrowCompletionOr<String> format_date_time_range(GlobalObject& global_object, DateTimeFormat& date_time_format, double start, double end)
|
||||
{
|
||||
// 1. Let parts be ? PartitionDateTimeRangePattern(dateTimeFormat, x, y).
|
||||
auto parts = TRY(partition_date_time_range_pattern(global_object, date_time_format, start, end));
|
||||
|
@ -1140,7 +1140,7 @@ ThrowCompletionOr<String> format_date_time_range(GlobalObject& global_object, Da
|
|||
}
|
||||
|
||||
// 11.5.12 FormatDateTimeRangeToParts ( dateTimeFormat, x, y ), https://tc39.es/ecma402/#sec-formatdatetimerangetoparts
|
||||
ThrowCompletionOr<Array*> format_date_time_range_to_parts(GlobalObject& global_object, DateTimeFormat& date_time_format, Value start, Value end)
|
||||
ThrowCompletionOr<Array*> format_date_time_range_to_parts(GlobalObject& global_object, DateTimeFormat& date_time_format, double start, double end)
|
||||
{
|
||||
auto& vm = global_object.vm();
|
||||
|
||||
|
|
|
@ -203,13 +203,13 @@ ThrowCompletionOr<Object*> to_date_time_options(GlobalObject& global_object, Val
|
|||
Optional<Unicode::CalendarPattern> date_time_style_format(StringView data_locale, DateTimeFormat& date_time_format);
|
||||
Optional<Unicode::CalendarPattern> basic_format_matcher(Unicode::CalendarPattern const& options, Vector<Unicode::CalendarPattern> formats);
|
||||
Optional<Unicode::CalendarPattern> best_fit_format_matcher(Unicode::CalendarPattern const& options, Vector<Unicode::CalendarPattern> formats);
|
||||
ThrowCompletionOr<Vector<PatternPartition>> format_date_time_pattern(GlobalObject& global_object, DateTimeFormat& date_time_format, Vector<PatternPartition> pattern_parts, Value time, Unicode::CalendarPattern const* range_format_options);
|
||||
ThrowCompletionOr<Vector<PatternPartition>> partition_date_time_pattern(GlobalObject& global_object, DateTimeFormat& date_time_format, Value time);
|
||||
ThrowCompletionOr<String> format_date_time(GlobalObject& global_object, DateTimeFormat& date_time_format, Value time);
|
||||
ThrowCompletionOr<Array*> format_date_time_to_parts(GlobalObject& global_object, DateTimeFormat& date_time_format, Value time);
|
||||
ThrowCompletionOr<Vector<PatternPartitionWithSource>> partition_date_time_range_pattern(GlobalObject& global_object, DateTimeFormat& date_time_format, Value start, Value end);
|
||||
ThrowCompletionOr<String> format_date_time_range(GlobalObject& global_object, DateTimeFormat& date_time_format, Value start, Value end);
|
||||
ThrowCompletionOr<Array*> format_date_time_range_to_parts(GlobalObject& global_object, DateTimeFormat& date_time_format, Value start, Value end);
|
||||
ThrowCompletionOr<Vector<PatternPartition>> format_date_time_pattern(GlobalObject& global_object, DateTimeFormat& date_time_format, Vector<PatternPartition> pattern_parts, double time, Unicode::CalendarPattern const* range_format_options);
|
||||
ThrowCompletionOr<Vector<PatternPartition>> partition_date_time_pattern(GlobalObject& global_object, DateTimeFormat& date_time_format, double time);
|
||||
ThrowCompletionOr<String> format_date_time(GlobalObject& global_object, DateTimeFormat& date_time_format, double time);
|
||||
ThrowCompletionOr<Array*> format_date_time_to_parts(GlobalObject& global_object, DateTimeFormat& date_time_format, double time);
|
||||
ThrowCompletionOr<Vector<PatternPartitionWithSource>> partition_date_time_range_pattern(GlobalObject& global_object, DateTimeFormat& date_time_format, double start, double end);
|
||||
ThrowCompletionOr<String> format_date_time_range(GlobalObject& global_object, DateTimeFormat& date_time_format, double start, double end);
|
||||
ThrowCompletionOr<Array*> format_date_time_range_to_parts(GlobalObject& global_object, DateTimeFormat& date_time_format, double start, double end);
|
||||
ThrowCompletionOr<LocalTime> to_local_time(GlobalObject& global_object, double time, StringView calendar, StringView time_zone);
|
||||
|
||||
template<typename Callback>
|
||||
|
|
|
@ -44,19 +44,21 @@ ThrowCompletionOr<Value> DateTimeFormatFunction::call()
|
|||
// 1. Let dtf be F.[[DateTimeFormat]].
|
||||
// 2. Assert: Type(dtf) is Object and dtf has an [[InitializedDateTimeFormat]] internal slot.
|
||||
|
||||
double date_value;
|
||||
|
||||
// 3. If date is not provided or is undefined, then
|
||||
if (date.is_undefined()) {
|
||||
// a. Let x be ! Call(%Date.now%, undefined).
|
||||
date = MUST(JS::call(global_object, global_object.date_constructor_now_function(), js_undefined()));
|
||||
date_value = MUST(JS::call(global_object, global_object.date_constructor_now_function(), js_undefined())).as_double();
|
||||
}
|
||||
// 4. Else,
|
||||
else {
|
||||
// a. Let x be ? ToNumber(date).
|
||||
date = TRY(date.to_number(global_object));
|
||||
date_value = TRY(date.to_number(global_object)).as_double();
|
||||
}
|
||||
|
||||
// 5. Return ? FormatDateTime(dtf, x).
|
||||
auto formatted = TRY(format_date_time(global_object, m_date_time_format, date));
|
||||
auto formatted = TRY(format_date_time(global_object, m_date_time_format, date_value));
|
||||
return js_string(vm, move(formatted));
|
||||
}
|
||||
|
||||
|
|
|
@ -69,19 +69,21 @@ JS_DEFINE_NATIVE_FUNCTION(DateTimeFormatPrototype::format_to_parts)
|
|||
// 2. Perform ? RequireInternalSlot(dtf, [[InitializedDateTimeFormat]]).
|
||||
auto* date_time_format = TRY(typed_this_object(global_object));
|
||||
|
||||
double date_value;
|
||||
|
||||
// 3. If date is undefined, then
|
||||
if (date.is_undefined()) {
|
||||
// a. Let x be ! Call(%Date.now%, undefined).
|
||||
date = MUST(call(global_object, global_object.date_constructor_now_function(), js_undefined()));
|
||||
date_value = MUST(call(global_object, global_object.date_constructor_now_function(), js_undefined())).as_double();
|
||||
}
|
||||
// 4. Else,
|
||||
else {
|
||||
// a. Let x be ? ToNumber(date).
|
||||
date = TRY(date.to_number(global_object));
|
||||
date_value = TRY(date.to_number(global_object)).as_double();
|
||||
}
|
||||
|
||||
// 5. Return ? FormatDateTimeToParts(dtf, x).
|
||||
return TRY(format_date_time_to_parts(global_object, *date_time_format, date));
|
||||
return TRY(format_date_time_to_parts(global_object, *date_time_format, date_value));
|
||||
}
|
||||
|
||||
// 11.3.5 Intl.DateTimeFormat.prototype.formatRange ( startDate, endDate ), https://tc39.es/ecma402/#sec-intl.datetimeformat.prototype.formatRange
|
||||
|
@ -101,13 +103,13 @@ JS_DEFINE_NATIVE_FUNCTION(DateTimeFormatPrototype::format_range)
|
|||
return vm.throw_completion<TypeError>(global_object, ErrorType::IsUndefined, "endDate"sv);
|
||||
|
||||
// 4. Let x be ? ToNumber(startDate).
|
||||
start_date = TRY(start_date.to_number(global_object));
|
||||
auto start_date_number = TRY(start_date.to_number(global_object)).as_double();
|
||||
|
||||
// 5. Let y be ? ToNumber(endDate).
|
||||
end_date = TRY(end_date.to_number(global_object));
|
||||
auto end_date_number = TRY(end_date.to_number(global_object)).as_double();
|
||||
|
||||
// 6. Return ? FormatDateTimeRange(dtf, x, y).
|
||||
auto formatted = TRY(format_date_time_range(global_object, *date_time_format, start_date, end_date));
|
||||
auto formatted = TRY(format_date_time_range(global_object, *date_time_format, start_date_number, end_date_number));
|
||||
return js_string(vm, move(formatted));
|
||||
}
|
||||
|
||||
|
@ -128,13 +130,13 @@ JS_DEFINE_NATIVE_FUNCTION(DateTimeFormatPrototype::format_range_to_parts)
|
|||
return vm.throw_completion<TypeError>(global_object, ErrorType::IsUndefined, "endDate"sv);
|
||||
|
||||
// 4. Let x be ? ToNumber(startDate).
|
||||
start_date = TRY(start_date.to_number(global_object));
|
||||
auto start_date_number = TRY(start_date.to_number(global_object)).as_double();
|
||||
|
||||
// 5. Let y be ? ToNumber(endDate).
|
||||
end_date = TRY(end_date.to_number(global_object));
|
||||
auto end_date_number = TRY(end_date.to_number(global_object)).as_double();
|
||||
|
||||
// 6. Return ? FormatDateTimeRangeToParts(dtf, x, y).
|
||||
return TRY(format_date_time_range_to_parts(global_object, *date_time_format, start_date, end_date));
|
||||
return TRY(format_date_time_range_to_parts(global_object, *date_time_format, start_date_number, end_date_number));
|
||||
}
|
||||
|
||||
// 11.3.7 Intl.DateTimeFormat.prototype.resolvedOptions ( ), https://tc39.es/ecma402/#sec-intl.datetimeformat.prototype.resolvedoptions
|
||||
|
|
|
@ -53,19 +53,19 @@ BigInt* get_epoch_from_iso_parts(GlobalObject& global_object, i32 year, u8 month
|
|||
VERIFY(is_valid_iso_date(year, month, day));
|
||||
|
||||
// 2. Let date be MakeDay(𝔽(year), 𝔽(month - 1), 𝔽(day)).
|
||||
auto date = make_day(global_object, Value(year), Value(month - 1), Value(day));
|
||||
auto date = make_day(year, month - 1, day);
|
||||
|
||||
// 3. Let time be MakeTime(𝔽(hour), 𝔽(minute), 𝔽(second), 𝔽(millisecond)).
|
||||
auto time = make_time(global_object, Value(hour), Value(minute), Value(second), Value(millisecond));
|
||||
auto time = make_time(hour, minute, second, millisecond);
|
||||
|
||||
// 4. Let ms be MakeDate(date, time).
|
||||
auto ms = make_date(date, time);
|
||||
|
||||
// 5. Assert: ms is finite.
|
||||
VERIFY(ms.is_finite_number());
|
||||
VERIFY(isfinite(ms));
|
||||
|
||||
// 6. Return ℤ(ℝ(ms) × 10^6 + microsecond × 10^3 + nanosecond).
|
||||
return js_bigint(vm, Crypto::SignedBigInteger::create_from(static_cast<i64>(ms.as_double())).multiplied_by(Crypto::UnsignedBigInteger { 1'000'000 }).plus(Crypto::SignedBigInteger::create_from((i64)microsecond * 1000)).plus(Crypto::SignedBigInteger(nanosecond)));
|
||||
return js_bigint(vm, Crypto::SignedBigInteger::create_from(static_cast<i64>(ms)).multiplied_by(Crypto::UnsignedBigInteger { 1'000'000 }).plus(Crypto::SignedBigInteger::create_from((i64)microsecond * 1000)).plus(Crypto::SignedBigInteger(nanosecond)));
|
||||
}
|
||||
|
||||
// -864 * 10^19 - 864 * 10^11
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue