• 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/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 
19 namespace v8 {
20 namespace internal {
21 
22 // -----------------------------------------------------------------------------
23 // ES6 section 20.3 Date Objects
24 
25 namespace {
26 
27 // ES6 section 20.3.1.16 Date Time String Format
ParseDateTimeString(Isolate * isolate,Handle<String> str)28 double 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 
SetLocalDateValue(Isolate * isolate,Handle<JSDate> date,double time_val)59 Object 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
BUILTIN(DateConstructor)73 BUILTIN(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 ( )
BUILTIN(DateNow)162 BUILTIN(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 )
BUILTIN(DateParse)168 BUILTIN(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)
BUILTIN(DateUTC)178 BUILTIN(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 )
BUILTIN(DatePrototypeSetDate)238 BUILTIN(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)
BUILTIN(DatePrototypeSetFullYear)258 BUILTIN(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)
BUILTIN(DatePrototypeSetHours)296 BUILTIN(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)
BUILTIN(DatePrototypeSetMilliseconds)337 BUILTIN(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 )
BUILTIN(DatePrototypeSetMinutes)358 BUILTIN(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 )
BUILTIN(DatePrototypeSetMonth)393 BUILTIN(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 )
BUILTIN(DatePrototypeSetSeconds)422 BUILTIN(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 )
BUILTIN(DatePrototypeSetTime)451 BUILTIN(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 )
BUILTIN(DatePrototypeSetUTCDate)461 BUILTIN(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)
BUILTIN(DatePrototypeSetUTCFullYear)479 BUILTIN(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)
BUILTIN(DatePrototypeSetUTCHours)516 BUILTIN(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)
BUILTIN(DatePrototypeSetUTCMilliseconds)556 BUILTIN(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 )
BUILTIN(DatePrototypeSetUTCMinutes)576 BUILTIN(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 )
BUILTIN(DatePrototypeSetUTCMonth)610 BUILTIN(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 )
BUILTIN(DatePrototypeSetUTCSeconds)638 BUILTIN(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 ( )
BUILTIN(DatePrototypeToDateString)666 BUILTIN(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 ( )
BUILTIN(DatePrototypeToISOString)677 BUILTIN(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 ( )
BUILTIN(DatePrototypeToString)704 BUILTIN(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 ( )
BUILTIN(DatePrototypeToTimeString)715 BUILTIN(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
BUILTIN(DatePrototypeToLocaleDateString)727 BUILTIN(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
BUILTIN(DatePrototypeToLocaleString)747 BUILTIN(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
BUILTIN(DatePrototypeToLocaleTimeString)767 BUILTIN(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 ( )
BUILTIN(DatePrototypeToUTCString)788 BUILTIN(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 ( )
BUILTIN(DatePrototypeGetYear)799 BUILTIN(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 )
BUILTIN(DatePrototypeSetYear)813 BUILTIN(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 )
BUILTIN(DatePrototypeToJson)844 BUILTIN(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