/
githubmirror
/
node
Обзор
Документация
Войти
/
githubmirror
/
node
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
deps/v8/src/builtins/builtins-date.cc
949 строк
38 KB
Michaël Zasso
deps: update V8 to 14.1.146.11
04 окт 2025, 19:47
Не верифицирован
04 окт 2025, 19:47
7772a2d
Код
Авторство
О чём код?
// Copyright 2016 the V8 project authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "src/builtins/builtins-utils-inl.h" #include "src/builtins/builtins.h" #include "src/codegen/code-factory.h" #include "src/date/date.h" #include "src/date/dateparser-inl.h" #include "src/logging/counters.h" #include "src/numbers/conversions.h" #include "src/objects/bigint.h" #ifdef V8_INTL_SUPPORT #include "src/objects/intl-objects.h" #include "src/objects/js-date-time-format.h" #endif #ifdef V8_TEMPORAL_SUPPORT #include "src/objects/js-temporal-objects-inl.h" #endif // V8_TEMPORAL_SUPPORT #include "src/objects/objects-inl.h" #include "src/strings/string-stream.h" namespace v8 { namespace internal { // ----------------------------------------------------------------------------- // ES6 section 20.3 Date Objects namespace { Tagged<Object> SetLocalDateValue(Isolate* isolate, DirectHandle<JSDate> date, double time_val) { if (time_val >= -DateCache::kMaxTimeBeforeUTCInMs && time_val <= DateCache::kMaxTimeBeforeUTCInMs) { time_val = isolate->date_cache()->ToUTC(static_cast<int64_t>(time_val)); if (DateCache::TryTimeClip(&time_val)) { date->SetValue(isolate, time_val); return *isolate->factory()->NewNumber(time_val); } } date->SetNanValue(); return ReadOnlyRoots(isolate).nan_value(); } Tagged<Object> SetDateValue(Isolate* isolate, DirectHandle<JSDate> date, double time_val) { if (DateCache::TryTimeClip(&time_val)) { date->SetValue(isolate, time_val); return *isolate->factory()->NewNumber(time_val); } date->SetNanValue(); return ReadOnlyRoots(isolate).nan_value(); } } // namespace // ES #sec-date-constructor BUILTIN(DateConstructor) { HandleScope scope(isolate); if (IsUndefined(*args.new_target(), isolate)) { double const time_val = static_cast<double>(JSDate::CurrentTimeValue(isolate)); DateBuffer buffer = ToDateString(time_val, isolate->date_cache(), ToDateStringMode::kLocalDateAndTime); RETURN_RESULT_OR_FAILURE( isolate, isolate->factory()->NewStringFromUtf8(base::VectorOf(buffer))); } // [Construct] int const argc = args.length() - 1; DirectHandle<JSFunction> target = args.target(); DirectHandle<JSReceiver> new_target = Cast<JSReceiver>(args.new_target()); double time_val; if (argc == 0) { time_val = static_cast<double>(JSDate::CurrentTimeValue(isolate)); } else if (argc == 1) { DirectHandle<Object> value = args.at(1); if (IsJSDate(*value)) { time_val = Cast<JSDate>(value)->value(); } else { ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, value, Object::ToPrimitive(isolate, value)); if (IsString(*value)) { time_val = ParseDateTimeString(isolate, Cast<String>(value)); } else { ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, value, Object::ToNumber(isolate, value)); time_val = Object::NumberValue(*value); } } } else { DirectHandle<Object> year_object; ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, year_object, Object::ToNumber(isolate, args.at(1))); DirectHandle<Object> month_object; ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, month_object, Object::ToNumber(isolate, args.at(2))); double year = Object::NumberValue(*year_object); double month = Object::NumberValue(*month_object); double date = 1.0, hours = 0.0, minutes = 0.0, seconds = 0.0, ms = 0.0; if (argc >= 3) { DirectHandle<Object> date_object; ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, date_object, Object::ToNumber(isolate, args.at(3))); date = Object::NumberValue(*date_object); if (argc >= 4) { DirectHandle<Object> hours_object; ASSIGN_RETURN_FAILURE_ON_EXCEPTION( isolate, hours_object, Object::ToNumber(isolate, args.at(4))); hours = Object::NumberValue(*hours_object); if (argc >= 5) { DirectHandle<Object> minutes_object; ASSIGN_RETURN_FAILURE_ON_EXCEPTION( isolate, minutes_object, Object::ToNumber(isolate, args.at(5))); minutes = Object::NumberValue(*minutes_object); if (argc >= 6) { DirectHandle<Object> seconds_object; ASSIGN_RETURN_FAILURE_ON_EXCEPTION( isolate, seconds_object, Object::ToNumber(isolate, args.at(6))); seconds = Object::NumberValue(*seconds_object); if (argc >= 7) { DirectHandle<Object> ms_object; ASSIGN_RETURN_FAILURE_ON_EXCEPTION( isolate, ms_object, Object::ToNumber(isolate, args.at(7))); ms = Object::NumberValue(*ms_object); } } } } } if (!std::isnan(year)) { double const y = DoubleToInteger(year); if (0.0 <= y && y <= 99) year = 1900 + y; } double const day = MakeDay(year, month, date); double const time = MakeTime(hours, minutes, seconds, ms); time_val = MakeDate(day, time); if (time_val >= -DateCache::kMaxTimeBeforeUTCInMs && time_val <= DateCache::kMaxTimeBeforeUTCInMs) { time_val = isolate->date_cache()->ToUTC(static_cast<int64_t>(time_val)); } else { time_val = std::numeric_limits<double>::quiet_NaN(); } } RETURN_RESULT_OR_FAILURE(isolate, JSDate::New(isolate, target, new_target, time_val)); } // ES6 section 20.3.3.1 Date.now ( ) BUILTIN(DateNow) { HandleScope scope(isolate); return *isolate->factory()->NewNumberFromInt64( JSDate::CurrentTimeValue(isolate)); } // ES6 section 20.3.3.2 Date.parse ( string ) BUILTIN(DateParse) { HandleScope scope(isolate); DirectHandle<String> string; ASSIGN_RETURN_FAILURE_ON_EXCEPTION( isolate, string, Object::ToString(isolate, args.atOrUndefined(isolate, 1))); return *isolate->factory()->NewNumber(ParseDateTimeString(isolate, string)); } // ES6 section 20.3.3.4 Date.UTC (year,month,date,hours,minutes,seconds,ms) BUILTIN(DateUTC) { HandleScope scope(isolate); int const argc = args.length() - 1; double year = std::numeric_limits<double>::quiet_NaN(); double month = 0.0, date = 1.0, hours = 0.0, minutes = 0.0, seconds = 0.0, ms = 0.0; if (argc >= 1) { DirectHandle<Object> year_object; ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, year_object, Object::ToNumber(isolate, args.at(1))); year = Object::NumberValue(*year_object); if (argc >= 2) { DirectHandle<Object> month_object; ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, month_object, Object::ToNumber(isolate, args.at(2))); month = Object::NumberValue(*month_object); if (argc >= 3) { DirectHandle<Object> date_object; ASSIGN_RETURN_FAILURE_ON_EXCEPTION( isolate, date_object, Object::ToNumber(isolate, args.at(3))); date = Object::NumberValue(*date_object); if (argc >= 4) { DirectHandle<Object> hours_object; ASSIGN_RETURN_FAILURE_ON_EXCEPTION( isolate, hours_object, Object::ToNumber(isolate, args.at(4))); hours = Object::NumberValue(*hours_object); if (argc >= 5) { DirectHandle<Object> minutes_object; ASSIGN_RETURN_FAILURE_ON_EXCEPTION( isolate, minutes_object, Object::ToNumber(isolate, args.at(5))); minutes = Object::NumberValue(*minutes_object); if (argc >= 6) { DirectHandle<Object> seconds_object; ASSIGN_RETURN_FAILURE_ON_EXCEPTION( isolate, seconds_object, Object::ToNumber(isolate, args.at(6))); seconds = Object::NumberValue(*seconds_object); if (argc >= 7) { DirectHandle<Object> ms_object; ASSIGN_RETURN_FAILURE_ON_EXCEPTION( isolate, ms_object, Object::ToNumber(isolate, args.at(7))); ms = Object::NumberValue(*ms_object); } } } } } } } if (!std::isnan(year)) { double const y = DoubleToInteger(year); if (0.0 <= y && y <= 99) year = 1900 + y; } double const day = MakeDay(year, month, date); double const time = MakeTime(hours, minutes, seconds, ms); double value = MakeDate(day, time); if (DateCache::TryTimeClip(&value)) { return *isolate->factory()->NewNumber(value); } return ReadOnlyRoots(isolate).nan_value(); } // ES6 section 20.3.4.20 Date.prototype.setDate ( date ) BUILTIN(DatePrototypeSetDate) { HandleScope scope(isolate); CHECK_RECEIVER(JSDate, date, "Date.prototype.setDate"); DirectHandle<Object> value = args.atOrUndefined(isolate, 1); double time_val = date->value(); ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, value, Object::ToNumber(isolate, value)); if (std::isnan(time_val)) { return ReadOnlyRoots(isolate).nan_value(); } int64_t const time_ms = static_cast<int64_t>(time_val); int64_t local_time_ms = isolate->date_cache()->ToLocal(time_ms); int const days = isolate->date_cache()->DaysFromTime(local_time_ms); int time_within_day = isolate->date_cache()->TimeInDay(local_time_ms, days); int year, month, day; isolate->date_cache()->YearMonthDayFromDays(days, &year, &month, &day); time_val = MakeDate(MakeDay(year, month, Object::NumberValue(*value)), time_within_day); return SetLocalDateValue(isolate, date, time_val); } // ES6 section 20.3.4.21 Date.prototype.setFullYear (year, month, date) BUILTIN(DatePrototypeSetFullYear) { HandleScope scope(isolate); CHECK_RECEIVER(JSDate, date, "Date.prototype.setFullYear"); int const argc = args.length() - 1; DirectHandle<Object> year = args.atOrUndefined(isolate, 1); ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, year, Object::ToNumber(isolate, year)); double year_double = Object::NumberValue(*year), month_double = 0.0, day_double = 1.0; int time_within_day = 0; if (!std::isnan(date->value())) { int64_t const time_ms = static_cast<int64_t>(date->value()); int64_t local_time_ms = isolate->date_cache()->ToLocal(time_ms); int const days = isolate->date_cache()->DaysFromTime(local_time_ms); time_within_day = isolate->date_cache()->TimeInDay(local_time_ms, days); int year_int, month_int, day_int; isolate->date_cache()->YearMonthDayFromDays(days, &year_int, &month_int, &day_int); month_double = month_int; day_double = day_int; } if (argc >= 2) { DirectHandle<Object> month = args.at(2); ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, month, Object::ToNumber(isolate, month)); month_double = Object::NumberValue(*month); if (argc >= 3) { DirectHandle<Object> day = args.at(3); ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, day, Object::ToNumber(isolate, day)); day_double = Object::NumberValue(*day); } } double time_val = MakeDate(MakeDay(year_double, month_double, day_double), time_within_day); return SetLocalDateValue(isolate, date, time_val); } // ES6 section 20.3.4.22 Date.prototype.setHours(hour, min, sec, ms) BUILTIN(DatePrototypeSetHours) { HandleScope scope(isolate); CHECK_RECEIVER(JSDate, date, "Date.prototype.setHours"); int const argc = args.length() - 1; DirectHandle<Object> hour = args.atOrUndefined(isolate, 1); double time_val = date->value(); ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, hour, Object::ToNumber(isolate, hour)); double const h = Object::NumberValue(*hour); std::optional<double> m; std::optional<double> s; std::optional<double> milli; if (argc >= 2) { DirectHandle<Object> min = args.at(2); ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, min, Object::ToNumber(isolate, min)); m = Object::NumberValue(*min); if (argc >= 3) { DirectHandle<Object> sec = args.at(3); ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, sec, Object::ToNumber(isolate, sec)); s = Object::NumberValue(*sec); if (argc >= 4) { DirectHandle<Object> ms = args.at(4); ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, ms, Object::ToNumber(isolate, ms)); milli = Object::NumberValue(*ms); } } } if (std::isnan(time_val)) { return ReadOnlyRoots(isolate).nan_value(); } int64_t const time_ms = static_cast<int64_t>(time_val); int64_t const local_time_ms = isolate->date_cache()->ToLocal(time_ms); int const day = isolate->date_cache()->DaysFromTime(local_time_ms); int const time_within_day = isolate->date_cache()->TimeInDay(local_time_ms, day); time_val = MakeDate( day, MakeTime(h, m.value_or((time_within_day / (60 * 1000)) % 60), s.value_or((time_within_day / 1000) % 60), milli.value_or(time_within_day % 1000))); return SetLocalDateValue(isolate, date, time_val); } // ES6 section 20.3.4.23 Date.prototype.setMilliseconds(ms) BUILTIN(DatePrototypeSetMilliseconds) { HandleScope scope(isolate); CHECK_RECEIVER(JSDate, date, "Date.prototype.setMilliseconds"); DirectHandle<Object> ms = args.atOrUndefined(isolate, 1); double time_val = date->value(); ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, ms, Object::ToNumber(isolate, ms)); if (std::isnan(time_val)) { return ReadOnlyRoots(isolate).nan_value(); } int64_t const time_ms = static_cast<int64_t>(time_val); int64_t const local_time_ms = isolate->date_cache()->ToLocal(time_ms); int const day = isolate->date_cache()->DaysFromTime(local_time_ms); int const time_within_day = isolate->date_cache()->TimeInDay(local_time_ms, day); int const h = time_within_day / (60 * 60 * 1000); int const m = (time_within_day / (60 * 1000)) % 60; int const s = (time_within_day / 1000) % 60; time_val = MakeDate(day, MakeTime(h, m, s, Object::NumberValue(*ms))); return SetLocalDateValue(isolate, date, time_val); } // ES6 section 20.3.4.24 Date.prototype.setMinutes ( min, sec, ms ) BUILTIN(DatePrototypeSetMinutes) { HandleScope scope(isolate); CHECK_RECEIVER(JSDate, date, "Date.prototype.setMinutes"); int const argc = args.length() - 1; DirectHandle<Object> min = args.atOrUndefined(isolate, 1); double time_val = date->value(); ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, min, Object::ToNumber(isolate, min)); std::optional<double> s; std::optional<double> milli; if (argc >= 2) { DirectHandle<Object> sec = args.at(2); ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, sec, Object::ToNumber(isolate, sec)); s = Object::NumberValue(*sec); if (argc >= 3) { DirectHandle<Object> ms = args.at(3); ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, ms, Object::ToNumber(isolate, ms)); milli = Object::NumberValue(*ms); } } if (std::isnan(time_val)) { return ReadOnlyRoots(isolate).nan_value(); } int64_t const time_ms = static_cast<int64_t>(time_val); int64_t const local_time_ms = isolate->date_cache()->ToLocal(time_ms); int const day = isolate->date_cache()->DaysFromTime(local_time_ms); int const time_within_day = isolate->date_cache()->TimeInDay(local_time_ms, day); int const h = time_within_day / (60 * 60 * 1000); double const m = Object::NumberValue(*min); time_val = MakeDate(day, MakeTime(h, m, s.value_or((time_within_day / 1000) % 60), milli.value_or(time_within_day % 1000))); return SetLocalDateValue(isolate, date, time_val); } // ES6 section 20.3.4.25 Date.prototype.setMonth ( month, date ) BUILTIN(DatePrototypeSetMonth) { HandleScope scope(isolate); CHECK_RECEIVER(JSDate, this_date, "Date.prototype.setMonth"); int const argc = args.length() - 1; DirectHandle<Object> month = args.atOrUndefined(isolate, 1); double time_val = this_date->value(); ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, month, Object::ToNumber(isolate, month)); std::optional<double> dt; if (argc >= 2) { DirectHandle<Object> date = args.at(2); ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, date, Object::ToNumber(isolate, date)); dt = Object::NumberValue(*date); } if (std::isnan(time_val)) { return ReadOnlyRoots(isolate).nan_value(); } int64_t const time_ms = static_cast<int64_t>(time_val); int64_t const local_time_ms = isolate->date_cache()->ToLocal(time_ms); int const days = isolate->date_cache()->DaysFromTime(local_time_ms); int const time_within_day = isolate->date_cache()->TimeInDay(local_time_ms, days); int year, unused, day; isolate->date_cache()->YearMonthDayFromDays(days, &year, &unused, &day); double const m = Object::NumberValue(*month); time_val = MakeDate(MakeDay(year, m, dt.value_or(day)), time_within_day); return SetLocalDateValue(isolate, this_date, time_val); } // ES6 section 20.3.4.26 Date.prototype.setSeconds ( sec, ms ) BUILTIN(DatePrototypeSetSeconds) { HandleScope scope(isolate); CHECK_RECEIVER(JSDate, date, "Date.prototype.setSeconds"); int const argc = args.length() - 1; DirectHandle<Object> sec = args.atOrUndefined(isolate, 1); double time_val = date->value(); ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, sec, Object::ToNumber(isolate, sec)); std::optional<double> milli; if (argc >= 2) { DirectHandle<Object> ms = args.at(2); ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, ms, Object::ToNumber(isolate, ms)); milli = Object::NumberValue(*ms); } if (std::isnan(time_val)) { return ReadOnlyRoots(isolate).nan_value(); } int64_t const time_ms = static_cast<int64_t>(time_val); int64_t const local_time_ms = isolate->date_cache()->ToLocal(time_ms); int const day = isolate->date_cache()->DaysFromTime(local_time_ms); int const time_within_day = isolate->date_cache()->TimeInDay(local_time_ms, day); int const h = time_within_day / (60 * 60 * 1000); double const m = (time_within_day / (60 * 1000)) % 60; double const s = Object::NumberValue(*sec); time_val = MakeDate(day, MakeTime(h, m, s, milli.value_or(time_within_day % 1000))); return SetLocalDateValue(isolate, date, time_val); } // ES6 section 20.3.4.27 Date.prototype.setTime ( time ) BUILTIN(DatePrototypeSetTime) { HandleScope scope(isolate); CHECK_RECEIVER(JSDate, date, "Date.prototype.setTime"); DirectHandle<Object> value = args.atOrUndefined(isolate, 1); ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, value, Object::ToNumber(isolate, value)); double value_double = Object::NumberValue(*value); // Don't use SetDateValue here, since we might already have a tagged value for // the time, and we don't want to reallocate it. double clipped_value = value_double; if (DateCache::TryTimeClip(&clipped_value)) { date->SetValue(isolate, clipped_value); // If the clipping didn't change the value (i.e. the value was already an // integer), we can reuse the incoming value for the return value. // Otherwise, we have to allocate a new value. Make sure to use // SameNumberValue so that -0 is _not_ treated as equal to the 0. if (Object::SameNumberValue(clipped_value, value_double)) { return *value; } return *isolate->factory()->NewNumber(clipped_value); } date->SetNanValue(); return ReadOnlyRoots(isolate).nan_value(); } // ES6 section 20.3.4.28 Date.prototype.setUTCDate ( date ) BUILTIN(DatePrototypeSetUTCDate) { HandleScope scope(isolate); CHECK_RECEIVER(JSDate, date, "Date.prototype.setUTCDate"); DirectHandle<Object> value = args.atOrUndefined(isolate, 1); double time_val = date->value(); ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, value, Object::ToNumber(isolate, value)); if (std::isnan(time_val)) { return ReadOnlyRoots(isolate).nan_value(); } int64_t const time_ms = static_cast<int64_t>(time_val); int const days = isolate->date_cache()->DaysFromTime(time_ms); int const time_within_day = isolate->date_cache()->TimeInDay(time_ms, days); int year, month, day; isolate->date_cache()->YearMonthDayFromDays(days, &year, &month, &day); time_val = MakeDate(MakeDay(year, month, Object::NumberValue(*value)), time_within_day); return SetDateValue(isolate, date, time_val); } // ES6 section 20.3.4.29 Date.prototype.setUTCFullYear (year, month, date) BUILTIN(DatePrototypeSetUTCFullYear) { HandleScope scope(isolate); CHECK_RECEIVER(JSDate, date, "Date.prototype.setUTCFullYear"); int const argc = args.length() - 1; DirectHandle<Object> year = args.atOrUndefined(isolate, 1); ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, year, Object::ToNumber(isolate, year)); double year_double = Object::NumberValue(*year), month_double = 0.0, day_double = 1.0; int time_within_day = 0; if (!std::isnan(date->value())) { int64_t const time_ms = static_cast<int64_t>(date->value()); int const days = isolate->date_cache()->DaysFromTime(time_ms); time_within_day = isolate->date_cache()->TimeInDay(time_ms, days); int year_int, month_int, day_int; isolate->date_cache()->YearMonthDayFromDays(days, &year_int, &month_int, &day_int); month_double = month_int; day_double = day_int; } if (argc >= 2) { DirectHandle<Object> month = args.at(2); ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, month, Object::ToNumber(isolate, month)); month_double = Object::NumberValue(*month); if (argc >= 3) { DirectHandle<Object> day = args.at(3); ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, day, Object::ToNumber(isolate, day)); day_double = Object::NumberValue(*day); } } double const time_val = MakeDate(MakeDay(year_double, month_double, day_double), time_within_day); return SetDateValue(isolate, date, time_val); } // ES6 section 20.3.4.30 Date.prototype.setUTCHours(hour, min, sec, ms) BUILTIN(DatePrototypeSetUTCHours) { HandleScope scope(isolate); CHECK_RECEIVER(JSDate, date, "Date.prototype.setUTCHours"); int const argc = args.length() - 1; DirectHandle<Object> hour = args.atOrUndefined(isolate, 1); double time_val = date->value(); ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, hour, Object::ToNumber(isolate, hour)); double const h = Object::NumberValue(*hour); std::optional<double> m; std::optional<double> s; std::optional<double> milli; if (argc >= 2) { DirectHandle<Object> min = args.at(2); ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, min, Object::ToNumber(isolate, min)); m = Object::NumberValue(*min); if (argc >= 3) { DirectHandle<Object> sec = args.at(3); ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, sec, Object::ToNumber(isolate, sec)); s = Object::NumberValue(*sec); if (argc >= 4) { DirectHandle<Object> ms = args.at(4); ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, ms, Object::ToNumber(isolate, ms)); milli = Object::NumberValue(*ms); } } } if (std::isnan(time_val)) { return ReadOnlyRoots(isolate).nan_value(); } int64_t const time_ms = static_cast<int64_t>(time_val); int const day = isolate->date_cache()->DaysFromTime(time_ms); int const time_within_day = isolate->date_cache()->TimeInDay(time_ms, day); time_val = MakeDate( day, MakeTime(h, m.value_or((time_within_day / (60 * 1000)) % 60), s.value_or((time_within_day / 1000) % 60), milli.value_or(time_within_day % 1000))); return SetDateValue(isolate, date, time_val); } // ES6 section 20.3.4.31 Date.prototype.setUTCMilliseconds(ms) BUILTIN(DatePrototypeSetUTCMilliseconds) { HandleScope scope(isolate); CHECK_RECEIVER(JSDate, date, "Date.prototype.setUTCMilliseconds"); DirectHandle<Object> ms = args.atOrUndefined(isolate, 1); double time_val = date->value(); ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, ms, Object::ToNumber(isolate, ms)); if (std::isnan(time_val)) { return ReadOnlyRoots(isolate).nan_value(); } int64_t const time_ms = static_cast<int64_t>(time_val); int const day = isolate->date_cache()->DaysFromTime(time_ms); int const time_within_day = isolate->date_cache()->TimeInDay(time_ms, day); int const h = time_within_day / (60 * 60 * 1000); int const m = (time_within_day / (60 * 1000)) % 60; int const s = (time_within_day / 1000) % 60; time_val = MakeDate(day, MakeTime(h, m, s, Object::NumberValue(*ms))); return SetDateValue(isolate, date, time_val); } // ES6 section 20.3.4.32 Date.prototype.setUTCMinutes ( min, sec, ms ) BUILTIN(DatePrototypeSetUTCMinutes) { HandleScope scope(isolate); CHECK_RECEIVER(JSDate, date, "Date.prototype.setUTCMinutes"); int const argc = args.length() - 1; DirectHandle<Object> min = args.atOrUndefined(isolate, 1); double time_val = date->value(); ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, min, Object::ToNumber(isolate, min)); std::optional<double> s; std::optional<double> milli; if (argc >= 2) { DirectHandle<Object> sec = args.at(2); ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, sec, Object::ToNumber(isolate, sec)); s = Object::NumberValue(*sec); if (argc >= 3) { DirectHandle<Object> ms = args.at(3); ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, ms, Object::ToNumber(isolate, ms)); milli = Object::NumberValue(*ms); } } if (std::isnan(time_val)) { return ReadOnlyRoots(isolate).nan_value(); } int64_t const time_ms = static_cast<int64_t>(time_val); int const day = isolate->date_cache()->DaysFromTime(time_ms); int const time_within_day = isolate->date_cache()->TimeInDay(time_ms, day); int const h = time_within_day / (60 * 60 * 1000); double const m = Object::NumberValue(*min); time_val = MakeDate(day, MakeTime(h, m, s.value_or((time_within_day / 1000) % 60), milli.value_or(time_within_day % 1000))); return SetDateValue(isolate, date, time_val); } // ES6 section 20.3.4.31 Date.prototype.setUTCMonth ( month, date ) BUILTIN(DatePrototypeSetUTCMonth) { HandleScope scope(isolate); CHECK_RECEIVER(JSDate, this_date, "Date.prototype.setUTCMonth"); int const argc = args.length() - 1; DirectHandle<Object> month = args.atOrUndefined(isolate, 1); double time_val = this_date->value(); ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, month, Object::ToNumber(isolate, month)); std::optional<double> dt; if (argc >= 2) { DirectHandle<Object> date = args.at(2); ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, date, Object::ToNumber(isolate, date)); dt = Object::NumberValue(*date); } if (std::isnan(time_val)) { return ReadOnlyRoots(isolate).nan_value(); } int64_t const time_ms = static_cast<int64_t>(time_val); int const days = isolate->date_cache()->DaysFromTime(time_ms); int const time_within_day = isolate->date_cache()->TimeInDay(time_ms, days); int year, unused, day; isolate->date_cache()->YearMonthDayFromDays(days, &year, &unused, &day); double const m = Object::NumberValue(*month); time_val = MakeDate(MakeDay(year, m, dt.value_or(day)), time_within_day); return SetDateValue(isolate, this_date, time_val); } // ES6 section 20.3.4.34 Date.prototype.setUTCSeconds ( sec, ms ) BUILTIN(DatePrototypeSetUTCSeconds) { HandleScope scope(isolate); CHECK_RECEIVER(JSDate, date, "Date.prototype.setUTCSeconds"); int const argc = args.length() - 1; DirectHandle<Object> sec = args.atOrUndefined(isolate, 1); double time_val = date->value(); ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, sec, Object::ToNumber(isolate, sec)); std::optional<double> milli; if (argc >= 2) { DirectHandle<Object> ms = args.at(2); ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, ms, Object::ToNumber(isolate, ms)); milli = Object::NumberValue(*ms); } if (std::isnan(time_val)) { return ReadOnlyRoots(isolate).nan_value(); } int64_t const time_ms = static_cast<int64_t>(time_val); int const day = isolate->date_cache()->DaysFromTime(time_ms); int const time_within_day = isolate->date_cache()->TimeInDay(time_ms, day); int const h = time_within_day / (60 * 60 * 1000); double const m = (time_within_day / (60 * 1000)) % 60; double const s = Object::NumberValue(*sec); time_val = MakeDate(day, MakeTime(h, m, s, milli.value_or(time_within_day % 1000))); return SetDateValue(isolate, date, time_val); } // ES6 section 20.3.4.35 Date.prototype.toDateString ( ) BUILTIN(DatePrototypeToDateString) { HandleScope scope(isolate); CHECK_RECEIVER(JSDate, date, "Date.prototype.toDateString"); DateBuffer buffer = ToDateString(date->value(), isolate->date_cache(), ToDateStringMode::kLocalDate); RETURN_RESULT_OR_FAILURE( isolate, isolate->factory()->NewStringFromUtf8(base::VectorOf(buffer))); } // ES6 section 20.3.4.36 Date.prototype.toISOString ( ) BUILTIN(DatePrototypeToISOString) { HandleScope scope(isolate); CHECK_RECEIVER(JSDate, date, "Date.prototype.toISOString"); double const time_val = date->value(); if (std::isnan(time_val)) { THROW_NEW_ERROR_RETURN_FAILURE( isolate, NewRangeError(MessageTemplate::kInvalidTimeValue)); } DateBuffer buffer = ToDateString(time_val, isolate->date_cache(), ToDateStringMode::kISODateAndTime); RETURN_RESULT_OR_FAILURE( isolate, isolate->factory()->NewStringFromUtf8(base::VectorOf(buffer))); } // ES6 section 20.3.4.41 Date.prototype.toString ( ) BUILTIN(DatePrototypeToString) { HandleScope scope(isolate); CHECK_RECEIVER(JSDate, date, "Date.prototype.toString"); DateBuffer buffer = ToDateString(date->value(), isolate->date_cache(), ToDateStringMode::kLocalDateAndTime); RETURN_RESULT_OR_FAILURE( isolate, isolate->factory()->NewStringFromUtf8(base::VectorOf(buffer))); } // ES6 section 20.3.4.42 Date.prototype.toTimeString ( ) BUILTIN(DatePrototypeToTimeString) { HandleScope scope(isolate); CHECK_RECEIVER(JSDate, date, "Date.prototype.toTimeString"); DateBuffer buffer = ToDateString(date->value(), isolate->date_cache(), ToDateStringMode::kLocalTime); RETURN_RESULT_OR_FAILURE( isolate, isolate->factory()->NewStringFromUtf8(base::VectorOf(buffer))); } #ifdef V8_INTL_SUPPORT // ecma402 #sup-date.prototype.tolocaledatestring BUILTIN(DatePrototypeToLocaleDateString) { HandleScope scope(isolate); isolate->CountUsage(v8::Isolate::UseCounterFeature::kDateToLocaleDateString); const char* method_name = "Date.prototype.toLocaleDateString"; CHECK_RECEIVER(JSDate, date, method_name); RETURN_RESULT_OR_FAILURE( isolate, JSDateTimeFormat::ToLocaleDateTime( isolate, date, // date args.atOrUndefined(isolate, 1), // locales args.atOrUndefined(isolate, 2), // options JSDateTimeFormat::RequiredOption::kDate, // required JSDateTimeFormat::DefaultsOption::kDate, // defaults method_name)); // method_name } // ecma402 #sup-date.prototype.tolocalestring BUILTIN(DatePrototypeToLocaleString) { HandleScope scope(isolate); isolate->CountUsage(v8::Isolate::UseCounterFeature::kDateToLocaleString); const char* method_name = "Date.prototype.toLocaleString"; CHECK_RECEIVER(JSDate, date, method_name); RETURN_RESULT_OR_FAILURE( isolate, JSDateTimeFormat::ToLocaleDateTime( isolate, date, // date args.atOrUndefined(isolate, 1), // locales args.atOrUndefined(isolate, 2), // options JSDateTimeFormat::RequiredOption::kAny, // required JSDateTimeFormat::DefaultsOption::kAll, // defaults method_name)); // method_name } // ecma402 #sup-date.prototype.tolocaletimestring BUILTIN(DatePrototypeToLocaleTimeString) { HandleScope scope(isolate); isolate->CountUsage(v8::Isolate::UseCounterFeature::kDateToLocaleTimeString); const char* method_name = "Date.prototype.toLocaleTimeString"; CHECK_RECEIVER(JSDate, date, method_name); RETURN_RESULT_OR_FAILURE( isolate, JSDateTimeFormat::ToLocaleDateTime( isolate, date, // date args.atOrUndefined(isolate, 1), // locales args.atOrUndefined(isolate, 2), // options JSDateTimeFormat::RequiredOption::kTime, // required JSDateTimeFormat::DefaultsOption::kTime, // defaults method_name)); // method_name } #endif // V8_INTL_SUPPORT // ES6 section 20.3.4.43 Date.prototype.toUTCString ( ) BUILTIN(DatePrototypeToUTCString) { HandleScope scope(isolate); CHECK_RECEIVER(JSDate, date, "Date.prototype.toUTCString"); DateBuffer buffer = ToDateString(date->value(), isolate->date_cache(), ToDateStringMode::kUTCDateAndTime); RETURN_RESULT_OR_FAILURE( isolate, isolate->factory()->NewStringFromUtf8(base::VectorOf(buffer))); } // ES6 section B.2.4.1 Date.prototype.getYear ( ) BUILTIN(DatePrototypeGetYear) { HandleScope scope(isolate); CHECK_RECEIVER(JSDate, date, "Date.prototype.getYear"); double time_val = date->value(); if (std::isnan(time_val)) return ReadOnlyRoots(isolate).nan_value(); int64_t time_ms = static_cast<int64_t>(time_val); int64_t local_time_ms = isolate->date_cache()->ToLocal(time_ms); int days = isolate->date_cache()->DaysFromTime(local_time_ms); int year, month, day; isolate->date_cache()->YearMonthDayFromDays(days, &year, &month, &day); return Smi::FromInt(year - 1900); } // ES6 section B.2.4.2 Date.prototype.setYear ( year ) BUILTIN(DatePrototypeSetYear) { HandleScope scope(isolate); CHECK_RECEIVER(JSDate, date, "Date.prototype.setYear"); DirectHandle<Object> year = args.atOrUndefined(isolate, 1); ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, year, Object::ToNumber(isolate, year)); double month_double = 0.0, day_double = 1.0, year_double = Object::NumberValue(*year); if (!std::isnan(year_double)) { double year_int = DoubleToInteger(year_double); if (0.0 <= year_int && year_int <= 99.0) { year_double = 1900.0 + year_int; } } int time_within_day = 0; if (!std::isnan(date->value())) { int64_t const time_ms = static_cast<int64_t>(date->value()); int64_t local_time_ms = isolate->date_cache()->ToLocal(time_ms); int const days = isolate->date_cache()->DaysFromTime(local_time_ms); time_within_day = isolate->date_cache()->TimeInDay(local_time_ms, days); int year_int, month_int, day_int; isolate->date_cache()->YearMonthDayFromDays(days, &year_int, &month_int, &day_int); month_double = month_int; day_double = day_int; } double time_val = MakeDate(MakeDay(year_double, month_double, day_double), time_within_day); return SetLocalDateValue(isolate, date, time_val); } // ES6 section 20.3.4.37 Date.prototype.toJSON ( key ) BUILTIN(DatePrototypeToJson) { HandleScope scope(isolate); DirectHandle<Object> receiver = args.atOrUndefined(isolate, 0); DirectHandle<JSReceiver> receiver_obj; ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, receiver_obj, Object::ToObject(isolate, receiver)); DirectHandle<Object> primitive; ASSIGN_RETURN_FAILURE_ON_EXCEPTION( isolate, primitive, Object::ToPrimitive(isolate, receiver_obj, ToPrimitiveHint::kNumber)); if (IsNumber(*primitive) && !std::isfinite(Object::NumberValue(*primitive))) { return ReadOnlyRoots(isolate).null_value(); } else { DirectHandle<String> name = isolate->factory()->NewStringFromAsciiChecked("toISOString"); DirectHandle<Object> function; ASSIGN_RETURN_FAILURE_ON_EXCEPTION( isolate, function, Object::GetProperty(isolate, receiver_obj, name)); if (!IsCallable(*function)) { THROW_NEW_ERROR_RETURN_FAILURE( isolate, NewTypeError(MessageTemplate::kCalledNonCallable, name)); } RETURN_RESULT_OR_FAILURE( isolate, Execution::Call(isolate, function, receiver_obj, {})); } } #ifdef V8_TEMPORAL_SUPPORT // Temporal #sec-date.prototype.totemporalinstant BUILTIN(DatePrototypeToTemporalInstant) { HandleScope scope(isolate); CHECK_RECEIVER(JSDate, date, "Date.prototype.toTemporalInstant"); // 1. Let t be ? thisTimeValue(this value). DirectHandle<BigInt> t; ASSIGN_RETURN_FAILURE_ON_EXCEPTION( isolate, t, BigInt::FromNumber(isolate, isolate->factory()->NewNumber(date->value()))); // 2. Let ns be ? NumberToBigInt(t) × 10^6. DirectHandle<BigInt> ns; ASSIGN_RETURN_FAILURE_ON_EXCEPTION( isolate, ns, BigInt::Multiply(isolate, t, BigInt::FromInt64(isolate, 1000000))); // 3. Return ! CreateTemporalInstant(ns). return *temporal::CreateTemporalInstantWithValidityCheck(isolate, ns) .ToHandleChecked(); } #endif // V8_TEMPORAL_SUPPORT } // namespace internal } // namespace v8