Jacek Caban : jscript: Added Array.join implementation.

Alexandre Julliard julliard at winehq.org
Mon Sep 22 07:04:00 CDT 2008


Module: wine
Branch: master
Commit: f62dd2a9fdc2a768205f93177285e89173caa093
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=f62dd2a9fdc2a768205f93177285e89173caa093

Author: Jacek Caban <jacek at codeweavers.com>
Date:   Sun Sep 21 15:36:26 2008 +0200

jscript: Added Array.join implementation.

---

 dlls/jscript/array.c      |  130 +++++++++++++++++++++++++++++++++++++++++++-
 dlls/jscript/dispex.c     |   28 ++++++++++
 dlls/jscript/jscript.h    |    6 ++
 dlls/jscript/tests/api.js |   11 ++++
 4 files changed, 172 insertions(+), 3 deletions(-)

diff --git a/dlls/jscript/array.c b/dlls/jscript/array.c
index 18ee3f5..944c0e8 100644
--- a/dlls/jscript/array.c
+++ b/dlls/jscript/array.c
@@ -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};
 
+const WCHAR default_separatorW[] = {',',0};
 
 static HRESULT Array_length(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
         VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
@@ -75,11 +76,134 @@ static HRESULT Array_concat(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAM
     return E_NOTIMPL;
 }
 
+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,
diff --git a/dlls/jscript/dispex.c b/dlls/jscript/dispex.c
index 1c643f6..7f7dd8c 100644
--- a/dlls/jscript/dispex.c
+++ b/dlls/jscript/dispex.c
@@ -931,6 +931,34 @@ HRESULT disp_propput(IDispatch *disp, DISPID id, LCID lcid, VARIANT *val, jsexce
     return hres;
 }
 
+static 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 disp_propget(IDispatch *disp, DISPID id, LCID lcid, VARIANT *val, jsexcept_t *ei, IServiceProvider *caller)
 {
     DISPPARAMS dp  = {NULL,NULL,0,0};
diff --git a/dlls/jscript/jscript.h b/dlls/jscript/jscript.h
index 6c4e272..1857459 100644
--- a/dlls/jscript/jscript.h
+++ b/dlls/jscript/jscript.h
@@ -126,6 +126,7 @@ HRESULT disp_propget(IDispatch*,DISPID,LCID,VARIANT*,jsexcept_t*,IServiceProvide
 HRESULT disp_propput(IDispatch*,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_idx(DispatchEx*,DWORD,LCID,VARIANT*,jsexcept_t*,IServiceProvider*);
 
 HRESULT create_builtin_function(script_ctx_t*,builtin_invoke_t,DWORD,DispatchEx*,DispatchEx**);
 
@@ -208,6 +209,11 @@ 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 void num_set_val(VARIANT *v, DOUBLE d)
 {
     if(d == (DOUBLE)(INT)d) {
diff --git a/dlls/jscript/tests/api.js b/dlls/jscript/tests/api.js
index c76a485..f331670 100644
--- a/dlls/jscript/tests/api.js
+++ b/dlls/jscript/tests/api.js
@@ -68,4 +68,15 @@ ok(arr.push(true, 'b', false) === 10, "arr.push(true, 'b', false) !== 10");
 ok(arr[8] === "b", "arr[8] != 'b'");
 ok(arr.length === 10, "arr.length != 10");
 
+arr = [1,2,null,false,undefined,,"a"];
+
+tmp = arr.join();
+ok(tmp === "1,2,,false,,,a", "arr.join() = " + tmp);
+tmp = arr.join(";");
+ok(tmp === "1;2;;false;;;a", "arr.join(';') = " + tmp);
+tmp = arr.join(";","test");
+ok(tmp === "1;2;;false;;;a", "arr.join(';') = " + tmp);
+tmp = arr.join("");
+ok(tmp === "12falsea", "arr.join('') = " + tmp);
+
 reportSuccess();




More information about the wine-cvs mailing list