1// Copyright 2021 the V8 project authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "src/objects/js-temporal-objects.h" 6 7#include <set> 8 9#include "src/common/globals.h" 10#include "src/date/date.h" 11#include "src/execution/isolate.h" 12#include "src/heap/factory.h" 13#include "src/numbers/conversions-inl.h" 14#ifdef V8_INTL_SUPPORT 15#include "src/objects/intl-objects.h" 16#include "src/objects/js-date-time-format.h" 17#endif // V8_INTL_SUPPORT 18#include "src/objects/js-objects-inl.h" 19#include "src/objects/js-objects.h" 20#include "src/objects/js-temporal-objects-inl.h" 21#ifdef V8_INTL_SUPPORT 22#include "src/objects/managed-inl.h" 23#endif // V8_INTL_SUPPORT 24#include "src/objects/objects-inl.h" 25#include "src/objects/option-utils.h" 26#include "src/objects/property-descriptor.h" 27#include "src/strings/string-builder-inl.h" 28#include "src/temporal/temporal-parser.h" 29#ifdef V8_INTL_SUPPORT 30#include "unicode/calendar.h" 31#include "unicode/unistr.h" 32#endif // V8_INTL_SUPPORT 33 34namespace v8 { 35namespace internal { 36 37namespace { 38 39enum class Unit { 40 kNotPresent, 41 kAuto, 42 kYear, 43 kMonth, 44 kWeek, 45 kDay, 46 kHour, 47 kMinute, 48 kSecond, 49 kMillisecond, 50 kMicrosecond, 51 kNanosecond 52}; 53 54/** 55 * This header declare the Abstract Operations defined in the 56 * Temporal spec with the enum and struct for them. 57 */ 58 59// Struct 60struct DateTimeRecordCommon { 61 int32_t year; 62 int32_t month; 63 int32_t day; 64 int32_t hour; 65 int32_t minute; 66 int32_t second; 67 int32_t millisecond; 68 int32_t microsecond; 69 int32_t nanosecond; 70}; 71 72struct DateRecord { 73 int32_t year; 74 int32_t month; 75 int32_t day; 76 Handle<String> calendar; 77}; 78 79struct InstantRecord : public DateTimeRecordCommon { 80 Handle<String> offset_string; 81}; 82 83struct DateTimeRecord : public DateTimeRecordCommon { 84 Handle<String> calendar; 85}; 86 87struct DurationRecord { 88 int64_t years; 89 int64_t months; 90 int64_t weeks; 91 int64_t days; 92 int64_t hours; 93 int64_t minutes; 94 int64_t seconds; 95 int64_t milliseconds; 96 int64_t microseconds; 97 int64_t nanoseconds; 98}; 99 100struct TimeRecord { 101 int32_t hour; 102 int32_t minute; 103 int32_t second; 104 int32_t millisecond; 105 int32_t microsecond; 106 int32_t nanosecond; 107 Handle<String> calendar; 108}; 109 110struct TimeZoneRecord { 111 bool z; 112 Handle<String> offset_string; 113 Handle<String> name; 114}; 115 116// Options 117 118V8_WARN_UNUSED_RESULT Handle<String> UnitToString(Isolate* isolate, Unit unit); 119 120// #sec-temporal-totemporaldisambiguation 121enum class Disambiguation { kCompatible, kEarlier, kLater, kReject }; 122 123// #sec-temporal-totemporaloverflow 124enum class ShowOverflow { kConstrain, kReject }; 125 126// ISO8601 String Parsing 127 128// #sec-temporal-parsetemporalcalendarstring 129V8_WARN_UNUSED_RESULT MaybeHandle<String> ParseTemporalCalendarString( 130 Isolate* isolate, Handle<String> iso_string); 131 132// #sec-temporal-parsetemporaldatestring 133V8_WARN_UNUSED_RESULT Maybe<DateRecord> ParseTemporalDateString( 134 Isolate* isolate, Handle<String> iso_string); 135 136// #sec-temporal-parsetemporaltimestring 137Maybe<TimeRecord> ParseTemporalTimeString(Isolate* isolate, 138 Handle<String> iso_string); 139 140// #sec-temporal-parsetemporaltimezone 141V8_WARN_UNUSED_RESULT MaybeHandle<String> ParseTemporalTimeZone( 142 Isolate* isolate, Handle<String> string); 143 144// #sec-temporal-parsetemporaltimezonestring 145V8_WARN_UNUSED_RESULT Maybe<TimeZoneRecord> ParseTemporalTimeZoneString( 146 Isolate* isolate, Handle<String> iso_string); 147 148// #sec-temporal-parsetimezoneoffsetstring 149V8_WARN_UNUSED_RESULT Maybe<int64_t> ParseTimeZoneOffsetString( 150 Isolate* isolate, Handle<String> offset_string, 151 bool throwIfNotSatisfy = true); 152 153// #sec-temporal-parsetemporalinstant 154V8_WARN_UNUSED_RESULT MaybeHandle<BigInt> ParseTemporalInstant( 155 Isolate* isolate, Handle<String> iso_string); 156 157void BalanceISODate(Isolate* isolate, int32_t* year, int32_t* month, 158 int32_t* day); 159 160// Math and Misc 161 162V8_WARN_UNUSED_RESULT MaybeHandle<BigInt> AddInstant( 163 Isolate* isolate, Handle<BigInt> epoch_nanoseconds, int64_t hours, 164 int64_t minutes, int64_t seconds, int64_t milliseconds, 165 int64_t microseconds, int64_t nanoseconds); 166 167// #sec-temporal-balanceduration 168V8_WARN_UNUSED_RESULT Maybe<bool> BalanceDuration( 169 Isolate* isolate, int64_t* days, int64_t* hours, int64_t* minutes, 170 int64_t* seconds, int64_t* milliseconds, int64_t* microseconds, 171 int64_t* nanoseconds, Unit largest_unit, Handle<Object> relative_to, 172 const char* method_name); 173 174V8_WARN_UNUSED_RESULT Maybe<DurationRecord> DifferenceISODateTime( 175 Isolate* isolate, int32_t y1, int32_t mon1, int32_t d1, int32_t h1, 176 int32_t min1, int32_t s1, int32_t ms1, int32_t mus1, int32_t ns1, 177 int32_t y2, int32_t mon2, int32_t d2, int32_t h2, int32_t min2, int32_t s2, 178 int32_t ms2, int32_t mus2, int32_t ns2, Handle<JSReceiver> calendar, 179 Unit largest_unit, Handle<Object> relative_to, const char* method_name); 180 181// #sec-temporal-adddatetime 182V8_WARN_UNUSED_RESULT Maybe<DateTimeRecordCommon> AddDateTime( 183 Isolate* isolate, int32_t year, int32_t month, int32_t day, int32_t hour, 184 int32_t minute, int32_t second, int32_t millisecond, int32_t microsecond, 185 int32_t nanosecond, Handle<JSReceiver> calendar, const DurationRecord& dur, 186 Handle<Object> options); 187 188// #sec-temporal-addzoneddatetime 189V8_WARN_UNUSED_RESULT MaybeHandle<BigInt> AddZonedDateTime( 190 Isolate* isolate, Handle<BigInt> eopch_nanoseconds, 191 Handle<JSReceiver> time_zone, Handle<JSReceiver> calendar, 192 const DurationRecord& duration, const char* method_name); 193 194V8_WARN_UNUSED_RESULT MaybeHandle<BigInt> AddZonedDateTime( 195 Isolate* isolate, Handle<BigInt> eopch_nanoseconds, 196 Handle<JSReceiver> time_zone, Handle<JSReceiver> calendar, 197 const DurationRecord& duration, Handle<JSReceiver> options, 198 const char* method_name); 199 200// #sec-temporal-isvalidepochnanoseconds 201bool IsValidEpochNanoseconds(Isolate* isolate, 202 Handle<BigInt> epoch_nanoseconds); 203 204// #sec-temporal-isvalidduration 205bool IsValidDuration(Isolate* isolate, const DurationRecord& dur); 206 207// #sec-temporal-nanosecondstodays 208V8_WARN_UNUSED_RESULT Maybe<bool> NanosecondsToDays( 209 Isolate* isolate, Handle<BigInt> nanoseconds, 210 Handle<Object> relative_to_obj, int64_t* result_days, 211 int64_t* result_nanoseconds, int64_t* result_day_length, 212 const char* method_name); 213 214V8_WARN_UNUSED_RESULT Maybe<bool> NanosecondsToDays( 215 Isolate* isolate, int64_t nanoseconds, Handle<Object> relative_to_obj, 216 int64_t* result_days, int64_t* resultj_nanoseconds, 217 int64_t* result_day_length, const char* method_name); 218 219// #sec-temporal-interpretisodatetimeoffset 220enum class OffsetBehaviour { kOption, kExact, kWall }; 221 222V8_WARN_UNUSED_RESULT 223MaybeHandle<BigInt> GetEpochFromISOParts(Isolate* isolate, int32_t year, 224 int32_t month, int32_t day, 225 int32_t hour, int32_t minute, 226 int32_t second, int32_t millisecond, 227 int32_t microsecond, 228 int32_t nanosecond); 229 230int32_t DurationSign(Isolate* isolaet, const DurationRecord& dur); 231 232// #sec-temporal-isodaysinmonth 233int32_t ISODaysInMonth(Isolate* isolate, int32_t year, int32_t month); 234 235// #sec-temporal-isodaysinyear 236int32_t ISODaysInYear(Isolate* isolate, int32_t year); 237 238bool IsValidTime(Isolate* isolate, int32_t hour, int32_t minute, int32_t second, 239 int32_t millisecond, int32_t microsecond, int32_t nanosecond); 240 241// #sec-temporal-isvalidisodate 242bool IsValidISODate(Isolate* isolate, int32_t year, int32_t month, int32_t day); 243 244// #sec-temporal-compareisodate 245int32_t CompareISODate(Isolate* isolate, int32_t y1, int32_t m1, int32_t d1, 246 int32_t y2, int32_t m2, int32_t d2); 247 248// #sec-temporal-balanceisoyearmonth 249void BalanceISOYearMonth(Isolate* isolate, int32_t* year, int32_t* month); 250 251// #sec-temporal-balancetime 252V8_WARN_UNUSED_RESULT DateTimeRecordCommon 253BalanceTime(Isolate* isolate, int64_t hour, int64_t minute, int64_t second, 254 int64_t millisecond, int64_t microsecond, int64_t nanosecond); 255 256// #sec-temporal-differencetime 257V8_WARN_UNUSED_RESULT DurationRecord 258DifferenceTime(Isolate* isolate, int32_t h1, int32_t min1, int32_t s1, 259 int32_t ms1, int32_t mus1, int32_t ns1, int32_t h2, int32_t min2, 260 int32_t s2, int32_t ms2, int32_t mus2, int32_t ns2); 261 262// #sec-temporal-addtime 263V8_WARN_UNUSED_RESULT DateTimeRecordCommon 264AddTime(Isolate* isolate, int64_t hour, int64_t minute, int64_t second, 265 int64_t millisecond, int64_t microsecond, int64_t nanosecond, 266 int64_t hours, int64_t minutes, int64_t seconds, int64_t milliseconds, 267 int64_t microseconds, int64_t nanoseconds); 268 269// #sec-temporal-totaldurationnanoseconds 270int64_t TotalDurationNanoseconds(Isolate* isolate, int64_t days, int64_t hours, 271 int64_t minutes, int64_t seconds, 272 int64_t milliseconds, int64_t microseconds, 273 int64_t nanoseconds, int64_t offset_shift); 274 275// #sec-temporal-totemporaltimerecord 276Maybe<TimeRecord> ToTemporalTimeRecord(Isolate* isolate, 277 Handle<JSReceiver> temporal_time_like, 278 const char* method_name); 279// Calendar Operations 280 281// #sec-temporal-calendardateadd 282V8_WARN_UNUSED_RESULT MaybeHandle<JSTemporalPlainDate> CalendarDateAdd( 283 Isolate* isolate, Handle<JSReceiver> calendar, Handle<Object> date, 284 Handle<Object> durations, Handle<Object> options, Handle<Object> date_add); 285 286// #sec-temporal-calendardateuntil 287V8_WARN_UNUSED_RESULT MaybeHandle<JSTemporalDuration> CalendarDateUntil( 288 Isolate* isolate, Handle<JSReceiver> calendar, Handle<Object> one, 289 Handle<Object> two, Handle<Object> options, Handle<Object> date_until); 290 291// #sec-temporal-calendarfields 292MaybeHandle<FixedArray> CalendarFields(Isolate* isolate, 293 Handle<JSReceiver> calendar, 294 Handle<FixedArray> field_names); 295 296// #sec-temporal-getoffsetnanosecondsfor 297V8_WARN_UNUSED_RESULT Maybe<int64_t> GetOffsetNanosecondsFor( 298 Isolate* isolate, Handle<JSReceiver> time_zone, Handle<Object> instant, 299 const char* method_name); 300 301// #sec-temporal-totemporalcalendarwithisodefault 302MaybeHandle<JSReceiver> ToTemporalCalendarWithISODefault( 303 Isolate* isolate, Handle<Object> temporal_calendar_like, 304 const char* method_name); 305 306// #sec-temporal-isbuiltincalendar 307bool IsBuiltinCalendar(Isolate* isolate, Handle<String> id); 308 309// Internal Helper Function 310int32_t CalendarIndex(Isolate* isolate, Handle<String> id); 311 312// #sec-isvalidtimezonename 313bool IsValidTimeZoneName(Isolate* isolate, Handle<String> time_zone); 314 315// #sec-canonicalizetimezonename 316V8_WARN_UNUSED_RESULT MaybeHandle<String> CanonicalizeTimeZoneName( 317 Isolate* isolate, Handle<String> identifier); 318 319// #sec-temporal-tointegerthrowoninfinity 320MaybeHandle<Object> ToIntegerThrowOnInfinity(Isolate* isolate, 321 Handle<Object> argument); 322 323// #sec-temporal-topositiveinteger 324MaybeHandle<Object> ToPositiveInteger(Isolate* isolate, 325 Handle<Object> argument); 326 327inline int64_t floor_divide(int64_t a, int64_t b) { 328 return (((a) / (b)) + ((((a) < 0) && (((a) % (b)) != 0)) ? -1 : 0)); 329} 330inline int64_t modulo(int64_t a, int64_t b) { 331 return ((((a) % (b)) + (b)) % (b)); 332} 333 334#define STRINGIFY(x) #x 335#define TOSTRING(x) STRINGIFY(x) 336#define AT __FILE__ ":" TOSTRING(__LINE__) 337 338#ifdef DEBUG 339#define TEMPORAL_DEBUG_INFO AT 340#define TEMPORAL_ENTER_FUNC() 341// #define TEMPORAL_ENTER_FUNC() do { PrintF("Start: %s\n", __func__); } while 342// (false) 343#else 344// #define TEMPORAL_DEBUG_INFO "" 345#define TEMPORAL_DEBUG_INFO AT 346#define TEMPORAL_ENTER_FUNC() 347// #define TEMPORAL_ENTER_FUNC() do { PrintF("Start: %s\n", __func__); } while 348// (false) 349#endif // DEBUG 350 351#define NEW_TEMPORAL_INVALD_ARG_TYPE_ERROR() \ 352 NewTypeError( \ 353 MessageTemplate::kInvalidArgumentForTemporal, \ 354 isolate->factory()->NewStringFromStaticChars(TEMPORAL_DEBUG_INFO)) 355 356#define NEW_TEMPORAL_INVALD_ARG_RANGE_ERROR() \ 357 NewRangeError( \ 358 MessageTemplate::kInvalidTimeValueForTemporal, \ 359 isolate->factory()->NewStringFromStaticChars(TEMPORAL_DEBUG_INFO)) 360 361// #sec-defaulttimezone 362MaybeHandle<String> DefaultTimeZone(Isolate* isolate) { 363 TEMPORAL_ENTER_FUNC(); 364 // For now, always return "UTC" 365 // TODO(ftang) implement behavior specified in #sup-defaulttimezone 366 return isolate->factory()->UTC_string(); 367} 368 369// #sec-temporal-isodatetimewithinlimits 370bool ISODateTimeWithinLimits(Isolate* isolate, int32_t year, int32_t month, 371 int32_t day, int32_t hour, int32_t minute, 372 int32_t second, int32_t millisecond, 373 int32_t microsecond, int32_t nanosecond) { 374 TEMPORAL_ENTER_FUNC(); 375 /** 376 * Note: It is really overkill to decide within the limit by following the 377 * specified algorithm literally, which require the conversion to BigInt. 378 * Take a short cut and use pre-calculated year/month/day boundary instead. 379 * 380 * Math: 381 * (-8.64 x 10^21- 8.64 x 10^16, 8.64 x 10^21 + 8.64 x 10^16) ns 382 * = (-8.64 x 9999 x 10^16, 8.64 x 9999 x 10^16) ns 383 * = (-8.64 x 9999 x 10^10, 8.64 x 9999 x 10^10) millisecond 384 * = (-8.64 x 9999 x 10^7, 8.64 x 9999 x 10^7) second 385 * = (-86400 x 9999 x 10^3, 86400 x 9999 x 10^3) second 386 * = (-9999 x 10^3, 9999 x 10^3) days => Because 60*60*24 = 86400 387 * 9999000 days is about 27376 years, 4 months and 7 days. 388 * Therefore 9999000 days before Jan 1 1970 is around Auguest 23, -25407 and 389 * 9999000 days after Jan 1 1970 is around April 9, 29346. 390 */ 391 if (year > -25407 && year < 29346) return true; 392 if (year < -25407 || year > 29346) return false; 393 if (year == -25407) { 394 if (month > 8) return true; 395 if (month < 8) return false; 396 return (day > 23); 397 } else { 398 DCHECK_EQ(year, 29346); 399 if (month > 4) return false; 400 if (month < 4) return true; 401 return (day > 23); 402 } 403 // 1. Assert: year, month, day, hour, minute, second, millisecond, 404 // microsecond, and nanosecond are integers. 405 // 2. Let ns be ! GetEpochFromISOParts(year, month, day, hour, minute, 406 // second, millisecond, microsecond, nanosecond). 407 // 3. If ns ≤ -8.64 × 10^21 - 8.64 × 10^16, then 408 // 4. If ns ≥ 8.64 × 10^21 + 8.64 × 10^16, then 409 // 5. Return true. 410} 411 412// #sec-temporal-isoyearmonthwithinlimits 413bool ISOYearMonthWithinLimits(int32_t year, int32_t month) { 414 TEMPORAL_ENTER_FUNC(); 415 // 1. Assert: year and month are integers. 416 // 2. If year < −271821 or year > 275760, then 417 // a. Return false. 418 if (year < -271821 || year > 275760) return false; 419 // 3. If year is −271821 and month < 4, then 420 // a. Return false. 421 if (year == -271821 && month < 4) return false; 422 // 4. If year is 275760 and month > 9, then 423 // a. Return false. 424 if (year == 275760 && month > 9) return false; 425 // 5. Return true. 426 return true; 427} 428 429#define ORDINARY_CREATE_FROM_CONSTRUCTOR(obj, target, new_target, T) \ 430 Handle<JSReceiver> new_target_receiver = \ 431 Handle<JSReceiver>::cast(new_target); \ 432 Handle<Map> map; \ 433 ASSIGN_RETURN_ON_EXCEPTION( \ 434 isolate, map, \ 435 JSFunction::GetDerivedMap(isolate, target, new_target_receiver), T); \ 436 Handle<T> object = \ 437 Handle<T>::cast(isolate->factory()->NewFastOrSlowJSObjectFromMap(map)); 438 439#define THROW_INVALID_RANGE(T) \ 440 THROW_NEW_ERROR(isolate, NEW_TEMPORAL_INVALD_ARG_RANGE_ERROR(), T); 441 442#define CONSTRUCTOR(name) \ 443 Handle<JSFunction>( \ 444 JSFunction::cast( \ 445 isolate->context().native_context().temporal_##name##_function()), \ 446 isolate) 447 448// #sec-temporal-systemutcepochnanoseconds 449MaybeHandle<BigInt> SystemUTCEpochNanoseconds(Isolate* isolate) { 450 TEMPORAL_ENTER_FUNC(); 451 // 1. Let ns be the approximate current UTC date and time, in nanoseconds 452 // since the epoch. 453 double ms = V8::GetCurrentPlatform()->CurrentClockTimeMillis(); 454 // 2. Set ns to the result of clamping ns between −8.64 × 10^21 and 8.64 × 455 // 10^21. 456 457 // 3. Return ℤ(ns). 458 double ns = ms * 1000000.0; 459 ns = std::floor(std::max(-8.64e21, std::min(ns, 8.64e21))); 460 return BigInt::FromNumber(isolate, isolate->factory()->NewNumber(ns)); 461} 462 463// #sec-temporal-createtemporalcalendar 464MaybeHandle<JSTemporalCalendar> CreateTemporalCalendar( 465 Isolate* isolate, Handle<JSFunction> target, Handle<HeapObject> new_target, 466 Handle<String> identifier) { 467 TEMPORAL_ENTER_FUNC(); 468 // 1. Assert: ! IsBuiltinCalendar(identifier) is true. 469 // 2. If newTarget is not provided, set newTarget to %Temporal.Calendar%. 470 // 3. Let object be ? OrdinaryCreateFromConstructor(newTarget, 471 // "%Temporal.Calendar.prototype%", « [[InitializedTemporalCalendar]], 472 // [[Identifier]] »). 473 int32_t index = CalendarIndex(isolate, identifier); 474 475 ORDINARY_CREATE_FROM_CONSTRUCTOR(object, target, new_target, 476 JSTemporalCalendar) 477 478 object->set_flags(0); 479 // 4. Set object.[[Identifier]] to identifier. 480 object->set_calendar_index(index); 481 // 5. Return object. 482 return object; 483} 484 485MaybeHandle<JSTemporalCalendar> CreateTemporalCalendar( 486 Isolate* isolate, Handle<String> identifier) { 487 TEMPORAL_ENTER_FUNC(); 488 return CreateTemporalCalendar(isolate, CONSTRUCTOR(calendar), 489 CONSTRUCTOR(calendar), identifier); 490} 491 492// #sec-temporal-createtemporaldate 493MaybeHandle<JSTemporalPlainDate> CreateTemporalDate( 494 Isolate* isolate, Handle<JSFunction> target, Handle<HeapObject> new_target, 495 int32_t iso_year, int32_t iso_month, int32_t iso_day, 496 Handle<JSReceiver> calendar) { 497 TEMPORAL_ENTER_FUNC(); 498 // 1. Assert: isoYear is an integer. 499 // 2. Assert: isoMonth is an integer. 500 // 3. Assert: isoDay is an integer. 501 // 4. Assert: Type(calendar) is Object. 502 // 5. If ! IsValidISODate(isoYear, isoMonth, isoDay) is false, throw a 503 // RangeError exception. 504 if (!IsValidISODate(isolate, iso_year, iso_month, iso_day)) { 505 THROW_INVALID_RANGE(JSTemporalPlainDate); 506 } 507 // 6. If ! ISODateTimeWithinLimits(isoYear, isoMonth, isoDay, 12, 0, 0, 0, 0, 508 // 0) is false, throw a RangeError exception. 509 if (!ISODateTimeWithinLimits(isolate, iso_year, iso_month, iso_day, 12, 0, 0, 510 0, 0, 0)) { 511 THROW_INVALID_RANGE(JSTemporalPlainDate); 512 } 513 // 7. If newTarget is not present, set it to %Temporal.PlainDate%. 514 515 // 8. Let object be ? OrdinaryCreateFromConstructor(newTarget, 516 // "%Temporal.PlainDate.prototype%", « [[InitializedTemporalDate]], 517 // [[ISOYear]], [[ISOMonth]], [[ISODay]], [[Calendar]] »). 518 ORDINARY_CREATE_FROM_CONSTRUCTOR(object, target, new_target, 519 JSTemporalPlainDate) 520 object->set_year_month_day(0); 521 // 9. Set object.[[ISOYear]] to isoYear. 522 object->set_iso_year(iso_year); 523 // 10. Set object.[[ISOMonth]] to isoMonth. 524 object->set_iso_month(iso_month); 525 // 11. Set object.[[ISODay]] to isoDay. 526 object->set_iso_day(iso_day); 527 // 12. Set object.[[Calendar]] to calendar. 528 object->set_calendar(*calendar); 529 // 13. Return object. 530 return object; 531} 532 533MaybeHandle<JSTemporalPlainDate> CreateTemporalDate( 534 Isolate* isolate, int32_t iso_year, int32_t iso_month, int32_t iso_day, 535 Handle<JSReceiver> calendar) { 536 TEMPORAL_ENTER_FUNC(); 537 return CreateTemporalDate(isolate, CONSTRUCTOR(plain_date), 538 CONSTRUCTOR(plain_date), iso_year, iso_month, 539 iso_day, calendar); 540} 541 542// #sec-temporal-createtemporaldatetime 543MaybeHandle<JSTemporalPlainDateTime> CreateTemporalDateTime( 544 Isolate* isolate, Handle<JSFunction> target, Handle<HeapObject> new_target, 545 int32_t iso_year, int32_t iso_month, int32_t iso_day, int32_t hour, 546 int32_t minute, int32_t second, int32_t millisecond, int32_t microsecond, 547 int32_t nanosecond, Handle<JSReceiver> calendar) { 548 TEMPORAL_ENTER_FUNC(); 549 // 1. Assert: isoYear, isoMonth, isoDay, hour, minute, second, millisecond, 550 // microsecond, and nanosecond are integers. 551 // 2. Assert: Type(calendar) is Object. 552 // 3. If ! IsValidISODate(isoYear, isoMonth, isoDay) is false, throw a 553 // RangeError exception. 554 if (!IsValidISODate(isolate, iso_year, iso_month, iso_day)) { 555 THROW_INVALID_RANGE(JSTemporalPlainDateTime); 556 } 557 // 4. If ! IsValidTime(hour, minute, second, millisecond, microsecond, 558 // nanosecond) is false, throw a RangeError exception. 559 if (!IsValidTime(isolate, hour, minute, second, millisecond, microsecond, 560 nanosecond)) { 561 THROW_INVALID_RANGE(JSTemporalPlainDateTime); 562 } 563 // 5. If ! ISODateTimeWithinLimits(isoYear, isoMonth, isoDay, hour, minute, 564 // second, millisecond, microsecond, nanosecond) is false, then 565 if (!ISODateTimeWithinLimits(isolate, iso_year, iso_month, iso_day, hour, 566 minute, second, millisecond, microsecond, 567 nanosecond)) { 568 // a. Throw a RangeError exception. 569 THROW_INVALID_RANGE(JSTemporalPlainDateTime); 570 } 571 // 6. If newTarget is not present, set it to %Temporal.PlainDateTime%. 572 // 7. Let object be ? OrdinaryCreateFromConstructor(newTarget, 573 // "%Temporal.PlainDateTime.prototype%", « [[InitializedTemporalDateTime]], 574 // [[ISOYear]], [[ISOMonth]], [[ISODay]], [[ISOHour]], [[ISOMinute]], 575 // [[ISOSecond]], [[ISOMillisecond]], [[ISOMicrosecond]], [[ISONanosecond]], 576 // [[Calendar]] »). 577 ORDINARY_CREATE_FROM_CONSTRUCTOR(object, target, new_target, 578 JSTemporalPlainDateTime) 579 580 object->set_year_month_day(0); 581 object->set_hour_minute_second(0); 582 object->set_second_parts(0); 583 // 8. Set object.[[ISOYear]] to isoYear. 584 object->set_iso_year(iso_year); 585 // 9. Set object.[[ISOMonth]] to isoMonth. 586 object->set_iso_month(iso_month); 587 // 10. Set object.[[ISODay]] to isoDay. 588 object->set_iso_day(iso_day); 589 // 11. Set object.[[ISOHour]] to hour. 590 object->set_iso_hour(hour); 591 // 12. Set object.[[ISOMinute]] to minute. 592 object->set_iso_minute(minute); 593 // 13. Set object.[[ISOSecond]] to second. 594 object->set_iso_second(second); 595 // 14. Set object.[[ISOMillisecond]] to millisecond. 596 object->set_iso_millisecond(millisecond); 597 // 15. Set object.[[ISOMicrosecond]] to microsecond. 598 object->set_iso_microsecond(microsecond); 599 // 16. Set object.[[ISONanosecond]] to nanosecond. 600 object->set_iso_nanosecond(nanosecond); 601 // 17. Set object.[[Calendar]] to calendar. 602 object->set_calendar(*calendar); 603 // 18. Return object. 604 return object; 605} 606 607MaybeHandle<JSTemporalPlainDateTime> CreateTemporalDateTimeDefaultTarget( 608 Isolate* isolate, int32_t iso_year, int32_t iso_month, int32_t iso_day, 609 int32_t hour, int32_t minute, int32_t second, int32_t millisecond, 610 int32_t microsecond, int32_t nanosecond, Handle<JSReceiver> calendar) { 611 TEMPORAL_ENTER_FUNC(); 612 return CreateTemporalDateTime(isolate, CONSTRUCTOR(plain_date_time), 613 CONSTRUCTOR(plain_date_time), iso_year, 614 iso_month, iso_day, hour, minute, second, 615 millisecond, microsecond, nanosecond, calendar); 616} 617 618} // namespace 619 620namespace temporal { 621 622MaybeHandle<JSTemporalPlainDateTime> CreateTemporalDateTime( 623 Isolate* isolate, int32_t iso_year, int32_t iso_month, int32_t iso_day, 624 int32_t hour, int32_t minute, int32_t second, int32_t millisecond, 625 int32_t microsecond, int32_t nanosecond, Handle<JSReceiver> calendar) { 626 return CreateTemporalDateTimeDefaultTarget( 627 isolate, iso_year, iso_month, iso_day, hour, minute, second, millisecond, 628 microsecond, nanosecond, calendar); 629} 630 631} // namespace temporal 632 633namespace { 634// #sec-temporal-createtemporaltime 635MaybeHandle<JSTemporalPlainTime> CreateTemporalTime( 636 Isolate* isolate, Handle<JSFunction> target, Handle<HeapObject> new_target, 637 int32_t hour, int32_t minute, int32_t second, int32_t millisecond, 638 int32_t microsecond, int32_t nanosecond) { 639 TEMPORAL_ENTER_FUNC(); 640 // 2. If ! IsValidTime(hour, minute, second, millisecond, microsecond, 641 // nanosecond) is false, throw a RangeError exception. 642 if (!IsValidTime(isolate, hour, minute, second, millisecond, microsecond, 643 nanosecond)) { 644 THROW_INVALID_RANGE(JSTemporalPlainTime); 645 } 646 647 // 4. Let object be ? OrdinaryCreateFromConstructor(newTarget, 648 // "%Temporal.PlainTime.prototype%", « [[InitializedTemporalTime]], 649 // [[ISOHour]], [[ISOMinute]], [[ISOSecond]], [[ISOMillisecond]], 650 // [[ISOMicrosecond]], [[ISONanosecond]], [[Calendar]] »). 651 ORDINARY_CREATE_FROM_CONSTRUCTOR(object, target, new_target, 652 JSTemporalPlainTime) 653 Handle<JSTemporalCalendar> calendar; 654 ASSIGN_RETURN_ON_EXCEPTION(isolate, calendar, 655 temporal::GetISO8601Calendar(isolate), 656 JSTemporalPlainTime); 657 object->set_hour_minute_second(0); 658 object->set_second_parts(0); 659 // 5. Set object.[[ISOHour]] to hour. 660 object->set_iso_hour(hour); 661 // 6. Set object.[[ISOMinute]] to minute. 662 object->set_iso_minute(minute); 663 // 7. Set object.[[ISOSecond]] to second. 664 object->set_iso_second(second); 665 // 8. Set object.[[ISOMillisecond]] to millisecond. 666 object->set_iso_millisecond(millisecond); 667 // 9. Set object.[[ISOMicrosecond]] to microsecond. 668 object->set_iso_microsecond(microsecond); 669 // 10. Set object.[[ISONanosecond]] to nanosecond. 670 object->set_iso_nanosecond(nanosecond); 671 // 11. Set object.[[Calendar]] to ? GetISO8601Calendar(). 672 object->set_calendar(*calendar); 673 674 // 12. Return object. 675 return object; 676} 677 678MaybeHandle<JSTemporalPlainTime> CreateTemporalTime( 679 Isolate* isolate, int32_t hour, int32_t minute, int32_t second, 680 int32_t millisecond, int32_t microsecond, int32_t nanosecond) { 681 TEMPORAL_ENTER_FUNC(); 682 return CreateTemporalTime(isolate, CONSTRUCTOR(plain_time), 683 CONSTRUCTOR(plain_time), hour, minute, second, 684 millisecond, microsecond, nanosecond); 685} 686 687// #sec-temporal-createtemporalmonthday 688MaybeHandle<JSTemporalPlainMonthDay> CreateTemporalMonthDay( 689 Isolate* isolate, Handle<JSFunction> target, Handle<HeapObject> new_target, 690 int32_t iso_month, int32_t iso_day, Handle<JSReceiver> calendar, 691 int32_t reference_iso_year) { 692 TEMPORAL_ENTER_FUNC(); 693 // 1. Assert: isoMonth, isoDay, and referenceISOYear are integers. 694 // 2. Assert: Type(calendar) is Object. 695 // 3. If ! IsValidISODate(referenceISOYear, isoMonth, isoDay) is false, throw 696 // a RangeError exception. 697 if (!IsValidISODate(isolate, reference_iso_year, iso_month, iso_day)) { 698 THROW_INVALID_RANGE(JSTemporalPlainMonthDay); 699 } 700 // 4. If newTarget is not present, set it to %Temporal.PlainMonthDay%. 701 // 5. Let object be ? OrdinaryCreateFromConstructor(newTarget, 702 // "%Temporal.PlainMonthDay.prototype%", « [[InitializedTemporalMonthDay]], 703 // [[ISOMonth]], [[ISODay]], [[ISOYear]], [[Calendar]] »). 704 ORDINARY_CREATE_FROM_CONSTRUCTOR(object, target, new_target, 705 JSTemporalPlainMonthDay) 706 object->set_year_month_day(0); 707 // 6. Set object.[[ISOMonth]] to isoMonth. 708 object->set_iso_month(iso_month); 709 // 7. Set object.[[ISODay]] to isoDay. 710 object->set_iso_day(iso_day); 711 // 8. Set object.[[Calendar]] to calendar. 712 object->set_calendar(*calendar); 713 // 9. Set object.[[ISOYear]] to referenceISOYear. 714 object->set_iso_year(reference_iso_year); 715 // 10. Return object. 716 return object; 717} 718 719// #sec-temporal-createtemporalyearmonth 720MaybeHandle<JSTemporalPlainYearMonth> CreateTemporalYearMonth( 721 Isolate* isolate, Handle<JSFunction> target, Handle<HeapObject> new_target, 722 int32_t iso_year, int32_t iso_month, Handle<JSReceiver> calendar, 723 int32_t reference_iso_day) { 724 TEMPORAL_ENTER_FUNC(); 725 // 1. Assert: isoYear, isoMonth, and referenceISODay are integers. 726 // 2. Assert: Type(calendar) is Object. 727 // 3. If ! IsValidISODate(isoYear, isoMonth, referenceISODay) is false, throw 728 // a RangeError exception. 729 if (!IsValidISODate(isolate, iso_year, iso_month, reference_iso_day)) { 730 THROW_INVALID_RANGE(JSTemporalPlainYearMonth); 731 } 732 // 4. If ! ISOYearMonthWithinLimits(isoYear, isoMonth) is false, throw a 733 // RangeError exception. 734 if (!ISOYearMonthWithinLimits(iso_year, iso_month)) { 735 THROW_INVALID_RANGE(JSTemporalPlainYearMonth); 736 } 737 // 5. If newTarget is not present, set it to %Temporal.PlainYearMonth%. 738 // 6. Let object be ? OrdinaryCreateFromConstructor(newTarget, 739 // "%Temporal.PlainYearMonth.prototype%", « [[InitializedTemporalYearMonth]], 740 // [[ISOYear]], [[ISOMonth]], [[ISODay]], [[Calendar]] »). 741 ORDINARY_CREATE_FROM_CONSTRUCTOR(object, target, new_target, 742 JSTemporalPlainYearMonth) 743 object->set_year_month_day(0); 744 // 7. Set object.[[ISOYear]] to isoYear. 745 object->set_iso_year(iso_year); 746 // 8. Set object.[[ISOMonth]] to isoMonth. 747 object->set_iso_month(iso_month); 748 // 9. Set object.[[Calendar]] to calendar. 749 object->set_calendar(*calendar); 750 // 10. Set object.[[ISODay]] to referenceISODay. 751 object->set_iso_day(reference_iso_day); 752 // 11. Return object. 753 return object; 754} 755 756// #sec-temporal-createtemporalzoneddatetime 757MaybeHandle<JSTemporalZonedDateTime> CreateTemporalZonedDateTime( 758 Isolate* isolate, Handle<JSFunction> target, Handle<HeapObject> new_target, 759 Handle<BigInt> epoch_nanoseconds, Handle<JSReceiver> time_zone, 760 Handle<JSReceiver> calendar) { 761 TEMPORAL_ENTER_FUNC(); 762 // 1. Assert: Type(epochNanoseconds) is BigInt. 763 // 2. Assert: ! IsValidEpochNanoseconds(epochNanoseconds) is true. 764 DCHECK(IsValidEpochNanoseconds(isolate, epoch_nanoseconds)); 765 // 3. Assert: Type(timeZone) is Object. 766 // 4. Assert: Type(calendar) is Object. 767 // 5. If newTarget is not present, set it to %Temporal.ZonedDateTime%. 768 // 6. Let object be ? OrdinaryCreateFromConstructor(newTarget, 769 // "%Temporal.ZonedDateTime.prototype%", « 770 // [[InitializedTemporalZonedDateTime]], [[Nanoseconds]], [[TimeZone]], 771 // [[Calendar]] »). 772 ORDINARY_CREATE_FROM_CONSTRUCTOR(object, target, new_target, 773 JSTemporalZonedDateTime) 774 // 7. Set object.[[Nanoseconds]] to epochNanoseconds. 775 object->set_nanoseconds(*epoch_nanoseconds); 776 // 8. Set object.[[TimeZone]] to timeZone. 777 object->set_time_zone(*time_zone); 778 // 9. Set object.[[Calendar]] to calendar. 779 object->set_calendar(*calendar); 780 // 10. Return object. 781 return object; 782} 783MaybeHandle<JSTemporalZonedDateTime> CreateTemporalZonedDateTime( 784 Isolate* isolate, Handle<BigInt> epoch_nanoseconds, 785 Handle<JSReceiver> time_zone, Handle<JSReceiver> calendar) { 786 TEMPORAL_ENTER_FUNC(); 787 return CreateTemporalZonedDateTime(isolate, CONSTRUCTOR(zoned_date_time), 788 CONSTRUCTOR(zoned_date_time), 789 epoch_nanoseconds, time_zone, calendar); 790} 791 792// #sec-temporal-createtemporalduration 793MaybeHandle<JSTemporalDuration> CreateTemporalDuration( 794 Isolate* isolate, Handle<JSFunction> target, Handle<HeapObject> new_target, 795 int64_t years, int64_t months, int64_t weeks, int64_t days, int64_t hours, 796 int64_t minutes, int64_t seconds, int64_t milliseconds, 797 int64_t microseconds, int64_t nanoseconds) { 798 TEMPORAL_ENTER_FUNC(); 799 Factory* factory = isolate->factory(); 800 // 1. If ! IsValidDuration(years, months, weeks, days, hours, minutes, 801 // seconds, milliseconds, microseconds, nanoseconds) is false, throw a 802 // RangeError exception. 803 if (!IsValidDuration(isolate, 804 {years, months, weeks, days, hours, minutes, seconds, 805 milliseconds, microseconds, nanoseconds})) { 806 THROW_INVALID_RANGE(JSTemporalDuration); 807 } 808 809 // 2. If newTarget is not present, set it to %Temporal.Duration%. 810 // 3. Let object be ? OrdinaryCreateFromConstructor(newTarget, 811 // "%Temporal.Duration.prototype%", « [[InitializedTemporalDuration]], 812 // [[Years]], [[Months]], [[Weeks]], [[Days]], [[Hours]], [[Minutes]], 813 // [[Seconds]], [[Milliseconds]], [[Microseconds]], [[Nanoseconds]] »). 814 ORDINARY_CREATE_FROM_CONSTRUCTOR(object, target, new_target, 815 JSTemporalDuration) 816#define SET_FROM_INT64(obj, p) \ 817 do { \ 818 Handle<Object> item = factory->NewNumberFromInt64(p); \ 819 object->set_##p(*item); \ 820 } while (false) 821 // 4. Set object.[[Years]] to years. 822 SET_FROM_INT64(object, years); 823 // 5. Set object.[[Months]] to months. 824 SET_FROM_INT64(object, months); 825 // 6. Set object.[[Weeks]] to weeks. 826 SET_FROM_INT64(object, weeks); 827 // 7. Set object.[[Days]] to days. 828 SET_FROM_INT64(object, days); 829 // 8. Set object.[[Hours]] to hours. 830 SET_FROM_INT64(object, hours); 831 // 9. Set object.[[Minutes]] to minutes. 832 SET_FROM_INT64(object, minutes); 833 // 10. Set object.[[Seconds]] to seconds. 834 SET_FROM_INT64(object, seconds); 835 // 11. Set object.[[Milliseconds]] to milliseconds. 836 SET_FROM_INT64(object, milliseconds); 837 // 12. Set object.[[Microseconds]] to microseconds. 838 SET_FROM_INT64(object, microseconds); 839 // 13. Set object.[[Nanoseconds]] to nanoseconds. 840 SET_FROM_INT64(object, nanoseconds); 841#undef SET_FROM_INT64 842 // 14. Return object. 843 return object; 844} 845 846MaybeHandle<JSTemporalDuration> CreateTemporalDuration( 847 Isolate* isolate, int64_t years, int64_t months, int64_t weeks, 848 int64_t days, int64_t hours, int64_t minutes, int64_t seconds, 849 int64_t milliseconds, int64_t microseconds, int64_t nanoseconds) { 850 TEMPORAL_ENTER_FUNC(); 851 return CreateTemporalDuration(isolate, CONSTRUCTOR(duration), 852 CONSTRUCTOR(duration), years, months, weeks, 853 days, hours, minutes, seconds, milliseconds, 854 microseconds, nanoseconds); 855} 856 857} // namespace 858 859namespace temporal { 860 861// #sec-temporal-createtemporalinstant 862MaybeHandle<JSTemporalInstant> CreateTemporalInstant( 863 Isolate* isolate, Handle<JSFunction> target, Handle<HeapObject> new_target, 864 Handle<BigInt> epoch_nanoseconds) { 865 TEMPORAL_ENTER_FUNC(); 866 // 1. Assert: Type(epochNanoseconds) is BigInt. 867 // 2. Assert: ! IsValidEpochNanoseconds(epochNanoseconds) is true. 868 DCHECK(IsValidEpochNanoseconds(isolate, epoch_nanoseconds)); 869 870 // 4. Let object be ? OrdinaryCreateFromConstructor(newTarget, 871 // "%Temporal.Instant.prototype%", « [[InitializedTemporalInstant]], 872 // [[Nanoseconds]] »). 873 ORDINARY_CREATE_FROM_CONSTRUCTOR(object, target, new_target, 874 JSTemporalInstant) 875 // 5. Set object.[[Nanoseconds]] to ns. 876 object->set_nanoseconds(*epoch_nanoseconds); 877 return object; 878} 879 880MaybeHandle<JSTemporalInstant> CreateTemporalInstant( 881 Isolate* isolate, Handle<BigInt> epoch_nanoseconds) { 882 TEMPORAL_ENTER_FUNC(); 883 return CreateTemporalInstant(isolate, CONSTRUCTOR(instant), 884 CONSTRUCTOR(instant), epoch_nanoseconds); 885} 886 887} // namespace temporal 888 889namespace { 890 891MaybeHandle<JSTemporalTimeZone> CreateTemporalTimeZoneFromIndex( 892 Isolate* isolate, Handle<JSFunction> target, Handle<HeapObject> new_target, 893 int32_t index) { 894 TEMPORAL_ENTER_FUNC(); 895 ORDINARY_CREATE_FROM_CONSTRUCTOR(object, target, new_target, 896 JSTemporalTimeZone) 897 object->set_flags(0); 898 object->set_details(0); 899 900 object->set_is_offset(false); 901 object->set_offset_milliseconds_or_time_zone_index(index); 902 return object; 903} 904 905MaybeHandle<JSTemporalTimeZone> CreateTemporalTimeZoneUTC( 906 Isolate* isolate, Handle<JSFunction> target, 907 Handle<HeapObject> new_target) { 908 TEMPORAL_ENTER_FUNC(); 909 return CreateTemporalTimeZoneFromIndex(isolate, target, new_target, 0); 910} 911 912bool IsUTC(Isolate* isolate, Handle<String> time_zone); 913 914// #sec-temporal-createtemporaltimezone 915MaybeHandle<JSTemporalTimeZone> CreateTemporalTimeZone( 916 Isolate* isolate, Handle<JSFunction> target, Handle<HeapObject> new_target, 917 Handle<String> identifier) { 918 TEMPORAL_ENTER_FUNC(); 919 // 1. If newTarget is not present, set it to %Temporal.TimeZone%. 920 // 2. Let object be ? OrdinaryCreateFromConstructor(newTarget, 921 // "%Temporal.TimeZone.prototype%", « [[InitializedTemporalTimeZone]], 922 // [[Identifier]], [[OffsetNanoseconds]] »). 923 // 3. Set object.[[Identifier]] to identifier. 924 if (IsUTC(isolate, identifier)) { 925 return CreateTemporalTimeZoneUTC(isolate, target, new_target); 926 } 927#ifdef V8_INTL_SUPPORT 928 int32_t time_zone_index; 929 Maybe<bool> maybe_time_zone_index = 930 Intl::GetTimeZoneIndex(isolate, identifier, &time_zone_index); 931 MAYBE_RETURN(maybe_time_zone_index, Handle<JSTemporalTimeZone>()); 932 if (maybe_time_zone_index.FromJust()) { 933 return CreateTemporalTimeZoneFromIndex(isolate, target, new_target, 934 time_zone_index); 935 } 936#endif // V8_INTL_SUPPORT 937 938 // 4. If identifier satisfies the syntax of a TimeZoneNumericUTCOffset 939 // (see 13.33), then a. Set object.[[OffsetNanoseconds]] to ! 940 // ParseTimeZoneOffsetString(identifier). 941 // 5. Else, 942 // a. Assert: ! CanonicalizeTimeZoneName(identifier) is identifier. 943 // b. Set object.[[OffsetNanoseconds]] to undefined. 944 // 6. Return object. 945 Maybe<int64_t> maybe_offset_nanoseconds = 946 ParseTimeZoneOffsetString(isolate, identifier, false); 947 MAYBE_RETURN(maybe_offset_nanoseconds, Handle<JSTemporalTimeZone>()); 948 int64_t offset_nanoseconds = maybe_offset_nanoseconds.FromJust(); 949 950 ORDINARY_CREATE_FROM_CONSTRUCTOR(object, target, new_target, 951 JSTemporalTimeZone) 952 object->set_flags(0); 953 object->set_details(0); 954 955 object->set_is_offset(true); 956 object->set_offset_nanoseconds(offset_nanoseconds); 957 return object; 958} 959 960MaybeHandle<JSTemporalTimeZone> CreateTemporalTimeZoneDefaultTarget( 961 Isolate* isolate, Handle<String> identifier) { 962 TEMPORAL_ENTER_FUNC(); 963 return CreateTemporalTimeZone(isolate, CONSTRUCTOR(time_zone), 964 CONSTRUCTOR(time_zone), identifier); 965} 966 967} // namespace 968 969namespace temporal { 970MaybeHandle<JSTemporalTimeZone> CreateTemporalTimeZone( 971 Isolate* isolate, Handle<String> identifier) { 972 return CreateTemporalTimeZoneDefaultTarget(isolate, identifier); 973} 974} // namespace temporal 975 976namespace { 977 978// #sec-temporal-systeminstant 979MaybeHandle<JSTemporalInstant> SystemInstant(Isolate* isolate) { 980 TEMPORAL_ENTER_FUNC(); 981 // 1. Let ns be ! SystemUTCEpochNanoseconds(). 982 Handle<BigInt> ns; 983 ASSIGN_RETURN_ON_EXCEPTION(isolate, ns, SystemUTCEpochNanoseconds(isolate), 984 JSTemporalInstant); 985 // 2. Return ? CreateTemporalInstant(ns). 986 return temporal::CreateTemporalInstant(isolate, ns); 987} 988 989// #sec-temporal-systemtimezone 990MaybeHandle<JSTemporalTimeZone> SystemTimeZone(Isolate* isolate) { 991 TEMPORAL_ENTER_FUNC(); 992 Handle<String> default_time_zone; 993 ASSIGN_RETURN_ON_EXCEPTION(isolate, default_time_zone, 994 DefaultTimeZone(isolate), JSTemporalTimeZone); 995 return temporal::CreateTemporalTimeZone(isolate, default_time_zone); 996} 997 998Maybe<DateTimeRecordCommon> GetISOPartsFromEpoch( 999 Isolate* isolate, Handle<BigInt> epoch_nanoseconds) { 1000 TEMPORAL_ENTER_FUNC(); 1001 DateTimeRecordCommon result; 1002 // 1. Let remainderNs be epochNanoseconds modulo 10^6. 1003 Handle<BigInt> million = BigInt::FromInt64(isolate, 1000000); 1004 Handle<BigInt> remainder_ns; 1005 ASSIGN_RETURN_ON_EXCEPTION_VALUE( 1006 isolate, remainder_ns, 1007 BigInt::Remainder(isolate, epoch_nanoseconds, million), 1008 Nothing<DateTimeRecordCommon>()); 1009 // Need to do some remainder magic to negative remainder. 1010 if (remainder_ns->IsNegative()) { 1011 ASSIGN_RETURN_ON_EXCEPTION_VALUE( 1012 isolate, remainder_ns, BigInt::Add(isolate, remainder_ns, million), 1013 Nothing<DateTimeRecordCommon>()); 1014 } 1015 1016 // 2. Let epochMilliseconds be (epochNanoseconds − remainderNs) / 10^6. 1017 Handle<BigInt> bigint; 1018 ASSIGN_RETURN_ON_EXCEPTION_VALUE( 1019 isolate, bigint, 1020 BigInt::Subtract(isolate, epoch_nanoseconds, remainder_ns), 1021 Nothing<DateTimeRecordCommon>()); 1022 ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, bigint, 1023 BigInt::Divide(isolate, bigint, million), 1024 Nothing<DateTimeRecordCommon>()); 1025 int64_t epoch_milliseconds = bigint->AsInt64(); 1026 int year = 0; 1027 int month = 0; 1028 int day = 0; 1029 int wday = 0; 1030 int hour = 0; 1031 int min = 0; 1032 int sec = 0; 1033 int ms = 0; 1034 isolate->date_cache()->BreakDownTime(epoch_milliseconds, &year, &month, &day, 1035 &wday, &hour, &min, &sec, &ms); 1036 1037 // 3. Let year be ! YearFromTime(epochMilliseconds). 1038 result.year = year; 1039 // 4. Let month be ! MonthFromTime(epochMilliseconds) + 1. 1040 result.month = month + 1; 1041 DCHECK_GE(result.month, 1); 1042 DCHECK_LE(result.month, 12); 1043 // 5. Let day be ! DateFromTime(epochMilliseconds). 1044 result.day = day; 1045 DCHECK_GE(result.day, 1); 1046 DCHECK_LE(result.day, 31); 1047 // 6. Let hour be ! HourFromTime(epochMilliseconds). 1048 result.hour = hour; 1049 DCHECK_GE(result.hour, 0); 1050 DCHECK_LE(result.hour, 23); 1051 // 7. Let minute be ! MinFromTime(epochMilliseconds). 1052 result.minute = min; 1053 DCHECK_GE(result.minute, 0); 1054 DCHECK_LE(result.minute, 59); 1055 // 8. Let second be ! SecFromTime(epochMilliseconds). 1056 result.second = sec; 1057 DCHECK_GE(result.second, 0); 1058 DCHECK_LE(result.second, 59); 1059 // 9. Let millisecond be ! msFromTime(epochMilliseconds). 1060 result.millisecond = ms; 1061 DCHECK_GE(result.millisecond, 0); 1062 DCHECK_LE(result.millisecond, 999); 1063 // 10. Let microsecond be floor(remainderNs / 1000) modulo 1000. 1064 int64_t remainder = remainder_ns->AsInt64(); 1065 result.microsecond = (remainder / 1000) % 1000; 1066 DCHECK_GE(result.microsecond, 0); 1067 DCHECK_LE(result.microsecond, 999); 1068 // 11. Let nanosecond be remainderNs modulo 1000. 1069 result.nanosecond = remainder % 1000; 1070 DCHECK_GE(result.nanosecond, 0); 1071 DCHECK_LE(result.nanosecond, 999); 1072 return Just(result); 1073} 1074 1075// #sec-temporal-balanceisodatetime 1076DateTimeRecordCommon BalanceISODateTime(Isolate* isolate, int32_t year, 1077 int32_t month, int32_t day, 1078 int32_t hour, int32_t minute, 1079 int32_t second, int32_t millisecond, 1080 int32_t microsecond, 1081 int64_t nanosecond) { 1082 TEMPORAL_ENTER_FUNC(); 1083 // 1. Assert: year, month, day, hour, minute, second, millisecond, 1084 // microsecond, and nanosecond are integers. 1085 // 2. Let balancedTime be ! BalanceTime(hour, minute, second, millisecond, 1086 // microsecond, nanosecond). 1087 DateTimeRecordCommon balanced_time = BalanceTime( 1088 isolate, hour, minute, second, millisecond, microsecond, nanosecond); 1089 // 3. Let balancedDate be ! BalanceISODate(year, month, day + 1090 // balancedTime.[[Days]]). 1091 day += balanced_time.day; 1092 BalanceISODate(isolate, &year, &month, &day); 1093 // 4. Return the Record { [[Year]]: balancedDate.[[Year]], [[Month]]: 1094 // balancedDate.[[Month]], [[Day]]: balancedDate.[[Day]], [[Hour]]: 1095 // balancedTime.[[Hour]], [[Minute]]: balancedTime.[[Minute]], [[Second]]: 1096 // balancedTime.[[Second]], [[Millisecond]]: balancedTime.[[Millisecond]], 1097 // [[Microsecond]]: balancedTime.[[Microsecond]], [[Nanosecond]]: 1098 // balancedTime.[[Nanosecond]] }. 1099 return {year, 1100 month, 1101 day, 1102 balanced_time.hour, 1103 balanced_time.minute, 1104 balanced_time.second, 1105 balanced_time.millisecond, 1106 balanced_time.microsecond, 1107 balanced_time.nanosecond}; 1108} 1109 1110} // namespace 1111 1112namespace temporal { 1113MaybeHandle<JSTemporalPlainDateTime> BuiltinTimeZoneGetPlainDateTimeFor( 1114 Isolate* isolate, Handle<JSReceiver> time_zone, 1115 Handle<JSTemporalInstant> instant, Handle<JSReceiver> calendar, 1116 const char* method_name) { 1117 TEMPORAL_ENTER_FUNC(); 1118 // 1. Let offsetNanoseconds be ? GetOffsetNanosecondsFor(timeZone, instant). 1119 Maybe<int64_t> maybe_offset_nanoseconds = 1120 GetOffsetNanosecondsFor(isolate, time_zone, instant, method_name); 1121 MAYBE_RETURN(maybe_offset_nanoseconds, Handle<JSTemporalPlainDateTime>()); 1122 // 2. Let result be ! GetISOPartsFromEpoch(instant.[[Nanoseconds]]). 1123 Maybe<DateTimeRecordCommon> maybe_result = GetISOPartsFromEpoch( 1124 isolate, Handle<BigInt>(instant->nanoseconds(), isolate)); 1125 MAYBE_RETURN(maybe_result, Handle<JSTemporalPlainDateTime>()); 1126 int64_t offset_nanoseconds = maybe_offset_nanoseconds.FromJust(); 1127 1128 // 3. Set result to ! BalanceISODateTime(result.[[Year]], result.[[Month]], 1129 // result.[[Day]], result.[[Hour]], result.[[Minute]], result.[[Second]], 1130 // result.[[Millisecond]], result.[[Microsecond]], result.[[Nanosecond]] + 1131 // offsetNanoseconds). 1132 DateTimeRecordCommon result = maybe_result.FromJust(); 1133 result = BalanceISODateTime(isolate, result.year, result.month, result.day, 1134 result.hour, result.minute, result.second, 1135 result.millisecond, result.microsecond, 1136 offset_nanoseconds + result.nanosecond); 1137 // 4. Return ? CreateTemporalDateTime(result.[[Year]], result.[[Month]], 1138 // result.[[Day]], result.[[Hour]], result.[[Minute]], result.[[Second]], 1139 // result.[[Millisecond]], result.[[Microsecond]], result.[[Nanosecond]], 1140 // calendar). 1141 return temporal::CreateTemporalDateTime( 1142 isolate, result.year, result.month, result.day, result.hour, 1143 result.minute, result.second, result.millisecond, result.microsecond, 1144 result.nanosecond, calendar); 1145} 1146 1147} // namespace temporal 1148 1149namespace { 1150// #sec-temporal-getpossibleinstantsfor 1151MaybeHandle<FixedArray> GetPossibleInstantsFor(Isolate* isolate, 1152 Handle<JSReceiver> time_zone, 1153 Handle<Object> date_time) { 1154 TEMPORAL_ENTER_FUNC(); 1155 // 1. Let possibleInstants be ? Invoke(timeZone, "getPossibleInstantsFor", « 1156 // dateTime »). 1157 Handle<Object> function; 1158 ASSIGN_RETURN_ON_EXCEPTION( 1159 isolate, function, 1160 Object::GetProperty(isolate, time_zone, 1161 isolate->factory()->getPossibleInstantsFor_string()), 1162 FixedArray); 1163 if (!function->IsCallable()) { 1164 THROW_NEW_ERROR( 1165 isolate, 1166 NewTypeError(MessageTemplate::kCalledNonCallable, 1167 isolate->factory()->getPossibleInstantsFor_string()), 1168 FixedArray); 1169 } 1170 Handle<Object> possible_instants; 1171 { 1172 Handle<Object> argv[] = {date_time}; 1173 ASSIGN_RETURN_ON_EXCEPTION( 1174 isolate, possible_instants, 1175 Execution::Call(isolate, function, time_zone, arraysize(argv), argv), 1176 FixedArray); 1177 } 1178 1179 // Step 4-6 of GetPossibleInstantsFor is implemented inside 1180 // temporal_instant_fixed_array_from_iterable. 1181 { 1182 Handle<Object> argv[] = {possible_instants}; 1183 ASSIGN_RETURN_ON_EXCEPTION( 1184 isolate, possible_instants, 1185 Execution::CallBuiltin( 1186 isolate, isolate->temporal_instant_fixed_array_from_iterable(), 1187 possible_instants, arraysize(argv), argv), 1188 FixedArray); 1189 } 1190 DCHECK(possible_instants->IsFixedArray()); 1191 // 7. Return list. 1192 return Handle<FixedArray>::cast(possible_instants); 1193} 1194 1195// #sec-temporal-disambiguatepossibleinstants 1196MaybeHandle<JSTemporalInstant> DisambiguatePossibleInstants( 1197 Isolate* isolate, Handle<FixedArray> possible_instants, 1198 Handle<JSReceiver> time_zone, Handle<Object> date_time_obj, 1199 Disambiguation disambiguation, const char* method_name) { 1200 TEMPORAL_ENTER_FUNC(); 1201 // 1. Assert: dateTime has an [[InitializedTemporalDateTime]] internal slot. 1202 DCHECK(date_time_obj->IsJSTemporalPlainDateTime()); 1203 Handle<JSTemporalPlainDateTime> date_time = 1204 Handle<JSTemporalPlainDateTime>::cast(date_time_obj); 1205 1206 // 2. Let n be possibleInstants's length. 1207 int32_t n = possible_instants->length(); 1208 1209 // 3. If n = 1, then 1210 if (n == 1) { 1211 // a. Return possibleInstants[0]. 1212 Handle<Object> ret_obj = FixedArray::get(*possible_instants, 0, isolate); 1213 DCHECK(ret_obj->IsJSTemporalInstant()); 1214 return Handle<JSTemporalInstant>::cast(ret_obj); 1215 } 1216 // 4. If n ≠ 0, then 1217 if (n != 0) { 1218 // a. If disambiguation is "earlier" or "compatible", then 1219 if (disambiguation == Disambiguation::kEarlier || 1220 disambiguation == Disambiguation::kCompatible) { 1221 // i. Return possibleInstants[0]. 1222 Handle<Object> ret_obj = FixedArray::get(*possible_instants, 0, isolate); 1223 DCHECK(ret_obj->IsJSTemporalInstant()); 1224 return Handle<JSTemporalInstant>::cast(ret_obj); 1225 } 1226 // b. If disambiguation is "later", then 1227 if (disambiguation == Disambiguation::kLater) { 1228 // i. Return possibleInstants[n − 1]. 1229 Handle<Object> ret_obj = 1230 FixedArray::get(*possible_instants, n - 1, isolate); 1231 DCHECK(ret_obj->IsJSTemporalInstant()); 1232 return Handle<JSTemporalInstant>::cast(ret_obj); 1233 } 1234 // c. Assert: disambiguation is "reject". 1235 DCHECK_EQ(disambiguation, Disambiguation::kReject); 1236 // d. Throw a RangeError exception. 1237 THROW_NEW_ERROR(isolate, NEW_TEMPORAL_INVALD_ARG_RANGE_ERROR(), 1238 JSTemporalInstant); 1239 } 1240 // 5. Assert: n = 0. 1241 DCHECK_EQ(n, 0); 1242 // 6. If disambiguation is "reject", then 1243 if (disambiguation == Disambiguation::kReject) { 1244 // a. Throw a RangeError exception. 1245 THROW_NEW_ERROR(isolate, NEW_TEMPORAL_INVALD_ARG_RANGE_ERROR(), 1246 JSTemporalInstant); 1247 } 1248 // 7. Let epochNanoseconds be ! GetEpochFromISOParts(dateTime.[[ISOYear]], 1249 // dateTime.[[ISOMonth]], dateTime.[[ISODay]], dateTime.[[ISOHour]], 1250 // dateTime.[[ISOMinute]], dateTime.[[ISOSecond]], 1251 // dateTime.[[ISOMillisecond]], dateTime.[[ISOMicrosecond]], 1252 // dateTime.[[ISONanosecond]]). 1253 Handle<BigInt> epoch_nanoseconds; 1254 ASSIGN_RETURN_ON_EXCEPTION( 1255 isolate, epoch_nanoseconds, 1256 GetEpochFromISOParts( 1257 isolate, date_time->iso_year(), date_time->iso_month(), 1258 date_time->iso_day(), date_time->iso_hour(), date_time->iso_minute(), 1259 date_time->iso_second(), date_time->iso_millisecond(), 1260 date_time->iso_microsecond(), date_time->iso_nanosecond()), 1261 JSTemporalInstant); 1262 1263 // 8. Let dayBefore be ! CreateTemporalInstant(epochNanoseconds − 8.64 × 1264 // 10^13). 1265 Handle<BigInt> one_day_in_ns = BigInt::FromUint64(isolate, 86400000000000ULL); 1266 Handle<BigInt> day_before_ns; 1267 ASSIGN_RETURN_ON_EXCEPTION( 1268 isolate, day_before_ns, 1269 BigInt::Subtract(isolate, epoch_nanoseconds, one_day_in_ns), 1270 JSTemporalInstant); 1271 Handle<JSTemporalInstant> day_before; 1272 ASSIGN_RETURN_ON_EXCEPTION( 1273 isolate, day_before, 1274 temporal::CreateTemporalInstant(isolate, day_before_ns), 1275 JSTemporalInstant); 1276 // 9. Let dayAfter be ! CreateTemporalInstant(epochNanoseconds + 8.64 × 1277 // 10^13). 1278 Handle<BigInt> day_after_ns; 1279 ASSIGN_RETURN_ON_EXCEPTION( 1280 isolate, day_after_ns, 1281 BigInt::Add(isolate, epoch_nanoseconds, one_day_in_ns), 1282 JSTemporalInstant); 1283 Handle<JSTemporalInstant> day_after; 1284 ASSIGN_RETURN_ON_EXCEPTION( 1285 isolate, day_after, 1286 temporal::CreateTemporalInstant(isolate, day_after_ns), 1287 JSTemporalInstant); 1288 // 10. Let offsetBefore be ? GetOffsetNanosecondsFor(timeZone, dayBefore). 1289 Maybe<int64_t> maybe_offset_before = 1290 GetOffsetNanosecondsFor(isolate, time_zone, day_before, method_name); 1291 MAYBE_RETURN(maybe_offset_before, Handle<JSTemporalInstant>()); 1292 // 11. Let offsetAfter be ? GetOffsetNanosecondsFor(timeZone, dayAfter). 1293 Maybe<int64_t> maybe_offset_after = 1294 GetOffsetNanosecondsFor(isolate, time_zone, day_after, method_name); 1295 MAYBE_RETURN(maybe_offset_after, Handle<JSTemporalInstant>()); 1296 1297 // 12. Let nanoseconds be offsetAfter − offsetBefore. 1298 int64_t nanoseconds = 1299 maybe_offset_after.FromJust() - maybe_offset_before.FromJust(); 1300 1301 // 13. If disambiguation is "earlier", then 1302 if (disambiguation == Disambiguation::kEarlier) { 1303 // a. Let earlier be ? AddDateTime(dateTime.[[ISOYear]], 1304 // dateTime.[[ISOMonth]], dateTime.[[ISODay]], dateTime.[[ISOHour]], 1305 // dateTime.[[ISOMinute]], dateTime.[[ISOSecond]], 1306 // dateTime.[[ISOMillisecond]], 1307 // dateTime.[[ISOMicrosecond]], dateTime.[[ISONanosecond]], 1308 // dateTime.[[Calendar]], 0, 0, 0, 0, 0, 0, 0, 0, 0, −nanoseconds, 1309 // undefined). 1310 Maybe<DateTimeRecordCommon> maybe_earlier = AddDateTime( 1311 isolate, date_time->iso_year(), date_time->iso_month(), 1312 date_time->iso_day(), date_time->iso_hour(), date_time->iso_minute(), 1313 date_time->iso_second(), date_time->iso_millisecond(), 1314 date_time->iso_microsecond(), date_time->iso_nanosecond(), 1315 handle(date_time->calendar(), isolate), 1316 {0, 0, 0, 0, 0, 0, 0, 0, 0, -nanoseconds}, 1317 isolate->factory()->undefined_value()); 1318 MAYBE_RETURN(maybe_earlier, Handle<JSTemporalInstant>()); 1319 DateTimeRecordCommon earlier = maybe_earlier.FromJust(); 1320 1321 // See https://github.com/tc39/proposal-temporal/issues/1816 1322 // b. Let earlierDateTime be ? CreateTemporalDateTime(earlier.[[Year]], 1323 // earlier.[[Month]], earlier.[[Day]], earlier.[[Hour]], earlier.[[Minute]], 1324 // earlier.[[Second]], earlier.[[Millisecond]], earlier.[[Microsecond]], 1325 // earlier.[[Nanosecond]], dateTime.[[Calendar]]). 1326 Handle<JSTemporalPlainDateTime> earlier_date_time; 1327 ASSIGN_RETURN_ON_EXCEPTION( 1328 isolate, earlier_date_time, 1329 temporal::CreateTemporalDateTime( 1330 isolate, earlier.year, earlier.month, earlier.day, earlier.hour, 1331 earlier.minute, earlier.second, earlier.millisecond, 1332 earlier.microsecond, earlier.nanosecond, 1333 handle(date_time->calendar(), isolate)), 1334 JSTemporalInstant); 1335 1336 // c. Set possibleInstants to ? GetPossibleInstantsFor(timeZone, 1337 // earlierDateTime). 1338 ASSIGN_RETURN_ON_EXCEPTION( 1339 isolate, possible_instants, 1340 GetPossibleInstantsFor(isolate, time_zone, earlier_date_time), 1341 JSTemporalInstant); 1342 1343 // d. If possibleInstants is empty, throw a RangeError exception. 1344 if (possible_instants->length() == 0) { 1345 THROW_NEW_ERROR(isolate, NEW_TEMPORAL_INVALD_ARG_RANGE_ERROR(), 1346 JSTemporalInstant); 1347 } 1348 // e. Return possibleInstants[0]. 1349 Handle<Object> ret_obj = FixedArray::get(*possible_instants, 0, isolate); 1350 DCHECK(ret_obj->IsJSTemporalInstant()); 1351 return Handle<JSTemporalInstant>::cast(ret_obj); 1352 } 1353 // 14. Assert: disambiguation is "compatible" or "later". 1354 DCHECK(disambiguation == Disambiguation::kCompatible || 1355 disambiguation == Disambiguation::kLater); 1356 // 15. Let later be ? AddDateTime(dateTime.[[ISOYear]], dateTime.[[ISOMonth]], 1357 // dateTime.[[ISODay]], dateTime.[[ISOHour]], dateTime.[[ISOMinute]], 1358 // dateTime.[[ISOSecond]], dateTime.[[ISOMillisecond]], 1359 // dateTime.[[ISOMicrosecond]], dateTime.[[ISONanosecond]], 1360 // dateTime.[[Calendar]], 0, 0, 0, 0, 0, 0, 0, 0, 0, nanoseconds, undefined). 1361 Maybe<DateTimeRecordCommon> maybe_later = AddDateTime( 1362 isolate, date_time->iso_year(), date_time->iso_month(), 1363 date_time->iso_day(), date_time->iso_hour(), date_time->iso_minute(), 1364 date_time->iso_second(), date_time->iso_millisecond(), 1365 date_time->iso_microsecond(), date_time->iso_nanosecond(), 1366 handle(date_time->calendar(), isolate), 1367 {0, 0, 0, 0, 0, 0, 0, 0, 0, nanoseconds}, 1368 isolate->factory()->undefined_value()); 1369 MAYBE_RETURN(maybe_later, Handle<JSTemporalInstant>()); 1370 DateTimeRecordCommon later = maybe_later.FromJust(); 1371 1372 // See https://github.com/tc39/proposal-temporal/issues/1816 1373 // 16. Let laterDateTime be ? CreateTemporalDateTime(later.[[Year]], 1374 // later.[[Month]], later.[[Day]], later.[[Hour]], later.[[Minute]], 1375 // later.[[Second]], later.[[Millisecond]], later.[[Microsecond]], 1376 // later.[[Nanosecond]], dateTime.[[Calendar]]). 1377 1378 Handle<JSTemporalPlainDateTime> later_date_time; 1379 ASSIGN_RETURN_ON_EXCEPTION( 1380 isolate, later_date_time, 1381 temporal::CreateTemporalDateTime( 1382 isolate, later.year, later.month, later.day, later.hour, later.minute, 1383 later.second, later.millisecond, later.microsecond, later.nanosecond, 1384 handle(date_time->calendar(), isolate)), 1385 JSTemporalInstant); 1386 // 17. Set possibleInstants to ? GetPossibleInstantsFor(timeZone, 1387 // laterDateTime). 1388 ASSIGN_RETURN_ON_EXCEPTION( 1389 isolate, possible_instants, 1390 GetPossibleInstantsFor(isolate, time_zone, later_date_time), 1391 JSTemporalInstant); 1392 // 18. Set n to possibleInstants's length. 1393 n = possible_instants->length(); 1394 // 19. If n = 0, throw a RangeError exception. 1395 if (n == 0) { 1396 THROW_NEW_ERROR(isolate, NEW_TEMPORAL_INVALD_ARG_RANGE_ERROR(), 1397 JSTemporalInstant); 1398 } 1399 // 20. Return possibleInstants[n − 1]. 1400 Handle<Object> ret_obj = FixedArray::get(*possible_instants, n - 1, isolate); 1401 DCHECK(ret_obj->IsJSTemporalInstant()); 1402 return Handle<JSTemporalInstant>::cast(ret_obj); 1403} 1404 1405// #sec-temporal-gettemporalcalendarwithisodefault 1406MaybeHandle<JSReceiver> GetTemporalCalendarWithISODefault( 1407 Isolate* isolate, Handle<JSReceiver> item, const char* method_name) { 1408 TEMPORAL_ENTER_FUNC(); 1409 1410 Factory* factory = isolate->factory(); 1411 // 1. If item has an [[InitializedTemporalDate]], 1412 // [[InitializedTemporalDateTime]], [[InitializedTemporalMonthDay]], 1413 // [[InitializedTemporalTime]], [[InitializedTemporalYearMonth]], or 1414 // [[InitializedTemporalZonedDateTime]] internal slot, then a. Return 1415 // item.[[Calendar]]. 1416 if (item->IsJSTemporalPlainDate()) { 1417 return handle(Handle<JSTemporalPlainDate>::cast(item)->calendar(), isolate); 1418 } 1419 if (item->IsJSTemporalPlainDateTime()) { 1420 return handle(Handle<JSTemporalPlainDateTime>::cast(item)->calendar(), 1421 isolate); 1422 } 1423 if (item->IsJSTemporalPlainMonthDay()) { 1424 return handle(Handle<JSTemporalPlainMonthDay>::cast(item)->calendar(), 1425 isolate); 1426 } 1427 if (item->IsJSTemporalPlainTime()) { 1428 return handle(Handle<JSTemporalPlainTime>::cast(item)->calendar(), isolate); 1429 } 1430 if (item->IsJSTemporalPlainYearMonth()) { 1431 return handle(Handle<JSTemporalPlainYearMonth>::cast(item)->calendar(), 1432 isolate); 1433 } 1434 if (item->IsJSTemporalZonedDateTime()) { 1435 return handle(Handle<JSTemporalZonedDateTime>::cast(item)->calendar(), 1436 isolate); 1437 } 1438 1439 // 2. Let calendar be ? Get(item, "calendar"). 1440 Handle<Object> calendar; 1441 ASSIGN_RETURN_ON_EXCEPTION( 1442 isolate, calendar, 1443 JSReceiver::GetProperty(isolate, item, factory->calendar_string()), 1444 JSReceiver); 1445 // 3. Return ? ToTemporalCalendarWithISODefault(calendar). 1446 return ToTemporalCalendarWithISODefault(isolate, calendar, method_name); 1447} 1448 1449enum class RequiredFields { kNone, kTimeZone, kTimeZoneAndOffset, kDay }; 1450 1451// The common part of PrepareTemporalFields and PreparePartialTemporalFields 1452// #sec-temporal-preparetemporalfields 1453// #sec-temporal-preparepartialtemporalfields 1454V8_WARN_UNUSED_RESULT MaybeHandle<JSObject> PrepareTemporalFieldsOrPartial( 1455 Isolate* isolate, Handle<JSReceiver> fields, Handle<FixedArray> field_names, 1456 RequiredFields required, bool partial) { 1457 TEMPORAL_ENTER_FUNC(); 1458 1459 Factory* factory = isolate->factory(); 1460 // 1. Assert: Type(fields) is Object. 1461 // 2. Let result be ! OrdinaryObjectCreate(%Object.prototype%). 1462 Handle<JSObject> result = 1463 isolate->factory()->NewJSObject(isolate->object_function()); 1464 // 3. For each value property of fieldNames, do 1465 int length = field_names->length(); 1466 bool any = false; 1467 for (int i = 0; i < length; i++) { 1468 Handle<Object> property_obj = Handle<Object>(field_names->get(i), isolate); 1469 Handle<String> property = Handle<String>::cast(property_obj); 1470 // a. Let value be ? Get(fields, property). 1471 Handle<Object> value; 1472 ASSIGN_RETURN_ON_EXCEPTION( 1473 isolate, value, JSReceiver::GetProperty(isolate, fields, property), 1474 JSObject); 1475 1476 // b. If value is undefined, then 1477 if (value->IsUndefined()) { 1478 // This part is only for PrepareTemporalFields 1479 // Skip for the case of PreparePartialTemporalFields. 1480 if (partial) continue; 1481 1482 // i. If requiredFields contains property, then 1483 if ((required == RequiredFields::kDay && 1484 String::Equals(isolate, property, factory->day_string())) || 1485 ((required == RequiredFields::kTimeZone || 1486 required == RequiredFields::kTimeZoneAndOffset) && 1487 String::Equals(isolate, property, factory->timeZone_string())) || 1488 (required == RequiredFields::kTimeZoneAndOffset && 1489 String::Equals(isolate, property, factory->offset_string()))) { 1490 // 1. Throw a TypeError exception. 1491 THROW_NEW_ERROR(isolate, NEW_TEMPORAL_INVALD_ARG_TYPE_ERROR(), 1492 JSObject); 1493 } 1494 // ii. Else, 1495 // 1. If property is in the Property column of Table 13, then 1496 // a. Set value to the corresponding Default value of the same row. 1497 if (String::Equals(isolate, property, factory->hour_string()) || 1498 String::Equals(isolate, property, factory->minute_string()) || 1499 String::Equals(isolate, property, factory->second_string()) || 1500 String::Equals(isolate, property, factory->millisecond_string()) || 1501 String::Equals(isolate, property, factory->microsecond_string()) || 1502 String::Equals(isolate, property, factory->nanosecond_string())) { 1503 value = Handle<Object>(Smi::zero(), isolate); 1504 } 1505 } else { 1506 // For both PrepareTemporalFields and PreparePartialTemporalFields 1507 any = partial; 1508 // c. Else, 1509 // i. If property is in the Property column of Table 13 and there is a 1510 // Conversion value in the same row, then 1511 // 1. Let Conversion represent the abstract operation named by the 1512 // Conversion value of the same row. 1513 // 2. Set value to ? Conversion(value). 1514 if (String::Equals(isolate, property, factory->month_string()) || 1515 String::Equals(isolate, property, factory->day_string())) { 1516 ASSIGN_RETURN_ON_EXCEPTION(isolate, value, 1517 ToPositiveInteger(isolate, value), JSObject); 1518 } else if (String::Equals(isolate, property, factory->year_string()) || 1519 String::Equals(isolate, property, factory->hour_string()) || 1520 String::Equals(isolate, property, factory->minute_string()) || 1521 String::Equals(isolate, property, factory->second_string()) || 1522 String::Equals(isolate, property, 1523 factory->millisecond_string()) || 1524 String::Equals(isolate, property, 1525 factory->microsecond_string()) || 1526 String::Equals(isolate, property, 1527 factory->nanosecond_string()) || 1528 String::Equals(isolate, property, factory->eraYear_string())) { 1529 ASSIGN_RETURN_ON_EXCEPTION( 1530 isolate, value, ToIntegerThrowOnInfinity(isolate, value), JSObject); 1531 } else if (String::Equals(isolate, property, 1532 factory->monthCode_string()) || 1533 String::Equals(isolate, property, factory->offset_string()) || 1534 String::Equals(isolate, property, factory->era_string())) { 1535 ASSIGN_RETURN_ON_EXCEPTION(isolate, value, 1536 Object::ToString(isolate, value), JSObject); 1537 } 1538 } 1539 1540 // d. Perform ! CreateDataPropertyOrThrow(result, property, value). 1541 CHECK(JSReceiver::CreateDataProperty(isolate, result, property, value, 1542 Just(kThrowOnError)) 1543 .FromJust()); 1544 } 1545 1546 // Only for PreparePartialTemporalFields 1547 if (partial) { 1548 // 5. If any is false, then 1549 if (!any) { 1550 // a. Throw a TypeError exception. 1551 THROW_NEW_ERROR(isolate, NEW_TEMPORAL_INVALD_ARG_TYPE_ERROR(), JSObject); 1552 } 1553 } 1554 // 4. Return result. 1555 return result; 1556} 1557 1558// #sec-temporal-preparetemporalfields 1559V8_WARN_UNUSED_RESULT MaybeHandle<JSObject> PrepareTemporalFields( 1560 Isolate* isolate, Handle<JSReceiver> fields, Handle<FixedArray> field_names, 1561 RequiredFields required) { 1562 TEMPORAL_ENTER_FUNC(); 1563 1564 return PrepareTemporalFieldsOrPartial(isolate, fields, field_names, required, 1565 false); 1566} 1567 1568// Template for DateFromFields, YearMonthFromFields, and MonthDayFromFields 1569template <typename T> 1570MaybeHandle<T> FromFields(Isolate* isolate, Handle<JSReceiver> calendar, 1571 Handle<JSReceiver> fields, Handle<Object> options, 1572 Handle<String> property, InstanceType type) { 1573 Handle<Object> function; 1574 ASSIGN_RETURN_ON_EXCEPTION( 1575 isolate, function, Object::GetProperty(isolate, calendar, property), T); 1576 if (!function->IsCallable()) { 1577 THROW_NEW_ERROR(isolate, 1578 NewTypeError(MessageTemplate::kCalledNonCallable, property), 1579 T); 1580 } 1581 Handle<Object> argv[] = {fields, options}; 1582 Handle<Object> result; 1583 ASSIGN_RETURN_ON_EXCEPTION( 1584 isolate, result, Execution::Call(isolate, function, calendar, 2, argv), 1585 T); 1586 if ((!result->IsHeapObject()) || 1587 HeapObject::cast(*result).map().instance_type() != type) { 1588 THROW_NEW_ERROR(isolate, NEW_TEMPORAL_INVALD_ARG_TYPE_ERROR(), T); 1589 } 1590 return Handle<T>::cast(result); 1591} 1592 1593// #sec-temporal-datefromfields 1594MaybeHandle<JSTemporalPlainDate> DateFromFields(Isolate* isolate, 1595 Handle<JSReceiver> calendar, 1596 Handle<JSReceiver> fields, 1597 Handle<Object> options) { 1598 return FromFields<JSTemporalPlainDate>( 1599 isolate, calendar, fields, options, 1600 isolate->factory()->dateFromFields_string(), JS_TEMPORAL_PLAIN_DATE_TYPE); 1601} 1602 1603// #sec-temporal-yearmonthfromfields 1604MaybeHandle<JSTemporalPlainYearMonth> YearMonthFromFields( 1605 Isolate* isolate, Handle<JSReceiver> calendar, Handle<JSReceiver> fields, 1606 Handle<Object> options) { 1607 return FromFields<JSTemporalPlainYearMonth>( 1608 isolate, calendar, fields, options, 1609 isolate->factory()->yearMonthFromFields_string(), 1610 JS_TEMPORAL_PLAIN_YEAR_MONTH_TYPE); 1611} 1612 1613// #sec-temporal-monthdayfromfields 1614MaybeHandle<JSTemporalPlainMonthDay> MonthDayFromFields( 1615 Isolate* isolate, Handle<JSReceiver> calendar, Handle<JSReceiver> fields, 1616 Handle<Object> options) { 1617 return FromFields<JSTemporalPlainMonthDay>( 1618 isolate, calendar, fields, options, 1619 isolate->factory()->monthDayFromFields_string(), 1620 JS_TEMPORAL_PLAIN_MONTH_DAY_TYPE); 1621} 1622 1623// #sec-temporal-totemporaloverflow 1624Maybe<ShowOverflow> ToTemporalOverflow(Isolate* isolate, 1625 Handle<JSReceiver> options, 1626 const char* method_name) { 1627 return GetStringOption<ShowOverflow>( 1628 isolate, options, "overflow", method_name, {"constrain", "reject"}, 1629 {ShowOverflow::kConstrain, ShowOverflow::kReject}, 1630 ShowOverflow::kConstrain); 1631} 1632 1633// #sec-temporal-builtintimezonegetinstantfor 1634MaybeHandle<JSTemporalInstant> BuiltinTimeZoneGetInstantFor( 1635 Isolate* isolate, Handle<JSReceiver> time_zone, 1636 Handle<JSTemporalPlainDateTime> date_time, Disambiguation disambiguation, 1637 const char* method_name) { 1638 TEMPORAL_ENTER_FUNC(); 1639 // 1. Assert: dateTime has an [[InitializedTemporalDateTime]] internal slot. 1640 // 2. Let possibleInstants be ? GetPossibleInstantsFor(timeZone, dateTime). 1641 Handle<FixedArray> possible_instants; 1642 ASSIGN_RETURN_ON_EXCEPTION( 1643 isolate, possible_instants, 1644 GetPossibleInstantsFor(isolate, time_zone, date_time), JSTemporalInstant); 1645 // 3. Return ? DisambiguatePossibleInstants(possibleInstants, timeZone, 1646 // dateTime, disambiguation). 1647 return DisambiguatePossibleInstants(isolate, possible_instants, time_zone, 1648 date_time, disambiguation, method_name); 1649} 1650 1651// #sec-temporal-totemporalinstant 1652MaybeHandle<JSTemporalInstant> ToTemporalInstant(Isolate* isolate, 1653 Handle<Object> item, 1654 const char* method) { 1655 TEMPORAL_ENTER_FUNC(); 1656 1657 // 1. If Type(item) is Object, then 1658 // a. If item has an [[InitializedTemporalInstant]] internal slot, then 1659 if (item->IsJSTemporalInstant()) { 1660 // i. Return item. 1661 return Handle<JSTemporalInstant>::cast(item); 1662 } 1663 // b. If item has an [[InitializedTemporalZonedDateTime]] internal slot, then 1664 if (item->IsJSTemporalZonedDateTime()) { 1665 // i. Return ! CreateTemporalInstant(item.[[Nanoseconds]]). 1666 Handle<BigInt> nanoseconds = 1667 handle(JSTemporalZonedDateTime::cast(*item).nanoseconds(), isolate); 1668 return temporal::CreateTemporalInstant(isolate, nanoseconds); 1669 } 1670 // 2. Let string be ? ToString(item). 1671 Handle<String> string; 1672 ASSIGN_RETURN_ON_EXCEPTION(isolate, string, Object::ToString(isolate, item), 1673 JSTemporalInstant); 1674 1675 // 3. Let epochNanoseconds be ? ParseTemporalInstant(string). 1676 Handle<BigInt> epoch_nanoseconds; 1677 ASSIGN_RETURN_ON_EXCEPTION(isolate, epoch_nanoseconds, 1678 ParseTemporalInstant(isolate, string), 1679 JSTemporalInstant); 1680 1681 // 4. Return ? CreateTemporalInstant(ℤ(epochNanoseconds)). 1682 return temporal::CreateTemporalInstant(isolate, epoch_nanoseconds); 1683} 1684 1685} // namespace 1686 1687namespace temporal { 1688 1689// #sec-temporal-totemporalcalendar 1690MaybeHandle<JSReceiver> ToTemporalCalendar( 1691 Isolate* isolate, Handle<Object> temporal_calendar_like, 1692 const char* method_name) { 1693 Factory* factory = isolate->factory(); 1694 // 1.If Type(temporalCalendarLike) is Object, then 1695 if (temporal_calendar_like->IsJSReceiver()) { 1696 // a. If temporalCalendarLike has an [[InitializedTemporalDate]], 1697 // [[InitializedTemporalDateTime]], [[InitializedTemporalMonthDay]], 1698 // [[InitializedTemporalTime]], [[InitializedTemporalYearMonth]], or 1699 // [[InitializedTemporalZonedDateTime]] internal slot, then i. Return 1700 // temporalCalendarLike.[[Calendar]]. 1701 1702#define EXTRACT_CALENDAR(T, obj) \ 1703 if (obj->IsJSTemporal##T()) { \ 1704 return handle(Handle<JSTemporal##T>::cast(obj)->calendar(), isolate); \ 1705 } 1706 1707 EXTRACT_CALENDAR(PlainDate, temporal_calendar_like) 1708 EXTRACT_CALENDAR(PlainDateTime, temporal_calendar_like) 1709 EXTRACT_CALENDAR(PlainMonthDay, temporal_calendar_like) 1710 EXTRACT_CALENDAR(PlainTime, temporal_calendar_like) 1711 EXTRACT_CALENDAR(PlainYearMonth, temporal_calendar_like) 1712 EXTRACT_CALENDAR(ZonedDateTime, temporal_calendar_like) 1713 1714#undef EXTRACT_CALENDAR 1715 Handle<JSReceiver> obj = Handle<JSReceiver>::cast(temporal_calendar_like); 1716 1717 // b. If ? HasProperty(temporalCalendarLike, "calendar") is false, return 1718 // temporalCalendarLike. 1719 Maybe<bool> maybe_has = 1720 JSReceiver::HasProperty(isolate, obj, factory->calendar_string()); 1721 1722 MAYBE_RETURN(maybe_has, Handle<JSReceiver>()); 1723 if (!maybe_has.FromJust()) { 1724 return obj; 1725 } 1726 // c. Set temporalCalendarLike to ? Get(temporalCalendarLike, "calendar"). 1727 ASSIGN_RETURN_ON_EXCEPTION( 1728 isolate, temporal_calendar_like, 1729 JSReceiver::GetProperty(isolate, obj, factory->calendar_string()), 1730 JSReceiver); 1731 // d. If Type(temporalCalendarLike) is Object 1732 if (temporal_calendar_like->IsJSReceiver()) { 1733 obj = Handle<JSReceiver>::cast(temporal_calendar_like); 1734 // and ? HasProperty(temporalCalendarLike, "calendar") is false, 1735 maybe_has = 1736 JSReceiver::HasProperty(isolate, obj, factory->calendar_string()); 1737 MAYBE_RETURN(maybe_has, Handle<JSReceiver>()); 1738 if (!maybe_has.FromJust()) { 1739 // return temporalCalendarLike. 1740 return obj; 1741 } 1742 } 1743 } 1744 1745 // 2. Let identifier be ? ToString(temporalCalendarLike). 1746 Handle<String> identifier; 1747 ASSIGN_RETURN_ON_EXCEPTION(isolate, identifier, 1748 Object::ToString(isolate, temporal_calendar_like), 1749 JSReceiver); 1750 // 3. If ! IsBuiltinCalendar(identifier) is false, then 1751 if (!IsBuiltinCalendar(isolate, identifier)) { 1752 // a. Let identifier be ? ParseTemporalCalendarString(identifier). 1753 ASSIGN_RETURN_ON_EXCEPTION(isolate, identifier, 1754 ParseTemporalCalendarString(isolate, identifier), 1755 JSReceiver); 1756 } 1757 // 4. Return ? CreateTemporalCalendar(identifier). 1758 return CreateTemporalCalendar(isolate, identifier); 1759} 1760 1761} // namespace temporal 1762 1763namespace { 1764// #sec-temporal-totemporalcalendarwithisodefault 1765MaybeHandle<JSReceiver> ToTemporalCalendarWithISODefault( 1766 Isolate* isolate, Handle<Object> temporal_calendar_like, 1767 const char* method_name) { 1768 TEMPORAL_ENTER_FUNC(); 1769 1770 // 1. If temporalCalendarLike is undefined, then 1771 if (temporal_calendar_like->IsUndefined()) { 1772 // a. Return ? GetISO8601Calendar(). 1773 return temporal::GetISO8601Calendar(isolate); 1774 } 1775 // 2. Return ? ToTemporalCalendar(temporalCalendarLike). 1776 return temporal::ToTemporalCalendar(isolate, temporal_calendar_like, 1777 method_name); 1778} 1779 1780// #sec-temporal-totemporaldate 1781MaybeHandle<JSTemporalPlainDate> ToTemporalDate(Isolate* isolate, 1782 Handle<Object> item_obj, 1783 Handle<JSReceiver> options, 1784 const char* method_name) { 1785 TEMPORAL_ENTER_FUNC(); 1786 1787 Factory* factory = isolate->factory(); 1788 // 2. Assert: Type(options) is Object. 1789 // 3. If Type(item) is Object, then 1790 if (item_obj->IsJSReceiver()) { 1791 Handle<JSReceiver> item = Handle<JSReceiver>::cast(item_obj); 1792 // a. If item has an [[InitializedTemporalDate]] internal slot, then 1793 // i. Return item. 1794 if (item->IsJSTemporalPlainDate()) { 1795 return Handle<JSTemporalPlainDate>::cast(item); 1796 } 1797 // b. If item has an [[InitializedTemporalZonedDateTime]] internal slot, 1798 // then 1799 if (item->IsJSTemporalZonedDateTime()) { 1800 // i. Let instant be ! CreateTemporalInstant(item.[[Nanoseconds]]). 1801 Handle<JSTemporalZonedDateTime> zoned_date_time = 1802 Handle<JSTemporalZonedDateTime>::cast(item); 1803 Handle<JSTemporalInstant> instant; 1804 ASSIGN_RETURN_ON_EXCEPTION( 1805 isolate, instant, 1806 temporal::CreateTemporalInstant( 1807 isolate, Handle<BigInt>(zoned_date_time->nanoseconds(), isolate)), 1808 JSTemporalPlainDate); 1809 // ii. Let plainDateTime be ? 1810 // BuiltinTimeZoneGetPlainDateTimeFor(item.[[TimeZone]], 1811 // instant, item.[[Calendar]]). 1812 Handle<JSTemporalPlainDateTime> plain_date_time; 1813 ASSIGN_RETURN_ON_EXCEPTION( 1814 isolate, plain_date_time, 1815 temporal::BuiltinTimeZoneGetPlainDateTimeFor( 1816 isolate, 1817 Handle<JSReceiver>(zoned_date_time->time_zone(), isolate), 1818 instant, Handle<JSReceiver>(zoned_date_time->calendar(), isolate), 1819 method_name), 1820 JSTemporalPlainDate); 1821 // iii. Return ! CreateTemporalDate(plainDateTime.[[ISOYear]], 1822 // plainDateTime.[[ISOMonth]], plainDateTime.[[ISODay]], 1823 // plainDateTime.[[Calendar]]). 1824 return CreateTemporalDate( 1825 isolate, plain_date_time->iso_year(), plain_date_time->iso_month(), 1826 plain_date_time->iso_day(), 1827 Handle<JSReceiver>(plain_date_time->calendar(), isolate)); 1828 } 1829 1830 // c. If item has an [[InitializedTemporalDateTime]] internal slot, then 1831 // i. Return ! CreateTemporalDate(item.[[ISOYear]], item.[[ISOMonth]], 1832 // item.[[ISODay]], item.[[Calendar]]). 1833 if (item->IsJSTemporalPlainDateTime()) { 1834 Handle<JSTemporalPlainDateTime> date_time = 1835 Handle<JSTemporalPlainDateTime>::cast(item); 1836 return CreateTemporalDate(isolate, date_time->iso_year(), 1837 date_time->iso_month(), date_time->iso_day(), 1838 handle(date_time->calendar(), isolate)); 1839 } 1840 1841 // d. Let calendar be ? GetTemporalCalendarWithISODefault(item). 1842 Handle<JSReceiver> calendar; 1843 ASSIGN_RETURN_ON_EXCEPTION( 1844 isolate, calendar, 1845 GetTemporalCalendarWithISODefault(isolate, item, method_name), 1846 JSTemporalPlainDate); 1847 // e. Let fieldNames be ? CalendarFields(calendar, « "day", "month", 1848 // "monthCode", "year" »). 1849 Handle<FixedArray> field_names = factory->NewFixedArray(4); 1850 field_names->set(0, ReadOnlyRoots(isolate).day_string()); 1851 field_names->set(1, ReadOnlyRoots(isolate).month_string()); 1852 field_names->set(2, ReadOnlyRoots(isolate).monthCode_string()); 1853 field_names->set(3, ReadOnlyRoots(isolate).year_string()); 1854 ASSIGN_RETURN_ON_EXCEPTION(isolate, field_names, 1855 CalendarFields(isolate, calendar, field_names), 1856 JSTemporalPlainDate); 1857 // f. Let fields be ? PrepareTemporalFields(item, 1858 // fieldNames, «»). 1859 Handle<JSReceiver> fields; 1860 ASSIGN_RETURN_ON_EXCEPTION(isolate, fields, 1861 PrepareTemporalFields(isolate, item, field_names, 1862 RequiredFields::kNone), 1863 JSTemporalPlainDate); 1864 // g. Return ? DateFromFields(calendar, fields, options). 1865 return DateFromFields(isolate, calendar, fields, options); 1866 } 1867 // 4. Perform ? ToTemporalOverflow(options). 1868 Maybe<ShowOverflow> maybe_overflow = 1869 ToTemporalOverflow(isolate, options, method_name); 1870 MAYBE_RETURN(maybe_overflow, Handle<JSTemporalPlainDate>()); 1871 1872 // 5. Let string be ? ToString(item). 1873 Handle<String> string; 1874 ASSIGN_RETURN_ON_EXCEPTION(isolate, string, 1875 Object::ToString(isolate, item_obj), 1876 JSTemporalPlainDate); 1877 // 6. Let result be ? ParseTemporalDateString(string). 1878 Maybe<DateRecord> maybe_result = ParseTemporalDateString(isolate, string); 1879 MAYBE_RETURN(maybe_result, MaybeHandle<JSTemporalPlainDate>()); 1880 DateRecord result = maybe_result.FromJust(); 1881 1882 // 7. Assert: ! IsValidISODate(result.[[Year]], result.[[Month]], 1883 // result.[[Day]]) is true. 1884 DCHECK(IsValidISODate(isolate, result.year, result.month, result.day)); 1885 // 8. Let calendar be ? ToTemporalCalendarWithISODefault(result.[[Calendar]]). 1886 Handle<Object> calendar_string; 1887 if (result.calendar->length() == 0) { 1888 calendar_string = factory->undefined_value(); 1889 } else { 1890 calendar_string = result.calendar; 1891 } 1892 Handle<JSReceiver> calendar; 1893 ASSIGN_RETURN_ON_EXCEPTION( 1894 isolate, calendar, 1895 ToTemporalCalendarWithISODefault(isolate, calendar_string, method_name), 1896 JSTemporalPlainDate); 1897 // 9. Return ? CreateTemporalDate(result.[[Year]], result.[[Month]], 1898 // result.[[Day]], calendar). 1899 return CreateTemporalDate(isolate, result.year, result.month, result.day, 1900 calendar); 1901} 1902 1903} // namespace 1904 1905namespace temporal { 1906 1907// #sec-temporal-regulatetime 1908Maybe<bool> RegulateTime(Isolate* isolate, TimeRecord* time, 1909 ShowOverflow overflow) { 1910 TEMPORAL_ENTER_FUNC(); 1911 1912 // 1. Assert: hour, minute, second, millisecond, microsecond and nanosecond 1913 // are integers. 1914 // 2. Assert: overflow is either "constrain" or "reject". 1915 switch (overflow) { 1916 case ShowOverflow::kConstrain: 1917 // 3. If overflow is "constrain", then 1918 // a. Return ! ConstrainTime(hour, minute, second, millisecond, 1919 // microsecond, nanosecond). 1920 time->hour = std::max(std::min(time->hour, 23), 0); 1921 time->minute = std::max(std::min(time->minute, 59), 0); 1922 time->second = std::max(std::min(time->second, 59), 0); 1923 time->millisecond = std::max(std::min(time->millisecond, 999), 0); 1924 time->microsecond = std::max(std::min(time->microsecond, 999), 0); 1925 time->nanosecond = std::max(std::min(time->nanosecond, 999), 0); 1926 return Just(true); 1927 case ShowOverflow::kReject: 1928 // 4. If overflow is "reject", then 1929 // a. If ! IsValidTime(hour, minute, second, millisecond, microsecond, 1930 // nanosecond) is false, throw a RangeError exception. 1931 if (!IsValidTime(isolate, time->hour, time->minute, time->second, 1932 time->millisecond, time->microsecond, 1933 time->nanosecond)) { 1934 THROW_NEW_ERROR_RETURN_VALUE( 1935 isolate, NEW_TEMPORAL_INVALD_ARG_RANGE_ERROR(), Nothing<bool>()); 1936 } 1937 // b. Return the new Record { [[Hour]]: hour, [[Minute]]: minute, 1938 // [[Second]]: second, [[Millisecond]]: millisecond, [[Microsecond]]: 1939 // microsecond, [[Nanosecond]]: nanosecond }. 1940 return Just(true); 1941 } 1942} 1943 1944// #sec-temporal-totemporaltime 1945MaybeHandle<JSTemporalPlainTime> ToTemporalTime(Isolate* isolate, 1946 Handle<Object> item_obj, 1947 ShowOverflow overflow, 1948 const char* method_name) { 1949 Factory* factory = isolate->factory(); 1950 TimeRecord result; 1951 // 2. Assert: overflow is either "constrain" or "reject". 1952 // 3. If Type(item) is Object, then 1953 if (item_obj->IsJSReceiver()) { 1954 Handle<JSReceiver> item = Handle<JSReceiver>::cast(item_obj); 1955 // a. If item has an [[InitializedTemporalTime]] internal slot, then 1956 // i. Return item. 1957 if (item->IsJSTemporalPlainTime()) { 1958 return Handle<JSTemporalPlainTime>::cast(item); 1959 } 1960 // b. If item has an [[InitializedTemporalZonedDateTime]] internal slot, 1961 // then 1962 if (item->IsJSTemporalZonedDateTime()) { 1963 // i. Let instant be ! CreateTemporalInstant(item.[[Nanoseconds]]). 1964 Handle<JSTemporalZonedDateTime> zoned_date_time = 1965 Handle<JSTemporalZonedDateTime>::cast(item); 1966 Handle<JSTemporalInstant> instant; 1967 ASSIGN_RETURN_ON_EXCEPTION( 1968 isolate, instant, 1969 CreateTemporalInstant( 1970 isolate, Handle<BigInt>(zoned_date_time->nanoseconds(), isolate)), 1971 JSTemporalPlainTime); 1972 // ii. Set plainDateTime to ? 1973 // BuiltinTimeZoneGetPlainDateTimeFor(item.[[TimeZone]], 1974 // instant, item.[[Calendar]]). 1975 Handle<JSTemporalPlainDateTime> plain_date_time; 1976 ASSIGN_RETURN_ON_EXCEPTION( 1977 isolate, plain_date_time, 1978 BuiltinTimeZoneGetPlainDateTimeFor( 1979 isolate, 1980 Handle<JSReceiver>(zoned_date_time->time_zone(), isolate), 1981 instant, Handle<JSReceiver>(zoned_date_time->calendar(), isolate), 1982 method_name), 1983 JSTemporalPlainTime); 1984 // iii. Return ! 1985 // CreateTemporalTime(plainDateTime.[[ISOHour]], 1986 // plainDateTime.[[ISOMinute]], plainDateTime.[[ISOSecond]], 1987 // plainDateTime.[[ISOMillisecond]], plainDateTime.[[ISOMicrosecond]], 1988 // plainDateTime.[[ISONanosecond]]). 1989 return CreateTemporalTime( 1990 isolate, plain_date_time->iso_hour(), plain_date_time->iso_minute(), 1991 plain_date_time->iso_second(), plain_date_time->iso_millisecond(), 1992 plain_date_time->iso_microsecond(), 1993 plain_date_time->iso_nanosecond()); 1994 } 1995 // c. If item has an [[InitializedTemporalDateTime]] internal slot, then 1996 if (item->IsJSTemporalPlainDateTime()) { 1997 // i. Return ! CreateTemporalTime(item.[[ISOHour]], item.[[ISOMinute]], 1998 // item.[[ISOSecond]], item.[[ISOMillisecond]], item.[[ISOMicrosecond]], 1999 // item.[[ISONanosecond]]). 2000 Handle<JSTemporalPlainDateTime> date_time = 2001 Handle<JSTemporalPlainDateTime>::cast(item); 2002 return CreateTemporalTime( 2003 isolate, date_time->iso_hour(), date_time->iso_minute(), 2004 date_time->iso_second(), date_time->iso_millisecond(), 2005 date_time->iso_microsecond(), date_time->iso_nanosecond()); 2006 } 2007 // d. Let calendar be ? GetTemporalCalendarWithISODefault(item). 2008 Handle<JSReceiver> calendar; 2009 ASSIGN_RETURN_ON_EXCEPTION( 2010 isolate, calendar, 2011 GetTemporalCalendarWithISODefault(isolate, item, method_name), 2012 JSTemporalPlainTime); 2013 // e. If ? ToString(calendar) is not "iso8601", then 2014 Handle<String> identifier; 2015 ASSIGN_RETURN_ON_EXCEPTION(isolate, identifier, 2016 Object::ToString(isolate, calendar), 2017 JSTemporalPlainTime); 2018 if (!String::Equals(isolate, factory->iso8601_string(), identifier)) { 2019 // i. Throw a RangeError exception. 2020 THROW_NEW_ERROR(isolate, NEW_TEMPORAL_INVALD_ARG_RANGE_ERROR(), 2021 JSTemporalPlainTime); 2022 } 2023 // f. Let result be ? ToTemporalTimeRecord(item). 2024 Maybe<TimeRecord> maybe_time_result = 2025 ToTemporalTimeRecord(isolate, item, method_name); 2026 MAYBE_RETURN(maybe_time_result, Handle<JSTemporalPlainTime>()); 2027 result = maybe_time_result.FromJust(); 2028 // g. Set result to ? RegulateTime(result.[[Hour]], result.[[Minute]], 2029 // result.[[Second]], result.[[Millisecond]], result.[[Microsecond]], 2030 // result.[[Nanosecond]], overflow). 2031 Maybe<bool> maybe_regulate_time = RegulateTime(isolate, &result, overflow); 2032 MAYBE_RETURN(maybe_regulate_time, Handle<JSTemporalPlainTime>()); 2033 DCHECK(maybe_regulate_time.FromJust()); 2034 } else { 2035 // 4. Else, 2036 // a. Let string be ? ToString(item). 2037 Handle<String> string; 2038 ASSIGN_RETURN_ON_EXCEPTION(isolate, string, 2039 Object::ToString(isolate, item_obj), 2040 JSTemporalPlainTime); 2041 // b. Let result be ? ParseTemporalTimeString(string). 2042 Maybe<TimeRecord> maybe_result = ParseTemporalTimeString(isolate, string); 2043 MAYBE_RETURN(maybe_result, MaybeHandle<JSTemporalPlainTime>()); 2044 result = maybe_result.FromJust(); 2045 // c. Assert: ! IsValidTime(result.[[Hour]], result.[[Minute]], 2046 // result.[[Second]], result.[[Millisecond]], result.[[Microsecond]], 2047 // result.[[Nanosecond]]) is true. 2048 DCHECK(IsValidTime(isolate, result.hour, result.minute, result.second, 2049 result.millisecond, result.microsecond, 2050 result.nanosecond)); 2051 // d. If result.[[Calendar]] is not one of undefined or "iso8601", then 2052 if ((result.calendar->length() > 0) /* not undefined */ && 2053 !String::Equals(isolate, result.calendar, 2054 isolate->factory()->iso8601_string())) { 2055 // i. Throw a RangeError exception. 2056 THROW_NEW_ERROR(isolate, NEW_TEMPORAL_INVALD_ARG_RANGE_ERROR(), 2057 JSTemporalPlainTime); 2058 } 2059 } 2060 // 5. Return ? CreateTemporalTime(result.[[Hour]], result.[[Minute]], 2061 // result.[[Second]], result.[[Millisecond]], result.[[Microsecond]], 2062 // result.[[Nanosecond]]). 2063 return CreateTemporalTime(isolate, result.hour, result.minute, result.second, 2064 result.millisecond, result.microsecond, 2065 result.nanosecond); 2066} 2067 2068// #sec-temporal-totemporaltimezone 2069MaybeHandle<JSReceiver> ToTemporalTimeZone( 2070 Isolate* isolate, Handle<Object> temporal_time_zone_like, 2071 const char* method_name) { 2072 TEMPORAL_ENTER_FUNC(); 2073 2074 Factory* factory = isolate->factory(); 2075 // 1. If Type(temporalTimeZoneLike) is Object, then 2076 if (temporal_time_zone_like->IsJSReceiver()) { 2077 // a. If temporalTimeZoneLike has an [[InitializedTemporalZonedDateTime]] 2078 // internal slot, then 2079 if (temporal_time_zone_like->IsJSTemporalZonedDateTime()) { 2080 // i. Return temporalTimeZoneLike.[[TimeZone]]. 2081 Handle<JSTemporalZonedDateTime> zoned_date_time = 2082 Handle<JSTemporalZonedDateTime>::cast(temporal_time_zone_like); 2083 return handle(zoned_date_time->time_zone(), isolate); 2084 } 2085 Handle<JSReceiver> obj = Handle<JSReceiver>::cast(temporal_time_zone_like); 2086 // b. If ? HasProperty(temporalTimeZoneLike, "timeZone") is false, 2087 Maybe<bool> maybe_has = 2088 JSReceiver::HasProperty(isolate, obj, factory->timeZone_string()); 2089 MAYBE_RETURN(maybe_has, Handle<JSReceiver>()); 2090 if (!maybe_has.FromJust()) { 2091 // return temporalTimeZoneLike. 2092 return obj; 2093 } 2094 // c. Set temporalTimeZoneLike to ? 2095 // Get(temporalTimeZoneLike, "timeZone"). 2096 ASSIGN_RETURN_ON_EXCEPTION( 2097 isolate, temporal_time_zone_like, 2098 JSReceiver::GetProperty(isolate, obj, factory->timeZone_string()), 2099 JSReceiver); 2100 // d. If Type(temporalTimeZoneLike) 2101 if (temporal_time_zone_like->IsJSReceiver()) { 2102 // is Object and ? HasProperty(temporalTimeZoneLike, "timeZone") is false, 2103 obj = Handle<JSReceiver>::cast(temporal_time_zone_like); 2104 maybe_has = 2105 JSReceiver::HasProperty(isolate, obj, factory->timeZone_string()); 2106 MAYBE_RETURN(maybe_has, Handle<JSReceiver>()); 2107 if (!maybe_has.FromJust()) { 2108 // return temporalTimeZoneLike. 2109 return obj; 2110 } 2111 } 2112 } 2113 Handle<String> identifier; 2114 // 2. Let identifier be ? ToString(temporalTimeZoneLike). 2115 ASSIGN_RETURN_ON_EXCEPTION(isolate, identifier, 2116 Object::ToString(isolate, temporal_time_zone_like), 2117 JSReceiver); 2118 // 3. Let result be ? ParseTemporalTimeZone(identifier). 2119 Handle<String> result; 2120 ASSIGN_RETURN_ON_EXCEPTION( 2121 isolate, result, ParseTemporalTimeZone(isolate, identifier), JSReceiver); 2122 2123 // 4. Return ? CreateTemporalTimeZone(result). 2124 return temporal::CreateTemporalTimeZone(isolate, result); 2125} 2126 2127} // namespace temporal 2128 2129namespace { 2130// #sec-temporal-systemdatetime 2131MaybeHandle<JSTemporalPlainDateTime> SystemDateTime( 2132 Isolate* isolate, Handle<Object> temporal_time_zone_like, 2133 Handle<Object> calendar_like, const char* method_name) { 2134 TEMPORAL_ENTER_FUNC(); 2135 2136 Handle<JSReceiver> time_zone; 2137 // 1. 1. If temporalTimeZoneLike is undefined, then 2138 if (temporal_time_zone_like->IsUndefined()) { 2139 // a. Let timeZone be ! SystemTimeZone(). 2140 ASSIGN_RETURN_ON_EXCEPTION(isolate, time_zone, SystemTimeZone(isolate), 2141 JSTemporalPlainDateTime); 2142 } else { 2143 // 2. Else, 2144 // a. Let timeZone be ? ToTemporalTimeZone(temporalTimeZoneLike). 2145 ASSIGN_RETURN_ON_EXCEPTION( 2146 isolate, time_zone, 2147 temporal::ToTemporalTimeZone(isolate, temporal_time_zone_like, 2148 method_name), 2149 JSTemporalPlainDateTime); 2150 } 2151 Handle<JSReceiver> calendar; 2152 // 3. Let calendar be ? ToTemporalCalendar(calendarLike). 2153 ASSIGN_RETURN_ON_EXCEPTION( 2154 isolate, calendar, 2155 temporal::ToTemporalCalendar(isolate, calendar_like, method_name), 2156 JSTemporalPlainDateTime); 2157 // 4. Let instant be ! SystemInstant(). 2158 Handle<JSTemporalInstant> instant; 2159 ASSIGN_RETURN_ON_EXCEPTION(isolate, instant, SystemInstant(isolate), 2160 JSTemporalPlainDateTime); 2161 // 5. Return ? BuiltinTimeZoneGetPlainDateTimeFor(timeZone, instant, 2162 // calendar). 2163 return temporal::BuiltinTimeZoneGetPlainDateTimeFor( 2164 isolate, time_zone, instant, calendar, method_name); 2165} 2166 2167MaybeHandle<JSTemporalZonedDateTime> SystemZonedDateTime( 2168 Isolate* isolate, Handle<Object> temporal_time_zone_like, 2169 Handle<Object> calendar_like, const char* method_name) { 2170 TEMPORAL_ENTER_FUNC(); 2171 2172 Handle<JSReceiver> time_zone; 2173 // 1. 1. If temporalTimeZoneLike is undefined, then 2174 if (temporal_time_zone_like->IsUndefined()) { 2175 // a. Let timeZone be ! SystemTimeZone(). 2176 ASSIGN_RETURN_ON_EXCEPTION(isolate, time_zone, SystemTimeZone(isolate), 2177 JSTemporalZonedDateTime); 2178 } else { 2179 // 2. Else, 2180 // a. Let timeZone be ? ToTemporalTimeZone(temporalTimeZoneLike). 2181 ASSIGN_RETURN_ON_EXCEPTION( 2182 isolate, time_zone, 2183 temporal::ToTemporalTimeZone(isolate, temporal_time_zone_like, 2184 method_name), 2185 JSTemporalZonedDateTime); 2186 } 2187 Handle<JSReceiver> calendar; 2188 // 3. Let calendar be ? ToTemporalCalendar(calendarLike). 2189 ASSIGN_RETURN_ON_EXCEPTION( 2190 isolate, calendar, 2191 temporal::ToTemporalCalendar(isolate, calendar_like, method_name), 2192 JSTemporalZonedDateTime); 2193 // 4. Let ns be ! SystemUTCEpochNanoseconds(). 2194 Handle<BigInt> ns; 2195 ASSIGN_RETURN_ON_EXCEPTION(isolate, ns, SystemUTCEpochNanoseconds(isolate), 2196 JSTemporalZonedDateTime); 2197 // Return ? CreateTemporalZonedDateTime(ns, timeZone, calendar). 2198 return CreateTemporalZonedDateTime(isolate, ns, time_zone, calendar); 2199} 2200 2201#define COMPARE_RESULT_TO_SIGN(r) \ 2202 ((r) == ComparisonResult::kEqual \ 2203 ? 0 \ 2204 : ((r) == ComparisonResult::kLessThan ? -1 : 1)) 2205 2206// #sec-temporal-formattimezoneoffsetstring 2207MaybeHandle<String> FormatTimeZoneOffsetString(Isolate* isolate, 2208 int64_t offset_nanoseconds) { 2209 IncrementalStringBuilder builder(isolate); 2210 // 1. Assert: offsetNanoseconds is an integer. 2211 // 2. If offsetNanoseconds ≥ 0, let sign be "+"; otherwise, let sign be "-". 2212 builder.AppendCString((offset_nanoseconds >= 0) ? "+" : "-"); 2213 // 3. Let offsetNanoseconds be abs(offsetNanoseconds). 2214 offset_nanoseconds = std::abs(offset_nanoseconds); 2215 // 3. Let nanoseconds be offsetNanoseconds modulo 10^9. 2216 int64_t nanoseconds = offset_nanoseconds % 1000000000; 2217 // 4. Let seconds be floor(offsetNanoseconds / 10^9) modulo 60. 2218 int64_t seconds = (offset_nanoseconds / 1000000000) % 60; 2219 // 5. Let minutes be floor(offsetNanoseconds / (6 × 10^10)) modulo 60. 2220 int64_t minutes = (offset_nanoseconds / 60000000000) % 60; 2221 // 6. Let hours be floor(offsetNanoseconds / (3.6 × 10^12)). 2222 int64_t hours = offset_nanoseconds / 3600000000000; 2223 // 7. Let h be hours, formatted as a two-digit decimal number, padded to the 2224 // left with a zero if necessary. 2225 if (hours < 10) { 2226 builder.AppendCStringLiteral("0"); 2227 } 2228 builder.AppendInt(static_cast<int32_t>(hours)); 2229 // 8. Let m be minutes, formatted as a two-digit decimal number, padded to the 2230 // left with a zero if necessary. 2231 builder.AppendCString((minutes < 10) ? ":0" : ":"); 2232 builder.AppendInt(static_cast<int>(minutes)); 2233 // 9. Let s be seconds, formatted as a two-digit decimal number, padded to the 2234 // left with a zero if necessary. 2235 // 10. If nanoseconds ≠ 0, then 2236 if (nanoseconds != 0) { 2237 builder.AppendCString((seconds < 10) ? ":0" : ":"); 2238 builder.AppendInt(static_cast<int>(seconds)); 2239 builder.AppendCStringLiteral("."); 2240 // a. Let fraction be nanoseconds, formatted as a nine-digit decimal number, 2241 // padded to the left with zeroes if necessary. 2242 // b. Set fraction to the longest possible substring of fraction starting at 2243 // position 0 and not ending with the code unit 0x0030 (DIGIT ZERO). 2244 int64_t divisor = 100000000; 2245 do { 2246 builder.AppendInt(static_cast<int>(nanoseconds / divisor)); 2247 nanoseconds %= divisor; 2248 divisor /= 10; 2249 } while (nanoseconds > 0); 2250 // c. Let post be the string-concatenation of the code unit 0x003A (COLON), 2251 // s, the code unit 0x002E (FULL STOP), and fraction. 2252 // 11. Else if seconds ≠ 0, then 2253 } else if (seconds != 0) { 2254 // a. Let post be the string-concatenation of the code unit 0x003A (COLON) 2255 // and s. 2256 builder.AppendCString((seconds < 10) ? ":0" : ":"); 2257 builder.AppendInt(static_cast<int>(seconds)); 2258 } 2259 // 12. Return the string-concatenation of sign, h, the code unit 0x003A 2260 // (COLON), m, and post. 2261 return builder.Finish(); 2262} 2263 2264// #sec-temporal-builtintimezonegetoffsetstringfor 2265MaybeHandle<String> BuiltinTimeZoneGetOffsetStringFor( 2266 Isolate* isolate, Handle<JSReceiver> time_zone, 2267 Handle<JSTemporalInstant> instant, const char* method_name) { 2268 TEMPORAL_ENTER_FUNC(); 2269 // 1. Let offsetNanoseconds be ? GetOffsetNanosecondsFor(timeZone, instant). 2270 Maybe<int64_t> maybe_offset_nanoseconds = 2271 GetOffsetNanosecondsFor(isolate, time_zone, instant, method_name); 2272 MAYBE_RETURN(maybe_offset_nanoseconds, Handle<String>()); 2273 int64_t offset_nanoseconds = maybe_offset_nanoseconds.FromJust(); 2274 2275 // 2. Return ! FormatTimeZoneOffsetString(offsetNanoseconds). 2276 return FormatTimeZoneOffsetString(isolate, offset_nanoseconds); 2277} 2278 2279// #sec-temporal-parseisodatetime 2280Maybe<DateTimeRecord> ParseISODateTime(Isolate* isolate, 2281 Handle<String> iso_string, 2282 const ParsedISO8601Result& parsed) { 2283 TEMPORAL_ENTER_FUNC(); 2284 2285 DateTimeRecord result; 2286 // 5. Set year to ! ToIntegerOrInfinity(year). 2287 result.year = parsed.date_year; 2288 // 6. If month is undefined, then 2289 if (parsed.date_month_is_undefined()) { 2290 // a. Set month to 1. 2291 result.month = 1; 2292 // 7. Else, 2293 } else { 2294 // a. Set month to ! ToIntegerOrInfinity(month). 2295 result.month = parsed.date_month; 2296 } 2297 2298 // 8. If day is undefined, then 2299 if (parsed.date_day_is_undefined()) { 2300 // a. Set day to 1. 2301 result.day = 1; 2302 // 9. Else, 2303 } else { 2304 // a. Set day to ! ToIntegerOrInfinity(day). 2305 result.day = parsed.date_day; 2306 } 2307 // 10. Set hour to ! ToIntegerOrInfinity(hour). 2308 result.hour = parsed.time_hour_is_undefined() ? 0 : parsed.time_hour; 2309 // 11. Set minute to ! ToIntegerOrInfinity(minute). 2310 result.minute = parsed.time_minute_is_undefined() ? 0 : parsed.time_minute; 2311 // 12. Set second to ! ToIntegerOrInfinity(second). 2312 result.second = parsed.time_second_is_undefined() ? 0 : parsed.time_second; 2313 // 13. If second is 60, then 2314 if (result.second == 60) { 2315 // a. Set second to 59. 2316 result.second = 59; 2317 } 2318 // 14. If fraction is not undefined, then 2319 if (!parsed.time_nanosecond_is_undefined()) { 2320 // a. Set fraction to the string-concatenation of the previous value of 2321 // fraction and the string "000000000". 2322 // b. Let millisecond be the String value equal to the substring of fraction 2323 // from 0 to 3. c. Set millisecond to ! ToIntegerOrInfinity(millisecond). 2324 result.millisecond = parsed.time_nanosecond / 1000000; 2325 // d. Let microsecond be the String value equal to the substring of fraction 2326 // from 3 to 6. e. Set microsecond to ! ToIntegerOrInfinity(microsecond). 2327 result.microsecond = (parsed.time_nanosecond / 1000) % 1000; 2328 // f. Let nanosecond be the String value equal to the substring of fraction 2329 // from 6 to 9. g. Set nanosecond to ! ToIntegerOrInfinity(nanosecond). 2330 result.nanosecond = (parsed.time_nanosecond % 1000); 2331 // 15. Else, 2332 } else { 2333 // a. Let millisecond be 0. 2334 result.millisecond = 0; 2335 // b. Let microsecond be 0. 2336 result.microsecond = 0; 2337 // c. Let nanosecond be 0. 2338 result.nanosecond = 0; 2339 } 2340 // 16. If ! IsValidISODate(year, month, day) is false, throw a RangeError 2341 // exception. 2342 if (!IsValidISODate(isolate, result.year, result.month, result.day)) { 2343 THROW_NEW_ERROR_RETURN_VALUE(isolate, NEW_TEMPORAL_INVALD_ARG_RANGE_ERROR(), 2344 Nothing<DateTimeRecord>()); 2345 } 2346 // 17. If ! IsValidTime(hour, minute, second, millisecond, microsecond, 2347 // nanosecond) is false, throw a RangeError exception. 2348 if (!IsValidTime(isolate, result.hour, result.minute, result.second, 2349 result.millisecond, result.microsecond, result.nanosecond)) { 2350 THROW_NEW_ERROR_RETURN_VALUE(isolate, NEW_TEMPORAL_INVALD_ARG_RANGE_ERROR(), 2351 Nothing<DateTimeRecord>()); 2352 } 2353 // 18. Return the Record { [[Year]]: year, [[Month]]: month, [[Day]]: day, 2354 // [[Hour]]: hour, [[Minute]]: minute, [[Second]]: second, [[Millisecond]]: 2355 // millisecond, [[Microsecond]]: microsecond, [[Nanosecond]]: nanosecond, 2356 // [[Calendar]]: calendar }. 2357 if (parsed.calendar_name_length == 0) { 2358 result.calendar = isolate->factory()->empty_string(); 2359 } else { 2360 result.calendar = isolate->factory()->NewSubString( 2361 iso_string, parsed.calendar_name_start, 2362 parsed.calendar_name_start + parsed.calendar_name_length); 2363 } 2364 return Just(result); 2365} 2366 2367// #sec-temporal-parsetemporaldatestring 2368Maybe<DateRecord> ParseTemporalDateString(Isolate* isolate, 2369 Handle<String> iso_string) { 2370 TEMPORAL_ENTER_FUNC(); 2371 // 1. Assert: Type(isoString) is String. 2372 // 2. If isoString does not satisfy the syntax of a TemporalDateString 2373 // (see 13.33), then 2374 Maybe<ParsedISO8601Result> maybe_parsed = 2375 TemporalParser::ParseTemporalDateString(isolate, iso_string); 2376 if (maybe_parsed.IsNothing()) { 2377 // a. Throw a *RangeError* exception. 2378 THROW_NEW_ERROR_RETURN_VALUE(isolate, NEW_TEMPORAL_INVALD_ARG_RANGE_ERROR(), 2379 Nothing<DateRecord>()); 2380 } 2381 MAYBE_RETURN(maybe_parsed, Nothing<DateRecord>()); 2382 2383 ParsedISO8601Result parsed = maybe_parsed.FromJust(); 2384 // 3. If _isoString_ contains a |UTCDesignator|, then 2385 if (parsed.utc_designator) { 2386 // a. Throw a *RangeError* exception. 2387 THROW_NEW_ERROR_RETURN_VALUE(isolate, NEW_TEMPORAL_INVALD_ARG_RANGE_ERROR(), 2388 Nothing<DateRecord>()); 2389 } 2390 // 3. Let result be ? ParseISODateTime(isoString). 2391 Maybe<DateTimeRecord> maybe_result = 2392 ParseISODateTime(isolate, iso_string, parsed); 2393 2394 MAYBE_RETURN(maybe_result, Nothing<DateRecord>()); 2395 DateTimeRecord result = maybe_result.FromJust(); 2396 // 4. Return the Record { [[Year]]: result.[[Year]], [[Month]]: 2397 // result.[[Month]], [[Day]]: result.[[Day]], [[Calendar]]: 2398 // result.[[Calendar]] }. 2399 DateRecord ret = {result.year, result.month, result.day, result.calendar}; 2400 return Just(ret); 2401} 2402 2403// #sec-temporal-parsetemporaltimestring 2404Maybe<TimeRecord> ParseTemporalTimeString(Isolate* isolate, 2405 Handle<String> iso_string) { 2406 TEMPORAL_ENTER_FUNC(); 2407 2408 // 1. Assert: Type(isoString) is String. 2409 // 2. If isoString does not satisfy the syntax of a TemporalTimeString 2410 // (see 13.33), then 2411 Maybe<ParsedISO8601Result> maybe_parsed = 2412 TemporalParser::ParseTemporalTimeString(isolate, iso_string); 2413 ParsedISO8601Result parsed; 2414 if (!maybe_parsed.To(&parsed)) { 2415 // a. Throw a *RangeError* exception. 2416 THROW_NEW_ERROR_RETURN_VALUE(isolate, NEW_TEMPORAL_INVALD_ARG_RANGE_ERROR(), 2417 Nothing<TimeRecord>()); 2418 } 2419 2420 // 3. If _isoString_ contains a |UTCDesignator|, then 2421 if (parsed.utc_designator) { 2422 // a. Throw a *RangeError* exception. 2423 THROW_NEW_ERROR_RETURN_VALUE(isolate, NEW_TEMPORAL_INVALD_ARG_RANGE_ERROR(), 2424 Nothing<TimeRecord>()); 2425 } 2426 2427 // 3. Let result be ? ParseISODateTime(isoString). 2428 Maybe<DateTimeRecord> maybe_result = 2429 ParseISODateTime(isolate, iso_string, parsed); 2430 MAYBE_RETURN(maybe_result, Nothing<TimeRecord>()); 2431 DateTimeRecord result = maybe_result.FromJust(); 2432 // 4. Return the Record { [[Hour]]: result.[[Hour]], [[Minute]]: 2433 // result.[[Minute]], [[Second]]: result.[[Second]], [[Millisecond]]: 2434 // result.[[Millisecond]], [[Microsecond]]: result.[[Microsecond]], 2435 // [[Nanosecond]]: result.[[Nanosecond]], [[Calendar]]: result.[[Calendar]] }. 2436 TimeRecord ret = {result.hour, result.minute, result.second, 2437 result.millisecond, result.microsecond, result.nanosecond, 2438 result.calendar}; 2439 return Just(ret); 2440} 2441 2442// #sec-temporal-parsetemporalinstantstring 2443Maybe<InstantRecord> ParseTemporalInstantString(Isolate* isolate, 2444 Handle<String> iso_string) { 2445 TEMPORAL_ENTER_FUNC(); 2446 2447 // 1. Assert: Type(isoString) is String. 2448 // 2. If isoString does not satisfy the syntax of a TemporalInstantString 2449 // (see 13.33), then 2450 Maybe<ParsedISO8601Result> maybe_parsed = 2451 TemporalParser::ParseTemporalInstantString(isolate, iso_string); 2452 if (maybe_parsed.IsNothing()) { 2453 THROW_NEW_ERROR_RETURN_VALUE(isolate, NEW_TEMPORAL_INVALD_ARG_RANGE_ERROR(), 2454 Nothing<InstantRecord>()); 2455 } 2456 2457 // 3. Let result be ! ParseISODateTime(isoString). 2458 Maybe<DateTimeRecord> maybe_result = 2459 ParseISODateTime(isolate, iso_string, maybe_parsed.FromJust()); 2460 2461 MAYBE_RETURN(maybe_result, Nothing<InstantRecord>()); 2462 DateTimeRecord result = maybe_result.FromJust(); 2463 2464 // 4. Let timeZoneResult be ? ParseTemporalTimeZoneString(isoString). 2465 Maybe<TimeZoneRecord> maybe_time_zone_result = 2466 ParseTemporalTimeZoneString(isolate, iso_string); 2467 MAYBE_RETURN(maybe_time_zone_result, Nothing<InstantRecord>()); 2468 TimeZoneRecord time_zone_result = maybe_time_zone_result.FromJust(); 2469 // 5. Let offsetString be timeZoneResult.[[OffsetString]]. 2470 Handle<String> offset_string = time_zone_result.offset_string; 2471 // 6. If timeZoneResult.[[Z]] is true, then 2472 if (time_zone_result.z) { 2473 // a. Set offsetString to "+00:00". 2474 offset_string = isolate->factory()->NewStringFromStaticChars("+00:00"); 2475 } 2476 // 7. Assert: offsetString is not undefined. 2477 DCHECK_GT(offset_string->length(), 0); 2478 2479 // 6. Return the new Record { [[Year]]: result.[[Year]], 2480 // [[Month]]: result.[[Month]], [[Day]]: result.[[Day]], 2481 // [[Hour]]: result.[[Hour]], [[Minute]]: result.[[Minute]], 2482 // [[Second]]: result.[[Second]], 2483 // [[Millisecond]]: result.[[Millisecond]], 2484 // [[Microsecond]]: result.[[Microsecond]], 2485 // [[Nanosecond]]: result.[[Nanosecond]], 2486 // [[TimeZoneOffsetString]]: offsetString }. 2487 InstantRecord record; 2488 record.year = result.year; 2489 record.month = result.month; 2490 record.day = result.day; 2491 record.hour = result.hour; 2492 record.minute = result.minute; 2493 record.second = result.second; 2494 record.millisecond = result.millisecond; 2495 record.microsecond = result.microsecond; 2496 record.nanosecond = result.nanosecond; 2497 record.offset_string = offset_string; 2498 return Just(record); 2499} 2500 2501// #sec-temporal-parsetemporalinstant 2502MaybeHandle<BigInt> ParseTemporalInstant(Isolate* isolate, 2503 Handle<String> iso_string) { 2504 TEMPORAL_ENTER_FUNC(); 2505 2506 Factory* factory = isolate->factory(); 2507 // 1. Assert: Type(isoString) is String. 2508 // 2. Let result be ? ParseTemporalInstantString(isoString). 2509 Maybe<InstantRecord> maybe_result = 2510 ParseTemporalInstantString(isolate, iso_string); 2511 MAYBE_RETURN(maybe_result, Handle<BigInt>()); 2512 InstantRecord result = maybe_result.FromJust(); 2513 2514 // 3. Let offsetString be result.[[TimeZoneOffsetString]]. 2515 // 4. Assert: offsetString is not undefined. 2516 DCHECK_NE(result.offset_string->length(), 0); 2517 2518 // 5. Let utc be ? GetEpochFromISOParts(result.[[Year]], result.[[Month]], 2519 // result.[[Day]], result.[[Hour]], result.[[Minute]], result.[[Second]], 2520 // result.[[Millisecond]], result.[[Microsecond]], result.[[Nanosecond]]). 2521 Handle<BigInt> utc; 2522 ASSIGN_RETURN_ON_EXCEPTION( 2523 isolate, utc, 2524 GetEpochFromISOParts(isolate, result.year, result.month, result.day, 2525 result.hour, result.minute, result.second, 2526 result.millisecond, result.microsecond, 2527 result.nanosecond), 2528 BigInt); 2529 2530 // 6. If utc < −8.64 × 10^21 or utc > 8.64 × 10^21, then 2531 if ((BigInt::CompareToNumber(utc, factory->NewNumber(-8.64e21)) == 2532 ComparisonResult::kLessThan) || 2533 (BigInt::CompareToNumber(utc, factory->NewNumber(8.64e21)) == 2534 ComparisonResult::kGreaterThan)) { 2535 // a. Throw a RangeError exception. 2536 THROW_NEW_ERROR(isolate, NEW_TEMPORAL_INVALD_ARG_RANGE_ERROR(), BigInt); 2537 } 2538 // 7. Let offsetNanoseconds be ? ParseTimeZoneOffsetString(offsetString). 2539 Maybe<int64_t> maybe_offset_nanoseconds = 2540 ParseTimeZoneOffsetString(isolate, result.offset_string); 2541 MAYBE_RETURN(maybe_offset_nanoseconds, Handle<BigInt>()); 2542 int64_t offset_nanoseconds = maybe_offset_nanoseconds.FromJust(); 2543 2544 // 8. Return utc − offsetNanoseconds. 2545 return BigInt::Subtract(isolate, utc, 2546 BigInt::FromInt64(isolate, offset_nanoseconds)); 2547} 2548 2549// #sec-temporal-parsetemporaltimezonestring 2550Maybe<TimeZoneRecord> ParseTemporalTimeZoneString(Isolate* isolate, 2551 Handle<String> iso_string) { 2552 TEMPORAL_ENTER_FUNC(); 2553 2554 // 1. Assert: Type(isoString) is String. 2555 // 2. If isoString does not satisfy the syntax of a TemporalTimeZoneString 2556 // (see 13.33), then 2557 Maybe<ParsedISO8601Result> maybe_parsed = 2558 TemporalParser::ParseTemporalTimeZoneString(isolate, iso_string); 2559 MAYBE_RETURN(maybe_parsed, Nothing<TimeZoneRecord>()); 2560 if (maybe_parsed.IsNothing()) { 2561 THROW_NEW_ERROR_RETURN_VALUE(isolate, NEW_TEMPORAL_INVALD_ARG_RANGE_ERROR(), 2562 Nothing<TimeZoneRecord>()); 2563 } 2564 ParsedISO8601Result parsed = maybe_parsed.FromJust(); 2565 // 3. Let z, sign, hours, minutes, seconds, fraction and name be the parts of 2566 // isoString produced respectively by the UTCDesignator, 2567 // TimeZoneUTCOffsetSign, TimeZoneUTCOffsetHour, TimeZoneUTCOffsetMinute, 2568 // TimeZoneUTCOffsetSecond, TimeZoneUTCOffsetFraction, and TimeZoneIANAName 2569 // productions, or undefined if not present. 2570 // 4. If z is not undefined, then 2571 if (parsed.utc_designator) { 2572 // a. Return the Record { [[Z]]: true, [[OffsetString]]: undefined, 2573 // [[Name]]: name }. 2574 if (parsed.tzi_name_length > 0) { 2575 Handle<String> name = isolate->factory()->NewSubString( 2576 iso_string, parsed.tzi_name_start, 2577 parsed.tzi_name_start + parsed.tzi_name_length); 2578 TimeZoneRecord ret({true, isolate->factory()->empty_string(), name}); 2579 return Just(ret); 2580 } 2581 TimeZoneRecord ret({true, isolate->factory()->empty_string(), 2582 isolate->factory()->empty_string()}); 2583 return Just(ret); 2584 } 2585 2586 // 5. If hours is undefined, then 2587 // a. Let offsetString be undefined. 2588 // 6. Else, 2589 Handle<String> offset_string; 2590 bool offset_string_is_defined = false; 2591 if (!parsed.tzuo_hour_is_undefined()) { 2592 // a. Assert: sign is not undefined. 2593 DCHECK(!parsed.tzuo_sign_is_undefined()); 2594 // b. Set hours to ! ToIntegerOrInfinity(hours). 2595 int32_t hours = parsed.tzuo_hour; 2596 // c. If sign is the code unit 0x002D (HYPHEN-MINUS) or the code unit 0x2212 2597 // (MINUS SIGN), then i. Set sign to −1. d. Else, i. Set sign to 1. 2598 int32_t sign = parsed.tzuo_sign; 2599 // e. Set minutes to ! ToIntegerOrInfinity(minutes). 2600 int32_t minutes = 2601 parsed.tzuo_minute_is_undefined() ? 0 : parsed.tzuo_minute; 2602 // f. Set seconds to ! ToIntegerOrInfinity(seconds). 2603 int32_t seconds = 2604 parsed.tzuo_second_is_undefined() ? 0 : parsed.tzuo_second; 2605 // g. If fraction is not undefined, then 2606 int32_t nanoseconds; 2607 if (!parsed.tzuo_nanosecond_is_undefined()) { 2608 // i. Set fraction to the string-concatenation of the previous value of 2609 // fraction and the string "000000000". 2610 // ii. Let nanoseconds be the String value equal to the substring of 2611 // fraction from 0 to 9. iii. Set nanoseconds to ! 2612 // ToIntegerOrInfinity(nanoseconds). 2613 nanoseconds = parsed.tzuo_nanosecond; 2614 // h. Else, 2615 } else { 2616 // i. Let nanoseconds be 0. 2617 nanoseconds = 0; 2618 } 2619 // i. Let offsetNanoseconds be sign × (((hours × 60 + minutes) × 60 + 2620 // seconds) × 10^9 + nanoseconds). 2621 int64_t offset_nanoseconds = 2622 sign * 2623 (((hours * 60 + minutes) * 60 + seconds) * 1000000000L + nanoseconds); 2624 // j. Let offsetString be ! FormatTimeZoneOffsetString(offsetNanoseconds). 2625 ASSIGN_RETURN_ON_EXCEPTION_VALUE( 2626 isolate, offset_string, 2627 FormatTimeZoneOffsetString(isolate, offset_nanoseconds), 2628 Nothing<TimeZoneRecord>()); 2629 offset_string_is_defined = true; 2630 } 2631 // 7. If name is not undefined, then 2632 Handle<String> name; 2633 if (parsed.tzi_name_length > 0) { 2634 name = isolate->factory()->NewSubString( 2635 iso_string, parsed.tzi_name_start, 2636 parsed.tzi_name_start + parsed.tzi_name_length); 2637 2638 // a. If ! IsValidTimeZoneName(name) is false, throw a RangeError exception. 2639 if (!IsValidTimeZoneName(isolate, name)) { 2640 THROW_NEW_ERROR_RETURN_VALUE(isolate, 2641 NEW_TEMPORAL_INVALD_ARG_RANGE_ERROR(), 2642 Nothing<TimeZoneRecord>()); 2643 } 2644 // b. Set name to ! CanonicalizeTimeZoneName(name). 2645 ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, name, 2646 CanonicalizeTimeZoneName(isolate, name), 2647 Nothing<TimeZoneRecord>()); 2648 // 8. Return the Record { [[Z]]: false, [[OffsetString]]: offsetString, 2649 // [[Name]]: name }. 2650 TimeZoneRecord ret({false, 2651 offset_string_is_defined 2652 ? offset_string 2653 : isolate->factory()->empty_string(), 2654 name}); 2655 return Just(ret); 2656 } 2657 // 8. Return the Record { [[Z]]: false, [[OffsetString]]: offsetString, 2658 // [[Name]]: name }. 2659 TimeZoneRecord ret({false, 2660 offset_string_is_defined 2661 ? offset_string 2662 : isolate->factory()->empty_string(), 2663 isolate->factory()->empty_string()}); 2664 return Just(ret); 2665} 2666 2667// #sec-temporal-parsetemporaltimezone 2668MaybeHandle<String> ParseTemporalTimeZone(Isolate* isolate, 2669 Handle<String> string) { 2670 TEMPORAL_ENTER_FUNC(); 2671 2672 // 2. Let result be ? ParseTemporalTimeZoneString(string). 2673 Maybe<TimeZoneRecord> maybe_result = 2674 ParseTemporalTimeZoneString(isolate, string); 2675 MAYBE_RETURN(maybe_result, Handle<String>()); 2676 TimeZoneRecord result = maybe_result.FromJust(); 2677 2678 // 3. If result.[[Name]] is not undefined, return result.[[Name]]. 2679 if (result.name->length() > 0) { 2680 return result.name; 2681 } 2682 2683 // 4. If result.[[Z]] is true, return "UTC". 2684 if (result.z) { 2685 return isolate->factory()->UTC_string(); 2686 } 2687 2688 // 5. Return result.[[OffsetString]]. 2689 return result.offset_string; 2690} 2691 2692Maybe<int64_t> ParseTimeZoneOffsetString(Isolate* isolate, 2693 Handle<String> iso_string, 2694 bool throwIfNotSatisfy) { 2695 TEMPORAL_ENTER_FUNC(); 2696 2697 // 1. Assert: Type(offsetString) is String. 2698 // 2. If offsetString does not satisfy the syntax of a 2699 // TimeZoneNumericUTCOffset (see 13.33), then 2700 Maybe<ParsedISO8601Result> maybe_parsed = 2701 TemporalParser::ParseTimeZoneNumericUTCOffset(isolate, iso_string); 2702 MAYBE_RETURN(maybe_parsed, Nothing<int64_t>()); 2703 if (throwIfNotSatisfy && maybe_parsed.IsNothing()) { 2704 /* a. Throw a RangeError exception. */ 2705 THROW_NEW_ERROR_RETURN_VALUE(isolate, NEW_TEMPORAL_INVALD_ARG_RANGE_ERROR(), 2706 Nothing<int64_t>()); 2707 } 2708 ParsedISO8601Result parsed = maybe_parsed.FromJust(); 2709 // 3. Let sign, hours, minutes, seconds, and fraction be the parts of 2710 // offsetString produced respectively by the TimeZoneUTCOffsetSign, 2711 // TimeZoneUTCOffsetHour, TimeZoneUTCOffsetMinute, TimeZoneUTCOffsetSecond, 2712 // and TimeZoneUTCOffsetFraction productions, or undefined if not present. 2713 // 4. If either hours or sign are undefined, throw a RangeError exception. 2714 if (parsed.tzuo_hour_is_undefined() || parsed.tzuo_sign_is_undefined()) { 2715 THROW_NEW_ERROR_RETURN_VALUE(isolate, NEW_TEMPORAL_INVALD_ARG_RANGE_ERROR(), 2716 Nothing<int64_t>()); 2717 } 2718 // 5. If sign is the code unit 0x002D (HYPHEN-MINUS) or 0x2212 (MINUS SIGN), 2719 // then a. Set sign to −1. 2720 // 6. Else, 2721 // a. Set sign to 1. 2722 int64_t sign = parsed.tzuo_sign; 2723 2724 // 7. Set hours to ! ToIntegerOrInfinity(hours). 2725 int64_t hours = parsed.tzuo_hour; 2726 // 8. Set minutes to ! ToIntegerOrInfinity(minutes). 2727 int64_t minutes = parsed.tzuo_minute_is_undefined() ? 0 : parsed.tzuo_minute; 2728 // 9. Set seconds to ! ToIntegerOrInfinity(seconds). 2729 int64_t seconds = parsed.tzuo_second_is_undefined() ? 0 : parsed.tzuo_second; 2730 // 10. If fraction is not undefined, then 2731 int64_t nanoseconds; 2732 if (!parsed.tzuo_nanosecond_is_undefined()) { 2733 // a. Set fraction to the string-concatenation of the previous value of 2734 // fraction and the string "000000000". 2735 // b. Let nanoseconds be the String value equal to the substring of fraction 2736 // consisting of the code units with indices 0 (inclusive) through 9 2737 // (exclusive). c. Set nanoseconds to ! ToIntegerOrInfinity(nanoseconds). 2738 nanoseconds = parsed.tzuo_nanosecond; 2739 // 11. Else, 2740 } else { 2741 // a. Let nanoseconds be 0. 2742 nanoseconds = 0; 2743 } 2744 // 12. Return sign × (((hours × 60 + minutes) × 60 + seconds) × 10^9 + 2745 // nanoseconds). 2746 return Just(sign * (((hours * 60 + minutes) * 60 + seconds) * 1000000000 + 2747 nanoseconds)); 2748} 2749 2750Maybe<bool> IsValidTimeZoneNumericUTCOffsetString(Isolate* isolate, 2751 Handle<String> iso_string) { 2752 TEMPORAL_ENTER_FUNC(); 2753 2754 Maybe<ParsedISO8601Result> maybe_parsed = 2755 TemporalParser::ParseTimeZoneNumericUTCOffset(isolate, iso_string); 2756 return Just(maybe_parsed.IsJust()); 2757} 2758 2759// #sec-temporal-parsetemporalcalendarstring 2760MaybeHandle<String> ParseTemporalCalendarString(Isolate* isolate, 2761 Handle<String> iso_string) { 2762 TEMPORAL_ENTER_FUNC(); 2763 2764 // 1. Assert: Type(isoString) is String. 2765 // 2. If isoString does not satisfy the syntax of a TemporalCalendarString 2766 // (see 13.33), then a. Throw a RangeError exception. 2767 Maybe<ParsedISO8601Result> maybe_parsed = 2768 TemporalParser::ParseTemporalCalendarString(isolate, iso_string); 2769 MAYBE_RETURN(maybe_parsed, Handle<String>()); 2770 if (maybe_parsed.IsNothing()) { 2771 THROW_NEW_ERROR(isolate, NEW_TEMPORAL_INVALD_ARG_RANGE_ERROR(), String); 2772 } 2773 ParsedISO8601Result parsed = maybe_parsed.FromJust(); 2774 // 3. Let id be the part of isoString produced by the CalendarName production, 2775 // or undefined if not present. 2776 // 4. If id is undefined, then 2777 if (parsed.calendar_name_length == 0) { 2778 // a. Return "iso8601". 2779 return isolate->factory()->iso8601_string(); 2780 } 2781 Handle<String> id = isolate->factory()->NewSubString( 2782 iso_string, parsed.calendar_name_start, 2783 parsed.calendar_name_start + parsed.calendar_name_length); 2784 // 5. If ! IsBuiltinCalendar(id) is false, then 2785 if (!IsBuiltinCalendar(isolate, id)) { 2786 // a. Throw a RangeError exception. 2787 THROW_NEW_ERROR( 2788 isolate, NewRangeError(MessageTemplate::kInvalidCalendar, id), String); 2789 } 2790 // 6. Return id. 2791 return id; 2792} 2793 2794// #sec-temporal-calendarfields 2795MaybeHandle<FixedArray> CalendarFields(Isolate* isolate, 2796 Handle<JSReceiver> calendar, 2797 Handle<FixedArray> field_names) { 2798 // 1. Let fields be ? GetMethod(calendar, "fields"). 2799 Handle<Object> fields; 2800 ASSIGN_RETURN_ON_EXCEPTION( 2801 isolate, fields, 2802 Object::GetMethod(calendar, isolate->factory()->fields_string()), 2803 FixedArray); 2804 // 2. Let fieldsArray be ! CreateArrayFromList(fieldNames). 2805 Handle<Object> fields_array = 2806 isolate->factory()->NewJSArrayWithElements(field_names); 2807 // 3. If fields is not undefined, then 2808 if (!fields->IsUndefined()) { 2809 // a. Set fieldsArray to ? Call(fields, calendar, « fieldsArray »). 2810 Handle<Object> argv[] = {fields_array}; 2811 ASSIGN_RETURN_ON_EXCEPTION( 2812 isolate, fields_array, 2813 Execution::Call(isolate, fields, calendar, 1, argv), FixedArray); 2814 } 2815 // 4. Return ? IterableToListOfType(fieldsArray, « String »). 2816 Handle<Object> argv[] = {fields_array}; 2817 ASSIGN_RETURN_ON_EXCEPTION( 2818 isolate, fields_array, 2819 Execution::CallBuiltin(isolate, 2820 isolate->string_fixed_array_from_iterable(), 2821 fields_array, 1, argv), 2822 FixedArray); 2823 DCHECK(fields_array->IsFixedArray()); 2824 return Handle<FixedArray>::cast(fields_array); 2825} 2826 2827MaybeHandle<JSTemporalPlainDate> CalendarDateAdd(Isolate* isolate, 2828 Handle<JSReceiver> calendar, 2829 Handle<Object> date, 2830 Handle<Object> duration, 2831 Handle<Object> options) { 2832 return CalendarDateAdd(isolate, calendar, date, duration, options, 2833 isolate->factory()->undefined_value()); 2834} 2835 2836MaybeHandle<JSTemporalPlainDate> CalendarDateAdd( 2837 Isolate* isolate, Handle<JSReceiver> calendar, Handle<Object> date, 2838 Handle<Object> duration, Handle<Object> options, Handle<Object> date_add) { 2839 // 1. Assert: Type(calendar) is Object. 2840 // 2. If dateAdd is not present, set dateAdd to ? GetMethod(calendar, 2841 // "dateAdd"). 2842 if (date_add->IsUndefined()) { 2843 ASSIGN_RETURN_ON_EXCEPTION( 2844 isolate, date_add, 2845 Object::GetMethod(calendar, isolate->factory()->dateAdd_string()), 2846 JSTemporalPlainDate); 2847 } 2848 // 3. Let addedDate be ? Call(dateAdd, calendar, « date, duration, options »). 2849 Handle<Object> argv[] = {date, duration, options}; 2850 Handle<Object> added_date; 2851 ASSIGN_RETURN_ON_EXCEPTION( 2852 isolate, added_date, 2853 Execution::Call(isolate, date_add, calendar, arraysize(argv), argv), 2854 JSTemporalPlainDate); 2855 // 4. Perform ? RequireInternalSlot(addedDate, [[InitializedTemporalDate]]). 2856 if (!added_date->IsJSTemporalPlainDate()) { 2857 THROW_NEW_ERROR(isolate, NEW_TEMPORAL_INVALD_ARG_TYPE_ERROR(), 2858 JSTemporalPlainDate); 2859 } 2860 // 5. Return addedDate. 2861 return Handle<JSTemporalPlainDate>::cast(added_date); 2862} 2863 2864MaybeHandle<JSTemporalDuration> CalendarDateUntil(Isolate* isolate, 2865 Handle<JSReceiver> calendar, 2866 Handle<Object> one, 2867 Handle<Object> two, 2868 Handle<Object> options) { 2869 return CalendarDateUntil(isolate, calendar, one, two, options, 2870 isolate->factory()->undefined_value()); 2871} 2872 2873MaybeHandle<JSTemporalDuration> CalendarDateUntil( 2874 Isolate* isolate, Handle<JSReceiver> calendar, Handle<Object> one, 2875 Handle<Object> two, Handle<Object> options, Handle<Object> date_until) { 2876 // 1. Assert: Type(calendar) is Object. 2877 // 2. If dateUntil is not present, set dateUntil to ? GetMethod(calendar, 2878 // "dateUntil"). 2879 if (date_until->IsUndefined()) { 2880 ASSIGN_RETURN_ON_EXCEPTION( 2881 isolate, date_until, 2882 Object::GetMethod(calendar, isolate->factory()->dateUntil_string()), 2883 JSTemporalDuration); 2884 } 2885 // 3. Let duration be ? Call(dateUntil, calendar, « one, two, options »). 2886 Handle<Object> argv[] = {one, two, options}; 2887 Handle<Object> duration; 2888 ASSIGN_RETURN_ON_EXCEPTION( 2889 isolate, duration, 2890 Execution::Call(isolate, date_until, calendar, arraysize(argv), argv), 2891 JSTemporalDuration); 2892 // 4. Perform ? RequireInternalSlot(duration, 2893 // [[InitializedTemporalDuration]]). 2894 if (!duration->IsJSTemporalDuration()) { 2895 THROW_NEW_ERROR(isolate, NEW_TEMPORAL_INVALD_ARG_TYPE_ERROR(), 2896 JSTemporalDuration); 2897 } 2898 // 5. Return duration. 2899 return Handle<JSTemporalDuration>::cast(duration); 2900} 2901 2902// #sec-temporal-defaultmergefields 2903MaybeHandle<JSReceiver> DefaultMergeFields( 2904 Isolate* isolate, Handle<JSReceiver> fields, 2905 Handle<JSReceiver> additional_fields) { 2906 Factory* factory = isolate->factory(); 2907 // 1. Let merged be ! OrdinaryObjectCreate(%Object.prototype%). 2908 Handle<JSObject> merged = 2909 isolate->factory()->NewJSObject(isolate->object_function()); 2910 2911 // 2. Let originalKeys be ? EnumerableOwnPropertyNames(fields, key). 2912 Handle<FixedArray> original_keys; 2913 ASSIGN_RETURN_ON_EXCEPTION( 2914 isolate, original_keys, 2915 KeyAccumulator::GetKeys(fields, KeyCollectionMode::kOwnOnly, 2916 ENUMERABLE_STRINGS, 2917 GetKeysConversion::kConvertToString), 2918 JSReceiver); 2919 // 3. For each element nextKey of originalKeys, do 2920 for (int i = 0; i < original_keys->length(); i++) { 2921 // a. If nextKey is not "month" or "monthCode", then 2922 Handle<Object> next_key = handle(original_keys->get(i), isolate); 2923 DCHECK(next_key->IsString()); 2924 Handle<String> next_key_string = Handle<String>::cast(next_key); 2925 if (!(String::Equals(isolate, factory->month_string(), next_key_string) || 2926 String::Equals(isolate, factory->monthCode_string(), 2927 next_key_string))) { 2928 // i. Let propValue be ? Get(fields, nextKey). 2929 Handle<Object> prop_value; 2930 ASSIGN_RETURN_ON_EXCEPTION( 2931 isolate, prop_value, 2932 JSReceiver::GetPropertyOrElement(isolate, fields, next_key_string), 2933 JSReceiver); 2934 // ii. If propValue is not undefined, then 2935 if (!prop_value->IsUndefined()) { 2936 // 1. Perform ! CreateDataPropertyOrThrow(merged, nextKey, 2937 // propValue). 2938 CHECK(JSReceiver::CreateDataProperty(isolate, merged, next_key_string, 2939 prop_value, Just(kDontThrow)) 2940 .FromJust()); 2941 } 2942 } 2943 } 2944 // 4. Let newKeys be ? EnumerableOwnPropertyNames(additionalFields, key). 2945 Handle<FixedArray> new_keys; 2946 ASSIGN_RETURN_ON_EXCEPTION( 2947 isolate, new_keys, 2948 KeyAccumulator::GetKeys(additional_fields, KeyCollectionMode::kOwnOnly, 2949 ENUMERABLE_STRINGS, 2950 GetKeysConversion::kConvertToString), 2951 JSReceiver); 2952 bool new_keys_has_month_or_month_code = false; 2953 // 5. For each element nextKey of newKeys, do 2954 for (int i = 0; i < new_keys->length(); i++) { 2955 Handle<Object> next_key = handle(new_keys->get(i), isolate); 2956 DCHECK(next_key->IsString()); 2957 Handle<String> next_key_string = Handle<String>::cast(next_key); 2958 // a. Let propValue be ? Get(additionalFields, nextKey). 2959 Handle<Object> prop_value; 2960 ASSIGN_RETURN_ON_EXCEPTION(isolate, prop_value, 2961 JSReceiver::GetPropertyOrElement( 2962 isolate, additional_fields, next_key_string), 2963 JSReceiver); 2964 // b. If propValue is not undefined, then 2965 if (!prop_value->IsUndefined()) { 2966 // 1. Perform ! CreateDataPropertyOrThrow(merged, nextKey, propValue). 2967 Maybe<bool> maybe_created = JSReceiver::CreateDataProperty( 2968 isolate, merged, next_key_string, prop_value, Just(kThrowOnError)); 2969 MAYBE_RETURN(maybe_created, Handle<JSReceiver>()); 2970 } 2971 new_keys_has_month_or_month_code |= 2972 String::Equals(isolate, factory->month_string(), next_key_string) || 2973 String::Equals(isolate, factory->monthCode_string(), next_key_string); 2974 } 2975 // 6. If newKeys does not contain either "month" or "monthCode", then 2976 if (!new_keys_has_month_or_month_code) { 2977 // a. Let month be ? Get(fields, "month"). 2978 Handle<Object> month; 2979 ASSIGN_RETURN_ON_EXCEPTION(isolate, month, 2980 JSReceiver::GetPropertyOrElement( 2981 isolate, fields, factory->month_string()), 2982 JSReceiver); 2983 // b. If month is not undefined, then 2984 if (!month->IsUndefined()) { 2985 // i. Perform ! CreateDataPropertyOrThrow(merged, "month", month). 2986 CHECK(JSReceiver::CreateDataProperty(isolate, merged, 2987 factory->month_string(), month, 2988 Just(kDontThrow)) 2989 .FromJust()); 2990 } 2991 // c. Let monthCode be ? Get(fields, "monthCode"). 2992 Handle<Object> month_code; 2993 ASSIGN_RETURN_ON_EXCEPTION( 2994 isolate, month_code, 2995 JSReceiver::GetPropertyOrElement(isolate, fields, 2996 factory->monthCode_string()), 2997 JSReceiver); 2998 // d. If monthCode is not undefined, then 2999 if (!month_code->IsUndefined()) { 3000 // i. Perform ! CreateDataPropertyOrThrow(merged, "monthCode", monthCode). 3001 CHECK(JSReceiver::CreateDataProperty(isolate, merged, 3002 factory->monthCode_string(), 3003 month_code, Just(kDontThrow)) 3004 .FromJust()); 3005 } 3006 } 3007 // 7. Return merged. 3008 return merged; 3009} 3010 3011// #sec-temporal-getoffsetnanosecondsfor 3012Maybe<int64_t> GetOffsetNanosecondsFor(Isolate* isolate, 3013 Handle<JSReceiver> time_zone_obj, 3014 Handle<Object> instant, 3015 const char* method_name) { 3016 TEMPORAL_ENTER_FUNC(); 3017 // 1. Let getOffsetNanosecondsFor be ? GetMethod(timeZone, 3018 // "getOffsetNanosecondsFor"). 3019 Handle<Object> get_offset_nanoseconds_for; 3020 ASSIGN_RETURN_ON_EXCEPTION_VALUE( 3021 isolate, get_offset_nanoseconds_for, 3022 Object::GetMethod(time_zone_obj, 3023 isolate->factory()->getOffsetNanosecondsFor_string()), 3024 Nothing<int64_t>()); 3025 if (!get_offset_nanoseconds_for->IsCallable()) { 3026 THROW_NEW_ERROR_RETURN_VALUE( 3027 isolate, 3028 NewTypeError(MessageTemplate::kCalledNonCallable, 3029 isolate->factory()->getOffsetNanosecondsFor_string()), 3030 Nothing<int64_t>()); 3031 } 3032 Handle<Object> offset_nanoseconds_obj; 3033 // 3. Let offsetNanoseconds be ? Call(getOffsetNanosecondsFor, timeZone, « 3034 // instant »). 3035 Handle<Object> argv[] = {instant}; 3036 ASSIGN_RETURN_ON_EXCEPTION_VALUE( 3037 isolate, offset_nanoseconds_obj, 3038 Execution::Call(isolate, get_offset_nanoseconds_for, time_zone_obj, 1, 3039 argv), 3040 Nothing<int64_t>()); 3041 3042 // 4. If Type(offsetNanoseconds) is not Number, throw a TypeError exception. 3043 if (!offset_nanoseconds_obj->IsNumber()) { 3044 THROW_NEW_ERROR_RETURN_VALUE(isolate, NEW_TEMPORAL_INVALD_ARG_TYPE_ERROR(), 3045 Nothing<int64_t>()); 3046 } 3047 3048 // 5. If ! IsIntegralNumber(offsetNanoseconds) is false, throw a RangeError 3049 // exception. 3050 double offset_nanoseconds = offset_nanoseconds_obj->Number(); 3051 if ((offset_nanoseconds - std::floor(offset_nanoseconds) != 0)) { 3052 THROW_NEW_ERROR_RETURN_VALUE(isolate, NEW_TEMPORAL_INVALD_ARG_RANGE_ERROR(), 3053 Nothing<int64_t>()); 3054 } 3055 3056 // 6. Set offsetNanoseconds to ℝ(offsetNanoseconds). 3057 int64_t offset_nanoseconds_int = static_cast<int64_t>(offset_nanoseconds); 3058 // 7. If abs(offsetNanoseconds) > 86400 × 10^9, throw a RangeError exception. 3059 if (std::abs(offset_nanoseconds_int) > 86400e9) { 3060 THROW_NEW_ERROR_RETURN_VALUE(isolate, NEW_TEMPORAL_INVALD_ARG_RANGE_ERROR(), 3061 Nothing<int64_t>()); 3062 } 3063 // 8. Return offsetNanoseconds. 3064 return Just(offset_nanoseconds_int); 3065} 3066 3067// #sec-temporal-topositiveinteger 3068MaybeHandle<Object> ToPositiveInteger(Isolate* isolate, 3069 Handle<Object> argument) { 3070 TEMPORAL_ENTER_FUNC(); 3071 3072 // 1. Let integer be ? ToInteger(argument). 3073 ASSIGN_RETURN_ON_EXCEPTION( 3074 isolate, argument, ToIntegerThrowOnInfinity(isolate, argument), Object); 3075 // 2. If integer ≤ 0, then 3076 if (NumberToInt32(*argument) <= 0) { 3077 // a. Throw a RangeError exception. 3078 THROW_NEW_ERROR(isolate, NEW_TEMPORAL_INVALD_ARG_RANGE_ERROR(), Object); 3079 } 3080 return argument; 3081} 3082 3083} // namespace 3084 3085namespace temporal { 3086MaybeHandle<Object> InvokeCalendarMethod(Isolate* isolate, 3087 Handle<JSReceiver> calendar, 3088 Handle<String> name, 3089 Handle<JSReceiver> date_like) { 3090 Handle<Object> result; 3091 /* 1. Assert: Type(calendar) is Object. */ 3092 DCHECK(calendar->IsObject()); 3093 /* 2. Let result be ? Invoke(calendar, #name, « dateLike »). */ 3094 Handle<Object> function; 3095 ASSIGN_RETURN_ON_EXCEPTION( 3096 isolate, function, Object::GetProperty(isolate, calendar, name), Object); 3097 if (!function->IsCallable()) { 3098 THROW_NEW_ERROR(isolate, 3099 NewTypeError(MessageTemplate::kCalledNonCallable, name), 3100 Object); 3101 } 3102 Handle<Object> argv[] = {date_like}; 3103 ASSIGN_RETURN_ON_EXCEPTION( 3104 isolate, result, 3105 Execution::Call(isolate, function, calendar, arraysize(argv), argv), 3106 Object); 3107 return result; 3108} 3109 3110#define CALENDAR_ABSTRACT_OPERATION_INT_ACTION(Name, name, Action) \ 3111 MaybeHandle<Object> Calendar##Name(Isolate* isolate, \ 3112 Handle<JSReceiver> calendar, \ 3113 Handle<JSReceiver> date_like) { \ 3114 /* 1. Assert: Type(calendar) is Object. */ \ 3115 /* 2. Let result be ? Invoke(calendar, property, « dateLike »). */ \ 3116 Handle<Object> result; \ 3117 ASSIGN_RETURN_ON_EXCEPTION( \ 3118 isolate, result, \ 3119 InvokeCalendarMethod(isolate, calendar, \ 3120 isolate->factory()->name##_string(), date_like), \ 3121 Object); \ 3122 /* 3. If result is undefined, throw a RangeError exception. */ \ 3123 if (result->IsUndefined()) { \ 3124 THROW_NEW_ERROR(isolate, NEW_TEMPORAL_INVALD_ARG_RANGE_ERROR(), Object); \ 3125 } \ 3126 /* 4. Return ? Action(result). */ \ 3127 ASSIGN_RETURN_ON_EXCEPTION(isolate, result, Action(isolate, result), \ 3128 Object); \ 3129 return Handle<Smi>(Smi::FromInt(result->Number()), isolate); \ 3130 } 3131 3132// #sec-temporal-calendaryear 3133CALENDAR_ABSTRACT_OPERATION_INT_ACTION(Year, year, ToIntegerThrowOnInfinity) 3134// #sec-temporal-calendarmonth 3135CALENDAR_ABSTRACT_OPERATION_INT_ACTION(Month, month, ToPositiveInteger) 3136// #sec-temporal-calendarday 3137CALENDAR_ABSTRACT_OPERATION_INT_ACTION(Day, day, ToPositiveInteger) 3138// #sec-temporal-calendarmonthcode 3139MaybeHandle<Object> CalendarMonthCode(Isolate* isolate, 3140 Handle<JSReceiver> calendar, 3141 Handle<JSReceiver> date_like) { 3142 // 1. Assert: Type(calendar) is Object. 3143 // 2. Let result be ? Invoke(calendar, monthCode , « dateLike »). 3144 Handle<Object> result; 3145 ASSIGN_RETURN_ON_EXCEPTION( 3146 isolate, result, 3147 InvokeCalendarMethod(isolate, calendar, 3148 isolate->factory()->monthCode_string(), date_like), 3149 Object); 3150 /* 3. If result is undefined, throw a RangeError exception. */ 3151 if (result->IsUndefined()) { 3152 THROW_NEW_ERROR(isolate, NEW_TEMPORAL_INVALD_ARG_RANGE_ERROR(), Object); 3153 } 3154 // 4. Return ? ToString(result). 3155 return Object::ToString(isolate, result); 3156} 3157 3158#ifdef V8_INTL_SUPPORT 3159// #sec-temporal-calendarerayear 3160MaybeHandle<Object> CalendarEraYear(Isolate* isolate, 3161 Handle<JSReceiver> calendar, 3162 Handle<JSReceiver> date_like) { 3163 // 1. Assert: Type(calendar) is Object. 3164 // 2. Let result be ? Invoke(calendar, eraYear , « dateLike »). 3165 Handle<Object> result; 3166 ASSIGN_RETURN_ON_EXCEPTION( 3167 isolate, result, 3168 InvokeCalendarMethod(isolate, calendar, 3169 isolate->factory()->eraYear_string(), date_like), 3170 Object); 3171 // 3. If result is not undefined, set result to ? ToIntegerOrInfinity(result). 3172 if (!result->IsUndefined()) { 3173 ASSIGN_RETURN_ON_EXCEPTION( 3174 isolate, result, ToIntegerThrowOnInfinity(isolate, result), Object); 3175 } 3176 // 4. Return result. 3177 return result; 3178} 3179 3180// #sec-temporal-calendarera 3181MaybeHandle<Object> CalendarEra(Isolate* isolate, Handle<JSReceiver> calendar, 3182 Handle<JSReceiver> date_like) { 3183 // 1. Assert: Type(calendar) is Object. 3184 // 2. Let result be ? Invoke(calendar, era , « dateLike »). 3185 Handle<Object> result; 3186 ASSIGN_RETURN_ON_EXCEPTION( 3187 isolate, result, 3188 InvokeCalendarMethod(isolate, calendar, isolate->factory()->era_string(), 3189 date_like), 3190 Object); 3191 // 3. If result is not undefined, set result to ? ToString(result). 3192 if (!result->IsUndefined()) { 3193 ASSIGN_RETURN_ON_EXCEPTION(isolate, result, 3194 Object::ToString(isolate, result), Object); 3195 } 3196 // 4. Return result. 3197 return result; 3198} 3199 3200#endif // V8_INTL_SUPPORT 3201 3202// #sec-temporal-getiso8601calendar 3203MaybeHandle<JSTemporalCalendar> GetISO8601Calendar(Isolate* isolate) { 3204 return CreateTemporalCalendar(isolate, isolate->factory()->iso8601_string()); 3205} 3206 3207} // namespace temporal 3208 3209namespace { 3210 3211bool IsUTC(Isolate* isolate, Handle<String> time_zone) { 3212 // 1. Assert: Type(timeZone) is String. 3213 // 2. Let tzText be ! StringToCodePoints(timeZone). 3214 // 3. Let tzUpperText be the result of toUppercase(tzText), according to the 3215 // Unicode Default Case Conversion algorithm. 3216 // 4. Let tzUpper be ! CodePointsToString(tzUpperText). 3217 // 5. If tzUpper and "UTC" are the same sequence of code points, return true. 3218 // 6. Return false. 3219 if (time_zone->length() != 3) return false; 3220 time_zone = String::Flatten(isolate, time_zone); 3221 DisallowGarbageCollection no_gc; 3222 const String::FlatContent& flat = time_zone->GetFlatContent(no_gc); 3223 return (flat.Get(0) == u'U' || flat.Get(0) == u'u') && 3224 (flat.Get(1) == u'T' || flat.Get(1) == u't') && 3225 (flat.Get(2) == u'C' || flat.Get(2) == u'c'); 3226} 3227 3228#ifdef V8_INTL_SUPPORT 3229class CalendarMap final { 3230 public: 3231 CalendarMap() { 3232 icu::Locale locale("und"); 3233 UErrorCode status = U_ZERO_ERROR; 3234 std::unique_ptr<icu::StringEnumeration> enumeration( 3235 icu::Calendar::getKeywordValuesForLocale("ca", locale, false, status)); 3236 calendar_ids.push_back("iso8601"); 3237 calendar_id_indices.insert({"iso8601", 0}); 3238 int32_t i = 1; 3239 for (const char* item = enumeration->next(nullptr, status); 3240 U_SUCCESS(status) && item != nullptr; 3241 item = enumeration->next(nullptr, status)) { 3242 if (strcmp(item, "iso8601") != 0) { 3243 const char* type = uloc_toUnicodeLocaleType("ca", item); 3244 calendar_ids.push_back(type); 3245 calendar_id_indices.insert({type, i++}); 3246 } 3247 } 3248 } 3249 bool Contains(const std::string& id) const { 3250 return calendar_id_indices.find(id) != calendar_id_indices.end(); 3251 } 3252 3253 std::string Id(int32_t index) const { 3254 DCHECK_LT(index, calendar_ids.size()); 3255 return calendar_ids[index]; 3256 } 3257 3258 int32_t Index(const char* id) const { 3259 return calendar_id_indices.find(id)->second; 3260 } 3261 3262 private: 3263 std::map<std::string, int32_t> calendar_id_indices; 3264 std::vector<std::string> calendar_ids; 3265}; 3266 3267DEFINE_LAZY_LEAKY_OBJECT_GETTER(CalendarMap, GetCalendarMap) 3268 3269// #sec-temporal-isbuiltincalendar 3270bool IsBuiltinCalendar(Isolate* isolate, const std::string& id) { 3271 return GetCalendarMap()->Contains(id); 3272} 3273 3274bool IsBuiltinCalendar(Isolate* isolate, Handle<String> id) { 3275 return IsBuiltinCalendar(isolate, id->ToCString().get()); 3276} 3277 3278Handle<String> CalendarIdentifier(Isolate* isolate, int32_t index) { 3279 return isolate->factory()->NewStringFromAsciiChecked( 3280 GetCalendarMap()->Id(index).c_str()); 3281} 3282 3283int32_t CalendarIndex(Isolate* isolate, Handle<String> id) { 3284 return GetCalendarMap()->Index(id->ToCString().get()); 3285} 3286 3287bool IsValidTimeZoneName(Isolate* isolate, Handle<String> time_zone) { 3288 return Intl::IsValidTimeZoneName(isolate, time_zone); 3289} 3290 3291MaybeHandle<String> CanonicalizeTimeZoneName(Isolate* isolate, 3292 Handle<String> identifier) { 3293 return Intl::CanonicalizeTimeZoneName(isolate, identifier); 3294} 3295 3296#else // V8_INTL_SUPPORT 3297Handle<String> CalendarIdentifier(Isolate* isolate, int32_t index) { 3298 DCHECK_EQ(index, 0); 3299 return isolate->factory()->iso8601_string(); 3300} 3301 3302// #sec-temporal-isbuiltincalendar 3303bool IsBuiltinCalendar(Isolate* isolate, Handle<String> id) { 3304 // 1. If id is not "iso8601", return false. 3305 // 2. Return true 3306 return isolate->factory()->iso8601_string()->Equals(*id); 3307} 3308 3309int32_t CalendarIndex(Isolate* isolate, Handle<String> id) { return 0; } 3310// #sec-isvalidtimezonename 3311bool IsValidTimeZoneName(Isolate* isolate, Handle<String> time_zone) { 3312 return IsUTC(isolate, time_zone); 3313} 3314// #sec-canonicalizetimezonename 3315MaybeHandle<String> CanonicalizeTimeZoneName(Isolate* isolate, 3316 Handle<String> identifier) { 3317 return isolate->factory()->UTC_string(); 3318} 3319#endif // V8_INTL_SUPPORT 3320 3321// #sec-temporal-totemporaltimerecord 3322Maybe<TimeRecord> ToTemporalTimeRecord(Isolate* isolate, 3323 Handle<JSReceiver> temporal_time_like, 3324 const char* method_name) { 3325 TEMPORAL_ENTER_FUNC(); 3326 3327 TimeRecord result; 3328 Factory* factory = isolate->factory(); 3329 // 1. Assert: Type(temporalTimeLike) is Object. 3330 // 2. Let result be the new Record { [[Hour]]: undefined, [[Minute]]: 3331 // undefined, [[Second]]: undefined, [[Millisecond]]: undefined, 3332 // [[Microsecond]]: undefined, [[Nanosecond]]: undefined }. 3333 // See https://github.com/tc39/proposal-temporal/pull/1862 3334 // 3. Let _any_ be *false*. 3335 bool any = false; 3336 // 4. For each row of Table 3, except the header row, in table order, do 3337 std::array<std::pair<Handle<String>, int32_t*>, 6> table3 = { 3338 {{factory->hour_string(), &result.hour}, 3339 {factory->microsecond_string(), &result.microsecond}, 3340 {factory->millisecond_string(), &result.millisecond}, 3341 {factory->minute_string(), &result.minute}, 3342 {factory->nanosecond_string(), &result.nanosecond}, 3343 {factory->second_string(), &result.second}}}; 3344 for (const auto& row : table3) { 3345 Handle<Object> value; 3346 // a. Let property be the Property value of the current row. 3347 // b. Let value be ? Get(temporalTimeLike, property). 3348 ASSIGN_RETURN_ON_EXCEPTION_VALUE( 3349 isolate, value, 3350 Object::GetPropertyOrElement(isolate, temporal_time_like, row.first), 3351 Nothing<TimeRecord>()); 3352 // c. If value is not undefined, then 3353 if (!value->IsUndefined()) { 3354 // i. Set _any_ to *true*. 3355 any = true; 3356 } 3357 // d. Set value to ? ToIntegerThrowOnOInfinity(value). 3358 ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, value, 3359 ToIntegerThrowOnInfinity(isolate, value), 3360 Nothing<TimeRecord>()); 3361 // e. Set result's internal slot whose name is the Internal Slot value of 3362 // the current row to value. 3363 *(row.second) = value->Number(); 3364 } 3365 3366 // 5. If _any_ is *false*, then 3367 if (!any) { 3368 // a. Throw a *TypeError* exception. 3369 THROW_NEW_ERROR_RETURN_VALUE(isolate, NEW_TEMPORAL_INVALD_ARG_TYPE_ERROR(), 3370 Nothing<TimeRecord>()); 3371 } 3372 // 4. Return result. 3373 return Just(result); 3374} 3375 3376// #sec-temporal-mergelargestunitoption 3377MaybeHandle<JSObject> MergeLargestUnitOption(Isolate* isolate, 3378 Handle<JSReceiver> options, 3379 Unit largest_unit) { 3380 TEMPORAL_ENTER_FUNC(); 3381 // 1. Let merged be ! OrdinaryObjectCreate(%Object.prototype%). 3382 Handle<JSObject> merged = 3383 isolate->factory()->NewJSObject(isolate->object_function()); 3384 // 2. Let keys be ? EnumerableOwnPropertyNames(options, key). 3385 // 3. For each element nextKey of keys, do 3386 // a. Let propValue be ? Get(options, nextKey). 3387 // b. Perform ! CreateDataPropertyOrThrow(merged, nextKey, propValue). 3388 JSReceiver::SetOrCopyDataProperties( 3389 isolate, merged, options, PropertiesEnumerationMode::kEnumerationOrder, 3390 nullptr, false) 3391 .Check(); 3392 3393 // 4. Perform ! CreateDataPropertyOrThrow(merged, "largestUnit", largestUnit). 3394 CHECK(JSReceiver::CreateDataProperty( 3395 isolate, merged, isolate->factory()->largestUnit_string(), 3396 UnitToString(isolate, largest_unit), Just(kThrowOnError)) 3397 .FromJust()); 3398 // 5. Return merged. 3399 return merged; 3400} 3401 3402// #sec-temporal-tointegerthrowoninfinity 3403MaybeHandle<Object> ToIntegerThrowOnInfinity(Isolate* isolate, 3404 Handle<Object> argument) { 3405 TEMPORAL_ENTER_FUNC(); 3406 3407 // 1. Let integer be ? ToIntegerOrInfinity(argument). 3408 ASSIGN_RETURN_ON_EXCEPTION(isolate, argument, 3409 Object::ToInteger(isolate, argument), Object); 3410 // 2. If integer is +∞ or -∞, throw a RangeError exception. 3411 if (!std::isfinite(argument->Number())) { 3412 // a. Throw a RangeError exception. 3413 THROW_NEW_ERROR(isolate, NEW_TEMPORAL_INVALD_ARG_RANGE_ERROR(), Object); 3414 } 3415 return argument; 3416} 3417 3418// #sec-temporal-largeroftwotemporalunits 3419Unit LargerOfTwoTemporalUnits(Isolate* isolate, Unit u1, Unit u2) { 3420 // 1. If either u1 or u2 is "year", return "year". 3421 if (u1 == Unit::kYear || u2 == Unit::kYear) return Unit::kYear; 3422 // 2. If either u1 or u2 is "month", return "month". 3423 if (u1 == Unit::kMonth || u2 == Unit::kMonth) return Unit::kMonth; 3424 // 3. If either u1 or u2 is "week", return "week". 3425 if (u1 == Unit::kWeek || u2 == Unit::kWeek) return Unit::kWeek; 3426 // 4. If either u1 or u2 is "day", return "day". 3427 if (u1 == Unit::kDay || u2 == Unit::kDay) return Unit::kDay; 3428 // 5. If either u1 or u2 is "hour", return "hour". 3429 if (u1 == Unit::kHour || u2 == Unit::kHour) return Unit::kHour; 3430 // 6. If either u1 or u2 is "minute", return "minute". 3431 if (u1 == Unit::kMinute || u2 == Unit::kMinute) return Unit::kMinute; 3432 // 7. If either u1 or u2 is "second", return "second". 3433 if (u1 == Unit::kSecond || u2 == Unit::kSecond) return Unit::kSecond; 3434 // 8. If either u1 or u2 is "millisecond", return "millisecond". 3435 if (u1 == Unit::kMillisecond || u2 == Unit::kMillisecond) 3436 return Unit::kMillisecond; 3437 // 9. If either u1 or u2 is "microsecond", return "microsecond". 3438 if (u1 == Unit::kMicrosecond || u2 == Unit::kMicrosecond) 3439 return Unit::kMicrosecond; 3440 // 10. Return "nanosecond". 3441 return Unit::kNanosecond; 3442} 3443 3444Handle<String> UnitToString(Isolate* isolate, Unit unit) { 3445 switch (unit) { 3446 case Unit::kYear: 3447 return ReadOnlyRoots(isolate).year_string_handle(); 3448 case Unit::kMonth: 3449 return ReadOnlyRoots(isolate).month_string_handle(); 3450 case Unit::kWeek: 3451 return ReadOnlyRoots(isolate).week_string_handle(); 3452 case Unit::kDay: 3453 return ReadOnlyRoots(isolate).day_string_handle(); 3454 case Unit::kHour: 3455 return ReadOnlyRoots(isolate).hour_string_handle(); 3456 case Unit::kMinute: 3457 return ReadOnlyRoots(isolate).minute_string_handle(); 3458 case Unit::kSecond: 3459 return ReadOnlyRoots(isolate).second_string_handle(); 3460 case Unit::kMillisecond: 3461 return ReadOnlyRoots(isolate).millisecond_string_handle(); 3462 case Unit::kMicrosecond: 3463 return ReadOnlyRoots(isolate).microsecond_string_handle(); 3464 case Unit::kNanosecond: 3465 return ReadOnlyRoots(isolate).nanosecond_string_handle(); 3466 default: 3467 UNREACHABLE(); 3468 } 3469} 3470 3471// #sec-temporal-balanceisodate 3472void BalanceISODate(Isolate* isolate, int32_t* year, int32_t* month, 3473 int32_t* day) { 3474 TEMPORAL_ENTER_FUNC(); 3475 3476 // 1. Assert: year, month, and day are integers. 3477 // 2. Let balancedYearMonth be ! BalanceISOYearMonth(year, month). 3478 // 3. Set month to balancedYearMonth.[[Month]]. 3479 // 4. Set year to balancedYearMonth.[[Year]]. 3480 BalanceISOYearMonth(isolate, year, month); 3481 // 5. NOTE: To deal with negative numbers of days whose absolute value is 3482 // greater than the number of days in a year, the following section subtracts 3483 // years and adds days until the number of days is greater than −366 or −365. 3484 // 6. If month > 2, then 3485 // a. Let testYear be year. 3486 // 7. Else, 3487 // a. Let testYear be year − 1. 3488 int32_t test_year = (*month > 2) ? *year : *year - 1; 3489 // 8. Repeat, while day < −1 × ! ISODaysInYear(testYear), 3490 int32_t iso_days_in_year; 3491 while (*day < -(iso_days_in_year = ISODaysInYear(isolate, test_year))) { 3492 // a. Set day to day + ! ISODaysInYear(testYear). 3493 *day += iso_days_in_year; 3494 // b. Set year to year − 1. 3495 (*year)--; 3496 // c. Set testYear to testYear − 1. 3497 test_year--; 3498 } 3499 // 9. NOTE: To deal with numbers of days greater than the number of days in a 3500 // year, the following section adds years and subtracts days until the number 3501 // of days is less than 366 or 365. 3502 // 10. Let testYear be year + 1. 3503 test_year = (*year) + 1; 3504 // 11. Repeat, while day > ! ISODaysInYear(testYear), 3505 while (*day > (iso_days_in_year = ISODaysInYear(isolate, test_year))) { 3506 // a. Set day to day − ! ISODaysInYear(testYear). 3507 *day -= iso_days_in_year; 3508 // b. Set year to year + 1. 3509 (*year)++; 3510 // c. Set testYear to testYear + 1. 3511 test_year++; 3512 } 3513 // 12. NOTE: To deal with negative numbers of days whose absolute value is 3514 // greater than the number of days in the current month, the following section 3515 // subtracts months and adds days until the number of days is greater than 0. 3516 // 13. Repeat, while day < 1, 3517 while (*day < 1) { 3518 // a. Set balancedYearMonth to ! BalanceISOYearMonth(year, month − 1). 3519 // b. Set year to balancedYearMonth.[[Year]]. 3520 // c. Set month to balancedYearMonth.[[Month]]. 3521 *month -= 1; 3522 BalanceISOYearMonth(isolate, year, month); 3523 // d. Set day to day + ! ISODaysInMonth(year, month). 3524 *day += ISODaysInMonth(isolate, *year, *month); 3525 } 3526 // 14. NOTE: To deal with numbers of days greater than the number of days in 3527 // the current month, the following section adds months and subtracts days 3528 // until the number of days is less than the number of days in the month. 3529 // 15. Repeat, while day > ! ISODaysInMonth(year, month), 3530 int32_t iso_days_in_month; 3531 while (*day > (iso_days_in_month = ISODaysInMonth(isolate, *year, *month))) { 3532 // a. Set day to day − ! ISODaysInMonth(year, month). 3533 *day -= iso_days_in_month; 3534 // b. Set balancedYearMonth to ! BalanceISOYearMonth(year, month + 1). 3535 // c. Set year to balancedYearMonth.[[Year]]. 3536 // d. Set month to balancedYearMonth.[[Month]]. 3537 *month += 1; 3538 BalanceISOYearMonth(isolate, year, month); 3539 } 3540 // 16. Return the new Record { [[Year]]: year, [[Month]]: month, [[Day]]: day 3541 // }. 3542 return; 3543} 3544 3545// #sec-temporal-adddatetime 3546Maybe<DateTimeRecordCommon> AddDateTime( 3547 Isolate* isolate, int32_t year, int32_t month, int32_t day, int32_t hour, 3548 int32_t minute, int32_t second, int32_t millisecond, int32_t microsecond, 3549 int32_t nanosecond, Handle<JSReceiver> calendar, const DurationRecord& dur, 3550 Handle<Object> options) { 3551 TEMPORAL_ENTER_FUNC(); 3552 3553 // 1. Assert: year, month, day, hour, minute, second, millisecond, 3554 // microsecond, and nanosecond are integers. 3555 // 2. Let timeResult be ! AddTime(hour, minute, second, millisecond, 3556 // microsecond, nanosecond, hours, minutes, seconds, milliseconds, 3557 // microseconds, nanoseconds). 3558 DateTimeRecordCommon time_result = 3559 AddTime(isolate, hour, minute, second, millisecond, microsecond, 3560 nanosecond, dur.hours, dur.minutes, dur.seconds, dur.milliseconds, 3561 dur.microseconds, dur.nanoseconds); 3562 3563 // 3. Let datePart be ? CreateTemporalDate(year, month, day, calendar). 3564 Handle<JSTemporalPlainDate> date_part; 3565 ASSIGN_RETURN_ON_EXCEPTION_VALUE( 3566 isolate, date_part, 3567 CreateTemporalDate(isolate, year, month, day, calendar), 3568 Nothing<DateTimeRecordCommon>()); 3569 // 4. Let dateDuration be ? CreateTemporalDuration(years, months, weeks, days 3570 // + timeResult.[[Days]], 0, 0, 0, 0, 0, 0). 3571 Handle<JSTemporalDuration> date_duration; 3572 ASSIGN_RETURN_ON_EXCEPTION_VALUE( 3573 isolate, date_duration, 3574 CreateTemporalDuration(isolate, dur.years, dur.months, dur.weeks, 3575 dur.days + time_result.day, 0, 0, 0, 0, 0, 0), 3576 Nothing<DateTimeRecordCommon>()); 3577 // 5. Let addedDate be ? CalendarDateAdd(calendar, datePart, dateDuration, 3578 // options). 3579 Handle<JSTemporalPlainDate> added_date; 3580 ASSIGN_RETURN_ON_EXCEPTION_VALUE( 3581 isolate, added_date, 3582 CalendarDateAdd(isolate, calendar, date_part, date_duration, options), 3583 Nothing<DateTimeRecordCommon>()); 3584 // 6. Return the new Record { [[Year]]: addedDate.[[ISOYear]], [[Month]]: 3585 // addedDate.[[ISOMonth]], [[Day]]: addedDate.[[ISODay]], [[Hour]]: 3586 // timeResult.[[Hour]], [[Minute]]: timeResult.[[Minute]], [[Second]]: 3587 // timeResult.[[Second]], [[Millisecond]]: timeResult.[[Millisecond]], 3588 // [[Microsecond]]: timeResult.[[Microsecond]], [[Nanosecond]]: 3589 // timeResult.[[Nanosecond]], }. 3590 time_result.year = added_date->iso_year(); 3591 time_result.month = added_date->iso_month(); 3592 time_result.day = added_date->iso_day(); 3593 return Just(time_result); 3594} 3595 3596Maybe<bool> BalanceDuration(Isolate* isolate, int64_t* days, int64_t* hours, 3597 int64_t* minutes, int64_t* seconds, 3598 int64_t* milliseconds, int64_t* microseconds, 3599 int64_t* nanoseconds, Unit largest_unit, 3600 const char* method_name) { 3601 TEMPORAL_ENTER_FUNC(); 3602 3603 // 1. If relativeTo is not present, set relativeTo to undefined. 3604 return BalanceDuration(isolate, days, hours, minutes, seconds, milliseconds, 3605 microseconds, nanoseconds, largest_unit, 3606 isolate->factory()->undefined_value(), method_name); 3607} 3608 3609Maybe<bool> BalanceDuration(Isolate* isolate, int64_t* days, int64_t* hours, 3610 int64_t* minutes, int64_t* seconds, 3611 int64_t* milliseconds, int64_t* microseconds, 3612 int64_t* nanoseconds, Unit largest_unit, 3613 Handle<Object> relative_to_obj, 3614 const char* method_name) { 3615 TEMPORAL_ENTER_FUNC(); 3616 3617 // 2. If Type(relativeTo) is Object and relativeTo has an 3618 // [[InitializedTemporalZonedDateTime]] internal slot, then 3619 if (relative_to_obj->IsJSTemporalZonedDateTime()) { 3620 Handle<JSTemporalZonedDateTime> relative_to = 3621 Handle<JSTemporalZonedDateTime>::cast(relative_to_obj); 3622 // a. Let endNs be ? AddZonedDateTime(relativeTo.[[Nanoseconds]], 3623 // relativeTo.[[TimeZone]], relativeTo.[[Calendar]], 0, 0, 0, days, hours, 3624 // minutes, seconds, milliseconds, microseconds, nanoseconds). 3625 Handle<BigInt> end_ns; 3626 ASSIGN_RETURN_ON_EXCEPTION_VALUE( 3627 isolate, end_ns, 3628 AddZonedDateTime(isolate, 3629 Handle<BigInt>(relative_to->nanoseconds(), isolate), 3630 Handle<JSReceiver>(relative_to->time_zone(), isolate), 3631 Handle<JSReceiver>(relative_to->calendar(), isolate), 3632 {0, 0, 0, *days, *hours, *minutes, *seconds, 3633 *milliseconds, *microseconds, *nanoseconds}, 3634 method_name), 3635 Nothing<bool>()); 3636 // b. Set nanoseconds to endNs − relativeTo.[[Nanoseconds]]. 3637 ASSIGN_RETURN_ON_EXCEPTION_VALUE( 3638 isolate, end_ns, 3639 BigInt::Subtract(isolate, end_ns, 3640 Handle<BigInt>(relative_to->nanoseconds(), isolate)), 3641 Nothing<bool>()); 3642 *nanoseconds = end_ns->AsInt64(); 3643 // 3. Else, 3644 } else { 3645 // a. Set nanoseconds to ℤ(! TotalDurationNanoseconds(days, hours, minutes, 3646 // seconds, milliseconds, microseconds, nanoseconds, 0)). 3647 *nanoseconds = 3648 TotalDurationNanoseconds(isolate, *days, *hours, *minutes, *seconds, 3649 *milliseconds, *microseconds, *nanoseconds, 0); 3650 } 3651 // 4. If largestUnit is one of "year", "month", "week", or "day", then 3652 if (largest_unit == Unit::kYear || largest_unit == Unit::kMonth || 3653 largest_unit == Unit::kWeek || largest_unit == Unit::kDay) { 3654 int64_t result_day_length; 3655 // a. Let result be ? NanosecondsToDays(nanoseconds, relativeTo). 3656 Maybe<bool> maybe_result = 3657 NanosecondsToDays(isolate, *nanoseconds, relative_to_obj, days, 3658 nanoseconds, &result_day_length, method_name); 3659 MAYBE_RETURN(maybe_result, Nothing<bool>()); 3660 DCHECK(maybe_result.FromJust()); 3661 // b. Set days to result.[[Days]]. 3662 // c. Set nanoseconds to result.[[Nanoseconds]]. 3663 // 5. Else, 3664 } else { 3665 // a. Set days to 0. 3666 *days = 0; 3667 } 3668 // 6. Set hours, minutes, seconds, milliseconds, and microseconds to 0. 3669 *hours = *minutes = *seconds = *milliseconds = *microseconds = 0; 3670 // 7. Set nanoseconds to ℝ(nanoseconds). 3671 3672 // 8. If nanoseconds < 0, let sign be −1; else, let sign be 1. 3673 int32_t sign = (*nanoseconds < 0) ? -1 : 1; 3674 // 9. Set nanoseconds to abs(nanoseconds). 3675 *nanoseconds = std::abs(*nanoseconds); 3676 // 10. If largestUnit is "year", "month", "week", "day", or "hour", then 3677 switch (largest_unit) { 3678 case Unit::kYear: 3679 case Unit::kMonth: 3680 case Unit::kWeek: 3681 case Unit::kDay: 3682 case Unit::kHour: 3683 // a. Set microseconds to floor(nanoseconds / 1000). 3684 *microseconds = floor_divide(*nanoseconds, 1000); 3685 // b. Set nanoseconds to nanoseconds modulo 1000. 3686 *nanoseconds = modulo(*nanoseconds, 1000); 3687 // c. Set milliseconds to floor(microseconds / 1000). 3688 *milliseconds = floor_divide(*microseconds, 1000); 3689 // d. Set microseconds to microseconds modulo 1000. 3690 *microseconds = modulo(*microseconds, 1000); 3691 // e. Set seconds to floor(milliseconds / 1000). 3692 *seconds = floor_divide(*milliseconds, 1000); 3693 // f. Set milliseconds to milliseconds modulo 1000. 3694 *milliseconds = modulo(*milliseconds, 1000); 3695 // g. Set minutes to floor(seconds, 60). 3696 *minutes = floor_divide(*seconds, 60); 3697 // h. Set seconds to seconds modulo 60. 3698 *seconds = modulo(*seconds, 60); 3699 // i. Set hours to floor(minutes / 60). 3700 *hours = floor_divide(*minutes, 60); 3701 // j. Set minutes to minutes modulo 60. 3702 *minutes = modulo(*minutes, 60); 3703 break; 3704 // 11. Else if largestUnit is "minute", then 3705 case Unit::kMinute: 3706 // a. Set microseconds to floor(nanoseconds / 1000). 3707 *microseconds = floor_divide(*nanoseconds, 1000); 3708 // b. Set nanoseconds to nanoseconds modulo 1000. 3709 *nanoseconds = modulo(*nanoseconds, 1000); 3710 // c. Set milliseconds to floor(microseconds / 1000). 3711 *milliseconds = floor_divide(*microseconds, 1000); 3712 // d. Set microseconds to microseconds modulo 1000. 3713 *microseconds = modulo(*microseconds, 1000); 3714 // e. Set seconds to floor(milliseconds / 1000). 3715 *seconds = floor_divide(*milliseconds, 1000); 3716 // f. Set milliseconds to milliseconds modulo 1000. 3717 *milliseconds = modulo(*milliseconds, 1000); 3718 // g. Set minutes to floor(seconds / 60). 3719 *minutes = floor_divide(*seconds, 60); 3720 // h. Set seconds to seconds modulo 60. 3721 *seconds = modulo(*seconds, 60); 3722 break; 3723 // 12. Else if largestUnit is "second", then 3724 case Unit::kSecond: 3725 // a. Set microseconds to floor(nanoseconds / 1000). 3726 *microseconds = floor_divide(*nanoseconds, 1000); 3727 // b. Set nanoseconds to nanoseconds modulo 1000. 3728 *nanoseconds = modulo(*nanoseconds, 1000); 3729 // c. Set milliseconds to floor(microseconds / 1000). 3730 *milliseconds = floor_divide(*microseconds, 1000); 3731 // d. Set microseconds to microseconds modulo 1000. 3732 *microseconds = modulo(*microseconds, 1000); 3733 // e. Set seconds to floor(milliseconds / 1000). 3734 *seconds = floor_divide(*milliseconds, 1000); 3735 // f. Set milliseconds to milliseconds modulo 1000. 3736 *milliseconds = modulo(*milliseconds, 1000); 3737 break; 3738 // 13. Else if largestUnit is "millisecond", then 3739 case Unit::kMillisecond: 3740 // a. Set microseconds to floor(nanoseconds / 1000). 3741 *microseconds = floor_divide(*nanoseconds, 1000); 3742 // b. Set nanoseconds to nanoseconds modulo 1000. 3743 *nanoseconds = modulo(*nanoseconds, 1000); 3744 // c. Set milliseconds to floor(microseconds / 1000). 3745 *milliseconds = floor_divide(*microseconds, 1000); 3746 // d. Set microseconds to microseconds modulo 1000. 3747 *microseconds = modulo(*microseconds, 1000); 3748 break; 3749 // 14. Else if largestUnit is "microsecond", then 3750 case Unit::kMicrosecond: 3751 // a. Set microseconds to floor(nanoseconds / 1000). 3752 *microseconds = floor_divide(*nanoseconds, 1000); 3753 // b. Set nanoseconds to nanoseconds modulo 1000. 3754 *nanoseconds = modulo(*nanoseconds, 1000); 3755 break; 3756 // 15. Else, 3757 default: 3758 // a. Assert: largestUnit is "nanosecond". 3759 DCHECK_EQ(largest_unit, Unit::kNanosecond); 3760 break; 3761 } 3762 // 16. Return the new Record { [[Days]]: (days), [[Hours]]: (hours × sign), 3763 // [[Minutes]]: (minutes × sign), [[Seconds]]: (seconds × sign), 3764 // [[Milliseconds]]: (milliseconds × sign), [[Microseconds]]: (microseconds 3765 // × sign), [[Nanoseconds]]: (nanoseconds × sign) }. 3766 *hours *= sign; 3767 *minutes *= sign; 3768 *seconds *= sign; 3769 *milliseconds *= sign; 3770 *microseconds *= sign; 3771 *nanoseconds *= sign; 3772 return Just(true); 3773} 3774 3775// #sec-temporal-addinstant 3776MaybeHandle<BigInt> AddZonedDateTime(Isolate* isolate, 3777 Handle<BigInt> epoch_nanoseconds, 3778 Handle<JSReceiver> time_zone, 3779 Handle<JSReceiver> calendar, 3780 const DurationRecord& duration, 3781 const char* method_name) { 3782 TEMPORAL_ENTER_FUNC(); 3783 3784 // 1. If options is not present, set options to ! OrdinaryObjectCreate(null). 3785 Handle<JSReceiver> options = isolate->factory()->NewJSObjectWithNullProto(); 3786 return AddZonedDateTime(isolate, epoch_nanoseconds, time_zone, calendar, 3787 duration, options, method_name); 3788} 3789 3790// #sec-temporal-addzoneddatetime 3791MaybeHandle<BigInt> AddZonedDateTime(Isolate* isolate, 3792 Handle<BigInt> epoch_nanoseconds, 3793 Handle<JSReceiver> time_zone, 3794 Handle<JSReceiver> calendar, 3795 const DurationRecord& duration, 3796 Handle<JSReceiver> options, 3797 const char* method_name) { 3798 TEMPORAL_ENTER_FUNC(); 3799 3800 // 2. If all of years, months, weeks, and days are 0, then 3801 if (duration.years == 0 && duration.months == 0 && duration.weeks == 0 && 3802 duration.days == 0) { 3803 // a. Return ! AddInstant(epochNanoseconds, hours, minutes, seconds, 3804 // milliseconds, microseconds, nanoseconds). 3805 return AddInstant(isolate, epoch_nanoseconds, duration.hours, 3806 duration.minutes, duration.seconds, duration.milliseconds, 3807 duration.microseconds, duration.nanoseconds); 3808 } 3809 // 3. Let instant be ! CreateTemporalInstant(epochNanoseconds). 3810 Handle<JSTemporalInstant> instant; 3811 ASSIGN_RETURN_ON_EXCEPTION( 3812 isolate, instant, 3813 temporal::CreateTemporalInstant(isolate, epoch_nanoseconds), BigInt); 3814 3815 // 4. Let temporalDateTime be ? 3816 // BuiltinTimeZoneGetPlainDateTimeFor(timeZone, instant, calendar). 3817 Handle<JSTemporalPlainDateTime> temporal_date_time; 3818 ASSIGN_RETURN_ON_EXCEPTION( 3819 isolate, temporal_date_time, 3820 temporal::BuiltinTimeZoneGetPlainDateTimeFor(isolate, time_zone, instant, 3821 calendar, method_name), 3822 BigInt); 3823 // 5. Let datePart be ? CreateTemporalDate(temporalDateTime.[[ISOYear]], 3824 // temporalDateTime.[[ISOMonth]], temporalDateTime.[[ISODay]], calendar). 3825 Handle<JSTemporalPlainDate> date_part; 3826 ASSIGN_RETURN_ON_EXCEPTION( 3827 isolate, date_part, 3828 CreateTemporalDate(isolate, temporal_date_time->iso_year(), 3829 temporal_date_time->iso_month(), 3830 temporal_date_time->iso_day(), calendar), 3831 BigInt); 3832 // 6. Let dateDuration be ? CreateTemporalDuration(years, months, weeks, days, 3833 // 0, 0, 0, 0, 0, 0). 3834 Handle<JSTemporalDuration> date_duration; 3835 ASSIGN_RETURN_ON_EXCEPTION( 3836 isolate, date_duration, 3837 CreateTemporalDuration(isolate, duration.years, duration.months, 3838 duration.weeks, duration.days, 0, 0, 0, 0, 0, 0), 3839 BigInt); 3840 // 7. Let addedDate be ? CalendarDateAdd(calendar, datePart, dateDuration, 3841 // options). 3842 Handle<JSTemporalPlainDate> added_date; 3843 ASSIGN_RETURN_ON_EXCEPTION( 3844 isolate, added_date, 3845 CalendarDateAdd(isolate, calendar, date_part, date_duration, options), 3846 BigInt); 3847 // 8. Let intermediateDateTime be ? 3848 // CreateTemporalDateTime(addedDate.[[ISOYear]], addedDate.[[ISOMonth]], 3849 // addedDate.[[ISODay]], temporalDateTime.[[ISOHour]], 3850 // temporalDateTime.[[ISOMinute]], temporalDateTime.[[ISOSecond]], 3851 // temporalDateTime.[[ISOMillisecond]], temporalDateTime.[[ISOMicrosecond]], 3852 // temporalDateTime.[[ISONanosecond]], calendar). 3853 Handle<JSTemporalPlainDateTime> intermediate_date_time; 3854 ASSIGN_RETURN_ON_EXCEPTION( 3855 isolate, intermediate_date_time, 3856 temporal::CreateTemporalDateTime( 3857 isolate, added_date->iso_year(), added_date->iso_month(), 3858 added_date->iso_day(), temporal_date_time->iso_hour(), 3859 temporal_date_time->iso_minute(), temporal_date_time->iso_second(), 3860 temporal_date_time->iso_millisecond(), 3861 temporal_date_time->iso_microsecond(), 3862 temporal_date_time->iso_nanosecond(), calendar), 3863 BigInt); 3864 // 9. Let intermediateInstant be ? BuiltinTimeZoneGetInstantFor(timeZone, 3865 // intermediateDateTime, "compatible"). 3866 Handle<JSTemporalInstant> intermediate_instant; 3867 ASSIGN_RETURN_ON_EXCEPTION( 3868 isolate, intermediate_instant, 3869 BuiltinTimeZoneGetInstantFor(isolate, time_zone, intermediate_date_time, 3870 Disambiguation::kCompatible, method_name), 3871 BigInt); 3872 // 10. Return ! AddInstant(intermediateInstant.[[Nanoseconds]], hours, 3873 // minutes, seconds, milliseconds, microseconds, nanoseconds). 3874 return AddInstant( 3875 isolate, Handle<BigInt>(intermediate_instant->nanoseconds(), isolate), 3876 duration.hours, duration.minutes, duration.seconds, duration.milliseconds, 3877 duration.microseconds, duration.nanoseconds); 3878} 3879 3880// #sec-temporal-nanosecondstodays 3881Maybe<bool> NanosecondsToDays(Isolate* isolate, int64_t nanoseconds, 3882 Handle<Object> relative_to_obj, 3883 int64_t* result_days, int64_t* result_nanoseconds, 3884 int64_t* result_day_length, 3885 const char* method_name) { 3886 return NanosecondsToDays(isolate, BigInt::FromInt64(isolate, nanoseconds), 3887 relative_to_obj, result_days, result_nanoseconds, 3888 result_day_length, method_name); 3889} 3890 3891Maybe<bool> NanosecondsToDays(Isolate* isolate, Handle<BigInt> nanoseconds, 3892 Handle<Object> relative_to_obj, 3893 int64_t* result_days, int64_t* result_nanoseconds, 3894 int64_t* result_day_length, 3895 const char* method_name) { 3896 TEMPORAL_ENTER_FUNC(); 3897 3898 // 1. Assert: Type(nanoseconds) is BigInt. 3899 // 2. Set nanoseconds to ℝ(nanoseconds). 3900 // 3. Let sign be ! ℝ(Sign((nanoseconds))). 3901 ComparisonResult compare_result = 3902 BigInt::CompareToBigInt(nanoseconds, BigInt::FromInt64(isolate, 0)); 3903 int64_t sign = COMPARE_RESULT_TO_SIGN(compare_result); 3904 // 4. Let dayLengthNs be 8.64 × 10^13. 3905 Handle<BigInt> day_length_ns = BigInt::FromInt64(isolate, 86400000000000LLU); 3906 // 5. If sign is 0, then 3907 if (sign == 0) { 3908 // a. Return the new Record { [[Days]]: 0, [[Nanoseconds]]: 0, 3909 // [[DayLength]]: dayLengthNs }. 3910 *result_days = 0; 3911 *result_nanoseconds = 0; 3912 *result_day_length = day_length_ns->AsInt64(); 3913 return Just(true); 3914 } 3915 // 6. If Type(relativeTo) is not Object or relativeTo does not have an 3916 // [[InitializedTemporalZonedDateTime]] internal slot, then 3917 if (!relative_to_obj->IsJSTemporalZonedDateTime()) { 3918 // Return the Record { 3919 // [[Days]]: the integral part of nanoseconds / dayLengthNs, 3920 // [[Nanoseconds]]: (abs(nanoseconds) modulo dayLengthNs) × sign, 3921 // [[DayLength]]: dayLengthNs }. 3922 Handle<BigInt> days_bigint; 3923 ASSIGN_RETURN_ON_EXCEPTION_VALUE( 3924 isolate, days_bigint, 3925 BigInt::Divide(isolate, nanoseconds, day_length_ns), Nothing<bool>()); 3926 3927 if (sign < 0) { 3928 nanoseconds = BigInt::UnaryMinus(isolate, nanoseconds); 3929 } 3930 3931 ASSIGN_RETURN_ON_EXCEPTION_VALUE( 3932 isolate, nanoseconds, 3933 BigInt::Remainder(isolate, nanoseconds, day_length_ns), 3934 Nothing<bool>()); 3935 *result_days = days_bigint->AsInt64(); 3936 *result_nanoseconds = nanoseconds->AsInt64() * sign; 3937 *result_day_length = day_length_ns->AsInt64(); 3938 return Just(true); 3939 } 3940 Handle<JSTemporalZonedDateTime> relative_to = 3941 Handle<JSTemporalZonedDateTime>::cast(relative_to_obj); 3942 // 7. Let startNs be ℝ(relativeTo.[[Nanoseconds]]). 3943 Handle<BigInt> start_ns = Handle<BigInt>(relative_to->nanoseconds(), isolate); 3944 // 8. Let startInstant be ! CreateTemporalInstant(ℤ(sartNs)). 3945 Handle<JSTemporalInstant> start_instant; 3946 ASSIGN_RETURN_ON_EXCEPTION_VALUE( 3947 isolate, start_instant, 3948 temporal::CreateTemporalInstant( 3949 isolate, Handle<BigInt>(relative_to->nanoseconds(), isolate)), 3950 Nothing<bool>()); 3951 3952 // 9. Let startDateTime be ? 3953 // BuiltinTimeZoneGetPlainDateTimeFor(relativeTo.[[TimeZone]], 3954 // startInstant, relativeTo.[[Calendar]]). 3955 Handle<JSReceiver> time_zone = 3956 Handle<JSReceiver>(relative_to->time_zone(), isolate); 3957 Handle<JSReceiver> calendar = 3958 Handle<JSReceiver>(relative_to->calendar(), isolate); 3959 Handle<JSTemporalPlainDateTime> start_date_time; 3960 ASSIGN_RETURN_ON_EXCEPTION_VALUE( 3961 isolate, start_date_time, 3962 temporal::BuiltinTimeZoneGetPlainDateTimeFor( 3963 isolate, time_zone, start_instant, calendar, method_name), 3964 Nothing<bool>()); 3965 3966 // 10. Let endNs be startNs + nanoseconds. 3967 Handle<BigInt> end_ns; 3968 ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, end_ns, 3969 BigInt::Add(isolate, start_ns, nanoseconds), 3970 Nothing<bool>()); 3971 3972 // 11. Let endInstant be ! CreateTemporalInstant(ℤ(endNs)). 3973 Handle<JSTemporalInstant> end_instant; 3974 ASSIGN_RETURN_ON_EXCEPTION_VALUE( 3975 isolate, end_instant, temporal::CreateTemporalInstant(isolate, end_ns), 3976 Nothing<bool>()); 3977 // 12. Let endDateTime be ? 3978 // BuiltinTimeZoneGetPlainDateTimeFor(relativeTo.[[TimeZone]], 3979 // endInstant, relativeTo.[[Calendar]]). 3980 Handle<JSTemporalPlainDateTime> end_date_time; 3981 ASSIGN_RETURN_ON_EXCEPTION_VALUE( 3982 isolate, end_date_time, 3983 temporal::BuiltinTimeZoneGetPlainDateTimeFor( 3984 isolate, time_zone, end_instant, calendar, method_name), 3985 Nothing<bool>()); 3986 3987 // 13. Let dateDifference be ? 3988 // DifferenceISODateTime(startDateTime.[[ISOYear]], 3989 // startDateTime.[[ISOMonth]], startDateTime.[[ISODay]], 3990 // startDateTime.[[ISOHour]], startDateTime.[[ISOMinute]], 3991 // startDateTime.[[ISOSecond]], startDateTime.[[ISOMillisecond]], 3992 // startDateTime.[[ISOMicrosecond]], startDateTime.[[ISONanosecond]], 3993 // endDateTime.[[ISOYear]], endDateTime.[[ISOMonth]], endDateTime.[[ISODay]], 3994 // endDateTime.[[ISOHour]], endDateTime.[[ISOMinute]], 3995 // endDateTime.[[ISOSecond]], endDateTime.[[ISOMillisecond]], 3996 // endDateTime.[[ISOMicrosecond]], endDateTime.[[ISONanosecond]], 3997 // relativeTo.[[Calendar]], "day"). 3998 Maybe<DurationRecord> maybe_date_difference = DifferenceISODateTime( 3999 isolate, start_date_time->iso_year(), start_date_time->iso_month(), 4000 start_date_time->iso_day(), start_date_time->iso_hour(), 4001 start_date_time->iso_minute(), start_date_time->iso_second(), 4002 start_date_time->iso_millisecond(), start_date_time->iso_microsecond(), 4003 start_date_time->iso_nanosecond(), end_date_time->iso_year(), 4004 end_date_time->iso_month(), end_date_time->iso_day(), 4005 end_date_time->iso_hour(), end_date_time->iso_minute(), 4006 end_date_time->iso_second(), end_date_time->iso_millisecond(), 4007 end_date_time->iso_microsecond(), end_date_time->iso_nanosecond(), 4008 calendar, Unit::kDay, relative_to, method_name); 4009 MAYBE_RETURN(maybe_date_difference, Nothing<bool>()); 4010 4011 DurationRecord date_difference = maybe_date_difference.FromJust(); 4012 // 14. Let days be dateDifference.[[Days]]. 4013 int64_t days = date_difference.days; 4014 4015 // 15. Let intermediateNs be ℝ(? AddZonedDateTime(ℤ(startNs), 4016 // relativeTo.[[TimeZone]], relativeTo.[[Calendar]], 0, 0, 0, days, 0, 0, 0, 4017 // 0, 0, 0)). 4018 Handle<BigInt> intermediate_ns; 4019 ASSIGN_RETURN_ON_EXCEPTION_VALUE( 4020 isolate, intermediate_ns, 4021 AddZonedDateTime(isolate, start_ns, time_zone, calendar, 4022 {0, 0, 0, days, 0, 0, 0, 0, 0, 0}, method_name), 4023 Nothing<bool>()); 4024 4025 // 16. If sign is 1, then 4026 if (sign == 1) { 4027 // a. Repeat, while days > 0 and intermediateNs > endNs, 4028 while (days > 0 && BigInt::CompareToBigInt(intermediate_ns, end_ns) == 4029 ComparisonResult::kGreaterThan) { 4030 // i. Set days to days − 1. 4031 days -= 1; 4032 // ii. Set intermediateNs to ℝ(? AddZonedDateTime(ℤ(startNs), 4033 // relativeTo.[[TimeZone]], relativeTo.[[Calendar]], 0, 0, 0, days, 0, 0, 4034 // 0, 0, 0, 0)). 4035 ASSIGN_RETURN_ON_EXCEPTION_VALUE( 4036 isolate, intermediate_ns, 4037 AddZonedDateTime(isolate, start_ns, time_zone, calendar, 4038 {0, 0, 0, days, 0, 0, 0, 0, 0, 0}, method_name), 4039 Nothing<bool>()); 4040 } 4041 } 4042 4043 // 17. Set nanoseconds to endNs − intermediateNs. 4044 ASSIGN_RETURN_ON_EXCEPTION_VALUE( 4045 isolate, nanoseconds, BigInt::Subtract(isolate, end_ns, intermediate_ns), 4046 Nothing<bool>()); 4047 4048 // 18. Let done be false. 4049 bool done = false; 4050 4051 // 19. Repeat, while done is false, 4052 while (!done) { 4053 // a. Let oneDayFartherNs be ℝ(? AddZonedDateTime(ℤ(intermediateNs), 4054 // relativeTo.[[TimeZone]], relativeTo.[[Calendar]], 0, 0, 0, sign, 0, 0, 0, 4055 // 0, 0, 0)). 4056 Handle<BigInt> one_day_farther_ns; 4057 ASSIGN_RETURN_ON_EXCEPTION_VALUE( 4058 isolate, one_day_farther_ns, 4059 AddZonedDateTime(isolate, intermediate_ns, time_zone, calendar, 4060 {0, 0, 0, sign, 0, 0, 0, 0, 0, 0}, method_name), 4061 Nothing<bool>()); 4062 4063 // b. Set dayLengthNs to oneDayFartherNs − intermediateNs. 4064 Handle<BigInt> day_length_ns; 4065 ASSIGN_RETURN_ON_EXCEPTION_VALUE( 4066 isolate, day_length_ns, 4067 BigInt::Subtract(isolate, one_day_farther_ns, intermediate_ns), 4068 Nothing<bool>()); 4069 4070 // c. If (nanoseconds − dayLengthNs) × sign ≥ 0, then 4071 compare_result = BigInt::CompareToBigInt(nanoseconds, day_length_ns); 4072 if (sign * COMPARE_RESULT_TO_SIGN(compare_result) >= 0) { 4073 // i. Set nanoseconds to nanoseconds − dayLengthNs. 4074 ASSIGN_RETURN_ON_EXCEPTION_VALUE( 4075 isolate, nanoseconds, 4076 BigInt::Subtract(isolate, nanoseconds, day_length_ns), 4077 Nothing<bool>()); 4078 4079 // ii. Set intermediateNs to oneDayFartherNs. 4080 intermediate_ns = one_day_farther_ns; 4081 4082 // iii. Set days to days + sign. 4083 days += sign; 4084 // d. Else, 4085 } else { 4086 // i. Set done to true. 4087 done = true; 4088 } 4089 } 4090 4091 // 20. Return the new Record { [[Days]]: days, [[Nanoseconds]]: nanoseconds, 4092 // [[DayLength]]: abs(dayLengthNs) }. 4093 *result_days = days; 4094 *result_nanoseconds = nanoseconds->AsInt64(); 4095 *result_day_length = std::abs(day_length_ns->AsInt64()); 4096 return Just(true); 4097} 4098 4099Maybe<DurationRecord> DifferenceISODateTime( 4100 Isolate* isolate, int32_t y1, int32_t mon1, int32_t d1, int32_t h1, 4101 int32_t min1, int32_t s1, int32_t ms1, int32_t mus1, int32_t ns1, 4102 int32_t y2, int32_t mon2, int32_t d2, int32_t h2, int32_t min2, int32_t s2, 4103 int32_t ms2, int32_t mus2, int32_t ns2, Handle<JSReceiver> calendar, 4104 Unit largest_unit, Handle<Object> options_obj, const char* method_name) { 4105 TEMPORAL_ENTER_FUNC(); 4106 4107 Factory* factory = isolate->factory(); 4108 DurationRecord result; 4109 // 1. Assert: y1, mon1, d1, h1, min1, s1, ms1, mus1, ns1, y2, mon2, d2, h2, 4110 // min2, s2, ms2, mus2, and ns2 are integers. 4111 // 2. If options is not present, set options to ! OrdinaryObjectCreate(null). 4112 Handle<JSReceiver> options; 4113 if (options_obj->IsUndefined()) { 4114 options = factory->NewJSObjectWithNullProto(); 4115 } else { 4116 DCHECK(options_obj->IsJSReceiver()); 4117 options = Handle<JSReceiver>::cast(options_obj); 4118 } 4119 // 3. Let timeDifference be ! DifferenceTime(h1, min1, s1, ms1, mus1, ns1, h2, 4120 // min2, s2, ms2, mus2, ns2). 4121 DurationRecord time_difference = DifferenceTime( 4122 isolate, h1, min1, s1, ms1, mus1, ns1, h2, min2, s2, ms2, mus2, ns2); 4123 4124 result.hours = time_difference.hours; 4125 result.minutes = time_difference.minutes; 4126 result.seconds = time_difference.seconds; 4127 result.milliseconds = time_difference.milliseconds; 4128 result.microseconds = time_difference.microseconds; 4129 result.nanoseconds = time_difference.nanoseconds; 4130 4131 // 4. Let timeSign be ! DurationSign(0, 0, 0, timeDifference.[[Days]], 4132 // timeDifference.[[Hours]], timeDifference.[[Minutes]], 4133 // timeDifference.[[Seconds]], timeDifference.[[Milliseconds]], 4134 // timeDifference.[[Microseconds]], timeDifference.[[Nanoseconds]]). 4135 int32_t time_sign = DurationSign(isolate, time_difference); 4136 // 5. Let dateSign be ! CompareISODate(y2, mon2, d2, y1, mon1, d1). 4137 int32_t date_sign = CompareISODate(isolate, y2, mon2, d2, y1, mon1, d1); 4138 // 6. Let balanceResult be ! BalanceISODate(y1, mon1, d1 + 4139 // timeDifference.[[Days]]). 4140 int32_t balanced_year = y1; 4141 int32_t balanced_month = mon1; 4142 int32_t balanced_day = d1 + static_cast<int32_t>(time_difference.days); 4143 BalanceISODate(isolate, &balanced_year, &balanced_month, &balanced_day); 4144 4145 // 7. If timeSign is -dateSign, then 4146 if (time_sign == -date_sign) { 4147 // a. Set balanceResult be ! BalanceISODate(balanceResult.[[Year]], 4148 // balanceResult.[[Month]], balanceResult.[[Day]] - timeSign). 4149 balanced_day -= time_sign; 4150 BalanceISODate(isolate, &balanced_year, &balanced_month, &balanced_day); 4151 // b. Set timeDifference to ? BalanceDuration(-timeSign, 4152 // timeDifference.[[Hours]], timeDifference.[[Minutes]], 4153 // timeDifference.[[Seconds]], timeDifference.[[Milliseconds]], 4154 // timeDifference.[[Microseconds]], timeDifference.[[Nanoseconds]], 4155 // largestUnit). 4156 result.days = -time_sign; 4157 result.hours = time_difference.hours; 4158 result.minutes = time_difference.minutes; 4159 result.seconds = time_difference.seconds; 4160 result.milliseconds = time_difference.milliseconds; 4161 result.microseconds = time_difference.microseconds; 4162 result.nanoseconds = time_difference.nanoseconds; 4163 4164 Maybe<bool> maybe_time_difference = BalanceDuration( 4165 isolate, &(result.days), &(result.hours), &(result.minutes), 4166 &(result.seconds), &(result.milliseconds), &(result.microseconds), 4167 &(result.nanoseconds), largest_unit, method_name); 4168 MAYBE_RETURN(maybe_time_difference, Nothing<DurationRecord>()); 4169 DCHECK(maybe_time_difference.FromJust()); 4170 } 4171 // 8. Let date1 be ? CreateTemporalDate(balanceResult.[[Year]], 4172 // balanceResult.[[Month]], balanceResult.[[Day]], calendar). 4173 Handle<JSTemporalPlainDate> date1; 4174 ASSIGN_RETURN_ON_EXCEPTION_VALUE( 4175 isolate, date1, 4176 CreateTemporalDate(isolate, balanced_year, balanced_month, balanced_day, 4177 calendar), 4178 Nothing<DurationRecord>()); 4179 // 9. Let date2 be ? CreateTemporalDate(y2, mon2, d2, calendar). 4180 Handle<JSTemporalPlainDate> date2; 4181 ASSIGN_RETURN_ON_EXCEPTION_VALUE( 4182 isolate, date2, CreateTemporalDate(isolate, y2, mon2, d2, calendar), 4183 Nothing<DurationRecord>()); 4184 // 10. Let dateLargestUnit be ! LargerOfTwoTemporalUnits("day", largestUnit). 4185 Unit date_largest_unit = 4186 LargerOfTwoTemporalUnits(isolate, Unit::kDay, largest_unit); 4187 4188 // 11. Let untilOptions be ? MergeLargestUnitOption(options, dateLargestUnit). 4189 Handle<JSObject> until_options; 4190 ASSIGN_RETURN_ON_EXCEPTION_VALUE( 4191 isolate, until_options, 4192 MergeLargestUnitOption(isolate, options, date_largest_unit), 4193 Nothing<DurationRecord>()); 4194 // 12. Let dateDifference be ? CalendarDateUntil(calendar, date1, date2, 4195 // untilOptions). 4196 Handle<JSTemporalDuration> date_difference; 4197 ASSIGN_RETURN_ON_EXCEPTION_VALUE( 4198 isolate, date_difference, 4199 CalendarDateUntil(isolate, calendar, date1, date2, until_options), 4200 Nothing<DurationRecord>()); 4201 // 13. Let balanceResult be ? BalanceDuration(dateDifference.[[Days]], 4202 // timeDifference.[[Hours]], timeDifference.[[Minutes]], 4203 // timeDifference.[[Seconds]], timeDifference.[[Milliseconds]], 4204 // timeDifference.[[Microseconds]], timeDifference.[[Nanoseconds]], 4205 // largestUnit). 4206 result.days = NumberToInt64(date_difference->days()); 4207 4208 Maybe<bool> maybe_balance_result = BalanceDuration( 4209 isolate, &(result.days), &(result.hours), &(result.minutes), 4210 &(result.seconds), &(result.milliseconds), &(result.microseconds), 4211 &(result.nanoseconds), largest_unit, method_name); 4212 MAYBE_RETURN(maybe_balance_result, Nothing<DurationRecord>()); 4213 DCHECK(maybe_balance_result.FromJust()); 4214 // 14. Return the Record { [[Years]]: dateDifference.[[Years]], [[Months]]: 4215 // dateDifference.[[Months]], [[Weeks]]: dateDifference.[[Weeks]], [[Days]]: 4216 // balanceResult.[[Days]], [[Hours]]: balanceResult.[[Hours]], [[Minutes]]: 4217 // balanceResult.[[Minutes]], [[Seconds]]: balanceResult.[[Seconds]], 4218 // [[Milliseconds]]: balanceResult.[[Milliseconds]], [[Microseconds]]: 4219 // balanceResult.[[Microseconds]], [[Nanoseconds]]: 4220 // balanceResult.[[Nanoseconds]] }. 4221 result.years = NumberToInt64(date_difference->years()); 4222 result.months = NumberToInt64(date_difference->months()); 4223 result.weeks = NumberToInt64(date_difference->weeks()); 4224 return Just(result); 4225} 4226 4227// #sec-temporal-addinstant 4228MaybeHandle<BigInt> AddInstant(Isolate* isolate, 4229 Handle<BigInt> epoch_nanoseconds, int64_t hours, 4230 int64_t minutes, int64_t seconds, 4231 int64_t milliseconds, int64_t microseconds, 4232 int64_t nanoseconds) { 4233 TEMPORAL_ENTER_FUNC(); 4234 4235 // 1. Assert: hours, minutes, seconds, milliseconds, microseconds, and 4236 // nanoseconds are integer Number values. 4237 // 2. Let result be epochNanoseconds + ℤ(nanoseconds) + 4238 // ℤ(microseconds) × 1000ℤ + ℤ(milliseconds) × 10^6ℤ + ℤ(seconds) × 10^9ℤ + 4239 // ℤ(minutes) × 60ℤ × 10^9ℤ + ℤ(hours) × 3600ℤ × 10^9ℤ. 4240 Handle<BigInt> result; 4241 ASSIGN_RETURN_ON_EXCEPTION( 4242 isolate, result, 4243 BigInt::Add(isolate, epoch_nanoseconds, 4244 BigInt::FromInt64(isolate, nanoseconds)), 4245 BigInt); 4246 Handle<BigInt> temp; 4247 ASSIGN_RETURN_ON_EXCEPTION( 4248 isolate, temp, 4249 BigInt::Multiply(isolate, BigInt::FromInt64(isolate, microseconds), 4250 BigInt::FromInt64(isolate, 1000)), 4251 BigInt); 4252 ASSIGN_RETURN_ON_EXCEPTION(isolate, result, 4253 BigInt::Add(isolate, result, temp), BigInt); 4254 4255 ASSIGN_RETURN_ON_EXCEPTION( 4256 isolate, temp, 4257 BigInt::Multiply(isolate, BigInt::FromInt64(isolate, milliseconds), 4258 BigInt::FromInt64(isolate, 1000000)), 4259 BigInt); 4260 ASSIGN_RETURN_ON_EXCEPTION(isolate, result, 4261 BigInt::Add(isolate, result, temp), BigInt); 4262 4263 ASSIGN_RETURN_ON_EXCEPTION( 4264 isolate, temp, 4265 BigInt::Multiply(isolate, BigInt::FromInt64(isolate, seconds), 4266 BigInt::FromInt64(isolate, 1000000000)), 4267 BigInt); 4268 ASSIGN_RETURN_ON_EXCEPTION(isolate, result, 4269 BigInt::Add(isolate, result, temp), BigInt); 4270 4271 ASSIGN_RETURN_ON_EXCEPTION( 4272 isolate, temp, 4273 BigInt::Multiply(isolate, BigInt::FromInt64(isolate, minutes), 4274 BigInt::FromInt64(isolate, 1000000000)), 4275 BigInt); 4276 ASSIGN_RETURN_ON_EXCEPTION( 4277 isolate, temp, 4278 BigInt::Multiply(isolate, temp, BigInt::FromInt64(isolate, 60)), BigInt); 4279 ASSIGN_RETURN_ON_EXCEPTION(isolate, result, 4280 BigInt::Add(isolate, result, temp), BigInt); 4281 4282 ASSIGN_RETURN_ON_EXCEPTION( 4283 isolate, temp, 4284 BigInt::Multiply(isolate, BigInt::FromInt64(isolate, hours), 4285 BigInt::FromInt64(isolate, 1000000000)), 4286 BigInt); 4287 ASSIGN_RETURN_ON_EXCEPTION( 4288 isolate, temp, 4289 BigInt::Multiply(isolate, temp, BigInt::FromInt64(isolate, 3600)), 4290 BigInt); 4291 ASSIGN_RETURN_ON_EXCEPTION(isolate, result, 4292 BigInt::Add(isolate, result, temp), BigInt); 4293 4294 // 3. If ! IsValidEpochNanoseconds(result) is false, throw a RangeError 4295 // exception. 4296 if (!IsValidEpochNanoseconds(isolate, result)) { 4297 THROW_NEW_ERROR(isolate, NEW_TEMPORAL_INVALD_ARG_RANGE_ERROR(), BigInt); 4298 } 4299 // 4. Return result. 4300 return result; 4301} 4302 4303// #sec-temporal-isvalidepochnanoseconds 4304bool IsValidEpochNanoseconds(Isolate* isolate, 4305 Handle<BigInt> epoch_nanoseconds) { 4306 TEMPORAL_ENTER_FUNC(); 4307 4308 // 1. Assert: Type(epochNanoseconds) is BigInt. 4309 // 2. If epochNanoseconds < −86400ℤ × 10^17ℤ or epochNanoseconds > 86400ℤ × 4310 // 10^17ℤ, then a. Return false. 4311 // 3. Return true. 4312 int64_t ns = epoch_nanoseconds->AsInt64(); 4313 return !(ns < -86400 * 1e17 || ns > 86400 * 1e17); 4314} 4315 4316MaybeHandle<BigInt> GetEpochFromISOParts(Isolate* isolate, int32_t year, 4317 int32_t month, int32_t day, 4318 int32_t hour, int32_t minute, 4319 int32_t second, int32_t millisecond, 4320 int32_t microsecond, 4321 int32_t nanosecond) { 4322 TEMPORAL_ENTER_FUNC(); 4323 // 1. Assert: year, month, day, hour, minute, second, millisecond, 4324 // microsecond, and nanosecond are integers. 4325 // 2. Assert: ! IsValidISODate(year, month, day) is true. 4326 DCHECK(IsValidISODate(isolate, year, month, day)); 4327 // 3. Assert: ! IsValidTime(hour, minute, second, millisecond, microsecond, 4328 // nanosecond) is true. 4329 DCHECK(IsValidTime(isolate, hour, minute, second, millisecond, microsecond, 4330 nanosecond)); 4331 // 4. Let date be ! MakeDay((year), (month − 1), (day)). 4332 double date = MakeDay(year, month - 1, day); 4333 // 5. Let time be ! MakeTime((hour), (minute), (second), (millisecond)). 4334 double time = MakeTime(hour, minute, second, millisecond); 4335 // 6. Let ms be ! MakeDate(date, time). 4336 double ms = MakeDate(date, time); 4337 // 7. Assert: ms is finite. 4338 // 8. Return ℝ(ms) × 10^6 + microsecond × 10^3 + nanosecond. 4339 Handle<BigInt> result; 4340 ASSIGN_RETURN_ON_EXCEPTION( 4341 isolate, result, 4342 BigInt::FromNumber(isolate, isolate->factory()->NewNumber(ms)), BigInt); 4343 4344 ASSIGN_RETURN_ON_EXCEPTION( 4345 isolate, result, 4346 BigInt::Multiply(isolate, result, BigInt::FromInt64(isolate, 1000000)), 4347 BigInt); 4348 4349 Handle<BigInt> temp; 4350 ASSIGN_RETURN_ON_EXCEPTION( 4351 isolate, temp, 4352 BigInt::Multiply(isolate, BigInt::FromInt64(isolate, microsecond), 4353 BigInt::FromInt64(isolate, 1000)), 4354 BigInt); 4355 4356 ASSIGN_RETURN_ON_EXCEPTION(isolate, result, 4357 BigInt::Add(isolate, result, temp), BigInt); 4358 return BigInt::Add(isolate, result, BigInt::FromInt64(isolate, nanosecond)); 4359} 4360 4361// #sec-temporal-durationsign 4362int32_t DurationSign(Isolate* isolaet, const DurationRecord& dur) { 4363 TEMPORAL_ENTER_FUNC(); 4364 4365 // 1. For each value v of « years, months, weeks, days, hours, minutes, 4366 // seconds, milliseconds, microseconds, nanoseconds », do a. If v < 0, return 4367 // −1. b. If v > 0, return 1. 4368 // 2. Return 0. 4369 if (dur.years < 0) return -1; 4370 if (dur.years > 0) return 1; 4371 if (dur.months < 0) return -1; 4372 if (dur.months > 0) return 1; 4373 if (dur.weeks < 0) return -1; 4374 if (dur.weeks > 0) return 1; 4375 if (dur.days < 0) return -1; 4376 if (dur.days > 0) return 1; 4377 if (dur.hours < 0) return -1; 4378 if (dur.hours > 0) return 1; 4379 if (dur.minutes < 0) return -1; 4380 if (dur.minutes > 0) return 1; 4381 if (dur.seconds < 0) return -1; 4382 if (dur.seconds > 0) return 1; 4383 if (dur.milliseconds < 0) return -1; 4384 if (dur.milliseconds > 0) return 1; 4385 if (dur.microseconds < 0) return -1; 4386 if (dur.microseconds > 0) return 1; 4387 if (dur.nanoseconds < 0) return -1; 4388 if (dur.nanoseconds > 0) return 1; 4389 return 0; 4390} 4391 4392// #sec-temporal-isvalidduration 4393bool IsValidDuration(Isolate* isolate, const DurationRecord& dur) { 4394 TEMPORAL_ENTER_FUNC(); 4395 4396 // 1. Let sign be ! DurationSign(years, months, weeks, days, hours, minutes, 4397 // seconds, milliseconds, microseconds, nanoseconds). 4398 int32_t sign = DurationSign(isolate, dur); 4399 // 2. For each value v of « years, months, weeks, days, hours, minutes, 4400 // seconds, milliseconds, microseconds, nanoseconds », do a. If v is not 4401 // finite, return false. b. If v < 0 and sign > 0, return false. c. If v > 0 4402 // and sign < 0, return false. 4403 // 3. Return true. 4404 return !((sign > 0 && (dur.years < 0 || dur.months < 0 || dur.weeks < 0 || 4405 dur.days < 0 || dur.hours < 0 || dur.minutes < 0 || 4406 dur.seconds < 0 || dur.milliseconds < 0 || 4407 dur.microseconds < 0 || dur.nanoseconds < 0)) || 4408 (sign < 0 && (dur.years > 0 || dur.months > 0 || dur.weeks > 0 || 4409 dur.days > 0 || dur.hours > 0 || dur.minutes > 0 || 4410 dur.seconds > 0 || dur.milliseconds > 0 || 4411 dur.microseconds > 0 || dur.nanoseconds > 0))); 4412} 4413 4414// #sec-temporal-isisoleapyear 4415bool IsISOLeapYear(Isolate* isolate, int32_t year) { 4416 TEMPORAL_ENTER_FUNC(); 4417 4418 // 1. Assert: year is an integer. 4419 // 2. If year modulo 4 ≠ 0, return false. 4420 // 3. If year modulo 400 = 0, return true. 4421 // 4. If year modulo 100 = 0, return false. 4422 // 5. Return true. 4423 return isolate->date_cache()->IsLeap(year); 4424} 4425 4426// #sec-temporal-isodaysinmonth 4427int32_t ISODaysInMonth(Isolate* isolate, int32_t year, int32_t month) { 4428 TEMPORAL_ENTER_FUNC(); 4429 4430 // 1. Assert: year is an integer. 4431 // 2. Assert: month is an integer, month ≥ 1, and month ≤ 12. 4432 DCHECK_GE(month, 1); 4433 DCHECK_LE(month, 12); 4434 // 3. If month is 1, 3, 5, 7, 8, 10, or 12, return 31. 4435 if (month % 2 == ((month < 8) ? 1 : 0)) return 31; 4436 // 4. If month is 4, 6, 9, or 11, return 30. 4437 DCHECK(month == 2 || month == 4 || month == 6 || month == 9 || month == 11); 4438 if (month != 2) return 30; 4439 // 5. If ! IsISOLeapYear(year) is true, return 29. 4440 return IsISOLeapYear(isolate, year) ? 29 : 28; 4441 // 6. Return 28. 4442} 4443 4444// #sec-temporal-isodaysinyear 4445int32_t ISODaysInYear(Isolate* isolate, int32_t year) { 4446 TEMPORAL_ENTER_FUNC(); 4447 4448 // 1. Assert: year is an integer. 4449 // 2. If ! IsISOLeapYear(year) is true, then 4450 // a. Return 366. 4451 // 3. Return 365. 4452 return IsISOLeapYear(isolate, year) ? 366 : 365; 4453} 4454 4455bool IsValidTime(Isolate* isolate, int32_t hour, int32_t minute, int32_t second, 4456 int32_t millisecond, int32_t microsecond, int32_t nanosecond) { 4457 TEMPORAL_ENTER_FUNC(); 4458 4459 // 2. If hour < 0 or hour > 23, then 4460 // a. Return false. 4461 if (hour < 0 || hour > 23) return false; 4462 // 3. If minute < 0 or minute > 59, then 4463 // a. Return false. 4464 if (minute < 0 || minute > 59) return false; 4465 // 4. If second < 0 or second > 59, then 4466 // a. Return false. 4467 if (second < 0 || second > 59) return false; 4468 // 5. If millisecond < 0 or millisecond > 999, then 4469 // a. Return false. 4470 if (millisecond < 0 || millisecond > 999) return false; 4471 // 6. If microsecond < 0 or microsecond > 999, then 4472 // a. Return false. 4473 if (microsecond < 0 || microsecond > 999) return false; 4474 // 7. If nanosecond < 0 or nanosecond > 999, then 4475 // a. Return false. 4476 if (nanosecond < 0 || nanosecond > 999) return false; 4477 // 8. Return true. 4478 return true; 4479} 4480 4481// #sec-temporal-isvalidisodate 4482bool IsValidISODate(Isolate* isolate, int32_t year, int32_t month, 4483 int32_t day) { 4484 TEMPORAL_ENTER_FUNC(); 4485 4486 // 1. Assert: year, month, and day are integers. 4487 // 2. If month < 1 or month > 12, then 4488 // a. Return false. 4489 if (month < 1 || month > 12) return false; 4490 // 3. Let daysInMonth be ! ISODaysInMonth(year, month). 4491 // 4. If day < 1 or day > daysInMonth, then 4492 // a. Return false. 4493 if (day < 1 || day > ISODaysInMonth(isolate, year, month)) return false; 4494 // 5. Return true. 4495 return true; 4496} 4497 4498// #sec-temporal-compareisodate 4499int32_t CompareISODate(Isolate* isolate, int32_t y1, int32_t m1, int32_t d1, 4500 int32_t y2, int32_t m2, int32_t d2) { 4501 TEMPORAL_ENTER_FUNC(); 4502 4503 // 1. Assert: y1, m1, d1, y2, m2, and d2 are integers. 4504 // 2. If y1 > y2, return 1. 4505 if (y1 > y2) return 1; 4506 // 3. If y1 < y2, return -1. 4507 if (y1 < y2) return -1; 4508 // 4. If m1 > m2, return 1. 4509 if (m1 > m2) return 1; 4510 // 5. If m1 < m2, return -1. 4511 if (m1 < m2) return -1; 4512 // 6. If d1 > d2, return 1. 4513 if (d1 > d2) return 1; 4514 // 7. If d1 < d2, return -1. 4515 if (d1 < d2) return -1; 4516 // 8. Return 0. 4517 return 0; 4518} 4519 4520// #sec-temporal-balanceisoyearmonth 4521void BalanceISOYearMonth(Isolate* isolate, int32_t* year, int32_t* month) { 4522 TEMPORAL_ENTER_FUNC(); 4523 4524 // 1. Assert: year and month are integers. 4525 // 2. Set year to year + floor((month - 1) / 12). 4526 *year += floor_divide((*month - 1), 12); 4527 // 3. Set month to (month − 1) modulo 12 + 1. 4528 *month = static_cast<int32_t>(modulo(*month - 1, 12)) + 1; 4529 4530 // 4. Return the new Record { [[Year]]: year, [[Month]]: month }. 4531} 4532// #sec-temporal-balancetime 4533DateTimeRecordCommon BalanceTime(Isolate* isolate, int64_t hour, int64_t minute, 4534 int64_t second, int64_t millisecond, 4535 int64_t microsecond, int64_t nanosecond) { 4536 TEMPORAL_ENTER_FUNC(); 4537 4538 // 1. Assert: hour, minute, second, millisecond, microsecond, and nanosecond 4539 // are integers. 4540 // 2. Set microsecond to microsecond + floor(nanosecond / 1000). 4541 microsecond += floor_divide(nanosecond, 1000L); 4542 // 3. Set nanosecond to nanosecond modulo 1000. 4543 nanosecond = modulo(nanosecond, 1000L); 4544 // 4. Set millisecond to millisecond + floor(microsecond / 1000). 4545 millisecond += floor_divide(microsecond, 1000L); 4546 // 5. Set microsecond to microsecond modulo 1000. 4547 microsecond = modulo(microsecond, 1000L); 4548 // 6. Set second to second + floor(millisecond / 1000). 4549 second += floor_divide(millisecond, 1000L); 4550 // 7. Set millisecond to millisecond modulo 1000. 4551 millisecond = modulo(millisecond, 1000L); 4552 // 8. Set minute to minute + floor(second / 60). 4553 minute += floor_divide(second, 60L); 4554 // 9. Set second to second modulo 60. 4555 second = modulo(second, 60L); 4556 // 10. Set hour to hour + floor(minute / 60). 4557 hour += floor_divide(minute, 60L); 4558 // 11. Set minute to minute modulo 60. 4559 minute = modulo(minute, 60L); 4560 // 12. Let days be floor(hour / 24). 4561 int64_t days = floor_divide(hour, 24L); 4562 // 13. Set hour to hour modulo 24. 4563 hour = modulo(hour, 24L); 4564 // 14. Return the new Record { [[Days]]: days, [[Hour]]: hour, [[Minute]]: 4565 // minute, [[Second]]: second, [[Millisecond]]: millisecond, [[Microsecond]]: 4566 // microsecond, [[Nanosecond]]: nanosecond }. 4567 return {0, 4568 0, 4569 static_cast<int32_t>(days), 4570 static_cast<int32_t>(hour), 4571 static_cast<int32_t>(minute), 4572 static_cast<int32_t>(second), 4573 static_cast<int32_t>(millisecond), 4574 static_cast<int32_t>(microsecond), 4575 static_cast<int32_t>(nanosecond)}; 4576} 4577 4578// #sec-temporal-differencetime 4579DurationRecord DifferenceTime(Isolate* isolate, int32_t h1, int32_t min1, 4580 int32_t s1, int32_t ms1, int32_t mus1, 4581 int32_t ns1, int32_t h2, int32_t min2, int32_t s2, 4582 int32_t ms2, int32_t mus2, int32_t ns2) { 4583 TEMPORAL_ENTER_FUNC(); 4584 4585 // 1. Assert: h1, min1, s1, ms1, mus1, ns1, h2, min2, s2, ms2, mus2, and ns2 4586 // are integers. 4587 DurationRecord dur; 4588 // 2. Let hours be h2 − h1. 4589 dur.hours = h2 - h1; 4590 // 3. Let minutes be min2 − min1. 4591 dur.minutes = min2 - min1; 4592 // 4. Let seconds be s2 − s1. 4593 dur.seconds = s2 - s1; 4594 // 5. Let milliseconds be ms2 − ms1. 4595 dur.milliseconds = ms2 - ms1; 4596 // 6. Let microseconds be mus2 − mus1. 4597 dur.microseconds = mus2 - mus1; 4598 // 7. Let nanoseconds be ns2 − ns1. 4599 dur.nanoseconds = ns2 - ns1; 4600 // 8. Let sign be ! DurationSign(0, 0, 0, 0, hours, minutes, seconds, 4601 // milliseconds, microseconds, nanoseconds). 4602 double sign = DurationSign(isolate, dur); 4603 4604 // See https://github.com/tc39/proposal-temporal/pull/1885 4605 // 9. Let bt be ! BalanceTime(hours × sign, minutes × sign, seconds × sign, 4606 // milliseconds × sign, microseconds × sign, nanoseconds × sign). 4607 DateTimeRecordCommon bt = BalanceTime( 4608 isolate, dur.hours * sign, dur.minutes * sign, dur.seconds * sign, 4609 dur.milliseconds * sign, dur.microseconds * sign, dur.nanoseconds * sign); 4610 4611 // 10. Return the new Record { [[Days]]: bt.[[Days]] × sign, [[Hours]]: 4612 // bt.[[Hour]] × sign, [[Minutes]]: bt.[[Minute]] × sign, [[Seconds]]: 4613 // bt.[[Second]] × sign, [[Milliseconds]]: bt.[[Millisecond]] × sign, 4614 // [[Microseconds]]: bt.[[Microsecond]] × sign, [[Nanoseconds]]: 4615 // bt.[[Nanosecond]] × sign }. 4616 return {0, 4617 0, 4618 0, 4619 static_cast<int64_t>(bt.day * sign), 4620 static_cast<int64_t>(bt.hour * sign), 4621 static_cast<int64_t>(bt.minute * sign), 4622 static_cast<int64_t>(bt.second * sign), 4623 static_cast<int64_t>(bt.millisecond * sign), 4624 static_cast<int64_t>(bt.microsecond * sign), 4625 static_cast<int64_t>(bt.nanosecond * sign)}; 4626} 4627 4628// #sec-temporal-addtime 4629DateTimeRecordCommon AddTime(Isolate* isolate, int64_t hour, int64_t minute, 4630 int64_t second, int64_t millisecond, 4631 int64_t microsecond, int64_t nanosecond, 4632 int64_t hours, int64_t minutes, int64_t seconds, 4633 int64_t milliseconds, int64_t microseconds, 4634 int64_t nanoseconds) { 4635 TEMPORAL_ENTER_FUNC(); 4636 4637 // 1. Assert: hour, minute, second, millisecond, microsecond, nanosecond, 4638 // hours, minutes, seconds, milliseconds, microseconds, and nanoseconds are 4639 // integers. 4640 // 2. Let hour be hour + hours. 4641 return BalanceTime(isolate, hour + hours, 4642 // 3. Let minute be minute + minutes. 4643 minute + minutes, 4644 // 4. Let second be second + seconds. 4645 second + seconds, 4646 // 5. Let millisecond be millisecond + milliseconds. 4647 millisecond + milliseconds, 4648 // 6. Let microsecond be microsecond + microseconds. 4649 microsecond + microseconds, 4650 // 7. Let nanosecond be nanosecond + nanoseconds. 4651 nanosecond + nanoseconds); 4652 // 8. Return ! BalanceTime(hour, minute, second, millisecond, microsecond, 4653 // nanosecond). 4654} 4655 4656// #sec-temporal-totaldurationnanoseconds 4657int64_t TotalDurationNanoseconds(Isolate* isolate, int64_t days, int64_t hours, 4658 int64_t minutes, int64_t seconds, 4659 int64_t milliseconds, int64_t microseconds, 4660 int64_t nanoseconds, int64_t offset_shift) { 4661 TEMPORAL_ENTER_FUNC(); 4662 4663 // 1. Assert: offsetShift is an integer. 4664 // 2. Set nanoseconds to ℝ(nanoseconds). 4665 // 3. If days ≠ 0, then 4666 if (days != 0) { 4667 // a. Set nanoseconds to nanoseconds − offsetShift. 4668 nanoseconds -= offset_shift; 4669 } 4670 4671 // 4. Set hours to ℝ(hours) + ℝ(days) × 24. 4672 hours += days * 24; 4673 4674 // 5. Set minutes to ℝ(minutes) + hours × 60. 4675 minutes += hours * 60; 4676 4677 // 6. Set seconds to ℝ(seconds) + minutes × 60. 4678 seconds += minutes * 60; 4679 4680 // 7. Set milliseconds to ℝ(milliseconds) + seconds × 1000. 4681 milliseconds += seconds * 1000; 4682 4683 // 8. Set microseconds to ℝ(microseconds) + milliseconds × 1000. 4684 microseconds += milliseconds * 1000; 4685 4686 // 9. Return nanoseconds + microseconds × 1000. 4687 return nanoseconds + microseconds * 1000; 4688} 4689 4690} // namespace 4691 4692// #sec-temporal.duration 4693MaybeHandle<JSTemporalDuration> JSTemporalDuration::Constructor( 4694 Isolate* isolate, Handle<JSFunction> target, Handle<HeapObject> new_target, 4695 Handle<Object> years, Handle<Object> months, Handle<Object> weeks, 4696 Handle<Object> days, Handle<Object> hours, Handle<Object> minutes, 4697 Handle<Object> seconds, Handle<Object> milliseconds, 4698 Handle<Object> microseconds, Handle<Object> nanoseconds) { 4699 const char* method_name = "Temporal.Duration"; 4700 // 1. If NewTarget is undefined, then 4701 if (new_target->IsUndefined()) { 4702 // a. Throw a TypeError exception. 4703 THROW_NEW_ERROR(isolate, 4704 NewTypeError(MessageTemplate::kMethodInvokedOnWrongType, 4705 isolate->factory()->NewStringFromAsciiChecked( 4706 method_name)), 4707 JSTemporalDuration); 4708 } 4709 // 2. Let y be ? ToIntegerThrowOnInfinity(years). 4710 Handle<Object> number_years; 4711 ASSIGN_RETURN_ON_EXCEPTION(isolate, number_years, 4712 ToIntegerThrowOnInfinity(isolate, years), 4713 JSTemporalDuration); 4714 int64_t y = NumberToInt64(*number_years); 4715 4716 // 3. Let mo be ? ToIntegerThrowOnInfinity(months). 4717 Handle<Object> number_months; 4718 ASSIGN_RETURN_ON_EXCEPTION(isolate, number_months, 4719 ToIntegerThrowOnInfinity(isolate, months), 4720 JSTemporalDuration); 4721 int64_t mo = NumberToInt64(*number_months); 4722 4723 // 4. Let w be ? ToIntegerThrowOnInfinity(weeks). 4724 Handle<Object> number_weeks; 4725 ASSIGN_RETURN_ON_EXCEPTION(isolate, number_weeks, 4726 ToIntegerThrowOnInfinity(isolate, weeks), 4727 JSTemporalDuration); 4728 int64_t w = NumberToInt64(*number_weeks); 4729 4730 // 5. Let d be ? ToIntegerThrowOnInfinity(days). 4731 Handle<Object> number_days; 4732 ASSIGN_RETURN_ON_EXCEPTION(isolate, number_days, 4733 ToIntegerThrowOnInfinity(isolate, days), 4734 JSTemporalDuration); 4735 int64_t d = NumberToInt64(*number_days); 4736 4737 // 6. Let h be ? ToIntegerThrowOnInfinity(hours). 4738 Handle<Object> number_hours; 4739 ASSIGN_RETURN_ON_EXCEPTION(isolate, number_hours, 4740 ToIntegerThrowOnInfinity(isolate, hours), 4741 JSTemporalDuration); 4742 int64_t h = NumberToInt64(*number_hours); 4743 4744 // 7. Let m be ? ToIntegerThrowOnInfinity(minutes). 4745 Handle<Object> number_minutes; 4746 ASSIGN_RETURN_ON_EXCEPTION(isolate, number_minutes, 4747 ToIntegerThrowOnInfinity(isolate, minutes), 4748 JSTemporalDuration); 4749 int64_t m = NumberToInt64(*number_minutes); 4750 4751 // 8. Let s be ? ToIntegerThrowOnInfinity(seconds). 4752 Handle<Object> number_seconds; 4753 ASSIGN_RETURN_ON_EXCEPTION(isolate, number_seconds, 4754 ToIntegerThrowOnInfinity(isolate, seconds), 4755 JSTemporalDuration); 4756 int64_t s = NumberToInt64(*number_seconds); 4757 4758 // 9. Let ms be ? ToIntegerThrowOnInfinity(milliseconds). 4759 Handle<Object> number_milliseconds; 4760 ASSIGN_RETURN_ON_EXCEPTION(isolate, number_milliseconds, 4761 ToIntegerThrowOnInfinity(isolate, milliseconds), 4762 JSTemporalDuration); 4763 int64_t ms = NumberToInt64(*number_milliseconds); 4764 4765 // 10. Let mis be ? ToIntegerThrowOnInfinity(microseconds). 4766 Handle<Object> number_microseconds; 4767 ASSIGN_RETURN_ON_EXCEPTION(isolate, number_microseconds, 4768 ToIntegerThrowOnInfinity(isolate, microseconds), 4769 JSTemporalDuration); 4770 int64_t mis = NumberToInt64(*number_microseconds); 4771 4772 // 11. Let ns be ? ToIntegerThrowOnInfinity(nanoseconds). 4773 Handle<Object> number_nanoseconds; 4774 ASSIGN_RETURN_ON_EXCEPTION(isolate, number_nanoseconds, 4775 ToIntegerThrowOnInfinity(isolate, nanoseconds), 4776 JSTemporalDuration); 4777 int64_t ns = NumberToInt64(*number_nanoseconds); 4778 4779 // 12. Return ? CreateTemporalDuration(y, mo, w, d, h, m, s, ms, mis, ns, 4780 // NewTarget). 4781 return CreateTemporalDuration(isolate, target, new_target, y, mo, w, d, h, m, 4782 s, ms, mis, ns); 4783} 4784 4785// #sec-get-temporal.duration.prototype.sign 4786MaybeHandle<Smi> JSTemporalDuration::Sign(Isolate* isolate, 4787 Handle<JSTemporalDuration> duration) { 4788 // 1. Let duration be the this value. 4789 // 2. Perform ? RequireInternalSlot(duration, 4790 // [[InitializedTemporalDuration]]). 4791 // 3. Return ! DurationSign(duration.[[Years]], duration.[[Months]], 4792 // duration.[[Weeks]], duration.[[Days]], duration.[[Hours]], 4793 // duration.[[Minutes]], duration.[[Seconds]], duration.[[Milliseconds]], 4794 // duration.[[Microseconds]], duration.[[Nanoseconds]]). 4795 return Handle<Smi>( 4796 Smi::FromInt(DurationSign( 4797 isolate, 4798 {NumberToInt64(duration->years()), NumberToInt64(duration->months()), 4799 NumberToInt64(duration->weeks()), NumberToInt64(duration->days()), 4800 NumberToInt64(duration->hours()), NumberToInt64(duration->minutes()), 4801 NumberToInt64(duration->seconds()), 4802 NumberToInt64(duration->milliseconds()), 4803 NumberToInt64(duration->microseconds()), 4804 NumberToInt64(duration->nanoseconds())})), 4805 isolate); 4806} 4807 4808// #sec-get-temporal.duration.prototype.blank 4809MaybeHandle<Oddball> JSTemporalDuration::Blank( 4810 Isolate* isolate, Handle<JSTemporalDuration> duration) { 4811 // 1. Let duration be the this value. 4812 // 2. Perform ? RequireInternalSlot(duration, 4813 // [[InitializedTemporalDuration]]). 4814 // 3. Let sign be ! DurationSign(duration.[[Years]], duration.[[Months]], 4815 // duration.[[Weeks]], duration.[[Days]], duration.[[Hours]], 4816 // duration.[[Minutes]], duration.[[Seconds]], duration.[[Milliseconds]], 4817 // duration.[[Microseconds]], duration.[[Nanoseconds]]). 4818 // 4. If sign = 0, return true. 4819 // 5. Return false. 4820 int32_t sign = DurationSign( 4821 isolate, 4822 {NumberToInt64(duration->years()), NumberToInt64(duration->months()), 4823 NumberToInt64(duration->weeks()), NumberToInt64(duration->days()), 4824 NumberToInt64(duration->hours()), NumberToInt64(duration->minutes()), 4825 NumberToInt64(duration->seconds()), 4826 NumberToInt64(duration->milliseconds()), 4827 NumberToInt64(duration->microseconds()), 4828 NumberToInt64(duration->nanoseconds())}); 4829 return sign == 0 ? isolate->factory()->true_value() 4830 : isolate->factory()->false_value(); 4831} 4832 4833namespace { 4834// #sec-temporal-createnegatedtemporalduration 4835MaybeHandle<JSTemporalDuration> CreateNegatedTemporalDuration( 4836 Isolate* isolate, Handle<JSTemporalDuration> duration) { 4837 TEMPORAL_ENTER_FUNC(); 4838 // 1. Assert: Type(duration) is Object. 4839 // 2. Assert: duration has an [[InitializedTemporalDuration]] internal slot. 4840 // 3. Return ! CreateTemporalDuration(−duration.[[Years]], 4841 // −duration.[[Months]], −duration.[[Weeks]], −duration.[[Days]], 4842 // −duration.[[Hours]], −duration.[[Minutes]], −duration.[[Seconds]], 4843 // −duration.[[Milliseconds]], −duration.[[Microseconds]], 4844 // −duration.[[Nanoseconds]]). 4845 4846 return CreateTemporalDuration( 4847 isolate, -NumberToInt64(duration->years()), 4848 -NumberToInt64(duration->months()), -NumberToInt64(duration->weeks()), 4849 -NumberToInt64(duration->days()), -NumberToInt64(duration->hours()), 4850 -NumberToInt64(duration->minutes()), -NumberToInt64(duration->seconds()), 4851 -NumberToInt64(duration->milliseconds()), 4852 -NumberToInt64(duration->microseconds()), 4853 -NumberToInt64(duration->nanoseconds())); 4854} 4855 4856} // namespace 4857 4858// #sec-temporal.duration.prototype.negated 4859MaybeHandle<JSTemporalDuration> JSTemporalDuration::Negated( 4860 Isolate* isolate, Handle<JSTemporalDuration> duration) { 4861 // Let duration be the this value. 4862 // 2. Perform ? RequireInternalSlot(duration, 4863 // [[InitializedTemporalDuration]]). 4864 4865 // 3. Return ! CreateNegatedTemporalDuration(duration). 4866 return CreateNegatedTemporalDuration(isolate, duration); 4867} 4868 4869// #sec-temporal.duration.prototype.abs 4870MaybeHandle<JSTemporalDuration> JSTemporalDuration::Abs( 4871 Isolate* isolate, Handle<JSTemporalDuration> duration) { 4872 // 1. Let duration be the this value. 4873 // 2. Perform ? RequireInternalSlot(duration, 4874 // [[InitializedTemporalDuration]]). 4875 // 3. Return ? CreateTemporalDuration(abs(duration.[[Years]]), 4876 // abs(duration.[[Months]]), abs(duration.[[Weeks]]), abs(duration.[[Days]]), 4877 // abs(duration.[[Hours]]), abs(duration.[[Minutes]]), 4878 // abs(duration.[[Seconds]]), abs(duration.[[Milliseconds]]), 4879 // abs(duration.[[Microseconds]]), abs(duration.[[Nanoseconds]])). 4880 return CreateTemporalDuration( 4881 isolate, std::abs(NumberToInt64(duration->years())), 4882 std::abs(NumberToInt64(duration->months())), 4883 std::abs(NumberToInt64(duration->weeks())), 4884 std::abs(NumberToInt64(duration->days())), 4885 std::abs(NumberToInt64(duration->hours())), 4886 std::abs(NumberToInt64(duration->minutes())), 4887 std::abs(NumberToInt64(duration->seconds())), 4888 std::abs(NumberToInt64(duration->milliseconds())), 4889 std::abs(NumberToInt64(duration->microseconds())), 4890 std::abs(NumberToInt64(duration->nanoseconds()))); 4891} 4892 4893// #sec-temporal.calendar 4894MaybeHandle<JSTemporalCalendar> JSTemporalCalendar::Constructor( 4895 Isolate* isolate, Handle<JSFunction> target, Handle<HeapObject> new_target, 4896 Handle<Object> identifier_obj) { 4897 // 1. If NewTarget is undefined, then 4898 if (new_target->IsUndefined(isolate)) { 4899 // a. Throw a TypeError exception. 4900 THROW_NEW_ERROR(isolate, 4901 NewTypeError(MessageTemplate::kConstructorNotFunction, 4902 isolate->factory()->NewStringFromStaticChars( 4903 "Temporal.Calendar")), 4904 JSTemporalCalendar); 4905 } 4906 // 2. Set identifier to ? ToString(identifier). 4907 Handle<String> identifier; 4908 ASSIGN_RETURN_ON_EXCEPTION(isolate, identifier, 4909 Object::ToString(isolate, identifier_obj), 4910 JSTemporalCalendar); 4911 // 3. If ! IsBuiltinCalendar(id) is false, then 4912 if (!IsBuiltinCalendar(isolate, identifier)) { 4913 // a. Throw a RangeError exception. 4914 THROW_NEW_ERROR( 4915 isolate, NewRangeError(MessageTemplate::kInvalidCalendar, identifier), 4916 JSTemporalCalendar); 4917 } 4918 return CreateTemporalCalendar(isolate, target, new_target, identifier); 4919} 4920 4921namespace { 4922 4923// #sec-temporal-toisodayofyear 4924int32_t ToISODayOfYear(Isolate* isolate, int32_t year, int32_t month, 4925 int32_t day) { 4926 TEMPORAL_ENTER_FUNC(); 4927 4928 // 1. Assert: year is an integer. 4929 // 2. Assert: month is an integer. 4930 // 3. Assert: day is an integer. 4931 // 4. Let date be the date given by year, month, and day. 4932 // 5. Return date's ordinal date in the year according to ISO-8601. 4933 // Note: In ISO 8601, Jan: month=1, Dec: month=12, 4934 // In DateCache API, Jan: month=0, Dec: month=11 so we need to - 1 for month. 4935 return day + isolate->date_cache()->DaysFromYearMonth(year, month - 1) - 4936 isolate->date_cache()->DaysFromYearMonth(year, 0); 4937} 4938 4939bool IsPlainDatePlainDateTimeOrPlainYearMonth( 4940 Handle<Object> temporal_date_like) { 4941 return temporal_date_like->IsJSTemporalPlainDate() || 4942 temporal_date_like->IsJSTemporalPlainDateTime() || 4943 temporal_date_like->IsJSTemporalPlainYearMonth(); 4944} 4945 4946// #sec-temporal-toisodayofweek 4947int32_t ToISODayOfWeek(Isolate* isolate, int32_t year, int32_t month, 4948 int32_t day) { 4949 TEMPORAL_ENTER_FUNC(); 4950 4951 // 1. Assert: year is an integer. 4952 // 2. Assert: month is an integer. 4953 // 3. Assert: day is an integer. 4954 // 4. Let date be the date given by year, month, and day. 4955 // 5. Return date's day of the week according to ISO-8601. 4956 // Note: In ISO 8601, Jan: month=1, Dec: month=12. 4957 // In DateCache API, Jan: month=0, Dec: month=11 so we need to - 1 for month. 4958 // Weekday() expect "the number of days since the epoch" as input and the 4959 // value of day is 1-based so we need to minus 1 to calculate "the number of 4960 // days" because the number of days on the epoch (1970/1/1) should be 0, 4961 // not 1. 4962 int32_t weekday = isolate->date_cache()->Weekday( 4963 isolate->date_cache()->DaysFromYearMonth(year, month - 1) + day - 1); 4964 // Note: In ISO 8601, Sun: weekday=7 Mon: weekday=1 4965 // In DateCache API, Sun: weekday=0 Mon: weekday=1 4966 return weekday == 0 ? 7 : weekday; 4967} 4968 4969// #sec-temporal-regulateisodate 4970Maybe<bool> RegulateISODate(Isolate* isolate, ShowOverflow overflow, 4971 int32_t year, int32_t* month, int32_t* day) { 4972 TEMPORAL_ENTER_FUNC(); 4973 4974 // 1. Assert: year, month, and day are integers. 4975 // 2. Assert: overflow is either "constrain" or "reject". 4976 switch (overflow) { 4977 // 3. If overflow is "reject", then 4978 case ShowOverflow::kReject: 4979 // a. If ! IsValidISODate(year, month, day) is false, throw a RangeError 4980 // exception. 4981 if (!IsValidISODate(isolate, year, *month, *day)) { 4982 THROW_NEW_ERROR_RETURN_VALUE( 4983 isolate, NEW_TEMPORAL_INVALD_ARG_RANGE_ERROR(), Nothing<bool>()); 4984 } 4985 // b. Return the Record { [[Year]]: year, [[Month]]: month, [[Day]]: day 4986 // }. 4987 return Just(true); 4988 // 4. If overflow is "constrain", then 4989 case ShowOverflow::kConstrain: 4990 // a. Set month to ! ConstrainToRange(month, 1, 12). 4991 *month = std::max(std::min(*month, 12), 1); 4992 // b. Set day to ! ConstrainToRange(day, 1, ! ISODaysInMonth(year, 4993 // month)). 4994 *day = std::max(std::min(*day, ISODaysInMonth(isolate, year, *month)), 1); 4995 // c. Return the Record { [[Year]]: year, [[Month]]: month, [[Day]]: day 4996 // }. 4997 return Just(true); 4998 } 4999} 5000 5001// #sec-temporal-resolveisomonth 5002Maybe<int32_t> ResolveISOMonth(Isolate* isolate, Handle<JSReceiver> fields) { 5003 Factory* factory = isolate->factory(); 5004 // 1. Let month be ? Get(fields, "month"). 5005 Handle<Object> month_obj; 5006 ASSIGN_RETURN_ON_EXCEPTION_VALUE( 5007 isolate, month_obj, 5008 Object::GetPropertyOrElement(isolate, fields, factory->month_string()), 5009 Nothing<int32_t>()); 5010 // 2. Let monthCode be ? Get(fields, "monthCode"). 5011 Handle<Object> month_code_obj; 5012 ASSIGN_RETURN_ON_EXCEPTION_VALUE( 5013 isolate, month_code_obj, 5014 Object::GetPropertyOrElement(isolate, fields, 5015 factory->monthCode_string()), 5016 Nothing<int32_t>()); 5017 // 3. If monthCode is undefined, then 5018 if (month_code_obj->IsUndefined(isolate)) { 5019 // a. If month is undefined, throw a TypeError exception. 5020 if (month_obj->IsUndefined(isolate)) { 5021 THROW_NEW_ERROR_RETURN_VALUE( 5022 isolate, NEW_TEMPORAL_INVALD_ARG_TYPE_ERROR(), Nothing<int32_t>()); 5023 } 5024 // b. Return month. 5025 // Note: In Temporal spec, "month" in fields is always converted by 5026 // ToPositiveInteger inside PrepareTemporalFields before calling 5027 // ResolveISOMonth. Therefore the month_obj is always a positive integer. 5028 DCHECK(month_obj->IsSmi() || month_obj->IsHeapNumber()); 5029 return Just(FastD2I(month_obj->Number())); 5030 } 5031 // 4. Assert: Type(monthCode) is String. 5032 DCHECK(month_code_obj->IsString()); 5033 Handle<String> month_code; 5034 ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, month_code, 5035 Object::ToString(isolate, month_code_obj), 5036 Nothing<int32_t>()); 5037 // 5. Let monthLength be the length of monthCode. 5038 // 6. If monthLength is not 3, throw a RangeError exception. 5039 if (month_code->length() != 3) { 5040 THROW_NEW_ERROR_RETURN_VALUE( 5041 isolate, 5042 NewRangeError(MessageTemplate::kPropertyValueOutOfRange, 5043 factory->monthCode_string()), 5044 Nothing<int32_t>()); 5045 } 5046 // 7. Let numberPart be the substring of monthCode from 1. 5047 // 8. Set numberPart to ! ToIntegerOrInfinity(numberPart). 5048 // 9. If numberPart < 1 or numberPart > 12, throw a RangeError exception. 5049 uint16_t m0 = month_code->Get(0); 5050 uint16_t m1 = month_code->Get(1); 5051 uint16_t m2 = month_code->Get(2); 5052 if (!((m0 == 'M') && ((m1 == '0' && '1' <= m2 && m2 <= '9') || 5053 (m1 == '1' && '0' <= m2 && m2 <= '2')))) { 5054 THROW_NEW_ERROR_RETURN_VALUE( 5055 isolate, 5056 NewRangeError(MessageTemplate::kPropertyValueOutOfRange, 5057 factory->monthCode_string()), 5058 Nothing<int32_t>()); 5059 } 5060 int32_t number_part = 5061 10 * static_cast<int32_t>(m1 - '0') + static_cast<int32_t>(m2 - '0'); 5062 // 10. If month is not undefined, and month ≠ numberPart, then 5063 // 11. If ! SameValueNonNumeric(monthCode, ! BuildISOMonthCode(numberPart)) is 5064 // false, then a. Throw a RangeError exception. 5065 // Note: In Temporal spec, "month" in fields is always converted by 5066 // ToPositiveInteger inside PrepareTemporalFields before calling 5067 // ResolveISOMonth. Therefore the month_obj is always a positive integer. 5068 if (!month_obj->IsUndefined() && 5069 FastD2I(month_obj->Number()) != number_part) { 5070 // a. Throw a RangeError exception. 5071 THROW_NEW_ERROR_RETURN_VALUE( 5072 isolate, 5073 NewRangeError(MessageTemplate::kPropertyValueOutOfRange, 5074 factory->month_string()), 5075 Nothing<int32_t>()); 5076 } 5077 5078 // 12. Return numberPart. 5079 return Just(number_part); 5080} 5081 5082// #sec-temporal-isodatefromfields 5083Maybe<bool> ISODateFromFields(Isolate* isolate, Handle<JSReceiver> fields, 5084 Handle<JSReceiver> options, 5085 const char* method_name, int32_t* year, 5086 int32_t* month, int32_t* day) { 5087 Factory* factory = isolate->factory(); 5088 5089 // 1. Assert: Type(fields) is Object. 5090 // 2. Let overflow be ? ToTemporalOverflow(options). 5091 Maybe<ShowOverflow> maybe_overflow = 5092 ToTemporalOverflow(isolate, options, method_name); 5093 MAYBE_RETURN(maybe_overflow, Nothing<bool>()); 5094 // 3. Set fields to ? PrepareTemporalFields(fields, « "day", "month", 5095 // "monthCode", "year" », «»). 5096 Handle<FixedArray> field_names = factory->NewFixedArray(4); 5097 field_names->set(0, ReadOnlyRoots(isolate).day_string()); 5098 field_names->set(1, ReadOnlyRoots(isolate).month_string()); 5099 field_names->set(2, ReadOnlyRoots(isolate).monthCode_string()); 5100 field_names->set(3, ReadOnlyRoots(isolate).year_string()); 5101 ASSIGN_RETURN_ON_EXCEPTION_VALUE( 5102 isolate, fields, 5103 PrepareTemporalFields(isolate, fields, field_names, 5104 RequiredFields::kNone), 5105 Nothing<bool>()); 5106 5107 // 4. Let year be ? Get(fields, "year"). 5108 Handle<Object> year_obj; 5109 ASSIGN_RETURN_ON_EXCEPTION_VALUE( 5110 isolate, year_obj, 5111 Object::GetPropertyOrElement(isolate, fields, factory->year_string()), 5112 Nothing<bool>()); 5113 // 5. If year is undefined, throw a TypeError exception. 5114 if (year_obj->IsUndefined(isolate)) { 5115 THROW_NEW_ERROR_RETURN_VALUE(isolate, NEW_TEMPORAL_INVALD_ARG_TYPE_ERROR(), 5116 Nothing<bool>()); 5117 } 5118 // Note: "year" in fields is always converted by 5119 // ToIntegerThrowOnInfinity inside the PrepareTemporalFields above. 5120 // Therefore the year_obj is always an integer. 5121 DCHECK(year_obj->IsSmi() || year_obj->IsHeapNumber()); 5122 *year = FastD2I(year_obj->Number()); 5123 5124 // 6. Let month be ? ResolveISOMonth(fields). 5125 Maybe<int32_t> maybe_month = ResolveISOMonth(isolate, fields); 5126 MAYBE_RETURN(maybe_month, Nothing<bool>()); 5127 *month = maybe_month.FromJust(); 5128 5129 // 7. Let day be ? Get(fields, "day"). 5130 Handle<Object> day_obj; 5131 ASSIGN_RETURN_ON_EXCEPTION_VALUE( 5132 isolate, day_obj, 5133 Object::GetPropertyOrElement(isolate, fields, factory->day_string()), 5134 Nothing<bool>()); 5135 // 8. If day is undefined, throw a TypeError exception. 5136 if (day_obj->IsUndefined(isolate)) { 5137 THROW_NEW_ERROR_RETURN_VALUE(isolate, NEW_TEMPORAL_INVALD_ARG_TYPE_ERROR(), 5138 Nothing<bool>()); 5139 } 5140 // Note: "day" in fields is always converted by 5141 // ToIntegerThrowOnInfinity inside the PrepareTemporalFields above. 5142 // Therefore the day_obj is always an integer. 5143 DCHECK(day_obj->IsSmi() || day_obj->IsHeapNumber()); 5144 *day = FastD2I(day_obj->Number()); 5145 // 9. Return ? RegulateISODate(year, month, day, overflow). 5146 return RegulateISODate(isolate, maybe_overflow.FromJust(), *year, month, day); 5147} 5148 5149} // namespace 5150 5151// #sec-temporal.calendar.prototype.daysinyear 5152MaybeHandle<Smi> JSTemporalCalendar::DaysInYear( 5153 Isolate* isolate, Handle<JSTemporalCalendar> calendar, 5154 Handle<Object> temporal_date_like) { 5155 // 1. Let calendar be the this value. 5156 // 2. Perform ? RequireInternalSlot(calendar, 5157 // [[InitializedTemporalCalendar]]). 5158 // 3. Assert: calendar.[[Identifier]] is "iso8601". 5159 // 4. If Type(temporalDateLike) is not Object or temporalDateLike does not 5160 // have an [[InitializedTemporalDate]], [[InitializedTemporalDateTime]] or 5161 // [[InitializedTemporalYearMonth]] internal slot, then 5162 if (!IsPlainDatePlainDateTimeOrPlainYearMonth(temporal_date_like)) { 5163 // a. Set temporalDateLike to ? ToTemporalDate(temporalDateLike). 5164 ASSIGN_RETURN_ON_EXCEPTION( 5165 isolate, temporal_date_like, 5166 ToTemporalDate(isolate, temporal_date_like, 5167 isolate->factory()->NewJSObjectWithNullProto(), 5168 "Temporal.Calendar.prototype.daysInYear"), 5169 Smi); 5170 } 5171 5172 // a. Let daysInYear be ! ISODaysInYear(temporalDateLike.[[ISOYear]]). 5173 int32_t year; 5174 if (temporal_date_like->IsJSTemporalPlainDate()) { 5175 year = Handle<JSTemporalPlainDate>::cast(temporal_date_like)->iso_year(); 5176 } else if (temporal_date_like->IsJSTemporalPlainDateTime()) { 5177 year = 5178 Handle<JSTemporalPlainDateTime>::cast(temporal_date_like)->iso_year(); 5179 } else { 5180 DCHECK(temporal_date_like->IsJSTemporalPlainYearMonth()); 5181 year = 5182 Handle<JSTemporalPlainYearMonth>::cast(temporal_date_like)->iso_year(); 5183 } 5184 int32_t days_in_year = ISODaysInYear(isolate, year); 5185 // 6. Return (daysInYear). 5186 return handle(Smi::FromInt(days_in_year), isolate); 5187} 5188 5189// #sec-temporal.calendar.prototype.daysinmonth 5190MaybeHandle<Smi> JSTemporalCalendar::DaysInMonth( 5191 Isolate* isolate, Handle<JSTemporalCalendar> calendar, 5192 Handle<Object> temporal_date_like) { 5193 // 1 Let calendar be the this value. 5194 // 2. Perform ? RequireInternalSlot(calendar, 5195 // [[InitializedTemporalCalendar]]). 5196 // 3. Assert: calendar.[[Identifier]] is "iso8601". 5197 // 4. If Type(temporalDateLike) is not Object or temporalDateLike does not 5198 // have an [[InitializedTemporalDate]], [[InitializedTemporalDateTime]] or 5199 // [[InitializedTemporalYearMonth]] internal slot, then 5200 if (!IsPlainDatePlainDateTimeOrPlainYearMonth(temporal_date_like)) { 5201 // a. Set temporalDateLike to ? ToTemporalDate(temporalDateLike). 5202 ASSIGN_RETURN_ON_EXCEPTION( 5203 isolate, temporal_date_like, 5204 ToTemporalDate(isolate, temporal_date_like, 5205 isolate->factory()->NewJSObjectWithNullProto(), 5206 "Temporal.Calendar.prototype.daysInMonth"), 5207 Smi); 5208 } 5209 5210 // 5. Return (! ISODaysInMonth(temporalDateLike.[[ISOYear]], 5211 // temporalDateLike.[[ISOMonth]])). 5212 int32_t year; 5213 int32_t month; 5214 if (temporal_date_like->IsJSTemporalPlainDate()) { 5215 year = Handle<JSTemporalPlainDate>::cast(temporal_date_like)->iso_year(); 5216 month = Handle<JSTemporalPlainDate>::cast(temporal_date_like)->iso_month(); 5217 } else if (temporal_date_like->IsJSTemporalPlainDateTime()) { 5218 year = 5219 Handle<JSTemporalPlainDateTime>::cast(temporal_date_like)->iso_year(); 5220 month = 5221 Handle<JSTemporalPlainDateTime>::cast(temporal_date_like)->iso_month(); 5222 } else { 5223 DCHECK(temporal_date_like->IsJSTemporalPlainYearMonth()); 5224 year = 5225 Handle<JSTemporalPlainYearMonth>::cast(temporal_date_like)->iso_year(); 5226 month = 5227 Handle<JSTemporalPlainYearMonth>::cast(temporal_date_like)->iso_month(); 5228 } 5229 return handle(Smi::FromInt(ISODaysInMonth(isolate, year, month)), isolate); 5230} 5231 5232// #sec-temporal.calendar.prototype.year 5233MaybeHandle<Smi> JSTemporalCalendar::Year(Isolate* isolate, 5234 Handle<JSTemporalCalendar> calendar, 5235 Handle<Object> temporal_date_like) { 5236 // 1. Let calendar be the this value. 5237 // 2. Perform ? RequireInternalSlot(calendar, 5238 // [[InitializedTemporalCalendar]]). 5239 // 3. Assert: calendar.[[Identifier]] is "iso8601". 5240 // 4. If Type(temporalDateLike) is not Object or temporalDateLike does not 5241 // have an [[InitializedTemporalDate]], [[InitializedTemporalDateTime]], 5242 // or [[InitializedTemporalYearMonth]] 5243 // internal slot, then 5244 if (!IsPlainDatePlainDateTimeOrPlainYearMonth(temporal_date_like)) { 5245 // a. Set temporalDateLike to ? ToTemporalDate(temporalDateLike). 5246 ASSIGN_RETURN_ON_EXCEPTION( 5247 isolate, temporal_date_like, 5248 ToTemporalDate(isolate, temporal_date_like, 5249 isolate->factory()->NewJSObjectWithNullProto(), 5250 "Temporal.Calendar.prototype.year"), 5251 Smi); 5252 } 5253 5254 // a. Let year be ! ISOYear(temporalDateLike). 5255 int32_t year; 5256 if (temporal_date_like->IsJSTemporalPlainDate()) { 5257 year = Handle<JSTemporalPlainDate>::cast(temporal_date_like)->iso_year(); 5258 } else if (temporal_date_like->IsJSTemporalPlainDateTime()) { 5259 year = 5260 Handle<JSTemporalPlainDateTime>::cast(temporal_date_like)->iso_year(); 5261 } else { 5262 DCHECK(temporal_date_like->IsJSTemporalPlainYearMonth()); 5263 year = 5264 Handle<JSTemporalPlainYearMonth>::cast(temporal_date_like)->iso_year(); 5265 } 5266 5267 // 6. Return (year). 5268 return handle(Smi::FromInt(year), isolate); 5269} 5270 5271// #sec-temporal.calendar.prototype.dayofyear 5272MaybeHandle<Smi> JSTemporalCalendar::DayOfYear( 5273 Isolate* isolate, Handle<JSTemporalCalendar> calendar, 5274 Handle<Object> temporal_date_like) { 5275 // 1. Let calendar be the this value. 5276 // 2. Perform ? RequireInternalSlot(calendar, 5277 // [[InitializedTemporalCalendar]]). 5278 // 3. Assert: calendar.[[Identifier]] is "iso8601". 5279 // 4. Let temporalDate be ? ToTemporalDate(temporalDateLike). 5280 Handle<JSTemporalPlainDate> temporal_date; 5281 ASSIGN_RETURN_ON_EXCEPTION( 5282 isolate, temporal_date, 5283 ToTemporalDate(isolate, temporal_date_like, 5284 isolate->factory()->NewJSObjectWithNullProto(), 5285 "Temporal.Calendar.prototype.dayOfYear"), 5286 Smi); 5287 // a. Let value be ! ToISODayOfYear(temporalDate.[[ISOYear]], 5288 // temporalDate.[[ISOMonth]], temporalDate.[[ISODay]]). 5289 int32_t value = 5290 ToISODayOfYear(isolate, temporal_date->iso_year(), 5291 temporal_date->iso_month(), temporal_date->iso_day()); 5292 return handle(Smi::FromInt(value), isolate); 5293} 5294 5295// #sec-temporal.calendar.prototype.dayofweek 5296MaybeHandle<Smi> JSTemporalCalendar::DayOfWeek( 5297 Isolate* isolate, Handle<JSTemporalCalendar> calendar, 5298 Handle<Object> temporal_date_like) { 5299 // 1. Let calendar be the this value. 5300 // 2. Perform ? RequireInternalSlot(calendar, 5301 // [[InitializedTemporalCalendar]]). 5302 // 3. Assert: calendar.[[Identifier]] is "iso8601". 5303 // 4. Let temporalDate be ? ToTemporalDate(temporalDateLike). 5304 Handle<JSTemporalPlainDate> temporal_date; 5305 ASSIGN_RETURN_ON_EXCEPTION( 5306 isolate, temporal_date, 5307 ToTemporalDate(isolate, temporal_date_like, 5308 isolate->factory()->NewJSObjectWithNullProto(), 5309 "Temporal.Calendar.prototype.dayOfWeek"), 5310 Smi); 5311 // a. Let value be ! ToISODayOfWeek(temporalDate.[[ISOYear]], 5312 // temporalDate.[[ISOMonth]], temporalDate.[[ISODay]]). 5313 int32_t value = 5314 ToISODayOfWeek(isolate, temporal_date->iso_year(), 5315 temporal_date->iso_month(), temporal_date->iso_day()); 5316 return handle(Smi::FromInt(value), isolate); 5317} 5318 5319// #sec-temporal.calendar.prototype.monthsinyear 5320MaybeHandle<Smi> JSTemporalCalendar::MonthsInYear( 5321 Isolate* isolate, Handle<JSTemporalCalendar> calendar, 5322 Handle<Object> temporal_date_like) { 5323 // 1. Let calendar be the this value. 5324 // 2. Perform ? RequireInternalSlot(calendar, 5325 // [[InitializedTemporalCalendar]]). 5326 // 3. Assert: calendar.[[Identifier]] is "iso8601". 5327 // 4. If Type(temporalDateLike) is not Object or temporalDateLike does not 5328 // have an [[InitializedTemporalDate]], [[InitializedTemporalDateTime]], or 5329 // [[InitializedTemporalYearMonth]] internal slot, then 5330 if (!IsPlainDatePlainDateTimeOrPlainYearMonth(temporal_date_like)) { 5331 // a. Set temporalDateLike to ? ToTemporalDate(temporalDateLike). 5332 ASSIGN_RETURN_ON_EXCEPTION( 5333 isolate, temporal_date_like, 5334 ToTemporalDate(isolate, temporal_date_like, 5335 isolate->factory()->NewJSObjectWithNullProto(), 5336 "Temporal.Calendar.prototype.monthsInYear"), 5337 Smi); 5338 } 5339 5340 // a. a. Let monthsInYear be 12. 5341 int32_t months_in_year = 12; 5342 // 6. Return (monthsInYear). 5343 return handle(Smi::FromInt(months_in_year), isolate); 5344} 5345 5346// #sec-temporal.calendar.prototype.inleapyear 5347MaybeHandle<Oddball> JSTemporalCalendar::InLeapYear( 5348 Isolate* isolate, Handle<JSTemporalCalendar> calendar, 5349 Handle<Object> temporal_date_like) { 5350 // 1. Let calendar be the this value. 5351 // 2. Perform ? RequireInternalSlot(calendar, 5352 // [[InitializedTemporalCalendar]]). 5353 // 3. Assert: calendar.[[Identifier]] is "iso8601". 5354 // 4. If Type(temporalDateLike) is not Object or temporalDateLike does not 5355 // have an [[InitializedTemporalDate]], [[InitializedTemporalDateTime]], or 5356 // [[InitializedTemporalYearMonth]] internal slot, then 5357 if (!IsPlainDatePlainDateTimeOrPlainYearMonth(temporal_date_like)) { 5358 // a. Set temporalDateLike to ? ToTemporalDate(temporalDateLike). 5359 ASSIGN_RETURN_ON_EXCEPTION( 5360 isolate, temporal_date_like, 5361 ToTemporalDate(isolate, temporal_date_like, 5362 isolate->factory()->NewJSObjectWithNullProto(), 5363 "Temporal.Calendar.prototype.inLeapYear"), 5364 Oddball); 5365 } 5366 5367 // a. Let inLeapYear be ! IsISOLeapYear(temporalDateLike.[[ISOYear]]). 5368 int32_t year; 5369 if (temporal_date_like->IsJSTemporalPlainDate()) { 5370 year = Handle<JSTemporalPlainDate>::cast(temporal_date_like)->iso_year(); 5371 } else if (temporal_date_like->IsJSTemporalPlainDateTime()) { 5372 year = 5373 Handle<JSTemporalPlainDateTime>::cast(temporal_date_like)->iso_year(); 5374 } else { 5375 DCHECK(temporal_date_like->IsJSTemporalPlainYearMonth()); 5376 year = 5377 Handle<JSTemporalPlainYearMonth>::cast(temporal_date_like)->iso_year(); 5378 } 5379 return isolate->factory()->ToBoolean(IsISOLeapYear(isolate, year)); 5380} 5381 5382// #sec-temporal.calendar.prototype.daysinweek 5383MaybeHandle<Smi> JSTemporalCalendar::DaysInWeek( 5384 Isolate* isolate, Handle<JSTemporalCalendar> calendar, 5385 Handle<Object> temporal_date_like) { 5386 // 1. Let calendar be the this value. 5387 // 2. Perform ? RequireInternalSlot(calendar, 5388 // [[InitializedTemporalCalendar]]). 5389 // 3. Assert: calendar.[[Identifier]] is "iso8601". 5390 // 4. Perform ? ToTemporalDate(temporalDateLike). 5391 Handle<JSTemporalPlainDate> date; 5392 ASSIGN_RETURN_ON_EXCEPTION( 5393 isolate, date, 5394 ToTemporalDate(isolate, temporal_date_like, 5395 isolate->factory()->NewJSObjectWithNullProto(), 5396 "Temporal.Calendar.prototype.daysInWeek"), 5397 Smi); 5398 // 5. Return 7. 5399 return handle(Smi::FromInt(7), isolate); 5400} 5401 5402// #sec-temporal.calendar.prototype.datefromfields 5403MaybeHandle<JSTemporalPlainDate> JSTemporalCalendar::DateFromFields( 5404 Isolate* isolate, Handle<JSTemporalCalendar> calendar, 5405 Handle<Object> fields_obj, Handle<Object> options_obj) { 5406 // 1. Let calendar be the this value. 5407 // 2. Perform ? RequireInternalSlot(calendar, 5408 // [[InitializedTemporalCalendar]]). 5409 // 3. Assert: calendar.[[Identifier]] is "iso8601". 5410 // 4. If Type(fields) is not Object, throw a TypeError exception. 5411 const char* method_name = "Temporal.Calendar.prototype.dateFromFields"; 5412 if (!fields_obj->IsJSReceiver()) { 5413 THROW_NEW_ERROR(isolate, 5414 NewTypeError(MessageTemplate::kCalledOnNonObject, 5415 isolate->factory()->NewStringFromAsciiChecked( 5416 method_name)), 5417 JSTemporalPlainDate); 5418 } 5419 Handle<JSReceiver> fields = Handle<JSReceiver>::cast(fields_obj); 5420 5421 // 5. Set options to ? GetOptionsObject(options). 5422 Handle<JSReceiver> options; 5423 ASSIGN_RETURN_ON_EXCEPTION( 5424 isolate, options, GetOptionsObject(isolate, options_obj, method_name), 5425 JSTemporalPlainDate); 5426 if (calendar->calendar_index() == 0) { 5427 int32_t year; 5428 int32_t month; 5429 int32_t day; 5430 // 6. Let result be ? ISODateFromFields(fields, options). 5431 Maybe<bool> maybe_result = ISODateFromFields( 5432 isolate, fields, options, method_name, &year, &month, &day); 5433 MAYBE_RETURN(maybe_result, Handle<JSTemporalPlainDate>()); 5434 DCHECK(maybe_result.FromJust()); 5435 // 7. Return ? CreateTemporalDate(result.[[Year]], result.[[Month]], 5436 // result.[[Day]], calendar). 5437 return CreateTemporalDate(isolate, year, month, day, calendar); 5438 } 5439 // TODO(ftang) add intl implementation inside #ifdef V8_INTL_SUPPORT 5440 UNREACHABLE(); 5441} 5442 5443// #sec-temporal.calendar.prototype.mergefields 5444MaybeHandle<JSReceiver> JSTemporalCalendar::MergeFields( 5445 Isolate* isolate, Handle<JSTemporalCalendar> calendar, 5446 Handle<Object> fields_obj, Handle<Object> additional_fields_obj) { 5447 // 1. Let calendar be the this value. 5448 // 2. Perform ? RequireInternalSlot(calendar, 5449 // [[InitializedTemporalCalendar]]). 5450 // 3. Assert: calendar.[[Identifier]] is "iso8601". 5451 // 4. Set fields to ? ToObject(fields). 5452 Handle<JSReceiver> fields; 5453 ASSIGN_RETURN_ON_EXCEPTION(isolate, fields, 5454 Object::ToObject(isolate, fields_obj), JSReceiver); 5455 5456 // 5. Set additionalFields to ? ToObject(additionalFields). 5457 Handle<JSReceiver> additional_fields; 5458 ASSIGN_RETURN_ON_EXCEPTION(isolate, additional_fields, 5459 Object::ToObject(isolate, additional_fields_obj), 5460 JSReceiver); 5461 // 5. If calendar.[[Identifier]] is "iso8601", then 5462 if (calendar->calendar_index() == 0) { 5463 // a. Return ? DefaultMergeFields(fields, additionalFields). 5464 return DefaultMergeFields(isolate, fields, additional_fields); 5465 } 5466#ifdef V8_INTL_SUPPORT 5467 // TODO(ftang) add Intl code. 5468#endif // V8_INTL_SUPPORT 5469 UNREACHABLE(); 5470} 5471 5472// #sec-temporal.calendar.prototype.tostring 5473MaybeHandle<String> JSTemporalCalendar::ToString( 5474 Isolate* isolate, Handle<JSTemporalCalendar> calendar, 5475 const char* method_name) { 5476 return CalendarIdentifier(isolate, calendar->calendar_index()); 5477} 5478 5479// #sec-temporal.now.timezone 5480MaybeHandle<JSTemporalTimeZone> JSTemporalTimeZone::Now(Isolate* isolate) { 5481 return SystemTimeZone(isolate); 5482} 5483 5484// #sec-temporal.timezone 5485MaybeHandle<JSTemporalTimeZone> JSTemporalTimeZone::Constructor( 5486 Isolate* isolate, Handle<JSFunction> target, Handle<HeapObject> new_target, 5487 Handle<Object> identifier_obj) { 5488 // 1. If NewTarget is undefined, then 5489 if (new_target->IsUndefined(isolate)) { 5490 // a. Throw a TypeError exception. 5491 THROW_NEW_ERROR(isolate, 5492 NewTypeError(MessageTemplate::kConstructorNotFunction, 5493 isolate->factory()->NewStringFromAsciiChecked( 5494 "Temporal.TimeZone")), 5495 JSTemporalTimeZone); 5496 } 5497 // 2. Set identifier to ? ToString(identifier). 5498 Handle<String> identifier; 5499 ASSIGN_RETURN_ON_EXCEPTION(isolate, identifier, 5500 Object::ToString(isolate, identifier_obj), 5501 JSTemporalTimeZone); 5502 Handle<String> canonical; 5503 // 3. If identifier satisfies the syntax of a TimeZoneNumericUTCOffset 5504 // (see 13.33), then 5505 Maybe<bool> maybe_valid = 5506 IsValidTimeZoneNumericUTCOffsetString(isolate, identifier); 5507 MAYBE_RETURN(maybe_valid, Handle<JSTemporalTimeZone>()); 5508 5509 if (maybe_valid.FromJust()) { 5510 // a. Let offsetNanoseconds be ? ParseTimeZoneOffsetString(identifier). 5511 Maybe<int64_t> maybe_offset_nanoseconds = 5512 ParseTimeZoneOffsetString(isolate, identifier); 5513 MAYBE_RETURN(maybe_offset_nanoseconds, Handle<JSTemporalTimeZone>()); 5514 int64_t offset_nanoseconds = maybe_offset_nanoseconds.FromJust(); 5515 5516 // b. Let canonical be ! FormatTimeZoneOffsetString(offsetNanoseconds). 5517 ASSIGN_RETURN_ON_EXCEPTION( 5518 isolate, canonical, 5519 FormatTimeZoneOffsetString(isolate, offset_nanoseconds), 5520 JSTemporalTimeZone); 5521 } else { 5522 // 4. Else, 5523 // a. If ! IsValidTimeZoneName(identifier) is false, then 5524 if (!IsValidTimeZoneName(isolate, identifier)) { 5525 // i. Throw a RangeError exception. 5526 THROW_NEW_ERROR( 5527 isolate, NewRangeError(MessageTemplate::kInvalidTimeZone, identifier), 5528 JSTemporalTimeZone); 5529 } 5530 // b. Let canonical be ! CanonicalizeTimeZoneName(identifier). 5531 ASSIGN_RETURN_ON_EXCEPTION(isolate, canonical, 5532 CanonicalizeTimeZoneName(isolate, identifier), 5533 JSTemporalTimeZone); 5534 } 5535 // 5. Return ? CreateTemporalTimeZone(canonical, NewTarget). 5536 return CreateTemporalTimeZone(isolate, target, new_target, canonical); 5537} 5538 5539// #sec-temporal.timezone.prototype.tostring 5540MaybeHandle<Object> JSTemporalTimeZone::ToString( 5541 Isolate* isolate, Handle<JSTemporalTimeZone> time_zone, 5542 const char* method_name) { 5543 return time_zone->id(isolate); 5544} 5545 5546int32_t JSTemporalTimeZone::time_zone_index() const { 5547 DCHECK(is_offset() == false); 5548 return offset_milliseconds_or_time_zone_index(); 5549} 5550 5551int64_t JSTemporalTimeZone::offset_nanoseconds() const { 5552 TEMPORAL_ENTER_FUNC(); 5553 DCHECK(is_offset()); 5554 return 1000000L * offset_milliseconds() + offset_sub_milliseconds(); 5555} 5556 5557void JSTemporalTimeZone::set_offset_nanoseconds(int64_t ns) { 5558 this->set_offset_milliseconds(static_cast<int32_t>(ns / 1000000L)); 5559 this->set_offset_sub_milliseconds(static_cast<int32_t>(ns % 1000000L)); 5560} 5561 5562MaybeHandle<String> JSTemporalTimeZone::id(Isolate* isolate) const { 5563 if (is_offset()) { 5564 return FormatTimeZoneOffsetString(isolate, offset_nanoseconds()); 5565 } 5566#ifdef V8_INTL_SUPPORT 5567 std::string id = 5568 Intl::TimeZoneIdFromIndex(offset_milliseconds_or_time_zone_index()); 5569 return isolate->factory()->NewStringFromAsciiChecked(id.c_str()); 5570#else // V8_INTL_SUPPORT 5571 DCHECK_EQ(0, offset_milliseconds_or_time_zone_index()); 5572 return isolate->factory()->UTC_string(); 5573#endif // V8_INTL_SUPPORT 5574} 5575 5576MaybeHandle<JSTemporalPlainDate> JSTemporalPlainDate::Constructor( 5577 Isolate* isolate, Handle<JSFunction> target, Handle<HeapObject> new_target, 5578 Handle<Object> iso_year_obj, Handle<Object> iso_month_obj, 5579 Handle<Object> iso_day_obj, Handle<Object> calendar_like) { 5580 const char* method_name = "Temporal.PlainDate"; 5581 // 1. If NewTarget is undefined, throw a TypeError exception. 5582 if (new_target->IsUndefined()) { 5583 THROW_NEW_ERROR(isolate, 5584 NewTypeError(MessageTemplate::kMethodInvokedOnWrongType, 5585 isolate->factory()->NewStringFromAsciiChecked( 5586 method_name)), 5587 JSTemporalPlainDate); 5588 } 5589#define TO_INT_THROW_ON_INFTY(name, T) \ 5590 int32_t name; \ 5591 { \ 5592 Handle<Object> number_##name; \ 5593 /* x. Let name be ? ToIntegerThrowOnInfinity(name). */ \ 5594 ASSIGN_RETURN_ON_EXCEPTION(isolate, number_##name, \ 5595 ToIntegerThrowOnInfinity(isolate, name##_obj), \ 5596 T); \ 5597 name = NumberToInt32(*number_##name); \ 5598 } 5599 5600 TO_INT_THROW_ON_INFTY(iso_year, JSTemporalPlainDate); 5601 TO_INT_THROW_ON_INFTY(iso_month, JSTemporalPlainDate); 5602 TO_INT_THROW_ON_INFTY(iso_day, JSTemporalPlainDate); 5603 5604 // 8. Let calendar be ? ToTemporalCalendarWithISODefault(calendarLike). 5605 Handle<JSReceiver> calendar; 5606 ASSIGN_RETURN_ON_EXCEPTION( 5607 isolate, calendar, 5608 ToTemporalCalendarWithISODefault(isolate, calendar_like, method_name), 5609 JSTemporalPlainDate); 5610 5611 // 9. Return ? CreateTemporalDate(y, m, d, calendar, NewTarget). 5612 return CreateTemporalDate(isolate, target, new_target, iso_year, iso_month, 5613 iso_day, calendar); 5614} 5615 5616// #sec-temporal.plaindate.prototype.withcalendar 5617MaybeHandle<JSTemporalPlainDate> JSTemporalPlainDate::WithCalendar( 5618 Isolate* isolate, Handle<JSTemporalPlainDate> temporal_date, 5619 Handle<Object> calendar_like) { 5620 const char* method_name = "Temporal.PlainDate.prototype.withCalendar"; 5621 // 1. Let temporalDate be the this value. 5622 // 2. Perform ? RequireInternalSlot(temporalDate, 5623 // [[InitializedTemporalDate]]). 5624 // 3. Let calendar be ? ToTemporalCalendar(calendar). 5625 Handle<JSReceiver> calendar; 5626 ASSIGN_RETURN_ON_EXCEPTION( 5627 isolate, calendar, 5628 temporal::ToTemporalCalendar(isolate, calendar_like, method_name), 5629 JSTemporalPlainDate); 5630 // 4. Return ? CreateTemporalDate(temporalDate.[[ISOYear]], 5631 // temporalDate.[[ISOMonth]], temporalDate.[[ISODay]], calendar). 5632 return CreateTemporalDate(isolate, temporal_date->iso_year(), 5633 temporal_date->iso_month(), 5634 temporal_date->iso_day(), calendar); 5635} 5636 5637// #sec-temporal.now.plaindate 5638MaybeHandle<JSTemporalPlainDate> JSTemporalPlainDate::Now( 5639 Isolate* isolate, Handle<Object> calendar_like, 5640 Handle<Object> temporal_time_zone_like) { 5641 const char* method_name = "Temporal.Now.plainDate"; 5642 // 1. Let dateTime be ? SystemDateTime(temporalTimeZoneLike, calendarLike). 5643 Handle<JSTemporalPlainDateTime> date_time; 5644 ASSIGN_RETURN_ON_EXCEPTION(isolate, date_time, 5645 SystemDateTime(isolate, temporal_time_zone_like, 5646 calendar_like, method_name), 5647 JSTemporalPlainDate); 5648 // 2. Return ! CreateTemporalDate(dateTime.[[ISOYear]], dateTime.[[ISOMonth]], 5649 // dateTime.[[ISODay]], dateTime.[[Calendar]]). 5650 return CreateTemporalDate(isolate, date_time->iso_year(), 5651 date_time->iso_month(), date_time->iso_day(), 5652 Handle<JSReceiver>(date_time->calendar(), isolate)); 5653} 5654 5655// #sec-temporal.now.plaindateiso 5656MaybeHandle<JSTemporalPlainDate> JSTemporalPlainDate::NowISO( 5657 Isolate* isolate, Handle<Object> temporal_time_zone_like) { 5658 const char* method_name = "Temporal.Now.plainDateISO"; 5659 // 1. Let calendar be ! GetISO8601Calendar(). 5660 Handle<JSReceiver> calendar; 5661 ASSIGN_RETURN_ON_EXCEPTION(isolate, calendar, 5662 temporal::GetISO8601Calendar(isolate), 5663 JSTemporalPlainDate); 5664 // 2. Let dateTime be ? SystemDateTime(temporalTimeZoneLike, calendar). 5665 Handle<JSTemporalPlainDateTime> date_time; 5666 ASSIGN_RETURN_ON_EXCEPTION( 5667 isolate, date_time, 5668 SystemDateTime(isolate, temporal_time_zone_like, calendar, method_name), 5669 JSTemporalPlainDate); 5670 // 3. Return ! CreateTemporalDate(dateTime.[[ISOYear]], dateTime.[[ISOMonth]], 5671 // dateTime.[[ISODay]], dateTime.[[Calendar]]). 5672 return CreateTemporalDate(isolate, date_time->iso_year(), 5673 date_time->iso_month(), date_time->iso_day(), 5674 Handle<JSReceiver>(date_time->calendar(), isolate)); 5675} 5676 5677// #sec-temporal.plaindate.from 5678MaybeHandle<JSTemporalPlainDate> JSTemporalPlainDate::From( 5679 Isolate* isolate, Handle<Object> item, Handle<Object> options_obj) { 5680 const char* method_name = "Temporal.PlainDate.from"; 5681 // 1. Set options to ? GetOptionsObject(options). 5682 Handle<JSReceiver> options; 5683 ASSIGN_RETURN_ON_EXCEPTION( 5684 isolate, options, GetOptionsObject(isolate, options_obj, method_name), 5685 JSTemporalPlainDate); 5686 // 2. If Type(item) is Object and item has an [[InitializedTemporalDate]] 5687 // internal slot, then 5688 if (item->IsJSTemporalPlainDate()) { 5689 // a. Perform ? ToTemporalOverflow(options). 5690 Maybe<ShowOverflow> maybe_overflow = 5691 ToTemporalOverflow(isolate, options, method_name); 5692 MAYBE_RETURN(maybe_overflow, Handle<JSTemporalPlainDate>()); 5693 // b. Return ? CreateTemporalDate(item.[[ISOYear]], item.[[ISOMonth]], 5694 // item.[[ISODay]], item.[[Calendar]]). 5695 Handle<JSTemporalPlainDate> date = Handle<JSTemporalPlainDate>::cast(item); 5696 return CreateTemporalDate(isolate, date->iso_year(), date->iso_month(), 5697 date->iso_day(), 5698 Handle<JSReceiver>(date->calendar(), isolate)); 5699 } 5700 // 3. Return ? ToTemporalDate(item, options). 5701 return ToTemporalDate(isolate, item, options, method_name); 5702} 5703 5704#define DEFINE_INT_FIELD(obj, str, field, item) \ 5705 CHECK(JSReceiver::CreateDataProperty( \ 5706 isolate, obj, factory->str##_string(), \ 5707 Handle<Smi>(Smi::FromInt(item->field()), isolate), \ 5708 Just(kThrowOnError)) \ 5709 .FromJust()); 5710 5711// #sec-temporal.plaindate.prototype.getisofields 5712MaybeHandle<JSReceiver> JSTemporalPlainDate::GetISOFields( 5713 Isolate* isolate, Handle<JSTemporalPlainDate> temporal_date) { 5714 Factory* factory = isolate->factory(); 5715 // 1. Let temporalDate be the this value. 5716 // 2. Perform ? RequireInternalSlot(temporalDate, 5717 // [[InitializedTemporalDate]]). 5718 // 3. Let fields be ! OrdinaryObjectCreate(%Object.prototype%). 5719 Handle<JSObject> fields = 5720 isolate->factory()->NewJSObject(isolate->object_function()); 5721 // 4. Perform ! CreateDataPropertyOrThrow(fields, "calendar", 5722 // temporalDate.[[Calendar]]). 5723 CHECK(JSReceiver::CreateDataProperty( 5724 isolate, fields, factory->calendar_string(), 5725 Handle<JSReceiver>(temporal_date->calendar(), isolate), 5726 Just(kThrowOnError)) 5727 .FromJust()); 5728 // 5. Perform ! CreateDataPropertyOrThrow(fields, "isoDay", 5729 // (temporalDate.[[ISODay]])). 5730 // 6. Perform ! CreateDataPropertyOrThrow(fields, "isoMonth", 5731 // (temporalDate.[[ISOMonth]])). 5732 // 7. Perform ! CreateDataPropertyOrThrow(fields, "isoYear", 5733 // (temporalDate.[[ISOYear]])). 5734 DEFINE_INT_FIELD(fields, isoDay, iso_day, temporal_date) 5735 DEFINE_INT_FIELD(fields, isoMonth, iso_month, temporal_date) 5736 DEFINE_INT_FIELD(fields, isoYear, iso_year, temporal_date) 5737 // 8. Return fields. 5738 return fields; 5739} 5740 5741// #sec-temporal-createtemporaldatetime 5742MaybeHandle<JSTemporalPlainDateTime> JSTemporalPlainDateTime::Constructor( 5743 Isolate* isolate, Handle<JSFunction> target, Handle<HeapObject> new_target, 5744 Handle<Object> iso_year_obj, Handle<Object> iso_month_obj, 5745 Handle<Object> iso_day_obj, Handle<Object> hour_obj, 5746 Handle<Object> minute_obj, Handle<Object> second_obj, 5747 Handle<Object> millisecond_obj, Handle<Object> microsecond_obj, 5748 Handle<Object> nanosecond_obj, Handle<Object> calendar_like) { 5749 const char* method_name = "Temporal.PlainDateTime"; 5750 // 1. If NewTarget is undefined, throw a TypeError exception. 5751 if (new_target->IsUndefined()) { 5752 THROW_NEW_ERROR(isolate, 5753 NewTypeError(MessageTemplate::kMethodInvokedOnWrongType, 5754 isolate->factory()->NewStringFromAsciiChecked( 5755 method_name)), 5756 JSTemporalPlainDateTime); 5757 } 5758 5759 TO_INT_THROW_ON_INFTY(iso_year, JSTemporalPlainDateTime); 5760 TO_INT_THROW_ON_INFTY(iso_month, JSTemporalPlainDateTime); 5761 TO_INT_THROW_ON_INFTY(iso_day, JSTemporalPlainDateTime); 5762 TO_INT_THROW_ON_INFTY(hour, JSTemporalPlainDateTime); 5763 TO_INT_THROW_ON_INFTY(minute, JSTemporalPlainDateTime); 5764 TO_INT_THROW_ON_INFTY(second, JSTemporalPlainDateTime); 5765 TO_INT_THROW_ON_INFTY(millisecond, JSTemporalPlainDateTime); 5766 TO_INT_THROW_ON_INFTY(microsecond, JSTemporalPlainDateTime); 5767 TO_INT_THROW_ON_INFTY(nanosecond, JSTemporalPlainDateTime); 5768 5769 // 20. Let calendar be ? ToTemporalCalendarWithISODefault(calendarLike). 5770 Handle<JSReceiver> calendar; 5771 ASSIGN_RETURN_ON_EXCEPTION( 5772 isolate, calendar, 5773 ToTemporalCalendarWithISODefault(isolate, calendar_like, method_name), 5774 JSTemporalPlainDateTime); 5775 5776 // 21. Return ? CreateTemporalDateTime(isoYear, isoMonth, isoDay, hour, 5777 // minute, second, millisecond, microsecond, nanosecond, calendar, NewTarget). 5778 return CreateTemporalDateTime(isolate, target, new_target, iso_year, 5779 iso_month, iso_day, hour, minute, second, 5780 millisecond, microsecond, nanosecond, calendar); 5781} 5782 5783// #sec-temporal.plaindatetime.prototype.withcalendar 5784MaybeHandle<JSTemporalPlainDateTime> JSTemporalPlainDateTime::WithCalendar( 5785 Isolate* isolate, Handle<JSTemporalPlainDateTime> date_time, 5786 Handle<Object> calendar_like) { 5787 const char* method_name = "Temporal.PlainDateTime.prototype.withCalendar"; 5788 // 1. Let temporalDateTime be the this value. 5789 // 2. Perform ? RequireInternalSlot(temporalDateTime, 5790 // [[InitializedTemporalDateTime]]). 5791 // 3. Let calendar be ? ToTemporalCalendar(calendar). 5792 Handle<JSReceiver> calendar; 5793 ASSIGN_RETURN_ON_EXCEPTION( 5794 isolate, calendar, 5795 temporal::ToTemporalCalendar(isolate, calendar_like, method_name), 5796 JSTemporalPlainDateTime); 5797 // 4. Return ? CreateTemporalDateTime(temporalDateTime.[[ISOYear]], 5798 // temporalDateTime.[[ISOMonth]], temporalDateTime.[[ISODay]], 5799 // temporalDateTime.[[ISOHour]], temporalDateTime.[[ISOMinute]], 5800 // temporalDateTime.[[ISOSecond]], temporalDateTime.[[ISOMillisecond]], 5801 // temporalDateTime.[[ISOMicrosecond]], temporalDateTime.[[ISONanosecond]], 5802 // calendar). 5803 return temporal::CreateTemporalDateTime( 5804 isolate, date_time->iso_year(), date_time->iso_month(), 5805 date_time->iso_day(), date_time->iso_hour(), date_time->iso_minute(), 5806 date_time->iso_second(), date_time->iso_millisecond(), 5807 date_time->iso_microsecond(), date_time->iso_nanosecond(), calendar); 5808} 5809 5810// #sec-temporal.now.plaindatetime 5811MaybeHandle<JSTemporalPlainDateTime> JSTemporalPlainDateTime::Now( 5812 Isolate* isolate, Handle<Object> calendar_like, 5813 Handle<Object> temporal_time_zone_like) { 5814 const char* method_name = "Temporal.Now.plainDateTime"; 5815 // 1. Return ? SystemDateTime(temporalTimeZoneLike, calendarLike). 5816 return SystemDateTime(isolate, temporal_time_zone_like, calendar_like, 5817 method_name); 5818} 5819 5820// #sec-temporal.now.plaindatetimeiso 5821MaybeHandle<JSTemporalPlainDateTime> JSTemporalPlainDateTime::NowISO( 5822 Isolate* isolate, Handle<Object> temporal_time_zone_like) { 5823 const char* method_name = "Temporal.Now.plainDateTimeISO"; 5824 // 1. Let calendar be ! GetISO8601Calendar(). 5825 Handle<JSReceiver> calendar; 5826 ASSIGN_RETURN_ON_EXCEPTION(isolate, calendar, 5827 temporal::GetISO8601Calendar(isolate), 5828 JSTemporalPlainDateTime); 5829 // 2. Return ? SystemDateTime(temporalTimeZoneLike, calendar). 5830 return SystemDateTime(isolate, temporal_time_zone_like, calendar, 5831 method_name); 5832} 5833 5834// #sec-temporal.plaindatetime.prototype.getisofields 5835MaybeHandle<JSReceiver> JSTemporalPlainDateTime::GetISOFields( 5836 Isolate* isolate, Handle<JSTemporalPlainDateTime> date_time) { 5837 Factory* factory = isolate->factory(); 5838 // 1. Let dateTime be the this value. 5839 // 2. Perform ? RequireInternalSlot(temporalDateTime, 5840 // [[InitializedTemporalDateTime]]). 5841 // 3. Let fields be ! OrdinaryObjectCreate(%Object.prototype%). 5842 Handle<JSObject> fields = 5843 isolate->factory()->NewJSObject(isolate->object_function()); 5844 // 4. Perform ! CreateDataPropertyOrThrow(fields, "calendar", 5845 // temporalTime.[[Calendar]]). 5846 CHECK(JSReceiver::CreateDataProperty( 5847 isolate, fields, factory->calendar_string(), 5848 Handle<JSReceiver>(date_time->calendar(), isolate), 5849 Just(kThrowOnError)) 5850 .FromJust()); 5851 // 5. Perform ! CreateDataPropertyOrThrow(fields, "isoDay", 5852 // (dateTime.[[ISODay]])). 5853 // 6. Perform ! CreateDataPropertyOrThrow(fields, "isoHour", 5854 // (temporalTime.[[ISOHour]])). 5855 // 7. Perform ! CreateDataPropertyOrThrow(fields, "isoMicrosecond", 5856 // (temporalTime.[[ISOMicrosecond]])). 5857 // 8. Perform ! CreateDataPropertyOrThrow(fields, "isoMillisecond", 5858 // (temporalTime.[[ISOMillisecond]])). 5859 // 9. Perform ! CreateDataPropertyOrThrow(fields, "isoMinute", 5860 // (temporalTime.[[ISOMinute]])). 5861 // 10. Perform ! CreateDataPropertyOrThrow(fields, "isoMonth", 5862 // (temporalTime.[[ISOMonth]])). 5863 // 11. Perform ! CreateDataPropertyOrThrow(fields, "isoNanosecond", 5864 // (temporalTime.[[ISONanosecond]])). 5865 // 12. Perform ! CreateDataPropertyOrThrow(fields, "isoSecond", 5866 // (temporalTime.[[ISOSecond]])). 5867 // 13. Perform ! CreateDataPropertyOrThrow(fields, "isoYear", 5868 // (temporalTime.[[ISOYear]])). 5869 DEFINE_INT_FIELD(fields, isoDay, iso_day, date_time) 5870 DEFINE_INT_FIELD(fields, isoHour, iso_hour, date_time) 5871 DEFINE_INT_FIELD(fields, isoMicrosecond, iso_microsecond, date_time) 5872 DEFINE_INT_FIELD(fields, isoMillisecond, iso_millisecond, date_time) 5873 DEFINE_INT_FIELD(fields, isoMinute, iso_minute, date_time) 5874 DEFINE_INT_FIELD(fields, isoMonth, iso_month, date_time) 5875 DEFINE_INT_FIELD(fields, isoNanosecond, iso_nanosecond, date_time) 5876 DEFINE_INT_FIELD(fields, isoSecond, iso_second, date_time) 5877 DEFINE_INT_FIELD(fields, isoYear, iso_year, date_time) 5878 // 14. Return fields. 5879 return fields; 5880} 5881 5882// #sec-temporal.plainmonthday 5883MaybeHandle<JSTemporalPlainMonthDay> JSTemporalPlainMonthDay::Constructor( 5884 Isolate* isolate, Handle<JSFunction> target, Handle<HeapObject> new_target, 5885 Handle<Object> iso_month_obj, Handle<Object> iso_day_obj, 5886 Handle<Object> calendar_like, Handle<Object> reference_iso_year_obj) { 5887 const char* method_name = "Temporal.PlainMonthDay"; 5888 // 1. If NewTarget is undefined, throw a TypeError exception. 5889 if (new_target->IsUndefined()) { 5890 THROW_NEW_ERROR(isolate, 5891 NewTypeError(MessageTemplate::kMethodInvokedOnWrongType, 5892 isolate->factory()->NewStringFromAsciiChecked( 5893 method_name)), 5894 JSTemporalPlainMonthDay); 5895 } 5896 5897 // 3. Let m be ? ToIntegerThrowOnInfinity(isoMonth). 5898 TO_INT_THROW_ON_INFTY(iso_month, JSTemporalPlainMonthDay); 5899 // 5. Let d be ? ToIntegerThrowOnInfinity(isoDay). 5900 TO_INT_THROW_ON_INFTY(iso_day, JSTemporalPlainMonthDay); 5901 // 7. Let calendar be ? ToTemporalCalendarWithISODefault(calendarLike). 5902 Handle<JSReceiver> calendar; 5903 ASSIGN_RETURN_ON_EXCEPTION( 5904 isolate, calendar, 5905 ToTemporalCalendarWithISODefault(isolate, calendar_like, method_name), 5906 JSTemporalPlainMonthDay); 5907 5908 // 2. If referenceISOYear is undefined, then 5909 // a. Set referenceISOYear to 1972. 5910 // ... 5911 // 8. Let ref be ? ToIntegerThrowOnInfinity(referenceISOYear). 5912 int32_t ref = 1972; 5913 if (!reference_iso_year_obj->IsUndefined()) { 5914 TO_INT_THROW_ON_INFTY(reference_iso_year, JSTemporalPlainMonthDay); 5915 ref = reference_iso_year; 5916 } 5917 5918 // 10. Return ? CreateTemporalMonthDay(y, m, calendar, ref, NewTarget). 5919 return CreateTemporalMonthDay(isolate, target, new_target, iso_month, iso_day, 5920 calendar, ref); 5921} 5922 5923// #sec-temporal.plainmonthday.prototype.getisofields 5924MaybeHandle<JSReceiver> JSTemporalPlainMonthDay::GetISOFields( 5925 Isolate* isolate, Handle<JSTemporalPlainMonthDay> month_day) { 5926 Factory* factory = isolate->factory(); 5927 // 1. Let monthDay be the this value. 5928 // 2. Perform ? RequireInternalSlot(monthDay, 5929 // [[InitializedTemporalMonthDay]]). 5930 // 3. Let fields be ! OrdinaryObjectCreate(%Object.prototype%). 5931 Handle<JSObject> fields = factory->NewJSObject(isolate->object_function()); 5932 // 4. Perform ! CreateDataPropertyOrThrow(fields, "calendar", 5933 // montyDay.[[Calendar]]). 5934 CHECK(JSReceiver::CreateDataProperty( 5935 isolate, fields, factory->calendar_string(), 5936 Handle<JSReceiver>(month_day->calendar(), isolate), 5937 Just(kThrowOnError)) 5938 .FromJust()); 5939 5940 // 5. Perform ! CreateDataPropertyOrThrow(fields, "isoDay", 5941 // (montyDay.[[ISODay]])). 5942 // 6. Perform ! CreateDataPropertyOrThrow(fields, "isoMonth", 5943 // (montyDay.[[ISOMonth]])). 5944 // 7. Perform ! CreateDataPropertyOrThrow(fields, "isoYear", 5945 // (montyDay.[[ISOYear]])). 5946 DEFINE_INT_FIELD(fields, isoDay, iso_day, month_day) 5947 DEFINE_INT_FIELD(fields, isoMonth, iso_month, month_day) 5948 DEFINE_INT_FIELD(fields, isoYear, iso_year, month_day) 5949 // 8. Return fields. 5950 return fields; 5951} 5952 5953MaybeHandle<JSTemporalPlainYearMonth> JSTemporalPlainYearMonth::Constructor( 5954 Isolate* isolate, Handle<JSFunction> target, Handle<HeapObject> new_target, 5955 Handle<Object> iso_year_obj, Handle<Object> iso_month_obj, 5956 Handle<Object> calendar_like, Handle<Object> reference_iso_day_obj) { 5957 const char* method_name = "Temporal.PlainYearMonth"; 5958 // 1. If NewTarget is undefined, throw a TypeError exception. 5959 if (new_target->IsUndefined()) { 5960 THROW_NEW_ERROR(isolate, 5961 NewTypeError(MessageTemplate::kMethodInvokedOnWrongType, 5962 isolate->factory()->NewStringFromAsciiChecked( 5963 method_name)), 5964 JSTemporalPlainYearMonth); 5965 } 5966 // 7. Let calendar be ? ToTemporalCalendarWithISODefault(calendarLike). 5967 // 10. Return ? CreateTemporalYearMonth(y, m, calendar, ref, NewTarget). 5968 5969 // 3. Let y be ? ToIntegerThrowOnInfinity(isoYear). 5970 TO_INT_THROW_ON_INFTY(iso_year, JSTemporalPlainYearMonth); 5971 // 5. Let m be ? ToIntegerThrowOnInfinity(isoMonth). 5972 TO_INT_THROW_ON_INFTY(iso_month, JSTemporalPlainYearMonth); 5973 // 7. Let calendar be ? ToTemporalCalendarWithISODefault(calendarLike). 5974 Handle<JSReceiver> calendar; 5975 ASSIGN_RETURN_ON_EXCEPTION( 5976 isolate, calendar, 5977 ToTemporalCalendarWithISODefault(isolate, calendar_like, method_name), 5978 JSTemporalPlainYearMonth); 5979 5980 // 2. If referenceISODay is undefined, then 5981 // a. Set referenceISODay to 1. 5982 // ... 5983 // 8. Let ref be ? ToIntegerThrowOnInfinity(referenceISODay). 5984 int32_t ref = 1; 5985 if (!reference_iso_day_obj->IsUndefined()) { 5986 TO_INT_THROW_ON_INFTY(reference_iso_day, JSTemporalPlainYearMonth); 5987 ref = reference_iso_day; 5988 } 5989 5990 // 10. Return ? CreateTemporalYearMonth(y, m, calendar, ref, NewTarget). 5991 return CreateTemporalYearMonth(isolate, target, new_target, iso_year, 5992 iso_month, calendar, ref); 5993} 5994 5995// #sec-temporal.plainyearmonth.prototype.getisofields 5996MaybeHandle<JSReceiver> JSTemporalPlainYearMonth::GetISOFields( 5997 Isolate* isolate, Handle<JSTemporalPlainYearMonth> year_month) { 5998 Factory* factory = isolate->factory(); 5999 // 1. Let yearMonth be the this value. 6000 // 2. Perform ? RequireInternalSlot(yearMonth, 6001 // [[InitializedTemporalYearMonth]]). 6002 // 3. Let fields be ! OrdinaryObjectCreate(%Object.prototype%). 6003 Handle<JSObject> fields = 6004 isolate->factory()->NewJSObject(isolate->object_function()); 6005 // 4. Perform ! CreateDataPropertyOrThrow(fields, "calendar", 6006 // yearMonth.[[Calendar]]). 6007 CHECK(JSReceiver::CreateDataProperty( 6008 isolate, fields, factory->calendar_string(), 6009 Handle<JSReceiver>(year_month->calendar(), isolate), 6010 Just(kThrowOnError)) 6011 .FromJust()); 6012 // 5. Perform ! CreateDataPropertyOrThrow(fields, "isoDay", 6013 // (yearMonth.[[ISODay]])). 6014 // 6. Perform ! CreateDataPropertyOrThrow(fields, "isoMonth", 6015 // (yearMonth.[[ISOMonth]])). 6016 // 7. Perform ! CreateDataPropertyOrThrow(fields, "isoYear", 6017 // (yearMonth.[[ISOYear]])). 6018 DEFINE_INT_FIELD(fields, isoDay, iso_day, year_month) 6019 DEFINE_INT_FIELD(fields, isoMonth, iso_month, year_month) 6020 DEFINE_INT_FIELD(fields, isoYear, iso_year, year_month) 6021 // 8. Return fields. 6022 return fields; 6023} 6024 6025// #sec-temporal-plaintime-constructor 6026MaybeHandle<JSTemporalPlainTime> JSTemporalPlainTime::Constructor( 6027 Isolate* isolate, Handle<JSFunction> target, Handle<HeapObject> new_target, 6028 Handle<Object> hour_obj, Handle<Object> minute_obj, 6029 Handle<Object> second_obj, Handle<Object> millisecond_obj, 6030 Handle<Object> microsecond_obj, Handle<Object> nanosecond_obj) { 6031 const char* method_name = "Temporal.PlainTime"; 6032 // 1. If NewTarget is undefined, then 6033 // a. Throw a TypeError exception. 6034 if (new_target->IsUndefined()) { 6035 // a. Throw a TypeError exception. 6036 THROW_NEW_ERROR(isolate, 6037 NewTypeError(MessageTemplate::kMethodInvokedOnWrongType, 6038 isolate->factory()->NewStringFromAsciiChecked( 6039 method_name)), 6040 JSTemporalPlainTime); 6041 } 6042 6043 TO_INT_THROW_ON_INFTY(hour, JSTemporalPlainTime); 6044 TO_INT_THROW_ON_INFTY(minute, JSTemporalPlainTime); 6045 TO_INT_THROW_ON_INFTY(second, JSTemporalPlainTime); 6046 TO_INT_THROW_ON_INFTY(millisecond, JSTemporalPlainTime); 6047 TO_INT_THROW_ON_INFTY(microsecond, JSTemporalPlainTime); 6048 TO_INT_THROW_ON_INFTY(nanosecond, JSTemporalPlainTime); 6049 6050 // 14. Return ? CreateTemporalTime(hour, minute, second, millisecond, 6051 // microsecond, nanosecond, NewTarget). 6052 return CreateTemporalTime(isolate, target, new_target, hour, minute, second, 6053 millisecond, microsecond, nanosecond); 6054} 6055 6056// #sec-temporal.now.plaintimeiso 6057MaybeHandle<JSTemporalPlainTime> JSTemporalPlainTime::NowISO( 6058 Isolate* isolate, Handle<Object> temporal_time_zone_like) { 6059 const char* method_name = "Temporal.Now.plainTimeISO"; 6060 // 1. Let calendar be ! GetISO8601Calendar(). 6061 Handle<JSReceiver> calendar; 6062 ASSIGN_RETURN_ON_EXCEPTION(isolate, calendar, 6063 temporal::GetISO8601Calendar(isolate), 6064 JSTemporalPlainTime); 6065 // 2. Let dateTime be ? SystemDateTime(temporalTimeZoneLike, calendar). 6066 Handle<JSTemporalPlainDateTime> date_time; 6067 ASSIGN_RETURN_ON_EXCEPTION( 6068 isolate, date_time, 6069 SystemDateTime(isolate, temporal_time_zone_like, calendar, method_name), 6070 JSTemporalPlainTime); 6071 // 3. Return ! CreateTemporalTime(dateTime.[[ISOHour]], 6072 // dateTime.[[ISOMinute]], dateTime.[[ISOSecond]], 6073 // dateTime.[[ISOMillisecond]], dateTime.[[ISOMicrosecond]], 6074 // dateTime.[[ISONanosecond]]). 6075 return CreateTemporalTime( 6076 isolate, date_time->iso_hour(), date_time->iso_minute(), 6077 date_time->iso_second(), date_time->iso_millisecond(), 6078 date_time->iso_microsecond(), date_time->iso_nanosecond()); 6079} 6080 6081// #sec-temporal.plaintime.from 6082MaybeHandle<JSTemporalPlainTime> JSTemporalPlainTime::From( 6083 Isolate* isolate, Handle<Object> item_obj, Handle<Object> options_obj) { 6084 const char* method_name = "Temporal.PlainTime.from"; 6085 // 1. Set options to ? GetOptionsObject(options). 6086 Handle<JSReceiver> options; 6087 ASSIGN_RETURN_ON_EXCEPTION( 6088 isolate, options, GetOptionsObject(isolate, options_obj, method_name), 6089 JSTemporalPlainTime); 6090 // 2. Let overflow be ? ToTemporalOverflow(options). 6091 Maybe<ShowOverflow> maybe_overflow = 6092 ToTemporalOverflow(isolate, options, method_name); 6093 MAYBE_RETURN(maybe_overflow, Handle<JSTemporalPlainTime>()); 6094 ShowOverflow overflow = maybe_overflow.FromJust(); 6095 // 3. If Type(item) is Object and item has an [[InitializedTemporalTime]] 6096 // internal slot, then 6097 if (item_obj->IsJSTemporalPlainTime()) { 6098 // a. Return ? CreateTemporalTime(item.[[ISOHour]], item.[[ISOMinute]], 6099 // item.[[ISOSecond]], item.[[ISOMillisecond]], item.[[ISOMicrosecond]], 6100 // item.[[ISONanosecond]]). 6101 Handle<JSTemporalPlainTime> item = 6102 Handle<JSTemporalPlainTime>::cast(item_obj); 6103 return CreateTemporalTime(isolate, item->iso_hour(), item->iso_minute(), 6104 item->iso_second(), item->iso_millisecond(), 6105 item->iso_microsecond(), item->iso_nanosecond()); 6106 } 6107 // 4. Return ? ToTemporalTime(item, overflow). 6108 return temporal::ToTemporalTime(isolate, item_obj, overflow, method_name); 6109} 6110 6111// #sec-temporal.plaintime.prototype.getisofields 6112MaybeHandle<JSReceiver> JSTemporalPlainTime::GetISOFields( 6113 Isolate* isolate, Handle<JSTemporalPlainTime> temporal_time) { 6114 Factory* factory = isolate->factory(); 6115 // 1. Let temporalTime be the this value. 6116 // 2. Perform ? RequireInternalSlot(temporalTime, 6117 // [[InitializedTemporalTime]]). 6118 // 3. Let fields be ! OrdinaryObjectCreate(%Object.prototype%). 6119 Handle<JSObject> fields = 6120 isolate->factory()->NewJSObject(isolate->object_function()); 6121 // 4. Perform ! CreateDataPropertyOrThrow(fields, "calendar", 6122 // temporalTime.[[Calendar]]). 6123 Handle<JSTemporalCalendar> iso8601_calendar; 6124 ASSIGN_RETURN_ON_EXCEPTION(isolate, iso8601_calendar, 6125 temporal::GetISO8601Calendar(isolate), 6126 JSTemporalPlainTime); 6127 CHECK(JSReceiver::CreateDataProperty(isolate, fields, 6128 factory->calendar_string(), 6129 iso8601_calendar, Just(kThrowOnError)) 6130 .FromJust()); 6131 6132 // 5. Perform ! CreateDataPropertyOrThrow(fields, "isoHour", 6133 // (temporalTime.[[ISOHour]])). 6134 // 6. Perform ! CreateDataPropertyOrThrow(fields, "isoMicrosecond", 6135 // (temporalTime.[[ISOMicrosecond]])). 6136 // 7. Perform ! CreateDataPropertyOrThrow(fields, "isoMillisecond", 6137 // (temporalTime.[[ISOMillisecond]])). 6138 // 8. Perform ! CreateDataPropertyOrThrow(fields, "isoMinute", 6139 // (temporalTime.[[ISOMinute]])). 6140 // 9. Perform ! CreateDataPropertyOrThrow(fields, "isoNanosecond", 6141 // (temporalTime.[[ISONanosecond]])). 6142 // 10. Perform ! CreateDataPropertyOrThrow(fields, "isoSecond", 6143 // (temporalTime.[[ISOSecond]])). 6144 DEFINE_INT_FIELD(fields, isoHour, iso_hour, temporal_time) 6145 DEFINE_INT_FIELD(fields, isoMicrosecond, iso_microsecond, temporal_time) 6146 DEFINE_INT_FIELD(fields, isoMillisecond, iso_millisecond, temporal_time) 6147 DEFINE_INT_FIELD(fields, isoMinute, iso_minute, temporal_time) 6148 DEFINE_INT_FIELD(fields, isoNanosecond, iso_nanosecond, temporal_time) 6149 DEFINE_INT_FIELD(fields, isoSecond, iso_second, temporal_time) 6150 // 11. Return fields. 6151 return fields; 6152} 6153 6154// #sec-temporal.zoneddatetime 6155MaybeHandle<JSTemporalZonedDateTime> JSTemporalZonedDateTime::Constructor( 6156 Isolate* isolate, Handle<JSFunction> target, Handle<HeapObject> new_target, 6157 Handle<Object> epoch_nanoseconds_obj, Handle<Object> time_zone_like, 6158 Handle<Object> calendar_like) { 6159 const char* method_name = "Temporal.ZonedDateTime"; 6160 // 1. If NewTarget is undefined, then 6161 if (new_target->IsUndefined()) { 6162 // a. Throw a TypeError exception. 6163 THROW_NEW_ERROR(isolate, 6164 NewTypeError(MessageTemplate::kMethodInvokedOnWrongType, 6165 isolate->factory()->NewStringFromAsciiChecked( 6166 method_name)), 6167 JSTemporalZonedDateTime); 6168 } 6169 // 2. Set epochNanoseconds to ? ToBigInt(epochNanoseconds). 6170 Handle<BigInt> epoch_nanoseconds; 6171 ASSIGN_RETURN_ON_EXCEPTION(isolate, epoch_nanoseconds, 6172 BigInt::FromObject(isolate, epoch_nanoseconds_obj), 6173 JSTemporalZonedDateTime); 6174 // 3. If ! IsValidEpochNanoseconds(epochNanoseconds) is false, throw a 6175 // RangeError exception. 6176 if (!IsValidEpochNanoseconds(isolate, epoch_nanoseconds)) { 6177 THROW_NEW_ERROR(isolate, NEW_TEMPORAL_INVALD_ARG_RANGE_ERROR(), 6178 JSTemporalZonedDateTime); 6179 } 6180 6181 // 4. Let timeZone be ? ToTemporalTimeZone(timeZoneLike). 6182 Handle<JSReceiver> time_zone; 6183 ASSIGN_RETURN_ON_EXCEPTION( 6184 isolate, time_zone, 6185 temporal::ToTemporalTimeZone(isolate, time_zone_like, method_name), 6186 JSTemporalZonedDateTime); 6187 6188 // 5. Let calendar be ? ToTemporalCalendarWithISODefault(calendarLike). 6189 Handle<JSReceiver> calendar; 6190 ASSIGN_RETURN_ON_EXCEPTION( 6191 isolate, calendar, 6192 ToTemporalCalendarWithISODefault(isolate, calendar_like, method_name), 6193 JSTemporalZonedDateTime); 6194 6195 // 6. Return ? CreateTemporalZonedDateTime(epochNanoseconds, timeZone, 6196 // calendar, NewTarget). 6197 return CreateTemporalZonedDateTime(isolate, target, new_target, 6198 epoch_nanoseconds, time_zone, calendar); 6199} 6200 6201// #sec-temporal.zoneddatetime.prototype.withcalendar 6202MaybeHandle<JSTemporalZonedDateTime> JSTemporalZonedDateTime::WithCalendar( 6203 Isolate* isolate, Handle<JSTemporalZonedDateTime> zoned_date_time, 6204 Handle<Object> calendar_like) { 6205 TEMPORAL_ENTER_FUNC(); 6206 const char* method_name = "Temporal.ZonedDateTime.prototype.withCalendar"; 6207 // 1. Let zonedDateTime be the this value. 6208 // 2. Perform ? RequireInternalSlot(zonedDateTime, 6209 // [[InitializedTemporalZonedDateTime]]). 6210 // 3. Let calendar be ? ToTemporalCalendar(calendarLike). 6211 Handle<JSReceiver> calendar; 6212 ASSIGN_RETURN_ON_EXCEPTION( 6213 isolate, calendar, 6214 temporal::ToTemporalCalendar(isolate, calendar_like, method_name), 6215 JSTemporalZonedDateTime); 6216 6217 // 4. Return ? CreateTemporalZonedDateTime(zonedDateTime.[[Nanoseconds]], 6218 // zonedDateTime.[[TimeZone]], calendar). 6219 Handle<BigInt> nanoseconds = handle(zoned_date_time->nanoseconds(), isolate); 6220 Handle<JSReceiver> time_zone = handle(zoned_date_time->time_zone(), isolate); 6221 return CreateTemporalZonedDateTime(isolate, nanoseconds, time_zone, calendar); 6222} 6223 6224// #sec-temporal.zoneddatetime.prototype.withtimezone 6225MaybeHandle<JSTemporalZonedDateTime> JSTemporalZonedDateTime::WithTimeZone( 6226 Isolate* isolate, Handle<JSTemporalZonedDateTime> zoned_date_time, 6227 Handle<Object> time_zone_like) { 6228 TEMPORAL_ENTER_FUNC(); 6229 const char* method_name = "Temporal.ZonedDateTime.prototype.withTimeZone"; 6230 // 1. Let zonedDateTime be the this value. 6231 // 2. Perform ? RequireInternalSlot(zonedDateTime, 6232 // [[InitializedTemporalZonedDateTime]]). 6233 // 3. Let timeZone be ? ToTemporalTimeZone(timeZoneLike). 6234 Handle<JSReceiver> time_zone; 6235 ASSIGN_RETURN_ON_EXCEPTION( 6236 isolate, time_zone, 6237 temporal::ToTemporalTimeZone(isolate, time_zone_like, method_name), 6238 JSTemporalZonedDateTime); 6239 6240 // 4. Return ? CreateTemporalZonedDateTime(zonedDateTime.[[Nanoseconds]], 6241 // timeZone, zonedDateTime.[[Calendar]]). 6242 Handle<BigInt> nanoseconds = handle(zoned_date_time->nanoseconds(), isolate); 6243 Handle<JSReceiver> calendar = handle(zoned_date_time->calendar(), isolate); 6244 return CreateTemporalZonedDateTime(isolate, nanoseconds, time_zone, calendar); 6245} 6246 6247// Common code shared by ZonedDateTime.prototype.toPlainYearMonth and 6248// toPlainMonthDay 6249template <typename T, 6250 MaybeHandle<T> (*from_fields_func)( 6251 Isolate*, Handle<JSReceiver>, Handle<JSReceiver>, Handle<Object>)> 6252MaybeHandle<T> ZonedDateTimeToPlainYearMonthOrMonthDay( 6253 Isolate* isolate, Handle<JSTemporalZonedDateTime> zoned_date_time, 6254 Handle<String> field_name_1, Handle<String> field_name_2, 6255 const char* method_name) { 6256 TEMPORAL_ENTER_FUNC(); 6257 Factory* factory = isolate->factory(); 6258 // 1. Let zonedDateTime be the this value. 6259 // 2. Perform ? RequireInternalSlot(zonedDateTime, 6260 // [[InitializedTemporalZonedDateTime]]). 6261 // 3. Let timeZone be zonedDateTime.[[TimeZone]]. 6262 Handle<JSReceiver> time_zone = handle(zoned_date_time->time_zone(), isolate); 6263 // 4. Let instant be ! CreateTemporalInstant(zonedDateTime.[[Nanoseconds]]). 6264 Handle<JSTemporalInstant> instant; 6265 ASSIGN_RETURN_ON_EXCEPTION( 6266 isolate, instant, 6267 temporal::CreateTemporalInstant( 6268 isolate, Handle<BigInt>(zoned_date_time->nanoseconds(), isolate)), 6269 T); 6270 // 5. Let calendar be zonedDateTime.[[Calendar]]. 6271 Handle<JSReceiver> calendar = handle(zoned_date_time->calendar(), isolate); 6272 // 6. Let temporalDateTime be ? 6273 // temporal::BuiltinTimeZoneGetPlainDateTimeFor(timeZone, instant, calendar). 6274 Handle<JSTemporalPlainDateTime> temporal_date_time; 6275 ASSIGN_RETURN_ON_EXCEPTION( 6276 isolate, temporal_date_time, 6277 temporal::BuiltinTimeZoneGetPlainDateTimeFor(isolate, time_zone, instant, 6278 calendar, method_name), 6279 T); 6280 // 7. Let fieldNames be ? CalendarFields(calendar, « field_name_1, 6281 // field_name_2 »). 6282 Handle<FixedArray> field_names = factory->NewFixedArray(2); 6283 field_names->set(0, *field_name_1); 6284 field_names->set(1, *field_name_2); 6285 ASSIGN_RETURN_ON_EXCEPTION(isolate, field_names, 6286 CalendarFields(isolate, calendar, field_names), T); 6287 // 8. Let fields be ? PrepareTemporalFields(temporalDateTime, fieldNames, «»). 6288 Handle<JSReceiver> fields; 6289 ASSIGN_RETURN_ON_EXCEPTION( 6290 isolate, fields, 6291 PrepareTemporalFields(isolate, temporal_date_time, field_names, 6292 RequiredFields::kNone), 6293 T); 6294 // 9. Return ? XxxFromFields(calendar, fields). 6295 return from_fields_func(isolate, calendar, fields, 6296 factory->undefined_value()); 6297} 6298 6299// #sec-temporal.zoneddatetime.prototype.toplainyearmonth 6300MaybeHandle<JSTemporalPlainYearMonth> JSTemporalZonedDateTime::ToPlainYearMonth( 6301 Isolate* isolate, Handle<JSTemporalZonedDateTime> zoned_date_time) { 6302 return ZonedDateTimeToPlainYearMonthOrMonthDay<JSTemporalPlainYearMonth, 6303 YearMonthFromFields>( 6304 isolate, zoned_date_time, isolate->factory()->monthCode_string(), 6305 isolate->factory()->year_string(), 6306 "Temporal.ZonedDateTime.prototype.toPlainYearMonth"); 6307} 6308 6309// #sec-temporal.zoneddatetime.prototype.toplainmonthday 6310MaybeHandle<JSTemporalPlainMonthDay> JSTemporalZonedDateTime::ToPlainMonthDay( 6311 Isolate* isolate, Handle<JSTemporalZonedDateTime> zoned_date_time) { 6312 return ZonedDateTimeToPlainYearMonthOrMonthDay<JSTemporalPlainMonthDay, 6313 MonthDayFromFields>( 6314 isolate, zoned_date_time, isolate->factory()->day_string(), 6315 isolate->factory()->monthCode_string(), 6316 "Temporal.ZonedDateTime.prototype.toPlainMonthDay"); 6317} 6318 6319// #sec-temporal.now.zoneddatetime 6320MaybeHandle<JSTemporalZonedDateTime> JSTemporalZonedDateTime::Now( 6321 Isolate* isolate, Handle<Object> calendar_like, 6322 Handle<Object> temporal_time_zone_like) { 6323 const char* method_name = "Temporal.Now.zonedDateTime"; 6324 // 1. Return ? SystemZonedDateTime(temporalTimeZoneLike, calendarLike). 6325 return SystemZonedDateTime(isolate, temporal_time_zone_like, calendar_like, 6326 method_name); 6327} 6328 6329// #sec-temporal.now.zoneddatetimeiso 6330MaybeHandle<JSTemporalZonedDateTime> JSTemporalZonedDateTime::NowISO( 6331 Isolate* isolate, Handle<Object> temporal_time_zone_like) { 6332 TEMPORAL_ENTER_FUNC(); 6333 const char* method_name = "Temporal.Now.zonedDateTimeISO"; 6334 // 1. Let calendar be ! GetISO8601Calendar(). 6335 Handle<JSReceiver> calendar; 6336 ASSIGN_RETURN_ON_EXCEPTION(isolate, calendar, 6337 temporal::GetISO8601Calendar(isolate), 6338 JSTemporalZonedDateTime); 6339 // 2. Return ? SystemZonedDateTime(temporalTimeZoneLike, calendar). 6340 return SystemZonedDateTime(isolate, temporal_time_zone_like, calendar, 6341 method_name); 6342} 6343 6344// #sec-temporal.zoneddatetime.prototype.getisofields 6345MaybeHandle<JSReceiver> JSTemporalZonedDateTime::GetISOFields( 6346 Isolate* isolate, Handle<JSTemporalZonedDateTime> zoned_date_time) { 6347 TEMPORAL_ENTER_FUNC(); 6348 const char* method_name = "Temporal.ZonedDateTime.prototype.getISOFields"; 6349 Factory* factory = isolate->factory(); 6350 // 1. Let zonedDateTime be the this value. 6351 // 2. Perform ? RequireInternalSlot(zonedDateTime, 6352 // [[InitializedTemporalZonedDateTime]]). 6353 // 3. Let fields be ! OrdinaryObjectCreate(%Object.prototype%). 6354 Handle<JSObject> fields = 6355 isolate->factory()->NewJSObject(isolate->object_function()); 6356 // 4. Let timeZone be zonedDateTime.[[TimeZone]]. 6357 Handle<JSReceiver> time_zone = 6358 Handle<JSReceiver>(zoned_date_time->time_zone(), isolate); 6359 // 5. Let instant be ? CreateTemporalInstant(zonedDateTime.[[Nanoseconds]]). 6360 Handle<JSTemporalInstant> instant; 6361 ASSIGN_RETURN_ON_EXCEPTION( 6362 isolate, instant, 6363 temporal::CreateTemporalInstant( 6364 isolate, Handle<BigInt>(zoned_date_time->nanoseconds(), isolate)), 6365 JSReceiver); 6366 6367 // 6. Let calendar be zonedDateTime.[[Calendar]]. 6368 Handle<JSReceiver> calendar = 6369 Handle<JSReceiver>(zoned_date_time->calendar(), isolate); 6370 // 7. Let dateTime be ? BuiltinTimeZoneGetPlainDateTimeFor(timeZone, 6371 // instant, calendar). 6372 Handle<JSTemporalPlainDateTime> date_time; 6373 ASSIGN_RETURN_ON_EXCEPTION( 6374 isolate, date_time, 6375 temporal::BuiltinTimeZoneGetPlainDateTimeFor(isolate, time_zone, instant, 6376 calendar, method_name), 6377 JSReceiver); 6378 // 8. Let offset be ? BuiltinTimeZoneGetOffsetStringFor(timeZone, instant). 6379 Handle<String> offset; 6380 ASSIGN_RETURN_ON_EXCEPTION(isolate, offset, 6381 BuiltinTimeZoneGetOffsetStringFor( 6382 isolate, time_zone, instant, method_name), 6383 JSReceiver); 6384 6385#define DEFINE_STRING_FIELD(obj, str, field) \ 6386 CHECK(JSReceiver::CreateDataProperty(isolate, obj, factory->str##_string(), \ 6387 field, Just(kThrowOnError)) \ 6388 .FromJust()); 6389 6390 // 9. Perform ! CreateDataPropertyOrThrow(fields, "calendar", calendar). 6391 // 10. Perform ! CreateDataPropertyOrThrow(fields, "isoDay", 6392 // (dateTime.[[ISODay]])). 6393 // 11. Perform ! CreateDataPropertyOrThrow(fields, "isoHour", 6394 // (temporalTime.[[ISOHour]])). 6395 // 12. Perform ! CreateDataPropertyOrThrow(fields, "isoMicrosecond", 6396 // (temporalTime.[[ISOMicrosecond]])). 6397 // 13. Perform ! CreateDataPropertyOrThrow(fields, "isoMillisecond", 6398 // (temporalTime.[[ISOMillisecond]])). 6399 // 14. Perform ! CreateDataPropertyOrThrow(fields, "isoMinute", 6400 // (temporalTime.[[ISOMinute]])). 6401 // 15. Perform ! CreateDataPropertyOrThrow(fields, "isoMonth", 6402 // (temporalTime.[[ISOMonth]])). 6403 // 16. Perform ! CreateDataPropertyOrThrow(fields, "isoNanosecond", 6404 // (temporalTime.[[ISONanosecond]])). 6405 // 17. Perform ! CreateDataPropertyOrThrow(fields, "isoSecond", 6406 // (temporalTime.[[ISOSecond]])). 6407 // 18. Perform ! CreateDataPropertyOrThrow(fields, "isoYear", 6408 // (temporalTime.[[ISOYear]])). 6409 // 19. Perform ! CreateDataPropertyOrThrow(fields, "offset", offset). 6410 // 20. Perform ! CreateDataPropertyOrThrow(fields, "timeZone", timeZone). 6411 DEFINE_STRING_FIELD(fields, calendar, calendar) 6412 DEFINE_INT_FIELD(fields, isoDay, iso_day, date_time) 6413 DEFINE_INT_FIELD(fields, isoHour, iso_hour, date_time) 6414 DEFINE_INT_FIELD(fields, isoMicrosecond, iso_microsecond, date_time) 6415 DEFINE_INT_FIELD(fields, isoMillisecond, iso_millisecond, date_time) 6416 DEFINE_INT_FIELD(fields, isoMinute, iso_minute, date_time) 6417 DEFINE_INT_FIELD(fields, isoMonth, iso_month, date_time) 6418 DEFINE_INT_FIELD(fields, isoNanosecond, iso_nanosecond, date_time) 6419 DEFINE_INT_FIELD(fields, isoSecond, iso_second, date_time) 6420 DEFINE_INT_FIELD(fields, isoYear, iso_year, date_time) 6421 DEFINE_STRING_FIELD(fields, offset, offset) 6422 DEFINE_STRING_FIELD(fields, timeZone, time_zone) 6423 // 21. Return fields. 6424 return fields; 6425} 6426 6427// #sec-temporal.now.instant 6428MaybeHandle<JSTemporalInstant> JSTemporalInstant::Now(Isolate* isolate) { 6429 TEMPORAL_ENTER_FUNC(); 6430 return SystemInstant(isolate); 6431} 6432 6433// #sec-temporal.instant 6434MaybeHandle<JSTemporalInstant> JSTemporalInstant::Constructor( 6435 Isolate* isolate, Handle<JSFunction> target, Handle<HeapObject> new_target, 6436 Handle<Object> epoch_nanoseconds_obj) { 6437 TEMPORAL_ENTER_FUNC(); 6438 const char* method_name = "Temporal.Instant"; 6439 // 1. If NewTarget is undefined, then 6440 if (new_target->IsUndefined()) { 6441 // a. Throw a TypeError exception. 6442 THROW_NEW_ERROR(isolate, 6443 NewTypeError(MessageTemplate::kMethodInvokedOnWrongType, 6444 isolate->factory()->NewStringFromAsciiChecked( 6445 method_name)), 6446 JSTemporalInstant); 6447 } 6448 // 2. Let epochNanoseconds be ? ToBigInt(epochNanoseconds). 6449 Handle<BigInt> epoch_nanoseconds; 6450 ASSIGN_RETURN_ON_EXCEPTION(isolate, epoch_nanoseconds, 6451 BigInt::FromObject(isolate, epoch_nanoseconds_obj), 6452 JSTemporalInstant); 6453 // 3. If ! IsValidEpochNanoseconds(epochNanoseconds) is false, throw a 6454 // RangeError exception. 6455 if (!IsValidEpochNanoseconds(isolate, epoch_nanoseconds)) { 6456 THROW_NEW_ERROR(isolate, NEW_TEMPORAL_INVALD_ARG_RANGE_ERROR(), 6457 JSTemporalInstant); 6458 } 6459 // 4. Return ? CreateTemporalInstant(epochNanoseconds, NewTarget). 6460 return temporal::CreateTemporalInstant(isolate, target, new_target, 6461 epoch_nanoseconds); 6462} 6463 6464namespace { 6465 6466// The logic in Temporal.Instant.fromEpochSeconds and fromEpochMilliseconds, 6467// are the same except a scaling factor, code all of them into the follow 6468// function. 6469MaybeHandle<JSTemporalInstant> ScaleNumberToNanosecondsVerifyAndMake( 6470 Isolate* isolate, Handle<BigInt> bigint, uint32_t scale) { 6471 TEMPORAL_ENTER_FUNC(); 6472 DCHECK(scale == 1 || scale == 1000 || scale == 1000000 || 6473 scale == 1000000000); 6474 // 2. Let epochNanoseconds be epochXseconds × scaleℤ. 6475 Handle<BigInt> epoch_nanoseconds; 6476 if (scale == 1) { 6477 epoch_nanoseconds = bigint; 6478 } else { 6479 ASSIGN_RETURN_ON_EXCEPTION( 6480 isolate, epoch_nanoseconds, 6481 BigInt::Multiply(isolate, BigInt::FromUint64(isolate, scale), bigint), 6482 JSTemporalInstant); 6483 } 6484 // 3. If ! IsValidEpochNanoseconds(epochNanoseconds) is false, throw a 6485 // RangeError exception. 6486 if (!IsValidEpochNanoseconds(isolate, epoch_nanoseconds)) { 6487 THROW_NEW_ERROR(isolate, NEW_TEMPORAL_INVALD_ARG_RANGE_ERROR(), 6488 JSTemporalInstant); 6489 } 6490 return temporal::CreateTemporalInstant(isolate, epoch_nanoseconds); 6491} 6492 6493MaybeHandle<JSTemporalInstant> ScaleNumberToNanosecondsVerifyAndMake( 6494 Isolate* isolate, Handle<Object> epoch_Xseconds, uint32_t scale) { 6495 TEMPORAL_ENTER_FUNC(); 6496 // 1. Set epochXseconds to ? ToNumber(epochXseconds). 6497 ASSIGN_RETURN_ON_EXCEPTION(isolate, epoch_Xseconds, 6498 Object::ToNumber(isolate, epoch_Xseconds), 6499 JSTemporalInstant); 6500 // 2. Set epochMilliseconds to ? NumberToBigInt(epochMilliseconds). 6501 Handle<BigInt> bigint; 6502 ASSIGN_RETURN_ON_EXCEPTION(isolate, bigint, 6503 BigInt::FromNumber(isolate, epoch_Xseconds), 6504 JSTemporalInstant); 6505 return ScaleNumberToNanosecondsVerifyAndMake(isolate, bigint, scale); 6506} 6507 6508MaybeHandle<JSTemporalInstant> ScaleToNanosecondsVerifyAndMake( 6509 Isolate* isolate, Handle<Object> epoch_Xseconds, uint32_t scale) { 6510 TEMPORAL_ENTER_FUNC(); 6511 // 1. Set epochMicroseconds to ? ToBigInt(epochMicroseconds). 6512 Handle<BigInt> bigint; 6513 ASSIGN_RETURN_ON_EXCEPTION(isolate, bigint, 6514 BigInt::FromObject(isolate, epoch_Xseconds), 6515 JSTemporalInstant); 6516 return ScaleNumberToNanosecondsVerifyAndMake(isolate, bigint, scale); 6517} 6518 6519} // namespace 6520 6521// #sec-temporal.instant.fromepochseconds 6522MaybeHandle<JSTemporalInstant> JSTemporalInstant::FromEpochSeconds( 6523 Isolate* isolate, Handle<Object> epoch_seconds) { 6524 TEMPORAL_ENTER_FUNC(); 6525 return ScaleNumberToNanosecondsVerifyAndMake(isolate, epoch_seconds, 6526 1000000000); 6527} 6528 6529// #sec-temporal.instant.fromepochmilliseconds 6530MaybeHandle<JSTemporalInstant> JSTemporalInstant::FromEpochMilliseconds( 6531 Isolate* isolate, Handle<Object> epoch_milliseconds) { 6532 TEMPORAL_ENTER_FUNC(); 6533 return ScaleNumberToNanosecondsVerifyAndMake(isolate, epoch_milliseconds, 6534 1000000); 6535} 6536 6537// #sec-temporal.instant.fromepochmicroseconds 6538MaybeHandle<JSTemporalInstant> JSTemporalInstant::FromEpochMicroseconds( 6539 Isolate* isolate, Handle<Object> epoch_microseconds) { 6540 TEMPORAL_ENTER_FUNC(); 6541 return ScaleToNanosecondsVerifyAndMake(isolate, epoch_microseconds, 1000); 6542} 6543 6544// #sec-temporal.instant.fromepochnanoeconds 6545MaybeHandle<JSTemporalInstant> JSTemporalInstant::FromEpochNanoseconds( 6546 Isolate* isolate, Handle<Object> epoch_nanoseconds) { 6547 TEMPORAL_ENTER_FUNC(); 6548 return ScaleToNanosecondsVerifyAndMake(isolate, epoch_nanoseconds, 1); 6549} 6550 6551// #sec-temporal.instant.from 6552MaybeHandle<JSTemporalInstant> JSTemporalInstant::From(Isolate* isolate, 6553 Handle<Object> item) { 6554 TEMPORAL_ENTER_FUNC(); 6555 const char* method_name = "Temporal.Instant.from"; 6556 // 1. If Type(item) is Object and item has an [[InitializedTemporalInstant]] 6557 // internal slot, then 6558 if (item->IsJSTemporalInstant()) { 6559 // a. Return ? CreateTemporalInstant(item.[[Nanoseconds]]). 6560 return temporal::CreateTemporalInstant( 6561 isolate, handle(JSTemporalInstant::cast(*item).nanoseconds(), isolate)); 6562 } 6563 // 2. Return ? ToTemporalInstant(item). 6564 return ToTemporalInstant(isolate, item, method_name); 6565} 6566 6567} // namespace internal 6568} // namespace v8 6569