sync shdocvw, mshtml and jscript to wine 1.1.15
authorChristoph von Wittich <christoph_vw@reactos.org>
Fri, 13 Feb 2009 18:04:38 +0000 (18:04 +0000)
committerChristoph von Wittich <christoph_vw@reactos.org>
Fri, 13 Feb 2009 18:04:38 +0000 (18:04 +0000)
svn path=/trunk/; revision=39589

38 files changed:
reactos/dll/win32/jscript/array.c
reactos/dll/win32/jscript/date.c [new file with mode: 0644]
reactos/dll/win32/jscript/dispex.c
reactos/dll/win32/jscript/engine.c
reactos/dll/win32/jscript/engine.h
reactos/dll/win32/jscript/function.c
reactos/dll/win32/jscript/global.c
reactos/dll/win32/jscript/jscript.c
reactos/dll/win32/jscript/jscript.h
reactos/dll/win32/jscript/jscript.rbuild
reactos/dll/win32/jscript/jsutils.c
reactos/dll/win32/jscript/lex.c
reactos/dll/win32/jscript/math.c
reactos/dll/win32/jscript/number.c
reactos/dll/win32/jscript/object.c
reactos/dll/win32/jscript/parser.tab.c
reactos/dll/win32/jscript/parser.tab.h
reactos/dll/win32/jscript/parser.y
reactos/dll/win32/jscript/regexp.c
reactos/dll/win32/jscript/string.c
reactos/dll/win32/mshtml/htmldoc.c
reactos/dll/win32/mshtml/htmllocation.c
reactos/dll/win32/mshtml/htmlstyle.c
reactos/dll/win32/mshtml/htmlstyle.h
reactos/dll/win32/mshtml/htmlstyle3.c [new file with mode: 0644]
reactos/dll/win32/mshtml/htmlstylesheet.c
reactos/dll/win32/mshtml/install.c
reactos/dll/win32/mshtml/mshtml.rbuild
reactos/dll/win32/mshtml/mshtml_private.h
reactos/dll/win32/mshtml/mutation.c
reactos/dll/win32/mshtml/nsembed.c
reactos/dll/win32/mshtml/nsiface.idl
reactos/dll/win32/mshtml/script.c
reactos/dll/win32/shdocvw/oleobject.c
reactos/include/psdk/activdbg.idl
reactos/include/psdk/activscp.idl
reactos/include/psdk/mshtmdid.h
reactos/include/psdk/mshtml.idl

index c131865..8f0802e 100644 (file)
@@ -47,6 +47,7 @@ static const WCHAR propertyIsEnumerableW[] =
     {'p','r','o','p','e','r','t','y','I','s','E','n','u','m','e','r','a','b','l','e',0};
 static const WCHAR isPrototypeOfW[] = {'i','s','P','r','o','t','o','t','y','p','e','O','f',0};
 
+static const WCHAR default_separatorW[] = {',',0};
 
 static HRESULT Array_length(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
         VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
@@ -68,32 +69,312 @@ static HRESULT Array_length(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAM
     return S_OK;
 }
 
+static HRESULT concat_array(DispatchEx *array, ArrayInstance *obj, DWORD *len, LCID lcid,
+        jsexcept_t *ei, IServiceProvider *caller)
+{
+    VARIANT var;
+    DWORD i;
+    HRESULT hres;
+
+    for(i=0; i < obj->length; i++) {
+        hres = jsdisp_propget_idx(&obj->dispex, i, lcid, &var, ei, caller);
+        if(hres == DISP_E_UNKNOWNNAME)
+            continue;
+        if(FAILED(hres))
+            return hres;
+
+        hres = jsdisp_propput_idx(array, *len+i, lcid, &var, ei, caller);
+        VariantClear(&var);
+        if(FAILED(hres))
+            return hres;
+    }
+
+    *len += obj->length;
+    return S_OK;
+}
+
+static HRESULT concat_obj(DispatchEx *array, IDispatch *obj, DWORD *len, LCID lcid, jsexcept_t *ei, IServiceProvider *caller)
+{
+    DispatchEx *jsobj;
+    VARIANT var;
+    HRESULT hres;
+
+    jsobj = iface_to_jsdisp((IUnknown*)obj);
+    if(jsobj) {
+        if(is_class(jsobj, JSCLASS_ARRAY)) {
+            hres = concat_array(array, (ArrayInstance*)jsobj, len, lcid, ei, caller);
+            jsdisp_release(jsobj);
+            return hres;
+        }
+        jsdisp_release(jsobj);
+    }
+
+    V_VT(&var) = VT_DISPATCH;
+    V_DISPATCH(&var) = obj;
+    return jsdisp_propput_idx(array, (*len)++, lcid, &var, ei, caller);
+}
+
 static HRESULT Array_concat(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
-        VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
+        VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
 {
-    FIXME("\n");
-    return E_NOTIMPL;
+    DispatchEx *ret;
+    DWORD len = 0;
+    HRESULT hres;
+
+    TRACE("\n");
+
+    hres = create_array(dispex->ctx, 0, &ret);
+    if(FAILED(hres))
+        return hres;
+
+    hres = concat_obj(ret, (IDispatch*)_IDispatchEx_(dispex), &len, lcid, ei, caller);
+    if(SUCCEEDED(hres)) {
+        VARIANT *arg;
+        DWORD i;
+
+        for(i=0; i < arg_cnt(dp); i++) {
+            arg = get_arg(dp, i);
+            if(V_VT(arg) == VT_DISPATCH)
+                hres = concat_obj(ret, V_DISPATCH(arg), &len, lcid, ei, caller);
+            else
+                hres = jsdisp_propput_idx(ret, len++, lcid, arg, ei, caller);
+            if(FAILED(hres))
+                break;
+        }
+    }
+
+    if(FAILED(hres))
+        return hres;
+
+    if(retv) {
+        V_VT(retv) = VT_DISPATCH;
+        V_DISPATCH(retv) = (IDispatch*)_IDispatchEx_(ret);
+    }else {
+        jsdisp_release(ret);
+    }
+    return S_OK;
+}
+
+static HRESULT array_join(DispatchEx *array, LCID lcid, DWORD length, const WCHAR *sep, VARIANT *retv,
+        jsexcept_t *ei, IServiceProvider *caller)
+{
+    BSTR *str_tab, ret = NULL;
+    VARIANT var;
+    DWORD i;
+    HRESULT hres = E_FAIL;
+
+    if(!length) {
+        if(retv) {
+            V_VT(retv) = VT_BSTR;
+            V_BSTR(retv) = SysAllocStringLen(NULL, 0);
+            if(!V_BSTR(retv))
+                return E_OUTOFMEMORY;
+        }
+        return S_OK;
+    }
+
+    str_tab = heap_alloc_zero(length * sizeof(BSTR));
+    if(!str_tab)
+        return E_OUTOFMEMORY;
+
+    for(i=0; i < length; i++) {
+        hres = jsdisp_propget_idx(array, i, lcid, &var, ei, caller);
+        if(FAILED(hres))
+            break;
+
+        if(V_VT(&var) != VT_EMPTY && V_VT(&var) != VT_NULL)
+            hres = to_string(array->ctx, &var, ei, str_tab+i);
+        VariantClear(&var);
+        if(FAILED(hres))
+            break;
+    }
+
+    if(SUCCEEDED(hres)) {
+        DWORD seplen = 0, len = 0;
+        WCHAR *ptr;
+
+        seplen = strlenW(sep);
+
+        if(str_tab[0])
+            len = SysStringLen(str_tab[0]);
+        for(i=1; i < length; i++)
+            len += seplen + SysStringLen(str_tab[i]);
+
+        ret = SysAllocStringLen(NULL, len);
+        if(ret) {
+            DWORD tmplen = 0;
+
+            if(str_tab[0]) {
+                tmplen = SysStringLen(str_tab[0]);
+                memcpy(ret, str_tab[0], tmplen*sizeof(WCHAR));
+            }
+
+            ptr = ret + tmplen;
+            for(i=1; i < length; i++) {
+                if(seplen) {
+                    memcpy(ptr, sep, seplen*sizeof(WCHAR));
+                    ptr += seplen;
+                }
+
+                if(str_tab[i]) {
+                    tmplen = SysStringLen(str_tab[i]);
+                    memcpy(ptr, str_tab[i], tmplen*sizeof(WCHAR));
+                    ptr += tmplen;
+                }
+            }
+            *ptr=0;
+        }else {
+            hres = E_OUTOFMEMORY;
+        }
+    }
+
+    for(i=0; i < length; i++)
+        SysFreeString(str_tab[i]);
+    heap_free(str_tab);
+    if(FAILED(hres))
+        return hres;
+
+    TRACE("= %s\n", debugstr_w(ret));
+
+    if(retv) {
+        if(!ret) {
+            ret = SysAllocStringLen(NULL, 0);
+            if(!ret)
+                return E_OUTOFMEMORY;
+        }
+
+        V_VT(retv) = VT_BSTR;
+        V_BSTR(retv) = ret;
+    }else {
+        SysFreeString(ret);
+    }
+
+    return S_OK;
 }
 
+/* ECMA-262 3rd Edition    15.4.4.5 */
 static HRESULT Array_join(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
-        VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
+        VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
 {
-    FIXME("\n");
-    return E_NOTIMPL;
+    DWORD length;
+    HRESULT hres;
+
+    TRACE("\n");
+
+    if(is_class(dispex, JSCLASS_ARRAY)) {
+        length = ((ArrayInstance*)dispex)->length;
+    }else {
+        FIXME("dispid is not Array\n");
+        return E_NOTIMPL;
+    }
+
+    if(arg_cnt(dp)) {
+        BSTR sep;
+
+        hres = to_string(dispex->ctx, dp->rgvarg + dp->cArgs-1, ei, &sep);
+        if(FAILED(hres))
+            return hres;
+
+        hres = array_join(dispex, lcid, length, sep, retv, ei, caller);
+
+        SysFreeString(sep);
+    }else {
+        hres = array_join(dispex, lcid, length, default_separatorW, retv, ei, caller);
+    }
+
+    return hres;
 }
 
 static HRESULT Array_pop(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
-        VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
+        VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
 {
-    FIXME("\n");
-    return E_NOTIMPL;
+    VARIANT val;
+    DWORD length;
+    WCHAR buf[14];
+    DISPID id;
+    HRESULT hres;
+
+    static const WCHAR formatW[] = {'%','d',0};
+
+    TRACE("\n");
+
+    if(is_class(dispex, JSCLASS_ARRAY)) {
+        ArrayInstance *array = (ArrayInstance*)dispex;
+        length = array->length;
+    }else {
+        FIXME("not Array this\n");
+        return E_NOTIMPL;
+    }
+
+    if(!length) {
+        if(retv)
+            V_VT(retv) = VT_EMPTY;
+        return S_OK;
+    }
+
+    sprintfW(buf, formatW, --length);
+    hres = jsdisp_get_id(dispex, buf, 0, &id);
+    if(SUCCEEDED(hres)) {
+        hres = jsdisp_propget(dispex, id, lcid, &val, ei, caller);
+        if(FAILED(hres))
+            return hres;
+
+        hres = IDispatchEx_DeleteMemberByDispID(_IDispatchEx_(dispex), id);
+    }else if(hres == DISP_E_UNKNOWNNAME) {
+        V_VT(&val) = VT_EMPTY;
+        hres = S_OK;
+    }else {
+        return hres;
+    }
+
+    if(SUCCEEDED(hres)) {
+        if(is_class(dispex, JSCLASS_ARRAY)) {
+            ArrayInstance *array = (ArrayInstance*)dispex;
+            array->length = length;
+        }
+    }
+
+    if(FAILED(hres)) {
+        VariantClear(&val);
+        return hres;
+    }
+
+    if(retv)
+        *retv = val;
+    else
+        VariantClear(&val);
+    return S_OK;
 }
 
+/* ECMA-262 3rd Edition    15.4.4.7 */
 static HRESULT Array_push(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
         VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
 {
-    FIXME("\n");
-    return E_NOTIMPL;
+    DWORD length = 0;
+    int i, n;
+    HRESULT hres;
+
+    TRACE("\n");
+
+    if(dispex->builtin_info->class == JSCLASS_ARRAY) {
+        length = ((ArrayInstance*)dispex)->length;
+    }else {
+        FIXME("not Array this\n");
+        return E_NOTIMPL;
+    }
+
+    n = dp->cArgs - dp->cNamedArgs;
+    for(i=0; i < n; i++) {
+        hres = jsdisp_propput_idx(dispex, length+i, lcid, get_arg(dp, i), ei, sp);
+        if(FAILED(hres))
+            return hres;
+    }
+
+    if(retv) {
+        V_VT(retv) = VT_I4;
+        V_I4(retv) = length+n;
+    }
+    return S_OK;
 }
 
 static HRESULT Array_reverse(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
@@ -117,11 +398,216 @@ static HRESULT Array_slice(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS
     return E_NOTIMPL;
 }
 
+static HRESULT sort_cmp(script_ctx_t *ctx, DispatchEx *cmp_func, VARIANT *v1, VARIANT *v2, jsexcept_t *ei,
+        IServiceProvider *caller, INT *cmp)
+{
+    HRESULT hres;
+
+    if(cmp_func) {
+        VARIANTARG args[2];
+        DISPPARAMS dp = {args, NULL, 2, 0};
+        VARIANT tmp;
+        VARIANT res;
+
+        args[0] = *v2;
+        args[1] = *v1;
+
+        hres = jsdisp_call_value(cmp_func, ctx->lcid, DISPATCH_METHOD, &dp, &res, ei, caller);
+        if(FAILED(hres))
+            return hres;
+
+        hres = to_number(ctx, &res, ei, &tmp);
+        VariantClear(&res);
+        if(FAILED(hres))
+            return hres;
+
+        if(V_VT(&tmp) == VT_I4)
+            *cmp = V_I4(&tmp);
+        else
+            *cmp = V_R8(&tmp) > 0.0 ? 1 : -1;
+    }else if(is_num_vt(V_VT(v1))) {
+        if(is_num_vt(V_VT(v2))) {
+            DOUBLE d = num_val(v1)-num_val(v2);
+            if(d > 0.0)
+                *cmp = 1;
+            else if(d < -0.0)
+                *cmp = -1;
+            else
+                *cmp = 0;
+        }else {
+            *cmp = -1;
+        }
+    }else if(is_num_vt(V_VT(v2))) {
+        *cmp = 1;
+    }else if(V_VT(v1) == VT_BSTR) {
+        if(V_VT(v2) == VT_BSTR)
+            *cmp = strcmpW(V_BSTR(v1), V_BSTR(v2));
+        else
+            *cmp = -1;
+    }else if(V_VT(v2) == VT_BSTR) {
+        *cmp = 1;
+    }else {
+        *cmp = 0;
+    }
+
+    return S_OK;
+}
+
+/* ECMA-262 3rd Edition    15.4.4.11 */
 static HRESULT Array_sort(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
-        VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
+        VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
 {
-    FIXME("\n");
-    return E_NOTIMPL;
+    DispatchEx *cmp_func = NULL;
+    VARIANT *vtab, **sorttab = NULL;
+    DWORD length;
+    DWORD i;
+    HRESULT hres = S_OK;
+
+    TRACE("\n");
+
+    if(is_class(dispex, JSCLASS_ARRAY)) {
+        length = ((ArrayInstance*)dispex)->length;
+    }else {
+        FIXME("unsupported this not array\n");
+        return E_NOTIMPL;
+    }
+
+    if(arg_cnt(dp) > 1) {
+        WARN("invalid arg_cnt %d\n", arg_cnt(dp));
+        return E_FAIL;
+    }
+
+    if(arg_cnt(dp) == 1) {
+        VARIANT *arg = get_arg(dp, 0);
+
+        if(V_VT(arg) != VT_DISPATCH) {
+            WARN("arg is not dispatch\n");
+            return E_FAIL;
+        }
+
+
+        cmp_func = iface_to_jsdisp((IUnknown*)V_DISPATCH(arg));
+        if(!cmp_func || !is_class(cmp_func, JSCLASS_FUNCTION)) {
+            WARN("cmp_func is not a function\n");
+            if(cmp_func)
+                jsdisp_release(cmp_func);
+            return E_FAIL;
+        }
+    }
+
+    if(!length) {
+        if(cmp_func)
+            jsdisp_release(cmp_func);
+        if(retv) {
+            V_VT(retv) = VT_DISPATCH;
+            V_DISPATCH(retv) = (IDispatch*)_IDispatchEx_(dispex);
+           IDispatchEx_AddRef(_IDispatchEx_(dispex));
+        }
+        return S_OK;
+    }
+
+    vtab = heap_alloc_zero(length * sizeof(VARIANT));
+    if(vtab) {
+        for(i=0; i<length; i++) {
+            hres = jsdisp_propget_idx(dispex, i, lcid, vtab+i, ei, caller);
+            if(FAILED(hres) && hres != DISP_E_UNKNOWNNAME) {
+                WARN("Could not get elem %d: %08x\n", i, hres);
+                break;
+            }
+        }
+    }else {
+        hres = E_OUTOFMEMORY;
+    }
+
+    if(SUCCEEDED(hres)) {
+        sorttab = heap_alloc(length*2*sizeof(VARIANT*));
+        if(!sorttab)
+            hres = E_OUTOFMEMORY;
+    }
+
+    /* merge-sort */
+    if(SUCCEEDED(hres)) {
+        VARIANT *tmpv, **tmpbuf;
+        INT cmp;
+
+        tmpbuf = sorttab + length;
+        for(i=0; i < length; i++)
+            sorttab[i] = vtab+i;
+
+        for(i=0; i < length/2; i++) {
+            hres = sort_cmp(dispex->ctx, cmp_func, sorttab[2*i+1], sorttab[2*i], ei, caller, &cmp);
+            if(FAILED(hres))
+                break;
+
+            if(cmp < 0) {
+                tmpv = sorttab[2*i];
+                sorttab[2*i] = sorttab[2*i+1];
+                sorttab[2*i+1] = tmpv;
+            }
+        }
+
+        if(SUCCEEDED(hres)) {
+            DWORD k, a, b, bend;
+
+            for(k=2; k < length; k *= 2) {
+                for(i=0; i+k < length; i += 2*k) {
+                    a = b = 0;
+                    if(i+2*k <= length)
+                        bend = k;
+                    else
+                        bend = length - (i+k);
+
+                    memcpy(tmpbuf, sorttab+i, k*sizeof(VARIANT*));
+
+                    while(a < k && b < bend) {
+                        hres = sort_cmp(dispex->ctx, cmp_func, tmpbuf[a], sorttab[i+k+b], ei, caller, &cmp);
+                        if(FAILED(hres))
+                            break;
+
+                        if(cmp < 0) {
+                            sorttab[i+a+b] = tmpbuf[a];
+                            a++;
+                        }else {
+                            sorttab[i+a+b] = sorttab[i+k+b];
+                            b++;
+                        }
+                    }
+
+                    if(FAILED(hres))
+                        break;
+
+                    if(a < k)
+                        memcpy(sorttab+i+a+b, tmpbuf+a, (k-a)*sizeof(VARIANT*));
+                }
+
+                if(FAILED(hres))
+                    break;
+            }
+        }
+
+        for(i=0; SUCCEEDED(hres) && i < length; i++)
+            hres = jsdisp_propput_idx(dispex, i, lcid, sorttab[i], ei, caller);
+    }
+
+    if(vtab) {
+        for(i=0; i < length; i++)
+            VariantClear(vtab+i);
+        heap_free(vtab);
+    }
+    heap_free(sorttab);
+    if(cmp_func)
+        jsdisp_release(cmp_func);
+
+    if(FAILED(hres))
+        return hres;
+
+    if(retv) {
+        V_VT(retv) = VT_DISPATCH;
+        V_DISPATCH(retv) = (IDispatch*)_IDispatchEx_(dispex);
+        IDispatch_AddRef(_IDispatchEx_(dispex));
+    }
+
+    return S_OK;
 }
 
 static HRESULT Array_splice(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
@@ -131,11 +617,18 @@ static HRESULT Array_splice(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAM
     return E_NOTIMPL;
 }
 
+/* ECMA-262 3rd Edition    15.4.4.2 */
 static HRESULT Array_toString(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
         VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
 {
-    FIXME("\n");
-    return E_NOTIMPL;
+    TRACE("\n");
+
+    if(!is_class(dispex, JSCLASS_ARRAY)) {
+        WARN("not Array object\n");
+        return E_FAIL;
+    }
+
+    return array_join(dispex, lcid, ((ArrayInstance*)dispex)->length, default_separatorW, retv, ei, sp);
 }
 
 static HRESULT Array_toLocaleString(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
@@ -183,8 +676,17 @@ static HRESULT Array_isPrototypeOf(DispatchEx *dispex, LCID lcid, WORD flags, DI
 static HRESULT Array_value(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
         VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
 {
-    FIXME("\n");
-    return E_NOTIMPL;
+    TRACE("\n");
+
+    switch(flags) {
+    case INVOKE_PROPERTYGET:
+        return array_join(dispex, lcid, ((ArrayInstance*)dispex)->length, default_separatorW, retv, ei, sp);
+    default:
+        FIXME("unimplemented flags %x\n", flags);
+        return E_NOTIMPL;
+    }
+
+    return S_OK;
 }
 
 static void Array_destructor(DispatchEx *dispex)
@@ -297,9 +799,13 @@ static HRESULT ArrayConstr_value(DispatchEx *dispex, LCID lcid, WORD flags, DISP
 
 static HRESULT alloc_array(script_ctx_t *ctx, BOOL use_constr, ArrayInstance **ret)
 {
-    ArrayInstance *array = heap_alloc_zero(sizeof(ArrayInstance));
+    ArrayInstance *array;
     HRESULT hres;
 
+    array = heap_alloc_zero(sizeof(ArrayInstance));
+    if(!array)
+        return E_OUTOFMEMORY;
+
     if(use_constr)
         hres = init_dispex_from_constr(&array->dispex, ctx, &Array_info, ctx->array_constr);
     else
diff --git a/reactos/dll/win32/jscript/date.c b/reactos/dll/win32/jscript/date.c
new file mode 100644 (file)
index 0000000..0dac085
--- /dev/null
@@ -0,0 +1,579 @@
+/*
+ * Copyright 2008 Jacek Caban for CodeWeavers
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include <limits.h>
+#include <math.h>
+
+#include "jscript.h"
+
+#include "wine/debug.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(jscript);
+
+typedef struct {
+    DispatchEx dispex;
+
+    /* ECMA-262 3rd Edition    15.9.1.1 */
+    DOUBLE time;
+} DateInstance;
+
+static const WCHAR toStringW[] = {'t','o','S','t','r','i','n','g',0};
+static const WCHAR toLocaleStringW[] = {'t','o','L','o','c','a','l','e','S','t','r','i','n','g',0};
+static const WCHAR hasOwnPropertyW[] = {'h','a','s','O','w','n','P','r','o','p','e','r','t','y',0};
+static const WCHAR propertyIsEnumerableW[] =
+    {'p','r','o','p','e','r','t','y','I','s','E','n','u','m','e','r','a','b','l','e',0};
+static const WCHAR isPrototypeOfW[] = {'i','s','P','r','o','t','o','t','y','p','e','O','f',0};
+static const WCHAR valueOfW[] = {'v','a','l','u','e','O','f',0};
+static const WCHAR toUTCStringW[] = {'t','o','U','T','C','S','t','r','i','n','g',0};
+static const WCHAR toDateStringW[] = {'t','o','D','a','t','e','S','t','r','i','n','g',0};
+static const WCHAR toTimeStringW[] = {'t','o','T','i','m','e','S','t','r','i','n','g',0};
+static const WCHAR toLocaleDateStringW[] = {'t','o','L','o','c','a','l','e','D','a','t','e','S','t','r','i','n','g',0};
+static const WCHAR toLocaleTimeStringW[] = {'t','o','L','o','c','a','l','e','T','i','m','e','S','t','r','i','n','g',0};
+static const WCHAR getTimeW[] = {'g','e','t','T','i','m','e',0};
+static const WCHAR getFullYearW[] = {'g','e','t','F','u','l','l','Y','e','a','r',0};
+static const WCHAR getUTCFullYearW[] = {'g','e','t','U','T','C','F','u','l','l','Y','e','a','r',0};
+static const WCHAR getMonthW[] = {'g','e','t','M','o','n','t','h',0};
+static const WCHAR getUTCMonthW[] = {'g','e','t','U','T','C','M','o','n','t','h',0};
+static const WCHAR getDateW[] = {'g','e','t','D','a','t','e',0};
+static const WCHAR getUTCDateW[] = {'g','e','t','U','T','C','D','a','t','e',0};
+static const WCHAR getDayW[] = {'g','e','t','D','a','y',0};
+static const WCHAR getUTCDayW[] = {'g','e','t','U','T','C','D','a','y',0};
+static const WCHAR getHoursW[] = {'g','e','t','H','o','u','r','s',0};
+static const WCHAR getUTCHoursW[] = {'g','e','t','U','T','C','H','o','u','r','s',0};
+static const WCHAR getMinutesW[] = {'g','e','t','M','i','n','u','t','e','s',0};
+static const WCHAR getUTCMinutesW[] = {'g','e','t','U','T','C','M','i','n','u','t','e','s',0};
+static const WCHAR getSecondsW[] = {'g','e','t','S','e','c','o','n','d','s',0};
+static const WCHAR getUTCSecondsW[] = {'g','e','t','U','T','C','S','e','c','o','n','d','s',0};
+static const WCHAR getMilisecondsW[] = {'g','e','t','M','i','l','i','s','e','c','o','n','d','s',0};
+static const WCHAR getUTCMilisecondsW[] = {'g','e','t','U','T','C','M','i','l','i','s','e','c','o','n','d','s',0};
+static const WCHAR getTimezoneOffsetW[] = {'g','e','t','T','i','m','e','z','o','n','e','O','f','f','s','e','t',0};
+static const WCHAR setTimeW[] = {'s','e','t','T','i','m','e',0};
+static const WCHAR setMilisecondsW[] = {'s','e','t','M','i','l','i','s','e','c','o','n','d','s',0};
+static const WCHAR setUTCMilisecondsW[] = {'s','e','t','U','T','C','M','i','l','i','s','e','c','o','n','d','s',0};
+static const WCHAR setSecondsW[] = {'s','e','t','S','e','c','o','n','d','s',0};
+static const WCHAR setUTCSecondsW[] = {'s','e','t','U','T','C','S','e','c','o','n','d','s',0};
+static const WCHAR setMinutesW[] = {'s','e','t','M','i','n','u','t','e','s',0};
+static const WCHAR setUTCMinutesW[] = {'s','e','t','U','T','C','M','i','n','u','t','e','s',0};
+static const WCHAR setHoursW[] = {'s','e','t','H','o','u','r','s',0};
+static const WCHAR setUTCHoursW[] = {'s','e','t','H','o','u','r','s',0};
+static const WCHAR setDateW[] = {'s','e','t','D','a','t','e',0};
+static const WCHAR setUTCDateW[] = {'s','e','t','U','T','C','D','a','t','e',0};
+static const WCHAR setMonthW[] = {'s','e','t','M','o','n','t','h',0};
+static const WCHAR setUTCMonthW[] = {'s','e','t','U','T','C','M','o','n','t','h',0};
+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 3rd Edition    15.9.1.14 */
+static inline DOUBLE time_clip(DOUBLE time)
+{
+    /* FIXME: Handle inf */
+
+    if(8.64e15 < time || time < -8.64e15) {
+        FIXME("return NaN\n");
+        return 0.0;
+    }
+
+    return floor(time);
+}
+
+static HRESULT Date_toString(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,
+        VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
+{
+    FIXME("\n");
+    return E_NOTIMPL;
+}
+
+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_propertyIsEnumerable(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;
+}
+
+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 HRESULT Date_toDateString(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
+        VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
+{
+    FIXME("\n");
+    return E_NOTIMPL;
+}
+
+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 HRESULT Date_toLocaleDateString(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
+        VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
+{
+    FIXME("\n");
+    return E_NOTIMPL;
+}
+
+static HRESULT Date_toLocaleTimeString(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.9 */
+static HRESULT Date_getTime(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
+        VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
+{
+    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, date->time);
+    }
+    return S_OK;
+}
+
+static HRESULT Date_getFullYear(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
+        VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
+{
+    FIXME("\n");
+    return E_NOTIMPL;
+}
+
+static HRESULT Date_getUTCFullYear(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
+        VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
+{
+    FIXME("\n");
+    return E_NOTIMPL;
+}
+
+static HRESULT Date_getMonth(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
+        VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
+{
+    FIXME("\n");
+    return E_NOTIMPL;
+}
+
+static HRESULT Date_getUTCMonth(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
+        VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
+{
+    FIXME("\n");
+    return E_NOTIMPL;
+}
+
+static HRESULT Date_getDate(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
+        VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
+{
+    FIXME("\n");
+    return E_NOTIMPL;
+}
+
+static HRESULT Date_getUTCDate(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
+        VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
+{
+    FIXME("\n");
+    return E_NOTIMPL;
+}
+
+static HRESULT Date_getDay(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
+        VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
+{
+    FIXME("\n");
+    return E_NOTIMPL;
+}
+
+static HRESULT Date_getUTCDay(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
+        VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
+{
+    FIXME("\n");
+    return E_NOTIMPL;
+}
+
+static HRESULT Date_getHours(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
+        VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
+{
+    FIXME("\n");
+    return E_NOTIMPL;
+}
+
+static HRESULT Date_getUTCHours(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
+        VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
+{
+    FIXME("\n");
+    return E_NOTIMPL;
+}
+
+static HRESULT Date_getMinutes(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
+        VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
+{
+    FIXME("\n");
+    return E_NOTIMPL;
+}
+
+static HRESULT Date_getUTCMinutes(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
+        VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
+{
+    FIXME("\n");
+    return E_NOTIMPL;
+}
+
+static HRESULT Date_getSeconds(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
+        VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
+{
+    FIXME("\n");
+    return E_NOTIMPL;
+}
+
+static HRESULT Date_getUTCSeconds(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
+        VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
+{
+    FIXME("\n");
+    return E_NOTIMPL;
+}
+
+static HRESULT Date_getMiliseconds(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
+        VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
+{
+    FIXME("\n");
+    return E_NOTIMPL;
+}
+
+static HRESULT Date_getUTCMiliseconds(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
+        VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
+{
+    FIXME("\n");
+    return E_NOTIMPL;
+}
+
+static HRESULT Date_getTimezoneOffset(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
+        VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
+{
+    FIXME("\n");
+    return E_NOTIMPL;
+}
+
+static HRESULT Date_setTime(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
+        VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
+{
+    FIXME("\n");
+    return E_NOTIMPL;
+}
+
+static HRESULT Date_setMiliseconds(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
+        VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
+{
+    FIXME("\n");
+    return E_NOTIMPL;
+}
+
+static HRESULT Date_setUTCMiliseconds(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
+        VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
+{
+    FIXME("\n");
+    return E_NOTIMPL;
+}
+
+static HRESULT Date_setSeconds(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
+        VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
+{
+    FIXME("\n");
+    return E_NOTIMPL;
+}
+
+static HRESULT Date_setUTCSeconds(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
+        VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
+{
+    FIXME("\n");
+    return E_NOTIMPL;
+}
+
+static HRESULT Date_setMinutes(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
+        VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
+{
+    FIXME("\n");
+    return E_NOTIMPL;
+}
+
+static HRESULT Date_setUTCMinutes(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
+        VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
+{
+    FIXME("\n");
+    return E_NOTIMPL;
+}
+
+static HRESULT Date_setHours(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
+        VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
+{
+    FIXME("\n");
+    return E_NOTIMPL;
+}
+
+static HRESULT Date_setUTCHours(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
+        VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
+{
+    FIXME("\n");
+    return E_NOTIMPL;
+}
+
+static HRESULT Date_setDate(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
+        VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
+{
+    FIXME("\n");
+    return E_NOTIMPL;
+}
+
+static HRESULT Date_setUTCDate(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
+        VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
+{
+    FIXME("\n");
+    return E_NOTIMPL;
+}
+
+static HRESULT Date_setMonth(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
+        VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
+{
+    FIXME("\n");
+    return E_NOTIMPL;
+}
+
+static HRESULT Date_setUTCMonth(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
+        VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
+{
+    FIXME("\n");
+    return E_NOTIMPL;
+}
+
+static HRESULT Date_setFullYear(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
+        VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
+{
+    FIXME("\n");
+    return E_NOTIMPL;
+}
+
+static HRESULT Date_setUTCFullYear(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
+        VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
+{
+    FIXME("\n");
+    return E_NOTIMPL;
+}
+
+static HRESULT Date_value(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
+        VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
+{
+    FIXME("\n");
+    return E_NOTIMPL;
+}
+
+static const builtin_prop_t Date_props[] = {
+    {getDateW,               Date_getDate,               PROPF_METHOD},
+    {getDayW,                Date_getDay,                PROPF_METHOD},
+    {getFullYearW,           Date_getFullYear,           PROPF_METHOD},
+    {getHoursW,              Date_getHours,              PROPF_METHOD},
+    {getMilisecondsW,        Date_getMiliseconds,        PROPF_METHOD},
+    {getMinutesW,            Date_getMinutes,            PROPF_METHOD},
+    {getMonthW,              Date_getMonth,              PROPF_METHOD},
+    {getSecondsW,            Date_getSeconds,            PROPF_METHOD},
+    {getTimeW,               Date_getTime,               PROPF_METHOD},
+    {getTimezoneOffsetW,     Date_getTimezoneOffset,     PROPF_METHOD},
+    {getUTCDateW,            Date_getUTCDate,            PROPF_METHOD},
+    {getUTCDayW,             Date_getUTCDay,             PROPF_METHOD},
+    {getUTCFullYearW,        Date_getUTCFullYear,        PROPF_METHOD},
+    {getUTCHoursW,           Date_getUTCHours,           PROPF_METHOD},
+    {getUTCMilisecondsW,     Date_getUTCMiliseconds,     PROPF_METHOD},
+    {getUTCMinutesW,         Date_getUTCMinutes,         PROPF_METHOD},
+    {getUTCMonthW,           Date_getUTCMonth,           PROPF_METHOD},
+    {getUTCSecondsW,         Date_getUTCSeconds,         PROPF_METHOD},
+    {hasOwnPropertyW,        Date_hasOwnProperty,        PROPF_METHOD},
+    {isPrototypeOfW,         Date_isPrototypeOf,         PROPF_METHOD},
+    {propertyIsEnumerableW,  Date_propertyIsEnumerable,  PROPF_METHOD},
+    {setDateW,               Date_setDate,               PROPF_METHOD},
+    {setFullYearW,           Date_setFullYear,           PROPF_METHOD},
+    {setHoursW,              Date_setHours,              PROPF_METHOD},
+    {setMilisecondsW,        Date_setMiliseconds,        PROPF_METHOD},
+    {setMinutesW,            Date_setMinutes,            PROPF_METHOD},
+    {setMonthW,              Date_setMonth,              PROPF_METHOD},
+    {setSecondsW,            Date_setSeconds,            PROPF_METHOD},
+    {setTimeW,               Date_setTime,               PROPF_METHOD},
+    {setUTCDateW,            Date_setUTCDate,            PROPF_METHOD},
+    {setUTCFullYearW,        Date_setUTCFullYear,        PROPF_METHOD},
+    {setUTCHoursW,           Date_setUTCHours,           PROPF_METHOD},
+    {setUTCMilisecondsW,     Date_setUTCMiliseconds,     PROPF_METHOD},
+    {setUTCMinutesW,         Date_setUTCMinutes,         PROPF_METHOD},
+    {setUTCMonthW,           Date_setUTCMonth,           PROPF_METHOD},
+    {setUTCSecondsW,         Date_setUTCSeconds,         PROPF_METHOD},
+    {toDateStringW,          Date_toDateString,          PROPF_METHOD},
+    {toLocaleDateStringW,    Date_toLocaleDateString,    PROPF_METHOD},
+    {toLocaleStringW,        Date_toLocaleString,        PROPF_METHOD},
+    {toLocaleTimeStringW,    Date_toLocaleTimeString,    PROPF_METHOD},
+    {toStringW,              Date_toString,              PROPF_METHOD},
+    {toTimeStringW,          Date_toTimeString,          PROPF_METHOD},
+    {toUTCStringW,           Date_toUTCString,           PROPF_METHOD},
+    {valueOfW,               Date_valueOf,               PROPF_METHOD},
+};
+
+static const builtin_info_t Date_info = {
+    JSCLASS_DATE,
+    {NULL, Date_value, 0},
+    sizeof(Date_props)/sizeof(*Date_props),
+    Date_props,
+    NULL,
+    NULL
+};
+
+static HRESULT create_date(script_ctx_t *ctx, BOOL use_constr, DOUBLE time, DispatchEx **ret)
+{
+    DateInstance *date;
+    HRESULT hres;
+
+    date = heap_alloc_zero(sizeof(DateInstance));
+    if(!date)
+        return E_OUTOFMEMORY;
+
+    if(use_constr)
+        hres = init_dispex_from_constr(&date->dispex, ctx, &Date_info, ctx->date_constr);
+    else
+        hres = init_dispex(&date->dispex, ctx, &Date_info, NULL);
+    if(FAILED(hres)) {
+        heap_free(date);
+        return hres;
+    }
+
+    date->time = time;
+
+    *ret = &date->dispex;
+    return S_OK;
+}
+
+static HRESULT DateConstr_value(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
+        VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
+{
+    DispatchEx *date;
+    HRESULT hres;
+
+    TRACE("\n");
+
+    switch(flags) {
+    case DISPATCH_CONSTRUCT:
+        switch(arg_cnt(dp)) {
+        /* ECMA-262 3rd Edition    15.9.3.3 */
+        case 0: {
+            FILETIME time;
+
+            GetSystemTimeAsFileTime(&time);
+
+            hres = create_date(dispex->ctx, TRUE,
+                   floor((DOUBLE)(time.dwLowDateTime/1e6) + (DOUBLE)time.dwHighDateTime*((DOUBLE)UINT_MAX+1.0)/1.e6),
+                   &date);
+            if(FAILED(hres))
+                return hres;
+            break;
+        }
+
+        /* ECMA-262 3rd Edition    15.9.3.2 */
+        case 1: {
+            VARIANT prim, num;
+
+            hres = to_primitive(dispex->ctx, get_arg(dp,0), ei, &prim);
+            if(FAILED(hres))
+                return hres;
+
+            if(V_VT(&prim) == VT_BSTR) {
+                FIXME("VT_BSTR not supported\n");
+                return E_NOTIMPL;
+            }
+
+            hres = to_number(dispex->ctx, &prim, ei, &num);
+            VariantClear(&prim);
+            if(FAILED(hres))
+                return hres;
+
+            hres = create_date(dispex->ctx, TRUE, time_clip(num_val(&num)), &date);
+            if(FAILED(hres))
+                return hres;
+            break;
+        }
+
+        default:
+            FIXME("unimplemented argcnt %d\n", arg_cnt(dp));
+            return E_NOTIMPL;
+        }
+
+        V_VT(retv) = VT_DISPATCH;
+        V_DISPATCH(retv) = (IDispatch*)_IDispatchEx_(date);
+        return S_OK;
+
+    default:
+        FIXME("unimplemented flags %x\n", flags);
+        return E_NOTIMPL;
+    }
+
+    return S_OK;
+}
+
+HRESULT create_date_constr(script_ctx_t *ctx, DispatchEx **ret)
+{
+    DispatchEx *date;
+    HRESULT hres;
+
+    hres = create_date(ctx, FALSE, 0.0, &date);
+    if(FAILED(hres))
+        return hres;
+
+    hres = create_builtin_function(ctx, DateConstr_value, PROPF_CONSTR, date, ret);
+
+    jsdisp_release(date);
+    return hres;
+}
index 1c643f6..86410af 100644 (file)
@@ -517,8 +517,6 @@ static HRESULT WINAPI DispatchEx_Invoke(IDispatchEx *iface, DISPID dispIdMember,
 static HRESULT WINAPI DispatchEx_GetDispID(IDispatchEx *iface, BSTR bstrName, DWORD grfdex, DISPID *pid)
 {
     DispatchEx *This = DISPATCHEX_THIS(iface);
-    dispex_prop_t *prop;
-    HRESULT hres;
 
     TRACE("(%p)->(%s %x %p)\n", This, debugstr_w(bstrName), grfdex, pid);
 
@@ -527,16 +525,7 @@ static HRESULT WINAPI DispatchEx_GetDispID(IDispatchEx *iface, BSTR bstrName, DW
         return E_NOTIMPL;
     }
 
-    hres = find_prop_name_prot(This, bstrName, (grfdex&fdexNameEnsure) != 0, &prop);
-    if(FAILED(hres))
-        return hres;
-    if(prop) {
-        *pid = prop_to_id(This, prop);
-        return S_OK;
-    }
-
-    TRACE("not found %s\n", debugstr_w(bstrName));
-    return DISP_E_UNKNOWNNAME;
+    return jsdisp_get_id(This, bstrName, grfdex, pid);
 }
 
 static HRESULT WINAPI DispatchEx_InvokeEx(IDispatchEx *iface, DISPID id, LCID lcid, WORD wFlags, DISPPARAMS *pdp,
@@ -582,6 +571,15 @@ static HRESULT WINAPI DispatchEx_InvokeEx(IDispatchEx *iface, DISPID id, LCID lc
     return hres;
 }
 
+static HRESULT delete_prop(dispex_prop_t *prop)
+{
+    heap_free(prop->name);
+    prop->name = NULL;
+    prop->type = PROP_DELETED;
+
+    return S_OK;
+}
+
 static HRESULT WINAPI DispatchEx_DeleteMemberByName(IDispatchEx *iface, BSTR bstrName, DWORD grfdex)
 {
     DispatchEx *This = DISPATCHEX_THIS(iface);
@@ -601,17 +599,23 @@ static HRESULT WINAPI DispatchEx_DeleteMemberByName(IDispatchEx *iface, BSTR bst
         return S_OK;
     }
 
-    heap_free(prop->name);
-    prop->name = NULL;
-    prop->type = PROP_DELETED;
-    return S_OK;
+    return delete_prop(prop);
 }
 
 static HRESULT WINAPI DispatchEx_DeleteMemberByDispID(IDispatchEx *iface, DISPID id)
 {
     DispatchEx *This = DISPATCHEX_THIS(iface);
-    FIXME("(%p)->(%x)\n", This, id);
-    return E_NOTIMPL;
+    dispex_prop_t *prop;
+
+    TRACE("(%p)->(%x)\n", This, id);
+
+    prop = get_prop(This, id);
+    if(!prop) {
+        WARN("invalid id\n");
+        return DISP_E_MEMBERNOTFOUND;
+    }
+
+    return delete_prop(prop);
 }
 
 static HRESULT WINAPI DispatchEx_GetMemberProperties(IDispatchEx *iface, DISPID id, DWORD grfdexFetch, DWORD *pgrfdex)
@@ -698,23 +702,6 @@ static IDispatchExVtbl DispatchExVtbl = {
     DispatchEx_GetNameSpaceParent
 };
 
-HRESULT jsdisp_set_prototype(DispatchEx *dispex, DispatchEx *prototype)
-{
-    VARIANT *var;
-
-    if(!dispex->props[1].name)
-        return E_OUTOFMEMORY;
-
-    dispex->props[1].type = PROP_VARIANT;
-    dispex->props[1].flags = 0;
-
-    var = &dispex->props[1].u.var;
-    V_VT(var) = VT_DISPATCH;
-    V_DISPATCH(var) = (IDispatch*)_IDispatchEx_(prototype);
-
-    return S_OK;
-}
-
 HRESULT init_dispex(DispatchEx *dispex, script_ctx_t *ctx, const builtin_info_t *builtin_info, DispatchEx *prototype)
 {
     TRACE("%p (%p)\n", dispex, prototype);
@@ -817,13 +804,31 @@ DispatchEx *iface_to_jsdisp(IUnknown *iface)
     return ret;
 }
 
+HRESULT jsdisp_get_id(DispatchEx *jsdisp, const WCHAR *name, DWORD flags, DISPID *id)
+{
+    dispex_prop_t *prop;
+    HRESULT hres;
+
+    hres = find_prop_name_prot(jsdisp, name, (flags&fdexNameEnsure) != 0, &prop);
+    if(FAILED(hres))
+        return hres;
+
+    if(prop) {
+        *id = prop_to_id(jsdisp, prop);
+        return S_OK;
+    }
+
+    TRACE("not found %s\n", debugstr_w(name));
+    return DISP_E_UNKNOWNNAME;
+}
+
 HRESULT jsdisp_call_value(DispatchEx *disp, LCID lcid, WORD flags, DISPPARAMS *dp, VARIANT *retv,
         jsexcept_t *ei, IServiceProvider *caller)
 {
     return disp->builtin_info->value_prop.invoke(disp, lcid, flags, dp, retv, ei, caller);
 }
 
-HRESULT jsdisp_call(DispatchEx *disp, DISPID id, LCID lcid, WORD flags, DISPPARAMS *dp, VARIANT *retv,
+static HRESULT jsdisp_call(DispatchEx *disp, DISPID id, LCID lcid, WORD flags, DISPPARAMS *dp, VARIANT *retv,
         jsexcept_t *ei, IServiceProvider *caller)
 {
     dispex_prop_t *prop;
@@ -861,6 +866,11 @@ HRESULT disp_call(IDispatch *disp, DISPID id, LCID lcid, WORD flags, DISPPARAMS
     if(FAILED(hres)) {
         UINT err = 0;
 
+        if(flags == DISPATCH_CONSTRUCT) {
+            WARN("IDispatch cannot be constructor\n");
+            return DISP_E_MEMBERNOTFOUND;
+        }
+
         TRACE("using IDispatch\n");
         return IDispatch_Invoke(disp, id, &IID_NULL, lcid, flags, dp, retv, &ei->ei, &err);
     }
@@ -931,6 +941,48 @@ HRESULT disp_propput(IDispatch *disp, DISPID id, LCID lcid, VARIANT *val, jsexce
     return hres;
 }
 
+HRESULT jsdisp_propget_name(DispatchEx *obj, const WCHAR *name, LCID lcid, VARIANT *var,
+        jsexcept_t *ei, IServiceProvider *caller)
+{
+    DISPPARAMS dp = {NULL, NULL, 0, 0};
+    dispex_prop_t *prop;
+    HRESULT hres;
+
+    hres = find_prop_name_prot(obj, name, FALSE, &prop);
+    if(FAILED(hres))
+        return hres;
+
+    V_VT(var) = VT_EMPTY;
+    if(!prop)
+        return S_OK;
+
+    return prop_get(obj, prop, lcid, &dp, var, ei, caller);
+}
+
+HRESULT jsdisp_propget_idx(DispatchEx *obj, DWORD idx, LCID lcid, VARIANT *var, jsexcept_t *ei, IServiceProvider *caller)
+{
+    WCHAR buf[12];
+
+    static const WCHAR formatW[] = {'%','d',0};
+
+    sprintfW(buf, formatW, idx);
+    return jsdisp_propget_name(obj, buf, lcid, var, ei, caller);
+}
+
+HRESULT jsdisp_propget(DispatchEx *jsdisp, DISPID id, LCID lcid, VARIANT *val, jsexcept_t *ei,
+        IServiceProvider *caller)
+{
+    DISPPARAMS dp  = {NULL,NULL,0,0};
+    dispex_prop_t *prop;
+
+    prop = get_prop(jsdisp, id);
+    if(!prop)
+        return DISP_E_MEMBERNOTFOUND;
+
+    V_VT(val) = VT_EMPTY;
+    return prop_get(jsdisp, prop, lcid, &dp, val, ei, caller);
+}
+
 HRESULT disp_propget(IDispatch *disp, DISPID id, LCID lcid, VARIANT *val, jsexcept_t *ei, IServiceProvider *caller)
 {
     DISPPARAMS dp  = {NULL,NULL,0,0};
@@ -940,14 +992,7 @@ HRESULT disp_propget(IDispatch *disp, DISPID id, LCID lcid, VARIANT *val, jsexce
 
     jsdisp = iface_to_jsdisp((IUnknown*)disp);
     if(jsdisp) {
-        dispex_prop_t *prop;
-
-        prop = get_prop(jsdisp, id);
-        if(prop)
-            hres = prop_get(jsdisp, prop, lcid, &dp, val, ei, caller);
-        else
-            hres = DISP_E_MEMBERNOTFOUND;
-
+        hres = jsdisp_propget(jsdisp, id, lcid, val, ei, caller);
         IDispatchEx_Release(_IDispatchEx_(jsdisp));
         return hres;
     }
@@ -956,8 +1001,8 @@ HRESULT disp_propget(IDispatch *disp, DISPID id, LCID lcid, VARIANT *val, jsexce
     if(FAILED(hres)) {
         ULONG err = 0;
 
-        TRACE("uding IDispatch\n");
-        return IDispatchEx_Invoke(dispex, id, &IID_NULL, lcid, INVOKE_PROPERTYGET, &dp, val, &ei->ei, &err);
+        TRACE("using IDispatch\n");
+        return IDispatch_Invoke(disp, id, &IID_NULL, lcid, INVOKE_PROPERTYGET, &dp, val, &ei->ei, &err);
     }
 
     hres = IDispatchEx_InvokeEx(dispex, id, lcid, INVOKE_PROPERTYGET, &dp, val, &ei->ei, caller);
index f0f5062..05c6225 100644 (file)
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  */
 
+#include "config.h"
+#include "wine/port.h"
+
+#include <math.h>
+
 #include "jscript.h"
 #include "engine.h"
 
@@ -203,13 +208,6 @@ void exec_release(exec_ctx_t *ctx)
     heap_free(ctx);
 }
 
-static HRESULT dispex_get_id(IDispatchEx *dispex, BSTR name, DWORD flags, DISPID *id)
-{
-    *id = 0;
-
-    return IDispatchEx_GetDispID(dispex, name, flags|fdexNameCaseSensitive, id);
-}
-
 static HRESULT disp_get_id(IDispatch *disp, BSTR name, DWORD flags, DISPID *id)
 {
     IDispatchEx *dispex;
@@ -223,7 +221,8 @@ static HRESULT disp_get_id(IDispatch *disp, BSTR name, DWORD flags, DISPID *id)
         return IDispatch_GetIDsOfNames(disp, &IID_NULL, &name, 1, 0, id);
     }
 
-    hres = dispex_get_id(dispex, name, flags, id);
+    *id = 0;
+    hres = IDispatchEx_GetDispID(dispex, name, flags|fdexNameCaseSensitive, id);
     IDispatchEx_Release(dispex);
     return hres;
 }
@@ -278,18 +277,8 @@ static HRESULT disp_cmp(IDispatch *disp1, IDispatch *disp2, BOOL *ret)
     return S_OK;
 }
 
-static inline BOOL is_num_vt(enum VARENUM vt)
-{
-    return vt == VT_I4 || vt == VT_R8;
-}
-
-static inline DOUBLE num_val(const VARIANT *v)
-{
-    return V_VT(v) == VT_I4 ? V_I4(v) : V_R8(v);
-}
-
 /* ECMA-262 3rd Edition    11.9.6 */
-HRESULT equal2_values(VARIANT *lval, VARIANT *rval, BOOL *ret)
+static HRESULT equal2_values(VARIANT *lval, VARIANT *rval, BOOL *ret)
 {
     TRACE("\n");
 
@@ -367,6 +356,7 @@ HRESULT exec_source(exec_ctx_t *ctx, parser_ctx_t *parser, source_elements_t *so
     script_ctx_t *script = parser->script;
     function_declaration_t *func;
     parser_ctx_t *prev_parser;
+    var_list_t *var;
     VARIANT val, tmp;
     statement_t *stat;
     exec_ctx_t *prev_ctx;
@@ -377,14 +367,23 @@ HRESULT exec_source(exec_ctx_t *ctx, parser_ctx_t *parser, source_elements_t *so
         DispatchEx *func_obj;
         VARIANT var;
 
-        hres = create_source_function(parser, func->parameter_list, func->source_elements, ctx->scope_chain, &func_obj);
+        hres = create_source_function(parser, func->expr->parameter_list, func->expr->source_elements,
+                ctx->scope_chain, func->expr->src_str, func->expr->src_len, &func_obj);
         if(FAILED(hres))
             return hres;
 
         V_VT(&var) = VT_DISPATCH;
         V_DISPATCH(&var) = (IDispatch*)_IDispatchEx_(func_obj);
-        hres = jsdisp_propput_name(ctx->var_disp, func->identifier, script->lcid, &var, ei, NULL);
-        IDispatchEx_Release(_IDispatchEx_(func_obj));
+        hres = jsdisp_propput_name(ctx->var_disp, func->expr->identifier, script->lcid, &var, ei, NULL);
+        jsdisp_release(func_obj);
+        if(FAILED(hres))
+            return hres;
+    }
+
+    for(var = source->variables; var; var = var->next) {
+        DISPID id = 0;
+
+        hres = jsdisp_get_id(ctx->var_disp, var->identifier, fdexNameEnsure, &id);
         if(FAILED(hres))
             return hres;
     }
@@ -442,7 +441,7 @@ static HRESULT identifier_eval(exec_ctx_t *ctx, BSTR identifier, DWORD flags, ex
     TRACE("%s\n", debugstr_w(identifier));
 
     for(scope = ctx->scope_chain; scope; scope = scope->next) {
-        hres = dispex_get_id(_IDispatchEx_(scope->obj), identifier, 0, &id);
+        hres = jsdisp_get_id(scope->obj, identifier, 0, &id);
         if(SUCCEEDED(hres))
             break;
     }
@@ -452,31 +451,64 @@ static HRESULT identifier_eval(exec_ctx_t *ctx, BSTR identifier, DWORD flags, ex
         return S_OK;
     }
 
-    hres = dispex_get_id(_IDispatchEx_(ctx->parser->script->global), identifier, 0, &id);
+    hres = jsdisp_get_id(ctx->parser->script->global, identifier, 0, &id);
     if(SUCCEEDED(hres)) {
         exprval_set_idref(ret, (IDispatch*)_IDispatchEx_(ctx->parser->script->global), id);
         return S_OK;
     }
 
     for(item = ctx->parser->script->named_items; item; item = item->next) {
-        hres = disp_get_id(item->disp, identifier, 0, &id);
-        if(SUCCEEDED(hres))
-            break;
+        if((item->flags & SCRIPTITEM_ISVISIBLE) && !strcmpW(item->name, identifier)) {
+            if(!item->disp) {
+                IUnknown *unk;
+
+                if(!ctx->parser->script->site)
+                    break;
+
+                hres = IActiveScriptSite_GetItemInfo(ctx->parser->script->site, identifier,
+                                                     SCRIPTINFO_IUNKNOWN, &unk, NULL);
+                if(FAILED(hres)) {
+                    WARN("GetItemInfo failed: %08x\n", hres);
+                    break;
+                }
+
+                hres = IUnknown_QueryInterface(unk, &IID_IDispatch, (void**)&item->disp);
+                IUnknown_Release(unk);
+                if(FAILED(hres)) {
+                    WARN("object does not implement IDispatch\n");
+                    break;
+                }
+            }
+
+            ret->type = EXPRVAL_VARIANT;
+            V_VT(&ret->u.var) = VT_DISPATCH;
+            V_DISPATCH(&ret->u.var) = item->disp;
+            IDispatch_AddRef(item->disp);
+            return S_OK;
+        }
+    }
+
+    for(item = ctx->parser->script->named_items; item; item = item->next) {
+        if(item->flags & SCRIPTITEM_GLOBALMEMBERS) {
+            hres = disp_get_id(item->disp, identifier, 0, &id);
+            if(SUCCEEDED(hres))
+                break;
+        }
     }
 
     if(item) {
-        exprval_set_idref(ret, (IDispatch*)item->disp, id);
+        exprval_set_idref(ret, item->disp, id);
         return S_OK;
     }
 
-    hres = dispex_get_id(_IDispatchEx_(ctx->parser->script->script_disp), identifier, 0, &id);
+    hres = jsdisp_get_id(ctx->parser->script->script_disp, identifier, 0, &id);
     if(SUCCEEDED(hres)) {
         exprval_set_idref(ret, (IDispatch*)_IDispatchEx_(ctx->parser->script->script_disp), id);
         return S_OK;
     }
 
     if(flags & EXPR_NEWREF) {
-        hres = dispex_get_id(_IDispatchEx_(ctx->var_disp), identifier, fdexNameEnsure, &id);
+        hres = jsdisp_get_id(ctx->var_disp, identifier, fdexNameEnsure, &id);
         if(FAILED(hres))
             return hres;
 
@@ -523,25 +555,23 @@ HRESULT block_statement_eval(exec_ctx_t *ctx, statement_t *_stat, return_type_t
 static HRESULT variable_list_eval(exec_ctx_t *ctx, variable_declaration_t *var_list, jsexcept_t *ei)
 {
     variable_declaration_t *iter;
-    HRESULT hres = E_FAIL;
+    HRESULT hres = S_OK;
 
     for(iter = var_list; iter; iter = iter->next) {
+        exprval_t exprval;
         VARIANT val;
 
-        if(iter->expr) {
-            exprval_t exprval;
+        if(!iter->expr)
+            continue;
 
-            hres = expr_eval(ctx, iter->expr, 0, ei, &exprval);
-            if(FAILED(hres))
-                break;
+        hres = expr_eval(ctx, iter->expr, 0, ei, &exprval);
+        if(FAILED(hres))
+            break;
 
-            hres = exprval_to_value(ctx->parser->script, &exprval, ei, &val);
-            exprval_release(&exprval);
-            if(FAILED(hres))
-                break;
-        }else {
-            V_VT(&val) = VT_EMPTY;
-        }
+        hres = exprval_to_value(ctx->parser->script, &exprval, ei, &val);
+        exprval_release(&exprval);
+        if(FAILED(hres))
+            break;
 
         hres = jsdisp_propput_name(ctx->var_disp, iter->identifier, ctx->parser->script->lcid, &val, ei, NULL/*FIXME*/);
         VariantClear(&val);
@@ -793,9 +823,10 @@ HRESULT forin_statement_eval(exec_ctx_t *ctx, statement_t *_stat, return_type_t
         return hres;
 
     if(V_VT(&val) != VT_DISPATCH) {
-        FIXME("in vt %d\n", V_VT(&val));
+        TRACE("in vt %d\n", V_VT(&val));
         VariantClear(&val);
-        return E_NOTIMPL;
+        V_VT(ret) = VT_EMPTY;
+        return S_OK;
     }
 
     hres = IDispatch_QueryInterface(V_DISPATCH(&val), &IID_IDispatchEx, (void**)&in_obj);
@@ -959,7 +990,8 @@ HRESULT with_statement_eval(exec_ctx_t *ctx, statement_t *_stat, return_type_t *
 
     hres = scope_push(ctx->scope_chain, obj, &ctx->scope_chain);
     jsdisp_release(obj);
-    if(FAILED(hres));
+    if(FAILED(hres))
+        return hres;
 
     hres = stat_eval(ctx, stat->statement, rt, ret);
 
@@ -1245,25 +1277,25 @@ static HRESULT assign_oper_eval(exec_ctx_t *ctx, expression_t *lexpr, expression
 HRESULT function_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
 {
     function_expression_t *expr = (function_expression_t*)_expr;
-    DispatchEx *dispex;
     VARIANT var;
     HRESULT hres;
 
     TRACE("\n");
 
-    hres = create_source_function(ctx->parser, expr->parameter_list, expr->source_elements, ctx->scope_chain, &dispex);
-    if(FAILED(hres))
-        return hres;
-
-    V_VT(&var) = VT_DISPATCH;
-    V_DISPATCH(&var) = (IDispatch*)_IDispatchEx_(dispex);
-
     if(expr->identifier) {
-        hres = jsdisp_propput_name(ctx->var_disp, expr->identifier, ctx->parser->script->lcid, &var, ei, NULL/*FIXME*/);
-        if(FAILED(hres)) {
-            jsdisp_release(dispex);
+        hres = jsdisp_propget_name(ctx->var_disp, expr->identifier, ctx->parser->script->lcid, &var, ei, NULL/*FIXME*/);
+        if(FAILED(hres))
             return hres;
-        }
+    }else {
+        DispatchEx *dispex;
+
+        hres = create_source_function(ctx->parser, expr->parameter_list, expr->source_elements, ctx->scope_chain,
+                expr->src_str, expr->src_len, &dispex);
+        if(FAILED(hres))
+            return hres;
+
+        V_VT(&var) = VT_DISPATCH;
+        V_DISPATCH(&var) = (IDispatch*)_IDispatchEx_(dispex);
     }
 
     ret->type = EXPRVAL_VARIANT;
@@ -1490,7 +1522,7 @@ HRESULT new_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flags, j
 HRESULT call_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
 {
     call_expression_t *expr = (call_expression_t*)_expr;
-    VARIANT func, var;
+    VARIANT var;
     exprval_t exprval;
     DISPPARAMS dp;
     HRESULT hres;
@@ -1511,7 +1543,7 @@ HRESULT call_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flags,
                 V_VT(&var) = VT_EMPTY;
             break;
         default:
-            FIXME("unimplemented type %d\n", V_VT(&func));
+            FIXME("unimplemented type %d\n", exprval.type);
             hres = E_NOTIMPL;
         }
 
@@ -1936,9 +1968,9 @@ static HRESULT add_eval(exec_ctx_t *ctx, VARIANT *lval, VARIANT *rval, jsexcept_
             memcpy(V_BSTR(retv)+len1, rstr, (len2+1)*sizeof(WCHAR));
         }
 
-        if(lstr && V_VT(&l) != VT_BSTR)
+        if(V_VT(&l) != VT_BSTR)
             SysFreeString(lstr);
-        if(rstr && V_VT(&r) != VT_BSTR)
+        if(V_VT(&r) != VT_BSTR)
             SysFreeString(rstr);
     }else {
         VARIANT nl, nr;
@@ -2051,10 +2083,31 @@ HRESULT div_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flags, j
 }
 
 /* ECMA-262 3rd Edition    11.5.3 */
-HRESULT mod_expression_eval(exec_ctx_t *ctx, expression_t *expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
+static HRESULT mod_eval(exec_ctx_t *ctx, VARIANT *lval, VARIANT *rval, jsexcept_t *ei, VARIANT *retv)
 {
-    FIXME("\n");
-    return E_NOTIMPL;
+    VARIANT lnum, rnum;
+    HRESULT hres;
+
+    hres = to_number(ctx->parser->script, lval, ei, &lnum);
+    if(FAILED(hres))
+        return hres;
+
+    hres = to_number(ctx->parser->script, rval, ei, &rnum);
+    if(FAILED(hres))
+        return hres;
+
+    num_set_val(retv, fmod(num_val(&lnum), num_val(&rnum)));
+    return S_OK;
+}
+
+/* ECMA-262 3rd Edition    11.5.3 */
+HRESULT mod_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
+{
+    binary_expression_t *expr = (binary_expression_t*)_expr;
+
+    TRACE("\n");
+
+    return binary_expr_eval(ctx, expr, mod_eval, ei, ret);
 }
 
 /* ECMA-262 3rd Edition    11.4.2 */
@@ -2072,6 +2125,17 @@ HRESULT delete_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flags
         return hres;
 
     switch(exprval.type) {
+    case EXPRVAL_IDREF: {
+        IDispatchEx *dispex;
+
+        hres = IDispatch_QueryInterface(exprval.u.nameref.disp, &IID_IDispatchEx, (void**)&dispex);
+        if(SUCCEEDED(hres)) {
+            hres = IDispatchEx_DeleteMemberByDispID(dispex, exprval.u.idref.id);
+            b = VARIANT_TRUE;
+            IDispatchEx_Release(dispex);
+        }
+        break;
+    }
     case EXPRVAL_NAMEREF: {
         IDispatchEx *dispex;
 
@@ -2179,12 +2243,11 @@ HRESULT typeof_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flags
     }
     default:
         FIXME("unhandled vt %d\n", V_VT(&val));
-        hres = E_NOTIMPL;
+        VariantClear(&val);
+        return E_NOTIMPL;
     }
 
     VariantClear(&val);
-    if(FAILED(hres))
-        return hres;
 
     ret->type = EXPRVAL_VARIANT;
     V_VT(&ret->u.var) = VT_BSTR;
@@ -2570,7 +2633,7 @@ HRESULT not_equal2_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD f
 }
 
 /* ECMA-262 3rd Edition    11.8.5 */
-static HRESULT less_eval(exec_ctx_t *ctx, VARIANT *lval, VARIANT *rval, jsexcept_t *ei, BOOL *ret)
+static HRESULT less_eval(exec_ctx_t *ctx, VARIANT *lval, VARIANT *rval, BOOL greater, jsexcept_t *ei, BOOL *ret)
 {
     VARIANT l, r, ln, rn;
     HRESULT hres;
@@ -2586,7 +2649,7 @@ static HRESULT less_eval(exec_ctx_t *ctx, VARIANT *lval, VARIANT *rval, jsexcept
     }
 
     if(V_VT(&l) == VT_BSTR && V_VT(&r) == VT_BSTR) {
-        *ret = strcmpW(V_BSTR(&l), V_BSTR(&r)) < 0;
+        *ret = (strcmpW(V_BSTR(&l), V_BSTR(&r)) < 0) ^ greater;
         SysFreeString(V_BSTR(&l));
         SysFreeString(V_BSTR(&r));
         return S_OK;
@@ -2600,10 +2663,14 @@ static HRESULT less_eval(exec_ctx_t *ctx, VARIANT *lval, VARIANT *rval, jsexcept
     if(FAILED(hres))
         return hres;
 
-    if(V_VT(&ln) == VT_I4 && V_VT(&rn) == VT_I4)
-        *ret = V_I4(&ln) < V_I4(&rn);
-    else
-        *ret = num_val(&ln) < num_val(&rn);
+    if(V_VT(&ln) == VT_I4 && V_VT(&rn) == VT_I4) {
+        *ret = (V_I4(&ln) < V_I4(&rn)) ^ greater;
+    }else  {
+        DOUBLE ld = num_val(&ln);
+        DOUBLE rd = num_val(&rn);
+
+        *ret = !isnan(ld) && !isnan(rd) && ((ld < rd) ^ greater);
+    }
 
     return S_OK;
 }
@@ -2622,7 +2689,7 @@ HRESULT less_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flags,
     if(FAILED(hres))
         return hres;
 
-    hres = less_eval(ctx, &lval, &rval, ei, &b);
+    hres = less_eval(ctx, &lval, &rval, FALSE, ei, &b);
     VariantClear(&lval);
     VariantClear(&rval);
     if(FAILED(hres))
@@ -2645,13 +2712,13 @@ HRESULT lesseq_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flags
     if(FAILED(hres))
         return hres;
 
-    hres = less_eval(ctx, &rval, &lval, ei, &b);
+    hres = less_eval(ctx, &rval, &lval, TRUE, ei, &b);
     VariantClear(&lval);
     VariantClear(&rval);
     if(FAILED(hres))
         return hres;
 
-    return return_bool(ret, !b);
+    return return_bool(ret, b);
 }
 
 /* ECMA-262 3rd Edition    11.8.2 */
@@ -2668,7 +2735,7 @@ HRESULT greater_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flag
     if(FAILED(hres))
         return hres;
 
-    hres = less_eval(ctx, &rval, &lval, ei, &b);
+    hres = less_eval(ctx, &rval, &lval, FALSE, ei, &b);
     VariantClear(&lval);
     VariantClear(&rval);
     if(FAILED(hres))
@@ -2691,13 +2758,13 @@ HRESULT greatereq_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD fl
     if(FAILED(hres))
         return hres;
 
-    hres = less_eval(ctx, &lval, &rval, ei, &b);
+    hres = less_eval(ctx, &lval, &rval, TRUE, ei, &b);
     VariantClear(&lval);
     VariantClear(&rval);
     if(FAILED(hres))
         return hres;
 
-    return return_bool(ret, !b);
+    return return_bool(ret, b);
 }
 
 /* ECMA-262 3rd Edition    11.4.8 */
@@ -2865,10 +2932,8 @@ HRESULT assign_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flags
         hres = put_value(ctx->parser->script, &exprval, &rval, ei);
 
     exprval_release(&exprval);
-    if(FAILED(hres)) {
-        VariantClear(&rval);
+    if(FAILED(hres))
         return hres;
-    }
 
     ret->type = EXPRVAL_VARIANT;
     ret->u.var = rval;
@@ -2946,10 +3011,13 @@ HRESULT assign_div_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD f
 }
 
 /* ECMA-262 3rd Edition    11.13.2 */
-HRESULT assign_mod_expression_eval(exec_ctx_t *ctx, expression_t *expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
+HRESULT assign_mod_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
 {
-    FIXME("\n");
-    return E_NOTIMPL;
+    binary_expression_t *expr = (binary_expression_t*)_expr;
+
+    TRACE("\n");
+
+    return assign_oper_eval(ctx, expr->expression1, expr->expression2, mod_eval, ei, ret);
 }
 
 /* ECMA-262 3rd Edition    11.13.2 */
index 3f7fda8..e02b717 100644 (file)
  */
 
 typedef struct _source_elements_t source_elements_t;
+typedef struct _function_expression_t function_expression_t;
 
 typedef struct _obj_literal_t {
     DispatchEx *obj;
     struct _obj_literal_t *next;
 } obj_literal_t;
 
+typedef struct _function_declaration_t {
+    function_expression_t *expr;
+
+    struct _function_declaration_t *next;
+} function_declaration_t;
+
+typedef struct _var_list_t {
+    const WCHAR *identifier;
+
+    struct _var_list_t *next;
+} var_list_t;
+
+typedef struct _func_stack {
+    function_declaration_t *func_head;
+    function_declaration_t *func_tail;
+    var_list_t *var_head;
+    var_list_t *var_tail;
+
+    struct _func_stack *next;
+} func_stack_t;
+
 typedef struct _parser_ctx_t {
     LONG ref;
 
@@ -38,6 +60,7 @@ typedef struct _parser_ctx_t {
     jsheap_t heap;
 
     obj_literal_t *obj_literals;
+    func_stack_t *func_stack;
 
     struct _parser_ctx_t *next;
 } parser_ctx_t;
@@ -98,7 +121,8 @@ typedef struct _statement_t statement_t;
 typedef struct _expression_t expression_t;
 typedef struct _parameter_t parameter_t;
 
-HRESULT create_source_function(parser_ctx_t*,parameter_t*,source_elements_t*,scope_chain_t*,DispatchEx**);
+HRESULT create_source_function(parser_ctx_t*,parameter_t*,source_elements_t*,scope_chain_t*,
+        const WCHAR*,DWORD,DispatchEx**);
 
 typedef struct {
     VARTYPE vt;
@@ -273,27 +297,21 @@ struct _parameter_t {
     struct _parameter_t *next;
 };
 
-typedef struct _function_declaration_t {
-    const WCHAR *identifier;
-    parameter_t *parameter_list;
-    source_elements_t *source_elements;
-
-    struct _function_declaration_t *next;
-} function_declaration_t;
-
 struct _source_elements_t {
     statement_t *statement;
     statement_t *statement_tail;
     function_declaration_t *functions;
-    function_declaration_t *functions_tail;
+    var_list_t *variables;
 };
 
-typedef struct {
+struct _function_expression_t {
     expression_t expr;
     const WCHAR *identifier;
     parameter_t *parameter_list;
     source_elements_t *source_elements;
-} function_expression_t;
+    const WCHAR *src_str;
+    DWORD src_len;
+};
 
 typedef struct {
     expression_t expr;
index 7d39ad0..314d585 100644 (file)
@@ -31,6 +31,8 @@ typedef struct {
     parameter_t *parameters;
     scope_chain_t *scope_chain;
     parser_ctx_t *parser;
+    const WCHAR *src_str;
+    DWORD src_len;
     DWORD length;
 } FunctionInstance;
 
@@ -189,7 +191,6 @@ static HRESULT invoke_constructor(FunctionInstance *function, LCID lcid, DISPPAR
         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
 {
     DispatchEx *this_obj;
-    VARIANT var;
     HRESULT hres;
 
     hres = create_object(function->dispex.ctx, &function->dispex, &this_obj);
@@ -201,7 +202,6 @@ static HRESULT invoke_constructor(FunctionInstance *function, LCID lcid, DISPPAR
     if(FAILED(hres))
         return hres;
 
-    VariantClear(&var);
     V_VT(retv) = VT_DISPATCH;
     V_DISPATCH(retv) = (IDispatch*)_IDispatchEx_(this_obj);
     return S_OK;
@@ -226,6 +226,23 @@ static HRESULT invoke_value_proc(FunctionInstance *function, LCID lcid, WORD fla
     return hres;
 }
 
+static HRESULT function_to_string(FunctionInstance *function, BSTR *ret)
+{
+    BSTR str;
+
+    if(function->value_proc) {
+        FIXME("Builtin functions not implemented\n");
+        return E_NOTIMPL;
+    }
+
+    str = SysAllocStringLen(function->src_str, function->src_len);
+    if(!str)
+        return E_OUTOFMEMORY;
+
+    *ret = str;
+    return S_OK;
+}
+
 static HRESULT Function_length(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
         VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
 {
@@ -249,8 +266,30 @@ static HRESULT Function_length(DispatchEx *dispex, LCID lcid, WORD flags, DISPPA
 static HRESULT Function_toString(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
         VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
 {
-    FIXME("\n");
-    return E_NOTIMPL;
+    FunctionInstance *function;
+    BSTR str;
+    HRESULT hres;
+
+    TRACE("\n");
+
+    if(!is_class(dispex, JSCLASS_FUNCTION)) {
+        FIXME("throw TypeError\n");
+        return E_FAIL;
+    }
+
+    function = (FunctionInstance*)dispex;
+
+    hres = function_to_string(function, &str);
+    if(FAILED(hres))
+        return hres;
+
+    if(retv) {
+        V_VT(retv) = VT_BSTR;
+        V_BSTR(retv) = str;
+    }else {
+        SysFreeString(str);
+    }
+    return S_OK;
 }
 
 static HRESULT Function_toLocaleString(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
@@ -323,6 +362,19 @@ static HRESULT Function_value(DispatchEx *dispex, LCID lcid, WORD flags, DISPPAR
 
         return invoke_function(function, lcid, dp, retv, ei, caller);
 
+    case DISPATCH_PROPERTYGET: {
+        HRESULT hres;
+        BSTR str;
+
+        hres = function_to_string(function, &str);
+        if(FAILED(hres))
+            return hres;
+
+        V_VT(retv) = VT_BSTR;
+        V_BSTR(retv) = str;
+        break;
+    }
+
     case DISPATCH_CONSTRUCT:
         if(function->value_proc)
             return invoke_value_proc(function, lcid, flags, dp, retv, ei, caller);
@@ -438,7 +490,7 @@ HRESULT create_builtin_function(script_ctx_t *ctx, builtin_invoke_t value_proc,
 }
 
 HRESULT create_source_function(parser_ctx_t *ctx, parameter_t *parameters, source_elements_t *source,
-        scope_chain_t *scope_chain, DispatchEx **ret)
+        scope_chain_t *scope_chain, const WCHAR *src_str, DWORD src_len, DispatchEx **ret)
 {
     FunctionInstance *function;
     DispatchEx *prototype;
@@ -470,6 +522,9 @@ HRESULT create_source_function(parser_ctx_t *ctx, parameter_t *parameters, sourc
         length++;
     function->length = length;
 
+    function->src_str = src_str;
+    function->src_len = src_len;
+
     *ret = &function->dispex;
     return S_OK;
 }
index 4404bff..d98b7b4 100644 (file)
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  */
 
+#include "config.h"
+#include "wine/port.h"
+
+#include <math.h>
+
 #include "jscript.h"
 #include "engine.h"
 
@@ -43,7 +48,7 @@ static const WCHAR isFiniteW[] = {'i','s','F','i','n','i','t','e',0};
 static const WCHAR parseIntW[] = {'p','a','r','s','e','I','n','t',0};
 static const WCHAR parseFloatW[] = {'p','a','r','s','e','F','l','o','a','t',0};
 static const WCHAR unescapeW[] = {'u','n','e','s','c','a','p','e',0};
-static const WCHAR GetObjectW[] = {'G','e','t','O','b','j','e','c','t',0};
+static const WCHAR _GetObjectW[] = {'G','e','t','O','b','j','e','c','t',0};
 static const WCHAR ScriptEngineW[] = {'S','c','r','i','p','t','E','n','g','i','n','e',0};
 static const WCHAR ScriptEngineMajorVersionW[] =
     {'S','c','r','i','p','t','E','n','g','i','n','e','M','a','j','o','r','V','e','r','s','i','o','n',0};
@@ -53,6 +58,40 @@ static const WCHAR ScriptEngineBuildVersionW[] =
     {'S','c','r','i','p','t','E','n','g','i','n','e','B','u','i','l','d','V','e','r','s','i','o','n',0};
 static const WCHAR CollectGarbageW[] = {'C','o','l','l','e','c','t','G','a','r','b','a','g','e',0};
 static const WCHAR MathW[] = {'M','a','t','h',0};
+static const WCHAR encodeURIW[] = {'e','n','c','o','d','e','U','R','I',0};
+
+static const WCHAR undefinedW[] = {'u','n','d','e','f','i','n','e','d',0};
+
+static int uri_char_table[] = {
+    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 00-0f */
+    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 10-1f */
+    0,2,0,0,1,0,1,2,2,2,2,1,1,2,2,1, /* 20-2f */
+    2,2,2,2,2,2,2,2,2,2,1,1,0,1,0,1, /* 30-3f */
+    1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, /* 40-4f */
+    2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,2, /* 50-5f */
+    0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, /* 60-6f */
+    2,2,2,2,2,2,2,2,2,2,2,0,0,0,2,0, /* 70-7f */
+};
+
+/* 1 - reserved */
+/* 2 - unescaped */
+
+static inline BOOL is_uri_reserved(WCHAR c)
+{
+    return c < 128 && uri_char_table[c] == 1;
+}
+
+static inline BOOL is_uri_unescaped(WCHAR c)
+{
+    return c < 128 && uri_char_table[c] == 2;
+}
+
+static WCHAR int_to_char(int i)
+{
+    if(i < 10)
+        return '0'+i;
+    return 'A'+i-10;
+}
 
 static HRESULT constructor_call(DispatchEx *constr, LCID lcid, WORD flags, DISPPARAMS *dp,
         VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
@@ -69,15 +108,37 @@ static HRESULT constructor_call(DispatchEx *constr, LCID lcid, WORD flags, DISPP
 static HRESULT JSGlobal_NaN(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
         VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
 {
-    FIXME("\n");
-    return E_NOTIMPL;
+    TRACE("\n");
+
+    switch(flags) {
+    case DISPATCH_PROPERTYGET:
+        num_set_nan(retv);
+        break;
+
+    default:
+        FIXME("unimplemented flags %x\n", flags);
+        return E_NOTIMPL;
+    }
+
+    return S_OK;
 }
 
 static HRESULT JSGlobal_Infinity(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
         VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
 {
-    FIXME("\n");
-    return E_NOTIMPL;
+    TRACE("\n");
+
+    switch(flags) {
+    case DISPATCH_PROPERTYGET:
+        num_set_inf(retv, TRUE);
+        break;
+
+    default:
+        FIXME("unimplemented flags %x\n", flags);
+        return E_NOTIMPL;
+    }
+
+    return S_OK;
 }
 
 static HRESULT JSGlobal_Array(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
@@ -99,8 +160,9 @@ static HRESULT JSGlobal_Boolean(DispatchEx *dispex, LCID lcid, WORD flags, DISPP
 static HRESULT JSGlobal_Date(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
         VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
 {
-    FIXME("\n");
-    return E_NOTIMPL;
+    TRACE("\n");
+
+    return constructor_call(dispex->ctx->date_constr, lcid, flags, dp, retv, ei, sp);
 }
 
 static HRESULT JSGlobal_Function(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
@@ -204,7 +266,7 @@ static HRESULT JSGlobal_eval(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARA
     TRACE("parsing %s\n", debugstr_w(V_BSTR(arg)));
     hres = script_parse(dispex->ctx, V_BSTR(arg), &parser_ctx);
     if(FAILED(hres)) {
-        FIXME("parse failed: %08x\n", hres);
+        WARN("parse (%s) failed: %08x\n", debugstr_w(V_BSTR(arg)), hres);
         return hres;
     }
 
@@ -217,21 +279,133 @@ static HRESULT JSGlobal_eval(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARA
 static HRESULT JSGlobal_isNaN(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
         VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
 {
-    FIXME("\n");
-    return E_NOTIMPL;
+    VARIANT_BOOL ret = VARIANT_FALSE;
+    VARIANT num;
+    HRESULT hres;
+
+    TRACE("\n");
+
+    if(arg_cnt(dp)) {
+        hres = to_number(dispex->ctx, get_arg(dp,0), ei, &num);
+        if(FAILED(hres))
+            return hres;
+
+        if(V_VT(&num) == VT_R8 && isnan(V_R8(&num)))
+            ret = VARIANT_TRUE;
+    }else {
+        ret = VARIANT_TRUE;
+    }
+
+    if(retv) {
+        V_VT(retv) = VT_BOOL;
+        V_BOOL(retv) = ret;
+    }
+    return S_OK;
 }
 
 static HRESULT JSGlobal_isFinite(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
         VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
 {
-    FIXME("\n");
-    return E_NOTIMPL;
+    VARIANT_BOOL ret = VARIANT_FALSE;
+    HRESULT hres;
+
+    TRACE("\n");
+
+    if(arg_cnt(dp)) {
+        VARIANT num;
+
+        hres = to_number(dispex->ctx, get_arg(dp,0), ei, &num);
+        if(FAILED(hres))
+            return hres;
+
+        if(V_VT(&num) != VT_R8 || (!isinf(V_R8(&num)) && !isnan(V_R8(&num))))
+            ret = VARIANT_TRUE;
+    }
+
+    if(retv) {
+        V_VT(retv) = VT_BOOL;
+        V_BOOL(retv) = ret;
+    }
+    return S_OK;
+}
+
+static INT char_to_int(WCHAR c)
+{
+    if('0' <= c && c <= '9')
+        return c - '0';
+    if('a' <= c && c <= 'z')
+        return c - 'a' + 10;
+    if('A' <= c && c <= 'Z')
+        return c - 'A' + 10;
+    return 100;
 }
 
 static HRESULT JSGlobal_parseInt(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
         VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
 {
-    return E_NOTIMPL;
+    DOUBLE ret = 0.0;
+    INT radix=10, i;
+    WCHAR *ptr;
+    BOOL neg = FALSE;
+    BSTR str;
+    HRESULT hres;
+
+    if(!arg_cnt(dp)) {
+        FIXME("NAN\n");
+        return E_NOTIMPL;
+    }
+
+    if(arg_cnt(dp) >= 2) {
+        hres = to_int32(dispex->ctx, get_arg(dp, 1), ei, &radix);
+        if(FAILED(hres))
+            return hres;
+
+        if(!radix) {
+            radix = 10;
+        }else if(radix < 2 || radix > 36) {
+            WARN("radix %d out of range\n", radix);
+            return E_FAIL;
+        }
+    }
+
+    hres = to_string(dispex->ctx, get_arg(dp, 0), ei, &str);
+    if(FAILED(hres))
+        return hres;
+
+    for(ptr = str; isspaceW(*ptr); ptr++);
+
+    switch(*ptr) {
+    case '+':
+        ptr++;
+        break;
+    case '-':
+        neg = TRUE;
+        ptr++;
+        break;
+    case '0':
+        ptr++;
+        if(*ptr == 'x' || *ptr == 'X') {
+            radix = 16;
+            ptr++;
+        }
+    }
+
+    while(*ptr) {
+        i = char_to_int(*ptr++);
+        if(i > radix)
+            break;
+
+        ret = ret*radix + i;
+    }
+
+    SysFreeString(str);
+
+    if(neg)
+        ret = -ret;
+
+    if(retv)
+        num_set_val(retv, ret);
+    return S_OK;
 }
 
 static HRESULT JSGlobal_parseFloat(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
@@ -290,6 +464,76 @@ static HRESULT JSGlobal_CollectGarbage(DispatchEx *dispex, LCID lcid, WORD flags
     return E_NOTIMPL;
 }
 
+static HRESULT JSGlobal_encodeURI(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
+        VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
+{
+    const WCHAR *ptr;
+    DWORD len = 0, i;
+    char buf[4];
+    BSTR str, ret;
+    WCHAR *rptr;
+    HRESULT hres;
+
+    TRACE("\n");
+
+    if(!arg_cnt(dp)) {
+        if(retv) {
+            ret = SysAllocString(undefinedW);
+            if(!ret)
+                return E_OUTOFMEMORY;
+
+            V_VT(retv) = VT_BSTR;
+            V_BSTR(retv) = ret;
+        }
+
+        return S_OK;
+    }
+
+    hres = to_string(dispex->ctx, get_arg(dp,0), ei, &str);
+    if(FAILED(hres))
+        return hres;
+
+    for(ptr = str; *ptr; ptr++) {
+        if(is_uri_unescaped(*ptr) || is_uri_reserved(*ptr) || *ptr == '#') {
+            len++;
+        }else {
+            i = WideCharToMultiByte(CP_UTF8, 0, ptr, 1, NULL, 0, NULL, NULL)*3;
+            if(!i) {
+                FIXME("throw URIError\n");
+                return E_FAIL;
+            }
+
+            len += i;
+        }
+    }
+
+    rptr = ret = SysAllocStringLen(NULL, len);
+    if(!ret)
+        return E_OUTOFMEMORY;
+
+    for(ptr = str; *ptr; ptr++) {
+        if(is_uri_unescaped(*ptr) || is_uri_reserved(*ptr) || *ptr == '#') {
+            *rptr++ = *ptr;
+        }else {
+            len = WideCharToMultiByte(CP_UTF8, 0, ptr, 1, buf, sizeof(buf), NULL, NULL);
+            for(i=0; i<len; i++) {
+                *rptr++ = '%';
+                *rptr++ = int_to_char((BYTE)buf[i] >> 4);
+                *rptr++ = int_to_char(buf[i] & 0x0f);
+            }
+        }
+    }
+
+    TRACE("%s -> %s\n", debugstr_w(str), debugstr_w(ret));
+    if(retv) {
+        V_VT(retv) = VT_BSTR;
+        V_BSTR(retv) = ret;
+    }else {
+        SysFreeString(ret);
+    }
+    return S_OK;
+}
+
 static const builtin_prop_t JSGlobal_props[] = {
     {ActiveXObjectW,             JSGlobal_ActiveXObject,             PROPF_METHOD},
     {ArrayW,                     JSGlobal_Array,                     PROPF_CONSTR},
@@ -298,7 +542,7 @@ static const builtin_prop_t JSGlobal_props[] = {
     {DateW,                      JSGlobal_Date,                      PROPF_CONSTR},
     {EnumeratorW,                JSGlobal_Enumerator,                PROPF_METHOD},
     {FunctionW,                  JSGlobal_Function,                  PROPF_CONSTR},
-    {GetObjectW,                 JSGlobal_GetObject,                 PROPF_METHOD},
+    {_GetObjectW,                JSGlobal_GetObject,                 PROPF_METHOD},
     {InfinityW,                  JSGlobal_Infinity,                  0},
 /*  {MathW,                      JSGlobal_Math,                      0},  */
     {NaNW,                       JSGlobal_NaN,                       0},
@@ -311,6 +555,7 @@ static const builtin_prop_t JSGlobal_props[] = {
     {ScriptEngineMinorVersionW,  JSGlobal_ScriptEngineMinorVersion,  PROPF_METHOD},
     {StringW,                    JSGlobal_String,                    PROPF_CONSTR},
     {VBArrayW,                   JSGlobal_VBArray,                   PROPF_METHOD},
+    {encodeURIW,                 JSGlobal_encodeURI,                 PROPF_METHOD},
     {escapeW,                    JSGlobal_escape,                    PROPF_METHOD},
     {evalW,                      JSGlobal_eval,                      PROPF_METHOD|1},
     {isFiniteW,                  JSGlobal_isFinite,                  PROPF_METHOD},
@@ -345,6 +590,10 @@ static HRESULT init_constructors(script_ctx_t *ctx)
     if(FAILED(hres))
         return hres;
 
+    hres = create_date_constr(ctx, &ctx->date_constr);
+    if(FAILED(hres))
+        return hres;
+
     hres = create_number_constr(ctx, &ctx->number_constr);
     if(FAILED(hres))
         return hres;
@@ -353,7 +602,7 @@ static HRESULT init_constructors(script_ctx_t *ctx)
     if(FAILED(hres))
         return hres;
 
-    hres = create_object_constr(ctx, &ctx->regexp_constr);
+    hres = create_regexp_constr(ctx, &ctx->regexp_constr);
     if(FAILED(hres))
         return hres;
 
index 7c7def0..fb99d24 100644 (file)
 
 WINE_DEFAULT_DEBUG_CHANNEL(jscript);
 
+#ifdef _WIN64
+
+#define CTXARG_T DWORDLONG
+#define IActiveScriptParseVtbl IActiveScriptParse64Vtbl
+#define IActiveScriptParseProcedure2Vtbl IActiveScriptParseProcedure2_64Vtbl
+
+#else
+
+#define CTXARG_T DWORD
+#define IActiveScriptParseVtbl IActiveScriptParse32Vtbl
+#define IActiveScriptParseProcedure2Vtbl IActiveScriptParseProcedure2_32Vtbl
+
+#endif
+
 typedef struct {
     const IActiveScriptVtbl                 *lpIActiveScriptVtbl;
     const IActiveScriptParseVtbl            *lpIActiveScriptParseVtbl;
@@ -36,6 +50,7 @@ typedef struct {
     DWORD safeopt;
     script_ctx_t *ctx;
     LONG thread_id;
+    LCID lcid;
 
     IActiveScriptSite *site;
 
@@ -43,11 +58,11 @@ typedef struct {
     parser_ctx_t *queue_tail;
 } JScript;
 
-#define ACTSCRIPT(x)    ((IActiveScript*)                 &(x)->lpIActiveScriptVtbl)
-#define ASPARSE(x)      ((IActiveScriptParse*)            &(x)->lpIActiveScriptParseVtbl)
-#define ASPARSEPROC(x)  ((IActiveScriptParseProcedure2*)  &(x)->lpIActiveScriptParseProcedure2Vtbl)
-#define ACTSCPPROP(x)   ((IActiveScriptProperty*)         &(x)->lpIActiveScriptPropertyVtbl)
-#define OBJSAFETY(x)    ((IObjectSafety*)                 &(x)->lpIObjectSafetyVtbl)
+#define ACTSCRIPT(x)    ((IActiveScript*) &(x)->lpIActiveScriptVtbl)
+#define ASPARSE(x)      (&(x)->lpIActiveScriptParseVtbl)
+#define ASPARSEPROC(x)  (&(x)->lpIActiveScriptParseProcedure2Vtbl)
+#define ACTSCPPROP(x)   (&(x)->lpIActiveScriptPropertyVtbl)
+#define OBJSAFETY(x)    (&(x)->lpIObjectSafetyVtbl)
 
 void script_release(script_ctx_t *ctx)
 {
@@ -127,6 +142,29 @@ static void exec_queued_code(JScript *This)
     clear_script_queue(This);
 }
 
+static HRESULT set_ctx_site(JScript *This)
+{
+    HRESULT hres;
+
+    This->ctx->lcid = This->lcid;
+
+    if(!This->ctx->script_disp) {
+        hres = create_dispex(This->ctx, NULL, NULL, &This->ctx->script_disp);
+        if(FAILED(hres))
+            return hres;
+    }
+
+    hres = init_global(This->ctx);
+    if(FAILED(hres))
+        return hres;
+
+    IActiveScriptSite_AddRef(This->site);
+    This->ctx->site = This->site;
+
+    change_state(This, SCRIPTSTATE_INITIALIZED);
+    return S_OK;
+}
+
 #define ACTSCRIPT_THIS(iface) DEFINE_THIS(JScript, IActiveScript, iface)
 
 static HRESULT WINAPI JScript_QueryInterface(IActiveScript *iface, REFIID riid, void **ppv)
@@ -211,22 +249,6 @@ static HRESULT WINAPI JScript_SetScriptSite(IActiveScript *iface,
     if(This->site)
         return E_UNEXPECTED;
 
-    if(!This->ctx) {
-        hres = IActiveScriptParse_InitNew(ASPARSE(This));
-        if(FAILED(hres))
-            return hres;
-    }
-
-    if(!This->ctx->script_disp) {
-        hres = create_dispex(This->ctx, NULL, NULL, &This->ctx->script_disp);
-        if(FAILED(hres))
-            return hres;
-    }
-
-    hres = init_global(This->ctx);
-    if(FAILED(hres))
-        return hres;
-
     if(InterlockedCompareExchange(&This->thread_id, GetCurrentThreadId(), 0))
         return E_UNEXPECTED;
 
@@ -235,10 +257,9 @@ static HRESULT WINAPI JScript_SetScriptSite(IActiveScript *iface,
 
     hres = IActiveScriptSite_GetLCID(This->site, &lcid);
     if(hres == S_OK)
-        This->ctx->lcid = lcid;
+        This->lcid = lcid;
 
-    change_state(This, SCRIPTSTATE_INITIALIZED);
-    return S_OK;
+    return This->ctx ? set_ctx_site(This) : S_OK;
 }
 
 static HRESULT WINAPI JScript_GetScriptSite(IActiveScript *iface, REFIID riid,
@@ -260,6 +281,7 @@ static HRESULT WINAPI JScript_SetScriptState(IActiveScript *iface, SCRIPTSTATE s
 
     switch(ss) {
     case SCRIPTSTATE_STARTED:
+    case SCRIPTSTATE_CONNECTED: /* FIXME */
         if(This->ctx->state == SCRIPTSTATE_CLOSED)
             return E_UNEXPECTED;
 
@@ -304,25 +326,39 @@ static HRESULT WINAPI JScript_Close(IActiveScript *iface)
     if(This->thread_id != GetCurrentThreadId())
         return E_UNEXPECTED;
 
-    clear_script_queue(This);
+    if(This->ctx) {
+        if(This->ctx->state == SCRIPTSTATE_CONNECTED)
+            change_state(This, SCRIPTSTATE_DISCONNECTED);
+
+        clear_script_queue(This);
+
+        if(This->ctx->state == SCRIPTSTATE_DISCONNECTED)
+            change_state(This, SCRIPTSTATE_INITIALIZED);
+
+        if(This->ctx->named_items) {
+            named_item_t *iter, *iter2;
 
-    if(This->ctx->named_items) {
-        named_item_t *iter, *iter2;
+            iter = This->ctx->named_items;
+            while(iter) {
+                iter2 = iter->next;
 
-        iter = This->ctx->named_items;
-        while(iter) {
-            iter2 = iter->next;
+                if(iter->disp)
+                    IDispatch_Release(iter->disp);
+                heap_free(iter->name);
+                heap_free(iter);
+                iter = iter2;
+            }
 
-            IDispatch_Release(iter->disp);
-            heap_free(iter);
-            iter = iter2;
+            This->ctx->named_items = NULL;
         }
 
-        This->ctx->named_items = NULL;
-    }
+        if(This->ctx->site) {
+            IActiveScriptSite_Release(This->ctx->site);
+            This->ctx->site = NULL;
+        }
 
-    if(This->ctx) {
-        change_state(This, SCRIPTSTATE_CLOSED);
+        if (This->site)
+            change_state(This, SCRIPTSTATE_CLOSED);
 
         if(This->ctx->script_disp) {
             IDispatchEx_Release(_IDispatchEx_(This->ctx->script_disp));
@@ -348,8 +384,7 @@ static HRESULT WINAPI JScript_AddNamedItem(IActiveScript *iface,
 {
     JScript *This = ACTSCRIPT_THIS(iface);
     named_item_t *item;
-    IDispatch *disp;
-    IUnknown *unk;
+    IDispatch *disp = NULL;
     HRESULT hres;
 
     TRACE("(%p)->(%s %x)\n", This, debugstr_w(pstrName), dwFlags);
@@ -357,27 +392,39 @@ static HRESULT WINAPI JScript_AddNamedItem(IActiveScript *iface,
     if(This->thread_id != GetCurrentThreadId() || !This->ctx || This->ctx->state == SCRIPTSTATE_CLOSED)
         return E_UNEXPECTED;
 
-    hres = IActiveScriptSite_GetItemInfo(This->site, pstrName, SCRIPTINFO_IUNKNOWN, &unk, NULL);
-    if(FAILED(hres)) {
-        WARN("GetItemInfo failed: %08x\n", hres);
-        return hres;
-    }
+    if(dwFlags & SCRIPTITEM_GLOBALMEMBERS) {
+        IUnknown *unk;
 
-    hres = IUnknown_QueryInterface(unk, &IID_IDispatch, (void**)&disp);
-    IUnknown_Release(unk);
-    if(FAILED(hres)) {
-        WARN("object does not implement IDispatch\n");
-        return hres;
+        hres = IActiveScriptSite_GetItemInfo(This->site, pstrName, SCRIPTINFO_IUNKNOWN, &unk, NULL);
+        if(FAILED(hres)) {
+            WARN("GetItemInfo failed: %08x\n", hres);
+            return hres;
+        }
+
+        hres = IUnknown_QueryInterface(unk, &IID_IDispatch, (void**)&disp);
+        IUnknown_Release(unk);
+        if(FAILED(hres)) {
+            WARN("object does not implement IDispatch\n");
+            return hres;
+        }
     }
 
     item = heap_alloc(sizeof(*item));
     if(!item) {
-        IDispatch_Release(disp);
+        if(disp)
+            IDispatch_Release(disp);
         return E_OUTOFMEMORY;
     }
 
     item->disp = disp;
     item->flags = dwFlags;
+    item->name = heap_strdupW(pstrName);
+    if(!item->name) {
+        IDispatch_Release(disp);
+        heap_free(item);
+        return E_OUTOFMEMORY;
+    }
+
     item->next = This->ctx->named_items;
     This->ctx->named_items = item;
 
@@ -516,35 +563,35 @@ static HRESULT WINAPI JScriptParse_InitNew(IActiveScriptParse *iface)
         return E_UNEXPECTED;
     }
 
-    return S_OK;
+    return This->site ? set_ctx_site(This) : S_OK;
 }
 
 static HRESULT WINAPI JScriptParse_AddScriptlet(IActiveScriptParse *iface,
         LPCOLESTR pstrDefaultName, LPCOLESTR pstrCode, LPCOLESTR pstrItemName,
         LPCOLESTR pstrSubItemName, LPCOLESTR pstrEventName, LPCOLESTR pstrDelimiter,
-        DWORD dwSourceContextCookie, ULONG ulStartingLineNumber, DWORD dwFlags,
+        CTXARG_T dwSourceContextCookie, ULONG ulStartingLineNumber, DWORD dwFlags,
         BSTR *pbstrName, EXCEPINFO *pexcepinfo)
 {
     JScript *This = ASPARSE_THIS(iface);
-    FIXME("(%p)->(%s %s %s %s %s %s %x %u %x %p %p)\n", This, debugstr_w(pstrDefaultName),
+    FIXME("(%p)->(%s %s %s %s %s %s %s %u %x %p %p)\n", This, debugstr_w(pstrDefaultName),
           debugstr_w(pstrCode), debugstr_w(pstrItemName), debugstr_w(pstrSubItemName),
-          debugstr_w(pstrEventName), debugstr_w(pstrDelimiter), dwSourceContextCookie,
+          debugstr_w(pstrEventName), debugstr_w(pstrDelimiter), wine_dbgstr_longlong(dwSourceContextCookie),
           ulStartingLineNumber, dwFlags, pbstrName, pexcepinfo);
     return E_NOTIMPL;
 }
 
 static HRESULT WINAPI JScriptParse_ParseScriptText(IActiveScriptParse *iface,
         LPCOLESTR pstrCode, LPCOLESTR pstrItemName, IUnknown *punkContext,
-        LPCOLESTR pstrDelimiter, DWORD dwSourceContextCookie, ULONG ulStartingLine,
+        LPCOLESTR pstrDelimiter, CTXARG_T dwSourceContextCookie, ULONG ulStartingLine,
         DWORD dwFlags, VARIANT *pvarResult, EXCEPINFO *pexcepinfo)
 {
     JScript *This = ASPARSE_THIS(iface);
     parser_ctx_t *parser_ctx;
     HRESULT hres;
 
-    TRACE("(%p)->(%s %s %p %s %x %u %x %p %p)\n", This, debugstr_w(pstrCode),
+    TRACE("(%p)->(%s %s %p %s %s %u %x %p %p)\n", This, debugstr_w(pstrCode),
           debugstr_w(pstrItemName), punkContext, debugstr_w(pstrDelimiter),
-          dwSourceContextCookie, ulStartingLine, dwFlags, pvarResult, pexcepinfo);
+          wine_dbgstr_longlong(dwSourceContextCookie), ulStartingLine, dwFlags, pvarResult, pexcepinfo);
 
     if(This->thread_id != GetCurrentThreadId() || This->ctx->state == SCRIPTSTATE_CLOSED)
         return E_UNEXPECTED;
@@ -601,16 +648,16 @@ static ULONG WINAPI JScriptParseProcedure_Release(IActiveScriptParseProcedure2 *
 static HRESULT WINAPI JScriptParseProcedure_ParseProcedureText(IActiveScriptParseProcedure2 *iface,
         LPCOLESTR pstrCode, LPCOLESTR pstrFormalParams, LPCOLESTR pstrProcedureName,
         LPCOLESTR pstrItemName, IUnknown *punkContext, LPCOLESTR pstrDelimiter,
-        DWORD dwSourceContextCookie, ULONG ulStartingLineNumber, DWORD dwFlags, IDispatch **ppdisp)
+        CTXARG_T dwSourceContextCookie, ULONG ulStartingLineNumber, DWORD dwFlags, IDispatch **ppdisp)
 {
     JScript *This = ASPARSEPROC_THIS(iface);
     parser_ctx_t *parser_ctx;
     DispatchEx *dispex;
     HRESULT hres;
 
-    TRACE("(%p)->(%s %s %s %s %p %s %x %u %x %p)\n", This, debugstr_w(pstrCode), debugstr_w(pstrFormalParams),
+    TRACE("(%p)->(%s %s %s %s %p %s %s %u %x %p)\n", This, debugstr_w(pstrCode), debugstr_w(pstrFormalParams),
           debugstr_w(pstrProcedureName), debugstr_w(pstrItemName), punkContext, debugstr_w(pstrDelimiter),
-          dwSourceContextCookie, ulStartingLineNumber, dwFlags, ppdisp);
+          wine_dbgstr_longlong(dwSourceContextCookie), ulStartingLineNumber, dwFlags, ppdisp);
 
     if(This->thread_id != GetCurrentThreadId() || This->ctx->state == SCRIPTSTATE_CLOSED)
         return E_UNEXPECTED;
@@ -621,7 +668,7 @@ static HRESULT WINAPI JScriptParseProcedure_ParseProcedureText(IActiveScriptPars
         return hres;
     }
 
-    hres = create_source_function(parser_ctx, NULL, parser_ctx->source, NULL, &dispex);
+    hres = create_source_function(parser_ctx, NULL, parser_ctx->source, NULL, NULL, 0, &dispex);
     parser_release(parser_ctx);
     if(FAILED(hres))
         return hres;
@@ -758,6 +805,8 @@ HRESULT WINAPI JScriptFactory_CreateInstance(IClassFactory *iface, IUnknown *pUn
     lock_module();
 
     ret = heap_alloc_zero(sizeof(*ret));
+    if(!ret)
+        return E_OUTOFMEMORY;
 
     ret->lpIActiveScriptVtbl                 = &JScriptVtbl;
     ret->lpIActiveScriptParseVtbl            = &JScriptParseVtbl;
index 6c4e272..4862b28 100644 (file)
@@ -67,6 +67,7 @@ typedef enum {
     JSCLASS_NONE,
     JSCLASS_ARRAY,
     JSCLASS_BOOLEAN,
+    JSCLASS_DATE,
     JSCLASS_FUNCTION,
     JSCLASS_GLOBAL,
     JSCLASS_MATH,
@@ -124,8 +125,12 @@ HRESULT disp_call(IDispatch*,DISPID,LCID,WORD,DISPPARAMS*,VARIANT*,jsexcept_t*,I
 HRESULT jsdisp_call_value(DispatchEx*,LCID,WORD,DISPPARAMS*,VARIANT*,jsexcept_t*,IServiceProvider*);
 HRESULT disp_propget(IDispatch*,DISPID,LCID,VARIANT*,jsexcept_t*,IServiceProvider*);
 HRESULT disp_propput(IDispatch*,DISPID,LCID,VARIANT*,jsexcept_t*,IServiceProvider*);
+HRESULT jsdisp_propget(DispatchEx*,DISPID,LCID,VARIANT*,jsexcept_t*,IServiceProvider*);
 HRESULT jsdisp_propput_name(DispatchEx*,const WCHAR*,LCID,VARIANT*,jsexcept_t*,IServiceProvider*);
 HRESULT jsdisp_propput_idx(DispatchEx*,DWORD,LCID,VARIANT*,jsexcept_t*,IServiceProvider*);
+HRESULT jsdisp_propget_name(DispatchEx*,LPCWSTR,LCID,VARIANT*,jsexcept_t*,IServiceProvider*);
+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**);
 
@@ -149,6 +154,7 @@ HRESULT to_object(exec_ctx_t*,VARIANT*,IDispatch**);
 typedef struct named_item_t {
     IDispatch *disp;
     DWORD flags;
+    LPWSTR name;
 
     struct named_item_t *next;
 } named_item_t;
@@ -159,6 +165,7 @@ struct _script_ctx_t {
     SCRIPTSTATE state;
     exec_ctx_t *exec_ctx;
     named_item_t *named_items;
+    IActiveScriptSite *site;
     LCID lcid;
 
     jsheap_t tmp_heap;
@@ -168,6 +175,7 @@ struct _script_ctx_t {
     DispatchEx *function_constr;
     DispatchEx *array_constr;
     DispatchEx *bool_constr;
+    DispatchEx *date_constr;
     DispatchEx *number_constr;
     DispatchEx *object_constr;
     DispatchEx *regexp_constr;
@@ -186,6 +194,7 @@ HRESULT init_function_constr(script_ctx_t*);
 
 HRESULT create_array_constr(script_ctx_t*,DispatchEx**);
 HRESULT create_bool_constr(script_ctx_t*,DispatchEx**);
+HRESULT create_date_constr(script_ctx_t*,DispatchEx**);
 HRESULT create_number_constr(script_ctx_t*,DispatchEx**);
 HRESULT create_object_constr(script_ctx_t*,DispatchEx**);
 HRESULT create_regexp_constr(script_ctx_t*,DispatchEx**);
@@ -196,6 +205,8 @@ typedef struct {
     DWORD len;
 } match_result_t;
 
+HRESULT regexp_match_next(DispatchEx*,BOOL,const WCHAR*,DWORD,const WCHAR**,match_result_t**,
+        DWORD*,DWORD*,match_result_t*);
 HRESULT regexp_match(DispatchEx*,const WCHAR*,DWORD,BOOL,match_result_t**,DWORD*);
 
 static inline VARIANT *get_arg(DISPPARAMS *dp, DWORD i)
@@ -208,6 +219,21 @@ static inline DWORD arg_cnt(const DISPPARAMS *dp)
     return dp->cArgs - dp->cNamedArgs;
 }
 
+static inline BOOL is_class(DispatchEx *jsdisp, jsclass_t class)
+{
+    return jsdisp->builtin_info->class == class;
+}
+
+static inline BOOL is_num_vt(enum VARENUM vt)
+{
+    return vt == VT_I4 || vt == VT_R8;
+}
+
+static inline DOUBLE num_val(const VARIANT *v)
+{
+    return V_VT(v) == VT_I4 ? V_I4(v) : V_R8(v);
+}
+
 static inline void num_set_val(VARIANT *v, DOUBLE d)
 {
     if(d == (DOUBLE)(INT)d) {
@@ -219,6 +245,28 @@ static inline void num_set_val(VARIANT *v, DOUBLE d)
     }
 }
 
+static inline void num_set_nan(VARIANT *v)
+{
+    V_VT(v) = VT_R8;
+#ifdef NAN
+    V_R8(v) = NAN;
+#else
+    V_UI8(v) = (ULONGLONG)0x7ff80000<<32;
+#endif
+}
+
+static inline void num_set_inf(VARIANT *v, BOOL positive)
+{
+    V_VT(v) = VT_R8;
+#ifdef INFINITY
+    V_R8(v) = positive ? INFINITY : -INFINITY;
+#else
+    V_UI8(v) = (ULONGLONG)0x7ff00000<<32;
+    if(!positive)
+        V_R8(v) = -V_R8(v);
+#endif
+}
+
 const char *debugstr_variant(const VARIANT*);
 
 HRESULT WINAPI JScriptFactory_CreateInstance(IClassFactory*,IUnknown*,REFIID,void**);
index 76c12d1..4f18caa 100644 (file)
@@ -11,6 +11,8 @@
        <library>wine</library>
        <library>kernel32</library>
        <library>oleaut32</library>
+       <library>advapi32</library>
+       <file>date.c</file>
        <file>dispex.c</file>
        <file>engine.c</file>
        <file>jscript.c</file>
index f368c3e..defddd4 100644 (file)
@@ -16,6 +16,9 @@
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  */
 
+#include "config.h"
+#include "wine/port.h"
+
 #include <math.h>
 
 #include "jscript.h"
@@ -217,10 +220,117 @@ HRESULT to_boolean(VARIANT *v, VARIANT_BOOL *b)
     return S_OK;
 }
 
+static int hex_to_int(WCHAR c)
+{
+    if('0' <= c && c <= '9')
+        return c-'0';
+
+    if('a' <= c && c <= 'f')
+        return c-'a'+10;
+
+    if('A' <= c && c <= 'F')
+        return c-'A'+10;
+
+    return -1;
+}
+
+/* ECMA-262 3rd Edition    9.3.1 */
+static HRESULT str_to_number(BSTR str, VARIANT *ret)
+{
+    const WCHAR *ptr = str;
+    BOOL neg = FALSE;
+    DOUBLE d = 0.0;
+
+    static const WCHAR infinityW[] = {'I','n','f','i','n','i','t','y'};
+
+    while(isspaceW(*ptr))
+        ptr++;
+
+    if(*ptr == '-') {
+        neg = TRUE;
+        ptr++;
+    }else if(*ptr == '+') {
+        ptr++;
+    }
+
+    if(!strncmpW(ptr, infinityW, sizeof(infinityW)/sizeof(WCHAR))) {
+        ptr += sizeof(infinityW)/sizeof(WCHAR);
+        while(*ptr && isspaceW(*ptr))
+            ptr++;
+
+        if(*ptr)
+            num_set_nan(ret);
+        else
+            num_set_inf(ret, !neg);
+        return S_OK;
+    }
+
+    if(*ptr == '0' && ptr[1] == 'x') {
+        DWORD l = 0;
+
+        ptr += 2;
+        while((l = hex_to_int(*ptr)) != -1) {
+            d = d*16 + l;
+            ptr++;
+        }
+
+        num_set_val(ret, d);
+        return S_OK;
+    }
+
+    while(isdigitW(*ptr))
+        d = d*10 + (*ptr++ - '0');
+
+    if(*ptr == 'e' || *ptr == 'E') {
+        BOOL eneg = FALSE;
+        LONG l = 0;
+
+        ptr++;
+        if(*ptr == '-') {
+            ptr++;
+            eneg = TRUE;
+        }else if(*ptr == '+') {
+            ptr++;
+        }
+
+        while(isdigitW(*ptr))
+            l = l*10 + (*ptr++ - '0');
+        if(eneg)
+            l = -l;
+
+        d *= pow(10, l);
+    }else if(*ptr == '.') {
+        DOUBLE dec = 0.1;
+
+        ptr++;
+        while(isdigitW(*ptr)) {
+            d += dec * (*ptr++ - '0');
+            dec *= 0.1;
+        }
+    }
+
+    while(isspaceW(*ptr))
+        ptr++;
+
+    if(*ptr) {
+        num_set_nan(ret);
+        return S_OK;
+    }
+
+    if(neg)
+        d = -d;
+
+    num_set_val(ret, d);
+    return S_OK;
+}
+
 /* ECMA-262 3rd Edition    9.3 */
 HRESULT to_number(script_ctx_t *ctx, VARIANT *v, jsexcept_t *ei, VARIANT *ret)
 {
     switch(V_VT(v)) {
+    case VT_EMPTY:
+        num_set_nan(ret);
+        break;
     case VT_NULL:
         V_VT(ret) = VT_I4;
         V_I4(ret) = 0;
@@ -229,6 +339,20 @@ HRESULT to_number(script_ctx_t *ctx, VARIANT *v, jsexcept_t *ei, VARIANT *ret)
     case VT_R8:
         *ret = *v;
         break;
+    case VT_BSTR:
+        return str_to_number(V_BSTR(v), ret);
+    case VT_DISPATCH: {
+        VARIANT prim;
+        HRESULT hres;
+
+        hres = to_primitive(ctx, v, ei, &prim);
+        if(FAILED(hres))
+            return hres;
+
+        hres = to_number(ctx, &prim, ei, ret);
+        VariantClear(&prim);
+        return hres;
+    }
     case VT_BOOL:
         V_VT(ret) = VT_I4;
         V_I4(ret) = V_BOOL(v) ? 1 : 0;
@@ -252,7 +376,7 @@ HRESULT to_integer(script_ctx_t *ctx, VARIANT *v, jsexcept_t *ei, VARIANT *ret)
         return hres;
 
     if(V_VT(&num) == VT_I4)
-        *ret = *v;
+        *ret = num;
     else
         num_set_val(ret, V_R8(&num) >= 0.0 ? floor(V_R8(&num)) : -floor(-V_R8(&num)));
 
@@ -335,6 +459,18 @@ HRESULT to_string(script_ctx_t *ctx, VARIANT *v, jsexcept_t *ei, BSTR *str)
     case VT_I4:
         *str = int_to_bstr(V_I4(v));
         break;
+    case VT_R8: {
+        VARIANT strv;
+        HRESULT hres;
+
+        V_VT(&strv) = VT_EMPTY;
+        hres = VariantChangeTypeEx(&strv, v, MAKELCID(MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),SORT_DEFAULT), 0, VT_BSTR);
+        if(FAILED(hres))
+            return hres;
+
+        *str = V_BSTR(&strv);
+        return S_OK;
+    }
     case VT_BSTR:
         *str = SysAllocString(V_BSTR(v));
         break;
index ed73202..bf298bf 100644 (file)
@@ -101,7 +101,7 @@ static int lex_error(parser_ctx_t *ctx, HRESULT hres)
     return -1;
 }
 
-static int check_keyword(parser_ctx_t *ctx, const WCHAR *word)
+static int check_keyword(parser_ctx_t *ctx, const WCHAR *word, const WCHAR **lval)
 {
     const WCHAR *p1 = ctx->ptr;
     const WCHAR *p2 = word;
@@ -116,6 +116,7 @@ static int check_keyword(parser_ctx_t *ctx, const WCHAR *word)
     if(*p2 || (p1 < ctx->end && isalnumW(*p1)))
         return 1;
 
+    *lval = ctx->ptr;
     ctx->ptr = p1;
     return 0;
 }
@@ -145,14 +146,14 @@ static int hex_to_int(WCHAR c)
     return -1;
 }
 
-static int check_keywords(parser_ctx_t *ctx)
+static int check_keywords(parser_ctx_t *ctx, const WCHAR **lval)
 {
     int min = 0, max = sizeof(keywords)/sizeof(keywords[0])-1, r, i;
 
     while(min <= max) {
         i = (min+max)/2;
 
-        r = check_keyword(ctx, keywords[i].word);
+        r = check_keyword(ctx, keywords[i].word, lval);
         if(!r)
             return keywords[i].token;
 
@@ -242,13 +243,11 @@ static BOOL unescape(WCHAR *str)
         case 'r':
             c = '\r';
             break;
-        case '0':
-            break;
         case 'x':
             i = hex_to_int(*++p);
             if(i == -1)
                 return FALSE;
-            c = i << 16;
+            c = i << 4;
 
             i = hex_to_int(*++p);
             if(i == -1)
@@ -259,17 +258,17 @@ static BOOL unescape(WCHAR *str)
             i = hex_to_int(*++p);
             if(i == -1)
                 return FALSE;
-            c = i << 24;
+            c = i << 12;
 
             i = hex_to_int(*++p);
             if(i == -1)
                 return FALSE;
-            c += i << 16;
+            c += i << 8;
 
             i = hex_to_int(*++p);
             if(i == -1)
                 return FALSE;
-            c += 1 << 8;
+            c += 1 << 4;
 
             i = hex_to_int(*++p);
             if(i == -1)
@@ -277,6 +276,14 @@ static BOOL unescape(WCHAR *str)
             c += i;
             break;
         default:
+            if(isdigitW(*p)) {
+                c = *p++ - '0';
+                while(isdigitW(*p))
+                    c = c*10 + (*p++ - '0');
+                *pd++ = c;
+                continue;
+            }
+
             c = *p;
         }
 
@@ -387,7 +394,7 @@ static int parse_double_literal(parser_ctx_t *ctx, LONG int_part, literal_t **li
             e = e*10 + *ctx->ptr++ - '0';
         e *= sign;
 
-        d = pow(d, e);
+        d *= pow(10, e);
     }
 
     *literal = parser_alloc(ctx, sizeof(literal_t));
@@ -468,11 +475,11 @@ int parser_lex(void *lval, parser_ctx_t *ctx)
     }while(skip_comment(ctx));
 
     if(isalphaW(*ctx->ptr)) {
-        ret = check_keywords(ctx);
+        ret = check_keywords(ctx, lval);
         if(ret)
             return ret;
 
-        return parse_identifier(ctx, (const WCHAR**)lval);
+        return parse_identifier(ctx, lval);
     }
 
     if(isdigitW(*ctx->ptr))
@@ -480,7 +487,6 @@ int parser_lex(void *lval, parser_ctx_t *ctx)
 
     switch(*ctx->ptr) {
     case '{':
-    case '}':
     case '(':
     case ')':
     case '[':
@@ -492,6 +498,10 @@ int parser_lex(void *lval, parser_ctx_t *ctx)
     case ':':
         return *ctx->ptr++;
 
+    case '}':
+        *(const WCHAR**)lval = ctx->ptr++;
+        return '}';
+
     case '.':
         if(++ctx->ptr < ctx->end && isdigitW(*ctx->ptr))
             return parse_double_literal(ctx, 0, lval);
@@ -674,7 +684,7 @@ int parser_lex(void *lval, parser_ctx_t *ctx)
 
     case '\"':
     case '\'':
-        return parse_string_literal(ctx, (const WCHAR**)lval, *ctx->ptr);
+        return parse_string_literal(ctx, lval, *ctx->ptr);
 
     case '_':
     case '$':
@@ -705,8 +715,10 @@ literal_t *parse_regexp(parser_ctx_t *ctx)
     TRACE("\n");
 
     re = ctx->ptr;
-    while(ctx->ptr < ctx->end && (*ctx->ptr != '/' || *(ctx->ptr-1) == '\\'))
-        ctx->ptr++;
+    while(ctx->ptr < ctx->end && *ctx->ptr != '/') {
+        if(*ctx->ptr++ == '\\' && ctx->ptr < ctx->end)
+            ctx->ptr++;
+    }
 
     if(ctx->ptr == ctx->end) {
         WARN("unexpected end of file\n");
index 8454cfa..4f6c049 100644 (file)
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  */
 
+#include "config.h"
+#include "wine/port.h"
+
+#include <math.h>
+#include <limits.h>
+
 #include "jscript.h"
+#include "ntsecapi.h"
 
 #include "wine/debug.h"
 
@@ -24,7 +31,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(jscript);
 
 static const WCHAR EW[] = {'E',0};
 static const WCHAR LOG2EW[] = {'L','O','G','2','E',0};
-static const WCHAR LOG10EW[] = {'L','O','G','1','0',0};
+static const WCHAR LOG10EW[] = {'L','O','G','1','0','E',0};
 static const WCHAR LN2W[] = {'L','N','2',0};
 static const WCHAR LN10W[] = {'L','N','1','0',0};
 static const WCHAR PIW[] = {'P','I',0};
@@ -49,25 +56,43 @@ static const WCHAR sinW[] = {'s','i','n',0};
 static const WCHAR sqrtW[] = {'s','q','r','t',0};
 static const WCHAR tanW[] = {'t','a','n',0};
 
+static HRESULT math_constant(DOUBLE val, WORD flags, VARIANT *retv)
+{
+    switch(flags) {
+    case DISPATCH_PROPERTYGET:
+        V_VT(retv) = VT_R8;
+        V_R8(retv) = val;
+        return S_OK;
+    case DISPATCH_PROPERTYPUT:
+        return S_OK;
+    }
+
+    FIXME("unhandled flags %x\n", flags);
+    return E_NOTIMPL;
+}
+
+/* ECMA-262 3rd Edition    15.8.1.1 */
 static HRESULT Math_E(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
         VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
 {
-    FIXME("\n");
-    return E_NOTIMPL;
+    TRACE("\n");
+    return math_constant(M_E, flags, retv);
 }
 
+/* ECMA-262 3rd Edition    15.8.1.4 */
 static HRESULT Math_LOG2E(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
         VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
 {
-    FIXME("\n");
-    return E_NOTIMPL;
+    TRACE("\n");
+    return math_constant(M_LOG2E, flags, retv);
 }
 
+/* ECMA-262 3rd Edition    15.8.1.4 */
 static HRESULT Math_LOG10E(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
         VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
 {
-    FIXME("\n");
-    return E_NOTIMPL;
+    TRACE("\n");
+    return math_constant(M_LOG10E, flags, retv);
 }
 
 static HRESULT Math_LN2(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
@@ -84,11 +109,12 @@ static HRESULT Math_LN10(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *
     return E_NOTIMPL;
 }
 
+/* ECMA-262 3rd Edition    15.8.1.6 */
 static HRESULT Math_PI(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
         VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
 {
-    FIXME("\n");
-    return E_NOTIMPL;
+    TRACE("\n");
+    return math_constant(M_PI, flags, retv);
 }
 
 static HRESULT Math_SQRT2(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
@@ -105,11 +131,30 @@ static HRESULT Math_SQRT1_2(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAM
     return E_NOTIMPL;
 }
 
+/* ECMA-262 3rd Edition    15.8.2.12 */
 static HRESULT Math_abs(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
         VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
 {
-    FIXME("\n");
-    return E_NOTIMPL;
+    VARIANT v;
+    DOUBLE d;
+    HRESULT hres;
+
+    TRACE("\n");
+
+    if(!arg_cnt(dp)) {
+        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;
+
+    d = num_val(&v);
+    if(retv)
+        num_set_val(retv, d < 0.0 ? -d : d);
+    return S_OK;
 }
 
 static HRESULT Math_acos(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
@@ -140,11 +185,28 @@ static HRESULT Math_atan2(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS
     return E_NOTIMPL;
 }
 
+/* ECMA-262 3rd Edition    15.8.2.6 */
 static HRESULT Math_ceil(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
         VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
 {
-    FIXME("\n");
-    return E_NOTIMPL;
+    VARIANT v;
+    HRESULT hres;
+
+    TRACE("\n");
+
+    if(!arg_cnt(dp)) {
+        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;
+
+    if(retv)
+        num_set_val(retv, ceil(num_val(&v)));
+    return S_OK;
 }
 
 static HRESULT Math_cos(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
@@ -164,8 +226,24 @@ static HRESULT Math_exp(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *d
 static HRESULT Math_floor(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
         VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
 {
-    FIXME("\n");
-    return E_NOTIMPL;
+    VARIANT v;
+    HRESULT hres;
+
+    TRACE("\n");
+
+    if(!arg_cnt(dp)) {
+        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;
+
+    if(retv)
+        num_set_val(retv, floor(num_val(&v)));
+    return S_OK;
 }
 
 static HRESULT Math_log(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
@@ -175,39 +253,145 @@ static HRESULT Math_log(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *d
     return E_NOTIMPL;
 }
 
+/* ECMA-262 3rd Edition    15.8.2.11 */
 static HRESULT Math_max(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
         VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
 {
-    FIXME("\n");
-    return E_NOTIMPL;
+    DOUBLE max, d;
+    VARIANT v;
+    DWORD i;
+    HRESULT hres;
+
+    TRACE("\n");
+
+    if(!arg_cnt(dp)) {
+        if(retv)
+            num_set_inf(retv, FALSE);
+        return S_OK;
+    }
+
+    hres = to_number(dispex->ctx, get_arg(dp, 0), ei, &v);
+    if(FAILED(hres))
+        return hres;
+
+    max = num_val(&v);
+    for(i=1; i < arg_cnt(dp); i++) {
+        hres = to_number(dispex->ctx, get_arg(dp, i), ei, &v);
+        if(FAILED(hres))
+            return hres;
+
+        d = num_val(&v);
+        if(d > max || isnan(d))
+            max = d;
+    }
+
+    if(retv)
+        num_set_val(retv, max);
+    return S_OK;
 }
 
+/* ECMA-262 3rd Edition    15.8.2.12 */
 static HRESULT Math_min(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
         VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
 {
-    FIXME("\n");
-    return E_NOTIMPL;
+    DOUBLE min, d;
+    VARIANT v;
+    DWORD i;
+    HRESULT hres;
+
+    TRACE("\n");
+
+    if(!arg_cnt(dp)) {
+        if(retv)
+            num_set_inf(retv, TRUE);
+        return S_OK;
+    }
+
+    hres = to_number(dispex->ctx, get_arg(dp, 0), ei, &v);
+    if(FAILED(hres))
+        return hres;
+
+    min = num_val(&v);
+    for(i=1; i < arg_cnt(dp); i++) {
+        hres = to_number(dispex->ctx, get_arg(dp, i), ei, &v);
+        if(FAILED(hres))
+            return hres;
+
+        d = num_val(&v);
+        if(d < min || isnan(d))
+            min = d;
+    }
+
+    if(retv)
+        num_set_val(retv, min);
+    return S_OK;
 }
 
+/* ECMA-262 3rd Edition    15.8.2.13 */
 static HRESULT Math_pow(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
         VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
 {
-    FIXME("\n");
-    return E_NOTIMPL;
+    VARIANT x, y;
+    HRESULT hres;
+
+    TRACE("\n");
+
+    if(arg_cnt(dp) < 2) {
+        FIXME("unimplemented arg_cnt %d\n", arg_cnt(dp));
+        return E_NOTIMPL;
+    }
+
+    hres = to_number(dispex->ctx, get_arg(dp, 0), ei, &x);
+    if(FAILED(hres))
+        return hres;
+
+    hres = to_number(dispex->ctx, get_arg(dp, 1), ei, &y);
+    if(FAILED(hres))
+        return hres;
+
+    if(retv)
+        num_set_val(retv, pow(num_val(&x), num_val(&y)));
+    return S_OK;
 }
 
+/* ECMA-262 3rd Edition    15.8.2.14 */
 static HRESULT Math_random(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
         VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
 {
-    FIXME("\n");
-    return E_NOTIMPL;
+    UINT r;
+
+    TRACE("\n");
+
+    if(!RtlGenRandom(&r, sizeof(r)))
+        return E_UNEXPECTED;
+
+    if(retv)
+        num_set_val(retv, (DOUBLE)r/(DOUBLE)UINT_MAX);
+
+    return S_OK;
 }
 
+/* ECMA-262 3rd Edition    15.8.2.15 */
 static HRESULT Math_round(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
         VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
 {
-    FIXME("\n");
-    return E_NOTIMPL;
+    VARIANT v;
+    HRESULT hres;
+
+    TRACE("\n");
+
+    if(!arg_cnt(dp)) {
+        num_set_nan(retv);
+        return S_OK;
+    }
+
+    hres = to_number(dispex->ctx, get_arg(dp, 0), ei, &v);
+    if(FAILED(hres))
+        return hres;
+
+    if(retv)
+        num_set_val(retv, floor(num_val(&v)+0.5));
+    return S_OK;
 }
 
 static HRESULT Math_sin(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
@@ -233,10 +417,10 @@ static HRESULT Math_tan(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *d
 
 static const builtin_prop_t Math_props[] = {
     {EW,        Math_E,        0},
-    {LOG2EW,    Math_LOG2E,    0},
-    {LOG10EW,   Math_LOG10E,   0},
-    {LN2W,      Math_LN2,      0},
     {LN10W,     Math_LN10,     0},
+    {LN2W,      Math_LN2,      0},
+    {LOG10EW,   Math_LOG10E,   0},
+    {LOG2EW,    Math_LOG2E,    0},
     {PIW,       Math_PI,       0},
     {SQRT1_2W,  Math_SQRT1_2,  0},
     {SQRT2W,    Math_SQRT2,    0},
index 108cfff..d909cdb 100644 (file)
@@ -39,11 +39,39 @@ static const WCHAR propertyIsEnumerableW[] =
     {'p','r','o','p','e','r','t','y','I','s','E','n','u','m','e','r','a','b','l','e',0};
 static const WCHAR isPrototypeOfW[] = {'i','s','P','r','o','t','o','t','y','p','e','O','f',0};
 
+/* ECMA-262 3rd Edition    15.7.4.2 */
 static HRESULT Number_toString(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
         VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
 {
-    FIXME("\n");
-    return E_NOTIMPL;
+    NumberInstance *number;
+    BSTR str;
+    HRESULT hres;
+
+    TRACE("\n");
+
+    if(!is_class(dispex, JSCLASS_NUMBER)) {
+        FIXME("throw TypeError\n");
+        return E_FAIL;
+    }
+
+    number = (NumberInstance*)dispex;
+
+    if(arg_cnt(dp) != 0) {
+        FIXME("unsupported args\n");
+        return E_NOTIMPL;
+    }
+
+    hres = to_string(dispex->ctx, &number->num, ei, &str);
+    if(FAILED(hres))
+        return hres;
+
+    if(retv) {
+        V_VT(retv) = VT_BSTR;
+        V_BSTR(retv) = str;
+    }else {
+        SysFreeString(str);
+    }
+    return S_OK;
 }
 
 static HRESULT Number_toLocaleString(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
@@ -77,8 +105,18 @@ static HRESULT Number_toPrecision(DispatchEx *dispex, LCID lcid, WORD flags, DIS
 static HRESULT Number_valueOf(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
         VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
 {
-    FIXME("\n");
-    return E_NOTIMPL;
+    TRACE("\n");
+
+    if(!is_class(dispex, JSCLASS_NUMBER)) {
+        FIXME("throw TypeError\n");
+        return E_FAIL;
+    }
+
+    if(retv) {
+        NumberInstance *number = (NumberInstance*)dispex;
+        *retv = number->num;
+    }
+    return S_OK;
 }
 
 static HRESULT Number_hasOwnProperty(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
@@ -105,8 +143,19 @@ static HRESULT Number_isPrototypeOf(DispatchEx *dispex, LCID lcid, WORD flags, D
 static HRESULT Number_value(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
         VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
 {
-    FIXME("\n");
-    return E_NOTIMPL;
+    NumberInstance *number = (NumberInstance*)dispex;
+
+    switch(flags) {
+    case DISPATCH_PROPERTYGET:
+        *retv = number->num;
+        break;
+
+    default:
+        FIXME("flags %x\n", flags);
+        return E_NOTIMPL;
+    }
+
+    return S_OK;
 }
 
 static const builtin_prop_t Number_props[] = {
@@ -133,15 +182,66 @@ static const builtin_info_t Number_info = {
 static HRESULT NumberConstr_value(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
         VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
 {
-    FIXME("\n");
-    return E_NOTIMPL;
+    VARIANT num;
+    HRESULT hres;
+
+    TRACE("\n");
+
+    switch(flags) {
+    case INVOKE_FUNC:
+        if(!arg_cnt(dp)) {
+            if(retv) {
+                V_VT(retv) = VT_I4;
+                V_I4(retv) = 0;
+            }
+            return S_OK;
+        }
+
+        hres = to_number(dispex->ctx, get_arg(dp, 0), ei, &num);
+        if(FAILED(hres))
+            return hres;
+
+        if(retv)
+            *retv = num;
+        break;
+
+    case DISPATCH_CONSTRUCT: {
+        DispatchEx *obj;
+
+        if(arg_cnt(dp)) {
+            hres = to_number(dispex->ctx, get_arg(dp, 0), ei, &num);
+            if(FAILED(hres))
+                return hres;
+        }else {
+            V_VT(&num) = VT_I4;
+            V_I4(&num) = 0;
+        }
+
+        hres = create_number(dispex->ctx, &num, &obj);
+        if(FAILED(hres))
+            return hres;
+
+        V_VT(retv) = VT_DISPATCH;
+        V_DISPATCH(retv) = (IDispatch*)_IDispatchEx_(obj);
+        break;
+    }
+    default:
+        FIXME("unimplemented flags %x\n", flags);
+        return E_NOTIMPL;
+    }
+
+    return S_OK;
 }
 
 static HRESULT alloc_number(script_ctx_t *ctx, BOOL use_constr, NumberInstance **ret)
 {
-    NumberInstance *number = heap_alloc_zero(sizeof(NumberInstance));
+    NumberInstance *number;
     HRESULT hres;
 
+    number = heap_alloc_zero(sizeof(NumberInstance));
+    if(!number)
+        return E_OUTOFMEMORY;
+
     if(use_constr)
         hres = init_dispex_from_constr(&number->dispex, ctx, &Number_info, ctx->number_constr);
     else
@@ -162,6 +262,7 @@ HRESULT create_number_constr(script_ctx_t *ctx, DispatchEx **ret)
     if(FAILED(hres))
         return hres;
 
+    V_VT(&number->num) = VT_I4;
     hres = create_builtin_function(ctx, NumberConstr_value, PROPF_CONSTR, &number->dispex, ret);
 
     jsdisp_release(&number->dispex);
index 2f021f7..02d80de 100644 (file)
@@ -30,6 +30,8 @@ static const WCHAR propertyIsEnumerableW[] =
     {'p','r','o','p','e','r','t','y','I','s','E','n','u','m','e','r','a','b','l','e',0};
 static const WCHAR isPrototypeOfW[] = {'i','s','P','r','o','t','o','t','y','p','e','O','f',0};
 
+static const WCHAR default_valueW[] = {'[','o','b','j','e','c','t',' ','O','b','j','e','c','t',']',0};
+
 static HRESULT Object_toString(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
         VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
 {
@@ -75,8 +77,21 @@ static HRESULT Object_isPrototypeOf(DispatchEx *dispex, LCID lcid, WORD flags, D
 static HRESULT Object_value(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
         VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
 {
-    FIXME("\n");
-    return E_NOTIMPL;
+    TRACE("\n");
+
+    switch(flags) {
+    case DISPATCH_PROPERTYGET:
+        V_VT(retv) = VT_BSTR;
+        V_BSTR(retv) = SysAllocString(default_valueW);
+        if(!V_BSTR(retv))
+            return E_OUTOFMEMORY;
+        break;
+    default:
+        FIXME("unimplemented flags %x\n", flags);
+        return E_NOTIMPL;
+    }
+
+    return S_OK;
 }
 
 static void Object_destructor(DispatchEx *dispex)
index f946a69..a2fd725 100644 (file)
      kIF = 266,
      kFINALLY = 267,
      kFOR = 268,
-     kFUNCTION = 269,
-     kIN = 270,
-     kINSTANCEOF = 271,
-     kNEW = 272,
-     kNULL = 273,
-     kUNDEFINED = 274,
-     kRETURN = 275,
-     kSWITCH = 276,
-     kTHIS = 277,
-     kTHROW = 278,
-     kTRUE = 279,
-     kFALSE = 280,
-     kTRY = 281,
-     kTYPEOF = 282,
-     kVAR = 283,
-     kVOID = 284,
-     kWHILE = 285,
-     kWITH = 286,
-     tANDAND = 287,
-     tOROR = 288,
-     tINC = 289,
-     tDEC = 290,
+     kIN = 269,
+     kINSTANCEOF = 270,
+     kNEW = 271,
+     kNULL = 272,
+     kUNDEFINED = 273,
+     kRETURN = 274,
+     kSWITCH = 275,
+     kTHIS = 276,
+     kTHROW = 277,
+     kTRUE = 278,
+     kFALSE = 279,
+     kTRY = 280,
+     kTYPEOF = 281,
+     kVAR = 282,
+     kVOID = 283,
+     kWHILE = 284,
+     kWITH = 285,
+     tANDAND = 286,
+     tOROR = 287,
+     tINC = 288,
+     tDEC = 289,
+     kFUNCTION = 290,
      tIdentifier = 291,
      tAssignOper = 292,
      tEqOper = 293,
      tShiftOper = 294,
      tRelOper = 295,
      tNumericLiteral = 296,
-     tStringLiteral = 297
+     tStringLiteral = 297,
+     LOWER_THAN_ELSE = 298
    };
 #endif
 /* Tokens.  */
 #define kIF 266
 #define kFINALLY 267
 #define kFOR 268
-#define kFUNCTION 269
-#define kIN 270
-#define kINSTANCEOF 271
-#define kNEW 272
-#define kNULL 273
-#define kUNDEFINED 274
-#define kRETURN 275
-#define kSWITCH 276
-#define kTHIS 277
-#define kTHROW 278
-#define kTRUE 279
-#define kFALSE 280
-#define kTRY 281
-#define kTYPEOF 282
-#define kVAR 283
-#define kVOID 284
-#define kWHILE 285
-#define kWITH 286
-#define tANDAND 287
-#define tOROR 288
-#define tINC 289
-#define tDEC 290
+#define kIN 269
+#define kINSTANCEOF 270
+#define kNEW 271
+#define kNULL 272
+#define kUNDEFINED 273
+#define kRETURN 274
+#define kSWITCH 275
+#define kTHIS 276
+#define kTHROW 277
+#define kTRUE 278
+#define kFALSE 279
+#define kTRY 280
+#define kTYPEOF 281
+#define kVAR 282
+#define kVOID 283
+#define kWHILE 284
+#define kWITH 285
+#define tANDAND 286
+#define tOROR 287
+#define tINC 288
+#define tDEC 289
+#define kFUNCTION 290
 #define tIdentifier 291
 #define tAssignOper 292
 #define tEqOper 293
 #define tRelOper 295
 #define tNumericLiteral 296
 #define tStringLiteral 297
+#define LOWER_THAN_ELSE 298
 
 
 
 #include "jscript.h"
 #include "engine.h"
 
-#include "wine/debug.h"
-
-WINE_DEFAULT_DEBUG_CHANNEL(jscript);
-
 #define YYLEX_PARAM ctx
 #define YYPARSE_PARAM ctx
 
 static int parser_error(const char*);
 static BOOL allow_auto_semicolon(parser_ctx_t*);
 static void program_parsed(parser_ctx_t*,source_elements_t*);
+static source_elements_t *function_body_parsed(parser_ctx_t*,source_elements_t*);
 
 typedef struct _statement_list_t {
     statement_t *head;
@@ -246,8 +245,8 @@ struct statement_list_t {
    statement_t *tail;
 };
 
-statement_list_t *new_statement_list(parser_ctx_t*,statement_t*);
-statement_list_t *statement_list_add(statement_list_t*,statement_t*);
+static statement_list_t *new_statement_list(parser_ctx_t*,statement_t*);
+static statement_list_t *statement_list_add(statement_list_t*,statement_t*);
 
 typedef struct _parameter_list_t {
     parameter_t *head;
@@ -257,7 +256,14 @@ typedef struct _parameter_list_t {
 static parameter_list_t *new_parameter_list(parser_ctx_t*,const WCHAR*);
 static parameter_list_t *parameter_list_add(parser_ctx_t*,parameter_list_t*,const WCHAR*);
 
-static expression_t *new_function_expression(parser_ctx_t*,const WCHAR*,parameter_list_t*,source_elements_t*);
+static void push_func(parser_ctx_t*);
+static inline void pop_func(parser_ctx_t *ctx)
+{
+    ctx->func_stack = ctx->func_stack->next;
+}
+
+static expression_t *new_function_expression(parser_ctx_t*,const WCHAR*,parameter_list_t*,
+        source_elements_t*,const WCHAR*,DWORD);
 static expression_t *new_binary_expression(parser_ctx_t*,expression_type_t,expression_t*,expression_t*);
 static expression_t *new_unary_expression(parser_ctx_t*,expression_type_t,expression_t*);
 static expression_t *new_conditional_expression(parser_ctx_t*,expression_t*,expression_t*,expression_t*);
@@ -271,10 +277,8 @@ static expression_t *new_literal_expression(parser_ctx_t*,literal_t*);
 static expression_t *new_array_literal_expression(parser_ctx_t*,element_list_t*,int);
 static expression_t *new_prop_and_value_expression(parser_ctx_t*,property_list_t*);
 
-static function_declaration_t *new_function_declaration(parser_ctx_t*,const WCHAR*,parameter_list_t*,source_elements_t*);
 static source_elements_t *new_source_elements(parser_ctx_t*);
 static source_elements_t *source_elements_add_statement(source_elements_t*,statement_t*);
-static source_elements_t *source_elements_add_function(source_elements_t*,function_declaration_t*);
 
 
 
@@ -297,9 +301,10 @@ static source_elements_t *source_elements_add_function(source_elements_t*,functi
 #endif
 
 #if ! defined (YYSTYPE) && ! defined (YYSTYPE_IS_DECLARED)
-#line 147 "parser.y"
+#line 149 "parser.y"
 typedef union YYSTYPE {
     int                     ival;
+    const WCHAR             *srcptr;
     LPCWSTR                 wstr;
     literal_t               *literal;
     struct _argument_list_t *argument_list;
@@ -309,7 +314,6 @@ typedef union YYSTYPE {
     struct _element_list_t  *element_list;
     expression_t            *expr;
     const WCHAR            *identifier;
-    function_declaration_t  *function_declaration;
     struct _parameter_list_t *parameter_list;
     struct _property_list_t *property_list;
     source_elements_t       *source_elements;
@@ -319,7 +323,7 @@ typedef union YYSTYPE {
     variable_declaration_t  *variable_declaration;
 } YYSTYPE;
 /* Line 196 of yacc.c.  */
-#line 323 "parser.tab.c"
+#line 327 "parser.tab.c"
 # define yystype YYSTYPE /* obsolescent; will be withdrawn */
 # define YYSTYPE_IS_DECLARED 1
 # define YYSTYPE_IS_TRIVIAL 1
@@ -331,7 +335,7 @@ typedef union YYSTYPE {
 
 
 /* Line 219 of yacc.c.  */
-#line 335 "parser.tab.c"
+#line 339 "parser.tab.c"
 
 #if ! defined (YYSIZE_T) && defined (__SIZE_TYPE__)
 # define YYSIZE_T __SIZE_TYPE__
@@ -482,20 +486,20 @@ union yyalloc
 /* YYFINAL -- State number of the termination state. */
 #define YYFINAL  3
 /* YYLAST -- Last index in YYTABLE.  */
-#define YYLAST   773
+#define YYLAST   818
 
 /* YYNTOKENS -- Number of terminals. */
-#define YYNTOKENS  65
+#define YYNTOKENS  66
 /* YYNNTS -- Number of nonterminals. */
 #define YYNNTS  85
 /* YYNRULES -- Number of rules. */
-#define YYNRULES  196
+#define YYNRULES  197
 /* YYNRULES -- Number of states. */
-#define YYNSTATES  360
+#define YYNSTATES  356
 
 /* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX.  */
 #define YYUNDEFTOK  2
-#define YYMAXUTOK   297
+#define YYMAXUTOK   298
 
 #define YYTRANSLATE(YYX)                                               \
   ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
@@ -506,16 +510,16 @@ static const unsigned char yytranslate[] =
        0,     2,     2,     2,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,    61,     2,     2,     2,    59,    54,     2,
-      43,    44,    57,    55,    47,    56,    64,    58,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,    50,    49,
-       2,    48,     2,    51,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,    62,     2,     2,     2,    60,    55,     2,
+      45,    46,    58,    56,    48,    57,    65,    59,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,    51,    50,
+       2,    49,     2,    52,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,    62,     2,    63,    53,     2,     2,     2,     2,     2,
+       2,    63,     2,    64,    54,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,    45,    52,    46,    60,     2,     2,     2,
+       2,     2,     2,    47,    53,    35,    61,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
@@ -532,7 +536,7 @@ static const unsigned char yytranslate[] =
        5,     6,     7,     8,     9,    10,    11,    12,    13,    14,
       15,    16,    17,    18,    19,    20,    21,    22,    23,    24,
       25,    26,    27,    28,    29,    30,    31,    32,    33,    34,
-      35,    36,    37,    38,    39,    40,    41,    42
+      36,    37,    38,    39,    40,    41,    42,    43,    44
 };
 
 #if YYDEBUG
@@ -540,119 +544,119 @@ static const unsigned char yytranslate[] =
    YYRHS.  */
 static const unsigned short int yyprhs[] =
 {
-       0,     0,     3,     5,     6,     9,    12,    21,    30,    32,
-      34,    38,    39,    41,    43,    45,    47,    49,    51,    53,
-      55,    57,    59,    61,    63,    65,    67,    69,    71,    74,
-      75,    77,    81,    85,    87,    91,    93,    97,   100,   103,
-     104,   106,   109,   110,   112,   115,   117,   120,   128,   134,
-     142,   148,   158,   169,   177,   186,   190,   194,   198,   204,
-     208,   214,   218,   224,   225,   227,   229,   232,   237,   241,
-     245,   249,   253,   258,   264,   267,   268,   270,   272,   276,
-     277,   279,   281,   285,   287,   291,   295,   297,   301,   305,
-     307,   313,   315,   321,   323,   327,   329,   333,   335,   339,
-     341,   345,   347,   351,   353,   357,   359,   363,   365,   369,
-     371,   375,   377,   381,   383,   387,   389,   393,   395,   399,
-     403,   407,   409,   413,   417,   419,   423,   425,   429,   433,
-     435,   439,   443,   447,   449,   452,   455,   458,   461,   464,
-     467,   470,   473,   476,   478,   481,   484,   486,   488,   490,
-     493,   495,   497,   502,   506,   510,   513,   516,   521,   525,
-     528,   532,   534,   538,   540,   542,   544,   546,   548,   552,
-     556,   560,   566,   569,   574,   576,   579,   580,   582,   585,
-     589,   593,   599,   601,   603,   605,   606,   608,   610,   612,
-     614,   616,   618,   620,   622,   624,   626
+       0,     0,     3,     5,     6,     9,    18,    20,    22,    24,
+      28,    29,    31,    33,    35,    37,    39,    41,    43,    45,
+      47,    49,    51,    53,    55,    57,    59,    61,    64,    65,
+      67,    71,    74,    78,    80,    84,    86,    90,    93,    96,
+      97,    99,   102,   103,   105,   108,   110,   113,   121,   127,
+     135,   141,   151,   162,   170,   179,   183,   187,   191,   197,
+     201,   207,   211,   217,   218,   220,   222,   225,   230,   234,
+     238,   242,   246,   251,   257,   260,   261,   263,   265,   269,
+     270,   272,   274,   278,   280,   284,   288,   290,   294,   298,
+     300,   306,   308,   314,   316,   320,   322,   326,   328,   332,
+     334,   338,   340,   344,   346,   350,   352,   356,   358,   362,
+     364,   368,   370,   374,   376,   380,   382,   386,   388,   392,
+     396,   400,   402,   406,   410,   412,   416,   418,   422,   426,
+     428,   432,   436,   440,   442,   445,   448,   451,   454,   457,
+     460,   463,   466,   469,   471,   474,   477,   479,   481,   483,
+     486,   488,   490,   495,   499,   503,   506,   509,   514,   518,
+     521,   525,   527,   531,   533,   535,   537,   539,   541,   545,
+     548,   552,   556,   562,   565,   570,   572,   575,   576,   578,
+     581,   585,   589,   595,   597,   599,   601,   602,   604,   606,
+     608,   610,   612,   614,   616,   618,   620,   622
 };
 
 /* YYRHS -- A `-1'-separated list of the rules' RHS. */
 static const short int yyrhs[] =
 {
-      66,     0,    -1,    67,    -1,    -1,    67,    73,    -1,    67,
-      68,    -1,    14,    36,    43,    72,    44,    45,    70,    46,
-      -1,    14,   146,    43,    72,    44,    45,    70,    46,    -1,
-      67,    -1,    36,    -1,    71,    47,    36,    -1,    -1,    71,
-      -1,    76,    -1,    77,    -1,    86,    -1,    87,    -1,    88,
-      -1,    89,    -1,    90,    -1,    91,    -1,    92,    -1,    93,
-      -1,    94,    -1,    95,    -1,   101,    -1,   102,    -1,    73,
-      -1,    74,    73,    -1,    -1,    74,    -1,    45,    75,    46,
-      -1,    28,    78,   149,    -1,    80,    -1,    78,    47,    80,
-      -1,    81,    -1,    79,    47,    81,    -1,    36,    82,    -1,
-      36,    84,    -1,    -1,    83,    -1,    48,   109,    -1,    -1,
-      85,    -1,    48,   110,    -1,    49,    -1,   106,   149,    -1,
-      11,    43,   106,    44,    73,    10,    73,    -1,    11,    43,
-     106,    44,    73,    -1,     9,    73,    30,    43,   106,    44,
-      49,    -1,    30,    43,   106,    44,    73,    -1,    13,    43,
-     107,    49,   105,    49,   105,    44,    73,    -1,    13,    43,
-      28,    79,    49,   105,    49,   105,    44,    73,    -1,    13,
-      43,   132,    15,   106,    44,    73,    -1,    13,    43,    28,
-      81,    15,   106,    44,    73,    -1,     6,   146,   149,    -1,
-       3,   146,   149,    -1,    20,   105,   149,    -1,    31,    43,
-     106,    44,    73,    -1,    36,    50,    73,    -1,    21,    43,
-     106,    44,    96,    -1,    45,    97,    46,    -1,    45,    97,
-     100,    97,    46,    -1,    -1,    98,    -1,    99,    -1,    98,
-      99,    -1,     4,   106,    50,    75,    -1,     7,    50,    75,
-      -1,    23,   106,   149,    -1,    26,    76,   103,    -1,    26,
-      76,   104,    -1,    26,    76,   103,   104,    -1,     5,    43,
-      36,    44,    76,    -1,    12,    76,    -1,    -1,   106,    -1,
-     109,    -1,   106,    47,   109,    -1,    -1,   108,    -1,   110,
-      -1,   108,    47,   110,    -1,   111,    -1,   132,    48,   109,
-      -1,   132,    37,   109,    -1,   112,    -1,   132,    48,   110,
-      -1,   132,    37,   110,    -1,   113,    -1,   113,    51,   109,
-      50,   109,    -1,   114,    -1,   114,    51,   110,    50,   110,
-      -1,   115,    -1,   113,    33,   115,    -1,   116,    -1,   114,
-      33,   116,    -1,   117,    -1,   115,    32,   117,    -1,   118,
-      -1,   116,    32,   118,    -1,   119,    -1,   117,    52,   119,
-      -1,   120,    -1,   118,    52,   120,    -1,   121,    -1,   119,
-      53,   121,    -1,   122,    -1,   120,    53,   122,    -1,   123,
-      -1,   121,    54,   123,    -1,   124,    -1,   122,    54,   124,
-      -1,   125,    -1,   123,    38,   125,    -1,   126,    -1,   124,
-      38,   126,    -1,   127,    -1,   125,    40,   127,    -1,   125,
-      16,   127,    -1,   125,    15,   127,    -1,   127,    -1,   126,
-      40,   127,    -1,   126,    16,   127,    -1,   128,    -1,   127,
-      39,   128,    -1,   129,    -1,   128,    55,   129,    -1,   128,
-      56,   129,    -1,   130,    -1,   129,    57,   130,    -1,   129,
-      58,   130,    -1,   129,    59,   130,    -1,   131,    -1,     8,
-     130,    -1,    29,   130,    -1,    27,   130,    -1,    34,   130,
-      -1,    35,   130,    -1,    55,   130,    -1,    56,   130,    -1,
-      60,   130,    -1,    61,   130,    -1,   132,    -1,   132,    34,
-      -1,   132,    35,    -1,   133,    -1,   135,    -1,   134,    -1,
-      17,   133,    -1,   138,    -1,    69,    -1,   134,    62,   106,
-      63,    -1,   134,    64,    36,    -1,    17,   134,   136,    -1,
-     134,   136,    -1,   135,   136,    -1,   135,    62,   106,    63,
-      -1,   135,    64,    36,    -1,    43,    44,    -1,    43,   137,
-      44,    -1,   109,    -1,   137,    47,   109,    -1,    22,    -1,
-      36,    -1,   147,    -1,   139,    -1,   143,    -1,    43,   106,
-      44,    -1,    62,   142,    63,    -1,    62,   140,    63,    -1,
-      62,   140,    47,   142,    63,    -1,   142,   109,    -1,   140,
-      47,   142,   109,    -1,    47,    -1,   141,    47,    -1,    -1,
-     141,    -1,    45,    46,    -1,    45,   144,    46,    -1,   145,
-      50,   109,    -1,   144,    47,   145,    50,   109,    -1,    36,
-      -1,    42,    -1,    41,    -1,    -1,    36,    -1,    18,    -1,
-      19,    -1,   148,    -1,    41,    -1,    42,    -1,    58,    -1,
-      24,    -1,    25,    -1,    49,    -1,     1,    -1
+      67,     0,    -1,    68,    -1,    -1,    68,    74,    -1,    70,
+     147,    45,    73,    46,    47,    71,    35,    -1,    36,    -1,
+      68,    -1,    37,    -1,    72,    48,    37,    -1,    -1,    72,
+      -1,    77,    -1,    78,    -1,    87,    -1,    88,    -1,    89,
+      -1,    90,    -1,    91,    -1,    92,    -1,    93,    -1,    94,
+      -1,    95,    -1,    96,    -1,   102,    -1,   103,    -1,    74,
+      -1,    75,    74,    -1,    -1,    75,    -1,    47,    75,    35,
+      -1,    47,    35,    -1,    27,    79,   150,    -1,    81,    -1,
+      79,    48,    81,    -1,    82,    -1,    80,    48,    82,    -1,
+      37,    83,    -1,    37,    85,    -1,    -1,    84,    -1,    49,
+     110,    -1,    -1,    86,    -1,    49,   111,    -1,    50,    -1,
+     107,   150,    -1,    11,    45,   107,    46,    74,    10,    74,
+      -1,    11,    45,   107,    46,    74,    -1,     9,    74,    29,
+      45,   107,    46,    50,    -1,    29,    45,   107,    46,    74,
+      -1,    13,    45,   108,    50,   106,    50,   106,    46,    74,
+      -1,    13,    45,    27,    80,    50,   106,    50,   106,    46,
+      74,    -1,    13,    45,   133,    14,   107,    46,    74,    -1,
+      13,    45,    27,    82,    14,   107,    46,    74,    -1,     6,
+     147,   150,    -1,     3,   147,   150,    -1,    19,   106,   150,
+      -1,    30,    45,   107,    46,    74,    -1,    37,    51,    74,
+      -1,    20,    45,   107,    46,    97,    -1,    47,    98,    35,
+      -1,    47,    98,   101,    98,    35,    -1,    -1,    99,    -1,
+     100,    -1,    99,   100,    -1,     4,   107,    51,    76,    -1,
+       7,    51,    76,    -1,    22,   107,   150,    -1,    25,    77,
+     104,    -1,    25,    77,   105,    -1,    25,    77,   104,   105,
+      -1,     5,    45,    37,    46,    77,    -1,    12,    77,    -1,
+      -1,   107,    -1,   110,    -1,   107,    48,   110,    -1,    -1,
+     109,    -1,   111,    -1,   109,    48,   111,    -1,   112,    -1,
+     133,    49,   110,    -1,   133,    38,   110,    -1,   113,    -1,
+     133,    49,   111,    -1,   133,    38,   111,    -1,   114,    -1,
+     114,    52,   110,    51,   110,    -1,   115,    -1,   115,    52,
+     111,    51,   111,    -1,   116,    -1,   114,    32,   116,    -1,
+     117,    -1,   115,    32,   117,    -1,   118,    -1,   116,    31,
+     118,    -1,   119,    -1,   117,    31,   119,    -1,   120,    -1,
+     118,    53,   120,    -1,   121,    -1,   119,    53,   121,    -1,
+     122,    -1,   120,    54,   122,    -1,   123,    -1,   121,    54,
+     123,    -1,   124,    -1,   122,    55,   124,    -1,   125,    -1,
+     123,    55,   125,    -1,   126,    -1,   124,    39,   126,    -1,
+     127,    -1,   125,    39,   127,    -1,   128,    -1,   126,    41,
+     128,    -1,   126,    15,   128,    -1,   126,    14,   128,    -1,
+     128,    -1,   127,    41,   128,    -1,   127,    15,   128,    -1,
+     129,    -1,   128,    40,   129,    -1,   130,    -1,   129,    56,
+     130,    -1,   129,    57,   130,    -1,   131,    -1,   130,    58,
+     131,    -1,   130,    59,   131,    -1,   130,    60,   131,    -1,
+     132,    -1,     8,   131,    -1,    28,   131,    -1,    26,   131,
+      -1,    33,   131,    -1,    34,   131,    -1,    56,   131,    -1,
+      57,   131,    -1,    61,   131,    -1,    62,   131,    -1,   133,
+      -1,   133,    33,    -1,   133,    34,    -1,   134,    -1,   136,
+      -1,   135,    -1,    16,   134,    -1,   139,    -1,    69,    -1,
+     135,    63,   107,    64,    -1,   135,    65,    37,    -1,    16,
+     135,   137,    -1,   135,   137,    -1,   136,   137,    -1,   136,
+      63,   107,    64,    -1,   136,    65,    37,    -1,    45,    46,
+      -1,    45,   138,    46,    -1,   110,    -1,   138,    48,   110,
+      -1,    21,    -1,    37,    -1,   148,    -1,   140,    -1,   144,
+      -1,    45,   107,    46,    -1,    63,    64,    -1,    63,   142,
+      64,    -1,    63,   141,    64,    -1,    63,   141,    48,   143,
+      64,    -1,   143,   110,    -1,   141,    48,   143,   110,    -1,
+      48,    -1,   142,    48,    -1,    -1,   142,    -1,    47,    35,
+      -1,    47,   145,    35,    -1,   146,    51,   110,    -1,   145,
+      48,   146,    51,   110,    -1,    37,    -1,    43,    -1,    42,
+      -1,    -1,    37,    -1,    17,    -1,    18,    -1,   149,    -1,
+      42,    -1,    43,    -1,    59,    -1,    23,    -1,    24,    -1,
+      50,    -1,     1,    -1
 };
 
 /* YYRLINE[YYN] -- source line where rule number YYN was defined.  */
 static const unsigned short int yyrline[] =
 {
-       0,   247,   247,   251,   252,   254,   259,   264,   269,   273,
-     274,   279,   280,   284,   285,   286,   287,   288,   289,   290,
-     291,   292,   293,   294,   295,   296,   297,   301,   302,   307,
-     308,   312,   317,   322,   323,   328,   330,   335,   340,   345,
-     346,   350,   355,   356,   360,   365,   369,   374,   376,   381,
-     383,   385,   387,   389,   391,   396,   401,   406,   411,   416,
-     421,   426,   428,   433,   434,   438,   439,   444,   449,   454,
-     459,   460,   461,   466,   471,   475,   476,   480,   481,   486,
-     487,   491,   493,   498,   499,   501,   506,   508,   510,   515,
-     516,   521,   523,   528,   529,   534,   536,   541,   542,   547,
-     549,   554,   555,   560,   562,   567,   568,   573,   575,   580,
-     581,   586,   588,   593,   594,   599,   600,   605,   606,   608,
-     610,   615,   616,   618,   623,   624,   629,   631,   633,   638,
-     639,   641,   643,   648,   649,   651,   652,   654,   655,   656,
-     657,   658,   659,   663,   665,   667,   673,   674,   678,   679,
-     683,   684,   685,   687,   689,   694,   696,   698,   700,   705,
-     706,   710,   711,   716,   717,   718,   719,   720,   721,   725,
-     726,   727,   732,   734,   739,   740,   744,   745,   749,   750,
-     755,   757,   762,   763,   764,   768,   769,   773,   774,   775,
-     776,   777,   778,   783,   784,   787,   788
+       0,   254,   254,   258,   259,   264,   268,   272,   276,   277,
+     282,   283,   287,   288,   289,   290,   291,   292,   293,   294,
+     295,   296,   297,   298,   299,   300,   304,   305,   310,   311,
+     315,   316,   320,   325,   326,   331,   333,   338,   343,   348,
+     349,   353,   358,   359,   363,   368,   372,   377,   379,   384,
+     386,   388,   390,   392,   394,   399,   404,   409,   414,   419,
+     424,   429,   431,   436,   437,   441,   442,   447,   452,   457,
+     462,   463,   464,   469,   474,   478,   479,   483,   484,   489,
+     490,   494,   496,   501,   502,   504,   509,   511,   513,   518,
+     519,   524,   526,   531,   532,   537,   539,   544,   545,   550,
+     552,   557,   558,   563,   565,   570,   571,   576,   578,   583,
+     584,   589,   591,   596,   597,   602,   603,   608,   609,   611,
+     613,   618,   619,   621,   626,   627,   632,   634,   636,   641,
+     642,   644,   646,   651,   652,   654,   655,   657,   658,   659,
+     660,   661,   662,   666,   668,   670,   676,   677,   681,   682,
+     686,   687,   688,   690,   692,   697,   699,   701,   703,   708,
+     709,   713,   714,   719,   720,   721,   722,   723,   724,   728,
+     729,   730,   731,   736,   738,   743,   744,   748,   749,   753,
+     754,   759,   761,   766,   767,   768,   772,   773,   777,   778,
+     779,   780,   781,   782,   787,   788,   791,   792
 };
 #endif
 
@@ -662,28 +666,28 @@ static const unsigned short int yyrline[] =
 static const char *const yytname[] =
 {
   "$end", "error", "$undefined", "kBREAK", "kCASE", "kCATCH", "kCONTINUE",
-  "kDEFAULT", "kDELETE", "kDO", "kELSE", "kIF", "kFINALLY", "kFOR",
-  "kFUNCTION", "kIN", "kINSTANCEOF", "kNEW", "kNULL", "kUNDEFINED",
-  "kRETURN", "kSWITCH", "kTHIS", "kTHROW", "kTRUE", "kFALSE", "kTRY",
-  "kTYPEOF", "kVAR", "kVOID", "kWHILE", "kWITH", "tANDAND", "tOROR",
-  "tINC", "tDEC", "tIdentifier", "tAssignOper", "tEqOper", "tShiftOper",
-  "tRelOper", "tNumericLiteral", "tStringLiteral", "'('", "')'", "'{'",
-  "'}'", "','", "'='", "';'", "':'", "'?'", "'|'", "'^'", "'&'", "'+'",
-  "'-'", "'*'", "'/'", "'%'", "'~'", "'!'", "'['", "']'", "'.'", "$accept",
-  "Program", "SourceElements", "FunctionDeclaration", "FunctionExpression",
-  "FunctionBody", "FormalParameterList", "FormalParameterList_opt",
-  "Statement", "StatementList", "StatementList_opt", "Block",
-  "VariableStatement", "VariableDeclarationList",
-  "VariableDeclarationListNoIn", "VariableDeclaration",
-  "VariableDeclarationNoIn", "Initialiser_opt", "Initialiser",
-  "InitialiserNoIn_opt", "InitialiserNoIn", "EmptyStatement",
-  "ExpressionStatement", "IfStatement", "IterationStatement",
-  "ContinueStatement", "BreakStatement", "ReturnStatement",
-  "WithStatement", "LabelledStatement", "SwitchStatement", "CaseBlock",
-  "CaseClausules_opt", "CaseClausules", "CaseClausule", "DefaultClausule",
-  "ThrowStatement", "TryStatement", "Catch", "Finally", "Expression_opt",
-  "Expression", "ExpressionNoIn_opt", "ExpressionNoIn",
-  "AssignmentExpression", "AssignmentExpressionNoIn",
+  "kDEFAULT", "kDELETE", "kDO", "kELSE", "kIF", "kFINALLY", "kFOR", "kIN",
+  "kINSTANCEOF", "kNEW", "kNULL", "kUNDEFINED", "kRETURN", "kSWITCH",
+  "kTHIS", "kTHROW", "kTRUE", "kFALSE", "kTRY", "kTYPEOF", "kVAR", "kVOID",
+  "kWHILE", "kWITH", "tANDAND", "tOROR", "tINC", "tDEC", "'}'",
+  "kFUNCTION", "tIdentifier", "tAssignOper", "tEqOper", "tShiftOper",
+  "tRelOper", "tNumericLiteral", "tStringLiteral", "LOWER_THAN_ELSE",
+  "'('", "')'", "'{'", "','", "'='", "';'", "':'", "'?'", "'|'", "'^'",
+  "'&'", "'+'", "'-'", "'*'", "'/'", "'%'", "'~'", "'!'", "'['", "']'",
+  "'.'", "$accept", "Program", "SourceElements", "FunctionExpression",
+  "KFunction", "FunctionBody", "FormalParameterList",
+  "FormalParameterList_opt", "Statement", "StatementList",
+  "StatementList_opt", "Block", "VariableStatement",
+  "VariableDeclarationList", "VariableDeclarationListNoIn",
+  "VariableDeclaration", "VariableDeclarationNoIn", "Initialiser_opt",
+  "Initialiser", "InitialiserNoIn_opt", "InitialiserNoIn",
+  "EmptyStatement", "ExpressionStatement", "IfStatement",
+  "IterationStatement", "ContinueStatement", "BreakStatement",
+  "ReturnStatement", "WithStatement", "LabelledStatement",
+  "SwitchStatement", "CaseBlock", "CaseClausules_opt", "CaseClausules",
+  "CaseClausule", "DefaultClausule", "ThrowStatement", "TryStatement",
+  "Catch", "Finally", "Expression_opt", "Expression", "ExpressionNoIn_opt",
+  "ExpressionNoIn", "AssignmentExpression", "AssignmentExpressionNoIn",
   "ConditionalExpression", "ConditionalExpressionNoIn",
   "LogicalORExpression", "LogicalORExpressionNoIn", "LogicalANDExpression",
   "LogicalANDExpressionNoIn", "BitwiseORExpression",
@@ -709,45 +713,45 @@ static const unsigned short int yytoknum[] =
        0,   256,   257,   258,   259,   260,   261,   262,   263,   264,
      265,   266,   267,   268,   269,   270,   271,   272,   273,   274,
      275,   276,   277,   278,   279,   280,   281,   282,   283,   284,
-     285,   286,   287,   288,   289,   290,   291,   292,   293,   294,
-     295,   296,   297,    40,    41,   123,   125,    44,    61,    59,
-      58,    63,   124,    94,    38,    43,    45,    42,    47,    37,
-     126,    33,    91,    93,    46
+     285,   286,   287,   288,   289,   125,   290,   291,   292,   293,
+     294,   295,   296,   297,   298,    40,    41,   123,    44,    61,
+      59,    58,    63,   124,    94,    38,    43,    45,    42,    47,
+      37,   126,    33,    91,    93,    46
 };
 # endif
 
 /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives.  */
 static const unsigned char yyr1[] =
 {
-       0,    65,    66,    67,    67,    67,    68,    69,    70,    71,
-      71,    72,    72,    73,    73,    73,    73,    73,    73,    73,
-      73,    73,    73,    73,    73,    73,    73,    74,    74,    75,
-      75,    76,    77,    78,    78,    79,    79,    80,    81,    82,
-      82,    83,    84,    84,    85,    86,    87,    88,    88,    89,
-      89,    89,    89,    89,    89,    90,    91,    92,    93,    94,
-      95,    96,    96,    97,    97,    98,    98,    99,   100,   101,
-     102,   102,   102,   103,   104,   105,   105,   106,   106,   107,
-     107,   108,   108,   109,   109,   109,   110,   110,   110,   111,
-     111,   112,   112,   113,   113,   114,   114,   115,   115,   116,
-     116,   117,   117,   118,   118,   119,   119,   120,   120,   121,
-     121,   122,   122,   123,   123,   124,   124,   125,   125,   125,
-     125,   126,   126,   126,   127,   127,   128,   128,   128,   129,
-     129,   129,   129,   130,   130,   130,   130,   130,   130,   130,
-     130,   130,   130,   131,   131,   131,   132,   132,   133,   133,
-     134,   134,   134,   134,   134,   135,   135,   135,   135,   136,
-     136,   137,   137,   138,   138,   138,   138,   138,   138,   139,
-     139,   139,   140,   140,   141,   141,   142,   142,   143,   143,
-     144,   144,   145,   145,   145,   146,   146,   147,   147,   147,
-     147,   147,   147,   148,   148,   149,   149
+       0,    66,    67,    68,    68,    69,    70,    71,    72,    72,
+      73,    73,    74,    74,    74,    74,    74,    74,    74,    74,
+      74,    74,    74,    74,    74,    74,    75,    75,    76,    76,
+      77,    77,    78,    79,    79,    80,    80,    81,    82,    83,
+      83,    84,    85,    85,    86,    87,    88,    89,    89,    90,
+      90,    90,    90,    90,    90,    91,    92,    93,    94,    95,
+      96,    97,    97,    98,    98,    99,    99,   100,   101,   102,
+     103,   103,   103,   104,   105,   106,   106,   107,   107,   108,
+     108,   109,   109,   110,   110,   110,   111,   111,   111,   112,
+     112,   113,   113,   114,   114,   115,   115,   116,   116,   117,
+     117,   118,   118,   119,   119,   120,   120,   121,   121,   122,
+     122,   123,   123,   124,   124,   125,   125,   126,   126,   126,
+     126,   127,   127,   127,   128,   128,   129,   129,   129,   130,
+     130,   130,   130,   131,   131,   131,   131,   131,   131,   131,
+     131,   131,   131,   132,   132,   132,   133,   133,   134,   134,
+     135,   135,   135,   135,   135,   136,   136,   136,   136,   137,
+     137,   138,   138,   139,   139,   139,   139,   139,   139,   140,
+     140,   140,   140,   141,   141,   142,   142,   143,   143,   144,
+     144,   145,   145,   146,   146,   146,   147,   147,   148,   148,
+     148,   148,   148,   148,   149,   149,   150,   150
 };
 
 /* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN.  */
 static const unsigned char yyr2[] =
 {
-       0,     2,     1,     0,     2,     2,     8,     8,     1,     1,
-       3,     0,     1,     1,     1,     1,     1,     1,     1,     1,
-       1,     1,     1,     1,     1,     1,     1,     1,     2,     0,
-       1,     3,     3,     1,     3,     1,     3,     2,     2,     0,
+       0,     2,     1,     0,     2,     8,     1,     1,     1,     3,
+       0,     1,     1,     1,     1,     1,     1,     1,     1,     1,
+       1,     1,     1,     1,     1,     1,     1,     2,     0,     1,
+       3,     2,     3,     1,     3,     1,     3,     2,     2,     0,
        1,     2,     0,     1,     2,     1,     2,     7,     5,     7,
        5,     9,    10,     7,     8,     3,     3,     3,     5,     3,
        5,     3,     5,     0,     1,     1,     2,     4,     3,     3,
@@ -760,10 +764,10 @@ static const unsigned char yyr2[] =
        3,     3,     3,     1,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     1,     2,     2,     1,     1,     1,     2,
        1,     1,     4,     3,     3,     2,     2,     4,     3,     2,
-       3,     1,     3,     1,     1,     1,     1,     1,     3,     3,
-       3,     5,     2,     4,     1,     2,     0,     1,     2,     3,
-       3,     5,     1,     1,     1,     0,     1,     1,     1,     1,
-       1,     1,     1,     1,     1,     1,     1
+       3,     1,     3,     1,     1,     1,     1,     1,     3,     2,
+       3,     3,     5,     2,     4,     1,     2,     0,     1,     2,
+       3,     3,     5,     1,     1,     1,     0,     1,     1,     1,
+       1,     1,     1,     1,     1,     1,     1,     1
 };
 
 /* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state
@@ -771,324 +775,332 @@ static const unsigned char yyr2[] =
    means the default is an error.  */
 static const unsigned char yydefact[] =
 {
-       3,     0,     2,     1,   185,   185,     0,     0,     0,     0,
-     185,     0,   187,   188,    75,     0,   163,     0,   193,   194,
-       0,     0,     0,     0,     0,     0,     0,     0,   164,   190,
-     191,     0,     0,    45,     0,     0,   192,     0,     0,   176,
-       5,   151,     4,    13,    14,    15,    16,    17,    18,    19,
-      20,    21,    22,    23,    24,    25,    26,     0,    77,    83,
+       3,     0,     2,     1,   186,   186,     0,     0,     0,     0,
+       0,   188,   189,    75,     0,   163,     0,   194,   195,     0,
+       0,     0,     0,     0,     0,     0,     0,     6,   164,   191,
+     192,     0,     0,    45,     0,     0,   193,     0,     0,   177,
+     151,   186,     4,    12,    13,    14,    15,    16,    17,    18,
+      19,    20,    21,    22,    23,    24,    25,     0,    77,    83,
       89,    93,    97,   101,   105,   109,   113,   117,   124,   126,
      129,   133,   143,   146,   148,   147,   150,   166,   167,   165,
-     189,   186,     0,     0,   185,   164,     0,   134,   143,     0,
-       0,    79,     0,     0,   149,   148,     0,    76,     0,     0,
-      29,     0,   136,    39,     0,    33,   135,     0,     0,   137,
-     138,     0,     0,   164,   190,   191,   178,    27,    30,     0,
-       0,     0,   139,   140,   141,   142,   174,     0,   177,     0,
-     196,     0,   195,    46,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-     144,   145,     0,     0,     0,     0,     0,   155,     0,     0,
-     156,    56,    55,   182,   184,   183,     0,     0,     0,     0,
-      80,    81,    86,    91,    95,    99,   103,   107,   111,   115,
-     121,   143,    11,    11,   154,    57,     0,    69,     0,     0,
-      70,    71,     0,    37,    40,     0,    32,     0,     0,    59,
-     168,    28,    31,   179,     0,     0,   176,   170,   175,   169,
-     172,    78,    94,     0,    98,   102,   106,   110,   114,   120,
-     119,   118,   125,   127,   128,   130,   131,   132,    85,    84,
-     159,   161,     0,     0,   153,     0,   158,     0,     0,    42,
-       0,    35,    75,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     9,    12,     0,     0,
-       0,     0,    74,    72,    41,    34,     0,     0,     0,   180,
-       0,     0,   160,     0,   152,   157,     0,    48,     0,    38,
-      43,     0,    75,     0,     0,    82,   143,    96,     0,   100,
-     104,   108,   112,   116,   123,   122,     0,    88,    87,     0,
-       0,     0,    63,    60,     0,    50,    58,     0,   171,   173,
-      90,   162,     0,     0,    44,    36,     0,     0,    75,     0,
-       0,    10,     3,     3,     0,     0,    64,    65,     0,   181,
-      49,    47,    75,     0,     0,    92,    53,     8,     0,     0,
-       0,     0,    61,    63,    66,    73,     0,    54,     0,     6,
-       7,    29,    29,     0,     0,    51,    67,    68,    62,    52
+     190,   187,     0,     0,   164,     0,   134,   143,     0,     0,
+      79,   149,   148,     0,    76,     0,     0,     0,     0,   136,
+      39,     0,    33,   135,     0,     0,   137,   138,     0,     0,
+      31,   164,   191,   192,    26,     0,     0,     0,   139,   140,
+     141,   142,   175,   169,     0,   178,     0,     0,   197,     0,
+     196,    46,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,   144,   145,
+       0,     0,     0,     0,     0,   155,     0,     0,   156,    56,
+      55,   179,   183,   185,   184,     0,     0,     0,     0,    80,
+      81,    86,    91,    95,    99,   103,   107,   111,   115,   121,
+     143,   154,    57,     0,    69,    31,     0,     0,    70,    71,
+       0,    37,    40,     0,    32,     0,     0,    59,   168,    30,
+      27,   180,     0,     0,   177,   171,   176,   170,   173,    10,
+      78,    94,     0,    98,   102,   106,   110,   114,   120,   119,
+     118,   125,   127,   128,   130,   131,   132,    85,    84,   159,
+     161,     0,     0,   153,     0,   158,     0,     0,    42,     0,
+      35,    75,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,    74,    72,    41,
+      34,     0,     0,     0,   181,   178,     0,     8,    11,     0,
+       0,   160,     0,   152,   157,     0,    48,     0,    38,    43,
+       0,    75,     0,     0,    82,   143,    96,     0,   100,   104,
+     108,   112,   116,   123,   122,     0,    88,    87,    63,    60,
+       0,    50,    58,     0,   172,   174,     0,     0,    90,   162,
+       0,     0,    44,    36,     0,     0,    75,     0,     0,     0,
+       0,    64,    65,     0,   182,     9,     3,    49,    47,    75,
+       0,     0,    92,    53,     0,     0,    61,    63,    66,    73,
+       7,     0,     0,    54,     0,    28,    28,     0,     5,     0,
+      51,    29,    67,    68,    62,    52
 };
 
 /* YYDEFGOTO[NTERM-NUM]. */
 static const short int yydefgoto[] =
 {
-      -1,     1,   337,    40,    41,   338,   257,   258,   117,   118,
-     119,    43,    44,   104,   240,   105,   241,   193,   194,   279,
-     280,    45,    46,    47,    48,    49,    50,    51,    52,    53,
-      54,   303,   325,   326,   327,   343,    55,    56,   190,   191,
-      96,    57,   169,   170,    58,   171,    59,   172,    60,   173,
-      61,   174,    62,   175,    63,   176,    64,   177,    65,   178,
-      66,   179,    67,    68,    69,    70,    71,    72,    73,    74,
-      75,   157,   232,    76,    77,   127,   128,   129,    78,   120,
-     121,    93,    79,    80,   133
+      -1,     1,     2,    40,    41,   341,   268,   269,   114,   115,
+     352,    43,    44,   101,   239,   102,   240,   191,   192,   278,
+     279,    45,    46,    47,    48,    49,    50,    51,    52,    53,
+      54,   299,   320,   321,   322,   337,    55,    56,   188,   189,
+      93,    57,   168,   169,    58,   170,    59,   171,    60,   172,
+      61,   173,    62,   174,    63,   175,    64,   176,    65,   177,
+      66,   178,    67,    68,    69,    70,    71,    72,    73,    74,
+      75,   155,   231,    76,    77,   124,   125,   126,    78,   116,
+     117,    82,    79,    80,   131
 };
 
 /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
    STATE-NUM.  */
-#define YYPACT_NINF -241
+#define YYPACT_NINF -236
 static const short int yypact[] =
 {
-    -241,     8,   402,  -241,   -17,   -17,   711,   462,   -20,   -12,
-       2,    88,  -241,  -241,   711,    20,  -241,   711,  -241,  -241,
-       1,   711,    37,   711,    50,    55,   711,   711,    36,  -241,
-    -241,   711,   342,  -241,   711,   711,  -241,   711,   711,    44,
-    -241,  -241,  -241,  -241,  -241,  -241,  -241,  -241,  -241,  -241,
-    -241,  -241,  -241,  -241,  -241,  -241,  -241,     0,  -241,  -241,
-      21,    72,    66,    67,    54,    89,    19,    93,   103,   153,
-    -241,  -241,    91,  -241,   -36,   -25,  -241,  -241,  -241,  -241,
-    -241,  -241,     9,     9,   -17,  -241,   115,  -241,   179,   151,
-     711,   613,   157,   164,  -241,   -36,     9,   148,   711,     0,
-     462,     4,  -241,   161,     3,  -241,  -241,   711,   711,  -241,
-    -241,   462,   -30,    36,   174,   175,  -241,  -241,   462,   181,
-     169,   178,  -241,  -241,  -241,  -241,  -241,    48,   182,   511,
-    -241,   711,  -241,  -241,   711,   711,   711,   711,   711,   711,
-     711,   711,   711,   711,   711,   711,   711,   711,   711,   711,
-    -241,  -241,   711,   711,   662,   711,   194,  -241,   711,   196,
-    -241,  -241,  -241,  -241,  -241,  -241,   190,    94,   198,   186,
-     192,  -241,  -241,    43,   205,   188,   191,   187,   207,     5,
-      93,    40,   210,   210,  -241,  -241,    96,  -241,   200,     1,
-     235,  -241,   711,  -241,  -241,    37,  -241,    98,   105,  -241,
-    -241,  -241,  -241,  -241,   156,   711,    44,  -241,  -241,  -241,
-    -241,  -241,    72,   199,    66,    67,    54,    89,    19,    93,
-      93,    93,   103,   153,   153,  -241,  -241,  -241,  -241,  -241,
-    -241,  -241,   116,    52,  -241,    56,  -241,   711,   462,   202,
-      22,   233,   711,   711,   711,   711,   711,   711,   711,   711,
-     711,   711,   711,   711,   711,   711,  -241,   204,   208,   209,
-     211,   219,  -241,  -241,  -241,  -241,   462,   462,   212,  -241,
-     562,   711,  -241,   711,  -241,  -241,   118,   244,   711,  -241,
-    -241,   198,   711,   711,   214,  -241,   100,   205,   216,   188,
-     191,   187,   207,     5,    93,    93,   152,  -241,  -241,   221,
-     215,   222,   255,  -241,   217,  -241,  -241,   711,  -241,  -241,
-    -241,  -241,   220,   462,  -241,  -241,   234,   159,   711,   711,
-     462,  -241,  -241,  -241,   711,    15,   255,  -241,     1,  -241,
-    -241,  -241,   711,   462,   224,  -241,  -241,   402,   240,   241,
-     158,   238,  -241,   255,  -241,  -241,   226,  -241,   462,  -241,
-    -241,   462,   462,   243,   462,  -241,  -241,  -241,  -241,  -241
+    -236,    13,   555,  -236,   -19,   -19,   755,   555,    -1,    31,
+      87,  -236,  -236,   755,    37,  -236,   755,  -236,  -236,   -21,
+     755,    34,   755,    54,    62,   755,   755,  -236,    77,  -236,
+    -236,   755,   372,  -236,   755,   755,  -236,   755,   755,    26,
+    -236,   -19,  -236,  -236,  -236,  -236,  -236,  -236,  -236,  -236,
+    -236,  -236,  -236,  -236,  -236,  -236,  -236,     9,  -236,  -236,
+      20,    16,   100,   104,   107,   140,     0,   182,   138,    97,
+    -236,  -236,    51,  -236,   -20,   -15,  -236,  -236,  -236,  -236,
+    -236,  -236,    11,    11,  -236,   117,  -236,   181,   175,   755,
+     655,  -236,   -20,    11,   173,   755,     9,   433,   126,  -236,
+     174,    10,  -236,  -236,   755,   755,  -236,  -236,   555,    22,
+     319,    77,   176,   177,  -236,   494,   -28,   179,  -236,  -236,
+    -236,  -236,  -236,  -236,    27,    61,   755,   180,  -236,   755,
+    -236,  -236,   755,   755,   755,   755,   755,   755,   755,   755,
+     755,   755,   755,   755,   755,   755,   755,   755,  -236,  -236,
+     755,   755,   705,   755,   189,  -236,   755,   194,  -236,  -236,
+    -236,  -236,  -236,  -236,  -236,   187,    49,   196,   184,   188,
+    -236,  -236,    21,   206,   185,   190,   186,   203,     1,   182,
+      84,  -236,  -236,    68,  -236,  -236,   198,   -21,   233,  -236,
+     755,  -236,  -236,    34,  -236,   132,   152,  -236,  -236,  -236,
+    -236,  -236,   154,   755,   199,  -236,  -236,  -236,  -236,   209,
+    -236,    16,   197,   100,   104,   107,   140,     0,   182,   182,
+     182,   138,    97,    97,  -236,  -236,  -236,  -236,  -236,  -236,
+    -236,   153,    73,  -236,    79,  -236,   755,   555,   200,   155,
+     236,   755,   755,   755,   755,   755,   755,   755,   755,   755,
+     755,   755,   755,   755,   755,   204,   215,  -236,  -236,  -236,
+    -236,   555,   555,   202,  -236,   207,   605,  -236,   210,   208,
+     755,  -236,   755,  -236,  -236,   161,   247,   755,  -236,  -236,
+     196,   755,   755,   211,  -236,   102,   206,   212,   185,   190,
+     186,   203,     1,   182,   182,   164,  -236,  -236,   258,  -236,
+     218,  -236,  -236,   755,  -236,  -236,   228,   219,  -236,  -236,
+     217,   555,  -236,  -236,   231,   165,   755,   755,   555,   755,
+      -4,   258,  -236,   -21,  -236,  -236,  -236,  -236,  -236,   755,
+     555,   222,  -236,  -236,    94,   234,  -236,   258,  -236,  -236,
+     555,   249,   240,  -236,   555,   555,   555,   252,  -236,   555,
+    -236,   555,  -236,  -236,  -236,  -236
 };
 
 /* YYPGOTO[NTERM-NUM].  */
 static const short int yypgoto[] =
 {
-    -241,  -241,   290,  -241,  -241,   -32,  -241,   109,    -2,  -241,
-    -133,    -9,  -241,  -241,  -241,    99,    12,  -241,  -241,  -241,
-    -241,  -241,  -241,  -241,  -241,  -241,  -241,  -241,  -241,  -241,
-    -241,  -241,   -48,  -241,   -29,  -241,  -241,  -241,  -241,   106,
-    -240,   -11,  -241,  -241,   -69,  -230,  -241,  -241,  -241,  -241,
-     165,    57,   162,    58,   163,    59,   167,    61,   171,    53,
-     172,    64,   -61,   173,    75,     6,  -241,    30,   292,   304,
-    -241,    -5,  -241,  -241,  -241,  -241,  -241,   110,  -241,  -241,
-     119,   218,  -241,  -241,    18
+    -236,  -236,   -38,  -236,  -236,  -236,  -236,  -236,    -2,  -128,
+     -57,   -10,  -236,  -236,  -236,    98,    12,  -236,  -236,  -236,
+    -236,  -236,  -236,  -236,  -236,  -236,  -236,  -236,  -236,  -236,
+    -236,  -236,   -47,  -236,   -27,  -236,  -236,  -236,  -236,   105,
+    -235,   -12,  -236,  -236,   -64,  -221,  -236,  -236,  -236,  -236,
+     163,    53,   166,    52,   167,    55,   162,    56,   168,    60,
+     172,    50,   -61,   169,    76,     2,  -236,    29,   302,   304,
+    -236,   -58,  -236,  -236,  -236,  -236,   111,   114,  -236,  -236,
+     119,    -3,  -236,  -236,    19
 };
 
 /* YYTABLE[YYPACT[STATE-NUM]].  What to do in state STATE-NUM.  If
    positive, shift that token.  If negative, reduce the rule which
    number is the opposite.  If zero, do what YYDEFACT says.
    If YYTABLE_NINF, syntax error.  */
-#define YYTABLE_NINF -185
+#define YYTABLE_NINF -186
 static const short int yytable[] =
 {
-      42,   130,   284,    97,   130,    89,    99,   154,     3,   188,
-     130,   101,    87,   285,   200,   288,   189,   131,   154,    81,
-     112,   251,   341,    90,   297,   298,   155,   102,   156,   106,
-     180,    91,   109,   110,   141,   142,    88,   158,    92,   159,
-     122,   123,   316,   124,   125,   252,   100,   131,   314,   132,
-     195,    88,   132,    88,   134,   253,    88,    88,   132,   143,
-     210,   342,   211,    98,    88,    88,   213,    88,    88,   281,
-     160,   282,   135,   103,   150,   151,   244,   254,   334,   167,
-     219,   220,   221,   228,   229,   231,   111,   186,   255,   335,
-     184,   126,   346,   107,   245,   206,   197,   198,   108,   131,
-     161,   162,    84,   131,   136,    11,    12,    13,   139,   199,
-      16,   207,    18,    19,   185,   274,   201,   187,   137,   275,
-     138,   181,   196,   264,    85,   150,   151,   140,   152,    29,
-      30,    31,   144,    86,   150,   151,   269,   254,   238,   153,
-     260,   131,   266,   131,   233,   131,    36,   235,   255,   267,
-      39,   163,   131,   225,   226,   227,   164,   165,   145,   146,
-     272,   116,   312,   273,    88,   131,    88,    88,    88,    88,
-      88,    88,    88,    88,    88,    88,    88,    88,    88,    88,
-     262,   166,   180,   180,   180,   180,   180,   180,   180,   180,
-     294,   295,   163,   180,   180,   131,   320,   164,   165,   131,
-     182,   309,   310,   333,   311,   131,   131,   183,   351,   192,
-     147,   148,   149,   150,   151,   203,   204,   180,   356,   357,
-     223,   224,    82,    83,  -184,  -183,   276,   202,   205,   208,
-     234,    97,   236,   237,   239,   242,   277,   246,   329,   243,
-     247,   249,   296,   261,   248,   250,   256,   189,   283,   271,
-     278,   299,   300,   301,   313,   304,   302,   321,   180,   324,
-     322,   328,   307,   318,   305,   306,   319,   323,   348,   330,
-     354,    97,   317,   286,    88,   286,    88,    88,    88,    88,
-      88,    88,    88,   332,   286,   286,   349,   350,   352,   358,
-       2,   339,   259,   315,   265,   353,   263,   344,   214,   212,
-     215,   287,   292,    94,   289,   216,   290,    97,   286,   291,
-     217,   331,   218,   340,   293,    95,   270,   222,   336,   345,
-       0,    97,     0,   268,     0,     0,     0,     0,     0,     0,
-       0,   347,     0,     0,     0,    42,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     4,   355,     0,     5,   286,
-       6,     7,   359,     8,     0,     9,    84,     0,     0,    11,
-      12,    13,    14,    15,    16,    17,    18,    19,    20,    21,
-      22,    23,    24,    25,     0,     0,    26,    27,   113,     0,
-       0,     0,     0,   114,   115,    31,     0,    32,   116,     0,
-       0,    33,     0,     0,     0,     0,     0,    34,    35,     0,
-      36,     0,    37,    38,    39,     4,     0,     0,     5,     0,
-       6,     7,     0,     8,     0,     9,    10,     0,     0,    11,
+      42,    94,    83,   335,    96,    88,   283,   201,    86,    98,
+     128,   128,   128,     3,   139,   140,   250,   158,    81,   109,
+     202,   284,    99,   287,   103,   152,    97,   106,   107,   179,
+     152,   336,   296,   297,   181,    87,   118,   119,   127,   120,
+     121,   141,   251,   153,    89,   154,   314,   134,   156,    87,
+     157,    87,   132,   243,    87,    87,   312,   129,   193,   130,
+     130,   130,   208,    87,    87,   210,    87,    87,   198,   212,
+     129,   100,   133,   244,   122,   204,    90,   166,   218,   219,
+     220,   331,    95,   183,   148,   149,   227,   228,   230,   150,
+     123,   205,   195,   196,   342,   237,   332,   129,   252,   104,
+     151,   159,   160,    10,    11,    12,   197,   105,    15,   206,
+      17,    18,   182,   200,   255,   184,   129,   148,   149,   180,
+     194,   129,   253,    27,    84,   207,   259,   129,   108,    29,
+      30,   186,    31,   254,    85,   148,   149,   273,   187,   264,
+     253,   232,   129,   274,   234,   345,    36,   224,   225,   226,
+      39,   254,   161,   135,   162,   145,   146,   147,   136,   163,
+     164,    87,   137,    87,    87,    87,    87,    87,    87,    87,
+      87,    87,    87,    87,    87,    87,    87,   257,   261,   138,
+     129,   179,   179,   179,   179,   179,   179,   179,   179,   293,
+     294,   162,   179,   179,   143,   144,   163,   164,   262,   271,
+     129,   272,   305,   280,   165,   281,   308,   310,   309,   129,
+     318,   330,   129,   129,   148,   149,   179,   351,   351,   222,
+     223,   129,   142,   190,   275,   209,   233,  -185,  -184,    94,
+     203,   235,   236,   238,   241,   276,   242,   245,   246,   324,
+     295,   248,   249,   256,   247,   187,   267,   122,   270,   277,
+     282,   298,   300,   303,   307,   206,   179,   311,   306,   301,
+     302,   316,   319,   317,   323,   325,   326,   327,   344,    94,
+     315,   285,    87,   285,    87,    87,    87,    87,    87,    87,
+      87,   329,   285,   285,   348,   346,   349,   354,   340,   353,
+     347,   260,   313,   258,   338,   211,   286,   288,   215,   292,
+     213,   289,   214,   290,    94,   216,   285,   334,   291,   328,
+     217,   221,    91,   339,    92,   265,   333,    94,   266,     0,
+    -179,   263,     0,     0,     0,     0,     0,     0,   343,     0,
+       0,     0,     0,  -179,  -179,     0,     0,     0,    42,     0,
+       0,     0,   350,     0,     0,     0,   285,   355,     0,   200,
+    -179,  -179,     0,     0,     0,     0,     0,  -179,  -179,  -179,
+    -179,     0,     0,     0,     0,     0,     0,  -179,  -179,     0,
+       0,  -179,  -179,  -179,  -179,     4,     0,  -179,     5,  -179,
+       6,     7,     0,     8,  -179,     9,     0,     0,    10,    11,
       12,    13,    14,    15,    16,    17,    18,    19,    20,    21,
-      22,    23,    24,    25,     0,     0,    26,    27,    28,     0,
-       0,     0,     0,    29,    30,    31,     0,    32,     0,     0,
-       0,    33,     0,     0,     0,     0,     0,    34,    35,     0,
-      36,     0,    37,    38,    39,     4,     0,     0,     5,     0,
-       6,     7,     0,     8,     0,     9,    84,     0,     0,    11,
-      12,    13,    14,    15,    16,    17,    18,    19,    20,    21,
-      22,    23,    24,    25,     0,     0,    26,    27,    28,     0,
-       0,     0,     0,    29,    30,    31,     0,    32,     0,     0,
-       0,    33,     0,     0,     0,     0,     0,    34,    35,     6,
-      36,     0,    37,    38,    39,    84,     0,     0,    11,    12,
-      13,     0,     0,    16,     0,    18,    19,     0,    21,     0,
-      23,     0,     0,     0,     0,    26,    27,    85,     0,     0,
-       0,     0,    29,    30,    31,     0,    86,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,    34,    35,     0,    36,
-       6,    37,    38,    39,   209,     0,    84,     0,     0,    11,
-      12,    13,     0,     0,    16,     0,    18,    19,     0,    21,
-       0,    23,     0,     0,     0,     0,    26,    27,    85,     0,
-       0,     0,     0,    29,    30,    31,     0,    86,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,    34,    35,     0,
-      36,     6,    37,    38,    39,   308,     0,    84,     0,     0,
-      11,    12,    13,     0,     0,    16,     0,    18,    19,     0,
-      21,   168,    23,     0,     0,     0,     0,    26,    27,    85,
-       0,     0,     0,     0,    29,    30,    31,     0,    86,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,    34,    35,
-       6,    36,     0,    37,    38,    39,    84,     0,     0,    11,
-      12,    13,     0,     0,    16,     0,    18,    19,     0,    21,
-       0,    23,     0,     0,     0,     0,    26,    27,    85,     0,
-       0,     0,     0,    29,    30,    31,   230,    86,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,    34,    35,     6,
-      36,     0,    37,    38,    39,    84,     0,     0,    11,    12,
-      13,     0,     0,    16,     0,    18,    19,     0,    21,     0,
-      23,     0,     0,     0,     0,    26,    27,    85,     0,     0,
-       0,     0,    29,    30,    31,     0,    86,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,    34,    35,     0,    36,
-       0,    37,    38,    39
+      22,    23,    24,     0,     0,    25,    26,   110,    27,   111,
+       0,     0,     0,     0,   112,   113,     0,    31,     0,    32,
+       0,     0,    33,     0,     0,     0,     0,     0,    34,    35,
+       0,    36,     0,    37,    38,    39,     4,     0,     0,     5,
+       0,     6,     7,     0,     8,     0,     9,     0,     0,    10,
+      11,    12,    13,    14,    15,    16,    17,    18,    19,    20,
+      21,    22,    23,    24,     0,     0,    25,    26,   185,    27,
+      28,     0,     0,     0,     0,    29,    30,     0,    31,     0,
+      32,     0,     0,    33,     0,     0,     0,     0,     0,    34,
+      35,     0,    36,     0,    37,    38,    39,     4,     0,     0,
+       5,     0,     6,     7,     0,     8,     0,     9,     0,     0,
+      10,    11,    12,    13,    14,    15,    16,    17,    18,    19,
+      20,    21,    22,    23,    24,     0,     0,    25,    26,   199,
+      27,    28,     0,     0,     0,     0,    29,    30,     0,    31,
+       0,    32,     0,     0,    33,     0,     0,     0,     0,     0,
+      34,    35,     0,    36,     0,    37,    38,    39,     4,     0,
+       0,     5,     0,     6,     7,     0,     8,     0,     9,     0,
+       0,    10,    11,    12,    13,    14,    15,    16,    17,    18,
+      19,    20,    21,    22,    23,    24,     0,     0,    25,    26,
+       0,    27,    28,     0,     0,     0,     0,    29,    30,     0,
+      31,     0,    32,     0,     0,    33,     0,     0,     0,     0,
+       0,    34,    35,     6,    36,     0,    37,    38,    39,     0,
+       0,    10,    11,    12,     0,     0,    15,     0,    17,    18,
+       0,    20,     0,    22,     0,     0,     0,     0,    25,    26,
+       0,    27,    84,     0,     0,     0,     0,    29,    30,     0,
+      31,     0,    85,     0,     0,     0,     0,     0,     0,     0,
+       0,    34,    35,     6,    36,     0,    37,    38,    39,   304,
+       0,    10,    11,    12,     0,     0,    15,     0,    17,    18,
+       0,    20,   167,    22,     0,     0,     0,     0,    25,    26,
+       0,    27,    84,     0,     0,     0,     0,    29,    30,     0,
+      31,     0,    85,     0,     0,     0,     0,     0,     0,     0,
+       0,    34,    35,     6,    36,     0,    37,    38,    39,     0,
+       0,    10,    11,    12,     0,     0,    15,     0,    17,    18,
+       0,    20,     0,    22,     0,     0,     0,     0,    25,    26,
+       0,    27,    84,     0,     0,     0,     0,    29,    30,     0,
+      31,   229,    85,     0,     0,     0,     0,     0,     0,     0,
+       0,    34,    35,     6,    36,     0,    37,    38,    39,     0,
+       0,    10,    11,    12,     0,     0,    15,     0,    17,    18,
+       0,    20,     0,    22,     0,     0,     0,     0,    25,    26,
+       0,    27,    84,     0,     0,     0,     0,    29,    30,     0,
+      31,     0,    85,     0,     0,     0,     0,     0,     0,     0,
+       0,    34,    35,     0,    36,     0,    37,    38,    39
 };
 
 static const short int yycheck[] =
 {
-       2,     1,   242,    14,     1,     7,    17,    43,     0,     5,
-       1,    20,     6,   243,    44,   245,    12,    47,    43,    36,
-      31,    16,     7,    43,   254,   255,    62,    21,    64,    23,
-      91,    43,    26,    27,    15,    16,     6,    62,    36,    64,
-      34,    35,   282,    37,    38,    40,    45,    47,   278,    49,
-      47,    21,    49,    23,    33,    15,    26,    27,    49,    40,
-     129,    46,   131,    43,    34,    35,   135,    37,    38,    47,
-      75,    49,    51,    36,    34,    35,    33,    37,   318,    90,
-     141,   142,   143,   152,   153,   154,    50,    98,    48,   319,
-      95,    47,   332,    43,    51,    47,   107,   108,    43,    47,
-      82,    83,    14,    47,    32,    17,    18,    19,    54,   111,
-      22,    63,    24,    25,    96,    63,   118,    99,    52,    63,
-      53,    91,   104,   192,    36,    34,    35,    38,    37,    41,
-      42,    43,    39,    45,    34,    35,   205,    37,    44,    48,
-      44,    47,    44,    47,   155,    47,    58,   158,    48,    44,
-      62,    36,    47,   147,   148,   149,    41,    42,    55,    56,
-      44,    46,    44,    47,   134,    47,   136,   137,   138,   139,
-     140,   141,   142,   143,   144,   145,   146,   147,   148,   149,
-     189,    30,   243,   244,   245,   246,   247,   248,   249,   250,
-     251,   252,    36,   254,   255,    47,    44,    41,    42,    47,
-      43,   270,   271,    44,   273,    47,    47,    43,    50,    48,
-      57,    58,    59,    34,    35,    46,    47,   278,   351,   352,
-     145,   146,     4,     5,    50,    50,   237,    46,    50,    47,
-      36,   242,    36,    43,    36,    49,   238,    32,   307,    47,
-      52,    54,   253,    43,    53,    38,    36,    12,    15,    50,
-      48,    47,    44,    44,    10,    36,    45,    36,   319,     4,
-      45,    44,    50,    49,   266,   267,    50,    45,    44,    49,
-      44,   282,   283,   243,   244,   245,   246,   247,   248,   249,
-     250,   251,   252,    49,   254,   255,    46,    46,    50,    46,
-       0,   323,   183,   281,   195,   343,   190,   326,   136,   134,
-     137,   244,   249,    11,   246,   138,   247,   318,   278,   248,
-     139,   313,   140,   324,   250,    11,   206,   144,   320,   328,
-      -1,   332,    -1,   204,    -1,    -1,    -1,    -1,    -1,    -1,
-      -1,   333,    -1,    -1,    -1,   337,    -1,    -1,    -1,    -1,
-      -1,    -1,    -1,    -1,    -1,     3,   348,    -1,     6,   319,
-       8,     9,   354,    11,    -1,    13,    14,    -1,    -1,    17,
-      18,    19,    20,    21,    22,    23,    24,    25,    26,    27,
-      28,    29,    30,    31,    -1,    -1,    34,    35,    36,    -1,
-      -1,    -1,    -1,    41,    42,    43,    -1,    45,    46,    -1,
-      -1,    49,    -1,    -1,    -1,    -1,    -1,    55,    56,    -1,
-      58,    -1,    60,    61,    62,     3,    -1,    -1,     6,    -1,
-       8,     9,    -1,    11,    -1,    13,    14,    -1,    -1,    17,
-      18,    19,    20,    21,    22,    23,    24,    25,    26,    27,
-      28,    29,    30,    31,    -1,    -1,    34,    35,    36,    -1,
-      -1,    -1,    -1,    41,    42,    43,    -1,    45,    -1,    -1,
-      -1,    49,    -1,    -1,    -1,    -1,    -1,    55,    56,    -1,
-      58,    -1,    60,    61,    62,     3,    -1,    -1,     6,    -1,
-       8,     9,    -1,    11,    -1,    13,    14,    -1,    -1,    17,
+       2,    13,     5,     7,    16,     7,   241,    35,     6,    19,
+       1,     1,     1,     0,    14,    15,    15,    75,    37,    31,
+      48,   242,    20,   244,    22,    45,    47,    25,    26,    90,
+      45,    35,   253,   254,    92,     6,    34,    35,    41,    37,
+      38,    41,    41,    63,    45,    65,   281,    31,    63,    20,
+      65,    22,    32,    32,    25,    26,   277,    48,    48,    50,
+      50,    50,   126,    34,    35,   129,    37,    38,    46,   133,
+      48,    37,    52,    52,    48,    48,    45,    89,   139,   140,
+     141,   316,    45,    95,    33,    34,   150,   151,   152,    38,
+      64,    64,   104,   105,   329,    46,   317,    48,    14,    45,
+      49,    82,    83,    16,    17,    18,   108,    45,    21,    48,
+      23,    24,    93,   115,    46,    96,    48,    33,    34,    90,
+     101,    48,    38,    36,    37,    64,   190,    48,    51,    42,
+      43,     5,    45,    49,    47,    33,    34,    64,    12,   203,
+      38,   153,    48,    64,   156,    51,    59,   145,   146,   147,
+      63,    49,    35,    53,    37,    58,    59,    60,    54,    42,
+      43,   132,    55,   134,   135,   136,   137,   138,   139,   140,
+     141,   142,   143,   144,   145,   146,   147,   187,    46,    39,
+      48,   242,   243,   244,   245,   246,   247,   248,   249,   250,
+     251,    37,   253,   254,    56,    57,    42,    43,    46,    46,
+      48,    48,   266,    48,    29,    50,   270,    46,   272,    48,
+      46,    46,    48,    48,    33,    34,   277,   345,   346,   143,
+     144,    48,    40,    49,   236,    45,    37,    51,    51,   241,
+      51,    37,    45,    37,    50,   237,    48,    31,    53,   303,
+     252,    55,    39,    45,    54,    12,    37,    48,    51,    49,
+      14,    47,    37,    51,    46,    48,   317,    10,    48,   261,
+     262,    50,     4,    51,    46,    37,    47,    50,    46,   281,
+     282,   242,   243,   244,   245,   246,   247,   248,   249,   250,
+     251,    50,   253,   254,    35,    51,    46,    35,   326,   346,
+     337,   193,   280,   188,   321,   132,   243,   245,   136,   249,
+     134,   246,   135,   247,   316,   137,   277,   319,   248,   311,
+     138,   142,    10,   323,    10,   204,   318,   329,   204,    -1,
+       1,   202,    -1,    -1,    -1,    -1,    -1,    -1,   330,    -1,
+      -1,    -1,    -1,    14,    15,    -1,    -1,    -1,   340,    -1,
+      -1,    -1,   344,    -1,    -1,    -1,   317,   349,    -1,   351,
+      31,    32,    -1,    -1,    -1,    -1,    -1,    38,    39,    40,
+      41,    -1,    -1,    -1,    -1,    -1,    -1,    48,    49,    -1,
+      -1,    52,    53,    54,    55,     3,    -1,    58,     6,    60,
+       8,     9,    -1,    11,    65,    13,    -1,    -1,    16,    17,
       18,    19,    20,    21,    22,    23,    24,    25,    26,    27,
-      28,    29,    30,    31,    -1,    -1,    34,    35,    36,    -1,
-      -1,    -1,    -1,    41,    42,    43,    -1,    45,    -1,    -1,
-      -1,    49,    -1,    -1,    -1,    -1,    -1,    55,    56,     8,
-      58,    -1,    60,    61,    62,    14,    -1,    -1,    17,    18,
-      19,    -1,    -1,    22,    -1,    24,    25,    -1,    27,    -1,
-      29,    -1,    -1,    -1,    -1,    34,    35,    36,    -1,    -1,
-      -1,    -1,    41,    42,    43,    -1,    45,    -1,    -1,    -1,
-      -1,    -1,    -1,    -1,    -1,    -1,    55,    56,    -1,    58,
-       8,    60,    61,    62,    63,    -1,    14,    -1,    -1,    17,
-      18,    19,    -1,    -1,    22,    -1,    24,    25,    -1,    27,
-      -1,    29,    -1,    -1,    -1,    -1,    34,    35,    36,    -1,
-      -1,    -1,    -1,    41,    42,    43,    -1,    45,    -1,    -1,
-      -1,    -1,    -1,    -1,    -1,    -1,    -1,    55,    56,    -1,
-      58,     8,    60,    61,    62,    63,    -1,    14,    -1,    -1,
-      17,    18,    19,    -1,    -1,    22,    -1,    24,    25,    -1,
-      27,    28,    29,    -1,    -1,    -1,    -1,    34,    35,    36,
-      -1,    -1,    -1,    -1,    41,    42,    43,    -1,    45,    -1,
-      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    55,    56,
-       8,    58,    -1,    60,    61,    62,    14,    -1,    -1,    17,
-      18,    19,    -1,    -1,    22,    -1,    24,    25,    -1,    27,
-      -1,    29,    -1,    -1,    -1,    -1,    34,    35,    36,    -1,
-      -1,    -1,    -1,    41,    42,    43,    44,    45,    -1,    -1,
-      -1,    -1,    -1,    -1,    -1,    -1,    -1,    55,    56,     8,
-      58,    -1,    60,    61,    62,    14,    -1,    -1,    17,    18,
-      19,    -1,    -1,    22,    -1,    24,    25,    -1,    27,    -1,
-      29,    -1,    -1,    -1,    -1,    34,    35,    36,    -1,    -1,
-      -1,    -1,    41,    42,    43,    -1,    45,    -1,    -1,    -1,
-      -1,    -1,    -1,    -1,    -1,    -1,    55,    56,    -1,    58,
-      -1,    60,    61,    62
+      28,    29,    30,    -1,    -1,    33,    34,    35,    36,    37,
+      -1,    -1,    -1,    -1,    42,    43,    -1,    45,    -1,    47,
+      -1,    -1,    50,    -1,    -1,    -1,    -1,    -1,    56,    57,
+      -1,    59,    -1,    61,    62,    63,     3,    -1,    -1,     6,
+      -1,     8,     9,    -1,    11,    -1,    13,    -1,    -1,    16,
+      17,    18,    19,    20,    21,    22,    23,    24,    25,    26,
+      27,    28,    29,    30,    -1,    -1,    33,    34,    35,    36,
+      37,    -1,    -1,    -1,    -1,    42,    43,    -1,    45,    -1,
+      47,    -1,    -1,    50,    -1,    -1,    -1,    -1,    -1,    56,
+      57,    -1,    59,    -1,    61,    62,    63,     3,    -1,    -1,
+       6,    -1,     8,     9,    -1,    11,    -1,    13,    -1,    -1,
+      16,    17,    18,    19,    20,    21,    22,    23,    24,    25,
+      26,    27,    28,    29,    30,    -1,    -1,    33,    34,    35,
+      36,    37,    -1,    -1,    -1,    -1,    42,    43,    -1,    45,
+      -1,    47,    -1,    -1,    50,    -1,    -1,    -1,    -1,    -1,
+      56,    57,    -1,    59,    -1,    61,    62,    63,     3,    -1,
+      -1,     6,    -1,     8,     9,    -1,    11,    -1,    13,    -1,
+      -1,    16,    17,    18,    19,    20,    21,    22,    23,    24,
+      25,    26,    27,    28,    29,    30,    -1,    -1,    33,    34,
+      -1,    36,    37,    -1,    -1,    -1,    -1,    42,    43,    -1,
+      45,    -1,    47,    -1,    -1,    50,    -1,    -1,    -1,    -1,
+      -1,    56,    57,     8,    59,    -1,    61,    62,    63,    -1,
+      -1,    16,    17,    18,    -1,    -1,    21,    -1,    23,    24,
+      -1,    26,    -1,    28,    -1,    -1,    -1,    -1,    33,    34,
+      -1,    36,    37,    -1,    -1,    -1,    -1,    42,    43,    -1,
+      45,    -1,    47,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    56,    57,     8,    59,    -1,    61,    62,    63,    64,
+      -1,    16,    17,    18,    -1,    -1,    21,    -1,    23,    24,
+      -1,    26,    27,    28,    -1,    -1,    -1,    -1,    33,    34,
+      -1,    36,    37,    -1,    -1,    -1,    -1,    42,    43,    -1,
+      45,    -1,    47,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    56,    57,     8,    59,    -1,    61,    62,    63,    -1,
+      -1,    16,    17,    18,    -1,    -1,    21,    -1,    23,    24,
+      -1,    26,    -1,    28,    -1,    -1,    -1,    -1,    33,    34,
+      -1,    36,    37,    -1,    -1,    -1,    -1,    42,    43,    -1,
+      45,    46,    47,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    56,    57,     8,    59,    -1,    61,    62,    63,    -1,
+      -1,    16,    17,    18,    -1,    -1,    21,    -1,    23,    24,
+      -1,    26,    -1,    28,    -1,    -1,    -1,    -1,    33,    34,
+      -1,    36,    37,    -1,    -1,    -1,    -1,    42,    43,    -1,
+      45,    -1,    47,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    56,    57,    -1,    59,    -1,    61,    62,    63
 };
 
 /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
    symbol of state STATE-NUM.  */
 static const unsigned char yystos[] =
 {
-       0,    66,    67,     0,     3,     6,     8,     9,    11,    13,
-      14,    17,    18,    19,    20,    21,    22,    23,    24,    25,
-      26,    27,    28,    29,    30,    31,    34,    35,    36,    41,
-      42,    43,    45,    49,    55,    56,    58,    60,    61,    62,
-      68,    69,    73,    76,    77,    86,    87,    88,    89,    90,
-      91,    92,    93,    94,    95,   101,   102,   106,   109,   111,
-     113,   115,   117,   119,   121,   123,   125,   127,   128,   129,
-     130,   131,   132,   133,   134,   135,   138,   139,   143,   147,
-     148,    36,   146,   146,    14,    36,    45,   130,   132,    73,
-      43,    43,    36,   146,   133,   134,   105,   106,    43,   106,
-      45,    76,   130,    36,    78,    80,   130,    43,    43,   130,
-     130,    50,   106,    36,    41,    42,    46,    73,    74,    75,
-     144,   145,   130,   130,   130,   130,    47,   140,   141,   142,
-       1,    47,    49,   149,    33,    51,    32,    52,    53,    54,
-      38,    15,    16,    40,    39,    55,    56,    57,    58,    59,
-      34,    35,    37,    48,    43,    62,    64,   136,    62,    64,
-     136,   149,   149,    36,    41,    42,    30,   106,    28,   107,
-     108,   110,   112,   114,   116,   118,   120,   122,   124,   126,
-     127,   132,    43,    43,   136,   149,   106,   149,     5,    12,
-     103,   104,    48,    82,    83,    47,   149,   106,   106,    73,
-      44,    73,    46,    46,    47,    50,    47,    63,    47,    63,
-     109,   109,   115,   109,   117,   119,   121,   123,   125,   127,
-     127,   127,   128,   129,   129,   130,   130,   130,   109,   109,
-      44,   109,   137,   106,    36,   106,    36,    43,    44,    36,
-      79,    81,    49,    47,    33,    51,    32,    52,    53,    54,
-      38,    16,    40,    15,    37,    48,    36,    71,    72,    72,
-      44,    43,    76,   104,   109,    80,    44,    44,   145,   109,
-     142,    50,    44,    47,    63,    63,   106,    73,    48,    84,
-      85,    47,    49,    15,   105,   110,   132,   116,   110,   118,
-     120,   122,   124,   126,   127,   127,   106,   110,   110,    47,
-      44,    44,    45,    96,    36,    73,    73,    50,    63,   109,
-     109,   109,    44,    10,   110,    81,   105,   106,    49,    50,
-      44,    36,    45,    45,     4,    97,    98,    99,    44,   109,
-      49,    73,    49,    44,   105,   110,    73,    67,    70,    70,
-     106,     7,    46,   100,    99,    76,   105,    73,    44,    46,
-      46,    50,    50,    97,    44,    73,    75,    75,    46,    73
+       0,    67,    68,     0,     3,     6,     8,     9,    11,    13,
+      16,    17,    18,    19,    20,    21,    22,    23,    24,    25,
+      26,    27,    28,    29,    30,    33,    34,    36,    37,    42,
+      43,    45,    47,    50,    56,    57,    59,    61,    62,    63,
+      69,    70,    74,    77,    78,    87,    88,    89,    90,    91,
+      92,    93,    94,    95,    96,   102,   103,   107,   110,   112,
+     114,   116,   118,   120,   122,   124,   126,   128,   129,   130,
+     131,   132,   133,   134,   135,   136,   139,   140,   144,   148,
+     149,    37,   147,   147,    37,    47,   131,   133,    74,    45,
+      45,   134,   135,   106,   107,    45,   107,    47,    77,   131,
+      37,    79,    81,   131,    45,    45,   131,   131,    51,   107,
+      35,    37,    42,    43,    74,    75,   145,   146,   131,   131,
+     131,   131,    48,    64,   141,   142,   143,   147,     1,    48,
+      50,   150,    32,    52,    31,    53,    54,    55,    39,    14,
+      15,    41,    40,    56,    57,    58,    59,    60,    33,    34,
+      38,    49,    45,    63,    65,   137,    63,    65,   137,   150,
+     150,    35,    37,    42,    43,    29,   107,    27,   108,   109,
+     111,   113,   115,   117,   119,   121,   123,   125,   127,   128,
+     133,   137,   150,   107,   150,    35,     5,    12,   104,   105,
+      49,    83,    84,    48,   150,   107,   107,    74,    46,    35,
+      74,    35,    48,    51,    48,    64,    48,    64,   110,    45,
+     110,   116,   110,   118,   120,   122,   124,   126,   128,   128,
+     128,   129,   130,   130,   131,   131,   131,   110,   110,    46,
+     110,   138,   107,    37,   107,    37,    45,    46,    37,    80,
+      82,    50,    48,    32,    52,    31,    53,    54,    55,    39,
+      15,    41,    14,    38,    49,    46,    45,    77,   105,   110,
+      81,    46,    46,   146,   110,   142,   143,    37,    72,    73,
+      51,    46,    48,    64,    64,   107,    74,    49,    85,    86,
+      48,    50,    14,   106,   111,   133,   117,   111,   119,   121,
+     123,   125,   127,   128,   128,   107,   111,   111,    47,    97,
+      37,    74,    74,    51,    64,   110,    48,    46,   110,   110,
+      46,    10,   111,    82,   106,   107,    50,    51,    46,     4,
+      98,    99,   100,    46,   110,    37,    47,    50,    74,    50,
+      46,   106,   111,    74,   107,     7,    35,   101,   100,    77,
+      68,    71,   106,    74,    46,    51,    51,    98,    35,    46,
+      74,    75,    76,    76,    35,    74
 };
 
 #define yyerrok                (yyerrstatus = 0)
@@ -1758,973 +1770,978 @@ yyreduce:
   switch (yyn)
     {
         case 2:
-#line 247 "parser.y"
+#line 254 "parser.y"
     { program_parsed(ctx, (yyvsp[0].source_elements)); ;}
     break;
 
   case 3:
-#line 251 "parser.y"
+#line 258 "parser.y"
     { (yyval.source_elements) = new_source_elements(ctx); ;}
     break;
 
   case 4:
-#line 253 "parser.y"
+#line 260 "parser.y"
     { (yyval.source_elements) = source_elements_add_statement((yyvsp[-1].source_elements), (yyvsp[0].statement)); ;}
     break;
 
   case 5:
-#line 255 "parser.y"
-    { (yyval.source_elements) = source_elements_add_function((yyvsp[-1].source_elements), (yyvsp[0].function_declaration)); ;}
+#line 265 "parser.y"
+    { (yyval.expr) = new_function_expression(ctx, (yyvsp[-6].identifier), (yyvsp[-4].parameter_list), (yyvsp[-1].source_elements), (yyvsp[-7].srcptr), (yyvsp[0].srcptr)-(yyvsp[-7].srcptr)+1); ;}
     break;
 
   case 6:
-#line 260 "parser.y"
-    { (yyval.function_declaration) = new_function_declaration(ctx, (yyvsp[-6].identifier), (yyvsp[-4].parameter_list), (yyvsp[-1].source_elements)); ;}
+#line 268 "parser.y"
+    { push_func(ctx); (yyval.srcptr) = (yyvsp[0].srcptr); ;}
     break;
 
   case 7:
-#line 265 "parser.y"
-    { (yyval.expr) = new_function_expression(ctx, (yyvsp[-6].identifier), (yyvsp[-4].parameter_list), (yyvsp[-1].source_elements)); ;}
+#line 272 "parser.y"
+    { (yyval.source_elements) = function_body_parsed(ctx, (yyvsp[0].source_elements)); ;}
     break;
 
   case 8:
-#line 269 "parser.y"
-    { (yyval.source_elements) = (yyvsp[0].source_elements); ;}
+#line 276 "parser.y"
+    { (yyval.parameter_list) = new_parameter_list(ctx, (yyvsp[0].identifier)); ;}
     break;
 
   case 9:
-#line 273 "parser.y"
-    { (yyval.parameter_list) = new_parameter_list(ctx, (yyvsp[0].identifier)); ;}
+#line 278 "parser.y"
+    { (yyval.parameter_list) = parameter_list_add(ctx, (yyvsp[-2].parameter_list), (yyvsp[0].identifier)); ;}
     break;
 
   case 10:
-#line 275 "parser.y"
-    { (yyval.parameter_list) = parameter_list_add(ctx, (yyvsp[-2].parameter_list), (yyvsp[0].identifier)); ;}
+#line 282 "parser.y"
+    { (yyval.parameter_list) = NULL; ;}
     break;
 
   case 11:
-#line 279 "parser.y"
-    { (yyval.parameter_list) = NULL; ;}
+#line 283 "parser.y"
+    { (yyval.parameter_list) = (yyvsp[0].parameter_list); ;}
     break;
 
   case 12:
-#line 280 "parser.y"
-    { (yyval.parameter_list) = (yyvsp[0].parameter_list); ;}
+#line 287 "parser.y"
+    { (yyval.statement) = (yyvsp[0].statement); ;}
     break;
 
   case 13:
-#line 284 "parser.y"
+#line 288 "parser.y"
     { (yyval.statement) = (yyvsp[0].statement); ;}
     break;
 
   case 14:
-#line 285 "parser.y"
+#line 289 "parser.y"
     { (yyval.statement) = (yyvsp[0].statement); ;}
     break;
 
   case 15:
-#line 286 "parser.y"
+#line 290 "parser.y"
     { (yyval.statement) = (yyvsp[0].statement); ;}
     break;
 
   case 16:
-#line 287 "parser.y"
+#line 291 "parser.y"
     { (yyval.statement) = (yyvsp[0].statement); ;}
     break;
 
   case 17:
-#line 288 "parser.y"
+#line 292 "parser.y"
     { (yyval.statement) = (yyvsp[0].statement); ;}
     break;
 
   case 18:
-#line 289 "parser.y"
+#line 293 "parser.y"
     { (yyval.statement) = (yyvsp[0].statement); ;}
     break;
 
   case 19:
-#line 290 "parser.y"
+#line 294 "parser.y"
     { (yyval.statement) = (yyvsp[0].statement); ;}
     break;
 
   case 20:
-#line 291 "parser.y"
+#line 295 "parser.y"
     { (yyval.statement) = (yyvsp[0].statement); ;}
     break;
 
   case 21:
-#line 292 "parser.y"
+#line 296 "parser.y"
     { (yyval.statement) = (yyvsp[0].statement); ;}
     break;
 
   case 22:
-#line 293 "parser.y"
+#line 297 "parser.y"
     { (yyval.statement) = (yyvsp[0].statement); ;}
     break;
 
   case 23:
-#line 294 "parser.y"
+#line 298 "parser.y"
     { (yyval.statement) = (yyvsp[0].statement); ;}
     break;
 
   case 24:
-#line 295 "parser.y"
+#line 299 "parser.y"
     { (yyval.statement) = (yyvsp[0].statement); ;}
     break;
 
   case 25:
-#line 296 "parser.y"
+#line 300 "parser.y"
     { (yyval.statement) = (yyvsp[0].statement); ;}
     break;
 
   case 26:
-#line 297 "parser.y"
-    { (yyval.statement) = (yyvsp[0].statement); ;}
+#line 304 "parser.y"
+    { (yyval.statement_list) = new_statement_list(ctx, (yyvsp[0].statement)); ;}
     break;
 
   case 27:
-#line 301 "parser.y"
-    { (yyval.statement_list) = new_statement_list(ctx, (yyvsp[0].statement)); ;}
+#line 306 "parser.y"
+    { (yyval.statement_list) = statement_list_add((yyvsp[-1].statement_list), (yyvsp[0].statement)); ;}
     break;
 
   case 28:
-#line 303 "parser.y"
-    { (yyval.statement_list) = statement_list_add((yyvsp[-1].statement_list), (yyvsp[0].statement)); ;}
+#line 310 "parser.y"
+    { (yyval.statement_list) = NULL; ;}
     break;
 
   case 29:
-#line 307 "parser.y"
-    { (yyval.statement_list) = NULL; ;}
+#line 311 "parser.y"
+    { (yyval.statement_list) = (yyvsp[0].statement_list); ;}
     break;
 
   case 30:
-#line 308 "parser.y"
-    { (yyval.statement_list) = (yyvsp[0].statement_list); ;}
+#line 315 "parser.y"
+    { (yyval.statement) = new_block_statement(ctx, (yyvsp[-1].statement_list)); ;}
     break;
 
   case 31:
-#line 313 "parser.y"
-    { (yyval.statement) = new_block_statement(ctx, (yyvsp[-1].statement_list)); ;}
+#line 316 "parser.y"
+    { (yyval.statement) = new_block_statement(ctx, NULL); ;}
     break;
 
   case 32:
-#line 318 "parser.y"
+#line 321 "parser.y"
     { (yyval.statement) = new_var_statement(ctx, (yyvsp[-1].variable_list)); ;}
     break;
 
   case 33:
-#line 322 "parser.y"
+#line 325 "parser.y"
     { (yyval.variable_list) = new_variable_list(ctx, (yyvsp[0].variable_declaration)); ;}
     break;
 
   case 34:
-#line 324 "parser.y"
+#line 327 "parser.y"
     { (yyval.variable_list) = variable_list_add(ctx, (yyvsp[-2].variable_list), (yyvsp[0].variable_declaration)); ;}
     break;
 
   case 35:
-#line 329 "parser.y"
+#line 332 "parser.y"
     { (yyval.variable_list) = new_variable_list(ctx, (yyvsp[0].variable_declaration)); ;}
     break;
 
   case 36:
-#line 331 "parser.y"
+#line 334 "parser.y"
     { (yyval.variable_list) = variable_list_add(ctx, (yyvsp[-2].variable_list), (yyvsp[0].variable_declaration)); ;}
     break;
 
   case 37:
-#line 336 "parser.y"
+#line 339 "parser.y"
     { (yyval.variable_declaration) = new_variable_declaration(ctx, (yyvsp[-1].identifier), (yyvsp[0].expr)); ;}
     break;
 
   case 38:
-#line 341 "parser.y"
+#line 344 "parser.y"
     { (yyval.variable_declaration) = new_variable_declaration(ctx, (yyvsp[-1].identifier), (yyvsp[0].expr)); ;}
     break;
 
   case 39:
-#line 345 "parser.y"
+#line 348 "parser.y"
     { (yyval.expr) = NULL; ;}
     break;
 
   case 40:
-#line 346 "parser.y"
+#line 349 "parser.y"
     { (yyval.expr) = (yyvsp[0].expr); ;}
     break;
 
   case 41:
-#line 351 "parser.y"
+#line 354 "parser.y"
     { (yyval.expr) = (yyvsp[0].expr); ;}
     break;
 
   case 42:
-#line 355 "parser.y"
+#line 358 "parser.y"
     { (yyval.expr) = NULL; ;}
     break;
 
   case 43:
-#line 356 "parser.y"
+#line 359 "parser.y"
     { (yyval.expr) = (yyvsp[0].expr); ;}
     break;
 
   case 44:
-#line 361 "parser.y"
+#line 364 "parser.y"
     { (yyval.expr) = (yyvsp[0].expr); ;}
     break;
 
   case 45:
-#line 365 "parser.y"
+#line 368 "parser.y"
     { (yyval.statement) = new_empty_statement(ctx); ;}
     break;
 
   case 46:
-#line 370 "parser.y"
+#line 373 "parser.y"
     { (yyval.statement) = new_expression_statement(ctx, (yyvsp[-1].expr)); ;}
     break;
 
   case 47:
-#line 375 "parser.y"
+#line 378 "parser.y"
     { (yyval.statement) = new_if_statement(ctx, (yyvsp[-4].expr), (yyvsp[-2].statement), (yyvsp[0].statement)); ;}
     break;
 
   case 48:
-#line 377 "parser.y"
+#line 380 "parser.y"
     { (yyval.statement) = new_if_statement(ctx, (yyvsp[-2].expr), (yyvsp[0].statement), NULL); ;}
     break;
 
   case 49:
-#line 382 "parser.y"
+#line 385 "parser.y"
     { (yyval.statement) = new_while_statement(ctx, TRUE, (yyvsp[-2].expr), (yyvsp[-5].statement)); ;}
     break;
 
   case 50:
-#line 384 "parser.y"
+#line 387 "parser.y"
     { (yyval.statement) = new_while_statement(ctx, FALSE, (yyvsp[-2].expr), (yyvsp[0].statement)); ;}
     break;
 
   case 51:
-#line 386 "parser.y"
+#line 389 "parser.y"
     { (yyval.statement) = new_for_statement(ctx, NULL, (yyvsp[-6].expr), (yyvsp[-4].expr), (yyvsp[-2].expr), (yyvsp[0].statement)); ;}
     break;
 
   case 52:
-#line 388 "parser.y"
+#line 391 "parser.y"
     { (yyval.statement) = new_for_statement(ctx, (yyvsp[-6].variable_list), NULL, (yyvsp[-4].expr), (yyvsp[-2].expr), (yyvsp[0].statement)); ;}
     break;
 
   case 53:
-#line 390 "parser.y"
+#line 393 "parser.y"
     { (yyval.statement) = new_forin_statement(ctx, NULL, (yyvsp[-4].expr), (yyvsp[-2].expr), (yyvsp[0].statement)); ;}
     break;
 
   case 54:
-#line 392 "parser.y"
+#line 395 "parser.y"
     { (yyval.statement) = new_forin_statement(ctx, (yyvsp[-4].variable_declaration), NULL, (yyvsp[-2].expr), (yyvsp[0].statement)); ;}
     break;
 
   case 55:
-#line 397 "parser.y"
+#line 400 "parser.y"
     { (yyval.statement) = new_continue_statement(ctx, (yyvsp[-1].identifier)); ;}
     break;
 
   case 56:
-#line 402 "parser.y"
+#line 405 "parser.y"
     { (yyval.statement) = new_break_statement(ctx, (yyvsp[-1].identifier)); ;}
     break;
 
   case 57:
-#line 407 "parser.y"
+#line 410 "parser.y"
     { (yyval.statement) = new_return_statement(ctx, (yyvsp[-1].expr)); ;}
     break;
 
   case 58:
-#line 412 "parser.y"
+#line 415 "parser.y"
     { (yyval.statement) = new_with_statement(ctx, (yyvsp[-2].expr), (yyvsp[0].statement)); ;}
     break;
 
   case 59:
-#line 417 "parser.y"
+#line 420 "parser.y"
     { (yyval.statement) = new_labelled_statement(ctx, (yyvsp[-2].identifier), (yyvsp[0].statement)); ;}
     break;
 
   case 60:
-#line 422 "parser.y"
+#line 425 "parser.y"
     { (yyval.statement) = new_switch_statement(ctx, (yyvsp[-2].expr), (yyvsp[0].case_clausule)); ;}
     break;
 
   case 61:
-#line 427 "parser.y"
+#line 430 "parser.y"
     { (yyval.case_clausule) = new_case_block(ctx, (yyvsp[-1].case_list), NULL, NULL); ;}
     break;
 
   case 62:
-#line 429 "parser.y"
+#line 432 "parser.y"
     { (yyval.case_clausule) = new_case_block(ctx, (yyvsp[-3].case_list), (yyvsp[-2].case_clausule), (yyvsp[-1].case_list)); ;}
     break;
 
   case 63:
-#line 433 "parser.y"
+#line 436 "parser.y"
     { (yyval.case_list) = NULL; ;}
     break;
 
   case 64:
-#line 434 "parser.y"
+#line 437 "parser.y"
     { (yyval.case_list) = (yyvsp[0].case_list); ;}
     break;
 
   case 65:
-#line 438 "parser.y"
+#line 441 "parser.y"
     { (yyval.case_list) = new_case_list(ctx, (yyvsp[0].case_clausule)); ;}
     break;
 
   case 66:
-#line 440 "parser.y"
+#line 443 "parser.y"
     { (yyval.case_list) = case_list_add(ctx, (yyvsp[-1].case_list), (yyvsp[0].case_clausule)); ;}
     break;
 
   case 67:
-#line 445 "parser.y"
+#line 448 "parser.y"
     { (yyval.case_clausule) = new_case_clausule(ctx, (yyvsp[-2].expr), (yyvsp[0].statement_list)); ;}
     break;
 
   case 68:
-#line 450 "parser.y"
+#line 453 "parser.y"
     { (yyval.case_clausule) = new_case_clausule(ctx, NULL, (yyvsp[0].statement_list)); ;}
     break;
 
   case 69:
-#line 455 "parser.y"
+#line 458 "parser.y"
     { (yyval.statement) = new_throw_statement(ctx, (yyvsp[-1].expr)); ;}
     break;
 
   case 70:
-#line 459 "parser.y"
+#line 462 "parser.y"
     { (yyval.statement) = new_try_statement(ctx, (yyvsp[-1].statement), (yyvsp[0].catch_block), NULL); ;}
     break;
 
   case 71:
-#line 460 "parser.y"
+#line 463 "parser.y"
     { (yyval.statement) = new_try_statement(ctx, (yyvsp[-1].statement), NULL, (yyvsp[0].statement)); ;}
     break;
 
   case 72:
-#line 462 "parser.y"
+#line 465 "parser.y"
     { (yyval.statement) = new_try_statement(ctx, (yyvsp[-2].statement), (yyvsp[-1].catch_block), (yyvsp[0].statement)); ;}
     break;
 
   case 73:
-#line 467 "parser.y"
+#line 470 "parser.y"
     { (yyval.catch_block) = new_catch_block(ctx, (yyvsp[-2].identifier), (yyvsp[0].statement)); ;}
     break;
 
   case 74:
-#line 471 "parser.y"
+#line 474 "parser.y"
     { (yyval.statement) = (yyvsp[0].statement); ;}
     break;
 
   case 75:
-#line 475 "parser.y"
+#line 478 "parser.y"
     { (yyval.expr) = NULL; ;}
     break;
 
   case 76:
-#line 476 "parser.y"
+#line 479 "parser.y"
     { (yyval.expr) = (yyvsp[0].expr); ;}
     break;
 
   case 77:
-#line 480 "parser.y"
+#line 483 "parser.y"
     { (yyval.expr) = (yyvsp[0].expr); ;}
     break;
 
   case 78:
-#line 482 "parser.y"
+#line 485 "parser.y"
     { (yyval.expr) = new_binary_expression(ctx, EXPR_COMMA, (yyvsp[-2].expr), (yyvsp[0].expr)); ;}
     break;
 
   case 79:
-#line 486 "parser.y"
+#line 489 "parser.y"
     { (yyval.expr) = NULL; ;}
     break;
 
   case 80:
-#line 487 "parser.y"
+#line 490 "parser.y"
     { (yyval.expr) = (yyvsp[0].expr); ;}
     break;
 
   case 81:
-#line 492 "parser.y"
+#line 495 "parser.y"
     { (yyval.expr) = (yyvsp[0].expr); ;}
     break;
 
   case 82:
-#line 494 "parser.y"
+#line 497 "parser.y"
     { (yyval.expr) = new_binary_expression(ctx, EXPR_COMMA, (yyvsp[-2].expr), (yyvsp[0].expr)); ;}
     break;
 
   case 83:
-#line 498 "parser.y"
+#line 501 "parser.y"
     { (yyval.expr) = (yyvsp[0].expr); ;}
     break;
 
   case 84:
-#line 500 "parser.y"
+#line 503 "parser.y"
     { (yyval.expr) = new_binary_expression(ctx, EXPR_ASSIGN, (yyvsp[-2].expr), (yyvsp[0].expr)); ;}
     break;
 
   case 85:
-#line 502 "parser.y"
+#line 505 "parser.y"
     { (yyval.expr) = new_binary_expression(ctx, (yyvsp[-1].ival), (yyvsp[-2].expr), (yyvsp[0].expr)); ;}
     break;
 
   case 86:
-#line 507 "parser.y"
+#line 510 "parser.y"
     { (yyval.expr) = (yyvsp[0].expr); ;}
     break;
 
   case 87:
-#line 509 "parser.y"
+#line 512 "parser.y"
     { (yyval.expr) = new_binary_expression(ctx, EXPR_ASSIGN, (yyvsp[-2].expr), (yyvsp[0].expr)); ;}
     break;
 
   case 88:
-#line 511 "parser.y"
+#line 514 "parser.y"
     { (yyval.expr) = new_binary_expression(ctx, (yyvsp[-1].ival), (yyvsp[-2].expr), (yyvsp[0].expr)); ;}
     break;
 
   case 89:
-#line 515 "parser.y"
+#line 518 "parser.y"
     { (yyval.expr) = (yyvsp[0].expr); ;}
     break;
 
   case 90:
-#line 517 "parser.y"
+#line 520 "parser.y"
     { (yyval.expr) = new_conditional_expression(ctx, (yyvsp[-4].expr), (yyvsp[-2].expr), (yyvsp[0].expr)); ;}
     break;
 
   case 91:
-#line 522 "parser.y"
+#line 525 "parser.y"
     { (yyval.expr) = (yyvsp[0].expr); ;}
     break;
 
   case 92:
-#line 524 "parser.y"
+#line 527 "parser.y"
     { (yyval.expr) = new_conditional_expression(ctx, (yyvsp[-4].expr), (yyvsp[-2].expr), (yyvsp[0].expr)); ;}
     break;
 
   case 93:
-#line 528 "parser.y"
+#line 531 "parser.y"
     { (yyval.expr) = (yyvsp[0].expr); ;}
     break;
 
   case 94:
-#line 530 "parser.y"
+#line 533 "parser.y"
     { (yyval.expr) = new_binary_expression(ctx, EXPR_OR, (yyvsp[-2].expr), (yyvsp[0].expr)); ;}
     break;
 
   case 95:
-#line 535 "parser.y"
+#line 538 "parser.y"
     { (yyval.expr) = (yyvsp[0].expr); ;}
     break;
 
   case 96:
-#line 537 "parser.y"
+#line 540 "parser.y"
     { (yyval.expr) = new_binary_expression(ctx, EXPR_OR, (yyvsp[-2].expr), (yyvsp[0].expr)); ;}
     break;
 
   case 97:
-#line 541 "parser.y"
+#line 544 "parser.y"
     { (yyval.expr) = (yyvsp[0].expr); ;}
     break;
 
   case 98:
-#line 543 "parser.y"
+#line 546 "parser.y"
     { (yyval.expr) = new_binary_expression(ctx, EXPR_AND, (yyvsp[-2].expr), (yyvsp[0].expr)); ;}
     break;
 
   case 99:
-#line 548 "parser.y"
+#line 551 "parser.y"
     { (yyval.expr) = (yyvsp[0].expr); ;}
     break;
 
   case 100:
-#line 550 "parser.y"
+#line 553 "parser.y"
     { (yyval.expr) = new_binary_expression(ctx, EXPR_AND, (yyvsp[-2].expr), (yyvsp[0].expr)); ;}
     break;
 
   case 101:
-#line 554 "parser.y"
+#line 557 "parser.y"
     { (yyval.expr) = (yyvsp[0].expr); ;}
     break;
 
   case 102:
-#line 556 "parser.y"
+#line 559 "parser.y"
     { (yyval.expr) = new_binary_expression(ctx, EXPR_BOR, (yyvsp[-2].expr), (yyvsp[0].expr)); ;}
     break;
 
   case 103:
-#line 561 "parser.y"
+#line 564 "parser.y"
     { (yyval.expr) = (yyvsp[0].expr); ;}
     break;
 
   case 104:
-#line 563 "parser.y"
+#line 566 "parser.y"
     { (yyval.expr) = new_binary_expression(ctx, EXPR_BOR, (yyvsp[-2].expr), (yyvsp[0].expr)); ;}
     break;
 
   case 105:
-#line 567 "parser.y"
+#line 570 "parser.y"
     { (yyval.expr) = (yyvsp[0].expr); ;}
     break;
 
   case 106:
-#line 569 "parser.y"
+#line 572 "parser.y"
     { (yyval.expr) = new_binary_expression(ctx, EXPR_BXOR, (yyvsp[-2].expr), (yyvsp[0].expr)); ;}
     break;
 
   case 107:
-#line 574 "parser.y"
+#line 577 "parser.y"
     { (yyval.expr) = (yyvsp[0].expr); ;}
     break;
 
   case 108:
-#line 576 "parser.y"
+#line 579 "parser.y"
     { (yyval.expr) = new_binary_expression(ctx, EXPR_BXOR, (yyvsp[-2].expr), (yyvsp[0].expr)); ;}
     break;
 
   case 109:
-#line 580 "parser.y"
+#line 583 "parser.y"
     { (yyval.expr) = (yyvsp[0].expr); ;}
     break;
 
   case 110:
-#line 582 "parser.y"
+#line 585 "parser.y"
     { (yyval.expr) = new_binary_expression(ctx, EXPR_BAND, (yyvsp[-2].expr), (yyvsp[0].expr)); ;}
     break;
 
   case 111:
-#line 587 "parser.y"
+#line 590 "parser.y"
     { (yyval.expr) = (yyvsp[0].expr); ;}
     break;
 
   case 112:
-#line 589 "parser.y"
+#line 592 "parser.y"
     { (yyval.expr) = new_binary_expression(ctx, EXPR_BAND, (yyvsp[-2].expr), (yyvsp[0].expr)); ;}
     break;
 
   case 113:
-#line 593 "parser.y"
+#line 596 "parser.y"
     { (yyval.expr) = (yyvsp[0].expr); ;}
     break;
 
   case 114:
-#line 595 "parser.y"
+#line 598 "parser.y"
     { (yyval.expr) = new_binary_expression(ctx, (yyvsp[-1].ival), (yyvsp[-2].expr), (yyvsp[0].expr)); ;}
     break;
 
   case 115:
-#line 599 "parser.y"
+#line 602 "parser.y"
     { (yyval.expr) = (yyvsp[0].expr); ;}
     break;
 
   case 116:
-#line 601 "parser.y"
+#line 604 "parser.y"
     { (yyval.expr) = new_binary_expression(ctx, (yyvsp[-1].ival), (yyvsp[-2].expr), (yyvsp[0].expr)); ;}
     break;
 
   case 117:
-#line 605 "parser.y"
+#line 608 "parser.y"
     { (yyval.expr) = (yyvsp[0].expr); ;}
     break;
 
   case 118:
-#line 607 "parser.y"
+#line 610 "parser.y"
     { (yyval.expr) = new_binary_expression(ctx, (yyvsp[-1].ival), (yyvsp[-2].expr), (yyvsp[0].expr)); ;}
     break;
 
   case 119:
-#line 609 "parser.y"
+#line 612 "parser.y"
     { (yyval.expr) = new_binary_expression(ctx, EXPR_INSTANCEOF, (yyvsp[-2].expr), (yyvsp[0].expr)); ;}
     break;
 
   case 120:
-#line 611 "parser.y"
+#line 614 "parser.y"
     { (yyval.expr) = new_binary_expression(ctx, EXPR_IN, (yyvsp[-2].expr), (yyvsp[0].expr)); ;}
     break;
 
   case 121:
-#line 615 "parser.y"
+#line 618 "parser.y"
     { (yyval.expr) = (yyvsp[0].expr); ;}
     break;
 
   case 122:
-#line 617 "parser.y"
+#line 620 "parser.y"
     { (yyval.expr) = new_binary_expression(ctx, (yyvsp[-1].ival), (yyvsp[-2].expr), (yyvsp[0].expr)); ;}
     break;
 
   case 123:
-#line 619 "parser.y"
+#line 622 "parser.y"
     { (yyval.expr) = new_binary_expression(ctx, EXPR_INSTANCEOF, (yyvsp[-2].expr), (yyvsp[0].expr)); ;}
     break;
 
   case 124:
-#line 623 "parser.y"
+#line 626 "parser.y"
     { (yyval.expr) = (yyvsp[0].expr); ;}
     break;
 
   case 125:
-#line 625 "parser.y"
+#line 628 "parser.y"
     { (yyval.expr) = new_binary_expression(ctx, (yyvsp[-1].ival), (yyvsp[-2].expr), (yyvsp[0].expr)); ;}
     break;
 
   case 126:
-#line 630 "parser.y"
+#line 633 "parser.y"
     { (yyval.expr) = (yyvsp[0].expr); ;}
     break;
 
   case 127:
-#line 632 "parser.y"
+#line 635 "parser.y"
     { (yyval.expr) = new_binary_expression(ctx, EXPR_ADD, (yyvsp[-2].expr), (yyvsp[0].expr)); ;}
     break;
 
   case 128:
-#line 634 "parser.y"
+#line 637 "parser.y"
     { (yyval.expr) = new_binary_expression(ctx, EXPR_SUB, (yyvsp[-2].expr), (yyvsp[0].expr)); ;}
     break;
 
   case 129:
-#line 638 "parser.y"
+#line 641 "parser.y"
     { (yyval.expr) = (yyvsp[0].expr); ;}
     break;
 
   case 130:
-#line 640 "parser.y"
+#line 643 "parser.y"
     { (yyval.expr) = new_binary_expression(ctx, EXPR_MUL, (yyvsp[-2].expr), (yyvsp[0].expr)); ;}
     break;
 
   case 131:
-#line 642 "parser.y"
+#line 645 "parser.y"
     { (yyval.expr) = new_binary_expression(ctx, EXPR_DIV, (yyvsp[-2].expr), (yyvsp[0].expr)); ;}
     break;
 
   case 132:
-#line 644 "parser.y"
+#line 647 "parser.y"
     { (yyval.expr) = new_binary_expression(ctx, EXPR_MOD, (yyvsp[-2].expr), (yyvsp[0].expr)); ;}
     break;
 
   case 133:
-#line 648 "parser.y"
+#line 651 "parser.y"
     { (yyval.expr) = (yyvsp[0].expr); ;}
     break;
 
   case 134:
-#line 650 "parser.y"
+#line 653 "parser.y"
     { (yyval.expr) = new_unary_expression(ctx, EXPR_DELETE, (yyvsp[0].expr)); ;}
     break;
 
   case 135:
-#line 651 "parser.y"
+#line 654 "parser.y"
     { (yyval.expr) = new_unary_expression(ctx, EXPR_VOID, (yyvsp[0].expr)); ;}
     break;
 
   case 136:
-#line 653 "parser.y"
+#line 656 "parser.y"
     { (yyval.expr) = new_unary_expression(ctx, EXPR_TYPEOF, (yyvsp[0].expr)); ;}
     break;
 
   case 137:
-#line 654 "parser.y"
+#line 657 "parser.y"
     { (yyval.expr) = new_unary_expression(ctx, EXPR_PREINC, (yyvsp[0].expr)); ;}
     break;
 
   case 138:
-#line 655 "parser.y"
+#line 658 "parser.y"
     { (yyval.expr) = new_unary_expression(ctx, EXPR_PREDEC, (yyvsp[0].expr)); ;}
     break;
 
   case 139:
-#line 656 "parser.y"
+#line 659 "parser.y"
     { (yyval.expr) = new_unary_expression(ctx, EXPR_PLUS, (yyvsp[0].expr)); ;}
     break;
 
   case 140:
-#line 657 "parser.y"
+#line 660 "parser.y"
     { (yyval.expr) = new_unary_expression(ctx, EXPR_MINUS, (yyvsp[0].expr)); ;}
     break;
 
   case 141:
-#line 658 "parser.y"
+#line 661 "parser.y"
     { (yyval.expr) = new_unary_expression(ctx, EXPR_BITNEG, (yyvsp[0].expr)); ;}
     break;
 
   case 142:
-#line 659 "parser.y"
+#line 662 "parser.y"
     { (yyval.expr) = new_unary_expression(ctx, EXPR_LOGNEG, (yyvsp[0].expr)); ;}
     break;
 
   case 143:
-#line 664 "parser.y"
+#line 667 "parser.y"
     { (yyval.expr) = (yyvsp[0].expr); ;}
     break;
 
   case 144:
-#line 666 "parser.y"
+#line 669 "parser.y"
     { (yyval.expr) = new_unary_expression(ctx, EXPR_POSTINC, (yyvsp[-1].expr)); ;}
     break;
 
   case 145:
-#line 668 "parser.y"
+#line 671 "parser.y"
     { (yyval.expr) = new_unary_expression(ctx, EXPR_POSTDEC, (yyvsp[-1].expr)); ;}
     break;
 
   case 146:
-#line 673 "parser.y"
+#line 676 "parser.y"
     { (yyval.expr) = (yyvsp[0].expr); ;}
     break;
 
   case 147:
-#line 674 "parser.y"
+#line 677 "parser.y"
     { (yyval.expr) = (yyvsp[0].expr); ;}
     break;
 
   case 148:
-#line 678 "parser.y"
+#line 681 "parser.y"
     { (yyval.expr) = (yyvsp[0].expr); ;}
     break;
 
   case 149:
-#line 679 "parser.y"
+#line 682 "parser.y"
     { (yyval.expr) = new_new_expression(ctx, (yyvsp[0].expr), NULL); ;}
     break;
 
   case 150:
-#line 683 "parser.y"
+#line 686 "parser.y"
     { (yyval.expr) = (yyvsp[0].expr); ;}
     break;
 
   case 151:
-#line 684 "parser.y"
+#line 687 "parser.y"
     { (yyval.expr) = (yyvsp[0].expr); ;}
     break;
 
   case 152:
-#line 686 "parser.y"
+#line 689 "parser.y"
     { (yyval.expr) = new_array_expression(ctx, (yyvsp[-3].expr), (yyvsp[-1].expr)); ;}
     break;
 
   case 153:
-#line 688 "parser.y"
+#line 691 "parser.y"
     { (yyval.expr) = new_member_expression(ctx, (yyvsp[-2].expr), (yyvsp[0].identifier)); ;}
     break;
 
   case 154:
-#line 690 "parser.y"
+#line 693 "parser.y"
     { (yyval.expr) = new_new_expression(ctx, (yyvsp[-1].expr), (yyvsp[0].argument_list)); ;}
     break;
 
   case 155:
-#line 695 "parser.y"
+#line 698 "parser.y"
     { (yyval.expr) = new_call_expression(ctx, (yyvsp[-1].expr), (yyvsp[0].argument_list)); ;}
     break;
 
   case 156:
-#line 697 "parser.y"
+#line 700 "parser.y"
     { (yyval.expr) = new_call_expression(ctx, (yyvsp[-1].expr), (yyvsp[0].argument_list)); ;}
     break;
 
   case 157:
-#line 699 "parser.y"
+#line 702 "parser.y"
     { (yyval.expr) = new_array_expression(ctx, (yyvsp[-3].expr), (yyvsp[-1].expr)); ;}
     break;
 
   case 158:
-#line 701 "parser.y"
+#line 704 "parser.y"
     { (yyval.expr) = new_member_expression(ctx, (yyvsp[-2].expr), (yyvsp[0].identifier)); ;}
     break;
 
   case 159:
-#line 705 "parser.y"
+#line 708 "parser.y"
     { (yyval.argument_list) = NULL; ;}
     break;
 
   case 160:
-#line 706 "parser.y"
+#line 709 "parser.y"
     { (yyval.argument_list) = (yyvsp[-1].argument_list); ;}
     break;
 
   case 161:
-#line 710 "parser.y"
+#line 713 "parser.y"
     { (yyval.argument_list) = new_argument_list(ctx, (yyvsp[0].expr)); ;}
     break;
 
   case 162:
-#line 712 "parser.y"
+#line 715 "parser.y"
     { (yyval.argument_list) = argument_list_add(ctx, (yyvsp[-2].argument_list), (yyvsp[0].expr)); ;}
     break;
 
   case 163:
-#line 716 "parser.y"
+#line 719 "parser.y"
     { (yyval.expr) = new_this_expression(ctx); ;}
     break;
 
   case 164:
-#line 717 "parser.y"
+#line 720 "parser.y"
     { (yyval.expr) = new_identifier_expression(ctx, (yyvsp[0].identifier)); ;}
     break;
 
   case 165:
-#line 718 "parser.y"
+#line 721 "parser.y"
     { (yyval.expr) = new_literal_expression(ctx, (yyvsp[0].literal)); ;}
     break;
 
   case 166:
-#line 719 "parser.y"
+#line 722 "parser.y"
     { (yyval.expr) = (yyvsp[0].expr); ;}
     break;
 
   case 167:
-#line 720 "parser.y"
+#line 723 "parser.y"
     { (yyval.expr) = (yyvsp[0].expr); ;}
     break;
 
   case 168:
-#line 721 "parser.y"
+#line 724 "parser.y"
     { (yyval.expr) = (yyvsp[-1].expr); ;}
     break;
 
   case 169:
-#line 725 "parser.y"
-    { (yyval.expr) = new_array_literal_expression(ctx, NULL, (yyvsp[-1].ival)); ;}
+#line 728 "parser.y"
+    { (yyval.expr) = new_array_literal_expression(ctx, NULL, 0); ;}
     break;
 
   case 170:
-#line 726 "parser.y"
-    { (yyval.expr) = new_array_literal_expression(ctx, (yyvsp[-1].element_list), 0); ;}
+#line 729 "parser.y"
+    { (yyval.expr) = new_array_literal_expression(ctx, NULL, (yyvsp[-1].ival)+1); ;}
     break;
 
   case 171:
-#line 728 "parser.y"
-    { (yyval.expr) = new_array_literal_expression(ctx, (yyvsp[-3].element_list), (yyvsp[-1].ival)); ;}
+#line 730 "parser.y"
+    { (yyval.expr) = new_array_literal_expression(ctx, (yyvsp[-1].element_list), 0); ;}
     break;
 
   case 172:
-#line 733 "parser.y"
-    { (yyval.element_list) = new_element_list(ctx, (yyvsp[-1].ival), (yyvsp[0].expr)); ;}
+#line 732 "parser.y"
+    { (yyval.expr) = new_array_literal_expression(ctx, (yyvsp[-3].element_list), (yyvsp[-1].ival)+1); ;}
     break;
 
   case 173:
-#line 735 "parser.y"
-    { (yyval.element_list) = element_list_add(ctx, (yyvsp[-3].element_list), (yyvsp[-1].ival), (yyvsp[0].expr)); ;}
+#line 737 "parser.y"
+    { (yyval.element_list) = new_element_list(ctx, (yyvsp[-1].ival), (yyvsp[0].expr)); ;}
     break;
 
   case 174:
 #line 739 "parser.y"
-    { (yyval.ival) = 1; ;}
+    { (yyval.element_list) = element_list_add(ctx, (yyvsp[-3].element_list), (yyvsp[-1].ival), (yyvsp[0].expr)); ;}
     break;
 
   case 175:
-#line 740 "parser.y"
-    { (yyval.ival) = (yyvsp[-1].ival) + 1; ;}
+#line 743 "parser.y"
+    { (yyval.ival) = 1; ;}
     break;
 
   case 176:
 #line 744 "parser.y"
-    { (yyval.ival) = 0; ;}
+    { (yyval.ival) = (yyvsp[-1].ival) + 1; ;}
     break;
 
   case 177:
-#line 745 "parser.y"
-    { (yyval.ival) = (yyvsp[0].ival); ;}
+#line 748 "parser.y"
+    { (yyval.ival) = 0; ;}
     break;
 
   case 178:
 #line 749 "parser.y"
-    { (yyval.expr) = new_prop_and_value_expression(ctx, NULL); ;}
+    { (yyval.ival) = (yyvsp[0].ival); ;}
     break;
 
   case 179:
-#line 751 "parser.y"
-    { (yyval.expr) = new_prop_and_value_expression(ctx, (yyvsp[-1].property_list)); ;}
+#line 753 "parser.y"
+    { (yyval.expr) = new_prop_and_value_expression(ctx, NULL); ;}
     break;
 
   case 180:
-#line 756 "parser.y"
-    { (yyval.property_list) = new_property_list(ctx, (yyvsp[-2].literal), (yyvsp[0].expr)); ;}
+#line 755 "parser.y"
+    { (yyval.expr) = new_prop_and_value_expression(ctx, (yyvsp[-1].property_list)); ;}
     break;
 
   case 181:
-#line 758 "parser.y"
-    { (yyval.property_list) = property_list_add(ctx, (yyvsp[-4].property_list), (yyvsp[-2].literal), (yyvsp[0].expr)); ;}
+#line 760 "parser.y"
+    { (yyval.property_list) = new_property_list(ctx, (yyvsp[-2].literal), (yyvsp[0].expr)); ;}
     break;
 
   case 182:
 #line 762 "parser.y"
-    { (yyval.literal) = new_string_literal(ctx, (yyvsp[0].identifier)); ;}
+    { (yyval.property_list) = property_list_add(ctx, (yyvsp[-4].property_list), (yyvsp[-2].literal), (yyvsp[0].expr)); ;}
     break;
 
   case 183:
-#line 763 "parser.y"
-    { (yyval.literal) = new_string_literal(ctx, (yyvsp[0].wstr)); ;}
+#line 766 "parser.y"
+    { (yyval.literal) = new_string_literal(ctx, (yyvsp[0].identifier)); ;}
     break;
 
   case 184:
-#line 764 "parser.y"
-    { (yyval.literal) = (yyvsp[0].literal); ;}
+#line 767 "parser.y"
+    { (yyval.literal) = new_string_literal(ctx, (yyvsp[0].wstr)); ;}
     break;
 
   case 185:
 #line 768 "parser.y"
-    { (yyval.identifier) = NULL; ;}
+    { (yyval.literal) = (yyvsp[0].literal); ;}
     break;
 
   case 186:
-#line 769 "parser.y"
-    { (yyval.identifier) = (yyvsp[0].identifier); ;}
+#line 772 "parser.y"
+    { (yyval.identifier) = NULL; ;}
     break;
 
   case 187:
 #line 773 "parser.y"
-    { (yyval.literal) = new_null_literal(ctx); ;}
+    { (yyval.identifier) = (yyvsp[0].identifier); ;}
     break;
 
   case 188:
-#line 774 "parser.y"
-    { (yyval.literal) = new_undefined_literal(ctx); ;}
+#line 777 "parser.y"
+    { (yyval.literal) = new_null_literal(ctx); ;}
     break;
 
   case 189:
-#line 775 "parser.y"
-    { (yyval.literal) = (yyvsp[0].literal); ;}
+#line 778 "parser.y"
+    { (yyval.literal) = new_undefined_literal(ctx); ;}
     break;
 
   case 190:
-#line 776 "parser.y"
+#line 779 "parser.y"
     { (yyval.literal) = (yyvsp[0].literal); ;}
     break;
 
   case 191:
-#line 777 "parser.y"
-    { (yyval.literal) = new_string_literal(ctx, (yyvsp[0].wstr)); ;}
+#line 780 "parser.y"
+    { (yyval.literal) = (yyvsp[0].literal); ;}
     break;
 
   case 192:
-#line 778 "parser.y"
+#line 781 "parser.y"
+    { (yyval.literal) = new_string_literal(ctx, (yyvsp[0].wstr)); ;}
+    break;
+
+  case 193:
+#line 782 "parser.y"
     { (yyval.literal) = parse_regexp(ctx);
                                   if(!(yyval.literal)) YYABORT; ;}
     break;
 
-  case 193:
-#line 783 "parser.y"
+  case 194:
+#line 787 "parser.y"
     { (yyval.literal) = new_boolean_literal(ctx, TRUE); ;}
     break;
 
-  case 194:
-#line 784 "parser.y"
+  case 195:
+#line 788 "parser.y"
     { (yyval.literal) = new_boolean_literal(ctx, FALSE); ;}
     break;
 
-  case 196:
-#line 788 "parser.y"
+  case 197:
+#line 792 "parser.y"
     { if(!allow_auto_semicolon(ctx)) {YYABORT;} ;}
     break;
 
@@ -2733,7 +2750,7 @@ yyreduce:
     }
 
 /* Line 1126 of yacc.c.  */
-#line 2737 "parser.tab.c"
+#line 2754 "parser.tab.c"
 \f
   yyvsp -= yylen;
   yyssp -= yylen;
@@ -3001,7 +3018,7 @@ yyreturn:
 }
 
 
-#line 790 "parser.y"
+#line 794 "parser.y"
 
 
 static BOOL allow_auto_semicolon(parser_ctx_t *ctx)
@@ -3228,11 +3245,20 @@ static statement_t *new_block_statement(parser_ctx_t *ctx, statement_list_t *lis
 static variable_declaration_t *new_variable_declaration(parser_ctx_t *ctx, const WCHAR *identifier, expression_t *expr)
 {
     variable_declaration_t *ret = parser_alloc(ctx, sizeof(variable_declaration_t));
+    var_list_t *var_list = parser_alloc(ctx, sizeof(var_list_t));
 
     ret->identifier = identifier;
     ret->expr = expr;
     ret->next = NULL;
 
+    var_list->identifier = identifier;
+    var_list->next = NULL;
+
+    if(ctx->func_stack->var_tail)
+        ctx->func_stack->var_tail = ctx->func_stack->var_tail->next = var_list;
+    else
+        ctx->func_stack->var_head = ctx->func_stack->var_tail = var_list;
+
     return ret;
 }
 
@@ -3462,7 +3488,7 @@ static parameter_list_t *parameter_list_add(parser_ctx_t *ctx, parameter_list_t
 }
 
 static expression_t *new_function_expression(parser_ctx_t *ctx, const WCHAR *identifier,
-       parameter_list_t *parameter_list, source_elements_t *source_elements)
+       parameter_list_t *parameter_list, source_elements_t *source_elements, const WCHAR *src_str, DWORD src_len)
 {
     function_expression_t *ret = parser_alloc(ctx, sizeof(function_expression_t));
 
@@ -3470,6 +3496,20 @@ static expression_t *new_function_expression(parser_ctx_t *ctx, const WCHAR *ide
     ret->identifier = identifier;
     ret->parameter_list = parameter_list ? parameter_list->head : NULL;
     ret->source_elements = source_elements;
+    ret->src_str = src_str;
+    ret->src_len = src_len;
+
+    if(ret->identifier) {
+        function_declaration_t *decl = parser_alloc(ctx, sizeof(function_declaration_t));
+
+        decl->expr = ret;
+        decl->next = NULL;
+
+        if(ctx->func_stack->func_tail)
+            ctx->func_stack->func_tail = ctx->func_stack->func_tail->next = decl;
+        else
+            ctx->func_stack->func_head = ctx->func_stack->func_tail = decl;
+    }
 
     return &ret->expr;
 }
@@ -3658,19 +3698,6 @@ static expression_t *new_literal_expression(parser_ctx_t *ctx, literal_t *litera
     return &ret->expr;
 }
 
-static function_declaration_t *new_function_declaration(parser_ctx_t *ctx, const WCHAR *identifier,
-       parameter_list_t *parameter_list, source_elements_t *source_elements)
-{
-    function_declaration_t *ret = parser_alloc(ctx, sizeof(function_declaration_t));
-
-    ret->identifier = identifier;
-    ret->parameter_list = parameter_list ? parameter_list->head : NULL;
-    ret->source_elements = source_elements;
-    ret->next = NULL;
-
-    return ret;
-}
-
 static source_elements_t *new_source_elements(parser_ctx_t *ctx)
 {
     source_elements_t *ret = parser_alloc(ctx, sizeof(source_elements_t));
@@ -3690,18 +3717,7 @@ static source_elements_t *source_elements_add_statement(source_elements_t *sourc
     return source_elements;
 }
 
-static source_elements_t *source_elements_add_function(source_elements_t *source_elements,
-       function_declaration_t *function_declaration)
-{
-    if(source_elements->functions_tail)
-        source_elements->functions_tail = source_elements->functions_tail->next = function_declaration;
-    else
-        source_elements->functions = source_elements->functions_tail = function_declaration;
-
-    return source_elements;
-}
-
-statement_list_t *new_statement_list(parser_ctx_t *ctx, statement_t *statement)
+static statement_list_t *new_statement_list(parser_ctx_t *ctx, statement_t *statement)
 {
     statement_list_t *ret =  parser_alloc_tmp(ctx, sizeof(statement_list_t));
 
@@ -3710,15 +3726,39 @@ statement_list_t *new_statement_list(parser_ctx_t *ctx, statement_t *statement)
     return ret;
 }
 
-statement_list_t *statement_list_add(statement_list_t *list, statement_t *statement)
+static statement_list_t *statement_list_add(statement_list_t *list, statement_t *statement)
 {
     list->tail = list->tail->next = statement;
 
     return list;
 }
 
+static void push_func(parser_ctx_t *ctx)
+{
+    func_stack_t *new_func = parser_alloc_tmp(ctx, sizeof(func_stack_t));
+
+    new_func->func_head = new_func->func_tail = NULL;
+    new_func->var_head = new_func->var_tail = NULL;
+
+    new_func->next = ctx->func_stack;
+    ctx->func_stack = new_func;
+}
+
+static source_elements_t *function_body_parsed(parser_ctx_t *ctx, source_elements_t *source)
+{
+    source->functions = ctx->func_stack->func_head;
+    source->variables = ctx->func_stack->var_head;
+    pop_func(ctx);
+
+    return source;
+}
+
 static void program_parsed(parser_ctx_t *ctx, source_elements_t *source)
 {
+    source->functions = ctx->func_stack->func_head;
+    source->variables = ctx->func_stack->var_head;
+    pop_func(ctx);
+
     ctx->source = source;
     ctx->hres = S_OK;
 }
@@ -3759,6 +3799,8 @@ HRESULT script_parse(script_ctx_t *ctx, const WCHAR *code, parser_ctx_t **ret)
     mark = jsheap_mark(&ctx->tmp_heap);
     jsheap_init(&parser_ctx->heap);
 
+    push_func(parser_ctx);
+
     parser_parse(parser_ctx);
     jsheap_clear(mark);
     if(FAILED(parser_ctx->hres)) {
index 4cbdd7e..1f49d2a 100644 (file)
      kIF = 266,
      kFINALLY = 267,
      kFOR = 268,
-     kFUNCTION = 269,
-     kIN = 270,
-     kINSTANCEOF = 271,
-     kNEW = 272,
-     kNULL = 273,
-     kUNDEFINED = 274,
-     kRETURN = 275,
-     kSWITCH = 276,
-     kTHIS = 277,
-     kTHROW = 278,
-     kTRUE = 279,
-     kFALSE = 280,
-     kTRY = 281,
-     kTYPEOF = 282,
-     kVAR = 283,
-     kVOID = 284,
-     kWHILE = 285,
-     kWITH = 286,
-     tANDAND = 287,
-     tOROR = 288,
-     tINC = 289,
-     tDEC = 290,
+     kIN = 269,
+     kINSTANCEOF = 270,
+     kNEW = 271,
+     kNULL = 272,
+     kUNDEFINED = 273,
+     kRETURN = 274,
+     kSWITCH = 275,
+     kTHIS = 276,
+     kTHROW = 277,
+     kTRUE = 278,
+     kFALSE = 279,
+     kTRY = 280,
+     kTYPEOF = 281,
+     kVAR = 282,
+     kVOID = 283,
+     kWHILE = 284,
+     kWITH = 285,
+     tANDAND = 286,
+     tOROR = 287,
+     tINC = 288,
+     tDEC = 289,
+     kFUNCTION = 290,
      tIdentifier = 291,
      tAssignOper = 292,
      tEqOper = 293,
      tShiftOper = 294,
      tRelOper = 295,
      tNumericLiteral = 296,
-     tStringLiteral = 297
+     tStringLiteral = 297,
+     LOWER_THAN_ELSE = 298
    };
 #endif
 /* Tokens.  */
 #define kIF 266
 #define kFINALLY 267
 #define kFOR 268
-#define kFUNCTION 269
-#define kIN 270
-#define kINSTANCEOF 271
-#define kNEW 272
-#define kNULL 273
-#define kUNDEFINED 274
-#define kRETURN 275
-#define kSWITCH 276
-#define kTHIS 277
-#define kTHROW 278
-#define kTRUE 279
-#define kFALSE 280
-#define kTRY 281
-#define kTYPEOF 282
-#define kVAR 283
-#define kVOID 284
-#define kWHILE 285
-#define kWITH 286
-#define tANDAND 287
-#define tOROR 288
-#define tINC 289
-#define tDEC 290
+#define kIN 269
+#define kINSTANCEOF 270
+#define kNEW 271
+#define kNULL 272
+#define kUNDEFINED 273
+#define kRETURN 274
+#define kSWITCH 275
+#define kTHIS 276
+#define kTHROW 277
+#define kTRUE 278
+#define kFALSE 279
+#define kTRY 280
+#define kTYPEOF 281
+#define kVAR 282
+#define kVOID 283
+#define kWHILE 284
+#define kWITH 285
+#define tANDAND 286
+#define tOROR 287
+#define tINC 288
+#define tDEC 289
+#define kFUNCTION 290
 #define tIdentifier 291
 #define tAssignOper 292
 #define tEqOper 293
 #define tRelOper 295
 #define tNumericLiteral 296
 #define tStringLiteral 297
+#define LOWER_THAN_ELSE 298
 
 
 
 
 #if ! defined (YYSTYPE) && ! defined (YYSTYPE_IS_DECLARED)
-#line 147 "parser.y"
+#line 149 "parser.y"
 typedef union YYSTYPE {
     int                     ival;
+    const WCHAR             *srcptr;
     LPCWSTR                 wstr;
     literal_t               *literal;
     struct _argument_list_t *argument_list;
@@ -129,7 +132,6 @@ typedef union YYSTYPE {
     struct _element_list_t  *element_list;
     expression_t            *expr;
     const WCHAR            *identifier;
-    function_declaration_t  *function_declaration;
     struct _parameter_list_t *parameter_list;
     struct _property_list_t *property_list;
     source_elements_t       *source_elements;
@@ -139,7 +141,7 @@ typedef union YYSTYPE {
     variable_declaration_t  *variable_declaration;
 } YYSTYPE;
 /* Line 1447 of yacc.c.  */
-#line 143 "parser.tab.h"
+#line 145 "parser.tab.h"
 # define yystype YYSTYPE /* obsolescent; will be withdrawn */
 # define YYSTYPE_IS_DECLARED 1
 # define YYSTYPE_IS_TRIVIAL 1
index a6cb5eb..96ba29c 100644 (file)
 #include "jscript.h"
 #include "engine.h"
 
-#include "wine/debug.h"
-
-WINE_DEFAULT_DEBUG_CHANNEL(jscript);
-
 #define YYLEX_PARAM ctx
 #define YYPARSE_PARAM ctx
 
 static int parser_error(const char*);
 static BOOL allow_auto_semicolon(parser_ctx_t*);
 static void program_parsed(parser_ctx_t*,source_elements_t*);
+static source_elements_t *function_body_parsed(parser_ctx_t*,source_elements_t*);
 
 typedef struct _statement_list_t {
     statement_t *head;
@@ -109,8 +106,8 @@ struct statement_list_t {
    statement_t *tail;
 };
 
-statement_list_t *new_statement_list(parser_ctx_t*,statement_t*);
-statement_list_t *statement_list_add(statement_list_t*,statement_t*);
+static statement_list_t *new_statement_list(parser_ctx_t*,statement_t*);
+static statement_list_t *statement_list_add(statement_list_t*,statement_t*);
 
 typedef struct _parameter_list_t {
     parameter_t *head;
@@ -120,7 +117,14 @@ typedef struct _parameter_list_t {
 static parameter_list_t *new_parameter_list(parser_ctx_t*,const WCHAR*);
 static parameter_list_t *parameter_list_add(parser_ctx_t*,parameter_list_t*,const WCHAR*);
 
-static expression_t *new_function_expression(parser_ctx_t*,const WCHAR*,parameter_list_t*,source_elements_t*);
+static void push_func(parser_ctx_t*);
+static inline void pop_func(parser_ctx_t *ctx)
+{
+    ctx->func_stack = ctx->func_stack->next;
+}
+
+static expression_t *new_function_expression(parser_ctx_t*,const WCHAR*,parameter_list_t*,
+        source_elements_t*,const WCHAR*,DWORD);
 static expression_t *new_binary_expression(parser_ctx_t*,expression_type_t,expression_t*,expression_t*);
 static expression_t *new_unary_expression(parser_ctx_t*,expression_type_t,expression_t*);
 static expression_t *new_conditional_expression(parser_ctx_t*,expression_t*,expression_t*,expression_t*);
@@ -134,10 +138,8 @@ static expression_t *new_literal_expression(parser_ctx_t*,literal_t*);
 static expression_t *new_array_literal_expression(parser_ctx_t*,element_list_t*,int);
 static expression_t *new_prop_and_value_expression(parser_ctx_t*,property_list_t*);
 
-static function_declaration_t *new_function_declaration(parser_ctx_t*,const WCHAR*,parameter_list_t*,source_elements_t*);
 static source_elements_t *new_source_elements(parser_ctx_t*);
 static source_elements_t *source_elements_add_statement(source_elements_t*,statement_t*);
-static source_elements_t *source_elements_add_function(source_elements_t*,function_declaration_t*);
 
 %}
 
@@ -146,6 +148,7 @@ static source_elements_t *source_elements_add_function(source_elements_t*,functi
 
 %union {
     int                     ival;
+    const WCHAR             *srcptr;
     LPCWSTR                 wstr;
     literal_t               *literal;
     struct _argument_list_t *argument_list;
@@ -155,7 +158,6 @@ static source_elements_t *source_elements_add_function(source_elements_t*,functi
     struct _element_list_t  *element_list;
     expression_t            *expr;
     const WCHAR            *identifier;
-    function_declaration_t  *function_declaration;
     struct _parameter_list_t *parameter_list;
     struct _property_list_t *property_list;
     source_elements_t       *source_elements;
@@ -166,10 +168,12 @@ static source_elements_t *source_elements_add_function(source_elements_t*,functi
 }
 
 /* keywords */
-%token kBREAK kCASE kCATCH kCONTINUE kDEFAULT kDELETE kDO kELSE kIF kFINALLY kFOR kFUNCTION kIN
+%token kBREAK kCASE kCATCH kCONTINUE kDEFAULT kDELETE kDO kELSE kIF kFINALLY kFOR kIN
 %token kINSTANCEOF kNEW kNULL kUNDEFINED kRETURN kSWITCH kTHIS kTHROW kTRUE kFALSE kTRY kTYPEOF kVAR kVOID kWHILE kWITH
 %token tANDAND tOROR tINC tDEC
 
+%token <srcptr> kFUNCTION '}'
+
 /* tokens */
 %token <identifier> tIdentifier
 %token <ival> tAssignOper tEqOper tShiftOper tRelOper
@@ -195,7 +199,6 @@ static source_elements_t *source_elements_add_function(source_elements_t*,functi
 %type <statement> TryStatement
 %type <statement> Finally
 %type <statement_list> StatementList StatementList_opt
-%type <function_declaration> FunctionDeclaration
 %type <parameter_list> FormalParameterList FormalParameterList_opt
 %type <expr> Expression Expression_opt
 %type <expr> ExpressionNoIn ExpressionNoIn_opt
@@ -239,6 +242,10 @@ static source_elements_t *source_elements_add_function(source_elements_t*,functi
 %type <property_list> PropertyNameAndValueList
 %type <literal> PropertyName
 %type <literal> BooleanLiteral
+%type <srcptr> KFunction
+
+%nonassoc LOWER_THAN_ELSE
+%nonassoc kELSE
 
 %%
 
@@ -251,22 +258,18 @@ SourceElements
         : /* empty */           { $$ = new_source_elements(ctx); }
         | SourceElements Statement
                                 { $$ = source_elements_add_statement($1, $2); }
-        | SourceElements FunctionDeclaration
-                                { $$ = source_elements_add_function($1, $2); }
-
-/* ECMA-262 3rd Edition    13 */
-FunctionDeclaration
-        : kFUNCTION tIdentifier '(' FormalParameterList_opt ')' '{' FunctionBody '}'
-                                { $$ = new_function_declaration(ctx, $2, $4, $7); }
 
 /* ECMA-262 3rd Edition    13 */
 FunctionExpression
-        : kFUNCTION Identifier_opt '(' FormalParameterList_opt ')' '{' FunctionBody '}'
-                                { $$ = new_function_expression(ctx, $2, $4, $7); }
+        : KFunction Identifier_opt '(' FormalParameterList_opt ')' '{' FunctionBody '}'
+                                { $$ = new_function_expression(ctx, $2, $4, $7, $1, $8-$1+1); }
+
+KFunction
+        : kFUNCTION             { push_func(ctx); $$ = $1; }
 
 /* ECMA-262 3rd Edition    13 */
 FunctionBody
-        : SourceElements        { $$ = $1; }
+        : SourceElements        { $$ = function_body_parsed(ctx, $1); }
 
 /* ECMA-262 3rd Edition    13 */
 FormalParameterList
@@ -309,8 +312,8 @@ StatementList_opt
 
 /* ECMA-262 3rd Edition    12.1 */
 Block
-        : '{' StatementList_opt '}'
-                                { $$ = new_block_statement(ctx, $2); }
+        : '{' StatementList '}' { $$ = new_block_statement(ctx, $2); }
+        | '{' '}'               { $$ = new_block_statement(ctx, NULL); }
 
 /* ECMA-262 3rd Edition    12.2 */
 VariableStatement
@@ -373,7 +376,7 @@ ExpressionStatement
 IfStatement
         : kIF '(' Expression ')' Statement kELSE Statement
                                 { $$ = new_if_statement(ctx, $3, $5, $7); }
-        | kIF '(' Expression ')' Statement
+        | kIF '(' Expression ')' Statement %prec LOWER_THAN_ELSE
                                 { $$ = new_if_statement(ctx, $3, $5, NULL); }
 
 /* ECMA-262 3rd Edition    12.6 */
@@ -722,10 +725,11 @@ PrimaryExpression
 
 /* ECMA-262 3rd Edition    11.1.4 */
 ArrayLiteral
-        : '[' Elision_opt ']'   { $$ = new_array_literal_expression(ctx, NULL, $2); }
+        : '[' ']'               { $$ = new_array_literal_expression(ctx, NULL, 0); }
+        | '[' Elision ']'       { $$ = new_array_literal_expression(ctx, NULL, $2+1); }
         | '[' ElementList ']'   { $$ = new_array_literal_expression(ctx, $2, 0); }
         | '[' ElementList ',' Elision_opt ']'
-                                { $$ = new_array_literal_expression(ctx, $2, $4); }
+                                { $$ = new_array_literal_expression(ctx, $2, $4+1); }
 
 /* ECMA-262 3rd Edition    11.1.4 */
 ElementList
@@ -1013,11 +1017,20 @@ static statement_t *new_block_statement(parser_ctx_t *ctx, statement_list_t *lis
 static variable_declaration_t *new_variable_declaration(parser_ctx_t *ctx, const WCHAR *identifier, expression_t *expr)
 {
     variable_declaration_t *ret = parser_alloc(ctx, sizeof(variable_declaration_t));
+    var_list_t *var_list = parser_alloc(ctx, sizeof(var_list_t));
 
     ret->identifier = identifier;
     ret->expr = expr;
     ret->next = NULL;
 
+    var_list->identifier = identifier;
+    var_list->next = NULL;
+
+    if(ctx->func_stack->var_tail)
+        ctx->func_stack->var_tail = ctx->func_stack->var_tail->next = var_list;
+    else
+        ctx->func_stack->var_head = ctx->func_stack->var_tail = var_list;
+
     return ret;
 }
 
@@ -1247,7 +1260,7 @@ static parameter_list_t *parameter_list_add(parser_ctx_t *ctx, parameter_list_t
 }
 
 static expression_t *new_function_expression(parser_ctx_t *ctx, const WCHAR *identifier,
-       parameter_list_t *parameter_list, source_elements_t *source_elements)
+       parameter_list_t *parameter_list, source_elements_t *source_elements, const WCHAR *src_str, DWORD src_len)
 {
     function_expression_t *ret = parser_alloc(ctx, sizeof(function_expression_t));
 
@@ -1255,6 +1268,20 @@ static expression_t *new_function_expression(parser_ctx_t *ctx, const WCHAR *ide
     ret->identifier = identifier;
     ret->parameter_list = parameter_list ? parameter_list->head : NULL;
     ret->source_elements = source_elements;
+    ret->src_str = src_str;
+    ret->src_len = src_len;
+
+    if(ret->identifier) {
+        function_declaration_t *decl = parser_alloc(ctx, sizeof(function_declaration_t));
+
+        decl->expr = ret;
+        decl->next = NULL;
+
+        if(ctx->func_stack->func_tail)
+            ctx->func_stack->func_tail = ctx->func_stack->func_tail->next = decl;
+        else
+            ctx->func_stack->func_head = ctx->func_stack->func_tail = decl;
+    }
 
     return &ret->expr;
 }
@@ -1443,19 +1470,6 @@ static expression_t *new_literal_expression(parser_ctx_t *ctx, literal_t *litera
     return &ret->expr;
 }
 
-static function_declaration_t *new_function_declaration(parser_ctx_t *ctx, const WCHAR *identifier,
-       parameter_list_t *parameter_list, source_elements_t *source_elements)
-{
-    function_declaration_t *ret = parser_alloc(ctx, sizeof(function_declaration_t));
-
-    ret->identifier = identifier;
-    ret->parameter_list = parameter_list ? parameter_list->head : NULL;
-    ret->source_elements = source_elements;
-    ret->next = NULL;
-
-    return ret;
-}
-
 static source_elements_t *new_source_elements(parser_ctx_t *ctx)
 {
     source_elements_t *ret = parser_alloc(ctx, sizeof(source_elements_t));
@@ -1475,18 +1489,7 @@ static source_elements_t *source_elements_add_statement(source_elements_t *sourc
     return source_elements;
 }
 
-static source_elements_t *source_elements_add_function(source_elements_t *source_elements,
-       function_declaration_t *function_declaration)
-{
-    if(source_elements->functions_tail)
-        source_elements->functions_tail = source_elements->functions_tail->next = function_declaration;
-    else
-        source_elements->functions = source_elements->functions_tail = function_declaration;
-
-    return source_elements;
-}
-
-statement_list_t *new_statement_list(parser_ctx_t *ctx, statement_t *statement)
+static statement_list_t *new_statement_list(parser_ctx_t *ctx, statement_t *statement)
 {
     statement_list_t *ret =  parser_alloc_tmp(ctx, sizeof(statement_list_t));
 
@@ -1495,15 +1498,39 @@ statement_list_t *new_statement_list(parser_ctx_t *ctx, statement_t *statement)
     return ret;
 }
 
-statement_list_t *statement_list_add(statement_list_t *list, statement_t *statement)
+static statement_list_t *statement_list_add(statement_list_t *list, statement_t *statement)
 {
     list->tail = list->tail->next = statement;
 
     return list;
 }
 
+static void push_func(parser_ctx_t *ctx)
+{
+    func_stack_t *new_func = parser_alloc_tmp(ctx, sizeof(func_stack_t));
+
+    new_func->func_head = new_func->func_tail = NULL;
+    new_func->var_head = new_func->var_tail = NULL;
+
+    new_func->next = ctx->func_stack;
+    ctx->func_stack = new_func;
+}
+
+static source_elements_t *function_body_parsed(parser_ctx_t *ctx, source_elements_t *source)
+{
+    source->functions = ctx->func_stack->func_head;
+    source->variables = ctx->func_stack->var_head;
+    pop_func(ctx);
+
+    return source;
+}
+
 static void program_parsed(parser_ctx_t *ctx, source_elements_t *source)
 {
+    source->functions = ctx->func_stack->func_head;
+    source->variables = ctx->func_stack->var_head;
+    pop_func(ctx);
+
     ctx->source = source;
     ctx->hres = S_OK;
 }
@@ -1544,6 +1571,8 @@ HRESULT script_parse(script_ctx_t *ctx, const WCHAR *code, parser_ctx_t **ret)
     mark = jsheap_mark(&ctx->tmp_heap);
     jsheap_init(&parser_ctx->heap);
 
+    push_func(parser_ctx);
+
     parser_parse(parser_ctx);
     jsheap_clear(mark);
     if(FAILED(parser_ctx->hres)) {
index e8e9bea..8ae2152 100644 (file)
@@ -181,7 +181,7 @@ typedef enum REOp {
 
 #define REOP_IS_SIMPLE(op)  ((op) <= REOP_NCLASS)
 
-const char *reop_names[] = {
+static const char *reop_names[] = {
     "empty",
     "bol",
     "eol",
@@ -559,7 +559,7 @@ EmitREBytecode(CompilerState *state, JSRegExp *re, size_t treeDepth,
             emitStateSP->jumpToJumpFlag = FALSE;
             ++emitStateSP;
             assert((size_t)(emitStateSP - emitStateStack) <= treeDepth);
-            t = (RENode *) t->kid;
+            t = t->kid;
             op = t->op;
             assert(op < REOP_LIMIT);
             continue;
@@ -572,7 +572,7 @@ EmitREBytecode(CompilerState *state, JSRegExp *re, size_t treeDepth,
             emitStateSP->continueOp = REOP_ENDALT;
             ++emitStateSP;
             assert((size_t)(emitStateSP - emitStateStack) <= treeDepth);
-            t = (RENode *) t->u.kid2;
+            t = t->u.kid2;
             op = t->op;
             assert(op < REOP_LIMIT);
             continue;
@@ -676,7 +676,7 @@ EmitREBytecode(CompilerState *state, JSRegExp *re, size_t treeDepth,
             emitStateSP->jumpToJumpFlag = FALSE;
             ++emitStateSP;
             assert((size_t)(emitStateSP - emitStateStack) <= treeDepth);
-            t = (RENode *) t->kid;
+            t = t->kid;
             op = t->op;
             assert(op < REOP_LIMIT);
             continue;
@@ -699,7 +699,7 @@ EmitREBytecode(CompilerState *state, JSRegExp *re, size_t treeDepth,
                 while (t->next &&
                        t->next->op == REOP_FLAT &&
                        (WCHAR*)t->kid + t->u.flat.length ==
-                       (WCHAR*)t->next->kid) {
+                       t->next->kid) {
                     t->u.flat.length += t->next->u.flat.length;
                     t->next = t->next->next;
                 }
@@ -727,7 +727,7 @@ EmitREBytecode(CompilerState *state, JSRegExp *re, size_t treeDepth,
             emitStateSP->continueOp = REOP_RPAREN;
             ++emitStateSP;
             assert((size_t)(emitStateSP - emitStateStack) <= treeDepth);
-            t = (RENode *) t->kid;
+            t = t->kid;
             op = t->op;
             continue;
 
@@ -747,7 +747,7 @@ EmitREBytecode(CompilerState *state, JSRegExp *re, size_t treeDepth,
             emitStateSP->continueOp = REOP_ASSERTTEST;
             ++emitStateSP;
             assert((size_t)(emitStateSP - emitStateStack) <= treeDepth);
-            t = (RENode *) t->kid;
+            t = t->kid;
             op = t->op;
             continue;
 
@@ -765,7 +765,7 @@ EmitREBytecode(CompilerState *state, JSRegExp *re, size_t treeDepth,
             emitStateSP->continueOp = REOP_ASSERTNOTTEST;
             ++emitStateSP;
             assert((size_t)(emitStateSP - emitStateStack) <= treeDepth);
-            t = (RENode *) t->kid;
+            t = t->kid;
             op = t->op;
             continue;
 
@@ -793,7 +793,7 @@ EmitREBytecode(CompilerState *state, JSRegExp *re, size_t treeDepth,
             emitStateSP->continueOp = REOP_ENDCHILD;
             ++emitStateSP;
             assert((size_t)(emitStateSP - emitStateStack) <= treeDepth);
-            t = (RENode *) t->kid;
+            t = t->kid;
             op = t->op;
             continue;
 
@@ -2571,7 +2571,7 @@ SimpleMatch(REGlobalData *gData, REMatchState *x, REOp op,
         if (!updatecp)
             x->cp = startcp;
         *startpc = pc;
-        TRACE(" * \n");
+        TRACE(" *\n");
         return result;
     }
     x->cp = startcp;
@@ -3001,7 +3001,7 @@ ExecuteREBytecode(REGlobalData *gData, REMatchState *x)
     }while(0)
 
                 if (!result) {
-                    TRACE(" - \n");
+                    TRACE(" -\n");
                     /*
                      * Non-greedy failure - try to consume another child.
                      */
@@ -3297,66 +3297,119 @@ out:
     return re;
 }
 
+static HRESULT do_regexp_match_next(RegExpInstance *regexp, const WCHAR *str, DWORD len,
+        const WCHAR **cp, match_result_t **parens, DWORD *parens_size, DWORD *parens_cnt, match_result_t *ret)
+{
+    REMatchState *x, *result;
+    REGlobalData gData;
+    DWORD matchlen;
+
+    gData.cpbegin = *cp;
+    gData.cpend = str + len;
+    gData.start = *cp-str;
+    gData.skipped = 0;
+    gData.pool = &regexp->dispex.ctx->tmp_heap;
+
+    x = InitMatch(NULL, &gData, regexp->jsregexp, gData.cpend - gData.cpbegin);
+    if(!x) {
+        WARN("InitMatch failed\n");
+        return E_FAIL;
+    }
+
+    x->cp = *cp;
+    result = MatchRegExp(&gData, x);
+    if(!gData.ok) {
+        WARN("MatchRegExp failed\n");
+        return E_FAIL;
+    }
+
+    if(!result)
+        return S_FALSE;
+
+    if(parens) {
+        DWORD i;
+
+        if(regexp->jsregexp->parenCount > *parens_size) {
+            match_result_t *new_parens;
+
+            if(*parens)
+                new_parens = heap_realloc(*parens, sizeof(match_result_t)*regexp->jsregexp->parenCount);
+            else
+                new_parens = heap_alloc(sizeof(match_result_t)*regexp->jsregexp->parenCount);
+            if(!new_parens)
+                return E_OUTOFMEMORY;
+
+            *parens = new_parens;
+        }
+
+        *parens_cnt = regexp->jsregexp->parenCount;
+
+        for(i=0; i < regexp->jsregexp->parenCount; i++) {
+            (*parens)[i].str = *cp + result->parens[i].index;
+            (*parens)[i].len = result->parens[i].length;
+        }
+    }
+
+    matchlen = (result->cp-*cp) - gData.skipped;
+    *cp = result->cp;
+    ret->str = result->cp-matchlen;
+    ret->len = matchlen;
+
+    return S_OK;
+}
+
+HRESULT regexp_match_next(DispatchEx *dispex, BOOL gcheck, const WCHAR *str, DWORD len,
+        const WCHAR **cp, match_result_t **parens, DWORD *parens_size, DWORD *parens_cnt, match_result_t *ret)
+{
+    RegExpInstance *regexp = (RegExpInstance*)dispex;
+    jsheap_t *mark;
+    HRESULT hres;
+
+    if(gcheck && !(regexp->jsregexp->flags & JSREG_GLOB))
+        return S_FALSE;
+
+    mark = jsheap_mark(&regexp->dispex.ctx->tmp_heap);
+
+    hres = do_regexp_match_next(regexp, str, len, cp, parens, parens_size, parens_cnt, ret);
+
+    jsheap_clear(mark);
+    return hres;
+}
+
 HRESULT regexp_match(DispatchEx *dispex, const WCHAR *str, DWORD len, BOOL gflag, match_result_t **match_result,
         DWORD *result_cnt)
 {
     RegExpInstance *This = (RegExpInstance*)dispex;
-    match_result_t *ret = NULL;
+    match_result_t *ret = NULL, cres;
     const WCHAR *cp = str;
-    REGlobalData gData;
-    REMatchState *x, *result;
-    DWORD matchlen;
     DWORD i=0, ret_size = 0;
     jsheap_t *mark;
-    size_t length;
-    HRESULT hres = E_FAIL;
-
-    length = len;
+    HRESULT hres;
 
     mark = jsheap_mark(&This->dispex.ctx->tmp_heap);
-    gData.pool = &This->dispex.ctx->tmp_heap;
 
     while(1) {
-        gData.cpbegin = cp;
-        gData.cpend = str + len;
-        gData.start = cp-str;
-        gData.skipped = 0;
-
-        x = InitMatch(NULL, &gData, This->jsregexp, length);
-        if(!x) {
-            WARN("InitMatch failed\n");
-            break;
-        }
-
-        x->cp = cp;
-        result = MatchRegExp(&gData, x);
-        if(!gData.ok) {
-            WARN("MatchRegExp failed\n");
-            break;
-        }
-
-        if(!result) {
+        hres = do_regexp_match_next(This, str, len, &cp, NULL, NULL, NULL, &cres);
+        if(hres == S_FALSE) {
             hres = S_OK;
             break;
         }
 
-        matchlen = (result->cp-cp) - gData.skipped;
+        if(FAILED(hres))
+            return hres;
 
-        if(ret)
-            ret = heap_realloc(ret, (ret_size <<= 1) * sizeof(match_result_t));
-        else if(ret_size == i)
-            ret = heap_alloc((ret_size=4) * sizeof(match_result_t));
-        if(!ret) {
-            hres = E_OUTOFMEMORY;
-            break;
+        if(ret_size == i) {
+            if(ret)
+                ret = heap_realloc(ret, (ret_size <<= 1) * sizeof(match_result_t));
+            else
+                ret = heap_alloc((ret_size=4) * sizeof(match_result_t));
+            if(!ret) {
+                hres = E_OUTOFMEMORY;
+                break;
+            }
         }
 
-        ret[i].str = result->cp-matchlen;
-        ret[i].len = matchlen;
-
-        length -= result->cp-cp;
-        cp = result->cp;
-        i++;
+        ret[i++] = cres;
 
         if(!gflag && !(This->jsregexp->flags & JSREG_GLOB)) {
             hres = S_OK;
@@ -3546,11 +3599,81 @@ static HRESULT create_regexp(script_ctx_t *ctx, const WCHAR *exp, int len, DWORD
     return S_OK;
 }
 
+static HRESULT regexp_constructor(script_ctx_t *ctx, DISPPARAMS *dp, VARIANT *retv)
+{
+    const WCHAR *opt = emptyW, *src;
+    DispatchEx *ret;
+    VARIANT *arg;
+    HRESULT hres;
+
+    if(!arg_cnt(dp)) {
+        FIXME("no args\n");
+        return E_NOTIMPL;
+    }
+
+    arg = get_arg(dp,0);
+    if(V_VT(arg) == VT_DISPATCH) {
+        DispatchEx *obj;
+
+        obj = iface_to_jsdisp((IUnknown*)V_DISPATCH(arg));
+        if(obj) {
+            if(is_class(obj, JSCLASS_REGEXP)) {
+                RegExpInstance *regexp = (RegExpInstance*)obj;
+
+                hres = create_regexp(ctx, regexp->str, -1, regexp->jsregexp->flags, &ret);
+                jsdisp_release(obj);
+                if(FAILED(hres))
+                    return hres;
+
+                V_VT(retv) = VT_DISPATCH;
+                V_DISPATCH(retv) = (IDispatch*)_IDispatchEx_(ret);
+                return S_OK;
+            }
+
+            jsdisp_release(obj);
+        }
+    }
+
+    if(V_VT(arg) != VT_BSTR) {
+        FIXME("vt arg0 = %d\n", V_VT(arg));
+        return E_NOTIMPL;
+    }
+
+    src = V_BSTR(arg);
+
+    if(arg_cnt(dp) >= 2) {
+        arg = get_arg(dp,1);
+        if(V_VT(arg) != VT_BSTR) {
+            FIXME("unimplemented for vt %d\n", V_VT(arg));
+            return E_NOTIMPL;
+        }
+
+        opt = V_BSTR(arg);
+    }
+
+    hres = create_regexp_str(ctx, src, -1, opt, strlenW(opt), &ret);
+    if(FAILED(hres))
+        return hres;
+
+    V_VT(retv) = VT_DISPATCH;
+    V_DISPATCH(retv) = (IDispatch*)_IDispatchEx_(ret);
+    return S_OK;
+}
+
 static HRESULT RegExpConstr_value(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
         VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
 {
-    FIXME("\n");
-    return E_NOTIMPL;
+    TRACE("\n");
+
+    switch(flags) {
+    case DISPATCH_CONSTRUCT:
+        return regexp_constructor(dispex->ctx, dp, retv);
+    default:
+        FIXME("unimplemented flags: %x\n", flags);
+        return E_NOTIMPL;
+    }
+
+    return S_OK;
 }
 
 HRESULT create_regexp_constr(script_ctx_t *ctx, DispatchEx **ret)
index 12140d5..eeceb1f 100644 (file)
@@ -88,18 +88,66 @@ static HRESULT String_length(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARA
     return S_OK;
 }
 
+/* ECMA-262 3rd Edition    15.5.4.2 */
 static HRESULT String_toString(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
         VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
 {
-    FIXME("\n");
-    return E_NOTIMPL;
+    StringInstance *string;
+
+    TRACE("\n");
+
+    if(!is_class(dispex, JSCLASS_STRING)) {
+        WARN("this is not a string object\n");
+        return E_FAIL;
+    }
+
+    string = (StringInstance*)dispex;
+
+    if(retv) {
+        BSTR str = SysAllocString(string->str);
+        if(!str)
+            return E_OUTOFMEMORY;
+
+        V_VT(retv) = VT_BSTR;
+        V_BSTR(retv) = str;
+    }
+    return S_OK;
 }
 
+/* ECMA-262 3rd Edition    15.5.4.2 */
 static HRESULT String_valueOf(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
         VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
 {
-    FIXME("\n");
-    return E_NOTIMPL;
+    TRACE("\n");
+
+    return String_toString(dispex, lcid, flags, dp, retv, ei, sp);
+}
+
+static HRESULT do_attributeless_tag_format(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
+        VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp, const WCHAR *tagname)
+{
+    static const WCHAR tagfmt[] = {'<','%','s','>','%','s','<','/','%','s','>',0};
+    StringInstance *string;
+    BSTR ret;
+
+    if(!is_class(dispex, JSCLASS_STRING)) {
+        WARN("this is not a string object\n");
+        return E_NOTIMPL;
+    }
+
+    string = (StringInstance*)dispex;
+
+    if(retv) {
+        ret = SysAllocStringLen(NULL, string->length + 2*strlenW(tagname) + 5);
+        if(!ret)
+            return E_OUTOFMEMORY;
+
+        sprintfW(ret, tagfmt, tagname, string->str, tagname);
+
+        V_VT(retv) = VT_BSTR;
+        V_BSTR(retv) = ret;
+    }
+    return S_OK;
 }
 
 static HRESULT String_anchor(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
@@ -112,22 +160,22 @@ static HRESULT String_anchor(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARA
 static HRESULT String_big(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
         VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
 {
-    FIXME("\n");
-    return E_NOTIMPL;
+    static const WCHAR bigtagW[] = {'B','I','G',0};
+    return do_attributeless_tag_format(dispex, lcid, flags, dp, retv, ei, sp, bigtagW);
 }
 
 static HRESULT String_blink(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
         VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
 {
-    FIXME("\n");
-    return E_NOTIMPL;
+    static const WCHAR blinktagW[] = {'B','L','I','N','K',0};
+    return do_attributeless_tag_format(dispex, lcid, flags, dp, retv, ei, sp, blinktagW);
 }
 
 static HRESULT String_bold(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
         VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
 {
-    FIXME("\n");
-    return E_NOTIMPL;
+    static const WCHAR boldtagW[] = {'B',0};
+    return do_attributeless_tag_format(dispex, lcid, flags, dp, retv, ei, sp, boldtagW);
 }
 
 /* ECMA-262 3rd Edition    15.5.4.5 */
@@ -178,25 +226,111 @@ static HRESULT String_charAt(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARA
     return S_OK;
 }
 
+/* ECMA-262 3rd Edition    15.5.4.5 */
 static HRESULT String_charCodeAt(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
         VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
 {
-    FIXME("\n");
-    return E_NOTIMPL;
+    const WCHAR *str;
+    DWORD length, idx = 0;
+    HRESULT hres;
+
+    TRACE("\n");
+
+    if(dispex->builtin_info->class == JSCLASS_STRING) {
+        StringInstance *string = (StringInstance*)dispex;
+
+        str = string->str;
+        length = string->length;
+    }else {
+        FIXME("not string this not supported\n");
+        return E_NOTIMPL;
+    }
+
+    if(arg_cnt(dp) > 0) {
+        VARIANT v;
+
+        hres = to_integer(dispex->ctx, get_arg(dp, 0), ei, &v);
+        if(FAILED(hres))
+            return hres;
+
+        if(V_VT(&v) != VT_I4 || V_I4(&v) < 0 || V_I4(&v) >= length) {
+            FIXME("NAN\n");
+            return E_FAIL;
+        }
+
+        idx = V_I4(&v);
+    }
+
+    if(retv) {
+        V_VT(retv) = VT_I4;
+        V_I4(retv) = str[idx];
+    }
+    return S_OK;
 }
 
+/* ECMA-262 3rd Edition    15.5.4.6 */
 static HRESULT String_concat(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
         VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
 {
-    FIXME("\n");
-    return E_NOTIMPL;
+    BSTR *strs = NULL, ret = NULL;
+    DWORD len = 0, i, l, str_cnt;
+    VARIANT var;
+    WCHAR *ptr;
+    HRESULT hres;
+
+    TRACE("\n");
+
+    str_cnt = arg_cnt(dp)+1;
+    strs = heap_alloc_zero(str_cnt * sizeof(BSTR));
+    if(!strs)
+        return E_OUTOFMEMORY;
+
+    V_VT(&var) = VT_DISPATCH;
+    V_DISPATCH(&var) = (IDispatch*)_IDispatchEx_(dispex);
+
+    hres = to_string(dispex->ctx, &var, ei, strs);
+    if(SUCCEEDED(hres)) {
+        for(i=0; i < arg_cnt(dp); i++) {
+            hres = to_string(dispex->ctx, get_arg(dp, i), ei, strs+i+1);
+            if(FAILED(hres))
+                break;
+        }
+    }
+
+    if(SUCCEEDED(hres)) {
+        for(i=0; i < str_cnt; i++)
+            len += SysStringLen(strs[i]);
+
+        ptr = ret = SysAllocStringLen(NULL, len);
+
+        for(i=0; i < str_cnt; i++) {
+            l = SysStringLen(strs[i]);
+            memcpy(ptr, strs[i], l*sizeof(WCHAR));
+            ptr += l;
+        }
+    }
+
+    for(i=0; i < str_cnt; i++)
+        SysFreeString(strs[i]);
+    heap_free(strs);
+
+    if(FAILED(hres))
+        return hres;
+
+    if(retv) {
+        V_VT(retv) = VT_BSTR;
+        V_BSTR(retv) = ret;
+    }else {
+        SysFreeString(ret);
+    }
+    return S_OK;
 }
 
 static HRESULT String_fixed(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
         VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
 {
-    FIXME("\n");
-    return E_NOTIMPL;
+    static const WCHAR fixedtagW[] = {'T','T',0};
+    return do_attributeless_tag_format(dispex, lcid, flags, dp, retv, ei, sp, fixedtagW);
 }
 
 static HRESULT String_fontcolor(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
@@ -216,15 +350,76 @@ static HRESULT String_fontsize(DispatchEx *dispex, LCID lcid, WORD flags, DISPPA
 static HRESULT String_indexOf(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
         VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
 {
-    FIXME("\n");
-    return E_NOTIMPL;
+    DWORD length, pos = 0;
+    const WCHAR *str;
+    BSTR search_str;
+    INT ret = -1;
+    HRESULT hres;
+
+    TRACE("\n");
+
+    if(is_class(dispex, JSCLASS_STRING)) {
+        StringInstance *string = (StringInstance*)dispex;
+
+        str = string->str;
+        length = string->length;
+    }else {
+        FIXME("not String this\n");
+        return E_NOTIMPL;
+    }
+
+    if(!arg_cnt(dp)) {
+        if(retv) {
+            V_VT(retv) = VT_I4;
+            V_I4(retv) = -1;
+        }
+        return S_OK;
+    }
+
+    hres = to_string(dispex->ctx, get_arg(dp,0), ei, &search_str);
+    if(FAILED(hres))
+        return hres;
+
+    if(arg_cnt(dp) >= 2) {
+        VARIANT ival;
+
+        hres = to_integer(dispex->ctx, get_arg(dp,1), ei, &ival);
+        if(SUCCEEDED(hres)) {
+            if(V_VT(&ival) == VT_I4)
+                pos = V_VT(&ival) > 0 ? V_I4(&ival) : 0;
+            else
+                pos = V_R8(&ival) > 0.0 ? length : 0;
+            if(pos > length)
+                pos = length;
+        }
+    }
+
+    if(SUCCEEDED(hres)) {
+        const WCHAR *ptr;
+
+        ptr = strstrW(str+pos, search_str);
+        if(ptr)
+            ret = ptr - str;
+        else
+            ret = -1;
+    }
+
+    SysFreeString(search_str);
+    if(FAILED(hres))
+        return hres;
+
+    if(retv) {
+        V_VT(retv) = VT_I4;
+        V_I4(retv) = ret;
+    }
+    return S_OK;
 }
 
 static HRESULT String_italics(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
         VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
 {
-    FIXME("\n");
-    return E_NOTIMPL;
+    static const WCHAR italicstagW[] = {'I',0};
+    return do_attributeless_tag_format(dispex, lcid, flags, dp, retv, ei, sp, italicstagW);
 }
 
 static HRESULT String_lastIndexOf(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
@@ -247,6 +442,7 @@ static HRESULT String_match(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAM
 {
     StringInstance *This = (StringInstance*)dispex;
     match_result_t *match_result;
+    DispatchEx *regexp;
     DispatchEx *array;
     VARIANT var, *arg_var;
     DWORD match_cnt, i;
@@ -254,33 +450,39 @@ static HRESULT String_match(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAM
 
     TRACE("\n");
 
-    if(dp->cArgs - dp->cNamedArgs != 1) {
+    if(arg_cnt(dp) != 1) {
         FIXME("unsupported args\n");
         return E_NOTIMPL;
     }
 
     arg_var = get_arg(dp, 0);
     switch(V_VT(arg_var)) {
-    case VT_DISPATCH: {
-        DispatchEx *regexp;
-
+    case VT_DISPATCH:
         regexp = iface_to_jsdisp((IUnknown*)V_DISPATCH(arg_var));
         if(regexp) {
-            if(regexp->builtin_info->class == JSCLASS_REGEXP) {
-                hres = regexp_match(regexp, This->str, This->length, FALSE, &match_result, &match_cnt);
-                jsdisp_release(regexp);
-                if(FAILED(hres))
-                    return hres;
+            if(regexp->builtin_info->class == JSCLASS_REGEXP)
                 break;
-            }
             jsdisp_release(regexp);
         }
+    default: {
+        BSTR match_str;
+
+        hres = to_string(dispex->ctx, arg_var, ei, &match_str);
+        if(FAILED(hres))
+            return hres;
+
+        hres = create_regexp_str(dispex->ctx, match_str, SysStringLen(match_str), NULL, 0, &regexp);
+        SysFreeString(match_str);
+        if(FAILED(hres))
+            return hres;
     }
-    default:
-        FIXME("implemented only for regexp args\n");
-        return E_NOTIMPL;
     }
 
+    hres = regexp_match(regexp, This->str, This->length, FALSE, &match_result, &match_cnt);
+    jsdisp_release(regexp);
+    if(FAILED(hres))
+        return hres;
+
     if(!match_cnt) {
         TRACE("no match\n");
 
@@ -308,21 +510,272 @@ static HRESULT String_match(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAM
             break;
     }
 
-    if(FAILED(hres)) {
+    if(SUCCEEDED(hres) && retv) {
+        V_VT(retv) = VT_DISPATCH;
+        V_DISPATCH(retv) = (IDispatch*)_IDispatchEx_(array);
+    }else {
         jsdisp_release(array);
-        return hres;
     }
+    return hres;
+}
 
-    V_VT(retv) = VT_DISPATCH;
-    V_DISPATCH(retv) = (IDispatch*)_IDispatchEx_(array);
+typedef struct {
+    WCHAR *buf;
+    DWORD size;
+    DWORD len;
+} strbuf_t;
+
+static HRESULT strbuf_append(strbuf_t *buf, const WCHAR *str, DWORD len)
+{
+    if(!len)
+        return S_OK;
+
+    if(len + buf->len > buf->size) {
+        WCHAR *new_buf;
+        DWORD new_size;
+
+        new_size = buf->size ? buf->size<<1 : 16;
+        if(new_size < buf->len+len)
+            new_size = buf->len+len;
+        if(buf->buf)
+            new_buf = heap_realloc(buf->buf, new_size*sizeof(WCHAR));
+        else
+            new_buf = heap_alloc(new_size*sizeof(WCHAR));
+        if(!new_buf)
+            return E_OUTOFMEMORY;
+
+        buf->buf = new_buf;
+        buf->size = new_size;
+    }
+
+    memcpy(buf->buf+buf->len, str, len*sizeof(WCHAR));
+    buf->len += len;
     return S_OK;
 }
 
+static HRESULT rep_call(DispatchEx *func, const WCHAR *str, match_result_t *match, match_result_t *parens,
+        DWORD parens_cnt, LCID lcid, BSTR *ret, jsexcept_t *ei, IServiceProvider *caller)
+{
+    DISPPARAMS dp = {NULL, NULL, 0, 0};
+    VARIANTARG *args, *arg;
+    VARIANT var;
+    DWORD i;
+    HRESULT hres = S_OK;
+
+    dp.cArgs = parens_cnt+3;
+    dp.rgvarg = args = heap_alloc_zero(sizeof(VARIANT)*dp.cArgs);
+    if(!args)
+        return E_OUTOFMEMORY;
+
+    arg = get_arg(&dp,0);
+    V_VT(arg) = VT_BSTR;
+    V_BSTR(arg) = SysAllocStringLen(match->str, match->len);
+    if(!V_BSTR(arg))
+        hres = E_OUTOFMEMORY;
+
+    if(SUCCEEDED(hres)) {
+        for(i=0; i < parens_cnt; i++) {
+            arg = get_arg(&dp,i+1);
+            V_VT(arg) = VT_BSTR;
+            V_BSTR(arg) = SysAllocStringLen(parens[i].str, parens[i].len);
+            if(!V_BSTR(arg)) {
+               hres = E_OUTOFMEMORY;
+               break;
+            }
+        }
+    }
+
+    if(SUCCEEDED(hres)) {
+        arg = get_arg(&dp,parens_cnt+1);
+        V_VT(arg) = VT_I4;
+        V_I4(arg) = match->str - str;
+
+        arg = get_arg(&dp,parens_cnt+2);
+        V_VT(arg) = VT_BSTR;
+        V_BSTR(arg) = SysAllocString(str);
+        if(!V_BSTR(arg))
+            hres = E_OUTOFMEMORY;
+    }
+
+    if(SUCCEEDED(hres))
+        hres = jsdisp_call_value(func, lcid, DISPATCH_METHOD, &dp, &var, ei, caller);
+
+    for(i=0; i < parens_cnt+1; i++) {
+        if(i != parens_cnt+1)
+            SysFreeString(V_BSTR(get_arg(&dp,i)));
+    }
+    heap_free(args);
+
+    if(FAILED(hres))
+        return hres;
+
+    hres = to_string(func->ctx, &var, ei, ret);
+    VariantClear(&var);
+    return hres;
+}
+
+/* ECMA-262 3rd Edition    15.5.4.11 */
 static HRESULT String_replace(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
-        VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
+        VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
 {
-    FIXME("\n");
-    return E_NOTIMPL;
+    DWORD parens_cnt = 0, parens_size=0, rep_len=0, length;
+    BSTR rep_str = NULL, match_str = NULL, ret_str;
+    DispatchEx *rep_func = NULL, *regexp = NULL;
+    match_result_t *parens = NULL, match;
+    const WCHAR *str;
+    strbuf_t ret = {NULL,0,0};
+    BOOL gcheck = FALSE;
+    VARIANT *arg_var;
+    HRESULT hres = S_OK;
+
+    TRACE("\n");
+
+    if(is_class(dispex, JSCLASS_STRING)) {
+        StringInstance *string = (StringInstance*)dispex;
+        str = string->str;
+        length = string->length;
+    }else {
+        FIXME("not String this\n");
+        return E_NOTIMPL;
+    }
+
+    if(!arg_cnt(dp)) {
+        if(retv) {
+            ret_str = SysAllocString(str);
+            if(!ret_str)
+                return E_OUTOFMEMORY;
+
+            V_VT(retv) = VT_BSTR;
+            V_BSTR(retv) = ret_str;
+        }
+        return S_OK;
+    }
+
+    arg_var = get_arg(dp, 0);
+    switch(V_VT(arg_var)) {
+    case VT_DISPATCH:
+        regexp = iface_to_jsdisp((IUnknown*)V_DISPATCH(arg_var));
+        if(regexp) {
+            if(is_class(regexp, JSCLASS_REGEXP)) {
+                break;
+            }else {
+                jsdisp_release(regexp);
+                regexp = NULL;
+            }
+        }
+
+    default:
+        hres = to_string(dispex->ctx, arg_var, ei, &match_str);
+        if(FAILED(hres))
+            return hres;
+    }
+
+    if(arg_cnt(dp) >= 2) {
+        arg_var = get_arg(dp,1);
+        switch(V_VT(arg_var)) {
+        case VT_DISPATCH:
+            rep_func = iface_to_jsdisp((IUnknown*)V_DISPATCH(arg_var));
+            if(rep_func) {
+                if(is_class(rep_func, JSCLASS_FUNCTION)) {
+                    break;
+                }else {
+                    jsdisp_release(rep_func);
+                    rep_func = NULL;
+                }
+            }
+
+        default:
+            hres = to_string(dispex->ctx, arg_var, ei, &rep_str);
+            if(FAILED(hres))
+                break;
+
+            if(strchrW(rep_str, '$')) {
+                FIXME("unsupported $ in replace string\n");
+                hres = E_NOTIMPL;
+            }
+
+            rep_len = SysStringLen(rep_str);
+        }
+    }
+
+    if(SUCCEEDED(hres)) {
+        const WCHAR *cp, *ecp;
+
+        cp = ecp = str;
+
+        while(1) {
+            if(regexp) {
+                hres = regexp_match_next(regexp, gcheck, str, length, &cp, rep_func ? &parens : NULL,
+                                         &parens_size, &parens_cnt, &match);
+                gcheck = TRUE;
+
+                if(hres == S_FALSE) {
+                    hres = S_OK;
+                    break;
+                }
+                if(FAILED(hres))
+                    break;
+            }else {
+                match.str = strstrW(cp, match_str);
+                if(!match.str)
+                    break;
+                match.len = SysStringLen(match_str);
+                cp = match.str+match.len;
+            }
+
+            hres = strbuf_append(&ret, ecp, match.str-ecp);
+            ecp = match.str+match.len;
+            if(FAILED(hres))
+                break;
+
+            if(rep_func) {
+                BSTR cstr;
+
+                hres = rep_call(rep_func, str, &match, parens, parens_cnt, lcid, &cstr, ei, caller);
+                if(FAILED(hres))
+                    break;
+
+                hres = strbuf_append(&ret, cstr, SysStringLen(cstr));
+                SysFreeString(cstr);
+                if(FAILED(hres))
+                    break;
+            }else if(rep_str) {
+                hres = strbuf_append(&ret, rep_str, rep_len);
+                if(FAILED(hres))
+                    break;
+            }else {
+                static const WCHAR undefinedW[] = {'u','n','d','e','f','i','n','e','d'};
+
+                hres = strbuf_append(&ret, undefinedW, sizeof(undefinedW)/sizeof(WCHAR));
+                if(FAILED(hres))
+                    break;
+            }
+        }
+
+        if(SUCCEEDED(hres))
+            hres = strbuf_append(&ret, ecp, (str+length)-ecp);
+    }
+
+    if(rep_func)
+        jsdisp_release(rep_func);
+    if(regexp)
+        jsdisp_release(regexp);
+    SysFreeString(rep_str);
+    SysFreeString(match_str);
+    heap_free(parens);
+
+    if(SUCCEEDED(hres) && retv) {
+        ret_str = SysAllocStringLen(ret.buf, ret.len);
+        if(!ret_str)
+            return E_OUTOFMEMORY;
+
+        V_VT(retv) = VT_BSTR;
+        V_BSTR(retv) = ret_str;
+        TRACE("= %s\n", debugstr_w(ret_str));
+    }
+
+    heap_free(ret.buf);
+    return hres;
 }
 
 static HRESULT String_search(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
@@ -332,46 +785,298 @@ static HRESULT String_search(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARA
     return E_NOTIMPL;
 }
 
+/* ECMA-262 3rd Edition    15.5.4.13 */
 static HRESULT String_slice(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
         VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
 {
-    FIXME("\n");
-    return E_NOTIMPL;
+    const WCHAR *str;
+    DWORD length;
+    INT start=0, end;
+    VARIANT v;
+    HRESULT hres;
+
+    TRACE("\n");
+
+    if(is_class(dispex, JSCLASS_STRING)) {
+        StringInstance *string = (StringInstance*)dispex;
+
+        str = string->str;
+        length = string->length;
+    }else {
+        FIXME("this is not a string class\n");
+        return E_NOTIMPL;
+    }
+
+    if(arg_cnt(dp)) {
+        hres = to_integer(dispex->ctx, dp->rgvarg + dp->cArgs-1, ei, &v);
+        if(FAILED(hres))
+            return hres;
+
+        if(V_VT(&v) == VT_I4) {
+            start = V_I4(&v);
+            if(start < 0) {
+                start = length + start;
+                if(start < 0)
+                    start = 0;
+            }else if(start > length) {
+                start = length;
+            }
+        }else {
+            start = V_R8(&v) < 0.0 ? 0 : length;
+        }
+    }else {
+        start = 0;
+    }
+
+    if(arg_cnt(dp) >= 2) {
+        hres = to_integer(dispex->ctx, dp->rgvarg + dp->cArgs-2, ei, &v);
+        if(FAILED(hres))
+            return hres;
+
+        if(V_VT(&v) == VT_I4) {
+            end = V_I4(&v);
+            if(end < 0) {
+                end = length + end;
+                if(end < 0)
+                    end = 0;
+            }else if(end > length) {
+                end = length;
+            }
+        }else {
+            end = V_R8(&v) < 0.0 ? 0 : length;
+        }
+    }else {
+        end = length;
+    }
+
+    if(end < start)
+        end = start;
+
+    if(retv) {
+        BSTR retstr = SysAllocStringLen(str+start, end-start);
+        if(!str)
+            return E_OUTOFMEMORY;
+
+        V_VT(retv) = VT_BSTR;
+        V_BSTR(retv) = retstr;
+    }
+    return S_OK;
 }
 
 static HRESULT String_small(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
         VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
 {
-    FIXME("\n");
-    return E_NOTIMPL;
+    static const WCHAR smalltagW[] = {'S','M','A','L','L',0};
+    return do_attributeless_tag_format(dispex, lcid, flags, dp, retv, ei, sp, smalltagW);
 }
 
 static HRESULT String_split(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
         VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
 {
-    FIXME("\n");
-    return E_NOTIMPL;
+    match_result_t *match_result = NULL;
+    DWORD match_cnt, i, match_len = 0;
+    StringInstance *string;
+    const WCHAR *ptr, *ptr2;
+    VARIANT *arg, var;
+    DispatchEx *array;
+    BSTR match_str = NULL;
+    HRESULT hres;
+
+    TRACE("\n");
+
+    if(!is_class(dispex, JSCLASS_STRING)) {
+        FIXME("not String this\n");
+        return E_NOTIMPL;
+    }
+
+    string = (StringInstance*)dispex;
+
+    if(arg_cnt(dp) != 1) {
+        FIXME("unsupported args\n");
+        return E_NOTIMPL;
+    }
+
+    arg = get_arg(dp, 0);
+    switch(V_VT(arg)) {
+    case VT_DISPATCH: {
+        DispatchEx *regexp;
+
+        regexp = iface_to_jsdisp((IUnknown*)V_DISPATCH(arg));
+        if(regexp) {
+            if(is_class(regexp, JSCLASS_REGEXP)) {
+                hres = regexp_match(regexp, string->str, string->length, TRUE, &match_result, &match_cnt);
+                jsdisp_release(regexp);
+                if(FAILED(hres))
+                    return hres;
+                break;
+            }
+            jsdisp_release(regexp);
+        }
+    }
+    default:
+        hres = to_string(dispex->ctx, arg, ei, &match_str);
+        if(FAILED(hres))
+            return hres;
+
+        match_len = SysStringLen(match_str);
+        if(!match_len) {
+            SysFreeString(match_str);
+            match_str = NULL;
+        }
+    }
+
+    hres = create_array(dispex->ctx, 0, &array);
+
+    if(SUCCEEDED(hres)) {
+        ptr = string->str;
+        for(i=0;; i++) {
+            if(match_result) {
+                if(i == match_cnt)
+                    break;
+                ptr2 = match_result[i].str;
+            }else if(match_str) {
+                ptr2 = strstrW(ptr, match_str);
+                if(!ptr2)
+                    break;
+            }else {
+                if(!*ptr)
+                    break;
+                ptr2 = ptr+1;
+            }
+
+            V_VT(&var) = VT_BSTR;
+            V_BSTR(&var) = SysAllocStringLen(ptr, ptr2-ptr);
+            if(!V_BSTR(&var)) {
+                hres = E_OUTOFMEMORY;
+                break;
+            }
+
+            hres = jsdisp_propput_idx(array, i, lcid, &var, ei, sp);
+            SysFreeString(V_BSTR(&var));
+            if(FAILED(hres))
+                break;
+
+            if(match_result)
+                ptr = match_result[i].str + match_result[i].len;
+            else if(match_str)
+                ptr = ptr2 + match_len;
+            else
+                ptr++;
+        }
+    }
+
+    if(SUCCEEDED(hres) && (match_str || match_result)) {
+        DWORD len = (string->str+string->length) - ptr;
+
+        if(len || match_str) {
+            V_VT(&var) = VT_BSTR;
+            V_BSTR(&var) = SysAllocStringLen(ptr, len);
+
+            if(V_BSTR(&var)) {
+                hres = jsdisp_propput_idx(array, i, lcid, &var, ei, sp);
+                SysFreeString(V_BSTR(&var));
+            }else {
+                hres = E_OUTOFMEMORY;
+            }
+        }
+    }
+
+    SysFreeString(match_str);
+    heap_free(match_result);
+
+    if(SUCCEEDED(hres) && retv) {
+        V_VT(retv) = VT_DISPATCH;
+        V_DISPATCH(retv) = (IDispatch*)_IDispatchEx_(array);
+    }else {
+        jsdisp_release(array);
+    }
+
+    return hres;
 }
 
 static HRESULT String_strike(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
         VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
 {
-    FIXME("\n");
-    return E_NOTIMPL;
+    static const WCHAR striketagW[] = {'S','T','R','I','K','E',0};
+    return do_attributeless_tag_format(dispex, lcid, flags, dp, retv, ei, sp, striketagW);
 }
 
 static HRESULT String_sub(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
         VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
 {
-    FIXME("\n");
-    return E_NOTIMPL;
+    static const WCHAR subtagW[] = {'S','U','B',0};
+    return do_attributeless_tag_format(dispex, lcid, flags, dp, retv, ei, sp, subtagW);
 }
 
+/* ECMA-262 3rd Edition    15.5.4.15 */
 static HRESULT String_substring(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
         VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
 {
-    FIXME("\n");
-    return E_NOTIMPL;
+    const WCHAR *str;
+    INT start=0, end;
+    DWORD length;
+    VARIANT v;
+    HRESULT hres;
+
+    TRACE("\n");
+
+    if(is_class(dispex, JSCLASS_STRING)) {
+        StringInstance *string = (StringInstance*)dispex;
+
+        length = string->length;
+        str = string->str;
+    }else {
+        FIXME("not string this not supported\n");
+        return E_NOTIMPL;
+    }
+
+    if(arg_cnt(dp) >= 1) {
+        hres = to_integer(dispex->ctx, dp->rgvarg + dp->cArgs-1, ei, &v);
+        if(FAILED(hres))
+            return hres;
+
+        if(V_VT(&v) == VT_I4) {
+            start = V_I4(&v);
+            if(start < 0)
+                start = 0;
+            else if(start >= length)
+                start = length;
+        }else {
+            start = V_R8(&v) < 0.0 ? 0 : length;
+        }
+    }
+
+    if(arg_cnt(dp) >= 2) {
+        hres = to_integer(dispex->ctx, dp->rgvarg + dp->cArgs-2, ei, &v);
+        if(FAILED(hres))
+            return hres;
+
+        if(V_VT(&v) == VT_I4) {
+            end = V_I4(&v);
+            if(end < 0)
+                end = 0;
+            else if(end > length)
+                end = length;
+        }else {
+            end = V_R8(&v) < 0.0 ? 0 : length;
+        }
+    }else {
+        end = length;
+    }
+
+    if(start > end) {
+        INT tmp = start;
+        start = end;
+        end = tmp;
+    }
+
+    if(retv) {
+        V_VT(retv) = VT_BSTR;
+        V_BSTR(retv) = SysAllocStringLen(str+start, end-start);
+        if(!V_BSTR(retv))
+            return E_OUTOFMEMORY;
+    }
+    return S_OK;
 }
 
 static HRESULT String_substr(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
@@ -384,22 +1089,74 @@ static HRESULT String_substr(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARA
 static HRESULT String_sup(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
         VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
 {
-    FIXME("\n");
-    return E_NOTIMPL;
+    static const WCHAR suptagW[] = {'S','U','P',0};
+    return do_attributeless_tag_format(dispex, lcid, flags, dp, retv, ei, sp, suptagW);
 }
 
 static HRESULT String_toLowerCase(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
         VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
 {
-    FIXME("\n");
-    return E_NOTIMPL;
+    StringInstance *string;
+    const WCHAR* str;
+    DWORD length;
+    BSTR bstr;
+
+    TRACE("\n");
+
+    if(is_class(dispex, JSCLASS_STRING)) {
+        string = (StringInstance*)dispex;
+
+        length = string->length;
+        str = string->str;
+    }else {
+        FIXME("not string this not supported\n");
+        return E_NOTIMPL;
+    }
+
+    if(retv) {
+        bstr = SysAllocStringLen(str, length);
+        if (!bstr)
+            return E_OUTOFMEMORY;
+
+        strlwrW(bstr);
+
+        V_VT(retv) = VT_BSTR;
+        V_BSTR(retv) = bstr;
+    }
+    return S_OK;
 }
 
 static HRESULT String_toUpperCase(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
         VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
 {
-    FIXME("\n");
-    return E_NOTIMPL;
+    StringInstance *string;
+    const WCHAR* str;
+    DWORD length;
+    BSTR bstr;
+
+    TRACE("\n");
+
+    if(is_class(dispex, JSCLASS_STRING)) {
+        string = (StringInstance*)dispex;
+
+        length = string->length;
+        str = string->str;
+    }else {
+        FIXME("not string this not supported\n");
+        return E_NOTIMPL;
+    }
+
+    if(retv) {
+        bstr = SysAllocStringLen(str, length);
+        if (!bstr)
+            return E_OUTOFMEMORY;
+
+        struprW(bstr);
+
+        V_VT(retv) = VT_BSTR;
+        V_BSTR(retv) = bstr;
+    }
+    return S_OK;
 }
 
 static HRESULT String_toLocaleLowerCase(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
@@ -447,8 +1204,26 @@ static HRESULT String_isPrototypeOf(DispatchEx *dispex, LCID lcid, WORD flags, D
 static HRESULT String_value(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
         VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
 {
-    FIXME("\n");
-    return E_NOTIMPL;
+    StringInstance *This = (StringInstance*)dispex;
+
+    TRACE("\n");
+
+    switch(flags) {
+    case DISPATCH_PROPERTYGET: {
+        BSTR str = SysAllocString(This->str);
+        if(!str)
+            return E_OUTOFMEMORY;
+
+        V_VT(retv) = VT_BSTR;
+        V_BSTR(retv) = str;
+        break;
+    }
+    default:
+        FIXME("flags %x\n", flags);
+        return E_NOTIMPL;
+    }
+
+    return S_OK;
 }
 
 static void String_destructor(DispatchEx *dispex)
@@ -486,9 +1261,9 @@ static const builtin_prop_t String_props[] = {
     {smallW,                 String_small,                 PROPF_METHOD},
     {splitW,                 String_split,                 PROPF_METHOD},
     {strikeW,                String_strike,                PROPF_METHOD},
-    {substringW,             String_substring,             PROPF_METHOD},
-    {substrW,                String_substr,                PROPF_METHOD},
     {subW,                   String_sub,                   PROPF_METHOD},
+    {substrW,                String_substr,                PROPF_METHOD},
+    {substringW,             String_substring,             PROPF_METHOD},
     {supW,                   String_sup,                   PROPF_METHOD},
     {toLocaleLowerCaseW,     String_toLocaleLowerCase,     PROPF_METHOD},
     {toLocaleUpperCaseW,     String_toLocaleUpperCase,     PROPF_METHOD},
@@ -510,8 +1285,58 @@ static const builtin_info_t String_info = {
 static HRESULT StringConstr_value(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
         VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
 {
-    FIXME("\n");
-    return E_NOTIMPL;
+    HRESULT hres;
+
+    TRACE("\n");
+
+    switch(flags) {
+    case INVOKE_FUNC: {
+        BSTR str;
+
+        if(arg_cnt(dp)) {
+            hres = to_string(dispex->ctx, get_arg(dp, 0), ei, &str);
+            if(FAILED(hres))
+                return hres;
+        }else {
+            str = SysAllocStringLen(NULL, 0);
+            if(!str)
+                return E_OUTOFMEMORY;
+        }
+
+        V_VT(retv) = VT_BSTR;
+        V_BSTR(retv) = str;
+        break;
+    }
+    case DISPATCH_CONSTRUCT: {
+        DispatchEx *ret;
+
+        if(arg_cnt(dp)) {
+            BSTR str;
+
+            hres = to_string(dispex->ctx, get_arg(dp, 0), ei, &str);
+            if(FAILED(hres))
+                return hres;
+
+            hres = create_string(dispex->ctx, str, SysStringLen(str), &ret);
+            SysFreeString(str);
+        }else {
+            hres = create_string(dispex->ctx, NULL, 0, &ret);
+        }
+
+        if(FAILED(hres))
+            return hres;
+
+        V_VT(retv) = VT_DISPATCH;
+        V_DISPATCH(retv) = (IDispatch*)_IDispatchEx_(ret);
+        break;
+    }
+
+    default:
+        FIXME("unimplemented flags: %x\n", flags);
+        return E_NOTIMPL;
+    }
+
+    return S_OK;
 }
 
 static HRESULT string_alloc(script_ctx_t *ctx, BOOL use_constr, StringInstance **ret)
index 32da2e0..a6aa73f 100644 (file)
@@ -214,8 +214,10 @@ static ULONG WINAPI HTMLDocument_Release(IHTMLDocument2 *iface)
 
         ConnectionPointContainer_Destroy(&This->cp_container);
 
-        if(This->nsdoc)
+        if(This->nsdoc) {
+            remove_mutation_observer(This->nscontainer, This->nsdoc);
             nsIDOMHTMLDocument_Release(This->nsdoc);
+        }
         if(This->nscontainer)
             NSContainer_Release(This->nscontainer);
 
index 5f0d7fb..c671073 100644 (file)
@@ -88,16 +88,14 @@ static ULONG WINAPI HTMLLocation_Release(IHTMLLocation *iface)
 static HRESULT WINAPI HTMLLocation_GetTypeInfoCount(IHTMLLocation *iface, UINT *pctinfo)
 {
     HTMLLocation *This = HTMLLOCATION_THIS(iface);
-    FIXME("(%p)->(%p)\n", This, pctinfo);
-    return E_NOTIMPL;
+    return IDispatchEx_GetTypeInfoCount(DISPATCHEX(&This->dispex), pctinfo);
 }
 
 static HRESULT WINAPI HTMLLocation_GetTypeInfo(IHTMLLocation *iface, UINT iTInfo,
                                               LCID lcid, ITypeInfo **ppTInfo)
 {
     HTMLLocation *This = HTMLLOCATION_THIS(iface);
-    FIXME("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
-    return E_NOTIMPL;
+    return IDispatchEx_GetTypeInfo(DISPATCHEX(&This->dispex), iTInfo, lcid, ppTInfo);
 }
 
 static HRESULT WINAPI HTMLLocation_GetIDsOfNames(IHTMLLocation *iface, REFIID riid,
@@ -105,9 +103,7 @@ static HRESULT WINAPI HTMLLocation_GetIDsOfNames(IHTMLLocation *iface, REFIID ri
                                                 LCID lcid, DISPID *rgDispId)
 {
     HTMLLocation *This = HTMLLOCATION_THIS(iface);
-    FIXME("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames,
-          lcid, rgDispId);
-    return E_NOTIMPL;
+    return IDispatchEx_GetIDsOfNames(DISPATCHEX(&This->dispex), riid, rgszNames, cNames, lcid, rgDispId);
 }
 
 static HRESULT WINAPI HTMLLocation_Invoke(IHTMLLocation *iface, DISPID dispIdMember,
@@ -115,9 +111,8 @@ static HRESULT WINAPI HTMLLocation_Invoke(IHTMLLocation *iface, DISPID dispIdMem
                             VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
 {
     HTMLLocation *This = HTMLLOCATION_THIS(iface);
-    FIXME("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
-          lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
-    return E_NOTIMPL;
+    return IDispatchEx_Invoke(DISPATCHEX(&This->dispex), dispIdMember, riid, lcid,
+            wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
 }
 
 static HRESULT WINAPI HTMLLocation_put_href(IHTMLLocation *iface, BSTR v)
index f252c70..18d3e31 100644 (file)
@@ -468,6 +468,12 @@ static HRESULT WINAPI HTMLStyle_QueryInterface(IHTMLStyle *iface, REFIID riid, v
     }else if(IsEqualGUID(&IID_IHTMLStyle2, riid)) {
         TRACE("(%p)->(IID_IHTMLStyle2 %p)\n", This, ppv);
         *ppv = HTMLSTYLE2(This);
+    }else if(IsEqualGUID(&IID_IHTMLStyle3, riid)) {
+        TRACE("(%p)->(IID_IHTMLStyle3 %p)\n", This, ppv);
+        *ppv = HTMLSTYLE3(This);
+    }else if(IsEqualGUID(&IID_IHTMLStyle4, riid)) {
+        TRACE("(%p)->(IID_IHTMLStyle4 %p)\n", This, ppv);
+        *ppv = HTMLSTYLE4(This);
     }else if(dispex_query_interface(&This->dispex, riid, ppv)) {
         return *ppv ? S_OK : E_NOINTERFACE;
     }
@@ -612,8 +618,35 @@ static HRESULT WINAPI HTMLStyle_get_fontVariant(IHTMLStyle *iface, BSTR *p)
 static HRESULT WINAPI HTMLStyle_put_fontWeight(IHTMLStyle *iface, BSTR v)
 {
     HTMLStyle *This = HTMLSTYLE_THIS(iface);
-    FIXME("(%p)->(%s)\n", This, debugstr_w(v));
-    return E_NOTIMPL;
+    static const WCHAR styleBold[] = {'b','o','l','d',0};
+    static const WCHAR styleBolder[] = {'b','o','l','d','e','r',0};
+    static const WCHAR styleLighter[]  = {'l','i','g','h','t','e','r',0};
+    static const WCHAR style100[] = {'1','0','0',0};
+    static const WCHAR style200[] = {'2','0','0',0};
+    static const WCHAR style300[] = {'3','0','0',0};
+    static const WCHAR style400[] = {'4','0','0',0};
+    static const WCHAR style500[] = {'5','0','0',0};
+    static const WCHAR style600[] = {'6','0','0',0};
+    static const WCHAR style700[] = {'7','0','0',0};
+    static const WCHAR style800[] = {'8','0','0',0};
+    static const WCHAR style900[] = {'9','0','0',0};
+
+    TRACE("(%p)->(%s)\n", This, debugstr_w(v));
+
+    /* fontWeight can only be one of the following */
+    if(!v || strcmpiW(szNormal, v) == 0    || strcmpiW(styleBold, v) == 0    ||
+             strcmpiW(styleBolder, v) == 0 || strcmpiW(styleLighter, v) == 0 ||
+             strcmpiW(style100, v) == 0    || strcmpiW(style200, v) == 0     ||
+             strcmpiW(style300, v) == 0    || strcmpiW(style400, v) == 0     ||
+             strcmpiW(style500, v) == 0    || strcmpiW(style600, v) == 0     ||
+             strcmpiW(style700, v) == 0    || strcmpiW(style800, v) == 0     ||
+             strcmpiW(style900, v) == 0
+             )
+    {
+        return set_nsstyle_attr(This->nsstyle, STYLEID_FONT_WEIGHT, v, 0);
+    }
+
+    return E_INVALIDARG;
 }
 
 static HRESULT WINAPI HTMLStyle_get_fontWeight(IHTMLStyle *iface, BSTR *p)
@@ -737,8 +770,10 @@ static HRESULT WINAPI HTMLStyle_put_backgroundColor(IHTMLStyle *iface, VARIANT v
 static HRESULT WINAPI HTMLStyle_get_backgroundColor(IHTMLStyle *iface, VARIANT *p)
 {
     HTMLStyle *This = HTMLSTYLE_THIS(iface);
-    FIXME("(%p)->(%p)\n", This, p);
-    return E_NOTIMPL;
+    TRACE("(%p)->(%p)\n", This, p);
+
+    V_VT(p) = VT_BSTR;
+    return get_style_attr(This, STYLEID_BACKGROUND_COLOR, &V_BSTR(p));
 }
 
 static HRESULT WINAPI HTMLStyle_put_backgroundImage(IHTMLStyle *iface, BSTR v)
@@ -890,8 +925,10 @@ static HRESULT WINAPI HTMLStyle_get_textDecorationNone(IHTMLStyle *iface, VARIAN
 static HRESULT WINAPI HTMLStyle_put_textDecorationUnderline(IHTMLStyle *iface, VARIANT_BOOL v)
 {
     HTMLStyle *This = HTMLSTYLE_THIS(iface);
-    FIXME("(%p)->(%x)\n", This, v);
-    return E_NOTIMPL;
+
+    TRACE("(%p)->(%x)\n", This, v);
+
+    return set_style_attr(This, STYLEID_TEXT_DECORATION, v ? valUnderline : emptyW, 0);
 }
 
 static HRESULT WINAPI HTMLStyle_get_textDecorationUnderline(IHTMLStyle *iface, VARIANT_BOOL *p)
@@ -920,8 +957,10 @@ static HRESULT WINAPI HTMLStyle_get_textDecorationOverline(IHTMLStyle *iface, VA
 static HRESULT WINAPI HTMLStyle_put_textDecorationLineThrough(IHTMLStyle *iface, VARIANT_BOOL v)
 {
     HTMLStyle *This = HTMLSTYLE_THIS(iface);
-    FIXME("(%p)->(%x)\n", This, v);
-    return E_NOTIMPL;
+
+    TRACE("(%p)->(%x)\n", This, v);
+
+    return set_style_attr(This, STYLEID_TEXT_DECORATION, v ? valLineThrough : emptyW, 0);
 }
 
 static HRESULT WINAPI HTMLStyle_get_textDecorationLineThrough(IHTMLStyle *iface, VARIANT_BOOL *p)
@@ -1218,8 +1257,18 @@ static HRESULT WINAPI HTMLStyle_put_paddingLeft(IHTMLStyle *iface, VARIANT v)
 static HRESULT WINAPI HTMLStyle_get_paddingLeft(IHTMLStyle *iface, VARIANT *p)
 {
     HTMLStyle *This = HTMLSTYLE_THIS(iface);
-    FIXME("(%p)->(%p)\n", This, p);
-    return E_NOTIMPL;
+    BSTR ret;
+    HRESULT hres;
+
+    TRACE("(%p)->(%p)\n", This, p);
+
+    hres = get_style_attr(This, STYLEID_PADDING_LEFT, &ret);
+    if(FAILED(hres))
+        return hres;
+
+    V_VT(p) = VT_BSTR;
+    V_BSTR(p) = ret;
+    return S_OK;
 }
 
 static HRESULT WINAPI HTMLStyle_put_padding(IHTMLStyle *iface, BSTR v)
@@ -2425,6 +2474,7 @@ IHTMLStyle *HTMLStyle_Create(nsIDOMCSSStyleDeclaration *nsstyle)
     ret->ref = 1;
     ret->nsstyle = nsstyle;
     HTMLStyle2_Init(ret);
+    HTMLStyle3_Init(ret);
 
     nsIDOMCSSStyleDeclaration_AddRef(nsstyle);
 
index b543380..a9ff535 100644 (file)
@@ -20,6 +20,8 @@ struct HTMLStyle {
     DispatchEx dispex;
     const IHTMLStyleVtbl    *lpHTMLStyleVtbl;
     const IHTMLStyle2Vtbl   *lpHTMLStyle2Vtbl;
+    const IHTMLStyle3Vtbl   *lpHTMLStyle3Vtbl;
+    const IHTMLStyle4Vtbl   *lpHTMLStyle4Vtbl;
 
     LONG ref;
 
@@ -28,6 +30,8 @@ struct HTMLStyle {
 
 #define HTMLSTYLE(x)     ((IHTMLStyle*)                   &(x)->lpHTMLStyleVtbl)
 #define HTMLSTYLE2(x)    ((IHTMLStyle2*)                  &(x)->lpHTMLStyle2Vtbl)
+#define HTMLSTYLE3(x)    ((IHTMLStyle3*)                  &(x)->lpHTMLStyle3Vtbl)
+#define HTMLSTYLE4(x)    ((IHTMLStyle4*)                  &(x)->lpHTMLStyle4Vtbl)
 
 /* NOTE: Make sure to keep in sync with style_tbl in htmlstyle.c */
 typedef enum {
@@ -68,6 +72,7 @@ typedef enum {
 } styleid_t;
 
 void HTMLStyle2_Init(HTMLStyle*);
+void HTMLStyle3_Init(HTMLStyle*);
 
 HRESULT get_nsstyle_attr(nsIDOMCSSStyleDeclaration*,styleid_t,BSTR*);
 HRESULT set_nsstyle_attr(nsIDOMCSSStyleDeclaration*,styleid_t,LPCWSTR,DWORD);
diff --git a/reactos/dll/win32/mshtml/htmlstyle3.c b/reactos/dll/win32/mshtml/htmlstyle3.c
new file mode 100644 (file)
index 0000000..f5ed8b5
--- /dev/null
@@ -0,0 +1,441 @@
+/*
+ * Copyright 2009 Alistair Leslie-Hughes
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include <stdarg.h>
+
+#define COBJMACROS
+
+#include "windef.h"
+#include "winbase.h"
+#include "winuser.h"
+#include "ole2.h"
+
+#include "mshtml_private.h"
+#include "htmlstyle.h"
+
+#include "wine/debug.h"
+#include "wine/unicode.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(mshtml);
+
+#define HTMLSTYLE3_THIS(iface) DEFINE_THIS(HTMLStyle, HTMLStyle3, iface)
+
+static HRESULT WINAPI HTMLStyle3_QueryInterface(IHTMLStyle3 *iface, REFIID riid, void **ppv)
+{
+    HTMLStyle *This = HTMLSTYLE3_THIS(iface);
+
+    return IHTMLStyle_QueryInterface(HTMLSTYLE(This), riid, ppv);
+}
+
+static ULONG WINAPI HTMLStyle3_AddRef(IHTMLStyle3 *iface)
+{
+    HTMLStyle *This = HTMLSTYLE3_THIS(iface);
+
+    return IHTMLStyle_AddRef(HTMLSTYLE(This));
+}
+
+static ULONG WINAPI HTMLStyle3_Release(IHTMLStyle3 *iface)
+{
+    HTMLStyle *This = HTMLSTYLE3_THIS(iface);
+
+    return IHTMLStyle_Release(HTMLSTYLE(This));
+}
+
+static HRESULT WINAPI HTMLStyle3_GetTypeInfoCount(IHTMLStyle3 *iface, UINT *pctinfo)
+{
+    HTMLStyle *This = HTMLSTYLE3_THIS(iface);
+    return IDispatchEx_GetTypeInfoCount(DISPATCHEX(&This->dispex), pctinfo);
+}
+
+static HRESULT WINAPI HTMLStyle3_GetTypeInfo(IHTMLStyle3 *iface, UINT iTInfo,
+                                              LCID lcid, ITypeInfo **ppTInfo)
+{
+    HTMLStyle *This = HTMLSTYLE3_THIS(iface);
+    return IDispatchEx_GetTypeInfo(DISPATCHEX(&This->dispex), iTInfo, lcid, ppTInfo);
+}
+
+static HRESULT WINAPI HTMLStyle3_GetIDsOfNames(IHTMLStyle3 *iface, REFIID riid,
+                                                LPOLESTR *rgszNames, UINT cNames,
+                                                LCID lcid, DISPID *rgDispId)
+{
+    HTMLStyle *This = HTMLSTYLE3_THIS(iface);
+    return IDispatchEx_GetIDsOfNames(DISPATCHEX(&This->dispex), riid, rgszNames, cNames, lcid, rgDispId);
+}
+
+static HRESULT WINAPI HTMLStyle3_Invoke(IHTMLStyle3 *iface, DISPID dispIdMember,
+                            REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
+                            VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
+{
+    HTMLStyle *This = HTMLSTYLE3_THIS(iface);
+    return IDispatchEx_Invoke(DISPATCHEX(&This->dispex), dispIdMember, riid, lcid,
+            wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
+}
+
+static HRESULT WINAPI HTMLStyle3_put_layoutFlow(IHTMLStyle3 *iface, BSTR v)
+{
+    HTMLStyle *This = HTMLSTYLE3_THIS(iface);
+    FIXME("(%p)->(%s)\n", This, debugstr_w(v));
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI HTMLStyle3_get_layoutFlow(IHTMLStyle3 *iface, BSTR *p)
+{
+    HTMLStyle *This = HTMLSTYLE3_THIS(iface);
+    FIXME("(%p)->(%p)\n", This, p);
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI HTMLStyle3_put_zoom(IHTMLStyle3 *iface, VARIANT v)
+{
+    HTMLStyle *This = HTMLSTYLE3_THIS(iface);
+    FIXME("(%p)->(%s)\n", This, debugstr_variant(&v));
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI HTMLStyle3_get_zoom(IHTMLStyle3 *iface, VARIANT *p)
+{
+    HTMLStyle *This = HTMLSTYLE3_THIS(iface);
+    FIXME("(%p)->(%p)\n", This, p);
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI HTMLStyle3_put_wordWrap(IHTMLStyle3 *iface, BSTR v)
+{
+    HTMLStyle *This = HTMLSTYLE3_THIS(iface);
+    FIXME("(%p)->(%s)\n", This, debugstr_w(v));
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI HTMLStyle3_get_wordWrap(IHTMLStyle3 *iface, BSTR *p)
+{
+    HTMLStyle *This = HTMLSTYLE3_THIS(iface);
+    FIXME("(%p)->(%p)\n", This, p);
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI HTMLStyle3_put_textUnderlinePosition(IHTMLStyle3 *iface, BSTR v)
+{
+    HTMLStyle *This = HTMLSTYLE3_THIS(iface);
+    FIXME("(%p)->(%s)\n", This, debugstr_w(v));
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI HTMLStyle3_get_textUnderlinePosition(IHTMLStyle3 *iface, BSTR *p)
+{
+    HTMLStyle *This = HTMLSTYLE3_THIS(iface);
+    FIXME("(%p)->(%p)\n", This, p);
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI HTMLStyle3_put_scrollbarBaseColor(IHTMLStyle3 *iface, VARIANT v)
+{
+    HTMLStyle *This = HTMLSTYLE3_THIS(iface);
+    FIXME("(%p)->(%s)\n", This, debugstr_variant(&v));
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI HTMLStyle3_get_scrollbarBaseColor(IHTMLStyle3 *iface, VARIANT *p)
+{
+    HTMLStyle *This = HTMLSTYLE3_THIS(iface);
+    FIXME("(%p)->(%p)\n", This, p);
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI HTMLStyle3_put_scrollbarFaceColor(IHTMLStyle3 *iface, VARIANT v)
+{
+    HTMLStyle *This = HTMLSTYLE3_THIS(iface);
+    FIXME("(%p)->(%s)\n", This, debugstr_variant(&v));
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI HTMLStyle3_get_scrollbarFaceColor(IHTMLStyle3 *iface, VARIANT *p)
+{
+    HTMLStyle *This = HTMLSTYLE3_THIS(iface);
+    FIXME("(%p)->(%p)\n", This, p);
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI HTMLStyle3_put_scrollbar3dLightColor(IHTMLStyle3 *iface, VARIANT v)
+{
+    HTMLStyle *This = HTMLSTYLE3_THIS(iface);
+    FIXME("(%p)->(%s)\n", This, debugstr_variant(&v));
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI HTMLStyle3_get_scrollbar3dLightColor(IHTMLStyle3 *iface, VARIANT *p)
+{
+    HTMLStyle *This = HTMLSTYLE3_THIS(iface);
+    FIXME("(%p)->(%p)\n", This, p);
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI HTMLStyle3_put_scrollbarShadowColor(IHTMLStyle3 *iface, VARIANT v)
+{
+    HTMLStyle *This = HTMLSTYLE3_THIS(iface);
+    FIXME("(%p)->(%s)\n", This, debugstr_variant(&v));
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI HTMLStyle3_get_scrollbarShadowColor(IHTMLStyle3 *iface, VARIANT *p)
+{
+    HTMLStyle *This = HTMLSTYLE3_THIS(iface);
+    FIXME("(%p)->(%p)\n", This, p);
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI HTMLStyle3_put_scrollbarHighlightColor(IHTMLStyle3 *iface, VARIANT v)
+{
+    HTMLStyle *This = HTMLSTYLE3_THIS(iface);
+    FIXME("(%p)->(%s)\n", This, debugstr_variant(&v));
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI HTMLStyle3_get_scrollbarHighlightColor(IHTMLStyle3 *iface, VARIANT *p)
+{
+    HTMLStyle *This = HTMLSTYLE3_THIS(iface);
+    FIXME("(%p)->(%p)\n", This, p);
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI HTMLStyle3_put_scrollbarDarkShadowColor(IHTMLStyle3 *iface, VARIANT v)
+{
+    HTMLStyle *This = HTMLSTYLE3_THIS(iface);
+    FIXME("(%p)->(%s)\n", This, debugstr_variant(&v));
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI HTMLStyle3_get_scrollbarDarkShadowColor(IHTMLStyle3 *iface, VARIANT *p)
+{
+    HTMLStyle *This = HTMLSTYLE3_THIS(iface);
+    FIXME("(%p)->(%p)\n", This, p);
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI HTMLStyle3_put_scrollbarArrowColor(IHTMLStyle3 *iface, VARIANT v)
+{
+    HTMLStyle *This = HTMLSTYLE3_THIS(iface);
+    FIXME("(%p)->(%s)\n", This, debugstr_variant(&v));
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI HTMLStyle3_get_scrollbarArrowColor(IHTMLStyle3 *iface, VARIANT *p)
+{
+    HTMLStyle *This = HTMLSTYLE3_THIS(iface);
+    FIXME("(%p)->(%p)\n", This, p);
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI HTMLStyle3_put_scrollbarTrackColor(IHTMLStyle3 *iface, VARIANT v)
+{
+    HTMLStyle *This = HTMLSTYLE3_THIS(iface);
+    FIXME("(%p)->(%s)\n", This, debugstr_variant(&v));
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI HTMLStyle3_get_scrollbarTrackColor(IHTMLStyle3 *iface, VARIANT *p)
+{
+    HTMLStyle *This = HTMLSTYLE3_THIS(iface);
+    FIXME("(%p)->(%p)\n", This, p);
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI HTMLStyle3_put_writingMode(IHTMLStyle3 *iface, BSTR v)
+{
+    HTMLStyle *This = HTMLSTYLE3_THIS(iface);
+    FIXME("(%p)->(%s)\n", This, debugstr_w(v));
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI HTMLStyle3_get_writingMode(IHTMLStyle3 *iface, BSTR *p)
+{
+    HTMLStyle *This = HTMLSTYLE3_THIS(iface);
+    FIXME("(%p)->(%p)\n", This, p);
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI HTMLStyle3_put_textAlignLast(IHTMLStyle3 *iface, BSTR v)
+{
+    HTMLStyle *This = HTMLSTYLE3_THIS(iface);
+    FIXME("(%p)->(%s)\n", This, debugstr_w(v));
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI HTMLStyle3_get_textAlignLast(IHTMLStyle3 *iface, BSTR *p)
+{
+    HTMLStyle *This = HTMLSTYLE3_THIS(iface);
+    FIXME("(%p)->(%p)\n", This, p);
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI HTMLStyle3_put_textKashidaSpace(IHTMLStyle3 *iface, VARIANT v)
+{
+    HTMLStyle *This = HTMLSTYLE3_THIS(iface);
+    FIXME("(%p)->(%s)\n", This, debugstr_variant(&v));
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI HTMLStyle3_get_textKashidaSpace(IHTMLStyle3 *iface, VARIANT *p)
+{
+    HTMLStyle *This = HTMLSTYLE3_THIS(iface);
+    FIXME("(%p)->(%p)\n", This, p);
+    return E_NOTIMPL;
+}
+
+static const IHTMLStyle3Vtbl HTMLStyle3Vtbl = {
+    HTMLStyle3_QueryInterface,
+    HTMLStyle3_AddRef,
+    HTMLStyle3_Release,
+    HTMLStyle3_GetTypeInfoCount,
+    HTMLStyle3_GetTypeInfo,
+    HTMLStyle3_GetIDsOfNames,
+    HTMLStyle3_Invoke,
+    HTMLStyle3_put_layoutFlow,
+    HTMLStyle3_get_layoutFlow,
+    HTMLStyle3_put_zoom,
+    HTMLStyle3_get_zoom,
+    HTMLStyle3_put_wordWrap,
+    HTMLStyle3_get_wordWrap,
+    HTMLStyle3_put_textUnderlinePosition,
+    HTMLStyle3_get_textUnderlinePosition,
+    HTMLStyle3_put_scrollbarBaseColor,
+    HTMLStyle3_get_scrollbarBaseColor,
+    HTMLStyle3_put_scrollbarFaceColor,
+    HTMLStyle3_get_scrollbarFaceColor,
+    HTMLStyle3_put_scrollbar3dLightColor,
+    HTMLStyle3_get_scrollbar3dLightColor,
+    HTMLStyle3_put_scrollbarShadowColor,
+    HTMLStyle3_get_scrollbarShadowColor,
+    HTMLStyle3_put_scrollbarHighlightColor,
+    HTMLStyle3_get_scrollbarHighlightColor,
+    HTMLStyle3_put_scrollbarDarkShadowColor,
+    HTMLStyle3_get_scrollbarDarkShadowColor,
+    HTMLStyle3_put_scrollbarArrowColor,
+    HTMLStyle3_get_scrollbarArrowColor,
+    HTMLStyle3_put_scrollbarTrackColor,
+    HTMLStyle3_get_scrollbarTrackColor,
+    HTMLStyle3_put_writingMode,
+    HTMLStyle3_get_writingMode,
+    HTMLStyle3_put_textAlignLast,
+    HTMLStyle3_get_textAlignLast,
+    HTMLStyle3_put_textKashidaSpace,
+    HTMLStyle3_get_textKashidaSpace
+};
+
+/*
+ * IHTMLStyle4 Interface
+ */
+#define HTMLSTYLE4_THIS(iface) DEFINE_THIS(HTMLStyle, HTMLStyle4, iface)
+
+static HRESULT WINAPI HTMLStyle4_QueryInterface(IHTMLStyle4 *iface, REFIID riid, void **ppv)
+{
+    HTMLStyle *This = HTMLSTYLE4_THIS(iface);
+
+    return IHTMLStyle_QueryInterface(HTMLSTYLE(This), riid, ppv);
+}
+
+static ULONG WINAPI HTMLStyle4_AddRef(IHTMLStyle4 *iface)
+{
+    HTMLStyle *This = HTMLSTYLE4_THIS(iface);
+
+    return IHTMLStyle_AddRef(HTMLSTYLE(This));
+}
+
+static ULONG WINAPI HTMLStyle4_Release(IHTMLStyle4 *iface)
+{
+    HTMLStyle *This = HTMLSTYLE4_THIS(iface);
+
+    return IHTMLStyle_Release(HTMLSTYLE(This));
+}
+
+static HRESULT WINAPI HTMLStyle4_GetTypeInfoCount(IHTMLStyle4 *iface, UINT *pctinfo)
+{
+    HTMLStyle *This = HTMLSTYLE4_THIS(iface);
+    return IDispatchEx_GetTypeInfoCount(DISPATCHEX(&This->dispex), pctinfo);
+}
+
+static HRESULT WINAPI HTMLStyle4_GetTypeInfo(IHTMLStyle4 *iface, UINT iTInfo,
+                                              LCID lcid, ITypeInfo **ppTInfo)
+{
+    HTMLStyle *This = HTMLSTYLE4_THIS(iface);
+    return IDispatchEx_GetTypeInfo(DISPATCHEX(&This->dispex), iTInfo, lcid, ppTInfo);
+}
+
+static HRESULT WINAPI HTMLStyle4_GetIDsOfNames(IHTMLStyle4 *iface, REFIID riid,
+                                                LPOLESTR *rgszNames, UINT cNames,
+                                                LCID lcid, DISPID *rgDispId)
+{
+    HTMLStyle *This = HTMLSTYLE4_THIS(iface);
+    return IDispatchEx_GetIDsOfNames(DISPATCHEX(&This->dispex), riid, rgszNames, cNames, lcid, rgDispId);
+}
+
+static HRESULT WINAPI HTMLStyle4_Invoke(IHTMLStyle4 *iface, DISPID dispIdMember,
+                            REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
+                            VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
+{
+    HTMLStyle *This = HTMLSTYLE4_THIS(iface);
+    return IDispatchEx_Invoke(DISPATCHEX(&This->dispex), dispIdMember, riid, lcid,
+            wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
+}
+
+static HRESULT WINAPI HTMLStyle4_put_textOverflow(IHTMLStyle4 *iface, BSTR v)
+{
+    HTMLStyle *This = HTMLSTYLE4_THIS(iface);
+    FIXME("(%p)->(%s)\n", This, debugstr_w(v));
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI HTMLStyle4_get_textOverflow(IHTMLStyle4 *iface, BSTR *p)
+{
+    HTMLStyle *This = HTMLSTYLE4_THIS(iface);
+    FIXME("(%p)->(%p)\n", This, p);
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI HTMLStyle4_put_minHeight(IHTMLStyle4 *iface, VARIANT v)
+{
+    HTMLStyle *This = HTMLSTYLE4_THIS(iface);
+    FIXME("(%p)->(%s)\n", This, debugstr_variant(&v));
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI HTMLStyle4_get_minHeight(IHTMLStyle4 *iface, VARIANT *p)
+{
+    HTMLStyle *This = HTMLSTYLE4_THIS(iface);
+    FIXME("(%p)->(%p)\n", This, p);
+    return E_NOTIMPL;
+}
+
+static const IHTMLStyle4Vtbl HTMLStyle4Vtbl = {
+    HTMLStyle4_QueryInterface,
+    HTMLStyle4_AddRef,
+    HTMLStyle4_Release,
+    HTMLStyle4_GetTypeInfoCount,
+    HTMLStyle4_GetTypeInfo,
+    HTMLStyle4_GetIDsOfNames,
+    HTMLStyle4_Invoke,
+    HTMLStyle4_put_textOverflow,
+    HTMLStyle4_get_textOverflow,
+    HTMLStyle4_put_minHeight,
+    HTMLStyle4_get_minHeight
+};
+
+void HTMLStyle3_Init(HTMLStyle *This)
+{
+    This->lpHTMLStyle3Vtbl = &HTMLStyle3Vtbl;
+    This->lpHTMLStyle4Vtbl = &HTMLStyle4Vtbl;
+}
index adbe740..5be78b8 100644 (file)
 
 WINE_DEFAULT_DEBUG_CHANNEL(mshtml);
 
-typedef struct {
+struct HTMLStyleSheet {
     const IHTMLStyleSheetVtbl *lpHTMLStyleSheetVtbl;
 
     LONG ref;
 
     nsIDOMCSSStyleSheet *nsstylesheet;
-} HTMLStyleSheet;
+};
 
-typedef struct {
+struct HTMLStyleSheetsCollection {
     const IHTMLStyleSheetsCollectionVtbl *lpHTMLStyleSheetsCollectionVtbl;
 
     LONG ref;
 
     nsIDOMStyleSheetList *nslist;
-} HTMLStyleSheetsCollection;
+};
 
 typedef struct {
     const IHTMLStyleSheetRulesCollectionVtbl *lpHTMLStyleSheetRulesCollectionVtbl;
index 9f1330d..15f6d93 100644 (file)
@@ -54,11 +54,6 @@ static const WCHAR mshtml_keyW[] =
      '\\','W','i','n','e',
      '\\','M','S','H','T','M','L',0};
 
-static const CHAR mshtml_keyA[] =
-    {'S','o','f','t','w','a','r','e',
-     '\\','W','i','n','e',
-     '\\','M','S','H','T','M','L',0};
-
 static HWND install_dialog = NULL;
 static LPWSTR tmp_file_name = NULL;
 static HANDLE tmp_file = INVALID_HANDLE_VALUE;
@@ -202,17 +197,17 @@ static BOOL install_from_unix_file(const char *file_name)
         wine_get_dos_file_name = (void*)GetProcAddress(GetModuleHandleW(kernel32W), "wine_get_dos_file_name");
 
     if(wine_get_dos_file_name) { /* Wine UNIX mode */
-        dos_file_name = wine_get_dos_file_name(file_name);
-        if(!dos_file_name) {
-            ERR("Could not get dos file name of %s\n", debugstr_a(file_name));
-            return FALSE;
-        }
-    } else { /* ReactOS mode. */
-        UINT res;
-        WARN("Could not get wine_get_dos_file_name function, calling install_cab directly.\n");
-        res = MultiByteToWideChar( CP_ACP, 0, file_name, -1, 0, 0);
-        dos_file_name = heap_alloc (res*sizeof(WCHAR));
-        MultiByteToWideChar( CP_ACP, 0, file_name, -1, dos_file_name, res);
+       dos_file_name = wine_get_dos_file_name(file_name);
+       if(!dos_file_name) {
+           ERR("Could not get dos file name of %s\n", debugstr_a(file_name));
+           return FALSE;
+       }
+    } else { /* Windows mode */
+       UINT res;
+       WARN("Could not get wine_get_dos_file_name function, calling install_cab directly.\n");
+       res = MultiByteToWideChar( CP_ACP, 0, file_name, -1, 0, 0);
+       dos_file_name = heap_alloc (res*sizeof(WCHAR));
+       MultiByteToWideChar( CP_ACP, 0, file_name, -1, dos_file_name, res);
     }
 
     ret = install_cab(dos_file_name);
@@ -224,18 +219,23 @@ static BOOL install_from_unix_file(const char *file_name)
 static BOOL install_from_registered_dir(void)
 {
     char *file_name;
+    HKEY hkey;
     DWORD res, type, size = MAX_PATH;
     BOOL ret;
 
-    file_name = heap_alloc(size+sizeof(GECKO_FILE_NAME));
     /* @@ Wine registry key: HKCU\Software\Wine\MSHTML */
-    res = RegGetValueA(HKEY_CURRENT_USER, mshtml_keyA, "GeckoCabDir", RRF_RT_ANY, &type, (PBYTE)file_name, &size);
+    res = RegOpenKeyW(HKEY_CURRENT_USER, mshtml_keyW, &hkey);
+    if(res != ERROR_SUCCESS)
+        return FALSE;
+
+    file_name = heap_alloc(size+sizeof(GECKO_FILE_NAME));
+    res = RegQueryValueExA(hkey, "GeckoCabDir", NULL, &type, (PBYTE)file_name, &size);
     if(res == ERROR_MORE_DATA) {
         file_name = heap_realloc(file_name, size+sizeof(GECKO_FILE_NAME));
-        res = RegGetValueA(HKEY_CURRENT_USER, mshtml_keyA, "GeckoCabDir", RRF_RT_ANY, &type, (PBYTE)file_name, &size);
+        res = RegQueryValueExA(hkey, "GeckoCabDir", NULL, &type, (PBYTE)file_name, &size);
     }
-    
-    if(res != ERROR_SUCCESS || (type != REG_SZ && type != REG_EXPAND_SZ)) {
+    RegCloseKey(hkey);
+    if(res != ERROR_SUCCESS || type != REG_SZ) {
         heap_free(file_name);
         return FALSE;
     }
@@ -384,13 +384,14 @@ static HRESULT WINAPI InstallCallback_OnDataAvailable(IBindStatusCallback *iface
     BYTE buf[1024];
     DWORD size;
     HRESULT hres;
-       DWORD dwBytesWritten;
 
     do {
+        DWORD written;
+
         size = 0;
         hres = IStream_Read(str, buf, sizeof(buf), &size);
         if(size)
-            WriteFile(tmp_file, buf, size, &dwBytesWritten, NULL);
+            WriteFile(tmp_file, buf, size, &written, NULL);
     }while(hres == S_OK);
 
     return S_OK;
@@ -446,7 +447,7 @@ static LPWSTR get_url(void)
 
     if(size > sizeof(httpW) && !memcmp(url, httpW, sizeof(httpW))) {
         strcatW(url, v_formatW);
-        MultiByteToWideChar(CP_ACP, 0, GECKO_VERSION, -1, url+strlenW(url), (size-strlenW(url)) / sizeof(WCHAR));
+        MultiByteToWideChar(CP_ACP, 0, GECKO_VERSION, -1, url+strlenW(url), size/sizeof(WCHAR)-strlenW(url));
     }
 
     TRACE("Got URL %s\n", debugstr_w(url));
index e2fb0b9..06d8ac0 100644 (file)
@@ -35,6 +35,7 @@
        <file>htmlselect.c</file>
        <file>htmlstyle.c</file>
        <file>htmlstyle2.c</file>
+       <file>htmlstyle3.c</file>
        <file>htmlstylesheet.c</file>
        <file>htmltable.c</file>
        <file>htmltablerow.c</file>
index d884ca3..b67c485 100644 (file)
@@ -199,14 +199,14 @@ struct ConnectionPoint {
     ConnectionPoint *next;
 };
 
-typedef struct {
+struct HTMLLocation {
     DispatchEx dispex;
     const IHTMLLocationVtbl *lpHTMLLocationVtbl;
 
     LONG ref;
 
     HTMLDocument *doc;
-} HTMLLocation;
+};
 
 typedef struct {
     const IHTMLOptionElementFactoryVtbl *lpHTMLOptionElementFactoryVtbl;
@@ -510,6 +510,7 @@ void NSContainer_Release(NSContainer*);
 
 void init_mutation(NSContainer*);
 void set_mutation_observer(NSContainer*,nsIDOMHTMLDocument*);
+void remove_mutation_observer(NSContainer*,nsIDOMHTMLDocument*);
 
 void HTMLDocument_LockContainer(HTMLDocument*,BOOL);
 void show_context_menu(HTMLDocument*,DWORD,POINT*,IDispatch*);
index 3994888..ab9649c 100644 (file)
@@ -55,6 +55,21 @@ void set_mutation_observer(NSContainer *nscontainer, nsIDOMHTMLDocument *nshtmld
     nsIDOMNSDocument_Release(nsdoc);
 }
 
+void remove_mutation_observer(NSContainer *nscontainer, nsIDOMHTMLDocument *nshtmldoc)
+{
+    nsIDOMNSDocument *nsdoc;
+    nsresult nsres;
+
+    nsres = nsIDOMHTMLDocument_QueryInterface(nshtmldoc, &IID_nsIDOMNSDocument, (void**)&nsdoc);
+    if(NS_FAILED(nsres)) {
+        ERR("Could not get nsIDOMNSDocument: %08x\n", nsres);
+        return;
+    }
+
+    nsIDOMNSDocument_WineRemoveObserver(nsdoc, NSDOCOBS(nscontainer));
+    nsIDOMNSDocument_Release(nsdoc);
+}
+
 #define IE_MAJOR_VERSION 7
 #define IE_MINOR_VERSION 0
 
@@ -358,7 +373,7 @@ static nsresult NSAPI nsDocumentObserver_QueryInterface(nsIDocumentObserver *ifa
 
     if(IsEqualGUID(&IID_nsISupports, riid)) {
         TRACE("(%p)->(IID_nsISupports, %p)\n", This, result);
-        *result = NSWBCHROME(This);
+        *result = NSDOCOBS(This);
     }else if(IsEqualGUID(&IID_nsIMutationObserver, riid)) {
         TRACE("(%p)->(IID_nsIMutationObserver %p)\n", This, result);
         *result = NSDOCOBS(This);
index ee386ac..16ac21e 100644 (file)
@@ -857,8 +857,10 @@ void update_nsdocument(HTMLDocument *doc)
         return;
     }
 
-    if(doc->nsdoc)
+    if(doc->nsdoc) {
+        remove_mutation_observer(doc->nscontainer, doc->nsdoc);
         nsIDOMHTMLDocument_Release(doc->nsdoc);
+    }
 
     doc->nsdoc = nsdoc;
 
index 219ac0c..894bb41 100644 (file)
  * compatible with XPCOM, usable in C code.
  */
 
-cpp_quote("#define GECKO_VERSION \"0.9.0\"")
+cpp_quote("#define GECKO_VERSION \"0.9.1\"")
 cpp_quote("#define GECKO_VERSION_STRING \"Wine Gecko \" GECKO_VERSION")
 
 import "wtypes.idl";
 
+cpp_quote("#ifdef WINE_NO_UNICODE_MACROS")
+cpp_quote("#undef GetForm")
+cpp_quote("#undef SetPort")
+cpp_quote("#endif")
+
 typedef HRESULT nsresult;
 typedef ULONG nsrefcnt;
 
@@ -873,6 +878,7 @@ interface nsIDOMNSDocument : nsISupports
 
     /* Wine extensions */
     nsresult WineAddObserver(nsIDocumentObserver *aObserver);
+    nsresult WineRemoveObserver(nsIDocumentObserver *aObserver);
     nsresult WineAddScriptRunner(nsIRunnable *aRunnable);
 }
 
index a3dfded..fb90b46 100644 (file)
@@ -119,7 +119,7 @@ static BOOL init_script_engine(ScriptHost *script_host)
         WARN("Could not get IActiveScriptProperty: %08x\n", hres);
     }
 
-    hres = IActiveScriptParse_InitNew(script_host->parse);
+    hres = IActiveScriptParse64_InitNew(script_host->parse);
     if(FAILED(hres)) {
         WARN("InitNew failed: %08x\n", hres);
         return FALSE;
@@ -175,12 +175,12 @@ static void release_script_engine(ScriptHost *This)
 
     default:
         if(This->parse_proc) {
-            IActiveScriptParseProcedure_Release(This->parse_proc);
+            IUnknown_Release(This->parse_proc);
             This->parse_proc = NULL;
         }
 
         if(This->parse) {
-            IActiveScriptParse_Release(This->parse);
+            IUnknown_Release(This->parse);
             This->parse = NULL;
         }
     }
@@ -552,7 +552,7 @@ static void parse_text(ScriptHost *script_host, LPCWSTR text)
 
     VariantInit(&var);
     memset(&excepinfo, 0, sizeof(excepinfo));
-    hres = IActiveScriptParse_ParseScriptText(script_host->parse, text, windowW, NULL, script_endW,
+    hres = IActiveScriptParse64_ParseScriptText(script_host->parse, text, windowW, NULL, script_endW,
                                               0, 0, SCRIPTTEXT_ISVISIBLE|SCRIPTTEXT_HOSTMANAGESSOURCE,
                                               &var, &excepinfo);
     if(FAILED(hres))
@@ -640,7 +640,7 @@ static BOOL get_guid_from_type(LPCWSTR type, GUID *guid)
         {'t','e','x','t','/','j','a','v','a','s','c','r','i','p','t',0};
 
     /* FIXME: Handle more types */
-    if(!strcmpW(type, text_javascriptW)) {
+    if(!strcmpiW(type, text_javascriptW)) {
         *guid = CLSID_JScript;
     }else {
         FIXME("Unknown type %s\n", debugstr_w(type));
@@ -783,7 +783,7 @@ IDispatch *script_parse_event(HTMLDocument *doc, LPCWSTR text)
     if(!script_host || !script_host->parse_proc)
         return NULL;
 
-    hres = IActiveScriptParseProcedure_ParseProcedureText(script_host->parse_proc, ptr, NULL, emptyW,
+    hres = IActiveScriptParseProcedure64_ParseProcedureText(script_host->parse_proc, ptr, NULL, emptyW,
             NULL, NULL, delimiterW, 0 /* FIXME */, 0,
             SCRIPTPROC_HOSTMANAGESSOURCE|SCRIPTPROC_IMPLICIT_THIS|SCRIPTPROC_IMPLICIT_PARENTS, &disp);
     if(FAILED(hres)) {
index 198ff2a..9b7168f 100644 (file)
@@ -718,6 +718,11 @@ static HRESULT WINAPI OleControl_OnAmbientPropertyChange(IOleControl *iface, DIS
     TRACE("(%p)->(%d)\n", This, dispID);
 
     switch(dispID) {
+    case DISPID_UNKNOWN:
+        /* Unknown means multiple properties changed, so check them all.
+         * BUT the Webbrowser OleControl object doesn't appear to do this.
+         */
+        return S_OK;
     case DISPID_AMBIENT_OFFLINEIFNOTCONNECTED:
         return on_offlineconnected_change(This);
     case DISPID_AMBIENT_SILENT:
index b41ae09..c046ad3 100644 (file)
@@ -333,6 +333,85 @@ interface IDebugApplication32 : IRemoteDebugApplication
             [in]  DWORD dwCookie);
 }
 
+/************************************************************
+ *      interface IDebugApplication64
+ */
+[
+    object,
+    uuid(4dedc754-04c7-4f10-9e60-16a390fe6e62),
+    pointer_default(unique),
+    local
+]
+interface IDebugApplication64 : IRemoteDebugApplication
+{
+    HRESULT SetName(
+            [in] LPCOLESTR pstrName);
+
+    HRESULT StepOutComplete();
+
+    HRESULT DebugOutput(
+            [in] LPCOLESTR pstr);
+
+    HRESULT StartDebugSession();
+
+    HRESULT HandleBreakPoint(
+            [in]  BREAKREASON br,
+            [out] BREAKRESUMEACTION *pbra);
+
+    HRESULT Close();
+
+    HRESULT GetBreakFlags(
+            [out] APPBREAKFLAGS *pabf,
+            [out] IRemoteDebugApplicationThread **pprdatSteppingThread);
+
+    HRESULT GetCurrentThread(
+            [out] IDebugApplicationThread **pat);
+
+    HRESULT CreateAsyncDebugOperation(
+            [in]  IDebugSyncOperation *psdo,
+            [out] IDebugAsyncOperation **ppado);
+
+    HRESULT AddStackFrameSniffer(
+            [in]  IDebugStackFrameSniffer *pdsfs,
+            [out] DWORD *pdwCookie);
+
+    HRESULT RemoveStackFrameSniffer(
+            [in]  DWORD dwCookie);
+
+    HRESULT QueryCurrentThreadIsDebuggerThread();
+
+    HRESULT SynchronousCallInDebuggerThread(
+            [in]  IDebugThreadCall32 *pptc,
+            [in]  DWORDLONG dwParam1,
+            [in]  DWORDLONG dwParam2,
+            [in]  DWORDLONG dwParam3);
+
+    HRESULT CreateApplicationNode(
+            [out] IDebugApplicationNode **ppdanNew);
+
+    HRESULT FireDebuggerEvent(
+            [in]  REFGUID riid,
+            [in]  IUnknown *punk);
+
+    HRESULT HandleRuntimeError(
+            [in]  IActiveScriptErrorDebug *pErrorDebug,
+            [in]  IActiveScriptSite *pScriptSite,
+            [out] BREAKRESUMEACTION *pbra,
+            [out] ERRORRESUMEACTION *perra,
+            [out] BOOL *pfCallOnScriptError);
+
+    BOOL FCanJitDebug();
+
+    BOOL FIsAutoJitDebugEnabled();
+
+    HRESULT AddGlobalExpressionContextProvider(
+            [in]  IProvideExpressionContexts *pdsfs,
+            [out] DWORDLONG *pdwCookie);
+
+    HRESULT RemoveGlobalExpressionContextProvider(
+            [in]  DWORDLONG dwCookie);
+}
+
 /************************************************************
  *      interface IActiveScriptSiteDebug32
  */
@@ -362,6 +441,35 @@ interface IActiveScriptSiteDebug32 : IUnknown
             [out] BOOL *pfCallOnScriptErrorWhenContinuing);
 }
 
+/************************************************************
+ *      interface IActiveScriptSiteDebug64
+ */
+[
+    object,
+    uuid(d6b96b0a-7463-402c-92ac-89984226942f),
+    pointer_default(unique),
+    local
+]
+interface IActiveScriptSiteDebug64 : IUnknown
+{
+    HRESULT GetDocumentContextFromPosition(
+            [in]  DWORDLONG dwSourceContext,
+            [in]  ULONG uCharacterOffset,
+            [in]  ULONG uNumChars,
+            [out] IDebugDocumentContext **ppsc);
+
+    HRESULT GetApplication(
+            [out] IDebugApplication64 **ppda);
+
+    HRESULT GetRootApplicationNode(
+            [out] IDebugApplicationNode **ppdanRoot);
+
+    HRESULT OnScriptErrorDebug(
+            [in]  IActiveScriptErrorDebug *pErrorDebug,
+            [out] BOOL *pfEnterDebugger,
+            [out] BOOL *pfCallOnScriptErrorWhenContinuing);
+}
+
 cpp_quote("#ifndef DISABLE_ACTIVDBG_INTERFACE_WRAPPERS")
 cpp_quote("#ifdef _WIN64")
 
index 6775f8a..e75fbec 100644 (file)
@@ -268,7 +268,7 @@ object,
 uuid(BB1A2AE2-A4F9-11cf-8F20-00805F2CD064),
 pointer_default(unique)
 ]
-interface IActiveScriptParse : IUnknown
+interface IActiveScriptParse32 : IUnknown
 {
     HRESULT InitNew(void);
 
@@ -299,6 +299,50 @@ interface IActiveScriptParse : IUnknown
     );
 }
 
+[
+   object,
+   uuid(c7ef7658-e1ee-480e-97ea-d52cb4d76d17),
+   pointer_default(unique)
+]
+interface IActiveScriptParse64 : IUnknown
+{
+    HRESULT InitNew(void);
+
+    HRESULT AddScriptlet(
+            [in] LPCOLESTR pstrDefaultName,
+            [in] LPCOLESTR pstrCode,
+            [in] LPCOLESTR pstrItemName,
+            [in] LPCOLESTR pstrSubItemName,
+            [in] LPCOLESTR pstrEventName,
+            [in] LPCOLESTR pstrDelimiter,
+            [in] DWORDLONG dwSourceContextCookie,
+            [in] ULONG ulStartingLineNumber,
+            [in] DWORD dwFlags,
+            [out] BSTR *pbstrName,
+            [out] EXCEPINFO *pexcepinfo
+    );
+
+    HRESULT ParseScriptText(
+            [in] LPCOLESTR pstrCode,
+            [in] LPCOLESTR pstrItemName,
+            [in] IUnknown *punkContext,
+            [in] LPCOLESTR pstrDelimiter,
+            [in] DWORDLONG dwSourceContextCookie,
+            [in] ULONG ulStartingLineNumber,
+            [in] DWORD dwFlags,
+            [out] VARIANT *pvarResult,
+            [out] EXCEPINFO *pexcepinfo
+    );
+}
+
+cpp_quote("#ifdef _WIN64")
+cpp_quote("#define IActiveScriptParse IActiveScriptParse64")
+cpp_quote("#define IID_IActiveScriptParse IID_IActiveScriptParse64")
+cpp_quote("#else")
+cpp_quote("#define IActiveScriptParse IActiveScriptParse32")
+cpp_quote("#define IID_IActiveScriptParse IID_IActiveScriptParse32")
+cpp_quote("#endif")
+
 cpp_quote("typedef IActiveScriptParse *PIActiveScriptParse;")
 
 [
@@ -306,7 +350,7 @@ object,
 uuid(1CFF0050-6FDD-11d0-9328-00A0C90DCAA9),
 pointer_default(unique)
 ]
-interface IActiveScriptParseProcedureOld : IUnknown
+interface IActiveScriptParseProcedureOld32 : IUnknown
 {
     HRESULT ParseProcedureText(
             [in] LPCOLESTR pstrCode,
@@ -321,12 +365,40 @@ interface IActiveScriptParseProcedureOld : IUnknown
     );
 }
 
+[
+    object,
+    uuid(21f57128-08c9-4638-ba12-22d15d88dc5c),
+    pointer_default(unique)
+]
+interface IActiveScriptParseProcedureOld64 : IUnknown
+{
+    HRESULT ParseProcedureText(
+            [in] LPCOLESTR pstrCode,
+            [in] LPCOLESTR pstrFormalParams,
+            [in] LPCOLESTR pstrItemName,
+            [in] IUnknown *punkContext,
+            [in] LPCOLESTR pstrDelimiter,
+            [in] DWORDLONG dwSourceContextCookie,
+            [in] ULONG ulStartingLineNumber,
+            [in] DWORD dwFlags,
+            [out] IDispatch **ppdisp
+    );
+}
+
+cpp_quote("#ifdef _WIN64")
+cpp_quote("#define IActiveScriptParseProcedureOld IActiveScriptParseProcedureOld64")
+cpp_quote("#define IID_IActiveScriptParseProcedureOld IID_IActiveScriptParseProcedureOld64")
+cpp_quote("#else")
+cpp_quote("#define IActiveScriptParseProcedureOld IActiveScriptParseProcedureOld32")
+cpp_quote("#define IID_IActiveScriptParseProcedureOld IID_IActiveScriptParseProcedureOld32")
+cpp_quote("#endif")
+
 [
 object,
 uuid(AA5B6A80-B834-11d0-932F-00A0C90DCAA9),
 pointer_default(unique)
 ]
-interface IActiveScriptParseProcedure : IUnknown
+interface IActiveScriptParseProcedure32 : IUnknown
 {
     HRESULT ParseProcedureText(
             [in] LPCOLESTR pstrCode,
@@ -342,15 +414,61 @@ interface IActiveScriptParseProcedure : IUnknown
     );
 }
 
+[
+    object,
+    uuid(c64713b6-e029-4cc5-9200-438b72890b6a),
+    pointer_default(unique)
+]
+interface IActiveScriptParseProcedure64 : IUnknown
+{
+    HRESULT ParseProcedureText(
+            [in] LPCOLESTR pstrCode,
+            [in] LPCOLESTR pstrFormalParams,
+            [in] LPCOLESTR pstrProcedureName,
+            [in] LPCOLESTR pstrItemName,
+            [in] IUnknown *punkContext,
+            [in] LPCOLESTR pstrDelimiter,
+            [in] DWORDLONG dwSourceContextCookie,
+            [in] ULONG ulStartingLineNumber,
+            [in] DWORD dwFlags,
+            [out] IDispatch **ppdisp
+    );
+}
+
+cpp_quote("#ifdef _WIN64")
+cpp_quote("#define IActiveScriptParseProcedure IActiveScriptParseProcedure64")
+cpp_quote("#define IID_IActiveScriptParseProcedure IID_IActiveScriptParseProcedure64")
+cpp_quote("#else")
+cpp_quote("#define IActiveScriptParseProcedure IActiveScriptParseProcedure32")
+cpp_quote("#define IID_IActiveScriptParseProcedure IID_IActiveScriptParseProcedure32")
+cpp_quote("#endif")
+
 [
     object,
     uuid(71ee5b20-fb04-11d1-b3a8-00a0c911e8b2),
     pointer_default(unique)
 ]
-interface IActiveScriptParseProcedure2 : IActiveScriptParseProcedure
+interface IActiveScriptParseProcedure2_32 : IActiveScriptParseProcedure32
+{
+}
+
+[
+    object,
+    uuid(fe7c4271-210c-448d-9f54-76dab7047b28),
+    pointer_default(unique)
+]
+interface IActiveScriptParseProcedure2_64 : IActiveScriptParseProcedure64
 {
 }
 
+cpp_quote("#ifdef _WIN64")
+cpp_quote("#define IActiveScriptParseProcedure2 IActiveScriptParseProcedure2_64")
+cpp_quote("#define IID_IActiveScriptParseProcedure2 IID_IActiveScriptParseProcedure2_64")
+cpp_quote("#else")
+cpp_quote("#define IActiveScriptParseProcedure2 IActiveScriptParseProcedure2_32")
+cpp_quote("#define IID_IActiveScriptParseProcedure2 IID_IActiveScriptParseProcedure2_32")
+cpp_quote("#endif")
+
 [
 object,
 uuid(63CDBCB0-C1B1-11d0-9336-00A0C90DCAA9),
index c8c8b27..75a7290 100644 (file)
 #define DISPID_SCRIPT           DISPID_NORMAL_FIRST
 #define DISPID_STYLESHEET       DISPID_NORMAL_FIRST
 #define DISPID_STYLERULE        DISPID_NORMAL_FIRST
+#define DISPID_STYLEPAGE        DISPID_NORMAL_FIRST
 #define DISPID_STYLESHEETS_COL  DISPID_NORMAL_FIRST
 #define DISPID_STYLERULES_COL   DISPID_NORMAL_FIRST
+#define DISPID_STYLEPAGES_COL   DISPID_NORMAL_FIRST
 #define DISPID_MIMETYPES_COL    DISPID_NORMAL_FIRST
 #define DISPID_PLUGINS_COL      DISPID_NORMAL_FIRST
 #define DISPID_2D               DISPID_NORMAL_FIRST
 #define DISPID_IHTMLSTYLESHEET_RULES              (DISPID_STYLESHEET+15)
 #define DISPID_IHTMLSTYLESHEET_DISABLED           STDPROPID_XOBJ_DISABLED
 
+/* IHTMLStyleSheet2 */
+#define DISPID_IHTMLSTYLESHEET2_PAGES             (DISPID_STYLESHEET+16)
+#define DISPID_IHTMLSTYLESHEET2_ADDPAGERULE       (DISPID_STYLESHEET+17)
+
 /* IHTMLStyleSheetRulesCollection */
 #define DISPID_IHTMLSTYLESHEETRULESCOLLECTION_LENGTH   (DISPID_STYLERULES_COL+1)
 #define DISPID_IHTMLSTYLESHEETRULESCOLLECTION_ITEM     DISPID_VALUE
 
+/* IHTMLStyleSheetPage */
+#define DISPID_IHTMLSTYLESHEETPAGE_SELECTOR       (DISPID_STYLEPAGE+1)
+#define DISPID_IHTMLSTYLESHEETPAGE_PSEUDOCLASS    (DISPID_STYLEPAGE+2)
+
+/* IHTMLStyleSheetPagesCollection */
+#define DISPID_IHTMLSTYLESHEETPAGESCOLLECTION_LENGTH      (DISPID_STYLEPAGES_COL+1)
+#define DISPID_IHTMLSTYLESHEETPAGESCOLLECTION_ITEM        DISPID_VALUE
+
 /* IHTMLStyleSheetRule */
 #define DISPID_IHTMLSTYLESHEETRULE_SELECTORTEXT   (DISPID_STYLERULE+1)
 #define DISPID_IHTMLSTYLESHEETRULE_READONLY       (DISPID_STYLERULE+2)
index 1e17857..929139a 100644 (file)
@@ -33,6 +33,10 @@ cpp_quote("DEFINE_GUID(SID_SHTMLEditServices,   0x3050f7f9,0x98b5,0x11cf,0xbb,0x
 cpp_quote("#define SID_SHTMLWindow IID_IHTMLWindow2")
 cpp_quote("#define SID_SElementBehaviorFactory IID_IElementBehaviorFactory")
 
+cpp_quote("#ifdef WINE_NO_UNICODE_MACROS")
+cpp_quote("#undef FindText")
+cpp_quote("#endif")
+
 typedef enum {
     POINTER_GRAVITY_Left,
     POINTER_GRAVITY_Right,
@@ -5393,6 +5397,38 @@ interface IHTMLStyleSheetRulesCollection : IDispatch
         [retval, out] IHTMLStyleSheetRule **ppHTMLStyleSheetRule);
 }
 
+[
+    odl,
+    oleautomation,
+    dual,
+    uuid(3050f7ee-98b5-11cf-bb82-00aa00bdce0b)
+]
+interface IHTMLStyleSheetPage : IDispatch
+{
+    [propget, id(DISPID_IHTMLSTYLESHEETPAGE_SELECTOR)]
+    HRESULT selector([retval, out] BSTR *p);
+
+    [propget, id(DISPID_IHTMLSTYLESHEETPAGE_PSEUDOCLASS)]
+    HRESULT pseudoClass([retval, out] BSTR *p);
+}
+
+[
+    odl,
+    oleautomation,
+    dual,
+    uuid(3050f7f0-98b5-11cf-bb82-00aa00bdce0b)
+]
+interface IHTMLStyleSheetPagesCollection : IDispatch
+{
+    [propget, id(DISPID_IHTMLSTYLESHEETPAGESCOLLECTION_LENGTH)]
+    HRESULT length([retval, out] long *p);
+
+    [id(DISPID_IHTMLSTYLESHEETPAGESCOLLECTION_ITEM)]
+    HRESULT item(
+        [in] long index,
+        [retval, out] IHTMLStyleSheetPage **ppHTMLStyleSheetPage);
+}
+
 /*****************************************************************************
  *    IHTMLStyleSheet interface
  */
@@ -5475,6 +5511,125 @@ interface IHTMLStyleSheet : IDispatch
     HRESULT rules([retval, out] IHTMLStyleSheetRulesCollection **p);
 }
 
+/*****************************************************************************
+ *    IHTMLStyleSheet2 interface
+ */
+[
+    odl,
+    oleautomation,
+    dual,
+    uuid(3050f3d1-98b5-11cf-bb82-00aa00bdce0b)
+]
+interface IHTMLStyleSheet2 : IDispatch
+{
+    [propget, id(DISPID_IHTMLSTYLESHEET2_PAGES)]
+    HRESULT pages([retval, out] IHTMLStyleSheetPagesCollection **p);
+
+    [id(DISPID_IHTMLSTYLESHEET2_ADDPAGERULE)]
+    HRESULT addPageRule(
+        [in] BSTR bstrSelector,
+        [in] BSTR bstrStyle,
+        [defaultvalue(-1), in] long lIndex,
+        [retval, out] long *plNewIndex);
+}
+
+[
+    hidden,
+    uuid(3050f58d-98b5-11cf-bb82-00aa00bdce0b)
+]
+dispinterface DispHTMLStyleSheet
+{
+properties:
+methods:
+    [propput, id(DISPID_IHTMLSTYLESHEET_TITLE)]
+    void title(BSTR v);
+
+    [propget, id(DISPID_IHTMLSTYLESHEET_TITLE)]
+    BSTR title();
+
+    [propget, id(DISPID_IHTMLSTYLESHEET_PARENTSTYLESHEET)]
+    IHTMLStyleSheet* parentStyleSheet();
+
+    [propget, id(DISPID_IHTMLSTYLESHEET_OWNINGELEMENT)]
+    IHTMLElement* owningElement();
+
+    [propput, id(DISPID_IHTMLSTYLESHEET_DISABLED)]
+    void disabled(VARIANT_BOOL v);
+
+    [propget, id(DISPID_IHTMLSTYLESHEET_DISABLED)]
+    VARIANT_BOOL disabled();
+
+    [propget, id(DISPID_IHTMLSTYLESHEET_READONLY)]
+    VARIANT_BOOL readOnly();
+
+    [propget, id(DISPID_IHTMLSTYLESHEET_IMPORTS)]
+    IHTMLStyleSheetsCollection* imports();
+
+    [propput, id(DISPID_IHTMLSTYLESHEET_HREF)]
+    void href(BSTR v);
+
+    [propget, id(DISPID_IHTMLSTYLESHEET_HREF)]
+    BSTR href();
+
+    [propget, id(DISPID_IHTMLSTYLESHEET_TYPE)]
+    BSTR type();
+
+    [propget, id(DISPID_IHTMLSTYLESHEET_ID)]
+    BSTR id();
+
+    [id(DISPID_IHTMLSTYLESHEET_ADDIMPORT)]
+    long addImport(
+        [in] BSTR bstrURL,
+        [defaultvalue(-1), in] long lIndex);
+
+    [id(DISPID_IHTMLSTYLESHEET_ADDRULE)]
+    long addRule(
+        [in] BSTR bstrSelector,
+        [in] BSTR bstrStyle,
+        [defaultvalue(-1), in] long lIndex);
+
+    [id(DISPID_IHTMLSTYLESHEET_REMOVEIMPORT)]
+    void removeImport([in] long lIndex);
+
+    [id(DISPID_IHTMLSTYLESHEET_REMOVERULE)]
+    void removeRule([in] long lIndex);
+
+    [propput, id(DISPID_IHTMLSTYLESHEET_MEDIA)]
+    void media(BSTR v);
+
+    [propget, id(DISPID_IHTMLSTYLESHEET_MEDIA)]
+    BSTR media();
+
+    [propput, id(DISPID_IHTMLSTYLESHEET_CSSTEXT)]
+    void cssText(BSTR v);
+
+    [propget, id(DISPID_IHTMLSTYLESHEET_CSSTEXT)]
+    BSTR cssText();
+
+    [propget, id(DISPID_IHTMLSTYLESHEET_RULES)]
+    IHTMLStyleSheetRulesCollection* rules();
+
+    [propget, id(DISPID_IHTMLSTYLESHEET2_PAGES)]
+    IHTMLStyleSheetPagesCollection* pages();
+
+    [id(DISPID_IHTMLSTYLESHEET2_ADDPAGERULE)]
+    long addPageRule(
+        [in] BSTR bstrSelector,
+        [in] BSTR bstrStyle,
+        [defaultvalue(-1), in] long lIndex);
+}
+
+[
+    noncreatable,
+    uuid(3050f2e4-98b5-11cf-bb82-00aa00bdce0b)
+]
+coclass HTMLStyleSheet
+{
+    [default]           dispinterface DispHTMLStyleSheet;
+                        interface IHTMLStyleSheet;
+                        interface IHTMLStyleSheet2;
+}
+
 /*****************************************************************************
  *    IHTMLStyleSheetsCollection interface
  */
@@ -5646,6 +5801,15 @@ interface IHTMLTxtRange : IDispatch
         [retval, out] VARIANT_BOOL *pfRet);
 }
 
+[
+    noncreatable,
+    uuid(3050f37f-98b5-11cf-bb82-00aa00bdce0b)
+]
+coclass HTMLStyleSheetsCollection
+{
+    [default]           interface IHTMLStyleSheetsCollection;
+}
+
 /*****************************************************************************
  *    IHTMLFormElement interface
  */
@@ -12622,6 +12786,15 @@ interface IOmHistory : IDispatch
     HRESULT go([optional, in] VARIANT *pvargdistance);
 }
 
+[
+    noncreatable,
+    uuid(FECEAAA3-8405-11cf-8BA1-00AA00476DA6)
+]
+coclass HTMLHistory
+{
+    [default]           interface IOmHistory;
+}
+
 /*****************************************************************************
  *    IHTMLMimeTypesCollection interface
  */
@@ -12637,6 +12810,15 @@ interface IHTMLMimeTypesCollection : IDispatch
     HRESULT length([retval, out] long *p);
 }
 
+[
+    noncreatable,
+    uuid(3050f3fe-98b5-11cf-bb82-00aa00bdce0b)
+]
+coclass CMimeTypes
+{
+    [default]           interface IHTMLMimeTypesCollection;
+}
+
 /*****************************************************************************
  *    IHTMLPluginsCollection interface
  */
@@ -12655,6 +12837,15 @@ interface IHTMLPluginsCollection : IDispatch
     HRESULT refresh([defaultvalue(0), in] VARIANT_BOOL reload);
 }
 
+[
+    noncreatable,
+    uuid(3050f3ff-98b5-11cf-bb82-00aa00bdce0b)
+]
+coclass CPlugins
+{
+    [default]           interface IHTMLPluginsCollection;
+}
+
 /*****************************************************************************
  *    IHTMLOpsProfile interface
  */
@@ -12718,6 +12909,15 @@ interface IHTMLOpsProfile : IDispatch
     HRESULT doWriteRequest([retval, out] VARIANT_BOOL *success);
 }
 
+[
+    noncreatable,
+    uuid(3050f402-98b5-11cf-bb82-00aa00bdce0b)
+]
+coclass COpsProfile
+{
+    [default]           interface IHTMLOpsProfile;
+}
+
 /*****************************************************************************
  *    IOmNavigator interface
  */
@@ -12790,6 +12990,15 @@ interface IOmNavigator : IDispatch
     HRESULT userProfile([retval, out] IHTMLOpsProfile **p);
 }
 
+[
+    noncreatable,
+    uuid(FECEAAA6-8405-11cf-8BA1-00AA00476DA6)
+]
+coclass HTMLNavigator
+{
+    [default]           interface IOmNavigator;
+}
+
 /*****************************************************************************
  *    IHTMLLocation interface
  */
@@ -12862,6 +13071,15 @@ interface IHTMLLocation : IDispatch
     HRESULT toString([retval, out] BSTR *String);
 }
 
+[
+    noncreatable,
+    uuid(163BB1E1-6E00-11cf-837A-48DC04C10000)
+]
+coclass HTMLLocation
+{
+    [default]           interface IHTMLLocation;
+}
+
 [
     odl,
     oleautomation,