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
);
31 /* ECMA-262 3rd Edition 15.9.1.1 */
35 static const WCHAR toStringW
[] = {'t','o','S','t','r','i','n','g',0};
36 static const WCHAR toLocaleStringW
[] = {'t','o','L','o','c','a','l','e','S','t','r','i','n','g',0};
37 static const WCHAR hasOwnPropertyW
[] = {'h','a','s','O','w','n','P','r','o','p','e','r','t','y',0};
38 static const WCHAR propertyIsEnumerableW
[] =
39 {'p','r','o','p','e','r','t','y','I','s','E','n','u','m','e','r','a','b','l','e',0};
40 static const WCHAR isPrototypeOfW
[] = {'i','s','P','r','o','t','o','t','y','p','e','O','f',0};
41 static const WCHAR valueOfW
[] = {'v','a','l','u','e','O','f',0};
42 static const WCHAR toUTCStringW
[] = {'t','o','U','T','C','S','t','r','i','n','g',0};
43 static const WCHAR toDateStringW
[] = {'t','o','D','a','t','e','S','t','r','i','n','g',0};
44 static const WCHAR toTimeStringW
[] = {'t','o','T','i','m','e','S','t','r','i','n','g',0};
45 static const WCHAR toLocaleDateStringW
[] = {'t','o','L','o','c','a','l','e','D','a','t','e','S','t','r','i','n','g',0};
46 static const WCHAR toLocaleTimeStringW
[] = {'t','o','L','o','c','a','l','e','T','i','m','e','S','t','r','i','n','g',0};
47 static const WCHAR getTimeW
[] = {'g','e','t','T','i','m','e',0};
48 static const WCHAR getFullYearW
[] = {'g','e','t','F','u','l','l','Y','e','a','r',0};
49 static const WCHAR getUTCFullYearW
[] = {'g','e','t','U','T','C','F','u','l','l','Y','e','a','r',0};
50 static const WCHAR getMonthW
[] = {'g','e','t','M','o','n','t','h',0};
51 static const WCHAR getUTCMonthW
[] = {'g','e','t','U','T','C','M','o','n','t','h',0};
52 static const WCHAR getDateW
[] = {'g','e','t','D','a','t','e',0};
53 static const WCHAR getUTCDateW
[] = {'g','e','t','U','T','C','D','a','t','e',0};
54 static const WCHAR getDayW
[] = {'g','e','t','D','a','y',0};
55 static const WCHAR getUTCDayW
[] = {'g','e','t','U','T','C','D','a','y',0};
56 static const WCHAR getHoursW
[] = {'g','e','t','H','o','u','r','s',0};
57 static const WCHAR getUTCHoursW
[] = {'g','e','t','U','T','C','H','o','u','r','s',0};
58 static const WCHAR getMinutesW
[] = {'g','e','t','M','i','n','u','t','e','s',0};
59 static const WCHAR getUTCMinutesW
[] = {'g','e','t','U','T','C','M','i','n','u','t','e','s',0};
60 static const WCHAR getSecondsW
[] = {'g','e','t','S','e','c','o','n','d','s',0};
61 static const WCHAR getUTCSecondsW
[] = {'g','e','t','U','T','C','S','e','c','o','n','d','s',0};
62 static const WCHAR getMilisecondsW
[] = {'g','e','t','M','i','l','i','s','e','c','o','n','d','s',0};
63 static const WCHAR getUTCMilisecondsW
[] = {'g','e','t','U','T','C','M','i','l','i','s','e','c','o','n','d','s',0};
64 static const WCHAR getTimezoneOffsetW
[] = {'g','e','t','T','i','m','e','z','o','n','e','O','f','f','s','e','t',0};
65 static const WCHAR setTimeW
[] = {'s','e','t','T','i','m','e',0};
66 static const WCHAR setMilisecondsW
[] = {'s','e','t','M','i','l','i','s','e','c','o','n','d','s',0};
67 static const WCHAR setUTCMilisecondsW
[] = {'s','e','t','U','T','C','M','i','l','i','s','e','c','o','n','d','s',0};
68 static const WCHAR setSecondsW
[] = {'s','e','t','S','e','c','o','n','d','s',0};
69 static const WCHAR setUTCSecondsW
[] = {'s','e','t','U','T','C','S','e','c','o','n','d','s',0};
70 static const WCHAR setMinutesW
[] = {'s','e','t','M','i','n','u','t','e','s',0};
71 static const WCHAR setUTCMinutesW
[] = {'s','e','t','U','T','C','M','i','n','u','t','e','s',0};
72 static const WCHAR setHoursW
[] = {'s','e','t','H','o','u','r','s',0};
73 static const WCHAR setUTCHoursW
[] = {'s','e','t','H','o','u','r','s',0};
74 static const WCHAR setDateW
[] = {'s','e','t','D','a','t','e',0};
75 static const WCHAR setUTCDateW
[] = {'s','e','t','U','T','C','D','a','t','e',0};
76 static const WCHAR setMonthW
[] = {'s','e','t','M','o','n','t','h',0};
77 static const WCHAR setUTCMonthW
[] = {'s','e','t','U','T','C','M','o','n','t','h',0};
78 static const WCHAR setFullYearW
[] = {'s','e','t','F','u','l','l','Y','e','a','r',0};
79 static const WCHAR setUTCFullYearW
[] = {'s','e','t','U','T','C','F','u','l','l','Y','e','a','r',0};
81 /* ECMA-262 3rd Edition 15.9.1.14 */
82 static inline DOUBLE
time_clip(DOUBLE time
)
84 /* FIXME: Handle inf */
86 if(8.64e15
< time
|| time
< -8.64e15
) {
87 FIXME("return NaN\n");
94 static HRESULT
Date_toString(DispatchEx
*dispex
, LCID lcid
, WORD flags
, DISPPARAMS
*dp
,
95 VARIANT
*retv
, jsexcept_t
*ei
, IServiceProvider
*caller
)
101 static HRESULT
Date_toLocaleString(DispatchEx
*dispex
, LCID lcid
, WORD flags
, DISPPARAMS
*dp
,
102 VARIANT
*retv
, jsexcept_t
*ei
, IServiceProvider
*caller
)
108 static HRESULT
Date_hasOwnProperty(DispatchEx
*dispex
, LCID lcid
, WORD flags
, DISPPARAMS
*dp
,
109 VARIANT
*retv
, jsexcept_t
*ei
, IServiceProvider
*caller
)
115 static HRESULT
Date_propertyIsEnumerable(DispatchEx
*dispex
, LCID lcid
, WORD flags
, DISPPARAMS
*dp
,
116 VARIANT
*retv
, jsexcept_t
*ei
, IServiceProvider
*caller
)
122 static HRESULT
Date_isPrototypeOf(DispatchEx
*dispex
, LCID lcid
, WORD flags
, DISPPARAMS
*dp
,
123 VARIANT
*retv
, jsexcept_t
*ei
, IServiceProvider
*caller
)
129 static HRESULT
Date_valueOf(DispatchEx
*dispex
, LCID lcid
, WORD flags
, DISPPARAMS
*dp
,
130 VARIANT
*retv
, jsexcept_t
*ei
, IServiceProvider
*caller
)
136 static HRESULT
Date_toUTCString(DispatchEx
*dispex
, LCID lcid
, WORD flags
, DISPPARAMS
*dp
,
137 VARIANT
*retv
, jsexcept_t
*ei
, IServiceProvider
*caller
)
143 static HRESULT
Date_toDateString(DispatchEx
*dispex
, LCID lcid
, WORD flags
, DISPPARAMS
*dp
,
144 VARIANT
*retv
, jsexcept_t
*ei
, IServiceProvider
*caller
)
150 static HRESULT
Date_toTimeString(DispatchEx
*dispex
, LCID lcid
, WORD flags
, DISPPARAMS
*dp
,
151 VARIANT
*retv
, jsexcept_t
*ei
, IServiceProvider
*caller
)
157 static HRESULT
Date_toLocaleDateString(DispatchEx
*dispex
, LCID lcid
, WORD flags
, DISPPARAMS
*dp
,
158 VARIANT
*retv
, jsexcept_t
*ei
, IServiceProvider
*caller
)
164 static HRESULT
Date_toLocaleTimeString(DispatchEx
*dispex
, LCID lcid
, WORD flags
, DISPPARAMS
*dp
,
165 VARIANT
*retv
, jsexcept_t
*ei
, IServiceProvider
*caller
)
171 /* ECMA-262 3rd Edition 15.9.5.9 */
172 static HRESULT
Date_getTime(DispatchEx
*dispex
, LCID lcid
, WORD flags
, DISPPARAMS
*dp
,
173 VARIANT
*retv
, jsexcept_t
*ei
, IServiceProvider
*caller
)
177 if(!is_class(dispex
, JSCLASS_DATE
)) {
178 FIXME("throw TypeError\n");
183 DateInstance
*date
= (DateInstance
*)dispex
;
184 num_set_val(retv
, date
->time
);
189 static HRESULT
Date_getFullYear(DispatchEx
*dispex
, LCID lcid
, WORD flags
, DISPPARAMS
*dp
,
190 VARIANT
*retv
, jsexcept_t
*ei
, IServiceProvider
*caller
)
196 static HRESULT
Date_getUTCFullYear(DispatchEx
*dispex
, LCID lcid
, WORD flags
, DISPPARAMS
*dp
,
197 VARIANT
*retv
, jsexcept_t
*ei
, IServiceProvider
*caller
)
203 static HRESULT
Date_getMonth(DispatchEx
*dispex
, LCID lcid
, WORD flags
, DISPPARAMS
*dp
,
204 VARIANT
*retv
, jsexcept_t
*ei
, IServiceProvider
*caller
)
210 static HRESULT
Date_getUTCMonth(DispatchEx
*dispex
, LCID lcid
, WORD flags
, DISPPARAMS
*dp
,
211 VARIANT
*retv
, jsexcept_t
*ei
, IServiceProvider
*caller
)
217 static HRESULT
Date_getDate(DispatchEx
*dispex
, LCID lcid
, WORD flags
, DISPPARAMS
*dp
,
218 VARIANT
*retv
, jsexcept_t
*ei
, IServiceProvider
*caller
)
224 static HRESULT
Date_getUTCDate(DispatchEx
*dispex
, LCID lcid
, WORD flags
, DISPPARAMS
*dp
,
225 VARIANT
*retv
, jsexcept_t
*ei
, IServiceProvider
*caller
)
231 static HRESULT
Date_getDay(DispatchEx
*dispex
, LCID lcid
, WORD flags
, DISPPARAMS
*dp
,
232 VARIANT
*retv
, jsexcept_t
*ei
, IServiceProvider
*caller
)
238 static HRESULT
Date_getUTCDay(DispatchEx
*dispex
, LCID lcid
, WORD flags
, DISPPARAMS
*dp
,
239 VARIANT
*retv
, jsexcept_t
*ei
, IServiceProvider
*caller
)
245 static HRESULT
Date_getHours(DispatchEx
*dispex
, LCID lcid
, WORD flags
, DISPPARAMS
*dp
,
246 VARIANT
*retv
, jsexcept_t
*ei
, IServiceProvider
*caller
)
252 static HRESULT
Date_getUTCHours(DispatchEx
*dispex
, LCID lcid
, WORD flags
, DISPPARAMS
*dp
,
253 VARIANT
*retv
, jsexcept_t
*ei
, IServiceProvider
*caller
)
259 static HRESULT
Date_getMinutes(DispatchEx
*dispex
, LCID lcid
, WORD flags
, DISPPARAMS
*dp
,
260 VARIANT
*retv
, jsexcept_t
*ei
, IServiceProvider
*caller
)
266 static HRESULT
Date_getUTCMinutes(DispatchEx
*dispex
, LCID lcid
, WORD flags
, DISPPARAMS
*dp
,
267 VARIANT
*retv
, jsexcept_t
*ei
, IServiceProvider
*caller
)
273 static HRESULT
Date_getSeconds(DispatchEx
*dispex
, LCID lcid
, WORD flags
, DISPPARAMS
*dp
,
274 VARIANT
*retv
, jsexcept_t
*ei
, IServiceProvider
*caller
)
280 static HRESULT
Date_getUTCSeconds(DispatchEx
*dispex
, LCID lcid
, WORD flags
, DISPPARAMS
*dp
,
281 VARIANT
*retv
, jsexcept_t
*ei
, IServiceProvider
*caller
)
287 static HRESULT
Date_getMiliseconds(DispatchEx
*dispex
, LCID lcid
, WORD flags
, DISPPARAMS
*dp
,
288 VARIANT
*retv
, jsexcept_t
*ei
, IServiceProvider
*caller
)
294 static HRESULT
Date_getUTCMiliseconds(DispatchEx
*dispex
, LCID lcid
, WORD flags
, DISPPARAMS
*dp
,
295 VARIANT
*retv
, jsexcept_t
*ei
, IServiceProvider
*caller
)
301 static HRESULT
Date_getTimezoneOffset(DispatchEx
*dispex
, LCID lcid
, WORD flags
, DISPPARAMS
*dp
,
302 VARIANT
*retv
, jsexcept_t
*ei
, IServiceProvider
*caller
)
308 static HRESULT
Date_setTime(DispatchEx
*dispex
, LCID lcid
, WORD flags
, DISPPARAMS
*dp
,
309 VARIANT
*retv
, jsexcept_t
*ei
, IServiceProvider
*caller
)
315 static HRESULT
Date_setMiliseconds(DispatchEx
*dispex
, LCID lcid
, WORD flags
, DISPPARAMS
*dp
,
316 VARIANT
*retv
, jsexcept_t
*ei
, IServiceProvider
*caller
)
322 static HRESULT
Date_setUTCMiliseconds(DispatchEx
*dispex
, LCID lcid
, WORD flags
, DISPPARAMS
*dp
,
323 VARIANT
*retv
, jsexcept_t
*ei
, IServiceProvider
*caller
)
329 static HRESULT
Date_setSeconds(DispatchEx
*dispex
, LCID lcid
, WORD flags
, DISPPARAMS
*dp
,
330 VARIANT
*retv
, jsexcept_t
*ei
, IServiceProvider
*caller
)
336 static HRESULT
Date_setUTCSeconds(DispatchEx
*dispex
, LCID lcid
, WORD flags
, DISPPARAMS
*dp
,
337 VARIANT
*retv
, jsexcept_t
*ei
, IServiceProvider
*caller
)
343 static HRESULT
Date_setMinutes(DispatchEx
*dispex
, LCID lcid
, WORD flags
, DISPPARAMS
*dp
,
344 VARIANT
*retv
, jsexcept_t
*ei
, IServiceProvider
*caller
)
350 static HRESULT
Date_setUTCMinutes(DispatchEx
*dispex
, LCID lcid
, WORD flags
, DISPPARAMS
*dp
,
351 VARIANT
*retv
, jsexcept_t
*ei
, IServiceProvider
*caller
)
357 static HRESULT
Date_setHours(DispatchEx
*dispex
, LCID lcid
, WORD flags
, DISPPARAMS
*dp
,
358 VARIANT
*retv
, jsexcept_t
*ei
, IServiceProvider
*caller
)
364 static HRESULT
Date_setUTCHours(DispatchEx
*dispex
, LCID lcid
, WORD flags
, DISPPARAMS
*dp
,
365 VARIANT
*retv
, jsexcept_t
*ei
, IServiceProvider
*caller
)
371 static HRESULT
Date_setDate(DispatchEx
*dispex
, LCID lcid
, WORD flags
, DISPPARAMS
*dp
,
372 VARIANT
*retv
, jsexcept_t
*ei
, IServiceProvider
*caller
)
378 static HRESULT
Date_setUTCDate(DispatchEx
*dispex
, LCID lcid
, WORD flags
, DISPPARAMS
*dp
,
379 VARIANT
*retv
, jsexcept_t
*ei
, IServiceProvider
*caller
)
385 static HRESULT
Date_setMonth(DispatchEx
*dispex
, LCID lcid
, WORD flags
, DISPPARAMS
*dp
,
386 VARIANT
*retv
, jsexcept_t
*ei
, IServiceProvider
*caller
)
392 static HRESULT
Date_setUTCMonth(DispatchEx
*dispex
, LCID lcid
, WORD flags
, DISPPARAMS
*dp
,
393 VARIANT
*retv
, jsexcept_t
*ei
, IServiceProvider
*caller
)
399 static HRESULT
Date_setFullYear(DispatchEx
*dispex
, LCID lcid
, WORD flags
, DISPPARAMS
*dp
,
400 VARIANT
*retv
, jsexcept_t
*ei
, IServiceProvider
*caller
)
406 static HRESULT
Date_setUTCFullYear(DispatchEx
*dispex
, LCID lcid
, WORD flags
, DISPPARAMS
*dp
,
407 VARIANT
*retv
, jsexcept_t
*ei
, IServiceProvider
*caller
)
413 static HRESULT
Date_value(DispatchEx
*dispex
, LCID lcid
, WORD flags
, DISPPARAMS
*dp
,
414 VARIANT
*retv
, jsexcept_t
*ei
, IServiceProvider
*caller
)
420 static const builtin_prop_t Date_props
[] = {
421 {getDateW
, Date_getDate
, PROPF_METHOD
},
422 {getDayW
, Date_getDay
, PROPF_METHOD
},
423 {getFullYearW
, Date_getFullYear
, PROPF_METHOD
},
424 {getHoursW
, Date_getHours
, PROPF_METHOD
},
425 {getMilisecondsW
, Date_getMiliseconds
, PROPF_METHOD
},
426 {getMinutesW
, Date_getMinutes
, PROPF_METHOD
},
427 {getMonthW
, Date_getMonth
, PROPF_METHOD
},
428 {getSecondsW
, Date_getSeconds
, PROPF_METHOD
},
429 {getTimeW
, Date_getTime
, PROPF_METHOD
},
430 {getTimezoneOffsetW
, Date_getTimezoneOffset
, PROPF_METHOD
},
431 {getUTCDateW
, Date_getUTCDate
, PROPF_METHOD
},
432 {getUTCDayW
, Date_getUTCDay
, PROPF_METHOD
},
433 {getUTCFullYearW
, Date_getUTCFullYear
, PROPF_METHOD
},
434 {getUTCHoursW
, Date_getUTCHours
, PROPF_METHOD
},
435 {getUTCMilisecondsW
, Date_getUTCMiliseconds
, PROPF_METHOD
},
436 {getUTCMinutesW
, Date_getUTCMinutes
, PROPF_METHOD
},
437 {getUTCMonthW
, Date_getUTCMonth
, PROPF_METHOD
},
438 {getUTCSecondsW
, Date_getUTCSeconds
, PROPF_METHOD
},
439 {hasOwnPropertyW
, Date_hasOwnProperty
, PROPF_METHOD
},
440 {isPrototypeOfW
, Date_isPrototypeOf
, PROPF_METHOD
},
441 {propertyIsEnumerableW
, Date_propertyIsEnumerable
, PROPF_METHOD
},
442 {setDateW
, Date_setDate
, PROPF_METHOD
},
443 {setFullYearW
, Date_setFullYear
, PROPF_METHOD
},
444 {setHoursW
, Date_setHours
, PROPF_METHOD
},
445 {setMilisecondsW
, Date_setMiliseconds
, PROPF_METHOD
},
446 {setMinutesW
, Date_setMinutes
, PROPF_METHOD
},
447 {setMonthW
, Date_setMonth
, PROPF_METHOD
},
448 {setSecondsW
, Date_setSeconds
, PROPF_METHOD
},
449 {setTimeW
, Date_setTime
, PROPF_METHOD
},
450 {setUTCDateW
, Date_setUTCDate
, PROPF_METHOD
},
451 {setUTCFullYearW
, Date_setUTCFullYear
, PROPF_METHOD
},
452 {setUTCHoursW
, Date_setUTCHours
, PROPF_METHOD
},
453 {setUTCMilisecondsW
, Date_setUTCMiliseconds
, PROPF_METHOD
},
454 {setUTCMinutesW
, Date_setUTCMinutes
, PROPF_METHOD
},
455 {setUTCMonthW
, Date_setUTCMonth
, PROPF_METHOD
},
456 {setUTCSecondsW
, Date_setUTCSeconds
, PROPF_METHOD
},
457 {toDateStringW
, Date_toDateString
, PROPF_METHOD
},
458 {toLocaleDateStringW
, Date_toLocaleDateString
, PROPF_METHOD
},
459 {toLocaleStringW
, Date_toLocaleString
, PROPF_METHOD
},
460 {toLocaleTimeStringW
, Date_toLocaleTimeString
, PROPF_METHOD
},
461 {toStringW
, Date_toString
, PROPF_METHOD
},
462 {toTimeStringW
, Date_toTimeString
, PROPF_METHOD
},
463 {toUTCStringW
, Date_toUTCString
, PROPF_METHOD
},
464 {valueOfW
, Date_valueOf
, PROPF_METHOD
},
467 static const builtin_info_t Date_info
= {
469 {NULL
, Date_value
, 0},
470 sizeof(Date_props
)/sizeof(*Date_props
),
476 static HRESULT
create_date(script_ctx_t
*ctx
, BOOL use_constr
, DOUBLE time
, DispatchEx
**ret
)
481 date
= heap_alloc_zero(sizeof(DateInstance
));
483 return E_OUTOFMEMORY
;
486 hres
= init_dispex_from_constr(&date
->dispex
, ctx
, &Date_info
, ctx
->date_constr
);
488 hres
= init_dispex(&date
->dispex
, ctx
, &Date_info
, NULL
);
496 *ret
= &date
->dispex
;
500 static HRESULT
DateConstr_value(DispatchEx
*dispex
, LCID lcid
, WORD flags
, DISPPARAMS
*dp
,
501 VARIANT
*retv
, jsexcept_t
*ei
, IServiceProvider
*sp
)
509 case DISPATCH_CONSTRUCT
:
510 switch(arg_cnt(dp
)) {
511 /* ECMA-262 3rd Edition 15.9.3.3 */
515 GetSystemTimeAsFileTime(&time
);
517 hres
= create_date(dispex
->ctx
, TRUE
,
518 floor((DOUBLE
)(time
.dwLowDateTime
/1e6
) + (DOUBLE
)time
.dwHighDateTime
*((DOUBLE
)UINT_MAX
+1.0)/1.e6
),
525 /* ECMA-262 3rd Edition 15.9.3.2 */
529 hres
= to_primitive(dispex
->ctx
, get_arg(dp
,0), ei
, &prim
);
533 if(V_VT(&prim
) == VT_BSTR
) {
534 FIXME("VT_BSTR not supported\n");
538 hres
= to_number(dispex
->ctx
, &prim
, ei
, &num
);
543 hres
= create_date(dispex
->ctx
, TRUE
, time_clip(num_val(&num
)), &date
);
550 FIXME("unimplemented argcnt %d\n", arg_cnt(dp
));
554 V_VT(retv
) = VT_DISPATCH
;
555 V_DISPATCH(retv
) = (IDispatch
*)_IDispatchEx_(date
);
559 FIXME("unimplemented flags %x\n", flags
);
566 HRESULT
create_date_constr(script_ctx_t
*ctx
, DispatchEx
**ret
)
571 hres
= create_date(ctx
, FALSE
, 0.0, &date
);
575 hres
= create_builtin_function(ctx
, DateConstr_value
, PROPF_CONSTR
, date
, ret
);
577 jsdisp_release(date
);