[ros-diffs] [cwittich] 41769: sync jscript with wine 1.1.25

cwittich at svn.reactos.org cwittich at svn.reactos.org
Sat Jul 4 13:49:54 CEST 2009


Author: cwittich
Date: Sat Jul  4 15:49:53 2009
New Revision: 41769

URL: http://svn.reactos.org/svn/reactos?rev=41769&view=rev
Log:
sync jscript with wine 1.1.25

Modified:
    trunk/reactos/dll/win32/jscript/array.c
    trunk/reactos/dll/win32/jscript/bool.c
    trunk/reactos/dll/win32/jscript/date.c
    trunk/reactos/dll/win32/jscript/dispex.c
    trunk/reactos/dll/win32/jscript/function.c
    trunk/reactos/dll/win32/jscript/jscript.h
    trunk/reactos/dll/win32/jscript/number.c
    trunk/reactos/dll/win32/jscript/object.c
    trunk/reactos/dll/win32/jscript/regexp.c
    trunk/reactos/dll/win32/jscript/string.c

Modified: trunk/reactos/dll/win32/jscript/array.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/jscript/array.c?rev=41769&r1=41768&r2=41769&view=diff
==============================================================================
--- trunk/reactos/dll/win32/jscript/array.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/jscript/array.c [iso-8859-1] Sat Jul  4 15:49:53 2009
@@ -829,7 +829,7 @@
     if(FAILED(hres))
         return hres;
 
-    hres = create_builtin_function(ctx, ArrayConstr_value, PROPF_CONSTR, &array->dispex, ret);
+    hres = create_builtin_function(ctx, ArrayConstr_value, NULL, PROPF_CONSTR, &array->dispex, ret);
 
     IDispatchEx_Release(_IDispatchEx_(&array->dispex));
     return hres;

Modified: trunk/reactos/dll/win32/jscript/bool.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/jscript/bool.c?rev=41769&r1=41768&r2=41769&view=diff
==============================================================================
--- trunk/reactos/dll/win32/jscript/bool.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/jscript/bool.c [iso-8859-1] Sat Jul  4 15:49:53 2009
@@ -142,7 +142,7 @@
     if(FAILED(hres))
         return hres;
 
-    hres = create_builtin_function(ctx, BoolConstr_value, PROPF_CONSTR, &bool->dispex, ret);
+    hres = create_builtin_function(ctx, BoolConstr_value, NULL, PROPF_CONSTR, &bool->dispex, ret);
 
     jsdisp_release(&bool->dispex);
     return hres;

Modified: trunk/reactos/dll/win32/jscript/date.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/jscript/date.c?rev=41769&r1=41768&r2=41769&view=diff
==============================================================================
--- trunk/reactos/dll/win32/jscript/date.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/jscript/date.c [iso-8859-1] Sat Jul  4 15:49:53 2009
@@ -35,6 +35,10 @@
     DOUBLE time;
 
     LONG bias;
+    SYSTEMTIME standardDate;
+    LONG standardBias;
+    SYSTEMTIME daylightDate;
+    LONG daylightBias;
 } DateInstance;
 
 static const WCHAR toStringW[] = {'t','o','S','t','r','i','n','g',0};
@@ -83,18 +87,33 @@
 static const WCHAR setFullYearW[] = {'s','e','t','F','u','l','l','Y','e','a','r',0};
 static const WCHAR setUTCFullYearW[] = {'s','e','t','U','T','C','F','u','l','l','Y','e','a','r',0};
 
-/*ECMA-262 3th Edition    15.9.1.2 */
+static const WCHAR UTCW[] = {'U','T','C',0};
+static const WCHAR parseW[] = {'p','a','r','s','e',0};
+
+/*ECMA-262 3rd Edition    15.9.1.2 */
 #define MS_PER_DAY 86400000
 #define MS_PER_HOUR 3600000
 #define MS_PER_MINUTE 60000
 
-/* ECMA-262 3th Edition    15.9.1.2 */
+/* ECMA-262 3rd Edition    15.9.1.2 */
 static inline DOUBLE day(DOUBLE time)
 {
     return floor(time / MS_PER_DAY);
 }
 
-/* ECMA-262 3th Edition    15.9.1.3 */
+/* ECMA-262 3rd Edition    15.9.1.2 */
+static inline DOUBLE time_within_day(DOUBLE time)
+{
+    DOUBLE ret;
+
+    ret = fmod(time, MS_PER_DAY);
+    if(ret < 0)
+        ret += MS_PER_DAY;
+
+    return ret;
+}
+
+/* ECMA-262 3rd Edition    15.9.1.3 */
 static inline DOUBLE days_in_year(DOUBLE year)
 {
     int y;
@@ -109,26 +128,54 @@
     return 366;
 }
 
-/* ECMA-262 3th Edition    15.9.1.3 */
+/* ECMA-262 3rd Edition    15.9.1.3 */
 static inline DOUBLE day_from_year(DOUBLE year)
 {
-    int y;
-
     if(year != (int)year)
         return ret_nan();
 
-    y = year;
-    return 365*(y-1970) + floor((y-1969)/4)
-        - floor((y-1901)/100) + floor((y-1601)/400);
-}
-
-/* ECMA-262 3th Edition    15.9.1.3 */
+    return floor(365.0*(year-1970) + floor((year-1969)/4)
+        - floor((year-1901)/100) + floor((year-1601)/400));
+}
+
+static inline int day_from_month(int month, int in_leap_year)
+{
+    switch(month)
+    {
+        case 0:
+            return 0;
+        case 1:
+            return 31;
+        case 2:
+            return 59+in_leap_year;
+        case 3:
+            return 90+in_leap_year;
+        case 4:
+            return 120+in_leap_year;
+        case 5:
+            return 151+in_leap_year;
+        case 6:
+            return 181+in_leap_year;
+        case 7:
+            return 212+in_leap_year;
+        case 8:
+            return 243+in_leap_year;
+        case 9:
+            return 273+in_leap_year;
+        case 10:
+            return 304+in_leap_year;
+        default:
+            return 334+in_leap_year;
+    }
+}
+
+/* ECMA-262 3rd Edition    15.9.1.3 */
 static inline DOUBLE time_from_year(DOUBLE year)
 {
     return MS_PER_DAY*day_from_year(year);
 }
 
-/* ECMA-262 3th Edition    15.9.1.3 */
+/* ECMA-262 3rd Edition    15.9.1.3 */
 static inline DOUBLE year_from_time(DOUBLE time)
 {
     int y;
@@ -146,7 +193,7 @@
     return y;
 }
 
-/* ECMA-262 3th Edition    15.9.1.3 */
+/* ECMA-262 3rd Edition    15.9.1.3 */
 static inline int in_leap_year(DOUBLE time)
 {
     if(days_in_year(year_from_time(time))==366)
@@ -154,13 +201,13 @@
     return 0;
 }
 
-/* ECMA-262 3th Edition    15.9.1.4 */
+/* ECMA-262 3rd Edition    15.9.1.4 */
 static inline int day_within_year(DOUBLE time)
 {
     return day(time) - day_from_year(year_from_time(time));
 }
 
-/* ECMA-262 3th Edition    15.9.1.4 */
+/* ECMA-262 3rd Edition    15.9.1.4 */
 static inline DOUBLE month_from_time(DOUBLE time)
 {
     int ily = in_leap_year(time);
@@ -183,7 +230,7 @@
     return  11;
 }
 
-/* ECMA-262 3th Edition    15.9.1.5 */
+/* ECMA-262 3rd Edition    15.9.1.5 */
 static inline DOUBLE date_from_time(DOUBLE time)
 {
     int dwy = day_within_year(time);
@@ -207,7 +254,7 @@
     return dwy-333-ily;
 }
 
-/* ECMA-262 3th Edition    15.9.1.6 */
+/* ECMA-262 3rd Edition    15.9.1.6 */
 static inline DOUBLE week_day(DOUBLE time)
 {
     DOUBLE ret;
@@ -221,7 +268,81 @@
     return ret;
 }
 
-/* ECMA-262 3th Edition    15.9.1.10 */
+static inline DOUBLE convert_time(int year, SYSTEMTIME st)
+{
+    DOUBLE time;
+    int set_week_day;
+
+    if(st.wMonth == 0)
+        return ret_nan();
+
+    if(st.wYear != 0)
+        year = st.wYear;
+
+    time = time_from_year(year);
+    time += (DOUBLE)day_from_month(st.wMonth-1, in_leap_year(time)) * MS_PER_DAY;
+
+    if(st.wYear == 0) {
+        set_week_day = st.wDayOfWeek-week_day(time);
+        if(set_week_day < 0)
+            set_week_day += 7;
+        time += set_week_day * MS_PER_DAY;
+
+        time += (DOUBLE)(st.wDay-1) * 7 * MS_PER_DAY;
+        if(month_from_time(time) != st.wMonth-1)
+            time -= 7 * MS_PER_DAY;
+    }
+    else
+        time += st.wDay * MS_PER_DAY;
+
+    time += st.wHour * MS_PER_HOUR;
+    time += st.wMinute * MS_PER_MINUTE;
+
+    return time;
+}
+
+/* ECMA-262 3rd Edition    15.9.1.9 */
+static inline DOUBLE daylight_saving_ta(DOUBLE time, DateInstance *date)
+{
+    int year = year_from_time(time);
+    DOUBLE standardTime, daylightTime;
+
+    if(isnan(time))
+        return 0;
+
+    standardTime = convert_time(year, date->standardDate);
+    daylightTime = convert_time(year, date->daylightDate);
+
+    if(isnan(standardTime) || isnan(daylightTime))
+        return 0;
+    else if(standardTime > daylightTime) {
+        if(daylightTime <= time && time < standardTime)
+            return date->daylightBias;
+
+        return date->standardBias;
+    }
+    else {
+        if(standardTime <= time && time < daylightTime)
+            return date->standardBias;
+
+        return date->daylightBias;
+    }
+}
+
+/* ECMA-262 3rd Edition    15.9.1.9 */
+static inline DOUBLE local_time(DOUBLE time, DateInstance *date)
+{
+    return time - (daylight_saving_ta(time, date)+date->bias)*MS_PER_MINUTE;
+}
+
+/* ECMA-262 3rd Edition    15.9.1.9 */
+static inline DOUBLE utc(DOUBLE time, DateInstance *date)
+{
+    time += date->bias * MS_PER_MINUTE;
+    return time + daylight_saving_ta(time, date)*MS_PER_MINUTE;
+}
+
+/* ECMA-262 3rd Edition    15.9.1.10 */
 static inline DOUBLE hour_from_time(DOUBLE time)
 {
     DOUBLE ret;
@@ -235,7 +356,7 @@
     return ret;
 }
 
