1 /*
2 * Copyright 2008 Jacek Caban for CodeWeavers
3 * Copyright 2009 Piotr Caban
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
18 */
19
20 #ifdef __REACTOS__
21 #include <wine/config.h>
22 #include <wine/port.h>
23 #endif
24
25 #include <limits.h>
26 #include <math.h>
27 #include <assert.h>
28
29 #include "jscript.h"
30
31 #include "wine/debug.h"
32
33 WINE_DEFAULT_DEBUG_CHANNEL(jscript);
34
35 /* 1601 to 1970 is 369 years plus 89 leap days */
36 #define TIME_EPOCH ((ULONGLONG)(369 * 365 + 89) * 86400 * 1000)
37
38 typedef struct {
39 jsdisp_t dispex;
40
41 /* ECMA-262 3rd Edition 15.9.1.1 */
42 DOUBLE time;
43
44 LONG bias;
45 SYSTEMTIME standardDate;
46 LONG standardBias;
47 SYSTEMTIME daylightDate;
48 LONG daylightBias;
49 } DateInstance;
50
51 static const WCHAR toStringW[] = {'t','o','S','t','r','i','n','g',0};
52 static const WCHAR toLocaleStringW[] = {'t','o','L','o','c','a','l','e','S','t','r','i','n','g',0};
53 static const WCHAR valueOfW[] = {'v','a','l','u','e','O','f',0};
54 static const WCHAR toISOStringW[] = {'t','o','I','S','O','S','t','r','i','n','g',0};
55 static const WCHAR toUTCStringW[] = {'t','o','U','T','C','S','t','r','i','n','g',0};
56 static const WCHAR toGMTStringW[] = {'t','o','G','M','T','S','t','r','i','n','g',0};
57 static const WCHAR toDateStringW[] = {'t','o','D','a','t','e','S','t','r','i','n','g',0};
58 static const WCHAR toTimeStringW[] = {'t','o','T','i','m','e','S','t','r','i','n','g',0};
59 static const WCHAR toLocaleDateStringW[] = {'t','o','L','o','c','a','l','e','D','a','t','e','S','t','r','i','n','g',0};
60 static const WCHAR toLocaleTimeStringW[] = {'t','o','L','o','c','a','l','e','T','i','m','e','S','t','r','i','n','g',0};
61 static const WCHAR getTimeW[] = {'g','e','t','T','i','m','e',0};
62 static const WCHAR getFullYearW[] = {'g','e','t','F','u','l','l','Y','e','a','r',0};
63 static const WCHAR getUTCFullYearW[] = {'g','e','t','U','T','C','F','u','l','l','Y','e','a','r',0};
64 static const WCHAR getMonthW[] = {'g','e','t','M','o','n','t','h',0};
65 static const WCHAR getUTCMonthW[] = {'g','e','t','U','T','C','M','o','n','t','h',0};
66 static const WCHAR getDateW[] = {'g','e','t','D','a','t','e',0};
67 static const WCHAR getUTCDateW[] = {'g','e','t','U','T','C','D','a','t','e',0};
68 static const WCHAR getDayW[] = {'g','e','t','D','a','y',0};
69 static const WCHAR getUTCDayW[] = {'g','e','t','U','T','C','D','a','y',0};
70 static const WCHAR getHoursW[] = {'g','e','t','H','o','u','r','s',0};
71 static const WCHAR getUTCHoursW[] = {'g','e','t','U','T','C','H','o','u','r','s',0};
72 static const WCHAR getMinutesW[] = {'g','e','t','M','i','n','u','t','e','s',0};
73 static const WCHAR getUTCMinutesW[] = {'g','e','t','U','T','C','M','i','n','u','t','e','s',0};
74 static const WCHAR getSecondsW[] = {'g','e','t','S','e','c','o','n','d','s',0};
75 static const WCHAR getUTCSecondsW[] = {'g','e','t','U','T','C','S','e','c','o','n','d','s',0};
76 static const WCHAR getMillisecondsW[] = {'g','e','t','M','i','l','l','i','s','e','c','o','n','d','s',0};
77 static const WCHAR getUTCMillisecondsW[] = {'g','e','t','U','T','C','M','i','l','l','i','s','e','c','o','n','d','s',0};
78 static const WCHAR getTimezoneOffsetW[] = {'g','e','t','T','i','m','e','z','o','n','e','O','f','f','s','e','t',0};
79 static const WCHAR setTimeW[] = {'s','e','t','T','i','m','e',0};
80 static const WCHAR setMillisecondsW[] = {'s','e','t','M','i','l','l','i','s','e','c','o','n','d','s',0};
81 static const WCHAR setUTCMillisecondsW[] = {'s','e','t','U','T','C','M','i','l','l','i','s','e','c','o','n','d','s',0};
82 static const WCHAR setSecondsW[] = {'s','e','t','S','e','c','o','n','d','s',0};
83 static const WCHAR setUTCSecondsW[] = {'s','e','t','U','T','C','S','e','c','o','n','d','s',0};
84 static const WCHAR setMinutesW[] = {'s','e','t','M','i','n','u','t','e','s',0};
85 static const WCHAR setUTCMinutesW[] = {'s','e','t','U','T','C','M','i','n','u','t','e','s',0};
86 static const WCHAR setHoursW[] = {'s','e','t','H','o','u','r','s',0};
87 static const WCHAR setUTCHoursW[] = {'s','e','t','U','T','C','H','o','u','r','s',0};
88 static const WCHAR setDateW[] = {'s','e','t','D','a','t','e',0};
89 static const WCHAR setUTCDateW[] = {'s','e','t','U','T','C','D','a','t','e',0};
90 static const WCHAR setMonthW[] = {'s','e','t','M','o','n','t','h',0};
91 static const WCHAR setUTCMonthW[] = {'s','e','t','U','T','C','M','o','n','t','h',0};
92 static const WCHAR setFullYearW[] = {'s','e','t','F','u','l','l','Y','e','a','r',0};
93 static const WCHAR setUTCFullYearW[] = {'s','e','t','U','T','C','F','u','l','l','Y','e','a','r',0};
94 static const WCHAR getYearW[] = {'g','e','t','Y','e','a','r',0};
95 static const WCHAR setYearW[] = {'s','e','t','Y','e','a','r',0};
96
97 static const WCHAR UTCW[] = {'U','T','C',0};
98 static const WCHAR nowW[] = {'n','o','w',0};
99 static const WCHAR parseW[] = {'p','a','r','s','e',0};
100
date_from_jsdisp(jsdisp_t * jsdisp)101 static inline DateInstance *date_from_jsdisp(jsdisp_t *jsdisp)
102 {
103 return CONTAINING_RECORD(jsdisp, DateInstance, dispex);
104 }
105
date_this(vdisp_t * jsthis)106 static inline DateInstance *date_this(vdisp_t *jsthis)
107 {
108 return is_vclass(jsthis, JSCLASS_DATE) ? date_from_jsdisp(jsthis->u.jsdisp) : NULL;
109 }
110
111 /*ECMA-262 3rd Edition 15.9.1.2 */
112 #define MS_PER_DAY 86400000
113 #define MS_PER_HOUR 3600000
114 #define MS_PER_MINUTE 60000
115
116 /* ECMA-262 3rd Edition 15.9.1.2 */
day(DOUBLE time)117 static inline DOUBLE day(DOUBLE time)
118 {
119 return floor(time / MS_PER_DAY);
120 }
121
122 /* ECMA-262 3rd Edition 15.9.1.2 */
time_within_day(DOUBLE time)123 static inline DOUBLE time_within_day(DOUBLE time)
124 {
125 DOUBLE ret;
126
127 ret = fmod(time, MS_PER_DAY);
128 if(ret < 0)
129 ret += MS_PER_DAY;
130
131 return ret;
132 }
133
134 /* ECMA-262 3rd Edition 15.9.1.3 */
days_in_year(DOUBLE year)135 static inline DOUBLE days_in_year(DOUBLE year)
136 {
137 int y;
138
139 if(year != (int)year)
140 return NAN;
141
142 y = year;
143 if(y%4 != 0) return 365;
144 if(y%100 != 0) return 366;
145 if(y%400 != 0) return 365;
146 return 366;
147 }
148
149 /* ECMA-262 3rd Edition 15.9.1.3 */
day_from_year(DOUBLE year)150 static inline DOUBLE day_from_year(DOUBLE year)
151 {
152 if(year != (int)year)
153 return NAN;
154
155 return floor(365.0*(year-1970) + floor((year-1969)/4)
156 - floor((year-1901)/100) + floor((year-1601)/400));
157 }
158
day_from_month(int month,int in_leap_year)159 static inline int day_from_month(int month, int in_leap_year)
160 {
161 switch(month)
162 {
163 case 0:
164 return 0;
165 case 1:
166 return 31;
167 case 2:
168 return 59+in_leap_year;
169 case 3:
170 return 90+in_leap_year;
171 case 4:
172 return 120+in_leap_year;
173 case 5:
174 return 151+in_leap_year;
175 case 6:
176 return 181+in_leap_year;
177 case 7:
178 return 212+in_leap_year;
179 case 8:
180 return 243+in_leap_year;
181 case 9:
182 return 273+in_leap_year;
183 case 10:
184 return 304+in_leap_year;
185 default:
186 return 334+in_leap_year;
187 }
188 }
189
190 /* ECMA-262 3rd Edition 15.9.1.3 */
time_from_year(DOUBLE year)191 static inline DOUBLE time_from_year(DOUBLE year)
192 {
193 return MS_PER_DAY*day_from_year(year);
194 }
195
196 /* ECMA-262 3rd Edition 15.9.1.3 */
year_from_time(DOUBLE time)197 static inline DOUBLE year_from_time(DOUBLE time)
198 {
199 int y;
200
201 if(isnan(time))
202 return NAN;
203
204 y = 1970 + time/365.25/MS_PER_DAY;
205
206 if(time_from_year(y) > time)
207 while(time_from_year(y) > time) y--;
208 else
209 while(time_from_year(y+1)<=time) y++;
210
211 return y;
212 }
213
214 /* ECMA-262 3rd Edition 15.9.1.3 */
in_leap_year(DOUBLE time)215 static inline int in_leap_year(DOUBLE time)
216 {
217 if(days_in_year(year_from_time(time))==366)
218 return 1;
219 return 0;
220 }
221
222 /* ECMA-262 3rd Edition 15.9.1.4 */
day_within_year(DOUBLE time)223 static inline int day_within_year(DOUBLE time)
224 {
225 return day(time) - day_from_year(year_from_time(time));
226 }
227
228 /* ECMA-262 3rd Edition 15.9.1.4 */
month_from_time(DOUBLE time)229 static inline DOUBLE month_from_time(DOUBLE time)
230 {
231 int ily = in_leap_year(time);
232 int dwy = day_within_year(time);
233
234 if(isnan(time))
235 return NAN;
236
237 if(0<=dwy && dwy<31) return 0;
238 if(dwy < 59+ily) return 1;
239 if(dwy < 90+ily) return 2;
240 if(dwy < 120+ily) return 3;
241 if(dwy < 151+ily) return 4;
242 if(dwy < 181+ily) return 5;
243 if(dwy < 212+ily) return 6;
244 if(dwy < 243+ily) return 7;
245 if(dwy < 273+ily) return 8;
246 if(dwy < 304+ily) return 9;
247 if(dwy < 334+ily) return 10;
248 return 11;
249 }
250
251 /* ECMA-262 3rd Edition 15.9.1.5 */
date_from_time(DOUBLE time)252 static inline DOUBLE date_from_time(DOUBLE time)
253 {
254 int dwy = day_within_year(time);
255 int ily = in_leap_year(time);
256 int mft = month_from_time(time);
257
258 if(isnan(time))
259 return NAN;
260
261 if(mft==0) return dwy+1;
262 if(mft==1) return dwy-30;
263 if(mft==2) return dwy-58-ily;
264 if(mft==3) return dwy-89-ily;
265 if(mft==4) return dwy-119-ily;
266 if(mft==5) return dwy-150-ily;
267 if(mft==6) return dwy-180-ily;
268 if(mft==7) return dwy-211-ily;
269 if(mft==8) return dwy-242-ily;
270 if(mft==9) return dwy-272-ily;
271 if(mft==10) return dwy-303-ily;
272 return dwy-333-ily;
273 }
274
275 /* ECMA-262 3rd Edition 15.9.1.6 */
week_day(DOUBLE time)276 static inline DOUBLE week_day(DOUBLE time)
277 {
278 DOUBLE ret;
279
280 if(isnan(time))
281 return NAN;
282
283 ret = fmod(day(time)+4, 7);
284 if(ret<0) ret += 7;
285
286 return ret;
287 }
288
convert_time(int year,SYSTEMTIME st)289 static inline DOUBLE convert_time(int year, SYSTEMTIME st)
290 {
291 DOUBLE time;
292 int set_week_day;
293
294 if(st.wMonth == 0)
295 return NAN;
296
297 if(st.wYear != 0)
298 year = st.wYear;
299
300 time = time_from_year(year);
301 time += (DOUBLE)day_from_month(st.wMonth-1, in_leap_year(time)) * MS_PER_DAY;
302
303 if(st.wYear == 0) {
304 set_week_day = st.wDayOfWeek-week_day(time);
305 if(set_week_day < 0)
306 set_week_day += 7;
307 time += set_week_day * MS_PER_DAY;
308
309 time += (DOUBLE)(st.wDay-1) * 7 * MS_PER_DAY;
310 if(month_from_time(time) != st.wMonth-1)
311 time -= 7 * MS_PER_DAY;
312 }
313 else
314 time += st.wDay * MS_PER_DAY;
315
316 time += st.wHour * MS_PER_HOUR;
317 time += st.wMinute * MS_PER_MINUTE;
318
319 return time;
320 }
321
322 /* ECMA-262 3rd Edition 15.9.1.9 */
daylight_saving_ta(DOUBLE time,DateInstance * date)323 static inline DOUBLE daylight_saving_ta(DOUBLE time, DateInstance *date)
324 {
325 int year = year_from_time(time);
326 DOUBLE standardTime, daylightTime;
327
328 if(isnan(time))
329 return 0;
330
331 standardTime = convert_time(year, date->standardDate);
332 daylightTime = convert_time(year, date->daylightDate);
333
334 if(isnan(standardTime) || isnan(daylightTime))
335 return 0;
336 else if(standardTime > daylightTime) {
337 if(daylightTime <= time && time < standardTime)
338 return date->daylightBias;
339
340 return date->standardBias;
341 }
342 else {
343 if(standardTime <= time && time < daylightTime)
344 return date->standardBias;
345
346 return date->daylightBias;
347 }
348 }
349
350 /* ECMA-262 3rd Edition 15.9.1.9 */
local_time(DOUBLE time,DateInstance * date)351 static inline DOUBLE local_time(DOUBLE time, DateInstance *date)
352 {
353 return time - (daylight_saving_ta(time, date)+date->bias)*MS_PER_MINUTE;
354 }
355
356 /* ECMA-262 3rd Edition 15.9.1.9 */
utc(DOUBLE time,DateInstance * date)357 static inline DOUBLE utc(DOUBLE time, DateInstance *date)
358 {
359 time += date->bias * MS_PER_MINUTE;
360 return time + daylight_saving_ta(time, date)*MS_PER_MINUTE;
361 }
362
363 /* ECMA-262 3rd Edition 15.9.1.10 */
hour_from_time(DOUBLE time)364 static inline DOUBLE hour_from_time(DOUBLE time)
365 {
366 DOUBLE ret;
367
368 if(isnan(time))
369 return NAN;
370
371 ret = fmod(floor(time/MS_PER_HOUR), 24);
372 if(ret<0) ret += 24;
373
374 return ret;
375 }
376
377 /* ECMA-262 3rd Edition 15.9.1.10 */
min_from_time(DOUBLE time)378 static inline DOUBLE min_from_time(DOUBLE time)
379 {
380 DOUBLE ret;
381
382 if(isnan(time))
383 return NAN;
384
385 ret = fmod(floor(time/MS_PER_MINUTE), 60);
386 if(ret<0) ret += 60;
387
388 return ret;
389 }
390
391 /* ECMA-262 3rd Edition 15.9.1.10 */
sec_from_time(DOUBLE time)392 static inline DOUBLE sec_from_time(DOUBLE time)
393 {
394 DOUBLE ret;
395
396 if(isnan(time))
397 return NAN;
398
399 ret = fmod(floor(time/1000), 60);
400 if(ret<0) ret += 60;
401
402 return ret;
403 }
404
405 /* ECMA-262 3rd Edition 15.9.1.10 */
ms_from_time(DOUBLE time)406 static inline DOUBLE ms_from_time(DOUBLE time)
407 {
408 DOUBLE ret;
409
410 if(isnan(time))
411 return NAN;
412
413 ret = fmod(time, 1000);
414 if(ret<0) ret += 1000;
415
416 return ret;
417 }
418
419 /* ECMA-262 3rd Edition 15.9.1.11 */
make_time(DOUBLE hour,DOUBLE min,DOUBLE sec,DOUBLE ms)420 static inline DOUBLE make_time(DOUBLE hour, DOUBLE min, DOUBLE sec, DOUBLE ms)
421 {
422 return hour*MS_PER_HOUR + min*MS_PER_MINUTE + sec*1000 + ms;
423 }
424
425 /* ECMA-262 3rd Edition 15.9.1.12 */
make_day(DOUBLE year,DOUBLE month,DOUBLE day)426 static inline DOUBLE make_day(DOUBLE year, DOUBLE month, DOUBLE day)
427 {
428 DOUBLE time;
429
430 year += floor(month/12);
431
432 month = fmod(month, 12);
433 if(month<0) month += 12;
434
435 time = time_from_year(year);
436
437 day += floor(time / MS_PER_DAY);
438 day += day_from_month(month, in_leap_year(time));
439
440 return day-1;
441 }
442
443 /* ECMA-262 3rd Edition 15.9.1.13 */
make_date(DOUBLE day,DOUBLE time)444 static inline DOUBLE make_date(DOUBLE day, DOUBLE time)
445 {
446 return day*MS_PER_DAY + time;
447 }
448
449 /* ECMA-262 3rd Edition 15.9.1.14 */
time_clip(DOUBLE time)450 static inline DOUBLE time_clip(DOUBLE time)
451 {
452 if(8.64e15 < time || time < -8.64e15) {
453 return NAN;
454 }
455
456 return floor(time);
457 }
458
date_now(void)459 static double date_now(void)
460 {
461 FILETIME ftime;
462 LONGLONG time;
463
464 GetSystemTimeAsFileTime(&ftime);
465 time = ((LONGLONG)ftime.dwHighDateTime << 32) + ftime.dwLowDateTime;
466
467 return time/10000 - TIME_EPOCH;
468 }
469
create_systemtime(DOUBLE time)470 static SYSTEMTIME create_systemtime(DOUBLE time)
471 {
472 SYSTEMTIME st;
473
474 st.wYear = year_from_time(time);
475 st.wMonth = month_from_time(time) + 1;
476 st.wDayOfWeek = week_day(time);
477 st.wDay = date_from_time(time);
478 st.wHour = hour_from_time(time);
479 st.wMinute = min_from_time(time);
480 st.wSecond = sec_from_time(time);
481 st.wMilliseconds = ms_from_time(time);
482
483 return st;
484 }
485
date_to_string(DOUBLE time,BOOL show_offset,int offset,jsval_t * r)486 static inline HRESULT date_to_string(DOUBLE time, BOOL show_offset, int offset, jsval_t *r)
487 {
488 static const WCHAR formatW[] = { '%','s',' ','%','s',' ','%','d',' ',
489 '%','0','2','d',':','%','0','2','d',':','%','0','2','d',' ',
490 'U','T','C','%','c','%','0','2','d','%','0','2','d',' ','%','d','%','s',0 };
491 static const WCHAR formatUTCW[] = { '%','s',' ','%','s',' ','%','d',' ',
492 '%','0','2','d',':','%','0','2','d',':','%','0','2','d',' ',
493 'U','T','C',' ','%','d','%','s',0 };
494 static const WCHAR formatNoOffsetW[] = { '%','s',' ','%','s',' ',
495 '%','d',' ','%','0','2','d',':','%','0','2','d',':',
496 '%','0','2','d',' ','%','d','%','s',0 };
497 static const WCHAR ADW[] = { 0 };
498 static const WCHAR BCW[] = { ' ','B','.','C','.',0 };
499
500 static const DWORD week_ids[] = { LOCALE_SABBREVDAYNAME7, LOCALE_SABBREVDAYNAME1,
501 LOCALE_SABBREVDAYNAME2, LOCALE_SABBREVDAYNAME3, LOCALE_SABBREVDAYNAME4,
502 LOCALE_SABBREVDAYNAME5, LOCALE_SABBREVDAYNAME6 };
503 static const DWORD month_ids[] = { LOCALE_SABBREVMONTHNAME1, LOCALE_SABBREVMONTHNAME2,
504 LOCALE_SABBREVMONTHNAME3, LOCALE_SABBREVMONTHNAME4,
505 LOCALE_SABBREVMONTHNAME5, LOCALE_SABBREVMONTHNAME6,
506 LOCALE_SABBREVMONTHNAME7, LOCALE_SABBREVMONTHNAME8,
507 LOCALE_SABBREVMONTHNAME9, LOCALE_SABBREVMONTHNAME10,
508 LOCALE_SABBREVMONTHNAME11, LOCALE_SABBREVMONTHNAME12 };
509
510 BOOL formatAD = TRUE;
511 WCHAR week[64], month[64];
512 WCHAR buf[192];
513 jsstr_t *date_jsstr;
514 int year, day;
515 DWORD lcid_en;
516 WCHAR sign = '-';
517
518 if(isnan(time)) {
519 if(r)
520 *r = jsval_string(jsstr_nan());
521 return S_OK;
522 }
523
524 if(r) {
525 lcid_en = MAKELCID(MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),SORT_DEFAULT);
526
527 week[0] = 0;
528 GetLocaleInfoW(lcid_en, week_ids[(int)week_day(time)], week, ARRAY_SIZE(week));
529
530 month[0] = 0;
531 GetLocaleInfoW(lcid_en, month_ids[(int)month_from_time(time)], month, ARRAY_SIZE(month));
532
533 year = year_from_time(time);
534 if(year<0) {
535 formatAD = FALSE;
536 year = -year+1;
537 }
538
539 day = date_from_time(time);
540
541 if(offset < 0) {
542 sign = '+';
543 offset = -offset;
544 }
545
546 if(!show_offset)
547 swprintf(buf, formatNoOffsetW, week, month, day,
548 (int)hour_from_time(time), (int)min_from_time(time),
549 (int)sec_from_time(time), year, formatAD?ADW:BCW);
550 else if(offset)
551 swprintf(buf, formatW, week, month, day,
552 (int)hour_from_time(time), (int)min_from_time(time),
553 (int)sec_from_time(time), sign, offset/60, offset%60,
554 year, formatAD?ADW:BCW);
555 else
556 swprintf(buf, formatUTCW, week, month, day,
557 (int)hour_from_time(time), (int)min_from_time(time),
558 (int)sec_from_time(time), year, formatAD?ADW:BCW);
559
560 date_jsstr = jsstr_alloc(buf);
561 if(!date_jsstr)
562 return E_OUTOFMEMORY;
563
564 *r = jsval_string(date_jsstr);
565 }
566 return S_OK;
567 }
568
569 /* ECMA-262 3rd Edition 15.9.1.2 */
dateobj_to_string(DateInstance * date,jsval_t * r)570 static HRESULT dateobj_to_string(DateInstance *date, jsval_t *r)
571 {
572 DOUBLE time;
573 int offset;
574
575 time = local_time(date->time, date);
576 offset = date->bias +
577 daylight_saving_ta(time, date);
578
579 return date_to_string(time, TRUE, offset, r);
580 }
581
Date_toString(script_ctx_t * ctx,vdisp_t * jsthis,WORD flags,unsigned argc,jsval_t * argv,jsval_t * r)582 static HRESULT Date_toString(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r)
583 {
584 DateInstance *date;
585
586 TRACE("\n");
587
588 if(!(date = date_this(jsthis)))
589 return throw_type_error(ctx, JS_E_DATE_EXPECTED, NULL);
590
591 return dateobj_to_string(date, r);
592 }
593
594 /* ECMA-262 3rd Edition 15.9.1.5 */
Date_toLocaleString(script_ctx_t * ctx,vdisp_t * jsthis,WORD flags,unsigned argc,jsval_t * argv,jsval_t * r)595 static HRESULT Date_toLocaleString(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
596 jsval_t *r)
597 {
598 SYSTEMTIME st;
599 DateInstance *date;
600 jsstr_t *date_str;
601 int date_len, time_len;
602
603 TRACE("\n");
604
605 if(!(date = date_this(jsthis)))
606 return throw_type_error(ctx, JS_E_DATE_EXPECTED, NULL);
607
608 if(isnan(date->time)) {
609 if(r)
610 *r = jsval_string(jsstr_nan());
611 return S_OK;
612 }
613
614 st = create_systemtime(local_time(date->time, date));
615
616 if(st.wYear<1601 || st.wYear>9999)
617 return dateobj_to_string(date, r);
618
619 if(r) {
620 WCHAR *ptr;
621
622 date_len = GetDateFormatW(ctx->lcid, DATE_LONGDATE, &st, NULL, NULL, 0);
623 time_len = GetTimeFormatW(ctx->lcid, 0, &st, NULL, NULL, 0);
624
625 date_str = jsstr_alloc_buf(date_len+time_len-1, &ptr);
626 if(!date_str)
627 return E_OUTOFMEMORY;
628
629 GetDateFormatW(ctx->lcid, DATE_LONGDATE, &st, NULL, ptr, date_len);
630 GetTimeFormatW(ctx->lcid, 0, &st, NULL, ptr+date_len, time_len);
631 ptr[date_len-1] = ' ';
632
633 *r = jsval_string(date_str);
634 }
635 return S_OK;
636 }
637
Date_toISOString(script_ctx_t * ctx,vdisp_t * jsthis,WORD flags,unsigned argc,jsval_t * argv,jsval_t * r)638 static HRESULT Date_toISOString(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
639 jsval_t *r)
640 {
641 DateInstance *date;
642 WCHAR buf[64], *p = buf;
643 double year;
644
645 static const WCHAR short_year_formatW[] = {'%','0','4','d',0};
646 static const WCHAR long_year_formatW[] = {'%','0','6','d',0};
647 static const WCHAR formatW[] = {'-','%','0','2','d','-','%','0','2','d',
648 'T','%','0','2','d',':','%','0','2','d',':','%','0','2','d','.','%','0','3','d','Z',0};
649
650 TRACE("\n");
651
652 if(!(date = date_this(jsthis)))
653 return throw_type_error(ctx, JS_E_DATE_EXPECTED, NULL);
654
655 year = year_from_time(date->time);
656 if(isnan(year) || year > 999999 || year < -999999) {
657 FIXME("year %lf should throw an exception\n", year);
658 return E_FAIL;
659 }
660
661 if(year < 0) {
662 *p++ = '-';
663 p += swprintf(p, long_year_formatW, -(int)year);
664 }else if(year > 9999) {
665 *p++ = '+';
666 p += swprintf(p, long_year_formatW, (int)year);
667 }else {
668 p += swprintf(p, short_year_formatW, (int)year);
669 }
670
671 swprintf(p, formatW,
672 (int)month_from_time(date->time) + 1, (int)date_from_time(date->time),
673 (int)hour_from_time(date->time), (int)min_from_time(date->time),
674 (int)sec_from_time(date->time), (int)ms_from_time(date->time));
675
676 if(r) {
677 jsstr_t *ret;
678 if(!(ret = jsstr_alloc(buf)))
679 return E_OUTOFMEMORY;
680 *r = jsval_string(ret);
681 }
682 return S_OK;
683 }
684
Date_valueOf(script_ctx_t * ctx,vdisp_t * jsthis,WORD flags,unsigned argc,jsval_t * argv,jsval_t * r)685 static HRESULT Date_valueOf(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
686 jsval_t *r)
687 {
688 DateInstance *date;
689
690 TRACE("\n");
691
692 if(!(date = date_this(jsthis)))
693 return throw_type_error(ctx, JS_E_DATE_EXPECTED, NULL);
694
695 if(r)
696 *r = jsval_number(date->time);
697 return S_OK;
698 }
699
create_utc_string(script_ctx_t * ctx,vdisp_t * jsthis,jsval_t * r)700 static inline HRESULT create_utc_string(script_ctx_t *ctx, vdisp_t *jsthis, jsval_t *r)
701 {
702 static const WCHAR formatADW[] = { '%','s',',',' ','%','d',' ','%','s',' ','%','d',' ',
703 '%','0','2','d',':','%','0','2','d',':','%','0','2','d',' ','U','T','C',0 };
704 static const WCHAR formatBCW[] = { '%','s',',',' ','%','d',' ','%','s',' ','%','d',' ','B','.','C','.',' ',
705 '%','0','2','d',':','%','0','2','d',':','%','0','2','d',' ','U','T','C',0 };
706
707 static const DWORD week_ids[] = { LOCALE_SABBREVDAYNAME7, LOCALE_SABBREVDAYNAME1,
708 LOCALE_SABBREVDAYNAME2, LOCALE_SABBREVDAYNAME3, LOCALE_SABBREVDAYNAME4,
709 LOCALE_SABBREVDAYNAME5, LOCALE_SABBREVDAYNAME6 };
710 static const DWORD month_ids[] = { LOCALE_SABBREVMONTHNAME1, LOCALE_SABBREVMONTHNAME2,
711 LOCALE_SABBREVMONTHNAME3, LOCALE_SABBREVMONTHNAME4,
712 LOCALE_SABBREVMONTHNAME5, LOCALE_SABBREVMONTHNAME6,
713 LOCALE_SABBREVMONTHNAME7, LOCALE_SABBREVMONTHNAME8,
714 LOCALE_SABBREVMONTHNAME9, LOCALE_SABBREVMONTHNAME10,
715 LOCALE_SABBREVMONTHNAME11, LOCALE_SABBREVMONTHNAME12 };
716
717 BOOL formatAD = TRUE;
718 WCHAR week[64], month[64];
719 WCHAR buf[192];
720 DateInstance *date;
721 jsstr_t *date_str;
722 int year, day;
723 DWORD lcid_en;
724
725 if(!(date = date_this(jsthis)))
726 return throw_type_error(ctx, JS_E_DATE_EXPECTED, NULL);
727
728 if(isnan(date->time)) {
729 if(r)
730 *r = jsval_string(jsstr_nan());
731 return S_OK;
732 }
733
734 if(r) {
735 lcid_en = MAKELCID(MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),SORT_DEFAULT);
736
737 week[0] = 0;
738 GetLocaleInfoW(lcid_en, week_ids[(int)week_day(date->time)], week, ARRAY_SIZE(week));
739
740 month[0] = 0;
741 GetLocaleInfoW(lcid_en, month_ids[(int)month_from_time(date->time)], month, ARRAY_SIZE(month));
742
743 year = year_from_time(date->time);
744 if(year<0) {
745 formatAD = FALSE;
746 year = -year+1;
747 }
748
749 day = date_from_time(date->time);
750
751 swprintf(buf, formatAD ? formatADW : formatBCW, week, day, month, year,
752 (int)hour_from_time(date->time), (int)min_from_time(date->time),
753 (int)sec_from_time(date->time));
754
755 date_str = jsstr_alloc(buf);
756 if(!date_str)
757 return E_OUTOFMEMORY;
758
759 *r = jsval_string(date_str);
760 }
761 return S_OK;
762 }
763
764 /* ECMA-262 3rd Edition 15.9.5.42 */
Date_toUTCString(script_ctx_t * ctx,vdisp_t * jsthis,WORD flags,unsigned argc,jsval_t * argv,jsval_t * r)765 static HRESULT Date_toUTCString(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
766 jsval_t *r)
767 {
768 TRACE("\n");
769 return create_utc_string(ctx, jsthis, r);
770 }
771
Date_toGMTString(script_ctx_t * ctx,vdisp_t * jsthis,WORD flags,unsigned argc,jsval_t * argv,jsval_t * r)772 static HRESULT Date_toGMTString(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
773 jsval_t *r)
774 {
775 TRACE("\n");
776 return create_utc_string(ctx, jsthis, r);
777 }
778
779 /* ECMA-262 3rd Edition 15.9.5.3 */
dateobj_to_date_string(DateInstance * date,jsval_t * r)780 static HRESULT dateobj_to_date_string(DateInstance *date, jsval_t *r)
781 {
782 static const WCHAR formatADW[] = { '%','s',' ','%','s',' ','%','d',' ','%','d',0 };
783 static const WCHAR formatBCW[] = { '%','s',' ','%','s',' ','%','d',' ','%','d',' ','B','.','C','.',0 };
784
785 static const DWORD week_ids[] = { LOCALE_SABBREVDAYNAME7, LOCALE_SABBREVDAYNAME1,
786 LOCALE_SABBREVDAYNAME2, LOCALE_SABBREVDAYNAME3, LOCALE_SABBREVDAYNAME4,
787 LOCALE_SABBREVDAYNAME5, LOCALE_SABBREVDAYNAME6 };
788 static const DWORD month_ids[] = { LOCALE_SABBREVMONTHNAME1, LOCALE_SABBREVMONTHNAME2,
789 LOCALE_SABBREVMONTHNAME3, LOCALE_SABBREVMONTHNAME4,
790 LOCALE_SABBREVMONTHNAME5, LOCALE_SABBREVMONTHNAME6,
791 LOCALE_SABBREVMONTHNAME7, LOCALE_SABBREVMONTHNAME8,
792 LOCALE_SABBREVMONTHNAME9, LOCALE_SABBREVMONTHNAME10,
793 LOCALE_SABBREVMONTHNAME11, LOCALE_SABBREVMONTHNAME12 };
794
795 BOOL formatAD = TRUE;
796 WCHAR week[64], month[64];
797 WCHAR buf[192];
798 jsstr_t *date_str;
799 DOUBLE time;
800 int year, day;
801 DWORD lcid_en;
802
803 if(isnan(date->time)) {
804 if(r)
805 *r = jsval_string(jsstr_nan());
806 return S_OK;
807 }
808
809 time = local_time(date->time, date);
810
811 if(r) {
812 lcid_en = MAKELCID(MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),SORT_DEFAULT);
813
814 week[0] = 0;
815 GetLocaleInfoW(lcid_en, week_ids[(int)week_day(time)], week, ARRAY_SIZE(week));
816
817 month[0] = 0;
818 GetLocaleInfoW(lcid_en, month_ids[(int)month_from_time(time)], month, ARRAY_SIZE(month));
819
820 year = year_from_time(time);
821 if(year<0) {
822 formatAD = FALSE;
823 year = -year+1;
824 }
825
826 day = date_from_time(time);
827
828 swprintf(buf, formatAD ? formatADW : formatBCW, week, month, day, year);
829
830 date_str = jsstr_alloc(buf);
831 if(!date_str)
832 return E_OUTOFMEMORY;
833
834 *r = jsval_string(date_str);
835 }
836 return S_OK;
837 }
838
Date_toDateString(script_ctx_t * ctx,vdisp_t * jsthis,WORD flags,unsigned argc,jsval_t * argv,jsval_t * r)839 static HRESULT Date_toDateString(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
840 jsval_t *r)
841 {
842 DateInstance *date;
843
844 if(!(date = date_this(jsthis)))
845 return throw_type_error(ctx, JS_E_DATE_EXPECTED, NULL);
846
847 return dateobj_to_date_string(date, r);
848 }
849
850 /* ECMA-262 3rd Edition 15.9.5.4 */
Date_toTimeString(script_ctx_t * ctx,vdisp_t * jsthis,WORD flags,unsigned argc,jsval_t * argv,jsval_t * r)851 static HRESULT Date_toTimeString(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
852 jsval_t *r)
853 {
854 static const WCHAR formatW[] = { '%','0','2','d',':','%','0','2','d',':','%','0','2','d',
855 ' ','U','T','C','%','c','%','0','2','d','%','0','2','d',0 };
856 static const WCHAR formatUTCW[] = { '%','0','2','d',':','%','0','2','d',
857 ':','%','0','2','d',' ','U','T','C',0 };
858 DateInstance *date;
859 jsstr_t *date_str;
860 WCHAR buf[32];
861 DOUBLE time;
862 WCHAR sign;
863 int offset;
864
865 TRACE("\n");
866
867 if(!(date = date_this(jsthis)))
868 return throw_type_error(ctx, JS_E_DATE_EXPECTED, NULL);
869
870 if(isnan(date->time)) {
871 if(r)
872 *r = jsval_string(jsstr_nan());
873 return S_OK;
874 }
875
876 time = local_time(date->time, date);
877
878 if(r) {
879 offset = date->bias +
880 daylight_saving_ta(time, date);
881
882 if(offset < 0) {
883 sign = '+';
884 offset = -offset;
885 }
886 else sign = '-';
887
888 if(offset)
889 swprintf(buf, formatW, (int)hour_from_time(time),
890 (int)min_from_time(time), (int)sec_from_time(time),
891 sign, offset/60, offset%60);
892 else
893 swprintf(buf, formatUTCW, (int)hour_from_time(time),
894 (int)min_from_time(time), (int)sec_from_time(time));
895
896 date_str = jsstr_alloc(buf);
897 if(!date_str)
898 return E_OUTOFMEMORY;
899
900 *r = jsval_string(date_str);
901 }
902 return S_OK;
903 }
904
905 /* ECMA-262 3rd Edition 15.9.5.6 */
Date_toLocaleDateString(script_ctx_t * ctx,vdisp_t * jsthis,WORD flags,unsigned argc,jsval_t * argv,jsval_t * r)906 static HRESULT Date_toLocaleDateString(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
907 jsval_t *r)
908 {
909 SYSTEMTIME st;
910 DateInstance *date;
911 jsstr_t *date_str;
912 int len;
913
914 TRACE("\n");
915
916 if(!(date = date_this(jsthis)))
917 return throw_type_error(ctx, JS_E_DATE_EXPECTED, NULL);
918
919 if(isnan(date->time)) {
920 if(r)
921 *r = jsval_string(jsstr_nan());
922 return S_OK;
923 }
924
925 st = create_systemtime(local_time(date->time, date));
926
927 if(st.wYear<1601 || st.wYear>9999)
928 return dateobj_to_date_string(date, r);
929
930 if(r) {
931 WCHAR *ptr;
932
933 len = GetDateFormatW(ctx->lcid, DATE_LONGDATE, &st, NULL, NULL, 0);
934 date_str = jsstr_alloc_buf(len-1, &ptr);
935 if(!date_str)
936 return E_OUTOFMEMORY;
937 GetDateFormatW(ctx->lcid, DATE_LONGDATE, &st, NULL, ptr, len);
938
939 *r = jsval_string(date_str);
940 }
941 return S_OK;
942 }
943
944 /* ECMA-262 3rd Edition 15.9.5.7 */
Date_toLocaleTimeString(script_ctx_t * ctx,vdisp_t * jsthis,WORD flags,unsigned argc,jsval_t * argv,jsval_t * r)945 static HRESULT Date_toLocaleTimeString(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
946 jsval_t *r)
947 {
948 SYSTEMTIME st;
949 DateInstance *date;
950 jsstr_t *date_str;
951 int len;
952
953 TRACE("\n");
954
955 if(!(date = date_this(jsthis)))
956 return throw_type_error(ctx, JS_E_DATE_EXPECTED, NULL);
957
958 if(isnan(date->time)) {
959 if(r)
960 *r = jsval_string(jsstr_nan());
961 return S_OK;
962 }
963
964 st = create_systemtime(local_time(date->time, date));
965
966 if(st.wYear<1601 || st.wYear>9999)
967 return Date_toTimeString(ctx, jsthis, flags, argc, argv, r);
968
969 if(r) {
970 WCHAR *ptr;
971
972 len = GetTimeFormatW(ctx->lcid, 0, &st, NULL, NULL, 0);
973 date_str = jsstr_alloc_buf(len-1, &ptr);
974 if(!date_str)
975 return E_OUTOFMEMORY;
976 GetTimeFormatW(ctx->lcid, 0, &st, NULL, ptr, len);
977
978 *r = jsval_string(date_str);
979 }
980 return S_OK;
981 }
982
983 /* ECMA-262 3rd Edition 15.9.5.9 */
Date_getTime(script_ctx_t * ctx,vdisp_t * jsthis,WORD flags,unsigned argc,jsval_t * argv,jsval_t * r)984 static HRESULT Date_getTime(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
985 jsval_t *r)
986 {
987 DateInstance *date;
988
989 TRACE("\n");
990
991 if(!(date = date_this(jsthis)))
992 return throw_type_error(ctx, JS_E_DATE_EXPECTED, NULL);
993
994 if(r)
995 *r = jsval_number(date->time);
996 return S_OK;
997 }
998
999 /* ECMA-262 3rd Edition 15.9.5.10 */
Date_getFullYear(script_ctx_t * ctx,vdisp_t * jsthis,WORD flags,unsigned argc,jsval_t * argv,jsval_t * r)1000 static HRESULT Date_getFullYear(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
1001 jsval_t *r)
1002 {
1003 DateInstance *date;
1004
1005 TRACE("\n");
1006
1007 if(!(date = date_this(jsthis)))
1008 return throw_type_error(ctx, JS_E_DATE_EXPECTED, NULL);
1009
1010 if(r) {
1011 DOUBLE time = local_time(date->time, date);
1012
1013 *r = jsval_number(year_from_time(time));
1014 }
1015 return S_OK;
1016 }
1017
1018 /* ECMA-262 3rd Edition 15.9.5.11 */
Date_getUTCFullYear(script_ctx_t * ctx,vdisp_t * jsthis,WORD flags,unsigned argc,jsval_t * argv,jsval_t * r)1019 static HRESULT Date_getUTCFullYear(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
1020 jsval_t *r)
1021 {
1022 DateInstance *date;
1023
1024 TRACE("\n");
1025
1026 if(!(date = date_this(jsthis)))
1027 return throw_type_error(ctx, JS_E_DATE_EXPECTED, NULL);
1028
1029 if(r)
1030 *r = jsval_number(year_from_time(date->time));
1031 return S_OK;
1032 }
1033
1034 /* ECMA-262 3rd Edition 15.9.5.12 */
Date_getMonth(script_ctx_t * ctx,vdisp_t * jsthis,WORD flags,unsigned argc,jsval_t * argv,jsval_t * r)1035 static HRESULT Date_getMonth(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r)
1036 {
1037 DateInstance *date;
1038
1039 TRACE("\n");
1040
1041 if(!(date = date_this(jsthis)))
1042 return throw_type_error(ctx, JS_E_DATE_EXPECTED, NULL);
1043
1044 if(r)
1045 *r = jsval_number(month_from_time(local_time(date->time, date)));
1046 return S_OK;
1047 }
1048
1049 /* ECMA-262 3rd Edition 15.9.5.13 */
Date_getUTCMonth(script_ctx_t * ctx,vdisp_t * jsthis,WORD flags,unsigned argc,jsval_t * argv,jsval_t * r)1050 static HRESULT Date_getUTCMonth(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
1051 jsval_t *r)
1052 {
1053 DateInstance *date;
1054
1055 TRACE("\n");
1056
1057 if(!(date = date_this(jsthis)))
1058 return throw_type_error(ctx, JS_E_DATE_EXPECTED, NULL);
1059
1060 if(r)
1061 *r = jsval_number(month_from_time(date->time));
1062 return S_OK;
1063 }
1064
1065 /* ECMA-262 3rd Edition 15.9.5.14 */
Date_getDate(script_ctx_t * ctx,vdisp_t * jsthis,WORD flags,unsigned argc,jsval_t * argv,jsval_t * r)1066 static HRESULT Date_getDate(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r)
1067 {
1068 DateInstance *date;
1069
1070 TRACE("\n");
1071
1072 if(!(date = date_this(jsthis)))
1073 return throw_type_error(ctx, JS_E_DATE_EXPECTED, NULL);
1074
1075 if(r)
1076 *r = jsval_number(date_from_time(local_time(date->time, date)));
1077 return S_OK;
1078 }
1079
1080 /* ECMA-262 3rd Edition 15.9.5.15 */
Date_getUTCDate(script_ctx_t * ctx,vdisp_t * jsthis,WORD flags,unsigned argc,jsval_t * argv,jsval_t * r)1081 static HRESULT Date_getUTCDate(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
1082 jsval_t *r)
1083 {
1084 DateInstance *date;
1085
1086 TRACE("\n");
1087
1088 if(!(date = date_this(jsthis)))
1089 return throw_type_error(ctx, JS_E_DATE_EXPECTED, NULL);
1090
1091 if(r)
1092 *r = jsval_number(date_from_time(date->time));
1093 return S_OK;
1094 }
1095
1096 /* ECMA-262 3rd Edition 15.9.5.16 */
Date_getDay(script_ctx_t * ctx,vdisp_t * jsthis,WORD flags,unsigned argc,jsval_t * argv,jsval_t * r)1097 static HRESULT Date_getDay(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
1098 jsval_t *r)
1099 {
1100 DateInstance *date;
1101
1102 TRACE("\n");
1103
1104 if(!(date = date_this(jsthis)))
1105 return throw_type_error(ctx, JS_E_DATE_EXPECTED, NULL);
1106
1107 if(r)
1108 *r = jsval_number(week_day(local_time(date->time, date)));
1109 return S_OK;
1110 }
1111
1112 /* ECMA-262 3rd Edition 15.9.5.17 */
Date_getUTCDay(script_ctx_t * ctx,vdisp_t * jsthis,WORD flags,unsigned argc,jsval_t * argv,jsval_t * r)1113 static HRESULT Date_getUTCDay(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
1114 jsval_t *r)
1115 {
1116 DateInstance *date;
1117
1118 TRACE("\n");
1119
1120 if(!(date = date_this(jsthis)))
1121 return throw_type_error(ctx, JS_E_DATE_EXPECTED, NULL);
1122
1123 if(r)
1124 *r = jsval_number(week_day(date->time));
1125 return S_OK;
1126 }
1127
1128 /* ECMA-262 3rd Edition 15.9.5.18 */
Date_getHours(script_ctx_t * ctx,vdisp_t * jsthis,WORD flags,unsigned argc,jsval_t * argv,jsval_t * r)1129 static HRESULT Date_getHours(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
1130 jsval_t *r)
1131 {
1132 DateInstance *date;
1133
1134 TRACE("\n");
1135
1136 if(!(date = date_this(jsthis)))
1137 return throw_type_error(ctx, JS_E_DATE_EXPECTED, NULL);
1138
1139 if(r)
1140 *r = jsval_number(hour_from_time(local_time(date->time, date)));
1141 return S_OK;
1142 }
1143
1144 /* ECMA-262 3rd Edition 15.9.5.19 */
Date_getUTCHours(script_ctx_t * ctx,vdisp_t * jsthis,WORD flags,unsigned argc,jsval_t * argv,jsval_t * r)1145 static HRESULT Date_getUTCHours(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
1146 jsval_t *r)
1147 {
1148 DateInstance *date;
1149
1150 TRACE("\n");
1151
1152 if(!(date = date_this(jsthis)))
1153 return throw_type_error(ctx, JS_E_DATE_EXPECTED, NULL);
1154
1155 if(r)
1156 *r = jsval_number(hour_from_time(date->time));
1157 return S_OK;
1158 }
1159
1160 /* ECMA-262 3rd Edition 15.9.5.20 */
Date_getMinutes(script_ctx_t * ctx,vdisp_t * jsthis,WORD flags,unsigned argc,jsval_t * argv,jsval_t * r)1161 static HRESULT Date_getMinutes(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
1162 jsval_t *r)
1163 {
1164 DateInstance *date;
1165
1166 TRACE("\n");
1167
1168 if(!(date = date_this(jsthis)))
1169 return throw_type_error(ctx, JS_E_DATE_EXPECTED, NULL);
1170
1171 if(r)
1172 *r = jsval_number(min_from_time(local_time(date->time, date)));
1173 return S_OK;
1174 }
1175
1176 /* ECMA-262 3rd Edition 15.9.5.21 */
Date_getUTCMinutes(script_ctx_t * ctx,vdisp_t * jsthis,WORD flags,unsigned argc,jsval_t * argv,jsval_t * r)1177 static HRESULT Date_getUTCMinutes(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
1178 jsval_t *r)
1179 {
1180 DateInstance *date;
1181
1182 TRACE("\n");
1183
1184 if(!(date = date_this(jsthis)))
1185 return throw_type_error(ctx, JS_E_DATE_EXPECTED, NULL);
1186
1187 if(r)
1188 *r = jsval_number(min_from_time(date->time));
1189 return S_OK;
1190 }
1191
1192 /* ECMA-262 3rd Edition 15.9.5.22 */
Date_getSeconds(script_ctx_t * ctx,vdisp_t * jsthis,WORD flags,unsigned argc,jsval_t * argv,jsval_t * r)1193 static HRESULT Date_getSeconds(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r)
1194 {
1195 DateInstance *date;
1196
1197 TRACE("\n");
1198
1199 if(!(date = date_this(jsthis)))
1200 return throw_type_error(ctx, JS_E_DATE_EXPECTED, NULL);
1201
1202 if(r)
1203 *r = jsval_number(sec_from_time(local_time(date->time, date)));
1204 return S_OK;
1205 }
1206
1207 /* ECMA-262 3rd Edition 15.9.5.23 */
Date_getUTCSeconds(script_ctx_t * ctx,vdisp_t * jsthis,WORD flags,unsigned argc,jsval_t * argv,jsval_t * r)1208 static HRESULT Date_getUTCSeconds(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
1209 jsval_t *r)
1210 {
1211 DateInstance *date;
1212
1213 TRACE("\n");
1214
1215 if(!(date = date_this(jsthis)))
1216 return throw_type_error(ctx, JS_E_DATE_EXPECTED, NULL);
1217
1218 if(r)
1219 *r = jsval_number(sec_from_time(date->time));
1220 return S_OK;
1221 }
1222
1223 /* ECMA-262 3rd Edition 15.9.5.24 */
Date_getMilliseconds(script_ctx_t * ctx,vdisp_t * jsthis,WORD flags,unsigned argc,jsval_t * argv,jsval_t * r)1224 static HRESULT Date_getMilliseconds(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
1225 jsval_t *r)
1226 {
1227 DateInstance *date;
1228
1229 TRACE("\n");
1230
1231 if(!(date = date_this(jsthis)))
1232 return throw_type_error(ctx, JS_E_DATE_EXPECTED, NULL);
1233
1234 if(r)
1235 *r = jsval_number(ms_from_time(local_time(date->time, date)));
1236 return S_OK;
1237 }
1238
1239 /* ECMA-262 3rd Edition 15.9.5.25 */
Date_getUTCMilliseconds(script_ctx_t * ctx,vdisp_t * jsthis,WORD flags,unsigned argc,jsval_t * argv,jsval_t * r)1240 static HRESULT Date_getUTCMilliseconds(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
1241 jsval_t *r)
1242 {
1243 DateInstance *date;
1244
1245 TRACE("\n");
1246
1247 if(!(date = date_this(jsthis)))
1248 return throw_type_error(ctx, JS_E_DATE_EXPECTED, NULL);
1249
1250 if(r)
1251 *r = jsval_number(ms_from_time(date->time));
1252 return S_OK;
1253 }
1254
1255 /* ECMA-262 3rd Edition 15.9.5.26 */
Date_getTimezoneOffset(script_ctx_t * ctx,vdisp_t * jsthis,WORD flags,unsigned argc,jsval_t * argv,jsval_t * r)1256 static HRESULT Date_getTimezoneOffset(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
1257 jsval_t *r)
1258 {
1259 DateInstance *date;
1260
1261 TRACE("\n");
1262
1263 if(!(date = date_this(jsthis)))
1264 return throw_type_error(ctx, JS_E_DATE_EXPECTED, NULL);
1265
1266 if(r)
1267 *r = jsval_number(floor((date->time-local_time(date->time, date))/MS_PER_MINUTE));
1268 return S_OK;
1269 }
1270
1271 /* ECMA-262 3rd Edition 15.9.5.27 */
Date_setTime(script_ctx_t * ctx,vdisp_t * jsthis,WORD flags,unsigned argc,jsval_t * argv,jsval_t * r)1272 static HRESULT Date_setTime(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
1273 jsval_t *r)
1274 {
1275 double n;
1276 HRESULT hres;
1277 DateInstance *date;
1278
1279 TRACE("\n");
1280
1281 if(!(date = date_this(jsthis)))
1282 return throw_type_error(ctx, JS_E_DATE_EXPECTED, NULL);
1283
1284 if(!argc)
1285 return throw_type_error(ctx, JS_E_MISSING_ARG, NULL);
1286
1287 hres = to_number(ctx, argv[0], &n);
1288 if(FAILED(hres))
1289 return hres;
1290
1291 date->time = time_clip(n);
1292
1293 if(r)
1294 *r = jsval_number(date->time);
1295 return S_OK;
1296 }
1297
1298 /* ECMA-262 3rd Edition 15.9.5.28 */
Date_setMilliseconds(script_ctx_t * ctx,vdisp_t * jsthis,WORD flags,unsigned argc,jsval_t * argv,jsval_t * r)1299 static HRESULT Date_setMilliseconds(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
1300 jsval_t *r)
1301 {
1302 DateInstance *date;
1303 double n, t;
1304 HRESULT hres;
1305
1306 TRACE("\n");
1307
1308 if(!(date = date_this(jsthis)))
1309 return throw_type_error(ctx, JS_E_DATE_EXPECTED, NULL);
1310
1311 if(!argc)
1312 return throw_type_error(ctx, JS_E_MISSING_ARG, NULL);
1313
1314 hres = to_number(ctx, argv[0], &n);
1315 if(FAILED(hres))
1316 return hres;
1317
1318 t = local_time(date->time, date);
1319 t = make_date(day(t), make_time(hour_from_time(t), min_from_time(t),
1320 sec_from_time(t), n));
1321 date->time = time_clip(utc(t, date));
1322
1323 if(r)
1324 *r = jsval_number(date->time);
1325 return S_OK;
1326 }
1327
1328 /* ECMA-262 3rd Edition 15.9.5.29 */
Date_setUTCMilliseconds(script_ctx_t * ctx,vdisp_t * jsthis,WORD flags,unsigned argc,jsval_t * argv,jsval_t * r)1329 static HRESULT Date_setUTCMilliseconds(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
1330 jsval_t *r)
1331 {
1332 DateInstance *date;
1333 double n, t;
1334 HRESULT hres;
1335
1336 TRACE("\n");
1337
1338 if(!(date = date_this(jsthis)))
1339 return throw_type_error(ctx, JS_E_DATE_EXPECTED, NULL);
1340
1341 if(!argc)
1342 return throw_type_error(ctx, JS_E_MISSING_ARG, NULL);
1343
1344 hres = to_number(ctx, argv[0], &n);
1345 if(FAILED(hres))
1346 return hres;
1347
1348 t = date->time;
1349 t = make_date(day(t), make_time(hour_from_time(t), min_from_time(t),
1350 sec_from_time(t), n));
1351 date->time = time_clip(t);
1352
1353 if(r)
1354 *r = jsval_number(date->time);
1355 return S_OK;
1356 }
1357
1358 /* ECMA-262 3rd Edition 15.9.5.30 */
Date_setSeconds(script_ctx_t * ctx,vdisp_t * jsthis,WORD flags,unsigned argc,jsval_t * argv,jsval_t * r)1359 static HRESULT Date_setSeconds(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
1360 jsval_t *r)
1361 {
1362 DateInstance *date;
1363 double t, sec, ms;
1364 HRESULT hres;
1365
1366 TRACE("\n");
1367
1368 if(!(date = date_this(jsthis)))
1369 return throw_type_error(ctx, JS_E_DATE_EXPECTED, NULL);
1370
1371 if(!argc)
1372 return throw_type_error(ctx, JS_E_MISSING_ARG, NULL);
1373
1374 t = local_time(date->time, date);
1375
1376 hres = to_number(ctx, argv[0], &sec);
1377 if(FAILED(hres))
1378 return hres;
1379
1380 if(argc > 1) {
1381 hres = to_number(ctx, argv[1], &ms);
1382 if(FAILED(hres))
1383 return hres;
1384 }else {
1385 ms = ms_from_time(t);
1386 }
1387
1388 t = make_date(day(t), make_time(hour_from_time(t),
1389 min_from_time(t), sec, ms));
1390 date->time = time_clip(utc(t, date));
1391
1392 if(r)
1393 *r = jsval_number(date->time);
1394 return S_OK;
1395 }
1396
1397 /* ECMA-262 3rd Edition 15.9.5.31 */
Date_setUTCSeconds(script_ctx_t * ctx,vdisp_t * jsthis,WORD flags,unsigned argc,jsval_t * argv,jsval_t * r)1398 static HRESULT Date_setUTCSeconds(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
1399 jsval_t *r)
1400 {
1401 DateInstance *date;
1402 double t, sec, ms;
1403 HRESULT hres;
1404
1405 TRACE("\n");
1406
1407 if(!(date = date_this(jsthis)))
1408 return throw_type_error(ctx, JS_E_DATE_EXPECTED, NULL);
1409
1410 if(!argc)
1411 return throw_type_error(ctx, JS_E_MISSING_ARG, NULL);
1412
1413 t = date->time;
1414
1415 hres = to_number(ctx, argv[0], &sec);
1416 if(FAILED(hres))
1417 return hres;
1418
1419 if(argc > 1) {
1420 hres = to_number(ctx, argv[1], &ms);
1421 if(FAILED(hres))
1422 return hres;
1423 }else {
1424 ms = ms_from_time(t);
1425 }
1426
1427 t = make_date(day(t), make_time(hour_from_time(t),
1428 min_from_time(t), sec, ms));
1429 date->time = time_clip(t);
1430
1431 if(r)
1432 *r = jsval_number(date->time);
1433 return S_OK;
1434 }
1435
1436 /* ECMA-262 3rd Edition 15.9.5.33 */
Date_setMinutes(script_ctx_t * ctx,vdisp_t * jsthis,WORD flags,unsigned argc,jsval_t * argv,jsval_t * r)1437 static HRESULT Date_setMinutes(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
1438 jsval_t *r)
1439 {
1440 DateInstance *date;
1441 double t, min, sec, ms;
1442 HRESULT hres;
1443
1444 TRACE("\n");
1445
1446 if(!(date = date_this(jsthis)))
1447 return throw_type_error(ctx, JS_E_DATE_EXPECTED, NULL);
1448
1449 if(!argc)
1450 return throw_type_error(ctx, JS_E_MISSING_ARG, NULL);
1451
1452 t = local_time(date->time, date);
1453
1454 hres = to_number(ctx, argv[0], &min);
1455 if(FAILED(hres))
1456 return hres;
1457
1458 if(argc > 1) {
1459 hres = to_number(ctx, argv[1], &sec);
1460 if(FAILED(hres))
1461 return hres;
1462 }else {
1463 sec = sec_from_time(t);
1464 }
1465
1466 if(argc > 2) {
1467 hres = to_number(ctx, argv[2], &ms);
1468 if(FAILED(hres))
1469 return hres;
1470 }else {
1471 ms = ms_from_time(t);
1472 }
1473
1474 t = make_date(day(t), make_time(hour_from_time(t),
1475 min, sec, ms));
1476 date->time = time_clip(utc(t, date));
1477
1478 if(r)
1479 *r = jsval_number(date->time);
1480 return S_OK;
1481 }
1482
1483 /* ECMA-262 3rd Edition 15.9.5.34 */
Date_setUTCMinutes(script_ctx_t * ctx,vdisp_t * jsthis,WORD flags,unsigned argc,jsval_t * argv,jsval_t * r)1484 static HRESULT Date_setUTCMinutes(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
1485 jsval_t *r)
1486 {
1487 DateInstance *date;
1488 double t, min, sec, ms;
1489 HRESULT hres;
1490
1491 TRACE("\n");
1492
1493 if(!(date = date_this(jsthis)))
1494 return throw_type_error(ctx, JS_E_DATE_EXPECTED, NULL);
1495
1496 if(!argc)
1497 return throw_type_error(ctx, JS_E_MISSING_ARG, NULL);
1498
1499 t = date->time;
1500
1501 hres = to_number(ctx, argv[0], &min);
1502 if(FAILED(hres))
1503 return hres;
1504
1505 if(argc > 1) {
1506 hres = to_number(ctx, argv[1], &sec);
1507 if(FAILED(hres))
1508 return hres;
1509 }else {
1510 sec = sec_from_time(t);
1511 }
1512
1513 if(argc > 2) {
1514 hres = to_number(ctx, argv[2], &ms);
1515 if(FAILED(hres))
1516 return hres;
1517 }else {
1518 ms = ms_from_time(t);
1519 }
1520
1521 t = make_date(day(t), make_time(hour_from_time(t),
1522 min, sec, ms));
1523 date->time = time_clip(t);
1524
1525 if(r)
1526 *r = jsval_number(date->time);
1527 return S_OK;
1528 }
1529
1530 /* ECMA-262 3rd Edition 15.9.5.35 */
Date_setHours(script_ctx_t * ctx,vdisp_t * jsthis,WORD flags,unsigned argc,jsval_t * argv,jsval_t * r)1531 static HRESULT Date_setHours(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
1532 jsval_t *r)
1533 {
1534 DateInstance *date;
1535 double t, hour, min, sec, ms;
1536 HRESULT hres;
1537
1538 TRACE("\n");
1539
1540 if(!(date = date_this(jsthis)))
1541 return throw_type_error(ctx, JS_E_DATE_EXPECTED, NULL);
1542
1543 if(!argc)
1544 return throw_type_error(ctx, JS_E_MISSING_ARG, NULL);
1545
1546 t = local_time(date->time, date);
1547
1548 hres = to_number(ctx, argv[0], &hour);
1549 if(FAILED(hres))
1550 return hres;
1551
1552 if(argc > 1) {
1553 hres = to_number(ctx, argv[1], &min);
1554 if(FAILED(hres))
1555 return hres;
1556 }else {
1557 min = min_from_time(t);
1558 }
1559
1560 if(argc > 2) {
1561 hres = to_number(ctx, argv[2], &sec);
1562 if(FAILED(hres))
1563 return hres;
1564 }else {
1565 sec = sec_from_time(t);
1566 }
1567
1568 if(argc > 3) {
1569 hres = to_number(ctx, argv[3], &ms);
1570 if(FAILED(hres))
1571 return hres;
1572 }else {
1573 ms = ms_from_time(t);
1574 }
1575
1576 t = make_date(day(t), make_time(hour, min, sec, ms));
1577 date->time = time_clip(utc(t, date));
1578
1579 if(r)
1580 *r = jsval_number(date->time);
1581 return S_OK;
1582 }
1583
1584 /* ECMA-262 3rd Edition 15.9.5.36 */
Date_setUTCHours(script_ctx_t * ctx,vdisp_t * jsthis,WORD flags,unsigned argc,jsval_t * argv,jsval_t * r)1585 static HRESULT Date_setUTCHours(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
1586 jsval_t *r)
1587 {
1588 DateInstance *date;
1589 double t, hour, min, sec, ms;
1590 HRESULT hres;
1591
1592 TRACE("\n");
1593
1594 if(!(date = date_this(jsthis)))
1595 return throw_type_error(ctx, JS_E_DATE_EXPECTED, NULL);
1596
1597 if(!argc)
1598 return throw_type_error(ctx, JS_E_MISSING_ARG, NULL);
1599
1600 t = date->time;
1601
1602 hres = to_number(ctx, argv[0], &hour);
1603 if(FAILED(hres))
1604 return hres;
1605
1606 if(argc > 1) {
1607 hres = to_number(ctx, argv[1], &min);
1608 if(FAILED(hres))
1609 return hres;
1610 }else {
1611 min = min_from_time(t);
1612 }
1613
1614 if(argc > 2) {
1615 hres = to_number(ctx, argv[2], &sec);
1616 if(FAILED(hres))
1617 return hres;
1618 }else {
1619 sec = sec_from_time(t);
1620 }
1621
1622 if(argc > 3) {
1623 hres = to_number(ctx, argv[3], &ms);
1624 if(FAILED(hres))
1625 return hres;
1626 }else {
1627 ms = ms_from_time(t);
1628 }
1629
1630 t = make_date(day(t), make_time(hour, min, sec, ms));
1631 date->time = time_clip(t);
1632
1633 if(r)
1634 *r = jsval_number(date->time);
1635 return S_OK;
1636 }
1637
1638 /* ECMA-262 3rd Edition 15.9.5.36 */
Date_setDate(script_ctx_t * ctx,vdisp_t * jsthis,WORD flags,unsigned argc,jsval_t * argv,jsval_t * r)1639 static HRESULT Date_setDate(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
1640 jsval_t *r)
1641 {
1642 DateInstance *date;
1643 double t, n;
1644 HRESULT hres;
1645
1646 TRACE("\n");
1647
1648 if(!(date = date_this(jsthis)))
1649 return throw_type_error(ctx, JS_E_DATE_EXPECTED, NULL);
1650
1651 if(!argc)
1652 return throw_type_error(ctx, JS_E_MISSING_ARG, NULL);
1653
1654 hres = to_number(ctx, argv[0], &n);
1655 if(FAILED(hres))
1656 return hres;
1657
1658 t = local_time(date->time, date);
1659 t = make_date(make_day(year_from_time(t), month_from_time(t), n), time_within_day(t));
1660 date->time = time_clip(utc(t, date));
1661
1662 if(r)
1663 *r = jsval_number(date->time);
1664 return S_OK;
1665 }
1666
1667 /* ECMA-262 3rd Edition 15.9.5.37 */
Date_setUTCDate(script_ctx_t * ctx,vdisp_t * jsthis,WORD flags,unsigned argc,jsval_t * argv,jsval_t * r)1668 static HRESULT Date_setUTCDate(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
1669 jsval_t *r)
1670 {
1671 DateInstance *date;
1672 double t, n;
1673 HRESULT hres;
1674
1675 TRACE("\n");
1676
1677 if(!(date = date_this(jsthis)))
1678 return throw_type_error(ctx, JS_E_DATE_EXPECTED, NULL);
1679
1680 if(!argc)
1681 return throw_type_error(ctx, JS_E_MISSING_ARG, NULL);
1682
1683 hres = to_number(ctx, argv[0], &n);
1684 if(FAILED(hres))
1685 return hres;
1686
1687 t = date->time;
1688 t = make_date(make_day(year_from_time(t), month_from_time(t), n), time_within_day(t));
1689 date->time = time_clip(t);
1690
1691 if(r)
1692 *r = jsval_number(date->time);
1693 return S_OK;
1694 }
1695
1696 /* ECMA-262 3rd Edition 15.9.5.38 */
Date_setMonth(script_ctx_t * ctx,vdisp_t * jsthis,WORD flags,unsigned argc,jsval_t * argv,jsval_t * r)1697 static HRESULT Date_setMonth(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
1698 jsval_t *r)
1699 {
1700 DateInstance *date;
1701 DOUBLE t, month, ddate;
1702 HRESULT hres;
1703
1704 TRACE("\n");
1705
1706 if(!(date = date_this(jsthis)))
1707 return throw_type_error(ctx, JS_E_DATE_EXPECTED, NULL);
1708
1709 if(!argc)
1710 return throw_type_error(ctx, JS_E_MISSING_ARG, NULL);
1711
1712 t = local_time(date->time, date);
1713
1714 hres = to_number(ctx, argv[0], &month);
1715 if(FAILED(hres))
1716 return hres;
1717
1718 if(argc > 1) {
1719 hres = to_number(ctx, argv[1], &ddate);
1720 if(FAILED(hres))
1721 return hres;
1722 }else {
1723 ddate = date_from_time(t);
1724 }
1725
1726 t = make_date(make_day(year_from_time(t), month, ddate),
1727 time_within_day(t));
1728 date->time = time_clip(utc(t, date));
1729
1730 if(r)
1731 *r = jsval_number(date->time);
1732 return S_OK;
1733 }
1734
1735 /* ECMA-262 3rd Edition 15.9.5.39 */
Date_setUTCMonth(script_ctx_t * ctx,vdisp_t * jsthis,WORD flags,unsigned argc,jsval_t * argv,jsval_t * r)1736 static HRESULT Date_setUTCMonth(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
1737 jsval_t *r)
1738 {
1739 DateInstance *date;
1740 double t, month, ddate;
1741 HRESULT hres;
1742
1743 TRACE("\n");
1744
1745 if(!(date = date_this(jsthis)))
1746 return throw_type_error(ctx, JS_E_DATE_EXPECTED, NULL);
1747
1748 if(!argc)
1749 return throw_type_error(ctx, JS_E_MISSING_ARG, NULL);
1750
1751 t = date->time;
1752
1753 hres = to_number(ctx, argv[0], &month);
1754 if(FAILED(hres))
1755 return hres;
1756
1757 if(argc > 1) {
1758 hres = to_number(ctx, argv[1], &ddate);
1759 if(FAILED(hres))
1760 return hres;
1761 }else {
1762 ddate = date_from_time(t);
1763 }
1764
1765 t = make_date(make_day(year_from_time(t), month, ddate),
1766 time_within_day(t));
1767 date->time = time_clip(t);
1768
1769 if(r)
1770 *r = jsval_number(date->time);
1771 return S_OK;
1772 }
1773
1774 /* ECMA-262 3rd Edition 15.9.5.40 */
Date_setFullYear(script_ctx_t * ctx,vdisp_t * jsthis,WORD flags,unsigned argc,jsval_t * argv,jsval_t * r)1775 static HRESULT Date_setFullYear(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
1776 jsval_t *r)
1777 {
1778 DateInstance *date;
1779 double t, year, month, ddate;
1780 HRESULT hres;
1781
1782 TRACE("\n");
1783
1784 if(!(date = date_this(jsthis)))
1785 return throw_type_error(ctx, JS_E_DATE_EXPECTED, NULL);
1786
1787 if(!argc)
1788 return throw_type_error(ctx, JS_E_MISSING_ARG, NULL);
1789
1790 t = local_time(date->time, date);
1791
1792 hres = to_number(ctx, argv[0], &year);
1793 if(FAILED(hres))
1794 return hres;
1795
1796 if(argc > 1) {
1797 hres = to_number(ctx, argv[1], &month);
1798 if(FAILED(hres))
1799 return hres;
1800 }else {
1801 month = month_from_time(t);
1802 }
1803
1804 if(argc > 2) {
1805 hres = to_number(ctx, argv[2], &ddate);
1806 if(FAILED(hres))
1807 return hres;
1808 }else {
1809 ddate = date_from_time(t);
1810 }
1811
1812 t = make_date(make_day(year, month, ddate), time_within_day(t));
1813 date->time = time_clip(utc(t, date));
1814
1815 if(r)
1816 *r = jsval_number(date->time);
1817 return S_OK;
1818 }
1819
1820 /* ECMA-262 3rd Edition 15.9.5.41 */
Date_setUTCFullYear(script_ctx_t * ctx,vdisp_t * jsthis,WORD flags,unsigned argc,jsval_t * argv,jsval_t * r)1821 static HRESULT Date_setUTCFullYear(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
1822 jsval_t *r)
1823 {
1824 DateInstance *date;
1825 double t, year, month, ddate;
1826 HRESULT hres;
1827
1828 TRACE("\n");
1829
1830 if(!(date = date_this(jsthis)))
1831 return throw_type_error(ctx, JS_E_DATE_EXPECTED, NULL);
1832
1833 if(!argc)
1834 return throw_type_error(ctx, JS_E_MISSING_ARG, NULL);
1835
1836 t = date->time;
1837
1838 hres = to_number(ctx, argv[0], &year);
1839 if(FAILED(hres))
1840 return hres;
1841
1842 if(argc > 1) {
1843 hres = to_number(ctx, argv[1], &month);
1844 if(FAILED(hres))
1845 return hres;
1846 }else {
1847 month = month_from_time(t);
1848 }
1849
1850 if(argc > 2) {
1851 hres = to_number(ctx, argv[2], &ddate);
1852 if(FAILED(hres))
1853 return hres;
1854 }else {
1855 ddate = date_from_time(t);
1856 }
1857
1858 t = make_date(make_day(year, month, ddate), time_within_day(t));
1859 date->time = time_clip(t);
1860
1861 if(r)
1862 *r = jsval_number(date->time);
1863 return S_OK;
1864 }
1865
1866 /* ECMA-262 3rd Edition B2.4 */
Date_getYear(script_ctx_t * ctx,vdisp_t * jsthis,WORD flags,unsigned argc,jsval_t * argv,jsval_t * r)1867 static HRESULT Date_getYear(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
1868 jsval_t *r)
1869 {
1870 DateInstance *date;
1871 DOUBLE t, year;
1872
1873 TRACE("\n");
1874
1875 if(!(date = date_this(jsthis)))
1876 return throw_type_error(ctx, JS_E_DATE_EXPECTED, NULL);
1877
1878 t = local_time(date->time, date);
1879 if(isnan(t)) {
1880 if(r)
1881 *r = jsval_number(NAN);
1882 return S_OK;
1883 }
1884
1885 year = year_from_time(t);
1886 if(r)
1887 *r = jsval_number((1900<=year && year<2000)?year-1900:year);
1888 return S_OK;
1889 }
1890
1891 /* ECMA-262 3rd Edition B2.5 */
Date_setYear(script_ctx_t * ctx,vdisp_t * jsthis,WORD flags,unsigned argc,jsval_t * argv,jsval_t * r)1892 static HRESULT Date_setYear(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
1893 jsval_t *r)
1894 {
1895 DateInstance *date;
1896 DOUBLE t, year;
1897 HRESULT hres;
1898
1899 TRACE("\n");
1900
1901 if(!(date = date_this(jsthis)))
1902 return throw_type_error(ctx, JS_E_DATE_EXPECTED, NULL);
1903
1904 if(!argc)
1905 return throw_type_error(ctx, JS_E_MISSING_ARG, NULL);
1906
1907 t = local_time(date->time, date);
1908
1909 hres = to_number(ctx, argv[0], &year);
1910 if(FAILED(hres))
1911 return hres;
1912
1913 if(isnan(year)) {
1914 date->time = year;
1915 if(r)
1916 *r = jsval_number(NAN);
1917 return S_OK;
1918 }
1919
1920 year = year >= 0.0 ? floor(year) : -floor(-year);
1921 if(-1.0 < year && year < 100.0)
1922 year += 1900.0;
1923
1924 date->time = time_clip(utc(make_date(make_day(year, month_from_time(t), date_from_time(t)), time_within_day(t)), date));
1925
1926 if(r)
1927 *r = jsval_number(date->time);
1928 return S_OK;
1929 }
1930
Date_get_value(script_ctx_t * ctx,jsdisp_t * jsthis,jsval_t * r)1931 static HRESULT Date_get_value(script_ctx_t *ctx, jsdisp_t *jsthis, jsval_t *r)
1932 {
1933 TRACE("\n");
1934
1935 return dateobj_to_string(date_from_jsdisp(jsthis), r);
1936 }
1937
1938 static const builtin_prop_t Date_props[] = {
1939 {getDateW, Date_getDate, PROPF_METHOD},
1940 {getDayW, Date_getDay, PROPF_METHOD},
1941 {getFullYearW, Date_getFullYear, PROPF_METHOD},
1942 {getHoursW, Date_getHours, PROPF_METHOD},
1943 {getMillisecondsW, Date_getMilliseconds, PROPF_METHOD},
1944 {getMinutesW, Date_getMinutes, PROPF_METHOD},
1945 {getMonthW, Date_getMonth, PROPF_METHOD},
1946 {getSecondsW, Date_getSeconds, PROPF_METHOD},
1947 {getTimeW, Date_getTime, PROPF_METHOD},
1948 {getTimezoneOffsetW, Date_getTimezoneOffset, PROPF_METHOD},
1949 {getUTCDateW, Date_getUTCDate, PROPF_METHOD},
1950 {getUTCDayW, Date_getUTCDay, PROPF_METHOD},
1951 {getUTCFullYearW, Date_getUTCFullYear, PROPF_METHOD},
1952 {getUTCHoursW, Date_getUTCHours, PROPF_METHOD},
1953 {getUTCMillisecondsW, Date_getUTCMilliseconds, PROPF_METHOD},
1954 {getUTCMinutesW, Date_getUTCMinutes, PROPF_METHOD},
1955 {getUTCMonthW, Date_getUTCMonth, PROPF_METHOD},
1956 {getUTCSecondsW, Date_getUTCSeconds, PROPF_METHOD},
1957 {getYearW, Date_getYear, PROPF_METHOD},
1958 {setDateW, Date_setDate, PROPF_METHOD|1},
1959 {setFullYearW, Date_setFullYear, PROPF_METHOD|3},
1960 {setHoursW, Date_setHours, PROPF_METHOD|4},
1961 {setMillisecondsW, Date_setMilliseconds, PROPF_METHOD|1},
1962 {setMinutesW, Date_setMinutes, PROPF_METHOD|3},
1963 {setMonthW, Date_setMonth, PROPF_METHOD|2},
1964 {setSecondsW, Date_setSeconds, PROPF_METHOD|2},
1965 {setTimeW, Date_setTime, PROPF_METHOD|1},
1966 {setUTCDateW, Date_setUTCDate, PROPF_METHOD|1},
1967 {setUTCFullYearW, Date_setUTCFullYear, PROPF_METHOD|3},
1968 {setUTCHoursW, Date_setUTCHours, PROPF_METHOD|4},
1969 {setUTCMillisecondsW, Date_setUTCMilliseconds, PROPF_METHOD|1},
1970 {setUTCMinutesW, Date_setUTCMinutes, PROPF_METHOD|3},
1971 {setUTCMonthW, Date_setUTCMonth, PROPF_METHOD|2},
1972 {setUTCSecondsW, Date_setUTCSeconds, PROPF_METHOD|2},
1973 {setYearW, Date_setYear, PROPF_METHOD|1},
1974 {toDateStringW, Date_toDateString, PROPF_METHOD},
1975 {toGMTStringW, Date_toGMTString, PROPF_METHOD},
1976 {toISOStringW, Date_toISOString, PROPF_METHOD|PROPF_ES5},
1977 {toLocaleDateStringW, Date_toLocaleDateString, PROPF_METHOD},
1978 {toLocaleStringW, Date_toLocaleString, PROPF_METHOD},
1979 {toLocaleTimeStringW, Date_toLocaleTimeString, PROPF_METHOD},
1980 {toStringW, Date_toString, PROPF_METHOD},
1981 {toTimeStringW, Date_toTimeString, PROPF_METHOD},
1982 {toUTCStringW, Date_toUTCString, PROPF_METHOD},
1983 {valueOfW, Date_valueOf, PROPF_METHOD},
1984 };
1985
1986 static const builtin_info_t Date_info = {
1987 JSCLASS_DATE,
1988 {NULL, NULL,0, Date_get_value},
1989 ARRAY_SIZE(Date_props),
1990 Date_props,
1991 NULL,
1992 NULL
1993 };
1994
1995 static const builtin_info_t DateInst_info = {
1996 JSCLASS_DATE,
1997 {NULL, NULL,0, Date_get_value},
1998 0, NULL,
1999 NULL,
2000 NULL
2001 };
2002
create_date(script_ctx_t * ctx,jsdisp_t * object_prototype,DOUBLE time,jsdisp_t ** ret)2003 static HRESULT create_date(script_ctx_t *ctx, jsdisp_t *object_prototype, DOUBLE time, jsdisp_t **ret)
2004 {
2005 DateInstance *date;
2006 HRESULT hres;
2007 TIME_ZONE_INFORMATION tzi;
2008
2009 GetTimeZoneInformation(&tzi);
2010
2011 date = heap_alloc_zero(sizeof(DateInstance));
2012 if(!date)
2013 return E_OUTOFMEMORY;
2014
2015 if(object_prototype)
2016 hres = init_dispex(&date->dispex, ctx, &Date_info, object_prototype);
2017 else
2018 hres = init_dispex_from_constr(&date->dispex, ctx, &DateInst_info, ctx->date_constr);
2019 if(FAILED(hres)) {
2020 heap_free(date);
2021 return hres;
2022 }
2023
2024 date->time = time;
2025 date->bias = tzi.Bias;
2026 date->standardDate = tzi.StandardDate;
2027 date->standardBias = tzi.StandardBias;
2028 date->daylightDate = tzi.DaylightDate;
2029 date->daylightBias = tzi.DaylightBias;
2030
2031 *ret = &date->dispex;
2032 return S_OK;
2033 }
2034
date_parse(jsstr_t * input_str,double * ret)2035 static inline HRESULT date_parse(jsstr_t *input_str, double *ret) {
2036 static const DWORD string_ids[] = { LOCALE_SMONTHNAME12, LOCALE_SMONTHNAME11,
2037 LOCALE_SMONTHNAME10, LOCALE_SMONTHNAME9, LOCALE_SMONTHNAME8,
2038 LOCALE_SMONTHNAME7, LOCALE_SMONTHNAME6, LOCALE_SMONTHNAME5,
2039 LOCALE_SMONTHNAME4, LOCALE_SMONTHNAME3, LOCALE_SMONTHNAME2,
2040 LOCALE_SMONTHNAME1, LOCALE_SDAYNAME7, LOCALE_SDAYNAME1,
2041 LOCALE_SDAYNAME2, LOCALE_SDAYNAME3, LOCALE_SDAYNAME4,
2042 LOCALE_SDAYNAME5, LOCALE_SDAYNAME6 };
2043 WCHAR *strings[ARRAY_SIZE(string_ids)];
2044 WCHAR *parse;
2045 int input_len, parse_len = 0, nest_level = 0, i, size;
2046 int year = 0, month = 0, day = 0, hour = 0, min = 0, sec = 0;
2047 int ms = 0, offset = 0, hour_adjust = 0;
2048 BOOL set_year = FALSE, set_month = FALSE, set_day = FALSE, set_hour = FALSE;
2049 BOOL set_offset = FALSE, set_era = FALSE, ad = TRUE, set_am = FALSE, am = TRUE;
2050 BOOL set_hour_adjust = TRUE;
2051 TIME_ZONE_INFORMATION tzi;
2052 const WCHAR *input;
2053 DateInstance di;
2054 DWORD lcid_en;
2055
2056 input_len = jsstr_length(input_str);
2057 input = jsstr_flatten(input_str);
2058 if(!input)
2059 return E_OUTOFMEMORY;
2060
2061 for(i=0; i<input_len; i++) {
2062 if(input[i] == '(') nest_level++;
2063 else if(input[i] == ')') {
2064 nest_level--;
2065 if(nest_level<0) {
2066 *ret = NAN;
2067 return S_OK;
2068 }
2069 }
2070 else if(!nest_level) parse_len++;
2071 }
2072
2073 parse = heap_alloc((parse_len+1)*sizeof(WCHAR));
2074 if(!parse)
2075 return E_OUTOFMEMORY;
2076 nest_level = 0;
2077 parse_len = 0;
2078 for(i=0; i<input_len; i++) {
2079 if(input[i] == '(') nest_level++;
2080 else if(input[i] == ')') nest_level--;
2081 else if(!nest_level) parse[parse_len++] = towupper(input[i]);
2082 }
2083 parse[parse_len] = 0;
2084
2085 GetTimeZoneInformation(&tzi);
2086 di.bias = tzi.Bias;
2087 di.standardDate = tzi.StandardDate;
2088 di.standardBias = tzi.StandardBias;
2089 di.daylightDate = tzi.DaylightDate;
2090 di.daylightBias = tzi.DaylightBias;
2091
2092 /* FIXME: Cache strings */
2093 lcid_en = MAKELCID(MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),SORT_DEFAULT);
2094 for(i=0; i<ARRAY_SIZE(string_ids); i++) {
2095 size = GetLocaleInfoW(lcid_en, string_ids[i], NULL, 0);
2096 strings[i] = heap_alloc((size+1)*sizeof(WCHAR));
2097 if(!strings[i]) {
2098 i--;
2099 while(i-- >= 0)
2100 heap_free(strings[i]);
2101 heap_free(parse);
2102 return E_OUTOFMEMORY;
2103 }
2104 GetLocaleInfoW(lcid_en, string_ids[i], strings[i], size);
2105 }
2106
2107 for(i=0; i<parse_len;) {
2108 while(iswspace(parse[i])) i++;
2109 if(parse[i] == ',') {
2110 while(parse[i] == ',') i++;
2111 continue;
2112 }
2113
2114 if(parse[i]>='0' && parse[i]<='9') {
2115 int tmp = wcstol(&parse[i], NULL, 10);
2116 while(parse[i]>='0' && parse[i]<='9') i++;
2117 while(iswspace(parse[i])) i++;
2118
2119 if(parse[i] == ':') {
2120 /* Time */
2121 if(set_hour) break;
2122 set_hour = TRUE;
2123
2124 hour = tmp;
2125
2126 while(parse[i] == ':') i++;
2127 while(iswspace(parse[i])) i++;
2128 if(parse[i]>='0' && parse[i]<='9') {
2129 min = wcstol(&parse[i], NULL, 10);
2130 while(parse[i]>='0' && parse[i]<='9') i++;
2131 }
2132
2133 while(iswspace(parse[i])) i++;
2134 while(parse[i] == ':') i++;
2135 while(iswspace(parse[i])) i++;
2136 if(parse[i]>='0' && parse[i]<='9') {
2137 sec = wcstol(&parse[i], NULL, 10);
2138 while(parse[i]>='0' && parse[i]<='9') i++;
2139 }
2140 }
2141 else if(parse[i]=='-' || parse[i]=='/') {
2142 /* Short or long date */
2143 if(set_day || set_month || set_year) break;
2144 set_day = TRUE;
2145 set_month = TRUE;
2146 set_year = TRUE;
2147
2148 month = tmp-1;
2149
2150 while(iswspace(parse[i])) i++;
2151 while(parse[i]=='-' || parse[i]=='/') i++;
2152 while(iswspace(parse[i])) i++;
2153 if(parse[i]<'0' || parse[i]>'9') break;
2154 day = wcstol(&parse[i], NULL, 10);
2155 while(parse[i]>='0' && parse[i]<='9') i++;
2156
2157 while(parse[i]=='-' || parse[i]=='/') i++;
2158 while(iswspace(parse[i])) i++;
2159 if(parse[i]<'0' || parse[i]>'9') break;
2160 year = wcstol(&parse[i], NULL, 10);
2161 while(parse[i]>='0' && parse[i]<='9') i++;
2162
2163 if(tmp >= 70){
2164 /* long date */
2165 month = day - 1;
2166 day = year;
2167 year = tmp;
2168 }
2169 }
2170 else if(tmp<0) break;
2171 else if(tmp<70) {
2172 /* Day */
2173 if(set_day) break;
2174 set_day = TRUE;
2175 day = tmp;
2176 }
2177 else {
2178 /* Year */
2179 if(set_year) break;
2180 set_year = TRUE;
2181 year = tmp;
2182 }
2183 }
2184 else if(parse[i]=='+' || parse[i]=='-') {
2185 /* Timezone offset */
2186 BOOL positive = TRUE;
2187
2188 if(set_offset && set_hour_adjust) break;
2189 set_offset = TRUE;
2190 set_hour_adjust = FALSE;
2191
2192 if(parse[i] == '-') positive = FALSE;
2193
2194 i++;
2195 while(iswspace(parse[i])) i++;
2196 if(parse[i]<'0' || parse[i]>'9') break;
2197 offset = wcstol(&parse[i], NULL, 10);
2198 while(parse[i]>='0' && parse[i]<='9') i++;
2199
2200 if(offset<24) offset *= 60;
2201 else offset = (offset/100)*60 + offset%100;
2202
2203 if(positive) offset = -offset;
2204
2205 }
2206 else {
2207 if(parse[i]<'A' || parse[i]>'Z') break;
2208 else if(parse[i]=='B' && (parse[i+1]=='C' ||
2209 (parse[i+1]=='.' && parse[i+2]=='C'))) {
2210 /* AD/BC */
2211 if(set_era) break;
2212 set_era = TRUE;
2213 ad = FALSE;
2214
2215 i++;
2216 if(parse[i] == '.') i++;
2217 i++;
2218 if(parse[i] == '.') i++;
2219 }
2220 else if(parse[i]=='A' && (parse[i+1]=='D' ||
2221 (parse[i+1]=='.' && parse[i+2]=='D'))) {
2222 /* AD/BC */
2223 if(set_era) break;
2224 set_era = TRUE;
2225
2226 i++;
2227 if(parse[i] == '.') i++;
2228 i++;
2229 if(parse[i] == '.') i++;
2230 }
2231 else if(parse[i+1]<'A' || parse[i+1]>'Z') {
2232 /* Timezone */
2233 if(set_offset) break;
2234 set_offset = TRUE;
2235
2236 if(parse[i] <= 'I') hour_adjust = parse[i]-'A'+2;
2237 else if(parse[i] == 'J') break;
2238 else if(parse[i] <= 'M') hour_adjust = parse[i]-'K'+11;
2239 else if(parse[i] <= 'Y') hour_adjust = parse[i]-'N';
2240 else hour_adjust = 1;
2241
2242 i++;
2243 if(parse[i] == '.') i++;
2244 }
2245 else if(parse[i]=='A' && parse[i+1]=='M') {
2246 /* AM/PM */
2247 if(set_am) break;
2248 set_am = TRUE;
2249 am = TRUE;
2250 i += 2;
2251 }
2252 else if(parse[i]=='P' && parse[i+1]=='M') {
2253 /* AM/PM */
2254 if(set_am) break;
2255 set_am = TRUE;
2256 am = FALSE;
2257 i += 2;
2258 }
2259 else if((parse[i]=='U' && parse[i+1]=='T' && parse[i+2]=='C')
2260 || (parse[i]=='G' && parse[i+1]=='M' && parse[i+2]=='T')) {
2261 /* Timezone */
2262 if(set_offset) break;
2263 set_offset = TRUE;
2264 set_hour_adjust = FALSE;
2265
2266 i += 3;
2267 }
2268 else {
2269 /* Month or garbage */
2270 unsigned int j;
2271
2272 for(size=i; parse[size]>='A' && parse[size]<='Z'; size++);
2273 size -= i;
2274
2275 for(j=0; j<ARRAY_SIZE(string_ids); j++)
2276 if(!_wcsnicmp(&parse[i], strings[j], size)) break;
2277
2278 if(j < 12) {
2279 if(set_month) break;
2280 set_month = TRUE;
2281 month = 11-j;
2282 }
2283 else if(j == ARRAY_SIZE(string_ids)) break;
2284
2285 i += size;
2286 }
2287 }
2288 }
2289
2290 if(i == parse_len && set_year && set_month && set_day && (!set_am || hour<13)) {
2291 if(set_am) {
2292 if(hour == 12) hour = 0;
2293 if(!am) hour += 12;
2294 }
2295
2296 if(!ad) year = -year+1;
2297 else if(year<100) year += 1900;
2298
2299 *ret = time_clip(make_date(make_day(year, month, day),
2300 make_time(hour+hour_adjust, min, sec, ms)) + offset*MS_PER_MINUTE);
2301
2302 if(set_hour_adjust)
2303 *ret = utc(*ret, &di);
2304 }else {
2305 *ret = NAN;
2306 }
2307
2308 for(i=0; i<ARRAY_SIZE(string_ids); i++)
2309 heap_free(strings[i]);
2310 heap_free(parse);
2311
2312 return S_OK;
2313 }
2314
DateConstr_parse(script_ctx_t * ctx,vdisp_t * jsthis,WORD flags,unsigned argc,jsval_t * argv,jsval_t * r)2315 static HRESULT DateConstr_parse(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
2316 jsval_t *r)
2317 {
2318 jsstr_t *parse_str;
2319 double n;
2320 HRESULT hres;
2321
2322 TRACE("\n");
2323
2324 if(!argc) {
2325 if(r)
2326 *r = jsval_number(NAN);
2327 return S_OK;
2328 }
2329
2330 hres = to_string(ctx, argv[0], &parse_str);
2331 if(FAILED(hres))
2332 return hres;
2333
2334 hres = date_parse(parse_str, &n);
2335 jsstr_release(parse_str);
2336 if(FAILED(hres))
2337 return hres;
2338
2339 *r = jsval_number(n);
2340 return S_OK;
2341 }
2342
date_utc(script_ctx_t * ctx,unsigned argc,jsval_t * argv,double * ret)2343 static HRESULT date_utc(script_ctx_t *ctx, unsigned argc, jsval_t *argv, double *ret)
2344 {
2345 double year, month, vdate, hours, minutes, seconds, ms;
2346 HRESULT hres;
2347
2348 TRACE("\n");
2349
2350 if(argc) {
2351 hres = to_number(ctx, argv[0], &year);
2352 if(FAILED(hres))
2353 return hres;
2354 if(0 <= year && year <= 99)
2355 year += 1900;
2356 }else {
2357 year = 1900;
2358 }
2359
2360 if(argc>1) {
2361 hres = to_number(ctx, argv[1], &month);
2362 if(FAILED(hres))
2363 return hres;
2364 }else {
2365 month = 0;
2366 }
2367
2368 if(argc>2) {
2369 hres = to_number(ctx, argv[2], &vdate);
2370 if(FAILED(hres))
2371 return hres;
2372 }else {
2373 vdate = 1;
2374 }
2375
2376 if(argc>3) {
2377 hres = to_number(ctx, argv[3], &hours);
2378 if(FAILED(hres))
2379 return hres;
2380 }else {
2381 hours = 0;
2382 }
2383
2384 if(argc>4) {
2385 hres = to_number(ctx, argv[4], &minutes);
2386 if(FAILED(hres))
2387 return hres;
2388 }else {
2389 minutes = 0;
2390 }
2391
2392 if(argc>5) {
2393 hres = to_number(ctx, argv[5], &seconds);
2394 if(FAILED(hres))
2395 return hres;
2396 }else {
2397 seconds = 0;
2398 }
2399
2400 if(argc>6) {
2401 hres = to_number(ctx, argv[6], &ms);
2402 if(FAILED(hres))
2403 return hres;
2404 } else {
2405 ms = 0;
2406 }
2407
2408 *ret = time_clip(make_date(make_day(year, month, vdate),
2409 make_time(hours, minutes,seconds, ms)));
2410 return S_OK;
2411 }
2412
DateConstr_UTC(script_ctx_t * ctx,vdisp_t * jsthis,WORD flags,unsigned argc,jsval_t * argv,jsval_t * r)2413 static HRESULT DateConstr_UTC(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
2414 jsval_t *r)
2415 {
2416 double n;
2417 HRESULT hres;
2418
2419 TRACE("\n");
2420
2421 hres = date_utc(ctx, argc, argv, &n);
2422 if(SUCCEEDED(hres) && r)
2423 *r = jsval_number(n);
2424 return hres;
2425 }
2426
2427 /* ECMA-262 5.1 Edition 15.9.4.4 */
DateConstr_now(script_ctx_t * ctx,vdisp_t * jsthis,WORD flags,unsigned argc,jsval_t * argv,jsval_t * r)2428 static HRESULT DateConstr_now(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r)
2429 {
2430 TRACE("\n");
2431
2432 if(r) *r = jsval_number(date_now());
2433 return S_OK;
2434 }
2435
DateConstr_value(script_ctx_t * ctx,vdisp_t * jsthis,WORD flags,unsigned argc,jsval_t * argv,jsval_t * r)2436 static HRESULT DateConstr_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
2437 jsval_t *r)
2438 {
2439 jsdisp_t *date;
2440 HRESULT hres;
2441
2442 TRACE("\n");
2443
2444 switch(flags) {
2445 case DISPATCH_CONSTRUCT:
2446 switch(argc) {
2447 /* ECMA-262 3rd Edition 15.9.3.3 */
2448 case 0:
2449 hres = create_date(ctx, NULL, date_now(), &date);
2450 if(FAILED(hres))
2451 return hres;
2452 break;
2453
2454 /* ECMA-262 3rd Edition 15.9.3.2 */
2455 case 1: {
2456 jsval_t prim;
2457 double n;
2458
2459 hres = to_primitive(ctx, argv[0], &prim, NO_HINT);
2460 if(FAILED(hres))
2461 return hres;
2462
2463 if(is_string(prim))
2464 hres = date_parse(get_string(prim), &n);
2465 else
2466 hres = to_number(ctx, prim, &n);
2467
2468 jsval_release(prim);
2469 if(FAILED(hres))
2470 return hres;
2471
2472 hres = create_date(ctx, NULL, time_clip(n), &date);
2473 if(FAILED(hres))
2474 return hres;
2475 break;
2476 }
2477
2478 /* ECMA-262 3rd Edition 15.9.3.1 */
2479 default: {
2480 double ret_date;
2481 DateInstance *di;
2482
2483 hres = date_utc(ctx, argc, argv, &ret_date);
2484 if(FAILED(hres))
2485 return hres;
2486
2487 hres = create_date(ctx, NULL, ret_date, &date);
2488 if(FAILED(hres))
2489 return hres;
2490
2491 di = date_from_jsdisp(date);
2492 di->time = utc(di->time, di);
2493 }
2494 }
2495
2496 *r = jsval_obj(date);
2497 return S_OK;
2498
2499 case INVOKE_FUNC: {
2500 FILETIME system_time, local_time;
2501 LONGLONG lltime;
2502
2503 GetSystemTimeAsFileTime(&system_time);
2504 FileTimeToLocalFileTime(&system_time, &local_time);
2505 lltime = ((LONGLONG)local_time.dwHighDateTime<<32)
2506 + local_time.dwLowDateTime;
2507
2508 return date_to_string(lltime/10000-TIME_EPOCH, FALSE, 0, r);
2509 }
2510
2511 default:
2512 FIXME("unimplemented flags %x\n", flags);
2513 return E_NOTIMPL;
2514 }
2515
2516 return S_OK;
2517 }
2518
2519 static const builtin_prop_t DateConstr_props[] = {
2520 {UTCW, DateConstr_UTC, PROPF_METHOD},
2521 {nowW, DateConstr_now, PROPF_HTML|PROPF_METHOD},
2522 {parseW, DateConstr_parse, PROPF_METHOD}
2523 };
2524
2525 static const builtin_info_t DateConstr_info = {
2526 JSCLASS_FUNCTION,
2527 DEFAULT_FUNCTION_VALUE,
2528 ARRAY_SIZE(DateConstr_props),
2529 DateConstr_props,
2530 NULL,
2531 NULL
2532 };
2533
create_date_constr(script_ctx_t * ctx,jsdisp_t * object_prototype,jsdisp_t ** ret)2534 HRESULT create_date_constr(script_ctx_t *ctx, jsdisp_t *object_prototype, jsdisp_t **ret)
2535 {
2536 jsdisp_t *date;
2537 HRESULT hres;
2538
2539 static const WCHAR DateW[] = {'D','a','t','e',0};
2540
2541 hres = create_date(ctx, object_prototype, 0.0, &date);
2542 if(FAILED(hres))
2543 return hres;
2544
2545 hres = create_builtin_constructor(ctx, DateConstr_value, DateW, &DateConstr_info,
2546 PROPF_CONSTR|7, date, ret);
2547
2548 jsdisp_release(date);
2549 return hres;
2550 }
2551