[PATCH 2/2] vbscript: Support properties with parameters.

Robert Wilhelm robert.wilhelm at gmx.net
Mon Oct 26 17:18:32 CDT 2020


Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=33996
Signed-off-by: Robert Wilhelm <robert.wilhelm at gmx.net>
---
 dlls/vbscript/parser.y       |  6 ++---
 dlls/vbscript/tests/lang.vbs | 21 +++++++++++++++++
 dlls/vbscript/vbdisp.c       | 45 ++++++++++++++++++++++++++----------
 3 files changed, 57 insertions(+), 15 deletions(-)

diff --git a/dlls/vbscript/parser.y b/dlls/vbscript/parser.y
index 942e76459c2..d1af9a8c84b 100644
--- a/dlls/vbscript/parser.y
+++ b/dlls/vbscript/parser.y
@@ -452,11 +452,11 @@ ClassBody
     | PropertyDecl StSep ClassBody                { $$ = add_class_function(ctx, $3, $1); CHECK_ERROR; }

 PropertyDecl
-    : Storage_opt tPROPERTY tGET tIdentifier ArgumentsDecl_opt StSep BodyStatements tEND tPROPERTY
+    : Storage_opt tPROPERTY tGET Identifier ArgumentsDecl_opt StSep BodyStatements tEND tPROPERTY
                                     { $$ = new_function_decl(ctx, $4, FUNC_PROPGET, $1, $5, $7); CHECK_ERROR; }
-    | Storage_opt tPROPERTY tLET tIdentifier '(' ArgumentDecl ')' StSep BodyStatements tEND tPROPERTY
+    | Storage_opt tPROPERTY tLET Identifier '(' ArgumentDeclList ')' StSep BodyStatements tEND tPROPERTY
                                     { $$ = new_function_decl(ctx, $4, FUNC_PROPLET, $1, $6, $9); CHECK_ERROR; }
-    | Storage_opt tPROPERTY tSET tIdentifier '(' ArgumentDecl ')' StSep BodyStatements tEND tPROPERTY
+    | Storage_opt tPROPERTY tSET Identifier '(' ArgumentDeclList ')' StSep BodyStatements tEND tPROPERTY
                                     { $$ = new_function_decl(ctx, $4, FUNC_PROPSET, $1, $6, $9); CHECK_ERROR; }

 FunctionDecl
diff --git a/dlls/vbscript/tests/lang.vbs b/dlls/vbscript/tests/lang.vbs
index 570bb7fbcb3..d9fcf4c6598 100644
--- a/dlls/vbscript/tests/lang.vbs
+++ b/dlls/vbscript/tests/lang.vbs
@@ -1757,6 +1757,27 @@ class TestPropSyntax
     end property
 end class

+Class TestPropParam
+    Public oDict
+    Public Property Let Key(oldKey, newKey)
+        oDict =oldKey & newKey
+    End Property
+    Public Property Let three(uno,due,tre)
+        oDict =uno & due & tre
+    End Property
+    Public Property Let ten(a,b,c,d,e,f,g,h,i,j)
+        oDict =a & b & c & d & e & f & g & h & i & j
+    End Property
+End Class
+
+Set x = new TestPropParam
+x.key("old") = "new"
+call ok(x.oDict = "oldnew","x.oDict = " & x.oDict & " expected oldnew")
+x.three(1,2) = 3
+call ok(x.oDict = "123","x.oDict = " & x.oDict & " expected 123")
+x.ten(1,2,3,4,5,6,7,8,9) = 0
+call ok(x.oDict = "1234567890","x.oDict = " & x.oDict & " expected 1234567890")
+
 set x = new TestPropSyntax
 set x.prop = new TestPropSyntax
 set x.prop.prop = new TestPropSyntax
diff --git a/dlls/vbscript/vbdisp.c b/dlls/vbscript/vbdisp.c
index 5f493d420bd..75b7badc5c7 100644
--- a/dlls/vbscript/vbdisp.c
+++ b/dlls/vbscript/vbdisp.c
@@ -78,7 +78,7 @@ HRESULT vbdisp_get_id(vbdisp_t *This, BSTR name, vbdisp_invoke_type_t invoke_typ
     return DISP_E_UNKNOWNNAME;
 }

