v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
builtins-date.cc
Go to the documentation of this file.
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
8#include "src/date/date.h"
12#include "src/objects/bigint.h"
13#ifdef V8_INTL_SUPPORT
16#endif
20
21namespace v8 {
22namespace internal {
23
24// -----------------------------------------------------------------------------
25// ES6 section 20.3 Date Objects
26
27namespace {
28
29Tagged<Object> SetLocalDateValue(Isolate* isolate, DirectHandle<JSDate> date,
30 double time_val) {
31 if (time_val >= -DateCache::kMaxTimeBeforeUTCInMs &&
33 time_val = isolate->date_cache()->ToUTC(static_cast<int64_t>(time_val));
34 if (DateCache::TryTimeClip(&time_val)) {
35 date->SetValue(time_val);
36 return *isolate->factory()->NewNumber(time_val);
37 }
38 }
39 date->SetNanValue();
40 return ReadOnlyRoots(isolate).nan_value();
41}
42
43Tagged<Object> SetDateValue(Isolate* isolate, DirectHandle<JSDate> date,
44 double time_val) {
45 if (DateCache::TryTimeClip(&time_val)) {
46 date->SetValue(time_val);
47 return *isolate->factory()->NewNumber(time_val);
48 }
49 date->SetNanValue();
50 return ReadOnlyRoots(isolate).nan_value();
51}
52
53} // namespace
54
55// ES #sec-date-constructor
56BUILTIN(DateConstructor) {
57 HandleScope scope(isolate);
58 if (IsUndefined(*args.new_target(), isolate)) {
59 double const time_val =
60 static_cast<double>(JSDate::CurrentTimeValue(isolate));
61 DateBuffer buffer = ToDateString(time_val, isolate->date_cache(),
64 isolate, isolate->factory()->NewStringFromUtf8(base::VectorOf(buffer)));
65 }
66 // [Construct]
67 int const argc = args.length() - 1;
68 DirectHandle<JSFunction> target = args.target();
70 double time_val;
71 if (argc == 0) {
72 time_val = static_cast<double>(JSDate::CurrentTimeValue(isolate));
73 } else if (argc == 1) {
74 DirectHandle<Object> value = args.at(1);
75 if (IsJSDate(*value)) {
76 time_val = Cast<JSDate>(value)->value();
77 } else {
79 Object::ToPrimitive(isolate, value));
80 if (IsString(*value)) {
81 time_val = ParseDateTimeString(isolate, Cast<String>(value));
82 } else {
84 Object::ToNumber(isolate, value));
85 time_val = Object::NumberValue(*value);
86 }
87 }
88 } else {
89 DirectHandle<Object> year_object;
90 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, year_object,
91 Object::ToNumber(isolate, args.at(1)));
92 DirectHandle<Object> month_object;
93 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, month_object,
94 Object::ToNumber(isolate, args.at(2)));
95 double year = Object::NumberValue(*year_object);
96 double month = Object::NumberValue(*month_object);
97 double date = 1.0, hours = 0.0, minutes = 0.0, seconds = 0.0, ms = 0.0;
98 if (argc >= 3) {
99 DirectHandle<Object> date_object;
100 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, date_object,
101 Object::ToNumber(isolate, args.at(3)));
102 date = Object::NumberValue(*date_object);
103 if (argc >= 4) {
104 DirectHandle<Object> hours_object;
106 isolate, hours_object, Object::ToNumber(isolate, args.at(4)));
107 hours = Object::NumberValue(*hours_object);
108 if (argc >= 5) {
109 DirectHandle<Object> minutes_object;
111 isolate, minutes_object, Object::ToNumber(isolate, args.at(5)));
112 minutes = Object::NumberValue(*minutes_object);
113 if (argc >= 6) {
114 DirectHandle<Object> seconds_object;
116 isolate, seconds_object, Object::ToNumber(isolate, args.at(6)));
117 seconds = Object::NumberValue(*seconds_object);
118 if (argc >= 7) {
119 DirectHandle<Object> ms_object;
121 isolate, ms_object, Object::ToNumber(isolate, args.at(7)));
122 ms = Object::NumberValue(*ms_object);
123 }
124 }
125 }
126 }
127 }
128 if (!std::isnan(year)) {
129 double const y = DoubleToInteger(year);
130 if (0.0 <= y && y <= 99) year = 1900 + y;
131 }
132 double const day = MakeDay(year, month, date);
133 double const time = MakeTime(hours, minutes, seconds, ms);
134 time_val = MakeDate(day, time);
135 if (time_val >= -DateCache::kMaxTimeBeforeUTCInMs &&
137 time_val = isolate->date_cache()->ToUTC(static_cast<int64_t>(time_val));
138 } else {
139 time_val = std::numeric_limits<double>::quiet_NaN();
140 }
141 }
142 RETURN_RESULT_OR_FAILURE(isolate, JSDate::New(target, new_target, time_val));
143}
144
145// ES6 section 20.3.3.1 Date.now ( )
146BUILTIN(DateNow) {
147 HandleScope scope(isolate);
148 return *isolate->factory()->NewNumberFromInt64(
149 JSDate::CurrentTimeValue(isolate));
150}
151
152// ES6 section 20.3.3.2 Date.parse ( string )
153BUILTIN(DateParse) {
154 HandleScope scope(isolate);
157 isolate, string,
158 Object::ToString(isolate, args.atOrUndefined(isolate, 1)));
159 return *isolate->factory()->NewNumber(ParseDateTimeString(isolate, string));
160}
161
162// ES6 section 20.3.3.4 Date.UTC (year,month,date,hours,minutes,seconds,ms)
163BUILTIN(DateUTC) {
164 HandleScope scope(isolate);
165 int const argc = args.length() - 1;
166 double year = std::numeric_limits<double>::quiet_NaN();
167 double month = 0.0, date = 1.0, hours = 0.0, minutes = 0.0, seconds = 0.0,
168 ms = 0.0;
169 if (argc >= 1) {
170 DirectHandle<Object> year_object;
171 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, year_object,
172 Object::ToNumber(isolate, args.at(1)));
173 year = Object::NumberValue(*year_object);
174 if (argc >= 2) {
175 DirectHandle<Object> month_object;
176 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, month_object,
177 Object::ToNumber(isolate, args.at(2)));
178 month = Object::NumberValue(*month_object);
179 if (argc >= 3) {
180 DirectHandle<Object> date_object;
182 isolate, date_object, Object::ToNumber(isolate, args.at(3)));
183 date = Object::NumberValue(*date_object);
184 if (argc >= 4) {
185 DirectHandle<Object> hours_object;
187 isolate, hours_object, Object::ToNumber(isolate, args.at(4)));
188 hours = Object::NumberValue(*hours_object);
189 if (argc >= 5) {
190 DirectHandle<Object> minutes_object;
192 isolate, minutes_object, Object::ToNumber(isolate, args.at(5)));
193 minutes = Object::NumberValue(*minutes_object);
194 if (argc >= 6) {
195 DirectHandle<Object> seconds_object;
197 isolate, seconds_object,
198 Object::ToNumber(isolate, args.at(6)));
199 seconds = Object::NumberValue(*seconds_object);
200 if (argc >= 7) {
201 DirectHandle<Object> ms_object;
203 isolate, ms_object, Object::ToNumber(isolate, args.at(7)));
204 ms = Object::NumberValue(*ms_object);
205 }
206 }
207 }
208 }
209 }
210 }
211 }
212 if (!std::isnan(year)) {
213 double const y = DoubleToInteger(year);
214 if (0.0 <= y && y <= 99) year = 1900 + y;
215 }
216 double const day = MakeDay(year, month, date);
217 double const time = MakeTime(hours, minutes, seconds, ms);
218 double value = MakeDate(day, time);
219 if (DateCache::TryTimeClip(&value)) {
220 return *isolate->factory()->NewNumber(value);
221 }
222 return ReadOnlyRoots(isolate).nan_value();
223}
224
225// ES6 section 20.3.4.20 Date.prototype.setDate ( date )
226BUILTIN(DatePrototypeSetDate) {
227 HandleScope scope(isolate);
228 CHECK_RECEIVER(JSDate, date, "Date.prototype.setDate");
229 DirectHandle<Object> value = args.atOrUndefined(isolate, 1);
230 double time_val = date->value();
232 Object::ToNumber(isolate, value));
233 if (std::isnan(time_val)) {
234 return ReadOnlyRoots(isolate).nan_value();
235 }
236
237 int64_t const time_ms = static_cast<int64_t>(time_val);
238 int64_t local_time_ms = isolate->date_cache()->ToLocal(time_ms);
239 int const days = isolate->date_cache()->DaysFromTime(local_time_ms);
240 int time_within_day = isolate->date_cache()->TimeInDay(local_time_ms, days);
241 int year, month, day;
242 isolate->date_cache()->YearMonthDayFromDays(days, &year, &month, &day);
243 time_val = MakeDate(MakeDay(year, month, Object::NumberValue(*value)),
244 time_within_day);
245 return SetLocalDateValue(isolate, date, time_val);
246}
247
248// ES6 section 20.3.4.21 Date.prototype.setFullYear (year, month, date)
249BUILTIN(DatePrototypeSetFullYear) {
250 HandleScope scope(isolate);
251 CHECK_RECEIVER(JSDate, date, "Date.prototype.setFullYear");
252 int const argc = args.length() - 1;
253 DirectHandle<Object> year = args.atOrUndefined(isolate, 1);
255 Object::ToNumber(isolate, year));
256 double year_double = Object::NumberValue(*year), month_double = 0.0,
257 day_double = 1.0;
258 int time_within_day = 0;
259 if (!std::isnan(date->value())) {
260 int64_t const time_ms = static_cast<int64_t>(date->value());
261 int64_t local_time_ms = isolate->date_cache()->ToLocal(time_ms);
262 int const days = isolate->date_cache()->DaysFromTime(local_time_ms);
263 time_within_day = isolate->date_cache()->TimeInDay(local_time_ms, days);
264 int year_int, month_int, day_int;
265 isolate->date_cache()->YearMonthDayFromDays(days, &year_int, &month_int,
266 &day_int);
267 month_double = month_int;
268 day_double = day_int;
269 }
270 if (argc >= 2) {
271 DirectHandle<Object> month = args.at(2);
273 Object::ToNumber(isolate, month));
274 month_double = Object::NumberValue(*month);
275 if (argc >= 3) {
276 DirectHandle<Object> day = args.at(3);
278 Object::ToNumber(isolate, day));
279 day_double = Object::NumberValue(*day);
280 }
281 }
282 double time_val =
283 MakeDate(MakeDay(year_double, month_double, day_double), time_within_day);
284 return SetLocalDateValue(isolate, date, time_val);
285}
286
287// ES6 section 20.3.4.22 Date.prototype.setHours(hour, min, sec, ms)
288BUILTIN(DatePrototypeSetHours) {
289 HandleScope scope(isolate);
290 CHECK_RECEIVER(JSDate, date, "Date.prototype.setHours");
291 int const argc = args.length() - 1;
292 DirectHandle<Object> hour = args.atOrUndefined(isolate, 1);
293 double time_val = date->value();
295 Object::ToNumber(isolate, hour));
296 double const h = Object::NumberValue(*hour);
297 std::optional<double> m;
298 std::optional<double> s;
299 std::optional<double> milli;
300
301 if (argc >= 2) {
302 DirectHandle<Object> min = args.at(2);
304 Object::ToNumber(isolate, min));
305 m = Object::NumberValue(*min);
306 if (argc >= 3) {
307 DirectHandle<Object> sec = args.at(3);
309 Object::ToNumber(isolate, sec));
310 s = Object::NumberValue(*sec);
311 if (argc >= 4) {
312 DirectHandle<Object> ms = args.at(4);
314 Object::ToNumber(isolate, ms));
315 milli = Object::NumberValue(*ms);
316 }
317 }
318 }
319
320 if (std::isnan(time_val)) {
321 return ReadOnlyRoots(isolate).nan_value();
322 }
323
324 int64_t const time_ms = static_cast<int64_t>(time_val);
325 int64_t const local_time_ms = isolate->date_cache()->ToLocal(time_ms);
326 int const day = isolate->date_cache()->DaysFromTime(local_time_ms);
327 int const time_within_day =
328 isolate->date_cache()->TimeInDay(local_time_ms, day);
329 time_val = MakeDate(
330 day, MakeTime(h, m.value_or((time_within_day / (60 * 1000)) % 60),
331 s.value_or((time_within_day / 1000) % 60),
332 milli.value_or(time_within_day % 1000)));
333 return SetLocalDateValue(isolate, date, time_val);
334}
335
336// ES6 section 20.3.4.23 Date.prototype.setMilliseconds(ms)
337BUILTIN(DatePrototypeSetMilliseconds) {
338 HandleScope scope(isolate);
339 CHECK_RECEIVER(JSDate, date, "Date.prototype.setMilliseconds");
340 DirectHandle<Object> ms = args.atOrUndefined(isolate, 1);
341 double time_val = date->value();
343 Object::ToNumber(isolate, ms));
344 if (std::isnan(time_val)) {
345 return ReadOnlyRoots(isolate).nan_value();
346 }
347 int64_t const time_ms = static_cast<int64_t>(time_val);
348 int64_t const local_time_ms = isolate->date_cache()->ToLocal(time_ms);
349 int const day = isolate->date_cache()->DaysFromTime(local_time_ms);
350 int const time_within_day =
351 isolate->date_cache()->TimeInDay(local_time_ms, day);
352 int const h = time_within_day / (60 * 60 * 1000);
353 int const m = (time_within_day / (60 * 1000)) % 60;
354 int const s = (time_within_day / 1000) % 60;
355 time_val = MakeDate(day, MakeTime(h, m, s, Object::NumberValue(*ms)));
356
357 return SetLocalDateValue(isolate, date, time_val);
358}
359
360// ES6 section 20.3.4.24 Date.prototype.setMinutes ( min, sec, ms )
361BUILTIN(DatePrototypeSetMinutes) {
362 HandleScope scope(isolate);
363 CHECK_RECEIVER(JSDate, date, "Date.prototype.setMinutes");
364 int const argc = args.length() - 1;
365 DirectHandle<Object> min = args.atOrUndefined(isolate, 1);
366 double time_val = date->value();
368 Object::ToNumber(isolate, min));
369 std::optional<double> s;
370 std::optional<double> milli;
371
372 if (argc >= 2) {
373 DirectHandle<Object> sec = args.at(2);
375 Object::ToNumber(isolate, sec));
376 s = Object::NumberValue(*sec);
377 if (argc >= 3) {
378 DirectHandle<Object> ms = args.at(3);
380 Object::ToNumber(isolate, ms));
381 milli = Object::NumberValue(*ms);
382 }
383 }
384
385 if (std::isnan(time_val)) {
386 return ReadOnlyRoots(isolate).nan_value();
387 }
388
389 int64_t const time_ms = static_cast<int64_t>(time_val);
390 int64_t const local_time_ms = isolate->date_cache()->ToLocal(time_ms);
391 int const day = isolate->date_cache()->DaysFromTime(local_time_ms);
392 int const time_within_day =
393 isolate->date_cache()->TimeInDay(local_time_ms, day);
394 int const h = time_within_day / (60 * 60 * 1000);
395 double const m = Object::NumberValue(*min);
396 time_val =
397 MakeDate(day, MakeTime(h, m, s.value_or((time_within_day / 1000) % 60),
398 milli.value_or(time_within_day % 1000)));
399 return SetLocalDateValue(isolate, date, time_val);
400}
401
402// ES6 section 20.3.4.25 Date.prototype.setMonth ( month, date )
403BUILTIN(DatePrototypeSetMonth) {
404 HandleScope scope(isolate);
405 CHECK_RECEIVER(JSDate, this_date, "Date.prototype.setMonth");
406 int const argc = args.length() - 1;
407 DirectHandle<Object> month = args.atOrUndefined(isolate, 1);
408 double time_val = this_date->value();
410 Object::ToNumber(isolate, month));
411 std::optional<double> dt;
412
413 if (argc >= 2) {
416 Object::ToNumber(isolate, date));
418 }
419
420 if (std::isnan(time_val)) {
421 return ReadOnlyRoots(isolate).nan_value();
422 }
423
424 int64_t const time_ms = static_cast<int64_t>(time_val);
425 int64_t const local_time_ms = isolate->date_cache()->ToLocal(time_ms);
426 int const days = isolate->date_cache()->DaysFromTime(local_time_ms);
427 int const time_within_day =
428 isolate->date_cache()->TimeInDay(local_time_ms, days);
429 int year, unused, day;
430 isolate->date_cache()->YearMonthDayFromDays(days, &year, &unused, &day);
431 double const m = Object::NumberValue(*month);
432 time_val = MakeDate(MakeDay(year, m, dt.value_or(day)), time_within_day);
433
434 return SetLocalDateValue(isolate, this_date, time_val);
435}
436
437// ES6 section 20.3.4.26 Date.prototype.setSeconds ( sec, ms )
438BUILTIN(DatePrototypeSetSeconds) {
439 HandleScope scope(isolate);
440 CHECK_RECEIVER(JSDate, date, "Date.prototype.setSeconds");
441 int const argc = args.length() - 1;
442 DirectHandle<Object> sec = args.atOrUndefined(isolate, 1);
443 double time_val = date->value();
445 Object::ToNumber(isolate, sec));
446 std::optional<double> milli;
447
448 if (argc >= 2) {
449 DirectHandle<Object> ms = args.at(2);
451 Object::ToNumber(isolate, ms));
452 milli = Object::NumberValue(*ms);
453 }
454
455 if (std::isnan(time_val)) {
456 return ReadOnlyRoots(isolate).nan_value();
457 }
458
459 int64_t const time_ms = static_cast<int64_t>(time_val);
460 int64_t const local_time_ms = isolate->date_cache()->ToLocal(time_ms);
461 int const day = isolate->date_cache()->DaysFromTime(local_time_ms);
462 int const time_within_day =
463 isolate->date_cache()->TimeInDay(local_time_ms, day);
464 int const h = time_within_day / (60 * 60 * 1000);
465 double const m = (time_within_day / (60 * 1000)) % 60;
466 double const s = Object::NumberValue(*sec);
467 time_val =
468 MakeDate(day, MakeTime(h, m, s, milli.value_or(time_within_day % 1000)));
469 return SetLocalDateValue(isolate, date, time_val);
470}
471
472// ES6 section 20.3.4.27 Date.prototype.setTime ( time )
473BUILTIN(DatePrototypeSetTime) {
474 HandleScope scope(isolate);
475 CHECK_RECEIVER(JSDate, date, "Date.prototype.setTime");
476 DirectHandle<Object> value = args.atOrUndefined(isolate, 1);
478 Object::ToNumber(isolate, value));
479 double value_double = Object::NumberValue(*value);
480
481 // Don't use SetDateValue here, since we might already have a tagged value for
482 // the time, and we don't want to reallocate it.
483 double clipped_value = value_double;
484 if (DateCache::TryTimeClip(&clipped_value)) {
485 date->SetValue(clipped_value);
486 // If the clipping didn't change the value (i.e. the value was already an
487 // integer), we can reuse the incoming value for the return value.
488 // Otherwise, we have to allocate a new value. Make sure to use
489 // SameNumberValue so that -0 is _not_ treated as equal to the 0.
490 if (Object::SameNumberValue(clipped_value, value_double)) {
491 return *value;
492 }
493 return *isolate->factory()->NewNumber(clipped_value);
494 }
495 date->SetNanValue();
496 return ReadOnlyRoots(isolate).nan_value();
497}
498
499// ES6 section 20.3.4.28 Date.prototype.setUTCDate ( date )
500BUILTIN(DatePrototypeSetUTCDate) {
501 HandleScope scope(isolate);
502 CHECK_RECEIVER(JSDate, date, "Date.prototype.setUTCDate");
503 DirectHandle<Object> value = args.atOrUndefined(isolate, 1);
504 double time_val = date->value();
506 Object::ToNumber(isolate, value));
507 if (std::isnan(time_val)) {
508 return ReadOnlyRoots(isolate).nan_value();
509 }
510
511 int64_t const time_ms = static_cast<int64_t>(time_val);
512 int const days = isolate->date_cache()->DaysFromTime(time_ms);
513 int const time_within_day = isolate->date_cache()->TimeInDay(time_ms, days);
514 int year, month, day;
515 isolate->date_cache()->YearMonthDayFromDays(days, &year, &month, &day);
516 time_val = MakeDate(MakeDay(year, month, Object::NumberValue(*value)),
517 time_within_day);
518 return SetDateValue(isolate, date, time_val);
519}
520
521// ES6 section 20.3.4.29 Date.prototype.setUTCFullYear (year, month, date)
522BUILTIN(DatePrototypeSetUTCFullYear) {
523 HandleScope scope(isolate);
524 CHECK_RECEIVER(JSDate, date, "Date.prototype.setUTCFullYear");
525 int const argc = args.length() - 1;
526 DirectHandle<Object> year = args.atOrUndefined(isolate, 1);
528 Object::ToNumber(isolate, year));
529 double year_double = Object::NumberValue(*year), month_double = 0.0,
530 day_double = 1.0;
531 int time_within_day = 0;
532 if (!std::isnan(date->value())) {
533 int64_t const time_ms = static_cast<int64_t>(date->value());
534 int const days = isolate->date_cache()->DaysFromTime(time_ms);
535 time_within_day = isolate->date_cache()->TimeInDay(time_ms, days);
536 int year_int, month_int, day_int;
537 isolate->date_cache()->YearMonthDayFromDays(days, &year_int, &month_int,
538 &day_int);
539 month_double = month_int;
540 day_double = day_int;
541 }
542 if (argc >= 2) {
543 DirectHandle<Object> month = args.at(2);
545 Object::ToNumber(isolate, month));
546 month_double = Object::NumberValue(*month);
547 if (argc >= 3) {
548 DirectHandle<Object> day = args.at(3);
550 Object::ToNumber(isolate, day));
551 day_double = Object::NumberValue(*day);
552 }
553 }
554 double const time_val =
555 MakeDate(MakeDay(year_double, month_double, day_double), time_within_day);
556 return SetDateValue(isolate, date, time_val);
557}
558
559// ES6 section 20.3.4.30 Date.prototype.setUTCHours(hour, min, sec, ms)
560BUILTIN(DatePrototypeSetUTCHours) {
561 HandleScope scope(isolate);
562 CHECK_RECEIVER(JSDate, date, "Date.prototype.setUTCHours");
563 int const argc = args.length() - 1;
564 DirectHandle<Object> hour = args.atOrUndefined(isolate, 1);
565 double time_val = date->value();
567 Object::ToNumber(isolate, hour));
568 double const h = Object::NumberValue(*hour);
569 std::optional<double> m;
570 std::optional<double> s;
571 std::optional<double> milli;
572
573 if (argc >= 2) {
574 DirectHandle<Object> min = args.at(2);
576 Object::ToNumber(isolate, min));
577 m = Object::NumberValue(*min);
578 if (argc >= 3) {
579 DirectHandle<Object> sec = args.at(3);
581 Object::ToNumber(isolate, sec));
582 s = Object::NumberValue(*sec);
583 if (argc >= 4) {
584 DirectHandle<Object> ms = args.at(4);
586 Object::ToNumber(isolate, ms));
587 milli = Object::NumberValue(*ms);
588 }
589 }
590 }
591
592 if (std::isnan(time_val)) {
593 return ReadOnlyRoots(isolate).nan_value();
594 }
595
596 int64_t const time_ms = static_cast<int64_t>(time_val);
597 int const day = isolate->date_cache()->DaysFromTime(time_ms);
598 int const time_within_day = isolate->date_cache()->TimeInDay(time_ms, day);
599 time_val = MakeDate(
600 day, MakeTime(h, m.value_or((time_within_day / (60 * 1000)) % 60),
601 s.value_or((time_within_day / 1000) % 60),
602 milli.value_or(time_within_day % 1000)));
603 return SetDateValue(isolate, date, time_val);
604}
605
606// ES6 section 20.3.4.31 Date.prototype.setUTCMilliseconds(ms)
607BUILTIN(DatePrototypeSetUTCMilliseconds) {
608 HandleScope scope(isolate);
609 CHECK_RECEIVER(JSDate, date, "Date.prototype.setUTCMilliseconds");
610 DirectHandle<Object> ms = args.atOrUndefined(isolate, 1);
611 double time_val = date->value();
613 Object::ToNumber(isolate, ms));
614 if (std::isnan(time_val)) {
615 return ReadOnlyRoots(isolate).nan_value();
616 }
617
618 int64_t const time_ms = static_cast<int64_t>(time_val);
619 int const day = isolate->date_cache()->DaysFromTime(time_ms);
620 int const time_within_day = isolate->date_cache()->TimeInDay(time_ms, day);
621 int const h = time_within_day / (60 * 60 * 1000);
622 int const m = (time_within_day / (60 * 1000)) % 60;
623 int const s = (time_within_day / 1000) % 60;
624 time_val = MakeDate(day, MakeTime(h, m, s, Object::NumberValue(*ms)));
625
626 return SetDateValue(isolate, date, time_val);
627}
628
629// ES6 section 20.3.4.32 Date.prototype.setUTCMinutes ( min, sec, ms )
630BUILTIN(DatePrototypeSetUTCMinutes) {
631 HandleScope scope(isolate);
632 CHECK_RECEIVER(JSDate, date, "Date.prototype.setUTCMinutes");
633 int const argc = args.length() - 1;
634 DirectHandle<Object> min = args.atOrUndefined(isolate, 1);
635 double time_val = date->value();
637 Object::ToNumber(isolate, min));
638 std::optional<double> s;
639 std::optional<double> milli;
640
641 if (argc >= 2) {
642 DirectHandle<Object> sec = args.at(2);
644 Object::ToNumber(isolate, sec));
645 s = Object::NumberValue(*sec);
646 if (argc >= 3) {
647 DirectHandle<Object> ms = args.at(3);
649 Object::ToNumber(isolate, ms));
650 milli = Object::NumberValue(*ms);
651 }
652 }
653
654 if (std::isnan(time_val)) {
655 return ReadOnlyRoots(isolate).nan_value();
656 }
657
658 int64_t const time_ms = static_cast<int64_t>(time_val);
659 int const day = isolate->date_cache()->DaysFromTime(time_ms);
660 int const time_within_day = isolate->date_cache()->TimeInDay(time_ms, day);
661 int const h = time_within_day / (60 * 60 * 1000);
662 double const m = Object::NumberValue(*min);
663 time_val =
664 MakeDate(day, MakeTime(h, m, s.value_or((time_within_day / 1000) % 60),
665 milli.value_or(time_within_day % 1000)));
666 return SetDateValue(isolate, date, time_val);
667}
668
669// ES6 section 20.3.4.31 Date.prototype.setUTCMonth ( month, date )
670BUILTIN(DatePrototypeSetUTCMonth) {
671 HandleScope scope(isolate);
672 CHECK_RECEIVER(JSDate, this_date, "Date.prototype.setUTCMonth");
673 int const argc = args.length() - 1;
674 DirectHandle<Object> month = args.atOrUndefined(isolate, 1);
675 double time_val = this_date->value();
677 Object::ToNumber(isolate, month));
678 std::optional<double> dt;
679 if (argc >= 2) {
682 Object::ToNumber(isolate, date));
684 }
685
686 if (std::isnan(time_val)) {
687 return ReadOnlyRoots(isolate).nan_value();
688 }
689
690 int64_t const time_ms = static_cast<int64_t>(time_val);
691 int const days = isolate->date_cache()->DaysFromTime(time_ms);
692 int const time_within_day = isolate->date_cache()->TimeInDay(time_ms, days);
693 int year, unused, day;
694 isolate->date_cache()->YearMonthDayFromDays(days, &year, &unused, &day);
695 double const m = Object::NumberValue(*month);
696 time_val = MakeDate(MakeDay(year, m, dt.value_or(day)), time_within_day);
697
698 return SetDateValue(isolate, this_date, time_val);
699}
700
701// ES6 section 20.3.4.34 Date.prototype.setUTCSeconds ( sec, ms )
702BUILTIN(DatePrototypeSetUTCSeconds) {
703 HandleScope scope(isolate);
704 CHECK_RECEIVER(JSDate, date, "Date.prototype.setUTCSeconds");
705 int const argc = args.length() - 1;
706 DirectHandle<Object> sec = args.atOrUndefined(isolate, 1);
707 double time_val = date->value();
709 Object::ToNumber(isolate, sec));
710 std::optional<double> milli;
711 if (argc >= 2) {
712 DirectHandle<Object> ms = args.at(2);
714 Object::ToNumber(isolate, ms));
715 milli = Object::NumberValue(*ms);
716 }
717 if (std::isnan(time_val)) {
718 return ReadOnlyRoots(isolate).nan_value();
719 }
720
721 int64_t const time_ms = static_cast<int64_t>(time_val);
722 int const day = isolate->date_cache()->DaysFromTime(time_ms);
723 int const time_within_day = isolate->date_cache()->TimeInDay(time_ms, day);
724 int const h = time_within_day / (60 * 60 * 1000);
725 double const m = (time_within_day / (60 * 1000)) % 60;
726 double const s = Object::NumberValue(*sec);
727 time_val =
728 MakeDate(day, MakeTime(h, m, s, milli.value_or(time_within_day % 1000)));
729 return SetDateValue(isolate, date, time_val);
730}
731
732// ES6 section 20.3.4.35 Date.prototype.toDateString ( )
733BUILTIN(DatePrototypeToDateString) {
734 HandleScope scope(isolate);
735 CHECK_RECEIVER(JSDate, date, "Date.prototype.toDateString");
736 DateBuffer buffer = ToDateString(date->value(), isolate->date_cache(),
739 isolate, isolate->factory()->NewStringFromUtf8(base::VectorOf(buffer)));
740}
741
742// ES6 section 20.3.4.36 Date.prototype.toISOString ( )
743BUILTIN(DatePrototypeToISOString) {
744 HandleScope scope(isolate);
745 CHECK_RECEIVER(JSDate, date, "Date.prototype.toISOString");
746 double const time_val = date->value();
747 if (std::isnan(time_val)) {
749 isolate, NewRangeError(MessageTemplate::kInvalidTimeValue));
750 }
751 DateBuffer buffer = ToDateString(time_val, isolate->date_cache(),
754 isolate, isolate->factory()->NewStringFromUtf8(base::VectorOf(buffer)));
755}
756
757// ES6 section 20.3.4.41 Date.prototype.toString ( )
758BUILTIN(DatePrototypeToString) {
759 HandleScope scope(isolate);
760 CHECK_RECEIVER(JSDate, date, "Date.prototype.toString");
761 DateBuffer buffer = ToDateString(date->value(), isolate->date_cache(),
764 isolate, isolate->factory()->NewStringFromUtf8(base::VectorOf(buffer)));
765}
766
767// ES6 section 20.3.4.42 Date.prototype.toTimeString ( )
768BUILTIN(DatePrototypeToTimeString) {
769 HandleScope scope(isolate);
770 CHECK_RECEIVER(JSDate, date, "Date.prototype.toTimeString");
771 DateBuffer buffer = ToDateString(date->value(), isolate->date_cache(),
774 isolate, isolate->factory()->NewStringFromUtf8(base::VectorOf(buffer)));
775}
776
777#ifdef V8_INTL_SUPPORT
778// ecma402 #sup-date.prototype.tolocaledatestring
779BUILTIN(DatePrototypeToLocaleDateString) {
780 HandleScope scope(isolate);
781
783
784 const char* method_name = "Date.prototype.toLocaleDateString";
785 CHECK_RECEIVER(JSDate, date, method_name);
786
789 isolate,
790 date, // date
791 args.atOrUndefined(isolate, 1), // locales
792 args.atOrUndefined(isolate, 2), // options
795 method_name)); // method_name
796}
797
798// ecma402 #sup-date.prototype.tolocalestring
799BUILTIN(DatePrototypeToLocaleString) {
800 HandleScope scope(isolate);
801
803
804 const char* method_name = "Date.prototype.toLocaleString";
805 CHECK_RECEIVER(JSDate, date, method_name);
806
809 isolate,
810 date, // date
811 args.atOrUndefined(isolate, 1), // locales
812 args.atOrUndefined(isolate, 2), // options
815 method_name)); // method_name
816}
817
818// ecma402 #sup-date.prototype.tolocaletimestring
819BUILTIN(DatePrototypeToLocaleTimeString) {
820 HandleScope scope(isolate);
821
823
824 const char* method_name = "Date.prototype.toLocaleTimeString";
825 CHECK_RECEIVER(JSDate, date, method_name);
826
829 isolate,
830 date, // date
831 args.atOrUndefined(isolate, 1), // locales
832 args.atOrUndefined(isolate, 2), // options
835 method_name)); // method_name
836}
837#endif // V8_INTL_SUPPORT
838
839// ES6 section 20.3.4.43 Date.prototype.toUTCString ( )
840BUILTIN(DatePrototypeToUTCString) {
841 HandleScope scope(isolate);
842 CHECK_RECEIVER(JSDate, date, "Date.prototype.toUTCString");
843 DateBuffer buffer = ToDateString(date->value(), isolate->date_cache(),
846 isolate, isolate->factory()->NewStringFromUtf8(base::VectorOf(buffer)));
847}
848
849// ES6 section B.2.4.1 Date.prototype.getYear ( )
850BUILTIN(DatePrototypeGetYear) {
851 HandleScope scope(isolate);
852 CHECK_RECEIVER(JSDate, date, "Date.prototype.getYear");
853 double time_val = date->value();
854 if (std::isnan(time_val)) return ReadOnlyRoots(isolate).nan_value();
855 int64_t time_ms = static_cast<int64_t>(time_val);
856 int64_t local_time_ms = isolate->date_cache()->ToLocal(time_ms);
857 int days = isolate->date_cache()->DaysFromTime(local_time_ms);
858 int year, month, day;
859 isolate->date_cache()->YearMonthDayFromDays(days, &year, &month, &day);
860 return Smi::FromInt(year - 1900);
861}
862
863// ES6 section B.2.4.2 Date.prototype.setYear ( year )
864BUILTIN(DatePrototypeSetYear) {
865 HandleScope scope(isolate);
866 CHECK_RECEIVER(JSDate, date, "Date.prototype.setYear");
867 DirectHandle<Object> year = args.atOrUndefined(isolate, 1);
869 Object::ToNumber(isolate, year));
870 double month_double = 0.0, day_double = 1.0,
871 year_double = Object::NumberValue(*year);
872 if (!std::isnan(year_double)) {
873 double year_int = DoubleToInteger(year_double);
874 if (0.0 <= year_int && year_int <= 99.0) {
875 year_double = 1900.0 + year_int;
876 }
877 }
878 int time_within_day = 0;
879 if (!std::isnan(date->value())) {
880 int64_t const time_ms = static_cast<int64_t>(date->value());
881 int64_t local_time_ms = isolate->date_cache()->ToLocal(time_ms);
882 int const days = isolate->date_cache()->DaysFromTime(local_time_ms);
883 time_within_day = isolate->date_cache()->TimeInDay(local_time_ms, days);
884 int year_int, month_int, day_int;
885 isolate->date_cache()->YearMonthDayFromDays(days, &year_int, &month_int,
886 &day_int);
887 month_double = month_int;
888 day_double = day_int;
889 }
890 double time_val =
891 MakeDate(MakeDay(year_double, month_double, day_double), time_within_day);
892 return SetLocalDateValue(isolate, date, time_val);
893}
894
895// ES6 section 20.3.4.37 Date.prototype.toJSON ( key )
896BUILTIN(DatePrototypeToJson) {
897 HandleScope scope(isolate);
898 DirectHandle<Object> receiver = args.atOrUndefined(isolate, 0);
899 DirectHandle<JSReceiver> receiver_obj;
900 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, receiver_obj,
901 Object::ToObject(isolate, receiver));
902 DirectHandle<Object> primitive;
904 isolate, primitive,
905 Object::ToPrimitive(isolate, receiver_obj, ToPrimitiveHint::kNumber));
906 if (IsNumber(*primitive) && !std::isfinite(Object::NumberValue(*primitive))) {
907 return ReadOnlyRoots(isolate).null_value();
908 } else {
910 isolate->factory()->NewStringFromAsciiChecked("toISOString");
911 DirectHandle<Object> function;
913 isolate, function, Object::GetProperty(isolate, receiver_obj, name));
914 if (!IsCallable(*function)) {
916 isolate, NewTypeError(MessageTemplate::kCalledNonCallable, name));
917 }
919 isolate, Execution::Call(isolate, function, receiver_obj, {}));
920 }
921}
922
923// Temporal #sec-date.prototype.totemporalinstant
924BUILTIN(DatePrototypeToTemporalInstant) {
925 HandleScope scope(isolate);
926 CHECK_RECEIVER(JSDate, date, "Date.prototype.toTemporalInstant");
927 // 1. Let t be ? thisTimeValue(this value).
930 isolate, t,
931 BigInt::FromNumber(isolate,
932 isolate->factory()->NewNumber(date->value())));
933 // 2. Let ns be ? NumberToBigInt(t) × 10^6.
936 isolate, ns,
937 BigInt::Multiply(isolate, t, BigInt::FromInt64(isolate, 1000000)));
938 // 3. Return ! CreateTemporalInstant(ns).
939 return *temporal::CreateTemporalInstant(isolate, ns).ToHandleChecked();
940}
941
942} // namespace internal
943} // namespace v8
#define CHECK_RECEIVER(Type, name, method)
#define BUILTIN(name)
@ kDateToLocaleTimeString
Definition v8-isolate.h:537
@ kDateToLocaleDateString
Definition v8-isolate.h:536
@ kDateToLocaleString
Definition v8-isolate.h:535
static MaybeHandle< BigInt > Multiply(Isolate *isolate, DirectHandle< BigInt > x, DirectHandle< BigInt > y)
Definition bigint.cc:432
static V8_EXPORT_PRIVATE Handle< BigInt > FromInt64(Isolate *isolate, int64_t n)
Definition bigint.cc:1333
static V8_EXPORT_PRIVATE MaybeHandle< BigInt > FromNumber(Isolate *isolate, DirectHandle< Object > number)
Definition bigint.cc:954
static bool TryTimeClip(double *time)
Definition date.h:70
static const int64_t kMaxTimeBeforeUTCInMs
Definition date.h:35
V8_EXPORT_PRIVATE static V8_WARN_UNUSED_RESULT MaybeHandle< Object > Call(Isolate *isolate, DirectHandle< Object > callable, DirectHandle< Object > receiver, base::Vector< const DirectHandle< Object > > args)
Definition execution.cc:523
static V8_WARN_UNUSED_RESULT MaybeDirectHandle< String > ToLocaleDateTime(Isolate *isolate, DirectHandle< Object > date, DirectHandle< Object > locales, DirectHandle< Object > options, RequiredOption required, DefaultsOption defaults, const char *method_name)
static int64_t CurrentTimeValue(Isolate *isolate)
static V8_WARN_UNUSED_RESULT MaybeDirectHandle< JSDate > New(DirectHandle< JSFunction > constructor, DirectHandle< JSReceiver > new_target, double tv)
static V8_WARN_UNUSED_RESULT HandleType< String >::MaybeType ToString(Isolate *isolate, HandleType< T > input)
static V8_WARN_UNUSED_RESULT HandleType< Number >::MaybeType ToNumber(Isolate *isolate, HandleType< T > input)
static bool SameNumberValue(double number1, double number2)
static V8_WARN_UNUSED_RESULT HandleType< JSReceiver >::MaybeType ToObject(Isolate *isolate, HandleType< T > object, const char *method_name=nullptr)
static double NumberValue(Tagged< Number > obj)
static V8_WARN_UNUSED_RESULT HandleType< Object >::MaybeType ToPrimitive(Isolate *isolate, HandleType< T > input, ToPrimitiveHint hint=ToPrimitiveHint::kDefault)
V8_EXPORT_PRIVATE static V8_WARN_UNUSED_RESULT MaybeHandle< Object > GetProperty(LookupIterator *it, bool is_global_reference=false)
Definition objects.cc:1248
static constexpr Tagged< Smi > FromInt(int value)
Definition smi.h:38
#define ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, dst, call)
Definition isolate.h:284
#define THROW_NEW_ERROR_RETURN_FAILURE(isolate, call)
Definition isolate.h:294
#define RETURN_RESULT_OR_FAILURE(isolate, call)
Definition isolate.h:264
base::Vector< const DirectHandle< Object > > args
Definition execution.cc:74
DirectHandle< Object > new_target
Definition execution.cc:75
TNode< Object > receiver
double hour
double days
DateRecord date
int s
Definition mul-fft.cc:297
int m
Definition mul-fft.cc:294
constexpr Vector< T > VectorOf(T *start, size_t size)
Definition vector.h:360
MaybeDirectHandle< JSTemporalInstant > CreateTemporalInstant(Isolate *isolate, DirectHandle< JSFunction > target, DirectHandle< HeapObject > new_target, DirectHandle< BigInt > epoch_nanoseconds)
double MakeDate(double day, double time)
Definition date.cc:491
bool IsNumber(Tagged< Object > obj)
double DoubleToInteger(double x)
DateBuffer ToDateString(double time_val, DateCache *date_cache, ToDateStringMode mode)
Definition date.cc:572
double MakeDay(double year, double month, double date)
Definition date.cc:498
double MakeTime(double hour, double min, double sec, double ms)
Definition date.cc:541
return value
Definition map-inl.h:893
double ParseDateTimeString(Isolate *isolate, DirectHandle< String > str)
Definition date.cc:626
template const char * string
Tagged< To > Cast(Tagged< From > value, const v8::SourceLocation &loc=INIT_SOURCE_LOCATION_IN_DEBUG)
Definition casting.h:150