1package goja
2
3import (
4	"fmt"
5	"math"
6	"time"
7)
8
9func (r *Runtime) makeDate(args []Value, utc bool) (t time.Time, valid bool) {
10	switch {
11	case len(args) >= 2:
12		t = time.Date(1970, time.January, 1, 0, 0, 0, 0, time.Local)
13		t, valid = _dateSetYear(t, FunctionCall{Arguments: args}, 0, utc)
14	case len(args) == 0:
15		t = r.now()
16		valid = true
17	default: // one argument
18		if o, ok := args[0].(*Object); ok {
19			if d, ok := o.self.(*dateObject); ok {
20				t = d.time()
21				valid = true
22			}
23		}
24		if !valid {
25			pv := toPrimitive(args[0])
26			if val, ok := pv.(valueString); ok {
27				return dateParse(val.String())
28			}
29			pv = pv.ToNumber()
30			var n int64
31			if i, ok := pv.(valueInt); ok {
32				n = int64(i)
33			} else if f, ok := pv.(valueFloat); ok {
34				f := float64(f)
35				if math.IsNaN(f) || math.IsInf(f, 0) {
36					return
37				}
38				if math.Abs(f) > maxTime {
39					return
40				}
41				n = int64(f)
42			} else {
43				n = pv.ToInteger()
44			}
45			t = timeFromMsec(n)
46			valid = true
47		}
48	}
49	if valid {
50		msec := t.Unix()*1000 + int64(t.Nanosecond()/1e6)
51		if msec < 0 {
52			msec = -msec
53		}
54		if msec > maxTime {
55			valid = false
56		}
57	}
58	return
59}
60
61func (r *Runtime) newDateTime(args []Value, proto *Object) *Object {
62	t, isSet := r.makeDate(args, false)
63	return r.newDateObject(t, isSet, proto)
64}
65
66func (r *Runtime) builtin_newDate(args []Value, proto *Object) *Object {
67	return r.newDateTime(args, proto)
68}
69
70func (r *Runtime) builtin_date(FunctionCall) Value {
71	return asciiString(dateFormat(r.now()))
72}
73
74func (r *Runtime) date_parse(call FunctionCall) Value {
75	t, set := dateParse(call.Argument(0).toString().String())
76	if set {
77		return intToValue(timeToMsec(t))
78	}
79	return _NaN
80}
81
82func (r *Runtime) date_UTC(call FunctionCall) Value {
83	var args []Value
84	if len(call.Arguments) < 2 {
85		args = []Value{call.Argument(0), _positiveZero}
86	} else {
87		args = call.Arguments
88	}
89	t, valid := r.makeDate(args, true)
90	if !valid {
91		return _NaN
92	}
93	return intToValue(timeToMsec(t))
94}
95
96func (r *Runtime) date_now(FunctionCall) Value {
97	return intToValue(timeToMsec(r.now()))
98}
99
100func (r *Runtime) dateproto_toString(call FunctionCall) Value {
101	obj := r.toObject(call.This)
102	if d, ok := obj.self.(*dateObject); ok {
103		if d.isSet() {
104			return asciiString(d.time().Format(dateTimeLayout))
105		} else {
106			return stringInvalidDate
107		}
108	}
109	panic(r.NewTypeError("Method Date.prototype.toString is called on incompatible receiver"))
110}
111
112func (r *Runtime) dateproto_toUTCString(call FunctionCall) Value {
113	obj := r.toObject(call.This)
114	if d, ok := obj.self.(*dateObject); ok {
115		if d.isSet() {
116			return asciiString(d.timeUTC().Format(utcDateTimeLayout))
117		} else {
118			return stringInvalidDate
119		}
120	}
121	panic(r.NewTypeError("Method Date.prototype.toUTCString is called on incompatible receiver"))
122}
123
124func (r *Runtime) dateproto_toISOString(call FunctionCall) Value {
125	obj := r.toObject(call.This)
126	if d, ok := obj.self.(*dateObject); ok {
127		if d.isSet() {
128			utc := d.timeUTC()
129			year := utc.Year()
130			if year >= -9999 && year <= 9999 {
131				return asciiString(utc.Format(isoDateTimeLayout))
132			}
133			// extended year
134			return asciiString(fmt.Sprintf("%+06d-", year) + utc.Format(isoDateTimeLayout[5:]))
135		} else {
136			panic(r.newError(r.global.RangeError, "Invalid time value"))
137		}
138	}
139	panic(r.NewTypeError("Method Date.prototype.toISOString is called on incompatible receiver"))
140}
141
142func (r *Runtime) dateproto_toJSON(call FunctionCall) Value {
143	obj := call.This.ToObject(r)
144	tv := obj.toPrimitiveNumber()
145	if f, ok := tv.(valueFloat); ok {
146		f := float64(f)
147		if math.IsNaN(f) || math.IsInf(f, 0) {
148			return _null
149		}
150	}
151
152	if toISO, ok := obj.self.getStr("toISOString", nil).(*Object); ok {
153		if toISO, ok := toISO.self.assertCallable(); ok {
154			return toISO(FunctionCall{
155				This: obj,
156			})
157		}
158	}
159
160	panic(r.NewTypeError("toISOString is not a function"))
161}
162
163func (r *Runtime) dateproto_toPrimitive(call FunctionCall) Value {
164	o := r.toObject(call.This)
165	arg := call.Argument(0)
166
167	if asciiString("string").StrictEquals(arg) || asciiString("default").StrictEquals(arg) {
168		return o.self.toPrimitiveString()
169	}
170	if asciiString("number").StrictEquals(arg) {
171		return o.self.toPrimitiveNumber()
172	}
173	panic(r.NewTypeError("Invalid hint: %s", arg))
174}
175
176func (r *Runtime) dateproto_toDateString(call FunctionCall) Value {
177	obj := r.toObject(call.This)
178	if d, ok := obj.self.(*dateObject); ok {
179		if d.isSet() {
180			return asciiString(d.time().Format(dateLayout))
181		} else {
182			return stringInvalidDate
183		}
184	}
185	panic(r.NewTypeError("Method Date.prototype.toDateString is called on incompatible receiver"))
186}
187
188func (r *Runtime) dateproto_toTimeString(call FunctionCall) Value {
189	obj := r.toObject(call.This)
190	if d, ok := obj.self.(*dateObject); ok {
191		if d.isSet() {
192			return asciiString(d.time().Format(timeLayout))
193		} else {
194			return stringInvalidDate
195		}
196	}
197	panic(r.NewTypeError("Method Date.prototype.toTimeString is called on incompatible receiver"))
198}
199
200func (r *Runtime) dateproto_toLocaleString(call FunctionCall) Value {
201	obj := r.toObject(call.This)
202	if d, ok := obj.self.(*dateObject); ok {
203		if d.isSet() {
204			return asciiString(d.time().Format(datetimeLayout_en_GB))
205		} else {
206			return stringInvalidDate
207		}
208	}
209	panic(r.NewTypeError("Method Date.prototype.toLocaleString is called on incompatible receiver"))
210}
211
212func (r *Runtime) dateproto_toLocaleDateString(call FunctionCall) Value {
213	obj := r.toObject(call.This)
214	if d, ok := obj.self.(*dateObject); ok {
215		if d.isSet() {
216			return asciiString(d.time().Format(dateLayout_en_GB))
217		} else {
218			return stringInvalidDate
219		}
220	}
221	panic(r.NewTypeError("Method Date.prototype.toLocaleDateString is called on incompatible receiver"))
222}
223
224func (r *Runtime) dateproto_toLocaleTimeString(call FunctionCall) Value {
225	obj := r.toObject(call.This)
226	if d, ok := obj.self.(*dateObject); ok {
227		if d.isSet() {
228			return asciiString(d.time().Format(timeLayout_en_GB))
229		} else {
230			return stringInvalidDate
231		}
232	}
233	panic(r.NewTypeError("Method Date.prototype.toLocaleTimeString is called on incompatible receiver"))
234}
235
236func (r *Runtime) dateproto_valueOf(call FunctionCall) Value {
237	obj := r.toObject(call.This)
238	if d, ok := obj.self.(*dateObject); ok {
239		if d.isSet() {
240			return intToValue(d.msec)
241		} else {
242			return _NaN
243		}
244	}
245	panic(r.NewTypeError("Method Date.prototype.valueOf is called on incompatible receiver"))
246}
247
248func (r *Runtime) dateproto_getTime(call FunctionCall) Value {
249	obj := r.toObject(call.This)
250	if d, ok := obj.self.(*dateObject); ok {
251		if d.isSet() {
252			return intToValue(d.msec)
253		} else {
254			return _NaN
255		}
256	}
257	panic(r.NewTypeError("Method Date.prototype.getTime is called on incompatible receiver"))
258}
259
260func (r *Runtime) dateproto_getFullYear(call FunctionCall) Value {
261	obj := r.toObject(call.This)
262	if d, ok := obj.self.(*dateObject); ok {
263		if d.isSet() {
264			return intToValue(int64(d.time().Year()))
265		} else {
266			return _NaN
267		}
268	}
269	panic(r.NewTypeError("Method Date.prototype.getFullYear is called on incompatible receiver"))
270}
271
272func (r *Runtime) dateproto_getUTCFullYear(call FunctionCall) Value {
273	obj := r.toObject(call.This)
274	if d, ok := obj.self.(*dateObject); ok {
275		if d.isSet() {
276			return intToValue(int64(d.timeUTC().Year()))
277		} else {
278			return _NaN
279		}
280	}
281	panic(r.NewTypeError("Method Date.prototype.getUTCFullYear is called on incompatible receiver"))
282}
283
284func (r *Runtime) dateproto_getMonth(call FunctionCall) Value {
285	obj := r.toObject(call.This)
286	if d, ok := obj.self.(*dateObject); ok {
287		if d.isSet() {
288			return intToValue(int64(d.time().Month()) - 1)
289		} else {
290			return _NaN
291		}
292	}
293	panic(r.NewTypeError("Method Date.prototype.getMonth is called on incompatible receiver"))
294}
295
296func (r *Runtime) dateproto_getUTCMonth(call FunctionCall) Value {
297	obj := r.toObject(call.This)
298	if d, ok := obj.self.(*dateObject); ok {
299		if d.isSet() {
300			return intToValue(int64(d.timeUTC().Month()) - 1)
301		} else {
302			return _NaN
303		}
304	}
305	panic(r.NewTypeError("Method Date.prototype.getUTCMonth is called on incompatible receiver"))
306}
307
308func (r *Runtime) dateproto_getHours(call FunctionCall) Value {
309	obj := r.toObject(call.This)
310	if d, ok := obj.self.(*dateObject); ok {
311		if d.isSet() {
312			return intToValue(int64(d.time().Hour()))
313		} else {
314			return _NaN
315		}
316	}
317	panic(r.NewTypeError("Method Date.prototype.getHours is called on incompatible receiver"))
318}
319
320func (r *Runtime) dateproto_getUTCHours(call FunctionCall) Value {
321	obj := r.toObject(call.This)
322	if d, ok := obj.self.(*dateObject); ok {
323		if d.isSet() {
324			return intToValue(int64(d.timeUTC().Hour()))
325		} else {
326			return _NaN
327		}
328	}
329	panic(r.NewTypeError("Method Date.prototype.getUTCHours is called on incompatible receiver"))
330}
331
332func (r *Runtime) dateproto_getDate(call FunctionCall) Value {
333	obj := r.toObject(call.This)
334	if d, ok := obj.self.(*dateObject); ok {
335		if d.isSet() {
336			return intToValue(int64(d.time().Day()))
337		} else {
338			return _NaN
339		}
340	}
341	panic(r.NewTypeError("Method Date.prototype.getDate is called on incompatible receiver"))
342}
343
344func (r *Runtime) dateproto_getUTCDate(call FunctionCall) Value {
345	obj := r.toObject(call.This)
346	if d, ok := obj.self.(*dateObject); ok {
347		if d.isSet() {
348			return intToValue(int64(d.timeUTC().Day()))
349		} else {
350			return _NaN
351		}
352	}
353	panic(r.NewTypeError("Method Date.prototype.getUTCDate is called on incompatible receiver"))
354}
355
356func (r *Runtime) dateproto_getDay(call FunctionCall) Value {
357	obj := r.toObject(call.This)
358	if d, ok := obj.self.(*dateObject); ok {
359		if d.isSet() {
360			return intToValue(int64(d.time().Weekday()))
361		} else {
362			return _NaN
363		}
364	}
365	panic(r.NewTypeError("Method Date.prototype.getDay is called on incompatible receiver"))
366}
367
368func (r *Runtime) dateproto_getUTCDay(call FunctionCall) Value {
369	obj := r.toObject(call.This)
370	if d, ok := obj.self.(*dateObject); ok {
371		if d.isSet() {
372			return intToValue(int64(d.timeUTC().Weekday()))
373		} else {
374			return _NaN
375		}
376	}
377	panic(r.NewTypeError("Method Date.prototype.getUTCDay is called on incompatible receiver"))
378}
379
380func (r *Runtime) dateproto_getMinutes(call FunctionCall) Value {
381	obj := r.toObject(call.This)
382	if d, ok := obj.self.(*dateObject); ok {
383		if d.isSet() {
384			return intToValue(int64(d.time().Minute()))
385		} else {
386			return _NaN
387		}
388	}
389	panic(r.NewTypeError("Method Date.prototype.getMinutes is called on incompatible receiver"))
390}
391
392func (r *Runtime) dateproto_getUTCMinutes(call FunctionCall) Value {
393	obj := r.toObject(call.This)
394	if d, ok := obj.self.(*dateObject); ok {
395		if d.isSet() {
396			return intToValue(int64(d.timeUTC().Minute()))
397		} else {
398			return _NaN
399		}
400	}
401	panic(r.NewTypeError("Method Date.prototype.getUTCMinutes is called on incompatible receiver"))
402}
403
404func (r *Runtime) dateproto_getSeconds(call FunctionCall) Value {
405	obj := r.toObject(call.This)
406	if d, ok := obj.self.(*dateObject); ok {
407		if d.isSet() {
408			return intToValue(int64(d.time().Second()))
409		} else {
410			return _NaN
411		}
412	}
413	panic(r.NewTypeError("Method Date.prototype.getSeconds is called on incompatible receiver"))
414}
415
416func (r *Runtime) dateproto_getUTCSeconds(call FunctionCall) Value {
417	obj := r.toObject(call.This)
418	if d, ok := obj.self.(*dateObject); ok {
419		if d.isSet() {
420			return intToValue(int64(d.timeUTC().Second()))
421		} else {
422			return _NaN
423		}
424	}
425	panic(r.NewTypeError("Method Date.prototype.getUTCSeconds is called on incompatible receiver"))
426}
427
428func (r *Runtime) dateproto_getMilliseconds(call FunctionCall) Value {
429	obj := r.toObject(call.This)
430	if d, ok := obj.self.(*dateObject); ok {
431		if d.isSet() {
432			return intToValue(int64(d.time().Nanosecond() / 1e6))
433		} else {
434			return _NaN
435		}
436	}
437	panic(r.NewTypeError("Method Date.prototype.getMilliseconds is called on incompatible receiver"))
438}
439
440func (r *Runtime) dateproto_getUTCMilliseconds(call FunctionCall) Value {
441	obj := r.toObject(call.This)
442	if d, ok := obj.self.(*dateObject); ok {
443		if d.isSet() {
444			return intToValue(int64(d.timeUTC().Nanosecond() / 1e6))
445		} else {
446			return _NaN
447		}
448	}
449	panic(r.NewTypeError("Method Date.prototype.getUTCMilliseconds is called on incompatible receiver"))
450}
451
452func (r *Runtime) dateproto_getTimezoneOffset(call FunctionCall) Value {
453	obj := r.toObject(call.This)
454	if d, ok := obj.self.(*dateObject); ok {
455		if d.isSet() {
456			_, offset := d.time().Zone()
457			return floatToValue(float64(-offset) / 60)
458		} else {
459			return _NaN
460		}
461	}
462	panic(r.NewTypeError("Method Date.prototype.getTimezoneOffset is called on incompatible receiver"))
463}
464
465func (r *Runtime) dateproto_setTime(call FunctionCall) Value {
466	obj := r.toObject(call.This)
467	if d, ok := obj.self.(*dateObject); ok {
468		n := call.Argument(0).ToNumber()
469		if IsNaN(n) {
470			d.unset()
471			return _NaN
472		}
473		return d.setTimeMs(n.ToInteger())
474	}
475	panic(r.NewTypeError("Method Date.prototype.setTime is called on incompatible receiver"))
476}
477
478// _norm returns nhi, nlo such that
479//	hi * base + lo == nhi * base + nlo
480//	0 <= nlo < base
481func _norm(hi, lo, base int64) (nhi, nlo int64, ok bool) {
482	if lo < 0 {
483		if hi == math.MinInt64 && lo <= -base {
484			// underflow
485			ok = false
486			return
487		}
488		n := (-lo-1)/base + 1
489		hi -= n
490		lo += n * base
491	}
492	if lo >= base {
493		if hi == math.MaxInt64 {
494			// overflow
495			ok = false
496			return
497		}
498		n := lo / base
499		hi += n
500		lo -= n * base
501	}
502	return hi, lo, true
503}
504
505func mkTime(year, m, day, hour, min, sec, nsec int64, loc *time.Location) (t time.Time, ok bool) {
506	year, m, ok = _norm(year, m, 12)
507	if !ok {
508		return
509	}
510
511	// Normalise nsec, sec, min, hour, overflowing into day.
512	sec, nsec, ok = _norm(sec, nsec, 1e9)
513	if !ok {
514		return
515	}
516	min, sec, ok = _norm(min, sec, 60)
517	if !ok {
518		return
519	}
520	hour, min, ok = _norm(hour, min, 60)
521	if !ok {
522		return
523	}
524	day, hour, ok = _norm(day, hour, 24)
525	if !ok {
526		return
527	}
528	if year > math.MaxInt32 || year < math.MinInt32 ||
529		day > math.MaxInt32 || day < math.MinInt32 ||
530		m >= math.MaxInt32 || m < math.MinInt32-1 {
531		return time.Time{}, false
532	}
533	month := time.Month(m) + 1
534	return time.Date(int(year), month, int(day), int(hour), int(min), int(sec), int(nsec), loc), true
535}
536
537func _intArg(call FunctionCall, argNum int) (int64, bool) {
538	n := call.Argument(argNum).ToNumber()
539	if IsNaN(n) {
540		return 0, false
541	}
542	return n.ToInteger(), true
543}
544
545func _dateSetYear(t time.Time, call FunctionCall, argNum int, utc bool) (time.Time, bool) {
546	var year int64
547	if argNum == 0 || argNum > 0 && argNum < len(call.Arguments) {
548		var ok bool
549		year, ok = _intArg(call, argNum)
550		if !ok {
551			return time.Time{}, false
552		}
553		if year >= 0 && year <= 99 {
554			year += 1900
555		}
556	} else {
557		year = int64(t.Year())
558	}
559
560	return _dateSetMonth(year, t, call, argNum+1, utc)
561}
562
563func _dateSetFullYear(t time.Time, call FunctionCall, argNum int, utc bool) (time.Time, bool) {
564	var year int64
565	if argNum == 0 || argNum > 0 && argNum < len(call.Arguments) {
566		var ok bool
567		year, ok = _intArg(call, argNum)
568		if !ok {
569			return time.Time{}, false
570		}
571	} else {
572		year = int64(t.Year())
573	}
574	return _dateSetMonth(year, t, call, argNum+1, utc)
575}
576
577func _dateSetMonth(year int64, t time.Time, call FunctionCall, argNum int, utc bool) (time.Time, bool) {
578	var mon int64
579	if argNum == 0 || argNum > 0 && argNum < len(call.Arguments) {
580		var ok bool
581		mon, ok = _intArg(call, argNum)
582		if !ok {
583			return time.Time{}, false
584		}
585	} else {
586		mon = int64(t.Month()) - 1
587	}
588
589	return _dateSetDay(year, mon, t, call, argNum+1, utc)
590}
591
592func _dateSetDay(year, mon int64, t time.Time, call FunctionCall, argNum int, utc bool) (time.Time, bool) {
593	var day int64
594	if argNum == 0 || argNum > 0 && argNum < len(call.Arguments) {
595		var ok bool
596		day, ok = _intArg(call, argNum)
597		if !ok {
598			return time.Time{}, false
599		}
600	} else {
601		day = int64(t.Day())
602	}
603
604	return _dateSetHours(year, mon, day, t, call, argNum+1, utc)
605}
606
607func _dateSetHours(year, mon, day int64, t time.Time, call FunctionCall, argNum int, utc bool) (time.Time, bool) {
608	var hours int64
609	if argNum == 0 || argNum > 0 && argNum < len(call.Arguments) {
610		var ok bool
611		hours, ok = _intArg(call, argNum)
612		if !ok {
613			return time.Time{}, false
614		}
615	} else {
616		hours = int64(t.Hour())
617	}
618	return _dateSetMinutes(year, mon, day, hours, t, call, argNum+1, utc)
619}
620
621func _dateSetMinutes(year, mon, day, hours int64, t time.Time, call FunctionCall, argNum int, utc bool) (time.Time, bool) {
622	var min int64
623	if argNum == 0 || argNum > 0 && argNum < len(call.Arguments) {
624		var ok bool
625		min, ok = _intArg(call, argNum)
626		if !ok {
627			return time.Time{}, false
628		}
629	} else {
630		min = int64(t.Minute())
631	}
632	return _dateSetSeconds(year, mon, day, hours, min, t, call, argNum+1, utc)
633}
634
635func _dateSetSeconds(year, mon, day, hours, min int64, t time.Time, call FunctionCall, argNum int, utc bool) (time.Time, bool) {
636	var sec int64
637	if argNum == 0 || argNum > 0 && argNum < len(call.Arguments) {
638		var ok bool
639		sec, ok = _intArg(call, argNum)
640		if !ok {
641			return time.Time{}, false
642		}
643	} else {
644		sec = int64(t.Second())
645	}
646	return _dateSetMilliseconds(year, mon, day, hours, min, sec, t, call, argNum+1, utc)
647}
648
649func _dateSetMilliseconds(year, mon, day, hours, min, sec int64, t time.Time, call FunctionCall, argNum int, utc bool) (time.Time, bool) {
650	var msec int64
651	if argNum == 0 || argNum > 0 && argNum < len(call.Arguments) {
652		var ok bool
653		msec, ok = _intArg(call, argNum)
654		if !ok {
655			return time.Time{}, false
656		}
657	} else {
658		msec = int64(t.Nanosecond() / 1e6)
659	}
660	var ok bool
661	sec, msec, ok = _norm(sec, msec, 1e3)
662	if !ok {
663		return time.Time{}, false
664	}
665
666	var loc *time.Location
667	if utc {
668		loc = time.UTC
669	} else {
670		loc = time.Local
671	}
672	r, ok := mkTime(year, mon, day, hours, min, sec, msec*1e6, loc)
673	if !ok {
674		return time.Time{}, false
675	}
676	if utc {
677		return r.In(time.Local), true
678	}
679	return r, true
680}
681
682func (r *Runtime) dateproto_setMilliseconds(call FunctionCall) Value {
683	obj := r.toObject(call.This)
684	if d, ok := obj.self.(*dateObject); ok {
685		if d.isSet() {
686			n := call.Argument(0).ToNumber()
687			if IsNaN(n) {
688				d.unset()
689				return _NaN
690			}
691			msec := n.ToInteger()
692			sec := d.msec / 1e3
693			var ok bool
694			sec, msec, ok = _norm(sec, msec, 1e3)
695			if !ok {
696				d.unset()
697				return _NaN
698			}
699			return d.setTimeMs(sec*1e3 + msec)
700		} else {
701			return _NaN
702		}
703	}
704	panic(r.NewTypeError("Method Date.prototype.setMilliseconds is called on incompatible receiver"))
705}
706
707func (r *Runtime) dateproto_setUTCMilliseconds(call FunctionCall) Value {
708	obj := r.toObject(call.This)
709	if d, ok := obj.self.(*dateObject); ok {
710		if d.isSet() {
711			n := call.Argument(0).ToNumber()
712			if IsNaN(n) {
713				d.unset()
714				return _NaN
715			}
716			msec := n.ToInteger()
717			sec := d.msec / 1e3
718			var ok bool
719			sec, msec, ok = _norm(sec, msec, 1e3)
720			if !ok {
721				d.unset()
722				return _NaN
723			}
724			return d.setTimeMs(sec*1e3 + msec)
725		} else {
726			return _NaN
727		}
728	}
729	panic(r.NewTypeError("Method Date.prototype.setUTCMilliseconds is called on incompatible receiver"))
730}
731
732func (r *Runtime) dateproto_setSeconds(call FunctionCall) Value {
733	obj := r.toObject(call.This)
734	if d, ok := obj.self.(*dateObject); ok {
735		if d.isSet() {
736			t, ok := _dateSetFullYear(d.time(), call, -5, false)
737			if !ok {
738				d.unset()
739				return _NaN
740			}
741			return d.setTimeMs(timeToMsec(t))
742		} else {
743			return _NaN
744		}
745	}
746	panic(r.NewTypeError("Method Date.prototype.setSeconds is called on incompatible receiver"))
747}
748
749func (r *Runtime) dateproto_setUTCSeconds(call FunctionCall) Value {
750	obj := r.toObject(call.This)
751	if d, ok := obj.self.(*dateObject); ok {
752		if d.isSet() {
753			t, ok := _dateSetFullYear(d.timeUTC(), call, -5, true)
754			if !ok {
755				d.unset()
756				return _NaN
757			}
758			return d.setTimeMs(timeToMsec(t))
759		} else {
760			return _NaN
761		}
762	}
763	panic(r.NewTypeError("Method Date.prototype.setUTCSeconds is called on incompatible receiver"))
764}
765
766func (r *Runtime) dateproto_setMinutes(call FunctionCall) Value {
767	obj := r.toObject(call.This)
768	if d, ok := obj.self.(*dateObject); ok {
769		if d.isSet() {
770			t, ok := _dateSetFullYear(d.time(), call, -4, false)
771			if !ok {
772				d.unset()
773				return _NaN
774			}
775			return d.setTimeMs(timeToMsec(t))
776		} else {
777			return _NaN
778		}
779	}
780	panic(r.NewTypeError("Method Date.prototype.setMinutes is called on incompatible receiver"))
781}
782
783func (r *Runtime) dateproto_setUTCMinutes(call FunctionCall) Value {
784	obj := r.toObject(call.This)
785	if d, ok := obj.self.(*dateObject); ok {
786		if d.isSet() {
787			t, ok := _dateSetFullYear(d.timeUTC(), call, -4, true)
788			if !ok {
789				d.unset()
790				return _NaN
791			}
792			return d.setTimeMs(timeToMsec(t))
793		} else {
794			return _NaN
795		}
796	}
797	panic(r.NewTypeError("Method Date.prototype.setUTCMinutes is called on incompatible receiver"))
798}
799
800func (r *Runtime) dateproto_setHours(call FunctionCall) Value {
801	obj := r.toObject(call.This)
802	if d, ok := obj.self.(*dateObject); ok {
803		if d.isSet() {
804			t, ok := _dateSetFullYear(d.time(), call, -3, false)
805			if !ok {
806				d.unset()
807				return _NaN
808			}
809			return d.setTimeMs(timeToMsec(t))
810		} else {
811			return _NaN
812		}
813	}
814	panic(r.NewTypeError("Method Date.prototype.setHours is called on incompatible receiver"))
815}
816
817func (r *Runtime) dateproto_setUTCHours(call FunctionCall) Value {
818	obj := r.toObject(call.This)
819	if d, ok := obj.self.(*dateObject); ok {
820		if d.isSet() {
821			t, ok := _dateSetFullYear(d.timeUTC(), call, -3, true)
822			if !ok {
823				d.unset()
824				return _NaN
825			}
826			return d.setTimeMs(timeToMsec(t))
827		} else {
828			return _NaN
829		}
830	}
831	panic(r.NewTypeError("Method Date.prototype.setUTCHours is called on incompatible receiver"))
832}
833
834func (r *Runtime) dateproto_setDate(call FunctionCall) Value {
835	obj := r.toObject(call.This)
836	if d, ok := obj.self.(*dateObject); ok {
837		if d.isSet() {
838			t, ok := _dateSetFullYear(d.time(), limitCallArgs(call, 1), -2, false)
839			if !ok {
840				d.unset()
841				return _NaN
842			}
843			return d.setTimeMs(timeToMsec(t))
844		} else {
845			return _NaN
846		}
847	}
848	panic(r.NewTypeError("Method Date.prototype.setDate is called on incompatible receiver"))
849}
850
851func (r *Runtime) dateproto_setUTCDate(call FunctionCall) Value {
852	obj := r.toObject(call.This)
853	if d, ok := obj.self.(*dateObject); ok {
854		if d.isSet() {
855			t, ok := _dateSetFullYear(d.timeUTC(), limitCallArgs(call, 1), -2, true)
856			if !ok {
857				d.unset()
858				return _NaN
859			}
860			return d.setTimeMs(timeToMsec(t))
861		} else {
862			return _NaN
863		}
864	}
865	panic(r.NewTypeError("Method Date.prototype.setUTCDate is called on incompatible receiver"))
866}
867
868func (r *Runtime) dateproto_setMonth(call FunctionCall) Value {
869	obj := r.toObject(call.This)
870	if d, ok := obj.self.(*dateObject); ok {
871		if d.isSet() {
872			t, ok := _dateSetFullYear(d.time(), limitCallArgs(call, 2), -1, false)
873			if !ok {
874				d.unset()
875				return _NaN
876			}
877			return d.setTimeMs(timeToMsec(t))
878		} else {
879			return _NaN
880		}
881	}
882	panic(r.NewTypeError("Method Date.prototype.setMonth is called on incompatible receiver"))
883}
884
885func (r *Runtime) dateproto_setUTCMonth(call FunctionCall) Value {
886	obj := r.toObject(call.This)
887	if d, ok := obj.self.(*dateObject); ok {
888		if d.isSet() {
889			t, ok := _dateSetFullYear(d.timeUTC(), limitCallArgs(call, 2), -1, true)
890			if !ok {
891				d.unset()
892				return _NaN
893			}
894			return d.setTimeMs(timeToMsec(t))
895		} else {
896			return _NaN
897		}
898	}
899	panic(r.NewTypeError("Method Date.prototype.setUTCMonth is called on incompatible receiver"))
900}
901
902func (r *Runtime) dateproto_setFullYear(call FunctionCall) Value {
903	obj := r.toObject(call.This)
904	if d, ok := obj.self.(*dateObject); ok {
905		var t time.Time
906		if d.isSet() {
907			t = d.time()
908		} else {
909			t = time.Date(1970, time.January, 1, 0, 0, 0, 0, time.Local)
910		}
911		t, ok := _dateSetFullYear(t, limitCallArgs(call, 3), 0, false)
912		if !ok {
913			d.unset()
914			return _NaN
915		}
916		return d.setTimeMs(timeToMsec(t))
917	}
918	panic(r.NewTypeError("Method Date.prototype.setFullYear is called on incompatible receiver"))
919}
920
921func (r *Runtime) dateproto_setUTCFullYear(call FunctionCall) Value {
922	obj := r.toObject(call.This)
923	if d, ok := obj.self.(*dateObject); ok {
924		var t time.Time
925		if d.isSet() {
926			t = d.timeUTC()
927		} else {
928			t = time.Date(1970, time.January, 1, 0, 0, 0, 0, time.UTC)
929		}
930		t, ok := _dateSetFullYear(t, limitCallArgs(call, 3), 0, true)
931		if !ok {
932			d.unset()
933			return _NaN
934		}
935		return d.setTimeMs(timeToMsec(t))
936	}
937	panic(r.NewTypeError("Method Date.prototype.setUTCFullYear is called on incompatible receiver"))
938}
939
940func (r *Runtime) createDateProto(val *Object) objectImpl {
941	o := &baseObject{
942		class:      classObject,
943		val:        val,
944		extensible: true,
945		prototype:  r.global.ObjectPrototype,
946	}
947	o.init()
948
949	o._putProp("constructor", r.global.Date, true, false, true)
950	o._putProp("toString", r.newNativeFunc(r.dateproto_toString, nil, "toString", nil, 0), true, false, true)
951	o._putProp("toDateString", r.newNativeFunc(r.dateproto_toDateString, nil, "toDateString", nil, 0), true, false, true)
952	o._putProp("toTimeString", r.newNativeFunc(r.dateproto_toTimeString, nil, "toTimeString", nil, 0), true, false, true)
953	o._putProp("toLocaleString", r.newNativeFunc(r.dateproto_toLocaleString, nil, "toLocaleString", nil, 0), true, false, true)
954	o._putProp("toLocaleDateString", r.newNativeFunc(r.dateproto_toLocaleDateString, nil, "toLocaleDateString", nil, 0), true, false, true)
955	o._putProp("toLocaleTimeString", r.newNativeFunc(r.dateproto_toLocaleTimeString, nil, "toLocaleTimeString", nil, 0), true, false, true)
956	o._putProp("valueOf", r.newNativeFunc(r.dateproto_valueOf, nil, "valueOf", nil, 0), true, false, true)
957	o._putProp("getTime", r.newNativeFunc(r.dateproto_getTime, nil, "getTime", nil, 0), true, false, true)
958	o._putProp("getFullYear", r.newNativeFunc(r.dateproto_getFullYear, nil, "getFullYear", nil, 0), true, false, true)
959	o._putProp("getUTCFullYear", r.newNativeFunc(r.dateproto_getUTCFullYear, nil, "getUTCFullYear", nil, 0), true, false, true)
960	o._putProp("getMonth", r.newNativeFunc(r.dateproto_getMonth, nil, "getMonth", nil, 0), true, false, true)
961	o._putProp("getUTCMonth", r.newNativeFunc(r.dateproto_getUTCMonth, nil, "getUTCMonth", nil, 0), true, false, true)
962	o._putProp("getDate", r.newNativeFunc(r.dateproto_getDate, nil, "getDate", nil, 0), true, false, true)
963	o._putProp("getUTCDate", r.newNativeFunc(r.dateproto_getUTCDate, nil, "getUTCDate", nil, 0), true, false, true)
964	o._putProp("getDay", r.newNativeFunc(r.dateproto_getDay, nil, "getDay", nil, 0), true, false, true)
965	o._putProp("getUTCDay", r.newNativeFunc(r.dateproto_getUTCDay, nil, "getUTCDay", nil, 0), true, false, true)
966	o._putProp("getHours", r.newNativeFunc(r.dateproto_getHours, nil, "getHours", nil, 0), true, false, true)
967	o._putProp("getUTCHours", r.newNativeFunc(r.dateproto_getUTCHours, nil, "getUTCHours", nil, 0), true, false, true)
968	o._putProp("getMinutes", r.newNativeFunc(r.dateproto_getMinutes, nil, "getMinutes", nil, 0), true, false, true)
969	o._putProp("getUTCMinutes", r.newNativeFunc(r.dateproto_getUTCMinutes, nil, "getUTCMinutes", nil, 0), true, false, true)
970	o._putProp("getSeconds", r.newNativeFunc(r.dateproto_getSeconds, nil, "getSeconds", nil, 0), true, false, true)
971	o._putProp("getUTCSeconds", r.newNativeFunc(r.dateproto_getUTCSeconds, nil, "getUTCSeconds", nil, 0), true, false, true)
972	o._putProp("getMilliseconds", r.newNativeFunc(r.dateproto_getMilliseconds, nil, "getMilliseconds", nil, 0), true, false, true)
973	o._putProp("getUTCMilliseconds", r.newNativeFunc(r.dateproto_getUTCMilliseconds, nil, "getUTCMilliseconds", nil, 0), true, false, true)
974	o._putProp("getTimezoneOffset", r.newNativeFunc(r.dateproto_getTimezoneOffset, nil, "getTimezoneOffset", nil, 0), true, false, true)
975	o._putProp("setTime", r.newNativeFunc(r.dateproto_setTime, nil, "setTime", nil, 1), true, false, true)
976	o._putProp("setMilliseconds", r.newNativeFunc(r.dateproto_setMilliseconds, nil, "setMilliseconds", nil, 1), true, false, true)
977	o._putProp("setUTCMilliseconds", r.newNativeFunc(r.dateproto_setUTCMilliseconds, nil, "setUTCMilliseconds", nil, 1), true, false, true)
978	o._putProp("setSeconds", r.newNativeFunc(r.dateproto_setSeconds, nil, "setSeconds", nil, 2), true, false, true)
979	o._putProp("setUTCSeconds", r.newNativeFunc(r.dateproto_setUTCSeconds, nil, "setUTCSeconds", nil, 2), true, false, true)
980	o._putProp("setMinutes", r.newNativeFunc(r.dateproto_setMinutes, nil, "setMinutes", nil, 3), true, false, true)
981	o._putProp("setUTCMinutes", r.newNativeFunc(r.dateproto_setUTCMinutes, nil, "setUTCMinutes", nil, 3), true, false, true)
982	o._putProp("setHours", r.newNativeFunc(r.dateproto_setHours, nil, "setHours", nil, 4), true, false, true)
983	o._putProp("setUTCHours", r.newNativeFunc(r.dateproto_setUTCHours, nil, "setUTCHours", nil, 4), true, false, true)
984	o._putProp("setDate", r.newNativeFunc(r.dateproto_setDate, nil, "setDate", nil, 1), true, false, true)
985	o._putProp("setUTCDate", r.newNativeFunc(r.dateproto_setUTCDate, nil, "setUTCDate", nil, 1), true, false, true)
986	o._putProp("setMonth", r.newNativeFunc(r.dateproto_setMonth, nil, "setMonth", nil, 2), true, false, true)
987	o._putProp("setUTCMonth", r.newNativeFunc(r.dateproto_setUTCMonth, nil, "setUTCMonth", nil, 2), true, false, true)
988	o._putProp("setFullYear", r.newNativeFunc(r.dateproto_setFullYear, nil, "setFullYear", nil, 3), true, false, true)
989	o._putProp("setUTCFullYear", r.newNativeFunc(r.dateproto_setUTCFullYear, nil, "setUTCFullYear", nil, 3), true, false, true)
990	o._putProp("toUTCString", r.newNativeFunc(r.dateproto_toUTCString, nil, "toUTCString", nil, 0), true, false, true)
991	o._putProp("toISOString", r.newNativeFunc(r.dateproto_toISOString, nil, "toISOString", nil, 0), true, false, true)
992	o._putProp("toJSON", r.newNativeFunc(r.dateproto_toJSON, nil, "toJSON", nil, 1), true, false, true)
993
994	o._putSym(SymToPrimitive, valueProp(r.newNativeFunc(r.dateproto_toPrimitive, nil, "[Symbol.toPrimitive]", nil, 1), false, false, true))
995
996	return o
997}
998
999func (r *Runtime) createDate(val *Object) objectImpl {
1000	o := r.newNativeFuncObj(val, r.builtin_date, r.builtin_newDate, "Date", r.global.DatePrototype, 7)
1001
1002	o._putProp("parse", r.newNativeFunc(r.date_parse, nil, "parse", nil, 1), true, false, true)
1003	o._putProp("UTC", r.newNativeFunc(r.date_UTC, nil, "UTC", nil, 7), true, false, true)
1004	o._putProp("now", r.newNativeFunc(r.date_now, nil, "now", nil, 0), true, false, true)
1005
1006	return o
1007}
1008
1009func (r *Runtime) initDate() {
1010	r.global.DatePrototype = r.newLazyObject(r.createDateProto)
1011
1012	r.global.Date = r.newLazyObject(r.createDate)
1013	r.addToGlobal("Date", r.global.Date)
1014}
1015