jscript: Add support for parametrized compound assignments.
Signed-off-by: Jacek Caban <jacek@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
9dd50eae06
commit
febfcdae40
|
@ -736,11 +736,6 @@ static HRESULT compile_assign_expression(compiler_ctx_t *ctx, binary_expression_
|
|||
call_expression_t *call_expr = (call_expression_t*)expr->expression1;
|
||||
argument_t *arg;
|
||||
|
||||
if(op != OP_LAST) {
|
||||
FIXME("op %d not supported on parametrized assign expressions\n", op);
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
if(is_memberid_expr(call_expr->expression->type) && call_expr->argument_list) {
|
||||
hres = compile_memberid_expression(ctx, call_expr->expression, fdexNameEnsure);
|
||||
if(FAILED(hres))
|
||||
|
@ -752,6 +747,23 @@ static HRESULT compile_assign_expression(compiler_ctx_t *ctx, binary_expression_
|
|||
return hres;
|
||||
arg_cnt++;
|
||||
}
|
||||
|
||||
if(op != OP_LAST) {
|
||||
unsigned instr;
|
||||
|
||||
/* We need to call the functions twice: to get the value and to set it.
|
||||
* JavaScript interpreted functions may to modify value on the stack,
|
||||
* but assignment calls are allowed only on external functions, so we
|
||||
* may reuse the stack here. */
|
||||
instr = push_instr(ctx, OP_call_member);
|
||||
if(!instr)
|
||||
return E_OUTOFMEMORY;
|
||||
instr_ptr(ctx, instr)->u.arg[0].uint = arg_cnt;
|
||||
instr_ptr(ctx, instr)->u.arg[1].lng = 1;
|
||||
|
||||
if(!push_instr(ctx, OP_push_acc))
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
}else {
|
||||
use_throw_path = TRUE;
|
||||
}
|
||||
|
@ -759,6 +771,8 @@ static HRESULT compile_assign_expression(compiler_ctx_t *ctx, binary_expression_
|
|||
hres = compile_memberid_expression(ctx, expr->expression1, fdexNameEnsure);
|
||||
if(FAILED(hres))
|
||||
return hres;
|
||||
if(op != OP_LAST && !push_instr(ctx, OP_refval))
|
||||
return E_OUTOFMEMORY;
|
||||
}else {
|
||||
use_throw_path = TRUE;
|
||||
}
|
||||
|
@ -779,9 +793,6 @@ static HRESULT compile_assign_expression(compiler_ctx_t *ctx, binary_expression_
|
|||
return push_instr_uint(ctx, OP_throw_ref, JS_E_ILLEGAL_ASSIGN);
|
||||
}
|
||||
|
||||
if(op != OP_LAST && !push_instr(ctx, OP_refval))
|
||||
return E_OUTOFMEMORY;
|
||||
|
||||
hres = compile_expression(ctx, expr->expression2, TRUE);
|
||||
if(FAILED(hres))
|
||||
return hres;
|
||||
|
|
|
@ -90,6 +90,9 @@ DEFINE_EXPECT(global_success_i);
|
|||
DEFINE_EXPECT(global_notexists_d);
|
||||
DEFINE_EXPECT(global_propargput_d);
|
||||
DEFINE_EXPECT(global_propargput_i);
|
||||
DEFINE_EXPECT(global_propargputop_d);
|
||||
DEFINE_EXPECT(global_propargputop_get_i);
|
||||
DEFINE_EXPECT(global_propargputop_put_i);
|
||||
DEFINE_EXPECT(global_testargtypes_i);
|
||||
DEFINE_EXPECT(global_calleval_i);
|
||||
DEFINE_EXPECT(puredisp_prop_d);
|
||||
|
@ -151,6 +154,7 @@ DEFINE_EXPECT(BindHandler);
|
|||
#define DISPID_GLOBAL_BINDEVENTHANDLER 0x101d
|
||||
#define DISPID_GLOBAL_TESTENUMOBJ 0x101e
|
||||
#define DISPID_GLOBAL_CALLEVAL 0x101f
|
||||
#define DISPID_GLOBAL_PROPARGPUTOP 0x1020
|
||||
|
||||
#define DISPID_GLOBAL_TESTPROPDELETE 0x2000
|
||||
#define DISPID_GLOBAL_TESTNOPROPDELETE 0x2001
|
||||
|
@ -928,6 +932,13 @@ static HRESULT WINAPI Global_GetDispID(IDispatchEx *iface, BSTR bstrName, DWORD
|
|||
return S_OK;
|
||||
}
|
||||
|
||||
if(!strcmp_wa(bstrName, "propArgPutOp")) {
|
||||
CHECK_EXPECT(global_propargputop_d);
|
||||
test_grfdex(grfdex, fdexNameCaseSensitive);
|
||||
*pid = DISPID_GLOBAL_PROPARGPUTOP;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
if(!strcmp_wa(bstrName, "propArgPutO")) {
|
||||
CHECK_EXPECT(global_propargput_d);
|
||||
test_grfdex(grfdex, fdexNameEnsure|fdexNameCaseSensitive);
|
||||
|
@ -1386,6 +1397,55 @@ static HRESULT WINAPI Global_InvokeEx(IDispatchEx *iface, DISPID id, LCID lcid,
|
|||
ok(V_I4(pdp->rgvarg+2) == 0, "V_I4(pdp->rgvarg+2) = %d\n", V_I4(pdp->rgvarg+2));
|
||||
return S_OK;
|
||||
|
||||
case DISPID_GLOBAL_PROPARGPUTOP:
|
||||
ok(pdp != NULL, "pdp == NULL\n");
|
||||
ok(pdp->rgvarg != NULL, "rgvarg != NULL\n");
|
||||
ok(pei != NULL, "pei == NULL\n");
|
||||
|
||||
switch(wFlags) {
|
||||
case INVOKE_PROPERTYGET | INVOKE_FUNC:
|
||||
CHECK_EXPECT(global_propargputop_get_i);
|
||||
|
||||
ok(pdp->cNamedArgs == 0, "cNamedArgs = %d\n", pdp->cNamedArgs);
|
||||
ok(!pdp->rgdispidNamedArgs, "rgdispidNamedArgs != NULL\n");
|
||||
ok(pdp->cArgs == 2, "cArgs = %d\n", pdp->cArgs);
|
||||
ok(pdp->cNamedArgs == 0, "cNamedArgs = %d\n", pdp->cNamedArgs);
|
||||
ok(pvarRes != NULL, "pvarRes = NULL\n");
|
||||
|
||||
ok(V_VT(pdp->rgvarg) == VT_I4, "V_VT(pdp->rgvarg) = %d\n", V_VT(pdp->rgvarg));
|
||||
ok(V_I4(pdp->rgvarg) == 1, "V_I4(pdp->rgvarg) = %d\n", V_I4(pdp->rgvarg));
|
||||
|
||||
ok(V_VT(pdp->rgvarg+1) == VT_I4, "V_VT(pdp->rgvarg+1) = %d\n", V_VT(pdp->rgvarg+1));
|
||||
ok(V_I4(pdp->rgvarg+1) == 0, "V_I4(pdp->rgvarg+1) = %d\n", V_I4(pdp->rgvarg+1));
|
||||
|
||||
V_VT(pvarRes) = VT_I4;
|
||||
V_I4(pvarRes) = 6;
|
||||
break;
|
||||
case INVOKE_PROPERTYPUT:
|
||||
CHECK_EXPECT(global_propargputop_put_i);
|
||||
|
||||
ok(pdp->cNamedArgs == 1, "cNamedArgs = %d\n", pdp->cNamedArgs);
|
||||
ok(pdp->rgdispidNamedArgs[0] == DISPID_PROPERTYPUT, "pdp->rgdispidNamedArgs[0] = %d\n", pdp->rgdispidNamedArgs[0]);
|
||||
ok(pdp->rgdispidNamedArgs != NULL, "rgdispidNamedArgs == NULL\n");
|
||||
ok(pdp->cArgs == 3, "cArgs = %d\n", pdp->cArgs);
|
||||
ok(pdp->cNamedArgs == 1, "cNamedArgs = %d\n", pdp->cNamedArgs);
|
||||
ok(!pvarRes, "pvarRes != NULL\n");
|
||||
|
||||
ok(V_VT(pdp->rgvarg) == VT_I4, "V_VT(pdp->rgvarg) = %d\n", V_VT(pdp->rgvarg));
|
||||
ok(V_I4(pdp->rgvarg) == 8, "V_I4(pdp->rgvarg) = %d\n", V_I4(pdp->rgvarg));
|
||||
|
||||
ok(V_VT(pdp->rgvarg+1) == VT_I4, "V_VT(pdp->rgvarg+1) = %d\n", V_VT(pdp->rgvarg+1));
|
||||
ok(V_I4(pdp->rgvarg+1) == 1, "V_I4(pdp->rgvarg+1) = %d\n", V_I4(pdp->rgvarg+1));
|
||||
|
||||
ok(V_VT(pdp->rgvarg+2) == VT_I4, "V_VT(pdp->rgvarg+2) = %d\n", V_VT(pdp->rgvarg+2));
|
||||
ok(V_I4(pdp->rgvarg+2) == 0, "V_I4(pdp->rgvarg+2) = %d\n", V_I4(pdp->rgvarg+2));
|
||||
break;
|
||||
default:
|
||||
ok(0, "wFlags = %x\n", wFlags);
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
|
||||
case DISPID_GLOBAL_OBJECT_FLAG: {
|
||||
IDispatchEx *dispex;
|
||||
BSTR str;
|
||||
|
@ -2926,6 +2986,22 @@ static BOOL run_tests(void)
|
|||
CHECK_CALLED(global_propargput_d);
|
||||
CHECK_CALLED(global_propargput_i);
|
||||
|
||||
SET_EXPECT(global_propargputop_d);
|
||||
SET_EXPECT(global_propargputop_get_i);
|
||||
SET_EXPECT(global_propargputop_put_i);
|
||||
parse_script_a("var t=0; propArgPutOp(t++, t++) += t++;");
|
||||
CHECK_CALLED(global_propargputop_d);
|
||||
CHECK_CALLED(global_propargputop_get_i);
|
||||
CHECK_CALLED(global_propargputop_put_i);
|
||||
|
||||
SET_EXPECT(global_propargputop_d);
|
||||
SET_EXPECT(global_propargputop_get_i);
|
||||
SET_EXPECT(global_propargputop_put_i);
|
||||
parse_script_a("var t=0; propArgPutOp(t++, t++) ^= 14;");
|
||||
CHECK_CALLED(global_propargputop_d);
|
||||
CHECK_CALLED(global_propargputop_get_i);
|
||||
CHECK_CALLED(global_propargputop_put_i);
|
||||
|
||||
SET_EXPECT(global_testargtypes_i);
|
||||
parse_script_a("testArgTypes(dispUnk, intProp(), intProp, getShort(), shortProp,"
|
||||
"function(i1,ui1,ui2,r4,i4ref,ui4,nullunk,d,i,s) {"
|
||||
|
|
Loading…
Reference in New Issue