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:
Jacek Caban 2019-08-08 15:26:37 +02:00 committed by Alexandre Julliard
parent 9dd50eae06
commit febfcdae40
2 changed files with 95 additions and 8 deletions

View File

@ -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;

View File

@ -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) {"