OLD | NEW |
(Empty) | |
| 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.h" |
| 6 #include "src/builtins/builtins-utils.h" |
| 7 |
| 8 #include "src/dateparser-inl.h" |
| 9 |
| 10 namespace v8 { |
| 11 namespace internal { |
| 12 |
| 13 // ----------------------------------------------------------------------------- |
| 14 // ES6 section 20.3 Date Objects |
| 15 |
| 16 namespace { |
| 17 |
| 18 // ES6 section 20.3.1.1 Time Values and Time Range |
| 19 const double kMinYear = -1000000.0; |
| 20 const double kMaxYear = -kMinYear; |
| 21 const double kMinMonth = -10000000.0; |
| 22 const double kMaxMonth = -kMinMonth; |
| 23 |
| 24 // 20.3.1.2 Day Number and Time within Day |
| 25 const double kMsPerDay = 86400000.0; |
| 26 |
| 27 // ES6 section 20.3.1.11 Hours, Minutes, Second, and Milliseconds |
| 28 const double kMsPerSecond = 1000.0; |
| 29 const double kMsPerMinute = 60000.0; |
| 30 const double kMsPerHour = 3600000.0; |
| 31 |
| 32 // ES6 section 20.3.1.14 MakeDate (day, time) |
| 33 double MakeDate(double day, double time) { |
| 34 if (std::isfinite(day) && std::isfinite(time)) { |
| 35 return time + day * kMsPerDay; |
| 36 } |
| 37 return std::numeric_limits<double>::quiet_NaN(); |
| 38 } |
| 39 |
| 40 // ES6 section 20.3.1.13 MakeDay (year, month, date) |
| 41 double MakeDay(double year, double month, double date) { |
| 42 if ((kMinYear <= year && year <= kMaxYear) && |
| 43 (kMinMonth <= month && month <= kMaxMonth) && std::isfinite(date)) { |
| 44 int y = FastD2I(year); |
| 45 int m = FastD2I(month); |
| 46 y += m / 12; |
| 47 m %= 12; |
| 48 if (m < 0) { |
| 49 m += 12; |
| 50 y -= 1; |
| 51 } |
| 52 DCHECK_LE(0, m); |
| 53 DCHECK_LT(m, 12); |
| 54 |
| 55 // kYearDelta is an arbitrary number such that: |
| 56 // a) kYearDelta = -1 (mod 400) |
| 57 // b) year + kYearDelta > 0 for years in the range defined by |
| 58 // ECMA 262 - 15.9.1.1, i.e. upto 100,000,000 days on either side of |
| 59 // Jan 1 1970. This is required so that we don't run into integer |
| 60 // division of negative numbers. |
| 61 // c) there shouldn't be an overflow for 32-bit integers in the following |
| 62 // operations. |
| 63 static const int kYearDelta = 399999; |
| 64 static const int kBaseDay = |
| 65 365 * (1970 + kYearDelta) + (1970 + kYearDelta) / 4 - |
| 66 (1970 + kYearDelta) / 100 + (1970 + kYearDelta) / 400; |
| 67 int day_from_year = 365 * (y + kYearDelta) + (y + kYearDelta) / 4 - |
| 68 (y + kYearDelta) / 100 + (y + kYearDelta) / 400 - |
| 69 kBaseDay; |
| 70 if ((y % 4 != 0) || (y % 100 == 0 && y % 400 != 0)) { |
| 71 static const int kDayFromMonth[] = {0, 31, 59, 90, 120, 151, |
| 72 181, 212, 243, 273, 304, 334}; |
| 73 day_from_year += kDayFromMonth[m]; |
| 74 } else { |
| 75 static const int kDayFromMonth[] = {0, 31, 60, 91, 121, 152, |
| 76 182, 213, 244, 274, 305, 335}; |
| 77 day_from_year += kDayFromMonth[m]; |
| 78 } |
| 79 return static_cast<double>(day_from_year - 1) + date; |
| 80 } |
| 81 return std::numeric_limits<double>::quiet_NaN(); |
| 82 } |
| 83 |
| 84 // ES6 section 20.3.1.12 MakeTime (hour, min, sec, ms) |
| 85 double MakeTime(double hour, double min, double sec, double ms) { |
| 86 if (std::isfinite(hour) && std::isfinite(min) && std::isfinite(sec) && |
| 87 std::isfinite(ms)) { |
| 88 double const h = DoubleToInteger(hour); |
| 89 double const m = DoubleToInteger(min); |
| 90 double const s = DoubleToInteger(sec); |
| 91 double const milli = DoubleToInteger(ms); |
| 92 return h * kMsPerHour + m * kMsPerMinute + s * kMsPerSecond + milli; |
| 93 } |
| 94 return std::numeric_limits<double>::quiet_NaN(); |
| 95 } |
| 96 |
| 97 // ES6 section 20.3.1.15 TimeClip (time) |
| 98 double TimeClip(double time) { |
| 99 if (-DateCache::kMaxTimeInMs <= time && time <= DateCache::kMaxTimeInMs) { |
| 100 return DoubleToInteger(time) + 0.0; |
| 101 } |
| 102 return std::numeric_limits<double>::quiet_NaN(); |
| 103 } |
| 104 |
| 105 const char* kShortWeekDays[] = {"Sun", "Mon", "Tue", "Wed", |
| 106 "Thu", "Fri", "Sat"}; |
| 107 const char* kShortMonths[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", |
| 108 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; |
| 109 |
| 110 // ES6 section 20.3.1.16 Date Time String Format |
| 111 double ParseDateTimeString(Handle<String> str) { |
| 112 Isolate* const isolate = str->GetIsolate(); |
| 113 str = String::Flatten(str); |
| 114 // TODO(bmeurer): Change DateParser to not use the FixedArray. |
| 115 Handle<FixedArray> tmp = |
| 116 isolate->factory()->NewFixedArray(DateParser::OUTPUT_SIZE); |
| 117 DisallowHeapAllocation no_gc; |
| 118 String::FlatContent str_content = str->GetFlatContent(); |
| 119 bool result; |
| 120 if (str_content.IsOneByte()) { |
| 121 result = DateParser::Parse(isolate, str_content.ToOneByteVector(), *tmp); |
| 122 } else { |
| 123 result = DateParser::Parse(isolate, str_content.ToUC16Vector(), *tmp); |
| 124 } |
| 125 if (!result) return std::numeric_limits<double>::quiet_NaN(); |
| 126 double const day = MakeDay(tmp->get(0)->Number(), tmp->get(1)->Number(), |
| 127 tmp->get(2)->Number()); |
| 128 double const time = MakeTime(tmp->get(3)->Number(), tmp->get(4)->Number(), |
| 129 tmp->get(5)->Number(), tmp->get(6)->Number()); |
| 130 double date = MakeDate(day, time); |
| 131 if (tmp->get(7)->IsNull(isolate)) { |
| 132 if (!std::isnan(date)) { |
| 133 date = isolate->date_cache()->ToUTC(static_cast<int64_t>(date)); |
| 134 } |
| 135 } else { |
| 136 date -= tmp->get(7)->Number() * 1000.0; |
| 137 } |
| 138 return date; |
| 139 } |
| 140 |
| 141 enum ToDateStringMode { kDateOnly, kTimeOnly, kDateAndTime }; |
| 142 |
| 143 // ES6 section 20.3.4.41.1 ToDateString(tv) |
| 144 void ToDateString(double time_val, Vector<char> str, DateCache* date_cache, |
| 145 ToDateStringMode mode = kDateAndTime) { |
| 146 if (std::isnan(time_val)) { |
| 147 SNPrintF(str, "Invalid Date"); |
| 148 return; |
| 149 } |
| 150 int64_t time_ms = static_cast<int64_t>(time_val); |
| 151 int64_t local_time_ms = date_cache->ToLocal(time_ms); |
| 152 int year, month, day, weekday, hour, min, sec, ms; |
| 153 date_cache->BreakDownTime(local_time_ms, &year, &month, &day, &weekday, &hour, |
| 154 &min, &sec, &ms); |
| 155 int timezone_offset = -date_cache->TimezoneOffset(time_ms); |
| 156 int timezone_hour = std::abs(timezone_offset) / 60; |
| 157 int timezone_min = std::abs(timezone_offset) % 60; |
| 158 const char* local_timezone = date_cache->LocalTimezone(time_ms); |
| 159 switch (mode) { |
| 160 case kDateOnly: |
| 161 SNPrintF(str, "%s %s %02d %4d", kShortWeekDays[weekday], |
| 162 kShortMonths[month], day, year); |
| 163 return; |
| 164 case kTimeOnly: |
| 165 SNPrintF(str, "%02d:%02d:%02d GMT%c%02d%02d (%s)", hour, min, sec, |
| 166 (timezone_offset < 0) ? '-' : '+', timezone_hour, timezone_min, |
| 167 local_timezone); |
| 168 return; |
| 169 case kDateAndTime: |
| 170 SNPrintF(str, "%s %s %02d %4d %02d:%02d:%02d GMT%c%02d%02d (%s)", |
| 171 kShortWeekDays[weekday], kShortMonths[month], day, year, hour, |
| 172 min, sec, (timezone_offset < 0) ? '-' : '+', timezone_hour, |
| 173 timezone_min, local_timezone); |
| 174 return; |
| 175 } |
| 176 UNREACHABLE(); |
| 177 } |
| 178 |
| 179 Object* SetLocalDateValue(Handle<JSDate> date, double time_val) { |
| 180 if (time_val >= -DateCache::kMaxTimeBeforeUTCInMs && |
| 181 time_val <= DateCache::kMaxTimeBeforeUTCInMs) { |
| 182 Isolate* const isolate = date->GetIsolate(); |
| 183 time_val = isolate->date_cache()->ToUTC(static_cast<int64_t>(time_val)); |
| 184 } else { |
| 185 time_val = std::numeric_limits<double>::quiet_NaN(); |
| 186 } |
| 187 return *JSDate::SetValue(date, TimeClip(time_val)); |
| 188 } |
| 189 |
| 190 } // namespace |
| 191 |
| 192 // ES6 section 20.3.2 The Date Constructor for the [[Call]] case. |
| 193 BUILTIN(DateConstructor) { |
| 194 HandleScope scope(isolate); |
| 195 double const time_val = JSDate::CurrentTimeValue(isolate); |
| 196 char buffer[128]; |
| 197 ToDateString(time_val, ArrayVector(buffer), isolate->date_cache()); |
| 198 RETURN_RESULT_OR_FAILURE( |
| 199 isolate, isolate->factory()->NewStringFromUtf8(CStrVector(buffer))); |
| 200 } |
| 201 |
| 202 // ES6 section 20.3.2 The Date Constructor for the [[Construct]] case. |
| 203 BUILTIN(DateConstructor_ConstructStub) { |
| 204 HandleScope scope(isolate); |
| 205 int const argc = args.length() - 1; |
| 206 Handle<JSFunction> target = args.target<JSFunction>(); |
| 207 Handle<JSReceiver> new_target = Handle<JSReceiver>::cast(args.new_target()); |
| 208 double time_val; |
| 209 if (argc == 0) { |
| 210 time_val = JSDate::CurrentTimeValue(isolate); |
| 211 } else if (argc == 1) { |
| 212 Handle<Object> value = args.at<Object>(1); |
| 213 if (value->IsJSDate()) { |
| 214 time_val = Handle<JSDate>::cast(value)->value()->Number(); |
| 215 } else { |
| 216 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, value, |
| 217 Object::ToPrimitive(value)); |
| 218 if (value->IsString()) { |
| 219 time_val = ParseDateTimeString(Handle<String>::cast(value)); |
| 220 } else { |
| 221 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, value, |
| 222 Object::ToNumber(value)); |
| 223 time_val = value->Number(); |
| 224 } |
| 225 } |
| 226 } else { |
| 227 Handle<Object> year_object; |
| 228 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, year_object, |
| 229 Object::ToNumber(args.at<Object>(1))); |
| 230 Handle<Object> month_object; |
| 231 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, month_object, |
| 232 Object::ToNumber(args.at<Object>(2))); |
| 233 double year = year_object->Number(); |
| 234 double month = month_object->Number(); |
| 235 double date = 1.0, hours = 0.0, minutes = 0.0, seconds = 0.0, ms = 0.0; |
| 236 if (argc >= 3) { |
| 237 Handle<Object> date_object; |
| 238 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, date_object, |
| 239 Object::ToNumber(args.at<Object>(3))); |
| 240 date = date_object->Number(); |
| 241 if (argc >= 4) { |
| 242 Handle<Object> hours_object; |
| 243 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( |
| 244 isolate, hours_object, Object::ToNumber(args.at<Object>(4))); |
| 245 hours = hours_object->Number(); |
| 246 if (argc >= 5) { |
| 247 Handle<Object> minutes_object; |
| 248 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( |
| 249 isolate, minutes_object, Object::ToNumber(args.at<Object>(5))); |
| 250 minutes = minutes_object->Number(); |
| 251 if (argc >= 6) { |
| 252 Handle<Object> seconds_object; |
| 253 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( |
| 254 isolate, seconds_object, Object::ToNumber(args.at<Object>(6))); |
| 255 seconds = seconds_object->Number(); |
| 256 if (argc >= 7) { |
| 257 Handle<Object> ms_object; |
| 258 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( |
| 259 isolate, ms_object, Object::ToNumber(args.at<Object>(7))); |
| 260 ms = ms_object->Number(); |
| 261 } |
| 262 } |
| 263 } |
| 264 } |
| 265 } |
| 266 if (!std::isnan(year)) { |
| 267 double const y = DoubleToInteger(year); |
| 268 if (0.0 <= y && y <= 99) year = 1900 + y; |
| 269 } |
| 270 double const day = MakeDay(year, month, date); |
| 271 double const time = MakeTime(hours, minutes, seconds, ms); |
| 272 time_val = MakeDate(day, time); |
| 273 if (time_val >= -DateCache::kMaxTimeBeforeUTCInMs && |
| 274 time_val <= DateCache::kMaxTimeBeforeUTCInMs) { |
| 275 time_val = isolate->date_cache()->ToUTC(static_cast<int64_t>(time_val)); |
| 276 } else { |
| 277 time_val = std::numeric_limits<double>::quiet_NaN(); |
| 278 } |
| 279 } |
| 280 RETURN_RESULT_OR_FAILURE(isolate, JSDate::New(target, new_target, time_val)); |
| 281 } |
| 282 |
| 283 // ES6 section 20.3.3.1 Date.now ( ) |
| 284 BUILTIN(DateNow) { |
| 285 HandleScope scope(isolate); |
| 286 return *isolate->factory()->NewNumber(JSDate::CurrentTimeValue(isolate)); |
| 287 } |
| 288 |
| 289 // ES6 section 20.3.3.2 Date.parse ( string ) |
| 290 BUILTIN(DateParse) { |
| 291 HandleScope scope(isolate); |
| 292 Handle<String> string; |
| 293 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( |
| 294 isolate, string, |
| 295 Object::ToString(isolate, args.atOrUndefined(isolate, 1))); |
| 296 return *isolate->factory()->NewNumber(ParseDateTimeString(string)); |
| 297 } |
| 298 |
| 299 // ES6 section 20.3.3.4 Date.UTC (year,month,date,hours,minutes,seconds,ms) |
| 300 BUILTIN(DateUTC) { |
| 301 HandleScope scope(isolate); |
| 302 int const argc = args.length() - 1; |
| 303 double year = std::numeric_limits<double>::quiet_NaN(); |
| 304 double month = std::numeric_limits<double>::quiet_NaN(); |
| 305 double date = 1.0, hours = 0.0, minutes = 0.0, seconds = 0.0, ms = 0.0; |
| 306 if (argc >= 1) { |
| 307 Handle<Object> year_object; |
| 308 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, year_object, |
| 309 Object::ToNumber(args.at<Object>(1))); |
| 310 year = year_object->Number(); |
| 311 if (argc >= 2) { |
| 312 Handle<Object> month_object; |
| 313 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, month_object, |
| 314 Object::ToNumber(args.at<Object>(2))); |
| 315 month = month_object->Number(); |
| 316 if (argc >= 3) { |
| 317 Handle<Object> date_object; |
| 318 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( |
| 319 isolate, date_object, Object::ToNumber(args.at<Object>(3))); |
| 320 date = date_object->Number(); |
| 321 if (argc >= 4) { |
| 322 Handle<Object> hours_object; |
| 323 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( |
| 324 isolate, hours_object, Object::ToNumber(args.at<Object>(4))); |
| 325 hours = hours_object->Number(); |
| 326 if (argc >= 5) { |
| 327 Handle<Object> minutes_object; |
| 328 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( |
| 329 isolate, minutes_object, Object::ToNumber(args.at<Object>(5))); |
| 330 minutes = minutes_object->Number(); |
| 331 if (argc >= 6) { |
| 332 Handle<Object> seconds_object; |
| 333 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( |
| 334 isolate, seconds_object, |
| 335 Object::ToNumber(args.at<Object>(6))); |
| 336 seconds = seconds_object->Number(); |
| 337 if (argc >= 7) { |
| 338 Handle<Object> ms_object; |
| 339 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( |
| 340 isolate, ms_object, Object::ToNumber(args.at<Object>(7))); |
| 341 ms = ms_object->Number(); |
| 342 } |
| 343 } |
| 344 } |
| 345 } |
| 346 } |
| 347 } |
| 348 } |
| 349 if (!std::isnan(year)) { |
| 350 double const y = DoubleToInteger(year); |
| 351 if (0.0 <= y && y <= 99) year = 1900 + y; |
| 352 } |
| 353 double const day = MakeDay(year, month, date); |
| 354 double const time = MakeTime(hours, minutes, seconds, ms); |
| 355 return *isolate->factory()->NewNumber(TimeClip(MakeDate(day, time))); |
| 356 } |
| 357 |
| 358 // ES6 section 20.3.4.20 Date.prototype.setDate ( date ) |
| 359 BUILTIN(DatePrototypeSetDate) { |
| 360 HandleScope scope(isolate); |
| 361 CHECK_RECEIVER(JSDate, date, "Date.prototype.setDate"); |
| 362 Handle<Object> value = args.atOrUndefined(isolate, 1); |
| 363 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, value, Object::ToNumber(value)); |
| 364 double time_val = date->value()->Number(); |
| 365 if (!std::isnan(time_val)) { |
| 366 int64_t const time_ms = static_cast<int64_t>(time_val); |
| 367 int64_t local_time_ms = isolate->date_cache()->ToLocal(time_ms); |
| 368 int const days = isolate->date_cache()->DaysFromTime(local_time_ms); |
| 369 int time_within_day = isolate->date_cache()->TimeInDay(local_time_ms, days); |
| 370 int year, month, day; |
| 371 isolate->date_cache()->YearMonthDayFromDays(days, &year, &month, &day); |
| 372 time_val = MakeDate(MakeDay(year, month, value->Number()), time_within_day); |
| 373 } |
| 374 return SetLocalDateValue(date, time_val); |
| 375 } |
| 376 |
| 377 // ES6 section 20.3.4.21 Date.prototype.setFullYear (year, month, date) |
| 378 BUILTIN(DatePrototypeSetFullYear) { |
| 379 HandleScope scope(isolate); |
| 380 CHECK_RECEIVER(JSDate, date, "Date.prototype.setFullYear"); |
| 381 int const argc = args.length() - 1; |
| 382 Handle<Object> year = args.atOrUndefined(isolate, 1); |
| 383 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, year, Object::ToNumber(year)); |
| 384 double y = year->Number(), m = 0.0, dt = 1.0; |
| 385 int time_within_day = 0; |
| 386 if (!std::isnan(date->value()->Number())) { |
| 387 int64_t const time_ms = static_cast<int64_t>(date->value()->Number()); |
| 388 int64_t local_time_ms = isolate->date_cache()->ToLocal(time_ms); |
| 389 int const days = isolate->date_cache()->DaysFromTime(local_time_ms); |
| 390 time_within_day = isolate->date_cache()->TimeInDay(local_time_ms, days); |
| 391 int year, month, day; |
| 392 isolate->date_cache()->YearMonthDayFromDays(days, &year, &month, &day); |
| 393 m = month; |
| 394 dt = day; |
| 395 } |
| 396 if (argc >= 2) { |
| 397 Handle<Object> month = args.at<Object>(2); |
| 398 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, month, Object::ToNumber(month)); |
| 399 m = month->Number(); |
| 400 if (argc >= 3) { |
| 401 Handle<Object> date = args.at<Object>(3); |
| 402 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, date, Object::ToNumber(date)); |
| 403 dt = date->Number(); |
| 404 } |
| 405 } |
| 406 double time_val = MakeDate(MakeDay(y, m, dt), time_within_day); |
| 407 return SetLocalDateValue(date, time_val); |
| 408 } |
| 409 |
| 410 // ES6 section 20.3.4.22 Date.prototype.setHours(hour, min, sec, ms) |
| 411 BUILTIN(DatePrototypeSetHours) { |
| 412 HandleScope scope(isolate); |
| 413 CHECK_RECEIVER(JSDate, date, "Date.prototype.setHours"); |
| 414 int const argc = args.length() - 1; |
| 415 Handle<Object> hour = args.atOrUndefined(isolate, 1); |
| 416 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, hour, Object::ToNumber(hour)); |
| 417 double h = hour->Number(); |
| 418 double time_val = date->value()->Number(); |
| 419 if (!std::isnan(time_val)) { |
| 420 int64_t const time_ms = static_cast<int64_t>(time_val); |
| 421 int64_t local_time_ms = isolate->date_cache()->ToLocal(time_ms); |
| 422 int day = isolate->date_cache()->DaysFromTime(local_time_ms); |
| 423 int time_within_day = isolate->date_cache()->TimeInDay(local_time_ms, day); |
| 424 double m = (time_within_day / (60 * 1000)) % 60; |
| 425 double s = (time_within_day / 1000) % 60; |
| 426 double milli = time_within_day % 1000; |
| 427 if (argc >= 2) { |
| 428 Handle<Object> min = args.at<Object>(2); |
| 429 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, min, Object::ToNumber(min)); |
| 430 m = min->Number(); |
| 431 if (argc >= 3) { |
| 432 Handle<Object> sec = args.at<Object>(3); |
| 433 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, sec, Object::ToNumber(sec)); |
| 434 s = sec->Number(); |
| 435 if (argc >= 4) { |
| 436 Handle<Object> ms = args.at<Object>(4); |
| 437 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, ms, Object::ToNumber(ms)); |
| 438 milli = ms->Number(); |
| 439 } |
| 440 } |
| 441 } |
| 442 time_val = MakeDate(day, MakeTime(h, m, s, milli)); |
| 443 } |
| 444 return SetLocalDateValue(date, time_val); |
| 445 } |
| 446 |
| 447 // ES6 section 20.3.4.23 Date.prototype.setMilliseconds(ms) |
| 448 BUILTIN(DatePrototypeSetMilliseconds) { |
| 449 HandleScope scope(isolate); |
| 450 CHECK_RECEIVER(JSDate, date, "Date.prototype.setMilliseconds"); |
| 451 Handle<Object> ms = args.atOrUndefined(isolate, 1); |
| 452 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, ms, Object::ToNumber(ms)); |
| 453 double time_val = date->value()->Number(); |
| 454 if (!std::isnan(time_val)) { |
| 455 int64_t const time_ms = static_cast<int64_t>(time_val); |
| 456 int64_t local_time_ms = isolate->date_cache()->ToLocal(time_ms); |
| 457 int day = isolate->date_cache()->DaysFromTime(local_time_ms); |
| 458 int time_within_day = isolate->date_cache()->TimeInDay(local_time_ms, day); |
| 459 int h = time_within_day / (60 * 60 * 1000); |
| 460 int m = (time_within_day / (60 * 1000)) % 60; |
| 461 int s = (time_within_day / 1000) % 60; |
| 462 time_val = MakeDate(day, MakeTime(h, m, s, ms->Number())); |
| 463 } |
| 464 return SetLocalDateValue(date, time_val); |
| 465 } |
| 466 |
| 467 // ES6 section 20.3.4.24 Date.prototype.setMinutes ( min, sec, ms ) |
| 468 BUILTIN(DatePrototypeSetMinutes) { |
| 469 HandleScope scope(isolate); |
| 470 CHECK_RECEIVER(JSDate, date, "Date.prototype.setMinutes"); |
| 471 int const argc = args.length() - 1; |
| 472 Handle<Object> min = args.atOrUndefined(isolate, 1); |
| 473 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, min, Object::ToNumber(min)); |
| 474 double time_val = date->value()->Number(); |
| 475 if (!std::isnan(time_val)) { |
| 476 int64_t const time_ms = static_cast<int64_t>(time_val); |
| 477 int64_t local_time_ms = isolate->date_cache()->ToLocal(time_ms); |
| 478 int day = isolate->date_cache()->DaysFromTime(local_time_ms); |
| 479 int time_within_day = isolate->date_cache()->TimeInDay(local_time_ms, day); |
| 480 int h = time_within_day / (60 * 60 * 1000); |
| 481 double m = min->Number(); |
| 482 double s = (time_within_day / 1000) % 60; |
| 483 double milli = time_within_day % 1000; |
| 484 if (argc >= 2) { |
| 485 Handle<Object> sec = args.at<Object>(2); |
| 486 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, sec, Object::ToNumber(sec)); |
| 487 s = sec->Number(); |
| 488 if (argc >= 3) { |
| 489 Handle<Object> ms = args.at<Object>(3); |
| 490 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, ms, Object::ToNumber(ms)); |
| 491 milli = ms->Number(); |
| 492 } |
| 493 } |
| 494 time_val = MakeDate(day, MakeTime(h, m, s, milli)); |
| 495 } |
| 496 return SetLocalDateValue(date, time_val); |
| 497 } |
| 498 |
| 499 // ES6 section 20.3.4.25 Date.prototype.setMonth ( month, date ) |
| 500 BUILTIN(DatePrototypeSetMonth) { |
| 501 HandleScope scope(isolate); |
| 502 CHECK_RECEIVER(JSDate, date, "Date.prototype.setMonth"); |
| 503 int const argc = args.length() - 1; |
| 504 Handle<Object> month = args.atOrUndefined(isolate, 1); |
| 505 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, month, Object::ToNumber(month)); |
| 506 double time_val = date->value()->Number(); |
| 507 if (!std::isnan(time_val)) { |
| 508 int64_t const time_ms = static_cast<int64_t>(time_val); |
| 509 int64_t local_time_ms = isolate->date_cache()->ToLocal(time_ms); |
| 510 int days = isolate->date_cache()->DaysFromTime(local_time_ms); |
| 511 int time_within_day = isolate->date_cache()->TimeInDay(local_time_ms, days); |
| 512 int year, unused, day; |
| 513 isolate->date_cache()->YearMonthDayFromDays(days, &year, &unused, &day); |
| 514 double m = month->Number(); |
| 515 double dt = day; |
| 516 if (argc >= 2) { |
| 517 Handle<Object> date = args.at<Object>(2); |
| 518 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, date, Object::ToNumber(date)); |
| 519 dt = date->Number(); |
| 520 } |
| 521 time_val = MakeDate(MakeDay(year, m, dt), time_within_day); |
| 522 } |
| 523 return SetLocalDateValue(date, time_val); |
| 524 } |
| 525 |
| 526 // ES6 section 20.3.4.26 Date.prototype.setSeconds ( sec, ms ) |
| 527 BUILTIN(DatePrototypeSetSeconds) { |
| 528 HandleScope scope(isolate); |
| 529 CHECK_RECEIVER(JSDate, date, "Date.prototype.setSeconds"); |
| 530 int const argc = args.length() - 1; |
| 531 Handle<Object> sec = args.atOrUndefined(isolate, 1); |
| 532 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, sec, Object::ToNumber(sec)); |
| 533 double time_val = date->value()->Number(); |
| 534 if (!std::isnan(time_val)) { |
| 535 int64_t const time_ms = static_cast<int64_t>(time_val); |
| 536 int64_t local_time_ms = isolate->date_cache()->ToLocal(time_ms); |
| 537 int day = isolate->date_cache()->DaysFromTime(local_time_ms); |
| 538 int time_within_day = isolate->date_cache()->TimeInDay(local_time_ms, day); |
| 539 int h = time_within_day / (60 * 60 * 1000); |
| 540 double m = (time_within_day / (60 * 1000)) % 60; |
| 541 double s = sec->Number(); |
| 542 double milli = time_within_day % 1000; |
| 543 if (argc >= 2) { |
| 544 Handle<Object> ms = args.at<Object>(2); |
| 545 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, ms, Object::ToNumber(ms)); |
| 546 milli = ms->Number(); |
| 547 } |
| 548 time_val = MakeDate(day, MakeTime(h, m, s, milli)); |
| 549 } |
| 550 return SetLocalDateValue(date, time_val); |
| 551 } |
| 552 |
| 553 // ES6 section 20.3.4.27 Date.prototype.setTime ( time ) |
| 554 BUILTIN(DatePrototypeSetTime) { |
| 555 HandleScope scope(isolate); |
| 556 CHECK_RECEIVER(JSDate, date, "Date.prototype.setTime"); |
| 557 Handle<Object> value = args.atOrUndefined(isolate, 1); |
| 558 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, value, Object::ToNumber(value)); |
| 559 return *JSDate::SetValue(date, TimeClip(value->Number())); |
| 560 } |
| 561 |
| 562 // ES6 section 20.3.4.28 Date.prototype.setUTCDate ( date ) |
| 563 BUILTIN(DatePrototypeSetUTCDate) { |
| 564 HandleScope scope(isolate); |
| 565 CHECK_RECEIVER(JSDate, date, "Date.prototype.setUTCDate"); |
| 566 Handle<Object> value = args.atOrUndefined(isolate, 1); |
| 567 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, value, Object::ToNumber(value)); |
| 568 if (std::isnan(date->value()->Number())) return date->value(); |
| 569 int64_t const time_ms = static_cast<int64_t>(date->value()->Number()); |
| 570 int const days = isolate->date_cache()->DaysFromTime(time_ms); |
| 571 int const time_within_day = isolate->date_cache()->TimeInDay(time_ms, days); |
| 572 int year, month, day; |
| 573 isolate->date_cache()->YearMonthDayFromDays(days, &year, &month, &day); |
| 574 double const time_val = |
| 575 MakeDate(MakeDay(year, month, value->Number()), time_within_day); |
| 576 return *JSDate::SetValue(date, TimeClip(time_val)); |
| 577 } |
| 578 |
| 579 // ES6 section 20.3.4.29 Date.prototype.setUTCFullYear (year, month, date) |
| 580 BUILTIN(DatePrototypeSetUTCFullYear) { |
| 581 HandleScope scope(isolate); |
| 582 CHECK_RECEIVER(JSDate, date, "Date.prototype.setUTCFullYear"); |
| 583 int const argc = args.length() - 1; |
| 584 Handle<Object> year = args.atOrUndefined(isolate, 1); |
| 585 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, year, Object::ToNumber(year)); |
| 586 double y = year->Number(), m = 0.0, dt = 1.0; |
| 587 int time_within_day = 0; |
| 588 if (!std::isnan(date->value()->Number())) { |
| 589 int64_t const time_ms = static_cast<int64_t>(date->value()->Number()); |
| 590 int const days = isolate->date_cache()->DaysFromTime(time_ms); |
| 591 time_within_day = isolate->date_cache()->TimeInDay(time_ms, days); |
| 592 int year, month, day; |
| 593 isolate->date_cache()->YearMonthDayFromDays(days, &year, &month, &day); |
| 594 m = month; |
| 595 dt = day; |
| 596 } |
| 597 if (argc >= 2) { |
| 598 Handle<Object> month = args.at<Object>(2); |
| 599 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, month, Object::ToNumber(month)); |
| 600 m = month->Number(); |
| 601 if (argc >= 3) { |
| 602 Handle<Object> date = args.at<Object>(3); |
| 603 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, date, Object::ToNumber(date)); |
| 604 dt = date->Number(); |
| 605 } |
| 606 } |
| 607 double const time_val = MakeDate(MakeDay(y, m, dt), time_within_day); |
| 608 return *JSDate::SetValue(date, TimeClip(time_val)); |
| 609 } |
| 610 |
| 611 // ES6 section 20.3.4.30 Date.prototype.setUTCHours(hour, min, sec, ms) |
| 612 BUILTIN(DatePrototypeSetUTCHours) { |
| 613 HandleScope scope(isolate); |
| 614 CHECK_RECEIVER(JSDate, date, "Date.prototype.setUTCHours"); |
| 615 int const argc = args.length() - 1; |
| 616 Handle<Object> hour = args.atOrUndefined(isolate, 1); |
| 617 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, hour, Object::ToNumber(hour)); |
| 618 double h = hour->Number(); |
| 619 double time_val = date->value()->Number(); |
| 620 if (!std::isnan(time_val)) { |
| 621 int64_t const time_ms = static_cast<int64_t>(time_val); |
| 622 int day = isolate->date_cache()->DaysFromTime(time_ms); |
| 623 int time_within_day = isolate->date_cache()->TimeInDay(time_ms, day); |
| 624 double m = (time_within_day / (60 * 1000)) % 60; |
| 625 double s = (time_within_day / 1000) % 60; |
| 626 double milli = time_within_day % 1000; |
| 627 if (argc >= 2) { |
| 628 Handle<Object> min = args.at<Object>(2); |
| 629 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, min, Object::ToNumber(min)); |
| 630 m = min->Number(); |
| 631 if (argc >= 3) { |
| 632 Handle<Object> sec = args.at<Object>(3); |
| 633 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, sec, Object::ToNumber(sec)); |
| 634 s = sec->Number(); |
| 635 if (argc >= 4) { |
| 636 Handle<Object> ms = args.at<Object>(4); |
| 637 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, ms, Object::ToNumber(ms)); |
| 638 milli = ms->Number(); |
| 639 } |
| 640 } |
| 641 } |
| 642 time_val = MakeDate(day, MakeTime(h, m, s, milli)); |
| 643 } |
| 644 return *JSDate::SetValue(date, TimeClip(time_val)); |
| 645 } |
| 646 |
| 647 // ES6 section 20.3.4.31 Date.prototype.setUTCMilliseconds(ms) |
| 648 BUILTIN(DatePrototypeSetUTCMilliseconds) { |
| 649 HandleScope scope(isolate); |
| 650 CHECK_RECEIVER(JSDate, date, "Date.prototype.setUTCMilliseconds"); |
| 651 Handle<Object> ms = args.atOrUndefined(isolate, 1); |
| 652 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, ms, Object::ToNumber(ms)); |
| 653 double time_val = date->value()->Number(); |
| 654 if (!std::isnan(time_val)) { |
| 655 int64_t const time_ms = static_cast<int64_t>(time_val); |
| 656 int day = isolate->date_cache()->DaysFromTime(time_ms); |
| 657 int time_within_day = isolate->date_cache()->TimeInDay(time_ms, day); |
| 658 int h = time_within_day / (60 * 60 * 1000); |
| 659 int m = (time_within_day / (60 * 1000)) % 60; |
| 660 int s = (time_within_day / 1000) % 60; |
| 661 time_val = MakeDate(day, MakeTime(h, m, s, ms->Number())); |
| 662 } |
| 663 return *JSDate::SetValue(date, TimeClip(time_val)); |
| 664 } |
| 665 |
| 666 // ES6 section 20.3.4.32 Date.prototype.setUTCMinutes ( min, sec, ms ) |
| 667 BUILTIN(DatePrototypeSetUTCMinutes) { |
| 668 HandleScope scope(isolate); |
| 669 CHECK_RECEIVER(JSDate, date, "Date.prototype.setUTCMinutes"); |
| 670 int const argc = args.length() - 1; |
| 671 Handle<Object> min = args.atOrUndefined(isolate, 1); |
| 672 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, min, Object::ToNumber(min)); |
| 673 double time_val = date->value()->Number(); |
| 674 if (!std::isnan(time_val)) { |
| 675 int64_t const time_ms = static_cast<int64_t>(time_val); |
| 676 int day = isolate->date_cache()->DaysFromTime(time_ms); |
| 677 int time_within_day = isolate->date_cache()->TimeInDay(time_ms, day); |
| 678 int h = time_within_day / (60 * 60 * 1000); |
| 679 double m = min->Number(); |
| 680 double s = (time_within_day / 1000) % 60; |
| 681 double milli = time_within_day % 1000; |
| 682 if (argc >= 2) { |
| 683 Handle<Object> sec = args.at<Object>(2); |
| 684 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, sec, Object::ToNumber(sec)); |
| 685 s = sec->Number(); |
| 686 if (argc >= 3) { |
| 687 Handle<Object> ms = args.at<Object>(3); |
| 688 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, ms, Object::ToNumber(ms)); |
| 689 milli = ms->Number(); |
| 690 } |
| 691 } |
| 692 time_val = MakeDate(day, MakeTime(h, m, s, milli)); |
| 693 } |
| 694 return *JSDate::SetValue(date, TimeClip(time_val)); |
| 695 } |
| 696 |
| 697 // ES6 section 20.3.4.31 Date.prototype.setUTCMonth ( month, date ) |
| 698 BUILTIN(DatePrototypeSetUTCMonth) { |
| 699 HandleScope scope(isolate); |
| 700 CHECK_RECEIVER(JSDate, date, "Date.prototype.setUTCMonth"); |
| 701 int const argc = args.length() - 1; |
| 702 Handle<Object> month = args.atOrUndefined(isolate, 1); |
| 703 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, month, Object::ToNumber(month)); |
| 704 double time_val = date->value()->Number(); |
| 705 if (!std::isnan(time_val)) { |
| 706 int64_t const time_ms = static_cast<int64_t>(time_val); |
| 707 int days = isolate->date_cache()->DaysFromTime(time_ms); |
| 708 int time_within_day = isolate->date_cache()->TimeInDay(time_ms, days); |
| 709 int year, unused, day; |
| 710 isolate->date_cache()->YearMonthDayFromDays(days, &year, &unused, &day); |
| 711 double m = month->Number(); |
| 712 double dt = day; |
| 713 if (argc >= 2) { |
| 714 Handle<Object> date = args.at<Object>(2); |
| 715 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, date, Object::ToNumber(date)); |
| 716 dt = date->Number(); |
| 717 } |
| 718 time_val = MakeDate(MakeDay(year, m, dt), time_within_day); |
| 719 } |
| 720 return *JSDate::SetValue(date, TimeClip(time_val)); |
| 721 } |
| 722 |
| 723 // ES6 section 20.3.4.34 Date.prototype.setUTCSeconds ( sec, ms ) |
| 724 BUILTIN(DatePrototypeSetUTCSeconds) { |
| 725 HandleScope scope(isolate); |
| 726 CHECK_RECEIVER(JSDate, date, "Date.prototype.setUTCSeconds"); |
| 727 int const argc = args.length() - 1; |
| 728 Handle<Object> sec = args.atOrUndefined(isolate, 1); |
| 729 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, sec, Object::ToNumber(sec)); |
| 730 double time_val = date->value()->Number(); |
| 731 if (!std::isnan(time_val)) { |
| 732 int64_t const time_ms = static_cast<int64_t>(time_val); |
| 733 int day = isolate->date_cache()->DaysFromTime(time_ms); |
| 734 int time_within_day = isolate->date_cache()->TimeInDay(time_ms, day); |
| 735 int h = time_within_day / (60 * 60 * 1000); |
| 736 double m = (time_within_day / (60 * 1000)) % 60; |
| 737 double s = sec->Number(); |
| 738 double milli = time_within_day % 1000; |
| 739 if (argc >= 2) { |
| 740 Handle<Object> ms = args.at<Object>(2); |
| 741 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, ms, Object::ToNumber(ms)); |
| 742 milli = ms->Number(); |
| 743 } |
| 744 time_val = MakeDate(day, MakeTime(h, m, s, milli)); |
| 745 } |
| 746 return *JSDate::SetValue(date, TimeClip(time_val)); |
| 747 } |
| 748 |
| 749 // ES6 section 20.3.4.35 Date.prototype.toDateString ( ) |
| 750 BUILTIN(DatePrototypeToDateString) { |
| 751 HandleScope scope(isolate); |
| 752 CHECK_RECEIVER(JSDate, date, "Date.prototype.toDateString"); |
| 753 char buffer[128]; |
| 754 ToDateString(date->value()->Number(), ArrayVector(buffer), |
| 755 isolate->date_cache(), kDateOnly); |
| 756 RETURN_RESULT_OR_FAILURE( |
| 757 isolate, isolate->factory()->NewStringFromUtf8(CStrVector(buffer))); |
| 758 } |
| 759 |
| 760 // ES6 section 20.3.4.36 Date.prototype.toISOString ( ) |
| 761 BUILTIN(DatePrototypeToISOString) { |
| 762 HandleScope scope(isolate); |
| 763 CHECK_RECEIVER(JSDate, date, "Date.prototype.toISOString"); |
| 764 double const time_val = date->value()->Number(); |
| 765 if (std::isnan(time_val)) { |
| 766 THROW_NEW_ERROR_RETURN_FAILURE( |
| 767 isolate, NewRangeError(MessageTemplate::kInvalidTimeValue)); |
| 768 } |
| 769 int64_t const time_ms = static_cast<int64_t>(time_val); |
| 770 int year, month, day, weekday, hour, min, sec, ms; |
| 771 isolate->date_cache()->BreakDownTime(time_ms, &year, &month, &day, &weekday, |
| 772 &hour, &min, &sec, &ms); |
| 773 char buffer[128]; |
| 774 if (year >= 0 && year <= 9999) { |
| 775 SNPrintF(ArrayVector(buffer), "%04d-%02d-%02dT%02d:%02d:%02d.%03dZ", year, |
| 776 month + 1, day, hour, min, sec, ms); |
| 777 } else if (year < 0) { |
| 778 SNPrintF(ArrayVector(buffer), "-%06d-%02d-%02dT%02d:%02d:%02d.%03dZ", -year, |
| 779 month + 1, day, hour, min, sec, ms); |
| 780 } else { |
| 781 SNPrintF(ArrayVector(buffer), "+%06d-%02d-%02dT%02d:%02d:%02d.%03dZ", year, |
| 782 month + 1, day, hour, min, sec, ms); |
| 783 } |
| 784 return *isolate->factory()->NewStringFromAsciiChecked(buffer); |
| 785 } |
| 786 |
| 787 // ES6 section 20.3.4.41 Date.prototype.toString ( ) |
| 788 BUILTIN(DatePrototypeToString) { |
| 789 HandleScope scope(isolate); |
| 790 CHECK_RECEIVER(JSDate, date, "Date.prototype.toString"); |
| 791 char buffer[128]; |
| 792 ToDateString(date->value()->Number(), ArrayVector(buffer), |
| 793 isolate->date_cache()); |
| 794 RETURN_RESULT_OR_FAILURE( |
| 795 isolate, isolate->factory()->NewStringFromUtf8(CStrVector(buffer))); |
| 796 } |
| 797 |
| 798 // ES6 section 20.3.4.42 Date.prototype.toTimeString ( ) |
| 799 BUILTIN(DatePrototypeToTimeString) { |
| 800 HandleScope scope(isolate); |
| 801 CHECK_RECEIVER(JSDate, date, "Date.prototype.toTimeString"); |
| 802 char buffer[128]; |
| 803 ToDateString(date->value()->Number(), ArrayVector(buffer), |
| 804 isolate->date_cache(), kTimeOnly); |
| 805 RETURN_RESULT_OR_FAILURE( |
| 806 isolate, isolate->factory()->NewStringFromUtf8(CStrVector(buffer))); |
| 807 } |
| 808 |
| 809 // ES6 section 20.3.4.43 Date.prototype.toUTCString ( ) |
| 810 BUILTIN(DatePrototypeToUTCString) { |
| 811 HandleScope scope(isolate); |
| 812 CHECK_RECEIVER(JSDate, date, "Date.prototype.toUTCString"); |
| 813 double const time_val = date->value()->Number(); |
| 814 if (std::isnan(time_val)) { |
| 815 return *isolate->factory()->NewStringFromAsciiChecked("Invalid Date"); |
| 816 } |
| 817 char buffer[128]; |
| 818 int64_t time_ms = static_cast<int64_t>(time_val); |
| 819 int year, month, day, weekday, hour, min, sec, ms; |
| 820 isolate->date_cache()->BreakDownTime(time_ms, &year, &month, &day, &weekday, |
| 821 &hour, &min, &sec, &ms); |
| 822 SNPrintF(ArrayVector(buffer), "%s, %02d %s %4d %02d:%02d:%02d GMT", |
| 823 kShortWeekDays[weekday], day, kShortMonths[month], year, hour, min, |
| 824 sec); |
| 825 return *isolate->factory()->NewStringFromAsciiChecked(buffer); |
| 826 } |
| 827 |
| 828 // ES6 section 20.3.4.44 Date.prototype.valueOf ( ) |
| 829 BUILTIN(DatePrototypeValueOf) { |
| 830 HandleScope scope(isolate); |
| 831 CHECK_RECEIVER(JSDate, date, "Date.prototype.valueOf"); |
| 832 return date->value(); |
| 833 } |
| 834 |
| 835 // ES6 section 20.3.4.45 Date.prototype [ @@toPrimitive ] ( hint ) |
| 836 BUILTIN(DatePrototypeToPrimitive) { |
| 837 HandleScope scope(isolate); |
| 838 DCHECK_EQ(2, args.length()); |
| 839 CHECK_RECEIVER(JSReceiver, receiver, "Date.prototype [ @@toPrimitive ]"); |
| 840 Handle<Object> hint = args.at<Object>(1); |
| 841 RETURN_RESULT_OR_FAILURE(isolate, JSDate::ToPrimitive(receiver, hint)); |
| 842 } |
| 843 |
| 844 // ES6 section B.2.4.1 Date.prototype.getYear ( ) |
| 845 BUILTIN(DatePrototypeGetYear) { |
| 846 HandleScope scope(isolate); |
| 847 CHECK_RECEIVER(JSDate, date, "Date.prototype.getYear"); |
| 848 double time_val = date->value()->Number(); |
| 849 if (std::isnan(time_val)) return date->value(); |
| 850 int64_t time_ms = static_cast<int64_t>(time_val); |
| 851 int64_t local_time_ms = isolate->date_cache()->ToLocal(time_ms); |
| 852 int days = isolate->date_cache()->DaysFromTime(local_time_ms); |
| 853 int year, month, day; |
| 854 isolate->date_cache()->YearMonthDayFromDays(days, &year, &month, &day); |
| 855 return Smi::FromInt(year - 1900); |
| 856 } |
| 857 |
| 858 // ES6 section B.2.4.2 Date.prototype.setYear ( year ) |
| 859 BUILTIN(DatePrototypeSetYear) { |
| 860 HandleScope scope(isolate); |
| 861 CHECK_RECEIVER(JSDate, date, "Date.prototype.setYear"); |
| 862 Handle<Object> year = args.atOrUndefined(isolate, 1); |
| 863 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, year, Object::ToNumber(year)); |
| 864 double m = 0.0, dt = 1.0, y = year->Number(); |
| 865 if (0.0 <= y && y <= 99.0) { |
| 866 y = 1900.0 + DoubleToInteger(y); |
| 867 } |
| 868 int time_within_day = 0; |
| 869 if (!std::isnan(date->value()->Number())) { |
| 870 int64_t const time_ms = static_cast<int64_t>(date->value()->Number()); |
| 871 int64_t local_time_ms = isolate->date_cache()->ToLocal(time_ms); |
| 872 int const days = isolate->date_cache()->DaysFromTime(local_time_ms); |
| 873 time_within_day = isolate->date_cache()->TimeInDay(local_time_ms, days); |
| 874 int year, month, day; |
| 875 isolate->date_cache()->YearMonthDayFromDays(days, &year, &month, &day); |
| 876 m = month; |
| 877 dt = day; |
| 878 } |
| 879 double time_val = MakeDate(MakeDay(y, m, dt), time_within_day); |
| 880 return SetLocalDateValue(date, time_val); |
| 881 } |
| 882 |
| 883 // ES6 section 20.3.4.37 Date.prototype.toJSON ( key ) |
| 884 BUILTIN(DatePrototypeToJson) { |
| 885 HandleScope scope(isolate); |
| 886 Handle<Object> receiver = args.atOrUndefined(isolate, 0); |
| 887 Handle<JSReceiver> receiver_obj; |
| 888 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, receiver_obj, |
| 889 Object::ToObject(isolate, receiver)); |
| 890 Handle<Object> primitive; |
| 891 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( |
| 892 isolate, primitive, |
| 893 Object::ToPrimitive(receiver_obj, ToPrimitiveHint::kNumber)); |
| 894 if (primitive->IsNumber() && !std::isfinite(primitive->Number())) { |
| 895 return isolate->heap()->null_value(); |
| 896 } else { |
| 897 Handle<String> name = |
| 898 isolate->factory()->NewStringFromAsciiChecked("toISOString"); |
| 899 Handle<Object> function; |
| 900 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, function, |
| 901 Object::GetProperty(receiver_obj, name)); |
| 902 if (!function->IsCallable()) { |
| 903 THROW_NEW_ERROR_RETURN_FAILURE( |
| 904 isolate, NewTypeError(MessageTemplate::kCalledNonCallable, name)); |
| 905 } |
| 906 RETURN_RESULT_OR_FAILURE( |
| 907 isolate, Execution::Call(isolate, function, receiver_obj, 0, NULL)); |
| 908 } |
| 909 } |
| 910 |
| 911 // static |
| 912 void Builtins::Generate_DatePrototypeGetDate(MacroAssembler* masm) { |
| 913 Generate_DatePrototype_GetField(masm, JSDate::kDay); |
| 914 } |
| 915 |
| 916 // static |
| 917 void Builtins::Generate_DatePrototypeGetDay(MacroAssembler* masm) { |
| 918 Generate_DatePrototype_GetField(masm, JSDate::kWeekday); |
| 919 } |
| 920 |
| 921 // static |
| 922 void Builtins::Generate_DatePrototypeGetFullYear(MacroAssembler* masm) { |
| 923 Generate_DatePrototype_GetField(masm, JSDate::kYear); |
| 924 } |
| 925 |
| 926 // static |
| 927 void Builtins::Generate_DatePrototypeGetHours(MacroAssembler* masm) { |
| 928 Generate_DatePrototype_GetField(masm, JSDate::kHour); |
| 929 } |
| 930 |
| 931 // static |
| 932 void Builtins::Generate_DatePrototypeGetMilliseconds(MacroAssembler* masm) { |
| 933 Generate_DatePrototype_GetField(masm, JSDate::kMillisecond); |
| 934 } |
| 935 |
| 936 // static |
| 937 void Builtins::Generate_DatePrototypeGetMinutes(MacroAssembler* masm) { |
| 938 Generate_DatePrototype_GetField(masm, JSDate::kMinute); |
| 939 } |
| 940 |
| 941 // static |
| 942 void Builtins::Generate_DatePrototypeGetMonth(MacroAssembler* masm) { |
| 943 Generate_DatePrototype_GetField(masm, JSDate::kMonth); |
| 944 } |
| 945 |
| 946 // static |
| 947 void Builtins::Generate_DatePrototypeGetSeconds(MacroAssembler* masm) { |
| 948 Generate_DatePrototype_GetField(masm, JSDate::kSecond); |
| 949 } |
| 950 |
| 951 // static |
| 952 void Builtins::Generate_DatePrototypeGetTime(MacroAssembler* masm) { |
| 953 Generate_DatePrototype_GetField(masm, JSDate::kDateValue); |
| 954 } |
| 955 |
| 956 // static |
| 957 void Builtins::Generate_DatePrototypeGetTimezoneOffset(MacroAssembler* masm) { |
| 958 Generate_DatePrototype_GetField(masm, JSDate::kTimezoneOffset); |
| 959 } |
| 960 |
| 961 // static |
| 962 void Builtins::Generate_DatePrototypeGetUTCDate(MacroAssembler* masm) { |
| 963 Generate_DatePrototype_GetField(masm, JSDate::kDayUTC); |
| 964 } |
| 965 |
| 966 // static |
| 967 void Builtins::Generate_DatePrototypeGetUTCDay(MacroAssembler* masm) { |
| 968 Generate_DatePrototype_GetField(masm, JSDate::kWeekdayUTC); |
| 969 } |
| 970 |
| 971 // static |
| 972 void Builtins::Generate_DatePrototypeGetUTCFullYear(MacroAssembler* masm) { |
| 973 Generate_DatePrototype_GetField(masm, JSDate::kYearUTC); |
| 974 } |
| 975 |
| 976 // static |
| 977 void Builtins::Generate_DatePrototypeGetUTCHours(MacroAssembler* masm) { |
| 978 Generate_DatePrototype_GetField(masm, JSDate::kHourUTC); |
| 979 } |
| 980 |
| 981 // static |
| 982 void Builtins::Generate_DatePrototypeGetUTCMilliseconds(MacroAssembler* masm) { |
| 983 Generate_DatePrototype_GetField(masm, JSDate::kMillisecondUTC); |
| 984 } |
| 985 |
| 986 // static |
| 987 void Builtins::Generate_DatePrototypeGetUTCMinutes(MacroAssembler* masm) { |
| 988 Generate_DatePrototype_GetField(masm, JSDate::kMinuteUTC); |
| 989 } |
| 990 |
| 991 // static |
| 992 void Builtins::Generate_DatePrototypeGetUTCMonth(MacroAssembler* masm) { |
| 993 Generate_DatePrototype_GetField(masm, JSDate::kMonthUTC); |
| 994 } |
| 995 |
| 996 // static |
| 997 void Builtins::Generate_DatePrototypeGetUTCSeconds(MacroAssembler* masm) { |
| 998 Generate_DatePrototype_GetField(masm, JSDate::kSecondUTC); |
| 999 } |
| 1000 |
| 1001 } // namespace internal |
| 1002 } // namespace v8 |
OLD | NEW |