2 * Copyright 2008 Jacek Caban for CodeWeavers
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
24 #include "wine/debug.h"
26 WINE_DEFAULT_DEBUG_CHANNEL(jscript
);
28 /* 1601 to 1970 is 369 years plus 89 leap days */
29 #define TIME_EPOCH ((ULONGLONG)(369 * 365 + 89) * 86400 * 1000)
34 /* ECMA-262 3rd Edition 15.9.1.1 */
40 static const WCHAR toStringW
[] = {'t','o','S','t','r','i','n','g',0};
41 static const WCHAR toLocaleStringW
[] = {'t','o','L','o','c','a','l','e','S','t','r','i','n','g',0};
42 static const WCHAR hasOwnPropertyW
[] = {'h','a','s','O','w','n','P','r','o','p','e','r','t','y',0};
43 static const WCHAR propertyIsEnumerableW
[] =
44 {'p','r','o','p','e','r','t','y','I','s','E','n','u','m','e','r','a','b','l','e',0};
45 static const WCHAR isPrototypeOfW
[] = {'i','s','P','r','o','t','o','t','y','p','e','O','f',0};
46 static const WCHAR valueOfW
[] = {'v','a','l','u','e','O','f',0};
47 static const WCHAR toUTCStringW
[] = {'t','o','U','T','C','S','t','r','i','n','g',0};
48 static const WCHAR toDateStringW
[] = {'t','o','D','a','t','e','S','t','r','i','n','g',0};
49 static const WCHAR toTimeStringW
[] = {'t','o','T','i','m','e','S','t','r','i','n','g',0};
50 static const WCHAR toLocaleDateStringW
[] = {'t','o','L','o','c','a','l','e','D','a','t','e','S','t','r','i','n','g',0};
51 static const WCHAR toLocaleTimeStringW
[] = {'t','o','L','o','c','a','l','e','T','i','m','e','S','t','r','i','n','g',0};
52 static const WCHAR getTimeW
[] = {'g','e','t','T','i','m','e',0};
53 static const WCHAR getFullYearW
[] = {'g','e','t','F','u','l','l','Y','e','a','r',0};
54 static const WCHAR getUTCFullYearW
[] = {'g','e','t','U','T','C','F','u','l','l','Y','e','a','r',0};
55 static const WCHAR getMonthW
[] = {'g','e','t','M','o','n','t','h',0};
56 static const WCHAR getUTCMonthW
[] = {'g','e','t','U','T','C','M','o','n','t','h',0};
57 static const WCHAR getDateW
[] = {'g','e','t','D','a','t','e',0};
58 static const WCHAR getUTCDateW
[] = {'g','e','t','U','T','C','D','a','t','e',0};
59 static const WCHAR getDayW
[] = {'g','e','t','D','a','y',0};
60 static const WCHAR getUTCDayW
[] = {'g','e','t','U','T','C','D','a','y',0};
61 static const WCHAR getHoursW
[] = {'g','e','t','H','o','u','r','s',0};
62 static const WCHAR getUTCHoursW
[] = {'g','e','t','U','T','C','H','o','u','r','s',0};
63 static const WCHAR getMinutesW
[] = {'g','e','t','M','i','n','u','t','e','s',0};
64 static const WCHAR getUTCMinutesW
[] = {'g','e','t','U','T','C','M','i','n','u','t','e','s',0};
65 static const WCHAR getSecondsW
[] = {'g','e','t','S','e','c','o','n','d','s',0};
66 static const WCHAR getUTCSecondsW
[] = {'g','e','t','U','T','C','S','e','c','o','n','d','s',0};
67 static const WCHAR getMilisecondsW
[] = {'g','e','t','M','i','l','i','s','e','c','o','n','d','s',0};
68 static const WCHAR getUTCMilisecondsW
[] = {'g','e','t','U','T','C','M','i','l','i','s','e','c','o','n','d','s',0};
69 static const WCHAR getTimezoneOffsetW
[] = {'g','e','t','T','i','m','e','z','o','n','e','O','f','f','s','e','t',0};
70 static const WCHAR setTimeW
[] = {'s','e','t','T','i','m','e',0};
71 static const WCHAR setMilisecondsW
[] = {'s','e','t','M','i','l','i','s','e','c','o','n','d','s',0};
72 static const WCHAR setUTCMilisecondsW
[] = {'s','e','t','U','T','C','M','i','l','i','s','e','c','o','n','d','s',0};
73 static const WCHAR setSecondsW
[] = {'s','e','t','S','e','c','o','n','d','s',0};
74 static const WCHAR setUTCSecondsW
[] = {'s','e','t','U','T','C','S','e','c','o','n','d','s',0};
75 static const WCHAR setMinutesW
[] = {'s','e','t','M','i','n','u','t','e','s',0};
76 static const WCHAR setUTCMinutesW
[] = {'s','e','t','U','T','C','M','i','n','u','t','e','s',0};
77 static const WCHAR setHoursW
[] = {'s','e','t','H','o','u','r','s',0};
78 static const WCHAR setUTCHoursW
[] = {'s','e','t','H','o','u','r','s',0};
79 static const WCHAR setDateW
[] = {'s','e','t','D','a','t','e',0};
80 static const WCHAR setUTCDateW
[] = {'s','e','t','U','T','C','D','a','t','e',0};
81 static const WCHAR setMonthW
[] = {'s','e','t','M','o','n','t','h',0};
82 static const WCHAR setUTCMonthW
[] = {'s','e','t','U','T','C','M','o','n','t','h',0};
83 static const WCHAR setFullYearW
[] = {'s','e','t','F','u','l','l','Y','e','a','r',0};
84 static const WCHAR setUTCFullYearW
[] = {'s','e','t','U','T','C','F','u','l','l','Y','e','a','r',0};
86 /* ECMA-262 3rd Edition 15.9.1.14 */
87 static inline DOUBLE
time_clip(DOUBLE time
)
89 if(8.64e15
< time
|| time
< -8.64e15
) {
96 static HRESULT
Date_toString(DispatchEx
*dispex
, LCID lcid
, WORD flags
, DISPPARAMS
*dp
,
97 VARIANT
*retv
, jsexcept_t
*ei
, IServiceProvider
*caller
)
103 static HRESULT
Date_toLocaleString(DispatchEx
*dispex
, LCID lcid
, WORD flags
, DISPPARAMS
*dp
,
104 VARIANT
*retv
, jsexcept_t
*ei
, IServiceProvider
*caller
)
110 static HRESULT
Date_hasOwnProperty(DispatchEx
*dispex
, LCID lcid
, WORD flags
, DISPPARAMS
*dp
,
111 VARIANT
*retv
, jsexcept_t
*ei
, IServiceProvider
*caller
)
117 static HRESULT
Date_propertyIsEnumerable(DispatchEx
*dispex
, LCID lcid
, WORD flags
, DISPPARAMS
*dp
,
118 VARIANT
*retv
, jsexcept_t
*ei
, IServiceProvider
*caller
)
124 static HRESULT
Date_isPrototypeOf(DispatchEx
*dispex
, LCID lcid
, WORD flags
, DISPPARAMS
*dp
,
125 VARIANT
*retv
, jsexcept_t
*ei
, IServiceProvider
*caller
)
131 static HRESULT
Date_valueOf(DispatchEx
*dispex
, LCID lcid
, WORD flags
, DISPPARAMS
*dp
,
132 VARIANT
*retv
, jsexcept_t
*ei
, IServiceProvider
*caller
)
138 static HRESULT
Date_toUTCString(DispatchEx
*dispex
, LCID lcid
, WORD flags
, DISPPARAMS
*dp
,
139 VARIANT
*retv
, jsexcept_t
*ei
, IServiceProvider
*caller
)
145 static HRESULT
Date_toDateString(DispatchEx
*dispex
, LCID lcid
, WORD flags
, DISPPARAMS
*dp
,
146 VARIANT
*retv
, jsexcept_t
*ei
, IServiceProvider
*caller
)
152 static HRESULT
Date_toTimeString(DispatchEx
*dispex
, LCID lcid
, WORD flags
, DISPPARAMS
*dp
,
153 VARIANT
*retv
, jsexcept_t
*ei
, IServiceProvider
*caller
)
159 static HRESULT
Date_toLocaleDateString(DispatchEx
*dispex
, LCID lcid
, WORD flags
, DISPPARAMS
*dp
,
160 VARIANT
*retv
, jsexcept_t
*ei
, IServiceProvider
*caller
)
166 static HRESULT
Date_toLocaleTimeString(DispatchEx
*dispex
, LCID lcid
, WORD flags
, DISPPARAMS
*dp
,
167 VARIANT
*retv
, jsexcept_t
*ei
, IServiceProvider
*caller
)
173 /* ECMA-262 3rd Edition 15.9.5.9 */
174 static HRESULT
Date_getTime(DispatchEx
*dispex
, LCID lcid
, WORD flags
, DISPPARAMS
*dp
,
175 VARIANT
*retv
, jsexcept_t
*ei
, IServiceProvider
*caller
)
179 if(!is_class(dispex
, JSCLASS_DATE
)) {
180 FIXME("throw TypeError\n");
185 DateInstance
*date
= (DateInstance
*)dispex
;
186 num_set_val(retv
, date
->time
);
191 static HRESULT
Date_getFullYear(DispatchEx
*dispex
, LCID lcid
, WORD flags
, DISPPARAMS
*dp
,
192 VARIANT
*retv
, jsexcept_t
*ei
, IServiceProvider
*caller
)
198 static HRESULT
Date_getUTCFullYear(DispatchEx
*dispex
, LCID lcid
, WORD flags
, DISPPARAMS
*dp
,
199 VARIANT
*retv
, jsexcept_t
*ei
, IServiceProvider
*caller
)
205 static HRESULT
Date_getMonth(DispatchEx
*dispex
, LCID lcid
, WORD flags
, DISPPARAMS
*dp
,
206 VARIANT
*retv
, jsexcept_t
*ei
, IServiceProvider
*caller
)
212 static HRESULT
Date_getUTCMonth(DispatchEx
*dispex
, LCID lcid
, WORD flags
, DISPPARAMS
*dp
,
213 VARIANT
*retv
, jsexcept_t
*ei
, IServiceProvider
*caller
)
219 static HRESULT
Date_getDate(DispatchEx
*dispex
, LCID lcid
, WORD flags
, DISPPARAMS
*dp
,
220 VARIANT
*retv
, jsexcept_t
*ei
, IServiceProvider
*caller
)
226 static HRESULT
Date_getUTCDate(DispatchEx
*dispex
, LCID lcid
, WORD flags
, DISPPARAMS
*dp
,
227 VARIANT
*retv
, jsexcept_t
*ei
, IServiceProvider
*caller
)
233 static HRESULT
Date_getDay(DispatchEx
*dispex
, LCID lcid
, WORD flags
, DISPPARAMS
*dp
,
234 VARIANT
*retv
, jsexcept_t
*ei
, IServiceProvider
*caller
)
240 static HRESULT
Date_getUTCDay(DispatchEx
*dispex
, LCID lcid
, WORD flags
, DISPPARAMS
*dp
,
241 VARIANT
*retv
, jsexcept_t
*ei
, IServiceProvider
*caller
)
247 static HRESULT
Date_getHours(DispatchEx
*dispex
, LCID lcid
, WORD flags
, DISPPARAMS
*dp
,
248 VARIANT
*retv
, jsexcept_t
*ei
, IServiceProvider
*caller
)
254 static HRESULT
Date_getUTCHours(DispatchEx
*dispex
, LCID lcid
, WORD flags
, DISPPARAMS
*dp
,
255 VARIANT
*retv
, jsexcept_t
*ei
, IServiceProvider
*caller
)
261 static HRESULT
Date_getMinutes(DispatchEx
*dispex
, LCID lcid
, WORD flags
, DISPPARAMS
*dp
,
262 VARIANT
*retv
, jsexcept_t
*ei
, IServiceProvider
*caller
)
268 static HRESULT
Date_getUTCMinutes(DispatchEx
*dispex
, LCID lcid
, WORD flags
, DISPPARAMS
*dp
,
269 VARIANT
*retv
, jsexcept_t
*ei
, IServiceProvider
*caller
)
275 static HRESULT
Date_getSeconds(DispatchEx
*dispex
, LCID lcid
, WORD flags
, DISPPARAMS
*dp
,
276 VARIANT
*retv
, jsexcept_t
*ei
, IServiceProvider
*caller
)
282 static HRESULT
Date_getUTCSeconds(DispatchEx
*dispex
, LCID lcid
, WORD flags
, DISPPARAMS
*dp
,
283 VARIANT
*retv
, jsexcept_t
*ei
, IServiceProvider
*caller
)
289 static HRESULT
Date_getMiliseconds(DispatchEx
*dispex
, LCID lcid
, WORD flags
, DISPPARAMS
*dp
,
290 VARIANT
*retv
, jsexcept_t
*ei
, IServiceProvider
*caller
)
296 static HRESULT
Date_getUTCMiliseconds(DispatchEx
*dispex
, LCID lcid
, WORD flags
, DISPPARAMS
*dp
,
297 VARIANT
*retv
, jsexcept_t
*ei
, IServiceProvider
*caller
)
303 static HRESULT
Date_getTimezoneOffset(DispatchEx
*dispex
, LCID lcid
, WORD flags
, DISPPARAMS
*dp
,
304 VARIANT
*retv
, jsexcept_t
*ei
, IServiceProvider
*caller
)
310 static HRESULT
Date_setTime(DispatchEx
*dispex
, LCID lcid
, WORD flags
, DISPPARAMS
*dp
,
311 VARIANT
*retv
, jsexcept_t
*ei
, IServiceProvider
*caller
)
319 if(!is_class(dispex
, JSCLASS_DATE
)) {
320 FIXME("throw TypeError\n");
325 if(retv
) num_set_nan(retv
);
329 hres
= to_number(dispex
->ctx
, get_arg(dp
, 0), ei
, &v
);
333 date
= (DateInstance
*)dispex
;
334 date
->time
= time_clip(num_val(&v
));
337 num_set_val(retv
, date
->time
);
342 static HRESULT
Date_setMiliseconds(DispatchEx
*dispex
, LCID lcid
, WORD flags
, DISPPARAMS
*dp
,
343 VARIANT
*retv
, jsexcept_t
*ei
, IServiceProvider
*caller
)
349 static HRESULT
Date_setUTCMiliseconds(DispatchEx
*dispex
, LCID lcid
, WORD flags
, DISPPARAMS
*dp
,
350 VARIANT
*retv
, jsexcept_t
*ei
, IServiceProvider
*caller
)
356 static HRESULT
Date_setSeconds(DispatchEx
*dispex
, LCID lcid
, WORD flags
, DISPPARAMS
*dp
,
357 VARIANT
*retv
, jsexcept_t
*ei
, IServiceProvider
*caller
)
363 static HRESULT
Date_setUTCSeconds(DispatchEx
*dispex
, LCID lcid
, WORD flags
, DISPPARAMS
*dp
,
364 VARIANT
*retv
, jsexcept_t
*ei
, IServiceProvider
*caller
)
370 static HRESULT
Date_setMinutes(DispatchEx
*dispex
, LCID lcid
, WORD flags
, DISPPARAMS
*dp
,
371 VARIANT
*retv
, jsexcept_t
*ei
, IServiceProvider
*caller
)
377 static HRESULT
Date_setUTCMinutes(DispatchEx
*dispex
, LCID lcid
, WORD flags
, DISPPARAMS
*dp
,
378 VARIANT
*retv
, jsexcept_t
*ei
, IServiceProvider
*caller
)
384 static HRESULT
Date_setHours(DispatchEx
*dispex
, LCID lcid
, WORD flags
, DISPPARAMS
*dp
,
385 VARIANT
*retv
, jsexcept_t
*ei
, IServiceProvider
*caller
)
391 static HRESULT
Date_setUTCHours(DispatchEx
*dispex
, LCID lcid
, WORD flags
, DISPPARAMS
*dp
,
392 VARIANT
*retv
, jsexcept_t
*ei
, IServiceProvider
*caller
)
398 static HRESULT
Date_setDate(DispatchEx
*dispex
, LCID lcid
, WORD flags
, DISPPARAMS
*dp
,
399 VARIANT
*retv
, jsexcept_t
*ei
, IServiceProvider
*caller
)
405 static HRESULT
Date_setUTCDate(DispatchEx
*dispex
, LCID lcid
, WORD flags
, DISPPARAMS
*dp
,
406 VARIANT
*retv
, jsexcept_t
*ei
, IServiceProvider
*caller
)
412 static HRESULT
Date_setMonth(DispatchEx
*dispex
, LCID lcid
, WORD flags
, DISPPARAMS
*dp
,
413 VARIANT
*retv
, jsexcept_t
*ei
, IServiceProvider
*caller
)
419 static HRESULT
Date_setUTCMonth(DispatchEx
*dispex
, LCID lcid
, WORD flags
, DISPPARAMS
*dp
,
420 VARIANT
*retv
, jsexcept_t
*ei
, IServiceProvider
*caller
)
426 static HRESULT
Date_setFullYear(DispatchEx
*dispex
, LCID lcid
, WORD flags
, DISPPARAMS
*dp
,
427 VARIANT
*retv
, jsexcept_t
*ei
, IServiceProvider
*caller
)
433 static HRESULT
Date_setUTCFullYear(DispatchEx
*dispex
, LCID lcid
, WORD flags
, DISPPARAMS
*dp
,
434 VARIANT
*retv
, jsexcept_t
*ei
, IServiceProvider
*caller
)
440 static HRESULT
Date_value(DispatchEx
*dispex
, LCID lcid
, WORD flags
, DISPPARAMS
*dp
,
441 VARIANT
*retv
, jsexcept_t
*ei
, IServiceProvider
*caller
)
447 static const builtin_prop_t Date_props
[] = {
448 {getDateW
, Date_getDate
, PROPF_METHOD
},
449 {getDayW
, Date_getDay
, PROPF_METHOD
},
450 {getFullYearW
, Date_getFullYear
, PROPF_METHOD
},
451 {getHoursW
, Date_getHours
, PROPF_METHOD
},
452 {getMilisecondsW
, Date_getMiliseconds
, PROPF_METHOD
},
453 {getMinutesW
, Date_getMinutes
, PROPF_METHOD
},
454 {getMonthW
, Date_getMonth
, PROPF_METHOD
},
455 {getSecondsW
, Date_getSeconds
, PROPF_METHOD
},
456 {getTimeW
, Date_getTime
, PROPF_METHOD
},
457 {getTimezoneOffsetW
, Date_getTimezoneOffset
, PROPF_METHOD
},
458 {getUTCDateW
, Date_getUTCDate
, PROPF_METHOD
},
459 {getUTCDayW
, Date_getUTCDay
, PROPF_METHOD
},
460 {getUTCFullYearW
, Date_getUTCFullYear
, PROPF_METHOD
},
461 {getUTCHoursW
, Date_getUTCHours
, PROPF_METHOD
},
462 {getUTCMilisecondsW
, Date_getUTCMiliseconds
, PROPF_METHOD
},
463 {getUTCMinutesW
, Date_getUTCMinutes
, PROPF_METHOD
},
464 {getUTCMonthW
, Date_getUTCMonth
, PROPF_METHOD
},
465 {getUTCSecondsW
, Date_getUTCSeconds
, PROPF_METHOD
},
466 {hasOwnPropertyW
, Date_hasOwnProperty
, PROPF_METHOD
},
467 {isPrototypeOfW
, Date_isPrototypeOf
, PROPF_METHOD
},
468 {propertyIsEnumerableW
, Date_propertyIsEnumerable
, PROPF_METHOD
},
469 {setDateW
, Date_setDate
, PROPF_METHOD
},
470 {setFullYearW
, Date_setFullYear
, PROPF_METHOD
},
471 {setHoursW
, Date_setHours
, PROPF_METHOD
},
472 {setMilisecondsW
, Date_setMiliseconds
, PROPF_METHOD
},
473 {setMinutesW
, Date_setMinutes
, PROPF_METHOD
},
474 {setMonthW
, Date_setMonth
, PROPF_METHOD
},
475 {setSecondsW
, Date_setSeconds
, PROPF_METHOD
},
476 {setTimeW
, Date_setTime
, PROPF_METHOD
},
477 {setUTCDateW
, Date_setUTCDate
, PROPF_METHOD
},
478 {setUTCFullYearW
, Date_setUTCFullYear
, PROPF_METHOD
},
479 {setUTCHoursW
, Date_setUTCHours
, PROPF_METHOD
},
480 {setUTCMilisecondsW
, Date_setUTCMiliseconds
, PROPF_METHOD
},
481 {setUTCMinutesW
, Date_setUTCMinutes
, PROPF_METHOD
},
482 {setUTCMonthW
, Date_setUTCMonth
, PROPF_METHOD
},
483 {setUTCSecondsW
, Date_setUTCSeconds
, PROPF_METHOD
},
484 {toDateStringW
, Date_toDateString
, PROPF_METHOD
},
485 {toLocaleDateStringW
, Date_toLocaleDateString
, PROPF_METHOD
},
486 {toLocaleStringW
, Date_toLocaleString
, PROPF_METHOD
},
487 {toLocaleTimeStringW
, Date_toLocaleTimeString
, PROPF_METHOD
},
488 {toStringW
, Date_toString
, PROPF_METHOD
},
489 {toTimeStringW
, Date_toTimeString
, PROPF_METHOD
},
490 {toUTCStringW
, Date_toUTCString
, PROPF_METHOD
},
491 {valueOfW
, Date_valueOf
, PROPF_METHOD
},
494 static const builtin_info_t Date_info
= {
496 {NULL
, Date_value
, 0},
497 sizeof(Date_props
)/sizeof(*Date_props
),
503 static HRESULT
create_date(script_ctx_t
*ctx
, BOOL use_constr
, DOUBLE time
, DispatchEx
**ret
)
507 TIME_ZONE_INFORMATION tzi
;
509 GetTimeZoneInformation(&tzi
);
511 date
= heap_alloc_zero(sizeof(DateInstance
));
513 return E_OUTOFMEMORY
;
516 hres
= init_dispex_from_constr(&date
->dispex
, ctx
, &Date_info
, ctx
->date_constr
);
518 hres
= init_dispex(&date
->dispex
, ctx
, &Date_info
, NULL
);
525 date
->bias
= tzi
.Bias
;
527 *ret
= &date
->dispex
;
531 static HRESULT
DateConstr_value(DispatchEx
*dispex
, LCID lcid
, WORD flags
, DISPPARAMS
*dp
,
532 VARIANT
*retv
, jsexcept_t
*ei
, IServiceProvider
*sp
)
540 case DISPATCH_CONSTRUCT
:
541 switch(arg_cnt(dp
)) {
542 /* ECMA-262 3rd Edition 15.9.3.3 */
547 GetSystemTimeAsFileTime(&time
);
548 lltime
= ((LONGLONG
)time
.dwHighDateTime
<<32)
549 + time
.dwLowDateTime
;
551 hres
= create_date(dispex
->ctx
, TRUE
, lltime
/10000-TIME_EPOCH
, &date
);
557 /* ECMA-262 3rd Edition 15.9.3.2 */
561 hres
= to_primitive(dispex
->ctx
, get_arg(dp
,0), ei
, &prim
);
565 if(V_VT(&prim
) == VT_BSTR
) {
566 FIXME("VT_BSTR not supported\n");
570 hres
= to_number(dispex
->ctx
, &prim
, ei
, &num
);
575 hres
= create_date(dispex
->ctx
, TRUE
, time_clip(num_val(&num
)), &date
);
582 FIXME("unimplemented argcnt %d\n", arg_cnt(dp
));
586 V_VT(retv
) = VT_DISPATCH
;
587 V_DISPATCH(retv
) = (IDispatch
*)_IDispatchEx_(date
);
591 FIXME("unimplemented flags %x\n", flags
);
598 HRESULT
create_date_constr(script_ctx_t
*ctx
, DispatchEx
**ret
)
603 hres
= create_date(ctx
, FALSE
, 0.0, &date
);
607 hres
= create_builtin_function(ctx
, DateConstr_value
, PROPF_CONSTR
, date
, ret
);
609 jsdisp_release(date
);