-/* ECMA-262 3th Edition    15.9.1.10 */
+/* ECMA-262 3rd Edition    15.9.1.10 */
 static inline DOUBLE min_from_time(DOUBLE time)
 {
     DOUBLE ret;
@@ -249,7 +370,7 @@
     return ret;
 }
 
-/* ECMA-262 3th Edition    15.9.1.10 */
+/* ECMA-262 3rd Edition    15.9.1.10 */
 static inline DOUBLE sec_from_time(DOUBLE time)
 {
     DOUBLE ret;
@@ -263,7 +384,7 @@
     return ret;
 }
 
-/* ECMA-262 3th Edition    15.9.1.10 */
+/* ECMA-262 3rd Edition    15.9.1.10 */
 static inline DOUBLE ms_from_time(DOUBLE time)
 {
     DOUBLE ret;
@@ -277,6 +398,36 @@
     return ret;
 }
 
+/* ECMA-262 3rd Edition    15.9.1.11 */
+static inline DOUBLE make_time(DOUBLE hour, DOUBLE min, DOUBLE sec, DOUBLE ms)
+{
+    return hour*MS_PER_HOUR + min*MS_PER_MINUTE + sec*1000 + ms;
+}
+
+/* ECMA-262 3rd Edition    15.9.1.12 */
+static inline DOUBLE make_day(DOUBLE year, DOUBLE month, DOUBLE day)
+{
+    DOUBLE time;
+
+    year += floor(month/12);
+
+    month = fmod(month, 12);
+    if(month<0) month += 12;
+
+    time = time_from_year(year);
+
+    day += floor(time / MS_PER_DAY);
+    day += day_from_month(month, in_leap_year(time));
+
+    return day-1;
+}
+
+/* ECMA-262 3rd Edition    15.9.1.13 */
+static inline DOUBLE make_date(DOUBLE day, DOUBLE time)
+{
+    return day*MS_PER_DAY + time;
+}
+
 /* ECMA-262 3rd Edition    15.9.1.14 */
 static inline DOUBLE time_clip(DOUBLE time)
 {
@@ -287,81 +438,609 @@
     return floor(time);
 }
 
