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