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