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