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