2 * Copyright 2010 Piotr Caban for CodeWeavers
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #include "wine/debug.h"
23 WINE_DEFAULT_DEBUG_CHANNEL(jscript
);
31 static const WCHAR dimensionsW
[] = {'d','i','m','e','n','s','i','o','n','s',0};
32 static const WCHAR getItemW
[] = {'g','e','t','I','t','e','m',0};
33 static const WCHAR lboundW
[] = {'l','b','o','u','n','d',0};
34 static const WCHAR toArrayW
[] = {'t','o','A','r','r','a','y',0};
35 static const WCHAR uboundW
[] = {'u','b','o','u','n','d',0};
37 static inline VBArrayInstance
*vbarray_from_jsdisp(jsdisp_t
*jsdisp
)
39 return CONTAINING_RECORD(jsdisp
, VBArrayInstance
, dispex
);
42 static inline VBArrayInstance
*vbarray_from_vdisp(vdisp_t
*vdisp
)
44 return vbarray_from_jsdisp(vdisp
->u
.jsdisp
);
47 static inline VBArrayInstance
*vbarray_this(vdisp_t
*jsthis
)
49 return is_vclass(jsthis
, JSCLASS_VBARRAY
) ? vbarray_from_vdisp(jsthis
) : NULL
;
52 static HRESULT
VBArray_dimensions(script_ctx_t
*ctx
, vdisp_t
*vthis
, WORD flags
, unsigned argc
, jsval_t
*argv
,
55 VBArrayInstance
*vbarray
;
59 vbarray
= vbarray_this(vthis
);
61 return throw_type_error(ctx
, JS_E_VBARRAY_EXPECTED
, NULL
);
64 *r
= jsval_number(SafeArrayGetDim(vbarray
->safearray
));
68 static HRESULT
VBArray_getItem(script_ctx_t
*ctx
, vdisp_t
*vthis
, WORD flags
, unsigned argc
, jsval_t
*argv
,
71 VBArrayInstance
*vbarray
;
78 vbarray
= vbarray_this(vthis
);
80 return throw_type_error(ctx
, JS_E_VBARRAY_EXPECTED
, NULL
);
82 if(argc
< SafeArrayGetDim(vbarray
->safearray
))
83 return throw_range_error(ctx
, JS_E_SUBSCRIPT_OUT_OF_RANGE
, NULL
);
85 indexes
= heap_alloc(sizeof(int)*argc
);
89 for(i
=0; i
<argc
; i
++) {
90 hres
= to_int32(ctx
, argv
[i
], indexes
+i
);
97 hres
= SafeArrayGetElement(vbarray
->safearray
, indexes
, (void*)&out
);
99 if(hres
== DISP_E_BADINDEX
)
100 return throw_range_error(ctx
, JS_E_SUBSCRIPT_OUT_OF_RANGE
, NULL
);
101 else if(FAILED(hres
))
105 hres
= variant_to_jsval(&out
, r
);
111 static HRESULT
VBArray_lbound(script_ctx_t
*ctx
, vdisp_t
*vthis
, WORD flags
, unsigned argc
, jsval_t
*argv
,
114 VBArrayInstance
*vbarray
;
120 vbarray
= vbarray_this(vthis
);
122 return throw_type_error(ctx
, JS_E_VBARRAY_EXPECTED
, NULL
);
125 hres
= to_int32(ctx
, argv
[0], &dim
);
131 hres
= SafeArrayGetLBound(vbarray
->safearray
, dim
, &dim
);
132 if(hres
== DISP_E_BADINDEX
)
133 return throw_range_error(ctx
, JS_E_SUBSCRIPT_OUT_OF_RANGE
, NULL
);
134 else if(FAILED(hres
))
138 *r
= jsval_number(dim
);
142 static HRESULT
VBArray_toArray(script_ctx_t
*ctx
, vdisp_t
*vthis
, WORD flags
, unsigned argc
, jsval_t
*argv
,
145 VBArrayInstance
*vbarray
;
149 int i
, size
= 1, ubound
, lbound
;
154 vbarray
= vbarray_this(vthis
);
156 return throw_type_error(ctx
, JS_E_VBARRAY_EXPECTED
, NULL
);
158 for(i
=1; i
<=SafeArrayGetDim(vbarray
->safearray
); i
++) {
159 SafeArrayGetLBound(vbarray
->safearray
, i
, &lbound
);
160 SafeArrayGetUBound(vbarray
->safearray
, i
, &ubound
);
161 size
*= ubound
-lbound
+1;
164 hres
= SafeArrayAccessData(vbarray
->safearray
, (void**)&v
);
168 hres
= create_array(ctx
, 0, &array
);
170 SafeArrayUnaccessData(vbarray
->safearray
);
174 for(i
=0; i
<size
; i
++) {
175 hres
= variant_to_jsval(v
, &val
);
176 if(SUCCEEDED(hres
)) {
177 hres
= jsdisp_propput_idx(array
, i
, val
);
181 SafeArrayUnaccessData(vbarray
->safearray
);
182 jsdisp_release(array
);
188 SafeArrayUnaccessData(vbarray
->safearray
);
191 *r
= jsval_obj(array
);
193 jsdisp_release(array
);
197 static HRESULT
VBArray_ubound(script_ctx_t
*ctx
, vdisp_t
*vthis
, WORD flags
, unsigned argc
, jsval_t
*argv
,
200 VBArrayInstance
*vbarray
;
206 vbarray
= vbarray_this(vthis
);
208 return throw_type_error(ctx
, JS_E_VBARRAY_EXPECTED
, NULL
);
211 hres
= to_int32(ctx
, argv
[0], &dim
);
217 hres
= SafeArrayGetUBound(vbarray
->safearray
, dim
, &dim
);
218 if(hres
== DISP_E_BADINDEX
)
219 return throw_range_error(ctx
, JS_E_SUBSCRIPT_OUT_OF_RANGE
, NULL
);
220 else if(FAILED(hres
))
224 *r
= jsval_number(dim
);
228 static HRESULT
VBArray_value(script_ctx_t
*ctx
, vdisp_t
*jsthis
, WORD flags
, unsigned argc
, jsval_t
*argv
,
235 FIXME("unimplemented flags %x\n", flags
);
242 static void VBArray_destructor(jsdisp_t
*dispex
)
244 VBArrayInstance
*vbarray
= vbarray_from_jsdisp(dispex
);
246 SafeArrayDestroy(vbarray
->safearray
);
250 static const builtin_prop_t VBArray_props
[] = {
251 {dimensionsW
, VBArray_dimensions
, PROPF_METHOD
},
252 {getItemW
, VBArray_getItem
, PROPF_METHOD
|1},
253 {lboundW
, VBArray_lbound
, PROPF_METHOD
},
254 {toArrayW
, VBArray_toArray
, PROPF_METHOD
},
255 {uboundW
, VBArray_ubound
, PROPF_METHOD
}
258 static const builtin_info_t VBArray_info
= {
260 {NULL
, VBArray_value
, 0},
261 sizeof(VBArray_props
)/sizeof(*VBArray_props
),
267 static HRESULT
alloc_vbarray(script_ctx_t
*ctx
, jsdisp_t
*object_prototype
, VBArrayInstance
**ret
)
269 VBArrayInstance
*vbarray
;
272 vbarray
= heap_alloc_zero(sizeof(VBArrayInstance
));
274 return E_OUTOFMEMORY
;
277 hres
= init_dispex(&vbarray
->dispex
, ctx
, &VBArray_info
, object_prototype
);
279 hres
= init_dispex_from_constr(&vbarray
->dispex
, ctx
, &VBArray_info
, ctx
->vbarray_constr
);
290 static HRESULT
VBArrayConstr_value(script_ctx_t
*ctx
, vdisp_t
*vthis
, WORD flags
, unsigned argc
, jsval_t
*argv
,
293 VBArrayInstance
*vbarray
;
299 case DISPATCH_METHOD
:
300 if(argc
<1 || !is_variant(argv
[0]) || V_VT(get_variant(argv
[0])) != (VT_ARRAY
|VT_VARIANT
))
301 return throw_type_error(ctx
, JS_E_VBARRAY_EXPECTED
, NULL
);
303 return jsval_copy(argv
[0], r
);
305 case DISPATCH_CONSTRUCT
:
306 if(argc
<1 || !is_variant(argv
[0]) || V_VT(get_variant(argv
[0])) != (VT_ARRAY
|VT_VARIANT
))
307 return throw_type_error(ctx
, JS_E_VBARRAY_EXPECTED
, NULL
);
309 hres
= alloc_vbarray(ctx
, NULL
, &vbarray
);
313 hres
= SafeArrayCopy(V_ARRAY(get_variant(argv
[0])), &vbarray
->safearray
);
315 jsdisp_release(&vbarray
->dispex
);
319 *r
= jsval_obj(&vbarray
->dispex
);
323 FIXME("unimplemented flags: %x\n", flags
);
330 HRESULT
create_vbarray_constr(script_ctx_t
*ctx
, jsdisp_t
*object_prototype
, jsdisp_t
**ret
)
332 VBArrayInstance
*vbarray
;
335 static const WCHAR VBArrayW
[] = {'V','B','A','r','r','a','y',0};
337 hres
= alloc_vbarray(ctx
, object_prototype
, &vbarray
);
341 hres
= create_builtin_constructor(ctx
, VBArrayConstr_value
, VBArrayW
, NULL
, PROPF_CONSTR
|1, &vbarray
->dispex
, ret
);
343 jsdisp_release(&vbarray
->dispex
);
347 HRESULT
create_vbarray(script_ctx_t
*ctx
, SAFEARRAY
*sa
, jsdisp_t
**ret
)
349 VBArrayInstance
*vbarray
;
352 hres
= alloc_vbarray(ctx
, NULL
, &vbarray
);
356 hres
= SafeArrayCopy(sa
, &vbarray
->safearray
);
358 jsdisp_release(&vbarray
->dispex
);
362 *ret
= &vbarray
->dispex
;