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