jscript: Added for..in statement implementation.

This commit is contained in:
Jacek Caban 2008-09-19 00:43:21 +02:00 committed by Alexandre Julliard
parent 4731f17435
commit 8e16240467
3 changed files with 130 additions and 3 deletions

View File

@ -381,6 +381,8 @@ static HRESULT fill_protrefs(DispatchEx *This)
fill_protrefs(This->prototype);
for(iter = This->prototype->props; iter < This->prototype->props+This->prototype->prop_cnt; iter++) {
if(!iter->name)
continue;
hres = find_prop_name(This, iter->name, &prop);
if(FAILED(hres))
return hres;

View File

@ -764,10 +764,102 @@ HRESULT for_statement_eval(exec_ctx_t *ctx, statement_t *_stat, return_type_t *r
return S_OK;
}
HRESULT forin_statement_eval(exec_ctx_t *ctx, statement_t *stat, return_type_t *rt, VARIANT *ret)
/* ECMA-262 3rd Edition 12.6.4 */
HRESULT forin_statement_eval(exec_ctx_t *ctx, statement_t *_stat, return_type_t *rt, VARIANT *ret)
{
FIXME("\n");
return E_NOTIMPL;
forin_statement_t *stat = (forin_statement_t*)_stat;
VARIANT val, name, retv, tmp;
DISPID id = DISPID_STARTENUM;
BSTR str, identifier = NULL;
IDispatchEx *in_obj;
exprval_t exprval;
HRESULT hres;
TRACE("\n");
if(stat->variable) {
hres = variable_list_eval(ctx, stat->variable, &rt->ei);
if(FAILED(hres))
return hres;
}
hres = expr_eval(ctx, stat->in_expr, EXPR_NEWREF, &rt->ei, &exprval);
if(FAILED(hres))
return hres;
hres = exprval_to_value(ctx->parser->script, &exprval, &rt->ei, &val);
exprval_release(&exprval);
if(FAILED(hres))
return hres;
if(V_VT(&val) != VT_DISPATCH) {
FIXME("in vt %d\n", V_VT(&val));
VariantClear(&val);
return E_NOTIMPL;
}
hres = IDispatch_QueryInterface(V_DISPATCH(&val), &IID_IDispatchEx, (void**)&in_obj);
IDispatch_Release(V_DISPATCH(&val));
if(FAILED(hres)) {
FIXME("Object doesn't support IDispatchEx\n");
return E_NOTIMPL;
}
V_VT(&retv) = VT_EMPTY;
if(stat->variable)
identifier = SysAllocString(stat->variable->identifier);
while(1) {
hres = IDispatchEx_GetNextDispID(in_obj, fdexEnumDefault, id, &id);
if(FAILED(hres) || hres == S_FALSE)
break;
hres = IDispatchEx_GetMemberName(in_obj, id, &str);
if(FAILED(hres))
break;
TRACE("iter %s\n", debugstr_w(str));
if(stat->variable)
hres = identifier_eval(ctx, identifier, 0, &exprval);
else
hres = expr_eval(ctx, stat->expr, EXPR_NEWREF, &rt->ei, &exprval);
if(SUCCEEDED(hres)) {
V_VT(&name) = VT_BSTR;
V_BSTR(&name) = str;
hres = put_value(ctx->parser->script, &exprval, &name, &rt->ei);
exprval_release(&exprval);
}
SysFreeString(str);
if(FAILED(hres))
break;
hres = stat_eval(ctx, stat->statement, rt, &tmp);
if(FAILED(hres))
break;
VariantClear(&retv);
retv = tmp;
if(rt->type == RT_CONTINUE)
rt->type = RT_NORMAL;
else if(rt->type != RT_NORMAL)
break;
}
SysFreeString(identifier);
IDispatchEx_Release(in_obj);
if(FAILED(hres)) {
VariantClear(&retv);
return hres;
}
if(rt->type == RT_BREAK)
rt->type = RT_NORMAL;
*ret = retv;
return S_OK;
}
/* ECMA-262 3rd Edition 12.7 */

View File

@ -617,4 +617,37 @@ ok(fi === 4, "fi !== 4");
ok((void 1) === undefined, "(void 1) !== undefined");
var inobj = new Object();
for(var iter in inobj)
ok(false, "unexpected iter = " + iter);
inobj.test = true;
tmp = 0;
for(iter in inobj) {
ok(iter == "test", "unexpected iter = " + iter);
tmp++;
}
ok(tmp === 1, "for..in tmp = " + tmp);
function forinTestObj() {}
forinTestObj.prototype.test3 = true;
var arr = new Array();
inobj = new forinTestObj();
inobj.test1 = true;
inobj.test2 = true;
tmp = 0;
for(iter in inobj) {
arr[iter] = true;
tmp++;
}
ok(tmp === 3, "for..in tmp = " + tmp);
ok(arr["test1"] === true, "arr[test1] !== true");
ok(arr["test2"] === true, "arr[test2] !== true");
ok(arr["test3"] === true, "arr[test3] !== true");
reportSuccess();