1// Copyright 2016 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/builtins/builtins-utils-inl.h" 6#include "src/builtins/builtins.h" 7#include "src/codegen/code-factory.h" 8#include "src/date/date.h" 9#include "src/date/dateparser-inl.h" 10#include "src/logging/counters.h" 11#include "src/numbers/conversions.h" 12#include "src/objects/objects-inl.h" 13#ifdef V8_INTL_SUPPORT 14#include "src/objects/intl-objects.h" 15#include "src/objects/js-date-time-format.h" 16#endif 17#include "src/strings/string-stream.h" 18 19namespace v8 { 20namespace internal { 21 22// ----------------------------------------------------------------------------- 23// ES6 section 20.3 Date Objects 24 25namespace { 26 27// ES6 section 20.3.1.16 Date Time String Format 28double ParseDateTimeString(Isolate* isolate, Handle<String> str) { 29 str = String::Flatten(isolate, str); 30 double out[DateParser::OUTPUT_SIZE]; 31 DisallowGarbageCollection no_gc; 32 String::FlatContent str_content = str->GetFlatContent(no_gc); 33 bool result; 34 if (str_content.IsOneByte()) { 35 result = DateParser::Parse(isolate, str_content.ToOneByteVector(), out); 36 } else { 37 result = DateParser::Parse(isolate, str_content.ToUC16Vector(), out); 38 } 39 if (!result) return std::numeric_limits<double>::quiet_NaN(); 40 double const day = MakeDay(out[DateParser::YEAR], out[DateParser::MONTH], 41 out[DateParser::DAY]); 42 double const time = 43 MakeTime(out[DateParser::HOUR], out[DateParser::MINUTE], 44 out[DateParser::SECOND], out[DateParser::MILLISECOND]); 45 double date = MakeDate(day, time); 46 if (std::isnan(out[DateParser::UTC_OFFSET])) { 47 if (date >= -DateCache::kMaxTimeBeforeUTCInMs && 48 date <= DateCache::kMaxTimeBeforeUTCInMs) { 49 date = isolate->date_cache()->ToUTC(static_cast<int64_t>(date)); 50 } else { 51 return std::numeric_limits<double>::quiet_NaN(); 52 } 53 } else { 54 date -= out[DateParser::UTC_OFFSET] * 1000.0; 55 } 56 return DateCache::TimeClip(date); 57} 58 59Object SetLocalDateValue(Isolate* isolate, Handle<JSDate> date, 60 double time_val) { 61 if (time_val >= -DateCache::kMaxTimeBeforeUTCInMs && 62 time_val <= DateCache::kMaxTimeBeforeUTCInMs) { 63 time_val = isolate->date_cache()->ToUTC(static_cast<int64_t>(time_val)); 64 } else { 65 time_val = std::numeric_limits<double>::quiet_NaN(); 66 } 67 return *JSDate::SetValue(date, DateCache::TimeClip(time_val)); 68} 69 70} // namespace 71 72// ES #sec-date-constructor 73BUILTIN(DateConstructor) { 74 HandleScope scope(isolate); 75 if (args.new_target()->IsUndefined(isolate)) { 76 double const time_val = JSDate::CurrentTimeValue(isolate); 77 DateBuffer buffer = ToDateString(time_val, isolate->date_cache(), 78 ToDateStringMode::kLocalDateAndTime); 79 RETURN_RESULT_OR_FAILURE( 80 isolate, isolate->factory()->NewStringFromUtf8(base::VectorOf(buffer))); 81 } 82 // [Construct] 83 int const argc = args.length() - 1; 84 Handle<JSFunction> target = args.target(); 85 Handle<JSReceiver> new_target = Handle<JSReceiver>::cast(args.new_target()); 86 double time_val; 87 if (argc == 0) { 88 time_val = JSDate::CurrentTimeValue(isolate); 89 } else if (argc == 1) { 90 Handle<Object> value = args.at(1); 91 if (value->IsJSDate()) { 92 time_val = Handle<JSDate>::cast(value)->value().Number(); 93 } else { 94 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, value, 95 Object::ToPrimitive(isolate, value)); 96 if (value->IsString()) { 97 time_val = ParseDateTimeString(isolate, Handle<String>::cast(value)); 98 } else { 99 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, value, 100 Object::ToNumber(isolate, value)); 101 time_val = value->Number(); 102 } 103 } 104 } else { 105 Handle<Object> year_object; 106 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, year_object, 107 Object::ToNumber(isolate, args.at(1))); 108 Handle<Object> month_object; 109 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, month_object, 110 Object::ToNumber(isolate, args.at(2))); 111 double year = year_object->Number(); 112 double month = month_object->Number(); 113 double date = 1.0, hours = 0.0, minutes = 0.0, seconds = 0.0, ms = 0.0; 114 if (argc >= 3) { 115 Handle<Object> date_object; 116 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, date_object, 117 Object::ToNumber(isolate, args.at(3))); 118 date = date_object->Number(); 119 if (argc >= 4) { 120 Handle<Object> hours_object; 121 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( 122 isolate, hours_object, Object::ToNumber(isolate, args.at(4))); 123 hours = hours_object->Number(); 124 if (argc >= 5) { 125 Handle<Object> minutes_object; 126 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( 127 isolate, minutes_object, Object::ToNumber(isolate, args.at(5))); 128 minutes = minutes_object->Number(); 129 if (argc >= 6) { 130 Handle<Object> seconds_object; 131 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( 132 isolate, seconds_object, Object::ToNumber(isolate, args.at(6))); 133 seconds = seconds_object->Number(); 134 if (argc >= 7) { 135 Handle<Object> ms_object; 136 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( 137 isolate, ms_object, Object::ToNumber(isolate, args.at(7))); 138 ms = ms_object->Number(); 139 } 140 } 141 } 142 } 143 } 144 if (!std::isnan(year)) { 145 double const y = DoubleToInteger(year); 146 if (0.0 <= y && y <= 99) year = 1900 + y; 147 } 148 double const day = MakeDay(year, month, date); 149 double const time = MakeTime(hours, minutes, seconds, ms); 150 time_val = MakeDate(day, time); 151 if (time_val >= -DateCache::kMaxTimeBeforeUTCInMs && 152 time_val <= DateCache::kMaxTimeBeforeUTCInMs) { 153 time_val = isolate->date_cache()->ToUTC(static_cast<int64_t>(time_val)); 154 } else { 155 time_val = std::numeric_limits<double>::quiet_NaN(); 156 } 157 } 158 RETURN_RESULT_OR_FAILURE(isolate, JSDate::New(target, new_target, time_val)); 159} 160 161// ES6 section 20.3.3.1 Date.now ( ) 162BUILTIN(DateNow) { 163 HandleScope scope(isolate); 164 return *isolate->factory()->NewNumber(JSDate::CurrentTimeValue(isolate)); 165} 166 167// ES6 section 20.3.3.2 Date.parse ( string ) 168BUILTIN(DateParse) { 169 HandleScope scope(isolate); 170 Handle<String> string; 171 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( 172 isolate, string, 173 Object::ToString(isolate, args.atOrUndefined(isolate, 1))); 174 return *isolate->factory()->NewNumber(ParseDateTimeString(isolate, string)); 175} 176 177// ES6 section 20.3.3.4 Date.UTC (year,month,date,hours,minutes,seconds,ms) 178BUILTIN(DateUTC) { 179 HandleScope scope(isolate); 180 int const argc = args.length() - 1; 181 double year = std::numeric_limits<double>::quiet_NaN(); 182 double month = 0.0, date = 1.0, hours = 0.0, minutes = 0.0, seconds = 0.0, 183 ms = 0.0; 184 if (argc >= 1) { 185 Handle<Object> year_object; 186 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, year_object, 187 Object::ToNumber(isolate, args.at(1))); 188 year = year_object->Number(); 189 if (argc >= 2) { 190 Handle<Object> month_object; 191 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, month_object, 192 Object::ToNumber(isolate, args.at(2))); 193 month = month_object->Number(); 194 if (argc >= 3) { 195 Handle<Object> date_object; 196 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( 197 isolate, date_object, Object::ToNumber(isolate, args.at(3))); 198 date = date_object->Number(); 199 if (argc >= 4) { 200 Handle<Object> hours_object; 201 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( 202 isolate, hours_object, Object::ToNumber(isolate, args.at(4))); 203 hours = hours_object->Number(); 204 if (argc >= 5) { 205 Handle<Object> minutes_object; 206 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( 207 isolate, minutes_object, Object::ToNumber(isolate, args.at(5))); 208 minutes = minutes_object->Number(); 209 if (argc >= 6) { 210 Handle<Object> seconds_object; 211 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( 212 isolate, seconds_object, 213 Object::ToNumber(isolate, args.at(6))); 214 seconds = seconds_object->Number(); 215 if (argc >= 7) { 216 Handle<Object> ms_object; 217 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( 218 isolate, ms_object, Object::ToNumber(isolate, args.at(7))); 219 ms = ms_object->Number(); 220 } 221 } 222 } 223 } 224 } 225 } 226 } 227 if (!std::isnan(year)) { 228 double const y = DoubleToInteger(year); 229 if (0.0 <= y && y <= 99) year = 1900 + y; 230 } 231 double const day = MakeDay(year, month, date); 232 double const time = MakeTime(hours, minutes, seconds, ms); 233 return *isolate->factory()->NewNumber( 234 DateCache::TimeClip(MakeDate(day, time))); 235} 236 237// ES6 section 20.3.4.20 Date.prototype.setDate ( date ) 238BUILTIN(DatePrototypeSetDate) { 239 HandleScope scope(isolate); 240 CHECK_RECEIVER(JSDate, date, "Date.prototype.setDate"); 241 Handle<Object> value = args.atOrUndefined(isolate, 1); 242 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, value, 243 Object::ToNumber(isolate, value)); 244 double time_val = date->value().Number(); 245 if (!std::isnan(time_val)) { 246 int64_t const time_ms = static_cast<int64_t>(time_val); 247 int64_t local_time_ms = isolate->date_cache()->ToLocal(time_ms); 248 int const days = isolate->date_cache()->DaysFromTime(local_time_ms); 249 int time_within_day = isolate->date_cache()->TimeInDay(local_time_ms, days); 250 int year, month, day; 251 isolate->date_cache()->YearMonthDayFromDays(days, &year, &month, &day); 252 time_val = MakeDate(MakeDay(year, month, value->Number()), time_within_day); 253 } 254 return SetLocalDateValue(isolate, date, time_val); 255} 256 257// ES6 section 20.3.4.21 Date.prototype.setFullYear (year, month, date) 258BUILTIN(DatePrototypeSetFullYear) { 259 HandleScope scope(isolate); 260 CHECK_RECEIVER(JSDate, date, "Date.prototype.setFullYear"); 261 int const argc = args.length() - 1; 262 Handle<Object> year = args.atOrUndefined(isolate, 1); 263 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, year, 264 Object::ToNumber(isolate, year)); 265 double year_double = year->Number(), month_double = 0.0, day_double = 1.0; 266 int time_within_day = 0; 267 if (!std::isnan(date->value().Number())) { 268 int64_t const time_ms = static_cast<int64_t>(date->value().Number()); 269 int64_t local_time_ms = isolate->date_cache()->ToLocal(time_ms); 270 int const days = isolate->date_cache()->DaysFromTime(local_time_ms); 271 time_within_day = isolate->date_cache()->TimeInDay(local_time_ms, days); 272 int year_int, month_int, day_int; 273 isolate->date_cache()->YearMonthDayFromDays(days, &year_int, &month_int, 274 &day_int); 275 month_double = month_int; 276 day_double = day_int; 277 } 278 if (argc >= 2) { 279 Handle<Object> month = args.at(2); 280 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, month, 281 Object::ToNumber(isolate, month)); 282 month_double = month->Number(); 283 if (argc >= 3) { 284 Handle<Object> day = args.at(3); 285 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, day, 286 Object::ToNumber(isolate, day)); 287 day_double = day->Number(); 288 } 289 } 290 double time_val = 291 MakeDate(MakeDay(year_double, month_double, day_double), time_within_day); 292 return SetLocalDateValue(isolate, date, time_val); 293} 294 295// ES6 section 20.3.4.22 Date.prototype.setHours(hour, min, sec, ms) 296BUILTIN(DatePrototypeSetHours) { 297 HandleScope scope(isolate); 298 CHECK_RECEIVER(JSDate, date, "Date.prototype.setHours"); 299 int const argc = args.length() - 1; 300 Handle<Object> hour = args.atOrUndefined(isolate, 1); 301 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, hour, 302 Object::ToNumber(isolate, hour)); 303 double h = hour->Number(); 304 double time_val = date->value().Number(); 305 if (!std::isnan(time_val)) { 306 int64_t const time_ms = static_cast<int64_t>(time_val); 307 int64_t local_time_ms = isolate->date_cache()->ToLocal(time_ms); 308 int day = isolate->date_cache()->DaysFromTime(local_time_ms); 309 int time_within_day = isolate->date_cache()->TimeInDay(local_time_ms, day); 310 double m = (time_within_day / (60 * 1000)) % 60; 311 double s = (time_within_day / 1000) % 60; 312 double milli = time_within_day % 1000; 313 if (argc >= 2) { 314 Handle<Object> min = args.at(2); 315 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, min, 316 Object::ToNumber(isolate, min)); 317 m = min->Number(); 318 if (argc >= 3) { 319 Handle<Object> sec = args.at(3); 320 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, sec, 321 Object::ToNumber(isolate, sec)); 322 s = sec->Number(); 323 if (argc >= 4) { 324 Handle<Object> ms = args.at(4); 325 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, ms, 326 Object::ToNumber(isolate, ms)); 327 milli = ms->Number(); 328 } 329 } 330 } 331 time_val = MakeDate(day, MakeTime(h, m, s, milli)); 332 } 333 return SetLocalDateValue(isolate, date, time_val); 334} 335 336// ES6 section 20.3.4.23 Date.prototype.setMilliseconds(ms) 337BUILTIN(DatePrototypeSetMilliseconds) { 338 HandleScope scope(isolate); 339 CHECK_RECEIVER(JSDate, date, "Date.prototype.setMilliseconds"); 340 Handle<Object> ms = args.atOrUndefined(isolate, 1); 341 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, ms, 342 Object::ToNumber(isolate, ms)); 343 double time_val = date->value().Number(); 344 if (!std::isnan(time_val)) { 345 int64_t const time_ms = static_cast<int64_t>(time_val); 346 int64_t local_time_ms = isolate->date_cache()->ToLocal(time_ms); 347 int day = isolate->date_cache()->DaysFromTime(local_time_ms); 348 int time_within_day = isolate->date_cache()->TimeInDay(local_time_ms, day); 349 int h = time_within_day / (60 * 60 * 1000); 350 int m = (time_within_day / (60 * 1000)) % 60; 351 int s = (time_within_day / 1000) % 60; 352 time_val = MakeDate(day, MakeTime(h, m, s, ms->Number())); 353 } 354 return SetLocalDateValue(isolate, date, time_val); 355} 356 357// ES6 section 20.3.4.24 Date.prototype.setMinutes ( min, sec, ms ) 358BUILTIN(DatePrototypeSetMinutes) { 359 HandleScope scope(isolate); 360 CHECK_RECEIVER(JSDate, date, "Date.prototype.setMinutes"); 361 int const argc = args.length() - 1; 362 Handle<Object> min = args.atOrUndefined(isolate, 1); 363 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, min, 364 Object::ToNumber(isolate, min)); 365 double time_val = date->value().Number(); 366 if (!std::isnan(time_val)) { 367 int64_t const time_ms = static_cast<int64_t>(time_val); 368 int64_t local_time_ms = isolate->date_cache()->ToLocal(time_ms); 369 int day = isolate->date_cache()->DaysFromTime(local_time_ms); 370 int time_within_day = isolate->date_cache()->TimeInDay(local_time_ms, day); 371 int h = time_within_day / (60 * 60 * 1000); 372 double m = min->Number(); 373 double s = (time_within_day / 1000) % 60; 374 double milli = time_within_day % 1000; 375 if (argc >= 2) { 376 Handle<Object> sec = args.at(2); 377 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, sec, 378 Object::ToNumber(isolate, sec)); 379 s = sec->Number(); 380 if (argc >= 3) { 381 Handle<Object> ms = args.at(3); 382 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, ms, 383 Object::ToNumber(isolate, ms)); 384 milli = ms->Number(); 385 } 386 } 387 time_val = MakeDate(day, MakeTime(h, m, s, milli)); 388 } 389 return SetLocalDateValue(isolate, date, time_val); 390} 391 392// ES6 section 20.3.4.25 Date.prototype.setMonth ( month, date ) 393BUILTIN(DatePrototypeSetMonth) { 394 HandleScope scope(isolate); 395 CHECK_RECEIVER(JSDate, this_date, "Date.prototype.setMonth"); 396 int const argc = args.length() - 1; 397 Handle<Object> month = args.atOrUndefined(isolate, 1); 398 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, month, 399 Object::ToNumber(isolate, month)); 400 double time_val = this_date->value().Number(); 401 if (!std::isnan(time_val)) { 402 int64_t const time_ms = static_cast<int64_t>(time_val); 403 int64_t local_time_ms = isolate->date_cache()->ToLocal(time_ms); 404 int days = isolate->date_cache()->DaysFromTime(local_time_ms); 405 int time_within_day = isolate->date_cache()->TimeInDay(local_time_ms, days); 406 int year, unused, day; 407 isolate->date_cache()->YearMonthDayFromDays(days, &year, &unused, &day); 408 double m = month->Number(); 409 double dt = day; 410 if (argc >= 2) { 411 Handle<Object> date = args.at(2); 412 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, date, 413 Object::ToNumber(isolate, date)); 414 dt = date->Number(); 415 } 416 time_val = MakeDate(MakeDay(year, m, dt), time_within_day); 417 } 418 return SetLocalDateValue(isolate, this_date, time_val); 419} 420 421// ES6 section 20.3.4.26 Date.prototype.setSeconds ( sec, ms ) 422BUILTIN(DatePrototypeSetSeconds) { 423 HandleScope scope(isolate); 424 CHECK_RECEIVER(JSDate, date, "Date.prototype.setSeconds"); 425 int const argc = args.length() - 1; 426 Handle<Object> sec = args.atOrUndefined(isolate, 1); 427 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, sec, 428 Object::ToNumber(isolate, sec)); 429 double time_val = date->value().Number(); 430 if (!std::isnan(time_val)) { 431 int64_t const time_ms = static_cast<int64_t>(time_val); 432 int64_t local_time_ms = isolate->date_cache()->ToLocal(time_ms); 433 int day = isolate->date_cache()->DaysFromTime(local_time_ms); 434 int time_within_day = isolate->date_cache()->TimeInDay(local_time_ms, day); 435 int h = time_within_day / (60 * 60 * 1000); 436 double m = (time_within_day / (60 * 1000)) % 60; 437 double s = sec->Number(); 438 double milli = time_within_day % 1000; 439 if (argc >= 2) { 440 Handle<Object> ms = args.at(2); 441 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, ms, 442 Object::ToNumber(isolate, ms)); 443 milli = ms->Number(); 444 } 445 time_val = MakeDate(day, MakeTime(h, m, s, milli)); 446 } 447 return SetLocalDateValue(isolate, date, time_val); 448} 449 450// ES6 section 20.3.4.27 Date.prototype.setTime ( time ) 451BUILTIN(DatePrototypeSetTime) { 452 HandleScope scope(isolate); 453 CHECK_RECEIVER(JSDate, date, "Date.prototype.setTime"); 454 Handle<Object> value = args.atOrUndefined(isolate, 1); 455 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, value, 456 Object::ToNumber(isolate, value)); 457 return *JSDate::SetValue(date, DateCache::TimeClip(value->Number())); 458} 459 460// ES6 section 20.3.4.28 Date.prototype.setUTCDate ( date ) 461BUILTIN(DatePrototypeSetUTCDate) { 462 HandleScope scope(isolate); 463 CHECK_RECEIVER(JSDate, date, "Date.prototype.setUTCDate"); 464 Handle<Object> value = args.atOrUndefined(isolate, 1); 465 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, value, 466 Object::ToNumber(isolate, value)); 467 if (std::isnan(date->value().Number())) return date->value(); 468 int64_t const time_ms = static_cast<int64_t>(date->value().Number()); 469 int const days = isolate->date_cache()->DaysFromTime(time_ms); 470 int const time_within_day = isolate->date_cache()->TimeInDay(time_ms, days); 471 int year, month, day; 472 isolate->date_cache()->YearMonthDayFromDays(days, &year, &month, &day); 473 double const time_val = 474 MakeDate(MakeDay(year, month, value->Number()), time_within_day); 475 return *JSDate::SetValue(date, DateCache::TimeClip(time_val)); 476} 477 478// ES6 section 20.3.4.29 Date.prototype.setUTCFullYear (year, month, date) 479BUILTIN(DatePrototypeSetUTCFullYear) { 480 HandleScope scope(isolate); 481 CHECK_RECEIVER(JSDate, date, "Date.prototype.setUTCFullYear"); 482 int const argc = args.length() - 1; 483 Handle<Object> year = args.atOrUndefined(isolate, 1); 484 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, year, 485 Object::ToNumber(isolate, year)); 486 double year_double = year->Number(), month_double = 0.0, day_double = 1.0; 487 int time_within_day = 0; 488 if (!std::isnan(date->value().Number())) { 489 int64_t const time_ms = static_cast<int64_t>(date->value().Number()); 490 int const days = isolate->date_cache()->DaysFromTime(time_ms); 491 time_within_day = isolate->date_cache()->TimeInDay(time_ms, days); 492 int year_int, month_int, day_int; 493 isolate->date_cache()->YearMonthDayFromDays(days, &year_int, &month_int, 494 &day_int); 495 month_double = month_int; 496 day_double = day_int; 497 } 498 if (argc >= 2) { 499 Handle<Object> month = args.at(2); 500 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, month, 501 Object::ToNumber(isolate, month)); 502 month_double = month->Number(); 503 if (argc >= 3) { 504 Handle<Object> day = args.at(3); 505 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, day, 506 Object::ToNumber(isolate, day)); 507 day_double = day->Number(); 508 } 509 } 510 double const time_val = 511 MakeDate(MakeDay(year_double, month_double, day_double), time_within_day); 512 return *JSDate::SetValue(date, DateCache::TimeClip(time_val)); 513} 514 515// ES6 section 20.3.4.30 Date.prototype.setUTCHours(hour, min, sec, ms) 516BUILTIN(DatePrototypeSetUTCHours) { 517 HandleScope scope(isolate); 518 CHECK_RECEIVER(JSDate, date, "Date.prototype.setUTCHours"); 519 int const argc = args.length() - 1; 520 Handle<Object> hour = args.atOrUndefined(isolate, 1); 521 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, hour, 522 Object::ToNumber(isolate, hour)); 523 double h = hour->Number(); 524 double time_val = date->value().Number(); 525 if (!std::isnan(time_val)) { 526 int64_t const time_ms = static_cast<int64_t>(time_val); 527 int day = isolate->date_cache()->DaysFromTime(time_ms); 528 int time_within_day = isolate->date_cache()->TimeInDay(time_ms, day); 529 double m = (time_within_day / (60 * 1000)) % 60; 530 double s = (time_within_day / 1000) % 60; 531 double milli = time_within_day % 1000; 532 if (argc >= 2) { 533 Handle<Object> min = args.at(2); 534 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, min, 535 Object::ToNumber(isolate, min)); 536 m = min->Number(); 537 if (argc >= 3) { 538 Handle<Object> sec = args.at(3); 539 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, sec, 540 Object::ToNumber(isolate, sec)); 541 s = sec->Number(); 542 if (argc >= 4) { 543 Handle<Object> ms = args.at(4); 544 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, ms, 545 Object::ToNumber(isolate, ms)); 546 milli = ms->Number(); 547 } 548 } 549 } 550 time_val = MakeDate(day, MakeTime(h, m, s, milli)); 551 } 552 return *JSDate::SetValue(date, DateCache::TimeClip(time_val)); 553} 554 555// ES6 section 20.3.4.31 Date.prototype.setUTCMilliseconds(ms) 556BUILTIN(DatePrototypeSetUTCMilliseconds) { 557 HandleScope scope(isolate); 558 CHECK_RECEIVER(JSDate, date, "Date.prototype.setUTCMilliseconds"); 559 Handle<Object> ms = args.atOrUndefined(isolate, 1); 560 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, ms, 561 Object::ToNumber(isolate, ms)); 562 double time_val = date->value().Number(); 563 if (!std::isnan(time_val)) { 564 int64_t const time_ms = static_cast<int64_t>(time_val); 565 int day = isolate->date_cache()->DaysFromTime(time_ms); 566 int time_within_day = isolate->date_cache()->TimeInDay(time_ms, day); 567 int h = time_within_day / (60 * 60 * 1000); 568 int m = (time_within_day / (60 * 1000)) % 60; 569 int s = (time_within_day / 1000) % 60; 570 time_val = MakeDate(day, MakeTime(h, m, s, ms->Number())); 571 } 572 return *JSDate::SetValue(date, DateCache::TimeClip(time_val)); 573} 574 575// ES6 section 20.3.4.32 Date.prototype.setUTCMinutes ( min, sec, ms ) 576BUILTIN(DatePrototypeSetUTCMinutes) { 577 HandleScope scope(isolate); 578 CHECK_RECEIVER(JSDate, date, "Date.prototype.setUTCMinutes"); 579 int const argc = args.length() - 1; 580 Handle<Object> min = args.atOrUndefined(isolate, 1); 581 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, min, 582 Object::ToNumber(isolate, min)); 583 double time_val = date->value().Number(); 584 if (!std::isnan(time_val)) { 585 int64_t const time_ms = static_cast<int64_t>(time_val); 586 int day = isolate->date_cache()->DaysFromTime(time_ms); 587 int time_within_day = isolate->date_cache()->TimeInDay(time_ms, day); 588 int h = time_within_day / (60 * 60 * 1000); 589 double m = min->Number(); 590 double s = (time_within_day / 1000) % 60; 591 double milli = time_within_day % 1000; 592 if (argc >= 2) { 593 Handle<Object> sec = args.at(2); 594 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, sec, 595 Object::ToNumber(isolate, sec)); 596 s = sec->Number(); 597 if (argc >= 3) { 598 Handle<Object> ms = args.at(3); 599 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, ms, 600 Object::ToNumber(isolate, ms)); 601 milli = ms->Number(); 602 } 603 } 604 time_val = MakeDate(day, MakeTime(h, m, s, milli)); 605 } 606 return *JSDate::SetValue(date, DateCache::TimeClip(time_val)); 607} 608 609// ES6 section 20.3.4.31 Date.prototype.setUTCMonth ( month, date ) 610BUILTIN(DatePrototypeSetUTCMonth) { 611 HandleScope scope(isolate); 612 CHECK_RECEIVER(JSDate, this_date, "Date.prototype.setUTCMonth"); 613 int const argc = args.length() - 1; 614 Handle<Object> month = args.atOrUndefined(isolate, 1); 615 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, month, 616 Object::ToNumber(isolate, month)); 617 double time_val = this_date->value().Number(); 618 if (!std::isnan(time_val)) { 619 int64_t const time_ms = static_cast<int64_t>(time_val); 620 int days = isolate->date_cache()->DaysFromTime(time_ms); 621 int time_within_day = isolate->date_cache()->TimeInDay(time_ms, days); 622 int year, unused, day; 623 isolate->date_cache()->YearMonthDayFromDays(days, &year, &unused, &day); 624 double m = month->Number(); 625 double dt = day; 626 if (argc >= 2) { 627 Handle<Object> date = args.at(2); 628 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, date, 629 Object::ToNumber(isolate, date)); 630 dt = date->Number(); 631 } 632 time_val = MakeDate(MakeDay(year, m, dt), time_within_day); 633 } 634 return *JSDate::SetValue(this_date, DateCache::TimeClip(time_val)); 635} 636 637// ES6 section 20.3.4.34 Date.prototype.setUTCSeconds ( sec, ms ) 638BUILTIN(DatePrototypeSetUTCSeconds) { 639 HandleScope scope(isolate); 640 CHECK_RECEIVER(JSDate, date, "Date.prototype.setUTCSeconds"); 641 int const argc = args.length() - 1; 642 Handle<Object> sec = args.atOrUndefined(isolate, 1); 643 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, sec, 644 Object::ToNumber(isolate, sec)); 645 double time_val = date->value().Number(); 646 if (!std::isnan(time_val)) { 647 int64_t const time_ms = static_cast<int64_t>(time_val); 648 int day = isolate->date_cache()->DaysFromTime(time_ms); 649 int time_within_day = isolate->date_cache()->TimeInDay(time_ms, day); 650 int h = time_within_day / (60 * 60 * 1000); 651 double m = (time_within_day / (60 * 1000)) % 60; 652 double s = sec->Number(); 653 double milli = time_within_day % 1000; 654 if (argc >= 2) { 655 Handle<Object> ms = args.at(2); 656 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, ms, 657 Object::ToNumber(isolate, ms)); 658 milli = ms->Number(); 659 } 660 time_val = MakeDate(day, MakeTime(h, m, s, milli)); 661 } 662 return *JSDate::SetValue(date, DateCache::TimeClip(time_val)); 663} 664 665// ES6 section 20.3.4.35 Date.prototype.toDateString ( ) 666BUILTIN(DatePrototypeToDateString) { 667 HandleScope scope(isolate); 668 CHECK_RECEIVER(JSDate, date, "Date.prototype.toDateString"); 669 DateBuffer buffer = 670 ToDateString(date->value().Number(), isolate->date_cache(), 671 ToDateStringMode::kLocalDate); 672 RETURN_RESULT_OR_FAILURE( 673 isolate, isolate->factory()->NewStringFromUtf8(base::VectorOf(buffer))); 674} 675 676// ES6 section 20.3.4.36 Date.prototype.toISOString ( ) 677BUILTIN(DatePrototypeToISOString) { 678 HandleScope scope(isolate); 679 CHECK_RECEIVER(JSDate, date, "Date.prototype.toISOString"); 680 double const time_val = date->value().Number(); 681 if (std::isnan(time_val)) { 682 THROW_NEW_ERROR_RETURN_FAILURE( 683 isolate, NewRangeError(MessageTemplate::kInvalidTimeValue)); 684 } 685 int64_t const time_ms = static_cast<int64_t>(time_val); 686 int year, month, day, weekday, hour, min, sec, ms; 687 isolate->date_cache()->BreakDownTime(time_ms, &year, &month, &day, &weekday, 688 &hour, &min, &sec, &ms); 689 char buffer[128]; 690 if (year >= 0 && year <= 9999) { 691 SNPrintF(base::ArrayVector(buffer), "%04d-%02d-%02dT%02d:%02d:%02d.%03dZ", 692 year, month + 1, day, hour, min, sec, ms); 693 } else if (year < 0) { 694 SNPrintF(base::ArrayVector(buffer), "-%06d-%02d-%02dT%02d:%02d:%02d.%03dZ", 695 -year, month + 1, day, hour, min, sec, ms); 696 } else { 697 SNPrintF(base::ArrayVector(buffer), "+%06d-%02d-%02dT%02d:%02d:%02d.%03dZ", 698 year, month + 1, day, hour, min, sec, ms); 699 } 700 return *isolate->factory()->NewStringFromAsciiChecked(buffer); 701} 702 703// ES6 section 20.3.4.41 Date.prototype.toString ( ) 704BUILTIN(DatePrototypeToString) { 705 HandleScope scope(isolate); 706 CHECK_RECEIVER(JSDate, date, "Date.prototype.toString"); 707 DateBuffer buffer = 708 ToDateString(date->value().Number(), isolate->date_cache(), 709 ToDateStringMode::kLocalDateAndTime); 710 RETURN_RESULT_OR_FAILURE( 711 isolate, isolate->factory()->NewStringFromUtf8(base::VectorOf(buffer))); 712} 713 714// ES6 section 20.3.4.42 Date.prototype.toTimeString ( ) 715BUILTIN(DatePrototypeToTimeString) { 716 HandleScope scope(isolate); 717 CHECK_RECEIVER(JSDate, date, "Date.prototype.toTimeString"); 718 DateBuffer buffer = 719 ToDateString(date->value().Number(), isolate->date_cache(), 720 ToDateStringMode::kLocalTime); 721 RETURN_RESULT_OR_FAILURE( 722 isolate, isolate->factory()->NewStringFromUtf8(base::VectorOf(buffer))); 723} 724 725#ifdef V8_INTL_SUPPORT 726// ecma402 #sup-date.prototype.tolocaledatestring 727BUILTIN(DatePrototypeToLocaleDateString) { 728 HandleScope scope(isolate); 729 730 isolate->CountUsage(v8::Isolate::UseCounterFeature::kDateToLocaleDateString); 731 732 const char* method_name = "Date.prototype.toLocaleDateString"; 733 CHECK_RECEIVER(JSDate, date, method_name); 734 735 RETURN_RESULT_OR_FAILURE( 736 isolate, JSDateTimeFormat::ToLocaleDateTime( 737 isolate, 738 date, // date 739 args.atOrUndefined(isolate, 1), // locales 740 args.atOrUndefined(isolate, 2), // options 741 JSDateTimeFormat::RequiredOption::kDate, // required 742 JSDateTimeFormat::DefaultsOption::kDate, // defaults 743 method_name)); // method_name 744} 745 746// ecma402 #sup-date.prototype.tolocalestring 747BUILTIN(DatePrototypeToLocaleString) { 748 HandleScope scope(isolate); 749 750 isolate->CountUsage(v8::Isolate::UseCounterFeature::kDateToLocaleString); 751 752 const char* method_name = "Date.prototype.toLocaleString"; 753 CHECK_RECEIVER(JSDate, date, method_name); 754 755 RETURN_RESULT_OR_FAILURE( 756 isolate, JSDateTimeFormat::ToLocaleDateTime( 757 isolate, 758 date, // date 759 args.atOrUndefined(isolate, 1), // locales 760 args.atOrUndefined(isolate, 2), // options 761 JSDateTimeFormat::RequiredOption::kAny, // required 762 JSDateTimeFormat::DefaultsOption::kAll, // defaults 763 method_name)); // method_name 764} 765 766// ecma402 #sup-date.prototype.tolocaletimestring 767BUILTIN(DatePrototypeToLocaleTimeString) { 768 HandleScope scope(isolate); 769 770 isolate->CountUsage(v8::Isolate::UseCounterFeature::kDateToLocaleTimeString); 771 772 const char* method_name = "Date.prototype.toLocaleTimeString"; 773 CHECK_RECEIVER(JSDate, date, method_name); 774 775 RETURN_RESULT_OR_FAILURE( 776 isolate, JSDateTimeFormat::ToLocaleDateTime( 777 isolate, 778 date, // date 779 args.atOrUndefined(isolate, 1), // locales 780 args.atOrUndefined(isolate, 2), // options 781 JSDateTimeFormat::RequiredOption::kTime, // required 782 JSDateTimeFormat::DefaultsOption::kTime, // defaults 783 method_name)); // method_name 784} 785#endif // V8_INTL_SUPPORT 786 787// ES6 section 20.3.4.43 Date.prototype.toUTCString ( ) 788BUILTIN(DatePrototypeToUTCString) { 789 HandleScope scope(isolate); 790 CHECK_RECEIVER(JSDate, date, "Date.prototype.toUTCString"); 791 DateBuffer buffer = 792 ToDateString(date->value().Number(), isolate->date_cache(), 793 ToDateStringMode::kUTCDateAndTime); 794 RETURN_RESULT_OR_FAILURE( 795 isolate, isolate->factory()->NewStringFromUtf8(base::VectorOf(buffer))); 796} 797 798// ES6 section B.2.4.1 Date.prototype.getYear ( ) 799BUILTIN(DatePrototypeGetYear) { 800 HandleScope scope(isolate); 801 CHECK_RECEIVER(JSDate, date, "Date.prototype.getYear"); 802 double time_val = date->value().Number(); 803 if (std::isnan(time_val)) return date->value(); 804 int64_t time_ms = static_cast<int64_t>(time_val); 805 int64_t local_time_ms = isolate->date_cache()->ToLocal(time_ms); 806 int days = isolate->date_cache()->DaysFromTime(local_time_ms); 807 int year, month, day; 808 isolate->date_cache()->YearMonthDayFromDays(days, &year, &month, &day); 809 return Smi::FromInt(year - 1900); 810} 811 812// ES6 section B.2.4.2 Date.prototype.setYear ( year ) 813BUILTIN(DatePrototypeSetYear) { 814 HandleScope scope(isolate); 815 CHECK_RECEIVER(JSDate, date, "Date.prototype.setYear"); 816 Handle<Object> year = args.atOrUndefined(isolate, 1); 817 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, year, 818 Object::ToNumber(isolate, year)); 819 double month_double = 0.0, day_double = 1.0, year_double = year->Number(); 820 if (!std::isnan(year_double)) { 821 double year_int = DoubleToInteger(year_double); 822 if (0.0 <= year_int && year_int <= 99.0) { 823 year_double = 1900.0 + year_int; 824 } 825 } 826 int time_within_day = 0; 827 if (!std::isnan(date->value().Number())) { 828 int64_t const time_ms = static_cast<int64_t>(date->value().Number()); 829 int64_t local_time_ms = isolate->date_cache()->ToLocal(time_ms); 830 int const days = isolate->date_cache()->DaysFromTime(local_time_ms); 831 time_within_day = isolate->date_cache()->TimeInDay(local_time_ms, days); 832 int year_int, month_int, day_int; 833 isolate->date_cache()->YearMonthDayFromDays(days, &year_int, &month_int, 834 &day_int); 835 month_double = month_int; 836 day_double = day_int; 837 } 838 double time_val = 839 MakeDate(MakeDay(year_double, month_double, day_double), time_within_day); 840 return SetLocalDateValue(isolate, date, time_val); 841} 842 843// ES6 section 20.3.4.37 Date.prototype.toJSON ( key ) 844BUILTIN(DatePrototypeToJson) { 845 HandleScope scope(isolate); 846 Handle<Object> receiver = args.atOrUndefined(isolate, 0); 847 Handle<JSReceiver> receiver_obj; 848 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, receiver_obj, 849 Object::ToObject(isolate, receiver)); 850 Handle<Object> primitive; 851 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( 852 isolate, primitive, 853 Object::ToPrimitive(isolate, receiver_obj, ToPrimitiveHint::kNumber)); 854 if (primitive->IsNumber() && !std::isfinite(primitive->Number())) { 855 return ReadOnlyRoots(isolate).null_value(); 856 } else { 857 Handle<String> name = 858 isolate->factory()->NewStringFromAsciiChecked("toISOString"); 859 Handle<Object> function; 860 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( 861 isolate, function, Object::GetProperty(isolate, receiver_obj, name)); 862 if (!function->IsCallable()) { 863 THROW_NEW_ERROR_RETURN_FAILURE( 864 isolate, NewTypeError(MessageTemplate::kCalledNonCallable, name)); 865 } 866 RETURN_RESULT_OR_FAILURE( 867 isolate, Execution::Call(isolate, function, receiver_obj, 0, nullptr)); 868 } 869} 870 871} // namespace internal 872} // namespace v8 873