+static SYSTEMTIME create_systemtime(DOUBLE time)
+{
+    SYSTEMTIME st;
+
+    st.wYear = year_from_time(time);
+    st.wMonth = month_from_time(time) + 1;
+    st.wDayOfWeek = week_day(time);
+    st.wDay = date_from_time(time);
+    st.wHour = hour_from_time(time);
+    st.wMinute = min_from_time(time);
+    st.wSecond = sec_from_time(time);
+    st.wMilliseconds = ms_from_time(time);
+
+    return st;
+}
+
+/* ECMA-262 3rd Edition    15.9.1.2 */
 static HRESULT Date_toString(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
+        VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
+{
+    static const WCHAR NaNW[] = { 'N','a','N',0 };
+    static const WCHAR formatW[] = { '%','s',' ','%','s',' ','%','d',' ',
+        '%','0','2','d',':','%','0','2','d',':','%','0','2','d',' ',
+        'U','T','C','%','c','%','0','2','d','%','0','2','d',' ','%','d','%','s',0 };
+    static const WCHAR formatUTCW[] = { '%','s',' ','%','s',' ','%','d',' ',
+        '%','0','2','d',':','%','0','2','d',':','%','0','2','d',' ',
+        'U','T','C',' ','%','d','%','s',0 };
+    static const WCHAR ADW[] = { 0 };
+    static const WCHAR BCW[] = { ' ','B','.','C','.',0 };
+
+    static const DWORD week_ids[] = { LOCALE_SABBREVDAYNAME7, LOCALE_SABBREVDAYNAME1,
+        LOCALE_SABBREVDAYNAME2, LOCALE_SABBREVDAYNAME3, LOCALE_SABBREVDAYNAME4,
+        LOCALE_SABBREVDAYNAME5, LOCALE_SABBREVDAYNAME6 };
+    static const DWORD month_ids[] = { LOCALE_SABBREVMONTHNAME1, LOCALE_SABBREVMONTHNAME2,
+        LOCALE_SABBREVMONTHNAME3, LOCALE_SABBREVMONTHNAME4,
+        LOCALE_SABBREVMONTHNAME5, LOCALE_SABBREVMONTHNAME6,
+        LOCALE_SABBREVMONTHNAME7, LOCALE_SABBREVMONTHNAME8,
+        LOCALE_SABBREVMONTHNAME9, LOCALE_SABBREVMONTHNAME10,
+        LOCALE_SABBREVMONTHNAME11, LOCALE_SABBREVMONTHNAME12 };
+
+    BOOL formatAD = TRUE;
+    BSTR week, month;
+    DateInstance *date;
+    BSTR date_str;
+    DOUBLE time;
+    int len, size, year, day, offset;
+    DWORD lcid_en, week_id, month_id;
+    WCHAR sign = '-';
+
+    TRACE("\n");
+
+    if(!is_class(dispex, JSCLASS_DATE)) {
+        FIXME("throw TypeError\n");
+        return E_FAIL;
+    }
+
+    date = (DateInstance*)dispex;
+
+    if(isnan(date->time)) {
+        if(retv) {
+            V_VT(retv) = VT_BSTR;
+            V_BSTR(retv) = SysAllocString(NaNW);
+            if(!V_BSTR(retv))
+                return E_OUTOFMEMORY;
+        }
+        return S_OK;
+    }
+
+    time = local_time(date->time, date);
+
+    if(retv) {
+        len = 21;
+
+        lcid_en = MAKELCID(MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),SORT_DEFAULT);
+
+        week_id = week_ids[(int)week_day(time)];
+        size = GetLocaleInfoW(lcid_en, week_id, NULL, 0);
+        week = SysAllocStringLen(NULL, size);
+        if(!week)
+            return E_OUTOFMEMORY;
+        GetLocaleInfoW(lcid_en, week_id, week, size);
+        len += size-1;
+
+        month_id = month_ids[(int)month_from_time(time)];
+        size = GetLocaleInfoW(lcid_en, month_id, NULL, 0);
+        month = SysAllocStringLen(NULL, size);
+        if(!month) {
+            SysFreeString(week);
+            return E_OUTOFMEMORY;
+        }
+        GetLocaleInfoW(lcid_en, month_id, month, size);
+        len += size-1;
+
+        year = year_from_time(time);
+        if(year<0)
+            year = -year+1;
+        do {
+            year /= 10;
+            len++;
+        } while(year);
+
+        year = year_from_time(time);
+        if(year<0) {
+            formatAD = FALSE;
+            year = -year+1;
+            len += 5;
+        }
+
+        day = date_from_time(time);
+        do {
+            day /= 10;
+            len++;
+        } while(day);
+        day = date_from_time(time);
+
+        offset = date->bias +
+            daylight_saving_ta(time, date);
+
+        if(offset == 0) len -= 5;
+        else if(offset < 0) {
+            sign = '+';
+            offset = -offset;
+        }
+
+        date_str = SysAllocStringLen(NULL, len);
+        if(!date_str) {
+            SysFreeString(week);
+            SysFreeString(month);
+            return E_OUTOFMEMORY;
+        }
+
+        if(offset)
+            sprintfW(date_str, formatW, week, month, day,
+                    (int)hour_from_time(time), (int)min_from_time(time),
+                    (int)sec_from_time(time), sign, offset/60, offset%60,
+                    year, formatAD?ADW:BCW);
+        else
+            sprintfW(date_str, formatUTCW, week, month, day,
+            (int)hour_from_time(time), (int)min_from_time(time),
+            (int)sec_from_time(time), year, formatAD?ADW:BCW);
+
+        SysFreeString(week);
+        SysFreeString(month);
+
+        V_VT(retv) = VT_BSTR;
+        V_BSTR(retv) = date_str;
+    }
+    return S_OK;
+}
+
+/* ECMA-262 3rd Edition    15.9.1.5 */
+static HRESULT Date_toLocaleString(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
+        VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
+{
+    static const WCHAR NaNW[] = { 'N','a','N',0 };
+    SYSTEMTIME st;
+    DateInstance *date;
+    BSTR date_str;
+    int date_len, time_len;
+
+    TRACE("\n");
+
+    if(!is_class(dispex, JSCLASS_DATE)) {
+        FIXME("throw TypeError\n");
+        return E_FAIL;
+    }
+
+    date = (DateInstance*)dispex;
+
+    if(isnan(date->time)) {
+        if(retv) {
+            V_VT(retv) = VT_BSTR;
+            V_BSTR(retv) = SysAllocString(NaNW);
+            if(!V_BSTR(retv))
+                return E_OUTOFMEMORY;
+        }
+        return S_OK;
+    }
+
+    st = create_systemtime(local_time(date->time, date));
+
+    if(st.wYear<1601 || st.wYear>9999)
+        return Date_toString(dispex, lcid, flags, dp, retv, ei, caller);
+
+    if(retv) {
+        date_len = GetDateFormatW(lcid, DATE_LONGDATE, &st, NULL, NULL, 0);
+        time_len = GetTimeFormatW(lcid, 0, &st, NULL, NULL, 0);
+        date_str = SysAllocStringLen(NULL, date_len+time_len-1);
+        if(!date_str)
+            return E_OUTOFMEMORY;
+        GetDateFormatW(lcid, DATE_LONGDATE, &st, NULL, date_str, date_len);
+        GetTimeFormatW(lcid, 0, &st, NULL, &date_str[date_len], time_len);
+        date_str[date_len-1] = ' ';
+
+        V_VT(retv) = VT_BSTR;
+        V_BSTR(retv) = date_str;
+    }
+    return S_OK;
+}
+
+static HRESULT Date_hasOwnProperty(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
 {
     FIXME("\n");
     return E_NOTIMPL;
 }
 
-static HRESULT Date_toLocaleString(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
+static HRESULT Date_propertyIsEnumerable(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
 {
     FIXME("\n");
     return E_NOTIMPL;
 }
 
-static HRESULT Date_hasOwnProperty(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
+static HRESULT Date_isPrototypeOf(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
 {
     FIXME("\n");
     return E_NOTIMPL;
 }
 
-static HRESULT Date_propertyIsEnumerable(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
+static HRESULT Date_valueOf(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
 {
     FIXME("\n");
     return E_NOTIMPL;
 }
 
-static HRESULT Date_isPrototypeOf(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
-        VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
-{
-    FIXME("\n");
-    return E_NOTIMPL;
-}
-
-static HRESULT Date_valueOf(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
-        VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
-{
-    FIXME("\n");
-    return E_NOTIMPL;
-}
-
+/* ECMA-262 3rd Edition    15.9.5.42 */
 static HRESULT Date_toUTCString(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
 {
-    FIXME("\n");
-    return E_NOTIMPL;
-}
-
+    static const WCHAR NaNW[] = { 'N','a','N',0 };
+    static const WCHAR formatADW[] = { '%','s',',',' ','%','d',' ','%','s',' ','%','d',' ',
+        '%','0','2','d',':','%','0','2','d',':','%','0','2','d',' ','U','T','C',0 };
+    static const WCHAR formatBCW[] = { '%','s',',',' ','%','d',' ','%','s',' ','%','d',' ','B','.','C','.',' ',
+        '%','0','2','d',':','%','0','2','d',':','%','0','2','d',' ','U','T','C',0 };
+
+    static const DWORD week_ids[] = { LOCALE_SABBREVDAYNAME7, LOCALE_SABBREVDAYNAME1,
+        LOCALE_SABBREVDAYNAME2, LOCALE_SABBREVDAYNAME3, LOCALE_SABBREVDAYNAME4,
+        LOCALE_SABBREVDAYNAME5, LOCALE_SABBREVDAYNAME6 };
+    static const DWORD month_ids[] = { LOCALE_SABBREVMONTHNAME1, LOCALE_SABBREVMONTHNAME2,
+        LOCALE_SABBREVMONTHNAME3, LOCALE_SABBREVMONTHNAME4,
+        LOCALE_SABBREVMONTHNAME5, LOCALE_SABBREVMONTHNAME6,
+        LOCALE_SABBREVMONTHNAME7, LOCALE_SABBREVMONTHNAME8,
+        LOCALE_SABBREVMONTHNAME9, LOCALE_SABBREVMONTHNAME10,
+        LOCALE_SABBREVMONTHNAME11, LOCALE_SABBREVMONTHNAME12 };
+
+    BOOL formatAD = TRUE;
+    BSTR week, month;
+    DateInstance *date;
+    BSTR date_str;
+    int len, size, year, day;
+    DWORD lcid_en, week_id, month_id;
+
+    TRACE("\n");
+
+    if(!is_class(dispex, JSCLASS_DATE)) {
+        FIXME("throw TypeError\n");
+        return E_FAIL;
+    }
+
+    date = (DateInstance*)dispex;
+
+    if(isnan(date->time)) {
+        if(retv) {
+            V_VT(retv) = VT_BSTR;
+            V_BSTR(retv) = SysAllocString(NaNW);
+            if(!V_BSTR(retv))
+                return E_OUTOFMEMORY;
+        }
+        return S_OK;
+    }
+
+    if(retv) {
+        len = 17;
+
+        lcid_en = MAKELCID(MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),SORT_DEFAULT);
+
+        week_id = week_ids[(int)week_day(date->time)];
+        size = GetLocaleInfoW(lcid_en, week_id, NULL, 0);
+        week = SysAllocStringLen(NULL, size);
+        if(!week)
+            return E_OUTOFMEMORY;
+        GetLocaleInfoW(lcid_en, week_id, week, size);
+        len += size-1;
+
+        month_id = month_ids[(int)month_from_time(date->time)];
+        size = GetLocaleInfoW(lcid_en, month_id, NULL, 0);
+        month = SysAllocStringLen(NULL, size);
+        if(!month) {
+            SysFreeString(week);
+            return E_OUTOFMEMORY;
+        }
+        GetLocaleInfoW(lcid_en, month_id, month, size);
+        len += size-1;
+
+        year = year_from_time(date->time);
+        if(year<0)
+            year = -year+1;
+        do {
+            year /= 10;
+            len++;
+        } while(year);
+
+        year = year_from_time(date->time);
+        if(year<0) {
+            formatAD = FALSE;
+            year = -year+1;
+            len += 5;
+        }
+
+        day = date_from_time(date->time);
+        do {
+            day /= 10;
+            len++;
+        } while(day);
+        day = date_from_time(date->time);
+
+        date_str = SysAllocStringLen(NULL, len);
+        if(!date_str) {
+            SysFreeString(week);
+            SysFreeString(month);
+            return E_OUTOFMEMORY;
+        }
+        sprintfW(date_str, formatAD?formatADW:formatBCW, week, day, month, year,
+                (int)hour_from_time(date->time), (int)min_from_time(date->time),
+                (int)sec_from_time(date->time));
+
+        SysFreeString(week);
+        SysFreeString(month);
+
+        V_VT(retv) = VT_BSTR;
+        V_BSTR(retv) = date_str;
+    }
+    return S_OK;
+}
+
+/* ECMA-262 3rd Edition    15.9.5.3 */
 static HRESULT Date_toDateString(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
 {
-    FIXME("\n");
-    return E_NOTIMPL;
-}
-
+    static const WCHAR NaNW[] = { 'N','a','N',0 };
+    static const WCHAR formatADW[] = { '%','s',' ','%','s',' ','%','d',' ','%','d',0 };
+    static const WCHAR formatBCW[] = { '%','s',' ','%','s',' ','%','d',' ','%','d',' ','B','.','C','.',0 };
+
+    static const DWORD week_ids[] = { LOCALE_SABBREVDAYNAME7, LOCALE_SABBREVDAYNAME1,
+        LOCALE_SABBREVDAYNAME2, LOCALE_SABBREVDAYNAME3, LOCALE_SABBREVDAYNAME4,
+        LOCALE_SABBREVDAYNAME5, LOCALE_SABBREVDAYNAME6 };
+    static const DWORD month_ids[] = { LOCALE_SABBREVMONTHNAME1, LOCALE_SABBREVMONTHNAME2,
+        LOCALE_SABBREVMONTHNAME3, LOCALE_SABBREVMONTHNAME4,
+        LOCALE_SABBREVMONTHNAME5, LOCALE_SABBREVMONTHNAME6,
+        LOCALE_SABBREVMONTHNAME7, LOCALE_SABBREVMONTHNAME8,
+        LOCALE_SABBREVMONTHNAME9, LOCALE_SABBREVMONTHNAME10,
+        LOCALE_SABBREVMONTHNAME11, LOCALE_SABBREVMONTHNAME12 };
+
+    BOOL formatAD = TRUE;
+    BSTR week, month;
+    DateInstance *date;
+    BSTR date_str;
+    DOUBLE time;
+    int len, size, year, day;
+    DWORD lcid_en, week_id, month_id;
+
+    TRACE("\n");
+
+    if(!is_class(dispex, JSCLASS_DATE)) {
+        FIXME("throw TypeError\n");
+        return E_FAIL;
+    }
+
+    date = (DateInstance*)dispex;
+
+    if(isnan(date->time)) {
+        if(retv) {
+            V_VT(retv) = VT_BSTR;
+            V_BSTR(retv) = SysAllocString(NaNW);
+            if(!V_BSTR(retv))
+                return E_OUTOFMEMORY;
+        }
+        return S_OK;
+    }
+
+    time = local_time(date->time, date);
+
+    if(retv) {
+        len = 5;
+
+        lcid_en = MAKELCID(MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),SORT_DEFAULT);
+
+        week_id = week_ids[(int)week_day(time)];
+        size = GetLocaleInfoW(lcid_en, week_id, NULL, 0);
+        week = SysAllocStringLen(NULL, size);
+        if(!week)
+            return E_OUTOFMEMORY;
+        GetLocaleInfoW(lcid_en, week_id, week, size);
+        len += size-1;
+
+        month_id = month_ids[(int)month_from_time(time)];
+        size = GetLocaleInfoW(lcid_en, month_id, NULL, 0);
+        month = SysAllocStringLen(NULL, size);
+        if(!month) {
+            SysFreeString(week);
+            return E_OUTOFMEMORY;
+        }
+        GetLocaleInfoW(lcid_en, month_id, month, size);
+        len += size-1;
+
+        year = year_from_time(time);
+        if(year<0)
+            year = -year+1;
+        do {
+            year /= 10;
+            len++;
+        } while(year);
+
+        year = year_from_time(time);
+        if(year<0) {
+            formatAD = FALSE;
+            year = -year+1;
+            len += 5;
+        }
+
+        day = date_from_time(time);
+        do {
+            day /= 10;
+            len++;
+        } while(day);
+        day = date_from_time(time);
+
+        date_str = SysAllocStringLen(NULL, len);
+        if(!date_str) {
+            SysFreeString(week);
+            SysFreeString(month);
+            return E_OUTOFMEMORY;
+        }
+        sprintfW(date_str, formatAD?formatADW:formatBCW, week, month, day, year);
+
+        SysFreeString(week);
+        SysFreeString(month);
+
+        V_VT(retv) = VT_BSTR;
+        V_BSTR(retv) = date_str;
+    }
+    return S_OK;
+}
+
+/* ECMA-262 3rd Edition    15.9.5.4 */
 static HRESULT Date_toTimeString(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
 {
-    FIXME("\n");
-    return E_NOTIMPL;
-}
-
+    static const WCHAR NaNW[] = { 'N','a','N',0 };
+    static const WCHAR formatW[] = { '%','0','2','d',':','%','0','2','d',':','%','0','2','d',
+        ' ','U','T','C','%','c','%','0','2','d','%','0','2','d',0 };
+    static const WCHAR formatUTCW[] = { '%','0','2','d',':','%','0','2','d',
+        ':','%','0','2','d',' ','U','T','C',0 };
+    DateInstance *date;
+    BSTR date_str;
+    DOUBLE time;
+    WCHAR sign;
+    int offset;
+
+    TRACE("\n");
+
+    if(!is_class(dispex, JSCLASS_DATE)) {
+        FIXME("throw TypeError\n");
+        return E_FAIL;
+    }
+
+    date = (DateInstance*)dispex;
+
+    if(isnan(date->time)) {
+        if(retv) {
+            V_VT(retv) = VT_BSTR;
+            V_BSTR(retv) = SysAllocString(NaNW);
+            if(!V_BSTR(retv))
+                return E_OUTOFMEMORY;
+        }
+        return S_OK;
+    }
+
+    time = local_time(date->time, date);
+
+    if(retv) {
+        date_str = SysAllocStringLen(NULL, 17);
+        if(!date_str)
+            return E_OUTOFMEMORY;
+
+        offset = date->bias +
+            daylight_saving_ta(time, date);
+
+        if(offset < 0) {
+            sign = '+';
+            offset = -offset;
+        }
+        else sign = '-';
+
+        if(offset)
+            sprintfW(date_str, formatW, (int)hour_from_time(time),
+                    (int)min_from_time(time), (int)sec_from_time(time),
+                    sign, offset/60, offset%60);
+        else
+            sprintfW(date_str, formatUTCW, (int)hour_from_time(time),
+                    (int)min_from_time(time), (int)sec_from_time(time));
+
+        V_VT(retv) = VT_BSTR;
+        V_BSTR(retv) = date_str;
+    }
+    return S_OK;
+}
+
+/* ECMA-262 3rd Edition    15.9.5.6 */
 static HRESULT Date_toLocaleDateString(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
 {
-    FIXME("\n");
-    return E_NOTIMPL;
-}
-
+    static const WCHAR NaNW[] = { 'N','a','N',0 };
+    SYSTEMTIME st;
+    DateInstance *date;
+    BSTR date_str;
+    int len;
+
+    TRACE("\n");
+
+    if(!is_class(dispex, JSCLASS_DATE)) {
+        FIXME("throw TypeError\n");
+        return E_FAIL;
+    }
+
+    date = (DateInstance*)dispex;
+
+    if(isnan(date->time)) {
+        if(retv) {
+            V_VT(retv) = VT_BSTR;
+            V_BSTR(retv) = SysAllocString(NaNW);
+            if(!V_BSTR(retv))
+                return E_OUTOFMEMORY;
+        }
+        return S_OK;
+    }
+
+    st = create_systemtime(local_time(date->time, date));
+
+    if(st.wYear<1601 || st.wYear>9999)
+        return Date_toDateString(dispex, lcid, flags, dp, retv, ei, caller);
+
+    if(retv) {
+        len = GetDateFormatW(lcid, DATE_LONGDATE, &st, NULL, NULL, 0);
+        date_str = SysAllocStringLen(NULL, len);
+        if(!date_str)
+            return E_OUTOFMEMORY;
+        GetDateFormatW(lcid, DATE_LONGDATE, &st, NULL, date_str, len);
+
+        V_VT(retv) = VT_BSTR;
+        V_BSTR(retv) = date_str;
+    }
+    return S_OK;
+}
+
+/* ECMA-262 3rd Edition    15.9.5.7 */
 static HRESULT Date_toLocaleTimeString(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
 {
-    FIXME("\n");
-    return E_NOTIMPL;
+    static const WCHAR NaNW[] = { 'N','a','N',0 };
+    SYSTEMTIME st;
+    DateInstance *date;
+    BSTR date_str;
+    int len;
+
+    TRACE("\n");
+
+    if(!is_class(dispex, JSCLASS_DATE)) {
+        FIXME("throw TypeError\n");
+        return E_FAIL;
+    }
+
+    date = (DateInstance*)dispex;
+
+    if(isnan(date->time)) {
+        if(retv) {
+            V_VT(retv) = VT_BSTR;
+            V_BSTR(retv) = SysAllocString(NaNW);
+            if(!V_BSTR(retv))
+                return E_OUTOFMEMORY;
+        }
+        return S_OK;
+    }
+
+    st = create_systemtime(local_time(date->time, date));
+
+    if(st.wYear<1601 || st.wYear>9999)
+        return Date_toTimeString(dispex, lcid, flags, dp, retv, ei, caller);
+
+    if(retv) {
+        len = GetTimeFormatW(lcid, 0, &st, NULL, NULL, 0);
+        date_str = SysAllocStringLen(NULL, len);
+        if(!date_str)
+            return E_OUTOFMEMORY;
+        GetTimeFormatW(lcid, 0, &st, NULL, date_str, len);
+
+        V_VT(retv) = VT_BSTR;
+        V_BSTR(retv) = date_str;
+    }
+    return S_OK;
 }
 
 /* ECMA-262 3rd Edition    15.9.5.9 */
@@ -382,7 +1061,7 @@
     return S_OK;
 }
 
-/* ECMA-262 3th Edition    15.9.1.3 */
+/* ECMA-262 3rd Edition    15.9.5.10 */
 static HRESULT Date_getFullYear(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
 {
@@ -395,14 +1074,14 @@
 
     if(retv) {
         DateInstance *date = (DateInstance*)dispex;
-        DOUBLE time = date->time - date->bias*MS_PER_MINUTE;
+        DOUBLE time = local_time(date->time, date);
 
         num_set_val(retv, year_from_time(time));
     }
     return S_OK;
 }
 
-/* ECMA-262 3th Edition    15.9.1.3 */
+/* ECMA-262 3rd Edition    15.9.5.11 */
 static HRESULT Date_getUTCFullYear(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
 {
@@ -420,7 +1099,7 @@
     return S_OK;
 }
 
-/* ECMA-262 3th Edition    15.9.1.4 */
+/* ECMA-262 3rd Edition    15.9.5.12 */
 static HRESULT Date_getMonth(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
 {
@@ -433,14 +1112,14 @@
 
     if(retv) {
         DateInstance *date = (DateInstance*)dispex;
-        DOUBLE time = date->time - date->bias*MS_PER_MINUTE;
+        DOUBLE time = local_time(date->time, date);
 
         num_set_val(retv, month_from_time(time));
     }
     return S_OK;
 }
 
-/* ECMA-262 3th Edition    15.9.1.4 */
+/* ECMA-262 3rd Edition    15.9.5.13 */
 static HRESULT Date_getUTCMonth(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
 {
@@ -458,7 +1137,7 @@
     return S_OK;
 }
 
-/* ECMA-262 3th Edition    15.9.1.5 */
+/* ECMA-262 3rd Edition    15.9.5.14 */
 static HRESULT Date_getDate(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
 {
@@ -471,14 +1150,14 @@
 
     if(retv) {
         DateInstance *date = (DateInstance*)dispex;
-        DOUBLE time = date->time - date->bias*MS_PER_MINUTE;
+        DOUBLE time = local_time(date->time, date);
 
         num_set_val(retv, date_from_time(time));
     }
     return S_OK;
 }
 
-/* ECMA-262 3th Edition    15.9.1.5 */
+/* ECMA-262 3rd Edition    15.9.5.15 */
 static HRESULT Date_getUTCDate(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
 {
@@ -496,7 +1175,7 @@
     return S_OK;
 }
 
-/* ECMA-262 3th Edition    15.9.1.6 */
+/* ECMA-262 3rd Edition    15.9.5.16 */
 static HRESULT Date_getDay(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
 {
@@ -509,14 +1188,14 @@
 
     if(retv) {
         DateInstance *date = (DateInstance*)dispex;
-        DOUBLE time = date->time - date->bias*MS_PER_MINUTE;
+        DOUBLE time = local_time(date->time, date);
 
         num_set_val(retv, week_day(time));
     }
     return S_OK;
 }
 
-/* ECMA-262 3th Edition    15.9.1.6 */
+/* ECMA-262 3rd Edition    15.9.5.17 */
 static HRESULT Date_getUTCDay(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
 {
@@ -534,7 +1213,7 @@
     return S_OK;
 }
 
-/* ECMA-262 3th Edition    15.9.1.10 */
+/* ECMA-262 3rd Edition    15.9.5.18 */
 static HRESULT Date_getHours(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
 {
@@ -547,14 +1226,14 @@
 
     if(retv) {
         DateInstance *date = (DateInstance*)dispex;
-        DOUBLE time = date->time - date->bias*MS_PER_MINUTE;
+        DOUBLE time = local_time(date->time, date);
 
         num_set_val(retv, hour_from_time(time));
     }
     return S_OK;
 }
 
-/* ECMA-262 3th Edition    15.9.1.10 */
+/* ECMA-262 3rd Edition    15.9.5.19 */
 static HRESULT Date_getUTCHours(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
 {
@@ -572,7 +1251,7 @@
     return S_OK;
 }
 
-/* ECMA-262 3th Edition    15.9.1.10 */
+/* ECMA-262 3rd Edition    15.9.5.20 */
 static HRESULT Date_getMinutes(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
 {
@@ -585,14 +1264,14 @@
 
     if(retv) {
         DateInstance *date = (DateInstance*)dispex;
-        DOUBLE time = date->time - date->bias*MS_PER_MINUTE;
+        DOUBLE time = local_time(date->time, date);
 
         num_set_val(retv, min_from_time(time));
     }
     return S_OK;
 }
 
-/* ECMA-262 3th Edition    15.9.1.10 */
+/* ECMA-262 3rd Edition    15.9.5.21 */
 static HRESULT Date_getUTCMinutes(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
 {
@@ -610,7 +1289,7 @@
     return S_OK;
 }
 
-/* ECMA-262 3th Edition    15.9.1.10 */
+/* ECMA-262 3rd Edition    15.9.5.22 */
 static HRESULT Date_getSeconds(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
 {
@@ -623,14 +1302,14 @@
 
     if(retv) {
         DateInstance *date = (DateInstance*)dispex;
-        DOUBLE time = date->time - date->bias*MS_PER_MINUTE;
+        DOUBLE time = local_time(date->time, date);
 
         num_set_val(retv, sec_from_time(time));
     }
     return S_OK;
 }
 
-/* ECMA-262 3th Edition    15.9.1.10 */
+/* ECMA-262 3rd Edition    15.9.5.23 */
 static HRESULT Date_getUTCSeconds(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
 {
@@ -648,7 +1327,7 @@
     return S_OK;
 }
 
-/* ECMA-262 3th Edition    15.9.1.10 */
+/* ECMA-262 3rd Edition    15.9.5.24 */
 static HRESULT Date_getMilliseconds(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
 {
@@ -661,14 +1340,14 @@
 
     if(retv) {
         DateInstance *date = (DateInstance*)dispex;
-        DOUBLE time = date->time - date->bias*MS_PER_MINUTE;
+        DOUBLE time = local_time(date->time, date);
 
         num_set_val(retv, ms_from_time(time));
     }
     return S_OK;
 }
 
-/* ECMA-262 3th Edition    15.9.1.10 */
+/* ECMA-262 3rd Edition    15.9.5.25 */
 static HRESULT Date_getUTCMilliseconds(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
 {
@@ -686,13 +1365,26 @@
     return S_OK;
 }
 
+/* ECMA-262 3rd Edition    15.9.5.26 */
 static HRESULT Date_getTimezoneOffset(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
 {
-    FIXME("\n");
-    return E_NOTIMPL;
-}
-
+    TRACE("\n");
+
+    if(!is_class(dispex, JSCLASS_DATE)) {
+        FIXME("throw TypeError\n");
+        return E_FAIL;
+    }
+
+    if(retv) {
+        DateInstance *date = (DateInstance*)dispex;
+        num_set_val(retv, floor(
+                    (date->time-local_time(date->time, date))/MS_PER_MINUTE));
+    }
+    return S_OK;
+}
+
+/* ECMA-262 3rd Edition    15.9.5.27 */
 static HRESULT Date_setTime(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
 {
@@ -726,12 +1418,14 @@
     return S_OK;
 }
 
+/* ECMA-262 3rd Edition    15.9.5.28 */
 static HRESULT Date_setMilliseconds(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
 {
     VARIANT v;
     HRESULT hres;
     DateInstance *date;
+    DOUBLE t;
 
     TRACE("\n");
 
@@ -751,7 +1445,10 @@
         return hres;
 
     date = (DateInstance*)dispex;
-    date->time = time_clip(date->time - ms_from_time(date->time) + num_val(&v));
+    t = local_time(date->time, date);
+    t = make_date(day(t), make_time(hour_from_time(t), min_from_time(t),
+                sec_from_time(t), num_val(&v)));
+    date->time = time_clip(utc(t, date));
 
     if(retv)
         num_set_val(retv, date->time);
@@ -759,18 +1456,14 @@
     return S_OK;
 }
 
+/* ECMA-262 3rd Edition    15.9.5.29 */
 static HRESULT Date_setUTCMilliseconds(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
-        VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
-{
-    return Date_setMilliseconds(dispex, lcid, flags, dp, retv, ei, caller);
-}
-
-static HRESULT Date_setSeconds(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
 {
     VARIANT v;
     HRESULT hres;
     DateInstance *date;
+    DOUBLE t;
 
     TRACE("\n");
 
@@ -790,7 +1483,10 @@
         return hres;
 
     date = (DateInstance*)dispex;
-    date->time = time_clip(date->time - (sec_from_time(date->time) - num_val(&v))*1000.0);
+    t = date->time;
+    t = make_date(day(t), make_time(hour_from_time(t), min_from_time(t),
+                sec_from_time(t), num_val(&v)));
+    date->time = time_clip(t);
 
     if(retv)
         num_set_val(retv, date->time);
@@ -798,18 +1494,14 @@
     return S_OK;
 }
 
-static HRESULT Date_setUTCSeconds(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
-        VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
-{
-    return Date_setSeconds(dispex, lcid, flags, dp, retv, ei, caller);
-}
-
-static HRESULT Date_setMinutes(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
+/* ECMA-262 3rd Edition    15.9.5.30 */
+static HRESULT Date_setSeconds(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
 {
     VARIANT v;
     HRESULT hres;
     DateInstance *date;
+    DOUBLE t, sec, ms;
 
     TRACE("\n");
 
@@ -824,12 +1516,25 @@
         return S_OK;
     }
 
+    date = (DateInstance*)dispex;
+    t = local_time(date->time, date);
+
     hres = to_number(dispex->ctx, get_arg(dp, 0), ei, &v);
     if(FAILED(hres))
         return hres;
-
-    date = (DateInstance*)dispex;
-    date->time = time_clip(date->time - (min_from_time(date->time) - num_val(&v))*MS_PER_MINUTE);
+    sec = num_val(&v);
+
+    if(arg_cnt(dp) > 1) {
+        hres = to_number(dispex->ctx, get_arg(dp, 1), ei, &v);
+        if(FAILED(hres))
+            return hres;
+        ms = num_val(&v);
+    }
+    else ms = ms_from_time(t);
+
+    t = make_date(day(t), make_time(hour_from_time(t),
+                min_from_time(t), sec, ms));
+    date->time = time_clip(utc(t, date));
 
     if(retv)
         num_set_val(retv, date->time);
@@ -837,18 +1542,14 @@
     return S_OK;
 }
 
-static HRESULT Date_setUTCMinutes(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
-        VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
-{
-    return Date_setMinutes(dispex, lcid, flags, dp, retv, ei, caller);
-}
-
-static HRESULT Date_setHours(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
+/* ECMA-262 3rd Edition    15.9.5.31 */
+static HRESULT Date_setUTCSeconds(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
 {
     VARIANT v;
     HRESULT hres;
     DateInstance *date;
+    DOUBLE t, sec, ms;
 
     TRACE("\n");
 
@@ -863,14 +1564,25 @@
         return S_OK;
     }
 
+    date = (DateInstance*)dispex;
+    t = date->time;
+
     hres = to_number(dispex->ctx, get_arg(dp, 0), ei, &v);
     if(FAILED(hres))
         return hres;
-
-    date = (DateInstance*)dispex;
-    date->time = time_clip(date->time
-            - (hour_from_time(date->time - date->bias*MS_PER_MINUTE)
-                - num_val(&v))*MS_PER_HOUR);
+    sec = num_val(&v);
+
+    if(arg_cnt(dp) > 1) {
+        hres = to_number(dispex->ctx, get_arg(dp, 1), ei, &v);
+        if(FAILED(hres))
+            return hres;
+        ms = num_val(&v);
+    }
+    else ms = ms_from_time(t);
+
+    t = make_date(day(t), make_time(hour_from_time(t),
+                min_from_time(t), sec, ms));
+    date->time = time_clip(t);
 
     if(retv)
         num_set_val(retv, date->time);
@@ -878,12 +1590,14 @@
     return S_OK;
 }
 
-static HRESULT Date_setUTCHours(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
+/* ECMA-262 3rd Edition    15.9.5.33 */
+static HRESULT Date_setMinutes(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
 {
     VARIANT v;
     HRESULT hres;
     DateInstance *date;
+    DOUBLE t, min, sec, ms;
 
     TRACE("\n");
 
@@ -898,13 +1612,33 @@
         return S_OK;
     }
 
+    date = (DateInstance*)dispex;
+    t = local_time(date->time, date);
+
     hres = to_number(dispex->ctx, get_arg(dp, 0), ei, &v);
     if(FAILED(hres))
         return hres;
-
-    date = (DateInstance*)dispex;
-    date->time = time_clip(date->time
-            - (hour_from_time(date->time) - num_val(&v))*MS_PER_HOUR);
+    min = num_val(&v);
+
+    if(arg_cnt(dp) > 1) {
+        hres = to_number(dispex->ctx, get_arg(dp, 1), ei, &v);
+        if(FAILED(hres))
+            return hres;
+        sec = num_val(&v);
+    }
+    else sec = sec_from_time(t);
+
+    if(arg_cnt(dp) > 2) {
+        hres = to_number(dispex->ctx, get_arg(dp, 2), ei, &v);
+        if(FAILED(hres))
+            return hres;
+        ms = num_val(&v);
+    }
+    else ms = ms_from_time(t);
+
+    t = make_date(day(t), make_time(hour_from_time(t),
+                min, sec, ms));
+    date->time = time_clip(utc(t, date));
 
     if(retv)
         num_set_val(retv, date->time);
@@ -912,46 +1646,468 @@
     return S_OK;
 }
 
+/* ECMA-262 3rd Edition    15.9.5.34 */
+static HRESULT Date_setUTCMinutes(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
+        VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
+{
+    VARIANT v;
+    HRESULT hres;
+    DateInstance *date;
+    DOUBLE t, min, sec, ms;
+
+    TRACE("\n");
+
+    if(!is_class(dispex, JSCLASS_DATE)) {
+        FIXME("throw TypeError\n");
+        return E_FAIL;
+    }
+
+    if(!arg_cnt(dp)) {
+        FIXME("throw ArgumentNotOptional\n");
+        if(retv) num_set_nan(retv);
+        return S_OK;
+    }
+
+    date = (DateInstance*)dispex;
+    t = date->time;
+
+    hres = to_number(dispex->ctx, get_arg(dp, 0), ei, &v);
+    if(FAILED(hres))
+        return hres;
+    min = num_val(&v);
+
+    if(arg_cnt(dp) > 1) {
+        hres = to_number(dispex->ctx, get_arg(dp, 1), ei, &v);
+        if(FAILED(hres))
+            return hres;
+        sec = num_val(&v);
+    }
+    else sec = sec_from_time(t);
+
+    if(arg_cnt(dp) > 2) {
+        hres = to_number(dispex->ctx, get_arg(dp, 2), ei, &v);
+        if(FAILED(hres))
+            return hres;
+        ms = num_val(&v);
+    }
+    else ms = ms_from_time(t);
+
+    t = make_date(day(t), make_time(hour_from_time(t),
+                min, sec, ms));
+    date->time = time_clip(t);
+
+    if(retv)
+        num_set_val(retv, date->time);
+
+    return S_OK;
+}
+
+/* ECMA-262 3rd Edition    15.9.5.35 */
+static HRESULT Date_setHours(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
+        VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
+{
+    VARIANT v;
+    HRESULT hres;
+    DateInstance *date;
+    DOUBLE t, hour, min, sec, ms;
+
+    TRACE("\n");
+
+    if(!is_class(dispex, JSCLASS_DATE)) {
+        FIXME("throw TypeError\n");
+        return E_FAIL;
+    }
+
+    if(!arg_cnt(dp)) {
+        FIXME("throw ArgumentNotOptional\n");
+        if(retv) num_set_nan(retv);
+        return S_OK;
+    }
+
+    date = (DateInstance*)dispex;
+    t = local_time(date->time, date);
+
+    hres = to_number(dispex->ctx, get_arg(dp, 0), ei, &v);
+    if(FAILED(hres))
+        return hres;
+    hour = num_val(&v);
+
+    if(arg_cnt(dp) > 1) {
+        hres = to_number(dispex->ctx, get_arg(dp, 1), ei, &v);
+        if(FAILED(hres))
+            return hres;
+        min = num_val(&v);
+    }
+    else min = min_from_time(t);
+
+    if(arg_cnt(dp) > 2) {
+        hres = to_number(dispex->ctx, get_arg(dp, 2), ei, &v);
+        if(FAILED(hres))
+            return hres;
+        sec = num_val(&v);
+    }
+    else sec = sec_from_time(t);
+
+    if(arg_cnt(dp) > 3) {
+        hres = to_number(dispex->ctx, get_arg(dp, 3), ei, &v);
+        if(FAILED(hres))
+            return hres;
+        ms = num_val(&v);
+    }
+    else ms = ms_from_time(t);
+
+    t = make_date(day(t), make_time(hour, min, sec, ms));
+    date->time = time_clip(utc(t, date));
+
+    if(retv)
+        num_set_val(retv, date->time);
+
+    return S_OK;
+}
+
+/* ECMA-262 3rd Edition    15.9.5.36 */
+static HRESULT Date_setUTCHours(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
+        VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
+{
+    VARIANT v;
+    HRESULT hres;
+    DateInstance *date;
+    DOUBLE t, hour, min, sec, ms;
+
+    TRACE("\n");
+
+    if(!is_class(dispex, JSCLASS_DATE)) {
+        FIXME("throw TypeError\n");
+        return E_FAIL;
+    }
+
+    if(!arg_cnt(dp)) {
+        FIXME("throw ArgumentNotOptional\n");
+        if(retv) num_set_nan(retv);
+        return S_OK;
+    }
+
+    date = (DateInstance*)dispex;
+    t = date->time;
+
+    hres = to_number(dispex->ctx, get_arg(dp, 0), ei, &v);
+    if(FAILED(hres))
+        return hres;
+    hour = num_val(&v);
+
+    if(arg_cnt(dp) > 1) {
+        hres = to_number(dispex->ctx, get_arg(dp, 1), ei, &v);
+        if(FAILED(hres))
+            return hres;
+        min = num_val(&v);
+    }
+    else min = min_from_time(t);
+
+    if(arg_cnt(dp) > 2) {
+        hres = to_number(dispex->ctx, get_arg(dp, 2), ei, &v);
+        if(FAILED(hres))
+            return hres;
+        sec = num_val(&v);
+    }
+    else sec = sec_from_time(t);
+
+    if(arg_cnt(dp) > 3) {
+        hres = to_number(dispex->ctx, get_arg(dp, 3), ei, &v);
+        if(FAILED(hres))
+            return hres;
+        ms = num_val(&v);
+    }
+    else ms = ms_from_time(t);
+
+    t = make_date(day(t), make_time(hour, min, sec, ms));
+    date->time = time_clip(t);
+
+    if(retv)
+        num_set_val(retv, date->time);
+
+    return S_OK;
+}
+
+/* ECMA-262 3rd Edition    15.9.5.36 */
 static HRESULT Date_setDate(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
 {
-    FIXME("\n");
-    return E_NOTIMPL;
-}
-
+    VARIANT v;
+    HRESULT hres;
+    DateInstance *date;
+    DOUBLE t;
+
+    TRACE("\n");
+
+    if(!is_class(dispex, JSCLASS_DATE)) {
+        FIXME("throw TypeError\n");
+        return E_FAIL;
+    }
+
+    if(!arg_cnt(dp)) {
+        FIXME("throw ArgumentNotOptional\n");
+        if(retv) num_set_nan(retv);
+        return S_OK;
+    }
+
+    hres = to_number(dispex->ctx, get_arg(dp, 0), ei, &v);
+    if(FAILED(hres))
+        return hres;
+
+    date = (DateInstance*)dispex;
+    t = local_time(date->time, date);
+    t = make_date(make_day(year_from_time(t), month_from_time(t),
+                num_val(&v)), time_within_day(t));
+    date->time = time_clip(utc(t, date));
+
+    if(retv)
+        num_set_val(retv, date->time);
+
+    return S_OK;
+}
+
+/* ECMA-262 3rd Edition    15.9.5.37 */
 static HRESULT Date_setUTCDate(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
 {
-    FIXME("\n");
-    return E_NOTIMPL;
-}
-
+    VARIANT v;
+    HRESULT hres;
+    DateInstance *date;
+    DOUBLE t;
+
+    TRACE("\n");
+
+    if(!is_class(dispex, JSCLASS_DATE)) {
+        FIXME("throw TypeError\n");
+        return E_FAIL;
+    }
+
+    if(!arg_cnt(dp)) {
+        FIXME("throw ArgumentNotOptional\n");
+        if(retv) num_set_nan(retv);
+        return S_OK;
+    }
+
+    hres = to_number(dispex->ctx, get_arg(dp, 0), ei, &v);
+    if(FAILED(hres))
+        return hres;
+
+    date = (DateInstance*)dispex;
+    t = date->time;
+    t = make_date(make_day(year_from_time(t), month_from_time(t),
+                num_val(&v)), time_within_day(t));
+    date->time = time_clip(t);
+
+    if(retv)
+        num_set_val(retv, date->time);
+
+    return S_OK;
+}
+
+/* ECMA-262 3rd Edition    15.9.5.38 */
 static HRESULT Date_setMonth(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
 {
-    FIXME("\n");
-    return E_NOTIMPL;
-}
-
+    VARIANT v;
+    HRESULT hres;
+    DateInstance *date;
+    DOUBLE t, month, ddate;
+
+    TRACE("\n");
+
+    if(!is_class(dispex, JSCLASS_DATE)) {
+        FIXME("throw TypeError\n");
+        return E_FAIL;
+    }
+
+    if(!arg_cnt(dp)) {
+        FIXME("throw ArgumentNotOptional\n");
+        if(retv) num_set_nan(retv);
+        return S_OK;
+    }
+
+    date = (DateInstance*)dispex;
+    t = local_time(date->time, date);
+
+    hres = to_number(dispex->ctx, get_arg(dp, 0), ei, &v);
+    if(FAILED(hres))
+        return hres;
+    month = num_val(&v);
+
+    if(arg_cnt(dp) > 1) {
+        hres = to_number(dispex->ctx, get_arg(dp, 1), ei, &v);
+        if(FAILED(hres))
+            return hres;
+        ddate = num_val(&v);
+    }
+    else ddate = date_from_time(t);
+
+    t = make_date(make_day(year_from_time(t), month, ddate),
+            time_within_day(t));
+    date->time = time_clip(utc(t, date));
+
+    if(retv)
+        num_set_val(retv, date->time);
+
+    return S_OK;
+}
+
+/* ECMA-262 3rd Edition    15.9.5.39 */
 static HRESULT Date_setUTCMonth(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
 {
-    FIXME("\n");
-    return E_NOTIMPL;
-}
-
+    VARIANT v;
+    HRESULT hres;
+    DateInstance *date;
+    DOUBLE t, month, ddate;
+
+    TRACE("\n");
+
+    if(!is_class(dispex, JSCLASS_DATE)) {
+        FIXME("throw TypeError\n");
+        return E_FAIL;
+    }
+
+    if(!arg_cnt(dp)) {
+        FIXME("throw ArgumentNotOptional\n");
+        if(retv) num_set_nan(retv);
+        return S_OK;
+    }
+
+    date = (DateInstance*)dispex;
+    t = date->time;
+
+    hres = to_number(dispex->ctx, get_arg(dp, 0), ei, &v);
+    if(FAILED(hres))
+        return hres;
+    month = num_val(&v);
+
+    if(arg_cnt(dp) > 1) {
+        hres = to_number(dispex->ctx, get_arg(dp, 1), ei, &v);
+        if(FAILED(hres))
+            return hres;
+        ddate = num_val(&v);
+    }
+    else ddate = date_from_time(t);
+
+    t = make_date(make_day(year_from_time(t), month, ddate),
+            time_within_day(t));
+    date->time = time_clip(t);
+
+    if(retv)
+        num_set_val(retv, date->time);
+
+    return S_OK;
+}
+
+/* ECMA-262 3rd Edition    15.9.5.40 */
 static HRESULT Date_setFullYear(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
 {
-    FIXME("\n");
-    return E_NOTIMPL;
-}
-
+    VARIANT v;
+    HRESULT hres;
+    DateInstance *date;
+    DOUBLE t, year, month, ddate;
+
+    TRACE("\n");
+
+    if(!is_class(dispex, JSCLASS_DATE)) {
+        FIXME("throw TypeError\n");
+        return E_FAIL;
+    }
+
+    if(!arg_cnt(dp)) {
+        FIXME("throw ArgumentNotOptional\n");
+        if(retv) num_set_nan(retv);
+        return S_OK;
+    }
+
+    date = (DateInstance*)dispex;
+    t = local_time(date->time, date);
+
+    hres = to_number(dispex->ctx, get_arg(dp, 0), ei, &v);
+    if(FAILED(hres))
+        return hres;
+    year = num_val(&v);
+
+    if(arg_cnt(dp) > 1) {
+        hres = to_number(dispex->ctx, get_arg(dp, 1), ei, &v);
+        if(FAILED(hres))
+            return hres;
+        month = num_val(&v);
+    }
+    else month = month_from_time(t);
+
+    if(arg_cnt(dp) > 2) {
+        hres = to_number(dispex->ctx, get_arg(dp, 2), ei, &v);
+        if(FAILED(hres))
+            return hres;
+        ddate = num_val(&v);
+    }
+    else ddate = date_from_time(t);
+
+    t = make_date(make_day(year, month, ddate), time_within_day(t));
+    date->time = time_clip(utc(t, date));
+
+    if(retv)
+        num_set_val(retv, date->time);
+
+    return S_OK;
+}
+
+/* ECMA-262 3rd Edition    15.9.5.41 */
 static HRESULT Date_setUTCFullYear(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
 {
-    FIXME("\n");
-    return E_NOTIMPL;
+    VARIANT v;
+    HRESULT hres;
+    DateInstance *date;
+    DOUBLE t, year, month, ddate;
+
+    TRACE("\n");
+
+    if(!is_class(dispex, JSCLASS_DATE)) {
+        FIXME("throw TypeError\n");
+        return E_FAIL;
+    }
+
+    if(!arg_cnt(dp)) {
+        FIXME("throw ArgumentNotOptional\n");
+        if(retv) num_set_nan(retv);
+        return S_OK;
+    }
+
+    date = (DateInstance*)dispex;
+    t = date->time;
+
+    hres = to_number(dispex->ctx, get_arg(dp, 0), ei, &v);
+    if(FAILED(hres))
+        return hres;
+    year = num_val(&v);
+
+    if(arg_cnt(dp) > 1) {
+        hres = to_number(dispex->ctx, get_arg(dp, 1), ei, &v);
+        if(FAILED(hres))
+            return hres;
+        month = num_val(&v);
+    }
+    else month = month_from_time(t);
+
+    if(arg_cnt(dp) > 2) {
+        hres = to_number(dispex->ctx, get_arg(dp, 2), ei, &v);
+        if(FAILED(hres))
+            return hres;
+        ddate = num_val(&v);
+    }
+    else ddate = date_from_time(t);
+
+    t = make_date(make_day(year, month, ddate), time_within_day(t));
+    date->time = time_clip(t);
+
+    if(retv)
+        num_set_val(retv, date->time);
+
+    return S_OK;
 }
 
 static HRESULT Date_value(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
@@ -1040,8 +2196,110 @@
 
     date->time = time;
     date->bias = tzi.Bias;
+    date->standardDate = tzi.StandardDate;
+    date->standardBias = tzi.StandardBias;
+    date->daylightDate = tzi.DaylightDate;
+    date->daylightBias = tzi.DaylightBias;
 
     *ret = &date->dispex;
+    return S_OK;
+}
+
+static HRESULT DateConstr_parse(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
+        VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
+{
+    FIXME("\n");
+    return E_NOTIMPL;
+}
+
+static HRESULT DateConstr_UTC(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
+        VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
+{
+    VARIANT year, month, vdate, hours, minutes, seconds, ms;
+    DOUBLE y;
+    int arg_no = arg_cnt(dp);
+    HRESULT hres;
+
+    TRACE("\n");
+
+    if(arg_no>0) {
+        hres = to_number(dispex->ctx, get_arg(dp, 0), ei, &year);
+        if(FAILED(hres))
+            return hres;
+        y = num_val(&year);
+        if(0<=y && y<=99)
+            y += 1900;
+    }
+    else y = 1900;
+
+    if(arg_no>1) {
+        hres = to_number(dispex->ctx, get_arg(dp, 1), ei, &month);
+        if(FAILED(hres))
+            return hres;
+    }
+    else {
+        V_VT(&month) = VT_R8;
+        V_R8(&month) = 0;
+    }
+
+    if(arg_no>2) {
+        hres = to_number(dispex->ctx, get_arg(dp, 2), ei, &vdate);
+        if(FAILED(hres))
+            return hres;
+    }
+    else {
+        V_VT(&vdate) = VT_R8;
+        V_R8(&vdate) = 1;
+    }
+
+    if(arg_no>3) {
+        hres = to_number(dispex->ctx, get_arg(dp, 3), ei, &hours);
+        if(FAILED(hres))
+            return hres;
+    }
+    else {
+        V_VT(&hours) = VT_R8;
+        V_R8(&hours) = 0;
+    }
+
+    if(arg_no>4) {
+        hres = to_number(dispex->ctx, get_arg(dp, 4), ei, &minutes);
+        if(FAILED(hres))
+            return hres;
+    }
+    else {
+        V_VT(&minutes) = VT_R8;
+        V_R8(&minutes) = 0;
+    }
+
+    if(arg_no>5) {
+        hres = to_number(dispex->ctx, get_arg(dp, 5), ei, &seconds);
+        if(FAILED(hres))
+            return hres;
+    }
+    else {
+        V_VT(&seconds) = VT_R8;
+        V_R8(&seconds) = 0;
+    }
+
+    if(arg_no>6) {
+        hres = to_number(dispex->ctx, get_arg(dp, 6), ei, &ms);
+        if(FAILED(hres))
+            return hres;
+    }
+    else {
+        V_VT(&ms) = VT_R8;
+        V_R8(&ms) = 0;
+    }
+
+    if(retv) {
+        V_VT(retv) = VT_R8;
+        V_R8(retv) = time_clip(make_date(
+                    make_day(y, num_val(&month), num_val(&vdate)),
+                    make_time(num_val(&hours), num_val(&minutes),
+                    num_val(&seconds), num_val(&ms))));
+    }
+
     return S_OK;
 }
 
@@ -1095,9 +2353,20 @@
             break;
         }
 
-        default:
-            FIXME("unimplemented argcnt %d\n", arg_cnt(dp));
-            return E_NOTIMPL;
+        /* ECMA-262 3rd Edition    15.9.3.1 */
+        default: {
+            VARIANT ret_date;
+            DateInstance *di;
+
+            DateConstr_UTC(dispex, lcid, flags, dp, &ret_date, ei, sp);
+
+            hres = create_date(dispex->ctx, TRUE, num_val(&ret_date), &date);
+            if(FAILED(hres))
+                return hres;
+
+            di = (DateInstance*)date;
+            di->time = utc(di->time, di);
+        }
         }
 
         V_VT(retv) = VT_DISPATCH;
@@ -1112,6 +2381,20 @@
     return S_OK;
 }
 
+static const builtin_prop_t DateConstr_props[] = {
+    {UTCW,    DateConstr_UTC,    PROPF_METHOD},
+    {parseW,  DateConstr_parse,  PROPF_METHOD}
+};
+
+static const builtin_info_t DateConstr_info = {
+    JSCLASS_FUNCTION,
+    {NULL, Function_value, 0},
+    sizeof(DateConstr_props)/sizeof(*DateConstr_props),
+    DateConstr_props,
+    NULL,
+    NULL
+};
+
 HRESULT create_date_constr(script_ctx_t *ctx, DispatchEx **ret)
 {
     DispatchEx *date;
@@ -1121,7 +2404,7 @@
     if(FAILED(hres))
         return hres;
 
-    hres = create_builtin_function(ctx, DateConstr_value, PROPF_CONSTR, date, ret);
+    hres = create_builtin_function(ctx, DateConstr_value, &DateConstr_info, PROPF_CONSTR, date, ret);
 
     jsdisp_release(date);
     return hres;

Modified: trunk/reactos/dll/win32/jscript/dispex.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/jscript/dispex.c?rev=41769&r1=41768&r2=41769&view=diff
==============================================================================
--- trunk/reactos/dll/win32/jscript/dispex.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/jscript/dispex.c [iso-8859-1] Sat Jul  4 15:49:53 2009
@@ -293,7 +293,7 @@
     case PROP_BUILTIN:
         if(prop->u.p->flags & PROPF_METHOD) {
             DispatchEx *obj;
-            hres = create_builtin_function(This->ctx, prop->u.p->invoke, prop->u.p->flags, NULL, &obj);
+            hres = create_builtin_function(This->ctx, prop->u.p->invoke, NULL, prop->u.p->flags, NULL, &obj);
             if(FAILED(hres))
                 break;
 

Modified: trunk/reactos/dll/win32/jscript/function.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/jscript/function.c?rev=41769&r1=41768&r2=41769&view=diff
==============================================================================
--- trunk/reactos/dll/win32/jscript/function.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/jscript/function.c [iso-8859-1] Sat Jul  4 15:49:53 2009
@@ -341,7 +341,7 @@
     return E_NOTIMPL;
 }
 
-static HRESULT Function_value(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
+HRESULT Function_value(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
 {
     FunctionInstance *function;
@@ -435,7 +435,8 @@
     return E_NOTIMPL;
 }
 
-static HRESULT create_function(script_ctx_t *ctx, DWORD flags, BOOL funcprot, DispatchEx *prototype, FunctionInstance **ret)
+static HRESULT create_function(script_ctx_t *ctx, const builtin_info_t *builtin_info, DWORD flags,
+        BOOL funcprot, DispatchEx *prototype, FunctionInstance **ret)
 {
     FunctionInstance *function;
     HRESULT hres;
@@ -446,6 +447,8 @@
 
     if(funcprot)
         hres = init_dispex(&function->dispex, ctx, &Function_info, prototype);
+    else if(builtin_info)
+        hres = init_dispex_from_constr(&function->dispex, ctx, builtin_info, ctx->function_constr);
     else
         hres = init_dispex_from_constr(&function->dispex, ctx, &Function_info, ctx->function_constr);
     if(FAILED(hres))
@@ -473,13 +476,13 @@
     return S_OK;
 }
 
-HRESULT create_builtin_function(script_ctx_t *ctx, builtin_invoke_t value_proc, DWORD flags,
-        DispatchEx *prototype, DispatchEx **ret)
+HRESULT create_builtin_function(script_ctx_t *ctx, builtin_invoke_t value_proc,
+        const builtin_info_t *builtin_info, DWORD flags, DispatchEx *prototype, DispatchEx **ret)
 {
     FunctionInstance *function;
     HRESULT hres;
 
-    hres = create_function(ctx, flags, FALSE, prototype, &function);
+    hres = create_function(ctx, builtin_info, flags, FALSE, prototype, &function);
     if(FAILED(hres))
         return hres;
 
@@ -502,7 +505,7 @@
     if(FAILED(hres))
         return hres;
 
-    hres = create_function(ctx->script, PROPF_CONSTR, FALSE, prototype, &function);
+    hres = create_function(ctx->script, NULL, PROPF_CONSTR, FALSE, prototype, &function);
     jsdisp_release(prototype);
     if(FAILED(hres))
         return hres;
@@ -534,13 +537,13 @@
     FunctionInstance *prot, *constr;
     HRESULT hres;
 
-    hres = create_function(ctx, PROPF_CONSTR, TRUE, NULL, &prot);
+    hres = create_function(ctx, NULL, PROPF_CONSTR, TRUE, NULL, &prot);
     if(FAILED(hres))
         return hres;
 
     prot->value_proc = FunctionProt_value;
 
-    hres = create_function(ctx, PROPF_CONSTR, TRUE, &prot->dispex, &constr);
+    hres = create_function(ctx, NULL, PROPF_CONSTR, TRUE, &prot->dispex, &constr);
     jsdisp_release(&prot->dispex);
     if(FAILED(hres))
         return hres;

Modified: trunk/reactos/dll/win32/jscript/jscript.h
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/jscript/jscript.h?rev=41769&r1=41768&r2=41769&view=diff
==============================================================================
--- trunk/reactos/dll/win32/jscript/jscript.h [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/jscript/jscript.h [iso-8859-1] Sat Jul  4 15:49:53 2009
@@ -132,7 +132,10 @@
 HRESULT jsdisp_propget_idx(DispatchEx*,DWORD,LCID,VARIANT*,jsexcept_t*,IServiceProvider*);
 HRESULT jsdisp_get_id(DispatchEx*,const WCHAR*,DWORD,DISPID*);
 
-HRESULT create_builtin_function(script_ctx_t*,builtin_invoke_t,DWORD,DispatchEx*,DispatchEx**);
+HRESULT create_builtin_function(script_ctx_t*,builtin_invoke_t,const builtin_info_t*,DWORD,
+        DispatchEx*,DispatchEx**);
+HRESULT Function_value(DispatchEx*,LCID,WORD,DISPPARAMS*,VARIANT*,jsexcept_t*,IServiceProvider*);
+
 
 HRESULT create_object(script_ctx_t*,DispatchEx*,DispatchEx**);
 HRESULT create_math(script_ctx_t*,DispatchEx**);

Modified: trunk/reactos/dll/win32/jscript/number.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/jscript/number.c?rev=41769&r1=41768&r2=41769&view=diff
==============================================================================
--- trunk/reactos/dll/win32/jscript/number.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/jscript/number.c [iso-8859-1] Sat Jul  4 15:49:53 2009
@@ -263,7 +263,7 @@
         return hres;
 
     V_VT(&number->num) = VT_I4;
-    hres = create_builtin_function(ctx, NumberConstr_value, PROPF_CONSTR, &number->dispex, ret);
+    hres = create_builtin_function(ctx, NumberConstr_value, NULL, PROPF_CONSTR, &number->dispex, ret);
 
     jsdisp_release(&number->dispex);
     return hres;

Modified: trunk/reactos/dll/win32/jscript/object.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/jscript/object.c?rev=41769&r1=41768&r2=41769&view=diff
==============================================================================
--- trunk/reactos/dll/win32/jscript/object.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/jscript/object.c [iso-8859-1] Sat Jul  4 15:49:53 2009
@@ -154,7 +154,7 @@
     if(FAILED(hres))
         return hres;
 
-    hres = create_builtin_function(ctx, ObjectConstr_value, PROPF_CONSTR, object, ret);
+    hres = create_builtin_function(ctx, ObjectConstr_value, NULL, PROPF_CONSTR, object, ret);
 
     jsdisp_release(object);
     return hres;

Modified: trunk/reactos/dll/win32/jscript/regexp.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/jscript/regexp.c?rev=41769&r1=41768&r2=41769&view=diff
==============================================================================
--- trunk/reactos/dll/win32/jscript/regexp.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/jscript/regexp.c [iso-8859-1] Sat Jul  4 15:49:53 2009
@@ -3685,7 +3685,7 @@
     if(FAILED(hres))
         return hres;
 
-    hres = create_builtin_function(ctx, RegExpConstr_value, PROPF_CONSTR, &regexp->dispex, ret);
+    hres = create_builtin_function(ctx, RegExpConstr_value, NULL, PROPF_CONSTR, &regexp->dispex, ret);
 
     jsdisp_release(&regexp->dispex);
     return hres;

Modified: trunk/reactos/dll/win32/jscript/string.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/jscript/string.c?rev=41769&r1=41768&r2=41769&view=diff
==============================================================================
--- trunk/reactos/dll/win32/jscript/string.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/jscript/string.c [iso-8859-1] Sat Jul  4 15:49:53 2009
@@ -1370,7 +1370,7 @@
     if(FAILED(hres))
         return hres;
 
-    hres = create_builtin_function(ctx, StringConstr_value, PROPF_CONSTR, &string->dispex, ret);
+    hres = create_builtin_function(ctx, StringConstr_value, NULL, PROPF_CONSTR, &string->dispex, ret);
 
     jsdisp_release(&string->dispex);
     return hres;



More information about the Ros-diffs mailing list