2 * Copyright 2019 Andreas Maier
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
23 #include "wine/debug.h"
25 WINE_DEFAULT_DEBUG_CHANNEL(jscript
);
29 /* IEnumVARIANT returned by _NewEnum */
30 IEnumVARIANT
*enumvar
;
36 static const WCHAR atEndW
[] = {'a','t','E','n','d',0};
37 static const WCHAR itemW
[] = {'i','t','e','m',0};
38 static const WCHAR moveFirstW
[] = {'m','o','v','e','F','i','r','s','t',0};
39 static const WCHAR moveNextW
[] = {'m','o','v','e','N','e','x','t',0};
41 static inline EnumeratorInstance
*enumerator_from_jsdisp(jsdisp_t
*jsdisp
)
43 return CONTAINING_RECORD(jsdisp
, EnumeratorInstance
, dispex
);
46 static inline EnumeratorInstance
*enumerator_from_vdisp(vdisp_t
*vdisp
)
48 return enumerator_from_jsdisp(vdisp
->u
.jsdisp
);
51 static inline EnumeratorInstance
*enumerator_this(vdisp_t
*jsthis
)
53 return is_vclass(jsthis
, JSCLASS_ENUMERATOR
) ? enumerator_from_vdisp(jsthis
) : NULL
;
56 static inline HRESULT
enumvar_get_next_item(EnumeratorInstance
*This
)
64 /* don't leak previous value */
65 jsval_release(This
->item
);
67 /* not at end ... get next item */
68 VariantInit(&nextitem
);
69 hres
= IEnumVARIANT_Next(This
->enumvar
, 1, &nextitem
, NULL
);
72 hres
= variant_to_jsval(&nextitem
, &This
->item
);
73 VariantClear(&nextitem
);
76 WARN("failed to convert jsval to variant!\n");
77 This
->item
= jsval_undefined();
83 This
->item
= jsval_undefined();
90 static void Enumerator_destructor(jsdisp_t
*dispex
)
92 EnumeratorInstance
*This
= enumerator_from_jsdisp(dispex
);
96 jsval_release(This
->item
);
100 static HRESULT
Enumerator_atEnd(script_ctx_t
*ctx
, vdisp_t
*jsthis
, WORD flags
, unsigned argc
, jsval_t
*argv
,
103 EnumeratorInstance
*This
;
105 if (!(This
= enumerator_this(jsthis
)))
106 return JS_E_ENUMERATOR_EXPECTED
;
108 TRACE("%d\n", This
->atend
);
111 *r
= jsval_bool(This
->atend
);
115 static HRESULT
Enumerator_item(script_ctx_t
*ctx
, vdisp_t
*jsthis
, WORD flags
, unsigned argc
, jsval_t
*argv
,
118 EnumeratorInstance
*This
;
122 if (!(This
= enumerator_this(jsthis
)))
123 return JS_E_ENUMERATOR_EXPECTED
;
125 return r
? jsval_copy(This
->item
, r
) : S_OK
;
128 static HRESULT
Enumerator_moveFirst(script_ctx_t
*ctx
, vdisp_t
*jsthis
, WORD flags
, unsigned argc
, jsval_t
*argv
,
131 EnumeratorInstance
*This
;
136 if (!(This
= enumerator_this(jsthis
)))
137 return JS_E_ENUMERATOR_EXPECTED
;
141 hres
= IEnumVARIANT_Reset(This
->enumvar
);
146 hres
= enumvar_get_next_item(This
);
152 *r
= jsval_undefined();
156 static HRESULT
Enumerator_moveNext(script_ctx_t
*ctx
, vdisp_t
*jsthis
, WORD flags
, unsigned argc
, jsval_t
*argv
,
159 EnumeratorInstance
*This
;
164 if (!(This
= enumerator_this(jsthis
)))
165 return JS_E_ENUMERATOR_EXPECTED
;
169 hres
= enumvar_get_next_item(This
);
175 *r
= jsval_undefined();
179 static const builtin_prop_t Enumerator_props
[] = {
180 {atEndW
, Enumerator_atEnd
, PROPF_METHOD
},
181 {itemW
, Enumerator_item
, PROPF_METHOD
},
182 {moveFirstW
, Enumerator_moveFirst
, PROPF_METHOD
},
183 {moveNextW
, Enumerator_moveNext
, PROPF_METHOD
},
186 static const builtin_info_t Enumerator_info
= {
189 ARRAY_SIZE(Enumerator_props
),
195 static const builtin_info_t EnumeratorInst_info
= {
197 {NULL
, NULL
, 0, NULL
},
200 Enumerator_destructor
,
204 static HRESULT
alloc_enumerator(script_ctx_t
*ctx
, jsdisp_t
*object_prototype
, EnumeratorInstance
**ret
)
206 EnumeratorInstance
*enumerator
;
209 enumerator
= heap_alloc_zero(sizeof(EnumeratorInstance
));
211 return E_OUTOFMEMORY
;
214 hres
= init_dispex(&enumerator
->dispex
, ctx
, &Enumerator_info
, object_prototype
);
216 hres
= init_dispex_from_constr(&enumerator
->dispex
, ctx
, &EnumeratorInst_info
,
217 ctx
->enumerator_constr
);
221 heap_free(enumerator
);
229 static HRESULT
create_enumerator(script_ctx_t
*ctx
, jsval_t
*argv
, jsdisp_t
**ret
)
231 EnumeratorInstance
*enumerator
;
234 DISPPARAMS dispparams
= {NULL
, NULL
, 0, 0};
235 IEnumVARIANT
*enumvar
= NULL
;
241 if (!is_object_instance(*argv
))
243 FIXME("I don't know how to handle this type!\n");
247 obj
= get_object(*argv
);
249 /* Try to get a IEnumVARIANT by _NewEnum */
250 VariantInit(&varresult
);
251 hres
= IDispatch_Invoke(obj
, DISPID_NEWENUM
, &IID_NULL
, LOCALE_NEUTRAL
,
252 DISPATCH_METHOD
, &dispparams
, &varresult
, NULL
, NULL
);
255 WARN("Enumerator: no DISPID_NEWENUM.\n");
259 if ((V_VT(&varresult
) == VT_DISPATCH
) || (V_VT(&varresult
) == VT_UNKNOWN
))
261 hres
= IUnknown_QueryInterface(V_UNKNOWN(&varresult
),
262 &IID_IEnumVARIANT
, (void**)&enumvar
);
266 FIXME("Enumerator: NewEnum unexpected type of varresult (%d).\n", V_VT(&varresult
));
269 VariantClear(&varresult
);
274 hres
= alloc_enumerator(ctx
, NULL
, &enumerator
);
278 IEnumVARIANT_Release(enumvar
);
282 enumerator
->enumvar
= enumvar
;
283 enumerator
->atend
= !enumvar
;
284 hres
= enumvar_get_next_item(enumerator
);
287 jsdisp_release(&enumerator
->dispex
);
291 *ret
= &enumerator
->dispex
;
295 static HRESULT
EnumeratorConstr_value(script_ctx_t
*ctx
, vdisp_t
*vthis
, WORD flags
, unsigned argc
, jsval_t
*argv
,
304 case DISPATCH_CONSTRUCT
: {
306 return JS_E_INVALIDARG
;
308 hres
= create_enumerator(ctx
, (argc
== 1) ? &argv
[0] : 0, &obj
);
316 FIXME("unimplemented flags: %x\n", flags
);
323 static const builtin_info_t EnumeratorConstr_info
= {
325 DEFAULT_FUNCTION_VALUE
,
332 HRESULT
create_enumerator_constr(script_ctx_t
*ctx
, jsdisp_t
*object_prototype
, jsdisp_t
**ret
)
334 EnumeratorInstance
*enumerator
;
336 static const WCHAR EnumeratorW
[] = {'E','n','u','m','e','r','a','t','o','r',0};
338 hres
= alloc_enumerator(ctx
, object_prototype
, &enumerator
);
342 hres
= create_builtin_constructor(ctx
, EnumeratorConstr_value
,
343 EnumeratorW
, &EnumeratorConstr_info
,
344 PROPF_CONSTR
|7, &enumerator
->dispex
, ret
);
345 jsdisp_release(&enumerator
->dispex
);