Jacek Caban : jscript: Add support for parametrized compound assignments.
Alexandre Julliard
julliard at winehq.org
Thu Aug 8 19:27:20 CDT 2019
Module: wine
Branch: master
Commit: febfcdae406438dbfba4659a44a01bfc04b99590
URL: https://source.winehq.org/git/wine.git/?a=commit;h=febfcdae406438dbfba4659a44a01bfc04b99590
Author: Jacek Caban <jacek at codeweavers.com>
Date: Thu Aug 8 15:26:37 2019 +0200
jscript: Add support for parametrized compound assignments.
Signed-off-by: Jacek Caban <jacek at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>
---
dlls/jscript/compile.c | 27 ++++++++++++-----
dlls/jscript/tests/run.c | 76 ++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 95 insertions(+), 8 deletions(-)
diff --git a/dlls/jscript/compile.c b/dlls/jscript/compile.c
index e38e5c5..db05d3c 100644
--- a/dlls/jscript/compile.c
+++ b/dlls/jscript/compile.c
@@ -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;
diff --git a/dlls/jscript/tests/run.c b/dlls/jscript/tests/run.c
index a7eaf08..7037cff 100644
--- a/dlls/jscript/tests/run.c
+++ b/dlls/jscript/tests/run.c
@@ -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) {"
More information about the wine-cvs
mailing list