-static HRESULT get_propput_arg(script_ctx_t *ctx, const DISPPARAMS *dp, WORD flags, VARIANT *v, BOOL *is_owned)
+static HRESULT get_propput_arg(script_ctx_t *ctx, const DISPPARAMS *dp, WORD flags, VARIANT *v, BOOL *is_owned, INT *index)
 {
     unsigned i;

@@ -88,9 +88,11 @@ static HRESULT get_propput_arg(script_ctx_t *ctx, const DISPPARAMS *dp, WORD fla
     }
     if(i == dp->cNamedArgs) {
         WARN("no value to set\n");
+        *index=-1;
         return DISP_E_PARAMNOTOPTIONAL;
     }

+    *index = i;
     *v = dp->rgvarg[i];
     if(V_VT(v) == (VT_VARIANT|VT_BYREF))
         *v = *V_VARIANTREF(v);
@@ -134,8 +136,9 @@ static HRESULT invoke_variant_prop(script_ctx_t *ctx, VARIANT *v, WORD flags, DI
     case DISPATCH_PROPERTYPUT|DISPATCH_PROPERTYPUTREF: {
         VARIANT put_val;
         BOOL own_val;
+        INT index;

-        hres = get_propput_arg(ctx, dp, flags, &put_val, &own_val);
+        hres = get_propput_arg(ctx, dp, flags, &put_val, &own_val, &index);
         if(FAILED(hres))
             return hres;

@@ -197,28 +200,46 @@ static HRESULT invoke_vbdisp(vbdisp_t *This, DISPID id, DWORD flags, BOOL extern
         case DISPATCH_PROPERTYPUT|DISPATCH_PROPERTYPUTREF: {
             DISPPARAMS dp = {NULL, NULL, 1, 0};
             BOOL needs_release;
-            VARIANT put_val;
+            VARIANT buf[6];
             HRESULT hres;
-
-            if(arg_cnt(params)) {
-                FIXME("arguments not implemented\n");
-                return E_NOTIMPL;
+            INT index,i,j;
+
+            dp.cArgs = arg_cnt(params) + 1;
+            if(dp.cArgs > ARRAY_SIZE(buf)) {
+                dp.rgvarg = heap_alloc(dp.cArgs*sizeof(VARIANT));
+                if(!dp.rgvarg)
+                    return E_OUTOFMEMORY;
+            }else {
+                dp.rgvarg = buf;
             }

-            hres = get_propput_arg(This->desc->ctx, params, flags, &put_val, &needs_release);
-            if(FAILED(hres))
+            hres = get_propput_arg(This->desc->ctx, params, flags, dp.rgvarg, &needs_release, &index);
+            if(FAILED(hres)) {
+                if(dp.rgvarg != buf)
+                    heap_free(dp.rgvarg);
                 return hres;
+            }

-            dp.rgvarg = &put_val;
-            func = This->desc->funcs[id].entries[V_VT(&put_val) == VT_DISPATCH ? VBDISP_SET : VBDISP_LET];
+            func = This->desc->funcs[id].entries[V_VT(dp.rgvarg) == VT_DISPATCH ? VBDISP_SET : VBDISP_LET];
             if(!func) {
                 FIXME("no letter/setter\n");
+                if(dp.rgvarg != buf)
+                    heap_free(dp.rgvarg);
                 return DISP_E_MEMBERNOTFOUND;
             }

+            for( i=1,j=0; i<dp.cArgs;i++,j++) {
+                if (j==index) {
+                    j++;
+                }
+                dp.rgvarg[i]=params->rgvarg[j];
+            }
+
             hres = exec_script(This->desc->ctx, extern_caller, func, This, &dp, NULL);
             if(needs_release)
-                VariantClear(&put_val);
+                VariantClear(dp.rgvarg);
+            if(dp.rgvarg != buf)
+                heap_free(dp.rgvarg);
             return hres;
         }
         default:
--
2.26.2





More information about the wine-devel mailing list